From 2faf1a1ed3851dce22ed117bc135c47d2172c84b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tomasz=20W=C5=82ostowski?= Date: Sat, 3 Feb 2018 10:39:46 +0100 Subject: [PATCH] Initial support for keepout zones in the P&S router. --- common/gal/opengl/opengl_gal.cpp | 2 +- common/geometry/shape_poly_set.cpp | 12 +++-- include/geometry/shape_poly_set.h | 14 +++--- pcbnew/router/pns_index.h | 2 + pcbnew/router/pns_item.h | 13 ++++++ pcbnew/router/pns_kicad_iface.cpp | 71 ++++++++++++++++++++++++++++-- pcbnew/router/pns_kicad_iface.h | 7 +-- pcbnew/router/pns_router.cpp | 21 +++++++++ pcbnew/router/pns_router.h | 1 + pcbnew/router/pns_tool_base.cpp | 3 ++ 10 files changed, 129 insertions(+), 17 deletions(-) diff --git a/common/gal/opengl/opengl_gal.cpp b/common/gal/opengl/opengl_gal.cpp index 608c117144..0286ce76a6 100644 --- a/common/gal/opengl/opengl_gal.cpp +++ b/common/gal/opengl/opengl_gal.cpp @@ -785,7 +785,7 @@ void OPENGL_GAL::drawTriangulatedPolyset( const SHAPE_POLY_SET& aPolySet ) { auto triPoly = aPolySet.TriangulatedPolygon( j ); - for ( int i = 0; i < triPoly->TriangleCount(); i++ ) + for ( int i = 0; i < triPoly->GetTriangleCount(); i++ ) { VECTOR2I a, b, c; triPoly->GetTriangle( i ,a,b,c); diff --git a/common/geometry/shape_poly_set.cpp b/common/geometry/shape_poly_set.cpp index b1cba0e2c8..c2821ff0b7 100644 --- a/common/geometry/shape_poly_set.cpp +++ b/common/geometry/shape_poly_set.cpp @@ -57,6 +57,12 @@ SHAPE_POLY_SET::SHAPE_POLY_SET( const SHAPE_POLY_SET& aOther ) : { } + +SHAPE_POLY_SET::~SHAPE_POLY_SET() +{ +} + + SHAPE* SHAPE_POLY_SET::Clone() const { return new SHAPE_POLY_SET( *this ); @@ -1033,9 +1039,7 @@ void SHAPE_POLY_SET::unfractureSingle( SHAPE_POLY_SET::POLYGON& aPoly ) n++; } - assert( outline >= 0 ); - - if( outline !=0 ) + if( outline > 0 ) std::swap( result[0], result[outline] ); aPoly = result; @@ -1970,7 +1974,7 @@ private: } else { - auto lastId = m_triPoly->VertexCount(); + auto lastId = m_triPoly->GetVertexCount(); auto p = new p2t::Point( aP.x, aP.y, lastId ); m_triPoly->AddVertex( aP ); m_uniquePoints.insert ( p ); diff --git a/include/geometry/shape_poly_set.h b/include/geometry/shape_poly_set.h index 9df221030c..65728de0ed 100644 --- a/include/geometry/shape_poly_set.h +++ b/include/geometry/shape_poly_set.h @@ -100,16 +100,16 @@ class SHAPE_POLY_SET : public SHAPE return (m_vertexCount++); } - int VertexCount() const - { - return m_vertexCount; - } - - int TriangleCount() const + int GetTriangleCount() const { return m_triangleCount; } + int GetVertexCount() const + { + return m_vertexCount; + } + private: TRI* m_triangles = nullptr; @@ -427,6 +427,8 @@ class SHAPE_POLY_SET : public SHAPE */ SHAPE_POLY_SET( const SHAPE_POLY_SET& aOther ); + ~SHAPE_POLY_SET(); + /** * Function GetRelativeIndices * diff --git a/pcbnew/router/pns_index.h b/pcbnew/router/pns_index.h index 7edec8900a..d6a1efbbc4 100644 --- a/pcbnew/router/pns_index.h +++ b/pcbnew/router/pns_index.h @@ -184,6 +184,8 @@ INDEX::ITEM_SHAPE_INDEX* INDEX::getSubindex( const ITEM* aItem ) idx_n = SI_PadsTop; else if( l.Start() == F_Cu ) idx_n = SI_PadsBottom; + else + idx_n = SI_Traces + 2 * l.Start() + SI_SegStraight; } break; diff --git a/pcbnew/router/pns_item.h b/pcbnew/router/pns_item.h index b02a455b14..a2d4975a6e 100644 --- a/pcbnew/router/pns_item.h +++ b/pcbnew/router/pns_item.h @@ -76,6 +76,7 @@ public: m_owner = NULL; m_marker = 0; m_rank = -1; + m_routable = true; } ITEM( const ITEM& aOther ) @@ -88,6 +89,7 @@ public: m_owner = NULL; m_marker = aOther.m_marker; m_rank = aOther.m_rank; + m_routable = aOther.m_routable; } virtual ~ITEM(); @@ -338,6 +340,16 @@ public: return Marker() & MK_LOCKED; } + void SetRoutable( bool aRoutable ) + { + m_routable = aRoutable; + } + + bool IsRoutable() const + { + return m_routable; + } + private: bool collideSimple( const ITEM* aOther, int aClearance, bool aNeedMTV, VECTOR2I& aMTV, bool aDifferentNetsOnly ) const; @@ -353,6 +365,7 @@ protected: int m_net; int m_marker; int m_rank; + bool m_routable; }; template< typename T, typename S > diff --git a/pcbnew/router/pns_kicad_iface.cpp b/pcbnew/router/pns_kicad_iface.cpp index 66ee91c0d9..e8b949bf28 100644 --- a/pcbnew/router/pns_kicad_iface.cpp +++ b/pcbnew/router/pns_kicad_iface.cpp @@ -24,6 +24,8 @@ #include #include #include +#include +#include #include #include #include @@ -84,7 +86,7 @@ private: }; int localPadClearance( const PNS::ITEM* aItem ) const; - int matchDpSuffix( const wxString& aNetName, wxString& aComplementNet, wxString& aBaseDpName ); + int matchDpSuffix( wxString aNetName, wxString& aComplementNet, wxString& aBaseDpName ); PNS::ROUTER* m_router; BOARD* m_board; @@ -225,7 +227,7 @@ void PNS_PCBNEW_RULE_RESOLVER::OverrideClearance( bool aEnable, int aNetA, int a } -int PNS_PCBNEW_RULE_RESOLVER::matchDpSuffix( const wxString& aNetName, wxString& aComplementNet, wxString& aBaseDpName ) +int PNS_PCBNEW_RULE_RESOLVER::matchDpSuffix( wxString aNetName, wxString& aComplementNet, wxString& aBaseDpName ) { int rv = 0; @@ -474,7 +476,6 @@ PNS_KICAD_IFACE::PNS_KICAD_IFACE() m_tool = nullptr; m_view = nullptr; m_previewItems = nullptr; - m_world = nullptr; m_router = nullptr; m_debugDecorator = nullptr; m_dispOptions = nullptr; @@ -789,6 +790,57 @@ std::unique_ptr PNS_KICAD_IFACE::syncVia( VIA* aVia ) return via; } +bool PNS_KICAD_IFACE::syncZone( PNS::NODE* aWorld, ZONE_CONTAINER* aZone ) +{ + SHAPE_POLY_SET poly; + + if( !aZone->GetIsKeepout() ) + return false; + + aZone->BuildSmoothedPoly( poly ); + poly.CacheTriangulation(); + + LSET layers = aZone->GetLayerSet(); + + for ( int layer = F_Cu; layer <= B_Cu; layer++ ) + { + if ( ! layers[layer] ) + continue; + + for ( int outline = 0; outline < poly.OutlineCount(); outline++ ) + { + auto tri = poly.TriangulatedPolygon( outline ); + + for( int i = 0; i < tri->GetTriangleCount(); i++) + { + VECTOR2I a, b, c; + tri->GetTriangle( i, a, b, c ); + auto triShape = new SHAPE_CONVEX; + + triShape->Append( a ); + triShape->Append( b ); + triShape->Append( c ); + + std::unique_ptr< PNS::SOLID > solid( new PNS::SOLID ); + + solid->SetLayer( layer ); + solid->SetNet( 0 ); + solid->SetParent( aZone ); + solid->SetShape( triShape ); + solid->SetRoutable( false ); + + aWorld->Add( std::move( solid ) ); + } + } + } + + return true; +} + +std::unique_ptr PNS_KICAD_IFACE::syncGraphicalItem( DRAWSEGMENT* aItem ) +{ + return nullptr; +} void PNS_KICAD_IFACE::SetBoard( BOARD* aBoard ) { @@ -807,6 +859,19 @@ void PNS_KICAD_IFACE::SyncWorld( PNS::NODE *aWorld ) return; } + for( auto gitem : m_board->Drawings() ) + { + auto solid = syncGraphicalItem( static_cast( gitem ) ); + + if ( solid ) + aWorld->Add( std::move( solid ) ); + } + + for( auto zone : m_board->Zones() ) + { + syncZone( aWorld, zone ); + } + for( auto module : m_board->Modules() ) { for( auto pad : module->Pads() ) diff --git a/pcbnew/router/pns_kicad_iface.h b/pcbnew/router/pns_kicad_iface.h index 18e6c8b3eb..bede5496ce 100644 --- a/pcbnew/router/pns_kicad_iface.h +++ b/pcbnew/router/pns_kicad_iface.h @@ -67,15 +67,16 @@ private: PNS_PCBNEW_RULE_RESOLVER* m_ruleResolver; PNS_PCBNEW_DEBUG_DECORATOR* m_debugDecorator; - std::unique_ptr syncPad( D_PAD* aPad ); + std::unique_ptr syncPad( D_PAD* aPad ); std::unique_ptr syncTrack( TRACK* aTrack ); - std::unique_ptr syncVia( VIA* aVia ); + std::unique_ptr syncVia( VIA* aVia ); + std::unique_ptr syncGraphicalItem( DRAWSEGMENT* aItem ); + bool syncZone( PNS::NODE* aWorld, ZONE_CONTAINER* aZone ); KIGFX::VIEW* m_view; KIGFX::VIEW_GROUP* m_previewItems; std::unordered_set m_hiddenItems; - PNS::NODE* m_world; PNS::ROUTER* m_router; BOARD* m_board; PCB_TOOL* m_tool; diff --git a/pcbnew/router/pns_router.cpp b/pcbnew/router/pns_router.cpp index 64762ee8e7..02acf6c2aa 100644 --- a/pcbnew/router/pns_router.cpp +++ b/pcbnew/router/pns_router.cpp @@ -152,9 +152,30 @@ bool ROUTER::StartDragging( const VECTOR2I& aP, ITEM* aStartItem, int aDragMode return true; } +bool ROUTER::isStartingPointRoutable( const VECTOR2I& aWhere, int aLayer ) +{ + auto candidates = QueryHoverItems( aWhere ); + + for( ITEM* item : candidates.Items() ) + { + if( ! item->IsRoutable() && item->Layers().Overlaps( aLayer ) ) + { + return false; + } + } + + return true; +} bool ROUTER::StartRouting( const VECTOR2I& aP, ITEM* aStartItem, int aLayer ) { + + if( ! isStartingPointRoutable( aP, aLayer ) ) + { + SetFailureReason( _("Cannot start routing inside a keepout area." ) ); + return false; + } + m_forceMarkObstaclesMode = false; switch( m_mode ) diff --git a/pcbnew/router/pns_router.h b/pcbnew/router/pns_router.h index 5ee6bd28f7..3ff593967d 100644 --- a/pcbnew/router/pns_router.h +++ b/pcbnew/router/pns_router.h @@ -245,6 +245,7 @@ private: void highlightCurrent( bool enabled ); void markViolations( NODE* aNode, ITEM_SET& aCurrent, NODE::ITEM_VECTOR& aRemoved ); + bool isStartingPointRoutable( const VECTOR2I& aWhere, int aLayer ); VECTOR2I m_currentEnd; RouterState m_state; diff --git a/pcbnew/router/pns_tool_base.cpp b/pcbnew/router/pns_tool_base.cpp index df2c0601fa..f9c56bf207 100644 --- a/pcbnew/router/pns_tool_base.cpp +++ b/pcbnew/router/pns_tool_base.cpp @@ -129,6 +129,9 @@ ITEM* TOOL_BASE::pickSingleItem( const VECTOR2I& aWhere, int aNet, int aLayer ) for( ITEM* item : candidates.Items() ) { + if( !item->IsRoutable() ) + continue; + if( !IsCopperLayer( item->Layers().Start() ) ) continue;