KiCad PCB EDA Suite
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-2020 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 using namespace std::placeholders;
28 
29 #include <class_board.h>
30 #include <class_dimension.h>
31 #include <fp_shape.h>
32 #include <class_module.h>
33 #include <class_track.h>
34 #include <class_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 <math/vector2d.h>
43 #include <painter.h>
44 #include <pcbnew_settings.h>
45 #include <tool/tool_manager.h>
46 #include <view/view.h>
47 #include <view/view_controls.h>
48 
49 #include "grid_helper.h"
50 
51 
52 GRID_HELPER::GRID_HELPER( TOOL_MANAGER* aToolMgr, MAGNETIC_SETTINGS* aMagneticSettings ) :
53  m_toolMgr( aToolMgr ),
54  m_magneticSettings( aMagneticSettings )
55 {
56  m_enableSnap = true;
57  m_enableGrid = true;
58  m_enableSnapLine = true;
59  m_snapItem = nullptr;
60  KIGFX::VIEW* view = m_toolMgr->GetView();
61 
62  m_viewAxis.SetSize( 20000 );
64  m_viewAxis.SetColor( COLOR4D( 1.0, 1.0, 1.0, 0.4 ) );
65  m_viewAxis.SetDrawAtZero( true );
66  view->Add( &m_viewAxis );
67  view->SetVisible( &m_viewAxis, false );
68 
70  m_viewSnapPoint.SetColor( COLOR4D( 1.0, 1.0, 1.0, 1.0 ) );
72  view->Add( &m_viewSnapPoint );
73  view->SetVisible( &m_viewSnapPoint, false );
74 
76  m_viewSnapLine.SetColor( COLOR4D( 0.33, 0.55, 0.95, 1.0 ) );
78  view->Add( &m_viewSnapLine );
79  view->SetVisible( &m_viewSnapLine, false );
80 }
81 
82 
84 {
85 }
86 
87 
89 {
91 
92  return VECTOR2I( KiROUND( size.x ), KiROUND( size.y ) );
93 }
94 
95 
97 {
98  VECTOR2D origin = m_toolMgr->GetView()->GetGAL()->GetGridOrigin();
99 
100  return VECTOR2I( origin );
101 }
102 
103 
104 void GRID_HELPER::SetAuxAxes( bool aEnable, const VECTOR2I& aOrigin )
105 {
106  if( aEnable )
107  {
108  m_auxAxis = aOrigin;
109  m_viewAxis.SetPosition( wxPoint( aOrigin ) );
110  m_toolMgr->GetView()->SetVisible( &m_viewAxis, true );
111  }
112  else
113  {
115  m_toolMgr->GetView()->SetVisible( &m_viewAxis, false );
116  }
117 }
118 
119 
120 VECTOR2I GRID_HELPER::Align( const VECTOR2I& aPoint ) const
121 {
122  if( !m_enableGrid )
123  return aPoint;
124 
125  const VECTOR2D gridOffset( GetOrigin() );
126  const VECTOR2D grid( GetGrid() );
127 
128  VECTOR2I nearest( KiROUND( ( aPoint.x - gridOffset.x ) / grid.x ) * grid.x + gridOffset.x,
129  KiROUND( ( aPoint.y - gridOffset.y ) / grid.y ) * grid.y + gridOffset.y );
130 
131  if( !m_auxAxis )
132  return nearest;
133 
134  if( std::abs( m_auxAxis->x - aPoint.x ) < std::abs( nearest.x - aPoint.x ) )
135  nearest.x = m_auxAxis->x;
136 
137  if( std::abs( m_auxAxis->y - aPoint.y ) < std::abs( nearest.y - aPoint.y ) )
138  nearest.y = m_auxAxis->y;
139 
140  return nearest;
141 }
142 
143 
144 VECTOR2I GRID_HELPER::AlignToSegment( const VECTOR2I& aPoint, const SEG& aSeg )
145 {
146  OPT_VECTOR2I pts[6];
147 
148  if( !m_enableSnap )
149  return aPoint;
150 
151  const VECTOR2D gridOffset( GetOrigin() );
152  const VECTOR2D gridSize( GetGrid() );
153 
154  VECTOR2I nearest( KiROUND( ( aPoint.x - gridOffset.x ) / gridSize.x ) * gridSize.x + gridOffset.x,
155  KiROUND( ( aPoint.y - gridOffset.y ) / gridSize.y ) * gridSize.y + gridOffset.y );
156 
157  pts[0] = aSeg.A;
158  pts[1] = aSeg.B;
159  pts[2] = aSeg.IntersectLines( SEG( nearest + VECTOR2I( -1, 1 ), nearest + VECTOR2I( 1, -1 ) ) );
160  pts[3] = aSeg.IntersectLines( SEG( nearest + VECTOR2I( -1, -1 ), nearest + VECTOR2I( 1, 1 ) ) );
161 
162  int min_d = std::numeric_limits<int>::max();
163 
164  for( int i = 0; i < 4; i++ )
165  {
166  if( pts[i] && aSeg.Contains( *pts[i] ) )
167  {
168  int d = (*pts[i] - aPoint).EuclideanNorm();
169 
170  if( d < min_d )
171  {
172  min_d = d;
173  nearest = *pts[i];
174  }
175  }
176  }
177 
178  return nearest;
179 }
180 
181 
182 VECTOR2I GRID_HELPER::AlignToArc( const VECTOR2I& aPoint, const SHAPE_ARC& aArc )
183 {
184  if( !m_enableSnap )
185  return aPoint;
186 
187  const VECTOR2D gridOffset( GetOrigin() );
188  const VECTOR2D gridSize( GetGrid() );
189 
190  VECTOR2I nearest( KiROUND( ( aPoint.x - gridOffset.x ) / gridSize.x ) * gridSize.x + gridOffset.x,
191  KiROUND( ( aPoint.y - gridOffset.y ) / gridSize.y ) * gridSize.y + gridOffset.y );
192 
193  int min_d = std::numeric_limits<int>::max();
194 
195  for( auto pt : { aArc.GetP0(), aArc.GetP1() } )
196  {
197  int d = ( pt - aPoint ).EuclideanNorm();
198 
199  if( d < min_d )
200  {
201  min_d = d;
202  nearest = pt;
203  }
204  else
205  break;
206  }
207 
208  return nearest;
209 }
210 
211 
212 VECTOR2I GRID_HELPER::BestDragOrigin( const VECTOR2I &aMousePos, std::vector<BOARD_ITEM*>& aItems )
213 {
214  clearAnchors();
215 
216  for( BOARD_ITEM* item : aItems )
217  computeAnchors( item, aMousePos, true );
218 
219  double worldScale = m_toolMgr->GetView()->GetGAL()->GetWorldScale();
220  double lineSnapMinCornerDistance = 50.0 / worldScale;
221 
222  ANCHOR* nearestOutline = nearestAnchor( aMousePos, OUTLINE, LSET::AllLayersMask() );
223  ANCHOR* nearestCorner = nearestAnchor( aMousePos, CORNER, LSET::AllLayersMask() );
224  ANCHOR* nearestOrigin = nearestAnchor( aMousePos, ORIGIN, LSET::AllLayersMask() );
225  ANCHOR* best = NULL;
226  double minDist = std::numeric_limits<double>::max();
227 
228  if( nearestOrigin )
229  {
230  minDist = nearestOrigin->Distance( aMousePos );
231  best = nearestOrigin;
232  }
233 
234  if( nearestCorner )
235  {
236  double dist = nearestCorner->Distance( aMousePos );
237 
238  if( dist < minDist )
239  {
240  minDist = dist;
241  best = nearestCorner;
242  }
243  }
244 
245  if( nearestOutline )
246  {
247  double dist = nearestOutline->Distance( aMousePos );
248 
249  if( minDist > lineSnapMinCornerDistance && dist < minDist )
250  best = nearestOutline;
251  }
252 
253  return best ? best->pos : aMousePos;
254 }
255 
256 
257 std::set<BOARD_ITEM*> GRID_HELPER::queryVisible( const BOX2I& aArea,
258  const std::vector<BOARD_ITEM*>& aSkip ) const
259 {
260  std::set<BOARD_ITEM*> items;
261  std::vector<KIGFX::VIEW::LAYER_ITEM_PAIR> selectedItems;
262 
263  KIGFX::VIEW* view = m_toolMgr->GetView();
264  RENDER_SETTINGS* settings = view->GetPainter()->GetSettings();
265  const std::set<unsigned int>& activeLayers = settings->GetHighContrastLayers();
266  bool isHighContrast = settings->GetHighContrast();
267 
268  view->Query( aArea, selectedItems );
269 
270  for( const KIGFX::VIEW::LAYER_ITEM_PAIR& it : selectedItems )
271  {
272  BOARD_ITEM* item = static_cast<BOARD_ITEM*>( it.first );
273 
274  // The item must be visible and on an active layer
275  if( view->IsVisible( item )
276  && ( !isHighContrast || activeLayers.count( it.second ) )
277  && item->ViewGetLOD( it.second, view ) < view->GetScale() )
278  {
279  items.insert ( item );
280  }
281  }
282 
283 
284  for( BOARD_ITEM* skipItem : aSkip )
285  items.erase( skipItem );
286 
287  return items;
288 }
289 
290 
291 VECTOR2I GRID_HELPER::BestSnapAnchor( const VECTOR2I& aOrigin, BOARD_ITEM* aDraggedItem )
292 {
293  LSET layers;
294  std::vector<BOARD_ITEM*> item;
295 
296  if( aDraggedItem )
297  {
298  layers = aDraggedItem->GetLayerSet();
299  item.push_back( aDraggedItem );
300  }
301  else
302  layers = LSET::AllLayersMask();
303 
304  return BestSnapAnchor( aOrigin, layers, item );
305 }
306 
307 
308 VECTOR2I GRID_HELPER::BestSnapAnchor( const VECTOR2I& aOrigin, const LSET& aLayers,
309  const std::vector<BOARD_ITEM*>& aSkip )
310 {
311  int snapDist = GetGrid().x;
312  int snapRange = snapDist;
313 
314  BOX2I bb( VECTOR2I( aOrigin.x - snapRange / 2, aOrigin.y - snapRange / 2 ),
315  VECTOR2I( snapRange, snapRange ) );
316 
317  clearAnchors();
318 
319  for( BOARD_ITEM* item : queryVisible( bb, aSkip ) )
320  computeAnchors( item, aOrigin );
321 
322  ANCHOR* nearest = nearestAnchor( aOrigin, SNAPPABLE, aLayers );
323  VECTOR2I nearestGrid = Align( aOrigin );
324 
325  if( nearest )
326  snapDist = nearest->Distance( aOrigin );
327 
328  // Existing snap lines need priority over new snaps
330  {
331  bool snapLine = false;
332  int x_dist = std::abs( m_viewSnapLine.GetPosition().x - aOrigin.x );
333  int y_dist = std::abs( m_viewSnapLine.GetPosition().y - aOrigin.y );
334 
336  if( x_dist < snapRange && ( !nearest || snapDist > snapRange ) )
337  {
338  nearestGrid.x = m_viewSnapLine.GetPosition().x;
339  snapLine = true;
340  }
341 
342  if( y_dist < snapRange && ( !nearest || snapDist > snapRange ) )
343  {
344  nearestGrid.y = m_viewSnapLine.GetPosition().y;
345  snapLine = true;
346  }
347 
348  if( snapLine && m_skipPoint != VECTOR2I( m_viewSnapLine.GetPosition() ) )
349  {
350  m_viewSnapLine.SetEndPosition( nearestGrid );
351 
354  else
356 
357  return nearestGrid;
358  }
359  }
360 
361  if( nearest && m_enableSnap )
362  {
363  if( nearest->Distance( aOrigin ) <= snapRange )
364  {
365  m_viewSnapPoint.SetPosition( wxPoint( nearest->pos ) );
366  m_viewSnapLine.SetPosition( wxPoint( nearest->pos ) );
368 
371  else
373 
374  m_snapItem = nearest;
375  return nearest->pos;
376  }
377  }
378 
379  m_snapItem = nullptr;
382  return nearestGrid;
383 }
384 
385 
387 {
388  if( !m_snapItem )
389  return nullptr;
390 
391  return m_snapItem->item;
392 }
393 
394 
395 void GRID_HELPER::computeAnchors( BOARD_ITEM* aItem, const VECTOR2I& aRefPos, bool aFrom )
396 {
397  VECTOR2I origin;
398  KIGFX::VIEW* view = m_toolMgr->GetView();
399  RENDER_SETTINGS* settings = view->GetPainter()->GetSettings();
400  const std::set<unsigned int>& activeLayers = settings->GetHighContrastLayers();
401  bool isHighContrast = settings->GetHighContrast();
402 
403  auto handlePadShape =
404  [&]( D_PAD* aPad )
405  {
406  addAnchor( aPad->GetPosition(), CORNER | SNAPPABLE, aPad );
407 
408  const std::shared_ptr<SHAPE> eshape = aPad->GetEffectiveShape( aPad->GetLayer() );
409 
410  wxASSERT( eshape->Type() == SH_COMPOUND );
411  const std::vector<SHAPE*> shapes =
412  static_cast<const SHAPE_COMPOUND*>( eshape.get() )->Shapes();
413 
414  for( const SHAPE* shape : shapes )
415  {
416  switch( shape->Type() )
417  {
418  case SH_RECT:
419  {
420  const SHAPE_RECT* rect = static_cast<const SHAPE_RECT*>( shape );
421  SHAPE_LINE_CHAIN outline = rect->Outline();
422 
423  for( int i = 0; i < outline.SegmentCount(); i++ )
424  {
425  const SEG& seg = outline.CSegment( i );
426  addAnchor( seg.A, OUTLINE | SNAPPABLE, aPad );
427  addAnchor( seg.Center(), OUTLINE | SNAPPABLE, aPad );
428  }
429 
430  break;
431  }
432 
433  case SH_SEGMENT:
434  {
435  const SHAPE_SEGMENT* segment = static_cast<const SHAPE_SEGMENT*>( shape );
436 
437  int offset = segment->GetWidth() / 2;
438  SEG seg = segment->GetSeg();
439  VECTOR2I normal = ( seg.B - seg.A ).Resize( offset ).Rotate( -M_PI_2 );
440 
441  /*
442  * TODO: This creates more snap points than necessary for rounded rect pads
443  * because they are built up of overlapping segments. We could fix this if
444  * desired by testing these to see if they are "inside" the pad.
445  */
446 
447  addAnchor( seg.A + normal, OUTLINE | SNAPPABLE, aPad );
448  addAnchor( seg.A - normal, OUTLINE | SNAPPABLE, aPad );
449  addAnchor( seg.B + normal, OUTLINE | SNAPPABLE, aPad );
450  addAnchor( seg.B - normal, OUTLINE | SNAPPABLE, aPad );
451  addAnchor( seg.Center() + normal, OUTLINE | SNAPPABLE, aPad );
452  addAnchor( seg.Center() - normal, OUTLINE | SNAPPABLE, aPad );
453 
454  normal = normal.Rotate( M_PI_2 );
455 
456  addAnchor( seg.A - normal, OUTLINE | SNAPPABLE, aPad );
457  addAnchor( seg.B + normal, OUTLINE | SNAPPABLE, aPad );
458  break;
459  }
460 
461  case SH_CIRCLE:
462  {
463  const SHAPE_CIRCLE* circle = static_cast<const SHAPE_CIRCLE*>( shape );
464 
465  int r = circle->GetRadius();
466  VECTOR2I start = circle->GetCenter();
467 
468  addAnchor( start + VECTOR2I( -r, 0 ), OUTLINE | SNAPPABLE, aPad );
469  addAnchor( start + VECTOR2I( r, 0 ), OUTLINE | SNAPPABLE, aPad );
470  addAnchor( start + VECTOR2I( 0, -r ), OUTLINE | SNAPPABLE, aPad );
471  addAnchor( start + VECTOR2I( 0, r ), OUTLINE | SNAPPABLE, aPad );
472  break;
473  }
474 
475  case SH_ARC:
476  {
477  const SHAPE_ARC* arc = static_cast<const SHAPE_ARC*>( shape );
478 
479  addAnchor( arc->GetP0(), OUTLINE | SNAPPABLE, aPad );
480  addAnchor( arc->GetP1(), OUTLINE | SNAPPABLE, aPad );
481  addAnchor( arc->GetArcMid(), OUTLINE | SNAPPABLE, aPad );
482  break;
483  }
484 
485  case SH_SIMPLE:
486  {
487  const SHAPE_SIMPLE* poly = static_cast<const SHAPE_SIMPLE*>( shape );
488 
489  for( size_t i = 0; i < poly->GetSegmentCount(); i++ )
490  {
491  const SEG& seg = poly->GetSegment( i );
492 
493  addAnchor( seg.A, OUTLINE | SNAPPABLE, aPad );
494  addAnchor( seg.Center(), OUTLINE | SNAPPABLE, aPad );
495 
496  if( i == poly->GetSegmentCount() - 1 )
497  addAnchor( seg.B, OUTLINE | SNAPPABLE, aPad );
498  }
499 
500  break;
501  }
502 
503  case SH_POLY_SET:
504  case SH_LINE_CHAIN:
505  case SH_COMPOUND:
507  case SH_NULL:
508  default:
509  break;
510  }
511  }
512  };
513 
514  switch( aItem->Type() )
515  {
516  case PCB_MODULE_T:
517  {
518  MODULE* mod = static_cast<MODULE*>( aItem );
519 
520  for( D_PAD* pad : mod->Pads() )
521  {
522  // Getting pads from the module requires re-checking that the pad is shown
524  && pad->GetBoundingBox().Contains( wxPoint( aRefPos.x, aRefPos.y ) )
525  && view->IsVisible( pad )
526  && ( !isHighContrast || activeLayers.count( pad->GetLayer() ) )
527  && pad->ViewGetLOD( pad->GetLayer(), view ) < view->GetScale() )
528  {
529  handlePadShape( pad );
530  break;
531  }
532  }
533 
534  // if the cursor is not over a pad, then drag the module by its origin
535  addAnchor( mod->GetPosition(), ORIGIN | SNAPPABLE, mod );
536  break;
537  }
538 
539  case PCB_PAD_T:
540  {
542  {
543  D_PAD* pad = static_cast<D_PAD*>( aItem );
544  handlePadShape( pad );
545  }
546 
547  break;
548  }
549 
550  case PCB_FP_SHAPE_T:
551  case PCB_SHAPE_T:
552  {
554  break;
555 
556  PCB_SHAPE* shape = static_cast<PCB_SHAPE*>( aItem );
557  VECTOR2I start = shape->GetStart();
558  VECTOR2I end = shape->GetEnd();
559 
560  switch( shape->GetShape() )
561  {
562  case S_CIRCLE:
563  {
564  int r = ( start - end ).EuclideanNorm();
565 
566  addAnchor( start, ORIGIN | SNAPPABLE, shape );
567  addAnchor( start + VECTOR2I( -r, 0 ), OUTLINE | SNAPPABLE, shape );
568  addAnchor( start + VECTOR2I( r, 0 ), OUTLINE | SNAPPABLE, shape );
569  addAnchor( start + VECTOR2I( 0, -r ), OUTLINE | SNAPPABLE, shape );
570  addAnchor( start + VECTOR2I( 0, r ), OUTLINE | SNAPPABLE, shape );
571  break;
572  }
573 
574  case S_ARC:
575  origin = shape->GetCenter();
576  addAnchor( shape->GetArcStart(), CORNER | SNAPPABLE, shape );
577  addAnchor( shape->GetArcEnd(), CORNER | SNAPPABLE, shape );
578  addAnchor( shape->GetArcMid(), CORNER | SNAPPABLE, shape );
579  addAnchor( origin, ORIGIN | SNAPPABLE, shape );
580  break;
581 
582  case S_RECT:
583  {
584  VECTOR2I point2( end.x, start.y );
585  VECTOR2I point3( start.x, end.y );
586  SEG first( start, point2 );
587  SEG second( point2, end );
588  SEG third( end, point3 );
589  SEG fourth( point3, start );
590 
591  addAnchor( first.A, CORNER | SNAPPABLE, shape );
592  addAnchor( first.Center(), CORNER | SNAPPABLE, shape );
593  addAnchor( second.A, CORNER | SNAPPABLE, shape );
594  addAnchor( second.Center(), CORNER | SNAPPABLE, shape );
595  addAnchor( third.A, CORNER | SNAPPABLE, shape );
596  addAnchor( third.Center(), CORNER | SNAPPABLE, shape );
597  addAnchor( fourth.A, CORNER | SNAPPABLE, shape );
598  addAnchor( fourth.Center(), CORNER | SNAPPABLE, shape );
599  break;
600  }
601 
602  case S_SEGMENT:
603  origin.x = start.x + ( start.x - end.x ) / 2;
604  origin.y = start.y + ( start.y - end.y ) / 2;
605  addAnchor( start, CORNER | SNAPPABLE, shape );
606  addAnchor( end, CORNER | SNAPPABLE, shape );
607  addAnchor( SEG( start, end ).Center(), CORNER | SNAPPABLE, shape );
608  addAnchor( origin, ORIGIN, shape );
609  break;
610 
611  case S_POLYGON:
612  for( const VECTOR2I& p : shape->BuildPolyPointsList() )
613  addAnchor( p, CORNER | SNAPPABLE, shape );
614 
615  break;
616 
617  case S_CURVE:
618  addAnchor( start, CORNER | SNAPPABLE, shape );
619  addAnchor( end, CORNER | SNAPPABLE, shape );
621 
622  default:
623  origin = shape->GetStart();
624  addAnchor( origin, ORIGIN | SNAPPABLE, shape );
625  break;
626  }
627  break;
628  }
629 
630  case PCB_TRACE_T:
631  case PCB_ARC_T:
632  {
634  {
635  TRACK* track = static_cast<TRACK*>( aItem );
636  VECTOR2I start = track->GetStart();
637  VECTOR2I end = track->GetEnd();
638  origin.x = start.x + ( start.x - end.x ) / 2;
639  origin.y = start.y + ( start.y - end.y ) / 2;
640  addAnchor( start, CORNER | SNAPPABLE, track );
641  addAnchor( end, CORNER | SNAPPABLE, track );
642  addAnchor( origin, ORIGIN, track);
643  }
644 
645  break;
646  }
647 
648  case PCB_MARKER_T:
649  case PCB_TARGET_T:
650  addAnchor( aItem->GetPosition(), ORIGIN | CORNER | SNAPPABLE, aItem );
651  break;
652 
653  case PCB_VIA_T:
654  {
656  addAnchor( aItem->GetPosition(), ORIGIN | CORNER | SNAPPABLE, aItem );
657 
658  break;
659  }
660 
661  case PCB_ZONE_AREA_T:
662  {
663  const SHAPE_POLY_SET* outline = static_cast<const ZONE_CONTAINER*>( aItem )->Outline();
664 
665  SHAPE_LINE_CHAIN lc;
666  lc.SetClosed( true );
667 
668  for( auto iter = outline->CIterateWithHoles(); iter; iter++ )
669  {
670  addAnchor( *iter, CORNER, aItem );
671  lc.Append( *iter );
672  }
673 
674  addAnchor( lc.NearestPoint( aRefPos ), OUTLINE, aItem );
675 
676  break;
677  }
678 
679  case PCB_DIM_ALIGNED_T:
681  {
682  const ALIGNED_DIMENSION* dim = static_cast<const ALIGNED_DIMENSION*>( aItem );
683  addAnchor( dim->GetCrossbarStart(), CORNER | SNAPPABLE, aItem );
684  addAnchor( dim->GetCrossbarEnd(), CORNER | SNAPPABLE, aItem );
685  addAnchor( dim->GetStart(), CORNER | SNAPPABLE, aItem );
686  addAnchor( dim->GetEnd(), CORNER | SNAPPABLE, aItem );
687  break;
688  }
689 
690  case PCB_DIM_CENTER_T:
691  {
692  const CENTER_DIMENSION* dim = static_cast<const CENTER_DIMENSION*>( aItem );
693  addAnchor( dim->GetStart(), CORNER | SNAPPABLE, aItem );
694  addAnchor( dim->GetEnd(), CORNER | SNAPPABLE, aItem );
695 
696  VECTOR2I start( dim->GetStart() );
697  VECTOR2I radial( dim->GetEnd() - dim->GetStart() );
698 
699  for( int i = 0; i < 2; i++ )
700  {
701  radial = radial.Rotate( DEG2RAD( 90 ) );
702  addAnchor( start + radial, CORNER | SNAPPABLE, aItem );
703  }
704 
705  break;
706  }
707 
708  case PCB_DIM_LEADER_T:
709  {
710  const LEADER* leader = static_cast<const LEADER*>( aItem );
711  addAnchor( leader->GetStart(), CORNER | SNAPPABLE, aItem );
712  addAnchor( leader->GetEnd(), CORNER | SNAPPABLE, aItem );
713  addAnchor( leader->Text().GetPosition(), CORNER | SNAPPABLE, aItem );
714  break;
715  }
716 
717  case PCB_FP_TEXT_T:
718  case PCB_TEXT_T:
719  addAnchor( aItem->GetPosition(), ORIGIN, aItem );
720  break;
721 
722  default:
723  break;
724  }
725 }
726 
727 
729  LSET aMatchLayers )
730 {
731  double minDist = std::numeric_limits<double>::max();
732  ANCHOR* best = NULL;
733 
734  for( ANCHOR& a : m_anchors )
735  {
736  if( ( aMatchLayers & a.item->GetLayerSet() ) == 0 )
737  continue;
738 
739  if( ( aFlags & a.flags ) != aFlags )
740  continue;
741 
742  double dist = a.Distance( aPos );
743 
744  if( dist < minDist )
745  {
746  minDist = dist;
747  best = &a;
748  }
749  }
750 
751  return best;
752 }
double EuclideanNorm(const wxPoint &vector)
Euclidean norm of a 2D vector.
Definition: trigo.h:134
void SetPosition(const wxPoint &aPosition) override
set of polygons (with holes, etc.)
Definition: shape.h:49
wxPoint GetArcEnd() const
Definition: pcb_shape.cpp:366
virtual const SEG GetSegment(int aIndex) const override
Definition: shape_simple.h:185
const std::set< unsigned int > GetHighContrastLayers() const
Function GetHighContrastLayers() Returns the set of currently high-contrast layers.
const VECTOR2I NearestPoint(const VECTOR2I &aP) const
Function NearestPoint()
usual segment : line with rounded ends
OPT< VECTOR2I > m_auxAxis
Definition: grid_helper.h:151
KIGFX::VIEW * GetView() const
Definition: tool_manager.h:290
SHAPE_SIMPLE.
Definition: shape_simple.h:43
class ALIGNED_DIMENSION, a linear dimension (graphic item)
Definition: typeinfo.h:101
class LEADER, a leader dimension (graphic item)
Definition: typeinfo.h:102
wxPoint GetPosition() const override
ANCHOR * m_snapItem
Definition: grid_helper.h:156
class FP_TEXT, text in a footprint
Definition: typeinfo.h:93
const SHAPE_LINE_CHAIN Outline() const
Definition: shape_rect.h:176
int GetRadius() const
Definition: shape_circle.h:99
RENDER_SETTINGS Contains all the knowledge about how graphical objects are drawn on any output surfac...
const wxPoint & GetEnd() const
Function GetEnd returns the ending point of the graphic.
Definition: pcb_shape.h:140
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:116
VIEW_CONTROLS class definition.
class CENTER_DIMENSION, a center point marking (graphic item)
Definition: typeinfo.h:103
TOOL_MANAGER * m_toolMgr
Definition: grid_helper.h:150
#define M_PI_2
Definition: transline.cpp:37
KIGFX::ORIGIN_VIEWITEM m_viewAxis
Definition: grid_helper.h:164
VECTOR2I GetOrigin() const
Definition: grid_helper.cpp:96
class ZONE_CONTAINER, a zone area
Definition: typeinfo.h:106
PADS & Pads()
Definition: class_module.h:182
VECTOR2I AlignToSegment(const VECTOR2I &aPoint, const SEG &aSeg)
CONST_ITERATOR CIterateWithHoles(int aOutline) const
class PCB_TEXT, text on a layer
Definition: typeinfo.h:92
class ARC, an arc track segment on a copper layer
Definition: typeinfo.h:98
Bezier Curve.
GAL * GetGAL() const
Function GetGAL() Returns the GAL this view is using to draw graphical primitives.
Definition: view.h:182
class FP_SHAPE, a footprint edge
Definition: typeinfo.h:94
class D_PAD, a pad in a footprint
Definition: typeinfo.h:90
#define KI_FALLTHROUGH
The KI_FALLTHROUGH macro is to be used when switch statement cases should purposely fallthrough from ...
Definition: macros.h:83
virtual const wxPoint & GetEnd() const
OPT_VECTOR2I IntersectLines(const SEG &aSeg) const
Function IntersectLines()
Definition: seg.h:191
VECTOR2I BestSnapAnchor(const VECTOR2I &aOrigin, BOARD_ITEM *aDraggedItem)
void SetEndPosition(const VECTOR2D &aPosition)
const VECTOR2I GetCenter() const
Definition: shape_circle.h:104
VECTOR2I Center() const
Returns the center point of the line
Definition: seg.h:350
virtual wxPoint GetPosition() const
Definition: eda_item.h:326
VECTOR2< int > VECTOR2I
Definition: vector2d.h:594
Arcs (with rounded ends)
const wxPoint & GetCrossbarStart() const
PAINTER * GetPainter() const
Function GetPainter() Returns the painter object used by the view for drawing VIEW_ITEMS.
Definition: view.h:201
A single base class (TRACK) represents both tracks and vias, with subclasses for curved tracks (ARC) ...
const SEG & GetSeg() const
class TRACK, a track segment (segment on a copper layer)
Definition: typeinfo.h:96
void Append(int aX, int aY, bool aAllowDuplication=false)
Function Append()
const wxPoint & GetCrossbarEnd() const
This file contains miscellaneous commonly used macros and functions.
wxPoint GetArcStart() const
Definition: pcb_shape.h:163
VECTOR2I GetGrid() const
Definition: grid_helper.cpp:88
BOARD_ITEM * GetSnapped() const
Function GetSnapped If the GRID_HELPER has highlighted a snap point (target shown),...
KIGFX::ORIGIN_VIEWITEM m_viewSnapPoint
Definition: grid_helper.h:162
TOOL_MANAGER.
Definition: tool_manager.h:51
DIMENSION class definition.
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:1179
class MODULE, a footprint
Definition: typeinfo.h:89
void SetClosed(bool aClosed)
Function SetClosed()
void SetAuxAxes(bool aEnable, const VECTOR2I &aOrigin=VECTOR2I(0, 0))
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,...
VECTOR2I BestDragOrigin(const VECTOR2I &aMousePos, std::vector< BOARD_ITEM * > &aItem)
LSET is a set of PCB_LAYER_IDs.
ANCHOR * nearestAnchor(const VECTOR2I &aPos, int aFlags, LSET aMatchLayers)
segment with non rounded ends
#define NULL
virtual wxPoint GetPosition() const override
Definition: pcb_text.h:72
OPT< VECTOR2I > OPT_VECTOR2I
Definition: seg.h:37
double Distance(const VECTOR2I &aP) const
Definition: grid_helper.h:117
GRID_HELPER(TOOL_MANAGER *aToolMgr, MAGNETIC_SETTINGS *aMagneticSettings)
Definition: grid_helper.cpp:52
A leader is a dimension-like object pointing to a specific point.
bool IsVisible(const VIEW_ITEM *aItem) const
Returns information if the item is visible (or not).
Definition: view.cpp:1499
BOARD_ITEM * item
Definition: grid_helper.h:115
SHAPE_POLY_SET.
SHAPE_LINE_CHAIN & Outline(int aIndex)
Returns the reference to aIndex-th outline in the set
void SetSize(int aSize)
const VECTOR2I & GetP0() const
Definition: shape_arc.h:85
wxPoint GetCenter() const override
Function GetCenter()
Definition: pcb_shape.cpp:334
const wxPoint & GetStart() const
Function GetStart returns the starting point of the graphic.
Definition: pcb_shape.h:129
void SetDrawAtZero(bool aDrawFlag)
Function SetDrawAtZero() Set the draw at zero flag.
PCB_TEXT & Text()
const VECTOR2I & GetArcMid() const
Definition: shape_arc.h:87
compound shape, consisting of multiple simple shapes
Definition: shape.h:50
static LSET AllLayersMask()
Definition: lset.cpp:786
SHAPE.
Definition: shape.h:122
bool m_enableSnap
Definition: grid_helper.h:153
VECTOR2I AlignToArc(const VECTOR2I &aPoint, const SHAPE_ARC &aSeg)
bool m_enableSnapLine
Definition: grid_helper.h:155
int SegmentCount() const
Function SegmentCount()
line chain (polyline)
Definition: shape.h:46
class PCB_TARGET, a target (graphic item)
Definition: typeinfo.h:105
Definition: seg.h:39
virtual size_t GetSegmentCount() const override
Definition: shape_simple.h:187
const VECTOR2D & GetGridSize() const
Returns the grid size.
VECTOR2I Align(const VECTOR2I &aPoint) const
bool GetHighContrast() const
virtual RENDER_SETTINGS * GetSettings()=0
Function GetAdapter Returns pointer to current settings that are going to be used when drawing items.
VECTOR2< T > Rotate(double aAngle) const
Function Rotate rotates the vector by a given angle.
Definition: vector2d.h:377
virtual const wxPoint & GetStart() const
The dimension's origin is the first feature point for the dimension.
simple polygon
Definition: shape.h:48
class MARKER_PCB, a marker used to show something
Definition: typeinfo.h:99
empty shape (no shape...),
Definition: shape.h:52
const SEG CSegment(int aIndex) const
Function CSegment()
double DEG2RAD(double deg)
Definition: trigo.h:220
polygon (not yet used for tracks, but could be in microwave apps)
SHAPE_LINE_CHAIN.
std::pair< VIEW_ITEM *, int > LAYER_ITEM_PAIR
Definition: view.h:68
VECTOR2I A
Definition: seg.h:47
MAGNETIC_OPTIONS pads
circular arc
Definition: shape.h:51
VECTOR2I m_skipPoint
Definition: grid_helper.h:158
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 segment
Definition: shape.h:45
std::set< BOARD_ITEM * > queryVisible(const BOX2I &aArea, const std::vector< BOARD_ITEM * > &aSkip) const
const wxPoint & GetEnd() const
Definition: class_track.h:113
boost::optional< T > OPT
Definition: optional.h:7
const VECTOR2D & GetGridOrigin() const
void addAnchor(const VECTOR2I &aPos, int aFlags, BOARD_ITEM *aItem)
Definition: grid_helper.h:128
void SetVisible(VIEW_ITEM *aItem, bool aIsVisible=true)
Sets the item visibility.
Definition: view.cpp:1459
MAGNETIC_SETTINGS * m_magneticSettings
Definition: grid_helper.h:160
class ORTHOGONAL_DIMENSION, a linear dimension constrained to x/y
Definition: typeinfo.h:104
class VIA, a via (like a track segment on a copper layer)
Definition: typeinfo.h:97
bool m_enableGrid
Definition: grid_helper.h:154
wxPoint GetArcMid() const
Definition: pcb_shape.cpp:384
virtual void Add(VIEW_ITEM *aItem, int aDrawPriority=-1)
Function Add() Adds a VIEW_ITEM to the view.
Definition: view.cpp:327
wxPoint GetPosition() const override
Definition: class_module.h:201
Definition: shape.h:43
PCB_SHAPE_TYPE_T GetShape() const
Definition: pcb_shape.h:114
virtual int Query(const BOX2I &aRect, std::vector< LAYER_ITEM_PAIR > &aResult) const
Function Query() Finds all visible items that touch or are within the rectangle aRect.
Definition: view.cpp:433
KIGFX::ORIGIN_VIEWITEM m_viewSnapLine
Definition: grid_helper.h:163
VIEW.
Definition: view.h:63
void SetStyle(MARKER_STYLE aStyle)
double GetScale() const
Function GetScale()
Definition: view.h:259
For better understanding of the points that make a dimension:
double GetWorldScale() const
Get the world scale.
std::vector< ANCHOR > m_anchors
Definition: grid_helper.h:123
int GetWidth() const
class PCB_SHAPE, a segment not on copper layers
Definition: typeinfo.h:91
circle
Definition: shape.h:47
const VECTOR2I & GetP1() const
Definition: shape_arc.h:86
void clearAnchors()
Definition: grid_helper.h:145
virtual double ViewGetLOD(int aLayer, VIEW *aView) const
Function ViewGetLOD() Returns the level of detail (LOD) of the item.
Definition: view_item.h:141
virtual LSET GetLayerSet() const
Function GetLayerSet returns a std::bitset of all layers on which the item physically resides.
virtual void Update(const VIEW_ITEM *aItem, int aUpdateFlags) const
For dynamic VIEWs, informs the associated VIEW that the graphical representation of this item has cha...
Definition: view.cpp:1513
MAGNETIC_OPTIONS tracks
KICAD_T Type() const
Function Type()
Definition: eda_item.h:182
axis-aligned rectangle
Definition: shape.h:44
Color has changed.
Definition: view_item.h:59
bool Contains(const SEG &aSeg) const
Definition: seg.h:299
COLOR4D is the color representation with 4 components: red, green, blue, alpha.
Definition: color4d.h:100
VECTOR2I B
Definition: seg.h:48
Marks the center of a circle or arc with a cross shape The size and orientation of the cross is adjus...