KiCad PCB EDA Suite
PNS::LINE_PLACER Class Reference

Class LINE_PLACER. 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
 Function Start() More...
 
bool Move (const VECTOR2I &aP, ITEM *aEndItem) override
 Function Move() More...
 
bool FixRoute (const VECTOR2I &aP, ITEM *aEndItem, bool aForceFinish) override
 Function FixRoute() More...
 
bool ToggleVia (bool aEnabled) override
 Function ToggleVia() More...
 
bool SetLayer (int aLayer) override
 Function SetLayer() More...
 
const LINEHead () const
 Function Head() More...
 
const LINETail () const
 Function Tail() More...
 
const LINE Trace () const
 Function Trace() More...
 
const ITEM_SET Traces () override
 Function Traces() More...
 
const VECTOR2ICurrentEnd () const override
 Function CurrentEnd() More...
 
const std::vector< int > CurrentNets () const override
 Function CurrentNet() More...
 
int CurrentLayer () const override
 Function CurrentLayer() More...
 
NODECurrentNode (bool aLoopsRemoved=false) const override
 Function CurrentNode() More...
 
void FlipPosture () override
 Function FlipPosture() More...
 
void UpdateSizes (const SIZES_SETTINGS &aSizes) override
 Function UpdateSizes() 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...
 
LOGGERLogger () override
 

Returns the logger object, allowing to dump geometry to a file.

More...
 
bool SplitAdjacentSegments (NODE *aNode, ITEM *aSeg, const VECTOR2I &aP)
 Function SplitAdjacentSegments() More...
 
ROUTERRouter () const
 

Returns the instance of our router

More...
 
ROUTING_SETTINGSSettings () const
 

Returns current router settings

More...
 
void SetDebugDecorator (DEBUG_DECORATOR *aDecorator)
 Function SetDebugDecorator. More...
 
DEBUG_DECORATORDbg () const
 

Private Member Functions

bool route (const VECTOR2I &aP)
 Function route() More...
 
void updateLeadingRatLine ()
 Function updateLeadingRatLine() More...
 
void setWorld (NODE *aWorld)
 Function setWorld() More...
 
void initPlacement ()
 Function startPlacement() More...
 
void setInitialDirection (const DIRECTION_45 &aDirection)
 Function setInitialDirection() More...
 
void removeLoops (NODE *aNode, LINE &aLatest)
 Function removeLoops() More...
 
void simplifyNewLine (NODE *aNode, SEGMENT *aLatest)
 Function simplifyNewLine() More...
 
bool checkObtusity (const SEG &aA, const SEG &aB) const
 Function checkObtusity() More...
 
bool handleSelfIntersections ()
 Function handleSelfIntersections() More...
 
bool handlePullback ()
 Function handlePullback() More...
 
bool mergeHead ()
 Function mergeHead() More...
 
bool reduceTail (const VECTOR2I &aEnd)
 Function reduceTail() More...
 
bool optimizeTailHeadTransition ()
 Function optimizeTailHeadTransition() More...
 
bool routeHead (const VECTOR2I &aP, LINE &aNewHead)
 Function routeHead() More...
 
void routeStep (const VECTOR2I &aP)
 Function routeStep() More...
 
const LINE reduceToNearestObstacle (const LINE &aOriginalLine)
 
bool rhStopAtNearestObstacle (const VECTOR2I &aP, LINE &aNewHead)
 
bool rhWalkOnly (const VECTOR2I &aP, LINE &aNewHead)
 

route step, walkaround mode

More...
 
bool rhShoveOnly (const VECTOR2I &aP, LINE &aNewHead)
 

route step, shove mode

More...
 
bool rhMarkObstacles (const VECTOR2I &aP, LINE &aNewHead)
 

route step, mark obstacles mode

More...
 
const VIA makeVia (const VECTOR2I &aP)
 
bool buildInitialLine (const VECTOR2I &aP, LINE &aHead, bool aInvertPosture=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
 

routing "head": volatile part of the track from the previously

analyzed point to the current routing destination 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 point (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
 

Are we placing a via?

More...
 
int m_currentNet
 
int m_currentLayer
 
VECTOR2I m_currentEnd
 
VECTOR2I m_currentStart
 
LINE m_currentTrace
 
PNS_MODE m_currentMode
 
ITEMm_startItem
 
bool m_idle
 
bool m_chainedPlacement
 
bool m_orthoMode
 

Detailed Description

Class LINE_PLACER.

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

Definition at line 52 of file pns_line_placer.h.

Constructor & Destructor Documentation

◆ LINE_PLACER()

PNS::LINE_PLACER::LINE_PLACER ( ROUTER aRouter)

Definition at line 37 of file pns_line_placer.cpp.

37  :
38  PLACEMENT_ALGO( aRouter )
39 {
41  m_world = NULL;
42  m_shove = NULL;
43  m_currentNode = NULL;
44  m_idle = true;
45 
46  // Init temporary variables (do not leave uninitialized members)
47  m_lastNode = NULL;
48  m_placingVia = false;
49  m_currentNet = 0;
50  m_currentLayer = 0;
52  m_startItem = NULL;
53  m_chainedPlacement = false;
54  m_orthoMode = false;
55 }
NODE * m_lastNode
Postprocessed world state (including marked collisions & removed loops)
NODE * m_world
pointer to world to search colliding items
DIRECTION_45 m_initial_direction
routing direction for new traces
std::unique_ptr< SHOVE > m_shove
The shove engine
NODE * m_currentNode
Current world state
bool m_placingVia
Are we placing a via?
PLACEMENT_ALGO(ROUTER *aRouter)

References m_chainedPlacement, m_currentLayer, m_currentMode, m_currentNet, m_currentNode, m_idle, m_initial_direction, m_lastNode, m_orthoMode, m_placingVia, m_shove, m_startItem, m_world, DIRECTION_45::N, and PNS::RM_MarkObstacles.

◆ ~LINE_PLACER()

PNS::LINE_PLACER::~LINE_PLACER ( )

Definition at line 58 of file pns_line_placer.cpp.

59 {
60 }

Member Function Documentation

◆ buildInitialLine()

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

Definition at line 1189 of file pns_line_placer.cpp.

1190 {
1191  SHAPE_LINE_CHAIN l;
1192 
1193  if( m_p_start == aP )
1194  {
1195  l.Clear();
1196  }
1197  else
1198  {
1199  if( Settings().GetFreeAngleMode() && Settings().Mode() == RM_MarkObstacles )
1200  {
1201  l = SHAPE_LINE_CHAIN( m_p_start, aP );
1202  }
1203  else
1204  {
1205  if ( aInvertPosture )
1207  else
1209  }
1210 
1211  if( l.SegmentCount() > 1 && m_orthoMode )
1212  {
1213  VECTOR2I newLast = l.CSegment( 0 ).LineProject( l.CPoint( -1 ) );
1214 
1215  l.Remove( -1, -1 );
1216  l.Point( 1 ) = newLast;
1217  }
1218  }
1219 
1220  aHead.SetShape( l );
1221 
1222  if( !m_placingVia )
1223  return true;
1224 
1225  VIA v( makeVia( aP ) );
1226  v.SetNet( aHead.Net() );
1227 
1229  {
1230  aHead.AppendVia( v );
1231  return true;
1232  }
1233 
1234  VECTOR2I force;
1235  VECTOR2I lead = aP - m_p_start;
1236 
1237  bool solidsOnly = ( m_currentMode != RM_Walkaround );
1238 
1239  if( v.PushoutForce( m_currentNode, lead, force, solidsOnly, 40 ) )
1240  {
1242  aHead = LINE( aHead, line );
1243 
1244  v.SetPos( v.Pos() + force );
1245  return true;
1246  }
1247 
1248  return false; // via placement unsuccessful
1249 }
const SHAPE_LINE_CHAIN BuildInitialTrace(const VECTOR2I &aP0, const VECTOR2I &aP1, bool aStartDiagonal=false) const
Function BuildInitialTrace()
Definition: direction45.h:202
const DIRECTION_45 Right() const
Function Right()
Definition: direction45.h:262
ROUTING_SETTINGS & Settings() const
Returns current router settings
const VECTOR2I & CPoint(int aIndex) const
Function CPoint()
VECTOR2I LineProject(const VECTOR2I &aP) const
Function LineProject()
Definition: seg.h:341
DIRECTION_45 m_direction
current routing direction
void Remove(int aStartIndex, int aEndIndex)
Function Remove()
int SegmentCount() const
Function SegmentCount()
NODE * m_currentNode
Current world state
const SEG CSegment(int aIndex) const
Function CSegment()
bool m_placingVia
Are we placing a via?
Class SHAPE_LINE_CHAIN.
void Clear()
Function Clear() Removes all points from the line chain.
VECTOR2I m_p_start
current routing start point (end of tail, beginning of head)
VECTOR2I & Point(int aIndex)
Function Point()
const VIA makeVia(const VECTOR2I &aP)

References PNS::LINE::AppendVia(), DIRECTION_45::BuildInitialTrace(), SHAPE_LINE_CHAIN::Clear(), SHAPE_LINE_CHAIN::CPoint(), SHAPE_LINE_CHAIN::CSegment(), SEG::LineProject(), m_currentMode, m_currentNode, m_direction, m_orthoMode, m_p_start, m_placingVia, makeVia(), PNS::ITEM::Net(), SHAPE_LINE_CHAIN::Point(), PNS::VIA::Pos(), PNS::VIA::PushoutForce(), SHAPE_LINE_CHAIN::Remove(), DIRECTION_45::Right(), PNS::RM_MarkObstacles, PNS::RM_Walkaround, SHAPE_LINE_CHAIN::SegmentCount(), PNS::ITEM::SetNet(), PNS::VIA::SetPos(), PNS::LINE::SetShape(), and PNS::ALGO_BASE::Settings().

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

◆ checkObtusity()

bool PNS::LINE_PLACER::checkObtusity ( const SEG aA,
const SEG aB 
) const
private

Function checkObtusity()

Helper function, checking if segments a and b form an obtuse angle (in 45-degree regime).

Returns
true, if angle (aA, aB) is obtuse

Definition at line 281 of file pns_line_placer.cpp.

282 {
283  const DIRECTION_45 dir_a( aA );
284  const DIRECTION_45 dir_b( aB );
285 
286  return dir_a.IsObtuse( dir_b ) || dir_a == dir_b;
287 }
Class DIRECTION_45.
Definition: direction45.h:36

References DIRECTION_45::IsObtuse().

◆ CurrentEnd()

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

Function CurrentEnd()

Returns 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 136 of file pns_line_placer.h.

137  {
138  return m_currentEnd;
139  }

References m_currentEnd.

◆ CurrentLayer()

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

Function CurrentLayer()

Returns the layer of currently routed track.

Implements PNS::PLACEMENT_ALGO.

Definition at line 156 of file pns_line_placer.h.

157  {
158  return m_currentLayer;
159  }

References m_currentLayer.

◆ CurrentNets()

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

Function CurrentNet()

Returns the net code of currently routed track.

Implements PNS::PLACEMENT_ALGO.

Definition at line 146 of file pns_line_placer.h.

147  {
148  return std::vector<int>( 1, m_currentNet );
149  }

References m_currentNet.

◆ CurrentNode()

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

Function CurrentNode()

Returns the most recent world state.

Implements PNS::PLACEMENT_ALGO.

Definition at line 820 of file pns_line_placer.cpp.

821 {
822  if( aLoopsRemoved && m_lastNode )
823  return m_lastNode;
824 
825  return m_currentNode;
826 }
NODE * m_lastNode
Postprocessed world state (including marked collisions & removed loops)
NODE * m_currentNode
Current world state

References m_currentNode, and m_lastNode.

◆ Dbg()

◆ FixRoute()

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

Function FixRoute()

Commits 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 commited. May return false if the routing result is violating design rules - in such case, the track is only committed if Settings.CanViolateDRC() is on.

Implements PNS::PLACEMENT_ALGO.

Definition at line 982 of file pns_line_placer.cpp.

983 {
984  bool realEnd = false;
985  int lastV;
986 
987  LINE pl = Trace();
988 
990  {
991  // Mark Obstacles is sort of a half-manual, half-automated mode in which the
992  // user has more responsibility and authority.
993 
994  if( aEndItem )
995  {
996  // The user has indicated a connection should be made. If either the
997  // trace or endItem is netless, then allow the connection by adopting the net of the other.
998  if( m_currentNet <= 0 )
999  {
1000  m_currentNet = aEndItem->Net();
1001  pl.SetNet( m_currentNet );
1002  }
1003  else if (aEndItem->Net() <= 0 )
1004  aEndItem->SetNet( m_currentNet );
1005  }
1006 
1007  // Collisions still prevent fixing unless "Allow DRC violations" is checked
1008  if( !Settings().CanViolateDRC() && m_world->CheckColliding( &pl ) )
1009  return false;
1010  }
1011 
1012  const SHAPE_LINE_CHAIN& l = pl.CLine();
1013 
1014  if( !l.SegmentCount() )
1015  {
1016  if( pl.EndsWithVia() )
1017  {
1018  m_lastNode->Add( Clone( pl.Via() ) );
1020 
1021  m_lastNode = NULL;
1022  m_currentNode = NULL;
1023 
1024  m_idle = true;
1025  }
1026 
1027  return true;
1028  }
1029 
1030  VECTOR2I p_pre_last = l.CPoint( -1 );
1031  const VECTOR2I p_last = l.CPoint( -1 );
1032  DIRECTION_45 d_last( l.CSegment( -1 ) );
1033 
1034  if( l.PointCount() > 2 )
1035  p_pre_last = l.CPoint( -2 );
1036 
1037  if( aEndItem && m_currentNet >= 0 && m_currentNet == aEndItem->Net() )
1038  realEnd = true;
1039 
1040  if( aForceFinish )
1041  realEnd = true;
1042 
1043  if( realEnd || m_placingVia )
1044  lastV = l.SegmentCount();
1045  else
1046  lastV = std::max( 1, l.SegmentCount() - 1 );
1047 
1048  SEGMENT* lastSeg = nullptr;
1049 
1050  for( int i = 0; i < lastV; i++ )
1051  {
1052  const SEG& s = pl.CSegment( i );
1053  lastSeg = new SEGMENT( s, m_currentNet );
1054  std::unique_ptr< SEGMENT > seg( lastSeg );
1055  seg->SetWidth( pl.Width() );
1056  seg->SetLayer( m_currentLayer );
1057  if( ! m_lastNode->Add( std::move( seg ) ) )
1058  {
1059  lastSeg = nullptr;
1060  }
1061  }
1062 
1063  if( pl.EndsWithVia() )
1064  m_lastNode->Add( Clone( pl.Via() ) );
1065 
1066  if( realEnd && lastSeg )
1067  simplifyNewLine( m_lastNode, lastSeg );
1068 
1070 
1071  m_lastNode = NULL;
1072  m_currentNode = NULL;
1073 
1074  if( !realEnd )
1075  {
1076  setInitialDirection( d_last );
1077  m_currentStart = m_placingVia ? p_last : p_pre_last;
1078  m_startItem = NULL;
1079  m_placingVia = false;
1080  m_chainedPlacement = !pl.EndsWithVia();
1081  initPlacement();
1082  }
1083  else
1084  {
1085  m_idle = true;
1086  }
1087 
1088  return realEnd;
1089 }
ROUTER * Router() const
Returns the instance of our router
Definition: pns_algo_base.h:49
NODE * m_lastNode
Postprocessed world state (including marked collisions & removed loops)
NODE * m_world
pointer to world to search colliding items
const LINE Trace() const
Function Trace()
void simplifyNewLine(NODE *aNode, SEGMENT *aLatest)
Function simplifyNewLine()
int PointCount() const
Function PointCount()
ROUTING_SETTINGS & Settings() const
Returns current router settings
const VECTOR2I & CPoint(int aIndex) const
Function CPoint()
void setInitialDirection(const DIRECTION_45 &aDirection)
Function setInitialDirection()
Class DIRECTION_45.
Definition: direction45.h:36
void initPlacement()
Function startPlacement()
int SegmentCount() const
Function SegmentCount()
std::unique_ptr< typename std::remove_const< T >::type > Clone(const T &aItem)
Definition: pns_item.h:385
Definition: seg.h:36
NODE * m_currentNode
Current world state
void CommitRouting(NODE *aNode)
Definition: pns_router.cpp:350
const SEG CSegment(int aIndex) const
Function CSegment()
#define max(a, b)
Definition: auxiliary.h:86
bool m_placingVia
Are we placing a via?
Class SHAPE_LINE_CHAIN.
OPT_OBSTACLE CheckColliding(const ITEM *aItem, int aKindMask=ITEM::ANY_T)
Function CheckColliding()
Definition: pns_node.cpp:425
size_t i
Definition: json11.cpp:597
bool Add(std::unique_ptr< SEGMENT > aSegment, bool aAllowRedundant=false)
Function Add()
Definition: pns_node.cpp:594

References PNS::NODE::Add(), PNS::NODE::CheckColliding(), PNS::LINE::CLine(), PNS::Clone(), PNS::ROUTER::CommitRouting(), SHAPE_LINE_CHAIN::CPoint(), PNS::LINE::CSegment(), SHAPE_LINE_CHAIN::CSegment(), PNS::LINE::EndsWithVia(), i, initPlacement(), m_chainedPlacement, m_currentLayer, m_currentMode, m_currentNet, m_currentNode, m_currentStart, m_idle, m_lastNode, m_placingVia, m_startItem, m_world, max, PNS::ITEM::Net(), SHAPE_LINE_CHAIN::PointCount(), PNS::RM_MarkObstacles, PNS::ALGO_BASE::Router(), SHAPE_LINE_CHAIN::SegmentCount(), setInitialDirection(), PNS::ITEM::SetNet(), PNS::ALGO_BASE::Settings(), simplifyNewLine(), Trace(), PNS::LINE::Via(), and PNS::LINE::Width().

◆ FlipPosture()

void PNS::LINE_PLACER::FlipPosture ( )
overridevirtual

Function FlipPosture()

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

Reimplemented from PNS::PLACEMENT_ALGO.

Definition at line 813 of file pns_line_placer.cpp.

814 {
817 }
const DIRECTION_45 Right() const
Function Right()
Definition: direction45.h:262
DIRECTION_45 m_initial_direction
routing direction for new traces
DIRECTION_45 m_direction
current routing direction

References m_direction, m_initial_direction, and DIRECTION_45::Right().

◆ 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 1252 of file pns_line_placer.cpp.

1253 {
1254  aNets.push_back( m_currentNet );
1255 }

References m_currentNet.

◆ handlePullback()

bool PNS::LINE_PLACER::handlePullback ( )
private

Function handlePullback()

Deals 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 157 of file pns_line_placer.cpp.

158 {
159  SHAPE_LINE_CHAIN& head = m_head.Line();
160  SHAPE_LINE_CHAIN& tail = m_tail.Line();
161 
162  if( head.PointCount() < 2 )
163  return false;
164 
165  int n = tail.PointCount();
166 
167  if( n == 0 )
168  return false;
169  else if( n == 1 )
170  {
171  m_p_start = tail.CPoint( 0 );
172  tail.Clear();
173  return true;
174  }
175 
176  DIRECTION_45 first_head( head.CSegment( 0 ) );
177  DIRECTION_45 last_tail( tail.CSegment( -1 ) );
178  DIRECTION_45::AngleType angle = first_head.Angle( last_tail );
179 
180  // case 1: we have a defined routing direction, and the currently computed
181  // head goes in different one.
182  bool pullback_1 = false; // (m_direction != DIRECTION_45::UNDEFINED && m_direction != first_head);
183 
184  // case 2: regardless of the current routing direction, if the tail/head
185  // extremities form an acute or right angle, reduce the tail by one segment
186  // (and hope that further iterations) will result with a cleaner trace
187  bool pullback_2 = ( angle == DIRECTION_45::ANG_RIGHT || angle == DIRECTION_45::ANG_ACUTE );
188 
189  if( pullback_1 || pullback_2 )
190  {
191  const SEG last = tail.CSegment( -1 );
192  m_direction = DIRECTION_45( last );
193  m_p_start = last.A;
194 
195  wxLogTrace( "PNS", "Placer: pullback triggered [%d] [%s %s]",
196  n, last_tail.Format().c_str(), first_head.Format().c_str() );
197 
198  // erase the last point in the tail, hoping that the next iteration will
199  // result with a head trace that starts with a segment following our
200  // current direction.
201  if( n < 2 )
202  tail.Clear(); // don't leave a single-point tail
203  else
204  tail.Remove( -1, -1 );
205 
206  if( !tail.SegmentCount() )
208 
209  return true;
210  }
211 
212  return false;
213 }
LINE m_head
routing "head": volatile part of the track from the previously analyzed point to the current routing ...
int PointCount() const
Function PointCount()
const VECTOR2I & CPoint(int aIndex) const
Function CPoint()
DIRECTION_45 m_initial_direction
routing direction for new traces
LINE m_tail
routing "tail": part of the track that has been already fixed due to collisions with obstacles
Class DIRECTION_45.
Definition: direction45.h:36
DIRECTION_45 m_direction
current routing direction
void Remove(int aStartIndex, int aEndIndex)
Function Remove()
int SegmentCount() const
Function SegmentCount()
SHAPE_LINE_CHAIN & Line()
Modifiable accessor to the underlying shape
Definition: pns_line.h:117
Definition: seg.h:36
AngleType
Enum AngleType Represents kind of angle formed by vectors heading in two DIRECTION_45s.
Definition: direction45.h:62
const SEG CSegment(int aIndex) const
Function CSegment()
Class SHAPE_LINE_CHAIN.
static DIRECTION_45::AngleType angle(const VECTOR2I &a, const VECTOR2I &b)
VECTOR2I A
Definition: seg.h:44
void Clear()
Function Clear() Removes all points from the line chain.
VECTOR2I m_p_start
current routing start point (end of tail, beginning of head)

References SEG::A, DIRECTION_45::ANG_ACUTE, DIRECTION_45::ANG_RIGHT, PNS::angle(), SHAPE_LINE_CHAIN::Clear(), SHAPE_LINE_CHAIN::CPoint(), SHAPE_LINE_CHAIN::CSegment(), PNS::LINE::Line(), m_direction, m_head, m_initial_direction, m_p_start, m_tail, SHAPE_LINE_CHAIN::PointCount(), SHAPE_LINE_CHAIN::Remove(), and SHAPE_LINE_CHAIN::SegmentCount().

Referenced by routeStep().

◆ handleSelfIntersections()

bool PNS::LINE_PLACER::handleSelfIntersections ( )
private

Function handleSelfIntersections()

Checks 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 97 of file pns_line_placer.cpp.

98 {
100  SHAPE_LINE_CHAIN& head = m_head.Line();
101  SHAPE_LINE_CHAIN& tail = m_tail.Line();
102 
103  // if there is no tail, there is nothing to intersect with
104  if( tail.PointCount() < 2 )
105  return false;
106 
107  tail.Intersect( head, ips );
108 
109  // no intesection points - nothing to reduce
110  if( ips.empty() )
111  return false;
112 
113  int n = INT_MAX;
114  VECTOR2I ipoint;
115 
116  // if there is more than one intersection, find the one that is
117  // closest to the beginning of the tail.
118  for( SHAPE_LINE_CHAIN::INTERSECTION i : ips )
119  {
120  if( i.our.Index() < n )
121  {
122  n = i.our.Index();
123  ipoint = i.p;
124  }
125  }
126 
127  // ignore the point where head and tail meet
128  if( ipoint == head.CPoint( 0 ) || ipoint == tail.CPoint( -1 ) )
129  return false;
130 
131  // Intersection point is on the first or the second segment: just start routing
132  // from the beginning
133  if( n < 2 )
134  {
135  m_p_start = tail.Point( 0 );
137  tail.Clear();
138  head.Clear();
139 
140  return true;
141  }
142  else
143  {
144  // Clip till the last tail segment before intersection.
145  // Set the direction to the one of this segment.
146  const SEG last = tail.CSegment( n - 1 );
147  m_p_start = last.A;
148  m_direction = DIRECTION_45( last );
149  tail.Remove( n, -1 );
150  return true;
151  }
152 
153  return false;
154 }
int Intersect(const SEG &aSeg, INTERSECTIONS &aIp) const
Function Intersect()
std::vector< INTERSECTION > INTERSECTIONS
LINE m_head
routing "head": volatile part of the track from the previously analyzed point to the current routing ...
int PointCount() const
Function PointCount()
const VECTOR2I & CPoint(int aIndex) const
Function CPoint()
DIRECTION_45 m_initial_direction
routing direction for new traces
LINE m_tail
routing "tail": part of the track that has been already fixed due to collisions with obstacles
Class DIRECTION_45.
Definition: direction45.h:36
DIRECTION_45 m_direction
current routing direction
void Remove(int aStartIndex, int aEndIndex)
Function Remove()
SHAPE_LINE_CHAIN & Line()
Modifiable accessor to the underlying shape
Definition: pns_line.h:117
Definition: seg.h:36
const SEG CSegment(int aIndex) const
Function CSegment()
Class SHAPE_LINE_CHAIN.
size_t i
Definition: json11.cpp:597
VECTOR2I A
Definition: seg.h:44
void Clear()
Function Clear() Removes all points from the line chain.
VECTOR2I m_p_start
current routing start point (end of tail, beginning of head)
VECTOR2I & Point(int aIndex)
Function Point()

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

Referenced by routeStep().

◆ Head()

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

Function Head()

Returns the "head" of the line being placed, that is the volatile part that has not "settled" yet.

Definition at line 106 of file pns_line_placer.h.

106 { return m_head; }
LINE m_head
routing "head": volatile part of the track from the previously analyzed point to the current routing ...

References m_head.

◆ initPlacement()

void PNS::LINE_PLACER::initPlacement ( )
private

Function startPlacement()

Initializes placement of a new line with given parameters.

Definition at line 899 of file pns_line_placer.cpp.

900 {
901  m_idle = false;
902 
903  m_head.Line().Clear();
904  m_tail.Line().Clear();
911  m_head.RemoveVia();
912  m_tail.RemoveVia();
913 
916 
917  NODE* world = Router()->GetWorld();
918 
919  world->KillChildren();
920  NODE* rootNode = world->Branch();
921 
923 
924  setWorld( rootNode );
925 
926  wxLogTrace( "PNS", "world %p, intitial-direction %s layer %d",
928 
929  m_lastNode = NULL;
932 
933  m_shove.reset();
934 
936  {
937  m_shove.reset( new SHOVE( m_world->Branch(), Router() ) );
938  }
939 }
ROUTER * Router() const
Returns the instance of our router
Definition: pns_algo_base.h:49
NODE * m_lastNode
Postprocessed world state (including marked collisions & removed loops)
NODE * m_world
pointer to world to search colliding items
void SetLayer(int aLayer)
Function SetLayer()
Definition: pns_item.h:204
const std::string Format() const
Function Format() Formats the direction in a human readable word.
Definition: direction45.h:97
Ignore collisions, mark obstacles
LINE m_head
routing "head": volatile part of the track from the previously analyzed point to the current routing ...
void RemoveVia()
Definition: pns_line.h:251
SIZES_SETTINGS m_sizes
NODE * Branch()
Function Branch()
Definition: pns_node.cpp:107
void SetWidth(int aWidth)
Sets line width
Definition: pns_line.h:153
void SetNet(int aNet)
Function SetNet()
Definition: pns_item.h:169
ROUTING_SETTINGS & Settings() const
Returns current router settings
DIRECTION_45 m_initial_direction
routing direction for new traces
void KillChildren()
Destroys all child nodes. Applicable only to the root node.
Definition: pns_node.cpp:1226
LINE m_tail
routing "tail": part of the track that has been already fixed due to collisions with obstacles
bool SplitAdjacentSegments(NODE *aNode, ITEM *aSeg, const VECTOR2I &aP)
Function SplitAdjacentSegments()
DIRECTION_45 m_direction
current routing direction
PNS_MODE Mode() const
Returns the routing mode.
std::unique_ptr< SHOVE > m_shove
The shove engine
SHAPE_LINE_CHAIN & Line()
Modifiable accessor to the underlying shape
Definition: pns_line.h:117
Only walkaround
NODE * m_currentNode
Current world state
void setWorld(NODE *aWorld)
Function setWorld()
void Clear()
Function Clear() Removes all points from the line chain.
VECTOR2I m_p_start
current routing start point (end of tail, beginning of head)
NODE * GetWorld() const
Definition: pns_router.h:143

References PNS::NODE::Branch(), SHAPE_LINE_CHAIN::Clear(), DIRECTION_45::Format(), PNS::ROUTER::GetWorld(), PNS::NODE::KillChildren(), PNS::LINE::Line(), m_currentLayer, m_currentMode, 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::ROUTING_SETTINGS::Mode(), PNS::LINE::RemoveVia(), PNS::RM_Shove, PNS::RM_Smart, PNS::ALGO_BASE::Router(), PNS::ITEM::SetLayer(), PNS::ITEM::SetNet(), PNS::ALGO_BASE::Settings(), PNS::LINE::SetWidth(), setWorld(), SplitAdjacentSegments(), and PNS::SIZES_SETTINGS::TrackWidth().

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

◆ 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 186 of file pns_line_placer.h.

186 { return m_placingVia; }
bool m_placingVia
Are we placing a via?

References m_placingVia.

◆ Logger()

LOGGER * PNS::LINE_PLACER::Logger ( )
overridevirtual

Returns the logger object, allowing to dump geometry to a file.

Reimplemented from PNS::ALGO_BASE.

Definition at line 1257 of file pns_line_placer.cpp.

1258 {
1259  if( m_shove )
1260  return m_shove->Logger();
1261 
1262  return NULL;
1263 }
std::unique_ptr< SHOVE > m_shove
The shove engine

References m_shove.

◆ makeVia()

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

◆ mergeHead()

bool PNS::LINE_PLACER::mergeHead ( )
private

Function mergeHead()

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

Returns
true, if the line has been changed.

Definition at line 290 of file pns_line_placer.cpp.

291 {
292  SHAPE_LINE_CHAIN& head = m_head.Line();
293  SHAPE_LINE_CHAIN& tail = m_tail.Line();
294 
295  const int ForbiddenAngles = DIRECTION_45::ANG_ACUTE |
298 
299  head.Simplify();
300  tail.Simplify();
301 
302  int n_head = head.SegmentCount();
303  int n_tail = tail.SegmentCount();
304 
305  if( n_head < 3 )
306  {
307  wxLogTrace( "PNS", "Merge failed: not enough head segs." );
308  return false;
309  }
310 
311  if( n_tail && head.CPoint( 0 ) != tail.CPoint( -1 ) )
312  {
313  wxLogTrace( "PNS", "Merge failed: head and tail discontinuous." );
314  return false;
315  }
316 
317  if( m_head.CountCorners( ForbiddenAngles ) != 0 )
318  return false;
319 
320  DIRECTION_45 dir_tail, dir_head;
321 
322  dir_head = DIRECTION_45( head.CSegment( 0 ) );
323 
324  if( n_tail )
325  {
326  dir_tail = DIRECTION_45( tail.CSegment( -1 ) );
327 
328  if( dir_head.Angle( dir_tail ) & ForbiddenAngles )
329  return false;
330  }
331 
332  if( !n_tail )
333  tail.Append( head.CSegment( 0 ).A );
334 
335  for( int i = 0; i < n_head - 2; i++ )
336  {
337  tail.Append( head.CSegment( i ).B );
338  }
339 
340  tail.Simplify();
341 
342  SEG last = tail.CSegment( -1 );
343 
344  m_p_start = last.B;
345  m_direction = DIRECTION_45( last ).Right();
346 
347  head.Remove( 0, n_head - 2 );
348 
349  wxLogTrace( "PNS", "Placer: merge %d, new direction: %s", n_head, m_direction.Format().c_str() );
350 
351  head.Simplify();
352  tail.Simplify();
353 
354  return true;
355 }
const std::string Format() const
Function Format() Formats the direction in a human readable word.
Definition: direction45.h:97
LINE m_head
routing "head": volatile part of the track from the previously analyzed point to the current routing ...
const DIRECTION_45 Right() const
Function Right()
Definition: direction45.h:262
void Append(int aX, int aY, bool aAllowDuplication=false)
Function Append()
SHAPE_LINE_CHAIN & Simplify()
Function Simplify()
AngleType Angle(const DIRECTION_45 &aOther) const
Function Angle() Returns the type of angle between directions (this) and aOther.
Definition: direction45.h:149
const VECTOR2I & CPoint(int aIndex) const
Function CPoint()
LINE m_tail
routing "tail": part of the track that has been already fixed due to collisions with obstacles
Class DIRECTION_45.
Definition: direction45.h:36
DIRECTION_45 m_direction
current routing direction
void Remove(int aStartIndex, int aEndIndex)
Function Remove()
int SegmentCount() const
Function SegmentCount()
SHAPE_LINE_CHAIN & Line()
Modifiable accessor to the underlying shape
Definition: pns_line.h:117
Definition: seg.h:36
const SEG CSegment(int aIndex) const
Function CSegment()
Class SHAPE_LINE_CHAIN.
size_t i
Definition: json11.cpp:597
VECTOR2I A
Definition: seg.h:44
VECTOR2I m_p_start
current routing start point (end of tail, beginning of head)
int CountCorners(int aAngles) const
Returns the number of corners of angles specified by mask aAngles.
Definition: pns_line.cpp:136
VECTOR2I B
Definition: seg.h:45

References SEG::A, DIRECTION_45::ANG_ACUTE, DIRECTION_45::ANG_HALF_FULL, DIRECTION_45::ANG_UNDEFINED, DIRECTION_45::Angle(), SHAPE_LINE_CHAIN::Append(), SEG::B, PNS::LINE::CountCorners(), SHAPE_LINE_CHAIN::CPoint(), SHAPE_LINE_CHAIN::CSegment(), DIRECTION_45::Format(), i, PNS::LINE::Line(), m_direction, m_head, m_p_start, m_tail, SHAPE_LINE_CHAIN::Remove(), DIRECTION_45::Right(), SHAPE_LINE_CHAIN::SegmentCount(), and SHAPE_LINE_CHAIN::Simplify().

Referenced by routeStep().

◆ Move()

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

Function Move()

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

Implements PNS::PLACEMENT_ALGO.

Definition at line 942 of file pns_line_placer.cpp.

943 {
944  LINE current;
945  VECTOR2I p = aP;
946  int eiDepth = -1;
947 
948  if( aEndItem && aEndItem->Owner() )
949  eiDepth = static_cast<NODE*>( aEndItem->Owner() )->Depth();
950 
951  if( m_lastNode )
952  {
953  delete m_lastNode;
954  m_lastNode = NULL;
955  }
956 
957  bool reachesEnd = route( p );
958 
959  current = Trace();
960 
961  if( !current.PointCount() )
963  else
964  m_currentEnd = current.CLine().CPoint( -1 );
965 
966  NODE* latestNode = m_currentNode;
967  m_lastNode = latestNode->Branch();
968 
969  if( reachesEnd && eiDepth >= 0 && aEndItem && latestNode->Depth() > eiDepth && current.SegmentCount() )
970  {
971  SplitAdjacentSegments( m_lastNode, aEndItem, current.CPoint( -1 ) );
972 
973  if( Settings().RemoveLoops() )
974  removeLoops( m_lastNode, current );
975  }
976 
978  return true;
979 }
NODE * m_lastNode
Postprocessed world state (including marked collisions & removed loops)
void removeLoops(NODE *aNode, LINE &aLatest)
Function removeLoops()
const LINE Trace() const
Function Trace()
NODE * Branch()
Function Branch()
Definition: pns_node.cpp:107
bool RemoveLoops() const
Returns true if loop (redundant track) removal is on.
ROUTING_SETTINGS & Settings() const
Returns current router settings
bool SplitAdjacentSegments(NODE *aNode, ITEM *aSeg, const VECTOR2I &aP)
Function SplitAdjacentSegments()
void updateLeadingRatLine()
Function updateLeadingRatLine()
bool route(const VECTOR2I &aP)
Function route()
NODE * m_currentNode
Current world state
VECTOR2I m_p_start
current routing start point (end of tail, beginning of head)

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

Referenced by SetLayer().

◆ optimizeTailHeadTransition()

bool PNS::LINE_PLACER::optimizeTailHeadTransition ( )
private

Function optimizeTailHeadTransition()

Tries 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 664 of file pns_line_placer.cpp.

665 {
666  LINE linetmp = Trace();
667 
669  {
670  if( linetmp.SegmentCount() < 1 )
671  return false;
672 
673  m_head = linetmp;
674  m_p_start = linetmp.CLine().CPoint( 0 );
675  m_direction = DIRECTION_45( linetmp.CSegment( 0 ) );
676  m_tail.Line().Clear();
677 
678  return true;
679  }
680 
681  SHAPE_LINE_CHAIN& head = m_head.Line();
682  SHAPE_LINE_CHAIN& tail = m_tail.Line();
683 
684  int tailLookbackSegments = 3;
685 
686  //if(m_currentMode() == RM_Walkaround)
687  // tailLookbackSegments = 10000;
688 
689  int threshold = std::min( tail.PointCount(), tailLookbackSegments + 1 );
690 
691  if( tail.SegmentCount() < 3 )
692  return false;
693 
694  // assemble TailLookbackSegments tail segments with the current head
695  SHAPE_LINE_CHAIN opt_line = tail.Slice( -threshold, -1 );
696 
697  int end = std::min(2, head.PointCount() - 1 );
698 
699  opt_line.Append( head.Slice( 0, end ) );
700 
701  LINE new_head( m_tail, opt_line );
702 
703  // and see if it could be made simpler by merging obtuse/collnear segments.
704  // If so, replace the (threshold) last tail points and the head with
705  // the optimized line
706 
708  {
709  LINE tmp( m_tail, opt_line );
710 
711  wxLogTrace( "PNS", "Placer: optimize tail-head [%d]", threshold );
712 
713  head.Clear();
714  tail.Replace( -threshold, -1, new_head.CLine() );
715  tail.Simplify();
716 
717  m_p_start = new_head.CLine().CPoint( -1 );
718  m_direction = DIRECTION_45( new_head.CSegment( -1 ) );
719 
720  return true;
721  }
722 
723  return false;
724 }
const SHAPE_LINE_CHAIN Slice(int aStartIndex, int aEndIndex=-1) const
Function Slice()
LINE m_head
routing "head": volatile part of the track from the previously analyzed point to the current routing ...
const LINE Trace() const
Function Trace()
int PointCount() const
Function PointCount()
void Append(int aX, int aY, bool aAllowDuplication=false)
Function Append()
SHAPE_LINE_CHAIN & Simplify()
Function Simplify()
LINE m_tail
routing "tail": part of the track that has been already fixed due to collisions with obstacles
Class DIRECTION_45.
Definition: direction45.h:36
DIRECTION_45 m_direction
current routing direction
int SegmentCount() const
Function SegmentCount()
SHAPE_LINE_CHAIN & Line()
Modifiable accessor to the underlying shape
Definition: pns_line.h:117
NODE * m_currentNode
Current world state
Class SHAPE_LINE_CHAIN.
void Clear()
Function Clear() Removes all points from the line chain.
VECTOR2I m_p_start
current routing start point (end of tail, beginning of head)
void Replace(int aStartIndex, int aEndIndex, const VECTOR2I &aP)
Function Replace()
static bool Optimize(LINE *aLine, int aEffortLevel, NODE *aWorld)
a quick shortcut to optmize a line without creating and setting up an optimizer
#define min(a, b)
Definition: auxiliary.h:85

References SHAPE_LINE_CHAIN::Append(), SHAPE_LINE_CHAIN::Clear(), PNS::LINE::CLine(), SHAPE_LINE_CHAIN::CPoint(), PNS::LINE::CSegment(), PNS::OPTIMIZER::FANOUT_CLEANUP, PNS::LINE::Line(), m_currentNode, m_direction, m_head, m_p_start, m_tail, PNS::OPTIMIZER::MERGE_OBTUSE, min, PNS::OPTIMIZER::Optimize(), SHAPE_LINE_CHAIN::PointCount(), SHAPE_LINE_CHAIN::Replace(), PNS::LINE::SegmentCount(), SHAPE_LINE_CHAIN::SegmentCount(), SHAPE_LINE_CHAIN::Simplify(), SHAPE_LINE_CHAIN::Slice(), and Trace().

Referenced by routeStep().

◆ reduceTail()

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

Function reduceTail()

Attempts to reduce the numer 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
aEndcurrent routing destination point.
Returns
true if the line has been changed.

Definition at line 216 of file pns_line_placer.cpp.

217 {
218  SHAPE_LINE_CHAIN& head = m_head.Line();
219  SHAPE_LINE_CHAIN& tail = m_tail.Line();
220 
221  int n = tail.SegmentCount();
222 
223  if( head.SegmentCount() < 1 )
224  return false;
225 
226  // Don't attempt this for too short tails
227  if( n < 2 )
228  return false;
229 
230  // Start from the segment farthest from the end of the tail
231  // int start_index = std::max(n - 1 - ReductionDepth, 0);
232 
233  DIRECTION_45 new_direction;
234  VECTOR2I new_start;
235  int reduce_index = -1;
236 
237  for( int i = tail.SegmentCount() - 1; i >= 0; i-- )
238  {
239  const SEG s = tail.CSegment( i );
240  DIRECTION_45 dir( s );
241 
242  // calculate a replacement route and check if it matches
243  // the direction of the segment to be replaced
244  SHAPE_LINE_CHAIN replacement = dir.BuildInitialTrace( s.A, aEnd );
245 
246  if( replacement.SegmentCount() < 1 )
247  continue;
248 
249  LINE tmp( m_tail, replacement );
250 
252  break;
253 
254  if( DIRECTION_45( replacement.CSegment( 0 ) ) == dir )
255  {
256  new_start = s.A;
257  new_direction = dir;
258  reduce_index = i;
259  }
260  }
261 
262  if( reduce_index >= 0 )
263  {
264  wxLogTrace( "PNS", "Placer: reducing tail: %d", reduce_index );
265  SHAPE_LINE_CHAIN reducedLine = new_direction.BuildInitialTrace( new_start, aEnd );
266 
267  m_p_start = new_start;
268  m_direction = new_direction;
269  tail.Remove( reduce_index + 1, -1 );
270  head.Clear();
271  return true;
272  }
273 
274  if( !tail.SegmentCount() )
276 
277  return false;
278 }
const SHAPE_LINE_CHAIN BuildInitialTrace(const VECTOR2I &aP0, const VECTOR2I &aP1, bool aStartDiagonal=false) const
Function BuildInitialTrace()
Definition: direction45.h:202
LINE m_head
routing "head": volatile part of the track from the previously analyzed point to the current routing ...
DIRECTION_45 m_initial_direction
routing direction for new traces
LINE m_tail
routing "tail": part of the track that has been already fixed due to collisions with obstacles
Class DIRECTION_45.
Definition: direction45.h:36
DIRECTION_45 m_direction
current routing direction
void Remove(int aStartIndex, int aEndIndex)
Function Remove()
int SegmentCount() const
Function SegmentCount()
SHAPE_LINE_CHAIN & Line()
Modifiable accessor to the underlying shape
Definition: pns_line.h:117
Definition: seg.h:36
NODE * m_currentNode
Current world state
const SEG CSegment(int aIndex) const
Function CSegment()
Class SHAPE_LINE_CHAIN.
OPT_OBSTACLE CheckColliding(const ITEM *aItem, int aKindMask=ITEM::ANY_T)
Function CheckColliding()
Definition: pns_node.cpp:425
size_t i
Definition: json11.cpp:597
VECTOR2I A
Definition: seg.h:44
void Clear()
Function Clear() Removes all points from the line chain.
VECTOR2I m_p_start
current routing start point (end of tail, beginning of head)

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

Referenced by routeStep().

◆ reduceToNearestObstacle()

const LINE PNS::LINE_PLACER::reduceToNearestObstacle ( const LINE aOriginalLine)
private

Definition at line 456 of file pns_line_placer.cpp.

457 {
458  const auto& l0 = aOriginalLine.CLine();
459 
460  if ( !l0.PointCount() )
461  return aOriginalLine;
462 
463  int l = l0.Length();
464  int step = l / 2;
465  VECTOR2I target;
466 
467  LINE l_test( aOriginalLine );
468 
469  while( step > 0 )
470  {
471  target = l0.PointAlong( l );
472  SHAPE_LINE_CHAIN l_cur( l0 );
473 
474  int index = l_cur.Split( target );
475 
476  l_test.SetShape( l_cur.Slice( 0, index ) );
477 
478  if ( m_currentNode->CheckColliding( &l_test ) )
479  l -= step;
480  else
481  l += step;
482 
483  step /= 2;
484  }
485 
486  l = l_test.CLine().Length();
487 
488  while( m_currentNode->CheckColliding( &l_test ) && l > 0 )
489  {
490  l--;
491  target = l0.PointAlong( l );
492  SHAPE_LINE_CHAIN l_cur( l0 );
493 
494  int index = l_cur.Split( target );
495 
496  l_test.SetShape( l_cur.Slice( 0, index ) );
497  }
498 
499  return l_test;
500 }
NODE * m_currentNode
Current world state
Class SHAPE_LINE_CHAIN.
OPT_OBSTACLE CheckColliding(const ITEM *aItem, int aKindMask=ITEM::ANY_T)
Function CheckColliding()
Definition: pns_node.cpp:425

References PNS::NODE::CheckColliding(), PNS::LINE::CLine(), SHAPE_LINE_CHAIN::Length(), m_currentNode, PNS::LINE::SetShape(), SHAPE_LINE_CHAIN::Slice(), and SHAPE_LINE_CHAIN::Split().

Referenced by rhStopAtNearestObstacle().

◆ removeLoops()

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

Function removeLoops()

Searches aNode for traces concurrent to aLatest and removes them. Updated topology is stored in aNode.

Definition at line 1092 of file pns_line_placer.cpp.

1093 {
1094  if( !aLatest.SegmentCount() )
1095  return;
1096 
1097  if( aLatest.CLine().CPoint( 0 ) == aLatest.CLine().CPoint( -1 ) )
1098  return;
1099 
1100  std::set<SEGMENT *> toErase;
1101  aNode->Add( aLatest, true );
1102 
1103  for( int s = 0; s < aLatest.LinkCount(); s++ )
1104  {
1105  SEGMENT* seg = aLatest.GetLink(s);
1106  LINE ourLine = aNode->AssembleLine( seg );
1107  JOINT a, b;
1108  std::vector<LINE> lines;
1109 
1110  aNode->FindLineEnds( ourLine, a, b );
1111 
1112  if( a == b )
1113  {
1114  aNode->FindLineEnds( aLatest, a, b );
1115  }
1116 
1117  aNode->FindLinesBetweenJoints( a, b, lines );
1118 
1119  int removedCount = 0;
1120  int total = 0;
1121 
1122  for( LINE& line : lines )
1123  {
1124  total++;
1125 
1126  if( !( line.ContainsSegment( seg ) ) && line.SegmentCount() )
1127  {
1128  for( SEGMENT *ss : line.LinkedSegments() )
1129  toErase.insert( ss );
1130 
1131  removedCount++;
1132  }
1133  }
1134 
1135  wxLogTrace( "PNS", "total segs removed: %d/%d", removedCount, total );
1136  }
1137 
1138  for( SEGMENT *s : toErase )
1139  aNode->Remove( s );
1140 
1141  aNode->Remove( aLatest );
1142 }

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

Referenced by Move().

◆ rhMarkObstacles()

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

route step, mark obstacles mode

Definition at line 415 of file pns_line_placer.cpp.

416 {
417  LINE newHead( m_head ), bestHead( m_head );
418  bool hasBest = false;
419 
420  buildInitialLine( aP, newHead );
421 
422  NODE::OBSTACLES obstacles;
423 
424  m_currentNode->QueryColliding( &newHead, obstacles );
425 
426  for( auto& obs : obstacles )
427  {
428  int cl = m_currentNode->GetClearance( obs.m_item, &newHead );
429  auto hull = obs.m_item->Hull( cl, newHead.Width() );
430 
431  auto nearest = hull.NearestPoint( aP );
432  Dbg()->AddLine( hull, 2, 10000 );
433 
434  if( ( nearest - aP ).EuclideanNorm() < newHead.Width() + cl )
435  {
436  buildInitialLine( nearest, newHead );
437  if ( newHead.CLine().Length() > bestHead.CLine().Length() )
438  {
439  bestHead = newHead;
440  hasBest = true;
441  }
442  }
443  }
444 
445  if( hasBest )
446  m_head = bestHead;
447  else
448  m_head = newHead;
449 
450  aNewHead = m_head;
451 
452  return static_cast<bool>( m_currentNode->CheckColliding( &m_head ) );
453 }
double EuclideanNorm(const wxPoint &vector)
Euclidean norm of a 2D vector.
Definition: trigo.h:112
LINE m_head
routing "head": volatile part of the track from the previously analyzed point to the current routing ...
virtual void AddLine(const SHAPE_LINE_CHAIN &aLine, int aType=0, int aWidth=0)
int GetClearance(const ITEM *aA, const ITEM *aB) const
Returns the expected clearance between items a and b.
Definition: pns_node.cpp:98
bool buildInitialLine(const VECTOR2I &aP, LINE &aHead, bool aInvertPosture=false)
DEBUG_DECORATOR * Dbg() const
Definition: pns_algo_base.h:70
NODE * m_currentNode
Current world state
OPT_OBSTACLE CheckColliding(const ITEM *aItem, int aKindMask=ITEM::ANY_T)
Function CheckColliding()
Definition: pns_node.cpp:425
std::vector< OBSTACLE > OBSTACLES
Definition: pns_node.h:141
int QueryColliding(const ITEM *aItem, OBSTACLES &aObstacles, int aKindMask=ITEM::ANY_T, int aLimitCount=-1, bool aDifferentNetsOnly=true, int aForceClearance=-1)
Function QueryColliding()
Definition: pns_node.cpp:276

References PNS::DEBUG_DECORATOR::AddLine(), buildInitialLine(), PNS::NODE::CheckColliding(), PNS::LINE::CLine(), PNS::ALGO_BASE::Dbg(), EuclideanNorm(), PNS::NODE::GetClearance(), SHAPE_LINE_CHAIN::Length(), m_currentNode, m_head, and PNS::NODE::QueryColliding().

Referenced by routeHead().

◆ rhShoveOnly()

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

route step, shove mode

Definition at line 555 of file pns_line_placer.cpp.

556 {
557  LINE initTrack( m_head );
558  LINE walkSolids, l2;
559 
560  bool viaOk = buildInitialLine( aP, initTrack );
561 
562  m_currentNode = m_shove->CurrentNode();
563  OPTIMIZER optimizer( m_currentNode );
564 
565  WALKAROUND walkaround( m_currentNode, Router() );
566 
567  walkaround.SetSolidsOnly( true );
568  walkaround.SetIterationLimit( 10 );
569  walkaround.SetDebugDecorator( Dbg() );
570  WALKAROUND::WALKAROUND_STATUS stat_solids = walkaround.Route( initTrack, walkSolids );
571 
572  optimizer.SetEffortLevel( OPTIMIZER::MERGE_SEGMENTS );
573  optimizer.SetCollisionMask( ITEM::SOLID_T );
574  optimizer.Optimize( &walkSolids );
575 
576  if( stat_solids == WALKAROUND::DONE )
577  l2 = walkSolids;
578  else
579  l2 = initTrack.ClipToNearestObstacle( m_shove->CurrentNode() );
580 
581  LINE l( m_tail );
582  l.Line().Append( l2.CLine() );
583  l.Line().Simplify();
584 
585  if( l.PointCount() == 0 || l2.PointCount() == 0 )
586  {
587  aNewHead = m_head;
588  return false;
589  }
590 
591  if( m_placingVia && viaOk )
592  {
593  VIA v1( makeVia( l.CPoint( -1 ) ) );
594  VIA v2( makeVia( l2.CPoint( -1 ) ) );
595 
596  l.AppendVia( v1 );
597  l2.AppendVia( v2 );
598  }
599 
600  l.Line().Simplify();
601 
602  // in certain, uncommon cases there may be loops in the head+tail, In such case, we don't shove to avoid
603  // screwing up the database.
604  if( l.HasLoops() )
605  {
606  aNewHead = m_head;
607  return false;
608  }
609 
610  SHOVE::SHOVE_STATUS status = m_shove->ShoveLines( l );
611 
612  m_currentNode = m_shove->CurrentNode();
613 
614  if( status == SHOVE::SH_OK || status == SHOVE::SH_HEAD_MODIFIED )
615  {
616  if( status == SHOVE::SH_HEAD_MODIFIED )
617  {
618  l2 = m_shove->NewHead();
619  }
620 
621  optimizer.SetWorld( m_currentNode );
622  optimizer.SetEffortLevel( OPTIMIZER::MERGE_OBTUSE | OPTIMIZER::SMART_PADS );
623  optimizer.SetCollisionMask( ITEM::ANY_T );
624  optimizer.Optimize( &l2 );
625 
626  aNewHead = l2;
627 
628  return true;
629  }
630  else
631  {
632  walkaround.SetWorld( m_currentNode );
633  walkaround.SetSolidsOnly( false );
634  walkaround.SetIterationLimit( 10 );
635  walkaround.SetApproachCursor( true, aP );
636  walkaround.Route( initTrack, l2 );
637  aNewHead = l2.ClipToNearestObstacle( m_shove->CurrentNode() );
638 
639  return false;
640  }
641 
642  return false;
643 }
ROUTER * Router() const
Returns the instance of our router
Definition: pns_algo_base.h:49
LINE m_head
routing "head": volatile part of the track from the previously analyzed point to the current routing ...
LINE m_tail
routing "tail": part of the track that has been already fixed due to collisions with obstacles
bool buildInitialLine(const VECTOR2I &aP, LINE &aHead, bool aInvertPosture=false)
DEBUG_DECORATOR * Dbg() const
Definition: pns_algo_base.h:70
std::unique_ptr< SHOVE > m_shove
The shove engine
NODE * m_currentNode
Current world state
bool m_placingVia
Are we placing a via?
const VIA makeVia(const VECTOR2I &aP)

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::LINE::Line(), m_currentNode, m_head, m_placingVia, m_shove, m_tail, makeVia(), PNS::OPTIMIZER::MERGE_OBTUSE, PNS::OPTIMIZER::MERGE_SEGMENTS, PNS::OPTIMIZER::Optimize(), PNS::LINE::PointCount(), PNS::WALKAROUND::Route(), PNS::ALGO_BASE::Router(), PNS::WALKAROUND::SetApproachCursor(), PNS::OPTIMIZER::SetCollisionMask(), PNS::ALGO_BASE::SetDebugDecorator(), PNS::OPTIMIZER::SetEffortLevel(), PNS::WALKAROUND::SetIterationLimit(), PNS::WALKAROUND::SetSolidsOnly(), PNS::WALKAROUND::SetWorld(), PNS::OPTIMIZER::SetWorld(), PNS::SHOVE::SH_HEAD_MODIFIED, PNS::SHOVE::SH_OK, SHAPE_LINE_CHAIN::Simplify(), PNS::OPTIMIZER::SMART_PADS, and PNS::ITEM::SOLID_T.

Referenced by routeHead().

◆ rhStopAtNearestObstacle()

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

Definition at line 503 of file pns_line_placer.cpp.

504 {
505  LINE l0;
506  l0 = m_head;
507 
508  buildInitialLine( aP, l0 );
509 
510  LINE l_cur = reduceToNearestObstacle( l0 );
511 
512  const auto l_shape = l_cur.CLine();
513 
514  if( l_shape.SegmentCount() == 0 )
515  {
516  return false;
517  }
518 
519  if( l_shape.SegmentCount() == 1 )
520  {
521  auto s = l_shape.CSegment( 0 );
522 
523  VECTOR2I dL( DIRECTION_45( s ).Left().ToVector() );
524  VECTOR2I dR( DIRECTION_45( s ).Right().ToVector() );
525 
526  SEG leadL( s.B, s.B + dL );
527  SEG leadR( s.B, s.B + dR );
528 
529  SEG segL( s.B, leadL.LineProject( aP ) );
530  SEG segR( s.B, leadR.LineProject( aP ) );
531 
532  LINE finishL( l0, SHAPE_LINE_CHAIN( segL.A, segL.B ) );
533  LINE finishR( l0, SHAPE_LINE_CHAIN( segR.A, segR.B ) );
534 
535  LINE reducedL = reduceToNearestObstacle( finishL );
536  LINE reducedR = reduceToNearestObstacle( finishR );
537 
538  int lL = reducedL.CLine().Length();
539  int lR = reducedR.CLine().Length();
540 
541  if( lL > lR )
542  l_cur.Line().Append( reducedL.CLine() );
543  else
544  l_cur.Line().Append( reducedR.CLine() );
545 
546  l_cur.Line().Simplify();
547  }
548 
549  m_head = l_cur;
550  aNewHead = m_head;
551  return true;
552 }
const LINE reduceToNearestObstacle(const LINE &aOriginalLine)
LINE m_head
routing "head": volatile part of the track from the previously analyzed point to the current routing ...
Class DIRECTION_45.
Definition: direction45.h:36
bool buildInitialLine(const VECTOR2I &aP, LINE &aHead, bool aInvertPosture=false)
Definition: seg.h:36
Class SHAPE_LINE_CHAIN.

References SHAPE_LINE_CHAIN::Append(), buildInitialLine(), PNS::LINE::CLine(), SHAPE_LINE_CHAIN::CSegment(), PCAD2KICAD::Left, SHAPE_LINE_CHAIN::Length(), PNS::LINE::Line(), SEG::LineProject(), m_head, reduceToNearestObstacle(), PCAD2KICAD::Right, and SHAPE_LINE_CHAIN::Simplify().

◆ rhWalkOnly()

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

route step, walkaround mode

Definition at line 358 of file pns_line_placer.cpp.

359 {
360  LINE initTrack( m_head );
361  LINE walkFull;
362  int effort = 0;
363  bool rv = true, viaOk;
364 
365  viaOk = buildInitialLine( aP, initTrack );
366 
367  WALKAROUND walkaround( m_currentNode, Router() );
368 
369  walkaround.SetSolidsOnly( false );
370  walkaround.SetDebugDecorator( Dbg() );
371  walkaround.SetIterationLimit( Settings().WalkaroundIterationLimit() );
372 
373  WALKAROUND::WALKAROUND_STATUS wf = walkaround.Route( initTrack, walkFull, false );
374 
375  switch( Settings().OptimizerEffort() )
376  {
377  case OE_LOW:
378  effort = 0;
379  break;
380 
381  case OE_MEDIUM:
382  case OE_FULL:
383  effort = OPTIMIZER::MERGE_SEGMENTS;
384  break;
385  }
386 
387  if( Settings().SmartPads() )
388  effort |= OPTIMIZER::SMART_PADS;
389 
390  if( wf == WALKAROUND::STUCK )
391  {
392  walkFull = walkFull.ClipToNearestObstacle( m_currentNode );
393  rv = true;
394  }
395  else if( m_placingVia && viaOk )
396  {
397  walkFull.AppendVia( makeVia( walkFull.CPoint( -1 ) ) );
398  }
399 
400  OPTIMIZER::Optimize( &walkFull, effort, m_currentNode );
401 
402  if( m_currentNode->CheckColliding( &walkFull ) )
403  {
404  aNewHead = m_head;
405  return false;
406  }
407 
408  m_head = walkFull;
409  aNewHead = walkFull;
410 
411  return rv;
412 }
ROUTER * Router() const
Returns the instance of our router
Definition: pns_algo_base.h:49
LINE m_head
routing "head": volatile part of the track from the previously analyzed point to the current routing ...
ROUTING_SETTINGS & Settings() const
Returns current router settings
bool buildInitialLine(const VECTOR2I &aP, LINE &aHead, bool aInvertPosture=false)
DEBUG_DECORATOR * Dbg() const
Definition: pns_algo_base.h:70
NODE * m_currentNode
Current world state
bool m_placingVia
Are we placing a via?
OPT_OBSTACLE CheckColliding(const ITEM *aItem, int aKindMask=ITEM::ANY_T)
Function CheckColliding()
Definition: pns_node.cpp:425
static bool Optimize(LINE *aLine, int aEffortLevel, NODE *aWorld)
a quick shortcut to optmize a line without creating and setting up an optimizer
const VIA makeVia(const VECTOR2I &aP)

References PNS::LINE::AppendVia(), buildInitialLine(), PNS::NODE::CheckColliding(), PNS::LINE::ClipToNearestObstacle(), PNS::LINE::CPoint(), PNS::ALGO_BASE::Dbg(), m_currentNode, m_head, m_placingVia, makeVia(), PNS::OPTIMIZER::MERGE_SEGMENTS, PNS::OE_FULL, PNS::OE_LOW, PNS::OE_MEDIUM, PNS::OPTIMIZER::Optimize(), PNS::WALKAROUND::Route(), PNS::ALGO_BASE::Router(), PNS::ALGO_BASE::SetDebugDecorator(), PNS::WALKAROUND::SetIterationLimit(), PNS::WALKAROUND::SetSolidsOnly(), PNS::ALGO_BASE::Settings(), PNS::OPTIMIZER::SMART_PADS, and PNS::WALKAROUND::STUCK.

Referenced by routeHead().

◆ route()

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

Function route()

Re-routes 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 780 of file pns_line_placer.cpp.

781 {
782  routeStep( aP );
783 
784  if (!m_head.PointCount() )
785  {
786  return false;
787  }
788  else
789  {
790  return m_head.CPoint(-1) == aP;
791  }
792 }
void routeStep(const VECTOR2I &aP)
Function routeStep()
LINE m_head
routing "head": volatile part of the track from the previously analyzed point to the current routing ...
int PointCount() const
Returns the number of points in the line
Definition: pns_line.h:135
const VECTOR2I & CPoint(int aIdx) const
Returns the aIdx-th point of the line
Definition: pns_line.h:141

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

Function routeHead()

Computes 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 646 of file pns_line_placer.cpp.

647 {
648  switch( m_currentMode )
649  {
650  case RM_MarkObstacles:
651  return rhMarkObstacles( aP, aNewHead );
652  case RM_Walkaround:
653  return rhWalkOnly( aP, aNewHead );
654  case RM_Shove:
655  return rhShoveOnly( aP, aNewHead );
656  default:
657  break;
658  }
659 
660  return false;
661 }
Ignore collisions, mark obstacles
bool rhWalkOnly(const VECTOR2I &aP, LINE &aNewHead)
route step, walkaround mode
bool rhMarkObstacles(const VECTOR2I &aP, LINE &aNewHead)
route step, mark obstacles mode
bool rhShoveOnly(const VECTOR2I &aP, LINE &aNewHead)
route step, shove mode

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

Referenced by routeStep().

◆ Router()

◆ routeStep()

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

Function routeStep()

Performs a single routing alorithm step, for the end point aP.

Parameters
aPending point of current route
Returns
true, if the line has been changed.

Definition at line 727 of file pns_line_placer.cpp.

728 {
729  bool fail = false;
730  bool go_back = false;
731 
732  int i, n_iter = 1;
733 
734  LINE new_head;
735 
736  wxLogTrace( "PNS", "INIT-DIR: %s head: %d, tail: %d segs",
738 
739  for( i = 0; i < n_iter; i++ )
740  {
741  if( !go_back && Settings().FollowMouse() )
742  reduceTail( aP );
743 
744  go_back = false;
745 
746  if( !routeHead( aP, new_head ) )
747  fail = true;
748 
749  if( !new_head.Is45Degree() )
750  fail = true;
751 
752  if( !Settings().FollowMouse() )
753  return;
754 
755  m_head = new_head;
756 
758  {
759  n_iter++;
760  go_back = true;
761  }
762 
763  if( !go_back && handlePullback() )
764  {
765  n_iter++;
766  go_back = true;
767  }
768  }
769 
770  if( !fail )
771  {
773  return;
774 
775  mergeHead();
776  }
777 }
int SegmentCount() const
Returns the number of segments in the line
Definition: pns_line.h:129
const std::string Format() const
Function Format() Formats the direction in a human readable word.
Definition: direction45.h:97
LINE m_head
routing "head": volatile part of the track from the previously analyzed point to the current routing ...
bool reduceTail(const VECTOR2I &aEnd)
Function reduceTail()
bool handlePullback()
Function handlePullback()
bool FollowMouse() const
Returns true if follow mouse mode is active (permanently on for the moment).
ROUTING_SETTINGS & Settings() const
Returns current router settings
DIRECTION_45 m_initial_direction
routing direction for new traces
LINE m_tail
routing "tail": part of the track that has been already fixed due to collisions with obstacles
bool routeHead(const VECTOR2I &aP, LINE &aNewHead)
Function routeHead()
bool handleSelfIntersections()
Function handleSelfIntersections()
bool optimizeTailHeadTransition()
Function optimizeTailHeadTransition()
size_t i
Definition: json11.cpp:597
bool mergeHead()
Function mergeHead()

References PNS::ROUTING_SETTINGS::FollowMouse(), DIRECTION_45::Format(), handlePullback(), handleSelfIntersections(), i, PNS::LINE::Is45Degree(), m_head, m_initial_direction, m_tail, mergeHead(), optimizeTailHeadTransition(), reduceTail(), routeHead(), PNS::LINE::SegmentCount(), and PNS::ALGO_BASE::Settings().

Referenced by route().

◆ SetDebugDecorator()

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

Function SetDebugDecorator.

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

Definition at line 65 of file pns_algo_base.h.

66  {
67  m_debugDecorator = aDecorator;
68  }
DEBUG_DECORATOR * m_debugDecorator
Definition: pns_algo_base.h:76

References PNS::ALGO_BASE::m_debugDecorator.

Referenced by rhShoveOnly(), and rhWalkOnly().

◆ setInitialDirection()

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

Function setInitialDirection()

Sets preferred direction of the very first track segment to be laid. Used by posture switching mechanism.

Definition at line 88 of file pns_line_placer.cpp.

89 {
90  m_initial_direction = aDirection;
91 
92  if( m_tail.SegmentCount() == 0 )
93  m_direction = aDirection;
94 }
int SegmentCount() const
Returns the number of segments in the line
Definition: pns_line.h:129
DIRECTION_45 m_initial_direction
routing direction for new traces
LINE m_tail
routing "tail": part of the track that has been already fixed due to collisions with obstacles
DIRECTION_45 m_direction
current routing direction

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

Function SetLayer()

Sets the current routing layer.

Reimplemented from PNS::PLACEMENT_ALGO.

Definition at line 860 of file pns_line_placer.cpp.

861 {
862  if( m_idle )
863  {
864  m_currentLayer = aLayer;
865  return true;
866  }
867  else if( m_chainedPlacement )
868  {
869  return false;
870  }
871  else if( !m_startItem || ( m_startItem->OfKind( ITEM::VIA_T ) && m_startItem->Layers().Overlaps( aLayer ) ) )
872  {
873  m_currentLayer = aLayer;
874  initPlacement();
875  Move( m_currentEnd, NULL );
876  return true;
877  }
878 
879  return false;
880 }
bool Move(const VECTOR2I &aP, ITEM *aEndItem) override
Function Move()
bool Overlaps(const LAYER_RANGE &aOther) const
Definition: pns_layerset.h:68
void initPlacement()
Function startPlacement()
bool OfKind(int aKindMask) const
Function OfKind()
Definition: pns_item.h:132
const LAYER_RANGE & Layers() const
Function Layers()
Definition: pns_item.h:214

References initPlacement(), PNS::ITEM::Layers(), m_chainedPlacement, m_currentEnd, m_currentLayer, m_idle, m_startItem, Move(), PNS::ITEM::OfKind(), LAYER_RANGE::Overlaps(), and PNS::ITEM::VIA_T.

◆ 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 1183 of file pns_line_placer.cpp.

1184 {
1185  m_orthoMode = aOrthoMode;
1186 }

References m_orthoMode.

◆ Settings()

◆ setWorld()

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

Function setWorld()

Sets the board to route.

Definition at line 63 of file pns_line_placer.cpp.

64 {
65  m_world = aWorld;
66 }
NODE * m_world
pointer to world to search colliding items

References m_world.

Referenced by initPlacement().

◆ simplifyNewLine()

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

Function simplifyNewLine()

Assembles a line starting from segment aLatest, removes collinear segments and redundant vertexes. If a simplification bhas been found, replaces the old line with the simplified one in aNode.

Definition at line 1145 of file pns_line_placer.cpp.

1146 {
1147  LINE l = aNode->AssembleLine( aLatest );
1148  SHAPE_LINE_CHAIN simplified( l.CLine() );
1149 
1150  simplified.Simplify();
1151 
1152  if( simplified.PointCount() != l.PointCount() )
1153  {
1154  aNode->Remove( l );
1155  l.SetShape( simplified );
1156  aNode->Add( l );
1157  }
1158 }
SHAPE_LINE_CHAIN & Simplify()
Function Simplify()
void Remove(int aStartIndex, int aEndIndex)
Function Remove()
Class SHAPE_LINE_CHAIN.

References PNS::NODE::Add(), PNS::NODE::AssembleLine(), PNS::LINE::CLine(), PNS::LINE::PointCount(), PNS::NODE::Remove(), PNS::LINE::SetShape(), and SHAPE_LINE_CHAIN::Simplify().

Referenced by FixRoute().

◆ SplitAdjacentSegments()

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

Function SplitAdjacentSegments()

Checks 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 829 of file pns_line_placer.cpp.

830 {
831  if( !aSeg )
832  return false;
833 
834  if( !aSeg->OfKind( ITEM::SEGMENT_T ) )
835  return false;
836 
837  JOINT* jt = aNode->FindJoint( aP, aSeg );
838 
839  if( jt && jt->LinkCount() >= 1 )
840  return false;
841 
842  SEGMENT* s_old = static_cast<SEGMENT*>( aSeg );
843 
844  std::unique_ptr< SEGMENT > s_new[2] = {
845  Clone( *s_old ),
846  Clone( *s_old )
847  };
848 
849  s_new[0]->SetEnds( s_old->Seg().A, aP );
850  s_new[1]->SetEnds( aP, s_old->Seg().B );
851 
852  aNode->Remove( s_old );
853  aNode->Add( std::move( s_new[0] ), true );
854  aNode->Add( std::move( s_new[1] ), true );
855 
856  return true;
857 }
std::unique_ptr< typename std::remove_const< T >::type > Clone(const T &aItem)
Definition: pns_item.h:385

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

Function Start()

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

Implements PNS::PLACEMENT_ALGO.

Definition at line 883 of file pns_line_placer.cpp.

884 {
885  m_currentStart = VECTOR2I( aP );
886  m_currentEnd = VECTOR2I( aP );
887  m_currentNet = std::max( 0, aStartItem ? aStartItem->Net() : 0 );
888  m_startItem = aStartItem;
889  m_placingVia = false;
890  m_chainedPlacement = false;
891 
892  setInitialDirection( Settings().InitialDirection() );
893 
894  initPlacement();
895  return true;
896 }
VECTOR2< int > VECTOR2I
Definition: vector2d.h:587
ROUTING_SETTINGS & Settings() const
Returns current router settings
void setInitialDirection(const DIRECTION_45 &aDirection)
Function setInitialDirection()
void initPlacement()
Function startPlacement()
#define max(a, b)
Definition: auxiliary.h:86
bool m_placingVia
Are we placing a via?

References initPlacement(), m_chainedPlacement, m_currentEnd, m_currentNet, m_currentStart, m_placingVia, m_startItem, max, PNS::ITEM::Net(), setInitialDirection(), and PNS::ALGO_BASE::Settings().

◆ Tail()

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

Function Tail()

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

Definition at line 114 of file pns_line_placer.h.

114 { return m_tail; }
LINE m_tail
routing "tail": part of the track that has been already fixed due to collisions with obstacles

References m_tail.

◆ ToggleVia()

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

Function ToggleVia()

Enables/disables a via at the end of currently routed trace.

Reimplemented from PNS::PLACEMENT_ALGO.

Definition at line 77 of file pns_line_placer.cpp.

78 {
79  m_placingVia = aEnabled;
80 
81  if( !aEnabled )
82  m_head.RemoveVia();
83 
84  return true;
85 }
LINE m_head
routing "head": volatile part of the track from the previously analyzed point to the current routing ...
void RemoveVia()
Definition: pns_line.h:251
bool m_placingVia
Are we placing a via?

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

◆ Trace()

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

Function Trace()

Returns the complete routed line.

Definition at line 795 of file pns_line_placer.cpp.

796 {
797  LINE tmp( m_head );
798 
799  tmp.SetShape( m_tail.CLine() );
800  tmp.Line().Append( m_head.CLine() );
801  tmp.Line().Simplify();
802  return tmp;
803 }
const SHAPE_LINE_CHAIN & CLine() const
Const accessor to the underlying shape
Definition: pns_line.h:123
LINE m_head
routing "head": volatile part of the track from the previously analyzed point to the current routing ...
LINE m_tail
routing "tail": part of the track that has been already fixed due to collisions with obstacles

References SHAPE_LINE_CHAIN::Append(), PNS::LINE::CLine(), PNS::LINE::Line(), m_head, m_tail, 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

Function Traces()

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

Implements PNS::PLACEMENT_ALGO.

Definition at line 806 of file pns_line_placer.cpp.

807 {
808  m_currentTrace = Trace();
809  return ITEM_SET( &m_currentTrace );
810 }
const LINE Trace() const
Function Trace()

References m_currentTrace, and Trace().

◆ updateLeadingRatLine()

void PNS::LINE_PLACER::updateLeadingRatLine ( )
private

Function updateLeadingRatLine()

Draws the "leading" ratsnest 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 1172 of file pns_line_placer.cpp.

1173 {
1174  LINE current = Trace();
1175  SHAPE_LINE_CHAIN ratLine;
1176  TOPOLOGY topo( m_lastNode );
1177 
1178  if( topo.LeadingRatLine( &current, ratLine ) )
1179  Dbg()->AddLine( ratLine, 5, 10000 );
1180 }
NODE * m_lastNode
Postprocessed world state (including marked collisions & removed loops)
const LINE Trace() const
Function Trace()
virtual void AddLine(const SHAPE_LINE_CHAIN &aLine, int aType=0, int aWidth=0)
DEBUG_DECORATOR * Dbg() const
Definition: pns_algo_base.h:70
Class SHAPE_LINE_CHAIN.

References PNS::DEBUG_DECORATOR::AddLine(), PNS::ALGO_BASE::Dbg(), PNS::TOPOLOGY::LeadingRatLine(), m_lastNode, and Trace().

Referenced by Move().

◆ UpdateSizes()

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

Function UpdateSizes()

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 1161 of file pns_line_placer.cpp.

1162 {
1163  m_sizes = aSizes;
1164 
1165  if( !m_idle )
1166  {
1167  initPlacement();
1168  }
1169 }
SIZES_SETTINGS m_sizes
void initPlacement()
Function startPlacement()

References initPlacement(), m_idle, and m_sizes.

Member Data Documentation

◆ m_chainedPlacement

bool PNS::LINE_PLACER::m_chainedPlacement
private

Definition at line 399 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 392 of file pns_line_placer.h.

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

◆ m_currentLayer

int PNS::LINE_PLACER::m_currentLayer
private

Definition at line 390 of file pns_line_placer.h.

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

◆ m_currentMode

PNS_MODE PNS::LINE_PLACER::m_currentMode
private

Definition at line 395 of file pns_line_placer.h.

Referenced by buildInitialLine(), FixRoute(), initPlacement(), LINE_PLACER(), and routeHead().

◆ m_currentNet

int PNS::LINE_PLACER::m_currentNet
private

◆ m_currentNode

◆ m_currentStart

VECTOR2I PNS::LINE_PLACER::m_currentStart
private

Definition at line 392 of file pns_line_placer.h.

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

◆ m_currentTrace

LINE PNS::LINE_PLACER::m_currentTrace
private

Definition at line 393 of file pns_line_placer.h.

Referenced by Traces().

◆ m_direction

DIRECTION_45 PNS::LINE_PLACER::m_direction
private

◆ m_head

LINE PNS::LINE_PLACER::m_head
private

routing "head": volatile part of the track from the previously

analyzed point to the current routing destination

Definition at line 364 of file pns_line_placer.h.

Referenced by handlePullback(), handleSelfIntersections(), Head(), initPlacement(), mergeHead(), optimizeTailHeadTransition(), reduceTail(), rhMarkObstacles(), rhShoveOnly(), rhStopAtNearestObstacle(), rhWalkOnly(), route(), routeStep(), ToggleVia(), and Trace().

◆ m_idle

bool PNS::LINE_PLACER::m_idle
private

Definition at line 398 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

routing direction for new traces

Definition at line 360 of file pns_line_placer.h.

Referenced by FlipPosture(), handlePullback(), handleSelfIntersections(), initPlacement(), LINE_PLACER(), reduceTail(), routeStep(), and setInitialDirection().

◆ m_lastNode

NODE* PNS::LINE_PLACER::m_lastNode
private

Postprocessed world state (including marked collisions & removed loops)

Definition at line 382 of file pns_line_placer.h.

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

◆ m_orthoMode

bool PNS::LINE_PLACER::m_orthoMode
private

Definition at line 400 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 point (end of tail, beginning of head)

Definition at line 373 of file pns_line_placer.h.

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

◆ m_placingVia

bool PNS::LINE_PLACER::m_placingVia
private

Are we placing a via?

Definition at line 387 of file pns_line_placer.h.

Referenced by buildInitialLine(), FixRoute(), IsPlacingVia(), LINE_PLACER(), rhShoveOnly(), rhWalkOnly(), Start(), and ToggleVia().

◆ m_shove

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

The shove engine

Definition at line 376 of file pns_line_placer.h.

Referenced by initPlacement(), LINE_PLACER(), Logger(), and rhShoveOnly().

◆ m_sizes

SIZES_SETTINGS PNS::LINE_PLACER::m_sizes
private

Definition at line 384 of file pns_line_placer.h.

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

◆ m_startItem

ITEM* PNS::LINE_PLACER::m_startItem
private

Definition at line 396 of file pns_line_placer.h.

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

◆ 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 367 of file pns_line_placer.h.

Referenced by handlePullback(), handleSelfIntersections(), initPlacement(), mergeHead(), optimizeTailHeadTransition(), reduceTail(), rhShoveOnly(), routeStep(), setInitialDirection(), Tail(), and Trace().

◆ m_world

NODE* PNS::LINE_PLACER::m_world
private

pointer to world to search colliding items

Definition at line 370 of file pns_line_placer.h.

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


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