diff --git a/pcbnew/router/CMakeLists.txt b/pcbnew/router/CMakeLists.txt index 4de04686bc..be9b7c386a 100644 --- a/pcbnew/router/CMakeLists.txt +++ b/pcbnew/router/CMakeLists.txt @@ -12,7 +12,7 @@ include_directories( set( PCBNEW_PNS_SRCS time_limit.cpp - + pns_kicad_iface.cpp pns_algo_base.cpp pns_diff_pair.cpp pns_diff_pair_placer.cpp diff --git a/pcbnew/router/length_tuner_tool.cpp b/pcbnew/router/length_tuner_tool.cpp index e2f56c0dd4..0317cfa4fb 100644 --- a/pcbnew/router/length_tuner_tool.cpp +++ b/pcbnew/router/length_tuner_tool.cpp @@ -279,13 +279,6 @@ int LENGTH_TUNER_TOOL::mainLoop( PNS_ROUTER_MODE aMode ) // Main loop: keep receiving events while( OPT_TOOL_EVENT evt = Wait() ) { - if( m_needsSync ) - { - m_router->SyncWorld(); - m_router->SetView( getView() ); - m_needsSync = false; - } - if( evt->IsCancel() || evt->IsActivate() ) break; // Finish else if( evt->IsMotion() ) diff --git a/pcbnew/router/pns_diff_pair.h b/pcbnew/router/pns_diff_pair.h index 234ef89851..e2e150097f 100644 --- a/pcbnew/router/pns_diff_pair.h +++ b/pcbnew/router/pns_diff_pair.h @@ -157,6 +157,12 @@ public: DIRECTION_45 DirP() const; DIRECTION_45 DirN() const; + void dump() + { + printf("-- Prim-P %p anchor [%d, %d]\n", m_primP, m_anchorP.x, m_anchorP.y); + printf("-- Prim-N %p anchor [%d, %d]\n", m_primN, m_anchorN.x, m_anchorN.y); + } + private: DIRECTION_45 anchorDirection( PNS_ITEM* aItem, const VECTOR2I& aP ) const; diff --git a/pcbnew/router/pns_diff_pair_placer.cpp b/pcbnew/router/pns_diff_pair_placer.cpp index 9711ed60ae..3293dd4156 100644 --- a/pcbnew/router/pns_diff_pair_placer.cpp +++ b/pcbnew/router/pns_diff_pair_placer.cpp @@ -79,7 +79,6 @@ void PNS_DIFF_PAIR_PLACER::setWorld( PNS_NODE* aWorld ) m_world = aWorld; } - const PNS_VIA PNS_DIFF_PAIR_PLACER::makeVia( const VECTOR2I& aP, int aNet ) { const PNS_LAYERSET layers( m_sizes.GetLayerTop(), m_sizes.GetLayerBottom() ); @@ -168,7 +167,7 @@ bool PNS_DIFF_PAIR_PLACER::attemptWalk( PNS_NODE* aNode, PNS_DIFF_PAIR* aCurrent PNS_WALKAROUND walkaround( aNode, Router() ); PNS_WALKAROUND::WALKAROUND_STATUS wf1; - Router()->GetClearanceFunc()->OverrideClearance( true, + Router()->GetRuleResolver()->OverrideClearance( true, aCurrent->NetP(), aCurrent->NetN(), aCurrent->Gap() ); walkaround.SetSolidsOnly( aSolidsOnly ); @@ -237,7 +236,7 @@ bool PNS_DIFF_PAIR_PLACER::attemptWalk( PNS_NODE* aNode, PNS_DIFF_PAIR* aCurrent return false; aWalk.SetShape( cur.CP(), cur.CN() ); - Router()->GetClearanceFunc()->OverrideClearance( false ); + Router()->GetRuleResolver()->OverrideClearance( false ); return true; } @@ -474,64 +473,41 @@ OPT_VECTOR2I PNS_DIFF_PAIR_PLACER::getDanglingAnchor( PNS_NODE* aNode, PNS_ITEM* } + bool PNS_DIFF_PAIR_PLACER::findDpPrimitivePair( const VECTOR2I& aP, PNS_ITEM* aItem, PNS_DP_PRIMITIVE_PAIR& aPair ) { - if( !aItem || !aItem->Parent() || !aItem->Parent()->GetNet() ) + int netP, netN; + + + printf("world %p\n", m_world); + + bool result = m_world->GetRuleResolver()->DpNetPair( aItem, netP, netN ); + + if(!result) return false; + + int refNet = aItem->Net(); + int coupledNet = (refNet == netP) ? netN : netP; - wxString netNameP = aItem->Parent()->GetNet()->GetNetname(); - wxString netNameN, netNameBase; - - BOARD* brd = Router()->GetBoard(); - PNS_ITEM *primRef = NULL, *primP = NULL, *primN = NULL; - - int refNet; - - wxString suffix; - - int r = matchDpSuffix ( netNameP, suffix, netNameBase ); - - if( r == 0 ) - return false; - else if( r == 1 ) - { - primRef = primP = static_cast( aItem ); - netNameN = netNameBase + suffix; - } - else - { - primRef = primN = static_cast( aItem ); - netNameN = netNameP; - netNameP = netNameBase + suffix; - } - - NETINFO_ITEM* netInfoP = brd->FindNet( netNameP ); - NETINFO_ITEM* netInfoN = brd->FindNet( netNameN ); - - if( !netInfoP || !netInfoN ) - return false; - - int netP = netInfoP->GetNet(); - int netN = netInfoN->GetNet(); - - if( primP ) - refNet = netN; - else - refNet = netP; + printf("result %d\n", !!result); - std::set items; - OPT_VECTOR2I refAnchor = getDanglingAnchor( m_currentNode, primRef ); + OPT_VECTOR2I refAnchor = getDanglingAnchor( m_currentNode, aItem ); + PNS_ITEM *primRef = aItem; + + printf("refAnchor %p\n", aItem); if( !refAnchor ) return false; - m_currentNode->AllItemsInNet( refNet, items ); + std::set coupledItems; + + m_currentNode->AllItemsInNet( coupledNet, coupledItems ); double bestDist = std::numeric_limits::max(); bool found = false; - for( PNS_ITEM* item : items ) + for( PNS_ITEM* item : coupledItems ) { if( item->Kind() == aItem->Kind() ) { @@ -599,7 +575,8 @@ bool PNS_DIFF_PAIR_PLACER::Start( const VECTOR2I& aP, PNS_ITEM* aStartItem ) return false; } - m_currentNode = Router()->GetWorld(); + setWorld( Router()->GetWorld() ); + m_currentNode = m_world; if( !findDpPrimitivePair( aP, aStartItem, m_start ) ) { @@ -612,8 +589,10 @@ bool PNS_DIFF_PAIR_PLACER::Start( const VECTOR2I& aP, PNS_ITEM* aStartItem ) m_netP = m_start.PrimP()->Net(); m_netN = m_start.PrimN()->Net(); + #if 0 + // FIXME: this also needs to be factored out but not so important right now // Check if the current track/via gap & track width settings are violated - BOARD* brd = Router()->GetBoard(); + BOARD* brd = NULL; // FIXME Router()->GetBoard(); NETCLASSPTR netclassP = brd->FindNet( m_netP )->GetNetClass(); NETCLASSPTR netclassN = brd->FindNet( m_netN )->GetNetClass(); int clearance = std::min( m_sizes.DiffPairGap(), m_sizes.DiffPairViaGap() ); @@ -630,6 +609,7 @@ bool PNS_DIFF_PAIR_PLACER::Start( const VECTOR2I& aP, PNS_ITEM* aStartItem ) Router()->SetFailureReason( _( "Current track width setting violates design rules." ) ); return false; } + #endif m_currentStart = p; m_currentEnd = p; @@ -683,6 +663,10 @@ bool PNS_DIFF_PAIR_PLACER::routeHead( const VECTOR2I& aP ) gwsEntry.BuildFromPrimitivePair( *m_prevPair, m_startDiagonal ); +// m_prevPair->dump(); + +// printf("Entry %d\n", gwsEntry.Gateways().size()); + PNS_DP_PRIMITIVE_PAIR target; if( findDpPrimitivePair ( aP, m_currentEndItem, target ) ) @@ -698,6 +682,7 @@ bool PNS_DIFF_PAIR_PLACER::routeHead( const VECTOR2I& aP ) gwsTarget.SetFitVias( m_placingVia, m_sizes.ViaDiameter(), viaGap() ); gwsTarget.BuildForCursor( fp ); gwsTarget.BuildOrthoProjections( gwsEntry, fp, m_orthoMode ? 200 : -200 ); +// printf("Target %d\n", gwsTarget.Gateways().size()); m_snapOnTarget = false; } diff --git a/pcbnew/router/pns_kicad_iface.cpp b/pcbnew/router/pns_kicad_iface.cpp new file mode 100644 index 0000000000..331e27eba5 --- /dev/null +++ b/pcbnew/router/pns_kicad_iface.cpp @@ -0,0 +1,772 @@ +/* + * KiRouter - a push-and-(sometimes-)shove PCB router + * + * Copyright (C) 2013-2014 CERN + * Author: Tomasz Wlostowski + * + * This program is free software: you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation, either version 3 of the License, or (at your + * option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program. If not, see . + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include +#include +#include +#include + +#include + +#include +#include +#include +#include +#include +#include + + +#include "pns_kicad_iface.h" +#include "pns_routing_settings.h" +#include "pns_sizes_settings.h" +#include "pns_item.h" +#include "pns_solid.h" +#include "pns_segment.h" +#include "pns_solid.h" +#include "pns_itemset.h" +#include "pns_node.h" +#include "pns_topology.h" +#include "pns_router.h" +#include "router_preview_item.h" + +class PNS_PCBNEW_RULE_RESOLVER : public PNS_RULE_RESOLVER +{ +public: + PNS_PCBNEW_RULE_RESOLVER( BOARD *aBoard, PNS_ROUTER *aRouter ); + virtual ~PNS_PCBNEW_RULE_RESOLVER(); + + virtual int Clearance( const PNS_ITEM* aA, const PNS_ITEM* aB ); + virtual void OverrideClearance (bool aEnable, int aNetA = 0, int aNetB = 0, int aClearance = 0); + virtual void UseDpGap( bool aUseDpGap ) { m_useDpGap = aUseDpGap; } + virtual int DpCoupledNet( int aNet ); + virtual int DpNetPolarity( int aNet ); + virtual bool DpNetPair( PNS_ITEM* aItem, int& aNetP, int& aNetN ); + +private: + + struct CLEARANCE_ENT { + int coupledNet; + int clearance; + }; + + int localPadClearance( const PNS_ITEM* aItem ) const; + int matchDpSuffix( wxString aNetName, wxString& aComplementNet, wxString& aBaseDpName ); + + PNS_ROUTER *m_router; + BOARD *m_board; + + std::vector m_clearanceCache; + int m_defaultClearance; + bool m_overrideEnabled; + int m_overrideNetA, m_overrideNetB; + int m_overrideClearance; + bool m_useDpGap; + +}; + + +PNS_PCBNEW_RULE_RESOLVER::PNS_PCBNEW_RULE_RESOLVER( BOARD *aBoard, PNS_ROUTER* aRouter ) : + m_router( aRouter ), + m_board( aBoard ) +{ + PNS_NODE* world = m_router->GetWorld(); + + PNS_TOPOLOGY topo( world ); + m_clearanceCache.resize( m_board->GetNetCount() ); + + for( unsigned int i = 0; i < m_board->GetNetCount(); i++ ) + { + NETINFO_ITEM* ni = m_board->FindNet( i ); + if( ni == NULL ) + continue; + + CLEARANCE_ENT ent; + ent.coupledNet = DpCoupledNet( i ); + + wxString netClassName = ni->GetClassName(); + NETCLASSPTR nc = m_board->GetDesignSettings().m_NetClasses.Find( netClassName ); + + int clearance = nc->GetClearance(); + ent.clearance = clearance; + m_clearanceCache[i] = ent; + + TRACE( 1, "Add net %d netclass %s clearance %d", i % netClassName.mb_str() % + clearance ); + } + + m_overrideEnabled = false; + m_defaultClearance = Millimeter2iu( 0.254 ); // m_board->m_NetClasses.Find ("Default clearance")->GetClearance(); + m_overrideNetA = 0; + m_overrideNetB = 0; + m_overrideClearance = 0; +} + +PNS_PCBNEW_RULE_RESOLVER::~PNS_PCBNEW_RULE_RESOLVER() +{ +} + +int PNS_PCBNEW_RULE_RESOLVER::localPadClearance( const PNS_ITEM* aItem ) const +{ + if( !aItem->Parent() || aItem->Parent()->Type() != PCB_PAD_T ) + return 0; + + const D_PAD* pad = static_cast( aItem->Parent() ); + return pad->GetLocalClearance(); +} + + +int PNS_PCBNEW_RULE_RESOLVER::Clearance( const PNS_ITEM* aA, const PNS_ITEM* aB ) +{ + int net_a = aA->Net(); + int cl_a = ( net_a >= 0 ? m_clearanceCache[net_a].clearance : m_defaultClearance ); + int net_b = aB->Net(); + int cl_b = ( net_b >= 0 ? m_clearanceCache[net_b].clearance : m_defaultClearance ); + + bool linesOnly = aA->OfKind( PNS_ITEM::SEGMENT | PNS_ITEM::LINE ) && aB->OfKind( PNS_ITEM::SEGMENT | PNS_ITEM::LINE ); + + if( linesOnly && net_a >= 0 && net_b >= 0 && m_clearanceCache[net_a].coupledNet == net_b ) + { + cl_a = cl_b = m_router->Sizes().DiffPairGap() - 2 * PNS_HULL_MARGIN; + } + + int pad_a = localPadClearance( aA ); + int pad_b = localPadClearance( aB ); + + cl_a = std::max( cl_a, pad_a ); + cl_b = std::max( cl_b, pad_b ); + + return std::max( cl_a, cl_b ); +} + + +// fixme: ugly hack to make the optimizer respect gap width for currently routed differential pair. +void PNS_PCBNEW_RULE_RESOLVER::OverrideClearance( bool aEnable, int aNetA, int aNetB , int aClearance ) +{ + m_overrideEnabled = aEnable; + m_overrideNetA = aNetA; + m_overrideNetB = aNetB; + m_overrideClearance = aClearance; +} + +int PNS_PCBNEW_RULE_RESOLVER::matchDpSuffix( wxString aNetName, wxString& aComplementNet, wxString& aBaseDpName ) +{ + int rv = 0; + + if( aNetName.EndsWith( "+" ) ) + { + aComplementNet = "-"; + rv = 1; + } + else if( aNetName.EndsWith( "_P" ) ) + { + aComplementNet = "_N"; + rv = 1; + } + else if( aNetName.EndsWith( "-" ) ) + { + aComplementNet = "+"; + rv = -1; + } + else if( aNetName.EndsWith( "_N" ) ) + { + aComplementNet = "_P"; + rv = -1; + } + + if( rv != 0 ) + { + aBaseDpName = aNetName.Left( aNetName.Length() - aComplementNet.Length() ); + aComplementNet = aBaseDpName + aComplementNet; + } + + return rv; +} + + +int PNS_PCBNEW_RULE_RESOLVER::DpCoupledNet( int aNet ) +{ + wxString refName = m_board->FindNet( aNet )->GetNetname(); + wxString dummy, coupledNetName; + + if( matchDpSuffix( refName, coupledNetName, dummy ) ) + { + NETINFO_ITEM* net = m_board->FindNet( coupledNetName ); + + if( !net ) + return -1; + + return net->GetNet(); + + } + + return -1; +} + + +int PNS_PCBNEW_RULE_RESOLVER::DpNetPolarity( int aNet ) +{ + wxString refName = m_board->FindNet( aNet )->GetNetname(); + wxString dummy1, dummy2; + + return matchDpSuffix( refName, dummy1, dummy2 ); +} + +bool PNS_PCBNEW_RULE_RESOLVER::DpNetPair( PNS_ITEM* aItem, int& aNetP, int& aNetN ) +{ + if( !aItem || !aItem->Parent() || !aItem->Parent()->GetNet() ) + return false; + + wxString netNameP = aItem->Parent()->GetNet()->GetNetname(); + wxString netNameN, netNameCoupled, netNameBase; + + bool refIsP = false; + int r = matchDpSuffix ( netNameP, netNameCoupled, netNameBase ); + + printf("matchDpSuffix %d\n", r); + + if( r == 0 ) + return false; + else if( r == 1 ) + { + netNameN = netNameCoupled; + } + else + { + netNameN = netNameP; + netNameP = netNameCoupled; + } + +// printf("p %s n %s base %s\n", (const char *)netNameP.c_str(), (const char *)netNameN.c_str(), (const char *)netNameBase.c_str() ); + + NETINFO_ITEM* netInfoP = m_board->FindNet( netNameP ); + NETINFO_ITEM* netInfoN = m_board->FindNet( netNameN ); + + //printf("ip %p in %p\n", netInfoP, netInfoN); + + if( !netInfoP || !netInfoN ) + return false; + + aNetP = netInfoP->GetNet(); + aNetN = netInfoN->GetNet(); + + return true; +} + + +PNS_KICAD_IFACE::PNS_KICAD_IFACE () +{ + m_ruleResolver = nullptr; + m_board = NULL; + m_frame = NULL; + m_view = NULL; + m_previewItems = nullptr; + m_world = nullptr; + m_router = nullptr; +} + +PNS_KICAD_IFACE::~PNS_KICAD_IFACE () +{ + if( m_ruleResolver ) + delete m_ruleResolver; +} + + +PNS_ITEM* PNS_KICAD_IFACE::syncPad( D_PAD* aPad ) +{ + PNS_LAYERSET layers( 0, MAX_CU_LAYERS - 1 ); + + // ignore non-copper pads + if ( (aPad->GetLayerSet() & LSET::AllCuMask()).none() ) + return NULL; + + switch( aPad->GetAttribute() ) + { + case PAD_ATTRIB_STANDARD: + break; + + case PAD_ATTRIB_SMD: + case PAD_ATTRIB_HOLE_NOT_PLATED: + case PAD_ATTRIB_CONN: + { + LSET lmsk = aPad->GetLayerSet(); + bool is_copper = false; + + for( int i = 0; i < MAX_CU_LAYERS; i++ ) + { + if( lmsk[i] ) + { + is_copper = true; + if( aPad->GetAttribute() != PAD_ATTRIB_HOLE_NOT_PLATED ) + layers = PNS_LAYERSET( i ); + break; + } + } + + if( !is_copper ) + return NULL; + } + break; + + default: + TRACE( 0, "unsupported pad type 0x%x", aPad->GetAttribute() ); + return NULL; + } + + PNS_SOLID* solid = new PNS_SOLID; + + solid->SetLayers( layers ); + solid->SetNet( aPad->GetNetCode() ); + solid->SetParent( aPad ); + + wxPoint wx_c = aPad->ShapePos(); + wxSize wx_sz = aPad->GetSize(); + wxPoint offset = aPad->GetOffset(); + + VECTOR2I c( wx_c.x, wx_c.y ); + VECTOR2I sz( wx_sz.x, wx_sz.y ); + + RotatePoint( &offset, aPad->GetOrientation() ); + + solid->SetPos( VECTOR2I( c.x - offset.x, c.y - offset.y ) ); + solid->SetOffset ( VECTOR2I ( offset.x, offset.y ) ); + + double orient = aPad->GetOrientation() / 10.0; + + if( aPad->GetShape() == PAD_SHAPE_CIRCLE ) + { + solid->SetShape( new SHAPE_CIRCLE( c, sz.x / 2 ) ); + } + else + { + if( orient == 0.0 || orient == 90.0 || orient == 180.0 || orient == 270.0 ) + { + if( orient == 90.0 || orient == 270.0 ) + sz = VECTOR2I( sz.y, sz.x ); + + switch( aPad->GetShape() ) + { + case PAD_SHAPE_OVAL: + if( sz.x == sz.y ) + solid->SetShape( new SHAPE_CIRCLE( c, sz.x / 2 ) ); + else + { + VECTOR2I delta; + + if( sz.x > sz.y ) + delta = VECTOR2I( ( sz.x - sz.y ) / 2, 0 ); + else + delta = VECTOR2I( 0, ( sz.y - sz.x ) / 2 ); + + SHAPE_SEGMENT* shape = new SHAPE_SEGMENT( c - delta, c + delta, + std::min( sz.x, sz.y ) ); + solid->SetShape( shape ); + } + break; + + case PAD_SHAPE_RECT: + solid->SetShape( new SHAPE_RECT( c - sz / 2, sz.x, sz.y ) ); + break; + + case PAD_SHAPE_TRAPEZOID: + { + wxPoint coords[4]; + aPad->BuildPadPolygon( coords, wxSize( 0, 0 ), aPad->GetOrientation() ); + SHAPE_CONVEX* shape = new SHAPE_CONVEX(); + + for( int ii = 0; ii < 4; ii++ ) + { + shape->Append( wx_c + coords[ii] ); + } + + solid->SetShape( shape ); + break; + } + + case PAD_SHAPE_ROUNDRECT: + { + SHAPE_POLY_SET outline; + const int segmentToCircleCount = 64; + + aPad->BuildPadShapePolygon( outline, wxSize( 0, 0 ), + segmentToCircleCount, 1.0 ); + + // TransformRoundRectToPolygon creates only one convex polygon + SHAPE_LINE_CHAIN& poly = outline.Outline( 0 ); + SHAPE_CONVEX* shape = new SHAPE_CONVEX(); + + for( int ii = 0; ii < poly.PointCount(); ++ii ) + { + shape->Append( wxPoint( poly.Point( ii ).x, poly.Point( ii ).y ) ); + } + + solid->SetShape( shape ); + } + break; + + default: + TRACEn( 0, "unsupported pad shape" ); + delete solid; + return NULL; + } + } + else + { + switch( aPad->GetShape() ) + { + // PAD_SHAPE_CIRCLE already handled above + + case PAD_SHAPE_OVAL: + if( sz.x == sz.y ) + solid->SetShape( new SHAPE_CIRCLE( c, sz.x / 2 ) ); + else + { + wxPoint start; + wxPoint end; + wxPoint corner; + + SHAPE_CONVEX* shape = new SHAPE_CONVEX(); + + int w = aPad->BuildSegmentFromOvalShape( start, end, 0.0, wxSize( 0, 0 ) ); + + if( start.y == 0 ) + corner = wxPoint( start.x, -( w / 2 ) ); + else + corner = wxPoint( w / 2, start.y ); + + RotatePoint( &start, aPad->GetOrientation() ); + RotatePoint( &corner, aPad->GetOrientation() ); + shape->Append( wx_c + corner ); + + for( int rot = 100; rot <= 1800; rot += 100 ) + { + wxPoint p( corner ); + RotatePoint( &p, start, rot ); + shape->Append( wx_c + p ); + } + + if( end.y == 0 ) + corner = wxPoint( end.x, w / 2 ); + else + corner = wxPoint( -( w / 2 ), end.y ); + + RotatePoint( &end, aPad->GetOrientation() ); + RotatePoint( &corner, aPad->GetOrientation() ); + shape->Append( wx_c + corner ); + + for( int rot = 100; rot <= 1800; rot += 100 ) + { + wxPoint p( corner ); + RotatePoint( &p, end, rot ); + shape->Append( wx_c + p ); + } + + solid->SetShape( shape ); + } + break; + + case PAD_SHAPE_RECT: + case PAD_SHAPE_TRAPEZOID: + { + wxPoint coords[4]; + aPad->BuildPadPolygon( coords, wxSize( 0, 0 ), aPad->GetOrientation() ); + + SHAPE_CONVEX* shape = new SHAPE_CONVEX(); + for( int ii = 0; ii < 4; ii++ ) + { + shape->Append( wx_c + coords[ii] ); + } + + solid->SetShape( shape ); + break; + } + + case PAD_SHAPE_ROUNDRECT: + { + SHAPE_POLY_SET outline; + const int segmentToCircleCount = 32; + aPad->BuildPadShapePolygon( outline, wxSize( 0, 0 ), + segmentToCircleCount, 1.0 ); + + // TransformRoundRectToPolygon creates only one convex polygon + SHAPE_LINE_CHAIN& poly = outline.Outline( 0 ); + SHAPE_CONVEX* shape = new SHAPE_CONVEX(); + + for( int ii = 0; ii < poly.PointCount(); ++ii ) + { + shape->Append( wxPoint( poly.Point( ii ).x, poly.Point( ii ).y ) ); + } + + solid->SetShape( shape ); + } + break; + + default: + TRACEn( 0, "unsupported pad shape" ); + delete solid; + + return NULL; + } + } + } + return solid; +} + + +PNS_ITEM* PNS_KICAD_IFACE::syncTrack( TRACK* aTrack ) +{ + PNS_SEGMENT* s = + new PNS_SEGMENT( SEG( aTrack->GetStart(), aTrack->GetEnd() ), aTrack->GetNetCode() ); + + s->SetWidth( aTrack->GetWidth() ); + s->SetLayers( PNS_LAYERSET( aTrack->GetLayer() ) ); + s->SetParent( aTrack ); + return s; +} + + +PNS_ITEM* PNS_KICAD_IFACE::syncVia( VIA* aVia ) +{ + LAYER_ID top, bottom; + aVia->LayerPair( &top, &bottom ); + PNS_VIA* v = new PNS_VIA( + aVia->GetPosition(), + PNS_LAYERSET( top, bottom ), + aVia->GetWidth(), + aVia->GetDrillValue(), + aVia->GetNetCode(), + aVia->GetViaType() ); + + v->SetParent( aVia ); + + return v; +} + + +void PNS_KICAD_IFACE::SetBoard( BOARD* aBoard ) +{ + m_board = aBoard; + TRACE( 1, "m_board = %p\n", m_board ); +} + + +void PNS_KICAD_IFACE::SyncWorld( PNS_NODE *aWorld ) +{ + if( !m_board ) + { + TRACEn( 0, "No board attached, aborting sync." ); + return; + } + + for( MODULE* module = m_board->m_Modules; module; module = module->Next() ) + { + for( D_PAD* pad = module->Pads(); pad; pad = pad->Next() ) + { + PNS_ITEM* solid = syncPad( pad ); + + if( solid ) + aWorld->Add( solid ); + } + } + + for( TRACK* t = m_board->m_Track; t; t = t->Next() ) + { + KICAD_T type = t->Type(); + PNS_ITEM* item = NULL; + + if( type == PCB_TRACE_T ) + item = syncTrack( t ); + else if( type == PCB_VIA_T ) + item = syncVia( static_cast( t ) ); + + if( item ) + aWorld->Add( item ); + } + + int worstClearance = m_board->GetDesignSettings().GetBiggestClearanceValue(); + + if (m_ruleResolver) + delete m_ruleResolver; + + m_ruleResolver = new PNS_PCBNEW_RULE_RESOLVER( m_board, m_router ); + + aWorld->SetRuleResolver( m_ruleResolver ); + aWorld->SetMaxClearance( 4 * worstClearance ); +} + +void PNS_KICAD_IFACE::EraseView() +{ + for ( auto item : m_hiddenItems) + item->ViewSetVisible( true ); + + m_hiddenItems.clear(); + + if( m_previewItems ) + { + m_previewItems->FreeItems(); + m_previewItems->ViewUpdate( KIGFX::VIEW_ITEM::GEOMETRY ); + } +} + +void PNS_KICAD_IFACE::DisplayItem( const PNS_ITEM* aItem, int aColor, int aClearance ) +{ + ROUTER_PREVIEW_ITEM* pitem = new ROUTER_PREVIEW_ITEM( aItem, m_previewItems ); + + if( aColor >= 0 ) + pitem->SetColor( KIGFX::COLOR4D( aColor ) ); + + if( aClearance >= 0 ) + pitem->SetClearance( aClearance ); + + m_previewItems->Add( pitem ); + + pitem->ViewSetVisible( true ); + m_previewItems->ViewUpdate( KIGFX::VIEW_ITEM::GEOMETRY | KIGFX::VIEW_ITEM::APPEARANCE ); +} + +void PNS_KICAD_IFACE::HideItem( PNS_ITEM *aItem ) +{ + BOARD_CONNECTED_ITEM* parent = aItem->Parent(); + + if( parent ) + { + if( parent->ViewIsVisible() ) + m_hiddenItems.insert( parent ); + + parent->ViewSetVisible( false ); + parent->ViewUpdate( KIGFX::VIEW_ITEM::APPEARANCE ); + } +} + +void PNS_KICAD_IFACE::RemoveItem ( PNS_ITEM *aItem ) +{ + BOARD_CONNECTED_ITEM* parent = aItem->Parent(); + + if( parent ) + { + m_view->Remove( parent ); + m_board->Remove( parent ); + m_undoBuffer.PushItem( ITEM_PICKER( parent, UR_DELETED ) ); + } +} + +void PNS_KICAD_IFACE::AddItem ( PNS_ITEM *aItem ) +{ + BOARD_CONNECTED_ITEM* newBI = NULL; + + switch( aItem->Kind() ) + { + case PNS_ITEM::SEGMENT: + { + PNS_SEGMENT* seg = static_cast( aItem ); + TRACK* track = new TRACK( m_board ); + const SEG& s = seg->Seg(); + track->SetStart( wxPoint( s.A.x, s.A.y ) ); + track->SetEnd( wxPoint( s.B.x, s.B.y ) ); + track->SetWidth( seg->Width() ); + track->SetLayer( ToLAYER_ID( seg->Layers().Start() ) ); + track->SetNetCode( seg->Net() > 0 ? seg->Net() : 0 ); + newBI = track; + break; + } + + case PNS_ITEM::VIA: + { + VIA* via_board = new VIA( m_board ); + PNS_VIA* via = static_cast( aItem ); + via_board->SetPosition( wxPoint( via->Pos().x, via->Pos().y ) ); + via_board->SetWidth( via->Diameter() ); + via_board->SetDrill( via->Drill() ); + via_board->SetNetCode( via->Net() > 0 ? via->Net() : 0 ); + via_board->SetViaType( via->ViaType() ); // MUST be before SetLayerPair() + via_board->SetLayerPair( ToLAYER_ID( via->Layers().Start() ), + ToLAYER_ID( via->Layers().End() ) ); + newBI = via_board; + break; + } + + default: + break; + } + + if( newBI ) + { + aItem->SetParent( newBI ); + newBI->ClearFlags(); + m_view->Add( newBI ); + m_board->Add( newBI ); + m_undoBuffer.PushItem( ITEM_PICKER( newBI, UR_NEW ) ); + newBI->ViewUpdate( KIGFX::VIEW_ITEM::GEOMETRY ); + } +} + +void PNS_KICAD_IFACE::Commit() +{ + m_board->GetRatsnest()->Recalculate(); + m_frame->SaveCopyInUndoList( m_undoBuffer, UR_UNSPECIFIED ); + m_undoBuffer.ClearItemsList(); + m_frame->OnModify(); +} + +void PNS_KICAD_IFACE::SetView ( KIGFX::VIEW *aView ) +{ + if( m_previewItems ) + { + m_previewItems->FreeItems(); + delete m_previewItems; + } + + m_view = aView; + m_previewItems = new KIGFX::VIEW_GROUP( m_view ); + m_previewItems->SetLayer( ITEM_GAL_LAYER( GP_OVERLAY ) ); + m_view->Add( m_previewItems ); + m_previewItems->ViewSetVisible( true ); +} + +void PNS_KICAD_IFACE::UpdateNet ( int aNetCode ) +{ + printf("Update-net %d\n", aNetCode); +} + +PNS_RULE_RESOLVER* PNS_KICAD_IFACE::GetRuleResolver() +{ + return m_ruleResolver; +} + +void PNS_KICAD_IFACE::SetRouter( PNS_ROUTER *aRouter ) +{ + m_router = aRouter; +} + +void PNS_KICAD_IFACE::SetHostFrame ( PCB_EDIT_FRAME *aFrame ) +{ + m_frame = aFrame; +} diff --git a/pcbnew/router/pns_kicad_iface.h b/pcbnew/router/pns_kicad_iface.h new file mode 100644 index 0000000000..fb7df8d83f --- /dev/null +++ b/pcbnew/router/pns_kicad_iface.h @@ -0,0 +1,78 @@ +/* + * KiRouter - a push-and-(sometimes-)shove PCB router + * + * Copyright (C) 2013-2016 CERN + * Author: Tomasz Wlostowski + * + * This program is free software: you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation, either version 3 of the License, or (at your + * option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program. If not, see . + */ + +#ifndef __PNS_KICAD_IFACE_H +#define __PNS_KICAD_IFACE_H + +#include + +#include "pns_router.h" + +class PNS_PCBNEW_RULE_RESOLVER; + + +class BOARD; +namespace KIGFX { + class VIEW; + +}; + +class PNS_KICAD_IFACE : public PNS_ROUTER_IFACE { +public: + PNS_KICAD_IFACE (); + ~PNS_KICAD_IFACE (); + + void SetRouter( PNS_ROUTER *aRouter ); + void SetHostFrame ( PCB_EDIT_FRAME *aFrame ); + + void SetBoard( BOARD* aBoard ); + void SetView ( KIGFX::VIEW *aView ); + void SyncWorld( PNS_NODE *aWorld ); + void EraseView(); + void HideItem ( PNS_ITEM *aItem ); + void DisplayItem( const PNS_ITEM* aItem, int aColor = 0, int aClearance = 0); + void AddItem ( PNS_ITEM *aItem ); + void RemoveItem ( PNS_ITEM *aItem ); + void Commit (); + + void UpdateNet ( int aNetCode ); + + PNS_RULE_RESOLVER* GetRuleResolver(); + +private: + + PNS_PCBNEW_RULE_RESOLVER* m_ruleResolver; + + PNS_ITEM* syncPad( D_PAD* aPad ); + PNS_ITEM* syncTrack( TRACK* aTrack ); + PNS_ITEM* syncVia( VIA* aVia ); + + 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; + PICKED_ITEMS_LIST m_undoBuffer; + PCB_EDIT_FRAME *m_frame; +}; + +#endif diff --git a/pcbnew/router/pns_node.cpp b/pcbnew/router/pns_node.cpp index 30355a8862..9fdd172943 100644 --- a/pcbnew/router/pns_node.cpp +++ b/pcbnew/router/pns_node.cpp @@ -52,7 +52,7 @@ PNS_NODE::PNS_NODE() m_root = this; m_parent = NULL; m_maxClearance = 800000; // fixme: depends on how thick traces are. - m_clearanceFunctor = NULL; + m_ruleResolver = NULL; m_index = new PNS_INDEX; m_collisionFilter = NULL; @@ -98,10 +98,10 @@ PNS_NODE::~PNS_NODE() int PNS_NODE::GetClearance( const PNS_ITEM* aA, const PNS_ITEM* aB ) const { - if( !m_clearanceFunctor ) + if( !m_ruleResolver ) return 100000; - return (*m_clearanceFunctor)( aA, aB ); + return m_ruleResolver->Clearance( aA, aB ); } @@ -115,7 +115,7 @@ PNS_NODE* PNS_NODE::Branch() child->m_depth = m_depth + 1; child->m_parent = this; - child->m_clearanceFunctor = m_clearanceFunctor; + child->m_ruleResolver = m_ruleResolver; child->m_root = isRoot() ? this : m_root; child->m_collisionFilter = m_collisionFilter; diff --git a/pcbnew/router/pns_node.h b/pcbnew/router/pns_node.h index 9846da85d9..6f8217b4a2 100644 --- a/pcbnew/router/pns_node.h +++ b/pcbnew/router/pns_node.h @@ -45,45 +45,26 @@ class PNS_INDEX; class PNS_ROUTER; /** - * Class PNS_CLEARANCE_FUNC + * Class PNS_RULE_RESOLVER * - * An abstract function object, returning a required clearance between two items. + * An abstract function object, returning a design rule (clearance, diff pair gap, etc) required between two items. **/ -class PNS_CLEARANCE_FUNC + +class PNS_RULE_RESOLVER { public: - virtual ~PNS_CLEARANCE_FUNC() {} - virtual int operator()( const PNS_ITEM* aA, const PNS_ITEM* aB ) = 0; + virtual ~PNS_RULE_RESOLVER() {} + + virtual int Clearance( const PNS_ITEM* aA, const PNS_ITEM* aB ) = 0; virtual void OverrideClearance (bool aEnable, int aNetA = 0, int aNetB = 0, int aClearance = 0) = 0; + virtual void UseDpGap( bool aUseDpGap ) = 0; + virtual int DpCoupledNet( int aNet ) = 0; + virtual int DpNetPolarity( int aNet ) = 0; + virtual bool DpNetPair( PNS_ITEM* aItem, int& aNetP, int& aNetN ) = 0; + + }; -class PNS_PCBNEW_CLEARANCE_FUNC : public PNS_CLEARANCE_FUNC -{ -public: - PNS_PCBNEW_CLEARANCE_FUNC( PNS_ROUTER *aRouter ); - virtual ~PNS_PCBNEW_CLEARANCE_FUNC(); - - virtual int operator()( const PNS_ITEM* aA, const PNS_ITEM* aB ); - virtual void OverrideClearance (bool aEnable, int aNetA = 0, int aNetB = 0, int aClearance = 0); - - void UseDpGap( bool aUseDpGap ) { m_useDpGap = aUseDpGap; } - -private: - struct CLEARANCE_ENT { - int coupledNet; - int clearance; - }; - - PNS_ROUTER *m_router; - - int localPadClearance( const PNS_ITEM* aItem ) const; - std::vector m_clearanceCache; - int m_defaultClearance; - bool m_overrideEnabled; - int m_overrideNetA, m_overrideNetB; - int m_overrideClearance; - bool m_useDpGap; -}; /** * Struct PNS_OBSTACLE @@ -157,9 +138,14 @@ public: } ///> Assigns a clerance resolution function object - void SetClearanceFunctor( PNS_CLEARANCE_FUNC* aFunc ) + void SetRuleResolver( PNS_RULE_RESOLVER* aFunc ) { - m_clearanceFunctor = aFunc; + m_ruleResolver = aFunc; + } + + PNS_RULE_RESOLVER* GetRuleResolver() + { + return m_ruleResolver; } ///> Returns the number of joints @@ -469,8 +455,8 @@ private: ///> worst case item-item clearance int m_maxClearance; - ///> Clearance resolution functor - PNS_CLEARANCE_FUNC* m_clearanceFunctor; + ///> Design rules resolver + PNS_RULE_RESOLVER* m_ruleResolver; ///> Geometric/Net index of the items PNS_INDEX* m_index; diff --git a/pcbnew/router/pns_router.cpp b/pcbnew/router/pns_router.cpp index 4c15fe83f9..dc2dda3968 100644 --- a/pcbnew/router/pns_router.cpp +++ b/pcbnew/router/pns_router.cpp @@ -33,8 +33,6 @@ #include #include -#include - #include "trace.h" #include "pns_node.h" #include "pns_line_placer.h" @@ -65,430 +63,14 @@ // To be fixed sometime in the future. static PNS_ROUTER* theRouter; - -PNS_PCBNEW_CLEARANCE_FUNC::PNS_PCBNEW_CLEARANCE_FUNC( PNS_ROUTER* aRouter ) : - m_router( aRouter ) -{ - BOARD* brd = m_router->GetBoard(); - PNS_NODE* world = m_router->GetWorld(); - - PNS_TOPOLOGY topo( world ); - m_clearanceCache.resize( brd->GetNetCount() ); - m_useDpGap = false; - - for( unsigned int i = 0; i < brd->GetNetCount(); i++ ) - { - NETINFO_ITEM* ni = brd->FindNet( i ); - if( ni == NULL ) - continue; - - CLEARANCE_ENT ent; - ent.coupledNet = topo.DpCoupledNet( i ); - - wxString netClassName = ni->GetClassName(); - NETCLASSPTR nc = brd->GetDesignSettings().m_NetClasses.Find( netClassName ); - - int clearance = nc->GetClearance(); - ent.clearance = clearance; - m_clearanceCache[i] = ent; - - TRACE( 1, "Add net %d netclass %s clearance %d", i % netClassName.mb_str() % - clearance ); - } - - m_overrideEnabled = false; - m_defaultClearance = Millimeter2iu( 0.254 ); // aBoard->m_NetClasses.Find ("Default clearance")->GetClearance(); - m_overrideNetA = 0; - m_overrideNetB = 0; - m_overrideClearance = 0; -} - - -PNS_PCBNEW_CLEARANCE_FUNC::~PNS_PCBNEW_CLEARANCE_FUNC() -{ -} - - -int PNS_PCBNEW_CLEARANCE_FUNC::localPadClearance( const PNS_ITEM* aItem ) const -{ - if( !aItem->Parent() || aItem->Parent()->Type() != PCB_PAD_T ) - return 0; - - const D_PAD* pad = static_cast( aItem->Parent() ); - return pad->GetLocalClearance(); -} - - -int PNS_PCBNEW_CLEARANCE_FUNC::operator()( const PNS_ITEM* aA, const PNS_ITEM* aB ) -{ - int net_a = aA->Net(); - int cl_a = ( net_a >= 0 ? m_clearanceCache[net_a].clearance : m_defaultClearance ); - int net_b = aB->Net(); - int cl_b = ( net_b >= 0 ? m_clearanceCache[net_b].clearance : m_defaultClearance ); - - bool linesOnly = aA->OfKind( PNS_ITEM::SEGMENT | PNS_ITEM::LINE ) && aB->OfKind( PNS_ITEM::SEGMENT | PNS_ITEM::LINE ); - - if( net_a == net_b ) - return 0; - - if( m_useDpGap && linesOnly && net_a >= 0 && net_b >= 0 && m_clearanceCache[net_a].coupledNet == net_b ) - { - cl_a = cl_b = m_router->Sizes().DiffPairGap() - 2 * PNS_HULL_MARGIN; - } - - int pad_a = localPadClearance( aA ); - int pad_b = localPadClearance( aB ); - - cl_a = std::max( cl_a, pad_a ); - cl_b = std::max( cl_b, pad_b ); - - return std::max( cl_a, cl_b ); -} - - -// fixme: ugly hack to make the optimizer respect gap width for currently routed differential pair. -void PNS_PCBNEW_CLEARANCE_FUNC::OverrideClearance( bool aEnable, int aNetA, int aNetB , int aClearance ) -{ - m_overrideEnabled = aEnable; - m_overrideNetA = aNetA; - m_overrideNetB = aNetB; - m_overrideClearance = aClearance; -} - - -PNS_ITEM* PNS_ROUTER::syncPad( D_PAD* aPad ) -{ - PNS_LAYERSET layers( 0, MAX_CU_LAYERS - 1 ); - - // ignore non-copper pads - if ( (aPad->GetLayerSet() & LSET::AllCuMask()).none() ) - return NULL; - - switch( aPad->GetAttribute() ) - { - case PAD_ATTRIB_STANDARD: - break; - - case PAD_ATTRIB_SMD: - case PAD_ATTRIB_HOLE_NOT_PLATED: - case PAD_ATTRIB_CONN: - { - LSET lmsk = aPad->GetLayerSet(); - bool is_copper = false; - - for( int i = 0; i < MAX_CU_LAYERS; i++ ) - { - if( lmsk[i] ) - { - is_copper = true; - if( aPad->GetAttribute() != PAD_ATTRIB_HOLE_NOT_PLATED ) - layers = PNS_LAYERSET( i ); - break; - } - } - - if( !is_copper ) - return NULL; - } - break; - - default: - TRACE( 0, "unsupported pad type 0x%x", aPad->GetAttribute() ); - return NULL; - } - - PNS_SOLID* solid = new PNS_SOLID; - - solid->SetLayers( layers ); - solid->SetNet( aPad->GetNetCode() ); - solid->SetParent( aPad ); - - wxPoint wx_c = aPad->ShapePos(); - wxSize wx_sz = aPad->GetSize(); - wxPoint offset = aPad->GetOffset(); - - VECTOR2I c( wx_c.x, wx_c.y ); - VECTOR2I sz( wx_sz.x, wx_sz.y ); - - RotatePoint( &offset, aPad->GetOrientation() ); - - solid->SetPos( VECTOR2I( c.x - offset.x, c.y - offset.y ) ); - solid->SetOffset ( VECTOR2I ( offset.x, offset.y ) ); - - double orient = aPad->GetOrientation() / 10.0; - - if( aPad->GetShape() == PAD_SHAPE_CIRCLE ) - { - solid->SetShape( new SHAPE_CIRCLE( c, sz.x / 2 ) ); - } - else - { - if( orient == 0.0 || orient == 90.0 || orient == 180.0 || orient == 270.0 ) - { - if( orient == 90.0 || orient == 270.0 ) - sz = VECTOR2I( sz.y, sz.x ); - - switch( aPad->GetShape() ) - { - case PAD_SHAPE_OVAL: - if( sz.x == sz.y ) - solid->SetShape( new SHAPE_CIRCLE( c, sz.x / 2 ) ); - else - { - VECTOR2I delta; - - if( sz.x > sz.y ) - delta = VECTOR2I( ( sz.x - sz.y ) / 2, 0 ); - else - delta = VECTOR2I( 0, ( sz.y - sz.x ) / 2 ); - - SHAPE_SEGMENT* shape = new SHAPE_SEGMENT( c - delta, c + delta, - std::min( sz.x, sz.y ) ); - solid->SetShape( shape ); - } - break; - - case PAD_SHAPE_RECT: - solid->SetShape( new SHAPE_RECT( c - sz / 2, sz.x, sz.y ) ); - break; - - case PAD_SHAPE_TRAPEZOID: - { - wxPoint coords[4]; - aPad->BuildPadPolygon( coords, wxSize( 0, 0 ), aPad->GetOrientation() ); - SHAPE_CONVEX* shape = new SHAPE_CONVEX(); - - for( int ii = 0; ii < 4; ii++ ) - { - shape->Append( wx_c + coords[ii] ); - } - - solid->SetShape( shape ); - break; - } - - case PAD_SHAPE_ROUNDRECT: - { - SHAPE_POLY_SET outline; - const int segmentToCircleCount = 64; - - aPad->BuildPadShapePolygon( outline, wxSize( 0, 0 ), - segmentToCircleCount, 1.0 ); - - // TransformRoundRectToPolygon creates only one convex polygon - SHAPE_LINE_CHAIN& poly = outline.Outline( 0 ); - SHAPE_CONVEX* shape = new SHAPE_CONVEX(); - - for( int ii = 0; ii < poly.PointCount(); ++ii ) - { - shape->Append( wxPoint( poly.Point( ii ).x, poly.Point( ii ).y ) ); - } - - solid->SetShape( shape ); - } - break; - - default: - TRACEn( 0, "unsupported pad shape" ); - delete solid; - return NULL; - } - } - else - { - switch( aPad->GetShape() ) - { - // PAD_SHAPE_CIRCLE already handled above - - case PAD_SHAPE_OVAL: - if( sz.x == sz.y ) - solid->SetShape( new SHAPE_CIRCLE( c, sz.x / 2 ) ); - else - { - wxPoint start; - wxPoint end; - wxPoint corner; - - SHAPE_CONVEX* shape = new SHAPE_CONVEX(); - - int w = aPad->BuildSegmentFromOvalShape( start, end, 0.0, wxSize( 0, 0 ) ); - - if( start.y == 0 ) - corner = wxPoint( start.x, -( w / 2 ) ); - else - corner = wxPoint( w / 2, start.y ); - - RotatePoint( &start, aPad->GetOrientation() ); - RotatePoint( &corner, aPad->GetOrientation() ); - shape->Append( wx_c + corner ); - - for( int rot = 100; rot <= 1800; rot += 100 ) - { - wxPoint p( corner ); - RotatePoint( &p, start, rot ); - shape->Append( wx_c + p ); - } - - if( end.y == 0 ) - corner = wxPoint( end.x, w / 2 ); - else - corner = wxPoint( -( w / 2 ), end.y ); - - RotatePoint( &end, aPad->GetOrientation() ); - RotatePoint( &corner, aPad->GetOrientation() ); - shape->Append( wx_c + corner ); - - for( int rot = 100; rot <= 1800; rot += 100 ) - { - wxPoint p( corner ); - RotatePoint( &p, end, rot ); - shape->Append( wx_c + p ); - } - - solid->SetShape( shape ); - } - break; - - case PAD_SHAPE_RECT: - case PAD_SHAPE_TRAPEZOID: - { - wxPoint coords[4]; - aPad->BuildPadPolygon( coords, wxSize( 0, 0 ), aPad->GetOrientation() ); - - SHAPE_CONVEX* shape = new SHAPE_CONVEX(); - for( int ii = 0; ii < 4; ii++ ) - { - shape->Append( wx_c + coords[ii] ); - } - - solid->SetShape( shape ); - break; - } - - case PAD_SHAPE_ROUNDRECT: - { - SHAPE_POLY_SET outline; - const int segmentToCircleCount = 32; - aPad->BuildPadShapePolygon( outline, wxSize( 0, 0 ), - segmentToCircleCount, 1.0 ); - - // TransformRoundRectToPolygon creates only one convex polygon - SHAPE_LINE_CHAIN& poly = outline.Outline( 0 ); - SHAPE_CONVEX* shape = new SHAPE_CONVEX(); - - for( int ii = 0; ii < poly.PointCount(); ++ii ) - { - shape->Append( wxPoint( poly.Point( ii ).x, poly.Point( ii ).y ) ); - } - - solid->SetShape( shape ); - } - break; - - default: - TRACEn( 0, "unsupported pad shape" ); - delete solid; - - return NULL; - } - } - } - return solid; -} - - -PNS_ITEM* PNS_ROUTER::syncTrack( TRACK* aTrack ) -{ - PNS_SEGMENT* s = - new PNS_SEGMENT( SEG( aTrack->GetStart(), aTrack->GetEnd() ), aTrack->GetNetCode() ); - - s->SetWidth( aTrack->GetWidth() ); - s->SetLayers( PNS_LAYERSET( aTrack->GetLayer() ) ); - s->SetParent( aTrack ); - return s; -} - - -PNS_ITEM* PNS_ROUTER::syncVia( VIA* aVia ) -{ - LAYER_ID top, bottom; - aVia->LayerPair( &top, &bottom ); - PNS_VIA* v = new PNS_VIA( - aVia->GetPosition(), - PNS_LAYERSET( top, bottom ), - aVia->GetWidth(), - aVia->GetDrillValue(), - aVia->GetNetCode(), - aVia->GetViaType() ); - - v->SetParent( aVia ); - - return v; -} - - -void PNS_ROUTER::SetBoard( BOARD* aBoard ) -{ - m_board = aBoard; - TRACE( 1, "m_board = %p\n", m_board ); -} - - -void PNS_ROUTER::SyncWorld() -{ - if( !m_board ) - { - TRACEn( 0, "No board attached, aborting sync." ); - return; - } - - ClearWorld(); - - m_world = new PNS_NODE(); - - for( MODULE* module = m_board->m_Modules; module; module = module->Next() ) - { - for( D_PAD* pad = module->Pads(); pad; pad = pad->Next() ) - { - PNS_ITEM* solid = syncPad( pad ); - - if( solid ) - m_world->Add( solid ); - } - } - - for( TRACK* t = m_board->m_Track; t; t = t->Next() ) - { - KICAD_T type = t->Type(); - PNS_ITEM* item = NULL; - - if( type == PCB_TRACE_T ) - item = syncTrack( t ); - else if( type == PCB_VIA_T ) - item = syncVia( static_cast( t ) ); - - if( item ) - m_world->Add( item ); - } - - int worstClearance = m_board->GetDesignSettings().GetBiggestClearanceValue(); - m_clearanceFunc = new PNS_PCBNEW_CLEARANCE_FUNC( this ); - m_world->SetClearanceFunctor( m_clearanceFunc ); - m_world->SetMaxClearance( 4 * worstClearance ); -} - - PNS_ROUTER::PNS_ROUTER() { theRouter = this; - m_clearanceFunc = NULL; m_state = IDLE; m_world = NULL; m_placer = NULL; - m_previewItems = NULL; - m_board = NULL; m_dragger = NULL; m_mode = PNS_MODE_ROUTE_SINGLE; @@ -501,27 +83,11 @@ PNS_ROUTER::PNS_ROUTER() m_view = NULL; m_snappingEnabled = false; m_violation = false; - m_gridHelper = NULL; +// m_gridHelper = NULL; } -void PNS_ROUTER::SetView( KIGFX::VIEW* aView ) -{ - if( m_previewItems ) - { - m_previewItems->FreeItems(); - delete m_previewItems; - } - - m_view = aView; - m_previewItems = new KIGFX::VIEW_GROUP( m_view ); - m_previewItems->SetLayer( ITEM_GAL_LAYER( GP_OVERLAY ) ); - m_view->Add( m_previewItems ); - m_previewItems->ViewSetVisible( true ); -} - - PNS_ROUTER* PNS_ROUTER::GetInstance() { return theRouter; @@ -532,11 +98,16 @@ PNS_ROUTER::~PNS_ROUTER() { ClearWorld(); theRouter = NULL; - - if( m_previewItems ) - delete m_previewItems; } +void PNS_ROUTER::SyncWorld( ) +{ + ClearWorld(); + + m_world = new PNS_NODE; + m_iface->SyncWorld( m_world ); + +} void PNS_ROUTER::ClearWorld() { @@ -546,19 +117,12 @@ void PNS_ROUTER::ClearWorld() delete m_world; } - if( m_clearanceFunc ) - delete m_clearanceFunc; - if( m_placer ) delete m_placer; - if( m_previewItems ) - delete m_previewItems; - m_clearanceFunc = NULL; m_world = NULL; m_placer = NULL; - m_previewItems = NULL; } @@ -615,8 +179,13 @@ const VECTOR2I PNS_ROUTER::SnapToItem( PNS_ITEM* aItem, VECTOR2I aP, bool& aSpli anchor = s.B; else { - anchor = m_gridHelper->AlignToSegment ( aP, s ); - aSplitsSegment = (anchor != s.A && anchor != s.B ); +// fixme: alignment! + anchor = s.NearestPoint( aP ); + aSplitsSegment = true; + +// anchor = m_gridHelper->AlignToSegment ( aP, s ); + // aSplitsSegment = (anchor != s.A && anchor != s.B ); + } break; @@ -652,29 +221,26 @@ bool PNS_ROUTER::StartDragging( const VECTOR2I& aP, PNS_ITEM* aStartItem ) bool PNS_ROUTER::StartRouting( const VECTOR2I& aP, PNS_ITEM* aStartItem, int aLayer ) { - m_clearanceFunc->UseDpGap( false ); - switch( m_mode ) { - case PNS_MODE_ROUTE_SINGLE: - m_placer = new PNS_LINE_PLACER( this ); - break; - case PNS_MODE_ROUTE_DIFF_PAIR: - m_placer = new PNS_DIFF_PAIR_PLACER( this ); - m_clearanceFunc->UseDpGap( true ); - break; - case PNS_MODE_TUNE_SINGLE: - m_placer = new PNS_MEANDER_PLACER( this ); - break; - case PNS_MODE_TUNE_DIFF_PAIR: - m_placer = new PNS_DP_MEANDER_PLACER( this ); - break; - case PNS_MODE_TUNE_DIFF_PAIR_SKEW: - m_placer = new PNS_MEANDER_SKEW_PLACER( this ); - break; + case PNS_MODE_ROUTE_SINGLE: + m_placer = new PNS_LINE_PLACER( this ); + break; + case PNS_MODE_ROUTE_DIFF_PAIR: + m_placer = new PNS_DIFF_PAIR_PLACER( this ); + break; + case PNS_MODE_TUNE_SINGLE: + m_placer = new PNS_MEANDER_PLACER( this ); + break; + case PNS_MODE_TUNE_DIFF_PAIR: + m_placer = new PNS_DP_MEANDER_PLACER( this ); + break; + case PNS_MODE_TUNE_DIFF_PAIR_SKEW: + m_placer = new PNS_MEANDER_SKEW_PLACER( this ); + break; - default: - return false; + default: + return false; } m_placer->UpdateSizes ( m_sizes ); @@ -691,72 +257,31 @@ bool PNS_ROUTER::StartRouting( const VECTOR2I& aP, PNS_ITEM* aStartItem, int aLa } -BOARD* PNS_ROUTER::GetBoard() -{ - return m_board; -} - - -void PNS_ROUTER::eraseView() -{ - for( BOARD_ITEM* item : m_hiddenItems ) - { - item->ViewSetVisible( true ); - } - - m_hiddenItems.clear(); - - if( m_previewItems ) - { - m_previewItems->FreeItems(); - m_previewItems->ViewUpdate( KIGFX::VIEW_ITEM::GEOMETRY ); - } -} - - -void PNS_ROUTER::DisplayItem( const PNS_ITEM* aItem, int aColor, int aClearance ) -{ - ROUTER_PREVIEW_ITEM* pitem = new ROUTER_PREVIEW_ITEM( aItem, m_previewItems ); - - if( aColor >= 0 ) - pitem->SetColor( KIGFX::COLOR4D( aColor ) ); - - if( aClearance >= 0 ) - pitem->SetClearance( aClearance ); - - m_previewItems->Add( pitem ); - - pitem->ViewSetVisible( true ); - m_previewItems->ViewUpdate( KIGFX::VIEW_ITEM::GEOMETRY | KIGFX::VIEW_ITEM::APPEARANCE ); -} - - void PNS_ROUTER::DisplayItems( const PNS_ITEMSET& aItems ) { for( const PNS_ITEM* item : aItems.CItems() ) - DisplayItem( item ); + m_iface->DisplayItem( item ); } - void PNS_ROUTER::DisplayDebugLine( const SHAPE_LINE_CHAIN& aLine, int aType, int aWidth ) { - ROUTER_PREVIEW_ITEM* pitem = new ROUTER_PREVIEW_ITEM( NULL, m_previewItems ); +/* ROUTER_PREVIEW_ITEM* pitem = new ROUTER_PREVIEW_ITEM( NULL, m_previewItems ); pitem->Line( aLine, aWidth, aType ); m_previewItems->Add( pitem ); pitem->ViewSetVisible( true ); - m_previewItems->ViewUpdate( KIGFX::VIEW_ITEM::GEOMETRY | KIGFX::VIEW_ITEM::APPEARANCE ); + m_previewItems->ViewUpdate( KIGFX::VIEW_ITEM::GEOMETRY | KIGFX::VIEW_ITEM::APPEARANCE );*/ } void PNS_ROUTER::DisplayDebugPoint( const VECTOR2I aPos, int aType ) { - ROUTER_PREVIEW_ITEM* pitem = new ROUTER_PREVIEW_ITEM( NULL, m_previewItems ); +/* ROUTER_PREVIEW_ITEM* pitem = new ROUTER_PREVIEW_ITEM( NULL, m_previewItems ); pitem->Point( aPos, aType ); m_previewItems->Add( pitem ); pitem->ViewSetVisible( true ); - m_previewItems->ViewUpdate( KIGFX::VIEW_ITEM::GEOMETRY | KIGFX::VIEW_ITEM::APPEARANCE ); + m_previewItems->ViewUpdate( KIGFX::VIEW_ITEM::GEOMETRY | KIGFX::VIEW_ITEM::APPEARANCE );*/ } @@ -782,7 +307,7 @@ void PNS_ROUTER::Move( const VECTOR2I& aP, PNS_ITEM* endItem ) void PNS_ROUTER::moveDragging( const VECTOR2I& aP, PNS_ITEM* aEndItem ) { - eraseView(); + m_iface->EraseView(); m_dragger->Drag( aP ); PNS_ITEMSET dragged = m_dragger->Traces(); @@ -816,7 +341,7 @@ void PNS_ROUTER::markViolations( PNS_NODE* aNode, PNS_ITEMSET& aCurrent, int clearance = aNode->GetClearance( item, obs.m_item ); std::unique_ptr tmp( obs.m_item->Clone() ); tmp->Mark( MK_VIOLATION ); - DisplayItem( tmp.get(), -1, clearance ); + m_iface->DisplayItem( tmp.get(), -1, clearance ); aRemoved.push_back( obs.m_item ); } } @@ -836,24 +361,11 @@ void PNS_ROUTER::updateView( PNS_NODE* aNode, PNS_ITEMSET& aCurrent ) aNode->GetUpdatedItems( removed, added ); - for( PNS_ITEM* item : added ) - { - DisplayItem( item ); - } + for ( auto item : added ) + m_iface->DisplayItem( item ); - for( PNS_ITEM* item : removed ) - { - BOARD_CONNECTED_ITEM* parent = item->Parent(); - - if( parent ) - { - if( parent->ViewIsVisible() ) - m_hiddenItems.insert( parent ); - - parent->ViewSetVisible( false ); - parent->ViewUpdate( KIGFX::VIEW_ITEM::APPEARANCE ); - } - } + for ( auto item : removed ) + m_iface->HideItem ( item ); } @@ -871,7 +383,7 @@ void PNS_ROUTER::UpdateSizes ( const PNS_SIZES_SETTINGS& aSizes ) void PNS_ROUTER::movePlacing( const VECTOR2I& aP, PNS_ITEM* aEndItem ) { - eraseView(); + m_iface->EraseView(); m_placer->Move( aP, aEndItem ); PNS_ITEMSET current = m_placer->Traces(); @@ -882,10 +394,10 @@ void PNS_ROUTER::movePlacing( const VECTOR2I& aP, PNS_ITEM* aEndItem ) continue; const PNS_LINE* l = static_cast( item ); - DisplayItem( l ); + m_iface->DisplayItem( l ); if( l->EndsWithVia() ) - DisplayItem( &l->Via() ); + m_iface->DisplayItem( &l->Via() ); } //PNS_ITEMSET tmp( ¤t ); @@ -900,70 +412,13 @@ void PNS_ROUTER::CommitRouting( PNS_NODE* aNode ) aNode->GetUpdatedItems( removed, added ); - for( unsigned int i = 0; i < removed.size(); i++ ) - { - BOARD_CONNECTED_ITEM* parent = removed[i]->Parent(); + for ( auto item : removed ) + m_iface->RemoveItem ( item ); - if( parent ) - { - m_view->Remove( parent ); - m_board->Remove( parent ); - m_undoBuffer.PushItem( ITEM_PICKER( parent, UR_DELETED ) ); - } - } + for ( auto item : added ) + m_iface->AddItem( item ); - for( PNS_ITEM* item : added ) - { - BOARD_CONNECTED_ITEM* newBI = NULL; - - switch( item->Kind() ) - { - case PNS_ITEM::SEGMENT: - { - PNS_SEGMENT* seg = static_cast( item ); - TRACK* track = new TRACK( m_board ); - const SEG& s = seg->Seg(); - - track->SetStart( wxPoint( s.A.x, s.A.y ) ); - track->SetEnd( wxPoint( s.B.x, s.B.y ) ); - track->SetWidth( seg->Width() ); - track->SetLayer( ToLAYER_ID( seg->Layers().Start() ) ); - track->SetNetCode( seg->Net() > 0 ? seg->Net() : 0 ); - newBI = track; - break; - } - - case PNS_ITEM::VIA: - { - VIA* via_board = new VIA( m_board ); - PNS_VIA* via = static_cast( item ); - via_board->SetPosition( wxPoint( via->Pos().x, via->Pos().y ) ); - via_board->SetWidth( via->Diameter() ); - via_board->SetDrill( via->Drill() ); - via_board->SetNetCode( via->Net() > 0 ? via->Net() : 0 ); - via_board->SetViaType( via->ViaType() ); // MUST be before SetLayerPair() - via_board->SetLayerPair( ToLAYER_ID( via->Layers().Start() ), - ToLAYER_ID( via->Layers().End() ) ); - newBI = via_board; - break; - } - - default: - break; - } - - if( newBI ) - { - item->SetParent( newBI ); - newBI->ClearFlags(); - m_view->Add( newBI ); - m_board->Add( newBI ); - m_undoBuffer.PushItem( ITEM_PICKER( newBI, UR_NEW ) ); - newBI->ViewUpdate( KIGFX::VIEW_ITEM::GEOMETRY ); - } - } - - m_board->GetRatsnest()->Recalculate(); + m_iface->Commit(); m_world->Commit( aNode ); } @@ -1002,11 +457,9 @@ void PNS_ROUTER::StopRouting() std::vector nets; m_placer->GetModifiedNets( nets ); - for( int n : nets ) - { - // Update the ratsnest with new changes - m_board->GetRatsnest()->Recalculate( n ); - } + // Update the ratsnest with new changes + for ( auto n : nets ) + m_iface->UpdateNet( n ); } if( !RoutingInProgress() ) @@ -1021,7 +474,7 @@ void PNS_ROUTER::StopRouting() m_placer = NULL; m_dragger = NULL; - eraseView(); + m_iface->EraseView(); m_state = IDLE; m_world->KillChildren(); @@ -1123,3 +576,9 @@ void PNS_ROUTER::SetMode( PNS_ROUTER_MODE aMode ) { m_mode = aMode; } + +void PNS_ROUTER::SetInterface( PNS_ROUTER_IFACE *aIface ) +{ + m_iface = aIface; + m_iface->SetRouter( this ); +} diff --git a/pcbnew/router/pns_router.h b/pcbnew/router/pns_router.h index 4bc4bc30dd..f9a422e34d 100644 --- a/pcbnew/router/pns_router.h +++ b/pcbnew/router/pns_router.h @@ -51,7 +51,7 @@ class PNS_SOLID; class PNS_SEGMENT; class PNS_JOINT; class PNS_VIA; -class PNS_CLEARANCE_FUNC; +class PNS_RULE_RESOLVER; class PNS_SHOVE; class PNS_DRAGGER; @@ -75,6 +75,28 @@ enum PNS_ROUTER_MODE { * * Main router class. */ + + class PNS_ROUTER_IFACE + { + public: + PNS_ROUTER_IFACE() {}; + virtual ~PNS_ROUTER_IFACE() {}; + + virtual void SetRouter ( PNS_ROUTER *aRouter ) = 0; + virtual void SyncWorld ( PNS_NODE *aNode ) = 0; + virtual void AddItem ( PNS_ITEM *aItem ) = 0; + virtual void RemoveItem ( PNS_ITEM *aItem ) = 0; + virtual void DisplayItem( const PNS_ITEM* aItem, int aColor = -1, int aClearance = -1 ) = 0; + virtual void HideItem ( PNS_ITEM *aItem ) = 0; + virtual void Commit () = 0; +// virtual void Abort () = 0; + + virtual void EraseView () = 0; + virtual void UpdateNet ( int aNetCode ) = 0; + + virtual PNS_RULE_RESOLVER* GetRuleResolver() = 0; +}; + class PNS_ROUTER { private: @@ -89,13 +111,13 @@ public: PNS_ROUTER(); ~PNS_ROUTER(); + void SetInterface( PNS_ROUTER_IFACE *aIface ); void SetMode ( PNS_ROUTER_MODE aMode ); PNS_ROUTER_MODE Mode() const { return m_mode; } static PNS_ROUTER* GetInstance(); void ClearWorld(); - void SetBoard( BOARD* aBoard ); void SyncWorld(); void SetView( KIGFX::VIEW* aView ); @@ -122,6 +144,7 @@ public: void DisplayDebugLine( const SHAPE_LINE_CHAIN& aLine, int aType = 0, int aWidth = 0 ); void DisplayDebugPoint( const VECTOR2I aPos, int aType = 0 ); void DisplayDebugBox( const BOX2I& aBox, int aType = 0, int aWidth = 0 ); + void DeleteTraces( PNS_ITEM *aStartItem, bool aWholeTrack ); void SwitchLayer( int layer ); @@ -133,10 +156,11 @@ public: void DumpLog(); - PNS_CLEARANCE_FUNC* GetClearanceFunc() const + PNS_RULE_RESOLVER* GetRuleResolver() const { - return m_clearanceFunc; + return m_iface->GetRuleResolver(); } + bool IsPlacingVia() const; const PNS_ITEMSET QueryHoverItems( const VECTOR2I& aP ); @@ -209,7 +233,6 @@ public: PNS_ITEM *QueryItemByParent ( const BOARD_ITEM *aItem ) const; - BOARD *GetBoard(); void SetFailureReason ( const wxString& aReason ) { m_failureReason = aReason; } const wxString& FailureReason() const { return m_failureReason; } @@ -221,6 +244,11 @@ public: m_gridHelper = aGridHelper; } + PNS_ROUTER_IFACE *GetInterface() const + { + return m_iface; + } + private: void movePlacing( const VECTOR2I& aP, PNS_ITEM* aItem ); void moveDragging( const VECTOR2I& aP, PNS_ITEM* aItem ); @@ -250,27 +278,24 @@ private: VECTOR2I m_currentEnd; RouterState m_state; - BOARD* m_board; + //BOARD* m_board; PNS_NODE* m_world; PNS_NODE* m_lastNode; PNS_PLACEMENT_ALGO * m_placer; PNS_DRAGGER* m_dragger; PNS_SHOVE* m_shove; + PNS_ROUTER_IFACE *m_iface; + int m_iterLimit; bool m_showInterSteps; int m_snapshotIter; KIGFX::VIEW* m_view; - KIGFX::VIEW_GROUP* m_previewItems; bool m_snappingEnabled; bool m_violation; PNS_ROUTING_SETTINGS m_settings; - PNS_PCBNEW_CLEARANCE_FUNC* m_clearanceFunc; - - boost::unordered_set m_hiddenItems; - ///> Stores list of modified items in the current operation PICKED_ITEMS_LIST m_undoBuffer; PNS_SIZES_SETTINGS m_sizes; diff --git a/pcbnew/router/pns_tool_base.cpp b/pcbnew/router/pns_tool_base.cpp index 504f24cb81..336d795336 100644 --- a/pcbnew/router/pns_tool_base.cpp +++ b/pcbnew/router/pns_tool_base.cpp @@ -46,6 +46,7 @@ using namespace std::placeholders; #include +#include "pns_kicad_iface.h" #include "pns_tool_base.h" #include "pns_segment.h" #include "pns_router.h" @@ -71,8 +72,6 @@ PNS_TOOL_BASE::PNS_TOOL_BASE( const std::string& aToolName ) : m_endItem = NULL; - m_needsSync = false; - m_frame = NULL; m_ctls = NULL; m_board = NULL; @@ -96,25 +95,26 @@ void PNS_TOOL_BASE::Reset( RESET_REASON aReason ) if( m_gridHelper) delete m_gridHelper; + m_frame = getEditFrame(); m_ctls = getViewControls(); m_board = getModel(); - m_router = new PNS_ROUTER; + m_iface = new PNS_KICAD_IFACE; + m_iface->SetBoard (m_board); + m_iface->SetView( getView() ); + m_iface->SetHostFrame ( m_frame ); + + m_router = new PNS_ROUTER; + m_router->SetInterface(m_iface); m_router->ClearWorld(); - m_router->SetBoard( m_board ); m_router->SyncWorld(); m_router->LoadSettings( m_savedSettings ); m_router->UpdateSizes( m_savedSizes ); m_gridHelper = new GRID_HELPER( m_frame ); m_router->SetGrid( m_gridHelper ); - - m_needsSync = false; - - if( getView() ) - m_router->SetView( getView() ); } @@ -306,3 +306,33 @@ void PNS_TOOL_BASE::updateEndItem( TOOL_EVENT& aEvent ) TRACE( 0, "%s, layer : %d", m_endItem->KindStr().c_str() % m_endItem->Layers().Start() ); } +#if 0 +void PNS_TOOL_BASE::DeleteTraces( PNS_ITEM *aStartItem, bool aWholeTrack ) +{ + PNS_NODE *node = m_router->GetWorld()->Branch(); + + if( !aStartItem ) + return; + + if ( !aWholeTrack ) + { + node->Remove ( aStartItem ); + } + else + { + PNS_TOPOLOGY topo (node); + PNS_ITEMSET path = topo.AssembleTrivialPath( aStartItem ); + + for ( auto ent : path.Items() ) + node->Remove( ent.item ); + } + + m_router->CommitRouting( node ); + +} +#endif + +PNS_ROUTER *PNS_TOOL_BASE::Router() const +{ + return m_router; +} diff --git a/pcbnew/router/pns_tool_base.h b/pcbnew/router/pns_tool_base.h index 20bed42382..b6973e7cee 100644 --- a/pcbnew/router/pns_tool_base.h +++ b/pcbnew/router/pns_tool_base.h @@ -33,6 +33,7 @@ class PNS_TUNE_STATUS_POPUP; class GRID_HELPER; +class PNS_KICAD_IFACE; class APIEXPORT PNS_TOOL_BASE : public TOOL_INTERACTIVE { @@ -49,6 +50,8 @@ public: return m_savedSettings; } + PNS_ROUTER *Router() const; + protected: virtual PNS_ITEM* pickSingleItem( const VECTOR2I& aWhere, int aNet = -1, int aLayer = -1 ); @@ -58,7 +61,6 @@ protected: MSG_PANEL_ITEMS m_panelItems; - PNS_ROUTER* m_router; PNS_ROUTING_SETTINGS m_savedSettings; ///< Stores routing settings between router invocations PNS_SIZES_SETTINGS m_savedSizes; ///< Stores sizes settings between router invocations PNS_ITEM* m_startItem; @@ -68,13 +70,12 @@ protected: PNS_ITEM* m_endItem; VECTOR2I m_endSnapPoint; - ///> Flag marking that the router's world needs syncing. - bool m_needsSync; - PCB_EDIT_FRAME* m_frame; KIGFX::VIEW_CONTROLS* m_ctls; BOARD* m_board; GRID_HELPER* m_gridHelper; + PNS_KICAD_IFACE *m_iface; + PNS_ROUTER *m_router; }; diff --git a/pcbnew/router/pns_topology.cpp b/pcbnew/router/pns_topology.cpp index df1e3c6086..a386bc85ad 100644 --- a/pcbnew/router/pns_topology.cpp +++ b/pcbnew/router/pns_topology.cpp @@ -230,12 +230,31 @@ bool PNS_TOPOLOGY::followTrivialPath( PNS_LINE* aLine, bool aLeft, PNS_ITEMSET& } -const PNS_ITEMSET PNS_TOPOLOGY::AssembleTrivialPath( PNS_SEGMENT* aStart ) +const PNS_ITEMSET PNS_TOPOLOGY::AssembleTrivialPath( PNS_ITEM* aStart ) { PNS_ITEMSET path; std::set visited; + PNS_SEGMENT *seg; + PNS_VIA *via; - PNS_LINE l = m_world->AssembleLine( aStart ); + seg = dyn_cast (aStart); + + if(!seg && (via = dyn_cast( aStart ) ) ) + { + PNS_JOINT *jt = m_world->FindJoint( via->Pos(), via ); + + if( !jt->IsNonFanoutVia () ) + return PNS_ITEMSET(); + + for ( auto entry : jt->Links().Items() ) + if ( ( seg = dyn_cast( entry.item ) ) ) + break; + } + + if( !seg ) + return PNS_ITEMSET(); + + PNS_LINE l = m_world->AssembleLine( seg ); path.Add( l ); @@ -258,72 +277,6 @@ const PNS_ITEMSET PNS_TOPOLOGY::ConnectedItems( PNS_ITEM* aStart, int aKindMask } -int PNS_TOPOLOGY::MatchDpSuffix( wxString aNetName, wxString& aComplementNet, wxString& aBaseDpName ) -{ - int rv = 0; - - if( aNetName.EndsWith( "+" ) ) - { - aComplementNet = "-"; - rv = 1; - } - else if( aNetName.EndsWith( "_P" ) ) - { - aComplementNet = "_N"; - rv = 1; - } - else if( aNetName.EndsWith( "-" ) ) - { - aComplementNet = "+"; - rv = -1; - } - else if( aNetName.EndsWith( "_N" ) ) - { - aComplementNet = "_P"; - rv = -1; - } - - if( rv != 0 ) - { - aBaseDpName = aNetName.Left( aNetName.Length() - aComplementNet.Length() ); - aComplementNet = aBaseDpName + aComplementNet; - } - - return rv; -} - - -int PNS_TOPOLOGY::DpCoupledNet( int aNet ) -{ - BOARD* brd = PNS_ROUTER::GetInstance()->GetBoard(); - - wxString refName = brd->FindNet( aNet )->GetNetname(); - wxString dummy, coupledNetName; - - if( MatchDpSuffix( refName, coupledNetName, dummy ) ) - { - NETINFO_ITEM* net = brd->FindNet( coupledNetName ); - - if( !net ) - return -1; - - return net->GetNet(); - - } - - return -1; -} - - -int PNS_TOPOLOGY::DpNetPolarity( int aNet ) -{ - BOARD* brd = PNS_ROUTER::GetInstance()->GetBoard(); - - wxString refName = brd->FindNet( aNet )->GetNetname(); - wxString dummy1, dummy2; - - return MatchDpSuffix( refName, dummy1, dummy2 ); -} bool commonParallelProjection( SEG n, SEG p, SEG &pClip, SEG& nClip ); @@ -332,7 +285,7 @@ bool commonParallelProjection( SEG n, SEG p, SEG &pClip, SEG& nClip ); bool PNS_TOPOLOGY::AssembleDiffPair( PNS_ITEM* aStart, PNS_DIFF_PAIR& aPair ) { int refNet = aStart->Net(); - int coupledNet = DpCoupledNet( refNet ); + int coupledNet = m_world->GetRuleResolver()->DpCoupledNet( refNet ); if( coupledNet < 0 ) return false; @@ -378,7 +331,7 @@ bool PNS_TOPOLOGY::AssembleDiffPair( PNS_ITEM* aStart, PNS_DIFF_PAIR& aPair ) PNS_LINE lp = m_world->AssembleLine( refSeg ); PNS_LINE ln = m_world->AssembleLine( coupledSeg ); - if( DpNetPolarity( refNet ) < 0 ) + if( m_world->GetRuleResolver()->DpNetPolarity( refNet ) < 0 ) { std::swap( lp, ln ); } diff --git a/pcbnew/router/pns_topology.h b/pcbnew/router/pns_topology.h index bbc36a875a..5a5a130afc 100644 --- a/pcbnew/router/pns_topology.h +++ b/pcbnew/router/pns_topology.h @@ -52,10 +52,9 @@ public: const PNS_ITEMSET ConnectedItems( PNS_ITEM* aStart, int aKindMask = PNS_ITEM::ANY ); int64_t ShortestConnectionLength( PNS_ITEM* aFrom, PNS_ITEM* aTo ); - const PNS_ITEMSET AssembleTrivialPath( PNS_SEGMENT* aStart ); + const PNS_ITEMSET AssembleTrivialPath( PNS_ITEM* aStart ); const PNS_DIFF_PAIR AssembleDiffPair( PNS_SEGMENT* aStart ); - int MatchDpSuffix( wxString aNetName, wxString& aComplementNet, wxString& aBaseDpName ); int DpCoupledNet( int aNet ); int DpNetPolarity( int aNet ); const PNS_LINE DpCoupledLine( PNS_LINE* aLine ); diff --git a/pcbnew/router/router_tool.cpp b/pcbnew/router/router_tool.cpp index 66e4931caa..443e92997c 100644 --- a/pcbnew/router/router_tool.cpp +++ b/pcbnew/router/router_tool.cpp @@ -687,13 +687,6 @@ int ROUTER_TOOL::mainLoop( PNS_ROUTER_MODE aMode ) // Main loop: keep receiving events while( OPT_TOOL_EVENT evt = Wait() ) { - if( m_needsSync ) - { - m_router->SyncWorld(); - m_router->SetView( getView() ); - m_needsSync = false; - } - if( evt->IsCancel() || evt->IsActivate() ) break; // Finish else if( evt->IsMotion() ) @@ -715,6 +708,14 @@ int ROUTER_TOOL::mainLoop( PNS_ROUTER_MODE aMode ) else if( evt->IsAction( &ACT_PlaceThroughVia ) ) { m_toolMgr->RunAction( COMMON_ACTIONS::layerToggle, true ); + } else if (evt->IsAction ( &COMMON_ACTIONS::remove ) ) + { + printf("delitemcursor\n"); + //m_router->DeleteTraces( m_startItem, true ); + } else if (evt->IsAction ( &COMMON_ACTIONS::removeAlt ) ) + { + printf("delitemcursor [alt]\n"); + //m_router->DeleteTraces( m_startItem, false ); } handleCommonEvents( *evt ); @@ -796,7 +797,6 @@ int ROUTER_TOOL::InlineDrag( const TOOL_EVENT& aEvent ) Activate(); m_router->SyncWorld(); - m_router->SetView( getView() ); m_startItem = m_router->GetWorld()->FindItemByParent( item ); @@ -849,4 +849,3 @@ int ROUTER_TOOL::InlineDrag( const TOOL_EVENT& aEvent ) return 0; } -