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

◆ AllAreModulesAndReturnSmallestIfSo()

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.

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 GetWidth() const
Definition: eda_rect.h:117
int GetCount() const
Function GetCount returns the number of objects in the list.
Definition: collector.h:114
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.
int GetHeight() const
Definition: eda_rect.h:118
size_t i
Definition: json11.cpp:597
#define min(a, b)
Definition: auxiliary.h:85

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().

◆ Magnetize()

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.

131 {
132  // Note: only used for routing in the Legacy Toolset
133  // 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:89
int GetNetCode() const
Function GetNetCode.
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:200
Class BOARD_ITEM is a base class for any item which can be embedded within the BOARD container class,...
const wxPoint & GetStart() const
Definition: class_track.h:133
bool HitTest(const wxPoint &aPosition, int aAccuracy=0) const override
Function HitTest tests if aPosition is contained within or on the bounding box of an item.
MAGNETIC_PAD_OPTION_VALUES m_magneticPads
D_PAD * GetPad(unsigned aIndex) const
Function GetPad.
PCB_LAYER_ID m_Active_Layer
Definition: pcb_screen.h:44
class TRACK, a track segment (segment on a copper layer)
Definition: typeinfo.h:95
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...
MAGNETIC_PAD_OPTION_VALUES m_magneticTracks
PCB_LAYER_ID
A quick note on layer IDs:
Class LSET is a set of PCB_LAYER_IDs.
virtual bool IsOnLayer(PCB_LAYER_ID aLayer) const
Function IsOnLayer tests to see if this object is on the given layer.
PCB_GENERAL_SETTINGS & Settings()
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,...
bool FindBestGridPointOnTrack(wxPoint *aNearPos, wxPoint on_grid, const TRACK *track)
Finds the projection of a grid point on a track.
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:453
int GetWidth() const
Definition: class_track.h:127
TRACK * Next() const
Definition: class_track.h:110
Class BOARD holds information pertinent to a Pcbnew printed circuit board.
Definition: class_board.h:170
wxPoint RefPos(bool useMouse) const
Return the reference position, coming from either the mouse position or the cursor position.
PCB_SCREEN * GetScreen() const override
Return a pointer to a BASE_SCREEN or one of its derivatives.
const wxPoint & GetEnd() const
Definition: class_track.h:130
class VIA, a via (like a track segment on a copper layer)
Definition: typeinfo.h:96
DLIST< TRACK > m_Track
Definition: class_board.h:249
BOARD * GetBoard() const
const wxPoint GetPosition() const override
Definition: class_pad.h:222
STATUS_FLAGS GetFlags() const
Definition: base_struct.h:261
BOARD_ITEM * GetCurItem()
virtual PCB_LAYER_ID GetLayer() const
Function GetLayer returns the primary layer this item is on.
KICAD_T Type() const
Function Type()
Definition: base_struct.h:204
TRACK * Back() const
Definition: class_track.h:111

References TRACK::Back(), CAPTURE_ALWAYS, CAPTURE_CURSOR_IN_TRACK_TOOL, FindBestGridPointOnTrack(), g_CurrentTrackSegment, PCB_BASE_FRAME::GetBoard(), PCB_BASE_FRAME::GetCurItem(), TRACK::GetEnd(), EDA_ITEM::GetFlags(), GetLineLength(), BOARD_CONNECTED_ITEM::GetNetCode(), BOARD::GetPad(), D_PAD::GetPosition(), PCB_BASE_FRAME::GetScreen(), TRACK::GetStart(), BOARD::GetVisibleTrack(), TRACK::GetWidth(), ID_TRACK_BUTT, BOARD::IsLayerVisible(), Join(), PCB_SCREEN::m_Active_Layer, PCB_GENERAL_SETTINGS::m_legacyDrcOn, PCB_GENERAL_SETTINGS::m_legacyUseTwoSegmentTracks, PCB_GENERAL_SETTINGS::m_magneticPads, PCB_GENERAL_SETTINGS::m_magneticTracks, BOARD::m_Track, PCB_TRACE_T, PCB_VIA_T, EDA_DRAW_FRAME::RefPos(), PCB_BASE_FRAME::Settings(), and EDA_ITEM::Type().

Referenced by PCB_EDIT_FRAME::GeneralControl().