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.

577 lines
12 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. * Copyright (C) 2018-2020 KiCad Developers, see AUTHORS.txt for contributors.
  6. *
  7. * @author Maciej Suminski <maciej.suminski@cern.ch>
  8. * @author Tomasz Wlostowski <tomasz.wlostowski@cern.ch>
  9. *
  10. * This program is free software; you can redistribute it and/or
  11. * modify it under the terms of the GNU General Public License
  12. * as published by the Free Software Foundation; either version 2
  13. * of the License, or (at your option) any later version.
  14. *
  15. * This program is distributed in the hope that it will be useful,
  16. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  17. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  18. * GNU General Public License for more details.
  19. *
  20. * You should have received a copy of the GNU General Public License
  21. * along with this program; if not, you may find one here:
  22. * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
  23. * or you may search the http://www.gnu.org website for the version 2 license,
  24. * or you may write to the Free Software Foundation, Inc.,
  25. * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
  26. */
  27. #ifndef PCBNEW_CONNECTIVITY_CONNECTIVITY_ITEMS_H_
  28. #define PCBNEW_CONNECTIVITY_CONNECTIVITY_ITEMS_H_
  29. #include <class_board.h>
  30. #include <class_pad.h>
  31. #include <class_module.h>
  32. #include <class_track.h>
  33. #include <class_zone.h>
  34. #include <geometry/shape_poly_set.h>
  35. #include <geometry/poly_grid_partition.h>
  36. #include <memory>
  37. #include <algorithm>
  38. #include <functional>
  39. #include <vector>
  40. #include <deque>
  41. #include <intrusive_list.h>
  42. #include <connectivity/connectivity_rtree.h>
  43. #include <connectivity/connectivity_data.h>
  44. class CN_ITEM;
  45. class CN_CLUSTER;
  46. class CN_ANCHOR
  47. {
  48. public:
  49. CN_ANCHOR()
  50. {
  51. m_item = nullptr;
  52. }
  53. CN_ANCHOR( const VECTOR2I& aPos, CN_ITEM* aItem )
  54. {
  55. m_pos = aPos;
  56. m_item = aItem;
  57. assert( m_item );
  58. }
  59. bool Valid() const;
  60. CN_ITEM* Item() const
  61. {
  62. return m_item;
  63. }
  64. BOARD_CONNECTED_ITEM* Parent() const;
  65. const VECTOR2I& Pos() const
  66. {
  67. return m_pos;
  68. }
  69. void Move( const VECTOR2I& aPos )
  70. {
  71. m_pos += aPos;
  72. }
  73. const unsigned int Dist( const CN_ANCHOR& aSecond )
  74. {
  75. return ( m_pos - aSecond.Pos() ).EuclideanNorm();
  76. }
  77. /// Returns tag, common identifier for connected nodes
  78. inline int GetTag() const
  79. {
  80. return m_tag;
  81. }
  82. /// Sets tag, common identifier for connected nodes
  83. inline void SetTag( int aTag )
  84. {
  85. m_tag = aTag;
  86. }
  87. /// Decides whether this node can be a ratsnest line target
  88. inline void SetNoLine( bool aEnable )
  89. {
  90. m_noline = aEnable;
  91. }
  92. /// Returns true if this node can be a target for ratsnest lines
  93. inline const bool& GetNoLine() const
  94. {
  95. return m_noline;
  96. }
  97. inline void SetCluster( std::shared_ptr<CN_CLUSTER> aCluster )
  98. {
  99. m_cluster = aCluster;
  100. }
  101. inline const std::shared_ptr<CN_CLUSTER>& GetCluster() const
  102. {
  103. return m_cluster;
  104. }
  105. /**
  106. * has meaning only for tracks and vias.
  107. * @return true if this anchor is dangling
  108. * The anchor point is dangling if the parent is a track
  109. * and this anchor point is not connected to another item
  110. * ( track, vas pad or zone) or if the parent is a via and this anchor point
  111. * is connected to only one track and not to another item
  112. */
  113. bool IsDangling() const;
  114. /**
  115. * has meaning only for tracks and vias.
  116. * @return the count of items connected to this anchor
  117. */
  118. int ConnectedItemsCount() const;
  119. // Tag used for unconnected items.
  120. static const int TAG_UNCONNECTED = -1;
  121. private:
  122. /// Position of the anchor
  123. VECTOR2I m_pos;
  124. /// Item owning the anchor
  125. CN_ITEM* m_item = nullptr;
  126. /// Tag for quick connection resolution
  127. int m_tag = -1;
  128. /// Whether it the node can be a target for ratsnest lines
  129. bool m_noline = false;
  130. /// Cluster to which the anchor belongs
  131. std::shared_ptr<CN_CLUSTER> m_cluster;
  132. };
  133. typedef std::shared_ptr<CN_ANCHOR> CN_ANCHOR_PTR;
  134. typedef std::vector<CN_ANCHOR_PTR> CN_ANCHORS;
  135. // basic connectivity item
  136. class CN_ITEM
  137. {
  138. public:
  139. using CONNECTED_ITEMS = std::vector<CN_ITEM*>;
  140. private:
  141. BOARD_CONNECTED_ITEM* m_parent;
  142. ///> list of items physically connected (touching)
  143. CONNECTED_ITEMS m_connected;
  144. CN_ANCHORS m_anchors;
  145. ///> visited flag for the BFS scan
  146. bool m_visited;
  147. ///> can the net propagator modify the netcode?
  148. bool m_canChangeNet;
  149. ///> valid flag, used to identify garbage items (we use lazy removal)
  150. bool m_valid;
  151. ///> mutex protecting this item's connected_items set to allow parallel connection threads
  152. std::mutex m_listLock;
  153. protected:
  154. ///> dirty flag, used to identify recently added item not yet scanned into the connectivity search
  155. bool m_dirty;
  156. ///> layer range over which the item exists
  157. LAYER_RANGE m_layers;
  158. ///> bounding box for the item
  159. BOX2I m_bbox;
  160. public:
  161. void Dump();
  162. CN_ITEM( BOARD_CONNECTED_ITEM* aParent, bool aCanChangeNet, int aAnchorCount = 2 )
  163. {
  164. m_parent = aParent;
  165. m_canChangeNet = aCanChangeNet;
  166. m_visited = false;
  167. m_valid = true;
  168. m_dirty = true;
  169. m_anchors.reserve( std::max( 6, aAnchorCount ) );
  170. m_layers = LAYER_RANGE( 0, PCB_LAYER_ID_COUNT );
  171. m_connected.reserve( 8 );
  172. }
  173. virtual ~CN_ITEM() {};
  174. void AddAnchor( const VECTOR2I& aPos )
  175. {
  176. m_anchors.emplace_back( std::make_shared<CN_ANCHOR>( aPos, this ) );
  177. }
  178. CN_ANCHORS& Anchors()
  179. {
  180. return m_anchors;
  181. }
  182. void SetValid( bool aValid )
  183. {
  184. m_valid = aValid;
  185. }
  186. bool Valid() const
  187. {
  188. return m_valid;
  189. }
  190. void SetDirty( bool aDirty )
  191. {
  192. m_dirty = aDirty;
  193. }
  194. bool Dirty() const
  195. {
  196. return m_dirty;
  197. }
  198. /**
  199. * Function SetLayers()
  200. *
  201. * Sets the layers spanned by the item to aLayers.
  202. */
  203. void SetLayers( const LAYER_RANGE& aLayers )
  204. {
  205. m_layers = aLayers;
  206. }
  207. /**
  208. * Function SetLayer()
  209. *
  210. * Sets the layers spanned by the item to a single layer aLayer.
  211. */
  212. void SetLayer( int aLayer )
  213. {
  214. m_layers = LAYER_RANGE( aLayer, aLayer );
  215. }
  216. /**
  217. * Function Layers()
  218. *
  219. * Returns the contiguous set of layers spanned by the item.
  220. */
  221. const LAYER_RANGE& Layers() const
  222. {
  223. return m_layers;
  224. }
  225. /**
  226. * Function Layer()
  227. *
  228. * Returns the item's layer, for single-layered items only.
  229. */
  230. virtual int Layer() const
  231. {
  232. return Layers().Start();
  233. }
  234. const BOX2I& BBox()
  235. {
  236. if( m_dirty && m_valid )
  237. {
  238. EDA_RECT box = m_parent->GetBoundingBox();
  239. m_bbox = BOX2I( box.GetPosition(), box.GetSize() );
  240. }
  241. return m_bbox;
  242. }
  243. BOARD_CONNECTED_ITEM* Parent() const
  244. {
  245. return m_parent;
  246. }
  247. const CONNECTED_ITEMS& ConnectedItems() const
  248. {
  249. return m_connected;
  250. }
  251. void ClearConnections()
  252. {
  253. m_connected.clear();
  254. }
  255. void SetVisited( bool aVisited )
  256. {
  257. m_visited = aVisited;
  258. }
  259. bool Visited() const
  260. {
  261. return m_visited;
  262. }
  263. bool CanChangeNet() const
  264. {
  265. return m_canChangeNet;
  266. }
  267. void Connect( CN_ITEM* b )
  268. {
  269. std::lock_guard<std::mutex> lock( m_listLock );
  270. auto i = std::lower_bound( m_connected.begin(), m_connected.end(), b );
  271. if( i != m_connected.end() && *i == b )
  272. return;
  273. m_connected.insert( i, b );
  274. }
  275. void RemoveInvalidRefs();
  276. virtual int AnchorCount() const;
  277. virtual const VECTOR2I GetAnchor( int n ) const;
  278. int Net() const
  279. {
  280. return ( !m_parent || !m_valid ) ? -1 : m_parent->GetNetCode();
  281. }
  282. };
  283. typedef std::shared_ptr<CN_ITEM> CN_ITEM_PTR;
  284. class CN_ZONE : public CN_ITEM
  285. {
  286. public:
  287. CN_ZONE( ZONE_CONTAINER* aParent, PCB_LAYER_ID aLayer, bool aCanChangeNet, int aSubpolyIndex ) :
  288. CN_ITEM( aParent, aCanChangeNet ),
  289. m_subpolyIndex( aSubpolyIndex ),
  290. m_layer( aLayer )
  291. {
  292. SHAPE_LINE_CHAIN outline = aParent->GetFilledPolysList( aLayer ).COutline( aSubpolyIndex );
  293. outline.SetClosed( true );
  294. outline.Simplify();
  295. m_cachedPoly = std::make_unique<POLY_GRID_PARTITION>( outline, 16 );
  296. }
  297. int SubpolyIndex() const
  298. {
  299. return m_subpolyIndex;
  300. }
  301. bool ContainsAnchor( const CN_ANCHOR_PTR anchor ) const
  302. {
  303. return ContainsPoint( anchor->Pos(), 0 );
  304. }
  305. bool ContainsPoint( const VECTOR2I p, int aAccuracy = 0 ) const
  306. {
  307. auto zone = static_cast<ZONE_CONTAINER*> ( Parent() );
  308. int clearance = aAccuracy;
  309. if( zone->GetFilledPolysUseThickness() )
  310. clearance += ( zone->GetMinThickness() + 1 ) / 2;
  311. return m_cachedPoly->ContainsPoint( p, clearance );
  312. }
  313. const BOX2I& BBox()
  314. {
  315. if( m_dirty )
  316. m_bbox = m_cachedPoly->BBox();
  317. return m_bbox;
  318. }
  319. virtual int AnchorCount() const override;
  320. virtual const VECTOR2I GetAnchor( int n ) const override;
  321. private:
  322. std::vector<VECTOR2I> m_testOutlinePoints;
  323. std::unique_ptr<POLY_GRID_PARTITION> m_cachedPoly;
  324. int m_subpolyIndex;
  325. PCB_LAYER_ID m_layer;
  326. };
  327. class CN_LIST
  328. {
  329. private:
  330. bool m_dirty;
  331. bool m_hasInvalid;
  332. CN_RTREE<CN_ITEM*> m_index;
  333. protected:
  334. std::vector<CN_ITEM*> m_items;
  335. void addItemtoTree( CN_ITEM* item )
  336. {
  337. m_index.Insert( item );
  338. }
  339. public:
  340. CN_LIST()
  341. {
  342. m_dirty = false;
  343. m_hasInvalid = false;
  344. }
  345. void Clear()
  346. {
  347. for( auto item : m_items )
  348. delete item;
  349. m_items.clear();
  350. m_index.RemoveAll();
  351. }
  352. using ITER = decltype( m_items )::iterator;
  353. using CONST_ITER = decltype( m_items )::const_iterator;
  354. ITER begin() { return m_items.begin(); };
  355. ITER end() { return m_items.end(); };
  356. CONST_ITER begin() const
  357. {
  358. return m_items.begin();
  359. }
  360. CONST_ITER end() const
  361. {
  362. return m_items.end();
  363. }
  364. CN_ITEM* operator[] ( int aIndex ) { return m_items[aIndex]; }
  365. template <class T>
  366. void FindNearby( CN_ITEM *aItem, T aFunc )
  367. {
  368. m_index.Query( aItem->BBox(), aItem->Layers(), aFunc );
  369. }
  370. void SetHasInvalid( bool aInvalid = true )
  371. {
  372. m_hasInvalid = aInvalid;
  373. }
  374. void SetDirty( bool aDirty = true )
  375. {
  376. m_dirty = aDirty;
  377. }
  378. bool IsDirty() const
  379. {
  380. return m_dirty;
  381. }
  382. void RemoveInvalidItems( std::vector<CN_ITEM*>& aGarbage );
  383. void ClearDirtyFlags()
  384. {
  385. for( auto item : m_items )
  386. item->SetDirty( false );
  387. SetDirty( false );
  388. }
  389. void MarkAllAsDirty()
  390. {
  391. for( auto item : m_items )
  392. item->SetDirty( true );
  393. SetDirty( true );
  394. }
  395. int Size() const
  396. {
  397. return m_items.size();
  398. }
  399. CN_ITEM* Add( D_PAD* pad );
  400. CN_ITEM* Add( TRACK* track );
  401. CN_ITEM* Add( ARC* track );
  402. CN_ITEM* Add( VIA* via );
  403. const std::vector<CN_ITEM*> Add( ZONE_CONTAINER* zone, PCB_LAYER_ID aLayer );
  404. };
  405. class CN_CLUSTER
  406. {
  407. private:
  408. bool m_conflicting = false;
  409. int m_originNet = 0;
  410. CN_ITEM* m_originPad = nullptr;
  411. std::vector<CN_ITEM*> m_items;
  412. public:
  413. CN_CLUSTER();
  414. ~CN_CLUSTER();
  415. bool HasValidNet() const
  416. {
  417. return m_originNet > 0;
  418. }
  419. int OriginNet() const
  420. {
  421. return m_originNet;
  422. }
  423. wxString OriginNetName() const;
  424. bool Contains( const CN_ITEM* aItem );
  425. bool Contains( const BOARD_CONNECTED_ITEM* aItem );
  426. void Dump();
  427. int Size() const
  428. {
  429. return m_items.size();
  430. }
  431. bool HasNet() const
  432. {
  433. return m_originNet > 0;
  434. }
  435. bool IsOrphaned() const
  436. {
  437. return m_originPad == nullptr;
  438. }
  439. bool IsConflicting() const
  440. {
  441. return m_conflicting;
  442. }
  443. void Add( CN_ITEM* item );
  444. using ITER = decltype(m_items)::iterator;
  445. ITER begin() { return m_items.begin(); };
  446. ITER end() { return m_items.end(); };
  447. };
  448. typedef std::shared_ptr<CN_CLUSTER> CN_CLUSTER_PTR;
  449. #endif /* PCBNEW_CONNECTIVITY_CONNECTIVITY_ITEMS_H_ */