72 }
catch (
const std::bad_alloc&) {
94 }
catch (
const std::bad_alloc&) {
99 for (
unsigned i = 0; i < numberOfVectors; ++i) {
116 bool useOriginPoint =
false;
117 bool fromOriginPoint =
true;
119 switch (preferredOrientation) {
127 assert(preferredOrientation >= 0 && preferredOrientation <= 5);
129 prefOrientation.
u[preferredOrientation >> 1] =
130 ((preferredOrientation & 1) == 0
142 QString(
"[UpdateNormalOrientations] Barycenter: (%1;%2;%3)")
145 .arg(originPoint.
z));
146 useOriginPoint =
true;
153 useOriginPoint =
true;
154 fromOriginPoint = (preferredOrientation ==
PLUS_ORIGIN);
160 "[UpdateNormalOrientations] Can't orient the new "
161 "normals with the previous ones... as the cloud has no "
170 bool sensorFound =
false;
176 useOriginPoint =
true;
186 "[UpdateNormalOrientations] Could not find a valid "
198 for (
unsigned i = 0; i < theNormsCodes.
currentSize(); i++) {
202 if (preferredOrientation ==
PREVIOUS) {
204 }
else if (useOriginPoint) {
205 if (fromOriginPoint) {
206 prefOrientation = *(theCloud->
getPoint(i)) - originPoint;
208 prefOrientation = originPoint - *(theCloud->
getPoint(i));
213 if (N.
dot(prefOrientation) < 0) {
233 std::min<unsigned>(100, std::max<unsigned>(1, cloud->
size() / 100));
251 "[GuessBestRadius] Failed to compute the cloud octree");
257 if (bestRadius == 0) {
258 CVLog::Warning(
"[GuessBestRadius] The cloud has invalid dimensions");
262 if (cloud->
size() < 100) {
270 static const int s_aimedPop = 16;
271 static const int s_aimedPopRange = 4;
272 static const int s_minPop = 6;
273 static const double s_minAboveMinRatio = 0.97;
275 const unsigned sampleCount =
276 std::min<unsigned>(200, cloud->
size() / 10);
278 double aimedPop = s_aimedPop;
281 double lastMeanPop = 0;
283 std::random_device rd;
284 std::mt19937 gen(rd());
285 std::uniform_int_distribution<unsigned> dist(0, cloud->
size() - 1);
288 for (
size_t attempt = 0; attempt < 10; ++attempt) {
290 int totalSquareCount = 0;
293 int aboveMinPopCount = 0;
299 for (
size_t i = 0; i < sampleCount; ++i) {
300 unsigned randomIndex = dist(gen);
301 assert(randomIndex < cloud->
size());
310 totalSquareCount += n * n;
325 double meanPop =
static_cast<double>(totalCount) / sampleCount;
326 double stdDevPop = sqrt(
327 fabs(
static_cast<double>(totalSquareCount) / sampleCount -
329 double aboveMinPopRatio =
330 static_cast<double>(aboveMinPopCount) / sampleCount;
332 CVLog::Print(QString(
"[GuessBestRadius] Radius = %1 -> samples "
333 "population in [%2 ; %3] (mean %4 / std. dev. "
334 "%5 / %6% above mininmum)")
340 .arg(aboveMinPopRatio * 100));
342 if (fabs(meanPop - aimedPop) < s_aimedPopRange) {
346 if (aboveMinPopRatio < s_minAboveMinRatio) {
351 aimedPop = s_aimedPop +
353 assert(aimedPop >= s_aimedPop);
363 assert(meanPop >= 1.0);
368 newRadius = radius * sqrt(aimedPop / meanPop);
371 if (fabs(meanPop - aimedPop) < fabs(bestRadius - aimedPop)) {
375 double slope = (radius * radius - lastRadius * lastRadius) /
376 (meanPop - lastMeanPop);
378 lastRadius * lastRadius +
379 (aimedPop - lastMeanPop) * slope;
380 if (newSquareRadius > 0) {
381 newRadius = sqrt(newSquareRadius);
389 lastMeanPop = meanPop;
395 if (
octree && !inputOctree) {
413 unsigned pointCount = theCloud->
size();
414 if (pointCount < 3) {
421 if (theOctree->
build() <= 0) {
431 if (theOctree && !inputOctree)
delete theOctree;
439 if (!theNorms->
resizeSafe(pointCount,
true, &blankN)) {
440 theNormsCodes.resize(0);
441 if (theOctree && !inputOctree)
delete theOctree;
446 void* additionalParameters[2] = {
reinterpret_cast<void*
>(theNorms),
447 reinterpret_cast<void*
>(&localRadius)};
449 unsigned processedCells = 0;
450 switch (localModel) {
452 unsigned char level =
458 true, progressCb,
"Normals Computation[LS]");
461 unsigned char level =
467 additionalParameters,
470 progressCb,
"Normals Computation[TRI]");
473 unsigned char level =
479 additionalParameters,
true, progressCb,
480 "Normals Computation[QUADRIC]");
488 if (processedCells == 0 ||
490 theNormsCodes.resize(0);
495 std::fill(theNormsCodes.begin(), theNormsCodes.end(), 0);
496 for (
unsigned i = 0; i < pointCount; i++) {
510 if (theOctree && !inputOctree) {
530 const unsigned char& iX = dims.
x;
531 const unsigned char& iY = dims.
y;
532 const unsigned char& iZ = dims.
z;
537 N.
u[iX] = h[1] + (2 * h[3] * lX) + (h[4] * lY);
538 N.
u[iY] = h[2] + (2 * h[5] * lY) + (h[4] * lX);
555 if (!pointAndNeighbors) {
560 if (pointAndNeighbors->
size() < 3) {
579 if (!pointAndNeighbors) {
584 if (pointAndNeighbors->
size() < 3) {
591 std::string errorStr;
599 unsigned triCount = theMesh->
size();
603 for (
unsigned j = 0; j < triCount; ++j) {
611 if (tsi->
i1 == 0 || tsi->
i2 == 0 || tsi->
i3 == 0) {
633 void** additionalParameters,
652 cloudViewer::DgmOctree::NeighboursSet::iterator it =
654 for (
unsigned j = 0; j < pointCount; ++j, ++it) {
660 for (
unsigned i = 0; i < pointCount; ++i) {
666 nNSS, radius,
false);
667 float cur_radius = radius;
669 cur_radius < 16 * radius) {
670 cur_radius *= 1.189207115f;
672 nNSS, cur_radius,
false);
692 void** additionalParameters,
712 cloudViewer::DgmOctree::NeighboursSet::iterator it =
714 for (
unsigned j = 0; j < pointCount; ++j, ++it) {
721 for (
unsigned i = 0; i < pointCount; ++i) {
727 nNSS, radius,
false);
728 float cur_radius = radius;
730 cur_radius < 16 * radius) {
731 cur_radius *= 1.189207115f;
733 nNSS, cur_radius,
false);
755 void** additionalParameters,
772 cloudViewer::DgmOctree::NeighboursSet::iterator it =
775 for (
unsigned j = 0; j < pointCount; ++j, ++it) {
782 for (
unsigned i = 0; i < pointCount; ++i) {
807 int iStrike =
static_cast<int>(strike_deg);
808 int iDip =
static_cast<int>(dip_deg);
810 return QString(
"N%1°E - %2°")
811 .arg(iStrike, 3, 10, QChar(
'0'))
812 .arg(iDip, 3, 10, QChar(
'0'));
817 int iDipDir =
static_cast<int>(dipDir_deg);
818 int iDip =
static_cast<int>(dip_deg);
820 return QString(
"Dip: %1 deg. - Dip direction: %2 deg.")
821 .arg(iDip, 3, 10, QChar(
'0'))
822 .arg(iDipDir, 3, 10, QChar(
'0'));
833 if (N.
norm2() > std::numeric_limits<PointCoordinateType>::epsilon()) {
840 sqrt(N.
x * N.
x + N.
y * N.
y);
843 strike_deg = dip_deg =
844 std::numeric_limits<PointCoordinateType>::quiet_NaN();
854 if (N.
norm2d() > std::numeric_limits<PointCoordinateType>::epsilon()) {
869 atan2(Nsign * N.
x, Nsign * N.
y);
870 if (dipDir_rad < 0) {
871 dipDir_rad += 2 *
M_PI;
880 double dip_rad = acos(fabs(N.
z));
887 dipDir_deg = dip_deg =
888 std::numeric_limits<PointCoordinateType>::quiet_NaN();
897 if (std::isnan(dip_deg) || std::isnan(dipDir_deg)) {
902 double Nxy = sqrt(1.0 - Nz * Nz);
912 assert(fabs(dip2 - dip_deg) < 1.0e-3 &&
913 (dip2 == 0 || fabs(dipDir2 - dipDir_deg) < 1.0e-3));
929 H =
static_cast<float>(dipDir);
932 S =
static_cast<float>(dip / 90);
constexpr PointCoordinateType PC_ONE
'1' as a PointCoordinateType value
Vector3Tpl< PointCoordinateType > CCVector3
Default 3D Vector.
float PointCoordinateType
Type of the coordinates of a (N-D) point.
virtual void release()
Decrease counter and deletes object when 0.
static bool Warning(const char *format,...)
Prints out a formatted warning message in console.
static bool Print(const char *format,...)
Prints out a formatted message in console.
Array of compressed 3D normals (single index)
Array of (uncompressed) 3D normals (Nx,Ny,Nz)
void normalize()
Sets vector norm to unity.
Type dot(const Vector3Tpl &v) const
Dot product.
Type norm2() const
Returns vector square norm.
double norm2d() const
Returns vector square norm (forces double precision output)
Type & getValue(size_t index)
bool isAllocated() const
Returns whether some memory has been allocated or not.
bool resizeSafe(size_t count, bool initNewElements=false, const Type *valueForNewElements=nullptr)
Resizes memory (no exception thrown)
void setValue(size_t index, const Type &value)
unsigned currentSize() const
virtual bool hasNormals() const
Returns whether normals are enabled or not.
A 3D cloud interface with associated features (color, normals, octree, etc.)
virtual const CCVector3 & getPointNormal(unsigned pointIndex) const =0
Returns normal corresponding to a given point.
ccBBox getOwnBB(bool withGLFeatures=false) override
Returns the entity's own bounding-box.
static ccSensor * ToSensor(ccHObject *obj)
Converts current object to ccSensor (if possible)
Hierarchical CLOUDVIEWER Object.
unsigned getChildrenNumber() const
Returns the number of children.
ccHObject * getChild(unsigned childPos) const
Returns the ith child.
static const unsigned NULL_NORM_CODE
Null normal code.
static unsigned Compress(const PointCoordinateType N[3])
Compression algorithm.
static void Decompress(unsigned index, PointCoordinateType N[3], unsigned char level=QUANTIZE_LEVEL)
Decompression algorithm.
Compressed normal vectors handler.
static QString ConvertStrikeAndDipToString(double &strike_deg, double &dip_deg)
virtual ~ccNormalVectors()
Default destructor.
bool init()
Inits internal structures.
static QString ConvertDipAndDipDirToString(PointCoordinateType dip_deg, PointCoordinateType dipDir_deg)
Converts geological 'dip direction & dip' parameters to a string.
static void ReleaseUniqueInstance()
Releases unique instance.
static void ConvertNormalToDipAndDipDir(const CCVector3 &N, PointCoordinateType &dip_deg, PointCoordinateType &dipDir_deg)
Converts a normal vector to geological 'dip direction & dip' parameters.
std::vector< CCVector3 > m_theNormalVectors
Compressed normal vectors.
static bool ComputeNormsAtLevelWithTri(const cloudViewer::DgmOctree::octreeCell &cell, void **additionalParameters, cloudViewer::NormalizedProgress *nProgress=nullptr)
Cellular method for octree-based normal computation.
static bool ComputeNormalWithLS(cloudViewer::GenericIndexedCloudPersist *pointAndNeighbors, CCVector3 &N)
Helper: computes the normal (with best LS fit)
ccNormalVectors()
Default constructor.
static void ConvertNormalToHSV(const CCVector3 &N, float &H, float &S, float &V)
Converts a normal vector to HSV color space.
static bool ComputeNormalWithTri(cloudViewer::GenericIndexedCloudPersist *pointAndNeighbors, CCVector3 &N)
Helper: computes the normal (with Delaunay 2.5D)
static bool ComputeNormsAtLevelWithQuadric(const cloudViewer::DgmOctree::octreeCell &cell, void **additionalParameters, cloudViewer::NormalizedProgress *nProgress=nullptr)
Cellular method for octree-based normal computation.
static PointCoordinateType GuessNaiveRadius(ccGenericPointCloud *cloud)
static void ConvertNormalToStrikeAndDip(const CCVector3 &N, PointCoordinateType &strike_deg, PointCoordinateType &dip_deg)
static ecvColor::Rgb ConvertNormalToRGB(const CCVector3 &N)
Converts a normal vector to RGB color space.
static PointCoordinateType GuessBestRadius(ccGenericPointCloud *cloud, cloudViewer::DgmOctree *cloudOctree=nullptr, cloudViewer::GenericProgressCallback *progressCb=nullptr)
std::vector< ecvColor::Rgb > m_theNormalHSVColors
'HSV' colors corresponding to each compressed normal index
static bool ComputeNormalWithQuadric(cloudViewer::GenericIndexedCloudPersist *points, const CCVector3 &P, CCVector3 &N)
Helper: computes the normal (with Delaunay 2.5D)
static bool UpdateNormalOrientations(ccGenericPointCloud *theCloud, NormsIndexesTableType &theNormsCodes, Orientation preferredOrientation)
Updates normals orientation based on a preferred orientation.
static bool ComputeCloudNormals(ccGenericPointCloud *cloud, NormsIndexesTableType &theNormsCodes, CV_LOCAL_MODEL_TYPES localModel, PointCoordinateType localRadius, Orientation preferredOrientation=UNDEFINED, cloudViewer::GenericProgressCallback *progressCb=nullptr, cloudViewer::DgmOctree *inputOctree=nullptr)
Computes normal at each point of a given cloud.
static CCVector3 ConvertDipAndDipDirToNormal(PointCoordinateType dip_deg, PointCoordinateType dipDir_deg, bool upward=true)
static const CCVector3 & GetNormal(unsigned normIndex)
Static access to ccNormalVectors::getNormal.
Orientation
'Default' orientations
@ PREVIOUS
Re-use previous normal (if any)
@ PLUS_X
N.x always positive.
@ MINUS_BARYCENTER
Normals always towards the cloud barycenter.
@ MINUS_Z
N.z always negative.
@ PLUS_Y
N.y always positive.
@ PLUS_BARYCENTER
Normals always opposite to the cloud barycenter.
@ PLUS_ORIGIN
Normals always opposite to the origin.
@ PLUS_Z
N.z always positive.
@ MINUS_Y
N.y always negative.
@ MINUS_ORIGIN
Normals always towards the origin.
@ UNDEFINED
Undefined (no orientation is required)
@ MINUS_X
N.x always negative.
static ccNormalVectors * GetUniqueInstance()
Returns unique instance.
static bool ComputeNormsAtLevelWithLS(const cloudViewer::DgmOctree::octreeCell &cell, void **additionalParameters, cloudViewer::NormalizedProgress *nProgress=nullptr)
Cellular method for octree-based normal computation.
static CompressedNormType GetNormIndex(const PointCoordinateType N[])
Returns the compressed index corresponding to a normal vector.
const ecvColor::Rgb & getNormalHSVColor(unsigned index) const
Returns the HSV color equivalent to a given compressed normal index.
bool enableNormalHSVColorsArray()
Allocates normal HSV colors array.
bool isKindOf(CV_CLASS_ENUM type) const
Generic sensor interface.
bool getActiveAbsoluteCenter(CCVector3 &vec) const
Gets currently active absolute position.
T getMaxBoxDim() const
Returns maximal box dimension.
A kind of ReferenceCloud based on the DgmOctree::NeighboursSet structure.
The octree structure used throughout the library.
void getCellPos(CellCode code, unsigned char level, Tuple3i &cellPos, bool isCodeTruncated) const
unsigned findNearestNeighborsStartingFromCell(NearestNeighboursSearchStruct &nNSS, bool getOnlyPointsWithValidScalar=false) const
unsigned char findBestLevelForAGivenNeighbourhoodSizeExtraction(PointCoordinateType radius) const
int findNeighborsInASphereStartingFromCell(NearestNeighboursSearchStruct &nNSS, double radius, bool sortValues=true) const
Advanced form of the nearest neighbours search algorithm (in a sphere)
const PointCoordinateType & getCellSize(unsigned char level) const
Returns the octree cells length for a given level of subdivision.
int getPointsInSphericalNeighbourhood(const CCVector3 &sphereCenter, PointCoordinateType radius, NeighboursSet &neighbours, unsigned char level) const
Returns the points falling inside a sphere.
void computeCellCenter(CellCode code, unsigned char level, CCVector3 ¢er, bool isCodeTruncated=false) const
unsigned executeFunctionForAllCellsAtLevel(unsigned char level, octreeCellFunc func, void **additionalParameters, bool multiThread=false, GenericProgressCallback *progressCb=nullptr, const char *functionTitle=nullptr, int maxThreadCount=0)
int build(GenericProgressCallback *progressCb=nullptr)
Builds the structure.
unsigned executeFunctionForAllCellsStartingAtLevel(unsigned char startingLevel, octreeCellFunc func, void **additionalParameters, unsigned minNumberOfPointsPerCell, unsigned maxNumberOfPointsPerCell, bool multiThread=true, GenericProgressCallback *progressCb=nullptr, const char *functionTitle=nullptr, int maxThreadCount=0)
std::vector< PointDescriptor > NeighboursSet
A set of neighbours.
unsigned char findBestLevelForAGivenPopulationPerCell(unsigned indicativeNumberOfPointsPerCell) const
virtual unsigned size() const =0
Returns the number of points.
A generic 3D point cloud with index-based and presistent access to points.
virtual const CCVector3 * getPoint(unsigned index) const =0
Returns the ith point.
A generic mesh with index-based vertex access.
virtual VerticesIndexes * getTriangleVertIndexes(unsigned triangleIndex)=0
Returns the indexes of the vertices of a given triangle.
virtual unsigned size() const =0
Returns the number of triangles.
virtual void placeIteratorAtBeginning()=0
Places the mesh iterator at the beginning.
virtual bool isCancelRequested()=0
Checks if the process should be canceled.
static constexpr bool DO_NOT_DUPLICATE_VERTICES
const PointCoordinateType * getQuadric(Tuple3ub *dims=nullptr)
Returns the best interpolating 2.5D quadric.
const CCVector3 * getGravityCenter()
Returns gravity center.
static constexpr int IGNORE_MAX_EDGE_LENGTH
GenericIndexedMesh * triangulateOnPlane(bool duplicateVertices, PointCoordinateType maxEdgeLength, std::string &outputErrorStr)
Applies 2D Delaunay triangulation.
const CCVector3 * getLSPlaneNormal()
Returns best interpolating plane (Least-square) normal vector.
bool oneStep()
Increments total progress value of a single unit.
unsigned size() const override
Returns the number of points.
virtual unsigned getPointGlobalIndex(unsigned localIndex) const
const CCVector3 * getPointPersistentPtr(unsigned index) override
Returns the ith point as a persistent pointer.
const CCVector3 * getPoint(unsigned index) const override
Returns the ith point.
unsigned int CompressedNormType
Compressed normals type.
unsigned char ColorCompType
Default color components type (R,G and B)
static ecvSingleton< ccNormalVectors > s_uniqueInstance
static const unsigned NUMBER_OF_POINTS_FOR_NORM_WITH_LS
static const unsigned NUMBER_OF_POINTS_FOR_NORM_WITH_QUADRIC
static const unsigned NUMBER_OF_POINTS_FOR_NORM_WITH_TRI
float RadiansToDegrees(int radians)
Convert radians to degrees.
float DegreesToRadians(int degrees)
Convert degrees to radians.
RgbTpl< ColorCompType > Rgb
3 components, default type
constexpr ColorCompType MAX
Max value of a single color component (default type)
ReferenceCloud * points
Set of points lying inside this cell.
const DgmOctree * parentOctree
Octree to which the cell belongs.
unsigned char level
Cell level of subdivision.
CellCode truncatedCode
Truncated cell code.
Triangle described by the indexes of its 3 vertices.
Generic singleton encapsulation structure.