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 <atomic>
22 
23 #include <boost/optional.hpp>
24 
25 namespace MAKVRinTerra
26 {
27  template <typename FS, typename S = typename FS::Sink>
29  : public FS
30  , public std::enable_shared_from_this<DtAttributeIndexingFeatureSet<FS,S> >
31  {
32  protected:
33  class Subtile;
34 
35  public:
36  typedef std::shared_ptr<DtAttributeIndexingFeatureSet> Ptr;
37  typedef std::shared_ptr<const DtAttributeIndexingFeatureSet> CPtr;
38  typedef std::weak_ptr<DtAttributeIndexingFeatureSet> WPtr;
39 
40  typedef typename FS::Feature Feature;
41  typedef typename FS::ForEachFunction ForEachFunction;
42  typedef typename FS::LoadedCallback LoadedCallback;
43  typedef typename FS::DetachCallback DetachCallback;
44 
45  typedef S Sink;
46  typedef typename Sink::Ptr SinkPtr;
47 
48  typedef std::string Bound;
49 
52  {
53  public:
54  typedef std::shared_ptr<Config> Ptr;
55 
56  explicit Config(FS* input, const DtFeature::Key& key)
57  : inputSink(Sink::Make(input)), indexKey(key) { }
58  explicit Config(const SinkPtr& input, const DtFeature::Key& key)
59  : inputSink(input ? input : Sink::Make(0)), indexKey(key) { }
60 
61  explicit Config(const Config& cfg)
62  : inputSink(cfg.inputSink)
63  , indexKey(cfg.indexKey)
64  {
65  static_cast<DtTerrainInterfaceConfig&>(*this) = cfg;
66  }
67 
70  };
71 
72  static FS* Make(Config* cfg, const Bound& lower=Bound(), const Bound& upper=Bound())
73  {
74  return Make(typename Config::Ptr(cfg), lower, upper);
75  }
76 
77  static FS* Make(
78  const typename Config::Ptr& cfg,
79  Bound lower=Bound(), Bound upper=Bound())
80  {
81  if (lower.empty()) lower = " ";
82  if (upper.empty()) upper = "~";
83 
84  Ptr set(new DtAttributeIndexingFeatureSet(cfg, lower, upper));
85  set->init();
86 
87  return FS::Wrap(set);
88  }
89 
90  FS* clone() const
91  {
92  return FS::Wrap(this->shared_from_this());
93  }
94 
95  std::string label() const
96  {
97  return myConfig->inputSink->label() + " index level "
98  + boost::lexical_cast<std::string>(myLevel);
99  }
100 
101  bool loaded(double timeout) const
102  {
103  return myFeatures->loaded(timeout);
104  }
105 
107  {
108  return myFeatures->addLoadedCallback(cb);
109  }
110 
111  unsigned numberOfFeatures() const
112  {
113  return myFeatures->numberOfFeatures();
114  }
115 
116  bool elided() const
117  {
118  return myFeatures->elided();
119  }
120 
121  bool empty() const
122  {
123  return myFeatures->empty();
124  }
125 
126  class QueryVisitor : public DtQuery::Visitor<DtQuery>
127  {
128  public:
129  explicit QueryVisitor(const DtFeature::Key& key, const Subtile& subtile)
130  : attribute(key)
131  , subtile(subtile)
132  {
133  }
134 
135  virtual DtQuery visit(const DtQuery& query) override
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 
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::unique_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 std::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  auto expected = START;
294  if (!myState.compare_exchange_strong(expected, ACTIVATING))
295  return false;
296 
297  try
298  {
299  Ptr This(this->shared_from_this());
300  mySubtile0.activate(This);
301  mySubtile1.activate(This);
302  }
303  catch (...)
304  {
305  myState = FAULT;
306  throw;
307  }
308 
309  expected = ACTIVATING;
310  if (!myState.compare_exchange_strong(expected, ACTIVE))
311  {
312  DtWarn << "Error activating subtile" << std::endl;
313  myState = FAULT;
314  return false;
315  }
316 
317  return true;
318  }
319 
321  const std::shared_ptr<Config> myConfig;
322 
324  const int myLevel;
325 
327  const WPtr myParent;
328 
331 
333  class Subtile
334  {
335  static std::string removePrefix(std::string& s1, std::string& s2)
336  {
337  assert(s1 < s2);
338 
339  std::string prefix;
340  while (!s1.empty() && !s2.empty() && s1[0] == s2[0])
341  {
342  prefix.push_back(s1[0]);
343 
344  s1 = s1.substr(1);
345  s2 = s2.substr(1);
346  }
347 
348  assert(s1 < s2);
349  return prefix;
350  }
351 
352  static std::string findMiddle(const std::string& lower, const std::string& upper)
353  {
354  using namespace std;
355 
356  string s1=lower, s2=upper;
357 
358  string prefix = removePrefix(s1, s2);
359  char c1 = s1.empty() ? ' ' : s1[0];
360  char c2 = s2.empty() ? '~' : s2[0];
361 
362  assert(c1 < c2);
363 
364  string ret;
365  if (c1 + 1 == c2)
366  {
367  ret = prefix + c1 + "z";
368  }
369  else
370  {
371  int middle = (c1+c2)/2;
372  ret = prefix + static_cast<char>(middle);
373  }
374 
375  assert(lower <= ret);
376  assert(ret < upper);
377 
378  //DtWarn << "[" << prefix << s1 << "," << prefix << s2 << "] -> " << prefix << std::endl;
379  return ret;
380  }
381 
383  const DtFeature::Key& indexKey, const Bound& bound,
385  {
386  return DtHasAttributeValue::Create(indexKey, bound, comp);
387  }
388 
389  std::shared_ptr<DtAttributeIndexingFeatureSet> myIndexingSet;
396 
397  public:
398  const DtQuery& query() const { return myQuery; }
399  const DtHasAttributeValue& lowerBoundQuery() const { return *myLowerBoundQuery.trycast<DtHasAttributeValue>(); }
400  const DtHasAttributeValue& upperBoundQuery() const { return *myUpperBoundQuery.trycast<DtHasAttributeValue>(); }
401  const Bound& upperBound() const { return myUpperBound; }
402  const Bound& lowerBound() const { return myLowerBound; }
403  const SinkPtr& sink() const { return mySink; }
404  const FS& indexedFeatures() const { return *myIndexingSet; }
405 
407  const Sink& parentFeatures,
408  const DtFeature::Key& indexKey,
409  const Bound& plower, const Bound& pupper,
410  unsigned i)
411  : myLowerBound(i == 0 ? plower : findMiddle(plower, pupper))
412  , myLowerBoundQuery(makeQuery(indexKey, myLowerBound, DtHasAttributeValue::GreaterEqual))
413  , myUpperBound(i == 1 ? pupper : findMiddle(plower, pupper))
414  , myUpperBoundQuery(makeQuery(indexKey, myUpperBound, DtHasAttributeValue::Less))
415  , myQuery(myLowerBoundQuery && myUpperBoundQuery)
416  , mySink(Sink::Make(parentFeatures, query()))
417  {
418  DtWarn << "Level " << i << ": " << plower
419  << " -> " << pupper
420  << " query " << query()
421  << std::endl;
422  }
423 
424  void init(const Ptr& parent)
425  {
426  Caller caller(parent, *this);
427  mySink->addLoadedCallback(caller);
428 
429  checkIndex(*parent);
430  }
431 
432  void activate(const Ptr& parent)
433  {
434  myIndexingSet.reset(new DtAttributeIndexingFeatureSet(parent, *this));
435  myIndexingSet->init();
436  }
437 
438  private:
440  {
441  try
442  {
443  if (!mySink->loaded())
444  return;
445  }
447  {
448  return;
449  }
450 
451  if (parent.myLevel >= parent.myConfig->featuresMaxIndexLOD)
452  return;
453 
454  size_t pc = parent.numberOfFeatures();
455  size_t c = mySink->numberOfFeatures();
456 
457  assert(pc >= c);
458 
460  if (pc <= parent.myConfig->minFeaturesToIndexTile)
461  return;
462 
463  //if (c > 0)
464  if (c > 10)
465  {
466  //if (pc/(double)c >= parent.myConfig->featuresIndexRatio)
467  parent.activateSubtiles();
468  }
469  else
470  {
472  //if (pc > 0)
474  }
475  }
476 
477  class Caller
478  {
479  public:
480  explicit Caller(const Ptr& set, Subtile& subtile)
481  : set(set), subtile(subtile)
482  {
483  }
484 
485  void operator()() const
486  {
487  Ptr p(set.lock());
488  if (p)
489  subtile.checkIndex(*p);
490  }
491 
492  private:
495  };
496  };
497 
498  friend class Subtile;
499 
502 
503  enum State
504  {
506  };
507 
508  std::atomic<State> myState;
509  };
510 }
Definition: attributeIndexingFeatureSet.h:126
const Bound & lowerBound() const
Definition: attributeIndexingFeatureSet.h:402
Config(const SinkPtr &input, const DtFeature::Key &key)
Definition: attributeIndexingFeatureSet.h:58
Definition: attributeIndexingFeatureSet.h:505
Class DtTerrainInterfaceConfig is a readable-writable class holding terrain interface configuration o...
Definition: terrainInterfaceConfig.h:33
const std::shared_ptr< Config > myConfig
Configuration data for this node.
Definition: attributeIndexingFeatureSet.h:321
bool elided() const
Definition: attributeIndexingFeatureSet.h:116
DtQuery myQuery
Definition: attributeIndexingFeatureSet.h:394
S Sink
Definition: attributeIndexingFeatureSet.h:45
static std::string removePrefix(std::string &s1, std::string &s2)
Definition: attributeIndexingFeatureSet.h:335
FS * clone() const
Definition: attributeIndexingFeatureSet.h:90
Set of subtiles.
Definition: attributeIndexingFeatureSet.h:333
const SinkPtr inputSink
Definition: attributeIndexingFeatureSet.h:68
Key used to lookup attributes. The DtFeature interface is a dictionary that maps Key objects to attri...
Definition: feature.h:67
Definition: attributeIndexingFeatureSet.h:505
Bound myLowerBound
Definition: attributeIndexingFeatureSet.h:390
DtAttributeIndexingFeatureSet(const Ptr &parent, const Subtile &subtile)
Definition: attributeIndexingFeatureSet.h:244
bool isTrue() const
Definition: query.h:113
std::string Bound
Definition: attributeIndexingFeatureSet.h:48
std::shared_ptr< Config > Ptr
Definition: attributeIndexingFeatureSet.h:54
DtAttributeIndexingFeatureSet(const std::shared_ptr< Config > &cfg, const Bound &lower, const Bound &upper)
Definition: attributeIndexingFeatureSet.h:255
bool empty() const
Definition: attributeIndexingFeatureSet.h:121
const int myLevel
Level in hierarchy.
Definition: attributeIndexingFeatureSet.h:324
FS::ForEachFunction ForEachFunction
Definition: attributeIndexingFeatureSet.h:41
FS * filter(const DtQuery &query, const boost::optional< DtFeatureGeometry > &geometry, DtLoadType load) const
Definition: attributeIndexingFeatureSet.h:166
Definition: query.h:59
SinkPtr myFeatures
Features in this tile.
Definition: attributeIndexingFeatureSet.h:330
DtQuery myLowerBoundQuery
Definition: attributeIndexingFeatureSet.h:391
Do not initiate new loads, read whatever is currently loaded.
Definition: featureSet.h:42
const Subtile & subtile
Definition: attributeIndexingFeatureSet.h:163
const DtHasAttributeValue & upperBoundQuery() const
Definition: attributeIndexingFeatureSet.h:400
FS::DetachCallback DetachCallback
Definition: attributeIndexingFeatureSet.h:43
FS::Feature Feature
Definition: attributeIndexingFeatureSet.h:40
Matches features that have an attribute with a certain key.
Definition: query.h:294
const Bound & upperBound() const
Definition: attributeIndexingFeatureSet.h:401
std::string label() const
Definition: attributeIndexingFeatureSet.h:95
Sink::Ptr SinkPtr
Definition: attributeIndexingFeatureSet.h:46
static FS * Make(const typename Config::Ptr &cfg, Bound lower=Bound(), Bound upper=Bound())
Definition: attributeIndexingFeatureSet.h:77
bool isFalse() const
Definition: query.h:114
Subtile mySubtile1
Definition: attributeIndexingFeatureSet.h:501
const Subtile & getSubtile(unsigned i) const
Definition: attributeIndexingFeatureSet.h:267
Caller(const Ptr &set, Subtile &subtile)
Definition: attributeIndexingFeatureSet.h:480
static DtQuery Merge(const DtHasAttributeValue &, const DtHasAttributeValue &)
Config(const Config &cfg)
Definition: attributeIndexingFeatureSet.h:61
Subtile & subtile
Definition: attributeIndexingFeatureSet.h:494
void checkIndex(DtAttributeIndexingFeatureSet &parent)
Definition: attributeIndexingFeatureSet.h:439
Configuration information.
Definition: attributeIndexingFeatureSet.h:51
FS::LoadedCallback LoadedCallback
Definition: attributeIndexingFeatureSet.h:42
static std::string findMiddle(const std::string &lower, const std::string &upper)
Definition: attributeIndexingFeatureSet.h:352
std::shared_ptr< const DtAttributeIndexingFeatureSet > CPtr
Definition: attributeIndexingFeatureSet.h:37
std::weak_ptr< DtAttributeIndexingFeatureSet > WPtr
Definition: attributeIndexingFeatureSet.h:38
std::shared_ptr< DtAttributeIndexingFeatureSet > Ptr
Definition: attributeIndexingFeatureSet.h:33
bool loaded(double timeout) const
Definition: attributeIndexingFeatureSet.h:101
virtual DtQuery visit(const DtQuery &query) override
Definition: attributeIndexingFeatureSet.h:135
Represents a set of characeters a DtFeature object can have. DtQuery objects are the way to communica...
Definition: query.h:37
Bound myUpperBound
Definition: attributeIndexingFeatureSet.h:392
void init(const Ptr &parent)
Definition: attributeIndexingFeatureSet.h:424
WPtr set
Definition: attributeIndexingFeatureSet.h:493
Subtile(const Sink &parentFeatures, const DtFeature::Key &indexKey, const Bound &plower, const Bound &pupper, unsigned i)
Definition: attributeIndexingFeatureSet.h:406
DtQuery myUpperBoundQuery
Definition: attributeIndexingFeatureSet.h:393
SinkPtr mySink
Definition: attributeIndexingFeatureSet.h:395
unsigned numberOfFeatures() const
Definition: attributeIndexingFeatureSet.h:111
static FS * Make(Config *cfg, const Bound &lower=Bound(), const Bound &upper=Bound())
Definition: attributeIndexingFeatureSet.h:72
State
Definition: attributeIndexingFeatureSet.h:503
Definition: attributeIndexingFeatureSet.h:28
const SinkPtr & sink() const
Definition: attributeIndexingFeatureSet.h:403
bool activateSubtiles()
Mark subtiles and read to use.
Definition: attributeIndexingFeatureSet.h:289
std::shared_ptr< DtAttributeIndexingFeatureSet > myIndexingSet
Definition: attributeIndexingFeatureSet.h:389
void forEachFeatureParallel(const ForEachFunction &func) const
Definition: attributeIndexingFeatureSet.h:233
QueryVisitor(const DtFeature::Key &key, const Subtile &subtile)
Definition: attributeIndexingFeatureSet.h:129
const DtHasAttributeValue & lowerBoundQuery() const
Definition: attributeIndexingFeatureSet.h:399
DtLoadType
Used to indicate whether to load features. See DtFeatureSetTemplate::filter.
Definition: featureSet.h:33
DtFeature::Key attribute
Definition: attributeIndexingFeatureSet.h:162
Definition: query.h:319
const FS & indexedFeatures() const
Definition: attributeIndexingFeatureSet.h:404
Definition: attributeIndexingFeatureSet.h:505
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:505
virtual Result apply(const DtQuery &query)
Definition: query.h:153
DetachCallback addLoadedCallback(const LoadedCallback &cb) const
Definition: attributeIndexingFeatureSet.h:106
const WPtr myParent
Weak pointer to parent node.
Definition: attributeIndexingFeatureSet.h:327
static DtQuery makeQuery(const DtFeature::Key &indexKey, const Bound &bound, DtHasAttributeValue::Comparison comp)
Definition: attributeIndexingFeatureSet.h:382
const DtFeature::Key indexKey
Definition: attributeIndexingFeatureSet.h:69
const DtQuery & query() const
Definition: attributeIndexingFeatureSet.h:398
static DtQuery Create(DtFeature::Key, DtFeature::Attribute, Comparison)
Comparison
Definition: query.h:324
const T * trycast() const
Definition: query.h:99
Subtile mySubtile0
Definition: attributeIndexingFeatureSet.h:500
void init()
Delayed init needed b/c we need a shared_ptr to ourself.
Definition: attributeIndexingFeatureSet.h:280
std::atomic< State > myState
Definition: attributeIndexingFeatureSet.h:508
Definition: attributeIndexingFeatureSet.h:477
void operator()() const
Definition: attributeIndexingFeatureSet.h:485
Config(FS *input, const DtFeature::Key &key)
Definition: attributeIndexingFeatureSet.h:56
void activate(const Ptr &parent)
Definition: attributeIndexingFeatureSet.h:432

Document ID: Generated on Thu Oct 23 22:29:17 EDT 2025 from SVN revision 280951
Copyright © 2005-2024 MAK Technologies. All Rights Reserved (www.mak.com)