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() ) )
255 for( std::pair<ssize_t, ssize_t>& sh :
m_shapes )
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++ )
365 [&]( ssize_t& aIndex )
396 SEG::ecoord dist_sq = ( pn - aP ).SquaredEuclideanNorm();
398 if( dist_sq < closest_dist_sq )
401 closest_dist_sq = dist_sq;
403 if( closest_dist_sq == 0 )
407 if( closest_dist_sq < clearance_sq && !aActual )
412 if( closest_dist_sq == 0 || closest_dist_sq < clearance_sq )
415 *aLocation = nearest;
418 *aActual = sqrt( closest_dist_sq );
453 SEG::ecoord dist_sq = ( pn - aP ).SquaredEuclideanNorm();
455 if( dist_sq < closest_dist_sq )
458 closest_dist_sq = dist_sq;
460 if( closest_dist_sq == 0 )
464 if( closest_dist_sq < clearance_sq && !aActual )
469 if( closest_dist_sq == 0 || closest_dist_sq < clearance_sq )
472 *aLocation = nearest;
475 *aActual = sqrt( closest_dist_sq );
481 for(
size_t i = 0; i <
ArcCount(); i++ )
486 wxASSERT_MSG( arc.
GetWidth() == 0, wxT(
"Invalid arc width - should be zero" ) );
488 if( arc.
Collide( aP, aClearance, aActual, aLocation ) )
502 arc.Rotate( aAngle, aCenter );
509 const std::vector<VECTOR2I>& myPts =
m_points;
510 const std::vector<VECTOR2I>& otherPts = aOther.
m_points;
512 const int c_maxBoxes = 100;
513 const int c_minPtsPerBox = 20;
515 int myPointsPerBox = std::max( c_minPtsPerBox,
int( myPts.size() / c_maxBoxes ) + 1 );
516 int otherPointsPerBox = std::max( c_minPtsPerBox,
int( otherPts.size() / c_maxBoxes ) + 1 );
518 int myNumBoxes = ( myPts.size() + myPointsPerBox - 1 ) / myPointsPerBox;
519 int otherNumBoxes = ( otherPts.size() + otherPointsPerBox - 1 ) / otherPointsPerBox;
529 std::vector<BOX> myBoxes( myNumBoxes );
530 std::vector<BOX> otherBoxes( otherNumBoxes );
533 for(
size_t i = 0; i < myPts.size(); i++ )
536 BOX& box = myBoxes[i / myPointsPerBox];
540 box.bbox.Merge( pt );
549 for(
size_t i = 0; i < otherPts.size(); i++ )
552 BOX& box = otherBoxes[i / otherPointsPerBox];
556 box.bbox.Merge( pt );
566 for( BOX& box : myBoxes )
568 box.center = box.bbox.GetCenter();
569 box.radius = int( box.bbox.GetDiameter() / 2 );
572 for( BOX& box : otherBoxes )
574 box.center = box.bbox.GetCenter();
575 box.radius = int( box.bbox.GetDiameter() / 2 );
581 DIST_PAIR( int64_t aDistSq,
size_t aIdA,
size_t aIdB ) :
582 dist( aDistSq ), idA( aIdA ), idB( aIdB )
591 std::vector<DIST_PAIR> pairsToTest;
593 for(
size_t ia = 0; ia < myBoxes.size(); ia++ )
595 for(
size_t ib = 0; ib < otherBoxes.size(); ib++ )
597 const BOX& ca = myBoxes[ia];
598 const BOX& cb = otherBoxes[ib];
600 if( !ca.valid || !cb.valid )
606 int64_t dist = ( pB - pA ).EuclideanNorm();
611 pairsToTest.emplace_back( dist, ia, ib );
615 std::sort( pairsToTest.begin(), pairsToTest.end(),
616 [](
const DIST_PAIR& a,
const DIST_PAIR& b )
618 return a.dist < b.dist;
621 const int c_polyPairsLimit = 5;
626 for(
size_t pairId = 0; pairId < pairsToTest.size() && pairId < c_polyPairsLimit; pairId++ )
628 const DIST_PAIR& pair = pairsToTest[pairId];
634 size_t myStartId = pair.idA * myPointsPerBox;
635 size_t myEndId = myStartId + myPointsPerBox;
637 if( myEndId > myPts.size() )
638 myEndId = myPts.size();
640 VECTOR2I myPrevPt = myPts[myStartId == 0 ? myPts.size() - 1 : myStartId - 1];
642 size_t otherStartId = pair.idB * otherPointsPerBox;
643 size_t otherEndId = otherStartId + otherPointsPerBox;
645 if( otherEndId > otherPts.size() )
646 otherEndId = otherPts.size();
648 VECTOR2I otherPrevPt = otherPts[otherStartId == 0 ? otherPts.size() - 1 : otherStartId - 1];
650 if(
ClosestSegments( myPrevPt, myPts.begin() + myStartId, myPts.begin() + myEndId,
651 otherPrevPt, otherPts.begin() + otherStartId,
652 otherPts.begin() + otherEndId, ptA, ptB, dist_sq ) )
654 if( dist_sq < total_closest_dist_sq )
656 total_closest_dist_sq = dist_sq;
673 if( aMyStart == aMyEnd )
676 if( aOtherStart == aOtherEnd )
682 for(
point_citer itA = aMyStart; itA != aMyEnd; itA++ )
687 for(
point_citer itB = aOtherStart; itB != aOtherEnd; itB++ )
691 SEG segA( lastPtA, ptA );
692 SEG segB( lastPtB, ptB );
698 if( segA.
NearestPoints( segB, nearestA, nearestB, dist_sq ) )
700 if( dist_sq < closest_dist_sq )
702 closest_dist_sq = dist_sq;
714 aDistSq = closest_dist_sq;
725 for(
point_citer itA = aMyStart; itA != aMyEnd; itA++ )
729 for(
point_citer itB = aOtherStart; itB != aOtherEnd; itB++ )
738 if( dist_sq < closest_dist_sq )
740 closest_dist_sq = dist_sq;
747 aDistSq = closest_dist_sq;
758 aOther.
m_points.cend(), aPt0, aPt1, dist_sq );
785 if( dist_sq < closest_dist_sq )
790 closest_dist_sq = dist_sq;
792 if( closest_dist_sq == 0)
796 if( closest_dist_sq < clearance_sq && !aActual )
801 if( closest_dist_sq == 0 || closest_dist_sq < clearance_sq )
804 *aLocation = nearest;
807 *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 = (int) sqrt( closest_dist_sq );
869 int dist = std::numeric_limits<int>::max();
870 SEG::ecoord closest_dist = std::numeric_limits<int>::max();
874 closest_dist =
KiROUND( sqrt( closest_dist_sq ) );
877 for(
size_t i = 0; i <
ArcCount(); i++ )
883 wxASSERT_MSG( arc.
GetWidth() == 0, wxT(
"Invalid arc width - should be zero" ) );
885 if( arc.
Collide( aSeg, aClearance, aActual || aLocation ? &dist :
nullptr,
886 aLocation ? &pos :
nullptr ) )
891 if( dist < closest_dist )
899 if( closest_dist == 0 || closest_dist < aClearance )
902 *aLocation = nearest;
905 *aActual = (int) closest_dist;
922 for( std::pair<ssize_t, ssize_t>& sh : a.
m_shapes )
927 [&]( ssize_t& aShapeIndex )
930 aShapeIndex = a.
m_arcs.size() - aShapeIndex - 1;
939 std::swap( sh.first, sh.second );
955 for( ssize_t arcIndex =
m_arcs.size() - 1; arcIndex >= 0; --arcIndex )
971 for(
size_t i = 0; i <
ArcCount(); i++ )
972 l +=
CArcs()[i].GetLength();
983 pt.x = -pt.x + 2 * aRef.
x;
985 pt.y = -pt.y + 2 * aRef.
y;
989 arc.Mirror( aRef, aFlipDirection );
1005 Remove( aStartIndex, aEndIndex );
1006 Insert( aStartIndex, aP );
1016 if( aStartIndex < 0 )
1020 wxASSERT( aStartIndex <= aEndIndex );
1021 wxASSERT( aEndIndex <
static_cast<int>(
m_points.size() ) );
1028 Remove( aStartIndex, aEndIndex );
1041 Remove( aStartIndex, aEndIndex );
1052 Remove( aStartIndex, aEndIndex );
1059 size_t prev_arc_count =
m_arcs.size();
1060 std::vector<std::pair<ssize_t, ssize_t>> new_shapes = newLine.
m_shapes;
1062 for( std::pair<ssize_t, ssize_t>& shape_pair : new_shapes )
1065 [&]( ssize_t& aShape )
1068 aShape += prev_arc_count;
1072 m_shapes.insert(
m_shapes.begin() + aStartIndex, new_shapes.begin(), new_shapes.end() );
1092 if( aStartIndex < 0 )
1115 if( aStartIndex > aEndIndex )
1121 std::set<size_t> extra_arcs;
1122 auto logArcIdxRemoval = [&]( ssize_t& aShapeIndex )
1125 extra_arcs.insert( aShapeIndex );
1129 for(
int i = aStartIndex; i <= aEndIndex; i++ )
1133 if( i == aStartIndex )
1135 logArcIdxRemoval(
m_shapes[i].second );
1142 else if( i == aEndIndex )
1144 logArcIdxRemoval(
m_shapes[i].first );
1147 assert( i > aStartIndex || (
IsSharedPt( i - 1 )
1159 for(
size_t arc : extra_arcs )
1189 int found_index =
Find( aP );
1191 if( found_index >= 0 && aExact )
1201 if( dist < min_dist && seg.
A != aP && seg.
B != aP )
1204 if( found_index < 0 )
1206 else if( s < found_index )
1220 size_t newIndex =
static_cast<size_t>( ii ) + 1;
1225 m_shapes.insert(
m_shapes.begin() + newIndex, { ArcIndex( ii ), SHAPE_IS_PT } );
1244 if( aThreshold == 0 )
1251 if( (
CPoint( s ) - aP).EuclideanNorm() <= aThreshold )
1274 wxCHECK2_MSG(
m_points.size() ==
m_shapes.size(),
return 0,
"Invalid chain!" );
1296 :
SEG( 0, 0, 0, 0 ) );
1307 if( aPointIndex < 0 )
1310 if( aPointIndex < 0 )
1316 if( aPointIndex >= lastIndex )
1321 if( aPointIndex == lastIndex - 1 )
1330 return aPointIndex + 1;
1334 int arcStart = aPointIndex;
1338 wxCHECK2_MSG(
m_shapes[aPointIndex].first !=
SHAPE_IS_PT,
return -1,
"malformed chain!" );
1340 ssize_t currentArcIdx =
ArcIndex( aPointIndex );
1343 while( aPointIndex < lastIndex &&
ArcIndex( aPointIndex ) == currentArcIdx )
1350 if( aPointIndex - arcStart > 1 && !indexStillOnArc )
1353 if( aPointIndex == lastIndex )
1375 [&]( ssize_t& aIdx )
1385 if( aPointIndex < 0 )
1388 if( aPointIndex >=
PointCount() || aPointIndex < 0 )
1397 int start = aPointIndex;
1398 int end = aPointIndex;
1399 int arcIdx =
ArcIndex( aPointIndex );
1404 while( start > 0 &&
ArcIndex(
static_cast<ssize_t
>( start ) - 1 ) == arcIdx )
1428 if( aStartIndex < 0 )
1438 int numPoints =
static_cast<int>(
PointCount() );
1442 if( aStartIndex == aEndIndex )
1449 ssize_t arcToSplitIndex =
ArcIndex( aStartIndex );
1453 for(
int i = aStartIndex; i <= aEndIndex && arcToSplitIndex ==
ArcIndex( i ); i++ )
1470 rv.
m_arcs.push_back( newArc );
1475 for(
int i = aStartIndex; i <= aEndIndex && i < numPoints; i =
NextShape( i ) )
1481 bool isLastShape = nextShape < 0;
1485 if( ( isLastShape && aEndIndex != ( numPoints - 1 ) )
1486 || ( nextShape > aEndIndex ) )
1488 if( i == aEndIndex )
1500 for( ; i <= aEndIndex && i < numPoints; i++ )
1517 rv.
m_arcs.push_back( newArc );
1525 rv.
Append( currentArc, aMaxError );
1533 wxASSERT_MSG( !
IsArcSegment( i ), wxT(
"Still on an arc segment, we missed something..." ) );
1535 if( i == aStartIndex )
1538 bool nextPointIsArc = isLastShape ? false :
IsArcSegment( nextShape );
1540 if( !nextPointIsArc && i <
SegmentCount() && i < aEndIndex )
1560 size_t num_arcs =
m_arcs.size();
1563 auto fixShapeIndices =
1564 [&](
const std::pair<ssize_t, ssize_t>& aShapeIndices ) -> std::pair<ssize_t, ssize_t>
1566 std::pair<ssize_t, ssize_t> retval = aShapeIndices;
1571 aIndex = aIndex + num_arcs;
1594 for(
int i = 1; i < aOtherLine.
PointCount(); i++ )
1599 ssize_t arcIndex = aOtherLine.
ArcIndex( i );
1625 if(
chain.PointCount() > 2 )
1627 chain.m_arcs.push_back( aArc );
1628 chain.m_arcs.back().SetWidth( 0 );
1630 for(
auto& sh :
chain.m_shapes )
1648 wxCHECK( aVertex <
m_points.size(), );
1650 if( aVertex > 0 &&
IsPtOnArc( aVertex ) )
1669 wxCHECK( aVertex <
m_points.size(), );
1671 if( aVertex > 0 &&
IsPtOnArc( aVertex ) )
1675 ssize_t arc_pos =
m_arcs.size();
1677 for(
auto arc_it =
m_shapes.rbegin() ;
1678 arc_it !=
m_shapes.rend() + aVertex;
1683 arc_pos = std::max( ( *arc_it ).first, ( *arc_it ).second );
1689 for( std::pair<ssize_t, ssize_t>& sh :
m_shapes )
1692 [&]( ssize_t& aIndex )
1694 if( aIndex >= arc_pos )
1710 std::vector<std::pair<ssize_t, ssize_t>> new_points(
chain.PointCount(), { arc_pos, SHAPE_IS_PT } );
1712 m_shapes.insert(
m_shapes.begin() + aVertex, new_points.begin(), new_points.end() );
1736 const int ptCount =
static_cast<int>(
m_points.size() );
1738 const int segMinX = std::min( aSeg.
A.
x, aSeg.
B.
x );
1739 const int segMaxX = std::max( aSeg.
A.
x, aSeg.
B.
x );
1740 const int segMinY = std::min( aSeg.
A.
y, aSeg.
B.
y );
1741 const int segMaxY = std::max( aSeg.
A.
y, aSeg.
B.
y );
1743 for(
int s = 0; s < segCount; s++ )
1748 if( std::max( ptA.
x, ptB.
x ) < segMinX || std::min( ptA.
x, ptB.
x ) > segMaxX
1749 || std::max( ptA.
y, ptB.
y ) < segMinY || std::min( ptA.
y, ptB.
y ) > segMaxY )
1764 aIp.push_back( is );
1769 sort( aIp.begin(), aIp.end(),
comp );
1778 const int ptCount =
static_cast<int>(
m_points.size() );
1780 const int segMinX = std::min( aSeg.
A.
x, aSeg.
B.
x );
1781 const int segMaxX = std::max( aSeg.
A.
x, aSeg.
B.
x );
1782 const int segMinY = std::min( aSeg.
A.
y, aSeg.
B.
y );
1783 const int segMaxY = std::max( aSeg.
A.
y, aSeg.
B.
y );
1785 for(
int s = 0; s < segCount; s++ )
1790 if( std::max( ptA.
x, ptB.
x ) < segMinX || std::min( ptA.
x, ptB.
x ) > segMaxX
1791 || std::max( ptA.
y, ptB.
y ) < segMinY || std::min( ptA.
y, ptB.
y ) > segMaxY )
1805 bool aExcludeColinearAndTouching,
BOX2I* aChainBBox )
const
1810 if( ourSegCount == 0 || theirSegCount == 0 )
1814 const int ourPtCount =
static_cast<int>(
m_points.size() );
1815 const int theirPtCount =
static_cast<int>( aChain.
CPoints().size() );
1816 const std::vector<VECTOR2I>& theirPts = aChain.
CPoints();
1818 thread_local std::vector<SEG> theirSegs;
1819 thread_local std::vector<SEG_EXTENT> sorted;
1821 theirSegs.resize( theirSegCount );
1822 sorted.resize( theirSegCount );
1825 for(
int i = 0; i < theirSegCount; i++ )
1828 const VECTOR2I& pb = theirPts[i + 1 < theirPtCount ? i + 1 : 0];
1829 theirSegs[i] =
SEG( pa, pb, i );
1833 for(
int i = 0; i < theirSegCount; i++ )
1835 const SEG& s = theirSegs[i];
1836 sorted[i] = { std::min( s.
A.
x, s.
B.
x ), std::max( s.
A.
x, s.
B.
x ),
1837 std::min( s.
A.
y, s.
B.
y ), std::max( s.
A.
y, s.
B.
y ), i };
1840 std::sort( sorted.begin(), sorted.end(),
1841 [](
const SEG_EXTENT& a,
const SEG_EXTENT& b )
1843 return a.minX < b.minX;
1846 for(
int s1 = 0; s1 < ourSegCount; s1++ )
1851 const int ourMinX = std::min( a1.
x, b1.
x );
1852 const int ourMaxX = std::max( a1.
x, b1.
x );
1853 const int ourMinY = std::min( a1.
y, b1.
y );
1854 const int ourMaxY = std::max( a1.
y, b1.
y );
1856 if( ourMaxX < bbOther.m_Left || ourMinX > bbOther.
m_Right
1857 || ourMaxY < bbOther.m_Top || ourMinY > bbOther.
m_Bottom )
1862 const SEG a( a1, b1, s1 );
1866 auto rightEnd = std::upper_bound( sorted.begin(), sorted.end(), ourMaxX,
1867 [](
int val,
const SEG_EXTENT& e )
1869 return val < e.minX;
1872 for(
auto jt = sorted.begin(); jt != rightEnd; ++jt )
1874 if( jt->maxX < ourMinX || jt->maxY < ourMinY || jt->minY > ourMaxY )
1877 const SEG& b = theirSegs[jt->segIdx];
1888 if( !aExcludeColinearAndTouching && a.
Collinear( b ) )
1894 aIp.push_back( is );
1902 aIp.push_back( is );
1909 aIp.push_back( is );
1917 aIp.push_back( is );
1948 aIp.push_back( is );
1964 bool indexMatch =
false;
1971 indexMatch = ( i == aIndex );
1976 sum += ( aP - seg.
A ).EuclideanNorm();
1994 const int pointCount =
static_cast<int>(
m_points.size() );
2001 bool inside =
false;
2003 for(
int i = 0; i < pointCount; )
2006 const VECTOR2I& p2 = pts[i == pointCount ? 0 : i];
2012 const int d =
rescale( diff.
x, ( aPt.
y - p1.
y ), diff.
y );
2014 if( ( ( p1.
y >= aPt.
y ) != ( p2.
y >= aPt.
y ) ) && ( aPt.
x - p1.
x < d ) )
2018 if( aAccuracy <= 1 )
2049 bool inside =
false;
2051 for(
int i = 0; i < pointCount; )
2060 const int d =
rescale( diff.
x, ( aPt.
y - p1.
y ), diff.
y );
2062 if( ( ( p1.
y >= aPt.
y ) != ( p2.
y >= aPt.
y ) ) && ( aPt.
x - p1.
x < d ) )
2068 if( aAccuracy <= 1 )
2083 const int threshold = aAccuracy + 1;
2084 const int64_t thresholdSq = int64_t( threshold ) * threshold;
2091 else if( pointCount == 1 )
2094 return distSq <= thresholdSq ? 0 : -1;
2099 for(
size_t i = 0; i < segCount; i++ )
2103 if( s.
A == aPt || s.
B == aPt )
2119 return m_points[0].Distance( aP ) <= aDist;
2125 if( s.
A == aP || s.
B == aP )
2139 const int ptCount =
static_cast<int>(
m_points.size() );
2143 return std::optional<INTERSECTION>();
2153 for(
int s1 = 0; s1 < segCount; s1++ )
2159 const int s1MinX = std::min( a1.
x, b1.
x ) - 2;
2160 const int s1MaxX = std::max( a1.
x, b1.
x ) + 2;
2161 const int s1MinY = std::min( a1.
y, b1.
y ) - 2;
2162 const int s1MaxY = std::max( a1.
y, b1.
y ) + 2;
2164 for(
int s2 = s1 + 1; s2 < segCount; s2++ )
2169 const int s2MinX = std::min( a2.
x, b2.
x );
2170 const int s2MaxX = std::max( a2.
x, b2.
x );
2172 if( s1MaxX < s2MinX || s2MaxX < s1MinX )
2175 const int s2MinY = std::min( a2.
y, b2.
y );
2176 const int s2MaxY = std::max( a2.
y, b2.
y );
2178 if( s1MaxY < s2MinY || s2MaxY < s1MinY )
2181 const SEG seg1( a1, b1, s1 );
2183 if( s1 + 1 != s2 && seg1.
Contains( a2 ) )
2195 && !( closed && s1 == 0 && s2 == segCount - 1 ) )
2219 return std::optional<INTERSECTION>();
2238const std::optional<SHAPE_LINE_CHAIN::INTERSECTION>
2244 return (
VECTOR2D( aPt1 ) - aPt2 ).SquaredEuclideanNorm() <= 2.0;
2247 auto collideArcSeg =
2248 [&pointsClose](
const SHAPE_ARC& aArc,
const SEG& aSeg,
int aClearance = 0,
VECTOR2I* aLocation = nullptr )
2253 std::vector<VECTOR2I> candidatePts =
circle.Intersect( aSeg );
2255 for(
const VECTOR2I& candidate : candidatePts )
2258 if( aArc.
GetP1() == aSeg.A && pointsClose( candidate, aSeg.A ) )
2261 if( aSeg.B == aArc.
GetP0() && pointsClose( candidate, aSeg.B ) )
2264 bool collides = aArc.
Collide( candidate, aClearance,
nullptr, aLocation );
2273 auto collideArcArc =
2276 std::vector<VECTOR2I> candidatePts;
2278 aArc1.
Intersect( aArc2, &candidatePts );
2280 for(
const VECTOR2I& candidate : candidatePts )
2283 if( aArc1.
GetP1() == aArc2.GetP0() && pointsClose( candidate, aArc1.
GetP1() ) )
2286 if( aArc2.GetP1() == aArc1.
GetP0() && pointsClose( candidate, aArc2.GetP1() ) )
2290 *aLocation = candidate;
2298 auto collideSegSeg =
2306 if( s1 + 1 != s2 && seg1.
Contains( s2a ) )
2309 is.index_their = s2;
2320 is.index_their = s2;
2331 is.index_their = s2;
2342 std::vector<SHAPE_KEY> shapeCache;
2344 for(
int si = 0; si != -1; si =
NextShape( si ) )
2352 for(
size_t sk1 = 0; sk1 < shapeCache.size(); sk1++ )
2354 for(
size_t sk2 = sk1 + 1; sk2 < shapeCache.size(); sk2++ )
2401 return std::optional<SHAPE_LINE_CHAIN::INTERSECTION>();
2413 int min_d = std::numeric_limits<int>::max();
2427 if( !aAllowInternalShapePoints )
2450 return nearestArc.
GetP1();
2452 return nearestArc.
GetP0();
2472 dist = std::numeric_limits<int>::max();
2485 return CPoint( nearest );
2491 int min_d = std::numeric_limits<int>::max();
2511 std::stringstream ss;
2513 ss <<
"SHAPE_LINE_CHAIN( { ";
2523 ss <<
"}, " << (
m_closed ?
"true" :
"false" );
2539 int aEpsilon )
const
2545 if( a.m_points.size() != b.
m_points.size() )
2548 if( aCyclicalCompare )
2550 std::vector<VECTOR2I> aVerts = a.m_points;
2551 std::vector<VECTOR2I> bVerts = b.
m_points;
2554 [](
const std::vector<VECTOR2I>& pts )
2556 double sx = 0.0, sy = 0.0;
2557 for(
const auto& p : pts )
2562 return std::pair<double, double>( sx / pts.size(), sy / pts.size() );
2565 std::pair<double, double> aC = centroid( aVerts );
2566 std::pair<double, double> bC = centroid( bVerts );
2569 [](
const std::pair<double, double>& c,
const VECTOR2I& p1,
const VECTOR2I& p2 )
2571 double a1 = atan2( p1.y - c.second, p1.x - c.first );
2572 double a2 = atan2( p2.y - c.second, p2.x - c.first );
2577 std::sort( aVerts.begin(), aVerts.end(),
2580 return angleCmp( aC, p1, p2 );
2583 std::sort( bVerts.begin(), bVerts.end(),
2586 return angleCmp( bC, p1, p2 );
2589 for(
size_t i = 0; i < aVerts.size(); i++ )
2591 if( abs( aVerts[i].x - bVerts[i].x ) > aEpsilon
2592 || abs( aVerts[i].y - bVerts[i].y ) > aEpsilon )
2601 for(
int i = 0; i < a.PointCount(); i++ )
2603 if( abs( a.CPoint( i ).x - b.
CPoint( i ).
x ) > aEpsilon
2604 || abs( a.CPoint( i ).y - b.
CPoint( i ).
y ) > aEpsilon )
2619 std::vector<INTERSECTION>
dummy;
2639 if( n_pts > aStream.str().size() )
2645 if( n_arcs > aStream.str().size() )
2648 for(
size_t i = 0; i < n_pts; i++ )
2660 for(
size_t i = 0; i < n_arcs; i++ )
2682 if( aPathLength == 0 )
2690 if( total + l >= aPathLength )
2693 return s.
A + d.
Resize( aPathLength - total );
2713 for(
int i = 0, j = size - 1; i < size; ++i )
2721 return std::fabs( area * 0.5 );
2729 std::vector<VECTOR2I> pts_unique;
2730 std::vector<std::pair<ssize_t, ssize_t>> shapes_unique;
2760 std::pair<ssize_t,ssize_t> shapeToKeep =
m_shapes[i];
2765 assert( shapeToKeep.first <
static_cast<int>(
m_arcs.size() ) );
2766 assert( shapeToKeep.second <
static_cast<int>(
m_arcs.size() ) );
2768 pts_unique.push_back(
CPoint( i ) );
2769 shapes_unique.push_back( shapeToKeep );
2777 for(
size_t ii = 0; ii < pts_unique.size(); ++ii )
2779 const VECTOR2I p0 = pts_unique[ii];
2782 m_shapes.push_back( shapes_unique[ii] );
2793 std::vector<VECTOR2I> new_points;
2794 std::vector<std::pair<ssize_t, ssize_t>> new_shapes;
2796 new_points.reserve(
m_points.size() );
2797 new_shapes.reserve(
m_shapes.size() );
2799 for(
size_t start_idx = 0; start_idx <
m_points.size(); )
2801 new_points.push_back(
m_points[start_idx] );
2802 new_shapes.push_back(
m_shapes[start_idx] );
2809 size_t end_idx = ( start_idx + 2 ) %
m_points.size();
2810 bool can_simplify =
true;
2812 while( can_simplify && end_idx != start_idx && ( end_idx > start_idx ||
m_closed ) )
2815 for(
size_t test_idx = ( start_idx + 1 ) %
m_points.size();
2816 test_idx != end_idx;
2817 test_idx = ( test_idx + 1 ) %
m_points.size() )
2824 can_simplify =
false;
2831 can_simplify =
false;
2839 end_idx = ( end_idx + 1 ) %
m_points.size();
2844 if( end_idx == ( start_idx + 2 ) %
m_points.size() )
2851 size_t new_start_idx = ( end_idx +
m_points.size() - 1 ) %
m_points.size();
2854 if( new_start_idx <= start_idx )
2857 start_idx = new_start_idx;
2862 if( new_points.size() == 1 )
2864 new_points.push_back(
m_points.back() );
2865 new_shapes.push_back(
m_shapes.back() );
2872 new_points.push_back(
m_points.back() );
2873 new_shapes.push_back(
m_shapes.back() );
2878 m_points = std::move( new_points );
2879 m_shapes = std::move( new_shapes );
2895 int i_start = l.
Find( m );
2896 int i_end = l.
Find( n );
2898 if( i_start > i_end )
2901 i_start = l.
Find( m );
2902 i_end = l.
Find( n );
2905 aPre = l.
Slice( 0, i_start );
2906 aPost = l.
Slice( i_end, -1 );
2907 aMid = l.
Slice( i_start, i_end );
2914 std::vector<VECTOR2I> pts_unique;
2915 std::vector<std::pair<ssize_t, ssize_t>> shapes_unique;
2947 std::pair<ssize_t,ssize_t> shapeToKeep =
m_shapes[i];
2952 assert( shapeToKeep.first <
static_cast<int>(
m_arcs.size() ) );
2953 assert( shapeToKeep.second <
static_cast<int>(
m_arcs.size() ) );
2955 pts_unique.push_back(
CPoint( i ) );
2956 shapes_unique.push_back( shapeToKeep );
2963 np = pts_unique.size();
2977 && (
SEG( p0, pts_unique[n + 2] ).LineDistance( pts_unique[n + 1] ) <= 1
2978 ||
SEG( p0, pts_unique[n + 2] ).Collinear(
SEG( p0, pts_unique[n + 1] ) ) ) )
2985 m_shapes.push_back( shapes_unique[i] );
2992 m_points.push_back( pts_unique[np - 1] );
2993 m_shapes.push_back( shapes_unique[np - 1] );
3002 m_points.push_back( pts_unique[np - 2] );
3003 m_shapes.push_back( shapes_unique[np - 2] );
3006 m_points.push_back( pts_unique[np - 1] );
3007 m_shapes.push_back( shapes_unique[np - 1] );
3021 poly.
OffsetLineChain( *
this, aAmount, aCornerStrategy, aMaxError, aSimplify );
3039 outline.
Split( start,
true );
3042 const int idA = outline.
Find( start );
3043 const int idB = outline.
Find(
end );
3045 if( idA == -1 || idB == -1 )
3051 for(
int i = idA;; )
3070 for(
int i = idB;; )
3089 if( aLeft.
CPoint( 0 ) != start )
3092 wxASSERT( aLeft.
CPoint( 0 ) == start );
3095 if( aRight.
CPoint( 0 ) != start )
3098 wxASSERT( aRight.
CPoint( 0 ) == start );
3102 int sideLeft = base.
Side( aLeft.
CPoint( 1 ) );
3103 int sideRight = base.
Side( aRight.
CPoint( 1 ) );
3105 if( sideLeft == 0 || sideRight == 0 )
3108 if( sideLeft == sideRight )
3111 if( sideLeft > 0 && sideRight < 0 )
3112 std::swap( aLeft, aRight );
3178 if( ( d > 0 ) == ( ipNext.
y > ip.
y ) )
3196 if( ( d > 0 ) == ( ipNext.
y > ip.
y ) )
3216 for(
int i = 1; i < aPolyline.
PointCount(); i++ )
3257 size_t nextIdx = aSegment + 1;
3259 if( nextIdx >
m_shapes.size() - 1 )
3287 size_t prevIndex = aIndex - 1;
3291 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 BOX2I KiROUND(const BOX2D &aBoxD)
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,...
int Intersect(const SEG &aSeg, std::vector< INTERSECTION > &aIp) const
Find all intersection points between our line chain and the segment aSeg.
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.
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.
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