38 #include <type_traits> 39 #include <unordered_set> 42 #include <clipper.hpp> 58 using namespace ClipperLib;
74 SHAPE( aOther ), m_polys( aOther.m_polys )
109 unsigned int contourIdx = 0;
112 int currentGlobalIdx = 0;
114 for( polygonIdx = 0; polygonIdx <
OutlineCount(); polygonIdx++ )
118 for( contourIdx = 0; contourIdx < currentPolygon.size(); contourIdx++ )
121 int totalPoints = currentContour.
PointCount();
123 for( vertexIdx = 0; vertexIdx < totalPoints; vertexIdx++ )
126 if( currentGlobalIdx == aGlobalIdx )
128 aRelativeIndices->
m_polygon = polygonIdx;
129 aRelativeIndices->
m_contour = contourIdx;
130 aRelativeIndices->
m_vertex = vertexIdx;
148 int selectedVertex = aRelativeIndices.
m_vertex;
149 unsigned int selectedContour = aRelativeIndices.
m_contour;
150 unsigned int selectedPolygon = aRelativeIndices.
m_polygon;
153 if( selectedPolygon <
m_polys.size() && selectedContour <
m_polys[selectedPolygon].size()
154 && selectedVertex <
m_polys[selectedPolygon][selectedContour].PointCount() )
160 for(
unsigned int polygonIdx = 0; polygonIdx < selectedPolygon; polygonIdx++ )
162 currentPolygon =
Polygon( polygonIdx );
164 for(
unsigned int contourIdx = 0; contourIdx < currentPolygon.size(); contourIdx++ )
166 aGlobalIdx += currentPolygon[contourIdx].PointCount();
170 currentPolygon =
Polygon( selectedPolygon );
172 for(
unsigned int contourIdx = 0; contourIdx < selectedContour; contourIdx++ )
174 aGlobalIdx += currentPolygon[contourIdx].PointCount();
177 aGlobalIdx += selectedVertex;
194 poly.push_back( empty_path );
211 m_polys[aOutline].push_back( empty_path );
213 return m_polys.back().size() - 2;
231 assert( aOutline < (
int)
m_polys.size() );
232 assert( idx < (
int)
m_polys[aOutline].size() );
234 m_polys[aOutline][idx].Append( x, y, aAllowDuplication );
236 return m_polys[aOutline][idx].PointCount();
244 if( aGlobalIndex < 0 )
257 throw( std::out_of_range(
"aGlobalIndex-th vertex does not exist" ) );
277 if( aOutline >= (
int)
m_polys.size() )
280 if( idx >= (
int)
m_polys[aOutline].size() )
283 return m_polys[aOutline][idx].PointCount();
289 assert( aFirstPolygon >= 0 && aLastPolygon <=
OutlineCount() );
293 for(
int index = aFirstPolygon; index < aLastPolygon; index++ )
314 assert( aOutline < (
int)
m_polys.size() );
315 assert( idx < (
int)
m_polys[aOutline].size() );
317 return m_polys[aOutline][idx].CPoint( aIndex );
327 throw( std::out_of_range(
"aGlobalIndex-th vertex does not exist" ) );
357 else if( index.
m_vertex == lastpoint )
372 *aPrevious = previous;
393 SEG firstSegment = *iterator;
396 innerIterator = iterator;
399 for( innerIterator++; innerIterator; innerIterator++ )
401 SEG secondSegment = *innerIterator;
404 if( !iterator.
IsAdjacent( innerIterator ) && firstSegment.
Collide( secondSegment, 0 ) )
415 for(
unsigned int polygon = 0; polygon <
m_polys.size(); polygon++ )
431 poly.push_back( aOutline );
446 assert( aOutline < (
int)
m_polys.size() );
450 assert( poly.size() );
452 poly.push_back( aHole );
454 return poly.size() - 2;
461 booleanOp( aType, *
this, aOtherShape, aFastMode );
474 for(
auto poly : aShape.
m_polys )
476 for(
size_t i = 0 ; i < poly.size(); i++ )
477 c.AddPath( poly[i].convertToClipper( i == 0 ), ptSubject, true );
480 for(
auto poly : aOtherShape.
m_polys )
482 for(
size_t i = 0; i < poly.size(); i++ )
483 c.AddPath( poly[i].convertToClipper( i == 0 ), ptClip, true );
488 c.Execute( aType, solution, pftNonZero, pftNonZero );
508 booleanOp( ctIntersection, b, aFastMode );
524 booleanOp( ctDifference, a, b, aFastMode );
532 booleanOp( ctIntersection, a, b, aFastMode );
540 Inflate( aFactor, aCircleSegmentsCount );
551 #define SEG_CNT_MAX 64 552 static double arc_tolerance_factor[
SEG_CNT_MAX + 1];
559 JoinType joinType = jtRound;
560 double miterLimit = 2.0;
561 JoinType miterFallback = jtSquare;
563 switch( aCornerStrategy )
568 miterFallback = jtSquare;
573 miterFallback = jtRound;
578 miterFallback = jtSquare;
583 miterFallback = jtSquare;
588 miterFallback = jtSquare;
594 for(
size_t i = 0; i < poly.size(); i++ )
595 c.AddPath( poly[i].convertToClipper( i == 0 ), joinType, etClosedPolygon );
604 if( aCircleSegmentsCount < 6 )
605 aCircleSegmentsCount = 6;
609 if( aCircleSegmentsCount >
SEG_CNT_MAX || arc_tolerance_factor[aCircleSegmentsCount] == 0 )
611 coeff = 1.0 - cos( M_PI / aCircleSegmentsCount );
614 arc_tolerance_factor[aCircleSegmentsCount] = coeff;
617 coeff = arc_tolerance_factor[aCircleSegmentsCount];
619 c.ArcTolerance = std::abs( aAmount ) * coeff;
620 c.MiterLimit = miterLimit;
621 c.MiterFallback = miterFallback;
622 c.Execute( solution, aAmount );
632 for( PolyNode* n = tree->GetFirst(); n; n = n->GetNext() )
637 paths.reserve( n->Childs.size() + 1 );
638 paths.push_back( n->Contour );
640 for(
unsigned int i = 0; i < n->Childs.size(); i++ )
641 paths.push_back( n->Childs[i]->Contour );
682 int x = edge->
m_p1.
x;
683 int y = edge->
m_p1.
y;
684 int min_dist = std::numeric_limits<int>::max();
691 if( !e->matches( y ) )
696 if( e->m_p1.y == e->m_p2.y )
698 x_intersect = std::max( e->m_p1.x, e->m_p2.x );
702 x_intersect = e->m_p1.x +
rescale( e->m_p2.x - e->m_p1.x, y - e->m_p1.y,
703 e->m_p2.y - e->m_p1.y );
706 int dist = ( x - x_intersect );
708 if( dist >= 0 && dist < min_dist && e->m_connected )
711 x_nearest = x_intersect;
724 edges.push_back( split_2 );
725 edges.push_back( lead1 );
726 edges.push_back( lead2 );
731 e_nearest->
m_next = lead1;
736 for( last = edge; last->
m_next != edge; last = last->
m_next )
762 if( paths.size() == 1 )
765 int num_unconnected = 0;
769 const std::vector<VECTOR2I>& points = path.CPoints();
770 int pointCount = points.size();
774 int x_min = std::numeric_limits<int>::max();
782 for(
int i = 0; i < pointCount; i++ )
787 points[ i+1 == pointCount ? 0 : i+1 ] );
798 if( i == pointCount - 1 )
802 edges.push_back( fe );
806 if( fe->
m_p1.
x == x_min )
807 border_edges.push_back( fe );
818 while( num_unconnected > 0 )
820 int x_min = std::numeric_limits<int>::max();
827 int xt = border_edge->m_p1.x;
829 if( ( xt < x_min ) && !border_edge->m_connected )
832 smallestX = border_edge;
836 num_unconnected -=
processEdge( edges, smallestX );
854 paths.push_back( std::move( newPath ) );
871 assert( aPoly.size() == 1 );
877 bool m_duplicate =
false;
884 bool compareSegs(
const SEG& s1,
const SEG& s2 )
const 886 return (s1.
A == s2.
B && s1.
B == s2.
A);
891 return compareSegs( m_poly->
CSegment( m_index ),
892 aOther.m_poly->CSegment( aOther.m_index ) );
897 return !compareSegs( m_poly->
CSegment( m_index ),
898 aOther.m_poly->CSegment( aOther.m_index ) );
903 std::size_t operator()(
const EDGE& aEdge )
const 905 const auto& a = aEdge.m_poly->CSegment( aEdge.m_index );
907 return (std::size_t) ( a.A.x + a.B.x + a.A.y + a.B.y );
912 struct EDGE_LIST_ENTRY
915 EDGE_LIST_ENTRY*
next;
918 std::unordered_set<EDGE, EDGE::HASH> uniqueEdges;
923 auto edgeList = std::make_unique<EDGE_LIST_ENTRY []>( lc.SegmentCount() );
925 for(
int i = 0; i < lc.SegmentCount(); i++ )
927 edgeList[i].index = i;
928 edgeList[i].next = &edgeList[ (i != lc.SegmentCount() - 1) ? i + 1 : 0 ];
931 std::unordered_set<EDGE_LIST_ENTRY*> queue;
933 for(
int i = 0; i < lc.SegmentCount(); i++ )
936 uniqueEdges.insert( e );
939 for(
int i = 0; i < lc.SegmentCount(); i++ )
942 auto it = uniqueEdges.find( e );
944 if( it != uniqueEdges.end() && it->m_index != i )
946 int e1 = it->m_index;
952 int e1_prev = e1 - 1;
955 e1_prev = lc.SegmentCount() - 1;
957 int e2_prev = e2 - 1;
960 e2_prev = lc.SegmentCount() - 1;
962 int e1_next = e1 + 1;
964 if( e1_next == lc.SegmentCount() )
967 int e2_next = e2 + 1;
969 if( e2_next == lc.SegmentCount() )
972 edgeList[e1_prev].next = &edgeList[ e2_next ];
973 edgeList[e2_prev].next = &edgeList[ e1_next ];
974 edgeList[i].next =
nullptr;
975 edgeList[it->m_index].next =
nullptr;
979 for(
int i = 0; i < lc.SegmentCount(); i++ )
981 if( edgeList[i].
next )
982 queue.insert( &edgeList[i] );
985 auto edgeBuf = std::make_unique<EDGE_LIST_ENTRY* []>( lc.SegmentCount() );
992 while( queue.size() )
994 auto e_first = (*queue.begin() );
1001 }
while( e && e != e_first );
1005 for(
int i = 0; i < cnt; i++ )
1007 auto p = lc.
CPoint( edgeBuf[i]->index );
1009 queue.erase( edgeBuf[i] );
1014 bool cw = outl.
Area() > 0.0;
1019 result.push_back( outl );
1024 std::swap( result[0], result[outline] );
1036 if( paths.size() > 1 )
1076 while( outline.size() > 1 )
1099 std::stringstream ss;
1101 ss <<
"SHAPE_LINE_CHAIN poly; \n";
1103 for(
unsigned i = 0; i <
m_polys.size(); i++ )
1105 for(
unsigned j = 0; j <
m_polys[i].size(); j++ )
1108 ss <<
"{ auto tmp = " <<
m_polys[i][j].Format() <<
";\n";
1114 ss <<
" poly.AddOutline(tmp); } \n";
1118 ss <<
" poly.AddHole(tmp); } \n";
1134 if( tmp !=
"polyset" )
1139 int n_polys = atoi( tmp.c_str() );
1144 for(
int i = 0; i < n_polys; i++ )
1154 int n_outlines = atoi( tmp.c_str() );
1156 if( n_outlines < 0 )
1159 for(
int j = 0; j < n_outlines; j++ )
1166 int n_vertices = atoi( tmp.c_str() );
1168 for(
int v = 0; v < n_vertices; v++ )
1172 aStream >> tmp; p.
x = atoi( tmp.c_str() );
1173 aStream >> tmp; p.
y = atoi( tmp.c_str() );
1177 paths.push_back( outline );
1191 for(
unsigned i = 0; i <
m_polys.size(); i++ )
1208 for(
unsigned i = 0; i <
m_polys.size(); i++ )
1211 bb =
m_polys[i][0].BBoxFromCache();
1228 if( lineChain.PointOnEdge( aP ) )
1243 if( dist_sq == 0 || dist_sq <
SEG::Square( aClearance ) )
1246 *aLocation = nearest;
1249 *aActual = sqrt( dist_sq );
1264 if( dist_sq == 0 || dist_sq <
SEG::Square( aClearance ) )
1267 *aLocation = nearest;
1270 *aActual = sqrt( dist_sq );
1286 const SHAPE_SEGMENT* segment = static_cast<const SHAPE_SEGMENT*>( aShape );
1287 int extra = segment->
GetWidth() / 2;
1289 if(
Collide( segment->
GetSeg(), aClearance + extra, aActual, aLocation ) )
1292 *aActual = std::max( 0, *aActual - extra );
1302 const SHAPE_CIRCLE* circle = static_cast<const SHAPE_CIRCLE*>( aShape );
1305 if(
Collide( circle->
GetCenter(), aClearance + extra, aActual, aLocation ) )
1308 *aActual = std::max( 0, *aActual - extra );
1316 const_cast<SHAPE_POLY_SET*>(
this )->CacheTriangulation(
true );
1318 int actual = INT_MAX;
1323 for (
auto& tri : tpoly->Triangles() )
1328 if( aShape->
Collide( &tri, aClearance, &triActual, &triLocation ) )
1330 if( !aActual && !aLocation )
1333 if( triActual < actual )
1336 location = triLocation;
1342 if( actual < INT_MAX )
1345 *aActual = std::max( 0, actual );
1348 *aLocation = location;
1366 if( aPolygonIdx < 0 )
1367 aPolygonIdx +=
m_polys.size();
1369 m_polys[aPolygonIdx].erase(
m_polys[aPolygonIdx].begin() + aContourIdx );
1387 segmentStart = *iterator;
1393 segmentEnd = contourStart;
1399 contourStart = *iterator;
1407 segmentEnd = *iterator;
1411 if( segmentStart == segmentEnd )
1440 Append( aP.
x, aP.
y, aOutline, aHole );
1446 int aClearance )
const 1449 bool collision =
false;
1456 clearance = aClearance;
1461 delta = *iterator - aPoint;
1475 aClosestVertex = iterator.GetIndex();
1485 int aClearance )
const 1488 bool collision =
false;
1492 const SEG currentSegment = *iterator;
1504 aClosestVertex = iterator.GetIndex();
1514 for(
int polygonIdx = 0; polygonIdx <
OutlineCount(); polygonIdx++ )
1518 for(
int holeIdx = 0; holeIdx <
HoleCount( polygonIdx ); holeIdx++ )
1525 bool aUseBBoxCaches )
const 1531 if( aSubpolyIndex >= 0 )
1532 return containsSingle( aP, aSubpolyIndex, aAccuracy, aUseBBoxCaches );
1535 for(
int polygonIdx = 0; polygonIdx <
OutlineCount(); polygonIdx++ )
1537 if(
containsSingle( aP, polygonIdx, aAccuracy, aUseBBoxCaches ) )
1553 throw( std::out_of_range(
"aGlobalIndex-th vertex does not exist" ) );
1570 throw( std::out_of_range(
"aGlobalIndex-th vertex does not exist" ) );
1581 bool aUseBBoxCaches )
const 1584 if(
m_polys[aSubpolyIndex][0].PointInside( aP, aAccuracy ) )
1587 for(
int holeIdx = 0; holeIdx <
HoleCount( aSubpolyIndex ); holeIdx++ )
1609 path.Move( aVector );
1613 tri->Move( aVector );
1624 path.Mirror( aX, aY, aRef );
1637 path.Rotate( aAngle, aCenter );
1653 c += path.PointCount();
1690 SEG::ecoord minDistance = (*iterator).SquaredDistance( aPoint );
1692 for( iterator++; iterator && minDistance > 0; iterator++ )
1694 SEG::ecoord currentDistance = (*iterator).SquaredDistance( aPoint );
1696 if( currentDistance < minDistance )
1699 *aNearest = (*iterator).NearestPoint( aPoint );
1701 minDistance = currentDistance;
1719 *aNearest = ( aSegment.
A + aSegment.
B ) / 2;
1725 SEG::ecoord minDistance = (*iterator).SquaredDistance( aSegment );
1727 for( iterator++; iterator && minDistance > 0; iterator++ )
1729 SEG::ecoord currentDistance = (*iterator).SquaredDistance( aSegment );
1731 if( currentDistance < minDistance )
1734 *aNearest = (*iterator).NearestPoint( aSegment );
1736 minDistance = currentDistance;
1741 return minDistance < 0 ? 0 : minDistance;
1752 for(
unsigned int polygonIdx = 0; polygonIdx <
m_polys.size(); polygonIdx++ )
1755 aNearest ? &nearest :
nullptr );
1757 if( currentDistance_sq < minDistance_sq )
1760 *aNearest = nearest;
1762 minDistance_sq = currentDistance_sq;
1766 return minDistance_sq;
1777 for(
unsigned int polygonIdx = 0; polygonIdx <
m_polys.size(); polygonIdx++ )
1780 aNearest ? &nearest :
nullptr );
1782 if( currentDistance_sq < minDistance_sq )
1785 *aNearest = nearest;
1787 minDistance_sq = currentDistance_sq;
1791 return minDistance_sq;
1812 for(
unsigned int idx = 0; idx <
m_polys.size(); idx++ )
1823 for(
size_t idx = 0; idx <
m_polys.size(); idx++ )
1831 unsigned int aDistance,
int aIndex,
int aErrorMax )
1840 if( aDistance == 0 )
1852 for(
int currVertex = 0; currVertex < currContour.PointCount(); currVertex++ )
1855 int x1 = currContour.
CPoint( currVertex ).
x;
1856 int y1 = currContour.CPoint( currVertex ).y;
1865 prevVertex = currVertex == 0 ? currContour.PointCount() - 1 : currVertex - 1;
1868 nextVertex = currVertex == currContour.PointCount() - 1 ? 0 : currVertex + 1;
1871 double xa = currContour.CPoint( prevVertex ).x - x1;
1872 double ya = currContour.CPoint( prevVertex ).y - y1;
1875 double xb = currContour.CPoint( nextVertex ).x - x1;
1876 double yb = currContour.CPoint( nextVertex ).y - y1;
1879 double lena = hypot( xa, ya );
1880 double lenb = hypot( xb, yb );
1883 if( aMode == CORNER_MODE::CHAMFERED )
1897 newContour.
Append( x1 + nx1, y1 + ny1 );
1902 newContour.
Append( x1 + nx2, y1 + ny2 );
1906 double cosine = ( xa * xb + ya * yb ) / ( lena * lenb );
1908 double radius = aDistance;
1909 double denom = sqrt( 2.0 / ( 1 + cosine ) - 1 );
1912 if( std::isinf( denom ) )
1916 if( 0.5 * lena * denom < radius )
1917 radius = 0.5 * lena * denom;
1919 if( 0.5 * lenb * denom < radius )
1920 radius = 0.5 * lenb * denom;
1923 double k = radius / sqrt( .5 * ( 1 - cosine ) );
1924 double lenab = sqrt( ( xa / lena + xb / lenb ) * ( xa / lena + xb / lenb ) +
1925 ( ya / lena + yb / lenb ) * ( ya / lena + yb / lenb ) );
1926 double xc = x1 + k * ( xa / lena + xb / lenb ) / lenab;
1927 double yc = y1 + k * ( ya / lena + yb / lenb ) / lenab;
1930 k = radius / sqrt( 2 / ( 1 + cosine ) - 1 );
1931 double xs = x1 + k * xa / lena - xc;
1932 double ys = y1 + k * ya / lena - yc;
1933 double xe = x1 + k * xb / lenb - xc;
1934 double ye = y1 + k * yb / lenb - yc;
1937 double argument = ( xs * xe + ys * ye ) / ( radius * radius );
1943 else if( argument > 1 )
1946 double arcAngle = acos( argument );
1947 double arcAngleDegrees = arcAngle * 180.0 / M_PI;
1950 double deltaAngle = arcAngle / segments;
1951 double startAngle = atan2( -ys, xs );
1954 if( xa * yb - ya * xb <= 0 )
1957 double nx = xc + xs;
1958 double ny = yc + ys;
1966 for(
int j = 0; j < segments; j++ )
1968 nx = xc + cos( startAngle + ( j + 1 ) * deltaAngle ) * radius;
1969 ny = yc - sin( startAngle + ( j + 1 ) * deltaAngle ) * radius;
1984 newPoly.push_back( newContour );
1993 static_cast<SHAPE&>(*
this) = aOther;
2044 if( w == 0.0 || h == 0.0 )
2047 int n_cells_x, n_cells_y;
2051 n_cells_x = w / aSize;
2052 n_cells_y = floor( h / w * n_cells_x ) + 1;
2056 n_cells_y = h / aSize;
2057 n_cells_x = floor( w / h * n_cells_y ) + 1;
2060 SHAPE_POLY_SET ps1( aPoly ), ps2( aPoly ), maskSetOdd, maskSetEven;
2062 for(
int yy = 0; yy < n_cells_y; yy++ )
2064 for(
int xx = 0; xx < n_cells_x; xx++ )
2068 p.
x = bb.
GetX() + w * xx / n_cells_x;
2069 p.
y = bb.
GetY() + h * yy / n_cells_y;
2073 p2.
x = bb.
GetX() + w * ( xx + 1 ) / n_cells_x;
2074 p2.
y = bb.
GetY() + h * ( yy + 1 ) / n_cells_y;
2082 mask.SetClosed(
true );
2084 if( ( xx ^ yy ) & 1 )
2098 for(
int i = 0; i < ps2.OutlineCount(); i++ )
2154 if( !tess.TesselatePolygon( tmpSet.
Polygon( 0 ).front() ) )
2176 for(
const auto& outline :
m_polys )
2178 hash.
Hash( outline.size() );
2180 for(
const auto& lc : outline )
2182 hash.
Hash( lc.PointCount() );
2184 for(
int i = 0; i < lc.PointCount(); i++ )
2186 hash.
Hash( lc.CPoint( i ).x );
2187 hash.
Hash( lc.CPoint( i ).y );
2214 std::set< long long > ptHashes;
2216 for(
const auto& lc : aPoly )
2218 for(
const VECTOR2I& pt : lc.CPoints() )
2220 const long long ptHash = (
long long) pt.x << 32 | pt.y;
2222 if( ptHashes.count( ptHash ) > 0 )
2227 ptHashes.insert( ptHash );
2246 n += t->GetTriangleCount();
2258 for (
auto& tri : tpoly->Triangles() )
2260 aSubshapes.push_back( &tri );
2272 if( aClearance != 0 )
int TotalVertices() const
Returns total number of vertices stored in the set.
std::vector< SHAPE_LINE_CHAIN > POLYGON
represents a single polygon outline with holes.
void booleanOp(ClipperLib::ClipType aType, const SHAPE_POLY_SET &aOtherShape, POLYGON_MODE aFastMode)
Function booleanOp this is the engine to execute all polygon boolean transforms (AND,...
int NewHole(int aOutline=-1)
Creates a new hole in a given outline
TRIANGULATED_POLYGON * parent
const POLYGON & CPolygon(int aIndex) const
int Distance(const SEG &aSeg) const
Function Distance()
virtual bool HasIndexableSubshapes() const override
int OutlineCount() const
Returns the number of outlines in the set
All angles are chamfered.
bool IsEndContour() const
Function IsEndContour.
void fractureSingle(POLYGON &paths)
void unfractureSingle(POLYGON &path)
void BooleanAdd(const SHAPE_POLY_SET &b, POLYGON_MODE aFastMode)
Performs boolean polyset union For aFastMode meaning, see function booleanOp
const BOX2I BBoxFromCaches() const
const VECTOR2I & CVertex(int aIndex, int aOutline, int aHole) const
Returns the index-th vertex in a given hole outline within a given outline
bool Collide(const SEG &aSeg, int aClearance, int *aActual=nullptr) const
VECTOR2I::extended_type ecoord
CONST_SEGMENT_ITERATOR CIterateSegmentsWithHoles() const
Returns an iterator object, for the aOutline-th outline in the set (with holes)
int NormalizeAreaOutlines()
Function NormalizeAreaOutlines Convert a self-intersecting polygon to one (or more) non self-intersec...
int VertexCount(int aOutline=-1, int aHole=-1) const
Returns the number of vertices in a given outline/hole
bool Parse(std::stringstream &aStream) override
bool HasHoles() const
Returns true if the polygon set has any holes.
CORNER_STRATEGY
< define how inflate transform build inflated polygon
SHAPE_LINE_CHAIN & Hole(int aOutline, int aHole)
Returns the reference to aHole-th hole in the aIndex-th outline
static int processEdge(FractureEdgeSet &edges, FractureEdge *edge)
MD5_HASH checksum() const
SEGMENT_ITERATOR_TEMPLATE.
const SHAPE_LINE_CHAIN & CHole(int aOutline, int aHole) const
void Rotate(double aAngle, const VECTOR2I &aCenter={ 0, 0 }) override
Function Rotate rotates all vertices by a given angle.
const VECTOR2I GetCenter() const
SHAPE_POLY_SET Fillet(int aRadius, int aErrorMax)
Function Fillet returns a filleted version of the polygon set.
bool Contains(const VECTOR2I &aP, int aSubpolyIndex=-1, int aAccuracy=0, bool aUseBBoxCaches=false) const
Returns true if a given subpolygon contains the point aP.
void Inflate(int aAmount, int aCircleSegmentsCount, CORNER_STRATEGY aCornerStrategy=ROUND_ALL_CORNERS)
Performs outline inflation/deflation.
bool m_triangulationValid
bool operator==(const PART_LIB &aLibrary, const wxString &aName)
Case insensitive library name comparison.
int PointCount() const
Function PointCount()
std::vector< std::unique_ptr< TRIANGULATED_POLYGON > > m_triangulatedPolys
static SEG::ecoord Square(int a)
SEG::ecoord SquaredDistance(VECTOR2I aPoint, VECTOR2I *aNearest=nullptr) const
Function SquaredDistance computes the minimum distance squared between aPoint and all the polygons in...
bool PointOnEdge(const VECTOR2I &aP) const
Function PointOnEdge()
VERTEX_INDEX GetIndex()
Function GetIndex.
virtual bool Collide(const VECTOR2I &aP, int aClearance=0, int *aActual=nullptr, VECTOR2I *aLocation=nullptr) const
Function Collide()
bool IsTriangulationUpToDate() const
const SEG & GetSeg() const
void Mirror(bool aX=true, bool aY=false, const VECTOR2I &aRef={ 0, 0 })
Mirrors the line points about y or x (or both)
bool hasTouchingHoles(const POLYGON &aPoly) const
Returns true if the polygon set has any holes that touch share a vertex.
void Append(int aX, int aY, bool aAllowDuplication=false)
Function Append()
bool IsVertexInHole(int aGlobalIdx)
Function IsVertexInHole.
void DeletePolygon(int aIdx)
Deletes aIdx-th polygon from the set
static void partitionPolyIntoRegularCellGrid(const SHAPE_POLY_SET &aPoly, int aSize, SHAPE_POLY_SET &aOut)
bool GetNeighbourIndexes(int aGlobalIndex, int *aPrevious, int *aNext)
Returns the global indexes of the previous and the next corner of the aGlobalIndex-th corner of a con...
void SetVertex(const VERTEX_INDEX &aIndex, const VECTOR2I &aPos)
Function SetVertex Accessor function to set the position of a specific point.
const VECTOR2I & CPoint(int aIndex) const
Function Point()
void SetClosed(bool aClosed)
Function SetClosed()
static constexpr extended_type ECOORD_MAX
void Hash(uint8_t *data, uint32_t length)
SHAPE_POLY_SET & operator=(const SHAPE_POLY_SET &)
Acute angles are rounded.
std::deque< TRI > m_triangles
void Move(const VECTOR2I &aVector) override
bool IsClosed() const override
Function IsClosed()
SHAPE_LINE_CHAIN & Outline(int aIndex)
Returns the reference to aIndex-th outline in the set
coord_type GetWidth() const
bool IsPolygonSelfIntersecting(int aPolygonIndex) const
Function IsPolygonSelfIntersecting.
bool IsAdjacent(SEGMENT_ITERATOR_TEMPLATE< T > aOther)
Function IsAdjacent.
bool PointInside(const VECTOR2I &aPt, int aAccuracy=0, bool aUseBBoxCache=false) const
Function PointInside()
a few functions useful in geometry calculations.
void Simplify(POLYGON_MODE aFastMode)
Simplifies the polyset (merges overlapping polys, eliminates degeneracy/self-intersections) For aFast...
SEG::ecoord SquaredDistanceToPolygon(VECTOR2I aPoint, int aIndex, VECTOR2I *aNearest) const
Function DistanceToPolygon computes the minimum distance between the aIndex-th polygon and aPoint.
static float distance(const SFVEC2UI &a, const SFVEC2UI &b)
BOX2< Vec > & Merge(const BOX2< Vec > &aRect)
Function Merge modifies the position and size of the rectangle in order to contain aRect.
const std::string Format() const override
int RemoveNullSegments()
Function RemoveNullSegments looks for null segments; ie, segments whose ends are exactly the same and...
void BooleanIntersection(const SHAPE_POLY_SET &b, POLYGON_MODE aFastMode)
Performs boolean polyset intersection For aFastMode meaning, see function booleanOp
bool GetRelativeIndices(int aGlobalIdx, VERTEX_INDEX *aRelativeIndices) const
Function GetRelativeIndices.
int NewOutline()
Creates a new empty polygon in the set and returns its index
int HoleCount(int aOutline) const
Returns the number of holes in a given outline
Acute angles are chamfered.
void Fracture(POLYGON_MODE aFastMode)
Converts a set of polygons with holes to a singe outline with "slits"/"fractures" connecting the oute...
int AddHole(const SHAPE_LINE_CHAIN &aHole, int aOutline=-1)
Adds a new hole to the given outline (default: last) and returns its index
POLYGON ChamferPolygon(unsigned int aDistance, int aIndex)
Function Chamfer returns a chamfered version of the aIndex-th polygon.
void BuildBBoxCaches()
Constructs BBoxCaches for Contains(), below.
FractureEdge(bool connected, const VECTOR2I &p1, const VECTOR2I &p2)
bool GetGlobalIndex(VERTEX_INDEX aRelativeIndices, int &aGlobalIdx)
Function GetGlobalIndex computes the global index of a vertex from the relative indices of polygon,...
int AddOutline(const SHAPE_LINE_CHAIN &aOutline)
Adds a new outline to the set and returns its index
bool Collide(const SHAPE *aShape, int aClearance=0, int *aActual=nullptr, VECTOR2I *aLocation=nullptr) const override
Function Collide()
CORNER_MODE
Operations ChamferPolygon and FilletPolygon are computed under the private chamferFillet method; this...
bool CollideEdge(const VECTOR2I &aPoint, VERTEX_INDEX &aClosestVertex, int aClearance=0) const
Function CollideEdge Checks whether aPoint collides with any edge of any of the contours of the polyg...
BOX2< Vec > & Inflate(coord_type dx, coord_type dy)
Function Inflate inflates the rectangle horizontally by dx and vertically by dy.
virtual const BOX2I BBox(int aClearance=0) const override
Function BBox()
TRIANGULATED_POLYGON & operator=(const TRIANGULATED_POLYGON &aOther)
SHAPE_POLY_SET Chamfer(int aDistance)
Function Chamfer returns a chamfered version of the polygon set.
void AddTriangle(int a, int b, int c)
const SEG CSegment(int aIndex) const
Function CSegment()
bool matches(int y) const
bool HasTouchingHoles() const
Returns true if the polygon set has any holes tha share a vertex.
ITERATOR IterateWithHoles()
Function IterateWithHoles.
VECTOR2I::extended_type ecoord
virtual void GetIndexableSubshapes(std::vector< SHAPE * > &aSubshapes) override
void RemoveVertex(int aGlobalIndex)
Function RemoveVertex deletes the aGlobalIndex-th vertex.
unsigned int TriangulatedPolyCount() const
Returns the number of triangulated polygons
POLYGON FilletPolygon(unsigned int aRadius, int aErrorMax, int aIndex)
Function Fillet returns a filleted version of the aIndex-th polygon.
void RemoveAllContours()
Removes all outlines & holes (clears) the polygon set.
T rescale(T aNumerator, T aValue, T aDenominator)
Function rescale()
static bool empty(const wxTextEntryBase *aCtrl)
constexpr ret_type KiROUND(fp_type v)
Round a floating point number to an integer using "round halfway cases away from zero".
POLYGON chamferFilletPolygon(CORNER_MODE aMode, unsigned int aDistance, int aIndex, int aErrorMax)
Function chamferFilletPolygon Returns the camfered or filleted version of the aIndex-th polygon in th...
coord_type GetHeight() const
void InflateWithLinkedHoles(int aFactor, int aCircleSegmentsCount, POLYGON_MODE aFastMode)
Performs outline inflation/deflation, using round corners.
virtual size_t GetIndexableSubshapeCount() const override
void InsertVertex(int aGlobalIndex, VECTOR2I aNewVertex)
Function InsertVertex Adds a vertex in the globally indexed position aGlobalIndex.
void CacheTriangulation(bool aPartition=true)
T EuclideanNorm() const
Destructor.
POLYGON_MODE
operations on polygons use a aFastMode param if aFastMode is PM_FAST (true) the result can be a weak ...
void BooleanSubtract(const SHAPE_POLY_SET &b, POLYGON_MODE aFastMode)
Performs boolean polyset difference For aFastMode meaning, see function booleanOp
POLYGON & Polygon(int aIndex)
Returns the aIndex-th subpolygon in the set
SHAPE * Clone() const override
Function Clone()
bool containsSingle(const VECTOR2I &aP, int aSubpolyIndex, int aAccuracy, bool aUseBBoxCaches=false) const
containsSingle function Checks whether the point aP is inside the aSubpolyIndex-th polygon of the pol...
const BOX2I BBox(int aClearance=0) const override
Function BBox()
just inflate the polygon. Acute angles create spikes
const TRIANGULATED_POLYGON * TriangulatedPolygon(int aIndex) const
int GetArcToSegmentCount(int aRadius, int aErrorMax, double aArcAngleDegree)
SHAPE_TYPE Type() const
Function Type()
bool CollideVertex(const VECTOR2I &aPoint, VERTEX_INDEX &aClosestVertex, int aClearance=0) const
Function CollideVertex Checks whether aPoint collides with any vertex of any of the contours of the p...
bool operator!=(const PART_LIB &aLibrary, const wxString &aName)
CONST_ITERATOR CIterateWithHoles() const
std::vector< FractureEdge * > FractureEdgeSet
SHAPE_POLY_SET Subset(int aFirstPolygon, int aLastPolygon)
Function Subset returns a subset of the polygons in this set, the ones between aFirstPolygon and aLas...
bool IsSelfIntersecting() const
Function IsSelfIntersecting Checks whether any of the polygons in the set is self intersecting.
std::deque< VECTOR2I > m_vertices
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)
void RemoveContour(int aContourIdx, int aPolygonIdx=-1)
Function RemoveContour deletes the aContourIdx-th contour of the aPolygonIdx-th polygon in the set.
void importTree(ClipperLib::PolyTree *tree)
void Unfracture(POLYGON_MODE aFastMode)
Converts a single outline slitted ("fractured") polygon into a set ouf outlines with holes.