KiCad PCB EDA Suite
Loading...
Searching...
No Matches
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-2023 KiCad Developers, see AUTHORS.txt for contributors.
6 * @author Tomasz Wlostowski <[email protected]>
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 "pcb_grid_helper.h"
27
28#include <functional>
29
30#include <pcb_dimension.h>
31#include <pcb_shape.h>
32#include <footprint.h>
33#include <pad.h>
34#include <pcb_group.h>
35#include <pcb_track.h>
36#include <zone.h>
38#include <geometry/oval.h>
41#include <geometry/shape_rect.h>
44#include <macros.h>
45#include <math/util.h> // for KiROUND
46#include <gal/painter.h>
47#include <pcbnew_settings.h>
48#include <tool/tool_manager.h>
49#include <tools/pcb_tool_base.h>
50#include <view/view.h>
51
53 GRID_HELPER( aToolMgr ),
54 m_magneticSettings( aMagneticSettings )
55{
56 KIGFX::VIEW* view = m_toolMgr->GetView();
57 KIGFX::RENDER_SETTINGS* settings = view->GetPainter()->GetSettings();
58 KIGFX::COLOR4D auxItemsColor = settings->GetLayerColor( LAYER_AUX_ITEMS );
59 KIGFX::COLOR4D umbilicalColor = settings->GetLayerColor( LAYER_ANCHOR );
60
61 m_viewAxis.SetSize( 20000 );
63 m_viewAxis.SetColor( auxItemsColor.WithAlpha( 0.4 ) );
65 view->Add( &m_viewAxis );
66 view->SetVisible( &m_viewAxis, false );
67
69 m_viewSnapPoint.SetColor( auxItemsColor );
71 view->Add( &m_viewSnapPoint );
72 view->SetVisible( &m_viewSnapPoint, false );
73
75 m_viewSnapLine.SetColor( umbilicalColor );
77 view->Add( &m_viewSnapLine );
78 view->SetVisible( &m_viewSnapLine, false );
79}
80
81
83{
84 KIGFX::VIEW* view = m_toolMgr->GetView();
85
86 view->Remove( &m_viewAxis );
87 view->Remove( &m_viewSnapPoint );
88 view->Remove( &m_viewSnapLine );
89}
90
91
93{
94 const int c_gridSnapEpsilon_sq = 4;
95
96 VECTOR2I aligned = Align( aPoint );
97
98 if( !m_enableSnap )
99 return aligned;
100
101 std::vector<VECTOR2I> points;
102
103 const SEG testSegments[] = { SEG( aligned, aligned + VECTOR2( 1, 0 ) ),
104 SEG( aligned, aligned + VECTOR2( 0, 1 ) ),
105 SEG( aligned, aligned + VECTOR2( 1, 1 ) ),
106 SEG( aligned, aligned + VECTOR2( 1, -1 ) ) };
107
108 for( const SEG& seg : testSegments )
109 {
110 OPT_VECTOR2I vec = aSeg.IntersectLines( seg );
111
112 if( vec && aSeg.SquaredDistance( *vec ) <= c_gridSnapEpsilon_sq )
113 points.push_back( *vec );
114 }
115
116 VECTOR2I nearest = aligned;
118
119 // Snap by distance between pointer and endpoints
120 for( const VECTOR2I& pt : { aSeg.A, aSeg.B } )
121 {
122 SEG::ecoord d_sq = ( pt - aPoint ).SquaredEuclideanNorm();
123
124 if( d_sq < min_d_sq )
125 {
126 min_d_sq = d_sq;
127 nearest = pt;
128 }
129 }
130
131 // Snap by distance between aligned cursor and intersections
132 for( const VECTOR2I& pt : points )
133 {
134 SEG::ecoord d_sq = ( pt - aligned ).SquaredEuclideanNorm();
135
136 if( d_sq < min_d_sq )
137 {
138 min_d_sq = d_sq;
139 nearest = pt;
140 }
141 }
142
143 return nearest;
144}
145
146
148{
149 VECTOR2I aligned = Align( aPoint );
150
151 if( !m_enableSnap )
152 return aligned;
153
154 std::vector<VECTOR2I> points;
155
156 aArc.IntersectLine( SEG( aligned, aligned + VECTOR2( 1, 0 ) ), &points );
157 aArc.IntersectLine( SEG( aligned, aligned + VECTOR2( 0, 1 ) ), &points );
158 aArc.IntersectLine( SEG( aligned, aligned + VECTOR2( 1, 1 ) ), &points );
159 aArc.IntersectLine( SEG( aligned, aligned + VECTOR2( 1, -1 ) ), &points );
160
161 VECTOR2I nearest = aligned;
163
164 // Snap by distance between pointer and endpoints
165 for( const VECTOR2I& pt : { aArc.GetP0(), aArc.GetP1() } )
166 {
167 SEG::ecoord d_sq = ( pt - aPoint ).SquaredEuclideanNorm();
168
169 if( d_sq < min_d_sq )
170 {
171 min_d_sq = d_sq;
172 nearest = pt;
173 }
174 }
175
176 // Snap by distance between aligned cursor and intersections
177 for( const VECTOR2I& pt : points )
178 {
179 SEG::ecoord d_sq = ( pt - aligned ).SquaredEuclideanNorm();
180
181 if( d_sq < min_d_sq )
182 {
183 min_d_sq = d_sq;
184 nearest = pt;
185 }
186 }
187
188 return nearest;
189}
190
191
192VECTOR2I PCB_GRID_HELPER::AlignToNearestPad( const VECTOR2I& aMousePos, std::deque<PAD*>& aPads )
193{
194 clearAnchors();
195
196 for( BOARD_ITEM* item : aPads )
197 computeAnchors( item, aMousePos, true );
198
199 double minDist = std::numeric_limits<double>::max();
200 ANCHOR* nearestOrigin = nullptr;
201
202 for( ANCHOR& a : m_anchors )
203 {
204 BOARD_ITEM* item = static_cast<BOARD_ITEM*>( a.item );
205
206 if( ( ORIGIN & a.flags ) != ORIGIN )
207 continue;
208
209 if( !item->HitTest( aMousePos ) )
210 continue;
211
212 double dist = a.Distance( aMousePos );
213
214 if( dist < minDist )
215 {
216 minDist = dist;
217 nearestOrigin = &a;
218 }
219 }
220
221 return nearestOrigin ? nearestOrigin->pos : aMousePos;
222}
223
224
226 std::vector<BOARD_ITEM*>& aItems,
227 GRID_HELPER_GRIDS aGrid,
228 const PCB_SELECTION_FILTER_OPTIONS* aSelectionFilter )
229{
230 clearAnchors();
231
232 for( BOARD_ITEM* item : aItems )
233 computeAnchors( item, aMousePos, true, aSelectionFilter );
234
235 double worldScale = m_toolMgr->GetView()->GetGAL()->GetWorldScale();
236 double lineSnapMinCornerDistance = 50.0 / worldScale;
237
238 ANCHOR* nearestOutline = nearestAnchor( aMousePos, OUTLINE, LSET::AllLayersMask() );
239 ANCHOR* nearestCorner = nearestAnchor( aMousePos, CORNER, LSET::AllLayersMask() );
240 ANCHOR* nearestOrigin = nearestAnchor( aMousePos, ORIGIN, LSET::AllLayersMask() );
241 ANCHOR* best = nullptr;
242 double minDist = std::numeric_limits<double>::max();
243
244 if( nearestOrigin )
245 {
246 minDist = nearestOrigin->Distance( aMousePos );
247 best = nearestOrigin;
248 }
249
250 if( nearestCorner )
251 {
252 double dist = nearestCorner->Distance( aMousePos );
253
254 if( dist < minDist )
255 {
256 minDist = dist;
257 best = nearestCorner;
258 }
259 }
260
261 if( nearestOutline )
262 {
263 double dist = nearestOutline->Distance( aMousePos );
264
265 if( minDist > lineSnapMinCornerDistance && dist < minDist )
266 best = nearestOutline;
267 }
268
269 return best ? best->pos : aMousePos;
270}
271
272
274 GRID_HELPER_GRIDS aGrid )
275{
276 LSET layers;
277 std::vector<BOARD_ITEM*> item;
278
279 if( aReferenceItem )
280 {
281 layers = aReferenceItem->GetLayerSet();
282 item.push_back( aReferenceItem );
283 }
284 else
285 {
286 layers = LSET::AllLayersMask();
287 }
288
289 return BestSnapAnchor( aOrigin, layers, aGrid, item );
290}
291
292
294 GRID_HELPER_GRIDS aGrid,
295 const std::vector<BOARD_ITEM*>& aSkip )
296{
297 // Tuning constant: snap radius in screen space
298 const int snapSize = 25;
299
300 // Snapping distance is in screen space, clamped to the current grid to ensure that the grid
301 // points that are visible can always be snapped to.
302 // see https://gitlab.com/kicad/code/kicad/-/issues/5638
303 // see https://gitlab.com/kicad/code/kicad/-/issues/7125
304 // see https://gitlab.com/kicad/code/kicad/-/issues/12303
305 double snapScale = snapSize / m_toolMgr->GetView()->GetGAL()->GetWorldScale();
306 // warning: GetVisibleGrid().x sometimes returns a value > INT_MAX. Intermediate calculation
307 // needs double.
308 int snapRange = KiROUND( m_enableGrid ? std::min( snapScale, GetVisibleGrid().x ) : snapScale );
309 int snapDist = snapRange;
310
311 //Respect limits of coordinates representation
312 BOX2I bb;
313 bb.SetOrigin( GetClampedCoords<double, int>( VECTOR2D( aOrigin ) - snapRange / 2.0 ) );
314 bb.SetEnd( GetClampedCoords<double, int>( VECTOR2D( aOrigin ) + snapRange / 2.0 ) );
315
316 clearAnchors();
317
318 for( BOARD_ITEM* item : queryVisible( bb, aSkip ) )
319 computeAnchors( item, aOrigin );
320
321 ANCHOR* nearest = nearestAnchor( aOrigin, SNAPPABLE, aLayers );
322 VECTOR2I nearestGrid = Align( aOrigin, aGrid );
323
324 if( nearest )
325 snapDist = nearest->Distance( aOrigin );
326
327 // Existing snap lines need priority over new snaps
329 {
330 bool snapLine = false;
331 int x_dist = std::abs( m_viewSnapLine.GetPosition().x - aOrigin.x );
332 int y_dist = std::abs( m_viewSnapLine.GetPosition().y - aOrigin.y );
333
335 if( x_dist < snapRange && ( !nearest || snapDist > snapRange ) )
336 {
337 nearestGrid.x = m_viewSnapLine.GetPosition().x;
338 snapLine = true;
339 }
340
341 if( y_dist < snapRange && ( !nearest || snapDist > snapRange ) )
342 {
343 nearestGrid.y = m_viewSnapLine.GetPosition().y;
344 snapLine = true;
345 }
346
347 if( snapLine && m_skipPoint != VECTOR2I( m_viewSnapLine.GetPosition() ) )
348 {
349 m_viewSnapLine.SetEndPosition( nearestGrid );
350
353 else
355
356 return nearestGrid;
357 }
358 }
359
360 if( nearest && m_enableSnap )
361 {
362 if( nearest->Distance( aOrigin ) <= snapRange )
363 {
364 m_viewSnapPoint.SetPosition( nearest->pos );
365 m_viewSnapLine.SetPosition( nearest->pos );
367
370 else
372
373 m_snapItem = nearest;
374 return nearest->pos;
375 }
376 }
377
378 m_snapItem = nullptr;
381 return nearestGrid;
382}
383
384
386{
387 if( !m_snapItem )
388 return nullptr;
389
390 return static_cast<BOARD_ITEM*>( m_snapItem->item );
391}
392
393
395{
396 if( !aItem )
397 return GRID_CURRENT;
398
399 switch( aItem->Type() )
400 {
401 case PCB_FOOTPRINT_T:
402 case PCB_PAD_T:
403 return GRID_CONNECTABLE;
404
405 case PCB_TEXT_T:
406 case PCB_FIELD_T:
407 return GRID_TEXT;
408
409 case PCB_SHAPE_T:
410 case PCB_DIMENSION_T:
412 case PCB_TEXTBOX_T:
413 return GRID_GRAPHICS;
414
415 case PCB_TRACE_T:
416 case PCB_ARC_T:
417 return GRID_WIRES;
418
419 case PCB_VIA_T:
420 return GRID_VIAS;
421
422 default:
423 return GRID_CURRENT;
424 }
425}
426
427
429{
431 int idx = -1;
432
434
435 if( !grid.overrides_enabled )
436 return g;
437
438 switch( aGrid )
439 {
440 case GRID_CONNECTABLE:
441 if( grid.override_connected )
442 idx = grid.override_connected_idx;
443
444 break;
445
446 case GRID_WIRES:
447 if( grid.override_wires )
448 idx = grid.override_wires_idx;
449
450 break;
451
452 case GRID_VIAS:
453 if( grid.override_vias )
454 idx = grid.override_vias_idx;
455
456 break;
457
458 case GRID_TEXT:
459 if( grid.override_text )
460 idx = grid.override_text_idx;
461
462 break;
463
464 case GRID_GRAPHICS:
465 if( grid.override_graphics )
466 idx = grid.override_graphics_idx;
467
468 break;
469
470 default:
471 break;
472 }
473
474 if( idx >= 0 && idx < (int) grid.grids.size() )
475 g = grid.grids[idx].ToDouble( pcbIUScale );
476
477 return g;
478}
479
480
481std::set<BOARD_ITEM*> PCB_GRID_HELPER::queryVisible( const BOX2I& aArea,
482 const std::vector<BOARD_ITEM*>& aSkip ) const
483{
484 std::set<BOARD_ITEM*> items;
485 std::vector<KIGFX::VIEW::LAYER_ITEM_PAIR> selectedItems;
486
487 PCB_TOOL_BASE* currentTool = static_cast<PCB_TOOL_BASE*>( m_toolMgr->GetCurrentTool() );
488 KIGFX::VIEW* view = m_toolMgr->GetView();
489 RENDER_SETTINGS* settings = view->GetPainter()->GetSettings();
490 const std::set<int>& activeLayers = settings->GetHighContrastLayers();
491 bool isHighContrast = settings->GetHighContrast();
492
493 view->Query( aArea, selectedItems );
494
495 for( const auto& [ viewItem, layer ] : selectedItems )
496 {
497 BOARD_ITEM* boardItem = static_cast<BOARD_ITEM*>( viewItem );
498
499 if( currentTool->IsFootprintEditor() )
500 {
501 // If we are in the footprint editor, don't use the footprint itself
502 if( boardItem->Type() == PCB_FOOTPRINT_T )
503 continue;
504 }
505 else
506 {
507 // If we are not in the footprint editor, don't use footprint-editor-private items
508 if( FOOTPRINT* parentFP = boardItem->GetParentFootprint() )
509 {
510 if( IsPcbLayer( layer ) && parentFP->GetPrivateLayers().test( layer ) )
511 continue;
512 }
513 }
514
515 // The boardItem must be visible and on an active layer
516 if( view->IsVisible( boardItem )
517 && ( !isHighContrast || activeLayers.count( layer ) )
518 && boardItem->ViewGetLOD( layer, view ) < view->GetScale() )
519 {
520 items.insert ( boardItem );
521 }
522 }
523
524 std::function<void( BOARD_ITEM* )> skipItem =
525 [&]( BOARD_ITEM* aItem )
526 {
527 items.erase( aItem );
528
529 aItem->RunOnDescendants(
530 [&]( BOARD_ITEM* aChild )
531 {
532 skipItem( aChild );
533 } );
534 };
535
536 for( BOARD_ITEM* item : aSkip )
537 skipItem( item );
538
539 return items;
540}
541
542
543void PCB_GRID_HELPER::computeAnchors( BOARD_ITEM* aItem, const VECTOR2I& aRefPos, bool aFrom,
544 const PCB_SELECTION_FILTER_OPTIONS* aSelectionFilter )
545{
546 KIGFX::VIEW* view = m_toolMgr->GetView();
547 RENDER_SETTINGS* settings = view->GetPainter()->GetSettings();
548 const std::set<int>& activeLayers = settings->GetHighContrastLayers();
549 bool isHighContrast = settings->GetHighContrast();
550
551 auto checkVisibility =
552 [&]( BOARD_ITEM* item )
553 {
554 if( !view->IsVisible( item ) )
555 return false;
556
557 bool onActiveLayer = !isHighContrast;
558 bool isLODVisible = false;
559
560 for( PCB_LAYER_ID layer : item->GetLayerSet().Seq() )
561 {
562 if( !onActiveLayer && activeLayers.count( layer ) )
563 onActiveLayer = true;
564
565 if( !isLODVisible && item->ViewGetLOD( layer, view ) < view->GetScale() )
566 isLODVisible = true;
567
568 if( onActiveLayer && isLODVisible )
569 return true;
570 }
571
572 return false;
573 };
574
575 // As defaults, these are probably reasonable to avoid spamming key points
576 const OVAL_KEY_POINT_FLAGS ovalKeyPointFlags = OVAL_CENTER
580
581 // The key points of a circle centred around (0, 0) with the given radius
582 auto getCircleKeyPoints =
583 []( int radius )
584 {
585 return std::vector<VECTOR2I>{ { 0, 0 },
586 { -radius, 0 },
587 { radius, 0 },
588 { 0, -radius },
589 { 0, radius } };
590 };
591
592 auto handlePadShape =
593 [&]( PAD* aPad )
594 {
595 addAnchor( aPad->GetPosition(), ORIGIN | SNAPPABLE, aPad );
596
598 if( aFrom )
599 return;
600
601 switch( aPad->GetShape() )
602 {
603 case PAD_SHAPE::CIRCLE:
604 for( const VECTOR2I& pt: getCircleKeyPoints( aPad->GetSizeX() / 2 ) )
605 {
606 // Transform to the pad positon
607 addAnchor( aPad->ShapePos() + pt, OUTLINE | SNAPPABLE, aPad );
608 }
609
610 break;
611
612 case PAD_SHAPE::OVAL:
613 for( const VECTOR2I& pt: GetOvalKeyPoints( aPad->GetSize(),
614 aPad->GetOrientation(),
615 ovalKeyPointFlags ) )
616 {
617 // Transform to the pad positon
618 addAnchor( aPad->ShapePos() + pt, OUTLINE | SNAPPABLE, aPad );
619 }
620
621 break;
622
623 case PAD_SHAPE::RECTANGLE:
624 case PAD_SHAPE::TRAPEZOID:
625 case PAD_SHAPE::ROUNDRECT:
626 case PAD_SHAPE::CHAMFERED_RECT:
627 {
628 VECTOR2I half_size( aPad->GetSize() / 2 );
629 VECTOR2I trap_delta( 0, 0 );
630
631 if( aPad->GetShape() == PAD_SHAPE::TRAPEZOID )
632 trap_delta = aPad->GetDelta() / 2;
633
634 SHAPE_LINE_CHAIN corners;
635
636 corners.Append( -half_size.x - trap_delta.y, half_size.y + trap_delta.x );
637 corners.Append( half_size.x + trap_delta.y, half_size.y - trap_delta.x );
638 corners.Append( half_size.x - trap_delta.y, -half_size.y + trap_delta.x );
639 corners.Append( -half_size.x + trap_delta.y, -half_size.y - trap_delta.x );
640 corners.SetClosed( true );
641
642 corners.Rotate( aPad->GetOrientation() );
643 corners.Move( aPad->ShapePos() );
644
645 for( size_t ii = 0; ii < corners.GetSegmentCount(); ++ii )
646 {
647 const SEG& seg = corners.GetSegment( ii );
648 addAnchor( seg.A, OUTLINE | SNAPPABLE, aPad );
649 addAnchor( seg.Center(), OUTLINE | SNAPPABLE, aPad );
650
651 if( ii == corners.GetSegmentCount() - 1 )
652 addAnchor( seg.B, OUTLINE | SNAPPABLE, aPad );
653 }
654
655 break;
656 }
657
658 default:
659 {
660 const auto& outline = aPad->GetEffectivePolygon( ERROR_INSIDE );
661
662 if( !outline->IsEmpty() )
663 {
664 for( const VECTOR2I& pt : outline->Outline( 0 ).CPoints() )
665 addAnchor( pt, OUTLINE | SNAPPABLE, aPad );
666 }
667
668 break;
669 }
670 }
671
672 if( aPad->HasHole() )
673 {
674 // Holes are at the pad centre (it's the shape that may be offset)
675 const VECTOR2I hole_pos = aPad->GetPosition();
676 const VECTOR2I hole_size = aPad->GetDrillSize();
677
678 std::vector<VECTOR2I> snap_pts;
679
680 if ( hole_size.x == hole_size.y )
681 {
682 // Circle
683 snap_pts = getCircleKeyPoints( hole_size.x / 2 );
684 }
685 else
686 {
687 // Oval
688
689 // For now there's no way to have an off-angle hole, so this is the
690 // same as the pad. In future, this may not be true:
691 // https://gitlab.com/kicad/code/kicad/-/issues/4124
692 snap_pts = GetOvalKeyPoints( hole_size, aPad->GetOrientation(),
693 ovalKeyPointFlags );
694 }
695
696 for( const VECTOR2I& snap_pt : snap_pts )
697 addAnchor( hole_pos + snap_pt, OUTLINE | SNAPPABLE, aPad );
698 }
699 };
700
701 auto handleShape =
702 [&]( PCB_SHAPE* shape )
703 {
704 VECTOR2I start = shape->GetStart();
705 VECTOR2I end = shape->GetEnd();
706
707 switch( shape->GetShape() )
708 {
709 case SHAPE_T::CIRCLE:
710 {
711 int r = ( start - end ).EuclideanNorm();
712
713 addAnchor( start, ORIGIN | SNAPPABLE, shape );
714 addAnchor( start + VECTOR2I( -r, 0 ), OUTLINE | SNAPPABLE, shape );
715 addAnchor( start + VECTOR2I( r, 0 ), OUTLINE | SNAPPABLE, shape );
716 addAnchor( start + VECTOR2I( 0, -r ), OUTLINE | SNAPPABLE, shape );
717 addAnchor( start + VECTOR2I( 0, r ), OUTLINE | SNAPPABLE, shape );
718 break;
719 }
720
721 case SHAPE_T::ARC:
722 addAnchor( shape->GetStart(), CORNER | SNAPPABLE, shape );
723 addAnchor( shape->GetEnd(), CORNER | SNAPPABLE, shape );
724 addAnchor( shape->GetArcMid(), CORNER | SNAPPABLE, shape );
725 addAnchor( shape->GetCenter(), ORIGIN | SNAPPABLE, shape );
726 break;
727
728 case SHAPE_T::RECTANGLE:
729 {
730 VECTOR2I point2( end.x, start.y );
731 VECTOR2I point3( start.x, end.y );
732 SEG first( start, point2 );
733 SEG second( point2, end );
734 SEG third( end, point3 );
735 SEG fourth( point3, start );
736
737 addAnchor( first.A, CORNER | SNAPPABLE, shape );
738 addAnchor( first.Center(), CORNER | SNAPPABLE, shape );
739 addAnchor( second.A, CORNER | SNAPPABLE, shape );
740 addAnchor( second.Center(), CORNER | SNAPPABLE, shape );
741 addAnchor( third.A, CORNER | SNAPPABLE, shape );
742 addAnchor( third.Center(), CORNER | SNAPPABLE, shape );
743 addAnchor( fourth.A, CORNER | SNAPPABLE, shape );
744 addAnchor( fourth.Center(), CORNER | SNAPPABLE, shape );
745 break;
746 }
747
748 case SHAPE_T::SEGMENT:
749 addAnchor( start, CORNER | SNAPPABLE, shape );
750 addAnchor( end, CORNER | SNAPPABLE, shape );
751 addAnchor( shape->GetCenter(), CORNER | SNAPPABLE, shape );
752 break;
753
754 case SHAPE_T::POLY:
755 {
757 lc.SetClosed( true );
758 std::vector<VECTOR2I> poly;
759 shape->DupPolyPointsList( poly );
760
761 for( const VECTOR2I& p : poly )
762 {
763 addAnchor( p, CORNER | SNAPPABLE, shape );
764 lc.Append( p );
765 }
766
767 addAnchor( lc.NearestPoint( aRefPos ), OUTLINE, aItem );
768 break;
769 }
770
771 case SHAPE_T::BEZIER:
772 addAnchor( start, CORNER | SNAPPABLE, shape );
773 addAnchor( end, CORNER | SNAPPABLE, shape );
775
776 default:
777 addAnchor( shape->GetPosition(), ORIGIN | SNAPPABLE, shape );
778 break;
779 }
780 };
781
782 switch( aItem->Type() )
783 {
784 case PCB_FOOTPRINT_T:
785 {
786 FOOTPRINT* footprint = static_cast<FOOTPRINT*>( aItem );
787
788 for( PAD* pad : footprint->Pads() )
789 {
790 if( aFrom )
791 {
792 if( aSelectionFilter && !aSelectionFilter->pads )
793 continue;
794 }
795 else
796 {
797 if( m_magneticSettings->pads != MAGNETIC_OPTIONS::CAPTURE_ALWAYS )
798 continue;
799 }
800
801 if( !checkVisibility( pad ) )
802 continue;
803
804 if( !pad->GetBoundingBox().Contains( aRefPos ) )
805 continue;
806
807 handlePadShape( pad );
808 }
809
810 if( aFrom && aSelectionFilter && !aSelectionFilter->footprints )
811 break;
812
813 // If the cursor is not over a pad, snap to the anchor (if visible) or the center
814 // (if markedly different from the anchor).
815 VECTOR2I position = footprint->GetPosition();
816 VECTOR2I center = footprint->GetBoundingBox( false, false ).Centre();
817 VECTOR2I grid( GetGrid() );
818
819 if( view->IsLayerVisible( LAYER_ANCHOR ) )
820 addAnchor( position, ORIGIN | SNAPPABLE, footprint );
821
822 if( ( center - position ).SquaredEuclideanNorm() > grid.SquaredEuclideanNorm() )
823 addAnchor( center, ORIGIN | SNAPPABLE, footprint );
824
825 break;
826 }
827
828 case PCB_PAD_T:
829 if( aFrom )
830 {
831 if( aSelectionFilter && !aSelectionFilter->pads )
832 break;
833 }
834 else
835 {
836 if( m_magneticSettings->pads != MAGNETIC_OPTIONS::CAPTURE_ALWAYS )
837 break;
838 }
839
840 if( checkVisibility( aItem ) )
841 handlePadShape( static_cast<PAD*>( aItem ) );
842
843 break;
844
845 case PCB_TEXTBOX_T:
846 if( aFrom )
847 {
848 if( aSelectionFilter && !aSelectionFilter->text )
849 break;
850 }
851 else
852 {
854 break;
855 }
856
857 if( checkVisibility( aItem ) )
858 handleShape( static_cast<PCB_SHAPE*>( aItem ) );
859
860 break;
861
862 case PCB_SHAPE_T:
863 if( aFrom )
864 {
865 if( aSelectionFilter && !aSelectionFilter->graphics )
866 break;
867 }
868 else
869 {
871 break;
872 }
873
874 if( checkVisibility( aItem ) )
875 handleShape( static_cast<PCB_SHAPE*>( aItem ) );
876
877 break;
878
879 case PCB_TRACE_T:
880 case PCB_ARC_T:
881 if( aFrom )
882 {
883 if( aSelectionFilter && !aSelectionFilter->tracks )
884 break;
885 }
886 else
887 {
888 if( m_magneticSettings->tracks != MAGNETIC_OPTIONS::CAPTURE_ALWAYS )
889 break;
890 }
891
892 if( checkVisibility( aItem ) )
893 {
894 PCB_TRACK* track = static_cast<PCB_TRACK*>( aItem );
895
896 addAnchor( track->GetStart(), CORNER | SNAPPABLE, track );
897 addAnchor( track->GetEnd(), CORNER | SNAPPABLE, track );
898 addAnchor( track->GetCenter(), ORIGIN, track);
899 }
900
901 break;
902
903 case PCB_MARKER_T:
904 case PCB_TARGET_T:
905 addAnchor( aItem->GetPosition(), ORIGIN | CORNER | SNAPPABLE, aItem );
906 break;
907
908 case PCB_VIA_T:
909 if( aFrom )
910 {
911 if( aSelectionFilter && !aSelectionFilter->vias )
912 break;
913 }
914 else
915 {
916 if( m_magneticSettings->tracks != MAGNETIC_OPTIONS::CAPTURE_ALWAYS )
917 break;
918 }
919
920 if( checkVisibility( aItem ) )
921 addAnchor( aItem->GetPosition(), ORIGIN | CORNER | SNAPPABLE, aItem );
922
923 break;
924
925 case PCB_ZONE_T:
926 if( aFrom && aSelectionFilter && !aSelectionFilter->zones )
927 break;
928
929 if( checkVisibility( aItem ) )
930 {
931 const SHAPE_POLY_SET* outline = static_cast<const ZONE*>( aItem )->Outline();
932
934 lc.SetClosed( true );
935
936 for( auto iter = outline->CIterateWithHoles(); iter; iter++ )
937 {
938 addAnchor( *iter, CORNER | SNAPPABLE, aItem );
939 lc.Append( *iter );
940 }
941
942 addAnchor( lc.NearestPoint( aRefPos ), OUTLINE, aItem );
943 }
944
945 break;
946
949 if( aFrom && aSelectionFilter && !aSelectionFilter->dimensions )
950 break;
951
952 if( checkVisibility( aItem ) )
953 {
954 const PCB_DIM_ALIGNED* dim = static_cast<const PCB_DIM_ALIGNED*>( aItem );
955 addAnchor( dim->GetCrossbarStart(), CORNER | SNAPPABLE, aItem );
956 addAnchor( dim->GetCrossbarEnd(), CORNER | SNAPPABLE, aItem );
957 addAnchor( dim->GetStart(), CORNER | SNAPPABLE, aItem );
958 addAnchor( dim->GetEnd(), CORNER | SNAPPABLE, aItem );
959 }
960
961 break;
962
963 case PCB_DIM_CENTER_T:
964 if( aFrom && aSelectionFilter && !aSelectionFilter->dimensions )
965 break;
966
967 if( checkVisibility( aItem ) )
968 {
969 const PCB_DIM_CENTER* dim = static_cast<const PCB_DIM_CENTER*>( aItem );
970 addAnchor( dim->GetStart(), CORNER | SNAPPABLE, aItem );
971 addAnchor( dim->GetEnd(), CORNER | SNAPPABLE, aItem );
972
973 VECTOR2I start( dim->GetStart() );
974 VECTOR2I radial( dim->GetEnd() - dim->GetStart() );
975
976 for( int i = 0; i < 2; i++ )
977 {
978 RotatePoint( radial, -ANGLE_90 );
979 addAnchor( start + radial, CORNER | SNAPPABLE, aItem );
980 }
981 }
982
983 break;
984
985 case PCB_DIM_RADIAL_T:
986 if( aFrom && aSelectionFilter && !aSelectionFilter->dimensions )
987 break;
988
989 if( checkVisibility( aItem ) )
990 {
991 const PCB_DIM_RADIAL* radialDim = static_cast<const PCB_DIM_RADIAL*>( aItem );
992 addAnchor( radialDim->GetStart(), CORNER | SNAPPABLE, aItem );
993 addAnchor( radialDim->GetEnd(), CORNER | SNAPPABLE, aItem );
994 addAnchor( radialDim->GetKnee(), CORNER | SNAPPABLE, aItem );
995 addAnchor( radialDim->GetTextPos(), CORNER | SNAPPABLE, aItem );
996 }
997
998 break;
999
1000 case PCB_DIM_LEADER_T:
1001 if( aFrom && aSelectionFilter && !aSelectionFilter->dimensions )
1002 break;
1003
1004 if( checkVisibility( aItem ) )
1005 {
1006 const PCB_DIM_LEADER* leader = static_cast<const PCB_DIM_LEADER*>( aItem );
1007 addAnchor( leader->GetStart(), CORNER | SNAPPABLE, aItem );
1008 addAnchor( leader->GetEnd(), CORNER | SNAPPABLE, aItem );
1009 addAnchor( leader->GetTextPos(), CORNER | SNAPPABLE, aItem );
1010 }
1011
1012 break;
1013
1014 case PCB_FIELD_T:
1015 case PCB_TEXT_T:
1016 if( aFrom && aSelectionFilter && !aSelectionFilter->text )
1017 break;
1018
1019 if( checkVisibility( aItem ) )
1020 addAnchor( aItem->GetPosition(), ORIGIN, aItem );
1021
1022 break;
1023
1024 case PCB_GROUP_T:
1025 for( BOARD_ITEM* item : static_cast<const PCB_GROUP*>( aItem )->GetItems() )
1026 {
1027 if( checkVisibility( item ) )
1028 computeAnchors( item, aRefPos, aFrom );
1029 }
1030
1031 break;
1032
1033 default:
1034 break;
1035 }
1036}
1037
1038
1040 LSET aMatchLayers )
1041{
1042 double minDist = std::numeric_limits<double>::max();
1043 ANCHOR* best = nullptr;
1044
1045 for( ANCHOR& a : m_anchors )
1046 {
1047 BOARD_ITEM* item = static_cast<BOARD_ITEM*>( a.item );
1048
1049 if( !m_magneticSettings->allLayers && ( ( aMatchLayers & item->GetLayerSet() ) == 0 ) )
1050 continue;
1051
1052 if( ( aFlags & a.flags ) != aFlags )
1053 continue;
1054
1055 double dist = a.Distance( aPos );
1056
1057 if( dist < minDist )
1058 {
1059 minDist = dist;
1060 best = &a;
1061 }
1062 }
1063
1064 return best;
1065}
constexpr EDA_IU_SCALE pcbIUScale
Definition: base_units.h:108
WINDOW_SETTINGS m_Window
Definition: app_settings.h:172
A base class for any item which can be embedded within the BOARD container class, and therefore insta...
Definition: board_item.h:79
virtual VECTOR2I GetCenter() const
This defaults to the center of the bounding box if not overridden.
Definition: board_item.h:114
FOOTPRINT * GetParentFootprint() const
Definition: board_item.cpp:266
virtual LSET GetLayerSet() const
Return a std::bitset of all layers on which the item physically resides.
Definition: board_item.h:245
virtual void RunOnDescendants(const std::function< void(BOARD_ITEM *)> &aFunction, int aDepth=0) const
Invoke a function on all descendants.
Definition: board_item.h:215
void SetOrigin(const Vec &pos)
Definition: box2.h:227
Vec Centre() const
Definition: box2.h:87
void SetEnd(coord_type x, coord_type y)
Definition: box2.h:280
A base class for most all the KiCad significant classes used in schematics and boards.
Definition: eda_item.h:89
virtual VECTOR2I GetPosition() const
Definition: eda_item.h:243
KICAD_T Type() const
Returns the type of object.
Definition: eda_item.h:101
virtual bool HitTest(const VECTOR2I &aPosition, int aAccuracy=0) const
Test if aPosition is inside or on the boundary of this item.
Definition: eda_item.h:216
const VECTOR2I & GetTextPos() const
Definition: eda_text.h:230
std::deque< PAD * > & Pads()
Definition: footprint.h:205
VECTOR2I GetPosition() const override
Definition: footprint.h:223
const BOX2I GetBoundingBox() const override
Return the orthogonal bounding box of this object for display purposes.
Definition: footprint.cpp:1253
VECTOR2I m_skipPoint
Definition: grid_helper.h:182
bool m_enableGrid
Definition: grid_helper.h:178
TOOL_MANAGER * m_toolMgr
Definition: grid_helper.h:172
VECTOR2D GetVisibleGrid() const
Definition: grid_helper.cpp:61
VECTOR2I GetGrid() const
Definition: grid_helper.cpp:53
ANCHOR * m_snapItem
Definition: grid_helper.h:180
bool m_enableSnapLine
Definition: grid_helper.h:179
bool m_enableSnap
Definition: grid_helper.h:177
void addAnchor(const VECTOR2I &aPos, int aFlags, EDA_ITEM *aItem)
Definition: grid_helper.h:148
void clearAnchors()
Definition: grid_helper.h:154
KIGFX::ORIGIN_VIEWITEM m_viewSnapPoint
Definition: grid_helper.h:184
KIGFX::ORIGIN_VIEWITEM m_viewSnapLine
Definition: grid_helper.h:185
KIGFX::ORIGIN_VIEWITEM m_viewAxis
Definition: grid_helper.h:186
std::vector< ANCHOR > m_anchors
Definition: grid_helper.h:170
A color representation with 4 components: red, green, blue, alpha.
Definition: color4d.h:104
COLOR4D WithAlpha(double aAlpha) const
Return a color with the same color, but the given alpha.
Definition: color4d.h:311
const VECTOR2D & GetGridSize() const
Return the grid size.
double GetWorldScale() const
Get the world scale.
void SetPosition(const VECTOR2I &aPosition) override
void SetColor(const KIGFX::COLOR4D &aColor)
VECTOR2I GetPosition() const override
void SetStyle(MARKER_STYLE aStyle)
void SetSize(int aSize)
void SetDrawAtZero(bool aDrawFlag)
Set the draw at zero flag.
void SetEndPosition(const VECTOR2D &aPosition)
virtual RENDER_SETTINGS * GetSettings()=0
Return a pointer to current settings that are going to be used when drawing items.
Container for all the knowledge about how graphical objects are drawn on any output surface/device.
const std::set< int > GetHighContrastLayers() const
Returns the set of currently high-contrast layers.
const COLOR4D & GetLayerColor(int aLayer) const
Return the color used to draw a layer.
bool GetHighContrast() const
virtual double ViewGetLOD(int aLayer, VIEW *aView) const
Return the level of detail (LOD) of the item.
Definition: view_item.h:141
Hold a (potentially large) number of VIEW_ITEMs and renders them on a graphics device provided by the...
Definition: view.h:68
double GetScale() const
Definition: view.h:277
virtual void Add(VIEW_ITEM *aItem, int aDrawPriority=-1)
Add a VIEW_ITEM to the view.
Definition: view.cpp:317
virtual void Remove(VIEW_ITEM *aItem)
Remove a VIEW_ITEM from the view.
Definition: view.cpp:357
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:437
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:1687
GAL * GetGAL() const
Return the #GAL this view is using to draw graphical primitives.
Definition: view.h:203
bool IsLayerVisible(int aLayer) const
Return information about visibility of a particular layer.
Definition: view.h:418
PAINTER * GetPainter() const
Return the painter object used by the view for drawing #VIEW_ITEMS.
Definition: view.h:221
bool IsVisible(const VIEW_ITEM *aItem) const
Return information if the item is visible (or not).
Definition: view.cpp:1657
void SetVisible(VIEW_ITEM *aItem, bool aIsVisible=true)
Set the item visibility.
Definition: view.cpp:1614
LSET is a set of PCB_LAYER_IDs.
Definition: lset.h:35
static LSET AllLayersMask()
Definition: lset.cpp:768
Definition: pad.h:54
virtual const VECTOR2I & GetStart() const
The dimension's origin is the first feature point for the dimension.
virtual const VECTOR2I & GetEnd() const
For better understanding of the points that make a dimension:
const VECTOR2I & GetCrossbarStart() const
const VECTOR2I & GetCrossbarEnd() const
Mark the center of a circle or arc with a cross shape.
A leader is a dimension-like object pointing to a specific point.
A radial dimension indicates either the radius or diameter of an arc or circle.
VECTOR2I GetKnee() const
void computeAnchors(BOARD_ITEM *aItem, const VECTOR2I &aRefPos, bool aFrom=false, const PCB_SELECTION_FILTER_OPTIONS *aSelectionFilter=nullptr)
computeAnchors inserts the local anchor points in to the grid helper for the specified board item,...
~PCB_GRID_HELPER() override
VECTOR2I AlignToArc(const VECTOR2I &aPoint, const SHAPE_ARC &aSeg)
BOARD_ITEM * GetSnapped() const
Function GetSnapped If the PCB_GRID_HELPER has highlighted a snap point (target shown),...
VECTOR2D GetGridSize(GRID_HELPER_GRIDS aGrid) const override
Return the size of the specified grid.
VECTOR2I BestSnapAnchor(const VECTOR2I &aOrigin, BOARD_ITEM *aReferenceItem, GRID_HELPER_GRIDS aGrid=GRID_HELPER_GRIDS::GRID_CURRENT)
Chooses the "best" snap anchor around the given point, optionally taking layers from the reference it...
VECTOR2I BestDragOrigin(const VECTOR2I &aMousePos, std::vector< BOARD_ITEM * > &aItem, GRID_HELPER_GRIDS aGrid=GRID_HELPER_GRIDS::GRID_CURRENT, const PCB_SELECTION_FILTER_OPTIONS *aSelectionFilter=nullptr)
std::set< BOARD_ITEM * > queryVisible(const BOX2I &aArea, const std::vector< BOARD_ITEM * > &aSkip) const
ANCHOR * nearestAnchor(const VECTOR2I &aPos, int aFlags, LSET aMatchLayers)
MAGNETIC_SETTINGS * m_magneticSettings
GRID_HELPER_GRIDS GetItemGrid(const EDA_ITEM *aItem) const override
Gets the coarsest grid that applies to an item.
VECTOR2I AlignToSegment(const VECTOR2I &aPoint, const SEG &aSeg)
VECTOR2I AlignToNearestPad(const VECTOR2I &aMousePos, std::deque< PAD * > &aPads)
virtual VECTOR2I Align(const VECTOR2I &aPoint, GRID_HELPER_GRIDS aGrid) const
Definition: grid_helper.h:60
PCB_GRID_HELPER(TOOL_MANAGER *aToolMgr, MAGNETIC_SETTINGS *aMagneticSettings)
A set of BOARD_ITEMs (i.e., without duplicates).
Definition: pcb_group.h:52
bool IsFootprintEditor() const
const VECTOR2I & GetStart() const
Definition: pcb_track.h:122
const VECTOR2I & GetEnd() const
Definition: pcb_track.h:119
Definition: seg.h:42
VECTOR2I A
Definition: seg.h:49
ecoord SquaredDistance(const SEG &aSeg) const
Definition: seg.cpp:75
VECTOR2I::extended_type ecoord
Definition: seg.h:44
VECTOR2I B
Definition: seg.h:50
VECTOR2I Center() const
Definition: seg.h:372
OPT_VECTOR2I IntersectLines(const SEG &aSeg) const
Compute the intersection point of lines passing through ends of (this) and aSeg.
Definition: seg.h:220
const VECTOR2I & GetP1() const
Definition: shape_arc.h:114
int IntersectLine(const SEG &aSeg, std::vector< VECTOR2I > *aIpsBuffer) const
Find intersection points between this arc and aSeg, treating aSeg as an infinite line.
Definition: shape_arc.cpp:295
const VECTOR2I & GetP0() const
Definition: shape_arc.h:113
Represent a polyline containing arcs as well as line segments: A chain of connected line and/or arc s...
void Move(const VECTOR2I &aVector) override
void SetClosed(bool aClosed)
Mark the line chain as closed (i.e.
void Append(int aX, int aY, bool aAllowDuplication=false)
Append a new point at the end of the line chain.
void Rotate(const EDA_ANGLE &aAngle, const VECTOR2I &aCenter={ 0, 0 }) override
Rotate all vertices by a given angle.
virtual const SEG GetSegment(int aIndex) const override
const VECTOR2I NearestPoint(const VECTOR2I &aP, bool aAllowInternalShapePoints=true) const
Find a point on the line chain that is closest to point aP.
virtual size_t GetSegmentCount() const override
Represent a set of closed polygons.
CONST_ITERATOR CIterateWithHoles(int aOutline) const
Master controller class:
Definition: tool_manager.h:62
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:421
APP_SETTINGS_BASE * GetSettings() const
Definition: tool_manager.h:400
KIGFX::VIEW * GetView() const
Definition: tool_manager.h:391
static constexpr extended_type ECOORD_MAX
Definition: vector2d.h:75
Handle a list of polygons defining a copper zone.
Definition: zone.h:73
static constexpr EDA_ANGLE ANGLE_90
Definition: eda_angle.h:403
@ ERROR_INSIDE
GRID_HELPER_GRIDS
Definition: grid_helper.h:37
@ GRID_VIAS
Definition: grid_helper.h:43
@ GRID_TEXT
Definition: grid_helper.h:44
@ GRID_CURRENT
Definition: grid_helper.h:39
@ GRID_GRAPHICS
Definition: grid_helper.h:45
@ GRID_CONNECTABLE
Definition: grid_helper.h:41
@ GRID_WIRES
Definition: grid_helper.h:42
bool IsPcbLayer(int aLayer)
Test whether a layer is a valid layer for Pcbnew.
Definition: layer_ids.h:520
@ LAYER_AUX_ITEMS
Auxiliary items (guides, rule, etc)
Definition: layer_ids.h:226
@ LAYER_ANCHOR
anchor of items having an anchor point (texts, footprints)
Definition: layer_ids.h:205
PCB_LAYER_ID
A quick note on layer IDs:
Definition: layer_ids.h:60
This file contains miscellaneous commonly used macros and functions.
#define KI_FALLTHROUGH
The KI_FALLTHROUGH macro is to be used when switch statement cases should purposely fallthrough from ...
Definition: macros.h:83
@ GEOMETRY
Position or shape has changed.
Definition: view_item.h:54
EDA_ANGLE abs(const EDA_ANGLE &aAngle)
Definition: eda_angle.h:390
unsigned int OVAL_KEY_POINT_FLAGS
Definition: oval.h:43
@ OVAL_CARDINAL_EXTREMES
Definition: oval.h:39
@ OVAL_CAP_TIPS
Definition: oval.h:35
@ OVAL_SIDE_MIDPOINTS
Definition: oval.h:37
@ OVAL_CENTER
Definition: oval.h:34
std::vector< VECTOR2I > GetOvalKeyPoints(const VECTOR2I &aOvalSize, const EDA_ANGLE &aRotation, OVAL_KEY_POINT_FLAGS aFlags)
Get a list of interesting points on an oval (rectangle with semicircular end caps)
Definition: oval.cpp:31
Class to handle a set of BOARD_ITEMs.
std::optional< VECTOR2I > OPT_VECTOR2I
Definition: seg.h:39
double Distance(const VECTOR2I &aP) const
Definition: grid_helper.h:142
MAGNETIC_OPTIONS tracks
MAGNETIC_OPTIONS pads
This file contains data structures that are saved in the project file or project local settings file ...
bool graphics
Graphic lines, shapes, polygons.
bool footprints
Allow selecting entire footprints.
bool text
Text (free or attached to a footprint)
GRID_SETTINGS grid
Definition: app_settings.h:81
void RotatePoint(int *pX, int *pY, const EDA_ANGLE &aAngle)
Calculate the new point of coord coord pX, pY, for a rotation center 0, 0.
Definition: trigo.cpp:228
@ PCB_SHAPE_T
class PCB_SHAPE, a segment not on copper layers
Definition: typeinfo.h:88
@ PCB_DIM_ORTHOGONAL_T
class PCB_DIM_ORTHOGONAL, a linear dimension constrained to x/y
Definition: typeinfo.h:105
@ PCB_DIM_LEADER_T
class PCB_DIM_LEADER, a leader dimension (graphic item)
Definition: typeinfo.h:102
@ PCB_VIA_T
class PCB_VIA, a via (like a track segment on a copper layer)
Definition: typeinfo.h:97
@ PCB_DIM_CENTER_T
class PCB_DIM_CENTER, a center point marking (graphic item)
Definition: typeinfo.h:103
@ PCB_GROUP_T
class PCB_GROUP, a set of BOARD_ITEMs
Definition: typeinfo.h:110
@ PCB_TEXTBOX_T
class PCB_TEXTBOX, wrapped text on a layer
Definition: typeinfo.h:93
@ PCB_ZONE_T
class ZONE, a copper pour area
Definition: typeinfo.h:107
@ PCB_TEXT_T
class PCB_TEXT, text on a layer
Definition: typeinfo.h:92
@ PCB_REFERENCE_IMAGE_T
class PCB_REFERENCE_IMAGE, bitmap on a layer
Definition: typeinfo.h:89
@ PCB_FIELD_T
class PCB_FIELD, text associated with a footprint property
Definition: typeinfo.h:90
@ PCB_MARKER_T
class PCB_MARKER, a marker used to show something
Definition: typeinfo.h:99
@ PCB_TARGET_T
class PCB_TARGET, a target (graphic item)
Definition: typeinfo.h:106
@ PCB_FOOTPRINT_T
class FOOTPRINT, a footprint
Definition: typeinfo.h:86
@ PCB_DIM_ALIGNED_T
class PCB_DIM_ALIGNED, a linear dimension (graphic item)
Definition: typeinfo.h:101
@ PCB_PAD_T
class PAD, a pad in a footprint
Definition: typeinfo.h:87
@ PCB_ARC_T
class PCB_ARC, an arc track segment on a copper layer
Definition: typeinfo.h:98
@ PCB_DIMENSION_T
class PCB_DIMENSION_BASE: abstract dimension meta-type
Definition: typeinfo.h:100
@ PCB_TRACE_T
class PCB_TRACK, a track segment (segment on a copper layer)
Definition: typeinfo.h:96
@ PCB_DIM_RADIAL_T
class PCB_DIM_RADIAL, a radius or diameter dimension
Definition: typeinfo.h:104
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:121
VECTOR2< int32_t > VECTOR2I
Definition: vector2d.h:673
VECTOR2< double > VECTOR2D
Definition: vector2d.h:672