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
21#include <base_units.h>
22#include <bitmaps.h>
23#include <string_utils.h>
24#include <core/mirror.h>
25#include <sch_painter.h>
26#include <sch_plotter.h>
29#include <sch_line.h>
30#include <sch_edit_frame.h>
32#include <connection_graph.h>
33#include <sch_netchain.h>
34#include <schematic.h>
37#include <trigo.h>
38#include <board_item.h>
39#include <api/api_enums.h>
40#include <api/api_utils.h>
41#include <api/schematic/schematic_types.pb.h>
42#include <properties/property.h>
44#include <origin_transforms.h>
45#include <math/util.h>
46
47
48SCH_LINE::SCH_LINE( const VECTOR2I& pos, int layer ) :
49 SCH_ITEM( nullptr, SCH_LINE_T )
50{
51 m_start = pos;
52 m_end = pos;
53 m_stroke.SetWidth( 0 );
54 m_stroke.SetLineStyle( LINE_STYLE::DEFAULT );
56
57 switch( layer )
58 {
59 default: m_layer = LAYER_NOTES; break;
60 case LAYER_WIRE: m_layer = LAYER_WIRE; break;
61 case LAYER_BUS: m_layer = LAYER_BUS; break;
62 }
63
64 if( layer == LAYER_NOTES )
66 else
68
69 if( layer == LAYER_WIRE )
71 else if( layer == LAYER_BUS )
73 else
75
78}
79
80
82 SCH_ITEM( aLine )
83{
84 m_start = aLine.m_start;
85 m_end = aLine.m_end;
86 m_stroke = aLine.m_stroke;
89
93
95
96 // Don't apply groups to cloned lines. We have too many areas where we clone them
97 // temporarily, then modify/split/join them in the line movement routines after the
98 // segments are committed. Rely on the commit framework to add the lines to the
99 // entered group as appropriate.
100 m_group = nullptr;
101}
102
103
104void SCH_LINE::Serialize( google::protobuf::Any &aContainer ) const
105{
106 using namespace kiapi::common;
107
108 kiapi::schematic::types::SchematicLine line;
109 types::StrokeAttributes* stroke = line.mutable_stroke();
110
111 line.mutable_id()->set_value( m_Uuid.AsStdString() );
112 PackVector2( *line.mutable_start(), GetStartPoint(), schIUScale );
113 PackVector2( *line.mutable_end(), GetEndPoint(), schIUScale );
114 line.set_locked( IsLocked() ? types::LockedState::LS_LOCKED : types::LockedState::LS_UNLOCKED );
115
116 PackDistance( *stroke->mutable_width(), m_stroke.GetWidth(), schIUScale );
117 stroke->set_style( ToProtoEnum<LINE_STYLE, types::StrokeLineStyle>( m_stroke.GetLineStyle() ) );
118
119 if( m_stroke.GetColor() != COLOR4D::UNSPECIFIED )
120 PackColor( *stroke->mutable_color(), m_stroke.GetColor() );
121
122 switch( GetLayer() )
123 {
124 case LAYER_WIRE:
125 line.set_type( kiapi::schematic::types::SLT_WIRE );
126 break;
127
128 case LAYER_BUS:
129 line.set_type( kiapi::schematic::types::SLT_BUS );
130 break;
131
132 case LAYER_NOTES:
133 line.set_type( kiapi::schematic::types::SLT_GRAPHIC );
134 break;
135
136 default:
137 line.set_type( kiapi::schematic::types::SLT_UNKNOWN );
138 break;
139 }
140
141 aContainer.PackFrom( line );
142}
143
144
145bool SCH_LINE::Deserialize( const google::protobuf::Any &aContainer )
146{
147 using namespace kiapi::common;
148
149 kiapi::schematic::types::SchematicLine line;
150
151 if( !aContainer.UnpackTo( &line ) )
152 return false;
153
154 const_cast<KIID&>( m_Uuid ) = KIID( line.id().value() );
155 SetStartPoint( UnpackVector2( line.start(), schIUScale ) );
156 SetEndPoint( UnpackVector2( line.end(), schIUScale ) );
157 SetLocked( line.locked() == types::LockedState::LS_LOCKED );
158
159 m_stroke.SetWidth( UnpackDistance( line.stroke().width(), schIUScale ) );
160 m_stroke.SetLineStyle( FromProtoEnum<LINE_STYLE, types::StrokeLineStyle>( line.stroke().style() ) );
161
162 if( line.stroke().has_color() )
163 m_stroke.SetColor( UnpackColor( line.stroke().color() ) );
164 else
165 m_stroke.SetColor( COLOR4D::UNSPECIFIED );
166
167 switch( line.type() )
168 {
169 case kiapi::schematic::types::SLT_WIRE:
171 break;
172
173 case kiapi::schematic::types::SLT_BUS:
175 break;
176
177 default:
178 case kiapi::schematic::types::SLT_GRAPHIC:
180 break;
181 }
182
183 return true;
184}
185
186
188{
189 switch( GetLayer() )
190 {
191 case LAYER_WIRE: return _( "Wire" );
192 case LAYER_BUS: return _( "Bus" );
193 default: return _( "Graphic Line" );
194 }
195}
196
197
199{
200 return new SCH_LINE( *this );
201}
202
203
204void SCH_LINE::Move( const VECTOR2I& aOffset )
205{
206 m_start += aOffset;
207 m_end += aOffset;
208}
209
210
211void SCH_LINE::MoveStart( const VECTOR2I& aOffset )
212{
213 m_start += aOffset;
214}
215
216
217void SCH_LINE::MoveEnd( const VECTOR2I& aOffset )
218{
219 m_end += aOffset;
220}
221
222
223#if defined(DEBUG)
224
225void SCH_LINE::Show( int nestLevel, std::ostream& os ) const
226{
227 NestedSpace( nestLevel, os ) << '<' << GetClass().Lower().mb_str()
228 << " layer=\"" << m_layer << '"'
229 << " startIsDangling=\"" << m_startIsDangling
230 << '"' << " endIsDangling=\""
231 << m_endIsDangling << '"' << ">"
232 << " <start" << m_start << "/>"
233 << " <end" << m_end << "/>" << "</"
234 << GetClass().Lower().mb_str() << ">\n";
235}
236
237#endif
238
239
248
249
250double SCH_LINE::ViewGetLOD( int aLayer, const KIGFX::VIEW* aView ) const
251{
252 if( aLayer == LAYER_OP_VOLTAGES )
253 {
254 if( m_start == m_end )
255 return LOD_HIDE;
256
257 const int height = std::abs( m_end.y - m_start.y );
258
259 // Operating points will be shown only if zoom is appropriate
260 if( height > 0 )
261 return lodScaleForThreshold( aView, height, schIUScale.mmToIU( 5 ) );
262
263 const int width = std::abs( m_end.x - m_start.x );
264 return lodScaleForThreshold( aView, width, schIUScale.mmToIU( 15 ) );
265 }
266
267 // Other layers are always drawn.
268 return LOD_SHOW;
269}
270
271
273{
274 int width = GetPenWidth() / 2;
275
276 int xmin = std::min( m_start.x, m_end.x ) - width;
277 int ymin = std::min( m_start.y, m_end.y ) - width;
278
279 int xmax = std::max( m_start.x, m_end.x ) + width + 1;
280 int ymax = std::max( m_start.y, m_end.y ) + width + 1;
281
282 BOX2I ret( VECTOR2I( xmin, ymin ), VECTOR2I( xmax - xmin, ymax - ymin ) );
283
284 return ret;
285}
286
287
289{
290 return m_start.Distance( m_end );
291}
292
293
294void SCH_LINE::SetLength( double aLength )
295{
296 if( aLength < 0.0 )
297 aLength = 0.0;
298
299 double currentLength = GetLength();
300 VECTOR2I start = GetStartPoint();
302
303 if( currentLength <= 0.0 )
304 {
305 end = start + KiROUND( aLength, 0.0 );
306 }
307 else
308 {
309 VECTOR2I delta = GetEndPoint() - start;
310 double scale = aLength / currentLength;
311
312 end = start + KiROUND( delta * scale );
313 }
314
315 SetEndPoint( end );
316}
317
318
319void SCH_LINE::SetLineColor( const COLOR4D& aColor )
320{
321 m_stroke.SetColor( aColor );
323}
324
325
326void SCH_LINE::SetLineColor( const double r, const double g, const double b, const double a )
327{
328 COLOR4D newColor(r, g, b, a);
329
330 if( newColor == COLOR4D::UNSPECIFIED )
331 {
332 m_stroke.SetColor( COLOR4D::UNSPECIFIED );
333 }
334 else
335 {
336 // Eeschema does not allow alpha channel in colors
337 newColor.a = 1.0;
338 m_stroke.SetColor( newColor );
339 }
340}
341
342
354
355
357{
358 m_stroke.SetLineStyle( aStyle );
360}
361
362
364{
365 if( IsGraphicLine() && m_stroke.GetLineStyle() == LINE_STYLE::DEFAULT )
366 return LINE_STYLE::SOLID;
367 else
368 return m_stroke.GetLineStyle();
369}
370
371
383
384
385void SCH_LINE::SetLineWidth( const int aSize )
386{
387 m_stroke.SetWidth( aSize );
389}
390
391
393{
394 SCHEMATIC* schematic = Schematic();
395
396 switch ( m_layer )
397 {
398 default:
399 if( m_stroke.GetWidth() > 0 )
400 return m_stroke.GetWidth();
401
402 if( schematic )
403 return schematic->Settings().m_DefaultLineWidth;
404
405 return schIUScale.MilsToIU( DEFAULT_LINE_WIDTH_MILS );
406
407 case LAYER_WIRE:
408 if( m_stroke.GetWidth() > 0 )
409 m_lastResolvedWidth = m_stroke.GetWidth();
410 else if( !IsConnectivityDirty() )
412
413 return m_lastResolvedWidth;
414
415 case LAYER_BUS:
416 if( m_stroke.GetWidth() > 0 )
417 m_lastResolvedWidth = m_stroke.GetWidth();
418 else if( !IsConnectivityDirty() )
420
421 return m_lastResolvedWidth;
422 }
423}
424
425
426void SCH_LINE::MirrorVertically( int aCenter )
427{
428 if( m_flags & STARTPOINT )
429 MIRROR( m_start.y, aCenter );
430
431 if( m_flags & ENDPOINT )
432 MIRROR( m_end.y, aCenter );
433}
434
435
437{
438 if( m_flags & STARTPOINT )
439 MIRROR( m_start.x, aCenter );
440
441 if( m_flags & ENDPOINT )
442 MIRROR( m_end.x, aCenter );
443}
444
445
446void SCH_LINE::Rotate( const VECTOR2I& aCenter, bool aRotateCCW )
447{
448 if( m_flags & STARTPOINT )
449 RotatePoint( m_start, aCenter, aRotateCCW ? ANGLE_90 : ANGLE_270 );
450
451 if( m_flags & ENDPOINT )
452 RotatePoint( m_end, aCenter, aRotateCCW ? ANGLE_90 : ANGLE_270 );
453}
454
455
456int SCH_LINE::GetAngleFrom( const VECTOR2I& aPoint ) const
457{
458 VECTOR2I vec;
459
460 if( aPoint == m_start )
461 vec = m_end - aPoint;
462 else
463 vec = m_start - aPoint;
464
465 return KiROUND( EDA_ANGLE( vec ).AsDegrees() );
466}
467
468
469int SCH_LINE::GetReverseAngleFrom( const VECTOR2I& aPoint ) const
470{
471 VECTOR2I vec;
472
473 if( aPoint == m_end )
474 vec = m_start - aPoint;
475 else
476 vec = m_end - aPoint;
477
478 return KiROUND( EDA_ANGLE( vec ).AsDegrees() );
479}
480
481
482bool SCH_LINE::IsParallel( const SCH_LINE* aLine ) const
483{
484 wxCHECK_MSG( aLine != nullptr && aLine->Type() == SCH_LINE_T, false,
485 wxT( "Cannot test line segment for overlap." ) );
486
487 VECTOR2I firstSeg = m_end - m_start;
488 VECTOR2I secondSeg = aLine->m_end - aLine->m_start;
489
490 // Use long long here to avoid overflow in calculations
491 return !( (long long) firstSeg.x * secondSeg.y - (long long) firstSeg.y * secondSeg.x );
492}
493
494
495SCH_LINE* SCH_LINE::MergeOverlap( SCH_SCREEN* aScreen, SCH_LINE* aLine, bool aCheckJunctions )
496{
497 auto less =
498 []( const VECTOR2I& lhs, const VECTOR2I& rhs ) -> bool
499 {
500 if( lhs.x == rhs.x )
501 return lhs.y < rhs.y;
502
503 return lhs.x < rhs.x;
504 };
505
506 wxCHECK_MSG( aLine != nullptr && aLine->Type() == SCH_LINE_T, nullptr,
507 wxT( "Cannot test line segment for overlap." ) );
508
509 if( this == aLine || GetLayer() != aLine->GetLayer() )
510 return nullptr;
511
512 VECTOR2I leftmost_start = aLine->m_start;
513 VECTOR2I leftmost_end = aLine->m_end;
514
515 VECTOR2I rightmost_start = m_start;
516 VECTOR2I rightmost_end = m_end;
517
518 // We place the start to the left and below the end of both lines
519 if( leftmost_start != std::min( { leftmost_start, leftmost_end }, less ) )
520 std::swap( leftmost_start, leftmost_end );
521 if( rightmost_start != std::min( { rightmost_start, rightmost_end }, less ) )
522 std::swap( rightmost_start, rightmost_end );
523
524 // - leftmost is the line that starts farthest to the left
525 // - other is the line that is _not_ leftmost
526 // - rightmost is the line that ends farthest to the right. This may or may not be 'other'
527 // as the second line may be completely covered by the first.
528 if( less( rightmost_start, leftmost_start ) )
529 {
530 std::swap( leftmost_start, rightmost_start );
531 std::swap( leftmost_end, rightmost_end );
532 }
533
534 VECTOR2I other_start = rightmost_start;
535 VECTOR2I other_end = rightmost_end;
536
537 if( less( rightmost_end, leftmost_end ) )
538 {
539 rightmost_start = leftmost_start;
540 rightmost_end = leftmost_end;
541 }
542
543 // If we end one before the beginning of the other, no overlap is possible
544 if( less( leftmost_end, other_start ) )
545 {
546 return nullptr;
547 }
548
549 // Search for a common end:
550 if( ( leftmost_start == other_start ) && ( leftmost_end == other_end ) ) // Trivial case
551 {
552 SCH_LINE* ret = new SCH_LINE( *aLine );
553 ret->SetStartPoint( leftmost_start );
554 ret->SetEndPoint( leftmost_end );
555 ret->SetConnectivityDirty( true );
556
557 if( IsSelected() || aLine->IsSelected() )
558 ret->SetSelected();
559
560 return ret;
561 }
562
563 bool colinear = false;
564
565 /* Test alignment: */
566 if( ( leftmost_start.y == leftmost_end.y ) &&
567 ( other_start.y == other_end.y ) ) // Horizontal segment
568 {
569 colinear = ( leftmost_start.y == other_start.y );
570 }
571 else if( ( leftmost_start.x == leftmost_end.x ) &&
572 ( other_start.x == other_end.x ) ) // Vertical segment
573 {
574 colinear = ( leftmost_start.x == other_start.x );
575 }
576 else
577 {
578 // We use long long here to avoid overflow -- it enforces promotion
579 // The slope of the left-most line is dy/dx. Then we check that the slope from the
580 // left most start to the right most start is the same as well as the slope from the
581 // left most start to right most end.
582 long long dx = leftmost_end.x - leftmost_start.x;
583 long long dy = leftmost_end.y - leftmost_start.y;
584 colinear = ( ( ( other_start.y - leftmost_start.y ) * dx ==
585 ( other_start.x - leftmost_start.x ) * dy ) &&
586 ( ( other_end.y - leftmost_start.y ) * dx ==
587 ( other_end.x - leftmost_start.x ) * dy ) );
588 }
589
590 if( !colinear )
591 return nullptr;
592
593 // We either have a true overlap or colinear touching segments. We always want to merge
594 // the former, but the later only get merged if there no junction at the touch point.
595
596 bool touching = leftmost_end == rightmost_start;
597
598 if( touching && aCheckJunctions && aScreen->IsJunction( leftmost_end ) )
599 return nullptr;
600
601 // Make a new segment that merges the 2 segments
602 leftmost_end = rightmost_end;
603
604 SCH_LINE* ret = new SCH_LINE( *aLine );
605 ret->SetStartPoint( leftmost_start );
606 ret->SetEndPoint( leftmost_end );
607 ret->SetConnectivityDirty( true );
608
609 if( IsSelected() || aLine->IsSelected() )
610 ret->SetSelected();
611
612 return ret;
613}
614
615
617{
618 SCH_LINE* newSegment = static_cast<SCH_LINE*>( Duplicate( true /* addToParentGroup */, aCommit ) );
619
620 newSegment->SetStartPoint( aPoint );
621 newSegment->SetConnectivityDirty( true );
622 SetEndPoint( aPoint );
623
624 return newSegment;
625}
626
627
629{
630 SCH_LINE* newSegment = static_cast<SCH_LINE*>( Duplicate( false /* addToParentGroup */, nullptr ) );
631
632 newSegment->SetStartPoint( aPoint );
633 newSegment->SetConnectivityDirty( true );
634 SetEndPoint( aPoint );
635
636 return newSegment;
637}
638
639
640void SCH_LINE::GetEndPoints( std::vector <DANGLING_END_ITEM>& aItemList )
641{
642 if( IsConnectable() )
643 {
644 aItemList.emplace_back( IsBus() ? BUS_END : WIRE_END, this, m_start );
645 aItemList.emplace_back( IsBus() ? BUS_END : WIRE_END, this, m_end );
646 }
647}
648
649
650bool SCH_LINE::UpdateDanglingState( std::vector<DANGLING_END_ITEM>& aItemListByType,
651 std::vector<DANGLING_END_ITEM>& aItemListByPos,
652 const SCH_SHEET_PATH* aPath )
653{
654 if( !IsConnectable() )
655 return false;
656
657 bool previousStartState = m_startIsDangling;
658 bool previousEndState = m_endIsDangling;
659
661
662 for( auto it = DANGLING_END_ITEM_HELPER::get_lower_pos( aItemListByPos, m_start );
663 it < aItemListByPos.end() && it->GetPosition() == m_start; it++ )
664 {
665 DANGLING_END_ITEM& item = *it;
666
667 if( item.GetItem() == this )
668 continue;
669
670 if( ( IsWire() && item.GetType() != BUS_END && item.GetType() != BUS_ENTRY_END )
671 || ( IsBus() && item.GetType() != WIRE_END && item.GetType() != PIN_END ) )
672 {
673 m_startIsDangling = false;
674 break;
675 }
676 }
677
678 for( auto it = DANGLING_END_ITEM_HELPER::get_lower_pos( aItemListByPos, m_end );
679 it < aItemListByPos.end() && it->GetPosition() == m_end; it++ )
680 {
681 DANGLING_END_ITEM& item = *it;
682
683 if( item.GetItem() == this )
684 continue;
685
686 if( ( IsWire() && item.GetType() != BUS_END && item.GetType() != BUS_ENTRY_END )
687 || ( IsBus() && item.GetType() != WIRE_END && item.GetType() != PIN_END ) )
688 {
689 m_endIsDangling = false;
690 break;
691 }
692 }
693
694 // We only use the bus dangling state for automatic line starting, so we don't care if it
695 // has changed or not (and returning true will result in extra work)
696 if( IsBus() )
697 return false;
698
699 return previousStartState != m_startIsDangling || previousEndState != m_endIsDangling;
700}
701
702
704{
705 if( m_layer == LAYER_WIRE || m_layer == LAYER_BUS )
706 return true;
707
708 return false;
709}
710
711
712bool SCH_LINE::CanConnect( const SCH_ITEM* aItem ) const
713{
714 switch( aItem->Type() )
715 {
716 case SCH_NO_CONNECT_T:
717 case SCH_SYMBOL_T:
718 return IsWire();
719
720 case SCH_JUNCTION_T:
721 case SCH_LABEL_T:
723 case SCH_HIER_LABEL_T:
726 case SCH_SHEET_T:
727 case SCH_SHEET_PIN_T:
728 return IsWire() || IsBus();
729
730 default:
731 return m_layer == aItem->GetLayer();
732 }
733}
734
735
737 const SCH_SHEET_PATH* aInstance ) const
738{
739 // Do not compare to ourself.
740 if( aItem == this || !IsConnectable() )
741 return false;
742
743 const SCH_LINE* line = dynamic_cast<const SCH_LINE*>( aItem );
744
745 // Don't compare against a different SCH_ITEM.
746 wxCHECK( line, false );
747
748 if( GetStartPoint() != line->GetStartPoint() )
749 return true;
750
751 return GetEndPoint() != line->GetEndPoint();
752}
753
754
755std::vector<VECTOR2I> SCH_LINE::GetConnectionPoints() const
756{
757 return { m_start, m_end };
758}
759
760
762{
763 switch( aItem->Type() )
764 {
765 case SCH_LINE_T:
766 return IsBus() == static_cast<const SCH_LINE*>( aItem )->IsBus();
767
768 default:
769 return true;
770 }
771}
772
773
774void SCH_LINE::GetSelectedPoints( std::vector<VECTOR2I>& aPoints ) const
775{
776 if( m_flags & STARTPOINT )
777 aPoints.push_back( m_start );
778
779 if( m_flags & ENDPOINT )
780 aPoints.push_back( m_end );
781}
782
783
784wxString SCH_LINE::GetItemDescription( UNITS_PROVIDER* aUnitsProvider, bool aFull ) const
785{
786 wxString txtfmt;
787
788 if( m_start.x == m_end.x )
789 {
790 switch( m_layer )
791 {
792 case LAYER_WIRE: txtfmt = _( "Vertical Wire, length %s" ); break;
793 case LAYER_BUS: txtfmt = _( "Vertical Bus, length %s" ); break;
794 default: txtfmt = _( "Vertical Graphic Line, length %s" ); break;
795 }
796 }
797 else if( m_start.y == m_end.y )
798 {
799 switch( m_layer )
800 {
801 case LAYER_WIRE: txtfmt = _( "Horizontal Wire, length %s" ); break;
802 case LAYER_BUS: txtfmt = _( "Horizontal Bus, length %s" ); break;
803 default: txtfmt = _( "Horizontal Graphic Line, length %s" ); break;
804 }
805 }
806 else
807 {
808 switch( m_layer )
809 {
810 case LAYER_WIRE: txtfmt = _( "Wire, length %s" ); break;
811 case LAYER_BUS: txtfmt = _( "Bus, length %s" ); break;
812 default: txtfmt = _( "Graphic Line, length %s" ); break;
813 }
814 }
815
816 return wxString::Format( txtfmt,
817 aUnitsProvider->MessageTextFromValue( m_start.Distance( m_end ) ) );
818}
819
820
822{
823 if( m_layer == LAYER_NOTES )
825 else if( m_layer == LAYER_WIRE )
826 return BITMAPS::add_line;
827
828 return BITMAPS::add_bus;
829}
830
831
832bool SCH_LINE::operator <( const SCH_ITEM& aItem ) const
833{
834 if( Type() != aItem.Type() )
835 return Type() < aItem.Type();
836
837 const SCH_LINE* line = static_cast<const SCH_LINE*>( &aItem );
838
839 if( GetLayer() != line->GetLayer() )
840 return GetLayer() < line->GetLayer();
841
842 if( GetStartPoint().x != line->GetStartPoint().x )
843 return GetStartPoint().x < line->GetStartPoint().x;
844
845 if( GetStartPoint().y != line->GetStartPoint().y )
846 return GetStartPoint().y < line->GetStartPoint().y;
847
848 if( GetEndPoint().x != line->GetEndPoint().x )
849 return GetEndPoint().x < line->GetEndPoint().x;
850
851 return GetEndPoint().y < line->GetEndPoint().y;
852}
853
854
855bool SCH_LINE::HitTest( const VECTOR2I& aPosition, int aAccuracy ) const
856{
857 // Performance enhancement for connection-building
858 if( aPosition == m_start || aPosition == m_end )
859 return true;
860
861 if( aAccuracy >= 0 )
862 aAccuracy += GetPenWidth() / 2;
863 else
864 aAccuracy = abs( aAccuracy );
865
866 return TestSegmentHit( aPosition, m_start, m_end, aAccuracy );
867}
868
869
870bool SCH_LINE::HitTest( const BOX2I& aRect, bool aContained, int aAccuracy ) const
871{
873 return false;
874
875 BOX2I rect = aRect;
876
877 if ( aAccuracy )
878 rect.Inflate( aAccuracy );
879
880 if( aContained )
881 return rect.Contains( m_start ) && rect.Contains( m_end );
882
883 return rect.Intersects( m_start, m_end );
884}
885
886
887bool SCH_LINE::HitTest( const SHAPE_LINE_CHAIN& aPoly, bool aContained ) const
888{
890 return false;
891
893 return KIGEOM::ShapeHitTest( aPoly, line, aContained );
894}
895
896
898{
899 SCH_LINE* item = (SCH_LINE*) aItem;
900
901 std::swap( m_start, item->m_start );
902 std::swap( m_end, item->m_end );
903 std::swap( m_startIsDangling, item->m_startIsDangling );
904 std::swap( m_endIsDangling, item->m_endIsDangling );
905 std::swap( m_stroke, item->m_stroke );
906}
907
908
909bool SCH_LINE::doIsConnected( const VECTOR2I& aPosition ) const
910{
911 if( m_layer != LAYER_WIRE && m_layer != LAYER_BUS )
912 return false;
913
914 return IsEndPoint( aPosition );
915}
916
917
918void SCH_LINE::Plot( PLOTTER* aPlotter, bool aBackground, const SCH_PLOT_OPTS& aPlotOpts,
919 int aUnit, int aBodyStyle, const VECTOR2I& aOffset, bool aDimmed )
920{
921 if( aBackground )
922 return;
923
924 SCH_RENDER_SETTINGS* renderSettings = getRenderSettings( aPlotter );
925 int penWidth = GetEffectivePenWidth( renderSettings );
926 COLOR4D color = GetLineColor();
927
928 if( color == COLOR4D::UNSPECIFIED )
929 color = renderSettings->GetLayerColor( GetLayer() );
930
931 if( color.m_text && Schematic() )
932 color = COLOR4D( ResolveText( *color.m_text, &Schematic()->CurrentSheet() ) );
933
934 aPlotter->SetColor( color );
935
936 aPlotter->SetCurrentLineWidth( penWidth );
937 aPlotter->SetDash( penWidth, GetEffectiveLineStyle() );
938
939 aPlotter->MoveTo( m_start );
940 aPlotter->FinishTo( m_end );
941
942 aPlotter->SetDash( penWidth, LINE_STYLE::SOLID );
943
944 // Plot attributes to a hypertext menu
945 std::vector<wxString> properties;
946 BOX2I bbox = GetBoundingBox();
947 bbox.Inflate( penWidth * 3 );
948
949 if( aPlotOpts.m_PDFPropertyPopups )
950 {
951 if( GetLayer() == LAYER_WIRE )
952 {
953 if( SCH_CONNECTION* connection = Connection() )
954 {
955 properties.emplace_back( wxString::Format( wxT( "!%s = %s" ),
956 _( "Net" ),
957 connection->Name() ) );
958
959 properties.emplace_back( wxString::Format( wxT( "!%s = %s" ),
960 _( "Resolved netclass" ),
961 GetEffectiveNetClass()->GetHumanReadableName() ) );
962 }
963 }
964 else if( GetLayer() == LAYER_BUS )
965 {
966 if( SCH_CONNECTION* connection = Connection() )
967 {
968 for( const std::shared_ptr<SCH_CONNECTION>& member : connection->Members() )
969 properties.emplace_back( wxT( "!" ) + member->Name() );
970 }
971 }
972
973 if( !properties.empty() )
974 aPlotter->HyperlinkMenu( bbox, properties );
975 }
976}
977
978
979void SCH_LINE::SetPosition( const VECTOR2I& aPosition )
980{
981 m_end = m_end - ( m_start - aPosition );
982 m_start = aPosition;
983}
984
985
986void SCH_LINE::GetMsgPanelInfo( EDA_DRAW_FRAME* aFrame, std::vector<MSG_PANEL_ITEM>& aList )
987{
988 wxString msg;
989
990 switch( GetLayer() )
991 {
992 case LAYER_WIRE: msg = _( "Wire" ); break;
993 case LAYER_BUS: msg = _( "Bus" ); break;
994 default: msg = _( "Graphical" ); break;
995 }
996
997 aList.emplace_back( _( "Line Type" ), msg );
998
999 LINE_STYLE lineStyle = GetStroke().GetLineStyle();
1000
1001 if( GetEffectiveLineStyle() != lineStyle )
1002 aList.emplace_back( _( "Line Style" ), _( "from netclass" ) );
1003 else
1004 m_stroke.GetMsgPanelInfo( aFrame, aList, true, false );
1005
1006 SCH_CONNECTION* conn = nullptr;
1007
1008 if( !IsConnectivityDirty() && dynamic_cast<SCH_EDIT_FRAME*>( aFrame ) )
1009 conn = Connection();
1010
1011 if( conn )
1012 {
1013 conn->AppendInfoToMsgPanel( aList );
1014
1015 if( !conn->IsBus() )
1016 {
1017 aList.emplace_back( _( "Resolved Netclass" ),
1018 UnescapeString( GetEffectiveNetClass()->GetHumanReadableName() ) );
1019
1020 if( SCHEMATIC* schematic = Schematic() )
1021 {
1022 if( SCH_NETCHAIN* chain = schematic->ConnectionGraph()->GetNetChainForNet( conn->Name() ) )
1023 aList.emplace_back( _( "Net Chain" ), UnescapeString( chain->GetName() ) );
1024 }
1025 }
1026 }
1027}
1028
1029
1031{
1032 return ( GetLayer() == LAYER_NOTES );
1033}
1034
1035
1037{
1038 return ( GetLayer() == LAYER_WIRE );
1039}
1040
1041
1043{
1044 return ( GetLayer() == LAYER_BUS );
1045}
1046
1047
1048bool SCH_LINE::operator==( const SCH_ITEM& aOther ) const
1049{
1050 if( Type() != aOther.Type() )
1051 return false;
1052
1053 const SCH_LINE& other = static_cast<const SCH_LINE&>( aOther );
1054
1055 if( GetLayer() != other.GetLayer() )
1056 return false;
1057
1058 if( m_start != other.m_start )
1059 return false;
1060
1061 if( m_end != other.m_end )
1062 return false;
1063
1064 if( m_stroke.GetWidth() != other.m_stroke.GetWidth() )
1065 return false;
1066
1067 if( m_stroke.GetColor() != other.m_stroke.GetColor() )
1068 return false;
1069
1070 if( m_stroke.GetLineStyle() != other.m_stroke.GetLineStyle() )
1071 return false;
1072
1073 return true;
1074}
1075
1076
1077double SCH_LINE::Similarity( const SCH_ITEM& aOther ) const
1078{
1079 if( m_Uuid == aOther.m_Uuid )
1080 return 1.0;
1081
1082 if( Type() != aOther.Type() )
1083 return 0.0;
1084
1085 const SCH_LINE& other = static_cast<const SCH_LINE&>( aOther );
1086
1087 if( GetLayer() != other.GetLayer() )
1088 return 0.0;
1089
1090 double similarity = 1.0;
1091
1092 if( m_start != other.m_start )
1093 similarity *= 0.9;
1094
1095 if( m_end != other.m_end )
1096 similarity *= 0.9;
1097
1098 if( m_stroke.GetWidth() != other.m_stroke.GetWidth() )
1099 similarity *= 0.9;
1100
1101 if( m_stroke.GetColor() != other.m_stroke.GetColor() )
1102 similarity *= 0.9;
1103
1104 if( m_stroke.GetLineStyle() != other.m_stroke.GetLineStyle() )
1105 similarity *= 0.9;
1106
1107 return similarity;
1108}
1109
1110
1111bool SCH_LINE::ShouldHopOver( const SCH_LINE* aLine ) const
1112{
1113 // try to find if this should hop over aLine. Horizontal wires have preference for hop.
1114 bool isMeVertical = ( m_end.x == m_start.x );
1115 bool isCandidateVertical = ( aLine->GetEndPoint().x == aLine->GetStartPoint().x );
1116
1117 // Vertical vs. Horizontal: Horizontal should hop
1118 if( isMeVertical && !isCandidateVertical )
1119 return false;
1120
1121 if( isCandidateVertical && !isMeVertical )
1122 return true;
1123
1124 // Both this and aLine have a slope. Try to find the best candidate
1125 double slopeMe = ( m_end.y - m_start.y ) / (double) ( m_end.x - m_start.x );
1126 double slopeCandidate = ( aLine->GetEndPoint().y - aLine->GetStartPoint().y )
1127 / (double) ( aLine->GetEndPoint().x - aLine->GetStartPoint().x );
1128
1129 if( fabs( slopeMe ) == fabs( slopeCandidate ) ) // Can easily happen with 45 deg wires
1130 return slopeMe < slopeCandidate; // signs are certainly different
1131
1132 return fabs( slopeMe ) < fabs( slopeCandidate ); // The shallower line should hop
1133}
1134
1135
1136std::vector<VECTOR3I> SCH_LINE::BuildWireWithHopShape( const SCH_SCREEN* aScreen,
1137 double aArcRadius ) const
1138{
1139 // Note: Points are VECTOR3D, with Z coord used as flag
1140 // for segments: start point and end point have the Z coord = 0
1141 // for arcs: start point middle point and end point have the Z coord = 1
1142
1143 std::vector<VECTOR3I> wire_shape; // List of coordinates:
1144 // 2 points for a segment, 3 points for an arc
1145
1146 if( !IsWire() && !IsBus() )
1147 {
1148 wire_shape.emplace_back( GetStartPoint().x,GetStartPoint().y, 0 );
1149 wire_shape.emplace_back( GetEndPoint().x, GetEndPoint().y, 0 );
1150 return wire_shape;
1151 }
1152
1153 std::vector<SCH_LINE*> existingWires; // wires to test (candidates)
1154 std::vector<VECTOR2I> intersections;
1155
1156 for( SCH_ITEM* item : aScreen->Items().Overlapping( SCH_LINE_T, GetBoundingBox() ) )
1157 {
1158 SCH_LINE* line = static_cast<SCH_LINE*>( item );
1159
1160 if( line->IsWire() || line->IsBus() )
1161 existingWires.push_back( line );
1162 }
1163
1164 VECTOR2I currentLineStartPoint = GetStartPoint();
1165 VECTOR2I currentLineEndPoint = GetEndPoint();
1166
1167 for( SCH_LINE* existingLine : existingWires )
1168 {
1169 VECTOR2I extLineStartPoint = existingLine->GetStartPoint();
1170 VECTOR2I extLineEndPoint = existingLine->GetEndPoint();
1171
1172 if( extLineStartPoint == currentLineStartPoint && extLineEndPoint == currentLineEndPoint )
1173 continue;
1174
1175 if( !ShouldHopOver( existingLine ) )
1176 continue;
1177
1178 SEG currentSegment = SEG( currentLineStartPoint, currentLineEndPoint );
1179 SEG existingSegment = SEG( extLineStartPoint, extLineEndPoint );
1180
1181 if( OPT_VECTOR2I intersect = currentSegment.Intersect( existingSegment, true, false ) )
1182 {
1183 if( IsEndPoint( *intersect ) || existingLine->IsEndPoint( *intersect ) )
1184 continue;
1185
1186 // Ensure intersecting point is not yet entered. it can be already just entered
1187 // if more than two wires are intersecting at the same point,
1188 // creating bad hop over shapes for the current wire
1189 if( intersections.size() == 0 || intersections.back() != *intersect )
1190 intersections.push_back( *intersect );
1191 }
1192 }
1193
1194 if( intersections.empty() )
1195 {
1196 wire_shape.emplace_back( currentLineStartPoint.x, currentLineStartPoint.y, 0 );
1197 wire_shape.emplace_back( currentLineEndPoint.x, currentLineEndPoint.y, 0 );
1198 }
1199 else
1200 {
1201 auto getDistance =
1202 []( const VECTOR2I& a, const VECTOR2I& b ) -> double
1203 {
1204 return std::sqrt( std::pow( a.x - b.x, 2 ) + std::pow( a.y - b.y, 2 ) );
1205 };
1206
1207 std::sort( intersections.begin(), intersections.end(),
1208 [&]( const VECTOR2I& a, const VECTOR2I& b )
1209 {
1210 return getDistance( GetStartPoint(), a ) < getDistance( GetStartPoint(), b );
1211 } );
1212
1213 VECTOR2I currentStart = GetStartPoint();
1214 double R = aArcRadius;
1215
1216 for( const VECTOR2I& hopMid : intersections )
1217 {
1218 // Calculate the angle of the line from start point to end point in radians
1219 double lineAngle = std::atan2( GetEndPoint().y - GetStartPoint().y,
1220 GetEndPoint().x - GetStartPoint().x );
1221
1222 // Normalize to [0, pi) so the arc side doesn't depend
1223 // on which endpoint is start vs end
1224 double arcAngle = lineAngle;
1225
1226 if( arcAngle < 0.0 )
1227 arcAngle += M_PI;
1228 else if( arcAngle >= M_PI )
1229 arcAngle -= M_PI;
1230
1231 VECTOR2I arcMidPoint = { hopMid.x + static_cast<int>( R * std::sin( arcAngle ) ),
1232 hopMid.y - static_cast<int>( R * std::cos( arcAngle ) ) };
1233
1234 VECTOR2I beforeHop = hopMid - KiROUND( R * std::cos( lineAngle ), R * std::sin( lineAngle ) );
1235 VECTOR2I afterHop = hopMid + KiROUND( R * std::cos( lineAngle ), R * std::sin( lineAngle ) );
1236
1237 // Draw the line from the current start point to the before-hop point
1238 wire_shape.emplace_back( currentStart.x, currentStart.y, 0 );
1239 wire_shape.emplace_back( beforeHop.x, beforeHop.y, 0 );
1240
1241 // Create an arc object
1242 wire_shape.emplace_back( beforeHop.x, beforeHop.y, 1 );
1243 wire_shape.emplace_back( arcMidPoint.x, arcMidPoint.y, 1 );
1244 wire_shape.emplace_back( afterHop.x, afterHop.y, 1 );
1245
1246 currentStart = afterHop;
1247 }
1248
1249 // Draw the final line from the current start point to the end point of the original line
1250 wire_shape.emplace_back( currentStart. x,currentStart.y, 0 );
1251 wire_shape.emplace_back( GetEndPoint().x, GetEndPoint().y, 0 );
1252 }
1253
1254 return wire_shape;
1255}
1256
1257
1258static struct SCH_LINE_DESC
1259{
1261 {
1263
1264 if( lineStyleEnum.Choices().GetCount() == 0 )
1265 {
1266 lineStyleEnum.Map( LINE_STYLE::SOLID, _HKI( "Solid" ) )
1267 .Map( LINE_STYLE::DASH, _HKI( "Dashed" ) )
1268 .Map( LINE_STYLE::DOT, _HKI( "Dotted" ) )
1269 .Map( LINE_STYLE::DASHDOT, _HKI( "Dash-Dot" ) )
1270 .Map( LINE_STYLE::DASHDOTDOT, _HKI( "Dash-Dot-Dot" ) );
1271 }
1272
1274
1275 if( wireLineStyleEnum.Choices().GetCount() == 0 )
1276 {
1277 wireLineStyleEnum.Map( WIRE_STYLE::DEFAULT, _HKI( "Default" ) )
1278 .Map( WIRE_STYLE::SOLID, _HKI( "Solid" ) )
1279 .Map( WIRE_STYLE::DASH, _HKI( "Dashed" ) )
1280 .Map( WIRE_STYLE::DOT, _HKI( "Dotted" ) )
1281 .Map( WIRE_STYLE::DASHDOT, _HKI( "Dash-Dot" ) )
1282 .Map( WIRE_STYLE::DASHDOTDOT, _HKI( "Dash-Dot-Dot" ) );
1283 }
1284
1288
1289 auto isGraphicLine =
1290 []( INSPECTABLE* aItem ) -> bool
1291 {
1292 if( SCH_LINE* line = dynamic_cast<SCH_LINE*>( aItem ) )
1293 return line->IsGraphicLine();
1294
1295 return false;
1296 };
1297
1298 auto isWireOrBus =
1299 []( INSPECTABLE* aItem ) -> bool
1300 {
1301 if( SCH_LINE* line = dynamic_cast<SCH_LINE*>( aItem ) )
1302 return line->IsWire() || line->IsBus();
1303
1304 return false;
1305 };
1306
1307 propMgr.AddProperty( new PROPERTY<SCH_LINE, int>( _HKI( "Start X" ),
1310
1311 propMgr.AddProperty( new PROPERTY<SCH_LINE, int>( _HKI( "Start Y" ),
1314
1315 propMgr.AddProperty( new PROPERTY<SCH_LINE, int>( _HKI( "End X" ),
1318
1319 propMgr.AddProperty( new PROPERTY<SCH_LINE, int>( _HKI( "End Y" ),
1322
1323 propMgr.AddProperty( new PROPERTY<SCH_LINE, double>( _HKI( "Length" ),
1325
1326 propMgr.AddProperty( new PROPERTY_ENUM<SCH_LINE, LINE_STYLE>( _HKI( "Line Style" ),
1328 .SetAvailableFunc( isGraphicLine );
1329
1332 .SetAvailableFunc( isWireOrBus );
1333
1334 propMgr.AddProperty( new PROPERTY<SCH_LINE, int>( _HKI( "Line Width" ),
1336
1337 propMgr.AddProperty( new PROPERTY<SCH_LINE, COLOR4D>( _HKI( "Color" ),
1339 }
1341
types::KiCadObjectType ToProtoEnum(KICAD_T aValue)
KICAD_T FromProtoEnum(types::KiCadObjectType aValue)
Definition api_enums.cpp:47
constexpr EDA_IU_SCALE schIUScale
Definition base_units.h:123
BITMAPS
A list of all bitmap identifiers.
@ add_dashed_line
BOX2< VECTOR2I > BOX2I
Definition box2.h:918
constexpr BOX2I KiROUND(const BOX2D &aBoxD)
Definition box2.h:986
constexpr BOX2< Vec > & Inflate(coord_type dx, coord_type dy)
Inflates the rectangle horizontally by dx and vertically by dy.
Definition box2.h:554
constexpr bool Contains(const Vec &aPoint) const
Definition box2.h:164
constexpr bool Intersects(const BOX2< Vec > &aRect) const
Definition box2.h:307
static const COLOR4D UNSPECIFIED
For legacy support; used as a value to indicate color hasn't been set yet.
Definition color4d.h:398
static std::vector< DANGLING_END_ITEM >::iterator get_lower_pos(std::vector< DANGLING_END_ITEM > &aItemListByPos, const VECTOR2I &aPos)
Definition sch_item.cpp:959
Helper class used to store the state of schematic items that can be connected to other schematic item...
Definition sch_item.h:93
DANGLING_END_T GetType() const
Definition sch_item.h:129
EDA_ITEM * GetItem() const
Definition sch_item.h:127
The base class for create windows for drawing purpose.
const KIID m_Uuid
Definition eda_item.h:531
KICAD_T Type() const
Returns the type of object.
Definition eda_item.h:108
EDA_ITEM_FLAGS m_flags
Definition eda_item.h:542
EDA_GROUP * m_group
The group this item belongs to, if any. No ownership implied.
Definition eda_item.h:544
bool IsSelected() const
Definition eda_item.h:132
void SetSelected()
Definition eda_item.h:144
EDA_ITEM(EDA_ITEM *parent, KICAD_T idType, bool isSCH_ITEM=false, bool isBOARD_ITEM=false)
Definition eda_item.cpp:37
EE_TYPE Overlapping(const BOX2I &aRect) const
Definition sch_rtree.h:226
ENUM_MAP & Map(T aValue, const wxString &aName)
Definition property.h:727
static ENUM_MAP< T > & Instance()
Definition property.h:721
wxPGChoices & Choices()
Definition property.h:772
Class that other classes need to inherit from, in order to be inspectable.
Definition inspectable.h:38
A color representation with 4 components: red, green, blue, alpha.
Definition color4d.h:101
std::shared_ptr< wxString > m_text
Definition color4d.h:395
double a
Alpha component.
Definition color4d.h:392
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:44
int GetLineStyle() const
Definition netclass.h:240
int GetWireWidth() const
Definition netclass.h:210
COLOR4D GetSchematicColor(bool aIsForSave=false) const
Definition netclass.h:225
int GetBusWidth() const
Definition netclass.h:218
Base plotter engine class.
Definition plotter.h:133
void MoveTo(const VECTOR2I &pos)
Definition plotter.h:305
virtual void SetDash(int aLineWidth, LINE_STYLE aLineStyle)=0
void FinishTo(const VECTOR2I &pos)
Definition plotter.h:315
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:514
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:262
Provide class metadata.Helper macro to map type hashes to names.
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:90
Each graphical item can have a SCH_CONNECTION describing its logical connection (to a bus or net).
wxString Name(bool aIgnoreSheet=false) const
bool IsBus() const
void AppendInfoToMsgPanel(std::vector< MSG_PANEL_ITEM > &aList) const
Adds information about the connection object to aList.
Schematic editor (Eeschema) main window.
Base class for any item which can be embedded within the SCHEMATIC container class,...
Definition sch_item.h:162
SCH_ITEM * Duplicate(bool addToParentGroup, SCH_COMMIT *aCommit=nullptr, bool doClone=false) const
Routine to create a new copy of given item.
Definition sch_item.cpp:160
void SetLocked(bool aLocked) override
Definition sch_item.h:251
SCH_RENDER_SETTINGS * getRenderSettings(PLOTTER *aPlotter) const
Definition sch_item.h:724
SCHEMATIC * Schematic() const
Search the item hierarchy to find a SCHEMATIC.
Definition sch_item.cpp:268
bool IsLocked() const override
Definition sch_item.cpp:148
std::shared_ptr< NETCLASS > GetEffectiveNetClass(const SCH_SHEET_PATH *aSheet=nullptr) const
Definition sch_item.cpp:523
void SetLayer(SCH_LAYER_ID aLayer)
Definition sch_item.h:339
SCH_LAYER_ID GetLayer() const
Return the layer this item is on.
Definition sch_item.h:338
void SetConnectivityDirty(bool aDirty=true)
Definition sch_item.h:587
bool IsConnectivityDirty() const
Definition sch_item.h:585
SCH_ITEM(EDA_ITEM *aParent, KICAD_T aType, int aUnit=0, int aBodyStyle=0)
Definition sch_item.cpp:52
SCH_CONNECTION * Connection(const SCH_SHEET_PATH *aSheet=nullptr) const
Retrieve the connection associated with this object in the given sheet.
Definition sch_item.cpp:487
wxString ResolveText(const wxString &aText, const SCH_SHEET_PATH *aPath, int aDepth=0) const
Definition sch_item.cpp:377
int GetEffectivePenWidth(const SCH_RENDER_SETTINGS *aSettings) const
Definition sch_item.cpp:790
SCH_LAYER_ID m_layer
Definition sch_item.h:775
Segment description base class to describe items which have 2 end points (track, wire,...
Definition sch_line.h:38
int GetPenWidth() const override
Definition sch_line.cpp:392
void SetStartY(int aY)
Definition sch_line.h:140
bool doIsConnected(const VECTOR2I &aPosition) const override
Provide the object specific test to see if it is connected to aPosition.
Definition sch_line.cpp:909
int GetEndY() const
Definition sch_line.h:148
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:640
void SetStartPoint(const VECTOR2I &aPosition)
Definition sch_line.h:136
EDA_ITEM * Clone() const override
Create a duplicate of this item with linked list members set to NULL.
Definition sch_line.cpp:198
BITMAPS GetMenuImage() const override
Return a pointer to an image to be used in menus.
Definition sch_line.cpp:821
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:650
bool m_startIsDangling
True if start point is not connected.
Definition sch_line.h:382
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:855
void SetPosition(const VECTOR2I &aPosition) override
Definition sch_line.cpp:979
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:137
SCH_LINE * NonGroupAware_BreakAt(const VECTOR2I &aPoint)
This version should only be used when importing files.
Definition sch_line.cpp:628
std::vector< VECTOR2I > GetConnectionPoints() const override
Add all the connection points for this item to aPoints.
Definition sch_line.cpp:755
int GetReverseAngleFrom(const VECTOR2I &aPoint) const
Definition sch_line.cpp:469
SCH_LINE(const VECTOR2I &pos=VECTOR2I(0, 0), int layer=LAYER_NOTES)
Definition sch_line.cpp:48
bool IsWire() const
Return true if the line is a wire.
const BOX2I GetBoundingBox() const override
Return the orthogonal bounding box of this object for display purposes.
Definition sch_line.cpp:272
void SetWireStyle(const WIRE_STYLE aStyle)
Definition sch_line.h:182
void SetLineColor(const COLOR4D &aColor)
Definition sch_line.cpp:319
bool CanConnect(const SCH_ITEM *aItem) const override
Definition sch_line.cpp:712
bool IsParallel(const SCH_LINE *aLine) const
Definition sch_line.cpp:482
int GetStartY() const
Definition sch_line.h:139
void SetLineWidth(const int aSize)
Definition sch_line.cpp:385
bool ShouldHopOver(const SCH_LINE *aLine) const
For wires only:
void MirrorHorizontally(int aCenter) override
Mirror item horizontally about aCenter.
Definition sch_line.cpp:436
virtual STROKE_PARAMS GetStroke() const override
Definition sch_line.h:197
int GetAngleFrom(const VECTOR2I &aPoint) const
Definition sch_line.cpp:456
void GetSelectedPoints(std::vector< VECTOR2I > &aPoints) const
Definition sch_line.cpp:774
COLOR4D m_lastResolvedColor
Definition sch_line.h:394
LINE_STYLE GetEffectiveLineStyle() const
Definition sch_line.cpp:372
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.
Definition sch_line.cpp:986
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.
Definition sch_line.cpp:918
wxString m_operatingPoint
Definition sch_line.h:396
void SetLength(double aLength)
Definition sch_line.cpp:294
wxString GetClass() const override
Return the class name.
Definition sch_line.h:60
void Rotate(const VECTOR2I &aCenter, bool aRotateCCW) override
Rotate the item around aCenter 90 degrees in the clockwise direction.
Definition sch_line.cpp:446
VECTOR2I GetEndPoint() const
Definition sch_line.h:144
VECTOR2I GetStartPoint() const
Definition sch_line.h:135
bool ConnectionPropagatesTo(const EDA_ITEM *aItem) const override
Return true if this item should propagate connection info to aItem.
Definition sch_line.cpp:761
LINE_STYLE m_lastResolvedLineStyle
Definition sch_line.h:392
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:495
void SetEndY(int aY)
Definition sch_line.h:149
VECTOR2I m_start
Line start point.
Definition sch_line.h:384
bool IsBus() const
Return true if the line is a bus.
int m_lastResolvedWidth
Definition sch_line.h:393
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:736
void Serialize(google::protobuf::Any &aContainer) const override
Serializes this object to the given Any message.
Definition sch_line.cpp:104
void SetLineStyle(const LINE_STYLE aStyle)
Definition sch_line.cpp:356
VECTOR2I m_end
Line end point.
Definition sch_line.h:385
void Move(const VECTOR2I &aMoveVector) override
Move the item by aMoveVector to a new position.
Definition sch_line.cpp:204
int GetEndX() const
Definition sch_line.h:146
LINE_STYLE GetLineStyle() const
Definition sch_line.cpp:363
void MoveEnd(const VECTOR2I &aMoveVector)
Definition sch_line.cpp:217
STROKE_PARAMS m_stroke
Line stroke properties.
Definition sch_line.h:387
SCH_LINE * BreakAt(SCH_COMMIT *aCommit, const VECTOR2I &aPoint)
Break this segment into two at the specified point.
Definition sch_line.cpp:616
bool m_endIsDangling
True if end point is not connected.
Definition sch_line.h:383
bool IsConnectable() const override
Definition sch_line.cpp:703
wxString GetFriendlyName() const override
Definition sch_line.cpp:187
double ViewGetLOD(int aLayer, const KIGFX::VIEW *aView) const override
Return the level of detail (LOD) of the item.
Definition sch_line.cpp:250
void MirrorVertically(int aCenter) override
Mirror item vertically about aCenter.
Definition sch_line.cpp:426
bool operator==(const SCH_ITEM &aOther) const override
bool operator<(const SCH_ITEM &aItem) const override
Definition sch_line.cpp:832
WIRE_STYLE GetWireStyle() const
Definition sch_line.h:183
wxString GetItemDescription(UNITS_PROVIDER *aUnitsProvider, bool aFull) const override
Return a user-visible description string of this item.
Definition sch_line.cpp:784
bool IsEndPoint(const VECTOR2I &aPoint) const override
Test if aPt is an end point of this schematic object.
Definition sch_line.h:87
bool IsGraphicLine() const
Return if the line is a graphic (non electrical line)
int GetLineWidth() const
Definition sch_line.h:194
COLOR4D GetLineColor() const
Return COLOR4D::UNSPECIFIED if a custom color hasn't been set for this line.
Definition sch_line.cpp:343
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:240
void MoveStart(const VECTOR2I &aMoveVector)
Definition sch_line.cpp:211
bool Deserialize(const google::protobuf::Any &aContainer) override
Deserializes the given protobuf message into this object.
Definition sch_line.cpp:145
double GetLength() const
Definition sch_line.cpp:288
void SetEndX(int aX)
Definition sch_line.h:147
void SetEndPoint(const VECTOR2I &aPosition)
Definition sch_line.h:145
void SetStartX(int aX)
Definition sch_line.h:138
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:897
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:115
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:442
Represent a polyline containing arcs as well as line segments: A chain of connected line and/or arc s...
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 noconnect size in mils.
#define DEFAULT_WIRE_WIDTH_MILS
The default bus width in mils. (can be changed in preference menu)
#define DEFAULT_LINE_WIDTH_MILS
The default wire width in mils. (can be changed in preference menu)
#define _(s)
static constexpr EDA_ANGLE ANGLE_90
Definition eda_angle.h:413
static constexpr EDA_ANGLE ANGLE_270
Definition eda_angle.h:416
#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.
a few functions useful in geometry calculations.
@ LAYER_DANGLING
Definition layer_ids.h:475
@ LAYER_WIRE
Definition layer_ids.h:450
@ LAYER_NOTES
Definition layer_ids.h:465
@ LAYER_NET_COLOR_HIGHLIGHT
Definition layer_ids.h:491
@ LAYER_BUS
Definition layer_ids.h:451
@ LAYER_SELECTION_SHADOWS
Definition layer_ids.h:493
@ LAYER_OP_VOLTAGES
Definition layer_ids.h:499
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.
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 KIGFX::COLOR4D UnpackColor(const types::Color &aInput)
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)
EDA_ANGLE abs(const EDA_ANGLE &aAngle)
Definition eda_angle.h:400
#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)
Definition property.h:74
#define IMPLEMENT_ENUM_TO_WXANY(type)
Definition property.h:826
@ 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)
@ BUS_END
Definition sch_item.h:77
@ PIN_END
Definition sch_item.h:79
@ BUS_ENTRY_END
Definition sch_item.h:81
@ WIRE_END
Definition sch_item.h:76
static struct SCH_LINE_DESC _SCH_LINE_DESC
std::optional< VECTOR2I > OPT_VECTOR2I
Definition seg.h:35
const int scale
wxString UnescapeString(const wxString &aSource)
LINE_STYLE
Dashed line types.
WIRE_STYLE
bool m_PDFPropertyPopups
Definition sch_plotter.h:61
const SHAPE_LINE_CHAIN chain
VECTOR2I end
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:171
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:225
@ SCH_LINE_T
Definition typeinfo.h:160
@ SCH_NO_CONNECT_T
Definition typeinfo.h:157
@ SCH_SYMBOL_T
Definition typeinfo.h:169
@ SCH_DIRECTIVE_LABEL_T
Definition typeinfo.h:168
@ SCH_LABEL_T
Definition typeinfo.h:164
@ SCH_SHEET_T
Definition typeinfo.h:172
@ SCH_HIER_LABEL_T
Definition typeinfo.h:166
@ SCH_SHEET_PIN_T
Definition typeinfo.h:171
@ SCH_BUS_WIRE_ENTRY_T
Definition typeinfo.h:158
@ SCH_GLOBAL_LABEL_T
Definition typeinfo.h:165
@ SCH_JUNCTION_T
Definition typeinfo.h:156
VECTOR2< int32_t > VECTOR2I
Definition vector2d.h:683