MeVisLab Toolbox Reference
mlPCLMLTools.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 <mlModuleIncludes.h>
20
21#include <mlPointList.h>
22#include <mlVectorList.h>
23#include <mlXMarkerList.h>
24
25ML_START_NAMESPACE
26
27class SubImage;
28class PagedImage;
29
31namespace PCLMLTools {
32
33
34//----------------------------------------------------------------------------------
37//----------------------------------------------------------------------------------
39 const MLTypeData* voxVal);
40
41//----------------------------------------------------------------------------------
45// Adapt this if a new PCL point type is integrated in the MeVisLab binding.
46//----------------------------------------------------------------------------------
48inline void setVectorReplacement(pcl::PointXYZ & /*p*/, const Vector3f & /*vf*/)
49{
50 // There is no member which could be used for the vector, do not assign anything.
51}
52
53// Handle all other point types generically.
54template <typename PCL_POINT_TYPE>
55inline void setVectorReplacement(PCL_POINT_TYPE &p, const Vector3f &vf)
56{
57 p.normal_x = vf[0];
58 p.normal_y = vf[1];
59 p.normal_z = vf[2];
60}
61
62
63//----------------------------------------------------------------------------------
65//----------------------------------------------------------------------------------
113
114
115//----------------------------------------------------------------------------------
121//----------------------------------------------------------------------------------
122template <typename POINT_CLOUD_TYPE>
123inline void transformTo(POINT_CLOUD_TYPE &pointCloud,
124 const Matrix4 &voxelToWorldMatrix,
125 bool toWorld)
126{
127 typedef typename POINT_CLOUD_TYPE::PointType PointType;
128 MedicalImageProperties mapProps;
129 mapProps.setVoxelToWorldMatrix(voxelToWorldMatrix);
130 const size_t numPoints = pointCloud.points.size();
131 Vector3 pnt;
132 for (size_t c=0; c < numPoints; ++c){
133 PointType &pclPoint = pointCloud.points[c];
134 pnt.assign(pclPoint.x, pclPoint.y, pclPoint.z);
135 if (toWorld){
136 pnt = mapProps.mapVoxelToWorld(pnt);
137 }
138 else{
139 pnt = mapProps.mapWorldToVoxel(pnt);
140 }
141 pclPoint.x = static_cast<float>(pnt[0]);
142 pclPoint.y = static_cast<float>(pnt[1]);
143 pclPoint.z = static_cast<float>(pnt[2]);
144 }
145}
146
147//----------------------------------------------------------------------------------
156//----------------------------------------------------------------------------------
157template <typename POINT_CLOUD_PTR_TYPE>
160 POINT_CLOUD_PTR_TYPE retPointCloudPtr)
161{
162 bool allAddedRet = true;
163 const MLTypeInfos* dataTypeInfos = subImg.getDataTypeInfos();
164 if (dataTypeInfos && subImg.getData() && retPointCloudPtr){
165
166 const MLDataType dt = subImg.getDataType();
167 const bool isVectorType = MLIsScalarType(dt) ? false : true;
168 double scale=0;
169 if (convParams.normalizeInClampedRange){
170 const double range = convParams.thresholdMax - convParams.thresholdMin;
171 if (range < 10e-10){
172 scale = 1.;
173 }
174 else{
175 scale = 1. / range;
176 }
177 }
178 typedef typename POINT_CLOUD_PTR_TYPE::element_type::PointType PointType;
179 typedef typename POINT_CLOUD_PTR_TYPE::element_type::VectorType PointVectorType;
180 PointVectorType tmpAddedPoints;
181 tmpAddedPoints.reserve(20000);
182 const SubImageBox subImgBox = subImg.getBox();
183 ImageVector p = subImgBox.v1;
184 PointType valToAppend;
185 Vector3f vec3fVal;
186 //for (p.u = subImgBox.v1.u; p.u <= subImgBox.v2.u; ++p.u){
187 //for (p.t = subImgBox.v1.t; p.t <= subImgBox.v2.t; ++p.t){
188 //for (p.c = subImgBox.v1.c; p.c <= subImgBox.v2.c; ++p.c){
189 for (p.z = subImgBox.v1.z; p.z <= subImgBox.v2.z; ++p.z){
190 for (p.y = subImgBox.v1.y; p.y <= subImgBox.v2.y; ++p.y){
191 for (p.x = subImgBox.v1.x; p.x <= subImgBox.v2.x; ++p.x){
192
193 // Get value from the image as generic voxel MLTypeData and determine
194 // whether the value interpreted as double shall be taken or
195 // alternatively the length of a vector if we have one.
196 const MLTypeData* voxVal = reinterpret_cast<MLTypeData*>(subImg.getImagePointer(p));
197 double dblVal = 0;
198 if (isVectorType){
199 vec3fVal = getVector3fFromVoxVal(dt, voxVal);
200 }
201 dblVal = isVectorType && convParams.useVectorLengthAsIntensity ?
202 vec3fVal.length() :
203 dataTypeInfos->castToDouble(voxVal);
204
205 // Do clamping and scaling.
206 bool add = true;
207 if (dblVal < convParams.thresholdMin){
208 if (convParams.skipVoxelsBelowMin){
209 add = false;
210 }
211 else{
212 dblVal = convParams.lowerValue;
213 }
214 }
215 if (dblVal > convParams.thresholdMax){
216 if (convParams.skipVoxelsAboveMax){
217 add = false;
218 }
219 else{
220 dblVal = convParams.upperValue;
221 }
222 }
223
224 // Append point with coordinates and intensity.
225 if (!add){
226 allAddedRet = false;
227 }
228 else{
229 valToAppend.x = static_cast<float>(p.x);
230 valToAppend.y = static_cast<float>(p.y);
231 valToAppend.z = static_cast<float>(p.z);
232 if (convParams.normalizeInClampedRange){
233 if (dblVal < convParams.thresholdMin){ dblVal = convParams.thresholdMin; }
234 if (dblVal > convParams.thresholdMax){ dblVal = convParams.thresholdMax; }
235 dblVal = (dblVal-convParams.thresholdMin)*scale;
236 }
237 valToAppend.data[3] = 1.0f;
238 PCLSupportTools::setIntensityReplacement(valToAppend, static_cast<float>(dblVal));
239 if (isVectorType){
240 setVectorReplacement(valToAppend, vec3fVal);
241 }
242 tmpAddedPoints.push_back(valToAppend);
243 }
244 }
245 }
246 }
247 //}
248 //}
249 //}
250 if (tmpAddedPoints.size() > 0){
251 const MLuint64 newSize = static_cast<MLuint64>(retPointCloudPtr->width) + tmpAddedPoints.size();
253 retPointCloudPtr->width = mlrange_cast<MLuint32>(newSize);
254 retPointCloudPtr->height = 1;
255 retPointCloudPtr->points.insert(retPointCloudPtr->points.end(), tmpAddedPoints.begin(), tmpAddedPoints.end());
256 }
257 else{
258 ML_PRINT_ERROR("mlPCLMLTools.cpp: appendSubImageVoxelsToPointCloud",
260 "Could not add points to point cloud since this would exceed "
261 "the maximum number UINT32_MAX points in a point cloud.");
262 }
263 }
264 }
265 return allAddedRet;
266}
267
268//----------------------------------------------------------------------------------
274//----------------------------------------------------------------------------------
275template <typename POINT_CLOUD_PTR_TYPE>
278 POINT_CLOUD_PTR_TYPE &retPointCloudPtr)
279{
280 typedef typename POINT_CLOUD_PTR_TYPE::element_type POINT_CLOUD_TYPE;
281 MLErrorCode retErr = ML_NO_MEMORY;
282 retPointCloudPtr = POINT_CLOUD_PTR_TYPE(new POINT_CLOUD_TYPE);
283 SubImage subImage(inImg.getBoxFromImageExtent(), inImg.getDataType(), nullptr);
285 bool isOrganized = false;
286 if (subImage.getData()){
287 retErr = inImg.getTile(subImage);
288 if (ML_RESULT_OK == retErr){
289 isOrganized = appendSubImageVoxelsToPointCloud(subImage, convParams, retPointCloudPtr);
290
291 // If all voxels have been added then we can set the height of the point cloud to mark it as organized.
292 if (isOrganized && retPointCloudPtr &&
294 retPointCloudPtr->width = mlrange_cast<MLuint32>(subImage.getExtent().x);
295 retPointCloudPtr->height = mlrange_cast<MLuint32>(subImage.getExtent().y * subImage.getExtent().z);
296 }
297 }
298 }
299 if (convParams.transformToWorld){
300 transformTo(*retPointCloudPtr, inImg.getVoxelToWorldMatrix(), true);
301 }
302 return retErr;
303}
304
306// Adapt this if a new PCL point type is integrated in the MeVisLab binding.
307//----------------------------------------------------------------------------------
310//----------------------------------------------------------------------------------
311template <typename POINT_TYPE>
312inline void assignPointDataFromXMarker(const XMarker &xMarker, POINT_TYPE &point)
313{
314 point.data[0] = static_cast<float>(xMarker.pos[0]);
315 point.data[1] = static_cast<float>(xMarker.pos[1]);
316 point.data[2] = static_cast<float>(xMarker.pos[2]);
317 point.data[3] = 1.0f;
318}
319
320//----------------------------------------------------------------------------------
326//----------------------------------------------------------------------------------
327inline void assignPointDataFromXMarker(const XMarker &xMarker, pcl::PointXYZLNormal &point)
328{
329 point.data[0] = static_cast<float>(xMarker.pos[0]);
330 point.data[1] = static_cast<float>(xMarker.pos[1]);
331 point.data[2] = static_cast<float>(xMarker.pos[2]);
332 point.data[3] = 1.0f;
333 point.data_n[0] = static_cast<float>(xMarker.vec[0]);
334 point.data_n[1] = static_cast<float>(xMarker.vec[1]);
335 point.data_n[2] = static_cast<float>(xMarker.vec[2]);
336 point.data_n[3] = 0.0f;
337 point.label = static_cast<unsigned int>(xMarker.type);
338}
339
340//----------------------------------------------------------------------------------
346//----------------------------------------------------------------------------------
347inline void assignPointDataFromXMarker(const XMarker &xMarker, pcl::PointXYZRGBNormal &point)
348{
349 point.data[0] = static_cast<float>(xMarker.pos[0]);
350 point.data[1] = static_cast<float>(xMarker.pos[1]);
351 point.data[2] = static_cast<float>(xMarker.pos[2]);
352 point.data[3] = 1.0f;
353 point.data_n[0] = static_cast<float>(xMarker.vec[0]);
354 point.data_n[1] = static_cast<float>(xMarker.vec[1]);
355 point.data_n[2] = static_cast<float>(xMarker.vec[2]);
356 point.data_n[3] = 0.0f;
357 point.rgba = static_cast<unsigned int>(xMarker.type);
358}
359
360//----------------------------------------------------------------------------------
366//----------------------------------------------------------------------------------
367inline void assignPointDataFromXMarker(const XMarker &xMarker, pcl::PointXYZINormal &point)
368{
369 point.data[0] = static_cast<float>(xMarker.pos[0]);
370 point.data[1] = static_cast<float>(xMarker.pos[1]);
371 point.data[2] = static_cast<float>(xMarker.pos[2]);
372 point.data[3] = 1.0f;
373 point.data_n[0] = static_cast<float>(xMarker.vec[0]);
374 point.data_n[1] = static_cast<float>(xMarker.vec[1]);
375 point.data_n[2] = static_cast<float>(xMarker.vec[2]);
376 point.data_n[3] = 0.0f;
377 point.intensity = static_cast<float>(xMarker.type);
378}
379
380
381//----------------------------------------------------------------------------------
389//----------------------------------------------------------------------------------
390template <typename POINT_CLOUD_PTR_TYPE>
391inline void createPointCloudFromBaseList(const Base *inBaseList,
392 POINT_CLOUD_PTR_TYPE &retPointCloudPtr)
393{
394 if (!inBaseList){
395 retPointCloudPtr.reset();
396 }
397 else{
398 // Check for list-like base types.
399 const PointList *pl = mlbase_cast<const PointList*>(inBaseList);
400 const VectorList *vl = mlbase_cast<const VectorList*>(inBaseList);
401 const XMarkerList *xml = mlbase_cast<const XMarkerList*>(inBaseList);
403
404 if (pl || vl || xml || xmlc){
405 // Create a new point cloud if we have an input object, even if it is empty.
406 typedef typename POINT_CLOUD_PTR_TYPE::element_type POINT_CLOUD_TYPE;
407 retPointCloudPtr = POINT_CLOUD_PTR_TYPE(new POINT_CLOUD_TYPE);
408
409 // Get number of points from list.
410 const MLssize_t numVals = (pl ? pl->getNum() :
411 (vl ? vl->getNum() :
412 (xml ? mlrange_cast<MLssize_t>(xml->size()) :
413 (xmlc ? mlrange_cast<MLssize_t>(const_cast<XMarkerListContainer*>(xmlc)->getList()->size()) : 0))));
414 if (static_cast<MLint>(numVals) > static_cast<MLint>(PCLSupportTools::getUnsigned32BitMaximumLimit())){
415 ML_PRINT_ERROR("mlPCLToMLTools.h: createPointCloudFromBaseList",
417 "Input point cloud has more than ML_UINT32_MAX entries; the "
418 "PointCloud.width parameter cannot be set to this value any more; "
419 "using ML_UINT32_MAX instead.");
420 retPointCloudPtr->width = static_cast<MLuint32>(PCLSupportTools::getUnsigned32BitMaximumLimit());
421 }
422 else{
423 retPointCloudPtr->width = static_cast<MLuint32>(numVals);
424 }
425 retPointCloudPtr->height = 1;
426 retPointCloudPtr->is_dense = true;
427 retPointCloudPtr->points.resize(mlrange_cast<size_t>(numVals));
428
429
430 if (numVals > 0){
431 for (MLssize_t cs=0; cs < numVals; ++cs){
432 typename POINT_CLOUD_TYPE::PointType &point = retPointCloudPtr->points[static_cast<size_t>(cs)];
433
434 if (pl){
435 pl->getValue(cs, point.data[0], point.data[1], point.data[2]);
436 }
437 else if (vl){
438 int vecType=0;
439 vl->getPoint(cs, vecType, point.data[0], point.data[1], point.data[2]);
440 }
441 else if (xml || xmlc){
442 const XMarker &xMarker = xml ? (*static_cast<const XMarker*>(xml->getConstItemAt(cs))) :
443 (*static_cast<const XMarker*>(const_cast<XMarkerListContainer*>(xmlc)->getList()->getConstItemAt(cs)));
444 assignPointDataFromXMarker(xMarker, point);
445 }
446 }
447 }
448 }
449 }
450}
451
452
453
455// Adapt this if a new PCL point type is integrated in the MeVisLab binding.
456//----------------------------------------------------------------------------------
459//----------------------------------------------------------------------------------
460template <typename POINT_TYPE>
461inline void assignXMarkerFromPointData(const POINT_TYPE &point, XMarker &xMarker)
462{
463 xMarker.pos[0] = point.data[0];
464 xMarker.pos[1] = point.data[1];
465 xMarker.pos[2] = point.data[2];
466}
467
468//----------------------------------------------------------------------------------
473//----------------------------------------------------------------------------------
474inline void assignXMarkerFromPointData(const pcl::PointXYZLNormal &point, XMarker &xMarker)
475{
476 xMarker.pos[0] = point.data[0];
477 xMarker.pos[1] = point.data[1];
478 xMarker.pos[2] = point.data[2];
479 xMarker.vec[0] = point.data_n[0];
480 xMarker.vec[1] = point.data_n[1];
481 xMarker.vec[2] = point.data_n[2];
482 xMarker.type = static_cast<int>(point.label);
483}
484
485//----------------------------------------------------------------------------------
490//----------------------------------------------------------------------------------
491inline void assignXMarkerFromPointData(const pcl::PointXYZRGBNormal &point, XMarker &xMarker)
492{
493 xMarker.pos[0] = point.data[0];
494 xMarker.pos[1] = point.data[1];
495 xMarker.pos[2] = point.data[2];
496 xMarker.vec[0] = point.data_n[0];
497 xMarker.vec[1] = point.data_n[1];
498 xMarker.vec[2] = point.data_n[2];
499 xMarker.type = static_cast<int>(point.rgba);
500}
501
502//----------------------------------------------------------------------------------
507//----------------------------------------------------------------------------------
508inline void assignXMarkerFromPointData(const pcl::PointXYZINormal &point, XMarker &xMarker)
509{
510 xMarker.pos[0] = point.data[0];
511 xMarker.pos[1] = point.data[1];
512 xMarker.pos[2] = point.data[2];
513 xMarker.vec[0] = point.data_n[0];
514 xMarker.vec[1] = point.data_n[1];
515 xMarker.vec[2] = point.data_n[2];
516 xMarker.type = static_cast<int>(point.intensity);
517}
518
519
520//----------------------------------------------------------------------------------
525//----------------------------------------------------------------------------------
526template <typename POINT_CLOUD_TYPE>
527inline void convertPointCloudToXMarkerList(POINT_CLOUD_TYPE &inputPointCloud,
528 XMarkerList &outputList)
529{
530 outputList.clear();
531 const size_t numInputPoints = inputPointCloud.points.size();
532 outputList.resize(numInputPoints);
533 for (size_t c=0; c < numInputPoints; ++c){
534 XMarker *xMarker = static_cast<XMarker*>(outputList.getItemAt(static_cast<MLssize_t>(c)));
535 assignXMarkerFromPointData(inputPointCloud.points[c], *xMarker);
536 }
537}
538
539};
540
541ML_END_NAMESPACE
542
Project global and OS specific declarations.
#define MLPCL_MLAdapters_EXPORT
If included by external modules, exported symbols are declared as import symbols.
BaseItem * getItemAt(MLssize_t index) override
Definition mlListBase.h:693
const BaseItem * getConstItemAt(MLssize_t index) const override
Same as getItemAt(MLssize_t index) for constant access.
Definition mlListBase.h:698
T length() const
Returns the length of the vector, i.e., norm2().
MLDataType getDataType() const
Returns the data type of the image.
SubImageBox getBoxFromImageExtent() const
Returns the size of image as box with origin 0.
void setVoxelToWorldMatrix(const Matrix4 &matrix)
Sets the matrix that transforms voxel to world coordinates to matrix.
Vector3 mapWorldToVoxel(const Vector3 &worldPosition) const
Maps the worldPosition vector to voxel coordinates and returns it.
Vector3 mapVoxelToWorld(const Vector3 &voxelPosition) const
Maps the voxelPosition vector to world coordinates and returns it.
const Matrix4 & getVoxelToWorldMatrix() const
Returns the voxelToWorld matrix.
MLEXPORT MLErrorCode getTile(SubImageBox location, MLDataType dataType, void **data, const ScaleShiftData &scaleShiftData=ScaleShiftData(), MLRequestProgressCB *progressCallback=nullptr, void *progressCallbackUserData=nullptr)
Base object class PointList managing a list of points.
Definition mlPointList.h:29
void getValue(MLssize_t index, Vector3 &vec) const
get point at given index
MLssize_t getNum() const
returns the number of contained points
void * getImagePointer(const ImageVector &voxelPosition) const
Definition mlSubImage.h:323
const SubImageBox & getBox() const
Returns the box describing the origin/extent of the subimage.
Definition mlSubImage.h:230
MLEXPORT void allocateAsMemoryBlockHandle(MLMemoryErrorHandling handleFailure=ML_RETURN_NULL)
Allocates data using the ML memory manager. For failure handing, see SubImage::allocate().
MLDataType getDataType() const
Returns the type of image data.
Definition mlSubImage.h:288
ImageVector getExtent() const
Returns the extent of the subimage, which is identical to getBox().getExtent().
Definition mlSubImage.h:197
void * getData() const
Returns the memory address of the memory managed by the subimage.
Definition mlSubImage.h:372
MLint getNumVoxels() const
Definition mlSubImage.h:255
const MLTypeInfos * getDataTypeInfos() const
Returns MLTypeInfos for image data type.
Definition mlSubImage.h:291
ComponentType z
Z component of the vector.
ComponentType x
X component of the vector.
ComponentType y
Y component of the vector.
void assign(const DT px, const DT py, const DT pz)
Sets all components to the passed values.
Definition mlVector3.h:171
Base object representing a list of vectors given as Vector4's.
void getPoint(MLssize_t index, int &type, float &x1, float &y1, float &z1) const
returns point of vectors at given point index (NOTE: (0,1 = first vector , 2,3 = second vector))
MLssize_t getNum() const
returns the number of contained points
Vector3 vec
Marker vector, relative to position.
Vector6 pos
Marker position.
int type
Marker type.
MLint32 MLDataType
Definition mlTypeDefs.h:595
MLEXPORT MLint32 MLIsScalarType(MLDataType dataType)
#define ML_BAD_PARAMETER
Definition mlTypeDefs.h:822
MLint32 MLErrorCode
Type of an ML Error code.
Definition mlTypeDefs.h:715
#define ML_NO_MEMORY
Definition mlTypeDefs.h:734
#define ML_RESULT_OK
No error. Everything seems to be okay.
Definition mlTypeDefs.h:723
#define ML_PRINT_ERROR(FUNC_NAME, REASON, HANDLING)
ToTypePtr mlbase_cast(ml::Base *from)
Template function to allow type-safe casting of a base object to a derived object.
Definition mlBase.h:176
A collection of tool functions used in MLPCLSupport.
Basic types used in the MeVislab binding of the Point Cloud Library(PCL).
Target mlrange_cast(Source arg)
Generic version of checked ML casts.
Tool class for some string operations.
UINT64 MLuint64
Introduce platform-independent 64-bit unsigned integer type.
Definition mlTypeDefs.h:424
@ ML_RETURN_NULL
On allocation failure, NULL is returned without error handling.
Definition mlTypeDefs.h:675
unsigned int MLuint32
Definition mlTypeDefs.h:184
unsigned char MLTypeData
This is the pointer type used to point to the data of MLType data instances.
MLint64 MLint
Definition mlTypeDefs.h:489
SSIZE_T MLssize_t
The signed ML size type that is a signed 32-bit size_t on 32-bit platforms and 64-bit one on 64-bit p...
Definition mlTypeDefs.h:565
Namespace with a collection of converter tools between the libraries ML and PCL.
void assignXMarkerFromPointData(const POINT_TYPE &point, XMarker &xMarker)
MLErrorCode createPointCloudFromPagedImage(PagedImage &inImg, const ImageToPointCloudConversionParameters &convParams, POINT_CLOUD_PTR_TYPE &retPointCloudPtr)
void convertPointCloudToXMarkerList(POINT_CLOUD_TYPE &inputPointCloud, XMarkerList &outputList)
void assignPointDataFromXMarker(const XMarker &xMarker, POINT_TYPE &point)
void setVectorReplacement(pcl::PointXYZ &, const Vector3f &)
void transformTo(POINT_CLOUD_TYPE &pointCloud, const Matrix4 &voxelToWorldMatrix, bool toWorld)
void createPointCloudFromBaseList(const Base *inBaseList, POINT_CLOUD_PTR_TYPE &retPointCloudPtr)
MLPCL_MLAdapters_EXPORT Vector3f getVector3fFromVoxVal(MLDataType dt, const MLTypeData *voxVal)
bool appendSubImageVoxelsToPointCloud(const SubImage &subImg, const ImageToPointCloudConversionParameters &convParams, POINT_CLOUD_PTR_TYPE retPointCloudPtr)
MLPCLSUPPORT_EXPORT MLuint64 getUnsigned32BitMaximumLimit()
void setIntensityReplacement(pcl::PointXYZ &, float=1.f, MLuint8=0xff)
Tmat4< MLdouble > Matrix4
The standard 4x4 matrix of type double.
Definition mlMatrix4.h:713
Tvec3< MLdouble > Vector3
A vector with three components of type double.
Definition mlVector3.h:286
TSubImageBox< MLint > SubImageBox
Defines the standard SubImageBox type used in the ML. Its size varies with the size of the MLint type...
Tvec3< MLfloat > Vector3f
A vector with three components of type float.
Definition mlVector3.h:280
TImageVector< MLint > ImageVector
Defines the standard ImageVector type that is used by the ML for indexing and coordinates.
Function_CastToDouble castToDouble
Returns a type value cast to double.
A container with parameters for the conversion from ML images to point clouds.
double upperValue
Possibly used on voxels larger than thresholdMax; see thresholdMax for details.
ImageToPointCloudConversionParameters()
Default constructor fixing the defaults.
bool skipVoxelsAboveMax
Used when voxels are larger than thresholdMax; see thresholdMax for details.
bool skipVoxelsBelowMin
Used when voxels are smaller than thresholdMin; see thresholdMin for details.
double lowerValue
Possibly used on voxels smaller than thresholdMin; see thresholdMin for details.