26 #ifdef CV_CORE_LIB_USES_QT_CONCURRENT
29 #define ENABLE_MT_OCTREE
31 #include <QThreadPool>
32 #include <QtConcurrentMap>
76 for (
int value = 0; value < VALUE_COUNT; ++value) {
77 int mask = VALUE_COUNT;
79 for (
unsigned char k = 0;
121 unsigned char level) {
122 assert(cellPos.
x >= 0 &&
138 #ifndef OCTREE_CODES_64_BITS
140 unsigned char level) {
141 assert(cellPos.
x >= 0 &&
163 #ifdef ENABLE_MT_OCTREE
175 : m_theAssociatedCloud(cloud),
176 m_numberOfProjectedPoints(0),
222 unsigned pointCount =
224 if (pointCount == 0) {
249 char infosBuffer[256];
250 sprintf(infosBuffer,
"Projecting %u points\nMax. depth: %i",
252 progressCb->
setInfo(infosBuffer);
258 progressCb, pointCount,
267 for (
unsigned i = 0; i < pointCount; i++) {
299 if (fillIndexesAtMaxLevel[0] > cellPos.
x)
300 fillIndexesAtMaxLevel[0] = cellPos.
x;
301 else if (fillIndexesAtMaxLevel[3] < cellPos.
x)
302 fillIndexesAtMaxLevel[3] = cellPos.
x;
304 if (fillIndexesAtMaxLevel[1] > cellPos.
y)
305 fillIndexesAtMaxLevel[1] = cellPos.
y;
306 else if (fillIndexesAtMaxLevel[4] < cellPos.
y)
307 fillIndexesAtMaxLevel[4] = cellPos.
y;
309 if (fillIndexesAtMaxLevel[2] > cellPos.
z)
310 fillIndexesAtMaxLevel[2] = cellPos.
z;
311 else if (fillIndexesAtMaxLevel[5] < cellPos.
z)
312 fillIndexesAtMaxLevel[5] = cellPos.
z;
314 fillIndexesAtMaxLevel[0] = fillIndexesAtMaxLevel[3] = cellPos.
x;
315 fillIndexesAtMaxLevel[1] = fillIndexesAtMaxLevel[4] = cellPos.
y;
316 fillIndexesAtMaxLevel[2] = fillIndexesAtMaxLevel[5] = cellPos.
z;
337 for (
int dim = 0; dim < 6; ++dim) {
338 fillIndexes[dim] = (fillIndexes[dim + 6] >> 1);
348 progressCb->
setInfo(
"Sorting cells...");
364 "[Octree::build] Octree successfully built... %u "
370 "[Octree::build] Warning : no point projected in "
374 "[Octree::build] Warning: some points have been "
375 "filtered out (%u/%u)",
383 progressCb->
update(100.0f);
388 (1 <<
static_cast<int>(
409 unsigned long long d = 1;
455 CellCode predCode = (p->theCode >> bitDec);
456 unsigned counter = 0;
457 unsigned cellCounter = 0;
458 unsigned maxCellPop = 0;
459 double sum = 0.0, sum2 = 0.0;
462 CellCode currentCode = (p->theCode >> bitDec);
463 if (predCode != currentCode) {
464 sum +=
static_cast<double>(cellCounter);
465 sum2 +=
static_cast<double>(cellCounter) *
466 static_cast<double>(cellCounter);
468 if (maxCellPop < cellCounter) maxCellPop = cellCounter;
471 predCode = currentCode;
479 sum +=
static_cast<double>(cellCounter);
480 sum2 +=
static_cast<double>(cellCounter) *
static_cast<double>(cellCounter);
481 if (maxCellPop < cellCounter) maxCellPop = cellCounter;
489 sum2 /
static_cast<double>(counter) -
501 bool isCodeTruncated)
const {
503 if (!isCodeTruncated) {
510 for (
unsigned char k = 0; k < level; ++k) {
511 if (code & 4) cellPos.
z |= bitMask;
512 if (code & 2) cellPos.
y |= bitMask;
513 if (code & 1) cellPos.
x |= bitMask;
524 bool isCodeTruncated)
const {
526 getCellPos(code, level, cellPos, isCodeTruncated);
534 cellMax = cellMin +
CCVector3(cs, cs, cs);
540 bool isCodeTruncated ,
541 bool clearOutputCloud )
const {
543 if (!isCodeTruncated) {
552 }
else if (clearOutputCloud) {
560 unsigned char bitDec)
const {
572 if (middleCode < truncatedCellCode) {
575 }
else if (middleCode == truncatedCellCode) {
578 bitDec) != truncatedCellCode) {
594 #ifdef COMPUTE_NN_SEARCH_STATISTICS
595 static double s_jumps = 0.0;
596 static double s_binarySearchCount = 0.0;
599 #ifdef ADAPTATIVE_BINARY_SEARCH
601 unsigned char bitDec,
603 unsigned end)
const {
605 assert(end >= begin);
608 #ifdef COMPUTE_NN_SEARCH_STATISTICS
609 s_binarySearchCount += 1;
616 if (truncatedCellCode < beginCode)
618 else if (truncatedCellCode == beginCode)
629 0.75f * (
static_cast<float>(truncatedCellCode - beginCode) /
631 unsigned middle = begin +
static_cast<unsigned>(centralPoint *
636 if (middleCode < truncatedCellCode) {
641 beginCode = middleCode;
642 }
else if (middleCode > truncatedCellCode) {
647 endCode = middleCode;
655 endCode = middleCode;
658 #ifdef COMPUTE_NN_SEARCH_STATISTICS
670 unsigned char bitDec,
672 unsigned end)
const {
676 #ifdef COMPUTE_NN_SEARCH_STATISTICS
677 s_binarySearchCount += 1;
684 unsigned count = end - begin + 1;
685 unsigned b = (1 <<
static_cast<int>(log(
static_cast<double>(
count - 1)) /
692 if (middleCode < truncatedCellCode) {
695 }
else if (middleCode == truncatedCellCode) {
699 bitDec) != truncatedCellCode) {
707 #ifdef COMPUTE_NN_SEARCH_STATISTICS
724 unsigned maxNumberOfNeighbors,
726 double& maxSquareDist,
727 double maxSearchDist ,
728 int* finalNeighbourhoodSize )
const {
734 bool inbounds =
false;
736 nNSS.
level, inbounds);
741 (maxSearchDist > 0 ? maxSearchDist * maxSearchDist : 0);
744 if (maxNumberOfNeighbors == 1) {
747 if (finalNeighbourhoodSize) {
751 if (maxSquareDist >= 0) {
764 nnFound =
std::min(nnFound, maxNumberOfNeighbors);
766 for (
unsigned j = 0; j < nnFound; ++j)
771 maxSquareDist = -1.0;
774 if (finalNeighbourhoodSize) {
783 int* cellDists)
const {
786 int* _cellDists = cellDists;
787 *_cellDists++ = cellPos.
x - fillIndexes[0];
788 *_cellDists++ = fillIndexes[3] - cellPos.
x;
789 *_cellDists++ = cellPos.
y - fillIndexes[1];
790 *_cellDists++ = fillIndexes[4] - cellPos.
y;
791 *_cellDists++ = cellPos.
z - fillIndexes[2];
792 *_cellDists++ = fillIndexes[5] - cellPos.
z;
797 int neighbourhoodLength,
801 int* _limits = limits;
802 for (
int dim = 0; dim < 3; ++dim) {
805 int a = cellPos.
u[dim] - fillIndexes[dim];
806 if (a < -neighbourhoodLength)
807 a = -neighbourhoodLength;
808 else if (a > neighbourhoodLength)
809 a = neighbourhoodLength;
815 int b = fillIndexes[3 + dim] - cellPos.
u[dim];
816 if (b < -neighbourhoodLength)
817 b = -neighbourhoodLength;
818 else if (b > neighbourhoodLength)
819 b = neighbourhoodLength;
828 int neighbourhoodLength,
829 unsigned char level)
const {
830 assert(neighbourhoodLength > 0);
837 const int& iMin = limits[0];
838 const int& iMax = limits[1];
839 const int& jMin = limits[2];
840 const int& jMax = limits[3];
841 const int& kMin = limits[4];
842 const int& kMax = limits[5];
847 for (
int i = -iMin; i <= iMax; i++) {
850 neighbourhoodLength);
854 for (
int j = -jMin; j <= jMax; j++) {
858 (
abs(j) == neighbourhoodLength))
861 for (
int k = -kMin; k <= kMax; k++) {
867 neighborCellsIndexes.push_back(index);
879 cellPos.
z - neighbourhoodLength)
884 neighborCellsIndexes.push_back(index);
898 neighborCellsIndexes.push_back(index);
908 int neighbourhoodLength,
909 bool getOnlyPointsWithValidScalar )
const {
918 const int& iMin = limits[0];
919 const int& iMax = limits[1];
920 const int& jMin = limits[2];
921 const int& jMax = limits[3];
922 const int& kMin = limits[4];
923 const int& kMax = limits[5];
928 for (
int i = -iMin; i <= iMax; i++) {
931 neighbourhoodLength);
935 for (
int j = -jMin; j <= jMax; j++) {
941 (
abs(j) == neighbourhoodLength))
944 for (
int k = -kMin; k <= kMax; k++) {
956 static_cast<unsigned>(
967 for (cellsContainer::const_iterator p =
971 ((p->theCode >> bitDec) == c2);
973 if (!getOnlyPointsWithValidScalar ||
976 ->getPointScalarValue(
980 ->getPointPersistentPtr(
1007 static_cast<unsigned>(
1018 for (cellsContainer::const_iterator p =
1022 ((p->theCode >> bitDec) == c2);
1024 if (!getOnlyPointsWithValidScalar ||
1027 ->getPointScalarValue(
1031 ->getPointPersistentPtr(
1040 neighbourhoodLength)
1047 neighbourhoodLength)
1057 static_cast<unsigned>(
1068 for (cellsContainer::const_iterator p =
1072 ((p->theCode >> bitDec) == c2);
1074 if (!getOnlyPointsWithValidScalar ||
1077 ->getPointScalarValue(
1081 ->getPointPersistentPtr(
1093 #ifdef TEST_CELLS_FOR_SPHERICAL_NN
1095 NearestNeighboursSphericalSearchStruct& nNSS,
1096 int minNeighbourhoodLength,
1097 int maxNeighbourhoodLength)
const {
1098 assert(minNeighbourhoodLength >= nNSS.alreadyVisitedNeighbourhoodSize);
1102 CellDescriptor cellDesc;
1104 if (minNeighbourhoodLength == 0)
1110 unsigned index =
getCellIndex(truncatedCellCode, bitDec);
1113 cellDesc.center =
CCVector3(nNSS.cellCenter);
1115 nNSS.cellsInNeighbourhood.push_back(cellDesc);
1117 for (cellsContainer::const_iterator p =
1120 ((p->theCode >> bitDec) == truncatedCellCode);
1122 PointDescriptor newPoint(
1126 nNSS.pointsInSphericalNeighbourhood.push_back(newPoint);
1129 if (maxNeighbourhoodLength == 0)
return;
1130 ++minNeighbourhoodLength;
1136 maxNeighbourhoodLength, limits))
1139 int& iMinAbs = limits[0];
1140 int& iMaxAbs = limits[1];
1141 int& jMinAbs = limits[2];
1142 int& jMaxAbs = limits[3];
1143 int& kMinAbs = limits[4];
1144 int& kMaxAbs = limits[5];
1146 unsigned old_index = 0;
1151 if (iMinAbs >= minNeighbourhoodLength) {
1152 for (
int v0 = nNSS.cellPos.x - iMinAbs;
1153 v0 <= nNSS.cellPos.x - minNeighbourhoodLength; ++v0) {
1155 currentCellPos.
x = v0;
1156 for (
int v1 = nNSS.cellPos.y - jMinAbs;
1157 v1 <= nNSS.cellPos.y + jMaxAbs; ++v1) {
1159 currentCellPos.
y = v1;
1160 for (
int v2 = nNSS.cellPos.z - kMinAbs;
1161 v2 <= nNSS.cellPos.z + kMaxAbs; ++v2) {
1168 c2, bitDec, old_index,
1173 currentCellPos.
z = v2;
1177 nNSS.pointsInSphericalNeighbourhood.size();
1178 nNSS.cellsInNeighbourhood.push_back(cellDesc);
1180 for (cellsContainer::const_iterator p =
1184 ((p->theCode >> bitDec) == c2);
1186 PointDescriptor newPoint(
1190 nNSS.pointsInSphericalNeighbourhood.push_back(
1200 iMinAbs = minNeighbourhoodLength - 1;
1204 if (iMaxAbs >= minNeighbourhoodLength) {
1205 for (
int v0 = nNSS.cellPos.x + minNeighbourhoodLength;
1206 v0 <= nNSS.cellPos.x + iMaxAbs; ++v0) {
1208 currentCellPos.
x = v0;
1209 for (
int v1 = nNSS.cellPos.y - jMinAbs;
1210 v1 <= nNSS.cellPos.y + jMaxAbs; ++v1) {
1212 currentCellPos.
y = v1;
1213 for (
int v2 = nNSS.cellPos.z - kMinAbs;
1214 v2 <= nNSS.cellPos.z + kMaxAbs; ++v2) {
1221 c2, bitDec, old_index,
1226 currentCellPos.
z = v2;
1230 nNSS.pointsInSphericalNeighbourhood.size();
1231 nNSS.cellsInNeighbourhood.push_back(cellDesc);
1233 for (cellsContainer::const_iterator p =
1237 ((p->theCode >> bitDec) == c2);
1239 PointDescriptor newPoint(
1243 nNSS.pointsInSphericalNeighbourhood.push_back(
1253 iMaxAbs = minNeighbourhoodLength - 1;
1257 if (jMinAbs >= minNeighbourhoodLength) {
1258 for (
int v1 = nNSS.cellPos.y - jMinAbs;
1259 v1 <= nNSS.cellPos.y - minNeighbourhoodLength; ++v1) {
1261 currentCellPos.
y = v1;
1262 for (
int v0 = nNSS.cellPos.x - iMinAbs;
1263 v0 <= nNSS.cellPos.x + iMaxAbs; ++v0) {
1265 currentCellPos.
x = v0;
1266 for (
int v2 = nNSS.cellPos.z - kMinAbs;
1267 v2 <= nNSS.cellPos.z + kMaxAbs; ++v2) {
1274 c2, bitDec, old_index,
1279 currentCellPos.
z = v2;
1283 nNSS.pointsInSphericalNeighbourhood.size();
1284 nNSS.cellsInNeighbourhood.push_back(cellDesc);
1286 for (cellsContainer::const_iterator p =
1290 ((p->theCode >> bitDec) == c2);
1292 PointDescriptor newPoint(
1296 nNSS.pointsInSphericalNeighbourhood.push_back(
1306 jMinAbs = minNeighbourhoodLength - 1;
1310 if (jMaxAbs >= minNeighbourhoodLength) {
1311 for (
int v1 = nNSS.cellPos.y + minNeighbourhoodLength;
1312 v1 <= nNSS.cellPos.y + jMaxAbs; ++v1) {
1314 currentCellPos.
y = v1;
1315 for (
int v0 = nNSS.cellPos.x - iMinAbs;
1316 v0 <= nNSS.cellPos.x + iMaxAbs; ++v0) {
1318 currentCellPos.
x = v0;
1319 for (
int v2 = nNSS.cellPos.z - kMinAbs;
1320 v2 <= nNSS.cellPos.z + kMaxAbs; ++v2) {
1327 c2, bitDec, old_index,
1332 currentCellPos.
z = v2;
1336 nNSS.pointsInSphericalNeighbourhood.size();
1337 nNSS.cellsInNeighbourhood.push_back(cellDesc);
1339 for (cellsContainer::const_iterator p =
1343 ((p->theCode >> bitDec) == c2);
1345 PointDescriptor newPoint(
1349 nNSS.pointsInSphericalNeighbourhood.push_back(
1359 jMaxAbs = minNeighbourhoodLength - 1;
1363 if (kMinAbs >= minNeighbourhoodLength) {
1364 for (
int v2 = nNSS.cellPos.z - kMinAbs;
1365 v2 <= nNSS.cellPos.z - minNeighbourhoodLength; ++v2) {
1367 currentCellPos.
z = v2;
1368 for (
int v0 = nNSS.cellPos.x - iMinAbs;
1369 v0 <= nNSS.cellPos.x + iMaxAbs; ++v0) {
1371 currentCellPos.
x = v0;
1372 for (
int v1 = nNSS.cellPos.y - jMinAbs;
1373 v1 <= nNSS.cellPos.y + jMaxAbs; ++v1) {
1379 c1, bitDec, old_index,
1384 currentCellPos.
y = v1;
1388 nNSS.pointsInSphericalNeighbourhood.size();
1389 nNSS.cellsInNeighbourhood.push_back(cellDesc);
1391 for (cellsContainer::const_iterator p =
1395 ((p->theCode >> bitDec) == c1);
1397 PointDescriptor newPoint(
1401 nNSS.pointsInSphericalNeighbourhood.push_back(
1415 if (kMaxAbs >= minNeighbourhoodLength) {
1416 for (
int v2 = nNSS.cellPos.z + minNeighbourhoodLength;
1417 v2 <= nNSS.cellPos.z + kMaxAbs; ++v2) {
1419 currentCellPos.
z = v2;
1420 for (
int v0 = nNSS.cellPos.x - iMinAbs;
1421 v0 <= nNSS.cellPos.x + iMaxAbs; ++v0) {
1423 currentCellPos.
x = v0;
1424 for (
int v1 = nNSS.cellPos.y - jMinAbs;
1425 v1 <= nNSS.cellPos.y + jMaxAbs; ++v1) {
1431 c1, bitDec, old_index,
1436 currentCellPos.
y = v1;
1440 nNSS.pointsInSphericalNeighbourhood.size();
1441 nNSS.cellsInNeighbourhood.push_back(cellDesc);
1443 for (cellsContainer::const_iterator p =
1447 ((p->theCode >> bitDec) == c1);
1449 PointDescriptor newPoint(
1453 nNSS.pointsInSphericalNeighbourhood.push_back(
1481 int eligibleCellDistance = visitedCellDistance;
1485 if (visitedCellDistance == 0) {
1497 visitedCellDistance = 1;
1503 eligibleCellDistance = 1;
1510 int diagonalDistance = 0;
1511 for (
int dim = 0; dim < 3; ++dim) {
1513 int distToBorder = *_fillIndexes - nNSS.
cellPos.
u[dim];
1515 if (distToBorder < 0) {
1517 distToBorder = nNSS.
cellPos.
u[dim] - _fillIndexes[3];
1520 if (distToBorder > 0) {
1521 visitedCellDistance =
1522 std::max(distToBorder, visitedCellDistance);
1523 diagonalDistance += distToBorder * distToBorder;
1531 diagonalDistance =
static_cast<int>(
1532 ceil(sqrt(
static_cast<float>(diagonalDistance))));
1533 eligibleCellDistance =
std::max(diagonalDistance, 1);
1538 static_cast<double>(eligibleCellDistance - 1) * cs;
1559 unsigned alreadyProcessedCells = 0;
1562 double minSquareDist = -1.0;
1566 if (minSquareDist > 0) {
1568 int newEligibleCellDistance =
static_cast<int>(
ceil(
1572 eligibleCellDistance =
1573 std::max(newEligibleCellDistance, eligibleCellDistance);
1578 eligibleCellDistance)
1590 DgmOctree::cellIndexesContainer::const_iterator q;
1597 cellsContainer::const_iterator p =
1599 CellCode code = (p->theCode >> bitDec);
1601 (p->theCode >> bitDec) == code) {
1608 if (dist2 < minSquareDist || minSquareDist < 0) {
1610 minSquareDist = dist2;
1618 alreadyProcessedCells =
1625 double eligibleDist =
1626 static_cast<double>(eligibleCellDistance - 1) * cs +
1628 double squareEligibleDist = eligibleDist * eligibleDist;
1631 if (minSquareDist >= 0 && minSquareDist <= squareEligibleDist) {
1634 return minSquareDist;
1645 ++eligibleCellDistance;
1657 bool getOnlyPointsWithValidScalar )
const {
1669 int eligibleCellDistance = visitedCellDistance;
1672 if (visitedCellDistance == 0) {
1684 visitedCellDistance = 1;
1689 cellsContainer::const_iterator p =
1692 (p->theCode >> bitDec) == truncatedCellCode) {
1693 if (!getOnlyPointsWithValidScalar ||
1705 eligibleCellDistance = 1;
1712 int diagonalDistance = 0;
1713 for (
int dim = 0; dim < 3; ++dim) {
1715 int distToBorder = *_fillIndexes - nNSS.
cellPos.
u[dim];
1717 if (distToBorder < 0) {
1719 distToBorder = nNSS.
cellPos.
u[dim] - _fillIndexes[3];
1722 if (distToBorder > 0) {
1723 visitedCellDistance =
1724 std::max(distToBorder, visitedCellDistance);
1725 diagonalDistance += distToBorder * distToBorder;
1733 diagonalDistance =
static_cast<int>(
1734 ceil(sqrt(
static_cast<float>(diagonalDistance))));
1735 eligibleCellDistance =
std::max(diagonalDistance, 1);
1740 static_cast<double>(eligibleCellDistance - 1) * cs;
1757 unsigned eligiblePoints = 0;
1760 unsigned alreadyProcessedPoints = 0;
1763 double minSquareDist = -1.0;
1768 if (minSquareDist > 0) {
1770 int newEligibleCellDistance =
static_cast<int>(
ceil(
1774 eligibleCellDistance =
1775 std::max(newEligibleCellDistance, eligibleCellDistance);
1779 while (visitedCellDistance <
1780 eligibleCellDistance)
1785 getOnlyPointsWithValidScalar);
1786 ++visitedCellDistance;
1790 NeighboursSet::iterator q;
1793 q->squareDistd = (*q->point - nNSS.
queryPoint).norm2d();
1794 alreadyProcessedPoints =
1801 double eligibleDist =
1802 static_cast<double>(eligibleCellDistance - 1) * cs +
1804 double squareEligibleDist = eligibleDist * eligibleDist;
1808 unsigned j = eligiblePoints;
1812 if (q->squareDistd <= squareEligibleDist) {
1813 if (eligiblePoints < j)
1819 else if (q->squareDistd < minSquareDist || j == eligiblePoints) {
1820 minSquareDist = q->squareDistd;
1830 ++eligibleCellDistance;
1843 return eligiblePoints;
1850 unsigned char level )
const {
1856 double squareRadius =
1857 static_cast<double>(radius) *
static_cast<double>(radius);
1859 double maxDiagFactor = squareRadius + (0.75 * cs +
SQRT_3 * radius) * cs;
1867 cornerPos.
x = std::max<int>(cornerPos.
x, 0);
1868 cornerPos.
y = std::max<int>(cornerPos.
y, 0);
1869 cornerPos.
z = std::max<int>(cornerPos.
z, 0);
1882 Tuple3i cellPos(cornerPos.
x, 0, 0);
1883 while (cellMin.
x < sphereCenter.
x + radius && cellPos.
x < maxCellCount) {
1884 CCVector3 cellCenter(cellMin.
x + halfCellSize, 0, 0);
1886 cellMin.
y = boxMin.
y;
1887 cellPos.
y = cornerPos.
y;
1888 while (cellMin.
y < sphereCenter.
y + radius &&
1889 cellPos.
y < maxCellCount) {
1890 cellCenter.
y = cellMin.
y + halfCellSize;
1892 cellMin.
z = boxMin.
z;
1893 cellPos.
z = cornerPos.
z;
1894 while (cellMin.
z < sphereCenter.
z + radius &&
1895 cellPos.
z < maxCellCount) {
1896 cellCenter.
z = cellMin.
z + halfCellSize;
1899 if ((cellCenter - sphereCenter).norm2d() <=
1905 unsigned cellIndex =
1913 cellsContainer::const_iterator p =
1916 CellCode searchCode = (p->theCode >> bitDec);
1920 ((p->theCode >> bitDec) == searchCode);
1924 double d2 = (*P - sphereCenter).norm2d();
1926 if (d2 <= squareRadius) {
1927 neighbours.emplace_back(P, p->theIndex, d2);
1948 return static_cast<int>(neighbours.size());
1961 params.axes[0].normalize();
1962 params.axes[1].normalize();
1963 params.axes[2].normalize();
1979 for (
unsigned char i = 0; i < 8; ++i) {
1980 corners[i] = corners[i].
x *
params.axes[0] +
1981 corners[i].
y *
params.axes[1] +
1982 corners[i].
z *
params.axes[2];
1984 if (corners[i].x < minCorner.
x)
1985 minCorner.
x = corners[i].
x;
1986 else if (corners[i].x > maxCorner.
x)
1987 maxCorner.
x = corners[i].
x;
1989 if (corners[i].y < minCorner.
y)
1990 minCorner.
y = corners[i].
y;
1991 else if (corners[i].y > maxCorner.
y)
1992 maxCorner.
y = corners[i].
y;
1994 if (corners[i].z < minCorner.
z)
1995 minCorner.
z = corners[i].
z;
1996 else if (corners[i].z > maxCorner.
z)
1997 maxCorner.
z = corners[i].
z;
1999 minCorner = maxCorner = corners[0];
2004 minCorner =
params.center + minCorner;
2005 maxCorner =
params.center + maxCorner;
2020 minCornerPos.
x = std::max<int>(minCornerPos.
x, minFillIndexes[0]);
2021 minCornerPos.
y = std::max<int>(minCornerPos.
y, minFillIndexes[1]);
2022 minCornerPos.
z = std::max<int>(minCornerPos.
z, minFillIndexes[2]);
2024 maxCornerPos.
x = std::min<int>(maxCornerPos.
x, maxFillIndexes[0]);
2025 maxCornerPos.
y = std::min<int>(maxCornerPos.
y, maxFillIndexes[1]);
2026 maxCornerPos.
z = std::min<int>(maxCornerPos.
z, maxFillIndexes[2]);
2030 CCVector3 maxHalfDist = boxHalfDimensions;
2034 maxHalfDist +=
CCVector3(halfDiag, halfDiag, halfDiag);
2040 for (
int i = minCornerPos.
x; i <= maxCornerPos.
x; ++i) {
2041 for (
int j = minCornerPos.
y; j <= maxCornerPos.
y; ++j) {
2042 for (
int k = minCornerPos.
z; k <= maxCornerPos.
z; ++k) {
2071 unsigned cellIndex =
getCellIndex(truncatedCellCode, bitDec);
2077 cellsContainer::const_iterator p =
2079 CellCode searchCode = (p->theCode >> bitDec);
2083 ((p->theCode >> bitDec) == searchCode);
2100 params.neighbours.emplace_back(P, p->theIndex, 0);
2108 return params.neighbours.size();
2118 double squareRadius =
static_cast<double>(
params.radius) *
2119 static_cast<double>(
params.radius);
2121 double maxDiagFactor =
2122 squareRadius + (0.75 * cs +
SQRT_3 *
params.radius) * cs;
2127 params.onlyPositiveDir ? 0 : -maxLengthFactor;
2171 cornerPos.
x = std::max<int>(cornerPos.
x, minFillIndexes[0]);
2172 cornerPos.
y = std::max<int>(cornerPos.
y, minFillIndexes[1]);
2173 cornerPos.
z = std::max<int>(cornerPos.
z, minFillIndexes[2]);
2185 Tuple3i cellPos(cornerPos.
x, 0, 0);
2186 while (cellMin.
x < maxCorner.
x && cellPos.
x <= maxFillIndexes[0]) {
2187 CCVector3 cellCenter(cellMin.
x + halfCellSize, 0, 0);
2189 cellMin.
y = boxMin.
y;
2190 cellPos.
y = cornerPos.
y;
2191 while (cellMin.
y < maxCorner.
y && cellPos.
y <= maxFillIndexes[1]) {
2192 cellCenter.
y = cellMin.
y + halfCellSize;
2194 cellMin.
z = boxMin.
z;
2195 cellPos.
z = cornerPos.
z;
2196 while (cellMin.
z < maxCorner.
z && cellPos.
z <= maxFillIndexes[2]) {
2197 cellCenter.
z = cellMin.
z + halfCellSize;
2202 double d2 = (OC -
params.dir *
dot).norm2d();
2203 if (d2 <= maxDiagFactor &&
dot <= maxLengthFactor &&
2204 dot >= minLengthFactor)
2210 unsigned cellIndex =
2218 cellsContainer::const_iterator p =
2221 CellCode searchCode = (p->theCode >> bitDec);
2225 ((p->theCode >> bitDec) == searchCode);
2234 if (d2 <= squareRadius && dot >= minHalfLength &&
2236 params.neighbours.emplace_back(
2261 return params.neighbours.size();
2271 double squareRadius =
static_cast<double>(
params.radius) *
2272 static_cast<double>(
params.radius);
2274 double maxDiagFactor =
2275 squareRadius + (0.75 * cs +
SQRT_3 *
params.radius) * cs;
2280 params.onlyPositiveDir ? 0 : -maxLengthFactor;
2290 params.onlyPositiveDir ? 0 : -
params.currentHalfLength;
2294 for (std::size_t k = 0; k <
params.potentialCandidates.size();
2297 if (
params.potentialCandidates[k].squareDistd >=
2298 currentHalfLengthMinus &&
2299 params.potentialCandidates[k].squareDistd <=
2300 params.currentHalfLength) {
2301 params.neighbours.push_back(
params.potentialCandidates[k]);
2304 params.potentialCandidates.back());
2305 params.potentialCandidates.pop_back();
2351 cornerPos.
x = std::max<int>(cornerPos.
x, minFillIndexes[0]);
2352 cornerPos.
y = std::max<int>(cornerPos.
y, minFillIndexes[1]);
2353 cornerPos.
z = std::max<int>(cornerPos.
z, minFillIndexes[2]);
2364 Tuple3i cellPos(cornerPos.
x, 0, 0);
2366 while (cellMin.
x < maxCorner.
x && cellPos.
x <= maxFillIndexes[0]) {
2367 CCVector3 cellCenter(cellMin.
x + halfCellSize, 0, 0);
2369 cellMin.
y = boxMin.
y;
2370 cellPos.
y = cornerPos.
y;
2371 while (cellMin.
y < maxCorner.
y && cellPos.
y <= maxFillIndexes[1]) {
2372 cellCenter.
y = cellMin.
y + halfCellSize;
2374 cellMin.
z = boxMin.
z;
2375 cellPos.
z = cornerPos.
z;
2376 while (cellMin.
z < maxCorner.
z && cellPos.
z <= maxFillIndexes[2]) {
2377 cellCenter.
z = cellMin.
z + halfCellSize;
2380 if (cellPos.
x <
params.prevMinCornerPos.x ||
2381 cellPos.
x >=
params.prevMaxCornerPos.x ||
2382 cellPos.
y <
params.prevMinCornerPos.y ||
2383 cellPos.
y >=
params.prevMaxCornerPos.y ||
2384 cellPos.
z <
params.prevMinCornerPos.z ||
2385 cellPos.
z >=
params.prevMaxCornerPos.z) {
2390 double d2 = (OC -
params.dir *
dot).norm2d();
2391 if (d2 <= maxDiagFactor &&
dot <= maxLengthFactor &&
2392 dot >= minLengthFactor)
2398 unsigned cellIndex =
2406 cellsContainer::const_iterator p =
2409 CellCode searchCode = (p->theCode >> bitDec);
2413 ((p->theCode >> bitDec) == searchCode);
2423 if (d2 <= squareRadius) {
2425 if (
dot >= currentHalfLengthMinus &&
2427 params.neighbours.emplace_back(
2433 }
else if (
params.currentHalfLength <
2437 params.potentialCandidates.emplace_back(
2465 params.prevMinCornerPos = cornerPos;
2466 params.prevMaxCornerPos = cellPos;
2468 return params.neighbours.size();
2471 #ifdef COMPUTE_NN_SEARCH_STATISTICS
2472 static double s_skippedPoints = 0.0;
2473 static double s_testedPoints = 0.0;
2482 bool sortValues)
const {
2483 #ifdef TEST_CELLS_FOR_SPHERICAL_NN
2490 int minNeighbourhoodSize =
2491 static_cast<int>(
ceil(radius / cs +
SQRT_3 / 2.0));
2493 nNSS.cellsInNeighbourhood.reserve(minNeighbourhoodSize *
2494 minNeighbourhoodSize *
2495 minNeighbourhoodSize);
2498 nNSS.cellsInNeighbourhood.empty() &&
2502 nNSS.cellsInNeighbourhood.push_back(
2509 minNeighbourhoodSize);
2512 nNSS.pointsInSphericalNeighbourhood.size())
2514 nNSS.pointsInSphericalNeighbourhood.size());
2532 const int minNeighbourhoodSize =
2534 (radius > minDistToBorder
2535 ?
static_cast<int>(
ceil((radius - minDistToBorder) / cs))
2542 i < minNeighbourhoodSize; ++i)
2551 const double squareRadius = radius * radius;
2552 unsigned numberOfEligiblePoints = 0;
2554 #ifdef TEST_CELLS_FOR_SPHERICAL_NN
2563 for (NeighbourCellsSet::iterator c = nNSS.cellsInNeighbourhood.begin();
2564 c != nNSS.cellsInNeighbourhood.end(); ++c) {
2576 if (d2 <= nNSS.minOutD2) {
2577 NeighboursSet::iterator p =
2578 nNSS.pointsInSphericalNeighbourhood.begin() + c->index;
2580 ((c + 1) != nNSS.cellsInNeighbourhood.end()
2582 : nNSS.pointsInSphericalNeighbourhood.size()) -
2591 numberOfEligiblePoints);
2592 numberOfEligiblePoints +=
count;
2593 #ifdef COMPUTE_NN_SEARCH_STATISTICS
2594 s_skippedPoints +=
static_cast<double>(
count);
2597 for (
unsigned j = 0; j <
count; ++j, ++p) {
2598 p->squareDist = (*p->point - nNSS.
queryPoint).norm2();
2599 #ifdef COMPUTE_NN_SEARCH_STATISTICS
2600 s_testedPoints += 1.0;
2603 if (p->squareDistd <= squareRadius) {
2614 #ifdef COMPUTE_NN_SEARCH_STATISTICS
2616 ((c + 1) != nNSS.cellsInNeighbourhood.end()
2618 : nNSS.pointsInSphericalNeighbourhood.size()) -
2620 s_skippedPoints +=
static_cast<double>(
count);
2636 if (i > numberOfEligiblePoints) {
2641 ++numberOfEligiblePoints;
2643 #ifdef COMPUTE_NN_SEARCH_STATISTICS
2644 s_testedPoints += 1.0;
2654 if (sortValues && numberOfEligiblePoints > 0) {
2661 return numberOfEligiblePoints;
2669 0, radius / c_neighbourhoodSizeExtractionFactor);
2673 minValue *= minValue;
2680 cellSizeDelta *= cellSizeDelta;
2682 if (cellSizeDelta < minValue) {
2684 minValue = cellSizeDelta;
2688 return static_cast<unsigned char>(level);
2692 const DgmOctree* theOtherOctree)
const {
2701 static_cast<unsigned char>(5));
2702 else if (
std::max(ptsA, ptsB) < 2000000)
2705 static_cast<unsigned char>(10));
2708 unsigned char bestLevel = 1;
2710 for (
int i = 1; i < maxOctreeLevel; ++i)
2719 diffB, cellsA, cellsB);
2727 ((
static_cast<double>(ptsA) * ptsB) / cellsB) * 0.001 + diffA;
2729 if (estimatedTime[i] < estimatedTime[bestLevel]) {
2738 unsigned indicativeNumberOfPointsPerCell)
const {
2741 indicativeNumberOfPointsPerCell)
2748 indicativeNumberOfPointsPerCell <=
2749 indicativeNumberOfPointsPerCell -
2767 unsigned indicativeNumberOfCells)
const {
2770 unsigned char bestLevel = 1;
2774 int oldd =
abs(n -
static_cast<int>(indicativeNumberOfCells));
2777 int d =
abs(n -
static_cast<int>(indicativeNumberOfCells));
2783 d =
abs(n -
static_cast<int>(indicativeNumberOfCells));
2796 bool truncatedCodes )
const {
2804 (p->theCode >> bitDec) +
2808 CellCode currentCode = (p->theCode >> bitDec);
2810 if (predCode != currentCode)
2811 vec.emplace_back(i, truncatedCodes ? currentCode : p->theCode);
2813 predCode = currentCode;
2815 }
catch (
const std::bad_alloc&) {
2824 bool truncatedCodes )
const {
2832 (p->theCode >> bitDec) +
2836 CellCode currentCode = (p->theCode >> bitDec);
2838 if (predCode != currentCode)
2839 vec.push_back(truncatedCodes ? currentCode : p->theCode);
2841 predCode = currentCode;
2843 }
catch (
const std::bad_alloc&) {
2854 }
catch (
const std::bad_alloc&) {
2865 (p->theCode >> bitDec) +
2869 CellCode currentCode = (p->theCode >> bitDec);
2871 if (predCode != currentCode) vec[j++] = i;
2873 predCode = currentCode;
2882 unsigned char level,
2883 bool clearOutputCloud )
const {
2891 cellsContainer::const_iterator p =
2893 CellCode searchCode = (p->theCode >> bitDec);
2895 if (clearOutputCloud) {
2901 ((p->theCode >> bitDec) == searchCode)) {
2911 unsigned char level,
2913 bool areCodesTruncated )
const {
2919 unsigned char bitDec2 =
2920 (areCodesTruncated ? 0 : bitDec1);
2925 (p->theCode >> bitDec1);
2930 cellCodesContainer::const_iterator q = cellCodes.begin();
2934 while (((toExtractCode = (*q >> bitDec2)) < currentCode) &&
2935 (q != cellCodes.end()))
2938 if (q == cellCodes.end())
break;
2942 (currentCode <= toExtractCode)) {
2943 if (currentCode == toExtractCode)
2948 currentCode = p->theCode >> bitDec1;
2959 if (codesA.empty() && codesB.empty())
return;
2961 cellCodesContainer::const_iterator pA = codesA.begin();
2962 cellCodesContainer::const_iterator pB = codesB.begin();
2965 while (pA != codesA.end() && pB != codesB.end()) {
2967 diffA.push_back(*pA++);
2969 diffB.push_back(*pB++);
2976 while (pA != codesA.end()) diffA.push_back(*pA++);
2977 while (pB != codesB.end()) diffB.push_back(*pB++);
2986 int& cellsB)
const {
2992 if (codesA.empty() && codesB.empty()) {
2996 cellsContainer::const_iterator pA = codesA.begin();
2997 cellsContainer::const_iterator pB = codesB.begin();
3002 CellCode predCodeA = pA->theCode >> bitDec;
3003 CellCode predCodeB = pB->theCode >> bitDec;
3009 while ((pA != codesA.end()) && (pB != codesB.end())) {
3010 if (predCodeA < predCodeB) {
3013 while ((pA != codesA.end()) &&
3014 ((currentCodeA = (pA->theCode >> bitDec)) == predCodeA))
3016 predCodeA = currentCodeA;
3017 }
else if (predCodeA > predCodeB) {
3020 while ((pB != codesB.end()) &&
3021 ((currentCodeB = (pB->theCode >> bitDec)) == predCodeB))
3023 predCodeB = currentCodeB;
3025 while ((pA != codesA.end()) &&
3026 ((currentCodeA = (pA->theCode >> bitDec)) == predCodeA))
3028 predCodeA = currentCodeA;
3030 while ((pB != codesB.end()) &&
3031 ((currentCodeB = (pB->theCode >> bitDec)) == predCodeB))
3033 predCodeB = currentCodeB;
3038 while (pA != codesA.end()) {
3041 while ((pA != codesA.end()) &&
3042 ((currentCodeA = (pA->theCode >> bitDec)) == predCodeA))
3044 predCodeA = currentCodeA;
3046 while (pB != codesB.end()) {
3049 while ((pB != codesB.end()) &&
3050 ((currentCodeB = (pB->theCode >> bitDec)) == predCodeB))
3052 predCodeB = currentCodeB;
3061 std::vector<CellCode> cellCodes;
3063 return extractCCs(cellCodes, level, sixConnexity, progressCb);
3067 #ifdef OCTREE_CODES_64_BITS
3089 return a.theIndex < b.theIndex;
3094 unsigned char level,
3097 std::size_t numberOfCells = cellCodes.size();
3098 if (numberOfCells == 0)
3102 std::vector<IndexAndCodeExt> ccCells;
3104 ccCells.resize(numberOfCells);
3105 }
catch (
const std::bad_alloc&) {
3116 for (std::size_t i = 0; i < numberOfCells; i++) {
3117 ccCells[i].theCode = (cellCodes[i] >> bitDec);
3120 getCellPos(ccCells[i].theCode, level, cellPos,
true);
3125 for (
unsigned char k = 0; k < 3; k++) {
3126 if (cellPos.
u[k] < indexMin.
u[k])
3127 indexMin.
u[k] = cellPos.
u[k];
3128 else if (cellPos.
u[k] > indexMax.
u[k])
3129 indexMax.
u[k] = cellPos.
u[k];
3132 indexMin.
x = indexMax.
x = cellPos.
x;
3133 indexMin.
y = indexMax.
y = cellPos.
y;
3134 indexMin.
z = indexMax.
z = cellPos.
z;
3139 ccCells[i].theIndex =
3155 const int& di = gridSize.
x;
3156 const int& dj = gridSize.
y;
3157 const int& step = gridSize.
z;
3161 unsigned char neighborsInCurrentSlice = 0, neighborsInPrecedingSlice = 0;
3162 int currentSliceNeighborsShifts[4],
3163 precedingSliceNeighborsShifts[9];
3168 neighborsInCurrentSlice = 2;
3169 currentSliceNeighborsShifts[0] = -(di + 2);
3170 currentSliceNeighborsShifts[1] = -1;
3172 neighborsInPrecedingSlice = 1;
3173 precedingSliceNeighborsShifts[0] = 0;
3176 neighborsInCurrentSlice = 4;
3177 currentSliceNeighborsShifts[0] = -1 - (di + 2);
3178 currentSliceNeighborsShifts[1] = -(di + 2);
3179 currentSliceNeighborsShifts[2] = 1 - (di + 2);
3180 currentSliceNeighborsShifts[3] = -1;
3182 neighborsInPrecedingSlice = 9;
3183 precedingSliceNeighborsShifts[0] = -1 - (di + 2);
3184 precedingSliceNeighborsShifts[1] = -(di + 2);
3185 precedingSliceNeighborsShifts[2] = 1 - (di + 2);
3186 precedingSliceNeighborsShifts[3] = -1;
3187 precedingSliceNeighborsShifts[4] = 0;
3188 precedingSliceNeighborsShifts[5] = 1;
3189 precedingSliceNeighborsShifts[6] = -1 + (di + 2);
3190 precedingSliceNeighborsShifts[7] = (di + 2);
3191 precedingSliceNeighborsShifts[8] = 1 + (di + 2);
3195 std::vector<int> neighboursVal, neighboursMin;
3197 neighboursVal.reserve(neighborsInCurrentSlice +
3198 neighborsInPrecedingSlice);
3199 neighboursMin.reserve(neighborsInCurrentSlice +
3200 neighborsInPrecedingSlice);
3201 }
catch (
const std::bad_alloc&) {
3208 (di + 2) * (dj + 2);
3209 std::vector<int> slice;
3210 std::vector<int> oldSlice;
3212 std::vector<int> equivalentLabels;
3213 std::vector<int> cellIndexToLabel;
3216 slice.resize(sliceSize);
3217 oldSlice.resize(sliceSize, 0);
3218 equivalentLabels.resize(numberOfCells + 2, 0);
3219 cellIndexToLabel.resize(numberOfCells, 0);
3220 }
catch (
const std::bad_alloc&) {
3230 sprintf(buffer,
"Box: [%i*%i*%i]", gridSize.
x, gridSize.
y,
3235 progressCb->
start();
3239 std::size_t currentLabel = 1;
3243 unsigned counter = 0;
3246 std::vector<IndexAndCodeExt>::const_iterator _ccCells = ccCells.begin();
3249 for (
int k = indexMin.
z; k < indexMin.
z + step; k++) {
3251 std::fill(slice.begin(), slice.end(), 0);
3254 while (counter < numberOfCells &&
3255 static_cast<int>(_ccCells->theIndex >> (level << 1)) == k) {
3256 int iind =
static_cast<int>(_ccCells->theIndex & gridCoordMask);
3257 int jind =
static_cast<int>((_ccCells->theIndex >> level) &
3259 int cellIndex = (iind - indexMin.
x + 1) +
3260 (jind - indexMin.
y + 1) * (di + 2);
3264 int* _slice = &(slice[cellIndex]);
3266 for (
unsigned char n = 0; n < neighborsInCurrentSlice;
3268 assert(cellIndex + currentSliceNeighborsShifts[n] <
3270 const int& neighborLabel =
3271 _slice[currentSliceNeighborsShifts[n]];
3272 if (neighborLabel > 1)
3273 neighboursVal.push_back(neighborLabel);
3278 const int* _oldSlice = &(oldSlice[cellIndex]);
3280 for (
unsigned char n = 0; n < neighborsInPrecedingSlice;
3282 assert(cellIndex + precedingSliceNeighborsShifts[n] <
3284 const int& neighborLabel =
3285 _oldSlice[precedingSliceNeighborsShifts[n]];
3286 if (neighborLabel > 1)
3287 neighboursVal.push_back(neighborLabel);
3292 std::size_t p = neighboursVal.size();
3296 *_slice =
static_cast<int>(
3300 *_slice = neighboursVal.back();
3301 neighboursVal.pop_back();
3305 ParallelSort(neighboursVal.begin(), neighboursVal.end());
3307 int smallestLabel = neighboursVal[0];
3310 if (smallestLabel != neighboursVal.back()) {
3312 neighboursMin.clear();
3316 for (std::size_t n = 0; n < p; n++) {
3318 int label = neighboursVal[n];
3321 if (label != lastLabel) {
3324 static_cast<int>(numberOfCells) + 2);
3328 while (equivalentLabels[label] > 1) {
3329 label = equivalentLabels[label];
3331 static_cast<int>(numberOfCells) +
3335 neighboursMin.push_back(label);
3342 neighboursMin.end());
3344 smallestLabel = neighboursMin.front();
3348 lastLabel = smallestLabel;
3350 for (std::size_t n = 1; n < neighboursMin.size();
3352 int label = neighboursMin[n];
3354 static_cast<int>(numberOfCells) + 2);
3357 if (label != lastLabel) {
3358 equivalentLabels[label] = smallestLabel;
3366 *_slice = smallestLabel;
3367 neighboursVal.clear();
3370 cellIndexToLabel[counter++] = *_slice;
3373 if (counter == numberOfCells)
break;
3389 if (currentLabel < 2) {
3395 assert(currentLabel < numberOfCells + 2);
3397 for (std::size_t i = 2; i <= currentLabel; i++) {
3398 int label = equivalentLabels[i];
3399 assert(label <
static_cast<int>(numberOfCells) + 2);
3400 while (equivalentLabels[label] > 1)
3402 label = equivalentLabels[label];
3403 assert(label <
static_cast<int>(numberOfCells) + 2);
3405 equivalentLabels[i] = label;
3411 for (std::size_t i = 0; i < numberOfCells; i++) {
3412 int label = cellIndexToLabel[i];
3413 assert(label <
static_cast<int>(numberOfCells) + 2);
3414 if (equivalentLabels[label] > 1)
3415 cellIndexToLabel[i] = equivalentLabels[label];
3421 int numberOfComponents = 0;
3423 std::fill(equivalentLabels.begin(), equivalentLabels.end(), 0);
3425 for (std::size_t i = 0; i < numberOfCells; i++) {
3426 assert(cellIndexToLabel[i] > 1 &&
3427 cellIndexToLabel[i] <
static_cast<int>(numberOfCells) + 2);
3428 equivalentLabels[cellIndexToLabel[i]] = 1;
3432 for (std::size_t i = 2; i < numberOfCells + 2; i++)
3433 if (equivalentLabels[i] == 1)
3434 equivalentLabels[i] =
3435 ++numberOfComponents;
3437 assert(equivalentLabels[0] == 0);
3438 assert(equivalentLabels[1] == 0);
3445 sprintf(buffer,
"Components: %i", numberOfComponents);
3450 progressCb->
start();
3453 static_cast<unsigned>(numberOfCells));
3456 for (std::size_t i = 0; i < numberOfCells; i++) {
3457 assert(cellIndexToLabel[i] <
static_cast<int>(numberOfCells) + 2);
3459 const int& label = equivalentLabels[cellIndexToLabel[i]];
3463 ScalarType d =
static_cast<ScalarType
>(label);
3464 for (
unsigned j = 0; j < Y.
size(); ++j) {
3477 return numberOfComponents;
3483 : parentOctree(_parentOctree),
3496 : parentOctree(cell.parentOctree),
3498 truncatedCode(cell.truncatedCode),
3510 #ifdef ENABLE_MT_OCTREE
3513 struct octreeCellDesc {
3516 unsigned char level;
3519 static DgmOctree* s_octree_MT =
nullptr;
3521 static void** s_userParams_MT =
nullptr;
3524 static bool s_cellFunc_MT_success =
true;
3526 void LaunchOctreeCellFunc_MT(
const octreeCellDesc& desc) {
3528 if (!s_cellFunc_MT_success) {
3537 cell.level = desc.level;
3538 cell.index = desc.i1;
3539 cell.truncatedCode = desc.truncatedCode;
3540 if (cell.points->reserve(desc.i2 - desc.i1 + 1)) {
3541 for (
unsigned i = desc.i1; i <= desc.i2; ++i) {
3542 cell.points->addPointIndex(pointsAndCodes[i].theIndex);
3545 s_cellFunc_MT_success &=
3546 (*s_func_MT)(cell, s_userParams_MT, s_normProgressCb_MT);
3548 s_cellFunc_MT_success =
false;
3551 if (!s_cellFunc_MT_success) {
3554 if (s_progressCb_MT) {
3556 s_progressCb_MT->
setInfo(
"Cancelling...");
3574 unsigned char level,
3576 void** additionalParameters,
3579 const char* functionTitle ,
3580 int maxThreadCount ) {
3583 #ifdef ENABLE_MT_OCTREE
3587 std::vector<octreeCellDesc> cells;
3591 cells.reserve(cellsNumber);
3592 }
catch (
const std::bad_alloc&) {
3595 multiThread =
false;
3629 if (functionTitle) {
3634 "Octree level %i\nCells: %u\nMean population: %3.2f "
3635 "(+/-%3.2f)\nMax population: %u",
3642 progressCb->
start();
3648 #ifdef COMPUTE_NN_SEARCH_STATISTICS
3649 s_skippedPoints = 0;
3652 s_binarySearchCount = 0.0;
3658 CellCode nextCode = (p->theCode >> bitDec);
3661 result = (*func)(cell, additionalParameters, &nprogress);
3666 cell.index += cell.points->size();
3667 cell.points->clear();
3668 cell.truncatedCode = nextCode;
3675 if (
result)
result = (*func)(cell, additionalParameters, &nprogress);
3677 #ifdef COMPUTE_NN_SEARCH_STATISTICS
3678 FILE* fp = fopen(
"octree_log.txt",
"at");
3680 fprintf(fp,
"Function: %s\n",
3681 functionTitle ? functionTitle :
"unknown");
3682 fprintf(fp,
"Tested: %f (%3.1f %%)\n", s_testedPoints,
3683 100.0 * s_testedPoints /
3684 std::max(1.0, s_testedPoints + s_skippedPoints));
3685 fprintf(fp,
"skipped: %f (%3.1f %%)\n", s_skippedPoints,
3686 100.0 * s_skippedPoints /
3687 std::max(1.0, s_testedPoints + s_skippedPoints));
3688 fprintf(fp,
"Binary search count: %.0f\n", s_binarySearchCount);
3689 if (s_binarySearchCount > 0.0)
3690 fprintf(fp,
"Mean jumps: %f\n", s_jumps / s_binarySearchCount);
3697 return (
result ? cellCount : 0);
3699 #ifdef ENABLE_MT_OCTREE
3701 assert(cells.capacity() == cellsNumber);
3710 octreeCellDesc cellDesc;
3713 cellDesc.level = level;
3714 cellDesc.truncatedCode = (p->theCode >> bitDec);
3719 CellCode nextCode = (p->theCode >> bitDec);
3721 if (nextCode != cellDesc.truncatedCode) {
3722 cells.push_back(cellDesc);
3723 cellDesc.i1 = cellDesc.i2 + 1;
3726 cellDesc.truncatedCode = nextCode;
3730 cells.push_back(cellDesc);
3735 s_userParams_MT = additionalParameters;
3736 s_cellFunc_MT_success =
true;
3737 s_progressCb_MT = progressCb;
3738 if (s_normProgressCb_MT) {
3739 delete s_normProgressCb_MT;
3740 s_normProgressCb_MT = 0;
3746 if (functionTitle) {
3751 "Octree level %i\nCells: %i\nAverage population: %3.2f "
3752 "(+/-%3.2f)\nMax population: %u",
3753 level,
static_cast<int>(cells.size()),
3762 progressCb->
start();
3765 #ifdef COMPUTE_NN_SEARCH_STATISTICS
3766 s_skippedPoints = 0;
3769 s_binarySearchCount = 0.0;
3772 if (maxThreadCount == 0) {
3773 maxThreadCount = QThread::idealThreadCount();
3775 QThreadPool::globalInstance()->setMaxThreadCount(maxThreadCount);
3776 QtConcurrent::blockingMap(cells, LaunchOctreeCellFunc_MT);
3778 #ifdef COMPUTE_NN_SEARCH_STATISTICS
3779 FILE* fp = fopen(
"octree_log.txt",
"at");
3781 fprintf(fp,
"Function: %s\n",
3782 functionTitle ? functionTitle :
"unknown");
3783 fprintf(fp,
"Tested: %f (%3.1f %%)\n", s_testedPoints,
3784 100.0 * s_testedPoints /
3785 std::max(1.0, s_testedPoints + s_skippedPoints));
3786 fprintf(fp,
"skipped: %f (%3.1f %%)\n", s_skippedPoints,
3787 100.0 * s_skippedPoints /
3788 std::max(1.0, s_testedPoints + s_skippedPoints));
3789 fprintf(fp,
"Binary search count: %.0f\n", s_binarySearchCount);
3790 if (s_binarySearchCount > 0.0)
3791 fprintf(fp,
"Mean jumps: %f\n", s_jumps / s_binarySearchCount);
3797 s_octree_MT =
nullptr;
3798 s_func_MT =
nullptr;
3799 s_userParams_MT =
nullptr;
3803 if (s_normProgressCb_MT)
delete s_normProgressCb_MT;
3804 s_normProgressCb_MT =
nullptr;
3805 s_progressCb_MT =
nullptr;
3809 if (!s_cellFunc_MT_success) cells.clear();
3811 return static_cast<unsigned>(cells.size());
3817 #define ENABLE_DOWN_TOP_TRAVERSAL
3818 #define ENABLE_DOWN_TOP_TRAVERSAL_MT
3821 unsigned char startingLevel,
3823 void** additionalParameters,
3824 unsigned minNumberOfPointsPerCell,
3825 unsigned maxNumberOfPointsPerCell,
3828 const char* functionTitle ,
3829 int maxThreadCount ) {
3834 #ifdef ENABLE_MT_OCTREE
3837 std::vector<octreeCellDesc> cells;
3840 cells.reserve(cellsNumber);
3841 }
catch (
const std::bad_alloc&) {
3844 multiThread =
false;
3858 cell.
level = startingLevel;
3864 if (functionTitle) {
3869 "Octree levels %i - %i\nCells: %i - %i\nAverage "
3870 "population: %3.2f (+/-%3.2f) - %3.2f (+/-%3.2f)\nMax "
3871 "population: %u - %u",
3884 progressCb->
start();
3886 #ifndef ENABLE_DOWN_TOP_TRAVERSAL
3893 #ifdef ENABLE_DOWN_TOP_TRAVERSAL
3894 bool firstSubCell =
true;
3896 unsigned char shallowSteps = 0;
3900 cellsContainer::const_iterator startingElement =
3908 cell.
truncatedCode = (startingElement->theCode >> currentBitDec);
3911 unsigned elements = 1;
3914 #ifndef ENABLE_DOWN_TOP_TRAVERSAL
3927 100.0f *
static_cast<float>(cell.
index) /
3937 for (cellsContainer::const_iterator p = startingElement + 1;
3940 CellCode currentTruncatedCode = (p->theCode >> currentBitDec);
3944 if (elements == maxNumberOfPointsPerCell) {
3945 bool keepGoing =
true;
3956 (startingElement->theCode >> currentBitDec);
3960 (p->theCode >> currentBitDec)) {
3964 p = startingElement;
3966 while (((++p)->theCode >> currentBitDec) ==
3973 #ifdef ENABLE_DOWN_TOP_TRAVERSAL
3976 firstSubCell =
false;
3983 if (!keepGoing)
break;
3990 #ifndef ENABLE_DOWN_TOP_TRAVERSAL
3993 assert(shallowSteps == 0);
3995 while (cell.
level > startingLevel + shallowSteps) {
3996 cellTruncatedCode >>= 3;
3997 currentTruncatedCode >>= 3;
3999 if (cellTruncatedCode == currentTruncatedCode)
break;
4007 bool keepGoing =
false;
4009 if (cell.
level > startingLevel) {
4012 (currentTruncatedCode >> 3)) {
4017 elements < minNumberOfPointsPerCell) {
4032 firstSubCell =
false;
4036 firstSubCell =
true;
4041 firstSubCell =
true;
4045 if (!keepGoing)
break;
4059 for (
unsigned i = 0; i < elements; ++i) {
4064 result = (*func)(cell, additionalParameters,
4065 #ifndef ENABLE_DOWN_TOP_TRAVERSAL
4075 cell.index += elements;
4077 #ifndef ENABLE_DOWN_TOP_TRAVERSAL
4080 assert(cell.level - shallowSteps >= startingLevel);
4081 cell.level -= shallowSteps;
4082 currentBitDec += 3 * shallowSteps;
4093 return (
result ? cellsNumber : 0);
4095 #ifdef ENABLE_MT_OCTREE
4097 assert(cells.capacity() == cellsNumber);
4100 octreeCellDesc cellDesc;
4103 cellDesc.level = startingLevel;
4108 #ifdef ENABLE_DOWN_TOP_TRAVERSAL_MT
4109 bool firstSubCell =
true;
4111 unsigned char shallowSteps = 0;
4114 cellsContainer::const_iterator startingElement =
4118 unsigned long long popSum = 0;
4119 unsigned long long popSum2 = 0;
4120 unsigned long long maxPop = 0;
4125 cellDesc.truncatedCode =
4126 (startingElement->theCode >> currentBitDec);
4129 unsigned elements = 1;
4132 for (cellsContainer::const_iterator p = startingElement + 1;
4135 CellCode currentTruncatedCode = (p->theCode >> currentBitDec);
4137 if (currentTruncatedCode == cellDesc.truncatedCode) {
4139 if (elements == maxNumberOfPointsPerCell) {
4140 bool keepGoing =
true;
4150 cellDesc.truncatedCode =
4151 (startingElement->theCode >> currentBitDec);
4154 if (cellDesc.truncatedCode !=
4155 (p->theCode >> currentBitDec)) {
4159 p = startingElement;
4161 while (((++p)->theCode >> currentBitDec) ==
4162 cellDesc.truncatedCode)
4168 #ifdef ENABLE_DOWN_TOP_TRAVERSAL_MT
4171 firstSubCell =
false;
4178 if (!keepGoing)
break;
4185 #ifndef ENABLE_DOWN_TOP_TRAVERSAL_MT
4188 assert(shallowSteps == 0);
4189 CellCode cellTruncatedCode = cellDesc.truncatedCode;
4190 while (cellDesc.level > startingLevel + shallowSteps) {
4191 cellTruncatedCode >>= 3;
4192 currentTruncatedCode >>= 3;
4194 if (cellTruncatedCode == currentTruncatedCode)
break;
4202 bool keepGoing =
false;
4204 if (cellDesc.level > startingLevel) {
4206 if ((cellDesc.truncatedCode >> 3) ==
4207 (currentTruncatedCode >> 3)) {
4212 elements < minNumberOfPointsPerCell) {
4216 cellDesc.truncatedCode >>= 3;
4227 firstSubCell =
false;
4231 firstSubCell =
true;
4236 firstSubCell =
true;
4240 if (!keepGoing)
break;
4246 cellDesc.i2 = cellDesc.i1 + (elements - 1);
4247 cells.push_back(cellDesc);
4248 popSum +=
static_cast<unsigned long long>(elements);
4249 popSum2 +=
static_cast<unsigned long long>(elements * elements);
4250 if (maxPop < elements) maxPop = elements;
4253 cellDesc.i1 += elements;
4254 startingElement += elements;
4256 #ifndef ENABLE_DOWN_TOP_TRAVERSAL_MT
4259 assert(cellDesc.level - shallowSteps >= startingLevel);
4260 cellDesc.level -= shallowSteps;
4261 currentBitDec += 3 * shallowSteps;
4268 double mean =
static_cast<double>(popSum) / cells.size();
4269 double stddev = sqrt(
static_cast<double>(popSum2 - popSum * popSum)) /
4275 s_userParams_MT = additionalParameters;
4276 s_cellFunc_MT_success =
true;
4277 if (s_normProgressCb_MT)
delete s_normProgressCb_MT;
4278 s_normProgressCb_MT =
nullptr;
4283 if (functionTitle) {
4288 "Octree levels %i - %i\nCells: %i\nAverage population: "
4289 "%3.2f (+/-%3.2f)\nMax population: %llu",
4291 static_cast<int>(cells.size()), mean,
stddev, maxPop);
4294 if (s_normProgressCb_MT) {
4295 delete s_normProgressCb_MT;
4298 progressCb,
static_cast<unsigned>(cells.size()));
4300 progressCb->
start();
4303 #ifdef COMPUTE_NN_SEARCH_STATISTICS
4304 s_skippedPoints = 0;
4307 s_binarySearchCount = 0.0;
4310 if (maxThreadCount == 0) {
4311 maxThreadCount = QThread::idealThreadCount();
4313 QThreadPool::globalInstance()->setMaxThreadCount(maxThreadCount);
4314 QtConcurrent::blockingMap(cells, LaunchOctreeCellFunc_MT);
4316 #ifdef COMPUTE_NN_SEARCH_STATISTICS
4317 FILE* fp = fopen(
"octree_log.txt",
"at");
4319 fprintf(fp,
"Function: %s\n",
4320 functionTitle ? functionTitle :
"unknown");
4321 fprintf(fp,
"Tested: %f (%3.1f %%)\n", s_testedPoints,
4322 100.0 * s_testedPoints /
4323 std::max(1.0, s_testedPoints + s_skippedPoints));
4324 fprintf(fp,
"skipped: %f (%3.1f %%)\n", s_skippedPoints,
4325 100.0 * s_skippedPoints /
4326 std::max(1.0, s_testedPoints + s_skippedPoints));
4327 fprintf(fp,
"Binary search count: %.0f\n", s_binarySearchCount);
4328 if (s_binarySearchCount > 0.0)
4329 fprintf(fp,
"Mean jumps: %f\n", s_jumps / s_binarySearchCount);
4335 s_octree_MT =
nullptr;
4336 s_func_MT =
nullptr;
4337 s_userParams_MT =
nullptr;
4341 if (s_normProgressCb_MT)
delete s_normProgressCb_MT;
4342 s_normProgressCb_MT =
nullptr;
4346 if (!s_cellFunc_MT_success) cells.resize(0);
4348 return static_cast<unsigned>(cells.size());
4355 double maxRadiusOrFov,
4358 std::vector<PointDescriptor>& output)
const {
4366 double maxSqRadius = 0;
4370 maxSqRadius = maxRadiusOrFov * maxRadiusOrFov;
4386 unsigned char level = 1;
4392 bool skipThisCell =
false;
4394 double smallestOrderDist = -1.0;
4404 for (cellsContainer::const_iterator it =
4407 CellCode truncatedCode = (it->theCode >> currentBitDec);
4410 if (truncatedCode != (currentCode >> currentBitDec)) {
4415 if ((it->theCode >> bitDec) == (currentCode >> bitDec)) {
4422 currentCode = it->theCode;
4425 while (level < maxLevel) {
4427 getCellPos(it->theCode, level, cellPos,
false);
4432 CCVector3 cellCenter((2 * cellPos.
x + 1) * halfCellSize,
4433 (2 * cellPos.
y + 1) * halfCellSize,
4434 (2 * cellPos.
z + 1) * halfCellSize);
4437 CCVector3(halfCellSize, halfCellSize, halfCellSize);
4440 double radialSqDist, sqDistToOrigin;
4444 double dx = sqrt(sqDistToOrigin);
4445 double dy = std::max<double>(
4446 0, sqrt(radialSqDist) -
SQRT_3 * halfCellSize);
4447 double fov_rad = atan2(dy, dx);
4449 skipThisCell = (fov_rad > maxRadiusOrFov);
4452 cellCenter - halfCell - margin,
4453 cellCenter + halfCell + margin)
4469 if (!skipThisCell) {
4474 double orderDist = -1.0;
4475 bool isElligible =
false;
4479 double fov_rad = atan2(sqrt(radialSqDist), sqrt(sqDist));
4480 isElligible = (fov_rad <= maxRadiusOrFov);
4481 orderDist = fov_rad;
4489 isElligible = (radialSqDist <= maxSqRadius);
4501 if (orderDist < 0) {
4505 orderDist = sqrt(radialSqDist * sqDist);
4509 if (output.empty()) {
4513 smallestOrderDist = orderDist;
4515 if (orderDist < smallestOrderDist) {
4517 P, it->theIndex, radialSqDist);
4518 smallestOrderDist = orderDist;
4527 output.emplace_back(P, it->theIndex, radialSqDist);
4534 }
catch (
const std::bad_alloc&) {
constexpr double SQRT_3
Square root of 3.
Tuple3Tpl< int > Tuple3i
Tuple of 3 int values.
Vector3Tpl< PointCoordinateType > CCVector3
Default 3D Vector.
float PointCoordinateType
Type of the coordinates of a (N-D) point.
cmdLineReadable * params[]
Type dot(const Vector3Tpl &v) const
Dot product.
The octree structure used throughout the library.
const int * getMaxFillIndexes(unsigned char level) const
static const CellCode INVALID_CELL_CODE
Invalid cell code.
static bool MultiThreadSupport()
unsigned CellCode
Type of the code of an octree cell.
void updateCellSizeTable()
void getNeighborCellsAround(const Tuple3i &cellPos, cellIndexesContainer &neighborCellsIndexes, int neighbourhoodLength, unsigned char level) const
static const int MAX_OCTREE_LENGTH
Max octree length at last level of subdivision (number of cells)
GenericIndexedCloudPersist * m_theAssociatedCloud
Associated cloud.
int m_fillIndexes[(MAX_OCTREE_LEVEL+1) *6]
unsigned char findBestLevelForAGivenCellNumber(unsigned indicativeNumberOfCells) const
std::vector< unsigned int > cellIndexesContainer
Octree cell indexes container.
void diff(const cellCodesContainer &codesA, const cellCodesContainer &codesB, cellCodesContainer &diffA, cellCodesContainer &diffB) const
void getCellPos(CellCode code, unsigned char level, Tuple3i &cellPos, bool isCodeTruncated) const
int genericBuild(GenericProgressCallback *progressCb=nullptr)
Generic method to build the octree structure.
unsigned findPointNeighbourhood(const CCVector3 *_queryPoint, ReferenceCloud *Yk, unsigned maxNumberOfNeighbors, unsigned char level, double &maxSquareDist, double maxSearchDist=0, int *finalNeighbourhoodSize=nullptr) const
Finds the nearest neighbours around a query point.
void getPointsInNeighbourCellsAround(NearestNeighboursSearchStruct &nNSS, int neighbourhoodLength, bool getOnlyPointsWithValidScalar=false) const
Gets point in the neighbourhing cells of a specific cell.
double findTheNearestNeighborStartingFromCell(NearestNeighboursSearchStruct &nNSS) const
static const int MAX_OCTREE_LEVEL
Max octree subdivision level.
bool getPointsInCellByCellIndex(ReferenceCloud *cloud, unsigned cellIndex, unsigned char level, bool clearOutputCloud=true) const
Returns the points lying in a specific cell.
unsigned findNearestNeighborsStartingFromCell(NearestNeighboursSearchStruct &nNSS, bool getOnlyPointsWithValidScalar=false) const
const int * getMinFillIndexes(unsigned char level) const
static PointCoordinateType ComputeMinDistanceToCellBorder(const CCVector3 &queryPoint, PointCoordinateType cs, const CCVector3 &cellCenter)
unsigned char findBestLevelForComparisonWithOctree(const DgmOctree *theOtherOctree) const
bool getCellIndexes(unsigned char level, cellIndexesContainer &vec) const
static int OCTREE_LENGTH(int level)
CCVector3 m_dimMax
Max coordinates of the octree bounding-box.
unsigned char findBestLevelForAGivenNeighbourhoodSizeExtraction(PointCoordinateType radius) const
bool getPointsInCell(CellCode cellCode, unsigned char level, ReferenceCloud *subset, bool isCodeTruncated=false, bool clearOutputCloud=true) const
Returns the points lying in a specific cell.
int findNeighborsInASphereStartingFromCell(NearestNeighboursSearchStruct &nNSS, double radius, bool sortValues=true) const
Advanced form of the nearest neighbours search algorithm (in a sphere)
std::size_t getPointsInBoxNeighbourhood(BoxNeighbourhood ¶ms) const
Returns the points falling inside a box.
bool(*)(const octreeCell &, void **, NormalizedProgress *) octreeCellFunc
virtual void clear()
Clears the octree.
void getTheCellPosWhichIncludesThePoint(const CCVector3 *thePoint, Tuple3i &cellPos) const
static CellCode GenerateTruncatedCellCode(const Tuple3i &cellPos, unsigned char level)
unsigned getNumberOfProjectedPoints() const
Returns the number of points projected into the octree.
PointCoordinateType m_cellSize[MAX_OCTREE_LEVEL+2]
Cell dimensions for all subdivision levels.
const PointCoordinateType & getCellSize(unsigned char level) const
Returns the octree cells length for a given level of subdivision.
std::vector< CellCode > cellCodesContainer
Octree cell codes container.
int getPointsInSphericalNeighbourhood(const CCVector3 &sphereCenter, PointCoordinateType radius, NeighboursSet &neighbours, unsigned char level) const
Returns the points falling inside a sphere.
unsigned m_numberOfProjectedPoints
Number of points projected in the octree.
int extractCCs(const cellCodesContainer &cellCodes, unsigned char level, bool sixConnexity, GenericProgressCallback *progressCb=nullptr) const
void computeCellCenter(CellCode code, unsigned char level, CCVector3 ¢er, bool isCodeTruncated=false) const
DgmOctree(GenericIndexedCloudPersist *cloud)
DgmOctree constructor.
double m_averageCellPopulation[MAX_OCTREE_LEVEL+1]
Average cell population per level of subdivision.
unsigned executeFunctionForAllCellsAtLevel(unsigned char level, octreeCellFunc func, void **additionalParameters, bool multiThread=false, GenericProgressCallback *progressCb=nullptr, const char *functionTitle=nullptr, int maxThreadCount=0)
unsigned m_cellCount[MAX_OCTREE_LEVEL+1]
Number of cells per level of subdivision.
unsigned getCellIndex(CellCode truncatedCellCode, unsigned char bitDec) const
Returns the index of a given cell represented by its code.
void computeCellLimits(CellCode code, unsigned char level, CCVector3 &cellMin, CCVector3 &cellMax, bool isCodeTruncated=false) const
Returns the spatial limits of a given cell.
RayCastProcess
Ray casting processes.
int build(GenericProgressCallback *progressCb=nullptr)
Builds the structure.
void updateCellCountTable()
void getBoundingBox(CCVector3 &bbMin, CCVector3 &bbMax) const
Returns the octree bounding box.
std::vector< IndexAndCode > cellsContainer
Container of 'IndexAndCode' structures.
CCVector3 m_dimMin
Min coordinates of the octree bounding-box.
void updateMinAndMaxTables()
Updates the tables containing octree limits and boundaries.
ReferenceCloud * getPointsInCellsWithSortedCellCodes(cellCodesContainer &cellCodes, unsigned char level, ReferenceCloud *subset, bool areCodesTruncated=false) const
Returns the points lying in multiple cells.
unsigned m_maxCellPopulation[MAX_OCTREE_LEVEL+1]
Max cell population per level of subdivision.
const cellsContainer & pointsAndTheirCellCodes() const
Returns the octree 'structure'.
bool getCellCodes(unsigned char level, cellCodesContainer &vec, bool truncatedCodes=false) const
double m_stdDevCellPopulation[MAX_OCTREE_LEVEL+1]
Std. dev. of cell population per level of subdivision.
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)
bool rayCast(const CCVector3 &rayAxis, const CCVector3 &rayOrigin, double maxRadiusOrFov, bool isFOV, RayCastProcess process, std::vector< PointDescriptor > &output) const
Ray casting algorithm.
cellsContainer m_thePointsAndTheirCellCodes
The coded octree structure.
const unsigned & getCellNumber(unsigned char level) const
Returns the number of cells for a given level of subdivision.
static unsigned char GET_BIT_SHIFT(unsigned char level)
Returns the binary shift for a given level of subdivision.
std::vector< PointDescriptor > NeighboursSet
A set of neighbours.
double computeMeanOctreeDensity(unsigned char level) const
std::size_t getPointsInCylindricalNeighbourhoodProgressive(ProgressiveCylindricalNeighbourhood ¶ms) const
Same as getPointsInCylindricalNeighbourhood with progressive approach.
std::size_t getPointsInCylindricalNeighbourhood(CylindricalNeighbourhood ¶ms) const
Returns the points falling inside a cylinder.
unsigned char findBestLevelForAGivenPopulationPerCell(unsigned indicativeNumberOfPointsPerCell) const
bool getCellCodesAndIndexes(unsigned char level, cellsContainer &vec, bool truncatedCodes=false) const
void getCellDistanceFromBorders(const Tuple3i &cellPos, unsigned char level, int *cellDists) const
void computeCellsStatistics(unsigned char level)
Computes statistics about cells for a given level of subdivision.
virtual void getBoundingBox(CCVector3 &bbMin, CCVector3 &bbMax)=0
Returns the cloud bounding box.
virtual bool enableScalarField()=0
Enables the scalar field associated to the cloud.
virtual unsigned size() const =0
Returns the number of points.
virtual ScalarType getPointScalarValue(unsigned pointIndex) const =0
Returns the ith point associated scalar value.
virtual void setPointScalarValue(unsigned pointIndex, ScalarType value)=0
Sets the ith point associated scalar value.
A generic 3D point cloud with index-based and presistent access to points.
virtual const CCVector3 * getPointPersistentPtr(unsigned index)=0
Returns the ith point as a persistent pointer.
virtual const CCVector3 * getPoint(unsigned index) const =0
Returns the ith point.
virtual void stop()=0
Notifies the fact that the process has ended.
virtual void setInfo(const char *infoStr)=0
Notifies some information about the ongoing process.
virtual void setMethodTitle(const char *methodTitle)=0
Notifies the algorithm title.
virtual bool textCanBeEdited() const
Returns whether the dialog title and info can be updated or not.
virtual void update(float percent)=0
Notifies the algorithm progress.
virtual bool isCancelRequested()=0
Checks if the process should be canceled.
bool oneStep()
Increments total progress value of a single unit.
A very simple point cloud (no point duplication)
virtual bool addPointIndex(unsigned globalIndex)
Point global index insertion mechanism.
void placeIteratorAtBeginning() override
Sets the cloud iterator at the beginning.
virtual GenericIndexedCloudPersist * getAssociatedCloud()
Returns the associated (source) cloud.
unsigned size() const override
Returns the number of points.
virtual void clear(bool releaseMemory=false)
Clears the cloud.
virtual void setCurrentPointScalarValue(ScalarType value)
Sets the current point associated scalar value.
virtual bool reserve(unsigned n)
Reserves some memory for hosting the point references.
virtual void forwardIterator()
Forwards the local element iterator.
static bool ValidValue(ScalarType value)
Returns whether a scalar value is valid or not.
static DgmOctree::CellCode GenerateCellCodeForDim(int pos)
static const double LOG_NAT_2
Const value: ln(2)
static BitShiftValues PRE_COMPUTED_BIT_SHIFT_VALUES
static MonoDimensionalCellCodes PRE_COMPUTED_POS_CODES
__host__ __device__ float dot(float2 a, float2 b)
__host__ __device__ int2 abs(int2 v)
MiniVec< float, N > ceil(const MiniVec< float, N > &a)
Generic file read and write utility for python interface.
constexpr Rgbaf middle(0.50f, 0.50f, 0.50f, 1.00f)
void swap(cloudViewer::core::SmallVectorImpl< T > &LHS, cloudViewer::core::SmallVectorImpl< T > &RHS)
Implement std::swap in terms of SmallVector swap.
double stddev(std::vector< double > const &func)
Simple axis aligned box structure.
bool intersects(const Ray< T > &r, T *t0=0, T *t1=0) const
Pre-computed bit shift values (one for each level)
unsigned char values[DgmOctree::MAX_OCTREE_LEVEL+1]
Values.
BitShiftValues()
Default initialization.
IndexAndCodeExt()
Default constructor.
DgmOctree::CellCode theCode
cell code
static bool indexComp(const IndexAndCodeExt &a, const IndexAndCodeExt &b)
Compares two IndexAndCodeExt instances based on their index.
static const int VALUE_COUNT
Total number of positions/values.
cloudViewer::DgmOctree::CellCode values[VALUE_COUNT]
Mono-dimensional cell codes.
MonoDimensionalCellCodes()
Default initialization.
double squareDistanceToOrigin(const Vector3Tpl< T > &P) const
double radialSquareDistance(const Vector3Tpl< T > &P) const
void squareDistances(const Vector3Tpl< T > &P, double &radial, double &toOrigin) const
Input/output parameters structure for getPointsInBoxNeighbourhood.
Structure used during nearest neighbour search.
static bool codeComp(const IndexAndCode &a, const IndexAndCode &b)
Compares two IndexAndCode instances based on their code.
Structure used during nearest neighbour search.
const CCVector3 * point
Point.
double squareDistd
Point associated distance value.
static bool distComp(const PointDescriptor &a, const PointDescriptor &b)
Comparison operator.
virtual ~octreeCell()
Default destructor.
octreeCell(const DgmOctree *parentOctree)
Default constructor.
ReferenceCloud * points
Set of points lying inside this cell.
unsigned index
Cell index in octree structure (see m_thePointsAndTheirCellCodes)
const DgmOctree * parentOctree
Octree to which the cell belongs.
unsigned char level
Cell level of subdivision.
CellCode truncatedCode
Truncated cell code.