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 ) )
 
  297            std::swap( pstart, pend );
 
  303        arcChain.
Append( sarc, aErrorMax );
 
  305        if( !aAllowUseArcsInPolygons )
 
  308        for( 
int ii = 1; ii < arcChain.
PointCount(); ++ii )
 
  310            aShapeOwners[ std::make_pair( arcChain.
CPoint( ii - 1 ),
 
  311                                         arcChain.
CPoint( ii ) ) ] = aShape;
 
  314        aContour.
Append( arcChain );
 
  321        bool     reverse = 
false;
 
  325            nextPt = aShape->
GetEnd();
 
  345                aShapeOwners[ std::make_pair( aPrevPt, pt ) ] = aShape;
 
  357                aShapeOwners[ std::make_pair( aPrevPt, pt ) ] = aShape;
 
 
  372    std::map<int, std::vector<int>> contourToParentIndexesMap;
 
  374    for( 
size_t ii = 0; ii < aContours.size(); ++ii )
 
  376        VECTOR2I         firstPt = aContours[ii].GetPoint( 0 );
 
  377        std::vector<int> parents;
 
  379        for( 
size_t jj = 0; jj < aContours.size(); ++jj )
 
  386            if( parentCandidate.
PointInside( firstPt, 0, 
true ) )
 
  387                parents.push_back( jj );
 
  390        contourToParentIndexesMap[ii] = std::move( parents );
 
  393    return contourToParentIndexesMap;
 
 
  397                                  const std::map<
int, std::vector<int>>& aContourHierarchy,
 
  400                                  const std::function<
PCB_SHAPE*(
const SEG&)>& aFetchOwner,
 
  401                                  std::map<int, int>& aContourToOutlineIdxMap )
 
  403    for( 
const auto& [ contourIndex, parentIndexes ] : aContourHierarchy )
 
  405        if( parentIndexes.size() % 2 == 0 )
 
  408            if( !aAllowDisjoint && !aPolygons.
IsEmpty() )
 
  413                    BOARD_ITEM* b = aFetchOwner( aContours[ contourIndex ].GetSegment( 0 ) );
 
  417                        (*aErrorHandler)( 
_( 
"(multiple board outlines not supported)" ), a, b,
 
  418                                          aContours[ contourIndex ].GetPoint( 0 ) );
 
  424            aPolygons.
AddOutline( aContours[ contourIndex ] );
 
  425            aContourToOutlineIdxMap[ contourIndex ] = aPolygons.
OutlineCount() - 1;
 
 
  432                               const std::map<
int, std::vector<int>>& aContourHierarchy,
 
  433                               const std::map<int, int>& aContourToOutlineIdxMap,
 
  436    for( 
const auto& [ contourIndex, parentIndexes ] : aContourHierarchy )
 
  438        if( parentIndexes.size() % 2 == 1 )
 
  443            for( 
int parentContourIdx : parentIndexes )
 
  445                if( aContourHierarchy.at( parentContourIdx ).size() == parentIndexes.size() - 1 )
 
  447                    int outlineIdx = aContourToOutlineIdxMap.at( parentContourIdx );
 
  448                    aPolygons.
AddHole( hole, outlineIdx );
 
 
  458                                   const std::function<
PCB_SHAPE*(
const SEG&)>& aFetchOwner )
 
  460    bool selfIntersecting = 
false;
 
  461    std::vector<SEG> segments;
 
  469        for( 
int jj = 0; jj < aPolygons.
HoleCount( ii ); ++jj )
 
  476    segments.reserve( total );
 
  483            std::swap( segment.
A, segment.
B );
 
  485        segments.push_back( segment );
 
  488    std::sort( segments.begin(), segments.end(),
 
  489               []( 
const SEG& a, 
const SEG& b )
 
  492                       return LexicographicalCompare( a.A, b.A ) < 0;
 
  493                   return LexicographicalCompare( a.B, b.B ) < 0;
 
  496    for( 
size_t i = 0; i < segments.size(); ++i )
 
  498        const SEG& seg1 = segments[i];
 
  500        for( 
size_t j = i + 1; j < segments.size(); ++j )
 
  502            const SEG& seg2 = segments[j];
 
  504            if( seg2.
A > seg1.
B )
 
  507            if( seg1 == seg2 || ( seg1.
A == seg2.
B && seg1.
B == seg2.
A ) )
 
  513                    (*aErrorHandler)( 
_( 
"(self-intersecting)" ), a, b, seg1.
A );
 
  515                selfIntersecting = 
true;
 
  523                    (*aErrorHandler)( 
_( 
"(self-intersecting)" ), a, b, *pt );
 
  525                selfIntersecting = 
true;
 
  530    return !selfIntersecting;
 
 
  537    const double query_pt[2] = { 
static_cast<double>( aPoint.
x ), 
static_cast<double>( aPoint.
y ) };
 
  541    kdTree.knnSearch( query_pt, 2, indices, distances );
 
  543    if( distances[0] == std::numeric_limits<double>::max() )
 
  548    double closest_dist_sq = aChainingEpsilon * aChainingEpsilon;
 
  550    for( 
size_t i = 0; i < 2; ++i )
 
  552        if( distances[i] == std::numeric_limits<double>::max() )
 
  557        if( candidate == aShape )
 
  560        if( distances[i] < closest_dist_sq )
 
  562            closest_dist_sq = distances[i];
 
  563            closest_graphic = candidate;
 
  567    return closest_graphic;
 
 
  571                                int aErrorMax, 
int aChainingEpsilon, 
bool aAllowDisjoint,
 
  575    if( aShapeList.size() == 0 )
 
  578    bool       selfIntersecting = 
false;
 
  581    std::set<PCB_SHAPE*> startCandidates( aShapeList.begin(), aShapeList.end() );
 
  585    KDTree                      kdTree( 2, adaptor );
 
  588    std::map<std::pair<VECTOR2I, VECTOR2I>, 
PCB_SHAPE*> shapeOwners;
 
  593                auto it = shapeOwners.find( std::make_pair( seg.A, seg.B ) );
 
  594                return it == shapeOwners.end() ? nullptr : it->second;
 
  597    std::set<std::pair<PCB_SHAPE*, PCB_SHAPE*>> reportedGaps;
 
  598    std::vector<SHAPE_LINE_CHAIN> contours;
 
  599    contours.reserve( startCandidates.size() );
 
  601    for( 
PCB_SHAPE* shape : startCandidates )
 
  605    while( startCandidates.size() )
 
  607        graphic = *startCandidates.begin();
 
  609        aCleaner.insert( graphic );
 
  610        startCandidates.erase( startCandidates.begin() );
 
  612        contours.emplace_back();
 
  620            processClosedShape( graphic, currContour, shapeOwners, aErrorMax, aAllowUseArcsInPolygons );
 
  625            std::deque<PCB_SHAPE*> 
chain;
 
  626            chain.push_back( graphic );
 
  632            auto extendChain = [&]( 
bool forward )
 
  635                VECTOR2I   prev = forward ? backPt : frontPt;
 
  644                        aCleaner.insert( 
next );
 
  645                        startCandidates.erase( 
next );
 
  653                            prev = 
next->GetEnd();
 
  655                            prev = 
next->GetStart();
 
  664                        VECTOR2I   chainPt = forward ? frontPt : backPt;
 
  673                                ( *aErrorHandler )( 
_( 
"(self-intersecting)" ), curr, 
next, prev );
 
  675                            selfIntersecting = 
true;
 
  691                extendChain( 
false );
 
  697            if( 
chain.size() > 1 )
 
  703                    startPt = first->
GetEnd();
 
  712            currContour.
Append( startPt );
 
  718                                   aErrorMax, aChainingEpsilon, aAllowUseArcsInPolygons );
 
  735                        arcChain.
Append( sarc, aErrorMax );
 
  737                        if( !aAllowUseArcsInPolygons )
 
  740                        for( 
int ii = 1; ii < arcChain.
PointCount(); ++ii )
 
  741                            shapeOwners[std::make_pair( arcChain.
CPoint( ii - 1 ), arcChain.
CPoint( ii ) )] = owner;
 
  744                        currContour.
Append( arcChain );
 
  750                        shapeOwners[ std::make_pair( currContour.
CPoints()[currContour.
PointCount() - 2],
 
  759                auto report_gap = [&]( 
const VECTOR2I& pt )
 
  764                    const double query_pt[2] = { 
static_cast<double>( pt.x ), 
static_cast<double>( pt.y ) };
 
  769                    kdTree.knnSearch( query_pt, 2, indices, dists );
 
  775                    auto key = std::minmax( shapeA, shapeB );
 
  777                    if( !reportedGaps.insert( key ).second )
 
  786                    if( effectiveShapeA && effectiveShapeB
 
  787                        && effectiveShapeA->NearestPoints( effectiveShapeB.get(), ptA, ptB ) )
 
  789                        midpoint = ( ptA + ptB ) / 2;
 
  792                    ( *aErrorHandler )( 
_( 
"(not a closed shape)" ), shapeA, shapeB, midpoint );
 
  795                report_gap( currContour.
CPoint( 0 ) );
 
  804        if( !contour.IsClosed() )
 
  809    for( 
size_t ii = 0; ii < contours.size(); ++ii )
 
  821    std::map<int, int> contourToOutlineIdxMap;
 
  823                               aErrorHandler, fetchOwner, contourToOutlineIdxMap ) )
 
  829    addHolesToPolygon( contours, contourHierarchy, contourToOutlineIdxMap, aPolygons );
 
 
  837                              int aErrorMax, 
int aChainingEpsilon, 
bool aAllowDisjoint,
 
  843                                      aAllowDisjoint, aErrorHandler, aAllowUseArcsInPolygons,
 
 
  853    int                 min_dist = std::max( 0, aMinDist );
 
  858    std::vector<PCB_SHAPE*> shapeList;
 
  860    for( 
int ii = 0; ii < items.
GetCount(); ii++ )
 
  865            shapeList.push_back( seg );
 
  871        switch( shape->GetShape() )
 
  875            VECTOR2I seg = shape->GetEnd() - shape->GetStart();
 
  878            if( dim <= min_dist )
 
  884                    (*aErrorHandler)( wxString::Format( 
_( 
"(rectangle has null or very small " 
  885                                                           "size: %d nm)" ), dim ),
 
  886                                      shape, 
nullptr, shape->GetStart() );
 
  894            int r = shape->GetRadius();
 
  902                    (*aErrorHandler)( wxString::Format( 
_( 
"(circle has null or very small " 
  903                                                           "radius: %d nm)" ), r ),
 
  904                                      shape, 
nullptr, shape->GetStart() );
 
  912            VECTOR2I seg = shape->GetEnd() - shape->GetStart();
 
  915            if( dim <= min_dist )
 
  921                    (*aErrorHandler)( wxString::Format( 
_( 
"(segment has null or very small " 
  922                                                           "length: %d nm)" ), dim ),
 
  923                                      shape, 
nullptr, shape->GetStart() );
 
  933            VECTOR2I arcMiddle = shape->GetArcMid();
 
  934            VECTOR2I seg1 = arcMiddle - shape->GetStart();
 
  935            VECTOR2I seg2 = shape->GetEnd() - arcMiddle;
 
  938            if( dim <= min_dist )
 
  944                    (*aErrorHandler)( wxString::Format( 
_( 
"(arc has null or very small size: " 
  946                                      shape, 
nullptr, shape->GetStart() );
 
 
  970                                bool aAllowUseArcsInPolygons )
 
  974    bool               success = 
false;
 
  981    for( 
int ii = 0; ii < items.
GetCount(); ++ii )
 
  989        std::vector<PCB_SHAPE*> fpSegList;
 
  991        for( 
int ii = 0; ii < fpItems.
GetCount(); ii++ )
 
  996                fpSegList.push_back( fpSeg );
 
  999        if( !fpSegList.empty() )
 
 1006                                                 nullptr, aAllowUseArcsInPolygons, cleaner );
 
 1015                fpHoles.
Append( fpOutlines );
 
 1021                for( 
int ii = 0; ii < fpItems.
GetCount(); ++ii )
 
 1028    std::vector<PCB_SHAPE*> segList;
 
 1030    for( 
int ii = 0; ii < items.
GetCount(); ii++ )
 
 1039            segList.push_back( seg );
 
 1042    if( segList.size() )
 
 1045                                             aErrorHandler, aAllowUseArcsInPolygons, cleaner );
 
 1071        aOutlines.
Append( corner );
 
 1077        aOutlines.
Append( corner );
 
 1083    if( aAllowUseArcsInPolygons )
 
 1108    if( aAllowUseArcsInPolygons )
 
 1117        for( 
int ii = 0; ii < outerContours.
OutlineCount(); ++ii )
 
 1121            for( 
int jj = 0; jj < aOutlines.
HoleCount( ii ); ++jj )
 
 1125        aOutlines = std::move( 
result );
 
 
 1165    chain.SetClosed( 
true );
 
 
 1173        int aOutlineNum = 0 )
 
 1175    int      minDistance = -1;
 
 1180        auto seg = it.Get();
 
 1181        int dis = seg.Distance( aEndPoint );
 
 1183        if( minDistance < 0 || ( dis < minDistance ) )
 
 1186            projPoint   = seg.NearestPoint( aEndPoint );
 
 
 1202        bool foundA = 
false;
 
 1203        bool foundB = 
false;
 
 1221        if( foundA && foundB )
 
 1224        if( foundSegs == 0 )
 
 1228                        seg.
A.
x, seg.
A.
y, seg.
B.
x, seg.
B.
y );
 
 1236                        seg.
A.
x, seg.
A.
y, seg.
B.
x, seg.
B.
y );
 
 
 1262    bool               success = 
false;
 
 1270    std::vector<PCB_SHAPE*> segList;
 
 1272    for( 
int ii = 0; ii < items.
GetCount(); ii++ )
 
 1274        if( items[ii]->GetLayer() == 
Edge_Cuts )
 
 1275            segList.push_back( 
static_cast<PCB_SHAPE*
>( items[ii] ) );
 
 1278    if( !segList.empty() )
 
 1281                                             aErrorHandler, 
false, cleaner );
 
 1305                for( 
int j = 0; j < outlines.
HoleCount( i ); j++ )
 
 1310                        aOutlines.
AddHole( hole, -1 );
 
 1318            aOutlines = std::move( outlines );
 
 1336        std::vector<SHAPE_LINE_CHAIN> closedChains;
 
 1337        std::vector<SHAPE_LINE_CHAIN> openChains;
 
 1341        openChains.push_back( outlines.
Outline( 0 ) );
 
 1343        for( 
int j = 0; j < outlines.
HoleCount( 0 ); j++ )
 
 1350                closedChains.push_back( hole );
 
 1355                openChains.push_back( hole );
 
 1367        chain.SetClosed( 
false );
 
 1378        if( 
chain.SegmentCount() == 0 )
 
 1382            aOutlines = std::move( bbox );
 
 1385        else if( 
chain.SegmentCount() == 1 )
 
 1389            wxLogTrace( 
traceBoardOutline, wxT( 
"Only 1 line segment in provided outline" ) );
 
 1391            startSeg = 
chain.Segment( 0 );
 
 1399            if( inter0 && inter2 && !inter1 && !inter3 )
 
 1402                wxLogTrace( 
traceBoardOutline, wxT( 
"Segment intersects only vertical bbox sides" ) );
 
 1418            else if( inter1 && inter3 && !inter0 && !inter2 )
 
 1421                wxLogTrace( 
traceBoardOutline, wxT( 
"Segment intersects only horizontal bbox sides" ) );
 
 1440                wxLogTrace( 
traceBoardOutline, wxT( 
"Segment intersects two perpendicular bbox sides" ) );
 
 1468                else if( hit1 && hit2 )
 
 1487                else if( hit2 && hit3 )
 
 1533            aOutlines = std::move( bbox );
 
 1550            aOutlines = std::move( poly2 );
 
 1555            aOutlines = std::move( poly1 );
 
 1562            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, 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
 
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
 
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 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
 
wxString result
Test unit parsing edge cases and error handling.
 
@ 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)