7
mirror of https://gitlab.com/kicad/code/kicad.git synced 2025-04-19 22:51:40 +00:00

Phase 2 of padstack support

CHANGED: PCB file format now supports saving/loading complex padstacks

CHANGED: PTH pads are now rendered per copper layer in the copper color;
         the PTH pad color is no longer used.

ADDED: support for importing complex pad stacks from Altium PCBs

Enforce padstack-aware access to pad properties across KiCad

Fixes https://gitlab.com/kicad/code/kicad/-/issues/8182
This commit is contained in:
Jon Evans 2024-09-15 13:26:01 -04:00
parent b255816000
commit 56e0811516
81 changed files with 5445 additions and 1805 deletions
3d-viewer/3d_canvas
api/proto/board
common
include
pcbnew
qa

View File

@ -408,7 +408,8 @@ private:
const EDA_ANGLE& aArcAngle, int aCircleToSegmentsCount, int aWidth,
CONTAINER_2D_BASE* aContainer, const BOARD_ITEM& aOwner );
void buildPadOutlineAsSegments( const PAD* aPad, CONTAINER_2D_BASE* aDstContainer, int aWidth );
void buildPadOutlineAsSegments( const PAD* aPad, PCB_LAYER_ID aLayer,
CONTAINER_2D_BASE* aDstContainer, int aWidth );
public:
static CUSTOM_COLORS_LIST g_SilkColors;

View File

@ -366,22 +366,22 @@ void BOARD_ADAPTER::createPadWithMargin( const PAD* aPad, CONTAINER_2D_BASE* aCo
// is only the size of the anchor), so for those we punt and just use aMargin.x.
if( ( clearance.x < 0 || clearance.x != clearance.y )
&& aPad->GetShape() != PAD_SHAPE::CUSTOM )
&& aPad->GetShape( aLayer ) != PAD_SHAPE::CUSTOM )
{
VECTOR2I dummySize = VECTOR2I( aPad->GetSize() ) + clearance + clearance;
VECTOR2I dummySize = VECTOR2I( aPad->GetSize( aLayer ) ) + clearance + clearance;
if( dummySize.x <= 0 || dummySize.y <= 0 )
return;
PAD dummy( *aPad );
dummy.SetSize( VECTOR2I( dummySize.x, dummySize.y ) );
dummy.SetSize( aLayer, VECTOR2I( dummySize.x, dummySize.y ) );
dummy.TransformShapeToPolygon( poly, aLayer, 0, maxError, ERROR_INSIDE );
clearance = { 0, 0 };
// Remove group membership from dummy item before deleting
dummy.SetParentGroup( nullptr );
}
else if( aPad->GetShape() == PAD_SHAPE::CUSTOM )
else if( aPad->GetShape( aLayer ) == PAD_SHAPE::CUSTOM )
{
// A custom pad can have many complex subshape items. To avoid issues, use its
// final polygon shape, not its basic shape set. One cannot apply the clearance
@ -390,7 +390,7 @@ void BOARD_ADAPTER::createPadWithMargin( const PAD* aPad, CONTAINER_2D_BASE* aCo
}
else
{
auto padShapes = std::static_pointer_cast<SHAPE_COMPOUND>( aPad->GetEffectiveShape() );
auto padShapes = std::static_pointer_cast<SHAPE_COMPOUND>( aPad->GetEffectiveShape( aLayer ) );
for( const SHAPE* shape : padShapes->Shapes() )
{
@ -540,13 +540,13 @@ void BOARD_ADAPTER::addPads( const FOOTPRINT* aFootprint, CONTAINER_2D_BASE* aCo
case F_Mask:
case B_Mask:
margin.x += pad->GetSolderMaskExpansion();
margin.y += pad->GetSolderMaskExpansion();
margin.x += pad->GetSolderMaskExpansion( aLayerId );
margin.y += pad->GetSolderMaskExpansion( aLayerId );
break;
case F_Paste:
case B_Paste:
margin += pad->GetSolderPasteMargin();
margin += pad->GetSolderPasteMargin( aLayerId );
break;
default:
@ -747,8 +747,8 @@ void BOARD_ADAPTER::addShape( const PCB_TEXTBOX* aTextBox, CONTAINER_2D_BASE* aC
{
SHAPE_POLY_SET polyList;
aTextBox->PCB_SHAPE::TransformShapeToPolygon( polyList, UNDEFINED_LAYER, 0,
ARC_HIGH_DEF, ERROR_INSIDE );
aTextBox->PCB_SHAPE::TransformShapeToPolygon( polyList, UNDEFINED_LAYER, 0, ARC_HIGH_DEF,
ERROR_INSIDE );
ConvertPolygonToTriangles( polyList, *aContainer, m_biuTo3Dunits, *aOwner );
}
@ -775,13 +775,13 @@ void BOARD_ADAPTER::addSolidAreasShapes( const ZONE* aZone, CONTAINER_2D_BASE* a
}
void BOARD_ADAPTER::buildPadOutlineAsSegments( const PAD* aPad, CONTAINER_2D_BASE* aContainer,
int aWidth )
void BOARD_ADAPTER::buildPadOutlineAsSegments( const PAD* aPad, PCB_LAYER_ID aLayer,
CONTAINER_2D_BASE* aContainer, int aWidth )
{
if( aPad->GetShape() == PAD_SHAPE::CIRCLE ) // Draw a ring
if( aPad->GetShape( aLayer ) == PAD_SHAPE::CIRCLE ) // Draw a ring
{
const SFVEC2F center3DU = TO_SFVEC2F( aPad->ShapePos() );
const int radius = aPad->GetSize().x / 2;
const SFVEC2F center3DU = TO_SFVEC2F( aPad->ShapePos( aLayer ) );
const int radius = aPad->GetSize( aLayer ).x / 2;
const float inner_radius3DU = TO_3DU( radius - aWidth / 2.0 );
const float outer_radius3DU = TO_3DU( radius + aWidth / 2.0 );
@ -790,7 +790,8 @@ void BOARD_ADAPTER::buildPadOutlineAsSegments( const PAD* aPad, CONTAINER_2D_BAS
else
{
// For other shapes, add outlines as thick segments in polygon buffer
const std::shared_ptr<SHAPE_POLY_SET>& corners = aPad->GetEffectivePolygon( ERROR_INSIDE );
const std::shared_ptr<SHAPE_POLY_SET>& corners = aPad->GetEffectivePolygon( aLayer,
ERROR_INSIDE );
const SHAPE_LINE_CHAIN& path = corners->COutline( 0 );
for( int j = 0; j < path.PointCount(); j++ )

View File

@ -65,18 +65,18 @@
/*
* This is used to draw pad outlines on silk layers.
*/
void buildPadOutlineAsPolygon( const PAD* aPad, SHAPE_POLY_SET& aBuffer, int aWidth, int aMaxError,
ERROR_LOC aErrorLoc )
void buildPadOutlineAsPolygon( const PAD* aPad, PCB_LAYER_ID aLayer, SHAPE_POLY_SET& aBuffer,
int aWidth, int aMaxError, ERROR_LOC aErrorLoc )
{
if( aPad->GetShape() == PAD_SHAPE::CIRCLE ) // Draw a ring
if( aPad->GetShape( aLayer ) == PAD_SHAPE::CIRCLE ) // Draw a ring
{
TransformRingToPolygon( aBuffer, aPad->ShapePos(), aPad->GetSize().x / 2, aWidth,
aMaxError, aErrorLoc );
TransformRingToPolygon( aBuffer, aPad->ShapePos( aLayer ), aPad->GetSize( aLayer ).x / 2,
aWidth, aMaxError, aErrorLoc );
}
else
{
// For other shapes, add outlines as thick segments in polygon buffer
const SHAPE_LINE_CHAIN& path = aPad->GetEffectivePolygon( ERROR_INSIDE )->COutline( 0 );
const SHAPE_LINE_CHAIN& path = aPad->GetEffectivePolygon( aLayer, ERROR_INSIDE )->COutline( 0 );
for( int ii = 0; ii < path.PointCount(); ++ii )
{
@ -903,7 +903,7 @@ void BOARD_ADAPTER::createLayers( REPORTER* aStatusReporter )
if( !pad->IsOnLayer( layer ) )
continue;
buildPadOutlineAsSegments( pad, layerContainer, linewidth );
buildPadOutlineAsSegments( pad, layer, layerContainer, linewidth );
}
}
else
@ -995,7 +995,7 @@ void BOARD_ADAPTER::createLayers( REPORTER* aStatusReporter )
{
if( pad->IsOnLayer( layer ) )
{
buildPadOutlineAsPolygon( pad, *layerPoly, linewidth, maxError,
buildPadOutlineAsPolygon( pad, layer, *layerPoly, linewidth, maxError,
ERROR_INSIDE );
}
}

View File

@ -141,7 +141,7 @@ enum PadStackType
PST_NORMAL = 1;
// The padstack uses up to three different shapes (F_Cu, inner layers, B_Cu)
PST_TOP_INNER_BOTTOM = 2;
PST_FRONT_INNER_BACK = 2;
// The padstack's shape may differ on arbitrary copper layers
PST_CUSTOM = 3;

View File

@ -35,6 +35,8 @@
#include <macros.h>
#include <functional>
#include <wx/log.h>
using namespace std;
// Common calculation part for all BOARD_ITEMs
@ -96,9 +98,52 @@ size_t hash_fp_item( const EDA_ITEM* aItem, int aFlags )
{
const PAD* pad = static_cast<const PAD*>( aItem );
ret = hash<int>{}( static_cast<int>( pad->GetShape() ) );
// TODO(JE) Implement this
if( pad->Padstack().Mode() != PADSTACK::MODE::NORMAL )
wxLogDebug( "Hashing pad with non-simple padstack; hash code needs to be expanded" );
hash_combine( ret, pad->GetAttribute() );
ret = hash<int>{}( static_cast<int>( pad->GetAttribute() ) );
auto hashPadLayer =
[&]( PCB_LAYER_ID aLayer )
{
hash_combine( ret, pad->GetShape( aLayer ) );
hash_combine( ret, pad->GetSize( aLayer ).x, pad->GetSize( aLayer ).y );
hash_combine( ret, pad->GetOffset( aLayer ).x, pad->GetOffset( aLayer ).y );
switch( pad->GetShape( PADSTACK::ALL_LAYERS ) )
{
case PAD_SHAPE::CHAMFERED_RECT:
hash_combine( ret, pad->GetChamferPositions( aLayer ) );
hash_combine( ret, pad->GetChamferRectRatio( aLayer ) );
break;
case PAD_SHAPE::ROUNDRECT:
hash_combine( ret, pad->GetRoundRectCornerRadius( aLayer ) );
break;
case PAD_SHAPE::TRAPEZOID:
hash_combine( ret, pad->GetDelta( aLayer ).x, pad->GetDelta( aLayer ).y );
break;
case PAD_SHAPE::CUSTOM:
{
auto poly = pad->GetEffectivePolygon( aLayer, ERROR_INSIDE );
for( int ii = 0; ii < poly->VertexCount(); ++ii )
{
VECTOR2I point = poly->CVertex( ii ) - pad->GetPosition();
hash_combine( ret, point.x, point.y );
}
break;
}
default:
break;
}
};
pad->Padstack().ForEachUniqueLayer( hashPadLayer );
if( pad->GetAttribute() == PAD_ATTRIB::PTH || pad->GetAttribute() == PAD_ATTRIB::NPTH )
{
@ -112,36 +157,6 @@ size_t hash_fp_item( const EDA_ITEM* aItem, int aFlags )
} );
}
hash_combine( ret, pad->GetSize().x, pad->GetSize().y );
hash_combine( ret, pad->GetOffset().x, pad->GetOffset().y );
switch( pad->GetShape() )
{
case PAD_SHAPE::CHAMFERED_RECT:
hash_combine( ret, pad->GetChamferPositions() );
hash_combine( ret, pad->GetChamferRectRatio() );
break;
case PAD_SHAPE::ROUNDRECT:
hash_combine( ret, pad->GetRoundRectCornerRadius() );
break;
case PAD_SHAPE::TRAPEZOID:
hash_combine( ret, pad->GetDelta().x, pad->GetDelta().y );
break;
case PAD_SHAPE::CUSTOM:
{
auto poly = pad->GetEffectivePolygon( ERROR_INSIDE );
for( int ii = 0; ii < poly->VertexCount(); ++ii )
{
VECTOR2I point = poly->CVertex( ii ) - pad->GetPosition();
hash_combine( ret, point.x, point.y );
}
break;
}
default:
break;
}
hash_combine( ret, hash_board_item( pad, aFlags ) );
if( aFlags & HASH_POS )

View File

@ -145,6 +145,7 @@ fp_text
fp_text_box
free
front
front_inner_back
full
general
generator
@ -251,6 +252,7 @@ pad_prop_castellated
pad_prop_testpoint
pad_prop_heatsink
pad_prop_mechanical
padstack
padvia
prefer_zone_connections
private_layers
@ -292,6 +294,7 @@ segment
segment_width
separators
setup
shape
sheetfile
sheetname
silk_line_width

View File

@ -740,6 +740,19 @@ inline bool IsNetCopperLayer( int aLayer )
return IsCopperLayer( aLayer ) || netCopperLayers.count( aLayer );
}
///! Converts KiCad copper layer enum to an ordinal between the front and back layers
inline size_t CopperLayerToOrdinal( PCB_LAYER_ID aLayer )
{
wxCHECK( IsCopperLayer( aLayer ), 0 );
switch( aLayer )
{
case F_Cu: return 0;
case B_Cu: return MAX_CU_LAYERS - 1;
default: return ( aLayer - B_Cu ) / 2;
}
}
KICOMMON_API PCB_LAYER_ID ToLAYER_ID( int aLayer );

View File

@ -57,7 +57,7 @@ public:
* @param aLayer is the layer to check
* @return true if the layer is included
*/
bool Contains( PCB_LAYER_ID aLayer )
bool Contains( PCB_LAYER_ID aLayer ) const
{
// At the moment, LSET cannot store negative layers, but PCB_LAYER_ID can contain them
if( aLayer < 0 )

View File

@ -108,7 +108,7 @@ types::PadStackType ToProtoEnum( PADSTACK::MODE aValue )
switch( aValue )
{
case PADSTACK::MODE::NORMAL: return types::PadStackType::PST_NORMAL;
case PADSTACK::MODE::TOP_INNER_BOTTOM: return types::PadStackType::PST_TOP_INNER_BOTTOM;
case PADSTACK::MODE::FRONT_INNER_BACK: return types::PadStackType::PST_FRONT_INNER_BACK;
case PADSTACK::MODE::CUSTOM: return types::PadStackType::PST_CUSTOM;
default:
@ -124,7 +124,7 @@ PADSTACK::MODE FromProtoEnum( types::PadStackType aValue )
switch( aValue )
{
case types::PadStackType::PST_NORMAL: return PADSTACK::MODE::NORMAL;
case types::PadStackType::PST_TOP_INNER_BOTTOM: return PADSTACK::MODE::TOP_INNER_BOTTOM;
case types::PadStackType::PST_FRONT_INNER_BACK: return PADSTACK::MODE::FRONT_INNER_BACK;
case types::PadStackType::PST_CUSTOM: return PADSTACK::MODE::CUSTOM;
default:

View File

@ -49,7 +49,7 @@ AR_MATRIX::AR_MATRIX()
m_GridRouting = 0;
m_RouteCount = 0;
m_routeLayerBottom = B_Cu;
m_routeLayerTop = F_Cu;
m_routeLayerTop = PADSTACK::ALL_LAYERS;
}
@ -901,24 +901,25 @@ void AR_MATRIX::CreateKeepOutRectangle(
void AR_MATRIX::PlacePad( PAD* aPad, int color, int marge, AR_MATRIX::CELL_OP op_logic )
{
int dx, dy;
VECTOR2I shape_pos = aPad->ShapePos();
VECTOR2I shape_pos = aPad->ShapePos( PADSTACK::ALL_LAYERS );
dx = aPad->GetSize().x / 2;
// TODO(JE) padstacks
dx = aPad->GetSize( PADSTACK::ALL_LAYERS ).x / 2;
dx += marge;
if( aPad->GetShape() == PAD_SHAPE::CIRCLE )
if( aPad->GetShape( PADSTACK::ALL_LAYERS ) == PAD_SHAPE::CIRCLE )
{
traceFilledCircle( shape_pos.x, shape_pos.y, dx, aPad->GetLayerSet(), color, op_logic );
return;
}
dy = aPad->GetSize().y / 2;
dy = aPad->GetSize( PADSTACK::ALL_LAYERS ).y / 2;
dy += marge;
if( aPad->GetShape() == PAD_SHAPE::TRAPEZOID )
if( aPad->GetShape( PADSTACK::ALL_LAYERS ) == PAD_SHAPE::TRAPEZOID )
{
dx += abs( aPad->GetDelta().y ) / 2;
dy += abs( aPad->GetDelta().x ) / 2;
dx += abs( aPad->GetDelta( PADSTACK::ALL_LAYERS ).y ) / 2;
dy += abs( aPad->GetDelta( PADSTACK::ALL_LAYERS ).x ) / 2;
}
// The pad is a rectangle ( horizontal or vertical )

View File

@ -2337,7 +2337,7 @@ std::tuple<int, double, double> BOARD::GetTrackLength( const PCB_TRACK& aTrack )
VECTOR2I loc;
// We may not collide even if we passed the bounding-box hit test
if( pad->GetEffectivePolygon( ERROR_INSIDE )->Collide( trackSeg, 0, nullptr, &loc ) )
if( pad->GetEffectivePolygon( track->GetLayer(), ERROR_INSIDE )->Collide( trackSeg, 0, nullptr, &loc ) )
{
// Part 1: length of the seg to the intersection with the pad poly
if( hitStart )

View File

@ -825,8 +825,8 @@ BOARD_DESIGN_SETTINGS::BOARD_DESIGN_SETTINGS( JSON_SETTINGS* aParent, const std:
{
nlohmann::json ret =
{
{ "width", pcbIUScale.IUTomm( m_Pad_Master->GetSize().x ) },
{ "height", pcbIUScale.IUTomm( m_Pad_Master->GetSize().y ) },
{ "width", pcbIUScale.IUTomm( m_Pad_Master->GetSize( PADSTACK::ALL_LAYERS ).x ) },
{ "height", pcbIUScale.IUTomm( m_Pad_Master->GetSize( PADSTACK::ALL_LAYERS ).y ) },
{ "drill", pcbIUScale.IUTomm( m_Pad_Master->GetDrillSize().x ) }
};
@ -841,7 +841,7 @@ BOARD_DESIGN_SETTINGS::BOARD_DESIGN_SETTINGS( JSON_SETTINGS* aParent, const std:
sz.x = pcbIUScale.mmToIU( aJson["width"].get<double>() );
sz.y = pcbIUScale.mmToIU( aJson["height"].get<double>() );
m_Pad_Master->SetSize( sz );
m_Pad_Master->SetSize( PADSTACK::ALL_LAYERS, sz );
int drill = pcbIUScale.mmToIU( aJson["drill"].get<double>() );
@ -1498,7 +1498,8 @@ void BOARD_DESIGN_SETTINGS::SetDefaultMasterPad()
m_Pad_Master.get()->SetDrillShape( PAD_DRILL_SHAPE::CIRCLE );
m_Pad_Master.get()->SetDrillSize(
VECTOR2I( pcbIUScale.mmToIU( DEFAULT_PAD_DRILL_DIAMETER_MM ), 0 ) );
m_Pad_Master.get()->SetShape( PAD_SHAPE::ROUNDRECT );
m_Pad_Master.get()->SetShape( PADSTACK::ALL_LAYERS, PAD_SHAPE::ROUNDRECT );
m_Pad_Master.get()->SetRoundRectCornerRadius(
PADSTACK::ALL_LAYERS,
pcbIUScale.mmToIU( DEFAULT_PAD_HEIGTH_MM / 100.0 * DEFAULT_PAD_REACT_RADIUS ) );
}

View File

@ -459,8 +459,10 @@ bool CONNECTIVITY_DATA::IsConnectedOnLayer( const BOARD_CONNECTED_ITEM *aItem, i
if( zone->IsFilled() )
{
const SHAPE_POLY_SET* zoneFill = zone->GetFill( ToLAYER_ID( aLayer ) );
const SHAPE_LINE_CHAIN& padHull = pad->GetEffectivePolygon( ERROR_INSIDE )->Outline( 0 );
PCB_LAYER_ID pcbLayer = ToLAYER_ID( aLayer );
const SHAPE_POLY_SET* zoneFill = zone->GetFill( pcbLayer );
const SHAPE_LINE_CHAIN& padHull =
pad->GetEffectivePolygon( pcbLayer, ERROR_INSIDE )->Outline( 0 );
for( const VECTOR2I& pt : zoneFill->COutline( islandIdx ).CPoints() )
{

View File

@ -150,8 +150,18 @@ CN_ITEM* CN_LIST::Add( PAD* pad )
if( !pad->IsOnCopperLayer() )
return nullptr;
auto item = new CN_ITEM( pad, false, 1 );
item->AddAnchor( pad->ShapePos() );
auto item = new CN_ITEM( pad, false, 1 );
std::set<VECTOR2I> uniqueAnchors;
pad->Padstack().ForEachUniqueLayer(
[&]( PCB_LAYER_ID aLayer )
{
uniqueAnchors.insert( pad->ShapePos( aLayer ) );
} );
for( const VECTOR2I& anchor : uniqueAnchors )
item->AddAnchor( anchor );
item->SetLayers( F_Cu, B_Cu );
switch( pad->GetAttribute() )

View File

@ -157,21 +157,27 @@ static bool isCopperOutside( const FOOTPRINT* aFootprint, SHAPE_POLY_SET& aShape
for( PAD* pad : aFootprint->Pads() )
{
SHAPE_POLY_SET poly = aShape.CloneDropTriangulation();
pad->Padstack().ForEachUniqueLayer(
[&]( PCB_LAYER_ID aLayer )
{
SHAPE_POLY_SET poly = aShape.CloneDropTriangulation();
poly.ClearArcs();
poly.ClearArcs();
poly.BooleanIntersection( *pad->GetEffectivePolygon( ERROR_INSIDE ),
SHAPE_POLY_SET::PM_FAST );
poly.BooleanIntersection( *pad->GetEffectivePolygon( aLayer, ERROR_INSIDE ),
SHAPE_POLY_SET::PM_FAST );
if( poly.OutlineCount() == 0 )
{
VECTOR2I padPos = pad->GetPosition();
wxLogTrace( traceBoardOutline, wxT( "Tested pad (%d, %d): outside" ),
padPos.x, padPos.y );
padOutside = true;
if( poly.OutlineCount() == 0 )
{
VECTOR2I padPos = pad->GetPosition();
wxLogTrace( traceBoardOutline, wxT( "Tested pad (%d, %d): outside" ),
padPos.x, padPos.y );
padOutside = true;
}
} );
if( padOutside )
break;
}
VECTOR2I padPos = pad->GetPosition();
wxLogTrace( traceBoardOutline, wxT( "Tested pad (%d, %d): not outside" ),

View File

@ -112,7 +112,7 @@ static PAD_ATTRIB code_type[] =
*/
static bool PadHasMeaningfulRoundingRadius( const PAD& aPad )
{
const PAD_SHAPE shape = aPad.GetShape();
const PAD_SHAPE shape = aPad.GetShape( PADSTACK::ALL_LAYERS );
return shape == PAD_SHAPE::ROUNDRECT || shape == PAD_SHAPE::CHAMFERED_RECT;
}
@ -223,7 +223,7 @@ DIALOG_PAD_PROPERTIES::DIALOG_PAD_PROPERTIES( PCB_BASE_FRAME* aParent, PAD* aPad
// Zero it out here to mark that we should recompute a better ratio if the user
// selects a pad shape which would need a default rounding ratio computed for it
if( !PadHasMeaningfulRoundingRadius( *m_previewPad ) )
m_previewPad->SetRoundRectRadiusRatio( 0.0 );
m_previewPad->SetRoundRectRadiusRatio( PADSTACK::ALL_LAYERS, 0.0 );
if( m_isFpEditor )
{
@ -409,20 +409,20 @@ void DIALOG_PAD_PROPERTIES::prepareCanvas()
void DIALOG_PAD_PROPERTIES::updateRoundRectCornerValues()
{
// Note: use ChangeValue() to avoid generating a wxEVT_TEXT event
m_cornerRadius.ChangeValue( m_previewPad->GetRoundRectCornerRadius() );
m_cornerRadius.ChangeValue( m_previewPad->GetRoundRectCornerRadius( PADSTACK::ALL_LAYERS ) );
m_cornerRatio.ChangeDoubleValue( m_previewPad->GetRoundRectRadiusRatio() * 100.0 );
m_mixedCornerRatio.ChangeDoubleValue( m_previewPad->GetRoundRectRadiusRatio() * 100.0 );
m_cornerRatio.ChangeDoubleValue( m_previewPad->GetRoundRectRadiusRatio( PADSTACK::ALL_LAYERS ) * 100.0 );
m_mixedCornerRatio.ChangeDoubleValue( m_previewPad->GetRoundRectRadiusRatio( PADSTACK::ALL_LAYERS ) * 100.0 );
m_chamferRatio.ChangeDoubleValue( m_previewPad->GetChamferRectRatio() * 100.0 );
m_mixedChamferRatio.ChangeDoubleValue( m_previewPad->GetChamferRectRatio() * 100.0 );
m_chamferRatio.ChangeDoubleValue( m_previewPad->GetChamferRectRatio( PADSTACK::ALL_LAYERS ) * 100.0 );
m_mixedChamferRatio.ChangeDoubleValue( m_previewPad->GetChamferRectRatio( PADSTACK::ALL_LAYERS ) * 100.0 );
}
void DIALOG_PAD_PROPERTIES::onCornerRadiusChange( wxCommandEvent& event )
{
if( m_previewPad->GetShape() != PAD_SHAPE::ROUNDRECT
&& m_previewPad->GetShape() != PAD_SHAPE::CHAMFERED_RECT )
if( m_previewPad->GetShape( PADSTACK::ALL_LAYERS ) != PAD_SHAPE::ROUNDRECT
&& m_previewPad->GetShape( PADSTACK::ALL_LAYERS ) != PAD_SHAPE::CHAMFERED_RECT )
{
return;
}
@ -432,10 +432,10 @@ void DIALOG_PAD_PROPERTIES::onCornerRadiusChange( wxCommandEvent& event )
if( transferDataToPad( m_previewPad ) )
{
m_previewPad->SetRoundRectCornerRadius( m_cornerRadius.GetValue() );
m_previewPad->SetRoundRectCornerRadius( PADSTACK::ALL_LAYERS, m_cornerRadius.GetValue() );
m_cornerRatio.ChangeDoubleValue( m_previewPad->GetRoundRectRadiusRatio() * 100.0 );
m_mixedCornerRatio.ChangeDoubleValue( m_previewPad->GetRoundRectRadiusRatio() * 100.0 );
m_cornerRatio.ChangeDoubleValue( m_previewPad->GetRoundRectRadiusRatio( PADSTACK::ALL_LAYERS ) * 100.0 );
m_mixedCornerRatio.ChangeDoubleValue( m_previewPad->GetRoundRectRadiusRatio( PADSTACK::ALL_LAYERS ) * 100.0 );
redraw();
}
@ -447,8 +447,8 @@ void DIALOG_PAD_PROPERTIES::onCornerRadiusChange( wxCommandEvent& event )
void DIALOG_PAD_PROPERTIES::onCornerSizePercentChange( wxCommandEvent& event )
{
if( m_previewPad->GetShape() != PAD_SHAPE::ROUNDRECT
&& m_previewPad->GetShape() != PAD_SHAPE::CHAMFERED_RECT )
if( m_previewPad->GetShape( PADSTACK::ALL_LAYERS ) != PAD_SHAPE::ROUNDRECT
&& m_previewPad->GetShape( PADSTACK::ALL_LAYERS ) != PAD_SHAPE::CHAMFERED_RECT )
{
return;
}
@ -511,7 +511,7 @@ void DIALOG_PAD_PROPERTIES::onCornerSizePercentChange( wxCommandEvent& event )
}
if( changed && transferDataToPad( m_previewPad ) )
m_cornerRadius.ChangeValue( m_previewPad->GetRoundRectCornerRadius() );
m_cornerRadius.ChangeValue( m_previewPad->GetRoundRectCornerRadius( PADSTACK::ALL_LAYERS ) );
redraw();
@ -598,7 +598,7 @@ void DIALOG_PAD_PROPERTIES::initValues()
}
}
m_primitives = m_previewPad->GetPrimitives();
m_primitives = m_previewPad->GetPrimitives( PADSTACK::ALL_LAYERS );
m_padNetSelector->SetSelectedNetcode( m_previewPad->GetNetCode() );
@ -609,21 +609,21 @@ void DIALOG_PAD_PROPERTIES::initValues()
m_holeX.ChangeValue( m_previewPad->GetDrillSize().x );
m_holeY.ChangeValue( m_previewPad->GetDrillSize().y );
m_sizeX.ChangeValue( m_previewPad->GetSize().x );
m_sizeY.ChangeValue( m_previewPad->GetSize().y );
m_sizeX.ChangeValue( m_previewPad->GetSize( PADSTACK::ALL_LAYERS ).x );
m_sizeY.ChangeValue( m_previewPad->GetSize( PADSTACK::ALL_LAYERS ).y );
m_offsetShapeOpt->SetValue( m_previewPad->GetOffset() != VECTOR2I() );
m_offsetX.ChangeValue( m_previewPad->GetOffset().x );
m_offsetY.ChangeValue( m_previewPad->GetOffset().y );
m_offsetShapeOpt->SetValue( m_previewPad->GetOffset( PADSTACK::ALL_LAYERS ) != VECTOR2I() );
m_offsetX.ChangeValue( m_previewPad->GetOffset( PADSTACK::ALL_LAYERS ).x );
m_offsetY.ChangeValue( m_previewPad->GetOffset( PADSTACK::ALL_LAYERS ).y );
if( m_previewPad->GetDelta().x )
if( m_previewPad->GetDelta( PADSTACK::ALL_LAYERS ).x )
{
m_trapDelta.ChangeValue( m_previewPad->GetDelta().x );
m_trapDelta.ChangeValue( m_previewPad->GetDelta( PADSTACK::ALL_LAYERS ).x );
m_trapAxisCtrl->SetSelection( 0 );
}
else
{
m_trapDelta.ChangeValue( m_previewPad->GetDelta().y );
m_trapDelta.ChangeValue( m_previewPad->GetDelta( PADSTACK::ALL_LAYERS ).y );
m_trapAxisCtrl->SetSelection( 1 );
}
@ -684,7 +684,7 @@ void DIALOG_PAD_PROPERTIES::initValues()
else
m_ZoneCustomPadShape->SetSelection( 0 );
switch( m_previewPad->GetShape() )
switch( m_previewPad->GetShape( PADSTACK::ALL_LAYERS ) )
{
default:
case PAD_SHAPE::CIRCLE: m_PadShapeSelector->SetSelection( CHOICE_SHAPE_CIRCLE ); break;
@ -694,28 +694,30 @@ void DIALOG_PAD_PROPERTIES::initValues()
case PAD_SHAPE::ROUNDRECT: m_PadShapeSelector->SetSelection( CHOICE_SHAPE_ROUNDRECT ); break;
case PAD_SHAPE::CHAMFERED_RECT:
if( m_previewPad->GetRoundRectRadiusRatio() > 0.0 )
if( m_previewPad->GetRoundRectRadiusRatio( PADSTACK::ALL_LAYERS ) > 0.0 )
m_PadShapeSelector->SetSelection( CHOICE_SHAPE_CHAMFERED_ROUNDED_RECT );
else
m_PadShapeSelector->SetSelection( CHOICE_SHAPE_CHAMFERED_RECT );
break;
case PAD_SHAPE::CUSTOM:
if( m_previewPad->GetAnchorPadShape() == PAD_SHAPE::RECTANGLE )
if( m_previewPad->GetAnchorPadShape( PADSTACK::ALL_LAYERS ) == PAD_SHAPE::RECTANGLE )
m_PadShapeSelector->SetSelection( CHOICE_SHAPE_CUSTOM_RECT_ANCHOR );
else
m_PadShapeSelector->SetSelection( CHOICE_SHAPE_CUSTOM_CIRC_ANCHOR );
break;
}
m_cbTopLeft->SetValue( m_previewPad->GetChamferPositions() & RECT_CHAMFER_TOP_LEFT );
m_cbTopLeft1->SetValue( m_previewPad->GetChamferPositions() & RECT_CHAMFER_TOP_LEFT );
m_cbTopRight->SetValue( m_previewPad->GetChamferPositions() & RECT_CHAMFER_TOP_RIGHT );
m_cbTopRight1->SetValue( m_previewPad->GetChamferPositions() & RECT_CHAMFER_TOP_RIGHT );
m_cbBottomLeft->SetValue( m_previewPad->GetChamferPositions() & RECT_CHAMFER_BOTTOM_LEFT );
m_cbBottomLeft1->SetValue( m_previewPad->GetChamferPositions() & RECT_CHAMFER_BOTTOM_LEFT );
m_cbBottomRight->SetValue( m_previewPad->GetChamferPositions() & RECT_CHAMFER_BOTTOM_RIGHT );
m_cbBottomRight1->SetValue( m_previewPad->GetChamferPositions() & RECT_CHAMFER_BOTTOM_RIGHT );
int chamferPositions = m_previewPad->GetChamferPositions( PADSTACK::ALL_LAYERS );
m_cbTopLeft->SetValue( chamferPositions & RECT_CHAMFER_TOP_LEFT );
m_cbTopLeft1->SetValue( chamferPositions & RECT_CHAMFER_TOP_LEFT );
m_cbTopRight->SetValue( chamferPositions & RECT_CHAMFER_TOP_RIGHT );
m_cbTopRight1->SetValue( chamferPositions & RECT_CHAMFER_TOP_RIGHT );
m_cbBottomLeft->SetValue( chamferPositions & RECT_CHAMFER_BOTTOM_LEFT );
m_cbBottomLeft1->SetValue( chamferPositions & RECT_CHAMFER_BOTTOM_LEFT );
m_cbBottomRight->SetValue( chamferPositions & RECT_CHAMFER_BOTTOM_RIGHT );
m_cbBottomRight1->SetValue( chamferPositions & RECT_CHAMFER_BOTTOM_RIGHT );
updateRoundRectCornerValues();
@ -820,7 +822,7 @@ void DIALOG_PAD_PROPERTIES::OnPadShapeSelection( wxCommandEvent& event )
m_shapePropsBook->SetSelection( 2 );
// Reasonable defaults
if( m_previewPad->GetRoundRectRadiusRatio() == 0.0 )
if( m_previewPad->GetRoundRectRadiusRatio( PADSTACK::ALL_LAYERS ) == 0.0 )
m_cornerRatio.ChangeDoubleValue( GetDefaultIpcRoundingRatio( *m_previewPad ) * 100 );
break;
@ -830,11 +832,11 @@ void DIALOG_PAD_PROPERTIES::OnPadShapeSelection( wxCommandEvent& event )
m_shapePropsBook->SetSelection( 3 );
// Reasonable default
if( m_previewPad->GetChamferRectRatio() == 0.0 )
m_previewPad->SetChamferRectRatio( 0.2 );
if( m_previewPad->GetChamferRectRatio( PADSTACK::ALL_LAYERS ) == 0.0 )
m_previewPad->SetChamferRectRatio( PADSTACK::ALL_LAYERS, 0.2 );
// Ensure the displayed value is up to date:
m_chamferRatio.ChangeDoubleValue( m_previewPad->GetChamferRectRatio() * 100.0 );
m_chamferRatio.ChangeDoubleValue( m_previewPad->GetChamferRectRatio( PADSTACK::ALL_LAYERS ) * 100.0 );
// A reasonable default is one corner chamfered (usual for some SMD pads).
if( !m_cbTopLeft->GetValue() && !m_cbTopRight->GetValue()
@ -852,17 +854,17 @@ void DIALOG_PAD_PROPERTIES::OnPadShapeSelection( wxCommandEvent& event )
m_shapePropsBook->SetSelection( 4 );
// Reasonable defaults
if( m_previewPad->GetRoundRectRadiusRatio() == 0.0
&& m_previewPad->GetChamferRectRatio() == 0.0 )
if( m_previewPad->GetRoundRectRadiusRatio( PADSTACK::ALL_LAYERS ) == 0.0
&& m_previewPad->GetChamferRectRatio( PADSTACK::ALL_LAYERS ) == 0.0 )
{
m_previewPad->SetRoundRectRadiusRatio(
GetDefaultIpcRoundingRatio( *m_previewPad ) );
m_previewPad->SetChamferRectRatio( 0.2 );
m_previewPad->SetRoundRectRadiusRatio( PADSTACK::ALL_LAYERS,
GetDefaultIpcRoundingRatio( *m_previewPad ) );
m_previewPad->SetChamferRectRatio( PADSTACK::ALL_LAYERS, 0.2 );
}
// Ensure the displayed values are up to date:
m_mixedChamferRatio.ChangeDoubleValue( m_previewPad->GetChamferRectRatio() * 100.0 );
m_mixedCornerRatio.ChangeDoubleValue( m_previewPad->GetRoundRectRadiusRatio() * 100.0 );
m_mixedChamferRatio.ChangeDoubleValue( m_previewPad->GetChamferRectRatio( PADSTACK::ALL_LAYERS ) * 100.0 );
m_mixedCornerRatio.ChangeDoubleValue( m_previewPad->GetRoundRectRadiusRatio( PADSTACK::ALL_LAYERS ) * 100.0 );
break;
case CHOICE_SHAPE_CUSTOM_CIRC_ANCHOR: // PAD_SHAPE::CUSTOM, circular anchor
@ -949,7 +951,7 @@ void DIALOG_PAD_PROPERTIES::UpdateLayersDropdown()
case PTH_DLG_TYPE:
m_rbCopperLayersSel->Append( _( "All copper layers" ) );
m_rbCopperLayersSel->Append( wxString::Format( _( "%s, %s and connected layers" ),
m_board->GetLayerName( F_Cu ),
m_board->GetLayerName( PADSTACK::ALL_LAYERS ),
m_board->GetLayerName( B_Cu ) ) );
m_rbCopperLayersSel->Append( _( "Connected layers only" ) );
m_rbCopperLayersSel->Append( _( "None" ) );
@ -957,16 +959,16 @@ void DIALOG_PAD_PROPERTIES::UpdateLayersDropdown()
case NPTH_DLG_TYPE:
m_rbCopperLayersSel->Append( wxString::Format( _( "%s and %s" ),
m_board->GetLayerName( F_Cu ),
m_board->GetLayerName( PADSTACK::ALL_LAYERS ),
m_board->GetLayerName( B_Cu ) ) );
m_rbCopperLayersSel->Append( m_board->GetLayerName( F_Cu ) );
m_rbCopperLayersSel->Append( m_board->GetLayerName( PADSTACK::ALL_LAYERS ) );
m_rbCopperLayersSel->Append( m_board->GetLayerName( B_Cu ) );
m_rbCopperLayersSel->Append( _( "None" ) );
break;
case SMD_DLG_TYPE:
case CONN_DLG_TYPE:
m_rbCopperLayersSel->Append( m_board->GetLayerName( F_Cu ) );
m_rbCopperLayersSel->Append( m_board->GetLayerName( PADSTACK::ALL_LAYERS ) );
m_rbCopperLayersSel->Append( m_board->GetLayerName( B_Cu ) );
break;
@ -1106,9 +1108,9 @@ void DIALOG_PAD_PROPERTIES::OnUpdateUI( wxUpdateUIEvent& event )
break;
case NPTH_DLG_TYPE:
if( cu_set.test( F_Cu ) && cu_set.test( B_Cu ) )
if( cu_set.test( PADSTACK::ALL_LAYERS ) && cu_set.test( B_Cu ) )
m_stackupImagesBook->SetSelection( 4 );
else if( cu_set.test( F_Cu ) )
else if( cu_set.test( PADSTACK::ALL_LAYERS ) )
m_stackupImagesBook->SetSelection( 5 );
else if( cu_set.test( B_Cu ) )
m_stackupImagesBook->SetSelection( 6 );
@ -1173,7 +1175,7 @@ void DIALOG_PAD_PROPERTIES::updatePadLayersList( LSET layer_mask, bool remove_un
if( !layer_mask.any() )
layer_mask = PAD::SMDMask();
if( layer_mask.test( F_Cu ) )
if( layer_mask.test( PADSTACK::ALL_LAYERS ) )
m_rbCopperLayersSel->SetSelection( 0 );
else
m_rbCopperLayersSel->SetSelection( 1 );
@ -1184,7 +1186,7 @@ void DIALOG_PAD_PROPERTIES::updatePadLayersList( LSET layer_mask, bool remove_un
if( !layer_mask.any() )
layer_mask = PAD::ConnSMDMask();
if( layer_mask.test( F_Cu ) )
if( layer_mask.test( PADSTACK::ALL_LAYERS ) )
m_rbCopperLayersSel->SetSelection( 0 );
else
m_rbCopperLayersSel->SetSelection( 1 );
@ -1195,9 +1197,9 @@ void DIALOG_PAD_PROPERTIES::updatePadLayersList( LSET layer_mask, bool remove_un
if( !layer_mask.any() )
layer_mask = PAD::UnplatedHoleMask();
if( layer_mask.test( F_Cu ) && layer_mask.test( B_Cu ) )
if( layer_mask.test( PADSTACK::ALL_LAYERS ) && layer_mask.test( B_Cu ) )
m_rbCopperLayersSel->SetSelection( 0 );
else if( layer_mask.test( F_Cu ) )
else if( layer_mask.test( PADSTACK::ALL_LAYERS ) )
m_rbCopperLayersSel->SetSelection( 1 );
else if( layer_mask.test( B_Cu ) )
m_rbCopperLayersSel->SetSelection( 2 );
@ -1423,28 +1425,31 @@ bool DIALOG_PAD_PROPERTIES::TransferDataFromWindow()
commit.Modify( m_currentPad );
// Update values
m_currentPad->SetShape( m_masterPad->GetShape() );
// TODO(JE) padstacks - a lot of the below can be removed; SetPadstack should handle it
m_currentPad->SetShape( PADSTACK::ALL_LAYERS, m_masterPad->GetShape( PADSTACK::ALL_LAYERS ) );
m_currentPad->SetAttribute( m_masterPad->GetAttribute() );
m_currentPad->SetFPRelativeOrientation( m_masterPad->GetOrientation() );
m_currentPad->SetSize( m_masterPad->GetSize() );
m_currentPad->SetSize( PADSTACK::ALL_LAYERS, m_masterPad->GetSize( PADSTACK::ALL_LAYERS ) );
VECTOR2I size = m_masterPad->GetDelta();
m_currentPad->SetDelta( size );
VECTOR2I size = m_masterPad->GetDelta( PADSTACK::ALL_LAYERS );
m_currentPad->SetDelta( PADSTACK::ALL_LAYERS, size );
m_currentPad->SetDrillSize( m_masterPad->GetDrillSize() );
m_currentPad->SetDrillShape( m_masterPad->GetDrillShape() );
VECTOR2I offset = m_masterPad->GetOffset();
m_currentPad->SetOffset( offset );
VECTOR2I offset = m_masterPad->GetOffset( PADSTACK::ALL_LAYERS );
m_currentPad->SetOffset( PADSTACK::ALL_LAYERS, offset );
m_currentPad->SetPadToDieLength( m_masterPad->GetPadToDieLength() );
if( m_masterPad->GetShape() != PAD_SHAPE::CUSTOM )
if( m_masterPad->GetShape( PADSTACK::ALL_LAYERS ) != PAD_SHAPE::CUSTOM )
m_masterPad->DeletePrimitivesList();
m_currentPad->SetAnchorPadShape( m_masterPad->GetAnchorPadShape() );
m_currentPad->ReplacePrimitives( m_masterPad->GetPrimitives() );
m_currentPad->SetAnchorPadShape( PADSTACK::ALL_LAYERS,
m_masterPad->GetAnchorPadShape( PADSTACK::ALL_LAYERS ) );
m_currentPad->ReplacePrimitives( PADSTACK::ALL_LAYERS,
m_masterPad->GetPrimitives( PADSTACK::ALL_LAYERS ) );
m_currentPad->SetPadstack( m_masterPad->Padstack() );
m_currentPad->SetLayerSet( m_masterPad->GetLayerSet() );
@ -1465,19 +1470,22 @@ bool DIALOG_PAD_PROPERTIES::TransferDataFromWindow()
m_currentPad->SetThermalSpokeWidth( m_masterPad->GetThermalSpokeWidth() );
m_currentPad->SetThermalSpokeAngle( m_masterPad->GetThermalSpokeAngle() );
m_currentPad->SetThermalGap( m_masterPad->GetThermalGap() );
m_currentPad->SetRoundRectRadiusRatio( m_masterPad->GetRoundRectRadiusRatio() );
m_currentPad->SetChamferRectRatio( m_masterPad->GetChamferRectRatio() );
m_currentPad->SetChamferPositions( m_masterPad->GetChamferPositions() );
m_currentPad->SetRoundRectRadiusRatio(
PADSTACK::ALL_LAYERS, m_masterPad->GetRoundRectRadiusRatio( PADSTACK::ALL_LAYERS ) );
m_currentPad->SetChamferRectRatio( PADSTACK::ALL_LAYERS,
m_masterPad->GetChamferRectRatio( PADSTACK::ALL_LAYERS ) );
m_currentPad->SetChamferPositions( PADSTACK::ALL_LAYERS,
m_masterPad->GetChamferPositions( PADSTACK::ALL_LAYERS ) );
m_currentPad->SetLocalZoneConnection( m_masterPad->GetLocalZoneConnection() );
m_currentPad->GetTeardropParams() = m_masterPad->GetTeardropParams();
// rounded rect pads with radius ratio = 0 are in fact rect pads.
// So set the right shape (and perhaps issues with a radius = 0)
if( m_currentPad->GetShape() == PAD_SHAPE::ROUNDRECT &&
m_currentPad->GetRoundRectRadiusRatio() == 0.0 )
if( m_currentPad->GetShape( PADSTACK::ALL_LAYERS ) == PAD_SHAPE::ROUNDRECT &&
m_currentPad->GetRoundRectRadiusRatio( PADSTACK::ALL_LAYERS ) == 0.0 )
{
m_currentPad->SetShape( PAD_SHAPE::RECTANGLE );
m_currentPad->SetShape( PADSTACK::ALL_LAYERS, PAD_SHAPE::RECTANGLE );
}
// Set the fabrication property:
@ -1586,15 +1594,15 @@ bool DIALOG_PAD_PROPERTIES::transferDataToPad( PAD* aPad )
return false;
aPad->SetAttribute( code_type[m_padType->GetSelection()] );
aPad->SetShape( code_shape[m_PadShapeSelector->GetSelection()] );
aPad->SetShape( PADSTACK::ALL_LAYERS, code_shape[m_PadShapeSelector->GetSelection()] );
if( m_PadShapeSelector->GetSelection() == CHOICE_SHAPE_CUSTOM_RECT_ANCHOR )
aPad->SetAnchorPadShape( PAD_SHAPE::RECTANGLE );
aPad->SetAnchorPadShape( PADSTACK::ALL_LAYERS, PAD_SHAPE::RECTANGLE );
else
aPad->SetAnchorPadShape( PAD_SHAPE::CIRCLE );
aPad->SetAnchorPadShape( PADSTACK::ALL_LAYERS, PAD_SHAPE::CIRCLE );
if( aPad->GetShape() == PAD_SHAPE::CUSTOM )
aPad->ReplacePrimitives( m_primitives );
if( aPad->GetShape( PADSTACK::ALL_LAYERS ) == PAD_SHAPE::CUSTOM )
aPad->ReplacePrimitives( PADSTACK::ALL_LAYERS, m_primitives );
aPad->GetTeardropParams().m_Enabled = m_cbTeardrops->GetValue();
aPad->GetTeardropParams().m_AllowUseTwoTracks = m_cbTeardropsUseNextTrack->GetValue();
@ -1669,17 +1677,19 @@ bool DIALOG_PAD_PROPERTIES::transferDataToPad( PAD* aPad )
aPad->SetDrillSize( VECTOR2I( m_holeX.GetIntValue(), m_holeY.GetIntValue() ) );
}
if( aPad->GetShape() == PAD_SHAPE::CIRCLE )
aPad->SetSize( VECTOR2I( m_sizeX.GetIntValue(), m_sizeX.GetIntValue() ) );
if( aPad->GetShape( PADSTACK::ALL_LAYERS ) == PAD_SHAPE::CIRCLE )
aPad->SetSize( PADSTACK::ALL_LAYERS,
VECTOR2I( m_sizeX.GetIntValue(), m_sizeX.GetIntValue() ) );
else
aPad->SetSize( VECTOR2I( m_sizeX.GetIntValue(), m_sizeY.GetIntValue() ) );
aPad->SetSize( PADSTACK::ALL_LAYERS,
VECTOR2I( m_sizeX.GetIntValue(), m_sizeY.GetIntValue() ) );
// For a trapezoid, test delta value (be sure delta is not too large for pad size)
// remember DeltaSize.x is the Y size variation
bool error = false;
VECTOR2I delta( 0, 0 );
if( aPad->GetShape() == PAD_SHAPE::TRAPEZOID )
if( aPad->GetShape( PADSTACK::ALL_LAYERS ) == PAD_SHAPE::TRAPEZOID )
{
// For a trapezoid, only one of delta.x or delta.y is not 0, depending on axis.
if( m_trapAxisCtrl->GetSelection() == 0 )
@ -1687,37 +1697,38 @@ bool DIALOG_PAD_PROPERTIES::transferDataToPad( PAD* aPad )
else
delta.y = m_trapDelta.GetIntValue();
if( delta.x < 0 && delta.x < -aPad->GetSize().y )
if( delta.x < 0 && delta.x < -aPad->GetSize( PADSTACK::ALL_LAYERS ).y )
{
delta.x = -aPad->GetSize().y + 2;
delta.x = -aPad->GetSize( PADSTACK::ALL_LAYERS ).y + 2;
error = true;
}
if( delta.x > 0 && delta.x > aPad->GetSize().y )
if( delta.x > 0 && delta.x > aPad->GetSize( PADSTACK::ALL_LAYERS ).y )
{
delta.x = aPad->GetSize().y - 2;
delta.x = aPad->GetSize( PADSTACK::ALL_LAYERS ).y - 2;
error = true;
}
if( delta.y < 0 && delta.y < -aPad->GetSize().x )
if( delta.y < 0 && delta.y < -aPad->GetSize( PADSTACK::ALL_LAYERS ).x )
{
delta.y = -aPad->GetSize().x + 2;
delta.y = -aPad->GetSize( PADSTACK::ALL_LAYERS ).x + 2;
error = true;
}
if( delta.y > 0 && delta.y > aPad->GetSize().x )
if( delta.y > 0 && delta.y > aPad->GetSize( PADSTACK::ALL_LAYERS ).x )
{
delta.y = aPad->GetSize().x - 2;
delta.y = aPad->GetSize( PADSTACK::ALL_LAYERS ).x - 2;
error = true;
}
}
aPad->SetDelta( delta );
aPad->SetDelta( PADSTACK::ALL_LAYERS, delta );
if( m_offsetShapeOpt->GetValue() )
aPad->SetOffset( VECTOR2I( m_offsetX.GetIntValue(), m_offsetY.GetIntValue() ) );
aPad->SetOffset( PADSTACK::ALL_LAYERS,
VECTOR2I( m_offsetX.GetIntValue(), m_offsetY.GetIntValue() ) );
else
aPad->SetOffset( VECTOR2I() );
aPad->SetOffset( PADSTACK::ALL_LAYERS, VECTOR2I() );
// Read pad length die
if( m_padToDieOpt->GetValue() )
@ -1758,16 +1769,17 @@ bool DIALOG_PAD_PROPERTIES::transferDataToPad( PAD* aPad )
if( m_cbBottomRight1->GetValue() )
chamfers |= RECT_CHAMFER_BOTTOM_RIGHT;
}
aPad->SetChamferPositions( chamfers );
aPad->SetChamferPositions( PADSTACK::ALL_LAYERS, chamfers );
if( aPad->GetShape() == PAD_SHAPE::CUSTOM )
if( aPad->GetShape( PADSTACK::ALL_LAYERS ) == PAD_SHAPE::CUSTOM )
{
// The pad custom has a "anchor pad" (a basic shape: round or rect pad)
// that is the minimal area of this pad, and is useful to ensure a hole
// diameter is acceptable, and is used in Gerber files as flashed area
// reference
if( aPad->GetAnchorPadShape() == PAD_SHAPE::CIRCLE )
aPad->SetSize( VECTOR2I( m_sizeX.GetIntValue(), m_sizeX.GetIntValue() ) );
if( aPad->GetAnchorPadShape( PADSTACK::ALL_LAYERS ) == PAD_SHAPE::CIRCLE )
aPad->SetSize( PADSTACK::ALL_LAYERS,
VECTOR2I( m_sizeX.GetIntValue(), m_sizeX.GetIntValue() ) );
}
// Define the way the clearance area is defined in zones. Since all non-custom pad
@ -1805,21 +1817,25 @@ bool DIALOG_PAD_PROPERTIES::transferDataToPad( PAD* aPad )
break;
}
if( aPad->GetShape() == PAD_SHAPE::ROUNDRECT )
if( aPad->GetShape( PADSTACK::ALL_LAYERS ) == PAD_SHAPE::ROUNDRECT )
{
aPad->SetRoundRectRadiusRatio( m_cornerRatio.GetDoubleValue() / 100.0 );
aPad->SetRoundRectRadiusRatio( PADSTACK::ALL_LAYERS,
m_cornerRatio.GetDoubleValue() / 100.0 );
}
else if( aPad->GetShape() == PAD_SHAPE::CHAMFERED_RECT )
else if( aPad->GetShape( PADSTACK::ALL_LAYERS ) == PAD_SHAPE::CHAMFERED_RECT )
{
if( m_PadShapeSelector->GetSelection() == CHOICE_SHAPE_CHAMFERED_ROUNDED_RECT )
{
aPad->SetChamferRectRatio( m_mixedChamferRatio.GetDoubleValue() / 100.0 );
aPad->SetRoundRectRadiusRatio( m_mixedCornerRatio.GetDoubleValue() / 100.0 );
aPad->SetChamferRectRatio( PADSTACK::ALL_LAYERS,
m_mixedChamferRatio.GetDoubleValue() / 100.0 );
aPad->SetRoundRectRadiusRatio( PADSTACK::ALL_LAYERS,
m_mixedCornerRatio.GetDoubleValue() / 100.0 );
}
else // Choice is CHOICE_SHAPE_CHAMFERED_RECT, no rounded corner
{
aPad->SetChamferRectRatio( m_chamferRatio.GetDoubleValue() / 100.0 );
aPad->SetRoundRectRadiusRatio( 0 );
aPad->SetChamferRectRatio( PADSTACK::ALL_LAYERS,
m_chamferRatio.GetDoubleValue() / 100.0 );
aPad->SetRoundRectRadiusRatio( PADSTACK::ALL_LAYERS, 0 );
}
}
@ -1863,8 +1879,8 @@ bool DIALOG_PAD_PROPERTIES::transferDataToPad( PAD* aPad )
case NPTH_DLG_TYPE:
switch( copperLayersChoice )
{
case 0: padLayerMask.set( F_Cu ).set( B_Cu ); break;
case 1: padLayerMask.set( F_Cu ); break;
case 0: padLayerMask.set( PADSTACK::ALL_LAYERS ).set( B_Cu ); break;
case 1: padLayerMask.set( PADSTACK::ALL_LAYERS ); break;
case 2: padLayerMask.set( B_Cu ); break;
default: break;
}
@ -1875,7 +1891,7 @@ bool DIALOG_PAD_PROPERTIES::transferDataToPad( PAD* aPad )
case CONN_DLG_TYPE:
switch( copperLayersChoice )
{
case 0: padLayerMask.set( F_Cu ); break;
case 0: padLayerMask.set( PADSTACK::ALL_LAYERS ); break;
case 1: padLayerMask.set( B_Cu ); break;
}
@ -1929,8 +1945,8 @@ void DIALOG_PAD_PROPERTIES::OnOffsetCheckbox( wxCommandEvent& event )
{
if( m_offsetShapeOpt->GetValue() )
{
m_offsetX.SetValue( m_previewPad->GetOffset().x );
m_offsetY.SetValue( m_previewPad->GetOffset().y );
m_offsetX.SetValue( m_previewPad->GetOffset( PADSTACK::ALL_LAYERS ).x );
m_offsetY.SetValue( m_previewPad->GetOffset( PADSTACK::ALL_LAYERS ).y );
}
// Show/hide controls depending on m_offsetShapeOpt being enabled

View File

@ -202,17 +202,18 @@ bool DRC_TEST_PROVIDER_ANNULAR_WIDTH::Run()
case PCB_PAD_T:
{
// TODO(JE) padstacks
PAD* pad = static_cast<PAD*>( item );
if( !pad->HasHole() || pad->GetAttribute() != PAD_ATTRIB::PTH )
return 0;
if( pad->GetOffset() == VECTOR2I( 0, 0 ) )
if( pad->GetOffset( PADSTACK::ALL_LAYERS ) == VECTOR2I( 0, 0 ) )
{
switch( pad->GetShape() )
switch( pad->GetShape( PADSTACK::ALL_LAYERS ) )
{
case PAD_SHAPE::CHAMFERED_RECT:
if( pad->GetChamferRectRatio() > 0.30 )
if( pad->GetChamferRectRatio( PADSTACK::ALL_LAYERS ) > 0.30 )
break;
KI_FALLTHROUGH;
@ -277,9 +278,9 @@ bool DRC_TEST_PROVIDER_ANNULAR_WIDTH::Run()
if( fp )
sameNumPads = fp->GetPads( pad->GetNumber(), pad );
if( pad->GetOffset() == VECTOR2I( 0, 0 ) )
if( pad->GetOffset( PADSTACK::ALL_LAYERS ) == VECTOR2I( 0, 0 ) )
{
switch( pad->GetShape() )
switch( pad->GetShape( PADSTACK::ALL_LAYERS ) )
{
case PAD_SHAPE::CIRCLE:
annularWidth = ( pad->GetSizeX() - pad->GetDrillSizeX() ) / 2;
@ -292,7 +293,7 @@ bool DRC_TEST_PROVIDER_ANNULAR_WIDTH::Run()
break;
case PAD_SHAPE::CHAMFERED_RECT:
if( pad->GetChamferRectRatio() > 0.30 )
if( pad->GetChamferRectRatio( PADSTACK::ALL_LAYERS ) > 0.30 )
break;
KI_FALLTHROUGH;
@ -322,7 +323,8 @@ bool DRC_TEST_PROVIDER_ANNULAR_WIDTH::Run()
SHAPE_POLY_SET padOutline;
std::shared_ptr<SHAPE_SEGMENT> slot = pad->GetEffectiveHoleShape();
pad->TransformShapeToPolygon( padOutline, UNDEFINED_LAYER, 0, maxError,
// TODO(JE) padstacks
pad->TransformShapeToPolygon( padOutline, PADSTACK::ALL_LAYERS, 0, maxError,
ERROR_INSIDE );
if( sameNumPads.empty() )
@ -353,7 +355,7 @@ bool DRC_TEST_PROVIDER_ANNULAR_WIDTH::Run()
{
// Construct the full pad with outline and hole.
sameNumPad->TransformShapeToPolygon( otherPadOutline,
UNDEFINED_LAYER, 0, maxError,
PADSTACK::ALL_LAYERS, 0, maxError,
ERROR_OUTSIDE );
sameNumPad->TransformHoleToPolygon( otherPadOutline, 0, maxError,

View File

@ -406,7 +406,7 @@ void DRC_TEST_PROVIDER_COPPER_CLEARANCE::testItemAgainstZone( BOARD_ITEM* aItem,
for( PAD* pad : allowedNetTiePads )
{
if( pad->GetBoundingBox().Intersects( itemBBox )
&& pad->GetEffectiveShape()->Collide( itemShape.get() ) )
&& pad->GetEffectiveShape( aLayer )->Collide( itemShape.get() ) )
{
return;
}

View File

@ -298,7 +298,8 @@ bool padNeedsUpdate( const PAD* a, const PAD* b, REPORTER* aReporter )
return true;
}
TEST( a->GetShape(), b->GetShape(),
// TOOD(JE) padstacks
TEST( a->GetShape( PADSTACK::ALL_LAYERS ), b->GetShape( PADSTACK::ALL_LAYERS ),
wxString::Format( _( "%s pad shape type differs." ), PAD_DESC( a ) ) );
TEST( a->GetAttribute(), b->GetAttribute(),
@ -311,21 +312,24 @@ bool padNeedsUpdate( const PAD* a, const PAD* b, REPORTER* aReporter )
b->GetFPRelativeOrientation().Normalize().AsDegrees(),
wxString::Format( _( "%s orientation differs." ), PAD_DESC( a ) ) );
TEST( a->GetSize(), b->GetSize(),
TEST( a->GetSize( PADSTACK::ALL_LAYERS ), b->GetSize( PADSTACK::ALL_LAYERS ),
wxString::Format( _( "%s size differs." ), PAD_DESC( a ) ) );
TEST( a->GetDelta(), b->GetDelta(),
TEST( a->GetDelta( PADSTACK::ALL_LAYERS ), b->GetDelta( PADSTACK::ALL_LAYERS ),
wxString::Format( _( "%s trapezoid delta differs." ), PAD_DESC( a ) ) );
TEST_D( a->GetRoundRectRadiusRatio(), b->GetRoundRectRadiusRatio(),
TEST_D( a->GetRoundRectRadiusRatio( PADSTACK::ALL_LAYERS ),
b->GetRoundRectRadiusRatio( PADSTACK::ALL_LAYERS ),
wxString::Format( _( "%s rounded corners differ." ), PAD_DESC( a ) ) );
TEST_D( a->GetChamferRectRatio(), b->GetChamferRectRatio(),
TEST_D( a->GetChamferRectRatio( PADSTACK::ALL_LAYERS ),
b->GetChamferRectRatio( PADSTACK::ALL_LAYERS ),
wxString::Format( _( "%s chamfered corner sizes differ." ), PAD_DESC( a ) ) );
TEST( a->GetChamferPositions(), b->GetChamferPositions(),
TEST( a->GetChamferPositions( PADSTACK::ALL_LAYERS ),
b->GetChamferPositions( PADSTACK::ALL_LAYERS ),
wxString::Format( _( "%s chamfered corners differ." ), PAD_DESC( a ) ) );
TEST_PT( a->GetOffset(), b->GetOffset(),
TEST_PT( a->GetOffset( PADSTACK::ALL_LAYERS ), b->GetOffset( PADSTACK::ALL_LAYERS ),
wxString::Format( _( "%s shape offset from hole differs." ), PAD_DESC( a ) ) );
TEST( a->GetDrillShape(), b->GetDrillShape(),
@ -348,15 +352,17 @@ bool padNeedsUpdate( const PAD* a, const PAD* b, REPORTER* aReporter )
bool primitivesDiffer = false;
if( a->GetPrimitives().size() != b->GetPrimitives().size() )
if( a->GetPrimitives( PADSTACK::ALL_LAYERS ).size() !=
b->GetPrimitives( PADSTACK::ALL_LAYERS ).size() )
{
primitivesDiffer = true;
}
else
{
for( size_t ii = 0; ii < a->GetPrimitives().size(); ++ii )
for( size_t ii = 0; ii < a->GetPrimitives( PADSTACK::ALL_LAYERS ).size(); ++ii )
{
if( primitiveNeedsUpdate( a->GetPrimitives()[ii], b->GetPrimitives()[ii] ) )
if( primitiveNeedsUpdate( a->GetPrimitives( PADSTACK::ALL_LAYERS )[ii],
b->GetPrimitives( PADSTACK::ALL_LAYERS )[ii] ) )
{
primitivesDiffer = true;
break;

View File

@ -134,7 +134,7 @@ void DRC_TEST_PROVIDER_SOLDER_MASK::addItemToRTrees( BOARD_ITEM* aItem )
if( aItem->IsOnLayer( layer ) )
{
PAD* pad = static_cast<PAD*>( aItem );
int clearance = ( m_webWidth / 2 ) + pad->GetSolderMaskExpansion();
int clearance = ( m_webWidth / 2 ) + pad->GetSolderMaskExpansion( layer );
aItem->TransformShapeToPolygon( *solderMask->GetFill( layer ), layer, clearance,
m_maxError, ERROR_OUTSIDE );
@ -321,10 +321,12 @@ bool isNullAperture( BOARD_ITEM* aItem )
{
PAD* pad = static_cast<PAD*>( aItem );
// TODO(JE) padstacks
if( pad->GetAttribute() == PAD_ATTRIB::NPTH
&& ( pad->GetShape() == PAD_SHAPE::CIRCLE || pad->GetShape() == PAD_SHAPE::OVAL )
&& pad->GetSize().x <= pad->GetDrillSize().x
&& pad->GetSize().y <= pad->GetDrillSize().y )
&& ( pad->GetShape( PADSTACK::ALL_LAYERS ) == PAD_SHAPE::CIRCLE
|| pad->GetShape( PADSTACK::ALL_LAYERS ) == PAD_SHAPE::OVAL )
&& pad->GetSize( PADSTACK::ALL_LAYERS ).x <= pad->GetDrillSize().x
&& pad->GetSize( PADSTACK::ALL_LAYERS ).y <= pad->GetDrillSize().y )
{
return true;
}
@ -358,7 +360,7 @@ bool DRC_TEST_PROVIDER_SOLDER_MASK::checkMaskAperture( BOARD_ITEM* aMaskItem, BO
PCB_LAYER_ID aTestLayer, int aTestNet,
BOARD_ITEM** aCollidingItem )
{
if( aTestLayer == F_Mask && !aTestItem->IsOnLayer( F_Cu ) )
if( aTestLayer == F_Mask && !aTestItem->IsOnLayer( PADSTACK::ALL_LAYERS ) )
return false;
if( aTestLayer == B_Mask && !aTestItem->IsOnLayer( B_Cu ) )
@ -557,12 +559,12 @@ void DRC_TEST_PROVIDER_SOLDER_MASK::testItemAgainstItems( BOARD_ITEM* aItem, con
}
if( pad )
clearance += pad->GetSolderMaskExpansion();
clearance += pad->GetSolderMaskExpansion( PADSTACK::ALL_LAYERS );
else if( via && !via->IsTented( aRefLayer ) )
clearance += via->GetSolderMaskExpansion();
if( otherPad )
clearance += otherPad->GetSolderMaskExpansion();
clearance += otherPad->GetSolderMaskExpansion( PADSTACK::ALL_LAYERS );
else if( otherVia && !otherVia->IsTented( aRefLayer ) )
clearance += otherVia->GetSolderMaskExpansion();
@ -644,7 +646,7 @@ void DRC_TEST_PROVIDER_SOLDER_MASK::testMaskItemAgainstZones( BOARD_ITEM* aItem,
int clearance = m_board->GetDesignSettings().m_SolderMaskToCopperClearance;
if( aItem->Type() == PCB_PAD_T )
clearance += static_cast<PAD*>( aItem )->GetSolderMaskExpansion();
clearance += static_cast<PAD*>( aItem )->GetSolderMaskExpansion( PADSTACK::ALL_LAYERS );
else if( aItem->Type() == PCB_VIA_T )
clearance += static_cast<PCB_VIA*>( aItem )->GetSolderMaskExpansion();
@ -735,7 +737,7 @@ void DRC_TEST_PROVIDER_SOLDER_MASK::testMaskBridges()
// Test for aperture-to-zone collisions
testMaskItemAgainstZones( item, itemBBox, F_Mask, F_Cu );
}
else if( item->IsOnLayer( F_Cu ) )
else if( item->IsOnLayer( PADSTACK::ALL_LAYERS ) )
{
// Test for copper-item-to-aperture collisions
testItemAgainstItems( item, itemBBox, F_Cu, F_Mask );
@ -777,7 +779,7 @@ bool DRC_TEST_PROVIDER_SOLDER_MASK::Run()
for( FOOTPRINT* footprint : m_board->Footprints() )
{
for( PAD* pad : footprint->Pads() )
m_largestClearance = std::max( m_largestClearance, pad->GetSolderMaskExpansion() );
m_largestClearance = std::max( m_largestClearance, pad->GetSolderMaskExpansion( PADSTACK::ALL_LAYERS ) );
}
// Order is important here: m_webWidth must be added in before m_largestCourtyardClearance is

View File

@ -119,13 +119,14 @@ static void build_pad_testpoints( BOARD *aPcb, std::vector <D356_RECORD>& aRecor
rk.mechanical = ( pad->GetAttribute() == PAD_ATTRIB::NPTH );
rk.x_location = pad->GetPosition().x - origin.x;
rk.y_location = origin.y - pad->GetPosition().y;
rk.x_size = pad->GetSize().x;
// TODO(JE) padstacks
rk.x_size = pad->GetSize( PADSTACK::ALL_LAYERS ).x;
// Rule: round pads have y = 0
if( pad->GetShape() == PAD_SHAPE::CIRCLE )
if( pad->GetShape( PADSTACK::ALL_LAYERS ) == PAD_SHAPE::CIRCLE )
rk.y_size = 0;
else
rk.y_size = pad->GetSize().y;
rk.y_size = pad->GetSize( PADSTACK::ALL_LAYERS ).y;
rk.rotation = - pad->GetOrientation().AsDegrees();

View File

@ -314,7 +314,7 @@ void GENCAD_EXPORTER::CreatePadsShapesSection()
for( unsigned i = 0; i<pads.size(); ++i )
{
PAD* pad = pads[i];
const VECTOR2I& off = pad->GetOffset();
const VECTOR2I& off = pad->GetOffset( PADSTACK::ALL_LAYERS );
pad->SetSubRatsnest( pad_name_number );
@ -331,13 +331,13 @@ void GENCAD_EXPORTER::CreatePadsShapesSection()
fprintf( m_file, "PAD P%d", pad->GetSubRatsnest() );
padstacks.push_back( pad ); // Will have its own padstack later
int dx = pad->GetSize().x / 2;
int dy = pad->GetSize().y / 2;
int dx = pad->GetSize( PADSTACK::ALL_LAYERS ).x / 2;
int dy = pad->GetSize( PADSTACK::ALL_LAYERS ).y / 2;
switch( pad->GetShape() )
switch( pad->GetShape( PADSTACK::ALL_LAYERS ) )
{
default:
UNIMPLEMENTED_FOR( pad->ShowPadShape() );
UNIMPLEMENTED_FOR( pad->ShowPadShape( PADSTACK::ALL_LAYERS ) );
KI_FALLTHROUGH;
case PAD_SHAPE::CIRCLE:
@ -348,7 +348,7 @@ void GENCAD_EXPORTER::CreatePadsShapesSection()
fprintf( m_file, "CIRCLE %g %g %g\n",
off.x / SCALE_FACTOR,
-off.y / SCALE_FACTOR,
pad->GetSize().x / (SCALE_FACTOR * 2) );
pad->GetSize( PADSTACK::ALL_LAYERS ).x / (SCALE_FACTOR * 2) );
break;
case PAD_SHAPE::RECTANGLE:
@ -365,12 +365,12 @@ void GENCAD_EXPORTER::CreatePadsShapesSection()
case PAD_SHAPE::ROUNDRECT:
case PAD_SHAPE::OVAL:
{
const VECTOR2I& size = pad->GetSize();
const VECTOR2I& size = pad->GetSize( PADSTACK::ALL_LAYERS );
int radius = std::min( size.x, size.y ) / 2;
if( pad->GetShape() == PAD_SHAPE::ROUNDRECT )
if( pad->GetShape( PADSTACK::ALL_LAYERS ) == PAD_SHAPE::ROUNDRECT )
{
radius = pad->GetRoundRectCornerRadius();
radius = pad->GetRoundRectCornerRadius( PADSTACK::ALL_LAYERS );
}
int lineX = size.x / 2 - radius;
@ -455,8 +455,8 @@ void GENCAD_EXPORTER::CreatePadsShapesSection()
{
fprintf( m_file, " POLYGON %g\n", pad->GetDrillSize().x / SCALE_FACTOR );
int ddx = pad->GetDelta().x / 2;
int ddy = pad->GetDelta().y / 2;
int ddx = pad->GetDelta( PADSTACK::ALL_LAYERS ).x / 2;
int ddy = pad->GetDelta( PADSTACK::ALL_LAYERS ).y / 2;
VECTOR2I poly[4];
poly[0] = VECTOR2I( -dx + ddy, dy + ddx );
@ -485,12 +485,13 @@ void GENCAD_EXPORTER::CreatePadsShapesSection()
int maxError = m_board->GetDesignSettings().m_MaxError;
VECTOR2I padOffset( 0, 0 );
TransformRoundChamferedRectToPolygon( outline, padOffset, pad->GetSize(),
TransformRoundChamferedRectToPolygon( outline, padOffset,
pad->GetSize( PADSTACK::ALL_LAYERS ),
pad->GetOrientation(),
pad->GetRoundRectCornerRadius(),
pad->GetChamferRectRatio(),
pad->GetChamferPositions(), 0, maxError,
ERROR_INSIDE );
pad->GetRoundRectCornerRadius( PADSTACK::ALL_LAYERS ),
pad->GetChamferRectRatio( PADSTACK::ALL_LAYERS ),
pad->GetChamferPositions( PADSTACK::ALL_LAYERS ),
0, maxError, ERROR_INSIDE );
for( int jj = 0; jj < outline.OutlineCount(); ++jj )
{
@ -516,7 +517,7 @@ void GENCAD_EXPORTER::CreatePadsShapesSection()
fprintf( m_file, " POLYGON %g\n", pad->GetDrillSize().x / SCALE_FACTOR );
SHAPE_POLY_SET outline;
pad->MergePrimitivesAsPolygon( &outline );
pad->MergePrimitivesAsPolygon( F_Cu, &outline );
for( int jj = 0; jj < outline.OutlineCount(); ++jj )
{

View File

@ -212,9 +212,10 @@ private:
HYPERLYNX_PAD_STACK::HYPERLYNX_PAD_STACK( BOARD* aBoard, const PAD* aPad )
{
// TODO(JE) padstacks
m_board = aBoard;
m_sx = aPad->GetSize().x;
m_sy = aPad->GetSize().y;
m_sx = aPad->GetSize( PADSTACK::ALL_LAYERS ).x;
m_sy = aPad->GetSize( PADSTACK::ALL_LAYERS ).y;
m_angle = 180.0 - aPad->GetOrientation().AsDegrees();
if( m_angle < 0.0 )
@ -222,7 +223,7 @@ HYPERLYNX_PAD_STACK::HYPERLYNX_PAD_STACK( BOARD* aBoard, const PAD* aPad )
m_layers = aPad->GetLayerSet();
m_drill = aPad->GetDrillSize().x;
m_shape = aPad->GetShape();
m_shape = aPad->GetShape( PADSTACK::ALL_LAYERS );
m_type = PAD_ATTRIB::PTH;
m_id = 0;
}

View File

@ -400,9 +400,10 @@ std::string PLACE_FILE_EXPORTER::GenReportData()
if( pad->GetLayerSet()[F_Cu] )
layer |= 2;
// TODO(JE) padstacks
static const char* layer_name[4] = { "nocopper", "back", "front", "both" };
snprintf( line, sizeof(line), "Shape %s Layer %s\n",
TO_UTF8( pad->ShowPadShape() ),
TO_UTF8( pad->ShowPadShape( PADSTACK::ALL_LAYERS ) ),
layer_name[layer] );
buffer += line;
@ -411,8 +412,8 @@ std::string PLACE_FILE_EXPORTER::GenReportData()
snprintf( line, sizeof(line), "position %9.6f %9.6f size %9.6f %9.6f orientation %.2f\n",
padPos.x * conv_unit,
padPos.y * conv_unit,
pad->GetSize().x * conv_unit,
pad->GetSize().y * conv_unit,
pad->GetSize( PADSTACK::ALL_LAYERS ).x * conv_unit,
pad->GetSize( PADSTACK::ALL_LAYERS ).y * conv_unit,
( pad->GetOrientation() - footprint->GetOrientation() ).AsDegrees() );
buffer += line;
@ -420,8 +421,8 @@ std::string PLACE_FILE_EXPORTER::GenReportData()
buffer += line;
snprintf( line, sizeof(line), "shape_offset %9.6f %9.6f\n",
pad->GetOffset().x * conv_unit,
pad->GetOffset().y * conv_unit );
pad->GetOffset( PADSTACK::ALL_LAYERS ).x * conv_unit,
pad->GetOffset( PADSTACK::ALL_LAYERS ).y * conv_unit );
buffer += line;
buffer += "$EndPAD\n";

View File

@ -206,9 +206,10 @@ bool EXPORTER_STEP::buildFootprint3DShapes( FOOTPRINT* aFootprint, VECTOR2D aOri
continue;
SHAPE_POLY_SET poly;
pad->TransformShapeToPolygon( poly, pcblayer, pad->GetSolderMaskExpansion(),
maxError, ERROR_INSIDE );
PCB_LAYER_ID cuLayer = ( pcblayer == F_Mask ) ? F_Cu : B_Cu;
pad->TransformShapeToPolygon( poly, cuLayer,
pad->GetSolderMaskExpansion( cuLayer ), maxError,
ERROR_INSIDE );
m_poly_shapes[pcblayer].Append( poly );
}
@ -245,7 +246,7 @@ bool EXPORTER_STEP::buildFootprint3DShapes( FOOTPRINT* aFootprint, VECTOR2D aOri
if( !pad->IsOnLayer( pcblayer ) )
continue;
std::shared_ptr<SHAPE_POLY_SET> padPoly = pad->GetEffectivePolygon();
std::shared_ptr<SHAPE_POLY_SET> padPoly = pad->GetEffectivePolygon( pcblayer );
SHAPE_POLY_SET gfxPoly( poly );
if( padPoly->Collide( &gfxPoly ) )

Some files were not shown because too many files have changed in this diff Show More