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