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
{
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() )
{
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,
-seg->GetSeg().A.y * 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:
{
const SHAPE_CIRCLE* circle = (SHAPE_CIRCLE*) shape.get();
const SHAPE_CIRCLE* circle = (SHAPE_CIRCLE*) shape;
const int radius = circle->GetRadius() + aClearanceValue.x;
const SFVEC2F center( circle->GetCenter().x * m_biuTo3Dunits,
-circle->GetCenter().y * m_biuTo3Dunits );
@ -371,7 +372,7 @@ void BOARD_ADAPTER::createNewPadWithClearance( const D_PAD* aPad,
case SH_RECT:
{
SHAPE_RECT* rect = (SHAPE_RECT*) shape.get();
SHAPE_RECT* rect = (SHAPE_RECT*) shape;
poly.NewOutline();
poly.Append( rect->GetPosition() );
@ -382,11 +383,11 @@ void BOARD_ADAPTER::createNewPadWithClearance( const D_PAD* aPad,
break;
case SH_SIMPLE:
poly.AddOutline( static_cast<SHAPE_SIMPLE*>( shape.get() )->Vertices() );
poly.AddOutline( static_cast<const SHAPE_SIMPLE*>( shape )->Vertices() );
break;
case SH_POLY_SET:
poly = *(SHAPE_POLY_SET*) shape.get();
poly = *(SHAPE_POLY_SET*) shape;
break;
default:

View File

@ -156,7 +156,20 @@ public:
*/
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; }

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;

View File

@ -296,10 +296,21 @@ void DRAWSEGMENT::RebuildBezierToSegmentsPointsList( int aMinSegLen )
m_BezierPoints.clear();
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
std::vector<wxPoint> ctrlPoints = { m_Start, m_BezierC1, m_BezierC2, m_End };
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;
@ -1082,12 +1093,12 @@ std::vector<SHAPE*> DRAWSEGMENT::MakeEffectiveShapes()
case S_CURVE:
{
RebuildBezierToSegmentsPointsList( GetWidth() );
wxPoint start_pt = GetBezierPoints()[0];
auto bezierPoints = buildBezierToSegmentsPointsList( GetWidth() );
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 ) );
start_pt = end_pt;
}
@ -1097,7 +1108,7 @@ std::vector<SHAPE*> DRAWSEGMENT::MakeEffectiveShapes()
case S_POLYGON:
{
SHAPE_LINE_CHAIN l = GetPolyShape().Outline( 0 );
SHAPE_LINE_CHAIN l = GetPolyShape().COutline( 0 );
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() ) );
}

View File

@ -64,6 +64,8 @@ protected:
// Computes the bounding box for an arc
void computeArcBBox( EDA_RECT& aBBox ) const;
const std::vector<wxPoint> buildBezierToSegmentsPointsList( int aMinSegLen ) const;
public:
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.
*/
std::vector<SHAPE*> MakeEffectiveShapes(); // fixme: move to shape_compound
virtual std::shared_ptr<SHAPE> GetEffectiveShape( PCB_LAYER_ID aLayer = UNDEFINED_LAYER ) override;
std::vector<SHAPE*> MakeEffectiveShapes() const; // fixme: move to shape_compound
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;

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 );
@ -865,53 +865,14 @@ bool D_PAD::Collide( const D_PAD* aPad, int aMinClearance, int* aActual )
if( center2center - GetBoundingRadius() - aPad->GetBoundingRadius() >= aMinClearance )
return false;
int actual = INT_MAX;
for( const std::shared_ptr<SHAPE>& aShape : GetEffectiveShapes() )
{
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;
return GetEffectiveShape()->Collide( aPad->GetEffectiveShape().get(), aMinClearance, aActual );
}
bool D_PAD::Collide( const SHAPE_SEGMENT* aSeg, int aMinClearance, int* aActual )
{
int actual = INT_MAX;
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;
return aSeg->Collide( GetEffectiveShape().get(), aMinClearance, aActual );
}

View File

@ -35,6 +35,7 @@
#include <class_board_item.h>
#include <convert_to_biu.h>
#include <geometry/shape_poly_set.h>
#include <geometry/shape_compound.h>
#include <pad_shapes.h>
#include <pcbnew.h>
@ -381,18 +382,8 @@ public:
bool TransformHoleWithClearanceToPolygon( SHAPE_POLY_SET& aCornerBuffer, int aInflateValue,
int aError = ARC_HIGH_DEF ) const;
/**
* Function GetEffectiveShapes
* 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;
// @copydoc BOARD_ITEM::GetEffectiveShape
virtual std::shared_ptr<SHAPE> GetEffectiveShape( PCB_LAYER_ID aLayer = UNDEFINED_LAYER ) const override;
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 ) )
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 );
}
}
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;
}
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 );
}
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 );
}
else
@ -879,16 +879,16 @@ void PCB_PAINTER::draw( const D_PAD* aPad, int aLayer )
m_gal->SetStrokeColor( color );
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 );
}
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 );
}
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->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
{