KiCad PCB EDA Suite
Loading...
Searching...
No Matches
pcb_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) 2018 Jean-Pierre Charras, jp.charras at wanadoo.fr
5 * Copyright (C) 2012 SoftPLC Corporation, Dick Hollenbeck <[email protected]>
6 * Copyright (C) 2011 Wayne Stambaugh <[email protected]>
7 * Copyright The KiCad Developers, see AUTHORS.txt for contributors.
8 *
9 * This program is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU General Public License
11 * as published by the Free Software Foundation; either version 2
12 * of the License, or (at your option) any later version.
13 *
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
18 *
19 * You should have received a copy of the GNU General Public License
20 * along with this program. If not, see <https://www.gnu.org/licenses/>.
21 */
22
23#include "pcb_shape.h"
24
25#include <google/protobuf/any.pb.h>
26#include <magic_enum.hpp>
27
28#include <bitmaps.h>
29#include <macros.h>
30#include <pcb_edit_frame.h>
33#include <board.h>
34#include <footprint.h>
35#include <lset.h>
36#include <pad.h>
37#include <base_units.h>
38#include <trigo.h>
39#include <drc/drc_engine.h>
45#include <pcb_painter.h>
47#include <api/board/board_types.pb.h>
48#include <api/api_enums.h>
49#include <api/api_utils.h>
50#include <properties/property.h>
52
53
54// Move every vertex of the polygon through the transform. SetVertex turns the arc a vertex
55// belongs to into segments, so a uniform transform maps each arc as an arc and only a skewing
56// one is left to flatten them.
57static void transformPolyVertices( SHAPE_POLY_SET& aPoly, const TRANSFORM_TRS& aXform, bool aInverse )
58{
59 auto map = [&]( const VECTOR2I& aPt )
60 {
61 return aInverse ? aXform.InverseApply( aPt ) : aXform.Apply( aPt );
62 };
63
64 if( !aXform.IsUniformScale() )
65 {
66 for( auto it = aPoly.IterateWithHoles(); it; it++ )
67 aPoly.SetVertex( it.GetIndex(), map( *it ) );
68
69 return;
70 }
71
72 // a mirroring transform reverses the sweep of an arc
73 const bool mirrored = aXform.GetScaleX() * aXform.GetScaleY() < 0;
74
75 auto transformChain = [&]( SHAPE_LINE_CHAIN& aChain )
76 {
77 SHAPE_LINE_CHAIN mapped;
78
79 for( int i = 0; i < aChain.PointCount(); i++ )
80 {
81 int arcIndex = aChain.ArcIndex( i );
82
83 if( arcIndex < 0 )
84 {
85 mapped.Append( map( aChain.CPoint( i ) ) );
86 continue;
87 }
88
89 const SHAPE_ARC& arc = aChain.Arc( arcIndex );
91
92 // three points fix an arc exactly, except a full circle whose ends coincide
93 if( arc.GetP0() != arc.GetP1() )
94 mapped.Append( SHAPE_ARC( map( arc.GetP0() ), map( arc.GetArcMid() ), map( arc.GetP1() ), 0 ) );
95 else
96 mapped.Append( SHAPE_ARC( map( arc.GetCenter() ), map( arc.GetP0() ), mirrored ? -sweep : sweep ) );
97
98 while( i + 1 < aChain.PointCount() && aChain.ArcIndex( i + 1 ) == arcIndex )
99 i++;
100 }
101
102 mapped.SetClosed( aChain.IsClosed() );
103 aChain = mapped;
104 };
105
106 for( int i = 0; i < aPoly.OutlineCount(); i++ )
107 {
108 transformChain( aPoly.Outline( i ) );
109
110 for( int j = 0; j < aPoly.HoleCount( i ); j++ )
111 transformChain( aPoly.Hole( i, j ) );
112 }
113}
114
115
116namespace
117{
118struct BOARD_ELLIPSE
119{
120 double major;
121 double minor;
122 EDA_ANGLE rotation;
123 EDA_ANGLE startShift;
124};
125
126
127// SVD of a 2x2 matrix into ellipse major / minor / rotation and the arc angle shift.
128static BOARD_ELLIPSE decompose2x2( double m00, double m01, double m10, double m11 )
129{
130 const double A = m00 * m00 + m10 * m10;
131 const double B = m00 * m01 + m10 * m11;
132 const double C = m01 * m01 + m11 * m11;
133
134 const double diff = A - C;
135 const double rad = std::hypot( diff, 2.0 * B );
136 const double lambda1 = ( A + C + rad ) * 0.5;
137 const double lambda2 = ( A + C - rad ) * 0.5;
138
139 const double sigma1 = std::sqrt( std::max( 0.0, lambda1 ) );
140 const double sigma2 = std::sqrt( std::max( 0.0, lambda2 ) );
141
142 double v0x;
143 double v0y;
144
145 if( std::abs( B ) > 1e-12 )
146 {
147 v0x = lambda1 - C;
148 v0y = B;
149 }
150 else if( A >= C )
151 {
152 v0x = 1.0;
153 v0y = 0.0;
154 }
155 else
156 {
157 v0x = 0.0;
158 v0y = 1.0;
159 }
160
161 const double vn = std::hypot( v0x, v0y );
162 v0x /= vn;
163 v0y /= vn;
164
165 double u0x = 1.0;
166 double u0y = 0.0;
167
168 if( sigma1 > 1e-12 )
169 {
170 u0x = ( m00 * v0x + m01 * v0y ) / sigma1;
171 u0y = ( m10 * v0x + m11 * v0y ) / sigma1;
172 }
173
174 BOARD_ELLIPSE out;
175 out.major = sigma1;
176 out.minor = sigma2;
177 out.rotation = EDA_ANGLE( std::atan2( u0y, u0x ), RADIANS_T );
178 out.startShift = EDA_ANGLE( -std::atan2( v0y, v0x ), RADIANS_T );
179 return out;
180}
181
182
183// Board ellipse from a lib ellipse: M = R(theta) * diag(sx, sy) * R(phi) * diag(a, b).
184static BOARD_ELLIPSE decomposeBoardEllipse( const TRANSFORM_TRS& aXform, int aLibMajor, int aLibMinor,
185 const EDA_ANGLE& aLibRotation )
186{
187 const double sx = aXform.GetScaleX();
188 const double sy = aXform.GetScaleY();
189 // Lib rotation and xform rotation use opposite signs, negate to match.
190 const double theta = -aXform.GetRotate().AsRadians();
191 const double phi = aLibRotation.AsRadians();
192 const double cTheta = std::cos( theta );
193 const double sTheta = std::sin( theta );
194 const double cPhi = std::cos( phi );
195 const double sPhi = std::sin( phi );
196 const double a = aLibMajor;
197 const double b = aLibMinor;
198
199 const double m00 = a * ( sx * cTheta * cPhi - sy * sTheta * sPhi );
200 const double m01 = -b * ( sx * cTheta * sPhi + sy * sTheta * cPhi );
201 const double m10 = a * ( sx * sTheta * cPhi + sy * cTheta * sPhi );
202 const double m11 = b * ( -sx * sTheta * sPhi + sy * cTheta * cPhi );
203
204 return decompose2x2( m00, m01, m10, m11 );
205}
206
207
208// Inverse of decomposeBoardEllipse: lib ellipse from a board ellipse.
209static BOARD_ELLIPSE composeLibEllipse( const TRANSFORM_TRS& aXform, double aBoardMajor, double aBoardMinor,
210 const EDA_ANGLE& aBoardRotation )
211{
212 const double sx = aXform.GetScaleX();
213 const double sy = aXform.GetScaleY();
214 const double theta = -aXform.GetRotate().AsRadians();
215 const double beta = aBoardRotation.AsRadians();
216
217 const double li00 = std::cos( theta ) / sx;
218 const double li01 = std::sin( theta ) / sx;
219 const double li10 = -std::sin( theta ) / sy;
220 const double li11 = std::cos( theta ) / sy;
221
222 const double e00 = aBoardMajor * std::cos( beta );
223 const double e01 = -aBoardMinor * std::sin( beta );
224 const double e10 = aBoardMajor * std::sin( beta );
225 const double e11 = aBoardMinor * std::cos( beta );
226
227 return decompose2x2( li00 * e00 + li01 * e10, li00 * e01 + li01 * e11, li10 * e00 + li11 * e10,
228 li10 * e01 + li11 * e11 );
229}
230} // namespace
231
232
233PCB_SHAPE::PCB_SHAPE( BOARD_ITEM* aParent, KICAD_T aItemType, SHAPE_T aShapeType ) :
234 BOARD_CONNECTED_ITEM( aParent, aItemType ),
235 EDA_SHAPE( aShapeType, pcbIUScale.mmToIU( DEFAULT_LINE_WIDTH ), FILL_T::NO_FILL ),
236 m_libStart( 0, 0 ),
237 m_libEnd( 0, 0 ),
239 m_libArcMid( 0, 0 ),
240 m_libBezierC1( 0, 0 ),
241 m_libBezierC2( 0, 0 ),
242 m_libEllipseCenter( 0, 0 ),
248 m_libShape( aShapeType )
249{
250 m_hasSolderMask = false;
251}
252
253
256 EDA_SHAPE( shapetype, pcbIUScale.mmToIU( DEFAULT_LINE_WIDTH ), FILL_T::NO_FILL ),
257 m_libStart( 0, 0 ),
258 m_libEnd( 0, 0 ),
260 m_libArcMid( 0, 0 ),
261 m_libBezierC1( 0, 0 ),
262 m_libBezierC2( 0, 0 ),
263 m_libEllipseCenter( 0, 0 ),
269 m_libShape( shapetype )
270{
271 m_hasSolderMask = false;
272}
273
274
278
279
280void PCB_SHAPE::CopyFrom( const BOARD_ITEM* aOther )
281{
282 wxCHECK( aOther && aOther->Type() == PCB_SHAPE_T, /* void */ );
283 *this = *static_cast<const PCB_SHAPE*>( aOther );
284}
285
286
287void PCB_SHAPE::Serialize( google::protobuf::Any &aContainer ) const
288{
289 using namespace kiapi::common;
290 using namespace kiapi::board::types;
291 BoardGraphicShape msg;
292
294 PackNet( msg.mutable_net() );
295 msg.mutable_id()->set_value( m_Uuid.AsStdString() );
296 msg.set_locked( IsLocked() ? types::LockedState::LS_LOCKED : types::LockedState::LS_UNLOCKED );
297
298 EDA_SHAPE::Serialize( *msg.mutable_shape(), pcbIUScale );
299
300 if( IsProxyItem() )
301 {
302 PadCustomShapeOptions* options = msg.mutable_pad_custom_shape_options();
303
304 switch( GetShape() )
305 {
306 case SHAPE_T::RECTANGLE: options->set_is_number_box( true ); break;
307 case SHAPE_T::SEGMENT: options->set_is_thermal_spoke_template( true ); break;
308 default: wxFAIL_MSG( wxT( "Unexpected proxy shape type" ) ); break;
309 }
310 }
311
312 if( FOOTPRINT* parent = GetParentFootprint() )
313 msg.mutable_parent()->set_value( parent->m_Uuid.AsStdString() );
314 else if( const BOARD* board = GetBoard() )
315 msg.mutable_parent()->set_value( board->m_Uuid.AsStdString() );
316
317 if( HasSolderMask() )
318 {
319 SolderMaskOverrides* sm = msg.mutable_solder_mask();
320 sm->set_expose_copper( true );
321
322 if( GetLocalSolderMaskMargin().has_value() )
323 sm->mutable_solder_mask_margin()->set_value_nm( GetLocalSolderMaskMargin().value() );
324 }
325
326 kiapi::common::PackCustomProperties( msg.mutable_custom_properties(), *this );
327 aContainer.PackFrom( msg );
328}
329
330
331bool PCB_SHAPE::Deserialize( const google::protobuf::Any &aContainer )
332{
333 using namespace kiapi::common;
334 using namespace kiapi::board::types;
335
336 BoardGraphicShape msg;
337
338 if( !aContainer.UnpackTo( &msg ) )
339 return false;
340
341 // Initialize everything to a known state that doesn't get touched by every
342 // codepath below, to make sure the equality operator is consistent
343 m_start = {};
344 m_end = {};
345 m_arcCenter = {};
346 m_arcMidData = {};
347 m_bezierC1 = {};
348 m_bezierC2 = {};
349 m_editState = 0;
350 m_proxyItem = false;
351 m_endsSwapped = false;
352
353 SetUuidDirect( KIID( msg.id().value() ) );
354 SetLocked( msg.locked() == types::LS_LOCKED );
356 UnpackNet( msg.net() );
357 kiapi::common::UnpackCustomProperties( msg.custom_properties(), *this );
358
359 EDA_SHAPE::Deserialize( msg.shape(), pcbIUScale );
360
361 if( msg.has_pad_custom_shape_options() )
362 {
363 switch( msg.pad_custom_shape_options().role_case() )
364 {
365 case PadCustomShapeOptions::kIsNumberBox:
367 m_proxyItem = true;
368
369 break;
370
371 case PadCustomShapeOptions::kIsThermalSpokeTemplate:
372 if( GetShape() == SHAPE_T::SEGMENT )
373 m_proxyItem = true;
374
375 break;
376
377 case PadCustomShapeOptions::ROLE_NOT_SET:
378 break;
379 }
380 }
381
382 if( msg.has_solder_mask() )
383 {
384 SetHasSolderMask( msg.solder_mask().expose_copper() );
385
386 if( msg.solder_mask().has_solder_mask_margin() )
387 SetLocalSolderMaskMargin( msg.solder_mask().solder_mask_margin().value_nm() );
388 else
390 }
391 else
392 {
393 SetHasSolderMask( false );
395 }
396
397 return true;
398}
399
400
401bool PCB_SHAPE::IsType( const std::vector<KICAD_T>& aScanTypes ) const
402{
403 if( BOARD_ITEM::IsType( aScanTypes ) )
404 return true;
405
406 bool sametype = false;
407
408 for( KICAD_T scanType : aScanTypes )
409 {
410 if( scanType == PCB_LOCATE_BOARD_EDGE_T )
411 sametype = m_layer == Edge_Cuts;
412 else if( scanType == PCB_SHAPE_LOCATE_ARC_T )
413 sametype = m_shape == SHAPE_T::ARC;
414 else if( scanType == PCB_SHAPE_LOCATE_CIRCLE_T )
415 sametype = m_shape == SHAPE_T::CIRCLE;
416 else if( scanType == PCB_SHAPE_LOCATE_RECT_T )
417 sametype = m_shape == SHAPE_T::RECTANGLE;
418 else if( scanType == PCB_SHAPE_LOCATE_SEGMENT_T )
419 sametype = m_shape == SHAPE_T::SEGMENT;
420 else if( scanType == PCB_SHAPE_LOCATE_POLY_T )
421 sametype = m_shape == SHAPE_T::POLY;
422 else if( scanType == PCB_SHAPE_LOCATE_BEZIER_T )
423 sametype = m_shape == SHAPE_T::BEZIER;
424 else if( scanType == PCB_SHAPE_LOCATE_ELLIPSE_T )
425 sametype = m_shape == SHAPE_T::ELLIPSE;
426 else if( scanType == PCB_SHAPE_LOCATE_ELLIPSE_ARC_T )
427 sametype = m_shape == SHAPE_T::ELLIPSE_ARC;
428
429 if( sametype )
430 return true;
431 }
432
433 return false;
434}
435
436
438{
439 // Only board-level copper shapes are connectable
440 return IsOnCopperLayer() && !GetParentFootprint();
441}
442
443
445{
446 BOARD_ITEM::SetLayer( aLayer );
447
448 if( !IsOnCopperLayer() )
449 SetNetCode( -1 );
450}
451
452
454{
455 int margin = 0;
456
457 if( GetBoard() && GetBoard()->GetDesignSettings().m_DRCEngine
458 && GetBoard()->GetDesignSettings().m_DRCEngine->HasRulesForConstraintType( SOLDER_MASK_EXPANSION_CONSTRAINT ) )
459 {
460 DRC_CONSTRAINT constraint;
461 std::shared_ptr<DRC_ENGINE> drcEngine = GetBoard()->GetDesignSettings().m_DRCEngine;
462
463 constraint = drcEngine->EvalRules( SOLDER_MASK_EXPANSION_CONSTRAINT, this, nullptr, m_layer );
464
465 if( constraint.m_Value.HasOpt() )
466 margin = constraint.m_Value.Opt();
467 }
468 else if( m_solderMaskMargin.has_value() )
469 {
470 margin = m_solderMaskMargin.value();
471 }
472 else if( const BOARD* board = GetBoard() )
473 {
474 margin = board->GetDesignSettings().m_SolderMaskExpansion;
475 }
476
477 // Ensure the resulting mask opening has a non-negative size
478 if( margin < 0 && !IsSolidFill() )
479 margin = std::max( margin, -GetWidth() / 2 );
480
481 return margin;
482}
483
484
486{
487 if( aLayer == m_layer )
488 {
489 return true;
490 }
491
493 && ( ( aLayer == F_Mask && m_layer == F_Cu )
494 || ( aLayer == B_Mask && m_layer == B_Cu ) ) )
495 {
496 return true;
497 }
498
499 return false;
500}
501
502
504{
505 LSET layermask( { m_layer } );
506
507 if( m_hasSolderMask )
508 {
509 if( layermask.test( F_Cu ) )
510 layermask.set( F_Mask );
511
512 if( layermask.test( B_Cu ) )
513 layermask.set( B_Mask );
514 }
515
516 return layermask;
517}
518
519
520void PCB_SHAPE::SetLayerSet( const LSET& aLayerSet )
521{
522 aLayerSet.RunOnLayers(
523 [&]( PCB_LAYER_ID layer )
524 {
525 if( IsCopperLayer( layer ) )
526 SetLayer( layer );
527 else if( IsSolderMaskLayer( layer ) )
528 SetHasSolderMask( true );
529 } );
530}
531
532
533std::vector<VECTOR2I> PCB_SHAPE::GetConnectionPoints() const
534{
535 std::vector<VECTOR2I> ret;
536
537 // For filled shapes, we may as well use a centroid
538 if( IsSolidFill() )
539 {
540 ret.emplace_back( GetCenter() );
541 return ret;
542 }
543
544 switch( m_shape )
545 {
546 case SHAPE_T::CIRCLE:
547 {
548 const CIRCLE circle( GetCenter(), GetRadius() );
549
550 for( const TYPED_POINT2I& pt : KIGEOM::GetCircleKeyPoints( circle, false ) )
551 ret.emplace_back( pt.m_point );
552
553 break;
554 }
555
556 case SHAPE_T::ARC:
557 ret.emplace_back( GetArcMid() );
559 case SHAPE_T::SEGMENT:
560 case SHAPE_T::BEZIER:
561 ret.emplace_back( GetStart() );
562 ret.emplace_back( GetEnd() );
563 break;
564
565 case SHAPE_T::POLY:
566 for( auto iter = GetPolyShape().CIterate(); iter; ++iter )
567 ret.emplace_back( *iter );
568
569 break;
570
572 for( const VECTOR2I& pt : GetRectCorners() )
573 ret.emplace_back( pt );
574
575 break;
576
577 case SHAPE_T::ELLIPSE:
578 {
579 const double phi = GetEllipseRotation().AsRadians();
580 const double cosPhi = std::cos( phi );
581 const double sinPhi = std::sin( phi );
582 const int a = GetEllipseMajorRadius();
583 const int b = GetEllipseMinorRadius();
584 const VECTOR2I c = GetEllipseCenter();
585
586 ret.emplace_back( c + VECTOR2I( KiROUND( a * cosPhi ), KiROUND( a * sinPhi ) ) );
587 ret.emplace_back( c + VECTOR2I( KiROUND( -a * cosPhi ), KiROUND( -a * sinPhi ) ) );
588 ret.emplace_back( c + VECTOR2I( KiROUND( -b * sinPhi ), KiROUND( b * cosPhi ) ) );
589 ret.emplace_back( c + VECTOR2I( KiROUND( b * sinPhi ), KiROUND( -b * cosPhi ) ) );
590 break;
591 }
592
594 {
595 const double a = GetEllipseMajorRadius();
596 const double b = GetEllipseMinorRadius();
597 const double phi = GetEllipseRotation().AsRadians();
598 const double cosPhi = std::cos( phi );
599 const double sinPhi = std::sin( phi );
600 const VECTOR2I c = GetEllipseCenter();
601
602 auto eval = [&]( double theta ) -> VECTOR2I
603 {
604 const double lx = a * std::cos( theta );
605 const double ly = b * std::sin( theta );
606 return c + VECTOR2I( KiROUND( lx * cosPhi - ly * sinPhi ), KiROUND( lx * sinPhi + ly * cosPhi ) );
607 };
608
609 double thetaStart = GetEllipseStartAngle().AsRadians();
610 double thetaEnd = GetEllipseEndAngle().AsRadians();
611
612 if( thetaEnd < thetaStart )
613 thetaEnd += 2.0 * M_PI;
614
615 ret.emplace_back( eval( thetaStart ) );
616 ret.emplace_back( eval( thetaEnd ) );
617 ret.emplace_back( eval( 0.5 * ( thetaStart + thetaEnd ) ) );
618 break;
619 }
620
623 break;
624 }
625
626 return ret;
627}
628
629
631{
632 // Force update; we don't bother to propagate damage from all the things that might
633 // knock-out parts of our hatching.
634 m_hatchingDirty = true;
635
637}
638
639
641{
642 SHAPE_POLY_SET knockouts;
643
644 if( !GetBoard() )
645 return knockouts;
646
647 PCB_LAYER_ID layer = GetLayer();
648 BOX2I bbox = GetBoundingBox();
649 int maxError = ARC_LOW_DEF;
650
651 auto knockoutItem =
652 [&]( BOARD_ITEM* item )
653 {
654 int margin = GetHatchLineSpacing() / 2;
655
656 if( item->Type() == PCB_TEXTBOX_T )
657 margin = 0;
658
659 item->TransformShapeToPolygon( knockouts, layer, margin, maxError, ERROR_OUTSIDE );
660 };
661
662 for( BOARD_ITEM* item : GetBoard()->Drawings() )
663 {
664 if( item == this )
665 continue;
666
667 if( item->Type() == PCB_FIELD_T
668 || item->Type() == PCB_TEXT_T
669 || item->Type() == PCB_TEXTBOX_T
670 || item->Type() == PCB_SHAPE_T )
671 {
672 if( item->GetLayer() == layer && item->GetBoundingBox().Intersects( bbox ) )
673 knockoutItem( item );
674 }
675 }
676
677 for( FOOTPRINT* footprint : GetBoard()->Footprints() )
678 {
679 if( footprint == GetParentFootprint() )
680 continue;
681
682 // GetCourtyard() returns the front courtyard for any non-back layer, so only knock it
683 // out when the hatched shape actually lives on a courtyard layer.
684 if( layer == F_CrtYd || layer == B_CrtYd )
685 knockouts.Append( footprint->GetCourtyard( layer ) );
686
687 // Knockout footprint fields
688 footprint->RunOnChildren(
689 [&]( BOARD_ITEM* item )
690 {
691 if( ( item->Type() == PCB_FIELD_T || item->Type() == PCB_SHAPE_T )
692 && item->GetLayer() == layer
693 && !( item->Type() == PCB_FIELD_T && !static_cast<PCB_FIELD*>(item)->IsVisible() )
694 && item->GetBoundingBox().Intersects( bbox ) )
695 {
696 knockoutItem( item );
697 }
698 },
700 }
701
702 return knockouts;
703}
704
705
706static double fpScaleLinear( const FOOTPRINT* aFp )
707{
708 if( !aFp )
709 return 1.0;
710
711 const TRANSFORM_TRS& xform = aFp->GetTransform();
712 return ( xform.GetScaleX() + xform.GetScaleY() ) * 0.5;
713}
714
715
717{
718 if( GetParent() && GetParent()->Type() == PCB_PAD_T )
719 return nullptr;
720
721 return GetParentFootprint();
722}
723
724
726{
727 // Clamp negative widths to zero. They mean something in eeschema but break
728 // plotters and exporters here.
729 const int lib = std::max( EDA_SHAPE::GetWidth(), 0 );
730 const double s = fpScaleLinear( transformFp() );
731 return s == 1.0 ? lib : KiROUND( lib * s );
732}
733
734
735void PCB_SHAPE::StyleFromSettings( const BOARD_DESIGN_SETTINGS& aSettings, bool aCheckSide )
736{
737 m_stroke.SetWidth( aSettings.GetLineThickness( GetLayer() ) );
738}
739
740
742{
743 // For some shapes return the visual center, but for not filled polygonal shapes,
744 // the center is usually far from the shape: a point on the outline is better
745
746 switch( m_shape )
747 {
748 case SHAPE_T::CIRCLE:
749 if( !IsAnyFill() )
750 return VECTOR2I( GetCenter().x + GetRadius(), GetCenter().y );
751 else
752 return GetCenter();
753
755 if( !IsAnyFill() )
756 return GetStart();
757 else
758 return GetCenter();
759
760 case SHAPE_T::POLY:
761 if( !IsAnyFill() )
762 {
763 VECTOR2I pos = GetPolyShape().Outline(0).CPoint(0);
764 return VECTOR2I( pos.x, pos.y );
765 }
766 else
767 {
768 return GetCenter();
769 }
770
771 case SHAPE_T::ARC:
772 return GetArcMid();
773
774 case SHAPE_T::BEZIER:
775 return GetStart();
776
777 default:
778 return GetCenter();
779 }
780}
781
782
783std::vector<VECTOR2I> PCB_SHAPE::GetCorners() const
784{
785 std::vector<VECTOR2I> pts;
786
788 {
789 pts = GetRectCorners();
790 }
791 else if( GetShape() == SHAPE_T::POLY )
792 {
793 for( int ii = 0; ii < GetPolyShape().OutlineCount(); ++ii )
794 {
795 for( const VECTOR2I& pt : GetPolyShape().Outline( ii ).CPoints() )
796 pts.emplace_back( pt );
797 }
798 }
799 else
800 {
802 }
803
804 while( pts.size() < 4 )
805 pts.emplace_back( pts.back() + VECTOR2I( 10, 10 ) );
806
807 return pts;
808}
809
810
811void PCB_SHAPE::Move( const VECTOR2I& aMoveVector )
812{
813 move( aMoveVector );
815}
816
817
818void PCB_SHAPE::Scale( double aScale )
819{
820 scale( aScale );
821}
822
823
825{
827 {
828 VECTOR2I start = GetStart();
829 VECTOR2I end = GetEnd();
830
831 BOX2I rect( start, end - start );
832 rect.Normalize();
833
834 SetStart( rect.GetPosition() );
835 SetEnd( rect.GetEnd() );
836 }
837 else if( m_shape == SHAPE_T::POLY )
838 {
839 auto horizontal =
840 []( const SEG& seg )
841 {
842 return seg.A.y == seg.B.y;
843 };
844
845 auto vertical =
846 []( const SEG& seg )
847 {
848 return seg.A.x == seg.B.x;
849 };
850
851 // Convert a poly back to a rectangle if appropriate
852 if( GetPolyShape().OutlineCount() == 1 && GetPolyShape().Outline( 0 ).SegmentCount() == 4 )
853 {
854 SHAPE_LINE_CHAIN& outline = GetPolyShape().Outline( 0 );
855
856 if( horizontal( outline.Segment( 0 ) )
857 && vertical( outline.Segment( 1 ) )
858 && horizontal( outline.Segment( 2 ) )
859 && vertical( outline.Segment( 3 ) ) )
860 {
862 SetStart( VECTOR2I( std::min( outline.Segment( 0 ).A.x, outline.Segment( 0 ).B.x ),
863 std::min( outline.Segment( 1 ).A.y, outline.Segment( 1 ).B.y ) ) );
864 SetEnd( VECTOR2I( std::max( outline.Segment( 0 ).A.x, outline.Segment( 0 ).B.x ),
865 std::max( outline.Segment( 1 ).A.y, outline.Segment( 1 ).B.y ) ) );
866 }
867 else if( vertical( outline.Segment( 0 ) )
868 && horizontal( outline.Segment( 1 ) )
869 && vertical( outline.Segment( 2 ) )
870 && horizontal( outline.Segment( 3 ) ) )
871 {
873 SetStart( VECTOR2I( std::min( outline.Segment( 1 ).A.x, outline.Segment( 1 ).B.x ),
874 std::min( outline.Segment( 0 ).A.y, outline.Segment( 0 ).B.y ) ) );
875 SetEnd( VECTOR2I( std::max( outline.Segment( 1 ).A.x, outline.Segment( 1 ).B.x ),
876 std::max( outline.Segment( 0 ).A.y, outline.Segment( 0 ).B.y ) ) );
877 }
878 }
879 }
880}
881
882
884{
886 {
887 VECTOR2I libStart = GetLibraryStart();
888 VECTOR2I libEnd = GetLibraryEnd();
889
890 if( ( libStart.x > libEnd.x ) || ( libStart.x == libEnd.x && libStart.y < libEnd.y ) )
891 {
892 VECTOR2I s = GetStart();
893 VECTOR2I e = GetEnd();
894 SetStart( e );
895 SetEnd( s );
896 }
897 }
898 else
899 Normalize();
900}
901
902
903void PCB_SHAPE::Rotate( const VECTOR2I& aRotCentre, const EDA_ANGLE& aAngle )
904{
905 rotate( aRotCentre, aAngle );
907}
908
909
910void PCB_SHAPE::Flip( const VECTOR2I& aCentre, FLIP_DIRECTION aFlipDirection )
911{
912 const FOOTPRINT* fp = transformFp();
913
914 TRANSFORM_TRS xform;
915 bool mirrorLib = false;
916
917 if( fp )
918 {
919 xform = fp->GetTransform();
920 mirrorLib = true;
921 }
922 else if( GetParent() && GetParent()->Type() == PCB_PAD_T && m_shape != m_libShape )
923 {
924 double sx = 1.0, sy = 1.0;
925 static_cast<const PAD*>( static_cast<const BOARD_ITEM*>( GetParent() ) )->GetPrimitiveLibScale( sx, sy );
926 xform.SetScale( sx, sy );
927 mirrorLib = true;
928 }
929
930 if( mirrorLib
933 {
934 const VECTOR2I libCenter = xform.InverseApply( aCentre );
935
936 auto mirrorPt =
937 [&]( VECTOR2I& p )
938 {
939 if( aFlipDirection == FLIP_DIRECTION::LEFT_RIGHT )
940 p.x = 2 * libCenter.x - p.x;
941 else
942 p.y = 2 * libCenter.y - p.y;
943 };
944
945 if( m_libShape == SHAPE_T::ARC )
946 {
947 mirrorPt( m_libStart );
948 mirrorPt( m_libEnd );
949 mirrorPt( m_libArcMid );
950 std::swap( m_libStart, m_libEnd );
951 }
952 else
953 {
954 mirrorPt( m_libStart );
955 mirrorPt( m_libEnd );
956 }
957
959 {
960 mirrorPt( m_libBezierC1 );
961 mirrorPt( m_libBezierC2 );
962 }
963
964 // Mirror() moves the arcs of the polygon as arcs, which a vertex at a time would turn into segments
966 m_libPoly.Mirror( libCenter, aFlipDirection );
967
969 rebakeFromTransform( xform );
970 return;
971 }
972
973 if( mirrorLib && ( m_libShape == SHAPE_T::ELLIPSE || m_libShape == SHAPE_T::ELLIPSE_ARC ) )
974 {
975 const VECTOR2I libCenter = xform.InverseApply( aCentre );
976
977 if( aFlipDirection == FLIP_DIRECTION::LEFT_RIGHT )
978 m_libEllipseCenter.x = 2 * libCenter.x - m_libEllipseCenter.x;
979 else
980 m_libEllipseCenter.y = 2 * libCenter.y - m_libEllipseCenter.y;
981
983
984 const EDA_ANGLE oldStart = m_libEllipseStartAngle;
985 const EDA_ANGLE oldEnd = m_libEllipseEndAngle;
986
987 if( aFlipDirection == FLIP_DIRECTION::LEFT_RIGHT )
988 {
990 m_libEllipseEndAngle = ANGLE_180 - oldStart;
991 }
992 else
993 {
994 m_libEllipseStartAngle = -oldEnd;
995 m_libEllipseEndAngle = -oldStart;
996 }
997
999 rebakeFromTransform( xform );
1000 return;
1001 }
1002
1003 flip( aCentre, aFlipDirection );
1004
1006 syncLibCoords();
1007}
1008
1009
1010void PCB_SHAPE::SetStart( const VECTOR2I& aStart )
1011{
1012 EDA_SHAPE::SetStart( aStart );
1013 syncLibCoords();
1014}
1015
1016
1017void PCB_SHAPE::SetEnd( const VECTOR2I& aEnd )
1018{
1019 EDA_SHAPE::SetEnd( aEnd );
1020 syncLibCoords();
1021}
1022
1023
1024void PCB_SHAPE::SetCenter( const VECTOR2I& aCenter )
1025{
1026 EDA_SHAPE::SetCenter( aCenter );
1027 syncLibCoords();
1028}
1029
1030
1031void PCB_SHAPE::SetCornerRadius( int aCornerRadius )
1032{
1033 EDA_SHAPE::SetCornerRadius( aCornerRadius );
1034 syncLibCoords();
1035}
1036
1037
1038void PCB_SHAPE::OnFootprintRescaled( double aRatioX, double aRatioY, double aLinearFactor, const VECTOR2I& aAnchor,
1039 const EDA_ANGLE& aParentRotate )
1040{
1041 RebakeFromLib();
1042}
1043
1044
1045void PCB_SHAPE::SetWidth( int aWidth )
1046{
1047 const double s = fpScaleLinear( transformFp() );
1048
1049 if( s == 1.0 )
1050 m_stroke.SetWidth( aWidth );
1051 else
1052 m_stroke.SetWidth( KiROUND( aWidth / s ) );
1053
1054 m_hatchingDirty = true;
1055}
1056
1057
1059{
1060 m_stroke.SetWidth( aWidth );
1061 m_hatchingDirty = true;
1062}
1063
1064
1066{
1068 s.SetWidth( GetWidth() );
1069 return s;
1070}
1071
1072
1074{
1075 m_stroke = aStroke;
1076 SetWidth( aStroke.GetWidth() );
1077}
1078
1079
1080void PCB_SHAPE::RebakeWithScale( double aScaleX, double aScaleY )
1081{
1082 TRANSFORM_TRS xform;
1083 xform.SetScale( aScaleX, aScaleY );
1084 rebakeFromTransform( xform );
1085}
1086
1087
1089{
1090 const FOOTPRINT* fp = transformFp();
1091
1092 if( !fp )
1093 return;
1094
1096}
1097
1098
1100{
1101 const bool nonUniform = !xform.IsUniformScale();
1102
1104 {
1105 VECTOR2I libCenter = m_libStart;
1106 int libRadius = ( m_libEnd - m_libStart ).EuclideanNorm();
1107 VECTOR2I newCenter = xform.Apply( libCenter );
1108
1109 if( nonUniform )
1110 {
1111 int majorRadius = std::abs( KiROUND( libRadius * xform.GetScaleX() ) );
1112 int minorRadius = std::abs( KiROUND( libRadius * xform.GetScaleY() ) );
1113
1114 EDA_ANGLE rotation = -xform.GetRotate();
1115
1116 if( minorRadius > majorRadius )
1117 {
1118 std::swap( majorRadius, minorRadius );
1119 rotation += EDA_ANGLE( 90.0, DEGREES_T );
1120 }
1121
1123 SetEllipseCenter( newCenter );
1124 SetEllipseMajorRadius( majorRadius );
1125 SetEllipseMinorRadius( minorRadius );
1126 SetEllipseRotation( rotation );
1127 }
1128 else
1129 {
1131 EDA_SHAPE::SetStart( newCenter );
1132 EDA_SHAPE::SetEnd( xform.Apply( m_libEnd ) );
1133 }
1134
1135 return;
1136 }
1137
1138 if( m_libShape == SHAPE_T::ARC )
1139 {
1141 int libRadius = ( m_libStart - libCenter ).EuclideanNorm();
1142 VECTOR2I newCenter = xform.Apply( libCenter );
1143
1144 if( nonUniform )
1145 {
1146 int majorRadius = std::abs( KiROUND( libRadius * xform.GetScaleX() ) );
1147 int minorRadius = std::abs( KiROUND( libRadius * xform.GetScaleY() ) );
1148
1149 EDA_ANGLE rotation = -xform.GetRotate();
1150 EDA_ANGLE startAngle( VECTOR2D( m_libStart - libCenter ) );
1151 EDA_ANGLE midAngle( VECTOR2D( m_libArcMid - libCenter ) );
1152 EDA_ANGLE endAngle( VECTOR2D( m_libEnd - libCenter ) );
1153
1154 auto wrap = []( EDA_ANGLE a, EDA_ANGLE base )
1155 {
1156 while( a < base )
1157 a += ANGLE_360;
1158 return a;
1159 };
1160
1161 if( wrap( midAngle, startAngle ) > wrap( endAngle, startAngle ) )
1162 std::swap( startAngle, endAngle );
1163
1164 while( endAngle < startAngle )
1165 endAngle += ANGLE_360;
1166
1167 if( minorRadius > majorRadius )
1168 {
1169 std::swap( majorRadius, minorRadius );
1170 rotation += EDA_ANGLE( 90.0, DEGREES_T );
1171 startAngle -= EDA_ANGLE( 90.0, DEGREES_T );
1172 endAngle -= EDA_ANGLE( 90.0, DEGREES_T );
1173 }
1174
1176 SetEllipseCenter( newCenter );
1177 SetEllipseMajorRadius( majorRadius );
1178 SetEllipseMinorRadius( minorRadius );
1179 SetEllipseRotation( rotation );
1180 SetEllipseStartAngle( startAngle );
1181 SetEllipseEndAngle( endAngle );
1182 }
1183 else
1184 {
1187 }
1188
1189 return;
1190 }
1191
1193 {
1194 // The linear transform preserves ellipse-ness only when scale is uniform
1195 // or the lib ellipse's axes are aligned with the scale axes (cardinal lib
1196 // rotation). Otherwise the result is a sheared shape that no standard
1197 // ellipse can represent; tessellate to POLY in that case.
1198 const bool keepNative = xform.IsUniformScale() || m_libEllipseRotation.IsCardinal();
1199
1200 if( keepNative )
1201 {
1204
1205 if( xform.IsUniformScale() )
1206 {
1207 double absScale = std::abs( xform.GetScaleX() );
1211
1213 {
1216 }
1217 }
1218 else
1219 {
1220 BOARD_ELLIPSE be = decomposeBoardEllipse( xform, m_libEllipseMajorRadius,
1223
1226 EDA_SHAPE::SetEllipseRotation( be.rotation );
1227
1229 {
1232 }
1233 }
1234 }
1235 else
1236 {
1237 const bool isArc = ( m_libShape == SHAPE_T::ELLIPSE_ARC );
1238
1239 std::unique_ptr<SHAPE_ELLIPSE> libEllipse;
1240
1241 if( isArc )
1242 {
1243 libEllipse = std::make_unique<SHAPE_ELLIPSE>( m_libEllipseCenter, m_libEllipseMajorRadius,
1246 }
1247 else
1248 {
1249 libEllipse = std::make_unique<SHAPE_ELLIPSE>( m_libEllipseCenter, m_libEllipseMajorRadius,
1251 }
1252
1253 SHAPE_LINE_CHAIN chain = libEllipse->ConvertToPolyline( getMaxError() );
1254
1256 SHAPE_POLY_SET& poly = GetPolyShape();
1257 poly.RemoveAllContours();
1258 poly.NewOutline();
1259
1260 for( int ii = 0; ii < chain.PointCount(); ++ii )
1261 poly.Append( xform.Apply( chain.CPoint( ii ) ) );
1262
1263 poly.Outline( 0 ).SetClosed( !isArc );
1264 }
1265
1266 return;
1267 }
1268
1270 {
1271 const VECTOR2I c1 = xform.Apply( m_libStart );
1272 const VECTOR2I c2 = xform.Apply( VECTOR2I( m_libEnd.x, m_libStart.y ) );
1273 const VECTOR2I c3 = xform.Apply( m_libEnd );
1274 const VECTOR2I c4 = xform.Apply( VECTOR2I( m_libStart.x, m_libEnd.y ) );
1275
1276 if( xform.GetRotate().IsCardinal()
1277 && ( m_libCornerRadius == 0 || xform.IsUniformScale() ) )
1278 {
1280 BOX2I bbox( c1, VECTOR2I( 0, 0 ) );
1281 bbox.Merge( c2 );
1282 bbox.Merge( c3 );
1283 bbox.Merge( c4 );
1285 EDA_SHAPE::SetEnd( bbox.GetEnd() );
1286
1288 }
1289 else
1290 {
1292 SHAPE_POLY_SET& poly = GetPolyShape();
1293 poly.RemoveAllContours();
1294
1295 if( m_libCornerRadius > 0 )
1296 {
1297 SHAPE_POLY_SET rounded;
1298 VECTOR2I libCenter = ( m_libStart + m_libEnd ) / 2;
1299 VECTOR2I libSize( std::abs( m_libEnd.x - m_libStart.x ), std::abs( m_libEnd.y - m_libStart.y ) );
1300
1301 TransformRoundChamferedRectToPolygon( rounded, libCenter, libSize, ANGLE_0, m_libCornerRadius, 0.0,
1302 0, 0, getMaxError(), ERROR_INSIDE );
1303
1304 poly.NewOutline();
1305
1306 for( int ii = 0; ii < rounded.Outline( 0 ).PointCount(); ++ii )
1307 poly.Append( xform.Apply( rounded.Outline( 0 ).CPoint( ii ) ) );
1308 }
1309 else
1310 {
1311 poly.NewOutline();
1312 poly.Append( c1 );
1313 poly.Append( c2 );
1314 poly.Append( c3 );
1315 poly.Append( c4 );
1316 }
1317
1318 EDA_SHAPE::SetStart( c1 );
1319 EDA_SHAPE::SetEnd( c3 );
1320 }
1321
1322 return;
1323 }
1324
1325 if( m_libShape == SHAPE_T::POLY )
1326 {
1327 SHAPE_POLY_SET& poly = GetPolyShape();
1328 poly = m_libPoly;
1329
1330 transformPolyVertices( poly, xform, false );
1331
1332 // m_libStart/m_libEnd are not seeded for POLY, skip the start/end fall-through below.
1333 return;
1334 }
1335
1337 EDA_SHAPE::SetEnd( xform.Apply( m_libEnd ) );
1338
1340 {
1344 }
1345}
1346
1347
1349{
1350 if( m_libShape == SHAPE_T::ARC )
1351 return m_libArcMid;
1352
1353 if( const FOOTPRINT* fp = transformFp() )
1354 return fp->GetTransform().InverseApply( GetArcMid() );
1355
1356 return GetArcMid();
1357}
1358
1359
1361{
1362 if( GetParent() && GetParent()->Type() == PCB_PAD_T )
1363 return m_libBezierC1;
1364
1365 if( const FOOTPRINT* fp = transformFp() )
1366 return fp->GetTransform().InverseApply( GetBezierC1() );
1367
1368 return GetBezierC1();
1369}
1370
1371
1373{
1374 if( GetParent() && GetParent()->Type() == PCB_PAD_T )
1375 return m_libBezierC2;
1376
1377 if( const FOOTPRINT* fp = transformFp() )
1378 return fp->GetTransform().InverseApply( GetBezierC2() );
1379
1380 return GetBezierC2();
1381}
1382
1383
1385{
1386 if( GetParent() && GetParent()->Type() == PCB_PAD_T )
1387 return m_libPoly;
1388
1390
1391 if( const FOOTPRINT* fp = transformFp() )
1392 {
1393 const TRANSFORM_TRS& xform = fp->GetTransform();
1394
1395 transformPolyVertices( poly, xform, true );
1396 }
1397
1398 return poly;
1399}
1400
1401
1402void PCB_SHAPE::SetArcGeometry( const VECTOR2I& aStart, const VECTOR2I& aMid, const VECTOR2I& aEnd )
1403{
1404 EDA_SHAPE::SetArcGeometry( aStart, aMid, aEnd );
1405 syncLibCoords();
1406}
1407
1408
1410{
1412 syncLibCoords();
1413}
1414
1415
1417{
1419 syncLibCoords();
1420}
1421
1422
1424{
1425 EDA_SHAPE::SetPolyShape( aShape );
1426 syncLibCoords();
1427}
1428
1429
1431{
1433 syncLibCoords();
1434}
1435
1436
1442
1443
1449
1450
1456
1457
1463
1464
1470
1471
1473{
1474 TRANSFORM_TRS xform;
1475 bool hasXform = false;
1476
1477 if( GetParent() && GetParent()->Type() == PCB_PAD_T )
1478 {
1479 double sx = 1.0, sy = 1.0;
1480 static_cast<const PAD*>( static_cast<const BOARD_ITEM*>( GetParent() ) )->GetPrimitiveLibScale( sx, sy );
1481 xform.SetScale( sx, sy );
1482 hasXform = ( sx != 1.0 || sy != 1.0 );
1483 }
1484 else if( const FOOTPRINT* fp = transformFp() )
1485 {
1486 xform = fp->GetTransform();
1487 hasXform = true;
1488 }
1489
1491 {
1492 if( hasXform )
1493 {
1495
1496 if( xform.IsUniformScale() )
1497 {
1498 double invScale = 1.0 / std::abs( xform.GetScaleX() );
1504 }
1505 else
1506 {
1507 // Non-uniform scale shears the ellipse, so invert the whole board ellipse to lib.
1508 BOARD_ELLIPSE le = composeLibEllipse( xform, GetEllipseMajorRadius(), GetEllipseMinorRadius(),
1510 m_libEllipseMajorRadius = KiROUND( le.major );
1511 m_libEllipseMinorRadius = KiROUND( le.minor );
1512 m_libEllipseRotation = le.rotation;
1513 m_libEllipseStartAngle = GetEllipseStartAngle() + le.startShift;
1514 m_libEllipseEndAngle = GetEllipseEndAngle() + le.startShift;
1515 }
1516 }
1517 else
1518 {
1525 }
1526
1527 return;
1528 }
1529
1530 if( m_shape == SHAPE_T::POLY )
1531 {
1533
1534 if( hasXform )
1535 transformPolyVertices( m_libPoly, xform, true );
1536
1537 return;
1538 }
1539
1540 if( hasXform )
1541 {
1542 m_libStart = xform.InverseApply( GetStart() );
1543 m_libEnd = xform.InverseApply( GetEnd() );
1544
1546 {
1547 // We assume xform is uniform scale. If not, we should have been turned into a
1548 // polygon.
1550 }
1551
1552 if( m_shape == SHAPE_T::ARC )
1553 m_libArcMid = xform.InverseApply( GetArcMid() );
1554
1555 if( m_shape == SHAPE_T::BEZIER )
1556 {
1559 }
1560 }
1561 else
1562 {
1563 m_libStart = GetStart();
1564 m_libEnd = GetEnd();
1565
1568
1569 if( m_shape == SHAPE_T::ARC )
1571
1572 if( m_shape == SHAPE_T::BEZIER )
1573 {
1576 }
1577 }
1578}
1579
1580
1581void PCB_SHAPE::Mirror( const VECTOR2I& aCentre, FLIP_DIRECTION aFlipDirection )
1582{
1583 flip( aCentre, aFlipDirection );
1584}
1585
1586
1587void PCB_SHAPE::SetIsProxyItem( bool aIsProxy )
1588{
1589 PAD* parentPad = nullptr;
1590
1591 if( GetBoard() && GetBoard()->IsFootprintHolder() )
1592 {
1593 for( FOOTPRINT* fp : GetBoard()->Footprints() )
1594 {
1595 for( PAD* pad : fp->Pads() )
1596 {
1597 if( pad->IsEntered() )
1598 {
1599 parentPad = pad;
1600 break;
1601 }
1602 }
1603 }
1604 }
1605
1606 if( aIsProxy && !m_proxyItem )
1607 {
1608 if( GetShape() == SHAPE_T::SEGMENT )
1609 {
1610 if( parentPad && parentPad->GetLocalThermalSpokeWidthOverride().has_value() )
1611 SetWidth( parentPad->GetLocalThermalSpokeWidthOverride().value() );
1612 else
1614 }
1615 else
1616 {
1617 SetWidth( 1 );
1618 }
1619 }
1620 else if( m_proxyItem && !aIsProxy )
1621 {
1623 }
1624
1625 m_proxyItem = aIsProxy;
1626}
1627
1628
1629double PCB_SHAPE::ViewGetLOD( int aLayer, const KIGFX::VIEW* aView ) const
1630{
1631 KIGFX::PCB_PAINTER& painter = static_cast<KIGFX::PCB_PAINTER&>( *aView->GetPainter() );
1632 KIGFX::PCB_RENDER_SETTINGS& renderSettings = *painter.GetSettings();
1633
1634 if( aLayer == LAYER_LOCKED_ITEM_SHADOW )
1635 {
1636 // Hide shadow if the main layer is not shown
1637 if( !aView->IsLayerVisibleCached( m_layer ) )
1638 return LOD_HIDE;
1639
1640 // Hide shadow on dimmed tracks
1641 if( renderSettings.GetHighContrast() )
1642 {
1643 if( m_layer != renderSettings.GetPrimaryHighContrastLayer() )
1644 return LOD_HIDE;
1645 }
1646 }
1647
1648 if( aLayer == LAYER_CONSTRAINT_SHADOW )
1649 {
1650 // Shadow always appended gate draw here on live constrained-item set not in
1651 // ViewGetLayers which caches
1652 if( !renderSettings.GetConstrainedItems().count( m_Uuid ) )
1653 return LOD_HIDE;
1654
1655 if( !aView->IsLayerVisibleCached( m_layer ) )
1656 return LOD_HIDE;
1657
1658 if( renderSettings.GetHighContrast() && m_layer != renderSettings.GetPrimaryHighContrastLayer() )
1659 return LOD_HIDE;
1660 }
1661
1662 if( FOOTPRINT* parent = GetParentFootprint() )
1663 {
1664 PCB_LAYER_ID checkLayer = m_layer;
1665
1666 if( !IsFrontLayer( checkLayer ) && !IsBackLayer( checkLayer ) )
1667 checkLayer = parent->GetLayer();
1668
1669 if( IsFrontLayer( checkLayer ) && !aView->IsLayerVisibleCached( LAYER_FOOTPRINTS_FR ) )
1670 return LOD_HIDE;
1671
1672 if( IsBackLayer( checkLayer ) && !aView->IsLayerVisibleCached( LAYER_FOOTPRINTS_BK ) )
1673 return LOD_HIDE;
1674 }
1675
1676 return LOD_SHOW;
1677}
1678
1679
1680std::vector<int> PCB_SHAPE::ViewGetLayers() const
1681{
1682 std::vector<int> layers;
1683 layers.reserve( 5 );
1684
1685 layers.push_back( GetLayer() );
1686
1687 if( IsOnCopperLayer() )
1688 {
1689 layers.push_back( GetNetnameLayer( GetLayer() ) );
1690
1691 if( m_hasSolderMask )
1692 {
1693 if( m_layer == F_Cu )
1694 layers.push_back( F_Mask );
1695 else if( m_layer == B_Cu )
1696 layers.push_back( B_Mask );
1697 }
1698 }
1699
1701 layers.push_back( LAYER_LOCKED_ITEM_SHADOW );
1702
1703 // Always advertise constraint-shadow layer ViewGetLOD gates draw by constrained state
1704 layers.push_back( LAYER_CONSTRAINT_SHADOW );
1705
1706 return layers;
1707}
1708
1709
1710void PCB_SHAPE::GetMsgPanelInfo( EDA_DRAW_FRAME* aFrame, std::vector<MSG_PANEL_ITEM>& aList )
1711{
1712 if( aFrame->GetName() == PCB_EDIT_FRAME_NAME )
1713 {
1714 if( FOOTPRINT* parent = GetParentFootprint() )
1715 aList.emplace_back( _( "Footprint" ), parent->GetReference() );
1716 }
1717
1718 aList.emplace_back( _( "Type" ), _( "Drawing" ) );
1719
1720 if( aFrame->GetName() == PCB_EDIT_FRAME_NAME && IsLocked() )
1721 aList.emplace_back( _( "Status" ), _( "Locked" ) );
1722
1723 ShapeGetMsgPanelInfo( aFrame, aList );
1724
1725 aList.emplace_back( _( "Layer" ), GetLayerName() );
1726
1727 if( IsOnCopperLayer() )
1728 {
1729 if( GetNetCode() > 0 ) // Only graphics connected to a net have a netcode > 0
1730 aList.emplace_back( _( "Net" ), GetNetname() );
1731 }
1732}
1733
1734
1735wxString PCB_SHAPE::GetItemDescription( UNITS_PROVIDER* aUnitsProvider, bool aFull ) const
1736{
1737 FOOTPRINT* parentFP = GetParentFootprint();
1738
1739 // Don't report parent footprint info from footprint editor, viewer, etc.
1740 if( GetBoard() && GetBoard()->GetBoardUse() == BOARD_USE::FPHOLDER )
1741 parentFP = nullptr;
1742
1743 if( IsOnCopperLayer() )
1744 {
1745 if( parentFP )
1746 {
1747 return wxString::Format( _( "%s %s of %s on %s" ),
1749 GetNetnameMsg(),
1750 parentFP->GetReference(),
1751 GetLayerName() );
1752 }
1753 else
1754 {
1755 return wxString::Format( _( "%s %s on %s" ),
1757 GetNetnameMsg(),
1758 GetLayerName() );
1759 }
1760 }
1761 else
1762 {
1763 if( parentFP )
1764 {
1765 return wxString::Format( _( "%s of %s on %s" ),
1767 parentFP->GetReference(),
1768 GetLayerName() );
1769 }
1770 else
1771 {
1772 return wxString::Format( _( "%s on %s" ),
1774 GetLayerName() );
1775 }
1776 }
1777}
1778
1779
1781{
1782 if( GetParentFootprint() )
1784 else
1786}
1787
1788
1790{
1791 return new PCB_SHAPE( *this );
1792}
1793
1794
1796{
1797 BOX2I return_box = EDA_ITEM::ViewBBox();
1798
1799 // Inflate the bounding box by just a bit more for safety.
1800 return_box.Inflate( GetWidth() );
1801
1802 return return_box;
1803}
1804
1805
1807{
1808 BOX2I bbox = getBoundingBox();
1809 BOX2I endingsBBox;
1810
1811 if( GetLineEndingsBoundingBox( endingsBBox, GetEffectiveWidth() ) )
1812 bbox.Merge( endingsBBox );
1813
1814 bbox.Normalize();
1815
1816 return bbox;
1817}
1818
1819
1821{
1822 int width = GetEffectiveWidth();
1823
1824 if( IsSolderMaskLayer( aLayer ) && HasSolderMask() && IsCopperLayer( GetLayer() ) )
1825 width += 2 * GetSolderMaskExpansion();
1826
1827 return std::make_shared<SHAPE_COMPOUND>( MakeEffectiveShapesWithLineEndings( width ) );
1828}
1829
1830
1832{
1833 return GetMaxError();
1834}
1835
1836
1838{
1839 PCB_SHAPE* image = dynamic_cast<PCB_SHAPE*>( aImage );
1840 wxCHECK( image, /* void */ );
1841
1842 SwapShape( image );
1843
1844 // Swap params not handled by SwapShape( image )
1845 std::swap( m_layer, image->m_layer );
1846 std::swap( m_isKnockout, image->m_isKnockout );
1847 std::swap( m_isLocked, image->m_isLocked );
1848 std::swap( m_flags, image->m_flags );
1849 std::swap( m_parent, image->m_parent );
1850 std::swap( m_forceVisible, image->m_forceVisible );
1851 std::swap( m_netinfo, image->m_netinfo );
1852 std::swap( m_hasSolderMask, image->m_hasSolderMask );
1853 std::swap( m_solderMaskMargin, image->m_solderMaskMargin );
1854 std::swap( m_customProperties, image->m_customProperties );
1855
1856 std::swap( m_libStart, image->m_libStart );
1857 std::swap( m_libEnd, image->m_libEnd );
1858 std::swap( m_libCornerRadius, image->m_libCornerRadius );
1859 std::swap( m_libArcMid, image->m_libArcMid );
1860 std::swap( m_libBezierC1, image->m_libBezierC1 );
1861 std::swap( m_libBezierC2, image->m_libBezierC2 );
1862 std::swap( m_libPoly, image->m_libPoly );
1863 std::swap( m_libEllipseCenter, image->m_libEllipseCenter );
1864 std::swap( m_libEllipseMajorRadius, image->m_libEllipseMajorRadius );
1865 std::swap( m_libEllipseMinorRadius, image->m_libEllipseMinorRadius );
1866 std::swap( m_libEllipseRotation, image->m_libEllipseRotation );
1867 std::swap( m_libEllipseStartAngle, image->m_libEllipseStartAngle );
1868 std::swap( m_libEllipseEndAngle, image->m_libEllipseEndAngle );
1869 std::swap( m_libShape, image->m_libShape );
1870}
1871
1872
1873bool PCB_SHAPE::cmp_drawings::operator()( const BOARD_ITEM* aFirst, const BOARD_ITEM* aSecond ) const
1874{
1875 if( aFirst->Type() != aSecond->Type() )
1876 return aFirst->Type() < aSecond->Type();
1877
1878 if( aFirst->GetLayer() != aSecond->GetLayer() )
1879 return aFirst->GetLayer() < aSecond->GetLayer();
1880
1881 if( aFirst->Type() == PCB_SHAPE_T )
1882 {
1883 const PCB_SHAPE* dwgA = static_cast<const PCB_SHAPE*>( aFirst );
1884 const PCB_SHAPE* dwgB = static_cast<const PCB_SHAPE*>( aSecond );
1885
1886 if( dwgA->GetShape() != dwgB->GetShape() )
1887 return dwgA->GetShape() < dwgB->GetShape();
1888 }
1889
1890 return aFirst->m_Uuid < aSecond->m_Uuid;
1891}
1892
1893
1894double PCB_SHAPE::GetCoverageArea( int aTextMargin ) const
1895{
1896 // Approximate "linear" shapes with just their width squared, as we don't want to consider
1897 // a linear shape as being much bigger than another for purposes of selection filtering
1898 // just because it happens to be really long.
1899 const double width = GetWidth();
1900
1901 switch( GetShape() )
1902 {
1903 case SHAPE_T::SEGMENT:
1904 case SHAPE_T::ARC:
1905 case SHAPE_T::BEZIER:
1906 return width * width;
1907
1908 case SHAPE_T::RECTANGLE:
1909 case SHAPE_T::CIRCLE:
1910 case SHAPE_T::POLY:
1911 if( !IsAnyFill() )
1912 return width * width;
1913
1915
1916 default:
1917 return BOARD_ITEM::GetCoverageArea( aTextMargin );
1918 }
1919}
1920
1921
1923 int aClearance, int aError, ERROR_LOC aErrorLoc,
1924 bool ignoreLineWidth ) const
1925{
1926 EDA_SHAPE::TransformShapeToPolygon( aBuffer, aClearance, aError, aErrorLoc, ignoreLineWidth,
1927 false );
1928}
1929
1930
1932 int aClearance, int aError, ERROR_LOC aErrorLoc,
1933 KIGFX::RENDER_SETTINGS* aRenderSettings ) const
1934{
1935 EDA_SHAPE::TransformShapeToPolygon( aBuffer, aClearance, aError, aErrorLoc, false, true );
1936}
1937
1938
1939bool PCB_SHAPE::operator==( const BOARD_ITEM& aOther ) const
1940{
1941 if( aOther.Type() != Type() )
1942 return false;
1943
1944 const PCB_SHAPE& other = static_cast<const PCB_SHAPE&>( aOther );
1945
1946 return *this == other;
1947}
1948
1949
1950bool PCB_SHAPE::operator==( const PCB_SHAPE& aOther ) const
1951{
1952 if( aOther.Type() != Type() )
1953 return false;
1954
1955 const PCB_SHAPE& other = static_cast<const PCB_SHAPE&>( aOther );
1956
1957 if( m_layer != other.m_layer )
1958 return false;
1959
1960 if( m_isKnockout != other.m_isKnockout )
1961 return false;
1962
1963 if( m_isLocked != other.m_isLocked )
1964 return false;
1965
1966 if( m_flags != other.m_flags )
1967 return false;
1968
1969 if( m_forceVisible != other.m_forceVisible )
1970 return false;
1971
1972 if( m_netinfo->GetNetCode() != other.m_netinfo->GetNetCode() )
1973 return false;
1974
1975 if( m_hasSolderMask != other.m_hasSolderMask )
1976 return false;
1977
1979 return false;
1980
1981 return EDA_SHAPE::operator==( other );
1982}
1983
1984
1985double PCB_SHAPE::Similarity( const BOARD_ITEM& aOther ) const
1986{
1987 if( aOther.Type() != Type() )
1988 return 0.0;
1989
1990 const PCB_SHAPE& other = static_cast<const PCB_SHAPE&>( aOther );
1991
1992 double similarity = 1.0;
1993
1994 if( GetLayer() != other.GetLayer() )
1995 similarity *= 0.9;
1996
1997 if( m_isKnockout != other.m_isKnockout )
1998 similarity *= 0.9;
1999
2000 if( m_isLocked != other.m_isLocked )
2001 similarity *= 0.9;
2002
2003 if( m_flags != other.m_flags )
2004 similarity *= 0.9;
2005
2006 if( m_forceVisible != other.m_forceVisible )
2007 similarity *= 0.9;
2008
2009 if( m_netinfo->GetNetCode() != other.m_netinfo->GetNetCode() )
2010 similarity *= 0.9;
2011
2012 if( m_hasSolderMask != other.m_hasSolderMask )
2013 similarity *= 0.9;
2014
2016 similarity *= 0.9;
2017
2018 similarity *= EDA_SHAPE::Similarity( other );
2019
2020 return similarity;
2021}
2022
2023
2024static struct PCB_SHAPE_DESC
2025{
2027 {
2034
2035 // Need to initialise enum_map before we can use a Property enum for it
2037
2038 if( layerEnum.Choices().GetCount() == 0 )
2039 {
2040 layerEnum.Undefined( UNDEFINED_LAYER );
2041
2042 for( PCB_LAYER_ID layer : LSET::AllLayersMask() )
2043 layerEnum.Map( layer, LSET::Name( layer ) );
2044 }
2045
2046 void ( PCB_SHAPE::*shapeLayerSetter )( PCB_LAYER_ID ) = &PCB_SHAPE::SetLayer;
2047 PCB_LAYER_ID ( PCB_SHAPE::*shapeLayerGetter )() const = &PCB_SHAPE::GetLayer;
2048
2049 propMgr.ReplaceProperty( TYPE_HASH( BOARD_CONNECTED_ITEM ), _HKI( "Layer" ),
2051 shapeLayerSetter, shapeLayerGetter ) ).SetIsCopyable();
2052
2053 auto isPolygonOrEllipse =
2054 []( INSPECTABLE* aItem ) -> bool
2055 {
2056 if( PCB_SHAPE* shape = dynamic_cast<PCB_SHAPE*>( aItem ) )
2057 {
2058 const SHAPE_T t = shape->GetShape();
2059 return t == SHAPE_T::POLY || t == SHAPE_T::ELLIPSE || t == SHAPE_T::ELLIPSE_ARC;
2060 }
2061
2062 return false;
2063 };
2064
2065 propMgr.OverrideAvailability( TYPE_HASH( PCB_SHAPE ), TYPE_HASH( BOARD_ITEM ), _HKI( "Position X" ),
2066 isPolygonOrEllipse );
2067 propMgr.OverrideAvailability( TYPE_HASH( PCB_SHAPE ), TYPE_HASH( BOARD_ITEM ), _HKI( "Position Y" ),
2068 isPolygonOrEllipse );
2069
2070 propMgr.Mask( TYPE_HASH( PCB_SHAPE ), TYPE_HASH( EDA_SHAPE ), _HKI( "Line Color" ) );
2071 propMgr.Mask( TYPE_HASH( PCB_SHAPE ), TYPE_HASH( EDA_SHAPE ), _HKI( "Fill Color" ) );
2072
2073 auto isNotBezierOrEllipseArc =
2074 []( INSPECTABLE* aItem ) -> bool
2075 {
2076 if( PCB_SHAPE* shape = dynamic_cast<PCB_SHAPE*>( aItem ) )
2077 {
2078 const SHAPE_T t = shape->GetShape();
2079 return t != SHAPE_T::BEZIER && t != SHAPE_T::ELLIPSE_ARC;
2080 }
2081
2082 return true;
2083 };
2084
2086 isNotBezierOrEllipseArc );
2087
2088 auto isCircle =
2089 []( INSPECTABLE* aItem ) -> bool
2090 {
2091 if( PCB_SHAPE* shape = dynamic_cast<PCB_SHAPE*>( aItem ) )
2092 return shape->GetShape() == SHAPE_T::CIRCLE;
2093
2094 return false;
2095 };
2096
2097 auto isNotCircleOrEllipse =
2098 []( INSPECTABLE* aItem ) -> bool
2099 {
2100 if( PCB_SHAPE* shape = dynamic_cast<PCB_SHAPE*>( aItem ) )
2101 {
2102 const SHAPE_T t = shape->GetShape();
2103 return t != SHAPE_T::CIRCLE && t != SHAPE_T::ELLIPSE && t != SHAPE_T::ELLIPSE_ARC;
2104 }
2105
2106 return true;
2107 };
2108
2109 propMgr.OverrideAvailability( TYPE_HASH( PCB_SHAPE ), TYPE_HASH( EDA_SHAPE ), _HKI( "Start X" ),
2110 isNotCircleOrEllipse );
2111 propMgr.OverrideAvailability( TYPE_HASH( PCB_SHAPE ), TYPE_HASH( EDA_SHAPE ), _HKI( "Start Y" ),
2112 isNotCircleOrEllipse );
2113 propMgr.OverrideAvailability( TYPE_HASH( PCB_SHAPE ), TYPE_HASH( EDA_SHAPE ), _HKI( "End X" ),
2114 isNotCircleOrEllipse );
2115 propMgr.OverrideAvailability( TYPE_HASH( PCB_SHAPE ), TYPE_HASH( EDA_SHAPE ), _HKI( "End Y" ),
2116 isNotCircleOrEllipse );
2117 propMgr.OverrideAvailability( TYPE_HASH( PCB_SHAPE ), TYPE_HASH( EDA_SHAPE ), _HKI( "Center X" ),
2118 isCircle );
2119 propMgr.OverrideAvailability( TYPE_HASH( PCB_SHAPE ), TYPE_HASH( EDA_SHAPE ), _HKI( "Center Y" ),
2120 isCircle );
2121 propMgr.OverrideAvailability( TYPE_HASH( PCB_SHAPE ), TYPE_HASH( EDA_SHAPE ), _HKI( "Radius" ),
2122 isCircle );
2123
2124 auto isCopper =
2125 []( INSPECTABLE* aItem ) -> bool
2126 {
2127 if( PCB_SHAPE* shape = dynamic_cast<PCB_SHAPE*>( aItem ) )
2128 return shape->IsOnCopperLayer();
2129
2130 return false;
2131 };
2132
2134 isCopper );
2135
2136 auto isPadEditMode =
2137 []( BOARD* aBoard ) -> bool
2138 {
2139 if( aBoard && aBoard->IsFootprintHolder() )
2140 {
2141 for( FOOTPRINT* fp : aBoard->Footprints() )
2142 {
2143 for( PAD* pad : fp->Pads() )
2144 {
2145 if( pad->IsEntered() )
2146 return true;
2147 }
2148 }
2149 }
2150
2151 return false;
2152 };
2153
2154 auto showNumberBoxProperty =
2155 [&]( INSPECTABLE* aItem ) -> bool
2156 {
2157 if( PCB_SHAPE* shape = dynamic_cast<PCB_SHAPE*>( aItem ) )
2158 {
2159 if( shape->GetShape() == SHAPE_T::RECTANGLE )
2160 return isPadEditMode( shape->GetBoard() );
2161 }
2162
2163 return false;
2164 };
2165
2166 auto showSpokeTemplateProperty =
2167 [&]( INSPECTABLE* aItem ) -> bool
2168 {
2169 if( PCB_SHAPE* shape = dynamic_cast<PCB_SHAPE*>( aItem ) )
2170 {
2171 if( shape->GetShape() == SHAPE_T::SEGMENT )
2172 return isPadEditMode( shape->GetBoard() );
2173 }
2174
2175 return false;
2176 };
2177
2178 const wxString groupPadPrimitives = _HKI( "Pad Primitives" );
2179
2180 propMgr.AddProperty( new PROPERTY<PCB_SHAPE, bool>( _HKI( "Number Box" ),
2182 groupPadPrimitives )
2183 .SetAvailableFunc( showNumberBoxProperty )
2185
2186 propMgr.AddProperty( new PROPERTY<PCB_SHAPE, bool>( _HKI( "Thermal Spoke Template" ),
2188 groupPadPrimitives )
2189 .SetAvailableFunc( showSpokeTemplateProperty )
2191
2192 const wxString groupTechLayers = _HKI( "Technical Layers" );
2193
2194 auto isExternalCuLayer =
2195 []( INSPECTABLE* aItem )
2196 {
2197 if( auto shape = dynamic_cast<PCB_SHAPE*>( aItem ) )
2198 return IsExternalCopperLayer( shape->GetLayer() );
2199
2200 return false;
2201 };
2202
2203 propMgr.AddProperty( new PROPERTY<PCB_SHAPE, bool>( _HKI( "Soldermask" ),
2205 groupTechLayers )
2206 .SetAvailableFunc( isExternalCuLayer ).SetIsCopyable();
2207
2208 propMgr.AddProperty( new PROPERTY<PCB_SHAPE, std::optional<int>>( _HKI( "Soldermask Margin Override" ),
2211 groupTechLayers )
2212 .SetAvailableFunc( isExternalCuLayer ).SetIsCopyable();
2213 }
KICOMMON_API types::KiCadObjectType ToProtoEnum(KICAD_T aValue)
KICOMMON_API KICAD_T FromProtoEnum(types::KiCadObjectType aValue)
Definition api_enums.cpp:55
ERROR_LOC
When approximating an arc or circle, should the error be placed on the outside or inside of the curve...
@ ERROR_OUTSIDE
@ ERROR_INSIDE
constexpr EDA_IU_SCALE pcbIUScale
Definition base_units.h:128
constexpr int ARC_LOW_DEF
Definition base_units.h:143
BITMAPS
A list of all bitmap identifiers.
@ add_dashed_line
@ FPHOLDER
Definition board.h:403
#define DEFAULT_LINE_WIDTH
BOX2< VECTOR2I > BOX2I
Definition box2.h:914
constexpr BOX2I KiROUND(const BOX2D &aBoxD)
Definition box2.h:982
A base class derived from BOARD_ITEM for items that can be connected and have a net,...
virtual bool SetNetCode(int aNetCode, bool aNoAssert)
Set net using a net code.
BOARD_CONNECTED_ITEM(BOARD_ITEM *aParent, KICAD_T idtype)
void PackNet(kiapi::board::types::Net *aProto) const
NETINFO_ITEM * m_netinfo
Store all information about the net that item belongs to.
void UnpackNet(const kiapi::board::types::Net &aProto)
Assigns a net to this item from an API message.
Container for design settings for a BOARD object.
std::shared_ptr< DRC_ENGINE > m_DRCEngine
int GetLineThickness(PCB_LAYER_ID aLayer) const
Return the default graphic segment thickness from the layer class for the given layer.
A base class for any item which can be embedded within the BOARD container class, and therefore insta...
Definition board_item.h:85
BOARD_ITEM(BOARD_ITEM *aParent, KICAD_T idtype, PCB_LAYER_ID aLayer=F_Cu)
Definition board_item.h:87
void SetUuidDirect(const KIID &aUuid)
Raw UUID assignment.
void SetLocked(bool aLocked) override
Definition board_item.h:427
bool m_isKnockout
Definition board_item.h:601
PCB_LAYER_ID GetFlippedLayer(PCB_LAYER_ID aLayer) const
Return the layer paired with aLayer on the opposite side of the board.
PCB_LAYER_ID m_layer
Definition board_item.h:600
bool m_isLocked
Definition board_item.h:602
bool IsLocked() const override
virtual PCB_LAYER_ID GetLayer() const
Return the primary layer this item is on.
virtual double GetCoverageArea(int aTextMargin) const
Return the board area this item covers, used to rank candidates under the cursor so a click on a smal...
virtual void SetLayer(PCB_LAYER_ID aLayer)
Set the layer this item is on.
Definition board_item.h:383
virtual const BOARD * GetBoard() const
Return the BOARD in which this BOARD_ITEM resides, or NULL if none.
FOOTPRINT * GetParentFootprint() const
BOARD_ITEM_CONTAINER * GetParent() const
Definition board_item.h:267
virtual bool IsOnCopperLayer() const
Definition board_item.h:190
wxString GetLayerName() const
Return the name of the PCB layer on which the item resides.
int GetMaxError() const
Information pertinent to a Pcbnew printed circuit board.
Definition board.h:411
BOARD_DESIGN_SETTINGS & GetDesignSettings()
Definition board.cpp:1290
constexpr const Vec & GetPosition() const
Definition box2.h:208
constexpr BOX2< Vec > & Inflate(coord_type dx, coord_type dy)
Inflates the rectangle horizontally by dx and vertically by dy.
Definition box2.h:553
constexpr const Vec GetEnd() const
Definition box2.h:209
constexpr BOX2< Vec > & Normalize()
Ensure that the height and width are positive.
Definition box2.h:143
constexpr BOX2< Vec > & Merge(const BOX2< Vec > &aRect)
Modify the position and size of the rectangle in order to contain aRect.
Definition box2.h:594
constexpr const Vec & GetOrigin() const
Definition box2.h:207
constexpr bool Intersects(const BOX2< Vec > &aRect) const
Definition box2.h:308
Represent basic circle geometry with utility geometry functions.
Definition circle.h:33
MINOPTMAX< int > m_Value
Definition drc_rule.h:204
bool IsCardinal() const
Definition eda_angle.cpp:40
double AsRadians() const
Definition eda_angle.h:119
The base class for create windows for drawing purpose.
virtual const BOX2I GetBoundingBox() const
Return the orthogonal bounding box of this object for display purposes.
Definition eda_item.cpp:270
const KIID m_Uuid
Definition eda_item.h:599
bool m_forceVisible
Definition eda_item.h:614
KICAD_T Type() const
Returns the type of object.
Definition eda_item.h:110
EDA_ITEM_FLAGS m_flags
Definition eda_item.h:608
virtual bool IsType(const std::vector< KICAD_T > &aScanTypes) const
Check whether the item is one of the listed types.
Definition eda_item.h:214
std::map< wxString, wxString > m_customProperties
Definition eda_item.h:617
virtual const BOX2I ViewBBox() const override
Return the bounding box of the item covering all its layers.
Definition eda_item.cpp:509
EDA_ITEM * m_parent
Owner.
Definition eda_item.h:609
EDA_ITEM(EDA_ITEM *parent, KICAD_T idType, bool isSCH_ITEM=false, bool isBOARD_ITEM=false)
Definition eda_item.cpp:84
virtual int GetHatchLineSpacing() const
Definition eda_shape.h:168
SHAPE_T m_shape
Definition eda_shape.h:752
virtual void SetEnd(const VECTOR2I &aEnd)
Definition eda_shape.h:337
void TransformShapeToPolygon(SHAPE_POLY_SET &aBuffer, int aClearance, int aError, ERROR_LOC aErrorLoc, bool ignoreLineWidth=false, bool includeFill=false) const
Convert the shape to a closed polygon.
int GetEllipseMinorRadius() const
Definition eda_shape.h:403
bool m_proxyItem
Definition eda_shape.h:781
bool m_hatchingDirty
Definition eda_shape.h:761
bool m_endsSwapped
Definition eda_shape.h:751
const VECTOR2I & GetBezierC2() const
Definition eda_shape.h:376
const VECTOR2I & GetEllipseCenter() const
Definition eda_shape.h:385
bool GetLineEndingsBoundingBox(BOX2I &aBBox, int aLineWidth) const
virtual void SetCenter(const VECTOR2I &aCenter)
int m_editState
Definition eda_shape.h:780
void rotate(const VECTOR2I &aRotCentre, const EDA_ANGLE &aAngle)
std::vector< SHAPE * > MakeEffectiveShapesWithLineEndings(int aLineWidth) const
Make effective geometry for the shape body shortened for line endings plus the line-ending geometry i...
EDA_ANGLE GetEllipseEndAngle() const
Definition eda_shape.h:431
virtual void SetCornerRadius(int aRadius)
int GetEllipseMajorRadius() const
Definition eda_shape.h:394
virtual int GetEffectiveWidth() const
Definition eda_shape.h:166
SHAPE_POLY_SET & GetPolyShape()
EDA_ANGLE GetEllipseRotation() const
Definition eda_shape.h:412
void ShapeGetMsgPanelInfo(EDA_DRAW_FRAME *aFrame, std::vector< MSG_PANEL_ITEM > &aList)
virtual void SetEllipseEndAngle(const EDA_ANGLE &aA)
Definition eda_shape.h:424
bool operator==(const EDA_SHAPE &aOther) const
int GetRadius() const
SHAPE_T GetShape() const
Definition eda_shape.h:177
virtual void SetBezierC2(const VECTOR2I &aPt)
Definition eda_shape.h:375
bool Deserialize(const google::protobuf::Any &aContainer) override
Deserializes the given protobuf message into this object.
VECTOR2I m_arcCenter
Definition eda_shape.h:770
virtual void SetBezierC1(const VECTOR2I &aPt)
Definition eda_shape.h:372
virtual void SetEllipseRotation(const EDA_ANGLE &aA)
Definition eda_shape.h:405
ARC_MID m_arcMidData
Definition eda_shape.h:771
bool IsSolidFill() const
Definition eda_shape.h:125
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:767
const VECTOR2I & GetEnd() const
Return the ending point of the graphic.
Definition eda_shape.h:333
virtual void SetEllipseCenter(const VECTOR2I &aPt)
Definition eda_shape.h:378
virtual void SetEllipseMinorRadius(int aR)
Definition eda_shape.h:396
const VECTOR2I & GetStart() const
Return the starting point of the graphic.
Definition eda_shape.h:283
virtual void SetEllipseMajorRadius(int aR)
Definition eda_shape.h:387
void SwapShape(EDA_SHAPE *aImage)
std::vector< VECTOR2I > GetRectCorners() const
bool IsAnyFill() const
Definition eda_shape.h:120
EDA_ANGLE GetEllipseStartAngle() const
Definition eda_shape.h:422
virtual void UpdateHatching() const
virtual void SetEllipseStartAngle(const EDA_ANGLE &aA)
Definition eda_shape.h:415
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
double Similarity(const EDA_SHAPE &aOther) const
const VECTOR2I & GetBezierC1() const
Definition eda_shape.h:373
VECTOR2I m_end
Definition eda_shape.h:768
const BOX2I getBoundingBox() const
virtual int GetWidth() const
Definition eda_shape.h:165
STROKE_PARAMS m_stroke
Definition eda_shape.h:753
void RebuildBezierToSegmentsPointsList()
Definition eda_shape.h:555
VECTOR2I m_bezierC1
Definition eda_shape.h:773
int GetCornerRadius() const
virtual void SetPolyShape(const SHAPE_POLY_SET &aShape)
Definition eda_shape.h:528
virtual void SetStart(const VECTOR2I &aStart)
Definition eda_shape.h:287
VECTOR2I m_bezierC2
Definition eda_shape.h:774
void Serialize(google::protobuf::Any &aContainer) const override
Serializes this object to the given Any message.
VECTOR2I GetArcMid() const
virtual bool IsVisible() const
Definition eda_text.h:226
ENUM_MAP & Map(T aValue, const wxString &aName)
Definition property.h:798
static ENUM_MAP< T > & Instance()
Definition property.h:792
ENUM_MAP & Undefined(T aValue)
Definition property.h:805
wxPGChoices & Choices()
Definition property.h:843
const TRANSFORM_TRS & GetTransform() const
Definition footprint.h:395
const wxString & GetReference() const
Definition footprint.h:793
Class that other classes need to inherit from, in order to be inspectable.
Definition inspectable.h:39
Contains methods for drawing PCB-specific items.
virtual PCB_RENDER_SETTINGS * GetSettings() override
Return a pointer to current settings that are going to be used when drawing items.
PCB specific render settings.
Definition pcb_painter.h:94
const std::unordered_set< KIID > & GetConstrainedItems() const
Container for all the knowledge about how graphical objects are drawn on any output surface/device.
PCB_LAYER_ID GetPrimaryHighContrastLayer() const
Return the board layer which is in high-contrast mode.
static constexpr double LOD_HIDE
Return this constant from ViewGetLOD() to hide the item unconditionally.
Definition view_item.h:176
static constexpr double LOD_SHOW
Return this constant from ViewGetLOD() to show the item unconditionally.
Definition view_item.h:181
Hold a (potentially large) number of VIEW_ITEMs and renders them on a graphics device provided by the...
Definition view.h:68
bool IsLayerVisibleCached(int aLayer) const
Definition view.h:472
PAINTER * GetPainter() const
Return the painter object used by the view for drawing VIEW_ITEM objects.
Definition view.h:242
Definition kiid.h:46
LSET is a set of PCB_LAYER_IDs.
Definition lset.h:37
void RunOnLayers(const std::function< void(PCB_LAYER_ID)> &aFunction) const
Execute a function on each layer of the LSET.
Definition lset.h:275
static const LSET & AllLayersMask()
Definition lset.cpp:637
static wxString Name(PCB_LAYER_ID aLayerId)
Return the fixed name association with aLayerId.
Definition lset.cpp:184
T Opt() const
Definition minoptmax.h:31
bool HasOpt() const
Definition minoptmax.h:39
int GetNetCode() const
Definition netinfo.h:104
Definition pad.h:61
std::optional< int > GetLocalThermalSpokeWidthOverride() const
Definition pad.h:741
void StyleFromSettings(const BOARD_DESIGN_SETTINGS &aSettings, bool aCheckSide) override
const BOX2I GetBoundingBox() const override
Return the orthogonal bounding box of this object for display purposes.
virtual void Mirror(const VECTOR2I &aCentre, FLIP_DIRECTION aFlipDirection) override
Mirror this object relative to a given horizontal axis the layer is not changed.
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.
VECTOR2I m_libEllipseCenter
Definition pcb_shape.h:397
void swapData(BOARD_ITEM *aImage) override
bool IsConnected() const override
Returns information if the object is derived from BOARD_CONNECTED_ITEM.
void SetEllipseCenter(const VECTOR2I &aPt) override
void SetCenter(const VECTOR2I &aCenter) override
EDA_ANGLE m_libEllipseStartAngle
Definition pcb_shape.h:401
double ViewGetLOD(int aLayer, const KIGFX::VIEW *aView) const override
Return the level of detail (LOD) of the item.
VECTOR2I m_libEnd
Definition pcb_shape.h:386
VECTOR2I m_libBezierC1
Definition pcb_shape.h:392
virtual void syncLibCoords()
SHAPE_POLY_SET getHatchingKnockouts() const override
void SetBezierC1(const VECTOR2I &aPt) override
void SetCornerRadius(int aCornerRadius) override
std::optional< int > GetLocalSolderMaskMargin() const
Definition pcb_shape.h:350
VECTOR2I GetCenter() const override
This defaults to the center of the bounding box if not overridden.
Definition pcb_shape.h:80
void Rotate(const VECTOR2I &aRotCentre, const EDA_ANGLE &aAngle) override
Rotate this object.
VECTOR2I GetLibraryBezierC1() const
BITMAPS GetMenuImage() const override
Return a pointer to an image to be used in menus.
PCB_SHAPE(BOARD_ITEM *aParent, KICAD_T aItemType, SHAPE_T aShapeType)
void SetWidth(int aWidth) override
EDA_ANGLE m_libEllipseEndAngle
Definition pcb_shape.h:402
void SetLibStrokeWidth(int aWidth)
SHAPE_T m_libShape
Definition pcb_shape.h:404
void rebakeFromTransform(const TRANSFORM_TRS &aXform)
int GetWidth() const override
const BOX2I ViewBBox() const override
Return the bounding box of the item covering all its layers.
bool HasSolderMask() const
Definition pcb_shape.h:347
void SetEllipseStartAngle(const EDA_ANGLE &aA) override
void SetHasSolderMask(bool aVal)
Definition pcb_shape.h:346
std::optional< int > m_solderMaskMargin
Definition pcb_shape.h:383
int GetSolderMaskExpansion() const
void NormalizeForCompare() override
Normalize coordinates to compare 2 similar PCB_SHAPES similat to Normalize(), but also normalize SEGM...
void SetShape(SHAPE_T aShape) override
Definition pcb_shape.h:212
void TransformShapeToPolySet(SHAPE_POLY_SET &aBuffer, PCB_LAYER_ID aLayer, int aClearance, int aError, ERROR_LOC aErrorLoc, KIGFX::RENDER_SETTINGS *aRenderSettings=nullptr) const override
Convert the item shape to a polyset.
VECTOR2I m_libArcMid
Definition pcb_shape.h:390
void SetEllipseEndAngle(const EDA_ANGLE &aA) override
int m_libEllipseMinorRadius
Definition pcb_shape.h:399
const VECTOR2I GetFocusPosition() const override
Allows items to return their visual center rather than their anchor.
virtual void SetLayerSet(const LSET &aLayers) override
void SetEnd(const VECTOR2I &aEnd) override
void Flip(const VECTOR2I &aCentre, FLIP_DIRECTION aFlipDirection) override
Flip this object, i.e.
VECTOR2I GetLibraryEnd() const
Definition pcb_shape.h:233
void SetPolyShape(const SHAPE_POLY_SET &aShape) override
virtual std::vector< VECTOR2I > GetCorners() const
Return 4 corners for a rectangle or rotated rectangle (stored as a poly).
bool IsProxyItem() const override
Definition pcb_shape.h:155
void SetEllipseRotation(const EDA_ANGLE &aA) override
bool m_hasSolderMask
Definition pcb_shape.h:382
const FOOTPRINT * transformFp() const
VECTOR2I GetLibraryStart() const
Definition pcb_shape.h:232
void OnFootprintRescaled(double aRatioX, double aRatioY, double aLinearFactor, const VECTOR2I &aAnchor, const EDA_ANGLE &aParentRotate) override
Apply a parent footprint scale to this item.
~PCB_SHAPE() override
virtual LSET GetLayerSet() const override
Return a std::bitset of all layers on which the item physically resides.
bool operator==(const PCB_SHAPE &aShape) const
std::shared_ptr< SHAPE > GetEffectiveShape(PCB_LAYER_ID aLayer=UNDEFINED_LAYER, FLASHING aFlash=FLASHING::DEFAULT, DRC_CONSTRAINT_T aUsage=NULL_CONSTRAINT) const override
Make a set of SHAPE objects representing the PCB_SHAPE.
void SetLayer(PCB_LAYER_ID aLayer) override
Set the layer this item is on.
int m_libCornerRadius
Definition pcb_shape.h:388
void SetEllipseMinorRadius(int aR) override
wxString GetFriendlyName() const override
Definition pcb_shape.h:65
void TransformShapeToPolygon(SHAPE_POLY_SET &aBuffer, PCB_LAYER_ID aLayer, int aClearance, int aError, ERROR_LOC aErrorLoc, bool ignoreLineWidth=false) const override
Convert the shape to a closed polygon.
STROKE_PARAMS GetStroke() const override
void SetIsProxyItem(bool aIsProxy=true) override
void RebakeWithScale(double aScaleX, double aScaleY)
SHAPE_POLY_SET m_libPoly
Definition pcb_shape.h:395
void SetLocalSolderMaskMargin(std::optional< int > aMargin)
Definition pcb_shape.h:349
void Move(const VECTOR2I &aMoveVector) override
Move this object.
std::vector< VECTOR2I > GetConnectionPoints() const
bool Deserialize(const google::protobuf::Any &aContainer) override
Deserializes the given protobuf message into this object.
EDA_ITEM * Clone() const override
Create a duplicate of this item with linked list members set to NULL.
double GetCoverageArea(int aTextMargin) const override
Return the board area this item covers, used to rank candidates under the cursor so a click on a smal...
int getMaxError() const override
void SetStart(const VECTOR2I &aStart) override
bool IsOnLayer(PCB_LAYER_ID aLayer) const override
Test to see if this object is on the given layer.
void SetBezierC2(const VECTOR2I &aPt) override
void UpdateHatching() const override
wxString GetItemDescription(UNITS_PROVIDER *aUnitsProvider, bool aFull) const override
Return a user-visible description string of this item.
void Scale(double aScale)
void Serialize(google::protobuf::Any &aContainer) const override
Serializes this object to the given Any message.
SHAPE_POLY_SET GetLibraryPolyShape() const
void SetStroke(const STROKE_PARAMS &aStroke) override
void Normalize() override
Perform any normalization required after a user rotate and/or flip.
bool IsType(const std::vector< KICAD_T > &aScanTypes) const override
Check whether the item is one of the listed types.
void CopyFrom(const BOARD_ITEM *aOther) override
VECTOR2I GetLibraryBezierC2() const
VECTOR2I m_libBezierC2
Definition pcb_shape.h:393
std::vector< int > ViewGetLayers() const override
Return the all the layers within the VIEW the object is painted on.
void RebakeFromLib()
void SetArcGeometry(const VECTOR2I &aStart, const VECTOR2I &aMid, const VECTOR2I &aEnd) override
Set the three controlling points for an arc.
double Similarity(const BOARD_ITEM &aBoardItem) const override
Return a measure of how likely the other object is to represent the same object.
VECTOR2I m_libStart
Definition pcb_shape.h:385
EDA_ANGLE m_libEllipseRotation
Definition pcb_shape.h:400
int m_libEllipseMajorRadius
Definition pcb_shape.h:398
VECTOR2I GetLibraryArcMid() const
void SetEllipseMajorRadius(int aR) override
PCB_LAYER_ID GetLayer() const override
Return the primary layer this item is on.
Definition pcb_shape.h:70
PROPERTY_BASE & SetAvailableFunc(std::function< bool(INSPECTABLE *)> aFunc)
Set a callback function to determine whether an object provides this property.
Definition property.h:275
PROPERTY_BASE & SetIsCopyable(bool aIsCopyable=true)
Definition property.h:371
PROPERTY_BASE & SetIsHiddenFromRulesEditor(bool aHide=true)
Definition property.h:344
Provide class metadata.
void InheritsAfter(TYPE_ID aDerived, TYPE_ID aBase)
Declare an inheritance relationship between types.
void Mask(TYPE_ID aDerived, TYPE_ID aBase, const wxString &aName)
Sets a base class property as masked in a derived class.
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.
PROPERTY_BASE & ReplaceProperty(size_t aBase, const wxString &aName, PROPERTY_BASE *aNew, const wxString &aGroup=wxEmptyString)
Replace an existing property for a specific type.
void AddTypeCast(TYPE_CAST_BASE *aCast)
Register a type converter.
Definition seg.h:38
VECTOR2I A
Definition seg.h:45
VECTOR2I B
Definition seg.h:46
EDA_ANGLE GetCentralAngle() const
Get the "central angle" of the arc - this is the angle at the point of the "pie slice".
const VECTOR2I & GetArcMid() const
Definition shape_arc.h:116
const VECTOR2I & GetP1() const
Definition shape_arc.h:115
const VECTOR2I & GetP0() const
Definition shape_arc.h:114
const VECTOR2I & GetCenter() const
Represent a polyline containing arcs as well as line segments: A chain of connected line and/or arc s...
void SetClosed(bool aClosed)
Mark the line chain as closed (i.e.
SEG Segment(int aIndex) const
Return a copy of the aIndex-th segment in the 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.
void RemoveAllContours()
Remove all outlines & holes (clears) the polygon set.
ITERATOR IterateWithHoles(int aOutline)
void SetVertex(const VERTEX_INDEX &aIndex, const VECTOR2I &aPos)
Accessor function to set the position of a specific point.
int HoleCount(int aOutline) const
Returns the number of holes in a given outline.
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.
SHAPE_LINE_CHAIN & Hole(int aOutline, int aHole)
Return the reference to aHole-th hole in the aIndex-th outline.
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.
Simple container to manage line stroke parameters.
int GetWidth() const
void SetWidth(int aWidth)
VECTOR2I InverseApply(const VECTOR2I &aPoint) const
bool IsUniformScale() const
Scales that differ only by rounding count as equal, so a pure rotation stays uniform.
const EDA_ANGLE & GetRotate() const
double GetScaleX() const
VECTOR2I Apply(const VECTOR2I &aPoint) const
double GetScaleY() const
double ApplyLinearScale(double aLength) const
void SetScale(double aSx, double aSy)
double InverseApplyLinearScale(double aLength) const
void TransformRoundChamferedRectToPolygon(SHAPE_POLY_SET &aBuffer, const VECTOR2I &aPosition, const VECTOR2I &aSize, const EDA_ANGLE &aRotation, int aCornerRadius, double aChamferRatio, int aChamferCorners, int aInflate, int aError, ERROR_LOC aErrorLoc)
Convert a rectangle with rounded corners and/or chamfered corners to a polygon.
@ SOLDER_MASK_EXPANSION_CONSTRAINT
#define _(s)
static constexpr EDA_ANGLE ANGLE_0
Definition eda_angle.h:448
@ RADIANS_T
Definition eda_angle.h:31
@ DEGREES_T
Definition eda_angle.h:30
static constexpr EDA_ANGLE ANGLE_360
Definition eda_angle.h:454
static constexpr EDA_ANGLE ANGLE_180
Definition eda_angle.h:452
#define PCB_EDIT_FRAME_NAME
FILL_T
Definition eda_fill.h:29
@ NO_FILL
Definition eda_fill.h:30
@ RECURSE
Definition eda_item.h:51
SHAPE_T
Definition eda_shape.h:54
@ UNDEFINED
Definition eda_shape.h:55
@ 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
bool IsSolderMaskLayer(int aLayer)
Definition layer_ids.h:812
bool IsFrontLayer(PCB_LAYER_ID aLayerId)
Layer classification: check if it's a front layer.
Definition layer_ids.h:844
FLASHING
Enum used during connectivity building to ensure we do not query connectivity while building the data...
Definition layer_ids.h:180
bool IsBackLayer(PCB_LAYER_ID aLayerId)
Layer classification: check if it's a back layer.
Definition layer_ids.h:867
int GetNetnameLayer(int aLayer)
Return a netname layer corresponding to the given layer.
Definition layer_ids.h:918
bool IsCopperLayer(int aLayerId)
Test whether a layer is a copper layer.
Definition layer_ids.h:741
@ LAYER_LOCKED_ITEM_SHADOW
Shadow layer for locked items.
Definition layer_ids.h:303
@ LAYER_FOOTPRINTS_FR
Show footprints on front.
Definition layer_ids.h:255
@ LAYER_CONSTRAINT_SHADOW
Shadow layer for items bound to a constraint.
Definition layer_ids.h:320
@ LAYER_FOOTPRINTS_BK
Show footprints on back.
Definition layer_ids.h:256
bool IsExternalCopperLayer(int aLayerId)
Test whether a layer is an external (F_Cu or B_Cu) copper layer.
Definition layer_ids.h:752
PCB_LAYER_ID
A quick note on layer IDs:
Definition layer_ids.h:56
@ F_CrtYd
Definition layer_ids.h:112
@ Edge_Cuts
Definition layer_ids.h:108
@ B_Mask
Definition layer_ids.h:94
@ B_Cu
Definition layer_ids.h:61
@ F_Mask
Definition layer_ids.h:93
@ B_CrtYd
Definition layer_ids.h:111
@ UNDEFINED_LAYER
Definition layer_ids.h:57
@ F_Cu
Definition layer_ids.h:60
This file contains miscellaneous commonly used macros and functions.
#define KI_FALLTHROUGH
The KI_FALLTHROUGH macro is to be used when switch statement cases should purposely fallthrough from ...
Definition macros.h:79
#define UNIMPLEMENTED_FOR(type)
Definition macros.h:92
FLIP_DIRECTION
Definition mirror.h:23
@ LEFT_RIGHT
Flip left to right (around the Y axis)
Definition mirror.h:24
std::vector< TYPED_POINT2I > GetCircleKeyPoints(const CIRCLE &aCircle, bool aIncludeCenter)
Get key points of an CIRCLE.
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
static void transformPolyVertices(SHAPE_POLY_SET &aPoly, const TRANSFORM_TRS &aXform, bool aInverse)
Definition pcb_shape.cpp:57
static double fpScaleLinear(const FOOTPRINT *aFp)
static struct PCB_SHAPE_DESC _PCB_SHAPE_DESC
static bool isCopper(const PNS::ITEM *aItem)
#define TYPE_HASH(x)
Macro to generate unique identifier for a type.
Definition property.h:74
@ PT_SIZE
Size expressed in distance units (mm/inch)
Definition property.h:63
#define REGISTER_TYPE(x)
Helper macro to map type hashes to names.
Utility functions for working with shapes.
const int scale
bool operator()(const BOARD_ITEM *aFirst, const BOARD_ITEM *aSecond) const
const SHAPE_LINE_CHAIN chain
VECTOR2I end
SHAPE_CIRCLE circle(c.m_circle_center, c.m_circle_radius)
static double sweep(float aStart, float aEnd)
#define M_PI
const VECTOR2I CalcArcCenter(const VECTOR2I &aStart, const VECTOR2I &aMid, const VECTOR2I &aEnd)
Determine the center of an arc or circle given three points on its circumference.
Definition trigo.cpp:540
KICAD_T
The set of class identification values stored in EDA_ITEM::m_structType.
Definition typeinfo.h:70
@ PCB_SHAPE_LOCATE_ELLIPSE_ARC_T
Definition typeinfo.h:236
@ PCB_SHAPE_T
class PCB_SHAPE, a segment not on copper layers
Definition typeinfo.h:80
@ PCB_LOCATE_BOARD_EDGE_T
Definition typeinfo.h:126
@ PCB_TEXTBOX_T
class PCB_TEXTBOX, wrapped text on a layer
Definition typeinfo.h:85
@ PCB_TEXT_T
class PCB_TEXT, text on a layer
Definition typeinfo.h:84
@ PCB_FIELD_T
class PCB_FIELD, text associated with a footprint property
Definition typeinfo.h:82
@ PCB_SHAPE_LOCATE_CIRCLE_T
Definition typeinfo.h:131
@ PCB_SHAPE_LOCATE_SEGMENT_T
Definition typeinfo.h:129
@ PCB_SHAPE_LOCATE_RECT_T
Definition typeinfo.h:130
@ PCB_SHAPE_LOCATE_ELLIPSE_T
Definition typeinfo.h:235
@ PCB_SHAPE_LOCATE_BEZIER_T
Definition typeinfo.h:134
@ PCB_PAD_T
class PAD, a pad in a footprint
Definition typeinfo.h:79
@ PCB_SHAPE_LOCATE_POLY_T
Definition typeinfo.h:133
@ PCB_SHAPE_LOCATE_ARC_T
Definition typeinfo.h:132
VECTOR2< int32_t > VECTOR2I
Definition vector2d.h:708
VECTOR2< double > VECTOR2D
Definition vector2d.h:707
#define ZONE_THERMAL_RELIEF_COPPER_WIDTH_MM
Definition zones.h:29