55 LINE l =
m_world->AssembleLine( root,
nullptr,
false,
false,
false );
75 std::deque<const JOINT*> searchQueue;
78 searchQueue.push_back( aStart );
79 processed.insert( aStart );
81 while( !searchQueue.empty() )
83 const JOINT* current = searchQueue.front();
84 searchQueue.pop_front();
90 const JOINT* a =
m_world->FindJoint( item->Anchor( 0 ), item );;
91 const JOINT* b =
m_world->FindJoint( item->Anchor( 1 ), item );;
92 const JOINT*
next = ( *a == *current ) ? b : a;
94 if( processed.find(
next ) == processed.end() )
96 processed.insert(
next );
97 searchQueue.push_back(
next );
110 LINE track( *aTrack );
116 std::unique_ptr<NODE> tmpNode(
m_world->Branch() );
119 tmpNode->Add( track );
123 if( !jt ||
m_world->GetRuleResolver()->NetCode( jt->
Net() ) <= 0 )
172 std::set<ITEM*> disconnected;
174 m_world->AllItemsInNet( aStart->
Net(), disconnected );
178 for(
ITEM* link : jt->LinkList() )
180 if( disconnected.find( link ) != disconnected.end() )
181 disconnected.erase( link );
185 int best_dist = INT_MAX;
186 ITEM* best =
nullptr;
188 for(
ITEM* item : disconnected )
190 if( item->OfKind( aKindMask ) )
192 for(
int i = 0; i < item->AnchorCount(); i++ )
195 int d = ( p - aStart->
Pos() ).EuclideanNorm();
214 std::set<ITEM*>& aVisited,
215 bool aFollowLockedSegments )
217 using clock = std::chrono::steady_clock;
220 best.
m_end = aStartJoint;
223 auto startTime = clock::now();
233 std::set<const JOINT*> visitedJoints;
237 std::stack<STATE> stateStack;
241 initial.joint = aStartJoint;
242 initial.prev = aPrev;
243 initial.pathLength = 0;
244 initial.visitedJoints.insert( aStartJoint );
245 initial.via =
nullptr;
247 stateStack.push( std::move( initial ) );
249 while( !stateStack.empty() )
252 auto elapsed = std::chrono::duration_cast<std::chrono::milliseconds>(
253 clock::now() - startTime ).count();
255 if( elapsed > timeoutMs )
257 wxLogTrace( wxT(
"PNS_TUNE" ),
258 wxT(
"followBranch: timeout after %lld ms, returning best path found" ),
263 STATE current = std::move( stateStack.top() );
266 const JOINT* joint = current.joint;
272 for(
ITEM* link : links )
274 if( link->OfKind(
ITEM::VIA_T ) && !aVisited.contains( link ) )
282 bool foundBranch =
false;
284 for(
ITEM* link : links )
289 if( link == current.prev )
292 if( aVisited.contains( link ) )
296 false, aFollowLockedSegments );
304 if( current.visitedJoints.count( nextJoint ) )
311 nextState.joint = nextJoint;
312 nextState.prev = l.
Links().back();
313 nextState.pathItems = current.pathItems;
314 nextState.pathLength = current.pathLength + l.
CLine().
Length();
315 nextState.visitedJoints = current.visitedJoints;
316 nextState.visitedJoints.insert( nextJoint );
321 nextState.pathItems.Add(
via );
323 nextState.pathItems.Add( l );
325 stateStack.push( std::move( nextState ) );
331 if( current.pathLength > best.
m_length )
335 best.
m_items = current.pathItems;
340 wxLogTrace( wxT(
"PNS_TUNE" ),
341 wxT(
"followBranch: completed with best path length=%d, %d items" ),
349 const JOINT** aTerminalJointB,
350 bool aFollowLockedSegments )
354 wxLogTrace( wxT(
"PNS_TUNE" ), wxT(
"=== followTrivialPath START ===" ) );
355 wxLogTrace( wxT(
"PNS_TUNE" ), wxT(
"followTrivialPath: initial line has %d segments, %zu links" ),
357 wxLogTrace( wxT(
"PNS_TUNE" ), wxT(
"followTrivialPath: line endpoints: (%d,%d) to (%d,%d)" ),
364 std::set<ITEM*> visited;
367 visited.insert( link );
372 wxLogTrace( wxT(
"PNS_TUNE" ), wxT(
"followTrivialPath: LEFT branch starting from joint at (%d,%d)" ),
375 wxLogTrace( wxT(
"PNS_TUNE" ), wxT(
"followTrivialPath: LEFT branch result: length=%d, %d items" ),
376 left.m_length,
left.m_items.Size() );
378 wxLogTrace( wxT(
"PNS_TUNE" ), wxT(
"followTrivialPath: RIGHT branch starting from joint at (%d,%d)" ),
381 wxLogTrace( wxT(
"PNS_TUNE" ), wxT(
"followTrivialPath: RIGHT branch result: length=%d, %d items" ),
384 if( aTerminalJointA )
385 *aTerminalJointA =
left.m_end;
387 if( aTerminalJointB )
388 *aTerminalJointB =
right.m_end;
391 int leftSegCount = 0;
392 int rightSegCount = 0;
393 int initialSegCount = 0;
402 path.Prepend( item );
405 LINE* l =
dynamic_cast<LINE*
>( item );
419 LINE* l =
dynamic_cast<LINE*
>( item );
430 wxLogTrace( wxT(
"PNS_TUNE" ), wxT(
"" ) );
431 wxLogTrace( wxT(
"PNS_TUNE" ), wxT(
"=== followTrivialPath SUMMARY ===" ) );
432 wxLogTrace( wxT(
"PNS_TUNE" ), wxT(
"Starting segment count: %d" ), initialSegCount );
433 wxLogTrace( wxT(
"PNS_TUNE" ), wxT(
"Left branch: %d segments, length=%d" ), leftSegCount,
left.m_length );
434 wxLogTrace( wxT(
"PNS_TUNE" ), wxT(
"Initial line: %d segments, length=%lld" ), initialSegCount, aLine2->
CLine().
Length() );
435 wxLogTrace( wxT(
"PNS_TUNE" ), wxT(
"Right branch: %d segments, length=%d" ), rightSegCount,
right.m_length );
436 wxLogTrace( wxT(
"PNS_TUNE" ), wxT(
"Total segments in path: %d" ), leftSegCount + initialSegCount + rightSegCount );
437 wxLogTrace( wxT(
"PNS_TUNE" ), wxT(
"Total path length: %d" ), totalLength );
438 wxLogTrace( wxT(
"PNS_TUNE" ), wxT(
"Total items in result: %d" ),
path.Size() );
439 wxLogTrace( wxT(
"PNS_TUNE" ), wxT(
"=== followTrivialPath END ===" ) );
440 wxLogTrace( wxT(
"PNS_TUNE" ), wxT(
"" ) );
447 std::pair<const JOINT*, const JOINT*>* aTerminalJoints,
448 bool aFollowLockedSegments )
450 wxLogTrace( wxT(
"PNS_TUNE" ), wxT(
"*** AssembleTrivialPath: START ***" ) );
451 wxLogTrace( wxT(
"PNS_TUNE" ), wxT(
"AssembleTrivialPath: aStart=%p, kind=%s" ),
452 aStart, aStart->
KindStr().c_str() );
459 wxLogTrace( wxT(
"PNS_TUNE" ), wxT(
"AssembleTrivialPath: starting from VIA" ) );
465 wxLogTrace( wxT(
"PNS_TUNE" ), wxT(
"AssembleTrivialPath: VIA is fanout, returning empty" ) );
471 for(
ITEM* item : links )
476 wxLogTrace( wxT(
"PNS_TUNE" ), wxT(
"AssembleTrivialPath: found segment/arc from VIA" ) );
484 wxLogTrace( wxT(
"PNS_TUNE" ), wxT(
"AssembleTrivialPath: starting from SEGMENT/ARC" ) );
489 wxLogTrace( wxT(
"PNS_TUNE" ), wxT(
"AssembleTrivialPath: no segment found, returning empty" ) );
495 LINE l =
m_world->AssembleLine( seg,
nullptr,
false, aFollowLockedSegments );
497 wxLogTrace( wxT(
"PNS_TUNE" ), wxT(
"AssembleTrivialPath: assembled line with %d segments, length=%lld" ),
500 const JOINT* jointA =
nullptr;
501 const JOINT* jointB =
nullptr;
505 if( aTerminalJoints )
507 wxASSERT( jointA && jointB );
508 *aTerminalJoints = std::make_pair( jointA, jointB );
509 wxLogTrace( wxT(
"PNS_TUNE" ), wxT(
"AssembleTrivialPath: terminal joints at (%d,%d) and (%d,%d)" ),
513 wxLogTrace( wxT(
"PNS_TUNE" ), wxT(
"AssembleTrivialPath: returning path with %d items" ),
path.Size() );
514 wxLogTrace( wxT(
"PNS_TUNE" ), wxT(
"*** AssembleTrivialPath: END ***" ) );
515 wxLogTrace( wxT(
"PNS_TUNE" ), wxT(
"" ) );
531 m_world->QueryColliding( aVia, obstacles, opts );
534 std::set<LINKED_ITEM*> assembled;
541 wxLogTrace( wxT(
"PNS_TUNE" ), wxT(
"findLinesFromVia: VIA at (%d,%d), net=%p, %zu obstacles" ), aVia->
Pos().
x,
542 aVia->
Pos().
y, net, obstacles.size() );
544 for(
const OBSTACLE& obs : obstacles )
546 if( obs.m_item->Net() != net )
551 if( aVisited.contains( linked ) )
554 if( assembled.contains( linked ) )
561 bool anchor0Inside, anchor1Inside;
573 anchor0Inside = shape && shape->
Collide( anchor0, 0 );
574 anchor1Inside = shape && shape->
Collide( anchor1, 0 );
577 if( !anchor0Inside && !anchor1Inside )
579 wxLogTrace( wxT(
"PNS_TUNE" ), wxT(
" skip collision: layer=%d anchor0=(%d,%d) anchor1=(%d,%d)" ),
580 linked->
Layer(), anchor0.
x, anchor0.
y, anchor1.
x, anchor1.
y );
584 LINE l =
m_world->AssembleLine( linked,
nullptr,
false,
true );
587 assembled.insert( link );
597 const std::set<ITEM*>& aVisited )
599 using clock = std::chrono::steady_clock;
605 auto startTime = clock::now();
612 std::set<ITEM*> visited;
615 std::stack<STATE> stateStack;
618 initial.endpoint = aStartFromBack ? aStartLine.
CLastPoint() : aStartLine.
CPoint( 0 );
619 initial.pathLength = 0;
620 initial.visited = aVisited;
621 stateStack.push( std::move( initial ) );
623 while( !stateStack.empty() )
625 auto elapsed = std::chrono::duration_cast<std::chrono::milliseconds>( clock::now() - startTime ).count();
627 if( elapsed > timeoutMs )
629 wxLogTrace( wxT(
"PNS_TUNE" ), wxT(
"walkTuningPath: timeout after %lld ms" ), elapsed );
633 STATE current = std::move( stateStack.top() );
640 for(
ITEM* item : hits )
642 if( item->OfKind(
ITEM::SOLID_T ) && item->Net() == net && !current.visited.contains( item ) )
651 if( current.pathLength > best.
m_length )
654 best.
m_items = current.pathItems;
663 for(
ITEM* item : hits )
665 if( item->OfKind(
ITEM::VIA_T ) && item->Net() == net && !item->IsVirtual()
666 && !current.visited.contains( item ) )
668 via =
static_cast<VIA*
>( item );
675 current.visited.insert(
via );
679 for(
LINE& contLine : continuations )
682 bool startNearVia = ( contLine.CPoint( 0 ) - ep ).SquaredEuclideanNorm()
683 <= ( contLine.CLastPoint() - ep ).SquaredEuclideanNorm();
685 VECTOR2I forwardEndpoint = startNearVia ? contLine.CLastPoint() : contLine.CPoint( 0 );
687 int64_t contLength = contLine.CLine().Length();
696 contLength = clipped.
Length();
700 nextState.endpoint = forwardEndpoint;
701 nextState.pathItems = current.pathItems;
702 nextState.pathItems.Add(
via );
703 nextState.pathItems.Add( contLine );
704 nextState.pathLength = current.pathLength + contLength;
705 nextState.visited = current.visited;
708 nextState.visited.insert( link );
710 stateStack.push( std::move( nextState ) );
713 if( continuations.empty() )
715 if( current.pathLength > best.
m_length )
718 best.
m_items = current.pathItems;
726 if( current.pathLength > best.
m_length )
729 best.
m_items = current.pathItems;
735 wxLogTrace( wxT(
"PNS_TUNE" ), wxT(
"walkTuningPath: completed, best length=%lld, %d items, pad=%p" ),
745 wxLogTrace( wxT(
"PNS_TUNE" ), wxT(
"" ) );
746 wxLogTrace( wxT(
"PNS_TUNE" ), wxT(
"########## AssembleTuningPath: START ##########" ) );
747 wxLogTrace( wxT(
"PNS_TUNE" ), wxT(
"AssembleTuningPath: aStart=%p, kind=%s" ),
748 aStart, aStart->
KindStr().c_str() );
762 for(
ITEM* item : links )
776 if( continuations.empty() )
778 wxLogTrace( wxT(
"PNS_TUNE" ),
779 wxT(
"AssembleTuningPath: no via continuation found, returning empty" ) );
783 for(
LINKED_ITEM* link : continuations.front().Links() )
800 wxLogTrace( wxT(
"PNS_TUNE" ), wxT(
"AssembleTuningPath: no segment found, returning empty" ) );
804 LINE l =
m_world->AssembleLine( seg,
nullptr,
false,
true );
806 wxLogTrace( wxT(
"PNS_TUNE" ), wxT(
"AssembleTuningPath: initial line %d segments, length=%lld" ), l.
SegmentCount(),
809 std::set<ITEM*> visited;
812 visited.insert( link );
814 wxLogTrace( wxT(
"PNS_TUNE" ), wxT(
"AssembleTuningPath: walking LEFT from (%d,%d)" ), l.
CPoint( 0 ).
x,
818 wxLogTrace( wxT(
"PNS_TUNE" ), wxT(
"AssembleTuningPath: walking RIGHT from (%d,%d)" ), l.
CLastPoint().
x,
825 path.Prepend( item );
841 padA =
static_cast<PAD*
>( bi );
844 *aStartPad =
left.m_endPad;
846 wxLogTrace( wxT(
"PNS_TUNE" ), wxT(
"AssembleTuningPath: found start pad" ) );
856 padB =
static_cast<PAD*
>( bi );
859 *aEndPad =
right.m_endPad;
861 wxLogTrace( wxT(
"PNS_TUNE" ), wxT(
"AssembleTuningPath: found end pad" ) );
867 wxLogTrace( wxT(
"PNS_TUNE" ), wxT(
"AssembleTuningPath: no pads found, returning path" ) );
868 wxLogTrace( wxT(
"PNS_TUNE" ), wxT(
"########## AssembleTuningPath: END ##########" ) );
872 auto processPad = [&](
PAD* aPad )
874 for(
int idx = 0; idx <
path.Size(); idx++ )
893 std::set<PAD*> processedPads;
896 processedPads.insert( padA );
899 processedPads.insert( padB );
901 for(
int idx = 0; idx <
path.Size(); idx++ )
912 for(
ITEM* item : hits )
921 PAD* intermediatePad =
static_cast<PAD*
>( bi );
923 if( processedPads.find( intermediatePad ) == processedPads.end() )
925 wxLogTrace( wxT(
"PNS_TUNE" ),
926 wxT(
"AssembleTuningPath: processing intermediate"
929 processPad( intermediatePad );
930 processedPads.insert( intermediatePad );
941 for(
int idx = 0; idx <
path.Size(); idx++ )
954 for(
int delta : { -1, 1 } )
969 wxLogTrace( wxT(
"PNS_TUNE" ), wxT(
"AssembleTuningPath: final path has %d items" ),
path.Size() );
970 wxLogTrace( wxT(
"PNS_TUNE" ), wxT(
"########## AssembleTuningPath: END ##########" ) );
997 if( !coupledNet || !startItem )
1002 std::vector<ITEM*> pItems;
1003 std::vector<ITEM*> nItems;
1008 pItems.push_back( item );
1011 std::set<ITEM*> coupledItems;
1012 m_world->AllItemsInNet( coupledNet, coupledItems );
1014 for(
ITEM* item : coupledItems )
1017 nItems.push_back( item );
1022 SEG::ecoord minDist_sq = std::numeric_limits<SEG::ecoord>::max();
1023 SEG::ecoord minDistTarget_sq = std::numeric_limits<SEG::ecoord>::max();
1026 auto findNItem = [&](
ITEM* p_item )
1028 for(
ITEM* n_item : nItems )
1030 SEG::ecoord dist_sq = std::numeric_limits<SEG::ecoord>::max();
1032 if( n_item->Kind() != p_item->Kind() )
1055 const ARC* p_arc =
static_cast<const ARC*
>( p_item );
1056 const ARC* n_arc =
static_cast<const ARC*
>( n_item );
1070 if( dist_sq <= minDist_sq )
1072 SEG::ecoord distTarget_sq = n_item->Shape( -1 )->SquaredDistance( targetPoint );
1073 if( distTarget_sq < minDistTarget_sq )
1075 minDistTarget_sq = distTarget_sq;
1076 minDist_sq = dist_sq;
1079 coupledItem =
static_cast<LINKED_ITEM*
>( n_item );
1085 findNItem( startItem );
1090 std::set<ITEM*> linksToTest;
1101 if( link != linked )
1102 linksToTest.emplace( link );
1106 for(
ITEM* link : linksToTest )
1115 if(
m_world->GetRuleResolver()->DpNetPolarity( refNet ) < 0 )
1116 std::swap( lp, ln );
1129 const ARC* refArc =
static_cast<ARC*
>( refItem );
1130 const ARC* coupledArc =
static_cast<ARC*
>( coupledItem );
1145 std::deque<ITEM*> pending;
1152 pending.push_back( aStart );
1155 int64_t initialArea = clusterBBox.
GetArea();
1156 std::unordered_set<ITEM*> processed;
1158 while( !pending.empty() )
1163 pending.pop_front();
1165 if( processed.find(
top ) == processed.end() )
1170 processed.insert(
top );
1172 m_world->QueryColliding(
top, obstacles, opts );
1174 for(
const OBSTACLE& obs : obstacles )
1181 if( aExcludedNet && obs.m_item->Net() == aExcludedNet )
1187 clusterBBox.
Merge( line.CLine().BBox() );
1191 clusterBBox.
Merge( obs.m_item->Shape( aLayer )->BBox() );
1194 const int64_t currentArea = clusterBBox.
GetArea();
1195 const double areaRatio = (double) currentArea / (
double) ( initialArea + 1 );
1197 if( aAreaExpansionLimit > 0.0 && areaRatio > aAreaExpansionLimit )
1200 if( processed.find( obs.m_item ) == processed.end() &&
1201 obs.m_item->Layers().Overlaps( aLayer ) && !( obs.m_item->Marker() &
MK_HEAD ) )
1203 processed.insert( obs.m_item );
1204 cluster.
m_items.push_back( obs.m_item );
1205 pending.push_back( obs.m_item );
static const ADVANCED_CFG & GetCfg()
Get the singleton instance's config, which is shared by all consumers.
A base class for any item which can be embedded within the BOARD container class, and therefore insta...
constexpr BOX2< Vec > & Merge(const BOX2< Vec > &aRect)
Modify the position and size of the rectangle in order to contain aRect.
constexpr ecoord_type GetArea() const
Return the area of the rectangle.
KICAD_T Type() const
Returns the type of object.
static void OptimiseTraceInVia(SHAPE_LINE_CHAIN &aLine, const PCB_VIA *aVia, PCB_LAYER_ID aLayer)
Clips trace portions inside a VIA pad and replaces them with a straight-line segment from the VIA edg...
static bool IsPointInsideViaPad(const PCB_VIA *aVia, const VECTOR2I &aPoint, PCB_LAYER_ID aLayer)
Returns true if the given point falls inside VIA pad shape on the given layer.
static void OptimiseTraceInPad(SHAPE_LINE_CHAIN &aLine, const PAD *aPad, PCB_LAYER_ID aPcbLayer)
Optimises the given trace / line to minimise the electrical path length within the given pad.
int Width() const override
const SHAPE_ARC & CArc() const
Basic class for a differential pair.
void SetWidth(int aWidth)
void Add(const LINE &aLine)
Base class for PNS router board items.
BOARD_ITEM * Parent() const
void SetLayers(const PNS_LAYER_RANGE &aLayers)
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 OfKind(int aKindMask) const
virtual VECTOR2I Anchor(int n) const
std::string KindStr() const
virtual int AnchorCount() 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
NET_HANDLE Net() const override
int LinkCount(int aMask=-1) const
bool IsNonFanoutVia() const
const ITEM_SET & CLinks() const
const VECTOR2I & Pos() const
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
SHAPE_LINE_CHAIN & Line()
void Reverse()
Clip the line to the nearest obstacle, traversing from the line's start vertex (0).
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()
LINKED_ITEM * GetLink(int aIndex) const
Erase the linking information. Used to detach the line from the owning node.
virtual void ClearLinks()
Return the number of segments that were assembled together to form this line.
std::set< OBSTACLE > OBSTACLES
virtual PCB_LAYER_ID GetBoardLayerFromPNSLayer(int aLayer) const =0
int Width() const override
ITEM * NearestUnconnectedItem(const JOINT *aStart, int *aAnchor=nullptr, int aKindMask=ITEM::ANY_T)
std::set< const JOINT * > JOINT_SET
bool LeadingRatLine(const LINE *aTrack, SHAPE_LINE_CHAIN &aRatLine)
std::vector< LINE > findLinesFromVia(ROUTER_IFACE *aRouterIface, VIA *aVia, const std::set< ITEM * > &aVisited)
const DIFF_PAIR AssembleDiffPair(SEGMENT *aStart)
WALK_RESULT walkTuningPath(ROUTER_IFACE *aRouterIface, LINE &aStartLine, bool aStartFromBack, const std::set< ITEM * > &aVisited)
ITEM_SET followTrivialPath(LINE *aLine, const JOINT **aTerminalJointA, const JOINT **aTerminalJointB, bool aFollowLockedSegments=false)
const ITEM_SET ConnectedItems(const JOINT *aStart, int aKindMask=ITEM::ANY_T)
bool NearestUnconnectedAnchorPoint(const LINE *aTrack, VECTOR2I &aPoint, PNS_LAYER_RANGE &aLayers, ITEM *&aItem)
const CLUSTER AssembleCluster(ITEM *aStart, int aLayer, double aAreaExpansionLimit=0.0, NET_HANDLE aExcludedNet=nullptr)
const JOINT_SET ConnectedJoints(const JOINT *aStart)
const ITEM_SET AssembleTuningPath(ROUTER_IFACE *aRouterIface, ITEM *aStart, SOLID **aStartPad=nullptr, SOLID **aEndPad=nullptr)
Like AssembleTrivialPath, but follows the track length algorithm, which discards segments that are fu...
const int DP_PARALLELITY_THRESHOLD
PATH_RESULT followBranch(const JOINT *aStartJoint, LINKED_ITEM *aPrev, std::set< ITEM * > &aVisited, bool aFollowLockedSegments)
const ITEM_SET AssembleTrivialPath(ITEM *aStart, std::pair< const JOINT *, const JOINT * > *aTerminalJoints=nullptr, bool aFollowLockedSegments=false)
Assemble a trivial path between two joints given a starting item.
bool SimplifyLine(LINE *aLine)
const VECTOR2I & Pos() const
const SHAPE * Shape(int aLayer) const override
Return the geometrical shape of the item.
Represent a contiguous set of PCB layers.
ecoord SquaredDistance(const SEG &aSeg) const
VECTOR2I::extended_type ecoord
static SEG::ecoord Square(int a)
bool ApproxParallel(const SEG &aSeg, int aDistanceThreshold=1) const
const VECTOR2I & GetCenter() const
Represent a polyline containing arcs as well as line segments: A chain of connected line and/or arc s...
int PointCount() const
Return the number of points (vertices) in this line chain.
void Clear()
Remove all points from the line chain.
void Simplify(int aTolerance=0)
Simplify the line chain by removing colinear adjacent segments and duplicate vertices.
void Append(int aX, int aY, bool aAllowDuplication=false)
Append a new point at the end of the line chain.
long long int Length() const
Return length of the line chain in Euclidean metric.
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,...
virtual VECTOR2I Centre() const
Compute a center-of-mass of the shape.
virtual const BOX2I BBox(int aClearance=0) const =0
Compute a bounding box of the shape, with a margin of aClearance a collision.
constexpr extended_type Cross(const VECTOR2< T > &aVector) const
Compute cross product of self with aVector.
constexpr extended_type SquaredEuclideanNorm() const
Compute the squared euclidean norm of the vector, which is defined as (x ** 2 + y ** 2).
T EuclideanNorm() const
Compute the Euclidean norm of the vector, which is defined as sqrt(x ** 2 + y ** 2).
int m_FollowBranchTimeout
Timeout for the PNS router's followBranch path search, in milliseconds.
PCB_LAYER_ID
A quick note on layer IDs:
Push and Shove diff pair dimensions (gap) settings dialog.
bool commonParallelProjection(SEG p, SEG n, SEG &pClip, SEG &nClip)
EDA_ANGLE abs(const EDA_ANGLE &aAngle)
Hold an object colliding with another object, along with some useful data about the collision.
std::vector< ITEM * > m_items
KIBIS top(path, &reporter)
wxString result
Test unit parsing edge cases and error handling.
@ PCB_VIA_T
class PCB_VIA, a via (like a track segment on a copper layer)
@ PCB_PAD_T
class PAD, a pad in a footprint
VECTOR2< int32_t > VECTOR2I