diff --git a/pcbnew/router/CMakeLists.txt b/pcbnew/router/CMakeLists.txt index a1c96ebbba..ad3df6d870 100644 --- a/pcbnew/router/CMakeLists.txt +++ b/pcbnew/router/CMakeLists.txt @@ -19,6 +19,7 @@ set( PCBNEW_PNS_SRCS pns_diff_pair_placer.cpp pns_dp_meander_placer.cpp pns_dragger.cpp + pns_hole.cpp pns_index.cpp pns_item.cpp pns_itemset.cpp diff --git a/pcbnew/router/pns_hole.cpp b/pcbnew/router/pns_hole.cpp index 8c8fd46fa0..92c08d06d8 100644 --- a/pcbnew/router/pns_hole.cpp +++ b/pcbnew/router/pns_hole.cpp @@ -1,7 +1,7 @@ /* * KiRouter - a push-and-(sometimes-)shove PCB router * - * Copyright (C) 2022 KiCad Developers, see AUTHORS.txt for contributors. + * Copyright (C) 2022-2023 KiCad Developers, see AUTHORS.txt for contributors. * * @author Tomasz Wlostowski * diff --git a/pcbnew/router/pns_hole.h b/pcbnew/router/pns_hole.h index 670add3100..f75de4668b 100644 --- a/pcbnew/router/pns_hole.h +++ b/pcbnew/router/pns_hole.h @@ -1,7 +1,7 @@ /* * KiRouter - a push-and-(sometimes-)shove PCB router * - * Copyright (C) 2016-2021 KiCad Developers, see AUTHORS.txt for contributors. + * Copyright (C) 2016-2023 KiCad Developers, see AUTHORS.txt for contributors. * * @author Tomasz Wlostowski * diff --git a/pcbnew/router/pns_item.cpp b/pcbnew/router/pns_item.cpp index 1b9cd7d93a..cfde15d769 100644 --- a/pcbnew/router/pns_item.cpp +++ b/pcbnew/router/pns_item.cpp @@ -2,7 +2,7 @@ * KiRouter - a push-and-(sometimes-)shove PCB router * * Copyright (C) 2013-2014 CERN - * Copyright (C) 2016-2022 KiCad Developers, see AUTHORS.txt for contributors. + * Copyright (C) 2016-2023 KiCad Developers, see AUTHORS.txt for contributors. * Author: Tomasz Wlostowski * * This program is free software: you can redistribute it and/or modify it @@ -35,13 +35,14 @@ namespace PNS { static void dumpObstacles( const PNS::NODE::OBSTACLES &obstacles ) { - printf("&&&& %d obstacles: \n", obstacles.size() ); + printf( "&&&& %lu obstacles: \n", obstacles.size() ); for( const auto& obs : obstacles ) { - printf("%p [%s] - %p [%s], clearance %d\n", obs.m_head, obs.m_head->KindStr().c_str(), - obs.m_item, obs.m_item->KindStr().c_str(), - obs.m_clearance ); + printf( "%p [%s] - %p [%s], clearance %d\n", + obs.m_head, obs.m_head->KindStr().c_str(), + obs.m_item, obs.m_item->KindStr().c_str(), + obs.m_clearance ); } } @@ -59,7 +60,7 @@ bool ITEM::collideSimple( const ITEM* aHead, const NODE* aNode, int clearanceEpsilon = aNode->GetRuleResolver()->ClearanceEpsilon(); bool collisionsFound = false; - printf("******************** CollideSimple %d\n", aCtx->obstacles.size() ); + printf( "******************** CollideSimple %lu\n", aCtx->obstacles.size() ); //printf( "h %p n %p t %p ctx %p\n", aHead, aNode, this, aCtx ); @@ -301,11 +302,11 @@ bool ITEM::collideSimple( const ITEM* aHead, const NODE* aNode, obs.m_item = const_cast( this ); obs.m_clearance = clearance; - //printf("i %p h %p ih %p hh %p\n", this ,aHead, holeI, holeH); - printf("HCHX %d %d\n", clearance, clearance + lineWidthH + lineWidthI - clearanceEpsilon); - //printf("pushc %p %p cl %d cle %d\n", obs.m_head, obs.m_item, clearance, clearance + lineWidthH + lineWidthI - clearanceEpsilon ); - //printf("SH %s\n", shapeH->Format().c_str(), aHead ); - //printf("SI %s\n", shapeI->Format().c_str(), this ); + //printf( "i %p h %p ih %p hh %p\n", this ,aHead, holeI, holeH ); + printf( "HCHX %d %d\n", clearance, clearance + lineWidthH + lineWidthI - clearanceEpsilon); + //printf( "pushc %p %p cl %d cle %d\n", obs.m_head, obs.m_item, clearance, clearance + lineWidthH + lineWidthI - clearanceEpsilon ); + //printf( "SH %s\n", shapeH->Format().c_str(), aHead ); + //printf( "SI %s\n", shapeI->Format().c_str(), this ); aCtx->obstacles.insert( obs ); @@ -375,112 +376,6 @@ ITEM::~ITEM() { } -HOLE::~HOLE() -{ - delete m_holeShape; -} - -HOLE* HOLE::Clone() const -{ - HOLE* h = new HOLE( m_parentPadVia, m_holeShape->Clone() ); - - h->SetNet( Net() ); - h->SetLayers( Layers() ); - - h->m_rank = m_rank; - h->m_marker = m_marker; - h->m_parent = m_parent; - h->m_isVirtual = m_isVirtual; - - return h; -} - -const SHAPE_LINE_CHAIN HOLE::Hull( int aClearance, int aWalkaroundThickness, int aLayer ) const -{ - if( !m_holeShape ) - return SHAPE_LINE_CHAIN(); - - if( m_holeShape->Type() == SH_CIRCLE ) - { - auto cir = static_cast( m_holeShape ); - int cl = ( aClearance + aWalkaroundThickness / 2 ); - int width = cir->GetRadius() * 2; - - // Chamfer = width * ( 1 - sqrt(2)/2 ) for equilateral octagon - return OctagonalHull( cir->GetCenter() - VECTOR2I( width / 2, width / 2 ), VECTOR2I( width, width ), cl, - ( 2 * cl + width ) * ( 1.0 - M_SQRT1_2 ) ); - } - else if( m_holeShape->Type() == SH_COMPOUND ) - { - SHAPE_COMPOUND* cmpnd = static_cast( m_holeShape ); - - if ( cmpnd->Shapes().size() == 1 ) - { - return BuildHullForPrimitiveShape( cmpnd->Shapes()[0], aClearance, - aWalkaroundThickness ); - } - else - { - SHAPE_POLY_SET hullSet; - - for( SHAPE* shape : cmpnd->Shapes() ) - { - hullSet.AddOutline( BuildHullForPrimitiveShape( shape, aClearance, - aWalkaroundThickness ) ); - } - - hullSet.Simplify( SHAPE_POLY_SET::PM_STRICTLY_SIMPLE ); - return hullSet.Outline( 0 ); - } - } - else - { - return BuildHullForPrimitiveShape( m_holeShape, aClearance, aWalkaroundThickness ); - } -} - -bool HOLE::IsCircular() const -{ - return m_holeShape->Type() == SH_CIRCLE; -} - -int HOLE::Radius() const -{ - assert( m_holeShape->Type() == SH_CIRCLE ); - - return static_cast( m_holeShape )->GetRadius(); -} - -const VECTOR2I HOLE::Pos() const -{ - return VECTOR2I( 0, 0 ); // fixme holes -} - -void HOLE::SetCenter( const VECTOR2I& aCenter ) -{ - assert( m_holeShape->Type() == SH_CIRCLE ); - static_cast( m_holeShape )->SetCenter( aCenter ); -} -void HOLE::SetRadius( int aRadius ) -{ - assert( m_holeShape->Type() == SH_CIRCLE ); - static_cast( m_holeShape )->SetRadius( aRadius ); -} - - -void HOLE::Move( const VECTOR2I& delta ) -{ - m_holeShape->Move( delta ); -} - -HOLE* HOLE::MakeCircularHole( const VECTOR2I& pos, int radius ) -{ - auto circle = new SHAPE_CIRCLE( pos, radius ); - auto hole = new HOLE( nullptr, circle ); - hole->SetLayers( LAYER_RANGE( F_Cu, B_Cu ) ); - return hole; -} - const std::string ITEM::Format() const { diff --git a/pcbnew/router/pns_item.h b/pcbnew/router/pns_item.h index eea5ff9aec..7fd8963ab1 100644 --- a/pcbnew/router/pns_item.h +++ b/pcbnew/router/pns_item.h @@ -2,7 +2,7 @@ * KiRouter - a push-and-(sometimes-)shove PCB router * * Copyright (C) 2013-2017 CERN - * Copyright (C) 2016-2021 KiCad Developers, see AUTHORS.txt for contributors. + * Copyright (C) 2016-2023 KiCad Developers, see AUTHORS.txt for contributors. * * @author Tomasz Wlostowski * diff --git a/pcbnew/router/pns_kicad_iface.h b/pcbnew/router/pns_kicad_iface.h index 3b903855d3..16b0151ee5 100644 --- a/pcbnew/router/pns_kicad_iface.h +++ b/pcbnew/router/pns_kicad_iface.h @@ -61,7 +61,8 @@ public: bool IsFlashedOnLayer( const PNS::ITEM* aItem, int aLayer ) const override; bool IsItemVisible( const PNS::ITEM* aItem ) const override { return true; }; void HideItem( PNS::ITEM* aItem ) override {} - void DisplayItem( const PNS::ITEM* aItem, int aClearance, bool aEdit = false, bool aIsHeadTrace = false ) override {} + void DisplayItem( const PNS::ITEM* aItem, int aClearance, bool aEdit = false, + bool aIsHeadTrace = false ) override {} void DisplayPathLine( const SHAPE_LINE_CHAIN& aLine, int aImportance ) override {} void DisplayRatline( const SHAPE_LINE_CHAIN& aRatline, int aNetCode ) override {} void AddItem( PNS::ITEM* aItem ) override; diff --git a/pcbnew/router/pns_line.cpp b/pcbnew/router/pns_line.cpp index 55849f5fd1..3848c9ff17 100644 --- a/pcbnew/router/pns_line.cpp +++ b/pcbnew/router/pns_line.cpp @@ -2,7 +2,7 @@ * KiRouter - a push-and-(sometimes-)shove PCB router * * Copyright (C) 2013-2017 CERN - * Copyright (C) 2016-2020 KiCad Developers, see AUTHORS.txt for contributors. + * Copyright (C) 2016-2023 KiCad Developers, see AUTHORS.txt for contributors. * Author: Tomasz Wlostowski * * This program is free software: you can redistribute it and/or modify it @@ -44,8 +44,15 @@ LINE::LINE( const LINE& aOther ) m_net = aOther.m_net; m_movable = aOther.m_movable; m_layers = aOther.m_layers; - m_via = aOther.m_via; - m_hasVia = aOther.m_hasVia; + + m_via = nullptr; + + if( aOther.m_via ) + { + m_via = aOther.m_via->Clone(); + m_via->SetOwner( this ); + } + m_marker = aOther.m_marker; m_rank = aOther.m_rank; m_blockingObstacle = aOther.m_blockingObstacle; @@ -56,6 +63,8 @@ LINE::LINE( const LINE& aOther ) LINE::~LINE() { + if( m_via && m_via->BelongsTo( this ) ) + delete m_via; } @@ -66,8 +75,15 @@ LINE& LINE::operator=( const LINE& aOther ) m_net = aOther.m_net; m_movable = aOther.m_movable; m_layers = aOther.m_layers; - m_via = aOther.m_via; - m_hasVia = aOther.m_hasVia; + + m_via = nullptr; + + if( aOther.m_via ) + { + m_via = aOther.m_via->Clone(); + m_via->SetOwner( this ); + } + m_marker = aOther.m_marker; m_rank = aOther.m_rank; m_owner = aOther.m_owner; @@ -1043,9 +1059,9 @@ void LINE::AppendVia( const VIA& aVia ) Reverse(); } - m_hasVia = true; - m_via = aVia; - m_via.SetNet( m_net ); + m_via = aVia.Clone(); + m_via->SetOwner( this ); + m_via->SetNet( m_net ); } @@ -1251,11 +1267,24 @@ bool LINE::HasLockedSegments() const void LINE::Clear() { - m_hasVia = false; + if( m_via && m_via->BelongsTo( this ) ) + { + delete m_via; + m_via = nullptr; + } m_line.Clear(); } +void LINE::RemoveVia() +{ + if( m_via && m_via->BelongsTo( this ) ) + delete m_via; + + m_via = nullptr; +} + + const std::string SEGMENT::Format( ) const { std::stringstream ss; @@ -1266,3 +1295,4 @@ const std::string SEGMENT::Format( ) const } + diff --git a/pcbnew/router/pns_line.h b/pcbnew/router/pns_line.h index 3fdd10ddad..08cf5cbf77 100644 --- a/pcbnew/router/pns_line.h +++ b/pcbnew/router/pns_line.h @@ -2,7 +2,7 @@ * KiRouter - a push-and-(sometimes-)shove PCB router * * Copyright (C) 2013-2017 CERN - * Copyright (C) 2016-2021 KiCad Developers, see AUTHORS.txt for contributors. + * Copyright (C) 2016-2023 KiCad Developers, see AUTHORS.txt for contributors. * * Author: Tomasz Wlostowski * @@ -67,9 +67,9 @@ public: LINK_HOLDER( LINE_T ), m_blockingObstacle( nullptr ) { - m_hasVia = false; m_width = 1; // Dummy value m_snapThreshhold = 0; + m_via = nullptr; } LINE( const LINE& aOther ); @@ -86,7 +86,7 @@ public: { m_net = aBase.m_net; m_layers = aBase.m_layers; - m_hasVia = false; + m_via = nullptr; } /** @@ -96,8 +96,7 @@ public: LINK_HOLDER( LINE_T ), m_blockingObstacle( nullptr ) { - m_hasVia = true; - m_via = aVia; + m_via = aVia.Clone(); m_width = aVia.Diameter(); m_net = aVia.Net(); m_layers = aVia.Layers(); @@ -127,11 +126,6 @@ public: { m_line = aLine; m_line.SetWidth( m_width ); - - if( m_hasVia && m_line.PointCount() > 0 ) - { - m_via.SetPos( m_line.CPoint( -1 ) ); - } } ///< Return the shape of the line. @@ -191,16 +185,16 @@ public: ///< Print out all linked segments. void ShowLinks() const; - bool EndsWithVia() const { return m_hasVia; } + bool EndsWithVia() const { return m_via != nullptr; } void AppendVia( const VIA& aVia ); - void RemoveVia() { m_hasVia = false; } + void RemoveVia(); - VIA& Via() { return m_via; } - const VIA& Via() const { return m_via; } + VIA& Via() { return *m_via; } + const VIA& Via() const { return *m_via; } - void SetViaDiameter( int aDiameter ) { m_via.SetDiameter( aDiameter ); } - void SetViaDrill( int aDrill ) { m_via.SetDrill( aDrill ); } + void SetViaDiameter( int aDiameter ) { assert(m_via); m_via->SetDiameter( aDiameter ); } + void SetViaDrill( int aDrill ) { assert(m_via); m_via->SetDrill( aDrill ); } virtual void Mark( int aMarker ) const override; virtual void Unmark( int aMarker = -1 ) const override; @@ -250,8 +244,7 @@ private: int m_snapThreshhold; ///< Width to smooth out jagged segments. - bool m_hasVia; ///< Optional via at the end point. - VIA m_via; + VIA* m_via; ITEM* m_blockingObstacle; ///< For mark obstacle mode. }; diff --git a/pcbnew/router/pns_node.cpp b/pcbnew/router/pns_node.cpp index e25f71f6bb..88b1c69dc5 100644 --- a/pcbnew/router/pns_node.cpp +++ b/pcbnew/router/pns_node.cpp @@ -539,17 +539,18 @@ const ITEM_SET NODE::HitTest( const VECTOR2I& aPoint ) const void NODE::addSolid( SOLID* aSolid ) { - if( aSolid->HasHole() ) + if( aSolid->HasHole() && aSolid->Hole()->BelongsTo( aSolid ) ) addHole( aSolid->Hole() ); if( aSolid->IsRoutable() ) linkJoint( aSolid->Pos(), aSolid->Layers(), aSolid->Net(), aSolid ); + aSolid->SetOwner( this ); m_index->Add( aSolid ); } -void NODE::Add( std::unique_ptr< SOLID > aSolid ) +void NODE::Add( std::unique_ptr< SOLID >&& aSolid ) { aSolid->SetOwner( this ); addSolid( aSolid.release() ); @@ -558,10 +559,11 @@ void NODE::Add( std::unique_ptr< SOLID > aSolid ) void NODE::addVia( VIA* aVia ) { - if( aVia->HasHole() ) + if( aVia->HasHole() && aVia->Hole()->BelongsTo( aVia ) ) addHole( aVia->Hole() ); linkJoint( aVia->Pos(), aVia->Layers(), aVia->Net(), aVia ); + aVia->SetOwner( this ); m_index->Add( aVia ); } @@ -572,20 +574,18 @@ void NODE::addHole( HOLE* aHole ) // do we need holes in the connection graph? //linkJoint( aHole->Pos(), aHole->Layers(), aHole->Net(), aHole ); + aHole->SetOwner( this ); m_index->Add( aHole ); } -void NODE::Add( std::unique_ptr< VIA > aVia ) +void NODE::Add( std::unique_ptr< VIA >&& aVia ) { - aVia->SetOwner( this ); addVia( aVia.release() ); } -void NODE::Add( ITEM* aItem, bool aAllowRedundant ) +void NODE::add( ITEM* aItem, bool aAllowRedundant ) { - aItem->SetOwner( this ); - switch( aItem->Kind() ) { case ITEM::ARC_T: @@ -660,6 +660,8 @@ void NODE::Add( LINE& aLine, bool aAllowRedundant ) void NODE::addSegment( SEGMENT* aSeg ) { + aSeg->SetOwner( this ); + linkJoint( aSeg->Seg().A, aSeg->Layers(), aSeg->Net(), aSeg ); linkJoint( aSeg->Seg().B, aSeg->Layers(), aSeg->Net(), aSeg ); @@ -667,7 +669,7 @@ void NODE::addSegment( SEGMENT* aSeg ) } -bool NODE::Add( std::unique_ptr< SEGMENT > aSegment, bool aAllowRedundant ) +bool NODE::Add( std::unique_ptr< SEGMENT >&& aSegment, bool aAllowRedundant ) { if( aSegment->Seg().A == aSegment->Seg().B ) { @@ -679,7 +681,6 @@ bool NODE::Add( std::unique_ptr< SEGMENT > aSegment, bool aAllowRedundant ) if( !aAllowRedundant && findRedundantSegment( aSegment.get() ) ) return false; - aSegment->SetOwner( this ); addSegment( aSegment.release() ); return true; @@ -688,6 +689,8 @@ bool NODE::Add( std::unique_ptr< SEGMENT > aSegment, bool aAllowRedundant ) void NODE::addArc( ARC* aArc ) { + aArc->SetOwner( this ); + linkJoint( aArc->Anchor( 0 ), aArc->Layers(), aArc->Net(), aArc ); linkJoint( aArc->Anchor( 1 ), aArc->Layers(), aArc->Net(), aArc ); @@ -695,7 +698,7 @@ void NODE::addArc( ARC* aArc ) } -bool NODE::Add( std::unique_ptr< ARC > aArc, bool aAllowRedundant ) +bool NODE::Add( std::unique_ptr< ARC >&& aArc, bool aAllowRedundant ) { const SHAPE_ARC& arc = aArc->CArc(); @@ -705,12 +708,12 @@ bool NODE::Add( std::unique_ptr< ARC > aArc, bool aAllowRedundant ) return false; } - aArc->SetOwner( this ); addArc( aArc.release() ); return true; } +#if 0 // JEY TODO: clean up void NODE::Add( std::unique_ptr< ITEM > aItem, bool aAllowRedundant ) { switch( aItem->Kind() ) @@ -718,6 +721,8 @@ void NODE::Add( std::unique_ptr< ITEM > aItem, bool aAllowRedundant ) case ITEM::SOLID_T: Add( ItemCast( std::move( aItem ) ) ); break; case ITEM::SEGMENT_T: Add( ItemCast( std::move( aItem ) ), aAllowRedundant ); break; case ITEM::VIA_T: Add( ItemCast( std::move( aItem ) ) ); break; + case ITEM::HOLE_T: + break; // ignore holes, they don't exist as independent objects case ITEM::ARC_T: //todo(snh): Add redundant search @@ -725,21 +730,11 @@ void NODE::Add( std::unique_ptr< ITEM > aItem, bool aAllowRedundant ) break; case ITEM::LINE_T: - { - // fixme(twl): I don't like unique_ptr in this methods as the router has its own garbage - // collecting mechanism. This particular case is used exclusively in - // ROUTER::GetUpdatedItems() for dumping debug logs. Please don't call Add ( up ) - // otherwise, dragons live here. - LINE *l = static_cast( aItem.get() ); - Add( *l ); - break; - } - default: assert( false ); } } - +#endif void NODE::AddEdgeExclusion( std::unique_ptr aShape ) { @@ -766,7 +761,7 @@ void NODE::doRemove( ITEM* aItem ) if( aItem->BelongsTo( m_root ) && !isRoot() ) { m_override.insert( aItem ); - + if( aItem->HasHole() ) m_override.insert( aItem->Hole() ); } @@ -793,7 +788,7 @@ void NODE::doRemove( ITEM* aItem ) if( hole ) { m_index->Remove( hole ); // hole is not directly owned by NODE but by the parent SOLID/VIA. - hole->SetOwner( nullptr ); + hole->SetOwner( hole->ParentPadVia() ); } } } @@ -878,10 +873,10 @@ void NODE::removeSolidIndex( SOLID* aSolid ) } -void NODE::Replace( ITEM* aOldItem, std::unique_ptr< ITEM > aNewItem ) +void NODE::Replace( ITEM* aOldItem, std::unique_ptr< ITEM >&& aNewItem ) { Remove( aOldItem ); - Add( std::move( aNewItem ) ); + add( aNewItem.release() ); } @@ -1482,7 +1477,7 @@ void NODE::Commit( NODE* aNode ) { item->SetRank( -1 ); item->Unmark(); - Add( std::unique_ptr( item ) ); + add( item ); } releaseChildren(); diff --git a/pcbnew/router/pns_node.h b/pcbnew/router/pns_node.h index a77bc46c96..c76a099fc9 100644 --- a/pcbnew/router/pns_node.h +++ b/pcbnew/router/pns_node.h @@ -314,17 +314,14 @@ public: * at the same coordinates as an existing one). * @return true if added */ - bool Add( std::unique_ptr< SEGMENT > aSegment, bool aAllowRedundant = false ); - void Add( std::unique_ptr< SOLID > aSolid ); - void Add( std::unique_ptr< VIA > aVia ); - bool Add( std::unique_ptr< ARC > aArc, bool aAllowRedundant = false ); + bool Add( std::unique_ptr< SEGMENT >&& aSegment, bool aAllowRedundant = false ); + void Add( std::unique_ptr< SOLID >&& aSolid ); + void Add( std::unique_ptr< VIA >&& aVia ); + bool Add( std::unique_ptr< ARC >&& aArc, bool aAllowRedundant = false ); void Add( LINE& aLine, bool aAllowRedundant = false ); - void Add( ITEM* aItem, bool aAllowRedundant = false ); - void AddEdgeExclusion( std::unique_ptr aShape ); - bool QueryEdgeExclusions( const VECTOR2I& aPos ) const; /** @@ -349,7 +346,7 @@ public: * @param aOldItem item to be removed * @param aNewItem item add instead */ - void Replace( ITEM* aOldItem, std::unique_ptr< ITEM > aNewItem ); + void Replace( ITEM* aOldItem, std::unique_ptr< ITEM >&& aNewItem ); void Replace( LINE& aOldLine, LINE& aNewLine ); /** @@ -462,9 +459,13 @@ public: return m_collisionQueryScope; } - void Add( std::unique_ptr< ITEM > aItem, bool aAllowRedundant = false ); + void AddRaw( ITEM* aItem, bool aAllowRedundant = false ) + { + add( aItem, aAllowRedundant ); + } private: + void add( ITEM* aItem, bool aAllowRedundant = false ); /// nodes are not copyable NODE( const NODE& aB ); diff --git a/pcbnew/router/pns_shove.cpp b/pcbnew/router/pns_shove.cpp index b0b4333c60..76b270cc88 100644 --- a/pcbnew/router/pns_shove.cpp +++ b/pcbnew/router/pns_shove.cpp @@ -2,7 +2,7 @@ * KiRouter - a push-and-(sometimes-)shove PCB router * * Copyright (C) 2013-2014 CERN - * Copyright (C) 2016-2021 KiCad Developers, see AUTHORS.txt for contributors. + * Copyright (C) 2016-2023 KiCad Developers, see AUTHORS.txt for contributors. * Author: Tomasz Wlostowski * * This program is free software: you can redistribute it and/or modify it @@ -1800,7 +1800,8 @@ SHOVE::SHOVE_STATUS SHOVE::ShoveDraggingVia( const VIA_HANDLE aOldVia, const VEC VIA headVia ( *viaToDrag ); headVia.SetPos( aWhere ); - headSet.Add( headVia ); + headSet.Add( &headVia, false ); // headVia is on stack + VIA_HANDLE prevViaHandle; NODE* parent = reduceSpringback( headSet, prevViaHandle ); diff --git a/pcbnew/router/pns_via.cpp b/pcbnew/router/pns_via.cpp index f2d4d95234..455a1793cd 100644 --- a/pcbnew/router/pns_via.cpp +++ b/pcbnew/router/pns_via.cpp @@ -2,7 +2,7 @@ * KiRouter - a push-and-(sometimes-)shove PCB router * * Copyright (C) 2013-2014 CERN - * Copyright (C) 2016-2020 KiCad Developers, see AUTHORS.txt for contributors. + * Copyright (C) 2016-2023 KiCad Developers, see AUTHORS.txt for contributors. * Author: Tomasz Wlostowski * * This program is free software: you can redistribute it and/or modify it @@ -36,7 +36,7 @@ bool VIA::PushoutForce( NODE* aNode, const ITEM* aOther, VECTOR2I& aForce ) VECTOR2I elementForces[4], force; size_t nf = 0; - #if 0 + #if 0 // JEY TODO: why is this commented out? Needs replacing, or deleting? if( aNode->GetCollisionQueryScope() == NODE::CQS_ALL_RULES ) { int holeClearance = aNode->GetHoleClearance( this, aOther ); @@ -161,12 +161,12 @@ const SHAPE_LINE_CHAIN VIA::Hull( int aClearance, int aWalkaroundThickness, int // Chamfer = width * ( 1 - sqrt(2)/2 ) for equilateral octagon return OctagonalHull( m_pos - VECTOR2I( width / 2, width / 2 ), - VECTOR2I( width, width ), - cl, ( 2 * cl + width ) * ( 1.0 - M_SQRT1_2 ) ); + VECTOR2I( width, width ), + cl, ( 2 * cl + width ) * ( 1.0 - M_SQRT1_2 ) ); } -#if 0 +#if 0 // JEY TODO: is this no longer needed? const SHAPE_LINE_CHAIN VIA::HoleHull( int aClearance, int aWalkaroundThickness, int aLayer ) const { int cl = ( aClearance + aWalkaroundThickness / 2 ); diff --git a/pcbnew/router/pns_via.h b/pcbnew/router/pns_via.h index ee303cbe4e..96e2e2ccfc 100644 --- a/pcbnew/router/pns_via.h +++ b/pcbnew/router/pns_via.h @@ -2,7 +2,7 @@ * KiRouter - a push-and-(sometimes-)shove PCB router * * Copyright (C) 2013-2014 CERN - * Copyright (C) 2016-2022 KiCad Developers, see AUTHORS.txt for contributors. + * Copyright (C) 2016-2023 KiCad Developers, see AUTHORS.txt for contributors. * Author: Tomasz Wlostowski * * This program is free software: you can redistribute it and/or modify it @@ -73,6 +73,7 @@ public: m_shape = SHAPE_CIRCLE( aPos, aDiameter / 2 ); m_hole = HOLE::MakeCircularHole( m_pos, aDrill / 2 ); m_hole->SetNet( aNet ); + m_hole->SetOwner( this ); m_viaType = aViaType; m_isFree = false; m_isVirtual = false; @@ -87,6 +88,7 @@ public: m_diameter = aB.m_diameter; m_shape = SHAPE_CIRCLE( m_pos, m_diameter / 2 ); m_hole = aB.m_hole->Clone(); + m_hole->SetOwner( this ); m_marker = aB.m_marker; m_rank = aB.m_rank; m_drill = aB.m_drill; @@ -97,8 +99,10 @@ public: virtual ~VIA() { - if ( m_hole ) + if ( m_hole && m_hole->BelongsTo( this ) ) + { delete m_hole; + } } static inline bool ClassOf( const ITEM* aItem ) @@ -167,9 +171,9 @@ public: virtual void SetHole( HOLE* aHole ) override { - if( m_hole ) + if( m_hole && m_hole->Owner() == this ) { - assert( m_hole->Owner() == nullptr ); + delete m_hole; } m_hole = aHole; diff --git a/qa/unittests/pcbnew/test_pns_basics.cpp b/qa/unittests/pcbnew/test_pns_basics.cpp index 2563bc8fa4..3527c8dbd0 100644 --- a/qa/unittests/pcbnew/test_pns_basics.cpp +++ b/qa/unittests/pcbnew/test_pns_basics.cpp @@ -89,7 +89,8 @@ public: virtual ~MOCK_RULE_RESOLVER() {} - virtual int Clearance( const PNS::ITEM* aA, const PNS::ITEM* aB ) override + virtual int Clearance( const PNS::ITEM* aA, const PNS::ITEM* aB, + bool aUseClearanceEpsilon = true ) override { PNS::CONSTRAINT constraint; int rv = -1; @@ -192,15 +193,15 @@ public: bool operator<( const ITEM_KEY& other ) const { if( a < other.a ) + { return true; + } else if ( a == other.a ) { if( b < other.b ) return true; else if ( b == other.b ) - { return type < other.type; - } } return false; @@ -211,7 +212,7 @@ public: virtual bool IsNetTieExclusion( const PNS::ITEM* aItem, const VECTOR2I& aCollisionPos, const PNS::ITEM* aCollidingItem ) override { - return false; + return false; } void AddMockRule( PNS::CONSTRAINT_TYPE aType, const PNS::ITEM* aItemA, const PNS::ITEM* aItemB, @@ -232,8 +233,7 @@ public: private: std::map m_ruleMap; - - int m_clearanceEpsilon; + int m_clearanceEpsilon; }; struct PNS_TEST_FIXTURE; @@ -242,11 +242,14 @@ class MOCK_PNS_KICAD_IFACE : public PNS_KICAD_IFACE_BASE { public: MOCK_PNS_KICAD_IFACE( PNS_TEST_FIXTURE *aFixture ) : - m_testFixture( aFixture ) {} + m_testFixture( aFixture ) + {} + ~MOCK_PNS_KICAD_IFACE() {} void HideItem( PNS::ITEM* aItem ) override {}; - void DisplayItem( const PNS::ITEM* aItem, int aClearance, bool aEdit = false ) override {}; + void DisplayItem( const PNS::ITEM* aItem, int aClearance, bool aEdit = false, + bool aIsHeadTrace = false ) override {}; PNS::RULE_RESOLVER* GetRuleResolver() override; private: @@ -256,17 +259,18 @@ private: struct PNS_TEST_FIXTURE { - PNS_TEST_FIXTURE() : m_settingsManager( true /* headless */ ) + PNS_TEST_FIXTURE() : + m_settingsManager( true /* headless */ ) { m_router = new PNS::ROUTER; m_iface = new MOCK_PNS_KICAD_IFACE( this ); m_router->SetInterface( m_iface ); } - SETTINGS_MANAGER m_settingsManager; - PNS::ROUTER* m_router; - MOCK_RULE_RESOLVER m_ruleResolver; - MOCK_PNS_KICAD_IFACE *m_iface; + SETTINGS_MANAGER m_settingsManager; + PNS::ROUTER* m_router; + MOCK_RULE_RESOLVER m_ruleResolver; + MOCK_PNS_KICAD_IFACE* m_iface; //std::unique_ptr m_board; }; @@ -278,18 +282,19 @@ PNS::RULE_RESOLVER* MOCK_PNS_KICAD_IFACE::GetRuleResolver() static void dumpObstacles( const PNS::NODE::OBSTACLES &obstacles ) { - for ( const auto& obs : obstacles ) + for( const PNS::OBSTACLE& obs : obstacles ) { - printf("%p [%s] - %p [%s], clearance %d\n", obs.m_head, obs.m_head->KindStr().c_str(), - obs.m_item, obs.m_item->KindStr().c_str(), - obs.m_clearance ); + printf( "%p [%s] - %p [%s], clearance %d\n", + obs.m_head, obs.m_head->KindStr().c_str(), + obs.m_item, obs.m_item->KindStr().c_str(), + obs.m_clearance ); } } BOOST_FIXTURE_TEST_CASE( PNSHoleCollisions, PNS_TEST_FIXTURE ) { - PNS::VIA* v1 = new PNS::VIA ( VECTOR2I( 0, 1000000 ), LAYER_RANGE( F_Cu, B_Cu ), 500000, 100000 ); - PNS::VIA* v2 = new PNS::VIA ( VECTOR2I( 0, 2000000 ), LAYER_RANGE( F_Cu, B_Cu ), 500000, 100000 ); + PNS::VIA* v1 = new PNS::VIA( VECTOR2I( 0, 1000000 ), LAYER_RANGE( F_Cu, B_Cu ), 500000, 100000 ); + PNS::VIA* v2 = new PNS::VIA( VECTOR2I( 0, 2000000 ), LAYER_RANGE( F_Cu, B_Cu ), 500000, 100000 ); std::unique_ptr world ( new PNS::NODE ); @@ -331,8 +336,6 @@ BOOST_FIXTURE_TEST_CASE( PNSHoleCollisions, PNS_TEST_FIXTURE ) world->QueryColliding( v1, obstacles ); dumpObstacles( obstacles ); - - BOOST_CHECK_EQUAL( obstacles.size(), 2 ); auto iter = obstacles.begin(); const auto first = *iter++;