VR-Forces 4.3 Class Documentation
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
indexingFeatureSet.h
Go to the documentation of this file.
1 /******************************************************************************
2  * Copyright (c) 2015 MAK Technologies, Inc.
3  * All rights reserved.
4  ******************************************************************************/
5 
9 
10 #pragma once
11 
13 #include <features/featureSet.h>
16 #include <features/tileFeature.h>
17 
19 
20 #include <tbb/atomic.h>
21 
22 namespace MAKVRinTerra
23 {
24  template <typename FS, typename S = typename FS::Sink>
26  : public FS
27  , public boost::enable_shared_from_this<DtIndexingFeatureSet<FS,S> >
28  {
29  public:
30  typedef boost::shared_ptr<DtIndexingFeatureSet> Ptr;
31  typedef boost::shared_ptr<const DtIndexingFeatureSet> CPtr;
32  typedef boost::weak_ptr<DtIndexingFeatureSet> WPtr;
33 
34  typedef typename FS::Feature Feature;
35  typedef typename FS::ForEachFunction ForEachFunction;
36  typedef typename FS::LoadedCallback LoadedCallback;
37  typedef typename FS::DetachCallback DetachCallback;
38 
39  typedef S Sink;
40  typedef typename Sink::Ptr SinkPtr;
41 
44  {
45  public:
46  typedef boost::shared_ptr<Config> Ptr;
47 
48  explicit Config(FS* input)
49  : inputSink(Sink::Make(input))
50  {
51  }
52 
53  explicit Config(const SinkPtr& input)
54  : inputSink(input ? input : Sink::Make(0))
55  {
56  }
57 
58  explicit Config(const Config& cfg)
60  , inputSink(cfg.inputSink)
61  {
62  static_cast<DtTerrainInterfaceConfig&>(*this) = cfg;
63  }
64 
65  void addTile(const DtFeature& feature)
66  {
67  if (tileFeatures)
68  tileFeatures->addFeature(feature);
69  }
70 
71  boost::shared_ptr<DtFeatureSet::Source> tileFeatures;
72 
74  };
75 
76  static FS* Make(const Config& cfg, const DtProj::Bounds& bounds)
77  {
78  return Make(new Config(cfg), bounds);
79  }
80 
81  static FS* Make(Config* cfg, const DtProj::Bounds& bounds)
82  {
83  return Make(boost::shared_ptr<Config>(cfg), bounds);
84  }
85 
86  static FS* Make(const boost::shared_ptr<Config>& cfg, const DtProj::Bounds& bounds)
87  {
88  Ptr set(new DtIndexingFeatureSet(typename Config::Ptr(cfg), bounds));
89  set->init();
90 
91  return FS::Wrap(set);
92  }
93 
95  {
97  }
98 
99  FS* clone() const
100  {
101  return FS::Wrap(this->shared_from_this());
102  }
103 
104  std::string label() const
105  {
106  return myConfig->inputSink->label() + " index level "
107  + boost::lexical_cast<std::string>(myLevel);
108  }
109 
110  bool loaded(double timeout) const
111  {
112  return myFeatures->loaded(timeout);
113  }
114 
116  {
117  return myFeatures->addLoadedCallback(cb);
118  }
119 
120  unsigned numberOfFeatures() const
121  {
122  return myFeatures->numberOfFeatures();
123  }
124 
125  bool empty() const
126  {
127  return myFeatures->empty();
128  }
129 
130  FS* filter(
131  const DtQuery& query,
132  const boost::optional<DtFeatureGeometry>& geometry,
133  DtLoadType load) const
134  {
136  if (!geometry)
137  return myFeatures->filter(query, boost::none_t(), load);
138 
140  if (myState != ACTIVE)
141  return myFeatures->filter(query, geometry, load);
142 
143  bool covers[4] = { false, false, false, false };
144  bool intersections[4] = { false, false, false, false };
145  size_t lastIntersection = 0;
146 
147  unsigned numIntersects = 0;
148  bool done = false;
149 
152  for (unsigned i=0; !done && i != 4; ++i)
153  {
154  std::auto_ptr<DtFeatureGeometry::RelationshipMatrix> matrix
155  = geometry->relate(getSubtile(i).geometry());
156 
157  if (!matrix->intersects())
158  continue;
159 
160  switch (geometry->type())
161  {
164  done = true;
165  intersections[i] = true;
166  ++numIntersects;
167  lastIntersection = i;
168  break;
169 
171  intersections[i] = true;
172  ++numIntersects;
173  lastIntersection = i;
174 
176  if (matrix->coveredBy())
177  done = true;
178 
179  break;
180 
181  default:
183  if (matrix->touches())
184  continue;
185 
186  intersections[i] = true;
187  ++numIntersects;
188  lastIntersection = i;
189 
191  if (matrix->covers())
192  covers[i] = true;
193 
195  if (matrix->coveredBy())
196  done = true;
197 
198  break;
199  }
200  }
201 
204  switch (numIntersects)
205  {
206  case 0: return 0;
207  case 1: return getSubtile(lastIntersection).indexedFeatures().filter(
208  query,
209  !covers[lastIntersection] ? geometry : boost::none_t(),
210  load);
211  }
212 
214  std::auto_ptr< DtFeatureSetList<FS> > list(new DtFeatureSetList<FS>(4));
215  for (size_t i=0; i != 4; ++i)
216  {
217  if (!intersections[i])
218  continue;
219 
220  list->add(getSubtile(i).indexedFeatures().filter(
221  query,
222  !covers[i] ? geometry : boost::none_t(),
223  load));
224  }
225 
226  return list.release();
227  }
228 
229  void forEachFeatureParallel(const ForEachFunction& func) const
230  {
231  myFeatures->forEachFeatureParallel(func);
232  }
233 
235  {
236  return myFeatures->forEachFeatureAsync(func);
237  }
238 
239  protected:
240  class Subtile;
241 
242  DtIndexingFeatureSet(const Ptr& parent, const Subtile& subtile)
243  : myConfig(parent->myConfig)
244  , myLevel(parent->myLevel + 1)
245  , myParent(parent)
246  , myTileGeometry(subtile.geometry())
247  , myFeatures(subtile.sink())
248  , mySubtile0(*myFeatures, subtile.bounds(), 0)
249  , mySubtile1(*myFeatures, subtile.bounds(), 1)
250  , mySubtile2(*myFeatures, subtile.bounds(), 2)
251  , mySubtile3(*myFeatures, subtile.bounds(), 3)
252  , myTileFeature(myTileGeometry.boundary(), 0xAA00FF, 1)
253  {
254  myState = START;
255  myConfig->addTile(myTileFeature);
256  }
257 
259  const boost::shared_ptr<Config>& cfg,
260  const DtProj::Bounds& bounds)
261  : myConfig(cfg)
262  , myLevel(0)
263  , myTileGeometry(DtFeatureGeometry::MakeBox(bounds))
264  , myFeatures(cfg->inputSink)
265  , mySubtile0(*myFeatures, bounds, 0)
266  , mySubtile1(*myFeatures, bounds, 1)
267  , mySubtile2(*myFeatures, bounds, 2)
268  , mySubtile3(*myFeatures, bounds, 3)
269  , myTileFeature(myTileGeometry.boundary(), 0xAA00FF, 1)
270  {
271  myState = START;
272  }
273 
274  const Subtile& getSubtile(unsigned i) const
275  {
276  switch (i)
277  {
278  case 0: return mySubtile0;
279  case 1: return mySubtile1;
280  case 2: return mySubtile2;
281  case 3: return mySubtile3;
282  }
283 
284  assert(false);
285  DtTHROW_NEW(DtException, "Tile index out of bounds");
286  }
287 
289  void init()
290  {
291  Ptr This(this->shared_from_this());
292 
293  mySubtile0.init(This);
294  mySubtile1.init(This);
295  mySubtile2.init(This);
296  mySubtile3.init(This);
297  }
298 
301  {
304  if (myState.compare_and_swap(ACTIVATING, START) != START)
305  return false;
306 
307  try
308  {
309  Ptr This(this->shared_from_this());
310  mySubtile0.activate(This);
311  mySubtile1.activate(This);
312  mySubtile2.activate(This);
313  mySubtile3.activate(This);
314  }
315  catch (...)
316  {
317  myState = FAULT;
318  throw;
319  }
320 
321  if (myState.compare_and_swap(ACTIVE, ACTIVATING) != ACTIVATING)
322  {
323  DtWarn << "Error activating subtile" << std::endl;
324  myState = FAULT;
325  return false;
326  }
327 
328  return true;
329  }
330 
332  const boost::shared_ptr<Config> myConfig;
333 
335  const int myLevel;
336 
338  const WPtr myParent;
339 
342 
345 
347  class Subtile
348  {
352  boost::shared_ptr<DtIndexingFeatureSet> myIndexingSet;
353 
354  public:
355  const DtFeatureGeometry& geometry() const { return myGeometry; }
356  const DtProj::Bounds& bounds() const { return myBounds; }
357  const SinkPtr& sink() const { return mySink; }
358  const FS& indexedFeatures() const { return *myIndexingSet; }
359 
360  Subtile(const Sink& parentFeatures, const DtProj::Bounds& pbounds, unsigned i)
361  : myBounds(pbounds.makeSubBounds(i,2,2))
362  , myGeometry(DtFeatureGeometry::MakeBox(bounds()))
363  , mySink(Sink::Make(parentFeatures, geometry()))
364  {
365  }
366 
367  void init(const Ptr& parent)
368  {
369  Caller caller(parent, *this);
370  mySink->addLoadedCallback(caller);
371 
372  checkIndex(*parent);
373  }
374 
375  void activate(const Ptr& parent)
376  {
377  myIndexingSet.reset(new DtIndexingFeatureSet(parent, *this));
378  myIndexingSet->init();
379  }
380 
381  private:
383  {
384  try
385  {
386  if (!mySink->loaded())
387  return;
388  }
390  {
391  return;
392  }
393 
394  if (parent.myLevel >= parent.myConfig->featuresMaxIndexLOD)
395  return;
396 
397  size_t pc = parent.numberOfFeatures();
398  size_t c = mySink->numberOfFeatures();
399 
400  assert(pc >= c);
401 
403  if (pc <= parent.myConfig->minFeaturesToIndexTile)
404  return;
405 
406  if (c > 0)
407  {
408  if (pc/(double)c >= parent.myConfig->featuresIndexRatio)
409  parent.activateSubtiles();
410  }
411  else
412  {
414  //if (pc > 0)
416  }
417  }
418 
419  class Caller
420  {
421  public:
422  explicit Caller(const Ptr& set, Subtile& subtile)
423  : set(set), subtile(subtile)
424  {
425  }
426 
427  void operator()() const
428  {
429  Ptr p(set.lock());
430  if (p)
431  subtile.checkIndex(*p);
432  }
433 
434  private:
435  WPtr set;
437  };
438  };
439 
440  friend class Subtile;
441 
446 
447  enum State
448  {
450  };
451 
452  tbb::atomic<State> myState;
453 
455  };
456 }

Document ID: Generated on Wed Mar 11 21:20:57 EDT 2015 from SVN revision 150940
Copyright © 2005-2014 VT MÄK. All Rights Reserved (www.mak.com)