KiCad PCB EDA Suite
pns_dragger.cpp
Go to the documentation of this file.
1 /*
2  * KiRouter - a push-and-(sometimes-)shove PCB router
3  *
4  * Copyright (C) 2013-2014 CERN
5  * Copyright (C) 2016 KiCad Developers, see AUTHORS.txt for contributors.
6  * Author: Tomasz Wlostowski <tomasz.wlostowski@cern.ch>
7  *
8  * This program is free software: you can redistribute it and/or modify it
9  * under the terms of the GNU General Public License as published by the
10  * Free Software Foundation, either version 3 of the License, or (at your
11  * option) any later version.
12  *
13  * This program is distributed in the hope that it will be useful, but
14  * WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16  * General Public License for more details.
17  *
18  * You should have received a copy of the GNU General Public License along
19  * with this program. If not, see <http://www.gnu.org/licenses/>.
20  */
21 
22 #include "pns_dragger.h"
23 #include "pns_shove.h"
24 #include "pns_router.h"
25 
26 namespace PNS {
27 
28 DRAGGER::DRAGGER( ROUTER* aRouter ) :
29  ALGO_BASE( aRouter )
30 {
31  m_world = NULL;
32  m_lastNode = NULL;
34  m_draggedVia = NULL;
35  m_shove = NULL;
37  m_dragStatus = false;
39  m_initialVia = NULL;
40 }
41 
42 
44 {
45  if( m_shove )
46  delete m_shove;
47 }
48 
49 
50 void DRAGGER::SetWorld( NODE* aWorld )
51 {
52  m_world = aWorld;
53 }
54 
55 
56 bool DRAGGER::startDragSegment( const VECTOR2D& aP, SEGMENT* aSeg )
57 {
58  int w2 = aSeg->Width() / 2;
59 
64 
65  if( ( aP - aSeg->Seg().A ).EuclideanNorm() <= w2 )
67  else if( ( aP - aSeg->Seg().B ).EuclideanNorm() <= w2 )
68  {
71  } else
73 
74  return true;
75 }
76 
77 
78 bool DRAGGER::startDragVia( const VECTOR2D& aP, VIA* aVia )
79 {
80  m_draggedVia = aVia;
81  m_initialVia = aVia;
82  m_mode = DRAG_VIA;
83 
84  VECTOR2I p0( aVia->Pos() );
85  JOINT* jt = m_world->FindJoint( p0, aVia->Layers().Start(), aVia->Net() );
86 
87  if( !jt )
88  return false;
89 
90  for( ITEM* item : jt->LinkList() )
91  {
92  if( item->OfKind( ITEM::SEGMENT_T ) )
93  {
94  int segIndex;
95  SEGMENT* seg = ( SEGMENT*) item;
96  LINE l = m_world->AssembleLine( seg, &segIndex );
97 
98  if( segIndex != 0 )
99  l.Reverse();
100 
102  }
103  }
104 
105  return true;
106 }
107 
108 
109 bool DRAGGER::Start( const VECTOR2I& aP, ITEM* aStartItem )
110 {
111  m_shove = new SHOVE( m_world, Router() );
112  m_lastNode = NULL;
115 
116  aStartItem->Unmark( MK_LOCKED );
117 
118  wxLogTrace( "PNS", "StartDragging: item %p [kind %d]", aStartItem, (int) aStartItem->Kind() );
119 
120  switch( aStartItem->Kind() )
121  {
122  case ITEM::SEGMENT_T:
123  return startDragSegment( aP, static_cast<SEGMENT*>( aStartItem ) );
124 
125  case ITEM::VIA_T:
126  return startDragVia( aP, static_cast<VIA*>( aStartItem ) );
127 
128  default:
129  return false;
130  }
131 }
132 
133 
135 {
136  if( m_lastNode )
137  {
138  delete m_lastNode;
139  m_lastNode = NULL;
140  }
141 
142  switch( m_mode )
143  {
144  case DRAG_SEGMENT:
145  case DRAG_CORNER:
146  {
147  int thresh = Settings().SmoothDraggedSegments() ? m_draggedLine.Width() / 4 : 0;
148  LINE dragged( m_draggedLine );
149 
150  if( m_mode == DRAG_SEGMENT )
151  dragged.DragSegment( aP, m_draggedSegmentIndex, thresh );
152  else
153  dragged.DragCorner( aP, m_draggedSegmentIndex, thresh );
154 
156 
157  m_lastValidDraggedLine = dragged;
160 
164 
165  break;
166  }
167 
168  case DRAG_VIA: // fixme...
169  {
172 
173  break;
174  }
175  }
176 
177  if( Settings().CanViolateDRC() )
178  m_dragStatus = true;
179  else
181 
182  return true;
183 }
184 
185 
186 void DRAGGER::dumbDragVia( VIA* aVia, NODE* aNode, const VECTOR2I& aP )
187 {
189 
190  // fixme: this is awful.
191  auto via_clone = Clone( *aVia );
192 
193  m_draggedVia = via_clone.get();
194  m_draggedVia->SetPos( aP );
195 
197 
198  m_lastNode->Remove( aVia );
199  m_lastNode->Add( std::move( via_clone ) );
200 
201  for( ITEM* item : m_origViaConnections.Items() )
202  {
203  if( const LINE* l = dyn_cast<const LINE*>( item ) )
204  {
205  LINE origLine( *l );
206  LINE draggedLine( *l );
207 
208  draggedLine.DragCorner( aP, origLine.CLine().Find( aVia->Pos() ) );
209  draggedLine.ClearSegmentLinks();
210 
211  m_draggedItems.Add( draggedLine );
212 
213  m_lastNode->Remove( origLine );
214  m_lastNode->Add( draggedLine );
215  }
216  }
217 }
218 
219 
220 bool DRAGGER::dragShove( const VECTOR2I& aP )
221 {
222  bool ok = false;
223 
224  if( m_lastNode )
225  {
226  delete m_lastNode;
227  m_lastNode = NULL;
228  }
229 
230  switch( m_mode )
231  {
232  case DRAG_SEGMENT:
233  case DRAG_CORNER:
234  {
235  int thresh = Settings().SmoothDraggedSegments() ? m_draggedLine.Width() / 4 : 0;
236  LINE dragged( m_draggedLine );
237 
238  if( m_mode == DRAG_SEGMENT )
239  dragged.DragSegment( aP, m_draggedSegmentIndex, thresh );
240  else
241  dragged.DragCorner( aP, m_draggedSegmentIndex, thresh );
242 
243  SHOVE::SHOVE_STATUS st = m_shove->ShoveLines( dragged );
244 
245  if( st == SHOVE::SH_OK )
246  ok = true;
247  else if( st == SHOVE::SH_HEAD_MODIFIED )
248  {
249  dragged = m_shove->NewHead();
250  ok = true;
251  }
252 
254 
255  if( ok )
256  m_lastValidDraggedLine = dragged;
257 
263 
264  break;
265  }
266 
267  case DRAG_VIA:
268  {
269  VIA* newVia;
271 
272  if( st == SHOVE::SH_OK || st == SHOVE::SH_HEAD_MODIFIED )
273  ok = true;
274 
276 
277  if( ok )
278  {
279  if( newVia )
280  m_draggedVia = newVia;
282  }
283 
284  break;
285  }
286  }
287 
288  m_dragStatus = ok;
289 
290  return ok;
291 }
292 
293 
295 {
296  if( m_dragStatus )
297  {
299  return true;
300  }
301 
302  return false;
303 }
304 
305 
306 bool DRAGGER::Drag( const VECTOR2I& aP )
307 {
308  switch( m_currentMode )
309  {
310  case RM_MarkObstacles:
311  return dragMarkObstacles( aP );
312 
313  case RM_Shove:
314  case RM_Walkaround:
315  case RM_Smart:
316  return dragShove( aP );
317 
318  default:
319  return false;
320  }
321 }
322 
323 
325 {
326  return m_lastNode;
327 }
328 
329 
331 {
332  return m_draggedItems;
333 }
334 
335 
337 {
338  if( m_shove )
339  return m_shove->Logger();
340 
341  return NULL;
342 }
343 
344 }
double EuclideanNorm(const wxPoint &vector)
Euclidean norm of a 2D vector.
Definition: trigo.h:104
const SHAPE_LINE_CHAIN & CLine() const
Const accessor to the underlying shape
Definition: pns_line.h:123
PNS_MODE Mode() const
Returns the routing mode.
Class ITEM.
Definition: pns_item.h:53
ITEM_SET m_draggedItems
Definition: pns_dragger.h:125
bool SmoothDraggedSegments() const
Returns true if smoothing segments durign dragging is enabled.
VECTOR2I & B
Definition: seg.h:52
VIA * m_initialVia
Definition: pns_dragger.h:124
virtual LOGGER * Logger() override
Returns the logger object, allowing to dump geometry to a file.
Class NODE.
Definition: pns_node.h:137
NODE * m_world
Definition: pns_dragger.h:113
const LAYER_RANGE & Layers() const
Function Layers()
Definition: pns_item.h:207
Class SHOVE.
Definition: pns_shove.h:46
DragMode m_mode
Definition: pns_dragger.h:115
DRAGGER(ROUTER *aRouter)
Definition: pns_dragger.cpp:28
const LINE AssembleLine(SEGMENT *aSeg, int *aOriginSegmentIndex=NULL, bool aStopAtLockedJoints=false)
Function AssembleLine()
Definition: pns_node.cpp:834
Ignore collisions, mark obstacles
Class ALGO_BASE.
Definition: pns_algo_base.h:39
ENTRIES & Items()
Definition: pns_itemset.h:137
bool m_dragStatus
Definition: pns_dragger.h:121
virtual void Unmark(int aMarker=-1)
Definition: pns_item.h:306
bool startDragSegment(const VECTOR2D &aP, SEGMENT *aSeg)
Definition: pns_dragger.cpp:56
LINE m_draggedLine
Definition: pns_dragger.h:116
ROUTING_SETTINGS & Settings() const
Returns current router settings
LINE m_lastValidDraggedLine
Definition: pns_dragger.h:118
const VECTOR2I & Pos() const
Definition: pns_via.h:88
void dumbDragVia(VIA *aVia, NODE *aNode, const VECTOR2I &aP)
int Width() const
Returns line width
Definition: pns_line.h:159
void Add(const LINE &aLine)
Definition: pns_itemset.cpp:32
NODE * Branch()
Function Branch()
Definition: pns_node.cpp:109
bool Drag(const VECTOR2I &aP)
Function Drag()
VIA * m_draggedVia
Definition: pns_dragger.h:117
void SetWorld(NODE *aWorld)
Function SetWorld()
Definition: pns_dragger.cpp:50
SHOVE_STATUS ShoveLines(const LINE &aCurrentHead)
Definition: pns_shove.cpp:1078
int Find(const VECTOR2I &aP) const
Function Find()
Class JOINT.
Definition: pns_joint.h:44
VECTOR2I & A
Definition: seg.h:51
void Reverse()
Reverses the point/vertex order
Definition: pns_line.cpp:699
const ITEM_SET Traces()
Function Traces()
SHOVE * m_shove
Definition: pns_dragger.h:119
bool startDragVia(const VECTOR2D &aP, VIA *aVia)
Definition: pns_dragger.cpp:78
int m_draggedSegmentIndex
Definition: pns_dragger.h:120
bool FixRoute()
Function FixRoute()
void DragCorner(const VECTOR2I &aP, int aIndex, int aSnappingThreshold=0)
Definition: pns_line.cpp:408
int Width() const
Definition: pns_segment.h:88
ITEM_SET m_origViaConnections
Definition: pns_dragger.h:123
bool Start(const VECTOR2I &aP, ITEM *aStartItem)
Function Start()
int Start() const
Definition: pns_layerset.h:83
ROUTER * Router() const
Returns the instance of our router
Definition: pns_algo_base.h:49
void Remove(SOLID *aSolid)
Function Remove()
Definition: pns_node.cpp:729
void DragSegment(const VECTOR2I &aP, int aIndex, int aSnappingThreshold=0)
Definition: pns_line.cpp:520
SHOVE_STATUS ShoveDraggingVia(VIA *aVia, const VECTOR2I &aWhere, VIA **aNewVia)
Definition: pns_shove.cpp:1262
JOINT * FindJoint(const VECTOR2I &aPos, int aLayer, int aNet)
Function FindJoint()
Definition: pns_node.cpp:968
NODE * m_lastNode
Definition: pns_dragger.h:114
const LINE NewHead() const
Definition: pns_shove.cpp:1399
PnsKind Kind() const
Function Kind()
Definition: pns_item.h:120
void SetPos(const VECTOR2I &aPos)
Definition: pns_via.h:93
std::unique_ptr< typename std::remove_const< T >::type > Clone(const T &aItem)
Definition: pns_item.h:367
Only walkaround
NODE * CurrentNode() const
Function CurrentNode()
void ClearSegmentLinks()
Erases the linking information. Used to detach the line from the owning node.
Definition: pns_line.cpp:784
bool dragShove(const VECTOR2I &aP)
PNS_MODE m_currentMode
Definition: pns_dragger.h:122
void CommitRouting(NODE *aNode)
Definition: pns_router.cpp:324
virtual LOGGER * Logger() override
Returns the logger object, allowing to dump geometry to a file.
Definition: pns_shove.h:62
OPT_OBSTACLE CheckColliding(const ITEM *aItem, int aKindMask=ITEM::ANY_T)
Function CheckColliding()
Definition: pns_node.cpp:427
int Net() const
Function Net()
Definition: pns_item.h:177
bool dragMarkObstacles(const VECTOR2I &aP)
void SetInitialLine(LINE &aInitial)
Definition: pns_shove.cpp:1407
const SEG & Seg() const
Definition: pns_segment.h:93
Push and Shove diff pair dimensions (gap) settings dialog.
void Add(std::unique_ptr< SEGMENT > aSegment, bool aAllowRedundant=false)
Function Add()
Definition: pns_node.cpp:596
virtual void Unmark(int aMarker=-1) override
Definition: pns_line.cpp:96
NODE * CurrentNode()
Definition: pns_shove.cpp:1393