KiCad PCB EDA Suite
pcb_grid_helper.cpp
Go to the documentation of this file.
1 /*
2  * This program source code file is part of KiCad, a free EDA CAD application.
3  *
4  * Copyright (C) 2014 CERN
5  * Copyright (C) 2018-2021 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
9  * modify it under the terms of the GNU General Public License
10  * as published by the Free Software Foundation; either version 2
11  * of the License, or (at your option) any later version.
12  *
13  * This program is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16  * GNU General Public License for more details.
17  *
18  * You should have received a copy of the GNU General Public License
19  * along with this program; if not, you may find one here:
20  * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
21  * or you may search the http://www.gnu.org website for the version 2 license,
22  * or you may write to the Free Software Foundation, Inc.,
23  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
24  */
25 
26 #include <functional>
27 #include <board.h>
28 #include <dimension.h>
29 #include <fp_shape.h>
30 #include <footprint.h>
31 #include <track.h>
32 #include <zone.h>
33 #include <geometry/shape_circle.h>
35 #include <geometry/shape_rect.h>
36 #include <geometry/shape_segment.h>
37 #include <geometry/shape_simple.h>
38 #include <macros.h>
39 #include <math/util.h> // for KiROUND
40 #include <painter.h>
41 #include <pcbnew_settings.h>
42 #include <tool/tool_manager.h>
43 #include <tools/pcb_tool_base.h>
44 #include <view/view.h>
45 #include "pcb_grid_helper.h"
46 
47 
49  GRID_HELPER( aToolMgr ),
50  m_magneticSettings( aMagneticSettings )
51 {
52  KIGFX::VIEW* view = m_toolMgr->GetView();
53  KIGFX::RENDER_SETTINGS* settings = view->GetPainter()->GetSettings();
54  KIGFX::COLOR4D auxItemsColor = settings->GetLayerColor( LAYER_AUX_ITEMS );
55  KIGFX::COLOR4D umbilicalColor = settings->GetLayerColor( LAYER_ANCHOR );
56 
57  m_viewAxis.SetSize( 20000 );
59  m_viewAxis.SetColor( auxItemsColor.WithAlpha( 0.4 ) );
60  m_viewAxis.SetDrawAtZero( true );
61  view->Add( &m_viewAxis );
62  view->SetVisible( &m_viewAxis, false );
63 
65  m_viewSnapPoint.SetColor( auxItemsColor );
67  view->Add( &m_viewSnapPoint );
68  view->SetVisible( &m_viewSnapPoint, false );
69 
71  m_viewSnapLine.SetColor( umbilicalColor );
73  view->Add( &m_viewSnapLine );
74  view->SetVisible( &m_viewSnapLine, false );
75 }
76 
77 
79 {
80  OPT_VECTOR2I pts[6];
81 
82  const int c_gridSnapEpsilon = 2;
83 
84  if( !m_enableSnap )
85  return aPoint;
86 
87  const VECTOR2D gridOffset( GetOrigin() );
88  const VECTOR2D gridSize( GetGrid() );
89 
90  VECTOR2I nearest( KiROUND( ( aPoint.x - gridOffset.x ) / gridSize.x ) * gridSize.x + gridOffset.x,
91  KiROUND( ( aPoint.y - gridOffset.y ) / gridSize.y ) * gridSize.y + gridOffset.y );
92 
93  pts[0] = aSeg.A;
94  pts[1] = aSeg.B;
95  pts[2] = aSeg.IntersectLines( SEG( nearest + VECTOR2I( -1, 1 ), nearest + VECTOR2I( 1, -1 ) ) );
96  pts[3] = aSeg.IntersectLines( SEG( nearest + VECTOR2I( -1, -1 ), nearest + VECTOR2I( 1, 1 ) ) );
97 
98  int min_d = std::numeric_limits<int>::max();
99 
100  for( int i = 0; i < 4; i++ )
101  {
102  if( pts[i] && aSeg.Distance( *pts[i] ) <= c_gridSnapEpsilon )
103  {
104  int d = (*pts[i] - aPoint).EuclideanNorm();
105 
106  if( d < min_d )
107  {
108  min_d = d;
109  nearest = *pts[i];
110  }
111  }
112  }
113 
114  return nearest;
115 }
116 
117 
119 {
120  if( !m_enableSnap )
121  return aPoint;
122 
123  const VECTOR2D gridOffset( GetOrigin() );
124  const VECTOR2D gridSize( GetGrid() );
125 
126  VECTOR2I nearest( KiROUND( ( aPoint.x - gridOffset.x ) / gridSize.x ) * gridSize.x + gridOffset.x,
127  KiROUND( ( aPoint.y - gridOffset.y ) / gridSize.y ) * gridSize.y + gridOffset.y );
128 
129  int min_d = std::numeric_limits<int>::max();
130 
131  for( auto pt : { aArc.GetP0(), aArc.GetP1() } )
132  {
133  int d = ( pt - aPoint ).EuclideanNorm();
134 
135  if( d < min_d )
136  {
137  min_d = d;
138  nearest = pt;
139  }
140  else
141  break;
142  }
143 
144  return nearest;
145 }
146 
147 
149  std::vector<BOARD_ITEM*>& aItems )
150 {
151  clearAnchors();
152 
153  for( BOARD_ITEM* item : aItems )
154  computeAnchors( item, aMousePos, true );
155 
156  double worldScale = m_toolMgr->GetView()->GetGAL()->GetWorldScale();
157  double lineSnapMinCornerDistance = 50.0 / worldScale;
158 
159  ANCHOR* nearestOutline = nearestAnchor( aMousePos, OUTLINE, LSET::AllLayersMask() );
160  ANCHOR* nearestCorner = nearestAnchor( aMousePos, CORNER, LSET::AllLayersMask() );
161  ANCHOR* nearestOrigin = nearestAnchor( aMousePos, ORIGIN, LSET::AllLayersMask() );
162  ANCHOR* best = NULL;
163  double minDist = std::numeric_limits<double>::max();
164 
165  if( nearestOrigin )
166  {
167  minDist = nearestOrigin->Distance( aMousePos );
168  best = nearestOrigin;
169  }
170 
171  if( nearestCorner )
172  {
173  double dist = nearestCorner->Distance( aMousePos );
174 
175  if( dist < minDist )
176  {
177  minDist = dist;
178  best = nearestCorner;
179  }
180  }
181 
182  if( nearestOutline )
183  {
184  double dist = nearestOutline->Distance( aMousePos );
185 
186  if( minDist > lineSnapMinCornerDistance && dist < minDist )
187  best = nearestOutline;
188  }
189 
190  return best ? best->pos : aMousePos;
191 }
192 
193 
195 {
196  LSET layers;
197  std::vector<BOARD_ITEM*> item;
198 
199  if( aReferenceItem )
200  {
201  layers = aReferenceItem->GetLayerSet();
202  item.push_back( aReferenceItem );
203  }
204  else
205  layers = LSET::AllLayersMask();
206 
207  return BestSnapAnchor( aOrigin, layers, item );
208 }
209 
210 
211 VECTOR2I PCB_GRID_HELPER::BestSnapAnchor( const VECTOR2I& aOrigin, const LSET& aLayers,
212  const std::vector<BOARD_ITEM*>& aSkip )
213 {
214  // Tuning constant: snap radius in screen space
215  const int snapSize = 25;
216 
217  // Snapping distance is in screen space, clamped to the current grid to ensure that the grid
218  // points that are visible can always be snapped to.
219  // see https://gitlab.com/kicad/code/kicad/-/issues/5638
220  // see https://gitlab.com/kicad/code/kicad/-/issues/7125
221  double snapScale = snapSize / m_toolMgr->GetView()->GetGAL()->GetWorldScale();
222  int snapRange = std::min( KiROUND( snapScale ), GetGrid().x );
223  int snapDist = snapRange;
224 
225  BOX2I bb( VECTOR2I( aOrigin.x - snapRange / 2, aOrigin.y - snapRange / 2 ),
226  VECTOR2I( snapRange, snapRange ) );
227 
228  clearAnchors();
229 
230  for( BOARD_ITEM* item : queryVisible( bb, aSkip ) )
231  computeAnchors( item, aOrigin );
232 
233  ANCHOR* nearest = nearestAnchor( aOrigin, SNAPPABLE, aLayers );
234  VECTOR2I nearestGrid = Align( aOrigin );
235 
236  if( nearest )
237  snapDist = nearest->Distance( aOrigin );
238 
239  // Existing snap lines need priority over new snaps
241  {
242  bool snapLine = false;
243  int x_dist = std::abs( m_viewSnapLine.GetPosition().x - aOrigin.x );
244  int y_dist = std::abs( m_viewSnapLine.GetPosition().y - aOrigin.y );
245 
247  if( x_dist < snapRange && ( !nearest || snapDist > snapRange ) )
248  {
249  nearestGrid.x = m_viewSnapLine.GetPosition().x;
250  snapLine = true;
251  }
252 
253  if( y_dist < snapRange && ( !nearest || snapDist > snapRange ) )
254  {
255  nearestGrid.y = m_viewSnapLine.GetPosition().y;
256  snapLine = true;
257  }
258 
259  if( snapLine && m_skipPoint != VECTOR2I( m_viewSnapLine.GetPosition() ) )
260  {
261  m_viewSnapLine.SetEndPosition( nearestGrid );
262 
265  else
267 
268  return nearestGrid;
269  }
270  }
271 
272  if( nearest && m_enableSnap )
273  {
274  if( nearest->Distance( aOrigin ) <= snapRange )
275  {
276  m_viewSnapPoint.SetPosition( wxPoint( nearest->pos ) );
277  m_viewSnapLine.SetPosition( wxPoint( nearest->pos ) );
279 
282  else
284 
285  m_snapItem = nearest;
286  return nearest->pos;
287  }
288  }
289 
290  m_snapItem = nullptr;
293  return nearestGrid;
294 }
295 
296 
298 {
299  if( !m_snapItem )
300  return nullptr;
301 
302  return static_cast<BOARD_ITEM*>( m_snapItem->item );
303 }
304 
305 
306 std::set<BOARD_ITEM*> PCB_GRID_HELPER::queryVisible( const BOX2I& aArea,
307  const std::vector<BOARD_ITEM*>& aSkip ) const
308 {
309  std::set<BOARD_ITEM*> items;
310  std::vector<KIGFX::VIEW::LAYER_ITEM_PAIR> selectedItems;
311 
312  KIGFX::VIEW* view = m_toolMgr->GetView();
313  RENDER_SETTINGS* settings = view->GetPainter()->GetSettings();
314  const std::set<unsigned int>& activeLayers = settings->GetHighContrastLayers();
315  bool isHighContrast = settings->GetHighContrast();
316 
317  view->Query( aArea, selectedItems );
318 
319  for( const KIGFX::VIEW::LAYER_ITEM_PAIR& it : selectedItems )
320  {
321  BOARD_ITEM* item = static_cast<BOARD_ITEM*>( it.first );
322 
323  // If we are in the footprint editor, don't use the footprint itself
324  if( static_cast<PCB_TOOL_BASE*>( m_toolMgr->GetCurrentTool() )->IsFootprintEditor()
325  && item->Type() == PCB_FOOTPRINT_T )
326  {
327  continue;
328  }
329 
330  // The item must be visible and on an active layer
331  if( view->IsVisible( item )
332  && ( !isHighContrast || activeLayers.count( it.second ) )
333  && item->ViewGetLOD( it.second, view ) < view->GetScale() )
334  {
335  items.insert ( item );
336  }
337  }
338 
339  for( BOARD_ITEM* skipItem : aSkip )
340  items.erase( skipItem );
341 
342  return items;
343 }
344 
345 
346 void PCB_GRID_HELPER::computeAnchors( BOARD_ITEM* aItem, const VECTOR2I& aRefPos, bool aFrom )
347 {
348  KIGFX::VIEW* view = m_toolMgr->GetView();
349  RENDER_SETTINGS* settings = view->GetPainter()->GetSettings();
350  const std::set<unsigned int>& activeLayers = settings->GetHighContrastLayers();
351  bool isHighContrast = settings->GetHighContrast();
352 
353  auto handlePadShape =
354  [&]( PAD* aPad )
355  {
356  addAnchor( aPad->GetPosition(), ORIGIN | SNAPPABLE, aPad );
357 
359  if( aFrom )
360  return;
361 
362  const std::shared_ptr<SHAPE> eshape = aPad->GetEffectiveShape( aPad->GetLayer() );
363 
364  wxASSERT( eshape->Type() == SH_COMPOUND );
365  const std::vector<SHAPE*> shapes =
366  static_cast<const SHAPE_COMPOUND*>( eshape.get() )->Shapes();
367 
368  for( const SHAPE* shape : shapes )
369  {
370  switch( shape->Type() )
371  {
372  case SH_RECT:
373  {
374  const SHAPE_RECT* rect = static_cast<const SHAPE_RECT*>( shape );
375  SHAPE_LINE_CHAIN outline = rect->Outline();
376 
377  for( int i = 0; i < outline.SegmentCount(); i++ )
378  {
379  const SEG& seg = outline.CSegment( i );
380  addAnchor( seg.A, OUTLINE | SNAPPABLE, aPad );
381  addAnchor( seg.Center(), OUTLINE | SNAPPABLE, aPad );
382  }
383 
384  break;
385  }
386 
387  case SH_SEGMENT:
388  {
389  const SHAPE_SEGMENT* segment = static_cast<const SHAPE_SEGMENT*>( shape );
390 
391  int offset = segment->GetWidth() / 2;
392  SEG seg = segment->GetSeg();
393  VECTOR2I normal = ( seg.B - seg.A ).Resize( offset ).Rotate( -M_PI_2 );
394 
395  /*
396  * TODO: This creates more snap points than necessary for rounded rect pads
397  * because they are built up of overlapping segments. We could fix this if
398  * desired by testing these to see if they are "inside" the pad.
399  */
400 
401  addAnchor( seg.A + normal, OUTLINE | SNAPPABLE, aPad );
402  addAnchor( seg.A - normal, OUTLINE | SNAPPABLE, aPad );
403  addAnchor( seg.B + normal, OUTLINE | SNAPPABLE, aPad );
404  addAnchor( seg.B - normal, OUTLINE | SNAPPABLE, aPad );
405  addAnchor( seg.Center() + normal, OUTLINE | SNAPPABLE, aPad );
406  addAnchor( seg.Center() - normal, OUTLINE | SNAPPABLE, aPad );
407 
408  normal = normal.Rotate( M_PI_2 );
409 
410  addAnchor( seg.A - normal, OUTLINE | SNAPPABLE, aPad );
411  addAnchor( seg.B + normal, OUTLINE | SNAPPABLE, aPad );
412  break;
413  }
414 
415  case SH_CIRCLE:
416  {
417  const SHAPE_CIRCLE* circle = static_cast<const SHAPE_CIRCLE*>( shape );
418 
419  int r = circle->GetRadius();
420  VECTOR2I start = circle->GetCenter();
421 
422  addAnchor( start + VECTOR2I( -r, 0 ), OUTLINE | SNAPPABLE, aPad );
423  addAnchor( start + VECTOR2I( r, 0 ), OUTLINE | SNAPPABLE, aPad );
424  addAnchor( start + VECTOR2I( 0, -r ), OUTLINE | SNAPPABLE, aPad );
425  addAnchor( start + VECTOR2I( 0, r ), OUTLINE | SNAPPABLE, aPad );
426  break;
427  }
428 
429  case SH_ARC:
430  {
431  const SHAPE_ARC* arc = static_cast<const SHAPE_ARC*>( shape );
432 
433  addAnchor( arc->GetP0(), OUTLINE | SNAPPABLE, aPad );
434  addAnchor( arc->GetP1(), OUTLINE | SNAPPABLE, aPad );
435  addAnchor( arc->GetArcMid(), OUTLINE | SNAPPABLE, aPad );
436  break;
437  }
438 
439  case SH_SIMPLE:
440  {
441  const SHAPE_SIMPLE* poly = static_cast<const SHAPE_SIMPLE*>( shape );
442 
443  for( size_t i = 0; i < poly->GetSegmentCount(); i++ )
444  {
445  const SEG& seg = poly->GetSegment( i );
446 
447  addAnchor( seg.A, OUTLINE | SNAPPABLE, aPad );
448  addAnchor( seg.Center(), OUTLINE | SNAPPABLE, aPad );
449 
450  if( i == poly->GetSegmentCount() - 1 )
451  addAnchor( seg.B, OUTLINE | SNAPPABLE, aPad );
452  }
453 
454  break;
455  }
456 
457  case SH_POLY_SET:
458  case SH_LINE_CHAIN:
459  case SH_COMPOUND:
461  case SH_NULL:
462  default:
463  break;
464  }
465  }
466  };
467 
468  switch( aItem->Type() )
469  {
470  case PCB_FOOTPRINT_T:
471  {
472  FOOTPRINT* footprint = static_cast<FOOTPRINT*>( aItem );
473 
474  for( PAD* pad : footprint->Pads() )
475  {
476  // Getting pads from the footprint requires re-checking that the pad is shown
478  && pad->GetBoundingBox().Contains( wxPoint( aRefPos.x, aRefPos.y ) )
479  && view->IsVisible( pad )
480  && ( !isHighContrast || activeLayers.count( pad->GetLayer() ) )
481  && pad->ViewGetLOD( pad->GetLayer(), view ) < view->GetScale() )
482  {
483  handlePadShape( pad );
484  break;
485  }
486  }
487 
488  // if the cursor is not over a pad, then drag the footprint by its origin
489  VECTOR2I position = footprint->GetPosition();
490  addAnchor( position, ORIGIN | SNAPPABLE, footprint );
491 
492  // Add the footprint center point if it is markedly different from the origin
493  VECTOR2I center = footprint->GetBoundingBox( false, false ).Centre();
494  VECTOR2I grid( GetGrid() );
495 
496  if( ( center - position ).SquaredEuclideanNorm() > grid.SquaredEuclideanNorm() )
497  addAnchor( center, ORIGIN | SNAPPABLE, footprint );
498 
499  break;
500  }
501 
502  case PCB_PAD_T:
503  {
505  {
506  PAD* pad = static_cast<PAD*>( aItem );
507  handlePadShape( pad );
508  }
509 
510  break;
511  }
512 
513  case PCB_FP_SHAPE_T:
514  case PCB_SHAPE_T:
515  {
517  break;
518 
519  PCB_SHAPE* shape = static_cast<PCB_SHAPE*>( aItem );
520  VECTOR2I start = shape->GetStart();
521  VECTOR2I end = shape->GetEnd();
522 
523  switch( shape->GetShape() )
524  {
525  case S_CIRCLE:
526  {
527  int r = ( start - end ).EuclideanNorm();
528 
529  addAnchor( start, ORIGIN | SNAPPABLE, shape );
530  addAnchor( start + VECTOR2I( -r, 0 ), OUTLINE | SNAPPABLE, shape );
531  addAnchor( start + VECTOR2I( r, 0 ), OUTLINE | SNAPPABLE, shape );
532  addAnchor( start + VECTOR2I( 0, -r ), OUTLINE | SNAPPABLE, shape );
533  addAnchor( start + VECTOR2I( 0, r ), OUTLINE | SNAPPABLE, shape );
534  break;
535  }
536 
537  case S_ARC:
538  addAnchor( shape->GetArcStart(), CORNER | SNAPPABLE, shape );
539  addAnchor( shape->GetArcEnd(), CORNER | SNAPPABLE, shape );
540  addAnchor( shape->GetArcMid(), CORNER | SNAPPABLE, shape );
541  addAnchor( shape->GetCenter(), ORIGIN | SNAPPABLE, shape );
542  break;
543 
544  case S_RECT:
545  {
546  VECTOR2I point2( end.x, start.y );
547  VECTOR2I point3( start.x, end.y );
548  SEG first( start, point2 );
549  SEG second( point2, end );
550  SEG third( end, point3 );
551  SEG fourth( point3, start );
552 
553  addAnchor( first.A, CORNER | SNAPPABLE, shape );
554  addAnchor( first.Center(), CORNER | SNAPPABLE, shape );
555  addAnchor( second.A, CORNER | SNAPPABLE, shape );
556  addAnchor( second.Center(), CORNER | SNAPPABLE, shape );
557  addAnchor( third.A, CORNER | SNAPPABLE, shape );
558  addAnchor( third.Center(), CORNER | SNAPPABLE, shape );
559  addAnchor( fourth.A, CORNER | SNAPPABLE, shape );
560  addAnchor( fourth.Center(), CORNER | SNAPPABLE, shape );
561  break;
562  }
563 
564  case S_SEGMENT:
565  addAnchor( start, CORNER | SNAPPABLE, shape );
566  addAnchor( end, CORNER | SNAPPABLE, shape );
567  addAnchor( shape->GetCenter(), CORNER | SNAPPABLE, shape );
568  break;
569 
570  case S_POLYGON:
571  for( const wxPoint& p : shape->BuildPolyPointsList() )
572  addAnchor( p, CORNER | SNAPPABLE, shape );
573 
574  break;
575 
576  case S_CURVE:
577  addAnchor( start, CORNER | SNAPPABLE, shape );
578  addAnchor( end, CORNER | SNAPPABLE, shape );
580 
581  default:
582  addAnchor( shape->GetStart(), ORIGIN | SNAPPABLE, shape );
583  break;
584  }
585  break;
586  }
587 
588  case PCB_TRACE_T:
589  case PCB_ARC_T:
590  {
592  {
593  TRACK* track = static_cast<TRACK*>( aItem );
594 
595  addAnchor( track->GetStart(), CORNER | SNAPPABLE, track );
596  addAnchor( track->GetEnd(), CORNER | SNAPPABLE, track );
597  addAnchor( track->GetCenter(), ORIGIN, track);
598  }
599 
600  break;
601  }
602 
603  case PCB_MARKER_T:
604  case PCB_TARGET_T:
605  addAnchor( aItem->GetPosition(), ORIGIN | CORNER | SNAPPABLE, aItem );
606  break;
607 
608  case PCB_VIA_T:
609  {
611  addAnchor( aItem->GetPosition(), ORIGIN | CORNER | SNAPPABLE, aItem );
612 
613  break;
614  }
615 
616  case PCB_ZONE_T:
617  {
618  const SHAPE_POLY_SET* outline = static_cast<const ZONE*>( aItem )->Outline();
619 
620  SHAPE_LINE_CHAIN lc;
621  lc.SetClosed( true );
622 
623  for( auto iter = outline->CIterateWithHoles(); iter; iter++ )
624  {
625  addAnchor( *iter, CORNER, aItem );
626  lc.Append( *iter );
627  }
628 
629  addAnchor( lc.NearestPoint( aRefPos ), OUTLINE, aItem );
630 
631  break;
632  }
633 
634  case PCB_DIM_ALIGNED_T:
636  {
637  const ALIGNED_DIMENSION* dim = static_cast<const ALIGNED_DIMENSION*>( aItem );
638  addAnchor( dim->GetCrossbarStart(), CORNER | SNAPPABLE, aItem );
639  addAnchor( dim->GetCrossbarEnd(), CORNER | SNAPPABLE, aItem );
640  addAnchor( dim->GetStart(), CORNER | SNAPPABLE, aItem );
641  addAnchor( dim->GetEnd(), CORNER | SNAPPABLE, aItem );
642  break;
643  }
644 
645  case PCB_DIM_CENTER_T:
646  {
647  const CENTER_DIMENSION* dim = static_cast<const CENTER_DIMENSION*>( aItem );
648  addAnchor( dim->GetStart(), CORNER | SNAPPABLE, aItem );
649  addAnchor( dim->GetEnd(), CORNER | SNAPPABLE, aItem );
650 
651  VECTOR2I start( dim->GetStart() );
652  VECTOR2I radial( dim->GetEnd() - dim->GetStart() );
653 
654  for( int i = 0; i < 2; i++ )
655  {
656  radial = radial.Rotate( DEG2RAD( 90 ) );
657  addAnchor( start + radial, CORNER | SNAPPABLE, aItem );
658  }
659 
660  break;
661  }
662 
663  case PCB_DIM_LEADER_T:
664  {
665  const LEADER* leader = static_cast<const LEADER*>( aItem );
666  addAnchor( leader->GetStart(), CORNER | SNAPPABLE, aItem );
667  addAnchor( leader->GetEnd(), CORNER | SNAPPABLE, aItem );
668  addAnchor( leader->Text().GetPosition(), CORNER | SNAPPABLE, aItem );
669  break;
670  }
671 
672  case PCB_FP_TEXT_T:
673  case PCB_TEXT_T:
674  addAnchor( aItem->GetPosition(), ORIGIN, aItem );
675  break;
676 
677  default:
678  break;
679  }
680 }
681 
682 
684  LSET aMatchLayers )
685 {
686  double minDist = std::numeric_limits<double>::max();
687  ANCHOR* best = NULL;
688 
689  for( ANCHOR& a : m_anchors )
690  {
691  BOARD_ITEM* item = static_cast<BOARD_ITEM*>( a.item );
692 
693  if( ( aMatchLayers & item->GetLayerSet() ) == 0 )
694  continue;
695 
696  if( ( aFlags & a.flags ) != aFlags )
697  continue;
698 
699  double dist = a.Distance( aPos );
700 
701  if( dist < minDist )
702  {
703  minDist = dist;
704  best = &a;
705  }
706  }
707 
708  return best;
709 }
double EuclideanNorm(const wxPoint &vector)
Euclidean norm of a 2D vector.
Definition: trigo.h:148
void SetPosition(const wxPoint &aPosition) override
compound shape, consisting of multiple simple shapes
Definition: shape.h:49
wxPoint GetArcEnd() const
Definition: pcb_shape.cpp:373
virtual const SEG GetSegment(int aIndex) const override
Definition: shape_simple.h:185
const std::set< unsigned int > GetHighContrastLayers() const
Returns the set of currently high-contrast layers.
KIGFX::VIEW * GetView() const
Definition: tool_manager.h:289
int Distance(const SEG &aSeg) const
Compute minimum Euclidean distance to segment aSeg.
Definition: seg.h:224
SHAPE_SIMPLE.
Definition: shape_simple.h:43
class ALIGNED_DIMENSION, a linear dimension (graphic item)
Definition: typeinfo.h:100
class LEADER, a leader dimension (graphic item)
Definition: typeinfo.h:101
wxPoint GetPosition() const override
ANCHOR * m_snapItem
Definition: grid_helper.h:137
class FP_TEXT, text in a footprint
Definition: typeinfo.h:92
void addAnchor(const VECTOR2I &aPos, int aFlags, EDA_ITEM *aItem)
Definition: grid_helper.h:106
const SHAPE_LINE_CHAIN Outline() const
Definition: shape_rect.h:170
int GetRadius() const
Definition: shape_circle.h:102
Container for all the knowledge about how graphical objects are drawn on any output surface/device.
const wxPoint & GetEnd() const
Function GetEnd returns the ending point of the graphic.
Definition: pcb_shape.h:156
A base class for any item which can be embedded within the BOARD container class, and therefore insta...
Definition: board_item.h:82
const wxPoint & GetStart() const
Definition: track.h:116
anchor of items having an anchor point (texts, footprints)
class CENTER_DIMENSION, a center point marking (graphic item)
Definition: typeinfo.h:102
TOOL_MANAGER * m_toolMgr
Definition: grid_helper.h:129
#define M_PI_2
Definition: transline.cpp:37
KIGFX::ORIGIN_VIEWITEM m_viewAxis
Definition: grid_helper.h:143
VECTOR2I GetOrigin() const
Definition: grid_helper.cpp:59
virtual const wxPoint & GetStart() const
The dimension's origin is the first feature point for the dimension.
Definition: dimension.h:121
polygon (not yet used for tracks, but could be in microwave apps)
Definition: board_item.h:54
CONST_ITERATOR CIterateWithHoles(int aOutline) const
const COLOR4D & GetLayerColor(int aLayer) const
Return the color used to draw a layer.
class PCB_TEXT, text on a layer
Definition: typeinfo.h:91
class ARC, an arc track segment on a copper layer
Definition: typeinfo.h:97
COLOR4D WithAlpha(double aAlpha) const
Return a color with the same color, but the given alpha.
Definition: color4d.h:300
usual segment : line with rounded ends
Definition: board_item.h:50
GAL * GetGAL() const
Return the #GAL this view is using to draw graphical primitives.
Definition: view.h:189
MAGNETIC_SETTINGS * m_magneticSettings
extended_type SquaredEuclideanNorm() const
Compute the squared euclidean norm of the vector, which is defined as (x ** 2 + y ** 2).
Definition: vector2d.h:300
Arcs (with rounded ends)
Definition: board_item.h:52
class FP_SHAPE, a footprint edge
Definition: typeinfo.h:93
class PAD, a pad in a footprint
Definition: typeinfo.h:89
#define KI_FALLTHROUGH
The KI_FALLTHROUGH macro is to be used when switch statement cases should purposely fallthrough from ...
Definition: macros.h:83
OPT_VECTOR2I IntersectLines(const SEG &aSeg) const
Compute the intersection point of lines passing through ends of (this) and aSeg.
Definition: seg.h:193
void SetEndPosition(const VECTOR2D &aPosition)
const VECTOR2I GetCenter() const
Definition: shape_circle.h:107
VECTOR2I Center() const
Definition: seg.h:376
virtual wxPoint GetPosition() const
Definition: eda_item.h:301
std::set< BOARD_ITEM * > queryVisible(const BOX2I &aArea, const std::vector< BOARD_ITEM * > &aSkip) const
segment with non rounded ends
Definition: board_item.h:51
VECTOR2< int > VECTOR2I
Definition: vector2d.h:623
const wxPoint & GetCrossbarStart() const
Definition: dimension.h:362
PAINTER * GetPainter() const
Return the painter object used by the view for drawing #VIEW_ITEMS.
Definition: view.h:207
const SEG & GetSeg() const
class TRACK, a track segment (segment on a copper layer)
Definition: typeinfo.h:95
void Append(int aX, int aY, bool aAllowDuplication=false)
Function Append()
PADS & Pads()
Definition: footprint.h:164
const wxPoint & GetCrossbarEnd() const
Definition: dimension.h:364
const VECTOR2I NearestPoint(const VECTOR2I &aP, bool aAllowInternalShapePoints=true) const
Finds a point on the line chain that is closest to point aP.
This file contains miscellaneous commonly used macros and functions.
wxPoint GetArcStart() const
Definition: pcb_shape.h:179
VECTOR2I GetGrid() const
Definition: grid_helper.cpp:51
KIGFX::ORIGIN_VIEWITEM m_viewSnapPoint
Definition: grid_helper.h:141
Master controller class:
Definition: tool_manager.h:52
VECTOR2I AlignToArc(const VECTOR2I &aPoint, const SHAPE_ARC &aSeg)
const std::vector< wxPoint > BuildPolyPointsList() const
Build and return the list of corners in a std::vector<wxPoint> It must be used only to convert the SH...
Definition: pcb_shape.cpp:1206
ANCHOR * nearestAnchor(const VECTOR2I &aPos, int aFlags, LSET aMatchLayers)
void SetClosed(bool aClosed)
Function SetClosed()
PCB_GRID_HELPER(TOOL_MANAGER *aToolMgr, MAGNETIC_SETTINGS *aMagneticSettings)
void computeAnchors(BOARD_ITEM *aItem, const VECTOR2I &aRefPos, bool aFrom=false)
computeAnchors inserts the local anchor points in to the grid helper for the specified board item,...
LSET is a set of PCB_LAYER_IDs.
Auxiliary items (guides, rule, etc)
VECTOR2I BestSnapAnchor(const VECTOR2I &aOrigin, BOARD_ITEM *aReferenceItem)
Chooses the "best" snap anchor around the given point, optionally taking layers from the reference it...
#define NULL
virtual wxPoint GetPosition() const override
Definition: pcb_text.h:72
OPT< VECTOR2I > OPT_VECTOR2I
Definition: seg.h:39
double Distance(const VECTOR2I &aP) const
Definition: grid_helper.h:100
A leader is a dimension-like object pointing to a specific point.
Definition: dimension.h:476
bool IsVisible(const VIEW_ITEM *aItem) const
Return information if the item is visible (or not).
Definition: view.cpp:1494
Represent a set of closed polygons.
SHAPE_LINE_CHAIN & Outline(int aIndex)
void SetSize(int aSize)
const VECTOR2I & GetP0() const
Definition: shape_arc.h:95
PCB_TEXT & Text()
Definition: dimension.h:209
wxPoint GetCenter() const override
This defaults to the center of the bounding box if not overridden.
Definition: pcb_shape.cpp:341
const wxPoint & GetStart() const
Function GetStart returns the starting point of the graphic.
Definition: pcb_shape.h:145
void SetDrawAtZero(bool aDrawFlag)
Set the draw at zero flag.
const VECTOR2I & GetArcMid() const
Definition: shape_arc.h:97
circular arc
Definition: shape.h:50
virtual wxPoint GetCenter() const
This defaults to the center of the bounding box if not overridden.
Definition: board_item.h:114
static LSET AllLayersMask()
Definition: lset.cpp:787
VECTOR2I BestDragOrigin(const VECTOR2I &aMousePos, std::vector< BOARD_ITEM * > &aItem)
class ZONE, a copper pour area
Definition: typeinfo.h:105
An abstract shape on 2D plane.
Definition: shape.h:116
bool m_enableSnap
Definition: grid_helper.h:134
TOOL_BASE * GetCurrentTool() const
Return the tool that is on the top of the active tools stack (was invoked the most recently).
Definition: tool_manager.h:319
bool m_enableSnapLine
Definition: grid_helper.h:136
int SegmentCount() const
Function SegmentCount()
circle
Definition: shape.h:46
class PCB_TARGET, a target (graphic item)
Definition: typeinfo.h:104
class FOOTPRINT, a footprint
Definition: typeinfo.h:88
Definition: seg.h:41
virtual size_t GetSegmentCount() const override
Definition: shape_simple.h:187
virtual VECTOR2I Align(const VECTOR2I &aPoint) const
Definition: grid_helper.cpp:95
bool GetHighContrast() const
virtual RENDER_SETTINGS * GetSettings()=0
Return a pointer to current settings that are going to be used when drawing items.
VECTOR2< T > Rotate(double aAngle) const
Rotate the vector by a given angle.
Definition: vector2d.h:371
set of polygons (with holes, etc.)
Definition: shape.h:48
class MARKER_PCB, a marker used to show something
Definition: typeinfo.h:98
a single triangle belonging to a POLY_SET triangulation
Definition: shape.h:52
const SEG CSegment(int aIndex) const
Function CSegment()
double DEG2RAD(double deg)
Definition: trigo.h:231
SHAPE_LINE_CHAIN.
const EDA_RECT GetBoundingBox() const override
Return the orthogonal bounding box of this object for display purposes.
Definition: footprint.cpp:630
std::pair< VIEW_ITEM *, int > LAYER_ITEM_PAIR
Definition: view.h:72
VECTOR2I A
Definition: seg.h:49
MAGNETIC_OPTIONS pads
empty shape (no shape...),
Definition: shape.h:51
VECTOR2I m_skipPoint
Definition: grid_helper.h:139
constexpr ret_type KiROUND(fp_type v)
Round a floating point number to an integer using "round halfway cases away from zero".
Definition: util.h:68
void SetColor(const KIGFX::COLOR4D &aColor)
line chain (polyline)
Definition: shape.h:45
wxPoint GetPosition() const override
Definition: footprint.h:182
wxPoint Centre() const
Definition: eda_rect.h:60
const wxPoint & GetEnd() const
Definition: track.h:113
void SetVisible(VIEW_ITEM *aItem, bool aIsVisible=true)
Set the item visibility.
Definition: view.cpp:1454
ring
Definition: board_item.h:53
BOARD_ITEM * GetSnapped() const
Function GetSnapped If the PCB_GRID_HELPER has highlighted a snap point (target shown),...
class ORTHOGONAL_DIMENSION, a linear dimension constrained to x/y
Definition: typeinfo.h:103
class VIA, a via (like a track segment on a copper layer)
Definition: typeinfo.h:96
wxPoint GetArcMid() const
Definition: pcb_shape.cpp:391
virtual void Add(VIEW_ITEM *aItem, int aDrawPriority=-1)
Add a VIEW_ITEM to the view.
Definition: view.cpp:321
axis-aligned rectangle
Definition: shape.h:43
PCB_SHAPE_TYPE_T GetShape() const
Definition: pcb_shape.h:130
virtual int Query(const BOX2I &aRect, std::vector< LAYER_ITEM_PAIR > &aResult) const
Find all visible items that touch or are within the rectangle aRect.
Definition: view.cpp:427
KIGFX::ORIGIN_VIEWITEM m_viewSnapLine
Definition: grid_helper.h:142
Hold a (potentially large) number of VIEW_ITEMs and renders them on a graphics device provided by the...
Definition: view.h:67
Definition: pad.h:60
void SetStyle(MARKER_STYLE aStyle)
double GetScale() const
Definition: view.h:263
For better understanding of the points that make a dimension:
Definition: dimension.h:333
double GetWorldScale() const
Get the world scale.
std::vector< ANCHOR > m_anchors
Definition: grid_helper.h:127
int GetWidth() const
class PCB_SHAPE, a segment not on copper layers
Definition: typeinfo.h:90
Bezier Curve.
Definition: board_item.h:55
virtual const wxPoint & GetEnd() const
Definition: dimension.h:124
simple polygon
Definition: shape.h:47
const VECTOR2I & GetP1() const
Definition: shape_arc.h:96
VECTOR2I AlignToSegment(const VECTOR2I &aPoint, const SEG &aSeg)
Definition: track.h:83
void clearAnchors()
Definition: grid_helper.h:112
virtual double ViewGetLOD(int aLayer, VIEW *aView) const
Return the level of detail (LOD) of the item.
Definition: view_item.h:137
virtual LSET GetLayerSet() const
Return a std::bitset of all layers on which the item physically resides.
Definition: board_item.h:178
virtual void Update(const VIEW_ITEM *aItem, int aUpdateFlags) const
For dynamic VIEWs, inform the associated VIEW that the graphical representation of this item has chan...
Definition: view.cpp:1508
MAGNETIC_OPTIONS tracks
KICAD_T Type() const
Returns the type of object.
Definition: eda_item.h:162
line segment
Definition: shape.h:44
Position or shape has changed.
Definition: view_item.h:54
A color representation with 4 components: red, green, blue, alpha.
Definition: color4d.h:98
VECTOR2I B
Definition: seg.h:50
Marks the center of a circle or arc with a cross shape The size and orientation of the cross is adjus...
Definition: dimension.h:515