Version: 0.6.0
spatialtree.h
1 /******************************************************************************
2  * Project: wxGIS
3  * Purpose: Various Spatial Tree classes
4  * Author: Dmitry Baryshnikov (aka Bishop), polimax@mail.ru
5  ******************************************************************************
6 * Copyright (C) 2011,2013 Dmitry Baryshnikov
7 *
8 * This program is free software: you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation, either version 2 of the License, or
11 * (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, see <http://www.gnu.org/licenses/>.
20  ****************************************************************************/
21 #pragma once
22 
23 #include "wxgis/datasource/gdalinh.h"
24 
25 #include "wx/thread.h"
26 #include <wx/list.h>
27 
29 
37 class WXDLLIMPEXP_GIS_DS wxGISSpatialTreeData
38 {
39 public:
40  wxGISSpatialTreeData(const wxGISGeometry &Geom = wxNullGeometry, long nFID = wxNOT_FOUND);
41  virtual ~wxGISSpatialTreeData();
42  virtual void SetFID(long nFID);
43  virtual long GetFID(void) const;
44  virtual wxGISGeometry GetGeometry(void) const;
45  virtual void SetGeometry(const wxGISGeometry &oGeom);
46  virtual wxGISSpatialTreeData* Clone() const;
47 protected:
48  wxGISGeometry m_Geom;
49  long m_nFID;
50 };
51 
52 WX_DEFINE_ARRAY_WITH_DECL_PTR(wxGISSpatialTreeData*, wxGISSpatialTreeCursor, class WXDLLIMPEXP_GIS_DS);
53 
54 extern WXDLLIMPEXP_DATA_GIS_DS(wxGISSpatialTreeCursor) wxNullSpatialTreeCursor;
55 
63 class WXDLLIMPEXP_GIS_DS wxGISSpatialTree : public wxThreadHelper
64 {
65 public:
67  virtual ~wxGISSpatialTree(void);
68  virtual bool Load(const wxGISSpatialReference &SpatRef = wxNullSpatialReference, ITrackCancel* const pTrackCancel = NULL);
69  virtual bool IsLoading(void) const;
70  virtual void CancelLoading();
71 
72  virtual void Insert(const wxGISGeometry &Geom, long nFID);
73  virtual void Remove(long nFID) = 0;
74  virtual void RemoveAll(void) = 0;
75  virtual void Change(const wxGISGeometry &Geom, long nFID);
76  virtual wxGISSpatialTreeCursor Search(const OGREnvelope& env) = 0;
77  virtual void Insert(wxGISSpatialTreeData* pData) = 0;
78  virtual bool HasFID(long nFID) const = 0;
79 protected:
80  virtual wxThread::ExitCode Entry();
81  bool CreateAndRunLoadGeometryThread(void);
82  void DestroyLoadGeometryThread(void);
83 protected:
84  wxGISFeatureDataset* m_pDSet;
85  long m_nReadPos;
86  short m_nPreloadItemCount;
87 protected:
88  bool m_bIsLoaded;
89  wxCriticalSection m_CritSect;
90  wxGISSpatialReference m_SpatialReference;
91  ITrackCancel* m_pTrackCancel;
92 };
93 
100 WXDLLIMPEXP_GIS_DS wxGISSpatialTree* CreateSpatialTree(wxGISFeatureDataset *pDS);
101 
102 // R* tree parameters
103 
104 #define RTREE_REINSERT_P 0.30
105 #define RTREE_CHOOSE_SUBTREE_P 32
106 
115 {
116  friend class wxGISRTree;
117 
118  enum enumChooseSubteeType{
119  PARTIAL_SORT = 1,
120  SORT_ENV = 2,
121  SORT_AREA = 3
122  };
123 public:
124  wxGISRTreeNode(unsigned short nMinChildItems = 32, unsigned short nMaxChildItems = 64, wxGISSpatialTreeData *pData = NULL);
125  ~wxGISRTreeNode();
126 
127  wxGISSpatialTreeData* GetData() const;
128 
129  typedef struct _split_dir{
130  int split_margin;
131  size_t split_edge;
132  size_t split_index;
133  } SPLIT_DIR;
134 protected:
135  void Search(wxGISSpatialTreeCursor &Cursor, const OGREnvelope& env);
136  void GetAll(wxGISSpatialTreeCursor &Cursor);
137  bool Remove(long nFID);
138  bool HasFID(long nFID) const;
139  double GetArea() const;
140  void StretchBounds(const OGREnvelope &Env);
141  wxGISRTreeNode* ChooseSubtree(const OGREnvelope &Env, enumChooseSubteeType eType);
142  OGREnvelope GetBounds() const;
143  size_t GetCount() const;
144  bool GetHasLeaves() const;
145  void SetHasLeaves(bool bHasLeaves);
146  wxGISRTreeNode* GetNode(size_t nIndex);
147  void PutNode(wxGISRTreeNode* pNode);
148  void UpdateBounds(void);
149  wxGISRTreeNode* Split();
150  SPLIT_DIR GetSplitDirection(const bool bIsX, size_t nDistributionCount);
151  void RemoveFarestItems(size_t p, wxVector<wxGISRTreeNode*> &removed_items);
152  void Delete();
153 protected:
154  struct SortBoundedItemsByAreaEnlargement : public std::binary_function< const wxGISRTreeNode * const, const wxGISRTreeNode * const, bool >
155  {
156  double m_dfArea;
157  explicit SortBoundedItemsByAreaEnlargement(const OGREnvelope &Env)
158  {
159  m_dfArea = fabs((Env.MaxX - Env.MinX) * (Env.MaxY - Env.MinY));
160  }
161 
162  bool operator() (const wxGISRTreeNode * const n1, const wxGISRTreeNode * const n2) const
163  {
164  return m_dfArea - n1->GetArea() < m_dfArea - n2->GetArea();
165  }
166  };
167 
168  struct SortBoundedItemsByOverlapEnlargement : public std::binary_function< const wxGISRTreeNode * const, const wxGISRTreeNode * const, bool >
169  {
170  const OGREnvelope m_Env;
171  explicit SortBoundedItemsByOverlapEnlargement(const OGREnvelope &Env) : m_Env(Env) {}
172 
173  bool operator() (const wxGISRTreeNode * const n1, const wxGISRTreeNode * const n2) const
174  {
175  OGREnvelope IntersectEnv = n1->GetBounds();
176  IntersectEnv.Intersect(m_Env);
177  double dfArea1 = fabs((IntersectEnv.MaxX - IntersectEnv.MinX) * (IntersectEnv.MaxY - IntersectEnv.MinY));
178  IntersectEnv = n2->GetBounds();
179  IntersectEnv.Intersect(m_Env);
180  double dfArea2 = fabs((IntersectEnv.MaxX - IntersectEnv.MinX) * (IntersectEnv.MaxY - IntersectEnv.MinY));
181 
182  return dfArea1 < dfArea2;
183  }
184  };
185 
186  struct SortBoundedItemsByDistanceFromCenter : public std::binary_function< const wxGISRTreeNode * const, const wxGISRTreeNode * const, bool >
187  {
188  double dfX, dfY;
189  explicit SortBoundedItemsByDistanceFromCenter(const OGREnvelope &Env)
190  {
191  dfX = (Env.MaxX - Env.MinX) / 2;
192  dfY = (Env.MaxY - Env.MinY) / 2;
193  }
194 
195  bool operator() (const wxGISRTreeNode * const n1, const wxGISRTreeNode * const n2) const
196  {
197  OGREnvelope OtherEnv = n1->GetBounds();
198  double dfXO, dfYO;
199  dfXO = (OtherEnv.MaxX - OtherEnv.MinX) / 2;
200  dfYO = (OtherEnv.MaxY - OtherEnv.MinY) / 2;
201  double dfDist1 = /*std::sqrt*/((dfX - dfXO) * (dfX - dfXO) + (dfY - dfYO) * (dfY - dfYO));
202 
203  OtherEnv = n2->GetBounds();
204  dfXO = (OtherEnv.MaxX - OtherEnv.MinX) / 2;
205  dfYO = (OtherEnv.MaxY - OtherEnv.MinY) / 2;
206  double dfDist2 = /*std::sqrt*/((dfX - dfXO) * (dfX - dfXO) + (dfY - dfYO) * (dfY - dfYO));
207 
208  return dfDist1 < dfDist2;
209  }
210  };
211 
212  struct SortBoundedItemsByEdge : public std::binary_function< const wxGISRTreeNode * const, const wxGISRTreeNode * const, bool >
213  {
214  const bool m_bIsX;
215  const bool m_bIsMin;
216  explicit SortBoundedItemsByEdge (const bool bIsX, const bool bIsMin) : m_bIsX(bIsX), m_bIsMin(bIsMin) {}
217 
218  bool operator() (const wxGISRTreeNode * const n1, const wxGISRTreeNode * const n2) const
219  {
220  OGREnvelope Env1 = n1->GetBounds();
221  OGREnvelope Env2 = n2->GetBounds();
222  if(m_bIsX)
223  {
224  if(m_bIsMin)
225  {
226  return Env1.MinX < Env2.MinX;
227  }
228  else //Max
229  {
230  return Env1.MaxX < Env2.MaxX;
231  }
232  }
233  else // Y
234  {
235  if(m_bIsMin)
236  {
237  return Env1.MinY < Env2.MinY;
238  }
239  else //Max
240  {
241  return Env1.MaxY < Env2.MaxY;
242  }
243  }
244  }
245  };
246 
247 protected:
248  unsigned short m_nMinChildItems, m_nMaxChildItems;
249  OGREnvelope m_Env;
250  double m_dfArea;
251  wxVector<wxGISRTreeNode*> m_paNodes;
252  wxGISSpatialTreeData* m_pData;
253  bool m_bHasLeaves;
254 };
255 
263 class WXDLLIMPEXP_GIS_DS wxGISRTree : public wxGISSpatialTree
264 {
265 public:
266  wxGISRTree(wxGISFeatureDataset* pDSet, unsigned short nMaxChildItems = 64, unsigned short nMinChildItems = 32);
267  virtual ~wxGISRTree(void);
268  virtual void Remove(long nFID);
269  virtual void RemoveAll(void);
270  virtual wxGISSpatialTreeCursor Search(const OGREnvelope& env);
271  virtual void Insert( wxGISSpatialTreeData* pData);
272  virtual bool HasFID(long nFID) const;
273 protected:
274  virtual wxGISRTreeNode* ChooseSubtree(wxGISRTreeNode* pNode, const OGREnvelope &Env);
275  virtual wxGISRTreeNode* InsertInternal(wxGISRTreeNode* pInsertNode, wxGISRTreeNode * pStartNode, bool bIsFirstInsert = true);
276  virtual wxGISRTreeNode* OverflowTreatment(wxGISRTreeNode* pNode, bool bIsFirstInsert);
277  virtual void Reinsert(wxGISRTreeNode* pNode);
278  virtual wxGISRTreeNode* Split(wxGISRTreeNode* pNode);
279 protected:
280  wxGISRTreeNode* m_pRoot;
281  unsigned short m_nMaxChildItems;
282  unsigned short m_nMinChildItems;
283 };
284 
285 #include "cpl_quad_tree.h"
286 
287 void GetGeometryBoundsFunc(const void* hFeature, CPLRectObj* pBounds);
288 
289 
297 class WXDLLIMPEXP_GIS_DS wxGISQuadTree : public wxGISSpatialTree
298 {
299 public:
301  virtual ~wxGISQuadTree(void);
302  virtual void Remove(long nFID);
303  virtual void RemoveAll(void);
304  virtual wxGISSpatialTreeCursor Search(const OGREnvelope& Env);
305  virtual void Insert(wxGISSpatialTreeData* pData);
306  virtual bool HasFID(long nFID) const;
307 protected:
308  void CreateQuadTree();
309  void DestroyQuadTree();
310 protected:
311  CPLQuadTree* m_pQuadTree;
312  wxGISSpatialTreeCursor m_Cursor;
313  OGREnvelope m_Envelope;
314 };
Definition: gdalinh.h:333
A TrackCancel interface class.
Definition: core.h:144
Definition: spatialtree.h:129
Definition: spatialtree.h:63
Definition: spatialtree.h:114
Definition: gdalinh.h:57
Definition: spatialtree.h:297
Definition: spatialtree.h:263
Definition: featuredataset.h:32
Definition: spatialtree.h:212
Definition: spatialtree.h:37