MeVisLab Toolbox Reference
mlPCLInventorTools.h
Go to the documentation of this file.
1 // Copyright (c) Fraunhofer MEVIS, Germany. All rights reserved.
2 // **InsertLicense** code author="Wolf Spindler"
3 //----------------------------------------------------------------------------------
5 
12 //----------------------------------------------------------------------------------
13 #pragma once
14 
16 #include <mlPCLTypes.h>
17 #include <mlPCLSupportTools.h>
18 #include <mlErrorMacros.h>
19 #include <mlRangeCasts.h>
21 #include <Inventor/nodes/SoVertexProperty.h>
23 
24 // Forwards to internally used classes.
25 class SoVertexProperty;
26 class SoMFInt32;
27 
28 ML_START_NAMESPACE
29 
31 namespace PCLInventorTools {
32 
33 //----------------------------------------------------------------------------------
34 // DESTINATION: SbVec2f
35 //----------------------------------------------------------------------------------
36 
37 //----------------------------------------------------------------------------------
41 //----------------------------------------------------------------------------------
42 inline void setOneMFVecFieldValue(SbVec2f *dstVal, const float data[4])
43 {
44  dstVal->setValue(data[0], data[1]);
45 }
46 
47 //----------------------------------------------------------------------------------
52 //----------------------------------------------------------------------------------
53 inline void setOneMFVecFieldValue(SbVec2f *dstVal, const unsigned int * /*rgbaVal*/)
54 {
55  dstVal->setValue(0.f, 0.f);
56 }
57 
58 //----------------------------------------------------------------------------------
62 //----------------------------------------------------------------------------------
63 inline void setOneMFVecFieldValue(SbVec2f *dstVal, float data)
64 {
65  dstVal->setValue(data, data);
66 }
67 
68 
69 //----------------------------------------------------------------------------------
70 // DESTINATION: SbVec3f
71 //----------------------------------------------------------------------------------
72 
73 //----------------------------------------------------------------------------------
77 //----------------------------------------------------------------------------------
78 inline void setOneMFVecFieldValue(SbVec3f *dstVal, const float data[4])
79 {
80  dstVal->setValue(data[0], data[1], data[2]);
81 }
82 
83 //----------------------------------------------------------------------------------
88 //----------------------------------------------------------------------------------
89 inline void setOneMFVecFieldValue(SbVec3f *dstVal, const unsigned int * /*rgbaVal*/)
90 {
91  dstVal->setValue(0.f, 0.f, 0.f);
92 }
93 
94 //----------------------------------------------------------------------------------
98 //----------------------------------------------------------------------------------
99 inline void setOneMFVecFieldValue(SbVec3f *dstVal, float data)
100 {
101  dstVal->setValue(data, data, data);
102 }
103 
104 
105 
106 //----------------------------------------------------------------------------------
107 // DESTINATION: MLuint32
108 //----------------------------------------------------------------------------------
109 
110 //----------------------------------------------------------------------------------
115 //----------------------------------------------------------------------------------
116 inline void setOneMFVecFieldValue(MLuint32 *dstVal, const float data)
117 {
118  const MLuint32 byteVal = static_cast<MLuint32>(data);
119  *dstVal = (byteVal | (byteVal << 8) | (byteVal << 16) | (byteVal << 24));
120 }
121 
122 //----------------------------------------------------------------------------------
127 //----------------------------------------------------------------------------------
128 inline void setOneMFVecFieldValue(MLuint32 *dstVal, const float data[4])
129 {
130  *dstVal = ((static_cast<MLuint32>(data[3]) ) |
131  (static_cast<MLuint32>(data[2]) << 8) |
132  (static_cast<MLuint32>(data[1]) << 16) |
133  (static_cast<MLuint32>(data[0]) << 24) );
134 }
135 
136 //----------------------------------------------------------------------------------
138 //----------------------------------------------------------------------------------
139 inline void setOneMFVecFieldValue(MLuint32 *dstVal, const unsigned int *rgbaVal)
140 {
141  *dstVal = ( (( (*rgbaVal) >> 24) & 0x000000ff) |
142  (( (*rgbaVal) >> 8) & 0x0000ff00) |
143  (( (*rgbaVal) << 8) & 0x00ff0000) |
144  (( (*rgbaVal) << 24) & 0xff000000) );
145 }
146 
147 //----------------------------------------------------------------------------------
152 //----------------------------------------------------------------------------------
153 #if defined(_MSC_VER) && !defined(_WIN64) && ((_MSC_VER == 1600) || (_MSC_VER == 1900))
154 #define SpecializedPCLPointXYZ EIGEN_WORKAROUND_MSVC_STL_SUPPORT(pcl::PointXYZ)
155 #else
156 #define SpecializedPCLPointXYZ pcl::PointXYZ
157 #endif
158 
159 //----------------------------------------------------------------------------------
162 //----------------------------------------------------------------------------------
163 template <typename DST_VAL_TYPE>
164 inline void setOneMFVecFieldValueFromPoint(DST_VAL_TYPE *dstVal, const SpecializedPCLPointXYZ &pnt, bool useData_n)
165 {
166  const float zeroData_n[4] = {0.f, 0.f, 0.f, 0.f};
167  setOneMFVecFieldValue(dstVal, useData_n ? zeroData_n : pnt.data);
168 }
169 
170 //----------------------------------------------------------------------------------
172 //----------------------------------------------------------------------------------
173 template <typename POINT_TYPE, typename DST_VAL_TYPE>
174 inline void setOneMFVecFieldValueFromPoint(DST_VAL_TYPE *dstVal, const POINT_TYPE &pnt, bool useData_n)
175 {
176  setOneMFVecFieldValue(dstVal, useData_n ? pnt.data_n : pnt.data);
177 }
178 
179 //----------------------------------------------------------------------------------
181 //----------------------------------------------------------------------------------
182 template <typename DST_VAL_TYPE>
183 inline void setTwoMFVecFieldValuesFromPoint(DST_VAL_TYPE *dstVal, const SpecializedPCLPointXYZ &pnt)
184 {
185  setOneMFVecFieldValue(dstVal , pnt.data);
186  setOneMFVecFieldValue(dstVal+1, pnt.data);
187 }
188 
189 //----------------------------------------------------------------------------------
191 //----------------------------------------------------------------------------------
192 template <typename POINT_TYPE, typename DST_VAL_TYPE>
193 inline void setTwoMFVecFieldValuesFromPoint(DST_VAL_TYPE *dstVal, const POINT_TYPE &pnt)
194 {
195  setOneMFVecFieldValue(dstVal , pnt.data );
196  setOneMFVecFieldValue(dstVal+1, pnt.data_n);
197  dstVal[1] += dstVal[0];
198 }
199 
200 //----------------------------------------------------------------------------------
203 //----------------------------------------------------------------------------------
210  UseOnlyRGBA,
219 };
220 
221 //----------------------------------------------------------------------------------
225 //----------------------------------------------------------------------------------
226 MLPCL_InventorAdapters_EXPORT void getRainbowRGB_From0_to_1(float intensity, float retRGB[3]);
227 
228 //----------------------------------------------------------------------------------
253 //----------------------------------------------------------------------------------
254 template <typename POINT_CLOUD_TYPE, typename SM_MF_VEC_FIELD_TYPE>
255 inline size_t setMFVecFromPointCloud(const POINT_CLOUD_TYPE &pointCloud,
256  SM_MF_VEC_FIELD_TYPE &mfvecField,
257  PCLMFVecStorageTypes storageType,
258  bool duplicateColors=false,
259  bool mapToRainbow=false,
260  bool useCurvatureForColor=false,
261  bool scaleFromInputRange=false,
262  float inRangeMin=0.f,
263  float inRangeMax=1.f)
264 {
265  // Ensure default scaling if scaleFromInputRange is false.
266  if (!scaleFromInputRange){
267  inRangeMin=0.f;
268  inRangeMax=1.f;
269  }
270  // Precalculate time critical calculations by inverting divisor safely.
271  const float scaleWidth = fabs(inRangeMax-inRangeMin) < 10e-6f ? 10e-6f : inRangeMax-inRangeMin;
272  const float scaleWidthInv = 1.f/scaleWidth;
273 
274  bool isSet = false;
275  const size_t numPoints = pointCloud.points.size();
276  if ((numPoints * (CopyDataAndData_n == storageType ? 2 : 1)) <= ML_NAMESPACE::PCLSupportTools::getSigned32BitMaximumLimit()){
277  const unsigned int numPointsAsUInt = mlrange_cast<unsigned int>(numPoints);
278  if ((CopyFromData == storageType) ||
279  (CopyFromData_n == storageType)){
280  mfvecField.setNum(mlrange_cast<int>(numPoints));
281 
282  // Enable fast direct pointer array editing on the inventor field data.
283  auto dataPtr = mfvecField.startEditing();
284  const bool copyFromData_n = (CopyFromData_n == storageType);
285  for (unsigned int c=0; c < numPointsAsUInt; ++c){
286  // Note: No scaling, because it is not very useful on RGB[A] data, it is needed only for incoming scalar colour scaling.
287  setOneMFVecFieldValueFromPoint(dataPtr+c, pointCloud.points[c], copyFromData_n);
288  }
289  mfvecField.finishEditing();
290  isSet = true;
291  }
292  else if (UseOnlyRGBA == storageType){
293  // Enable fast direct pointer array editing on the inventor field data.
294  mfvecField.setNum(mlrange_cast<int>(numPoints * (duplicateColors ? 2u:1u)));
295  auto dataPtr = mfvecField.startEditing();
296  // Use direct copying of .rgba to uint32 inventor data values.
297  for (unsigned int c=0; c < numPointsAsUInt; ++c){
298  const unsigned int rgbaVal = ML_NAMESPACE::PCLSupportTools::getPointRGBA(pointCloud.points[c]);
299  // Note: No scaling, because it is not very useful on RGB[A] data, it is needed only for incoming scalar colour scaling.
300  if (duplicateColors){
301  setOneMFVecFieldValue(dataPtr+c*2 , &rgbaVal);
302  setOneMFVecFieldValue(dataPtr+c*2+1, &rgbaVal);
303  }
304  else{
305  setOneMFVecFieldValue(dataPtr+c , &rgbaVal);
306  }
307  }
308  mfvecField.finishEditing();
309  isSet = true;
310  }
311  else if ((StoreIntensitReplacementAsRGB == storageType) ||
312  (StoreIntensitReplacementAsRGBA == storageType)){
313  // Enable fast direct pointer array editing on the inventor field data.
314  mfvecField.setNum(mlrange_cast<int>(numPoints * (duplicateColors ? 2u:1u)));
315  auto dataPtr = mfvecField.startEditing();
316  // Use assignment of any value usable as intensity to RGBA voxels as grey values
317  // where the intensity value is used as an rgb triple or - if requested - as rgba quadrupel.
318  float data[4]={0,0,0,255.9f};
319  const bool isRGBAAssignment = (StoreIntensitReplacementAsRGBA == storageType);
320 
321  // An often used mode is that intensity and transparency are the same value; then we can
322  // assign the value more effectively.
323  const bool allChannelsAreTheSame = isRGBAAssignment && !useCurvatureForColor && !mapToRainbow;
324 
325  float curvatureVal = 0.f;
326  for (unsigned int c=0; c < numPointsAsUInt; ++c){
327  float dataVal = ML_NAMESPACE::PCLSupportTools::getIntensityReplacement(pointCloud.points[c]);
328  if (dataVal < inRangeMin){ dataVal = inRangeMin; }
329  else if (dataVal > inRangeMax){ dataVal = inRangeMax; }
330  if (scaleFromInputRange){
331  dataVal = (dataVal-inRangeMin)*scaleWidthInv;
332  }
333  // If dataVal is the same four RGBA values then use optimized version below.
334  if (!allChannelsAreTheSame){
335  // Channels differ, the four RGBA channels come from different sources.
336  float intensityVal = dataVal; // -> color RGB
337  float alphaVal = dataVal; // -> transparency
338 
339  // What is used as intensity (i.e. for RGB channels)?
340  if (useCurvatureForColor){
341  // Use curvature instead
342  curvatureVal = ML_NAMESPACE::PCLSupportTools::getCurvature(pointCloud.points[c]);
343  if (curvatureVal < inRangeMin){ curvatureVal = inRangeMin; }
344  else if (curvatureVal > inRangeMax){ curvatureVal = inRangeMax; }
345  if (scaleFromInputRange){
346  curvatureVal = (curvatureVal-inRangeMin)*scaleWidthInv;
347  }
348  intensityVal = curvatureVal;
349  }
350 
351  // Translate intensity to a rainbow color table (especially interesting for curvature values).
352  if (mapToRainbow){
353  float retRGB[3]={0.f, 0.f, 0.f};
354  getRainbowRGB_From0_to_1(intensityVal, retRGB);
355  data[0] = retRGB[0]*255.999f;
356  data[1] = retRGB[1]*255.999f;
357  data[2] = retRGB[2]*255.999f;
358  }
359  else{
360  // Use the same value for R, G, and B.
361  data[0] = data[1] = data[2] = intensityVal*255.999f;
362  }
363 
364  if (isRGBAAssignment){
365  // Opacity is related to dataVal.
366  data[3] = alphaVal*255.999f;
367  }
368  else{
369  // Opacity shall always be dense.
370  data[3] = 255.999f;
371  }
372  if (duplicateColors){
373  setOneMFVecFieldValue(dataPtr+c*2 , data);
374  setOneMFVecFieldValue(dataPtr+c*2+1, data);
375  }
376  else{
377  setOneMFVecFieldValue(dataPtr+c, data);
378  }
379  }
380  else{
381  dataVal*=255.999f;
382  // Use optimized version with a single float for all components.
383  if (duplicateColors){
384  setOneMFVecFieldValue(dataPtr+c*2 , dataVal);
385  setOneMFVecFieldValue(dataPtr+c*2+1, dataVal);
386  }
387  else{
388  setOneMFVecFieldValue(dataPtr+c, dataVal);
389  }
390  }
391  }
392  mfvecField.finishEditing();
393  isSet = true;
394  }
395  else if (CopyDataAndData_n == storageType){
396  // Enable fast direct pointer array editing on the inventor field data.
397  mfvecField.setNum(mlrange_cast<int>(numPoints*2u));
398  auto dataPtr = mfvecField.startEditing();
399  for (unsigned int c=0; c < numPointsAsUInt; ++c){
400  // Note: No scaling, because it is not very useful on vector data, it is needed only for incoming scalar colour scaling.
401  setTwoMFVecFieldValuesFromPoint(dataPtr+(c*2u), pointCloud.points[c]);
402  }
403  mfvecField.finishEditing();
404  isSet = true;
405  }
406  else{
407  ML_PRINT_ERROR("mlPCLInventorTools.h: setMFVecFromPointCloud", ML_BAD_PARAMETER,
408  "Bad enumerator value passed. Not setting any MField values.");
409  }
410  }
411  else{
412  ML_PRINT_ERROR("mlPCLInventorTools.h: setMFVecFromPointCloud", ML_BAD_PARAMETER,
413  "Inventor cannot handle field sets with more than ML_INT32_MAX points which, "
414  "however, are required for the current input data conversion. Not setting the MField values.");
415  }
416  if (!isSet){
417  mfvecField.deleteValues(0);
418  }
419  return isSet ? numPoints : 0u;
420 }
421 
422 
423 
424 //----------------------------------------------------------------------------------
430 //----------------------------------------------------------------------------------
431 MLPCL_InventorAdapters_EXPORT void setVertices(const std::vector<pcl::Vertices> &verticesVector,
432  SoMFInt32 &mfIntField,
433  bool terminateWithMinusOne);
434 
435 };
436 
437 ML_END_NAMESPACE
Project global and OS specific declarations.
#define MLPCL_InventorAdapters_EXPORT
If included by external modules, exported symbols are declared as import symbols.
Disables warnings from PCL headers which otherwise cannot be avoided.
Restores disabled warnings from PCL headers which otherwise cannot be avoided.
#define ML_BAD_PARAMETER
A bad/invalid parameter (or even an inappropriate image) has been passed to a module or an algorithm;...
Definition: mlTypeDefs.h:925
#define ML_PRINT_ERROR(FUNC_NAME, REASON, HANDLING)
Like ML_PRINT_ERROR_DUMP(FUNC_NAME, REASON, HANDLING, RT_OBJ) without a runtime object to be dumped.
#define SpecializedPCLPointXYZ
Eigen makes strange stuff with some types on some windows platforms which makes some specializations ...
A collection of tool functions used in MLPCLSupport.
Basic types used in the MeVislab binding of the Point Cloud Library(PCL).
unsigned int MLuint32
Definition: mlTypeDefs.h:191
MLPCL_InventorAdapters_EXPORT void getRainbowRGB_From0_to_1(float intensity, float retRGB[3])
Maps an intensity value from [0,1] to an RGB rainbow value where 0 is mapped to red increasing to gre...
void setOneMFVecFieldValueFromPoint(DST_VAL_TYPE *dstVal, const POINT_TYPE &pnt, bool useData_n)
Generic function to copy pnt.data[0-2] or pnt.data_n[0-2] (dependent on useData_n) to dstVal.
void setTwoMFVecFieldValuesFromPoint(DST_VAL_TYPE *dstVal, const POINT_TYPE &pnt)
Generic function to copy data[0-2] to dstVal and data[0-2}+data_n[0-2] to dstVal+1.
size_t setMFVecFromPointCloud(const POINT_CLOUD_TYPE &pointCloud, SM_MF_VEC_FIELD_TYPE &mfvecField, PCLMFVecStorageTypes storageType, bool duplicateColors=false, bool mapToRainbow=false, bool useCurvatureForColor=false, bool scaleFromInputRange=false, float inRangeMin=0.f, float inRangeMax=1.f)
Converts the point cloud to an Inventor SoMFVec2f, SoMFVec3f, or SoMFUInt32 field; it does not necess...
MLPCL_InventorAdapters_EXPORT void setVertices(const std::vector< pcl::Vertices > &verticesVector, SoMFInt32 &mfIntField, bool terminateWithMinusOne)
For each entry of verticesVector all indexes of are appended mfIntField and - if terminateWithMinusOn...
void setOneMFVecFieldValue(MLuint32 *dstVal, const unsigned int *rgbaVal)
Writes swapped *rgbaVal into *dstVal.
PCLMFVecStorageTypes
Describes the way how data combinations of a point cloud are stored in an OpenInventor MFVec field.
@ CopyFromData
The data vector of the points are copied to the MFVec.
@ StoreIntensitReplacementAsRGB
Store the member values of the points, which is considered as an intensity replacement,...
@ UseOnlyRGBA
If the point is of an RGBA type the rgba member is used for the SoVertexProperty.rgba settings,...
@ CopyFromData_n
If available then the point values describing the vector are copied, if not then nullptr vectors are ...
@ CopyDataAndData_n
From each point the point given by point.data followed by another coordinate, which is the result fro...
@ StoreIntensitReplacementAsRGBA
Store the member values of the points, which is considered as an intensity replacement,...
unsigned int getPointRGBA(const pcl::PointXYZ &)
Get the rgba value from PCL point if it has that member otherwise get 0u; for set functionality set t...
MLPCLSUPPORT_EXPORT MLuint64 getSigned32BitMaximumLimit()
Returns the maximum number of entries allowed in data structured with 32 bit signed indexing,...
float getIntensityReplacement(const pcl::PointXYZ &)
Gets the scalar value in a member which is considered as storage for an additional value,...
float getCurvature(const pcl::PointXYZ &)
Gets/sets the curvature value as float if the point has one, otherwise return 0 (for example in the c...