KiCad PCB EDA Suite
Loading...
Searching...
No Matches
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-2022 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 <clipper2/clipper.h>
32#include <geometry/seg.h>
33#include <geometry/shape.h>
34#include <geometry/shape_arc.h>
36#include <math/vector2d.h>
37
43{
45 {
46 m_FirstArcIdx = -1;
47 m_SecondArcIdx = -1;
48 }
49
50 CLIPPER_Z_VALUE( const std::pair<ssize_t, ssize_t> aShapeIndices, ssize_t aOffset = 0 )
51 {
52 m_FirstArcIdx = aShapeIndices.first;
53 m_SecondArcIdx = aShapeIndices.second;
54
55 auto offsetVal = [&]( ssize_t& aVal )
56 {
57 if( aVal >= 0 )
58 aVal += aOffset;
59 };
60
61 offsetVal( m_FirstArcIdx );
62 offsetVal( m_SecondArcIdx );
63 }
64
67};
68
69
83{
84private:
85 typedef std::vector<VECTOR2I>::iterator point_iter;
86 typedef std::vector<VECTOR2I>::const_iterator point_citer;
87
88public:
93 {
96
99
103
106
111
115 bool valid;
116
118 index_our( -1 ),
119 index_their( -1 ),
120 is_corner_our( false ),
121 is_corner_their( false ),
122 valid( false )
123 {
124 }
125 };
126
127
133 {
134 public:
135 POINT_INSIDE_TRACKER( const VECTOR2I& aPoint );
136
137 void AddPolyline( const SHAPE_LINE_CHAIN& aPolyline );
138 bool IsInside();
139
140 private:
141
142 bool processVertex ( const VECTOR2I& ip, const VECTOR2I& ipNext );
143
150 };
151
152 typedef std::vector<INTERSECTION> INTERSECTIONS;
153
154
160 m_closed( false ),
161 m_width( 0 )
162 {}
163
166 m_points( aShape.m_points ),
167 m_shapes( aShape.m_shapes ),
168 m_arcs( aShape.m_arcs ),
169 m_closed( aShape.m_closed ),
170 m_width( aShape.m_width ),
171 m_bbox( aShape.m_bbox )
172 {}
173
174 SHAPE_LINE_CHAIN( const std::vector<int>& aV );
175
176 SHAPE_LINE_CHAIN( const std::vector<VECTOR2I>& aV, bool aClosed = false ) :
178 m_closed( aClosed ),
179 m_width( 0 )
180 {
181 m_points = aV;
182 m_shapes = std::vector<std::pair<ssize_t, ssize_t>>( aV.size(), SHAPES_ARE_PT );
183 }
184
185 SHAPE_LINE_CHAIN( const SHAPE_ARC& aArc, bool aClosed = false ) :
187 m_closed( aClosed ),
188 m_width( 0 )
189 {
191 m_arcs.emplace_back( aArc );
192 m_arcs.back().SetWidth( 0 );
193 m_shapes = std::vector<std::pair<ssize_t, ssize_t>>( m_points.size(), { 0, SHAPE_IS_PT } );
194 }
195
196 SHAPE_LINE_CHAIN( const ClipperLib::Path& aPath,
197 const std::vector<CLIPPER_Z_VALUE>& aZValueBuffer,
198 const std::vector<SHAPE_ARC>& aArcBuffer );
199
200 SHAPE_LINE_CHAIN( const Clipper2Lib::Path64& aPath,
201 const std::vector<CLIPPER_Z_VALUE>& aZValueBuffer,
202 const std::vector<SHAPE_ARC>& aArcBuffer );
203
205 {}
206
219 virtual bool Collide( const VECTOR2I& aP, int aClearance = 0, int* aActual = nullptr,
220 VECTOR2I* aLocation = nullptr ) const override;
221
234 virtual bool Collide( const SEG& aSeg, int aClearance = 0, int* aActual = nullptr,
235 VECTOR2I* aLocation = nullptr ) const override;
236
238
239 SHAPE* Clone() const override;
240
244 void Clear()
245 {
246 m_points.clear();
247 m_arcs.clear();
248 m_shapes.clear();
249 m_closed = false;
250 }
251
258 void SetClosed( bool aClosed )
259 {
260 m_closed = aClosed;
262 }
263
267 bool IsClosed() const override
268 {
269 return m_closed;
270 }
271
277 void SetWidth( int aWidth )
278 {
279 m_width = aWidth;
280 }
281
287 int Width() const
288 {
289 return m_width;
290 }
291
297 int SegmentCount() const
298 {
299 int c = m_points.size() - 1;
300
301 if( m_closed )
302 c++;
303
304 return std::max( 0, c );
305 }
306
314 int ShapeCount() const;
315
321 int PointCount() const
322 {
323 return m_points.size();
324 }
325
333 SEG Segment( int aIndex )
334 {
335 if( aIndex < 0 )
336 aIndex += SegmentCount();
337
338 if( aIndex == (int)( m_points.size() - 1 ) && m_closed )
339 return SEG( m_points[aIndex], m_points[0], aIndex );
340 else
341 return SEG( m_points[aIndex], m_points[aIndex + 1], aIndex );
342 }
343
351 const SEG CSegment( int aIndex ) const
352 {
353 if( aIndex < 0 )
354 aIndex += SegmentCount();
355
356 if( aIndex == (int)( m_points.size() - 1 ) && m_closed )
357 return SEG( m_points[aIndex], m_points[0], aIndex );
358 else
359 return SEG( m_points[aIndex], m_points[aIndex + 1], aIndex );
360 }
361
375 int NextShape( int aPointIndex, bool aForwards = true ) const;
376
377 int PrevShape( int aPointIndex ) const
378 {
379 return NextShape( aPointIndex, false );
380 }
381
388 void SetPoint( int aIndex, const VECTOR2I& aPos );
389
396 const VECTOR2I& CPoint( int aIndex ) const
397 {
398 if( aIndex < 0 )
399 aIndex += PointCount();
400 else if( aIndex >= PointCount() )
401 aIndex -= PointCount();
402
403 return m_points[aIndex];
404 }
405
406 const std::vector<VECTOR2I>& CPoints() const
407 {
408 return m_points;
409 }
410
414 const VECTOR2I& CLastPoint() const
415 {
416 return m_points[static_cast<size_t>( PointCount() ) - 1];
417 }
418
422 const std::vector<SHAPE_ARC>& CArcs() const
423 {
424 return m_arcs;
425 }
426
430 const std::vector<std::pair<ssize_t, ssize_t>>& CShapes() const
431 {
432 return m_shapes;
433 }
434
436 const BOX2I BBox( int aClearance = 0 ) const override
437 {
438 BOX2I bbox;
439 bbox.Compute( m_points );
440
441 if( aClearance != 0 || m_width != 0 )
442 bbox.Inflate( aClearance + m_width );
443
444 return bbox;
445 }
446
447 void GenerateBBoxCache() const
448 {
450
451 if( m_width != 0 )
453 }
454
455 BOX2I* GetCachedBBox() const override
456 {
457 return &m_bbox;
458 }
459
465 const SHAPE_LINE_CHAIN Reverse() const;
466
472 void ClearArcs();
473
479 long long int Length() const;
480
484 void ReservePoints( size_t aSize )
485 {
486 m_points.reserve( aSize );
487 }
488
498 void Append( int aX, int aY, bool aAllowDuplication = false )
499 {
500 VECTOR2I v( aX, aY );
501 Append( v, aAllowDuplication );
502 }
503
512 void Append( const VECTOR2I& aP, bool aAllowDuplication = false )
513 {
514 if( m_points.size() == 0 )
515 m_bbox = BOX2I( aP, VECTOR2I( 0, 0 ) );
516
517 if( m_points.size() == 0 || aAllowDuplication || CPoint( -1 ) != aP )
518 {
519 m_points.push_back( aP );
520 m_shapes.push_back( SHAPES_ARE_PT );
521 m_bbox.Merge( aP );
522 }
523 }
524
530 void Append( const SHAPE_LINE_CHAIN& aOtherLine );
531
532 void Append( const SHAPE_ARC& aArc );
533 void Append( const SHAPE_ARC& aArc, double aAccuracy );
534
535 void Insert( size_t aVertex, const VECTOR2I& aP );
536
537 void Insert( size_t aVertex, const SHAPE_ARC& aArc );
538
546 void Replace( int aStartIndex, int aEndIndex, const VECTOR2I& aP );
547
556 void Replace( int aStartIndex, int aEndIndex, const SHAPE_LINE_CHAIN& aLine );
557
564 void Remove( int aStartIndex, int aEndIndex );
565
571 void Remove( int aIndex )
572 {
573 Remove( aIndex, aIndex );
574 }
575
584 void RemoveShape( int aPointIndex );
585
594 int Split( const VECTOR2I& aP, bool aExact = false );
595
602 int Find( const VECTOR2I& aP, int aThreshold = 0 ) const;
603
610 int FindSegment( const VECTOR2I& aP, int aThreshold = 1 ) const;
611
619 const SHAPE_LINE_CHAIN Slice( int aStartIndex, int aEndIndex = -1 ) const;
620
622 {
624 m_origin( aOrigin )
625 {}
626
627 bool operator()( const INTERSECTION& aA, const INTERSECTION& aB )
628 {
629 return ( m_origin - aA.p ).EuclideanNorm() < ( m_origin - aB.p ).EuclideanNorm();
630 }
631
633 };
634
635 bool Intersects( const SHAPE_LINE_CHAIN& aChain ) const;
636
645 int Intersect( const SEG& aSeg, INTERSECTIONS& aIp ) const;
646
655 int Intersect( const SHAPE_LINE_CHAIN& aChain, INTERSECTIONS& aIp,
656 bool aExcludeColinearAndTouching = false,
657 BOX2I* aChainBBox = nullptr ) const;
658
665 int PathLength( const VECTOR2I& aP, int aIndex = -1 ) const;
666
674 bool CheckClearance( const VECTOR2I& aP, const int aDist) const;
675
681 const std::optional<INTERSECTION> SelfIntersecting() const;
682
689 SHAPE_LINE_CHAIN& Simplify( bool aRemoveColinear = true );
690
697 int NearestSegment( const VECTOR2I& aP ) const;
698
707 const VECTOR2I NearestPoint( const VECTOR2I& aP, bool aAllowInternalShapePoints = true ) const;
708
717 const VECTOR2I NearestPoint( const SEG& aSeg, int& dist ) const;
718
720 const std::string Format( bool aCplusPlus = true ) const override;
721
723 bool Parse( std::stringstream& aStream ) override;
724
725 bool operator!=( const SHAPE_LINE_CHAIN& aRhs ) const
726 {
727 if( PointCount() != aRhs.PointCount() )
728 return true;
729
730 for( int i = 0; i < PointCount(); i++ )
731 {
732 if( CPoint( i ) != aRhs.CPoint( i ) )
733 return true;
734 }
735
736 return false;
737 }
738
739 bool CompareGeometry( const SHAPE_LINE_CHAIN& aOther ) const;
740
741 void Move( const VECTOR2I& aVector ) override
742 {
743 for( auto& pt : m_points )
744 pt += aVector;
745
746 for( auto& arc : m_arcs )
747 arc.Move( aVector );
748
749 m_bbox.Move( aVector );
750 }
751
759 void Mirror( bool aX = true, bool aY = false, const VECTOR2I& aRef = { 0, 0 } );
760
766 void Mirror( const SEG& axis );
767
774 void Rotate( const EDA_ANGLE& aAngle, const VECTOR2I& aCenter = { 0, 0 } ) override;
775
776 bool IsSolid() const override
777 {
778 return false;
779 }
780
781 const VECTOR2I PointAlong( int aPathLength ) const;
782
788 double Area( bool aAbsolute = true ) const;
789
799 void Split( const VECTOR2I& aStart, const VECTOR2I& aEnd, SHAPE_LINE_CHAIN& aPre,
800 SHAPE_LINE_CHAIN& aMid, SHAPE_LINE_CHAIN& aPost ) const;
801
812 bool OffsetLine( int aAmount, CORNER_STRATEGY aCornerStrategy, int aMaxError,
813 SHAPE_LINE_CHAIN& aLeft, SHAPE_LINE_CHAIN& aRight,
814 bool aSimplify = false ) const;
815
816 size_t ArcCount() const
817 {
818 return m_arcs.size();
819 }
820
824 ssize_t ArcIndex( size_t aSegment ) const
825 {
826 if( IsSharedPt( aSegment ) )
827 return m_shapes[aSegment].second;
828 else
829 return m_shapes[aSegment].first;
830 }
831
832 const SHAPE_ARC& Arc( size_t aArc ) const
833 {
834 return m_arcs[aArc];
835 }
836
842 bool IsSharedPt( size_t aIndex ) const
843 {
844 return aIndex < m_shapes.size()
845 && m_shapes[aIndex].first != SHAPE_IS_PT
846 && m_shapes[aIndex].second != SHAPE_IS_PT;
847 }
848
849
850 bool IsPtOnArc( size_t aPtIndex ) const
851 {
852 return aPtIndex < m_shapes.size() && m_shapes[aPtIndex] != SHAPES_ARE_PT;
853 }
854
855
856 bool IsArcSegment( size_t aSegment ) const
857 {
858 /*
859 * A segment is part of an arc except in the special case of two arcs next to each other
860 * but without a shared vertex. Here there is a segment between the end of the first arc
861 * and the start of the second arc.
862 */
863 size_t nextIdx = aSegment + 1;
864
865 if( nextIdx > m_shapes.size() - 1 )
866 {
867 if( nextIdx == m_shapes.size() && m_closed )
868 nextIdx = 0; // segment between end point and first point
869 else
870 return false;
871 }
872
873 return ( IsPtOnArc( aSegment )
874 && ( IsSharedPt( aSegment )
875 || m_shapes[aSegment].first == m_shapes[nextIdx].first ) );
876 }
877
878
879 bool IsArcStart( size_t aIndex ) const
880 {
881 if( aIndex == 0 )
882 return IsPtOnArc( aIndex );
883
884 return ( IsSharedPt( aIndex ) || ( IsPtOnArc( aIndex ) && !IsArcSegment( aIndex - 1 ) ) );
885 }
886
887
888 bool IsArcEnd( size_t aIndex ) const
889 {
890 return ( IsSharedPt( aIndex ) || ( IsPtOnArc( aIndex ) && !IsArcSegment( aIndex ) ) );
891 }
892
893 using SHAPE::Distance;
894
895 int Distance( const VECTOR2I& aP, bool aOutlineOnly ) const
896 {
897 return sqrt( SquaredDistance( aP, aOutlineOnly ) );
898 }
899
900 virtual const VECTOR2I GetPoint( int aIndex ) const override { return CPoint(aIndex); }
901 virtual const SEG GetSegment( int aIndex ) const override { return CSegment(aIndex); }
902 virtual size_t GetPointCount() const override { return PointCount(); }
903 virtual size_t GetSegmentCount() const override { return SegmentCount(); }
904
905 void TransformToPolygon( SHAPE_POLY_SET& aBuffer, int aError,
906 ERROR_LOC aErrorLoc ) const override;
907
908protected:
909 friend class SHAPE_POLY_SET;
910
916 void convertArc( ssize_t aArcIndex );
917
930 void splitArc( ssize_t aPtIndex, bool aCoincident = false );
931
932 void amendArc( size_t aArcIndex, const VECTOR2I& aNewStart, const VECTOR2I& aNewEnd );
933
934 void amendArcStart( size_t aArcIndex, const VECTOR2I& aNewStart )
935 {
936 amendArc( aArcIndex, aNewStart, m_arcs[aArcIndex].GetP1() );
937 }
938
939 void amendArcEnd( size_t aArcIndex, const VECTOR2I& aNewEnd )
940 {
941 amendArc( aArcIndex, m_arcs[aArcIndex].GetP0(), aNewEnd );
942 }
943
947 ssize_t reversedArcIndex( size_t aSegment ) const
948 {
949 if( IsSharedPt( aSegment ) )
950 return m_shapes[aSegment].first;
951 else
952 return m_shapes[aSegment].second;
953 }
954
958 ClipperLib::Path convertToClipper( bool aRequiredOrientation,
959 std::vector<CLIPPER_Z_VALUE>& aZValueBuffer,
960 std::vector<SHAPE_ARC>& aArcBuffer ) const;
961
965 Clipper2Lib::Path64 convertToClipper2( bool aRequiredOrientation,
966 std::vector<CLIPPER_Z_VALUE> &aZValueBuffer,
967 std::vector<SHAPE_ARC> &aArcBuffer ) const;
968
972 void fixIndicesRotation();
973
978
979private:
980
981 static const ssize_t SHAPE_IS_PT;
982
983 static const std::pair<ssize_t, ssize_t> SHAPES_ARE_PT;
984
986 std::vector<VECTOR2I> m_points;
987
1002 std::vector<std::pair<ssize_t, ssize_t>> m_shapes;
1003
1004 std::vector<SHAPE_ARC> m_arcs;
1005
1008
1015
1017 mutable BOX2I m_bbox;
1018};
1019
1020
1021#endif // __SHAPE_LINE_CHAIN
BOX2< VECTOR2I > BOX2I
Definition: box2.h:853
void Move(const Vec &aMoveVector)
Move the rectangle by the aMoveVector.
Definition: box2.h:112
BOX2< Vec > & Inflate(coord_type dx, coord_type dy)
Inflates the rectangle horizontally by dx and vertically by dy.
Definition: box2.h:507
void Compute(const Container &aPointList)
Compute the bounding box from a given list of points.
Definition: box2.h:83
BOX2< Vec > & Merge(const BOX2< Vec > &aRect)
Modify the position and size of the rectangle in order to contain aRect.
Definition: box2.h:589
Definition: seg.h:42
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:471
A dynamic state checking if a point lies within polygon with a dynamically built outline ( with each ...
bool processVertex(const VECTOR2I &ip, const VECTOR2I &ipNext)
void AddPolyline(const SHAPE_LINE_CHAIN &aPolyline)
SEG::ecoord SquaredDistance(const VECTOR2I &aP, bool aOutlineOnly=false) const override
Represent a polyline containing arcs as well as line segments: A chain of connected line and/or arc s...
std::vector< std::pair< ssize_t, ssize_t > > m_shapes
Array of indices that refer to the index of the shape if the point is part of a larger shape,...
const SHAPE_LINE_CHAIN Reverse() const
Reverse point order in the line chain.
void Move(const VECTOR2I &aVector) override
bool IsPtOnArc(size_t aPtIndex) const
void amendArcStart(size_t aArcIndex, const VECTOR2I &aNewStart)
void Remove(int aIndex)
Remove the aIndex-th point from the line chain.
void amendArcEnd(size_t aArcIndex, const VECTOR2I &aNewEnd)
int Width() const
Get the current width of the segments in the chain.
const SHAPE_ARC & Arc(size_t aArc) const
void splitArc(ssize_t aPtIndex, bool aCoincident=false)
Splits an arc into two arcs at aPtIndex.
void Append(const VECTOR2I &aP, bool aAllowDuplication=false)
Append a new point at the end of the line chain.
const std::optional< INTERSECTION > SelfIntersecting() const
Check if the line chain is self-intersecting.
bool Parse(std::stringstream &aStream) override
bool CheckClearance(const VECTOR2I &aP, const int aDist) const
Check if point aP is closer to (or on) an edge or vertex of the line chain.
std::vector< SHAPE_ARC > m_arcs
SHAPE_LINE_CHAIN & Simplify(bool aRemoveColinear=true)
Simplify the line chain by removing colinear adjacent segments and duplicate vertices.
int Distance(const VECTOR2I &aP, bool aOutlineOnly) const
bool IsClosed() const override
virtual const VECTOR2I GetPoint(int aIndex) const override
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.
void SetPoint(int aIndex, const VECTOR2I &aPos)
Move a point to a specific location.
const VECTOR2I PointAlong(int aPathLength) const
int PrevShape(int aPointIndex) const
int Split(const VECTOR2I &aP, bool aExact=false)
Insert the point aP belonging to one of the our segments, splitting the adjacent segment in two.
SHAPE_LINE_CHAIN & operator=(const SHAPE_LINE_CHAIN &)=default
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.
void fixIndicesRotation()
Fix indices of this chain to ensure arcs are not split between the end and start indices.
std::vector< VECTOR2I > m_points
array of vertices
void GenerateBBoxCache() const
int FindSegment(const VECTOR2I &aP, int aThreshold=1) const
Search for segment containing point aP.
int ShapeCount() const
Return the number of shapes (line segments or arcs) in this line chain.
void SetClosed(bool aClosed)
Mark the line chain as closed (i.e.
ssize_t reversedArcIndex(size_t aSegment) const
Return the arc index for the given segment index, looking backwards.
int Intersect(const SEG &aSeg, INTERSECTIONS &aIp) const
Find all intersection points between our line chain and the segment aSeg.
bool Intersects(const SHAPE_LINE_CHAIN &aChain) const
SHAPE_LINE_CHAIN()
Initialize an empty line chain.
int m_width
Width of the segments (for BBox calculations in RTree) TODO Adjust usage of SHAPE_LINE_CHAIN to accou...
virtual ~SHAPE_LINE_CHAIN()
int PointCount() const
Return the number of points (vertices) in this line chain.
bool IsArcEnd(size_t aIndex) const
void Replace(int aStartIndex, int aEndIndex, const VECTOR2I &aP)
Replace points with indices in range [start_index, end_index] with a single point aP.
void TransformToPolygon(SHAPE_POLY_SET &aBuffer, int aError, ERROR_LOC aErrorLoc) const override
Fills a SHAPE_POLY_SET with a polygon representation of this shape.
virtual bool Collide(const VECTOR2I &aP, int aClearance=0, int *aActual=nullptr, VECTOR2I *aLocation=nullptr) const override
Check if point aP lies closer to us than aClearance.
void ClearArcs()
Remove all arc references in the line chain, resulting in a chain formed only of straight segments.
void ReservePoints(size_t aSize)
Allocate a number of points all at once (for performance).
void mergeFirstLastPointIfNeeded()
Merge the first and last point if they are the same and this chain is closed.
bool CompareGeometry(const SHAPE_LINE_CHAIN &aOther) const
ssize_t ArcIndex(size_t aSegment) const
Return the arc index for the given segment index.
void Clear()
Remove all points from the line chain.
SHAPE_LINE_CHAIN(const SHAPE_ARC &aArc, bool aClosed=false)
BOX2I m_bbox
cached bounding box
BOX2I * GetCachedBBox() const override
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.
bool m_closed
is the line chain closed?
const std::vector< SHAPE_ARC > & CArcs() const
int NearestSegment(const VECTOR2I &aP) const
Find the segment nearest the given point.
double Area(bool aAbsolute=true) const
Return the area of this chain.
void Mirror(bool aX=true, bool aY=false, const VECTOR2I &aRef={ 0, 0 })
Mirror the line points about y or x (or both).
void amendArc(size_t aArcIndex, const VECTOR2I &aNewStart, const VECTOR2I &aNewEnd)
virtual size_t GetPointCount() const override
SHAPE_LINE_CHAIN(const std::vector< VECTOR2I > &aV, bool aClosed=false)
void Append(int aX, int aY, bool aAllowDuplication=false)
Append a new point at the end of the line chain.
void Rotate(const EDA_ANGLE &aAngle, const VECTOR2I &aCenter={ 0, 0 }) override
Rotate all vertices by a given angle.
virtual const SEG GetSegment(int aIndex) const override
const VECTOR2I & CPoint(int aIndex) const
Return a reference to a given point in the line chain.
bool operator!=(const SHAPE_LINE_CHAIN &aRhs) const
const std::vector< std::pair< ssize_t, ssize_t > > & CShapes() const
const VECTOR2I NearestPoint(const VECTOR2I &aP, bool aAllowInternalShapePoints=true) const
Find a point on the line chain that is closest to point aP.
std::vector< VECTOR2I >::iterator point_iter
int SegmentCount() const
Return the number of segments in this line chain.
int PathLength(const VECTOR2I &aP, int aIndex=-1) const
Compute the walk path length from the beginning of the line chain and the point aP belonging to our l...
const VECTOR2I & CLastPoint() const
Return the last point in the line chain.
const std::string Format(bool aCplusPlus=true) const override
SHAPE_LINE_CHAIN(const SHAPE_LINE_CHAIN &aShape)
Clipper2Lib::Path64 convertToClipper2(bool aRequiredOrientation, std::vector< CLIPPER_Z_VALUE > &aZValueBuffer, std::vector< SHAPE_ARC > &aArcBuffer) const
Create a new Clipper2 path from the SHAPE_LINE_CHAIN in a given orientation.
static const std::pair< ssize_t, ssize_t > SHAPES_ARE_PT
void convertArc(ssize_t aArcIndex)
Convert an arc to only a point chain by removing the arc and references.
virtual size_t GetSegmentCount() const override
void Remove(int aStartIndex, int aEndIndex)
Remove the range of points [start_index, end_index] from the line chain.
size_t ArcCount() const
const SEG CSegment(int aIndex) const
Return a constant copy of the aIndex segment in the line chain.
bool IsArcSegment(size_t aSegment) const
void RemoveShape(int aPointIndex)
Remove the shape at the given index from the line chain.
void Insert(size_t aVertex, const VECTOR2I &aP)
bool IsArcStart(size_t aIndex) const
void SetWidth(int aWidth)
Set the width of all segments in the chain.
bool IsSharedPt(size_t aIndex) const
Test if a point is shared between multiple shapes.
std::vector< INTERSECTION > INTERSECTIONS
long long int Length() const
Return length of the line chain in Euclidean metric.
int Find(const VECTOR2I &aP, int aThreshold=0) const
Search for point aP.
const std::vector< VECTOR2I > & CPoints() const
const BOX2I BBox(int aClearance=0) const override
Compute a bounding box of the shape, with a margin of aClearance a collision.
std::vector< VECTOR2I >::const_iterator point_citer
SHAPE * Clone() const override
Return a dynamically allocated copy of the shape.
bool IsSolid() const override
static const ssize_t SHAPE_IS_PT
SEG Segment(int aIndex)
Return a copy of the aIndex-th segment in the line chain.
bool OffsetLine(int aAmount, CORNER_STRATEGY aCornerStrategy, int aMaxError, SHAPE_LINE_CHAIN &aLeft, SHAPE_LINE_CHAIN &aRight, bool aSimplify=false) const
Creates line chains aLeft and aRight offset to this line chain.
Represent a set of closed polygons.
An abstract shape on 2D plane.
Definition: shape.h:126
virtual int Distance(const VECTOR2I &aP) const
Returns the minimum distance from a given point to this shape.
Definition: shape.cpp:85
CORNER_STRATEGY
define how inflate transform build inflated polygon
ERROR_LOC
When approximating an arc or circle, should the error be placed on the outside or inside of the curve...
@ SH_LINE_CHAIN
line chain (polyline)
Definition: shape.h:49
Holds information on each point of a SHAPE_LINE_CHAIN that is retrievable after an operation with Cli...
CLIPPER_Z_VALUE(const std::pair< ssize_t, ssize_t > aShapeIndices, ssize_t aOffset=0)
Represent an intersection between two line segments.
bool is_corner_their
When true, the corner [index_their] of the 'their' line lies exactly on 'our' line.
bool is_corner_our
When true, the corner [index_our] of the 'our' line lies exactly on 'their' line.
int index_our
Index of the intersecting corner/segment in the 'our' (== this) line.
VECTOR2I p
Point of intersection between our and their.
bool valid
Auxiliary flag to avoid copying intersection info to intersection refining code, used by the refining...
int index_their
index of the intersecting corner/segment in the 'their' (Intersect() method parameter) line.
compareOriginDistance(const VECTOR2I &aOrigin)
bool operator()(const INTERSECTION &aA, const INTERSECTION &aB)
double EuclideanNorm(const VECTOR2I &vector)
Definition: trigo.h:128
VECTOR2< int > VECTOR2I
Definition: vector2d.h:588