KiCad PCB EDA Suite
Loading...
Searching...
No Matches
shape_poly_set.h
Go to the documentation of this file.
1/*
2 * This program source code file is part of KiCad, a free EDA CAD application.
3 *
4 * Copyright (C) 2015-2019 CERN
5 * Copyright The KiCad Developers, see AUTHORS.txt for contributors.
6 *
7 * @author Tomasz Wlostowski <[email protected]>
8 * @author Alejandro García Montoro <[email protected]>
9 *
10 * This program is free software; you can redistribute it and/or
11 * modify it under the terms of the GNU General Public License
12 * as published by the Free Software Foundation; either version 2
13 * of the License, or (at your option) any later version.
14 *
15 * This program is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 * GNU General Public License for more details.
19 *
20 * You should have received a copy of the GNU General Public License
21 * along with this program. If not, see <https://www.gnu.org/licenses/>.
22 */
23
24#ifndef __SHAPE_POLY_SET_H
25#define __SHAPE_POLY_SET_H
26
27#include <atomic>
28#include <cstdio>
29#include <deque> // for deque
30#include <functional>
31#include <iosfwd> // for string, stringstream
32#include <memory>
33#include <mutex>
34#include <set> // for set
35#include <stdexcept> // for out_of_range
36#include <stdlib.h> // for abs
37#include <vector>
38
39#include <clipper2/clipper.h>
40#include <core/mirror.h> // for FLIP_DIRECTION
42#include <geometry/seg.h> // for SEG
43#include <geometry/shape.h>
45#include <math/box2.h> // for BOX2I
46#include <math/vector2d.h> // for VECTOR2I
47#include <hash_128.h>
48
49
51
66class SHAPE_POLY_SET : public SHAPE
67{
68public:
70 typedef std::function<void( std::function<void()> )> TASK_SUBMITTER;
71
75 typedef std::vector<SHAPE_LINE_CHAIN> POLYGON;
76
78 {
79 public:
80 struct TRI : public SHAPE_LINE_CHAIN_BASE
81 {
82 TRI( int _a = 0, int _b = 0, int _c = 0, TRIANGULATED_POLYGON* aParent = nullptr ) :
84 a( _a ),
85 b( _b ),
86 c( _c ),
87 parent( aParent )
88 {
89 }
90
91 virtual void Rotate( const EDA_ANGLE& aAngle,
92 const VECTOR2I& aCenter = { 0, 0 } ) override {};
93
94 virtual void Move( const VECTOR2I& aVector ) override {};
95
96 virtual bool IsSolid() const override { return true; }
97
98 virtual bool IsClosed() const override { return true; }
99
100 virtual const BOX2I BBox( int aClearance = 0 ) const override;
101
102 virtual const VECTOR2I GetPoint( int aIndex ) const override
103 {
104 switch(aIndex)
105 {
106 case 0: return parent->m_vertices[a];
107 case 1: return parent->m_vertices[b];
108 case 2: return parent->m_vertices[c];
109 default: wxCHECK( false, VECTOR2I() );
110 }
111 }
112
113 virtual const SEG GetSegment( int aIndex ) const override
114 {
115 switch(aIndex)
116 {
117 case 0: return SEG( parent->m_vertices[a], parent->m_vertices[b] );
118 case 1: return SEG( parent->m_vertices[b], parent->m_vertices[c] );
119 case 2: return SEG( parent->m_vertices[c], parent->m_vertices[a] );
120 default: wxCHECK( false, SEG() );
121 }
122 }
123
124 virtual size_t GetPointCount() const override { return 3; }
125 virtual size_t GetSegmentCount() const override { return 3; }
126
127 double Area() const
128 {
129 VECTOR2I& aa = parent->m_vertices[a];
130 VECTOR2I& bb = parent->m_vertices[b];
131 VECTOR2I& cc = parent->m_vertices[c];
132
133 VECTOR2D ba = bb - aa;
134 VECTOR2D cb = cc - bb;
135
136 return std::abs( cb.Cross( ba ) * 0.5 );
137 }
138
139 int a;
140 int b;
141 int c;
143 };
144
145 TRIANGULATED_POLYGON( int aSourceOutline );
148
149 void Clear()
150 {
151 m_vertices.clear();
152 m_triangles.clear();
153 }
154
155 void GetTriangle( int index, VECTOR2I& a, VECTOR2I& b, VECTOR2I& c ) const
156 {
157 auto& tri = m_triangles[ index ];
158 a = m_vertices[ tri.a ];
159 b = m_vertices[ tri.b ];
160 c = m_vertices[ tri.c ];
161 }
162
168 void Refine();
169
171
172 // Move assignment operator.
174 {
175 if( this != &aOther )
176 {
177 m_sourceOutline = aOther.m_sourceOutline;
178 m_triangles = std::move( aOther.m_triangles );
179 m_vertices = std::move( aOther.m_vertices );
180
181 for( TRI& tri : m_triangles )
182 tri.parent = this;
183 }
184
185 return *this;
186 }
187
188 void AddTriangle( int a, int b, int c );
189
190 void AddVertex( const VECTOR2I& aP )
191 {
192 m_vertices.push_back( aP );
193 }
194
195 size_t GetTriangleCount() const { return m_triangles.size(); }
196
198 void SetSourceOutlineIndex( int aIndex ) { m_sourceOutline = aIndex; }
199
200 const std::deque<TRI>& Triangles() const { return m_triangles; }
201 void SetTriangles( const std::deque<TRI>& aTriangles )
202 {
203 m_triangles.resize( aTriangles.size() );
204
205 for( size_t ii = 0; ii < aTriangles.size(); ii++ )
206 {
207 m_triangles[ii] = aTriangles[ii];
208 m_triangles[ii].parent = this;
209 }
210 }
211
212 const std::deque<VECTOR2I>& Vertices() const { return m_vertices; }
213 void SetVertices( const std::deque<VECTOR2I>& aVertices )
214 {
215 m_vertices = aVertices;
216 }
217
218 size_t GetVertexCount() const
219 {
220 return m_vertices.size();
221 }
222
223 void Move( const VECTOR2I& aVec )
224 {
225 for( VECTOR2I& vertex : m_vertices )
226 vertex += aVec;
227 }
228
229 private:
231 std::deque<TRI> m_triangles;
232 std::deque<VECTOR2I> m_vertices;
233 };
234
241 {
245
247 m_polygon(-1),
248 m_contour(-1),
249 m_vertex(-1)
250 {
251 }
252 };
253
257 template <class T>
259 {
260 public:
261
266 bool IsEndContour() const
267 {
268 return m_currentVertex + 1 == m_poly->CPolygon( m_currentPolygon )[m_currentContour].PointCount();
269 }
270
274 bool IsLastPolygon() const
275 {
277 }
278
279 operator bool() const
280 {
282 return true;
283
284 if( m_currentPolygon != m_poly->OutlineCount() - 1 )
285 return false;
286
287 const auto& currentPolygon = m_poly->CPolygon( m_currentPolygon );
288
289 return m_currentContour < (int) currentPolygon.size() - 1
290 || m_currentVertex < currentPolygon[m_currentContour].PointCount();
291 }
292
297 void Advance()
298 {
299 // Advance vertex index
301
302 // Check whether the user wants to iterate through the vertices of the holes
303 // and behave accordingly
304 if( m_iterateHoles )
305 {
306 // If the last vertex of the contour was reached, advance the contour index
307 if( m_currentVertex >= m_poly->CPolygon( m_currentPolygon )[m_currentContour].PointCount() )
308 {
309 m_currentVertex = 0;
311
312 // If the last contour of the current polygon was reached, advance the
313 // outline index
314 int totalContours = m_poly->CPolygon( m_currentPolygon ).size();
315
316 if( m_currentContour >= totalContours )
317 {
320 }
321 }
322 }
323 else
324 {
325 // If the last vertex of the outline was reached, advance to the following polygon
326 if( m_currentVertex >= m_poly->CPolygon( m_currentPolygon )[0].PointCount() )
327 {
328 m_currentVertex = 0;
330 }
331 }
332 }
333
334 void operator++( int dummy )
335 {
336 Advance();
337 }
338
340 {
341 Advance();
342 }
343
344 const T& Get()
345 {
346 return m_poly->Polygon( m_currentPolygon )[m_currentContour].CPoint( m_currentVertex );
347 }
348
349 const T& operator*()
350 {
351 return Get();
352 }
353
354 const T* operator->()
355 {
356 return &Get();
357 }
358
363 {
365
366 index.m_polygon = m_currentPolygon;
367 index.m_contour = m_currentContour;
368 index.m_vertex = m_currentVertex;
369
370 return index;
371 }
372
373 private:
374 friend class SHAPE_POLY_SET;
375
382 };
383
387 template <class T>
389 {
390 public:
394 bool IsLastPolygon() const
395 {
397 }
398
399 operator bool() const
400 {
402 }
403
408 void Advance()
409 {
410 // Advance vertex index
412 int last;
413
414 // Check whether the user wants to iterate through the vertices of the holes
415 // and behave accordingly.
416 if( m_iterateHoles )
417 {
418 last = m_poly->CPolygon( m_currentPolygon )[m_currentContour].SegmentCount();
419
420 // If the last vertex of the contour was reached, advance the contour index.
421 if( m_currentSegment >= last )
422 {
425
426 // If the last contour of the current polygon was reached, advance the
427 // outline index.
428 int totalContours = m_poly->CPolygon( m_currentPolygon ).size();
429
430 if( m_currentContour >= totalContours )
431 {
434 }
435 }
436 }
437 else
438 {
439 last = m_poly->CPolygon( m_currentPolygon )[0].SegmentCount();
440 // If the last vertex of the outline was reached, advance to the following
441 // polygon
442 if( m_currentSegment >= last )
443 {
446 }
447 }
448 }
449
450 void operator++( int dummy )
451 {
452 Advance();
453 }
454
456 {
457 Advance();
458 }
459
461 {
462 return m_poly->Polygon( m_currentPolygon )[m_currentContour].Segment( m_currentSegment );
463 }
464
466 {
467 return Get();
468 }
469
474 {
476
477 index.m_polygon = m_currentPolygon;
478 index.m_contour = m_currentContour;
479 index.m_vertex = m_currentSegment;
480
481 return index;
482 }
483
490 {
491 // Check that both iterators point to the same contour of the same polygon of the
492 // same polygon set.
493 if( m_poly == aOther.m_poly && m_currentPolygon == aOther.m_currentPolygon &&
495 {
496 // Compute the total number of segments.
497 int numSeg;
498 numSeg = m_poly->CPolygon( m_currentPolygon )[m_currentContour].SegmentCount();
499
500 // Compute the difference of the segment indices. If it is exactly one, they
501 // are adjacent. The only missing case where they also are adjacent is when
502 // the segments are the first and last one, in which case the difference
503 // always equals the total number of segments minus one.
504 int indexDiff = std::abs( m_currentSegment - aOther.m_currentSegment );
505
506 return ( indexDiff == 1 ) || ( indexDiff == (numSeg - 1) );
507 }
508
509 return false;
510 }
511
512 private:
513 friend class SHAPE_POLY_SET;
514
521 };
522
523 // Iterator and const iterator types to visit polygon's points.
526
527 // Iterator and const iterator types to visit polygon's edges.
530
532
533 SHAPE_POLY_SET( const BOX2D& aRect );
534
540 SHAPE_POLY_SET( const SHAPE_LINE_CHAIN& aOutline );
541
547 SHAPE_POLY_SET( const POLYGON& aPolygon );
548
555 SHAPE_POLY_SET( const SHAPE_POLY_SET& aOther );
556
558
559 SHAPE_POLY_SET& operator=( const SHAPE_POLY_SET& aOther );
560
561 SHAPE_POLY_SET& operator=( SHAPE_POLY_SET&& aOther ) noexcept;
562
570 virtual void CacheTriangulation( bool aSimplify = false, const TASK_SUBMITTER& aSubmitter = {},
571 bool aBuildIndexes = false )
572 {
573 cacheTriangulation( aSimplify, nullptr, aSubmitter, aBuildIndexes );
574 }
575 bool IsTriangulationUpToDate() const;
576
577 HASH_128 GetHash() const;
578
579 virtual bool HasIndexableSubshapes() const override;
580
581 virtual size_t GetIndexableSubshapeCount() const override;
582
583 virtual void GetIndexableSubshapes( std::vector<const SHAPE*>& aSubshapes ) const override;
584
596 bool GetRelativeIndices( int aGlobalIdx, VERTEX_INDEX* aRelativeIndices ) const;
597
607 bool GetGlobalIndex( VERTEX_INDEX aRelativeIndices, int& aGlobalIdx ) const;
608
610 SHAPE* Clone() const override;
611
613
615 int NewOutline();
616
618 int NewHole( int aOutline = -1 );
619
621 int AddOutline( const SHAPE_LINE_CHAIN& aOutline );
622
624 int AddHole( const SHAPE_LINE_CHAIN& aHole, int aOutline = -1 );
625
627 int AddPolygon( const POLYGON& apolygon );
628
630 double Area();
631
633 int ArcCount() const;
634
636 void GetArcs( std::vector<SHAPE_ARC>& aArcBuffer ) const;
637
639 void ClearArcs();
640
642
654 int Append( int x, int y, int aOutline = -1, int aHole = -1, bool aAllowDuplication = false );
655
657 void Append( const SHAPE_POLY_SET& aSet );
658
660 void Append( const VECTOR2I& aP, int aOutline = -1, int aHole = -1 );
661
671 int Append( const SHAPE_ARC& aArc, int aOutline = -1, int aHole = -1,
672 std::optional<int> aMaxError = {} );
673
681 void InsertVertex( int aGlobalIndex, const VECTOR2I& aNewVertex );
682
684 const VECTOR2I& CVertex( int aIndex, int aOutline, int aHole ) const;
685
687 const VECTOR2I& CVertex( int aGlobalIndex ) const;
688
690 const VECTOR2I& CVertex( VERTEX_INDEX aIndex ) const;
691
705 bool GetNeighbourIndexes( int aGlobalIndex, int* aPrevious, int* aNext ) const;
706
713 bool IsPolygonSelfIntersecting( int aPolygonIndex ) const;
714
720 bool IsSelfIntersecting() const;
721
723 unsigned int TriangulatedPolyCount() const { return m_triangulatedPolys.size(); }
724
726 const TRIANGULATION_INDEX* TriangulationIndex() const { return m_triIndex.get(); }
727
729 int OutlineCount() const { return m_polys.size(); }
730
732 int VertexCount( int aOutline = -1, int aHole = -1 ) const;
733
736 int FullPointCount() const;
737
739 int HoleCount( int aOutline ) const
740 {
741 if( aOutline < 0 || aOutline >= (int) m_polys.size() || m_polys[aOutline].size() < 2 )
742 return 0;
743
744 // the first polygon in m_polys[aOutline] is the main contour,
745 // only others are holes:
746 return m_polys[aOutline].size() - 1;
747 }
748
751 {
752 return m_polys[aIndex][0];
753 }
754
755 const SHAPE_LINE_CHAIN& Outline( int aIndex ) const
756 {
757 return m_polys[aIndex][0];
758 }
759
769 SHAPE_POLY_SET Subset( int aFirstPolygon, int aLastPolygon );
770
771 SHAPE_POLY_SET UnitSet( int aPolygonIndex )
772 {
773 return Subset( aPolygonIndex, aPolygonIndex + 1 );
774 }
775
777 SHAPE_LINE_CHAIN& Hole( int aOutline, int aHole )
778 {
779 return m_polys[aOutline][aHole + 1];
780 }
781
783 POLYGON& Polygon( int aIndex )
784 {
785 return m_polys[aIndex];
786 }
787
788 const POLYGON& Polygon( int aIndex ) const
789 {
790 return m_polys[aIndex];
791 }
792
793 const TRIANGULATED_POLYGON* TriangulatedPolygon( int aIndex ) const
794 {
795 return m_triangulatedPolys[aIndex].get();
796 }
797
798 const SHAPE_LINE_CHAIN& COutline( int aIndex ) const
799 {
800 return m_polys[aIndex][0];
801 }
802
803 const SHAPE_LINE_CHAIN& CHole( int aOutline, int aHole ) const
804 {
805 return m_polys[aOutline][aHole + 1];
806 }
807
808 const POLYGON& CPolygon( int aIndex ) const
809 {
810 return m_polys[aIndex];
811 }
812
813 const std::vector<POLYGON>& CPolygons() const { return m_polys; }
814
825 ITERATOR Iterate( int aFirst, int aLast, bool aIterateHoles = false )
826 {
827 ITERATOR iter;
828
829 iter.m_poly = this;
830 iter.m_currentPolygon = aFirst;
831 iter.m_lastPolygon = aLast < 0 ? OutlineCount() - 1 : aLast;
832 iter.m_currentContour = 0;
833 iter.m_currentVertex = 0;
834 iter.m_iterateHoles = aIterateHoles;
835
836 return iter;
837 }
838
844 ITERATOR Iterate( int aOutline )
845 {
846 return Iterate( aOutline, aOutline );
847 }
848
855 {
856 return Iterate( aOutline, aOutline, true );
857 }
858
864 {
865 return Iterate( 0, OutlineCount() - 1 );
866 }
867
873 {
874 return Iterate( 0, OutlineCount() - 1, true );
875 }
876
877
878 CONST_ITERATOR CIterate( int aFirst, int aLast, bool aIterateHoles = false ) const
879 {
880 CONST_ITERATOR iter;
881
882 iter.m_poly = const_cast<SHAPE_POLY_SET*>( this );
883 iter.m_currentPolygon = aFirst;
884 iter.m_lastPolygon = aLast < 0 ? OutlineCount() - 1 : aLast;
885 iter.m_currentContour = 0;
886 iter.m_currentVertex = 0;
887 iter.m_iterateHoles = aIterateHoles;
888
889 return iter;
890 }
891
892 CONST_ITERATOR CIterate( int aOutline ) const
893 {
894 return CIterate( aOutline, aOutline );
895 }
896
897 CONST_ITERATOR CIterateWithHoles( int aOutline ) const
898 {
899 return CIterate( aOutline, aOutline, true );
900 }
901
903 {
904 return CIterate( 0, OutlineCount() - 1 );
905 }
906
908 {
909 return CIterate( 0, OutlineCount() - 1, true );
910 }
911
913 {
914 // Build iterator
915 ITERATOR iter = IterateWithHoles();
916
917 // Get the relative indices of the globally indexed vertex
918 VERTEX_INDEX indices;
919
920 if( !GetRelativeIndices( aGlobalIdx, &indices ) )
921 throw( std::out_of_range( "aGlobalIndex-th vertex does not exist" ) );
922
923 // Adjust where the iterator is pointing
924 iter.m_currentPolygon = indices.m_polygon;
925 iter.m_currentContour = indices.m_contour;
926 iter.m_currentVertex = indices.m_vertex;
927
928 return iter;
929 }
930
933 SEGMENT_ITERATOR IterateSegments( int aFirst, int aLast, bool aIterateHoles = false )
934 {
935 SEGMENT_ITERATOR iter;
936
937 iter.m_poly = this;
938 iter.m_currentPolygon = aFirst;
939 iter.m_lastPolygon = aLast < 0 ? OutlineCount() - 1 : aLast;
940 iter.m_currentContour = 0;
941 iter.m_currentSegment = 0;
942 iter.m_iterateHoles = aIterateHoles;
943
944 return iter;
945 }
946
950 bool aIterateHoles = false ) const
951 {
953
954 iter.m_poly = const_cast<SHAPE_POLY_SET*>( this );
955 iter.m_currentPolygon = aFirst;
956 iter.m_lastPolygon = aLast < 0 ? OutlineCount() - 1 : aLast;
957 iter.m_currentContour = 0;
958 iter.m_currentSegment = 0;
959 iter.m_iterateHoles = aIterateHoles;
960
961 return iter;
962 }
963
966 {
967 return IterateSegments( aPolygonIdx, aPolygonIdx );
968 }
969
972 {
973 return CIterateSegments( aPolygonIdx, aPolygonIdx );
974 }
975
978 {
979 return IterateSegments( 0, OutlineCount() - 1 );
980 }
981
984 {
985 return CIterateSegments( 0, OutlineCount() - 1 );
986 }
987
990 {
991 return IterateSegments( 0, OutlineCount() - 1, true );
992 }
993
996 {
997 return IterateSegments( aOutline, aOutline, true );
998 }
999
1002 {
1003 return CIterateSegments( 0, OutlineCount() - 1, true );
1004 }
1005
1008 {
1009 return CIterateSegments( aOutline, aOutline, true );
1010 }
1011
1012
1014 void BooleanAdd( const SHAPE_POLY_SET& b );
1015
1017 void BooleanSubtract( const SHAPE_POLY_SET& b );
1018
1020 void BooleanIntersection( const SHAPE_POLY_SET& b );
1021
1023 void BooleanXor( const SHAPE_POLY_SET& b );
1024
1026 void BooleanAdd( const SHAPE_POLY_SET& a, const SHAPE_POLY_SET& b );
1027
1029 void BooleanSubtract( const SHAPE_POLY_SET& a, const SHAPE_POLY_SET& b );
1030
1032 void BooleanIntersection( const SHAPE_POLY_SET& a, const SHAPE_POLY_SET& b );
1033
1035 void BooleanXor( const SHAPE_POLY_SET& a, const SHAPE_POLY_SET& b );
1036
1042
1059 void Inflate( int aAmount, CORNER_STRATEGY aCornerStrategy, int aMaxError,
1060 bool aSimplify = false );
1061
1062 void Deflate( int aAmount, CORNER_STRATEGY aCornerStrategy, int aMaxError )
1063 {
1064 Inflate( -aAmount, aCornerStrategy, aMaxError );
1065 }
1066
1080 void OffsetLineChain( const SHAPE_LINE_CHAIN& aLine, int aAmount,
1081 CORNER_STRATEGY aCornerStrategy, int aMaxError, bool aSimplify );
1082
1089 void InflateWithLinkedHoles( int aFactor, CORNER_STRATEGY aCornerStrategy, int aMaxError );
1090
1098 void Fracture( bool aSimplify = true );
1099
1102 void Unfracture();
1103
1105 bool HasHoles() const;
1106
1108 bool HasTouchingHoles() const;
1109
1110
1112 void Simplify();
1113
1120 void SimplifyOutlines( int aMaxError = 0 );
1121
1131
1133 const std::string Format( bool aCplusPlus = true ) const override;
1134
1136 bool Parse( std::stringstream& aStream ) override;
1137
1139 void Move( const VECTOR2I& aVector ) override;
1140
1147 void Mirror( const VECTOR2I& aRef, FLIP_DIRECTION aFlipDirection );
1148
1155 void Rotate( const EDA_ANGLE& aAngle, const VECTOR2I& aCenter = { 0, 0 } ) override;
1156
1158 bool IsSolid() const override
1159 {
1160 return true;
1161 }
1162
1163 const BOX2I BBox( int aClearance = 0 ) const override;
1164
1172 bool PointOnEdge( const VECTOR2I& aP, int aAccuracy = 0 ) const;
1173
1186 bool Collide( const SHAPE* aShape, int aClearance = 0, int* aActual = nullptr,
1187 VECTOR2I* aLocation = nullptr ) const override;
1188
1209 bool Collide( const VECTOR2I& aP, int aClearance = 0, int* aActual = nullptr,
1210 VECTOR2I* aLocation = nullptr ) const override;
1211
1231 bool Collide( const SEG& aSeg, int aClearance = 0, int* aActual = nullptr,
1232 VECTOR2I* aLocation = nullptr ) const override;
1233
1244 bool CollideVertex( const VECTOR2I& aPoint, VERTEX_INDEX* aClosestVertex = nullptr,
1245 int aClearance = 0 ) const;
1246
1257 bool CollideEdge( const VECTOR2I& aPoint, VERTEX_INDEX* aClosestVertex = nullptr,
1258 int aClearance = 0 ) const;
1259
1260 bool PointInside( const VECTOR2I& aPt, int aAccuracy = 0,
1261 bool aUseBBoxCache = false ) const override;
1262
1269 void BuildBBoxCaches() const;
1270
1271 const BOX2I BBoxFromCaches() const;
1272
1284 bool Contains( const VECTOR2I& aP, int aSubpolyIndex = -1, int aAccuracy = 0,
1285 bool aUseBBoxCaches = false ) const;
1286
1288 bool IsEmpty() const
1289 {
1290 return m_polys.empty();
1291 }
1292
1298 void RemoveVertex( int aGlobalIndex );
1299
1305 void RemoveVertex( VERTEX_INDEX aRelativeIndices );
1306
1308 void RemoveAllContours();
1309
1318 void RemoveContour( int aContourIdx, int aPolygonIdx = -1 );
1319
1320
1326 void RemoveOutline( int aOutlineIdx );
1327
1333 int RemoveNullSegments();
1334
1341 void SetVertex( const VERTEX_INDEX& aIndex, const VECTOR2I& aPos );
1342
1351 void SetVertex( int aGlobalIndex, const VECTOR2I& aPos );
1352
1354 int TotalVertices() const;
1355
1357 void DeletePolygon( int aIdx );
1358
1361 void DeletePolygonAndTriangulationData( int aIdx, bool aUpdateHash = true );
1362
1364
1372 POLYGON ChamferPolygon( unsigned int aDistance, int aIndex );
1373
1382 POLYGON FilletPolygon( unsigned int aRadius, int aErrorMax, int aIndex );
1383
1390 SHAPE_POLY_SET Chamfer( int aDistance );
1391
1399 SHAPE_POLY_SET Fillet( int aRadius, int aErrorMax );
1400
1411 SEG::ecoord SquaredDistanceToPolygon( VECTOR2I aPoint, int aIndex,
1412 VECTOR2I* aNearest ) const;
1413
1426 SEG::ecoord SquaredDistanceToPolygon( const SEG& aSegment, int aIndex,
1427 VECTOR2I* aNearest) const;
1428
1440 SEG::ecoord SquaredDistance( const VECTOR2I& aPoint, bool aOutlineOnly,
1441 VECTOR2I* aNearest ) const;
1442
1443 SEG::ecoord SquaredDistance( const VECTOR2I& aPoint, bool aOutlineOnly = false ) const override
1444 {
1445 return SquaredDistance( aPoint, aOutlineOnly, nullptr );
1446 }
1447
1458 SEG::ecoord SquaredDistanceToSeg( const SEG& aSegment, VECTOR2I* aNearest = nullptr ) const;
1459
1466 bool IsVertexInHole( int aGlobalIdx );
1467
1475 void BuildPolysetFromOrientedPaths( const std::vector<SHAPE_LINE_CHAIN>& aPaths,
1476 bool aEvenOdd = false );
1477
1478 void TransformToPolygon( SHAPE_POLY_SET& aBuffer, int aError,
1479 ERROR_LOC aErrorLoc ) const override
1480 {
1481 aBuffer.Append( *this );
1482 }
1483
1484 const std::vector<SEG> GenerateHatchLines( const std::vector<double>& aSlopes, int aSpacing,
1485 int aLineLength ) const;
1486
1487 void Scale( double aScaleFactorX, double aScaleFactorY, const VECTOR2I& aCenter );
1488
1489protected:
1490 void cacheTriangulation( bool aSimplify, std::vector<std::unique_ptr<TRIANGULATED_POLYGON>>* aHintData,
1491 const TASK_SUBMITTER& aSubmitter = {}, bool aBuildIndexes = false );
1492
1493private:
1495
1497
1498 void fractureSingle( POLYGON& paths );
1499 void unfractureSingle ( POLYGON& path );
1500 void importTree( Clipper2Lib::PolyTree64& tree,
1501 const std::vector<CLIPPER_Z_VALUE>& aZValueBuffer,
1502 const std::vector<SHAPE_ARC>& aArcBuffe );
1503 void importPaths( Clipper2Lib::Paths64& paths,
1504 const std::vector<CLIPPER_Z_VALUE>& aZValueBuffer,
1505 const std::vector<SHAPE_ARC>& aArcBuffe );
1506 void importPolyPath( const std::unique_ptr<Clipper2Lib::PolyPath64>& aPolyPath,
1507 const std::vector<CLIPPER_Z_VALUE>& aZValueBuffer,
1508 const std::vector<SHAPE_ARC>& aArcBuffer );
1509
1510 void inflate2( int aAmount, int aCircleSegCount, CORNER_STRATEGY aCornerStrategy, bool aSimplify = false );
1511
1512 void inflateLine2( const SHAPE_LINE_CHAIN& aLine, int aAmount, int aCircleSegCount,
1513 CORNER_STRATEGY aCornerStrategy, bool aSimplify = false );
1514
1516
1526
1534 bool isExteriorWaist( const SEG& aSegA, const SEG& aSegB ) const;
1535
1543 void booleanOp( Clipper2Lib::ClipType aType, const SHAPE_POLY_SET& aOtherShape );
1544
1545 void booleanOp( Clipper2Lib::ClipType aType, const SHAPE_POLY_SET& aShape,
1546 const SHAPE_POLY_SET& aOtherShape );
1547
1556 static bool appendBridgeFreePaths( const SHAPE_LINE_CHAIN& aChain, Clipper2Lib::Paths64& aPaths,
1557 std::vector<CLIPPER_Z_VALUE>& aZValues,
1558 std::vector<SHAPE_ARC>& aArcBuffer );
1559
1574 bool containsSingle( const VECTOR2I& aP, int aSubpolyIndex, int aAccuracy,
1575 bool aUseBBoxCaches = false ) const;
1576
1587
1601 POLYGON chamferFilletPolygon( CORNER_MODE aMode, unsigned int aDistance,
1602 int aIndex, int aErrorMax );
1603
1605 bool hasTouchingHoles( const POLYGON& aPoly ) const;
1606
1607 HASH_128 checksum() const;
1608
1609protected:
1610 std::vector<POLYGON> m_polys;
1611 std::vector<std::unique_ptr<TRIANGULATED_POLYGON>> m_triangulatedPolys;
1612
1616 std::unique_ptr<TRIANGULATION_INDEX> m_triIndex;
1617
1618 std::atomic<bool> m_triangulationValid = false;
1620
1621private:
1623 std::atomic<bool> m_hashValid = false;
1624
1626 std::atomic<bool> m_failedHashValid = false;
1627};
1628
1629#endif // __SHAPE_POLY_SET_H
int index
ERROR_LOC
When approximating an arc or circle, should the error be placed on the outside or inside of the curve...
BOX2< VECTOR2I > BOX2I
Definition box2.h:914
BOX2< VECTOR2D > BOX2D
Definition box2.h:915
Definition seg.h:38
VECTOR2I::extended_type ecoord
Definition seg.h:40
SHAPE_LINE_CHAIN_BASE(SHAPE_TYPE aType)
Definition shape.h:318
Represent a polyline containing arcs as well as line segments: A chain of connected line and/or arc s...
Base class for iterating over all vertices in a given SHAPE_POLY_SET.
void Advance()
Advance the indices of the current vertex/outline/contour, checking whether the vertices in the holes...
Base class for iterating over all segments in a given SHAPE_POLY_SET.
bool IsAdjacent(SEGMENT_ITERATOR_TEMPLATE< T > aOther) const
void Advance()
Advance the indices of the current vertex/outline/contour, checking whether the vertices in the holes...
void Refine()
Refine this triangulation in place with boundary-preserving Lawson edge flips, minimizing the number ...
void AddVertex(const VECTOR2I &aP)
void GetTriangle(int index, VECTOR2I &a, VECTOR2I &b, VECTOR2I &c) const
const std::deque< VECTOR2I > & Vertices() const
void SetVertices(const std::deque< VECTOR2I > &aVertices)
const std::deque< TRI > & Triangles() const
TRIANGULATED_POLYGON & operator=(TRIANGULATED_POLYGON &&aOther) noexcept
void AddTriangle(int a, int b, int c)
void SetTriangles(const std::deque< TRI > &aTriangles)
TRIANGULATED_POLYGON & operator=(const TRIANGULATED_POLYGON &aOther)
void Move(const VECTOR2I &aVec)
Represent a set of closed polygons.
std::mutex m_triangulationMutex
virtual bool HasIndexableSubshapes() const override
void Rotate(const EDA_ANGLE &aAngle, const VECTOR2I &aCenter={ 0, 0 }) override
Rotate all vertices by a given angle.
void RemoveAllContours()
Remove all outlines & holes (clears) the polygon set.
SHAPE_POLY_SET Chamfer(int aDistance)
Return a chamfered version of the polygon set.
void RemoveOutline(int aOutlineIdx)
Delete the aOutlineIdx-th outline of the set including its contours and holes.
void Scale(double aScaleFactorX, double aScaleFactorY, const VECTOR2I &aCenter)
bool CollideEdge(const VECTOR2I &aPoint, VERTEX_INDEX *aClosestVertex=nullptr, int aClearance=0) const
Check whether aPoint collides with any edge of any of the contours of the polygon.
HASH_128 GetHash() const
virtual void GetIndexableSubshapes(std::vector< const SHAPE * > &aSubshapes) const override
void BooleanXor(const SHAPE_POLY_SET &b)
Perform boolean polyset exclusive or.
ITERATOR_TEMPLATE< VECTOR2I > ITERATOR
void fractureSingle(POLYGON &paths)
bool HasHoles() const
Return true if the polygon set has any holes.
void cacheTriangulation(bool aSimplify, std::vector< std::unique_ptr< TRIANGULATED_POLYGON > > *aHintData, const TASK_SUBMITTER &aSubmitter={}, bool aBuildIndexes=false)
CONST_ITERATOR CIterateWithHoles() const
void BooleanAdd(const SHAPE_POLY_SET &b)
Perform boolean polyset union.
ITERATOR IterateWithHoles(int aOutline)
ITERATOR IterateWithHoles()
void ClearArcs()
Removes all arc references from all the outlines and holes in the polyset.
bool IsTriangulationUpToDate() const
void importPaths(Clipper2Lib::Paths64 &paths, const std::vector< CLIPPER_Z_VALUE > &aZValueBuffer, const std::vector< SHAPE_ARC > &aArcBuffe)
void InsertVertex(int aGlobalIndex, const VECTOR2I &aNewVertex)
Adds a vertex in the globally indexed position aGlobalIndex.
const TRIANGULATION_INDEX * TriangulationIndex() const
The spatial index over the cached triangulation, or nullptr when none was built.
std::atomic< bool > m_failedHashValid
CONST_ITERATOR CIterate() const
CORNER_MODE
Operation ChamferPolygon and FilletPolygon are computed under the private chamferFillet method; this ...
int AddOutline(const SHAPE_LINE_CHAIN &aOutline)
Adds a new outline to the set and returns its index.
int VertexCount(int aOutline=-1, int aHole=-1) const
Return the number of vertices in a given outline/hole.
void DeletePolygon(int aIdx)
Delete aIdx-th polygon from the set.
double Area()
Return the area of this poly set.
void SetVertex(const VERTEX_INDEX &aIndex, const VECTOR2I &aPos)
Accessor function to set the position of a specific point.
bool IsEmpty() const
Return true if the set is empty (no polygons at all)
virtual void CacheTriangulation(bool aSimplify=false, const TASK_SUBMITTER &aSubmitter={}, bool aBuildIndexes=false)
Build a polygon triangulation, needed to draw a polygon on OpenGL and in some other calculations.
CONST_ITERATOR CIterate(int aFirst, int aLast, bool aIterateHoles=false) const
bool Collide(const SHAPE *aShape, int aClearance=0, int *aActual=nullptr, VECTOR2I *aLocation=nullptr) const override
Check if the boundary of shape (this) lies closer to the shape aShape than aClearance,...
void BuildPolysetFromOrientedPaths(const std::vector< SHAPE_LINE_CHAIN > &aPaths, bool aEvenOdd=false)
Build a SHAPE_POLY_SET from a bunch of outlines in provided in random order.
ITERATOR Iterate(int aOutline)
bool Parse(std::stringstream &aStream) override
int TotalVertices() const
Return total number of vertices stored in the set.
CONST_ITERATOR CIterate(int aOutline) const
POLYGON & Polygon(int aIndex)
Return the aIndex-th subpolygon in the set.
int FullPointCount() const
Return the number of points in the shape poly set.
void GetArcs(std::vector< SHAPE_ARC > &aArcBuffer) const
Appends all the arcs in this polyset to aArcBuffer.
bool IsVertexInHole(int aGlobalIdx)
Check whether the aGlobalIndex-th vertex belongs to a hole.
int NormalizeAreaOutlines()
Convert a self-intersecting polygon to one (or more) non self-intersecting polygon(s).
static bool appendBridgeFreePaths(const SHAPE_LINE_CHAIN &aChain, Clipper2Lib::Paths64 &aPaths, std::vector< CLIPPER_Z_VALUE > &aZValues, std::vector< SHAPE_ARC > &aArcBuffer)
Append the rings left after cutting the fracture bridges out of aChain.
void RemoveVertex(int aGlobalIndex)
Delete the aGlobalIndex-th vertex.
void unfractureSingle(POLYGON &path)
void inflateLine2(const SHAPE_LINE_CHAIN &aLine, int aAmount, int aCircleSegCount, CORNER_STRATEGY aCornerStrategy, bool aSimplify=false)
SEGMENT_ITERATOR IterateSegments(int aPolygonIdx)
Return an iterator object, for iterating aPolygonIdx-th polygon edges.
SEGMENT_ITERATOR IterateSegmentsWithHoles(int aOutline)
Return an iterator object, for the aOutline-th outline in the set (with holes).
bool GetRelativeIndices(int aGlobalIdx, VERTEX_INDEX *aRelativeIndices) const
Convert a global vertex index —i.e., a number that globally identifies a vertex in a concatenated lis...
bool IsPolygonSelfIntersecting(int aPolygonIndex) const
Check whether the aPolygonIndex-th polygon in the set is self intersecting.
SHAPE_POLY_SET Subset(int aFirstPolygon, int aLastPolygon)
Return a subset of the polygons in this set, the ones between aFirstPolygon and aLastPolygon.
SHAPE_POLY_SET UnitSet(int aPolygonIndex)
const POLYGON & Polygon(int aIndex) const
int RemoveNullSegments()
Look for null segments; ie, segments whose ends are exactly the same and deletes them.
HASH_128 checksum() const
void Inflate(int aAmount, CORNER_STRATEGY aCornerStrategy, int aMaxError, bool aSimplify=false)
Perform outline inflation/deflation.
int HoleCount(int aOutline) const
Returns the number of holes in a given outline.
int Append(int x, int y, int aOutline=-1, int aHole=-1, bool aAllowDuplication=false)
Appends a vertex at the end of the given outline/hole (default: the last outline)
int AddPolygon(const POLYGON &apolygon)
Adds a polygon to the set.
const std::vector< SEG > GenerateHatchLines(const std::vector< double > &aSlopes, int aSpacing, int aLineLength) const
const std::string Format(bool aCplusPlus=true) const override
void Simplify()
Simplify the polyset (merges overlapping polys, eliminates degeneracy/self-intersections)
std::vector< SHAPE_LINE_CHAIN > POLYGON
represents a single polygon outline with holes.
std::vector< std::unique_ptr< TRIANGULATED_POLYGON > > m_triangulatedPolys
SEGMENT_ITERATOR IterateSegments()
Return an iterator object, for all outlines in the set (no holes).
ITERATOR Iterate()
const SHAPE_LINE_CHAIN & Outline(int aIndex) const
CONST_SEGMENT_ITERATOR CIterateSegments() const
Returns an iterator object, for all outlines in the set (no holes)
ITERATOR_TEMPLATE< const VECTOR2I > CONST_ITERATOR
void inflate2(int aAmount, int aCircleSegCount, CORNER_STRATEGY aCornerStrategy, bool aSimplify=false)
int AddHole(const SHAPE_LINE_CHAIN &aHole, int aOutline=-1)
Adds a new hole to the given outline (default: last) and returns its index.
SEG::ecoord SquaredDistance(const VECTOR2I &aPoint, bool aOutlineOnly, VECTOR2I *aNearest) const
Compute the minimum distance squared between aPoint and all the polygons in the set.
void RemoveContour(int aContourIdx, int aPolygonIdx=-1)
Delete the aContourIdx-th contour of the aPolygonIdx-th polygon in the set.
void Unfracture()
Convert a single outline slitted ("fractured") polygon into a set ouf outlines with holes.
int ArcCount() const
Count the number of arc shapes present.
bool GetGlobalIndex(VERTEX_INDEX aRelativeIndices, int &aGlobalIdx) const
Compute the global index of a vertex from the relative indices of polygon, contour and vertex.
bool GetNeighbourIndexes(int aGlobalIndex, int *aPrevious, int *aNext) const
Return the global indexes of the previous and the next corner of the aGlobalIndex-th corner of a cont...
std::unique_ptr< TRIANGULATION_INDEX > m_triIndex
One index over every triangle of every polygon above.
SHAPE_LINE_CHAIN & Outline(int aIndex)
Return the reference to aIndex-th outline in the set.
SHAPE_LINE_CHAIN & Hole(int aOutline, int aHole)
Return the reference to aHole-th hole in the aIndex-th outline.
bool IsSolid() const override
int NewOutline()
Creates a new empty polygon in the set and returns its index.
void SimplifyOutlines(int aMaxError=0)
Simplifies the lines in the polyset.
void booleanOp(Clipper2Lib::ClipType aType, const SHAPE_POLY_SET &aOtherShape)
This is the engine to execute all polygon boolean transforms (AND, OR, ... and polygon simplification...
const TRIANGULATED_POLYGON * TriangulatedPolygon(int aIndex) const
bool hasTouchingHoles(const POLYGON &aPoly) const
Return true if the polygon set has any holes that touch share a vertex.
CONST_SEGMENT_ITERATOR CIterateSegments(int aPolygonIdx) const
Return an iterator object, for iterating aPolygonIdx-th polygon edges.
SEG::ecoord SquaredDistance(const VECTOR2I &aPoint, bool aOutlineOnly=false) const override
bool PointOnEdge(const VECTOR2I &aP, int aAccuracy=0) const
Check if point aP lies on an edge or vertex of some of the outlines or holes.
std::atomic< bool > m_hashValid
bool CollideVertex(const VECTOR2I &aPoint, VERTEX_INDEX *aClosestVertex=nullptr, int aClearance=0) const
Check whether aPoint collides with any vertex of any of the contours of the polygon.
void DeletePolygonAndTriangulationData(int aIdx, bool aUpdateHash=true)
Delete aIdx-th polygon and its triangulation data from the set.
unsigned int TriangulatedPolyCount() const
Return the number of triangulated polygons.
std::atomic< bool > m_triangulationValid
void Deflate(int aAmount, CORNER_STRATEGY aCornerStrategy, int aMaxError)
void UpdateTriangulationDataHash()
void BooleanIntersection(const SHAPE_POLY_SET &b)
Perform boolean polyset intersection.
int NewHole(int aOutline=-1)
Creates a new hole in a given outline.
SEG::ecoord SquaredDistanceToPolygon(VECTOR2I aPoint, int aIndex, VECTOR2I *aNearest) const
Compute the minimum distance between the aIndex-th polygon and aPoint.
CONST_SEGMENT_ITERATOR CIterateSegmentsWithHoles() const
Return an iterator object, for the aOutline-th outline in the set (with holes).
virtual size_t GetIndexableSubshapeCount() const override
SEGMENT_ITERATOR IterateSegments(int aFirst, int aLast, bool aIterateHoles=false)
Return an iterator object, for iterating between aFirst and aLast outline, with or without holes (def...
ITERATOR Iterate(int aFirst, int aLast, bool aIterateHoles=false)
Return an object to iterate through the points of the polygons between aFirst and aLast.
CONST_SEGMENT_ITERATOR CIterateSegments(int aFirst, int aLast, bool aIterateHoles=false) const
Return an iterator object, for iterating between aFirst and aLast outline, with or without holes (def...
ITERATOR IterateFromVertexWithHoles(int aGlobalIdx)
SEG::ecoord SquaredDistanceToSeg(const SEG &aSegment, VECTOR2I *aNearest=nullptr) const
Compute the minimum distance squared between aSegment and all the polygons in the set.
void importPolyPath(const std::unique_ptr< Clipper2Lib::PolyPath64 > &aPolyPath, const std::vector< CLIPPER_Z_VALUE > &aZValueBuffer, const std::vector< SHAPE_ARC > &aArcBuffer)
void RebuildHolesFromContours()
Extract all contours from this polygon set, then recreate polygons with holes.
void Mirror(const VECTOR2I &aRef, FLIP_DIRECTION aFlipDirection)
Mirror the line points about y or x (or both)
void OffsetLineChain(const SHAPE_LINE_CHAIN &aLine, int aAmount, CORNER_STRATEGY aCornerStrategy, int aMaxError, bool aSimplify)
Perform offsetting of a line chain.
void BuildBBoxCaches() const
Construct BBoxCaches for Contains(), below.
std::vector< POLYGON > m_polys
void splitSelfTouchingOutlines()
Split outline segments at vertices that lie on them (self-touching polygons).
const SHAPE_LINE_CHAIN & CHole(int aOutline, int aHole) const
POLYGON FilletPolygon(unsigned int aRadius, int aErrorMax, int aIndex)
Return a filleted version of the aIndex-th polygon.
bool containsSingle(const VECTOR2I &aP, int aSubpolyIndex, int aAccuracy, bool aUseBBoxCaches=false) const
Check whether the point aP is inside the aSubpolyIndex-th polygon of the polyset.
const VECTOR2I & CVertex(int aIndex, int aOutline, int aHole) const
Return the index-th vertex in a given hole outline within a given outline.
int OutlineCount() const
Return the number of outlines in the set.
void InflateWithLinkedHoles(int aFactor, CORNER_STRATEGY aCornerStrategy, int aMaxError)
Perform outline inflation/deflation, using round corners.
SEGMENT_ITERATOR_TEMPLATE< SEG > SEGMENT_ITERATOR
POLYGON chamferFilletPolygon(CORNER_MODE aMode, unsigned int aDistance, int aIndex, int aErrorMax)
Return the chamfered or filleted version of the aIndex-th polygon in the set, depending on the aMode ...
SHAPE_POLY_SET Fillet(int aRadius, int aErrorMax)
Return a filleted version of the polygon set.
void Move(const VECTOR2I &aVector) override
bool HasTouchingHoles() const
Return true if the polygon set has any holes that share a vertex.
SHAPE * Clone() const override
Return a dynamically allocated copy of the shape.
void Fracture(bool aSimplify=true)
Convert a set of polygons with holes to a single outline with "slits"/"fractures" connecting the oute...
SHAPE_POLY_SET & operator=(const SHAPE_POLY_SET &aOther)
bool Contains(const VECTOR2I &aP, int aSubpolyIndex=-1, int aAccuracy=0, bool aUseBBoxCaches=false) const
Return true if a given subpolygon contains the point aP.
SHAPE_POLY_SET CloneDropTriangulation() const
void TransformToPolygon(SHAPE_POLY_SET &aBuffer, int aError, ERROR_LOC aErrorLoc) const override
Fills a SHAPE_POLY_SET with a polygon representation of this shape.
bool isExteriorWaist(const SEG &aSegA, const SEG &aSegB) const
Check if two line segments are collinear and overlap.
void BooleanSubtract(const SHAPE_POLY_SET &b)
Perform boolean polyset difference.
const POLYGON & CPolygon(int aIndex) const
CONST_ITERATOR CIterateWithHoles(int aOutline) const
const SHAPE_LINE_CHAIN & COutline(int aIndex) const
POLYGON ChamferPolygon(unsigned int aDistance, int aIndex)
Return a chamfered version of the aIndex-th polygon.
std::function< void(std::function< void()>)> TASK_SUBMITTER
Callback that submits a unit of work for asynchronous execution.
bool PointInside(const VECTOR2I &aPt, int aAccuracy=0, bool aUseBBoxCache=false) const override
Check if point aP lies inside a closed shape.
const std::vector< POLYGON > & CPolygons() const
SEGMENT_ITERATOR IterateSegmentsWithHoles()
Returns an iterator object, for all outlines in the set (with holes)
const BOX2I BBoxFromCaches() const
CONST_SEGMENT_ITERATOR CIterateSegmentsWithHoles(int aOutline) const
Return an iterator object, for the aOutline-th outline in the set (with holes).
const BOX2I BBox(int aClearance=0) const override
Compute a bounding box of the shape, with a margin of aClearance a collision.
void importTree(Clipper2Lib::PolyTree64 &tree, const std::vector< CLIPPER_Z_VALUE > &aZValueBuffer, const std::vector< SHAPE_ARC > &aArcBuffe)
SEGMENT_ITERATOR_TEMPLATE< const SEG > CONST_SEGMENT_ITERATOR
bool IsSelfIntersecting() const
Check whether any of the polygons in the set is self intersecting.
An abstract shape on 2D plane.
Definition shape.h:124
SHAPE(SHAPE_TYPE aType)
Create an empty shape of type aType.
Definition shape.h:134
A spatial index over the triangles of a cached triangulation, used to prune collision tests.
constexpr extended_type Cross(const VECTOR2< T > &aVector) const
Compute cross product of self with aVector.
Definition vector2d.h:559
CORNER_STRATEGY
define how inflate transform build inflated polygon
FLIP_DIRECTION
Definition mirror.h:23
EDA_ANGLE abs(const EDA_ANGLE &aAngle)
Definition eda_angle.h:437
@ SH_POLY_SET_TRIANGLE
a single triangle belonging to a POLY_SET triangulation
Definition shape.h:52
std::vector< FAB_LAYER_COLOR > dummy
A storage class for 128-bit hash value.
Definition hash_128.h:33
virtual bool IsClosed() const override
TRI(int _a=0, int _b=0, int _c=0, TRIANGULATED_POLYGON *aParent=nullptr)
virtual bool IsSolid() const override
virtual void Move(const VECTOR2I &aVector) override
virtual void Rotate(const EDA_ANGLE &aAngle, const VECTOR2I &aCenter={ 0, 0 }) override
virtual const BOX2I BBox(int aClearance=0) const override
Compute a bounding box of the shape, with a margin of aClearance a collision.
virtual size_t GetPointCount() const override
virtual const VECTOR2I GetPoint(int aIndex) const override
virtual size_t GetSegmentCount() const override
virtual const SEG GetSegment(int aIndex) const override
Structure to hold the necessary information in order to index a vertex on a SHAPE_POLY_SET object: th...
std::string path
VECTOR2< int32_t > VECTOR2I
Definition vector2d.h:708
VECTOR2< double > VECTOR2D
Definition vector2d.h:707