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_render_settings.h>
22#include <sch_draw_panel.h>
23#include <macros.h>
24#include <plotters/plotter.h>
25#include <base_units.h>
26#include <widgets/msgpanel.h>
27#include <bitmaps.h>
28#include <eda_draw_frame.h>
29#include <gr_basic.h>
31#include <geometry/shape_arc.h>
34#include <schematic.h>
35#include <api/api_utils.h>
36#include <api/schematic/schematic_types.pb.h>
37#include <sch_shape.h>
38#include <properties/property.h>
40
41
42SCH_SHAPE::SCH_SHAPE( SHAPE_T aShape, SCH_LAYER_ID aLayer, int aLineWidth, FILL_T aFillType,
43 KICAD_T aType ) :
44 SCH_ITEM( nullptr, aType ),
45 EDA_SHAPE( aShape, aLineWidth, aFillType )
46{
47 SetLayer( aLayer );
48}
49
50
52{
53 return new SCH_SHAPE( *this );
54}
55
56
57void SCH_SHAPE::Serialize( google::protobuf::Any& aContainer ) const
58{
59 using namespace kiapi::common;
60
61 kiapi::schematic::types::SchematicGraphicShape msg;
62
63 msg.mutable_id()->set_value( m_Uuid.AsStdString() );
64 msg.set_locked( IsLocked() ? types::LockedState::LS_LOCKED : types::LockedState::LS_UNLOCKED );
65
66 EDA_SHAPE::Serialize( *msg.mutable_shape(), schIUScale );
67
68 kiapi::common::PackCustomProperties( msg.mutable_custom_properties(), *this );
69 aContainer.PackFrom( msg );
70}
71
72
73bool SCH_SHAPE::Deserialize( const google::protobuf::Any& aContainer )
74{
75 using namespace kiapi::common;
76
77 kiapi::schematic::types::SchematicGraphicShape msg;
78
79 if( !aContainer.UnpackTo( &msg ) )
80 return false;
81
82 const_cast<KIID&>( m_Uuid ) = KIID( msg.id().value() );
83 SetLocked( msg.locked() == types::LockedState::LS_LOCKED );
84 kiapi::common::UnpackCustomProperties( msg.custom_properties(), *this );
85
86 return EDA_SHAPE::Deserialize( msg.shape(), schIUScale );
87}
88
89
91{
92 SCH_SHAPE* shape = static_cast<SCH_SHAPE*>( aItem );
93
94 EDA_SHAPE::SwapShape( shape );
95}
96
97
98void SCH_SHAPE::SetStroke( const STROKE_PARAMS& aStroke )
99{
100 m_stroke = aStroke;
101}
102
103
104void SCH_SHAPE::SetFilled( bool aFilled )
105{
106 if( !aFilled )
108 else if( GetParentSymbol() )
110 else
112}
113
114
116{
117 if( !IsMoving() )
118 {
120 return;
121 }
122
123 SCH_SHAPE* movingShape = const_cast<SCH_SHAPE*>( this );
124 movingShape->ClearFlags( IS_MOVING );
126 movingShape->SetFlags( IS_MOVING );
127}
128
129
130void SCH_SHAPE::Move( const VECTOR2I& aOffset )
131{
132 move( aOffset );
133}
134
135
137{
139 {
140 VECTOR2I size = GetEnd() - GetPosition();
141
142 if( size.y < 0 )
143 {
144 SetStartY( GetStartY() + size.y );
145 SetEndY( GetStartY() - size.y );
146 }
147
148 if( size.x < 0 )
149 {
150 SetStartX( GetStartX() + size.x );
151 SetEndX( GetStartX() - size.x );
152 }
153 }
154}
155
156
158{
159 flip( VECTOR2I( aCenter, 0 ), FLIP_DIRECTION::LEFT_RIGHT );
160}
161
162
164{
165 flip( VECTOR2I( 0, aCenter ), FLIP_DIRECTION::TOP_BOTTOM );
166}
167
168
169void SCH_SHAPE::Rotate( const VECTOR2I& aCenter, bool aRotateCCW )
170{
171 rotate( aCenter, aRotateCCW ? ANGLE_90 : ANGLE_270 );
172}
173
174
175bool SCH_SHAPE::HitTest( const VECTOR2I& aPosition, int aAccuracy ) const
176{
177 return hitTest( aPosition, aAccuracy );
178}
179
180
181bool SCH_SHAPE::HitTest( const BOX2I& aRect, bool aContained, int aAccuracy ) const
182{
184 return false;
185
186 return hitTest( aRect, aContained, aAccuracy );
187}
188
189
190bool SCH_SHAPE::HitTest( const SHAPE_LINE_CHAIN& aPoly, bool aContained ) const
191{
193 return false;
194
195 std::vector<SHAPE*> shapes = MakeEffectiveShapes( false );
196
197 for( SHAPE* shape : shapes )
198 {
199 bool hit = KIGEOM::ShapeHitTest( aPoly, *shape, aContained );
200
201 if( hit )
202 {
203 for( SHAPE* s : shapes )
204 delete s;
205 return true;
206 }
207 }
208
209 for( SHAPE* shape : shapes )
210 delete shape;
211
212 return false;
213}
214
215
216bool SCH_SHAPE::IsEndPoint( const VECTOR2I& aPt ) const
217{
218 SHAPE_T shape = GetShape();
219
220 if( shape == SHAPE_T::ARC || shape == SHAPE_T::BEZIER || shape == SHAPE_T::SEGMENT )
221 return ( aPt == GetStart() ) || ( aPt == GetEnd() );
222
223 if( shape == SHAPE_T::RECTANGLE )
224 {
225 for( const VECTOR2I& corner : GetRectCorners() )
226 {
227 if( corner == aPt )
228 return true;
229 }
230
231 return false;
232 }
233
234 if( shape == SHAPE_T::POLY )
235 {
236 for( const VECTOR2I& pt : GetPolyPoints() )
237 {
238 if( pt == aPt )
239 return true;
240 }
241
242 return false;
243 }
244
245 return false;
246}
247
248
249void SCH_SHAPE::Plot( PLOTTER* aPlotter, bool aBackground, const SCH_PLOT_OPTS& aPlotOpts,
250 int aUnit, int aBodyStyle, const VECTOR2I& aOffset, bool aDimmed )
251{
252 if( IsPrivate() )
253 return;
254
255 // note: if aBodyStyle == -1 the outline shape is not plotted. Only the filled area
256 // is plotted (used to plot cells for SCH_TABLE items
257
258 SCH_RENDER_SETTINGS* renderSettings = getRenderSettings( aPlotter );
259 int pen_size = GetEffectivePenWidth( renderSettings );
260
261 static std::vector<VECTOR2I> ptList;
262
263 if( GetShape() == SHAPE_T::POLY )
264 {
265 ptList.clear();
266
267 if( !GetPolyShape().IsEmpty() )
268 {
269 for( const VECTOR2I& pt : GetPolyShape().Outline( 0 ).CPoints() )
270 ptList.push_back( renderSettings->TransformCoordinate( pt ) + aOffset );
271 }
272 }
273 else if( GetShape() == SHAPE_T::BEZIER )
274 {
275 ptList.clear();
276
277 for( const VECTOR2I& pt : m_bezierPoints )
278 ptList.push_back( renderSettings->TransformCoordinate( pt ) + aOffset );
279 }
281 {
282 ptList.clear();
283
285
287
288 for( int ii = 0; ii < chain.PointCount(); ++ii )
289 ptList.push_back( renderSettings->TransformCoordinate( chain.CPoint( ii ) ) + aOffset );
290 }
291
292 COLOR4D color = GetStroke().GetColor();
293 COLOR4D bg = renderSettings->GetBackgroundColor();
294 LINE_STYLE lineStyle = GetStroke().GetLineStyle();
295 FILL_T fill = m_fill;
296
297 if( aBackground )
298 {
299 switch( m_fill )
300 {
302 // Fill in the foreground layer
303 return;
304
305 case FILL_T::HATCH:
308 if( !aPlotter->GetColorMode() || color == COLOR4D::UNSPECIFIED )
309 color = renderSettings->GetLayerColor( m_layer );
310
311 color.a = color.a * 0.4;
312 break;
313
315 // drop separate fills in B&W mode
316 if( !aPlotter->GetColorMode() && pen_size > 0 )
317 return;
318
319 color = GetFillColor();
320
321 if( color == COLOR4D::UNSPECIFIED )
322 color = renderSettings->GetLayerColor( m_layer );
323
324 break;
325
327 // drop fill in B&W mode
328 if( !aPlotter->GetColorMode() )
329 return;
330
331 color = renderSettings->GetLayerColor( LAYER_DEVICE_BACKGROUND );
332 break;
333
334 default:
335 return;
336 }
337
338 pen_size = 0;
339 lineStyle = LINE_STYLE::SOLID;
340 }
341 else /* if( aForeground ) */
342 {
343 if( !aPlotter->GetColorMode() || color == COLOR4D::UNSPECIFIED )
344 color = renderSettings->GetLayerColor( m_layer );
345
346 if( lineStyle == LINE_STYLE::DEFAULT )
347 lineStyle = LINE_STYLE::SOLID;
348
350 fill = m_fill;
351 else
352 fill = FILL_T::NO_FILL;
353
354 pen_size = aBodyStyle == -1 ? 0 : GetEffectivePenWidth( renderSettings );
355 }
356
357 if( bg == COLOR4D::UNSPECIFIED || !aPlotter->GetColorMode() )
358 bg = COLOR4D::WHITE;
359
360 if( color.m_text && Schematic() )
361 color = COLOR4D( ResolveText( *color.m_text, &Schematic()->CurrentSheet() ) );
362
363 if( aDimmed )
364 {
365 color.Desaturate( );
366 color = color.Mix( bg, 0.5f );
367 }
368
369 aPlotter->SetColor( color );
370
371 if( aBackground && IsHatchedFill() )
372 {
373 for( int ii = 0; ii < GetHatching().OutlineCount(); ++ii )
374 {
375 SHAPE_LINE_CHAIN outline = GetHatching().COutline( ii );
376
377 for( int jj = 0; jj < outline.PointCount(); ++jj )
378 outline.SetPoint( jj, renderSettings->TransformCoordinate( outline.CPoint( jj ) ) + aOffset );
379
380 aPlotter->PlotPoly( outline, FILL_T::FILLED_SHAPE, 0, nullptr );
381 }
382
383 return;
384 }
385
386 aPlotter->SetCurrentLineWidth( pen_size );
387 aPlotter->SetDash( pen_size, lineStyle );
388
389 VECTOR2I start = renderSettings->TransformCoordinate( m_start ) + aOffset;
390 VECTOR2I end = renderSettings->TransformCoordinate( m_end ) + aOffset;
391 VECTOR2I mid, center;
392
393 auto transformBezierPoint =
394 [&]( const VECTOR2D& aPoint )
395 {
396 return renderSettings->TransformCoordinate( VECTOR2I( aPoint ) ) + aOffset;
397 };
398
399 std::vector<VECTOR2I> lineEndingPlotPoints = ptList;
400
401 switch( GetShape() )
402 {
403 case SHAPE_T::ARC:
404 {
405 mid = renderSettings->TransformCoordinate( GetArcMid() ) + aOffset;
406
407 // Save original endpoints before shortening.
408 VECTOR2I origArcStart = start;
409 VECTOR2I origArcEnd = end;
410
411 if( GetStartEnding().GetStyle() != LINE_ENDING_STYLE::NONE
412 || GetEndEnding().GetStyle() != LINE_ENDING_STYLE::NONE )
413 {
414 SHAPE_ARC arc( start, mid, end, 0 );
415 VECTOR2I c = arc.GetCenter();
416 EDA_ANGLE startAngle = arc.GetStartAngle();
417 EDA_ANGLE arcAngle = arc.GetCentralAngle();
418
419 // Determine arc direction from start/mid/end.
420 EDA_ANGLE origStart = startAngle;
421 if( ShortenArcForEndings( startAngle, arcAngle, arc.GetRadius(), pen_size ) )
422 {
423 RotatePoint( start, c, origStart - startAngle );
424
425 VECTOR2I newEnd = start;
426 RotatePoint( newEnd, c, -arcAngle );
427
428 VECTOR2I newMid = start;
429 RotatePoint( newMid, c, -arcAngle / 2 );
430
431 aPlotter->Arc( start, newMid, newEnd, fill, pen_size );
432 }
433 }
434 else
435 {
436 aPlotter->Arc( start, mid, end, fill, pen_size );
437 }
438
439 // Restore original endpoints for ending placement.
440 start = origArcStart;
441 end = origArcEnd;
442
443 break;
444 }
445
446 case SHAPE_T::CIRCLE:
447 center = renderSettings->TransformCoordinate( getCenter() ) + aOffset;
448 aPlotter->Circle( center, GetRadius() * 2, fill, pen_size );
449 break;
450
452 aPlotter->Rect( start, end, fill, pen_size, GetCornerRadius() );
453 break;
454
455 case SHAPE_T::SEGMENT:
456 aPlotter->ThickSegment( start, end, pen_size, nullptr );
457 break;
458
459 case SHAPE_T::POLY:
460 if( !ShortenBodyPolyPoints( ptList, IsClosed(), 0, pen_size ) )
461 break;
462
463 aPlotter->PlotPoly( ptList, fill, pen_size, nullptr );
464 break;
465
466 case SHAPE_T::BEZIER:
467 {
468 std::optional<BEZIER<double>> curve = ShortenedBezierCurve( pen_size );
469
470 if( curve && aPlotter->GetPlotterType() == PLOT_FORMAT::SVG )
471 {
472 aPlotter->BezierCurve( transformBezierPoint( curve->Start ), transformBezierPoint( curve->C1 ),
473 transformBezierPoint( curve->C2 ), transformBezierPoint( curve->End ),
474 GetMaxError(), pen_size );
475 }
476 else if( curve )
477 {
478 std::vector<VECTOR2D> pts = ShortenedBezierPolyline( pen_size );
479 std::vector<VECTOR2I> plotPts;
480
481 plotPts.reserve( pts.size() );
482
483 for( const VECTOR2D& pt : pts )
484 plotPts.push_back( transformBezierPoint( pt ) );
485
486 aPlotter->PlotPoly( plotPts, fill, pen_size, nullptr );
487 }
488
489 break;
490 }
491
492 case SHAPE_T::ELLIPSE:
493 if( !ptList.empty() )
494 ptList.push_back( ptList.front() );
495
496 aPlotter->PlotPoly( ptList, fill, pen_size, nullptr );
497 break;
498
500 aPlotter->PlotPoly( ptList, FILL_T::NO_FILL, pen_size, nullptr );
501 break;
502
503 default:
505 }
506
507 aPlotter->SetDash( pen_size, LINE_STYLE::SOLID );
508
509 // Plot line endings for open shapes.
510 if( !IsClosed()
511 && ( GetStartEnding().GetStyle() != LINE_ENDING_STYLE::NONE
512 || GetEndEnding().GetStyle() != LINE_ENDING_STYLE::NONE ) )
513 {
514 VECTOR2I startPt, endPt;
515
516 if( !GetLineEndingEndpoints( startPt, endPt ) )
517 return;
518
519 startPt = renderSettings->TransformCoordinate( startPt ) + aOffset;
520 endPt = renderSettings->TransformCoordinate( endPt ) + aOffset;
521
522 EDA_SHAPE endingShape( *this );
523
524 switch( GetShape() )
525 {
526 case SHAPE_T::ARC:
527 endingShape.SetArcGeometry( startPt, mid, endPt );
528 break;
529
530 case SHAPE_T::POLY:
531 if( lineEndingPlotPoints.size() >= 2 )
532 {
533 SHAPE_POLY_SET plotPoly;
534 plotPoly.NewOutline();
535
536 for( const VECTOR2I& pt : lineEndingPlotPoints )
537 plotPoly.Append( pt );
538
539 if( GetPolyShape().OutlineCount() > 0 )
540 plotPoly.Outline( 0 ).SetClosed( GetPolyShape().COutline( 0 ).IsClosed() );
541
542 endingShape.SetPolyShape( plotPoly );
543 }
544
545 break;
546
547 case SHAPE_T::BEZIER:
548 endingShape.SetStart( startPt );
549 endingShape.SetBezierC1( transformBezierPoint( GetBezierC1() ) );
550 endingShape.SetBezierC2( transformBezierPoint( GetBezierC2() ) );
551 endingShape.SetEnd( endPt );
553 break;
554
555 case SHAPE_T::SEGMENT:
556 endingShape.SetStart( startPt );
557 endingShape.SetEnd( endPt );
558 break;
559
560 default: break;
561 }
562
563 EDA_ANGLE startTangent;
564 EDA_ANGLE endTangent;
565
566 endingShape.GetEndingTangents( startTangent, endTangent, pen_size );
567 GetStartEnding().Plot( aPlotter, startPt, startTangent, pen_size );
568 GetEndEnding().Plot( aPlotter, endPt, endTangent, pen_size );
569 }
570}
571
572
574{
575 if( GetPenWidth() > 0 )
576 return GetPenWidth();
577
578 // Historically 0 meant "default width" and negative numbers meant "don't stroke".
579 if( GetPenWidth() < 0 )
580 return 0;
581
583
584 if( schematic )
585 return schematic->Settings().m_DefaultLineWidth;
586
587 return schIUScale.MilsToIU( DEFAULT_LINE_WIDTH_MILS );
588}
589
590
592{
593 return getBoundingBox();
594}
595
596
597void SCH_SHAPE::GetMsgPanelInfo( EDA_DRAW_FRAME* aFrame, std::vector<MSG_PANEL_ITEM>& aList )
598{
599 SCH_ITEM::GetMsgPanelInfo( aFrame, aList );
600
601 ShapeGetMsgPanelInfo( aFrame, aList );
602}
603
604
605wxString SCH_SHAPE::GetItemDescription( UNITS_PROVIDER* aUnitsProvider, bool aFull ) const
606{
607 switch( GetShape() )
608 {
609 case SHAPE_T::ARC:
610 return wxString::Format( _( "Arc, radius %s" ),
611 aUnitsProvider->MessageTextFromValue( GetRadius() ) );
612
613 case SHAPE_T::CIRCLE:
614 return wxString::Format( _( "Circle, radius %s" ),
615 aUnitsProvider->MessageTextFromValue( GetRadius() ) );
616
618 return wxString::Format( _( "Rectangle, width %s height %s" ),
619 aUnitsProvider->MessageTextFromValue( std::abs( m_start.x - m_end.x ) ),
620 aUnitsProvider->MessageTextFromValue( std::abs( m_start.y - m_end.y ) ) );
621
622 case SHAPE_T::SEGMENT:
623 return wxString::Format( _( "Line, length %s" ),
624 aUnitsProvider->MessageTextFromValue( ( m_start - m_end ).EuclideanNorm() ) );
625
626 case SHAPE_T::POLY:
627 return wxString::Format( _( "Polyline, %d points" ),
628 int( GetPolyShape().IsEmpty() ? 0 : GetPolyShape().Outline( 0 ).GetPointCount() ) );
629
630 case SHAPE_T::BEZIER:
631 return wxString::Format( _( "Bezier Curve, %d points" ),
632 int( m_bezierPoints.size() ) );
633
634 case SHAPE_T::ELLIPSE:
635 return wxString::Format( _( "Ellipse, %s x %s" ),
636 aUnitsProvider->MessageTextFromValue( GetEllipseMajorRadius() ),
637 aUnitsProvider->MessageTextFromValue( GetEllipseMinorRadius() ) );
638
640 return wxString::Format( _( "Elliptical Arc, %s x %s" ),
641 aUnitsProvider->MessageTextFromValue( GetEllipseMajorRadius() ),
642 aUnitsProvider->MessageTextFromValue( GetEllipseMinorRadius() ) );
643
644 default:
646 return wxEmptyString;
647 }
648}
649
650
669
670
671std::vector<int> SCH_SHAPE::ViewGetLayers() const
672{
673 std::vector<int> layers( 3 );
674
675 layers[0] = IsPrivate() ? LAYER_PRIVATE_NOTES : m_layer;
676
677 if( m_layer == LAYER_DEVICE )
678 {
680 layers[1] = LAYER_DEVICE_BACKGROUND;
681 else
682 layers[1] = LAYER_SHAPES_BACKGROUND;
683 }
684 else
685 {
686 layers[1] = LAYER_SHAPES_BACKGROUND;
687 }
688
689 layers[2] = LAYER_SELECTION_SHADOWS;
690
691 return layers;
692}
693
694
695void SCH_SHAPE::AddPoint( const VECTOR2I& aPosition )
696{
697 if( GetShape() == SHAPE_T::POLY )
698 {
699 if( GetPolyShape().IsEmpty() )
700 {
702 GetPolyShape().Outline( 0 ).SetClosed( false );
703 }
704
705 GetPolyShape().Outline( 0 ).Append( aPosition, true );
706 }
707 else
708 {
710 }
711}
712
713
714bool SCH_SHAPE::operator==( const SCH_ITEM& aOther ) const
715{
716 if( aOther.Type() != Type() )
717 return false;
718
719 const SCH_SHAPE& other = static_cast<const SCH_SHAPE&>( aOther );
720
721 return SCH_ITEM::operator==( aOther ) && EDA_SHAPE::operator==( other );
722}
723
724
725double SCH_SHAPE::Similarity( const SCH_ITEM& aOther ) const
726{
727 if( m_Uuid == aOther.m_Uuid )
728 return 1.0;
729
730 if( aOther.Type() != Type() )
731 return 0.0;
732
733 const SCH_SHAPE& other = static_cast<const SCH_SHAPE&>( aOther );
734
735 double similarity = SimilarityBase( other );
736
737 similarity *= EDA_SHAPE::Similarity( other );
738
739 return similarity;
740}
741
742
743int SCH_SHAPE::compare( const SCH_ITEM& aOther, int aCompareFlags ) const
744{
745 // The object UUIDs must be compared after the shape coordinates because shapes do not
746 // have immutable UUIDs.
747 int retv = SCH_ITEM::compare( aOther, aCompareFlags & ~COMPARE_FLAGS::UUID );
748
749 if( retv )
750 return retv;
751
752 retv = EDA_SHAPE::Compare( &static_cast<const SCH_SHAPE&>( aOther ) );
753
754 if( retv )
755 return retv;
756
757 if( aCompareFlags & COMPARE_FLAGS::UUID )
758 {
759 if( m_Uuid < aOther.m_Uuid )
760 return -1;
761
762 if( m_Uuid > aOther.m_Uuid )
763 return 1;
764 }
765
766 return 0;
767}
768
769
770static struct SCH_SHAPE_DESC
771{
773 {
775
776 if( fillEnum.Choices().GetCount() == 0 )
777 {
778 fillEnum.Map( FILL_T::NO_FILL, _HKI( "None" ) )
779 .Map( FILL_T::FILLED_SHAPE, _HKI( "Body outline color" ) )
780 .Map( FILL_T::FILLED_WITH_BG_BODYCOLOR, _HKI( "Body background color" ) )
781 .Map( FILL_T::FILLED_WITH_COLOR, _HKI( "Fill color" ) )
782 .Map( FILL_T::HATCH, _HKI( "Hatch" ) )
783 .Map( FILL_T::REVERSE_HATCH, _HKI( "Reverse hatch" ) )
784 .Map( FILL_T::CROSS_HATCH, _HKI( "Cross hatch" ) );
785 }
786
793
794 // Polygons and ellipses have meaningful Position properties (first vertex / center).
795 // On other shapes, Position duplicates the Start properties.
796 auto isPolygonOrEllipse =
797 []( INSPECTABLE* aItem ) -> bool
798 {
799 if( SCH_SHAPE* shape = dynamic_cast<SCH_SHAPE*>( aItem ) )
800 {
801 const SHAPE_T t = shape->GetShape();
802 return t == SHAPE_T::POLY || t == SHAPE_T::ELLIPSE || t == SHAPE_T::ELLIPSE_ARC;
803 }
804 return false;
805 };
806
807 // Hide Start/End for shapes that don't use them directly
808 // (polygon uses first vertex via Position; circle uses Center; ellipse uses Center + radii).
809 auto isNotPolygonOrCircleOrEllipse =
810 []( INSPECTABLE* aItem ) -> bool
811 {
812 if( SCH_SHAPE* shape = dynamic_cast<SCH_SHAPE*>( aItem ) )
813 {
814 const SHAPE_T t = shape->GetShape();
815 return t != SHAPE_T::POLY
816 && t != SHAPE_T::CIRCLE
817 && t != SHAPE_T::ELLIPSE
818 && t != SHAPE_T::ELLIPSE_ARC;
819 }
820 return true;
821 };
822
823 auto isSymbolItem =
824 []( INSPECTABLE* aItem ) -> bool
825 {
826 if( SCH_SHAPE* shape = dynamic_cast<SCH_SHAPE*>( aItem ) )
827 return shape->GetLayer() == LAYER_DEVICE;
828
829 return false;
830 };
831
832 auto isSchematicItem =
833 []( INSPECTABLE* aItem ) -> bool
834 {
835 if( SCH_SHAPE* shape = dynamic_cast<SCH_SHAPE*>( aItem ) )
836 return shape->GetLayer() != LAYER_DEVICE;
837
838 return false;
839 };
840
841 auto isFillColorEditable =
842 []( INSPECTABLE* aItem ) -> bool
843 {
844 if( SCH_SHAPE* shape = dynamic_cast<SCH_SHAPE*>( aItem ) )
845 {
846 if( shape->GetParentSymbol() )
847 return shape->GetFillMode() == FILL_T::FILLED_WITH_COLOR;
848 else
849 return shape->IsSolidFill();
850 }
851
852 return true;
853 };
854
855 const wxString shapeProps = _HKI( "Shape Properties" );
856
857 propMgr.AddProperty( new PROPERTY<SCH_SHAPE, int>( _HKI( "Position X" ),
860 shapeProps )
861 .SetAvailableFunc( isPolygonOrEllipse );
862
863 propMgr.AddProperty( new PROPERTY<SCH_SHAPE, int>( _HKI( "Position Y" ),
866 shapeProps )
867 .SetAvailableFunc( isPolygonOrEllipse );
868
869 propMgr.OverrideAvailability( TYPE_HASH( SCH_SHAPE ), TYPE_HASH( EDA_SHAPE ), _HKI( "Start X" ),
870 isNotPolygonOrCircleOrEllipse );
871 propMgr.OverrideAvailability( TYPE_HASH( SCH_SHAPE ), TYPE_HASH( EDA_SHAPE ), _HKI( "Start Y" ),
872 isNotPolygonOrCircleOrEllipse );
874 isNotPolygonOrCircleOrEllipse );
876 isNotPolygonOrCircleOrEllipse );
877
878 propMgr.OverrideAvailability( TYPE_HASH( SCH_SHAPE ), TYPE_HASH( EDA_SHAPE ), _HKI( "Filled" ),
879 isSchematicItem );
880
881 propMgr.OverrideWriteability( TYPE_HASH( SCH_SHAPE ), TYPE_HASH( EDA_SHAPE ), _HKI( "Fill Color" ),
882 isFillColorEditable );
883
884 void ( SCH_SHAPE::*fillModeSetter )( FILL_T ) = &SCH_SHAPE::SetFillMode;
885 FILL_T ( SCH_SHAPE::*fillModeGetter )() const = &SCH_SHAPE::GetFillMode;
886
887 propMgr.AddProperty( new PROPERTY_ENUM<SCH_SHAPE, FILL_T>( _HKI( "Fill Mode" ),
888 fillModeSetter, fillModeGetter ),
889 _HKI( "Shape Properties" ) )
890 .SetAvailableFunc( isSymbolItem );
891 }
893
constexpr EDA_IU_SCALE schIUScale
Definition base_units.h:130
BITMAPS
A list of all bitmap identifiers.
@ add_rectangle
@ add_ellipse_arc
@ add_graphical_segments
BOX2< VECTOR2I > BOX2I
Definition box2.h:914
static const COLOR4D WHITE
Definition color4d.h:403
static const COLOR4D UNSPECIFIED
For legacy support; used as a value to indicate color hasn't been set yet.
Definition color4d.h:400
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:599
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:608
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:752
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:761
const LINE_ENDING & GetStartEnding() const
Definition eda_shape.h:177
virtual void UpdateHatching() const
virtual 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:753
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:739
const LINE_ENDING & GetEndEnding() const
Definition eda_shape.h:180
FILL_T m_fill
Definition eda_shape.h:742
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:789
static ENUM_MAP< T > & Instance()
Definition property.h:783
wxPGChoices & Choices()
Definition property.h:834
Class that other classes need to inherit from, in order to be inspectable.
Definition inspectable.h:39
A color representation with 4 components: red, green, blue, alpha.
Definition color4d.h:101
std::shared_ptr< wxString > m_text
Definition color4d.h:397
double a
Alpha component.
Definition color4d.h:394
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:293
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 ThickSegment(const VECTOR2I &start, const VECTOR2I &end, int width, void *aData)
Definition plotter.cpp:441
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.
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:149
Base class for any item which can be embedded within the SCHEMATIC container class,...
Definition sch_item.h:170
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 SetLocked(bool aLocked) override
Definition sch_item.h:262
SCH_RENDER_SETTINGS * getRenderSettings(PLOTTER *aPlotter) const
Definition sch_item.cpp:46
const SYMBOL * GetParentSymbol() const
Definition sch_item.cpp:350
SCHEMATIC * Schematic() const
Search the item hierarchy to find a SCHEMATIC.
Definition sch_item.cpp:302
bool IsLocked() const override
Definition sch_item.cpp:179
virtual bool operator==(const SCH_ITEM &aOther) const
Definition sch_item.cpp:911
bool IsPrivate() const
Definition sch_item.h:259
void SetLayer(SCH_LAYER_ID aLayer)
Definition sch_item.h:354
int GetMaxError() const
Definition sch_item.cpp:990
SCH_ITEM(EDA_ITEM *aParent, KICAD_T aType, int aUnit=0, int aBodyStyle=0)
Definition sch_item.cpp:65
wxString ResolveText(const wxString &aText, const SCH_SHEET_PATH *aPath, int aDepth=0) const
Definition sch_item.cpp:464
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:935
int GetEffectivePenWidth(const SCH_RENDER_SETTINGS *aSettings) const
SCH_LAYER_ID m_layer
Definition sch_item.h:838
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:398
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:73
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:51
void SetStroke(const STROKE_PARAMS &aStroke) override
Definition sch_shape.cpp:98
void swapData(SCH_ITEM *aItem) override
Swap the internal data structures aItem with the schematic item.
Definition sch_shape.cpp:90
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:42
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:57
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 line width in mils. (can be changed in preference menu)
#define _(s)
static constexpr EDA_ANGLE ANGLE_90
Definition eda_angle.h:450
static constexpr EDA_ANGLE ANGLE_270
Definition eda_angle.h:453
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:437
#define _HKI(x)
Definition page_info.cpp:40
#define TYPE_HASH(x)
Macro to generate unique identifier for a type.
Definition property.h:74
#define ENUM_TO_WXANY(type)
Definition property.h:890
@ PT_COORD
Coordinate expressed in distance units (mm/inch)
Definition property.h:65
#define REGISTER_TYPE(x)
Helper macro to map type hashes to names.
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:227
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:708
VECTOR2< double > VECTOR2D
Definition vector2d.h:707