Zivid C++ API 2.12.0+6afd4961-1
Settings.h
Go to the documentation of this file.
1/*******************************************************************************
2 * This file is part of the Zivid API
3 *
4 * Copyright 2015-2024 (C) Zivid AS
5 * All rights reserved.
6 *
7 * Zivid Software License, v1.0
8 *
9 * Redistribution and use in source and binary forms, with or without
10 * modification, are permitted provided that the following conditions are met:
11 *
12 * 1. Redistributions of source code must retain the above copyright notice,
13 * this list of conditions and the following disclaimer.
14 *
15 * 2. Redistributions in binary form must reproduce the above copyright notice,
16 * this list of conditions and the following disclaimer in the documentation
17 * and/or other materials provided with the distribution.
18 *
19 * 3. Neither the name of Zivid AS nor the names of its contributors may be used
20 * to endorse or promote products derived from this software without specific
21 * prior written permission.
22 *
23 * 4. This software, with or without modification, must not be used with any
24 * other 3D camera than from Zivid AS.
25 *
26 * 5. Any software provided in binary form under this license must not be
27 * reverse engineered, decompiled, modified and/or disassembled.
28 *
29 * THIS SOFTWARE IS PROVIDED BY ZIVID AS "AS IS" AND ANY EXPRESS OR IMPLIED
30 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
31 * MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE
32 * DISCLAIMED. IN NO EVENT SHALL ZIVID AS OR CONTRIBUTORS BE LIABLE FOR ANY
33 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
34 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
35 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
36 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
37 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
38 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
39 *
40 * Contact: Zivid Customer Success Team <customersuccess@zivid.com>
41 * Info: http://www.zivid.com
42 ******************************************************************************/
43
44#pragma once
45
46#include <array>
47#include <chrono>
48#include <cmath>
49#include <ctime>
50#include <iomanip>
51#include <memory>
52#include <set>
53#include <sstream>
54#include <string>
55#include <tuple>
56#include <utility>
57#include <vector>
58
64#include "Zivid/Point.h"
65#include "Zivid/Range.h"
66
67#ifdef _MSC_VER
68# pragma warning(push)
69# pragma warning(disable : 4251) // "X needs to have dll-interface to be used by clients of class Y."
70#endif
71
72namespace Zivid
73{
74
76
77 // NOLINTNEXTLINE(clang-analyzer-optin.performance.Padding)
79 {
80 public:
82 static constexpr DataModel::NodeType nodeType = DataModel::NodeType::group;
83
85 static constexpr const char *path{ "" };
86
88 static constexpr const char *name{ "Settings" };
89
91 static constexpr const char *description{
92 R"description(Settings used when capturing with a Zivid camera.)description"
93 };
94
95 static constexpr size_t version{ 24 };
96
97#ifndef NO_DOC
98 template<size_t>
99 struct Version;
100
101 using LatestVersion = Zivid::Settings;
102
103 // Short identifier. This value is not guaranteed to be universally unique
104 // Todo(ZIVID-2808): Move this to internal DataModelExt header
105 static constexpr std::array<uint8_t, 3> binaryId{ 's', 'e', 't' };
106
107#endif
108
110
111 // NOLINTNEXTLINE(clang-analyzer-optin.performance.Padding)
113 {
114 public:
116 static constexpr DataModel::NodeType nodeType = DataModel::NodeType::group;
117
119 static constexpr const char *path{ "Acquisition" };
120
122 static constexpr const char *name{ "Acquisition" };
123
125 static constexpr const char *description{ R"description(Settings for a single acquisition.)description" };
126
130
131 // NOLINTNEXTLINE(clang-analyzer-optin.performance.Padding)
133 {
134 public:
136 static constexpr DataModel::NodeType nodeType = DataModel::NodeType::leafValue;
137
139 static constexpr const char *path{ "Acquisition/Aperture" };
140
142 static constexpr const char *name{ "Aperture" };
143
145 static constexpr const char *description{
146 R"description(Aperture setting for the camera. Specified as an f-number (the ratio of lens focal length to
147the effective aperture diameter).
148)description"
149 };
150
152 using ValueType = double;
153
155 static constexpr Range<double> validRange()
156 {
157 return { 1.4, 32.0 };
158 }
159
161 Aperture() = default;
162
164 explicit constexpr Aperture(double value)
165 : m_opt{ verifyValue(value) }
166 {}
167
172 double value() const;
173
175 bool hasValue() const;
176
178 void reset();
179
181 std::string toString() const;
182
184 bool operator==(const Aperture &other) const
185 {
186 return m_opt == other.m_opt;
187 }
188
190 bool operator!=(const Aperture &other) const
191 {
192 return m_opt != other.m_opt;
193 }
194
196 bool operator<(const Aperture &other) const
197 {
198 return m_opt < other.m_opt;
199 }
200
202 bool operator>(const Aperture &other) const
203 {
204 return m_opt > other.m_opt;
205 }
206
208 bool operator<=(const Aperture &other) const
209 {
210 return m_opt <= other.m_opt;
211 }
212
214 bool operator>=(const Aperture &other) const
215 {
216 return m_opt >= other.m_opt;
217 }
218
220 friend std::ostream &operator<<(std::ostream &stream, const Aperture &value)
221 {
222 return stream << value.toString();
223 }
224
225 private:
226 void setFromString(const std::string &value);
227
228 constexpr ValueType static verifyValue(const ValueType &value)
229 {
230 return validRange().isInRange(value)
231 ? value
232 : throw std::out_of_range{ "Aperture{ " + std::to_string(value) + " } is not in range ["
233 + std::to_string(validRange().min()) + ", "
234 + std::to_string(validRange().max()) + "]" };
235 }
236
237 Zivid::DataModel::Detail::Optional<double> m_opt;
238
239 friend struct DataModel::Detail::Befriend<Aperture>;
240 };
241
253
254 // NOLINTNEXTLINE(clang-analyzer-optin.performance.Padding)
256 {
257 public:
259 static constexpr DataModel::NodeType nodeType = DataModel::NodeType::leafValue;
260
262 static constexpr const char *path{ "Acquisition/Brightness" };
263
265 static constexpr const char *name{ "Brightness" };
266
268 static constexpr const char *description{
269 R"description(Brightness controls the light output from the projector.
270
271Brightness above 1.0 may be needed when the distance between the camera and the scene is large,
272or in case of high levels of ambient lighting.
273
274When brightness is above 1.0 the duty cycle of the camera (the percentage of time the camera
275can capture) will be reduced. The duty cycle in boost mode is 50%. The duty cycle is calculated
276over a 10 second period. This limitation is enforced automatically by the camera. Calling capture
277when the duty cycle limit has been reached will cause the camera to first wait (sleep) for a
278duration of time to cool down, before capture will start.
279)description"
280 };
281
283 using ValueType = double;
284
286 static constexpr Range<double> validRange()
287 {
288 return { 0, 2.5 };
289 }
290
292 Brightness() = default;
293
295 explicit constexpr Brightness(double value)
296 : m_opt{ verifyValue(value) }
297 {}
298
303 double value() const;
304
306 bool hasValue() const;
307
309 void reset();
310
312 std::string toString() const;
313
315 bool operator==(const Brightness &other) const
316 {
317 return m_opt == other.m_opt;
318 }
319
321 bool operator!=(const Brightness &other) const
322 {
323 return m_opt != other.m_opt;
324 }
325
327 bool operator<(const Brightness &other) const
328 {
329 return m_opt < other.m_opt;
330 }
331
333 bool operator>(const Brightness &other) const
334 {
335 return m_opt > other.m_opt;
336 }
337
339 bool operator<=(const Brightness &other) const
340 {
341 return m_opt <= other.m_opt;
342 }
343
345 bool operator>=(const Brightness &other) const
346 {
347 return m_opt >= other.m_opt;
348 }
349
351 friend std::ostream &operator<<(std::ostream &stream, const Brightness &value)
352 {
353 return stream << value.toString();
354 }
355
356 private:
357 void setFromString(const std::string &value);
358
359 constexpr ValueType static verifyValue(const ValueType &value)
360 {
361 return validRange().isInRange(value)
362 ? value
363 : throw std::out_of_range{ "Brightness{ " + std::to_string(value)
364 + " } is not in range [" + std::to_string(validRange().min())
365 + ", " + std::to_string(validRange().max()) + "]" };
366 }
367
368 Zivid::DataModel::Detail::Optional<double> m_opt;
369
370 friend struct DataModel::Detail::Befriend<Brightness>;
371 };
372
374
375 // NOLINTNEXTLINE(clang-analyzer-optin.performance.Padding)
377 {
378 public:
380 static constexpr DataModel::NodeType nodeType = DataModel::NodeType::leafValue;
381
383 static constexpr const char *path{ "Acquisition/ExposureTime" };
384
386 static constexpr const char *name{ "ExposureTime" };
387
389 static constexpr const char *description{
390 R"description(Exposure time for each single image in the measurement. Affects frame rate.)description"
391 };
392
394 using ValueType = std::chrono::microseconds;
395
398 {
399 return { std::chrono::microseconds{ 1677 }, std::chrono::microseconds{ 100000 } };
400 }
401
403 ExposureTime() = default;
404
406 explicit constexpr ExposureTime(std::chrono::microseconds value)
407 : m_opt{ verifyValue(value) }
408 {}
409
414 std::chrono::microseconds value() const;
415
417 bool hasValue() const;
418
420 void reset();
421
423 std::string toString() const;
424
426 bool operator==(const ExposureTime &other) const
427 {
428 return m_opt == other.m_opt;
429 }
430
432 bool operator!=(const ExposureTime &other) const
433 {
434 return m_opt != other.m_opt;
435 }
436
438 bool operator<(const ExposureTime &other) const
439 {
440 return m_opt < other.m_opt;
441 }
442
444 bool operator>(const ExposureTime &other) const
445 {
446 return m_opt > other.m_opt;
447 }
448
450 bool operator<=(const ExposureTime &other) const
451 {
452 return m_opt <= other.m_opt;
453 }
454
456 bool operator>=(const ExposureTime &other) const
457 {
458 return m_opt >= other.m_opt;
459 }
460
462 friend std::ostream &operator<<(std::ostream &stream, const ExposureTime &value)
463 {
464 return stream << value.toString();
465 }
466
467 private:
468 void setFromString(const std::string &value);
469
470 constexpr ValueType static verifyValue(const ValueType &value)
471 {
472 return validRange().isInRange(value)
473 ? value
474 : throw std::out_of_range{ "ExposureTime{ " + std::to_string(value.count())
475 + " } is not in range ["
476 + std::to_string(validRange().min().count()) + ", "
477 + std::to_string(validRange().max().count()) + "]" };
478 }
479
480 Zivid::DataModel::Detail::Optional<std::chrono::microseconds> m_opt;
481
482 friend struct DataModel::Detail::Befriend<ExposureTime>;
483 };
484
486
487 // NOLINTNEXTLINE(clang-analyzer-optin.performance.Padding)
489 {
490 public:
492 static constexpr DataModel::NodeType nodeType = DataModel::NodeType::leafValue;
493
495 static constexpr const char *path{ "Acquisition/Gain" };
496
498 static constexpr const char *name{ "Gain" };
499
501 static constexpr const char *description{ R"description(Analog gain in the camera.)description" };
502
504 using ValueType = double;
505
507 static constexpr Range<double> validRange()
508 {
509 return { 1, 16 };
510 }
511
513 Gain() = default;
514
516 explicit constexpr Gain(double value)
517 : m_opt{ verifyValue(value) }
518 {}
519
524 double value() const;
525
527 bool hasValue() const;
528
530 void reset();
531
533 std::string toString() const;
534
536 bool operator==(const Gain &other) const
537 {
538 return m_opt == other.m_opt;
539 }
540
542 bool operator!=(const Gain &other) const
543 {
544 return m_opt != other.m_opt;
545 }
546
548 bool operator<(const Gain &other) const
549 {
550 return m_opt < other.m_opt;
551 }
552
554 bool operator>(const Gain &other) const
555 {
556 return m_opt > other.m_opt;
557 }
558
560 bool operator<=(const Gain &other) const
561 {
562 return m_opt <= other.m_opt;
563 }
564
566 bool operator>=(const Gain &other) const
567 {
568 return m_opt >= other.m_opt;
569 }
570
572 friend std::ostream &operator<<(std::ostream &stream, const Gain &value)
573 {
574 return stream << value.toString();
575 }
576
577 private:
578 void setFromString(const std::string &value);
579
580 constexpr ValueType static verifyValue(const ValueType &value)
581 {
582 return validRange().isInRange(value)
583 ? value
584 : throw std::out_of_range{ "Gain{ " + std::to_string(value) + " } is not in range ["
585 + std::to_string(validRange().min()) + ", "
586 + std::to_string(validRange().max()) + "]" };
587 }
588
589 Zivid::DataModel::Detail::Optional<double> m_opt;
590
591 friend struct DataModel::Detail::Befriend<Gain>;
592 };
593
594 using Descendants = std::tuple<
599
602
617#ifndef NO_DOC
618 template<
619 typename... Args,
620 typename std::enable_if<sizeof...(Args) >= 1, int>::type = 0,
621 typename std::enable_if<
622 Zivid::Detail::TypeTraits::AllArgsAreInTuple<Descendants, typename std::decay<Args>::type...>::
623 value,
624 int>::type = 0>
625#else
626 template<typename... Args>
627#endif
628 explicit Acquisition(Args &&...args)
629 {
630 using namespace Zivid::Detail::TypeTraits;
631
632 static_assert(
633 AllArgsDecayedAreUnique<Args...>::value,
634 "Found duplicate types among the arguments passed to Acquisition(...). "
635 "Types should be listed at most once.");
636
637 set(std::forward<Args>(args)...);
638 }
639
653#ifndef NO_DOC
654 template<typename... Args, typename std::enable_if<sizeof...(Args) >= 2, int>::type = 0>
655#else
656 template<typename... Args>
657#endif
658 void set(Args &&...args)
659 {
660 using namespace Zivid::Detail::TypeTraits;
661
662 using AllArgsAreDescendantNodes = AllArgsAreInTuple<Descendants, typename std::decay<Args>::type...>;
663 static_assert(
664 AllArgsAreDescendantNodes::value, "All arguments passed to set(...) must be descendant nodes.");
665
666 static_assert(
667 AllArgsDecayedAreUnique<Args...>::value,
668 "Found duplicate types among the arguments passed to set(...). "
669 "Types should be listed at most once.");
670
671 Zivid::DataModel::Detail::invokeSetWithEachArgument(*this, std::forward<Args>(args)...);
672 }
673
688#ifndef NO_DOC
689 template<typename... Args, typename std::enable_if<sizeof...(Args) >= 1, int>::type = 0>
690#else
691 template<typename... Args>
692#endif
693 Acquisition copyWith(Args &&...args) const
694 {
695 using namespace Zivid::Detail::TypeTraits;
696
697 using AllArgsAreDescendantNodes = AllArgsAreInTuple<Descendants, typename std::decay<Args>::type...>;
698 static_assert(
699 AllArgsAreDescendantNodes::value,
700 "All arguments passed to copyWith(...) must be descendant nodes.");
701
702 static_assert(
703 AllArgsDecayedAreUnique<Args...>::value,
704 "Found duplicate types among the arguments passed to copyWith(...). "
705 "Types should be listed at most once.");
706
707 auto copy{ *this };
708 copy.set(std::forward<Args>(args)...);
709 return copy;
710 }
711
713 const Aperture &aperture() const
714 {
715 return m_aperture;
716 }
717
720 {
721 return m_aperture;
722 }
723
725 Acquisition &set(const Aperture &value)
726 {
727 m_aperture = value;
728 return *this;
729 }
730
732 const Brightness &brightness() const
733 {
734 return m_brightness;
735 }
736
739 {
740 return m_brightness;
741 }
742
745 {
746 m_brightness = value;
747 return *this;
748 }
749
752 {
753 return m_exposureTime;
754 }
755
758 {
759 return m_exposureTime;
760 }
761
764 {
765 m_exposureTime = value;
766 return *this;
767 }
768
770 const Gain &gain() const
771 {
772 return m_gain;
773 }
774
777 {
778 return m_gain;
779 }
780
782 Acquisition &set(const Gain &value)
783 {
784 m_gain = value;
785 return *this;
786 }
787
788 template<
789 typename T,
790 typename std::enable_if<std::is_same<T, Settings::Acquisition::Aperture>::value, int>::type = 0>
792 {
793 return m_aperture;
794 }
795
796 template<
797 typename T,
798 typename std::enable_if<std::is_same<T, Settings::Acquisition::Brightness>::value, int>::type = 0>
800 {
801 return m_brightness;
802 }
803
804 template<
805 typename T,
806 typename std::enable_if<std::is_same<T, Settings::Acquisition::ExposureTime>::value, int>::type = 0>
808 {
809 return m_exposureTime;
810 }
811
812 template<
813 typename T,
814 typename std::enable_if<std::is_same<T, Settings::Acquisition::Gain>::value, int>::type = 0>
816 {
817 return m_gain;
818 }
819
820 template<size_t i, typename std::enable_if<i == 0, int>::type = 0>
822 {
823 return m_aperture;
824 }
825
826 template<size_t i, typename std::enable_if<i == 1, int>::type = 0>
828 {
829 return m_brightness;
830 }
831
832 template<size_t i, typename std::enable_if<i == 2, int>::type = 0>
834 {
835 return m_exposureTime;
836 }
837
838 template<size_t i, typename std::enable_if<i == 3, int>::type = 0>
840 {
841 return m_gain;
842 }
843
845 template<typename F>
846 void forEach(const F &f) const
847 {
848 f(m_aperture);
849 f(m_brightness);
850 f(m_exposureTime);
851 f(m_gain);
852 }
853
855 template<typename F>
856 void forEach(const F &f)
857 {
858 f(m_aperture);
859 f(m_brightness);
860 f(m_exposureTime);
861 f(m_gain);
862 }
863
865 bool operator==(const Acquisition &other) const;
866
868 bool operator!=(const Acquisition &other) const;
869
871 std::string toString() const;
872
874 friend std::ostream &operator<<(std::ostream &stream, const Acquisition &value)
875 {
876 return stream << value.toString();
877 }
878
879 private:
880 void setFromString(const std::string &value);
881
882 void setFromString(const std::string &fullPath, const std::string &value);
883
884 std::string getString(const std::string &fullPath) const;
885
886 Aperture m_aperture;
887 Brightness m_brightness;
888 ExposureTime m_exposureTime;
889 Gain m_gain;
890
891 friend struct DataModel::Detail::Befriend<Acquisition>;
892 };
893
895
896 // NOLINTNEXTLINE(clang-analyzer-optin.performance.Padding)
898 {
899 public:
901 static constexpr DataModel::NodeType nodeType = DataModel::NodeType::leafDataModelList;
902
904 static constexpr const char *path{ "Acquisitions" };
905
907 static constexpr const char *name{ "Acquisitions" };
908
910 static constexpr const char *description{ R"description(List of Acquisition objects.)description" };
911
913 using ValueType = std::vector<Settings::Acquisition>;
914
917 {
918 return { 0, std::numeric_limits<ValueType::size_type>::max() };
919 }
920
922 Acquisitions() = default;
923
925 explicit Acquisitions(std::vector<Settings::Acquisition> value)
926 : m_value{ std::move(value) }
927 {}
928
930 explicit Acquisitions(std::initializer_list<Settings::Acquisition> value)
931 : Acquisitions{ ValueType{ value } }
932 {}
933
935 const std::vector<Settings::Acquisition> &value() const;
936
938 std::string toString() const;
939
941 std::size_t size() const noexcept;
942
944 bool isEmpty() const noexcept;
945
951 template<typename... Args>
952 void emplaceBack(Args &&...args)
953 {
954 m_value.emplace_back(std::forward<Args>(args)...);
955 }
956
962 Settings::Acquisition &at(std::size_t pos);
963
969 const Settings::Acquisition &at(std::size_t pos) const;
970
977
983 const Settings::Acquisition &operator[](std::size_t pos) const;
984
986 template<typename F>
987 void forEach(const F &f)
988 {
989 for(auto &child : m_value)
990 {
991 f(child);
992 }
993 }
994
996 template<typename F>
997 void forEach(const F &f) const
998 {
999 for(const auto &child : m_value)
1000 {
1001 f(child);
1002 }
1003 }
1004
1006 using Iterator = std::vector<Settings::Acquisition>::iterator;
1007
1009 Iterator begin() noexcept;
1010
1012 Iterator end() noexcept;
1013
1015 using ConstIterator = std::vector<Settings::Acquisition>::const_iterator;
1016
1018 ConstIterator begin() const noexcept;
1019
1021 ConstIterator end() const noexcept;
1022
1024 ConstIterator cbegin() const noexcept;
1025
1027 ConstIterator cend() const noexcept;
1028
1030 bool operator==(const Acquisitions &other) const
1031 {
1032 return m_value == other.m_value;
1033 }
1034
1036 bool operator!=(const Acquisitions &other) const
1037 {
1038 return m_value != other.m_value;
1039 }
1040
1042 friend std::ostream &operator<<(std::ostream &stream, const Acquisitions &value)
1043 {
1044 return stream << value.toString();
1045 }
1046
1047 private:
1048 void setFromString(const std::string &value);
1049
1050 std::vector<Settings::Acquisition> m_value{};
1051
1052 friend struct DataModel::Detail::Befriend<Acquisitions>;
1053 };
1054
1062
1063 // NOLINTNEXTLINE(clang-analyzer-optin.performance.Padding)
1065 {
1066 public:
1068 static constexpr DataModel::NodeType nodeType = DataModel::NodeType::group;
1069
1071 static constexpr const char *path{ "Diagnostics" };
1072
1074 static constexpr const char *name{ "Diagnostics" };
1075
1077 static constexpr const char *description{
1078 R"description(When Diagnostics is enabled, additional diagnostic data is recorded during capture and included when saving
1079the frame to a .zdf file. This enables Zivid's Customer Success team to provide better assistance and more
1080thorough troubleshooting.
1081
1082Enabling Diagnostics increases the capture time and the RAM usage. It will also increase the size of the
1083.zdf file. It is recommended to enable Diagnostics only when reporting issues to Zivid's support team.
1084)description"
1085 };
1086
1088
1089 // NOLINTNEXTLINE(clang-analyzer-optin.performance.Padding)
1091 {
1092 public:
1094 static constexpr DataModel::NodeType nodeType = DataModel::NodeType::leafValue;
1095
1097 static constexpr const char *path{ "Diagnostics/Enabled" };
1098
1100 static constexpr const char *name{ "Enabled" };
1101
1103 static constexpr const char *description{ R"description(Enable or disable diagnostics.)description" };
1104
1106 using ValueType = bool;
1107 static const Enabled yes;
1108 static const Enabled no;
1109
1111 static std::set<bool> validValues()
1112 {
1113 return { false, true };
1114 }
1115
1117 Enabled() = default;
1118
1120 explicit constexpr Enabled(bool value)
1121 : m_opt{ value }
1122 {}
1123
1128 bool value() const;
1129
1131 bool hasValue() const;
1132
1134 void reset();
1135
1137 std::string toString() const;
1138
1140 bool operator==(const Enabled &other) const
1141 {
1142 return m_opt == other.m_opt;
1143 }
1144
1146 bool operator!=(const Enabled &other) const
1147 {
1148 return m_opt != other.m_opt;
1149 }
1150
1152 friend std::ostream &operator<<(std::ostream &stream, const Enabled &value)
1153 {
1154 return stream << value.toString();
1155 }
1156
1157 private:
1158 void setFromString(const std::string &value);
1159
1160 Zivid::DataModel::Detail::Optional<bool> m_opt;
1161
1162 friend struct DataModel::Detail::Befriend<Enabled>;
1163 };
1164
1165 using Descendants = std::tuple<Settings::Diagnostics::Enabled>;
1166
1169
1181#ifndef NO_DOC
1182 template<
1183 typename... Args,
1184 typename std::enable_if<sizeof...(Args) >= 1, int>::type = 0,
1185 typename std::enable_if<
1186 Zivid::Detail::TypeTraits::AllArgsAreInTuple<Descendants, typename std::decay<Args>::type...>::
1187 value,
1188 int>::type = 0>
1189#else
1190 template<typename... Args>
1191#endif
1192 explicit Diagnostics(Args &&...args)
1193 {
1194 using namespace Zivid::Detail::TypeTraits;
1195
1196 static_assert(
1197 AllArgsDecayedAreUnique<Args...>::value,
1198 "Found duplicate types among the arguments passed to Diagnostics(...). "
1199 "Types should be listed at most once.");
1200
1201 set(std::forward<Args>(args)...);
1202 }
1203
1214#ifndef NO_DOC
1215 template<typename... Args, typename std::enable_if<sizeof...(Args) >= 2, int>::type = 0>
1216#else
1217 template<typename... Args>
1218#endif
1219 void set(Args &&...args)
1220 {
1221 using namespace Zivid::Detail::TypeTraits;
1222
1223 using AllArgsAreDescendantNodes = AllArgsAreInTuple<Descendants, typename std::decay<Args>::type...>;
1224 static_assert(
1225 AllArgsAreDescendantNodes::value, "All arguments passed to set(...) must be descendant nodes.");
1226
1227 static_assert(
1228 AllArgsDecayedAreUnique<Args...>::value,
1229 "Found duplicate types among the arguments passed to set(...). "
1230 "Types should be listed at most once.");
1231
1232 Zivid::DataModel::Detail::invokeSetWithEachArgument(*this, std::forward<Args>(args)...);
1233 }
1234
1246#ifndef NO_DOC
1247 template<typename... Args, typename std::enable_if<sizeof...(Args) >= 1, int>::type = 0>
1248#else
1249 template<typename... Args>
1250#endif
1251 Diagnostics copyWith(Args &&...args) const
1252 {
1253 using namespace Zivid::Detail::TypeTraits;
1254
1255 using AllArgsAreDescendantNodes = AllArgsAreInTuple<Descendants, typename std::decay<Args>::type...>;
1256 static_assert(
1257 AllArgsAreDescendantNodes::value,
1258 "All arguments passed to copyWith(...) must be descendant nodes.");
1259
1260 static_assert(
1261 AllArgsDecayedAreUnique<Args...>::value,
1262 "Found duplicate types among the arguments passed to copyWith(...). "
1263 "Types should be listed at most once.");
1264
1265 auto copy{ *this };
1266 copy.set(std::forward<Args>(args)...);
1267 return copy;
1268 }
1269
1271 const Enabled &isEnabled() const
1272 {
1273 return m_enabled;
1274 }
1275
1278 {
1279 return m_enabled;
1280 }
1281
1283 Diagnostics &set(const Enabled &value)
1284 {
1285 m_enabled = value;
1286 return *this;
1287 }
1288
1289 template<
1290 typename T,
1291 typename std::enable_if<std::is_same<T, Settings::Diagnostics::Enabled>::value, int>::type = 0>
1293 {
1294 return m_enabled;
1295 }
1296
1297 template<size_t i, typename std::enable_if<i == 0, int>::type = 0>
1299 {
1300 return m_enabled;
1301 }
1302
1304 template<typename F>
1305 void forEach(const F &f) const
1306 {
1307 f(m_enabled);
1308 }
1309
1311 template<typename F>
1312 void forEach(const F &f)
1313 {
1314 f(m_enabled);
1315 }
1316
1318 bool operator==(const Diagnostics &other) const;
1319
1321 bool operator!=(const Diagnostics &other) const;
1322
1324 std::string toString() const;
1325
1327 friend std::ostream &operator<<(std::ostream &stream, const Diagnostics &value)
1328 {
1329 return stream << value.toString();
1330 }
1331
1332 private:
1333 void setFromString(const std::string &value);
1334
1335 void setFromString(const std::string &fullPath, const std::string &value);
1336
1337 std::string getString(const std::string &fullPath) const;
1338
1339 Enabled m_enabled;
1340
1341 friend struct DataModel::Detail::Befriend<Diagnostics>;
1342 };
1343
1361
1362 // NOLINTNEXTLINE(clang-analyzer-optin.performance.Padding)
1364 {
1365 public:
1367 static constexpr DataModel::NodeType nodeType = DataModel::NodeType::leafValue;
1368
1370 static constexpr const char *path{ "Engine" };
1371
1373 static constexpr const char *name{ "Engine" };
1374
1376 static constexpr const char *description{ R"description(Set the Zivid Vision Engine to use.
1377
1378The Phase Engine is the fastest choice in terms of both acquisition time and total capture
1379time, and is a good compromise between quality and speed. The Phase Engine is recommended for
1380objects that are diffuse, opaque, and slightly specular, and is suitable for applications in
1381logistics such as parcel induction.
1382
1383The Stripe Engine is built for exceptional point cloud quality in scenes with highly specular
1384reflective objects. This makes the engine suitable for applications such as factory automation,
1385manufacturing, and bin picking. Additional acquisition and processing time are required for
1386the Stripe Engine.
1387
1388The Omni Engine is built for exceptional point cloud quality on all scenes, including scenes
1389with extremely specular reflective objects, as well as transparent objects. This makes the Omni
1390Engine suitable for applications such as piece picking. Same as for the Stripe Engine, it trades
1391off speed for quality. The Omni Engine is only available for Zivid 2+.
1392)description" };
1393
1395 enum class ValueType
1396 {
1397 phase,
1398 stripe,
1399 omni
1400 };
1401 static const Engine phase;
1402 static const Engine stripe;
1403 static const Engine omni;
1404
1406 static std::set<ValueType> validValues()
1407 {
1408 return { ValueType::phase, ValueType::stripe, ValueType::omni };
1409 }
1410
1412 Engine() = default;
1413
1415 explicit constexpr Engine(ValueType value)
1416 : m_opt{ verifyValue(value) }
1417 {}
1418
1424
1426 bool hasValue() const;
1427
1429 void reset();
1430
1432 std::string toString() const;
1433
1435 friend std::ostream &operator<<(std::ostream &stream, const Engine::ValueType &value)
1436 {
1437 return stream << Engine{ value }.toString();
1438 }
1439
1441 bool operator==(const Engine &other) const
1442 {
1443 return m_opt == other.m_opt;
1444 }
1445
1447 bool operator!=(const Engine &other) const
1448 {
1449 return m_opt != other.m_opt;
1450 }
1451
1453 friend std::ostream &operator<<(std::ostream &stream, const Engine &value)
1454 {
1455 return stream << value.toString();
1456 }
1457
1458 private:
1459 void setFromString(const std::string &value);
1460
1461 constexpr ValueType static verifyValue(const ValueType &value)
1462 {
1463 return value == ValueType::phase || value == ValueType::stripe || value == ValueType::omni
1464 ? value
1465 : throw std::invalid_argument{
1466 "Invalid value: Engine{ "
1467 + std::to_string(static_cast<std::underlying_type<ValueType>::type>(value)) + " }"
1468 };
1469 }
1470
1471 Zivid::DataModel::Detail::Optional<ValueType> m_opt;
1472
1473 friend struct DataModel::Detail::Befriend<Engine>;
1474 };
1475
1477
1478 // NOLINTNEXTLINE(clang-analyzer-optin.performance.Padding)
1480 {
1481 public:
1483 static constexpr DataModel::NodeType nodeType = DataModel::NodeType::group;
1484
1486 static constexpr const char *path{ "Processing" };
1487
1489 static constexpr const char *name{ "Processing" };
1490
1492 static constexpr const char *description{
1493 R"description(Settings related to processing of a capture, including filters and color balance.)description"
1494 };
1495
1497
1498 // NOLINTNEXTLINE(clang-analyzer-optin.performance.Padding)
1500 {
1501 public:
1503 static constexpr DataModel::NodeType nodeType = DataModel::NodeType::group;
1504
1506 static constexpr const char *path{ "Processing/Color" };
1507
1509 static constexpr const char *name{ "Color" };
1510
1512 static constexpr const char *description{ R"description(Color settings.)description" };
1513
1515
1516 // NOLINTNEXTLINE(clang-analyzer-optin.performance.Padding)
1518 {
1519 public:
1521 static constexpr DataModel::NodeType nodeType = DataModel::NodeType::group;
1522
1524 static constexpr const char *path{ "Processing/Color/Balance" };
1525
1527 static constexpr const char *name{ "Balance" };
1528
1530 static constexpr const char *description{ R"description(Color balance settings.)description" };
1531
1533
1534 // NOLINTNEXTLINE(clang-analyzer-optin.performance.Padding)
1536 {
1537 public:
1539 static constexpr DataModel::NodeType nodeType = DataModel::NodeType::leafValue;
1540
1542 static constexpr const char *path{ "Processing/Color/Balance/Blue" };
1543
1545 static constexpr const char *name{ "Blue" };
1546
1548 static constexpr const char *description{
1549 R"description(Digital gain applied to blue channel.)description"
1550 };
1551
1553 using ValueType = double;
1554
1556 static constexpr Range<double> validRange()
1557 {
1558 return { 1.0, 8.0 };
1559 }
1560
1562 Blue() = default;
1563
1565 explicit constexpr Blue(double value)
1566 : m_opt{ verifyValue(value) }
1567 {}
1568
1573 double value() const;
1574
1576 bool hasValue() const;
1577
1579 void reset();
1580
1582 std::string toString() const;
1583
1585 bool operator==(const Blue &other) const
1586 {
1587 return m_opt == other.m_opt;
1588 }
1589
1591 bool operator!=(const Blue &other) const
1592 {
1593 return m_opt != other.m_opt;
1594 }
1595
1597 bool operator<(const Blue &other) const
1598 {
1599 return m_opt < other.m_opt;
1600 }
1601
1603 bool operator>(const Blue &other) const
1604 {
1605 return m_opt > other.m_opt;
1606 }
1607
1609 bool operator<=(const Blue &other) const
1610 {
1611 return m_opt <= other.m_opt;
1612 }
1613
1615 bool operator>=(const Blue &other) const
1616 {
1617 return m_opt >= other.m_opt;
1618 }
1619
1621 friend std::ostream &operator<<(std::ostream &stream, const Blue &value)
1622 {
1623 return stream << value.toString();
1624 }
1625
1626 private:
1627 void setFromString(const std::string &value);
1628
1629 constexpr ValueType static verifyValue(const ValueType &value)
1630 {
1631 return validRange().isInRange(value)
1632 ? value
1633 : throw std::out_of_range{ "Blue{ " + std::to_string(value)
1634 + " } is not in range ["
1635 + std::to_string(validRange().min()) + ", "
1636 + std::to_string(validRange().max()) + "]" };
1637 }
1638
1639 Zivid::DataModel::Detail::Optional<double> m_opt;
1640
1641 friend struct DataModel::Detail::Befriend<Blue>;
1642 };
1643
1645
1646 // NOLINTNEXTLINE(clang-analyzer-optin.performance.Padding)
1648 {
1649 public:
1651 static constexpr DataModel::NodeType nodeType = DataModel::NodeType::leafValue;
1652
1654 static constexpr const char *path{ "Processing/Color/Balance/Green" };
1655
1657 static constexpr const char *name{ "Green" };
1658
1660 static constexpr const char *description{
1661 R"description(Digital gain applied to green channel.)description"
1662 };
1663
1665 using ValueType = double;
1666
1668 static constexpr Range<double> validRange()
1669 {
1670 return { 1.0, 8.0 };
1671 }
1672
1674 Green() = default;
1675
1677 explicit constexpr Green(double value)
1678 : m_opt{ verifyValue(value) }
1679 {}
1680
1685 double value() const;
1686
1688 bool hasValue() const;
1689
1691 void reset();
1692
1694 std::string toString() const;
1695
1697 bool operator==(const Green &other) const
1698 {
1699 return m_opt == other.m_opt;
1700 }
1701
1703 bool operator!=(const Green &other) const
1704 {
1705 return m_opt != other.m_opt;
1706 }
1707
1709 bool operator<(const Green &other) const
1710 {
1711 return m_opt < other.m_opt;
1712 }
1713
1715 bool operator>(const Green &other) const
1716 {
1717 return m_opt > other.m_opt;
1718 }
1719
1721 bool operator<=(const Green &other) const
1722 {
1723 return m_opt <= other.m_opt;
1724 }
1725
1727 bool operator>=(const Green &other) const
1728 {
1729 return m_opt >= other.m_opt;
1730 }
1731
1733 friend std::ostream &operator<<(std::ostream &stream, const Green &value)
1734 {
1735 return stream << value.toString();
1736 }
1737
1738 private:
1739 void setFromString(const std::string &value);
1740
1741 constexpr ValueType static verifyValue(const ValueType &value)
1742 {
1743 return validRange().isInRange(value)
1744 ? value
1745 : throw std::out_of_range{ "Green{ " + std::to_string(value)
1746 + " } is not in range ["
1747 + std::to_string(validRange().min()) + ", "
1748 + std::to_string(validRange().max()) + "]" };
1749 }
1750
1751 Zivid::DataModel::Detail::Optional<double> m_opt;
1752
1753 friend struct DataModel::Detail::Befriend<Green>;
1754 };
1755
1757
1758 // NOLINTNEXTLINE(clang-analyzer-optin.performance.Padding)
1760 {
1761 public:
1763 static constexpr DataModel::NodeType nodeType = DataModel::NodeType::leafValue;
1764
1766 static constexpr const char *path{ "Processing/Color/Balance/Red" };
1767
1769 static constexpr const char *name{ "Red" };
1770
1772 static constexpr const char *description{
1773 R"description(Digital gain applied to red channel.)description"
1774 };
1775
1777 using ValueType = double;
1778
1780 static constexpr Range<double> validRange()
1781 {
1782 return { 1.0, 8.0 };
1783 }
1784
1786 Red() = default;
1787
1789 explicit constexpr Red(double value)
1790 : m_opt{ verifyValue(value) }
1791 {}
1792
1797 double value() const;
1798
1800 bool hasValue() const;
1801
1803 void reset();
1804
1806 std::string toString() const;
1807
1809 bool operator==(const Red &other) const
1810 {
1811 return m_opt == other.m_opt;
1812 }
1813
1815 bool operator!=(const Red &other) const
1816 {
1817 return m_opt != other.m_opt;
1818 }
1819
1821 bool operator<(const Red &other) const
1822 {
1823 return m_opt < other.m_opt;
1824 }
1825
1827 bool operator>(const Red &other) const
1828 {
1829 return m_opt > other.m_opt;
1830 }
1831
1833 bool operator<=(const Red &other) const
1834 {
1835 return m_opt <= other.m_opt;
1836 }
1837
1839 bool operator>=(const Red &other) const
1840 {
1841 return m_opt >= other.m_opt;
1842 }
1843
1845 friend std::ostream &operator<<(std::ostream &stream, const Red &value)
1846 {
1847 return stream << value.toString();
1848 }
1849
1850 private:
1851 void setFromString(const std::string &value);
1852
1853 constexpr ValueType static verifyValue(const ValueType &value)
1854 {
1855 return validRange().isInRange(value)
1856 ? value
1857 : throw std::out_of_range{ "Red{ " + std::to_string(value)
1858 + " } is not in range ["
1859 + std::to_string(validRange().min()) + ", "
1860 + std::to_string(validRange().max()) + "]" };
1861 }
1862
1863 Zivid::DataModel::Detail::Optional<double> m_opt;
1864
1865 friend struct DataModel::Detail::Befriend<Red>;
1866 };
1867
1868 using Descendants = std::tuple<
1872
1875
1889#ifndef NO_DOC
1890 template<
1891 typename... Args,
1892 typename std::enable_if<sizeof...(Args) >= 1, int>::type = 0,
1893 typename std::enable_if<
1894 Zivid::Detail::TypeTraits::
1895 AllArgsAreInTuple<Descendants, typename std::decay<Args>::type...>::value,
1896 int>::type = 0>
1897#else
1898 template<typename... Args>
1899#endif
1900 explicit Balance(Args &&...args)
1901 {
1902 using namespace Zivid::Detail::TypeTraits;
1903
1904 static_assert(
1905 AllArgsDecayedAreUnique<Args...>::value,
1906 "Found duplicate types among the arguments passed to Balance(...). "
1907 "Types should be listed at most once.");
1908
1909 set(std::forward<Args>(args)...);
1910 }
1911
1924#ifndef NO_DOC
1925 template<typename... Args, typename std::enable_if<sizeof...(Args) >= 2, int>::type = 0>
1926#else
1927 template<typename... Args>
1928#endif
1929 void set(Args &&...args)
1930 {
1931 using namespace Zivid::Detail::TypeTraits;
1932
1933 using AllArgsAreDescendantNodes =
1934 AllArgsAreInTuple<Descendants, typename std::decay<Args>::type...>;
1935 static_assert(
1936 AllArgsAreDescendantNodes::value,
1937 "All arguments passed to set(...) must be descendant nodes.");
1938
1939 static_assert(
1940 AllArgsDecayedAreUnique<Args...>::value,
1941 "Found duplicate types among the arguments passed to set(...). "
1942 "Types should be listed at most once.");
1943
1944 Zivid::DataModel::Detail::invokeSetWithEachArgument(*this, std::forward<Args>(args)...);
1945 }
1946
1960#ifndef NO_DOC
1961 template<typename... Args, typename std::enable_if<sizeof...(Args) >= 1, int>::type = 0>
1962#else
1963 template<typename... Args>
1964#endif
1965 Balance copyWith(Args &&...args) const
1966 {
1967 using namespace Zivid::Detail::TypeTraits;
1968
1969 using AllArgsAreDescendantNodes =
1970 AllArgsAreInTuple<Descendants, typename std::decay<Args>::type...>;
1971 static_assert(
1972 AllArgsAreDescendantNodes::value,
1973 "All arguments passed to copyWith(...) must be descendant nodes.");
1974
1975 static_assert(
1976 AllArgsDecayedAreUnique<Args...>::value,
1977 "Found duplicate types among the arguments passed to copyWith(...). "
1978 "Types should be listed at most once.");
1979
1980 auto copy{ *this };
1981 copy.set(std::forward<Args>(args)...);
1982 return copy;
1983 }
1984
1986 const Blue &blue() const
1987 {
1988 return m_blue;
1989 }
1990
1993 {
1994 return m_blue;
1995 }
1996
1998 Balance &set(const Blue &value)
1999 {
2000 m_blue = value;
2001 return *this;
2002 }
2003
2005 const Green &green() const
2006 {
2007 return m_green;
2008 }
2009
2012 {
2013 return m_green;
2014 }
2015
2017 Balance &set(const Green &value)
2018 {
2019 m_green = value;
2020 return *this;
2021 }
2022
2024 const Red &red() const
2025 {
2026 return m_red;
2027 }
2028
2031 {
2032 return m_red;
2033 }
2034
2036 Balance &set(const Red &value)
2037 {
2038 m_red = value;
2039 return *this;
2040 }
2041
2042 template<
2043 typename T,
2044 typename std::enable_if<
2045 std::is_same<T, Settings::Processing::Color::Balance::Blue>::value,
2046 int>::type = 0>
2048 {
2049 return m_blue;
2050 }
2051
2052 template<
2053 typename T,
2054 typename std::enable_if<
2055 std::is_same<T, Settings::Processing::Color::Balance::Green>::value,
2056 int>::type = 0>
2058 {
2059 return m_green;
2060 }
2061
2062 template<
2063 typename T,
2064 typename std::
2065 enable_if<std::is_same<T, Settings::Processing::Color::Balance::Red>::value, int>::type = 0>
2067 {
2068 return m_red;
2069 }
2070
2071 template<size_t i, typename std::enable_if<i == 0, int>::type = 0>
2073 {
2074 return m_blue;
2075 }
2076
2077 template<size_t i, typename std::enable_if<i == 1, int>::type = 0>
2079 {
2080 return m_green;
2081 }
2082
2083 template<size_t i, typename std::enable_if<i == 2, int>::type = 0>
2085 {
2086 return m_red;
2087 }
2088
2090 template<typename F>
2091 void forEach(const F &f) const
2092 {
2093 f(m_blue);
2094 f(m_green);
2095 f(m_red);
2096 }
2097
2099 template<typename F>
2100 void forEach(const F &f)
2101 {
2102 f(m_blue);
2103 f(m_green);
2104 f(m_red);
2105 }
2106
2108 bool operator==(const Balance &other) const;
2109
2111 bool operator!=(const Balance &other) const;
2112
2114 std::string toString() const;
2115
2117 friend std::ostream &operator<<(std::ostream &stream, const Balance &value)
2118 {
2119 return stream << value.toString();
2120 }
2121
2122 private:
2123 void setFromString(const std::string &value);
2124
2125 void setFromString(const std::string &fullPath, const std::string &value);
2126
2127 std::string getString(const std::string &fullPath) const;
2128
2129 Blue m_blue;
2130 Green m_green;
2131 Red m_red;
2132
2133 friend struct DataModel::Detail::Befriend<Balance>;
2134 };
2135
2137
2138 // NOLINTNEXTLINE(clang-analyzer-optin.performance.Padding)
2140 {
2141 public:
2143 static constexpr DataModel::NodeType nodeType = DataModel::NodeType::group;
2144
2146 static constexpr const char *path{ "Processing/Color/Experimental" };
2147
2149 static constexpr const char *name{ "Experimental" };
2150
2152 static constexpr const char *description{
2153 R"description(Experimental color settings. These may be renamed, moved or deleted in the future.)description"
2154 };
2155
2178
2179 // NOLINTNEXTLINE(clang-analyzer-optin.performance.Padding)
2181 {
2182 public:
2184 static constexpr DataModel::NodeType nodeType = DataModel::NodeType::leafValue;
2185
2187 static constexpr const char *path{ "Processing/Color/Experimental/Mode" };
2188
2190 static constexpr const char *name{ "Mode" };
2191
2193 static constexpr const char *description{
2194 R"description(This setting controls how the color image is computed.
2195
2196`automatic` is the default option. `automatic` is identical to `useFirstAcquisition` for
2197single-acquisition captures and multi-acquisition captures when all the acquisitions have
2198identical (duplicated) acquisition settings. `automatic` is identical to `toneMapping` for
2199multi-acquisition HDR captures with differing acquisition settings.
2200
2201`useFirstAcquisition` uses the color data acquired from the first acquisition provided. If
2202the capture consists of more than one acquisition, then the remaining acquisitions are not used
2203for the color image. No tone mapping is performed. This option provides the most control of
2204the color image, and the color values will be consistent over repeated captures with the same
2205settings.
2206
2207`toneMapping` uses all the acquisitions to create one merged and normalized color image. For
2208HDR captures the dynamic range of the captured images is usually higher than the 8-bit color
2209image range. `toneMapping` will map the HDR color data to the 8-bit color output range by
2210applying a scaling factor. `toneMapping` can also be used for single-acquisition captures to
2211normalize the captured color image to the full 8-bit output. Note that when using `toneMapping`
2212mode the color values can be inconsistent over repeated captures if you move, add or remove
2213objects in the scene. For the most control over the colors, select the `useFirstAcquisition`
2214mode.
2215)description"
2216 };
2217
2219 enum class ValueType
2220 {
2221 automatic,
2222 useFirstAcquisition,
2223 toneMapping
2224 };
2225 static const Mode automatic;
2227 static const Mode toneMapping;
2228
2230 static std::set<ValueType> validValues()
2231 {
2232 return { ValueType::automatic, ValueType::useFirstAcquisition, ValueType::toneMapping };
2233 }
2234
2236 Mode() = default;
2237
2239 explicit constexpr Mode(ValueType value)
2240 : m_opt{ verifyValue(value) }
2241 {}
2242
2248
2250 bool hasValue() const;
2251
2253 void reset();
2254
2256 std::string toString() const;
2257
2259 friend std::ostream &operator<<(std::ostream &stream, const Mode::ValueType &value)
2260 {
2261 return stream << Mode{ value }.toString();
2262 }
2263
2265 bool operator==(const Mode &other) const
2266 {
2267 return m_opt == other.m_opt;
2268 }
2269
2271 bool operator!=(const Mode &other) const
2272 {
2273 return m_opt != other.m_opt;
2274 }
2275
2277 friend std::ostream &operator<<(std::ostream &stream, const Mode &value)
2278 {
2279 return stream << value.toString();
2280 }
2281
2282 private:
2283 void setFromString(const std::string &value);
2284
2285 constexpr ValueType static verifyValue(const ValueType &value)
2286 {
2287 return value == ValueType::automatic || value == ValueType::useFirstAcquisition
2288 || value == ValueType::toneMapping
2289 ? value
2290 : throw std::invalid_argument{
2291 "Invalid value: Mode{ "
2292 + std::to_string(static_cast<std::underlying_type<ValueType>::type>(value))
2293 + " }"
2294 };
2295 }
2296
2297 Zivid::DataModel::Detail::Optional<ValueType> m_opt;
2298
2299 friend struct DataModel::Detail::Befriend<Mode>;
2300 };
2301
2302 using Descendants = std::tuple<Settings::Processing::Color::Experimental::Mode>;
2303
2306
2318#ifndef NO_DOC
2319 template<
2320 typename... Args,
2321 typename std::enable_if<sizeof...(Args) >= 1, int>::type = 0,
2322 typename std::enable_if<
2323 Zivid::Detail::TypeTraits::
2324 AllArgsAreInTuple<Descendants, typename std::decay<Args>::type...>::value,
2325 int>::type = 0>
2326#else
2327 template<typename... Args>
2328#endif
2329 explicit Experimental(Args &&...args)
2330 {
2331 using namespace Zivid::Detail::TypeTraits;
2332
2333 static_assert(
2334 AllArgsDecayedAreUnique<Args...>::value,
2335 "Found duplicate types among the arguments passed to Experimental(...). "
2336 "Types should be listed at most once.");
2337
2338 set(std::forward<Args>(args)...);
2339 }
2340
2351#ifndef NO_DOC
2352 template<typename... Args, typename std::enable_if<sizeof...(Args) >= 2, int>::type = 0>
2353#else
2354 template<typename... Args>
2355#endif
2356 void set(Args &&...args)
2357 {
2358 using namespace Zivid::Detail::TypeTraits;
2359
2360 using AllArgsAreDescendantNodes =
2361 AllArgsAreInTuple<Descendants, typename std::decay<Args>::type...>;
2362 static_assert(
2363 AllArgsAreDescendantNodes::value,
2364 "All arguments passed to set(...) must be descendant nodes.");
2365
2366 static_assert(
2367 AllArgsDecayedAreUnique<Args...>::value,
2368 "Found duplicate types among the arguments passed to set(...). "
2369 "Types should be listed at most once.");
2370
2371 Zivid::DataModel::Detail::invokeSetWithEachArgument(*this, std::forward<Args>(args)...);
2372 }
2373
2385#ifndef NO_DOC
2386 template<typename... Args, typename std::enable_if<sizeof...(Args) >= 1, int>::type = 0>
2387#else
2388 template<typename... Args>
2389#endif
2390 Experimental copyWith(Args &&...args) const
2391 {
2392 using namespace Zivid::Detail::TypeTraits;
2393
2394 using AllArgsAreDescendantNodes =
2395 AllArgsAreInTuple<Descendants, typename std::decay<Args>::type...>;
2396 static_assert(
2397 AllArgsAreDescendantNodes::value,
2398 "All arguments passed to copyWith(...) must be descendant nodes.");
2399
2400 static_assert(
2401 AllArgsDecayedAreUnique<Args...>::value,
2402 "Found duplicate types among the arguments passed to copyWith(...). "
2403 "Types should be listed at most once.");
2404
2405 auto copy{ *this };
2406 copy.set(std::forward<Args>(args)...);
2407 return copy;
2408 }
2409
2411 const Mode &mode() const
2412 {
2413 return m_mode;
2414 }
2415
2418 {
2419 return m_mode;
2420 }
2421
2423 Experimental &set(const Mode &value)
2424 {
2425 m_mode = value;
2426 return *this;
2427 }
2428
2429 template<
2430 typename T,
2431 typename std::enable_if<
2432 std::is_same<T, Settings::Processing::Color::Experimental::Mode>::value,
2433 int>::type = 0>
2435 {
2436 return m_mode;
2437 }
2438
2439 template<size_t i, typename std::enable_if<i == 0, int>::type = 0>
2441 {
2442 return m_mode;
2443 }
2444
2446 template<typename F>
2447 void forEach(const F &f) const
2448 {
2449 f(m_mode);
2450 }
2451
2453 template<typename F>
2454 void forEach(const F &f)
2455 {
2456 f(m_mode);
2457 }
2458
2460 bool operator==(const Experimental &other) const;
2461
2463 bool operator!=(const Experimental &other) const;
2464
2466 std::string toString() const;
2467
2469 friend std::ostream &operator<<(std::ostream &stream, const Experimental &value)
2470 {
2471 return stream << value.toString();
2472 }
2473
2474 private:
2475 void setFromString(const std::string &value);
2476
2477 void setFromString(const std::string &fullPath, const std::string &value);
2478
2479 std::string getString(const std::string &fullPath) const;
2480
2481 Mode m_mode;
2482
2483 friend struct DataModel::Detail::Befriend<Experimental>;
2484 };
2485
2489
2490 // NOLINTNEXTLINE(clang-analyzer-optin.performance.Padding)
2492 {
2493 public:
2495 static constexpr DataModel::NodeType nodeType = DataModel::NodeType::leafValue;
2496
2498 static constexpr const char *path{ "Processing/Color/Gamma" };
2499
2501 static constexpr const char *name{ "Gamma" };
2502
2504 static constexpr const char *description{
2505 R"description(Gamma applied to the color values. Gamma less than 1 makes the colors brighter, while gamma
2506greater than 1 makes the colors darker.
2507)description"
2508 };
2509
2511 using ValueType = double;
2512
2514 static constexpr Range<double> validRange()
2515 {
2516 return { 0.25, 1.5 };
2517 }
2518
2520 Gamma() = default;
2521
2523 explicit constexpr Gamma(double value)
2524 : m_opt{ verifyValue(value) }
2525 {}
2526
2531 double value() const;
2532
2534 bool hasValue() const;
2535
2537 void reset();
2538
2540 std::string toString() const;
2541
2543 bool operator==(const Gamma &other) const
2544 {
2545 return m_opt == other.m_opt;
2546 }
2547
2549 bool operator!=(const Gamma &other) const
2550 {
2551 return m_opt != other.m_opt;
2552 }
2553
2555 bool operator<(const Gamma &other) const
2556 {
2557 return m_opt < other.m_opt;
2558 }
2559
2561 bool operator>(const Gamma &other) const
2562 {
2563 return m_opt > other.m_opt;
2564 }
2565
2567 bool operator<=(const Gamma &other) const
2568 {
2569 return m_opt <= other.m_opt;
2570 }
2571
2573 bool operator>=(const Gamma &other) const
2574 {
2575 return m_opt >= other.m_opt;
2576 }
2577
2579 friend std::ostream &operator<<(std::ostream &stream, const Gamma &value)
2580 {
2581 return stream << value.toString();
2582 }
2583
2584 private:
2585 void setFromString(const std::string &value);
2586
2587 constexpr ValueType static verifyValue(const ValueType &value)
2588 {
2589 return validRange().isInRange(value)
2590 ? value
2591 : throw std::out_of_range{ "Gamma{ " + std::to_string(value) + " } is not in range ["
2592 + std::to_string(validRange().min()) + ", "
2593 + std::to_string(validRange().max()) + "]" };
2594 }
2595
2596 Zivid::DataModel::Detail::Optional<double> m_opt;
2597
2598 friend struct DataModel::Detail::Befriend<Gamma>;
2599 };
2600
2601 using Descendants = std::tuple<
2609
2612
2630#ifndef NO_DOC
2631 template<
2632 typename... Args,
2633 typename std::enable_if<sizeof...(Args) >= 1, int>::type = 0,
2634 typename std::enable_if<
2635 Zivid::Detail::TypeTraits::AllArgsAreInTuple<Descendants, typename std::decay<Args>::type...>::
2636 value,
2637 int>::type = 0>
2638#else
2639 template<typename... Args>
2640#endif
2641 explicit Color(Args &&...args)
2642 {
2643 using namespace Zivid::Detail::TypeTraits;
2644
2645 static_assert(
2646 AllArgsDecayedAreUnique<Args...>::value,
2647 "Found duplicate types among the arguments passed to Color(...). "
2648 "Types should be listed at most once.");
2649
2650 set(std::forward<Args>(args)...);
2651 }
2652
2669#ifndef NO_DOC
2670 template<typename... Args, typename std::enable_if<sizeof...(Args) >= 2, int>::type = 0>
2671#else
2672 template<typename... Args>
2673#endif
2674 void set(Args &&...args)
2675 {
2676 using namespace Zivid::Detail::TypeTraits;
2677
2678 using AllArgsAreDescendantNodes =
2679 AllArgsAreInTuple<Descendants, typename std::decay<Args>::type...>;
2680 static_assert(
2681 AllArgsAreDescendantNodes::value, "All arguments passed to set(...) must be descendant nodes.");
2682
2683 static_assert(
2684 AllArgsDecayedAreUnique<Args...>::value,
2685 "Found duplicate types among the arguments passed to set(...). "
2686 "Types should be listed at most once.");
2687
2688 Zivid::DataModel::Detail::invokeSetWithEachArgument(*this, std::forward<Args>(args)...);
2689 }
2690
2708#ifndef NO_DOC
2709 template<typename... Args, typename std::enable_if<sizeof...(Args) >= 1, int>::type = 0>
2710#else
2711 template<typename... Args>
2712#endif
2713 Color copyWith(Args &&...args) const
2714 {
2715 using namespace Zivid::Detail::TypeTraits;
2716
2717 using AllArgsAreDescendantNodes =
2718 AllArgsAreInTuple<Descendants, typename std::decay<Args>::type...>;
2719 static_assert(
2720 AllArgsAreDescendantNodes::value,
2721 "All arguments passed to copyWith(...) must be descendant nodes.");
2722
2723 static_assert(
2724 AllArgsDecayedAreUnique<Args...>::value,
2725 "Found duplicate types among the arguments passed to copyWith(...). "
2726 "Types should be listed at most once.");
2727
2728 auto copy{ *this };
2729 copy.set(std::forward<Args>(args)...);
2730 return copy;
2731 }
2732
2734 const Balance &balance() const
2735 {
2736 return m_balance;
2737 }
2738
2741 {
2742 return m_balance;
2743 }
2744
2746 Color &set(const Balance &value)
2747 {
2748 m_balance = value;
2749 return *this;
2750 }
2751
2753 Color &set(const Balance::Blue &value)
2754 {
2755 m_balance.set(value);
2756 return *this;
2757 }
2758
2760 Color &set(const Balance::Green &value)
2761 {
2762 m_balance.set(value);
2763 return *this;
2764 }
2765
2767 Color &set(const Balance::Red &value)
2768 {
2769 m_balance.set(value);
2770 return *this;
2771 }
2772
2775 {
2776 return m_experimental;
2777 }
2778
2781 {
2782 return m_experimental;
2783 }
2784
2786 Color &set(const Experimental &value)
2787 {
2788 m_experimental = value;
2789 return *this;
2790 }
2791
2794 {
2795 m_experimental.set(value);
2796 return *this;
2797 }
2798
2800 const Gamma &gamma() const
2801 {
2802 return m_gamma;
2803 }
2804
2807 {
2808 return m_gamma;
2809 }
2810
2812 Color &set(const Gamma &value)
2813 {
2814 m_gamma = value;
2815 return *this;
2816 }
2817
2818 template<
2819 typename T,
2820 typename std::enable_if<std::is_same<T, Settings::Processing::Color::Balance>::value, int>::type =
2821 0>
2823 {
2824 return m_balance;
2825 }
2826
2827 template<
2828 typename T,
2829 typename std::enable_if<std::is_same<T, Settings::Processing::Color::Balance::Blue>::value, int>::
2830 type = 0>
2832 {
2833 return m_balance.get<Settings::Processing::Color::Balance::Blue>();
2834 }
2835
2836 template<
2837 typename T,
2838 typename std::enable_if<std::is_same<T, Settings::Processing::Color::Balance::Green>::value, int>::
2839 type = 0>
2841 {
2842 return m_balance.get<Settings::Processing::Color::Balance::Green>();
2843 }
2844
2845 template<
2846 typename T,
2847 typename std::enable_if<std::is_same<T, Settings::Processing::Color::Balance::Red>::value, int>::
2848 type = 0>
2850 {
2851 return m_balance.get<Settings::Processing::Color::Balance::Red>();
2852 }
2853
2854 template<
2855 typename T,
2856 typename std::enable_if<std::is_same<T, Settings::Processing::Color::Experimental>::value, int>::
2857 type = 0>
2859 {
2860 return m_experimental;
2861 }
2862
2863 template<
2864 typename T,
2865 typename std::enable_if<
2866 std::is_same<T, Settings::Processing::Color::Experimental::Mode>::value,
2867 int>::type = 0>
2869 {
2870 return m_experimental.get<Settings::Processing::Color::Experimental::Mode>();
2871 }
2872
2873 template<
2874 typename T,
2875 typename std::enable_if<std::is_same<T, Settings::Processing::Color::Gamma>::value, int>::type = 0>
2877 {
2878 return m_gamma;
2879 }
2880
2881 template<size_t i, typename std::enable_if<i == 0, int>::type = 0>
2883 {
2884 return m_balance;
2885 }
2886
2887 template<size_t i, typename std::enable_if<i == 1, int>::type = 0>
2889 {
2890 return m_experimental;
2891 }
2892
2893 template<size_t i, typename std::enable_if<i == 2, int>::type = 0>
2895 {
2896 return m_gamma;
2897 }
2898
2900 template<typename F>
2901 void forEach(const F &f) const
2902 {
2903 f(m_balance);
2904 f(m_experimental);
2905 f(m_gamma);
2906 }
2907
2909 template<typename F>
2910 void forEach(const F &f)
2911 {
2912 f(m_balance);
2913 f(m_experimental);
2914 f(m_gamma);
2915 }
2916
2918 bool operator==(const Color &other) const;
2919
2921 bool operator!=(const Color &other) const;
2922
2924 std::string toString() const;
2925
2927 friend std::ostream &operator<<(std::ostream &stream, const Color &value)
2928 {
2929 return stream << value.toString();
2930 }
2931
2932 private:
2933 void setFromString(const std::string &value);
2934
2935 void setFromString(const std::string &fullPath, const std::string &value);
2936
2937 std::string getString(const std::string &fullPath) const;
2938
2939 Balance m_balance;
2940 Experimental m_experimental;
2941 Gamma m_gamma;
2942
2943 friend struct DataModel::Detail::Befriend<Color>;
2944 };
2945
2947
2948 // NOLINTNEXTLINE(clang-analyzer-optin.performance.Padding)
2950 {
2951 public:
2953 static constexpr DataModel::NodeType nodeType = DataModel::NodeType::group;
2954
2956 static constexpr const char *path{ "Processing/Filters" };
2957
2959 static constexpr const char *name{ "Filters" };
2960
2962 static constexpr const char *description{ R"description(Filter settings.)description" };
2963
2966
2967 // NOLINTNEXTLINE(clang-analyzer-optin.performance.Padding)
2969 {
2970 public:
2972 static constexpr DataModel::NodeType nodeType = DataModel::NodeType::group;
2973
2975 static constexpr const char *path{ "Processing/Filters/Cluster" };
2976
2978 static constexpr const char *name{ "Cluster" };
2979
2981 static constexpr const char *description{
2982 R"description(Removes floating points and isolated clusters from the point cloud.
2983)description"
2984 };
2985
2987
2988 // NOLINTNEXTLINE(clang-analyzer-optin.performance.Padding)
2990 {
2991 public:
2993 static constexpr DataModel::NodeType nodeType = DataModel::NodeType::group;
2994
2996 static constexpr const char *path{ "Processing/Filters/Cluster/Removal" };
2997
2999 static constexpr const char *name{ "Removal" };
3000
3002 static constexpr const char *description{ R"description(Cluster removal filter.)description" };
3003
3005
3006 // NOLINTNEXTLINE(clang-analyzer-optin.performance.Padding)
3008 {
3009 public:
3011 static constexpr DataModel::NodeType nodeType = DataModel::NodeType::leafValue;
3012
3014 static constexpr const char *path{ "Processing/Filters/Cluster/Removal/Enabled" };
3015
3017 static constexpr const char *name{ "Enabled" };
3018
3020 static constexpr const char *description{
3021 R"description(Enable or disable cluster removal.)description"
3022 };
3023
3025 using ValueType = bool;
3026 static const Enabled yes;
3027 static const Enabled no;
3028
3030 static std::set<bool> validValues()
3031 {
3032 return { false, true };
3033 }
3034
3036 Enabled() = default;
3037
3039 explicit constexpr Enabled(bool value)
3040 : m_opt{ value }
3041 {}
3042
3047 bool value() const;
3048
3050 bool hasValue() const;
3051
3053 void reset();
3054
3056 std::string toString() const;
3057
3059 bool operator==(const Enabled &other) const
3060 {
3061 return m_opt == other.m_opt;
3062 }
3063
3065 bool operator!=(const Enabled &other) const
3066 {
3067 return m_opt != other.m_opt;
3068 }
3069
3071 friend std::ostream &operator<<(std::ostream &stream, const Enabled &value)
3072 {
3073 return stream << value.toString();
3074 }
3075
3076 private:
3077 void setFromString(const std::string &value);
3078
3079 Zivid::DataModel::Detail::Optional<bool> m_opt;
3080
3081 friend struct DataModel::Detail::Befriend<Enabled>;
3082 };
3083
3088
3089 // NOLINTNEXTLINE(clang-analyzer-optin.performance.Padding)
3091 {
3092 public:
3094 static constexpr DataModel::NodeType nodeType = DataModel::NodeType::leafValue;
3095
3097 static constexpr const char *path{
3098 "Processing/Filters/Cluster/Removal/MaxNeighborDistance"
3099 };
3100
3102 static constexpr const char *name{ "MaxNeighborDistance" };
3103
3105 static constexpr const char *description{
3106 R"description(Maximum normalized distance between neighboring points that are still classified as
3107belonging to the same cluster. The default value is optimal for most scenes. On messy
3108scenes turning this setting down helps removing more bad points.
3109)description"
3110 };
3111
3113 using ValueType = double;
3114
3116 static constexpr Range<double> validRange()
3117 {
3118 return { 2.0, 10.0 };
3119 }
3120
3123
3125 explicit constexpr MaxNeighborDistance(double value)
3126 : m_opt{ verifyValue(value) }
3127 {}
3128
3133 double value() const;
3134
3136 bool hasValue() const;
3137
3139 void reset();
3140
3142 std::string toString() const;
3143
3145 bool operator==(const MaxNeighborDistance &other) const
3146 {
3147 return m_opt == other.m_opt;
3148 }
3149
3151 bool operator!=(const MaxNeighborDistance &other) const
3152 {
3153 return m_opt != other.m_opt;
3154 }
3155
3157 bool operator<(const MaxNeighborDistance &other) const
3158 {
3159 return m_opt < other.m_opt;
3160 }
3161
3163 bool operator>(const MaxNeighborDistance &other) const
3164 {
3165 return m_opt > other.m_opt;
3166 }
3167
3169 bool operator<=(const MaxNeighborDistance &other) const
3170 {
3171 return m_opt <= other.m_opt;
3172 }
3173
3175 bool operator>=(const MaxNeighborDistance &other) const
3176 {
3177 return m_opt >= other.m_opt;
3178 }
3179
3181 friend std::ostream &operator<<(std::ostream &stream, const MaxNeighborDistance &value)
3182 {
3183 return stream << value.toString();
3184 }
3185
3186 private:
3187 void setFromString(const std::string &value);
3188
3189 constexpr ValueType static verifyValue(const ValueType &value)
3190 {
3191 return validRange().isInRange(value)
3192 ? value
3193 : throw std::out_of_range{ "MaxNeighborDistance{ " + std::to_string(value)
3194 + " } is not in range ["
3195 + std::to_string(validRange().min()) + ", "
3196 + std::to_string(validRange().max()) + "]" };
3197 }
3198
3199 Zivid::DataModel::Detail::Optional<double> m_opt;
3200
3201 friend struct DataModel::Detail::Befriend<MaxNeighborDistance>;
3202 };
3203
3207
3208 // NOLINTNEXTLINE(clang-analyzer-optin.performance.Padding)
3210 {
3211 public:
3213 static constexpr DataModel::NodeType nodeType = DataModel::NodeType::leafValue;
3214
3216 static constexpr const char *path{ "Processing/Filters/Cluster/Removal/MinArea" };
3217
3219 static constexpr const char *name{ "MinArea" };
3220
3222 static constexpr const char *description{
3223 R"description(Clusters with area below this threshold are removed by the filter.
3224The area is given in mm^2.
3225)description"
3226 };
3227
3229 using ValueType = double;
3230
3232 static constexpr Range<double> validRange()
3233 {
3234 return { 0.0, 1500.0 };
3235 }
3236
3238 MinArea() = default;
3239
3241 explicit constexpr MinArea(double value)
3242 : m_opt{ verifyValue(value) }
3243 {}
3244
3249 double value() const;
3250
3252 bool hasValue() const;
3253
3255 void reset();
3256
3258 std::string toString() const;
3259
3261 bool operator==(const MinArea &other) const
3262 {
3263 return m_opt == other.m_opt;
3264 }
3265
3267 bool operator!=(const MinArea &other) const
3268 {
3269 return m_opt != other.m_opt;
3270 }
3271
3273 bool operator<(const MinArea &other) const
3274 {
3275 return m_opt < other.m_opt;
3276 }
3277
3279 bool operator>(const MinArea &other) const
3280 {
3281 return m_opt > other.m_opt;
3282 }
3283
3285 bool operator<=(const MinArea &other) const
3286 {
3287 return m_opt <= other.m_opt;
3288 }
3289
3291 bool operator>=(const MinArea &other) const
3292 {
3293 return m_opt >= other.m_opt;
3294 }
3295
3297 friend std::ostream &operator<<(std::ostream &stream, const MinArea &value)
3298 {
3299 return stream << value.toString();
3300 }
3301
3302 private:
3303 void setFromString(const std::string &value);
3304
3305 constexpr ValueType static verifyValue(const ValueType &value)
3306 {
3307 return validRange().isInRange(value)
3308 ? value
3309 : throw std::out_of_range{ "MinArea{ " + std::to_string(value)
3310 + " } is not in range ["
3311 + std::to_string(validRange().min()) + ", "
3312 + std::to_string(validRange().max()) + "]" };
3313 }
3314
3315 Zivid::DataModel::Detail::Optional<double> m_opt;
3316
3317 friend struct DataModel::Detail::Befriend<MinArea>;
3318 };
3319
3320 using Descendants = std::tuple<
3324
3327
3341#ifndef NO_DOC
3342 template<
3343 typename... Args,
3344 typename std::enable_if<sizeof...(Args) >= 1, int>::type = 0,
3345 typename std::enable_if<
3346 Zivid::Detail::TypeTraits::
3347 AllArgsAreInTuple<Descendants, typename std::decay<Args>::type...>::value,
3348 int>::type = 0>
3349#else
3350 template<typename... Args>
3351#endif
3352 explicit Removal(Args &&...args)
3353 {
3354 using namespace Zivid::Detail::TypeTraits;
3355
3356 static_assert(
3357 AllArgsDecayedAreUnique<Args...>::value,
3358 "Found duplicate types among the arguments passed to Removal(...). "
3359 "Types should be listed at most once.");
3360
3361 set(std::forward<Args>(args)...);
3362 }
3363
3376#ifndef NO_DOC
3377 template<typename... Args, typename std::enable_if<sizeof...(Args) >= 2, int>::type = 0>
3378#else
3379 template<typename... Args>
3380#endif
3381 void set(Args &&...args)
3382 {
3383 using namespace Zivid::Detail::TypeTraits;
3384
3385 using AllArgsAreDescendantNodes =
3386 AllArgsAreInTuple<Descendants, typename std::decay<Args>::type...>;
3387 static_assert(
3388 AllArgsAreDescendantNodes::value,
3389 "All arguments passed to set(...) must be descendant nodes.");
3390
3391 static_assert(
3392 AllArgsDecayedAreUnique<Args...>::value,
3393 "Found duplicate types among the arguments passed to set(...). "
3394 "Types should be listed at most once.");
3395
3396 Zivid::DataModel::Detail::invokeSetWithEachArgument(*this, std::forward<Args>(args)...);
3397 }
3398
3412#ifndef NO_DOC
3413 template<typename... Args, typename std::enable_if<sizeof...(Args) >= 1, int>::type = 0>
3414#else
3415 template<typename... Args>
3416#endif
3417 Removal copyWith(Args &&...args) const
3418 {
3419 using namespace Zivid::Detail::TypeTraits;
3420
3421 using AllArgsAreDescendantNodes =
3422 AllArgsAreInTuple<Descendants, typename std::decay<Args>::type...>;
3423 static_assert(
3424 AllArgsAreDescendantNodes::value,
3425 "All arguments passed to copyWith(...) must be descendant nodes.");
3426
3427 static_assert(
3428 AllArgsDecayedAreUnique<Args...>::value,
3429 "Found duplicate types among the arguments passed to copyWith(...). "
3430 "Types should be listed at most once.");
3431
3432 auto copy{ *this };
3433 copy.set(std::forward<Args>(args)...);
3434 return copy;
3435 }
3436
3438 const Enabled &isEnabled() const
3439 {
3440 return m_enabled;
3441 }
3442
3445 {
3446 return m_enabled;
3447 }
3448
3450 Removal &set(const Enabled &value)
3451 {
3452 m_enabled = value;
3453 return *this;
3454 }
3455
3458 {
3459 return m_maxNeighborDistance;
3460 }
3461
3464 {
3465 return m_maxNeighborDistance;
3466 }
3467
3470 {
3471 m_maxNeighborDistance = value;
3472 return *this;
3473 }
3474
3476 const MinArea &minArea() const
3477 {
3478 return m_minArea;
3479 }
3480
3483 {
3484 return m_minArea;
3485 }
3486
3488 Removal &set(const MinArea &value)
3489 {
3490 m_minArea = value;
3491 return *this;
3492 }
3493
3494 template<
3495 typename T,
3496 typename std::enable_if<
3497 std::is_same<T, Settings::Processing::Filters::Cluster::Removal::Enabled>::value,
3498 int>::type = 0>
3500 {
3501 return m_enabled;
3502 }
3503
3504 template<
3505 typename T,
3506 typename std::enable_if<
3507 std::is_same<T, Settings::Processing::Filters::Cluster::Removal::MaxNeighborDistance>::
3508 value,
3509 int>::type = 0>
3511 {
3512 return m_maxNeighborDistance;
3513 }
3514
3515 template<
3516 typename T,
3517 typename std::enable_if<
3518 std::is_same<T, Settings::Processing::Filters::Cluster::Removal::MinArea>::value,
3519 int>::type = 0>
3521 {
3522 return m_minArea;
3523 }
3524
3525 template<size_t i, typename std::enable_if<i == 0, int>::type = 0>
3527 {
3528 return m_enabled;
3529 }
3530
3531 template<size_t i, typename std::enable_if<i == 1, int>::type = 0>
3533 {
3534 return m_maxNeighborDistance;
3535 }
3536
3537 template<size_t i, typename std::enable_if<i == 2, int>::type = 0>
3539 {
3540 return m_minArea;
3541 }
3542
3544 template<typename F>
3545 void forEach(const F &f) const
3546 {
3547 f(m_enabled);
3548 f(m_maxNeighborDistance);
3549 f(m_minArea);
3550 }
3551
3553 template<typename F>
3554 void forEach(const F &f)
3555 {
3556 f(m_enabled);
3557 f(m_maxNeighborDistance);
3558 f(m_minArea);
3559 }
3560
3562 bool operator==(const Removal &other) const;
3563
3565 bool operator!=(const Removal &other) const;
3566
3568 std::string toString() const;
3569
3571 friend std::ostream &operator<<(std::ostream &stream, const Removal &value)
3572 {
3573 return stream << value.toString();
3574 }
3575
3576 private:
3577 void setFromString(const std::string &value);
3578
3579 void setFromString(const std::string &fullPath, const std::string &value);
3580
3581 std::string getString(const std::string &fullPath) const;
3582
3583 Enabled m_enabled;
3584 MaxNeighborDistance m_maxNeighborDistance;
3585 MinArea m_minArea;
3586
3587 friend struct DataModel::Detail::Befriend<Removal>;
3588 };
3589
3590 using Descendants = std::tuple<
3595
3598
3613#ifndef NO_DOC
3614 template<
3615 typename... Args,
3616 typename std::enable_if<sizeof...(Args) >= 1, int>::type = 0,
3617 typename std::enable_if<
3618 Zivid::Detail::TypeTraits::
3619 AllArgsAreInTuple<Descendants, typename std::decay<Args>::type...>::value,
3620 int>::type = 0>
3621#else
3622 template<typename... Args>
3623#endif
3624 explicit Cluster(Args &&...args)
3625 {
3626 using namespace Zivid::Detail::TypeTraits;
3627
3628 static_assert(
3629 AllArgsDecayedAreUnique<Args...>::value,
3630 "Found duplicate types among the arguments passed to Cluster(...). "
3631 "Types should be listed at most once.");
3632
3633 set(std::forward<Args>(args)...);
3634 }
3635
3649#ifndef NO_DOC
3650 template<typename... Args, typename std::enable_if<sizeof...(Args) >= 2, int>::type = 0>
3651#else
3652 template<typename... Args>
3653#endif
3654 void set(Args &&...args)
3655 {
3656 using namespace Zivid::Detail::TypeTraits;
3657
3658 using AllArgsAreDescendantNodes =
3659 AllArgsAreInTuple<Descendants, typename std::decay<Args>::type...>;
3660 static_assert(
3661 AllArgsAreDescendantNodes::value,
3662 "All arguments passed to set(...) must be descendant nodes.");
3663
3664 static_assert(
3665 AllArgsDecayedAreUnique<Args...>::value,
3666 "Found duplicate types among the arguments passed to set(...). "
3667 "Types should be listed at most once.");
3668
3669 Zivid::DataModel::Detail::invokeSetWithEachArgument(*this, std::forward<Args>(args)...);
3670 }
3671
3686#ifndef NO_DOC
3687 template<typename... Args, typename std::enable_if<sizeof...(Args) >= 1, int>::type = 0>
3688#else
3689 template<typename... Args>
3690#endif
3691 Cluster copyWith(Args &&...args) const
3692 {
3693 using namespace Zivid::Detail::TypeTraits;
3694
3695 using AllArgsAreDescendantNodes =
3696 AllArgsAreInTuple<Descendants, typename std::decay<Args>::type...>;
3697 static_assert(
3698 AllArgsAreDescendantNodes::value,
3699 "All arguments passed to copyWith(...) must be descendant nodes.");
3700
3701 static_assert(
3702 AllArgsDecayedAreUnique<Args...>::value,
3703 "Found duplicate types among the arguments passed to copyWith(...). "
3704 "Types should be listed at most once.");
3705
3706 auto copy{ *this };
3707 copy.set(std::forward<Args>(args)...);
3708 return copy;
3709 }
3710
3712 const Removal &removal() const
3713 {
3714 return m_removal;
3715 }
3716
3719 {
3720 return m_removal;
3721 }
3722
3724 Cluster &set(const Removal &value)
3725 {
3726 m_removal = value;
3727 return *this;
3728 }
3729
3732 {
3733 m_removal.set(value);
3734 return *this;
3735 }
3736
3739 {
3740 m_removal.set(value);
3741 return *this;
3742 }
3743
3746 {
3747 m_removal.set(value);
3748 return *this;
3749 }
3750
3751 template<
3752 typename T,
3753 typename std::enable_if<
3754 std::is_same<T, Settings::Processing::Filters::Cluster::Removal>::value,
3755 int>::type = 0>
3757 {
3758 return m_removal;
3759 }
3760
3761 template<
3762 typename T,
3763 typename std::enable_if<
3764 std::is_same<T, Settings::Processing::Filters::Cluster::Removal::Enabled>::value,
3765 int>::type = 0>
3767 {
3769 }
3770
3771 template<
3772 typename T,
3773 typename std::enable_if<
3774 std::is_same<T, Settings::Processing::Filters::Cluster::Removal::MaxNeighborDistance>::
3775 value,
3776 int>::type = 0>
3778 {
3780 }
3781
3782 template<
3783 typename T,
3784 typename std::enable_if<
3785 std::is_same<T, Settings::Processing::Filters::Cluster::Removal::MinArea>::value,
3786 int>::type = 0>
3788 {
3790 }
3791
3792 template<size_t i, typename std::enable_if<i == 0, int>::type = 0>
3794 {
3795 return m_removal;
3796 }
3797
3799 template<typename F>
3800 void forEach(const F &f) const
3801 {
3802 f(m_removal);
3803 }
3804
3806 template<typename F>
3807 void forEach(const F &f)
3808 {
3809 f(m_removal);
3810 }
3811
3813 bool operator==(const Cluster &other) const;
3814
3816 bool operator!=(const Cluster &other) const;
3817
3819 std::string toString() const;
3820
3822 friend std::ostream &operator<<(std::ostream &stream, const Cluster &value)
3823 {
3824 return stream << value.toString();
3825 }
3826
3827 private:
3828 void setFromString(const std::string &value);
3829
3830 void setFromString(const std::string &fullPath, const std::string &value);
3831
3832 std::string getString(const std::string &fullPath) const;
3833
3834 Removal m_removal;
3835
3836 friend struct DataModel::Detail::Befriend<Cluster>;
3837 };
3838
3840
3841 // NOLINTNEXTLINE(clang-analyzer-optin.performance.Padding)
3843 {
3844 public:
3846 static constexpr DataModel::NodeType nodeType = DataModel::NodeType::group;
3847
3849 static constexpr const char *path{ "Processing/Filters/Experimental" };
3850
3852 static constexpr const char *name{ "Experimental" };
3853
3855 static constexpr const char *description{
3856 R"description(Experimental filters. These may be renamed, moved or deleted in the future.)description"
3857 };
3858
3864
3865 // NOLINTNEXTLINE(clang-analyzer-optin.performance.Padding)
3867 {
3868 public:
3870 static constexpr DataModel::NodeType nodeType = DataModel::NodeType::group;
3871
3873 static constexpr const char *path{ "Processing/Filters/Experimental/ContrastDistortion" };
3874
3876 static constexpr const char *name{ "ContrastDistortion" };
3877
3879 static constexpr const char *description{
3880 R"description(Corrects artifacts that appear when imaging scenes with large texture gradients
3881or high contrast. These artifacts are caused by blurring in the lens. The filter
3882works best when aperture values are chosen such that the camera has quite good focus.
3883The filter also supports removing the points that experience a large correction.
3884)description"
3885 };
3886
3888
3889 // NOLINTNEXTLINE(clang-analyzer-optin.performance.Padding)
3891 {
3892 public:
3894 static constexpr DataModel::NodeType nodeType = DataModel::NodeType::group;
3895
3897 static constexpr const char *path{
3898 "Processing/Filters/Experimental/ContrastDistortion/Correction"
3899 };
3900
3902 static constexpr const char *name{ "Correction" };
3903
3905 static constexpr const char *description{
3906 R"description(Contrast distortion correction filter.)description"
3907 };
3908
3910
3911 // NOLINTNEXTLINE(clang-analyzer-optin.performance.Padding)
3913 {
3914 public:
3916 static constexpr DataModel::NodeType nodeType = DataModel::NodeType::leafValue;
3917
3919 static constexpr const char *path{
3920 "Processing/Filters/Experimental/ContrastDistortion/Correction/Enabled"
3921 };
3922
3924 static constexpr const char *name{ "Enabled" };
3925
3927 static constexpr const char *description{
3928 R"description(Enable or disable contrast distortion correction.)description"
3929 };
3930
3932 using ValueType = bool;
3933 static const Enabled yes;
3934 static const Enabled no;
3935
3937 static std::set<bool> validValues()
3938 {
3939 return { false, true };
3940 }
3941
3943 Enabled() = default;
3944
3946 explicit constexpr Enabled(bool value)
3947 : m_opt{ value }
3948 {}
3949
3954 bool value() const;
3955
3957 bool hasValue() const;
3958
3960 void reset();
3961
3963 std::string toString() const;
3964
3966 bool operator==(const Enabled &other) const
3967 {
3968 return m_opt == other.m_opt;
3969 }
3970
3972 bool operator!=(const Enabled &other) const
3973 {
3974 return m_opt != other.m_opt;
3975 }
3976
3978 friend std::ostream &operator<<(std::ostream &stream, const Enabled &value)
3979 {
3980 return stream << value.toString();
3981 }
3982
3983 private:
3984 void setFromString(const std::string &value);
3985
3986 Zivid::DataModel::Detail::Optional<bool> m_opt;
3987
3988 friend struct DataModel::Detail::Befriend<Enabled>;
3989 };
3990
3992
3993 // NOLINTNEXTLINE(clang-analyzer-optin.performance.Padding)
3995 {
3996 public:
3998 static constexpr DataModel::NodeType nodeType = DataModel::NodeType::leafValue;
3999
4001 static constexpr const char *path{
4002 "Processing/Filters/Experimental/ContrastDistortion/Correction/Strength"
4003 };
4004
4006 static constexpr const char *name{ "Strength" };
4007
4009 static constexpr const char *description{
4010 R"description(Strength of correction. Higher values give more correction.)description"
4011 };
4012
4014 using ValueType = double;
4015
4017 static constexpr Range<double> validRange()
4018 {
4019 return { 0.0, 1.0 };
4020 }
4021
4023 Strength() = default;
4024
4026 explicit constexpr Strength(double value)
4027 : m_opt{ verifyValue(value) }
4028 {}
4029
4034 double value() const;
4035
4037 bool hasValue() const;
4038
4040 void reset();
4041
4043 std::string toString() const;
4044
4046 bool operator==(const Strength &other) const
4047 {
4048 return m_opt == other.m_opt;
4049 }
4050
4052 bool operator!=(const Strength &other) const
4053 {
4054 return m_opt != other.m_opt;
4055 }
4056
4058 bool operator<(const Strength &other) const
4059 {
4060 return m_opt < other.m_opt;
4061 }
4062
4064 bool operator>(const Strength &other) const
4065 {
4066 return m_opt > other.m_opt;
4067 }
4068
4070 bool operator<=(const Strength &other) const
4071 {
4072 return m_opt <= other.m_opt;
4073 }
4074
4076 bool operator>=(const Strength &other) const
4077 {
4078 return m_opt >= other.m_opt;
4079 }
4080
4082 friend std::ostream &operator<<(std::ostream &stream, const Strength &value)
4083 {
4084 return stream << value.toString();
4085 }
4086
4087 private:
4088 void setFromString(const std::string &value);
4089
4090 constexpr ValueType static verifyValue(const ValueType &value)
4091 {
4092 return validRange().isInRange(value)
4093 ? value
4094 : throw std::out_of_range{ "Strength{ " + std::to_string(value)
4095 + " } is not in range ["
4096 + std::to_string(validRange().min()) + ", "
4097 + std::to_string(validRange().max()) + "]" };
4098 }
4099
4100 Zivid::DataModel::Detail::Optional<double> m_opt;
4101
4102 friend struct DataModel::Detail::Befriend<Strength>;
4103 };
4104
4105 using Descendants = std::tuple<
4108
4111
4124#ifndef NO_DOC
4125 template<
4126 typename... Args,
4127 typename std::enable_if<sizeof...(Args) >= 1, int>::type = 0,
4128 typename std::enable_if<
4129 Zivid::Detail::TypeTraits::
4130 AllArgsAreInTuple<Descendants, typename std::decay<Args>::type...>::value,
4131 int>::type = 0>
4132#else
4133 template<typename... Args>
4134#endif
4135 explicit Correction(Args &&...args)
4136 {
4137 using namespace Zivid::Detail::TypeTraits;
4138
4139 static_assert(
4140 AllArgsDecayedAreUnique<Args...>::value,
4141 "Found duplicate types among the arguments passed to Correction(...). "
4142 "Types should be listed at most once.");
4143
4144 set(std::forward<Args>(args)...);
4145 }
4146
4158#ifndef NO_DOC
4159 template<typename... Args, typename std::enable_if<sizeof...(Args) >= 2, int>::type = 0>
4160#else
4161 template<typename... Args>
4162#endif
4163 void set(Args &&...args)
4164 {
4165 using namespace Zivid::Detail::TypeTraits;
4166
4167 using AllArgsAreDescendantNodes =
4168 AllArgsAreInTuple<Descendants, typename std::decay<Args>::type...>;
4169 static_assert(
4170 AllArgsAreDescendantNodes::value,
4171 "All arguments passed to set(...) must be descendant nodes.");
4172
4173 static_assert(
4174 AllArgsDecayedAreUnique<Args...>::value,
4175 "Found duplicate types among the arguments passed to set(...). "
4176 "Types should be listed at most once.");
4177
4178 Zivid::DataModel::Detail::invokeSetWithEachArgument(*this, std::forward<Args>(args)...);
4179 }
4180
4193#ifndef NO_DOC
4194 template<typename... Args, typename std::enable_if<sizeof...(Args) >= 1, int>::type = 0>
4195#else
4196 template<typename... Args>
4197#endif
4198 Correction copyWith(Args &&...args) const
4199 {
4200 using namespace Zivid::Detail::TypeTraits;
4201
4202 using AllArgsAreDescendantNodes =
4203 AllArgsAreInTuple<Descendants, typename std::decay<Args>::type...>;
4204 static_assert(
4205 AllArgsAreDescendantNodes::value,
4206 "All arguments passed to copyWith(...) must be descendant nodes.");
4207
4208 static_assert(
4209 AllArgsDecayedAreUnique<Args...>::value,
4210 "Found duplicate types among the arguments passed to copyWith(...). "
4211 "Types should be listed at most once.");
4212
4213 auto copy{ *this };
4214 copy.set(std::forward<Args>(args)...);
4215 return copy;
4216 }
4217
4219 const Enabled &isEnabled() const
4220 {
4221 return m_enabled;
4222 }
4223
4226 {
4227 return m_enabled;
4228 }
4229
4231 Correction &set(const Enabled &value)
4232 {
4233 m_enabled = value;
4234 return *this;
4235 }
4236
4238 const Strength &strength() const
4239 {
4240 return m_strength;
4241 }
4242
4245 {
4246 return m_strength;
4247 }
4248
4250 Correction &set(const Strength &value)
4251 {
4252 m_strength = value;
4253 return *this;
4254 }
4255
4256 template<
4257 typename T,
4258 typename std::enable_if<
4259 std::is_same<
4260 T,
4261 Settings::Processing::Filters::Experimental::ContrastDistortion::Correction::
4262 Enabled>::value,
4263 int>::type = 0>
4265 get() const
4266 {
4267 return m_enabled;
4268 }
4269
4270 template<
4271 typename T,
4272 typename std::enable_if<
4273 std::is_same<
4274 T,
4275 Settings::Processing::Filters::Experimental::ContrastDistortion::Correction::
4276 Strength>::value,
4277 int>::type = 0>
4278 const Settings::Processing::Filters::Experimental::ContrastDistortion::Correction::
4279 Strength &
4280 get() const
4281 {
4282 return m_strength;
4283 }
4284
4285 template<size_t i, typename std::enable_if<i == 0, int>::type = 0>
4287 get() const
4288 {
4289 return m_enabled;
4290 }
4291
4292 template<size_t i, typename std::enable_if<i == 1, int>::type = 0>
4293 const Settings::Processing::Filters::Experimental::ContrastDistortion::Correction::
4294 Strength &
4295 get() const
4296 {
4297 return m_strength;
4298 }
4299
4301 template<typename F>
4302 void forEach(const F &f) const
4303 {
4304 f(m_enabled);
4305 f(m_strength);
4306 }
4307
4309 template<typename F>
4310 void forEach(const F &f)
4311 {
4312 f(m_enabled);
4313 f(m_strength);
4314 }
4315
4317 bool operator==(const Correction &other) const;
4318
4320 bool operator!=(const Correction &other) const;
4321
4323 std::string toString() const;
4324
4326 friend std::ostream &operator<<(std::ostream &stream, const Correction &value)
4327 {
4328 return stream << value.toString();
4329 }
4330
4331 private:
4332 void setFromString(const std::string &value);
4333
4334 void setFromString(const std::string &fullPath, const std::string &value);
4335
4336 std::string getString(const std::string &fullPath) const;
4337
4338 Enabled m_enabled;
4339 Strength m_strength;
4340
4341 friend struct DataModel::Detail::Befriend<Correction>;
4342 };
4343
4345
4346 // NOLINTNEXTLINE(clang-analyzer-optin.performance.Padding)
4348 {
4349 public:
4351 static constexpr DataModel::NodeType nodeType = DataModel::NodeType::group;
4352
4354 static constexpr const char *path{
4355 "Processing/Filters/Experimental/ContrastDistortion/Removal"
4356 };
4357
4359 static constexpr const char *name{ "Removal" };
4360
4362 static constexpr const char *description{
4363 R"description(Contrast distortion removal filter.)description"
4364 };
4365
4367
4368 // NOLINTNEXTLINE(clang-analyzer-optin.performance.Padding)
4370 {
4371 public:
4373 static constexpr DataModel::NodeType nodeType = DataModel::NodeType::leafValue;
4374
4376 static constexpr const char *path{
4377 "Processing/Filters/Experimental/ContrastDistortion/Removal/Enabled"
4378 };
4379
4381 static constexpr const char *name{ "Enabled" };
4382
4384 static constexpr const char *description{
4385 R"description(Enable or disable contrast distortion removal.)description"
4386 };
4387
4389 using ValueType = bool;
4390 static const Enabled yes;
4391 static const Enabled no;
4392
4394 static std::set<bool> validValues()
4395 {
4396 return { false, true };
4397 }
4398
4400 Enabled() = default;
4401
4403 explicit constexpr Enabled(bool value)
4404 : m_opt{ value }
4405 {}
4406
4411 bool value() const;
4412
4414 bool hasValue() const;
4415
4417 void reset();
4418
4420 std::string toString() const;
4421
4423 bool operator==(const Enabled &other) const
4424 {
4425 return m_opt == other.m_opt;
4426 }
4427
4429 bool operator!=(const Enabled &other) const
4430 {
4431 return m_opt != other.m_opt;
4432 }
4433
4435 friend std::ostream &operator<<(std::ostream &stream, const Enabled &value)
4436 {
4437 return stream << value.toString();
4438 }
4439
4440 private:
4441 void setFromString(const std::string &value);
4442
4443 Zivid::DataModel::Detail::Optional<bool> m_opt;
4444
4445 friend struct DataModel::Detail::Befriend<Enabled>;
4446 };
4447
4449
4450 // NOLINTNEXTLINE(clang-analyzer-optin.performance.Padding)
4452 {
4453 public:
4455 static constexpr DataModel::NodeType nodeType = DataModel::NodeType::leafValue;
4456
4458 static constexpr const char *path{
4459 "Processing/Filters/Experimental/ContrastDistortion/Removal/Threshold"
4460 };
4461
4463 static constexpr const char *name{ "Threshold" };
4464
4466 static constexpr const char *description{
4467 R"description(Threshold for removal. Higher values remove more points.)description"
4468 };
4469
4471 using ValueType = double;
4472
4474 static constexpr Range<double> validRange()
4475 {
4476 return { 0.0, 1.0 };
4477 }
4478
4480 Threshold() = default;
4481
4483 explicit constexpr Threshold(double value)
4484 : m_opt{ verifyValue(value) }
4485 {}
4486
4491 double value() const;
4492
4494 bool hasValue() const;
4495
4497 void reset();
4498
4500 std::string toString() const;
4501
4503 bool operator==(const Threshold &other) const
4504 {
4505 return m_opt == other.m_opt;
4506 }
4507
4509 bool operator!=(const Threshold &other) const
4510 {
4511 return m_opt != other.m_opt;
4512 }
4513
4515 bool operator<(const Threshold &other) const
4516 {
4517 return m_opt < other.m_opt;
4518 }
4519
4521 bool operator>(const Threshold &other) const
4522 {
4523 return m_opt > other.m_opt;
4524 }
4525
4527 bool operator<=(const Threshold &other) const
4528 {
4529 return m_opt <= other.m_opt;
4530 }
4531
4533 bool operator>=(const Threshold &other) const
4534 {
4535 return m_opt >= other.m_opt;
4536 }
4537
4539 friend std::ostream &operator<<(std::ostream &stream, const Threshold &value)
4540 {
4541 return stream << value.toString();
4542 }
4543
4544 private:
4545 void setFromString(const std::string &value);
4546
4547 constexpr ValueType static verifyValue(const ValueType &value)
4548 {
4549 return validRange().isInRange(value)
4550 ? value
4551 : throw std::out_of_range{ "Threshold{ " + std::to_string(value)
4552 + " } is not in range ["
4553 + std::to_string(validRange().min()) + ", "
4554 + std::to_string(validRange().max()) + "]" };
4555 }
4556
4557 Zivid::DataModel::Detail::Optional<double> m_opt;
4558
4559 friend struct DataModel::Detail::Befriend<Threshold>;
4560 };
4561
4562 using Descendants = std::tuple<
4565
4568
4581#ifndef NO_DOC
4582 template<
4583 typename... Args,
4584 typename std::enable_if<sizeof...(Args) >= 1, int>::type = 0,
4585 typename std::enable_if<
4586 Zivid::Detail::TypeTraits::
4587 AllArgsAreInTuple<Descendants, typename std::decay<Args>::type...>::value,
4588 int>::type = 0>
4589#else
4590 template<typename... Args>
4591#endif
4592 explicit Removal(Args &&...args)
4593 {
4594 using namespace Zivid::Detail::TypeTraits;
4595
4596 static_assert(
4597 AllArgsDecayedAreUnique<Args...>::value,
4598 "Found duplicate types among the arguments passed to Removal(...). "
4599 "Types should be listed at most once.");
4600
4601 set(std::forward<Args>(args)...);
4602 }
4603
4615#ifndef NO_DOC
4616 template<typename... Args, typename std::enable_if<sizeof...(Args) >= 2, int>::type = 0>
4617#else
4618 template<typename... Args>
4619#endif
4620 void set(Args &&...args)
4621 {
4622 using namespace Zivid::Detail::TypeTraits;
4623
4624 using AllArgsAreDescendantNodes =
4625 AllArgsAreInTuple<Descendants, typename std::decay<Args>::type...>;
4626 static_assert(
4627 AllArgsAreDescendantNodes::value,
4628 "All arguments passed to set(...) must be descendant nodes.");
4629
4630 static_assert(
4631 AllArgsDecayedAreUnique<Args...>::value,
4632 "Found duplicate types among the arguments passed to set(...). "
4633 "Types should be listed at most once.");
4634
4635 Zivid::DataModel::Detail::invokeSetWithEachArgument(*this, std::forward<Args>(args)...);
4636 }
4637
4650#ifndef NO_DOC
4651 template<typename... Args, typename std::enable_if<sizeof...(Args) >= 1, int>::type = 0>
4652#else
4653 template<typename... Args>
4654#endif
4655 Removal copyWith(Args &&...args) const
4656 {
4657 using namespace Zivid::Detail::TypeTraits;
4658
4659 using AllArgsAreDescendantNodes =
4660 AllArgsAreInTuple<Descendants, typename std::decay<Args>::type...>;
4661 static_assert(
4662 AllArgsAreDescendantNodes::value,
4663 "All arguments passed to copyWith(...) must be descendant nodes.");
4664
4665 static_assert(
4666 AllArgsDecayedAreUnique<Args...>::value,
4667 "Found duplicate types among the arguments passed to copyWith(...). "
4668 "Types should be listed at most once.");
4669
4670 auto copy{ *this };
4671 copy.set(std::forward<Args>(args)...);
4672 return copy;
4673 }
4674
4676 const Enabled &isEnabled() const
4677 {
4678 return m_enabled;
4679 }
4680
4683 {
4684 return m_enabled;
4685 }
4686
4688 Removal &set(const Enabled &value)
4689 {
4690 m_enabled = value;
4691 return *this;
4692 }
4693
4695 const Threshold &threshold() const
4696 {
4697 return m_threshold;
4698 }
4699
4702 {
4703 return m_threshold;
4704 }
4705
4707 Removal &set(const Threshold &value)
4708 {
4709 m_threshold = value;
4710 return *this;
4711 }
4712
4713 template<
4714 typename T,
4715 typename std::enable_if<
4716 std::is_same<
4717 T,
4718 Settings::Processing::Filters::Experimental::ContrastDistortion::Removal::
4719 Enabled>::value,
4720 int>::type = 0>
4722 get() const
4723 {
4724 return m_enabled;
4725 }
4726
4727 template<
4728 typename T,
4729 typename std::enable_if<
4730 std::is_same<
4731 T,
4732 Settings::Processing::Filters::Experimental::ContrastDistortion::Removal::
4733 Threshold>::value,
4734 int>::type = 0>
4736 get() const
4737 {
4738 return m_threshold;
4739 }
4740
4741 template<size_t i, typename std::enable_if<i == 0, int>::type = 0>
4743 get() const
4744 {
4745 return m_enabled;
4746 }
4747
4748 template<size_t i, typename std::enable_if<i == 1, int>::type = 0>
4750 get() const
4751 {
4752 return m_threshold;
4753 }
4754
4756 template<typename F>
4757 void forEach(const F &f) const
4758 {
4759 f(m_enabled);
4760 f(m_threshold);
4761 }
4762
4764 template<typename F>
4765 void forEach(const F &f)
4766 {
4767 f(m_enabled);
4768 f(m_threshold);
4769 }
4770
4772 bool operator==(const Removal &other) const;
4773
4775 bool operator!=(const Removal &other) const;
4776
4778 std::string toString() const;
4779
4781 friend std::ostream &operator<<(std::ostream &stream, const Removal &value)
4782 {
4783 return stream << value.toString();
4784 }
4785
4786 private:
4787 void setFromString(const std::string &value);
4788
4789 void setFromString(const std::string &fullPath, const std::string &value);
4790
4791 std::string getString(const std::string &fullPath) const;
4792
4793 Enabled m_enabled;
4794 Threshold m_threshold;
4795
4796 friend struct DataModel::Detail::Befriend<Removal>;
4797 };
4798
4799 using Descendants = std::tuple<
4806
4809
4826#ifndef NO_DOC
4827 template<
4828 typename... Args,
4829 typename std::enable_if<sizeof...(Args) >= 1, int>::type = 0,
4830 typename std::enable_if<
4831 Zivid::Detail::TypeTraits::
4832 AllArgsAreInTuple<Descendants, typename std::decay<Args>::type...>::value,
4833 int>::type = 0>
4834#else
4835 template<typename... Args>
4836#endif
4837 explicit ContrastDistortion(Args &&...args)
4838 {
4839 using namespace Zivid::Detail::TypeTraits;
4840
4841 static_assert(
4842 AllArgsDecayedAreUnique<Args...>::value,
4843 "Found duplicate types among the arguments passed to ContrastDistortion(...). "
4844 "Types should be listed at most once.");
4845
4846 set(std::forward<Args>(args)...);
4847 }
4848
4864#ifndef NO_DOC
4865 template<typename... Args, typename std::enable_if<sizeof...(Args) >= 2, int>::type = 0>
4866#else
4867 template<typename... Args>
4868#endif
4869 void set(Args &&...args)
4870 {
4871 using namespace Zivid::Detail::TypeTraits;
4872
4873 using AllArgsAreDescendantNodes =
4874 AllArgsAreInTuple<Descendants, typename std::decay<Args>::type...>;
4875 static_assert(
4876 AllArgsAreDescendantNodes::value,
4877 "All arguments passed to set(...) must be descendant nodes.");
4878
4879 static_assert(
4880 AllArgsDecayedAreUnique<Args...>::value,
4881 "Found duplicate types among the arguments passed to set(...). "
4882 "Types should be listed at most once.");
4883
4884 Zivid::DataModel::Detail::invokeSetWithEachArgument(*this, std::forward<Args>(args)...);
4885 }
4886
4903#ifndef NO_DOC
4904 template<typename... Args, typename std::enable_if<sizeof...(Args) >= 1, int>::type = 0>
4905#else
4906 template<typename... Args>
4907#endif
4908 ContrastDistortion copyWith(Args &&...args) const
4909 {
4910 using namespace Zivid::Detail::TypeTraits;
4911
4912 using AllArgsAreDescendantNodes =
4913 AllArgsAreInTuple<Descendants, typename std::decay<Args>::type...>;
4914 static_assert(
4915 AllArgsAreDescendantNodes::value,
4916 "All arguments passed to copyWith(...) must be descendant nodes.");
4917
4918 static_assert(
4919 AllArgsDecayedAreUnique<Args...>::value,
4920 "Found duplicate types among the arguments passed to copyWith(...). "
4921 "Types should be listed at most once.");
4922
4923 auto copy{ *this };
4924 copy.set(std::forward<Args>(args)...);
4925 return copy;
4926 }
4927
4929 const Correction &correction() const
4930 {
4931 return m_correction;
4932 }
4933
4936 {
4937 return m_correction;
4938 }
4939
4942 {
4943 m_correction = value;
4944 return *this;
4945 }
4946
4949 {
4950 m_correction.set(value);
4951 return *this;
4952 }
4953
4956 {
4957 m_correction.set(value);
4958 return *this;
4959 }
4960
4962 const Removal &removal() const
4963 {
4964 return m_removal;
4965 }
4966
4969 {
4970 return m_removal;
4971 }
4972
4975 {
4976 m_removal = value;
4977 return *this;
4978 }
4979
4982 {
4983 m_removal.set(value);
4984 return *this;
4985 }
4986
4989 {
4990 m_removal.set(value);
4991 return *this;
4992 }
4993
4994 template<
4995 typename T,
4996 typename std::enable_if<
4997 std::is_same<
4998 T,
5000 int>::type = 0>
5002 {
5003 return m_correction;
5004 }
5005
5006 template<
5007 typename T,
5008 typename std::enable_if<
5009 std::is_same<
5010 T,
5011 Settings::Processing::Filters::Experimental::ContrastDistortion::Correction::
5012 Enabled>::value,
5013 int>::type = 0>
5015 get() const
5016 {
5017 return m_correction.get<
5019 }
5020
5021 template<
5022 typename T,
5023 typename std::enable_if<
5024 std::is_same<
5025 T,
5026 Settings::Processing::Filters::Experimental::ContrastDistortion::Correction::
5027 Strength>::value,
5028 int>::type = 0>
5030 get() const
5031 {
5032 return m_correction.get<Settings::Processing::Filters::Experimental::ContrastDistortion::
5033 Correction::Strength>();
5034 }
5035
5036 template<
5037 typename T,
5038 typename std::enable_if<
5039 std::is_same<
5040 T,
5042 int>::type = 0>
5044 {
5045 return m_removal;
5046 }
5047
5048 template<
5049 typename T,
5050 typename std::enable_if<
5051 std::is_same<
5052 T,
5054 value,
5055 int>::type = 0>
5057 const
5058 {
5059 return m_removal.get<
5061 }
5062
5063 template<
5064 typename T,
5065 typename std::enable_if<
5066 std::is_same<
5067 T,
5068 Settings::Processing::Filters::Experimental::ContrastDistortion::Removal::
5069 Threshold>::value,
5070 int>::type = 0>
5072 const
5073 {
5074 return m_removal.get<
5076 }
5077
5078 template<size_t i, typename std::enable_if<i == 0, int>::type = 0>
5080 {
5081 return m_correction;
5082 }
5083
5084 template<size_t i, typename std::enable_if<i == 1, int>::type = 0>
5086 {
5087 return m_removal;
5088 }
5089
5091 template<typename F>
5092 void forEach(const F &f) const
5093 {
5094 f(m_correction);
5095 f(m_removal);
5096 }
5097
5099 template<typename F>
5100 void forEach(const F &f)
5101 {
5102 f(m_correction);
5103 f(m_removal);
5104 }
5105
5107 bool operator==(const ContrastDistortion &other) const;
5108
5110 bool operator!=(const ContrastDistortion &other) const;
5111
5113 std::string toString() const;
5114
5116 friend std::ostream &operator<<(std::ostream &stream, const ContrastDistortion &value)
5117 {
5118 return stream << value.toString();
5119 }
5120
5121 private:
5122 void setFromString(const std::string &value);
5123
5124 void setFromString(const std::string &fullPath, const std::string &value);
5125
5126 std::string getString(const std::string &fullPath) const;
5127
5128 Correction m_correction;
5129 Removal m_removal;
5130
5131 friend struct DataModel::Detail::Befriend<ContrastDistortion>;
5132 };
5133
5134 using Descendants = std::tuple<
5142
5145
5163#ifndef NO_DOC
5164 template<
5165 typename... Args,
5166 typename std::enable_if<sizeof...(Args) >= 1, int>::type = 0,
5167 typename std::enable_if<
5168 Zivid::Detail::TypeTraits::
5169 AllArgsAreInTuple<Descendants, typename std::decay<Args>::type...>::value,
5170 int>::type = 0>
5171#else
5172 template<typename... Args>
5173#endif
5174 explicit Experimental(Args &&...args)
5175 {
5176 using namespace Zivid::Detail::TypeTraits;
5177
5178 static_assert(
5179 AllArgsDecayedAreUnique<Args...>::value,
5180 "Found duplicate types among the arguments passed to Experimental(...). "
5181 "Types should be listed at most once.");
5182
5183 set(std::forward<Args>(args)...);
5184 }
5185
5202#ifndef NO_DOC
5203 template<typename... Args, typename std::enable_if<sizeof...(Args) >= 2, int>::type = 0>
5204#else
5205 template<typename... Args>
5206#endif
5207 void set(Args &&...args)
5208 {
5209 using namespace Zivid::Detail::TypeTraits;
5210
5211 using AllArgsAreDescendantNodes =
5212 AllArgsAreInTuple<Descendants, typename std::decay<Args>::type...>;
5213 static_assert(
5214 AllArgsAreDescendantNodes::value,
5215 "All arguments passed to set(...) must be descendant nodes.");
5216
5217 static_assert(
5218 AllArgsDecayedAreUnique<Args...>::value,
5219 "Found duplicate types among the arguments passed to set(...). "
5220 "Types should be listed at most once.");
5221
5222 Zivid::DataModel::Detail::invokeSetWithEachArgument(*this, std::forward<Args>(args)...);
5223 }
5224
5242#ifndef NO_DOC
5243 template<typename... Args, typename std::enable_if<sizeof...(Args) >= 1, int>::type = 0>
5244#else
5245 template<typename... Args>
5246#endif
5247 Experimental copyWith(Args &&...args) const
5248 {
5249 using namespace Zivid::Detail::TypeTraits;
5250
5251 using AllArgsAreDescendantNodes =
5252 AllArgsAreInTuple<Descendants, typename std::decay<Args>::type...>;
5253 static_assert(
5254 AllArgsAreDescendantNodes::value,
5255 "All arguments passed to copyWith(...) must be descendant nodes.");
5256
5257 static_assert(
5258 AllArgsDecayedAreUnique<Args...>::value,
5259 "Found duplicate types among the arguments passed to copyWith(...). "
5260 "Types should be listed at most once.");
5261
5262 auto copy{ *this };
5263 copy.set(std::forward<Args>(args)...);
5264 return copy;
5265 }
5266
5269 {
5270 return m_contrastDistortion;
5271 }
5272
5275 {
5276 return m_contrastDistortion;
5277 }
5278
5281 {
5282 m_contrastDistortion = value;
5283 return *this;
5284 }
5285
5288 {
5289 m_contrastDistortion.set(value);
5290 return *this;
5291 }
5292
5295 {
5296 m_contrastDistortion.set(value);
5297 return *this;
5298 }
5299
5302 {
5303 m_contrastDistortion.set(value);
5304 return *this;
5305 }
5306
5309 {
5310 m_contrastDistortion.set(value);
5311 return *this;
5312 }
5313
5316 {
5317 m_contrastDistortion.set(value);
5318 return *this;
5319 }
5320
5323 {
5324 m_contrastDistortion.set(value);
5325 return *this;
5326 }
5327
5328 template<
5329 typename T,
5330 typename std::enable_if<
5331 std::is_same<T, Settings::Processing::Filters::Experimental::ContrastDistortion>::value,
5332 int>::type = 0>
5334 {
5335 return m_contrastDistortion;
5336 }
5337
5338 template<
5339 typename T,
5340 typename std::enable_if<
5341 std::is_same<
5342 T,
5344 int>::type = 0>
5346 {
5347 return m_contrastDistortion
5349 }
5350
5351 template<
5352 typename T,
5353 typename std::enable_if<
5354 std::is_same<
5355 T,
5357 value,
5358 int>::type = 0>
5360 const
5361 {
5362 return m_contrastDistortion.get<
5364 }
5365
5366 template<
5367 typename T,
5368 typename std::enable_if<
5369 std::is_same<
5370 T,
5372 value,
5373 int>::type = 0>
5375 const
5376 {
5377 return m_contrastDistortion.get<
5379 }
5380
5381 template<
5382 typename T,
5383 typename std::enable_if<
5384 std::is_same<T, Settings::Processing::Filters::Experimental::ContrastDistortion::Removal>::
5385 value,
5386 int>::type = 0>
5388 {
5389 return m_contrastDistortion
5391 }
5392
5393 template<
5394 typename T,
5395 typename std::enable_if<
5396 std::is_same<
5397 T,
5399 value,
5400 int>::type = 0>
5402 {
5403 return m_contrastDistortion
5405 }
5406
5407 template<
5408 typename T,
5409 typename std::enable_if<
5410 std::is_same<
5411 T,
5413 value,
5414 int>::type = 0>
5416 const
5417 {
5418 return m_contrastDistortion
5420 }
5421
5422 template<size_t i, typename std::enable_if<i == 0, int>::type = 0>
5424 {
5425 return m_contrastDistortion;
5426 }
5427
5429 template<typename F>
5430 void forEach(const F &f) const
5431 {
5432 f(m_contrastDistortion);
5433 }
5434
5436 template<typename F>
5437 void forEach(const F &f)
5438 {
5439 f(m_contrastDistortion);
5440 }
5441
5443 bool operator==(const Experimental &other) const;
5444
5446 bool operator!=(const Experimental &other) const;
5447
5449 std::string toString() const;
5450
5452 friend std::ostream &operator<<(std::ostream &stream, const Experimental &value)
5453 {
5454 return stream << value.toString();
5455 }
5456
5457 private:
5458 void setFromString(const std::string &value);
5459
5460 void setFromString(const std::string &fullPath, const std::string &value);
5461
5462 std::string getString(const std::string &fullPath) const;
5463
5464 ContrastDistortion m_contrastDistortion;
5465
5466 friend struct DataModel::Detail::Befriend<Experimental>;
5467 };
5468
5470
5471 // NOLINTNEXTLINE(clang-analyzer-optin.performance.Padding)
5473 {
5474 public:
5476 static constexpr DataModel::NodeType nodeType = DataModel::NodeType::group;
5477
5479 static constexpr const char *path{ "Processing/Filters/Hole" };
5480
5482 static constexpr const char *name{ "Hole" };
5483
5485 static constexpr const char *description{
5486 R"description(Contains filters that can be used to deal with holes in the point cloud.)description"
5487 };
5488
5491
5492 // NOLINTNEXTLINE(clang-analyzer-optin.performance.Padding)
5494 {
5495 public:
5497 static constexpr DataModel::NodeType nodeType = DataModel::NodeType::group;
5498
5500 static constexpr const char *path{ "Processing/Filters/Hole/Repair" };
5501
5503 static constexpr const char *name{ "Repair" };
5504
5506 static constexpr const char *description{
5507 R"description(Fills in point cloud holes by interpolating remaining surrounding points.
5508)description"
5509 };
5510
5512
5513 // NOLINTNEXTLINE(clang-analyzer-optin.performance.Padding)
5515 {
5516 public:
5518 static constexpr DataModel::NodeType nodeType = DataModel::NodeType::leafValue;
5519
5521 static constexpr const char *path{ "Processing/Filters/Hole/Repair/Enabled" };
5522
5524 static constexpr const char *name{ "Enabled" };
5525
5527 static constexpr const char *description{
5528 R"description(Enable or disable hole repair.)description"
5529 };
5530
5532 using ValueType = bool;
5533 static const Enabled yes;
5534 static const Enabled no;
5535
5537 static std::set<bool> validValues()
5538 {
5539 return { false, true };
5540 }
5541
5543 Enabled() = default;
5544
5546 explicit constexpr Enabled(bool value)
5547 : m_opt{ value }
5548 {}
5549
5554 bool value() const;
5555
5557 bool hasValue() const;
5558
5560 void reset();
5561
5563 std::string toString() const;
5564
5566 bool operator==(const Enabled &other) const
5567 {
5568 return m_opt == other.m_opt;
5569 }
5570
5572 bool operator!=(const Enabled &other) const
5573 {
5574 return m_opt != other.m_opt;
5575 }
5576
5578 friend std::ostream &operator<<(std::ostream &stream, const Enabled &value)
5579 {
5580 return stream << value.toString();
5581 }
5582
5583 private:
5584 void setFromString(const std::string &value);
5585
5586 Zivid::DataModel::Detail::Optional<bool> m_opt;
5587
5588 friend struct DataModel::Detail::Befriend<Enabled>;
5589 };
5590
5595
5596 // NOLINTNEXTLINE(clang-analyzer-optin.performance.Padding)
5598 {
5599 public:
5601 static constexpr DataModel::NodeType nodeType = DataModel::NodeType::leafValue;
5602
5604 static constexpr const char *path{ "Processing/Filters/Hole/Repair/HoleSize" };
5605
5607 static constexpr const char *name{ "HoleSize" };
5608
5610 static constexpr const char *description{
5611 R"description(Relative diameter of holes to fill. Increasing this will fill more points, but require more
5612computation time. The maximum allowed hole size scales with distance, so that we allow
5613filling larger holes at greater distances, measured in mm.
5614)description"
5615 };
5616
5618 using ValueType = double;
5619
5621 static constexpr Range<double> validRange()
5622 {
5623 return { 0.0, 1.0 };
5624 }
5625
5627 HoleSize() = default;
5628
5630 explicit constexpr HoleSize(double value)
5631 : m_opt{ verifyValue(value) }
5632 {}
5633
5638 double value() const;
5639
5641 bool hasValue() const;
5642
5644 void reset();
5645
5647 std::string toString() const;
5648
5650 bool operator==(const HoleSize &other) const
5651 {
5652 return m_opt == other.m_opt;
5653 }
5654
5656 bool operator!=(const HoleSize &other) const
5657 {
5658 return m_opt != other.m_opt;
5659 }
5660
5662 bool operator<(const HoleSize &other) const
5663 {
5664 return m_opt < other.m_opt;
5665 }
5666
5668 bool operator>(const HoleSize &other) const
5669 {
5670 return m_opt > other.m_opt;
5671 }
5672
5674 bool operator<=(const HoleSize &other) const
5675 {
5676 return m_opt <= other.m_opt;
5677 }
5678
5680 bool operator>=(const HoleSize &other) const
5681 {
5682 return m_opt >= other.m_opt;
5683 }
5684
5686 friend std::ostream &operator<<(std::ostream &stream, const HoleSize &value)
5687 {
5688 return stream << value.toString();
5689 }
5690
5691 private:
5692 void setFromString(const std::string &value);
5693
5694 constexpr ValueType static verifyValue(const ValueType &value)
5695 {
5696 return validRange().isInRange(value)
5697 ? value
5698 : throw std::out_of_range{ "HoleSize{ " + std::to_string(value)
5699 + " } is not in range ["
5700 + std::to_string(validRange().min()) + ", "
5701 + std::to_string(validRange().max()) + "]" };
5702 }
5703
5704 Zivid::DataModel::Detail::Optional<double> m_opt;
5705
5706 friend struct DataModel::Detail::Befriend<HoleSize>;
5707 };
5708
5714
5715 // NOLINTNEXTLINE(clang-analyzer-optin.performance.Padding)
5717 {
5718 public:
5720 static constexpr DataModel::NodeType nodeType = DataModel::NodeType::leafValue;
5721
5723 static constexpr const char *path{ "Processing/Filters/Hole/Repair/Strictness" };
5724
5726 static constexpr const char *name{ "Strictness" };
5727
5729 static constexpr const char *description{
5730 R"description(Level of strictness when considering if a point should be filled. A higher level of
5731strictness requires a missing point to be surrounded by valid points on more sides in
5732order to be filled. Increasing this will fill fewer points, but it will be less likely to
5733fill gaps that are not circular, for example between two edges.
5734)description"
5735 };
5736
5738 using ValueType = int32_t;
5739
5741 static constexpr Range<int32_t> validRange()
5742 {
5743 return { 1, 4 };
5744 }
5745
5747 Strictness() = default;
5748
5750 explicit constexpr Strictness(int32_t value)
5751 : m_opt{ verifyValue(value) }
5752 {}
5753
5758 int32_t value() const;
5759
5761 bool hasValue() const;
5762
5764 void reset();
5765
5767 std::string toString() const;
5768
5770 bool operator==(const Strictness &other) const
5771 {
5772 return m_opt == other.m_opt;
5773 }
5774
5776 bool operator!=(const Strictness &other) const
5777 {
5778 return m_opt != other.m_opt;
5779 }
5780
5782 bool operator<(const Strictness &other) const
5783 {
5784 return m_opt < other.m_opt;
5785 }
5786
5788 bool operator>(const Strictness &other) const
5789 {
5790 return m_opt > other.m_opt;
5791 }
5792
5794 bool operator<=(const Strictness &other) const
5795 {
5796 return m_opt <= other.m_opt;
5797 }
5798
5800 bool operator>=(const Strictness &other) const
5801 {
5802 return m_opt >= other.m_opt;
5803 }
5804
5806 friend std::ostream &operator<<(std::ostream &stream, const Strictness &value)
5807 {
5808 return stream << value.toString();
5809 }
5810
5811 private:
5812 void setFromString(const std::string &value);
5813
5814 constexpr ValueType static verifyValue(const ValueType &value)
5815 {
5816 return validRange().isInRange(value)
5817 ? value
5818 : throw std::out_of_range{ "Strictness{ " + std::to_string(value)
5819 + " } is not in range ["
5820 + std::to_string(validRange().min()) + ", "
5821 + std::to_string(validRange().max()) + "]" };
5822 }
5823
5824 Zivid::DataModel::Detail::Optional<int32_t> m_opt;
5825
5826 friend struct DataModel::Detail::Befriend<Strictness>;
5827 };
5828
5829 using Descendants = std::tuple<
5833
5836
5850#ifndef NO_DOC
5851 template<
5852 typename... Args,
5853 typename std::enable_if<sizeof...(Args) >= 1, int>::type = 0,
5854 typename std::enable_if<
5855 Zivid::Detail::TypeTraits::
5856 AllArgsAreInTuple<Descendants, typename std::decay<Args>::type...>::value,
5857 int>::type = 0>
5858#else
5859 template<typename... Args>
5860#endif
5861 explicit Repair(Args &&...args)
5862 {
5863 using namespace Zivid::Detail::TypeTraits;
5864
5865 static_assert(
5866 AllArgsDecayedAreUnique<Args...>::value,
5867 "Found duplicate types among the arguments passed to Repair(...). "
5868 "Types should be listed at most once.");
5869
5870 set(std::forward<Args>(args)...);
5871 }
5872
5885#ifndef NO_DOC
5886 template<typename... Args, typename std::enable_if<sizeof...(Args) >= 2, int>::type = 0>
5887#else
5888 template<typename... Args>
5889#endif
5890 void set(Args &&...args)
5891 {
5892 using namespace Zivid::Detail::TypeTraits;
5893
5894 using AllArgsAreDescendantNodes =
5895 AllArgsAreInTuple<Descendants, typename std::decay<Args>::type...>;
5896 static_assert(
5897 AllArgsAreDescendantNodes::value,
5898 "All arguments passed to set(...) must be descendant nodes.");
5899
5900 static_assert(
5901 AllArgsDecayedAreUnique<Args...>::value,
5902 "Found duplicate types among the arguments passed to set(...). "
5903 "Types should be listed at most once.");
5904
5905 Zivid::DataModel::Detail::invokeSetWithEachArgument(*this, std::forward<Args>(args)...);
5906 }
5907
5921#ifndef NO_DOC
5922 template<typename... Args, typename std::enable_if<sizeof...(Args) >= 1, int>::type = 0>
5923#else
5924 template<typename... Args>
5925#endif
5926 Repair copyWith(Args &&...args) const
5927 {
5928 using namespace Zivid::Detail::TypeTraits;
5929
5930 using AllArgsAreDescendantNodes =
5931 AllArgsAreInTuple<Descendants, typename std::decay<Args>::type...>;
5932 static_assert(
5933 AllArgsAreDescendantNodes::value,
5934 "All arguments passed to copyWith(...) must be descendant nodes.");
5935
5936 static_assert(
5937 AllArgsDecayedAreUnique<Args...>::value,
5938 "Found duplicate types among the arguments passed to copyWith(...). "
5939 "Types should be listed at most once.");
5940
5941 auto copy{ *this };
5942 copy.set(std::forward<Args>(args)...);
5943 return copy;
5944 }
5945
5947 const Enabled &isEnabled() const
5948 {
5949 return m_enabled;
5950 }
5951
5954 {
5955 return m_enabled;
5956 }
5957
5959 Repair &set(const Enabled &value)
5960 {
5961 m_enabled = value;
5962 return *this;
5963 }
5964
5966 const HoleSize &holeSize() const
5967 {
5968 return m_holeSize;
5969 }
5970
5973 {
5974 return m_holeSize;
5975 }
5976
5978 Repair &set(const HoleSize &value)
5979 {
5980 m_holeSize = value;
5981 return *this;
5982 }
5983
5985 const Strictness &strictness() const
5986 {
5987 return m_strictness;
5988 }
5989
5992 {
5993 return m_strictness;
5994 }
5995
5997 Repair &set(const Strictness &value)
5998 {
5999 m_strictness = value;
6000 return *this;
6001 }
6002
6003 template<
6004 typename T,
6005 typename std::enable_if<
6006 std::is_same<T, Settings::Processing::Filters::Hole::Repair::Enabled>::value,
6007 int>::type = 0>
6009 {
6010 return m_enabled;
6011 }
6012
6013 template<
6014 typename T,
6015 typename std::enable_if<
6016 std::is_same<T, Settings::Processing::Filters::Hole::Repair::HoleSize>::value,
6017 int>::type = 0>
6019 {
6020 return m_holeSize;
6021 }
6022
6023 template<
6024 typename T,
6025 typename std::enable_if<
6026 std::is_same<T, Settings::Processing::Filters::Hole::Repair::Strictness>::value,
6027 int>::type = 0>
6029 {
6030 return m_strictness;
6031 }
6032
6033 template<size_t i, typename std::enable_if<i == 0, int>::type = 0>
6035 {
6036 return m_enabled;
6037 }
6038
6039 template<size_t i, typename std::enable_if<i == 1, int>::type = 0>
6041 {
6042 return m_holeSize;
6043 }
6044
6045 template<size_t i, typename std::enable_if<i == 2, int>::type = 0>
6047 {
6048 return m_strictness;
6049 }
6050
6052 template<typename F>
6053 void forEach(const F &f) const
6054 {
6055 f(m_enabled);
6056 f(m_holeSize);
6057 f(m_strictness);
6058 }
6059
6061 template<typename F>
6062 void forEach(const F &f)
6063 {
6064 f(m_enabled);
6065 f(m_holeSize);
6066 f(m_strictness);
6067 }
6068
6070 bool operator==(const Repair &other) const;
6071
6073 bool operator!=(const Repair &other) const;
6074
6076 std::string toString() const;
6077
6079 friend std::ostream &operator<<(std::ostream &stream, const Repair &value)
6080 {
6081 return stream << value.toString();
6082 }
6083
6084 private:
6085 void setFromString(const std::string &value);
6086
6087 void setFromString(const std::string &fullPath, const std::string &value);
6088
6089 std::string getString(const std::string &fullPath) const;
6090
6091 Enabled m_enabled;
6092 HoleSize m_holeSize;
6093 Strictness m_strictness;
6094
6095 friend struct DataModel::Detail::Befriend<Repair>;
6096 };
6097
6098 using Descendants = std::tuple<
6103
6106
6121#ifndef NO_DOC
6122 template<
6123 typename... Args,
6124 typename std::enable_if<sizeof...(Args) >= 1, int>::type = 0,
6125 typename std::enable_if<
6126 Zivid::Detail::TypeTraits::
6127 AllArgsAreInTuple<Descendants, typename std::decay<Args>::type...>::value,
6128 int>::type = 0>
6129#else
6130 template<typename... Args>
6131#endif
6132 explicit Hole(Args &&...args)
6133 {
6134 using namespace Zivid::Detail::TypeTraits;
6135
6136 static_assert(
6137 AllArgsDecayedAreUnique<Args...>::value,
6138 "Found duplicate types among the arguments passed to Hole(...). "
6139 "Types should be listed at most once.");
6140
6141 set(std::forward<Args>(args)...);
6142 }
6143
6157#ifndef NO_DOC
6158 template<typename... Args, typename std::enable_if<sizeof...(Args) >= 2, int>::type = 0>
6159#else
6160 template<typename... Args>
6161#endif
6162 void set(Args &&...args)
6163 {
6164 using namespace Zivid::Detail::TypeTraits;
6165
6166 using AllArgsAreDescendantNodes =
6167 AllArgsAreInTuple<Descendants, typename std::decay<Args>::type...>;
6168 static_assert(
6169 AllArgsAreDescendantNodes::value,
6170 "All arguments passed to set(...) must be descendant nodes.");
6171
6172 static_assert(
6173 AllArgsDecayedAreUnique<Args...>::value,
6174 "Found duplicate types among the arguments passed to set(...). "
6175 "Types should be listed at most once.");
6176
6177 Zivid::DataModel::Detail::invokeSetWithEachArgument(*this, std::forward<Args>(args)...);
6178 }
6179
6194#ifndef NO_DOC
6195