KiCad PCB EDA Suite
PNS::LINE_PLACER Class Reference

Single track placement algorithm. More...

#include <pns_line_placer.h>

Inheritance diagram for PNS::LINE_PLACER:
PNS::PLACEMENT_ALGO PNS::ALGO_BASE

Public Member Functions

 LINE_PLACER (ROUTER *aRouter)
 
 ~LINE_PLACER ()
 
bool Start (const VECTOR2I &aP, ITEM *aStartItem) override
 Start routing a single track at point aP, taking item aStartItem as anchor (unless NULL). More...
 
bool Move (const VECTOR2I &aP, ITEM *aEndItem) override
 Move the end of the currently routed trace to the point aP, taking aEndItem as anchor (if not NULL). More...
 
bool FixRoute (const VECTOR2I &aP, ITEM *aEndItem, bool aForceFinish) override
 Commit the currently routed track to the parent node taking aP as the final end point and aEndItem as the final anchor (if provided). More...
 
bool UnfixRoute () override
 
bool CommitPlacement () override
 
bool AbortPlacement () override
 
bool HasPlacedAnything () const override
 
bool ToggleVia (bool aEnabled) override
 Enable/disable a via at the end of currently routed trace. More...
 
bool SetLayer (int aLayer) override
 Set the current routing layer. More...
 
const LINEHead () const
 Return the "head" of the line being placed, that is the volatile part that has not been "fixed" yet. More...
 
const LINETail () const
 Return the "tail" of the line being placed, the part which has already wrapped around and shoved some obstacles. More...
 
const LINE Trace () const
 Return the complete routed line. More...
 
const ITEM_SET Traces () override
 Return the complete routed line, as a single-member ITEM_SET. More...
 
const VECTOR2ICurrentEnd () const override
 Return the current end of the line being placed. More...
 
const std::vector< int > CurrentNets () const override
 Return the net code of currently routed track. More...
 
int CurrentLayer () const override
 Return the layer of currently routed track. More...
 
NODECurrentNode (bool aLoopsRemoved=false) const override
 Return the most recent world state. More...
 
void FlipPosture () override
 Toggle the current posture (straight/diagonal) of the trace head. More...
 
void UpdateSizes (const SIZES_SETTINGS &aSizes) override
 Perform on-the-fly update of the width, via diameter & drill size from a settings class. More...
 
void SetOrthoMode (bool aOrthoMode) override
 Function SetOrthoMode() More...
 
bool IsPlacingVia () const override
 Function IsPlacingVia() More...
 
void GetModifiedNets (std::vector< int > &aNets) const override
 Function GetModifiedNets. More...
 
bool SplitAdjacentSegments (NODE *aNode, ITEM *aSeg, const VECTOR2I &aP)
 Check if point aP lies on segment aSeg. More...
 
ROUTERRouter () const
 Return current router settings. More...
 
ROUTING_SETTINGSSettings () const
 Return the logger object, allowing to dump geometry to a file. More...
 
virtual LOGGERLogger ()
 
void SetLogger (LOGGER *aLogger)
 
void SetDebugDecorator (DEBUG_DECORATOR *aDecorator)
 Assign a debug decorator allowing this algo to draw extra graphics for visual debugging. More...
 
DEBUG_DECORATORDbg () const
 
const BOX2IVisibleViewArea () const
 

Protected Attributes

DEBUG_DECORATORm_debugDecorator
 
ROUTERm_router
 
LOGGERm_logger
 

Private Member Functions

bool route (const VECTOR2I &aP)
 Re-route the current track to point aP. More...
 
void updateLeadingRatLine ()
 Draw the "leading" rats nest line, which connects the end of currently routed track and the nearest yet unrouted item. More...
 
void setWorld (NODE *aWorld)
 Set the board to route. More...
 
void initPlacement ()
 Initialize placement of a new line with given parameters. More...
 
void setInitialDirection (const DIRECTION_45 &aDirection)
 Set preferred direction of the very first track segment to be laid. More...
 
void removeLoops (NODE *aNode, LINE &aLatest)
 Searches aNode for traces concurrent to aLatest and removes them. More...
 
void simplifyNewLine (NODE *aNode, LINKED_ITEM *aLatest)
 Assemble a line starting from segment or arc aLatest, removes collinear segments and redundant vertices. More...
 
bool handleSelfIntersections ()
 Check if the head of the track intersects its tail. More...
 
bool handlePullback ()
 Deal with pull-back: reduces the tail if head trace is moved backwards wrs to the current tail direction. More...
 
bool mergeHead ()
 Moves "established" segments from the head to the tail if certain conditions are met. More...
 
bool reduceTail (const VECTOR2I &aEnd)
 Attempt to reduce the number of segments in the tail by trying to replace a certain number of latest tail segments with a direct trace leading to aEnd that does not collide with anything. More...
 
bool optimizeTailHeadTransition ()
 Try to reduce the corner count of the most recent part of tail/head by merging obtuse/collinear segments. More...
 
bool routeHead (const VECTOR2I &aP, LINE &aNewHead)
 Compute the head trace between the current start point (m_p_start) and point aP, starting with direction defined in m_direction. More...
 
void routeStep (const VECTOR2I &aP)
 Perform a single routing algorithm step, for the end point aP. More...
 
bool rhWalkOnly (const VECTOR2I &aP, LINE &aNewHead)
 Route step shove mode. More...
 
bool rhShoveOnly (const VECTOR2I &aP, LINE &aNewHead)
 Route step mark obstacles mode. More...
 
bool rhMarkObstacles (const VECTOR2I &aP, LINE &aNewHead)
 
const VIA makeVia (const VECTOR2I &aP)
 
bool buildInitialLine (const VECTOR2I &aP, LINE &aHead, bool aForceNoVia=false)
 

Private Attributes

DIRECTION_45 m_direction
 current routing direction More...
 
DIRECTION_45 m_initial_direction
 routing direction for new traces More...
 
LINE m_head
 the volatile part of the track from the previously analyzed point to the current routing destination More...
 
LINE m_last_head
 Most recent successful (non-colliding) head. More...
 
LINE m_tail
 routing "tail": part of the track that has been already fixed due to collisions with obstacles More...
 
NODEm_world
 pointer to world to search colliding items More...
 
VECTOR2I m_p_start
 current routing start (end of tail, beginning of head) More...
 
std::unique_ptr< SHOVEm_shove
 The shove engine. More...
 
NODEm_currentNode
 Current world state. More...
 
NODEm_lastNode
 Postprocessed world state (including marked collisions & removed loops) More...
 
SIZES_SETTINGS m_sizes
 
bool m_placingVia
 
int m_currentNet
 
int m_currentLayer
 
VECTOR2I m_currentEnd
 
VECTOR2I m_currentStart
 
LINE m_currentTrace
 
ITEMm_startItem
 
ITEMm_endItem
 
bool m_idle
 
bool m_chainedPlacement
 
bool m_orthoMode
 
bool m_placementCorrect
 
FIXED_TAIL m_fixedTail
 
MOUSE_TRAIL_TRACER m_mouseTrailTracer
 

Detailed Description

Single track placement algorithm.

Interactively routes a track. Applies shove and walkaround algorithms when needed.

Definition at line 84 of file pns_line_placer.h.

Constructor & Destructor Documentation

◆ LINE_PLACER()

PNS::LINE_PLACER::LINE_PLACER ( ROUTER aRouter)

Definition at line 41 of file pns_line_placer.cpp.

41 :
42 PLACEMENT_ALGO( aRouter )
43{
45 m_world = nullptr;
46 m_shove = nullptr;
47 m_currentNode = nullptr;
48 m_idle = true;
49
50 // Init temporary variables (do not leave uninitialized members)
51 m_lastNode = nullptr;
52 m_placingVia = false;
53 m_currentNet = 0;
55 m_startItem = nullptr;
56 m_endItem = nullptr;
57 m_chainedPlacement = false;
58 m_orthoMode = false;
59 m_placementCorrect = false;
60}
NODE * m_lastNode
Postprocessed world state (including marked collisions & removed loops)
std::unique_ptr< SHOVE > m_shove
The shove engine.
NODE * m_currentNode
Current world state.
NODE * m_world
pointer to world to search colliding items
DIRECTION_45 m_initial_direction
routing direction for new traces
PLACEMENT_ALGO(ROUTER *aRouter)

References m_chainedPlacement, m_currentLayer, m_currentNet, m_currentNode, m_endItem, m_idle, m_initial_direction, m_lastNode, m_orthoMode, m_placementCorrect, m_placingVia, m_shove, m_startItem, m_world, and DIRECTION_45::N.

◆ ~LINE_PLACER()

PNS::LINE_PLACER::~LINE_PLACER ( )

Definition at line 63 of file pns_line_placer.cpp.

64{
65}

Member Function Documentation

◆ AbortPlacement()

bool PNS::LINE_PLACER::AbortPlacement ( )
overridevirtual

Reimplemented from PNS::PLACEMENT_ALGO.

Definition at line 1816 of file pns_line_placer.cpp.

1817{
1819 return true;
1820}
void KillChildren()
Definition: pns_node.cpp:1451

References PNS::NODE::KillChildren(), and m_world.

◆ buildInitialLine()

bool PNS::LINE_PLACER::buildInitialLine ( const VECTOR2I aP,
LINE aHead,
bool  aForceNoVia = false 
)
private

Definition at line 1729 of file pns_line_placer.cpp.

1730{
1732 DIRECTION_45 guessedDir = m_mouseTrailTracer.GetPosture( aP );
1733
1734 wxLogTrace( wxT( "PNS" ),
1735 wxT( "buildInitialLine: m_direction %s, guessedDir %s, tail points %d" ),
1736 m_direction.Format(), guessedDir.Format(), m_tail.PointCount() );
1737
1739 // Rounded corners don't make sense when routing orthogonally (single track at a time)
1740 if( m_orthoMode )
1741 cornerMode = DIRECTION_45::CORNER_MODE::MITERED_45;
1742
1743 PNS_DBG( Dbg(), AddPoint, m_p_start, WHITE, 10000, wxT( "pstart [buildInitial]" ) );
1744
1745
1746 if( m_p_start == aP )
1747 {
1748 l.Clear();
1749 }
1750 else
1751 {
1752 if( Settings().GetFreeAngleMode() && Settings().Mode() == RM_MarkObstacles )
1753 {
1754 l = SHAPE_LINE_CHAIN( { m_p_start, aP } );
1755 }
1756 else
1757 {
1758 if( !m_tail.PointCount() )
1759 l = guessedDir.BuildInitialTrace( m_p_start, aP, false, cornerMode );
1760 else
1761 l = m_direction.BuildInitialTrace( m_p_start, aP, false, cornerMode );
1762 }
1763
1764 if( l.SegmentCount() > 1 && m_orthoMode )
1765 {
1766 VECTOR2I newLast = l.CSegment( 0 ).LineProject( l.CPoint( -1 ) );
1767
1768 l.Remove( -1, -1 );
1769 l.SetPoint( 1, newLast );
1770 }
1771 }
1772
1773 aHead.SetLayer( m_currentLayer );
1774 aHead.SetShape( l );
1775
1776 PNS_DBG( Dbg(), AddItem, &aHead, CYAN, 10000, wxT( "initial-trace" ) );
1777
1778
1779 if( !m_placingVia || aForceNoVia )
1780 return true;
1781
1782 VIA v( makeVia( aP ) );
1783 v.SetNet( aHead.Net() );
1784
1785 if( Settings().Mode() == RM_MarkObstacles )
1786 {
1787 aHead.AppendVia( v );
1788 return true;
1789 }
1790
1791 VECTOR2I force;
1792 VECTOR2I lead = aP - m_p_start;
1793
1794 bool solidsOnly = ( Settings().Mode() != RM_Walkaround );
1795
1796 if( v.PushoutForce( m_currentNode, lead, force, solidsOnly, 40 ) )
1797 {
1798 SHAPE_LINE_CHAIN line =
1799 guessedDir.BuildInitialTrace( m_p_start, aP + force, false, cornerMode );
1800 aHead = LINE( aHead, line );
1801
1802 v.SetPos( v.Pos() + force );
1803 return true;
1804 }
1805
1806 return false; // via placement unsuccessful
1807}
Represent route directions & corner angles in a 45-degree metric.
Definition: direction45.h:37
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.
CORNER_MODE
Corner modes.
Definition: direction45.h:67
const std::string Format() const
Format the direction in a human readable word.
Definition: direction45.h:129
ROUTING_SETTINGS & Settings() const
Return the logger object, allowing to dump geometry to a file.
DEBUG_DECORATOR * Dbg() const
Definition: pns_algo_base.h:78
LINE m_tail
routing "tail": part of the track that has been already fixed due to collisions with obstacles
MOUSE_TRAIL_TRACER m_mouseTrailTracer
const VIA makeVia(const VECTOR2I &aP)
VECTOR2I m_p_start
current routing start (end of tail, beginning of head)
DIRECTION_45 m_direction
current routing direction
int PointCount() const
Definition: pns_line.h:140
DIRECTION_45 GetPosture(const VECTOR2I &aP)
PNS_MODE Mode() const
Set the routing mode.
DIRECTION_45::CORNER_MODE GetCornerMode() const
VECTOR2I LineProject(const VECTOR2I &aP) const
Compute the perpendicular projection point of aP on a line passing through ends of the segment.
Definition: seg.cpp:302
Represent a polyline containing arcs as well as line segments: A chain of connected line and/or arc s...
void SetPoint(int aIndex, const VECTOR2I &aPos)
Move a point to a specific location.
void Clear()
Remove all points from the line chain.
const VECTOR2I & CPoint(int aIndex) const
Return a reference to a given point in the line chain.
int SegmentCount() const
Return the number of segments in this 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.
@ WHITE
Definition: color4d.h:48
@ CYAN
Definition: color4d.h:58
@ RM_MarkObstacles
Ignore collisions, mark obstacles.
@ RM_Walkaround
Only walk around.
#define PNS_DBG(dbg, method,...)
@ VIA
Normal via.
Definition: router_tool.cpp:76

References PNS::LINE::AppendVia(), DIRECTION_45::BuildInitialTrace(), SHAPE_LINE_CHAIN::Clear(), SHAPE_LINE_CHAIN::CPoint(), SHAPE_LINE_CHAIN::CSegment(), CYAN, PNS::ALGO_BASE::Dbg(), DIRECTION_45::Format(), PNS::ROUTING_SETTINGS::GetCornerMode(), PNS::MOUSE_TRAIL_TRACER::GetPosture(), SEG::LineProject(), m_currentLayer, m_currentNode, m_direction, m_mouseTrailTracer, m_orthoMode, m_p_start, m_placingVia, m_tail, makeVia(), PNS::ROUTING_SETTINGS::Mode(), PNS::ITEM::Net(), PNS_DBG, PNS::LINE::PointCount(), PNS::VIA::Pos(), PNS::VIA::PushoutForce(), SHAPE_LINE_CHAIN::Remove(), PNS::RM_MarkObstacles, PNS::RM_Walkaround, SHAPE_LINE_CHAIN::SegmentCount(), PNS::ITEM::SetLayer(), PNS::ITEM::SetNet(), SHAPE_LINE_CHAIN::SetPoint(), PNS::VIA::SetPos(), PNS::LINE::SetShape(), PNS::ALGO_BASE::Settings(), and WHITE.

Referenced by rhMarkObstacles(), rhShoveOnly(), and rhWalkOnly().

◆ CommitPlacement()

bool PNS::LINE_PLACER::CommitPlacement ( )
overridevirtual

Reimplemented from PNS::PLACEMENT_ALGO.

Definition at line 1530 of file pns_line_placer.cpp.

1531{
1532 if( Settings().Mode() == PNS::RM_Shove )
1533 {
1534 m_shove->RewindToLastLockedNode();
1535 m_lastNode = m_shove->CurrentNode();
1537 }
1538
1539 if( m_lastNode )
1541
1542 m_lastNode = nullptr;
1543 m_currentNode = nullptr;
1544 return true;
1545}
ROUTER * Router() const
Return current router settings.
Definition: pns_algo_base.h:54
void CommitRouting()
Definition: pns_router.cpp:728
@ RM_Shove
Only shove.

References PNS::ROUTER::CommitRouting(), PNS::NODE::KillChildren(), m_currentNode, m_lastNode, m_shove, PNS::RM_Shove, PNS::ALGO_BASE::Router(), and PNS::ALGO_BASE::Settings().

◆ CurrentEnd()

const VECTOR2I & PNS::LINE_PLACER::CurrentEnd ( ) const
inlineoverridevirtual

Return the current end of the line being placed.

It may not be equal to the cursor position due to collisions.

Implements PNS::PLACEMENT_ALGO.

Definition at line 155 of file pns_line_placer.h.

156 {
157 return m_currentEnd;
158 }

References m_currentEnd.

◆ CurrentLayer()

int PNS::LINE_PLACER::CurrentLayer ( ) const
inlineoverridevirtual

Return the layer of currently routed track.

Implements PNS::PLACEMENT_ALGO.

Definition at line 171 of file pns_line_placer.h.

172 {
173 return m_currentLayer;
174 }

References m_currentLayer.

◆ CurrentNets()

const std::vector< int > PNS::LINE_PLACER::CurrentNets ( ) const
inlineoverridevirtual

Return the net code of currently routed track.

Implements PNS::PLACEMENT_ALGO.

Definition at line 163 of file pns_line_placer.h.

164 {
165 return std::vector<int>( 1, m_currentNet );
166 }

References m_currentNet.

◆ CurrentNode()

NODE * PNS::LINE_PLACER::CurrentNode ( bool  aLoopsRemoved = false) const
overridevirtual

Return the most recent world state.

Implements PNS::PLACEMENT_ALGO.

Definition at line 1079 of file pns_line_placer.cpp.

1080{
1081 if( aLoopsRemoved && m_lastNode )
1082 return m_lastNode;
1083
1084 return m_currentNode;
1085}

References m_currentNode, and m_lastNode.

◆ Dbg()

◆ FixRoute()

bool PNS::LINE_PLACER::FixRoute ( const VECTOR2I aP,
ITEM aEndItem,
bool  aForceFinish 
)
overridevirtual

Commit the currently routed track to the parent node taking aP as the final end point and aEndItem as the final anchor (if provided).

Returns
true if route has been committed. May return false if the routing result is violating design rules. In such cases, the track is only committed if CanViolateDRC() is on.

<

Todo:
Determine what to do if m_lastNode is a null pointer. I'm guessing return false but someone with more knowledge of the code will need to determine that..

Implements PNS::PLACEMENT_ALGO.

Definition at line 1297 of file pns_line_placer.cpp.

1298{
1299 bool fixAll = Settings().GetFixAllSegments();
1300 bool realEnd = false;
1301
1302 LINE pl = Trace();
1303
1304 if( Settings().Mode() == RM_MarkObstacles )
1305 {
1306 // Mark Obstacles is sort of a half-manual, half-automated mode in which the
1307 // user has more responsibility and authority.
1308
1309 if( aEndItem )
1310 {
1311 // The user has indicated a connection should be made. If either the trace or
1312 // endItem is net-less, then allow the connection by adopting the net of the other.
1313 if( m_currentNet <= 0 )
1314 {
1315 m_currentNet = aEndItem->Net();
1316 pl.SetNet( m_currentNet );
1317 }
1318 else if (aEndItem->Net() <= 0 )
1319 {
1320 aEndItem->SetNet( m_currentNet );
1321 }
1322 }
1323
1324 // Collisions still prevent fixing unless "Allow DRC violations" is checked
1325 if( !Settings().AllowDRCViolations() && m_world->CheckColliding( &pl ) )
1326 return false;
1327 }
1328
1329 const SHAPE_LINE_CHAIN& l = pl.CLine();
1330
1331 if( !l.SegmentCount() )
1332 {
1333 if( m_lastNode )
1334 {
1335 // Do a final optimization to the stored state
1336 NODE::ITEM_VECTOR removed, added;
1337 m_lastNode->GetUpdatedItems( removed, added );
1338
1339 if( !added.empty() && added.back()->Kind() == ITEM::SEGMENT_T )
1340 simplifyNewLine( m_lastNode, static_cast<SEGMENT*>( added.back() ) );
1341 }
1342
1343 // Nothing to commit if we have an empty line
1344 if( !pl.EndsWithVia() )
1345 return false;
1346
1349 if( m_lastNode )
1350 {
1351 m_lastNode->Add( Clone( pl.Via() ) );
1352 m_shove->AddLockedSpringbackNode( m_lastNode );
1353 }
1354
1355 m_currentNode = nullptr;
1356
1357 m_idle = true;
1358 m_placementCorrect = true;
1359 return true;
1360 }
1361
1362 VECTOR2I p_pre_last = l.CPoint( -1 );
1363 const VECTOR2I p_last = l.CPoint( -1 );
1364
1365 if( l.PointCount() > 2 )
1366 p_pre_last = l.CPoint( -2 );
1367
1368 if( aEndItem && m_currentNet >= 0 && m_currentNet == aEndItem->Net() )
1369 realEnd = true;
1370
1371 if( aForceFinish )
1372 realEnd = true;
1373
1374 // TODO: Rollback doesn't work properly if fix-all isn't enabled and we are placing arcs,
1375 // so if we are, act as though we are in fix-all mode.
1376 if( !fixAll && l.ArcCount() )
1377 fixAll = true;
1378
1379 // TODO: lastDirSeg will be calculated incorrectly if we end on an arc
1380 SEG lastDirSeg = ( !fixAll && l.SegmentCount() > 1 ) ? l.CSegment( -2 ) : l.CSegment( -1 );
1381 DIRECTION_45 d_last( lastDirSeg );
1382
1383 int lastV;
1384
1385 if( realEnd || m_placingVia || fixAll )
1386 lastV = l.SegmentCount();
1387 else
1388 lastV = std::max( 1, l.SegmentCount() - 1 );
1389
1390 ARC arc;
1391 SEGMENT seg;
1392 LINKED_ITEM* lastItem = nullptr;
1393 int lastArc = -1;
1394
1395 for( int i = 0; i < lastV; i++ )
1396 {
1397 ssize_t arcIndex = l.ArcIndex( i );
1398
1399 if( arcIndex < 0 || ( lastArc >= 0 && i == lastV - 1 && !l.IsPtOnArc( lastV ) ) )
1400 {
1401 seg = SEGMENT( pl.CSegment( i ), m_currentNet );
1402 seg.SetWidth( pl.Width() );
1403 seg.SetLayer( m_currentLayer );
1404
1405 std::unique_ptr<SEGMENT> sp = std::make_unique<SEGMENT>( seg );
1406 lastItem = sp.get();
1407
1408 if( !m_lastNode->Add( std::move( sp ) ) )
1409 lastItem = nullptr;
1410 }
1411 else
1412 {
1413 if( arcIndex == lastArc )
1414 continue;
1415
1416 arc = ARC( l.Arc( arcIndex ), m_currentNet );
1417 arc.SetWidth( pl.Width() );
1418 arc.SetLayer( m_currentLayer );
1419
1420 std::unique_ptr<ARC> ap = std::make_unique<ARC>( arc );
1421 lastItem = ap.get();
1422
1423 if( !m_lastNode->Add( std::move( ap ) ) )
1424 lastItem = nullptr;
1425
1426 lastArc = arcIndex;
1427 }
1428 }
1429
1430 if( pl.EndsWithVia() )
1431 m_lastNode->Add( Clone( pl.Via() ) );
1432
1433 if( realEnd && lastItem )
1434 simplifyNewLine( m_lastNode, lastItem );
1435
1436 if( !realEnd )
1437 {
1438 setInitialDirection( d_last );
1439 m_currentStart = ( m_placingVia || fixAll ) ? p_last : p_pre_last;
1440
1441 VECTOR2I ps;
1442 if( m_tail.SegmentCount() )
1443 ps = m_tail.CPoint( 0 );
1444 else
1445 ps = m_p_start;
1446
1448
1449 m_startItem = nullptr;
1450 m_placingVia = false;
1451 m_chainedPlacement = !pl.EndsWithVia();
1452
1455
1456 m_head.Line().Clear();
1457 m_tail.Line().Clear();
1458 m_head.RemoveVia();
1459 m_tail.RemoveVia();
1462
1463 m_shove->AddLockedSpringbackNode( m_currentNode );
1464
1465 DIRECTION_45 lastSegDir = pl.EndsWithVia() ? DIRECTION_45::UNDEFINED : d_last;
1466
1471
1472 m_placementCorrect = true;
1473 }
1474 else
1475 {
1476 m_shove->AddLockedSpringbackNode( m_lastNode );
1477 m_placementCorrect = true;
1478 m_idle = true;
1479 }
1480
1481 return realEnd;
1482}
void AddStage(const VECTOR2I &aStart, int aLayer, bool placingVias, DIRECTION_45 direction, NODE *aNode)
@ SEGMENT_T
Definition: pns_item.h:66
const LINE Trace() const
Return the complete routed line.
LINE m_head
the volatile part of the track from the previously analyzed point to the current routing destination
void setInitialDirection(const DIRECTION_45 &aDirection)
Set preferred direction of the very first track segment to be laid.
void simplifyNewLine(NODE *aNode, LINKED_ITEM *aLatest)
Assemble a line starting from segment or arc aLatest, removes collinear segments and redundant vertic...
FIXED_TAIL m_fixedTail
const VECTOR2I & CPoint(int aIdx) const
Definition: pns_line.h:145
void RemoveVia()
Definition: pns_line.h:192
SHAPE_LINE_CHAIN & Line()
Definition: pns_line.h:136
int SegmentCount() const
Definition: pns_line.h:139
int Width() const
Return true if the line is geometrically identical as line aOther.
Definition: pns_line.h:156
void SetDefaultDirections(DIRECTION_45 aInitDirection, DIRECTION_45 aLastSegDir)
void AddTrailPoint(const VECTOR2I &aP)
NODE * Branch()
Create a lightweight copy (called branch) of self that tracks the changes (added/removed items) wrs t...
Definition: pns_node.cpp:139
std::vector< ITEM * > ITEM_VECTOR
Definition: pns_node.h:161
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.
Definition: pns_node.cpp:1384
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.
Definition: pns_node.cpp:468
bool Add(std::unique_ptr< SEGMENT > aSegment, bool aAllowRedundant=false)
Add an item to the current node.
Definition: pns_node.cpp:656
Definition: seg.h:42
bool IsPtOnArc(size_t aPtIndex) const
const SHAPE_ARC & Arc(size_t aArc) const
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.
size_t ArcCount() const
std::unique_ptr< typename std::remove_const< T >::type > Clone(const T &aItem)
Definition: pns_item.h:271

References PNS::NODE::Add(), PNS::FIXED_TAIL::AddStage(), PNS::MOUSE_TRAIL_TRACER::AddTrailPoint(), SHAPE_LINE_CHAIN::Arc(), SHAPE_LINE_CHAIN::ArcCount(), SHAPE_LINE_CHAIN::ArcIndex(), PNS::NODE::Branch(), PNS::NODE::CheckColliding(), SHAPE_LINE_CHAIN::Clear(), PNS::MOUSE_TRAIL_TRACER::Clear(), PNS::LINE::CLine(), PNS::Clone(), PNS::LINE::CPoint(), SHAPE_LINE_CHAIN::CPoint(), PNS::LINE::CSegment(), SHAPE_LINE_CHAIN::CSegment(), PNS::LINE::EndsWithVia(), PNS::ROUTING_SETTINGS::GetFixAllSegments(), PNS::NODE::GetUpdatedItems(), SHAPE_LINE_CHAIN::IsPtOnArc(), PNS::LINE::Line(), m_chainedPlacement, m_currentLayer, m_currentNet, m_currentNode, m_currentStart, m_direction, m_fixedTail, m_head, m_idle, m_initial_direction, m_lastNode, m_mouseTrailTracer, m_p_start, m_placementCorrect, m_placingVia, m_shove, m_startItem, m_tail, m_world, PNS::ITEM::Net(), SHAPE_LINE_CHAIN::PointCount(), PNS::LINE::RemoveVia(), PNS::RM_MarkObstacles, PNS::ITEM::SEGMENT_T, SHAPE_LINE_CHAIN::SegmentCount(), PNS::LINE::SegmentCount(), PNS::MOUSE_TRAIL_TRACER::SetDefaultDirections(), setInitialDirection(), PNS::ITEM::SetLayer(), PNS::ITEM::SetNet(), PNS::ALGO_BASE::Settings(), PNS::MOUSE_TRAIL_TRACER::SetTolerance(), PNS::ARC::SetWidth(), PNS::SEGMENT::SetWidth(), simplifyNewLine(), Trace(), DIRECTION_45::UNDEFINED, PNS::LINE::Via(), and PNS::LINE::Width().

◆ FlipPosture()

void PNS::LINE_PLACER::FlipPosture ( )
overridevirtual

Toggle the current posture (straight/diagonal) of the trace head.

Reimplemented from PNS::PLACEMENT_ALGO.

Definition at line 1073 of file pns_line_placer.cpp.

References PNS::MOUSE_TRAIL_TRACER::FlipPosture(), and m_mouseTrailTracer.

◆ GetModifiedNets()

void PNS::LINE_PLACER::GetModifiedNets ( std::vector< int > &  aNets) const
overridevirtual

Function GetModifiedNets.

Returns the net codes of all currently routed trace(s)

Reimplemented from PNS::PLACEMENT_ALGO.

Definition at line 1810 of file pns_line_placer.cpp.

1811{
1812 aNets.push_back( m_currentNet );
1813}

References m_currentNet.

◆ handlePullback()

bool PNS::LINE_PLACER::handlePullback ( )
private

Deal with pull-back: reduces the tail if head trace is moved backwards wrs to the current tail direction.

Returns
true if the line has been changed.

Definition at line 180 of file pns_line_placer.cpp.

181{
182 SHAPE_LINE_CHAIN& head = m_head.Line();
183 SHAPE_LINE_CHAIN& tail = m_tail.Line();
184
185 if( head.PointCount() < 2 )
186 return false;
187
188 int n = tail.PointCount();
189
190 if( n == 0 )
191 {
192 return false;
193 }
194 else if( n == 1 )
195 {
196 m_p_start = tail.CPoint( 0 );
197 PNS_DBG( Dbg(), AddPoint, m_p_start, WHITE, 10000, wxT( "new-pstart [pullback]" ) );
198
199 tail.Clear();
200 return true;
201 }
202
203 DIRECTION_45 first_head, last_tail;
204
205 wxASSERT( tail.PointCount() >= 2 );
206
207 if( !head.IsPtOnArc( 0 ) )
208 first_head = DIRECTION_45( head.CSegment( 0 ) );
209 else
210 first_head = DIRECTION_45( head.CArcs()[head.ArcIndex(0)] );
211
212 int lastSegIdx = tail.PointCount() - 2;
213
214 if( !tail.IsPtOnArc( lastSegIdx ) )
215 last_tail = DIRECTION_45( tail.CSegment( lastSegIdx ) );
216 else
217 last_tail = DIRECTION_45( tail.CArcs()[tail.ArcIndex(lastSegIdx)] );
218
219 DIRECTION_45::AngleType angle = first_head.Angle( last_tail );
220
221 // case 1: we have a defined routing direction, and the currently computed
222 // head goes in different one.
223 bool pullback_1 = false; // (m_direction != DIRECTION_45::UNDEFINED && m_direction != first_head);
224
225 // case 2: regardless of the current routing direction, if the tail/head
226 // extremities form an acute or right angle, reduce the tail by one segment
227 // (and hope that further iterations) will result with a cleaner trace
228 bool pullback_2 = ( angle == DIRECTION_45::ANG_RIGHT || angle == DIRECTION_45::ANG_ACUTE );
229
230 if( pullback_1 || pullback_2 )
231 {
232 lastSegIdx = tail.PrevShape( -1 );
233
234 if( !tail.IsPtOnArc( lastSegIdx ) )
235 {
236 const SEG& seg = tail.CSegment( lastSegIdx );
237 m_direction = DIRECTION_45( seg );
238 m_p_start = seg.A;
239 PNS_DBG( Dbg(), AddPoint, m_p_start, WHITE, 10000, wxT( "new-pstart [pullback3]" ) );
240
241 }
242 else
243 {
244 const SHAPE_ARC& arc = tail.CArcs()[tail.ArcIndex( lastSegIdx )];
245 m_direction = DIRECTION_45( arc );
246 m_p_start = arc.GetP0();
247 }
248
249 wxLogTrace( wxT( "PNS" ), wxT( "Placer: pullback triggered [%d] [%s %s]" ),
250 n, last_tail.Format().c_str(), first_head.Format().c_str() );
251
252 // erase the last point in the tail, hoping that the next iteration will
253 // result with a head trace that starts with a segment following our
254 // current direction.
255 if( n < 2 )
256 tail.Clear(); // don't leave a single-point tail
257 else
258 tail.RemoveShape( -1 );
259
260 if( !tail.SegmentCount() )
262
263 return true;
264 }
265
266 return false;
267}
AngleType Angle(const DIRECTION_45 &aOther) const
Return the type of angle between directions (this) and aOther.
Definition: direction45.h:181
AngleType
Represent kind of angle formed by vectors heading in two DIRECTION_45s.
Definition: direction45.h:78
VECTOR2I A
Definition: seg.h:49
const VECTOR2I & GetP0() const
Definition: shape_arc.h:112
int PrevShape(int aPointIndex) const
const std::vector< SHAPE_ARC > & CArcs() const
void RemoveShape(int aPointIndex)
Remove the shape at the given index from the line chain.
static DIRECTION_45::AngleType angle(const VECTOR2I &a, const VECTOR2I &b)

References SEG::A, DIRECTION_45::ANG_ACUTE, DIRECTION_45::ANG_RIGHT, DIRECTION_45::Angle(), PNS::angle(), SHAPE_LINE_CHAIN::ArcIndex(), SHAPE_LINE_CHAIN::CArcs(), SHAPE_LINE_CHAIN::Clear(), SHAPE_LINE_CHAIN::CPoint(), SHAPE_LINE_CHAIN::CSegment(), PNS::ALGO_BASE::Dbg(), DIRECTION_45::Format(), SHAPE_ARC::GetP0(), SHAPE_LINE_CHAIN::IsPtOnArc(), PNS::LINE::Line(), m_direction, m_head, m_initial_direction, m_p_start, m_tail, PNS_DBG, SHAPE_LINE_CHAIN::PointCount(), SHAPE_LINE_CHAIN::PrevShape(), SHAPE_LINE_CHAIN::RemoveShape(), SHAPE_LINE_CHAIN::SegmentCount(), and WHITE.

Referenced by routeStep().

◆ handleSelfIntersections()

bool PNS::LINE_PLACER::handleSelfIntersections ( )
private

Check if the head of the track intersects its tail.

If so, cuts the tail up to the intersecting segment and fixes the head direction to match the last segment before the cut.

Returns
true if the line has been changed.

Definition at line 103 of file pns_line_placer.cpp.

104{
106 SHAPE_LINE_CHAIN& head = m_head.Line();
107 SHAPE_LINE_CHAIN& tail = m_tail.Line();
108
109 // if there is no tail, there is nothing to intersect with
110 if( tail.PointCount() < 2 )
111 return false;
112
113 if( head.PointCount() < 2 )
114 return false;
115
116 // completely new head trace? chop off the tail
117 if( tail.CPoint(0) == head.CPoint(0) )
118 {
119 m_p_start = tail.CPoint( 0 );
120 PNS_DBG( Dbg(), AddPoint, m_p_start, WHITE, 10000, wxT( "new-pstart [sameP0]" ) );
122 tail.Clear();
123 return true;
124 }
125
126 tail.Intersect( head, ips );
127
128 // no intesection points - nothing to reduce
129 if( ips.empty() )
130 return false;
131
132 int n = INT_MAX;
133 VECTOR2I ipoint;
134
135 // if there is more than one intersection, find the one that is
136 // closest to the beginning of the tail.
137 for( const SHAPE_LINE_CHAIN::INTERSECTION& i : ips )
138 {
139 if( i.index_our < n )
140 {
141 n = i.index_our;
142 ipoint = i.p;
143 }
144 }
145
146 // ignore the point where head and tail meet
147 if( ipoint == head.CPoint( 0 ) || ipoint == tail.CPoint( -1 ) )
148 return false;
149
150 // Intersection point is on the first or the second segment: just start routing
151 // from the beginning
152 if( n < 2 )
153 {
154 m_p_start = tail.CPoint( 0 );
155 PNS_DBG( Dbg(), AddPoint, m_p_start, WHITE, 10000, wxT( "new-pstart [self-isect1]" ) );
156
158 tail.Clear();
159 head.Clear();
160
161 return true;
162 }
163 else
164 {
165 // Clip till the last tail segment before intersection.
166 // Set the direction to the one of this segment.
167 const SEG last = tail.CSegment( n - 1 );
168 m_p_start = last.A;
169 PNS_DBG( Dbg(), AddPoint, m_p_start, WHITE, 10000, wxT( "new-pstart [self-isect2]" ) );
170
171 m_direction = DIRECTION_45( last );
172 tail.Remove( n, -1 );
173 return true;
174 }
175
176 return false;
177}
int Intersect(const SEG &aSeg, INTERSECTIONS &aIp) const
Find all intersection points between our line chain and the segment aSeg.
std::vector< INTERSECTION > INTERSECTIONS
Represent an intersection between two line segments.

References SEG::A, SHAPE_LINE_CHAIN::Clear(), SHAPE_LINE_CHAIN::CPoint(), SHAPE_LINE_CHAIN::CSegment(), PNS::ALGO_BASE::Dbg(), SHAPE_LINE_CHAIN::Intersect(), PNS::LINE::Line(), m_direction, m_head, m_initial_direction, m_p_start, m_tail, PNS_DBG, SHAPE_LINE_CHAIN::PointCount(), SHAPE_LINE_CHAIN::Remove(), and WHITE.

Referenced by routeStep().

◆ HasPlacedAnything()

bool PNS::LINE_PLACER::HasPlacedAnything ( ) const
overridevirtual

Reimplemented from PNS::PLACEMENT_ALGO.

Definition at line 1524 of file pns_line_placer.cpp.

1525{
1527}
int StageCount() const

References m_fixedTail, m_placementCorrect, and PNS::FIXED_TAIL::StageCount().

Referenced by UpdateSizes().

◆ Head()

const LINE & PNS::LINE_PLACER::Head ( ) const
inline

Return the "head" of the line being placed, that is the volatile part that has not been "fixed" yet.

Definition at line 133 of file pns_line_placer.h.

133{ return m_head; }

References m_head.

◆ initPlacement()

void PNS::LINE_PLACER::initPlacement ( )
private

Initialize placement of a new line with given parameters.

Definition at line 1212 of file pns_line_placer.cpp.

1213{
1214 m_idle = false;
1215
1216 m_head.Line().Clear();
1217 m_tail.Line().Clear();
1224 m_head.RemoveVia();
1225 m_tail.RemoveVia();
1226
1229
1230 NODE* world = Router()->GetWorld();
1231
1232 world->KillChildren();
1233 NODE* rootNode = world->Branch();
1234
1236
1237 setWorld( rootNode );
1238
1239 wxLogTrace( wxT( "PNS" ), wxT( "world %p, intitial-direction %s layer %d" ),
1240 m_world,
1241 m_direction.Format().c_str(),
1243
1244 m_lastNode = nullptr;
1246
1247 m_shove = std::make_unique<SHOVE>( m_world->Branch(), Router() );
1248}
void SetNet(int aNet)
Definition: pns_item.h:151
void SetLayer(int aLayer)
Definition: pns_item.h:157
void setWorld(NODE *aWorld)
Set the board to route.
SIZES_SETTINGS m_sizes
bool SplitAdjacentSegments(NODE *aNode, ITEM *aSeg, const VECTOR2I &aP)
Check if point aP lies on segment aSeg.
void SetWidth(int aWidth)
Return line width.
Definition: pns_line.h:149
NODE * GetWorld() const
Definition: pns_router.h:154

References PNS::NODE::Branch(), SHAPE_LINE_CHAIN::Clear(), DIRECTION_45::Format(), PNS::ROUTER::GetWorld(), PNS::NODE::KillChildren(), PNS::LINE::Line(), m_currentLayer, m_currentNet, m_currentNode, m_currentStart, m_direction, m_head, m_idle, m_initial_direction, m_lastNode, m_p_start, m_shove, m_sizes, m_startItem, m_tail, m_world, PNS::LINE::RemoveVia(), PNS::ALGO_BASE::Router(), PNS::ITEM::SetLayer(), PNS::ITEM::SetNet(), PNS::LINE::SetWidth(), setWorld(), SplitAdjacentSegments(), and PNS::SIZES_SETTINGS::TrackWidth().

Referenced by Start().

◆ IsPlacingVia()

bool PNS::LINE_PLACER::IsPlacingVia ( ) const
inlineoverridevirtual

Function IsPlacingVia()

Returns true if the placer is placing a via (or more vias).

Reimplemented from PNS::PLACEMENT_ALGO.

Definition at line 196 of file pns_line_placer.h.

196{ return m_placingVia; }

References m_placingVia.

◆ Logger()

LOGGER * PNS::ALGO_BASE::Logger ( )
virtualinherited

Reimplemented in PNS::SHOVE.

Definition at line 34 of file pns_algo_base.cpp.

35{
36 return nullptr;
37}

Referenced by rhShoveOnly(), rhWalkOnly(), PNS::DRAGGER::Start(), and PNS::DRAGGER::tryWalkaround().

◆ makeVia()

const VIA PNS::LINE_PLACER::makeVia ( const VECTOR2I aP)
private

◆ mergeHead()

bool PNS::LINE_PLACER::mergeHead ( )
private

Moves "established" segments from the head to the tail if certain conditions are met.

Returns
true, if the line has been changed.

Definition at line 337 of file pns_line_placer.cpp.

338{
339 SHAPE_LINE_CHAIN& head = m_head.Line();
340 SHAPE_LINE_CHAIN& tail = m_tail.Line();
341
342 const int ForbiddenAngles = DIRECTION_45::ANG_ACUTE
345
346 head.Simplify();
347 tail.Simplify();
348
349 int n_head = head.ShapeCount();
350 int n_tail = tail.ShapeCount();
351
352 if( n_head < 3 )
353 {
354 wxLogTrace( wxT( "PNS" ), wxT( "Merge failed: not enough head segs." ) );
355 return false;
356 }
357
358 if( n_tail && head.CPoint( 0 ) != tail.CPoint( -1 ) )
359 {
360 wxLogTrace( wxT( "PNS" ), wxT( "Merge failed: head and tail discontinuous." ) );
361 return false;
362 }
363
364 if( m_head.CountCorners( ForbiddenAngles ) != 0 )
365 return false;
366
367 DIRECTION_45 dir_tail, dir_head;
368
369 if( !head.IsPtOnArc( 0 ) )
370 dir_head = DIRECTION_45( head.CSegment( 0 ) );
371 else
372 dir_head = DIRECTION_45( head.CArcs()[head.ArcIndex( 0 )] );
373
374 if( n_tail )
375 {
376 wxASSERT( tail.PointCount() >= 2 );
377 int lastSegIdx = tail.PointCount() - 2;
378
379 if( !tail.IsPtOnArc( lastSegIdx ) )
380 dir_tail = DIRECTION_45( tail.CSegment( -1 ) );
381 else
382 dir_tail = DIRECTION_45( tail.CArcs()[tail.ArcIndex( lastSegIdx )] );
383
384 if( dir_head.Angle( dir_tail ) & ForbiddenAngles )
385 return false;
386 }
387
388 tail.Append( head );
389
390 tail.Simplify();
391
392 SEG last = tail.CSegment( -1 );
393 m_p_start = last.B;
394
395 PNS_DBG( Dbg(), AddPoint, m_p_start, WHITE, 10000, wxT( "new-pstart [mergeHead]" ) );
396
397
398 int lastSegIdx = tail.PointCount() - 2;
399
400 if( !tail.IsArcSegment( lastSegIdx ) )
401 m_direction = DIRECTION_45( tail.CSegment( -1 ) );
402 else
403 m_direction = DIRECTION_45( tail.CArcs()[tail.ArcIndex( lastSegIdx )] );
404
405 head.Remove( 0, -1 );
406
407 // wxLogTrace( wxT( "PNS" ), wxT( "Placer: merge %d, new direction: %s" ), n_head,
408// m_direction.Format().c_str() );
409
410 head.Simplify();
411 tail.Simplify();
412
413 return true;
414}
int CountCorners(int aAngles) const
Definition: pns_line.cpp:135
VECTOR2I B
Definition: seg.h:50
SHAPE_LINE_CHAIN & Simplify(bool aRemoveColinear=true)
Simplify the line chain by removing colinear adjacent segments and duplicate vertices.
int ShapeCount() const
Return the number of shapes (line segments or arcs) in this line chain.
void Append(int aX, int aY, bool aAllowDuplication=false)
Append a new point at the end of the line chain.
bool IsArcSegment(size_t aSegment) const

References DIRECTION_45::ANG_ACUTE, DIRECTION_45::ANG_HALF_FULL, DIRECTION_45::ANG_UNDEFINED, DIRECTION_45::Angle(), SHAPE_LINE_CHAIN::Append(), SHAPE_LINE_CHAIN::ArcIndex(), SEG::B, SHAPE_LINE_CHAIN::CArcs(), PNS::LINE::CountCorners(), SHAPE_LINE_CHAIN::CPoint(), SHAPE_LINE_CHAIN::CSegment(), PNS::ALGO_BASE::Dbg(), SHAPE_LINE_CHAIN::IsArcSegment(), SHAPE_LINE_CHAIN::IsPtOnArc(), PNS::LINE::Line(), m_direction, m_head, m_p_start, m_tail, PNS_DBG, SHAPE_LINE_CHAIN::PointCount(), SHAPE_LINE_CHAIN::Remove(), SHAPE_LINE_CHAIN::ShapeCount(), SHAPE_LINE_CHAIN::Simplify(), and WHITE.

Referenced by routeStep().

◆ Move()

bool PNS::LINE_PLACER::Move ( const VECTOR2I aP,
ITEM aEndItem 
)
overridevirtual

Move the end of the currently routed trace to the point aP, taking aEndItem as anchor (if not NULL).

Implements PNS::PLACEMENT_ALGO.

Definition at line 1251 of file pns_line_placer.cpp.

1252{
1253 LINE current;
1254 VECTOR2I p = aP;
1255 int eiDepth = -1;
1256
1257 if( aEndItem && aEndItem->Owner() )
1258 eiDepth = static_cast<NODE*>( aEndItem->Owner() )->Depth();
1259
1260 if( m_lastNode )
1261 {
1262 delete m_lastNode;
1263 m_lastNode = nullptr;
1264 }
1265
1266 m_endItem = aEndItem;
1267
1268 bool reachesEnd = route( p );
1269
1270 current = Trace();
1271
1272 if( !current.PointCount() )
1274 else
1275 m_currentEnd = current.CLine().CPoint( -1 );
1276
1277 NODE* latestNode = m_currentNode;
1278 m_lastNode = latestNode->Branch();
1279
1280 if( reachesEnd
1281 && eiDepth >= 0
1282 && aEndItem && latestNode->Depth() >= eiDepth
1283 && current.SegmentCount() )
1284 {
1285 SplitAdjacentSegments( m_lastNode, aEndItem, current.CPoint( -1 ) );
1286
1287 if( Settings().RemoveLoops() )
1288 removeLoops( m_lastNode, current );
1289 }
1290
1293 return true;
1294}
bool route(const VECTOR2I &aP)
Re-route the current track to point aP.
void removeLoops(NODE *aNode, LINE &aLatest)
Searches aNode for traces concurrent to aLatest and removes them.
void updateLeadingRatLine()
Draw the "leading" rats nest line, which connects the end of currently routed track and the nearest y...

References PNS::MOUSE_TRAIL_TRACER::AddTrailPoint(), PNS::NODE::Branch(), PNS::LINE::CLine(), PNS::LINE::CPoint(), SHAPE_LINE_CHAIN::CPoint(), PNS::NODE::Depth(), m_currentEnd, m_currentNode, m_endItem, m_lastNode, m_mouseTrailTracer, m_p_start, PNS::ITEM::Owner(), PNS::LINE::PointCount(), removeLoops(), route(), PNS::LINE::SegmentCount(), PNS::ALGO_BASE::Settings(), SplitAdjacentSegments(), Trace(), and updateLeadingRatLine().

Referenced by SetLayer().

◆ optimizeTailHeadTransition()

bool PNS::LINE_PLACER::optimizeTailHeadTransition ( )
private

Try to reduce the corner count of the most recent part of tail/head by merging obtuse/collinear segments.

Returns
true if the line has been changed.

Definition at line 870 of file pns_line_placer.cpp.

871{
872 LINE linetmp = Trace();
873
874 PNS_DBG( Dbg(), Message, "optimize HT" );
875
876 // NOTE: FANOUT_CLEANUP can override posture setting at the moment
879 {
880 if( linetmp.SegmentCount() < 1 )
881 return false;
882
883 m_head = linetmp;
884 m_p_start = linetmp.CLine().CPoint( 0 );
885
886 PNS_DBG( Dbg(), AddPoint, m_p_start, WHITE, 10000, wxT( "new-pstart [optFanoutCleanup]" ) );
887
888 m_direction = DIRECTION_45( linetmp.CSegment( 0 ) );
889 m_tail.Line().Clear();
890
891 return true;
892 }
893
894 SHAPE_LINE_CHAIN& head = m_head.Line();
895 SHAPE_LINE_CHAIN& tail = m_tail.Line();
896
897 int tailLookbackSegments = 3;
898
899 //if(m_currentMode() == RM_Walkaround)
900 // tailLookbackSegments = 10000;
901
902 int threshold = std::min( tail.PointCount(), tailLookbackSegments + 1 );
903
904 if( tail.ShapeCount() < 3 )
905 return false;
906
907 // assemble TailLookbackSegments tail segments with the current head
908 SHAPE_LINE_CHAIN opt_line = tail.Slice( -threshold, -1 );
909
910 int end = std::min(2, head.PointCount() - 1 );
911
912 opt_line.Append( head.Slice( 0, end ) );
913
914 LINE new_head( m_tail, opt_line );
915
916 // and see if it could be made simpler by merging obtuse/collnear segments.
917 // If so, replace the (threshold) last tail points and the head with
918 // the optimized line
919
920
921 PNS_DBG( Dbg(), AddItem, &new_head, LIGHTCYAN, 10000, wxT( "ht-newline" ) );
922
924 {
925 LINE tmp( m_tail, opt_line );
926
927 head.Clear();
928 tail.Replace( -threshold, -1, new_head.CLine() );
929 tail.Simplify();
930
931 m_p_start = new_head.CLine().CPoint( -1 );
932
933 PNS_DBG( Dbg(), AddPoint, m_p_start, WHITE, 10000, wxT( "new-pstart [opt-tail-head]" ) );
934
935 m_direction = DIRECTION_45( new_head.CSegment( -1 ) );
936
937 return true;
938 }
939
940 return false;
941}
static bool Optimize(LINE *aLine, int aEffortLevel, NODE *aWorld, const VECTOR2I &aV=VECTOR2I(0, 0))
@ FANOUT_CLEANUP
Simplify pad-pad and pad-via connections if possible.
@ MERGE_SEGMENTS
Reduce corner cost iteratively.
Definition: pns_optimizer.h:99
void Replace(int aStartIndex, int aEndIndex, const VECTOR2I &aP)
Replace points with indices in range [start_index, end_index] with a single point aP.
const SHAPE_LINE_CHAIN Slice(int aStartIndex, int aEndIndex=-1) const
Return a subset of this line chain containing the [start_index, end_index] range of points.
@ LIGHTCYAN
Definition: color4d.h:64

References SHAPE_LINE_CHAIN::Append(), SHAPE_LINE_CHAIN::Clear(), PNS::LINE::CLine(), SHAPE_LINE_CHAIN::CPoint(), PNS::LINE::CSegment(), PNS::ALGO_BASE::Dbg(), PNS::OPTIMIZER::FANOUT_CLEANUP, PNS::MOUSE_TRAIL_TRACER::IsManuallyForced(), LIGHTCYAN, PNS::LINE::Line(), m_currentNode, m_direction, m_head, m_mouseTrailTracer, m_p_start, m_tail, PNS::OPTIMIZER::MERGE_SEGMENTS, PNS::OPTIMIZER::Optimize(), PNS_DBG, SHAPE_LINE_CHAIN::PointCount(), SHAPE_LINE_CHAIN::Replace(), PNS::LINE::SegmentCount(), SHAPE_LINE_CHAIN::ShapeCount(), SHAPE_LINE_CHAIN::Simplify(), SHAPE_LINE_CHAIN::Slice(), Trace(), and WHITE.

Referenced by routeStep().

◆ reduceTail()

bool PNS::LINE_PLACER::reduceTail ( const VECTOR2I aEnd)
private

Attempt to reduce the number of segments in the tail by trying to replace a certain number of latest tail segments with a direct trace leading to aEnd that does not collide with anything.

Parameters
aEndis the current routing destination point.
Returns
true if the line has been changed.

Definition at line 270 of file pns_line_placer.cpp.

271{
272 SHAPE_LINE_CHAIN& head = m_head.Line();
273 SHAPE_LINE_CHAIN& tail = m_tail.Line();
274
275 int n = tail.SegmentCount();
276
277 if( head.SegmentCount() < 1 )
278 return false;
279
280 // Don't attempt this for too short tails
281 if( n < 2 )
282 return false;
283
284 // Start from the segment farthest from the end of the tail
285 // int start_index = std::max(n - 1 - ReductionDepth, 0);
286
287 DIRECTION_45 new_direction;
288 VECTOR2I new_start;
289 int reduce_index = -1;
290
291 for( int i = tail.SegmentCount() - 1; i >= 0; i-- )
292 {
293 const SEG s = tail.CSegment( i );
294 DIRECTION_45 dir( s );
295
296 // calculate a replacement route and check if it matches
297 // the direction of the segment to be replaced
298 SHAPE_LINE_CHAIN replacement = dir.BuildInitialTrace( s.A, aEnd );
299
300 if( replacement.SegmentCount() < 1 )
301 continue;
302
303 LINE tmp( m_tail, replacement );
304
306 break;
307
308 if( DIRECTION_45( replacement.CSegment( 0 ) ) == dir )
309 {
310 new_start = s.A;
311 new_direction = dir;
312 reduce_index = i;
313 }
314 }
315
316 if( reduce_index >= 0 )
317 {
318 wxLogTrace( wxT( "PNS" ), wxT( "Placer: reducing tail: %d" ), reduce_index );
319 SHAPE_LINE_CHAIN reducedLine = new_direction.BuildInitialTrace( new_start, aEnd );
320
321 m_p_start = new_start;
322 PNS_DBG( Dbg(), AddPoint, m_p_start, WHITE, 10000, wxT( "new-pstart [reduceTail]" ) );
323
324 m_direction = new_direction;
325 tail.Remove( reduce_index + 1, -1 );
326 head.Clear();
327 return true;
328 }
329
330 if( !tail.SegmentCount() )
332
333 return false;
334}

References SEG::A, PNS::ITEM::ANY_T, DIRECTION_45::BuildInitialTrace(), PNS::NODE::CheckColliding(), SHAPE_LINE_CHAIN::Clear(), SHAPE_LINE_CHAIN::CSegment(), PNS::ALGO_BASE::Dbg(), PNS::LINE::Line(), m_currentNode, m_direction, m_head, m_initial_direction, m_p_start, m_tail, PNS_DBG, SHAPE_LINE_CHAIN::Remove(), SHAPE_LINE_CHAIN::SegmentCount(), and WHITE.

Referenced by routeStep().

◆ removeLoops()

void PNS::LINE_PLACER::removeLoops ( NODE aNode,
LINE aLatest 
)
private

Searches aNode for traces concurrent to aLatest and removes them.

Updated topology is stored in aNode.

Definition at line 1548 of file pns_line_placer.cpp.

1549{
1550 if( !aLatest.SegmentCount() )
1551 return;
1552
1553 if( aLatest.CLine().CPoint( 0 ) == aLatest.CLine().CPoint( -1 ) )
1554 return;
1555
1556 std::set<LINKED_ITEM *> toErase;
1557 aNode->Add( aLatest, true );
1558
1559 for( int s = 0; s < aLatest.LinkCount(); s++ )
1560 {
1561 LINKED_ITEM* seg = aLatest.GetLink(s);
1562 LINE ourLine = aNode->AssembleLine( seg );
1563 JOINT a, b;
1564 std::vector<LINE> lines;
1565
1566 aNode->FindLineEnds( ourLine, a, b );
1567
1568 if( a == b )
1569 aNode->FindLineEnds( aLatest, a, b );
1570
1571 aNode->FindLinesBetweenJoints( a, b, lines );
1572
1573 int removedCount = 0;
1574 int total = 0;
1575
1576 for( LINE& line : lines )
1577 {
1578 total++;
1579
1580 if( !( line.ContainsLink( seg ) ) && line.SegmentCount() )
1581 {
1582 for( LINKED_ITEM* ss : line.Links() )
1583 toErase.insert( ss );
1584
1585 removedCount++;
1586 }
1587 }
1588
1589 wxLogTrace( wxT( "PNS" ), wxT( "total segs removed: %d/%d" ), removedCount, total );
1590 }
1591
1592 for( LINKED_ITEM* s : toErase )
1593 aNode->Remove( s );
1594
1595 aNode->Remove( aLatest );
1596}

References PNS::NODE::Add(), PNS::NODE::AssembleLine(), PNS::LINE::CLine(), SHAPE_LINE_CHAIN::CPoint(), PNS::NODE::FindLineEnds(), PNS::NODE::FindLinesBetweenJoints(), PNS::LINK_HOLDER::GetLink(), PNS::LINK_HOLDER::LinkCount(), PNS::NODE::Remove(), and PNS::LINE::SegmentCount().

Referenced by Move().

◆ rhMarkObstacles()

bool PNS::LINE_PLACER::rhMarkObstacles ( const VECTOR2I aP,
LINE aNewHead 
)
private

Definition at line 700 of file pns_line_placer.cpp.

701{
703 m_head.SetBlockingObstacle( nullptr );
704
705 auto obs = m_currentNode->NearestObstacle( &m_head );
706
707 // If the head is in colliding state, snap to the hull of the first obstacle.
708 // This way, one can route tracks as tightly as possible without enabling
709 // the shove/walk mode that certain users find too intrusive.
710 if( obs )
711 {
712 int cl = m_currentNode->GetClearance( obs->m_item, &m_head, false );
713 auto hull = obs->m_item->Hull( cl, m_head.Width() );
714
715 auto nearest = hull.NearestPoint( aP );
716
717 if( ( nearest - aP ).EuclideanNorm() < m_head.Width() / 2 )
718 {
719 buildInitialLine( nearest, m_head );
720 }
721 }
722
723 // Note: Something like the below could be used to implement a "stop at first obstacle" mode,
724 // but we don't have one right now and there isn't a lot of demand for one. If we do end up
725 // doing that, put it in a new routing mode as "highlight collisions" mode should not have
726 // collision handling other than highlighting.
727#if 0
728 if( !Settings().AllowDRCViolations() )
729 {
731
732 if( obs && obs->m_distFirst != INT_MAX )
733 {
734 buildInitialLine( obs->m_ipFirst, m_head );
735 m_head.SetBlockingObstacle( obs->m_item );
736 }
737 }
738#endif
739
740 aNewHead = m_head;
741
742 return true;
743}
bool buildInitialLine(const VECTOR2I &aP, LINE &aHead, bool aForceNoVia=false)
void SetBlockingObstacle(ITEM *aObstacle)
Definition: pns_line.h:203
int GetClearance(const ITEM *aA, const ITEM *aB, bool aUseClearanceEpsilon=true) const
Definition: pns_node.cpp:103
OPT< OBSTACLE > OPT_OBSTACLE
Definition: pns_node.h:160
OPT_OBSTACLE NearestObstacle(const LINE *aLine, int aKindMask=ITEM::ANY_T, const std::set< ITEM * > *aRestrictedSet=nullptr, bool aUseClearanceEpsilon=true)
Follow the line in search of an obstacle that is nearest to the starting to the line's starting point...
Definition: pns_node.cpp:301
double EuclideanNorm(const VECTOR2I &vector)
Definition: trigo.h:129

References buildInitialLine(), EuclideanNorm(), PNS::NODE::GetClearance(), m_currentNode, m_head, PNS::NODE::NearestObstacle(), PNS::LINE::SetBlockingObstacle(), PNS::ALGO_BASE::Settings(), and PNS::LINE::Width().

Referenced by routeHead().

◆ rhShoveOnly()

bool PNS::LINE_PLACER::rhShoveOnly ( const VECTOR2I aP,
LINE aNewHead 
)
private

Route step mark obstacles mode.

Definition at line 746 of file pns_line_placer.cpp.

747{
748 LINE initTrack( m_head );
749 LINE walkSolids, l2;
750
751 bool viaOk = buildInitialLine( aP, initTrack );
752
753 m_currentNode = m_shove->CurrentNode();
754
755 m_shove->SetLogger( Logger() );
756 m_shove->SetDebugDecorator( Dbg() );
757
758 OPTIMIZER optimizer( m_currentNode );
759
760 WALKAROUND walkaround( m_currentNode, Router() );
761
762 walkaround.SetSolidsOnly( true );
763 walkaround.SetIterationLimit( 10 );
764 walkaround.SetDebugDecorator( Dbg() );
765 walkaround.SetLogger( Logger() );
766 WALKAROUND::WALKAROUND_STATUS stat_solids = walkaround.Route( initTrack, walkSolids );
767
768 optimizer.SetEffortLevel( OPTIMIZER::MERGE_SEGMENTS );
769 optimizer.SetCollisionMask( ITEM::SOLID_T );
770 optimizer.Optimize( &walkSolids );
771
772 if( stat_solids == WALKAROUND::DONE )
773 l2 = walkSolids;
774 else
775 l2 = initTrack.ClipToNearestObstacle( m_shove->CurrentNode() );
776
777 LINE l( m_tail );
778 l.Line().Append( l2.CLine() );
779 l.Line().Simplify();
780
781 if( l.PointCount() == 0 || l2.PointCount() == 0 )
782 {
783 aNewHead = m_head;
784 return false;
785 }
786
787 if( m_placingVia && viaOk )
788 {
789 VIA v1( makeVia( l.CPoint( -1 ) ) );
790 VIA v2( makeVia( l2.CPoint( -1 ) ) );
791
792 l.AppendVia( v1 );
793 l2.AppendVia( v2 );
794 }
795
796 l.Line().Simplify();
797
798 // in certain, uncommon cases there may be loops in the head+tail, In such case, we don't
799 // shove to avoid screwing up the database.
800 if( l.HasLoops() )
801 {
802 aNewHead = m_head;
803 return false;
804 }
805
806 if( m_endItem )
807 {
808 // Make sure the springback algorithm won't erase the NODE that owns m_endItem.
809 m_shove->SetSpringbackDoNotTouchNode( m_endItem->Owner() );
810 }
811
812 SHOVE::SHOVE_STATUS status = m_shove->ShoveLines( l );
813
814 m_currentNode = m_shove->CurrentNode();
815
816 if( status == SHOVE::SH_OK || status == SHOVE::SH_HEAD_MODIFIED )
817 {
818 if( status == SHOVE::SH_HEAD_MODIFIED )
819 l2 = m_shove->NewHead();
820
821 optimizer.SetWorld( m_currentNode );
822
823 int effortLevel = OPTIMIZER::MERGE_OBTUSE;
824
825 if( Settings().SmartPads() && !m_mouseTrailTracer.IsManuallyForced() )
826 effortLevel = OPTIMIZER::SMART_PADS;
827
828 optimizer.SetEffortLevel( effortLevel );
829
830 optimizer.SetCollisionMask( ITEM::ANY_T );
831 optimizer.Optimize( &l2 );
832
833 aNewHead = l2;
834
835 return true;
836 }
837 else
838 {
839 walkaround.SetWorld( m_currentNode );
840 walkaround.SetSolidsOnly( false );
841 walkaround.SetIterationLimit( 10 );
842 walkaround.Route( initTrack, l2 );
843 aNewHead = l2.ClipToNearestObstacle( m_shove->CurrentNode() );
844
845 return false;
846 }
847
848 return false;
849}
virtual LOGGER * Logger()
NODE * Owner() const
Return the owner of this item, or NULL if there's none.
Definition: pns_item.h:171
@ SOLID_T
Definition: pns_item.h:63
@ SMART_PADS
Reroute pad exits.
@ MERGE_OBTUSE
Reduce corner cost by merging obtuse segments.
@ SH_HEAD_MODIFIED
Definition: pns_shove.h:54
VECTOR2I v2(1, 0)
Test suite for KiCad math code.

References PNS::ITEM::ANY_T, SHAPE_LINE_CHAIN::Append(), PNS::LINE::AppendVia(), buildInitialLine(), PNS::LINE::CLine(), PNS::LINE::ClipToNearestObstacle(), PNS::LINE::CPoint(), PNS::ALGO_BASE::Dbg(), PNS::WALKAROUND::DONE, PNS::LINE::HasLoops(), PNS::MOUSE_TRAIL_TRACER::IsManuallyForced(), PNS::LINE::Line(), PNS::ALGO_BASE::Logger(), m_currentNode, m_endItem, m_head, m_mouseTrailTracer, m_placingVia, m_shove, m_tail, makeVia(), PNS::OPTIMIZER::MERGE_OBTUSE, PNS::OPTIMIZER::MERGE_SEGMENTS, PNS::OPTIMIZER::Optimize(), PNS::ITEM::Owner(), PNS::LINE::PointCount(), PNS::WALKAROUND::Route(), PNS::ALGO_BASE::Router(), PNS::OPTIMIZER::SetCollisionMask(), PNS::ALGO_BASE::SetDebugDecorator(), PNS::OPTIMIZER::SetEffortLevel(), PNS::WALKAROUND::SetIterationLimit(), PNS::ALGO_BASE::SetLogger(), PNS::WALKAROUND::SetSolidsOnly(), PNS::ALGO_BASE::Settings(), PNS::OPTIMIZER::SetWorld(), PNS::WALKAROUND::SetWorld(), PNS::SHOVE::SH_HEAD_MODIFIED, PNS::SHOVE::SH_OK, SHAPE_LINE_CHAIN::Simplify(), PNS::OPTIMIZER::SMART_PADS, PNS::ITEM::SOLID_T, and v2.

Referenced by routeHead().

◆ rhWalkOnly()

bool PNS::LINE_PLACER::rhWalkOnly ( const VECTOR2I aP,
LINE aNewHead 
)
private

Route step shove mode.

Definition at line 542 of file pns_line_placer.cpp.

543{
544 LINE initTrack( m_head );
545 LINE walkFull( m_head );
546
547 initTrack.RemoveVia();
548 walkFull.RemoveVia();
549
550 int effort = 0;
551 bool viaOk = false;
552
553 VECTOR2I walkP = aP;
554
555 WALKAROUND walkaround( m_currentNode, Router() );
556
557 walkaround.SetSolidsOnly( false );
558 walkaround.SetDebugDecorator( Dbg() );
559 walkaround.SetLogger( Logger() );
560 walkaround.SetIterationLimit( Settings().WalkaroundIterationLimit() );
561
562 char name[50];
563 int round = 0;
564
565 do {
566 snprintf( name, sizeof( name ), "walk-round-%d", round );
567 PNS_DBG( Dbg(), BeginGroup, name, 0 );
568
569 viaOk = buildInitialLine( walkP, initTrack, round == 0 );
570
571 double initialLength = initTrack.CLine().Length();
572 double hugThresholdLength = initialLength * Settings().WalkaroundHugLengthThreshold();
573
574 WALKAROUND::RESULT wr = walkaround.Route( initTrack );
575
576 SHAPE_LINE_CHAIN l_cw = wr.lineCw.CLine();
577 SHAPE_LINE_CHAIN l_ccw = wr.lineCcw.CLine();
578
579 if( wr.statusCcw == WALKAROUND::DONE || wr.statusCw == WALKAROUND::DONE )
580 {
581 int len_cw = wr.statusCw == WALKAROUND::DONE ? l_cw.Length() : INT_MAX;
582 int len_ccw = wr.statusCcw == WALKAROUND::DONE ? l_ccw.Length() : INT_MAX;
583
584 PNS_DBG( Dbg(), AddItem, &wr.lineCw, CYAN, 10000, wxT( "wf-result-cw" ) );
585 PNS_DBG( Dbg(), AddItem, &wr.lineCcw, BLUE, 20000, wxT( "wf-result-ccw" ) );
586
587 int bestLength = len_cw < len_ccw ? len_cw : len_ccw;
588
589 if( bestLength > hugThresholdLength )
590 {
591 wr.statusCw = WALKAROUND::ALMOST_DONE;
592 wr.statusCcw = WALKAROUND::ALMOST_DONE;
593 }
594
595 SHAPE_LINE_CHAIN& bestLine = len_cw < len_ccw ? l_cw : l_ccw;
596 walkFull.SetShape( bestLine );
597 }
598
599 if( wr.statusCcw == WALKAROUND::ALMOST_DONE || wr.statusCw == WALKAROUND::ALMOST_DONE )
600 {
601 bool valid_cw = false, valid_ccw = false;
602 VECTOR2I p_cw, p_ccw;
603 int dist_ccw = 0, dist_cw = 0;
604
605 if( wr.statusCcw == WALKAROUND::ALMOST_DONE )
606 {
607 valid_ccw = cursorDistMinimum( l_ccw, aP, hugThresholdLength, dist_ccw, p_ccw );
608
609 if( valid_ccw )
610 {
611 int idx_ccw = l_ccw.Split( p_ccw );
612 l_ccw = l_ccw.Slice( 0, idx_ccw );
613 PNS_DBG( Dbg(), AddPoint, p_ccw, BLUE, 500000, wxT( "hug-target-ccw" ) );
614 PNS_DBG( Dbg(), AddShape, &l_ccw, MAGENTA, 200000, wxT( "wh-result-ccw" ) );
615 }
616 }
617
618 if( wr.statusCw == WALKAROUND::ALMOST_DONE )
619 {
620 valid_cw = cursorDistMinimum( l_cw, aP, hugThresholdLength, dist_cw, p_cw );
621
622 if( valid_cw )
623 {
624 int idx_cw = l_cw.Split( p_cw );
625 l_cw = l_cw.Slice( 0, idx_cw );
626 PNS_DBG( Dbg(), AddPoint, p_cw, YELLOW, 500000, wxT( "hug-target-cw" ) );
627 PNS_DBG( Dbg(), AddShape, &l_cw, BLUE, 200000, wxT( "wh-result-cw" ) );
628 }
629 }
630
631 if( dist_cw < dist_ccw && valid_cw )
632 {
633 walkFull.SetShape( l_cw );
634 walkP = p_cw;
635 }
636 else if ( valid_ccw )
637 {
638 walkFull.SetShape( l_ccw );
639 walkP = p_ccw;
640 }
641 else
642 {
643 PNS_DBGN( Dbg(), EndGroup );
644 return false;
645 }
646 }
647 else if ( wr.statusCcw == WALKAROUND::STUCK || wr.statusCw == WALKAROUND::STUCK )
648 {
649 PNS_DBGN( Dbg(), EndGroup );
650 return false;
651 }
652
653 PNS_DBGN( Dbg(), EndGroup );
654
655 round++;
656 } while( round < 2 && m_placingVia );
657
658 PNS_DBG( Dbg(), AddItem, &walkFull, GREEN, 200000, wxT( "walk-full" ) );
659
660 switch( Settings().OptimizerEffort() )
661 {
662 case OE_LOW:
663 effort = 0;
664 break;
665
666 case OE_MEDIUM:
667 case OE_FULL:
669 break;
670 }
671
673
674 // Smart Pads is incompatible with 90-degree mode for now
675 if( Settings().SmartPads()
676 && ( cornerMode == DIRECTION_45::MITERED_45 || cornerMode == DIRECTION_45::ROUNDED_45 )
678 {
679 effort |= OPTIMIZER::SMART_PADS;
680 }
681
682 if( m_placingVia && viaOk )
683 {
684 walkFull.AppendVia( makeVia( walkFull.CPoint( -1 ) ) );
685 }
686
687 OPTIMIZER::Optimize( &walkFull, effort, m_currentNode );
688
689 if( m_currentNode->CheckColliding( &walkFull ) )
690 {
691 return false;
692 }
693
694 aNewHead = walkFull;
695
696 return true;
697}
const char * name
Definition: DXF_plotter.cpp:56
@ ROUNDED_45
H/V/45 with filleted corners.
Definition: direction45.h:69
@ MITERED_45
H/V/45 with mitered corners (default)
Definition: direction45.h:68
double WalkaroundHugLengthThreshold() const
int Split(const VECTOR2I &aP)
Insert the point aP belonging to one of the our segments, splitting the adjacent segment in two.
long long int Length() const
Return length of the line chain in Euclidean metric.
@ BLUE
Definition: color4d.h:56
@ MAGENTA
Definition: color4d.h:60
@ GREEN
Definition: color4d.h:57
@ YELLOW
Definition: color4d.h:67
static bool cursorDistMinimum(const SHAPE_LINE_CHAIN &aL, const VECTOR2I &aCursor, double lengthThreshold, int &theDist, VECTOR2I &aNearest)
#define PNS_DBGN(dbg, method)

References PNS::WALKAROUND::ALMOST_DONE, PNS::LINE::AppendVia(), BLUE, buildInitialLine(), PNS::NODE::CheckColliding(), PNS::LINE::CLine(), PNS::LINE::CPoint(), PNS::cursorDistMinimum(), CYAN, PNS::ALGO_BASE::Dbg(), PNS::WALKAROUND::DONE, PNS::ROUTING_SETTINGS::GetCornerMode(), GREEN, PNS::MOUSE_TRAIL_TRACER::IsManuallyForced(), SHAPE_LINE_CHAIN::Length(), PNS::WALKAROUND::RESULT::lineCcw, PNS::WALKAROUND::RESULT::lineCw, PNS::ALGO_BASE::Logger(), m_currentNode, m_head, m_mouseTrailTracer, m_placingVia, MAGENTA, makeVia(), PNS::OPTIMIZER::MERGE_SEGMENTS, DIRECTION_45::MITERED_45, name, PNS::OE_FULL, PNS::OE_LOW, PNS::OE_MEDIUM, PNS::OPTIMIZER::Optimize(), PNS_DBG, PNS_DBGN, PNS::LINE::RemoveVia(), DIRECTION_45::ROUNDED_45, PNS::WALKAROUND::Route(), PNS::ALGO_BASE::Router(), PNS::ALGO_BASE::SetDebugDecorator(), PNS::WALKAROUND::SetIterationLimit(), PNS::ALGO_BASE::SetLogger(), PNS::LINE::SetShape(), PNS::WALKAROUND::SetSolidsOnly(), PNS::ALGO_BASE::Settings(), SHAPE_LINE_CHAIN::Slice(), PNS::OPTIMIZER::SMART_PADS, SHAPE_LINE_CHAIN::Split(), PNS::WALKAROUND::RESULT::statusCcw, PNS::WALKAROUND::RESULT::statusCw, PNS::WALKAROUND::STUCK, PNS::ROUTING_SETTINGS::WalkaroundHugLengthThreshold(), and YELLOW.

Referenced by routeHead().

◆ route()

bool PNS::LINE_PLACER::route ( const VECTOR2I aP)
private

Re-route the current track to point aP.

Returns true, when routing has completed successfully (i.e. the trace end has reached point aP), and false if the trace was stuck somewhere on the way. May call routeStep() repetitively due to mouse smoothing.

Parameters
aPending point of current route.
Returns
true, if the routing is complete.

Definition at line 1040 of file pns_line_placer.cpp.

1041{
1042 routeStep( aP );
1043
1044 if (!m_head.PointCount() )
1045 return false;
1046
1047 return m_head.CPoint(-1) == aP;
1048}
void routeStep(const VECTOR2I &aP)
Perform a single routing algorithm step, for the end point aP.

References PNS::LINE::CPoint(), m_head, PNS::LINE::PointCount(), and routeStep().

Referenced by Move().

◆ routeHead()

bool PNS::LINE_PLACER::routeHead ( const VECTOR2I aP,
LINE aNewHead 
)
private

Compute the head trace between the current start point (m_p_start) and point aP, starting with direction defined in m_direction.

The trace walks around all colliding solid or non-movable items. Movable segments are ignored, as they'll be handled later by the shove algorithm.

Definition at line 852 of file pns_line_placer.cpp.

853{
854 switch( Settings().Mode() )
855 {
856 case RM_MarkObstacles:
857 return rhMarkObstacles( aP, aNewHead );
858 case RM_Walkaround:
859 return rhWalkOnly( aP, aNewHead );
860 case RM_Shove:
861 return rhShoveOnly( aP, aNewHead );
862 default:
863 break;
864 }
865
866 return false;
867}
bool rhMarkObstacles(const VECTOR2I &aP, LINE &aNewHead)
bool rhWalkOnly(const VECTOR2I &aP, LINE &aNewHead)
Route step shove mode.
bool rhShoveOnly(const VECTOR2I &aP, LINE &aNewHead)
Route step mark obstacles mode.

References rhMarkObstacles(), rhShoveOnly(), rhWalkOnly(), PNS::RM_MarkObstacles, PNS::RM_Shove, PNS::RM_Walkaround, and PNS::ALGO_BASE::Settings().

Referenced by routeStep().

◆ Router()

◆ routeStep()

void PNS::LINE_PLACER::routeStep ( const VECTOR2I aP)
private

Perform a single routing algorithm step, for the end point aP.

Parameters
aPis the ending point of current route.
Returns
true if the line has been changed. Route step walk around mode.

Definition at line 944 of file pns_line_placer.cpp.

945{
946 bool fail = false;
947 bool go_back = false;
948
949 int i, n_iter = 1;
950
951 LINE new_head;
952
953 wxLogTrace( wxT( "PNS" ), wxT( "routeStep: direction: %s head: %d, tail: %d shapes" ),
954 m_direction.Format().c_str(),
956 m_tail.ShapeCount() );
957
958 PNS_DBG( Dbg(), BeginGroup, wxT( "route-step" ), 0 );
959
960 PNS_DBG( Dbg(), AddItem, &m_tail, WHITE, 10000, wxT( "tail-init" ) );
961 PNS_DBG( Dbg(), AddItem, &m_head, GREEN, 10000, wxT( "head-init" ) );
962
963 for( i = 0; i < n_iter; i++ )
964 {
965 if( !go_back && Settings().FollowMouse() )
966 reduceTail( aP );
967
968 PNS_DBG( Dbg(), AddItem, &m_tail, WHITE, 10000, wxT( "tail-after-reduce" ) );
969 PNS_DBG( Dbg(), AddItem, &m_head, GREEN, 10000, wxT( "head-after-reduce" ) );
970
971 go_back = false;
972
973 if( !routeHead( aP, new_head ) )
974 {
975 fail = true;
976 }
977
978 PNS_DBG( Dbg(), AddItem, &new_head, LIGHTGREEN, 100000, wxString::Format( "new_head [fail: %d]", fail?1:0 ) );
979
980 if( fail )
981 break;
982
983 m_head = new_head;
984
986 {
987 n_iter++;
988 go_back = true;
989 }
990
991 PNS_DBG( Dbg(), AddItem, &m_tail, WHITE, 10000, wxT( "tail-after-si" ) );
992 PNS_DBG( Dbg(), AddItem, &m_head, GREEN, 10000, wxT( "head-after-si" ) );
993
994 if( !go_back && handlePullback() )
995 {
996 n_iter++;
997 go_back = true;
998 }
999
1000 PNS_DBG( Dbg(), AddItem, &m_tail, WHITE, 100000, wxT( "tail-after-pb" ) );
1001 PNS_DBG( Dbg(), AddItem, &m_head, GREEN, 100000, wxT( "head-after-pb" ) );
1002 }
1003
1004 if( fail )
1005 {
1006 if( m_last_head.PointCount() > 0 )
1007 {
1009 PNS_DBG( Dbg(), AddItem, &m_last_head, CYAN, 10000, wxT( "apply-last-head" ) );
1010 }
1011 else
1012 {
1013 m_head.RemoveVia();
1014 m_head.Clear();
1015 }
1016 }
1017 else
1018 {
1020 }
1021
1022 if( !fail && Settings().FollowMouse() )
1023 {
1024 PNS_DBG( Dbg(), AddItem, &m_tail, WHITE, 10000, wxT( "tail-pre-merge" ) );
1025 PNS_DBG( Dbg(), AddItem, &m_head, GREEN, 10000, wxT( "head-pre-merge" ) );
1026
1028 {
1029 mergeHead();
1030 }
1031
1032 PNS_DBG( Dbg(), AddItem, &m_tail, WHITE, 100000, wxT( "tail-post-merge" ) );
1033 PNS_DBG( Dbg(), AddItem, &m_head, GREEN, 100000, wxT( "head-post-merge" ) );
1034 }
1035
1036 PNS_DBGN( Dbg(), EndGroup );
1037}
bool mergeHead()
Moves "established" segments from the head to the tail if certain conditions are met.
bool handleSelfIntersections()
Check if the head of the track intersects its tail.
bool handlePullback()
Deal with pull-back: reduces the tail if head trace is moved backwards wrs to the current tail direct...
bool reduceTail(const VECTOR2I &aEnd)
Attempt to reduce the number of segments in the tail by trying to replace a certain number of latest ...
LINE m_last_head
Most recent successful (non-colliding) head.
bool optimizeTailHeadTransition()
Try to reduce the corner count of the most recent part of tail/head by merging obtuse/collinear segme...
bool routeHead(const VECTOR2I &aP, LINE &aNewHead)
Compute the head trace between the current start point (m_p_start) and point aP, starting with direct...
void Clear()
Definition: pns_line.cpp:1227
int ShapeCount() const
Return the aIdx-th point of the line.
Definition: pns_line.h:142
@ LIGHTGREEN
Definition: color4d.h:63
void Format(OUTPUTFORMATTER *out, int aNestLevel, int aCtl, const CPTREE &aTree)
Output a PTREE into s-expression format via an OUTPUTFORMATTER derivative.
Definition: ptree.cpp:200

References PNS::LINE::Clear(), CYAN, PNS::ALGO_BASE::Dbg(), DIRECTION_45::Format(), Format(), GREEN, handlePullback(), handleSelfIntersections(), LIGHTGREEN, m_direction, m_head, m_last_head, m_tail, mergeHead(), optimizeTailHeadTransition(), PNS_DBG, PNS_DBGN, PNS::LINE::PointCount(), reduceTail(), PNS::LINE::RemoveVia(), routeHead(), PNS::ALGO_BASE::Settings(), PNS::LINE::ShapeCount(), and WHITE.

Referenced by route().

◆ SetDebugDecorator()

void PNS::ALGO_BASE::SetDebugDecorator ( DEBUG_DECORATOR aDecorator)
inlineinherited

Assign a debug decorator allowing this algo to draw extra graphics for visual debugging.

Definition at line 73 of file pns_algo_base.h.

74 {
75 m_debugDecorator = aDecorator;
76 }

References PNS::ALGO_BASE::m_debugDecorator.

Referenced by PNS::SHOVE::onCollidingSolid(), rhShoveOnly(), rhWalkOnly(), PNS::SHOVE::SHOVE(), and PNS::DRAGGER::tryWalkaround().

◆ setInitialDirection()

void PNS::LINE_PLACER::setInitialDirection ( const DIRECTION_45 aDirection)
private

Set preferred direction of the very first track segment to be laid.

Used by posture switching mechanism.

Definition at line 94 of file pns_line_placer.cpp.

95{
96 m_initial_direction = aDirection;
97
98 if( m_tail.SegmentCount() == 0 )
99 m_direction = aDirection;
100}

References m_direction, m_initial_direction, m_tail, and PNS::LINE::SegmentCount().

Referenced by FixRoute(), and Start().

◆ SetLayer()

bool PNS::LINE_PLACER::SetLayer ( int  aLayer)
overridevirtual

Set the current routing layer.

Reimplemented from PNS::PLACEMENT_ALGO.

Definition at line 1116 of file pns_line_placer.cpp.

1117{
1118 if( m_idle )
1119 {
1120 m_currentLayer = aLayer;
1121 return true;
1122 }
1123 else if( m_chainedPlacement )
1124 {
1125 return false;
1126 }
1127 else if( !m_startItem
1128 || ( m_startItem->OfKind( ITEM::VIA_T ) && m_startItem->Layers().Overlaps( aLayer ) )
1129 || ( m_startItem->OfKind( ITEM::SOLID_T ) && m_startItem->Layers().Overlaps( aLayer ) ) )
1130 {
1131 m_currentLayer = aLayer;
1135 m_head.Line().Clear();
1136 m_tail.Line().Clear();
1138 m_head.RemoveVia();
1139 m_tail.RemoveVia();
1143 Move( m_currentEnd, nullptr );
1144 return true;
1145 }
1146
1147 return false;
1148}
bool Overlaps(const LAYER_RANGE &aOther) const
Definition: pns_layerset.h:67
const LAYER_RANGE & Layers() const
Definition: pns_item.h:154
bool OfKind(int aKindMask) const
Return true if the item's type matches the mask aKindMask.
Definition: pns_item.h:138
bool Move(const VECTOR2I &aP, ITEM *aEndItem) override
Move the end of the currently routed trace to the point aP, taking aEndItem as anchor (if not NULL).

References SHAPE_LINE_CHAIN::Clear(), PNS::MOUSE_TRAIL_TRACER::Clear(), PNS::ITEM::Layers(), PNS::LINE::Line(), m_chainedPlacement, m_currentEnd, m_currentLayer, m_currentStart, m_direction, m_head, m_idle, m_initial_direction, m_last_head, m_mouseTrailTracer, m_p_start, m_startItem, m_tail, Move(), PNS::ITEM::OfKind(), LAYER_RANGE::Overlaps(), PNS::LINE::RemoveVia(), PNS::ITEM::SetLayer(), PNS::ITEM::SOLID_T, and PNS::ITEM::VIA_T.

◆ SetLogger()

void PNS::ALGO_BASE::SetLogger ( LOGGER aLogger)
inlineinherited

Definition at line 65 of file pns_algo_base.h.

66 {
67 m_logger = aLogger;
68 }
LOGGER * m_logger
Definition: pns_algo_base.h:88

References PNS::ALGO_BASE::m_logger.

Referenced by rhShoveOnly(), rhWalkOnly(), and PNS::DRAGGER::tryWalkaround().

◆ SetOrthoMode()

void PNS::LINE_PLACER::SetOrthoMode ( bool  aOrthoMode)
overridevirtual

Function SetOrthoMode()

Forces the router to place a straight 90/45 degree trace (with the end as near to the cursor as possible) instead of a standard 135 degree two-segment bend.

Reimplemented from PNS::PLACEMENT_ALGO.

Definition at line 1723 of file pns_line_placer.cpp.

1724{
1725 m_orthoMode = aOrthoMode;
1726}

References m_orthoMode.

◆ Settings()

◆ setWorld()

void PNS::LINE_PLACER::setWorld ( NODE aWorld)
private

Set the board to route.

Definition at line 68 of file pns_line_placer.cpp.

69{
70 m_world = aWorld;
71}

References m_world.

Referenced by initPlacement().

◆ simplifyNewLine()

void PNS::LINE_PLACER::simplifyNewLine ( NODE aNode,
LINKED_ITEM aLatest 
)
private

Assemble a line starting from segment or arc aLatest, removes collinear segments and redundant vertices.

If a simplification has been found, replaces the old line with the simplified one in aNode.

Definition at line 1599 of file pns_line_placer.cpp.

1600{
1601 wxASSERT( aLatest->OfKind( ITEM::SEGMENT_T | ITEM::ARC_T ) );
1602
1603 // Before we assemble the final line and run the optimizer, do a separate pass to clean up
1604 // colinear segments that exist on non-line-corner joints, as these will prevent proper assembly
1605 // of the line and won't get cleaned up by the optimizer.
1606 NODE::ITEM_VECTOR removed, added;
1607 aNode->GetUpdatedItems( removed, added );
1608
1609 std::set<ITEM*> cleanup;
1610
1611 auto processJoint =
1612 [&]( JOINT* aJoint, ITEM* aItem )
1613 {
1614 if( !aJoint || aJoint->IsLineCorner() )
1615 return;
1616
1617 SEG refSeg = static_cast<SEGMENT*>( aItem )->Seg();
1618
1619 NODE::ITEM_VECTOR toRemove;
1620
1621 for( ITEM* neighbor : aJoint->Links() )
1622 {
1623 if( neighbor == aItem
1624 || !neighbor->OfKind( ITEM::SEGMENT_T | ITEM::ARC_T )
1625 || !neighbor->LayersOverlap( aItem ) )
1626 {
1627 continue;
1628 }
1629
1630 if( static_cast<SEGMENT*>( neighbor )->Width()
1631 != static_cast<SEGMENT*>( aItem )->Width() )
1632 {
1633 continue;
1634 }
1635
1636 const SEG& testSeg = static_cast<SEGMENT*>( neighbor )->Seg();
1637
1638 if( refSeg.Contains( testSeg ) )
1639 {
1640 JOINT* nA = aNode->FindJoint( neighbor->Anchor( 0 ), neighbor );
1641 JOINT* nB = aNode->FindJoint( neighbor->Anchor( 1 ), neighbor );
1642
1643 if( ( nA == aJoint && nB->LinkCount() == 1 ) ||
1644 ( nB == aJoint && nA->LinkCount() == 1 ) )
1645 {
1646 cleanup.insert( neighbor );
1647 }
1648 }
1649 }
1650 };
1651
1652 for( ITEM* item : added )
1653 {
1654 if( !item->OfKind( ITEM::SEGMENT_T ) || cleanup.count( item ) )
1655 continue;
1656
1657 JOINT* jA = aNode->FindJoint( item->Anchor( 0 ), item );
1658 JOINT* jB = aNode->FindJoint( item->Anchor( 1 ), item );
1659
1660 processJoint( jA, item );
1661 processJoint( jB, item );
1662 }
1663
1664 for( ITEM* seg : cleanup )
1665 aNode->Remove( seg );
1666
1667 // And now we can proceed with assembling the final line and optimizing it.
1668
1669 LINE l = aNode->AssembleLine( aLatest );
1670
1671 bool optimized = OPTIMIZER::Optimize( &l, OPTIMIZER::MERGE_COLINEAR, aNode );
1672
1673 SHAPE_LINE_CHAIN simplified( l.CLine() );
1674
1675 simplified.Simplify();
1676
1677 if( optimized || simplified.PointCount() != l.PointCount() )
1678 {
1679 aNode->Remove( l );
1680 l.SetShape( simplified );
1681 aNode->Add( l );
1682 }
1683}
@ MERGE_COLINEAR
Merge co-linear segments.
bool Contains(const SEG &aSeg) const
Definition: seg.h:332

References PNS::NODE::Add(), PNS::ITEM::ARC_T, PNS::NODE::AssembleLine(), PNS::LINE::CLine(), SEG::Contains(), PNS::NODE::FindJoint(), PNS::NODE::GetUpdatedItems(), PNS::JOINT::IsLineCorner(), PNS::JOINT::LinkCount(), PNS::JOINT::Links(), PNS::OPTIMIZER::MERGE_COLINEAR, PNS::ITEM::OfKind(), PNS::OPTIMIZER::Optimize(), SHAPE_LINE_CHAIN::PointCount(), PNS::LINE::PointCount(), PNS::NODE::Remove(), PNS::ITEM::SEGMENT_T, PNS::LINE::SetShape(), SHAPE_LINE_CHAIN::Simplify(), and PNS::SEGMENT::Width().

Referenced by FixRoute().

◆ SplitAdjacentSegments()

bool PNS::LINE_PLACER::SplitAdjacentSegments ( NODE aNode,
ITEM aSeg,
const VECTOR2I aP 
)

Check if point aP lies on segment aSeg.

If so, splits the segment in two, forming a joint at aP and stores updated topology in node aNode.

Definition at line 1088 of file pns_line_placer.cpp.

1089{
1090 if( !aSeg )
1091 return false;
1092
1093 if( !aSeg->OfKind( ITEM::SEGMENT_T ) )
1094 return false;
1095
1096 JOINT* jt = aNode->FindJoint( aP, aSeg );
1097
1098 if( jt && jt->LinkCount() >= 1 )
1099 return false;
1100
1101 SEGMENT* s_old = static_cast<SEGMENT*>( aSeg );
1102
1103 std::unique_ptr<SEGMENT> s_new[2] = { Clone( *s_old ), Clone( *s_old ) };
1104
1105 s_new[0]->SetEnds( s_old->Seg().A, aP );
1106 s_new[1]->SetEnds( aP, s_old->Seg().B );
1107
1108 aNode->Remove( s_old );
1109 aNode->Add( std::move( s_new[0] ), true );
1110 aNode->Add( std::move( s_new[1] ), true );
1111
1112 return true;
1113}

References SEG::A, PNS::NODE::Add(), SEG::B, PNS::Clone(), PNS::NODE::FindJoint(), PNS::JOINT::LinkCount(), PNS::ITEM::OfKind(), PNS::NODE::Remove(), PNS::SEGMENT::Seg(), and PNS::ITEM::SEGMENT_T.

Referenced by PNS::ROUTER::BreakSegment(), initPlacement(), and Move().

◆ Start()

bool PNS::LINE_PLACER::Start ( const VECTOR2I aP,
ITEM aStartItem 
)
overridevirtual

Start routing a single track at point aP, taking item aStartItem as anchor (unless NULL).

Implements PNS::PLACEMENT_ALGO.

Definition at line 1151 of file pns_line_placer.cpp.

1152{
1153 m_placementCorrect = false;
1154 m_currentStart = VECTOR2I( aP );
1155 m_currentEnd = VECTOR2I( aP );
1156 m_currentNet = std::max( 0, aStartItem ? aStartItem->Net() : 0 );
1157 m_startItem = aStartItem;
1158 m_placingVia = false;
1159 m_chainedPlacement = false;
1161 m_endItem = nullptr;
1162
1163 setInitialDirection( Settings().InitialDirection() );
1164
1165 initPlacement();
1166
1167 DIRECTION_45 initialDir = m_initial_direction;
1169
1170 if( aStartItem && aStartItem->Kind() == ITEM::SEGMENT_T )
1171 {
1172 // If we land on a segment endpoint, assume the starting direction is continuing along
1173 // the same direction as the endpoint. If we started in the middle, don't set a
1174 // direction so that the posture solver is not biased.
1175 SEG seg = static_cast<SEGMENT*>( aStartItem )->Seg();
1176
1177 if( aP == seg.A )
1178 lastSegDir = DIRECTION_45( seg.Reversed() );
1179 else if( aP == seg.B )
1180 lastSegDir = DIRECTION_45( seg );
1181 }
1182 else if( aStartItem && aStartItem->Kind() == ITEM::SOLID_T &&
1183 static_cast<SOLID*>( aStartItem )->Parent()->Type() == PCB_PAD_T )
1184 {
1185 double angle = static_cast<SOLID*>( aStartItem )->GetOrientation().AsDegrees();
1186 angle = ( angle + 22.5 ) / 45.0;
1187 initialDir = DIRECTION_45( static_cast<DIRECTION_45::Directions>( int( angle ) ) );
1188 }
1189
1190 wxLogTrace( wxT( "PNS" ), wxT( "Posture: init %s, last seg %s" ),
1191 initialDir.Format(), lastSegDir.Format() );
1192
1197 m_mouseTrailTracer.SetMouseDisabled( !Settings().GetAutoPosture() );
1198
1199 NODE *n;
1200
1201 if ( Settings().Mode() == PNS::RM_Shove )
1202 n = m_shove->CurrentNode();
1203 else
1204 n = m_currentNode;
1205
1207
1208 return true;
1209}
Directions
Available directions, there are 8 of them, as on a rectilinear map (north = up) + an extra undefined ...
Definition: direction45.h:49
void initPlacement()
Initialize placement of a new line with given parameters.
void SetMouseDisabled(bool aDisabled=true)
Disables the mouse-trail portion of the posture solver; leaving only the manual posture switch and th...
SEG Reversed() const
Returns the center point of the line.
Definition: seg.h:381
@ PCB_PAD_T
class PAD, a pad in a footprint
Definition: typeinfo.h:89
VECTOR2< int > VECTOR2I
Definition: vector2d.h:607

References SEG::A, PNS::FIXED_TAIL::AddStage(), PNS::MOUSE_TRAIL_TRACER::AddTrailPoint(), PNS::angle(), SEG::B, PNS::FIXED_TAIL::Clear(), PNS::MOUSE_TRAIL_TRACER::Clear(), DIRECTION_45::Format(), initPlacement(), PNS::ITEM::Kind(), m_chainedPlacement, m_currentEnd, m_currentLayer, m_currentNet, m_currentNode, m_currentStart, m_direction, m_endItem, m_fixedTail, m_head, m_initial_direction, m_mouseTrailTracer, m_placementCorrect, m_placingVia, m_shove, m_startItem, PNS::ITEM::Net(), PNS::ITEM::Parent(), PCB_PAD_T, SEG::Reversed(), PNS::RM_Shove, PNS::ITEM::SEGMENT_T, PNS::MOUSE_TRAIL_TRACER::SetDefaultDirections(), setInitialDirection(), PNS::MOUSE_TRAIL_TRACER::SetMouseDisabled(), PNS::ALGO_BASE::Settings(), PNS::MOUSE_TRAIL_TRACER::SetTolerance(), PNS::ITEM::SOLID_T, EDA_ITEM::Type(), DIRECTION_45::UNDEFINED, and PNS::LINE::Width().

◆ Tail()

const LINE & PNS::LINE_PLACER::Tail ( ) const
inline

Return the "tail" of the line being placed, the part which has already wrapped around and shoved some obstacles.

Definition at line 139 of file pns_line_placer.h.

139{ return m_tail; }

References m_tail.

◆ ToggleVia()

bool PNS::LINE_PLACER::ToggleVia ( bool  aEnabled)
overridevirtual

Enable/disable a via at the end of currently routed trace.

Reimplemented from PNS::PLACEMENT_ALGO.

Definition at line 83 of file pns_line_placer.cpp.

84{
85 m_placingVia = aEnabled;
86
87 if( !aEnabled )
89
90 return true;
91}

References m_head, m_placingVia, and PNS::LINE::RemoveVia().

◆ Trace()

const LINE PNS::LINE_PLACER::Trace ( ) const

Return the complete routed line.

Definition at line 1051 of file pns_line_placer.cpp.

1052{
1053 LINE tmp( m_head );
1054
1055 tmp.SetShape( m_tail.CLine() );
1056 tmp.Line().Append( m_head.CLine() );
1057
1058 PNS_DBG( Dbg(), AddItem, &m_tail, GREEN, 100000, wxT( "tmp-tail" ) );
1059 PNS_DBG( Dbg(), AddItem, &m_head, LIGHTGREEN, 100000, wxT( "tmp-head" ) );
1060
1061 tmp.Line().Simplify();
1062 return tmp;
1063}
const SHAPE_LINE_CHAIN & CLine() const
Definition: pns_line.h:137

References SHAPE_LINE_CHAIN::Append(), PNS::LINE::CLine(), PNS::ALGO_BASE::Dbg(), GREEN, LIGHTGREEN, PNS::LINE::Line(), m_head, m_tail, PNS_DBG, PNS::LINE::SetShape(), and SHAPE_LINE_CHAIN::Simplify().

Referenced by FixRoute(), Move(), optimizeTailHeadTransition(), Traces(), and updateLeadingRatLine().

◆ Traces()

const ITEM_SET PNS::LINE_PLACER::Traces ( )
overridevirtual

Return the complete routed line, as a single-member ITEM_SET.

Implements PNS::PLACEMENT_ALGO.

Definition at line 1066 of file pns_line_placer.cpp.

1067{
1069 return ITEM_SET( &m_currentTrace );
1070}

References m_currentTrace, and Trace().

◆ UnfixRoute()

bool PNS::LINE_PLACER::UnfixRoute ( )
overridevirtual

Reimplemented from PNS::PLACEMENT_ALGO.

Definition at line 1485 of file pns_line_placer.cpp.

1486{
1487 FIXED_TAIL::STAGE st;
1488
1489 if ( !m_fixedTail.PopStage( st ) )
1490 return false;
1491
1492 m_head.Line().Clear();
1493 m_tail.Line().Clear();
1494 m_startItem = nullptr;
1495 m_p_start = st.pts[0].p;
1496 m_direction = st.pts[0].direction;
1497 m_placingVia = st.pts[0].placingVias;
1498 m_currentNode = st.commit;
1499 m_currentLayer = st.pts[0].layer;
1502 m_head.RemoveVia();
1503 m_tail.RemoveVia();
1504
1508
1509 m_shove->RewindSpringbackTo( m_currentNode );
1510 m_shove->UnlockSpringbackNode( m_currentNode );
1511
1512 if( Settings().Mode() == PNS::RM_Shove )
1513 {
1514 m_currentNode = m_shove->CurrentNode();
1516 }
1517
1519
1520 return true;
1521}
bool PopStage(STAGE &aStage)

References PNS::MOUSE_TRAIL_TRACER::AddTrailPoint(), PNS::NODE::Branch(), SHAPE_LINE_CHAIN::Clear(), PNS::MOUSE_TRAIL_TRACER::Clear(), PNS::FIXED_TAIL::STAGE::commit, PNS::NODE::KillChildren(), PNS::LINE::Line(), m_currentLayer, m_currentNode, m_direction, m_fixedTail, m_head, m_initial_direction, m_lastNode, m_mouseTrailTracer, m_p_start, m_placingVia, m_shove, m_startItem, m_tail, PNS::FIXED_TAIL::PopStage(), PNS::FIXED_TAIL::STAGE::pts, PNS::LINE::RemoveVia(), PNS::RM_Shove, PNS::MOUSE_TRAIL_TRACER::SetDefaultDirections(), PNS::ITEM::SetLayer(), and PNS::ALGO_BASE::Settings().

◆ updateLeadingRatLine()

void PNS::LINE_PLACER::updateLeadingRatLine ( )
private

Draw the "leading" rats nest line, which connects the end of currently routed track and the nearest yet unrouted item.

If the routing for current net is complete, draws nothing.

Definition at line 1712 of file pns_line_placer.cpp.

1713{
1714 LINE current = Trace();
1715 SHAPE_LINE_CHAIN ratLine;
1716 TOPOLOGY topo( m_lastNode );
1717
1718 if( topo.LeadingRatLine( &current, ratLine ) )
1719 m_router->GetInterface()->DisplayRatline( ratLine, 5 );
1720}
virtual void DisplayRatline(const SHAPE_LINE_CHAIN &aRatline, int aColor=-1)=0
ROUTER_IFACE * GetInterface() const
Definition: pns_router.h:208

References PNS::ROUTER_IFACE::DisplayRatline(), PNS::ROUTER::GetInterface(), PNS::TOPOLOGY::LeadingRatLine(), m_lastNode, PNS::ALGO_BASE::m_router, and Trace().

Referenced by Move().

◆ UpdateSizes()

void PNS::LINE_PLACER::UpdateSizes ( const SIZES_SETTINGS aSizes)
overridevirtual

Perform on-the-fly update of the width, via diameter & drill size from a settings class.

Performs on-the-fly update of the width, via diameter & drill size from a settings class. Used to dynamically change these parameters as the track is routed.

Reimplemented from PNS::PLACEMENT_ALGO.

Definition at line 1686 of file pns_line_placer.cpp.

1687{
1688 m_sizes = aSizes;
1689
1690 if( !m_idle )
1691 {
1692 // If the track width continues from an existing track, we don't want to change the width.
1693 // Disallow changing width after the first segment has been fixed because we don't want to
1694 // go back and rip up tracks or allow DRC errors
1696 && ( !m_startItem || m_startItem->Kind() != ITEM::SEGMENT_T ) ) )
1697 {
1701 }
1702
1703 if( m_head.EndsWithVia() )
1704 {
1707 }
1708 }
1709}
PnsKind Kind() const
Return the type (kind) of the item.
Definition: pns_item.h:130
bool HasPlacedAnything() const override
void SetViaDrill(int aDrill)
Definition: pns_line.h:197
void SetViaDiameter(int aDiameter)
Definition: pns_line.h:196
bool EndsWithVia() const
Definition: pns_line.h:189
bool TrackWidthIsExplicit() const

References PNS::LINE::EndsWithVia(), HasPlacedAnything(), PNS::ITEM::Kind(), m_currentTrace, m_head, m_idle, m_sizes, m_startItem, m_tail, PNS::ITEM::SEGMENT_T, PNS::LINE::SetViaDiameter(), PNS::LINE::SetViaDrill(), PNS::LINE::SetWidth(), PNS::SIZES_SETTINGS::TrackWidth(), PNS::SIZES_SETTINGS::TrackWidthIsExplicit(), PNS::SIZES_SETTINGS::ViaDiameter(), and PNS::SIZES_SETTINGS::ViaDrill().

◆ VisibleViewArea()

const BOX2I & PNS::ALGO_BASE::VisibleViewArea ( ) const
inherited

Definition at line 40 of file pns_algo_base.cpp.

41{
42 return m_router->VisibleViewArea();
43}
const BOX2I & VisibleViewArea() const
Definition: pns_router.h:211

References PNS::ALGO_BASE::m_router, and PNS::ROUTER::VisibleViewArea().

Referenced by PNS::DRAGGER::optimizeAndUpdateDraggedLine(), and PNS::SHOVE::runOptimizer().

Member Data Documentation

◆ m_chainedPlacement

bool PNS::LINE_PLACER::m_chainedPlacement
private

Definition at line 359 of file pns_line_placer.h.

Referenced by FixRoute(), LINE_PLACER(), SetLayer(), and Start().

◆ m_currentEnd

VECTOR2I PNS::LINE_PLACER::m_currentEnd
private

Definition at line 351 of file pns_line_placer.h.

Referenced by CurrentEnd(), Move(), SetLayer(), and Start().

◆ m_currentLayer

int PNS::LINE_PLACER::m_currentLayer
private

◆ m_currentNet

int PNS::LINE_PLACER::m_currentNet
private

◆ m_currentNode

◆ m_currentStart

VECTOR2I PNS::LINE_PLACER::m_currentStart
private

Definition at line 352 of file pns_line_placer.h.

Referenced by FixRoute(), initPlacement(), SetLayer(), and Start().

◆ m_currentTrace

LINE PNS::LINE_PLACER::m_currentTrace
private

Definition at line 353 of file pns_line_placer.h.

Referenced by Traces(), and UpdateSizes().

◆ m_debugDecorator

DEBUG_DECORATOR* PNS::ALGO_BASE::m_debugDecorator
protectedinherited

Definition at line 86 of file pns_algo_base.h.

Referenced by PNS::ALGO_BASE::Dbg(), and PNS::ALGO_BASE::SetDebugDecorator().

◆ m_direction

◆ m_endItem

ITEM* PNS::LINE_PLACER::m_endItem
private

Definition at line 356 of file pns_line_placer.h.

Referenced by LINE_PLACER(), Move(), rhShoveOnly(), and Start().

◆ m_fixedTail

FIXED_TAIL PNS::LINE_PLACER::m_fixedTail
private

Definition at line 363 of file pns_line_placer.h.

Referenced by FixRoute(), HasPlacedAnything(), Start(), and UnfixRoute().

◆ m_head

LINE PNS::LINE_PLACER::m_head
private

the volatile part of the track from the previously analyzed point to the current routing destination

Definition at line 327 of file pns_line_placer.h.

Referenced by FixRoute(), handlePullback(), handleSelfIntersections(), Head(), initPlacement(), mergeHead(), optimizeTailHeadTransition(), reduceTail(), rhMarkObstacles(), rhShoveOnly(), rhWalkOnly(), route(), routeStep(), SetLayer(), Start(), ToggleVia(), Trace(), UnfixRoute(), and UpdateSizes().

◆ m_idle

bool PNS::LINE_PLACER::m_idle
private

Definition at line 358 of file pns_line_placer.h.

Referenced by FixRoute(), initPlacement(), LINE_PLACER(), SetLayer(), and UpdateSizes().

◆ m_initial_direction

DIRECTION_45 PNS::LINE_PLACER::m_initial_direction
private

◆ m_last_head

LINE PNS::LINE_PLACER::m_last_head
private

Most recent successful (non-colliding) head.

Definition at line 330 of file pns_line_placer.h.

Referenced by routeStep(), and SetLayer().

◆ m_lastNode

NODE* PNS::LINE_PLACER::m_lastNode
private

Postprocessed world state (including marked collisions & removed loops)

Definition at line 341 of file pns_line_placer.h.

Referenced by CommitPlacement(), CurrentNode(), FixRoute(), initPlacement(), LINE_PLACER(), Move(), UnfixRoute(), and updateLeadingRatLine().

◆ m_logger

LOGGER* PNS::ALGO_BASE::m_logger
protectedinherited

Definition at line 88 of file pns_algo_base.h.

Referenced by PNS::ALGO_BASE::SetLogger().

◆ m_mouseTrailTracer

MOUSE_TRAIL_TRACER PNS::LINE_PLACER::m_mouseTrailTracer
private

◆ m_orthoMode

bool PNS::LINE_PLACER::m_orthoMode
private

Definition at line 360 of file pns_line_placer.h.

Referenced by buildInitialLine(), LINE_PLACER(), and SetOrthoMode().

◆ m_p_start

VECTOR2I PNS::LINE_PLACER::m_p_start
private

current routing start (end of tail, beginning of head)

Definition at line 336 of file pns_line_placer.h.

Referenced by buildInitialLine(), FixRoute(), handlePullback(), handleSelfIntersections(), initPlacement(), mergeHead(), Move(), optimizeTailHeadTransition(), reduceTail(), SetLayer(), and UnfixRoute().

◆ m_placementCorrect

bool PNS::LINE_PLACER::m_placementCorrect
private

Definition at line 361 of file pns_line_placer.h.

Referenced by FixRoute(), HasPlacedAnything(), LINE_PLACER(), and Start().

◆ m_placingVia

bool PNS::LINE_PLACER::m_placingVia
private

◆ m_router

◆ m_shove

std::unique_ptr<SHOVE> PNS::LINE_PLACER::m_shove
private

The shove engine.

Definition at line 338 of file pns_line_placer.h.

Referenced by CommitPlacement(), FixRoute(), initPlacement(), LINE_PLACER(), rhShoveOnly(), Start(), and UnfixRoute().

◆ m_sizes

SIZES_SETTINGS PNS::LINE_PLACER::m_sizes
private

Definition at line 344 of file pns_line_placer.h.

Referenced by initPlacement(), makeVia(), and UpdateSizes().

◆ m_startItem

ITEM* PNS::LINE_PLACER::m_startItem
private

◆ m_tail

LINE PNS::LINE_PLACER::m_tail
private

routing "tail": part of the track that has been already fixed due to collisions with obstacles

Definition at line 332 of file pns_line_placer.h.

Referenced by buildInitialLine(), FixRoute(), handlePullback(), handleSelfIntersections(), initPlacement(), mergeHead(), optimizeTailHeadTransition(), reduceTail(), rhShoveOnly(), routeStep(), setInitialDirection(), SetLayer(), Tail(), Trace(), UnfixRoute(), and UpdateSizes().

◆ m_world

NODE* PNS::LINE_PLACER::m_world
private

pointer to world to search colliding items

Definition at line 335 of file pns_line_placer.h.

Referenced by AbortPlacement(), FixRoute(), initPlacement(), LINE_PLACER(), and setWorld().


The documentation for this class was generated from the following files: