From dd6213051df1323956bbd4a13f7d107f810a5e1a Mon Sep 17 00:00:00 2001 From: Alex Shvartzkop Date: Tue, 20 Feb 2024 22:05:57 +0300 Subject: [PATCH] Pick DP coupled segment closest to start item and baseline. --- pcbnew/generators/pcb_tuning_pattern.cpp | 65 ++++++++++++++---------- pcbnew/router/pns_topology.cpp | 51 +++++++++++++++---- 2 files changed, 80 insertions(+), 36 deletions(-) diff --git a/pcbnew/generators/pcb_tuning_pattern.cpp b/pcbnew/generators/pcb_tuning_pattern.cpp index 3b979fb1eb..e2f6b782c1 100644 --- a/pcbnew/generators/pcb_tuning_pattern.cpp +++ b/pcbnew/generators/pcb_tuning_pattern.cpp @@ -786,33 +786,25 @@ void PCB_TUNING_PATTERN::EditStart( GENERATOR_TOOL* aTool, BOARD* aBoard, BOARD_ static PNS::LINKED_ITEM* pickSegment( PNS::ROUTER* aRouter, const VECTOR2I& aWhere, int aLayer, - VECTOR2I& aPointOut ) + VECTOR2I& aPointOut, + const SHAPE_LINE_CHAIN& aBaseline = SHAPE_LINE_CHAIN() ) { - int maxSlopRadius = aRouter->Sizes().Clearance() + aRouter->Sizes().TrackWidth() / 2; + int maxSlopRadius = aRouter->Sizes().Clearance() + aRouter->Sizes().TrackWidth() / 2; + bool checkBaseline = aBaseline.SegmentCount() > 0; static const int candidateCount = 2; PNS::LINKED_ITEM* prioritized[candidateCount]; SEG::ecoord dist[candidateCount]; + SEG::ecoord distBaseline[candidateCount]; VECTOR2I point[candidateCount]; for( int i = 0; i < candidateCount; i++ ) { prioritized[i] = nullptr; dist[i] = VECTOR2I::ECOORD_MAX; + distBaseline[i] = VECTOR2I::ECOORD_MAX; } - auto haveCandidates = - [&]() - { - for( PNS::ITEM* item : prioritized ) - { - if( item ) - return true; - } - - return false; - }; - for( int slopRadius : { 0, maxSlopRadius } ) { PNS::ITEM_SET candidates = aRouter->QueryHoverItems( aWhere, slopRadius ); @@ -837,12 +829,22 @@ static PNS::LINKED_ITEM* pickSegment( PNS::ROUTER* aRouter, const VECTOR2I& aWhe VECTOR2I nearest = pnsArc->Arc().NearestPoint( aWhere ); SEG::ecoord d0 = ( nearest - aWhere ).SquaredEuclideanNorm(); - if( d0 <= dist[1] ) + if( d0 > dist[1] ) + continue; + + if( checkBaseline ) { - prioritized[1] = linked; - dist[1] = d0; - point[1] = nearest; + SEG::ecoord dcBaseline = aBaseline.SquaredDistance( pnsArc->Arc().GetArcMid() ); + + if( dcBaseline > distBaseline[1] ) + continue; + + distBaseline[1] = dcBaseline; } + + prioritized[1] = linked; + dist[1] = d0; + point[1] = nearest; } else if( item->Kind() & PNS::ITEM::SEGMENT_T ) { @@ -851,17 +853,24 @@ static PNS::LINKED_ITEM* pickSegment( PNS::ROUTER* aRouter, const VECTOR2I& aWhe VECTOR2I nearest = segm->CLine().NearestPoint( aWhere, false ); SEG::ecoord dd = ( aWhere - nearest ).SquaredEuclideanNorm(); - if( dd <= dist[1] ) + if( dd > dist[1] ) + continue; + + if( checkBaseline ) { - prioritized[1] = segm; - dist[1] = dd; - point[1] = nearest; + SEG::ecoord dcBaseline = aBaseline.SquaredDistance( segm->Shape()->Centre() ); + + if( dcBaseline > distBaseline[1] ) + continue; + + distBaseline[1] = dcBaseline; } + + prioritized[1] = segm; + dist[1] = dd; + point[1] = nearest; } } - - if( haveCandidates() ) - break; } PNS::LINKED_ITEM* rv = nullptr; @@ -1306,8 +1315,10 @@ bool PCB_TUNING_PATTERN::Update( GENERATOR_TOOL* aTool, BOARD* aBoard, BOARD_COM // Snap points VECTOR2I startSnapPoint, endSnapPoint; - PNS::LINKED_ITEM* startItem = pickSegment( router, m_origin, layer, startSnapPoint ); - PNS::LINKED_ITEM* endItem = pickSegment( router, m_end, layer, endSnapPoint ); + wxCHECK( m_baseLine, false ); + + PNS::LINKED_ITEM* startItem = pickSegment( router, m_origin, layer, startSnapPoint, *m_baseLine); + PNS::LINKED_ITEM* endItem = pickSegment( router, m_end, layer, endSnapPoint, *m_baseLine ); wxASSERT( startItem ); wxASSERT( endItem ); diff --git a/pcbnew/router/pns_topology.cpp b/pcbnew/router/pns_topology.cpp index 60e39d3983..f8bfedd0fc 100644 --- a/pcbnew/router/pns_topology.cpp +++ b/pcbnew/router/pns_topology.cpp @@ -500,8 +500,10 @@ bool TOPOLOGY::AssembleDiffPair( ITEM* aStart, DIFF_PAIR& aPair ) LINKED_ITEM* refItem = nullptr; LINKED_ITEM* coupledItem = nullptr; SEG::ecoord minDist_sq = std::numeric_limits::max(); + SEG::ecoord minDistTarget_sq = std::numeric_limits::max(); + VECTOR2I targetPoint = aStart->Shape()->Centre(); - for( ITEM* p_item : pItems ) + auto findNItem = [&]( ITEM* p_item ) { for( ITEM* n_item : nItems ) { @@ -512,8 +514,8 @@ bool TOPOLOGY::AssembleDiffPair( ITEM* aStart, DIFF_PAIR& aPair ) if( p_item->Kind() == ITEM::SEGMENT_T ) { - SEGMENT* p_seg = static_cast( p_item ); - SEGMENT* n_seg = static_cast( n_item ); + const SEGMENT* p_seg = static_cast( p_item ); + const SEGMENT* n_seg = static_cast( n_item ); if( n_seg->Width() != p_seg->Width() ) continue; @@ -530,8 +532,8 @@ bool TOPOLOGY::AssembleDiffPair( ITEM* aStart, DIFF_PAIR& aPair ) } else if( p_item->Kind() == ITEM::ARC_T ) { - ARC* p_arc = static_cast( p_item ); - ARC* n_arc = static_cast( n_item ); + const ARC* p_arc = static_cast( p_item ); + const ARC* n_arc = static_cast( n_item ); if( n_arc->Width() != p_arc->Width() ) continue; @@ -545,13 +547,44 @@ bool TOPOLOGY::AssembleDiffPair( ITEM* aStart, DIFF_PAIR& aPair ) dist_sq = SEG::Square( p_arc->CArc().GetRadius() - n_arc->CArc().GetRadius() ); } - if( dist_sq < minDist_sq ) + if( dist_sq <= minDist_sq ) { - minDist_sq = dist_sq; - refItem = static_cast( p_item ); - coupledItem = static_cast( n_item ); + SEG::ecoord distTarget_sq = n_item->Shape()->SquaredDistance( targetPoint ); + if( distTarget_sq < minDistTarget_sq ) + { + minDistTarget_sq = distTarget_sq; + minDist_sq = dist_sq; + + refItem = static_cast( p_item ); + coupledItem = static_cast( n_item ); + } } } + }; + + findNItem( startItem ); + + if( !coupledItem ) + { + LINKED_ITEM* linked = static_cast( startItem ); + std::set linksToTest; + + for( int i = 0; i < linked->AnchorCount(); i++ ) + { + const JOINT* jt = m_world->FindJoint( linked->Anchor( i ), linked ); + + if( !jt ) + continue; + + for( ITEM* link : jt->LinkList() ) + { + if( link != linked ) + linksToTest.emplace( link ); + } + } + + for( ITEM* link : linksToTest ) + findNItem( link ); } if( !coupledItem )