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 
153 void DRAGGER::SetMode( int aMode )
154 {
155  m_mode = aMode;
156 }
157 
158 
160 {
161  if( m_lastNode )
162  {
163  delete m_lastNode;
164  m_lastNode = NULL;
165  }
166 
167  switch( m_mode )
168  {
169  case DM_SEGMENT:
170  case DM_CORNER:
171  {
172  int thresh = Settings().SmoothDraggedSegments() ? m_draggedLine.Width() / 4 : 0;
173  LINE dragged( m_draggedLine );
174 
175  if( m_mode == DM_SEGMENT )
176  dragged.DragSegment( aP, m_draggedSegmentIndex, thresh );
177  else
178  dragged.DragCorner( aP, m_draggedSegmentIndex, thresh, m_freeAngleMode );
179 
181 
182  m_lastValidDraggedLine = dragged;
185 
189 
190  break;
191  }
192 
193  case DM_VIA: // fixme...
194  {
197 
198  break;
199  }
200  }
201 
202  if( Settings().CanViolateDRC() )
203  m_dragStatus = true;
204  else
206 
207  return true;
208 }
209 
210 
211 void DRAGGER::dumbDragVia( VIA* aVia, NODE* aNode, const VECTOR2I& aP )
212 {
214 
215  // fixme: this is awful.
216  auto via_clone = Clone( *aVia );
217 
218  m_draggedVia = via_clone.get();
219  m_draggedVia->SetPos( aP );
220 
222 
223  m_lastNode->Remove( aVia );
224  m_lastNode->Add( std::move( via_clone ) );
225 
226  for( ITEM* item : m_origViaConnections.Items() )
227  {
228  if( const LINE* l = dyn_cast<const LINE*>( item ) )
229  {
230  LINE origLine( *l );
231  LINE draggedLine( *l );
232 
233  draggedLine.DragCorner( aP, origLine.CLine().Find( aVia->Pos() ), 0, m_freeAngleMode );
234  draggedLine.ClearSegmentLinks();
235 
236  m_draggedItems.Add( draggedLine );
237 
238  m_lastNode->Remove( origLine );
239  m_lastNode->Add( draggedLine );
240  }
241  }
242 }
243 
244 
245 bool DRAGGER::dragShove( const VECTOR2I& aP )
246 {
247  bool ok = false;
248 
249  if( m_lastNode )
250  {
251  delete m_lastNode;
252  m_lastNode = NULL;
253  }
254 
255  switch( m_mode )
256  {
257  case DM_SEGMENT:
258  case DM_CORNER:
259  {
260  int thresh = Settings().SmoothDraggedSegments() ? m_draggedLine.Width() / 4 : 0;
261  LINE dragged( m_draggedLine );
262 
263  if( m_mode == DM_SEGMENT )
264  dragged.DragSegment( aP, m_draggedSegmentIndex, thresh );
265  else
266  dragged.DragCorner( aP, m_draggedSegmentIndex, thresh );
267 
268  SHOVE::SHOVE_STATUS st = m_shove->ShoveLines( dragged );
269 
270  if( st == SHOVE::SH_OK )
271  ok = true;
272  else if( st == SHOVE::SH_HEAD_MODIFIED )
273  {
274  dragged = m_shove->NewHead();
275  ok = true;
276  }
277 
279 
280  if( ok )
281  m_lastValidDraggedLine = dragged;
282 
288 
289  break;
290  }
291 
292  case DM_VIA:
293  {
294  VIA* newVia;
296 
297  if( st == SHOVE::SH_OK || st == SHOVE::SH_HEAD_MODIFIED )
298  ok = true;
299 
301 
302  if( ok )
303  {
304  if( newVia )
305  m_draggedVia = newVia;
306 
308  }
309 
310  break;
311  }
312  }
313 
314  m_dragStatus = ok;
315 
316  return ok;
317 }
318 
319 
321 {
322  NODE* node = CurrentNode();
323 
324  if( node )
325  {
326  // Collisions still prevent fixing unless "Allow DRC violations" is checked
327  if( !m_dragStatus )
328  return false;
329 
330  Router()->CommitRouting( node );
331  return true;
332  }
333 
334  return false;
335 }
336 
337 
338 bool DRAGGER::Drag( const VECTOR2I& aP )
339 {
340  if( m_freeAngleMode )
341  return dragMarkObstacles( aP );
342 
343  switch( m_currentMode )
344  {
345  case RM_MarkObstacles:
346  return dragMarkObstacles( aP );
347 
348  case RM_Shove:
349  case RM_Walkaround:
350  case RM_Smart:
351  return dragShove( aP );
352 
353  default:
354  return false;
355  }
356 }
357 
358 
360 {
361  return m_lastNode;
362 }
363 
364 
366 {
367  return m_draggedItems;
368 }
369 
370 
372 {
373  if( m_shove )
374  return m_shove->Logger();
375 
376  return NULL;
377 }
378 
379 }
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:441
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:136
NODE * m_world
Definition: pns_dragger.h:111
const LAYER_RANGE & Layers() const
Function Layers()
Definition: pns_item.h:209
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:140
bool m_dragStatus
Definition: pns_dragger.h:119
virtual void Unmark(int aMarker=-1)
Definition: pns_item.h:308
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:453
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:1087
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:733
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:729
SHOVE_STATUS ShoveDraggingVia(VIA *aVia, const VECTOR2I &aWhere, VIA **aNewVia)
Definition: pns_shove.cpp:1271
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:1408
PnsKind Kind() const
Function Kind()
Definition: pns_item.h:122
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:380
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:818
bool dragShove(const VECTOR2I &aP)
PNS_MODE m_currentMode
Definition: pns_dragger.h:120
void CommitRouting(NODE *aNode)
Definition: pns_router.cpp:350
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:179
bool dragMarkObstacles(const VECTOR2I &aP)
void SetInitialLine(LINE &aInitial)
Definition: pns_shove.cpp:1416
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.
bool 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:1402
VECTOR2I B
Definition: seg.h:47