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;
212 aContour.
Append( arc360, aErrorMax );
215 for(
int ii = 1; ii < aContour.
PointCount(); ++ii )
216 aShapeOwners[ std::make_pair( aContour.
CPoint( ii-1 ), aContour.
CPoint( ii ) ) ] = aShape;
218 if( !aAllowUseArcsInPolygons )
233 for(
int ii = 1; ii < aContour.
PointCount(); ++ii )
234 aShapeOwners[ std::make_pair( aContour.
CPoint( ii - 1 ), aContour.
CPoint( ii ) ) ] = aShape;
236 if( !aAllowUseArcsInPolygons )
254 aShapeOwners[ std::make_pair( prevPt, pt ) ] = aShape;
269 std::map<std::pair<VECTOR2I, VECTOR2I>,
PCB_SHAPE*>& aShapeOwners,
270 int aErrorMax,
int aChainingEpsilon,
bool aAllowUseArcsInPolygons )
279 nextPt = aShape->
GetEnd();
283 aContour.
Append( nextPt );
284 aShapeOwners[ std::make_pair( aPrevPt, nextPt ) ] = aShape;
294 if( !
close_enough( aPrevPt, pstart, aChainingEpsilon ) )
299 std::swap( pstart, pend );
305 arcChain.
Append( sarc, aErrorMax );
307 if( !aAllowUseArcsInPolygons )
310 for(
int ii = 1; ii < arcChain.
PointCount(); ++ii )
312 aShapeOwners[ std::make_pair( arcChain.
CPoint( ii - 1 ),
313 arcChain.
CPoint( ii ) ) ] = aShape;
316 aContour.
Append( arcChain );
323 bool reverse =
false;
327 nextPt = aShape->
GetEnd();
347 aShapeOwners[ std::make_pair( aPrevPt, pt ) ] = aShape;
359 aShapeOwners[ std::make_pair( aPrevPt, pt ) ] = aShape;
374 std::map<int, std::vector<int>> contourToParentIndexesMap;
376 for(
size_t ii = 0; ii < aContours.size(); ++ii )
378 if( aContours[ii].PointCount() < 1 )
381 VECTOR2I firstPt = aContours[ii].GetPoint( 0 );
382 std::vector<int> parents;
384 for(
size_t jj = 0; jj < aContours.size(); ++jj )
391 if( parentCandidate.
PointInside( firstPt, 0,
true ) )
392 parents.push_back( jj );
395 contourToParentIndexesMap[ii] = std::move( parents );
398 return contourToParentIndexesMap;
402 const std::map<
int, std::vector<int>>& aContourHierarchy,
405 const std::function<
PCB_SHAPE*(
const SEG&)>& aFetchOwner,
406 std::map<int, int>& aContourToOutlineIdxMap )
408 for(
const auto& [ contourIndex, parentIndexes ] : aContourHierarchy )
410 if( parentIndexes.size() % 2 == 0 )
413 if( !aAllowDisjoint && !aPolygons.
IsEmpty() )
418 BOARD_ITEM* b = aFetchOwner( aContours[ contourIndex ].GetSegment( 0 ) );
422 (*aErrorHandler)(
_(
"(multiple board outlines not supported)" ), a, b,
423 aContours[ contourIndex ].GetPoint( 0 ) );
429 aPolygons.
AddOutline( aContours[ contourIndex ] );
430 aContourToOutlineIdxMap[ contourIndex ] = aPolygons.
OutlineCount() - 1;
437 const std::map<
int, std::vector<int>>& aContourHierarchy,
438 const std::map<int, int>& aContourToOutlineIdxMap,
SHAPE_POLY_SET& aPolygons,
439 bool aAllowUseArcsInPolygons,
bool aHasMalformedOverlap )
441 if( aAllowUseArcsInPolygons || !aHasMalformedOverlap )
443 for(
const auto& [contourIndex, parentIndexes] : aContourHierarchy )
445 if( parentIndexes.size() % 2 == 1 )
450 for(
int parentContourIdx : parentIndexes )
452 if( aContourHierarchy.at( parentContourIdx ).size() == parentIndexes.size() - 1 )
454 int outlineIdx = aContourToOutlineIdxMap.at( parentContourIdx );
455 aPolygons.
AddHole( hole, outlineIdx );
469 for(
const auto& [contourIndex, parentIndexes] : aContourHierarchy )
471 if( parentIndexes.empty() )
474 if( parentIndexes.size() % 2 == 1 )
475 cutoutCandidates.
AddOutline( aContours[contourIndex] );
477 islandCandidates.
AddOutline( aContours[contourIndex] );
495 const std::function<
PCB_SHAPE*(
const SEG&)>& aFetchOwner )
497 bool selfIntersecting =
false;
498 std::vector<SEG> segments;
506 for(
int jj = 0; jj < aPolygons.
HoleCount( ii ); ++jj )
513 segments.reserve( total );
520 std::swap( segment.
A, segment.
B );
522 segments.push_back( segment );
525 std::sort( segments.begin(), segments.end(),
526 [](
const SEG& a,
const SEG& b )
529 return LexicographicalCompare( a.A, b.A ) < 0;
530 return LexicographicalCompare( a.B, b.B ) < 0;
533 for(
size_t i = 0; i < segments.size(); ++i )
535 const SEG& seg1 = segments[i];
537 for(
size_t j = i + 1; j < segments.size(); ++j )
539 const SEG& seg2 = segments[j];
541 if( seg2.
A > seg1.
B )
544 if( seg1 == seg2 || ( seg1.
A == seg2.
B && seg1.
B == seg2.
A ) )
550 (*aErrorHandler)(
_(
"(self-intersecting)" ), a, b, seg1.
A );
552 selfIntersecting =
true;
560 (*aErrorHandler)(
_(
"(self-intersecting)" ), a, b, *pt );
562 selfIntersecting =
true;
567 return !selfIntersecting;
574 const double query_pt[2] = {
static_cast<double>( aPoint.
x ),
static_cast<double>( aPoint.
y ) };
578 kdTree.knnSearch( query_pt, 2, indices, distances );
580 if( distances[0] == std::numeric_limits<double>::max() )
585 double closest_dist_sq = aChainingEpsilon * aChainingEpsilon;
587 for(
size_t i = 0; i < 2; ++i )
589 if( distances[i] == std::numeric_limits<double>::max() )
594 if( candidate == aShape )
597 if( distances[i] < closest_dist_sq )
599 closest_dist_sq = distances[i];
600 closest_graphic = candidate;
604 return closest_graphic;
610 for(
size_t ii = 0; ii < aContours.size(); ++ii )
612 for(
size_t jj = ii + 1; jj < aContours.size(); ++jj )
616 if( aContours[ii].Intersect( aContours[jj], intersections,
true ) != 0 )
626 int aErrorMax,
int aChainingEpsilon,
bool aAllowDisjoint,
630 if( aShapeList.size() == 0 )
633 bool selfIntersecting =
false;
636 std::set<PCB_SHAPE*> startCandidates( aShapeList.begin(), aShapeList.end() );
640 KDTree kdTree( 2, adaptor );
643 std::map<std::pair<VECTOR2I, VECTOR2I>,
PCB_SHAPE*> shapeOwners;
648 auto it = shapeOwners.find( std::make_pair( seg.A, seg.B ) );
649 return it == shapeOwners.end() ? nullptr : it->second;
652 std::set<std::pair<PCB_SHAPE*, PCB_SHAPE*>> reportedGaps;
653 std::vector<SHAPE_LINE_CHAIN> contours;
654 contours.reserve( startCandidates.size() );
656 for(
PCB_SHAPE* shape : startCandidates )
660 while( startCandidates.size() )
662 graphic = *startCandidates.begin();
664 aCleaner.insert( graphic );
665 startCandidates.erase( startCandidates.begin() );
667 contours.emplace_back();
675 processClosedShape( graphic, currContour, shapeOwners, aErrorMax, aAllowUseArcsInPolygons );
680 std::deque<PCB_SHAPE*>
chain;
681 chain.push_back( graphic );
687 auto extendChain = [&](
bool forward )
690 VECTOR2I prev = forward ? backPt : frontPt;
699 aCleaner.insert(
next );
700 startCandidates.erase(
next );
708 prev =
next->GetEnd();
710 prev =
next->GetStart();
719 VECTOR2I chainPt = forward ? frontPt : backPt;
728 ( *aErrorHandler )(
_(
"(self-intersecting)" ), curr,
next, prev );
730 selfIntersecting =
true;
746 extendChain(
false );
752 if(
chain.size() > 1 )
758 startPt = first->
GetEnd();
767 currContour.
Append( startPt );
773 aErrorMax, aChainingEpsilon, aAllowUseArcsInPolygons );
790 arcChain.
Append( sarc, aErrorMax );
792 if( !aAllowUseArcsInPolygons )
795 for(
int ii = 1; ii < arcChain.
PointCount(); ++ii )
796 shapeOwners[std::make_pair( arcChain.
CPoint( ii - 1 ), arcChain.
CPoint( ii ) )] = owner;
799 currContour.
Append( arcChain );
805 shapeOwners[ std::make_pair( currContour.
CPoints()[currContour.
PointCount() - 2],
814 auto report_gap = [&](
const VECTOR2I& pt )
819 const double query_pt[2] = {
static_cast<double>( pt.x ),
static_cast<double>( pt.y ) };
820 uint32_t indices[2] = { 0, 0 };
824 kdTree.knnSearch( query_pt, 2, indices, dists );
830 auto key = std::minmax( shapeA, shapeB );
832 if( !reportedGaps.insert( key ).second )
841 if( effectiveShapeA && effectiveShapeB
842 && effectiveShapeA->NearestPoints( effectiveShapeB.get(), ptA, ptB ) )
844 midpoint = ( ptA + ptB ) / 2;
847 ( *aErrorHandler )(
_(
"(not a closed shape)" ), shapeA, shapeB, midpoint );
850 report_gap( currContour.
CPoint( 0 ) );
859 if( !contour.IsClosed() )
864 for(
size_t ii = 0; ii < contours.size(); ++ii )
878 std::map<int, int> contourToOutlineIdxMap;
879 if( !
addOutlinesToPolygon( contours, contourHierarchy, aPolygons, aAllowDisjoint, aErrorHandler, fetchOwner,
880 contourToOutlineIdxMap ) )
886 addHolesToPolygon( contours, contourHierarchy, contourToOutlineIdxMap, aPolygons, aAllowUseArcsInPolygons,
887 hasMalformedOverlap );
895 int aErrorMax,
int aChainingEpsilon,
bool aAllowDisjoint,
901 aAllowDisjoint, aErrorHandler, aAllowUseArcsInPolygons,
911 int min_dist = std::max( 0, aMinDist );
916 std::vector<PCB_SHAPE*> shapeList;
918 for(
int ii = 0; ii < items.
GetCount(); ii++ )
923 shapeList.push_back( seg );
929 switch( shape->GetShape() )
933 VECTOR2I seg = shape->GetEnd() - shape->GetStart();
936 if( dim <= min_dist )
942 (*aErrorHandler)( wxString::Format(
_(
"(rectangle has null or very small "
943 "size: %d nm)" ), dim ),
944 shape,
nullptr, shape->GetStart() );
952 int r = shape->GetRadius();
960 (*aErrorHandler)( wxString::Format(
_(
"(circle has null or very small "
961 "radius: %d nm)" ), r ),
962 shape,
nullptr, shape->GetStart() );
970 VECTOR2I seg = shape->GetEnd() - shape->GetStart();
973 if( dim <= min_dist )
979 (*aErrorHandler)( wxString::Format(
_(
"(segment has null or very small "
980 "length: %d nm)" ), dim ),
981 shape,
nullptr, shape->GetStart() );
991 VECTOR2I arcMiddle = shape->GetArcMid();
992 VECTOR2I seg1 = arcMiddle - shape->GetStart();
993 VECTOR2I seg2 = shape->GetEnd() - arcMiddle;
996 if( dim <= min_dist )
1002 (*aErrorHandler)( wxString::Format(
_(
"(arc has null or very small size: "
1004 shape,
nullptr, shape->GetStart() );
1022 std::vector<std::pair<PCB_SHAPE*, SHAPE_LINE_CHAIN>> closedContours;
1023 closedContours.reserve( shapeList.size() );
1034 std::map<std::pair<VECTOR2I, VECTOR2I>,
PCB_SHAPE*> shapeOwners;
1037 closedContours.emplace_back( shape, std::move( contour ) );
1040 for(
size_t ii = 0; ii < closedContours.size(); ++ii )
1044 for(
size_t jj = ii + 1; jj < closedContours.size(); ++jj )
1050 if( contourA.
Intersect( contourB, intersections,
true ) == 0 )
1057 PCB_SHAPE* shapeA = closedContours[ii].first;
1058 PCB_SHAPE* shapeB = closedContours[jj].first;
1060 VECTOR2I midpoint = intersections.front().p;
1064 if( effectiveShapeA && effectiveShapeB )
1066 BOX2I bboxA = effectiveShapeA->BBox();
1067 BOX2I bboxB = effectiveShapeB->BBox();
1071 midpoint = overlapBox.
Centre();
1074 ( *aErrorHandler )(
_(
"(self-intersecting)" ), shapeA, shapeB, midpoint );
1084 int aChainingEpsilon,
bool aInferOutlineIfNecessary,
1089 bool success =
false;
1096 for(
int ii = 0; ii < items.
GetCount(); ++ii )
1104 std::vector<PCB_SHAPE*> fpSegList;
1106 for(
int ii = 0; ii < fpItems.
GetCount(); ii++ )
1111 fpSegList.push_back( fpSeg );
1114 if( !fpSegList.empty() )
1121 aAllowUseArcsInPolygons,
1131 fpHoles.
Append( fpOutlines );
1137 for(
int ii = 0; ii < fpItems.
GetCount(); ++ii )
1144 std::vector<PCB_SHAPE*> segList;
1146 for(
int ii = 0; ii < items.
GetCount(); ii++ )
1155 segList.push_back( seg );
1158 if( segList.size() )
1161 aErrorHandler, aAllowUseArcsInPolygons, cleaner );
1164 if( ( !success || !aOutlines.
OutlineCount() ) && aInferOutlineIfNecessary )
1187 aOutlines.
Append( corner );
1193 aOutlines.
Append( corner );
1196 if( aAllowUseArcsInPolygons )
1254 chain.SetClosed(
true );
1262 int aOutlineNum = 0 )
1264 int minDistance = -1;
1269 auto seg = it.Get();
1270 int dis = seg.Distance( aEndPoint );
1272 if( minDistance < 0 || ( dis < minDistance ) )
1275 projPoint = seg.NearestPoint( aEndPoint );
1291 bool foundA =
false;
1292 bool foundB =
false;
1310 if( foundA && foundB )
1313 if( foundSegs == 0 )
1317 seg.
A.
x, seg.
A.
y, seg.
B.
x, seg.
B.
y );
1325 seg.
A.
x, seg.
A.
y, seg.
B.
x, seg.
B.
y );
1351 bool success =
false;
1359 std::vector<PCB_SHAPE*> segList;
1361 for(
int ii = 0; ii < items.
GetCount(); ii++ )
1363 if( items[ii]->GetLayer() ==
Edge_Cuts )
1364 segList.push_back(
static_cast<PCB_SHAPE*
>( items[ii] ) );
1367 if( !segList.empty() )
1370 aErrorHandler,
false, cleaner );
1394 for(
int j = 0; j < outlines.
HoleCount( i ); j++ )
1399 aOutlines.
AddHole( hole, -1 );
1407 aOutlines = std::move( outlines );
1425 std::vector<SHAPE_LINE_CHAIN> closedChains;
1426 std::vector<SHAPE_LINE_CHAIN> openChains;
1430 openChains.push_back( outlines.
Outline( 0 ) );
1432 for(
int j = 0; j < outlines.
HoleCount( 0 ); j++ )
1439 closedChains.push_back( hole );
1444 openChains.push_back( hole );
1456 chain.SetClosed(
false );
1467 if(
chain.SegmentCount() == 0 )
1471 aOutlines = std::move( bbox );
1474 else if(
chain.SegmentCount() == 1 )
1478 wxLogTrace(
traceBoardOutline, wxT(
"Only 1 line segment in provided outline" ) );
1480 startSeg =
chain.Segment( 0 );
1488 if( inter0 && inter2 && !inter1 && !inter3 )
1491 wxLogTrace(
traceBoardOutline, wxT(
"Segment intersects only vertical bbox sides" ) );
1507 else if( inter1 && inter3 && !inter0 && !inter2 )
1510 wxLogTrace(
traceBoardOutline, wxT(
"Segment intersects only horizontal bbox sides" ) );
1529 wxLogTrace(
traceBoardOutline, wxT(
"Segment intersects two perpendicular bbox sides" ) );
1557 else if( hit1 && hit2 )
1576 else if( hit2 && hit3 )
1622 aOutlines = std::move( bbox );
1639 aOutlines = std::move( poly2 );
1644 aOutlines = std::move( poly1 );
1651 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.
const FOOTPRINTS & Footprints() const
BOX2I ComputeBoundingBox(bool aBoardEdgesOnly=false, bool aPhysicalLayersOnly=false) const
Calculate the bounding box containing all board items (or board edge segments).
constexpr BOX2< Vec > Intersect(const BOX2< Vec > &aRect)
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 Vec Centre() 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, int aMaxError) 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
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 Intersect(const SEG &aSeg, INTERSECTIONS &aIp) const
Find all intersection points between our line chain and the segment aSeg.
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.
bool PointInside(const VECTOR2I &aPt, int aAccuracy=0, bool aUseBBoxCache=false) const override
Check if point aP lies inside a closed shape.
std::vector< INTERSECTION > INTERSECTIONS
const std::vector< VECTOR2I > & CPoints() const
Represent a set of closed polygons.
void RemoveAllContours()
Remove all outlines & holes (clears) the polygon set.
void BooleanAdd(const SHAPE_POLY_SET &b)
Perform boolean polyset union.
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)
void Simplify()
Simplify the polyset (merges overlapping polys, eliminates degeneracy/self-intersections)
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
void BooleanSubtract(const SHAPE_POLY_SET &b)
Perform boolean polyset difference.
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 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, bool aAllowUseArcsInPolygons, bool aHasMalformedOverlap)
bool BuildBoardPolygonOutlines(BOARD *aBoard, SHAPE_POLY_SET &aOutlines, int aErrorMax, int aChainingEpsilon, bool aInferOutlineIfNecessary, 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 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
static bool hasOverlappingClosedContours(const std::vector< SHAPE_LINE_CHAIN > &aContours)
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)
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 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)