49    if( aPrimitives.
Empty() )
 
   60        bool         redundant = 
false;
 
   63            if( l.originalLine.ContainsLink( litem ) )
 
   65                l.originalLeaders.push_back( litem );
 
   85    bool anyStrictCornersFound = 
false;
 
   86    bool anyStrictMidSegsFound = 
false;
 
   90        const int       thr = l.originalLine.Width() / 2;
 
   92        const VECTOR2I& origFirst = l.originalLine.CLine().CPoint( 0 );
 
   93        const int       distFirst = ( origFirst - aP ).EuclideanNorm();
 
   95        const VECTOR2I& origLast = l.originalLine.CLine().CLastPoint();
 
   96        const int       distLast = ( origLast - aP ).EuclideanNorm();
 
   98        l.cornerDistance = std::min( distFirst, distLast );
 
  100        bool takeFirst = 
false;
 
  101        auto ilast = aPrimitives.
FindVertex( origLast );
 
  102        auto ifirst = aPrimitives.
FindVertex( origFirst );
 
  104        if( ilast && ifirst )
 
  105            takeFirst = distFirst < distLast;
 
  111        if( ifirst || ilast )
 
  115                l.cornerIsLast = 
false;
 
  116                l.leaderSegIndex = 0;
 
  117                l.cornerDistance = distFirst;
 
  120                if( distFirst <= thr )
 
  123                    l.cornerDistance = 0;
 
  128                l.cornerIsLast = 
true;
 
  129                l.leaderSegIndex = l.originalLine.SegmentCount() - 1;
 
  130                l.cornerDistance = distLast;
 
  133                if( distLast <= thr )
 
  136                    l.cornerDistance = 0;
 
  141        const auto& links = l.originalLine.Links();
 
  143            for( 
int lidx = 0; lidx < (int) links.size(); lidx++ )
 
  151                        int d = lseg->Seg().Distance( aP );
 
  153                        l.midSeg = lseg->Seg();
 
  155                        l.leaderSegIndex = lidx;
 
  156                        l.leaderSegDistance = d + thr;
 
  158                        if( d < thr && !l.isStrict )
 
  162                            l.leaderSegDistance = 0;
 
  169            anyStrictCornersFound |= l.isCorner;
 
  170            anyStrictMidSegsFound |= !l.isCorner;
 
  174    if( anyStrictCornersFound )
 
  176    else if (anyStrictMidSegsFound )
 
  180        int minLeadSegDist = std::numeric_limits<int>::max();
 
  181        int minCornerDist = std::numeric_limits<int>::max();
 
  187            if( l.cornerDistance < minCornerDist )
 
  189                minCornerDist = l.cornerDistance;
 
  192            if( l.leaderSegDistance < minLeadSegDist )
 
  194                minLeadSegDist = l.leaderSegDistance;
 
  199        if( bestCorner && bestSeg )
 
  201            if( minCornerDist < minLeadSegDist )
 
  212        else if ( bestCorner )
 
  230            if ( !l.cornerIsLast )
 
  232                l.originalLine.Reverse();
 
  233                l.cornerIsLast = 
true;
 
  237            const JOINT* jt = 
m_world->FindJoint( l.originalLine.CLastPoint(), &l.originalLine );
 
  239            assert (jt != 
nullptr);
 
  250        if( (anyStrictCornersFound || anyStrictMidSegsFound) && l.isStrict )
 
  252            l.isPrimaryLine = 
true;
 
 
  290    std::set<OBSTACLE> obstacles;
 
  293    constexpr int clipLengthThreshold = 100;
 
  300    bool didClip = 
false;
 
  302    int step = curL / 2 - 1;
 
  304    while( step > clipLengthThreshold )
 
  308        int idx = sl_tmp.
Split( pclip );
 
  309        sl_tmp = sl_tmp.
Slice(0, idx);
 
  323            tightest = std::move( sl_tmp );
 
 
  347    std::set<NET_HANDLE> uniqueNets;
 
  352            uniqueNets.insert( net );
 
  355    return std::vector<NET_HANDLE>( uniqueNets.begin(), uniqueNets.end() );
 
 
  413        PNS_DBG(
Dbg(), Message, wxString::Format(
"s %d ip=%d c=%s o=%s", i, ip?1:0, curDir.
Format(), origLeaderDir.
Format() ));
 
  416            if( curDir == origLeaderDir || curDir == origLeaderDir.
Opposite() )
 
 
  428    for( 
auto& l : aCompletedLines )
 
  434                if( l.draggedLine.LinkCount() > 0 )
 
  437                        static_cast<PNS::ITEM*
>( l.draggedLine.GetLink( -1 ) ) );
 
  443                if( newLeaderIdx >= 0 && newLeaderIdx < l.draggedLine.LinkCount() )
 
  446                        static_cast<PNS::ITEM*
>( l.draggedLine.GetLink( newLeaderIdx ) ) );
 
 
  467    std::sort( aCompletedLines.begin(), aCompletedLines.end(), compareDragStartDist );
 
  472    for( 
auto& l : aCompletedLines )
 
  474        PNS_DBG( 
Dbg(), AddItem, &l.originalLine, 
BLUE, 100000, wxString::Format(
"prewalk-remove lc=%d", l.originalLine.LinkCount() ) );
 
  475        preWalkNode->
Remove( l.originalLine );
 
  483    for( 
int attempt = 0; attempt < 2; attempt++ )
 
  485        NODE *node = tmpNodes[attempt] = preWalkNode->
Branch();
 
  486        totalLength[attempt] = 0;
 
  489        for( 
int lidx = 0; lidx < aCompletedLines.size(); lidx++ )
 
  491            MDRAG_LINE& l = aCompletedLines[attempt ? aCompletedLines.size() - 1 - lidx : lidx];
 
  497            PNS_DBG( 
Dbg(), AddItem, &walk, 
BLUE, 100000, wxString::Format(
"walk    lidx=%d attempt=%d", lidx, attempt) );
 
  509                tmpNodes[attempt] = 
nullptr;
 
  522    if( tmpNodes[0] && tmpNodes[1] )
 
  524        if ( totalLength[0] < totalLength[1] )
 
  537    else if ( tmpNodes[0] )
 
  542    else if ( tmpNodes[1] )
 
 
  572    for( 
int l1 = 0; l1 < aCompletedLines.size(); l1++ )
 
  574        for( 
int l2 = l1 + 1; l2 < aCompletedLines.size(); l2++ )
 
  576            const auto& l1l = aCompletedLines[l1].draggedLine;
 
  577            auto l2l        = aCompletedLines[l2].draggedLine;
 
  581                aCompletedLines[l2].draggedLine = l2l;
 
  587    for ( 
auto&l : aCompletedLines )
 
 
  614    std::sort( aCompletedLines.begin(), aCompletedLines.end(), compareDragStartDist );
 
  620        PNS_DBG( 
Dbg(), Message, wxString::Format ( wxT(
"net %-30s: isCorner %d isStrict %d c-Dist %-10d l-dist %-10d leadIndex %-2d CisLast %d dragDist %-10d"),
 
  621            iface->GetNetName( l.draggedLine.Net() ),
 
  622            (
int) l.isCorner?1:0,
 
  623            (
int) l.isStrict?1:0,
 
  624            (
int) l.cornerDistance,
 
  625            (
int) l.leaderSegDistance,
 
  626            (
int) l.leaderSegIndex,
 
  627            (
int) l.cornerIsLast?1:0,
 
  628            (
int) l.dragDist ) );
 
  635    for( 
auto& l : aCompletedLines )
 
  647        for( 
int i = 0; i < aCompletedLines.size(); i++ )
 
  650            if( 
m_shove->HeadsModified( i ) )
 
 
  672    std::optional<LINE> primaryPreDrag, primaryDragged;
 
  681    std::vector<MDRAG_LINE> completed;
 
  683    auto tryPosture = [&] ( 
int aVariant ) -> 
bool 
  690            l.preDragLine = l.originalLine;
 
  692            if( l.isPrimaryLine )
 
  700                primaryDragged = l.originalLine;
 
  701                primaryDragged->ClearLinks();
 
  702                primaryPreDrag = l.originalLine;
 
  708        if( aVariant == 1 && (primaryPreDrag->PointCount() > 2) )
 
  710                primaryPreDrag->Line().Remove( -1 );
 
  711                primaryDragged->Line().Remove( -1 );
 
  715                    l.preDragLine.Line().Remove(-1);
 
  726            PNS_DBG( 
Dbg(), AddPoint, primaryDragged->CLastPoint(), 
YELLOW, 600000, wxT(
"mdrag-sec"));
 
  728            lastPreDrag =  primaryPreDrag->CSegment( -1 );
 
  731            primaryDragged->SetSnapThreshhold( snapThreshold );
 
  732            primaryDragged->DragCorner( aP, primaryDragged->PointCount() - 1, 
false );
 
  735            if( primaryDragged->SegmentCount() > 0 )
 
  737                SEG lastPrimDrag = primaryDragged->CSegment( -1 );
 
  740                    lastPrimDrag = lastPreDrag;
 
  742                auto lastSeg = primaryDragged->CSegment( -1 );
 
  745                    if( lastSeg.Length() < primaryDragged->Width() )
 
  747                        lastPrimDrag = lastPreDrag;
 
  751                perp = (lastPrimDrag.
B - lastPrimDrag.
A).Perpendicular();
 
  756                PNS_DBG( 
Dbg(), AddShape, 
SEG(lastPrimDrag.
B, lastPrimDrag.
B + perp), 
LIGHTGRAY, 100000, wxString::Format(
"prim-perp-seg") );
 
  771            lastPreDrag =  primaryDragged->CSegment( primaryLine->
leaderSegIndex );
 
  772            primaryDragged->SetSnapThreshhold( snapThreshold );
 
  774            perp = (primaryLine->
midSeg.
B - primaryLine->
midSeg.
A).Perpendicular();
 
  792                if( l.preDragLine.SegmentCount() >= 1 )
 
  805                        DIRECTION_45 parallelDir( l.preDragLine.CSegment( -1 ) );
 
  807                        auto leadAngle = primaryDir.
Angle( parallelDir );
 
  814                            int dist = lastPreDrag.
LineDistance( l.preDragLine.CLastPoint(), 
true );
 
  817                            auto projected = aP + perp.
Resize( dist );
 
  820                            LINE parallelDragged( l.preDragLine );
 
  829                                                        false, primaryLastSegDir );
 
  836                            if( !l.isPrimaryLine )
 
  838                                l.draggedLine = parallelDragged;
 
  839                                completed.push_back( l );
 
  846                        SEG sdrag = l.midSeg;
 
  849                        auto ang = refDir.
Angle( curDir );
 
  854                                    l.preDragLine.CPoint( l.leaderSegIndex ), 
true );
 
  855                            auto projected = aP + perp.
Resize( dist );
 
  857                            SEG      sperp( aP, aP + perp.
Resize( 10000000 ) );
 
  870                            if( !l.isPrimaryLine )
 
  872                                l.draggedLine = l.preDragLine;
 
  873                                l.draggedLine.ClearLinks();
 
  874                                l.draggedLine.SetSnapThreshhold( snapThreshold );
 
  875                                l.draggedLine.DragSegment( projected, l.leaderSegIndex, 
false );
 
  876                                completed.push_back( l );
 
  883                                     wxT( 
"startProj" ) );
 
  885                                     wxString::Format( 
"pro dd=%d", l.dragDist ) );
 
  893                l.draggedLine = *primaryDragged;
 
  895                completed.push_back( l );
 
  903            for ( 
const auto &l: completed )
 
  905                if( !l.dragOK && aVariant < 2 )
 
  908                if( l.isPrimaryLine )
 
  913                if( lastDir != primaryLastSegDir )
 
  923    for( 
int variant = 0; variant < 3; variant++ )
 
  925        res = tryPosture( 0 );
 
 
Represent route directions & corner angles in a 45-degree metric.
 
AngleType Angle(const DIRECTION_45 &aOther) const
Return the type of angle between directions (this) and aOther.
 
const std::string Format() const
Format the direction in a human readable word.
 
DIRECTION_45 Opposite() const
Return a direction opposite (180 degree) to (this).
 
void SetDebugDecorator(DEBUG_DECORATOR *aDecorator)
Assign a debug decorator allowing this algo to draw extra graphics for visual debugging.
 
void SetLogger(LOGGER *aLogger)
 
virtual LOGGER * Logger()
 
ROUTER * Router() const
Return current router settings.
 
ROUTING_SETTINGS & Settings() const
Return the logger object, allowing to dump geometry to a file.
 
DEBUG_DECORATOR * Dbg() const
 
DRAG_ALGO(ROUTER *aRouter)
 
bool Contains(ITEM *aItem) const
 
std::vector< ITEM * > & Items()
 
ITEM * FindVertex(const VECTOR2I &aV) const
 
Base class for PNS router board items.
 
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.
 
A 2D point on a given set of layers and belonging to a certain net, that links together a number of b...
 
bool IsTrivialEndpoint() const
 
Represents a track on a PCB, connecting two non-trivial joints (that is, vias, pads,...
 
void SetShape(const SHAPE_LINE_CHAIN &aLine)
Return the shape of the line.
 
const SHAPE_LINE_CHAIN & CLine() const
 
const VECTOR2I & CLastPoint() const
 
void DragCorner(const VECTOR2I &aP, int aIndex, bool aFreeAngle=false, DIRECTION_45 aPreferredEndingDirection=DIRECTION_45())
 
const SEG CSegment(int aIdx) const
Set line width.
 
virtual void ClearLinks()
Return the number of segments that were assembled together to form this line.
 
bool multidragShove(std::vector< MDRAG_LINE > &aCompletedLines)
 
bool multidragMarkObstacles(std::vector< MDRAG_LINE > &aCompletedLines)
 
std::vector< PNS::ITEM * > m_leaderSegments
 
virtual bool Start(const VECTOR2I &aP, ITEM_SET &aPrimitives) override
Function Start()
 
bool FixRoute(bool aForceCommit) override
Function FixRoute()
 
bool Drag(const VECTOR2I &aP) override
Function Drag()
 
ITEM_SET m_origDraggedItems
 
int CurrentLayer() const override
Function CurrentLayer()
 
NODE * CurrentNode() const override
Function CurrentNode()
 
std::vector< MDRAG_LINE > m_mdragLines
 
bool tryWalkaround(NODE *aNode, LINE &aOrig, LINE &aWalk)
 
VECTOR2I m_dragStartPoint
 
void SetMode(PNS::DRAG_MODE aDragMode) override
 
int findNewLeaderSegment(const MDRAG_LINE &aLine) const
 
void restoreLeaderSegments(std::vector< MDRAG_LINE > &aCompletedLines)
 
bool multidragWalkaround(std::vector< MDRAG_LINE > &aCompletedLines)
 
const ITEM_SET Traces() override
Function Traces()
 
const std::vector< NET_HANDLE > CurrentNets() const override
Function CurrentNets()
 
MULTI_DRAGGER(ROUTER *aRouter)
 
PNS::DRAG_MODE Mode() const override
 
std::unique_ptr< SHOVE > m_shove
 
Keep the router "world" - i.e.
 
NODE * Branch()
Create a lightweight copy (called branch) of self that tracks the changes (added/removed items) wrs t...
 
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.
 
ROUTER_IFACE * GetInterface() const
 
bool SmoothDraggedSegments() const
Enable/disable smoothing segments during dragging.
 
The actual Push and Shove algorithm.
 
@ SHP_DONT_LOCK_ENDPOINTS
 
void SetIterationLimit(const int aIterLimit)
 
void SetLengthLimit(bool aEnable, double aLengthExpansionFactor)
 
void SetSolidsOnly(bool aSolidsOnly)
 
STATUS Route(const LINE &aInitialPath, LINE &aWalkPath, bool aOptimize=true)
 
void SetAllowedPolicies(std::vector< WALK_POLICY > aPolicies)
 
int LineDistance(const VECTOR2I &aP, bool aDetermineSide=false) const
Return the closest Euclidean distance between point aP and the line defined by the ends of segment (t...
 
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
 
VECTOR2I LineProject(const VECTOR2I &aP) const
Compute the perpendicular projection point of aP on a line passing through ends of the segment.
 
Represent a polyline containing arcs as well as line segments: A chain of connected line and/or arc s...
 
const VECTOR2I PointAlong(int aPathLength) const
 
int Split(const VECTOR2I &aP, bool aExact=false)
Insert the point aP belonging to one of the our segments, splitting the adjacent segment in two.
 
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.
 
long long int Length() const
Return length of the line chain in Euclidean metric.
 
T EuclideanNorm() const
Compute the Euclidean norm of the vector, which is defined as sqrt(x ** 2 + y ** 2).
 
constexpr extended_type Dot(const VECTOR2< T > &aVector) const
Compute dot product of self with aVector.
 
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.
 
@ RM_MarkObstacles
Ignore collisions, mark obstacles.
 
@ RM_Walkaround
Only walk around.
 
bool clipToOtherLine(NODE *aNode, const LINE &aRef, LINE &aClipped)
 
#define PNS_DBG(dbg, method,...)
 
std::vector< PNS::ITEM * > originalLeaders
 
LINE lines[MaxWalkPolicies]
 
STATUS status[MaxWalkPolicies]
 
wxString result
Test unit parsing edge cases and error handling.
 
Casted dyn_cast(From aObject)
A lightweight dynamic downcast.
 
constexpr int sign(T val)
 
VECTOR2< int32_t > VECTOR2I