TFulcrumGrid.h
Go to the documentation of this file.
1 #ifndef imath_TFulcrumGrid_included
2 #define imath_TFulcrumGrid_included
3 
4 
5 // Qt includes
6 #include <QtCore/QObject>
7 #include <QtCore/QtAlgorithms>
8 #include <QtCore/QVector>
9 
10 // ACF includes
11 #include <istd/CChangeNotifier.h>
12 #include <iser/ISerializable.h>
13 #include <iser/CArchiveTag.h>
14 
15 
16 namespace imath
17 {
18 
19 
32 template <class Position, class Fulcrums>
33 class TFulcrumGrid: virtual public iser::ISerializable
34 {
35 public:
36  typedef typename Fulcrums::ElementType FulcrumType;
37  typedef typename Fulcrums::IndexType FulcrumIndex;
38  typedef typename Fulcrums::SizesType FulcrumSizes;
39  typedef Position PositionType;
40 
45  {
46  CF_SORT_LAYERS = 0x8352707
47  };
48 
49  TFulcrumGrid();
50 
54  void Reset();
55 
59  FulcrumSizes GetGridSize() const;
60 
64  int GetDimensionsCount() const;
65 
71  virtual bool SetDimensionsCount(int count);
72 
76  int GetLayersCount(int dimension) const;
77 
82  virtual void SetLayersCount(int dimension, int count);
83 
87  double GetLayerPosition(int dimension, int layerIndex) const;
88 
94  virtual void SetLayerPosition(int dimension, int layerIndex, double position);
95 
99  void GetFulcrumPosition(const FulcrumIndex& index, PositionType& result) const;
100 
104  const FulcrumType& GetFulcrumAtIndex(const FulcrumIndex& index) const;
105 
109  virtual void SetFulcrumAtIndex(const FulcrumIndex& index, const FulcrumType& value);
110 
115  int InsertLayer(int dimension, double position);
116 
120  virtual void RemoveLayer(int dimension, int layerIndex);
121 
122  // reimplemented (iser::ISerializable)
123  virtual bool Serialize(iser::IArchive& archive);
124 
125  // operators
126  bool operator==(const TFulcrumGrid<Position, Fulcrums>& value) const;
127  bool operator!=(const TFulcrumGrid<Position, Fulcrums>& value) const;
128 
129 protected:
133  virtual void SortFulcrums();
134 
142  int FindLayerIndex(int dimension, double value) const;
146  typename Fulcrums::IndexType FindIndices(const PositionType& argument) const;
147 
148 protected:
149  static const ChangeSet s_fulcrumPositionChange;
150 
151 private:
152  Fulcrums m_fulcrums;
153 
154  typedef QVector<double> LayerPositions;
155  typedef QVector<LayerPositions> Layers;
156 
157  Layers m_layers;
158 };
159 
160 
161 
162 // inline methods
163 
164 template <class Position, class Fulcrums>
167 {
168  return m_fulcrums.GetSizes();
169 }
170 
171 
172 template <class Position, class Fulcrums>
174 {
175  return m_fulcrums.GetDimensionsCount();
176 }
177 
178 
179 template <class Position, class Fulcrums>
181 {
182  Q_ASSERT(dimension >= 0);
183  Q_ASSERT(dimension < int(m_layers.size()));
184 
185  return m_layers[dimension].size();
186 }
187 
188 
189 template <class Position, class Fulcrums>
190 inline double TFulcrumGrid<Position, Fulcrums>::GetLayerPosition(int dimension, int layerIndex) const
191 {
192  Q_ASSERT(dimension >= 0);
193  Q_ASSERT(dimension < int(m_layers.size()));
194 
195  const LayerPositions& positions = m_layers[dimension];
196 
197  Q_ASSERT(layerIndex >= 0);
198  Q_ASSERT(layerIndex < int(positions.size()));
199 
200  return positions[layerIndex];
201 }
202 
203 
204 // public methods
205 
206 template <class Position, class Fulcrums>
208 {
209  m_layers.resize(m_fulcrums.GetDimensionsCount());
210 }
211 
212 
213 template <class Position, class Fulcrums>
215 {
216  m_fulcrums.Reset();
217 
218  for (Layers::iterator iter = m_layers.begin(); iter != m_layers.end(); ++iter){
219  iter->clear();
220  }
221 
222  m_layers.resize(m_fulcrums.GetDimensionsCount());
223 }
224 
225 
226 template <class Position, class Fulcrums>
228 {
229  if (m_fulcrums.SetDimensionsCount(count)){
230  m_layers.resize(count);
231 
232  return true;
233  }
234 
235  return false;
236 }
237 
238 
239 template <class Position, class Fulcrums>
241 {
242  Q_ASSERT(dimension >= 0);
243  Q_ASSERT(dimension < int(m_layers.size()));
244 
245  m_layers[dimension].resize(count);
246  m_fulcrums.SetSize(dimension, count);
247 }
248 
249 
250 template <class Position, class Fulcrums>
251 void TFulcrumGrid<Position, Fulcrums>::SetLayerPosition(int dimension, int layerIndex, double position)
252 {
253  Q_ASSERT(dimension >= 0);
254  Q_ASSERT(dimension < int(m_layers.size()));
255 
256  LayerPositions& positions = m_layers[dimension];
257 
258  Q_ASSERT(layerIndex >= 0);
259  Q_ASSERT(layerIndex < int(positions.size()));
260 
261  istd::CChangeNotifier notifier(this, &s_fulcrumPositionChange);
262  Q_UNUSED(notifier);
263 
264  positions[layerIndex] = position;
265 }
266 
267 
268 template <class Position, class Fulcrums>
270 {
271  int layersCount = int(m_layers.size());
272  Q_ASSERT(layersCount <= index.GetDimensionsCount());
273 
274  result.SetElementsCount(layersCount);
275 
276  for (int i = 0; i < layersCount; ++i){
277  const LayerPositions& positions = m_layers[i];
278 
279  Q_ASSERT(index[i] >= 0);
280  Q_ASSERT(index[i] < int(positions.size()));
281 
282  result[i] = positions[index[i]];
283  }
284 }
285 
286 
287 template <class Position, class Fulcrums>
290 {
291  return m_fulcrums.GetAt(index);
292 }
293 
294 
295 template <class Position, class Fulcrums>
297 {
298  istd::CChangeNotifier notifier(this);
299 
300  m_fulcrums.SetAt(index, value);
301 }
302 
303 
304 template <class Position, class Fulcrums>
305 int TFulcrumGrid<Position, Fulcrums>::InsertLayer(int dimension, double position)
306 {
307  Q_ASSERT(dimension >= 0);
308  Q_ASSERT(dimension < m_fulcrums.GetDimensionsCount());
309 
310  Fulcrums newFulcrums = m_fulcrums;
311 
312  newFulcrums.SetSize(dimension, m_fulcrums.GetSize(dimension) + 1);
313 
314  int layerIndex = FindLayerIndex(dimension, position);
315 
316  LayerPositions& positions = m_layers[dimension];
317 
318  double prevPosition = position;
319  double nextPosition = position;
320  if (!positions.isEmpty()){
321  if (layerIndex >= 0){
322  prevPosition = positions[layerIndex];
323  }
324  if (layerIndex < GetLayersCount(dimension) - 1){
325  nextPosition = positions[layerIndex + 1];
326  }
327  }
328  Q_ASSERT(position >= prevPosition);
329  Q_ASSERT(position <= nextPosition);
330 
331  double prevFactor = 0.5;
332  if (nextPosition - prevPosition > I_BIG_EPSILON){
333  prevFactor = (position - prevPosition) / (nextPosition - prevPosition);
334 
335  Q_ASSERT(prevFactor >= 0);
336  Q_ASSERT(prevFactor - I_EPSILON <= 1.0);
337  }
338  double nextFactor = 1 - prevFactor;
339 
340  int oldLayersCount = int(positions.size());
341  Q_ASSERT(oldLayersCount == m_fulcrums.GetSize(dimension));
342 
343  for ( typename Fulcrums::Iterator destIter = newFulcrums.Begin();
344  destIter != newFulcrums.End();
345  ++destIter){
346  PositionType sourceIndex = destIter;
347  if ((destIter[dimension] >= layerIndex) && (sourceIndex[dimension] > 0)){
348  sourceIndex[dimension]--;
349 
350  if ((destIter[dimension] == layerIndex) && (layerIndex < oldLayersCount)){
351  PositionType prevFulcrumPosition;
352  GetFulcrumPosition(sourceIndex, prevFulcrumPosition);
353 
354  PositionType nextFulcrumPosition;
355  GetFulcrumPosition(destIter, nextFulcrumPosition);
356 
357  PositionType position = prevFactor * prevFulcrumPosition + nextFactor * nextFulcrumPosition;
358 
359  newFulcrums[destIter] = GetValueAt(position);
360 
361  continue;
362  }
363  }
364 
365  *destIter = m_fulcrums[sourceIndex];
366  }
367 
368  positions.insert(positions.begin() + layerIndex + 1, position);
369  m_fulcrums = newFulcrums;
370 
371  return layerIndex;
372 }
373 
374 
375 template <class Position, class Fulcrums>
376 void TFulcrumGrid<Position, Fulcrums>::RemoveLayer(int dimension, int layerIndex)
377 {
378  Q_ASSERT(dimension >= 0);
379  Q_ASSERT(dimension < GetDimensionsCount());
380  Q_ASSERT(m_fulcrums.GetSize(dimension) > 0);
381 
382  Fulcrums newFulcrums = m_fulcrums;
383 
384  newFulcrums.SetSize(dimension, m_fulcrums.GetSize(dimension) + 1);
385 
386  LayerPositions& positions = m_layers[dimension];
387 
388  for ( typename Fulcrums::Iterator destIter = newFulcrums.Begin();
389  destIter != newFulcrums.End();
390  ++destIter){
391  FulcrumIndex sourceIndex = destIter;
392  if (destIter[dimension] >= layerIndex){
393  sourceIndex.IncreaseAt(dimension);
394  }
395 
396  *destIter = m_fulcrums[sourceIndex];
397  }
398 
399  positions.erase(positions.begin() + layerIndex);
400  m_fulcrums = newFulcrums;
401 }
402 
403 
404 // reimplemented (iser::ISerializable)
405 
406 template <class Position, class Fulcrums>
408 {
409  bool retVal = true;
410 
411  iser::CArchiveTag gridTag("Grid", "Description of fulcrums grid", iser::CArchiveTag::TT_MULTIPLE);
412  iser::CArchiveTag positionsTag("Positions", "List of positions at single axis of fulcrum grid", iser::CArchiveTag::TT_MULTIPLE, &gridTag);
413  iser::CArchiveTag positionTag("Position", "Single layer position", iser::CArchiveTag::TT_LEAF, &positionsTag);
414  iser::CArchiveTag fulcrumsTag("Fulcrums", "List of fulcrums", iser::CArchiveTag::TT_GROUP);
415  iser::CArchiveTag fulcrumTag("Fulcrum", "Single fulcrum", iser::CArchiveTag::TT_GROUP, &fulcrumsTag);
416 
417  bool isStoring = archive.IsStoring();
418 
419  istd::CChangeNotifier notifier(isStoring? NULL: this);
420 
421  int dimensionsCount = m_fulcrums.GetDimensionsCount();
422  Q_ASSERT(dimensionsCount == int(m_layers.size()));
423 
424  retVal = retVal && archive.BeginMultiTag(gridTag, positionsTag, dimensionsCount);
425 
426  if (!isStoring && (dimensionsCount != m_fulcrums.GetDimensionsCount())){
427  if (!SetDimensionsCount(dimensionsCount)){
428  return false;
429  }
430  }
431 
432  FulcrumSizes sizes = m_fulcrums.GetSizes();
433  Q_ASSERT(sizes.GetDimensionsCount() >= dimensionsCount);
434 
435  for (int dimensionIndex = 0; dimensionIndex < dimensionsCount; ++dimensionIndex){
436  LayerPositions& positions = m_layers[dimensionIndex];
437 
438  int& positionsCount = sizes[dimensionIndex];
439  Q_ASSERT(positionsCount == int(positions.size()));
440 
441  retVal = retVal && archive.BeginMultiTag(positionsTag, positionTag, positionsCount);
442 
443  if (!isStoring){
444  if (!retVal){
445  Reset();
446 
447  return false;
448  }
449 
450  SetLayersCount(dimensionIndex, positionsCount);
451  }
452 
453  for (int positionIndex = 0; positionIndex < positionsCount; ++positionIndex){
454  retVal = retVal && archive.BeginTag(positionTag);
455  retVal = retVal && archive.Process(positions[positionIndex]);
456  retVal = retVal && archive.EndTag(positionTag);
457  }
458 
459  retVal = retVal && archive.EndTag(positionsTag);
460  }
461 
462  retVal = retVal && archive.EndTag(gridTag);
463 
464  retVal = retVal && archive.BeginTag(fulcrumsTag);
465 
466  for ( typename Fulcrums::Iterator iter = m_fulcrums.Begin();
467  iter != m_fulcrums.End();
468  ++iter){
469  FulcrumType& point = *iter;
470 
471  retVal = retVal && archive.BeginTag(fulcrumTag);
472  retVal = retVal && point.Serialize(archive);
473  retVal = retVal && archive.EndTag(fulcrumTag);
474  }
475 
476  retVal = retVal && archive.EndTag(fulcrumsTag);
477 
478  return retVal;
479 }
480 
481 
482 // operators
483 
484 template <class Position, class Fulcrums>
486 {
487  return (m_fulcrums == value.m_fulcrums) && (m_layers == value.m_layers);
488 }
489 
490 
491 template <class Position, class Fulcrums>
493 {
494  return (m_fulcrums != value.m_fulcrums) || (m_layers != value.m_layers);
495 }
496 
497 
498 // protected methods
499 
500 template <class Position, class Fulcrums>
502 {
503  for (Layers::iterator iter = m_layers.begin(); iter != m_layers.end(); ++iter){
504  LayerPositions& positions = *iter;
505 
506  qSort(positions.begin(), positions.end());
507  }
508 }
509 
510 
511 template <class Position, class Fulcrums>
512 int TFulcrumGrid<Position, Fulcrums>::FindLayerIndex(int dimension, double value) const
513 {
514  Q_ASSERT(dimension >= 0);
515  Q_ASSERT(dimension < GetDimensionsCount());
516 
517  const LayerPositions& positions = m_layers[dimension];
518 
519  int left = 0;
520  int right = int(positions.size());
521 
522  while (left != right){
523  int center = (left + right) / 2;
524 
525  if (value >= positions[center]){
526  left = center + 1;
527  }
528  else{
529  right = center;
530  }
531  }
532 
533  return left - 1;
534 }
535 
536 
537 template <class Position, class Fulcrums>
538 typename Fulcrums::IndexType
540 {
541  int dimensionsCount = GetDimensionsCount();
542 
543  FulcrumIndex retVal(dimensionsCount);
544 
545  for (int i = 0; i < dimensionsCount; ++i){
546  retVal[i] = FindLayerIndex(i, argument[i]);
547  }
548 
549  return retVal;
550 }
551 
552 
553 // protected static members
554 
555 template <class Position, class Fulcrums>
556 const istd::IChangeable::ChangeSet TFulcrumGrid<Position, Fulcrums>::s_fulcrumPositionChange(CF_SORT_LAYERS, QObject::tr("Change fulcrum position"));
557 
558 
559 } // namespace imath
560 
561 
562 #endif // !imath_TFulcrumGrid_included
563 
564 
virtual void SetFulcrumAtIndex(const FulcrumIndex &index, const FulcrumType &value)
Set single fulcrum point.
Definition: TFulcrumGrid.h:296
bool operator==(const TFulcrumGrid< Position, Fulcrums > &value) const
Definition: TFulcrumGrid.h:485
Fulcrums::IndexType FulcrumIndex
Definition: TFulcrumGrid.h:37
Fulcrums::SizesType FulcrumSizes
Definition: TFulcrumGrid.h:38
virtual bool IsStoring() const =0
Check if this archive is loading or storing.
#define I_EPSILON
Some very small number.
Definition: istd.h:31
Fulcrums::IndexType FindIndices(const PositionType &argument) const
Find indices of cuboid containing specified argument value.
Definition: TFulcrumGrid.h:539
double GetLayerPosition(int dimension, int layerIndex) const
Get position of specified layer of fulcrums.
Definition: TFulcrumGrid.h:190
int FindLayerIndex(int dimension, double value) const
Find layer index of specified value for specified dimension.
Definition: TFulcrumGrid.h:512
Common class for all classes which objects can be archived or restored from archive.
Definition: ISerializable.h:23
void Reset()
Removes all fulcrum points.
Definition: TFulcrumGrid.h:214
virtual bool Process(bool &value)=0
Process primitive type.
int GetDimensionsCount() const
Get number of dimensions.
Definition: TFulcrumGrid.h:173
const FulcrumType & GetFulcrumAtIndex(const FulcrumIndex &index) const
Get value at specified index.
Definition: TFulcrumGrid.h:289
static const ChangeSet s_fulcrumPositionChange
Definition: TFulcrumGrid.h:149
virtual bool BeginTag(const CArchiveTag &tag)=0
Begin of archive tag.
virtual void RemoveLayer(int dimension, int layerIndex)
Remove fulcrums at spacified layer.
Definition: TFulcrumGrid.h:376
Multiple tag containing variable number of child tags.
Definition: CArchiveTag.h:42
Normal tag used for grouping of tags or processed elements.
Definition: CArchiveTag.h:37
virtual bool BeginMultiTag(const CArchiveTag &tag, const CArchiveTag &subTag, int &count)=0
Begin of archive tag containing set of subelements of the same type.
Represent input/output persistence archive.
Definition: IArchive.h:30
virtual bool Serialize(iser::IArchive &archive)
Load or store state of this object as a archive stream.
Definition: TFulcrumGrid.h:407
Fulcrums::ElementType FulcrumType
Definition: TFulcrumGrid.h:36
virtual void SetLayersCount(int dimension, int count)
Set number of fulcrum layers at specified dimension.
Definition: TFulcrumGrid.h:240
int InsertLayer(int dimension, double position)
Inserts single fulcrum layer.
Definition: TFulcrumGrid.h:305
Help class which provides the automatic update mechanism of the model.
FulcrumSizes GetGridSize() const
Return complete grid size.
Definition: TFulcrumGrid.h:166
Leaf tag, it can contain only one primitive element.
Definition: CArchiveTag.h:48
#define NULL
Definition: istd.h:64
bool operator!=(const TFulcrumGrid< Position, Fulcrums > &value) const
Definition: TFulcrumGrid.h:492
virtual void SortFulcrums()
Sort fulcrums in this collection.
Definition: TFulcrumGrid.h:501
virtual bool SetDimensionsCount(int count)
Set number of dimensions.
Definition: TFulcrumGrid.h:227
static const double I_BIG_EPSILON
Definition: istd.h:26
Set of change flags (its IDs).
Definition: IChangeable.h:30
Process tag used to group data in archive stream.
Definition: CArchiveTag.h:21
virtual bool EndTag(const CArchiveTag &tag)=0
End of archive tag.
ChangeFlags
Data model change notification flags.
Definition: IChangeable.h:111
Representation of fulcrums in multi-dimesional regular grid.
Definition: TFulcrumGrid.h:33
void GetFulcrumPosition(const FulcrumIndex &index, PositionType &result) const
Get position of node at specified grid index.
Definition: TFulcrumGrid.h:269
virtual void SetLayerPosition(int dimension, int layerIndex, double position)
Set position of specified layer of fulcrums.
Definition: TFulcrumGrid.h:251
int GetLayersCount(int dimension) const
Get number of fulcrum points used in this function.
Definition: TFulcrumGrid.h:180

© 2007-2017 Witold Gantzke and Kirill Lepskiy