You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

1745 lines
43 KiB

7 years ago
7 years ago
7 years ago
5 years ago
9 years ago
9 years ago
9 years ago
5 years ago
9 years ago
5 years ago
11 years ago
9 years ago
9 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
11 years ago
5 years ago
5 years ago
11 years ago
5 years ago
5 years ago
5 years ago
5 years ago
11 years ago
11 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
11 years ago
5 years ago
5 years ago
11 years ago
11 years ago
11 years ago
11 years ago
9 years ago
11 years ago
5 years ago
11 years ago
11 years ago
5 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
  1. /*
  2. * KiRouter - a push-and-(sometimes-)shove PCB router
  3. *
  4. * Copyright (C) 2013-2019 CERN
  5. * Copyright (C) 2016-2023 KiCad Developers, see AUTHORS.txt for contributors.
  6. *
  7. * @author Tomasz Wlostowski <tomasz.wlostowski@cern.ch>
  8. *
  9. * This program is free software: you can redistribute it and/or modify it
  10. * under the terms of the GNU General Public License as published by the
  11. * Free Software Foundation, either version 3 of the License, or (at your
  12. * option) any later version.
  13. *
  14. * This program is distributed in the hope that it will be useful, but
  15. * WITHOUT ANY WARRANTY; without even the implied warranty of
  16. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  17. * General Public License for more details.
  18. *
  19. * You should have received a copy of the GNU General Public License along
  20. * with this program. If not, see <http://www.gnu.org/licenses/>.
  21. */
  22. #include <vector>
  23. #include <cassert>
  24. #include <utility>
  25. #include <math/vector2d.h>
  26. #include <geometry/seg.h>
  27. #include <geometry/shape_line_chain.h>
  28. #include <zone.h>
  29. #include <wx/log.h>
  30. #include "pns_arc.h"
  31. #include "pns_item.h"
  32. #include "pns_itemset.h"
  33. #include "pns_line.h"
  34. #include "pns_node.h"
  35. #include "pns_via.h"
  36. #include "pns_solid.h"
  37. #include "pns_joint.h"
  38. #include "pns_index.h"
  39. #include "pns_debug_decorator.h"
  40. #include "pns_router.h"
  41. #include "pns_utils.h"
  42. namespace PNS {
  43. #ifdef DEBUG
  44. static std::unordered_set<const NODE*> allocNodes;
  45. #endif
  46. NODE::NODE()
  47. {
  48. m_depth = 0;
  49. m_root = this;
  50. m_parent = nullptr;
  51. m_maxClearance = 800000; // fixme: depends on how thick traces are.
  52. m_ruleResolver = nullptr;
  53. m_index = new INDEX;
  54. #ifdef DEBUG
  55. allocNodes.insert( this );
  56. #endif
  57. }
  58. NODE::~NODE()
  59. {
  60. if( !m_children.empty() )
  61. {
  62. wxLogTrace( wxT( "PNS" ), wxT( "attempting to free a node that has kids." ) );
  63. assert( false );
  64. }
  65. #ifdef DEBUG
  66. if( allocNodes.find( this ) == allocNodes.end() )
  67. {
  68. wxLogTrace( wxT( "PNS" ), wxT( "attempting to free an already-free'd node." ) );
  69. assert( false );
  70. }
  71. allocNodes.erase( this );
  72. #endif
  73. m_joints.clear();
  74. std::vector<const ITEM*> toDelete;
  75. toDelete.reserve( m_index->Size() );
  76. for( ITEM* item : *m_index )
  77. {
  78. if( item->BelongsTo( this ) && item->OfKind( ITEM::HOLE_T ) )
  79. {
  80. #ifdef DEBUG
  81. HOLE* hole = static_cast<HOLE*>( item );
  82. // If a hole is no longer owned by the same NODE as its parent then we're in a
  83. // heap of trouble.
  84. if( hole->ParentPadVia() && !hole->ParentPadVia()->BelongsTo( this ) )
  85. assert( false );
  86. #endif
  87. toDelete.push_back( item );
  88. }
  89. }
  90. for( const ITEM* item : toDelete )
  91. {
  92. wxLogTrace( wxT( "PNS" ), wxT( "del item %p type %s" ), item, item->KindStr().c_str() );
  93. delete item;
  94. }
  95. if( m_ruleResolver )
  96. {
  97. m_ruleResolver->ClearCacheForItems( toDelete );
  98. }
  99. releaseGarbage();
  100. unlinkParent();
  101. delete m_index;
  102. }
  103. int NODE::GetClearance( const ITEM* aA, const ITEM* aB, bool aUseClearanceEpsilon ) const
  104. {
  105. if( !m_ruleResolver )
  106. return 100000;
  107. if( aA->IsVirtual() || aB->IsVirtual() )
  108. return 0;
  109. int cl = m_ruleResolver->Clearance( aA, aB, aUseClearanceEpsilon );
  110. return cl;
  111. }
  112. NODE* NODE::Branch()
  113. {
  114. NODE* child = new NODE;
  115. m_children.insert( child );
  116. child->m_depth = m_depth + 1;
  117. child->m_parent = this;
  118. child->m_ruleResolver = m_ruleResolver;
  119. child->m_root = isRoot() ? this : m_root;
  120. child->m_maxClearance = m_maxClearance;
  121. // Immediate offspring of the root branch needs not copy anything. For the rest, deep-copy
  122. // joints, overridden item maps and pointers to stored items.
  123. if( !isRoot() )
  124. {
  125. JOINT_MAP::iterator j;
  126. for( ITEM* item : *m_index )
  127. child->m_index->Add( item );
  128. child->m_joints = m_joints;
  129. child->m_override = m_override;
  130. }
  131. #if 0
  132. wxLogTrace( wxT( "PNS" ), wxT( "%d items, %d joints, %d overrides" ),
  133. child->m_index->Size(),
  134. (int) child->m_joints.size(),
  135. (int) child->m_override.size() );
  136. #endif
  137. return child;
  138. }
  139. void NODE::unlinkParent()
  140. {
  141. if( isRoot() )
  142. return;
  143. m_parent->m_children.erase( this );
  144. }
  145. OBSTACLE_VISITOR::OBSTACLE_VISITOR( const ITEM* aItem ) :
  146. m_item( aItem ),
  147. m_node( nullptr ),
  148. m_override( nullptr )
  149. {
  150. }
  151. void OBSTACLE_VISITOR::SetWorld( const NODE* aNode, const NODE* aOverride )
  152. {
  153. m_node = aNode;
  154. m_override = aOverride;
  155. }
  156. bool OBSTACLE_VISITOR::visit( ITEM* aCandidate )
  157. {
  158. // check if there is a more recent branch with a newer (possibly modified) version of this
  159. // item.
  160. if( m_override && m_override->Overrides( aCandidate ) )
  161. return true;
  162. return false;
  163. }
  164. // function object that visits potential obstacles and performs the actual collision refining
  165. struct NODE::DEFAULT_OBSTACLE_VISITOR : public OBSTACLE_VISITOR
  166. {
  167. COLLISION_SEARCH_CONTEXT* m_ctx;
  168. DEFAULT_OBSTACLE_VISITOR( COLLISION_SEARCH_CONTEXT* aCtx, const ITEM* aItem ) :
  169. OBSTACLE_VISITOR( aItem ),
  170. m_ctx( aCtx )
  171. {
  172. }
  173. virtual ~DEFAULT_OBSTACLE_VISITOR()
  174. {
  175. }
  176. bool operator()( ITEM* aCandidate ) override
  177. {
  178. if( !aCandidate->OfKind( m_ctx->options.m_kindMask ) )
  179. return true;
  180. // Collisions with self aren't a thing; don't spend time on them.
  181. if( m_item == aCandidate )
  182. return true;
  183. if( m_ctx->options.m_filter && !m_ctx->options.m_filter( aCandidate ) )
  184. return true;
  185. if( visit( aCandidate ) )
  186. return true;
  187. if( !aCandidate->Collide( m_item, m_node, m_layerContext.value_or( -1 ), m_ctx ) )
  188. return true;
  189. if( m_ctx->options.m_limitCount > 0 && m_ctx->obstacles.size() >= m_ctx->options.m_limitCount )
  190. return false;
  191. return true;
  192. };
  193. };
  194. int NODE::QueryColliding( const ITEM* aItem, NODE::OBSTACLES& aObstacles,
  195. const COLLISION_SEARCH_OPTIONS& aOpts ) const
  196. {
  197. COLLISION_SEARCH_CONTEXT ctx( aObstacles, aOpts );
  198. /// By default, virtual items cannot collide
  199. if( aItem->IsVirtual() )
  200. return 0;
  201. DEFAULT_OBSTACLE_VISITOR visitor( &ctx, aItem );
  202. #ifdef DEBUG
  203. assert( allocNodes.find( this ) != allocNodes.end() );
  204. #endif
  205. visitor.SetWorld( this, nullptr );
  206. // first, look for colliding items in the local index
  207. m_index->Query( aItem, m_maxClearance, visitor );
  208. // if we haven't found enough items, look in the root branch as well.
  209. if( !isRoot() && ( ctx.obstacles.size() < aOpts.m_limitCount || aOpts.m_limitCount < 0 ) )
  210. {
  211. visitor.SetWorld( m_root, this );
  212. m_root->m_index->Query( aItem, m_maxClearance, visitor );
  213. }
  214. return aObstacles.size();
  215. }
  216. NODE::OPT_OBSTACLE NODE::NearestObstacle( const LINE* aLine,
  217. const COLLISION_SEARCH_OPTIONS& aOpts )
  218. {
  219. DIRECTION_45::CORNER_MODE cornerMode = ROUTER::GetInstance()->Settings().GetCornerMode();
  220. const int clearanceEpsilon = GetRuleResolver()->ClearanceEpsilon();
  221. OBSTACLES obstacleList;
  222. for( int i = 0; i < aLine->CLine().SegmentCount(); i++ )
  223. {
  224. // Note: Clearances between &s and other items are cached,
  225. // which means they'll be the same for all segments in the line.
  226. // Disabling the cache will lead to slowness.
  227. const SEGMENT s( *aLine, aLine->CLine().CSegment( i ) );
  228. QueryColliding( &s, obstacleList, aOpts );
  229. }
  230. if( aLine->EndsWithVia() )
  231. QueryColliding( &aLine->Via(), obstacleList, aOpts );
  232. if( obstacleList.empty() )
  233. return OPT_OBSTACLE();
  234. OBSTACLE nearest;
  235. nearest.m_head = nullptr;
  236. nearest.m_item = nullptr;
  237. nearest.m_distFirst = INT_MAX;
  238. nearest.m_maxFanoutWidth = 0;
  239. auto updateNearest =
  240. [&]( const SHAPE_LINE_CHAIN::INTERSECTION& pt, const OBSTACLE& obstacle )
  241. {
  242. int dist = aLine->CLine().PathLength( pt.p, pt.index_their );
  243. if( dist < nearest.m_distFirst )
  244. {
  245. nearest = obstacle;
  246. nearest.m_distFirst = dist;
  247. nearest.m_ipFirst = pt.p;
  248. }
  249. };
  250. SHAPE_LINE_CHAIN obstacleHull;
  251. DEBUG_DECORATOR* debugDecorator = ROUTER::GetInstance()->GetInterface()->GetDebugDecorator();
  252. std::vector<SHAPE_LINE_CHAIN::INTERSECTION> intersectingPts;
  253. int layer = aLine->Layer();
  254. for( const OBSTACLE& obstacle : obstacleList )
  255. {
  256. int clearance = GetClearance( obstacle.m_item, aLine, aOpts.m_useClearanceEpsilon )
  257. + aLine->Width() / 2;
  258. obstacleHull = obstacle.m_item->Hull( clearance, 0, layer );
  259. if( cornerMode == DIRECTION_45::MITERED_90 || cornerMode == DIRECTION_45::ROUNDED_90 )
  260. {
  261. BOX2I bbox = obstacleHull.BBox();
  262. obstacleHull.Clear();
  263. obstacleHull.Append( bbox.GetLeft(), bbox.GetTop() );
  264. obstacleHull.Append( bbox.GetRight(), bbox.GetTop() );
  265. obstacleHull.Append( bbox.GetRight(), bbox.GetBottom() );
  266. obstacleHull.Append( bbox.GetLeft(), bbox.GetBottom() );
  267. }
  268. //debugDecorator->AddLine( obstacleHull, 2, 40000, "obstacle-hull-test" );
  269. //debugDecorator->AddLine( aLine->CLine(), 5, 40000, "obstacle-test-line" );
  270. intersectingPts.clear();
  271. HullIntersection( obstacleHull, aLine->CLine(), intersectingPts );
  272. for( const auto& ip : intersectingPts )
  273. {
  274. //debugDecorator->AddPoint( ip.p, ip.valid?3:6, 100000, (const char *) wxString::Format("obstacle-isect-point-%d" ).c_str() );
  275. if( ip.valid )
  276. updateNearest( ip, obstacle );
  277. }
  278. if( aLine->EndsWithVia() )
  279. {
  280. const VIA& via = aLine->Via();
  281. int viaClearance = GetClearance( obstacle.m_item, &via, aOpts.m_useClearanceEpsilon )
  282. + via.Diameter( aLine->Layer() ) / 2;
  283. obstacleHull = obstacle.m_item->Hull( viaClearance, 0, layer );
  284. if( cornerMode == DIRECTION_45::MITERED_90 || cornerMode == DIRECTION_45::ROUNDED_90 )
  285. {
  286. BOX2I bbox = obstacleHull.BBox();
  287. obstacleHull.Clear();
  288. obstacleHull.Append( bbox.GetLeft(), bbox.GetTop() );
  289. obstacleHull.Append( bbox.GetRight(), bbox.GetTop() );
  290. obstacleHull.Append( bbox.GetRight(), bbox.GetBottom() );
  291. obstacleHull.Append( bbox.GetLeft(), bbox.GetBottom() );
  292. }
  293. //debugDecorator->AddLine( obstacleHull, 3 );
  294. intersectingPts.clear();
  295. HullIntersection( obstacleHull, aLine->CLine(), intersectingPts );
  296. for( const SHAPE_LINE_CHAIN::INTERSECTION& ip : intersectingPts )
  297. updateNearest( ip, obstacle );
  298. }
  299. }
  300. if( nearest.m_distFirst == INT_MAX )
  301. nearest = (*obstacleList.begin());
  302. return nearest;
  303. }
  304. NODE::OPT_OBSTACLE NODE::CheckColliding( const ITEM_SET& aSet, int aKindMask )
  305. {
  306. for( const ITEM* item : aSet.CItems() )
  307. {
  308. OPT_OBSTACLE obs = CheckColliding( item, aKindMask );
  309. if( obs )
  310. return obs;
  311. }
  312. return OPT_OBSTACLE();
  313. }
  314. NODE::OPT_OBSTACLE NODE::CheckColliding( const ITEM* aItemA, int aKindMask )
  315. {
  316. COLLISION_SEARCH_OPTIONS opts;
  317. opts.m_kindMask = aKindMask;
  318. opts.m_limitCount = 1;
  319. return CheckColliding( aItemA, opts );
  320. }
  321. NODE::OPT_OBSTACLE NODE::CheckColliding( const ITEM* aItemA, const COLLISION_SEARCH_OPTIONS& aOpts )
  322. {
  323. OBSTACLES obs;
  324. if( aItemA->Kind() == ITEM::LINE_T )
  325. {
  326. int n = 0;
  327. const LINE* line = static_cast<const LINE*>( aItemA );
  328. const SHAPE_LINE_CHAIN& l = line->CLine();
  329. for( int i = 0; i < l.SegmentCount(); i++ )
  330. {
  331. // Note: Clearances between &s and other items are cached,
  332. // which means they'll be the same for all segments in the line.
  333. // Disabling the cache will lead to slowness.
  334. const SEGMENT s( *line, l.CSegment( i ) );
  335. n += QueryColliding( &s, obs, aOpts );
  336. if( n )
  337. return OPT_OBSTACLE( *obs.begin() );
  338. }
  339. if( line->EndsWithVia() )
  340. {
  341. n += QueryColliding( &line->Via(), obs, aOpts );
  342. if( n )
  343. return OPT_OBSTACLE( *obs.begin() );
  344. }
  345. }
  346. else if( QueryColliding( aItemA, obs, aOpts ) > 0 )
  347. {
  348. return OPT_OBSTACLE( *obs.begin() );
  349. }
  350. return OPT_OBSTACLE();
  351. }
  352. struct HIT_VISITOR : public OBSTACLE_VISITOR
  353. {
  354. ITEM_SET& m_items;
  355. const VECTOR2I& m_point;
  356. HIT_VISITOR( ITEM_SET& aTab, const VECTOR2I& aPoint ) :
  357. OBSTACLE_VISITOR( nullptr ),
  358. m_items( aTab ),
  359. m_point( aPoint )
  360. {}
  361. virtual ~HIT_VISITOR()
  362. {
  363. }
  364. bool operator()( ITEM* aItem ) override
  365. {
  366. SHAPE_CIRCLE cp( m_point, 0 );
  367. int cl = 0;
  368. // TODO(JE) padstacks -- this may not work
  369. if( aItem->Shape( -1 )->Collide( &cp, cl ) )
  370. m_items.Add( aItem );
  371. return true;
  372. }
  373. };
  374. const ITEM_SET NODE::HitTest( const VECTOR2I& aPoint ) const
  375. {
  376. ITEM_SET items;
  377. // fixme: we treat a point as an infinitely small circle - this is inefficient.
  378. SHAPE_CIRCLE s( aPoint, 0 );
  379. HIT_VISITOR visitor( items, aPoint );
  380. visitor.SetWorld( this, nullptr );
  381. m_index->Query( &s, m_maxClearance, visitor );
  382. if( !isRoot() ) // fixme: could be made cleaner
  383. {
  384. ITEM_SET items_root;
  385. visitor.SetWorld( m_root, nullptr );
  386. HIT_VISITOR visitor_root( items_root, aPoint );
  387. m_root->m_index->Query( &s, m_maxClearance, visitor_root );
  388. for( ITEM* item : items_root.Items() )
  389. {
  390. if( !Overrides( item ) )
  391. items.Add( item );
  392. }
  393. }
  394. return items;
  395. }
  396. void NODE::addSolid( SOLID* aSolid )
  397. {
  398. if( aSolid->HasHole() )
  399. {
  400. assert( aSolid->Hole()->BelongsTo( aSolid ) );
  401. addHole( aSolid->Hole() );
  402. }
  403. if( aSolid->IsRoutable() )
  404. linkJoint( aSolid->Pos(), aSolid->Layers(), aSolid->Net(), aSolid );
  405. aSolid->SetOwner( this );
  406. m_index->Add( aSolid );
  407. }
  408. void NODE::Add( std::unique_ptr< SOLID > aSolid )
  409. {
  410. aSolid->SetOwner( this );
  411. addSolid( aSolid.release() );
  412. }
  413. void NODE::addVia( VIA* aVia )
  414. {
  415. if( aVia->HasHole() )
  416. {
  417. if( ! aVia->Hole()->BelongsTo( aVia ) )
  418. {
  419. assert( false );
  420. }
  421. addHole( aVia->Hole() );
  422. }
  423. linkJoint( aVia->Pos(), aVia->Layers(), aVia->Net(), aVia );
  424. aVia->SetOwner( this );
  425. m_index->Add( aVia );
  426. }
  427. void NODE::addHole( HOLE* aHole )
  428. {
  429. // do we need holes in the connection graph?
  430. //linkJoint( aHole->Pos(), aHole->Layers(), aHole->Net(), aHole );
  431. aHole->SetOwner( this );
  432. m_index->Add( aHole );
  433. }
  434. void NODE::Add( std::unique_ptr< VIA > aVia )
  435. {
  436. addVia( aVia.release() );
  437. }
  438. void NODE::add( ITEM* aItem, bool aAllowRedundant )
  439. {
  440. switch( aItem->Kind() )
  441. {
  442. case ITEM::ARC_T:
  443. addArc( static_cast<ARC*>( aItem ) );
  444. break;
  445. case ITEM::SEGMENT_T:
  446. addSegment( static_cast<SEGMENT*>( aItem ) );
  447. break;
  448. case ITEM::VIA_T:
  449. addVia( static_cast<VIA*>( aItem ) );
  450. break;
  451. case ITEM::SOLID_T:
  452. addSolid( static_cast<SOLID*>( aItem ) );
  453. break;
  454. case ITEM::HOLE_T:
  455. // added by parent VIA_T or SOLID_T (pad)
  456. break;
  457. default:
  458. assert( false );
  459. }
  460. }
  461. void NODE::Add( LINE& aLine, bool aAllowRedundant )
  462. {
  463. assert( !aLine.IsLinked() );
  464. SHAPE_LINE_CHAIN& l = aLine.Line();
  465. for( size_t i = 0; i < l.ArcCount(); i++ )
  466. {
  467. auto s = l.Arc( i );
  468. ARC* rarc;
  469. if( !aAllowRedundant && ( rarc = findRedundantArc( s.GetP0(), s.GetP1(), aLine.Layers(),
  470. aLine.Net() ) ) )
  471. {
  472. aLine.Link( rarc );
  473. }
  474. else
  475. {
  476. auto newarc = std::make_unique< ARC >( aLine, s );
  477. aLine.Link( newarc.get() );
  478. Add( std::move( newarc ), true );
  479. }
  480. }
  481. for( int i = 0; i < l.SegmentCount(); i++ )
  482. {
  483. if( l.IsArcSegment( i ) )
  484. continue;
  485. SEG s = l.CSegment( i );
  486. if( s.A != s.B )
  487. {
  488. SEGMENT* rseg;
  489. if( !aAllowRedundant && ( rseg = findRedundantSegment( s.A, s.B, aLine.Layers(),
  490. aLine.Net() ) ) )
  491. {
  492. // another line could be referencing this segment too :(
  493. aLine.Link( rseg );
  494. }
  495. else
  496. {
  497. std::unique_ptr<SEGMENT> newseg = std::make_unique<SEGMENT>( aLine, s );
  498. aLine.Link( newseg.get() );
  499. Add( std::move( newseg ), true );
  500. }
  501. }
  502. }
  503. }
  504. void NODE::addSegment( SEGMENT* aSeg )
  505. {
  506. aSeg->SetOwner( this );
  507. linkJoint( aSeg->Seg().A, aSeg->Layers(), aSeg->Net(), aSeg );
  508. linkJoint( aSeg->Seg().B, aSeg->Layers(), aSeg->Net(), aSeg );
  509. m_index->Add( aSeg );
  510. }
  511. bool NODE::Add( std::unique_ptr< SEGMENT > aSegment, bool aAllowRedundant )
  512. {
  513. if( aSegment->Seg().A == aSegment->Seg().B )
  514. {
  515. wxLogTrace( wxT( "PNS" ),
  516. wxT( "attempting to add a segment with same end coordinates, ignoring." ) );
  517. return false;
  518. }
  519. if( !aAllowRedundant && findRedundantSegment( aSegment.get() ) )
  520. return false;
  521. addSegment( aSegment.release() );
  522. return true;
  523. }
  524. void NODE::addArc( ARC* aArc )
  525. {
  526. aArc->SetOwner( this );
  527. linkJoint( aArc->Anchor( 0 ), aArc->Layers(), aArc->Net(), aArc );
  528. linkJoint( aArc->Anchor( 1 ), aArc->Layers(), aArc->Net(), aArc );
  529. m_index->Add( aArc );
  530. }
  531. bool NODE::Add( std::unique_ptr< ARC > aArc, bool aAllowRedundant )
  532. {
  533. const SHAPE_ARC& arc = aArc->CArc();
  534. if( !aAllowRedundant && findRedundantArc( arc.GetP0(), arc.GetP1(), aArc->Layers(),
  535. aArc->Net() ) )
  536. {
  537. return false;
  538. }
  539. addArc( aArc.release() );
  540. return true;
  541. }
  542. void NODE::AddEdgeExclusion( std::unique_ptr<SHAPE> aShape )
  543. {
  544. m_edgeExclusions.push_back( std::move( aShape ) );
  545. }
  546. bool NODE::QueryEdgeExclusions( const VECTOR2I& aPos ) const
  547. {
  548. for( const std::unique_ptr<SHAPE>& edgeExclusion : m_edgeExclusions )
  549. {
  550. if( edgeExclusion->Collide( aPos ) )
  551. return true;
  552. }
  553. return false;
  554. }
  555. void NODE::doRemove( ITEM* aItem )
  556. {
  557. bool holeRemoved = false; // fixme: better logic, I don't like this
  558. // case 1: removing an item that is stored in the root node from any branch:
  559. // mark it as overridden, but do not remove
  560. if( aItem->BelongsTo( m_root ) && !isRoot() )
  561. {
  562. m_override.insert( aItem );
  563. if( aItem->HasHole() )
  564. m_override.insert( aItem->Hole() );
  565. }
  566. // case 2: the item belongs to this branch or a parent, non-root branch,
  567. // or the root itself and we are the root: remove from the index
  568. else if( !aItem->BelongsTo( m_root ) || isRoot() )
  569. {
  570. m_index->Remove( aItem );
  571. if( aItem->HasHole() )
  572. {
  573. m_index->Remove( aItem->Hole() );
  574. holeRemoved = true;
  575. }
  576. }
  577. // the item belongs to this particular branch: un-reference it
  578. if( aItem->BelongsTo( this ) )
  579. {
  580. aItem->SetOwner( nullptr );
  581. m_root->m_garbageItems.insert( aItem );
  582. HOLE *hole = aItem->Hole();
  583. if( hole )
  584. {
  585. if( ! holeRemoved )
  586. {
  587. m_index->Remove( hole ); // hole is not directly owned by NODE but by the parent SOLID/VIA.
  588. }
  589. hole->SetOwner( aItem );
  590. }
  591. }
  592. }
  593. void NODE::removeSegmentIndex( SEGMENT* aSeg )
  594. {
  595. unlinkJoint( aSeg->Seg().A, aSeg->Layers(), aSeg->Net(), aSeg );
  596. unlinkJoint( aSeg->Seg().B, aSeg->Layers(), aSeg->Net(), aSeg );
  597. }
  598. void NODE::removeArcIndex( ARC* aArc )
  599. {
  600. unlinkJoint( aArc->Anchor( 0 ), aArc->Layers(), aArc->Net(), aArc );
  601. unlinkJoint( aArc->Anchor( 1 ), aArc->Layers(), aArc->Net(), aArc );
  602. }
  603. void NODE::rebuildJoint( const JOINT* aJoint, const ITEM* aItem )
  604. {
  605. // We have to split a single joint (associated with a via or a pad, binding together multiple
  606. // layers) into multiple independent joints. As I'm a lazy bastard, I simply delete the
  607. // via/solid and all its links and re-insert them.
  608. std::vector<ITEM*> links( aJoint->LinkList() );
  609. JOINT::HASH_TAG tag;
  610. NET_HANDLE net = aItem->Net();
  611. tag.net = net;
  612. tag.pos = aJoint->Pos();
  613. bool split;
  614. do
  615. {
  616. split = false;
  617. auto range = m_joints.equal_range( tag );
  618. if( range.first == m_joints.end() )
  619. break;
  620. // find and remove all joints containing the via to be removed
  621. for( auto f = range.first; f != range.second; ++f )
  622. {
  623. if( aItem->LayersOverlap( &f->second ) )
  624. {
  625. m_joints.erase( f );
  626. split = true;
  627. break;
  628. }
  629. }
  630. } while( split );
  631. bool completelyErased = false;
  632. if( !isRoot() && m_joints.find( tag ) == m_joints.end() )
  633. {
  634. JOINT jtDummy( tag.pos, PNS_LAYER_RANGE(-1), tag.net );
  635. m_joints.insert( TagJointPair( tag, jtDummy ) );
  636. completelyErased = true;
  637. }
  638. // and re-link them, using the former via's link list
  639. for( ITEM* link : links )
  640. {
  641. if( link != aItem )
  642. linkJoint( tag.pos, link->Layers(), net, link );
  643. else if( !completelyErased )
  644. unlinkJoint( tag.pos, link->Layers(), net, link );
  645. }
  646. }
  647. void NODE::removeViaIndex( VIA* aVia )
  648. {
  649. const JOINT* jt = FindJoint( aVia->Pos(), aVia->Layers().Start(), aVia->Net() );
  650. assert( jt );
  651. rebuildJoint( jt, aVia );
  652. }
  653. void NODE::removeSolidIndex( SOLID* aSolid )
  654. {
  655. if( !aSolid->IsRoutable() )
  656. return;
  657. // fixme: redundant code
  658. const JOINT* jt = FindJoint( aSolid->Pos(), aSolid->Layers().Start(), aSolid->Net() );
  659. assert( jt );
  660. rebuildJoint( jt, aSolid );
  661. }
  662. void NODE::Replace( ITEM* aOldItem, std::unique_ptr< ITEM > aNewItem )
  663. {
  664. Remove( aOldItem );
  665. add( aNewItem.release() );
  666. }
  667. void NODE::Replace( LINE& aOldLine, LINE& aNewLine )
  668. {
  669. Remove( aOldLine );
  670. Add( aNewLine );
  671. }
  672. void NODE::Remove( SOLID* aSolid )
  673. {
  674. removeSolidIndex( aSolid );
  675. doRemove( aSolid );
  676. }
  677. void NODE::Remove( VIA* aVia )
  678. {
  679. removeViaIndex( aVia );
  680. doRemove( aVia );
  681. if( !aVia->Owner() )
  682. {
  683. assert( aVia->Hole()->BelongsTo( aVia ) );
  684. }
  685. }
  686. void NODE::Remove( SEGMENT* aSegment )
  687. {
  688. removeSegmentIndex( aSegment );
  689. doRemove( aSegment );
  690. }
  691. void NODE::Remove( ARC* aArc )
  692. {
  693. removeArcIndex( aArc );
  694. doRemove( aArc );
  695. }
  696. void NODE::Remove( ITEM* aItem )
  697. {
  698. switch( aItem->Kind() )
  699. {
  700. case ITEM::ARC_T:
  701. Remove( static_cast<ARC*>( aItem ) );
  702. break;
  703. case ITEM::SOLID_T:
  704. {
  705. SOLID* solid = static_cast<SOLID*>( aItem );
  706. if( solid->HasHole() )
  707. {
  708. Remove( solid->Hole() );
  709. solid->Hole()->SetOwner( solid );
  710. }
  711. Remove( static_cast<SOLID*>( aItem ) );
  712. break;
  713. }
  714. case ITEM::SEGMENT_T:
  715. Remove( static_cast<SEGMENT*>( aItem ) );
  716. break;
  717. case ITEM::LINE_T:
  718. {
  719. LINE* l = static_cast<LINE*>( aItem );
  720. for ( LINKED_ITEM* s : l->Links() )
  721. Remove( s );
  722. break;
  723. }
  724. case ITEM::VIA_T:
  725. {
  726. VIA* via = static_cast<VIA*>( aItem );
  727. if( via->HasHole() )
  728. {
  729. Remove( via->Hole() );
  730. via->Hole()->SetOwner( via );
  731. }
  732. Remove( static_cast<VIA*>( aItem ) );
  733. break;
  734. }
  735. default:
  736. break;
  737. }
  738. }
  739. void NODE::Remove( LINE& aLine )
  740. {
  741. // LINE does not have a separate remover, as LINEs are never truly a member of the tree
  742. std::vector<LINKED_ITEM*>& segRefs = aLine.Links();
  743. for( LINKED_ITEM* li : segRefs )
  744. {
  745. if( li->OfKind( ITEM::SEGMENT_T ) )
  746. Remove( static_cast<SEGMENT*>( li ) );
  747. else if( li->OfKind( ITEM::ARC_T ) )
  748. Remove( static_cast<ARC*>( li ) );
  749. else if( li->OfKind( ITEM::VIA_T ) )
  750. Remove( static_cast<VIA*>( li ) );
  751. }
  752. aLine.SetOwner( nullptr );
  753. aLine.ClearLinks();
  754. }
  755. void NODE::followLine( LINKED_ITEM* aCurrent, bool aScanDirection, int& aPos, int aLimit,
  756. VECTOR2I* aCorners, LINKED_ITEM** aSegments, bool* aArcReversed,
  757. bool& aGuardHit, bool aStopAtLockedJoints, bool aFollowLockedSegments )
  758. {
  759. bool prevReversed = false;
  760. const VECTOR2I guard = aCurrent->Anchor( aScanDirection );
  761. for( int count = 0 ; ; ++count )
  762. {
  763. const VECTOR2I p = aCurrent->Anchor( aScanDirection ^ prevReversed );
  764. const JOINT* jt = FindJoint( p, aCurrent );
  765. if( !jt )
  766. break;
  767. aCorners[aPos] = jt->Pos();
  768. aSegments[aPos] = aCurrent;
  769. aArcReversed[aPos] = false;
  770. if( aCurrent->Kind() == ITEM::ARC_T )
  771. {
  772. if( ( aScanDirection && jt->Pos() == aCurrent->Anchor( 0 ) )
  773. || ( !aScanDirection && jt->Pos() == aCurrent->Anchor( 1 ) ) )
  774. {
  775. aArcReversed[aPos] = true;
  776. }
  777. }
  778. aPos += ( aScanDirection ? 1 : -1 );
  779. if( count && guard == p )
  780. {
  781. if( aPos >= 0 && aPos < aLimit )
  782. aSegments[aPos] = nullptr;
  783. aGuardHit = true;
  784. break;
  785. }
  786. bool locked = aStopAtLockedJoints ? jt->IsLocked() : false;
  787. if( locked || aPos < 0 || aPos == aLimit )
  788. break;
  789. aCurrent = jt->NextSegment( aCurrent, aFollowLockedSegments );
  790. if( !aCurrent )
  791. break;
  792. prevReversed = ( aCurrent && jt->Pos() == aCurrent->Anchor( aScanDirection ) );
  793. }
  794. }
  795. const LINE NODE::AssembleLine( LINKED_ITEM* aSeg, int* aOriginSegmentIndex,
  796. bool aStopAtLockedJoints, bool aFollowLockedSegments )
  797. {
  798. const int MaxVerts = 1024 * 16;
  799. std::array<VECTOR2I, MaxVerts + 1> corners;
  800. std::array<LINKED_ITEM*, MaxVerts + 1> segs;
  801. std::array<bool, MaxVerts + 1> arcReversed;
  802. LINE pl;
  803. bool guardHit = false;
  804. int i_start = MaxVerts / 2;
  805. int i_end = i_start + 1;
  806. pl.SetWidth( aSeg->Width() );
  807. pl.SetLayers( aSeg->Layers() );
  808. pl.SetNet( aSeg->Net() );
  809. pl.SetOwner( this );
  810. followLine( aSeg, false, i_start, MaxVerts, corners.data(), segs.data(), arcReversed.data(),
  811. guardHit, aStopAtLockedJoints, aFollowLockedSegments );
  812. if( !guardHit )
  813. {
  814. followLine( aSeg, true, i_end, MaxVerts, corners.data(), segs.data(), arcReversed.data(),
  815. guardHit, aStopAtLockedJoints, aFollowLockedSegments );
  816. }
  817. int n = 0;
  818. LINKED_ITEM* prev_seg = nullptr;
  819. bool originSet = false;
  820. SHAPE_LINE_CHAIN& line = pl.Line();
  821. for( int i = i_start + 1; i < i_end; i++ )
  822. {
  823. const VECTOR2I& p = corners[i];
  824. LINKED_ITEM* li = segs[i];
  825. if( !li || li->Kind() != ITEM::ARC_T )
  826. line.Append( p );
  827. if( li && prev_seg != li )
  828. {
  829. if( li->Kind() == ITEM::ARC_T )
  830. {
  831. const ARC* arc = static_cast<const ARC*>( li );
  832. const SHAPE_ARC* sa = static_cast<const SHAPE_ARC*>( arc->Shape( -1 ) );
  833. int nSegs = line.PointCount();
  834. VECTOR2I last = nSegs ? line.CPoint( -1 ) : VECTOR2I();
  835. ssize_t lastShape = nSegs ? line.ArcIndex( static_cast<ssize_t>( nSegs ) - 1 ) : -1;
  836. line.Append( arcReversed[i] ? sa->Reversed() : *sa );
  837. }
  838. pl.Link( li );
  839. // latter condition to avoid loops
  840. if( li == aSeg && aOriginSegmentIndex && !originSet )
  841. {
  842. wxASSERT( n < line.SegmentCount() ||
  843. ( n == line.SegmentCount() && li->Kind() == ITEM::SEGMENT_T ) );
  844. *aOriginSegmentIndex = line.PointCount() - 1;
  845. originSet = true;
  846. }
  847. }
  848. prev_seg = li;
  849. }
  850. // Remove duplicate verts, but do NOT remove colinear segments here!
  851. pl.Line().RemoveDuplicatePoints();
  852. // TODO: maintain actual segment index under simplification system
  853. if( aOriginSegmentIndex && *aOriginSegmentIndex >= pl.SegmentCount() )
  854. *aOriginSegmentIndex = pl.SegmentCount() - 1;
  855. wxASSERT_MSG( pl.SegmentCount() != 0, "assembled line should never be empty" );
  856. return pl;
  857. }
  858. void NODE::FindLineEnds( const LINE& aLine, JOINT& aA, JOINT& aB )
  859. {
  860. aA = *FindJoint( aLine.CPoint( 0 ), &aLine );
  861. aB = *FindJoint( aLine.CPoint( -1 ), &aLine );
  862. }
  863. int NODE::FindLinesBetweenJoints( const JOINT& aA, const JOINT& aB, std::vector<LINE>& aLines )
  864. {
  865. for( ITEM* item : aA.LinkList() )
  866. {
  867. if( item->Kind() == ITEM::SEGMENT_T || item->Kind() == ITEM::ARC_T )
  868. {
  869. LINKED_ITEM* li = static_cast<LINKED_ITEM*>( item );
  870. LINE line = AssembleLine( li );
  871. if( !line.Layers().Overlaps( aB.Layers() ) )
  872. continue;
  873. JOINT j_start, j_end;
  874. FindLineEnds( line, j_start, j_end );
  875. int id_start = line.CLine().Find( aA.Pos() );
  876. int id_end = line.CLine().Find( aB.Pos() );
  877. if( id_end < id_start )
  878. std::swap( id_end, id_start );
  879. if( id_start >= 0 && id_end >= 0 )
  880. {
  881. line.ClipVertexRange( id_start, id_end );
  882. aLines.push_back( line );
  883. }
  884. }
  885. }
  886. return 0;
  887. }
  888. void NODE::FixupVirtualVias()
  889. {
  890. const SEGMENT* locked_seg = nullptr;
  891. std::vector<VVIA*> vvias;
  892. for( auto& jointPair : m_joints )
  893. {
  894. JOINT joint = jointPair.second;
  895. if( joint.Layers().IsMultilayer() )
  896. continue;
  897. int n_seg = 0, n_solid = 0, n_vias = 0;
  898. int prev_w = -1;
  899. int max_w = -1;
  900. bool is_width_change = false;
  901. bool is_locked = false;
  902. for( const ITEM* item : joint.LinkList() )
  903. {
  904. if( item->OfKind( ITEM::VIA_T ) )
  905. {
  906. n_vias++;
  907. }
  908. else if( item->OfKind( ITEM::SOLID_T ) )
  909. {
  910. n_solid++;
  911. }
  912. else if( const auto t = dyn_cast<const PNS::SEGMENT*>( item ) )
  913. {
  914. int w = t->Width();
  915. if( prev_w >= 0 && w != prev_w )
  916. {
  917. is_width_change = true;
  918. }
  919. max_w = std::max( w, max_w );
  920. prev_w = w;
  921. is_locked = t->IsLocked();
  922. locked_seg = t;
  923. }
  924. }
  925. if( ( is_width_change || n_seg >= 3 || is_locked ) && n_solid == 0 && n_vias == 0 )
  926. {
  927. // fixme: the hull margin here is an ugly temporary workaround. The real fix
  928. // is to use octagons for via force propagation.
  929. vvias.push_back( new VVIA( joint.Pos(), joint.Layers().Start(),
  930. max_w + 2 * PNS_HULL_MARGIN, joint.Net() ) );
  931. }
  932. if( is_locked )
  933. {
  934. const VECTOR2I& secondPos = ( locked_seg->Seg().A == joint.Pos() ) ?
  935. locked_seg->Seg().B :
  936. locked_seg->Seg().A;
  937. vvias.push_back( new VVIA( secondPos, joint.Layers().Start(),
  938. max_w + 2 * PNS_HULL_MARGIN, joint.Net() ) );
  939. }
  940. }
  941. for( auto vvia : vvias )
  942. {
  943. Add( ItemCast<VIA>( std::move( std::unique_ptr<VVIA>( vvia ) ) ) );
  944. }
  945. }
  946. const JOINT* NODE::FindJoint( const VECTOR2I& aPos, int aLayer, NET_HANDLE aNet ) const
  947. {
  948. JOINT::HASH_TAG tag;
  949. tag.net = aNet;
  950. tag.pos = aPos;
  951. JOINT_MAP::const_iterator f = m_joints.find( tag ), end = m_joints.end();
  952. if( f == end && !isRoot() )
  953. {
  954. end = m_root->m_joints.end();
  955. f = m_root->m_joints.find( tag ); // m_root->FindJoint(aPos, aLayer, aNet);
  956. }
  957. while( f != end )
  958. {
  959. if( f->second.Pos() == aPos && f->second.Net() == aNet && f->second.Layers().Overlaps( aLayer ) )
  960. return &f->second;
  961. f++;
  962. }
  963. return nullptr;
  964. }
  965. void NODE::LockJoint( const VECTOR2I& aPos, const ITEM* aItem, bool aLock )
  966. {
  967. JOINT& jt = touchJoint( aPos, aItem->Layers(), aItem->Net() );
  968. jt.Lock( aLock );
  969. }
  970. JOINT& NODE::touchJoint( const VECTOR2I& aPos, const PNS_LAYER_RANGE& aLayers, NET_HANDLE aNet )
  971. {
  972. JOINT::HASH_TAG tag;
  973. tag.pos = aPos;
  974. tag.net = aNet;
  975. // try to find the joint in this node.
  976. JOINT_MAP::iterator f = m_joints.find( tag );
  977. std::pair<JOINT_MAP::iterator, JOINT_MAP::iterator> range;
  978. // not found and we are not root? find in the root and copy results here.
  979. if( f == m_joints.end() && !isRoot() )
  980. {
  981. range = m_root->m_joints.equal_range( tag );
  982. for( f = range.first; f != range.second; ++f )
  983. m_joints.insert( *f );
  984. }
  985. // now insert and combine overlapping joints
  986. JOINT jt( aPos, aLayers, aNet );
  987. bool merged;
  988. do
  989. {
  990. merged = false;
  991. range = m_joints.equal_range( tag );
  992. if( range.first == m_joints.end() )
  993. break;
  994. for( f = range.first; f != range.second; ++f )
  995. {
  996. if( aLayers.Overlaps( f->second.Layers() ) )
  997. {
  998. jt.Merge( f->second );
  999. m_joints.erase( f );
  1000. merged = true;
  1001. break;
  1002. }
  1003. }
  1004. } while( merged );
  1005. return m_joints.insert( TagJointPair( tag, jt ) )->second;
  1006. }
  1007. void JOINT::Dump() const
  1008. {
  1009. wxLogTrace( wxT( "PNS" ), wxT( "joint layers %d-%d, net %d, pos %s, links: %d" ),
  1010. m_layers.Start(),
  1011. m_layers.End(),
  1012. m_tag.net,
  1013. m_tag.pos.Format().c_str(),
  1014. LinkCount() );
  1015. }
  1016. void NODE::linkJoint( const VECTOR2I& aPos, const PNS_LAYER_RANGE& aLayers, NET_HANDLE aNet,
  1017. ITEM* aWhere )
  1018. {
  1019. JOINT& jt = touchJoint( aPos, aLayers, aNet );
  1020. jt.Link( aWhere );
  1021. }
  1022. void NODE::unlinkJoint( const VECTOR2I& aPos, const PNS_LAYER_RANGE& aLayers, NET_HANDLE aNet,
  1023. ITEM* aWhere )
  1024. {
  1025. // fixme: remove dangling joints
  1026. JOINT& jt = touchJoint( aPos, aLayers, aNet );
  1027. jt.Unlink( aWhere );
  1028. }
  1029. void NODE::Dump( bool aLong )
  1030. {
  1031. #if 0
  1032. std::unordered_set<SEGMENT*> all_segs;
  1033. SHAPE_INDEX_LIST<ITEM*>::iterator i;
  1034. for( i = m_items.begin(); i != m_items.end(); i++ )
  1035. {
  1036. if( (*i)->GetKind() == ITEM::SEGMENT_T )
  1037. all_segs.insert( static_cast<SEGMENT*>( *i ) );
  1038. }
  1039. if( !isRoot() )
  1040. {
  1041. for( i = m_root->m_items.begin(); i != m_root->m_items.end(); i++ )
  1042. {
  1043. if( (*i)->GetKind() == ITEM::SEGMENT_T && !overrides( *i ) )
  1044. all_segs.insert( static_cast<SEGMENT*>(*i) );
  1045. }
  1046. }
  1047. JOINT_MAP::iterator j;
  1048. if( aLong )
  1049. {
  1050. for( j = m_joints.begin(); j != m_joints.end(); ++j )
  1051. {
  1052. wxLogTrace( wxT( "PNS" ), wxT( "joint : %s, links : %d\n" ),
  1053. j->second.GetPos().Format().c_str(), j->second.LinkCount() );
  1054. JOINT::LINKED_ITEMS::const_iterator k;
  1055. for( k = j->second.GetLinkList().begin(); k != j->second.GetLinkList().end(); ++k )
  1056. {
  1057. const ITEM* m_item = *k;
  1058. switch( m_item->GetKind() )
  1059. {
  1060. case ITEM::SEGMENT_T:
  1061. {
  1062. const SEGMENT* seg = static_cast<const SEGMENT*>( m_item );
  1063. wxLogTrace( wxT( "PNS" ), wxT( " -> seg %s %s\n" ),
  1064. seg->GetSeg().A.Format().c_str(),
  1065. seg->GetSeg().B.Format().c_str() );
  1066. break;
  1067. }
  1068. default:
  1069. break;
  1070. }
  1071. }
  1072. }
  1073. }
  1074. int lines_count = 0;
  1075. while( !all_segs.empty() )
  1076. {
  1077. SEGMENT* s = *all_segs.begin();
  1078. LINE* l = AssembleLine( s );
  1079. LINE::LinkedSegments* seg_refs = l->GetLinkedSegments();
  1080. if( aLong )
  1081. {
  1082. wxLogTrace( wxT( "PNS" ), wxT( "Line: %s, net %d " ),
  1083. l->GetLine().Format().c_str(), l->GetNet() );
  1084. }
  1085. for( std::vector<SEGMENT*>::iterator j = seg_refs->begin(); j != seg_refs->end(); ++j )
  1086. {
  1087. wxLogTrace( wxT( "PNS" ), wxT( "%s " ), (*j)->GetSeg().A.Format().c_str() );
  1088. if( j + 1 == seg_refs->end() )
  1089. wxLogTrace( wxT( "PNS" ), wxT( "%s\n" ), (*j)->GetSeg().B.Format().c_str() );
  1090. all_segs.erase( *j );
  1091. }
  1092. lines_count++;
  1093. }
  1094. wxLogTrace( wxT( "PNS" ), wxT( "Local joints: %d, lines : %d \n" ),
  1095. m_joints.size(), lines_count );
  1096. #endif
  1097. }
  1098. void NODE::GetUpdatedItems( ITEM_VECTOR& aRemoved, ITEM_VECTOR& aAdded )
  1099. {
  1100. if( isRoot() )
  1101. return;
  1102. if( m_override.size() )
  1103. aRemoved.reserve( m_override.size() );
  1104. if( m_index->Size() )
  1105. aAdded.reserve( m_index->Size() );
  1106. for( ITEM* item : m_override )
  1107. aRemoved.push_back( item );
  1108. for( ITEM* item : *m_index )
  1109. aAdded.push_back( item );
  1110. }
  1111. void NODE::releaseChildren()
  1112. {
  1113. // copy the kids as the NODE destructor erases the item from the parent node.
  1114. std::set<NODE*> kids = m_children;
  1115. for( NODE* node : kids )
  1116. {
  1117. node->releaseChildren();
  1118. delete node;
  1119. }
  1120. }
  1121. void NODE::releaseGarbage()
  1122. {
  1123. if( !isRoot() )
  1124. return;
  1125. std::vector<const ITEM*> cacheCheckItems;
  1126. cacheCheckItems.reserve( m_garbageItems.size() );
  1127. for( ITEM* item : m_garbageItems )
  1128. {
  1129. if( !item->BelongsTo( this ) )
  1130. delete item;
  1131. }
  1132. m_garbageItems.clear();
  1133. if( m_ruleResolver )
  1134. {
  1135. m_ruleResolver->ClearCacheForItems( cacheCheckItems );
  1136. }
  1137. }
  1138. void NODE::Commit( NODE* aNode )
  1139. {
  1140. if( aNode->isRoot() )
  1141. return;
  1142. for( ITEM* item : aNode->m_override )
  1143. Remove( item );
  1144. for( ITEM* item : *aNode->m_index )
  1145. {
  1146. if( item->HasHole() )
  1147. {
  1148. item->Hole()->SetOwner( item );
  1149. }
  1150. item->SetRank( -1 );
  1151. item->Unmark();
  1152. add( item );
  1153. }
  1154. releaseChildren();
  1155. releaseGarbage();
  1156. }
  1157. void NODE::KillChildren()
  1158. {
  1159. releaseChildren();
  1160. }
  1161. void NODE::AllItemsInNet( NET_HANDLE aNet, std::set<ITEM*>& aItems, int aKindMask )
  1162. {
  1163. INDEX::NET_ITEMS_LIST* l_cur = m_index->GetItemsForNet( aNet );
  1164. if( l_cur )
  1165. {
  1166. for( ITEM* item : *l_cur )
  1167. {
  1168. if( item->OfKind( aKindMask ) && item->IsRoutable() )
  1169. aItems.insert( item );
  1170. }
  1171. }
  1172. if( !isRoot() )
  1173. {
  1174. INDEX::NET_ITEMS_LIST* l_root = m_root->m_index->GetItemsForNet( aNet );
  1175. if( l_root )
  1176. {
  1177. for( ITEM* item : *l_root )
  1178. {
  1179. if( !Overrides( item ) && item->OfKind( aKindMask ) && item->IsRoutable() )
  1180. aItems.insert( item );
  1181. }
  1182. }
  1183. }
  1184. }
  1185. void NODE::ClearRanks( int aMarkerMask )
  1186. {
  1187. for( ITEM* item : *m_index )
  1188. {
  1189. item->SetRank( -1 );
  1190. item->Mark( item->Marker() & ~aMarkerMask );
  1191. }
  1192. }
  1193. void NODE::RemoveByMarker( int aMarker )
  1194. {
  1195. std::vector<ITEM*> garbage;
  1196. for( ITEM* item : *m_index )
  1197. {
  1198. if( item->Marker() & aMarker )
  1199. garbage.emplace_back( item );
  1200. }
  1201. for( ITEM* item : garbage )
  1202. Remove( item );
  1203. }
  1204. SEGMENT* NODE::findRedundantSegment( const VECTOR2I& A, const VECTOR2I& B, const PNS_LAYER_RANGE& lr,
  1205. NET_HANDLE aNet )
  1206. {
  1207. const JOINT* jtStart = FindJoint( A, lr.Start(), aNet );
  1208. if( !jtStart )
  1209. return nullptr;
  1210. for( ITEM* item : jtStart->LinkList() )
  1211. {
  1212. if( item->OfKind( ITEM::SEGMENT_T ) )
  1213. {
  1214. SEGMENT* seg2 = (SEGMENT*)item;
  1215. const VECTOR2I a2( seg2->Seg().A );
  1216. const VECTOR2I b2( seg2->Seg().B );
  1217. if( seg2->Layers().Start() == lr.Start()
  1218. && ( ( A == a2 && B == b2 ) || ( A == b2 && B == a2 ) ) )
  1219. {
  1220. return seg2;
  1221. }
  1222. }
  1223. }
  1224. return nullptr;
  1225. }
  1226. SEGMENT* NODE::findRedundantSegment( SEGMENT* aSeg )
  1227. {
  1228. return findRedundantSegment( aSeg->Seg().A, aSeg->Seg().B, aSeg->Layers(), aSeg->Net() );
  1229. }
  1230. ARC* NODE::findRedundantArc( const VECTOR2I& A, const VECTOR2I& B, const PNS_LAYER_RANGE& lr,
  1231. NET_HANDLE aNet )
  1232. {
  1233. const JOINT* jtStart = FindJoint( A, lr.Start(), aNet );
  1234. if( !jtStart )
  1235. return nullptr;
  1236. for( ITEM* item : jtStart->LinkList() )
  1237. {
  1238. if( item->OfKind( ITEM::ARC_T ) )
  1239. {
  1240. ARC* seg2 = static_cast<ARC*>( item );
  1241. const VECTOR2I a2( seg2->Anchor( 0 ) );
  1242. const VECTOR2I b2( seg2->Anchor( 1 ) );
  1243. if( seg2->Layers().Start() == lr.Start()
  1244. && ( ( A == a2 && B == b2 ) || ( A == b2 && B == a2 ) ) )
  1245. {
  1246. return seg2;
  1247. }
  1248. }
  1249. }
  1250. return nullptr;
  1251. }
  1252. ARC* NODE::findRedundantArc( ARC* aArc )
  1253. {
  1254. return findRedundantArc( aArc->Anchor( 0 ), aArc->Anchor( 1 ), aArc->Layers(), aArc->Net() );
  1255. }
  1256. int NODE::QueryJoints( const BOX2I& aBox, std::vector<JOINT*>& aJoints, PNS_LAYER_RANGE aLayerMask,
  1257. int aKindMask )
  1258. {
  1259. int n = 0;
  1260. aJoints.clear();
  1261. for( JOINT_MAP::value_type& j : m_joints )
  1262. {
  1263. if( !j.second.Layers().Overlaps( aLayerMask ) )
  1264. continue;
  1265. if( aBox.Contains( j.second.Pos() ) && j.second.LinkCount( aKindMask ) )
  1266. {
  1267. aJoints.push_back( &j.second );
  1268. n++;
  1269. }
  1270. }
  1271. if( isRoot() )
  1272. return n;
  1273. for( JOINT_MAP::value_type& j : m_root->m_joints )
  1274. {
  1275. if( !Overrides( &j.second ) && j.second.Layers().Overlaps( aLayerMask ) )
  1276. {
  1277. if( aBox.Contains( j.second.Pos() ) && j.second.LinkCount( aKindMask ) )
  1278. {
  1279. aJoints.push_back( &j.second );
  1280. n++;
  1281. }
  1282. }
  1283. }
  1284. return n;
  1285. }
  1286. ITEM *NODE::FindItemByParent( const BOARD_ITEM* aParent )
  1287. {
  1288. if( aParent && aParent->IsConnected() )
  1289. {
  1290. const BOARD_CONNECTED_ITEM* cItem = static_cast<const BOARD_CONNECTED_ITEM*>( aParent );
  1291. INDEX::NET_ITEMS_LIST* l_cur = m_index->GetItemsForNet( cItem->GetNet() );
  1292. if( l_cur )
  1293. {
  1294. for( ITEM* item : *l_cur )
  1295. {
  1296. if( item->Parent() == aParent )
  1297. return item;
  1298. }
  1299. }
  1300. }
  1301. return nullptr;
  1302. }
  1303. std::vector<ITEM*> NODE::FindItemsByZone( const ZONE* aParent )
  1304. {
  1305. std::vector<ITEM*> ret;
  1306. for( ITEM* item : *m_index )
  1307. {
  1308. if( item->Parent() == aParent )
  1309. ret.push_back( item );
  1310. }
  1311. return ret;
  1312. }
  1313. VIA* NODE::FindViaByHandle ( const VIA_HANDLE& handle ) const
  1314. {
  1315. const JOINT* jt = FindJoint( handle.pos, handle.layers.Start(), handle.net );
  1316. if( !jt )
  1317. return nullptr;
  1318. for( ITEM* item : jt->LinkList() )
  1319. {
  1320. if( item->OfKind( ITEM::VIA_T ) )
  1321. {
  1322. if( item->Net() == handle.net && item->Layers().Overlaps(handle.layers) )
  1323. return static_cast<VIA*>( item );
  1324. }
  1325. }
  1326. return nullptr;
  1327. }
  1328. }