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.

515 lines
14 KiB

  1. /*
  2. * This program source code file is part of KICAD, a free EDA CAD application.
  3. *
  4. * Copyright (C) 2013-2017 CERN
  5. * @author Maciej Suminski <maciej.suminski@cern.ch>
  6. * @author Tomasz Wlostowski <tomasz.wlostowski@cern.ch>
  7. *
  8. * This program is free software; you can redistribute it and/or
  9. * modify it under the terms of the GNU General Public License
  10. * as published by the Free Software Foundation; either version 2
  11. * of the License, or (at your option) any later version.
  12. *
  13. * This program is distributed in the hope that it will be useful,
  14. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  15. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  16. * GNU General Public License for more details.
  17. *
  18. * You should have received a copy of the GNU General Public License
  19. * along with this program; if not, you may find one here:
  20. * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
  21. * or you may search the http://www.gnu.org website for the version 2 license,
  22. * or you may write to the Free Software Foundation, Inc.,
  23. * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
  24. */
  25. /**
  26. * @file ratsnest_data.cpp
  27. * @brief Class that computes missing connections on a PCB.
  28. */
  29. #ifdef USE_OPENMP
  30. #include <omp.h>
  31. #endif /* USE_OPENMP */
  32. #ifdef PROFILE
  33. #include <profile.h>
  34. #endif
  35. #include <ratsnest_data.h>
  36. #include <functional>
  37. using namespace std::placeholders;
  38. #include <cassert>
  39. #include <algorithm>
  40. #include <limits>
  41. #include <connectivity_algo.h>
  42. static uint64_t getDistance( const CN_ANCHOR_PTR& aNode1, const CN_ANCHOR_PTR& aNode2 )
  43. {
  44. double dx = ( aNode1->Pos().x - aNode2->Pos().x );
  45. double dy = ( aNode1->Pos().y - aNode2->Pos().y );
  46. return sqrt( dx * dx + dy * dy );
  47. }
  48. static bool sortWeight( const CN_EDGE& aEdge1, const CN_EDGE& aEdge2 )
  49. {
  50. return aEdge1.GetWeight() < aEdge2.GetWeight();
  51. }
  52. static const std::vector<CN_EDGE> kruskalMST( std::list<CN_EDGE>& aEdges,
  53. std::vector<CN_ANCHOR_PTR>& aNodes )
  54. {
  55. unsigned int nodeNumber = aNodes.size();
  56. unsigned int mstExpectedSize = nodeNumber - 1;
  57. unsigned int mstSize = 0;
  58. bool ratsnestLines = false;
  59. //printf("mst nodes : %d edges : %d\n", aNodes.size(), aEdges.size () );
  60. // The output
  61. std::vector<CN_EDGE> mst;
  62. // Set tags for marking cycles
  63. std::unordered_map<CN_ANCHOR_PTR, int> tags;
  64. unsigned int tag = 0;
  65. for( auto& node : aNodes )
  66. {
  67. node->SetTag( tag );
  68. tags[node] = tag++;
  69. }
  70. // Lists of nodes connected together (subtrees) to detect cycles in the graph
  71. std::vector<std::list<int> > cycles( nodeNumber );
  72. for( unsigned int i = 0; i < nodeNumber; ++i )
  73. cycles[i].push_back( i );
  74. // Kruskal algorithm requires edges to be sorted by their weight
  75. aEdges.sort( sortWeight );
  76. while( mstSize < mstExpectedSize && !aEdges.empty() )
  77. {
  78. //printf("mstSize %d %d\n", mstSize, mstExpectedSize);
  79. auto& dt = aEdges.front();
  80. int srcTag = tags[dt.GetSourceNode()];
  81. int trgTag = tags[dt.GetTargetNode()];
  82. // Check if by adding this edge we are going to join two different forests
  83. if( srcTag != trgTag )
  84. {
  85. // Because edges are sorted by their weight, first we always process connected
  86. // items (weight == 0). Once we stumble upon an edge with non-zero weight,
  87. // it means that the rest of the lines are ratsnest.
  88. if( !ratsnestLines && dt.GetWeight() != 0 )
  89. ratsnestLines = true;
  90. // Update tags
  91. if( ratsnestLines )
  92. {
  93. for( auto it = cycles[trgTag].begin(); it != cycles[trgTag].end(); ++it )
  94. {
  95. tags[aNodes[*it]] = srcTag;
  96. }
  97. // Do a copy of edge, but make it RN_EDGE_MST. In contrary to RN_EDGE,
  98. // RN_EDGE_MST saves both source and target node and does not require any other
  99. // edges to exist for getting source/target nodes
  100. CN_EDGE newEdge ( dt.GetSourceNode(), dt.GetTargetNode(), dt.GetWeight() );
  101. assert( newEdge.GetSourceNode()->GetTag() != newEdge.GetTargetNode()->GetTag() );
  102. assert( newEdge.GetWeight() > 0 );
  103. mst.push_back( newEdge );
  104. ++mstSize;
  105. }
  106. else
  107. {
  108. // for( it = cycles[trgTag].begin(), itEnd = cycles[trgTag].end(); it != itEnd; ++it )
  109. // for( auto it : cycles[trgTag] )
  110. for( auto it = cycles[trgTag].begin(); it != cycles[trgTag].end(); ++it )
  111. {
  112. tags[aNodes[*it]] = srcTag;
  113. aNodes[*it]->SetTag( srcTag );
  114. }
  115. // Processing a connection, decrease the expected size of the ratsnest MST
  116. --mstExpectedSize;
  117. }
  118. // Move nodes that were marked with old tag to the list marked with the new tag
  119. cycles[srcTag].splice( cycles[srcTag].end(), cycles[trgTag] );
  120. }
  121. // Remove the edge that was just processed
  122. aEdges.erase( aEdges.begin() );
  123. }
  124. // Probably we have discarded some of edges, so reduce the size
  125. mst.resize( mstSize );
  126. return mst;
  127. }
  128. class RN_NET::TRIANGULATOR_STATE
  129. {
  130. private:
  131. std::vector<CN_ANCHOR_PTR> m_allNodes;
  132. std::vector<VECTOR2I> m_prevNodes;
  133. std::vector<std::pair<int, int> > m_prevEdges;
  134. std::list<hed::EDGE_PTR> hedTriangulation( std::vector<hed::NODE_PTR>& aNodes )
  135. {
  136. hed::TRIANGULATION triangulator;
  137. triangulator.CreateDelaunay( aNodes.begin(), aNodes.end() );
  138. std::list<hed::EDGE_PTR> edges;
  139. triangulator.GetEdges( edges );
  140. return edges;
  141. }
  142. std::list<hed::EDGE_PTR> computeTriangulation( std::vector<hed::NODE_PTR>& aNodes )
  143. {
  144. #if 0
  145. bool refresh = false;
  146. // we assume aNodes are sorted
  147. VECTOR2I prevDelta;
  148. if ( aNodes.size() == m_prevNodes.size() )
  149. {
  150. for ( int i = 0; i < aNodes.size(); i++ )
  151. {
  152. const auto& a = aNodes[i];
  153. const auto& b = m_prevNodes[i];
  154. const auto delta = a->Pos() - b;
  155. if ( i > 0 && delta != prevDelta )
  156. {
  157. refresh = true;
  158. break;
  159. }
  160. prevDelta = delta;
  161. }
  162. }
  163. if( refresh )
  164. {
  165. m_prevNodes.resize( aNodes.size() );
  166. for ( int i = 0; i < aNodes.size(); i++ )
  167. {
  168. m_prevNodes[i] = aNodes[i]->Pos();
  169. }
  170. printf("need triang refresh\n");
  171. auto edges = hedTriangulation( aNodes );
  172. m_prevEdges.resize( edges.size() );
  173. int i = 0;
  174. for ( auto e : edges )
  175. {
  176. m_prevEdges[i].first = e->GetSourceNode()->Id();
  177. m_prevEdges[i].second = e->GetTargetNode()->Id();
  178. }
  179. }
  180. #endif
  181. return hedTriangulation( aNodes );
  182. }
  183. public:
  184. void Clear()
  185. {
  186. m_allNodes.clear();
  187. }
  188. void AddNode( CN_ANCHOR_PTR aNode )
  189. {
  190. m_allNodes.push_back( aNode );
  191. }
  192. const std::list<CN_EDGE> Triangulate()
  193. {
  194. std::list<CN_EDGE> mstEdges;
  195. std::list<hed::EDGE_PTR> triangEdges;
  196. std::vector<hed::NODE_PTR> triNodes;
  197. using ANCHOR_LIST = std::vector<CN_ANCHOR_PTR>;
  198. std::vector<ANCHOR_LIST> anchorChains;
  199. triNodes.reserve( m_allNodes.size() );
  200. anchorChains.reserve( m_allNodes.size() );
  201. std::sort( m_allNodes.begin(), m_allNodes.end(),
  202. [] ( const CN_ANCHOR_PTR& aNode1, const CN_ANCHOR_PTR& aNode2 )
  203. {
  204. if( aNode1->Pos().y < aNode2->Pos().y )
  205. return true;
  206. else if( aNode1->Pos().y == aNode2->Pos().y )
  207. {
  208. return aNode1->Pos().x < aNode2->Pos().x;
  209. }
  210. return false;
  211. }
  212. );
  213. CN_ANCHOR_PTR prev, last;
  214. int id = 0;
  215. for( auto n : m_allNodes )
  216. {
  217. anchorChains.push_back( ANCHOR_LIST() );
  218. }
  219. for( auto n : m_allNodes )
  220. {
  221. if( !prev || prev->Pos() != n->Pos() )
  222. {
  223. auto tn = std::make_shared<hed::NODE> ( n->Pos().x, n->Pos().y );
  224. tn->SetId( id );
  225. triNodes.push_back( tn );
  226. }
  227. id++;
  228. prev = n;
  229. }
  230. int prevId = 0;
  231. for( auto n : triNodes )
  232. {
  233. for( int i = prevId; i < n->Id(); i++ )
  234. anchorChains[prevId].push_back( m_allNodes[ i ] );
  235. prevId = n->Id();
  236. }
  237. for( int i = prevId; i < id; i++ )
  238. anchorChains[prevId].push_back( m_allNodes[ i ] );
  239. if( triNodes.size() == 1 )
  240. {
  241. return mstEdges;
  242. }
  243. else if( triNodes.size() == 2 )
  244. {
  245. auto src = m_allNodes[ triNodes[0]->Id() ];
  246. auto dst = m_allNodes[ triNodes[1]->Id() ];
  247. mstEdges.emplace_back( src, dst, getDistance( src, dst ) );
  248. }
  249. else
  250. {
  251. hed::TRIANGULATION triangulator;
  252. triangulator.CreateDelaunay( triNodes.begin(), triNodes.end() );
  253. // std::list<hed::EDGE_PTR> edges;
  254. triangulator.GetEdges( triangEdges );
  255. for( auto e : triangEdges )
  256. {
  257. auto src = m_allNodes[ e->GetSourceNode()->Id() ];
  258. auto dst = m_allNodes[ e->GetTargetNode()->Id() ];
  259. mstEdges.emplace_back( src, dst, getDistance( src, dst ) );
  260. }
  261. }
  262. for( unsigned int i = 0; i < anchorChains.size(); i++ )
  263. {
  264. auto& chain = anchorChains[i];
  265. if( chain.size() < 2 )
  266. continue;
  267. std::sort( chain.begin(), chain.end(),
  268. [] ( const CN_ANCHOR_PTR& a, const CN_ANCHOR_PTR& b ) {
  269. return a->GetCluster().get() < b->GetCluster().get();
  270. } );
  271. for( unsigned int j = 1; j < chain.size(); j++ )
  272. {
  273. const auto& prevNode = chain[j - 1];
  274. const auto& curNode = chain[j];
  275. int weight = prevNode->GetCluster() != curNode->GetCluster() ? 1 : 0;
  276. mstEdges.push_back( CN_EDGE ( prevNode, curNode, weight ) );
  277. }
  278. }
  279. return mstEdges;
  280. }
  281. };
  282. RN_NET::RN_NET() : m_dirty( true )
  283. {
  284. m_triangulator.reset( new TRIANGULATOR_STATE );
  285. }
  286. void RN_NET::compute()
  287. {
  288. // Special cases do not need complicated algorithms (actually, it does not work well with
  289. // the Delaunay triangulator)
  290. //printf("compute nodes : %d\n", m_nodes.size() );
  291. if( m_nodes.size() <= 2 )
  292. {
  293. m_rnEdges.clear();
  294. // Check if the only possible connection exists
  295. if( m_boardEdges.size() == 0 && m_nodes.size() == 2 )
  296. {
  297. auto last = ++m_nodes.begin();
  298. // There can be only one possible connection, but it is missing
  299. CN_EDGE edge (*m_nodes.begin(), *last );
  300. edge.GetSourceNode()->SetTag( 0 );
  301. edge.GetTargetNode()->SetTag( 1 );
  302. m_rnEdges.push_back( edge );
  303. }
  304. else
  305. {
  306. // Set tags to m_nodes as connected
  307. for( auto node : m_nodes )
  308. node->SetTag( 0 );
  309. }
  310. return;
  311. }
  312. m_triangulator->Clear();
  313. for( auto n : m_nodes )
  314. {
  315. m_triangulator->AddNode( n );
  316. }
  317. #ifdef PROFILE
  318. PROF_COUNTER cnt("triangulate");
  319. #endif
  320. auto triangEdges = m_triangulator->Triangulate();
  321. #ifdef PROFILE
  322. cnt.Show();
  323. #endif
  324. for( const auto& e : m_boardEdges )
  325. triangEdges.push_back( e );
  326. // Get the minimal spanning tree
  327. #ifdef PROFILE
  328. PROF_COUNTER cnt2("mst");
  329. #endif
  330. m_rnEdges = kruskalMST( triangEdges, m_nodes );
  331. #ifdef PROFILE
  332. cnt2.Show();
  333. #endif
  334. }
  335. void RN_NET::Update()
  336. {
  337. compute();
  338. m_dirty = false;
  339. }
  340. void RN_NET::Clear()
  341. {
  342. m_rnEdges.clear();
  343. m_boardEdges.clear();
  344. m_nodes.clear();
  345. m_dirty = true;
  346. }
  347. void RN_NET::AddCluster( CN_CLUSTER_PTR aCluster )
  348. {
  349. CN_ANCHOR_PTR firstAnchor;
  350. for( auto item : *aCluster )
  351. {
  352. bool isZone = dynamic_cast<CN_ZONE*>(item) != nullptr;
  353. auto& anchors = item->Anchors();
  354. unsigned int nAnchors = isZone ? 1 : anchors.size();
  355. if( nAnchors > anchors.size() )
  356. nAnchors = anchors.size();
  357. //printf("item %p anchors : %d\n", item, anchors.size() );
  358. //printf("add item %p anchors : %d net : %d\n", item, item->Anchors().size(), item->Parent()->GetNetCode() );
  359. for( unsigned int i = 0; i < nAnchors; i++ )
  360. {
  361. // printf("add anchor %p\n", anchors[i].get() );
  362. anchors[i]->SetCluster( aCluster );
  363. m_nodes.push_back(anchors[i]);
  364. if( firstAnchor )
  365. {
  366. if( firstAnchor != anchors[i] )
  367. {
  368. m_boardEdges.emplace_back( firstAnchor, anchors[i], 0 );
  369. }
  370. }
  371. else
  372. {
  373. firstAnchor = anchors[i];
  374. }
  375. }
  376. }
  377. }
  378. bool RN_NET::NearestBicoloredPair( const RN_NET& aOtherNet, CN_ANCHOR_PTR& aNode1,
  379. CN_ANCHOR_PTR& aNode2 ) const
  380. {
  381. bool rv = false;
  382. VECTOR2I::extended_type distMax = VECTOR2I::ECOORD_MAX;
  383. for( auto nodeA : m_nodes )
  384. {
  385. for( auto nodeB : aOtherNet.m_nodes )
  386. {
  387. if( !nodeA->GetNoLine() )
  388. {
  389. auto squaredDist = (nodeA->Pos() - nodeB->Pos() ).SquaredEuclideanNorm();
  390. if( squaredDist < distMax )
  391. {
  392. rv = true;
  393. distMax = squaredDist;
  394. aNode1 = nodeA;
  395. aNode2 = nodeB;
  396. }
  397. }
  398. }
  399. }
  400. return rv;
  401. }
  402. void RN_NET::SetVisible( bool aEnabled )
  403. {
  404. for( auto& edge : m_rnEdges )
  405. edge.SetVisible( aEnabled );
  406. }