26#include <unordered_set>
45#include <nanoflann.hpp>
85 return ( aLeft - aRight ).SquaredEuclideanNorm() <=
SEG::Square( aLimit );
99 return ( aRef - aFirst ).SquaredEuclideanNorm() < ( aRef - aSecond ).SquaredEuclideanNorm();
105 bool padOutside =
false;
109 pad->Padstack().ForEachUniqueLayer(
122 padPos.
x, padPos.
y );
132 padPos.
x, padPos.
y );
149 endpoints.emplace_back( shape->GetStart(), shape );
150 endpoints.emplace_back( shape->GetEnd(), shape );
161 return static_cast<double>(
endpoints[idx].first.x );
163 return static_cast<double>(
endpoints[idx].first.y );
166 template <
class BBOX>
173using KDTree = nanoflann::KDTreeSingleIndexAdaptor<nanoflann::L2_Simple_Adaptor<double, PCB_SHAPE_ENDPOINTS_ADAPTOR>,
178 std::map<std::pair<VECTOR2I, VECTOR2I>,
PCB_SHAPE*>& aShapeOwners,
179 int aErrorMax,
bool aAllowUseArcsInPolygons )
196 aShapeOwners[ std::make_pair( prevPt, pt ) ] = aShape;
211 aContour.
Append( arc360, aErrorMax );
214 for(
int ii = 1; ii < aContour.
PointCount(); ++ii )
216 aShapeOwners[ std::make_pair( aContour.
CPoint( ii-1 ),
217 aContour.
CPoint( ii ) ) ] = aShape;
220 if( !aAllowUseArcsInPolygons )
234 for(
int ii = 1; ii < aContour.
PointCount(); ++ii )
236 aShapeOwners[ std::make_pair( aContour.
CPoint( ii - 1 ),
237 aContour.
CPoint( ii ) ) ] = aShape;
240 if( !aAllowUseArcsInPolygons )
258 aShapeOwners[ std::make_pair( prevPt, pt ) ] = aShape;
273 std::map<std::pair<VECTOR2I, VECTOR2I>,
PCB_SHAPE*>& aShapeOwners,
274 int aErrorMax,
int aChainingEpsilon,
bool aAllowUseArcsInPolygons )
283 nextPt = aShape->
GetEnd();
287 aContour.
Append( nextPt );
288 aShapeOwners[ std::make_pair( aPrevPt, nextPt ) ] = aShape;
298 if( !
close_enough( aPrevPt, pstart, aChainingEpsilon ) )
301 std::swap( pstart, pend );
307 arcChain.
Append( sarc, aErrorMax );
309 if( !aAllowUseArcsInPolygons )
312 for(
int ii = 1; ii < arcChain.
PointCount(); ++ii )
314 aShapeOwners[ std::make_pair( arcChain.
CPoint( ii - 1 ),
315 arcChain.
CPoint( ii ) ) ] = aShape;
318 aContour.
Append( arcChain );
325 bool reverse =
false;
329 nextPt = aShape->
GetEnd();
349 aShapeOwners[ std::make_pair( aPrevPt, pt ) ] = aShape;
361 aShapeOwners[ std::make_pair( aPrevPt, pt ) ] = aShape;
376 std::map<int, std::vector<int>> contourToParentIndexesMap;
378 for(
size_t ii = 0; ii < aContours.size(); ++ii )
380 VECTOR2I firstPt = aContours[ii].GetPoint( 0 );
381 std::vector<int> parents;
383 for(
size_t jj = 0; jj < aContours.size(); ++jj )
390 if( parentCandidate.
PointInside( firstPt, 0,
true ) )
391 parents.push_back( jj );
394 contourToParentIndexesMap[ii] = std::move( parents );
397 return contourToParentIndexesMap;
401 const std::map<
int, std::vector<int>>& aContourHierarchy,
404 const std::function<
PCB_SHAPE*(
const SEG&)>& aFetchOwner,
405 std::map<int, int>& aContourToOutlineIdxMap )
407 for(
const auto& [ contourIndex, parentIndexes ] : aContourHierarchy )
409 if( parentIndexes.size() % 2 == 0 )
412 if( !aAllowDisjoint && !aPolygons.
IsEmpty() )
417 BOARD_ITEM* b = aFetchOwner( aContours[ contourIndex ].GetSegment( 0 ) );
421 (*aErrorHandler)(
_(
"(multiple board outlines not supported)" ), a, b,
422 aContours[ contourIndex ].GetPoint( 0 ) );
428 aPolygons.
AddOutline( aContours[ contourIndex ] );
429 aContourToOutlineIdxMap[ contourIndex ] = aPolygons.
OutlineCount() - 1;
436 const std::map<
int, std::vector<int>>& aContourHierarchy,
437 const std::map<int, int>& aContourToOutlineIdxMap,
440 for(
const auto& [ contourIndex, parentIndexes ] : aContourHierarchy )
442 if( parentIndexes.size() % 2 == 1 )
447 for(
int parentContourIdx : parentIndexes )
449 if( aContourHierarchy.at( parentContourIdx ).size() == parentIndexes.size() - 1 )
451 int outlineIdx = aContourToOutlineIdxMap.at( parentContourIdx );
452 aPolygons.
AddHole( hole, outlineIdx );
462 const std::function<
PCB_SHAPE*(
const SEG&)>& aFetchOwner )
464 bool selfIntersecting =
false;
465 std::vector<SEG> segments;
473 for(
int jj = 0; jj < aPolygons.
HoleCount( ii ); ++jj )
480 segments.reserve( total );
487 std::swap( segment.
A, segment.
B );
489 segments.push_back( segment );
492 std::sort( segments.begin(), segments.end(),
493 [](
const SEG& a,
const SEG& b )
496 return LexicographicalCompare( a.A, b.A ) < 0;
497 return LexicographicalCompare( a.B, b.B ) < 0;
500 for(
size_t i = 0; i < segments.size(); ++i )
502 const SEG& seg1 = segments[i];
504 for(
size_t j = i + 1; j < segments.size(); ++j )
506 const SEG& seg2 = segments[j];
508 if( seg2.
A > seg1.
B )
511 if( seg1 == seg2 || ( seg1.
A == seg2.
B && seg1.
B == seg2.
A ) )
517 (*aErrorHandler)(
_(
"(self-intersecting)" ), a, b, seg1.
A );
519 selfIntersecting =
true;
527 (*aErrorHandler)(
_(
"(self-intersecting)" ), a, b, *pt );
529 selfIntersecting =
true;
534 return !selfIntersecting;
541 const double query_pt[2] = {
static_cast<double>( aPoint.
x ),
static_cast<double>( aPoint.
y ) };
545 kdTree.knnSearch( query_pt, 2, indices, distances );
547 if( distances[0] == std::numeric_limits<double>::max() )
552 double closest_dist_sq = aChainingEpsilon * aChainingEpsilon;
554 for(
size_t i = 0; i < 2; ++i )
556 if( distances[i] == std::numeric_limits<double>::max() )
561 if( candidate == aShape )
564 if( distances[i] < closest_dist_sq )
566 closest_dist_sq = distances[i];
567 closest_graphic = candidate;
571 return closest_graphic;
575 int aErrorMax,
int aChainingEpsilon,
bool aAllowDisjoint,
579 if( aShapeList.size() == 0 )
582 bool selfIntersecting =
false;
585 std::set<PCB_SHAPE*> startCandidates( aShapeList.begin(), aShapeList.end() );
589 KDTree kdTree( 2, adaptor );
592 std::map<std::pair<VECTOR2I, VECTOR2I>,
PCB_SHAPE*> shapeOwners;
597 auto it = shapeOwners.find( std::make_pair( seg.A, seg.B ) );
598 return it == shapeOwners.end() ? nullptr : it->second;
601 std::set<std::pair<PCB_SHAPE*, PCB_SHAPE*>> reportedGaps;
602 std::vector<SHAPE_LINE_CHAIN> contours;
603 contours.reserve( startCandidates.size() );
605 for(
PCB_SHAPE* shape : startCandidates )
609 while( startCandidates.size() )
611 graphic = *startCandidates.begin();
613 aCleaner.insert( graphic );
614 startCandidates.erase( startCandidates.begin() );
616 contours.emplace_back();
624 processClosedShape( graphic, currContour, shapeOwners, aErrorMax, aAllowUseArcsInPolygons );
629 std::deque<PCB_SHAPE*>
chain;
630 chain.push_back( graphic );
636 auto extendChain = [&](
bool forward )
639 VECTOR2I prev = forward ? backPt : frontPt;
648 aCleaner.insert(
next );
649 startCandidates.erase(
next );
657 prev =
next->GetEnd();
659 prev =
next->GetStart();
668 VECTOR2I chainPt = forward ? frontPt : backPt;
677 ( *aErrorHandler )(
_(
"(self-intersecting)" ), curr,
next, prev );
679 selfIntersecting =
true;
695 extendChain(
false );
701 if(
chain.size() > 1 )
707 startPt = first->
GetEnd();
716 currContour.
Append( startPt );
722 aErrorMax, aChainingEpsilon, aAllowUseArcsInPolygons );
739 arcChain.
Append( sarc, aErrorMax );
741 if( !aAllowUseArcsInPolygons )
744 for(
int ii = 1; ii < arcChain.
PointCount(); ++ii )
745 shapeOwners[std::make_pair( arcChain.
CPoint( ii - 1 ), arcChain.
CPoint( ii ) )] = owner;
748 currContour.
Append( arcChain );
754 shapeOwners[ std::make_pair( currContour.
CPoints()[currContour.
PointCount() - 2],
763 auto report_gap = [&](
const VECTOR2I& pt )
768 const double query_pt[2] = {
static_cast<double>( pt.x ),
static_cast<double>( pt.y ) };
773 kdTree.knnSearch( query_pt, 2, indices, dists );
779 auto key = std::minmax( shapeA, shapeB );
781 if( !reportedGaps.insert( key ).second )
790 if( effectiveShapeA && effectiveShapeB
791 && effectiveShapeA->NearestPoints( effectiveShapeB.get(), ptA, ptB ) )
793 midpoint = ( ptA + ptB ) / 2;
796 ( *aErrorHandler )(
_(
"(not a closed shape)" ), shapeA, shapeB, midpoint );
799 report_gap( currContour.
CPoint( 0 ) );
808 if( !contour.IsClosed() )
813 for(
size_t ii = 0; ii < contours.size(); ++ii )
825 std::map<int, int> contourToOutlineIdxMap;
827 aErrorHandler, fetchOwner, contourToOutlineIdxMap ) )
833 addHolesToPolygon( contours, contourHierarchy, contourToOutlineIdxMap, aPolygons );
841 int aErrorMax,
int aChainingEpsilon,
bool aAllowDisjoint,
847 aAllowDisjoint, aErrorHandler, aAllowUseArcsInPolygons,
857 int min_dist = std::max( 0, aMinDist );
862 std::vector<PCB_SHAPE*> shapeList;
864 for(
int ii = 0; ii < items.
GetCount(); ii++ )
869 shapeList.push_back( seg );
875 switch( shape->GetShape() )
879 VECTOR2I seg = shape->GetEnd() - shape->GetStart();
882 if( dim <= min_dist )
888 (*aErrorHandler)( wxString::Format(
_(
"(rectangle has null or very small "
889 "size: %d nm)" ), dim ),
890 shape,
nullptr, shape->GetStart() );
898 int r = shape->GetRadius();
906 (*aErrorHandler)( wxString::Format(
_(
"(circle has null or very small "
907 "radius: %d nm)" ), r ),
908 shape,
nullptr, shape->GetStart() );
916 VECTOR2I seg = shape->GetEnd() - shape->GetStart();
919 if( dim <= min_dist )
925 (*aErrorHandler)( wxString::Format(
_(
"(segment has null or very small "
926 "length: %d nm)" ), dim ),
927 shape,
nullptr, shape->GetStart() );
937 VECTOR2I arcMiddle = shape->GetArcMid();
938 VECTOR2I seg1 = arcMiddle - shape->GetStart();
939 VECTOR2I seg2 = shape->GetEnd() - arcMiddle;
942 if( dim <= min_dist )
948 (*aErrorHandler)( wxString::Format(
_(
"(arc has null or very small size: "
950 shape,
nullptr, shape->GetStart() );
974 bool aAllowUseArcsInPolygons )
978 bool success =
false;
985 for(
int ii = 0; ii < items.
GetCount(); ++ii )
993 std::vector<PCB_SHAPE*> fpSegList;
995 for(
int ii = 0; ii < fpItems.
GetCount(); ii++ )
1000 fpSegList.push_back( fpSeg );
1003 if( !fpSegList.empty() )
1010 nullptr, aAllowUseArcsInPolygons, cleaner );
1019 fpHoles.
Append( fpOutlines );
1025 for(
int ii = 0; ii < fpItems.
GetCount(); ++ii )
1032 std::vector<PCB_SHAPE*> segList;
1034 for(
int ii = 0; ii < items.
GetCount(); ii++ )
1043 segList.push_back( seg );
1046 if( segList.size() )
1049 aErrorHandler, aAllowUseArcsInPolygons, cleaner );
1075 aOutlines.
Append( corner );
1081 aOutlines.
Append( corner );
1134 chain.SetClosed(
true );
1142 int aOutlineNum = 0 )
1144 int minDistance = -1;
1149 auto seg = it.Get();
1150 int dis = seg.Distance( aEndPoint );
1152 if( minDistance < 0 || ( dis < minDistance ) )
1155 projPoint = seg.NearestPoint( aEndPoint );
1171 bool foundA =
false;
1172 bool foundB =
false;
1190 if( foundA && foundB )
1193 if( foundSegs == 0 )
1197 seg.
A.
x, seg.
A.
y, seg.
B.
x, seg.
B.
y );
1205 seg.
A.
x, seg.
A.
y, seg.
B.
x, seg.
B.
y );
1231 bool success =
false;
1239 std::vector<PCB_SHAPE*> segList;
1241 for(
int ii = 0; ii < items.
GetCount(); ii++ )
1243 if( items[ii]->GetLayer() ==
Edge_Cuts )
1244 segList.push_back(
static_cast<PCB_SHAPE*
>( items[ii] ) );
1247 if( !segList.empty() )
1250 aErrorHandler,
false, cleaner );
1274 for(
int j = 0; j < outlines.
HoleCount( i ); j++ )
1279 aOutlines.
AddHole( hole, -1 );
1287 aOutlines = std::move( outlines );
1305 std::vector<SHAPE_LINE_CHAIN> closedChains;
1306 std::vector<SHAPE_LINE_CHAIN> openChains;
1310 openChains.push_back( outlines.
Outline( 0 ) );
1312 for(
int j = 0; j < outlines.
HoleCount( 0 ); j++ )
1319 closedChains.push_back( hole );
1324 openChains.push_back( hole );
1336 chain.SetClosed(
false );
1347 if(
chain.SegmentCount() == 0 )
1351 aOutlines = std::move( bbox );
1354 else if(
chain.SegmentCount() == 1 )
1358 wxLogTrace(
traceBoardOutline, wxT(
"Only 1 line segment in provided outline" ) );
1360 startSeg =
chain.Segment( 0 );
1368 if( inter0 && inter2 && !inter1 && !inter3 )
1371 wxLogTrace(
traceBoardOutline, wxT(
"Segment intersects only vertical bbox sides" ) );
1387 else if( inter1 && inter3 && !inter0 && !inter2 )
1390 wxLogTrace(
traceBoardOutline, wxT(
"Segment intersects only horizontal bbox sides" ) );
1409 wxLogTrace(
traceBoardOutline, wxT(
"Segment intersects two perpendicular bbox sides" ) );
1437 else if( hit1 && hit2 )
1456 else if( hit2 && hit3 )
1502 aOutlines = std::move( bbox );
1519 aOutlines = std::move( poly2 );
1524 aOutlines = std::move( poly1 );
1531 aOutlines.
AddHole( closedChain, -1 );
constexpr EDA_IU_SCALE pcbIUScale
A base class for any item which can be embedded within the BOARD container class, and therefore insta...
Information pertinent to a Pcbnew printed circuit board.
const BOX2I GetBoardEdgesBoundingBox() const
Return the board bounding box calculated using exclusively the board edges (graphics on Edge....
const BOX2I GetBoundingBox() const override
Return the orthogonal bounding box of this object for display purposes.
FOOTPRINT * GetFirstFootprint() const
Get the first footprint on the board or nullptr.
BOX2I ComputeBoundingBox(bool aBoardEdgesOnly=false) const
Calculate the bounding box containing all board items (or board edge segments).
const FOOTPRINTS & Footprints() const
constexpr BOX2< Vec > & Inflate(coord_type dx, coord_type dy)
Inflates the rectangle horizontally by dx and vertically by dy.
constexpr const Vec GetEnd() const
constexpr size_type GetWidth() const
constexpr size_type GetHeight() const
constexpr const Vec & GetOrigin() const
constexpr bool IsValid() const
int GetCount() const
Return the number of objects in the list.
A base class for most all the KiCad significant classes used in schematics and boards.
void SetFlags(EDA_ITEM_FLAGS aMask)
void ClearFlags(EDA_ITEM_FLAGS aMask=EDA_ITEM_ALL_FLAGS)
EDA_ITEM_FLAGS GetFlags() const
int GetRectangleWidth() const
SHAPE_POLY_SET & GetPolyShape()
void RebuildBezierToSegmentsPointsList(int aMaxError)
Rebuild the m_bezierPoints vertex list that approximate the Bezier curve by a list of segments.
const VECTOR2I & GetEnd() const
Return the ending point of the graphic.
const VECTOR2I & GetStart() const
Return the starting point of the graphic.
std::vector< VECTOR2I > GetRectCorners() const
const std::vector< VECTOR2I > & GetBezierPoints() const
int GetRectangleHeight() const
int GetCornerRadius() const
VECTOR2I GetArcMid() const
VECTOR2I GetCenter() const override
This defaults to the center of the bounding box if not overridden.
int GetWidth() const override
std::shared_ptr< SHAPE > GetEffectiveShape(PCB_LAYER_ID aLayer=UNDEFINED_LAYER, FLASHING aFlash=FLASHING::DEFAULT) const override
Make a set of SHAPE objects representing the PCB_SHAPE.
PCB_LAYER_ID GetLayer() const override
Return the primary layer this item is on.
Collect all BOARD_ITEM objects of a given set of KICAD_T type(s).
void Collect(BOARD_ITEM *aBoard, const std::vector< KICAD_T > &aTypes)
Collect BOARD_ITEM objects using this class's Inspector method, which does the collection.
A round rectangle shape, based on a rectangle and a radius.
void TransformToPolygon(SHAPE_POLY_SET &aBuffer) const
Get the polygonal representation of the roundrect.
EDA_ITEM_FLAGS m_flagsToClear
SCOPED_FLAGS_CLEANER(const EDA_ITEM_FLAGS &aFlagsToClear)
OPT_VECTOR2I Intersect(const SEG &aSeg, bool aIgnoreEndpoints=false, bool aLines=false) const
Compute intersection point of segment (this) with segment aSeg.
static SEG::ecoord Square(int a)
OPT_VECTOR2I IntersectLines(const SEG &aSeg) const
Compute the intersection point of lines passing through ends of (this) and aSeg.
bool Contains(const SEG &aSeg) const
const VECTOR2I & GetArcMid() const
const VECTOR2I & GetP0() const
bool PointInside(const VECTOR2I &aPt, int aAccuracy=0, bool aUseBBoxCache=false) const override
Check if point aP lies inside a closed shape.
Represent a polyline containing arcs as well as line segments: A chain of connected line and/or arc s...
const SHAPE_ARC & Arc(size_t aArc) const
bool IsClosed() const override
virtual const VECTOR2I GetPoint(int aIndex) const override
void SetPoint(int aIndex, const VECTOR2I &aPos)
Move a point to a specific location.
void GenerateBBoxCache() const
void SetClosed(bool aClosed)
Mark the line chain as closed (i.e.
int PointCount() const
Return the number of points (vertices) in this line chain.
bool IsArcEnd(size_t aIndex) const
void ClearArcs()
Remove all arc references in the line chain, resulting in a chain formed only of straight segments.
ssize_t ArcIndex(size_t aSegment) const
Return the arc index for the given segment index.
void SetWidth(int aWidth) override
Set the width of all segments in the chain.
SEG Segment(int aIndex) const
Return a copy of the aIndex-th segment in the line chain.
BOX2I * GetCachedBBox() const override
void Append(int aX, int aY, bool aAllowDuplication=false)
Append a new point at the end of the line chain.
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.
int SegmentCount() const
Return the number of segments in this line chain.
const VECTOR2I & CLastPoint() const
Return the last point in the line chain.
const SEG CSegment(int aIndex) const
Return a constant copy of the aIndex segment in the line chain.
void RemoveShape(int aPointIndex)
Remove the shape at the given index from the line chain.
const std::vector< VECTOR2I > & CPoints() const
Represent a set of closed polygons.
void RemoveAllContours()
Remove all outlines & holes (clears) the polygon set.
void ClearArcs()
Removes all arc references from all the outlines and holes in the polyset.
int AddOutline(const SHAPE_LINE_CHAIN &aOutline)
Adds a new outline to the set and returns its index.
bool IsEmpty() const
Return true if the set is empty (no polygons at all)
CONST_ITERATOR CIterate(int aFirst, int aLast, bool aIterateHoles=false) const
int HoleCount(int aOutline) const
Returns the number of holes in a given outline.
int Append(int x, int y, int aOutline=-1, int aHole=-1, bool aAllowDuplication=false)
Appends a vertex at the end of the given outline/hole (default: the last outline)
int AddHole(const SHAPE_LINE_CHAIN &aHole, int aOutline=-1)
Adds a new hole to the given outline (default: last) and returns its index.
SHAPE_LINE_CHAIN & Outline(int aIndex)
Return the reference to aIndex-th outline in the set.
SHAPE_LINE_CHAIN & Hole(int aOutline, int aHole)
Return the reference to aHole-th hole in the aIndex-th outline.
int NewOutline()
Creates a new empty polygon in the set and returns its index.
void BooleanIntersection(const SHAPE_POLY_SET &b)
Perform boolean polyset intersection.
CONST_SEGMENT_ITERATOR CIterateSegments(int aFirst, int aLast, bool aIterateHoles=false) const
Return an iterator object, for iterating between aFirst and aLast outline, with or without holes (def...
int OutlineCount() const
Return the number of outlines in the set.
SHAPE_POLY_SET CloneDropTriangulation() const
SEGMENT_ITERATOR IterateSegmentsWithHoles()
Returns an iterator object, for all outlines in the set (with holes)
T EuclideanNorm() const
Compute the Euclidean norm of the vector, which is defined as sqrt(x ** 2 + y ** 2).
VECTOR2I projectPointOnSegment(const VECTOR2I &aEndPoint, const SHAPE_POLY_SET &aOutline, int aOutlineNum=0)
static bool isCopperOutside(const FOOTPRINT *aFootprint, SHAPE_POLY_SET &aShape)
static void processClosedShape(PCB_SHAPE *aShape, SHAPE_LINE_CHAIN &aContour, std::map< std::pair< VECTOR2I, VECTOR2I >, PCB_SHAPE * > &aShapeOwners, int aErrorMax, bool aAllowUseArcsInPolygons)
nanoflann::KDTreeSingleIndexAdaptor< nanoflann::L2_Simple_Adaptor< double, PCB_SHAPE_ENDPOINTS_ADAPTOR >, PCB_SHAPE_ENDPOINTS_ADAPTOR, 2 > KDTree
bool ConvertOutlineToPolygon(std::vector< PCB_SHAPE * > &aShapeList, SHAPE_POLY_SET &aPolygons, int aErrorMax, int aChainingEpsilon, bool aAllowDisjoint, OUTLINE_ERROR_HANDLER *aErrorHandler, bool aAllowUseArcsInPolygons)
Build a polygon set with holes from a PCB_SHAPE list.
bool TestBoardOutlinesGraphicItems(BOARD *aBoard, int aMinDist, OUTLINE_ERROR_HANDLER *aErrorHandler)
Test a board graphic items on edge cut layer for validity.
void buildBoardBoundingBoxPoly(const BOARD *aBoard, SHAPE_POLY_SET &aOutline)
Get the complete bounding box of the board (including all items).
int findEndSegments(SHAPE_LINE_CHAIN &aChain, SEG &aStartSeg, SEG &aEndSeg)
bool BuildBoardPolygonOutlines(BOARD *aBoard, SHAPE_POLY_SET &aOutlines, int aErrorMax, int aChainingEpsilon, OUTLINE_ERROR_HANDLER *aErrorHandler, bool aAllowUseArcsInPolygons)
Extract the board outlines and build a closed polygon from lines, arcs and circle items on edge cut l...
static bool close_enough(VECTOR2I aLeft, VECTOR2I aRight, unsigned aLimit)
Local and tunable method of qualifying the proximity of two points.
static PCB_SHAPE * findNext(PCB_SHAPE *aShape, const VECTOR2I &aPoint, const KDTree &kdTree, const PCB_SHAPE_ENDPOINTS_ADAPTOR &adaptor, double aChainingEpsilon)
static bool checkSelfIntersections(SHAPE_POLY_SET &aPolygons, OUTLINE_ERROR_HANDLER *aErrorHandler, const std::function< PCB_SHAPE *(const SEG &)> &aFetchOwner)
static std::map< int, std::vector< int > > buildContourHierarchy(const std::vector< SHAPE_LINE_CHAIN > &aContours)
static void addHolesToPolygon(const std::vector< SHAPE_LINE_CHAIN > &aContours, const std::map< int, std::vector< int > > &aContourHierarchy, const std::map< int, int > &aContourToOutlineIdxMap, SHAPE_POLY_SET &aPolygons)
static bool closer_to_first(VECTOR2I aRef, VECTOR2I aFirst, VECTOR2I aSecond)
Local method which qualifies whether the start or end point of a segment is closest to a point.
bool BuildFootprintPolygonOutlines(BOARD *aBoard, SHAPE_POLY_SET &aOutlines, int aErrorMax, int aChainingEpsilon, OUTLINE_ERROR_HANDLER *aErrorHandler)
Extract a board outline for a footprint view.
static void processShapeSegment(PCB_SHAPE *aShape, SHAPE_LINE_CHAIN &aContour, VECTOR2I &aPrevPt, std::map< std::pair< VECTOR2I, VECTOR2I >, PCB_SHAPE * > &aShapeOwners, int aErrorMax, int aChainingEpsilon, bool aAllowUseArcsInPolygons)
static bool addOutlinesToPolygon(const std::vector< SHAPE_LINE_CHAIN > &aContours, const std::map< int, std::vector< int > > &aContourHierarchy, SHAPE_POLY_SET &aPolygons, bool aAllowDisjoint, OUTLINE_ERROR_HANDLER *aErrorHandler, const std::function< PCB_SHAPE *(const SEG &)> &aFetchOwner, std::map< int, int > &aContourToOutlineIdxMap)
bool doConvertOutlineToPolygon(std::vector< PCB_SHAPE * > &aShapeList, SHAPE_POLY_SET &aPolygons, int aErrorMax, int aChainingEpsilon, bool aAllowDisjoint, OUTLINE_ERROR_HANDLER *aErrorHandler, bool aAllowUseArcsInPolygons, SCOPED_FLAGS_CLEANER &aCleaner)
const std::function< void(const wxString &msg, BOARD_ITEM *itemA, BOARD_ITEM *itemB, const VECTOR2I &pt)> OUTLINE_ERROR_HANDLER
static constexpr EDA_ANGLE ANGLE_360
#define SKIP_STRUCT
flag indicating that the structure should be ignored
std::uint32_t EDA_ITEM_FLAGS
@ RECTANGLE
Use RECTANGLE instead of RECT to avoid collision in a Windows header.
a few functions useful in geometry calculations.
const wxChar * traceBoardOutline
Flag to enable debug tracing for the board outline creation.
PCB_LAYER_ID
A quick note on layer IDs:
This file contains miscellaneous commonly used macros and functions.
#define UNIMPLEMENTED_FOR(type)
std::optional< VECTOR2I > OPT_VECTOR2I
std::vector< std::pair< VECTOR2I, PCB_SHAPE * > > endpoints
bool kdtree_get_bbox(BBOX &) const
PCB_SHAPE_ENDPOINTS_ADAPTOR(const std::vector< PCB_SHAPE * > &shapes)
size_t kdtree_get_point_count() const
double kdtree_get_pt(const size_t idx, const size_t dim) const
const SHAPE_LINE_CHAIN chain
@ PCB_SHAPE_T
class PCB_SHAPE, a segment not on copper layers
VECTOR2< int32_t > VECTOR2I
constexpr int LexicographicalCompare(const VECTOR2< T > &aA, const VECTOR2< T > &aB)