32 #include <clipper.hpp> 50 for(
size_t i = 0; i < aV.size(); i+= 2 )
57 const std::vector<CLIPPER_Z_VALUE>& aZValueBuffer,
58 const std::vector<SHAPE_ARC>& aArcBuffer ) :
60 m_closed( true ), m_width( 0 )
62 std::map<ssize_t, ssize_t> loadedArcs;
67 [&]( ssize_t aArcIndex ) -> ssize_t
73 else if( loadedArcs.count( aArcIndex ) == 0 )
75 loadedArcs.insert( { aArcIndex,
m_arcs.size() } );
76 m_arcs.push_back( aArcBuffer.at( aArcIndex ) );
79 return loadedArcs.at( aArcIndex );
82 for(
size_t ii = 0; ii < aPath.size(); ++ii )
84 Append( aPath[ii].X, aPath[ii].Y );
86 m_shapes[ii].first = loadArc( aZValueBuffer[aPath[ii].Z].m_FirstArcIdx );
87 m_shapes[ii].second = loadArc( aZValueBuffer[aPath[ii].Z].m_SecondArcIdx );
100 std::vector<CLIPPER_Z_VALUE>& aZValueBuffer,
101 std::vector<SHAPE_ARC>& aArcBuffer )
const 103 ClipperLib::Path c_path;
105 bool orientation =
Area(
false ) >= 0;
106 ssize_t shape_offset = aArcBuffer.size();
108 if( orientation != aRequiredOrientation )
118 size_t z_value_ptr = aZValueBuffer.size();
119 aZValueBuffer.push_back( z_value );
121 c_path.push_back( ClipperLib::IntPoint( vertex.
x, vertex.
y, z_value_ptr ) );
124 aArcBuffer.insert( aArcBuffer.end(), input.
m_arcs.begin(), input.
m_arcs.end() );
137 size_t rotations = 0;
148 wxCHECK( rotations++ <=
m_shapes.size(), );
177 aArcIndex +=
m_arcs.size();
179 if( aArcIndex >= static_cast<ssize_t>(
m_arcs.size() ) )
186 [&]( ssize_t& aShapeIndex )
188 if( aShapeIndex == aArcIndex )
191 if( aShapeIndex > aArcIndex )
196 std::swap( sh.first, sh.second );
206 wxCHECK_MSG( aArcIndex <
m_arcs.size(), ,
207 wxT(
"Invalid arc index requested." ) );
214 theArc.IsClockwise() );
216 m_arcs[aArcIndex] = newArc;
231 wxCHECK_MSG( aPtIndex < static_cast<ssize_t>(
m_shapes.size() ), ,
232 wxT(
"Invalid point index requested." ) );
236 if( aCoincident || aPtIndex == 0 )
239 ssize_t firstArcIndex =
m_shapes[aPtIndex].first;
243 amendArc( firstArcIndex, newStart, newEnd );
258 ssize_t currArcIdx =
ArcIndex( aPtIndex );
273 if( !aCoincident &&
ArcIndex( aPtIndex - 1 ) != currArcIdx )
276 m_arcs[currArcIdx] = newArc2;
280 m_arcs[currArcIdx] = newArc1;
281 m_arcs.insert(
m_arcs.begin() + currArcIdx + 1, newArc2 );
285 m_shapes[aPtIndex].second = currArcIdx + 1;
290 for(
int i = aPtIndex; i <
PointCount(); i++ )
323 SEG::ecoord dist_sq = ( pn - aP ).SquaredEuclideanNorm();
325 if( dist_sq < closest_dist_sq )
328 closest_dist_sq = dist_sq;
330 if( closest_dist_sq == 0 )
334 if( closest_dist_sq < clearance_sq && !aActual )
339 if( closest_dist_sq == 0 || closest_dist_sq < clearance_sq )
342 *aLocation = nearest;
345 *aActual = sqrt( closest_dist_sq );
380 SEG::ecoord dist_sq = ( pn - aP ).SquaredEuclideanNorm();
382 if( dist_sq < closest_dist_sq )
385 closest_dist_sq = dist_sq;
387 if( closest_dist_sq == 0 )
391 if( closest_dist_sq < clearance_sq && !aActual )
396 if( closest_dist_sq == 0 || closest_dist_sq < clearance_sq )
399 *aLocation = nearest;
402 *aActual = sqrt( closest_dist_sq );
408 for(
size_t i = 0; i <
ArcCount(); i++ )
413 wxASSERT_MSG( arc.
GetWidth() == 0, wxT(
"Invalid arc width - should be zero" ) );
415 if( arc.
Collide( aP, aClearance, aActual, aLocation ) )
433 arc.
Rotate( aAngle, aCenter );
460 if( dist_sq < closest_dist_sq )
465 closest_dist_sq = dist_sq;
467 if( closest_dist_sq == 0)
471 if( closest_dist_sq < clearance_sq && !aActual )
476 if( closest_dist_sq == 0 || closest_dist_sq < clearance_sq )
479 *aLocation = nearest;
482 *aActual = sqrt( closest_dist_sq );
518 if( dist_sq < closest_dist_sq )
523 closest_dist_sq = dist_sq;
525 if( closest_dist_sq == 0 )
529 if( closest_dist_sq < clearance_sq && !aActual )
534 if( closest_dist_sq == 0 || closest_dist_sq < clearance_sq )
537 *aLocation = nearest;
540 *aActual = sqrt( closest_dist_sq );
546 for(
size_t i = 0; i <
ArcCount(); i++ )
551 wxASSERT_MSG( arc.
GetWidth() == 0, wxT(
"Invalid arc width - should be zero" ) );
553 if( arc.
Collide( aSeg, aClearance, aActual, aLocation ) )
574 [&]( ssize_t& aShapeIndex )
577 aShapeIndex = a.
m_arcs.size() - aShapeIndex - 1;
586 std::swap( sh.first, sh.second );
602 for( ssize_t arcIndex =
m_arcs.size() - 1; arcIndex >= 0; --arcIndex )
618 for(
int i = 0; i <
ArcCount(); i++ )
619 l +=
CArcs()[i].GetLength();
630 pt.x = -pt.x + 2 * aRef.
x;
633 pt.y = -pt.y + 2 * aRef.
y;
637 arc.Mirror( aX, aY, aRef );
653 Remove( aStartIndex, aEndIndex );
654 Insert( aStartIndex, aP );
664 if( aStartIndex < 0 )
668 wxASSERT( aStartIndex <= aEndIndex );
669 wxASSERT( aEndIndex <
m_points.size() );
674 if( newLine.PointCount() == 0 )
676 Remove( aStartIndex, aEndIndex );
681 if( newLine.m_points.front() ==
m_points[aStartIndex] )
687 if( newLine.PointCount() == 0 )
689 Remove( aStartIndex, aEndIndex );
694 if( newLine.m_points.back() ==
m_points[aEndIndex] && aEndIndex > 0 )
697 newLine.Remove( -1 );
700 Remove( aStartIndex, aEndIndex );
703 if( newLine.PointCount() == 0 )
707 size_t prev_arc_count =
m_arcs.size();
708 std::vector<std::pair<ssize_t, ssize_t>> new_shapes = newLine.m_shapes;
710 for( std::pair<ssize_t, ssize_t>& shape_pair : new_shapes )
713 [&]( ssize_t& aShape )
716 aShape += prev_arc_count;
720 m_shapes.insert(
m_shapes.begin() + aStartIndex, new_shapes.begin(), new_shapes.end() );
722 newLine.m_points.end() );
723 m_arcs.insert(
m_arcs.end(), newLine.m_arcs.begin(), newLine.m_arcs.end() );
736 if( aStartIndex < 0 )
742 aEndIndex = std::min( aEndIndex,
PointCount() - 1 );
748 size_t nextIndex = static_cast<size_t>( aEndIndex ) + 1;
753 std::set<size_t> extra_arcs;
754 auto logArcIdxRemoval = [&]( ssize_t& aShapeIndex )
757 extra_arcs.insert( aShapeIndex );
761 for(
int i = aStartIndex; i <= aEndIndex; i++ )
765 if( i == aStartIndex )
767 logArcIdxRemoval(
m_shapes[i].second );
774 else if( i == aEndIndex )
776 logArcIdxRemoval(
m_shapes[i].first );
779 assert( i > aStartIndex ||
IsSharedPt( i - 1 )
789 for(
auto arc : extra_arcs )
823 int found_index =
Find( aP );
832 if( dist < min_dist && seg.
A != aP && seg.
B != aP )
835 if( found_index < 0 )
837 else if( s < found_index )
851 size_t newIndex = static_cast<size_t>( ii ) + 1;
875 if( aThreshold == 0 )
882 if( (
CPoint( s ) - aP).EuclideanNorm() <= aThreshold )
908 int numPoints = static_cast<int>(
m_shapes.size() );
912 for(
int i = 0; i <
m_points.size() - 1; i++ )
936 while( i < numPoints &&
m_shapes[i].first == arcIdx )
955 if( aPointIndex < 0 )
961 if( ( aForwards && aPointIndex == lastIndex ) ||
962 ( !aForwards && aPointIndex == 0 ) )
967 int delta = aForwards ? 1 : -1;
970 return aPointIndex +
delta;
972 int arcStart = aPointIndex;
979 auto arcIndex = [&](
int aIndex ) -> ssize_t
987 ssize_t currentArcIdx = arcIndex( aPointIndex );
990 while( aPointIndex < lastIndex && aPointIndex >= 0 && arcIndex( aPointIndex ) == currentArcIdx )
991 aPointIndex +=
delta;
993 if( aPointIndex == lastIndex )
995 if( !
m_closed && arcIndex( aPointIndex ) == currentArcIdx )
1005 if( aPointIndex - arcStart > 1 && !indexStillOnArc )
1006 aPointIndex -=
delta;
1022 [&]( ssize_t& aIdx )
1032 if( aPointIndex < 0 )
1042 int start = aPointIndex;
1043 int end = aPointIndex;
1044 int arcIdx =
ArcIndex( aPointIndex );
1049 while( start >= 0 &&
m_shapes[start].first == arcIdx )
1053 if( start >= 1 &&
m_shapes[static_cast<ssize_t>( start ) - 1].second == arcIdx )
1059 while( end < static_cast<int>(
m_shapes.size() ) - 1 &&
m_shapes[end].first == arcIdx )
1073 if( aStartIndex < 0 )
1076 int numPoints = static_cast<int>(
m_points.size() );
1082 ssize_t arcIndex =
ArcIndex( aStartIndex );
1086 for(
size_t i = aStartIndex; arcIndex ==
ArcIndex( i ); i++ )
1103 rv.
m_arcs.push_back( newArc );
1108 for(
int i = aStartIndex; i <= aEndIndex && i < numPoints; i =
NextShape( i ) )
1117 bool isLastShape = nextShape < 0;
1119 if( ( isLastShape && aEndIndex != ( numPoints - 1 ) )
1120 || ( nextShape > aEndIndex ) )
1122 if( i == aEndIndex )
1134 for( ; i <= aEndIndex && i < numPoints; i++ )
1154 rv.
m_arcs.push_back( newArc );
1170 wxT(
"Still on an arc segment, we missed something..." ) );
1189 size_t num_arcs =
m_arcs.size();
1192 auto fixShapeIndices =
1193 [&](
const std::pair<ssize_t, ssize_t>& aShapeIndices ) -> std::pair<ssize_t, ssize_t>
1195 std::pair<ssize_t, ssize_t> retval = aShapeIndices;
1200 aIndex = aIndex + num_arcs;
1223 for(
int i = 1; i < aOtherLine.
PointCount(); i++ )
1228 ssize_t arcIndex = aOtherLine.
ArcIndex( i );
1250 if( startToEnd.Distance( aArc.
GetArcMid() ) < 1 )
1261 chain.
m_arcs.push_back( aArc );
1262 chain.
m_arcs.back().SetWidth( 0 );
1282 wxCHECK( aVertex <
m_points.size(), );
1284 if( aVertex > 0 &&
IsPtOnArc( aVertex ) )
1297 wxCHECK( aVertex <
m_points.size(), );
1299 if( aVertex > 0 &&
IsPtOnArc( aVertex ) )
1303 ssize_t arc_pos =
m_arcs.size();
1305 for(
auto arc_it =
m_shapes.rbegin() ;
1306 arc_it !=
m_shapes.rend() + aVertex;
1311 arc_pos = std::max( ( *arc_it ).first, ( *arc_it ).second );
1320 [&]( ssize_t& aIndex )
1322 if( aIndex >= arc_pos )
1334 m_points.insert(
m_points.begin() + aVertex, chain.CPoints().begin(), chain.CPoints().end() );
1338 std::vector<std::pair<ssize_t, ssize_t>> new_points( chain.PointCount(),
1341 m_shapes.insert(
m_shapes.begin() + aVertex, new_points.begin(), new_points.end() );
1375 aIp.push_back( is );
1380 sort( aIp.begin(), aIp.end(), comp );
1389 if( aIps.size() == 0 )
1391 aIps.push_back( aP );
1395 const auto& last = aIps.back();
1397 aIps.push_back( aP );
1402 bool aExcludeColinearAndTouching )
const 1409 const BOX2I bb_cur( a.
A, a.
B - a.
A );
1429 if( coll && ! aExcludeColinearAndTouching )
1508 bool indexMatch =
true;
1518 indexMatch = ( i == aIndex );
1536 bool aUseBBoxCache )
const 1548 bool inside =
false;
1563 for(
int i = 0; i < pointCount; )
1566 const auto p2 =
GetPoint( i == pointCount ? 0 : i );
1567 const auto diff = p2 - p1;
1571 const int d =
rescale( diff.x, ( aPt.
y - p1.y ), diff.y );
1573 if( ( ( p1.y > aPt.
y ) != ( p2.y > aPt.
y ) ) && ( aPt.
x - p1.x < d ) )
1580 if( aAccuracy <= 1 )
1602 return ( hypot( dist.
x, dist.
y ) <= aAccuracy + 1 ) ? 0 : -1;
1609 if( s.
A == aPt || s.
B == aPt )
1612 if( s.
Distance( aPt ) <= aAccuracy + 1 )
1631 if( s.
A == aP || s.
B == aP )
1650 if( s1 + 1 != s2 &&
CSegment( s1 ).Contains( s2a ) )
1658 else if(
CSegment( s1 ).Contains( s2b ) &&
1692 std::vector<VECTOR2I> pts_unique;
1693 std::vector<std::pair<ssize_t, ssize_t>> shapes_unique;
1725 std::pair<ssize_t,ssize_t> shapeToKeep =
m_shapes[i];
1730 assert( shapeToKeep.first < static_cast<int>(
m_arcs.size() ) );
1731 assert( shapeToKeep.second < static_cast<int>(
m_arcs.size() ) );
1733 pts_unique.push_back(
CPoint( i ) );
1734 shapes_unique.push_back( shapeToKeep );
1741 np = pts_unique.size();
1749 const VECTOR2I p1 = pts_unique[i + 1];
1756 && (
SEG( p0, p1 ).LineDistance( pts_unique[n + 2] ) <= 1
1757 ||
SEG( p0, p1 ).Collinear(
SEG( p1, pts_unique[n + 2] ) ) ) )
1762 m_shapes.push_back( shapes_unique[i] );
1769 m_points.push_back( pts_unique[np - 1] );
1770 m_shapes.push_back( shapes_unique[np - 1] );
1779 m_points.push_back( pts_unique[np - 2] );
1780 m_shapes.push_back( shapes_unique[np - 2] );
1783 m_points.push_back( pts_unique[np - 1] );
1784 m_shapes.push_back( shapes_unique[np - 1] );
1793 bool aAllowInternalShapePoints )
const 1795 int min_d = INT_MAX;
1809 if( !aAllowInternalShapePoints )
1832 return nearestArc.
GetP1();
1834 return nearestArc.
GetP0();
1861 return CPoint( nearest );
1867 int min_d = INT_MAX;
1887 std::stringstream ss;
1889 ss <<
"SHAPE_LINE_CHAIN( { ";
1899 ss <<
"}, " << (
m_closed ?
"true" :
"false" );
1920 if( a.m_points.size() != b.
m_points.size() )
1923 for(
int i = 0; i < a.PointCount(); i++ )
1925 if( a.CPoint( i ) != b.
CPoint( i ) )
1955 if( n_pts > aStream.str().size() )
1961 if( n_arcs > aStream.str().size() )
1964 for(
size_t i = 0; i < n_pts; i++ )
1976 for(
size_t i = 0; i < n_arcs; i++ )
1998 if( aPathLength == 0 )
2006 if( total + l >= aPathLength )
2009 return s.
A + d.
Resize( aPathLength - total );
2029 for(
int i = 0, j = size - 1; i < size; ++i )
2037 return std::fabs( area * 0.5 );
2045 m_finished( false ),
2055 if( ipNext.
y == m_point.y )
2057 if( ( ipNext.
x == m_point.x )
2058 || ( ip.
y == m_point.y && ( ( ipNext.
x > m_point.x ) == ( ip.
x < m_point.x ) ) ) )
2066 if( ( ip.
y < m_point.y ) != ( ipNext.
y < m_point.y ) )
2068 if( ip.
x >= m_point.x )
2070 if( ipNext.
x > m_point.x )
2072 m_state = 1 - m_state;
2076 double d = (double) ( ip.
x - m_point.x ) * ( ipNext.
y - m_point.y )
2077 - (
double) ( ipNext.
x - m_point.x ) * ( ip.
y - m_point.y );
2086 if( ( d > 0 ) == ( ipNext.
y > ip.
y ) )
2087 m_state = 1 - m_state;
2092 if( ipNext.
x > m_point.x )
2094 double d = (double) ( ip.
x - m_point.x ) * ( ipNext.
y - m_point.y )
2095 - (
double) ( ipNext.
x - m_point.x ) * ( ip.
y - m_point.y );
2104 if( ( d > 0 ) == ( ipNext.
y > ip.
y ) )
2105 m_state = 1 - m_state;
2118 m_lastPoint = aPolyline.
CPoint( 0 );
2119 m_firstPoint = aPolyline.
CPoint( 0 );
2124 for(
int i = 1; i < aPolyline.
PointCount(); i++ )
2126 auto p = aPolyline.
CPoint( i );
2128 if( !processVertex( m_lastPoint, p ) )
2139 processVertex( m_lastPoint, m_firstPoint );
double EuclideanNorm(const wxPoint &vector)
Euclidean norm of a 2D vector.
int Length() const
Return the length (this).
Represent an intersection between two line segments.
const std::vector< std::pair< ssize_t, ssize_t > > & CShapes() const
BOX2I m_bbox
cached bounding box
const SHAPE_ARC & Arc(size_t aArc) const
long long int Length() const
Return length of the line chain in Euclidean metric.
int Split(const VECTOR2I &aP)
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.
int Distance(const SEG &aSeg) const
Compute minimum Euclidean distance to segment aSeg.
int Intersect(const SEG &aSeg, INTERSECTIONS &aIp) const
Find all intersection points between our line chain and the segment aSeg.
ClipperLib::Path convertToClipper(bool aRequiredOrientation, std::vector< CLIPPER_Z_VALUE > &aZValueBuffer, std::vector< SHAPE_ARC > &aArcBuffer) const
Create a new Clipper path from the SHAPE_LINE_CHAIN in a given orientation.
virtual size_t GetSegmentCount() const override
std::vector< INTERSECTION > INTERSECTIONS
bool IsSharedPt(size_t aIndex) const
Test if a point is shared between multiple shapes.
void RemoveShape(int aPointIndex)
Remove the shape at the given index from the line chain.
virtual BOX2I * GetCachedBBox() const
SHAPE_LINE_CHAIN & Simplify(bool aRemoveColinear=true)
Simplify the line chain by removing colinear adjacent segments and duplicate vertices.
void SetPoint(int aIndex, const VECTOR2I &aPos)
Move a point to a specific location.
SEG::ecoord SquaredDistance(const VECTOR2I &aP, bool aOutlineOnly=false) 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 const ssize_t SHAPE_IS_PT
OPT_VECTOR2I Intersect(const SEG &aSeg, bool aIgnoreEndpoints=false, bool aLines=false) const
Compute intersection point of segment (this) with segment aSeg.
const SHAPE_LINE_CHAIN Slice(int aStartIndex, int aEndIndex=-1) const
Return a subset of this line chain containing the [start_index, end_index] range of points.
virtual bool IsClosed() const =0
VECTOR2I p
< Point of intersection between our and their.
VECTOR2I::extended_type ecoord
Define a general 2D-vector/point.
const VECTOR2I ReflectPoint(const VECTOR2I &aP) const
Reflect a point using this segment as axis.
virtual size_t GetPointCount() const =0
compareOriginDistance(const VECTOR2I &aOrigin)
int Distance(const VECTOR2I &aP, bool aOutlineOnly=false) const
Compute the minimum distance between the line chain and a point aP.
bool PointOnEdge(const VECTOR2I &aP, int aAccuracy=0) const
Check if point aP lies on an edge or vertex of the line chain.
ecoord SquaredDistance(const SEG &aSeg) const
void AddPolyline(const SHAPE_LINE_CHAIN &aPolyline)
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...
double Area(bool aAbsolute=true) const
Return the area of this chain.
virtual size_t GetSegmentCount() const =0
const SHAPE_LINE_CHAIN Reverse() const
Reverse point order in the line chain.
const std::vector< SHAPE_ARC > & CArcs() const
void convertArc(ssize_t aArcIndex)
Convert an arc to only a point chain by removing the arc and references.
int PointCount() const
Return the number of points (vertices) in this line chain.
static SEG::ecoord Square(int a)
int FindSegment(const VECTOR2I &aP, int aThreshold=1) const
Search for segment containing point aP.
void splitArc(ssize_t aPtIndex, bool aCoincident=false)
Splits an arc into two arcs at aPtIndex.
const OPT< INTERSECTION > SelfIntersecting() const
Check if the line chain is self-intersecting.
void Append(int aX, int aY, bool aAllowDuplication=false)
Append a new point at the end of the line chain.
std::vector< SHAPE_ARC > m_arcs
const VECTOR2I NearestPoint(const VECTOR2I &aP, bool aAllowInternalShapePoints=true) const
Find a point on the line chain that is closest to point aP.
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 Parse(std::stringstream &aStream) override
bool operator()(const SHAPE_LINE_CHAIN::INTERSECTION &aA, const SHAPE_LINE_CHAIN::INTERSECTION &aB) const
void Insert(size_t aVertex, const VECTOR2I &aP)
static LIB_SYMBOL * dummy()
Used to draw a dummy shape when a LIB_SYMBOL is not found in library.
ssize_t ArcIndex(size_t aSegment) const
Return the arc index for the given segment index.
bool Intersects(const BOX2< Vec > &aRect) const
const VECTOR2I & CPoint(int aIndex) const
Return a reference to a given point in the line chain.
bool IsArcStart(size_t aIndex) const
bool m_closed
is the line chain closed?
SHAPE_LINE_CHAIN()
Initialize an empty line chain.
static constexpr extended_type ECOORD_MAX
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 BOX2I BBox(int aClearance=0) const override
Compute a bounding box of the shape, with a margin of aClearance a collision.
bool IsArcSegment(size_t aSegment) const
bool IsClosed() const override
OPT< VECTOR2I > OPT_VECTOR2I
bool is_corner_their
Auxiliary flag to avoid copying intersection info to intersection refining code, used by the refining...
int Find(const VECTOR2I &aP, int aThreshold=0) const
Search for point aP.
void ClearArcs()
Remove all arc references in the line chain, resulting in a chain formed only of straight segments.
std::vector< VECTOR2I > m_points
array of vertices
void run_on_pair(std::pair< _Type, _Type > &__pair, _Function __f)
Apply a function to the first and second element of a std::pair.
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.
virtual const SEG GetSegment(int aIndex) const override
const VECTOR2I & GetP0() const
bool PointInside(const VECTOR2I &aPt, int aAccuracy=0, bool aUseBBoxCache=false) const
Check if point aP lies inside a polygon (any type) defined by the line chain.
POINT_INSIDE_TRACKER(const VECTOR2I &aPoint)
const VECTOR2I & GetArcMid() const
bool Intersects(const SHAPE_LINE_CHAIN &aChain) const
const VECTOR2I NearestPoint(const VECTOR2I &aP) const
Compute a point on the segment (this) that is closest to point aP.
int ShapeCount() const
Return the number of shapes (line segments or arcs) in this line chain.
An abstract shape on 2D plane.
void Remove(int aStartIndex, int aEndIndex)
Remove the range of points [start_index, end_index] from the line chain.
BOX2< Vec > & Merge(const BOX2< Vec > &aRect)
Modify the position and size of the rectangle in order to contain aRect.
void amendArc(size_t aArcIndex, const VECTOR2I &aNewStart, const VECTOR2I &aNewEnd)
const std::string Format() const override
int SegmentCount() const
Return the number of segments in this line chain.
virtual const VECTOR2I GetPoint(int aIndex) const override
bool IsPtOnArc(size_t aPtIndex) const
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 Rotate(double aAngle, const VECTOR2I &aCenter=VECTOR2I(0, 0)) override
Rotate all vertices by a given angle.
bool Collinear(const SEG &aSeg) const
Check if segment aSeg lies on the same line as (this).
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,...
virtual const SEG GetSegment(int aIndex) const =0
int NearestSegment(const VECTOR2I &aP) const
Find the segment nearest the given point.
VECTOR2< T > Resize(T aNewLength) const
Return a vector of the same direction, but length specified in aNewLength.
void mergeFirstLastPointIfNeeded()
Merge the first and last point if they are the same and this chain is closed.
VECTOR2< T > Rotate(double aAngle) const
Rotate the vector by a given angle.
const SHAPE_LINE_CHAIN ConvertToPolyline(double aAccuracy=DefaultAccuracyForPCB(), double *aEffectiveAccuracy=nullptr) const
Construct a SHAPE_LINE_CHAIN of segments from a given arc.
int index_their
When true, the corner [index_our] of the 'our' line lies exactly on 'their' line.
bool is_corner_our
When true, the corner [index_their] of the 'their' line lies exactly on 'our' line.
const SEG CSegment(int aIndex) const
Return a constant copy of the aIndex segment in the line chain.
ssize_t reversedArcIndex(size_t aSegment) const
Return the arc index for the given segment index, looking backwards.
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.
VECTOR2I::extended_type ecoord
Represent a polyline containing arcs as well as line segments: A chain of connected line and/or arc s...
static DIRECTION_45::AngleType angle(const VECTOR2I &a, const VECTOR2I &b)
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.
bool IsArcEnd(size_t aIndex) const
T rescale(T aNumerator, T aValue, T aDenominator)
Scale a number (value) by rational (numerator/denominator).
SHAPE * Clone() const override
Return a dynamically allocated copy of the shape.
Holds information on each point of a SHAPE_LINE_CHAIN that is retrievable after an operation with Cli...
int EdgeContainingPoint(const VECTOR2I &aP, int aAccuracy=0) const
Check if point aP lies on an edge or vertex of the line chain.
T EuclideanNorm() const
Compute the Euclidean norm of the vector, which is defined as sqrt(x ** 2 + y ** 2).
void SetWidth(int aWidth)
void Replace(int aStartIndex, int aEndIndex, const VECTOR2I &aP)
Replace points with indices in range [start_index, end_index] with a single point aP.
int NextShape(int aPointIndex, bool aForwards=true) const
Return the vertex index of the next shape in the chain, or -1 if aPointIndex is the last shape.
virtual const VECTOR2I GetPoint(int aIndex) const =0
static const std::pair< ssize_t, ssize_t > SHAPES_ARE_PT
static void addIntersection(SHAPE_LINE_CHAIN::INTERSECTIONS &aIps, int aPc, const SHAPE_LINE_CHAIN::INTERSECTION &aP)
int index_our
index of the intersecting corner/segment in the 'their' (Intersect() method parameter) line.
const VECTOR2I PointAlong(int aPathLength) const
const VECTOR2I & GetP1() const
VECTOR2I GetCenter() const
bool processVertex(const VECTOR2I &ip, const VECTOR2I &ipNext)
void Mirror(bool aX=true, bool aY=false, const VECTOR2I &aRef={ 0, 0 })
Mirror the line points about y or x (or both).
bool CompareGeometry(const SHAPE_LINE_CHAIN &aOther) const
bool Contains(const SEG &aSeg) const