KiCad PCB EDA Suite
Loading...
Searching...
No Matches
sch_line.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) 2015 Jean-Pierre Charras, jp.charras at wanadoo.fr
5 * Copyright The KiCad Developers, see AUTHORS.txt for contributors.
6 *
7 * This program is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU General Public License
9 * as published by the Free Software Foundation; either version 2
10 * of the License, or (at your option) any later version.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program. If not, see <https://www.gnu.org/licenses/>.
19 */
20
22#include <base_units.h>
23#include <bitmaps.h>
24#include <string_utils.h>
25#include <core/mirror.h>
26#include <sch_painter.h>
27#include <sch_plotter.h>
32#include <sch_line.h>
33#include <eda_shape.h>
34#include <sch_edit_frame.h>
37#include <sch_netchain.h>
38#include <schematic.h>
41#include <trigo.h>
42#include <api/api_enums.h>
43#include <api/api_utils.h>
44#include <api/schematic/schematic_types.pb.h>
45#include <properties/property.h>
47#include <origin_transforms.h>
48#include <math/util.h>
49
50
51namespace
52{
53
54bool hasLineEnding( const SCH_LINE& aLine )
55{
58}
59
60
61EDA_SHAPE makeLineEndingShape( const SCH_LINE& aLine )
62{
64 shape.SetStart( aLine.GetStartPoint() );
65 shape.SetEnd( aLine.GetEndPoint() );
66 shape.SetStartEnding( aLine.GetStartEnding() );
67 shape.SetEndEnding( aLine.GetEndEnding() );
68
69 return shape;
70}
71
72} // namespace
73
74
75SCH_LINE::SCH_LINE( const VECTOR2I& pos, int layer ) :
76 SCH_ITEM( nullptr, SCH_LINE_T )
77{
78 m_start = pos;
79 m_end = pos;
80 m_stroke.SetWidth( 0 );
81 m_stroke.SetLineStyle( LINE_STYLE::DEFAULT );
83
84 switch( layer )
85 {
86 default: m_layer = LAYER_NOTES; break;
87 case LAYER_WIRE: m_layer = LAYER_WIRE; break;
88 case LAYER_BUS: m_layer = LAYER_BUS; break;
89 }
90
91 if( layer == LAYER_NOTES )
93 else
95
96 if( layer == LAYER_WIRE )
98 else if( layer == LAYER_BUS )
100 else
102
105}
106
107
109 SCH_ITEM( aLine )
110{
111 m_start = aLine.m_start;
112 m_end = aLine.m_end;
113 m_stroke = aLine.m_stroke;
116
120
123 m_endEnding = aLine.m_endEnding;
124
125 // Don't apply groups to cloned lines. We have too many areas where we clone them
126 // temporarily, then modify/split/join them in the line movement routines after the
127 // segments are committed. Rely on the commit framework to add the lines to the
128 // entered group as appropriate.
129 m_group = nullptr;
130}
131
132
133void SCH_LINE::Serialize( google::protobuf::Any &aContainer ) const
134{
135 using namespace kiapi::common;
136
137 kiapi::schematic::types::SchematicLine line;
138 types::StrokeAttributes* stroke = line.mutable_stroke();
139
140 line.mutable_id()->set_value( m_Uuid.AsStdString() );
141 PackVector2( *line.mutable_start(), GetStartPoint(), schIUScale );
142 PackVector2( *line.mutable_end(), GetEndPoint(), schIUScale );
143 line.set_locked( IsLocked() ? types::LockedState::LS_LOCKED : types::LockedState::LS_UNLOCKED );
144
145 PackDistance( *stroke->mutable_width(), m_stroke.GetWidth(), schIUScale );
146 stroke->set_style( ToProtoEnum<LINE_STYLE, types::StrokeLineStyle>( m_stroke.GetLineStyle() ) );
147
148 if( m_stroke.GetColor() != COLOR4D::UNSPECIFIED )
149 PackColor( *stroke->mutable_color(), m_stroke.GetColor() );
150
151 switch( GetLayer() )
152 {
153 case LAYER_WIRE:
154 line.set_type( kiapi::schematic::types::SLT_WIRE );
155 break;
156
157 case LAYER_BUS:
158 line.set_type( kiapi::schematic::types::SLT_BUS );
159 break;
160
161 case LAYER_NOTES:
162 line.set_type( kiapi::schematic::types::SLT_GRAPHIC );
163 break;
164
165 default:
166 line.set_type( kiapi::schematic::types::SLT_UNKNOWN );
167 break;
168 }
169
170 if( GetStartEnding().GetStyle() != LINE_ENDING_STYLE::NONE )
171 PackLineEnding( *line.mutable_start_ending(), GetStartEnding(), schIUScale );
172
173 if( GetEndEnding().GetStyle() != LINE_ENDING_STYLE::NONE )
174 PackLineEnding( *line.mutable_end_ending(), GetEndEnding(), schIUScale );
175
176 kiapi::common::PackCustomProperties( line.mutable_custom_properties(), *this );
177 aContainer.PackFrom( line );
178}
179
180
181bool SCH_LINE::Deserialize( const google::protobuf::Any &aContainer )
182{
183 using namespace kiapi::common;
184
185 kiapi::schematic::types::SchematicLine line;
186
187 if( !aContainer.UnpackTo( &line ) )
188 return false;
189
190 const_cast<KIID&>( m_Uuid ) = KIID( line.id().value() );
191 SetStartPoint( UnpackVector2( line.start(), schIUScale ) );
192 SetEndPoint( UnpackVector2( line.end(), schIUScale ) );
193 SetLocked( line.locked() == types::LockedState::LS_LOCKED );
194 kiapi::common::UnpackCustomProperties( line.custom_properties(), *this );
195
196 m_stroke.SetWidth( UnpackDistance( line.stroke().width(), schIUScale ) );
197 m_stroke.SetLineStyle( FromProtoEnum<LINE_STYLE, types::StrokeLineStyle>( line.stroke().style() ) );
198
199 if( line.stroke().has_color() )
200 m_stroke.SetColor( UnpackColor( line.stroke().color() ) );
201 else
202 m_stroke.SetColor( COLOR4D::UNSPECIFIED );
203
204 switch( line.type() )
205 {
206 case kiapi::schematic::types::SLT_WIRE:
208 break;
209
210 case kiapi::schematic::types::SLT_BUS:
212 break;
213
214 default:
215 case kiapi::schematic::types::SLT_GRAPHIC:
217 break;
218 }
219
220 SetStartEnding( line.has_start_ending() ? UnpackLineEnding( line.start_ending(), schIUScale )
221 : LINE_ENDING() );
222
223 SetEndEnding( line.has_end_ending() ? UnpackLineEnding( line.end_ending(), schIUScale )
224 : LINE_ENDING() );
225
226 return true;
227}
228
229
231{
232 switch( GetLayer() )
233 {
234 case LAYER_WIRE: return _( "Wire" );
235 case LAYER_BUS: return _( "Bus" );
236 default: return _( "Graphic Line" );
237 }
238}
239
240
242{
243 return new SCH_LINE( *this );
244}
245
246
247void SCH_LINE::Move( const VECTOR2I& aOffset )
248{
249 m_start += aOffset;
250 m_end += aOffset;
251}
252
253
254void SCH_LINE::MoveStart( const VECTOR2I& aOffset )
255{
256 m_start += aOffset;
257}
258
259
260void SCH_LINE::MoveEnd( const VECTOR2I& aOffset )
261{
262 m_end += aOffset;
263}
264
265
266#if defined(DEBUG)
267
268void SCH_LINE::Show( int nestLevel, std::ostream& os ) const
269{
270 NestedSpace( nestLevel, os ) << '<' << GetClass().Lower().mb_str()
271 << " layer=\"" << m_layer << '"'
272 << " startIsDangling=\"" << m_startIsDangling
273 << '"' << " endIsDangling=\""
274 << m_endIsDangling << '"' << ">"
275 << " <start" << m_start << "/>"
276 << " <end" << m_end << "/>" << "</"
277 << GetClass().Lower().mb_str() << ">\n";
278}
279
280#endif
281
282
291
292
293double SCH_LINE::ViewGetLOD( int aLayer, const KIGFX::VIEW* aView ) const
294{
295 if( aLayer == LAYER_OP_VOLTAGES )
296 {
297 if( m_start == m_end )
298 return LOD_HIDE;
299
300 const int height = std::abs( m_end.y - m_start.y );
301
302 // Operating points will be shown only if zoom is appropriate
303 if( height > 0 )
304 return lodScaleForThreshold( aView, height, schIUScale.mmToIU( 5 ) );
305
306 const int width = std::abs( m_end.x - m_start.x );
307 return lodScaleForThreshold( aView, width, schIUScale.mmToIU( 15 ) );
308 }
309
310 // Other layers are always drawn.
311 return LOD_SHOW;
312}
313
314
316{
317 int width = GetPenWidth() / 2;
318
319 int xmin = std::min( m_start.x, m_end.x ) - width;
320 int ymin = std::min( m_start.y, m_end.y ) - width;
321
322 int xmax = std::max( m_start.x, m_end.x ) + width + 1;
323 int ymax = std::max( m_start.y, m_end.y ) + width + 1;
324
325 BOX2I ret( VECTOR2I( xmin, ymin ), VECTOR2I( xmax - xmin, ymax - ymin ) );
326
327 if( IsGraphicLine() )
328 {
329 EDA_SHAPE tempShape = makeLineEndingShape( *this );
330 BOX2I endingsBBox;
331
332 if( tempShape.GetLineEndingsBoundingBox( endingsBBox, GetPenWidth() ) )
333 ret.Merge( endingsBBox );
334 }
335
336 return ret;
337}
338
339
341{
342 return m_start.Distance( m_end );
343}
344
345
346void SCH_LINE::SetLength( double aLength )
347{
348 if( aLength < 0.0 )
349 aLength = 0.0;
350
351 double currentLength = GetLength();
352 VECTOR2I start = GetStartPoint();
354
355 if( currentLength <= 0.0 )
356 {
357 end = start + KiROUND( aLength, 0.0 );
358 }
359 else
360 {
361 VECTOR2I delta = GetEndPoint() - start;
362 double scale = aLength / currentLength;
363
364 end = start + KiROUND( delta * scale );
365 }
366
367 SetEndPoint( end );
368}
369
370
371void SCH_LINE::SetLineColor( const COLOR4D& aColor )
372{
373 m_stroke.SetColor( aColor );
375}
376
377
378void SCH_LINE::SetLineColor( const double r, const double g, const double b, const double a )
379{
380 COLOR4D newColor(r, g, b, a);
381
382 if( newColor == COLOR4D::UNSPECIFIED )
383 {
384 m_stroke.SetColor( COLOR4D::UNSPECIFIED );
385 }
386 else
387 {
388 // Eeschema does not allow alpha channel in colors
389 newColor.a = 1.0;
390 m_stroke.SetColor( newColor );
391 }
392}
393
394
406
407
409{
410 m_stroke.SetLineStyle( aStyle );
412}
413
414
416{
417 if( IsGraphicLine() && m_stroke.GetLineStyle() == LINE_STYLE::DEFAULT )
418 return LINE_STYLE::SOLID;
419 else
420 return m_stroke.GetLineStyle();
421}
422
423
435
436
437void SCH_LINE::SetLineWidth( const int aSize )
438{
439 m_stroke.SetWidth( aSize );
441}
442
443
445{
447
448 switch ( m_layer )
449 {
450 default:
451 if( m_stroke.GetWidth() > 0 )
452 return m_stroke.GetWidth();
453
454 if( schematic )
455 return schematic->Settings().m_DefaultLineWidth;
456
457 return schIUScale.MilsToIU( DEFAULT_LINE_WIDTH_MILS );
458
459 case LAYER_WIRE:
460 if( m_stroke.GetWidth() > 0 )
461 m_lastResolvedWidth = m_stroke.GetWidth();
462 else if( !IsConnectivityDirty() )
464
465 return m_lastResolvedWidth;
466
467 case LAYER_BUS:
468 if( m_stroke.GetWidth() > 0 )
469 m_lastResolvedWidth = m_stroke.GetWidth();
470 else if( !IsConnectivityDirty() )
472
473 return m_lastResolvedWidth;
474 }
475}
476
477
478void SCH_LINE::MirrorVertically( int aCenter )
479{
480 if( m_flags & STARTPOINT )
481 MIRROR( m_start.y, aCenter );
482
483 if( m_flags & ENDPOINT )
484 MIRROR( m_end.y, aCenter );
485}
486
487
489{
490 if( m_flags & STARTPOINT )
491 MIRROR( m_start.x, aCenter );
492
493 if( m_flags & ENDPOINT )
494 MIRROR( m_end.x, aCenter );
495}
496
497
498void SCH_LINE::Rotate( const VECTOR2I& aCenter, bool aRotateCCW )
499{
500 if( m_flags & STARTPOINT )
501 RotatePoint( m_start, aCenter, aRotateCCW ? ANGLE_90 : ANGLE_270 );
502
503 if( m_flags & ENDPOINT )
504 RotatePoint( m_end, aCenter, aRotateCCW ? ANGLE_90 : ANGLE_270 );
505}
506
507
508int SCH_LINE::GetAngleFrom( const VECTOR2I& aPoint ) const
509{
510 VECTOR2I vec;
511
512 if( aPoint == m_start )
513 vec = m_end - aPoint;
514 else
515 vec = m_start - aPoint;
516
517 return KiROUND( EDA_ANGLE( vec ).AsDegrees() );
518}
519
520
521int SCH_LINE::GetReverseAngleFrom( const VECTOR2I& aPoint ) const
522{
523 VECTOR2I vec;
524
525 if( aPoint == m_end )
526 vec = m_start - aPoint;
527 else
528 vec = m_end - aPoint;
529
530 return KiROUND( EDA_ANGLE( vec ).AsDegrees() );
531}
532
533
534bool SCH_LINE::IsParallel( const SCH_LINE* aLine ) const
535{
536 wxCHECK_MSG( aLine != nullptr && aLine->Type() == SCH_LINE_T, false,
537 wxT( "Cannot test line segment for overlap." ) );
538
539 VECTOR2I firstSeg = m_end - m_start;
540 VECTOR2I secondSeg = aLine->m_end - aLine->m_start;
541
542 // Use long long here to avoid overflow in calculations
543 return !( (long long) firstSeg.x * secondSeg.y - (long long) firstSeg.y * secondSeg.x );
544}
545
546
547SCH_LINE* SCH_LINE::MergeOverlap( SCH_SCREEN* aScreen, SCH_LINE* aLine, bool aCheckJunctions )
548{
549 auto less =
550 []( const VECTOR2I& lhs, const VECTOR2I& rhs ) -> bool
551 {
552 if( lhs.x == rhs.x )
553 return lhs.y < rhs.y;
554
555 return lhs.x < rhs.x;
556 };
557
558 wxCHECK_MSG( aLine != nullptr && aLine->Type() == SCH_LINE_T, nullptr,
559 wxT( "Cannot test line segment for overlap." ) );
560
561 if( this == aLine || GetLayer() != aLine->GetLayer() || GetStroke() != aLine->GetStroke() )
562 return nullptr;
563
564 VECTOR2I leftmost_start = aLine->m_start;
565 VECTOR2I leftmost_end = aLine->m_end;
566
567 VECTOR2I rightmost_start = m_start;
568 VECTOR2I rightmost_end = m_end;
569
570 // We place the start to the left and below the end of both lines
571 if( leftmost_start != std::min( { leftmost_start, leftmost_end }, less ) )
572 std::swap( leftmost_start, leftmost_end );
573 if( rightmost_start != std::min( { rightmost_start, rightmost_end }, less ) )
574 std::swap( rightmost_start, rightmost_end );
575
576 // - leftmost is the line that starts farthest to the left
577 // - other is the line that is _not_ leftmost
578 // - rightmost is the line that ends farthest to the right. This may or may not be 'other'
579 // as the second line may be completely covered by the first.
580 if( less( rightmost_start, leftmost_start ) )
581 {
582 std::swap( leftmost_start, rightmost_start );
583 std::swap( leftmost_end, rightmost_end );
584 }
585
586 VECTOR2I other_start = rightmost_start;
587 VECTOR2I other_end = rightmost_end;
588
589 if( less( rightmost_end, leftmost_end ) )
590 {
591 rightmost_start = leftmost_start;
592 rightmost_end = leftmost_end;
593 }
594
595 // If we end one before the beginning of the other, no overlap is possible
596 if( less( leftmost_end, other_start ) )
597 {
598 return nullptr;
599 }
600
601 // Search for a common end:
602 if( ( leftmost_start == other_start ) && ( leftmost_end == other_end ) ) // Trivial case
603 {
604 SCH_LINE* ret = new SCH_LINE( *aLine );
605 ret->SetStartPoint( leftmost_start );
606 ret->SetEndPoint( leftmost_end );
607 // Only insertion should invalidate the screen; junction queries also merge temporary copies
608 ret->m_connectivity_dirty = true;
609
610 if( IsSelected() || aLine->IsSelected() )
611 ret->SetSelected();
612
613 return ret;
614 }
615
616 bool colinear = false;
617
618 /* Test alignment: */
619 if( ( leftmost_start.y == leftmost_end.y ) &&
620 ( other_start.y == other_end.y ) ) // Horizontal segment
621 {
622 colinear = ( leftmost_start.y == other_start.y );
623 }
624 else if( ( leftmost_start.x == leftmost_end.x ) &&
625 ( other_start.x == other_end.x ) ) // Vertical segment
626 {
627 colinear = ( leftmost_start.x == other_start.x );
628 }
629 else
630 {
631 // We use long long here to avoid overflow -- it enforces promotion
632 // The slope of the left-most line is dy/dx. Then we check that the slope from the
633 // left most start to the right most start is the same as well as the slope from the
634 // left most start to right most end.
635 long long dx = leftmost_end.x - leftmost_start.x;
636 long long dy = leftmost_end.y - leftmost_start.y;
637 colinear = ( ( ( other_start.y - leftmost_start.y ) * dx ==
638 ( other_start.x - leftmost_start.x ) * dy ) &&
639 ( ( other_end.y - leftmost_start.y ) * dx ==
640 ( other_end.x - leftmost_start.x ) * dy ) );
641 }
642
643 if( !colinear )
644 return nullptr;
645
646 // We either have a true overlap or colinear touching segments. We always want to merge
647 // the former, but the later only get merged if there no junction at the touch point.
648
649 bool touching = leftmost_end == rightmost_start;
650
651 if( touching && aCheckJunctions && aScreen->IsJunction( leftmost_end ) )
652 return nullptr;
653
654 // Make a new segment that merges the 2 segments
655 leftmost_end = rightmost_end;
656
657 SCH_LINE* ret = new SCH_LINE( *aLine );
658 ret->SetStartPoint( leftmost_start );
659 ret->SetEndPoint( leftmost_end );
660 // This result is not on the screen yet, even though its copy retains the parent
661 ret->m_connectivity_dirty = true;
662
663 if( IsSelected() || aLine->IsSelected() )
664 ret->SetSelected();
665
666 return ret;
667}
668
669
671{
672 SCH_LINE* newSegment = static_cast<SCH_LINE*>( Duplicate( true /* addToParentGroup */, aCommit ) );
673
674 newSegment->SetStartPoint( aPoint );
675 newSegment->SetConnectivityDirty( true );
676 SetEndPoint( aPoint );
677
678 return newSegment;
679}
680
681
683{
684 SCH_LINE* newSegment = static_cast<SCH_LINE*>( Duplicate( false /* addToParentGroup */, nullptr ) );
685
686 newSegment->SetStartPoint( aPoint );
687 newSegment->SetConnectivityDirty( true );
688 SetEndPoint( aPoint );
689
690 return newSegment;
691}
692
693
694void SCH_LINE::GetEndPoints( std::vector <DANGLING_END_ITEM>& aItemList )
695{
696 if( IsConnectable() )
697 {
698 aItemList.emplace_back( IsBus() ? BUS_END : WIRE_END, this, m_start );
699 aItemList.emplace_back( IsBus() ? BUS_END : WIRE_END, this, m_end );
700 }
701}
702
703
704bool SCH_LINE::UpdateDanglingState( std::vector<DANGLING_END_ITEM>& aItemListByType,
705 std::vector<DANGLING_END_ITEM>& aItemListByPos,
706 const SCH_SHEET_PATH* aPath )
707{
708 if( !IsConnectable() )
709 return false;
710
711 bool previousStartState = m_startIsDangling;
712 bool previousEndState = m_endIsDangling;
713
715
716 for( auto it = DANGLING_END_ITEM_HELPER::get_lower_pos( aItemListByPos, m_start );
717 it < aItemListByPos.end() && it->GetPosition() == m_start; it++ )
718 {
719 DANGLING_END_ITEM& item = *it;
720
721 if( item.GetItem() == this )
722 continue;
723
724 if( ( IsWire() && item.GetType() != BUS_END && item.GetType() != BUS_ENTRY_END )
725 || ( IsBus() && item.GetType() != WIRE_END && item.GetType() != PIN_END ) )
726 {
727 m_startIsDangling = false;
728 break;
729 }
730 }
731
732 for( auto it = DANGLING_END_ITEM_HELPER::get_lower_pos( aItemListByPos, m_end );
733 it < aItemListByPos.end() && it->GetPosition() == m_end; it++ )
734 {
735 DANGLING_END_ITEM& item = *it;
736
737 if( item.GetItem() == this )
738 continue;
739
740 if( ( IsWire() && item.GetType() != BUS_END && item.GetType() != BUS_ENTRY_END )
741 || ( IsBus() && item.GetType() != WIRE_END && item.GetType() != PIN_END ) )
742 {
743 m_endIsDangling = false;
744 break;
745 }
746 }
747
748 // We only use the bus dangling state for automatic line starting, so we don't care if it
749 // has changed or not (and returning true will result in extra work)
750 if( IsBus() )
751 return false;
752
753 return previousStartState != m_startIsDangling || previousEndState != m_endIsDangling;
754}
755
756
758{
759 if( m_layer == LAYER_WIRE || m_layer == LAYER_BUS )
760 return true;
761
762 return false;
763}
764
765
766bool SCH_LINE::CanConnect( const SCH_ITEM* aItem ) const
767{
768 switch( aItem->Type() )
769 {
770 case SCH_NO_CONNECT_T:
771 case SCH_SYMBOL_T:
772 return IsWire();
773
774 case SCH_JUNCTION_T:
775 case SCH_LABEL_T:
777 case SCH_HIER_LABEL_T:
780 case SCH_SHEET_T:
781 case SCH_SHEET_PIN_T:
782 return IsWire() || IsBus();
783
784 default:
785 return m_layer == aItem->GetLayer();
786 }
787}
788
789
790bool SCH_LINE::HasConnectivityChanges( const SCH_ITEM* aItem, const SCH_SHEET_PATH* aInstance ) const
791{
792 // Do not compare to ourself.
793 if( aItem == this || !IsConnectable() )
794 return false;
795
796 const SCH_LINE* line = dynamic_cast<const SCH_LINE*>( aItem );
797
798 // Don't compare against a different SCH_ITEM.
799 wxCHECK( line, false );
800
801 if( GetStartPoint() != line->GetStartPoint() )
802 return true;
803
804 return GetEndPoint() != line->GetEndPoint();
805}
806
807
808std::vector<VECTOR2I> SCH_LINE::GetConnectionPoints() const
809{
810 return { m_start, m_end };
811}
812
813
815{
816 switch( aItem->Type() )
817 {
818 case SCH_LINE_T:
819 return IsBus() == static_cast<const SCH_LINE*>( aItem )->IsBus();
820
821 default:
822 return true;
823 }
824}
825
826
827void SCH_LINE::GetSelectedPoints( std::vector<VECTOR2I>& aPoints ) const
828{
829 if( m_flags & STARTPOINT )
830 aPoints.push_back( m_start );
831
832 if( m_flags & ENDPOINT )
833 aPoints.push_back( m_end );
834}
835
836
837wxString SCH_LINE::GetItemDescription( UNITS_PROVIDER* aUnitsProvider, bool aFull ) const
838{
839 wxString txtfmt;
840
841 if( m_start.x == m_end.x )
842 {
843 switch( m_layer )
844 {
845 case LAYER_WIRE: txtfmt = _( "Vertical Wire, length %s" ); break;
846 case LAYER_BUS: txtfmt = _( "Vertical Bus, length %s" ); break;
847 default: txtfmt = _( "Vertical Graphic Line, length %s" ); break;
848 }
849 }
850 else if( m_start.y == m_end.y )
851 {
852 switch( m_layer )
853 {
854 case LAYER_WIRE: txtfmt = _( "Horizontal Wire, length %s" ); break;
855 case LAYER_BUS: txtfmt = _( "Horizontal Bus, length %s" ); break;
856 default: txtfmt = _( "Horizontal Graphic Line, length %s" ); break;
857 }
858 }
859 else
860 {
861 switch( m_layer )
862 {
863 case LAYER_WIRE: txtfmt = _( "Wire, length %s" ); break;
864 case LAYER_BUS: txtfmt = _( "Bus, length %s" ); break;
865 default: txtfmt = _( "Graphic Line, length %s" ); break;
866 }
867 }
868
869 return wxString::Format( txtfmt,
870 aUnitsProvider->MessageTextFromValue( m_start.Distance( m_end ) ) );
871}
872
873
875{
876 if( m_layer == LAYER_NOTES )
878 else if( m_layer == LAYER_WIRE )
879 return BITMAPS::add_line;
880
881 return BITMAPS::add_bus;
882}
883
884
885bool SCH_LINE::operator <( const SCH_ITEM& aItem ) const
886{
887 if( Type() != aItem.Type() )
888 return Type() < aItem.Type();
889
890 const SCH_LINE* line = static_cast<const SCH_LINE*>( &aItem );
891
892 if( GetLayer() != line->GetLayer() )
893 return GetLayer() < line->GetLayer();
894
895 if( GetStartPoint().x != line->GetStartPoint().x )
896 return GetStartPoint().x < line->GetStartPoint().x;
897
898 if( GetStartPoint().y != line->GetStartPoint().y )
899 return GetStartPoint().y < line->GetStartPoint().y;
900
901 if( GetEndPoint().x != line->GetEndPoint().x )
902 return GetEndPoint().x < line->GetEndPoint().x;
903
904 return GetEndPoint().y < line->GetEndPoint().y;
905}
906
907
908bool SCH_LINE::HitTest( const VECTOR2I& aPosition, int aAccuracy ) const
909{
910 // Performance enhancement for connection-building
911 if( aPosition == m_start || aPosition == m_end )
912 return true;
913
914 if( IsGraphicLine() && hasLineEnding( *this ) )
915 {
916 EDA_SHAPE tempShape = makeLineEndingShape( *this );
918 const SHAPE& hitShape = shape;
919 int accuracy = aAccuracy >= 0 ? aAccuracy : abs( aAccuracy );
920
921 return hitShape.Collide( aPosition, accuracy );
922 }
923
924 if( aAccuracy >= 0 )
925 aAccuracy += GetPenWidth() / 2;
926 else
927 aAccuracy = abs( aAccuracy );
928
929 return TestSegmentHit( aPosition, m_start, m_end, aAccuracy );
930}
931
932
933bool SCH_LINE::HitTest( const BOX2I& aRect, bool aContained, int aAccuracy ) const
934{
936 return false;
937
938 BOX2I rect = aRect;
939
940 if ( aAccuracy )
941 rect.Inflate( aAccuracy );
942
943 if( IsGraphicLine() && hasLineEnding( *this ) )
944 {
945 EDA_SHAPE tempShape = makeLineEndingShape( *this );
947 SHAPE_LINE_CHAIN selection = KIGEOM::BoxToLineChain( rect );
948
949 return KIGEOM::ShapeHitTest( selection, shape, aContained );
950 }
951
952 if( aContained )
953 return rect.Contains( m_start ) && rect.Contains( m_end );
954
955 return rect.Intersects( m_start, m_end );
956}
957
958
959bool SCH_LINE::HitTest( const SHAPE_LINE_CHAIN& aPoly, bool aContained ) const
960{
962 return false;
963
964 if( IsGraphicLine() && hasLineEnding( *this ) )
965 {
966 EDA_SHAPE tempShape = makeLineEndingShape( *this );
968
969 return KIGEOM::ShapeHitTest( aPoly, shape, aContained );
970 }
971
973 return KIGEOM::ShapeHitTest( aPoly, line, aContained );
974}
975
976
978{
979 SCH_LINE* item = (SCH_LINE*) aItem;
980
981 std::swap( m_start, item->m_start );
982 std::swap( m_end, item->m_end );
983 std::swap( m_startIsDangling, item->m_startIsDangling );
984 std::swap( m_endIsDangling, item->m_endIsDangling );
985 std::swap( m_stroke, item->m_stroke );
986 std::swap( m_startEnding, item->m_startEnding );
987 std::swap( m_endEnding, item->m_endEnding );
988}
989
990
991bool SCH_LINE::doIsConnected( const VECTOR2I& aPosition ) const
992{
993 if( m_layer != LAYER_WIRE && m_layer != LAYER_BUS )
994 return false;
995
996 return IsEndPoint( aPosition );
997}
998
999
1000void SCH_LINE::Plot( PLOTTER* aPlotter, bool aBackground, const SCH_PLOT_OPTS& aPlotOpts,
1001 int aUnit, int aBodyStyle, const VECTOR2I& aOffset, bool aDimmed )
1002{
1003 if( aBackground )
1004 return;
1005
1006 SCH_RENDER_SETTINGS* renderSettings = getRenderSettings( aPlotter );
1007 int penWidth = GetEffectivePenWidth( renderSettings );
1008 COLOR4D color = GetLineColor();
1009
1010 if( color == COLOR4D::UNSPECIFIED )
1011 color = renderSettings->GetLayerColor( GetLayer() );
1012
1013 if( color.m_text && Schematic() )
1014 color = COLOR4D( ResolveText( *color.m_text, &Schematic()->CurrentSheet() ) );
1015
1016 aPlotter->SetColor( color );
1017
1018 aPlotter->SetCurrentLineWidth( penWidth );
1019 aPlotter->SetDash( penWidth, GetEffectiveLineStyle() );
1020
1021 VECTOR2I plotStart = m_start;
1022 VECTOR2I plotEnd = m_end;
1023 bool drawLineBody = true;
1024
1025 if( IsGraphicLine() )
1026 {
1027 drawLineBody = EDA_SHAPE::ShortenSegmentForEndings( plotStart, plotEnd, GetStartEnding(), GetEndEnding(),
1028 penWidth );
1029 }
1030
1031 if( drawLineBody )
1032 {
1033 aPlotter->MoveTo( plotStart );
1034 aPlotter->FinishTo( plotEnd );
1035 }
1036
1037 aPlotter->SetDash( penWidth, LINE_STYLE::SOLID );
1038
1039 if( IsGraphicLine() )
1040 {
1041 EDA_ANGLE lineAngle( m_end - m_start );
1042 GetStartEnding().Plot( aPlotter, m_start, lineAngle + ANGLE_180, penWidth );
1043 GetEndEnding().Plot( aPlotter, m_end, lineAngle, penWidth );
1044 }
1045
1046 // Plot attributes to a hypertext menu
1047 std::vector<wxString> properties;
1048 BOX2I bbox = GetBoundingBox();
1049 bbox.Inflate( penWidth * 3 );
1050
1051 if( aPlotOpts.m_PDFPropertyPopups )
1052 {
1053 if( GetLayer() == LAYER_WIRE )
1054 {
1055 if( const auto name = GetConnectionName() )
1056 {
1057 properties.emplace_back( wxString::Format( wxT( "!%s = %s" ),
1058 _( "Net" ),
1059 *name ) );
1060
1061 properties.emplace_back( wxString::Format( wxT( "!%s = %s" ),
1062 _( "Resolved netclass" ),
1063 GetEffectiveNetClass()->GetHumanReadableName() ) );
1064 }
1065 }
1066 else if( GetLayer() == LAYER_BUS )
1067 {
1068 for( const wxString& member : GetBusMemberNames() )
1069 properties.emplace_back( wxT( "!" ) + member );
1070 }
1071
1072 if( !properties.empty() )
1073 aPlotter->HyperlinkMenu( bbox, properties );
1074 }
1075}
1076
1077
1078void SCH_LINE::SetPosition( const VECTOR2I& aPosition )
1079{
1080 m_end = m_end - ( m_start - aPosition );
1081 m_start = aPosition;
1082}
1083
1084
1085void SCH_LINE::GetMsgPanelInfo( EDA_DRAW_FRAME* aFrame, std::vector<MSG_PANEL_ITEM>& aList )
1086{
1087 wxString msg;
1088
1089 switch( GetLayer() )
1090 {
1091 case LAYER_WIRE: msg = _( "Wire" ); break;
1092 case LAYER_BUS: msg = _( "Bus" ); break;
1093 default: msg = _( "Graphical" ); break;
1094 }
1095
1096 aList.emplace_back( _( "Line Type" ), msg );
1097
1098 LINE_STYLE lineStyle = GetStroke().GetLineStyle();
1099
1100 if( ( IsWire() || IsBus() ) && GetEffectiveLineStyle() != lineStyle )
1101 aList.emplace_back( _( "Line Style" ), _( "from netclass" ) );
1102 else
1103 m_stroke.GetMsgPanelInfo( aFrame, aList, true, false );
1104
1105 if( !IsConnectivityDirty() && dynamic_cast<SCH_EDIT_FRAME*>( aFrame ) )
1106 {
1107 if( const auto name = SCH_CONNECTIVITY::AppendConnectionInfo( *this, aList ) )
1108 {
1109 if( SCHEMATIC* schematic = Schematic() )
1110 {
1111 if( SCH_NETCHAIN* chain = schematic->NetChains().GetNetChainForNet( *name ) )
1112 aList.emplace_back( _( "Net Chain" ), UnescapeString( chain->GetName() ) );
1113 }
1114 }
1115 }
1116}
1117
1118
1120{
1121 return ( GetLayer() == LAYER_NOTES );
1122}
1123
1124
1126{
1127 return ( GetLayer() == LAYER_WIRE );
1128}
1129
1130
1132{
1133 return ( GetLayer() == LAYER_BUS );
1134}
1135
1136
1137bool SCH_LINE::operator==( const SCH_ITEM& aOther ) const
1138{
1139 if( Type() != aOther.Type() )
1140 return false;
1141
1142 const SCH_LINE& other = static_cast<const SCH_LINE&>( aOther );
1143
1144 if( GetLayer() != other.GetLayer() )
1145 return false;
1146
1147 if( m_start != other.m_start )
1148 return false;
1149
1150 if( m_end != other.m_end )
1151 return false;
1152
1153 if( m_stroke.GetWidth() != other.m_stroke.GetWidth() )
1154 return false;
1155
1156 if( m_stroke.GetColor() != other.m_stroke.GetColor() )
1157 return false;
1158
1159 if( m_stroke.GetLineStyle() != other.m_stroke.GetLineStyle() )
1160 return false;
1161
1162 if( m_startEnding != other.m_startEnding )
1163 return false;
1164
1165 if( m_endEnding != other.m_endEnding )
1166 return false;
1167
1168 return true;
1169}
1170
1171
1172double SCH_LINE::Similarity( const SCH_ITEM& aOther ) const
1173{
1174 if( m_Uuid == aOther.m_Uuid )
1175 return 1.0;
1176
1177 if( Type() != aOther.Type() )
1178 return 0.0;
1179
1180 const SCH_LINE& other = static_cast<const SCH_LINE&>( aOther );
1181
1182 if( GetLayer() != other.GetLayer() )
1183 return 0.0;
1184
1185 double similarity = 1.0;
1186
1187 if( m_start != other.m_start )
1188 similarity *= 0.9;
1189
1190 if( m_end != other.m_end )
1191 similarity *= 0.9;
1192
1193 if( m_stroke.GetWidth() != other.m_stroke.GetWidth() )
1194 similarity *= 0.9;
1195
1196 if( m_stroke.GetColor() != other.m_stroke.GetColor() )
1197 similarity *= 0.9;
1198
1199 if( m_stroke.GetLineStyle() != other.m_stroke.GetLineStyle() )
1200 similarity *= 0.9;
1201
1202 if( m_startEnding != other.m_startEnding )
1203 similarity *= 0.9;
1204
1205 if( m_endEnding != other.m_endEnding )
1206 similarity *= 0.9;
1207
1208 return similarity;
1209}
1210
1211
1212bool SCH_LINE::ShouldHopOver( const SCH_LINE* aLine ) const
1213{
1214 // try to find if this should hop over aLine. Horizontal wires have preference for hop.
1215 bool isMeVertical = ( m_end.x == m_start.x );
1216 bool isCandidateVertical = ( aLine->GetEndPoint().x == aLine->GetStartPoint().x );
1217
1218 // Vertical vs. Horizontal: Horizontal should hop
1219 if( isMeVertical && !isCandidateVertical )
1220 return false;
1221
1222 if( isCandidateVertical && !isMeVertical )
1223 return true;
1224
1225 // Both this and aLine have a slope. Try to find the best candidate
1226 double slopeMe = ( m_end.y - m_start.y ) / (double) ( m_end.x - m_start.x );
1227 double slopeCandidate = ( aLine->GetEndPoint().y - aLine->GetStartPoint().y )
1228 / (double) ( aLine->GetEndPoint().x - aLine->GetStartPoint().x );
1229
1230 if( fabs( slopeMe ) == fabs( slopeCandidate ) ) // Can easily happen with 45 deg wires
1231 return slopeMe < slopeCandidate; // signs are certainly different
1232
1233 return fabs( slopeMe ) < fabs( slopeCandidate ); // The shallower line should hop
1234}
1235
1236
1237std::vector<VECTOR3I> SCH_LINE::BuildWireWithHopShape( const SCH_SCREEN* aScreen, double aArcRadius ) const
1238{
1239 // Note: Points are VECTOR3D, with Z coord used as flag
1240 // for segments: start point and end point have the Z coord = 0
1241 // for arcs: start point middle point and end point have the Z coord = 1
1242
1243 std::vector<VECTOR3I> wire_shape; // List of coordinates:
1244 // 2 points for a segment, 3 points for an arc
1245
1246 if( !IsWire() && !IsBus() )
1247 {
1248 wire_shape.emplace_back( GetStartPoint().x,GetStartPoint().y, 0 );
1249 wire_shape.emplace_back( GetEndPoint().x, GetEndPoint().y, 0 );
1250 return wire_shape;
1251 }
1252
1253 std::vector<SCH_LINE*> existingWires; // wires to test (candidates)
1254 std::vector<VECTOR2I> intersections;
1255
1256 for( SCH_ITEM* item : aScreen->Items().Overlapping( SCH_LINE_T, GetBoundingBox() ) )
1257 {
1258 SCH_LINE* line = static_cast<SCH_LINE*>( item );
1259
1260 if( line->IsWire() || line->IsBus() )
1261 existingWires.push_back( line );
1262 }
1263
1264 VECTOR2I currentLineStartPoint = GetStartPoint();
1265 VECTOR2I currentLineEndPoint = GetEndPoint();
1266
1267 for( SCH_LINE* existingLine : existingWires )
1268 {
1269 VECTOR2I extLineStartPoint = existingLine->GetStartPoint();
1270 VECTOR2I extLineEndPoint = existingLine->GetEndPoint();
1271
1272 if( extLineStartPoint == currentLineStartPoint && extLineEndPoint == currentLineEndPoint )
1273 continue;
1274
1275 if( !ShouldHopOver( existingLine ) )
1276 continue;
1277
1278 SEG currentSegment = SEG( currentLineStartPoint, currentLineEndPoint );
1279 SEG existingSegment = SEG( extLineStartPoint, extLineEndPoint );
1280
1281 if( OPT_VECTOR2I intersect = currentSegment.Intersect( existingSegment, true, false ) )
1282 {
1283 if( IsEndPoint( *intersect ) || existingLine->IsEndPoint( *intersect ) )
1284 continue;
1285
1286 // Ensure intersecting point is not yet entered. it can be already just entered
1287 // if more than two wires are intersecting at the same point,
1288 // creating bad hop over shapes for the current wire
1289 if( intersections.size() == 0 || intersections.back() != *intersect )
1290 intersections.push_back( *intersect );
1291 }
1292 }
1293
1294 if( intersections.empty() )
1295 {
1296 wire_shape.emplace_back( currentLineStartPoint.x, currentLineStartPoint.y, 0 );
1297 wire_shape.emplace_back( currentLineEndPoint.x, currentLineEndPoint.y, 0 );
1298 }
1299 else
1300 {
1301 auto getDistance =
1302 []( const VECTOR2I& a, const VECTOR2I& b ) -> double
1303 {
1304 return std::sqrt( std::pow( a.x - b.x, 2 ) + std::pow( a.y - b.y, 2 ) );
1305 };
1306
1307 std::sort( intersections.begin(), intersections.end(),
1308 [&]( const VECTOR2I& a, const VECTOR2I& b )
1309 {
1310 return getDistance( GetStartPoint(), a ) < getDistance( GetStartPoint(), b );
1311 } );
1312
1313 VECTOR2I currentStart = GetStartPoint();
1314 double R = aArcRadius;
1315
1316 for( const VECTOR2I& hopMid : intersections )
1317 {
1318 // Calculate the angle of the line from start point to end point in radians
1319 double lineAngle = std::atan2( GetEndPoint().y - GetStartPoint().y,
1320 GetEndPoint().x - GetStartPoint().x );
1321
1322 // Normalize to [0, pi) so the arc side doesn't depend
1323 // on which endpoint is start vs end
1324 double arcAngle = lineAngle;
1325
1326 if( arcAngle < 0.0 )
1327 arcAngle += M_PI;
1328 else if( arcAngle >= M_PI )
1329 arcAngle -= M_PI;
1330
1331 VECTOR2I arcMidPoint = { hopMid.x + static_cast<int>( R * std::sin( arcAngle ) ),
1332 hopMid.y - static_cast<int>( R * std::cos( arcAngle ) ) };
1333
1334 VECTOR2I beforeHop = hopMid - KiROUND( R * std::cos( lineAngle ), R * std::sin( lineAngle ) );
1335 VECTOR2I afterHop = hopMid + KiROUND( R * std::cos( lineAngle ), R * std::sin( lineAngle ) );
1336
1337 // Draw the line from the current start point to the before-hop point
1338 wire_shape.emplace_back( currentStart.x, currentStart.y, 0 );
1339 wire_shape.emplace_back( beforeHop.x, beforeHop.y, 0 );
1340
1341 // Create an arc object
1342 wire_shape.emplace_back( beforeHop.x, beforeHop.y, 1 );
1343 wire_shape.emplace_back( arcMidPoint.x, arcMidPoint.y, 1 );
1344 wire_shape.emplace_back( afterHop.x, afterHop.y, 1 );
1345
1346 currentStart = afterHop;
1347 }
1348
1349 // Draw the final line from the current start point to the end point of the original line
1350 wire_shape.emplace_back( currentStart. x,currentStart.y, 0 );
1351 wire_shape.emplace_back( GetEndPoint().x, GetEndPoint().y, 0 );
1352 }
1353
1354 return wire_shape;
1355}
1356
1357
1358static struct SCH_LINE_DESC
1359{
1361 {
1363
1364 if( endingStyleEnum.Choices().GetCount() == 0 )
1365 {
1366 endingStyleEnum.Map( LINE_ENDING_STYLE::NONE, _HKI( "None" ) )
1367 .Map( LINE_ENDING_STYLE::ARROW, _HKI( "Arrow" ) )
1368 .Map( LINE_ENDING_STYLE::CIRCLE, _HKI( "Circle" ) )
1369 .Map( LINE_ENDING_STYLE::SQUARE, _HKI( "Square" ) )
1370 .Map( LINE_ENDING_STYLE::ARROW_OPEN, _HKI( "Open Arrow" ) );
1371 }
1372
1374
1375 if( lineStyleEnum.Choices().GetCount() == 0 )
1376 {
1377 lineStyleEnum.Map( LINE_STYLE::SOLID, _HKI( "Solid" ) )
1378 .Map( LINE_STYLE::DASH, _HKI( "Dashed" ) )
1379 .Map( LINE_STYLE::DOT, _HKI( "Dotted" ) )
1380 .Map( LINE_STYLE::DASHDOT, _HKI( "Dash-Dot" ) )
1381 .Map( LINE_STYLE::DASHDOTDOT, _HKI( "Dash-Dot-Dot" ) );
1382 }
1383
1385
1386 if( wireLineStyleEnum.Choices().GetCount() == 0 )
1387 {
1388 wireLineStyleEnum.Map( WIRE_STYLE::DEFAULT, _HKI( "Default" ) )
1389 .Map( WIRE_STYLE::SOLID, _HKI( "Solid" ) )
1390 .Map( WIRE_STYLE::DASH, _HKI( "Dashed" ) )
1391 .Map( WIRE_STYLE::DOT, _HKI( "Dotted" ) )
1392 .Map( WIRE_STYLE::DASHDOT, _HKI( "Dash-Dot" ) )
1393 .Map( WIRE_STYLE::DASHDOTDOT, _HKI( "Dash-Dot-Dot" ) );
1394 }
1395
1399
1400 auto isGraphicLine =
1401 []( INSPECTABLE* aItem ) -> bool
1402 {
1403 if( SCH_LINE* line = dynamic_cast<SCH_LINE*>( aItem ) )
1404 return line->IsGraphicLine();
1405
1406 return false;
1407 };
1408
1409 auto isWireOrBus =
1410 []( INSPECTABLE* aItem ) -> bool
1411 {
1412 if( SCH_LINE* line = dynamic_cast<SCH_LINE*>( aItem ) )
1413 return line->IsWire() || line->IsBus();
1414
1415 return false;
1416 };
1417
1418 propMgr.AddProperty( new PROPERTY<SCH_LINE, int>( _HKI( "Start X" ),
1421
1422 propMgr.AddProperty( new PROPERTY<SCH_LINE, int>( _HKI( "Start Y" ),
1425
1426 propMgr.AddProperty( new PROPERTY<SCH_LINE, int>( _HKI( "End X" ),
1429
1430 propMgr.AddProperty( new PROPERTY<SCH_LINE, int>( _HKI( "End Y" ),
1433
1434 propMgr.AddProperty( new PROPERTY<SCH_LINE, double>( _HKI( "Length" ),
1436
1437 propMgr.AddProperty( new PROPERTY_ENUM<SCH_LINE, LINE_STYLE>( _HKI( "Line Style" ),
1439 .SetAvailableFunc( isGraphicLine );
1440
1441 propMgr.AddProperty( new PROPERTY_ENUM<SCH_LINE, WIRE_STYLE>( _HKI( "Wire Style" ),
1443 .SetAvailableFunc( isWireOrBus );
1444
1445 propMgr.AddProperty( new PROPERTY<SCH_LINE, int>( _HKI( "Line Width" ),
1447
1448 propMgr.AddProperty( new PROPERTY<SCH_LINE, COLOR4D>( _HKI( "Color" ),
1450
1451 propMgr.AddProperty( new PROPERTY_ENUM<SCH_LINE, LINE_ENDING_STYLE>( _HKI( "Start Shape" ),
1453 .SetAvailableFunc( isGraphicLine );
1454
1455 propMgr.AddProperty( new PROPERTY<SCH_LINE, int>( _HKI( "Start Length" ),
1457 .SetAvailableFunc( isGraphicLine );
1458
1459 propMgr.AddProperty( new PROPERTY<SCH_LINE, int>( _HKI( "Start Width" ),
1461 .SetAvailableFunc( isGraphicLine );
1462
1463 propMgr.AddProperty( new PROPERTY<SCH_LINE, int>( _HKI( "Start Stroke Width" ),
1466 .SetAvailableFunc( isGraphicLine );
1467
1468 propMgr.AddProperty( new PROPERTY_ENUM<SCH_LINE, LINE_ENDING_STYLE>( _HKI( "End Shape" ),
1470 .SetAvailableFunc( isGraphicLine );
1471
1472 propMgr.AddProperty( new PROPERTY<SCH_LINE, int>( _HKI( "End Length" ),
1474 .SetAvailableFunc( isGraphicLine );
1475
1476 propMgr.AddProperty( new PROPERTY<SCH_LINE, int>( _HKI( "End Width" ),
1478 .SetAvailableFunc( isGraphicLine );
1479
1480 propMgr.AddProperty( new PROPERTY<SCH_LINE, int>( _HKI( "End Stroke Width" ),
1483 .SetAvailableFunc( isGraphicLine );
1484 }
1486
const char * name
KICOMMON_API types::KiCadObjectType ToProtoEnum(KICAD_T aValue)
KICOMMON_API KICAD_T FromProtoEnum(types::KiCadObjectType aValue)
Definition api_enums.cpp:55
constexpr EDA_IU_SCALE schIUScale
Definition base_units.h:130
BITMAPS
A list of all bitmap identifiers.
@ add_dashed_line
BOX2< VECTOR2I > BOX2I
Definition box2.h:914
constexpr BOX2I KiROUND(const BOX2D &aBoxD)
Definition box2.h:982
constexpr BOX2< Vec > & Inflate(coord_type dx, coord_type dy)
Inflates the rectangle horizontally by dx and vertically by dy.
Definition box2.h:553
constexpr BOX2< Vec > & Merge(const BOX2< Vec > &aRect)
Modify the position and size of the rectangle in order to contain aRect.
Definition box2.h:594
constexpr bool Contains(const Vec &aPoint) const
Definition box2.h:165
constexpr bool Intersects(const BOX2< Vec > &aRect) const
Definition box2.h:308
static const COLOR4D UNSPECIFIED
For legacy support; used as a value to indicate color hasn't been set yet.
Definition color4d.h:400
static std::vector< DANGLING_END_ITEM >::iterator get_lower_pos(std::vector< DANGLING_END_ITEM > &aItemListByPos, const VECTOR2I &aPos)
Helper class used to store the state of schematic items that can be connected to other schematic item...
Definition sch_item.h:101
DANGLING_END_T GetType() const
Definition sch_item.h:137
EDA_ITEM * GetItem() const
Definition sch_item.h:135
The base class for create windows for drawing purpose.
const KIID m_Uuid
Definition eda_item.h:599
KICAD_T Type() const
Returns the type of object.
Definition eda_item.h:110
EDA_ITEM_FLAGS m_flags
Definition eda_item.h:608
EDA_GROUP * m_group
The group this item belongs to, if any. No ownership implied.
Definition eda_item.h:610
bool IsSelected() const
Definition eda_item.h:134
void SetSelected()
Definition eda_item.h:150
EDA_ITEM(EDA_ITEM *parent, KICAD_T idType, bool isSCH_ITEM=false, bool isBOARD_ITEM=false)
Definition eda_item.cpp:84
static bool ShortenSegmentForEndings(VECTOR2I &aStart, VECTOR2I &aEnd, const LINE_ENDING &aStartEnding, const LINE_ENDING &aEndEnding, int aLineWidth)
Shorten a segment body for line endings.
bool GetLineEndingsBoundingBox(BOX2I &aBBox, int aLineWidth) const
std::vector< SHAPE * > MakeEffectiveShapesWithLineEndings(int aLineWidth) const
Make effective geometry for the shape body shortened for line endings plus the line-ending geometry i...
EE_TYPE Overlapping(const BOX2I &aRect) const
Definition sch_rtree.h:253
ENUM_MAP & Map(T aValue, const wxString &aName)
Definition property.h:789
static ENUM_MAP< T > & Instance()
Definition property.h:783
wxPGChoices & Choices()
Definition property.h:834
Class that other classes need to inherit from, in order to be inspectable.
Definition inspectable.h:39
A color representation with 4 components: red, green, blue, alpha.
Definition color4d.h:101
std::shared_ptr< wxString > m_text
Definition color4d.h:397
double a
Alpha component.
Definition color4d.h:394
const COLOR4D & GetLayerColor(int aLayer) const
Return the color used to draw a layer.
static double lodScaleForThreshold(const KIGFX::VIEW *aView, int aWhatIu, int aThresholdIu)
Get the scale at which aWhatIu would be drawn at the same size as aThresholdIu on screen.
Definition view_item.cpp:35
static constexpr double LOD_HIDE
Return this constant from ViewGetLOD() to hide the item unconditionally.
Definition view_item.h:176
static constexpr double LOD_SHOW
Return this constant from ViewGetLOD() to show the item unconditionally.
Definition view_item.h:181
Hold a (potentially large) number of VIEW_ITEMs and renders them on a graphics device provided by the...
Definition view.h:63
Definition kiid.h:46
Decorative shape (arrowhead, circle, square) at the start or end of a graphic line,...
Definition line_ending.h:62
void Plot(PLOTTER *aPlotter, const VECTOR2I &aPoint, const EDA_ANGLE &aTangent, int aLineWidth, void *aData=nullptr) const
int GetLineStyle() const
Definition netclass.h:251
int GetWireWidth() const
Definition netclass.h:221
COLOR4D GetSchematicColor(bool aIsForSave=false) const
Definition netclass.h:236
int GetBusWidth() const
Definition netclass.h:229
Base plotter engine class.
Definition plotter.h:136
void MoveTo(const VECTOR2I &pos)
Definition plotter.h:310
virtual void SetDash(int aLineWidth, LINE_STYLE aLineStyle)=0
void FinishTo(const VECTOR2I &pos)
Definition plotter.h:320
virtual void SetCurrentLineWidth(int width, void *aData=nullptr)=0
Set the line width for the next drawing.
virtual void HyperlinkMenu(const BOX2I &aBox, const std::vector< wxString > &aDestURLs)
Create a clickable hyperlink menu with a rectangular click area.
Definition plotter.h:521
virtual void SetColor(const COLOR4D &color)=0
PROPERTY_BASE & SetAvailableFunc(std::function< bool(INSPECTABLE *)> aFunc)
Set a callback function to determine whether an object provides this property.
Definition property.h:263
Provide class metadata.
void InheritsAfter(TYPE_ID aDerived, TYPE_ID aBase)
Declare an inheritance relationship between types.
static PROPERTY_MANAGER & Instance()
PROPERTY_BASE & AddProperty(PROPERTY_BASE *aProperty, const wxString &aGroup=wxEmptyString)
Register a property.
Holds all the data relating to one schematic.
Definition schematic.h:149
Commit for the schematic and symbol editors.
Definition sch_commit.h:54
Schematic editor (Eeschema) main window.
Base class for any item which can be embedded within the SCHEMATIC container class,...
Definition sch_item.h:170
SCH_ITEM * Duplicate(bool addToParentGroup, SCH_COMMIT *aCommit=nullptr, bool aDoClone=false) const
Routine to create a new copy of given item.
Definition sch_item.cpp:191
void SetLocked(bool aLocked) override
Definition sch_item.h:262
SCH_RENDER_SETTINGS * getRenderSettings(PLOTTER *aPlotter) const
Definition sch_item.cpp:46
SCHEMATIC * Schematic() const
Search the item hierarchy to find a SCHEMATIC.
Definition sch_item.cpp:302
bool IsLocked() const override
Definition sch_item.cpp:179
std::vector< wxString > GetBusMemberNames(const SCH_SHEET_PATH *aSheet=nullptr) const
Names of the bus members of this item's connection, empty when it does not have a bus.
Definition sch_item.cpp:647
std::shared_ptr< NETCLASS > GetEffectiveNetClass(const SCH_SHEET_PATH *aSheet=nullptr) const
Definition sch_item.cpp:733
bool m_connectivity_dirty
Definition sch_item.h:852
void SetLayer(SCH_LAYER_ID aLayer)
Definition sch_item.h:354
SCH_LAYER_ID GetLayer() const
Return the layer this item is on.
Definition sch_item.h:353
void SetConnectivityDirty(bool aDirty=true)
Set the dirty flag.
Definition sch_item.cpp:314
bool IsConnectivityDirty() const
Definition sch_item.h:630
std::optional< wxString > GetConnectionName(const SCH_SHEET_PATH *aSheet=nullptr, bool aLocal=false, bool aIgnoreSheet=false) const
Return the active connection name; absent for missing or stale published rows.
Definition sch_item.cpp:629
SCH_ITEM(EDA_ITEM *aParent, KICAD_T aType, int aUnit=0, int aBodyStyle=0)
Definition sch_item.cpp:65
wxString ResolveText(const wxString &aText, const SCH_SHEET_PATH *aPath, int aDepth=0) const
Definition sch_item.cpp:464
int GetEffectivePenWidth(const SCH_RENDER_SETTINGS *aSettings) const
SCH_LAYER_ID m_layer
Definition sch_item.h:838
Segment description base class to describe items which have 2 end points (track, wire,...
Definition sch_line.h:39
int GetPenWidth() const override
Definition sch_line.cpp:444
void SetStartY(int aY)
Definition sch_line.h:141
bool doIsConnected(const VECTOR2I &aPosition) const override
Provide the object specific test to see if it is connected to aPosition.
Definition sch_line.cpp:991
int GetStartEndingStrokeWidth() const
Definition sch_line.h:223
int GetEndY() const
Definition sch_line.h:149
void GetEndPoints(std::vector< DANGLING_END_ITEM > &aItemList) override
Add the schematic item end points to aItemList if the item has end points.
Definition sch_line.cpp:694
void SetStartPoint(const VECTOR2I &aPosition)
Definition sch_line.h:137
void SetEndEnding(const LINE_ENDING &aEnding)
Definition sch_line.h:205
EDA_ITEM * Clone() const override
Create a duplicate of this item with linked list members set to NULL.
Definition sch_line.cpp:241
BITMAPS GetMenuImage() const override
Return a pointer to an image to be used in menus.
Definition sch_line.cpp:874
bool UpdateDanglingState(std::vector< DANGLING_END_ITEM > &aItemListByType, std::vector< DANGLING_END_ITEM > &aItemListByPos, const SCH_SHEET_PATH *aPath=nullptr) override
Test the schematic item to aItemList to check if it's dangling state has changed.
Definition sch_line.cpp:704
bool m_startIsDangling
True if start point is not connected.
Definition sch_line.h:417
bool HitTest(const VECTOR2I &aPosition, int aAccuracy=0) const override
Test if aPosition is inside or on the boundary of this item.
Definition sch_line.cpp:908
void SetPosition(const VECTOR2I &aPosition) override
void SetEndEndingStyle(LINE_ENDING_STYLE aStyle)
Definition sch_line.h:211
std::vector< VECTOR3I > BuildWireWithHopShape(const SCH_SCREEN *aScreen, double aArcRadius) const
For wires only: build the list of points to draw the shape using segments and 180 deg arcs Points are...
int GetStartX() const
Definition sch_line.h:138
SCH_LINE * NonGroupAware_BreakAt(const VECTOR2I &aPoint)
This version should only be used when importing files.
Definition sch_line.cpp:682
std::vector< VECTOR2I > GetConnectionPoints() const override
Add all the connection points for this item to aPoints.
Definition sch_line.cpp:808
int GetReverseAngleFrom(const VECTOR2I &aPoint) const
Definition sch_line.cpp:521
SCH_LINE(const VECTOR2I &pos=VECTOR2I(0, 0), int layer=LAYER_NOTES)
Definition sch_line.cpp:75
bool IsWire() const
Return true if the line is a wire.
void SetStartEndingStyle(LINE_ENDING_STYLE aStyle)
Definition sch_line.h:208
const BOX2I GetBoundingBox() const override
Return the orthogonal bounding box of this object for display purposes.
Definition sch_line.cpp:315
void SetEndEndingWidth(int aWidth)
Definition sch_line.h:221
void SetWireStyle(const WIRE_STYLE aStyle)
Definition sch_line.h:183
bool CanConnect(const SCH_ITEM *aItem) const override
Definition sch_line.cpp:766
bool IsParallel(const SCH_LINE *aLine) const
Definition sch_line.cpp:534
int GetStartY() const
Definition sch_line.h:140
int GetEndEndingLength() const
Definition sch_line.h:218
void SetLineWidth(const int aSize)
Definition sch_line.cpp:437
bool ShouldHopOver(const SCH_LINE *aLine) const
For wires only:
void MirrorHorizontally(int aCenter) override
Mirror item horizontally about aCenter.
Definition sch_line.cpp:488
virtual STROKE_PARAMS GetStroke() const override
Definition sch_line.h:198
LINE_ENDING m_startEnding
Line ending at start point.
Definition sch_line.h:423
int GetAngleFrom(const VECTOR2I &aPoint) const
Definition sch_line.cpp:508
void GetSelectedPoints(std::vector< VECTOR2I > &aPoints) const
Definition sch_line.cpp:827
LINE_STYLE GetEffectiveLineStyle() const
Definition sch_line.cpp:424
void GetMsgPanelInfo(EDA_DRAW_FRAME *aFrame, std::vector< MSG_PANEL_ITEM > &aList) override
Populate aList of MSG_PANEL_ITEM objects with it's internal state for display purposes.
void SetEndEndingStrokeWidth(int aWidth)
Definition sch_line.h:226
void Plot(PLOTTER *aPlotter, bool aBackground, const SCH_PLOT_OPTS &aPlotOpts, int aUnit, int aBodyStyle, const VECTOR2I &aOffset, bool aDimmed) override
Plot the item to aPlotter.
wxString m_operatingPoint
Definition sch_line.h:433
void SetLength(double aLength)
Definition sch_line.cpp:346
const LINE_ENDING & GetEndEnding() const
Definition sch_line.h:204
wxString GetClass() const override
Return the class name.
Definition sch_line.h:61
void Rotate(const VECTOR2I &aCenter, bool aRotateCCW) override
Rotate the item around aCenter 90 degrees in the clockwise direction.
Definition sch_line.cpp:498
VECTOR2I GetEndPoint() const
Definition sch_line.h:145
VECTOR2I GetStartPoint() const
Definition sch_line.h:136
bool ConnectionPropagatesTo(const EDA_ITEM *aItem) const override
Return true if this item should propagate connection info to aItem.
Definition sch_line.cpp:814
LINE_STYLE m_lastResolvedLineStyle
Definition sch_line.h:429
SCH_LINE * MergeOverlap(SCH_SCREEN *aScreen, SCH_LINE *aLine, bool aCheckJunctions)
Check line against aLine to see if it overlaps and merge if it does.
Definition sch_line.cpp:547
int GetEndEndingWidth() const
Definition sch_line.h:220
void SetEndY(int aY)
Definition sch_line.h:150
int GetStartEndingWidth() const
Definition sch_line.h:215
VECTOR2I m_start
Line start point.
Definition sch_line.h:419
bool IsBus() const
Return true if the line is a bus.
int m_lastResolvedWidth
Definition sch_line.h:430
void SetStartEndingLength(int aLength)
Definition sch_line.h:214
LINE_ENDING m_endEnding
Line ending at end point.
Definition sch_line.h:424
bool HasConnectivityChanges(const SCH_ITEM *aItem, const SCH_SHEET_PATH *aInstance=nullptr) const override
Check if aItem has connectivity changes against this object.
Definition sch_line.cpp:790
void Serialize(google::protobuf::Any &aContainer) const override
Serializes this object to the given Any message.
Definition sch_line.cpp:133
LINE_ENDING_STYLE GetEndEndingStyle() const
Definition sch_line.h:210
void SetLineStyle(const LINE_STYLE aStyle)
Definition sch_line.cpp:408
VECTOR2I m_end
Line end point.
Definition sch_line.h:420
void SetEndEndingLength(int aLength)
Definition sch_line.h:219
void Move(const VECTOR2I &aMoveVector) override
Move the item by aMoveVector to a new position.
Definition sch_line.cpp:247
int GetEndX() const
Definition sch_line.h:147
LINE_STYLE GetLineStyle() const
Definition sch_line.cpp:415
void SetStartEndingWidth(int aWidth)
Definition sch_line.h:216
int GetEndEndingStrokeWidth() const
Definition sch_line.h:225
LINE_ENDING_STYLE GetStartEndingStyle() const
Definition sch_line.h:207
void SetStartEnding(const LINE_ENDING &aEnding)
Definition sch_line.h:202
void MoveEnd(const VECTOR2I &aMoveVector)
Definition sch_line.cpp:260
KIGFX::COLOR4D m_lastResolvedColor
Definition sch_line.h:431
STROKE_PARAMS m_stroke
Line stroke properties.
Definition sch_line.h:422
SCH_LINE * BreakAt(SCH_COMMIT *aCommit, const VECTOR2I &aPoint)
Break this segment into two at the specified point.
Definition sch_line.cpp:670
bool m_endIsDangling
True if end point is not connected.
Definition sch_line.h:418
bool IsConnectable() const override
Definition sch_line.cpp:757
wxString GetFriendlyName() const override
Definition sch_line.cpp:230
double ViewGetLOD(int aLayer, const KIGFX::VIEW *aView) const override
Return the level of detail (LOD) of the item.
Definition sch_line.cpp:293
void MirrorVertically(int aCenter) override
Mirror item vertically about aCenter.
Definition sch_line.cpp:478
bool operator==(const SCH_ITEM &aOther) const override
bool operator<(const SCH_ITEM &aItem) const override
Definition sch_line.cpp:885
WIRE_STYLE GetWireStyle() const
Definition sch_line.h:184
wxString GetItemDescription(UNITS_PROVIDER *aUnitsProvider, bool aFull) const override
Return a user-visible description string of this item.
Definition sch_line.cpp:837
bool IsEndPoint(const VECTOR2I &aPoint) const override
Test if aPt is an end point of this schematic object.
Definition sch_line.h:88
bool IsGraphicLine() const
Return if the line is a graphic (non electrical line)
int GetLineWidth() const
Definition sch_line.h:195
KIGFX::COLOR4D GetLineColor() const
Return COLOR4D::UNSPECIFIED if a custom color hasn't been set for this line.
Definition sch_line.cpp:395
std::vector< int > ViewGetLayers() const override
Return the layers the item is drawn on (which may be more than its "home" layer)
Definition sch_line.cpp:283
void MoveStart(const VECTOR2I &aMoveVector)
Definition sch_line.cpp:254
void SetLineColor(const KIGFX::COLOR4D &aColor)
Definition sch_line.cpp:371
bool Deserialize(const google::protobuf::Any &aContainer) override
Deserializes the given protobuf message into this object.
Definition sch_line.cpp:181
double GetLength() const
Definition sch_line.cpp:340
void SetEndX(int aX)
Definition sch_line.h:148
void SetStartEndingStrokeWidth(int aWidth)
Definition sch_line.h:224
const LINE_ENDING & GetStartEnding() const
Definition sch_line.h:201
int GetStartEndingLength() const
Definition sch_line.h:213
void SetEndPoint(const VECTOR2I &aPosition)
Definition sch_line.h:146
void SetStartX(int aX)
Definition sch_line.h:139
double Similarity(const SCH_ITEM &aOther) const override
Return a measure of how likely the other object is to represent the same object.
void swapData(SCH_ITEM *aItem) override
Swap the internal data structures aItem with the schematic item.
Definition sch_line.cpp:977
A net chain is a collection of nets that are connected together through passive components.
EE_RTREE & Items()
Get the full RTree, usually for iterating.
Definition sch_screen.h:122
bool IsJunction(const VECTOR2I &aPosition) const
Test if a junction is required for the items at aPosition on the screen.
Handle access to a stack of flattened SCH_SHEET objects by way of a path for creating a flattened sch...
Definition seg.h:38
OPT_VECTOR2I Intersect(const SEG &aSeg, bool aIgnoreEndpoints=false, bool aLines=false) const
Compute intersection point of segment (this) with segment aSeg.
Definition seg.cpp:401
Represent a polyline containing arcs as well as line segments: A chain of connected line and/or arc s...
An abstract shape on 2D plane.
Definition shape.h:124
virtual bool Collide(const VECTOR2I &aP, int aClearance=0, int *aActual=nullptr, VECTOR2I *aLocation=nullptr) const
Check if the boundary of shape (this) lies closer to the point aP than aClearance,...
Definition shape.h:181
int GetWidth() const
LINE_STYLE GetLineStyle() const
KIGFX::COLOR4D GetColor() const
wxString MessageTextFromValue(double aValue, bool aAddUnitLabel=true, EDA_DATA_TYPE aType=EDA_DATA_TYPE::DISTANCE) const
A lower-precision version of StringFromValue().
#define DEFAULT_BUS_WIDTH_MILS
The default bus width in mils. (can be changed in preference menu)
#define DEFAULT_WIRE_WIDTH_MILS
The default wire width in mils. (can be changed in preference menu)
#define DEFAULT_LINE_WIDTH_MILS
The default line width in mils. (can be changed in preference menu)
#define _(s)
static constexpr EDA_ANGLE ANGLE_90
Definition eda_angle.h:450
static constexpr EDA_ANGLE ANGLE_270
Definition eda_angle.h:453
static constexpr EDA_ANGLE ANGLE_180
Definition eda_angle.h:452
@ NO_FILL
Definition eda_fill.h:30
#define STRUCT_DELETED
flag indication structures to be erased
#define ENDPOINT
ends. (Used to support dragging.)
#define SKIP_STRUCT
flag indicating that the structure should be ignored
#define STARTPOINT
When a line is selected, these flags indicate which.
static bool hasLineEnding(const LINE_ENDING &aStartEnding, const LINE_ENDING &aEndEnding)
@ SEGMENT
Definition eda_shape.h:56
a few functions useful in geometry calculations.
@ LAYER_DANGLING
Definition layer_ids.h:499
@ LAYER_WIRE
Definition layer_ids.h:474
@ LAYER_NOTES
Definition layer_ids.h:489
@ LAYER_NET_COLOR_HIGHLIGHT
Definition layer_ids.h:515
@ LAYER_BUS
Definition layer_ids.h:475
@ LAYER_SELECTION_SHADOWS
Definition layer_ids.h:517
@ LAYER_OP_VOLTAGES
Definition layer_ids.h:523
constexpr void MIRROR(T &aPoint, const T &aMirrorRef)
Updates aPoint with the mirror of aPoint relative to the aMirrorRef.
Definition mirror.h:41
bool ShapeHitTest(const SHAPE_LINE_CHAIN &aHitter, const SHAPE &aHittee, bool aHitteeContained)
Perform a shape-to-shape hit test.
SHAPE_LINE_CHAIN BoxToLineChain(const BOX2I &aBox)
Get a SHAPE_LINE_CHAIN representing the outline of a box.
std::optional< wxString > AppendConnectionInfo(const SCH_ITEM &aItem, std::vector< MSG_PANEL_ITEM > &aList, const SCH_SHEET_PATH *aPath=nullptr)
Append connection details; return its name for a signal, or no value for a bus/missing row.
KICOMMON_API void PackLineEnding(types::LineEnding &aOutput, const LINE_ENDING &aInput, const EDA_IU_SCALE &aScale)
KICOMMON_API void PackColor(types::Color &aOutput, const KIGFX::COLOR4D &aInput)
KICOMMON_API int UnpackDistance(const types::Distance &aInput, const EDA_IU_SCALE &aScale)
KICOMMON_API LINE_ENDING UnpackLineEnding(const types::LineEnding &aInput, const EDA_IU_SCALE &aScale)
KICOMMON_API KIGFX::COLOR4D UnpackColor(const types::Color &aInput)
KICOMMON_API void PackCustomProperties(google::protobuf::RepeatedPtrField< types::CustomProperty > *aOutput, const EDA_ITEM &aItem)
KICOMMON_API VECTOR2I UnpackVector2(const types::Vector2 &aInput, const EDA_IU_SCALE &aScale)
KICOMMON_API void PackDistance(types::Distance &aOutput, int aInput, const EDA_IU_SCALE &aScale)
KICOMMON_API void PackVector2(types::Vector2 &aOutput, const VECTOR2I &aInput, const EDA_IU_SCALE &aScale)
KICOMMON_API void UnpackCustomProperties(const google::protobuf::RepeatedPtrField< types::CustomProperty > &aInput, EDA_ITEM &aItem)
EDA_ANGLE abs(const EDA_ANGLE &aAngle)
Definition eda_angle.h:437
#define _HKI(x)
Definition page_info.cpp:40
static bool intersect(const SEGMENT_WITH_NORMALS &aSeg, const SFVEC2F &aStart, const SFVEC2F &aEnd)
#define TYPE_HASH(x)
Macro to generate unique identifier for a type.
Definition property.h:74
#define IMPLEMENT_ENUM_TO_WXANY(type)
Definition property.h:888
@ PT_COORD
Coordinate expressed in distance units (mm/inch)
Definition property.h:65
@ PT_SIZE
Size expressed in distance units (mm/inch)
Definition property.h:63
#define REGISTER_TYPE(x)
Helper macro to map type hashes to names.
@ BUS_END
Definition sch_item.h:85
@ PIN_END
Definition sch_item.h:87
@ BUS_ENTRY_END
Definition sch_item.h:89
@ WIRE_END
Definition sch_item.h:84
static struct SCH_LINE_DESC _SCH_LINE_DESC
std::optional< VECTOR2I > OPT_VECTOR2I
Definition seg.h:35
Utility functions for working with shapes.
const int scale
wxString UnescapeString(const wxString &aSource)
LINE_STYLE
Dashed line types.
WIRE_STYLE
bool m_PDFPropertyPopups
Definition sch_plotter.h:66
const SHAPE_LINE_CHAIN chain
VECTOR2I end
const int accuracy
int delta
#define M_PI
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:173
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:227
@ SCH_LINE_T
Definition typeinfo.h:159
@ SCH_NO_CONNECT_T
Definition typeinfo.h:156
@ SCH_SYMBOL_T
Definition typeinfo.h:168
@ SCH_DIRECTIVE_LABEL_T
Definition typeinfo.h:167
@ SCH_LABEL_T
Definition typeinfo.h:163
@ SCH_SHEET_T
Definition typeinfo.h:171
@ SCH_HIER_LABEL_T
Definition typeinfo.h:165
@ SCH_SHEET_PIN_T
Definition typeinfo.h:170
@ SCH_BUS_WIRE_ENTRY_T
Definition typeinfo.h:157
@ SCH_GLOBAL_LABEL_T
Definition typeinfo.h:164
@ SCH_JUNCTION_T
Definition typeinfo.h:155
VECTOR2< int32_t > VECTOR2I
Definition vector2d.h:708