libCZI
Reading and Writing CZI documents made easy
libCZI_DimCoordinate.h
1 // SPDX-FileCopyrightText: 2017-2022 Carl Zeiss Microscopy GmbH
2 //
3 // SPDX-License-Identifier: LGPL-3.0-or-later
4 
5 #pragma once
6 
7 #include "ImportExport.h"
8 #include "libCZI_exceptions.h"
9 #include <cstdint>
10 #include <functional>
11 #include <initializer_list>
12 
13 namespace libCZI
14 {
16  enum class DimensionIndex : std::uint8_t
17  {
18  invalid = 0,
19 
20  MinDim = 1,
21 
22  Z = 1,
23  C = 2,
24  T = 3,
25  R = 4,
26  S = 5,
27  I = 6,
28  H = 7,
29  V = 8,
30  B = 9,
31 
32  MaxDim = 9
33  };
34 
36  class LIBCZI_API IDimCoordinate
37  {
38  public:
39 
46  virtual bool TryGetPosition(DimensionIndex dim, int* coordinate) const = 0;
47 
48  virtual ~IDimCoordinate() = default;
49 
55  inline bool IsValid(DimensionIndex dim) const
56  {
57  return this->TryGetPosition(dim, nullptr);
58  }
59 
63  inline int GetNumberOfValidDimensions() const
64  {
65  int cnt = 0;
66  for (auto i = static_cast<std::underlying_type<libCZI::DimensionIndex>::type>(libCZI::DimensionIndex::MinDim); i <= static_cast<std::underlying_type<libCZI::DimensionIndex>::type>(libCZI::DimensionIndex::MaxDim); ++i)
67  {
68  if (this->IsValid(static_cast<libCZI::DimensionIndex>(i)))
69  {
70  ++cnt;
71  }
72  }
73 
74  return cnt;
75  }
76  };
77 
79  class LIBCZI_API IDimBounds
80  {
81  public:
82 
88  virtual bool TryGetInterval(DimensionIndex dim, int* startIndex, int* size) const = 0;
89 
90  virtual ~IDimBounds() = default;
91 
95  inline bool IsValid(DimensionIndex dim) const
96  {
97  return this->TryGetInterval(dim, nullptr, nullptr);
98  }
99  };
100 
103  class LIBCZI_API IIndexSet
104  {
105  public:
106 
112  virtual bool IsContained(int index) const = 0;
113 
114  virtual ~IIndexSet() = default;
115  };
116 
119  {
121  int value;
122  };
123 
126  {
128  int start;
129  int size;
130  };
131 
133  class LIBCZI_API CDimBase
134  {
135  protected:
139  static std::underlying_type<libCZI::DimensionIndex>::type GetBitIndexForDimension(libCZI::DimensionIndex dim)
140  {
141  // TODO: add checks and asserts
142  auto i = ((std::underlying_type<libCZI::DimensionIndex>::type)dim) - 1;
143  return i;
144  }
145  };
146 
148  class LIBCZI_API CDimCoordinate : public CDimBase, public libCZI::IDimCoordinate
149  {
150  private:
151  std::uint32_t validDims;
152  int values[static_cast<int>(libCZI::DimensionIndex::MaxDim)];
153  public:
155  CDimCoordinate() : validDims(0) {}
156 
165  CDimCoordinate(std::initializer_list<DimensionAndValue> list) : CDimCoordinate()
166  {
167  for (const auto& d : list)
168  {
169  this->Set(d.dimension, d.value);
170  }
171  }
172 
177  {
178  if (other != nullptr)
179  {
180  for (auto i = (std::underlying_type<libCZI::DimensionIndex>::type)(libCZI::DimensionIndex::MinDim); i <= (std::underlying_type<libCZI::DimensionIndex>::type)(libCZI::DimensionIndex::MaxDim); ++i)
181  {
182  int coord;
183  if (other->TryGetPosition((libCZI::DimensionIndex)i, &coord))
184  {
185  this->Set((libCZI::DimensionIndex)i, coord);
186  }
187  }
188  }
189  }
190 
195  void Set(libCZI::DimensionIndex dimension, int value)
196  {
197  int index = CDimCoordinate::GetBitIndexForDimension(dimension);
198  this->values[index] = value;
199  this->validDims |= (1 << index);
200  }
201 
206  {
207  int index = CDimCoordinate::GetBitIndexForDimension(dimension);
208  this->validDims &= ~(1 << index);
209  }
210 
212  void Clear()
213  {
214  this->validDims = 0;
215  }
216 
222  void EnumValidDimensions(const std::function<bool(libCZI::DimensionIndex dim, int value)>& func) const
223  {
224  for (auto i = (std::underlying_type<libCZI::DimensionIndex>::type)(libCZI::DimensionIndex::MinDim); i <= (std::underlying_type<libCZI::DimensionIndex>::type)(libCZI::DimensionIndex::MaxDim); ++i)
225  {
227  if ((this->validDims & (1 << bitIndex)) != 0)
228  {
229  if (func((libCZI::DimensionIndex)i, this->values[bitIndex]) != true)
230  break;
231  }
232  }
233  }
234 
237  {
238  int count = 0;
239  for (auto i = (std::underlying_type<libCZI::DimensionIndex>::type)(libCZI::DimensionIndex::MinDim); i <= (std::underlying_type<libCZI::DimensionIndex>::type)(libCZI::DimensionIndex::MaxDim); ++i)
240  {
242  if ((this->validDims & (1 << bitIndex)) != 0)
243  {
244  ++count;
245  }
246  }
247 
248  return count;
249  }
250 
267  static CDimCoordinate Parse(const char* str);
268  public: // IDimCoordinate
269  bool TryGetPosition(libCZI::DimensionIndex dim, int* coordinate) const override
270  {
271  const int index = CDimCoordinate::GetBitIndexForDimension(dim);
272  if ((this->validDims & (1 << index)) != 0)
273  {
274  if (coordinate != nullptr)
275  {
276  *coordinate = this->values[index];
277  }
278 
279  return true;
280  }
281 
282  return false;
283  }
284  };
285 
287  class LIBCZI_API CDimBounds : public CDimBase, public libCZI::IDimBounds
288  {
289  private:
290  std::uint32_t validDims;
291  int start[static_cast<int>(libCZI::DimensionIndex::MaxDim)];
292  int size[static_cast<int>(libCZI::DimensionIndex::MaxDim)];
293  public:
295  CDimBounds() : validDims(0) {}
296 
300  explicit CDimBounds(const IDimBounds* other) : validDims(0)
301  {
302  if (other != nullptr)
303  {
304  for (int i = static_cast<int>(libCZI::DimensionIndex::MinDim); i <= static_cast<int>(libCZI::DimensionIndex::MaxDim); ++i)
305  {
306  int start, size;
307  if (other->TryGetInterval(static_cast<DimensionIndex>(i), &start, &size))
308  {
309  this->Set(static_cast<DimensionIndex>(i), start, size);
310  }
311  }
312  }
313  }
314 
317  CDimBounds(std::initializer_list<DimensionAndStartSize> list) : CDimBounds()
318  {
319  for (auto d : list)
320  {
321  this->Set(d.dimension, d.start, d.size);
322  }
323  }
324 
329  void Set(libCZI::DimensionIndex dimension, int start, int size)
330  {
331  const int index = CDimBounds::GetBitIndexForDimension(dimension);
332  this->start[index] = start;
333  this->size[index] = size;
334  this->validDims |= (1 << index);
335  }
336 
339  void EnumValidDimensions(const std::function<bool(libCZI::DimensionIndex dim, int start, int size)>& func) const
340  {
341  for (int i = static_cast<int>(libCZI::DimensionIndex::MinDim); i <= static_cast<int>(libCZI::DimensionIndex::MaxDim); ++i)
342  {
343  const int bitIndex = CDimBase::GetBitIndexForDimension(static_cast<libCZI::DimensionIndex>(i));
344  if ((this->validDims & (1 << bitIndex)) != 0)
345  {
346  if (func(static_cast<libCZI::DimensionIndex>(i), this->start[bitIndex], this->size[bitIndex]) != true)
347  {
348  break;
349  }
350  }
351  }
352  }
353 
357  {
358  int index = CDimBounds::GetBitIndexForDimension(dimension);
359  this->validDims &= ~(1 << index);
360  }
361 
363  void Clear()
364  {
365  this->validDims = 0;
366  }
367 
371  bool IsEmpty() const
372  {
373  return this->validDims == 0;
374  }
375 
390  static CDimBounds Parse(const char* str);
391 
392  public: // IDimBounds
398  bool TryGetInterval(libCZI::DimensionIndex dim, int* startIndex, int* size) const override
399  {
400  const int index = CDimBounds::GetBitIndexForDimension(dim);
401  if ((this->validDims & (1 << index)) != 0)
402  {
403  if (startIndex != nullptr)
404  {
405  *startIndex = this->start[index];
406  }
407 
408  if (size != nullptr)
409  {
410  *size = this->size[index];
411  }
412 
413  return true;
414  }
415 
416  return false;
417  }
418  };
419 }
Base class containing some commonly used methods.
Definition: libCZI_DimCoordinate.h:134
static std::underlying_type< libCZI::DimensionIndex >::type GetBitIndexForDimension(libCZI::DimensionIndex dim)
Definition: libCZI_DimCoordinate.h:139
Implementation of a class representing an interval (and implementing the libCZI::IDimBounds-interface...
Definition: libCZI_DimCoordinate.h:288
static CDimBounds Parse(const char *str)
CDimBounds(const IDimBounds *other)
Definition: libCZI_DimCoordinate.h:300
void EnumValidDimensions(const std::function< bool(libCZI::DimensionIndex dim, int start, int size)> &func) const
Definition: libCZI_DimCoordinate.h:339
bool TryGetInterval(libCZI::DimensionIndex dim, int *startIndex, int *size) const override
Definition: libCZI_DimCoordinate.h:398
void Set(libCZI::DimensionIndex dimension, int start, int size)
Definition: libCZI_DimCoordinate.h:329
void Clear()
Clears this object to its blank/initial state. All dimensions will be set to invalid.
Definition: libCZI_DimCoordinate.h:363
CDimBounds()
Default constructor - the object will contain no valid dimension.
Definition: libCZI_DimCoordinate.h:295
bool IsEmpty() const
Definition: libCZI_DimCoordinate.h:371
void Clear(libCZI::DimensionIndex dimension)
Definition: libCZI_DimCoordinate.h:356
CDimBounds(std::initializer_list< DimensionAndStartSize > list)
Definition: libCZI_DimCoordinate.h:317
Implementation of a class representing a coordinate (and implementing the IDimCoordinate-interface).
Definition: libCZI_DimCoordinate.h:149
CDimCoordinate(std::initializer_list< DimensionAndValue > list)
Definition: libCZI_DimCoordinate.h:165
CDimCoordinate()
Default constructor which constructs an empty coordinate (no valid dimensions).
Definition: libCZI_DimCoordinate.h:155
static CDimCoordinate Parse(const char *str)
int GetValidDimensionsCount() const
Determine the number the valid dimensions contained in this coordinate.
Definition: libCZI_DimCoordinate.h:236
CDimCoordinate(const libCZI::IDimCoordinate *other)
Definition: libCZI_DimCoordinate.h:176
void Set(libCZI::DimensionIndex dimension, int value)
Definition: libCZI_DimCoordinate.h:195
void EnumValidDimensions(const std::function< bool(libCZI::DimensionIndex dim, int value)> &func) const
Definition: libCZI_DimCoordinate.h:222
void Clear(libCZI::DimensionIndex dimension)
Definition: libCZI_DimCoordinate.h:205
bool TryGetPosition(libCZI::DimensionIndex dim, int *coordinate) const override
Definition: libCZI_DimCoordinate.h:269
void Clear()
Clears the validity of all dimensions.
Definition: libCZI_DimCoordinate.h:212
Interface used to represent an interval (for several dimensions).
Definition: libCZI_DimCoordinate.h:80
virtual bool TryGetInterval(DimensionIndex dim, int *startIndex, int *size) const =0
bool IsValid(DimensionIndex dim) const
Definition: libCZI_DimCoordinate.h:95
Interface used to represent a coordinate (in the space of the dimensions identified by DimensionIndex...
Definition: libCZI_DimCoordinate.h:37
virtual bool TryGetPosition(DimensionIndex dim, int *coordinate) const =0
bool IsValid(DimensionIndex dim) const
Definition: libCZI_DimCoordinate.h:55
int GetNumberOfValidDimensions() const
Definition: libCZI_DimCoordinate.h:63
Definition: libCZI_DimCoordinate.h:104
virtual bool IsContained(int index) const =0
External interfaces, classes, functions and structs are found in the namespace "libCZI".
Definition: libCZI.h:31
DimensionIndex
Values that represent dimension indexes.
Definition: libCZI_DimCoordinate.h:17
@ C
The C-dimension ("channel").
@ MaxDim
This enum must be have the value of the highest (valid) dimension index.
@ Z
The Z-dimension.
@ MinDim
This enum must be have the value of the lowest (valid) dimension index.
@ V
The V-dimension ("view").
@ S
The S-dimension ("scene").
@ B
The B-dimension ("block") - its use is deprecated.
@ T
The T-dimension ("time").
@ H
The H-dimension ("phase").
@ I
The I-dimension ("illumination").
@ R
The R-dimension ("rotation").
@ invalid
Invalid dimension index.
A structure combining a dimension and an interval (defined by a start value and the size).
Definition: libCZI_DimCoordinate.h:126
libCZI::DimensionIndex dimension
The dimension.
Definition: libCZI_DimCoordinate.h:127
int start
The start value.
Definition: libCZI_DimCoordinate.h:128
int size
The size.
Definition: libCZI_DimCoordinate.h:129
A structure combining a dimension and a value.
Definition: libCZI_DimCoordinate.h:119
libCZI::DimensionIndex dimension
The dimension.
Definition: libCZI_DimCoordinate.h:120
int value
The value (for this dimension).
Definition: libCZI_DimCoordinate.h:121