diff --git a/pcbnew/drc/drc_engine.h b/pcbnew/drc/drc_engine.h index a8917e70a7..46363aa69a 100644 --- a/pcbnew/drc/drc_engine.h +++ b/pcbnew/drc/drc_engine.h @@ -46,6 +46,7 @@ class REPORTER; namespace KIGFX { class WS_PROXY_VIEW_ITEM; + class VIEW_OVERLAY; }; void drcPrintDebugMessage( int level, const wxString& msg, const char *function, int line ); @@ -96,6 +97,10 @@ public: void SetWorksheet( KIGFX::WS_PROXY_VIEW_ITEM* aWorksheet ) { m_worksheet = aWorksheet; } KIGFX::WS_PROXY_VIEW_ITEM* GetWorksheet() const { return m_worksheet; } + void SetDebugOverlay( std::shared_ptr aOverlay ) { m_debugOverlay = aOverlay; } + std::shared_ptr GetDebugOverlay() const { return m_debugOverlay; } + + /** * Set an optional DRC violation handler (receives DRC_ITEMs and positions). */ @@ -224,6 +229,7 @@ protected: PROGRESS_REPORTER* m_progressReporter; wxString m_msg; // Allocating strings gets expensive enough to want to avoid it + std::shared_ptr m_debugOverlay; }; #endif // DRC_H diff --git a/pcbnew/drc/drc_rtree.h b/pcbnew/drc/drc_rtree.h index 7fb02a08de..03e9d6058e 100644 --- a/pcbnew/drc/drc_rtree.h +++ b/pcbnew/drc/drc_rtree.h @@ -239,8 +239,8 @@ public: bool CheckColliding( SHAPE* aRefShape, PCB_LAYER_ID aTargetLayer, - int aClearance = 0 - ) + int aClearance = 0, + std::function aFilter = nullptr ) { BOX2I box = aRefShape->BBox(); box.Inflate( aClearance ); @@ -254,6 +254,10 @@ public: { int actual; + // keep searching + if( aFilter && ! aFilter( aItem->parent ) ) + return true; + bool colliding = aRefShape->Collide( aItem->shape, aClearance, &actual ); if( colliding ) diff --git a/pcbnew/drc/drc_test_provider_diff_pair_coupling.cpp b/pcbnew/drc/drc_test_provider_diff_pair_coupling.cpp index 8192cac8aa..7be28e9f8e 100644 --- a/pcbnew/drc/drc_test_provider_diff_pair_coupling.cpp +++ b/pcbnew/drc/drc_test_provider_diff_pair_coupling.cpp @@ -256,6 +256,7 @@ struct DIFF_PAIR_KEY SEG coupledN, coupledP; TRACK* parentN, *parentP; int computedGap; + PCB_LAYER_ID layer; bool couplingOK; }; @@ -270,10 +271,11 @@ struct DIFF_PAIR_KEY static void extractDiffPairCoupledItems( DIFF_PAIR_ITEMS& aDp, DRC_RTREE& aTree ) { - for( BOARD_CONNECTED_ITEM* itemP : aDp.itemsP ) { auto sp = dyn_cast( itemP ); + OPT bestCoupled; + int bestGap = std::numeric_limits::max(); if(!sp) continue; @@ -298,28 +300,61 @@ static void extractDiffPairCoupledItems( DIFF_PAIR_ITEMS& aDp, DRC_RTREE& aTree if( coupled ) { - SHAPE_SEGMENT checkSegStart( cpair.coupledP.A, cpair.coupledN.A ); - SHAPE_SEGMENT checkSegEnd( cpair.coupledP.B, cpair.coupledN.B ); + cpair.parentP = sp; + cpair.parentN = sn; + cpair.layer = sp->GetLayer(); - // check if there's anyting in between the segments suspected to be coupled. If - // there's nothing, assume they are really coupled. - - if( !aTree.CheckColliding( &checkSegStart, sp->GetLayer() ) - && !aTree.CheckColliding( &checkSegEnd, sp->GetLayer() ) ) + int gap = (cpair.coupledP.A - cpair.coupledN.A).EuclideanNorm(); + if( gap < bestGap ) { - - cpair.parentP = sp; - cpair.parentN = sn; - - aDp.coupled.push_back( cpair ); + bestGap = gap; + bestCoupled = cpair; } } + } } + + if( bestCoupled ) + { + printf("Best-gap %d\n", bestGap ); + auto excludeSelf = [&] ( BOARD_ITEM *aItem ) + { + if( aItem == bestCoupled->parentN || aItem == bestCoupled->parentP ) + { + return false; + } + + if( aItem->Type() == PCB_TRACE_T || aItem->Type() == PCB_VIA_T ) + { + auto bci = static_cast( aItem ); + + if( bci->GetNetCode() == bestCoupled->parentN->GetNetCode() + || bci->GetNetCode() == bestCoupled->parentP->GetNetCode() ) + return false; + } + + return true; + }; + + SHAPE_SEGMENT checkSegStart( bestCoupled->coupledP.A, bestCoupled->coupledN.A ); + SHAPE_SEGMENT checkSegEnd( bestCoupled->coupledP.B, bestCoupled->coupledN.B ); + + // check if there's anyting in between the segments suspected to be coupled. If + // there's nothing, assume they are really coupled. + + if( !aTree.CheckColliding( &checkSegStart, sp->GetLayer(), 0, excludeSelf ) + && !aTree.CheckColliding( &checkSegEnd, sp->GetLayer(), 0, excludeSelf ) ) + { + aDp.coupled.push_back( *bestCoupled ); + } + + } } } + bool test::DRC_TEST_PROVIDER_DIFF_PAIR_COUPLING::Run() { m_board = m_drcEngine->GetBoard(); @@ -338,6 +373,8 @@ bool test::DRC_TEST_PROVIDER_DIFF_PAIR_COUPLING::Run() if( !isNetADiffPair( m_board, refNet, key.netP, key.netN ) ) // not our business return true; + drc_dbg(10, "eval dp %p\n", item ); + const DRC_CONSTRAINT_TYPE_T constraintsToCheck[] = { DRC_CONSTRAINT_TYPE_DIFF_PAIR_GAP, DRC_CONSTRAINT_TYPE_DIFF_PAIR_MAX_UNCOUPLED @@ -350,6 +387,8 @@ bool test::DRC_TEST_PROVIDER_DIFF_PAIR_COUPLING::Run() if( constraint.IsNull() ) continue; + drc_dbg(10, "cns %d item %p\n", constraintsToCheck[i], item ); + key.parentRule = constraint.GetParentRule(); if( refNet == key.netN ) @@ -366,6 +405,8 @@ bool test::DRC_TEST_PROVIDER_DIFF_PAIR_COUPLING::Run() forEachGeometryItem( { PCB_TRACE_T, PCB_VIA_T, PCB_ARC_T }, LSET::AllCuMask(), evaluateDpConstraints ); + drc_dbg(10, "dp rule matches %d\n", dpRuleMatches.size() ); + DRC_RTREE copperTree; @@ -430,6 +471,21 @@ bool test::DRC_TEST_PROVIDER_DIFF_PAIR_COUPLING::Run() cpair.computedGap = gap; + auto overlay = m_drcEngine->GetDebugOverlay(); + + printf("Overlay %p\n", overlay.get () ); + + if( overlay ) + { + overlay->SetIsFill(false); + overlay->SetIsStroke(true); + overlay->SetStrokeColor( RED ); + overlay->SetLineWidth( 100000 ); + overlay->Line( cpair.coupledP ); + overlay->SetStrokeColor( BLUE ); + overlay->Line( cpair.coupledN ); + } + drc_dbg(10, " len %d gap %d l %d\n", length, gap, cpair.parentP->GetLayer() ); if( gapConstraint )