Migrated GetEffectiveShape(s) to SHAPE_COMPOUND

This commit is contained in:
Tomasz Wlostowski 2020-07-23 01:05:22 +02:00
parent 85aecc15ee
commit 89a953e039
10 changed files with 69 additions and 90 deletions

View File

@ -329,13 +329,14 @@ void BOARD_ADAPTER::createNewPadWithClearance( const D_PAD* aPad,
} }
else else
{ {
for( const std::shared_ptr<SHAPE>& shape : aPad->GetEffectiveShapes() ) auto padShapes = std::static_pointer_cast<SHAPE_COMPOUND>( aPad->GetEffectiveShape() );
for( const SHAPE* shape : padShapes->Shapes() )
{ {
switch( shape->Type() ) switch( shape->Type() )
{ {
case SH_SEGMENT: case SH_SEGMENT:
{ {
const SHAPE_SEGMENT* seg = (SHAPE_SEGMENT*) shape.get(); const SHAPE_SEGMENT* seg = (SHAPE_SEGMENT*) shape;
const SFVEC2F start3DU( seg->GetSeg().A.x * m_biuTo3Dunits, const SFVEC2F start3DU( seg->GetSeg().A.x * m_biuTo3Dunits,
-seg->GetSeg().A.y * m_biuTo3Dunits ); -seg->GetSeg().A.y * m_biuTo3Dunits );
const SFVEC2F end3DU ( seg->GetSeg().B.x * m_biuTo3Dunits, const SFVEC2F end3DU ( seg->GetSeg().B.x * m_biuTo3Dunits,
@ -360,7 +361,7 @@ void BOARD_ADAPTER::createNewPadWithClearance( const D_PAD* aPad,
case SH_CIRCLE: case SH_CIRCLE:
{ {
const SHAPE_CIRCLE* circle = (SHAPE_CIRCLE*) shape.get(); const SHAPE_CIRCLE* circle = (SHAPE_CIRCLE*) shape;
const int radius = circle->GetRadius() + aClearanceValue.x; const int radius = circle->GetRadius() + aClearanceValue.x;
const SFVEC2F center( circle->GetCenter().x * m_biuTo3Dunits, const SFVEC2F center( circle->GetCenter().x * m_biuTo3Dunits,
-circle->GetCenter().y * m_biuTo3Dunits ); -circle->GetCenter().y * m_biuTo3Dunits );
@ -371,7 +372,7 @@ void BOARD_ADAPTER::createNewPadWithClearance( const D_PAD* aPad,
case SH_RECT: case SH_RECT:
{ {
SHAPE_RECT* rect = (SHAPE_RECT*) shape.get(); SHAPE_RECT* rect = (SHAPE_RECT*) shape;
poly.NewOutline(); poly.NewOutline();
poly.Append( rect->GetPosition() ); poly.Append( rect->GetPosition() );
@ -382,11 +383,11 @@ void BOARD_ADAPTER::createNewPadWithClearance( const D_PAD* aPad,
break; break;
case SH_SIMPLE: case SH_SIMPLE:
poly.AddOutline( static_cast<SHAPE_SIMPLE*>( shape.get() )->Vertices() ); poly.AddOutline( static_cast<const SHAPE_SIMPLE*>( shape )->Vertices() );
break; break;
case SH_POLY_SET: case SH_POLY_SET:
poly = *(SHAPE_POLY_SET*) shape.get(); poly = *(SHAPE_POLY_SET*) shape;
break; break;
default: default:

View File

@ -156,7 +156,20 @@ public:
*/ */
static wxPoint ZeroOffset; static wxPoint ZeroOffset;
virtual std::shared_ptr<SHAPE> GetEffectiveShape( PCB_LAYER_ID aLayer = UNDEFINED_LAYER ); /**
* Function GetEffectiveShape
* Some pad shapes can be complex (rounded/chamfered rectangle), even without considering
* custom shapes. This routine returns a COMPOUND shape (set of simple shapes which make
* up the pad fod use with routing, collision determiniation, etc).
*
* Note that this list can contain a SHAPE_SIMPLE (a simple single-outline non-intersecting
* polygon), but should never contain a SHAPE_POLY_SET (a complex polygon consisting of
* multiple outlines and/or holes).
*
* @param aLayer in case of items spanning multiple layers, only the shapes belonging to aLayer
* will be returned. Pass UNDEFINED_LAYER to return shapes for all layers.
*/
virtual std::shared_ptr<SHAPE> GetEffectiveShape( PCB_LAYER_ID aLayer = UNDEFINED_LAYER ) const;
BOARD_ITEM_CONTAINER* GetParent() const { return (BOARD_ITEM_CONTAINER*) m_Parent; } BOARD_ITEM_CONTAINER* GetParent() const { return (BOARD_ITEM_CONTAINER*) m_Parent; }

View File

@ -151,7 +151,7 @@ bool BOARD_ITEM::ptr_cmp::operator() ( const BOARD_ITEM* a, const BOARD_ITEM* b
} }
std::shared_ptr<SHAPE> BOARD_ITEM::GetEffectiveShape( PCB_LAYER_ID aLayer ) std::shared_ptr<SHAPE> BOARD_ITEM::GetEffectiveShape( PCB_LAYER_ID aLayer ) const
{ {
std::shared_ptr<SHAPE> shape; std::shared_ptr<SHAPE> shape;

View File

@ -296,10 +296,21 @@ void DRAWSEGMENT::RebuildBezierToSegmentsPointsList( int aMinSegLen )
m_BezierPoints.clear(); m_BezierPoints.clear();
return; return;
} }
// Rebuild the m_BezierPoints vertex list that approximate the Bezier curve
m_BezierPoints = buildBezierToSegmentsPointsList( aMinSegLen );
}
const std::vector<wxPoint> DRAWSEGMENT::buildBezierToSegmentsPointsList( int aMinSegLen ) const
{
std::vector<wxPoint> bezierPoints;
// Rebuild the m_BezierPoints vertex list that approximate the Bezier curve // Rebuild the m_BezierPoints vertex list that approximate the Bezier curve
std::vector<wxPoint> ctrlPoints = { m_Start, m_BezierC1, m_BezierC2, m_End }; std::vector<wxPoint> ctrlPoints = { m_Start, m_BezierC1, m_BezierC2, m_End };
BEZIER_POLY converter( ctrlPoints ); BEZIER_POLY converter( ctrlPoints );
converter.GetPoly( m_BezierPoints, aMinSegLen ); converter.GetPoly( bezierPoints, aMinSegLen );
return bezierPoints;
} }
@ -1015,7 +1026,7 @@ void DRAWSEGMENT::SetPolyPoints( const std::vector<wxPoint>& aPoints )
} }
std::vector<SHAPE*> DRAWSEGMENT::MakeEffectiveShapes() std::vector<SHAPE*> DRAWSEGMENT::MakeEffectiveShapes() const
{ {
std::vector<SHAPE*> effectiveShapes; std::vector<SHAPE*> effectiveShapes;
@ -1082,12 +1093,12 @@ std::vector<SHAPE*> DRAWSEGMENT::MakeEffectiveShapes()
case S_CURVE: case S_CURVE:
{ {
RebuildBezierToSegmentsPointsList( GetWidth() ); auto bezierPoints = buildBezierToSegmentsPointsList( GetWidth() );
wxPoint start_pt = GetBezierPoints()[0]; wxPoint start_pt = bezierPoints[0];
for( unsigned int jj = 1; jj < GetBezierPoints().size(); jj++ ) for( unsigned int jj = 1; jj < bezierPoints.size(); jj++ )
{ {
wxPoint end_pt = GetBezierPoints()[jj]; wxPoint end_pt = bezierPoints[jj];
effectiveShapes.emplace_back( new SHAPE_SEGMENT( start_pt, end_pt, m_Width ) ); effectiveShapes.emplace_back( new SHAPE_SEGMENT( start_pt, end_pt, m_Width ) );
start_pt = end_pt; start_pt = end_pt;
} }
@ -1097,7 +1108,7 @@ std::vector<SHAPE*> DRAWSEGMENT::MakeEffectiveShapes()
case S_POLYGON: case S_POLYGON:
{ {
SHAPE_LINE_CHAIN l = GetPolyShape().Outline( 0 ); SHAPE_LINE_CHAIN l = GetPolyShape().COutline( 0 );
if( IsPolygonFilled() ) if( IsPolygonFilled() )
{ {
@ -1121,7 +1132,7 @@ std::vector<SHAPE*> DRAWSEGMENT::MakeEffectiveShapes()
} }
std::shared_ptr<SHAPE> DRAWSEGMENT::GetEffectiveShape( PCB_LAYER_ID aLayer ) std::shared_ptr<SHAPE> DRAWSEGMENT::GetEffectiveShape( PCB_LAYER_ID aLayer ) const
{ {
return std::shared_ptr<SHAPE>( new SHAPE_COMPOUND( MakeEffectiveShapes() ) ); return std::shared_ptr<SHAPE>( new SHAPE_COMPOUND( MakeEffectiveShapes() ) );
} }

View File

@ -64,6 +64,8 @@ protected:
// Computes the bounding box for an arc // Computes the bounding box for an arc
void computeArcBBox( EDA_RECT& aBBox ) const; void computeArcBBox( EDA_RECT& aBBox ) const;
const std::vector<wxPoint> buildBezierToSegmentsPointsList( int aMinSegLen ) const;
public: public:
DRAWSEGMENT( BOARD_ITEM* aParent = NULL, KICAD_T idtype = PCB_LINE_T ); DRAWSEGMENT( BOARD_ITEM* aParent = NULL, KICAD_T idtype = PCB_LINE_T );
@ -244,8 +246,8 @@ public:
/** /**
* Makes a set of SHAPE objects representing the DRAWSEGMENT. Caller owns the objects. * Makes a set of SHAPE objects representing the DRAWSEGMENT. Caller owns the objects.
*/ */
std::vector<SHAPE*> MakeEffectiveShapes(); // fixme: move to shape_compound std::vector<SHAPE*> MakeEffectiveShapes() const; // fixme: move to shape_compound
virtual std::shared_ptr<SHAPE> GetEffectiveShape( PCB_LAYER_ID aLayer = UNDEFINED_LAYER ) override; virtual std::shared_ptr<SHAPE> GetEffectiveShape( PCB_LAYER_ID aLayer = UNDEFINED_LAYER ) const override;
void GetMsgPanelInfo( EDA_DRAW_FRAME* aFrame, std::vector<MSG_PANEL_ITEM>& aList ) override; void GetMsgPanelInfo( EDA_DRAW_FRAME* aFrame, std::vector<MSG_PANEL_ITEM>& aList ) override;

View File

@ -222,7 +222,7 @@ const std::shared_ptr<SHAPE_POLY_SET>& D_PAD::GetEffectivePolygon() const
} }
std::shared_ptr<SHAPE> D_PAD::GetEffectiveShape( PCB_LAYER_ID aLayer ) std::shared_ptr<SHAPE> D_PAD::GetEffectiveShape( PCB_LAYER_ID aLayer ) const
{ {
std::shared_ptr<SHAPE_COMPOUND> shape( new SHAPE_COMPOUND ); std::shared_ptr<SHAPE_COMPOUND> shape( new SHAPE_COMPOUND );
@ -865,53 +865,14 @@ bool D_PAD::Collide( const D_PAD* aPad, int aMinClearance, int* aActual )
if( center2center - GetBoundingRadius() - aPad->GetBoundingRadius() >= aMinClearance ) if( center2center - GetBoundingRadius() - aPad->GetBoundingRadius() >= aMinClearance )
return false; return false;
int actual = INT_MAX;
for( const std::shared_ptr<SHAPE>& aShape : GetEffectiveShapes() ) return GetEffectiveShape()->Collide( aPad->GetEffectiveShape().get(), aMinClearance, aActual );
{
for( const std::shared_ptr<SHAPE>& bShape : aPad->GetEffectiveShapes() )
{
int this_dist;
if( aShape->Collide( bShape.get(), aMinClearance, &this_dist ) )
actual = std::min( actual, this_dist );
}
}
if( actual < INT_MAX )
{
// returns the actual clearance (clearance < aMinClearance) for diags:
if( aActual )
*aActual = std::max( 0, actual );
return true;
}
return false;
} }
bool D_PAD::Collide( const SHAPE_SEGMENT* aSeg, int aMinClearance, int* aActual ) bool D_PAD::Collide( const SHAPE_SEGMENT* aSeg, int aMinClearance, int* aActual )
{ {
int actual = INT_MAX; return aSeg->Collide( GetEffectiveShape().get(), aMinClearance, aActual );
for( const std::shared_ptr<SHAPE>& shape : GetEffectiveShapes() )
{
int this_dist;
if( shape->Collide( aSeg, aMinClearance, &this_dist ) )
actual = std::min( actual, this_dist );
}
if( actual < INT_MAX )
{
if( aActual )
*aActual = std::max( 0, actual );
return true;
}
return false;
} }

View File

@ -35,6 +35,7 @@
#include <class_board_item.h> #include <class_board_item.h>
#include <convert_to_biu.h> #include <convert_to_biu.h>
#include <geometry/shape_poly_set.h> #include <geometry/shape_poly_set.h>
#include <geometry/shape_compound.h>
#include <pad_shapes.h> #include <pad_shapes.h>
#include <pcbnew.h> #include <pcbnew.h>
@ -381,18 +382,8 @@ public:
bool TransformHoleWithClearanceToPolygon( SHAPE_POLY_SET& aCornerBuffer, int aInflateValue, bool TransformHoleWithClearanceToPolygon( SHAPE_POLY_SET& aCornerBuffer, int aInflateValue,
int aError = ARC_HIGH_DEF ) const; int aError = ARC_HIGH_DEF ) const;
/** // @copydoc BOARD_ITEM::GetEffectiveShape
* Function GetEffectiveShapes virtual std::shared_ptr<SHAPE> GetEffectiveShape( PCB_LAYER_ID aLayer = UNDEFINED_LAYER ) const override;
* Some pad shapes can be complex (rounded/chamfered rectangle), even without considering
* custom shapes. This routine returns a list of simple shapes which make up the pad for
* use with routing, collision determiniation, etc.
*
* Note that this list can contain a SHAPE_SIMPLE (a simple single-outline non-intersecting
* polygon), but should never contain a SHAPE_POLY_LIST (a complex polygon consisting of
* multiple outlines and/or holes).
*/
const std::vector<std::shared_ptr<SHAPE>>& GetEffectiveShapes() const;
virtual std::shared_ptr<SHAPE> GetEffectiveShape( PCB_LAYER_ID aLayer = UNDEFINED_LAYER ) override;
const std::shared_ptr<SHAPE_POLY_SET>& GetEffectivePolygon() const; const std::shared_ptr<SHAPE_POLY_SET>& GetEffectivePolygon() const;

View File

@ -973,15 +973,12 @@ void DRC::testCopperDrawItem( BOARD_COMMIT& aCommit, BOARD_ITEM* aItem )
if( !bboxShape.Collide( SEG( pad->GetPosition(), pad->GetPosition() ), bb_radius ) ) if( !bboxShape.Collide( SEG( pad->GetPosition(), pad->GetPosition() ), bb_radius ) )
continue; continue;
for( const std::shared_ptr<SHAPE>& aShape : pad->GetEffectiveShapes() ) for( const SHAPE* bShape : itemShapes )
{ {
for( const SHAPE* bShape : itemShapes ) int this_dist;
{
int this_dist;
if( aShape->Collide( bShape, minClearance, &this_dist ) ) if( pad->GetEffectiveShape()->Collide( bShape, minClearance, &this_dist ) )
actual = std::min( actual, this_dist ); actual = std::min( actual, this_dist );
}
} }
if( actual < INT_MAX ) if( actual < INT_MAX )

View File

@ -842,16 +842,16 @@ void PCB_PAINTER::draw( const D_PAD* aPad, int aLayer )
margin.x = margin.y = 0; margin.x = margin.y = 0;
} }
const std::vector<std::shared_ptr<SHAPE>>& shapes = aPad->GetEffectiveShapes(); const std::shared_ptr<SHAPE_COMPOUND> shapes = std::dynamic_pointer_cast<SHAPE_COMPOUND>( aPad->GetEffectiveShape() );
if( shapes.size() == 1 && shapes[0]->Type() == SH_SEGMENT ) if( shapes && shapes->Size() == 1 && shapes->Shapes()[0]->Type() == SH_SEGMENT )
{ {
const SHAPE_SEGMENT* seg = (SHAPE_SEGMENT*) shapes[0].get(); const SHAPE_SEGMENT* seg = (SHAPE_SEGMENT*) shapes->Shapes()[0];
m_gal->DrawSegment( seg->GetSeg().A, seg->GetSeg().B, seg->GetWidth() + 2 * margin.x ); m_gal->DrawSegment( seg->GetSeg().A, seg->GetSeg().B, seg->GetWidth() + 2 * margin.x );
} }
else if( shapes.size() == 1 && shapes[0]->Type() == SH_CIRCLE ) else if( shapes && shapes->Size() == 1 && shapes->Shapes()[0]->Type() == SH_CIRCLE )
{ {
const SHAPE_CIRCLE* circle = (SHAPE_CIRCLE*) shapes[0].get(); const SHAPE_CIRCLE* circle = (SHAPE_CIRCLE*) shapes->Shapes()[0];
m_gal->DrawCircle( circle->GetCenter(), circle->GetRadius() + margin.x ); m_gal->DrawCircle( circle->GetCenter(), circle->GetRadius() + margin.x );
} }
else else
@ -879,16 +879,16 @@ void PCB_PAINTER::draw( const D_PAD* aPad, int aLayer )
m_gal->SetStrokeColor( color ); m_gal->SetStrokeColor( color );
int clearance = aPad->GetClearance(); int clearance = aPad->GetClearance();
const std::vector<std::shared_ptr<SHAPE>>& shapes = aPad->GetEffectiveShapes(); const std::shared_ptr<SHAPE_COMPOUND> shapes = std::dynamic_pointer_cast<SHAPE_COMPOUND>( aPad->GetEffectiveShape() );
if( shapes.size() == 1 && shapes[0]->Type() == SH_SEGMENT ) if( shapes && shapes->Size() == 1 && shapes->Shapes()[0]->Type() == SH_SEGMENT )
{ {
const SHAPE_SEGMENT* seg = (SHAPE_SEGMENT*) shapes[0].get(); const SHAPE_SEGMENT* seg = (SHAPE_SEGMENT*) shapes->Shapes()[0];
m_gal->DrawSegment( seg->GetSeg().A, seg->GetSeg().B, seg->GetWidth() + 2 * clearance ); m_gal->DrawSegment( seg->GetSeg().A, seg->GetSeg().B, seg->GetWidth() + 2 * clearance );
} }
else if( shapes.size() == 1 && shapes[0]->Type() == SH_CIRCLE ) else if( shapes && shapes->Size() == 1 && shapes->Shapes()[0]->Type() == SH_CIRCLE )
{ {
const SHAPE_CIRCLE* circle = (SHAPE_CIRCLE*) shapes[0].get(); const SHAPE_CIRCLE* circle = (SHAPE_CIRCLE*) shapes->Shapes()[0];
m_gal->DrawCircle( circle->GetCenter(), circle->GetRadius() + clearance ); m_gal->DrawCircle( circle->GetCenter(), circle->GetRadius() + clearance );
} }
else else

View File

@ -634,9 +634,12 @@ std::unique_ptr<PNS::SOLID> PNS_KICAD_IFACE_BASE::syncPad( D_PAD* aPad )
solid->SetPos( VECTOR2I( c.x - offset.x, c.y - offset.y ) ); solid->SetPos( VECTOR2I( c.x - offset.x, c.y - offset.y ) );
solid->SetOffset( VECTOR2I( offset.x, offset.y ) ); solid->SetOffset( VECTOR2I( offset.x, offset.y ) );
if( aPad->GetEffectiveShapes().size() == 1 )
auto shapes = std::dynamic_pointer_cast<SHAPE_COMPOUND>( aPad->GetEffectiveShape() );
if( shapes && shapes->Size() == 1 )
{ {
solid->SetShape( aPad->GetEffectiveShapes()[0]->Clone() ); solid->SetShape( shapes->Shapes()[0]->Clone() );
} }
else else
{ {