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