KiCad PCB EDA Suite
SHAPE_LINE_CHAIN Class Reference

Represent a polyline containing arcs as well as line segments: A chain of connected line and/or arc segments. More...

#include <shape_line_chain.h>

Inheritance diagram for SHAPE_LINE_CHAIN:
SHAPE_LINE_CHAIN_BASE SHAPE SHAPE_BASE

Classes

struct  compareOriginDistance
 
struct  INTERSECTION
 Represent an intersection between two line segments. More...
 
class  POINT_INSIDE_TRACKER
 A dynamic state checking if a point lies within polygon with a dynamically built outline ( with each piece of the outline added by AddPolyline () More...
 

Public Types

typedef std::vector< INTERSECTIONINTERSECTIONS
 

Public Member Functions

 SHAPE_LINE_CHAIN ()
 Initialize an empty line chain. More...
 
 SHAPE_LINE_CHAIN (const SHAPE_LINE_CHAIN &aShape)
 
 SHAPE_LINE_CHAIN (const std::vector< int > &aV)
 
 SHAPE_LINE_CHAIN (const std::vector< VECTOR2I > &aV, bool aClosed=false)
 
 SHAPE_LINE_CHAIN (const SHAPE_ARC &aArc, bool aClosed=false)
 
 SHAPE_LINE_CHAIN (const ClipperLib::Path &aPath, const std::vector< CLIPPER_Z_VALUE > &aZValueBuffer, const std::vector< SHAPE_ARC > &aArcBuffer)
 
virtual ~SHAPE_LINE_CHAIN ()
 
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. More...
 
virtual bool Collide (const SEG &aSeg, int aClearance=0, int *aActual=nullptr, VECTOR2I *aLocation=nullptr) const override
 Check if segment aSeg lies closer to us than aClearance. More...
 
SHAPE_LINE_CHAINoperator= (const SHAPE_LINE_CHAIN &)=default
 
SHAPEClone () const override
 Return a dynamically allocated copy of the shape. More...
 
void Clear ()
 Remove all points from the line chain. More...
 
void SetClosed (bool aClosed)
 Mark the line chain as closed (i.e. More...
 
bool IsClosed () const override
 
void SetWidth (int aWidth)
 Set the width of all segments in the chain. More...
 
int Width () const
 Get the current width of the segments in the chain. More...
 
int SegmentCount () const
 Return the number of segments in this line chain. More...
 
int ShapeCount () const
 Return the number of shapes (line segments or arcs) in this line chain. More...
 
int PointCount () const
 Return the number of points (vertices) in this line chain. More...
 
SEG Segment (int aIndex)
 Return a copy of the aIndex-th segment in the line chain. More...
 
const SEG CSegment (int aIndex) const
 Return a constant copy of the aIndex segment in the line chain. More...
 
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. More...
 
int PrevShape (int aPointIndex) const
 
void SetPoint (int aIndex, const VECTOR2I &aPos)
 Move a point to a specific location. More...
 
const VECTOR2ICPoint (int aIndex) const
 Return a reference to a given point in the line chain. More...
 
const std::vector< VECTOR2I > & CPoints () const
 
const VECTOR2ICLastPoint () const
 Return the last point in the line chain. More...
 
const std::vector< SHAPE_ARC > & CArcs () const
 
const std::vector< std::pair< ssize_t, ssize_t > > & CShapes () const
 
const BOX2I BBox (int aClearance=0) const override
 Compute a bounding box of the shape, with a margin of aClearance a collision. More...
 
void GenerateBBoxCache () const
 
BOX2IGetCachedBBox () const override
 
int Distance (const VECTOR2I &aP, bool aOutlineOnly=false) const
 Compute the minimum distance between the line chain and a point aP. More...
 
const SHAPE_LINE_CHAIN Reverse () const
 Reverse point order in the line chain. More...
 
void ClearArcs ()
 Remove all arc references in the line chain, resulting in a chain formed only of straight segments. More...
 
long long int Length () const
 Return length of the line chain in Euclidean metric. More...
 
void Append (int aX, int aY, bool aAllowDuplication=false)
 Append a new point at the end of the line chain. More...
 
void Append (const VECTOR2I &aP, bool aAllowDuplication=false)
 Append a new point at the end of the line chain. More...
 
void Append (const SHAPE_LINE_CHAIN &aOtherLine)
 Append another line chain at the end. More...
 
void Append (const SHAPE_ARC &aArc)
 
void Insert (size_t aVertex, const VECTOR2I &aP)
 
void Insert (size_t aVertex, const SHAPE_ARC &aArc)
 
void Replace (int aStartIndex, int aEndIndex, const VECTOR2I &aP)
 Replace points with indices in range [start_index, end_index] with a single point aP. More...
 
void Replace (int aStartIndex, int aEndIndex, const SHAPE_LINE_CHAIN &aLine)
 Replace points with indices in range [start_index, end_index] with the points from line chain aLine. More...
 
void Remove (int aStartIndex, int aEndIndex)
 Remove the range of points [start_index, end_index] from the line chain. More...
 
void Remove (int aIndex)
 Remove the aIndex-th point from the line chain. More...
 
void RemoveShape (int aPointIndex)
 Remove the shape at the given index from the line chain. More...
 
int Split (const VECTOR2I &aP)
 Insert the point aP belonging to one of the our segments, splitting the adjacent segment in two. More...
 
int Find (const VECTOR2I &aP, int aThreshold=0) const
 Search for point aP. More...
 
int FindSegment (const VECTOR2I &aP, int aThreshold=1) const
 Search for segment containing point aP. More...
 
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. More...
 
bool Intersects (const SHAPE_LINE_CHAIN &aChain) const
 
int Intersect (const SEG &aSeg, INTERSECTIONS &aIp) const
 Find all intersection points between our line chain and the segment aSeg. More...
 
int Intersect (const SHAPE_LINE_CHAIN &aChain, INTERSECTIONS &aIp, bool aExcludeColinearAndTouching=false, BOX2I *aChainBBox=nullptr) const
 Find all intersection points between our line chain and the line chain aChain. More...
 
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 line. More...
 
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. More...
 
const std::optional< INTERSECTIONSelfIntersecting () const
 Check if the line chain is self-intersecting. More...
 
SHAPE_LINE_CHAINSimplify (bool aRemoveColinear=true)
 Simplify the line chain by removing colinear adjacent segments and duplicate vertices. More...
 
int NearestSegment (const VECTOR2I &aP) const
 Find the segment nearest the given point. More...
 
const VECTOR2I NearestPoint (const VECTOR2I &aP, bool aAllowInternalShapePoints=true) const
 Find a point on the line chain that is closest to point aP. More...
 
const VECTOR2I NearestPoint (const SEG &aSeg, int &dist) const
 Find a point on the line chain that is closest to the line defined by the points of segment aSeg, also returns the distance. More...
 
const std::string Format () const override
 
bool Parse (std::stringstream &aStream) override
 
bool operator!= (const SHAPE_LINE_CHAIN &aRhs) const
 
bool CompareGeometry (const SHAPE_LINE_CHAIN &aOther) const
 
void Move (const VECTOR2I &aVector) override
 
void Mirror (bool aX=true, bool aY=false, const VECTOR2I &aRef={ 0, 0 })
 Mirror the line points about y or x (or both). More...
 
void Mirror (const SEG &axis)
 Mirror the line points using an given axis. More...
 
void Rotate (const EDA_ANGLE &aAngle, const VECTOR2I &aCenter={ 0, 0 }) override
 Rotate all vertices by a given angle. More...
 
bool IsSolid () const override
 
const VECTOR2I PointAlong (int aPathLength) const
 
double Area (bool aAbsolute=true) const
 Return the area of this chain. More...
 
size_t ArcCount () const
 
ssize_t ArcIndex (size_t aSegment) const
 Return the arc index for the given segment index. More...
 
const SHAPE_ARCArc (size_t aArc) const
 
bool IsSharedPt (size_t aIndex) const
 Test if a point is shared between multiple shapes. More...
 
bool IsPtOnArc (size_t aPtIndex) const
 
bool IsArcSegment (size_t aSegment) const
 
bool IsArcStart (size_t aIndex) const
 
bool IsArcEnd (size_t aIndex) const
 
virtual const VECTOR2I GetPoint (int aIndex) const override
 
virtual const SEG GetSegment (int aIndex) const override
 
virtual size_t GetPointCount () const override
 
virtual size_t GetSegmentCount () const override
 
virtual bool Collide (const SHAPE *aShape, int aClearance, VECTOR2I *aMTV) const
 Check if the boundary of shape (this) lies closer to the shape aShape than aClearance, indicating a collision. More...
 
virtual bool Collide (const SHAPE *aShape, int aClearance=0, int *aActual=nullptr, VECTOR2I *aLocation=nullptr) const
 
SEG::ecoord SquaredDistance (const VECTOR2I &aP, bool aOutlineOnly=false) 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. More...
 
bool PointOnEdge (const VECTOR2I &aP, int aAccuracy=0) const
 Check if point aP lies on an edge or vertex of the line chain. More...
 
int EdgeContainingPoint (const VECTOR2I &aP, int aAccuracy=0) const
 Check if point aP lies on an edge or vertex of the line chain. More...
 
int GetClearance (const SHAPE *aOther) const
 Return the actual minimum distance between two shapes. More...
 
bool IsNull () const
 Return true if the shape is a null shape. More...
 
virtual VECTOR2I Centre () const
 Compute a center-of-mass of the shape. More...
 
FACETNewFacet ()
 
SGNODECalcShape (SGNODE *aParent, SGNODE *aColor, WRL1_ORDER aVertexOrder, float aCreaseLimit=0.74317, bool isVRML2=false)
 
SHAPE_TYPE Type () const
 Return the type of the shape. More...
 
wxString TypeName () const
 
virtual bool HasIndexableSubshapes () const
 
virtual size_t GetIndexableSubshapeCount () const
 
virtual void GetIndexableSubshapes (std::vector< const SHAPE * > &aSubshapes) const
 

Static Public Attributes

static const int MIN_PRECISION_IU = 4
 This is the minimum precision for all the points in a shape. More...
 

Protected Types

typedef VECTOR2I::extended_type ecoord
 

Protected Member Functions

void convertArc (ssize_t aArcIndex)
 Convert an arc to only a point chain by removing the arc and references. More...
 
void splitArc (ssize_t aPtIndex, bool aCoincident=false)
 Splits an arc into two arcs at aPtIndex. More...
 
void amendArc (size_t aArcIndex, const VECTOR2I &aNewStart, const VECTOR2I &aNewEnd)
 
void amendArcStart (size_t aArcIndex, const VECTOR2I &aNewStart)
 
void amendArcEnd (size_t aArcIndex, const VECTOR2I &aNewEnd)
 
ssize_t reversedArcIndex (size_t aSegment) const
 Return the arc index for the given segment index, looking backwards. More...
 
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. More...
 
void fixIndicesRotation ()
 Fix indices of this chain to ensure arcs are not split between the end and start indices. More...
 
void mergeFirstLastPointIfNeeded ()
 Merge the first and last point if they are the same and this chain is closed. More...
 

Protected Attributes

SHAPE_TYPE m_type
 < type of our shape More...
 

Private Types

typedef std::vector< VECTOR2I >::iterator point_iter
 
typedef std::vector< VECTOR2I >::const_iterator point_citer
 

Private Attributes

std::vector< VECTOR2Im_points
 array of vertices More...
 
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, e.g. More...
 
std::vector< SHAPE_ARCm_arcs
 
bool m_closed
 is the line chain closed? More...
 
int m_width
 Width of the segments (for BBox calculations in RTree) TODO Adjust usage of SHAPE_LINE_CHAIN to account for where we need a width and where not Alternatively, we could split the class into a LINE_CHAIN (no width) and SHAPE_LINE_CHAIN that derives from SHAPE as well that does have a width. More...
 
BOX2I m_bbox
 cached bounding box More...
 
std::list< FACET * > facets
 

Static Private Attributes

static const ssize_t SHAPE_IS_PT = -1
 
static const std::pair< ssize_t, ssize_t > SHAPES_ARE_PT = { SHAPE_IS_PT, SHAPE_IS_PT }
 

Friends

class SHAPE_POLY_SET
 

Detailed Description

Represent a polyline containing arcs as well as line segments: A chain of connected line and/or arc segments.

The arc shapes are piecewise approximated for the purpose of boolean operations but are used as arcs when doing collision checks.

It is purposely not named "polyline" to avoid confusion with the existing CPolyLine in Pcbnew.

Note
The SHAPE_LINE_CHAIN class shall not be used for polygons!

Definition at line 80 of file shape_line_chain.h.

Member Typedef Documentation

◆ ecoord

typedef VECTOR2I::extended_type SHAPE::ecoord
protectedinherited

Definition at line 249 of file shape.h.

◆ INTERSECTIONS

Definition at line 150 of file shape_line_chain.h.

◆ point_citer

typedef std::vector<VECTOR2I>::const_iterator SHAPE_LINE_CHAIN::point_citer
private

Definition at line 84 of file shape_line_chain.h.

◆ point_iter

typedef std::vector<VECTOR2I>::iterator SHAPE_LINE_CHAIN::point_iter
private

Definition at line 83 of file shape_line_chain.h.

Constructor & Destructor Documentation

◆ SHAPE_LINE_CHAIN() [1/6]

SHAPE_LINE_CHAIN::SHAPE_LINE_CHAIN ( )
inline

Initialize an empty line chain.

Definition at line 156 of file shape_line_chain.h.

156 :
158 m_closed( false ),
159 m_width( 0 )
160 {}
SHAPE_LINE_CHAIN_BASE(SHAPE_TYPE aType)
Definition: shape.h:256
int m_width
Width of the segments (for BBox calculations in RTree) TODO Adjust usage of SHAPE_LINE_CHAIN to accou...
bool m_closed
is the line chain closed?
@ SH_LINE_CHAIN
line chain (polyline)
Definition: shape.h:46

Referenced by Clone().

◆ SHAPE_LINE_CHAIN() [2/6]

SHAPE_LINE_CHAIN::SHAPE_LINE_CHAIN ( const SHAPE_LINE_CHAIN aShape)
inline

Definition at line 162 of file shape_line_chain.h.

162 :
164 m_points( aShape.m_points ),
165 m_shapes( aShape.m_shapes ),
166 m_arcs( aShape.m_arcs ),
167 m_closed( aShape.m_closed ),
168 m_width( aShape.m_width ),
169 m_bbox( aShape.m_bbox )
170 {}
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,...
std::vector< SHAPE_ARC > m_arcs
std::vector< VECTOR2I > m_points
array of vertices
BOX2I m_bbox
cached bounding box

◆ SHAPE_LINE_CHAIN() [3/6]

SHAPE_LINE_CHAIN::SHAPE_LINE_CHAIN ( const std::vector< int > &  aV)

Definition at line 46 of file shape_line_chain.cpp.

48{
49 for(size_t i = 0; i < aV.size(); i+= 2 )
50 {
51 Append( aV[i], aV[i+1] );
52 }
53}
void Append(int aX, int aY, bool aAllowDuplication=false)
Append a new point at the end of the line chain.

References Append().

◆ SHAPE_LINE_CHAIN() [4/6]

SHAPE_LINE_CHAIN::SHAPE_LINE_CHAIN ( const std::vector< VECTOR2I > &  aV,
bool  aClosed = false 
)
inline

Definition at line 174 of file shape_line_chain.h.

174 :
176 m_closed( aClosed ),
177 m_width( 0 )
178 {
179 m_points = aV;
180 m_shapes = std::vector<std::pair<ssize_t, ssize_t>>( aV.size(), SHAPES_ARE_PT );
181 }
static const std::pair< ssize_t, ssize_t > SHAPES_ARE_PT

References m_points, m_shapes, and SHAPES_ARE_PT.

◆ SHAPE_LINE_CHAIN() [5/6]

SHAPE_LINE_CHAIN::SHAPE_LINE_CHAIN ( const SHAPE_ARC aArc,
bool  aClosed = false 
)
inline

Definition at line 183 of file shape_line_chain.h.

183 :
185 m_closed( aClosed ),
186 m_width( 0 )
187 {
189 m_arcs.emplace_back( aArc );
190 m_arcs.back().SetWidth( 0 );
191 m_shapes = std::vector<std::pair<ssize_t, ssize_t>>( m_points.size(), { 0, SHAPE_IS_PT } );
192 }
const SHAPE_LINE_CHAIN ConvertToPolyline(double aAccuracy=DefaultAccuracyForPCB(), double *aEffectiveAccuracy=nullptr) const
Construct a SHAPE_LINE_CHAIN of segments from a given arc.
Definition: shape_arc.cpp:461
const std::vector< VECTOR2I > & CPoints() const
static const ssize_t SHAPE_IS_PT

References SHAPE_ARC::ConvertToPolyline(), CPoints(), m_arcs, m_points, m_shapes, and SHAPE_IS_PT.

◆ SHAPE_LINE_CHAIN() [6/6]

SHAPE_LINE_CHAIN::SHAPE_LINE_CHAIN ( const ClipperLib::Path &  aPath,
const std::vector< CLIPPER_Z_VALUE > &  aZValueBuffer,
const std::vector< SHAPE_ARC > &  aArcBuffer 
)

Definition at line 55 of file shape_line_chain.cpp.

57 :
59 m_closed( true ), m_width( 0 )
60{
61 std::map<ssize_t, ssize_t> loadedArcs;
62 m_points.reserve( aPath.size() );
63 m_shapes.reserve( aPath.size() );
64
65 auto loadArc =
66 [&]( ssize_t aArcIndex ) -> ssize_t
67 {
68 if( aArcIndex == SHAPE_IS_PT )
69 {
70 return SHAPE_IS_PT;
71 }
72 else if( loadedArcs.count( aArcIndex ) == 0 )
73 {
74 loadedArcs.insert( { aArcIndex, m_arcs.size() } );
75 m_arcs.push_back( aArcBuffer.at( aArcIndex ) );
76 }
77
78 return loadedArcs.at( aArcIndex );
79 };
80
81 for( size_t ii = 0; ii < aPath.size(); ++ii )
82 {
83 Append( aPath[ii].X, aPath[ii].Y );
84
85 m_shapes[ii].first = loadArc( aZValueBuffer[aPath[ii].Z].m_FirstArcIdx );
86 m_shapes[ii].second = loadArc( aZValueBuffer[aPath[ii].Z].m_SecondArcIdx );
87 }
88
89 // Clipper shouldn't return duplicate contiguous points. if it did, these would be
90 // removed during Append() and we would have different number of shapes to points
91 wxASSERT( m_shapes.size() == m_points.size() );
92
93 // Clipper might mess up the rotation of the indices such that an arc can be split between
94 // the end point and wrap around to the start point. Lets fix the indices up now
96}
void fixIndicesRotation()
Fix indices of this chain to ensure arcs are not split between the end and start indices.
#define Z()
#define X()

References Append(), fixIndicesRotation(), m_arcs, m_points, m_shapes, SHAPE_IS_PT, X, and Z.

◆ ~SHAPE_LINE_CHAIN()

virtual SHAPE_LINE_CHAIN::~SHAPE_LINE_CHAIN ( )
inlinevirtual

Definition at line 198 of file shape_line_chain.h.

199 {}

Member Function Documentation

◆ amendArc()

void SHAPE_LINE_CHAIN::amendArc ( size_t  aArcIndex,
const VECTOR2I aNewStart,
const VECTOR2I aNewEnd 
)
protected

Definition at line 206 of file shape_line_chain.cpp.

208{
209 wxCHECK_MSG( aArcIndex < m_arcs.size(), /* void */,
210 wxT( "Invalid arc index requested." ) );
211
212 SHAPE_ARC& theArc = m_arcs[aArcIndex];
213
214 // Try to preseve the centre of the original arc
215 SHAPE_ARC newArc;
216 newArc.ConstructFromStartEndCenter( aNewStart, aNewEnd, theArc.GetCenter(),
217 theArc.IsClockwise() );
218
219 m_arcs[aArcIndex] = newArc;
220}
bool IsClockwise() const
Definition: shape_arc.cpp:363
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.
Definition: shape_arc.cpp:209
VECTOR2I GetCenter() const
Definition: shape_arc.cpp:430

References SHAPE_ARC::ConstructFromStartEndCenter(), SHAPE_ARC::GetCenter(), SHAPE_ARC::IsClockwise(), and m_arcs.

Referenced by amendArcEnd(), amendArcStart(), and splitArc().

◆ amendArcEnd()

void SHAPE_LINE_CHAIN::amendArcEnd ( size_t  aArcIndex,
const VECTOR2I aNewEnd 
)
inlineprotected

Definition at line 893 of file shape_line_chain.h.

894 {
895 amendArc( aArcIndex, m_arcs[aArcIndex].GetP0(), aNewEnd );
896 }
void amendArc(size_t aArcIndex, const VECTOR2I &aNewStart, const VECTOR2I &aNewEnd)

References amendArc(), and m_arcs.

◆ amendArcStart()

void SHAPE_LINE_CHAIN::amendArcStart ( size_t  aArcIndex,
const VECTOR2I aNewStart 
)
inlineprotected

Definition at line 888 of file shape_line_chain.h.

889 {
890 amendArc( aArcIndex, aNewStart, m_arcs[aArcIndex].GetP1() );
891 }

References amendArc(), and m_arcs.

◆ Append() [1/4]

void SHAPE_LINE_CHAIN::Append ( const SHAPE_ARC aArc)

Definition at line 1245 of file shape_line_chain.cpp.

1246{
1247 SEG startToEnd( aArc.GetP0(), aArc.GetP1() );
1248
1249 if( startToEnd.Distance( aArc.GetArcMid() ) < 1 )
1250 {
1251 // Not really a valid arc. Add as a straight line segment instead
1252 Append( aArc.GetP0() );
1253 Append( aArc.GetP1() );
1254 }
1255 else
1256 {
1257 SHAPE_LINE_CHAIN chain = aArc.ConvertToPolyline();
1258
1259 // @todo should the below 4 LOC be moved to SHAPE_ARC::ConvertToPolyline ?
1260 chain.m_arcs.push_back( aArc );
1261 chain.m_arcs.back().SetWidth( 0 );
1262
1263 for( auto& sh : chain.m_shapes )
1264 sh.first = 0;
1265
1266 Append( chain );
1267 }
1268
1269 assert( m_shapes.size() == m_points.size() );
1270}
Definition: seg.h:42
const VECTOR2I & GetArcMid() const
Definition: shape_arc.h:114
const VECTOR2I & GetP1() const
Definition: shape_arc.h:113
const VECTOR2I & GetP0() const
Definition: shape_arc.h:112
Represent a polyline containing arcs as well as line segments: A chain of connected line and/or arc s...

References Append(), SHAPE_ARC::ConvertToPolyline(), SEG::Distance(), SHAPE_ARC::GetArcMid(), SHAPE_ARC::GetP0(), SHAPE_ARC::GetP1(), m_arcs, m_points, and m_shapes.

◆ Append() [2/4]

void SHAPE_LINE_CHAIN::Append ( const SHAPE_LINE_CHAIN aOtherLine)

Append another line chain at the end.

Parameters
aOtherLineis the line chain to be appended.

Definition at line 1179 of file shape_line_chain.cpp.

1180{
1181 assert( m_shapes.size() == m_points.size() );
1182
1183 if( aOtherLine.PointCount() == 0 )
1184 {
1185 return;
1186 }
1187
1188 size_t num_arcs = m_arcs.size();
1189 m_arcs.insert( m_arcs.end(), aOtherLine.m_arcs.begin(), aOtherLine.m_arcs.end() );
1190
1191 auto fixShapeIndices =
1192 [&]( const std::pair<ssize_t, ssize_t>& aShapeIndices ) -> std::pair<ssize_t, ssize_t>
1193 {
1194 std::pair<ssize_t, ssize_t> retval = aShapeIndices;
1195
1196 alg::run_on_pair( retval, [&]( ssize_t& aIndex )
1197 {
1198 if( aIndex != SHAPE_IS_PT )
1199 aIndex = aIndex + num_arcs;
1200 } );
1201
1202 return retval;
1203 };
1204
1205 if( PointCount() == 0 || aOtherLine.CPoint( 0 ) != CPoint( -1 ) )
1206 {
1207 const VECTOR2I p = aOtherLine.CPoint( 0 );
1208 m_points.push_back( p );
1209 m_shapes.push_back( fixShapeIndices( aOtherLine.CShapes()[0] ) );
1210 m_bbox.Merge( p );
1211 }
1212 else if( aOtherLine.IsArcSegment( 0 ) )
1213 {
1214 // Associate the new arc shape with the last point of this chain
1215 if( m_shapes.back() == SHAPES_ARE_PT )
1216 m_shapes.back().first = aOtherLine.CShapes()[0].first + num_arcs;
1217 else
1218 m_shapes.back().second = aOtherLine.CShapes()[0].first + num_arcs;
1219 }
1220
1221
1222 for( int i = 1; i < aOtherLine.PointCount(); i++ )
1223 {
1224 const VECTOR2I p = aOtherLine.CPoint( i );
1225 m_points.push_back( p );
1226
1227 ssize_t arcIndex = aOtherLine.ArcIndex( i );
1228
1229 if( arcIndex != ssize_t( SHAPE_IS_PT ) )
1230 {
1231 m_shapes.push_back( fixShapeIndices( aOtherLine.m_shapes[i] ) );
1232 }
1233 else
1234 m_shapes.push_back( SHAPES_ARE_PT );
1235
1236 m_bbox.Merge( p );
1237 }
1238
1240
1241 assert( m_shapes.size() == m_points.size() );
1242}
BOX2< Vec > & Merge(const BOX2< Vec > &aRect)
Modify the position and size of the rectangle in order to contain aRect.
Definition: box2.h:588
int PointCount() const
Return the number of points (vertices) in this line chain.
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.
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 IsArcSegment(size_t aSegment) const
void run_on_pair(std::pair< _Type, _Type > &__pair, _Function __f)
Apply a function to the first and second element of a std::pair.
Definition: kicad_algo.h:44

References ArcIndex(), CPoint(), CShapes(), IsArcSegment(), m_arcs, m_bbox, m_points, m_shapes, BOX2< Vec >::Merge(), mergeFirstLastPointIfNeeded(), PointCount(), alg::run_on_pair(), SHAPE_IS_PT, and SHAPES_ARE_PT.

◆ Append() [3/4]

void SHAPE_LINE_CHAIN::Append ( const VECTOR2I aP,
bool  aAllowDuplication = false 
)
inline

Append a new point at the end of the line chain.

Parameters
aPis the new point.
aAllowDuplicationset to true to append the new point even it is the same as the last entered point or false (default) to skip it if it is the same as the last entered point.

Definition at line 506 of file shape_line_chain.h.

507 {
508 if( m_points.size() == 0 )
509 m_bbox = BOX2I( aP, VECTOR2I( 0, 0 ) );
510
511 if( m_points.size() == 0 || aAllowDuplication || CPoint( -1 ) != aP )
512 {
513 m_points.push_back( aP );
514 m_shapes.push_back( SHAPES_ARE_PT );
515 m_bbox.Merge( aP );
516 }
517 }
BOX2< VECTOR2I > BOX2I
Definition: box2.h:847
VECTOR2< int > VECTOR2I
Definition: vector2d.h:618

References CPoint(), m_bbox, m_points, m_shapes, BOX2< Vec >::Merge(), and SHAPES_ARE_PT.

◆ Append() [4/4]

void SHAPE_LINE_CHAIN::Append ( int  aX,
int  aY,
bool  aAllowDuplication = false 
)
inline

Append a new point at the end of the line chain.

Parameters
aXis X coordinate of the new point.
aYis Y coordinate of the new point.
aAllowDuplicationset to true to append the new point even if it is the same as the last entered point, false (default) to skip it if it is the same as the last entered point.

Definition at line 492 of file shape_line_chain.h.

493 {
494 VECTOR2I v( aX, aY );
495 Append( v, aAllowDuplication );
496 }

References Append().

Referenced by ZONE_FILLER::addHatchFillTypeOnZone(), PNS_PCBNEW_DEBUG_DECORATOR::AddPoint(), PNS_TEST_DEBUG_DECORATOR::AddPoint(), LIB_SHAPE::AddPoint(), SCH_SHAPE::AddPoint(), POLYGON_GEOM_MANAGER::AddPoint(), ZONE::AddPolygon(), PNS::DEBUG_DECORATOR::AddShape(), PNS::MOUSE_TRAIL_TRACER::AddTrailPoint(), PNS::DIFF_PAIR::Append(), SHAPE_SIMPLE::Append(), Append(), PNS::ArcHull(), PNS::NODE::AssembleLine(), EDA_SHAPE::beginEdit(), BOOST_AUTO_TEST_CASE(), buildBoardBoundingBoxPoly(), PAD::BuildEffectiveShapes(), BuildFootprintPolygonOutlines(), PNS::DIFF_PAIR::BuildInitial(), DIRECTION_45::BuildInitialTrace(), SHAPE_POLY_SET::BuildPolysetFromOrientedPaths(), ZONE_FILLER::buildThermalSpokes(), SHAPE_POLY_SET::chamferFilletPolygon(), PNS::KEEP_TOPOLOGY_CONSTRAINT::Check(), PNS::OPTIMIZER::circleBreakouts(), KI_TEST::CommonTestData::CommonTestData(), PCB_GRID_HELPER::computeAnchors(), SCH_SHEET_PIN::ConstrainOnEdge(), EDA_SHAPE::continueEdit(), ConvertArcToPolyline(), convertPolygon(), SHAPE_ARC::ConvertToPolyline(), PNS::ConvexHull(), PLACEFILE_GERBER_WRITER::CreatePlaceFile(), PNS::OPTIMIZER::customBreakouts(), PNS::MEANDER_PLACER::doMove(), PNS::LINE::dragSegment45(), PNS::MEANDER_SHAPE::forward(), SHAPE_POLY_SET::fractureSingle(), PNS::MEANDER_SHAPE::genMeanderShape(), CADSTAR_PCB_ARCHIVE_LOADER::getLineChainFromShapes(), PNS::MOUSE_TRAIL_TRACER::GetPosture(), KIFONT::OUTLINE_FONT::getTextAsGlyphs(), HelperShapeLineChainFromAltiumVertices(), Insert(), POLYGON_GEOM_MANAGER::IsSelfIntersecting(), PNS::ROUTER::isStartingPointRoutable(), IteratorFixture::IteratorFixture(), PNS::TOPOLOGY::LeadingRatLine(), CADSTAR_SCH_ARCHIVE_LOADER::loadBusses(), FABMASTER::loadFootprints(), CADSTAR_SCH_ARCHIVE_LOADER::loadNets(), FABMASTER::loadShapePolySet(), FABMASTER::loadZone(), PNS::MEANDER_SHAPE::MakeArc(), PNS::MEANDER_SHAPE::MakeCorner(), PNS::MEANDER_SHAPE::makeMiterShape(), CONVERT_TOOL::makePolysFromChainedSegs(), GEOM_TEST::MakeSquarePolyLine(), PNS::LINE_PLACER::mergeHead(), PNS::OPTIMIZER::mergeObtuse(), PNS::MEANDER_SHAPE::miter(), PNS::DP_MEANDER_PLACER::Move(), PNS::OctagonalHull(), ZONE_CREATE_HELPER::OnComplete(), PNS::LINE_PLACER::optimizeTailHeadTransition(), SHAPE_RECT::Outline(), SHAPE_POLY_SET::Parse(), PCB_PARSER::parseOutlinePoints(), ALTIUM_PCB::ParseRegions6Data(), partitionPolyIntoRegularCellGrid(), BRDITEMS_PLOTTER::PlotFootprintShape(), BRDITEMS_PLOTTER::PlotPcbShape(), PNS::LINE_PLACER::rhShoveOnly(), PNS::SegmentHull(), SHAPE_LINE_CHAIN(), MARKER_BASE::ShapeToPolygon(), Slice(), PNS::OPTIMIZER::smartPadsSingle(), PNS::MEANDER_SHAPE::start(), TestConcaveSquareFillet(), PNS::tightenSegment(), PNS::LINE_PLACER::Trace(), TransformCircleToPolygon(), unfracture(), SHAPE_POLY_SET::unfractureSingle(), POLYGON_GEOM_MANAGER::updateLeaderPoints(), and PNS::LINE::Walkaround().

◆ Arc()

◆ ArcCount()

size_t SHAPE_LINE_CHAIN::ArcCount ( ) const
inline

◆ ArcIndex()

ssize_t SHAPE_LINE_CHAIN::ArcIndex ( size_t  aSegment) const
inline

Return the arc index for the given segment index.

Definition at line 788 of file shape_line_chain.h.

789 {
790 if( IsSharedPt( aSegment ) )
791 return m_shapes[aSegment].second;
792 else
793 return m_shapes[aSegment].first;
794 }
bool IsSharedPt(size_t aIndex) const
Test if a point is shared between multiple shapes.

References IsSharedPt(), and m_shapes.

Referenced by Append(), PNS::NODE::AssembleLine(), PNS::MEANDER_PLACER::doMove(), fixIndicesRotation(), PNS::LINE_PLACER::FixRoute(), PCB_PLUGIN::formatPolyPts(), PNS::LINE_PLACER::handlePullback(), ALTIUM_PCB::HelperCreateBoardOutline(), GEOM_TEST::IsOutlineValid(), PNS::LINE_PLACER::mergeHead(), PNS::DP_MEANDER_PLACER::Move(), NearestPoint(), NextShape(), GERBER_PLOTTER::PlotPoly(), RemoveShape(), Slice(), Split(), and splitArc().

◆ Area()

double SHAPE_LINE_CHAIN::Area ( bool  aAbsolute = true) const

Return the area of this chain.

Parameters
aAbsoluteIf true, returns a positive value. Otherwise the value depends on the orientation of the chain

Definition at line 2030 of file shape_line_chain.cpp.

2031{
2032 // see https://www.mathopenref.com/coordpolygonarea2.html
2033
2034 if( !m_closed )
2035 return 0.0;
2036
2037 double area = 0.0;
2038 int size = m_points.size();
2039
2040 for( int i = 0, j = size - 1; i < size; ++i )
2041 {
2042 area += ( (double) m_points[j].x + m_points[i].x ) *
2043 ( (double) m_points[j].y - m_points[i].y );
2044 j = i;
2045 }
2046
2047 if( aAbsolute )
2048 return std::fabs( area * 0.5 ); // The result would be negative if points are anti-clockwise
2049 else
2050 return -area * 0.5; // The result would be negative if points are anti-clockwise
2051}

References m_closed, and m_points.

Referenced by ZONE_FILLER::addHatchFillTypeOnZone(), SHAPE_POLY_SET::Area(), TEARDROP_MANAGER::ComputePointsOnPadVia(), convertToClipper(), ZONE_FILLER::Fill(), FOOTPRINT::GetCoverageArea(), DIALOG_BOARD_STATISTICS::getDataFromPCB(), PNS::MOUSE_TRAIL_TRACER::GetPosture(), unfracture(), and SHAPE_POLY_SET::unfractureSingle().

◆ BBox()

const BOX2I SHAPE_LINE_CHAIN::BBox ( int  aClearance = 0) const
inlineoverridevirtual

Compute a bounding box of the shape, with a margin of aClearance a collision.

Parameters
aClearancehow much the bounding box is expanded wrs to the minimum enclosing rectangle for the shape.
Returns
the bounding box.

Implements SHAPE.

Definition at line 430 of file shape_line_chain.h.

431 {
432 BOX2I bbox;
433 bbox.Compute( m_points );
434
435 if( aClearance != 0 || m_width != 0 )
436 bbox.Inflate( aClearance + m_width );
437
438 return bbox;
439 }
BOX2< Vec > & Inflate(coord_type dx, coord_type dy)
Inflates the rectangle horizontally by dx and vertically by dy.
Definition: box2.h:506
void Compute(const Container &aPointList)
Compute the bounding box from a given list of points.
Definition: box2.h:82

References BOX2< Vec >::Compute(), BOX2< Vec >::Inflate(), m_points, and m_width.

Referenced by SHAPE_SIMPLE::BBox(), PNS::KEEP_TOPOLOGY_CONSTRAINT::Check(), AR_AUTOPLACER::fillMatrix(), POLYGON_TEST::FindPairs(), DIALOG_BOARD_STATISTICS::getDataFromPCB(), Intersect(), FABMASTER::loadZones(), PNS::COMPONENT_DRAGGER::Start(), and PolygonTriangulation::TesselatePolygon().

◆ CalcShape()

SGNODE * SHAPE::CalcShape ( SGNODE aParent,
SGNODE aColor,
WRL1_ORDER  aVertexOrder,
float  aCreaseLimit = 0.74317,
bool  isVRML2 = false 
)
inherited

Definition at line 703 of file wrlfacet.cpp.

705{
706 if( facets.empty() || !facets.front()->HasMinPoints() )
707 return nullptr;
708
709 std::vector< std::list< FACET* > > flist;
710
711 // determine the max. index and size flist as appropriate
712 std::list< FACET* >::iterator sF = facets.begin();
713 std::list< FACET* >::iterator eF = facets.end();
714
715 int maxIdx = 0;
716 int tmi;
717 float maxV = 0.0;
718 float tV = 0.0;
719
720 while( sF != eF )
721 {
722 tV = ( *sF )->CalcFaceNormal();
723 tmi = ( *sF )->GetMaxIndex();
724
725 if( tmi > maxIdx )
726 maxIdx = tmi;
727
728 if( tV > maxV )
729 maxV = tV;
730
731 ++sF;
732 }
733
734 ++maxIdx;
735
736 if( maxIdx < 3 )
737 return nullptr;
738
739 flist.resize( maxIdx );
740
741 // create the lists of facets common to indices
742 sF = facets.begin();
743
744 while( sF != eF )
745 {
746 ( *sF )->Renormalize( tV );
747 ( *sF )->CollectVertices( flist );
748 ++sF;
749 }
750
751 // calculate the normals
752 size_t vs = flist.size();
753
754 for( size_t i = 0; i < vs; ++i )
755 {
756 sF = flist[i].begin();
757 eF = flist[i].end();
758
759 while( sF != eF )
760 {
761 ( *sF )->CalcVertexNormal( static_cast<int>( i ), flist[i], aCreaseLimit );
762 ++sF;
763 }
764 }
765
766 std::vector< WRLVEC3F > vertices;
767 std::vector< WRLVEC3F > normals;
768 std::vector< SGCOLOR > colors;
769
770 // push the facet data to the final output list
771 sF = facets.begin();
772 eF = facets.end();
773
774 while( sF != eF )
775 {
776 ( *sF )->GetData( vertices, normals, colors, aVertexOrder );
777 ++sF;
778 }
779
780 flist.clear();
781
782 if( vertices.size() < 3 )
783 return nullptr;
784
785 IFSG_SHAPE shapeNode( false );
786
787 if( !isVRML2 )
788 {
789 shapeNode.NewNode( aParent );
790
791 if( aColor )
792 {
793 if( nullptr == S3D::GetSGNodeParent( aColor ) )
794 shapeNode.AddChildNode( aColor );
795 else
796 shapeNode.AddRefNode( aColor );
797 }
798 }
799
800 std::vector< SGPOINT > lCPts; // vertex points in SGPOINT (double) format
801 std::vector< SGVECTOR > lCNorm; // per-vertex normals
802 vs = vertices.size();
803
804 for( size_t i = 0; i < vs; ++i )
805 {
806 SGPOINT pt;
807 pt.x = vertices[i].x;
808 pt.y = vertices[i].y;
809 pt.z = vertices[i].z;
810 lCPts.push_back( pt );
811 lCNorm.emplace_back( normals[i].x, normals[i].y, normals[i].z );
812 }
813
814 vertices.clear();
815 normals.clear();
816
817 IFSG_FACESET fsNode( false );
818
819 if( !isVRML2 )
820 fsNode.NewNode( shapeNode );
821 else
822 fsNode.NewNode( aParent );
823
824 IFSG_COORDS cpNode( fsNode );
825 cpNode.SetCoordsList( lCPts.size(), &lCPts[0] );
826 IFSG_COORDINDEX ciNode( fsNode );
827
828 for( int i = 0; i < (int)lCPts.size(); ++i )
829 ciNode.AddIndex( i );
830
831 IFSG_NORMALS nmNode( fsNode );
832 nmNode.SetNormalList( lCNorm.size(), &lCNorm[0] );
833
834 if( !colors.empty() )
835 {
836 IFSG_COLORS nmColor( fsNode );
837 nmColor.SetColorList( colors.size(), &colors[0] );
838 colors.clear();
839 }
840
841 if( !isVRML2 )
842 return shapeNode.GetRawPtr();
843
844 return fsNode.GetRawPtr();
845}
IFSG_COLORS is the wrapper for SGCOLORS.
Definition: ifsg_colors.h:42
IFSG_COORDINDEX is the wrapper for SGCOORDINDEX.
IFSG_COORDS is the wrapper for SGCOORDS.
Definition: ifsg_coords.h:41
IFSG_FACESET is the wrapper for the SGFACESET class.
Definition: ifsg_faceset.h:41
IFSG_NORMALS is the wrapper for the SGNORMALS class.
Definition: ifsg_normals.h:41
IFSG_SHAPE is the wrapper for the SGSHAPE class.
Definition: ifsg_shape.h:41
double z
Definition: sg_base.h:72
double x
Definition: sg_base.h:70
double y
Definition: sg_base.h:71
std::list< FACET * > facets
Definition: wrlfacet.h:143
SGLIB_API SGNODE * GetSGNodeParent(SGNODE *aNode)
Definition: ifsg_api.cpp:494

References IFSG_NODE::AddChildNode(), IFSG_INDEX::AddIndex(), IFSG_NODE::AddRefNode(), SHAPE::facets, IFSG_NODE::GetRawPtr(), S3D::GetSGNodeParent(), IFSG_FACESET::NewNode(), IFSG_SHAPE::NewNode(), IFSG_COLORS::SetColorList(), IFSG_COORDS::SetCoordsList(), IFSG_NORMALS::SetNormalList(), SGPOINT::x, SGPOINT::y, and SGPOINT::z.

Referenced by WRL2FACESET::TranslateToSG(), X3DIFACESET::TranslateToSG(), and WRL1FACESET::TranslateToSG().

◆ CArcs()

const std::vector< SHAPE_ARC > & SHAPE_LINE_CHAIN::CArcs ( ) const
inline
Returns
the vector of stored arcs.

Definition at line 416 of file shape_line_chain.h.

417 {
418 return m_arcs;
419 }

References m_arcs.

Referenced by ROUTER_PREVIEW_ITEM::drawLineChain(), PNS::LINE_PLACER::handlePullback(), Length(), and PNS::LINE_PLACER::mergeHead().

◆ Centre()

virtual VECTOR2I SHAPE::Centre ( ) const
inlinevirtualinherited

Compute a center-of-mass of the shape.

Returns
the center-of-mass point

Definition at line 229 of file shape.h.

230 {
231 return BBox( 0 ).Centre(); // if nothing better is available....
232 }
Vec Centre() const
Definition: box2.h:70
virtual const BOX2I BBox(int aClearance=0) const =0
Compute a bounding box of the shape, with a margin of aClearance a collision.

References SHAPE::BBox(), and BOX2< Vec >::Centre().

Referenced by Collide().

◆ CheckClearance()

bool SHAPE_LINE_CHAIN::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.

Parameters
aPis the point to check.
aDistis the distance in internal units.
Returns
true if the point is equal to or closer than aDist to the line chain.

Definition at line 1619 of file shape_line_chain.cpp.

1620{
1621 if( !PointCount() )
1622 return false;
1623 else if( PointCount() == 1 )
1624 return m_points[0] == aP;
1625
1626 for( int i = 0; i < SegmentCount(); i++ )
1627 {
1628 const SEG s = CSegment( i );
1629
1630 if( s.A == aP || s.B == aP )
1631 return true;
1632
1633 if( s.Distance( aP ) <= aDist )
1634 return true;
1635 }
1636
1637 return false;
1638}
VECTOR2I A
Definition: seg.h:49
VECTOR2I B
Definition: seg.h:50
int Distance(const SEG &aSeg) const
Compute minimum Euclidean distance to segment aSeg.
Definition: seg.cpp:319
int SegmentCount() const
Return the number of segments in this line chain.
const SEG CSegment(int aIndex) const
Return a constant copy of the aIndex segment in the line chain.

References SEG::A, SEG::B, CSegment(), SEG::Distance(), m_points, PointCount(), and SegmentCount().

◆ CLastPoint()

const VECTOR2I & SHAPE_LINE_CHAIN::CLastPoint ( ) const
inline

Return the last point in the line chain.

Definition at line 408 of file shape_line_chain.h.

409 {
410 return m_points[static_cast<size_t>( PointCount() ) - 1];
411 }

References m_points, and PointCount().

Referenced by BOOST_AUTO_TEST_CASE(), EDA_SHAPE::continueEdit(), POLYGON_GEOM_MANAGER::DeleteLastCorner(), EDA_SHAPE::endEdit(), and POLYGON_GEOM_MANAGER::updateLeaderPoints().

◆ Clear()

◆ ClearArcs()

void SHAPE_LINE_CHAIN::ClearArcs ( )

Remove all arc references in the line chain, resulting in a chain formed only of straight segments.

Any arcs in the chain are removed and only the piecewise linear approximation remains.

Definition at line 599 of file shape_line_chain.cpp.

600{
601 for( ssize_t arcIndex = m_arcs.size() - 1; arcIndex >= 0; --arcIndex )
602 convertArc( arcIndex );
603}
void convertArc(ssize_t aArcIndex)
Convert an arc to only a point chain by removing the arc and references.

References convertArc(), and m_arcs.

◆ Clone()

SHAPE * SHAPE_LINE_CHAIN::Clone ( ) const
overridevirtual

Return a dynamically allocated copy of the shape.

Return values
copyof the shape

Reimplemented from SHAPE.

Definition at line 1951 of file shape_line_chain.cpp.

1952{
1953 return new SHAPE_LINE_CHAIN( *this );
1954}
SHAPE_LINE_CHAIN()
Initialize an empty line chain.

References SHAPE_LINE_CHAIN().

◆ Collide() [1/4]

bool SHAPE_LINE_CHAIN::Collide ( const SEG aSeg,
int  aClearance = 0,
int *  aActual = nullptr,
VECTOR2I aLocation = nullptr 
) const
overridevirtual

Check if segment aSeg lies closer to us than aClearance.

Note: This is overridden as we want to ensure we test collisions with the arcs in this chain as true arcs rather than segment approximations.

Parameters
aSegthe segment to check for collisions with
aClearanceminimum distance that does not qualify as a collision.
aActualan optional pointer to an int to store the actual distance in the event of a collision.
Returns
true, when a collision has been found

Reimplemented from SHAPE_LINE_CHAIN_BASE.

Definition at line 490 of file shape_line_chain.cpp.

492{
493 if( IsClosed() && PointInside( aSeg.A ) )
494 {
495 if( aLocation )
496 *aLocation = aSeg.A;
497
498 if( aActual )
499 *aActual = 0;
500
501 return true;
502 }
503
504 SEG::ecoord closest_dist_sq = VECTOR2I::ECOORD_MAX;
505 SEG::ecoord clearance_sq = SEG::Square( aClearance );
506 VECTOR2I nearest;
507
508 // Collide line segments
509 for( size_t i = 0; i < GetSegmentCount(); i++ )
510 {
511 if( IsArcSegment( i ) )
512 continue;
513
514 const SEG& s = GetSegment( i );
515 SEG::ecoord dist_sq = s.SquaredDistance( aSeg );
516
517 if( dist_sq < closest_dist_sq )
518 {
519 if( aLocation )
520 nearest = s.NearestPoint( aSeg );
521
522 closest_dist_sq = dist_sq;
523
524 if( closest_dist_sq == 0 )
525 break;
526
527 // If we're not looking for aActual then any collision will do
528 if( closest_dist_sq < clearance_sq && !aActual )
529 break;
530 }
531 }
532
533 if( closest_dist_sq == 0 || closest_dist_sq < clearance_sq )
534 {
535 if( aLocation )
536 *aLocation = nearest;
537
538 if( aActual )
539 *aActual = sqrt( closest_dist_sq );
540
541 return true;
542 }
543
544 // Collide arc segments
545 for( size_t i = 0; i < ArcCount(); i++ )
546 {
547 const SHAPE_ARC& arc = Arc( i );
548
549 // The arcs in the chain should have zero width
550 wxASSERT_MSG( arc.GetWidth() == 0, wxT( "Invalid arc width - should be zero" ) );
551
552 if( arc.Collide( aSeg, aClearance, aActual, aLocation ) )
553 return true;
554 }
555
556 return false;
557}
ecoord SquaredDistance(const SEG &aSeg) const
Definition: seg.cpp:75
VECTOR2I::extended_type ecoord
Definition: seg.h:44
const VECTOR2I NearestPoint(const VECTOR2I &aP) const
Compute a point on the segment (this) that is closest to point aP.
Definition: seg.cpp:261
static SEG::ecoord Square(int a)
Definition: seg.h:123
int GetWidth() const
Definition: shape_arc.h:157
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,...
Definition: shape_arc.cpp:241
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.
const SHAPE_ARC & Arc(size_t aArc) const
bool IsClosed() const override
virtual const SEG GetSegment(int aIndex) const override
virtual size_t GetSegmentCount() const override
size_t ArcCount() const
static constexpr extended_type ECOORD_MAX
Definition: vector2d.h:79

References SEG::A, Arc(), ArcCount(), SHAPE_ARC::Collide(), VECTOR2< int >::ECOORD_MAX, GetSegment(), GetSegmentCount(), SHAPE_ARC::GetWidth(), IsArcSegment(), IsClosed(), SEG::NearestPoint(), SHAPE_LINE_CHAIN_BASE::PointInside(), SEG::Square(), and SEG::SquaredDistance().

◆ Collide() [2/4]

bool SHAPE::Collide ( const SHAPE aShape,
int  aClearance,
VECTOR2I aMTV 
) const
virtualinherited

Check if the boundary of shape (this) lies closer to the shape aShape than aClearance, indicating a collision.

Parameters
aShapeshape to check collision against
aClearanceminimum clearance
aMTVminimum translation vector
aActual[out] an optional pointer to an int to store the actual distance in the event of a collision.
aLocation[out] an option pointer to a point to store a nearby location in the event of a collision.
Returns
true, if there is a collision.

Reimplemented in SHAPE_COMPOUND, SHAPE_RECT, and SHAPE_SEGMENT.

Definition at line 1109 of file shape_collisions.cpp.

1110{
1111 return collideShapes( this, aShape, aClearance, nullptr, nullptr, aMTV );
1112}
static bool collideShapes(const SHAPE *aA, const SHAPE *aB, int aClearance, int *aActual, VECTOR2I *aLocation, VECTOR2I *aMTV)

References collideShapes().

◆ Collide() [3/4]

bool SHAPE::Collide ( const SHAPE aShape,
int  aClearance = 0,
int *  aActual = nullptr,
VECTOR2I aLocation = nullptr 
) const
virtualinherited

Reimplemented in SHAPE_ARC, SHAPE_COMPOUND, SHAPE_POLY_SET, SHAPE_RECT, and SHAPE_SEGMENT.

Definition at line 1115 of file shape_collisions.cpp.

1116{
1117 return collideShapes( this, aShape, aClearance, aActual, aLocation, nullptr );
1118}

References collideShapes().

◆ Collide() [4/4]

bool SHAPE_LINE_CHAIN::Collide ( const VECTOR2I aP,
int  aClearance = 0,
int *  aActual = nullptr,
VECTOR2I aLocation = nullptr 
) const
overridevirtual

Check if point aP lies closer to us than aClearance.

Note: This is overridden as we want to ensure we test collisions with the arcs in this chain as true arcs rather than segment approximations.

Parameters
aPthe point to check for collisions with
aClearanceminimum distance that does not qualify as a collision.
aActualan optional pointer to an int to store the actual distance in the event of a collision.
Returns
true, when a collision has been found

Reimplemented from SHAPE_LINE_CHAIN_BASE.

Definition at line 357 of file shape_line_chain.cpp.

359{
360 if( IsClosed() && PointInside( aP, aClearance ) )
361 {
362 if( aLocation )
363 *aLocation = aP;
364
365 if( aActual )
366 *aActual = 0;
367
368 return true;
369 }
370
371 SEG::ecoord closest_dist_sq = VECTOR2I::ECOORD_MAX;
372 SEG::ecoord clearance_sq = SEG::Square( aClearance );
373 VECTOR2I nearest;
374
375 // Collide line segments
376 for( size_t i = 0; i < GetSegmentCount(); i++ )
377 {
378 if( IsArcSegment( i ) )
379 continue;
380
381 const SEG& s = GetSegment( i );
382 VECTOR2I pn = s.NearestPoint( aP );
383 SEG::ecoord dist_sq = ( pn - aP ).SquaredEuclideanNorm();
384
385 if( dist_sq < closest_dist_sq )
386 {
387 nearest = pn;
388 closest_dist_sq = dist_sq;
389
390 if( closest_dist_sq == 0 )
391 break;
392
393 // If we're not looking for aActual then any collision will do
394 if( closest_dist_sq < clearance_sq && !aActual )
395 break;
396 }
397 }
398
399 if( closest_dist_sq == 0 || closest_dist_sq < clearance_sq )
400 {
401 if( aLocation )
402 *aLocation = nearest;
403
404 if( aActual )
405 *aActual = sqrt( closest_dist_sq );
406
407 return true;
408 }
409
410 // Collide arc segments
411 for( size_t i = 0; i < ArcCount(); i++ )
412 {
413 const SHAPE_ARC& arc = Arc( i );
414
415 // The arcs in the chain should have zero width
416 wxASSERT_MSG( arc.GetWidth() == 0, wxT( "Invalid arc width - should be zero" ) );
417
418 if( arc.Collide( aP, aClearance, aActual, aLocation ) )
419 return true;
420 }
421
422 return false;
423}

References Arc(), ArcCount(), SHAPE_ARC::Collide(), VECTOR2< int >::ECOORD_MAX, GetSegment(), GetSegmentCount(), SHAPE_ARC::GetWidth(), IsArcSegment(), IsClosed(), SEG::NearestPoint(), SHAPE_LINE_CHAIN_BASE::PointInside(), and SEG::Square().

Referenced by PNS::MEANDERED_LINE::CheckSelfIntersections(), SHAPE_SIMPLE::Collide(), PCB_SELECTION_TOOL::hitTestDistance(), and DRC_TEST_PROVIDER_PHYSICAL_CLEARANCE::testZoneLayer().

◆ CompareGeometry()

bool SHAPE_LINE_CHAIN::CompareGeometry ( const SHAPE_LINE_CHAIN aOther) const

Definition at line 1925 of file shape_line_chain.cpp.

1926{
1927 SHAPE_LINE_CHAIN a(*this), b( aOther );
1928 a.Simplify();
1929 b.Simplify();
1930
1931 if( a.m_points.size() != b.m_points.size() )
1932 return false;
1933
1934 for( int i = 0; i < a.PointCount(); i++ )
1935 {
1936 if( a.CPoint( i ) != b.CPoint( i ) )
1937 return false;
1938 }
1939
1940 return true;
1941}

References CPoint(), m_points, and Simplify().

Referenced by PNS::LINE::CompareGeometry().

◆ convertArc()

void SHAPE_LINE_CHAIN::convertArc ( ssize_t  aArcIndex)
protected

Convert an arc to only a point chain by removing the arc and references.

Parameters
aArcIndexindex of the arc to convert to points

Definition at line 177 of file shape_line_chain.cpp.

178{
179 if( aArcIndex < 0 )
180 aArcIndex += m_arcs.size();
181
182 if( aArcIndex >= static_cast<ssize_t>( m_arcs.size() ) )
183 return;
184
185 // Clear the shapes references
186 for( auto& sh : m_shapes )
187 {
189 [&]( ssize_t& aShapeIndex )
190 {
191 if( aShapeIndex == aArcIndex )
192 aShapeIndex = SHAPE_IS_PT;
193
194 if( aShapeIndex > aArcIndex )
195 --aShapeIndex;
196 } );
197
198 if( sh.second != SHAPE_IS_PT && sh.first == SHAPE_IS_PT )
199 std::swap( sh.first, sh.second );
200 }
201
202 m_arcs.erase( m_arcs.begin() + aArcIndex );
203}

References m_arcs, m_shapes, alg::run_on_pair(), and SHAPE_IS_PT.

Referenced by ClearArcs(), Remove(), and SetPoint().

◆ convertToClipper()

ClipperLib::Path SHAPE_LINE_CHAIN::convertToClipper ( bool  aRequiredOrientation,
std::vector< CLIPPER_Z_VALUE > &  aZValueBuffer,
std::vector< SHAPE_ARC > &  aArcBuffer 
) const
protected

Create a new Clipper path from the SHAPE_LINE_CHAIN in a given orientation.

Definition at line 98 of file shape_line_chain.cpp.

101{
102 ClipperLib::Path c_path;
103 SHAPE_LINE_CHAIN input;
104 bool orientation = Area( false ) >= 0;
105 ssize_t shape_offset = aArcBuffer.size();
106
107 if( orientation != aRequiredOrientation )
108 input = Reverse();
109 else
110 input = *this;
111
112 int pointCount = input.PointCount();
113 c_path.reserve( pointCount );
114
115 for( int i = 0; i < pointCount; i++ )
116 {
117 const VECTOR2I& vertex = input.CPoint( i );
118
119 CLIPPER_Z_VALUE z_value( input.m_shapes[i], shape_offset );
120 size_t z_value_ptr = aZValueBuffer.size();
121 aZValueBuffer.push_back( z_value );
122
123 c_path.emplace_back( vertex.x, vertex.y, z_value_ptr );
124 }
125
126 aArcBuffer.insert( aArcBuffer.end(), input.m_arcs.begin(), input.m_arcs.end() );
127
128 return c_path;
129}
const SHAPE_LINE_CHAIN Reverse() const
Reverse point order in the line chain.
double Area(bool aAbsolute=true) const
Return the area of this chain.
Holds information on each point of a SHAPE_LINE_CHAIN that is retrievable after an operation with Cli...

References Area(), CPoint(), m_arcs, m_shapes, PointCount(), Reverse(), VECTOR2< T >::x, and VECTOR2< T >::y.

◆ CPoint()

const VECTOR2I & SHAPE_LINE_CHAIN::CPoint ( int  aIndex) const
inline

Return a reference to a given point in the line chain.

Parameters
aIndexis the index of the point.
Returns
a const reference to the point.

Definition at line 390 of file shape_line_chain.h.

391 {
392 if( aIndex < 0 )
393 aIndex += PointCount();
394 else if( aIndex >= PointCount() )
395 aIndex -= PointCount();
396
397 return m_points[aIndex];
398 }

References m_points, and PointCount().

Referenced by LABEL_MANAGER::Add(), EE_POINT_EDITOR::addCorner(), POLYGON_GEOM_MANAGER::AddPoint(), SHAPE_LINE_CHAIN::POINT_INSIDE_TRACKER::AddPolyline(), TRIANGLE_DISPLAY_LIST::AddToMiddleContourns(), PNS::MOUSE_TRAIL_TRACER::AddTrailPoint(), Append(), PNS::LINE::AppendVia(), ArePolylineEndPointsNearCircle(), ArePolylineMidPointsNearCircle(), PNS::NODE::AssembleLine(), PNS::TOPOLOGY::AssembleTuningPath(), BOOST_AUTO_TEST_CASE(), BuildConvexHull(), PAD::BuildEffectivePolygon(), PAD::BuildEffectiveShapes(), PNS::LINE_PLACER::buildInitialLine(), SHAPE_POLY_SET::chamferFilletPolygon(), PNS::LINE::ChangedArea(), PNS::KEEP_TOPOLOGY_CONSTRAINT::Check(), CN_VISITOR::checkZoneZoneConnection(), CompareGeometry(), EDA_SHAPE::continueEdit(), convertPolygon(), convertToClipper(), PNS::coupledBypass(), PNS::LINE::CPoint(), SHAPE_SIMPLE::CPoint(), PolygonTriangulation::createList(), POLYGON_TEST::createList(), CreatePadsShapesSection(), PNS::cursorDistMinimum(), PNS::LINE::dragCorner45(), PNS::dragCornerInternal(), KIGFX::PCB_PAINTER::draw(), APERTURE_MACRO::DrawApertureMacroShape(), KIGFX::CAIRO_GAL_BASE::drawPoly(), KIGFX::OPENGL_GAL::DrawPolygon(), KIGFX::OPENGL_GAL::DrawPolyline(), KIGFX::CAIRO_GAL_BASE::DrawSegmentChain(), KIGFX::OPENGL_GAL::DrawSegmentChain(), EDA_SHAPE::endEdit(), EXPORTER_PCB_VRML::ExportVrmlBoard(), EXPORTER_PCB_VRML::ExportVrmlPolygonSet(), DSN::SPECCTRA_DB::fillBOUNDARY(), AR_AUTOPLACER::fillMatrix(), Find(), PNS::LINE_PLACER::FixRoute(), CADSTAR_SCH_ARCHIVE_LOADER::fixUpLibraryPins(), GERBER_PLOTTER::FlashPadChamferRoundRect(), DXF_PLOTTER::FlashPadCustom(), HPGL_PLOTTER::FlashPadCustom(), PSLIKE_PLOTTER::FlashPadCustom(), GERBER_PLOTTER::FlashPadCustom(), DXF_PLOTTER::FlashPadRoundRect(), GERBER_PLOTTER::FlashPadRoundRect(), HPGL_PLOTTER::FlashPadRoundRect(), PSLIKE_PLOTTER::FlashPadRoundRect(), PNS::TOPOLOGY::followTrivialPath(), PCB_PLUGIN::formatPolyPts(), PCB_SHAPE::GetFocusPosition(), GetPoint(), SHAPE_SIMPLE::GetPoint(), PNS::MOUSE_TRAIL_TRACER::GetPosture(), CADSTAR_SCH_ARCHIVE_LOADER::getScaledLibPart(), PNS::MOUSE_TRAIL_TRACER::GetTrailLeadVector(), PNS::LINE_PLACER::handlePullback(), PNS::LINE_PLACER::handleSelfIntersections(), DS_DRAW_ITEM_POLYPOLYGONS::HitTest(), GEOM_TEST::IsOutlineValid(), POLYGON_GEOM_MANAGER::IsSelfIntersecting(), DSN::SPECCTRA_DB::makeIMAGE(), DSN::SPECCTRA_DB::makePADSTACK(), PNS::LINE_PLACER::mergeHead(), PNS::MEANDER_SHAPE::miter(), PNS::DP_MEANDER_PLACER::Move(), PNS::LINE_PLACER::Move(), NearestPoint(), POLYGON_GEOM_MANAGER::NewPointClosesOutline(), operator!=(), BOOST_TEST_PRINT_NAMESPACE_OPEN::print_log_value< SHAPE_LINE_CHAIN >::operator()(), PNS::LINE_PLACER::optimizeTailHeadTransition(), BITMAPCONV_INFO::outputOnePolygon(), SCH_SEXPR_PARSER::ParseSchematic(), PlotDrawingSheet(), PLOTTER::PlotPoly(), GERBER_PLOTTER::PlotPoly(), PointAlong(), PNS::pointInside2(), polygon_Convert(), SCH_SHAPE::Print(), LIB_SHAPE::print(), GERBER_DRAW_ITEM::PrintGerberPoly(), DS_DRAW_ITEM_POLYPOLYGONS::PrintWsItem(), DRC_RTREE::QueryColliding(), PNS::LINE_PLACER::removeLoops(), PNS::DIFF_PAIR_PLACER::routeHead(), DRC_TEST_PROVIDER_CONNECTION_WIDTH::Run(), PNS::OPTIMIZER::runSmartPads(), KIGFX::PREVIEW::POLYGON_ITEM::SetPoints(), PNS::shovedArea(), PNS::SHOVE::shoveLineFromLoneVia(), PNS::SHOVE::shoveLineToHullSet(), Simplify(), PNS::OPTIMIZER::smartPadsSingle(), PNS::COMPONENT_DRAGGER::Start(), unfracture(), SHAPE_POLY_SET::unfractureSingle(), PNS::MEANDER_SHAPE::updateBaseSegment(), POLYGON_GEOM_MANAGER::updateLeaderPoints(), PNS::LINE::Walkaround(), HYPERLYNX_EXPORTER::writeNetObjects(), GBR_TO_PCB_EXPORTER::writePcbPolygon(), and GBR_TO_PCB_EXPORTER::writePcbZoneItem().

◆ CPoints()

◆ CSegment()

const SEG SHAPE_LINE_CHAIN::CSegment ( int  aIndex) const
inline

Return a constant copy of the aIndex segment in the line chain.

Parameters
aIndexis the index of the segment in the line chain. Negative values are counted from the end (i.e. -1 means the last segment in the line chain).
Returns
a segment at aIndex in the line chain.

Definition at line 345 of file shape_line_chain.h.

346 {
347 if( aIndex < 0 )
348 aIndex += SegmentCount();
349
350 if( aIndex == (int)( m_points.size() - 1 ) && m_closed )
351 return SEG( m_points[aIndex], m_points[0], aIndex );
352 else
353 return SEG( m_points[aIndex], m_points[aIndex + 1], aIndex );
354 }

References m_closed, m_points, and SegmentCount().

Referenced by PNS::NODE::Add(), PNS::MOUSE_TRAIL_TRACER::AddTrailPoint(), PNS::ArcHull(), PNS::LINE_PLACER::buildInitialLine(), PNS::LINE::ChangedArea(), PNS::PRESERVE_VERTEX_CONSTRAINT::Check(), CheckClearance(), PNS::NODE::CheckColliding(), PNS::DIFF_PAIR::CheckConnectionAngle(), PNS::checkGap(), PNS::MEANDERED_LINE::CheckSelfIntersections(), PNS::LINE::ClipToNearestObstacle(), PNS::closestProjectedPoint(), PCB_GRID_HELPER::computeAnchors(), PNS::COST_ESTIMATOR::CornerCost(), PNS::LINE::CountCorners(), PNS::coupledBypass(), PNS::DIFF_PAIR::CoupledLength(), PNS::LINE::CSegment(), PNS::cursorDistMinimum(), PNS::MEANDER_PLACER_BASE::cutTunedLine(), PNS::MEANDER_PLACER::doMove(), PNS::dragCornerInternal(), PNS::findCoupledVertices(), FindSegment(), PNS::DIFF_PAIR_PLACER::FixRoute(), PNS::LINE_PLACER::FixRoute(), EDA_SHAPE::GetLength(), PNS::MOUSE_TRAIL_TRACER::GetPosture(), GetSegment(), SHAPE_SIMPLE::GetSegment(), PNS::LINE_PLACER::handlePullback(), PNS::LINE_PLACER::handleSelfIntersections(), PNS::HullIntersection(), Intersect(), isLine45Degree(), Length(), PNS::OPTIMIZER::mergeColinear(), PNS::OPTIMIZER::mergeDpStep(), PNS::LINE_PLACER::mergeHead(), PNS::OPTIMIZER::mergeObtuse(), PNS::OPTIMIZER::mergeStep(), PNS::NODE::NearestObstacle(), NearestPoint(), NearestSegment(), PathLength(), PointAlong(), KIGFX::VIEW_OVERLAY::Polyline(), PNS::LINE_PLACER::reduceTail(), DRC_TEST_PROVIDER_EDGE_CLEARANCE::Run(), PNS::SegmentHull(), SelfIntersecting(), PNS::OPTIMIZER::smartPadsSingle(), PNS::LINE::snapDraggedCorner(), PNS::LINE::snapToNeighbourSegments(), Split(), DRC_TEST_PROVIDER_PHYSICAL_CLEARANCE::testShapeLineChain(), PNS::tightenSegment(), SHAPE_POLY_SET::unfractureSingle(), and HYPERLYNX_EXPORTER::writeBoardInfo().

◆ CShapes()

const std::vector< std::pair< ssize_t, ssize_t > > & SHAPE_LINE_CHAIN::CShapes ( ) const
inline
Returns
the vector of values indicating shape type and location.

Definition at line 424 of file shape_line_chain.h.

425 {
426 return m_shapes;
427 }

References m_shapes.

Referenced by Append(), and BOOST_AUTO_TEST_CASE().

◆ Distance()

int SHAPE_LINE_CHAIN::Distance ( const VECTOR2I aP,
bool  aOutlineOnly = false 
) const

Compute the minimum distance between the line chain and a point aP.

Parameters
aPthe point.
Returns
minimum distance.

Definition at line 797 of file shape_line_chain.cpp.

798{
799 return sqrt( SquaredDistance( aP, aOutlineOnly ) );
800}
SEG::ecoord SquaredDistance(const VECTOR2I &aP, bool aOutlineOnly=false) const

References SHAPE_LINE_CHAIN_BASE::SquaredDistance().

Referenced by PAD::GetBestAnchorPosition().

◆ EdgeContainingPoint()

int SHAPE_LINE_CHAIN_BASE::EdgeContainingPoint ( const VECTOR2I aP,
int  aAccuracy = 0 
) const
inherited

Check if point aP lies on an edge or vertex of the line chain.

Parameters
aPpoint to check
Returns
index of the first edge containing the point, otherwise negative

Definition at line 1592 of file shape_line_chain.cpp.

1593{
1594 if( !GetPointCount() )
1595 {
1596 return -1;
1597 }
1598 else if( GetPointCount() == 1 )
1599 {
1600 VECTOR2I dist = GetPoint(0) - aPt;
1601 return ( hypot( dist.x, dist.y ) <= aAccuracy + 1 ) ? 0 : -1;
1602 }
1603
1604 for( size_t i = 0; i < GetSegmentCount(); i++ )
1605 {
1606 const SEG s = GetSegment( i );
1607
1608 if( s.A == aPt || s.B == aPt )
1609 return i;
1610
1611 if( s.Distance( aPt ) <= aAccuracy + 1 )
1612 return i;
1613 }
1614
1615 return -1;
1616}
virtual size_t GetPointCount() const =0
virtual size_t GetSegmentCount() const =0
virtual const VECTOR2I GetPoint(int aIndex) const =0
virtual const SEG GetSegment(int aIndex) const =0

References SEG::A, SEG::B, SEG::Distance(), SHAPE_LINE_CHAIN_BASE::GetPoint(), SHAPE_LINE_CHAIN_BASE::GetPointCount(), SHAPE_LINE_CHAIN_BASE::GetSegment(), SHAPE_LINE_CHAIN_BASE::GetSegmentCount(), VECTOR2< T >::x, and VECTOR2< T >::y.

Referenced by SHAPE_LINE_CHAIN_BASE::PointOnEdge().

◆ Find()

int SHAPE_LINE_CHAIN::Find ( const VECTOR2I aP,
int  aThreshold = 0 
) const

Search for point aP.

Parameters
aPis the point to be looked for.
Returns
the index of the corresponding point in the line chain or negative when not found.

Definition at line 870 of file shape_line_chain.cpp.

871{
872 for( int s = 0; s < PointCount(); s++ )
873 {
874 if( aThreshold == 0 )
875 {
876 if( CPoint( s ) == aP )
877 return s;
878 }
879 else
880 {
881 if( (CPoint( s ) - aP).EuclideanNorm() <= aThreshold )
882 return s;
883 }
884 }
885
886 return -1;
887}

References CPoint(), and PointCount().

Referenced by PNS::MEANDER_PLACER_BASE::cutTunedLine(), PNS::DRAGGER::dragViaMarkObstacles(), PNS::DRAGGER::dragViaWalkaround(), PNS::NODE::FindLinesBetweenJoints(), PNS::DRAGGER::optimizeAndUpdateDraggedLine(), Split(), and PNS::LINE::Walkaround().

◆ FindSegment()

int SHAPE_LINE_CHAIN::FindSegment ( const VECTOR2I aP,
int  aThreshold = 1 
) const

Search for segment containing point aP.

Parameters
aPis the point to be looked for.
Returns
index of the corresponding segment in the line chain or negative when not found.

Definition at line 890 of file shape_line_chain.cpp.

891{
892 for( int s = 0; s < SegmentCount(); s++ )
893 {
894 if( CSegment( s ).Distance( aP ) <= aThreshold )
895 return s;
896 }
897
898 return -1;
899}

References CSegment(), SEG::Distance(), and SegmentCount().

Referenced by PNS::MEANDER_PLACER_BASE::cutTunedLine(), and CADSTAR_SCH_ARCHIVE_LOADER::loadNets().

◆ fixIndicesRotation()

void SHAPE_LINE_CHAIN::fixIndicesRotation ( )
protected

Fix indices of this chain to ensure arcs are not split between the end and start indices.

Definition at line 132 of file shape_line_chain.cpp.

133{
134 wxCHECK( m_shapes.size() == m_points.size(), /*void*/ );
135
136 if( m_shapes.size() <= 1 || m_arcs.size() <= 1 )
137 return;
138
139 size_t rotations = 0;
140 size_t numPoints = m_points.size();
141
142 while( ArcIndex( 0 ) != SHAPE_IS_PT
143 && ArcIndex( 0 ) == ArcIndex( numPoints - 1 ) )
144 {
145 // Rotate right
146 std::rotate( m_points.rbegin(), m_points.rbegin() + 1, m_points.rend() );
147 std::rotate( m_shapes.rbegin(), m_shapes.rbegin() + 1, m_shapes.rend() );
148
149 // Sanity check - avoid infinite loops (NB: wxCHECK is not thread-safe)
150 if( rotations++ > m_shapes.size() )
151 return;
152 }
153}

References ArcIndex(), m_arcs, m_points, m_shapes, and SHAPE_IS_PT.

Referenced by mergeFirstLastPointIfNeeded(), and SHAPE_LINE_CHAIN().

◆ Format()

const std::string SHAPE_LINE_CHAIN::Format ( ) const
overridevirtual

Reimplemented from SHAPE.

Definition at line 1896 of file shape_line_chain.cpp.

1897{
1898 std::stringstream ss;
1899
1900 ss << "SHAPE_LINE_CHAIN( { ";
1901
1902 for( int i = 0; i < PointCount(); i++ )
1903 {
1904 ss << "VECTOR2I( " << m_points[i].x << ", " << m_points[i].y << ")";
1905
1906 if( i != PointCount() -1 )
1907 ss << ", ";
1908 }
1909
1910 ss << "}, " << ( m_closed ? "true" : "false" );
1911 ss << " );";
1912
1913 return ss.str();
1914
1915 /* fixme: arcs
1916 for( size_t i = 0; i < m_arcs.size(); i++ )
1917 ss << m_arcs[i].GetCenter().x << " " << m_arcs[i].GetCenter().y << " "
1918 << m_arcs[i].GetP0().x << " " << m_arcs[i].GetP0().y << " "
1919 << m_arcs[i].GetCentralAngle().AsDegrees();
1920
1921 return ss.str();*/
1922}

References m_closed, m_points, and PointCount().

Referenced by PNS::SHOVE::shoveLineToHullSet().

◆ GenerateBBoxCache()

void SHAPE_LINE_CHAIN::GenerateBBoxCache ( ) const
inline

◆ GetCachedBBox()

BOX2I * SHAPE_LINE_CHAIN::GetCachedBBox ( ) const
inlineoverridevirtual

Reimplemented from SHAPE_LINE_CHAIN_BASE.

Definition at line 449 of file shape_line_chain.h.

450 {
451 return &m_bbox;
452 }

References m_bbox.

◆ GetClearance()

int SHAPE::GetClearance ( const SHAPE aOther) const
inherited

Return the actual minimum distance between two shapes.

Return values
distancein IU

Definition at line 48 of file shape.cpp.

49{
50 int actual_clearance = std::numeric_limits<int>::max();
51 std::vector<const SHAPE*> a_shapes;
52 std::vector<const SHAPE*> b_shapes;
53
54 GetIndexableSubshapes( a_shapes );
55 aOther->GetIndexableSubshapes( b_shapes );
56
57 if( GetIndexableSubshapeCount() == 0 )
58 a_shapes.push_back( this );
59
60 if( aOther->GetIndexableSubshapeCount() == 0 )
61 b_shapes.push_back( aOther );
62
63 for( const SHAPE* a : a_shapes )
64 {
65 for( const SHAPE* b : b_shapes )
66 {
67 int temp_dist = 0;
68 a->Collide( b, std::numeric_limits<int>::max() / 2, &temp_dist );
69
70 if( temp_dist < actual_clearance )
71 actual_clearance = temp_dist;
72 }
73 }
74
75 return actual_clearance;
76}
virtual size_t GetIndexableSubshapeCount() const
Definition: shape.h:110
virtual void GetIndexableSubshapes(std::vector< const SHAPE * > &aSubshapes) const
Definition: shape.h:112
An abstract shape on 2D plane.
Definition: shape.h:123

References SHAPE_BASE::GetIndexableSubshapeCount(), and SHAPE_BASE::GetIndexableSubshapes().

◆ GetIndexableSubshapeCount()

virtual size_t SHAPE_BASE::GetIndexableSubshapeCount ( ) const
inlinevirtualinherited

Reimplemented in SHAPE_COMPOUND, and SHAPE_POLY_SET.

Definition at line 110 of file shape.h.

110{ return 0; }

Referenced by SHAPE::GetClearance().

◆ GetIndexableSubshapes()

virtual void SHAPE_BASE::GetIndexableSubshapes ( std::vector< const SHAPE * > &  aSubshapes) const
inlinevirtualinherited

Reimplemented in SHAPE_COMPOUND, and SHAPE_POLY_SET.

Definition at line 112 of file shape.h.

112{ }

Referenced by SHAPE_COMPOUND::AddShape(), SHAPE::GetClearance(), and ROUTER_PREVIEW_ITEM::ViewDraw().

◆ GetPoint()

virtual const VECTOR2I SHAPE_LINE_CHAIN::GetPoint ( int  aIndex) const
inlineoverridevirtual

◆ GetPointCount()

◆ GetSegment()

virtual const SEG SHAPE_LINE_CHAIN::GetSegment ( int  aIndex) const
inlineoverridevirtual

Implements SHAPE_LINE_CHAIN_BASE.

Definition at line 858 of file shape_line_chain.h.

858{ return CSegment(aIndex); }

References CSegment().

Referenced by Collide(), and Collide().

◆ GetSegmentCount()

virtual size_t SHAPE_LINE_CHAIN::GetSegmentCount ( ) const
inlineoverridevirtual

Implements SHAPE_LINE_CHAIN_BASE.

Definition at line 860 of file shape_line_chain.h.

860{ return SegmentCount(); }

References SegmentCount().

Referenced by Collide(), Collide(), and DRC_TEST_PROVIDER_EDGE_CLEARANCE::Run().

◆ HasIndexableSubshapes()

virtual bool SHAPE_BASE::HasIndexableSubshapes ( ) const
inlinevirtualinherited

Reimplemented in SHAPE_COMPOUND, and SHAPE_POLY_SET.

Definition at line 105 of file shape.h.

106 {
107 return false;
108 }

Referenced by SHAPE_COMPOUND::AddShape(), and ROUTER_PREVIEW_ITEM::ViewDraw().

◆ Insert() [1/2]

void SHAPE_LINE_CHAIN::Insert ( size_t  aVertex,
const SHAPE_ARC aArc 
)

Step 1: Find the position for the new arc in the existing arc vector

Step 2: Add the arc polyline points to the chain

Step 3: Add the vector of indices to the shape vector

Definition at line 1294 of file shape_line_chain.cpp.

1295{
1296 wxCHECK( aVertex < m_points.size(), /* void */ );
1297
1298 if( aVertex > 0 && IsPtOnArc( aVertex ) )
1299 splitArc( aVertex );
1300
1302 ssize_t arc_pos = m_arcs.size();
1303
1304 for( auto arc_it = m_shapes.rbegin() ;
1305 arc_it != m_shapes.rend() + aVertex;
1306 arc_it++ )
1307 {
1308 if( *arc_it != SHAPES_ARE_PT )
1309 {
1310 arc_pos = std::max( ( *arc_it ).first, ( *arc_it ).second );
1311 arc_pos++;
1312 }
1313 }
1314
1315 //Increment all arc indices before inserting the new arc
1316 for( auto& sh : m_shapes )
1317 {
1318 alg::run_on_pair( sh,
1319 [&]( ssize_t& aIndex )
1320 {
1321 if( aIndex >= arc_pos )
1322 aIndex++;
1323 } );
1324 }
1325
1326 SHAPE_ARC arcCopy( aArc );
1327 arcCopy.SetWidth( 0 );
1328 m_arcs.insert( m_arcs.begin() + arc_pos, arcCopy );
1329
1331 //@todo need to check we aren't creating duplicate points at start or end
1332 auto& chain = aArc.ConvertToPolyline();
1333 m_points.insert( m_points.begin() + aVertex, chain.CPoints().begin(), chain.CPoints().end() );
1334
1336 //@todo need to check we aren't creating duplicate points at start or end
1337 std::vector<std::pair<ssize_t, ssize_t>> new_points( chain.PointCount(),
1338 { arc_pos, SHAPE_IS_PT } );
1339
1340 m_shapes.insert( m_shapes.begin() + aVertex, new_points.begin(), new_points.end() );
1341 assert( m_shapes.size() == m_points.size() );
1342}
bool IsPtOnArc(size_t aPtIndex) const
void splitArc(ssize_t aPtIndex, bool aCoincident=false)
Splits an arc into two arcs at aPtIndex.

References SHAPE_ARC::ConvertToPolyline(), IsPtOnArc(), m_arcs, m_points, m_shapes, alg::run_on_pair(), SHAPE_ARC::SetWidth(), SHAPES_ARE_PT, and splitArc().

◆ Insert() [2/2]

void SHAPE_LINE_CHAIN::Insert ( size_t  aVertex,
const VECTOR2I aP 
)

Definition at line 1273 of file shape_line_chain.cpp.

1274{
1275 if( aVertex == m_points.size() )
1276 {
1277 Append( aP );
1278 return;
1279 }
1280
1281 wxCHECK( aVertex < m_points.size(), /* void */ );
1282
1283 if( aVertex > 0 && IsPtOnArc( aVertex ) )
1284 splitArc( aVertex );
1285
1286 //@todo need to check we aren't creating duplicate points
1287 m_points.insert( m_points.begin() + aVertex, aP );
1288 m_shapes.insert( m_shapes.begin() + aVertex, SHAPES_ARE_PT );
1289
1290 assert( m_shapes.size() == m_points.size() );
1291}

References Append(), IsPtOnArc(), m_points, m_shapes, SHAPES_ARE_PT, and splitArc().

Referenced by EE_POINT_EDITOR::addCorner(), PNS::TOPOLOGY::AssembleTuningPath(), PNS::LINE::dragCorner45(), PNS::LINE::dragCornerFree(), CONVERT_TOOL::makePolysFromChainedSegs(), Replace(), and Split().

◆ Intersect() [1/2]

int SHAPE_LINE_CHAIN::Intersect ( const SEG aSeg,
INTERSECTIONS aIp 
) const

Find all intersection points between our line chain and the segment aSeg.

Parameters
aSegis the segment chain to find intersections with.
aIpis the reference to a vector to store found intersections. Intersection points are sorted with increasing distances from point aSeg.a.
Returns
the number of intersections found.

Definition at line 1360 of file shape_line_chain.cpp.

1361{
1362 for( int s = 0; s < SegmentCount(); s++ )
1363 {
1364 OPT_VECTOR2I p = CSegment( s ).Intersect( aSeg );
1365
1366 if( p )
1367 {
1368 INTERSECTION is;
1369 is.valid = true;
1370 is.index_our = s;
1371 is.index_their = -1;
1372 is.is_corner_our = is.is_corner_their = false;
1373 is.p = *p;
1374 aIp.push_back( is );
1375 }
1376 }
1377
1378 compareOriginDistance comp( aSeg.A );
1379 sort( aIp.begin(), aIp.end(), comp );
1380
1381 return aIp.size();
1382}
OPT_VECTOR2I Intersect(const SEG &aSeg, bool aIgnoreEndpoints=false, bool aLines=false) const
Compute intersection point of segment (this) with segment aSeg.
Definition: seg.cpp:188
std::optional< VECTOR2I > OPT_VECTOR2I
Definition: seg.h:39

References SEG::A, CSegment(), SHAPE_LINE_CHAIN::INTERSECTION::index_our, SHAPE_LINE_CHAIN::INTERSECTION::index_their, SEG::Intersect(), SHAPE_LINE_CHAIN::INTERSECTION::is_corner_our, SHAPE_LINE_CHAIN::INTERSECTION::is_corner_their, SHAPE_LINE_CHAIN::INTERSECTION::p, SegmentCount(), and SHAPE_LINE_CHAIN::INTERSECTION::valid.

Referenced by PNS::OPTIMIZER::customBreakouts(), TEARDROP_MANAGER::findAnchorPointsOnTrack(), PNS::LINE_PLACER::handleSelfIntersections(), PNS::HullIntersection(), Intersects(), CADSTAR_SCH_ARCHIVE_LOADER::loadNets(), and POLYGON_GEOM_MANAGER::updateLeaderPoints().

◆ Intersect() [2/2]

int SHAPE_LINE_CHAIN::Intersect ( const SHAPE_LINE_CHAIN aChain,
INTERSECTIONS aIp,
bool  aExcludeColinearAndTouching = false,
BOX2I aChainBBox = nullptr 
) const

Find all intersection points between our line chain and the line chain aChain.

Parameters
aChainis the line chain to find intersections with.
aIpis reference to a vector to store found intersections. Intersection points are sorted with increasing path lengths from the starting point of aChain.
Returns
the number of intersections found.

Definition at line 1400 of file shape_line_chain.cpp.

1402{
1403 BOX2I bb_other = aChainBBox ? *aChainBBox : aChain.BBox();
1404
1405 for( int s1 = 0; s1 < SegmentCount(); s1++ )
1406 {
1407 const SEG& a = CSegment( s1 );
1408 const BOX2I bb_cur( a.A, a.B - a.A );
1409
1410 if( !bb_other.Intersects( bb_cur ) )
1411 continue;
1412
1413 for( int s2 = 0; s2 < aChain.SegmentCount(); s2++ )
1414 {
1415 const SEG& b = aChain.CSegment( s2 );
1416 INTERSECTION is;
1417
1418 is.index_our = s1;
1419 is.index_their = s2;
1420 is.is_corner_our = false;
1421 is.is_corner_their = false;
1422 is.valid = true;
1423
1424 OPT_VECTOR2I p = a.Intersect( b );
1425
1426 bool coll = a.Collinear( b );
1427
1428 if( coll && ! aExcludeColinearAndTouching )
1429 {
1430 if( a.Contains( b.A ) )
1431 {
1432 is.p = b.A;
1433 is.is_corner_their = true;
1434 addIntersection(aIp, PointCount(), is);
1435 }
1436
1437 if( a.Contains( b.B ) )
1438 {
1439 is.p = b.B;
1440 is.index_their++;
1441 is.is_corner_their = true;
1442 addIntersection( aIp, PointCount(), is );
1443 }
1444
1445 if( b.Contains( a.A ) )
1446 {
1447 is.p = a.A;
1448 is.is_corner_our = true;
1449 addIntersection( aIp, PointCount(), is );
1450 }
1451
1452 if( b.Contains( a.B ) )
1453 {
1454 is.p = a.B;
1455 is.index_our++;
1456 is.is_corner_our = true;
1457 addIntersection( aIp, PointCount(), is );
1458 }
1459 }
1460 else if( p )
1461 {
1462 is.p = *p;
1463 is.is_corner_our = false;
1464 is.is_corner_their = false;
1465
1466 int distA = ( b.A - *p ).EuclideanNorm();
1467 int distB = ( b.B - *p ).EuclideanNorm();
1468
1469 if( p == a.A )
1470 {
1471 is.is_corner_our = true;
1472 }
1473
1474 if( p == a.B )
1475 {
1476 is.is_corner_our = true;
1477 is.index_our++;
1478 }
1479
1480 if( p == b.A )
1481 {
1482 is.is_corner_their = true;
1483 }
1484
1485 if( p == b.B )
1486 {
1487 is.is_corner_their = true;
1488 is.index_their++;
1489 }
1490
1491 addIntersection( aIp, PointCount(), is );
1492 }
1493 }
1494 }
1495
1496 return aIp.size();
1497}
bool Intersects(const BOX2< Vec > &aRect) const
Definition: box2.h:269
bool Collinear(const SEG &aSeg) const
Check if segment aSeg lies on the same line as (this).
Definition: seg.h:269
bool Contains(const SEG &aSeg) const
Definition: seg.h:332
const BOX2I BBox(int aClearance=0) const override
Compute a bounding box of the shape, with a margin of aClearance a collision.
static void addIntersection(SHAPE_LINE_CHAIN::INTERSECTIONS &aIps, int aPc, const SHAPE_LINE_CHAIN::INTERSECTION &aP)
double EuclideanNorm(const VECTOR2I &vector)
Definition: trigo.h:129

References SEG::A, addIntersection(), SEG::B, BBox(), SEG::Collinear(), SEG::Contains(), CSegment(), EuclideanNorm(), SHAPE_LINE_CHAIN::INTERSECTION::index_our, SHAPE_LINE_CHAIN::INTERSECTION::index_their, SEG::Intersect(), BOX2< Vec >::Intersects(), SHAPE_LINE_CHAIN::INTERSECTION::is_corner_our, SHAPE_LINE_CHAIN::INTERSECTION::is_corner_their, SHAPE_LINE_CHAIN::INTERSECTION::p, PointCount(), SegmentCount(), and SHAPE_LINE_CHAIN::INTERSECTION::valid.

◆ Intersects()

bool SHAPE_LINE_CHAIN::Intersects ( const SHAPE_LINE_CHAIN aChain) const

Definition at line 1944 of file shape_line_chain.cpp.

1945{
1947 return Intersect( aChain, dummy ) != 0;
1948}
int Intersect(const SEG &aSeg, INTERSECTIONS &aIp) const
Find all intersection points between our line chain and the segment aSeg.
std::vector< INTERSECTION > INTERSECTIONS
static LIB_SYMBOL * dummy()
Used to draw a dummy shape when a LIB_SYMBOL is not found in library.
Definition: sch_symbol.cpp:74

References dummy(), and Intersect().

Referenced by PNS::DIFF_PAIR::BuildInitial().

◆ IsArcEnd()

bool SHAPE_LINE_CHAIN::IsArcEnd ( size_t  aIndex) const
inline

Definition at line 852 of file shape_line_chain.h.

853 {
854 return ( IsSharedPt( aIndex ) || ( IsPtOnArc( aIndex ) && !IsArcSegment( aIndex ) ) );
855 }

References IsArcSegment(), IsPtOnArc(), and IsSharedPt().

Referenced by BOOST_AUTO_TEST_CASE(), NearestPoint(), and splitArc().

◆ IsArcSegment()

bool SHAPE_LINE_CHAIN::IsArcSegment ( size_t  aSegment) const
inline

Definition at line 820 of file shape_line_chain.h.

821 {
822 /*
823 * A segment is part of an arc except in the special case of two arcs next to each other
824 * but without a shared vertex. Here there is a segment between the end of the first arc
825 * and the start of the second arc.
826 */
827 size_t nextIdx = aSegment + 1;
828
829 if( nextIdx > m_shapes.size() - 1 )
830 {
831 if( nextIdx == m_shapes.size() && m_closed )
832 nextIdx = 0; // segment between end point and first point
833 else
834 return false;
835 }
836
837 return ( IsPtOnArc( aSegment )
838 && ( IsSharedPt( aSegment )
839 || m_shapes[aSegment].first == m_shapes[nextIdx].first ) );
840 }

References IsPtOnArc(), IsSharedPt(), m_closed, and m_shapes.

Referenced by PNS::NODE::Add(), Append(), PNS::LINE::ClipToNearestObstacle(), Collide(), Collide(), PNS::MEANDER_PLACER::doMove(), PNS::LINE::dragCornerFree(), IsArcEnd(), IsArcStart(), isLine45Degree(), Length(), PNS::LINE_PLACER::mergeHead(), PNS::OPTIMIZER::mergeStep(), PNS::DP_MEANDER_PLACER::Move(), NearestPoint(), PNS::SHOVE::ShoveObstacleLine(), Slice(), and Split().

◆ IsArcStart()

bool SHAPE_LINE_CHAIN::IsArcStart ( size_t  aIndex) const
inline

Definition at line 843 of file shape_line_chain.h.

844 {
845 if( aIndex == 0 )
846 return IsPtOnArc( aIndex );
847
848 return ( IsSharedPt( aIndex ) || ( IsPtOnArc( aIndex ) && !IsArcSegment( aIndex - 1 ) ) );
849 }

References IsArcSegment(), IsPtOnArc(), and IsSharedPt().

Referenced by BOOST_AUTO_TEST_CASE(), ALTIUM_PCB::HelperCreateBoardOutline(), NearestPoint(), Slice(), and splitArc().

◆ IsClosed()

◆ IsNull()

bool SHAPE::IsNull ( ) const
inlineinherited

Return true if the shape is a null shape.

Return values
trueif null :-)

Definition at line 163 of file shape.h.

164 {
165 return m_type == SH_NULL;
166 }
SHAPE_TYPE m_type
< type of our shape
Definition: shape.h:116
@ SH_NULL
empty shape (no shape...),
Definition: shape.h:52

References SHAPE_BASE::m_type, and SH_NULL.

◆ IsPtOnArc()

◆ IsSharedPt()

bool SHAPE_LINE_CHAIN::IsSharedPt ( size_t  aIndex) const
inline

Test if a point is shared between multiple shapes.

Parameters
aIndex
Returns

Definition at line 806 of file shape_line_chain.h.

807 {
808 return aIndex < m_shapes.size()
809 && m_shapes[aIndex].first != SHAPE_IS_PT
810 && m_shapes[aIndex].second != SHAPE_IS_PT;
811 }

References m_shapes, and SHAPE_IS_PT.

Referenced by ArcIndex(), BOOST_AUTO_TEST_CASE(), IsArcEnd(), IsArcSegment(), IsArcStart(), GEOM_TEST::IsOutlineValid(), Remove(), RemoveShape(), reversedArcIndex(), and splitArc().

◆ IsSolid()

bool SHAPE_LINE_CHAIN::IsSolid ( ) const
inlineoverridevirtual

Implements SHAPE.

Definition at line 766 of file shape_line_chain.h.

767 {
768 return false;
769 }

◆ Length()

long long int SHAPE_LINE_CHAIN::Length ( ) const

Return length of the line chain in Euclidean metric.

Returns
the length of the line chain.

Definition at line 606 of file shape_line_chain.cpp.

607{
608 long long int l = 0;
609
610 for( int i = 0; i < SegmentCount(); i++ )
611 {
612 // Only include segments that aren't part of arc shapes
613 if( !IsArcSegment(i) )
614 l += CSegment( i ).Length();
615 }
616
617 for( int i = 0; i < ArcCount(); i++ )
618 l += CArcs()[i].GetLength();
619
620 return l;
621}
int Length() const
Return the length (this).
Definition: seg.h:351
const std::vector< SHAPE_ARC > & CArcs() const

References ArcCount(), CArcs(), CSegment(), IsArcSegment(), SEG::Length(), and SegmentCount().

Referenced by PNS::COST_ESTIMATOR::Add(), PNS::MEANDER_PLACER::doMove(), PNS::LINE::dragSegment45(), PNS::OPTIMIZER::fanoutCleanup(), PNS::MEANDER_SHAPE::MaxTunableLength(), PNS::DP_MEANDER_PLACER::Move(), PNS::SHOVE::onCollidingArc(), PNS::SHOVE::onCollidingSegment(), PNS::COST_ESTIMATOR::Remove(), PNS::COST_ESTIMATOR::Replace(), PNS::LINE_PLACER::rhWalkOnly(), PNS::WALKAROUND::Route(), PNS::SHOVE::shoveLineFromLoneVia(), PNS::DIFF_PAIR::Skew(), PNS::OPTIMIZER::smartPadsSingle(), PNS::DIFF_PAIR::TotalLength(), and PNS::DRAGGER::tryWalkaround().

◆ mergeFirstLastPointIfNeeded()

void SHAPE_LINE_CHAIN::mergeFirstLastPointIfNeeded ( )
protected

Merge the first and last point if they are the same and this chain is closed.

Definition at line 156 of file shape_line_chain.cpp.

157{
158 if( m_closed )
159 {
160 if( m_points.size() > 1 && m_points.front() == m_points.back() )
161 {
162 if( m_shapes.back() != SHAPES_ARE_PT )
163 {
164 m_shapes.front().second = m_shapes.front().first;
165 m_shapes.front().first = m_shapes.back().first;
166 }
167
168 m_points.pop_back();
169 m_shapes.pop_back();
170
172 }
173 }
174}

References fixIndicesRotation(), m_closed, m_points, m_shapes, and SHAPES_ARE_PT.

Referenced by Append(), and SetClosed().

◆ Mirror() [1/2]

void SHAPE_LINE_CHAIN::Mirror ( bool  aX = true,
bool  aY = false,
const VECTOR2I aRef = { 0, 0 } 
)

Mirror the line points about y or x (or both).

Parameters
aXIf true, mirror about the y axis (flip X coordinate).
aYIf true, mirror about the x axis (flip Y coordinate).
aRefsets the reference point about which to mirror.

Definition at line 624 of file shape_line_chain.cpp.

625{
626 for( auto& pt : m_points )
627 {
628 if( aX )
629 pt.x = -pt.x + 2 * aRef.x;
630
631 if( aY )
632 pt.y = -pt.y + 2 * aRef.y;
633 }
634
635 for( auto& arc : m_arcs )
636 arc.Mirror( aX, aY, aRef );
637}

References m_arcs, m_points, VECTOR2< T >::x, and VECTOR2< T >::y.

Referenced by PNS::MEANDER_SHAPE::genMeanderShape().

◆ Mirror() [2/2]

void SHAPE_LINE_CHAIN::Mirror ( const SEG axis)

Mirror the line points using an given axis.

Parameters
axisis the axis on which to mirror.

Definition at line 640 of file shape_line_chain.cpp.

641{
642 for( auto& pt : m_points )
643 pt = axis.ReflectPoint( pt );
644
645 for( auto& arc : m_arcs )
646 arc.Mirror( axis );
647}
const VECTOR2I ReflectPoint(const VECTOR2I &aP) const
Reflect a point using this segment as axis.
Definition: seg.cpp:283

References m_arcs, m_points, and SEG::ReflectPoint().

◆ Move()

void SHAPE_LINE_CHAIN::Move ( const VECTOR2I aVector)
inlineoverridevirtual

Implements SHAPE.

Definition at line 733 of file shape_line_chain.h.

734 {
735 for( auto& pt : m_points )
736 pt += aVector;
737
738 for( auto& arc : m_arcs )
739 arc.Move( aVector );
740 }

References m_arcs, and m_points.

Referenced by ZONE_FILLER::addHatchFillTypeOnZone(), PAD::BuildEffectiveShapes(), ZONE_FILLER::buildThermalSpokes(), PLACEFILE_GERBER_WRITER::CreatePlaceFile(), EDA_SHAPE::hitTest(), PCB_SELECTION_TOOL::hitTestDistance(), EDA_SHAPE::makeEffectiveShapes(), and SHAPE_SIMPLE::Move().

◆ NearestPoint() [1/2]

const VECTOR2I SHAPE_LINE_CHAIN::NearestPoint ( const SEG aSeg,
int &  dist 
) const

Find a point on the line chain that is closest to the line defined by the points of segment aSeg, also returns the distance.

Parameters
aSegis the segment defining the line.
distis the reference receiving the distance to the nearest point.
Returns
the nearest point.

Definition at line 1849 of file shape_line_chain.cpp.

1850{
1851 if( PointCount() == 0 )
1852 {
1853 // The only right answer here is "don't crash".
1854 return { 0, 0 };
1855 }
1856
1857 int nearest = 0;
1858
1859 dist = INT_MAX;
1860
1861 for( int i = 0; i < PointCount(); i++ )
1862 {
1863 int d = aSeg.LineDistance( CPoint( i ) );
1864
1865 if( d < dist )
1866 {
1867 dist = d;
1868 nearest = i;
1869 }
1870 }
1871
1872 return CPoint( nearest );
1873}
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...
Definition: seg.cpp:331

References CPoint(), SEG::LineDistance(), and PointCount().

◆ NearestPoint() [2/2]

const VECTOR2I SHAPE_LINE_CHAIN::NearestPoint ( const VECTOR2I aP,
bool  aAllowInternalShapePoints = true 
) const

Find a point on the line chain that is closest to point aP.

Parameters
aPis the point to find.
aAllowInternalShapePointsif false will not return points internal to an arc (i.e. only the arc endpoints are possible candidates)
Returns
the nearest point.

Definition at line 1791 of file shape_line_chain.cpp.

1793{
1794 if( PointCount() == 0 )
1795 {
1796 // The only right answer here is "don't crash".
1797 return { 0, 0 };
1798 }
1799
1800 int min_d = INT_MAX;
1801 int nearest = 0;
1802
1803 for( int i = 0; i < SegmentCount(); i++ )
1804 {
1805 int d = CSegment( i ).Distance( aP );
1806
1807 if( d < min_d )
1808 {
1809 min_d = d;
1810 nearest = i;
1811 }
1812 }
1813
1814 if( !aAllowInternalShapePoints )
1815 {
1816 //Snap to arc end points if the closest found segment is part of an arc segment
1817 if( nearest > 0 && nearest < PointCount() && IsArcSegment( nearest ) )
1818 {
1819 VECTOR2I ptToSegStart = CSegment( nearest ).A - aP;
1820 VECTOR2I ptToSegEnd = CSegment( nearest ).B - aP;
1821
1822 if( ptToSegStart.EuclideanNorm() > ptToSegEnd.EuclideanNorm() )
1823 nearest++;
1824
1825 // Is this the start or end of an arc? If so, return it directly
1826 if( IsArcStart( nearest ) || IsArcEnd( nearest ) )
1827 {
1828 return m_points[nearest];
1829 }
1830 else
1831 {
1832 const SHAPE_ARC& nearestArc = Arc( ArcIndex( nearest ) );
1833 VECTOR2I ptToArcStart = nearestArc.GetP0() - aP;
1834 VECTOR2I ptToArcEnd = nearestArc.GetP1() - aP;
1835
1836 if( ptToArcStart.EuclideanNorm() > ptToArcEnd.EuclideanNorm() )
1837 return nearestArc.GetP1();
1838 else
1839 return nearestArc.GetP0();
1840 }
1841
1842 }
1843 }
1844
1845 return CSegment( nearest ).NearestPoint( aP );
1846}
bool IsArcEnd(size_t aIndex) const
bool IsArcStart(size_t aIndex) const
T EuclideanNorm() const
Compute the Euclidean norm of the vector, which is defined as sqrt(x ** 2 + y ** 2).
Definition: vector2d.h:293

References SEG::A, Arc(), ArcIndex(), SEG::B, CSegment(), SEG::Distance(), VECTOR2< T >::EuclideanNorm(), SHAPE_ARC::GetP0(), SHAPE_ARC::GetP1(), IsArcEnd(), IsArcSegment(), IsArcStart(), m_points, SEG::NearestPoint(), PointCount(), and SegmentCount().

Referenced by FOOTPRINT::CheckNetTies(), PCB_GRID_HELPER::computeAnchors(), PNS::MEANDER_PLACER_BASE::cutTunedLine(), CADSTAR_SCH_ARCHIVE_LOADER::loadBusses(), PNS::MoveDiagonal(), and PNS::DRAGGER::optimizeAndUpdateDraggedLine().

◆ NearestSegment()

int SHAPE_LINE_CHAIN::NearestSegment ( const VECTOR2I aP) const

Find the segment nearest the given point.

Parameters
aPis the point to compare with.
Returns
the index of the segment closest to the point.

Definition at line 1876 of file shape_line_chain.cpp.

1877{
1878 int min_d = INT_MAX;
1879 int nearest = 0;
1880
1881 for( int i = 0; i < SegmentCount(); i++ )
1882 {
1883 int d = CSegment( i ).Distance( aP );
1884
1885 if( d < min_d )
1886 {
1887 min_d = d;
1888 nearest = i;
1889 }
1890 }
1891
1892 return nearest;
1893}

References CSegment(), SEG::Distance(), and SegmentCount().

Referenced by PNS::LINE::ClipToNearestObstacle(), and SCH_SHEET_PIN::ConstrainOnEdge().

◆ NewFacet()

FACET * SHAPE::NewFacet ( )
inherited

Definition at line 695 of file wrlfacet.cpp.

696{
697 FACET* fp = new FACET;
698 facets.push_back( fp );
699 return fp;
700}
Definition: wrlfacet.h:43

References SHAPE::facets.

Referenced by WRL2FACESET::TranslateToSG(), X3DIFACESET::TranslateToSG(), and WRL1FACESET::TranslateToSG().

◆ NextShape()

int SHAPE_LINE_CHAIN::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.

If aPointIndex is the start of a segment, this will be ( aPointIndex + 1 ). If aPointIndex is part of an arc, this will be the index of the start of the next shape after the arc, in other words, the last point of the arc.

Parameters
aPointIndexis a vertex in the chain.
aForwardsis true if the next shape is desired, false for previous shape.
Returns
the vertex index of the start of the next shape after aPoint's shape or -1 if the end was reached.

Definition at line 952 of file shape_line_chain.cpp.

953{
954 if( aPointIndex < 0 )
955 aPointIndex += PointCount();
956
957 int lastIndex = PointCount() - 1;
958
959 // First or last point?
960 if( ( aForwards && aPointIndex == lastIndex ) ||
961 ( !aForwards && aPointIndex == 0 ) )
962 {
963 return -1; // we don't want to wrap around
964 }
965
966 int delta = aForwards ? 1 : -1;
967
968 if( m_shapes[aPointIndex] == SHAPES_ARE_PT )
969 return aPointIndex + delta;
970
971 int arcStart = aPointIndex;
972
973 // The second element should only get populated when the point is shared between two shapes.
974 // If not a shared point, then the index should always go on the first element.
975 assert( m_shapes[aPointIndex].first != SHAPE_IS_PT );
976
977 // Start with the assumption the point is shared
978 auto arcIndex = [&]( int aIndex ) -> ssize_t
979 {
980 if( aForwards )
981 return ArcIndex( aIndex );
982 else
983 return reversedArcIndex( aIndex );
984 };
985
986 ssize_t currentArcIdx = arcIndex( aPointIndex );
987
988 // Now skip the rest of the arc
989 while( aPointIndex < lastIndex && aPointIndex >= 0 && arcIndex( aPointIndex ) == currentArcIdx )
990 aPointIndex += delta;
991
992 if( aPointIndex == lastIndex )
993 {
994 if( !m_closed && arcIndex( aPointIndex ) == currentArcIdx )
995 return -1;
996 else
997 return lastIndex; // Segment between last point and the start
998 }
999
1000 bool indexStillOnArc = alg::pair_contains( m_shapes[aPointIndex], currentArcIdx );
1001
1002 // We want the last vertex of the arc if the initial point was the start of one
1003 // Well-formed arcs should generate more than one point to travel above
1004 if( aPointIndex - arcStart > 1 && !indexStillOnArc )
1005 aPointIndex -= delta;
1006
1007 return aPointIndex;
1008}
ssize_t reversedArcIndex(size_t aSegment) const
Return the arc index for the given segment index, looking backwards.
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.
Definition: kicad_algo.h:112
constexpr int delta

References ArcIndex(), delta, m_closed, m_shapes, alg::pair_contains(), PointCount(), reversedArcIndex(), SHAPE_IS_PT, and SHAPES_ARE_PT.

Referenced by PNS::LINE::ClipVertexRange(), PNS::MEANDER_PLACER::doMove(), ALTIUM_PCB::HelperCreateBoardOutline(), PNS::DP_MEANDER_PLACER::Move(), PrevShape(), and Slice().

◆ operator!=()

bool SHAPE_LINE_CHAIN::operator!= ( const SHAPE_LINE_CHAIN aRhs) const
inline

Definition at line 717 of file shape_line_chain.h.

718 {
719 if( PointCount() != aRhs.PointCount() )
720 return true;
721
722 for( int i = 0; i < PointCount(); i++ )
723 {
724 if( CPoint( i ) != aRhs.CPoint( i ) )
725 return true;
726 }
727
728 return false;
729 }

References CPoint(), and PointCount().

◆ operator=()

SHAPE_LINE_CHAIN & SHAPE_LINE_CHAIN::operator= ( const SHAPE_LINE_CHAIN )
default

◆ Parse()

bool SHAPE_LINE_CHAIN::Parse ( std::stringstream &  aStream)
overridevirtual

Reimplemented from SHAPE.

Definition at line 1957 of file shape_line_chain.cpp.

1958{
1959 size_t n_pts;
1960 size_t n_arcs;
1961
1962 m_points.clear();
1963 aStream >> n_pts;
1964
1965 // Rough sanity check, just make sure the loop bounds aren't absolutely outlandish
1966 if( n_pts > aStream.str().size() )
1967 return false;
1968
1969 aStream >> m_closed;
1970 aStream >> n_arcs;
1971
1972 if( n_arcs > aStream.str().size() )
1973 return false;
1974
1975 for( size_t i = 0; i < n_pts; i++ )
1976 {
1977 int x, y;
1978 ssize_t ind;
1979 aStream >> x;
1980 aStream >> y;
1981 m_points.emplace_back( x, y );
1982
1983 aStream >> ind;
1984 m_shapes.emplace_back( std::make_pair( ind, SHAPE_IS_PT ) );
1985 }
1986
1987 for( size_t i = 0; i < n_arcs; i++ )
1988 {
1989 VECTOR2I p0, pc;
1990 double angle;
1991
1992 aStream >> pc.x;
1993 aStream >> pc.y;
1994 aStream >> p0.x;
1995 aStream >> p0.y;
1996 aStream >> angle;
1997
1998 m_arcs.emplace_back( pc, p0, EDA_ANGLE( angle, DEGREES_T ) );
1999 }
2000
2001 return true;
2002}
@ DEGREES_T
Definition: eda_angle.h:31
static DIRECTION_45::AngleType angle(const VECTOR2I &a, const VECTOR2I &b)

References PNS::angle(), DEGREES_T, m_arcs, m_closed, m_points, m_shapes, SHAPE_IS_PT, VECTOR2< T >::x, and VECTOR2< T >::y.

◆ PathLength()

int SHAPE_LINE_CHAIN::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 line.

Returns
the path length in Euclidean metric or -1 if aP does not belong to the line chain.

Definition at line 1500 of file shape_line_chain.cpp.

1501{
1502 int sum = 0;
1503
1504 for( int i = 0; i < SegmentCount(); i++ )
1505 {
1506 const SEG seg = CSegment( i );
1507 bool indexMatch = true;
1508
1509 if( aIndex >= 0 )
1510 {
1511 if( aIndex == SegmentCount() )
1512 {
1513 indexMatch = ( i == SegmentCount() - 1 );
1514 }
1515 else
1516 {
1517 indexMatch = ( i == aIndex );
1518 }
1519 }
1520
1521 if( indexMatch )
1522 {
1523 sum += ( aP - seg.A ).EuclideanNorm();
1524 return sum;
1525 }
1526 else
1527 sum += seg.Length();
1528 }
1529
1530 return -1;
1531}

References SEG::A, CSegment(), EuclideanNorm(), SEG::Length(), and SegmentCount().

Referenced by PNS::NODE::NearestObstacle().

◆ PointAlong()

const VECTOR2I SHAPE_LINE_CHAIN::PointAlong ( int  aPathLength) const

Definition at line 2005 of file shape_line_chain.cpp.

2006{
2007 int total = 0;
2008
2009 if( aPathLength == 0 )
2010 return CPoint( 0 );
2011
2012 for( int i = 0; i < SegmentCount(); i++ )
2013 {
2014 const SEG& s = CSegment( i );
2015 int l = s.Length();
2016
2017 if( total + l >= aPathLength )
2018 {
2019 VECTOR2I d( s.B - s.A );
2020 return s.A + d.Resize( aPathLength - total );
2021 }
2022
2023 total += l;
2024 }
2025
2026 return CPoint( -1 );
2027}
VECTOR2< T > Resize(T aNewLength) const
Return a vector of the same direction, but length specified in aNewLength.
Definition: vector2d.h:378

References SEG::A, SEG::B, CPoint(), CSegment(), SEG::Length(), VECTOR2< T >::Resize(), and SegmentCount().

◆ PointCount()

int SHAPE_LINE_CHAIN::PointCount ( ) const
inline

Return the number of points (vertices) in this line chain.

Returns
the number of points.

Definition at line 315 of file shape_line_chain.h.

316 {
317 return m_points.size();
318 }

References m_points.

Referenced by LABEL_MANAGER::Add(), POLYGON_GEOM_MANAGER::AddPoint(), SHAPE_LINE_CHAIN::POINT_INSIDE_TRACKER::AddPolyline(), TRIANGLE_DISPLAY_LIST::AddToMiddleContourns(), Append(), PNS::LINE::AppendVia(), ArePolylineEndPointsNearCircle(), ArePolylineMidPointsNearCircle(), PNS::NODE::AssembleLine(), PNS::TOPOLOGY::AssembleTuningPath(), BOOST_AUTO_TEST_CASE(), BuildConvexHull(), PAD::BuildEffectivePolygon(), PAD::BuildEffectiveShapes(), PNS::LINE::ChangedArea(), PNS::KEEP_TOPOLOGY_CONSTRAINT::Check(), CheckClearance(), CN_VISITOR::checkZoneZoneConnection(), CLastPoint(), PNS::LINE::ClipVertexRange(), convertPolygon(), ALTIUM_PCB::ConvertShapeBasedRegions6ToBoardItem(), ALTIUM_PCB::ConvertShapeBasedRegions6ToBoardItemOnLayer(), ALTIUM_PCB::ConvertShapeBasedRegions6ToFootprintItem(), ALTIUM_PCB::ConvertShapeBasedRegions6ToFootprintItemOnLayer(), convertToClipper(), PNS::coupledBypass(), CPoint(), PolygonTriangulation::createList(), POLYGON_TEST::createList(), CreatePadsShapesSection(), PLACEFILE_GERBER_WRITER::CreatePlaceFile(), PNS::cursorDistMinimum(), POLYGON_GEOM_MANAGER::DeleteLastCorner(), DIALOG_PAD_PRIMITIVE_POLY_PROPS::doValidate(), PNS::LINE::dragCornerFree(), PNS::dragCornerInternal(), PNS::LINE::dragSegment45(), PNS::DRAGGER::dragWalkaround(), KIGFX::PCB_PAINTER::draw(), KIGFX::GERBVIEW_PAINTER::draw(), APERTURE_MACRO::DrawApertureMacroShape(), KIGFX::CAIRO_GAL_BASE::drawPoly(), KIGFX::OPENGL_GAL::DrawPolygon(), KIGFX::OPENGL_GAL::DrawPolyline(), KIGFX::PREVIEW::POLYGON_ITEM::drawPreviewShape(), KIGFX::CAIRO_GAL_BASE::DrawSegmentChain(), KIGFX::OPENGL_GAL::DrawSegmentChain(), EDA_SHAPE::DupPolyPointsList(), EXPORTER_PCB_VRML::ExportVrmlBoard(), EXPORTER_PCB_VRML::ExportVrmlPolygonSet(), DSN::SPECCTRA_DB::fillBOUNDARY(), AR_AUTOPLACER::fillMatrix(), Find(), PNS::LINE_PLACER::FixRoute(), GERBER_PLOTTER::FlashPadChamferRoundRect(), DXF_PLOTTER::FlashPadCustom(), HPGL_PLOTTER::FlashPadCustom(), PSLIKE_PLOTTER::FlashPadCustom(), GERBER_PLOTTER::FlashPadCustom(), DXF_PLOTTER::FlashPadRoundRect(), GERBER_PLOTTER::FlashPadRoundRect(), HPGL_PLOTTER::FlashPadRoundRect(), PSLIKE_PLOTTER::FlashPadRoundRect(), Format(), PCB_PLUGIN::formatPolyPts(), CADSTAR_PCB_ARCHIVE_LOADER::getLineChainFromShapes(), GetPointCount(), SHAPE_SIMPLE::GetPointCount(), CADSTAR_PCB_ARCHIVE_LOADER::getPolySetFromCadstarShape(), PNS::MOUSE_TRAIL_TRACER::GetPosture(), SHAPE_POLY_SET::GetRelativeIndices(), PNS::MOUSE_TRAIL_TRACER::GetTrailLeadVector(), PNS::LINE_PLACER::handlePullback(), PNS::LINE_PLACER::handleSelfIntersections(), ALTIUM_PCB::HelperCreateBoardOutline(), DS_DRAW_ITEM_POLYPOLYGONS::HitTest(), PNS::HullIntersection(), Intersect(), GEOM_TEST::IsOutlineValid(), POLYGON_GEOM_MANAGER::IsPolygonInProgress(), EDA_SHAPE::IsPolyShapeValid(), POLYGON_GEOM_MANAGER::IsSelfIntersecting(), FABMASTER::loadFootprints(), FABMASTER::loadGraphics(), FABMASTER::loadPolygon(), FABMASTER::loadZone(), DSN::SPECCTRA_DB::makeIMAGE(), DSN::SPECCTRA_DB::makePADSTACK(), CONVERT_TOOL::makePolysFromChainedSegs(), PNS::LINE_PLACER::mergeHead(), PNS::OPTIMIZER::mergeObtuse(), PNS::DP_MEANDER_PLACER::Move(), NearestPoint(), POLYGON_GEOM_MANAGER::NewPointClosesOutline(), NextShape(), operator!=(), BOOST_TEST_PRINT_NAMESPACE_OPEN::print_log_value< SHAPE_LINE_CHAIN >::operator()(), PNS::LINE_PLACER::optimizeTailHeadTransition(), BITMAPCONV_INFO::outputOnePolygon(), ALTIUM_PCB::ParsePolygons6Data(), PlotDrawingSheet(), GERBER_PLOTTER::PlotGerberRegion(), PLOTTER::PlotPoly(), GERBER_PLOTTER::PlotPoly(), SHAPE_SIMPLE::PointCount(), PNS::LINE::PointCount(), PNS::pointInside2(), polygon_Convert(), GERBER_DRAW_ITEM::PrintGerberPoly(), DS_DRAW_ITEM_POLYPOLYGONS::PrintWsItem(), Remove(), RemoveShape(), Replace(), PNS::OPTIMIZER::runSmartPads(), SetPoint(), KIGFX::PREVIEW::POLYGON_ITEM::SetPoints(), PNS::shovedArea(), PNS::SHOVE::shoveLineFromLoneVia(), PNS::SHOVE::shoveLineToHullSet(), Simplify(), PNS::TOPOLOGY::SimplifyLine(), PNS::LINE_PLACER::simplifyNewLine(), Slice(), PNS::OPTIMIZER::smartPadsSingle(), splitArc(), PNS::DRAGGER::tryWalkaround(), POLYGON_GEOM_MANAGER::updateLeaderPoints(), PNS::LINE::Walkaround(), HYPERLYNX_EXPORTER::writeNetObjects(), GBR_TO_PCB_EXPORTER::writePcbPolygon(), and GBR_TO_PCB_EXPORTER::writePcbZoneItem().

◆ PointInside()

bool SHAPE_LINE_CHAIN_BASE::PointInside ( const VECTOR2I aPt,
int  aAccuracy = 0,
bool  aUseBBoxCache = false 
) const
inherited

Check if point aP lies inside a polygon (any type) defined by the line chain.

For closed shapes only.

Parameters
aPtpoint to check
aUseBBoxCachegives better performance if the bounding box caches have been generated.
Returns
true if the point is inside the shape (edge is not treated as being inside).

Definition at line 1534 of file shape_line_chain.cpp.

1536{
1537 /*
1538 * Don't check the bounding box unless it's cached. Building it is about the same speed as
1539 * the rigorous test below and so just slows things down by doing potentially two tests.
1540 */
1541 if( aUseBBoxCache && GetCachedBBox() && !GetCachedBBox()->Contains( aPt ) )
1542 return false;
1543
1544 if( !IsClosed() || GetPointCount() < 3 )
1545 return false;
1546
1547 bool inside = false;
1548
1549 /*
1550 * To check for interior points, we draw a line in the positive x direction from
1551 * the point. If it intersects an even number of segments, the point is outside the
1552 * line chain (it had to first enter and then exit). Otherwise, it is inside the chain.
1553 *
1554 * Note: slope might be denormal here in the case of a horizontal line but we require our
1555 * y to move from above to below the point (or vice versa)
1556 *
1557 * Note: we open-code CPoint() here so that we don't end up calculating the size of the
1558 * vector number-of-points times. This has a non-trivial impact on zone fill times.
1559 */
1560 int pointCount = GetPointCount();
1561
1562 for( int i = 0; i < pointCount; )
1563 {
1564 const auto p1 = GetPoint( i++ );
1565 const auto p2 = GetPoint( i == pointCount ? 0 : i );
1566 const auto diff = p2 - p1;
1567
1568 if( diff.y != 0 )
1569 {
1570 const int d = rescale( diff.x, ( aPt.y - p1.y ), diff.y );
1571
1572 if( ( ( p1.y > aPt.y ) != ( p2.y > aPt.y ) ) && ( aPt.x - p1.x < d ) )
1573 inside = !inside;
1574 }
1575 }
1576
1577 // If accuracy is <= 1 (nm) then we skip the accuracy test for performance. Otherwise
1578 // we use "OnEdge(accuracy)" as a proxy for "Inside(accuracy)".
1579 if( aAccuracy <= 1 )
1580 return inside;
1581 else
1582 return inside || PointOnEdge( aPt, aAccuracy );
1583}
bool PointOnEdge(const VECTOR2I &aP, int aAccuracy=0) const
Check if point aP lies on an edge or vertex of the line chain.
virtual BOX2I * GetCachedBBox() const
Definition: shape.h:325
virtual bool IsClosed() const =0
T rescale(T aNumerator, T aValue, T aDenominator)
Scale a number (value) by rational (numerator/denominator).
Definition: util.h:105

References SHAPE_LINE_CHAIN_BASE::GetCachedBBox(), SHAPE_LINE_CHAIN_BASE::GetPoint(), SHAPE_LINE_CHAIN_BASE::GetPointCount(), SHAPE_LINE_CHAIN_BASE::IsClosed(), SHAPE_LINE_CHAIN_BASE::PointOnEdge(), rescale(), VECTOR2< T >::x, and VECTOR2< T >::y.

Referenced by Collide(), SHAPE_LINE_CHAIN_BASE::Collide(), Collide(), SHAPE_POLY_SET::containsSingle(), ZONE::HitTestCutout(), MARKER_BASE::HitTestMarker(), CONNECTIVITY_DATA::IsConnectedOnLayer(), DRC_RTREE::QueryColliding(), SHAPE_LINE_CHAIN_BASE::SquaredDistance(), DRC_TEST_PROVIDER_ZONE_CONNECTIONS::testZoneLayer(), and PNS::LINE::Walkaround().

◆ PointOnEdge()

bool SHAPE_LINE_CHAIN_BASE::PointOnEdge ( const VECTOR2I aP,
int  aAccuracy = 0 
) const
inherited

Check if point aP lies on an edge or vertex of the line chain.

Parameters
aPpoint to check
Returns
true if the point lies on the edge.

Definition at line 1586 of file shape_line_chain.cpp.

1587{
1588 return EdgeContainingPoint( aPt, aAccuracy ) >= 0;
1589}
int EdgeContainingPoint(const VECTOR2I &aP, int aAccuracy=0) const
Check if point aP lies on an edge or vertex of the line chain.

References SHAPE_LINE_CHAIN_BASE::EdgeContainingPoint().

Referenced by FABMASTER::loadZones(), SHAPE_LINE_CHAIN_BASE::PointInside(), and PNS::LINE::Walkaround().

◆ PrevShape()

int SHAPE_LINE_CHAIN::PrevShape ( int  aPointIndex) const
inline

Definition at line 371 of file shape_line_chain.h.

372 {
373 return NextShape( aPointIndex, false );
374 }
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.

References NextShape().

Referenced by PNS::LINE_PLACER::handlePullback().

◆ Remove() [1/2]

void SHAPE_LINE_CHAIN::Remove ( int  aIndex)
inline

Remove the aIndex-th point from the line chain.

Parameters
aIndexis the index of the point to be removed.

Definition at line 564 of file shape_line_chain.h.

565 {
566 Remove( aIndex, aIndex );
567 }
void Remove(int aStartIndex, int aEndIndex)
Remove the range of points [start_index, end_index] from the line chain.

References Remove().

◆ Remove() [2/2]

void SHAPE_LINE_CHAIN::Remove ( int  aStartIndex,
int  aEndIndex 
)

Remove the range of points [start_index, end_index] from the line chain.

Parameters
aStartIndexis the start of the point range to be replaced (inclusive).
aEndIndexis the end of the point range to be replaced (inclusive).

Definition at line 728 of file shape_line_chain.cpp.

729{
730 assert( m_shapes.size() == m_points.size() );
731
732 if( aEndIndex < 0 )
733 aEndIndex += PointCount();
734
735 if( aStartIndex < 0 )
736 aStartIndex += PointCount();
737
738 if( aStartIndex >= PointCount() )
739 return;
740
741 aEndIndex = std::min( aEndIndex, PointCount() - 1 );
742
743 // Split arcs at start index and end just after the end index
744 if( IsPtOnArc( aStartIndex ) )
745 splitArc( aStartIndex );
746
747 size_t nextIndex = static_cast<size_t>( aEndIndex ) + 1;
748
749 if( IsPtOnArc( nextIndex ) )
750 splitArc( nextIndex );
751
752 std::set<size_t> extra_arcs;
753 auto logArcIdxRemoval = [&]( ssize_t& aShapeIndex )
754 {
755 if( aShapeIndex != SHAPE_IS_PT )
756 extra_arcs.insert( aShapeIndex );
757 };
758
759 // Remove any overlapping arcs in the point range
760 for( int i = aStartIndex; i <= aEndIndex; i++ )
761 {
762 if( IsSharedPt( i ) )
763 {
764 if( i == aStartIndex )
765 {
766 logArcIdxRemoval( m_shapes[i].second ); // Only remove the arc on the second index
767
768 // Ensure that m_shapes has been built correctly.
769 assert( i < aEndIndex || m_shapes[i + 1].first == m_shapes[i].second );
770
771 continue;
772 }
773 else if( i == aEndIndex )
774 {
775 logArcIdxRemoval( m_shapes[i].first ); // Only remove the arc on the first index
776
777 // Ensure that m_shapes has been built correctly.
778 assert( i > aStartIndex || IsSharedPt( i - 1 )
779 ? m_shapes[i - 1].second == m_shapes[i].first
780 : m_shapes[i - 1].first == m_shapes[i].first );
781 continue;
782 }
783 }
784
785 alg::run_on_pair( m_shapes[i], logArcIdxRemoval );
786 }
787
788 for( auto arc : extra_arcs )
789 convertArc( arc );
790
791 m_shapes.erase( m_shapes.begin() + aStartIndex, m_shapes.begin() + aEndIndex + 1 );
792 m_points.erase( m_points.begin() + aStartIndex, m_points.begin() + aEndIndex + 1 );
793 assert( m_shapes.size() == m_points.size() );
794}

References convertArc(), IsPtOnArc(), IsSharedPt(), m_points, m_shapes, PointCount(), alg::run_on_pair(), SHAPE_IS_PT, and splitArc().

Referenced by POLYGON_GEOM_MANAGER::AddPoint(), PNS::TOPOLOGY::AssembleTuningPath(), PNS::LINE_PLACER::buildInitialLine(), PNS::LINE::ClipToNearestObstacle(), POLYGON_GEOM_MANAGER::DeleteLastCorner(), EDA_SHAPE::endEdit(), PNS::DIFF_PAIR_PLACER::FixRoute(), PNS::LINE_PLACER::handleSelfIntersections(), PNS::OPTIMIZER::mergeColinear(), PNS::LINE_PLACER::mergeHead(), PNS::LINE_PLACER::reduceTail(), Remove(), EE_POINT_EDITOR::removeCorner(), RemoveShape(), Replace(), and Simplify().

◆ RemoveShape()

void SHAPE_LINE_CHAIN::RemoveShape ( int  aPointIndex)

Remove the shape at the given index from the line chain.

If the given index is inside an arc, the entire arc will be removed. Otherwise this is equivalent to Remove( aPointIndex ).

Parameters
aPointIndexis the index of the point to remove.

Definition at line 1029 of file shape_line_chain.cpp.

1030{
1031 if( aPointIndex < 0 )
1032 aPointIndex += PointCount();
1033
1034 if( m_shapes[aPointIndex] == SHAPES_ARE_PT )
1035 {
1036 Remove( aPointIndex );
1037 return;
1038 }
1039
1040 //@todo should this be replaced to use NextShape() / PrevShape()?
1041 int start = aPointIndex;
1042 int end = aPointIndex;
1043 int arcIdx = ArcIndex( aPointIndex );
1044
1045 if( !IsSharedPt( aPointIndex ) )
1046 {
1047 // aPointIndex is not a shared point, so iterate backwards to find the start of the arc
1048 while( start >= 0 && m_shapes[start].first == arcIdx )
1049 start--;
1050
1051 // Check if the previous point might be a shared point and decrement 'start' if so
1052 if( start >= 1 && m_shapes[static_cast<ssize_t>( start ) - 1].second == arcIdx )
1053 start--;
1054 }
1055
1056 // For the end point we only need to check the first element in m_shapes (the second one is only
1057 // populated if there is an arc after the current one sharing the same point).
1058 while( end < static_cast<int>( m_shapes.size() ) - 1 && m_shapes[end].first == arcIdx )
1059 end++;
1060
1061 Remove( start, end );
1062}

References ArcIndex(), IsSharedPt(), m_shapes, PointCount(), Remove(), and SHAPES_ARE_PT.

Referenced by PNS::LINE_PLACER::handlePullback().

◆ Replace() [1/2]

void SHAPE_LINE_CHAIN::Replace ( int  aStartIndex,
int  aEndIndex,
const SHAPE_LINE_CHAIN aLine 
)

Replace points with indices in range [start_index, end_index] with the points from line chain aLine.

Parameters
aStartIndexis the start of the point range to be replaced (inclusive).
aEndIndexis the end of the point range to be replaced (inclusive).
aLineis the replacement line chain.

Definition at line 658 of file shape_line_chain.cpp.

659{
660 if( aEndIndex < 0 )
661 aEndIndex += PointCount();
662
663 if( aStartIndex < 0 )
664 aStartIndex += PointCount();
665
666 // We only process lines in order in this house
667 wxASSERT( aStartIndex <= aEndIndex );
668 wxASSERT( aEndIndex < m_points.size() );
669
670 SHAPE_LINE_CHAIN newLine = aLine;
671
672 // Zero points to add?
673 if( newLine.PointCount() == 0 )
674 {
675 Remove( aStartIndex, aEndIndex );
676 return;
677 }
678
679 // Remove coincident points in the new line
680 if( newLine.m_points.front() == m_points[aStartIndex] )
681 {
682 aStartIndex++;
683 newLine.Remove( 0 );
684
685 // Zero points to add?
686 if( newLine.PointCount() == 0 )
687 {
688 Remove( aStartIndex, aEndIndex );
689 return;
690 }
691 }
692
693 if( newLine.m_points.back() == m_points[aEndIndex] && aEndIndex > 0 )
694 {
695 aEndIndex--;
696 newLine.Remove( -1 );
697 }
698
699 Remove( aStartIndex, aEndIndex );
700
701 // Zero points to add?
702 if( newLine.PointCount() == 0 )
703 return;
704
705 // The total new arcs index is added to the new arc indices
706 size_t prev_arc_count = m_arcs.size();
707 std::vector<std::pair<ssize_t, ssize_t>> new_shapes = newLine.m_shapes;
708
709 for( std::pair<ssize_t, ssize_t>& shape_pair : new_shapes )
710 {
711 alg::run_on_pair( shape_pair,
712 [&]( ssize_t& aShape )
713 {
714 if( aShape != SHAPE_IS_PT )
715 aShape += prev_arc_count;
716 } );
717 }
718
719 m_shapes.insert( m_shapes.begin() + aStartIndex, new_shapes.begin(), new_shapes.end() );
720 m_points.insert( m_points.begin() + aStartIndex, newLine.m_points.begin(),
721 newLine.m_points.end() );
722 m_arcs.insert( m_arcs.end(), newLine.m_arcs.begin(), newLine.m_arcs.end() );
723
724 assert( m_shapes.size() == m_points.size() );
725}

References m_arcs, m_points, m_shapes, PointCount(), Remove(), alg::run_on_pair(), and SHAPE_IS_PT.

◆ Replace() [2/2]

void SHAPE_LINE_CHAIN::Replace ( int  aStartIndex,
int  aEndIndex,
const VECTOR2I aP 
)

Replace points with indices in range [start_index, end_index] with a single point aP.

Parameters
aStartIndexis the start of the point range to be replaced (inclusive).
aEndIndexis the end of the point range to be replaced (inclusive).
aPis the replacement point.

Definition at line 650 of file shape_line_chain.cpp.

651{
652 Remove( aStartIndex, aEndIndex );
653 Insert( aStartIndex, aP );
654 assert( m_shapes.size() == m_points.size() );
655}
void Insert(size_t aVertex, const VECTOR2I &aP)

References Insert(), m_points, m_shapes, and Remove().

Referenced by PNS::TOPOLOGY::AssembleTuningPath(), BOOST_AUTO_TEST_CASE(), PNS::CORNER_COUNT_LIMIT_CONSTRAINT::Check(), PNS::coupledBypass(), PNS::LINE::dragSegment45(), CADSTAR_SCH_ARCHIVE_LOADER::loadNets(), PNS::OPTIMIZER::mergeDpStep(), PNS::OPTIMIZER::mergeObtuse(), PNS::LINE_PLACER::optimizeTailHeadTransition(), and PNS::Tighten().

◆ Reverse()

const SHAPE_LINE_CHAIN SHAPE_LINE_CHAIN::Reverse ( ) const

Reverse point order in the line chain.

Returns
line chain with reversed point order (original A-B-C-D: returned D-C-B-A).

Definition at line 560 of file shape_line_chain.cpp.

561{
562 SHAPE_LINE_CHAIN a( *this );
563
564 reverse( a.m_points.begin(), a.m_points.end() );
565 reverse( a.m_shapes.begin(), a.m_shapes.end() );
566 reverse( a.m_arcs.begin(), a.m_arcs.end() );
567
568 for( auto& sh : a.m_shapes )
569 {
570 if( sh != SHAPES_ARE_PT )
571 {
573 [&]( ssize_t& aShapeIndex )
574 {
575 if( aShapeIndex != SHAPE_IS_PT )
576 aShapeIndex = a.m_arcs.size() - aShapeIndex - 1;
577 } );
578
579 if( sh.second != SHAPE_IS_PT )
580 {
581 // If the second element is populated, the first one should be too!
582 assert( sh.first != SHAPE_IS_PT );
583
584 // Switch round first and second in shared points, as part of reversing the chain
585 std::swap( sh.first, sh.second );
586 }
587 }
588 }
589
590 for( SHAPE_ARC& arc : a.m_arcs )
591 arc.Reverse();
592
593 a.m_closed = m_closed;
594
595 return a;
596}
void Reverse()
Definition: shape_arc.cpp:572

References m_arcs, m_closed, m_points, m_shapes, SHAPE_ARC::Reverse(), alg::run_on_pair(), SHAPE_IS_PT, and SHAPES_ARE_PT.

Referenced by PNS::ArcHull(), PNS::DP_GATEWAYS::buildEntries(), PNS::KEEP_TOPOLOGY_CONSTRAINT::Check(), PNS::SHOVE::checkShoveDirection(), convertToClipper(), PNS::coupledBypass(), PNS::MEANDER_PLACER_BASE::cutTunedLine(), PNS::LINE::dragCorner45(), PNS::MOUSE_TRAIL_TRACER::GetPosture(), CADSTAR_SCH_ARCHIVE_LOADER::loadNets(), PNS::DP_GATEWAY::Reverse(), PNS::LINE::Reverse(), PNS::SegmentHull(), PNS::OPTIMIZER::smartPadsSingle(), and PNS::LINE::Walkaround().

◆ reversedArcIndex()

ssize_t SHAPE_LINE_CHAIN::reversedArcIndex ( size_t  aSegment) const
inlineprotected

Return the arc index for the given segment index, looking backwards.

Definition at line 901 of file shape_line_chain.h.

902 {
903 if( IsSharedPt( aSegment ) )
904 return m_shapes[aSegment].first;
905 else
906 return m_shapes[aSegment].second;
907 }

References IsSharedPt(), and m_shapes.

Referenced by NextShape().

◆ Rotate()

void SHAPE_LINE_CHAIN::Rotate ( const EDA_ANGLE aAngle,
const VECTOR2I aCenter = { 0, 0 } 
)
overridevirtual

Rotate all vertices by a given angle.

Parameters
aCenteris the rotation center.
aAngleis the rotation angle.

Implements SHAPE.

Definition at line 426 of file shape_line_chain.cpp.

427{
428 for( VECTOR2I& pt : m_points )
429 RotatePoint( pt, aCenter, aAngle );
430
431 for( SHAPE_ARC& arc : m_arcs )
432 arc.Rotate( aAngle, aCenter );
433}
void RotatePoint(int *pX, int *pY, const EDA_ANGLE &aAngle)
Definition: trigo.cpp:183

References m_arcs, m_points, and RotatePoint().

Referenced by PAD::BuildEffectiveShapes(), ZONE_FILLER::buildThermalSpokes(), PLACEFILE_GERBER_WRITER::CreatePlaceFile(), EDA_SHAPE::hitTest(), and EDA_SHAPE::makeEffectiveShapes().

◆ Segment()

SEG SHAPE_LINE_CHAIN::Segment ( int  aIndex)
inline

Return a copy of the aIndex-th segment in the line chain.

Parameters
aIndexis the index of the segment in the line chain. Negative values are counted from the end (i.e. -1 means the last segment in the line chain).
Returns
a segment at the aIndex in the line chain.

Definition at line 327 of file shape_line_chain.h.

328 {
329 if( aIndex < 0 )
330 aIndex += SegmentCount();
331
332 if( aIndex == (int)( m_points.size() - 1 ) && m_closed )
333 return SEG( m_points[aIndex], m_points[0], aIndex );
334 else
335 return SEG( m_points[aIndex], m_points[aIndex + 1], aIndex );
336 }

References m_closed, m_points, and SegmentCount().

Referenced by BuildFootprintPolygonOutlines(), PNS::DIFF_PAIR::CoupledSegmentPairs(), BOARD_ADAPTER::createPadWithMargin(), findEndSegments(), ALTIUM_PCB::HelperCreateBoardOutline(), CADSTAR_SCH_ARCHIVE_LOADER::loadShapeVertices(), EDA_SHAPE::makeEffectiveShapes(), DRC_TEST_PROVIDER_PHYSICAL_CLEARANCE::testZoneLayer(), and unfracture().

◆ SegmentCount()

int SHAPE_LINE_CHAIN::SegmentCount ( ) const
inline

Return the number of segments in this line chain.

Returns
the number of segments.

Definition at line 291 of file shape_line_chain.h.

292 {
293 int c = m_points.size() - 1;
294
295 if( m_closed )
296 c++;
297
298 return std::max( 0, c );
299 }

References m_closed, and m_points.

Referenced by PNS::NODE::Add(), PNS::MOUSE_TRAIL_TRACER::AddTrailPoint(), PNS::NODE::AssembleLine(), BuildFootprintPolygonOutlines(), PNS::LINE_PLACER::buildInitialLine(), PNS::PRESERVE_VERTEX_CONSTRAINT::Check(), CheckClearance(), PNS::NODE::CheckColliding(), PNS::DIFF_PAIR::CheckConnectionAngle(), PNS::checkGap(), PNS::MEANDERED_LINE::CheckSelfIntersections(), PNS::closestProjectedPoint(), PCB_GRID_HELPER::computeAnchors(), PNS::COST_ESTIMATOR::CornerCost(), PNS::LINE::CountCorners(), PNS::DIFF_PAIR::CoupledLength(), PNS::DIFF_PAIR::CoupledSegmentPairs(), BOARD_ADAPTER::createPadWithMargin(), CSegment(), PNS::cursorDistMinimum(), PNS::MEANDER_PLACER::doMove(), PNS::LINE::dragCorner45(), PNS::dragCornerInternal(), PNS::LINE::dragSegment45(), KIGFX::OPENGL_GAL::DrawPolygon(), PNS::DIFF_PAIR::Empty(), PNS::findCoupledVertices(), findEndSegments(), FindSegment(), PNS::DIFF_PAIR_PLACER::FixRoute(), PNS::LINE_PLACER::FixRoute(), GetSegmentCount(), SHAPE_SIMPLE::GetSegmentCount(), PNS::LINE_PLACER::handlePullback(), PNS::DIFF_PAIR_PLACER::HasPlacedAnything(), PNS::DP_MEANDER_PLACER::HasPlacedAnything(), PNS::HullIntersection(), Intersect(), isLine45Degree(), Length(), CADSTAR_SCH_ARCHIVE_LOADER::loadShapeVertices(), EDA_SHAPE::makeEffectiveShapes(), PNS::OPTIMIZER::mergeColinear(), PNS::OPTIMIZER::mergeDpSegments(), PNS::OPTIMIZER::mergeDpStep(), PNS::OPTIMIZER::mergeFull(), PNS::OPTIMIZER::mergeObtuse(), PNS::OPTIMIZER::mergeStep(), NearestPoint(), NearestSegment(), PathLength(), PointAlong(), PNS::pointInside2(), KIGFX::VIEW_OVERLAY::Polyline(), PNS::LINE_PLACER::reduceTail(), Segment(), PNS::LINE::SegmentCount(), SelfIntersecting(), PNS::OPTIMIZER::smartPadsSingle(), PNS::LINE::snapDraggedCorner(), PNS::LINE::snapToNeighbourSegments(), Split(), DRC_TEST_PROVIDER_PHYSICAL_CLEARANCE::testShapeLineChain(), DRC_TEST_PROVIDER_PHYSICAL_CLEARANCE::testZoneLayer(), PNS::Tighten(), SHAPE_POLY_SET::unfractureSingle(), POLYGON_GEOM_MANAGER::updateLeaderPoints(), PNS::LINE::Walkaround(), and HYPERLYNX_EXPORTER::writeBoardInfo().

◆ SelfIntersecting()

const std::optional< SHAPE_LINE_CHAIN::INTERSECTION > SHAPE_LINE_CHAIN::SelfIntersecting ( ) const

Check if the line chain is self-intersecting.

Returns
(optional) first found self-intersection point.

Definition at line 1641 of file shape_line_chain.cpp.

1642{
1643 for( int s1 = 0; s1 < SegmentCount(); s1++ )
1644 {
1645 for( int s2 = s1 + 1; s2 < SegmentCount(); s2++ )
1646 {
1647 const VECTOR2I s2a = CSegment( s2 ).A, s2b = CSegment( s2 ).B;
1648
1649 if( s1 + 1 != s2 && CSegment( s1 ).Contains( s2a ) )
1650 {
1651 INTERSECTION is;
1652 is.index_our = s1;
1653 is.index_their = s2;
1654 is.p = s2a;
1655 return is;
1656 }
1657 else if( CSegment( s1 ).Contains( s2b ) &&
1658 // for closed polylines, the ending point of the
1659 // last segment == starting point of the first segment
1660 // this is a normal case, not self intersecting case
1661 !( IsClosed() && s1 == 0 && s2 == SegmentCount()-1 ) )
1662 {
1663 INTERSECTION is;
1664 is.index_our = s1;
1665 is.index_their = s2;
1666 is.p = s2b;
1667 return is;
1668 }
1669 else
1670 {
1671 OPT_VECTOR2I p = CSegment( s1 ).Intersect( CSegment( s2 ), true );
1672
1673 if( p )
1674 {
1675 INTERSECTION is;
1676 is.index_our = s1;
1677 is.index_their = s2;
1678 is.p = *p;
1679 return is;
1680 }
1681 }
1682 }
1683 }
1684
1685 return std::optional<SHAPE_LINE_CHAIN::INTERSECTION>();
1686}

References SEG::A, SEG::B, CSegment(), SHAPE_LINE_CHAIN::INTERSECTION::index_our, SHAPE_LINE_CHAIN::INTERSECTION::index_their, SEG::Intersect(), IsClosed(), SHAPE_LINE_CHAIN::INTERSECTION::p, and SegmentCount().

Referenced by PNS::DIFF_PAIR::BuildInitial(), DIALOG_PAD_PRIMITIVE_POLY_PROPS::doValidate(), and POLYGON_GEOM_MANAGER::IsSelfIntersecting().

◆ SetClosed()

void SHAPE_LINE_CHAIN::SetClosed ( bool  aClosed)
inline

Mark the line chain as closed (i.e.

with a segment connecting the last point with the first point).

Parameters
aClosedwhether the line chain is to be closed or not.

Definition at line 252 of file shape_line_chain.h.

253 {
254 m_closed = aClosed;
256 }

References m_closed, and mergeFirstLastPointIfNeeded().

Referenced by ZONE_FILLER::addHatchFillTypeOnZone(), ZONE::AddPolygon(), PNS::ArcHull(), EDA_SHAPE::beginEdit(), BOOST_AUTO_TEST_CASE(), buildBoardBoundingBoxPoly(), BuildFootprintPolygonOutlines(), KI_TEST::BuildRectChain(), ZONE_FILLER::buildThermalSpokes(), SHAPE_POLY_SET::chamferFilletPolygon(), PNS::KEEP_TOPOLOGY_CONSTRAINT::Check(), KI_TEST::CommonTestData::CommonTestData(), PCB_GRID_HELPER::computeAnchors(), convertPolygon(), ConvertPolygonToBlocks(), PNS::ConvexHull(), PLACEFILE_GERBER_WRITER::CreatePlaceFile(), KIGFX::GERBVIEW_PAINTER::draw(), EDA_SHAPE::endEdit(), TEARDROP_MANAGER::findAnchorPointsOnTrack(), SHAPE_POLY_SET::fractureSingle(), CADSTAR_PCB_ARCHIVE_LOADER::getLineChainFromShapes(), PNS::MOUSE_TRAIL_TRACER::GetPosture(), KIFONT::OUTLINE_FONT::getTextAsGlyphs(), HelperShapeLineChainFromAltiumVertices(), POLYGON_GEOM_MANAGER::IsSelfIntersecting(), IteratorFixture::IteratorFixture(), EDA_SHAPE::makeEffectiveShapes(), CONVERT_TOOL::makePolysFromChainedSegs(), GEOM_TEST::MakeSquarePolyLine(), SHAPE_POLY_SET::NewHole(), SHAPE_POLY_SET::NewOutline(), PNS::OctagonalHull(), SHAPE_RECT::Outline(), EAGLE_PLUGIN::packagePolygon(), SHAPE_POLY_SET::Parse(), ALTIUM_PCB::ParseRegions6Data(), PCB_PARSER::parseRenderCache(), PCB_PARSER::parseZONE(), BRDITEMS_PLOTTER::PlotFootprintShape(), BRDITEMS_PLOTTER::PlotPcbShape(), polygonArea(), RENDER_3D_OPENGL::reload(), DRC_TEST_PROVIDER_ANNULAR_WIDTH::Run(), PNS::SegmentHull(), SHAPE_POLY_SET::SHAPE_POLY_SET(), SHAPE_SIMPLE::SHAPE_SIMPLE(), MARKER_BASE::ShapeToPolygon(), TestConcaveSquareFillet(), TransformCircleToPolygon(), unfracture(), and SHAPE_POLY_SET::unfractureSingle().

◆ SetPoint()

void SHAPE_LINE_CHAIN::SetPoint ( int  aIndex,
const VECTOR2I aPos 
)

Move a point to a specific location.

Parameters
aIndexis the index of the point to move.
aPosis the new absolute location of the point.

Definition at line 1011 of file shape_line_chain.cpp.

1012{
1013 if( aIndex < 0 )
1014 aIndex += PointCount();
1015 else if( aIndex >= PointCount() )
1016 aIndex -= PointCount();
1017
1018 m_points[aIndex] = aPos;
1019
1020 alg::run_on_pair( m_shapes[aIndex],
1021 [&]( ssize_t& aIdx )
1022 {
1023 if( aIdx != SHAPE_IS_PT )
1024 convertArc( aIdx );
1025 } );
1026}

References convertArc(), m_points, m_shapes, PointCount(), alg::run_on_pair(), and SHAPE_IS_PT.

Referenced by PNS::LINE_PLACER::buildInitialLine(), EDA_SHAPE::calcEdit(), PNS::LINE::dragCornerFree(), and CADSTAR_SCH_ARCHIVE_LOADER::getScaledLibPart().

◆ SetWidth()

void SHAPE_LINE_CHAIN::SetWidth ( int  aWidth)
inline

Set the width of all segments in the chain.

Parameters
aWidthis the width in internal units.

Definition at line 271 of file shape_line_chain.h.

272 {
273 m_width = aWidth;
274 }

References m_width.

Referenced by BOOST_AUTO_TEST_CASE(), CONVERT_TOOL::makePolysFromChainedSegs(), PNS::LINE::SetShape(), PNS::DIFF_PAIR::SetWidth(), and PNS::LINE::SetWidth().

◆ ShapeCount()

int SHAPE_LINE_CHAIN::ShapeCount ( ) const

Return the number of shapes (line segments or arcs) in this line chain.

This is kind of like SegmentCount() but will only count arcs as 1 segment.

Returns
ArcCount() + the number of non-arc segments.

Definition at line 902 of file shape_line_chain.cpp.

903{
904 if( m_points.empty() )
905 return 0;
906
907 int numPoints = static_cast<int>( m_shapes.size() );
908 int numShapes = 0;
909 int arcIdx = -1;
910
911 for( int i = 0; i < m_points.size() - 1; i++ )
912 {
913 if( m_shapes[i] == SHAPES_ARE_PT )
914 {
915 numShapes++;
916 }
917 else
918 {
919 // Expect that the second index only gets populated when the point is shared between
920 // two shapes. Otherwise, the shape index should always go on the first element of
921 // the pair.
922 assert( m_shapes[i].first != SHAPE_IS_PT );
923
924 // Start assuming the point is shared with the previous arc
925 // If so, the new/next arc index should be located at the second
926 // element in the pair
927 arcIdx = m_shapes[i].second;
928
929 if( arcIdx == SHAPE_IS_PT )
930 arcIdx = m_shapes[i].first; // Not a shared point
931
932 numShapes++;
933
934 // Now skip the rest of the arc
935 while( i < numPoints && m_shapes[i].first == arcIdx )
936 i++;
937
938 // Add the "hidden" segment at the end of the arc, if it exists
939 if( i < numPoints && m_points[i] != m_points[i - 1] )
940 {
941 numShapes++;
942 }
943
944 i--;
945 }
946 }
947
948 return numShapes;
949}

References m_points, m_shapes, SHAPE_IS_PT, and SHAPES_ARE_PT.

Referenced by PNS::LINE_PLACER::mergeHead(), PNS::LINE_PLACER::optimizeTailHeadTransition(), and PNS::LINE::ShapeCount().

◆ Simplify()

SHAPE_LINE_CHAIN & SHAPE_LINE_CHAIN::Simplify ( bool  aRemoveColinear = true)

Simplify the line chain by removing colinear adjacent segments and duplicate vertices.

Parameters
aRemoveColinearcontrols the removal of colinear adjacent segments.
Returns
reference to this line chain.

Definition at line 1689 of file shape_line_chain.cpp.

1690{
1691 std::vector<VECTOR2I> pts_unique;
1692 std::vector<std::pair<ssize_t, ssize_t>> shapes_unique;
1693
1694 // Always try to keep at least 2 points otherwise, we're not really a line
1695 if( PointCount() < 3 )
1696 {
1697 return *this;
1698 }
1699 else if( PointCount() == 3 )
1700 {
1701 if( m_points[0] == m_points[1] )
1702 Remove( 1 );
1703
1704 return *this;
1705 }
1706
1707 int i = 0;
1708 int np = PointCount();
1709
1710 // stage 1: eliminate duplicate vertices
1711 while( i < np )
1712 {
1713 int j = i + 1;
1714
1715 // We can eliminate duplicate vertices as long as they are part of the same shape, OR if
1716 // one of them is part of a shape and one is not.
1717 while( j < np && m_points[i] == m_points[j] &&
1718 ( m_shapes[i] == m_shapes[j] ||
1719 m_shapes[i] == SHAPES_ARE_PT ||
1720 m_shapes[j] == SHAPES_ARE_PT ) )
1721 {
1722 j++;
1723 }
1724
1725 std::pair<ssize_t,ssize_t> shapeToKeep = m_shapes[i];
1726
1727 if( shapeToKeep == SHAPES_ARE_PT )
1728 shapeToKeep = m_shapes[j - 1];
1729
1730 assert( shapeToKeep.first < static_cast<int>( m_arcs.size() ) );
1731 assert( shapeToKeep.second < static_cast<int>( m_arcs.size() ) );
1732
1733 pts_unique.push_back( CPoint( i ) );
1734 shapes_unique.push_back( shapeToKeep );
1735
1736 i = j;
1737 }
1738
1739 m_points.clear();
1740 m_shapes.clear();
1741 np = pts_unique.size();
1742
1743 i = 0;
1744
1745 // stage 2: eliminate colinear segments
1746 while( i < np - 2 )
1747 {
1748 const VECTOR2I p0 = pts_unique[i];
1749 int n = i;
1750
1751 if( aRemoveColinear && shapes_unique[i] == SHAPES_ARE_PT
1752 && shapes_unique[i + 1] == SHAPES_ARE_PT )
1753 {
1754 while( n < np - 2
1755 && ( SEG( p0, pts_unique[n + 2] ).LineDistance( pts_unique[n + 1] ) <= 1
1756 || SEG( p0, pts_unique[n + 2] ).Collinear( SEG( p0, pts_unique[n + 1] ) ) ) )
1757 n++;
1758 }
1759
1760 m_points.push_back( p0 );
1761 m_shapes.push_back( shapes_unique[i] );
1762
1763 if( n > i )
1764 i = n;
1765
1766 if( n == np - 2 )
1767 {
1768 m_points.push_back( pts_unique[np - 1] );
1769 m_shapes.push_back( shapes_unique[np - 1] );
1770 return *this;
1771 }
1772
1773 i++;
1774 }
1775
1776 if( np > 1 )
1777 {
1778 m_points.push_back( pts_unique[np - 2] );
1779 m_shapes.push_back( shapes_unique[np - 2] );
1780 }
1781
1782 m_points.push_back( pts_unique[np - 1] );
1783 m_shapes.push_back( shapes_unique[np - 1] );
1784
1785 assert( m_points.size() == m_shapes.size() );
1786
1787 return *this;
1788}

References CPoint(), m_arcs, m_points, m_shapes, PointCount(), Remove(), and SHAPES_ARE_PT.

Referenced by PNS::MOUSE_TRAIL_TRACER::AddTrailPoint(), PNS::NODE::AssembleLine(), PNS::DIFF_PAIR_PLACER::attemptWalk(), BOOST_AUTO_TEST_CASE(), DIRECTION_45::BuildInitialTrace(), PNS::LINE::ChangedArea(), PNS::CORNER_COUNT_LIMIT_CONSTRAINT::Check(), CompareGeometry(), PNS::DIFF_PAIR::CoupledSegmentPairs(), PNS::MEANDER_PLACER_BASE::cutTunedLine(), PNS::MEANDER_PLACER::doMove(), DIALOG_PAD_PRIMITIVE_POLY_PROPS::doValidate(), PNS::LINE::dragCornerFree(), PNS::LINE::dragSegment45(), PNS::MOUSE_TRAIL_TRACER::GetPosture(), CONVERT_TOOL::makePolysFromChainedSegs(), PNS::OPTIMIZER::mergeDpStep(), PNS::OPTIMIZER::mergeFull(), PNS::LINE_PLACER::mergeHead(), PNS::DP_MEANDER_PLACER::Move(), PNS::SHOVE::onCollidingSolid(), PNS::LINE_PLACER::optimizeTailHeadTransition(), PNS::LINE_PLACER::rhShoveOnly(), PNS::WALKAROUND::Route(), PNS::OPTIMIZER::runSmartPads(), PNS::TOPOLOGY::SimplifyLine(), PNS::LINE_PLACER::simplifyNewLine(), PNS::WALKAROUND::singleStep(), PNS::OPTIMIZER::smartPadsSingle(), PNS::Tighten(), PNS::LINE_PLACER::Trace(), and SHAPE_POLY_SET::unfractureSingle().

◆ Slice()

const SHAPE_LINE_CHAIN 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.

Parameters
aStartIndexis the start of the point range to be returned (inclusive).
aEndIndexis the end of the point range to be returned (inclusive).
Returns
the cut line chain.

Definition at line 1065 of file shape_line_chain.cpp.

1066{
1068
1069 if( aEndIndex < 0 )
1070 aEndIndex += PointCount();
1071
1072 if( aStartIndex < 0 )
1073 aStartIndex += PointCount();
1074
1075 int numPoints = static_cast<int>( m_points.size() );
1076
1077
1078 if( IsArcSegment( aStartIndex ) && !IsArcStart( aStartIndex ) )
1079 {
1080 // Cutting in middle of an arc, lets split it
1081 ssize_t arcIndex = ArcIndex( aStartIndex );
1082 const SHAPE_ARC& currentArc = Arc( arcIndex );
1083
1084 // Copy the points as arc points
1085 for( size_t i = aStartIndex; arcIndex == ArcIndex( i ); i++ )
1086 {
1087 rv.m_points.push_back( m_points[i] );
1088 rv.m_shapes.push_back( { rv.m_arcs.size(), SHAPE_IS_PT } );
1089 rv.m_bbox.Merge( m_points[i] );
1090 }
1091
1092 // Create a new arc from the existing one, with different start point.
1093 SHAPE_ARC newArc;
1094
1095 VECTOR2I newArcStart = m_points[aStartIndex];
1096
1097 newArc.ConstructFromStartEndCenter( newArcStart, currentArc.GetP1(),
1098 currentArc.GetCenter(),
1099 currentArc.IsClockwise() );
1100
1101
1102 rv.m_arcs.push_back( newArc );
1103
1104 aStartIndex += rv.PointCount();
1105 }
1106
1107 for( int i = aStartIndex; i <= aEndIndex && i < numPoints; i = NextShape( i ) )
1108 {
1109 if( i == -1 )
1110 return rv; // NextShape reached the end
1111
1112 if( IsArcStart( i ) )
1113 {
1114 const SHAPE_ARC &currentArc = Arc( ArcIndex( i ) );
1115 int nextShape = NextShape( i );
1116 bool isLastShape = nextShape < 0;
1117
1118 if( ( isLastShape && aEndIndex != ( numPoints - 1 ) )
1119 || ( nextShape > aEndIndex ) )
1120 {
1121 if( i == aEndIndex )
1122 {
1123 // Single point on an arc, just append the single point
1124 rv.Append( m_points[i] );
1125 return rv;
1126 }
1127
1128 // Cutting in middle of an arc, lets split it
1129 ssize_t arcIndex = ArcIndex( i );
1130 const SHAPE_ARC& currentArc = Arc( arcIndex );
1131
1132 // Copy the points as arc points
1133 for( ; i <= aEndIndex && i < numPoints; i++ )
1134 {
1135 if( arcIndex != ArcIndex( i ) )
1136 break;
1137
1138 rv.m_points.push_back( m_points[i] );
1139 rv.m_shapes.push_back( { rv.m_arcs.size(), SHAPE_IS_PT } );
1140 rv.m_bbox.Merge( m_points[i] );
1141 }
1142
1143 // Create a new arc from the existing one, with different end point.
1144 SHAPE_ARC newArc;
1145
1146 VECTOR2I newArcEnd = m_points[aEndIndex];
1147
1148 newArc.ConstructFromStartEndCenter( currentArc.GetP0(), newArcEnd,
1149 currentArc.GetCenter(),
1150 currentArc.IsClockwise() );
1151
1152
1153 rv.m_arcs.push_back( newArc );
1154
1155 return rv;
1156 }
1157 else
1158 {
1159 // append the whole arc
1160 rv.Append( currentArc );
1161 }
1162
1163 if( isLastShape )
1164 return rv;
1165 }
1166 else
1167 {
1168 wxASSERT_MSG( !IsArcSegment( i ),
1169 wxT( "Still on an arc segment, we missed something..." ) );
1170
1171 rv.Append( m_points[i] );
1172 }
1173 }
1174
1175 return rv;
1176}

References Append(), Arc(), ArcIndex(), SHAPE_ARC::ConstructFromStartEndCenter(), SHAPE_ARC::GetCenter(), SHAPE_ARC::GetP0(), SHAPE_ARC::GetP1(), IsArcSegment(), IsArcStart(), SHAPE_ARC::IsClockwise(), m_arcs, m_bbox, m_points, m_shapes, BOX2< Vec >::Merge(), NextShape(), PointCount(), and SHAPE_IS_PT.

Referenced by PNS::MOUSE_TRAIL_TRACER::AddTrailPoint(), BOOST_AUTO_TEST_CASE(), PNS::KEEP_TOPOLOGY_CONSTRAINT::Check(), PNS::LINE::ClipVertexRange(), PNS::MEANDER_PLACER_BASE::cutTunedLine(), PNS::LINE::dragCorner45(), PNS::dragCornerInternal(), PNS::LINE_PLACER::optimizeTailHeadTransition(), PNS::LINE_PLACER::rhWalkOnly(), and PNS::Tighten().

◆ Split()

int SHAPE_LINE_CHAIN::Split ( const VECTOR2I aP)

Insert the point aP belonging to one of the our segments, splitting the adjacent segment in two.

Parameters
aPis the point to be inserted.
Returns
index of the newly inserted point (or a negative value if aP does not lie on our line).

Definition at line 817 of file shape_line_chain.cpp.

818{
819 int ii = -1;
820 int min_dist = 2;
821
822 int found_index = Find( aP );
823
824 for( int s = 0; s < SegmentCount(); s++ )
825 {
826 const SEG seg = CSegment( s );
827 int dist = seg.Distance( aP );
828
829 // make sure we are not producing a 'slightly concave' primitive. This might happen
830 // if aP lies very close to one of already existing points.
831 if( dist < min_dist && seg.A != aP && seg.B != aP )
832 {
833 min_dist = dist;
834 if( found_index < 0 )
835 ii = s;
836 else if( s < found_index )
837 ii = s;
838 }
839 }
840
841 if( ii < 0 )
842 ii = found_index;
843
844 if( ii >= 0 )
845 {
846 // Don't create duplicate points
847 if( GetPoint( ii ) == aP )
848 return ii;
849
850 size_t newIndex = static_cast<size_t>( ii ) + 1;
851
852 if( IsArcSegment( ii ) )
853 {
854 m_points.insert( m_points.begin() + newIndex, aP );
855 m_shapes.insert( m_shapes.begin() + newIndex, { ArcIndex( ii ), SHAPE_IS_PT } );
856 splitArc( newIndex, true ); // Make the inserted point a shared point
857 }
858 else
859 {
860 Insert( newIndex, aP );
861 }
862
863 return newIndex;
864 }
865
866 return -1;
867}
virtual const VECTOR2I GetPoint(int aIndex) const override
int Find(const VECTOR2I &aP, int aThreshold=0) const
Search for point aP.

References SEG::A, ArcIndex(), SEG::B, CSegment(), SEG::Distance(), Find(), GetPoint(), Insert(), IsArcSegment(), m_points, m_shapes, SegmentCount(), SHAPE_IS_PT, and splitArc().

Referenced by BOOST_AUTO_TEST_CASE(), PNS::LINE::ClipToNearestObstacle(), PNS::MEANDER_PLACER_BASE::cutTunedLine(), PNS::LINE_PLACER::rhWalkOnly(), and PNS::LINE::Walkaround().

◆ splitArc()

void SHAPE_LINE_CHAIN::splitArc ( ssize_t  aPtIndex,
bool  aCoincident = false 
)
protected

Splits an arc into two arcs at aPtIndex.

Parameter aCoincident controls whether the two arcs are to be coincident at aPtIndex or whether a short straight segment should be created instead

Parameters
aPtIndexindex of the point in the chain in which to split the arc
aCoincidentIf true, the end point of the first arc will be coincident with the start point of the second arc at aPtIndex. If false, the end point of the first arc will be at aPtIndex-1 and the start point of the second arc will be at aPtIndex, resulting in a short straight line segment between aPtIndex-1 and aPtIndex.

Definition at line 223 of file shape_line_chain.cpp.

224{
225 if( aPtIndex < 0 )
226 aPtIndex += m_shapes.size();
227
228 if( !IsSharedPt( aPtIndex ) && IsArcStart( aPtIndex ) )
229 return; // Nothing to do
230
231 if( !IsPtOnArc( aPtIndex ) )
232 return; // Nothing to do
233
234 wxCHECK_MSG( aPtIndex < static_cast<ssize_t>( m_shapes.size() ), /* void */,
235 wxT( "Invalid point index requested." ) );
236
237 if( IsSharedPt( aPtIndex ) || IsArcEnd( aPtIndex ) )
238 {
239 if( aCoincident || aPtIndex == 0 )
240 return; // nothing to do
241
242 ssize_t firstArcIndex = m_shapes[aPtIndex].first;
243
244 const VECTOR2I& newStart = m_arcs[firstArcIndex].GetP0(); // don't amend the start
245 const VECTOR2I& newEnd = m_points[aPtIndex - 1];
246 amendArc( firstArcIndex, newStart, newEnd );
247
248 if( IsSharedPt( aPtIndex ) )
249 {
250 m_shapes[aPtIndex].first = m_shapes[aPtIndex].second;
251 m_shapes[aPtIndex].second = SHAPE_IS_PT;
252 }
253 else
254 {
255 m_shapes[aPtIndex] = SHAPES_ARE_PT;
256 }
257
258 return;
259 }
260
261 ssize_t currArcIdx = ArcIndex( aPtIndex );
262 SHAPE_ARC& currentArc = m_arcs[currArcIdx];
263
264 SHAPE_ARC newArc1;
265 SHAPE_ARC newArc2;
266
267 VECTOR2I arc1End = ( aCoincident ) ? m_points[aPtIndex] : m_points[aPtIndex - 1];
268 VECTOR2I arc2Start = m_points[aPtIndex];
269
270 newArc1.ConstructFromStartEndCenter( currentArc.GetP0(), arc1End, currentArc.GetCenter(),
271 currentArc.IsClockwise() );
272
273 newArc2.ConstructFromStartEndCenter( arc2Start, currentArc.GetP1(), currentArc.GetCenter(),
274 currentArc.IsClockwise() );
275
276 if( !aCoincident && ArcIndex( aPtIndex - 1 ) != currArcIdx )
277 {
278 //Ignore newArc1 as it has zero points
279 m_arcs[currArcIdx] = newArc2;
280 }
281 else
282 {
283 m_arcs[currArcIdx] = newArc1;
284 m_arcs.insert( m_arcs.begin() + currArcIdx + 1, newArc2 );
285
286 if( aCoincident )
287 {
288 m_shapes[aPtIndex].second = currArcIdx + 1;
289 aPtIndex++;
290 }
291
292 // Only change the arc indices for the second half of the point range
293 for( int i = aPtIndex; i < PointCount(); i++ )
294 {
295 alg::run_on_pair( m_shapes[i], [&]( ssize_t& aIndex ) {
296 if( aIndex != SHAPE_IS_PT )
297 aIndex++;
298 } );
299 }
300 }
301}

References amendArc(), ArcIndex(), SHAPE_ARC::ConstructFromStartEndCenter(), SHAPE_ARC::GetCenter(), SHAPE_ARC::GetP0(), SHAPE_ARC::GetP1(), IsArcEnd(), IsArcStart(), SHAPE_ARC::IsClockwise(), IsPtOnArc(), IsSharedPt(), m_arcs, m_points, m_shapes, PointCount(), alg::run_on_pair(), SHAPE_IS_PT, and SHAPES_ARE_PT.

Referenced by Insert(), Remove(), and Split().

◆ SquaredDistance()

SEG::ecoord SHAPE_LINE_CHAIN_BASE::SquaredDistance ( const VECTOR2I aP,
bool  aOutlineOnly = false 
) const
inherited

Definition at line 803 of file shape_line_chain.cpp.

804{
806
807 if( IsClosed() && PointInside( aP ) && !aOutlineOnly )
808 return 0;
809
810 for( size_t s = 0; s < GetSegmentCount(); s++ )
811 d = std::min( d, GetSegment( s ).SquaredDistance( aP ) );
812
813 return d;
814}
VECTOR2I::extended_type ecoord

References VECTOR2< int >::ECOORD_MAX, SHAPE_LINE_CHAIN_BASE::GetSegment(), SHAPE_LINE_CHAIN_BASE::GetSegmentCount(), SHAPE_LINE_CHAIN_BASE::IsClosed(), SHAPE_LINE_CHAIN_BASE::PointInside(), and SEG::SquaredDistance().

Referenced by Distance().

◆ Type()

◆ TypeName()

wxString SHAPE_BASE::TypeName ( ) const
inlineinherited

Definition at line 100 of file shape.h.

101 {
102 return SHAPE_TYPE_asString( m_type );
103 }
static wxString SHAPE_TYPE_asString(SHAPE_TYPE a)
Definition: shape.h:56

References SHAPE_BASE::m_type, and SHAPE_TYPE_asString().

Referenced by Collide().

◆ Width()

int SHAPE_LINE_CHAIN::Width ( ) const
inline

Get the current width of the segments in the chain.

Returns
the width in internal units.

Definition at line 281 of file shape_line_chain.h.

282 {
283 return m_width;
284 }

References m_width.

Referenced by PNS::LINE::dragCorner45().

Friends And Related Function Documentation

◆ SHAPE_POLY_SET

friend class SHAPE_POLY_SET
friend

Definition at line 863 of file shape_line_chain.h.

Member Data Documentation

◆ facets

std::list< FACET* > SHAPE::facets
privateinherited

Definition at line 143 of file wrlfacet.h.

Referenced by SHAPE::CalcShape(), and SHAPE::NewFacet().

◆ m_arcs

◆ m_bbox

BOX2I SHAPE_LINE_CHAIN::m_bbox
mutableprivate

cached bounding box

Definition at line 964 of file shape_line_chain.h.

Referenced by Append(), GenerateBBoxCache(), GetCachedBBox(), and Slice().

◆ m_closed

bool SHAPE_LINE_CHAIN::m_closed
private

◆ m_points

◆ m_shapes

std::vector<std::pair<ssize_t, ssize_t> > SHAPE_LINE_CHAIN::m_shapes
private

Array of indices that refer to the index of the shape if the point is part of a larger shape, e.g.

arc or spline. If the value is -1, the point is just a point.

There can be up to two shapes associated with a single point (e.g. the end point of one arc might be the start point of another).

Generally speaking only the first element of the pair will be populated (i.e. with a value not equal to SHAPE_IS_PT), unless the point is shared between two arc shapes. If the point is shared, then both the first and second element of the pair should be populated.

The second element must always be SHAPE_IS_PT if the first element is SHAPE_IS_PT.

Definition at line 949 of file shape_line_chain.h.

Referenced by Append(), ArcIndex(), Clear(), convertArc(), convertToClipper(), CShapes(), fixIndicesRotation(), Insert(), IsArcSegment(), IsPtOnArc(), IsSharedPt(), mergeFirstLastPointIfNeeded(), NextShape(), Parse(), Remove(), RemoveShape(), Replace(), Reverse(), reversedArcIndex(), SetPoint(), SHAPE_LINE_CHAIN(), ShapeCount(), Simplify(), Slice(), Split(), and splitArc().

◆ m_type

SHAPE_TYPE SHAPE_BASE::m_type
protectedinherited

< type of our shape

Definition at line 116 of file shape.h.

Referenced by SHAPE::IsNull(), SHAPE_BASE::Type(), and SHAPE_BASE::TypeName().

◆ m_width

int SHAPE_LINE_CHAIN::m_width
private

Width of the segments (for BBox calculations in RTree) TODO Adjust usage of SHAPE_LINE_CHAIN to account for where we need a width and where not Alternatively, we could split the class into a LINE_CHAIN (no width) and SHAPE_LINE_CHAIN that derives from SHAPE as well that does have a width.

Not sure yet on the correct path. TODO Note that we also have SHAPE_SIMPLE which is a closed, filled SHAPE_LINE_CHAIN.

Definition at line 961 of file shape_line_chain.h.

Referenced by BBox(), GenerateBBoxCache(), SetWidth(), and Width().

◆ MIN_PRECISION_IU

const int SHAPE::MIN_PRECISION_IU = 4
staticinherited

This is the minimum precision for all the points in a shape.

Definition at line 128 of file shape.h.

Referenced by BOOST_AUTO_TEST_CASE(), DIRECTION_45::BuildInitialTrace(), CompareLength(), CIRCLE::Contains(), EDIT_TOOL::FilletTracks(), and CIRCLE::IntersectLine().

◆ SHAPE_IS_PT

const ssize_t SHAPE_LINE_CHAIN::SHAPE_IS_PT = -1
staticprivate

◆ SHAPES_ARE_PT

const std::pair< ssize_t, ssize_t > SHAPE_LINE_CHAIN::SHAPES_ARE_PT = { SHAPE_IS_PT, SHAPE_IS_PT }
staticprivate

The documentation for this class was generated from the following files: