KiCad PCB EDA Suite
Loading...
Searching...
No Matches
shape_index.h
Go to the documentation of this file.
1/*
2 * This program source code file is part of KiCad, a free EDA CAD application.
3 *
4 * Copyright (C) 2013 CERN
5 * Copyright The KiCad Developers, see AUTHORS.txt for contributors.
6 *
7 * @author Jacobo Aragunde Pérez
8 * @author Tomasz Wlostowski <[email protected]>
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, see <https://www.gnu.org/licenses/>.
22 */
23
24#ifndef __SHAPE_INDEX_H
25#define __SHAPE_INDEX_H
26
27#include <vector>
28
30#include <geometry/shape.h>
31#include <math/box2.h>
32
42template <class T>
43static const SHAPE* shapeFunctor( T aItem, int aLayer )
44{
45 return aItem->Shape( aLayer );
46}
47
57template <class T>
58BOX2I boundingBox( T aObject, int aLayer )
59{
60 BOX2I bbox = shapeFunctor( aObject, aLayer )->BBox();
61
62 return bbox;
63}
64
74template <class T, class V>
75void acceptVisitor( T aObject, V aVisitor )
76{
77 aVisitor( aObject );
78}
79
92template <class T, class U>
93bool collide( T aObject, U aAnotherObject, int aLayer, int aMinDistance )
94{
95 return shapeFunctor( aObject, aLayer )->Collide( aAnotherObject, aMinDistance );
96}
97
98template <class T, class V>
99bool queryCallback( T aShape, void* aContext )
100{
101 V* visitor = (V*) aContext;
102
103 acceptVisitor<T, V>( aShape, *visitor );
104
105 return true;
106}
107
108template <class T = SHAPE*>
110{
111 public:
113
115 {
116 private:
117 using TreeIterator = typename TREE_TYPE::Iterator;
120
121 public:
122 Iterator( const TREE_TYPE& aTree ) :
123 m_current( aTree.begin() ),
124 m_end( aTree.end() )
125 {
126 }
127
129 {
130 return *m_current;
131 }
132
137 {
138 ++m_current;
139 return m_current != m_end;
140 }
141
145 bool operator++( int )
146 {
147 ++m_current;
148 return m_current != m_end;
149 }
150
156 bool IsNull() const
157 {
158 return m_current == m_end;
159 }
160
166 bool IsNotNull() const
167 {
168 return m_current != m_end;
169 }
170
177 {
178 T object = *m_current;
179 ++m_current;
180
181 return object;
182 }
183 };
184
185 explicit SHAPE_INDEX( int aLayer ) : m_shapeLayer( aLayer ) {}
186
187 ~SHAPE_INDEX() = default;
188
189 // Move semantics
190 SHAPE_INDEX( SHAPE_INDEX&& aOther ) noexcept = default;
191 SHAPE_INDEX& operator=( SHAPE_INDEX&& aOther ) noexcept = default;
192
193 // Non-copyable (use Clone() for intentional sharing)
194 SHAPE_INDEX( const SHAPE_INDEX& ) = delete;
195 SHAPE_INDEX& operator=( const SHAPE_INDEX& ) = delete;
196
202 {
203 SHAPE_INDEX clone( m_shapeLayer );
204 clone.m_tree = m_tree.Clone();
205 return clone;
206 }
207
213 void Add( T aShape )
214 {
215 BOX2I box = boundingBox( aShape, m_shapeLayer );
216 int min[2] = { box.GetX(), box.GetY() };
217 int max[2] = { box.GetRight(), box.GetBottom() };
218
219 m_tree.Insert( min, max, aShape );
220 }
221
228 void Add( T aShape, const BOX2I& aBbox )
229 {
230 int min[2] = { aBbox.GetX(), aBbox.GetY() };
231 int max[2] = { aBbox.GetRight(), aBbox.GetBottom() };
232
233 m_tree.Insert( min, max, aShape );
234 }
235
241 void Remove( T aShape )
242 {
243 BOX2I box = boundingBox( aShape, m_shapeLayer );
244 int min[2] = { box.GetX(), box.GetY() };
245 int max[2] = { box.GetRight(), box.GetBottom() };
246
247 m_tree.Remove( min, max, aShape );
248 }
249
254 {
255 m_tree.RemoveAll();
256 }
257
263 template <class V>
264 void Accept( V aVisitor )
265 {
266 for( const T& item : m_tree )
267 acceptVisitor( item, aVisitor );
268 }
269
274 void BulkLoad( std::vector<std::pair<T, BOX2I>>& aItems )
275 {
276 using BULK_ENTRY = typename TREE_TYPE::BULK_ENTRY;
277 std::vector<BULK_ENTRY> entries;
278 entries.reserve( aItems.size() );
279
280 for( const auto& [item, box] : aItems )
281 {
282 BULK_ENTRY e;
283 e.min[0] = box.GetX();
284 e.min[1] = box.GetY();
285 e.max[0] = box.GetRight();
286 e.max[1] = box.GetBottom();
287 e.data = item;
288 entries.push_back( e );
289 }
290
291 m_tree.BulkLoad( entries );
292 }
293
299 void Reindex()
300 {
301 std::vector<T> items;
302 items.reserve( m_tree.size() );
303
304 for( const T& item : m_tree )
305 items.push_back( item );
306
307 m_tree.RemoveAll();
308
309 for( T& item : items )
310 Add( item );
311 }
312
320 template <class V>
321 int Query( const SHAPE *aShape, int aMinDistance, V& aVisitor) const
322 {
323 BOX2I box = aShape->BBox();
324 box.Inflate( aMinDistance );
325
326 int min[2] = { box.GetX(), box.GetY() };
327 int max[2] = { box.GetRight(), box.GetBottom() };
328
329 return m_tree.Search( min, max, aVisitor );
330 }
331
337 Iterator Begin() const
338 {
339 return Iterator( m_tree );
340 }
341
342 // Range-for support
343 typename TREE_TYPE::Iterator begin() const { return m_tree.begin(); }
344 typename TREE_TYPE::Iterator end() const { return m_tree.end(); }
345
346 size_t Size() const { return m_tree.size(); }
347
348 private:
351};
352
353#endif /* __SHAPE_INDEX_H */
BOX2< VECTOR2I > BOX2I
Definition box2.h:918
constexpr BOX2< Vec > & Inflate(coord_type dx, coord_type dy)
Inflates the rectangle horizontally by dx and vertically by dy.
Definition box2.h:554
constexpr coord_type GetY() const
Definition box2.h:204
constexpr coord_type GetX() const
Definition box2.h:203
constexpr coord_type GetRight() const
Definition box2.h:213
constexpr coord_type GetBottom() const
Definition box2.h:218
Iterator for traversing all data items.
Copy-on-Write wrapper for DYNAMIC_RTREE.
typename DYNAMIC_RTREE< DATATYPE, ELEMTYPE, NUMDIMS, TMAXNODES >::BULK_ENTRY BULK_ENTRY
Bulk load entries using Hilbert curve sorting and bottom-up packing.
bool operator++()
Shift the iterator to the next element.
bool IsNotNull() const
Check if the iterator has not reached the end.
bool operator++(int)
Shift the iterator to the next element.
typename TREE_TYPE::Iterator TreeIterator
T Next()
Return the current element of the iterator and moves to the next position.
bool IsNull() const
Check if the iterator has reached the end.
Iterator(const TREE_TYPE &aTree)
TreeIterator m_current
Iterator Begin() const
Create an iterator for the current index object.
TREE_TYPE::Iterator begin() const
SHAPE_INDEX(SHAPE_INDEX &&aOther) noexcept=default
void Remove(T aShape)
Remove a SHAPE from the index.
void BulkLoad(std::vector< std::pair< T, BOX2I > > &aItems)
Build from a batch of items using Hilbert-curve bulk loading.
SHAPE_INDEX & operator=(const SHAPE_INDEX &)=delete
TREE_TYPE::Iterator end() const
SHAPE_INDEX & operator=(SHAPE_INDEX &&aOther) noexcept=default
~SHAPE_INDEX()=default
KIRTREE::COW_RTREE< T, int, 2 > TREE_TYPE
SHAPE_INDEX(const SHAPE_INDEX &)=delete
SHAPE_INDEX Clone() const
Create a CoW clone that shares tree structure with this index.
void Add(T aShape, const BOX2I &aBbox)
Add a shape with alternate BBox.
SHAPE_INDEX(int aLayer)
TREE_TYPE m_tree
void RemoveAll()
Remove all the contents of the index.
void Accept(V aVisitor)
Accept a visitor for every SHAPE object contained in this INDEX.
void Reindex()
Rebuild the index.
size_t Size() const
void Add(T aShape)
Add a SHAPE to the index.
int Query(const SHAPE *aShape, int aMinDistance, V &aVisitor) const
Run a callback on every SHAPE object contained in the bounding box of (shape).
An abstract shape on 2D plane.
Definition shape.h:124
virtual bool Collide(const VECTOR2I &aP, int aClearance=0, int *aActual=nullptr, VECTOR2I *aLocation=nullptr) const
Check if the boundary of shape (this) lies closer to the point aP than aClearance,...
Definition shape.h:179
virtual const BOX2I BBox(int aClearance=0) const =0
Compute a bounding box of the shape, with a margin of aClearance a collision.
bool collide(T aObject, U aAnotherObject, int aLayer, int aMinDistance)
Used by SHAPE_INDEX to implement Query().
Definition shape_index.h:93
bool queryCallback(T aShape, void *aContext)
Definition shape_index.h:99
static const SHAPE * shapeFunctor(T aItem, int aLayer)
Used by SHAPE_INDEX to get a SHAPE* from another type.
Definition shape_index.h:43
void acceptVisitor(T aObject, V aVisitor)
Used by SHAPE_INDEX to implement Accept().
Definition shape_index.h:75
BOX2I boundingBox(T aObject, int aLayer)
Used by SHAPE_INDEX to get the bounding box of a generic T object.
Definition shape_index.h:58