KiCad PCB EDA Suite
Loading...
Searching...
No Matches
sch_rtree.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 The KiCad Developers, see AUTHORS.txt for contributors.
5 * Copyright (C) 2020 CERN
6 *
7 * This program is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU General Public License
9 * as published by the Free Software Foundation; either version 3
10 * of the License, or (at your option) any later version.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program. If not, see <https://www.gnu.org/licenses/>.
19 */
20
21#ifndef EESCHEMA_SCH_RTREE_H_
22#define EESCHEMA_SCH_RTREE_H_
23
24#include <core/typeinfo.h>
25#include <sch_item.h>
26
28
29#include <utility>
30#include <unordered_set>
31
37{
38private:
40
41public:
42 EE_RTREE() = default;
43 EE_RTREE( const EE_RTREE& ) = delete;
44 EE_RTREE& operator=( const EE_RTREE& ) = delete;
45
46 EE_RTREE( EE_RTREE&& aOther ) noexcept :
47 m_tree( std::move( aOther.m_tree ) ),
48 m_members( std::move( aOther.m_members ) )
49 {
50 aOther.m_members.clear();
51 }
52
53 EE_RTREE& operator=( EE_RTREE&& aOther ) noexcept
54 {
55 if( this != &aOther )
56 {
57 m_tree = std::move( aOther.m_tree );
58 m_members = std::move( aOther.m_members );
59 aOther.m_members.clear();
60 }
61
62 return *this;
63 }
64
65 ~EE_RTREE() = default;
66
70 void insert( SCH_ITEM* aItem )
71 {
72 BOX2I bbox = aItem->GetBoundingBox();
73
74 // Inflate a bit for safety, selection shadows, etc.
75 bbox.Inflate( aItem->GetPenWidth() );
76
77 const int type = int( aItem->Type() );
78 const int mmin[3] = { type, bbox.GetX(), bbox.GetY() };
79 const int mmax[3] = { type, bbox.GetRight(), bbox.GetBottom() };
80
81 const auto member = m_members.insert( aItem );
82
83 try
84 {
85 m_tree.Insert( mmin, mmax, aItem );
86 }
87 catch( ... )
88 {
89 m_members.erase( member );
90 throw;
91 }
92 }
93
99 bool remove( SCH_ITEM* aItem )
100 {
101 BOX2I bbox = aItem->GetBoundingBox();
102
103 // Inflate a bit for safety, selection shadows, etc.
104 bbox.Inflate( aItem->GetPenWidth() );
105
106 const int type = int( aItem->Type() );
107 const int mmin[3] = { type, bbox.GetX(), bbox.GetY() };
108 const int mmax[3] = { type, bbox.GetRight(), bbox.GetBottom() };
109
110 // DYNAMIC_RTREE::Remove tries the provided bbox first, then falls back
111 // to full-tree search if the item has moved since insertion.
112 if( !m_tree.Remove( mmin, mmax, aItem ) )
113 return false;
114
115 const auto member = m_members.find( aItem );
116 wxASSERT( member != m_members.end() );
117 m_members.erase( member );
118 return true;
119 }
120
124 void clear()
125 {
126 m_tree.RemoveAll();
127 m_members.clear();
128 }
129
140 bool contains( const SCH_ITEM* aItem, bool aRobust = false ) const
141 {
142 if( aRobust )
143 return m_members.contains( aItem );
144
145 BOX2I bbox = aItem->GetBoundingBox();
146
147 // Inflate a bit for safety, selection shadows, etc.
148 bbox.Inflate( aItem->GetPenWidth() );
149
150 const int type = int( aItem->Type() );
151 const int mmin[3] = { type, bbox.GetX(), bbox.GetY() };
152 const int mmax[3] = { type, bbox.GetRight(), bbox.GetBottom() };
153 bool found = false;
154
155 auto search =
156 [&found, &aItem]( const SCH_ITEM* aSearchItem )
157 {
158 if( aSearchItem == aItem )
159 {
160 found = true;
161 return false;
162 }
163
164 return true;
165 };
166
167 m_tree.Search( mmin, mmax, search );
168
169 return found;
170 }
171
177 size_t size() const
178 {
179 return m_members.size();
180 }
181
182 bool empty() const
183 {
184 return m_members.empty();
185 }
186
197 struct EE_TYPE
198 {
199 using SearchIter = typename ee_rtree::SearchIterator;
200
201 EE_TYPE( const ee_rtree& aTree, KICAD_T aType )
202 {
203 KICAD_T type = BaseType( aType );
204
205 if( type == SCH_LOCATE_ANY_T )
206 {
207 m_min[0] = INT_MIN; m_min[1] = INT_MIN; m_min[2] = INT_MIN;
208 m_max[0] = INT_MAX; m_max[1] = INT_MAX; m_max[2] = INT_MAX;
209 }
210 else
211 {
212 m_min[0] = type; m_min[1] = INT_MIN; m_min[2] = INT_MIN;
213 m_max[0] = type; m_max[1] = INT_MAX; m_max[2] = INT_MAX;
214 }
215
216 m_range = aTree.Overlapping( m_min, m_max );
217 }
218
219 EE_TYPE( const ee_rtree& aTree, KICAD_T aType, const BOX2I& aRect )
220 {
221 KICAD_T type = BaseType( aType );
222
223 if( type == SCH_LOCATE_ANY_T )
224 {
225 m_min[0] = INT_MIN; m_min[1] = aRect.GetX(); m_min[2] = aRect.GetY();
226 m_max[0] = INT_MAX; m_max[1] = aRect.GetRight(); m_max[2] = aRect.GetBottom();
227 }
228 else
229 {
230 m_min[0] = type; m_min[1] = aRect.GetX(); m_min[2] = aRect.GetY();
231 m_max[0] = type; m_max[1] = aRect.GetRight(); m_max[2] = aRect.GetBottom();
232 }
233
234 m_range = aTree.Overlapping( m_min, m_max );
235 }
236
237 SearchIter begin() { return m_range.begin(); }
238 SearchIter end() { return m_range.end(); }
239
240 bool empty() { return m_range.empty(); }
241
242 private:
243 int m_min[3] = {};
244 int m_max[3] = {};
245 typename ee_rtree::SearchRange m_range{ nullptr, m_min, m_max };
246 };
247
248 EE_TYPE OfType( KICAD_T aType ) const
249 {
250 return EE_TYPE( m_tree, aType );
251 }
252
253 EE_TYPE Overlapping( const BOX2I& aRect ) const
254 {
255 return EE_TYPE( m_tree, SCH_LOCATE_ANY_T, aRect );
256 }
257
258 EE_TYPE Overlapping( const VECTOR2I& aPoint, int aAccuracy = 0 ) const
259 {
260 BOX2I rect( aPoint, VECTOR2I( 0, 0 ) );
261 rect.Inflate( aAccuracy );
262 return EE_TYPE( m_tree, SCH_LOCATE_ANY_T, rect );
263 }
264
265 EE_TYPE Overlapping( KICAD_T aType, const VECTOR2I& aPoint, int aAccuracy = 0 ) const
266 {
267 BOX2I rect( aPoint, VECTOR2I( 0, 0 ) );
268 rect.Inflate( aAccuracy );
269 return EE_TYPE( m_tree, aType, rect );
270 }
271
272 EE_TYPE Overlapping( KICAD_T aType, const BOX2I& aRect ) const
273 {
274 return EE_TYPE( m_tree, aType, aRect );
275 }
276
288 typename ee_rtree::Iterator begin() const
289 {
290 return m_tree.begin();
291 }
292
296 typename ee_rtree::Iterator end() const
297 {
298 return m_tree.end();
299 }
300
301
302private:
304 std::unordered_multiset<const SCH_ITEM*> m_members;
305};
306
307
308#endif /* EESCHEMA_SCH_RTREE_H_ */
BOX2< VECTOR2I > BOX2I
Definition box2.h:927
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
virtual const BOX2I GetBoundingBox() const
Return the orthogonal bounding box of this object for display purposes.
Definition eda_item.cpp:270
KICAD_T Type() const
Returns the type of object.
Definition eda_item.h:110
EE_RTREE(EE_RTREE &&aOther) noexcept
Definition sch_rtree.h:46
~EE_RTREE()=default
EE_RTREE & operator=(const EE_RTREE &)=delete
bool empty() const
Definition sch_rtree.h:182
EE_TYPE Overlapping(KICAD_T aType, const BOX2I &aRect) const
Definition sch_rtree.h:272
size_t size() const
Return the number of items in the tree.
Definition sch_rtree.h:177
EE_TYPE Overlapping(const BOX2I &aRect) const
Definition sch_rtree.h:253
EE_RTREE(const EE_RTREE &)=delete
ee_rtree m_tree
Definition sch_rtree.h:303
bool remove(SCH_ITEM *aItem)
Remove an item from the tree.
Definition sch_rtree.h:99
ee_rtree::Iterator begin() const
Return a read/write iterator that points to the first.
Definition sch_rtree.h:288
std::unordered_multiset< const SCH_ITEM * > m_members
Definition sch_rtree.h:304
void insert(SCH_ITEM *aItem)
Insert an item into the tree.
Definition sch_rtree.h:70
bool contains(const SCH_ITEM *aItem, bool aRobust=false) const
Determine if a given item exists in the tree.
Definition sch_rtree.h:140
EE_RTREE()=default
KIRTREE::DYNAMIC_RTREE< SCH_ITEM *, int, 3 > ee_rtree
Definition sch_rtree.h:39
EE_TYPE Overlapping(const VECTOR2I &aPoint, int aAccuracy=0) const
Definition sch_rtree.h:258
ee_rtree::Iterator end() const
Return a read/write iterator that points to one past the last element in the EE_RTREE.
Definition sch_rtree.h:296
EE_RTREE & operator=(EE_RTREE &&aOther) noexcept
Definition sch_rtree.h:53
EE_TYPE Overlapping(KICAD_T aType, const VECTOR2I &aPoint, int aAccuracy=0) const
Definition sch_rtree.h:265
EE_TYPE OfType(KICAD_T aType) const
Definition sch_rtree.h:248
void clear()
Remove all items from the RTree.
Definition sch_rtree.h:124
Dynamic R*-tree with SoA node layout and stored insertion bounding boxes.
SearchRange Overlapping(const ELEMTYPE aMin[NUMDIMS], const ELEMTYPE aMax[NUMDIMS]) const
Return a lazy range of items overlapping the query rectangle.
Base class for any item which can be embedded within the SCHEMATIC container class,...
Definition sch_item.h:165
virtual int GetPenWidth() const
Definition sch_item.h:358
The EE_TYPE struct provides a type-specific auto-range iterator to the RTree.
Definition sch_rtree.h:198
ee_rtree::SearchRange m_range
Definition sch_rtree.h:245
EE_TYPE(const ee_rtree &aTree, KICAD_T aType, const BOX2I &aRect)
Definition sch_rtree.h:219
typename ee_rtree::SearchIterator SearchIter
Definition sch_rtree.h:199
SearchIter begin()
Definition sch_rtree.h:237
EE_TYPE(const ee_rtree &aTree, KICAD_T aType)
Definition sch_rtree.h:201
SearchIter end()
Definition sch_rtree.h:238
constexpr KICAD_T BaseType(const KICAD_T aType)
Return the underlying type of the given type.
Definition typeinfo.h:259
KICAD_T
The set of class identification values stored in EDA_ITEM::m_structType.
Definition typeinfo.h:70
@ SCH_LOCATE_ANY_T
Definition typeinfo.h:195
VECTOR2< int32_t > VECTOR2I
Definition vector2d.h:683