From 89a953e0390804480a00ab03d48f795b52550a4f Mon Sep 17 00:00:00 2001 From: Tomasz Wlostowski Date: Thu, 23 Jul 2020 01:05:22 +0200 Subject: [PATCH] Migrated GetEffectiveShape(s) to SHAPE_COMPOUND --- .../3d_canvas/create_3Dgraphic_brd_items.cpp | 13 +++--- include/class_board_item.h | 15 ++++++- pcbnew/class_board_item.cpp | 2 +- pcbnew/class_drawsegment.cpp | 27 +++++++---- pcbnew/class_drawsegment.h | 6 ++- pcbnew/class_pad.cpp | 45 ++----------------- pcbnew/class_pad.h | 15 ++----- pcbnew/drc/drc.cpp | 9 ++-- pcbnew/pcb_painter.cpp | 20 ++++----- pcbnew/router/pns_kicad_iface.cpp | 7 ++- 10 files changed, 69 insertions(+), 90 deletions(-) diff --git a/3d-viewer/3d_canvas/create_3Dgraphic_brd_items.cpp b/3d-viewer/3d_canvas/create_3Dgraphic_brd_items.cpp index 011b70d4f7..073596628e 100644 --- a/3d-viewer/3d_canvas/create_3Dgraphic_brd_items.cpp +++ b/3d-viewer/3d_canvas/create_3Dgraphic_brd_items.cpp @@ -329,13 +329,14 @@ void BOARD_ADAPTER::createNewPadWithClearance( const D_PAD* aPad, } else { - for( const std::shared_ptr& shape : aPad->GetEffectiveShapes() ) + auto padShapes = std::static_pointer_cast( 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.get() )->Vertices() ); + poly.AddOutline( static_cast( shape )->Vertices() ); break; case SH_POLY_SET: - poly = *(SHAPE_POLY_SET*) shape.get(); + poly = *(SHAPE_POLY_SET*) shape; break; default: diff --git a/include/class_board_item.h b/include/class_board_item.h index 261373a144..c9027d7df8 100644 --- a/include/class_board_item.h +++ b/include/class_board_item.h @@ -156,7 +156,20 @@ public: */ static wxPoint ZeroOffset; - virtual std::shared_ptr 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 GetEffectiveShape( PCB_LAYER_ID aLayer = UNDEFINED_LAYER ) const; BOARD_ITEM_CONTAINER* GetParent() const { return (BOARD_ITEM_CONTAINER*) m_Parent; } diff --git a/pcbnew/class_board_item.cpp b/pcbnew/class_board_item.cpp index 85bb6b7781..459b81ca2c 100644 --- a/pcbnew/class_board_item.cpp +++ b/pcbnew/class_board_item.cpp @@ -151,7 +151,7 @@ bool BOARD_ITEM::ptr_cmp::operator() ( const BOARD_ITEM* a, const BOARD_ITEM* b } -std::shared_ptr BOARD_ITEM::GetEffectiveShape( PCB_LAYER_ID aLayer ) +std::shared_ptr BOARD_ITEM::GetEffectiveShape( PCB_LAYER_ID aLayer ) const { std::shared_ptr shape; diff --git a/pcbnew/class_drawsegment.cpp b/pcbnew/class_drawsegment.cpp index 870080ce60..4658033b9c 100644 --- a/pcbnew/class_drawsegment.cpp +++ b/pcbnew/class_drawsegment.cpp @@ -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 DRAWSEGMENT::buildBezierToSegmentsPointsList( int aMinSegLen ) const +{ + std::vector bezierPoints; + // Rebuild the m_BezierPoints vertex list that approximate the Bezier curve std::vector 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& aPoints ) } -std::vector DRAWSEGMENT::MakeEffectiveShapes() +std::vector DRAWSEGMENT::MakeEffectiveShapes() const { std::vector effectiveShapes; @@ -1082,12 +1093,12 @@ std::vector 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 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 DRAWSEGMENT::MakeEffectiveShapes() } -std::shared_ptr DRAWSEGMENT::GetEffectiveShape( PCB_LAYER_ID aLayer ) +std::shared_ptr DRAWSEGMENT::GetEffectiveShape( PCB_LAYER_ID aLayer ) const { return std::shared_ptr( new SHAPE_COMPOUND( MakeEffectiveShapes() ) ); } diff --git a/pcbnew/class_drawsegment.h b/pcbnew/class_drawsegment.h index b910a85b39..efaf57ba53 100644 --- a/pcbnew/class_drawsegment.h +++ b/pcbnew/class_drawsegment.h @@ -64,6 +64,8 @@ protected: // Computes the bounding box for an arc void computeArcBBox( EDA_RECT& aBBox ) const; + const std::vector 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 MakeEffectiveShapes(); // fixme: move to shape_compound - virtual std::shared_ptr GetEffectiveShape( PCB_LAYER_ID aLayer = UNDEFINED_LAYER ) override; + std::vector MakeEffectiveShapes() const; // fixme: move to shape_compound + virtual std::shared_ptr GetEffectiveShape( PCB_LAYER_ID aLayer = UNDEFINED_LAYER ) const override; void GetMsgPanelInfo( EDA_DRAW_FRAME* aFrame, std::vector& aList ) override; diff --git a/pcbnew/class_pad.cpp b/pcbnew/class_pad.cpp index b51e43f6fc..ac00162b5b 100644 --- a/pcbnew/class_pad.cpp +++ b/pcbnew/class_pad.cpp @@ -222,7 +222,7 @@ const std::shared_ptr& D_PAD::GetEffectivePolygon() const } -std::shared_ptr D_PAD::GetEffectiveShape( PCB_LAYER_ID aLayer ) +std::shared_ptr D_PAD::GetEffectiveShape( PCB_LAYER_ID aLayer ) const { std::shared_ptr 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& aShape : GetEffectiveShapes() ) - { - for( const std::shared_ptr& 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 : 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 ); } diff --git a/pcbnew/class_pad.h b/pcbnew/class_pad.h index 27abb9acf1..4f41bbde70 100644 --- a/pcbnew/class_pad.h +++ b/pcbnew/class_pad.h @@ -35,6 +35,7 @@ #include #include #include +#include #include #include @@ -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>& GetEffectiveShapes() const; - virtual std::shared_ptr GetEffectiveShape( PCB_LAYER_ID aLayer = UNDEFINED_LAYER ) override; + // @copydoc BOARD_ITEM::GetEffectiveShape + virtual std::shared_ptr GetEffectiveShape( PCB_LAYER_ID aLayer = UNDEFINED_LAYER ) const override; const std::shared_ptr& GetEffectivePolygon() const; diff --git a/pcbnew/drc/drc.cpp b/pcbnew/drc/drc.cpp index bb1b431696..42da492440 100644 --- a/pcbnew/drc/drc.cpp +++ b/pcbnew/drc/drc.cpp @@ -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& 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 ) diff --git a/pcbnew/pcb_painter.cpp b/pcbnew/pcb_painter.cpp index d840bf682e..1c03d6bdc8 100644 --- a/pcbnew/pcb_painter.cpp +++ b/pcbnew/pcb_painter.cpp @@ -842,16 +842,16 @@ void PCB_PAINTER::draw( const D_PAD* aPad, int aLayer ) margin.x = margin.y = 0; } - const std::vector>& shapes = aPad->GetEffectiveShapes(); + const std::shared_ptr shapes = std::dynamic_pointer_cast( 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>& shapes = aPad->GetEffectiveShapes(); + const std::shared_ptr shapes = std::dynamic_pointer_cast( 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 diff --git a/pcbnew/router/pns_kicad_iface.cpp b/pcbnew/router/pns_kicad_iface.cpp index a3e8fce73f..fb4a246954 100644 --- a/pcbnew/router/pns_kicad_iface.cpp +++ b/pcbnew/router/pns_kicad_iface.cpp @@ -634,9 +634,12 @@ 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 ) ); - if( aPad->GetEffectiveShapes().size() == 1 ) + + auto shapes = std::dynamic_pointer_cast( aPad->GetEffectiveShape() ); + + if( shapes && shapes->Size() == 1 ) { - solid->SetShape( aPad->GetEffectiveShapes()[0]->Clone() ); + solid->SetShape( shapes->Shapes()[0]->Clone() ); } else {