From fc1b0ec11fdb83262d4c56e1769f61ab70fd489c Mon Sep 17 00:00:00 2001 From: Jeff Young Date: Fri, 1 Jan 2021 17:17:55 +0000 Subject: [PATCH] Improve feedback when routing in highlight collisions mode. In particular, when Allow DRC violations is NOT turned on and we bump in to an obstacle. --- pcbnew/router/pns_item.cpp | 8 +- pcbnew/router/pns_line.cpp | 2 + pcbnew/router/pns_line.h | 23 ++++-- pcbnew/router/pns_line_placer.cpp | 101 +------------------------- pcbnew/router/pns_line_placer.h | 5 -- pcbnew/router/pns_node.cpp | 6 +- pcbnew/router/pns_router.cpp | 36 ++++++--- pcbnew/router/router_preview_item.cpp | 2 +- 8 files changed, 57 insertions(+), 126 deletions(-) diff --git a/pcbnew/router/pns_item.cpp b/pcbnew/router/pns_item.cpp index f37799e63a..0142d083e3 100644 --- a/pcbnew/router/pns_item.cpp +++ b/pcbnew/router/pns_item.cpp @@ -60,13 +60,13 @@ bool ITEM::collideSimple( const ITEM* aOther, const NODE* aNode, bool aDifferent if( holeA && holeA->Collide( shapeB, holeClearance + lineWidthB ) ) { - Mark( MK_HOLE ); + Mark( Marker() | MK_HOLE ); return true; } if( holeB && holeB->Collide( shapeA, holeClearance + lineWidthA ) ) { - aOther->Mark( MK_HOLE ); + aOther->Mark( aOther->Marker() | MK_HOLE ); return true; } @@ -76,8 +76,8 @@ bool ITEM::collideSimple( const ITEM* aOther, const NODE* aNode, bool aDifferent if( holeA->Collide( holeB, holeToHoleClearance ) ) { - Mark( MK_HOLE ); - aOther->Mark( MK_HOLE ); + Mark( Marker() | MK_HOLE ); + aOther->Mark( aOther->Marker() | MK_HOLE ); return true; } } diff --git a/pcbnew/router/pns_line.cpp b/pcbnew/router/pns_line.cpp index fa605c0811..5335ac743c 100644 --- a/pcbnew/router/pns_line.cpp +++ b/pcbnew/router/pns_line.cpp @@ -47,6 +47,7 @@ LINE::LINE( const LINE& aOther ) m_hasVia = aOther.m_hasVia; m_marker = aOther.m_marker; m_rank = aOther.m_rank; + m_blockingObstacle = aOther.m_blockingObstacle; copyLinks( &aOther ); } @@ -70,6 +71,7 @@ LINE& LINE::operator=( const LINE& aOther ) m_rank = aOther.m_rank; m_owner = aOther.m_owner; m_snapThreshhold = aOther.m_snapThreshhold; + m_blockingObstacle = aOther.m_blockingObstacle; copyLinks( &aOther ); diff --git a/pcbnew/router/pns_line.h b/pcbnew/router/pns_line.h index 4ca519b0ca..8a7dbd1f90 100644 --- a/pcbnew/router/pns_line.h +++ b/pcbnew/router/pns_line.h @@ -68,7 +68,8 @@ public: * Makes an empty line. */ LINE() : - LINK_HOLDER( LINE_T ) + LINK_HOLDER( LINE_T ), + m_blockingObstacle( nullptr ) { m_hasVia = false; m_width = 1; // Dummy value @@ -86,7 +87,8 @@ public: LINK_HOLDER( aBase ), m_line( aLine ), m_width( aBase.m_width ), - m_snapThreshhold( aBase.m_snapThreshhold ) + m_snapThreshhold( aBase.m_snapThreshhold ), + m_blockingObstacle( nullptr ) { m_net = aBase.m_net; m_layers = aBase.m_layers; @@ -99,7 +101,8 @@ public: * @param aVia */ LINE( const VIA& aVia ) : - LINK_HOLDER( LINE_T ) + LINK_HOLDER( LINE_T ), + m_blockingObstacle( nullptr ) { m_hasVia = true; m_via = aVia; @@ -204,6 +207,9 @@ public: virtual void Unmark( int aMarker = -1 ) const override; virtual int Marker() const override; + void SetBlockingObstacle( ITEM* aObstacle ) { m_blockingObstacle = aObstacle; } + ITEM* GetBlockingObstacle() const { return m_blockingObstacle; } + void DragSegment( const VECTOR2I& aP, int aIndex, bool aFreeAngle = false ); void DragCorner( const VECTOR2I& aP, int aIndex, bool aFreeAngle = false ); @@ -214,7 +220,6 @@ public: bool HasLockedSegments() const; void Clear(); - void Merge ( const LINE& aOther ); OPT_BOX2I ChangedArea( const LINE* aOther ) const; @@ -240,14 +245,16 @@ private: VECTOR2I snapDraggedCorner( const SHAPE_LINE_CHAIN& aPath, const VECTOR2I& aP, int aIndex ) const; - SHAPE_LINE_CHAIN m_line; ///> The actual shape of the line - int m_width; ///> our width + SHAPE_LINE_CHAIN m_line; ///> The actual shape of the line. + int m_width; ///> Our width. - int m_snapThreshhold; ///> Width to smooth out jagged segments + int m_snapThreshhold; ///> Width to smooth out jagged segments. - bool m_hasVia; ///> Optional via at the end point + bool m_hasVia; ///> Optional via at the end point. VIA m_via; + + ITEM* m_blockingObstacle; ///> For mark obstacle mode. }; } diff --git a/pcbnew/router/pns_line_placer.cpp b/pcbnew/router/pns_line_placer.cpp index e1790d5693..5e17604c9b 100644 --- a/pcbnew/router/pns_line_placer.cpp +++ b/pcbnew/router/pns_line_placer.cpp @@ -479,6 +479,7 @@ bool LINE_PLACER::rhWalkOnly( const VECTOR2I& aP, LINE& aNewHead ) bool LINE_PLACER::rhMarkObstacles( const VECTOR2I& aP, LINE& aNewHead ) { buildInitialLine( aP, m_head ); + m_head.SetBlockingObstacle( nullptr ); // If we are enforcing DRC violations, push back to the hull if( !Settings().CanViolateDRC() ) @@ -486,7 +487,10 @@ bool LINE_PLACER::rhMarkObstacles( const VECTOR2I& aP, LINE& aNewHead ) NODE::OPT_OBSTACLE obs = m_currentNode->NearestObstacle( &m_head ); if( obs && obs->m_distFirst != INT_MAX ) + { buildInitialLine( obs->m_ipFirst, m_head ); + m_head.SetBlockingObstacle( obs->m_item ); + } } aNewHead = m_head; @@ -495,103 +499,6 @@ bool LINE_PLACER::rhMarkObstacles( const VECTOR2I& aP, LINE& aNewHead ) } -const LINE LINE_PLACER::reduceToNearestObstacle( const LINE& aOriginalLine ) -{ - const auto& l0 = aOriginalLine.CLine(); - - if ( !l0.PointCount() ) - return aOriginalLine; - - int l = l0.Length(); - int step = l / 2; - VECTOR2I target; - - LINE l_test( aOriginalLine ); - - while( step > 0 ) - { - target = l0.PointAlong( l ); - SHAPE_LINE_CHAIN l_cur( l0 ); - - int index = l_cur.Split( target ); - - l_test.SetShape( l_cur.Slice( 0, index ) ); - - if ( m_currentNode->CheckColliding( &l_test ) ) - l -= step; - else - l += step; - - step /= 2; - } - - l = l_test.CLine().Length(); - - while( m_currentNode->CheckColliding( &l_test ) && l > 0 ) - { - l--; - target = l0.PointAlong( l ); - SHAPE_LINE_CHAIN l_cur( l0 ); - - int index = l_cur.Split( target ); - - l_test.SetShape( l_cur.Slice( 0, index ) ); - } - - return l_test; -} - - -bool LINE_PLACER::rhStopAtNearestObstacle( const VECTOR2I& aP, LINE& aNewHead ) -{ - LINE l0; - l0 = m_head; - - buildInitialLine( aP, l0 ); - - LINE l_cur = reduceToNearestObstacle( l0 ); - - const SHAPE_LINE_CHAIN l_shape = l_cur.CLine(); - - if( l_shape.SegmentCount() == 0 ) - return false; - - if( l_shape.SegmentCount() == 1 ) - { - SEG s = l_shape.CSegment( 0 ); - - VECTOR2I dL( DIRECTION_45( s ).Left().ToVector() ); - VECTOR2I dR( DIRECTION_45( s ).Right().ToVector() ); - - SEG leadL( s.B, s.B + dL ); - SEG leadR( s.B, s.B + dR ); - - SEG segL( s.B, leadL.LineProject( aP ) ); - SEG segR( s.B, leadR.LineProject( aP ) ); - - LINE finishL( l0, SHAPE_LINE_CHAIN( { segL.A, segL.B } ) ); - LINE finishR( l0, SHAPE_LINE_CHAIN( { segR.A, segR.B } ) ); - - LINE reducedL = reduceToNearestObstacle( finishL ); - LINE reducedR = reduceToNearestObstacle( finishR ); - - int lL = reducedL.CLine().Length(); - int lR = reducedR.CLine().Length(); - - if( lL > lR ) - l_cur.Line().Append( reducedL.CLine() ); - else - l_cur.Line().Append( reducedR.CLine() ); - - l_cur.Line().Simplify(); - } - - m_head = l_cur; - aNewHead = m_head; - return true; -} - - bool LINE_PLACER::rhShoveOnly( const VECTOR2I& aP, LINE& aNewHead ) { LINE initTrack( m_head ); diff --git a/pcbnew/router/pns_line_placer.h b/pcbnew/router/pns_line_placer.h index 492c54d9d9..42a1bab798 100644 --- a/pcbnew/router/pns_line_placer.h +++ b/pcbnew/router/pns_line_placer.h @@ -404,11 +404,6 @@ private: */ void routeStep( const VECTOR2I& aP ); - const LINE reduceToNearestObstacle( const LINE& aOriginalLine ); - - bool rhStopAtNearestObstacle( const VECTOR2I& aP, LINE& aNewHead ); - - ///> route step, walkaround mode bool rhWalkOnly( const VECTOR2I& aP, LINE& aNewHead); diff --git a/pcbnew/router/pns_node.cpp b/pcbnew/router/pns_node.cpp index 88e1bb3546..c208773005 100644 --- a/pcbnew/router/pns_node.cpp +++ b/pcbnew/router/pns_node.cpp @@ -333,8 +333,8 @@ NODE::OPT_OBSTACLE NODE::NearestObstacle( const LINE* aLine, int aKindMask, if( aLine->EndsWithVia() ) { const VIA& via = aLine->Via(); - int viaClearance = GetClearance( obstacle.m_item, &via ); - int holeClearance = GetHoleClearance( obstacle.m_item, &via ); + int viaClearance = GetClearance( obstacle.m_item, &via ); + int holeClearance = GetHoleClearance( obstacle.m_item, &via ); if( holeClearance + via.Drill() / 2 > viaClearance + via.Diameter() / 2 ) viaClearance = holeClearance + via.Drill() / 2 - via.Diameter() / 2; @@ -396,6 +396,7 @@ NODE::OPT_OBSTACLE NODE::NearestObstacle( const LINE* aLine, int aKindMask, { int dist = aLine->CLine().Length() + ( ip.p - via.Pos() ).EuclideanNorm(); updateNearest( dist, ip.p, obstacle.m_item, obstacleHull ); + obstacle.m_item->Mark( obstacle.m_item->Marker() | MK_HOLE ); } } @@ -406,6 +407,7 @@ NODE::OPT_OBSTACLE NODE::NearestObstacle( const LINE* aLine, int aKindMask, { int dist = aLine->CLine().PathLength( ip.p ); updateNearest( dist, ip.p, obstacle.m_item, obstacleHull ); + obstacle.m_item->Mark( obstacle.m_item->Marker() | MK_HOLE ); } } } diff --git a/pcbnew/router/pns_router.cpp b/pcbnew/router/pns_router.cpp index 0baafc6dba..dece1e5bac 100644 --- a/pcbnew/router/pns_router.cpp +++ b/pcbnew/router/pns_router.cpp @@ -289,6 +289,24 @@ void ROUTER::moveDragging( const VECTOR2I& aP, ITEM* aEndItem ) void ROUTER::markViolations( NODE* aNode, ITEM_SET& aCurrent, NODE::ITEM_VECTOR& aRemoved ) { + auto updateItem = + [&]( ITEM* currentItem, ITEM* itemToMark ) + { + std::unique_ptr tmp( itemToMark->Clone() ); + int clearance; + + if( itemToMark->Marker() & MK_HOLE ) + clearance = aNode->GetHoleClearance( currentItem, itemToMark ); + else + clearance = aNode->GetClearance( currentItem, itemToMark ); + + m_iface->DisplayItem( tmp.get(), -1, clearance ); + + // Remove the obstacle itself from the view unless we're just marking its hole + if( itemToMark->Marker() & MK_HOLE ) + aRemoved.push_back( itemToMark ); + }; + for( ITEM* item : aCurrent.Items() ) { NODE::OBSTACLES obstacles; @@ -308,17 +326,17 @@ void ROUTER::markViolations( NODE* aNode, ITEM_SET& aCurrent, NODE::ITEM_VECTOR& for( OBSTACLE& obs : obstacles ) { - int clearance; + obs.m_item->Mark( obs.m_item->Marker() | MK_VIOLATION ); + updateItem( item, obs.m_item ); + } - if( ( obs.m_item->Marker() & MK_HOLE ) > 0 ) - clearance = aNode->GetHoleClearance( item, obs.m_item ); - else - clearance = aNode->GetClearance( item, obs.m_item ); + if( item->Kind() == ITEM::LINE_T ) + { + LINE* line = static_cast( item ); - std::unique_ptr tmp( obs.m_item->Clone() ); - tmp->Mark( tmp->Marker() | MK_VIOLATION ); - m_iface->DisplayItem( tmp.get(), -1, clearance ); - aRemoved.push_back( obs.m_item ); + // Show clearance on any blocking obstacles + if( line->GetBlockingObstacle() ) + updateItem( item, line->GetBlockingObstacle() ); } } } diff --git a/pcbnew/router/router_preview_item.cpp b/pcbnew/router/router_preview_item.cpp index a54dfca446..ca384757f4 100644 --- a/pcbnew/router/router_preview_item.cpp +++ b/pcbnew/router/router_preview_item.cpp @@ -86,7 +86,7 @@ void ROUTER_PREVIEW_ITEM::Update( const PNS::ITEM* aItem ) m_color.a = 0.8; m_depth = BaseOverlayDepth - aItem->Layers().Start(); - if(( aItem->Marker() & PNS::MK_HOLE ) && aItem->Hole() ) + if( ( aItem->Marker() & PNS::MK_HOLE ) && aItem->Hole() ) m_shape = aItem->Hole()->Clone(); else m_shape = aItem->Shape()->Clone();