47 switch( dir_a.Angle( dir_b ) )
100 double aCornerTolerance )
const
175 auto links = aLine->
Links();
180 for(
int i = aStartVertex; i < aEndVertex - 1; i++ )
207 if( i->second.m_isStatic )
231 if( aVertex1 < aCurrentPath.
PointCount() - 1 && !p1_in && p2_in
254 for(
int i = aVertex1; i < aVertex2; i++ )
292 LINE newPath( *aOriginLine, aCurrentPath );
293 newPath.
Line().
Replace( aVertex1, aVertex2, aReplacement );
328 for(
size_t i = 1; i <= cnt; ++i )
332 if( ipNext.
y == aP.
y )
334 if( ( ipNext.
x == aP.
x )
335 || ( ip.
y == aP.
y && ( ( ipNext.
x > aP.
x ) == ( ip.
x < aP.
x ) ) ) )
339 if( ( ip.
y < aP.
y ) != ( ipNext.
y < aP.
y ) )
349 double d =
static_cast<double>( ip.
x - aP.
x ) *
350 static_cast<double>( ipNext.
y - aP.
y ) -
351 static_cast<double>( ipNext.
x - aP.
x ) *
352 static_cast<double>( ip.
y - aP.
y );
357 if( ( d > 0 ) == ( ipNext.
y > ip.
y ) )
365 double d = ( (double) ip.
x - aP.
x ) * ( (
double) ipNext.
y - aP.
y )
366 - ( (double) ipNext.
x - aP.
x ) * ( (
double) ip.
y - aP.
y );
371 if( ( d > 0 ) == ( ipNext.
y > ip.
y ) )
395 std::vector<JOINT*> joints;
402 for(
JOINT* j : joints )
404 if( j->Net() == aOriginLine->
Net() )
409 bool falsePositive =
false;
411 for(
int k = 0; k < encPoly.
PointCount(); k++ )
413 if( encPoly.
CPoint(k) == j->Pos() )
415 falsePositive =
true;
436 return static_cast<bool>(
m_world->CheckColliding( aItem ) );
452 if( !c->Check( aVertex1, aVertex2, aOriginLine, aCurrentPath, aReplacement ) )
462 LINE tmp( *aLine, aOptPath );
485 int max_step = n_segs - 2;
487 if( step > max_step )
492 line = std::move( current_path );
496 bool found_anything =
false;
498 for(
int n = 0; n < n_segs - step; n++ )
508 s1opt =
SEG( s1.
A, ip );
509 s2opt =
SEG( ip, s2.
B );
518 LINE opt_track( *aLine, opt_path );
526 found_anything =
true;
533 if( !found_anything )
537 line = std::move( current_path );
564 int max_step = n_segs - 2;
566 if( step > max_step )
572 bool found_anything =
mergeStep( aLine, current_path, step );
574 if( !found_anything )
593 for(
int segIdx = 0; segIdx < line.
SegmentCount() - 1; ++segIdx )
604 line.
Remove( segIdx + 1 );
634 int rootObtuseCorners = aRoot->
CountCorners( angleMask );
710 for(
int n = 0; n < n_segs - step; n++ )
714 || aCurrentPath.
IsArcSegment(
static_cast<std::size_t
>( n ) + step ) )
726 for(
int i = 0; i < 2; i++ )
740 path[i] = aCurrentPath;
747 if( cost[0] < cost_orig && cost[0] < cost[1] )
749 else if( cost[1] < cost_orig )
755 aCurrentPath = *picked;
765 bool aPermitDiagonal )
const
780 breakouts.push_back( l );
788 bool aPermitDiagonal )
const
823 l.
Append( intersections[0].p );
825 breakouts.push_back( l );
834 bool aPermitDiagonal )
const
841 breakouts.reserve( 12 );
845 d_offset.
x = ( s.
x > s.
y ) ? ( s.
x - s.
y ) / 2 : 0;
846 d_offset.
y = ( s.
x < s.
y ) ? ( s.
y - s.
x ) / 2 : 0;
856 if( aPermitDiagonal )
858 int l = aWidth + std::min( s.
x, s.
y ) / 2;
863 breakouts.emplace_back(
865 breakouts.emplace_back(
867 breakouts.emplace_back(
869 breakouts.emplace_back(
875 breakouts.emplace_back(
877 breakouts.emplace_back(
879 breakouts.emplace_back(
881 breakouts.emplace_back(
891 bool aPermitDiagonal )
const
893 switch( aItem->
Kind() )
897 const VIA*
via =
static_cast<const VIA*
>( aItem );
906 switch( shape->
Type() )
941 const JOINT* jt =
m_world->FindJoint( aP, aLayer, aNet );
963 typedef std::tuple<int, long long int, SHAPE_LINE_CHAIN> RtVariant;
964 std::vector<RtVariant> variants;
979 int p_end = std::min( aEndVertex, std::min( 3, line.
PointCount() - 1 ) );
982 for(
int p = 1; p <= p_end; p++ )
993 for(
int diag = 0; diag < 2; diag++ )
997 breakout.CLastPoint(), line.
CPoint( p ), diag == 0 );
1006 if( ang1 & ForbiddenAngles )
1009 if( breakout.Length() > line.
Length() )
1015 for(
int i = p + 1; i < line.
PointCount(); i++ )
1018 LINE tmp( *aLine, v );
1024 std::get<0>( vp ) = p;
1025 std::get<1>( vp ) = breakout.Length();
1026 std::get<2>( vp ) = aEnd ? v.
Reverse() : v;
1028 variants.push_back( std::move( vp ) );
1040 long long int max_length = 0;
1045 for( RtVariant& vp : variants )
1047 LINE tmp( *aLine, std::get<2>( vp ) );
1049 long long int len = std::get<1>( vp );
1053 if( cost < min_cost || ( cost == min_cost && len > max_length ) )
1055 l_best = std::get<2>( vp );
1056 p_best = std::get<0>( vp );
1059 if( cost <= min_cost )
1060 max_length = std::max<int>( len, max_length );
1062 min_cost = std::min( cost, min_cost );
1108 opt.SetEffortLevel( aEffortLevel );
1109 opt.SetCollisionMask( -1 );
1112 opt.SetPreserveVertex( aV );
1115 return opt.Optimize( &tmp, aLine );
1131 int thr = aLine->
Width() * 10;
1138 bool endMatch =
false;
1149 if( startMatch && endMatch && len < thr )
1151 for(
int i = 0; i < 2; i++ )
1155 repl =
LINE( *aLine, l2 );
1157 if( !
m_world->CheckColliding( &repl ) )
1182 int64_t{ ( ( projOverCoupled - aVertex ).EuclideanNorm() ) } - aPair->
Width();
1199 LINE refLine ( aRefIsP ? aPair->
PLine() : aPair->
NLine(), aNewRef );
1200 LINE coupledLine ( aRefIsP ? aPair->
NLine() : aPair->
PLine(), aNewCoupled );
1202 if( refLine.
Collide( &coupledLine, aNode, refLine.
Layer() ) )
1219 int vStartIdx[1024];
1222 aCoupled, aPair, vStartIdx );
1225 int64_t bestLength = -1;
1230 for(
int i=0; i< nStarts; i++ )
1232 for(
int j = 1; j < aCoupled.
PointCount() - 1; j++ )
1242 int64_t coupledLength = aPair->
CoupledLength( aRef, bypass );
1250 newCoupled.
Replace( si, ei, bypass );
1254 if( coupledLength > bestLength &&
verifyDpBypass( aNode, aPair, aRefIsP, aRef,
1257 bestBypass = std::move( newCoupled );
1258 bestLength = coupledLength;
1266 aNewCoupled = std::move( bestBypass );
1289 int64_t clenPre = aPair->
CoupledLength( currentPath, coupledPath );
1290 int64_t budget = clenPre / 10;
1292 while( n < n_segs - step )
1306 int64_t deltaCoupled = -1, deltaUni = -1;
1308 newRef = currentPath;
1311 deltaUni = aPair->
CoupledLength ( newRef, coupledPath ) - clenPre + budget;
1315 deltaCoupled = aPair->
CoupledLength( newRef, newCoup ) - clenPre + budget;
1317 if( deltaCoupled >= 0 )
1322 aPair->
SetShape( newRef, newCoup, !aTryP );
1331 aPair->
SetShape( newRef, coupledPath, !aTryP );
1353 int max_step_p = n_segs_p - 2;
1354 int max_step_n = n_segs_n - 2;
1356 if( step_p > max_step_p )
1357 step_p = max_step_p;
1359 if( step_n > max_step_n )
1360 step_n = max_step_n;
1362 if( step_p < 1 && step_n < 1 )
1365 bool found_anything_p =
false;
1366 bool found_anything_n =
false;
1369 found_anything_p =
mergeDpStep( aPair,
true, step_p );
1372 found_anything_n =
mergeDpStep( aPair,
false, step_n );
1374 if( !found_anything_n && !found_anything_p )
1395 const int total = oc + nc;
1397 for(
int i = 0; i < total; i++)
1399 int i_next = (i + 1 == total ? 0 : i + 1);
1402 : aNew.
CPoint( nc - 1 - (i - oc) );
1404 : aNew.
CPoint( nc - 1 - (i_next - oc) );
1405 area += -(int64_t) v0.
y *
v1.x + (int64_t) v0.
x *
v1.y;
1468 initial = guide.
Length();
1490 else if ( current + step >= initial )
1499 if ( current == initial )
1505 out = std::move( snew );
1520 for(
int step = 0; step < 3; step++ )
1528 l_in = current.
Slice( i, i + 3 );
1530 for(
int dir = 0; dir <= 1; dir++ )
1532 if(
tightenSegment( dir ?
true :
false, aNode, aNewLine, l_in, l_out ) )
1535 opt.
Replace( i, i + 3, l_out );
1539 if( optArea < prevArea )
1540 current = std::move( opt );
1548 aOptimized =
LINE( aNewLine, current );
constexpr size_type GetWidth() const
constexpr size_type GetHeight() const
Represent route directions & corner angles in a 45-degree metric.
const SHAPE_LINE_CHAIN BuildInitialTrace(const VECTOR2I &aP0, const VECTOR2I &aP1, bool aStartDiagonal=false, CORNER_MODE aMode=CORNER_MODE::MITERED_45) const
Build a 2-segment line chain between points aP0 and aP1 and following 45-degree routing regime.
AngleType Angle(const DIRECTION_45 &aOther) const
Return the type of angle between directions (this) and aOther.
bool IsDiagonal() const
Returns true if the direction is diagonal (e.g.
@ ROUNDED_90
H/V with filleted corners.
@ MITERED_90
H/V only (90-degree corners)
bool IsObtuse(const DIRECTION_45 &aOther) const
bool IsHorizontal() const
bool Check(int aVertex1, int aVertex2, const LINE *aOriginLine, const SHAPE_LINE_CHAIN &aCurrentPath, const SHAPE_LINE_CHAIN &aReplacement) override
virtual bool Check(int aVertex1, int aVertex2, const LINE *aOriginLine, const SHAPE_LINE_CHAIN &aCurrentPath, const SHAPE_LINE_CHAIN &aReplacement) override
static int CornerCost(const SHAPE_LINE_CHAIN &aLine)
void Replace(const LINE &aOldLine, const LINE &aNewLine)
void Remove(const LINE &aLine)
void Add(const LINE &aLine)
static int CornerCost(const SEG &aA, const SEG &aB)
bool IsBetter(const COST_ESTIMATOR &aOther, double aLengthTolerance, double aCornerTollerace) const
Basic class for a differential pair.
const SHAPE_LINE_CHAIN & CN() const
const RANGED_NUM< int > GapConstraint() const
double CoupledLength() const
void SetShape(const SHAPE_LINE_CHAIN &aP, const SHAPE_LINE_CHAIN &aN, bool aSwapLanes=false)
const SHAPE_LINE_CHAIN & CP() const
Base class for PNS router board items.
virtual const SHAPE * Shape(int aLayer) const
Return the geometrical shape of the item.
const PNS_LAYER_RANGE & Layers() const
virtual NET_HANDLE Net() const
PnsKind Kind() const
Return the type (kind) of the item.
virtual int Layer() const
bool Collide(const ITEM *aHead, const NODE *aNode, int aLayer, COLLISION_SEARCH_CONTEXT *aCtx=nullptr) const
Check for a collision (clearance violation) with between us and item aOther.
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...
const std::vector< ITEM * > & LinkList() const
bool Check(int aVertex1, int aVertex2, const LINE *aOriginLine, const SHAPE_LINE_CHAIN &aCurrentPath, const SHAPE_LINE_CHAIN &aReplacement) override
Represents a track on a PCB, connecting two non-trivial joints (that is, vias, pads,...
const VECTOR2I & CPoint(int aIdx) const
void SetShape(const SHAPE_LINE_CHAIN &aLine)
Return the shape of the line.
const SHAPE_LINE_CHAIN & CLine() const
const VECTOR2I & CLastPoint() const
int CountCorners(int aAngles) const
SHAPE_LINE_CHAIN & Line()
const SEG CSegment(int aIdx) const
Set line width.
int Width() const
Return true if the line is geometrically identical as line aOther.
bool IsLinked() const
Check if the segment aLink is a part of the line.
std::vector< LINKED_ITEM * > & Links()
virtual void ClearLinks()
Return the number of segments that were assembled together to form this line.
Keep the router "world" - i.e.
OPT_OBSTACLE CheckColliding(const ITEM *aItem, int aKindMask=ITEM::ANY_T)
Check if the item collides with anything else in the world, and if found, returns the obstacle.
std::pair< int, int > m_restrictedVertexRange
std::vector< OPT_CONSTRAINT * > m_constraints
~OPTIMIZER()
A quick shortcut to optimize a line without creating and setting up an optimizer.
bool mergeColinear(LINE *aLine)
void cacheAdd(ITEM *aItem, bool aIsStatic)
void removeCachedSegments(LINE *aLine, int aStartVertex=0, int aEndVertex=-1)
bool m_restrictAreaIsStrict
BREAKOUT_LIST computeBreakouts(int aWidth, const ITEM *aItem, bool aPermitDiagonal) const
bool fanoutCleanup(LINE *aLine)
std::vector< SHAPE_LINE_CHAIN > BREAKOUT_LIST
bool mergeFull(LINE *aLine)
bool mergeStep(LINE *aLine, SHAPE_LINE_CHAIN &aCurrentLine, int step)
bool mergeDpStep(DIFF_PAIR *aPair, bool aTryP, int step)
void CacheRemove(ITEM *aItem)
bool mergeObtuse(LINE *aLine)
bool checkConstraints(int aVertex1, int aVertex2, LINE *aOriginLine, const SHAPE_LINE_CHAIN &aCurrentPath, const SHAPE_LINE_CHAIN &aReplacement)
bool checkColliding(ITEM *aItem, bool aUpdateCache=true)
std::unordered_map< ITEM *, CACHED_ITEM > m_cacheTags
bool runSmartPads(LINE *aLine)
bool mergeDpSegments(DIFF_PAIR *aPair)
int smartPadsSingle(LINE *aLine, ITEM *aPad, bool aEnd, int aEndVertex)
ITEM * findPadOrVia(int aLayer, NET_HANDLE aNet, const VECTOR2I &aP) const
BREAKOUT_LIST rectBreakouts(int aWidth, const SHAPE *aShape, bool aPermitDiagonal) const
BREAKOUT_LIST customBreakouts(int aWidth, const ITEM *aItem, bool aPermitDiagonal) const
BREAKOUT_LIST circleBreakouts(int aWidth, const SHAPE *aShape, bool aPermitDiagonal) const
VECTOR2I m_preservedVertex
static bool Optimize(LINE *aLine, int aEffortLevel, NODE *aWorld, const VECTOR2I &aV=VECTOR2I(0, 0))
void addConstraint(OPT_CONSTRAINT *aConstraint)
void ClearCache(bool aStaticOnly=false)
@ LIMIT_CORNER_COUNT
Do not attempt to optimize if the resulting line's corner count is outside the predefined range.
@ SMART_PADS
Reroute pad exits.
@ FANOUT_CLEANUP
Simplify pad-pad and pad-via connections if possible.
@ MERGE_SEGMENTS
Reduce corner cost iteratively.
@ MERGE_COLINEAR
Merge co-linear segments.
@ MERGE_OBTUSE
Reduce corner cost by merging obtuse segments.
SHAPE_INDEX_LIST< ITEM * > m_cache
bool Check(int aVertex1, int aVertex2, const LINE *aOriginLine, const SHAPE_LINE_CHAIN &aCurrentPath, const SHAPE_LINE_CHAIN &aReplacement) override
virtual bool Check(int aVertex1, int aVertex2, const LINE *aOriginLine, const SHAPE_LINE_CHAIN &aCurrentPath, const SHAPE_LINE_CHAIN &aReplacement) override
virtual DEBUG_DECORATOR * GetDebugDecorator()=0
ROUTER_IFACE * GetInterface() const
ROUTING_SETTINGS & Settings()
static ROUTER * GetInstance()
DIRECTION_45::CORNER_MODE GetCornerMode() const
const SHAPE * Shape(int aLayer) const override
Return the geometrical shape of the item.
bool Matches(const T &aOther) const
ecoord SquaredDistance(const SEG &aSeg) const
VECTOR2I::extended_type ecoord
int Index() const
Return the index of this segment in its parent shape (applicable only to non-local segments).
int Length() const
Return the length (this).
bool ApproxParallel(const SEG &aSeg, int aDistanceThreshold=1) const
bool Collinear(const SEG &aSeg) const
Check if segment aSeg lies on the same line as (this).
OPT_VECTOR2I IntersectLines(const SEG &aSeg) const
Compute the intersection point of lines passing through ends of (this) and aSeg.
ecoord SquaredLength() const
VECTOR2I LineProject(const VECTOR2I &aP) const
Compute the perpendicular projection point of aP on a line passing through ends of the segment.
EDA_ANGLE Angle(const SEG &aOther) const
Determine the smallest angle between two segments.
SHAPE_TYPE Type() const
Return the type of the shape.
const VECTOR2I GetCenter() const
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.
bool IsPtOnArc(size_t aPtIndex) const
bool IsClosed() const override
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 Replace(int aStartIndex, int aEndIndex, const VECTOR2I &aP)
Replace points with indices in range [start_index, end_index] with a single point aP.
void Clear()
Remove all points from the line chain.
SHAPE_LINE_CHAIN & Simplify2(bool aRemoveColinear=true)
void Append(int aX, int aY, bool aAllowDuplication=false)
Append a new point at the end of the line chain.
const VECTOR2I & CPoint(int aIndex) const
Return a reference to a given point in the line chain.
const SHAPE_LINE_CHAIN Slice(int aStartIndex, int aEndIndex) const
Return a subset of this line chain containing the [start_index, end_index] range of points.
int SegmentCount() const
Return the number of segments in this line chain.
const VECTOR2I & CLastPoint() const
Return the last point in the line chain.
void Remove(int aStartIndex, int aEndIndex)
Remove the range of points [start_index, end_index] from the line chain.
const SEG CSegment(int aIndex) const
Return a constant copy of the aIndex segment in the line chain.
bool IsArcSegment(size_t aSegment) const
std::vector< INTERSECTION > INTERSECTIONS
long long int Length() const
Return length of the line chain in Euclidean metric.
const BOX2I BBox(int aClearance=0) const override
Compute a bounding box of the shape, with a margin of aClearance a collision.
const VECTOR2I & GetPosition() const
const VECTOR2I GetSize() const
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.
virtual bool Collide(const VECTOR2I &aP, int aClearance=0, int *aActual=nullptr, VECTOR2I *aLocation=nullptr) const
Check if the boundary of shape (this) lies closer to the point aP than aClearance,...
VECTOR2< T > Resize(T aNewLength) const
Return a vector of the same direction, but length specified in aNewLength.
static constexpr EDA_ANGLE ANGLE_0
static constexpr EDA_ANGLE ANGLE_90
static constexpr EDA_ANGLE ANGLE_45
static constexpr EDA_ANGLE ANGLE_360
Push and Shove diff pair dimensions (gap) settings dialog.
bool tightenSegment(bool dir, NODE *aNode, const LINE &cur, const SHAPE_LINE_CHAIN &in, SHAPE_LINE_CHAIN &out)
SHAPE_RECT ApproximateSegmentAsRect(const SHAPE_SEGMENT &aSeg)
int findCoupledVertices(const VECTOR2I &aVertex, const SEG &aOrigSeg, const SHAPE_LINE_CHAIN &aCoupled, DIFF_PAIR *aPair, int *aIndices)
bool coupledBypass(NODE *aNode, DIFF_PAIR *aPair, bool aRefIsP, const SHAPE_LINE_CHAIN &aRef, const SHAPE_LINE_CHAIN &aRefBypass, const SHAPE_LINE_CHAIN &aCoupled, SHAPE_LINE_CHAIN &aNewCoupled)
void Tighten(NODE *aNode, const SHAPE_LINE_CHAIN &aOldLine, const LINE &aNewLine, LINE &aOptimized)
bool verifyDpBypass(NODE *aNode, DIFF_PAIR *aPair, bool aRefIsP, const SHAPE_LINE_CHAIN &aNewRef, const SHAPE_LINE_CHAIN &aNewCoupled)
bool checkDpColliding(NODE *aNode, DIFF_PAIR *aPair, bool aIsP, const SHAPE_LINE_CHAIN &aPath)
static bool pointInside2(const SHAPE_LINE_CHAIN &aL, const VECTOR2I &aP)
Determine if a point is located within a given polygon.
static int64_t shovedArea(const SHAPE_LINE_CHAIN &aOld, const SHAPE_LINE_CHAIN &aNew)
static DIRECTION_45::AngleType angle(const VECTOR2I &a, const VECTOR2I &b)
EDA_ANGLE abs(const EDA_ANGLE &aAngle)
@ SH_RECT
axis-aligned rectangle
@ SH_SIMPLE
simple polygon
bool operator()(ITEM *aOtherItem)
CACHE_VISITOR(const ITEM *aOurItem, NODE *aNode, int aMask)
wxString result
Test unit parsing edge cases and error handling.
void RotatePoint(int *pX, int *pY, const EDA_ANGLE &aAngle)
Calculate the new point of coord coord pX, pY, for a rotation center 0, 0.
Casted dyn_cast(From aObject)
A lightweight dynamic downcast.
VECTOR2< int32_t > VECTOR2I