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();
232 shapeOwners[ std::make_pair( prevPt, pt ) ] = graphic;
248 currContour.
Append( arc360, aErrorMax );
252 for(
int ii = 1; ii < currContour.
PointCount(); ++ii )
254 shapeOwners[ std::make_pair( currContour.
CPoint( ii-1 ),
255 currContour.
CPoint( ii ) ) ] = graphic;
258 if( !aAllowUseArcsInPolygons )
272 shapeOwners[ std::make_pair( prevPt, pt ) ] = graphic;
286 currContour.
Append( prevPt );
300 wxASSERT( prevGraphic );
301 (*aErrorHandler)(
_(
"(self-intersecting)" ), prevGraphic, graphic, prevPt );
304 selfIntersecting =
true;
318 nextPt = graphic->
GetEnd();
322 currContour.
Append( nextPt );
323 shapeOwners[ std::make_pair( prevPt, nextPt ) ] = graphic;
338 std::swap( pstart, pend );
344 arcChain.
Append( sarc, aErrorMax );
346 if( !aAllowUseArcsInPolygons )
350 for(
int ii = 1; ii < arcChain.
PointCount(); ++ii )
352 shapeOwners[std::make_pair( arcChain.
CPoint( ii - 1 ),
353 arcChain.
CPoint( ii ) )] = graphic;
356 currContour.
Append( arcChain );
367 bool reverse =
false;
374 nextPt = graphic->
GetEnd();
398 shapeOwners[ std::make_pair( prevPt, pt ) ] = graphic;
410 shapeOwners[ std::make_pair( prevPt, pt ) ] = graphic;
426 PCB_SHAPE* nextGraphic =
findNext( graphic, prevPt, aShapeList, aChainingEpsilon );
430 prevGraphic = graphic;
431 graphic = nextGraphic;
433 startCandidates.erase( graphic );
444 else if( nextGraphic )
447 (*aErrorHandler)(
_(
"(self-intersecting)" ), graphic, nextGraphic, prevPt );
454 (*aErrorHandler)(
_(
"(not a closed shape)" ), graphic,
nullptr, prevPt );
464 if( !contour.IsClosed() )
470 std::map<int, std::vector<int>> contourToParentIndexesMap;
472 for(
size_t ii = 0; ii < contours.size(); ++ii )
474 VECTOR2I firstPt = contours[ii].GetPoint( 0 );
475 std::vector<int> parents;
477 for(
size_t jj = 0; jj < contours.size(); ++jj )
485 parents.push_back( jj );
488 contourToParentIndexesMap[ii] = parents;
493 std::map<int, int> contourToOutlineIdxMap;
495 for(
const auto& [ contourIndex, parentIndexes ] : contourToParentIndexesMap )
497 if( parentIndexes.size() %2 == 0 )
500 if( !aAllowDisjoint && !aPolygons.
IsEmpty() )
505 BOARD_ITEM* b = fetchOwner( contours[ contourIndex ].GetSegment( 0 ) );
509 (*aErrorHandler)(
_(
"(multiple board outlines not supported)" ), a, b,
510 contours[ contourIndex ].GetPoint( 0 ) );
517 aPolygons.
AddOutline( contours[ contourIndex ] );
518 contourToOutlineIdxMap[ contourIndex ] = aPolygons.
OutlineCount() - 1;
524 for(
const auto& [ contourIndex, parentIndexes ] : contourToParentIndexesMap )
526 if( parentIndexes.size() %2 == 1 )
532 for(
int parentContourIdx : parentIndexes )
534 if( contourToParentIndexesMap[ parentContourIdx ].size() == parentIndexes.size() - 1 )
536 int outlineIdx = contourToOutlineIdxMap[ parentContourIdx ];
537 aPolygons.
AddHole( hole, outlineIdx );
552 for( ++seg2; seg2; seg2++ )
555 if( *seg1 == *seg2 || ( ( *seg1 ).A == ( *seg2 ).B && ( *seg1 ).B == ( *seg2 ).A ) )
561 (*aErrorHandler)(
_(
"(self-intersecting)" ), a, b, ( *seg1 ).A );
564 selfIntersecting =
true;
567 if(
OPT_VECTOR2I pt = seg1.Get().Intersect( seg2.Get(),
true ) )
573 (*aErrorHandler)(
_(
"(self-intersecting)" ), a, b, *pt );
576 selfIntersecting =
true;
581 return !selfIntersecting;
594 bool aAllowUseArcsInPolygons )
597 bool success =
false;
604 for(
int ii = 0; ii < items.
GetCount(); ++ii )
612 std::vector<PCB_SHAPE*> fpSegList;
614 for(
int ii = 0; ii < fpItems.
GetCount(); ii++ )
619 fpSegList.push_back( fpSeg );
622 if( !fpSegList.empty() )
629 nullptr, aAllowUseArcsInPolygons );
637 fpHoles.
Append( fpOutlines );
643 for(
int ii = 0; ii < fpItems.
GetCount(); ++ii )
650 std::vector<PCB_SHAPE*> segList;
652 for(
int ii = 0; ii < items.
GetCount(); ii++ )
661 segList.push_back( seg );
667 true, aErrorHandler, aAllowUseArcsInPolygons );
694 aOutlines.
Append( corner );
700 aOutlines.
Append( corner );
761 int aOutlineNum = 0 )
763 int minDistance = -1;
769 int dis = seg.Distance( aEndPoint );
771 if( minDistance < 0 || ( dis < minDistance ) )
774 projPoint = seg.NearestPoint( aEndPoint );
809 if( foundA && foundB )
816 seg.
A.
x, seg.
A.
y, seg.
B.
x, seg.
B.
y );
824 seg.
A.
x, seg.
A.
y, seg.
B.
x, seg.
B.
y );
861 bool success =
false;
867 std::vector<PCB_SHAPE*> segList;
869 for(
int ii = 0; ii < items.
GetCount(); ii++ )
872 segList.push_back(
static_cast<PCB_SHAPE*
>( items[ii] ) );
875 if( !segList.empty() )
878 true, aErrorHandler );
902 for(
int j = 0; j < outlines.
HoleCount( i ); j++ )
915 aOutlines = outlines;
933 std::vector<SHAPE_LINE_CHAIN> closedChains;
934 std::vector<SHAPE_LINE_CHAIN> openChains;
938 openChains.push_back( outlines.
Outline( 0 ) );
940 for(
int j = 0; j < outlines.
HoleCount( 0 ); j++ )
947 closedChains.push_back( hole );
952 openChains.push_back( hole );
986 wxLogTrace(
traceBoardOutline, wxT(
"Only 1 line segment in provided outline" ) );
996 if( inter0 && inter2 && !inter1 && !inter3 )
1016 else if( inter1 && inter3 && !inter0 && !inter2 )
1039 wxLogTrace(
traceBoardOutline, wxT(
"Segment intersects two perpendicular bbox "
1068 else if( hit1 && hit2 )
1087 else if( hit2 && hit3 )
1162 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).
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
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 GetArcMid() const
VECTOR2I GetCenter() const override
This defaults to the center of the bounding box if not overridden.
int GetWidth() const override
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.
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 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...
bool IsClosed() const override
virtual const VECTOR2I GetPoint(int aIndex) const override
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.
void ClearArcs()
Remove all arc references in the line chain, resulting in a chain formed only of straight segments.
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.
void RemoveAllContours()
Remove all outlines & holes (clears) the polygon set.
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
void BooleanIntersection(const SHAPE_POLY_SET &b, POLYGON_MODE aFastMode)
Perform boolean polyset intersection For aFastMode meaning, see function booleanOp.
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.
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)
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.
static bool isCopperOutside(const FOOTPRINT *aFootprint, SHAPE_POLY_SET &aShape)
bool ConvertOutlineToPolygon(std::vector< PCB_SHAPE * > &aShapeList, SHAPE_POLY_SET &aPolygons, int aErrorMax, int aChainingEpsilon, bool aAllowDisjoint, OUTLINE_ERROR_HANDLER *aErrorHandler, bool aAllowUseArcsInPolygons)
Function ConvertOutlineToPolygon build a polygon set (with holes) from a PCB_SHAPE list,...
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)
Extracts the board outlines and build a closed polygon from lines, arcs and circle items on edge cut ...
static 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.
static 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 ...
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.
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
@ ARC
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.
This file contains miscellaneous commonly used macros and functions.
#define UNIMPLEMENTED_FOR(type)
std::optional< VECTOR2I > OPT_VECTOR2I
constexpr int mmToIU(double mm) const
@ PCB_SHAPE_T
class PCB_SHAPE, a segment not on copper layers