56template<
typename Output,
typename Input>
59 static Output clamp(
const Input& value)
noexcept
61 static_assert(std::is_arithmetic_v<Output>,
"Output must be arithmetic");
62 static_assert(std::is_arithmetic_v<Input>,
"Input must be arithmetic");
64 if constexpr (std::is_same_v<Input, Output>)
68 else if constexpr (std::is_same_v<Input, bool> || std::is_same_v<Output, bool>)
70 return static_cast<Output
>(value);
74 constexpr const auto max_output = std::numeric_limits<Output>::max();
75 if constexpr (std::is_unsigned_v<Input> && std::is_unsigned_v<Output>)
77 return value > max_output ? max_output :
static_cast<Output
>(value);
79 else if constexpr (std::is_unsigned_v<Input> && std::is_signed_v<Output>)
81 return value >= max_output ? max_output :
static_cast<Output
>(value);
83 else if constexpr (std::is_signed_v<Input> && std::is_unsigned_v<Output>)
91 return static_cast<uint64_t
>(value) > max_output ? max_output :
static_cast<Output
>(value);
98 constexpr const auto min_output = std::numeric_limits<Output>::lowest();
99 return value <= min_output ? min_output : static_cast<Output>(value);
103 if constexpr (max_output > std::numeric_limits<Input>::max())
105 return static_cast<Output
>(value);
109 return value > max_output ? max_output :
static_cast<Output
>(value);
117template <
typename Output>
120 static Output clamp(
const float16_t& value)
noexcept
122 return Clamper<Output, float>::clamp(
static_cast<float>(value));
126template <
typename Input>
129 static float16_t clamp(
const Input& value)
noexcept
131 return float16_t(
static_cast<double>(value));
144template<
typename Output,
typename Input>
145Output clamp(
const Input& value)
noexcept
147 return Clamper<Output, Input>::clamp(value);
150template <
typename SourceType,
typename DestinationType>
153 const void*
const __restrict pSourceBuffer,
154 void*
const __restrict pDestinationBuffer,
157 auto pReadPosition =
static_cast<const std::byte*
>(pSourceBuffer) + sSource.offset;
158 auto pWritePosition =
static_cast<std::byte*
>(pDestinationBuffer) + sDestination.offset;
160 if constexpr (std::is_same_v<SourceType, DestinationType>)
162 if (sSource.stride ==
sizeof(SourceType) &&
163 sSource.stride == sDestination.stride &&
164 sSource.endianess == sDestination.endianess)
166 std::memcpy(pWritePosition, pReadPosition,
sizeof(SourceType) * nCount);
171 if (sSource.endianess == get_byteorder())
173 if (sSource.endianess == sDestination.endianess)
175 for (
size_t nIndex = 0; nIndex < nCount; ++nIndex)
177 *(
reinterpret_cast<DestinationType*
>(pWritePosition)) = clamp<DestinationType>(access<SourceType, false>(pReadPosition));
178 pReadPosition += sSource.stride;
179 pWritePosition += sDestination.stride;
184 for (
size_t nIndex = 0; nIndex < nCount; ++nIndex)
186 *(
reinterpret_cast<DestinationType*
>(pWritePosition)) = byte_swap(clamp<DestinationType>(access<SourceType, false>(pReadPosition)));
187 pReadPosition += sSource.stride;
188 pWritePosition += sDestination.stride;
194 if (sSource.endianess == sDestination.endianess)
196 if constexpr (std::is_same_v<SourceType, DestinationType>)
198 for (
size_t nIndex = 0; nIndex < nCount; ++nIndex)
200 *(
reinterpret_cast<DestinationType*
>(pWritePosition)) = *(
reinterpret_cast<const SourceType*
>(pReadPosition));
201 pReadPosition += sSource.stride;
202 pWritePosition += sDestination.stride;
207 for (
size_t nIndex = 0; nIndex < nCount; ++nIndex)
209 *(
reinterpret_cast<DestinationType*
>(pWritePosition)) = byte_swap(clamp<DestinationType>(access<SourceType, true>(pReadPosition)));
210 pReadPosition += sSource.stride;
211 pWritePosition += sDestination.stride;
217 for (
size_t nIndex = 0; nIndex < nCount; ++nIndex)
219 *(
reinterpret_cast<DestinationType*
>(pWritePosition)) = clamp<DestinationType>(access<SourceType, true>(pReadPosition));
220 pReadPosition += sSource.stride;
221 pWritePosition += sDestination.stride;
227template <
typename SourceType>
229 const tAttribute& sDestinationAttribute,
230 const void*
const __restrict pSourceBuffer,
231 void*
const __restrict pDestinationBuffer,
234 switch (sDestinationAttribute.type)
236 case tAttribute::tDataType::dt_boolean: copy<SourceType, bool>(sSource, sDestinationAttribute.sInMemory, pSourceBuffer, pDestinationBuffer, nCount);
break;
237 case tAttribute::tDataType::dt_int8: copy<SourceType, int8_t>(sSource, sDestinationAttribute.sInMemory, pSourceBuffer, pDestinationBuffer, nCount);
break;
238 case tAttribute::tDataType::dt_uint8: copy<SourceType, uint8_t>(sSource, sDestinationAttribute.sInMemory, pSourceBuffer, pDestinationBuffer, nCount);
break;
239 case tAttribute::tDataType::dt_int16: copy<SourceType, int16_t>(sSource, sDestinationAttribute.sInMemory, pSourceBuffer, pDestinationBuffer, nCount);
break;
240 case tAttribute::tDataType::dt_uint16: copy<SourceType, uint16_t>(sSource, sDestinationAttribute.sInMemory, pSourceBuffer, pDestinationBuffer, nCount);
break;
241 case tAttribute::tDataType::dt_int32: copy<SourceType, int32_t>(sSource, sDestinationAttribute.sInMemory, pSourceBuffer, pDestinationBuffer, nCount);
break;
242 case tAttribute::tDataType::dt_uint32: copy<SourceType, uint32_t>(sSource, sDestinationAttribute.sInMemory, pSourceBuffer, pDestinationBuffer, nCount);
break;
243 case tAttribute::tDataType::dt_int64: copy<SourceType, int64_t>(sSource, sDestinationAttribute.sInMemory, pSourceBuffer, pDestinationBuffer, nCount);
break;
244 case tAttribute::tDataType::dt_uint64: copy<SourceType, uint64_t>(sSource, sDestinationAttribute.sInMemory, pSourceBuffer, pDestinationBuffer, nCount);
break;
245 case tAttribute::tDataType::dt_float16: copy<SourceType, float16_t>(sSource, sDestinationAttribute.sInMemory, pSourceBuffer, pDestinationBuffer, nCount);
break;
246 case tAttribute::tDataType::dt_float32: copy<SourceType, float>(sSource, sDestinationAttribute.sInMemory, pSourceBuffer, pDestinationBuffer, nCount);
break;
247 case tAttribute::tDataType::dt_float64: copy<SourceType, double>(sSource, sDestinationAttribute.sInMemory, pSourceBuffer, pDestinationBuffer, nCount);
break;
248 case tAttribute::tDataType::dt_computed_from_index:
throw std::runtime_error(
"unexpected");
break;
252inline void copy(
const tAttribute& sSourceAttribute,
253 const tAttribute& sDestinationAttribute,
254 const void*
const __restrict pSourceBuffer,
255 void*
const __restrict pDestinationBuffer,
258 switch (sSourceAttribute.type)
260 case tAttribute::tDataType::dt_boolean: copy<bool>(sSourceAttribute.sInMemory, sDestinationAttribute, pSourceBuffer, pDestinationBuffer, nCount);
break;
261 case tAttribute::tDataType::dt_int8: copy<int8_t>(sSourceAttribute.sInMemory, sDestinationAttribute, pSourceBuffer, pDestinationBuffer, nCount);
break;
262 case tAttribute::tDataType::dt_uint8: copy<uint8_t>(sSourceAttribute.sInMemory, sDestinationAttribute, pSourceBuffer, pDestinationBuffer, nCount);
break;
263 case tAttribute::tDataType::dt_int16: copy<int16_t>(sSourceAttribute.sInMemory, sDestinationAttribute, pSourceBuffer, pDestinationBuffer, nCount);
break;
264 case tAttribute::tDataType::dt_uint16: copy<uint16_t>(sSourceAttribute.sInMemory, sDestinationAttribute, pSourceBuffer, pDestinationBuffer, nCount);
break;
265 case tAttribute::tDataType::dt_int32: copy<int32_t>(sSourceAttribute.sInMemory, sDestinationAttribute, pSourceBuffer, pDestinationBuffer, nCount);
break;
266 case tAttribute::tDataType::dt_uint32: copy<uint32_t>(sSourceAttribute.sInMemory, sDestinationAttribute, pSourceBuffer, pDestinationBuffer, nCount);
break;
267 case tAttribute::tDataType::dt_int64: copy<int64_t>(sSourceAttribute.sInMemory, sDestinationAttribute, pSourceBuffer, pDestinationBuffer, nCount);
break;
268 case tAttribute::tDataType::dt_uint64: copy<uint64_t>(sSourceAttribute.sInMemory, sDestinationAttribute, pSourceBuffer, pDestinationBuffer, nCount);
break;
269 case tAttribute::tDataType::dt_float16: copy<float16_t>(sSourceAttribute.sInMemory, sDestinationAttribute, pSourceBuffer, pDestinationBuffer, nCount);
break;
270 case tAttribute::tDataType::dt_float32: copy<float>(sSourceAttribute.sInMemory, sDestinationAttribute, pSourceBuffer, pDestinationBuffer, nCount);
break;
271 case tAttribute::tDataType::dt_float64: copy<double>(sSourceAttribute.sInMemory, sDestinationAttribute, pSourceBuffer, pDestinationBuffer, nCount);
break;
272 case tAttribute::tDataType::dt_computed_from_index:
throw std::runtime_error(
"unexpected");
break;
276inline void copy_attributes(
const tAttributes& oSourceAttributes,
277 const tAttributes& oDestAttributes,
278 const void*
const __restrict pSourceData,
279 void*
const __restrict pDestData,
281 bool bIgnoreMissing =
true)
283 for (
const auto& oTuple : oDestAttributes)
285 const auto& oDestAttr = std::get<tAttribute>(oTuple);
286 const auto& strDestAttrName = std::get<std::string>(oTuple);
288 if (oDestAttr.type == tAttribute::tDataType::dt_computed_from_index)
290 THROW_ERROR_DESC(ERR_INVALID_ARG,
"The destination attribute %s is of type computed_from_index, which cannot be written to.",
291 strDestAttrName.c_str());
294 if (!oSourceAttributes.exists(strDestAttrName))
301 THROW_ERROR_DESC(ERR_NOT_FOUND,
"The source does not contain the %s attribute.", strDestAttrName.c_str());
304 const auto& oSourceAttr = oSourceAttributes.at(strDestAttrName);
306 copy(oSourceAttr, oDestAttr, pSourceData, pDestData, nCount);
310template <
bool exclude = true,
typename Elements>
311tAttributes filter(
const tAttributes& oSourceAttributes,
const Elements& elements)
315 if constexpr(exclude)
317 for (
const auto& oAttribute : oSourceAttributes)
319 if (std::find(elements.begin(), elements.end(), std::get<0>(oAttribute)) ==
322 oResult.add(std::get<0>(oAttribute), std::get<1>(oAttribute));
328 for (
const auto& oAttribute : oSourceAttributes)
330 if (std::find(elements.begin(), elements.end(), std::get<0>(oAttribute)) !=
333 oResult.add(std::get<0>(oAttribute), std::get<1>(oAttribute));
345 enum struct tTransformation
350 cartesian_to_polar = 3,
351 polar_to_cartesian = 4,
354 static tTransformation GetSupportedTransformation(
const tAttributes& oSourceAttributes,
355 const tAttributes& oDestAttributes)
357 const auto bAllDestinationAttributesInSource = [&]()
359 for (
const auto& strDestinationAttribute: oDestAttributes)
361 if (!oSourceAttributes.exists(std::get<0>(strDestinationAttribute)))
369 if (bAllDestinationAttributesInSource)
371 return tTransformation::copy_all;
373 else if (CanTransform<cTransformCartesianToPolar>(oSourceAttributes, oDestAttributes))
375 return tTransformation::cartesian_to_polar;
377 else if (CanTransform<cTransformPolarToCartesian>(oSourceAttributes, oDestAttributes))
379 return tTransformation::polar_to_cartesian;
383 return tTransformation::none;
387 static void Transform(tTransformation eTransformType,
388 const tAttributes& oSourceAttributes,
389 const tAttributes& oDestAttributes,
394 switch (eTransformType)
396 case tTransformation::cartesian_to_polar:
398 cTransformCartesianToPolar::transform(oSourceAttributes, oDestAttributes, nCount, oSourceBuffer, oDestinationBuffer);
401 case tTransformation::polar_to_cartesian:
403 cTransformPolarToCartesian::transform(oSourceAttributes, oDestAttributes, nCount, oSourceBuffer, oDestinationBuffer);
406 case tTransformation::copy_all:
408 detail::copy_attributes(oSourceAttributes, oDestAttributes, oSourceBuffer.pData, oDestinationBuffer.pData, nCount);
411 case tTransformation::copy_existing:
413 detail::copy_attributes(oSourceAttributes, oDestAttributes, oSourceBuffer.pData, oDestinationBuffer.pData, nCount,
true);
416 case tTransformation::none:
425 bool bIgnoreMissingAdditionalAttributes =
false)
427 if (*oSource.GetCount() != *oDestination.GetCount())
429 THROW_ERROR_DESC(ERR_INVALID_ARG,
430 "The layouts have no matching amount of points within their pointclouds (%zu vs. %zu).",
431 *oSource.GetCount(), *oDestination.GetCount());
434 const auto& oSourceAttributes = oSource.GetAttributes();
435 const auto& oDestAttributes = oDestination.GetAttributes();
437 const auto nSourceBufferSize = oSource.GetBufferSize();
438 const auto nDestBufferSize = oDestination.GetBufferSize();
441 if (oSourceAttributes == oDestAttributes)
443 if (nSourceBufferSize != nDestBufferSize)
445 THROW_ERROR_DESC(ERR_MEMORY,
"Can only copy buffers with same sizes (%zu vs. %zu).",
446 nSourceBufferSize, nDestBufferSize);
449 std::memcpy(oDestination.GetMutableData(), oSource.GetData(), nSourceBufferSize);
453 using namespace std::literals;
454 static const std::array<std::string, 6> oMandatoryNames{
"x"s,
"y"s,
"z"s,
"distance"s,
"yaw"s,
"pitch"s};
456 const auto oMandatoryAttributes = detail::filter<false>(oDestAttributes, oMandatoryNames);
457 const auto oAdditionalAttributes = detail::filter<true>(oDestAttributes, oMandatoryNames);
459 const auto eMandatoryTransformType = cPointCloudTransformation::GetSupportedTransformation(oSourceAttributes,
460 oMandatoryAttributes);
461 if (eMandatoryTransformType == cPointCloudTransformation::tTransformation::none)
463 THROW_ERROR_DESC(ERR_NOT_SUPPORTED,
"No transformation for mandatory attributes found.");
466 const auto nCount = *oSource.GetCount();
467 Transform(eMandatoryTransformType,
469 oMandatoryAttributes,
474 if (!oAdditionalAttributes.empty())
476 auto eAdditionlTransformType = cPointCloudTransformation::GetSupportedTransformation(oSourceAttributes,
477 oAdditionalAttributes);
478 if (eAdditionlTransformType == cPointCloudTransformation::tTransformation::none)
480 if (!bIgnoreMissingAdditionalAttributes)
482 THROW_ERROR_DESC(ERR_NOT_SUPPORTED,
"No transformation for additonal attributes found.");
485 eAdditionlTransformType = cPointCloudTransformation::tTransformation::copy_existing;
488 Transform(eAdditionlTransformType,
490 oAdditionalAttributes,
500 template <
typename Transform>
501 static bool CanTransform(
const tAttributes& oSourceAttributes,
502 const tAttributes& oDestAttributes)
504 for (
const auto& strSourceElement: Transform::required_source_elements)
506 if (!oSourceAttributes.exists(strSourceElement))
512 for (
const auto& strDestinationElement: Transform::required_destination_elements)
514 if (!oDestAttributes.exists(strDestinationElement) ||
515 oDestAttributes.at(strDestinationElement).type == tAttribute::tDataType::dt_computed_from_index)
524 struct cTransformCartesianToPolar
526 static constexpr std::array<const char*, 3> required_source_elements = {
"x",
"y",
"z"};
527 static constexpr std::array<const char*, 3> required_destination_elements = {
"distance",
"yaw",
"pitch"};
532 static void transform(
const tAttributes& oSourceAttributes,
533 const tAttributes& oDestAttributes,
534 const size_t& nCount,
538 using namespace std::literals;
539 const auto& oX = oSourceAttributes.at(
"x"s);
540 const auto& oY = oSourceAttributes.at(
"y"s);
541 const auto& oZ = oSourceAttributes.at(
"z"s);
543 const auto& oDistance = oDestAttributes.at(
"distance"s);
544 const auto& oYaw = oDestAttributes.at(
"yaw"s);
545 const auto& oPitch = oDestAttributes.at(
"pitch"s);
547 for (
size_t nIdx = 0; nIdx < nCount; nIdx++)
550 const auto x = detail::to_type<double>(get_attribute_value(oX, oSourceBuffer, nIdx));
551 const auto y = detail::to_type<double>(get_attribute_value(oY, oSourceBuffer, nIdx));
552 const auto z = detail::to_type<double>(get_attribute_value(oZ, oSourceBuffer, nIdx));
555 const auto distance = std::sqrt(std::pow(x, 2) + std::pow(y, 2) + std::pow(z, 2));
556 const auto yaw = std::atan2(y, x);
558 distance == 0.0 ? pitch = 0.0 : pitch = std::asin(z / distance);
561 set_attribute_value(oDistance, oDestinationBuffer, nIdx, distance);
562 set_attribute_value(oYaw, oDestinationBuffer, nIdx, yaw);
563 set_attribute_value(oPitch, oDestinationBuffer, nIdx, pitch);
568 struct cTransformPolarToCartesian
570 static constexpr std::array<const char*, 3> required_source_elements = {
"distance",
"yaw",
"pitch"};
571 static constexpr std::array<const char*, 3> required_destination_elements = {
"x",
"y",
"z"};
576 static void transform(
const tAttributes& oSourceAttributes,
577 const tAttributes& oDestAttributes,
578 const size_t& nCount,
582 using namespace std::literals;
584 const auto& oDistance = oSourceAttributes.at(
"distance"s);
585 const auto& oYaw = oSourceAttributes.at(
"yaw"s);
586 const auto& oPitch = oSourceAttributes.at(
"pitch"s);
588 const auto& oX = oDestAttributes.at(
"x"s);
589 const auto& oY = oDestAttributes.at(
"y"s);
590 const auto& oZ = oDestAttributes.at(
"z"s);
592 for (
size_t nIdx = 0; nIdx < nCount; ++nIdx)
595 const auto distance = detail::to_type<double>(get_attribute_value(oDistance, oSourceBuffer, nIdx));
596 const auto yaw = detail::to_type<double>(get_attribute_value(oYaw, oSourceBuffer, nIdx));
597 const auto pitch = detail::to_type<double>(get_attribute_value(oPitch, oSourceBuffer, nIdx));
600 const auto x = distance * std::cos(pitch) * std::cos(yaw);
601 const auto y = distance * std::cos(pitch) * std::sin(yaw);
602 const auto z = distance * std::sin(pitch);
605 set_attribute_value(oX, oDestinationBuffer, nIdx, x);
606 set_attribute_value(oY, oDestinationBuffer, nIdx, y);
607 set_attribute_value(oZ, oDestinationBuffer, nIdx, z);
Namespace for functionality provided by 3.13.0.
Definition pointcloud_access.h:52
Namespace for pointcloud in ADTF-Devicetoolbox.
Definition pointcloud_access.h:49
Namespace for SDK of ADTF-Devicetoolbox.
Definition bus_database_intf.h:42
Devicetoolbox - Namespace.
Definition bus_database_intf.h:36
ADTF - Namespace.
Definition bus_database_intf.h:30
Definition pointcloud_data.h:627
Definition pointcloud_transformation.h:58
Definition pointcloud_types.h:307
Definition pointcloud_types.h:316
Definition pointcloud_access.h:55
Definition pointcloud_types.h:113