API Documentation
Loading...
Searching...
No Matches
Polygon.hpp
Go to the documentation of this file.
1/*--------------------------------------------------------------------------------------------
2Copyright (c) 2019, NDEVR LLC
3tyler.parke@ndevr.org
4 __ __ ____ _____ __ __ _______
5 | \ | | | __ \ | ___|\ \ / / | __ \
6 | \ | | | | \ \ | |___ \ \ / / | |__) |
7 | . \| | | |__/ / | |___ \ V / | _ /
8 | |\ |_|_____/__|_____|___\_/____| | \ \
9 |__| \__________________________________| \__\
10
11Subject to the terms of the Enterprise+ Agreement, NDEVR hereby grants
12Licensee a limited, non-exclusive, non-transferable, royalty-free license
13(without the right to sublicense) to use the API solely for the purpose of
14Licensee's internal development efforts to develop applications for which
15the API was provided.
16
17The above copyright notice and this permission notice shall be included in all
18copies or substantial portions of the Software.
19
20THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
21INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
22PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE
23FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
24OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
25DEALINGS IN THE SOFTWARE.
26
27Library: Base
28File: Polygon
29Included in API: True
30Author(s): Tyler Parke
31 *-----------------------------------------------------------------------------------------**/
32#pragma once
33#include <NDEVR/BaseValues.h>
34#include <NDEVR/MatrixFunctions.h>
35#include <NDEVR/Buffer.h>
36#include <NDEVR/Vertex.h>
37#include <NDEVR/Bounds.h>
38#include <NDEVR/LineSegment.h>
39#include <NDEVR/Plane.h>
40namespace NDEVR
41{
42 /**--------------------------------------------------------------------------------------------------
43 Class: Polygon
44
45 \brief An N-sided polygon.
46
47 Author: Tyler Parke
48
49 Date: 2017-11-19
50 **/
51 template<class t_type, class t_vertex = Vertex<2, t_type>>
52 class Polygon
53 {
54 public:
56 : m_vertices()
57 , m_cache_bounds(Constant<Bounds<2, t_type, t_vertex>>::Invalid)
58 , m_cache_length(Constant<t_type>::Invalid)
59 , m_is_inside_cached(false)
60 , m_is_convex_cached(false)
61 , m_is_convex(false)
62 , m_polygon_plane(Vector<3, t_type>(0, 0, 1), 0)
63 {}
64 Polygon(const Polygon& polygon)
65 : m_vertices(polygon.m_vertices)
66 , m_cache_bounds(polygon.m_cache_bounds)
67 , m_cache_length(polygon.m_cache_length)
68 , m_cache_constant(polygon.m_cache_constant)
69 , m_cache_multiple(polygon.m_cache_multiple)
70 , m_is_inside_cached(polygon.m_is_inside_cached)
71 , m_is_convex_cached(polygon.m_is_convex_cached)
72 , m_is_convex(polygon.m_is_convex)
73 , m_polygon_plane(polygon.m_polygon_plane)
74 {}
75 Polygon(Polygon&& polygon) noexcept
76 : m_cache_bounds(polygon.m_cache_bounds)
77 , m_cache_length(polygon.m_cache_length)
78 , m_is_inside_cached(polygon.m_is_inside_cached)
79 , m_is_convex_cached(polygon.m_is_convex_cached)
80 , m_is_convex(polygon.m_is_convex)
81 , m_polygon_plane(polygon.m_polygon_plane)
82 {
83 std::swap(m_vertices, polygon.m_vertices);
84 std::swap(m_cache_multiple, polygon.m_cache_multiple);
85 std::swap(m_cache_constant, polygon.m_cache_constant);
86 }
88 : m_vertices(vertices)
89 , m_cache_bounds(Constant<Bounds<2, t_type, t_vertex>>::Invalid)
90 , m_cache_length(Constant<t_type>::Invalid)
91 , m_is_inside_cached(false)
92 , m_is_convex_cached(false)
93 , m_is_convex(false)
94 , m_polygon_plane(Vector<3, t_type>(0, 0, 1), 0)
95 {}
96 explicit Polygon(const Buffer<Vertex<3, fltp08>>& points)
97 : m_cache_bounds(Constant<Bounds<2, t_type, t_vertex>>::Invalid)
98 , m_cache_length(Constant<t_type>::Invalid)
99 , m_is_inside_cached(false)
100 , m_is_convex_cached(false)
101 , m_is_convex(false)
102 , m_polygon_plane(Plane<3, fltp08>::CreateBestFitPlane(points))
103 {
104 Matrix<fltp08> plane_transform = m_polygon_plane.projectionMatrix();
105 for (uint04 n = 0; n < points.size(); n++)
106 {
107 add(t_vertex(plane_transform * points[n]).template as<2, t_type>());
108 }
109 }
110 explicit Polygon(uint04 allocated_size)
111 : m_vertices(allocated_size)
112 , m_cache_bounds(Constant<Bounds<2, t_type, t_vertex>>::Invalid)
113 , m_cache_length(Constant<t_type>::Invalid)
114 , m_is_inside_cached(false)
115 , m_is_convex_cached(false)
116 , m_is_convex(false)
117 , m_polygon_plane(Vector<3, t_type>(0, 0, 1), 0)
118 {}
119
120 /**--------------------------------------------------------------------------------------------------
121 Gets the bounds.
122
123 Author: Tyler Parke
124
125 Date: 2017-11-19
126
127 \returns A Bounds&lt;2,t_type&gt;
128 **/
130 {
131 if (IsInvalid(m_cache_bounds))
132 {
133 m_cache_bounds = Constant<Bounds<2, t_type, t_vertex>>::Min;
134 for (uint04 i = 0; i < m_vertices.size(); i++)
135 {
136 m_cache_bounds.addToBounds(m_vertices[i]);
137 }
138 }
139 return m_cache_bounds;
140 }
141
142
143 /**--------------------------------------------------------------------------------------------------
144 Vertices the given index.
145
146 Author: Tyler Parke
147
148 Date: 2017-11-19
149
150 Parameters:
151 index - Zero-based index of the.
152
153 \returns A reference to a const t_vertex.
154 **/
155
156 const t_vertex& vertex(uint04 index) const
157 {
158 return m_vertices[index];
159 }
160
161 /**--------------------------------------------------------------------------------------------------
162 Edges the given index.
163
164 Author: Tyler Parke
165
166 Date: 2017-11-19
167
168 Parameters:
169 index - Zero-based index of the.
170
171 \returns A LineSegment&lt;2,t_type,t_vertex&gt;
172 **/
173
175 {
176 return LineSegment<2, t_type, t_vertex>(vertex(index), vertex((index + 1) % m_vertices.size()));
177 }
178
179 /**--------------------------------------------------------------------------------------------------
180 Gets the vertices.
181
182 Author: Tyler Parke
183
184 Date: 2017-11-19
185
186 \returns A reference to a const Buffer&lt;t_vertex&gt;
187 **/
188
189 inline const Buffer<t_vertex>& vertices() const
190 {
191 return m_vertices;
192 }
193
194 /**--------------------------------------------------------------------------------------------------
195 Vertex count.
196
197 Author: Tyler Parke
198
199 Date: 2017-11-19
200
201 \returns An uint04.
202 **/
203
204 inline uint04 vertexCount() const
205 {
206 return m_vertices.size();
207 }
208
209 /**--------------------------------------------------------------------------------------------------
210 Edge count.
211
212 Author: Tyler Parke
213
214 Date: 2017-11-19
215
216 \returns An uint04.
217 **/
218
219 inline uint04 edgeCount() const
220 {
221 return m_vertices.size();
222 }
223 bool isConvex() const
224 {
225 if (!m_is_convex_cached)
226 {
227 if (edgeCount() < 3)
228 {
229 m_is_convex = false;
230 }
231 else if (edgeCount() == 3)
232 {
233 m_is_convex = true;
234 }
235 else
236 {
237 m_is_convex = true;
238 t_type last_cross_prod = 0;
239 const uint04 vert_count = vertexCount();
240 for (uint04 i = 0; i < vert_count; i++)
241 {
242 const Vector<2, t_type> d1 = vertex((i + 1) % vert_count) - vertex((i + 0) % vert_count);
243 const Vector<2, t_type> d2 = vertex((i + 2) % vert_count) - vertex((i + 1) % vert_count);
244 const t_type cross_prod = d1[X] * d2[Y] - d1[Y] * d2[X];
245 if (cross_prod != cast<t_type>(0))
246 {
247 if ((last_cross_prod > cast<t_type>(0) && cross_prod < cast<t_type>(0))
248 || (last_cross_prod < cast<t_type>(0) && cross_prod > cast<t_type>(0)))
249 {
250 m_is_convex = false;
251 break;
252 }
253 last_cross_prod = cross_prod;
254 }
255 }
256 }
257 m_is_convex_cached = true;
258 }
259 return m_is_convex;
260 }
261 /**--------------------------------------------------------------------------------------------------
262 Sets the vertices.
263
264 Author: Tyler Parke
265
266 Date: 2017-11-19
267
268 Parameters:
269 vertices - The vertices.
270 **/
271
273 {
274 updateVertices(vertices);
275 }
276 inline void addVertices(const t_vertex* vertices, uint04 size)
277 {
278 m_vertices.addAll(vertices, size);
279 invalidateCache();
280 }
281
282 /**--------------------------------------------------------------------------------------------------
283 Adds vertex.
284
285 Author: Tyler Parke
286
287 Date: 2017-11-19
288
289 Parameters:
290 vertex - The vertex to add.
291 **/
292
293 void add(const t_vertex& vertex)
294 {
295 m_vertices.add(vertex);
296 invalidateCache();
297 }
298
299 /**--------------------------------------------------------------------------------------------------
300 Inserts.
301
302 Author: Tyler Parke
303
304 Date: 2017-11-19
305
306 Parameters:
307 index - Zero-based index of the.
308 vertex - The vertex.
309 **/
310
311 void insert(uint04 index, const t_vertex& vertex)
312 {
313 m_vertices.insert(index, vertex);
314 invalidateCache();
315 }
316
317 /**--------------------------------------------------------------------------------------------------
318 Replaces.
319
320 Author: Tyler Parke
321
322 Date: 2017-11-19
323
324 Parameters:
325 index - Zero-based index of the.
326 vector - The vector.
327 **/
328
329 void replace(uint04 index, const t_vertex& vector)
330 {
331 if (m_vertices[index] != vector)
332 {
333 m_vertices[index] = vector;
334 invalidateCache();
335 }
336 }
337
338 /**--------------------------------------------------------------------------------------------------
339 Removes all duplicate adjacent vertices.
340
341 Author: Tyler Parke
342
343 Date: 2017-05-16
344
345 Parameters:
346 index - The index to removeRows.
347 **/
348 void simplify()
349 {
350 if (vertexCount() <= 1)
351 return;
352 for (uint04 i = 0; i < vertexCount() - 1; i++)
353 {
354 if (vertex(i).template as<2, t_type>() == vertex(i + 1).template as<2, t_type>())
355 {
356 remove(i + 1);
357 i--;
358 }
359 else if (i > 0 && edge(i).template isParallel<t_type>(edge(i - 1), cast<t_type>(0.00001)))
360 {
361 remove(i);
362 i--;
363 }
364 }
365 while (vertexCount() > 0 && vertex(vertexCount() - 1).template as<2, t_type>() == vertex(0).template as<2, t_type>())
366 {
367 remove(vertexCount() - 1);
368 }
369 while (vertexCount() > 2 && edge(edgeCount() - 1).template isParallel<t_type>(edge(0), cast<t_type>(0.00001)))
370 {
371 remove(0);
372 }
373 }
374 void flip()
375 {
376 uint04 iMax = vertexCount() / 2;
377
378 if (vertexCount() % 2 != 0)
379 iMax += 1;
380
381 for (uint04 i = 1; i < iMax; ++i)
382 std::swap(m_vertices[i], m_vertices[vertexCount() - i]);
383 invalidateCache();
384 }
385 /**--------------------------------------------------------------------------------------------------
386 Removes the given index.
387
388 Author: Tyler Parke
389
390 Date: 2017-11-19
391
392 Parameters:
393 index - The index to removeRows.
394 **/
395
396 void remove(uint04 index)
397 {
398 m_vertices.removeIndex(index);
399 invalidateCache();
400 }
401
402 /**--------------------------------------------------------------------------------------------------
403 Clears this object to its blank/initial state.
404
405 Author: Tyler Parke
406
407 Date: 2017-11-19
408 **/
409
410 void clear()
411 {
412 m_vertices.clear();
413 invalidateCache();
414 }
415
416 /**--------------------------------------------------------------------------------------------------
417 Gets as.
418
419 Author: Tyler Parke
420
421 Date: 2017-11-19
422
423 \returns A Polygon&lt;t_new_type,t_new_vertex_type&gt;
424 **/
425 template<class t_new_type, class t_new_vertex_type = Vertex<2, t_new_type>>
427 {
429 for(uint04 i = 0; i < vertexCount(); i++)
430 {
431 poly.add(t_new_vertex_type(vertex(i).template as<2, t_new_type>()));
432 }
433 return poly;
434 }
435
436 /**--------------------------------------------------------------------------------------------------
437 Gets the perimeter.
438
439 Author: Tyler Parke
440
441 Date: 2017-11-19
442
443 \returns A t_type.
444 **/
445
446 t_type perimeter() const
447 {
448 if(IsInvalid(m_cache_length))
449 {
450 if(vertexCount() > 0)
451 {
452 m_cache_length = cast<t_type>(0);
453 }
454 if (vertexCount() > 1)
455 {
456 for (uint04 i = 0; i < edgeCount(); i++)
457 {
458 m_cache_length += edge(i).template length<t_type>();
459 }
460 }
461 }
462 return m_cache_length;
463 }
464
465 /**--------------------------------------------------------------------------------------------------
466 Query if this object contains the given vector.
467
468 Author: Tyler Parke
469
470 Date: 2017-11-19
471
472 Parameters:
473 vector - The const t_vertex&amp; to test for containment.
474
475 \returns True if the object is in this collection, false if not.
476 **/
477
478 bool contains(const Vertex<2, t_type>& vector) const
479 {
480 if (!bounds().template as<2, t_type>().contains(vector))
481 return false;
482 cacheBoundaryCheck();
483 uint04 last = vertexCount() - 1;
484 bool odd_vertices = false;
485 for (uint04 current = 0; current < vertexCount(); ++current)
486 {
487 if ((m_vertices[current][Y] < vector[Y] && m_vertices[last][Y] >= vector[Y])
488 || (m_vertices[last][Y] < vector[Y] && m_vertices[current][Y] >= vector[Y]))
489 {
490 odd_vertices ^= ((vector[Y] * m_cache_multiple[current] + m_cache_constant[current]) < vector[X]);
491 }
492 last = current;
493 }
494 return odd_vertices;
495 }
496
497 template<class t_precision>
499 {
500 if (m_vertices.size() <= 2)
501 return outside;
502 if (!bounds().intersects(line))
503 return outside;
504 bool is_inside = contains(line.vertex(A));
505 if (contains(line.vertex(B)) != is_inside)
506 return mixed;
507
508 for (uint04 i = 0; i < edgeCount(); i++)
509 {
510 LineSegment<2, t_type, t_vertex> current_edge = edge(i);
511 if (current_edge.template intersects<t_precision>(line))
512 return mixed;
513 }
514 return is_inside ? inside : outside;
515 }
516
517 /**--------------------------------------------------------------------------------------------------
518 Determines if this collection contains a given object.
519
520 Author: Tyler Parke
521
522 Date: 2017-11-19
523
524 Parameters:
525 bounds - The const Bounds&lt;2,t_type,t_vertex&gt;&amp; to test for containment.
526
527 \returns The IntersectionTypes.
528 **/
529 template<class t_precision>
531 {
532 if(vertexCount() <= 2)
533 return outside;
534 if (!bounds().intersects(o_bounds))
535 return outside;
536 const t_vertex v1(o_bounds[MIN][X], o_bounds[MIN][Y]);
537 const t_vertex v2(o_bounds[MAX][X], o_bounds[MIN][Y]);
538 const t_vertex v3(o_bounds[MAX][X], o_bounds[MAX][Y]);
539 const t_vertex v4(o_bounds[MIN][X], o_bounds[MAX][Y]);
540
541 const bool is_inside = contains(v1);
542 if(contains(v2) != is_inside) return mixed;
543 if(contains(v3) != is_inside) return mixed;
544 if(contains(v4) != is_inside) return mixed;
545 // If all of the bounding points are outside, we need only prove that a single polygon vertex is
546 // inside (Which is cheap)
547 if(!is_inside) for (uint04 i = 0; i < edgeCount(); i++)
548 {
549 if (o_bounds.contains(vertex(i)))
550 return mixed;
551 }
552 for(uint04 i = 0; i < edgeCount(); i++)
553 {
554 const LineSegment<2, t_type, t_vertex> current_edge = edge(i);
555 if(current_edge.template intersects<t_precision>(LineSegment<2, t_type>(v1, v2))) return mixed;
556 if(current_edge.template intersects<t_precision>(LineSegment<2, t_type>(v2, v3))) return mixed;
557 if(current_edge.template intersects<t_precision>(LineSegment<2, t_type>(v3, v4))) return mixed;
558 if(current_edge.template intersects<t_precision>(LineSegment<2, t_type>(v4, v1))) return mixed;
559 }
560 return is_inside ? inside : outside;
561 }
562
563 decltype(auto) begin()
564 {
565 return m_vertices.begin();
566 }
567 decltype(auto) begin() const
568 {
569 return m_vertices.begin();
570 }
571
572 decltype(auto) begin(uint04 index) const
573 {
574 return m_vertices.begin(index);
575 }
576 decltype(auto) begin(uint04 index)
577 {
578 return m_vertices.begin(index);
579 }
580
581 decltype(auto) end()
582 {
583 return m_vertices.end();
584 }
585 decltype(auto) end() const
586 {
587 return m_vertices.end();
588 }
589
590
591 /**--------------------------------------------------------------------------------------------------
592 Determines if this collection contains a given object.
593
594 Author: Tyler Parke
595
596 Date: 2017-11-19
597
598 Parameters:
599 tri - The const Triangle&lt;2,t_type,t_vertex&gt;&amp; to test for containment.
600
601 \returns The IntersectionTypes.
602 **/
603 template<class t_precision>
605 {
606 //Check each vertex, if some are inside, or some are outside, we know we are mixed
607 if(m_vertices.size() <= 2)
608 return outside;
609 //if (!bounds().intersects(tri))
610 //return outside;
611 bool is_inside = contains(tri.vertex(A));
612 if(contains(tri.vertex(B)) != is_inside) return mixed;
613 if(contains(tri.vertex(C)) != is_inside) return mixed;
614
615 // If all of the triangles points are outside, we need only prove that a single polygon vertex is
616 // inside (Which is cheap)
617 if (!is_inside) for (uint04 i = 0; i < edgeCount(); i++)
618 {
619 if (tri.contains(vertex(i)))
620 return mixed;
621 }
622 for (uint04 i = 0; i < edgeCount(); i++)
623 {
624 const LineSegment<2, t_type, t_vertex> current_edge = edge(i);
625 if(current_edge.template intersects<t_precision>(tri.edge(A, B))) return mixed;
626 if(current_edge.template intersects<t_precision>(tri.edge(B, C))) return mixed;
627 if(current_edge.template intersects<t_precision>(tri.edge(C, A))) return mixed;
628 }
629 return is_inside ? inside : outside;
630 }
631
632 template<class t_precision, class t_other_vertex>
634 {
635 if (m_vertices.size() <= 2 || poly.edgeCount() == 0)
636 return outside;
637 if (!bounds().intersects(poly.bounds()))
638 return outside;
639
641 if (type == mixed || (type == outside && poly.contains(vertex(0))))
642 return mixed;
643 for (uint04 i = 1; i < poly.edgeCount(); i++)
644 {
645 if (type != contains<t_precision>(poly.edge(i)))
646 return mixed;
647 }
648
649 return type;
650 }
651
652 Polygon clip(const Bounds<t_vertex::NumberOfDimensions(), t_type>& bounds) const
653 {
654 if (bounds.template as<2, t_type>().template contains<true>(this->bounds().template as<2, t_type>()))
655 return *this;
656 if (!bounds.template as<2, t_type>().intersects(this->bounds()))
657 return Polygon();
658 Polygon polygon(vertexCount());
659 for (uint04 ii = 0; ii < vertexCount() - 1; ++ii)
660 {
661 LineSegment<t_vertex::NumberOfDimensions(), t_type> line(vertex(ii), vertex(ii + 1));
662 line = intersection(bounds, line);
663 if (!IsInvalid(line))
664 {
665 if (polygon.vertexCount() == 0 || polygon.vertex(polygon.vertexCount() - 1) != polygon.vertex(A))
666 polygon.add(line.vertex(A));
667 polygon.add(line.vertex(B));
668 }
669 }
670 LineSegment<t_vertex::NumberOfDimensions(), t_type> line(vertex(vertexCount() - 1), vertex(0));
671 if (!IsInvalid(line))
672 {
673 line = intersection(bounds, line);
674 if (!IsInvalid(line))
675 {
676 if (polygon.vertexCount() == 0 || polygon.vertex(polygon.vertexCount() - 1) != polygon.vertex(A))
677 polygon.add(line.vertex(A));
678 polygon.add(line.vertex(B));
679 }
680 }
681
682 polygon.simplify();
683 return polygon;
684 }
685
687 {
688 return m_polygon_plane;
689 }
691 {
692 m_polygon_plane = plane;
693 }
695 {
696 t_type sum = 0;
697 for (uint04 i = 0; i < edgeCount(); i++)
698 {
699 auto side = edge(i);
700 sum += (side[B][X] - side[A][X]) * (side[B][Y] + side[A][Y]);
701 }
702 return sum > 0.0;//this is also half surface area
703 }
704 /**--------------------------------------------------------------------------------------------------
705 Equality operator.
706
707 Author: Tyler Parke
708
709 Date: 2017-11-19
710
711 Parameters:
712 polygon - The polygon.
713
714 \returns True if the parameters are considered equivalent.
715 **/
716
717 bool operator==(const Polygon& polygon) const
718 {
719 return m_vertices == polygon.m_vertices && m_polygon_plane == polygon.m_polygon_plane;
720 }
721 bool operator!=(const Polygon& polygon) const
722 {
723 return m_vertices != polygon.m_vertices || m_polygon_plane != polygon.m_polygon_plane;
724 }
725 bool isEquivalent(const Polygon& polygon, fltp08 epsilon)
726 {
727 if (bounds().template as<2, fltp08>() != polygon.bounds().template as<2, fltp08>())
728 return false;
729 if (abs(perimeter() - polygon.perimeter()) > epsilon)
730 return false;
731 for (uint04 i = 0; i < polygon.edgeCount(); i++)
732 {
733 bool found = false;
734 for (uint04 n = 0; n < edgeCount(); n++)
735 {
736 if (edge(n).template as<2, fltp08>().template isCollinear<fltp08>(polygon.edge(i).template as<2, fltp08>(), epsilon))
737 {
738 found = true;
739 break;
740 }
741 }
742 if (!found)
743 return false;
744 }
745 return true;
746 }
747 Polygon opheimSimplification(t_type min_tol, t_type max_tol) const
748 {
749
750 uint04 count = vertexCount();
751 t_type min_tol2 = min_tol * min_tol; // squared minimum distance tolerance
752 t_type max_tol2 = max_tol * max_tol; // squared maximum distance tolerance
753
754 // validate input and check if simplification required
755 if (count < 3 || min_tol2 == 0 || max_tol2 == 0)
756 return *this;
757 // define the ray R(r0, r1)
758 uint04 r0 = 0; // indicates the current key and start of the ray
759 uint04 r1 = 0; // indicates a point on the ray
760 bool rayDefined = false;
761
762 // keep track of two test points
763 uint04 pi = r0; // the previous test point
764 uint04 pj = pi;
765
766 Polygon poly;
767 poly.add(vertex(r0));
768 for (uint04 j = 1; j < count; ++j)
769 {
770 pi = pj++;
771
772 t_type dist_squared = distanceSquared(vertex(r0), vertex(pj));
773 if (!rayDefined) {
774 // discard each point within minimum tolerance
775 if (dist_squared < min_tol2)
776 continue;
777 // the last point within minimum tolerance pi defines the ray R(r0, r1)
778 r1 = pi;
779 rayDefined = true;
780 }
781
782 // check each point pj against R(r0, r1)
783 if (dist_squared < max_tol2)
784 {
785 t_vertex v = vertex(r1) - vertex(r0); // vector r1 --> r2
786 t_vertex w = vertex(pj) - vertex(r0); // vector r1 --> p
787
788 t_type cv = dot(v, v); // squared length of v
789 t_type cw = dot(w, v); // project w onto v
790
791 if (cw <= 0)
792 {
793 // projection of w lies to the left of r1 (not on the ray)
794 if (distanceSquared(vertex(pj), vertex(r0)) < min_tol2)
795 continue;
796 }
797 else
798 {
799 // avoid problems with divisions when value_type is an integer type
800 t_type fraction = cv == 0 ? 0 : cw /cv;
801
802
803 t_vertex proj = vertex(r0) + (fraction * (vertex(r1) - vertex(r0)));
804
805 if (distanceSquared(vertex(pj), proj) < min_tol2)
806 continue;
807 }
808 }
809 poly.add(vertex(pi));
810 r0 = pi;
811 rayDefined = false;
812 }
813 return poly;
814 }
816 {
817 m_vertices = poly.m_vertices;
818 m_cache_bounds = poly.m_cache_bounds;
819 m_cache_length = poly.m_cache_length;
820 m_cache_constant = poly.m_cache_constant;
821 m_cache_multiple = poly.m_cache_multiple;
822 m_is_inside_cached = poly.m_is_inside_cached;
823 return *this;
824 }
826 {
827 std::swap(m_vertices, poly.m_vertices);
828 m_cache_bounds = poly.m_cache_bounds;
829 m_cache_length = poly.m_cache_length;
830 m_cache_constant = poly.m_cache_constant;
831 m_cache_multiple = poly.m_cache_multiple;
832 m_is_inside_cached = poly.m_is_inside_cached;
833 return *this;
834 }
835 bool validate() const
836 {
837 for (uint04 i = 0; i < edgeCount(); i++)
838 {
839 auto seg_to_check = edge(i);
840 for (uint04 n = i + 2; n < edgeCount(); n++)
841 {
842 if (n == i || (n == edgeCount() - 1 && i == 0))
843 continue;
844 auto seg = edge(n);
845 if (!IsInvalid(seg_to_check.template intersection<fltp08>(seg, 0.000000001)))
846 {
847 lib_assert(false, "Bad polygon");
848 return false;
849 }
850 }
851 }
852 return true;
853 }
854 private:
855
856 /**--------------------------------------------------------------------------------------------------
857 Invalidate cache.
858
859 Author: Tyler Parke
860
861 Date: 2017-11-19
862 **/
863
864 inline void invalidateCache() const
865 {
866 m_cache_length = Constant<t_type>::Invalid;
867 m_is_inside_cached = false;
868 m_is_convex_cached = false;
869 m_cache_constant.clear();
870 m_cache_multiple.clear();
872 }
873
874 /**--------------------------------------------------------------------------------------------------
875 Updates the vertices described by the given vertices.
876
877 Author: Tyler Parke
878
879 Date: 2017-11-19
880
881 Parameters:
882 vertices - The vertices.
883 **/
884
885 void updateVertices(const Buffer<t_vertex>& vertices)
886 {
887 m_vertices = vertices;
888 invalidateCache();
889 }
890
891 /**--------------------------------------------------------------------------------------------------
892 Cache boundary check.
893
894 Author: Tyler Parke
895
896 Date: 2017-11-19
897 **/
898
899 void cacheBoundaryCheck() const
900 {
901 if(m_is_inside_cached)
902 return;
903 m_cache_constant.setSize(m_vertices.size());
904 m_cache_multiple.setSize(m_vertices.size());
905 uint04 jj = m_vertices.size() - 1;
906 for(uint04 ii = 0; ii < m_vertices.size(); ++ii)
907 {
908 if(m_vertices[jj][Y] == m_vertices[ii][Y])
909 {
910 m_cache_constant[ii] = cast<fltp08>(m_vertices[ii][X]);
911 m_cache_multiple[ii] = 0;
912 }
913 else
914 {
915 m_cache_constant[ii] = m_vertices[ii][X]
916 - cast<fltp08>(m_vertices[ii][Y] * m_vertices[jj][X])
917 / cast<fltp08>(m_vertices[jj][Y] - m_vertices[ii][Y])
918 + cast<fltp08>(m_vertices[ii][Y] * m_vertices[ii][X])
919 / cast<fltp08>(m_vertices[jj][Y] - m_vertices[ii][Y]);
920 m_cache_multiple[ii] = cast<fltp08>(m_vertices[jj][X] - m_vertices[ii][X])
921 / cast<fltp08>(m_vertices[jj][Y] - m_vertices[ii][Y]);
922 }
923 jj = ii;
924 }
925 m_is_inside_cached = true;
926 }
927
928 private:
929 /** The vertices. */
930 Buffer<t_vertex> m_vertices;
931
932 /**--------------------------------------------------------------------------------------------------
933 Property: mutable Bounds<2, t_type> m_cache_bounds
934
935 Gets the cache bounds.
936
937 \returns The m cache bounds.
938 **/
939
940 mutable Bounds<2, t_type, t_vertex> m_cache_bounds;
941
942 /**--------------------------------------------------------------------------------------------------
943 Property: mutable t_type m_cache_length
944
945 Gets the length of the cache.
946
947 \returns The length of the cache.
948 **/
949
950 mutable t_type m_cache_length;
951
952 /**--------------------------------------------------------------------------------------------------
953 Property: mutable Buffer<fltp08> m_cache_constant
954
955 Gets the cache constant.
956
957 \returns The m cache constant.
958 **/
959
960 mutable Buffer<fltp08> m_cache_constant;
961
962 /**--------------------------------------------------------------------------------------------------
963 Property: mutable Buffer<fltp08> m_cache_multiple
964
965 Gets the cache multiple.
966
967 \returns The m cache multiple.
968 **/
969
970 mutable Buffer<fltp08> m_cache_multiple;
971
972 /**--------------------------------------------------------------------------------------------------
973 Property: mutable bool m_is_inside_cached
974
975 Gets a value indicating whether this object is inside cached.
976
977 \returns True if this object m is inside cached, false if not.
978 **/
979
980 mutable bool m_is_inside_cached;
981 mutable bool m_is_convex_cached;
982 mutable bool m_is_convex;
983 Plane<3, t_type> m_polygon_plane;
984 };
985
986 template<class t_type, class t_vertex, uint01 t_row_dims, uint01 t_col_dims>
988 {
990 for (uint04 i = 0; i < poly.vertexCount(); i++)
991 {
992 polygon.add(matrix * poly.vertex(i));
993 }
994 return polygon;
995 }
996
997 template<class t_type, class t_vertex>
998 static bool IsInvalid(const Polygon<t_type, t_vertex>& poly)
999 {
1000 Polygon<t_type, t_vertex> polygon(poly.vertexCount());
1001 for (uint04 i = 0; i < poly.vertexCount(); i++)
1002 {
1003 if(IsInvalid(poly.vertex(i)))
1004 return true;
1005 }
1006 return false;
1007 }
1008
1009}
#define lib_assert(expression, message)
Definition LibAssert.h:61
A specification of upper and lower bounds in N-dimensions.
Definition Bounds.hpp:52
constexpr bool contains(const t_type &value) const
Query if this object contains the given value. t_allow_bounds - whether or not to allow boundary case...
Definition Bounds.hpp:237
The equivelent of std::vector but with a bit more control. The basic array unit of the library.
Definition Buffer.hpp:56
void add(t_type &&object)
Adds object to the end of the buffer.
Definition Buffer.hpp:186
constexpr t_index_type size() const
Definition Buffer.hpp:823
void addAll(const Buffer< t_type, t_other_index_type, t_other_memory_allocator, t_other_memory_manager > &buffer)
Definition Buffer.hpp:243
decltype(auto) end()
Definition Buffer.hpp:507
void setSize(t_index_type new_size)
Definition Buffer.hpp:803
void insert(t_index_type location, const t_type &object)
Adds an object to a specific location.
Definition Buffer.hpp:227
void removeIndex(t_index_type location)
Definition Buffer.hpp:606
decltype(auto) begin()
Definition Buffer.hpp:402
void clear()
Definition Buffer.hpp:422
A line segment represented by two vertices, a start and end.
Definition Line.hpp:49
constexpr const t_vertex & vertex(uint01 index) const
Definition Line.hpp:152
Definition Matrix.hpp:176
Logic for a given plane or N-dimensions. Planes are coordinate systems of one less dimension than the...
Definition Geometry.h:41
Matrix< t_type > projectionMatrix(const Vector< 3, t_type > &up) const
Definition Plane.hpp:141
An N-sided polygon.
Definition Polygon.hpp:53
Polygon & operator=(Polygon &&poly)
Definition Polygon.hpp:825
LineSegment< 2, t_type, t_vertex > edge(uint04 index) const
Definition Polygon.hpp:174
IntersectionTypes contains(const Triangle< 2, t_type, t_vertex > &tri) const
Definition Polygon.hpp:604
void simplify()
Definition Polygon.hpp:348
Polygon< t_new_type, t_new_vertex_type > as() const
Definition Polygon.hpp:426
void flip()
Definition Polygon.hpp:374
Polygon opheimSimplification(t_type min_tol, t_type max_tol) const
Definition Polygon.hpp:747
Plane< 3, t_type > plane() const
Definition Polygon.hpp:686
Polygon clip(const Bounds< t_vertex::NumberOfDimensions(), t_type > &bounds) const
Definition Polygon.hpp:652
void replace(uint04 index, const t_vertex &vector)
Definition Polygon.hpp:329
bool validate() const
Definition Polygon.hpp:835
void addVertices(const t_vertex *vertices, uint04 size)
Definition Polygon.hpp:276
bool contains(const Vertex< 2, t_type > &vector) const
Definition Polygon.hpp:478
decltype(auto) begin(uint04 index)
Definition Polygon.hpp:576
uint04 vertexCount() const
Definition Polygon.hpp:204
Polygon(const Buffer< Vertex< 3, fltp08 > > &points)
Definition Polygon.hpp:96
void insert(uint04 index, const t_vertex &vertex)
Definition Polygon.hpp:311
t_type perimeter() const
Definition Polygon.hpp:446
Polygon(const Polygon &polygon)
Definition Polygon.hpp:64
IntersectionTypes contains(const Bounds< 2, t_type, t_vertex > &o_bounds) const
Definition Polygon.hpp:530
bool hasClockwiseWinding() const
Definition Polygon.hpp:694
bool isEquivalent(const Polygon &polygon, fltp08 epsilon)
Definition Polygon.hpp:725
void setVertices(const Buffer< t_vertex > &vertices)
Definition Polygon.hpp:272
void remove(uint04 index)
Definition Polygon.hpp:396
decltype(auto) end()
Definition Polygon.hpp:581
Polygon & operator=(const Polygon &poly)
Definition Polygon.hpp:815
bool operator==(const Polygon &polygon) const
Definition Polygon.hpp:717
IntersectionTypes contains(const LineSegment< 2, t_type, t_vertex > &line) const
Definition Polygon.hpp:498
Bounds< 2, t_type, t_vertex > bounds() const
Definition Polygon.hpp:129
decltype(auto) begin()
Definition Polygon.hpp:563
void setPlane(const Plane< 3, t_type > &plane)
Definition Polygon.hpp:690
decltype(auto) begin(uint04 index) const
Definition Polygon.hpp:572
void add(const t_vertex &vertex)
Definition Polygon.hpp:293
bool isConvex() const
Definition Polygon.hpp:223
Polygon(uint04 allocated_size)
Definition Polygon.hpp:110
void clear()
Definition Polygon.hpp:410
decltype(auto) begin() const
Definition Polygon.hpp:567
const t_vertex & vertex(uint04 index) const
Definition Polygon.hpp:156
Polygon(Polygon &&polygon) noexcept
Definition Polygon.hpp:75
Polygon()
Definition Polygon.hpp:55
const Buffer< t_vertex > & vertices() const
Definition Polygon.hpp:189
Polygon(Buffer< t_vertex > &vertices)
Definition Polygon.hpp:87
uint04 edgeCount() const
Definition Polygon.hpp:219
decltype(auto) end() const
Definition Polygon.hpp:585
IntersectionTypes contains(const Polygon< t_type, t_other_vertex > &poly) const
Definition Polygon.hpp:633
bool operator!=(const Polygon &polygon) const
Definition Polygon.hpp:721
A triangle is a polygon with three edges and three vertices. It is one of the basic shapes in geometr...
Definition Triangle.hpp:138
constexpr bool contains(const Vector< t_dims - 1, t_type > &p) const
Definition Triangle.hpp:443
constexpr t_vertex & vertex(TriangleLocation triangle_node)
Vertices the given triangle node.
Definition Triangle.hpp:168
constexpr LineSegment< t_dims, t_type, t_vertex > edge(uint01 triangle_node_a, uint01 triangle_node_b) const
Definition Triangle.hpp:256
A fixed-size array with better performance compared to dynamic containers.
Definition Vector.hpp:60
A vertex or point. A specific type of Vector used primarily for spacial location information.
Definition Vertex.hpp:48
Definition ACIColor.h:37
constexpr bool IsInvalid(const t_type &value)
Query if 'value' is valid or invalid. Invalid values should return invalid if used for calculations o...
Definition BaseFunctions.hpp:170
constexpr std::enable_if< IsVecType< t_vector_type, Angle< fltp08 > >::value, t_vector_type >::type operator*(const t_vector_type &angle, const t_type &mult)
Multiplication operator for a Vector of Angles.
Definition AngleFunctions.h:326
t_type dot(const Vector< t_dims, t_type > &v1, const Vector< t_dims, t_type > &v2)
Definition VectorFunctions.hpp:1030
@ MIN
Definition BaseValues.hpp:196
@ MAX
Definition BaseValues.hpp:197
t_type distanceSquared(const Bounds< t_dims, t_type, t_vertex > &bounds, const Vector< t_dims, t_type > &vertex)
Definition Distance.hpp:46
IntersectionTypes
Used for classifying shape intersections.
Definition BaseValues.hpp:210
@ inside
Definition BaseValues.hpp:212
@ mixed
Definition BaseValues.hpp:213
@ outside
Definition BaseValues.hpp:211
uint32_t uint04
-Defines an alias representing a 4 byte, unsigned integer -Can represent exact integer values 0 throu...
Definition BaseValues.hpp:96
constexpr t_to cast(const Angle< t_from > &value)
Definition Angle.h:375
constexpr Angle< t_angle_type > abs(const Angle< t_angle_type > &value)
Changes an input with a negative sign, to a positive sign.
Definition AngleFunctions.h:645
@ B
Definition BaseValues.hpp:170
@ A
Definition BaseValues.hpp:168
@ Y
Definition BaseValues.hpp:169
@ X
Definition BaseValues.hpp:167
@ C
Definition BaseValues.hpp:172
double fltp08
Defines an alias representing an 8 byte floating-point number.
Definition BaseValues.hpp:149
Defines for a given type (such as sint04, fltp08, UUID, etc) a maximum, minimum, and reserved 'invali...
Definition BaseValues.hpp:233