26#include <api/board/board_types.pb.h>
29#include <magic_enum.hpp>
65 for( std::shared_ptr<PCB_SHAPE>& shape :
CopperLayer( aLayer ).custom_shapes )
102 if( shape == PAD_SHAPE::CUSTOM )
108 SetShape( PAD_SHAPE::RECTANGLE, aLayer );
147 bool copperMatches =
true;
153 copperMatches =
false;
156 return copperMatches;
163 PCB_LAYER_ID layer = FromProtoEnum<PCB_LAYER_ID, BoardLayer>( aProto.layer() );
172 SetShape( FromProtoEnum<PAD_SHAPE>( aProto.shape() ), layer );
174 SetAnchorShape( FromProtoEnum<PAD_SHAPE>( aProto.custom_anchor_shape() ), layer );
180 if(
Shape( layer ) == PAD_SHAPE::TRAPEZOID && aProto.has_trapezoid_delta() )
183 if( aProto.chamfered_corners().top_left() )
186 if( aProto.chamfered_corners().top_right() )
189 if( aProto.chamfered_corners().bottom_left() )
192 if( aProto.chamfered_corners().bottom_right() )
196 google::protobuf::Any a;
198 for(
const BoardGraphicShape& shapeProto : aProto.custom_shapes() )
200 a.PackFrom( shapeProto );
201 std::unique_ptr<PCB_SHAPE> shape = std::make_unique<PCB_SHAPE>(
m_parent );
203 if( shape->Deserialize( a ) )
216 auto unpackOptional = []<
typename ProtoEnum>(
const ProtoEnum& aProto,
217 std::optional<bool>& aDest, ProtoEnum aTrueValue,
218 ProtoEnum aFalseValue )
220 if( aProto == aTrueValue )
222 else if( aProto == aFalseValue )
225 aDest = std::nullopt;
228 if( !aContainer.UnpackTo( &padstack ) )
231 m_mode = FromProtoEnum<MODE>( padstack.type() );
236 Drill().
start = FromProtoEnum<PCB_LAYER_ID>( padstack.drill().start_layer() );
237 Drill().
end = FromProtoEnum<PCB_LAYER_ID>( padstack.drill().end_layer() );
238 unpackOptional( padstack.drill().capped(),
Drill().is_capped, VDCM_CAPPED, VDCM_UNCAPPED );
239 unpackOptional( padstack.drill().filled(),
Drill().is_filled, VDFM_FILLED, VDFM_UNFILLED );
241 for(
const PadStackLayer& layer : padstack.copper_layers() )
250 if( padstack.has_zone_settings() )
253 FromProtoEnum<ZONE_CONNECTION>( padstack.zone_settings().zone_connection() );
255 if( padstack.zone_settings().has_thermal_spokes() )
257 const ThermalSpokeSettings& thermals = padstack.zone_settings().thermal_spokes();
259 if( thermals.has_gap() )
262 if( thermals.has_width() )
275 FromProtoEnum<UNCONNECTED_LAYER_MODE>( padstack.unconnected_layer_removal() ) );
277 unpackOptional( padstack.front_outer_layers().solder_mask_mode(),
280 unpackOptional( padstack.back_outer_layers().solder_mask_mode(),
283 unpackOptional( padstack.front_outer_layers().covering_mode(),
FrontOuterLayers().has_covering,
284 VCM_COVERED, VCM_UNCOVERED );
286 unpackOptional( padstack.back_outer_layers().covering_mode(),
BackOuterLayers().has_covering,
287 VCM_COVERED, VCM_UNCOVERED );
289 unpackOptional( padstack.front_outer_layers().plugging_mode(),
FrontOuterLayers().has_plugging,
290 VPM_PLUGGED, VPM_UNPLUGGED );
292 unpackOptional( padstack.back_outer_layers().plugging_mode(),
BackOuterLayers().has_plugging,
293 VPM_PLUGGED, VPM_UNPLUGGED );
295 unpackOptional( padstack.front_outer_layers().solder_paste_mode(),
298 unpackOptional( padstack.back_outer_layers().solder_paste_mode(),
301 if( padstack.front_outer_layers().has_solder_mask_settings()
302 && padstack.front_outer_layers().solder_mask_settings().has_solder_mask_margin() )
305 padstack.front_outer_layers().solder_mask_settings().solder_mask_margin().value_nm();
312 if( padstack.back_outer_layers().has_solder_mask_settings()
313 && padstack.back_outer_layers().solder_mask_settings().has_solder_mask_margin() )
316 padstack.back_outer_layers().solder_mask_settings().solder_mask_margin().value_nm();
323 if( padstack.front_outer_layers().has_solder_paste_settings()
324 && padstack.front_outer_layers().solder_paste_settings().has_solder_paste_margin() )
327 padstack.front_outer_layers().solder_paste_settings().solder_paste_margin().value_nm();
334 if( padstack.back_outer_layers().has_solder_paste_settings()
335 && padstack.back_outer_layers().solder_paste_settings().has_solder_paste_margin() )
338 padstack.back_outer_layers().solder_paste_settings().solder_paste_margin().value_nm();
345 if( padstack.front_outer_layers().has_solder_paste_settings()
346 && padstack.front_outer_layers().solder_paste_settings().has_solder_paste_margin_ratio() )
349 padstack.front_outer_layers().solder_paste_settings().solder_paste_margin_ratio().value();
356 if( padstack.back_outer_layers().has_solder_paste_settings()
357 && padstack.back_outer_layers().solder_paste_settings().has_solder_paste_margin_ratio() )
360 padstack.back_outer_layers().solder_paste_settings().solder_paste_margin_ratio().value();
376 PadStackLayer* stackLayer = aProto.add_copper_layers();
378 stackLayer->set_layer( ToProtoEnum<PCB_LAYER_ID, BoardLayer>( aLayer ) );
382 stackLayer->set_shape( ToProtoEnum<PAD_SHAPE, PadStackShape>(
Shape( aLayer ) ) );
384 stackLayer->set_custom_anchor_shape(
385 ToProtoEnum<PAD_SHAPE, PadStackShape>(
AnchorShape( aLayer ) ) );
387 stackLayer->set_chamfer_ratio(
CopperLayer( aLayer ).shape.chamfered_rect_ratio );
388 stackLayer->set_corner_rounding_ratio(
CopperLayer( aLayer ).shape.round_rect_radius_ratio );
390 if(
Shape( aLayer ) == PAD_SHAPE::TRAPEZOID )
396 google::protobuf::Any a;
398 for(
const std::shared_ptr<PCB_SHAPE>& shape :
Primitives( aLayer ) )
400 shape->Serialize( a );
401 BoardGraphicShape* s = stackLayer->add_custom_shapes();
418 auto packOptional = []<
typename ProtoEnum>(
const std::optional<bool>& aVal, ProtoEnum aTrueVal,
420 ProtoEnum aNullVal ) -> ProtoEnum
422 if( aVal.has_value() )
423 return *aVal ? aTrueVal : aFalseVal;
428 padstack.set_type( ToProtoEnum<MODE, PadStackType>(
m_mode ) );
432 DrillProperties* drill = padstack.mutable_drill();
433 drill->set_start_layer( ToProtoEnum<PCB_LAYER_ID, BoardLayer>(
StartLayer() ) );
434 drill->set_end_layer( ToProtoEnum<PCB_LAYER_ID, BoardLayer>(
EndLayer() ) );
436 packOptional(
Drill().is_filled, VDFM_FILLED, VDFM_UNFILLED, VDFM_FROM_DESIGN_RULES ) );
439 packOptional(
Drill().is_capped, VDCM_CAPPED, VDCM_UNCAPPED, VDCM_FROM_DESIGN_RULES ) );
448 ZoneConnectionSettings* zoneSettings = padstack.mutable_zone_settings();
449 ThermalSpokeSettings* thermalSettings = zoneSettings->mutable_thermal_spokes();
453 zoneSettings->set_zone_connection( ToProtoEnum<ZONE_CONNECTION, ZoneConnectionStyle>(
458 thermalSettings->mutable_width()->set_value_nm( *width );
461 thermalSettings->mutable_gap()->set_value_nm( *gap );
465 padstack.set_unconnected_layer_removal(
468 PadStackOuterLayer* frontOuter = padstack.mutable_front_outer_layers();
469 PadStackOuterLayer* backOuter = padstack.mutable_back_outer_layers();
471 frontOuter->set_solder_mask_mode( packOptional(
FrontOuterLayers().has_solder_mask, SMM_MASKED,
472 SMM_UNMASKED, SMM_FROM_DESIGN_RULES ) );
474 backOuter->set_solder_mask_mode( packOptional(
BackOuterLayers().has_solder_mask, SMM_MASKED,
475 SMM_UNMASKED, SMM_FROM_DESIGN_RULES ) );
477 frontOuter->set_plugging_mode( packOptional(
FrontOuterLayers().has_plugging, VPM_PLUGGED,
478 VPM_UNPLUGGED, VPM_FROM_DESIGN_RULES ) );
480 backOuter->set_plugging_mode( packOptional(
BackOuterLayers().has_plugging, VPM_PLUGGED,
481 VPM_UNPLUGGED, VPM_FROM_DESIGN_RULES ) );
483 frontOuter->set_covering_mode( packOptional(
FrontOuterLayers().has_covering, VCM_COVERED,
484 VCM_UNCOVERED, VCM_FROM_DESIGN_RULES ) );
486 backOuter->set_covering_mode( packOptional(
BackOuterLayers().has_covering, VCM_COVERED,
487 VCM_UNCOVERED, VCM_FROM_DESIGN_RULES ) );
489 frontOuter->set_solder_paste_mode( packOptional(
FrontOuterLayers().has_solder_paste, SPM_PASTE,
490 SPM_NO_PASTE, SPM_FROM_DESIGN_RULES ) );
492 backOuter->set_solder_paste_mode( packOptional(
BackOuterLayers().has_solder_paste, SPM_PASTE,
493 SPM_NO_PASTE, SPM_FROM_DESIGN_RULES ) );
497 frontOuter->mutable_solder_mask_settings()->mutable_solder_mask_margin()->set_value_nm(
503 backOuter->mutable_solder_mask_settings()->mutable_solder_mask_margin()->set_value_nm(
509 frontOuter->mutable_solder_paste_settings()->mutable_solder_paste_margin()->set_value_nm(
515 backOuter->mutable_solder_paste_settings()->mutable_solder_paste_margin()->set_value_nm(
521 frontOuter->mutable_solder_paste_settings()->mutable_solder_paste_margin_ratio()->set_value(
527 backOuter->mutable_solder_paste_settings()->mutable_solder_paste_margin_ratio()->set_value(
531 aContainer.PackFrom( padstack );
539 auto compareCopperProps =
542 if( ( diff =
static_cast<int>( aPadstackRef->
Shape( aLayer ) ) -
543 static_cast<int>( aPadstackCmp->
Shape( aLayer ) ) ) != 0 )
546 if( ( diff = aPadstackRef->
Size( aLayer ).
x - aPadstackCmp->
Size( aLayer ).
x ) != 0 )
549 if( ( diff = aPadstackRef->
Size( aLayer ).
y - aPadstackCmp->
Size( aLayer ).
y ) != 0 )
552 if( ( diff = aPadstackRef->
Offset( aLayer ).
x
553 - aPadstackCmp->
Offset( aLayer ).
x ) != 0 )
556 if( ( diff = aPadstackRef->
Offset( aLayer ).
y
557 - aPadstackCmp->
Offset( aLayer ).
y ) != 0 )
589 if( ( diff =
static_cast<int>( aPadstackRef->
Primitives( aLayer ).size() ) -
590 static_cast<int>( aPadstackCmp->
Primitives( aLayer ).size() ) ) != 0 )
600 if( ( diff =
static_cast<int>( aPadstackRef->
DrillShape() ) -
601 static_cast<int>( aPadstackCmp->
DrillShape() ) ) != 0 )
616 double similarity = 1.0;
621 if(
Shape( aLayer ) != aOther.
Shape( aLayer ) )
624 if(
Size( aLayer ) != aOther.
Size( aLayer ) )
701 return wxEmptyString;
727 if( aCopperLayerCount > 2 )
729 int innerCount = ( aCopperLayerCount - 2 );
730 int halfInnerLayerCount = innerCount / 2;
739 magic_enum::enum_cast<PCB_LAYER_ID>( lastInner - ( layer -
In1_Cu ) );
740 wxCHECK2_MSG( conjugate.has_value() &&
m_copperProps.contains( conjugate.value() ),
741 continue,
"Invalid inner layer conjugate!" );
760 round_rect_corner_radius( 0 ),
761 round_rect_radius_ratio( 0.25 ),
762 chamfered_rect_ratio( 0.2 ),
770 return shape == aOther.
shape && offset == aOther.
offset
780 if( shape != aOther.
shape )
798 if( !std::equal( custom_shapes.begin(), custom_shapes.end(),
800 [](
const std::shared_ptr<PCB_SHAPE>& aFirst,
801 const std::shared_ptr<PCB_SHAPE>& aSecond )
803 return *aFirst == *aSecond;
825 return size == aOther.
size && shape == aOther.
shape
839 [](
const auto& aEntry )
841 const auto& [key, value] = aEntry;
875 parentPad->SetDirty();
919 std::vector<PCB_LAYER_ID> layers;
923 layers.push_back( layer );
933 switch(
static_cast<int>( aLayer ) )
976 wxString::Format( wxT(
"Unhandled layer %d in PADSTACK::EffectiveLayerFor" ),
987 if( boardCopper.
Contains( boardCuLayer ) )
1016 wxT(
"Expected both padstacks to have the same board copper layer count" ) );
1040 "Attempt to retrieve layer " + std::string( magic_enum::enum_name( layer ) ) +
" from a "
1041 "padstack that does not contain it" );
1144 int min_r = std::min( size.
x, size.
y );
1274 return ( defaults.
shape.
shape == PAD_SHAPE::CIRCLE
1275 || ( defaults.
shape.
shape == PAD_SHAPE::CUSTOM
1317 for(
const std::shared_ptr<PCB_SHAPE>& prim : aPrimitivesList )
1327 if( aPrimitivesList.size() )
1346 wxCHECK_MSG(
false, std::nullopt,
"IsTented expects a front or back layer" );
1357 wxCHECK_MSG(
false, std::nullopt,
"IsCovered expects a front or back layer" );
1368 wxCHECK_MSG(
false, std::nullopt,
"IsPlugged expects a front or back layer" );
@ NORMAL
Use all material properties from model file.
constexpr BOX2I KiROUND(const BOX2D &aBoxD)
int compare(const BASE_SET &other) const
BASE_SET & set(size_t pos)
A base class for any item which can be embedded within the BOARD container class, and therefore insta...
virtual LSET BoardLayerSet() const
Return the LSET for the board that this item resides on.
virtual int BoardCopperLayerCount() const
Return the total number of copper layers for the board that this item resides on.
Represent basic circle geometry with utility geometry functions.
virtual void SetParent(EDA_ITEM *aParent)
LSET is a set of PCB_LAYER_IDs.
static LSET AllCuMask(int aCuLayerCount=MAX_CU_LAYERS)
Return a mask holding the requested number of Cu PCB_LAYER_IDs.
bool Contains(PCB_LAYER_ID aLayer) const
See if the layer set contains a PCB layer.
A PADSTACK defines the characteristics of a single or multi-layer pad, in the IPC sense of the word.
std::optional< bool > IsFilled() const
bool operator==(const PADSTACK &aOther) const
CUSTOM_SHAPE_ZONE_MODE CustomShapeInZoneMode() const
std::optional< int > & Clearance(PCB_LAYER_ID aLayer=F_Cu)
void AddPrimitive(PCB_SHAPE *aShape, PCB_LAYER_ID aLayer)
Adds a custom shape primitive to the padstack.
void ReplacePrimitives(const std::vector< std::shared_ptr< PCB_SHAPE > > &aPrimitivesList, PCB_LAYER_ID aLayer)
Clears the existing primitive list (freeing the owned shapes) and adds copies of the given shapes to ...
void packCopperLayer(PCB_LAYER_ID aLayer, kiapi::board::types::PadStack &aProto) const
bool Deserialize(const google::protobuf::Any &aContainer) override
Deserializes the given protobuf message into this object.
MASK_LAYER_PROPS & FrontOuterLayers()
double Similarity(const PADSTACK &aOther) const
Return a measure of how likely the other object is to represent the same object.
int RoundRectRadius(PCB_LAYER_ID aLayer) const
void SetDrillShape(PAD_DRILL_SHAPE aShape)
std::optional< double > & SolderPasteMarginRatio(PCB_LAYER_ID aLayer=F_Cu)
wxString m_customName
! An override for the IPC-7351 padstack name
DRILL_PROPS m_drill
! The primary drill parameters, which also define the start and end layers for through-hole vias and ...
void ForEachUniqueLayer(const std::function< void(PCB_LAYER_ID)> &aMethod) const
Runs the given callable for each active unique copper layer in this padstack, meaning F_Cu for MODE::...
void SetThermalSpokeAngle(EDA_ANGLE aAngle, PCB_LAYER_ID aLayer=F_Cu)
void SetRoundRectRadiusRatio(double aRatio, PCB_LAYER_ID aLayer)
UNCONNECTED_LAYER_MODE m_unconnectedLayerMode
void ClearPrimitives(PCB_LAYER_ID aLayer)
void SetUnconnectedLayerMode(UNCONNECTED_LAYER_MODE aMode)
std::optional< bool > IsTented(PCB_LAYER_ID aSide) const
Checks if this padstack is tented (covered in soldermask) on the given side.
std::optional< int > & ThermalSpokeWidth(PCB_LAYER_ID aLayer=F_Cu)
std::optional< int > & SolderPasteMargin(PCB_LAYER_ID aLayer=F_Cu)
std::optional< int > & SolderMaskMargin(PCB_LAYER_ID aLayer=F_Cu)
void SetChamferRatio(double aRatio, PCB_LAYER_ID aLayer)
const LSET & LayerSet() const
PCB_LAYER_ID EffectiveLayerFor(PCB_LAYER_ID aLayer) const
Determines which geometry layer should be used for the given input layer.
PADSTACK & operator=(const PADSTACK &aOther)
void SetShape(PAD_SHAPE aShape, PCB_LAYER_ID aLayer)
EDA_ANGLE DefaultThermalSpokeAngleForShape(PCB_LAYER_ID aLayer=F_Cu) const
VECTOR2I & TrapezoidDeltaSize(PCB_LAYER_ID aLayer)
DRILL_PROPS m_secondaryDrill
! Secondary drill, used to define back-drilling
VECTOR2I & Offset(PCB_LAYER_ID aLayer)
MASK_LAYER_PROPS m_backMaskProps
! The overrides applied to back outer technical layers
COPPER_LAYER_PROPS & CopperLayer(PCB_LAYER_ID aLayer)
EDA_ANGLE ThermalSpokeAngle(PCB_LAYER_ID aLayer=F_Cu) const
void FlipLayers(int aCopperLayerCount)
Flips the padstack layers in the case that the pad's parent footprint is flipped to the other side of...
CUSTOM_SHAPE_ZONE_MODE m_customShapeInZoneMode
How to build the custom shape in zone, to create the clearance area: CUSTOM_SHAPE_ZONE_MODE::OUTLINE ...
bool unpackCopperLayer(const kiapi::board::types::PadStackLayer &aProto)
PAD_DRILL_SHAPE DrillShape() const
void SetChamferPositions(int aPositions, PCB_LAYER_ID aLayer)
void SetRoundRectRadius(double aRadius, PCB_LAYER_ID aLayer)
std::optional< bool > IsPlugged(PCB_LAYER_ID aSide) const
LSET RelevantShapeLayers(const PADSTACK &aOther) const
Returns the set of layers that must be considered if checking one padstack against another.
std::optional< int > & ThermalGap(PCB_LAYER_ID aLayer=F_Cu)
PAD_SHAPE Shape(PCB_LAYER_ID aLayer) const
void SetAnchorShape(PAD_SHAPE aShape, PCB_LAYER_ID aLayer)
BOARD_ITEM * m_parent
! The BOARD_ITEM this PADSTACK belongs to; will be used as the parent for owned shapes
PADSTACK(BOARD_ITEM *aParent)
std::optional< bool > IsCapped() const
std::vector< PCB_LAYER_ID > UniqueLayers() const
LSET m_layerSet
! The board layers that this padstack is active on
std::unordered_map< PCB_LAYER_ID, COPPER_LAYER_PROPS > m_copperProps
! The properties applied to copper layers if they aren't overridden
static int Compare(const PADSTACK *aPadstackRef, const PADSTACK *aPadstackCmp)
Compare two padstacks and return 0 if they are equal.
PCB_LAYER_ID EndLayer() const
std::optional< bool > IsCovered(PCB_LAYER_ID aSide) const
int & ChamferPositions(PCB_LAYER_ID aLayer)
MASK_LAYER_PROPS m_frontMaskProps
! The overrides applied to front outer technical layers
const VECTOR2I & Size(PCB_LAYER_ID aLayer) const
MODE
! Copper geometry mode: controls how many unique copper layer shapes this padstack has
@ NORMAL
Shape is the same on all layers.
@ CUSTOM
Shapes can be defined on arbitrary layers.
@ FRONT_INNER_BACK
Up to three shapes can be defined (F_Cu, inner copper layers, B_Cu)
void AppendPrimitives(const std::vector< std::shared_ptr< PCB_SHAPE > > &aPrimitivesList, PCB_LAYER_ID aLayer)
Appends a copy of each shape in the given list to this padstack's custom shape list.
double RoundRectRadiusRatio(PCB_LAYER_ID aLayer) const
UNCONNECTED_LAYER_MODE
! Whether or not to remove the copper shape for unconnected layers
PCB_LAYER_ID StartLayer() const
PAD_SHAPE AnchorShape(PCB_LAYER_ID aLayer) const
MASK_LAYER_PROPS & BackOuterLayers()
void Serialize(google::protobuf::Any &aContainer) const override
Serializes this object to the given Any message.
wxString Name() const
! Returns the name of this padstack in IPC-7351 format
void SetSize(const VECTOR2I &aSize, PCB_LAYER_ID aLayer)
double ChamferRatio(PCB_LAYER_ID aLayer) const
static constexpr PCB_LAYER_ID ALL_LAYERS
! Temporary layer identifier to identify code that is not padstack-aware
EDA_ANGLE GetOrientation() const
static constexpr PCB_LAYER_ID INNER_LAYERS
! The layer identifier to use for "inner layers" on top/inner/bottom padstacks
void SetLayerSet(const LSET &aSet)
std::optional< ZONE_CONNECTION > & ZoneConnection(PCB_LAYER_ID aLayer=F_Cu)
MODE m_mode
! The copper layer variation mode this padstack is in
EDA_ANGLE m_orientation
! The rotation of the pad relative to an outer reference frame
std::vector< std::shared_ptr< PCB_SHAPE > > & Primitives(PCB_LAYER_ID aLayer)
@ RECT_CHAMFER_BOTTOM_RIGHT
@ RECT_CHAMFER_BOTTOM_LEFT
static constexpr EDA_ANGLE ANGLE_0
static constexpr EDA_ANGLE ANGLE_90
static constexpr EDA_ANGLE ANGLE_45
@ LAYER_PAD_FR_NETNAMES
Additional netnames layers (not associated with a PCB layer).
bool IsPadCopperLayer(int aLayer)
bool IsFrontLayer(PCB_LAYER_ID aLayerId)
Layer classification: check if it's a front layer.
bool IsBackLayer(PCB_LAYER_ID aLayerId)
Layer classification: check if it's a back layer.
bool IsClearanceLayer(int aLayer)
bool IsCopperLayer(int aLayerId)
Test whether a layer is a copper layer.
@ LAYER_PAD_COPPER_START
Virtual layers for pad copper on a given copper layer.
@ LAYER_PADS
Meta control for all pads opacity/visibility (color ignored).
@ LAYER_PAD_PLATEDHOLES
to draw pad holes (plated)
@ LAYER_VIA_COPPER_START
Virtual layers for via copper on a given copper layer.
@ LAYER_CLEARANCE_START
Virtual layers for pad/via/track clearance outlines for a given copper layer.
@ LAYER_VIA_HOLES
Draw via holes (pad holes do not use this layer).
bool IsViaCopperLayer(int aLayer)
PCB_LAYER_ID
A quick note on layer IDs:
PCB_LAYER_ID ToLAYER_ID(int aLayer)
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 ...
void PackLayerSet(google::protobuf::RepeatedField< int > &aOutput, const LSET &aLayerSet)
LSET UnpackLayerSet(const google::protobuf::RepeatedField< int > &aProtoLayerSet)
KICOMMON_API VECTOR2I UnpackVector2(const types::Vector2 &aInput)
KICOMMON_API void PackVector2(types::Vector2 &aOutput, const VECTOR2I &aInput)
EDA_ANGLE abs(const EDA_ANGLE &aAngle)
PAD_DRILL_SHAPE
The set of pad drill shapes, used with PAD::{Set,Get}DrillShape()
PAD_SHAPE
The set of pad shapes, used with PAD::{Set,Get}Shape()
#define IMPLEMENT_ENUM_TO_WXANY(type)
The features of a padstack that can vary between copper layers All parameters are optional; leaving t...
std::optional< ZONE_CONNECTION > zone_connection
std::optional< int > thermal_spoke_width
std::vector< std::shared_ptr< PCB_SHAPE > > custom_shapes
bool operator==(const COPPER_LAYER_PROPS &aOther) const
std::optional< EDA_ANGLE > thermal_spoke_angle
std::optional< int > clearance
std::optional< int > thermal_gap
! The properties of a padstack drill. Drill position is always the pad position (origin).
bool operator==(const DRILL_PROPS &aOther) const
VECTOR2I size
Drill diameter (x == y) or slot dimensions (x != y)
std::optional< bool > is_capped
True if the drill hole should be capped.
std::optional< bool > is_filled
True if the drill hole should be filled completely.
! The features of a padstack that can vary on outer layers.
bool operator==(const MASK_LAYER_PROPS &aOther) const
std::optional< int > solder_mask_margin
std::optional< bool > has_covering
True if the pad on this side should have covering.
std::optional< int > solder_paste_margin
std::optional< double > solder_paste_margin_ratio
std::optional< bool > has_solder_mask
True if this outer layer has mask (is not tented)
std::optional< bool > has_solder_paste
True if this outer layer has solder paste.
std::optional< bool > has_plugging
True if the drill hole should be plugged on this side.
! The set of properties that define a pad's shape on a given layer
int chamfered_rect_positions
VECTOR2I trapezoid_delta_size
Delta for PAD_SHAPE::TRAPEZOID; half the delta squeezes one end and half expands the other.
double round_rect_corner_radius
VECTOR2I offset
Offset of the shape center from the pad center.
bool operator==(const SHAPE_PROPS &aOther) const
VECTOR2I size
Size of the shape, or of the anchor pad for custom shape pads.
double chamfered_rect_ratio
Size of chamfer: ratio of smallest of X,Y size.
double round_rect_radius_ratio
PAD_SHAPE shape
Shape of the pad.
PAD_SHAPE anchor_shape
Shape of the anchor when shape == PAD_SHAPE::CUSTOM.