KiCad PCB EDA Suite
Loading...
Searching...
No Matches
ee_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 The 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, see <https://www.gnu.org/licenses/>.
20 */
21
22#include <functional>
23#include <cmath>
24#include <advanced_config.h>
25#include <macros.h>
27#include <eeschema_settings.h>
28#include <sch_base_frame.h>
29#include <sch_pin.h>
30#include <sch_symbol.h>
32#include <sch_group.h>
33#include <sch_item.h>
34#include <sch_line.h>
35#include <sch_shape.h>
36#include <sch_table.h>
37#include <sch_tablecell.h>
38#include <sch_painter.h>
40#include <snap/snap_inference.h>
41#include <tool/snap_frame.h>
42#include <tool/tool_manager.h>
43#include <sch_tool_base.h>
45#include <trigo.h>
46#include <view/view.h>
47#include "ee_grid_helper.h"
48
49
50namespace
51{
52std::optional<INTERSECTABLE_GEOM> getSchematicIntersectable( const SCH_ITEM& aItem )
53{
54 if( aItem.Type() == SCH_LINE_T )
55 {
56 const SCH_LINE& line = static_cast<const SCH_LINE&>( aItem );
57 return SEG( line.GetStartPoint(), line.GetEndPoint() );
58 }
59
60 if( aItem.Type() != SCH_SHAPE_T )
61 return std::nullopt;
62
63 const SCH_SHAPE& shape = static_cast<const SCH_SHAPE&>( aItem );
64
65 switch( shape.GetShape() )
66 {
67 case SHAPE_T::SEGMENT: return SEG( shape.GetStart(), shape.GetEnd() );
68 case SHAPE_T::CIRCLE: return CIRCLE( shape.GetCenter(), shape.GetRadius() );
69 case SHAPE_T::ARC: return SHAPE_ARC( shape.GetStart(), shape.GetArcMid(), shape.GetEnd(), 0 );
70 case SHAPE_T::RECTANGLE: return BOX2I::ByCorners( shape.GetStart(), shape.GetEnd() );
71 default: return std::nullopt;
72 }
73}
74} // namespace
75
76
81
82
85{
86 if( !m_toolMgr )
87 return;
88
89 KIGFX::VIEW* view = m_toolMgr->GetView();
90
91 m_viewAxis.SetSize( 20000 );
93 m_viewAxis.SetColor( COLOR4D( 0.0, 0.1, 0.4, 0.8 ) );
94 m_viewAxis.SetDrawAtZero( true );
95 view->Add( &m_viewAxis );
96 view->SetVisible( &m_viewAxis, false );
97
99 m_viewSnapPoint.SetColor( COLOR4D( 0.0, 0.1, 0.4, 1.0 ) );
100 m_viewSnapPoint.SetDrawAtZero( true );
101 view->Add( &m_viewSnapPoint );
102 view->SetVisible( &m_viewSnapPoint, false );
103}
104
105
107{
108 if( !m_toolMgr )
109 return;
110
111 KIGFX::VIEW* view = m_toolMgr->GetView();
112
113 view->Remove( &m_viewAxis );
114 view->Remove( &m_viewSnapPoint );
115}
116
117
118void EE_GRID_HELPER::AddConstructionItems( std::vector<SCH_ITEM*> aItems, bool aExtensionOnly, bool aIsPersistent )
119{
120 if( !ADVANCED_CFG::GetCfg().m_EnableExtensionSnaps )
121 return;
122
123 if( !snapInferenceSettings().constructionExtensions )
124 return;
125
126 auto batch = std::make_unique<CONSTRUCTION_MANAGER::CONSTRUCTION_ITEM_BATCH>();
127
128 for( SCH_ITEM* item : aItems )
129 {
130 std::vector<KIGFX::CONSTRUCTION_GEOM::DRAWABLE> drawables;
131 std::optional<SEG> segment;
132
133 if( item->Type() == SCH_LINE_T )
134 {
135 const SCH_LINE& line = static_cast<const SCH_LINE&>( *item );
136 segment = SEG( line.GetStartPoint(), line.GetEndPoint() );
137 }
138 else if( item->Type() == SCH_SHAPE_T )
139 {
140 const SCH_SHAPE& shape = static_cast<const SCH_SHAPE&>( *item );
141
142 if( shape.GetShape() == SHAPE_T::SEGMENT )
143 {
144 segment = SEG( shape.GetStart(), shape.GetEnd() );
145 }
146 else if( shape.GetShape() == SHAPE_T::ARC )
147 {
148 drawables.emplace_back( CIRCLE( shape.GetCenter(), shape.GetRadius() ) );
149 drawables.emplace_back( shape.GetCenter() );
150 }
151 else if( shape.GetShape() == SHAPE_T::CIRCLE )
152 {
153 drawables.emplace_back( shape.GetCenter() );
154 }
155 }
156
157 if( segment )
158 {
159 if( aExtensionOnly )
160 {
161 VECTOR2I direction = segment->B - segment->A;
162 drawables.emplace_back( HALF_LINE( segment->A, segment->A - direction ) );
163 drawables.emplace_back( HALF_LINE( segment->B, segment->B + direction ) );
164 }
165 else
166 {
167 drawables.emplace_back( LINE( *segment ) );
168 }
169
170 if( aIsPersistent )
171 {
172 drawables.emplace_back( segment->A );
173 drawables.emplace_back( segment->B );
174 }
175 }
176
177 std::vector<CONSTRUCTION_MANAGER::CONSTRUCTION_ITEM::DRAWABLE_ENTRY> entries;
178
179 for( KIGFX::CONSTRUCTION_GEOM::DRAWABLE& drawable : drawables )
180 entries.push_back( { std::move( drawable ), 1 } );
181
182 batch->push_back( { CONSTRUCTION_MANAGER::SOURCE::FROM_ITEMS, item, std::move( entries ) } );
183 }
184
185 getSnapManager().GetConstructionManager().ProposeConstructionItems( std::move( batch ), aIsPersistent );
186}
187
188
190{
192
193 if( !m_toolMgr )
194 return settings;
195
196 if( SCH_BASE_FRAME* frame = dynamic_cast<SCH_BASE_FRAME*>( m_toolMgr->GetToolHolder() ) )
197 {
198 // eeconfig() and libeditconfig() are unrelated types, so the editor has to be resolved
199 // first; a plain dynamic_cast silently yields defaults in the symbol editor.
200 if( frame->IsType( FRAME_SCH_SYMBOL_EDITOR ) )
201 {
202 if( SYMBOL_EDITOR_SETTINGS* cfg = frame->libeditconfig() )
203 settings = cfg->m_SnapInference;
204 }
205 else if( EESCHEMA_SETTINGS* cfg = frame->eeconfig() )
206 {
207 settings = cfg->m_SnapInference;
208 }
209 }
210
211 return settings;
212}
213
214
216{
217 if( aItem.Type() == SCH_SYMBOL_T )
218 return static_cast<const SCH_SYMBOL&>( aItem ).GetBodyAndPinsBoundingBox();
219
220 return aItem.GetBoundingBox();
221}
222
223
224std::vector<std::pair<const SCH_PIN*, VECTOR2I>> EE_GRID_HELPER::layoutPins( SCH_ITEM& aItem )
225{
226 std::vector<std::pair<const SCH_PIN*, VECTOR2I>> pins;
227
228 if( aItem.Type() == SCH_PIN_T )
229 {
230 SCH_PIN& pin = static_cast<SCH_PIN&>( aItem );
231 pins.emplace_back( &pin, pin.GetPosition() );
232 }
233 else if( aItem.Type() == SCH_SYMBOL_T )
234 {
235 for( SCH_PIN* pin : static_cast<SCH_SYMBOL&>( aItem ).GetPins() )
236 pins.emplace_back( pin, pin->GetPosition() );
237 }
238
239 return pins;
240}
241
242
244 const SCH_SELECTION& aItems )
245{
246 clearAnchors();
247
248 // If we're working with any connectable objects, skip non-connectable objects
249 // since they are often off-grid, e.g. text anchors
250 bool hasConnectables = false;
251
252 for( EDA_ITEM* item : aItems )
253 {
254 GRID_HELPER_GRIDS grid = GetItemGrid( static_cast<SCH_ITEM*>( item ) );
255 if( grid == GRID_CONNECTABLE || grid == GRID_WIRES )
256 {
257 hasConnectables = true;
258 break;
259 }
260 }
261
262 for( EDA_ITEM* item : aItems )
263 computeAnchors( static_cast<SCH_ITEM*>( item ), aMousePos, true, !hasConnectables );
264
265 double worldScale = m_toolMgr->GetView()->GetGAL()->GetWorldScale();
266 double lineSnapMinCornerDistance = 50.0 / worldScale;
267
268 ANCHOR* nearestOutline = nearestAnchor( aMousePos, OUTLINE, aGrid );
269 ANCHOR* nearestCorner = nearestAnchor( aMousePos, CORNER, aGrid );
270 ANCHOR* nearestOrigin = nearestAnchor( aMousePos, ORIGIN, aGrid );
271 ANCHOR* best = nullptr;
272 double minDist = std::numeric_limits<double>::max();
273
274 if( nearestOrigin )
275 {
276 minDist = nearestOrigin->Distance( aMousePos );
277 best = nearestOrigin;
278 }
279
280 if( nearestCorner )
281 {
282 double dist = nearestCorner->Distance( aMousePos );
283
284 if( dist < minDist )
285 {
286 minDist = dist;
287 best = nearestCorner;
288 }
289 }
290
291 if( nearestOutline )
292 {
293 double dist = nearestOutline->Distance( aMousePos );
294
295 if( minDist > lineSnapMinCornerDistance && dist < minDist )
296 best = nearestOutline;
297 }
298
299 VECTOR2I ret = best ? best->pos : aMousePos;
300
301 if( best )
302 {
303 std::optional<BOX2I> movingBounds;
304 bool pinEnd = false;
305
306 // A symbol's pin anchors are tagged with the symbol, not the pin, so the grab is
307 // classified against pin geometry rather than against the anchor's item.
308 for( EDA_ITEM* item : aItems )
309 {
310 SCH_ITEM& schematicItem = *static_cast<SCH_ITEM*>( item );
311 BOX2I bounds = layoutBounds( schematicItem );
312
313 if( movingBounds )
314 movingBounds->Merge( bounds );
315 else
316 movingBounds = bounds;
317
318 if( !pinEnd )
319 {
320 std::vector<std::pair<const SCH_PIN*, VECTOR2I>> pins = layoutPins( schematicItem );
321
322 pinEnd = std::any_of( pins.begin(), pins.end(),
323 [&]( const std::pair<const SCH_PIN*, VECTOR2I>& aPin )
324 {
325 return aPin.second == ret;
326 } );
327 }
328 }
329
330 setLayoutReference( ret, movingBounds, pinEnd );
331 }
332 else
333 {
334 setLayoutReference( ret, std::nullopt, false );
335 }
336
337 return ret;
338}
339
340
342{
343 SCH_SELECTION skipItems;
344
345 // No skip item means nothing is moving, which selects the picker snap profile
346 if( aSkip )
347 skipItems.Add( aSkip );
348
349 return ResolveSnap( aOrigin, aGrid, skipItems );
350}
351
352
354 std::optional<VECTOR2I> aMovingReferencePoint )
355{
356 const SNAP_RANGES ranges = computeSnapRanges( canUseGrid() );
357 const double snapScale = ranges.scale;
358 const int snapRange = ranges.range;
359 const int snapIn = ranges.in;
360 const int snapOut = ranges.out;
361
362 const SNAP_INFERENCE_SETTINGS inferenceSettings = snapInferenceSettings();
363
364 const bool constructionEnabled =
366
367 if( !constructionEnabled )
369
370 BOX2I bb( VECTOR2I( aOrigin.x - snapRange / 2, aOrigin.y - snapRange / 2 ), VECTOR2I( snapRange, snapRange ) );
371
372 std::optional<ANCHOR> retained = m_snapItem;
373 clearAnchors();
374
375 const std::set<SCH_ITEM*> visibleItems = queryVisible( bb, aSkip );
376
377 for( SCH_ITEM* item : visibleItems )
378 computeAnchors( item, aOrigin );
379
380 ANCHOR* nearest = nearestAnchor( aOrigin, SNAPPABLE, aGrid );
381 VECTOR2I nearestGrid = Align( aOrigin, aGrid );
382
384 {
385 ad->ClearAnchors();
386 for( const ANCHOR& a : m_anchors )
387 ad->AddAnchor( a.pos );
388
389 ad->SetNearest( nearest ? OPT_VECTOR2I( nearest->pos ) : std::nullopt );
390 m_toolMgr->GetView()->Update( ad, KIGFX::GEOMETRY );
391 }
392
394
396 const VECTOR2D gridSize = GetGridSize( aGrid );
397
398 std::optional<VECTOR2I> guideSnap;
399
400 if( m_enableSnapLine )
401 guideSnap = SnapToConstructionLines( aOrigin, nearestGrid, gridSize, snapRange );
402
403 const auto anchorId = [&]( const ANCHOR& aAnchor )
404 {
405 std::vector<SNAP_TARGET_ID> targets;
406
407 for( const EDA_ITEM* item : aAnchor.items )
408 {
409 if( item )
410 targets.push_back( SnapTargetId( item->m_Uuid ) );
411 }
412
413 SNAP_ID_KIND kind =
415
416 if( targets.empty() )
417 return MakePointSnapId( kind, aAnchor.pos, aAnchor.pointTypes );
418
419 if( targets.size() == 1 )
420 return SNAP_STABLE_ID{ kind, targets.front(), aAnchor.pointTypes, 0 };
421
422 return MakeCompositeSnapId( kind, targets, aAnchor.pointTypes );
423 };
424
425 SNAP_SOURCE_CONTEXT context;
427 context.sourcePoint = aOrigin;
428 context.movingReferencePoint = aMovingReferencePoint;
430
431 for( EDA_ITEM* item : aSkip )
432 {
433 BOX2I bounds = layoutBounds( *static_cast<SCH_ITEM*>( item ) );
434
435 if( context.movingBounds )
436 context.movingBounds->Merge( bounds );
437 else
438 context.movingBounds = bounds;
439 }
440
441 if( aSkip.GetSize() == 1 )
442 {
443 SCH_ITEM* sourceItem = static_cast<SCH_ITEM*>( *aSkip.begin() );
445
448
449 if( sourceItem->Type() == SCH_LINE_T && m_pointEditProfile )
450 {
451 SCH_LINE* line = static_cast<SCH_LINE*>( sourceItem );
452 context.stationarySourceLeg =
453 line->GetStartPoint().SquaredDistance( aOrigin ) > line->GetEndPoint().SquaredDistance( aOrigin )
454 ? line->GetStartPoint()
455 : line->GetEndPoint();
456 }
457 }
458
459 enum class PRESENTATION_KIND
460 {
461 ANCHOR_MARKER,
462 GUIDE
463 };
464
465 struct PRESENTATION
466 {
467 PRESENTATION_KIND kind;
468 std::optional<ANCHOR> anchor;
469 bool proposeConstruction;
470 };
471
473 frame.context = context;
477 frame.trace = snapTraceCallback( context );
478
479 SNAP_INFERENCE_PROVIDER inferenceProvider;
480 SNAP_INFERENCE_PROVIDER tangentProvider;
481 const bool inferenceEnabled = m_enableSnap
482 && ( inferenceSettings.objectGeometry || inferenceSettings.tangentNormal
483 || inferenceSettings.alignmentDistribution );
484
485 // CollectTangentNormal only reads arcs and circles, and only when dragging away from a fixed leg
486 const bool tangentEnabled = inferenceSettings.tangentNormal && context.stationarySourceLeg.has_value();
487
488 if( inferenceEnabled && context.movingItem )
489 {
490 for( size_t i = 0; i < m_stationarySelfSegments.size(); ++i )
491 {
492 SNAP_STABLE_ID id =
493 MakeDerivedSnapId( SNAP_ID_KIND::SELF_SEGMENT, *context.movingItem, static_cast<int>( i ) );
494 context.stationarySelfFeatures.push_back( id );
495
496 if( inferenceSettings.objectGeometry )
497 inferenceProvider.AddPath( { id, m_stationarySelfSegments[i], false } );
498 }
499 }
500
501 emitAngleBranchCandidates( frame.candidates, aOrigin, snapScale );
502
503 if( inferenceEnabled )
504 {
505 for( SCH_ITEM* item : visibleItems )
506 {
507 if( inferenceSettings.objectGeometry || tangentEnabled )
508 {
509 std::optional<INTERSECTABLE_GEOM> geometry = getSchematicIntersectable( *item );
510
511 if( geometry )
512 {
514 static_cast<int>( item->Type() ), 0 };
515 const bool curved = std::holds_alternative<CIRCLE>( *geometry )
516 || std::holds_alternative<SHAPE_ARC>( *geometry );
517
518 if( inferenceSettings.objectGeometry )
519 inferenceProvider.AddPath( { id, *geometry, false } );
520
521 if( tangentEnabled && curved )
522 tangentProvider.AddPath( { std::move( id ), std::move( *geometry ), false } );
523 }
524 }
525
526 if( inferenceSettings.alignmentDistribution )
527 {
528 inferenceProvider.AddBounds( { { SNAP_ID_KIND::ITEM_GEOMETRY, SnapTargetId( item->m_Uuid ),
529 static_cast<int>( item->Type() ), 0 },
530 layoutBounds( *item ),
531 std::nullopt } );
532
533 for( const auto& [pin, position] : layoutPins( *item ) )
534 {
535 inferenceProvider.AddAlignmentPoint(
537 position,
538 SnapTargetId( item->m_Uuid ) } );
539 }
540 }
541 }
542 }
543
544 int constructionIndex = 0;
545
546 if( constructionEnabled )
547 {
548 for( const CONSTRUCTION_MANAGER::CONSTRUCTION_ITEM_BATCH& batch : getSnapManager().GetConstructionItems() )
549 {
550 for( const CONSTRUCTION_MANAGER::CONSTRUCTION_ITEM& item : batch )
551 {
552 SNAP_TARGET_ID target = item.Item ? SnapTargetId( item.Item->m_Uuid ) : SNAP_TARGET_ID{};
553
554 for( const CONSTRUCTION_MANAGER::CONSTRUCTION_ITEM::DRAWABLE_ENTRY& entry : item.Constructions )
555 {
556 SNAP_STABLE_ID id{ SNAP_ID_KIND::CONSTRUCTION, target, constructionIndex++, 0 };
557
558 std::visit(
559 [&]( const auto& drawable )
560 {
561 using DRAWABLE_TYPE = std::decay_t<decltype( drawable )>;
562
563 if constexpr( std::is_same_v<DRAWABLE_TYPE, VECTOR2I> )
564 {
565 frame.candidates.push_back( SNAP_CANDIDATE::Point(
567 drawable, drawable.Distance( aOrigin ) / snapScale ) );
568 }
569 else
570 {
571 inferenceProvider.AddPath( { id, drawable, false, true } );
572 }
573 },
574 entry.Drawable );
575 }
576 }
577 }
578 }
579
580 if( m_enableSnap && ( inferenceSettings.objectGeometry || constructionEnabled ) )
581 {
582 for( SNAP_CANDIDATE& candidate : inferenceProvider.CollectObjectGeometry( context, snapRange ) )
583 frame.candidates.push_back( std::move( candidate ) );
584 }
585
586 if( m_enableSnap && inferenceSettings.tangentNormal && context.stationarySourceLeg )
587 {
588 for( SNAP_CANDIDATE& candidate : tangentProvider.CollectTangentNormal( context, snapRange, true, true ) )
589 {
590 frame.candidates.push_back( std::move( candidate ) );
591 }
592 }
593
594 if( m_enableSnap && inferenceSettings.alignmentDistribution && context.movingBounds )
595 {
596 for( SNAP_CANDIDATE& candidate : inferenceProvider.CollectAlignment( context, snapRange ) )
597 frame.candidates.push_back( std::move( candidate ) );
598
599 for( SNAP_CANDIDATE& candidate : inferenceProvider.CollectEqualSpacing( context, snapRange ) )
600 frame.candidates.push_back( std::move( candidate ) );
601 }
602
603 if( m_enableSnap && retained && retained->Distance( aOrigin ) <= snapOut )
604 {
605 SNAP_STABLE_ID retainedId = anchorId( *retained );
606 frame.retainedId = retainedId;
607 frame.candidates.push_back( SNAP_CANDIDATE::Point( retainedId, SNAP_PRIORITY_TIER::OBJECT,
608 retained->flags & CONSTRUCTED
611 retained->pos, retained->Distance( aOrigin ) / snapScale ) );
612 frame.presentation.emplace( retainedId, PRESENTATION{ PRESENTATION_KIND::ANCHOR_MARKER, *retained, false } );
613 }
614
615 if( m_enableSnap && nearest && nearest->Distance( aOrigin ) <= snapIn && m_skipPoint != nearest->pos )
616 {
617 SNAP_STABLE_ID nearestId = anchorId( *nearest );
619 nearest->flags & CONSTRUCTED
622 nearest->pos, nearest->Distance( aOrigin ) / snapScale ) );
623 frame.presentation.insert_or_assign( nearestId,
624 PRESENTATION{ PRESENTATION_KIND::ANCHOR_MARKER, *nearest, true } );
625 }
626
627 if( guideSnap && m_skipPoint != *guideSnap )
628 {
630 SNAP_CANDIDATE candidate =
632 *guideSnap, guideSnap->Distance( aOrigin ) / snapScale );
633 frame.candidates.push_back( std::move( candidate ) );
634 frame.presentation.emplace( guideId, PRESENTATION{ PRESENTATION_KIND::GUIDE, std::nullopt, false } );
635 }
636
637 emitSelfAndGridCandidates( frame.candidates, context, aOrigin, nearestGrid, snapScale, snapRange, canUseGrid() );
638
639 // Object retention wins because its tier already outranks angle restriction.
640 if( !frame.retainedId && m_retainedAngleBranch )
642
643 SNAP_FRAME_OUTPUT<PRESENTATION> output = ResolveSnapFrame( std::move( frame ) );
644 SNAP_RESULT& result = output.result;
646
647 bool keepConstructionProposal = false;
648
649 if( output.presentation && output.presentation->payload.kind == PRESENTATION_KIND::GUIDE )
650 {
651 snapLineManager.SetSnapLineEnd( result.position );
652 m_toolMgr->GetView()->SetVisible( &m_viewSnapPoint, false );
653 m_snapItem = std::nullopt;
654 }
655 else if( output.presentation && output.presentation->payload.anchor )
656 {
657 const PRESENTATION& presentation = output.presentation->payload;
658 std::vector<SCH_ITEM*> items;
659
660 for( EDA_ITEM* item : presentation.anchor->items )
661 {
662 if( item && item->IsSCH_ITEM() )
663 items.push_back( static_cast<SCH_ITEM*>( item ) );
664 }
665
666 if( presentation.proposeConstruction && constructionEnabled && !items.empty() )
667 {
668 AddConstructionItems( std::move( items ), true, false );
669 keepConstructionProposal = true;
670 }
671
672 m_snapItem = *presentation.anchor;
673 m_viewSnapPoint.SetPosition( result.position );
674 m_viewSnapPoint.SetSnapTypes( m_snapItem->pointTypes );
675 snapLineManager.SetSnapLineOrigin( result.position );
676 snapLineManager.SetSnapLineEnd( std::nullopt );
677
678 if( m_toolMgr->GetView()->IsVisible( &m_viewSnapPoint ) )
679 m_toolMgr->GetView()->Update( &m_viewSnapPoint, KIGFX::GEOMETRY );
680 else
681 m_toolMgr->GetView()->SetVisible( &m_viewSnapPoint, true );
682 }
683 else
684 {
685 m_snapItem = std::nullopt;
686 snapLineManager.SetSnapLineEnd( std::nullopt );
687 m_toolMgr->GetView()->SetVisible( &m_viewSnapPoint, false );
688 }
689
691
692 if( constructionEnabled && !keepConstructionProposal && ADVANCED_CFG::GetCfg().m_ExtensionSnapActivateOnHover )
693 {
694 for( SCH_ITEM* item : visibleItems )
695 {
696 if( item->HitTest( aOrigin, 0 ) )
697 {
698 AddConstructionItems( { item }, true, false );
699 keepConstructionProposal = true;
700 break;
701 }
702 }
703 }
704
705 if( !keepConstructionProposal )
707
708 return result;
709}
710
711
713{
714 const GRID_SETTINGS& grid = m_toolMgr->GetSettings()->m_Window.grid;
715 int idx = -1;
716
717 VECTOR2D g = m_toolMgr->GetView()->GetGAL()->GetGridSize();
718
719 if( !grid.overrides_enabled )
720 return g;
721
722 switch( aGrid )
723 {
724 case GRID_CONNECTABLE:
725 if( grid.override_connected )
726 idx = grid.override_connected_idx;
727
728 break;
729
730 case GRID_WIRES:
731 if( grid.override_wires )
732 idx = grid.override_wires_idx;
733
734 break;
735
736 case GRID_TEXT:
737 if( grid.override_text )
738 idx = grid.override_text_idx;
739
740 break;
741
742 case GRID_GRAPHICS:
743 if( grid.override_graphics )
744 idx = grid.override_graphics_idx;
745
746 break;
747
748 default:
749 break;
750 }
751
752 if( idx >= 0 && idx < (int) grid.grids.size() )
753 g = grid.grids[idx].ToDouble( schIUScale );
754
755 return g;
756}
757
758
760{
761 if( !m_snapItem )
762 return nullptr;
763
764 if( m_snapItem->items.empty() )
765 return nullptr;
766
767 return static_cast<SCH_ITEM*>( m_snapItem->items[0] );
768}
769
770
771std::set<SCH_ITEM*> EE_GRID_HELPER::queryVisible( const BOX2I& aArea,
772 const SCH_SELECTION& aSkipList ) const
773{
774 std::set<SCH_ITEM*> items;
775 std::vector<KIGFX::VIEW::LAYER_ITEM_PAIR> selectedItems;
776
777 EDA_DRAW_FRAME* frame = dynamic_cast<EDA_DRAW_FRAME*>( m_toolMgr->GetToolHolder() );
778 KIGFX::VIEW* view = m_toolMgr->GetView();
779
780 view->Query( aArea, selectedItems );
781
782 for( const KIGFX::VIEW::LAYER_ITEM_PAIR& it : selectedItems )
783 {
784 if( !it.first->IsSCH_ITEM() )
785 continue;
786
787 SCH_ITEM* item = static_cast<SCH_ITEM*>( it.first );
788
789 if( frame && frame->IsType( FRAME_SCH_SYMBOL_EDITOR ) )
790 {
791 // If we are in the symbol editor, don't use the symbol itself
792 if( item->Type() == LIB_SYMBOL_T )
793 continue;
794 }
795 else
796 {
797 // If we are not in the symbol editor, don't use symbol-editor-private items
798 if( item->IsPrivate() )
799 continue;
800 }
801
802 // The item must be visible and on an active layer
803 if( view->IsVisible( item ) && item->ViewGetLOD( it.second, view ) < view->GetScale() )
804 items.insert( item );
805 }
806
807 for( EDA_ITEM* skipItem : aSkipList )
808 items.erase( static_cast<SCH_ITEM*>( skipItem ) );
809
810 return items;
811}
812
813
815{
816 if( !aItem )
817 return GRID_CURRENT;
818
819 switch( aItem->Type() )
820 {
821 case LIB_SYMBOL_T:
822 case SCH_SYMBOL_T:
823 case SCH_PIN_T:
824 case SCH_SHEET_PIN_T:
825 case SCH_SHEET_T:
826 case SCH_NO_CONNECT_T:
828 case SCH_HIER_LABEL_T:
829 case SCH_LABEL_T:
831 case SCH_RULE_AREA_T:
832 return GRID_CONNECTABLE;
833
834 case SCH_FIELD_T:
835 case SCH_TEXT_T:
836 return GRID_TEXT;
837
838 case SCH_SHAPE_T:
839 // The text box's border lines are what need to be on the graphic grid
840 case SCH_TEXTBOX_T:
841 case SCH_BITMAP_T:
842 return GRID_GRAPHICS;
843
844 case SCH_JUNCTION_T:
845 return GRID_WIRES;
846
847 case SCH_LINE_T:
848 if( static_cast<const SCH_LINE*>( aItem )->IsConnectable() )
849 return GRID_WIRES;
850 else
851 return GRID_GRAPHICS;
852
855 return GRID_WIRES;
856
857 // Groups need to get the grid of their children
858 case SCH_GROUP_T:
859 {
860 const SCH_GROUP* group = static_cast<const SCH_GROUP*>( aItem );
861
862 // Shouldn't happen
863 if( group->GetItems().empty() )
864 return GRID_CURRENT;
865
866 GRID_HELPER_GRIDS grid = GetItemGrid( *group->GetItems().begin() );
867
868 for( EDA_ITEM* item : static_cast<const SCH_GROUP*>( aItem )->GetItems() )
869 {
870 GRID_HELPER_GRIDS itemGrid = GetItemGrid( item );
871
872 if( GetGridSize( itemGrid ) > GetGridSize( grid ) )
873 grid = itemGrid;
874 }
875
876 return grid;
877 }
878
879 default: return GRID_CURRENT;
880 }
881}
882
883
884void EE_GRID_HELPER::computeAnchors( SCH_ITEM* aItem, const VECTOR2I& aRefPos, bool aFrom, bool aIncludeText )
885{
886 bool isGraphicLine = aItem->Type() == SCH_LINE_T && static_cast<SCH_LINE*>( aItem )->IsGraphicLine();
887
888 switch( aItem->Type() )
889 {
890 case SCH_TEXT_T:
891 case SCH_FIELD_T:
892 {
893 if( aIncludeText )
894 addAnchor( aItem->GetPosition(), ORIGIN, aItem );
895
896 break;
897 }
898
899 case SCH_TABLE_T:
900 {
901 if( aIncludeText )
902 {
903 addAnchor( aItem->GetPosition(), SNAPPABLE | CORNER, aItem );
904 addAnchor( static_cast<SCH_TABLE*>( aItem )->GetEnd(), SNAPPABLE | CORNER, aItem );
905 }
906
907 break;
908 }
909
910 case SCH_TEXTBOX_T:
911 case SCH_TABLECELL_T:
912 {
913 if( aIncludeText )
914 {
915 addAnchor( aItem->GetPosition(), SNAPPABLE | CORNER, aItem );
916 addAnchor( static_cast<SCH_SHAPE*>( aItem )->GetEnd(), SNAPPABLE | CORNER, aItem );
917 }
918
919 break;
920 }
921
922 case SCH_SYMBOL_T:
923 case SCH_SHEET_T:
924 addAnchor( aItem->GetPosition(), ORIGIN, aItem );
926
927 case SCH_JUNCTION_T:
928 case SCH_NO_CONNECT_T:
929 case SCH_LINE_T:
930 // Don't add anchors for graphic lines unless we're including text,
931 // they may be on a non-connectable grid
932 if( isGraphicLine && !aIncludeText )
933 break;
934
937 case SCH_HIER_LABEL_T:
938 case SCH_LABEL_T:
941 case SCH_SHEET_PIN_T:
942 {
943 std::vector<VECTOR2I> pts = aItem->GetConnectionPoints();
944
945 for( const VECTOR2I& pt : pts )
946 addAnchor( VECTOR2I( pt ), SNAPPABLE | CORNER, aItem );
947
948 break;
949 }
950 case SCH_PIN_T:
951 {
952 SCH_PIN* pin = static_cast<SCH_PIN*>( aItem );
953 addAnchor( pin->GetPosition(), SNAPPABLE | ORIGIN, aItem );
954 break;
955 }
956
957 case SCH_GROUP_T:
958 for( EDA_ITEM* item : static_cast<SCH_GROUP*>( aItem )->GetItems() )
959 {
960 computeAnchors( static_cast<SCH_ITEM*>( item ), aRefPos, aFrom, aIncludeText );
961 }
962
963 break;
964
965 default:
966 break;
967 }
968
969 // Don't add anchors for graphic lines unless we're including text,
970 // they may be on a non-connectable grid
971 if( aItem->Type() == SCH_LINE_T && ( aIncludeText || !isGraphicLine ) )
972 {
973 SCH_LINE* line = static_cast<SCH_LINE*>( aItem );
974 VECTOR2I pt = Align( aRefPos );
975
976 if( line->GetStartPoint().x == line->GetEndPoint().x )
977 {
978 VECTOR2I possible( line->GetStartPoint().x, pt.y );
979
980 if( TestSegmentHit( possible, line->GetStartPoint(), line->GetEndPoint(), 0 ) )
981 addAnchor( possible, SNAPPABLE | VERTICAL, aItem );
982 }
983 else if( line->GetStartPoint().y == line->GetEndPoint().y )
984 {
985 VECTOR2I possible( pt.x, line->GetStartPoint().y );
986
987 if( TestSegmentHit( possible, line->GetStartPoint(), line->GetEndPoint(), 0 ) )
988 addAnchor( possible, SNAPPABLE | HORIZONTAL, aItem );
989 }
990 }
991}
992
993
995 GRID_HELPER_GRIDS aGrid )
996{
997 double minDist = std::numeric_limits<double>::max();
998 ANCHOR* best = nullptr;
999
1000 for( ANCHOR& a : m_anchors )
1001 {
1002 if( ( aFlags & a.flags ) != aFlags )
1003 continue;
1004
1005 // A "virtual" anchor with no real items associated shouldn't be filtered out
1006 if( !a.items.empty() )
1007 {
1008 // Filter using the first item
1009 SCH_ITEM* item = static_cast<SCH_ITEM*>( a.items[0] );
1010
1011 if( aGrid == GRID_CONNECTABLE && !item->IsConnectable() )
1012 continue;
1013 else if( aGrid == GRID_GRAPHICS && item->IsConnectable() )
1014 continue;
1015 }
1016
1017 double dist = a.Distance( aPos );
1018
1019 if( dist < minDist )
1020 {
1021 minDist = dist;
1022 best = &a;
1023 }
1024 }
1025
1026 return best;
1027}
constexpr EDA_IU_SCALE schIUScale
Definition base_units.h:123
BOX2< VECTOR2I > BOX2I
Definition box2.h:918
static const ADVANCED_CFG & GetCfg()
Get the singleton instance's config, which is shared by all consumers.
static constexpr BOX2< VECTOR2I > ByCorners(const VECTOR2I &aCorner1, const VECTOR2I &aCorner2)
Definition box2.h:66
void ProposeConstructionItems(std::unique_ptr< CONSTRUCTION_ITEM_BATCH > aBatch, bool aIsPersistent)
Add a batch of construction items to the helper.
void CancelProposal()
Cancel outstanding proposals for new geometry.
void Clear()
Clear all construction items.
std::vector< CONSTRUCTION_ITEM > CONSTRUCTION_ITEM_BATCH
bool IsType(FRAME_T aType) const
The base class for create windows for drawing purpose.
A base class for most all the KiCad significant classes used in schematics and boards.
Definition eda_item.h:96
virtual VECTOR2I GetPosition() const
Definition eda_item.h:282
virtual const BOX2I GetBoundingBox() const
Return the orthogonal bounding box of this object for display purposes.
Definition eda_item.cpp:135
const KIID m_Uuid
Definition eda_item.h:531
KICAD_T Type() const
Returns the type of object.
Definition eda_item.h:108
int GetRadius() const
SHAPE_T GetShape() const
Definition eda_shape.h:185
const VECTOR2I & GetEnd() const
Return the ending point of the graphic.
Definition eda_shape.h:240
const VECTOR2I & GetStart() const
Return the starting point of the graphic.
Definition eda_shape.h:190
VECTOR2I GetArcMid() const
static std::vector< std::pair< const SCH_PIN *, VECTOR2I > > layoutPins(SCH_ITEM &aItem)
Pin connection points the item offers as alignment anchors.
~EE_GRID_HELPER() override
GRID_HELPER_GRIDS GetItemGrid(const EDA_ITEM *aItem) const override
Get the coarsest grid that applies to an item.
VECTOR2I BestDragOrigin(const VECTOR2I &aMousePos, GRID_HELPER_GRIDS aGrid, const SCH_SELECTION &aItems)
std::set< SCH_ITEM * > queryVisible(const BOX2I &aArea, const SCH_SELECTION &aSkipList) const
void AddConstructionItems(std::vector< SCH_ITEM * > aItems, bool aExtensionOnly, bool aIsPersistent)
ANCHOR * nearestAnchor(const VECTOR2I &aPos, int aFlags, GRID_HELPER_GRIDS aGrid)
VECTOR2D GetGridSize(GRID_HELPER_GRIDS aGrid) const override
Return the size of the specified grid.
SCH_ITEM * GetSnapped() const
Function GetSnapped If the EE_GRID_HELPER has highlighted a snap point (target shown),...
SNAP_RESULT ResolveSnap(const VECTOR2I &aOrigin, GRID_HELPER_GRIDS aGrid, SCH_ITEM *aSkip)
SNAP_INFERENCE_SETTINGS snapInferenceSettings() const
Snap inference settings for whichever editor owns this helper.
void computeAnchors(SCH_ITEM *aItem, const VECTOR2I &aRefPos, bool aFrom=false, bool aIncludeText=false)
Insert the local anchor points in to the grid helper for the specified schematic item,...
static BOX2I layoutBounds(const SCH_ITEM &aItem)
Bounds a layout relation should align to.
void retainAcceptedSnaps(const SNAP_RESULT &aResult)
Record which snaps the resolver accepted so they can be re-biased on the next resolve,...
std::optional< VECTOR2I > SnapToConstructionLines(const VECTOR2I &aPoint, const VECTOR2I &aNearestGrid, const VECTOR2D &aGrid, double aSnapRange) const
void addAnchor(const VECTOR2I &aPos, int aFlags, EDA_ITEM *aItem, int aPointTypes=POINT_TYPE::PT_NONE)
SNAP_MANAGER & getSnapManager()
VECTOR2I m_skipPoint
SNAP_RANGES computeSnapRanges(bool aClampToVisibleGrid) const
Compute the snap thresholds.
void emitAngleBranchCandidates(std::vector< SNAP_CANDIDATE > &aCandidates, const VECTOR2I &aOrigin, double aSnapScale) const
Emit the angle-restriction snap candidates (the two branches bracketing the cursor angle) into the cu...
void showConstructionGeometry(bool aShow)
SNAP_RESOLVER::FEASIBILITY_CALLBACK m_feasibilityCallback
std::vector< SEG > m_stationarySelfSegments
TOOL_MANAGER * m_toolMgr
SNAP_RESOLVER::TRACE_CALLBACK snapTraceCallback(const SNAP_SOURCE_CONTEXT &aContext) const
bool m_enableSnapLine
bool m_enableSnap
bool canUseGrid() const
Check whether it is possible to use the grid – this depends both on local grid helper settings and gl...
std::optional< SNAP_STABLE_ID > m_retainedAngleBranch
void clearAnchors()
std::optional< ANCHOR > m_snapItem
SNAP_REFERENCE_PREFERENCE m_layoutReferencePreference
KIGFX::ANCHOR_DEBUG * enableAndGetAnchorDebug()
Enable the anchor debug if permitted and return it.
KIGFX::SNAP_INDICATOR m_viewSnapPoint
virtual VECTOR2I Align(const VECTOR2I &aPoint, GRID_HELPER_GRIDS aGrid) const
KIGFX::ORIGIN_VIEWITEM m_viewAxis
bool m_pointEditProfile
std::vector< SNAP_STABLE_ID > m_stickySnapIds
void setLayoutReference(const VECTOR2I &aPoint, const std::optional< BOX2I > &aBounds, bool aAnchorPoint)
Record the classified drag reference and trace it.
void emitSelfAndGridCandidates(std::vector< SNAP_CANDIDATE > &aCandidates, const SNAP_SOURCE_CONTEXT &aContext, const VECTOR2I &aOrigin, const VECTOR2I &aNearestGrid, double aSnapScale, int aSnapRange, bool aUseGrid) const
Emit the point editor's unchanged self-geometry and the independent grid axes.
void applySnapResultGuides(const SNAP_RESULT &aResult)
std::vector< ANCHOR > m_anchors
View item to draw debug items for anchors.
A color representation with 4 components: red, green, blue, alpha.
Definition color4d.h:101
std::variant< SEG, LINE, HALF_LINE, CIRCLE, SHAPE_ARC, VECTOR2I > DRAWABLE
bool IsSCH_ITEM() const
Definition view_item.h:97
virtual double ViewGetLOD(int aLayer, const VIEW *aView) const
Return the level of detail (LOD) of the item.
Definition view_item.h:151
Hold a (potentially large) number of VIEW_ITEMs and renders them on a graphics device provided by the...
Definition view.h:63
double GetScale() const
Definition view.h:281
virtual void Add(VIEW_ITEM *aItem, int aDrawPriority=-1)
Add a VIEW_ITEM to the view.
Definition view.cpp:300
virtual void Remove(VIEW_ITEM *aItem)
Remove a VIEW_ITEM from the view.
Definition view.cpp:404
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:487
std::pair< VIEW_ITEM *, int > LAYER_ITEM_PAIR
Definition view.h:67
bool IsVisible(const VIEW_ITEM *aItem) const
Return information if the item is visible (or not).
Definition view.cpp:1805
void SetVisible(VIEW_ITEM *aItem, bool aIsVisible=true)
Set the item visibility.
Definition view.cpp:1756
A shim class between EDA_DRAW_FRAME and several derived classes: SYMBOL_EDIT_FRAME,...
A set of SCH_ITEMs (i.e., without duplicates).
Definition sch_group.h:48
Base class for any item which can be embedded within the SCHEMATIC container class,...
Definition sch_item.h:162
virtual bool IsConnectable() const
Definition sch_item.h:524
bool IsPrivate() const
Definition sch_item.h:248
virtual std::vector< VECTOR2I > GetConnectionPoints() const
Add all the connection points for this item to aPoints.
Definition sch_item.h:539
Segment description base class to describe items which have 2 end points (track, wire,...
Definition sch_line.h:38
VECTOR2I GetEndPoint() const
Definition sch_line.h:144
VECTOR2I GetStartPoint() const
Definition sch_line.h:135
VECTOR2I GetCenter() const
Definition sch_shape.h:92
Schematic symbol object.
Definition sch_symbol.h:69
Definition seg.h:38
virtual void Add(EDA_ITEM *aItem)
A null aItem is ignored; the selection never holds null members.
Definition selection.cpp:38
ITER begin()
Definition selection.h:75
virtual unsigned int GetSize() const override
Return the number of stored items.
Definition selection.h:104
bool Empty() const
Checks if there is anything selected.
Definition selection.h:114
std::vector< SNAP_CANDIDATE > CollectObjectGeometry(const SNAP_SOURCE_CONTEXT &aContext, int aRadius) const
std::vector< SNAP_CANDIDATE > CollectEqualSpacing(const SNAP_SOURCE_CONTEXT &aContext, int aRadius) const
void AddBounds(SNAP_OBJECT_BOUNDS aBounds)
std::vector< SNAP_CANDIDATE > CollectTangentNormal(const SNAP_SOURCE_CONTEXT &aContext, int aRadius, bool aTangentEnabled, bool aNormalEnabled) const
void AddPath(SNAP_OBJECT_PATH aPath)
void AddAlignmentPoint(SNAP_ALIGNMENT_POINT aPoint)
std::vector< SNAP_CANDIDATE > CollectAlignment(const SNAP_SOURCE_CONTEXT &aContext, int aRadius) const
void SetSnapLineOrigin(const VECTOR2I &aOrigin)
The snap point is a special point that is located at the last point the cursor snapped to.
void SetSnapLineEnd(const OPT_VECTOR2I &aSnapPoint)
Set the end point of the snap line.
SNAP_LINE_MANAGER & GetSnapLineManager()
CONSTRUCTION_MANAGER & GetConstructionManager()
Master controller class:
constexpr extended_type SquaredDistance(const VECTOR2< T > &aVector) const
Compute the squared distance between two vectors.
Definition vector2d.h:557
@ SEGMENT
Definition eda_shape.h:46
@ RECTANGLE
Use RECTANGLE instead of RECT to avoid collision in a Windows header.
Definition eda_shape.h:47
@ FRAME_SCH_SYMBOL_EDITOR
Definition frame_type.h:31
SNAP_TARGET_ID SnapTargetId(const KIID &aId)
The snap identity of a document item.
Definition grid_helper.h:49
GRID_HELPER_GRIDS
Definition grid_helper.h:55
@ GRID_TEXT
Definition grid_helper.h:62
@ GRID_CURRENT
Definition grid_helper.h:57
@ GRID_GRAPHICS
Definition grid_helper.h:63
@ GRID_CONNECTABLE
Definition grid_helper.h:59
@ GRID_WIRES
Definition grid_helper.h:60
bool m_EnableExtensionSnaps
Enable snap anchors based on item line extensions.
@ LAYER_SCHEMATIC_ANCHOR
Definition layer_ids.h:506
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:79
@ GEOMETRY
Position or shape has changed.
Definition view_item.h:51
Class to handle a set of SCH_ITEMs.
std::optional< VECTOR2I > OPT_VECTOR2I
Definition seg.h:35
SNAP_FRAME_OUTPUT< Payload > ResolveSnapFrame(SNAP_FRAME_INPUT< Payload > aInput)
Definition snap_frame.h:60
SNAP_STABLE_ID MakePointSnapId(SNAP_ID_KIND aKind, const VECTOR2I &aPoint, int aFeatureIndex=0)
SNAP_STABLE_ID MakeCompositeSnapId(SNAP_ID_KIND aKind, const std::vector< SNAP_TARGET_ID > &aTargets, int aFeatureIndex=0)
SNAP_STABLE_ID MakeDerivedSnapId(SNAP_ID_KIND aKind, const SNAP_STABLE_ID &aSource, int aFeatureIndex=0, int aSolutionBranch=0)
SNAP_ID_KIND
std::array< uint8_t, 16 > SNAP_TARGET_ID
KIGFX::CONSTRUCTION_GEOM::DRAWABLE Drawable
Items to be used for the construction of "virtual" anchors, for example, when snapping to a point inv...
double Distance(const VECTOR2I &aP) const
World-space snap thresholds derived from the screen-space snap radius.
int range
Snap radius, optionally clamped to the visible grid.
int in
Distance at which a candidate is picked up.
double scale
SNAP_SCREEN_RADIUS in world units.
int out
Distance at which a held candidate is released.
double rankingHysteresis
Resolver ranking stickiness, as a fraction of the radius.
static SNAP_CANDIDATE Point(SNAP_STABLE_ID aId, SNAP_PRIORITY_TIER aPriority, SNAP_CANDIDATE_SUBTYPE aSubtype, const VECTOR2I &aPoint, double aResidual)
std::optional< SNAP_STABLE_ID > retainedId
Definition snap_frame.h:34
SNAP_RESOLVER::TRACE_CALLBACK trace
Definition snap_frame.h:39
SNAP_RESOLVER::FEASIBILITY_CALLBACK feasibility
Definition snap_frame.h:38
std::map< SNAP_STABLE_ID, Payload > presentation
Definition snap_frame.h:35
SNAP_SOURCE_CONTEXT context
Definition snap_frame.h:32
std::vector< SNAP_CANDIDATE > candidates
Definition snap_frame.h:33
double rankingHysteresis
Definition snap_frame.h:37
std::vector< SNAP_STABLE_ID > stickyIds
Definition snap_frame.h:36
std::optional< SNAP_FRAME_PRESENTATION< Payload > > presentation
Definition snap_frame.h:55
SNAP_RESULT result
Definition snap_frame.h:54
std::optional< VECTOR2I > stationarySourceLeg
std::optional< BOX2I > movingBounds
std::optional< VECTOR2I > movingReferencePoint
std::optional< SNAP_STABLE_ID > movingItem
std::vector< SNAP_STABLE_ID > stationarySelfFeatures
SNAP_EDITOR_PROFILE profile
SNAP_REFERENCE_PREFERENCE referencePreference
KIBIS_PIN * pin
wxString result
Test unit parsing edge cases and error handling.
bool TestSegmentHit(const VECTOR2I &aRefPoint, const VECTOR2I &aStart, const VECTOR2I &aEnd, int aDist)
Test if aRefPoint is with aDistance on the line defined by aStart and aEnd.
Definition trigo.cpp:171
@ SCH_GROUP_T
Definition typeinfo.h:170
@ SCH_TABLE_T
Definition typeinfo.h:162
@ SCH_LINE_T
Definition typeinfo.h:160
@ LIB_SYMBOL_T
Definition typeinfo.h:145
@ SCH_NO_CONNECT_T
Definition typeinfo.h:157
@ SCH_SYMBOL_T
Definition typeinfo.h:169
@ SCH_TABLECELL_T
Definition typeinfo.h:163
@ SCH_FIELD_T
Definition typeinfo.h:147
@ SCH_DIRECTIVE_LABEL_T
Definition typeinfo.h:168
@ SCH_LABEL_T
Definition typeinfo.h:164
@ SCH_SHEET_T
Definition typeinfo.h:172
@ SCH_SHAPE_T
Definition typeinfo.h:146
@ SCH_RULE_AREA_T
Definition typeinfo.h:167
@ SCH_HIER_LABEL_T
Definition typeinfo.h:166
@ SCH_BUS_BUS_ENTRY_T
Definition typeinfo.h:159
@ SCH_SHEET_PIN_T
Definition typeinfo.h:171
@ SCH_TEXT_T
Definition typeinfo.h:148
@ SCH_BUS_WIRE_ENTRY_T
Definition typeinfo.h:158
@ SCH_BITMAP_T
Definition typeinfo.h:161
@ SCH_TEXTBOX_T
Definition typeinfo.h:149
@ SCH_GLOBAL_LABEL_T
Definition typeinfo.h:165
@ SCH_JUNCTION_T
Definition typeinfo.h:156
@ SCH_PIN_T
Definition typeinfo.h:150
VECTOR2< int32_t > VECTOR2I
Definition vector2d.h:683
VECTOR2< double > VECTOR2D
Definition vector2d.h:682