44 int aClearance,
int aChamfer )
50 s.
Append( aP0.
x - aClearance, aP0.
y - aClearance + aChamfer );
53 s.
Append( aP0.
x - aClearance + aChamfer, aP0.
y - aClearance );
55 s.
Append( aP0.
x + aSize.
x + aClearance - aChamfer, aP0.
y - aClearance );
58 s.
Append( aP0.
x + aSize.
x + aClearance, aP0.
y - aClearance + aChamfer );
60 s.
Append( aP0.
x + aSize.
x + aClearance, aP0.
y + aSize.
y + aClearance - aChamfer );
63 s.
Append( aP0.
x + aSize.
x + aClearance - aChamfer, aP0.
y + aSize.
y + aClearance );
65 s.
Append( aP0.
x - aClearance + aChamfer, aP0.
y + aSize.
y + aClearance );
68 s.
Append( aP0.
x - aClearance, aP0.
y + aSize.
y + aClearance - aChamfer );
76 int cl = aClearance + ( aWalkaroundThickness + 1 ) / 2;
85 2.0 * ( 1.0 - M_SQRT1_2 ) * ( r + cl ) );
89 int x = (int) ( 2.0 / ( 1.0 + M_SQRT2 ) * d ) / 2;
95 std::vector<VECTOR2I> reverse_line;
97 auto seg = line.Segment( 0 );
105 s.
Append( seg.A + p0 - pd );
106 s.
Append( seg.A - dp + ds );
107 s.
Append( seg.A - dp - ds );
108 s.
Append( seg.A - p0 - pd );
110 for(
int i = 1; i < line.SegmentCount(); i++ )
114 ( line.CSegment( i - 1 ).
B - line.CSegment( i - 1 ).
A ).Perpendicular().Resize( d );
115 auto pp2 = ( line.CSegment( i ).
B - line.CSegment( i ).
A ).Perpendicular().Resize( d );
117 auto sa_out = line.CSegment( i - 1 ), sa_in = line.CSegment( i - 1 );
118 auto sb_out = line.CSegment( i ), sb_in = line.CSegment( i );
130 auto ip_out = sa_out.IntersectLines( sb_out );
131 auto ip_in = sa_in.IntersectLines( sb_in );
133 seg = line.CSegment( i );
135 reverse_line.push_back( *ip_in );
138 seg = line.CSegment( -1 );
144 s.
Append( seg.B - p0 + pd );
145 s.
Append( seg.B + dp - ds );
146 s.
Append( seg.B + dp + ds );
147 s.
Append( seg.B + p0 + pd );
149 for(
int i = reverse_line.size() - 1; i >= 0; i-- )
150 s.
Append( reverse_line[i] );
179template <
typename T>
int sgn(
T val) {
180 return (
T(0) < val) - (val <
T(0));
185 int aWalkaroundThickness )
187 const int kinkThreshold = aClearance / 10;
189 int cl = aClearance + aWalkaroundThickness / 2;
190 double d = (double)aSeg.
GetWidth() / 2.0 + cl;
191 double x = 2.0 / ( 1.0 + M_SQRT2 ) * d;
214 if ( len <= kinkThreshold && len > 0 )
223 if( len <= kinkThreshold )
236 else if ( delta45 <= 2 )
255 int xx2 =
KiROUND( 2.0 * ( 1.0 - M_SQRT1_2 ) * d );
297 VECTOR2I moveBy = ( aDiagonal.
A - aDiagonal.
B ).Perpendicular().Resize( dist - aClearance );
298 aDiagonal.
A += moveBy;
299 aDiagonal.
B += moveBy;
321 SEG toprightline =
SEG( corner,
333 SEG bottomleftline =
SEG( corner,
367 return SHAPE_RECT( std::min( p0.
x, p1.
x ), std::min( p0.
y, p1.
y ),
376 const VIA* va =
static_cast<const VIA*
>( aItemA );
377 const VIA* vb =
static_cast<const VIA*
>( aItemB );
383 const LINE* la =
static_cast<const LINE*
> ( aItemA );
384 const LINE* lb =
static_cast<const LINE*
> ( aItemB );
408 for(
auto& p : ips_raw )
414 int d1_idx = 0, d2_idx = 0;
419 if( !p.is_corner_our && !p.is_corner_their )
422 ips.push_back( ipp );
429 if( p.is_corner_our )
431 d1[0] = hull.
CSegment( p.index_our );
432 d1[1] = hull.
CSegment( p.index_our - 1 );
437 d1[0] = hull.
CSegment( p.index_our );
441 if( p.is_corner_their )
443 if( p.index_their > 0 )
445 d2[d2_idx++] = line.
CSegment( p.index_their - 1 ).
A;
449 d2[d2_idx++] = line.
CSegment( p.index_their ).
B;
454 d2[d2_idx++] = line.
CSegment( p.index_their ).
A;
455 d2[d2_idx++] = line.
CSegment( p.index_their ).
B;
458 for(
int i = 0; i < d1_idx; i++ )
460 for(
int j = 0; j < d2_idx; j++ )
462 if( d1[i].Side( d2[j] ) > 0 )
469#ifdef TOM_EXTRA_DEBUG
470 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);
471 printf(
"d1 %d d2 %d\n", d1_idx, d2_idx );
475 ips.push_back( ipp );
482 int aWalkaroundThickness )
484 int cl = aClearance + ( aWalkaroundThickness + 1 )/ 2;
486 switch( aShape->
Type() )
500 int r =
circle->GetRadius();
504 2.0 * ( 1.0 - M_SQRT1_2 ) * ( r + cl ) );
510 return SegmentHull( *seg, aClearance, aWalkaroundThickness );
516 return ArcHull( *arc, aClearance, aWalkaroundThickness );
536 wxFAIL_MSG( wxString::Format( wxT(
"Unsupported hull shape: %d (%s)." ),
552 PNS_DBG( dbg, BeginGroup, wxString::Format(
"node:%s this=%p depth=%d added=%d removed=%d",
553 label, node, node->
Depth(), (
int)added.size(), (
int) removed.size() ), 0 );
555 for(
auto& item : added )
556 PNS_DBG( dbg, AddItem, item,
BLUE, 10000, wxT(
"added-item") );
557 for(
auto& item : removed )
558 PNS_DBG( dbg, AddItem, item,
RED, 10000, wxString::Format(
"removed-item") );
586 if( s_old->
Seg().
B != aP )
588 std::unique_ptr<SEGMENT> s_new (
Clone( *s_old ) );
589 s_new->SetEnds( s_old->
Seg().
A, aP );
591 aNode->
Add( std::move( s_new ),
true );
594 if( s_old->
Seg().
A != aP )
596 std::unique_ptr<SEGMENT> s_new (
Clone( *s_old ) );
597 s_new->SetEnds( aP, s_old->
Seg().
B );
599 aNode->
Add( std::move( s_new ),
true );
619 ARC* a_old =
static_cast<ARC*
>( aArc );
622 std::unique_ptr<ARC> a_new[2] = {
Clone( *a_old ),
Clone( *a_old ) };
624 a_new[0]->Arc().ConstructFromStartEndCenter( o_arc.
GetP0(), aP, o_arc.
GetCenter(),
627 a_new[1]->Arc().ConstructFromStartEndCenter( aP, o_arc.
GetP1(), o_arc.
GetCenter(),
631 aNode->
Add( std::move( a_new[0] ),
true );
632 aNode->
Add( std::move( a_new[1] ),
true );
643 ret.Append( wxString::Format( wxT(
"%d" ), x.
Min() ) );
645 ret.Append( wxT(
"none" ) );
647 ret.Append( wxT(
" max:" ) );
649 ret.Append( wxString::Format( wxT(
"%d" ), x.
Max() ) );
651 ret.Append( wxT(
"none" ) );
653 ret.Append( wxT(
" opt:" ) );
655 ret.Append( wxString::Format( wxT(
"%d" ), x.
Opt() ) );
657 ret.Append( wxT(
"none" ) );
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
A 2D point on a given set of layers and belonging to a certain net, that links together a number of b...
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.
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
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...
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 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.
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.
std::vector< INTERSECTION > INTERSECTIONS
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.
void HullIntersection(const SHAPE_LINE_CHAIN &hull, const SHAPE_LINE_CHAIN &line, SHAPE_LINE_CHAIN::INTERSECTIONS &ips)
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)
OPT_BOX2I ChangedArea(const ITEM *aItemA, const ITEM *aItemB)
std::unique_ptr< typename std::remove_const< T >::type > Clone(const T &aItem)
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