45 int aClearance,
int aChamfer )
51 s.
Append( aP0.
x - aClearance, aP0.
y - aClearance + aChamfer );
54 s.
Append( aP0.
x - aClearance + aChamfer, aP0.
y - aClearance );
56 s.
Append( aP0.
x + aSize.
x + aClearance - aChamfer, aP0.
y - aClearance );
59 s.
Append( aP0.
x + aSize.
x + aClearance, aP0.
y - aClearance + aChamfer );
61 s.
Append( aP0.
x + aSize.
x + aClearance, aP0.
y + aSize.
y + aClearance - aChamfer );
64 s.
Append( aP0.
x + aSize.
x + aClearance - aChamfer, aP0.
y + aSize.
y + aClearance );
66 s.
Append( aP0.
x - aClearance + aChamfer, aP0.
y + aSize.
y + aClearance );
69 s.
Append( aP0.
x - aClearance, aP0.
y + aSize.
y + aClearance - aChamfer );
77 int cl = aClearance + ( aWalkaroundThickness + 1 ) / 2;
86 2.0 * ( 1.0 - M_SQRT1_2 ) * ( r + cl ) );
90 int x = (int) ( 2.0 / ( 1.0 + M_SQRT2 ) * d ) / 2;
96 std::vector<VECTOR2I> reverse_line;
98 auto seg = line.Segment( 0 );
106 s.
Append( seg.A + p0 - pd );
107 s.
Append( seg.A - dp + ds );
108 s.
Append( seg.A - dp - ds );
109 s.
Append( seg.A - p0 - pd );
111 for(
int i = 1; i < line.SegmentCount(); i++ )
115 ( line.CSegment( i - 1 ).
B - line.CSegment( i - 1 ).A ).Perpendicular().Resize( d );
116 auto pp2 = ( line.CSegment( i ).
B - line.CSegment( i ).A ).Perpendicular().Resize( d );
118 auto sa_out = line.CSegment( i - 1 ), sa_in = line.CSegment( i - 1 );
119 auto sb_out = line.CSegment( i ), sb_in = line.CSegment( i );
131 auto ip_out = sa_out.IntersectLines( sb_out );
132 auto ip_in = sa_in.IntersectLines( sb_in );
134 seg = line.CSegment( i );
136 reverse_line.push_back( *ip_in );
139 seg = line.CSegment( -1 );
145 s.
Append( seg.B - p0 + pd );
146 s.
Append( seg.B + dp - ds );
147 s.
Append( seg.B + dp + ds );
148 s.
Append( seg.B + p0 + pd );
150 for(
int i = reverse_line.size() - 1; i >= 0; i-- )
151 s.
Append( reverse_line[i] );
180template <
typename T>
int sgn(
T val) {
181 return (
T(0) < val) - (val <
T(0));
186 int aWalkaroundThickness )
188 const int kinkThreshold = aClearance / 10;
190 int cl = aClearance + aWalkaroundThickness / 2;
191 double d = (double)aSeg.
GetWidth() / 2.0 + cl;
192 double x = 2.0 / ( 1.0 + M_SQRT2 ) * d;
215 if ( len <= kinkThreshold && len > 0 )
224 if( len <= kinkThreshold )
237 else if ( delta45 <= 2 )
256 int xx2 =
KiROUND( 2.0 * ( 1.0 - M_SQRT1_2 ) * d );
298 VECTOR2I moveBy = ( aDiagonal.
A - aDiagonal.
B ).Perpendicular().Resize( dist - aClearance );
299 aDiagonal.
A += moveBy;
300 aDiagonal.
B += moveBy;
322 SEG toprightline =
SEG( corner,
334 SEG bottomleftline =
SEG( corner,
368 return SHAPE_RECT( std::min( p0.
x, p1.
x ), std::min( p0.
y, p1.
y ),
377 const VIA* va =
static_cast<const VIA*
>( aItemA );
378 const VIA* vb =
static_cast<const VIA*
>( aItemB );
384 const LINE* la =
static_cast<const LINE*
> ( aItemA );
385 const LINE* lb =
static_cast<const LINE*
> ( aItemB );
400 std::vector<SHAPE_LINE_CHAIN::INTERSECTION>& ips )
402 std::vector<SHAPE_LINE_CHAIN::INTERSECTION> ips_raw;
415 int d1_idx = 0, d2_idx = 0;
420 if( !p.is_corner_our && !p.is_corner_their )
423 ips.push_back( ipp );
430 if( p.is_corner_our )
432 d1[0] = hull.
CSegment( p.index_our );
433 d1[1] = hull.
CSegment( p.index_our - 1 );
438 d1[0] = hull.
CSegment( p.index_our );
442 if( p.is_corner_their )
444 if( p.index_their > 0 )
446 d2[d2_idx++] = line.
CSegment( p.index_their - 1 ).
A;
450 d2[d2_idx++] = line.
CSegment( p.index_their ).
B;
455 d2[d2_idx++] = line.
CSegment( p.index_their ).
A;
456 d2[d2_idx++] = line.
CSegment( p.index_their ).
B;
459 for(
int i = 0; i < d1_idx; i++ )
461 for(
int j = 0; j < d2_idx; j++ )
463 if( d1[i].Side( d2[j] ) > 0 )
470#ifdef TOM_EXTRA_DEBUG
471 printf(
"p %d %d hi %d their %d co %d ct %d ipv %d\n", p.p.x, p.p.y, p.index_our, p.index_their, p.is_corner_our?1:0, p.is_corner_their?1:0, ipp.
valid ?1:0);
472 printf(
"d1 %d d2 %d\n", d1_idx, d2_idx );
476 ips.push_back( ipp );
483 int aWalkaroundThickness )
485 int cl = aClearance + ( aWalkaroundThickness + 1 )/ 2;
487 switch( aShape->
Type() )
501 int r =
circle->GetRadius();
505 2.0 * ( 1.0 - M_SQRT1_2 ) * ( r + cl ) );
511 return SegmentHull( *seg, aClearance, aWalkaroundThickness );
517 return ArcHull( *arc, aClearance, aWalkaroundThickness );
537 wxFAIL_MSG( wxString::Format( wxT(
"Unsupported hull shape: %d (%s)." ),
553 PNS_DBG( dbg, BeginGroup, wxString::Format(
"node:%s this=%p depth=%d added=%d removed=%d",
554 label, node, node->
Depth(), (
int) added.size(), (
int) removed.size() ),
557 for(
ITEM* item : added )
558 PNS_DBG( dbg, AddItem, item,
BLUE, 10000, wxT(
"added-item" ) );
560 for(
ITEM* item : removed )
561 PNS_DBG( dbg, AddItem, item,
RED, 10000, wxT(
"removed-item" ) );
595 if( s_old->
Seg().
B != aP )
597 std::unique_ptr<SEGMENT> s_new (
Clone( *s_old ) );
598 s_new->SetEnds( s_old->
Seg().
A, aP );
600 aNode->
Add( std::move( s_new ),
true );
603 if( s_old->
Seg().
A != aP )
605 std::unique_ptr<SEGMENT> s_new (
Clone( *s_old ) );
606 s_new->SetEnds( aP, s_old->
Seg().
B );
608 aNode->
Add( std::move( s_new ),
true );
633 ARC* a_old =
static_cast<ARC*
>( aArc );
636 std::unique_ptr<ARC> a_new[2] = {
Clone( *a_old ),
Clone( *a_old ) };
638 a_new[0]->Arc().ConstructFromStartEndCenter( o_arc.
GetP0(), aP, o_arc.
GetCenter(),
641 a_new[1]->Arc().ConstructFromStartEndCenter( aP, o_arc.
GetP1(), o_arc.
GetCenter(),
645 aNode->
Add( std::move( a_new[0] ),
true );
646 aNode->
Add( std::move( a_new[1] ),
true );
657 ret.Append( wxString::Format( wxT(
"%d" ), x.
Min() ) );
659 ret.Append( wxT(
"none" ) );
661 ret.Append( wxT(
" max:" ) );
663 ret.Append( wxString::Format( wxT(
"%d" ), x.
Max() ) );
665 ret.Append( wxT(
"none" ) );
667 ret.Append( wxT(
" opt:" ) );
669 ret.Append( wxString::Format( wxT(
"%d" ), x.
Opt() ) );
671 ret.Append( wxT(
"none" ) );
681 (a.
A - b.
A).SquaredEuclideanNorm(),
682 (a.
A - b.
B).SquaredEuclideanNorm(),
683 (a.
B - b.
A).SquaredEuclideanNorm(),
684 (a.
B - b.
B).SquaredEuclideanNorm()
687 SEG::ecoord maxDist = std::numeric_limits<SEG::ecoord>::min();
690 for(
int i = 0; i < 4; i++ )
692 if ( dists[i] > maxDist )
701 case 0:
return SEG( a.
A, b.
A );
702 case 1:
return SEG( a.
A, b.
B );
703 case 2:
return SEG( a.
B, b.
A );
704 case 3:
return SEG( a.
B, b.
B );
705 default: wxASSERT_MSG(
false, wxT(
"failed to find farthest points?"));
break;
constexpr int ARC_LOW_DEF
std::optional< BOX2I > OPT_BOX2I
constexpr BOX2I KiROUND(const BOX2D &aBoxD)
constexpr const Vec & GetPosition() const
constexpr BOX2< Vec > & Normalize()
Ensure that the height and width are positive.
constexpr coord_type GetY() const
constexpr size_type GetWidth() const
constexpr coord_type GetX() const
constexpr size_type GetHeight() const
constexpr const Vec & GetOrigin() const
constexpr const SizeVec & GetSize() const
Base class for PNS router board items.
bool OfKind(int aKindMask) const
virtual VECTOR2I Anchor(int n) const
A 2D point on a given set of layers and belonging to a certain net, that links together a number of b...
const std::vector< ITEM * > & LinkList() const
int LinkCount(int aMask=-1) const
Represents a track on a PCB, connecting two non-trivial joints (that is, vias, pads,...
OPT_BOX2I ChangedArea(const LINE *aOther) const
Keep the router "world" - i.e.
std::vector< ITEM * > ITEM_VECTOR
void GetUpdatedItems(ITEM_VECTOR &aRemoved, ITEM_VECTOR &aAdded)
Return the list of items removed and added in this branch with respect to the root branch.
const JOINT * FindJoint(const VECTOR2I &aPos, int aLayer, NET_HANDLE aNet) const
Search for a joint at a given position, layer and belonging to given net.
int Depth() const
Return the number of nodes in the inheritance chain (wrs to the root node).
bool Add(std::unique_ptr< SEGMENT > aSegment, bool aAllowRedundant=false)
Add an item to the current node.
void Remove(ARC *aArc)
Remove an item from this branch.
OPT_BOX2I ChangedArea(const VIA *aOther) const
VECTOR2I::extended_type ecoord
int Length() const
Return the length (this).
OPT_VECTOR2I IntersectLines(const SEG &aSeg) const
Compute the intersection point of lines passing through ends of (this) and aSeg.
int Distance(const SEG &aSeg) const
Compute minimum Euclidean distance to segment aSeg.
int Side(const VECTOR2I &aP) const
Determine on which side of directed line passing via segment ends point aP lies.
EDA_ANGLE GetCentralAngle() const
Get the "central angle" of the arc - this is the angle at the point of the "pie slice".
int GetWidth() const override
const SHAPE_LINE_CHAIN ConvertToPolyline(int aMaxError=DefaultAccuracyForPCB(), int *aActualError=nullptr) const
Construct a SHAPE_LINE_CHAIN of segments from a given arc.
const VECTOR2I & GetP1() const
static int DefaultAccuracyForPCB()
const VECTOR2I & GetP0() const
const VECTOR2I & GetCenter() const
SHAPE_TYPE Type() const
Return the type of the shape.
const BOX2I BBox(int aClearance=0) const override
Compute a bounding box of the shape, with a margin of aClearance a collision.
Represent a polyline containing arcs as well as line segments: A chain of connected line and/or arc s...
int Intersect(const SEG &aSeg, std::vector< INTERSECTION > &aIp) const
Find all intersection points between our line chain and the segment aSeg.
const SHAPE_LINE_CHAIN Reverse() const
Reverse point order in the line chain.
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 Append(int aX, int aY, bool aAllowDuplication=false)
Append a new point at the end of the line chain.
const VECTOR2I NearestPoint(const VECTOR2I &aP, bool aAllowInternalShapePoints=true) const
Find a point on the line chain that is closest to point aP.
int SegmentCount() const
Return the number of segments in this line chain.
const SEG CSegment(int aIndex) const
Return a constant copy of the aIndex segment in the line chain.
const VECTOR2I & GetPosition() const
const VECTOR2I GetSize() const
const SEG & GetSeg() const
int GetWidth() const override
Represent a simple polygon consisting of a zero-thickness closed chain of connected line segments.
const SHAPE_LINE_CHAIN & Vertices() const
Return the list of vertices defining this simple polygon.
const BOX2I BBox(int aClearance=0) const override
Compute a bounding box of the shape, with a margin of aClearance a collision.
An abstract shape on 2D plane.
constexpr VECTOR2< T > Perpendicular() const
Compute the perpendicular vector.
VECTOR2< T > Resize(T aNewLength) const
Return a vector of the same direction, but length specified in aNewLength.
Push and Shove diff pair dimensions (gap) settings dialog.
const wxString Format(const MINOPTMAX< int > x)
bool SplitAdjacentSegments(NODE *aNode, ITEM *aSeg, const VECTOR2I &aP)
Snaps the point aP to segment aSeg.
const SHAPE_LINE_CHAIN BuildHullForPrimitiveShape(const SHAPE *aShape, int aClearance, int aWalkaroundThickness)
const SHAPE_LINE_CHAIN OctagonalHull(const VECTOR2I &aP0, const VECTOR2I &aSize, int aClearance, int aChamfer)
SHAPE_RECT ApproximateSegmentAsRect(const SHAPE_SEGMENT &aSeg)
bool SplitAdjacentArcs(NODE *aNode, ITEM *aArc, const VECTOR2I &aP)
Snaps the point aP to arc aArc.
const SHAPE_LINE_CHAIN ArcHull(const SHAPE_ARC &aArc, int aClearance, int aWalkaroundThickness)
Various utility functions.
const SHAPE_LINE_CHAIN ConvexHull(const SHAPE_SIMPLE &aConvex, int aClearance)
Function ConvexHull()
void NodeStats(DEBUG_DECORATOR *dbg, wxString label, PNS::NODE *node)
const SHAPE_LINE_CHAIN SegmentHull(const SHAPE_SEGMENT &aSeg, int aClearance, int aWalkaroundThickness)
static bool IsSegment45Degree(const SEG &aS)
static void MoveDiagonal(SEG &aDiagonal, const SHAPE_LINE_CHAIN &aVertices, int aClearance)
void HullIntersection(const SHAPE_LINE_CHAIN &hull, const SHAPE_LINE_CHAIN &line, std::vector< SHAPE_LINE_CHAIN::INTERSECTION > &ips)
OPT_BOX2I ChangedArea(const ITEM *aItemA, const ITEM *aItemB)
std::unique_ptr< typename std::remove_const< T >::type > Clone(const T &aItem)
const SEG LongestCoveringSegment(const SEG &a, const SEG &b)
bool contains(const _Container &__container, _Value __value)
Returns true if the container contains the given value.
EDA_ANGLE abs(const EDA_ANGLE &aAngle)
#define PNS_DBG(dbg, method,...)
#define PNS_DBGN(dbg, method)
@ SH_RECT
axis-aligned rectangle
@ SH_SIMPLE
simple polygon
@ SH_ELLIPSE
ellipse or elliptical arc
static wxString SHAPE_TYPE_asString(SHAPE_TYPE a)
Represent an intersection between two line segments.
bool valid
Auxiliary flag to avoid copying intersection info to intersection refining code, used by the refining...
SHAPE_CIRCLE circle(c.m_circle_center, c.m_circle_radius)
VECTOR2< int32_t > VECTOR2I