diff --git a/pcbnew/exporters/export_gencad.cpp b/pcbnew/exporters/export_gencad.cpp index 0884e29aec..d9f588f410 100644 --- a/pcbnew/exporters/export_gencad.cpp +++ b/pcbnew/exporters/export_gencad.cpp @@ -63,8 +63,8 @@ static void CreateShapesSection( FILE* aFile, BOARD* aPcb ); static void CreatePadsShapesSection( FILE* aFile, BOARD* aPcb ); static void FootprintWriteShape( FILE* File, FOOTPRINT* aFootprint, const wxString& aShapeName ); -// layer names for Gencad export +// layer names for Gencad export static std::string GenCADLayerName( int aCuCount, PCB_LAYER_ID aId ) { if( IsCopperLayer( aId ) ) @@ -179,6 +179,7 @@ static std::string fmt_mask( LSET aSet ) return StrPrintf( "%08x", (unsigned) ( aSet & LSET::AllCuMask() ).to_ulong() ); } + // Export options static bool flipBottomPads; static bool uniquePins; @@ -192,6 +193,7 @@ static int GencadOffsetX, GencadOffsetY; static std::map<FOOTPRINT*, int> componentShapes; static std::map<int, wxString> shapeNames; + static const wxString getShapeName( FOOTPRINT* aFootprint ) { static const wxString invalid( "invalid" ); @@ -208,9 +210,11 @@ static const wxString getShapeName( FOOTPRINT* aFootprint ) return itName->second; } + // GerbTool chokes on units different than INCH so this is the conversion factor const static double SCALE_FACTOR = 1000.0 * IU_PER_MILS; + /* Two helper functions to calculate coordinates of footprints in gencad values * (GenCAD Y axis from bottom to top) */ @@ -398,7 +402,6 @@ static void CreatePadsShapesSection( FILE* aFile, BOARD* aPcb ) vias.end() ); // Emit vias pads - for( PCB_VIA* via : vias ) { viastacks.push_back( via ); @@ -420,8 +423,10 @@ static void CreatePadsShapesSection( FILE* aFile, BOARD* aPcb ) pad->SetSubRatsnest( pad_name_number ); + // @warning: This code is not 100% correct. The #PAD::Compare function does not test + // custom pad primitives so there may be duplicate custom pads in the export. if( old_pad && 0 == PAD::Compare( old_pad, pad ) ) - continue; // already created + continue; old_pad = pad; @@ -443,6 +448,7 @@ static void CreatePadsShapesSection( FILE* aFile, BOARD* aPcb ) case PAD_SHAPE::CIRCLE: fprintf( aFile, " ROUND %g\n", pad->GetDrillSize().x / SCALE_FACTOR ); + /* Circle is center, radius */ fprintf( aFile, "CIRCLE %g %g %g\n", off.x / SCALE_FACTOR, @@ -582,21 +588,14 @@ static void CreatePadsShapesSection( FILE* aFile, BOARD* aPcb ) SHAPE_POLY_SET outline; int maxError = aPcb->GetDesignSettings().m_MaxError; + wxPoint padOffset( 0, 0 ); - TransformRoundChamferedRectToPolygon( outline, pad->GetPosition(), pad->GetSize(), - pad->GetOrientation(), pad->GetRoundRectCornerRadius(), - pad->GetChamferRectRatio(), pad->GetChamferPositions(), 0, maxError, - ERROR_INSIDE ); - - // The chamfered rectangle polygon code calculates the absolute board position so - // the footprint position has to be subtracted off polygon points to get the - // pad position relative to the footprint. - FOOTPRINT* parent = pad->GetParent(); - - wxPoint parentPos( 0, 0 ); - - if( parent ) - parentPos = parent->GetPosition(); + TransformRoundChamferedRectToPolygon( outline, padOffset, pad->GetSize(), + pad->GetOrientation(), + pad->GetRoundRectCornerRadius(), + pad->GetChamferRectRatio(), + pad->GetChamferPositions(), 0, maxError, + ERROR_INSIDE ); for( int jj = 0; jj < outline.OutlineCount(); ++jj ) { @@ -607,10 +606,10 @@ static void CreatePadsShapesSection( FILE* aFile, BOARD* aPcb ) { int next = ( ii + 1 ) % pointCount; fprintf( aFile, "LINE %g %g %g %g\n", - ( -parentPos.x + off.x + poly.CPoint( ii ).x ) / SCALE_FACTOR, - ( parentPos.y - off.y - poly.CPoint( ii ).y ) / SCALE_FACTOR, - ( -parentPos.x + off.x + poly.CPoint( next ).x ) / SCALE_FACTOR, - ( parentPos.y - off.y - poly.CPoint( next ).y ) / SCALE_FACTOR ); + poly.CPoint( ii ).x / SCALE_FACTOR, + -poly.CPoint( ii ).y / SCALE_FACTOR, + poly.CPoint( next ).x / SCALE_FACTOR, + -poly.CPoint( next ).y / SCALE_FACTOR ); } } diff --git a/pcbnew/pad.cpp b/pcbnew/pad.cpp index 27206eb622..079bf0d3f8 100644 --- a/pcbnew/pad.cpp +++ b/pcbnew/pad.cpp @@ -1032,48 +1032,67 @@ bool PAD::HitTest( const EDA_RECT& aRect, bool aContained, int aAccuracy ) const } -int PAD::Compare( const PAD* padref, const PAD* padcmp ) +int PAD::Compare( const PAD* aPadRef, const PAD* aPadCmp ) { int diff; - if( ( diff = static_cast<int>( padref->GetShape() ) - - static_cast<int>( padcmp->GetShape() ) ) != 0 ) + if( ( diff = static_cast<int>( aPadRef->GetShape() ) - + static_cast<int>( aPadCmp->GetShape() ) ) != 0 ) return diff; - if( ( diff = padref->GetDrillShape() - padcmp->GetDrillShape() ) != 0) + if( ( diff = static_cast<int>( aPadRef->m_attribute ) - + static_cast<int>( aPadCmp->m_attribute ) ) != 0 ) return diff; - if( ( diff = padref->m_drill.x - padcmp->m_drill.x ) != 0 ) + if( ( diff = aPadRef->m_drillShape - aPadCmp->m_drillShape ) != 0 ) return diff; - if( ( diff = padref->m_drill.y - padcmp->m_drill.y ) != 0 ) + if( ( diff = aPadRef->m_drill.x - aPadCmp->m_drill.x ) != 0 ) return diff; - if( ( diff = padref->m_size.x - padcmp->m_size.x ) != 0 ) + if( ( diff = aPadRef->m_drill.y - aPadCmp->m_drill.y ) != 0 ) return diff; - if( ( diff = padref->m_size.y - padcmp->m_size.y ) != 0 ) + if( ( diff = aPadRef->m_size.x - aPadCmp->m_size.x ) != 0 ) return diff; - if( ( diff = padref->m_offset.x - padcmp->m_offset.x ) != 0 ) + if( ( diff = aPadRef->m_size.y - aPadCmp->m_size.y ) != 0 ) return diff; - if( ( diff = padref->m_offset.y - padcmp->m_offset.y ) != 0 ) + if( ( diff = aPadRef->m_offset.x - aPadCmp->m_offset.x ) != 0 ) return diff; - if( ( diff = padref->m_deltaSize.x - padcmp->m_deltaSize.x ) != 0 ) + if( ( diff = aPadRef->m_offset.y - aPadCmp->m_offset.y ) != 0 ) return diff; - if( ( diff = padref->m_deltaSize.y - padcmp->m_deltaSize.y ) != 0 ) + if( ( diff = aPadRef->m_deltaSize.x - aPadCmp->m_deltaSize.x ) != 0 ) return diff; - // TODO: test custom shapes + if( ( diff = aPadRef->m_deltaSize.y - aPadCmp->m_deltaSize.y ) != 0 ) + return diff; + + if( ( diff = aPadRef->m_roundedCornerScale - aPadCmp->m_roundedCornerScale ) != 0 ) + return diff; + + if( ( diff = aPadRef->m_chamferPositions - aPadCmp->m_chamferPositions ) != 0 ) + return diff; + + if( ( diff = aPadRef->m_chamferScale - aPadCmp->m_chamferScale ) != 0 ) + return diff; + + if( ( diff = static_cast<int>( aPadRef->m_editPrimitives.size() ) - + static_cast<int>( aPadCmp->m_editPrimitives.size() ) ) != 0 ) + return diff; + + // @todo: Compare custom pad primitives for pads that have the same number of primitives + // here. Currently there is no compare function for PCB_SHAPE objects. // Dick: specctra_export needs this // Lorenzo: gencad also needs it to implement padstacks! #if __cplusplus >= 201103L - long long d = padref->m_layerMask.to_ullong() - padcmp->m_layerMask.to_ullong(); + long long d = aPadRef->m_layerMask.to_ullong() - aPadCmp->m_layerMask.to_ullong(); + if( d < 0 ) return -1; else if( d > 0 ) @@ -1082,8 +1101,8 @@ int PAD::Compare( const PAD* padref, const PAD* padcmp ) return 0; #else // these strings are not typically constructed, since we don't get here often. - std::string s1 = padref->m_layerMask.to_string(); - std::string s2 = padcmp->m_layerMask.to_string(); + std::string s1 = aPadRef->m_layerMask.to_string(); + std::string s2 = aPadCmp->m_layerMask.to_string(); return s1.compare( s2 ); #endif } diff --git a/pcbnew/pad.h b/pcbnew/pad.h index 7c8151ca17..252e8b9b46 100644 --- a/pcbnew/pad.h +++ b/pcbnew/pad.h @@ -612,7 +612,7 @@ public: * @return less than 0 if left less than right, 0 if equal, or greater than 0 if left * greater than right. */ - static int Compare( const PAD* padref, const PAD* padcmp ); + static int Compare( const PAD* aPadRef, const PAD* aPadCmp ); void Move( const wxPoint& aMoveVector ) override {