From a7a7f62cb7bc3b7d7b2e1d787d3d17c47f2e2b9f Mon Sep 17 00:00:00 2001 From: jean-pierre charras Date: Sat, 3 Feb 2018 18:50:55 +0100 Subject: [PATCH] Specctra export: export roundrect pads with the right shape --- .../specctra_export.cpp | 67 ++++++++++++++++++- .../specctra_import.cpp | 2 +- 2 files changed, 67 insertions(+), 2 deletions(-) diff --git a/pcbnew/specctra_import_export/specctra_export.cpp b/pcbnew/specctra_import_export/specctra_export.cpp index c8441c1833..f87eaf83b2 100644 --- a/pcbnew/specctra_import_export/specctra_export.cpp +++ b/pcbnew/specctra_import_export/specctra_export.cpp @@ -55,6 +55,7 @@ #include #include +#include #include "specctra.h" @@ -489,6 +490,70 @@ PADSTACK* SPECCTRA_DB::makePADSTACK( BOARD* aBoard, D_PAD* aPad ) } break; + case PAD_SHAPE_ROUNDRECT: + { + // Export the shape as as polygon, round rect does not exist as primitive + const int circleToSegmentsCount = 36; + int rradius = aPad->GetRoundRectCornerRadius(); + SHAPE_POLY_SET cornerBuffer; + // Use a slightly bigger shape because the round corners are approximated by + // segments, giving to the polygon a slightly smaller shape than the actual shape + + /* calculates the coeff to compensate radius reduction of holes clearance + * due to the segment approx. + * For a circle the min radius is radius * cos( 2PI / s_CircleToSegmentsCount / 2) + * correctionFactor is 1 /cos( PI/s_CircleToSegmentsCount ) + */ + double correctionFactor = 1.0 / cos( M_PI / (double) circleToSegmentsCount ); + int extra_clearance = KiROUND( rradius * (1.0 - correctionFactor ) ) + 1; + wxSize psize = aPad->GetSize(); + psize.x += extra_clearance*2; + psize.y += extra_clearance*2; + rradius += extra_clearance; + TransformRoundRectToPolygon( cornerBuffer, wxPoint(0,0), psize, + 0, rradius, circleToSegmentsCount ); + SHAPE_LINE_CHAIN& polygonal_shape = cornerBuffer.Outline( 0 ); + + for( int ndx=0; ndx < reportedLayers; ++ndx ) + { + SHAPE* shape = new SHAPE( padstack ); + + padstack->Append( shape ); + + // a T_polygon exists as a PATH + PATH* polygon = new PATH( shape, T_polygon ); + + shape->SetShape( polygon ); + + polygon->SetLayerId( layerName[ndx] ); + // append a closed polygon + POINT first_corner; + + for( int idx = 0; idx < polygonal_shape.PointCount(); idx++ ) + { + POINT corner( scale( polygonal_shape.Point( idx ).x ), + scale( -polygonal_shape.Point( idx ).y ) ); + corner += dsnOffset; + polygon->AppendPoint( corner ); + + if( idx == 0 ) + first_corner = corner; + } + polygon->AppendPoint( first_corner ); // Close polygon + } + + // this string _must_ be unique for a given physical shape + snprintf( name, sizeof(name), "RoundRect%sPad_%.6gx%.6g_%.6g_um", + uniqifier.c_str(), + IU2um( aPad->GetSize().x ), + IU2um( aPad->GetSize().y ), IU2um( rradius ) ); + + name[ sizeof(name) - 1 ] = 0; + + padstack->SetPadstackId( name ); + } + break; + case PAD_SHAPE_CUSTOM: { std::vector polygonal_shape; @@ -519,7 +584,7 @@ PADSTACK* SPECCTRA_DB::makePADSTACK( BOARD* aBoard, D_PAD* aPad ) polygon->SetLayerId( layerName[ndx] ); - for( unsigned idx = 0; idx <= polygonal_shape.size(); idx++ ) + for( unsigned idx = 0; idx < polygonal_shape.size(); idx++ ) { POINT corner( scale( polygonal_shape[idx].x ), scale( -polygonal_shape[idx].y ) ); corner += dsnOffset; diff --git a/pcbnew/specctra_import_export/specctra_import.cpp b/pcbnew/specctra_import_export/specctra_import.cpp index 95135c13bb..bde0d58ed8 100644 --- a/pcbnew/specctra_import_export/specctra_import.cpp +++ b/pcbnew/specctra_import_export/specctra_import.cpp @@ -152,7 +152,7 @@ namespace DSN { * @param distance The session file length to convert. * @param aResolution The session UNIT_RES which holds the engineering unit * specifier - * @return int - The KiCad length in deci-mils + * @return int - The KiCad length in internal unit */ static int scale( double distance, UNIT_RES* aResolution ) {