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  auto distA = ( aP - aSeg->Seg().A ).EuclideanNorm();
66  auto distB = ( aP - aSeg->Seg().B ).EuclideanNorm();
67 
68 
69  if( distA <= w2 )
70  {
71  m_mode = DM_CORNER;
72  }
73  else if( distB <= w2 )
74  {
76  m_mode = DM_CORNER;
77  }
78  else if ( m_freeAngleMode )
79  {
80  if( distB < distA )
81  {
83  }
84  m_mode = DM_CORNER;
85  }
86  else
87  {
89  }
90 
91  return true;
92 }
93 
94 
95 bool DRAGGER::startDragVia( const VECTOR2D& aP, VIA* aVia )
96 {
97  m_draggedVia = aVia;
98  m_initialVia = aVia;
99  m_mode = DM_VIA;
100 
101  VECTOR2I p0( aVia->Pos() );
102  JOINT* jt = m_world->FindJoint( p0, aVia->Layers().Start(), aVia->Net() );
103 
104  if( !jt )
105  return false;
106 
107  for( ITEM* item : jt->LinkList() )
108  {
109  if( item->OfKind( ITEM::SEGMENT_T ) )
110  {
111  int segIndex;
112  SEGMENT* seg = ( SEGMENT*) item;
113  LINE l = m_world->AssembleLine( seg, &segIndex );
114 
115  if( segIndex != 0 )
116  l.Reverse();
117 
119  }
120  }
121 
122  return true;
123 }
124 
125 
126 bool DRAGGER::Start( const VECTOR2I& aP, ITEM* aStartItem )
127 {
128  m_shove = new SHOVE( m_world, Router() );
129  m_lastNode = NULL;
133 
134  aStartItem->Unmark( MK_LOCKED );
135 
136  wxLogTrace( "PNS", "StartDragging: item %p [kind %d]", aStartItem, (int) aStartItem->Kind() );
137 
138  switch( aStartItem->Kind() )
139  {
140  case ITEM::SEGMENT_T:
141  return startDragSegment( aP, static_cast<SEGMENT*>( aStartItem ) );
142 
143  case ITEM::VIA_T:
144  return startDragVia( aP, static_cast<VIA*>( aStartItem ) );
145 
146  default:
147  return false;
148  }
149 }
150 
151 void DRAGGER::SetMode( int aMode )
152 {
153  m_mode = aMode;
154 }
155 
157 {
158  if( m_lastNode )
159  {
160  delete m_lastNode;
161  m_lastNode = NULL;
162  }
163 
164  switch( m_mode )
165  {
166  case DM_SEGMENT:
167  case DM_CORNER:
168  {
169  int thresh = Settings().SmoothDraggedSegments() ? m_draggedLine.Width() / 4 : 0;
170  LINE dragged( m_draggedLine );
171 
172  if( m_mode == DM_SEGMENT )
173  dragged.DragSegment( aP, m_draggedSegmentIndex, thresh );
174  else
175  dragged.DragCorner( aP, m_draggedSegmentIndex, thresh, m_freeAngleMode );
176 
178 
179  m_lastValidDraggedLine = dragged;
182 
186 
187  break;
188  }
189 
190  case DM_VIA: // fixme...
191  {
194 
195  break;
196  }
197  }
198 
199  if( Settings().CanViolateDRC() )
200  m_dragStatus = true;
201  else
203 
204  return true;
205 }
206 
207 
208 void DRAGGER::dumbDragVia( VIA* aVia, NODE* aNode, const VECTOR2I& aP )
209 {
211 
212  // fixme: this is awful.
213  auto via_clone = Clone( *aVia );
214 
215  m_draggedVia = via_clone.get();
216  m_draggedVia->SetPos( aP );
217 
219 
220  m_lastNode->Remove( aVia );
221  m_lastNode->Add( std::move( via_clone ) );
222 
223  for( ITEM* item : m_origViaConnections.Items() )
224  {
225  if( const LINE* l = dyn_cast<const LINE*>( item ) )
226  {
227  LINE origLine( *l );
228  LINE draggedLine( *l );
229 
230  draggedLine.DragCorner( aP, origLine.CLine().Find( aVia->Pos() ), 0, m_freeAngleMode );
231  draggedLine.ClearSegmentLinks();
232 
233  m_draggedItems.Add( draggedLine );
234 
235  m_lastNode->Remove( origLine );
236  m_lastNode->Add( draggedLine );
237  }
238  }
239 }
240 
241 
242 bool DRAGGER::dragShove( const VECTOR2I& aP )
243 {
244  bool ok = false;
245 
246  if( m_lastNode )
247  {
248  delete m_lastNode;
249  m_lastNode = NULL;
250  }
251 
252  switch( m_mode )
253  {
254  case DM_SEGMENT:
255  case DM_CORNER:
256  {
257  int thresh = Settings().SmoothDraggedSegments() ? m_draggedLine.Width() / 4 : 0;
258  LINE dragged( m_draggedLine );
259 
260  if( m_mode == DM_SEGMENT )
261  dragged.DragSegment( aP, m_draggedSegmentIndex, thresh );
262  else
263  dragged.DragCorner( aP, m_draggedSegmentIndex, thresh );
264 
265  SHOVE::SHOVE_STATUS st = m_shove->ShoveLines( dragged );
266 
267  if( st == SHOVE::SH_OK )
268  ok = true;
269  else if( st == SHOVE::SH_HEAD_MODIFIED )
270  {
271  dragged = m_shove->NewHead();
272  ok = true;
273  }
274 
276 
277  if( ok )
278  m_lastValidDraggedLine = dragged;
279 
285 
286  break;
287  }
288 
289  case DM_VIA:
290  {
291  VIA* newVia;
293 
294  if( st == SHOVE::SH_OK || st == SHOVE::SH_HEAD_MODIFIED )
295  ok = true;
296 
298 
299  if( ok )
300  {
301  if( newVia )
302  m_draggedVia = newVia;
304  }
305 
306  break;
307  }
308  }
309 
310  m_dragStatus = ok;
311 
312  return ok;
313 }
314 
315 
317 {
318  if( m_dragStatus )
319  {
321  return true;
322  }
323 
324  return false;
325 }
326 
327 
328 bool DRAGGER::Drag( const VECTOR2I& aP )
329 {
330  if( m_freeAngleMode )
331  return dragMarkObstacles( aP );
332 
333  switch( m_currentMode )
334  {
335  case RM_MarkObstacles:
336  return dragMarkObstacles( aP );
337 
338  case RM_Shove:
339  case RM_Walkaround:
340  case RM_Smart:
341  return dragShove( aP );
342 
343  default:
344  return false;
345  }
346 }
347 
348 
350 {
351  return m_lastNode;
352 }
353 
354 
356 {
357  return m_draggedItems;
358 }
359 
360 
362 {
363  if( m_shove )
364  return m_shove->Logger();
365 
366  return NULL;
367 }
368 
369 }
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:123
void DragCorner(const VECTOR2I &aP, int aIndex, int aSnappingThreshold=0, bool aFreeAngle=false)
Definition: pns_line.cpp:438
bool SmoothDraggedSegments() const
Returns true if smoothing segments durign dragging is enabled.
VIA * m_initialVia
Definition: pns_dragger.h:122
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:111
const LAYER_RANGE & Layers() const
Function Layers()
Definition: pns_item.h:207
Class SHOVE.
Definition: pns_shove.h:46
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:119
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:114
ROUTING_SETTINGS & Settings() const
Returns current router settings
LINE m_lastValidDraggedLine
Definition: pns_dragger.h:116
void DragSegment(const VECTOR2I &aP, int aIndex, int aSnappingThreshold=0, bool aFreeAngle=false)
Definition: pns_line.cpp:450
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:115
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
void Reverse()
Reverses the point/vertex order
Definition: pns_line.cpp:730
const ITEM_SET Traces()
Function Traces()
SHOVE * m_shove
Definition: pns_dragger.h:117
bool startDragVia(const VECTOR2D &aP, VIA *aVia)
Definition: pns_dragger.cpp:95
int m_draggedSegmentIndex
Definition: pns_dragger.h:118
bool FixRoute()
Function FixRoute()
int Width() const
Definition: pns_segment.h:88
ITEM_SET m_origViaConnections
Definition: pns_dragger.h:121
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
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
void SetMode(int aDragMode)
NODE * m_lastNode
Definition: pns_dragger.h:112
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:815
bool dragShove(const VECTOR2I &aP)
PNS_MODE m_currentMode
Definition: pns_dragger.h:120
void CommitRouting(NODE *aNode)
Definition: pns_router.cpp:326
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
VECTOR2I A
Definition: seg.h:47
int Net() const
Function Net()
Definition: pns_item.h:177
bool dragMarkObstacles(const VECTOR2I &aP)
void SetInitialLine(LINE &aInitial)
Definition: pns_shove.cpp:1407
bool m_freeAngleMode
Definition: pns_dragger.h:124
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
VECTOR2I B
Definition: seg.h:48