visilibity 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,2158 @@
1
+ /**
2
+ * \file visilibity.hpppp
3
+ * \authors Karl J. Obermeyer
4
+ * \date March 20, 2008
5
+ *
6
+ VisiLibity: A Floating-Point Visibility Algorithms Library,
7
+ Copyright (C) 2008 Karl J. Obermeyer (karl.obermeyer [ at ] gmail.com)
8
+
9
+ This file is part of VisiLibity.
10
+
11
+ VisiLibity is free software: you can redistribute it and/or modify it under
12
+ the terms of the GNU Lesser General Public License as published by the
13
+ Free Software Foundation, either version 3 of the License, or (at your
14
+ option) any later version.
15
+
16
+ VisiLibity is distributed in the hope that it will be useful, but WITHOUT
17
+ ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
18
+ FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
19
+ License for more details.
20
+
21
+ You should have received a copy of the GNU Lesser General Public
22
+ License along with VisiLibity. If not, see <http://www.gnu.org/licenses/>.
23
+ */
24
+
25
+ /**
26
+ * \mainpage
27
+ * <center>
28
+ * see also the <a href="../index.html">VisiLibity Project Page</a>
29
+ * </center>
30
+ * <b>Authors</b>: Karl J. Obermeyer
31
+ * <hr>
32
+ * \section developers For Developers
33
+ * <a href="../VisiLibity.coding_standards.html">Coding Standards</a>
34
+ * <hr>
35
+ * \section release_notes Release Notes
36
+ * <b>Current Functionality</b>
37
+ * <ul>
38
+ * <li>visibility polygons in polygonal environments with holes</li>
39
+ * <li>visibility graphs</li>
40
+ * <li>shortest path planning for a point</li>
41
+ * </ul>
42
+ */
43
+
44
+ #ifndef VISILIBITY_H
45
+ #define VISILIBITY_H
46
+
47
+
48
+ #include <cmath> //math functions in std namespace
49
+ #include <vector>
50
+ #include <queue> //queue and priority_queue.
51
+ #include <set> //priority queues with iteration,
52
+ //integrated keys
53
+ #include <list>
54
+ #include <algorithm> //sorting, min, max, reverse
55
+ #include <cstdlib> //rand and srand
56
+ #include <ctime> //Unix time
57
+ #include <fstream> //file I/O
58
+ #include <iostream>
59
+ #include <cstring> //C-string manipulation
60
+ #include <string> //string class
61
+ #include <cassert> //assertions
62
+
63
+
64
+ /// VisiLibity's sole namespace
65
+ namespace VisiLibity
66
+ {
67
+
68
+ //Fwd declaration of all classes and structs serves as index.
69
+ struct Bounding_Box;
70
+ class Point;
71
+ class Line_Segment;
72
+ class Angle;
73
+ class Ray;
74
+ class Polar_Point;
75
+ class Polyline;
76
+ class Polygon;
77
+ class Environment;
78
+ class Guards;
79
+ class Visibility_Polygon;
80
+ class Visibility_Graph;
81
+
82
+
83
+ /** \brief floating-point display precision.
84
+ *
85
+ * This is the default precision with which floating point
86
+ * numbers are displayed or written to files for classes with a
87
+ * write_to_file() method.
88
+ */
89
+ const int FIOS_PRECISION = 10;
90
+
91
+
92
+ /** \brief get a uniform random sample from an (inclusive) interval
93
+ * on the real line
94
+ *
95
+ * \author Karl J. Obermeyer
96
+ * \param lower_bound lower bound of the real interval
97
+ * \param upper_bound upper bound of the real interval
98
+ * \pre \a lower_bound <= \a upper_bound
99
+ * \return a random sample from a uniform probability distribution
100
+ * on the real interval [\a lower_bound, \a upper_bound]
101
+ * \remarks Uses the Standard Library's rand() function. rand()
102
+ * should be seeded (only necessary once at the beginning of the
103
+ * program) using the command
104
+ * std::srand( std::time( NULL ) ); rand();
105
+ * \warning performance degrades as upper_bound - lower_bound
106
+ * approaches RAND_MAX.
107
+ */
108
+ double uniform_random_sample(double lower_bound, double upper_bound);
109
+
110
+
111
+ /** \brief rectangle with sides parallel to the x- and y-axes
112
+ *
113
+ * \author Karl J. Obermeyer
114
+ * Useful for enclosing other geometric objects.
115
+ */
116
+ struct Bounding_Box { double x_min, x_max, y_min, y_max; };
117
+
118
+
119
+ /// Point in the plane represented by Cartesian coordinates
120
+ class Point
121
+ {
122
+ public:
123
+ //Constructors
124
+ /** \brief default
125
+ *
126
+ * \remarks Data defaults to NAN so that checking whether the
127
+ * data are numbers can be used as a precondition in functions.
128
+ */
129
+ Point() : x_(NAN) , y_(NAN) { }
130
+ /// costruct from raw coordinates
131
+ Point(double x_temp, double y_temp)
132
+ { x_=x_temp; y_=y_temp; }
133
+ //Accessors
134
+ /// get x coordinate
135
+ double x () const { return x_; }
136
+ /// get y coordinate
137
+ double y () const { return y_; }
138
+ /** \brief closest Point on \a line_segment_temp
139
+ *
140
+ * \author Karl J. Obermeyer
141
+ * \pre the calling Point data are numbers
142
+ * and \a line_segment_temp is nonempty
143
+ * \return the Point on \a line_segment_temp which is the smallest
144
+ * Euclidean distance from the calling Point
145
+ */
146
+ Point projection_onto(const Line_Segment& line_segment_temp) const;
147
+ /** \brief closest Point on \a ray_temp
148
+ *
149
+ * \author Karl J. Obermeyer
150
+ * \pre the calling Point and \a ray_temp data are numbers
151
+ * \return the Point on \a ray_temp which is the smallest
152
+ * Euclidean distance from the calling Point
153
+ */
154
+ Point projection_onto(const Ray& ray_temp) const;
155
+ /** \brief closest Point on \a polyline_temp
156
+ *
157
+ * \pre the calling Point data are numbers and \a polyline_temp
158
+ * is nonempty
159
+ * \return the Point on \a polyline_temp which is the smallest
160
+ * Euclidean distance from the calling Point
161
+ */
162
+ Point projection_onto(const Polyline& polyline_temp) const;
163
+ /** \brief closest vertex of \a polygon_temp
164
+ *
165
+ * \author Karl J. Obermeyer
166
+ * \pre the calling Point data are numbers and \a polygon_temp
167
+ * is nonempty
168
+ * \return the vertex of \a polygon_temp which is the
169
+ * smallest Euclidean distance from the calling Point
170
+ */
171
+ Point projection_onto_vertices_of(const Polygon& polygon_temp) const;
172
+ /** \brief closest vertex of \a environment_temp
173
+ *
174
+ * \author Karl J. Obermeyer
175
+ * \pre the calling Point data are numbers and \a environment_temp
176
+ * is nonempty
177
+ * \return the vertex of \a environment_temp which is
178
+ * the smallest Euclidean distance from the calling Point
179
+ */
180
+ Point projection_onto_vertices_of(const Environment&
181
+ enviroment_temp) const;
182
+ /** \brief closest Point on boundary of \a polygon_temp
183
+ *
184
+ * \author Karl J. Obermeyer
185
+ * \pre the calling Point data are numbers and \a polygon_temp
186
+ * is nonempty
187
+ * \return the Point on the boundary of \a polygon_temp which is the
188
+ * smallest Euclidean distance from the calling Point
189
+ */
190
+ Point projection_onto_boundary_of(const Polygon& polygon_temp) const;
191
+ /** \brief closest Point on boundary of \a environment_temp
192
+ *
193
+ * \author Karl J. Obermeyer
194
+ * \pre the calling Point data are numbers and \a environment_temp
195
+ * is nonempty
196
+ * \return the Point on the boundary of \a environment_temp which is
197
+ * the smalles Euclidean distance from the calling Point
198
+ */
199
+ Point projection_onto_boundary_of(const Environment&
200
+ enviroment_temp) const;
201
+ /** \brief true iff w/in \a epsilon of boundary of \a polygon_temp
202
+ *
203
+ * \author Karl J. Obermeyer
204
+ * \pre the calling Point data are numbers and \a polygon_temp
205
+ * is nonempty
206
+ * \return true iff the calling Point is within Euclidean distance
207
+ * \a epsilon of \a polygon_temp 's boundary
208
+ * \remarks O(n) time complexity, where n is the number
209
+ * of vertices of \a polygon_temp
210
+ */
211
+ bool on_boundary_of(const Polygon& polygon_temp,
212
+ double epsilon=0.0) const;
213
+ /** \brief true iff w/in \a epsilon of boundary of \a environment_temp
214
+ *
215
+ * \author Karl J. Obermeyer
216
+ * \pre the calling Point data are numbers and \a environment_temp
217
+ * is nonempty
218
+ * \return true iff the calling Point is within Euclidean distance
219
+ * \a epsilon of \a environment_temp 's boundary
220
+ * \remarks O(n) time complexity, where n is the number
221
+ * of vertices of \a environment_temp
222
+ */
223
+ bool on_boundary_of(const Environment& environment_temp,
224
+ double epsilon=0.0) const;
225
+ /** \brief true iff w/in \a epsilon of \a line_segment_temp
226
+ *
227
+ * \author Karl J. Obermeyer
228
+ * \pre the calling Point data are numbers and \a line_segment_temp
229
+ * is nonempty
230
+ * \return true iff the calling Point is within distance
231
+ * \a epsilon of the (closed) Line_Segment \a line_segment_temp
232
+ */
233
+ bool in(const Line_Segment& line_segment_temp,
234
+ double epsilon=0.0) const;
235
+ /** \brief true iff w/in \a epsilon of interior but greater than
236
+ * \a espilon away from endpoints of \a line_segment_temp
237
+ *
238
+ * \author Karl J. Obermeyer
239
+ * \pre the calling Point data are numbers and \a line_segment_temp
240
+ * is nonempty
241
+ * \return true iff the calling Point is within distance \a
242
+ * epsilon of \line_segment_temp, but distance (strictly) greater
243
+ * than epsilon from \a line_segment_temp 's endpoints.
244
+ */
245
+ bool in_relative_interior_of(const Line_Segment& line_segment_temp,
246
+ double epsilon=0.0) const;
247
+ /** \brief true iff w/in \a epsilon of \a polygon_temp
248
+ *
249
+ * \author Karl J. Obermeyer
250
+ *
251
+ * \pre the calling Point data are numbers and \a polygon_temp is
252
+ * \a epsilon -simple. Test simplicity with
253
+ * Polygon::is_simple(epsilon)
254
+ *
255
+ * \return true iff the calling Point is a Euclidean distance no greater
256
+ * than \a epsilon from the (closed) Polygon (with vertices listed
257
+ * either cw or ccw) \a polygon_temp.
258
+ * \remarks O(n) time complexity, where n is the number of vertices
259
+ * in \a polygon_temp
260
+ */
261
+ bool in(const Polygon& polygon_temp,
262
+ double epsilon=0.0) const;
263
+ /** \brief true iff w/in \a epsilon of \a environment_temp
264
+ *
265
+ * \author Karl J. Obermeyer
266
+ *
267
+ * \pre the calling Point data are numbers and \a environment_temp
268
+ * is nonempty and \a epsilon -valid. Test validity with
269
+ * Enviroment::is_valid(epsilon)
270
+ *
271
+ * \return true iff the calling Point is a Euclidean distance no greater
272
+ * than \a epsilon from the in the (closed) Environment \a environment_temp
273
+ * \remarks O(n) time complexity, where n is the number of
274
+ * vertices in \a environment_temp
275
+ */
276
+ bool in(const Environment& environment_temp,
277
+ double epsilon=0.0) const;
278
+ /** \brief true iff w/in \a epsilon of some endpoint
279
+ * of \a line_segment_temp
280
+ *
281
+ * \pre the calling Point data are numbers and \a line_segment_temp
282
+ * is nonempty
283
+ * \return true iff calling Point is a Euclidean distance no greater
284
+ * than \a epsilon from some endpoint of \a line_segment_temp
285
+ */
286
+ bool is_endpoint_of(const Line_Segment& line_segment_temp,
287
+ double epsilon=0.0) const;
288
+ //Mutators
289
+ /// change x coordinate
290
+ void set_x(double x_temp) { x_ = x_temp;}
291
+ /// change y coordinate
292
+ void set_y(double y_temp) { y_ = y_temp;}
293
+ /** \brief relocate to closest vertex if w/in \a epsilon of some
294
+ * vertex (of \a polygon_temp)
295
+ *
296
+ * \author Karl J. Obermeyer
297
+ * \pre the calling Point data are numbers and \a polygon_temp
298
+ * is nonempty
299
+ * \post If the calling Point was a Euclidean distance no greater
300
+ * than \a epsilon from any vertex of \a polygon_temp, then it
301
+ * will be repositioned to coincide with the closest such vertex
302
+ * \remarks O(n) time complexity, where n is the number of
303
+ * vertices in \a polygon_temp.
304
+ */
305
+ void snap_to_vertices_of(const Polygon& polygon_temp,
306
+ double epsilon=0.0);
307
+ /** \brief relocate to closest vertex if w/in \a epsilon of some
308
+ * vertex (of \a environment_temp)
309
+ *
310
+ * \author Karl J. Obermeyer
311
+ * \pre the calling Point data are numbers and \a environment_temp
312
+ * is nonempty
313
+ * \post If the calling Point was a Euclidean distance no greater
314
+ * than \a epsilon from any vertex of \a environment_temp, then it
315
+ * will be repositioned to coincide with the closest such vertex
316
+ * \remarks O(n) time complexity, where n is the number of
317
+ * vertices in \a environment_temp.
318
+ */
319
+ void snap_to_vertices_of(const Environment& environment_temp,
320
+ double epsilon=0.0);
321
+ /** \brief relocate to closest Point on boundary if w/in \a epsilon
322
+ * of the boundary (of \a polygon_temp)
323
+ *
324
+ * \author Karl J. Obermeyer
325
+ * \pre the calling Point data are numbers and \a polygon_temp
326
+ * is nonempty
327
+ * \post if the calling Point was a Euclidean distance no greater
328
+ * than \a epsilon from the boundary of \a polygon_temp, then it
329
+ * will be repositioned to it's projection onto that boundary
330
+ * \remarks O(n) time complexity, where n is the number of
331
+ * vertices in \a polygon_temp.
332
+ */
333
+ void snap_to_boundary_of(const Polygon& polygon_temp,
334
+ double epsilon=0.0);
335
+ /** \brief relocate to closest Point on boundary if w/in \a epsilon
336
+ * of the boundary (of \a environment_temp)
337
+ *
338
+ * \author Karl J. Obermeyer
339
+ * \pre the calling Point data are numbers and \a environment_temp
340
+ * is nonempty
341
+ * \post if the calling Point was a Euclidean distance no greater
342
+ * than \a epsilon from the boundary of \a environment_temp, then it
343
+ * will be repositioned to it's projection onto that boundary
344
+ * \remarks O(n) time complexity, where n is the number of
345
+ * vertices in \a environment_temp.
346
+ */
347
+ void snap_to_boundary_of(const Environment& environment_temp,
348
+ double epsilon=0.0);
349
+ protected:
350
+ double x_;
351
+ double y_;
352
+ };
353
+
354
+
355
+ /** \brief True iff Points' coordinates are identical.
356
+ *
357
+ * \remarks NAN==NAN returns false, so if either point has
358
+ * not been assigned real number coordinates, they will not be ==
359
+ */
360
+ bool operator == (const Point& point1, const Point& point2);
361
+ /// True iff Points' coordinates are not identical.
362
+ bool operator != (const Point& point1, const Point& point2);
363
+
364
+
365
+ /** \brief compare lexicographic order of points
366
+ *
367
+ * For Points p1 and p2, p1 < p2 iff either p1.x() < p2.x() or
368
+ * p1.x()==p2.x() and p1.y()<p2.y(). False if any member data have
369
+ * not been assigned (numbers).
370
+ * \remarks lex. comparison is very sensitive to perturbations if
371
+ * two Points nearly define a line parallel to one of the axes
372
+ */
373
+ bool operator < (const Point& point1, const Point& point2);
374
+ /** \brief compare lexicographic order of points
375
+ *
376
+ * For Points p1 and p2, p1 < p2 iff either p1.x() < p2.x() or
377
+ * p1.x()==p2.x() and p1.y()<p2.y(). False if any member data have
378
+ * not been assigned (numbers).
379
+ * \remarks lex. comparison is very sensitive to perturbations if
380
+ * two Points nearly define a line parallel to one of the axes
381
+ */
382
+ bool operator > (const Point& point1, const Point& point2);
383
+ /** \brief compare lexicographic order of points
384
+ *
385
+ * For Points p1 and p2, p1 < p2 iff either p1.x() < p2.x() or
386
+ * p1.x()==p2.x() and p1.y()<p2.y(). False if any member data have
387
+ * not been assigned (numbers).
388
+ * \remarks lex. comparison is very sensitive to perturbations if
389
+ * two Points nearly define a line parallel to one of the axes
390
+ */
391
+ bool operator >= (const Point& point1, const Point& point2);
392
+ /** \brief compare lexicographic order of points
393
+ *
394
+ * For Points p1 and p2, p1 < p2 iff either p1.x() < p2.x() or
395
+ * p1.x()==p2.x() and p1.y()<p2.y(). False if any member data have
396
+ * not been assigned (numbers).
397
+ * \remarks lex. comparison is very sensitive to perturbations if
398
+ * two Points nearly define a line parallel to one of the axes
399
+ */
400
+ bool operator <= (const Point& point1, const Point& point2);
401
+
402
+
403
+ /// vector addition of Points
404
+ Point operator + (const Point& point1, const Point& point2);
405
+ /// vector subtraction of Points
406
+ Point operator - (const Point& point1, const Point& point2);
407
+
408
+
409
+ //// dot (scalar) product treats the Points as vectors
410
+ Point operator * (const Point& point1, const Point& point2);
411
+
412
+
413
+ /// simple scaling treats the Point as a vector
414
+ Point operator * (double scalar, const Point& point2);
415
+ /// simple scaling treats the Point as a vector
416
+ Point operator * (const Point& point1, double scalar);
417
+
418
+
419
+ /** \brief cross product (signed) magnitude treats the Points as vectors
420
+ *
421
+ * \author Karl J. Obermeyer
422
+ * \pre Points' data are numbers
423
+ * \remarks This is equal to the (signed) area of the parallelogram created
424
+ * by the Points viewed as vectors.
425
+ */
426
+ double cross(const Point& point1, const Point& point2);
427
+
428
+
429
+ /** \brief Euclidean distance between Points
430
+ *
431
+ * \pre Points' data are numbers
432
+ */
433
+ double distance(const Point& point1, const Point& point2);
434
+
435
+
436
+ /** \brief Euclidean distance between a Point and a Line_Segment
437
+ *
438
+ * \author Karl J. Obermeyer
439
+ * \pre Point's data are numbers and the Line_Segment is nonempty
440
+ */
441
+ double distance(const Point& point_temp,
442
+ const Line_Segment& line_segment_temp);
443
+ /** \brief Euclidean distance between a Point and a Line_Segment
444
+ *
445
+ * \author Karl J. Obermeyer
446
+ * \pre Point's data are numbers and the Line_Segment is nonempty
447
+ */
448
+ double distance(const Line_Segment& line_segment_temp,
449
+ const Point& point_temp);
450
+
451
+
452
+ /** \brief Euclidean distance between a Point and a Ray
453
+ *
454
+ * \author Karl J. Obermeyer
455
+ * \pre Point's and Ray's data are numbers
456
+ */
457
+ double distance(const Point& point_temp,
458
+ const Ray& ray_temp);
459
+ /** \brief Euclidean distance between a Point and a Ray
460
+ *
461
+ * \author Karl J. Obermeyer
462
+ * \pre Point's and Ray's data are numbers
463
+ */
464
+ double distance(const Ray& ray_temp,
465
+ const Point& point_temp);
466
+
467
+
468
+ /** \brief Euclidean distance between a Point and a Polyline
469
+ *
470
+ * \author Karl J. Obermeyer
471
+ * \pre Point's data are numbers and the Polyline is nonempty
472
+ */
473
+ double distance(const Point& point_temp,
474
+ const Polyline& polyline_temp);
475
+ /** \brief Euclidean distance between a Point and a Polyline
476
+ *
477
+ * \author Karl J. Obermeyer
478
+ * \pre Point's data are numbers and the Polyline is nonempty
479
+ */
480
+ double distance(const Polyline& polyline_temp,
481
+ const Point& point_temp);
482
+
483
+
484
+ /** \brief Euclidean distance between a Point and a Polygon's boundary
485
+ *
486
+ * \author Karl J. Obermeyer
487
+ * \pre Point's data are numbers and the Polygon is nonempty
488
+ */
489
+ double boundary_distance(const Point& point_temp,
490
+ const Polygon& polygon_temp);
491
+ /** \brief Euclidean distance between a Point and a Polygon's boundary
492
+ *
493
+ * \author Karl J. Obermeyer
494
+ * \pre Point's data are numbers and the Polygon is nonempty
495
+ */
496
+ double boundary_distance(const Polygon& polygon_temp,
497
+ const Point& point_temp);
498
+
499
+
500
+ /** \brief Euclidean distance between a Point and a Environment's boundary
501
+ *
502
+ * \author Karl J. Obermeyer
503
+ * \pre Point's data are numbers and the Environment is nonempty
504
+ */
505
+ double boundary_distance(const Point& point_temp,
506
+ const Environment& environment_temp);
507
+ /** \brief Euclidean distance between a Point and a Environment's boundary
508
+ *
509
+ * \author Karl J. Obermeyer
510
+ * \pre Point's data are numbers and the Environment is nonempty
511
+ */
512
+ double boundary_distance(const Environment& environment_temp,
513
+ const Point& point_temp);
514
+
515
+
516
+ /// print a Point
517
+ std::ostream& operator << (std::ostream& outs, const Point& point_temp);
518
+
519
+
520
+ /** \brief line segment in the plane represented by its endpoints
521
+ *
522
+ * Closed and oriented line segment in the plane represented by its endpoints.
523
+ * \remarks may be degenerate (colocated endpoints) or empty
524
+ */
525
+ class Line_Segment
526
+ {
527
+ public:
528
+ //Constructors
529
+ /// default to empty
530
+ Line_Segment();
531
+ /// copy constructor
532
+ Line_Segment(const Line_Segment& line_segment_temp);
533
+ /// construct degenerate segment from a single Point
534
+ Line_Segment(const Point& point_temp);
535
+ /// Line_Segment pointing from first_point_temp to second_point_temp
536
+ Line_Segment(const Point& first_point_temp,
537
+ const Point& second_point_temp, double epsilon=0);
538
+ //Accessors
539
+ /** \brief first endpoint
540
+ *
541
+ * \pre size() > 0
542
+ * \return the first Point of the Line_Segment
543
+ * \remarks If size() == 1, then both first() and second() are valid
544
+ * and will return the same Point
545
+ */
546
+ Point first() const;
547
+ /** \brief second endpoint
548
+ *
549
+ * \pre size() > 0
550
+ * \return the second Point of the Line_Segment
551
+ * \remarks If size() == 1, then both first() and second() are valid
552
+ * and will return the same Point
553
+ */
554
+ Point second() const;
555
+ /** \brief number of distinct endpoints
556
+ *
557
+ * \remarks
558
+ * size 0 => empty line segment;
559
+ * size 1 => degenerate (single point) line segment;
560
+ * size 2 => full-fledged (bona fide) line segment
561
+ */
562
+ unsigned size() const { return size_; }
563
+ /** \brief midpoint
564
+ *
565
+ * \pre size() > 0
566
+ */
567
+ Point midpoint() const;
568
+ /** \brief Euclidean length
569
+ *
570
+ * \pre size() > 0
571
+ */
572
+ double length() const;
573
+ /** \brief true iff vertices in lex. order
574
+ *
575
+ * \pre size() > 0
576
+ * \return true iff vertices are listed beginning with the vertex
577
+ * which is lexicographically smallest (lowest x, then lowest y)
578
+ * \remarks lex. comparison is very sensitive to perturbations if
579
+ * two Points nearly define a line parallel to one of the axes
580
+ */
581
+ bool is_in_standard_form() const;
582
+ //Mutators
583
+ /// assignment operator
584
+ Line_Segment& operator = (const Line_Segment& line_segment_temp);
585
+ /** \brief set first endpoint
586
+ *
587
+ * \remarks if \a point_temp is w/in a distance \a epsilon of an existing
588
+ * endpoint, the coordinates of \a point_temp are used and size is set to
589
+ * 1 as appropriate
590
+ */
591
+ void set_first(const Point& point_temp, double epsilon=0.0);
592
+ /** \brief set second endpoint
593
+ *
594
+ * \remarks if \a point_temp is w/in a distance \a epsilon of an existing
595
+ * endpoint, the coordinates of \a point_temp are used and size is set to
596
+ * 1 as appropriate
597
+ */
598
+ void set_second(const Point& point_temp, double epsilon=0.0);
599
+ /** \brief reverse order of endpoints
600
+ *
601
+ * \post order of endpoints is reversed.
602
+ */
603
+ void reverse();
604
+ /** \brief enforce that lex. smallest endpoint first
605
+ *
606
+ * \post the lexicographically smallest endpoint (lowest x, then lowest y)
607
+ * is first
608
+ * \remarks lex. comparison is very sensitive to perturbations if
609
+ * two Points nearly define a line parallel to one of the axes
610
+ */
611
+ void enforce_standard_form();
612
+ /// erase both endpoints and set line segment empty (size 0)
613
+ void clear();
614
+ /// destructor
615
+ virtual ~Line_Segment();
616
+ protected:
617
+ //Pointer to dynamic array of endpoints.
618
+ Point *endpoints_;
619
+ //See size() comments.
620
+ unsigned size_;
621
+ };
622
+
623
+
624
+ /** \brief true iff endpoint coordinates are exactly equal, but
625
+ * false if either Line_Segment has size 0
626
+ *
627
+ * \remarks respects ordering of vertices, i.e., even if the line segments
628
+ * overlap exactly, they are not considered == unless the orientations are
629
+ * the same
630
+ */
631
+ bool operator == (const Line_Segment& line_segment1,
632
+ const Line_Segment& line_segment2);
633
+ /// true iff endpoint coordinates are not ==
634
+ bool operator != (const Line_Segment& line_segment1,
635
+ const Line_Segment& line_segment2);
636
+
637
+
638
+ /** \brief true iff line segments' endpoints match up w/in a (closed)
639
+ * \a epsilon ball of each other, but false if either
640
+ * Line_Segment has size 0
641
+ *
642
+ * \author Karl J. Obermeyer
643
+ * \remarks this function will return true even if it has to flip
644
+ * the orientation of one of the segments to get the vertices to
645
+ * match up
646
+ */
647
+ bool equivalent(Line_Segment line_segment1,
648
+ Line_Segment line_segment2, double epsilon=0);
649
+
650
+
651
+ /** \brief Euclidean distance between Line_Segments
652
+ *
653
+ * \author Karl J. Obermeyer
654
+ * \pre \a line_segment1.size() > 0 and \a line_segment2.size() > 0
655
+ */
656
+ double distance(const Line_Segment& line_segment1,
657
+ const Line_Segment& line_segment2);
658
+
659
+
660
+ /** \brief Euclidean distance between a Line_Segment and the
661
+ * boundary of a Polygon
662
+ *
663
+ * \author Karl J. Obermeyer
664
+ * \pre \a line_segment.size() > 0 and \a polygon.n() > 0
665
+ */
666
+ double boundary_distance(const Line_Segment& line_segment,
667
+ const Polygon& polygon);
668
+
669
+
670
+ /** \brief Euclidean distance between a Line_Segment and the
671
+ * boundary of a Polygon
672
+ *
673
+ * \author Karl J. Obermeyer
674
+ * \pre \a line_segment.size() > 0 and \a polygon.n() > 0
675
+ */
676
+ double boundary_distance(const Polygon& polygon,
677
+ const Line_Segment& line_segment);
678
+
679
+
680
+ /** \brief true iff the Euclidean distance between Line_Segments is
681
+ * no greater than \a epsilon, false if either line segment
682
+ * has size 0
683
+ *
684
+ * \author Karl J. Obermeyer
685
+ */
686
+ bool intersect(const Line_Segment& line_segment1,
687
+ const Line_Segment& line_segment2,
688
+ double epsilon=0.0);
689
+
690
+
691
+ /** \brief true iff line segments intersect properly w/in epsilon,
692
+ * false if either line segment has size 0
693
+ *
694
+ * \author Karl J. Obermeyer
695
+ * \return true iff Line_Segments intersect exactly at a single
696
+ * point in their relative interiors. For robustness, here the
697
+ * relative interior of a Line_Segment is consider to be any Point
698
+ * in the Line_Segment which is a distance greater than \a epsilon
699
+ * from both endpoints.
700
+ */
701
+ bool intersect_proper(const Line_Segment& line_segment1,
702
+ const Line_Segment& line_segment2,
703
+ double epsilon=0.0);
704
+
705
+
706
+ /** \brief intersection of Line_Segments
707
+ *
708
+ * \author Karl J. Obermeyer
709
+ * \return a Line_Segment of size 0, 1, or 2
710
+ * \remarks size 0 results if the distance (or at least the
711
+ * floating-point computed distance) between line_segment1 and
712
+ * line_segment2 is (strictly) greater than epsilon. size 1 results
713
+ * if the segments intersect poperly, form a T intersection, or --
714
+ * intersection. size 2 results when two or more endpoints are a
715
+ * Euclidean distance no greater than \a epsilon from the opposite
716
+ * segment, and the overlap of the segments has a length greater
717
+ * than \a epsilon.
718
+ */
719
+ Line_Segment intersection(const Line_Segment& line_segment1,
720
+ const Line_Segment& line_segment2,
721
+ double epsilon=0.0);
722
+
723
+
724
+ /// print a Line_Segment
725
+ std::ostream& operator << (std::ostream& outs,
726
+ const Line_Segment& line_segment_temp);
727
+
728
+
729
+ /** \brief angle in radians represented by a value in
730
+ * the interval [0,2*M_PI]
731
+ *
732
+ * \remarks the intended interpretation is that angles 0 and 2*M_PI
733
+ * correspond to the positive x-axis of the coordinate system
734
+ */
735
+ class Angle
736
+ {
737
+ public:
738
+ //Constructors
739
+ /** \brief default
740
+ *
741
+ * \remarks data defaults to NAN so that checking whether the
742
+ * data are numbers can be used as a precondition in functions
743
+ */
744
+ Angle() : angle_radians_(NAN) { }
745
+ /// construct from real value, mod into interval [0, 2*M_PI)
746
+ Angle(double data_temp);
747
+ /** \brief construct using 4 quadrant inverse tangent into [0, 2*M_PI),
748
+ * where 0 points along the x-axis
749
+ */
750
+ Angle(double rise_temp, double run_temp);
751
+ //Accessors
752
+ /// get radians
753
+ double get() const { return angle_radians_; }
754
+ //Mutators
755
+ /// set angle, mod into interval [0, 2*PI)
756
+ void set(double data_temp);
757
+ /** \brief set angle data to 2*M_PI
758
+ *
759
+ * \remarks sometimes it is necessary to set the angle value to
760
+ * 2*M_PI instead of 0, so that the lex. inequalities behave
761
+ * appropriately during a radial line sweep
762
+ */
763
+ void set_to_2pi() { angle_radians_=2*M_PI; }
764
+ /// set to new random angle in [0, 2*M_PI)
765
+ void randomize();
766
+ private:
767
+ double angle_radians_;
768
+ };
769
+
770
+
771
+ /// compare angle radians
772
+ bool operator == (const Angle& angle1, const Angle& angle2);
773
+ /// compare angle radians
774
+ bool operator != (const Angle& angle1, const Angle& angle2);
775
+
776
+
777
+ /// compare angle radians
778
+ bool operator > (const Angle& angle1, const Angle& angle2);
779
+ /// compare angle radians
780
+ bool operator < (const Angle& angle1, const Angle& angle2);
781
+ /// compare angle radians
782
+ bool operator >= (const Angle& angle1, const Angle& angle2);
783
+ /// compare angle radians
784
+ bool operator <= (const Angle& angle1, const Angle& angle2);
785
+
786
+
787
+ /// add angles' radians and mod into [0, 2*M_PI)
788
+ Angle operator + (const Angle& angle1, const Angle& angle2);
789
+ /// subtract angles' radians and mod into [0, 2*M_PI)
790
+ Angle operator - (const Angle& angle1, const Angle& angle2);
791
+
792
+
793
+ /** \brief geodesic distance in radians between Angles
794
+ *
795
+ * \author Karl J. Obermeyer
796
+ * \pre \a angle1 and \a angle2 data are numbers
797
+ */
798
+ double geodesic_distance(const Angle& angle1, const Angle& angle2);
799
+
800
+
801
+ /** \brief 1.0 => geodesic path from angle1 to angle2
802
+ * is couterclockwise, -1.0 => clockwise
803
+ *
804
+ * \author Karl J. Obermeyer
805
+ * \pre \a angle1 and \a angle2 data are numbers
806
+ */
807
+ double geodesic_direction(const Angle& angle1, const Angle& angle2);
808
+
809
+
810
+ /// print Angle
811
+ std::ostream& operator << (std::ostream& outs, const Angle& angle_temp);
812
+
813
+
814
+ /** \brief Point in the plane packaged together with polar
815
+ * coordinates w.r.t. specified origin
816
+ *
817
+ * The origin of the polar coordinate system is stored with the
818
+ * Polar_Point (in \a polar_origin_) and bearing is measured ccw from the
819
+ * positive x-axis.
820
+ * \remarks used, e.g., for radial line sweeps
821
+ */
822
+ class Polar_Point : public Point
823
+ {
824
+ public:
825
+ //Constructors
826
+ /** \brief default
827
+ *
828
+ * \remarks Data defaults to NAN so that checking whether the
829
+ * data are numbers can be used as a precondition in functions.
830
+ */
831
+ Polar_Point() : Point(), range_(NAN), bearing_(NAN) { }
832
+ /** \brief construct from (Cartesian) Points
833
+ *
834
+ * \pre member data of \a polar_origin_temp and \a point_temp have
835
+ * been assigned (numbers)
836
+ * \param polar_origin_temp the origin of the polar coordinate system
837
+ * \param point_temp the point to be represented
838
+ * \remarks if polar_origin_temp == point_temp, the default
839
+ * bearing is Angle(0.0)
840
+ */
841
+ Polar_Point(const Point& polar_origin_temp,
842
+ const Point& point_temp,
843
+ double epsilon=0.0);
844
+ //Accessors
845
+ /** \brief origin of the polar coordinate system in which the point is
846
+ * represented
847
+ */
848
+ Point polar_origin() const { return polar_origin_; }
849
+ /// Euclidean distance from the point represented to the origin of
850
+ /// the polar coordinate system
851
+ double range() const { return range_; }
852
+ /// bearing from polar origin w.r.t. direction parallel to x-axis
853
+ Angle bearing() const { return bearing_; }
854
+ //Mutators
855
+ /** \brief set the origin of the polar coordinate system
856
+ *
857
+ * \remarks x and y held constant, bearing and range modified
858
+ * accordingly
859
+ */
860
+ void set_polar_origin(const Point& polar_origin_temp);
861
+ /** \brief set x
862
+ *
863
+ * \remarks polar_origin held constant, bearing and range modified
864
+ * accordingly
865
+ */
866
+ void set_x(double x_temp);
867
+ /** \brief set y
868
+ *
869
+ * \remarks polar_origin held constant, bearing and range modified
870
+ * accordingly
871
+ */
872
+ void set_y(double y_temp);
873
+ /** \brief set range
874
+ *
875
+ * \remarks polar_origin held constant, x and y modified
876
+ * accordingly
877
+ */
878
+ void set_range(double range_temp);
879
+ /** \brief set bearing
880
+ *
881
+ * \remarks polar_origin and range held constant, x and y modified
882
+ * accordingly
883
+ */
884
+ void set_bearing(const Angle& bearing_temp);
885
+ /** \brief set bearing Angle data to 2*M_PI
886
+ *
887
+ * \remarks Special function for use in computations involving a
888
+ * radial line sweep; sometimes it is necessary to set the angle
889
+ * value to 2*PI instead of 0, so that the lex. inequalities
890
+ * behave appropriately
891
+ */
892
+ void set_bearing_to_2pi() { bearing_.set_to_2pi(); }
893
+ protected:
894
+ //Origin of the polar coordinate system in world coordinates.
895
+ Point polar_origin_;
896
+ //Polar coordinates where radius always positive, and angle
897
+ //measured ccw from the world coordinate system's x-axis.
898
+ double range_;
899
+ Angle bearing_;
900
+ };
901
+
902
+
903
+ /** \brief compare member data
904
+ *
905
+ * \remarks returns false if any member data are NaN
906
+ */
907
+ bool operator == (const Polar_Point& polar_point1,
908
+ const Polar_Point& polar_point2);
909
+ bool operator != (const Polar_Point& polar_point1,
910
+ const Polar_Point& polar_point2);
911
+
912
+
913
+ /** \brief compare according to polar lexicographic order
914
+ * (smaller bearing, then smaller range)
915
+ *
916
+ * false if any member data have not been assigned (numbers)
917
+ * \remarks lex. comparison is very sensitive to perturbations if
918
+ * two Points nearly define a radial line
919
+ */
920
+ bool operator > (const Polar_Point& polar_point1,
921
+ const Polar_Point& polar_point2);
922
+ /** \brief compare according to polar lexicographic order
923
+ * (smaller bearing, then smaller range)
924
+ *
925
+ * false if any member data have not been assigned (numbers)
926
+ * \remarks lex. comparison is very sensitive to perturbations if
927
+ * two Points nearly define a radial line
928
+ */
929
+ bool operator < (const Polar_Point& polar_point1,
930
+ const Polar_Point& polar_point2);
931
+ /** \brief compare according to polar lexicographic order
932
+ * (smaller bearing, then smaller range)
933
+ *
934
+ * false if any member data have not been assigned (numbers)
935
+ * \remarks lex. comparison is very sensitive to perturbations if
936
+ * two Points nearly define a radial line
937
+ */
938
+ bool operator >= (const Polar_Point& polar_point1,
939
+ const Polar_Point& polar_point2);
940
+ /** \brief compare according to polar lexicographic order
941
+ * (smaller bearing, then smaller range)
942
+ *
943
+ * false if any member data have not been assigned (numbers)
944
+ * \remarks lex. comparison is very sensitive to perturbations if
945
+ * two Points nearly define a radial line
946
+ */
947
+ bool operator <= (const Polar_Point& polar_point1,
948
+ const Polar_Point& polar_point2);
949
+
950
+
951
+ /// print Polar_Point
952
+ std::ostream& operator << (std::ostream& outs,
953
+ const Polar_Point& polar_point_temp);
954
+
955
+
956
+ /// ray in the plane represented by base Point and bearing Angle
957
+ class Ray
958
+ {
959
+ public:
960
+ //Constructors
961
+ /** \brief default
962
+ *
963
+ * \remarks data defaults to NAN so that checking whether the data
964
+ * are numbers can be used as a precondition in functions
965
+ */
966
+ Ray() { }
967
+ /// construct ray emanating from \a base_point_temp in the direction
968
+ /// \a bearing_temp
969
+ Ray(Point base_point_temp, Angle bearing_temp) :
970
+ base_point_(base_point_temp) , bearing_(bearing_temp) {}
971
+ /// construct ray emanating from \a base_point_temp towards
972
+ /// \a bearing_point
973
+ Ray(Point base_point_temp, Point bearing_point);
974
+ //Accessors
975
+ /// get base point
976
+ Point base_point() const { return base_point_; }
977
+ /// get bearing
978
+ Angle bearing() const { return bearing_; }
979
+ //Mutators
980
+ /// set base point
981
+ void set_base_point(const Point& point_temp)
982
+ { base_point_ = point_temp; }
983
+ /// set bearing
984
+ void set_bearing(const Angle& angle_temp)
985
+ { bearing_ = angle_temp; }
986
+ private:
987
+ Point base_point_;
988
+ Angle bearing_;
989
+ };
990
+
991
+
992
+ /** \brief compare member data
993
+ *
994
+ * \remarks returns false if any member data are NaN
995
+ */
996
+ bool operator == (const Ray& ray1,
997
+ const Ray& ray2);
998
+ /** \brief compare member data
999
+ *
1000
+ * \remarks negation of ==
1001
+ */
1002
+ bool operator != (const Ray& ray1,
1003
+ const Ray& ray2);
1004
+
1005
+
1006
+ /** \brief compute the intersection of a Line_Segment with a Ray
1007
+ *
1008
+ * \author Karl J. Obermeyer
1009
+ * \pre member data of \a ray_temp has been assigned (numbers) and
1010
+ * \a line_segment_temp has size greater than 0
1011
+ * \remarks as a convention, if the intersection has positive
1012
+ * length, the Line_Segment returned has the first point closest to
1013
+ * the Ray's base point
1014
+ */
1015
+ Line_Segment intersection(const Ray ray_temp,
1016
+ const Line_Segment& line_segment_temp,
1017
+ double epsilon=0.0);
1018
+ /** \brief compute the intersection of a Line_Segment with a Ray
1019
+ *
1020
+ * \author Karl J. Obermeyer
1021
+ * \pre member data of \a ray_temp has been assigned (numbers) and
1022
+ * \a line_segment_temp has size greater than 0
1023
+ * \remarks as a convention, if the intersection has positive
1024
+ * length, the Line_Segment returned has the first point closest to
1025
+ * the Ray's base point
1026
+ */
1027
+ Line_Segment intersection(const Line_Segment& line_segment_temp,
1028
+ const Ray& ray_temp,
1029
+ double epsilon=0.0);
1030
+
1031
+
1032
+ ///oriented polyline in the plane represented by list of vertices
1033
+ class Polyline
1034
+ {
1035
+ public:
1036
+ friend class Point;
1037
+ //Constructors
1038
+ /// default to empty
1039
+ Polyline() { }
1040
+ /// construct from vector of vertices
1041
+ Polyline(const std::vector<Point>& vertices_temp)
1042
+ { vertices_ = vertices_temp; }
1043
+ //Accessors
1044
+ /** \brief raw access
1045
+ *
1046
+ * \remarks for efficiency, no bounds checks; usually trying to
1047
+ * access out of bounds causes a bus error
1048
+ */
1049
+ Point operator [] (unsigned i) const
1050
+ { return vertices_[i]; }
1051
+ /// vertex count
1052
+ unsigned size() const
1053
+ { return vertices_.size(); }
1054
+ /// Euclidean length of the Polyline
1055
+ double length() const;
1056
+ /** \brief Euclidean diameter
1057
+ *
1058
+ * \pre Polyline has greater than 0 vertices
1059
+ * \return the maximum Euclidean distance between all pairs of
1060
+ * vertices
1061
+ * \remarks time complexity O(n^2), where n is the number of
1062
+ * vertices representing the Polyline
1063
+ */
1064
+ double diameter() const;
1065
+ //a box which fits snugly around the Polyline
1066
+ Bounding_Box bbox() const;
1067
+ //Mutators
1068
+ /** \brief raw access
1069
+ *
1070
+ * \remarks for efficiency, no bounds checks; usually trying to
1071
+ * access out of bounds causes a bus error
1072
+ */
1073
+ Point& operator [] (unsigned i)
1074
+ { return vertices_[i]; }
1075
+ /// erase all points
1076
+ void clear()
1077
+ { vertices_.clear(); }
1078
+ /// add a vertex to the back (end) of the list
1079
+ void push_back(const Point& point_temp)
1080
+ { vertices_.push_back(point_temp); }
1081
+ /// delete a vertex to the back (end) of the list
1082
+ void pop_back()
1083
+ { vertices_.pop_back(); }
1084
+ /// reset the whole list of vertices at once
1085
+ void set_vertices(const std::vector<Point>& vertices_temp)
1086
+ { vertices_ = vertices_temp; }
1087
+ /** \brief eliminates vertices which are (\a epsilon) - colinear
1088
+ * with their respective neighbors
1089
+ *
1090
+ * \author Karl J. Obermeyer
1091
+ * \post the Euclidean distance between each vertex and the line
1092
+ * segment connecting its neighbors is at least \a epsilon
1093
+ * \remarks time complexity O(n), where n is the number of
1094
+ * vertices representing the Polyline.
1095
+ */
1096
+ void eliminate_redundant_vertices(double epsilon=0.0);
1097
+ //Reduce number of vertices in representation...
1098
+ //void smooth(double epsilon);
1099
+ /// reverse order of vertices
1100
+ void reverse();
1101
+ /// append the points from another polyline
1102
+ void append( const Polyline& polyline );
1103
+ private:
1104
+ std::vector<Point> vertices_;
1105
+ };
1106
+
1107
+
1108
+ //print Polyline
1109
+ std::ostream& operator << (std::ostream& outs,
1110
+ const Polyline& polyline_temp);
1111
+
1112
+
1113
+ /** \brief simple polygon in the plane represented by list of vertices
1114
+ *
1115
+ * Simple here means non-self-intersecting. More precisely, edges
1116
+ * should not (i) intersect with an edge not adjacent to it, nor
1117
+ * (ii) intersect at more than one Point with an adjacent edge.
1118
+ * \remarks vertices may be listed cw or ccw
1119
+ */
1120
+ class Polygon
1121
+ {
1122
+ public:
1123
+ friend class Point;
1124
+ //Constructors
1125
+ ///default to empty
1126
+ Polygon() { }
1127
+ /** \brief construct from *.polygon file
1128
+ *
1129
+ * \author Karl J. Obermeyer
1130
+ * \remarks for efficiency, simplicity check not called here
1131
+ */
1132
+ Polygon(const std::string& filename);
1133
+ /** \brief construct from vector of vertices
1134
+ *
1135
+ * \remarks for efficiency, simplicity check not called here
1136
+ */
1137
+ Polygon(const std::vector<Point>& vertices_temp);
1138
+ /** \brief construct triangle from 3 Points
1139
+ *
1140
+ * \remarks for efficiency, simplicity check not called here
1141
+ */
1142
+ Polygon(const Point& point0, const Point& point1, const Point& point2);
1143
+ //Accessors
1144
+ /** \brief access with automatic wrap-around in forward direction
1145
+ *
1146
+ * \remarks For efficiency, no bounds check; usually trying to
1147
+ * access out of bounds causes a bus error
1148
+ */
1149
+ const Point& operator [] (unsigned i) const
1150
+ { return vertices_[i % vertices_.size()]; }
1151
+ /** \brief vertex count
1152
+ *
1153
+ * \remarks O(1) time complexity
1154
+ */
1155
+ unsigned n() const { return vertices_.size(); }
1156
+ /** \brief reflex vertex count (nonconvex vertices)
1157
+ *
1158
+ * \author Karl J. Obermeyer
1159
+ * \remarks Works regardless of polygon orientation (ccw vs cw),
1160
+ * but assumes no redundant vertices. Time complexity O(n), where
1161
+ * n is the number of vertices representing the Polygon
1162
+ */
1163
+ unsigned r() const;
1164
+ /** \brief true iff Polygon is (\a epsilon) simple
1165
+ *
1166
+ * \author Karl J. Obermeyer
1167
+ *
1168
+ * \remarks A Polygon is considered \a epsilon -simple iff (i) the
1169
+ * Euclidean distance between nonadjacent edges is no greater than
1170
+ * \a epsilon, (ii) adjacent edges intersect only at their single
1171
+ * shared Point, (iii) and it has at least 3 vertices. One
1172
+ * consequence of these conditions is that there can be no
1173
+ * redundant vertices.
1174
+ */
1175
+ bool is_simple(double epsilon=0.0) const;
1176
+ /** \brief true iff lexicographically smallest vertex is first in
1177
+ * the list of vertices representing the Polygon
1178
+ *
1179
+ * \author Karl J. Obermeyer
1180
+ * \remarks lex. comparison is very sensitive to perturbations if
1181
+ * two Points nearly define a line parallel to one of the axes
1182
+ */
1183
+ bool is_in_standard_form() const;
1184
+ /// perimeter length
1185
+ double boundary_length() const;
1186
+ /** oriented area of the Polygon
1187
+ *
1188
+ * \author Karl J. Obermeyer
1189
+ * \pre Polygon is simple, but for efficiency simplicity is not asserted.
1190
+ * area > 0 => vertices listed ccw,
1191
+ * area < 0 => cw
1192
+ * \remarks O(n) time complexity, where n is the number
1193
+ * of vertices representing the Polygon
1194
+ */
1195
+ double area() const;
1196
+ /** \brief Polygon's centroid (center of mass)
1197
+ *
1198
+ * \author Karl J. Obermeyer
1199
+ * \pre Polygon has greater than 0 vertices and is simple,
1200
+ * but for efficiency simplicity is not asserted
1201
+ */
1202
+ Point centroid() const;
1203
+ /** \brief Euclidean diameter
1204
+ *
1205
+ * \pre Polygon has greater than 0 vertices
1206
+ * \return maximum Euclidean distance between all pairs of
1207
+ * vertices
1208
+ * \remarks time complexity O(n^2), where n is the number of
1209
+ * vertices representing the Polygon
1210
+ */
1211
+ double diameter() const;
1212
+ /** \brief box which fits snugly around the Polygon
1213
+ *
1214
+ * \author Karl J. Obermeyer
1215
+ * \pre Polygon has greater than 0 vertices
1216
+ */
1217
+ Bounding_Box bbox() const;
1218
+ // Returns a vector of n pts randomly situated in the polygon.
1219
+ std::vector<Point> random_points(const unsigned& count,
1220
+ double epsilon=0.0) const;
1221
+ /** \brief write list of vertices to *.polygon file
1222
+ *
1223
+ * \author Karl J. Obermeyer
1224
+ * Uses intuitive human and computer readable decimal format with
1225
+ * display precision \a fios_precision_temp.
1226
+ * \pre \a fios_precision_temp >=1
1227
+ */
1228
+ void write_to_file(const std::string& filename,
1229
+ int fios_precision_temp=FIOS_PRECISION);
1230
+ //Mutators
1231
+ /** \brief access with automatic wrap-around in forward direction
1232
+ *
1233
+ * \remarks for efficiency, no bounds check; usually trying to
1234
+ * access out of bounds causes a bus error
1235
+ */
1236
+ Point& operator [] (unsigned i) { return vertices_[i % vertices_.size()]; }
1237
+ /// set vertices using STL vector of Points
1238
+ void set_vertices(const std::vector<Point>& vertices_temp)
1239
+ { vertices_ = vertices_temp; }
1240
+ /// push a Point onto the back of the vertex list
1241
+ void push_back(const Point& vertex_temp )
1242
+ { vertices_.push_back( vertex_temp ); }
1243
+ /// erase all vertices
1244
+ void clear()
1245
+ { vertices_.clear(); }
1246
+ /** \brief enforces that the lexicographically smallest vertex is first
1247
+ * in the list of vertices representing the Polygon
1248
+ *
1249
+ * \author Karl J. Obermeyer
1250
+ * \remarks O(n) time complexity, where n is the number of
1251
+ * vertices representing the Polygon. Lex. comparison is very
1252
+ * sensitive to perturbations if two Points nearly define a line
1253
+ * parallel to one of the axes
1254
+ */
1255
+ void enforce_standard_form();
1256
+ /** \brief eliminates vertices which are (\a epsilon) - colinear
1257
+ * with their respective neighbors
1258
+ *
1259
+ * \author Karl J. Obermeyer
1260
+ * \post the Euclidean distance between each vertex and the line
1261
+ * segment connecting its neighbors is at least \a epsilon, and the
1262
+ * Polygon is in standard form
1263
+ * \remarks time complexity O(n), where n is the number of
1264
+ * vertices representing the the Polygon
1265
+ */
1266
+ void eliminate_redundant_vertices(double epsilon=0.0);
1267
+ /** \brief reverse (cyclic) order of vertices
1268
+ *
1269
+ * \remarks vertex first in list is held first
1270
+ */
1271
+ void reverse();
1272
+ protected:
1273
+ std::vector<Point> vertices_;
1274
+ };
1275
+
1276
+
1277
+ /** \brief true iff vertex lists are identical, but false if either
1278
+ * Polygon has size 0
1279
+ *
1280
+ * \remarks returns false if either Polygon has size 0
1281
+ * \remarks O(n) time complexity
1282
+ */
1283
+ bool operator == (Polygon polygon1, Polygon polygon2);
1284
+ bool operator != (Polygon polygon1, Polygon polygon2);
1285
+ /** \brief true iff the Polygon's vertices match up w/in a (closed)
1286
+ * epsilon ball of each other, but false if either Polygon
1287
+ * has size 0
1288
+ *
1289
+ * Respects number, ordering, and orientation of vertices, i.e.,
1290
+ * even if the (conceptual) polygons represented by two Polygons are
1291
+ * identical, they are not considered \a epsilon - equivalent unless
1292
+ * the number of vertices is the same, the orientations are the same
1293
+ * (cw vs. ccw list), and the Points of the vertex lists match up
1294
+ * within epsilon. This function does attempt to match the polygons
1295
+ * for all possible cyclic permutations, hence the quadratic time
1296
+ * complexity.
1297
+ * \author Karl J. Obermeyer
1298
+ * \remarks O(n^2) time complexity, where n is the number of
1299
+ * vertices representing the polygon
1300
+ */
1301
+ bool equivalent(Polygon polygon1, Polygon polygon2,
1302
+ double epsilon=0.0);
1303
+
1304
+
1305
+ /** \brief Euclidean distance between Polygons' boundaries
1306
+ *
1307
+ * \author Karl J. Obermeyer
1308
+ * \pre \a polygon1 and \a polygon2 each have greater than 0 vertices
1309
+ */
1310
+ double boundary_distance( const Polygon& polygon1,
1311
+ const Polygon& polygon2 );
1312
+
1313
+
1314
+ //print Polygon
1315
+ std::ostream& operator << (std::ostream& outs,
1316
+ const Polygon& polygon_temp);
1317
+
1318
+
1319
+ /** \brief environment represented by simple polygonal outer boundary
1320
+ * with simple polygonal holes
1321
+ *
1322
+ * \remarks For methods to work correctly, the outer boundary vertices must
1323
+ * be listed ccw and the hole vertices cw
1324
+ */
1325
+ class Environment
1326
+ {
1327
+ public:
1328
+ friend class Point;
1329
+ //Constructors
1330
+ /// default to empty
1331
+ Environment() { }
1332
+ /** \brief construct Environment without holes
1333
+ *
1334
+ * \remarks time complexity O(n), where n is the number of vertices
1335
+ * representing the Environment
1336
+ */
1337
+ Environment(const Polygon& polygon_temp)
1338
+ { outer_boundary_=polygon_temp; update_flattened_index_key(); }
1339
+ /** \brief construct Environment with holes from STL vector of Polygons
1340
+ *
1341
+ * the first Polygon in the vector becomes the outer boundary,
1342
+ * the rest become the holes
1343
+ * \remarks time complexity O(n), where n is the number of vertices
1344
+ * representing the Environment
1345
+ */
1346
+ Environment(const std::vector<Polygon>& polygons);
1347
+ /** construct from *.environment file.
1348
+ *
1349
+ * \author Karl J. Obermeyer
1350
+ * \remarks time complexity O(n), where n is the number of vertices
1351
+ * representing the Environment
1352
+ */
1353
+ Environment(const std::string& filename);
1354
+ //Accessors
1355
+ /** \brief raw access to Polygons
1356
+ *
1357
+ * An argument of 0 accesses the outer boundary, 1 and above
1358
+ * access the holes.
1359
+ * \remarks for efficiency, no bounds check; usually trying to
1360
+ * access out of bounds causes a bus error
1361
+ */
1362
+ const Polygon& operator [] (unsigned i) const
1363
+ { if(i==0){return outer_boundary_;} else{return holes_[i-1];} }
1364
+ /** \brief raw access to vertices via flattened index
1365
+ *
1366
+ * By flattened index is intended the label given to a vertex if
1367
+ * you were to label all the vertices from 0 to n-1 (where n is
1368
+ * the number of vertices representing the Environment) starting
1369
+ * with the first vertex of the outer boundary and progressing in
1370
+ * order through all the remaining vertices of the outer boundary
1371
+ * and holes.
1372
+ *
1373
+ * \remarks Time complexity O(1). For efficiency, no bounds
1374
+ * check; usually trying to access out of bounds causes a bus
1375
+ * error.
1376
+ */
1377
+ const Point& operator () (unsigned k) const;
1378
+ /// hole count
1379
+ unsigned h() const { return holes_.size(); }
1380
+ /** \brief vertex count
1381
+ *
1382
+ * \remarks time complexity O(h)
1383
+ */
1384
+ unsigned n() const;
1385
+ /** \brief total reflex vertex count (nonconvex vertices)
1386
+ *
1387
+ * \author Karl J. Obermeyer
1388
+ * \remarks time complexity O(n), where n is the number of
1389
+ * vertices representing the Environment
1390
+ */
1391
+ unsigned r() const;
1392
+ /** \brief true iff lexicographically smallest vertex is first in
1393
+ * each list of vertices representing a Polygon of the
1394
+ * Environment
1395
+ *
1396
+ * \author Karl J. Obermeyer
1397
+ * \remarks lex. comparison is very sensitive to perturbations if
1398
+ * two Points nearly define a line parallel to one of the axes
1399
+ */
1400
+ bool is_in_standard_form() const;
1401
+ /** \brief true iff \a epsilon -valid
1402
+ *
1403
+ * \a epsilon -valid means (i) the outer boundary and holes are
1404
+ * pairwise \a epsilon -disjoint (no two features should come
1405
+ * within \a epsilon of each other) simple polygons, (ii) outer
1406
+ * boundary is oriented ccw, and (iii) holes are oriented cw.
1407
+ *
1408
+ * \author Karl J. Obermeyer
1409
+ *
1410
+ * \pre Environment has greater than 2 vertices
1411
+ * (otherwise it can't even have nonzero area)
1412
+ * \remarks time complexity O(h^2*n^2), where h is the number of
1413
+ * holes and n is the number of vertices representing the
1414
+ * Environment
1415
+ */
1416
+ bool is_valid(double epsilon=0.0) const;
1417
+ /** \brief sum of perimeter lengths of outer boundary and holes
1418
+ *
1419
+ * \author Karl J. Obermeyer
1420
+ * \remarks O(n) time complexity, where n is the number of
1421
+ * vertices representing the Environment
1422
+ */
1423
+ double boundary_length() const;
1424
+ /** \brief (obstacle/hole free) area of the Environment
1425
+ *
1426
+ * \author Karl J. Obermeyer
1427
+ * \remarks O(n) time complexity, where n is the number of
1428
+ * vertices representing the Environment
1429
+ */
1430
+ double area() const;
1431
+ /** \brief Euclidean diameter
1432
+ *
1433
+ * \author Karl J. Obermeyer
1434
+ * \pre Environment has greater than 0 vertices
1435
+ * \return maximum Euclidean distance between all pairs of
1436
+ * vertices
1437
+ * \remarks time complexity O(n^2), where n is the number of
1438
+ * vertices representing the Environment
1439
+ */
1440
+ double diameter() const { return outer_boundary_.diameter(); }
1441
+ /** \brief box which fits snugly around the Environment
1442
+ *
1443
+ * \author Karl J. Obermeyer
1444
+ * \pre Environment has greater than 0 vertices
1445
+ */
1446
+ Bounding_Box bbox() const { return outer_boundary_.bbox(); }
1447
+ /** \brief get STL vector of \a count Points randomly situated
1448
+ * within \a epsilon of the Environment
1449
+ *
1450
+ * \author Karl J. Obermeyer
1451
+ * \pre the Environment has positive area
1452
+ */
1453
+ std::vector<Point> random_points(const unsigned& count,
1454
+ double epsilon=0.0) const;
1455
+ /** \brief compute a shortest path between 2 Points
1456
+ *
1457
+ * Uses the classical visibility graph method as described, e.g.,
1458
+ * in ``Robot Motion Planning" (Ch. 4 Sec. 1) by J.C. Latombe.
1459
+ * Specifically, an A* search is performed on the visibility graph
1460
+ * using the Euclidean distance as the heuristic function.
1461
+ *
1462
+ * \author Karl J. Obermeyer
1463
+ *
1464
+ * \pre \a start and \a finish must be in the environment.
1465
+ * Environment must be \a epsilon -valid. Test with
1466
+ * Environment::is_valid(epsilon).
1467
+ *
1468
+ * \remarks If multiple shortest path queries are made for the
1469
+ * same Envrionment, it is better to precompute the
1470
+ * Visibility_Graph. For a precomputed Visibility_Graph, the time
1471
+ * complexity of a shortest_path() query is O(n^2), where n is the
1472
+ * number of vertices representing the Environment.
1473
+ *
1474
+ * \todo return not just one, but all shortest paths (w/in
1475
+ * epsilon), e.g., returning a std::vector<Polyline>)
1476
+ */
1477
+ Polyline shortest_path(const Point& start,
1478
+ const Point& finish,
1479
+ const Visibility_Graph& visibility_graph,
1480
+ double epsilon=0.0);
1481
+ /** \brief compute shortest path between 2 Points
1482
+ *
1483
+ * \author Karl J. Obermeyer
1484
+ *
1485
+ * \pre \a start and \a finish must be in the environment.
1486
+ * Environment must be \a epsilon -valid. Test with
1487
+ * Environment::is_valid(epsilon).
1488
+ *
1489
+ * \remarks For single shortest path query, visibility graph is
1490
+ * not precomputed. Time complexity O(n^3), where n is the number
1491
+ * of vertices representing the Environment.
1492
+ */
1493
+ Polyline shortest_path(const Point& start,
1494
+ const Point& finish,
1495
+ double epsilon=0.0);
1496
+ /** \brief compute the faces (partition cells) of an arrangement
1497
+ * of Line_Segments inside the Environment
1498
+ *
1499
+ * \author Karl J. Obermeyer
1500
+ * \todo finish this
1501
+ */
1502
+ std::vector<Polygon> compute_partition_cells( std::vector<Line_Segment>
1503
+ partition_inducing_segments,
1504
+ double epsilon=0.0 )
1505
+ {
1506
+ std::vector<Polygon> cells;
1507
+ return cells;
1508
+ }
1509
+ /** \brief write lists of vertices to *.environment file
1510
+ *
1511
+ * uses intuitive human and computer readable decimal format with
1512
+ * display precision \a fios_precision_temp
1513
+ * \author Karl J. Obermeyer
1514
+ * \pre \a fios_precision_temp >=1
1515
+ */
1516
+ void write_to_file(const std::string& filename,
1517
+ int fios_precision_temp=FIOS_PRECISION);
1518
+ //Mutators
1519
+ /** \brief raw access to Polygons
1520
+ *
1521
+ * An argument of 0 accesses the outer boundary, 1 and above
1522
+ * access the holes.
1523
+ * \author Karl J. Obermeyer
1524
+ * \remarks for efficiency, no bounds check; usually trying to
1525
+ * access out of bounds causes a bus error
1526
+ */
1527
+ Polygon& operator [] (unsigned i)
1528
+ { if(i==0){return outer_boundary_;} else{return holes_[i-1];} }
1529
+ //Mutators
1530
+ /** \brief raw access to vertices via flattened index
1531
+ *
1532
+ * By flattened index is intended the label given to a vertex if
1533
+ * you were to label all the vertices from 0 to n-1 (where n is
1534
+ * the number of vertices representing the Environment) starting
1535
+ * with the first vertex of the outer boundary and progressing in
1536
+ * order through all the remaining vertices of the outer boundary
1537
+ * and holes.
1538
+ * \author Karl J. Obermeyer
1539
+ * \remarks for efficiency, no bounds check; usually trying to
1540
+ * access out of bounds causes a bus error.
1541
+ */
1542
+ Point& operator () (unsigned k);
1543
+ /// set outer boundary
1544
+ void set_outer_boundary(const Polygon& polygon_temp)
1545
+ { outer_boundary_ = polygon_temp; update_flattened_index_key(); }
1546
+ /// add hole
1547
+ void add_hole(const Polygon& polygon_temp)
1548
+ { holes_.push_back(polygon_temp); update_flattened_index_key(); }
1549
+ /** \brief enforces outer boundary vertices are listed ccw and
1550
+ * holes listed cw, and that these lists begin with respective
1551
+ * lexicographically smallest vertex
1552
+ *
1553
+ * \author Karl J. Obermeyer
1554
+ * \remarks O(n) time complexity, where n is the number of
1555
+ * vertices representing the Environment. Lex. comparison is very
1556
+ * sensitive to perturbations if two Points nearly define a line
1557
+ * parallel to one of the axes.
1558
+ */
1559
+ void enforce_standard_form();
1560
+ /** \brief eliminates vertices which are (\a epsilon) - colinear
1561
+ * with their respective neighbors
1562
+ *
1563
+ * \author Karl J. Obermeyer
1564
+ * \post the Euclidean distance between each vertex and the line
1565
+ * segment connecting its neighbors is at least \a epsilon
1566
+ * \remarks time complexity O(n), where n is the number of
1567
+ * vertices representing the the Environment
1568
+ */
1569
+ void eliminate_redundant_vertices(double epsilon=0.0);
1570
+ /** \brief reverse (cyclic) order of vertices belonging to holes
1571
+ * only
1572
+ *
1573
+ * \remarks vertex first in each hole's list is held first
1574
+ */
1575
+ void reverse_holes();
1576
+ private:
1577
+ Polygon outer_boundary_;
1578
+ //obstacles
1579
+ std::vector<Polygon> holes_;
1580
+ //allows constant time access to vertices via operator () with
1581
+ //flattened index as argument
1582
+ std::vector< std::pair<unsigned,unsigned> > flattened_index_key_;
1583
+ //Must call if size of outer_boundary and/or holes_ changes. Time
1584
+ //complexity O(n), where n is the number of vertices representing
1585
+ //the Environment.
1586
+ void update_flattened_index_key();
1587
+ //converts flattened index to index pair (hole #, vertex #) in
1588
+ //time O(n), where n is the number of vertices representing the
1589
+ //Environment
1590
+ std::pair<unsigned,unsigned> one_to_two(unsigned k) const;
1591
+ //node used for search tree of A* search in shortest_path() method
1592
+ class Shortest_Path_Node
1593
+ {
1594
+ public:
1595
+ //flattened index of corresponding Environment vertex
1596
+ //convention vertex_index = n() => corresponds to start Point
1597
+ //vertex_index = n() + 1 => corresponds to finish Point
1598
+ unsigned vertex_index;
1599
+ //pointer to self in search tree.
1600
+ std::list<Shortest_Path_Node>::iterator search_tree_location;
1601
+ //pointer to parent in search tree.
1602
+ std::list<Shortest_Path_Node>::iterator parent_search_tree_location;
1603
+ //Geodesic distance from start Point.
1604
+ double cost_to_come;
1605
+ //Euclidean distance to finish Point.
1606
+ double estimated_cost_to_go;
1607
+ //std::vector<Shortest_Path_Node> expand();
1608
+ bool operator < (const Shortest_Path_Node& spn2) const
1609
+ {
1610
+ double f1 = this->cost_to_come + this->estimated_cost_to_go;
1611
+ double f2 = spn2.cost_to_come + spn2.estimated_cost_to_go;
1612
+ if( f1 < f2 )
1613
+ return true;
1614
+ else if( f2 < f1 )
1615
+ return false;
1616
+ else if( this->vertex_index < spn2.vertex_index )
1617
+ return true;
1618
+ else if( this->vertex_index > spn2.vertex_index )
1619
+ return false;
1620
+ else if( &(*(this->parent_search_tree_location))
1621
+ < &(*(spn2.parent_search_tree_location)) )
1622
+ return true;
1623
+ else
1624
+ return false;
1625
+ }
1626
+ // print member data for debugging
1627
+ void print() const
1628
+ {
1629
+ std::cout << " vertex_index = " << vertex_index << std::endl
1630
+ << "parent's vertex_index = "
1631
+ << parent_search_tree_location->vertex_index
1632
+ << std::endl
1633
+ << " cost_to_come = " << cost_to_come << std::endl
1634
+ << " estimated_cost_to_go = "
1635
+ << estimated_cost_to_go << std::endl;
1636
+ }
1637
+ };
1638
+ };
1639
+
1640
+
1641
+ /// printing Environment
1642
+ std::ostream& operator << (std::ostream& outs,
1643
+ const Environment& environment_temp);
1644
+
1645
+
1646
+ /** \brief set of Guards represented by a list of Points
1647
+ */
1648
+ class Guards
1649
+ {
1650
+ public:
1651
+ friend class Visibility_Graph;
1652
+ //Constructors
1653
+ /// default to empty
1654
+ Guards() { }
1655
+ /** \brief construct from *.guards file
1656
+ *
1657
+ * \author Karl J. Obermeyer
1658
+ */
1659
+ Guards(const std::string& filename);
1660
+ /// construct from STL vector of Points
1661
+ Guards(const std::vector<Point>& positions)
1662
+ { positions_ = positions; }
1663
+ //Accessors
1664
+ /** \brief raw access to guard position Points
1665
+ *
1666
+ * \author Karl J. Obermeyer
1667
+ * \remarks for efficiency, no bounds check; usually trying to
1668
+ * access out of bounds causes a bus error
1669
+ */
1670
+ const Point& operator [] (unsigned i) const { return positions_[i]; }
1671
+ /// guard count
1672
+ unsigned N() const { return positions_.size(); }
1673
+ /// true iff positions are lexicographically ordered
1674
+ bool are_lex_ordered() const;
1675
+ /// true iff no two guards are w/in epsilon of each other
1676
+ bool noncolocated(double epsilon=0.0) const;
1677
+ /// true iff all guards are located in \a polygon_temp
1678
+ bool in(const Polygon& polygon_temp, double epsilon=0.0) const;
1679
+ /// true iff all guards are located in \a environment_temp
1680
+ bool in(const Environment& environment_temp, double epsilon=0.0) const;
1681
+ /** \brief Euclidean diameter
1682
+ *
1683
+ * \author Karl J. Obermeyer
1684
+ * \pre greater than 0 guards
1685
+ * \return maximum Euclidean distance between all pairs of
1686
+ * vertices
1687
+ * \remarks time complexity O(N^2), where N is the number of
1688
+ * guards
1689
+ */
1690
+ double diameter() const;
1691
+ /** \brief box which fits snugly around the Guards
1692
+ *
1693
+ * \author Karl J. Obermeyer
1694
+ * \pre greater than 0 guards
1695
+ */
1696
+ Bounding_Box bbox() const;
1697
+ /** \brief write list of positions to *.guards file
1698
+ *
1699
+ * Uses intuitive human and computer readable decimal format with
1700
+ * display precision \a fios_precision_temp.
1701
+ * \author Karl J. Obermeyer
1702
+ * \pre \a fios_precision_temp >=1
1703
+ */
1704
+ void write_to_file(const std::string& filename,
1705
+ int fios_precision_temp=FIOS_PRECISION);
1706
+ //Mutators
1707
+ /** \brief raw access to guard position Points
1708
+ *
1709
+ * \author Karl J. Obermeyer
1710
+ * \remarks for efficiency, no bounds check; usually trying to
1711
+ * access out of bounds causes a bus error
1712
+ */
1713
+ Point& operator [] (unsigned i) { return positions_[i]; }
1714
+ /// add a guard
1715
+ void push_back(const Point& point_temp)
1716
+ { positions_.push_back(point_temp); }
1717
+ /// set positions with STL vector of Points
1718
+ void set_positions(const std::vector<Point>& positions_temp)
1719
+ { positions_ = positions_temp; }
1720
+ /** \brief sort positions in lexicographic order
1721
+ *
1722
+ * from (lowest x, then lowest y) to (highest x, then highest y)
1723
+ * \author Karl J. Obermeyer
1724
+ * \remarks time complexity O(N logN), where N is the guard count.
1725
+ * Lex. comparison is very sensitive to perturbations if two
1726
+ * Points nearly define a line parallel to one of the axes.
1727
+ */
1728
+ void enforce_lex_order();
1729
+ /// reverse order of positions
1730
+ void reverse();
1731
+ /** \brief relocate each guard to closest vertex if within
1732
+ * \a epsilon of some vertex (of \a environment_temp)
1733
+ *
1734
+ * \author Karl J. Obermeyer
1735
+ * \pre the guards' position data are numbers and \a environment_temp
1736
+ * is nonempty
1737
+ * \post if a guard was a Euclidean distance no greater
1738
+ * than \a epsilon from any vertex of \a environment_temp, then it
1739
+ * will be repositioned to coincide with the closest such vertex
1740
+ * \remarks O(N*n) time complexity, where N is the guard count
1741
+ * and n is the number of vertices in \a environment_temp.
1742
+ */
1743
+ void snap_to_vertices_of(const Environment& environment_temp,
1744
+ double epsilon=0.0);
1745
+
1746
+ /** \brief relocate each guard to closest vertex if within
1747
+ * \a epsilon of some vertex (of \a environment_temp)
1748
+ *
1749
+ * \author Karl J. Obermeyer
1750
+ * \pre the guards' position data are numbers and \a polygon_temp
1751
+ * is nonempty
1752
+ * \post if a guard was a Euclidean distance no greater
1753
+ * than \a epsilon from any vertex of \a polygon_temp, then it
1754
+ * will be repositioned to coincide with the closest such vertex
1755
+ * \remarks O(N*n) time complexity, where N is the guard count
1756
+ * and n is the number of vertices in \a polygon_temp
1757
+ */
1758
+ void snap_to_vertices_of(const Polygon& polygon_temp,
1759
+ double epsilon=0.0);
1760
+ /** \brief relocate each guard to closest Point on boundary if
1761
+ * within \a epsilon of the boundary (of \a environment_temp)
1762
+ *
1763
+ * \author Karl J. Obermeyer
1764
+ * \pre the guards' position data are numbers and \a environment_temp
1765
+ * is nonempty
1766
+ * \post If the calling Point was a Euclidean distance no greater
1767
+ * than \a epsilon from the boundary of \a environment_temp, then it
1768
+ * will be repositioned to it's projection onto that boundary
1769
+ * \remarks O(N*n) time complexity, where N is the guard count and
1770
+ * n is the number of vertices in \a environment_temp
1771
+ */
1772
+ void snap_to_boundary_of(const Environment& environment_temp,
1773
+ double epsilon=0.0);
1774
+ /** \brief relocate each guard to closest Point on boundary if
1775
+ * within \a epsilon of the boundary (of \a polygon_temp)
1776
+ *
1777
+ * \author Karl J. Obermeyer
1778
+ * \pre the guards' position data are numbers and \a polygon_temp
1779
+ * is nonempty
1780
+ * \post If the calling Point was a Euclidean distance no greater
1781
+ * than \a epsilon from the boundary of \a polygon_temp, then it
1782
+ * will be repositioned to it's projection onto that boundary
1783
+ * \remarks O(N*n) time complexity, where N is the guard count and
1784
+ * n is the number of vertices in \a polygon_temp
1785
+ */
1786
+ void snap_to_boundary_of(const Polygon& polygon_temp,
1787
+ double epsilon=0.0);
1788
+ private:
1789
+ std::vector<Point> positions_;
1790
+ };
1791
+
1792
+
1793
+ /// print Guards
1794
+ std::ostream& operator << (std::ostream& outs,
1795
+ const Guards& guards);
1796
+
1797
+
1798
+ /** \brief visibility polygon of a Point in an Environment or Polygon
1799
+ *
1800
+ * A Visibility_Polygon represents the closure of the set of all
1801
+ * points in an environment which are {\it clearly visible} from a
1802
+ * point (the observer). Two Points p1 and p2 are (mutually) {\it
1803
+ * clearly visible} in an environment iff the relative interior of
1804
+ * the line segment connecting p1 and p2 does not intersect the
1805
+ * boundary of the environment.
1806
+ *
1807
+ * \remarks average case time complexity O(n log(n)), where n is the
1808
+ * number of vertices in the Evironment (resp. Polygon). Note the
1809
+ * Standard Library's sort() function performs O(n log(n))
1810
+ * comparisons (both average and worst-case) and the sort() member
1811
+ * function of an STL list performs "approximately O(n log(n))
1812
+ * comparisons". For robustness, any Point (observer) should be \a
1813
+ * epsilon -snapped to the environment boundary and vertices before
1814
+ * computing its Visibility_Polygon (use the Point methods
1815
+ * snap_to_vertices_of(...) and snap_to_boundary_of(...) ).
1816
+ */
1817
+ class Visibility_Polygon : public Polygon
1818
+ {
1819
+ public:
1820
+ //Constructors
1821
+ /// default to empty
1822
+ Visibility_Polygon() { }
1823
+ //:TRICKY:
1824
+ /** \brief visibility set of a Point in an Environment
1825
+ *
1826
+ * \author Karl J. Obermeyer
1827
+ *
1828
+ * \pre \a observer is in \a environment_temp (w/in \a epsilon )
1829
+ * and has been epsilon-snapped to the Environment using the
1830
+ * method Point::snap_to_boundary_of() followed by (order is
1831
+ * important) Point::snap_to_vertices_of(). \a environment_temp
1832
+ * must be \a epsilon -valid. Test with
1833
+ * Environment::is_valid(epsilon).
1834
+ *
1835
+ * \remarks O(n log(n)) average case time complexity, where n is the
1836
+ * number of vertices in the Evironment (resp. Polygon).
1837
+ */
1838
+ Visibility_Polygon(const Point& observer,
1839
+ const Environment& environment_temp,
1840
+ double epsilon=0.0);
1841
+ /** \brief visibility set of a Point in a Polygon
1842
+ *
1843
+ * \pre \a observer is in \a polygon_temp (w/in \a epsilon ) and
1844
+ * has been epsilon-snapped to the Polygon using the methods
1845
+ * Point::snap_to_vertices_of() and Point::snap_to_boundary_of().
1846
+ * \a environment_temp must be \a epsilon -valid. Test with
1847
+ * Environment::is_valid(epsilon).
1848
+ *
1849
+ * \remarks less efficient because constructs an Environment from
1850
+ * a Polygon and then calls the other Visibility_Polygon constructor.
1851
+ * O(n log(n)) average case time complexity, where n is the
1852
+ * number of vertices in the Evironment (resp. Polygon).
1853
+ */
1854
+ Visibility_Polygon(const Point& observer,
1855
+ const Polygon& polygon_temp,
1856
+ double epsilon=0.0);
1857
+ //Accessors
1858
+ //std::vector<bool> get_gap_edges(double epsilon=0.0) { return gap_edges_; }
1859
+ /// location of observer which induced the visibility polygon
1860
+ Point observer() const
1861
+ { return observer_; }
1862
+ //Mutators
1863
+ private:
1864
+ //ith entry of gap_edges is true iff the edge following ith vertex
1865
+ //is a gap edge (not solid).
1866
+ //std::vector<bool> gap_edges_;
1867
+ Point observer_;
1868
+
1869
+ struct Polar_Edge
1870
+ {
1871
+ Polar_Point first;
1872
+ Polar_Point second;
1873
+ Polar_Edge() { }
1874
+ Polar_Edge(const Polar_Point& ppoint1,
1875
+ const Polar_Point& ppoint2) :
1876
+ first(ppoint1), second(ppoint2) {}
1877
+ };
1878
+
1879
+ class Polar_Point_With_Edge_Info : public Polar_Point
1880
+ {
1881
+ public:
1882
+ std::list<Polar_Edge>::iterator incident_edge;
1883
+ bool is_first; //True iff polar_point is the first_point of the
1884
+ //Polar_Edge pointed to by
1885
+ //incident_edge.
1886
+ void set_polar_point(const Polar_Point& ppoint_temp)
1887
+ {
1888
+ set_polar_origin( ppoint_temp.polar_origin() );
1889
+ set_x( ppoint_temp.x() );
1890
+ set_y( ppoint_temp.y() );
1891
+ set_range( ppoint_temp.range() );
1892
+ set_bearing( ppoint_temp.bearing() );
1893
+ }
1894
+ //The operator < is the same as for Polar_Point with one
1895
+ //exception. If two vertices have equal coordinates, but one is
1896
+ //the first point of its respecitve edge and the other is the
1897
+ //second point of its respective edge, then the vertex which is
1898
+ //the second point of its respective edge is considered
1899
+ //lexicographically smaller.
1900
+ friend bool operator < (const Polar_Point_With_Edge_Info& ppwei1,
1901
+ const Polar_Point_With_Edge_Info& ppwei2)
1902
+ {
1903
+ if( Polar_Point(ppwei1) == Polar_Point(ppwei2)
1904
+ and !ppwei1.is_first and ppwei2.is_first )
1905
+ return true;
1906
+ else
1907
+ return Polar_Point(ppwei1) < Polar_Point(ppwei2);
1908
+ }
1909
+ };
1910
+
1911
+ //Strict weak ordering (acts like <) for pointers to Polar_Edges.
1912
+ //Used to sort the priority_queue q2 used in the radial line sweep
1913
+ //of Visibility_Polygon constructors. Let p1 be a pointer to
1914
+ //Polar_Edge e1 and p2 be a pointer to Polar_Edge e2. Then p1 is
1915
+ //considered greater (higher priority) than p2 if the distance
1916
+ //from the observer (pointed to by observer_pointer) to e1 along
1917
+ //the direction to current_vertex is smaller than the distance
1918
+ //from the observer to e2 along the direction to current_vertex.
1919
+ class Incident_Edge_Compare
1920
+ {
1921
+ const Point *const observer_pointer;
1922
+ const Polar_Point_With_Edge_Info *const current_vertex_pointer;
1923
+ double epsilon;
1924
+ public:
1925
+ Incident_Edge_Compare(const Point& observer,
1926
+ const Polar_Point_With_Edge_Info& current_vertex,
1927
+ double epsilon_temp) :
1928
+ observer_pointer(&observer),
1929
+ current_vertex_pointer(&current_vertex),
1930
+ epsilon(epsilon_temp) { }
1931
+ bool operator () (std::list<Polar_Edge>::iterator e1,
1932
+ std::list<Polar_Edge>::iterator e2) const
1933
+ {
1934
+ Polar_Point k1, k2;
1935
+ Line_Segment xing1 = intersection( Ray(*observer_pointer,
1936
+ current_vertex_pointer->bearing()),
1937
+ Line_Segment(e1->first,
1938
+ e1->second),
1939
+ epsilon);
1940
+ Line_Segment xing2 = intersection( Ray(*observer_pointer,
1941
+ current_vertex_pointer->bearing()),
1942
+ Line_Segment(e2->first,
1943
+ e2->second),
1944
+ epsilon);
1945
+ if( xing1.size() > 0 and xing2.size() > 0 ){
1946
+ k1 = Polar_Point( *observer_pointer,
1947
+ xing1.first() );
1948
+ k2 = Polar_Point( *observer_pointer,
1949
+ xing2.first() );
1950
+ if( k1.range() <= k2.range() )
1951
+ return false;
1952
+ return true;
1953
+ }
1954
+ //Otherwise infeasible edges are given higher priority, so they
1955
+ //get pushed out the top of the priority_queue's (q2's)
1956
+ //heap.
1957
+ else if( xing1.size() == 0 and xing2.size() > 0 )
1958
+ return false;
1959
+ else if( xing1.size() > 0 and xing2.size() == 0 )
1960
+ return true;
1961
+ else
1962
+ return true;
1963
+ }
1964
+ };
1965
+
1966
+ bool is_spike( const Point& observer,
1967
+ const Point& point1,
1968
+ const Point& point2,
1969
+ const Point& point3,
1970
+ double epsilon=0.0 ) const;
1971
+
1972
+ //For eliminating spikes as they appear. In the
1973
+ //Visibility_Polygon constructors, these are checked every time a
1974
+ //Point is added to vertices.
1975
+ void chop_spikes_at_back(const Point& observer,
1976
+ double epsilon);
1977
+ void chop_spikes_at_wrap_around(const Point& observer,
1978
+ double epsilon);
1979
+ void chop_spikes(const Point& observer,
1980
+ double epsilon);
1981
+ //For debugging Visibility_Polygon constructors.
1982
+ //Prints current_vertex and active_edge data to screen.
1983
+ void print_cv_and_ae(const Polar_Point_With_Edge_Info& current_vertex,
1984
+ const std::list<Polar_Edge>::iterator&
1985
+ active_edge);
1986
+ };
1987
+
1988
+
1989
+ /** \brief visibility graph of points in an Environment,
1990
+ * represented by adjacency matrix
1991
+ *
1992
+ * \remarks used for shortest path planning in the
1993
+ * Environment::shortest_path() method
1994
+ *
1995
+ * \todo Add method to prune edges for faster shortest path
1996
+ * calculation, e.g., exclude concave vertices and only include
1997
+ * tangent edges as described in ``Robot Motion Planning" (Ch. 4
1998
+ * Sec. 1) by J.C. Latombe.
1999
+ */
2000
+ class Visibility_Graph
2001
+ {
2002
+ public:
2003
+ //Constructors
2004
+ /// default to empty
2005
+ Visibility_Graph() { n_=0; adjacency_matrix_ = NULL; }
2006
+ /// copy
2007
+ Visibility_Graph( const Visibility_Graph& vg2 );
2008
+ /** \brief construct the visibility graph of Environment vertices
2009
+ *
2010
+ * \author Karl J. Obermeyer
2011
+ *
2012
+ * \pre \a environment must be \a epsilon -valid. Test with
2013
+ * Environment::is_valid(epsilon).
2014
+ *
2015
+ * \remarks Currently this constructor simply computes the
2016
+ * Visibility_Polygon of each vertex and checks inclusion of the
2017
+ * other vertices, taking time complexity O(n^3), where n is the
2018
+ * number of vertices representing the Environment. This time
2019
+ * complexity is not optimal. As mentioned in ``Robot Motion
2020
+ * Planning" by J.C. Latombe p.157, there are algorithms able to
2021
+ * construct a visibility graph for a polygonal environment with
2022
+ * holes in time O(n^2). The nonoptimal algorithm is being used
2023
+ * temporarily because of (1) its ease to implement using the
2024
+ * Visibility_Polygon class, and (2) its apparent robustness.
2025
+ * Implementing the optimal algorithm robustly is future work.
2026
+ */
2027
+ Visibility_Graph(const Environment& environment, double epsilon=0.0);
2028
+ //Constructors
2029
+ /** \brief construct the visibility graph of Points in an Environment
2030
+ *
2031
+ * \pre \a environment must be \a epsilon -valid. Test with
2032
+ * Environment::is_valid(epsilon).
2033
+ *
2034
+ * \author Karl J. Obermeyer \remarks Currently this constructor
2035
+ * simply computes the Visibility_Polygon of each Point and checks
2036
+ * inclusion of the other Points, taking time complexity
2037
+ * O(N n log(n) + N^2 n), where N is the number of Points and n is
2038
+ * the number of vertices representing the Environment. This time
2039
+ * complexity is not optimal, but has been used for
2040
+ * simplicity. More efficient algorithms are discussed in ``Robot
2041
+ * Motion Planning" by J.C. Latombe p.157.
2042
+ */
2043
+ Visibility_Graph(const std::vector<Point> points,
2044
+ const Environment& environment, double epsilon=0.0);
2045
+ //Constructors
2046
+ /** \brief construct the visibility graph of Guards in an Environment
2047
+ *
2048
+ * \pre \a start and \a finish must be in the environment.
2049
+ * Environment must be \a epsilon -valid. Test with
2050
+ * Environment::is_valid(epsilon).
2051
+ *
2052
+ * \author Karl J. Obermeyer
2053
+ * \remarks Currently this constructor simply computes the
2054
+ * Visibility_Polygon of each guard and checks inclusion of the
2055
+ * other guards, taking time complexity O(N n log(n) + N^2 n),
2056
+ * where N is the number of guards and n is the number of vertices
2057
+ * representing the Environment. This time complexity is not
2058
+ * optimal, but has been used for simplicity. More efficient
2059
+ * algorithms are discussed in ``Robot Motion Planning" by
2060
+ * J.C. Latombe p.157.
2061
+ */
2062
+ Visibility_Graph(const Guards& guards,
2063
+ const Environment& environment, double epsilon=0.0);
2064
+ //Accessors
2065
+ /** \brief raw access to adjacency matrix data
2066
+ *
2067
+ * \author Karl J. Obermeyer
2068
+ * \param i1 Polygon index of first vertex
2069
+ * \param j1 index of first vertex within its Polygon
2070
+ * \param i2 Polygon index of second vertex
2071
+ * \param j2 index of second vertex within its Polygon
2072
+ * \return true iff first vertex is visible from second vertex
2073
+ * \remarks for efficiency, no bounds check; usually trying to
2074
+ * access out of bounds causes a bus error
2075
+ */
2076
+ bool operator () (unsigned i1,
2077
+ unsigned j1,
2078
+ unsigned i2,
2079
+ unsigned j2) const;
2080
+ /** \brief raw access to adjacency matrix data via flattened
2081
+ * indices
2082
+ *
2083
+ * By flattened index is intended the label given to a vertex if
2084
+ * you were to label all the vertices from 0 to n-1 (where n is
2085
+ * the number of vertices representing the Environment) starting
2086
+ * with the first vertex of the outer boundary and progressing in
2087
+ * order through all the remaining vertices of the outer boundary
2088
+ * and holes.
2089
+ * \author Karl J. Obermeyer
2090
+ * \param k1 flattened index of first vertex
2091
+ * \param k1 flattened index of second vertex
2092
+ * \return true iff first vertex is visible from second vertex
2093
+ * \remarks for efficiency, no bounds check; usually trying to
2094
+ * access out of bounds causes a bus error
2095
+ */
2096
+ bool operator () (unsigned k1,
2097
+ unsigned k2) const;
2098
+ /// \brief total number of vertices in corresponding Environment
2099
+ unsigned n() const { return n_; }
2100
+ //Mutators
2101
+ /** \brief raw access to adjacency matrix data
2102
+ *
2103
+ * \author Karl J. Obermeyer
2104
+ * \param i1 Polygon index of first vertex
2105
+ * \param j1 index of first vertex within its Polygon
2106
+ * \param i2 Polygon index of second vertex
2107
+ * \param j2 index of second vertex within its Polygon
2108
+ * \return true iff first vertex is visible from second vertex
2109
+ * \remarks for efficiency, no bounds check; usually trying to
2110
+ * access out of bounds causes a bus error
2111
+ */
2112
+ bool& operator () (unsigned i1,
2113
+ unsigned j1,
2114
+ unsigned i2,
2115
+ unsigned j2);
2116
+ /** \brief raw access to adjacency matrix data via flattened
2117
+ * indices
2118
+ *
2119
+ * By flattened index is intended the label given to a vertex if
2120
+ * you were to label all the vertices from 0 to n-1 (where n is
2121
+ * the number of vertices representing the Environment) starting
2122
+ * with the first vertex of the outer boundary and progressing in
2123
+ * order through all the remaining vertices of the outer boundary
2124
+ * and holes.
2125
+ * \author Karl J. Obermeyer
2126
+ * \param k1 flattened index of first vertex
2127
+ * \param k1 flattened index of second vertex
2128
+ * \return true iff first vertex is visible from second vertex
2129
+ * \remarks for efficiency, no bounds check; usually trying to
2130
+ * access out of bounds causes a bus error
2131
+ */
2132
+ bool& operator () (unsigned k1,
2133
+ unsigned k2);
2134
+ /// assignment operator
2135
+ Visibility_Graph& operator =
2136
+ (const Visibility_Graph& visibility_graph_temp);
2137
+ /// destructor
2138
+ virtual ~Visibility_Graph();
2139
+ private:
2140
+ //total number of vertices of corresponding Environment
2141
+ unsigned n_;
2142
+ //the number of vertices in each Polygon of corresponding Environment
2143
+ std::vector<unsigned> vertex_counts_;
2144
+ // n_-by-n_ adjacency matrix data stored as 2D dynamic array
2145
+ bool **adjacency_matrix_;
2146
+ //converts vertex pairs (hole #, vertex #) to flattened index
2147
+ unsigned two_to_one(unsigned i,
2148
+ unsigned j) const;
2149
+ };
2150
+
2151
+
2152
+ /// print Visibility_Graph adjacency matrix
2153
+ std::ostream& operator << (std::ostream& outs,
2154
+ const Visibility_Graph& visibility_graph);
2155
+
2156
+ }
2157
+
2158
+ #endif //VISILIBITY_H