VR-Forces Developer's Guide
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Groups Pages
attributeIndexingFeatureSet.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/feature.h>
14 #include <features/featureSet.h>
17 #include <features/tileFeature.h>
18 
20 
21 #include <tbb/atomic.h>
22 
23 #include <boost/optional.hpp>
24 #include <boost/shared_ptr.hpp>
25 
26 namespace MAKVRinTerra
27 {
28  template <typename FS, typename S = typename FS::Sink>
30  : public FS
31  , public boost::enable_shared_from_this<DtAttributeIndexingFeatureSet<FS,S> >
32  {
33  protected:
34  class Subtile;
35 
36  public:
37  typedef boost::shared_ptr<DtAttributeIndexingFeatureSet> Ptr;
38  typedef boost::shared_ptr<const DtAttributeIndexingFeatureSet> CPtr;
39  typedef boost::weak_ptr<DtAttributeIndexingFeatureSet> WPtr;
40 
41  typedef typename FS::Feature Feature;
42  typedef typename FS::ForEachFunction ForEachFunction;
43  typedef typename FS::LoadedCallback LoadedCallback;
44  typedef typename FS::DetachCallback DetachCallback;
45 
46  typedef S Sink;
47  typedef typename Sink::Ptr SinkPtr;
48 
49  typedef std::string Bound;
50 
53  {
54  public:
55  typedef boost::shared_ptr<Config> Ptr;
56 
57  explicit Config(FS* input, const DtFeature::Key& key)
58  : inputSink(Sink::Make(input)), indexKey(key) { }
59  explicit Config(const SinkPtr& input, const DtFeature::Key& key)
60  : inputSink(input ? input : Sink::Make(0)), indexKey(key) { }
61 
62  explicit Config(const Config& cfg)
63  : inputSink(cfg.inputSink)
64  , indexKey(cfg.indexKey)
65  {
66  static_cast<DtTerrainInterfaceConfig&>(*this) = cfg;
67  }
68 
71  };
72 
73  static FS* Make(Config* cfg, const Bound& lower=Bound(), const Bound& upper=Bound())
74  {
75  return Make(typename Config::Ptr(cfg), lower, upper);
76  }
77 
78  static FS* Make(
79  const typename Config::Ptr& cfg,
80  Bound lower=Bound(), Bound upper=Bound())
81  {
82  if (lower.empty()) lower = " ";
83  if (upper.empty()) upper = "~";
84 
85  Ptr set(new DtAttributeIndexingFeatureSet(cfg, lower, upper));
86  set->init();
87 
88  return FS::Wrap(set);
89  }
90 
91  FS* clone() const
92  {
93  return FS::Wrap(this->shared_from_this());
94  }
95 
96  std::string label() const
97  {
98  return myConfig->inputSink->label() + " index level "
99  + boost::lexical_cast<std::string>(myLevel);
100  }
101 
102  bool loaded(double timeout) const
103  {
104  return myFeatures->loaded(timeout);
105  }
106 
108  {
109  return myFeatures->addLoadedCallback(cb);
110  }
111 
112  unsigned numberOfFeatures() const
113  {
114  return myFeatures->numberOfFeatures();
115  }
116 
117  bool elided() const
118  {
119  return myFeatures->elided();
120  }
121 
122  bool empty() const
123  {
124  return myFeatures->empty();
125  }
126 
127  class QueryVisitor : public DtQuery::Visitor<DtQuery>
128  {
129  public:
130  explicit QueryVisitor(const DtFeature::Key& key, const Subtile& subtile)
131  : attribute(key), subtile(subtile)
132  {
133  }
134 
135  DtQuery visit(const DtQuery& query)
136  {
137  if (const DtHasAttribute* i = query.trycast<DtHasAttribute>())
138  {
140  if (i->key() != attribute)
141  return query;
142 
143  const DtHasAttributeValue* val = query.trycast<DtHasAttributeValue>();
144 
146  if (!val)
147  return query;
148 
150  if (mlower.isFalse())
151  return false;
152 
154  if (mupper.isFalse())
155  return false;
156  }
157 
158  return query;
159  }
160 
161  private:
163  const Subtile& subtile;
164  };
165 
166  FS* filter(
167  const DtQuery& query,
168  const boost::optional<DtFeatureGeometry>& geometry,
169  DtLoadType load) const
170  {
171  if (load == DO_NOT_LOAD)
172  return new typename FS::Filtered(FS::Wrap(this->shared_from_this()), query, geometry);
173 
175  if (query.isTrue())
176  return myFeatures->filter(true, geometry, load);
177 
179  if (myState != ACTIVE)
180  return myFeatures->filter(query, geometry, load);
181 
182  bool covers[2] = { false, false };
183  bool intersections[2] = { false, false };
184  size_t lastIntersection = 0;
185  unsigned numIntersects = 0;
186 
189  for (unsigned i=0 ; i < 2; ++i)
190  {
191  QueryVisitor visitor(myConfig->indexKey, this->getSubtile(i));
192  DtQuery processed = visitor.apply(query);
193  if (processed.isFalse())
194  continue;
195 
196  intersections[i] = true;
197  lastIntersection = i;
198  ++numIntersects;
199 
202  }
203 
206  switch (numIntersects)
207  {
208  case 0: return 0;
209  case 1: return getSubtile(lastIntersection).indexedFeatures().filter(
210  !covers[lastIntersection] ? query : true,
212  geometry,
213  load);
214  }
215 
217  std::auto_ptr< DtFeatureSetList<FS> > list(new DtFeatureSetList<FS>(4));
218  for (size_t i=0; i != 4; ++i)
219  {
220  if (!intersections[i])
221  continue;
222 
223  list->add(getSubtile(i).indexedFeatures().filter(
224  !covers[i] ? query : true,
226  geometry,
227  load));
228  }
229 
230  return list.release();
231  }
232 
233  void forEachFeatureParallel(const ForEachFunction& func) const
234  {
235  myFeatures->forEachFeatureParallel(func);
236  }
237 
239  {
240  return myFeatures->forEachFeatureAsync(func);
241  }
242 
243  protected:
244  DtAttributeIndexingFeatureSet(const Ptr& parent, const Subtile& subtile)
245  : myConfig(parent->myConfig)
246  , myLevel(parent->myLevel + 1)
247  , myParent(parent)
248  , myFeatures(subtile.sink())
249  , mySubtile0(*myFeatures, myConfig->indexKey, subtile.lowerBound(), subtile.upperBound(), 0)
250  , mySubtile1(*myFeatures, myConfig->indexKey, subtile.lowerBound(), subtile.upperBound(), 1)
251  {
252  myState = START;
253  }
254 
256  const boost::shared_ptr<Config>& cfg,
257  const Bound& lower, const Bound& upper)
258  : myConfig(cfg)
259  , myLevel(0)
260  , myFeatures(cfg->inputSink)
261  , mySubtile0(*myFeatures, myConfig->indexKey, lower, upper, 0)
262  , mySubtile1(*myFeatures, myConfig->indexKey, lower, upper, 1)
263  {
264  myState = START;
265  }
266 
267  const Subtile& getSubtile(unsigned i) const
268  {
269  switch (i)
270  {
271  case 0: return mySubtile0;
272  case 1: return mySubtile1;
273  }
274 
275  assert(false);
276  DtTHROW_NEW(DtException, "Tile index out of bounds");
277  }
278 
280  void init()
281  {
282  Ptr This(this->shared_from_this());
283 
284  mySubtile0.init(This);
285  mySubtile1.init(This);
286  }
287 
290  {
293  if (myState.compare_and_swap(ACTIVATING, START) != START)
294  return false;
295 
296  try
297  {
298  Ptr This(this->shared_from_this());
299  mySubtile0.activate(This);
300  mySubtile1.activate(This);
301  }
302  catch (...)
303  {
304  myState = FAULT;
305  throw;
306  }
307 
308  if (myState.compare_and_swap(ACTIVE, ACTIVATING) != ACTIVATING)
309  {
310  DtWarn << "Error activating subtile" << std::endl;
311  myState = FAULT;
312  return false;
313  }
314 
315  return true;
316  }
317 
319  const boost::shared_ptr<Config> myConfig;
320 
322  const int myLevel;
323 
325  const WPtr myParent;
326 
329 
331  class Subtile
332  {
333  static std::string removePrefix(std::string& s1, std::string& s2)
334  {
335  assert(s1 < s2);
336 
337  std::string prefix;
338  while (!s1.empty() && !s2.empty() && s1[0] == s2[0])
339  {
340  prefix.push_back(s1[0]);
341 
342  s1 = s1.substr(1);
343  s2 = s2.substr(1);
344  }
345 
346  assert(s1 < s2);
347  return prefix;
348  }
349 
350  static std::string findMiddle(const std::string& lower, const std::string& upper)
351  {
352  using namespace std;
353 
354  string s1=lower, s2=upper;
355 
356  string prefix = removePrefix(s1, s2);
357  char c1 = s1.empty() ? ' ' : s1[0];
358  char c2 = s2.empty() ? '~' : s2[0];
359 
360  assert(c1 < c2);
361 
362  string ret;
363  if (c1 + 1 == c2)
364  {
365  ret = prefix + c1 + "z";
366  }
367  else
368  {
369  int middle = (c1+c2)/2;
370  ret = prefix + static_cast<char>(middle);
371  }
372 
373  assert(lower <= ret);
374  assert(ret < upper);
375 
376  //DtWarn << "[" << prefix << s1 << "," << prefix << s2 << "] -> " << prefix << std::endl;
377  return ret;
378  }
379 
381  const DtFeature::Key& indexKey, const Bound& bound,
383  {
384  return DtHasAttributeValue::Create(indexKey, bound, comp);
385  }
386 
387  boost::shared_ptr<DtAttributeIndexingFeatureSet> myIndexingSet;
394 
395  public:
396  const DtQuery& query() const { return myQuery; }
397  const DtHasAttributeValue& lowerBoundQuery() const { return *myLowerBoundQuery.trycast<DtHasAttributeValue>(); }
398  const DtHasAttributeValue& upperBoundQuery() const { return *myUpperBoundQuery.trycast<DtHasAttributeValue>(); }
399  const Bound& upperBound() const { return myUpperBound; }
400  const Bound& lowerBound() const { return myLowerBound; }
401  const SinkPtr& sink() const { return mySink; }
402  const FS& indexedFeatures() const { return *myIndexingSet; }
403 
405  const Sink& parentFeatures,
406  const DtFeature::Key& indexKey,
407  const Bound& plower, const Bound& pupper,
408  unsigned i)
409  : myLowerBound(i == 0 ? plower : findMiddle(plower, pupper))
410  , myLowerBoundQuery(makeQuery(indexKey, myLowerBound, DtHasAttributeValue::GreaterEqual))
411  , myUpperBound(i == 1 ? pupper : findMiddle(plower, pupper))
412  , myUpperBoundQuery(makeQuery(indexKey, myUpperBound, DtHasAttributeValue::Less))
413  , myQuery(myLowerBoundQuery && myUpperBoundQuery)
414  , mySink(Sink::Make(parentFeatures, query()))
415  {
416  DtWarn << "Level " << i << ": " << plower
417  << " -> " << pupper
418  << " query " << query()
419  << std::endl;
420  }
421 
422  void init(const Ptr& parent)
423  {
424  Caller caller(parent, *this);
425  mySink->addLoadedCallback(caller);
426 
427  checkIndex(*parent);
428  }
429 
430  void activate(const Ptr& parent)
431  {
432  myIndexingSet.reset(new DtAttributeIndexingFeatureSet(parent, *this));
433  myIndexingSet->init();
434  }
435 
436  private:
438  {
439  try
440  {
441  if (!mySink->loaded())
442  return;
443  }
445  {
446  return;
447  }
448 
449  if (parent.myLevel >= parent.myConfig->featuresMaxIndexLOD)
450  return;
451 
452  size_t pc = parent.numberOfFeatures();
453  size_t c = mySink->numberOfFeatures();
454 
455  assert(pc >= c);
456 
458  if (pc <= parent.myConfig->minFeaturesToIndexTile)
459  return;
460 
461  //if (c > 0)
462  if (c > 10)
463  {
464  //if (pc/(double)c >= parent.myConfig->featuresIndexRatio)
465  parent.activateSubtiles();
466  }
467  else
468  {
470  //if (pc > 0)
472  }
473  }
474 
475  class Caller
476  {
477  public:
478  explicit Caller(const Ptr& set, Subtile& subtile)
479  : set(set), subtile(subtile)
480  {
481  }
482 
483  void operator()() const
484  {
485  Ptr p(set.lock());
486  if (p)
487  subtile.checkIndex(*p);
488  }
489 
490  private:
493  };
494  };
495 
496  friend class Subtile;
497 
500 
501  enum State
502  {
504  };
505 
506  tbb::atomic<State> myState;
507  };
508 }
Definition: attributeIndexingFeatureSet.h:127
const Bound & lowerBound() const
Definition: attributeIndexingFeatureSet.h:400
Config(const SinkPtr &input, const DtFeature::Key &key)
Definition: attributeIndexingFeatureSet.h:59
Definition: attributeIndexingFeatureSet.h:503
Class DtTerrainInterfaceConfig is a readable-writable class holding terrain interface configuration o...
Definition: terrainInterfaceConfig.h:32
bool elided() const
Definition: attributeIndexingFeatureSet.h:117
DtQuery myQuery
Definition: attributeIndexingFeatureSet.h:392
boost::shared_ptr< DtAttributeIndexingFeatureSet > Ptr
Definition: attributeIndexingFeatureSet.h:34
S Sink
Definition: attributeIndexingFeatureSet.h:46
static std::string removePrefix(std::string &s1, std::string &s2)
Definition: attributeIndexingFeatureSet.h:333
FS * clone() const
Definition: attributeIndexingFeatureSet.h:91
Set of subtiles.
Definition: attributeIndexingFeatureSet.h:331
const SinkPtr inputSink
Definition: attributeIndexingFeatureSet.h:69
Key used to lookup attributes. The DtFeature interface is a dictionary that maps Key objects to attri...
Definition: feature.h:68
Definition: attributeIndexingFeatureSet.h:503
Bound myLowerBound
Definition: attributeIndexingFeatureSet.h:388
DtQuery visit(const DtQuery &query)
Definition: attributeIndexingFeatureSet.h:135
DtAttributeIndexingFeatureSet(const Ptr &parent, const Subtile &subtile)
Definition: attributeIndexingFeatureSet.h:244
bool isTrue() const
Definition: query.h:114
std::string Bound
Definition: attributeIndexingFeatureSet.h:49
bool empty() const
Definition: attributeIndexingFeatureSet.h:122
const int myLevel
Level in hierarchy.
Definition: attributeIndexingFeatureSet.h:322
FS::ForEachFunction ForEachFunction
Definition: attributeIndexingFeatureSet.h:42
FS * filter(const DtQuery &query, const boost::optional< DtFeatureGeometry > &geometry, DtLoadType load) const
Definition: attributeIndexingFeatureSet.h:166
Definition: query.h:60
SinkPtr myFeatures
Features in this tile.
Definition: attributeIndexingFeatureSet.h:328
DtQuery myLowerBoundQuery
Definition: attributeIndexingFeatureSet.h:389
Do not initiate new loads, read whatever is currently loaded.
Definition: featureSet.h:45
const Subtile & subtile
Definition: attributeIndexingFeatureSet.h:163
const DtHasAttributeValue & upperBoundQuery() const
Definition: attributeIndexingFeatureSet.h:398
FS::DetachCallback DetachCallback
Definition: attributeIndexingFeatureSet.h:44
boost::shared_ptr< DtAttributeIndexingFeatureSet > myIndexingSet
Definition: attributeIndexingFeatureSet.h:387
FS::Feature Feature
Definition: attributeIndexingFeatureSet.h:41
Matches features that have an attribute with a certain key.
Definition: query.h:295
const Bound & upperBound() const
Definition: attributeIndexingFeatureSet.h:399
std::string label() const
Definition: attributeIndexingFeatureSet.h:96
Sink::Ptr SinkPtr
Definition: attributeIndexingFeatureSet.h:47
static FS * Make(const typename Config::Ptr &cfg, Bound lower=Bound(), Bound upper=Bound())
Definition: attributeIndexingFeatureSet.h:78
bool isFalse() const
Definition: query.h:115
Subtile mySubtile1
Definition: attributeIndexingFeatureSet.h:499
const Subtile & getSubtile(unsigned i) const
Definition: attributeIndexingFeatureSet.h:267
Caller(const Ptr &set, Subtile &subtile)
Definition: attributeIndexingFeatureSet.h:478
static DtQuery Merge(const DtHasAttributeValue &, const DtHasAttributeValue &)
Config(const Config &cfg)
Definition: attributeIndexingFeatureSet.h:62
Subtile & subtile
Definition: attributeIndexingFeatureSet.h:492
void checkIndex(DtAttributeIndexingFeatureSet &parent)
Definition: attributeIndexingFeatureSet.h:437
Configuration information.
Definition: attributeIndexingFeatureSet.h:52
FS::LoadedCallback LoadedCallback
Definition: attributeIndexingFeatureSet.h:43
static std::string findMiddle(const std::string &lower, const std::string &upper)
Definition: attributeIndexingFeatureSet.h:350
bool loaded(double timeout) const
Definition: attributeIndexingFeatureSet.h:102
Represents a set of characeters a DtFeature object can have. DtQuery objects are the way to communica...
Definition: query.h:38
Bound myUpperBound
Definition: attributeIndexingFeatureSet.h:390
boost::weak_ptr< DtAttributeIndexingFeatureSet > WPtr
Definition: attributeIndexingFeatureSet.h:39
void init(const Ptr &parent)
Definition: attributeIndexingFeatureSet.h:422
WPtr set
Definition: attributeIndexingFeatureSet.h:491
Subtile(const Sink &parentFeatures, const DtFeature::Key &indexKey, const Bound &plower, const Bound &pupper, unsigned i)
Definition: attributeIndexingFeatureSet.h:404
DtQuery myUpperBoundQuery
Definition: attributeIndexingFeatureSet.h:391
SinkPtr mySink
Definition: attributeIndexingFeatureSet.h:393
unsigned numberOfFeatures() const
Definition: attributeIndexingFeatureSet.h:112
static FS * Make(Config *cfg, const Bound &lower=Bound(), const Bound &upper=Bound())
Definition: attributeIndexingFeatureSet.h:73
State
Definition: attributeIndexingFeatureSet.h:501
Definition: attributeIndexingFeatureSet.h:29
const SinkPtr & sink() const
Definition: attributeIndexingFeatureSet.h:401
bool activateSubtiles()
Mark subtiles and read to use.
Definition: attributeIndexingFeatureSet.h:289
void forEachFeatureParallel(const ForEachFunction &func) const
Definition: attributeIndexingFeatureSet.h:233
QueryVisitor(const DtFeature::Key &key, const Subtile &subtile)
Definition: attributeIndexingFeatureSet.h:130
const boost::shared_ptr< Config > myConfig
Configuration data for this node.
Definition: attributeIndexingFeatureSet.h:319
const DtHasAttributeValue & lowerBoundQuery() const
Definition: attributeIndexingFeatureSet.h:397
DtLoadType
Used to indicate whether to load features. See DtFeatureSetTemplate::filter.
Definition: featureSet.h:36
DtFeature::Key attribute
Definition: attributeIndexingFeatureSet.h:162
Definition: query.h:320
const FS & indexedFeatures() const
Definition: attributeIndexingFeatureSet.h:402
DtAttributeIndexingFeatureSet(const boost::shared_ptr< Config > &cfg, const Bound &lower, const Bound &upper)
Definition: attributeIndexingFeatureSet.h:255
boost::shared_ptr< const DtAttributeIndexingFeatureSet > CPtr
Definition: attributeIndexingFeatureSet.h:38
Definition: attributeIndexingFeatureSet.h:503
DetachCallback forEachFeatureAsync(const ForEachFunction &func) const
Definition: attributeIndexingFeatureSet.h:238
DtFeatureSet used to combine multiple feature sets into one. This class allows all feature set algori...
Definition: featureSetList.h:26
Definition: attributeIndexingFeatureSet.h:503
virtual Result apply(const DtQuery &query)
Definition: query.h:154
DetachCallback addLoadedCallback(const LoadedCallback &cb) const
Definition: attributeIndexingFeatureSet.h:107
boost::shared_ptr< Config > Ptr
Definition: attributeIndexingFeatureSet.h:55
tbb::atomic< State > myState
Definition: attributeIndexingFeatureSet.h:506
const WPtr myParent
Weak pointer to parent node.
Definition: attributeIndexingFeatureSet.h:325
static DtQuery makeQuery(const DtFeature::Key &indexKey, const Bound &bound, DtHasAttributeValue::Comparison comp)
Definition: attributeIndexingFeatureSet.h:380
const DtFeature::Key indexKey
Definition: attributeIndexingFeatureSet.h:70
const DtQuery & query() const
Definition: attributeIndexingFeatureSet.h:396
static DtQuery Create(DtFeature::Key, DtFeature::Attribute, Comparison)
Comparison
Definition: query.h:325
const T * trycast() const
Definition: query.h:100
Subtile mySubtile0
Definition: attributeIndexingFeatureSet.h:498
void init()
Delayed init needed b/c we need a shared_ptr to ourself.
Definition: attributeIndexingFeatureSet.h:280
Definition: attributeIndexingFeatureSet.h:475
void operator()() const
Definition: attributeIndexingFeatureSet.h:483
Config(FS *input, const DtFeature::Key &key)
Definition: attributeIndexingFeatureSet.h:57
void activate(const Ptr &parent)
Definition: attributeIndexingFeatureSet.h:430

Document ID: Generated on Wed Mar 27 22:49:11 EDT 2024 from SVN revision 264633
Copyright © 2005-2024 MAK Technologies. All Rights Reserved (www.mak.com)