28#include <clipper2/clipper.h>
51 int minX, maxX, minY, maxY;
71 for(
size_t i = 0; i < aV.size(); i+= 2 )
96 if( aMaxError.has_value() )
97 Append( aArc, aMaxError.value() );
106 const std::vector<CLIPPER_Z_VALUE>& aZValueBuffer,
107 const std::vector<SHAPE_ARC>& aArcBuffer ) :
113 std::map<ssize_t, ssize_t> loadedArcs;
118 [&]( ssize_t aArcIndex ) -> ssize_t
120 if( aArcIndex == SHAPE_IS_PT )
124 else if( loadedArcs.count( aArcIndex ) == 0 )
126 loadedArcs.insert( { aArcIndex, m_arcs.size() } );
127 m_arcs.push_back( aArcBuffer.at( aArcIndex ) );
130 return loadedArcs.at( aArcIndex );
133 for(
size_t ii = 0; ii < aPath.size(); ++ii )
135 Append( aPath[ii].x, aPath[ii].y );
138 int idx_z = aPath[ii].z;
140 if( idx_z < 0 || idx_z >= (
int)aZValueBuffer.size() )
143 m_shapes[ii].first = loadArc( aZValueBuffer[idx_z].m_FirstArcIdx );
144 m_shapes[ii].second = loadArc( aZValueBuffer[idx_z].m_SecondArcIdx );
149 wxASSERT( m_shapes.size() == m_points.size() );
153 fixIndicesRotation();
158 std::vector<CLIPPER_Z_VALUE>& aZValueBuffer,
159 std::vector<SHAPE_ARC>& aArcBuffer )
const
161 Clipper2Lib::Path64 c_path;
163 bool orientation =
Area(
false ) >= 0;
164 ssize_t shape_offset = aArcBuffer.size();
166 if( orientation != aRequiredOrientation )
172 c_path.reserve( pointCount );
174 for(
int i = 0; i < pointCount; i++ )
179 size_t z_value_ptr = aZValueBuffer.size();
180 aZValueBuffer.push_back( z_value );
182 c_path.emplace_back( vertex.
x, vertex.
y, z_value_ptr );
185 aArcBuffer.insert( aArcBuffer.end(), input.
m_arcs.begin(), input.
m_arcs.end() );
198 size_t rotations = 0;
249 aArcIndex +=
m_arcs.size();
251 if( aArcIndex >=
static_cast<ssize_t
>(
m_arcs.size() ) )
258 [&]( ssize_t& aShapeIndex )
260 if( aShapeIndex == aArcIndex )
263 if( aShapeIndex > aArcIndex )
268 std::swap( sh.first, sh.second );
278 wxCHECK_MSG( aArcIndex <
m_arcs.size(), ,
279 wxT(
"Invalid arc index requested." ) );
288 m_arcs[aArcIndex] = newArc;
303 wxCHECK_MSG( aPtIndex <
static_cast<ssize_t
>(
m_shapes.size() ), ,
304 wxT(
"Invalid point index requested." ) );
308 if( aCoincident || aPtIndex == 0 )
311 ssize_t firstArcIndex =
m_shapes[aPtIndex].first;
315 amendArc( firstArcIndex, newStart, newEnd );
330 ssize_t currArcIdx =
ArcIndex( aPtIndex );
345 if( !aCoincident &&
ArcIndex( aPtIndex - 1 ) != currArcIdx )
348 m_arcs[currArcIdx] = newArc2;
352 m_arcs[currArcIdx] = newArc1;
353 m_arcs.insert(
m_arcs.begin() + currArcIdx + 1, newArc2 );
357 m_shapes[aPtIndex].second = currArcIdx + 1;
362 for(
int i = aPtIndex; i <
PointCount(); i++ )
395 SEG::ecoord dist_sq = ( pn - aP ).SquaredEuclideanNorm();
397 if( dist_sq < closest_dist_sq )
400 closest_dist_sq = dist_sq;
402 if( closest_dist_sq == 0 )
406 if( closest_dist_sq < clearance_sq && !aActual )
411 if( closest_dist_sq == 0 || closest_dist_sq < clearance_sq )
414 *aLocation = nearest;
417 *aActual = sqrt( closest_dist_sq );
452 SEG::ecoord dist_sq = ( pn - aP ).SquaredEuclideanNorm();
454 if( dist_sq < closest_dist_sq )
457 closest_dist_sq = dist_sq;
459 if( closest_dist_sq == 0 )
463 if( closest_dist_sq < clearance_sq && !aActual )
468 if( closest_dist_sq == 0 || closest_dist_sq < clearance_sq )
471 *aLocation = nearest;
474 *aActual = sqrt( closest_dist_sq );
480 for(
size_t i = 0; i <
ArcCount(); i++ )
485 wxASSERT_MSG( arc.
GetWidth() == 0, wxT(
"Invalid arc width - should be zero" ) );
487 if( arc.
Collide( aP, aClearance, aActual, aLocation ) )
501 arc.Rotate( aAngle, aCenter );
508 const std::vector<VECTOR2I>& myPts =
m_points;
509 const std::vector<VECTOR2I>& otherPts = aOther.
m_points;
511 const int c_maxBoxes = 100;
512 const int c_minPtsPerBox = 20;
514 int myPointsPerBox = std::max( c_minPtsPerBox,
int( myPts.size() / c_maxBoxes ) + 1 );
515 int otherPointsPerBox = std::max( c_minPtsPerBox,
int( otherPts.size() / c_maxBoxes ) + 1 );
517 int myNumBoxes = ( myPts.size() + myPointsPerBox - 1 ) / myPointsPerBox;
518 int otherNumBoxes = ( otherPts.size() + otherPointsPerBox - 1 ) / otherPointsPerBox;
528 std::vector<BOX> myBoxes( myNumBoxes );
529 std::vector<BOX> otherBoxes( otherNumBoxes );
532 for(
size_t i = 0; i < myPts.size(); i++ )
535 BOX& box = myBoxes[i / myPointsPerBox];
539 box.bbox.Merge( pt );
548 for(
size_t i = 0; i < otherPts.size(); i++ )
551 BOX& box = otherBoxes[i / otherPointsPerBox];
555 box.bbox.Merge( pt );
565 for( BOX& box : myBoxes )
567 box.center = box.bbox.GetCenter();
568 box.radius = int( box.bbox.GetDiameter() / 2 );
571 for( BOX& box : otherBoxes )
573 box.center = box.bbox.GetCenter();
574 box.radius = int( box.bbox.GetDiameter() / 2 );
580 DIST_PAIR( int64_t aDistSq,
size_t aIdA,
size_t aIdB ) :
581 dist( aDistSq ), idA( aIdA ), idB( aIdB )
590 std::vector<DIST_PAIR> pairsToTest;
592 for(
size_t ia = 0; ia < myBoxes.size(); ia++ )
594 for(
size_t ib = 0; ib < otherBoxes.size(); ib++ )
596 const BOX& ca = myBoxes[ia];
597 const BOX& cb = otherBoxes[ib];
599 if( !ca.valid || !cb.valid )
605 int64_t dist = ( pB - pA ).EuclideanNorm();
610 pairsToTest.emplace_back( dist, ia, ib );
614 std::sort( pairsToTest.begin(), pairsToTest.end(),
615 [](
const DIST_PAIR& a,
const DIST_PAIR& b )
617 return a.dist < b.dist;
620 const int c_polyPairsLimit = 5;
625 for(
size_t pairId = 0; pairId < pairsToTest.size() && pairId < c_polyPairsLimit; pairId++ )
627 const DIST_PAIR& pair = pairsToTest[pairId];
633 size_t myStartId = pair.idA * myPointsPerBox;
634 size_t myEndId = myStartId + myPointsPerBox;
636 if( myEndId > myPts.size() )
637 myEndId = myPts.size();
639 VECTOR2I myPrevPt = myPts[myStartId == 0 ? myPts.size() - 1 : myStartId - 1];
641 size_t otherStartId = pair.idB * otherPointsPerBox;
642 size_t otherEndId = otherStartId + otherPointsPerBox;
644 if( otherEndId > otherPts.size() )
645 otherEndId = otherPts.size();
647 VECTOR2I otherPrevPt = otherPts[otherStartId == 0 ? otherPts.size() - 1 : otherStartId - 1];
649 if(
ClosestSegments( myPrevPt, myPts.begin() + myStartId, myPts.begin() + myEndId,
650 otherPrevPt, otherPts.begin() + otherStartId,
651 otherPts.begin() + otherEndId, ptA, ptB, dist_sq ) )
653 if( dist_sq < total_closest_dist_sq )
655 total_closest_dist_sq = dist_sq;
672 if( aMyStart == aMyEnd )
675 if( aOtherStart == aOtherEnd )
681 for(
point_citer itA = aMyStart; itA != aMyEnd; itA++ )
686 for(
point_citer itB = aOtherStart; itB != aOtherEnd; itB++ )
690 SEG segA( lastPtA, ptA );
691 SEG segB( lastPtB, ptB );
697 if( segA.
NearestPoints( segB, nearestA, nearestB, dist_sq ) )
699 if( dist_sq < closest_dist_sq )
701 closest_dist_sq = dist_sq;
713 aDistSq = closest_dist_sq;
724 for(
point_citer itA = aMyStart; itA != aMyEnd; itA++ )
728 for(
point_citer itB = aOtherStart; itB != aOtherEnd; itB++ )
737 if( dist_sq < closest_dist_sq )
739 closest_dist_sq = dist_sq;
746 aDistSq = closest_dist_sq;
757 aOther.
m_points.cend(), aPt0, aPt1, dist_sq );
784 if( dist_sq < closest_dist_sq )
789 closest_dist_sq = dist_sq;
791 if( closest_dist_sq == 0)
795 if( closest_dist_sq < clearance_sq && !aActual )
800 if( closest_dist_sq == 0 || closest_dist_sq < clearance_sq )
803 *aLocation = nearest;
806 *aActual = sqrt( closest_dist_sq );
842 if( dist_sq < closest_dist_sq )
847 closest_dist_sq = dist_sq;
849 if( closest_dist_sq == 0 )
853 if( closest_dist_sq < clearance_sq && !aActual )
858 if( closest_dist_sq == 0 || closest_dist_sq < clearance_sq )
861 *aLocation = nearest;
864 *aActual = sqrt( closest_dist_sq );
869 int dist = std::numeric_limits<int>::max();
870 SEG::ecoord closest_dist = sqrt( closest_dist_sq );
873 for(
size_t i = 0; i <
ArcCount(); i++ )
879 wxASSERT_MSG( arc.
GetWidth() == 0, wxT(
"Invalid arc width - should be zero" ) );
881 if( arc.
Collide( aSeg, aClearance, aActual || aLocation ? &dist :
nullptr,
882 aLocation ? &pos :
nullptr ) )
887 if( dist < closest_dist )
895 if( closest_dist == 0 || closest_dist < aClearance )
898 *aLocation = nearest;
901 *aActual = closest_dist;
923 [&]( ssize_t& aShapeIndex )
926 aShapeIndex = a.
m_arcs.size() - aShapeIndex - 1;
935 std::swap( sh.first, sh.second );
951 for( ssize_t arcIndex =
m_arcs.size() - 1; arcIndex >= 0; --arcIndex )
967 for(
size_t i = 0; i <
ArcCount(); i++ )
968 l +=
CArcs()[i].GetLength();
979 pt.x = -pt.x + 2 * aRef.
x;
981 pt.y = -pt.y + 2 * aRef.
y;
985 arc.Mirror( aRef, aFlipDirection );
1001 Remove( aStartIndex, aEndIndex );
1002 Insert( aStartIndex, aP );
1012 if( aStartIndex < 0 )
1016 wxASSERT( aStartIndex <= aEndIndex );
1017 wxASSERT( aEndIndex <
static_cast<int>(
m_points.size() ) );
1024 Remove( aStartIndex, aEndIndex );
1037 Remove( aStartIndex, aEndIndex );
1048 Remove( aStartIndex, aEndIndex );
1055 size_t prev_arc_count =
m_arcs.size();
1056 std::vector<std::pair<ssize_t, ssize_t>> new_shapes = newLine.
m_shapes;
1058 for( std::pair<ssize_t, ssize_t>& shape_pair : new_shapes )
1061 [&]( ssize_t& aShape )
1064 aShape += prev_arc_count;
1068 m_shapes.insert(
m_shapes.begin() + aStartIndex, new_shapes.begin(), new_shapes.end() );
1089 if( aStartIndex < 0 )
1112 if( aStartIndex > aEndIndex )
1118 std::set<size_t> extra_arcs;
1119 auto logArcIdxRemoval = [&]( ssize_t& aShapeIndex )
1122 extra_arcs.insert( aShapeIndex );
1126 for(
int i = aStartIndex; i <= aEndIndex; i++ )
1130 if( i == aStartIndex )
1132 logArcIdxRemoval(
m_shapes[i].second );
1139 else if( i == aEndIndex )
1141 logArcIdxRemoval(
m_shapes[i].first );
1144 assert( i > aStartIndex || (
IsSharedPt( i - 1 )
1156 for(
auto arc : extra_arcs )
1186 int found_index =
Find( aP );
1188 if( found_index >= 0 && aExact )
1198 if( dist < min_dist && seg.
A != aP && seg.
B != aP )
1201 if( found_index < 0 )
1203 else if( s < found_index )
1217 size_t newIndex =
static_cast<size_t>( ii ) + 1;
1222 m_shapes.insert(
m_shapes.begin() + newIndex, { ArcIndex( ii ), SHAPE_IS_PT } );
1241 if( aThreshold == 0 )
1248 if( (
CPoint( s ) - aP).EuclideanNorm() <= aThreshold )
1271 wxCHECK2_MSG(
m_points.size() ==
m_shapes.size(),
return 0,
"Invalid chain!" );
1292 wxCHECK( aIndex < segCount && aIndex >= 0,
1304 if( aPointIndex < 0 )
1307 if( aPointIndex < 0 )
1313 if( aPointIndex >= lastIndex )
1318 if( aPointIndex == lastIndex - 1 )
1327 return aPointIndex + 1;
1331 int arcStart = aPointIndex;
1335 wxCHECK2_MSG(
m_shapes[aPointIndex].first !=
SHAPE_IS_PT,
return -1,
"malformed chain!" );
1337 ssize_t currentArcIdx =
ArcIndex( aPointIndex );
1340 while( aPointIndex < lastIndex &&
ArcIndex( aPointIndex ) == currentArcIdx )
1347 if( aPointIndex - arcStart > 1 && !indexStillOnArc )
1350 if( aPointIndex == lastIndex )
1372 [&]( ssize_t& aIdx )
1382 if( aPointIndex < 0 )
1385 if( aPointIndex >=
PointCount() || aPointIndex < 0 )
1394 int start = aPointIndex;
1395 int end = aPointIndex;
1396 int arcIdx =
ArcIndex( aPointIndex );
1401 while( start > 0 &&
ArcIndex(
static_cast<ssize_t
>( start ) - 1 ) == arcIdx )
1425 if( aStartIndex < 0 )
1435 int numPoints =
static_cast<int>(
PointCount() );
1440 ssize_t arcToSplitIndex =
ArcIndex( aStartIndex );
1444 for(
int i = aStartIndex; i < aEndIndex && arcToSplitIndex ==
ArcIndex( i ); i++ )
1458 rv.
m_arcs.push_back( newArc );
1463 for(
int i = aStartIndex; i <= aEndIndex && i < numPoints; i =
NextShape( i ) )
1469 bool isLastShape = nextShape < 0;
1473 if( ( isLastShape && aEndIndex != ( numPoints - 1 ) )
1474 || ( nextShape > aEndIndex ) )
1476 if( i == aEndIndex )
1488 for( ; i <= aEndIndex && i < numPoints; i++ )
1505 rv.
m_arcs.push_back( newArc );
1513 rv.
Append( currentArc, aMaxError );
1521 wxASSERT_MSG( !
IsArcSegment( i ), wxT(
"Still on an arc segment, we missed something..." ) );
1523 if( i == aStartIndex )
1526 bool nextPointIsArc = isLastShape ? false :
IsArcSegment( nextShape );
1528 if( !nextPointIsArc && i <
SegmentCount() && i < aEndIndex )
1548 size_t num_arcs =
m_arcs.size();
1551 auto fixShapeIndices =
1552 [&](
const std::pair<ssize_t, ssize_t>& aShapeIndices ) -> std::pair<ssize_t, ssize_t>
1554 std::pair<ssize_t, ssize_t> retval = aShapeIndices;
1559 aIndex = aIndex + num_arcs;
1582 for(
int i = 1; i < aOtherLine.
PointCount(); i++ )
1587 ssize_t arcIndex = aOtherLine.
ArcIndex( i );
1615 if(
chain.PointCount() > 2 )
1617 chain.m_arcs.push_back( aArc );
1618 chain.m_arcs.back().SetWidth( 0 );
1620 for(
auto& sh :
chain.m_shapes )
1638 wxCHECK( aVertex <
m_points.size(), );
1640 if( aVertex > 0 &&
IsPtOnArc( aVertex ) )
1659 wxCHECK( aVertex <
m_points.size(), );
1661 if( aVertex > 0 &&
IsPtOnArc( aVertex ) )
1665 ssize_t arc_pos =
m_arcs.size();
1667 for(
auto arc_it =
m_shapes.rbegin() ;
1668 arc_it !=
m_shapes.rend() + aVertex;
1673 arc_pos = std::max( ( *arc_it ).first, ( *arc_it ).second );
1682 [&]( ssize_t& aIndex )
1684 if( aIndex >= arc_pos )
1700 std::vector<std::pair<ssize_t, ssize_t>> new_points(
chain.PointCount(),
1701 { arc_pos, SHAPE_IS_PT } );
1703 m_shapes.insert(
m_shapes.begin() + aVertex, new_points.begin(), new_points.end() );
1727 const int ptCount =
static_cast<int>(
m_points.size() );
1729 const int segMinX = std::min( aSeg.
A.
x, aSeg.
B.
x );
1730 const int segMaxX = std::max( aSeg.
A.
x, aSeg.
B.
x );
1731 const int segMinY = std::min( aSeg.
A.
y, aSeg.
B.
y );
1732 const int segMaxY = std::max( aSeg.
A.
y, aSeg.
B.
y );
1734 for(
int s = 0; s < segCount; s++ )
1739 if( std::max( ptA.
x, ptB.
x ) < segMinX || std::min( ptA.
x, ptB.
x ) > segMaxX
1740 || std::max( ptA.
y, ptB.
y ) < segMinY || std::min( ptA.
y, ptB.
y ) > segMaxY )
1755 aIp.push_back( is );
1760 sort( aIp.begin(), aIp.end(),
comp );
1769 const int ptCount =
static_cast<int>(
m_points.size() );
1771 const int segMinX = std::min( aSeg.
A.
x, aSeg.
B.
x );
1772 const int segMaxX = std::max( aSeg.
A.
x, aSeg.
B.
x );
1773 const int segMinY = std::min( aSeg.
A.
y, aSeg.
B.
y );
1774 const int segMaxY = std::max( aSeg.
A.
y, aSeg.
B.
y );
1776 for(
int s = 0; s < segCount; s++ )
1781 if( std::max( ptA.
x, ptB.
x ) < segMinX || std::min( ptA.
x, ptB.
x ) > segMaxX
1782 || std::max( ptA.
y, ptB.
y ) < segMinY || std::min( ptA.
y, ptB.
y ) > segMaxY )
1796 bool aExcludeColinearAndTouching,
BOX2I* aChainBBox )
const
1801 if( ourSegCount == 0 || theirSegCount == 0 )
1805 const int ourPtCount =
static_cast<int>(
m_points.size() );
1806 const int theirPtCount =
static_cast<int>( aChain.
CPoints().size() );
1807 const std::vector<VECTOR2I>& theirPts = aChain.
CPoints();
1809 thread_local std::vector<SEG> theirSegs;
1810 thread_local std::vector<SEG_EXTENT> sorted;
1812 theirSegs.resize( theirSegCount );
1813 sorted.resize( theirSegCount );
1816 for(
int i = 0; i < theirSegCount; i++ )
1819 const VECTOR2I& pb = theirPts[i + 1 < theirPtCount ? i + 1 : 0];
1820 theirSegs[i] =
SEG( pa, pb, i );
1824 for(
int i = 0; i < theirSegCount; i++ )
1826 const SEG& s = theirSegs[i];
1827 sorted[i] = { std::min( s.
A.
x, s.
B.
x ), std::max( s.
A.
x, s.
B.
x ),
1828 std::min( s.
A.
y, s.
B.
y ), std::max( s.
A.
y, s.
B.
y ), i };
1831 std::sort( sorted.begin(), sorted.end(),
1832 [](
const SEG_EXTENT& a,
const SEG_EXTENT& b ) { return a.minX < b.minX; } );
1834 for(
int s1 = 0; s1 < ourSegCount; s1++ )
1839 const int ourMinX = std::min( a1.
x, b1.
x );
1840 const int ourMaxX = std::max( a1.
x, b1.
x );
1841 const int ourMinY = std::min( a1.
y, b1.
y );
1842 const int ourMaxY = std::max( a1.
y, b1.
y );
1844 if( ourMaxX < bbOther.m_Left || ourMinX > bbOther.
m_Right
1845 || ourMaxY < bbOther.m_Top || ourMinY > bbOther.
m_Bottom )
1850 const SEG a( a1, b1, s1 );
1854 auto rightEnd = std::upper_bound( sorted.begin(), sorted.end(), ourMaxX,
1855 [](
int val,
const SEG_EXTENT& e )
1857 return val < e.minX;
1860 for(
auto jt = sorted.begin(); jt != rightEnd; ++jt )
1862 if( jt->maxX < ourMinX || jt->maxY < ourMinY || jt->minY > ourMaxY )
1865 const SEG& b = theirSegs[jt->segIdx];
1876 if( !aExcludeColinearAndTouching && a.
Collinear( b ) )
1882 aIp.push_back( is );
1890 aIp.push_back( is );
1897 aIp.push_back( is );
1905 aIp.push_back( is );
1936 aIp.push_back( is );
1952 bool indexMatch =
false;
1962 indexMatch = ( i == aIndex );
1968 sum += ( aP - seg.
A ).EuclideanNorm();
1986 const int pointCount =
static_cast<int>(
m_points.size() );
1993 bool inside =
false;
1995 for(
int i = 0; i < pointCount; )
1998 const VECTOR2I& p2 = pts[i == pointCount ? 0 : i];
2004 const int d =
rescale( diff.
x, ( aPt.
y - p1.
y ), diff.
y );
2006 if( ( ( p1.
y >= aPt.
y ) != ( p2.
y >= aPt.
y ) ) && ( aPt.
x - p1.
x < d ) )
2010 if( aAccuracy <= 1 )
2018 bool aUseBBoxCache )
const
2042 bool inside =
false;
2044 for(
int i = 0; i < pointCount; )
2053 const int d =
rescale( diff.
x, ( aPt.
y - p1.
y ), diff.
y );
2055 if( ( ( p1.
y >= aPt.
y ) != ( p2.
y >= aPt.
y ) ) && ( aPt.
x - p1.
x < d ) )
2061 if( aAccuracy <= 1 )
2076 const int threshold = aAccuracy + 1;
2077 const int64_t thresholdSq = int64_t( threshold ) * threshold;
2084 else if( pointCount == 1 )
2087 return distSq <= thresholdSq ? 0 : -1;
2092 for(
size_t i = 0; i < segCount; i++ )
2096 if( s.
A == aPt || s.
B == aPt )
2112 return m_points[0].Distance( aP ) <= aDist;
2118 if( s.
A == aP || s.
B == aP )
2132 const int ptCount =
static_cast<int>(
m_points.size() );
2136 return std::optional<INTERSECTION>();
2139 auto endIdx = [ptCount](
int i )
2145 for(
int s1 = 0; s1 < segCount; s1++ )
2151 const int s1MinX = std::min( a1.
x, b1.
x ) - 2;
2152 const int s1MaxX = std::max( a1.
x, b1.
x ) + 2;
2153 const int s1MinY = std::min( a1.
y, b1.
y ) - 2;
2154 const int s1MaxY = std::max( a1.
y, b1.
y ) + 2;
2156 for(
int s2 = s1 + 1; s2 < segCount; s2++ )
2161 const int s2MinX = std::min( a2.
x, b2.
x );
2162 const int s2MaxX = std::max( a2.
x, b2.
x );
2164 if( s1MaxX < s2MinX || s2MaxX < s1MinX )
2167 const int s2MinY = std::min( a2.
y, b2.
y );
2168 const int s2MaxY = std::max( a2.
y, b2.
y );
2170 if( s1MaxY < s2MinY || s2MaxY < s1MinY )
2173 const SEG seg1( a1, b1, s1 );
2175 if( s1 + 1 != s2 && seg1.
Contains( a2 ) )
2187 !( closed && s1 == 0 && s2 == segCount - 1 ) )
2211 return std::optional<INTERSECTION>();
2228const std::optional<SHAPE_LINE_CHAIN::INTERSECTION>
2231 auto pointsClose = [](
const VECTOR2I& aPt1,
const VECTOR2I& aPt2 ) ->
bool
2233 return (
VECTOR2D( aPt1 ) - aPt2 ).SquaredEuclideanNorm() <= 2.0;
2236 auto collideArcSeg = [&pointsClose](
const SHAPE_ARC& aArc,
const SEG& aSeg,
int aClearance = 0,
2242 std::vector<VECTOR2I> candidatePts =
circle.Intersect( aSeg );
2244 for(
const VECTOR2I& candidate : candidatePts )
2247 if( aArc.
GetP1() == aSeg.A && pointsClose( candidate, aSeg.A ) )
2250 if( aSeg.B == aArc.
GetP0() && pointsClose( candidate, aSeg.B ) )
2253 bool collides = aArc.
Collide( candidate, aClearance,
nullptr, aLocation );
2265 std::vector<VECTOR2I> candidatePts;
2267 aArc1.
Intersect( aArc2, &candidatePts );
2269 for(
const VECTOR2I& candidate : candidatePts )
2272 if( aArc1.
GetP1() == aArc2.GetP0() && pointsClose( candidate, aArc1.
GetP1() ) )
2275 if( aArc2.GetP1() == aArc1.
GetP0() && pointsClose( candidate, aArc2.GetP1() ) )
2279 *aLocation = candidate;
2287 auto collideSegSeg = [
this](
int s1,
int s2,
INTERSECTION& is )
2294 if( s1 + 1 != s2 && seg1.
Contains( s2a ) )
2297 is.index_their = s2;
2308 is.index_their = s2;
2319 is.index_their = s2;
2330 std::vector<SHAPE_KEY> shapeCache;
2331 for(
int si = 0; si != -1; si =
NextShape( si ) )
2335 shapeCache.emplace_back( si, arci,
2340 for(
size_t sk1 = 0; sk1 < shapeCache.size(); sk1++ )
2342 for(
size_t sk2 = sk1 + 1; sk2 < shapeCache.size(); sk2++ )
2391 return std::optional<SHAPE_LINE_CHAIN::INTERSECTION>();
2396 bool aAllowInternalShapePoints )
const
2404 int min_d = std::numeric_limits<int>::max();
2418 if( !aAllowInternalShapePoints )
2441 return nearestArc.
GetP1();
2443 return nearestArc.
GetP0();
2463 dist = std::numeric_limits<int>::max();
2476 return CPoint( nearest );
2482 int min_d = std::numeric_limits<int>::max();
2502 std::stringstream ss;
2504 ss <<
"SHAPE_LINE_CHAIN( { ";
2514 ss <<
"}, " << (
m_closed ?
"true" :
"false" );
2530 bool aCyclicalCompare,
2531 int aEpsilon )
const
2537 if( a.m_points.size() != b.
m_points.size() )
2540 if( aCyclicalCompare )
2542 std::vector<VECTOR2I> aVerts = a.m_points;
2543 std::vector<VECTOR2I> bVerts = b.
m_points;
2545 auto centroid = [](
const std::vector<VECTOR2I>& pts )
2547 double sx = 0.0, sy = 0.0;
2548 for(
const auto& p : pts )
2553 return std::pair<double, double>( sx / pts.size(), sy / pts.size() );
2556 auto aC = centroid( aVerts );
2557 auto bC = centroid( bVerts );
2560 [](
const std::pair<double, double>& c,
const VECTOR2I& p1,
const VECTOR2I& p2 )
2562 double a1 = atan2( p1.y - c.second, p1.x - c.first );
2563 double a2 = atan2( p2.y - c.second, p2.x - c.first );
2568 std::sort( aVerts.begin(), aVerts.end(),
2571 return angleCmp( aC, p1, p2 );
2574 std::sort( bVerts.begin(), bVerts.end(),
2577 return angleCmp( bC, p1, p2 );
2580 for(
size_t i = 0; i < aVerts.size(); i++ )
2582 if( abs( aVerts[i].x - bVerts[i].x ) > aEpsilon
2583 || abs( aVerts[i].y - bVerts[i].y ) > aEpsilon )
2590 for(
int i = 0; i < a.PointCount(); i++ )
2592 if( abs( a.CPoint( i ).x - b.
CPoint( i ).
x ) > aEpsilon
2593 || abs( a.CPoint( i ).y - b.
CPoint( i ).
y ) > aEpsilon )
2626 if( n_pts > aStream.str().size() )
2632 if( n_arcs > aStream.str().size() )
2635 for(
size_t i = 0; i < n_pts; i++ )
2647 for(
size_t i = 0; i < n_arcs; i++ )
2669 if( aPathLength == 0 )
2677 if( total + l >= aPathLength )
2680 return s.
A + d.
Resize( aPathLength - total );
2700 for(
int i = 0, j = size - 1; i < size; ++i )
2708 return std::fabs( area * 0.5 );
2716 std::vector<VECTOR2I> pts_unique;
2717 std::vector<std::pair<ssize_t, ssize_t>> shapes_unique;
2748 std::pair<ssize_t,ssize_t> shapeToKeep =
m_shapes[i];
2753 assert( shapeToKeep.first <
static_cast<int>(
m_arcs.size() ) );
2754 assert( shapeToKeep.second <
static_cast<int>(
m_arcs.size() ) );
2756 pts_unique.push_back(
CPoint( i ) );
2757 shapes_unique.push_back( shapeToKeep );
2765 for(
size_t ii = 0; ii < pts_unique.size(); ++ii )
2767 const VECTOR2I p0 = pts_unique[ii];
2770 m_shapes.push_back( shapes_unique[ii] );
2781 std::vector<VECTOR2I> new_points;
2782 std::vector<std::pair<ssize_t, ssize_t>> new_shapes;
2784 new_points.reserve(
m_points.size() );
2785 new_shapes.reserve(
m_shapes.size() );
2787 for(
size_t start_idx = 0; start_idx <
m_points.size(); )
2789 new_points.push_back(
m_points[start_idx] );
2790 new_shapes.push_back(
m_shapes[start_idx] );
2797 size_t end_idx = ( start_idx + 2 ) %
m_points.size();
2798 bool can_simplify =
true;
2800 while( can_simplify && end_idx != start_idx && ( end_idx > start_idx ||
m_closed ) )
2803 for(
size_t test_idx = ( start_idx + 1 ) %
m_points.size();
2804 test_idx != end_idx;
2805 test_idx = ( test_idx + 1 ) %
m_points.size() )
2812 can_simplify =
false;
2819 can_simplify =
false;
2827 end_idx = ( end_idx + 1 ) %
m_points.size();
2832 if( end_idx == ( start_idx + 2 ) %
m_points.size() )
2839 size_t new_start_idx = ( end_idx +
m_points.size() - 1 ) %
m_points.size();
2842 if( new_start_idx <= start_idx )
2845 start_idx = new_start_idx;
2850 if( new_points.size() == 1 )
2852 new_points.push_back(
m_points.back() );
2853 new_shapes.push_back(
m_shapes.back() );
2860 new_points.push_back(
m_points.back() );
2861 new_shapes.push_back(
m_shapes.back() );
2866 m_points = std::move( new_points );
2867 m_shapes = std::move( new_shapes );
2883 int i_start = l.
Find( m );
2884 int i_end = l.
Find( n );
2886 if( i_start > i_end )
2889 i_start = l.
Find( m );
2890 i_end = l.
Find( n );
2893 aPre = l.
Slice( 0, i_start );
2894 aPost = l.
Slice( i_end, -1 );
2895 aMid = l.
Slice( i_start, i_end );
2902 std::vector<VECTOR2I> pts_unique;
2903 std::vector<std::pair<ssize_t, ssize_t>> shapes_unique;
2936 std::pair<ssize_t,ssize_t> shapeToKeep =
m_shapes[i];
2941 assert( shapeToKeep.first <
static_cast<int>(
m_arcs.size() ) );
2942 assert( shapeToKeep.second <
static_cast<int>(
m_arcs.size() ) );
2944 pts_unique.push_back(
CPoint( i ) );
2945 shapes_unique.push_back( shapeToKeep );
2952 np = pts_unique.size();
2966 && (
SEG( p0, pts_unique[n + 2] ).LineDistance( pts_unique[n + 1] ) <= 1
2967 ||
SEG( p0, pts_unique[n + 2] ).Collinear(
SEG( p0, pts_unique[n + 1] ) ) ) )
2972 m_shapes.push_back( shapes_unique[i] );
2979 m_points.push_back( pts_unique[np - 1] );
2980 m_shapes.push_back( shapes_unique[np - 1] );
2989 m_points.push_back( pts_unique[np - 2] );
2990 m_shapes.push_back( shapes_unique[np - 2] );
2993 m_points.push_back( pts_unique[np - 1] );
2994 m_shapes.push_back( shapes_unique[np - 1] );
3003 bool aSimplify )
const
3009 poly.
OffsetLineChain( *
this, aAmount, aCornerStrategy, aMaxError, aSimplify );
3027 outline.
Split( start,
true );
3030 const int idA = outline.
Find( start );
3031 const int idB = outline.
Find(
end );
3033 if( idA == -1 || idB == -1 )
3039 for(
int i = idA;; )
3058 for(
int i = idB;; )
3077 if( aLeft.
CPoint( 0 ) != start )
3080 wxASSERT( aLeft.
CPoint( 0 ) == start );
3083 if( aRight.
CPoint( 0 ) != start )
3086 wxASSERT( aRight.
CPoint( 0 ) == start );
3090 int sideLeft = base.
Side( aLeft.
CPoint( 1 ) );
3091 int sideRight = base.
Side( aRight.
CPoint( 1 ) );
3093 if( sideLeft == 0 || sideRight == 0 )
3096 if( sideLeft == sideRight )
3099 if( sideLeft > 0 && sideRight < 0 )
3100 std::swap( aLeft, aRight );
3168 if( ( d > 0 ) == ( ipNext.
y > ip.
y ) )
3186 if( ( d > 0 ) == ( ipNext.
y > ip.
y ) )
3206 for(
int i = 1; i < aPolyline.
PointCount(); i++ )
3208 auto p = aPolyline.
CPoint( i );
3247 size_t nextIdx = aSegment + 1;
3249 if( nextIdx >
m_shapes.size() - 1 )
3278 size_t prevIndex = aIndex - 1;
3282 else if( aIndex >
m_points.size() -1 )
ERROR_LOC
When approximating an arc or circle, should the error be placed on the outside or inside of the curve...
constexpr BOX2< Vec > & Merge(const BOX2< Vec > &aRect)
Modify the position and size of the rectangle in order to contain aRect.
Represent basic circle geometry with utility geometry functions.
const VECTOR2I ReflectPoint(const VECTOR2I &aP) const
Reflect a point using this segment as axis.
int LineDistance(const VECTOR2I &aP, bool aDetermineSide=false) const
Return the closest Euclidean distance between point aP and the line defined by the ends of segment (t...
ecoord SquaredDistance(const SEG &aSeg) const
VECTOR2I::extended_type ecoord
const VECTOR2I NearestPoint(const VECTOR2I &aP) const
Compute a point on the segment (this) that is closest to point aP.
int Length() const
Return the length (this).
OPT_VECTOR2I Intersect(const SEG &aSeg, bool aIgnoreEndpoints=false, bool aLines=false) const
Compute intersection point of segment (this) with segment aSeg.
static SEG::ecoord Square(int a)
bool Collinear(const SEG &aSeg) const
Check if segment aSeg lies on the same line as (this).
bool NearestPoints(const SEG &aSeg, VECTOR2I &aPtA, VECTOR2I &aPtB, int64_t &aDistSq) const
Compute closest points between this segment and aSeg.
int Distance(const SEG &aSeg) const
Compute minimum Euclidean distance to segment aSeg.
bool Contains(const SEG &aSeg) const
int Side(const VECTOR2I &aP) const
Determine on which side of directed line passing via segment ends point aP lies.
int GetWidth() const override
const SHAPE_LINE_CHAIN ConvertToPolyline(int aMaxError=DefaultAccuracyForPCB(), int *aActualError=nullptr) const
Construct a SHAPE_LINE_CHAIN of segments from a given arc.
int Intersect(const CIRCLE &aArc, std::vector< VECTOR2I > *aIpsBuffer) const
Find intersection points between this arc and a CIRCLE.
SHAPE_ARC & ConstructFromStartEndCenter(const VECTOR2I &aStart, const VECTOR2I &aEnd, const VECTOR2I &aCenter, bool aClockwise=false, double aWidth=0)
Constructs this arc from the given start, end and center.
const VECTOR2I & GetP1() const
bool Collide(const SEG &aSeg, int aClearance=0, int *aActual=nullptr, VECTOR2I *aLocation=nullptr) const override
Check if the boundary of shape (this) lies closer to the segment aSeg than aClearance,...
static int DefaultAccuracyForPCB()
const VECTOR2I & GetP0() const
void SetWidth(int aWidth) override
const VECTOR2I & GetCenter() const
POINT_INSIDE_TRACKER(const VECTOR2I &aPoint)
bool processVertex(const VECTOR2I &ip, const VECTOR2I &ipNext)
void AddPolyline(const SHAPE_LINE_CHAIN &aPolyline)
virtual bool Collide(const VECTOR2I &aP, int aClearance=0, int *aActual=nullptr, VECTOR2I *aLocation=nullptr) const override
Check if point aP lies closer to us than aClearance.
bool PointOnEdge(const VECTOR2I &aP, int aAccuracy=0) const
Check if point aP lies on an edge or vertex of the line chain.
int EdgeContainingPoint(const VECTOR2I &aP, int aAccuracy=0) const
Check if point aP lies on an edge or vertex of the line chain.
virtual size_t GetPointCount() const =0
SHAPE_LINE_CHAIN_BASE(SHAPE_TYPE aType)
virtual size_t GetSegmentCount() const =0
virtual const VECTOR2I GetPoint(int aIndex) const =0
virtual BOX2I * GetCachedBBox() const
bool PointInside(const VECTOR2I &aPt, int aAccuracy=0, bool aUseBBoxCache=false) const override
Check if point aP lies inside a closed shape.
virtual bool IsClosed() const =0
virtual const SEG GetSegment(int aIndex) const =0
SEG::ecoord SquaredDistance(const VECTOR2I &aP, bool aOutlineOnly=false) const override
std::vector< std::pair< ssize_t, ssize_t > > m_shapes
Array of indices that refer to the index of the shape if the point is part of a larger shape,...
const SHAPE_LINE_CHAIN Reverse() const
Reverse point order in the line chain.
bool IsPtOnArc(size_t aPtIndex) const
const SHAPE_ARC & Arc(size_t aArc) const
void splitArc(ssize_t aPtIndex, bool aCoincident=false)
Splits an arc into two arcs at aPtIndex.
const std::optional< INTERSECTION > SelfIntersecting() const
Check if the line chain is self-intersecting.
bool Parse(std::stringstream &aStream) override
bool CheckClearance(const VECTOR2I &aP, const int aDist) const
Check if point aP is closer to (or on) an edge or vertex of the line chain.
std::vector< SHAPE_ARC > m_arcs
int Distance(const VECTOR2I &aP, bool aOutlineOnly) const
bool IsClosed() const override
virtual const VECTOR2I GetPoint(int aIndex) const override
void SetPoint(int aIndex, const VECTOR2I &aPos)
Move a point to a specific location.
const VECTOR2I PointAlong(int aPathLength) const
int Split(const VECTOR2I &aP, bool aExact=false)
Insert the point aP belonging to one of the our segments, splitting the adjacent segment in two.
void fixIndicesRotation()
Fix indices of this chain to ensure arcs are not split between the end and start indices.
std::vector< VECTOR2I > m_points
array of vertices
int FindSegment(const VECTOR2I &aP, int aThreshold=1) const
Search for segment containing point aP.
int ShapeCount() const
Return the number of shapes (line segments or arcs) in this line chain.
void SetClosed(bool aClosed)
Mark the line chain as closed (i.e.
int Intersect(const SEG &aSeg, INTERSECTIONS &aIp) const
Find all intersection points between our line chain and the segment aSeg.
SHAPE_LINE_CHAIN()
Initialize an empty line chain.
int m_width
Width of the segments (for BBox calculations in RTree) TODO Adjust usage of SHAPE_LINE_CHAIN to accou...
int PointCount() const
Return the number of points (vertices) in this line chain.
bool IsArcEnd(size_t aIndex) const
void Replace(int aStartIndex, int aEndIndex, const VECTOR2I &aP)
Replace points with indices in range [start_index, end_index] with a single point aP.
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.
virtual bool Collide(const VECTOR2I &aP, int aClearance=0, int *aActual=nullptr, VECTOR2I *aLocation=nullptr) const override
Check if point aP lies closer to us than aClearance.
void ClearArcs()
Remove all arc references in the line chain, resulting in a chain formed only of straight segments.
void mergeFirstLastPointIfNeeded()
Merge the first and last point if they are the same and this chain is closed.
ssize_t ArcIndex(size_t aSegment) const
Return the arc index for the given segment index.
void Clear()
Remove all points from the line chain.
void Simplify(int aTolerance=0)
Simplify the line chain by removing colinear adjacent segments and duplicate vertices.
SEG Segment(int aIndex) const
Return a copy of the aIndex-th segment in the line chain.
BOX2I m_bbox
cached bounding box
BOX2I * GetCachedBBox() const override
bool m_closed
is the line chain closed?
friend class SHAPE_POLY_SET
const std::vector< SHAPE_ARC > & CArcs() const
const std::optional< INTERSECTION > SelfIntersectingWithArcs() const
Check if the line chain is self-intersecting.
bool Intersects(const SEG &aSeg) const
int NearestSegment(const VECTOR2I &aP) const
Find the segment nearest the given point.
int NextShape(int aPointIndex) const
Return the vertex index of the next shape in the chain, or -1 if aPointIndex is the last shape.
double Area(bool aAbsolute=true) const
Return the area of this chain.
SHAPE_LINE_CHAIN & Simplify2(bool aRemoveColinear=true)
void amendArc(size_t aArcIndex, const VECTOR2I &aNewStart, const VECTOR2I &aNewEnd)
bool ClosestPoints(const SHAPE_LINE_CHAIN &aOther, VECTOR2I &aPt0, VECTOR2I &aPt1) const
Finds closest points between this and the other line chain.
void Append(int aX, int aY, bool aAllowDuplication=false)
Append a new point at the end of the line chain.
void Rotate(const EDA_ANGLE &aAngle, const VECTOR2I &aCenter={ 0, 0 }) override
Rotate all vertices by a given angle.
virtual const SEG GetSegment(int aIndex) const override
const VECTOR2I & CPoint(int aIndex) const
Return a reference to a given point in the line chain.
const std::vector< std::pair< ssize_t, ssize_t > > & CShapes() const
bool CompareGeometry(const SHAPE_LINE_CHAIN &aOther, bool aCyclicalCompare=false, int aEpsilon=0) const
Compare this line chain with another one.
const VECTOR2I NearestPoint(const VECTOR2I &aP, bool aAllowInternalShapePoints=true) const
Find a point on the line chain that is closest to point aP.
const SHAPE_LINE_CHAIN Slice(int aStartIndex, int aEndIndex) const
Return a subset of this line chain containing the [start_index, end_index] range of points.
int SegmentCount() const
Return the number of segments in this line chain.
int PathLength(const VECTOR2I &aP, int aIndex=-1) const
Compute the walk path length from the beginning of the line chain and the point aP belonging to our l...
const VECTOR2I & CLastPoint() const
Return the last point in the line chain.
void Mirror(const VECTOR2I &aRef, FLIP_DIRECTION aFlipDirection)
Mirror the line points about y or x (or both).
bool ClosestSegmentsFast(const SHAPE_LINE_CHAIN &aOther, VECTOR2I &aPt0, VECTOR2I &aPt1) const
Finds closest points between segments of this and the other line chain.
const std::string Format(bool aCplusPlus=true) const override
static bool ClosestSegments(const VECTOR2I &aMyPrevPt, const point_citer &aMyStart, const point_citer &aMyEnd, const VECTOR2I &aOtherPrevPt, const point_citer &aOtherStart, const point_citer &aOtherEnd, VECTOR2I &aPt0, VECTOR2I &aPt1, int64_t &aDistSq)
Clipper2Lib::Path64 convertToClipper2(bool aRequiredOrientation, std::vector< CLIPPER_Z_VALUE > &aZValueBuffer, std::vector< SHAPE_ARC > &aArcBuffer) const
Create a new Clipper2 path from the SHAPE_LINE_CHAIN in a given orientation.
static const std::pair< ssize_t, ssize_t > SHAPES_ARE_PT
void convertArc(ssize_t aArcIndex)
Convert an arc to only a point chain by removing the arc and references.
virtual size_t GetSegmentCount() const override
void Remove(int aStartIndex, int aEndIndex)
Remove the range of points [start_index, end_index] from the line chain.
void RemoveDuplicatePoints()
Remove the duplicate points from the line chain.
const SEG CSegment(int aIndex) const
Return a constant copy of the aIndex segment in the line chain.
bool IsArcSegment(size_t aSegment) const
void RemoveShape(int aPointIndex)
Remove the shape at the given index from the line chain.
void Insert(size_t aVertex, const VECTOR2I &aP)
bool IsArcStart(size_t aIndex) const
bool IsSharedPt(size_t aIndex) const
Test if a point is shared between multiple shapes.
bool PointInside(const VECTOR2I &aPt, int aAccuracy=0, bool aUseBBoxCache=false) const override
Check if point aP lies inside a closed shape.
std::vector< INTERSECTION > INTERSECTIONS
long long int Length() const
Return length of the line chain in Euclidean metric.
int Find(const VECTOR2I &aP, int aThreshold=0) const
Search for point aP.
const std::vector< VECTOR2I > & CPoints() const
const BOX2I BBox(int aClearance=0) const override
Compute a bounding box of the shape, with a margin of aClearance a collision.
std::vector< VECTOR2I >::const_iterator point_citer
SHAPE * Clone() const override
Return a dynamically allocated copy of the shape.
static const ssize_t SHAPE_IS_PT
bool OffsetLine(int aAmount, CORNER_STRATEGY aCornerStrategy, int aMaxError, SHAPE_LINE_CHAIN &aLeft, SHAPE_LINE_CHAIN &aRight, bool aSimplify=false) const
Creates line chains aLeft and aRight offset to this line chain.
bool HasHoles() const
Return true if the polygon set has any holes.
int AddOutline(const SHAPE_LINE_CHAIN &aOutline)
Adds a new outline to the set and returns its index.
void OffsetLineChain(const SHAPE_LINE_CHAIN &aLine, int aAmount, CORNER_STRATEGY aCornerStrategy, int aMaxError, bool aSimplify)
Perform offsetting of a line chain.
int OutlineCount() const
Return the number of outlines in the set.
const SHAPE_LINE_CHAIN & COutline(int aIndex) const
An abstract shape on 2D plane.
VECTOR2I::extended_type ecoord
SHAPE(SHAPE_TYPE aType)
Create an empty shape of type aType.
virtual int GetWidth() const
constexpr extended_type SquaredDistance(const VECTOR2< T > &aVector) const
Compute the squared distance between two vectors.
static constexpr extended_type ECOORD_MAX
T EuclideanNorm() const
Compute the Euclidean norm of the vector, which is defined as sqrt(x ** 2 + y ** 2).
VECTOR2< T > Resize(T aNewLength) const
Return a vector of the same direction, but length specified in aNewLength.
CORNER_STRATEGY
define how inflate transform build inflated polygon
@ LEFT_RIGHT
Flip left to right (around the Y axis)
bool pair_contains(const std::pair< _Type, _Type > __pair, _Value __value)
Returns true if either of the elements in an std::pair contains the given value.
void run_on_pair(std::pair< _Type, _Type > &__pair, _Function __f)
Apply a function to the first and second element of a std::pair.
std::optional< VECTOR2I > OPT_VECTOR2I
@ SH_LINE_CHAIN
line chain (polyline)
int getArcPolygonizationMaxError()
std::vector< FAB_LAYER_COLOR > dummy
A min-max version of BOX2 for fast intersection checking.
bool Intersects(const BOX2I_MINMAX &aOther) const
Holds information on each point of a SHAPE_LINE_CHAIN that is retrievable after an operation with Cli...
SHAPE_KEY(int aFirstIdx, int aArcIdx, const BOX2I_MINMAX &aBBox)
Represent an intersection between two line segments.
bool is_corner_their
When true, the corner [index_their] of the 'their' line lies exactly on 'our' line.
bool is_corner_our
When true, the corner [index_our] of the 'our' line lies exactly on 'their' line.
int index_our
Index of the intersecting corner/segment in the 'our' (== this) line.
VECTOR2I p
Point of intersection between our and their.
bool valid
Auxiliary flag to avoid copying intersection info to intersection refining code, used by the refining...
int index_their
index of the intersecting corner/segment in the 'their' (Intersect() method parameter) line.
bool operator()(const SHAPE_LINE_CHAIN::INTERSECTION &aA, const SHAPE_LINE_CHAIN::INTERSECTION &aB) const
compareOriginDistance(const VECTOR2I &aOrigin)
const SHAPE_LINE_CHAIN chain
SHAPE_CIRCLE circle(c.m_circle_center, c.m_circle_radius)
bool TestSegmentHit(const VECTOR2I &aRefPoint, const VECTOR2I &aStart, const VECTOR2I &aEnd, int aDist)
Test if aRefPoint is with aDistance on the line defined by aStart and aEnd.
void RotatePoint(int *pX, int *pY, const EDA_ANGLE &aAngle)
Calculate the new point of coord coord pX, pY, for a rotation center 0, 0.
T rescale(T aNumerator, T aValue, T aDenominator)
Scale a number (value) by rational (numerator/denominator).
VECTOR2< int32_t > VECTOR2I
VECTOR2< double > VECTOR2D
VECTOR2< int64_t > VECTOR2L