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
43template <class T>
44static const SHAPE* shapeFunctor( T aItem, int aLayer )
45{
46 wxCHECK( aItem, nullptr );
47 return aItem->Shape( aLayer );
48}
49
60template <class T>
61BOX2I boundingBox( T aObject, int aLayer )
62{
63 const SHAPE* shape = shapeFunctor( aObject, aLayer );
64
65 BOX2I bBox;
66 wxCHECK( shape, bBox );
67
68 bBox = shape->BBox();
69 return bBox;
70}
71
81template <class T, class V>
82void acceptVisitor( T aObject, V aVisitor )
83{
84 aVisitor( aObject );
85}
86
99template <class T, class U>
100bool collide( T aObject, U aAnotherObject, int aLayer, int aMinDistance )
101{
102 const SHAPE* shape = shapeFunctor( aObject, aLayer );
103
104 wxCHECK( shape, false );
105
106 return shape->Collide( aAnotherObject, aMinDistance );
107}
108
109template <class T, class V>
110bool queryCallback( T aShape, void* aContext )
111{
112 V* visitor = (V*) aContext;
113
114 acceptVisitor<T, V>( aShape, *visitor );
115
116 return true;
117}
118
119template <class T = SHAPE*>
121{
122 public:
124
126 {
127 private:
128 using TreeIterator = typename TREE_TYPE::Iterator;
131
132 public:
133 Iterator( const TREE_TYPE& aTree ) :
134 m_current( aTree.begin() ),
135 m_end( aTree.end() )
136 {
137 }
138
140 {
141 return *m_current;
142 }
143
148 {
149 ++m_current;
150 return m_current != m_end;
151 }
152
156 bool operator++( int )
157 {
158 ++m_current;
159 return m_current != m_end;
160 }
161
167 bool IsNull() const
168 {
169 return m_current == m_end;
170 }
171
177 bool IsNotNull() const
178 {
179 return m_current != m_end;
180 }
181
188 {
189 T object = *m_current;
190 ++m_current;
191
192 return object;
193 }
194 };
195
196 explicit SHAPE_INDEX( int aLayer ) : m_shapeLayer( aLayer ) {}
197
198 ~SHAPE_INDEX() = default;
199
200 // Move semantics
201 SHAPE_INDEX( SHAPE_INDEX&& aOther ) noexcept = default;
202 SHAPE_INDEX& operator=( SHAPE_INDEX&& aOther ) noexcept = default;
203
204 // Non-copyable (use Clone() for intentional sharing)
205 SHAPE_INDEX( const SHAPE_INDEX& ) = delete;
206 SHAPE_INDEX& operator=( const SHAPE_INDEX& ) = delete;
207
213 {
214 SHAPE_INDEX clone( m_shapeLayer );
215 clone.m_tree = m_tree.Clone();
216 return clone;
217 }
218
224 void Add( T aShape )
225 {
226 BOX2I box = boundingBox( aShape, m_shapeLayer );
227 int min[2] = { box.GetX(), box.GetY() };
228 int max[2] = { box.GetRight(), box.GetBottom() };
229
230 m_tree.Insert( min, max, aShape );
231 }
232
239 void Add( T aShape, const BOX2I& aBbox )
240 {
241 int min[2] = { aBbox.GetX(), aBbox.GetY() };
242 int max[2] = { aBbox.GetRight(), aBbox.GetBottom() };
243
244 m_tree.Insert( min, max, aShape );
245 }
246
252 void Remove( T aShape )
253 {
254 BOX2I box = boundingBox( aShape, m_shapeLayer );
255 int min[2] = { box.GetX(), box.GetY() };
256 int max[2] = { box.GetRight(), box.GetBottom() };
257
258 m_tree.Remove( min, max, aShape );
259 }
260
265 {
266 m_tree.RemoveAll();
267 }
268
274 template <class V>
275 void Accept( V aVisitor )
276 {
277 for( const T& item : m_tree )
278 acceptVisitor( item, aVisitor );
279 }
280
285 void BulkLoad( std::vector<std::pair<T, BOX2I>>& aItems )
286 {
287 using BULK_ENTRY = typename TREE_TYPE::BULK_ENTRY;
288 std::vector<BULK_ENTRY> entries;
289 entries.reserve( aItems.size() );
290
291 for( const auto& [item, box] : aItems )
292 {
293 BULK_ENTRY e;
294 e.min[0] = box.GetX();
295 e.min[1] = box.GetY();
296 e.max[0] = box.GetRight();
297 e.max[1] = box.GetBottom();
298 e.data = item;
299 entries.push_back( e );
300 }
301
302 m_tree.BulkLoad( entries );
303 }
304
310 void Reindex()
311 {
312 std::vector<T> items;
313 items.reserve( m_tree.size() );
314
315 for( const T& item : m_tree )
316 items.push_back( item );
317
318 m_tree.RemoveAll();
319
320 for( T& item : items )
321 Add( item );
322 }
323
331 template <class V>
332 int Query( const SHAPE *aShape, int aMinDistance, V& aVisitor) const
333 {
334 BOX2I box = aShape->BBox();
335 box.Inflate( aMinDistance );
336
337 int min[2] = { box.GetX(), box.GetY() };
338 int max[2] = { box.GetRight(), box.GetBottom() };
339
340 return m_tree.Search( min, max, aVisitor );
341 }
342
348 Iterator Begin() const
349 {
350 return Iterator( m_tree );
351 }
352
353 // Range-for support
354 typename TREE_TYPE::Iterator begin() const { return m_tree.begin(); }
355 typename TREE_TYPE::Iterator end() const { return m_tree.end(); }
356
357 size_t Size() const { return m_tree.size(); }
358
359 private:
362};
363
364#endif /* __SHAPE_INDEX_H */
BOX2< VECTOR2I > BOX2I
Definition box2.h:914
constexpr BOX2< Vec > & Inflate(coord_type dx, coord_type dy)
Inflates the rectangle horizontally by dx and vertically by dy.
Definition box2.h:553
constexpr coord_type GetY() const
Definition box2.h:205
constexpr coord_type GetX() const
Definition box2.h:204
constexpr coord_type GetRight() const
Definition box2.h:214
constexpr coord_type GetBottom() const
Definition box2.h:219
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: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().
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:44
void acceptVisitor(T aObject, V aVisitor)
Used by SHAPE_INDEX to implement Accept().
Definition shape_index.h:82
BOX2I boundingBox(T aObject, int aLayer)
Used by SHAPE_INDEX to get the bounding box of a generic T object.
Definition shape_index.h:61