39using namespace std::placeholders;
45#include <delaunator.hpp>
56 for(
size_t i = 0; i < size; i++ )
64 while(
m_data[root] != root )
68 while(
m_data[aVal] != aVal )
79 bool unite(
int aVal1,
int aVal2 )
81 aVal1 =
find( aVal1 );
82 aVal2 =
find( aVal2 );
118 for(
const std::shared_ptr<CN_ANCHOR>& node :
m_nodes )
121 for(
const CN_EDGE& tmp : aEdges )
123 const std::shared_ptr<const CN_ANCHOR>& source = tmp.GetSourceNode();
124 const std::shared_ptr<const CN_ANCHOR>& target = tmp.GetTargetNode();
126 wxCHECK2( source && !source->Dirty() && target && !target->Dirty(),
continue );
128 if( dset.
unite( source->GetTag(), target->GetTag() ) )
130 if( tmp.GetWeight() > 0 )
147 if ( aNodes.size() <= 2 )
150 const VECTOR2I p0( aNodes[0]->Pos() );
151 const VECTOR2I v0( aNodes[1]->Pos() - p0 );
153 for(
unsigned i = 2; i < aNodes.size(); i++ )
171 void AddNode(
const std::shared_ptr<CN_ANCHOR>& aNode )
178 std::vector<double> node_pts;
179 std::vector<std::shared_ptr<CN_ANCHOR>> anchors;
180 std::vector< std::vector<std::shared_ptr<CN_ANCHOR>> > anchorChains(
m_allNodes.size() );
186 [&](
const std::shared_ptr<CN_ANCHOR>& src,
const std::shared_ptr<CN_ANCHOR>& dst )
188 mstEdges.emplace_back( src, dst, src->Dist( *dst ) );
191 std::shared_ptr<CN_ANCHOR> prev =
nullptr;
193 for(
const std::shared_ptr<CN_ANCHOR>& n :
m_allNodes )
195 if( !prev || prev->Pos() != n->Pos() )
197 node_pts.push_back( n->Pos().x );
198 node_pts.push_back( n->Pos().y );
199 anchors.push_back( n );
203 anchorChains[anchors.size() - 1].push_back( n );
206 if( anchors.empty() )
210 else if( anchors.size() == 1 )
215 for(
const std::shared_ptr<CN_ANCHOR>& n :
m_allNodes )
217 if( prev && !( prev->Parent()->GetLayerSet() & n->Parent()->GetLayerSet() ).any() )
220 mstEdges.emplace_back( prev, n, 1 );
233 for(
size_t i = 0; i < anchors.size() - 1; i++ )
234 addEdge( anchors[i], anchors[i + 1] );
238 delaunator::Delaunator delaunator( node_pts );
239 auto& triangles = delaunator.triangles;
241 for(
size_t i = 0; i < triangles.size(); i += 3 )
243 addEdge( anchors[triangles[i]], anchors[triangles[i + 1]] );
244 addEdge( anchors[triangles[i + 1]], anchors[triangles[i + 2]] );
245 addEdge( anchors[triangles[i + 2]], anchors[triangles[i]] );
248 for(
size_t i = 0; i < delaunator.halfedges.size(); i++ )
250 if( delaunator.halfedges[i] == delaunator::INVALID_INDEX )
253 addEdge( anchors[triangles[i]], anchors[triangles[delaunator.halfedges[i]]] );
257 for(
size_t i = 0; i < anchorChains.size(); i++ )
259 std::vector<std::shared_ptr<CN_ANCHOR>>& chain = anchorChains[i];
261 if( chain.size() < 2 )
264 std::sort( chain.begin(), chain.end(),
265 [] (
const std::shared_ptr<CN_ANCHOR>& a,
const std::shared_ptr<CN_ANCHOR>& b )
267 return a->GetCluster().get() < b->GetCluster().get();
270 for(
unsigned int j = 1; j < chain.size(); j++ )
272 const std::shared_ptr<CN_ANCHOR>& prevNode = chain[j - 1];
273 const std::shared_ptr<CN_ANCHOR>& curNode = chain[j];
274 int weight = prevNode->GetCluster() != curNode->GetCluster() ? 1 : 0;
275 mstEdges.emplace_back( prevNode, curNode, weight );
301 const std::shared_ptr<CN_ANCHOR>& source = *it++;
302 const std::shared_ptr<CN_ANCHOR>& target = *it;
306 m_rnEdges.emplace_back( source, target );
311 for(
const std::shared_ptr<CN_ANCHOR>& node :
m_nodes )
321 for(
const std::shared_ptr<CN_ANCHOR>& n :
m_nodes )
324 std::vector<CN_EDGE> triangEdges;
336 triangEdges.emplace_back( e );
338 std::sort( triangEdges.begin(), triangEdges.end() );
353 auto optimizeZoneAnchor =
355 const std::shared_ptr<const CN_ANCHOR>& aAnchor,
356 const std::function<void( std::shared_ptr<const CN_ANCHOR> )>& setOptimizedTo )
358 SEG::ecoord closest_dist_sq = ( aAnchor->Pos() - aPos ).SquaredEuclideanNorm();
360 CN_ITEM* closest_item =
nullptr;
365 if( aAnchor->Item()->Net() != item->Net() )
370 if( zoneLayer && aLayerSet.test( zoneLayer->
GetBoardLayer() ) )
376 SEG::ecoord dist_sq = ( pt - aPos ).SquaredEuclideanNorm();
378 if( dist_sq < closest_dist_sq )
381 closest_item = zoneLayer;
382 closest_dist_sq = dist_sq;
389 setOptimizedTo( std::make_shared<CN_ANCHOR>( closest_pt, closest_item ) );
392 auto optimizeZoneToZoneAnchors =
393 [&](
const std::shared_ptr<const CN_ANCHOR>& a,
394 const std::shared_ptr<const CN_ANCHOR>& b,
395 const std::function<void(
const std::shared_ptr<const CN_ANCHOR>& )>&
397 const std::function<void(
const std::shared_ptr<const CN_ANCHOR>& )>&
408 DIST_PAIR( int64_t aDistSq,
size_t aIdA,
size_t aIdB )
409 : dist_sq( aDistSq ), idA( aIdA ), idB( aIdB )
417 const std::vector<CN_ITEM*>& connectedItemsA = a->Item()->ConnectedItems();
418 const std::vector<CN_ITEM*>& connectedItemsB = b->Item()->ConnectedItems();
420 std::vector<CENTER> centersA( connectedItemsA.size() );
421 std::vector<CENTER> centersB( connectedItemsB.size() );
423 for(
size_t i = 0; i < connectedItemsA.size(); i++ )
425 CN_ITEM* itemA = connectedItemsA[i];
433 centersA[i].valid =
true;
436 for(
size_t i = 0; i < connectedItemsB.size(); i++ )
438 CN_ITEM* itemB = connectedItemsB[i];
446 centersB[i].valid =
true;
449 std::vector<DIST_PAIR> pairsToTest;
451 for(
size_t ia = 0; ia < centersA.size(); ia++ )
453 for(
size_t ib = 0; ib < centersB.size(); ib++ )
455 const CENTER& ca = centersA[ia];
456 const CENTER& cb = centersB[ib];
458 if( !ca.valid || !cb.valid )
464 int64_t dist_sq = ( pB - pA ).SquaredEuclideanNorm();
465 pairsToTest.emplace_back( dist_sq, ia, ib );
469 std::sort( pairsToTest.begin(), pairsToTest.end(),
470 [](
const DIST_PAIR& dp_a,
const DIST_PAIR& dp_b )
472 return dp_a.dist_sq < dp_b.dist_sq;
475 const int c_polyPairsLimit = 3;
477 for(
size_t i = 0; i < pairsToTest.size() && i < c_polyPairsLimit; i++ )
479 const DIST_PAIR& pair = pairsToTest[i];
484 if( zoneLayerA == zoneLayerB )
495 setOptimizedATo( std::make_shared<CN_ANCHOR>( ptA, zoneLayerA ) );
496 setOptimizedBTo( std::make_shared<CN_ANCHOR>( ptB, zoneLayerB ) );
503 const std::shared_ptr<const CN_ANCHOR>& source = edge.GetSourceNode();
504 const std::shared_ptr<const CN_ANCHOR>& target = edge.GetTargetNode();
506 wxCHECK2( source && !source->Dirty() && target && !target->Dirty(),
continue );
508 if( source->ConnectedItemsCount() == 0 )
510 optimizeZoneAnchor( source->Pos(), source->Parent()->GetLayerSet(), target,
511 [&](
const std::shared_ptr<const CN_ANCHOR>& optimized )
513 edge.SetTargetNode( optimized );
516 else if( target->ConnectedItemsCount() == 0 )
518 optimizeZoneAnchor( target->Pos(), target->Parent()->GetLayerSet(), source,
519 [&](
const std::shared_ptr<const CN_ANCHOR>& optimized )
521 edge.SetSourceNode( optimized );
526 optimizeZoneToZoneAnchors( source, target,
527 [&](
const std::shared_ptr<const CN_ANCHOR>& optimized )
529 edge.SetSourceNode( optimized );
531 [&](
const std::shared_ptr<const CN_ANCHOR>& optimized )
533 edge.SetTargetNode( optimized );
551 edge.RemoveInvalidRefs();
554 edge.RemoveInvalidRefs();
570 std::shared_ptr<CN_ANCHOR> firstAnchor;
572 for(
CN_ITEM* item : *aCluster )
574 std::vector<std::shared_ptr<CN_ANCHOR>>& anchors = item->Anchors();
575 unsigned int nAnchors =
dynamic_cast<CN_ZONE_LAYER*
>( item ) ? 1 : anchors.size();
577 if( nAnchors > anchors.size() )
578 nAnchors = anchors.size();
580 for(
unsigned int i = 0; i < nAnchors; i++ )
582 anchors[i]->SetCluster( aCluster );
587 if( firstAnchor != anchors[i] )
588 m_boardEdges.emplace_back( firstAnchor, anchors[i], 0 );
592 firstAnchor = anchors[i];
606 [&](
const std::shared_ptr<CN_ANCHOR>& aTestNode1,
607 const std::shared_ptr<CN_ANCHOR>& aTestNode2 )
609 VECTOR2I diff = aTestNode1->Pos() - aTestNode2->Pos();
612 if( dist_sq < distMax_sq )
615 distMax_sq = dist_sq;
616 aPos1 = aTestNode1->Pos();
617 aPos2 = aTestNode2->Pos();
624 for(
const std::shared_ptr<CN_ANCHOR>& nodeA : aOtherNet->
m_nodes )
627 if( nodeA->GetNoLine() )
633 auto fwd_it =
m_nodes.lower_bound( nodeA );
634 auto rev_it = std::make_reverse_iterator( fwd_it );
636 for( ; fwd_it !=
m_nodes.end(); ++fwd_it )
638 const std::shared_ptr<CN_ANCHOR>& nodeB = *fwd_it;
640 if( nodeB->GetNoLine() )
647 if( distX_sq > distMax_sq )
650 verify( nodeA, nodeB );
654 for( ; rev_it !=
m_nodes.rend(); ++rev_it )
656 const std::shared_ptr<CN_ANCHOR>& nodeB = *rev_it;
658 if( nodeB->GetNoLine() )
663 if( distX_sq > distMax_sq )
666 verify( nodeA, nodeB );
constexpr const Vec GetCenter() const
CN_EDGE represents a point-to-point connection, whether realized or unrealized (ie: tracks etc.
CN_ITEM represents a BOARD_CONNETED_ITEM in the connectivity system (ie: a pad, track/arc/via,...
const std::vector< CN_ITEM * > & ConnectedItems() const
PCB_LAYER_ID GetBoardLayer() const
When using CN_ITEM layers to compare against board items, use this function which correctly remaps th...
const SHAPE_LINE_CHAIN & GetOutline() const
LSET is a set of PCB_LAYER_IDs.
A small class to help profiling.
void Show(std::ostream &aStream=std::cerr)
Print the elapsed time (in a suitable unit) to a stream.
void AddNode(const std::shared_ptr< CN_ANCHOR > &aNode)
std::multiset< std::shared_ptr< CN_ANCHOR >, CN_PTR_CMP > m_allNodes
bool areNodesColinear(const std::vector< std::shared_ptr< CN_ANCHOR > > &aNodes) const
void Triangulate(std::vector< CN_EDGE > &mstEdges)
Describe ratsnest for a single net.
std::shared_ptr< TRIANGULATOR_STATE > m_triangulator
std::multiset< std::shared_ptr< CN_ANCHOR >, CN_PTR_CMP > m_nodes
< Vector of nodes
void kruskalMST(const std::vector< CN_EDGE > &aEdges)
void UpdateNet()
Recompute ratsnest for a net.
std::vector< CN_EDGE > m_rnEdges
Flag indicating necessity of recalculation of ratsnest for a net.
void OptimizeRNEdges()
Find optimal ends of RNEdges.
bool NearestBicoloredPair(RN_NET *aOtherNet, VECTOR2I &aPos1, VECTOR2I &aPos2) const
std::vector< CN_EDGE > m_boardEdges
Vector of edges that makes ratsnest for a given net.
void compute()
< Recompute ratsnest from scratch.
void AddCluster(std::shared_ptr< CN_CLUSTER > aCluster)
VECTOR2I::extended_type ecoord
static SEG::ecoord Square(int a)
Represent a polyline containing arcs as well as line segments: A chain of connected line and/or arc s...
bool ClosestSegmentsFast(const SHAPE_LINE_CHAIN &aOther, VECTOR2I &aPt0, VECTOR2I &aPt1) const
Finds closest points between segments of this and the other line chain.
const std::vector< VECTOR2I > & CPoints() const
const BOX2I BBox(int aClearance=0) const override
Compute a bounding box of the shape, with a margin of aClearance a collision.
constexpr extended_type Cross(const VECTOR2< T > &aVector) const
Compute cross product of self with aVector.
constexpr extended_type SquaredEuclideanNorm() const
Compute the squared euclidean norm of the vector, which is defined as (x ** 2 + y ** 2).
static constexpr extended_type ECOORD_MAX
disjoint_set(size_t size)
std::vector< int > m_data
std::vector< int > m_depth
bool unite(int aVal1, int aVal2)
Class that computes missing connections on a PCB.