62 return ( aLeft - aRight ).SquaredEuclideanNorm() <=
SEG::Square( aLimit );
76 return ( aRef - aFirst ).SquaredEuclideanNorm() < ( aRef - aSecond ).SquaredEuclideanNorm();
90 const std::vector<PCB_SHAPE*>& aList,
unsigned aLimit )
95 if( graphic == aShape || ( graphic->GetFlags() &
SKIP_STRUCT ) != 0 )
98 if( aPoint == graphic->GetStart() || aPoint == graphic->GetEnd() )
111 if( graphic == aShape )
114 d_sq = ( pt - graphic->GetStart() ).SquaredEuclideanNorm();
116 if( d_sq < closest_dist_sq )
118 closest_dist_sq = d_sq;
119 closest_graphic = graphic;
122 d_sq = ( pt - graphic->GetEnd() ).SquaredEuclideanNorm();
124 if( d_sq < closest_dist_sq )
126 closest_dist_sq = d_sq;
127 closest_graphic = graphic;
131 return closest_graphic;
137 bool padOutside =
false;
149 padPos.
x, padPos.
y );
156 padPos.
x, padPos.
y );
176 int aErrorMax,
int aChainingEpsilon,
bool aAllowDisjoint,
179 if( aShapeList.size() == 0 )
182 bool selfIntersecting =
false;
187 std::set<PCB_SHAPE*> startCandidates( aShapeList.begin(), aShapeList.end() );
191 std::map<std::pair<VECTOR2I, VECTOR2I>,
PCB_SHAPE*> shapeOwners;
196 auto it = shapeOwners.find( std::make_pair( seg.A, seg.B ) );
197 return it == shapeOwners.end() ? nullptr : it->second;
203 std::vector<SHAPE_LINE_CHAIN> contours;
205 for(
PCB_SHAPE* shape : startCandidates )
208 while( startCandidates.size() )
210 graphic = (
PCB_SHAPE*) *startCandidates.begin();
212 startCandidates.erase( startCandidates.begin() );
214 contours.emplace_back();
243 shapeOwners[ std::make_pair( prevPt, pt ) ] = graphic;
261 for(
int step = 0; step < steps; ++step )
265 currContour.
Append( nextPt );
270 shapeOwners[ std::make_pair( prevPt, nextPt ) ] = graphic;
288 shapeOwners[ std::make_pair( prevPt, pt ) ] = graphic;
302 currContour.
Append( prevPt );
316 wxASSERT( prevGraphic );
317 (*aErrorHandler)(
_(
"(self-intersecting)" ), prevGraphic, graphic, prevPt );
320 selfIntersecting =
true;
334 nextPt = graphic->
GetEnd();
338 currContour.
Append( nextPt );
339 shapeOwners[ std::make_pair( prevPt, nextPt ) ] = graphic;
360 std::swap( pstart, pend );
364 for(
int step = 1; step < steps; ++step )
372 shapeOwners[ std::make_pair( prevPt, pt ) ] = graphic;
377 currContour.
Append( pend );
378 shapeOwners[ std::make_pair( prevPt, pend ) ] = graphic;
388 bool reverse =
false;
395 nextPt = graphic->
GetEnd();
419 shapeOwners[ std::make_pair( prevPt, pt ) ] = graphic;
431 shapeOwners[ std::make_pair( prevPt, pt ) ] = graphic;
447 PCB_SHAPE* nextGraphic =
findNext( graphic, prevPt, aShapeList, aChainingEpsilon );
451 prevGraphic = graphic;
452 graphic = nextGraphic;
454 startCandidates.erase( graphic );
465 else if( nextGraphic )
468 (*aErrorHandler)(
_(
"(self-intersecting)" ), graphic, nextGraphic, prevPt );
475 (*aErrorHandler)(
_(
"(not a closed shape)" ), graphic,
nullptr, prevPt );
485 if( !contour.IsClosed() )
491 std::map<int, std::vector<int>> contourToParentIndexesMap;
493 for(
size_t ii = 0; ii < contours.size(); ++ii )
495 VECTOR2I firstPt = contours[ii].GetPoint( 0 );
496 std::vector<int> parents;
498 for(
size_t jj = 0; jj < contours.size(); ++jj )
506 parents.push_back( jj );
509 contourToParentIndexesMap[ii] = parents;
514 std::map<int, int> contourToOutlineIdxMap;
516 for(
const auto& [ contourIndex, parentIndexes ] : contourToParentIndexesMap )
518 if( parentIndexes.size() %2 == 0 )
521 if( !aAllowDisjoint && !aPolygons.
IsEmpty() )
526 BOARD_ITEM* b = fetchOwner( contours[ contourIndex ].GetSegment( 0 ) );
530 (*aErrorHandler)(
_(
"(multiple board outlines not supported)" ), a, b,
531 contours[ contourIndex ].GetPoint( 0 ) );
538 aPolygons.
AddOutline( contours[ contourIndex ] );
539 contourToOutlineIdxMap[ contourIndex ] = aPolygons.
OutlineCount() - 1;
545 for(
const auto& [ contourIndex, parentIndexes ] : contourToParentIndexesMap )
547 if( parentIndexes.size() %2 == 1 )
553 for(
int parentContourIdx : parentIndexes )
555 if( contourToParentIndexesMap[ parentContourIdx ].size() == parentIndexes.size() - 1 )
557 int outlineIdx = contourToOutlineIdxMap[ parentContourIdx ];
558 aPolygons.
AddHole( hole, outlineIdx );
573 for( ++seg2; seg2; seg2++ )
576 if( *seg1 == *seg2 || ( ( *seg1 ).A == ( *seg2 ).B && ( *seg1 ).B == ( *seg2 ).A ) )
584 (*aErrorHandler)(
_(
"(self-intersecting)" ), a, b, ( *seg1 ).A );
587 selfIntersecting =
true;
590 if(
OPT_VECTOR2I pt = seg1.Get().Intersect( seg2.Get(),
true ) )
598 (*aErrorHandler)(
_(
"(self-intersecting)" ), a, b, *pt );
601 selfIntersecting =
true;
606 return !selfIntersecting;
621 bool success =
false;
628 for(
int ii = 0; ii < items.
GetCount(); ++ii )
636 std::vector<PCB_SHAPE*> fpSegList;
638 for(
int ii = 0; ii < fpItems.
GetCount(); ii++ )
643 fpSegList.push_back( fpSeg );
646 if( !fpSegList.empty() )
657 fpHoles.
Append( fpOutlines );
663 for(
int ii = 0; ii < fpItems.
GetCount(); ++ii )
670 std::vector<PCB_SHAPE*> segList;
672 for(
int ii = 0; ii < items.
GetCount(); ii++ )
681 segList.push_back( seg );
687 true, aErrorHandler );
714 aOutlines.
Append( corner );
720 aOutlines.
Append( corner );
781 int aOutlineNum = 0 )
783 int minDistance = -1;
789 int dis = seg.Distance( aEndPoint );
791 if( minDistance < 0 || ( dis < minDistance ) )
794 projPoint = seg.NearestPoint( aEndPoint );
829 if( foundA && foundB )
836 seg.
A.
x, seg.
A.
y, seg.
B.
x, seg.
B.
y );
844 seg.
A.
x, seg.
A.
y, seg.
B.
x, seg.
B.
y );
881 bool success =
false;
887 std::vector<PCB_SHAPE*> segList;
889 for(
int ii = 0; ii < items.
GetCount(); ii++ )
892 segList.push_back(
static_cast<PCB_SHAPE*
>( items[ii] ) );
895 if( !segList.empty() )
898 true, aErrorHandler );
921 for(
int j = 0; j < outlines.
HoleCount( i ); j++ )
934 aOutlines = outlines;
952 std::vector<SHAPE_LINE_CHAIN> closedChains;
953 std::vector<SHAPE_LINE_CHAIN> openChains;
957 openChains.push_back( outlines.
Outline( 0 ) );
959 for(
int j = 0; j < outlines.
HoleCount( 0 ); j++ )
966 closedChains.push_back( hole );
971 openChains.push_back( hole );
1005 wxLogTrace(
traceBoardOutline, wxT(
"Only 1 line segment in provided outline" ) );
1007 startSeg = chain.
Segment( 0 );
1015 if( inter0 && inter2 && !inter1 && !inter3 )
1035 else if( inter1 && inter3 && !inter0 && !inter2 )
1058 wxLogTrace(
traceBoardOutline, wxT(
"Segment intersects two perpendicular bbox "
1087 else if( hit1 && hit2 )
1106 else if( hit2 && hit3 )
1181 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...
virtual PCB_LAYER_ID GetLayer() const
Return the primary layer this item is on.
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).
FOOTPRINTS & Footprints()
const Vec & GetOrigin() const
coord_type GetHeight() const
coord_type GetWidth() const
BOX2< Vec > & Inflate(coord_type dx, coord_type dy)
Inflates the rectangle horizontally by dx and vertically by dy.
int GetCount() const
Return the number of objects in the list.
void SetFlags(EDA_ITEM_FLAGS aMask)
EDA_ITEM_FLAGS GetFlags() const
EDA_ANGLE GetArcAngle() const
void RebuildBezierToSegmentsPointsList(int aMinSegLen)
Rebuild the m_bezierPoints vertex list that approximate the Bezier curve by a list of segments.
SHAPE_POLY_SET & GetPolyShape()
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
wxString SHAPE_T_asString() const
VECTOR2I GetCenter() const override
This defaults to the center of the bounding box if not overridden.
FOOTPRINT * GetParentFootprint() const
Return the parent footprint or NULL if PCB_SHAPE does not belong to a footprint.
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.
VECTOR2I::extended_type ecoord
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
bool PointInside(const VECTOR2I &aPt, int aAccuracy=0, bool aUseBBoxCache=false) const
Check if point aP lies inside a polygon (any type) defined by the line chain.
Represent a polyline containing arcs as well as line segments: A chain of connected line and/or arc s...
bool IsClosed() const override
virtual const VECTOR2I GetPoint(int aIndex) const override
void SetClosed(bool aClosed)
Mark the line chain as closed (i.e.
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.
SEG Segment(int aIndex)
Return a copy of the aIndex-th segment in the line chain.
Represent a set of closed polygons.
int AddOutline(const SHAPE_LINE_CHAIN &aOutline)
Adds a new hole to the given outline (default: last) and returns its index.
CONST_ITERATOR CIterate(int aFirst, int aLast, bool aIterateHoles=false) const
void BooleanIntersection(const SHAPE_POLY_SET &b, POLYGON_MODE aFastMode)
Perform boolean polyset union between a and b, store the result in it self For aFastMode meaning,...
int HoleCount(int aOutline) const
Return the reference to aIndex-th outline in the set.
int Append(int x, int y, int aOutline=-1, int aHole=-1, bool aAllowDuplication=false)
Add a new vertex to the contour indexed by aOutline and aHole (defaults to the outline of the last po...
int AddHole(const SHAPE_LINE_CHAIN &aHole, int aOutline=-1)
Return the area of this poly set.
SHAPE_LINE_CHAIN & Outline(int aIndex)
SHAPE_LINE_CHAIN & Hole(int aOutline, int aHole)
Return the aIndex-th subpolygon in the set.
int NewOutline()
Creates a new hole in a given outline.
CONST_SEGMENT_ITERATOR CIterateSegments(int aFirst, int aLast, bool aIterateHoles=false) const
Return an iterator object, for iterating aPolygonIdx-th polygon edges.
int OutlineCount() const
Return the number of vertices in a given outline/hole.
SHAPE_POLY_SET CloneDropTriangulation() const
Creates a new empty polygon in the set and returns its index.
SEGMENT_ITERATOR IterateSegmentsWithHoles()
Return an iterator object, for the aOutline-th outline in the set (with holes).
VECTOR2I projectPointOnSegment(const VECTOR2I &aEndPoint, const SHAPE_POLY_SET &aOutline, int aOutlineNum=0)
static PCB_SHAPE * findNext(PCB_SHAPE *aShape, const VECTOR2I &aPoint, const std::vector< PCB_SHAPE * > &aList, unsigned aLimit)
Searches for a PCB_SHAPE matching a given end point or start point in a list.
bool close_enough(VECTOR2I aLeft, VECTOR2I aRight, unsigned aLimit)
Function close_enough is a local and tunable method of qualifying the proximity of two points.
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)
Extracts the board outlines and build a closed polygon from lines, arcs and circle items on edge cut ...
bool ConvertOutlineToPolygon(std::vector< PCB_SHAPE * > &aShapeList, SHAPE_POLY_SET &aPolygons, int aErrorMax, int aChainingEpsilon, bool aAllowDisjoint, OUTLINE_ERROR_HANDLER *aErrorHandler)
Function ConvertOutlineToPolygon Build a polygon (with holes) from a PCB_SHAPE list,...
bool BuildFootprintPolygonOutlines(BOARD *aBoard, SHAPE_POLY_SET &aOutlines, int aErrorMax, int aChainingEpsilon, OUTLINE_ERROR_HANDLER *aErrorHandler)
This function is used to extract a board outline for a footprint view.
bool isCopperOutside(const FOOTPRINT *aFootprint, SHAPE_POLY_SET &aShape)
bool closer_to_first(VECTOR2I aRef, VECTOR2I aFirst, VECTOR2I aSecond)
Function closer_to_first Local method which qualifies whether the start or end point of a segment is ...
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
static constexpr EDA_ANGLE & FULL_CIRCLE
static constexpr EDA_ANGLE & ANGLE_0
#define SKIP_STRUCT
flag indicating that the structure should be ignored
a few functions useful in geometry calculations.
int GetArcToSegmentCount(int aRadius, int aErrorMax, const EDA_ANGLE &aArcAngle)
const wxChar * traceBoardOutline
Flag to enable debug tracing for the board outline creation.
This file contains miscellaneous commonly used macros and functions.
#define UNIMPLEMENTED_FOR(type)
static DIRECTION_45::AngleType angle(const VECTOR2I &a, const VECTOR2I &b)
std::optional< VECTOR2I > OPT_VECTOR2I
constexpr int mmToIU(double mm) const
void RotatePoint(int *pX, int *pY, const EDA_ANGLE &aAngle)
@ PCB_SHAPE_T
class PCB_SHAPE, a segment not on copper layers
@ PCB_FP_SHAPE_T
class FP_SHAPE, a footprint edge