KiCad PCB EDA Suite
shape_line_chain.h
Go to the documentation of this file.
1 /*
2  * This program source code file is part of KiCad, a free EDA CAD application.
3  *
4  * Copyright (C) 2013 CERN
5  * @author Tomasz Wlostowski <[email protected]>
6  * Copyright (C) 2013-2021 KiCad Developers, see AUTHORS.txt for contributors.
7  *
8  * This program is free software; you can redistribute it and/or
9  * modify it under the terms of the GNU General Public License
10  * as published by the Free Software Foundation; either version 2
11  * of the License, or (at your option) any later version.
12  *
13  * This program is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16  * GNU General Public License for more details.
17  *
18  * You should have received a copy of the GNU General Public License
19  * along with this program; if not, you may find one here:
20  * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
21  * or you may search the http://www.gnu.org website for the version 2 license,
22  * or you may write to the Free Software Foundation, Inc.,
23  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
24  */
25 
26 #ifndef __SHAPE_LINE_CHAIN
27 #define __SHAPE_LINE_CHAIN
28 
29 
30 #include <clipper.hpp>
31 #include <geometry/seg.h>
32 #include <geometry/shape.h>
33 #include <geometry/shape_arc.h>
34 #include <math/vector2d.h>
35 
41 {
43  {
44  m_FirstArcIdx = -1;
45  m_SecondArcIdx = -1;
46  }
47 
48  CLIPPER_Z_VALUE( const std::pair<ssize_t, ssize_t> aShapeIndices, ssize_t aOffset = 0 )
49  {
50  m_FirstArcIdx = aShapeIndices.first;
51  m_SecondArcIdx = aShapeIndices.second;
52 
53  auto offsetVal = [&]( ssize_t& aVal )
54  {
55  if( aVal >= 0 )
56  aVal += aOffset;
57  };
58 
59  offsetVal( m_FirstArcIdx );
60  offsetVal( m_SecondArcIdx );
61  }
62 
63  ssize_t m_FirstArcIdx;
64  ssize_t m_SecondArcIdx;
65 };
66 
67 
81 {
82 private:
83  typedef std::vector<VECTOR2I>::iterator point_iter;
84  typedef std::vector<VECTOR2I>::const_iterator point_citer;
85 
86 public:
90  struct INTERSECTION
91  {
94 
96  int index_our;
97 
101 
104 
109 
113  bool valid;
114  };
115 
116 
122  {
123  public:
124  POINT_INSIDE_TRACKER( const VECTOR2I& aPoint );
125 
126  void AddPolyline( const SHAPE_LINE_CHAIN& aPolyline );
127  bool IsInside();
128 
129  private:
130 
131  bool processVertex ( const VECTOR2I& ip, const VECTOR2I& ipNext );
132 
137  int m_state;
138  int m_count;
139  };
140 
141  typedef std::vector<INTERSECTION> INTERSECTIONS;
142 
143 
149  m_closed( false ),
150  m_width( 0 )
151  {}
152 
155  m_points( aShape.m_points ),
156  m_shapes( aShape.m_shapes ),
157  m_arcs( aShape.m_arcs ),
158  m_closed( aShape.m_closed ),
159  m_width( aShape.m_width ),
160  m_bbox( aShape.m_bbox )
161  {}
162 
163  SHAPE_LINE_CHAIN( const std::vector<int>& aV );
164 
165  SHAPE_LINE_CHAIN( const std::vector<wxPoint>& aV, bool aClosed = false ) :
167  m_closed( aClosed ),
168  m_width( 0 )
169  {
170  m_points.reserve( aV.size() );
171 
172  for( auto pt : aV )
173  m_points.emplace_back( pt.x, pt.y );
174 
175  m_shapes = std::vector<std::pair<ssize_t, ssize_t>>( aV.size(), SHAPES_ARE_PT );
176  }
177 
178  SHAPE_LINE_CHAIN( const std::vector<VECTOR2I>& aV, bool aClosed = false ) :
180  m_closed( aClosed ),
181  m_width( 0 )
182  {
183  m_points = aV;
184  m_shapes = std::vector<std::pair<ssize_t, ssize_t>>( aV.size(), SHAPES_ARE_PT );
185  }
186 
187  SHAPE_LINE_CHAIN( const SHAPE_ARC& aArc, bool aClosed = false ) :
189  m_closed( aClosed ),
190  m_width( 0 )
191  {
193  m_arcs.emplace_back( aArc );
194  m_arcs.back().SetWidth( 0 );
195  m_shapes = std::vector<std::pair<ssize_t, ssize_t>>( m_points.size(), { 0, SHAPE_IS_PT } );
196  }
197 
198  SHAPE_LINE_CHAIN( const ClipperLib::Path& aPath,
199  const std::vector<CLIPPER_Z_VALUE>& aZValueBuffer,
200  const std::vector<SHAPE_ARC>& aArcBuffer );
201 
203  {}
204 
217  virtual bool Collide( const VECTOR2I& aP, int aClearance = 0, int* aActual = nullptr,
218  VECTOR2I* aLocation = nullptr ) const override;
219 
232  virtual bool Collide( const SEG& aSeg, int aClearance = 0, int* aActual = nullptr,
233  VECTOR2I* aLocation = nullptr ) const override;
234 
235  SHAPE_LINE_CHAIN& operator=( const SHAPE_LINE_CHAIN& ) = default;
236 
237  SHAPE* Clone() const override;
238 
242  void Clear()
243  {
244  m_points.clear();
245  m_arcs.clear();
246  m_shapes.clear();
247  m_closed = false;
248  }
249 
256  void SetClosed( bool aClosed )
257  {
258  m_closed = aClosed;
260  }
261 
265  bool IsClosed() const override
266  {
267  return m_closed;
268  }
269 
275  void SetWidth( int aWidth )
276  {
277  m_width = aWidth;
278  }
279 
285  int Width() const
286  {
287  return m_width;
288  }
289 
295  int SegmentCount() const
296  {
297  int c = m_points.size() - 1;
298  if( m_closed )
299  c++;
300 
301  return std::max( 0, c );
302  }
303 
311  int ShapeCount() const;
312 
318  int PointCount() const
319  {
320  return m_points.size();
321  }
322 
330  SEG Segment( int aIndex )
331  {
332  if( aIndex < 0 )
333  aIndex += SegmentCount();
334 
335  if( aIndex == (int)( m_points.size() - 1 ) && m_closed )
336  return SEG( m_points[aIndex], m_points[0], aIndex );
337  else
338  return SEG( m_points[aIndex], m_points[aIndex + 1], aIndex );
339  }
340 
348  const SEG CSegment( int aIndex ) const
349  {
350  if( aIndex < 0 )
351  aIndex += SegmentCount();
352 
353  if( aIndex == (int)( m_points.size() - 1 ) && m_closed )
354  return SEG( m_points[aIndex], m_points[0], aIndex );
355  else
356  return SEG( m_points[aIndex], m_points[aIndex + 1], aIndex );
357  }
358 
372  int NextShape( int aPointIndex, bool aForwards = true ) const;
373 
374  int PrevShape( int aPointIndex ) const
375  {
376  return NextShape( aPointIndex, false );
377  }
378 
385  void SetPoint( int aIndex, const VECTOR2I& aPos );
386 
393  const VECTOR2I& CPoint( int aIndex ) const
394  {
395  if( aIndex < 0 )
396  aIndex += PointCount();
397  else if( aIndex >= PointCount() )
398  aIndex -= PointCount();
399 
400  return m_points[aIndex];
401  }
402 
403  const std::vector<VECTOR2I>& CPoints() const
404  {
405  return m_points;
406  }
407 
411  const VECTOR2I& CLastPoint() const
412  {
413  return m_points[static_cast<size_t>( PointCount() ) - 1];
414  }
415 
419  const std::vector<SHAPE_ARC>& CArcs() const
420  {
421  return m_arcs;
422  }
423 
427  const std::vector<std::pair<ssize_t, ssize_t>>& CShapes() const
428  {
429  return m_shapes;
430  }
431 
433  const BOX2I BBox( int aClearance = 0 ) const override
434  {
435  BOX2I bbox;
436  bbox.Compute( m_points );
437 
438  if( aClearance != 0 || m_width != 0 )
439  bbox.Inflate( aClearance + m_width );
440 
441  return bbox;
442  }
443 
444  void GenerateBBoxCache() const
445  {
447 
448  if( m_width != 0 )
450  }
451 
452  BOX2I* GetCachedBBox() const override
453  {
454  return &m_bbox;
455  }
456 
463  int Distance( const VECTOR2I& aP, bool aOutlineOnly = false ) const;
464 
470  const SHAPE_LINE_CHAIN Reverse() const;
471 
477  void ClearArcs();
478 
484  long long int Length() const;
485 
495  void Append( int aX, int aY, bool aAllowDuplication = false )
496  {
497  VECTOR2I v( aX, aY );
498  Append( v, aAllowDuplication );
499  }
500 
509  void Append( const VECTOR2I& aP, bool aAllowDuplication = false )
510  {
511  if( m_points.size() == 0 )
512  m_bbox = BOX2I( aP, VECTOR2I( 0, 0 ) );
513 
514  if( m_points.size() == 0 || aAllowDuplication || CPoint( -1 ) != aP )
515  {
516  m_points.push_back( aP );
517  m_shapes.push_back( SHAPES_ARE_PT );
518  m_bbox.Merge( aP );
519  }
520  }
521 
527  void Append( const SHAPE_LINE_CHAIN& aOtherLine );
528 
529  void Append( const SHAPE_ARC& aArc );
530 
531  void Insert( size_t aVertex, const VECTOR2I& aP );
532 
533  void Insert( size_t aVertex, const SHAPE_ARC& aArc );
534 
542  void Replace( int aStartIndex, int aEndIndex, const VECTOR2I& aP );
543 
552  void Replace( int aStartIndex, int aEndIndex, const SHAPE_LINE_CHAIN& aLine );
553 
560  void Remove( int aStartIndex, int aEndIndex );
561 
567  void Remove( int aIndex )
568  {
569  Remove( aIndex, aIndex );
570  }
571 
580  void RemoveShape( int aPointIndex );
581 
589  int Split( const VECTOR2I& aP );
590 
597  int Find( const VECTOR2I& aP, int aThreshold = 0 ) const;
598 
605  int FindSegment( const VECTOR2I& aP, int aThreshold = 1 ) const;
606 
614  const SHAPE_LINE_CHAIN Slice( int aStartIndex, int aEndIndex = -1 ) const;
615 
617  {
618  compareOriginDistance( const VECTOR2I& aOrigin ):
619  m_origin( aOrigin )
620  {}
621 
622  bool operator()( const INTERSECTION& aA, const INTERSECTION& aB )
623  {
624  return ( m_origin - aA.p ).EuclideanNorm() < ( m_origin - aB.p ).EuclideanNorm();
625  }
626 
628  };
629 
630  bool Intersects( const SHAPE_LINE_CHAIN& aChain ) const;
631 
640  int Intersect( const SEG& aSeg, INTERSECTIONS& aIp ) const;
641 
650  int Intersect( const SHAPE_LINE_CHAIN& aChain, INTERSECTIONS& aIp,
651  bool aExcludeColinearAndTouching = false ) const;
652 
659  int PathLength( const VECTOR2I& aP, int aIndex = -1 ) const;
660 
668  bool CheckClearance( const VECTOR2I& aP, const int aDist) const;
669 
675  const OPT<INTERSECTION> SelfIntersecting() const;
676 
683  SHAPE_LINE_CHAIN& Simplify( bool aRemoveColinear = true );
684 
691  int NearestSegment( const VECTOR2I& aP ) const;
692 
701  const VECTOR2I NearestPoint( const VECTOR2I& aP, bool aAllowInternalShapePoints = true ) const;
702 
711  const VECTOR2I NearestPoint( const SEG& aSeg, int& dist ) const;
712 
714  const std::string Format() const override;
715 
717  bool Parse( std::stringstream& aStream ) override;
718 
719  bool operator!=( const SHAPE_LINE_CHAIN& aRhs ) const
720  {
721  if( PointCount() != aRhs.PointCount() )
722  return true;
723 
724  for( int i = 0; i < PointCount(); i++ )
725  {
726  if( CPoint( i ) != aRhs.CPoint( i ) )
727  return true;
728  }
729 
730  return false;
731  }
732 
733  bool CompareGeometry( const SHAPE_LINE_CHAIN& aOther ) const;
734 
735  void Move( const VECTOR2I& aVector ) override
736  {
737  for( auto& pt : m_points )
738  pt += aVector;
739 
740  for( auto& arc : m_arcs )
741  arc.Move( aVector );
742  }
743 
751  void Mirror( bool aX = true, bool aY = false, const VECTOR2I& aRef = { 0, 0 } );
752 
758  void Mirror( const SEG& axis );
759 
766  void Rotate( double aAngle, const VECTOR2I& aCenter = VECTOR2I( 0, 0 ) ) override;
767 
768  bool IsSolid() const override
769  {
770  return false;
771  }
772 
773  const VECTOR2I PointAlong( int aPathLength ) const;
774 
780  double Area( bool aAbsolute = true ) const;
781 
782  size_t ArcCount() const
783  {
784  return m_arcs.size();
785  }
786 
790  ssize_t ArcIndex( size_t aSegment ) const
791  {
792  if( IsSharedPt( aSegment ) )
793  return m_shapes[aSegment].second;
794  else
795  return m_shapes[aSegment].first;
796  }
797 
798  const SHAPE_ARC& Arc( size_t aArc ) const
799  {
800  return m_arcs[aArc];
801  }
802 
808  bool IsSharedPt( size_t aIndex ) const
809  {
810  return aIndex < m_shapes.size()
811  && m_shapes[aIndex].first != SHAPE_IS_PT
812  && m_shapes[aIndex].second != SHAPE_IS_PT;
813  }
814 
815 
816  bool IsPtOnArc( size_t aPtIndex ) const
817  {
818  return aPtIndex < m_shapes.size() && m_shapes[aPtIndex] != SHAPES_ARE_PT;
819  }
820 
821 
822  bool IsArcSegment( size_t aSegment ) const
823  {
824  /*
825  * A segment is part of an arc except in the special case of two arcs next to each other
826  * but without a shared vertex. Here there is a segment between the end of the first arc
827  * and the start of the second arc.
828  */
829  size_t nextIdx = aSegment + 1;
830 
831  if( nextIdx > m_shapes.size() - 1 )
832  {
833  if( nextIdx == m_shapes.size() && m_closed )
834  nextIdx = 0; // segment between end point and first point
835  else
836  return false;
837  }
838 
839  return ( IsPtOnArc( aSegment )
840  && ( IsSharedPt( aSegment )
841  || m_shapes[aSegment].first == m_shapes[nextIdx].first ) );
842  }
843 
844 
845  bool IsArcStart( size_t aIndex ) const
846  {
847  if( aIndex == 0 )
848  return IsPtOnArc( aIndex );
849 
850  return ( IsSharedPt( aIndex ) || ( IsPtOnArc( aIndex ) && !IsArcSegment( aIndex - 1 ) ) );
851  }
852 
853 
854  bool IsArcEnd( size_t aIndex ) const
855  {
856  return ( IsSharedPt( aIndex ) || ( IsPtOnArc( aIndex ) && !IsArcSegment( aIndex ) ) );
857  }
858 
859  virtual const VECTOR2I GetPoint( int aIndex ) const override { return CPoint(aIndex); }
860  virtual const SEG GetSegment( int aIndex ) const override { return CSegment(aIndex); }
861  virtual size_t GetPointCount() const override { return PointCount(); }
862  virtual size_t GetSegmentCount() const override { return SegmentCount(); }
863 
864 protected:
865  friend class SHAPE_POLY_SET;
866 
872  void convertArc( ssize_t aArcIndex );
873 
886  void splitArc( ssize_t aPtIndex, bool aCoincident = false );
887 
888  void amendArc( size_t aArcIndex, const VECTOR2I& aNewStart, const VECTOR2I& aNewEnd );
889 
890  void amendArcStart( size_t aArcIndex, const VECTOR2I& aNewStart )
891  {
892  amendArc( aArcIndex, aNewStart, m_arcs[aArcIndex].GetP1() );
893  }
894 
895  void amendArcEnd( size_t aArcIndex, const VECTOR2I& aNewEnd )
896  {
897  amendArc( aArcIndex, m_arcs[aArcIndex].GetP0(), aNewEnd );
898  }
899 
903  ssize_t reversedArcIndex( size_t aSegment ) const
904  {
905  if( IsSharedPt( aSegment ) )
906  return m_shapes[aSegment].first;
907  else
908  return m_shapes[aSegment].second;
909  }
910 
914  ClipperLib::Path convertToClipper( bool aRequiredOrientation,
915  std::vector<CLIPPER_Z_VALUE>& aZValueBuffer,
916  std::vector<SHAPE_ARC>& aArcBuffer ) const;
917 
921  void fixIndicesRotation();
922 
927 
928 private:
929 
930  static const ssize_t SHAPE_IS_PT;
931 
932  static const std::pair<ssize_t, ssize_t> SHAPES_ARE_PT;
933 
935  std::vector<VECTOR2I> m_points;
936 
951  std::vector<std::pair<ssize_t, ssize_t>> m_shapes;
952 
953  std::vector<SHAPE_ARC> m_arcs;
954 
956  bool m_closed;
957 
963  int m_width;
964 
966  mutable BOX2I m_bbox;
967 };
968 
969 
970 #endif // __SHAPE_LINE_CHAIN
double EuclideanNorm(const wxPoint &vector)
Euclidean norm of a 2D vector.
Definition: trigo.h:146
Represent an intersection between two line segments.
int PrevShape(int aPointIndex) const
const std::vector< std::pair< ssize_t, ssize_t > > & CShapes() const
BOX2I m_bbox
cached bounding box
compareOriginDistance(const VECTOR2I &aOrigin)
void Append(const VECTOR2I &aP, bool aAllowDuplication=false)
Append a new point at the end of the line chain.
const SHAPE_ARC & Arc(size_t aArc) const
long long int Length() const
Return length of the line chain in Euclidean metric.
int Split(const VECTOR2I &aP)
Insert the point aP belonging to one of the our segments, splitting the adjacent segment in two.
BOX2< VECTOR2I > BOX2I
Definition: box2.h:506
void fixIndicesRotation()
Fix indices of this chain to ensure arcs are not split between the end and start indices.
bool operator!=(const SHAPE_LINE_CHAIN &aRhs) const
int Intersect(const SEG &aSeg, INTERSECTIONS &aIp) const
Find all intersection points between our line chain and the segment aSeg.
ClipperLib::Path convertToClipper(bool aRequiredOrientation, std::vector< CLIPPER_Z_VALUE > &aZValueBuffer, std::vector< SHAPE_ARC > &aArcBuffer) const
Create a new Clipper path from the SHAPE_LINE_CHAIN in a given orientation.
virtual size_t GetSegmentCount() const override
std::vector< INTERSECTION > INTERSECTIONS
bool IsSharedPt(size_t aIndex) const
Test if a point is shared between multiple shapes.
virtual size_t GetPointCount() const override
void RemoveShape(int aPointIndex)
Remove the shape at the given index from the line chain.
SHAPE_LINE_CHAIN & Simplify(bool aRemoveColinear=true)
Simplify the line chain by removing colinear adjacent segments and duplicate vertices.
void SetPoint(int aIndex, const VECTOR2I &aPos)
Move a point to a specific location.
static const ssize_t SHAPE_IS_PT
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.
SHAPE_LINE_CHAIN(const SHAPE_LINE_CHAIN &aShape)
VECTOR2I p
< Point of intersection between our and their.
void Move(const VECTOR2I &aVector) override
int Width() const
Get the current width of the segments in the chain.
std::vector< VECTOR2I >::const_iterator point_citer
void Compute(const Container &aPointList)
Compute the bounding box from a given list of points.
Definition: box2.h:75
SHAPE_LINE_CHAIN(const SHAPE_ARC &aArc, bool aClosed=false)
int Distance(const VECTOR2I &aP, bool aOutlineOnly=false) const
Compute the minimum distance between the line chain and a point aP.
virtual ~SHAPE_LINE_CHAIN()
size_t ArcCount() const
void AddPolyline(const SHAPE_LINE_CHAIN &aPolyline)
double Area(bool aAbsolute=true) const
Return the area of this chain.
const SHAPE_LINE_CHAIN Reverse() const
Reverse point order in the line chain.
const std::vector< SHAPE_ARC > & CArcs() const
VECTOR2< int > VECTOR2I
Definition: vector2d.h:622
void convertArc(ssize_t aArcIndex)
Convert an arc to only a point chain by removing the arc and references.
int PointCount() const
Return the number of points (vertices) in this line chain.
int FindSegment(const VECTOR2I &aP, int aThreshold=1) const
Search for segment containing point aP.
void splitArc(ssize_t aPtIndex, bool aCoincident=false)
Splits an arc into two arcs at aPtIndex.
const OPT< INTERSECTION > SelfIntersecting() const
Check if the line chain is self-intersecting.
SHAPE_LINE_CHAIN(const std::vector< VECTOR2I > &aV, bool aClosed=false)
bool operator()(const INTERSECTION &aA, const INTERSECTION &aB)
void Append(int aX, int aY, bool aAllowDuplication=false)
Append a new point at the end of the line chain.
std::vector< SHAPE_ARC > m_arcs
const VECTOR2I NearestPoint(const VECTOR2I &aP, bool aAllowInternalShapePoints=true) const
Find a point on the line chain that is closest to point aP.
bool Parse(std::stringstream &aStream) override
void Insert(size_t aVertex, const VECTOR2I &aP)
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.
bool IsArcStart(size_t aIndex) const
void SetWidth(int aWidth)
Set the width of all segments in the chain.
void SetClosed(bool aClosed)
Mark the line chain as closed (i.e.
bool m_closed
is the line chain closed?
SHAPE_LINE_CHAIN()
Initialize an empty line chain.
SHAPE_LINE_CHAIN & operator=(const SHAPE_LINE_CHAIN &)=default
int PathLength(const VECTOR2I &aP, int aIndex=-1) const
Compute the walk path length from the beginning of the line chain and the point aP belonging to our l...
const BOX2I BBox(int aClearance=0) const override
Compute a bounding box of the shape, with a margin of aClearance a collision.
bool IsArcSegment(size_t aSegment) const
bool IsClosed() const override
const std::vector< VECTOR2I > & CPoints() const
bool is_corner_their
Auxiliary flag to avoid copying intersection info to intersection refining code, used by the refining...
int Find(const VECTOR2I &aP, int aThreshold=0) const
Search for point aP.
void ClearArcs()
Remove all arc references in the line chain, resulting in a chain formed only of straight segments.
Represent a set of closed polygons.
std::vector< VECTOR2I > m_points
array of vertices
bool CheckClearance(const VECTOR2I &aP, const int aDist) const
Check if point aP is closer to (or on) an edge or vertex of the line chain.
virtual const SEG GetSegment(int aIndex) const override
bool Intersects(const SHAPE_LINE_CHAIN &aChain) const
int ShapeCount() const
Return the number of shapes (line segments or arcs) in this line chain.
bool IsSolid() const override
An abstract shape on 2D plane.
Definition: shape.h:116
void amendArcStart(size_t aArcIndex, const VECTOR2I &aNewStart)
void Remove(int aStartIndex, int aEndIndex)
Remove the range of points [start_index, end_index] from the line chain.
BOX2< Vec > & Merge(const BOX2< Vec > &aRect)
Modify the position and size of the rectangle in order to contain aRect.
Definition: box2.h:363
void amendArc(size_t aArcIndex, const VECTOR2I &aNewStart, const VECTOR2I &aNewEnd)
const std::string Format() const override
void Remove(int aIndex)
Remove the aIndex-th point from the line chain.
int SegmentCount() const
Return the number of segments in this line chain.
virtual const VECTOR2I GetPoint(int aIndex) const override
bool IsPtOnArc(size_t aPtIndex) const
CLIPPER_Z_VALUE(const std::pair< ssize_t, ssize_t > aShapeIndices, ssize_t aOffset=0)
SHAPE_LINE_CHAIN(const std::vector< wxPoint > &aV, bool aClosed=false)
virtual bool Collide(const VECTOR2I &aP, int aClearance=0, int *aActual=nullptr, VECTOR2I *aLocation=nullptr) const override
Check if point aP lies closer to us than aClearance.
void Rotate(double aAngle, const VECTOR2I &aCenter=VECTOR2I(0, 0)) override
Rotate all vertices by a given angle.
Definition: seg.h:40
std::vector< std::pair< ssize_t, ssize_t > > m_shapes
Array of indices that refer to the index of the shape if the point is part of a larger shape,...
int NearestSegment(const VECTOR2I &aP) const
Find the segment nearest the given point.
void mergeFirstLastPointIfNeeded()
Merge the first and last point if they are the same and this chain is closed.
BOX2< Vec > & Inflate(coord_type dx, coord_type dy)
Inflates the rectangle horizontally by dx and vertically by dy.
Definition: box2.h:281
SEG Segment(int aIndex)
Return a copy of the aIndex-th segment in the line chain.
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:458
int index_their
When true, the corner [index_our] of the 'our' line lies exactly on 'their' line.
bool is_corner_our
When true, the corner [index_their] of the 'their' line lies exactly on 'our' line.
const SEG CSegment(int aIndex) const
Return a constant copy of the aIndex segment in the line chain.
ssize_t reversedArcIndex(size_t aSegment) const
Return the arc index for the given segment index, looking backwards.
Represent a polyline containing arcs as well as line segments: A chain of connected line and/or arc s...
int m_width
Width of the segments (for BBox calculations in RTree) TODO Adjust usage of SHAPE_LINE_CHAIN to accou...
bool IsArcEnd(size_t aIndex) const
line chain (polyline)
Definition: shape.h:45
const VECTOR2I & CLastPoint() const
Return the last point in the line chain.
boost::optional< T > OPT
Definition: optional.h:7
A dynamic state checking if a point lies within polygon with a dynamically built outline ( with each ...
BOX2I * GetCachedBBox() const override
void Clear()
Remove all points from the line chain.
SHAPE * Clone() const override
Return a dynamically allocated copy of the shape.
void GenerateBBoxCache() const
std::vector< VECTOR2I >::iterator point_iter
Holds information on each point of a SHAPE_LINE_CHAIN that is retrievable after an operation with Cli...
void Replace(int aStartIndex, int aEndIndex, const VECTOR2I &aP)
Replace points with indices in range [start_index, end_index] with a single point aP.
int NextShape(int aPointIndex, bool aForwards=true) const
Return the vertex index of the next shape in the chain, or -1 if aPointIndex is the last shape.
static const std::pair< ssize_t, ssize_t > SHAPES_ARE_PT
void amendArcEnd(size_t aArcIndex, const VECTOR2I &aNewEnd)
int index_our
index of the intersecting corner/segment in the 'their' (Intersect() method parameter) line.
const VECTOR2I PointAlong(int aPathLength) const
bool processVertex(const VECTOR2I &ip, const VECTOR2I &ipNext)
void Mirror(bool aX=true, bool aY=false, const VECTOR2I &aRef={ 0, 0 })
Mirror the line points about y or x (or both).
bool CompareGeometry(const SHAPE_LINE_CHAIN &aOther) const