KiCad PCB EDA Suite
Loading...
Searching...
No Matches
sch_shape.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) 2017 Jean-Pierre Charras, jp.charras at wanadoo.fr
5 * Copyright The KiCad Developers, see AUTHORS.txt for contributors.
6 *
7 * This program is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU General Public License
9 * as published by the Free Software Foundation; either version 2
10 * of the License, or (at your option) any later version.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program. If not, see <https://www.gnu.org/licenses/>.
19 */
20
21#include <sch_draw_panel.h>
22#include <macros.h>
23#include <plotters/plotter.h>
24#include <base_units.h>
25#include <widgets/msgpanel.h>
26#include <bitmaps.h>
27#include <eda_draw_frame.h>
28#include <gr_basic.h>
30#include <geometry/shape_arc.h>
33#include <schematic.h>
34#include <api/api_utils.h>
35#include <api/schematic/schematic_types.pb.h>
36#include <sch_shape.h>
37#include <properties/property.h>
39
40
41SCH_SHAPE::SCH_SHAPE( SHAPE_T aShape, SCH_LAYER_ID aLayer, int aLineWidth, FILL_T aFillType,
42 KICAD_T aType ) :
43 SCH_ITEM( nullptr, aType ),
44 EDA_SHAPE( aShape, aLineWidth, aFillType )
45{
46 SetLayer( aLayer );
47}
48
49
51{
52 return new SCH_SHAPE( *this );
53}
54
55
56void SCH_SHAPE::Serialize( google::protobuf::Any& aContainer ) const
57{
58 using namespace kiapi::common;
59
60 kiapi::schematic::types::SchematicGraphicShape msg;
61
62 msg.mutable_id()->set_value( m_Uuid.AsStdString() );
63 msg.set_locked( IsLocked() ? types::LockedState::LS_LOCKED : types::LockedState::LS_UNLOCKED );
64
65 EDA_SHAPE::Serialize( *msg.mutable_shape(), schIUScale );
66
67 kiapi::common::PackCustomProperties( msg.mutable_custom_properties(), *this );
68 aContainer.PackFrom( msg );
69}
70
71
72bool SCH_SHAPE::Deserialize( const google::protobuf::Any& aContainer )
73{
74 using namespace kiapi::common;
75
76 kiapi::schematic::types::SchematicGraphicShape msg;
77
78 if( !aContainer.UnpackTo( &msg ) )
79 return false;
80
81 const_cast<KIID&>( m_Uuid ) = KIID( msg.id().value() );
82 SetLocked( msg.locked() == types::LockedState::LS_LOCKED );
83 kiapi::common::UnpackCustomProperties( msg.custom_properties(), *this );
84
85 return EDA_SHAPE::Deserialize( msg.shape(), schIUScale );
86}
87
88
90{
91 SCH_SHAPE* shape = static_cast<SCH_SHAPE*>( aItem );
92
93 EDA_SHAPE::SwapShape( shape );
94}
95
96
97void SCH_SHAPE::SetStroke( const STROKE_PARAMS& aStroke )
98{
99 m_stroke = aStroke;
100}
101
102
103void SCH_SHAPE::SetFilled( bool aFilled )
104{
105 if( !aFilled )
107 else if( GetParentSymbol() )
109 else
111}
112
113
115{
116 if( !IsMoving() )
117 {
119 return;
120 }
121
122 SCH_SHAPE* movingShape = const_cast<SCH_SHAPE*>( this );
123 movingShape->ClearFlags( IS_MOVING );
125 movingShape->SetFlags( IS_MOVING );
126}
127
128
129void SCH_SHAPE::Move( const VECTOR2I& aOffset )
130{
131 move( aOffset );
132}
133
134
136{
138 {
139 VECTOR2I size = GetEnd() - GetPosition();
140
141 if( size.y < 0 )
142 {
143 SetStartY( GetStartY() + size.y );
144 SetEndY( GetStartY() - size.y );
145 }
146
147 if( size.x < 0 )
148 {
149 SetStartX( GetStartX() + size.x );
150 SetEndX( GetStartX() - size.x );
151 }
152 }
153}
154
155
157{
158 flip( VECTOR2I( aCenter, 0 ), FLIP_DIRECTION::LEFT_RIGHT );
159}
160
161
163{
164 flip( VECTOR2I( 0, aCenter ), FLIP_DIRECTION::TOP_BOTTOM );
165}
166
167
168void SCH_SHAPE::Rotate( const VECTOR2I& aCenter, bool aRotateCCW )
169{
170 rotate( aCenter, aRotateCCW ? ANGLE_90 : ANGLE_270 );
171}
172
173
174bool SCH_SHAPE::HitTest( const VECTOR2I& aPosition, int aAccuracy ) const
175{
176 return hitTest( aPosition, aAccuracy );
177}
178
179
180bool SCH_SHAPE::HitTest( const BOX2I& aRect, bool aContained, int aAccuracy ) const
181{
183 return false;
184
185 return hitTest( aRect, aContained, aAccuracy );
186}
187
188
189bool SCH_SHAPE::HitTest( const SHAPE_LINE_CHAIN& aPoly, bool aContained ) const
190{
192 return false;
193
194 std::vector<SHAPE*> shapes = MakeEffectiveShapes( false );
195
196 for( SHAPE* shape : shapes )
197 {
198 bool hit = KIGEOM::ShapeHitTest( aPoly, *shape, aContained );
199
200 if( hit )
201 {
202 for( SHAPE* s : shapes )
203 delete s;
204 return true;
205 }
206 }
207
208 for( SHAPE* shape : shapes )
209 delete shape;
210
211 return false;
212}
213
214
215bool SCH_SHAPE::IsEndPoint( const VECTOR2I& aPt ) const
216{
217 SHAPE_T shape = GetShape();
218
219 if( shape == SHAPE_T::ARC || shape == SHAPE_T::BEZIER || shape == SHAPE_T::SEGMENT )
220 return ( aPt == GetStart() ) || ( aPt == GetEnd() );
221
222 if( shape == SHAPE_T::RECTANGLE )
223 {
224 for( const VECTOR2I& corner : GetRectCorners() )
225 {
226 if( corner == aPt )
227 return true;
228 }
229
230 return false;
231 }
232
233 if( shape == SHAPE_T::POLY )
234 {
235 for( const VECTOR2I& pt : GetPolyPoints() )
236 {
237 if( pt == aPt )
238 return true;
239 }
240
241 return false;
242 }
243
244 return false;
245}
246
247
248void SCH_SHAPE::Plot( PLOTTER* aPlotter, bool aBackground, const SCH_PLOT_OPTS& aPlotOpts,
249 int aUnit, int aBodyStyle, const VECTOR2I& aOffset, bool aDimmed )
250{
251 if( IsPrivate() )
252 return;
253
254 // note: if aBodyStyle == -1 the outline shape is not plotted. Only the filled area
255 // is plotted (used to plot cells for SCH_TABLE items
256
257 SCH_RENDER_SETTINGS* renderSettings = getRenderSettings( aPlotter );
258 int pen_size = GetEffectivePenWidth( renderSettings );
259
260 static std::vector<VECTOR2I> ptList;
261
262 if( GetShape() == SHAPE_T::POLY )
263 {
264 ptList.clear();
265
266 for( const VECTOR2I& pt : GetPolyShape().Outline( 0 ).CPoints() )
267 ptList.push_back( renderSettings->TransformCoordinate( pt ) + aOffset );
268 }
269 else if( GetShape() == SHAPE_T::BEZIER )
270 {
271 ptList.clear();
272
273 for( const VECTOR2I& pt : m_bezierPoints )
274 ptList.push_back( renderSettings->TransformCoordinate( pt ) + aOffset );
275 }
277 {
278 ptList.clear();
279
281
283
284 for( int ii = 0; ii < chain.PointCount(); ++ii )
285 ptList.push_back( renderSettings->TransformCoordinate( chain.CPoint( ii ) ) + aOffset );
286 }
287
288 COLOR4D color = GetStroke().GetColor();
289 COLOR4D bg = renderSettings->GetBackgroundColor();
290 LINE_STYLE lineStyle = GetStroke().GetLineStyle();
291 FILL_T fill = m_fill;
292
293 if( aBackground )
294 {
295 switch( m_fill )
296 {
298 // Fill in the foreground layer
299 return;
300
301 case FILL_T::HATCH:
304 if( !aPlotter->GetColorMode() || color == COLOR4D::UNSPECIFIED )
305 color = renderSettings->GetLayerColor( m_layer );
306
307 color.a = color.a * 0.4;
308 break;
309
311 // drop separate fills in B&W mode
312 if( !aPlotter->GetColorMode() && pen_size > 0 )
313 return;
314
315 color = GetFillColor();
316
317 if( color == COLOR4D::UNSPECIFIED )
318 color = renderSettings->GetLayerColor( m_layer );
319
320 break;
321
323 // drop fill in B&W mode
324 if( !aPlotter->GetColorMode() )
325 return;
326
327 color = renderSettings->GetLayerColor( LAYER_DEVICE_BACKGROUND );
328 break;
329
330 default:
331 return;
332 }
333
334 pen_size = 0;
335 lineStyle = LINE_STYLE::SOLID;
336 }
337 else /* if( aForeground ) */
338 {
339 if( !aPlotter->GetColorMode() || color == COLOR4D::UNSPECIFIED )
340 color = renderSettings->GetLayerColor( m_layer );
341
342 if( lineStyle == LINE_STYLE::DEFAULT )
343 lineStyle = LINE_STYLE::SOLID;
344
346 fill = m_fill;
347 else
348 fill = FILL_T::NO_FILL;
349
350 pen_size = aBodyStyle == -1 ? 0 : GetEffectivePenWidth( renderSettings );
351 }
352
353 if( bg == COLOR4D::UNSPECIFIED || !aPlotter->GetColorMode() )
354 bg = COLOR4D::WHITE;
355
356 if( color.m_text && Schematic() )
357 color = COLOR4D( ResolveText( *color.m_text, &Schematic()->CurrentSheet() ) );
358
359 if( aDimmed )
360 {
361 color.Desaturate( );
362 color = color.Mix( bg, 0.5f );
363 }
364
365 aPlotter->SetColor( color );
366
367 if( aBackground && IsHatchedFill() )
368 {
369 for( int ii = 0; ii < GetHatching().OutlineCount(); ++ii )
370 {
371 SHAPE_LINE_CHAIN outline = GetHatching().COutline( ii );
372
373 for( int jj = 0; jj < outline.PointCount(); ++jj )
374 outline.SetPoint( jj, renderSettings->TransformCoordinate( outline.CPoint( jj ) ) + aOffset );
375
376 aPlotter->PlotPoly( outline, FILL_T::FILLED_SHAPE, 0, nullptr );
377 }
378
379 return;
380 }
381
382 aPlotter->SetCurrentLineWidth( pen_size );
383 aPlotter->SetDash( pen_size, lineStyle );
384
385 VECTOR2I start = renderSettings->TransformCoordinate( m_start ) + aOffset;
386 VECTOR2I end = renderSettings->TransformCoordinate( m_end ) + aOffset;
387 VECTOR2I mid, center;
388
389 auto transformBezierPoint = [&]( const VECTOR2D& aPoint )
390 {
391 return renderSettings->TransformCoordinate( VECTOR2I( aPoint ) ) + aOffset;
392 };
393
394 std::vector<VECTOR2I> lineEndingPlotPoints = ptList;
395
396 switch( GetShape() )
397 {
398 case SHAPE_T::ARC:
399 {
400 mid = renderSettings->TransformCoordinate( GetArcMid() ) + aOffset;
401
402 // Save original endpoints before shortening.
403 VECTOR2I origArcStart = start;
404 VECTOR2I origArcEnd = end;
405
406 if( GetStartEnding().GetStyle() != LINE_ENDING_STYLE::NONE
407 || GetEndEnding().GetStyle() != LINE_ENDING_STYLE::NONE )
408 {
409 SHAPE_ARC arc( start, mid, end, 0 );
410 VECTOR2I c = arc.GetCenter();
411 EDA_ANGLE startAngle = arc.GetStartAngle();
412 EDA_ANGLE arcAngle = arc.GetCentralAngle();
413
414 // Determine arc direction from start/mid/end.
415 EDA_ANGLE origStart = startAngle;
416 if( ShortenArcForEndings( startAngle, arcAngle, arc.GetRadius(), pen_size ) )
417 {
418 RotatePoint( start, c, origStart - startAngle );
419
420 VECTOR2I newEnd = start;
421 RotatePoint( newEnd, c, -arcAngle );
422
423 VECTOR2I newMid = start;
424 RotatePoint( newMid, c, -arcAngle / 2 );
425
426 aPlotter->Arc( start, newMid, newEnd, fill, pen_size );
427 }
428 }
429 else
430 {
431 aPlotter->Arc( start, mid, end, fill, pen_size );
432 }
433
434 // Restore original endpoints for ending placement.
435 start = origArcStart;
436 end = origArcEnd;
437
438 break;
439 }
440
441 case SHAPE_T::CIRCLE:
442 center = renderSettings->TransformCoordinate( getCenter() ) + aOffset;
443 aPlotter->Circle( center, GetRadius() * 2, fill, pen_size );
444 break;
445
447 aPlotter->Rect( start, end, fill, pen_size, GetCornerRadius() );
448 break;
449
450 case SHAPE_T::POLY:
451 {
452 if( !ShortenBodyPolyPoints( ptList, IsClosed(), 0, pen_size ) )
453 break;
454
455 aPlotter->PlotPoly( ptList, fill, pen_size, nullptr );
456 break;
457 }
458
459 case SHAPE_T::BEZIER:
460 {
461 std::optional<BEZIER<double>> curve = ShortenedBezierCurve( pen_size );
462
463 if( curve && aPlotter->GetPlotterType() == PLOT_FORMAT::SVG )
464 {
465 aPlotter->BezierCurve( transformBezierPoint( curve->Start ), transformBezierPoint( curve->C1 ),
466 transformBezierPoint( curve->C2 ), transformBezierPoint( curve->End ), GetMaxError(),
467 pen_size );
468 }
469 else if( curve )
470 {
471 std::vector<VECTOR2D> pts = ShortenedBezierPolyline( pen_size );
472 std::vector<VECTOR2I> plotPts;
473
474 plotPts.reserve( pts.size() );
475
476 for( const VECTOR2D& pt : pts )
477 plotPts.push_back( transformBezierPoint( pt ) );
478
479 aPlotter->PlotPoly( plotPts, fill, pen_size, nullptr );
480 }
481 break;
482 }
483
484 case SHAPE_T::ELLIPSE:
485 if( !ptList.empty() )
486 ptList.push_back( ptList.front() );
487
488 aPlotter->PlotPoly( ptList, fill, pen_size, nullptr );
489 break;
490
491 case SHAPE_T::ELLIPSE_ARC: aPlotter->PlotPoly( ptList, FILL_T::NO_FILL, pen_size, nullptr ); break;
492
493 default:
495 }
496
497 aPlotter->SetDash( pen_size, LINE_STYLE::SOLID );
498
499 // Plot line endings for open shapes.
500 if( !IsClosed()
501 && ( GetStartEnding().GetStyle() != LINE_ENDING_STYLE::NONE
502 || GetEndEnding().GetStyle() != LINE_ENDING_STYLE::NONE ) )
503 {
504 VECTOR2I startPt, endPt;
505
506 if( !GetLineEndingEndpoints( startPt, endPt ) )
507 return;
508
509 startPt = renderSettings->TransformCoordinate( startPt ) + aOffset;
510 endPt = renderSettings->TransformCoordinate( endPt ) + aOffset;
511
512 EDA_SHAPE endingShape( *this );
513
514 switch( GetShape() )
515 {
516 case SHAPE_T::ARC:
517 {
518 endingShape.SetArcGeometry( startPt, mid, endPt );
519 break;
520 }
521
522 case SHAPE_T::POLY:
523 if( lineEndingPlotPoints.size() >= 2 )
524 {
525 SHAPE_POLY_SET plotPoly;
526 plotPoly.NewOutline();
527
528 for( const VECTOR2I& pt : lineEndingPlotPoints )
529 plotPoly.Append( pt );
530
531 if( GetPolyShape().OutlineCount() > 0 )
532 plotPoly.Outline( 0 ).SetClosed( GetPolyShape().COutline( 0 ).IsClosed() );
533
534 endingShape.SetPolyShape( plotPoly );
535 }
536
537 break;
538
539 case SHAPE_T::BEZIER:
540 {
541 endingShape.SetStart( startPt );
542 endingShape.SetBezierC1( transformBezierPoint( GetBezierC1() ) );
543 endingShape.SetBezierC2( transformBezierPoint( GetBezierC2() ) );
544 endingShape.SetEnd( endPt );
546 break;
547 }
548
549 case SHAPE_T::SEGMENT:
550 endingShape.SetStart( startPt );
551 endingShape.SetEnd( endPt );
552 break;
553
554 default: break;
555 }
556
557 EDA_ANGLE startTangent;
558 EDA_ANGLE endTangent;
559
560 endingShape.GetEndingTangents( startTangent, endTangent, pen_size );
561 GetStartEnding().Plot( aPlotter, startPt, startTangent, pen_size );
562 GetEndEnding().Plot( aPlotter, endPt, endTangent, pen_size );
563 }
564}
565
566
568{
569 if( GetPenWidth() > 0 )
570 return GetPenWidth();
571
572 // Historically 0 meant "default width" and negative numbers meant "don't stroke".
573 if( GetPenWidth() < 0 )
574 return 0;
575
577
578 if( schematic )
579 return schematic->Settings().m_DefaultLineWidth;
580
581 return schIUScale.MilsToIU( DEFAULT_LINE_WIDTH_MILS );
582}
583
584
586{
587 return getBoundingBox();
588}
589
590
591void SCH_SHAPE::GetMsgPanelInfo( EDA_DRAW_FRAME* aFrame, std::vector<MSG_PANEL_ITEM>& aList )
592{
593 SCH_ITEM::GetMsgPanelInfo( aFrame, aList );
594
595 ShapeGetMsgPanelInfo( aFrame, aList );
596}
597
598
599wxString SCH_SHAPE::GetItemDescription( UNITS_PROVIDER* aUnitsProvider, bool aFull ) const
600{
601 switch( GetShape() )
602 {
603 case SHAPE_T::ARC:
604 return wxString::Format( _( "Arc, radius %s" ),
605 aUnitsProvider->MessageTextFromValue( GetRadius() ) );
606
607 case SHAPE_T::CIRCLE:
608 return wxString::Format( _( "Circle, radius %s" ),
609 aUnitsProvider->MessageTextFromValue( GetRadius() ) );
610
612 return wxString::Format( _( "Rectangle, width %s height %s" ),
613 aUnitsProvider->MessageTextFromValue( std::abs( m_start.x - m_end.x ) ),
614 aUnitsProvider->MessageTextFromValue( std::abs( m_start.y - m_end.y ) ) );
615
616 case SHAPE_T::POLY:
617 return wxString::Format( _( "Polyline, %d points" ),
618 int( GetPolyShape().Outline( 0 ).GetPointCount() ) );
619
620 case SHAPE_T::BEZIER:
621 return wxString::Format( _( "Bezier Curve, %d points" ),
622 int( m_bezierPoints.size() ) );
623
624 case SHAPE_T::ELLIPSE:
625 return wxString::Format( _( "Ellipse, %s x %s" ),
626 aUnitsProvider->MessageTextFromValue( GetEllipseMajorRadius() ),
627 aUnitsProvider->MessageTextFromValue( GetEllipseMinorRadius() ) );
628
630 return wxString::Format( _( "Elliptical Arc, %s x %s" ),
631 aUnitsProvider->MessageTextFromValue( GetEllipseMajorRadius() ),
632 aUnitsProvider->MessageTextFromValue( GetEllipseMinorRadius() ) );
633
634 default:
636 return wxEmptyString;
637 }
638}
639
640
659
660
661std::vector<int> SCH_SHAPE::ViewGetLayers() const
662{
663 std::vector<int> layers( 3 );
664
665 layers[0] = IsPrivate() ? LAYER_PRIVATE_NOTES : m_layer;
666
667 if( m_layer == LAYER_DEVICE )
668 {
670 layers[1] = LAYER_DEVICE_BACKGROUND;
671 else
672 layers[1] = LAYER_SHAPES_BACKGROUND;
673 }
674 else
675 {
676 layers[1] = LAYER_SHAPES_BACKGROUND;
677 }
678
679 layers[2] = LAYER_SELECTION_SHADOWS;
680
681 return layers;
682}
683
684
685void SCH_SHAPE::AddPoint( const VECTOR2I& aPosition )
686{
687 if( GetShape() == SHAPE_T::POLY )
688 {
689 if( GetPolyShape().IsEmpty() )
690 {
692 GetPolyShape().Outline( 0 ).SetClosed( false );
693 }
694
695 GetPolyShape().Outline( 0 ).Append( aPosition, true );
696 }
697 else
698 {
700 }
701}
702
703
704bool SCH_SHAPE::operator==( const SCH_ITEM& aOther ) const
705{
706 if( aOther.Type() != Type() )
707 return false;
708
709 const SCH_SHAPE& other = static_cast<const SCH_SHAPE&>( aOther );
710
711 return SCH_ITEM::operator==( aOther ) && EDA_SHAPE::operator==( other );
712}
713
714
715double SCH_SHAPE::Similarity( const SCH_ITEM& aOther ) const
716{
717 if( m_Uuid == aOther.m_Uuid )
718 return 1.0;
719
720 if( aOther.Type() != Type() )
721 return 0.0;
722
723 const SCH_SHAPE& other = static_cast<const SCH_SHAPE&>( aOther );
724
725 double similarity = SimilarityBase( other );
726
727 similarity *= EDA_SHAPE::Similarity( other );
728
729 return similarity;
730}
731
732
733int SCH_SHAPE::compare( const SCH_ITEM& aOther, int aCompareFlags ) const
734{
735 // The object UUIDs must be compared after the shape coordinates because shapes do not
736 // have immutable UUIDs.
737 int retv = SCH_ITEM::compare( aOther, aCompareFlags & ~COMPARE_FLAGS::UUID );
738
739 if( retv )
740 return retv;
741
742 retv = EDA_SHAPE::Compare( &static_cast<const SCH_SHAPE&>( aOther ) );
743
744 if( retv )
745 return retv;
746
747 if( aCompareFlags & COMPARE_FLAGS::UUID )
748 {
749 if( m_Uuid < aOther.m_Uuid )
750 return -1;
751
752 if( m_Uuid > aOther.m_Uuid )
753 return 1;
754 }
755
756 return 0;
757}
758
759
760static struct SCH_SHAPE_DESC
761{
763 {
765
766 if( fillEnum.Choices().GetCount() == 0 )
767 {
768 fillEnum.Map( FILL_T::NO_FILL, _HKI( "None" ) )
769 .Map( FILL_T::FILLED_SHAPE, _HKI( "Body outline color" ) )
770 .Map( FILL_T::FILLED_WITH_BG_BODYCOLOR, _HKI( "Body background color" ) )
771 .Map( FILL_T::FILLED_WITH_COLOR, _HKI( "Fill color" ) )
772 .Map( FILL_T::HATCH, _HKI( "Hatch" ) )
773 .Map( FILL_T::REVERSE_HATCH, _HKI( "Reverse hatch" ) )
774 .Map( FILL_T::CROSS_HATCH, _HKI( "Cross hatch" ) );
775 }
776
783
784 // Polygons and ellipses have meaningful Position properties (first vertex / center).
785 // On other shapes, Position duplicates the Start properties.
786 auto isPolygonOrEllipse =
787 []( INSPECTABLE* aItem ) -> bool
788 {
789 if( SCH_SHAPE* shape = dynamic_cast<SCH_SHAPE*>( aItem ) )
790 {
791 const SHAPE_T t = shape->GetShape();
792 return t == SHAPE_T::POLY || t == SHAPE_T::ELLIPSE || t == SHAPE_T::ELLIPSE_ARC;
793 }
794 return false;
795 };
796
797 // Hide Start/End for shapes that don't use them directly
798 // (polygon uses first vertex via Position; circle uses Center; ellipse uses Center + radii).
799 auto isNotPolygonOrCircleOrEllipse =
800 []( INSPECTABLE* aItem ) -> bool
801 {
802 if( SCH_SHAPE* shape = dynamic_cast<SCH_SHAPE*>( aItem ) )
803 {
804 const SHAPE_T t = shape->GetShape();
805 return t != SHAPE_T::POLY
806 && t != SHAPE_T::CIRCLE
807 && t != SHAPE_T::ELLIPSE
808 && t != SHAPE_T::ELLIPSE_ARC;
809 }
810 return true;
811 };
812
813 auto isSymbolItem =
814 []( INSPECTABLE* aItem ) -> bool
815 {
816 if( SCH_SHAPE* shape = dynamic_cast<SCH_SHAPE*>( aItem ) )
817 return shape->GetLayer() == LAYER_DEVICE;
818
819 return false;
820 };
821
822 auto isSchematicItem =
823 []( INSPECTABLE* aItem ) -> bool
824 {
825 if( SCH_SHAPE* shape = dynamic_cast<SCH_SHAPE*>( aItem ) )
826 return shape->GetLayer() != LAYER_DEVICE;
827
828 return false;
829 };
830
831 auto isFillColorEditable =
832 []( INSPECTABLE* aItem ) -> bool
833 {
834 if( SCH_SHAPE* shape = dynamic_cast<SCH_SHAPE*>( aItem ) )
835 {
836 if( shape->GetParentSymbol() )
837 return shape->GetFillMode() == FILL_T::FILLED_WITH_COLOR;
838 else
839 return shape->IsSolidFill();
840 }
841
842 return true;
843 };
844
845 const wxString shapeProps = _HKI( "Shape Properties" );
846
847 propMgr.AddProperty( new PROPERTY<SCH_SHAPE, int>( _HKI( "Position X" ),
850 shapeProps )
851 .SetAvailableFunc( isPolygonOrEllipse );
852
853 propMgr.AddProperty( new PROPERTY<SCH_SHAPE, int>( _HKI( "Position Y" ),
856 shapeProps )
857 .SetAvailableFunc( isPolygonOrEllipse );
858
859 propMgr.OverrideAvailability( TYPE_HASH( SCH_SHAPE ), TYPE_HASH( EDA_SHAPE ), _HKI( "Start X" ),
860 isNotPolygonOrCircleOrEllipse );
861 propMgr.OverrideAvailability( TYPE_HASH( SCH_SHAPE ), TYPE_HASH( EDA_SHAPE ), _HKI( "Start Y" ),
862 isNotPolygonOrCircleOrEllipse );
864 isNotPolygonOrCircleOrEllipse );
866 isNotPolygonOrCircleOrEllipse );
867
868 propMgr.OverrideAvailability( TYPE_HASH( SCH_SHAPE ), TYPE_HASH( EDA_SHAPE ), _HKI( "Filled" ),
869 isSchematicItem );
870
871 propMgr.OverrideWriteability( TYPE_HASH( SCH_SHAPE ), TYPE_HASH( EDA_SHAPE ), _HKI( "Fill Color" ),
872 isFillColorEditable );
873
874 void ( SCH_SHAPE::*fillModeSetter )( FILL_T ) = &SCH_SHAPE::SetFillMode;
875 FILL_T ( SCH_SHAPE::*fillModeGetter )() const = &SCH_SHAPE::GetFillMode;
876
877 propMgr.AddProperty( new PROPERTY_ENUM<SCH_SHAPE, FILL_T>( _HKI( "Fill Mode" ),
878 fillModeSetter, fillModeGetter ),
879 _HKI( "Shape Properties" ) )
880 .SetAvailableFunc( isSymbolItem );
881 }
883
constexpr EDA_IU_SCALE schIUScale
Definition base_units.h:123
BITMAPS
A list of all bitmap identifiers.
@ add_rectangle
@ add_ellipse_arc
@ add_graphical_segments
BOX2< VECTOR2I > BOX2I
Definition box2.h:927
static const COLOR4D WHITE
Definition color4d.h:402
static const COLOR4D UNSPECIFIED
For legacy support; used as a value to indicate color hasn't been set yet.
Definition color4d.h:399
The base class for create windows for drawing purpose.
void SetFlags(EDA_ITEM_FLAGS aMask)
Definition eda_item.h:158
const KIID m_Uuid
Definition eda_item.h:597
KICAD_T Type() const
Returns the type of object.
Definition eda_item.h:110
void ClearFlags(EDA_ITEM_FLAGS aMask=EDA_ITEM_ALL_FLAGS)
Definition eda_item.h:160
EDA_ITEM_FLAGS m_flags
Definition eda_item.h:606
bool IsMoving() const
Definition eda_item.h:132
EDA_ITEM(EDA_ITEM *parent, KICAD_T idType, bool isSCH_ITEM=false, bool isBOARD_ITEM=false)
Definition eda_item.cpp:84
virtual void SetEnd(const VECTOR2I &aEnd)
Definition eda_shape.h:329
void SetStartX(int x)
Definition eda_shape.h:293
int GetEllipseMinorRadius() const
Definition eda_shape.h:395
const VECTOR2I & GetBezierC2() const
Definition eda_shape.h:368
VECTOR2I getCenter() const
int GetStartY() const
Definition eda_shape.h:276
void rotate(const VECTOR2I &aRotCentre, const EDA_ANGLE &aAngle)
const SHAPE_POLY_SET & GetHatching() const
FILL_T GetFillMode() const
Definition eda_shape.h:148
int GetEllipseMajorRadius() const
Definition eda_shape.h:386
void SetEndY(int aY)
Definition eda_shape.h:336
std::vector< VECTOR2I > GetPolyPoints() const
Duplicate the polygon outlines into a flat list of VECTOR2I points.
SHAPE_ELLIPSE buildShapeEllipse() const
void SetStartY(int y)
Definition eda_shape.h:286
SHAPE_POLY_SET & GetPolyShape()
void GetEndingTangents(EDA_ANGLE &aStartTangent, EDA_ANGLE &aEndTangent, int aLineWidth=0) const
Compute outward-facing tangent angles at the start and end of the shape.
void ShapeGetMsgPanelInfo(EDA_DRAW_FRAME *aFrame, std::vector< MSG_PANEL_ITEM > &aList)
bool operator==(const EDA_SHAPE &aOther) const
int GetRadius() const
SHAPE_T GetShape() const
Definition eda_shape.h:175
virtual void SetBezierC2(const VECTOR2I &aPt)
Definition eda_shape.h:367
bool Deserialize(const google::protobuf::Any &aContainer) override
Deserializes the given protobuf message into this object.
bool IsHatchedFill() const
Definition eda_shape.h:130
virtual void SetBezierC1(const VECTOR2I &aPt)
Definition eda_shape.h:364
bool GetLineEndingEndpoints(VECTOR2I &aStartPoint, VECTOR2I &aEndPoint) const
Return the source endpoints used to place line endings.
bool hitTest(const VECTOR2I &aPosition, int aAccuracy=0) const
void SetEndX(int aX)
Definition eda_shape.h:343
void RebuildBezierToSegmentsPointsList(int aMaxError)
Rebuild the m_bezierPoints vertex list that approximate the Bezier curve by a list of segments.
void flip(const VECTOR2I &aCentre, FLIP_DIRECTION aFlipDirection)
EDA_SHAPE(SHAPE_T aType, int aLineWidth, FILL_T aFill)
Definition eda_shape.cpp:56
VECTOR2I m_start
Definition eda_shape.h:747
int GetPointCount() const
const VECTOR2I & GetEnd() const
Return the ending point of the graphic.
Definition eda_shape.h:325
bool IsClosed() const
const VECTOR2I & GetStart() const
Return the starting point of the graphic.
Definition eda_shape.h:275
COLOR4D GetFillColor() const
Definition eda_shape.h:159
void SwapShape(EDA_SHAPE *aImage)
std::vector< VECTOR2I > GetRectCorners() const
std::vector< VECTOR2I > m_bezierPoints
Definition eda_shape.h:756
const LINE_ENDING & GetStartEnding() const
Definition eda_shape.h:177
virtual void UpdateHatching() const
void SetArcGeometry(const VECTOR2I &aStart, const VECTOR2I &aMid, const VECTOR2I &aEnd)
Set the three controlling points for an arc.
wxString SHAPE_T_asString() const
int GetStartX() const
Definition eda_shape.h:277
double Similarity(const EDA_SHAPE &aOther) const
const VECTOR2I & GetBezierC1() const
Definition eda_shape.h:365
std::optional< BEZIER< double > > ShortenedBezierCurve(int aLineWidth) const
Return the cubic Bezier curve shortened for line endings.
VECTOR2I m_end
Definition eda_shape.h:748
const BOX2I getBoundingBox() const
bool ShortenBodyPolyPoints(std::vector< VECTOR2I > &aPoints, bool aClosed, int aOutlineIdx, int aLineWidth) const
Apply line-ending body shortening to copied/generated polyline points.
bool ShortenArcForEndings(EDA_ANGLE &aStartAngle, EDA_ANGLE &aArcAngle, double aRadius, int aLineWidth) const
Shorten an arc body for line endings.
std::vector< VECTOR2D > ShortenedBezierPolyline(int aLineWidth) const
Return the flattened Bezier polyline after line-ending shortening.
STROKE_PARAMS m_stroke
Definition eda_shape.h:734
const LINE_ENDING & GetEndEnding() const
Definition eda_shape.h:180
FILL_T m_fill
Definition eda_shape.h:737
int GetCornerRadius() const
void SetFillMode(FILL_T aFill)
virtual void SetPolyShape(const SHAPE_POLY_SET &aShape)
Definition eda_shape.h:514
virtual void SetStart(const VECTOR2I &aStart)
Definition eda_shape.h:279
void Serialize(google::protobuf::Any &aContainer) const override
Serializes this object to the given Any message.
int Compare(const EDA_SHAPE *aOther) const
VECTOR2I GetArcMid() const
ENUM_MAP & Map(T aValue, const wxString &aName)
Definition property.h:776
static ENUM_MAP< T > & Instance()
Definition property.h:770
wxPGChoices & Choices()
Definition property.h:821
Class that other classes need to inherit from, in order to be inspectable.
Definition inspectable.h:39
A color representation with 4 components: red, green, blue, alpha.
Definition color4d.h:101
std::shared_ptr< wxString > m_text
Definition color4d.h:396
double a
Alpha component.
Definition color4d.h:393
COLOR4D & Desaturate()
Removes color (in HSL model)
Definition color4d.cpp:530
COLOR4D Mix(const COLOR4D &aColor, double aFactor) const
Return a color that is mixed with the input by a factor.
Definition color4d.h:292
const COLOR4D & GetLayerColor(int aLayer) const
Return the color used to draw a layer.
Definition kiid.h:46
void Plot(PLOTTER *aPlotter, const VECTOR2I &aPoint, const EDA_ANGLE &aTangent, int aLineWidth, void *aData=nullptr) const
Base plotter engine class.
Definition plotter.h:136
virtual void Circle(const VECTOR2I &pos, int diametre, FILL_T fill, int width)=0
virtual void SetDash(int aLineWidth, LINE_STYLE aLineStyle)=0
virtual PLOT_FORMAT GetPlotterType() const =0
Return the effective plot engine in use.
virtual void Rect(const VECTOR2I &p1, const VECTOR2I &p2, FILL_T fill, int width, int aCornerRadius=0)=0
virtual void BezierCurve(const VECTOR2I &aStart, const VECTOR2I &aControl1, const VECTOR2I &aControl2, const VECTOR2I &aEnd, int aTolerance, int aLineThickness)
Generic fallback: Cubic Bezier curve rendered as a polyline.
Definition plotter.cpp:230
bool GetColorMode() const
Definition plotter.h:164
virtual void SetCurrentLineWidth(int width, void *aData=nullptr)=0
Set the line width for the next drawing.
virtual void PlotPoly(const std::vector< VECTOR2I > &aCornerList, FILL_T aFill, int aWidth, void *aData)=0
Draw a polygon ( filled or not ).
virtual void SetColor(const COLOR4D &color)=0
virtual void Arc(const VECTOR2D &aStart, const VECTOR2D &aMid, const VECTOR2D &aEnd, FILL_T aFill, int aWidth)
Definition plotter.cpp:150
PROPERTY_BASE & SetAvailableFunc(std::function< bool(INSPECTABLE *)> aFunc)
Set a callback function to determine whether an object provides this property.
Definition property.h:263
Provide class metadata.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.
void OverrideAvailability(TYPE_ID aDerived, TYPE_ID aBase, const wxString &aName, std::function< bool(INSPECTABLE *)> aFunc)
Sets an override availability functor for a base class property of a given derived class.
void OverrideWriteability(TYPE_ID aDerived, TYPE_ID aBase, const wxString &aName, std::function< bool(INSPECTABLE *)> aFunc)
Sets an override writeability functor for a base class property of a given derived class.
void AddTypeCast(TYPE_CAST_BASE *aCast)
Register a type converter.
Holds all the data relating to one schematic.
Definition schematic.h:148
Base class for any item which can be embedded within the SCHEMATIC container class,...
Definition sch_item.h:165
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_item.cpp:859
void SetLocked(bool aLocked) override
Definition sch_item.h:256
SCH_RENDER_SETTINGS * getRenderSettings(PLOTTER *aPlotter) const
Definition sch_item.h:739
const SYMBOL * GetParentSymbol() const
Definition sch_item.cpp:287
SCHEMATIC * Schematic() const
Search the item hierarchy to find a SCHEMATIC.
Definition sch_item.cpp:281
bool IsLocked() const override
Definition sch_item.cpp:158
virtual bool operator==(const SCH_ITEM &aOther) const
Definition sch_item.cpp:730
bool IsPrivate() const
Definition sch_item.h:253
void SetLayer(SCH_LAYER_ID aLayer)
Definition sch_item.h:346
int GetMaxError() const
Definition sch_item.cpp:793
SCH_ITEM(EDA_ITEM *aParent, KICAD_T aType, int aUnit=0, int aBodyStyle=0)
Definition sch_item.cpp:52
wxString ResolveText(const wxString &aText, const SCH_SHEET_PATH *aPath, int aDepth=0) const
Definition sch_item.cpp:390
virtual int compare(const SCH_ITEM &aOther, int aCompareFlags=~COMPARE_FLAGS::UNIT) const
Provide the draw object specific comparison called by the == and < operators.
Definition sch_item.cpp:754
int GetEffectivePenWidth(const SCH_RENDER_SETTINGS *aSettings) const
Definition sch_item.cpp:824
SCH_LAYER_ID m_layer
Definition sch_item.h:790
double SimilarityBase(const SCH_ITEM &aItem) const
Calculate the boilerplate similarity for all LIB_ITEMs without preventing the use above of a pure vir...
Definition sch_item.h:384
VECTOR2I TransformCoordinate(const VECTOR2I &aPoint) const
const KIGFX::COLOR4D & GetBackgroundColor() const override
Return current background color settings.
void MirrorHorizontally(int aCenter) override
Mirror item horizontally about aCenter.
void SetPositionX(int aX)
Definition sch_shape.h:91
wxString GetItemDescription(UNITS_PROVIDER *aUnitsProvider, bool aFull) const override
Return a user-visible description string of this item.
bool Deserialize(const google::protobuf::Any &aContainer) override
Deserializes the given protobuf message into this object.
Definition sch_shape.cpp:72
std::vector< SHAPE * > MakeEffectiveShapes(bool aEdgeOnly=false) const override
Make a set of SHAPE objects representing the SCH_SHAPE.
Definition sch_shape.h:118
void SetFilled(bool aFilled) override
void Move(const VECTOR2I &aOffset) override
Move the item by aMoveVector to a new position.
void UpdateHatching() const override
EDA_ITEM * Clone() const override
Create a duplicate of this item with linked list members set to NULL.
Definition sch_shape.cpp:50
void SetStroke(const STROKE_PARAMS &aStroke) override
Definition sch_shape.cpp:97
void swapData(SCH_ITEM *aItem) override
Swap the internal data structures aItem with the schematic item.
Definition sch_shape.cpp:89
void Normalize()
double Similarity(const SCH_ITEM &aOther) const override
Return a measure of how likely the other object is to represent the same object.
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.
SCH_SHAPE(SHAPE_T aShape=SHAPE_T::UNDEFINED, SCH_LAYER_ID aLayer=LAYER_NOTES, int aLineWidth=0, FILL_T aFillType=FILL_T::NO_FILL, KICAD_T aType=SCH_SHAPE_T)
Definition sch_shape.cpp:41
const BOX2I GetBoundingBox() const override
Return the orthogonal bounding box of this object for display purposes.
void MirrorVertically(int aCenter) override
Mirror item vertically about aCenter.
void GetMsgPanelInfo(EDA_DRAW_FRAME *aFrame, std::vector< MSG_PANEL_ITEM > &aList) override
Populate aList of MSG_PANEL_ITEM objects with it's internal state for display purposes.
void AddPoint(const VECTOR2I &aPosition)
BITMAPS GetMenuImage() const override
Return a pointer to an image to be used in menus.
bool HitTest(const VECTOR2I &aPosition, int aAccuracy=0) const override
Test if aPosition is inside or on the boundary of this item.
void Rotate(const VECTOR2I &aCenter, bool aRotateCCW) override
Rotate the item around aCenter 90 degrees in the clockwise direction.
bool operator==(const SCH_ITEM &aOther) const override
void SetPositionY(int aY)
Definition sch_shape.h:92
std::vector< int > ViewGetLayers() const override
Return the layers the item is drawn on (which may be more than its "home" layer)
int GetPenWidth() const override
Definition sch_shape.h:54
bool IsEndPoint(const VECTOR2I &aPoint) const override
Test if aPt is an end point of this schematic object.
void Serialize(google::protobuf::Any &aContainer) const override
Serializes this object to the given Any message.
Definition sch_shape.cpp:56
STROKE_PARAMS GetStroke() const override
Definition sch_shape.h:57
int GetPositionX() const
Definition sch_shape.h:89
VECTOR2I GetPosition() const override
Definition sch_shape.h:86
int GetEffectiveWidth() const override
int compare(const SCH_ITEM &aOther, int aCompareFlags=0) const override
Provide the draw object specific comparison called by the == and < operators.
int GetPositionY() const
Definition sch_shape.h:90
int getMaxError() const override
Definition sch_shape.h:154
EDA_ANGLE GetCentralAngle() const
Get the "central angle" of the arc - this is the angle at the point of the "pie slice".
double GetRadius() const
EDA_ANGLE GetStartAngle() const
const VECTOR2I & GetCenter() const
SHAPE_LINE_CHAIN ConvertToPolyline(int aMaxError) const
Build a polyline approximation of the ellipse or arc.
Represent a polyline containing arcs as well as line segments: A chain of connected line and/or arc s...
void SetPoint(int aIndex, const VECTOR2I &aPos)
Move a point to a specific location.
void SetClosed(bool aClosed)
Mark the line chain as closed (i.e.
int PointCount() const
Return the number of points (vertices) in this line chain.
void Append(int aX, int aY, bool aAllowDuplication=false)
Append a new point at the end of the line chain.
const VECTOR2I & CPoint(int aIndex) const
Return a reference to a given point in the line chain.
Represent a set of closed polygons.
int Append(int x, int y, int aOutline=-1, int aHole=-1, bool aAllowDuplication=false)
Appends a vertex at the end of the given outline/hole (default: the last outline)
SHAPE_LINE_CHAIN & Outline(int aIndex)
Return the reference to aIndex-th outline in the set.
int NewOutline()
Creates a new empty polygon in the set and returns its index.
int OutlineCount() const
Return the number of outlines in the set.
const SHAPE_LINE_CHAIN & COutline(int aIndex) const
An abstract shape on 2D plane.
Definition shape.h:124
Simple container to manage line stroke parameters.
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_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:424
static constexpr EDA_ANGLE ANGLE_270
Definition eda_angle.h:427
FILL_T
Definition eda_fill.h:29
@ FILLED_WITH_COLOR
Definition eda_fill.h:33
@ NO_FILL
Definition eda_fill.h:30
@ REVERSE_HATCH
Definition eda_fill.h:35
@ HATCH
Definition eda_fill.h:34
@ FILLED_WITH_BG_BODYCOLOR
Definition eda_fill.h:32
@ FILLED_SHAPE
Fill with object color.
Definition eda_fill.h:31
@ CROSS_HATCH
Definition eda_fill.h:36
#define STRUCT_DELETED
flag indication structures to be erased
#define SKIP_STRUCT
flag indicating that the structure should be ignored
#define IS_MOVING
Item being moved.
SHAPE_T
Definition eda_shape.h:54
@ ELLIPSE
Definition eda_shape.h:62
@ SEGMENT
Definition eda_shape.h:56
@ RECTANGLE
Use RECTANGLE instead of RECT to avoid collision in a Windows header.
Definition eda_shape.h:57
@ ELLIPSE_ARC
Definition eda_shape.h:63
a few functions useful in geometry calculations.
SCH_LAYER_ID
Eeschema drawing layers.
Definition layer_ids.h:471
@ LAYER_SHAPES_BACKGROUND
Definition layer_ids.h:505
@ LAYER_DEVICE
Definition layer_ids.h:488
@ LAYER_PRIVATE_NOTES
Definition layer_ids.h:490
@ LAYER_DEVICE_BACKGROUND
Definition layer_ids.h:506
@ LAYER_SELECTION_SHADOWS
Definition layer_ids.h:517
This file contains miscellaneous commonly used macros and functions.
#define UNIMPLEMENTED_FOR(type)
Definition macros.h:92
@ LEFT_RIGHT
Flip left to right (around the Y axis)
Definition mirror.h:24
@ TOP_BOTTOM
Flip top to bottom (around the X axis)
Definition mirror.h:25
Message panel definition file.
bool ShapeHitTest(const SHAPE_LINE_CHAIN &aHitter, const SHAPE &aHittee, bool aHitteeContained)
Perform a shape-to-shape hit test.
KICOMMON_API void PackCustomProperties(google::protobuf::RepeatedPtrField< types::CustomProperty > *aOutput, const EDA_ITEM &aItem)
KICOMMON_API void UnpackCustomProperties(const google::protobuf::RepeatedPtrField< types::CustomProperty > &aInput, EDA_ITEM &aItem)
EDA_ANGLE abs(const EDA_ANGLE &aAngle)
Definition eda_angle.h:411
#define _HKI(x)
Definition page_info.cpp:40
#define TYPE_HASH(x)
Definition property.h:74
#define ENUM_TO_WXANY(type)
Macro to define read-only fields (no setter method available)
Definition property.h:877
@ PT_COORD
Coordinate expressed in distance units (mm/inch)
Definition property.h:65
#define REGISTER_TYPE(x)
static struct SCH_SHAPE_DESC _SCH_SHAPE_DESC
LINE_STYLE
Dashed line types.
VECTOR2I center
const SHAPE_LINE_CHAIN chain
VECTOR2I end
void RotatePoint(int *pX, int *pY, const EDA_ANGLE &aAngle)
Calculate the new point of coord coord pX, pY, for a rotation center 0, 0.
Definition trigo.cpp:225
KICAD_T
The set of class identification values stored in EDA_ITEM::m_structType.
Definition typeinfo.h:70
VECTOR2< int32_t > VECTOR2I
Definition vector2d.h:683
VECTOR2< double > VECTOR2D
Definition vector2d.h:682