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  m_freeAngleMode = false;
41 }
42 
43 
45 {
46  if( m_shove )
47  delete m_shove;
48 }
49 
50 
51 void DRAGGER::SetWorld( NODE* aWorld )
52 {
53  m_world = aWorld;
54 }
55 
56 
57 bool DRAGGER::startDragSegment( const VECTOR2D& aP, SEGMENT* aSeg )
58 {
59  int w2 = aSeg->Width() / 2;
60 
65 
66  auto distA = ( aP - aSeg->Seg().A ).EuclideanNorm();
67  auto distB = ( aP - aSeg->Seg().B ).EuclideanNorm();
68 
69 
70  if( distA <= w2 )
71  {
72  m_mode = DM_CORNER;
73  }
74  else if( distB <= w2 )
75  {
77  m_mode = DM_CORNER;
78  }
79  else if ( m_freeAngleMode )
80  {
81  if( distB < distA )
82  {
84  }
85  m_mode = DM_CORNER;
86  }
87  else
88  {
90  }
91 
92  return true;
93 }
94 
95 
96 bool DRAGGER::startDragVia( const VECTOR2D& aP, VIA* aVia )
97 {
98  m_draggedVia = aVia;
99  m_initialVia = aVia;
100  m_mode = DM_VIA;
101 
102  VECTOR2I p0( aVia->Pos() );
103  JOINT* jt = m_world->FindJoint( p0, aVia->Layers().Start(), aVia->Net() );
104 
105  if( !jt )
106  return false;
107 
108  for( ITEM* item : jt->LinkList() )
109  {
110  if( item->OfKind( ITEM::SEGMENT_T ) )
111  {
112  int segIndex;
113  SEGMENT* seg = ( SEGMENT*) item;
114  LINE l = m_world->AssembleLine( seg, &segIndex );
115 
116  if( segIndex != 0 )
117  l.Reverse();
118 
120  }
121  }
122 
123  return true;
124 }
125 
126 
127 bool DRAGGER::Start( const VECTOR2I& aP, ITEM* aStartItem )
128 {
129  m_shove = new SHOVE( m_world, Router() );
130  m_lastNode = NULL;
134 
135  aStartItem->Unmark( MK_LOCKED );
136 
137  wxLogTrace( "PNS", "StartDragging: item %p [kind %d]", aStartItem, (int) aStartItem->Kind() );
138 
139  switch( aStartItem->Kind() )
140  {
141  case ITEM::SEGMENT_T:
142  return startDragSegment( aP, static_cast<SEGMENT*>( aStartItem ) );
143 
144  case ITEM::VIA_T:
145  return startDragVia( aP, static_cast<VIA*>( aStartItem ) );
146 
147  default:
148  return false;
149  }
150 }
151 
152 void DRAGGER::SetMode( int aMode )
153 {
154  m_mode = aMode;
155 }
156 
158 {
159  if( m_lastNode )
160  {
161  delete m_lastNode;
162  m_lastNode = NULL;
163  }
164 
165  switch( m_mode )
166  {
167  case DM_SEGMENT:
168  case DM_CORNER:
169  {
170  int thresh = Settings().SmoothDraggedSegments() ? m_draggedLine.Width() / 4 : 0;
171  LINE dragged( m_draggedLine );
172 
173  if( m_mode == DM_SEGMENT )
174  dragged.DragSegment( aP, m_draggedSegmentIndex, thresh );
175  else
176  dragged.DragCorner( aP, m_draggedSegmentIndex, thresh, m_freeAngleMode );
177 
179 
180  m_lastValidDraggedLine = dragged;
183 
187 
188  break;
189  }
190 
191  case DM_VIA: // fixme...
192  {
195 
196  break;
197  }
198  }
199 
200  if( Settings().CanViolateDRC() )
201  m_dragStatus = true;
202  else
204 
205  return true;
206 }
207 
208 
209 void DRAGGER::dumbDragVia( VIA* aVia, NODE* aNode, const VECTOR2I& aP )
210 {
212 
213  // fixme: this is awful.
214  auto via_clone = Clone( *aVia );
215 
216  m_draggedVia = via_clone.get();
217  m_draggedVia->SetPos( aP );
218 
220 
221  m_lastNode->Remove( aVia );
222  m_lastNode->Add( std::move( via_clone ) );
223 
224  for( ITEM* item : m_origViaConnections.Items() )
225  {
226  if( const LINE* l = dyn_cast<const LINE*>( item ) )
227  {
228  LINE origLine( *l );
229  LINE draggedLine( *l );
230 
231  draggedLine.DragCorner( aP, origLine.CLine().Find( aVia->Pos() ), 0, m_freeAngleMode );
232  draggedLine.ClearSegmentLinks();
233 
234  m_draggedItems.Add( draggedLine );
235 
236  m_lastNode->Remove( origLine );
237  m_lastNode->Add( draggedLine );
238  }
239  }
240 }
241 
242 
243 bool DRAGGER::dragShove( const VECTOR2I& aP )
244 {
245  bool ok = false;
246 
247  if( m_lastNode )
248  {
249  delete m_lastNode;
250  m_lastNode = NULL;
251  }
252 
253  switch( m_mode )
254  {
255  case DM_SEGMENT:
256  case DM_CORNER:
257  {
258  int thresh = Settings().SmoothDraggedSegments() ? m_draggedLine.Width() / 4 : 0;
259  LINE dragged( m_draggedLine );
260 
261  if( m_mode == DM_SEGMENT )
262  dragged.DragSegment( aP, m_draggedSegmentIndex, thresh );
263  else
264  dragged.DragCorner( aP, m_draggedSegmentIndex, thresh );
265 
266  SHOVE::SHOVE_STATUS st = m_shove->ShoveLines( dragged );
267 
268  if( st == SHOVE::SH_OK )
269  ok = true;
270  else if( st == SHOVE::SH_HEAD_MODIFIED )
271  {
272  dragged = m_shove->NewHead();
273  ok = true;
274  }
275 
277 
278  if( ok )
279  m_lastValidDraggedLine = dragged;
280 
286 
287  break;
288  }
289 
290  case DM_VIA:
291  {
292  VIA* newVia;
294 
295  if( st == SHOVE::SH_OK || st == SHOVE::SH_HEAD_MODIFIED )
296  ok = true;
297 
299 
300  if( ok )
301  {
302  if( newVia )
303  m_draggedVia = newVia;
305  }
306 
307  break;
308  }
309  }
310 
311  m_dragStatus = ok;
312 
313  return ok;
314 }
315 
316 
318 {
319  if( m_dragStatus )
320  {
322  return true;
323  }
324 
325  return false;
326 }
327 
328 
329 bool DRAGGER::Drag( const VECTOR2I& aP )
330 {
331  if( m_freeAngleMode )
332  return dragMarkObstacles( aP );
333 
334  switch( m_currentMode )
335  {
336  case RM_MarkObstacles:
337  return dragMarkObstacles( aP );
338 
339  case RM_Shove:
340  case RM_Walkaround:
341  case RM_Smart:
342  return dragShove( aP );
343 
344  default:
345  return false;
346  }
347 }
348 
349 
351 {
352  return m_lastNode;
353 }
354 
355 
357 {
358  return m_draggedItems;
359 }
360 
361 
363 {
364  if( m_shove )
365  return m_shove->Logger();
366 
367  return NULL;
368 }
369 
370 }
double EuclideanNorm(const wxPoint &vector)
Euclidean norm of a 2D vector.
Definition: trigo.h:112
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:436
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:832
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:57
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:448
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:107
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:51
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:43
void Reverse()
Reverses the point/vertex order
Definition: pns_line.cpp:728
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:96
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:727
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:966
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:813
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:425
VECTOR2I A
Definition: seg.h:46
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:594
virtual void Unmark(int aMarker=-1) override
Definition: pns_line.cpp:94
NODE * CurrentNode()
Definition: pns_shove.cpp:1393
VECTOR2I B
Definition: seg.h:47