30#include <wx/translation.h>
50 m_draggedSegmentIndex = 0;
53 m_freeAngleMode =
false;
54 m_forceMarkObstaclesMode =
false;
72 if(
via->PushoutForce( node, lead, force,
ITEM::ANY_T, iterLimit ) )
74 via->SetPos(
via->Pos() + force );
84 int w2 = aSeg->
Width() / 2;
86 auto distA = ( aP - aSeg->
Seg().A ).EuclideanNorm();
87 auto distB = ( aP - aSeg->
Seg().
B ).EuclideanNorm();
93 psnap = aSeg->
Seg().
A;
95 else if( distB <= w2 )
97 psnap = aSeg->
Seg().
B;
111 if( item->IsVirtual() && item->OfKind(
ITEM::VIA_T ))
112 return static_cast<VVIA*
>( item );
121 int w2 = aSeg->
Width() / 2;
126 auto distA = ( aP - aSeg->
Seg().A ).EuclideanNorm();
127 auto distB = ( aP - aSeg->
Seg().
B ).EuclideanNorm();
129 if( distA < w2 || distB < w2 )
162 if( centralAngle + maxDeviation >=
ANGLE_180 )
166 wxString::Format(
_(
"Unable to drag arc tracks of %.1f degrees or greater." ), limit.
AsDegrees() ) );
171 LINE probe =
m_world->AssembleLine( aArc, &probeIdx );
196 bool isolatedStart = ( firstArcPt == 0 );
197 bool isolatedEnd = ( lastArcPt == probe.
PointCount() - 1 );
199 if( isolatedStart || isolatedEnd )
202 int stubLen = std::max( 1, maxStubIU / 2 );
214 if( perp.
Dot( toMid ) > 0 )
217 double mag = std::hypot( (
double) perp.
x, (
double) perp.
y );
229 VECTOR2I stubFar = p0 + outwardTangent( p0 );
230 auto stub = std::make_unique<SEGMENT>(
SEG( stubFar, p0 ), aArc->
Net() );
231 stub->SetWidth( aArc->
Width() );
232 stub->SetLayers( aArc->
Layers() );
239 VECTOR2I stubFar = p1 + outwardTangent( p1 );
240 auto stub = std::make_unique<SEGMENT>(
SEG( p1, stubFar ), aArc->
Net() );
241 stub->SetWidth( aArc->
Width() );
242 stub->SetLayers( aArc->
Layers() );
278 bool foundVia =
false;
308 if( aPrimitives.
Empty() )
311 ITEM* startItem = aPrimitives[0];
335 PNS_DBG(
Dbg(), Message, wxString::Format(
"StartDragging: item %p [kind %d]",
336 startItem, (
int) startItem->
Kind() ) );
338 switch( startItem->
Kind() )
364 m_mode =
static_cast<int>( aMode );
465 if(
Settings().AllowDRCViolations() )
488 LINE draggedLine( *l );
523 bool viaPropOk =
false;
530 std::unique_ptr<VIA> draggedVia =
Clone( *
via );
532 draggedVia->SetPos( aP );
537 vias.insert( draggedVia.get() );
545 viaTargetPos = draggedVia->Pos();
560 LINE draggedLine( *l );
567 if (
m_world->CheckColliding( &draggedLine ) )
593 LINE draggedPostOpt, origLine( aOrig );
602 if(
Settings().SmoothDraggedSegments() )
605 if(
Settings().GetRestrictAngles() )
620 if( !
Settings().GetOptimizeEntireDraggedTrack() )
625 affectedArea =
BOX2I( aP );
627 PNS_DBG(
Dbg(), AddShape, *affectedArea,
RED, 0, wxT(
"drag-affected-area" ) );
632 PNS_DBG(
Dbg(), AddItem, &aDragged,
RED, 0, wxT(
"drag-preopt" ) );
634 optimizer.
Optimize( &aDragged, &draggedPostOpt, &origLine );
635 aDragged = draggedPostOpt;
646 if( aVertexIndex <= 0 || aVertexIndex >= aLine.
PointCount() - 1 )
649 SEG segBefore( aLine.
CPoint( aVertexIndex - 1 ), aLine.
CPoint( aVertexIndex ) );
650 SEG segAfter( aLine.
CPoint( aVertexIndex ), aLine.
CPoint( aVertexIndex + 1 ) );
664 int vertIdx = aLine.
Find( nearest );
668 PNS_DBG(
Dbg(), Message, wxString::Format(
"anchor: nearest pt used (vert=%d)", vertIdx ) );
672 for(
int offset = 1; offset < aLine.
PointCount(); offset++ )
674 int rightIdx = vertIdx + offset;
675 std::optional<VECTOR2I> candidate;
678 candidate = aLine.
CPoint( rightIdx );
680 int leftIdx = vertIdx - offset;
686 if( !candidate || ( leftPt - aP ).SquaredEuclideanNorm() < ( *candidate - aP ).SquaredEuclideanNorm() )
688 PNS_DBG(
Dbg(), Message, wxString::Format(
"anchor: good alt vertex idx %d", leftIdx ) );
689 PNS_DBG(
Dbg(), AddPoint, leftPt,
GREEN, 100000, wxT(
"drag-anchor-alt" ) );
694 if( candidate.has_value() )
696 PNS_DBG(
Dbg(), Message, wxString::Format(
"anchor: good alt vertex idx %d", rightIdx ) );
697 PNS_DBG(
Dbg(), AddPoint, *candidate,
GREEN, 100000, wxT(
"drag-anchor-alt" ) );
702 PNS_DBG(
Dbg(), Message, wxString::Format(
"anchor: nearest pt bad; no alternative (vert=%d)", vertIdx ) );
761 if (
m_world->CheckColliding( &dragged ) )
767 draggedWalk = dragged;
792 if(
m_world->CheckColliding( &dragged ) )
798 draggedWalk = dragged;
849 auto preShoveNode =
m_shove->CurrentNode();
852 preShoveNode->Remove( draggedPreShove );
862 m_shove->AddHeads( draggedPreShove, policy );
865 LINE draggedPostShove( draggedPreShove );
870 draggedPostShove =
m_shove->GetModifiedHead( 0 );
878 draggedPostShove.
Unmark();
899 auto preShoveNode =
m_shove->CurrentNode();
902 preShoveNode->Remove( draggedPreShove );
907 m_shove->AddHeads( draggedPreShove, policy );
911 LINE draggedPostShove( draggedPreShove );
913 if( ok &&
m_shove->HeadsModified() )
914 draggedPostShove =
m_shove->GetModifiedHead( 0 );
921 draggedPostShove.
Unmark();
943 PNS_DBG(
Dbg(), Message, wxString::Format(
"head-mod %d",
944 m_shove->HeadsModified() ? 1: 0 ) );
948 newVia =
m_shove->GetModifiedHeadVia( 0 );
950 PNS_DBG(
Dbg(), Message, wxString::Format(
"newvia %d %d %d %d",
constexpr EDA_IU_SCALE pcbIUScale
std::optional< BOX2I > OPT_BOX2I
constexpr BOX2I KiROUND(const BOX2D &aBoxD)
static const ADVANCED_CFG & GetCfg()
Get the singleton instance's config, which is shared by all consumers.
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.
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()
Return the logger object, allowing to dump geometry to a file.
ROUTER * Router() const
Return the instance of our router.
ROUTING_SETTINGS & Settings() const
Return current router settings.
DEBUG_DECORATOR * Dbg() const
int Width() const override
const SHAPE_ARC & CArc() const
ITEM_SET m_draggedItems
Contains the list of items that are currently modified by the dragger.
PNS::DRAG_MODE Mode() const override
void optimizeAndUpdateDraggedLine(LINE &aDragged, const LINE &aOrig, const VECTOR2I &aP)
const ITEM_SET findViaFanoutByHandle(NODE *aNode, const VIA_HANDLE &handle)
bool startDragSegment(const VECTOR2D &aP, SEGMENT *aSeg)
VECTOR2D m_lastValidPoint
virtual bool Start(const VECTOR2I &aP, ITEM_SET &aPrimitives) override
Function Start()
NODE * CurrentNode() const override
Function CurrentNode()
bool dragViaMarkObstacles(const VIA_HANDLE &aHandle, NODE *aNode, const VECTOR2I &aP)
bool IsDragOrigin(const ITEM *aItem) const
Return true if aItem is a world item that moves with the drag: a link of the original line,...
bool Drag(const VECTOR2I &aP) override
Function Drag()
bool startDragVia(VIA *aVia)
int m_draggedSegmentIndex
bool pointHasBadCorner(const SHAPE_LINE_CHAIN &aLine, int aVertexIndex) const
Returns true if the vertex at aVertexIndex has a non-obtuse corner.
const std::vector< NET_HANDLE > CurrentNets() const override
Function CurrentNets()
bool dragShove(const VECTOR2I &aP)
void SetMode(PNS::DRAG_MODE aDragMode) override
bool dragMarkObstacles(const VECTOR2I &aP)
bool FixRoute(bool aForceCommit) override
Function FixRoute()
std::unique_ptr< SHOVE > m_shove
bool dragWalkaround(const VECTOR2I &aP)
VVIA * checkVirtualVia(const VECTOR2D &aP, SEGMENT *aSeg)
bool dragViaWalkaround(const VIA_HANDLE &aHandle, NODE *aNode, const VECTOR2I &aP)
bool m_freeAngleMode
If true, moves the connection lines without maintaining 45 degrees corners.
bool m_forceMarkObstaclesMode
const ITEM_SET Traces() override
Function Traces()
bool tryWalkaround(NODE *aNode, LINE &aOrig, LINE &aWalk)
VECTOR2I bestAnchorForPoint(const SHAPE_LINE_CHAIN &aLine, const VECTOR2I &aP) const
When the cursor is unreachable (e.g.
bool startDragArc(const VECTOR2D &aP, ARC *aArc)
MOUSE_TRAIL_TRACER m_mouseTrailTracer
bool propagateViaForces(NODE *node, std::set< VIA * > &vias)
DRAG_ALGO(ROUTER *aRouter)
void Add(const LINE &aLine)
std::vector< ITEM * > & Items()
Base class for PNS router board items.
virtual void Unmark(int aMarker=-1) const
const PNS_LAYER_RANGE & Layers() const
virtual NET_HANDLE Net() const
PnsKind Kind() const
Return the type (kind) of the item.
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
Represents a track on a PCB, connecting two non-trivial joints (that is, vias, pads,...
OPT_BOX2I ChangedArea(const LINE *aOther) const
void DragArc(const VECTOR2I &aP, int aIndex)
const SHAPE_LINE_CHAIN & CLine() const
SHAPE_LINE_CHAIN & Line()
Modifiable accessor to the underlying shape.
void DragCorner(const VECTOR2I &aP, int aIndex, bool aFreeAngle=false, DIRECTION_45 aPreferredEndingDirection=DIRECTION_45())
void SetSnapThreshhold(int aThreshhold)
virtual void Unmark(int aMarker=-1) const override
void DragSegment(const VECTOR2I &aP, int aIndex, bool aFreeAngle=false)
void Reverse()
Reverse the point/vertex order.
virtual void ClearLinks()
Erase the linking information. Used to detach the line from the owning node.
Keep the router "world" - i.e.
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.
const LINE AssembleLine(LINKED_ITEM *aSeg, int *aOriginSegmentIndex=nullptr, bool aStopAtLockedJoints=false, bool aFollowLockedSegments=false, bool aAllowSegmentSizeMismatch=true)
Follow the joint map to assemble a line connecting two non-trivial joints starting from segment aSeg.
Perform various optimizations of the lines being routed, attempting to make the lines shorter and les...
void SetPreserveVertex(const VECTOR2I &aV)
void SetRestrictArea(const BOX2I &aArea, bool aStrict=true)
void SetEffortLevel(int aEffort)
static bool Optimize(LINE *aLine, int aEffortLevel, NODE *aWorld, const VECTOR2I &aV=VECTOR2I(0, 0))
A quick shortcut to optimize a line without creating and setting up an optimizer.
@ LIMIT_CORNER_COUNT
Do not attempt to optimize if the resulting line's corner count is outside the predefined range.
@ MERGE_SEGMENTS
Reduce corner cost iteratively.
@ MERGE_COLINEAR
Merge co-linear segments.
@ REQUIRE_OBTUSE_ANGLES
Try to prevent 90-degree or acute corners in a drag.
void SetFailureReason(const wxString &aReason)
int ViaForcePropIterationLimit() const
bool SmoothDraggedSegments() const
Return true if smoothing segments during dragging is enabled.
PNS_MODE Mode() const
Return the routing mode.
int Width() const override
@ SHP_DONT_LOCK_ENDPOINTS
const VIA_HANDLE MakeHandle() const
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)
EDA_ANGLE GetCentralAngle() const
Get the "central angle" of the arc - this is the angle at the point of the "pie slice".
const VECTOR2I & GetArcMid() const
const VECTOR2I & GetP1() const
const VECTOR2I & GetP0() 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 Split(const VECTOR2I &aP, bool aExact=false)
Insert the point aP belonging to one of the our segments, splitting the adjacent segment in two.
int PointCount() const
Return the number of points (vertices) in this line chain.
ssize_t ArcIndex(size_t aSegment) const
Return the arc index for the given segment index.
const VECTOR2I & CPoint(int aIndex) const
Return a reference to a given point in 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 Find(const VECTOR2I &aP, int aThreshold=0) const
Search for point aP.
constexpr extended_type Dot(const VECTOR2< T > &aVector) const
Compute dot product of self with aVector.
static constexpr EDA_ANGLE ANGLE_180
Push and Shove diff pair dimensions (gap) settings dialog.
@ RM_MarkObstacles
Ignore collisions, mark obstacles.
@ RM_Walkaround
Only walk around.
std::unique_ptr< typename std::remove_const< T >::type > Clone(const T &aItem)
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,...)
LINE lines[MaxWalkPolicies]
STATUS status[MaxWalkPolicies]
Casted dyn_cast(From aObject)
A lightweight dynamic downcast.
VECTOR2< int32_t > VECTOR2I
VECTOR2< double > VECTOR2D