7
mirror of https://gitlab.com/kicad/code/kicad.git synced 2025-04-07 21:25:31 +00:00

Step export: handle castellated pads.

Only pads having the fab property "Castellated" are handled.
This commit is contained in:
jean-pierre charras 2025-03-17 11:14:53 +01:00
parent 1848401d5b
commit 60f65e68c1
4 changed files with 101 additions and 15 deletions

View File

@ -155,7 +155,8 @@ EXPORTER_STEP::~EXPORTER_STEP()
}
bool EXPORTER_STEP::buildFootprint3DShapes( FOOTPRINT* aFootprint, VECTOR2D aOrigin )
bool EXPORTER_STEP::buildFootprint3DShapes( FOOTPRINT* aFootprint, VECTOR2D aOrigin,
SHAPE_POLY_SET* aClipPolygon )
{
bool hasdata = false;
std::vector<PAD*> padsMatchingNetFilter;
@ -164,6 +165,7 @@ bool EXPORTER_STEP::buildFootprint3DShapes( FOOTPRINT* aFootprint, VECTOR2D aOri
// Dump the pad holes into the PCB
for( PAD* pad : aFootprint->Pads() )
{
bool castellated = pad->GetProperty() == PAD_PROP::CASTELLATED;
std::shared_ptr<SHAPE_SEGMENT> holeShape = pad->GetEffectiveHoleShape();
SHAPE_POLY_SET holePoly;
@ -198,7 +200,8 @@ bool EXPORTER_STEP::buildFootprint3DShapes( FOOTPRINT* aFootprint, VECTOR2D aOri
if( m_params.m_ExportPads )
{
if( m_pcbModel->AddPadShape( pad, aOrigin, false ) )
if( m_pcbModel->AddPadShape( pad, aOrigin, false,
castellated ? aClipPolygon : nullptr) )
hasdata = true;
if( m_params.m_ExportSoldermask )
@ -603,6 +606,9 @@ bool EXPORTER_STEP::buildBoard3DShapes()
wxLogWarning( _( "Board outline is malformed. Run DRC for a full analysis." ) );
}
SHAPE_POLY_SET pcbOutlinesNoArcs = pcbOutlines;
pcbOutlinesNoArcs.ClearArcs();
VECTOR2D origin;
// Determine the coordinate system reference:
@ -640,7 +646,7 @@ bool EXPORTER_STEP::buildBoard3DShapes()
// For copper layers, only pads and tracks are added, because adding everything on copper
// generate unreasonable file sizes and take a unreasonable calculation time.
for( FOOTPRINT* fp : m_board->Footprints() )
buildFootprint3DShapes( fp, origin );
buildFootprint3DShapes( fp, origin, &pcbOutlinesNoArcs );
for( PCB_TRACK* track : m_board->Tracks() )
buildTrack3DShape( track, origin );
@ -653,9 +659,6 @@ bool EXPORTER_STEP::buildBoard3DShapes()
buildZones3DShape( origin );
}
SHAPE_POLY_SET pcbOutlinesNoArcs = pcbOutlines;
pcbOutlinesNoArcs.ClearArcs();
for( PCB_LAYER_ID pcblayer : m_layersToExport.Seq() )
{
SHAPE_POLY_SET poly = m_poly_shapes[pcblayer];

View File

@ -58,7 +58,7 @@ public:
private:
bool buildBoard3DShapes();
bool buildFootprint3DShapes( FOOTPRINT* aFootprint, VECTOR2D aOrigin );
bool buildFootprint3DShapes( FOOTPRINT* aFootprint, VECTOR2D aOrigin, SHAPE_POLY_SET* aClipPolygon );
bool buildTrack3DShape( PCB_TRACK* aTrack, VECTOR2D aOrigin );
void buildZones3DShape( VECTOR2D aOrigin );
bool buildGraphic3DShape( BOARD_ITEM* aItem, VECTOR2D aOrigin );

View File

@ -125,6 +125,7 @@
#endif
#include <macros.h>
#include <convert_basic_shapes_to_polygon.h>
static constexpr double USER_PREC = 1e-4;
static constexpr double USER_ANGLE_PREC = 1e-6;
@ -783,10 +784,12 @@ STEP_PCB_MODEL::~STEP_PCB_MODEL()
}
bool STEP_PCB_MODEL::AddPadShape( const PAD* aPad, const VECTOR2D& aOrigin, bool aVia )
bool STEP_PCB_MODEL::AddPadShape( const PAD* aPad, const VECTOR2D& aOrigin, bool aVia,
SHAPE_POLY_SET* aClipPolygon )
{
bool success = true;
std::vector<TopoDS_Shape> padShapes;
bool castellated = aClipPolygon && aPad->GetProperty() == PAD_PROP::CASTELLATED;
for( PCB_LAYER_ID pcb_layer : aPad->GetLayerSet().Seq() )
{
@ -817,6 +820,12 @@ bool STEP_PCB_MODEL::AddPadShape( const PAD* aPad, const VECTOR2D& aOrigin, bool
SHAPE_POLY_SET polySet;
aPad->TransformShapeToPolygon( polySet, pcb_layer, 0, ARC_HIGH_DEF, ERROR_INSIDE );
if( castellated )
{
polySet.ClearArcs();
polySet.BooleanIntersection( *aClipPolygon );
}
success &= MakeShapes( padShapes, polySet, m_simplifyShapes, thickness, Zpos, aOrigin );
if( testShape.IsNull() )
@ -862,20 +871,56 @@ bool STEP_PCB_MODEL::AddPadShape( const PAD* aPad, const VECTOR2D& aOrigin, bool
getLayerZPlacement( B_Cu, b_pos, b_thickness );
double top = std::max( f_pos, f_pos + f_thickness );
double bottom = std::min( b_pos, b_pos + b_thickness );
double hole_height = top - bottom;
TopoDS_Shape plating;
std::shared_ptr<SHAPE_SEGMENT> seg_hole = aPad->GetEffectiveHoleShape();
double width = std::min( aPad->GetDrillSize().x, aPad->GetDrillSize().y );
if( MakeShapeAsThickSegment( plating, seg_hole->GetSeg().A, seg_hole->GetSeg().B, width,
( top - bottom ), bottom, aOrigin ) )
if( !castellated )
{
padShapes.push_back( plating );
if( MakeShapeAsThickSegment( plating, seg_hole->GetSeg().A, seg_hole->GetSeg().B, width,
hole_height, bottom, aOrigin ) )
{
padShapes.push_back( plating );
}
else
{
success = false;
}
}
else
{
success = false;
// Note:
// the truncated hole shape is exported as a vertical filled shape. The hole itself
// will be removed later, when all holes are removed from the board
SHAPE_POLY_SET polyHole;
if( seg_hole->GetSeg().A == seg_hole->GetSeg().B ) // Hole is a circle
{
TransformCircleToPolygon( polyHole, seg_hole->GetSeg().A, width/2,
ARC_HIGH_DEF, ERROR_OUTSIDE );
}
else
{
TransformOvalToPolygon( polyHole,
seg_hole->GetSeg().A, seg_hole->GetSeg().B,
width, ARC_HIGH_DEF, ERROR_OUTSIDE );
}
polyHole.ClearArcs();
polyHole.BooleanIntersection( *aClipPolygon );
if( MakePolygonAsWall( plating, polyHole, hole_height, bottom, aOrigin ) )
{
padShapes.push_back( plating );
}
else
{
success = false;
}
}
}
@ -1382,6 +1427,25 @@ bool STEP_PCB_MODEL::MakeShapeAsThickSegment( TopoDS_Shape& aShape,
}
bool STEP_PCB_MODEL::MakePolygonAsWall( TopoDS_Shape& aShape,
SHAPE_POLY_SET& aPolySet,
double aHeight,
double aZposition, const VECTOR2D& aOrigin )
{
std::vector<TopoDS_Shape> testShapes;
bool success = MakeShapes( testShapes, aPolySet, m_simplifyShapes,
aHeight, aZposition, aOrigin );
if( testShapes.size() > 0 )
aShape = testShapes.front();
else
success = false;
return success;
}
static wxString formatBBox( const BOX2I& aBBox )
{
wxString str;
@ -1557,7 +1621,8 @@ static bool makeWireFromChain( BRepLib_MakeWire& aMkWire, const SHAPE_LINE_CHAIN
}
bool STEP_PCB_MODEL::MakeShapes( std::vector<TopoDS_Shape>& aShapes, const SHAPE_POLY_SET& aPolySet, bool aConvertToArcs,
bool STEP_PCB_MODEL::MakeShapes( std::vector<TopoDS_Shape>& aShapes, const SHAPE_POLY_SET& aPolySet,
bool aConvertToArcs,
double aThickness, double aZposition, const VECTOR2D& aOrigin )
{
SHAPE_POLY_SET workingPoly = aPolySet;

View File

@ -97,7 +97,10 @@ public:
void SpecializeVariant( OUTPUT_FORMAT aVariant ) { m_outFmt = aVariant; }
// add a pad shape (must be in final position)
bool AddPadShape( const PAD* aPad, const VECTOR2D& aOrigin, bool aVia );
// if aClipPolygon is not nullptr, the pad shape will be clipped by aClipPolygon
// (usually aClipPolygon is the board outlines and use for castelleted pads)
bool AddPadShape( const PAD* aPad, const VECTOR2D& aOrigin, bool aVia,
SHAPE_POLY_SET* aClipPolygon = nullptr );
// add a pad hole or slot (must be in final position)
bool AddHole( const SHAPE_SEGMENT& aShape, int aPlatingThickness, PCB_LAYER_ID aLayerTop,
@ -138,7 +141,7 @@ public:
/**
* Convert a SHAPE_POLY_SET to TopoDS_Shape's (polygonal vertical prisms, or flat faces)
* @param aShapes is the TopoDS_Shape list to append to
* @param aPolySet is a polygon set
* @param aPolySet is the polygon set
* @param aConvertToArcs set to approximate with arcs
* @param aThickness is the height of the created prism, or 0.0: flat face pointing up, -0.0: down.
* @param aOrigin is the origin of the coordinates
@ -164,6 +167,21 @@ public:
double aWidth, double aThickness, double aZposition,
const VECTOR2D& aOrigin );
/**
* Make a polygonal shape to create a vertical wall.
* It is a specialized version of MakeShape()
* @param aShape is the TopoDS_Shape to initialize (must be empty)
* @param aPolySet is the outline of the wall
* @param aHeight is the height of the wall.
* @param aZposition is the Z postion of the wall
* @param aOrigin is the origin of the coordinates
* @return true if success
*/
bool MakePolygonAsWall( TopoDS_Shape& aShape,
SHAPE_POLY_SET& aPolySet,
double aHeight,
double aZposition, const VECTOR2D& aOrigin );
#ifdef SUPPORTS_IGES
// write the assembly model in IGES format
bool WriteIGES( const wxString& aFileName );