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:
parent
1848401d5b
commit
60f65e68c1
pcbnew/exporters/step
@ -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];
|
||||
|
@ -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 );
|
||||
|
@ -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;
|
||||
|
@ -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 );
|
||||
|
Loading…
Reference in New Issue
Block a user