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, 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
28#ifndef __SHAPE_INDEX_H
29#define __SHAPE_INDEX_H
30
31#include <vector>
32
34#include <geometry/shape.h>
35#include <math/box2.h>
36
46template <class T>
47static const SHAPE* shapeFunctor( T aItem, int aLayer )
48{
49 return aItem->Shape( aLayer );
50}
51
61template <class T>
62BOX2I boundingBox( T aObject, int aLayer )
63{
64 BOX2I bbox = shapeFunctor( aObject, aLayer )->BBox();
65
66 return bbox;
67}
68
78template <class T, class V>
79void acceptVisitor( T aObject, V aVisitor )
80{
81 aVisitor( aObject );
82}
83
96template <class T, class U>
97bool collide( T aObject, U aAnotherObject, int aLayer, int aMinDistance )
98{
99 return shapeFunctor( aObject, aLayer )->Collide( aAnotherObject, aMinDistance );
100}
101
102template <class T, class V>
103bool queryCallback( T aShape, void* aContext )
104{
105 V* visitor = (V*) aContext;
106
107 acceptVisitor<T, V>( aShape, *visitor );
108
109 return true;
110}
111
112template <class T = SHAPE*>
114{
115 public:
117
119 {
120 private:
121 using TreeIterator = typename TREE_TYPE::Iterator;
124
125 public:
126 Iterator( const TREE_TYPE& aTree ) :
127 m_current( aTree.begin() ),
128 m_end( aTree.end() )
129 {
130 }
131
133 {
134 return *m_current;
135 }
136
141 {
142 ++m_current;
143 return m_current != m_end;
144 }
145
149 bool operator++( int )
150 {
151 ++m_current;
152 return m_current != m_end;
153 }
154
160 bool IsNull() const
161 {
162 return m_current == m_end;
163 }
164
170 bool IsNotNull() const
171 {
172 return m_current != m_end;
173 }
174
181 {
182 T object = *m_current;
183 ++m_current;
184
185 return object;
186 }
187 };
188
189 explicit SHAPE_INDEX( int aLayer ) : m_shapeLayer( aLayer ) {}
190
191 ~SHAPE_INDEX() = default;
192
193 // Move semantics
194 SHAPE_INDEX( SHAPE_INDEX&& aOther ) noexcept = default;
195 SHAPE_INDEX& operator=( SHAPE_INDEX&& aOther ) noexcept = default;
196
197 // Non-copyable (use Clone() for intentional sharing)
198 SHAPE_INDEX( const SHAPE_INDEX& ) = delete;
199 SHAPE_INDEX& operator=( const SHAPE_INDEX& ) = delete;
200
206 {
207 SHAPE_INDEX clone( m_shapeLayer );
208 clone.m_tree = m_tree.Clone();
209 return clone;
210 }
211
217 void Add( T aShape )
218 {
219 BOX2I box = boundingBox( aShape, m_shapeLayer );
220 int min[2] = { box.GetX(), box.GetY() };
221 int max[2] = { box.GetRight(), box.GetBottom() };
222
223 m_tree.Insert( min, max, aShape );
224 }
225
232 void Add( T aShape, const BOX2I& aBbox )
233 {
234 int min[2] = { aBbox.GetX(), aBbox.GetY() };
235 int max[2] = { aBbox.GetRight(), aBbox.GetBottom() };
236
237 m_tree.Insert( min, max, aShape );
238 }
239
245 void Remove( T aShape )
246 {
247 BOX2I box = boundingBox( aShape, m_shapeLayer );
248 int min[2] = { box.GetX(), box.GetY() };
249 int max[2] = { box.GetRight(), box.GetBottom() };
250
251 m_tree.Remove( min, max, aShape );
252 }
253
258 {
259 m_tree.RemoveAll();
260 }
261
267 template <class V>
268 void Accept( V aVisitor )
269 {
270 for( const T& item : m_tree )
271 acceptVisitor( item, aVisitor );
272 }
273
278 void BulkLoad( std::vector<std::pair<T, BOX2I>>& aItems )
279 {
280 using BULK_ENTRY = typename TREE_TYPE::BULK_ENTRY;
281 std::vector<BULK_ENTRY> entries;
282 entries.reserve( aItems.size() );
283
284 for( const auto& [item, box] : aItems )
285 {
286 BULK_ENTRY e;
287 e.min[0] = box.GetX();
288 e.min[1] = box.GetY();
289 e.max[0] = box.GetRight();
290 e.max[1] = box.GetBottom();
291 e.data = item;
292 entries.push_back( e );
293 }
294
295 m_tree.BulkLoad( entries );
296 }
297
303 void Reindex()
304 {
305 std::vector<T> items;
306 items.reserve( m_tree.size() );
307
308 for( const T& item : m_tree )
309 items.push_back( item );
310
311 m_tree.RemoveAll();
312
313 for( T& item : items )
314 Add( item );
315 }
316
324 template <class V>
325 int Query( const SHAPE *aShape, int aMinDistance, V& aVisitor) const
326 {
327 BOX2I box = aShape->BBox();
328 box.Inflate( aMinDistance );
329
330 int min[2] = { box.GetX(), box.GetY() };
331 int max[2] = { box.GetRight(), box.GetBottom() };
332
333 return m_tree.Search( min, max, aVisitor );
334 }
335
341 Iterator Begin() const
342 {
343 return Iterator( m_tree );
344 }
345
346 // Range-for support
347 typename TREE_TYPE::Iterator begin() const { return m_tree.begin(); }
348 typename TREE_TYPE::Iterator end() const { return m_tree.end(); }
349
350 size_t Size() const { return m_tree.size(); }
351
352 private:
355};
356
357#endif /* __SHAPE_INDEX_H */
BOX2< VECTOR2I > BOX2I
Definition box2.h:922
constexpr BOX2< Vec > & Inflate(coord_type dx, coord_type dy)
Inflates the rectangle horizontally by dx and vertically by dy.
Definition box2.h:558
constexpr coord_type GetY() const
Definition box2.h:208
constexpr coord_type GetX() const
Definition box2.h:207
constexpr coord_type GetRight() const
Definition box2.h:217
constexpr coord_type GetBottom() const
Definition box2.h:222
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:126
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:181
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:97
bool queryCallback(T aShape, void *aContext)
static const SHAPE * shapeFunctor(T aItem, int aLayer)
Used by SHAPE_INDEX to get a SHAPE* from another type.
Definition shape_index.h:47
void acceptVisitor(T aObject, V aVisitor)
Used by SHAPE_INDEX to implement Accept().
Definition shape_index.h:79
BOX2I boundingBox(T aObject, int aLayer)
Used by SHAPE_INDEX to get the bounding box of a generic T object.
Definition shape_index.h:62