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 <pcb_dimension.h>
29 #include <fp_shape.h>
30 #include <footprint.h>
31 #include <pad.h>
32 #include <pcb_group.h>
33 #include <pcb_track.h>
34 #include <zone.h>
35 #include <geometry/shape_circle.h>
37 #include <geometry/shape_rect.h>
38 #include <geometry/shape_segment.h>
39 #include <geometry/shape_simple.h>
40 #include <macros.h>
41 #include <math/util.h> // for KiROUND
42 #include <painter.h>
43 #include <pcbnew_settings.h>
44 #include <tool/tool_manager.h>
45 #include <tools/pcb_tool_base.h>
46 #include <view/view.h>
47 #include "pcb_grid_helper.h"
48 
49 
51  GRID_HELPER( aToolMgr ),
52  m_magneticSettings( aMagneticSettings )
53 {
54  KIGFX::VIEW* view = m_toolMgr->GetView();
55  KIGFX::RENDER_SETTINGS* settings = view->GetPainter()->GetSettings();
56  KIGFX::COLOR4D auxItemsColor = settings->GetLayerColor( LAYER_AUX_ITEMS );
57  KIGFX::COLOR4D umbilicalColor = settings->GetLayerColor( LAYER_ANCHOR );
58 
59  m_viewAxis.SetSize( 20000 );
61  m_viewAxis.SetColor( auxItemsColor.WithAlpha( 0.4 ) );
62  m_viewAxis.SetDrawAtZero( true );
63  view->Add( &m_viewAxis );
64  view->SetVisible( &m_viewAxis, false );
65 
67  m_viewSnapPoint.SetColor( auxItemsColor );
69  view->Add( &m_viewSnapPoint );
70  view->SetVisible( &m_viewSnapPoint, false );
71 
73  m_viewSnapLine.SetColor( umbilicalColor );
75  view->Add( &m_viewSnapLine );
76  view->SetVisible( &m_viewSnapLine, false );
77 }
78 
79 
81 {
82  OPT_VECTOR2I pts[6];
83 
84  const int c_gridSnapEpsilon = 2;
85 
86  if( !m_enableSnap )
87  return aPoint;
88 
89  VECTOR2I nearest = Align( aPoint );
90 
91  pts[0] = aSeg.A;
92  pts[1] = aSeg.B;
93  pts[2] = aSeg.IntersectLines( SEG( nearest + VECTOR2I( -1, 1 ), nearest + VECTOR2I( 1, -1 ) ) );
94  pts[3] = aSeg.IntersectLines( SEG( nearest + VECTOR2I( -1, -1 ), nearest + VECTOR2I( 1, 1 ) ) );
95 
96  int min_d = std::numeric_limits<int>::max();
97 
98  for( int i = 0; i < 4; i++ )
99  {
100  if( pts[i] && aSeg.Distance( *pts[i] ) <= c_gridSnapEpsilon )
101  {
102  int d = (*pts[i] - aPoint).EuclideanNorm();
103 
104  if( d < min_d )
105  {
106  min_d = d;
107  nearest = *pts[i];
108  }
109  }
110  }
111 
112  return nearest;
113 }
114 
115 
117 {
118  if( !m_enableSnap )
119  return aPoint;
120 
121  const VECTOR2D gridOffset( GetOrigin() );
122  const VECTOR2D gridSize( GetGrid() );
123 
124  VECTOR2I nearest( KiROUND( ( aPoint.x - gridOffset.x ) / gridSize.x ) * gridSize.x + gridOffset.x,
125  KiROUND( ( aPoint.y - gridOffset.y ) / gridSize.y ) * gridSize.y + gridOffset.y );
126 
127  int min_d = std::numeric_limits<int>::max();
128 
129  for( auto pt : { aArc.GetP0(), aArc.GetP1() } )
130  {
131  int d = ( pt - aPoint ).EuclideanNorm();
132 
133  if( d < min_d )
134  {
135  min_d = d;
136  nearest = pt;
137  }
138  else
139  break;
140  }
141 
142  return nearest;
143 }
144 
145 
147  std::vector<BOARD_ITEM*>& aItems )
148 {
149  clearAnchors();
150 
151  for( BOARD_ITEM* item : aItems )
152  computeAnchors( item, aMousePos, true );
153 
154  double worldScale = m_toolMgr->GetView()->GetGAL()->GetWorldScale();
155  double lineSnapMinCornerDistance = 50.0 / worldScale;
156 
157  ANCHOR* nearestOutline = nearestAnchor( aMousePos, OUTLINE, LSET::AllLayersMask() );
158  ANCHOR* nearestCorner = nearestAnchor( aMousePos, CORNER, LSET::AllLayersMask() );
159  ANCHOR* nearestOrigin = nearestAnchor( aMousePos, ORIGIN, LSET::AllLayersMask() );
160  ANCHOR* best = NULL;
161  double minDist = std::numeric_limits<double>::max();
162 
163  if( nearestOrigin )
164  {
165  minDist = nearestOrigin->Distance( aMousePos );
166  best = nearestOrigin;
167  }
168 
169  if( nearestCorner )
170  {
171  double dist = nearestCorner->Distance( aMousePos );
172 
173  if( dist < minDist )
174  {
175  minDist = dist;
176  best = nearestCorner;
177  }
178  }
179 
180  if( nearestOutline )
181  {
182  double dist = nearestOutline->Distance( aMousePos );
183 
184  if( minDist > lineSnapMinCornerDistance && dist < minDist )
185  best = nearestOutline;
186  }
187 
188  return best ? best->pos : aMousePos;
189 }
190 
191 
193 {
194  LSET layers;
195  std::vector<BOARD_ITEM*> item;
196 
197  if( aReferenceItem )
198  {
199  layers = aReferenceItem->GetLayerSet();
200  item.push_back( aReferenceItem );
201  }
202  else
203  {
204  layers = LSET::AllLayersMask();
205  }
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  {
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 PCB_SHAPE_TYPE::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 
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 
565  addAnchor( start, CORNER | SNAPPABLE, shape );
566  addAnchor( end, CORNER | SNAPPABLE, shape );
567  addAnchor( shape->GetCenter(), CORNER | SNAPPABLE, shape );
568  break;
569 
571  {
572  SHAPE_LINE_CHAIN lc;
573  lc.SetClosed( true );
574 
575  for( const wxPoint& p : shape->BuildPolyPointsList() )
576  {
577  addAnchor( p, CORNER | SNAPPABLE, shape );
578  lc.Append( p );
579  }
580 
581  addAnchor( lc.NearestPoint( aRefPos ), OUTLINE, aItem );
582  break;
583  }
584 
586  addAnchor( start, CORNER | SNAPPABLE, shape );
587  addAnchor( end, CORNER | SNAPPABLE, shape );
589 
590  default:
591  addAnchor( shape->GetStart(), ORIGIN | SNAPPABLE, shape );
592  break;
593  }
594  break;
595  }
596 
597  case PCB_TRACE_T:
598  case PCB_ARC_T:
599  {
601  {
602  PCB_TRACK* track = static_cast<PCB_TRACK*>( aItem );
603 
604  addAnchor( track->GetStart(), CORNER | SNAPPABLE, track );
605  addAnchor( track->GetEnd(), CORNER | SNAPPABLE, track );
606  addAnchor( track->GetCenter(), ORIGIN, track);
607  }
608 
609  break;
610  }
611 
612  case PCB_MARKER_T:
613  case PCB_TARGET_T:
614  addAnchor( aItem->GetPosition(), ORIGIN | CORNER | SNAPPABLE, aItem );
615  break;
616 
617  case PCB_VIA_T:
618  {
620  addAnchor( aItem->GetPosition(), ORIGIN | CORNER | SNAPPABLE, aItem );
621 
622  break;
623  }
624 
625  case PCB_ZONE_T:
626  {
627  const SHAPE_POLY_SET* outline = static_cast<const ZONE*>( aItem )->Outline();
628 
629  SHAPE_LINE_CHAIN lc;
630  lc.SetClosed( true );
631 
632  for( auto iter = outline->CIterateWithHoles(); iter; iter++ )
633  {
634  addAnchor( *iter, CORNER, aItem );
635  lc.Append( *iter );
636  }
637 
638  addAnchor( lc.NearestPoint( aRefPos ), OUTLINE, aItem );
639 
640  break;
641  }
642 
643  case PCB_DIM_ALIGNED_T:
645  {
646  const PCB_DIM_ALIGNED* dim = static_cast<const PCB_DIM_ALIGNED*>( aItem );
647  addAnchor( dim->GetCrossbarStart(), CORNER | SNAPPABLE, aItem );
648  addAnchor( dim->GetCrossbarEnd(), CORNER | SNAPPABLE, aItem );
649  addAnchor( dim->GetStart(), CORNER | SNAPPABLE, aItem );
650  addAnchor( dim->GetEnd(), CORNER | SNAPPABLE, aItem );
651  break;
652  }
653 
654  case PCB_DIM_CENTER_T:
655  {
656  const PCB_DIM_CENTER* dim = static_cast<const PCB_DIM_CENTER*>( aItem );
657  addAnchor( dim->GetStart(), CORNER | SNAPPABLE, aItem );
658  addAnchor( dim->GetEnd(), CORNER | SNAPPABLE, aItem );
659 
660  VECTOR2I start( dim->GetStart() );
661  VECTOR2I radial( dim->GetEnd() - dim->GetStart() );
662 
663  for( int i = 0; i < 2; i++ )
664  {
665  radial = radial.Rotate( DEG2RAD( 90 ) );
666  addAnchor( start + radial, CORNER | SNAPPABLE, aItem );
667  }
668 
669  break;
670  }
671 
672  case PCB_DIM_LEADER_T:
673  {
674  const PCB_DIM_LEADER* leader = static_cast<const PCB_DIM_LEADER*>( aItem );
675  addAnchor( leader->GetStart(), CORNER | SNAPPABLE, aItem );
676  addAnchor( leader->GetEnd(), CORNER | SNAPPABLE, aItem );
677  addAnchor( leader->Text().GetPosition(), CORNER | SNAPPABLE, aItem );
678  break;
679  }
680 
681  case PCB_FP_TEXT_T:
682  case PCB_TEXT_T:
683  addAnchor( aItem->GetPosition(), ORIGIN, aItem );
684  break;
685 
686  case PCB_GROUP_T:
687  {
688  const PCB_GROUP* group = static_cast<const PCB_GROUP*>( aItem );
689 
690  for( BOARD_ITEM* item : group->GetItems() )
691  computeAnchors( item, aRefPos, aFrom );
692 
693  break;
694  }
695 
696  default:
697  break;
698  }
699 }
700 
701 
703  LSET aMatchLayers )
704 {
705  double minDist = std::numeric_limits<double>::max();
706  ANCHOR* best = NULL;
707 
708  for( ANCHOR& a : m_anchors )
709  {
710  BOARD_ITEM* item = static_cast<BOARD_ITEM*>( a.item );
711 
712  if( ( aMatchLayers & item->GetLayerSet() ) == 0 )
713  continue;
714 
715  if( ( aFlags & a.flags ) != aFlags )
716  continue;
717 
718  double dist = a.Distance( aPos );
719 
720  if( dist < minDist )
721  {
722  minDist = dist;
723  best = &a;
724  }
725  }
726 
727  return best;
728 }
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:376
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:283
int Distance(const SEG &aSeg) const
Compute minimum Euclidean distance to segment aSeg.
Definition: seg.cpp:285
SHAPE_SIMPLE.
Definition: shape_simple.h:43
class PCB_DIM_ALIGNED, a linear dimension (graphic item)
Definition: typeinfo.h:100
class PCB_DIM_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
const wxPoint & GetCrossbarStart() const
int GetRadius() const
Definition: shape_circle.h:107
Container for all the knowledge about how graphical objects are drawn on any output surface/device.
const wxPoint & GetEnd() const
Definition: pcb_track.h:105
const wxPoint & GetEnd() const
Return the ending point of the graphic.
Definition: pcb_shape.h:134
A base class for any item which can be embedded within the BOARD container class, and therefore insta...
Definition: board_item.h:80
class PCB_GROUP, a set of BOARD_ITEMs
Definition: typeinfo.h:108
A set of BOARD_ITEMs (i.e., without duplicates).
Definition: pcb_group.h:50
PCB_TEXT & Text()
anchor of items having an anchor point (texts, footprints)
PCB_SHAPE_TYPE GetShape() const
Definition: pcb_shape.h:110
class PCB_DIM_CENTER, 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:40
KIGFX::ORIGIN_VIEWITEM m_viewAxis
Definition: grid_helper.h:143
VECTOR2I GetOrigin() const
Definition: grid_helper.cpp:59
const wxPoint & GetCrossbarEnd() const
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 PCB_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:305
GAL * GetGAL() const
Return the #GAL this view is using to draw graphical primitives.
Definition: view.h:189
MAGNETIC_SETTINGS * m_magneticSettings
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:209
void SetEndPosition(const VECTOR2D &aPosition)
const VECTOR2I GetCenter() const
Definition: shape_circle.h:112
VECTOR2I Center() const
Definition: seg.h:386
virtual wxPoint GetPosition() const
Definition: eda_item.h:252
std::set< BOARD_ITEM * > queryVisible(const BOX2I &aArea, const std::vector< BOARD_ITEM * > &aSkip) const
VECTOR2< int > VECTOR2I
Definition: vector2d.h:623
PAINTER * GetPainter() const
Return the painter object used by the view for drawing #VIEW_ITEMS.
Definition: view.h:207
const SEG & GetSeg() const
class PCB_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:159
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:157
For better understanding of the points that make a dimension:
VECTOR2I GetGrid() const
Definition: grid_helper.cpp:51
polygon (not yet used for tracks, but could be in microwave apps)
KIGFX::ORIGIN_VIEWITEM m_viewSnapPoint
Definition: grid_helper.h:141
Master controller class:
Definition: tool_manager.h:54
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>
Definition: pcb_shape.cpp:1225
ANCHOR * nearestAnchor(const VECTOR2I &aPos, int aFlags, LSET aMatchLayers)
virtual const wxPoint & GetStart() const
The dimension's origin is the first feature point for the dimension.
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:38
double Distance(const VECTOR2I &aP) const
Definition: grid_helper.h:100
bool IsVisible(const VIEW_ITEM *aItem) const
Return information if the item is visible (or not).
Definition: view.cpp:1490
Represent a set of closed polygons.
SHAPE_LINE_CHAIN & Outline(int aIndex)
void SetSize(int aSize)
segment with non rounded ends
const VECTOR2I & GetP0() const
Definition: shape_arc.h:95
wxPoint GetCenter() const override
This defaults to the center of the bounding box if not overridden.
Definition: pcb_shape.cpp:344
const wxPoint & GetStart() const
Return the starting point of the graphic.
Definition: pcb_shape.h:124
Mark the center of a circle or arc with a cross shape.
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:112
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:313
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:40
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 PCB_MARKER, 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:635
std::pair< VIEW_ITEM *, int > LAYER_ITEM_PAIR
Definition: view.h:72
VECTOR2I A
Definition: seg.h:48
MAGNETIC_OPTIONS pads
empty shape (no shape...),
Definition: shape.h:51
VECTOR2I m_skipPoint
Definition: grid_helper.h:139
usual segment : line with rounded ends
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:70
void SetColor(const KIGFX::COLOR4D &aColor)
line chain (polyline)
Definition: shape.h:45
wxPoint GetPosition() const override
Definition: footprint.h:177
wxPoint Centre() const
Definition: eda_rect.h:55
void SetVisible(VIEW_ITEM *aItem, bool aIsVisible=true)
Set the item visibility.
Definition: view.cpp:1450
BOARD_ITEM * GetSnapped() const
Function GetSnapped If the PCB_GRID_HELPER has highlighted a snap point (target shown),...
A leader is a dimension-like object pointing to a specific point.
class PCB_DIM_ORTHOGONAL, a linear dimension constrained to x/y
Definition: typeinfo.h:103
class PCB_VIA, a via (like a track segment on a copper layer)
Definition: typeinfo.h:96
wxPoint GetArcMid() const
Definition: pcb_shape.cpp:394
virtual const wxPoint & GetEnd() const
virtual void Add(VIEW_ITEM *aItem, int aDrawPriority=-1)
Add a VIEW_ITEM to the view.
Definition: view.cpp:322
axis-aligned rectangle
Definition: shape.h:43
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:428
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:57
void SetStyle(MARKER_STYLE aStyle)
double GetScale() const
Definition: view.h:263
Arcs (with rounded ends)
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
simple polygon
Definition: shape.h:47
const VECTOR2I & GetP1() const
Definition: shape_arc.h:96
VECTOR2I AlignToSegment(const VECTOR2I &aPoint, const SEG &aSeg)
void clearAnchors()
Definition: grid_helper.h:112
const wxPoint & GetStart() const
Definition: pcb_track.h:108
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:176
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:1504
MAGNETIC_OPTIONS tracks
KICAD_T Type() const
Returns the type of object.
Definition: eda_item.h:113
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:103
VECTOR2I B
Definition: seg.h:49