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.

364 lines
9.3 KiB

  1. /*
  2. * This program source code file is part of KiCad, a free EDA CAD application.
  3. *
  4. * Copyright (C) 2013 CERN
  5. * @author Jacobo Aragunde Pérez
  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. #ifndef __SHAPE_INDEX_H
  26. #define __SHAPE_INDEX_H
  27. #include <vector>
  28. #include <geometry/rtree.h>
  29. #include <geometry/shape.h>
  30. #include <math/box2.h>
  31. /**
  32. * shapeFunctor template function
  33. *
  34. * It is used by SHAPE_INDEX to get a SHAPE* from another type.
  35. * By default relies on T::GetShape() method, should be specialized if the T object
  36. * doesn't allow that method.
  37. * @param aItem generic T object
  38. * @return a SHAPE* object equivalent to object.
  39. */
  40. template <class T>
  41. static const SHAPE* shapeFunctor( T aItem )
  42. {
  43. return aItem->Shape();
  44. }
  45. /**
  46. * boundingBox template method
  47. *
  48. * It is used by SHAPE_INDEX to get the bounding box of a generic T object.
  49. * By default relies on T::BBox() method, should be specialized if the T object
  50. * doesn't allow that method.
  51. * @param aObject generic T object
  52. * @return a BOX2I object containing the bounding box of the T object.
  53. */
  54. template <class T>
  55. BOX2I boundingBox( T aObject )
  56. {
  57. return shapeFunctor( aObject )->BBox();
  58. }
  59. /**
  60. * acceptVisitor template method
  61. *
  62. * It is used by SHAPE_INDEX to implement Accept().
  63. * By default relies on V::operation() redefinition, should be specialized if V class
  64. * doesn't have its () operation defined to accept T objects.
  65. * @param aObject generic T object
  66. * @param aVisitor V visitor object
  67. */
  68. template <class T, class V>
  69. void acceptVisitor( T aObject, V aVisitor )
  70. {
  71. aVisitor( aObject );
  72. }
  73. /**
  74. * collide template method
  75. *
  76. * It is used by SHAPE_INDEX to implement Query().
  77. * By default relies on T::Collide(U) method, should be specialized if the T object
  78. * doesn't allow that method.
  79. * @param aObject generic T object
  80. * @param aAnotherObject generic U object
  81. * @param aMinDistance minimum collision distance
  82. * @return if object and anotherObject collide
  83. */
  84. template <class T, class U>
  85. bool collide( T aObject, U aAnotherObject, int aMinDistance )
  86. {
  87. return shapeFunctor( aObject )->Collide( aAnotherObject, aMinDistance );
  88. }
  89. template <class T, class V>
  90. bool queryCallback( T aShape, void* aContext )
  91. {
  92. V* visitor = (V*) aContext;
  93. acceptVisitor<T, V>( aShape, *visitor );
  94. return true;
  95. }
  96. template <class T = SHAPE*>
  97. class SHAPE_INDEX
  98. {
  99. public:
  100. class Iterator
  101. {
  102. private:
  103. typedef typename RTree<T, int, 2, double>::Iterator RTreeIterator;
  104. RTreeIterator iterator;
  105. /**
  106. * Function Init()
  107. *
  108. * Setup the internal tree iterator.
  109. * @param aTree pointer to a RTREE object
  110. */
  111. void Init( RTree<T, int, 2, double>* aTree )
  112. {
  113. aTree->GetFirst( iterator );
  114. }
  115. public:
  116. /**
  117. * Iterator constructor
  118. *
  119. * Creates an iterator for the index object
  120. * @param aIndex SHAPE_INDEX object to iterate
  121. */
  122. Iterator( SHAPE_INDEX* aIndex )
  123. {
  124. Init( aIndex->m_tree );
  125. }
  126. /**
  127. * Operator * (prefix)
  128. *
  129. * Returns the next data element.
  130. */
  131. T operator*()
  132. {
  133. return *iterator;
  134. }
  135. /**
  136. * Operator ++ (prefix)
  137. *
  138. * Shifts the iterator to the next element.
  139. */
  140. bool operator++()
  141. {
  142. return ++iterator;
  143. }
  144. /**
  145. * Operator ++ (postfix)
  146. *
  147. * Shifts the iterator to the next element.
  148. */
  149. bool operator++( int )
  150. {
  151. return ++iterator;
  152. }
  153. /**
  154. * Function IsNull()
  155. *
  156. * Checks if the iterator has reached the end.
  157. * @return true if it is in an invalid position (data finished)
  158. */
  159. bool IsNull()
  160. {
  161. return iterator.IsNull();
  162. }
  163. /**
  164. * Function IsNotNull()
  165. *
  166. * Checks if the iterator has not reached the end.
  167. * @return true if it is in an valid position (data not finished)
  168. */
  169. bool IsNotNull()
  170. {
  171. return iterator.IsNotNull();
  172. }
  173. /**
  174. * Function Next()
  175. *
  176. * Returns the current element of the iterator and moves to the next
  177. * position.
  178. * @return SHAPE object pointed by the iterator before moving to the next position.
  179. */
  180. T Next()
  181. {
  182. T object = *iterator;
  183. ++iterator;
  184. return object;
  185. }
  186. };
  187. SHAPE_INDEX();
  188. ~SHAPE_INDEX();
  189. /**
  190. * Function Add()
  191. *
  192. * Adds a SHAPE to the index.
  193. * @param aShape is the new SHAPE.
  194. */
  195. void Add( T aShape );
  196. /**
  197. * Function Remove()
  198. *
  199. * Removes a SHAPE to the index.
  200. * @param aShape is the new SHAPE.
  201. */
  202. void Remove( T aShape );
  203. /**
  204. * Function RemoveAll()
  205. *
  206. * Removes all the contents of the index.
  207. */
  208. void RemoveAll();
  209. /**
  210. * Function Accept()
  211. *
  212. * Accepts a visitor for every SHAPE object contained in this INDEX.
  213. * @param aVisitor Visitor object to be run
  214. */
  215. template <class V>
  216. void Accept( V aVisitor )
  217. {
  218. Iterator iter = this->Begin();
  219. while( !iter.IsNull() )
  220. {
  221. T shape = *iter;
  222. acceptVisitor( shape, aVisitor );
  223. iter++;
  224. }
  225. }
  226. /**
  227. * Function Reindex()
  228. *
  229. * Rebuilds the index. This should be used if the geometry of the objects
  230. * contained by the index has changed.
  231. */
  232. void Reindex();
  233. /**
  234. * Function Query()
  235. *
  236. * Runs a callback on every SHAPE object contained in the bounding box of (shape).
  237. * @param aShape shape to search against
  238. * @param aMinDistance distance threshold
  239. * @param aVisitor object to be invoked on every object contained in the search area.
  240. */
  241. template <class V>
  242. int Query( const SHAPE *aShape, int aMinDistance, V& aVisitor, bool aExact )
  243. {
  244. BOX2I box = aShape->BBox();
  245. box.Inflate( aMinDistance );
  246. int min[2] = { box.GetX(), box.GetY() };
  247. int max[2] = { box.GetRight(), box.GetBottom() };
  248. return this->m_tree->Search( min, max, aVisitor );
  249. }
  250. /**
  251. * Function Begin()
  252. *
  253. * Creates an iterator for the current index object
  254. * @return iterator
  255. */
  256. Iterator Begin();
  257. private:
  258. RTree<T, int, 2, double>* m_tree;
  259. };
  260. /*
  261. * Class members implementation
  262. */
  263. template <class T>
  264. SHAPE_INDEX<T>::SHAPE_INDEX()
  265. {
  266. this->m_tree = new RTree<T, int, 2, double>();
  267. }
  268. template <class T>
  269. SHAPE_INDEX<T>::~SHAPE_INDEX()
  270. {
  271. delete this->m_tree;
  272. }
  273. template <class T>
  274. void SHAPE_INDEX<T>::Add( T aShape )
  275. {
  276. BOX2I box = boundingBox( aShape );
  277. int min[2] = { box.GetX(), box.GetY() };
  278. int max[2] = { box.GetRight(), box.GetBottom() };
  279. this->m_tree->Insert( min, max, aShape );
  280. }
  281. template <class T>
  282. void SHAPE_INDEX<T>::Remove( T aShape )
  283. {
  284. BOX2I box = boundingBox( aShape );
  285. int min[2] = { box.GetX(), box.GetY() };
  286. int max[2] = { box.GetRight(), box.GetBottom() };
  287. this->m_tree->Remove( min, max, aShape );
  288. }
  289. template <class T>
  290. void SHAPE_INDEX<T>::RemoveAll()
  291. {
  292. this->m_tree->RemoveAll();
  293. }
  294. template <class T>
  295. void SHAPE_INDEX<T>::Reindex()
  296. {
  297. RTree<T, int, 2, double>* newTree;
  298. newTree = new RTree<T, int, 2, double>();
  299. Iterator iter = this->Begin();
  300. while( !iter.IsNull() )
  301. {
  302. T shape = *iter;
  303. BOX2I box = boundingBox( shape );
  304. int min[2] = { box.GetX(), box.GetY() };
  305. int max[2] = { box.GetRight(), box.GetBottom() };
  306. newTree->Insert( min, max, shape );
  307. iter++;
  308. }
  309. delete this->m_tree;
  310. this->m_tree = newTree;
  311. }
  312. template <class T>
  313. typename SHAPE_INDEX<T>::Iterator SHAPE_INDEX<T>::Begin()
  314. {
  315. return Iterator( this );
  316. }
  317. #endif