KiCad PCB EDA Suite
pcbnew/controle.cpp File Reference
#include <fctsys.h>
#include <class_drawpanel.h>
#include <pcb_edit_frame.h>
#include <pcbnew_id.h>
#include <class_board.h>
#include <class_module.h>
#include <class_zone.h>
#include <pcbnew.h>
#include <protos.h>
#include <collectors.h>
#include <menus_helpers.h>

Go to the source code of this file.

Functions

bool Magnetize (PCB_BASE_EDIT_FRAME *frame, int aCurrentTool, wxSize aGridSize, wxPoint on_grid, wxPoint *curpos)
 Function Magnetize tests to see if there are any magnetic items within near reach of the given "curpos". More...
 
static BOARD_ITEMAllAreModulesAndReturnSmallestIfSo (GENERAL_COLLECTOR *aCollector)
 Function AllAreModulesAndReturnSmallestIfSo tests that all items in the collection are MODULEs and if so, returns the smallest MODULE. More...
 

Function Documentation

static BOARD_ITEM* AllAreModulesAndReturnSmallestIfSo ( GENERAL_COLLECTOR aCollector)
static

Function AllAreModulesAndReturnSmallestIfSo tests that all items in the collection are MODULEs and if so, returns the smallest MODULE.

Returns
BOARD_ITEM* - The smallest or NULL.

Definition at line 55 of file pcbnew/controle.cpp.

References MODULE::GetBoundingBox(), COLLECTOR::GetCount(), EDA_RECT::GetHeight(), GENERAL_COLLECTOR::GetPrimaryCount(), EDA_RECT::GetWidth(), i, min, and PCB_MODULE_T.

Referenced by PCB_BASE_FRAME::PcbGeneralLocateAndDisplay().

56 {
57 #if 0 // Dick: this is not consistent with name of this function, and does not
58  // work correctly using 'M' (move hotkey) when another module's (2nd module) reference
59  // is under a module (first module) and you want to move the reference.
60  // Another way to fix this would be to
61  // treat module text as copper layer content, and put the module text into
62  // the primary list. I like the coded behavior best. If it breaks something
63  // perhaps you need a different test before calling this function, which should
64  // do what its name says it does.
65  int count = aCollector->GetPrimaryCount(); // try to use preferred layer
66  if( 0 == count ) count = aCollector->GetCount();
67 #else
68  int count = aCollector->GetCount();
69 #endif
70 
71  for( int i = 0; i<count; ++i )
72  {
73  if( (*aCollector)[i]->Type() != PCB_MODULE_T )
74  return NULL;
75  }
76 
77  // all are modules, now find smallest MODULE
78 
79  int minDim = 0x7FFFFFFF;
80  int minNdx = 0;
81 
82  for( int i = 0; i<count; ++i )
83  {
84  MODULE* module = (MODULE*) (*aCollector)[i];
85 
86  int lx = module->GetBoundingBox().GetWidth();
87  int ly = module->GetBoundingBox().GetHeight();
88 
89  int lmin = std::min( lx, ly );
90 
91  if( lmin < minDim )
92  {
93  minDim = lmin;
94  minNdx = i;
95  }
96  }
97 
98  return (*aCollector)[minNdx];
99 }
int GetCount() const
Function GetCount returns the number of objects in the list.
Definition: collector.h:106
int GetHeight() const
Definition: eda_rect.h:118
class MODULE, a footprint
Definition: typeinfo.h:89
const EDA_RECT GetBoundingBox() const override
Function GetBoundingBox returns the orthogonal, bounding box of this object for display purposes...
size_t i
Definition: json11.cpp:597
int GetWidth() const
Definition: eda_rect.h:117
#define min(a, b)
Definition: auxiliary.h:85
bool Magnetize ( PCB_BASE_EDIT_FRAME frame,
int  aCurrentTool,
wxSize  aGridSize,
wxPoint  on_grid,
wxPoint curpos 
)

Function Magnetize tests to see if there are any magnetic items within near reach of the given "curpos".

If yes, then curpos is adjusted appropriately according to that near magnetic item and true is returned.

Parameters
frame= the current frame
aCurrentTool= the current tool id (from vertical right toolbar)
aGridSize= the current grid size
on_grid= the on grid position near initial position ( often on_grid = curpos)
curposThe initial position, and what to adjust if a change is needed.
Returns
bool - true if the position was adjusted magnetically, else false.

Definition at line 129 of file magnetic_tracks_functions.cpp.

Referenced by PCB_EDIT_FRAME::GeneralControl().

131 {
132  // Note: only used for routing in the Legacy Toolset and for the measurement tool in the
133  // Modern Toolset. Can be greatly simplified when the Legacy Toolset is retired.
134 
135  bool doCheckNet = frame->Settings().m_magneticPads != CAPTURE_ALWAYS && frame->Settings().m_legacyDrcOn;
136  bool doCheckLayer = aCurrentTool == ID_TRACK_BUTT;
137  bool doTrack = false;
138  bool doPad = false;
139  bool amMovingVia = false;
140 
141  BOARD* m_Pcb = frame->GetBoard();
142  TRACK* currTrack = g_CurrentTrackSegment;
143  BOARD_ITEM* currItem = frame->GetCurItem();
144  PCB_SCREEN* screen = frame->GetScreen();
145  wxPoint pos = frame->RefPos( true );
146 
147  // D( printf( "currTrack=%p currItem=%p currTrack->Type()=%d currItem->Type()=%d\n", currTrack, currItem, currTrack ? currTrack->Type() : 0, currItem ? currItem->Type() : 0 ); )
148 
149  if( !currTrack && currItem && currItem->Type()==PCB_VIA_T && currItem->GetFlags() )
150  {
151  // moving a VIA
152  currTrack = (TRACK*) currItem;
153  amMovingVia = true;
154 
155  return false; // comment this return out and play with it.
156  }
157  else if( currItem != currTrack )
158  {
159  currTrack = NULL;
160  }
161 
162  if( frame->Settings().m_magneticPads == CAPTURE_ALWAYS )
163  doPad = true;
164 
165  if( frame->Settings().m_magneticTracks == CAPTURE_ALWAYS )
166  doTrack = true;
167 
168  if( aCurrentTool == ID_TRACK_BUTT || amMovingVia )
169  {
171 
172  if( frame->Settings().m_magneticPads == q )
173  doPad = true;
174 
175  if( frame->Settings().m_magneticTracks == q )
176  doTrack = true;
177  }
178 
179  // The search precedence order is pads, then tracks/vias
180  if( doPad )
181  {
182  D_PAD* pad;
183  if( doCheckLayer )
184  pad = m_Pcb->GetPad( pos, LSET( screen->m_Active_Layer ) );
185  else
186  pad = m_Pcb->GetPad( pos );
187 
188  if( pad )
189  {
190  if( doCheckNet && currTrack && currTrack->GetNetCode() != pad->GetNetCode() )
191  return false;
192 
193  *curpos = pad->GetPosition();
194  return true;
195  }
196  }
197 
198  // after pads, only track & via tests remain, skip them if not desired
199  if( doTrack )
200  {
201  PCB_LAYER_ID layer = screen->m_Active_Layer;
202 
203  for( TRACK* via = m_Pcb->m_Track;
204  via && (via = via->GetVia( *curpos, layer )) != NULL;
205  via = via->Next() )
206  {
207  if( via != currTrack ) // a via cannot influence itself
208  {
209  if( !doCheckNet || !currTrack || currTrack->GetNetCode() == via->GetNetCode() )
210  {
211  *curpos = via->GetStart();
212  // D(printf("via hit\n");)
213  return true;
214  }
215  }
216  }
217 
218  if( !currTrack )
219  {
220  LSET layers( layer );
221 
222  TRACK* track = m_Pcb->GetVisibleTrack( m_Pcb->m_Track, pos, layers );
223 
224  if( !track || track->Type() != PCB_TRACE_T )
225  {
226  return false;
227  }
228 
229  return FindBestGridPointOnTrack( curpos, on_grid, track );
230  }
231 
232  /*
233  * In two segment mode, ignore the final segment if it's inside a grid square.
234  */
235  if( !amMovingVia && currTrack && frame->Settings().m_legacyUseTwoSegmentTracks && currTrack->Back()
236  && currTrack->GetStart().x - aGridSize.x < currTrack->GetEnd().x
237  && currTrack->GetStart().x + aGridSize.x > currTrack->GetEnd().x
238  && currTrack->GetStart().y - aGridSize.y < currTrack->GetEnd().y
239  && currTrack->GetStart().y + aGridSize.y > currTrack->GetEnd().y )
240  {
241  currTrack = currTrack->Back();
242  }
243 
244 
245  for( TRACK* track = m_Pcb->m_Track; track; track = track->Next() )
246  {
247  if( track->Type() != PCB_TRACE_T )
248  continue;
249 
250  if( doCheckNet && currTrack && currTrack->GetNetCode() != track->GetNetCode() )
251  continue;
252 
253  if( m_Pcb->IsLayerVisible( track->GetLayer() ) == false )
254  continue;
255 
256  // omit the layer check if moving a via
257  if( !amMovingVia && !track->IsOnLayer( layer ) )
258  continue;
259 
260  if( !track->HitTest( *curpos ) )
261  continue;
262 
263  if( Join( curpos, track->GetStart(), track->GetEnd(), currTrack->GetStart(), currTrack->GetEnd() ) )
264  {
265  return true;
266  }
267 
268  if( aCurrentTool == ID_TRACK_BUTT || amMovingVia )
269  {
270  // At this point we have a drawing mouse on a track, we are drawing
271  // a new track and that new track is parallel to the track the
272  // mouse is on. Find the nearest end point of the track under mouse
273  // to the mouse and return that.
274  double distStart = GetLineLength( *curpos, track->GetStart() );
275  double distEnd = GetLineLength( *curpos, track->GetEnd() );
276 
277  // if track not via, or if its a via dragging but not with its adjacent track
278  if( currTrack->Type() != PCB_VIA_T ||
279  ( currTrack->GetStart() != track->GetStart() && currTrack->GetStart() != track->GetEnd() ))
280  {
281  double max_dist = currTrack->GetWidth() / 2.0f;
282 
283  if( distStart <= max_dist )
284  {
285  // D(printf("nearest end is start\n");)
286  *curpos = track->GetStart();
287  return true;
288  }
289 
290  if( distEnd <= max_dist )
291  {
292  // D(printf("nearest end is end\n");)
293  *curpos = track->GetEnd();
294  return true;
295  }
296 
297  // @todo otherwise confine curpos such that it stays centered within "track"
298  }
299  }
300  }
301  }
302 
303  return false;
304 }
#define g_CurrentTrackSegment
most recently created segment
Definition: pcbnew.h:99
KICAD_T Type() const
Function Type()
Definition: base_struct.h:209
STATUS_FLAGS GetFlags() const
Definition: base_struct.h:266
double GetLineLength(const wxPoint &aPointA, const wxPoint &aPointB)
Function GetLineLength returns the length of a line segment defined by aPointA and aPointB...
Definition: trigo.h:191
virtual bool IsOnLayer(PCB_LAYER_ID aLayer) const
Function IsOnLayer tests to see if this object is on the given layer.
Class BOARD_ITEM is a base class for any item which can be embedded within the BOARD container class...
virtual PCB_LAYER_ID GetLayer() const
Function GetLayer returns the primary layer this item is on.
MAGNETIC_PAD_OPTION_VALUES m_magneticPads
BOARD * GetBoard() const
D_PAD * GetPad(unsigned aIndex) const
Function GetPad.
PCB_LAYER_ID m_Active_Layer
Definition: pcb_screen.h:44
TRACK * Back() const
Definition: class_track.h:100
const wxPoint & GetEnd() const
Definition: class_track.h:119
class TRACK, a track segment (segment on a copper layer)
Definition: typeinfo.h:95
MAGNETIC_PAD_OPTION_VALUES m_magneticTracks
PCB_LAYER_ID
A quick note on layer IDs:
virtual bool HitTest(const wxPoint &aPosition) const override
Function HitTest tests if aPosition is contained within or on the bounding area of an item...
Class LSET is a set of PCB_LAYER_IDs.
PCB_GENERAL_SETTINGS & Settings()
const wxPoint & GetStart() const
Definition: class_track.h:122
TRACK * GetVisibleTrack(TRACK *aStartingTrace, const wxPoint &aPosition, LSET aLayerSet) const
Function GetVisibleTrack finds the neighboring visible segment of aTrace at aPosition that is on a la...
static bool Join(wxPoint *aIntersectPoint, wxPoint a0, wxPoint a1, wxPoint b0, wxPoint b1)
Function Join finds the point where line segment (b1,b0) intersects with segment (a1,a0).
bool FindBestGridPointOnTrack(wxPoint *aNearPos, wxPoint on_grid, const TRACK *track)
Finds the projection of a grid point on a track.
int GetNetCode() const
Function GetNetCode.
wxPoint RefPos(bool useMouse) const
Function RefPos Return the reference position, coming from either the mouse position or the cursor po...
TRACK * Next() const
Definition: class_track.h:99
Class BOARD holds information pertinent to a Pcbnew printed circuit board.
Definition: class_board.h:169
int GetWidth() const
Definition: class_track.h:116
PCB_SCREEN * GetScreen() const override
Function GetScreen returns a pointer to a BASE_SCREEN or one of its derivatives.
class VIA, a via (like a track segment on a copper layer)
Definition: typeinfo.h:96
DLIST< TRACK > m_Track
Definition: class_board.h:248
const wxPoint GetPosition() const override
Definition: class_pad.h:220
BOARD_ITEM * GetCurItem()
bool IsLayerVisible(PCB_LAYER_ID aLayer) const
Function IsLayerVisible is a proxy function that calls the correspondent function in m_BoardSettings ...
Definition: class_board.h:454