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:
parent
b255816000
commit
56e0811516
3d-viewer/3d_canvas
api/proto/board
common
include
pcbnew
api
autorouter
board.cppboard_design_settings.cppconnectivity
convert_shape_list_to_polygon.cppdialogs
drc
drc_test_provider_annular_width.cppdrc_test_provider_copper_clearance.cppdrc_test_provider_library_parity.cppdrc_test_provider_solder_mask.cpp
exporters
footprint.cppfootprint.hmicrowave
pad.cpppad.hpad_custom_shape_functions.cpppadstack.cpppadstack.hpcb_io
altium
cadstar
eagle
easyeda
easyedapro
fabmaster
geda
ipc2581
kicad_legacy
kicad_sexpr
odbpp
pcad
python/swig
router
specctra_import_export
teardrop
tools
convert_tool.cppedit_tool.cppitem_modification_routine.cpppad_tool.cpppcb_grid_helper.cpppcb_point_editor.cpppcb_selection_tool.cpp
tracks_cleaner.cppzone_filler.cppqa
@ -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;
|
||||
|
@ -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++ )
|
||||
|
@ -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 );
|
||||
}
|
||||
}
|
||||
|
@ -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;
|
||||
|
@ -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 )
|
||||
|
@ -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
|
||||
|
@ -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 );
|
||||
|
||||
|
@ -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 )
|
||||
|
@ -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:
|
||||
|
@ -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 )
|
||||
|
@ -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 )
|
||||
|
@ -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 ) );
|
||||
}
|
||||
|
@ -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() )
|
||||
{
|
||||
|
@ -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() )
|
||||
|
@ -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" ),
|
||||
|
@ -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
|
||||
|
@ -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,
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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;
|
||||
|
@ -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
|
||||
|
@ -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();
|
||||
|
||||
|
@ -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 )
|
||||
{
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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";
|
||||
|
@ -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
Loading…
Reference in New Issue
Block a user