diff --git a/pcbnew/router/pns_kicad_iface.cpp b/pcbnew/router/pns_kicad_iface.cpp index 380794eed7..4b429fc170 100644 --- a/pcbnew/router/pns_kicad_iface.cpp +++ b/pcbnew/router/pns_kicad_iface.cpp @@ -647,7 +647,31 @@ std::unique_ptr PNS_KICAD_IFACE_BASE::syncPad( D_PAD* aPad ) solid->SetPos( VECTOR2I( c.x - offset.x, c.y - offset.y ) ); solid->SetOffset( VECTOR2I( offset.x, offset.y ) ); - solid->SetShape( aPad->GetEffectiveShape()->Clone() ); + + + auto shapes = std::dynamic_pointer_cast( aPad->GetEffectiveShape() ); + + if( shapes && shapes->Size() == 1 ) + { + solid->SetShape( shapes->Clone() ); + } + else + { + // Fixme (but not urgent). For complex pad shapes, we pass a single simple polygon to the + // router, otherwise it won't know how to correctly build walkaround 'hulls' for the pad + // primitives - it can recognize only simple shapes, but not COMPOUNDs made of multiple shapes. + // The proper way to fix this would be to implement SHAPE_COMPOUND::ConvertToSimplePolygon(), + // but the complexity of pad polygonization code (see D_PAD::GetEffectivePolygon), including approximation + // error handling makes me slightly scared to do it right now. + + const std::shared_ptr& outline = aPad->GetEffectivePolygon(); + SHAPE_SIMPLE* shape = new SHAPE_SIMPLE(); + + for( auto iter = outline->CIterate( 0 ); iter; iter++ ) + shape->Append( *iter ); + + solid->SetShape( shape ); + } return solid; } diff --git a/pcbnew/router/pns_solid.cpp b/pcbnew/router/pns_solid.cpp index 99eb780d00..ce7ef4cb78 100644 --- a/pcbnew/router/pns_solid.cpp +++ b/pcbnew/router/pns_solid.cpp @@ -26,6 +26,7 @@ #include #include #include +#include #include "pns_router.h" #include "pns_solid.h" @@ -33,9 +34,51 @@ namespace PNS { -const SHAPE_LINE_CHAIN SOLID::Hull( int aClearance, int aWalkaroundThickness, int aLayer ) const +static const SHAPE_LINE_CHAIN buildHullForPrimitiveShape( const SHAPE* aShape, int aClearance, int aWalkaroundThickness ) { int cl = aClearance + ( aWalkaroundThickness + 1 )/ 2; + + switch( aShape->Type() ) + { + case SH_RECT: + { + const SHAPE_RECT* rect = static_cast( aShape ); + return OctagonalHull( rect->GetPosition(), rect->GetSize(), cl + 1, 0.2 * cl ); + } + + case SH_CIRCLE: + { + const SHAPE_CIRCLE* circle = static_cast( aShape ); + int r = circle->GetRadius(); + return OctagonalHull( circle->GetCenter() - VECTOR2I( r, r ), VECTOR2I( 2 * r, 2 * r ), + cl + 1, 0.52 * ( r + cl ) ); + } + + case SH_SEGMENT: + { + const SHAPE_SEGMENT* seg = static_cast( aShape ); + return SegmentHull( *seg, aClearance, aWalkaroundThickness ); + } + + case SH_SIMPLE: + { + const SHAPE_SIMPLE* convex = static_cast( aShape ); + + return ConvexHull( *convex, cl ); + } + default: + { + wxLogError("Unsupported hull shape: %d", aShape->Type() ); + break; + } + } + + return SHAPE_LINE_CHAIN(); +} + + +const SHAPE_LINE_CHAIN SOLID::Hull( int aClearance, int aWalkaroundThickness, int aLayer ) const +{ SHAPE* shape = m_shape; if( !ROUTER::GetInstance()->GetInterface()->IsOnLayer( this, aLayer ) ) @@ -48,39 +91,25 @@ const SHAPE_LINE_CHAIN SOLID::Hull( int aClearance, int aWalkaroundThickness, in shape = m_alternateShape; } - switch( shape->Type() ) + if( shape->Type() == SH_COMPOUND ) { - case SH_RECT: + auto cmpnd = static_cast( shape ); + if ( cmpnd->Shapes().size() == 1 ) + { + return buildHullForPrimitiveShape( cmpnd->Shapes()[0], aClearance, aWalkaroundThickness ); + } + else + { + // fixme - shouldn't happen but one day we should move TransformShapeWithClearanceToPolygon() + // to the Geometry Library + return SHAPE_LINE_CHAIN(); + } + } + else { - SHAPE_RECT* rect = static_cast( shape ); - return OctagonalHull( rect->GetPosition(), rect->GetSize(), cl + 1, 0.2 * cl ); + return buildHullForPrimitiveShape( shape, aClearance, aWalkaroundThickness ); } - - case SH_CIRCLE: - { - SHAPE_CIRCLE* circle = static_cast( shape ); - int r = circle->GetRadius(); - return OctagonalHull( circle->GetCenter() - VECTOR2I( r, r ), VECTOR2I( 2 * r, 2 * r ), - cl + 1, 0.52 * ( r + cl ) ); - } - - case SH_SEGMENT: - { - SHAPE_SEGMENT* seg = static_cast( shape ); - return SegmentHull( *seg, aClearance, aWalkaroundThickness ); - } - - case SH_SIMPLE: - { - SHAPE_SIMPLE* convex = static_cast( shape ); - - return ConvexHull( *convex, cl ); - } - - default: - break; - } - + return SHAPE_LINE_CHAIN(); }