27 #ifdef CV_CORE_LIB_USES_QT_CONCURRENT
30 #define ENABLE_CLOUD2MESH_DIST_MT
32 #include <QtConcurrentMap>
47 inline bool push(
unsigned index) {
50 }
catch (
const std::bad_alloc&) {
90 if (*data)
delete (*data);
105 #ifdef ENABLE_CLOUD2MESH_DIST_MT
119 assert(comparedCloud && referenceCloud);
125 return DISTANCE_COMPUTATION_RESULTS::
126 ERROR_CANT_USE_MAX_SEARCH_DIST_AND_CLOSEST_POINT_SET;
130 DgmOctree *comparedOctree = compOctree, *referenceOctree = refOctree;
132 comparedOctree, referenceOctree,
133 params.maxSearchDist, progressCb);
137 return DISTANCE_COMPUTATION_RESULTS::ERROR_SYNCHRONIZE_OCTREES_FAILURE;
144 return DISTANCE_COMPUTATION_RESULTS::ERROR_OUT_OF_MEMORY;
149 double maxSearchSquareDistd =
152 :
static_cast<double>(
params.maxSearchDist) *
157 assert(maxSearchSquareDistd <= 0);
159 if (!
params.CPSet->resize(comparedCloud->
size())) {
161 if (comparedOctree && !compOctree)
delete comparedOctree;
162 if (referenceOctree && !refOctree)
delete referenceOctree;
163 return DISTANCE_COMPUTATION_RESULTS::ERROR_OUT_OF_MEMORY;
168 const ScalarType resetValue =
170 if (
params.resetFormerDistances) {
171 for (
unsigned i = 0; i < comparedCloud->
size(); ++i) {
178 if (maxSearchSquareDistd > 0 && soCode ==
DISJOINT) {
180 return DISTANCE_COMPUTATION_RESULTS::SUCCESS;
185 if (
params.octreeLevel == 0 &&
195 bool computeSplitDistances =
false;
197 for (
int i = 0; i < 3; ++i) {
198 if (
params.splitDistances[i] &&
199 params.splitDistances[i]->currentSize() ==
200 comparedCloud->
size()) {
201 computeSplitDistances =
true;
208 void* additionalParameters[] = {
209 reinterpret_cast<void*
>(referenceCloud),
210 reinterpret_cast<void*
>(referenceOctree),
211 reinterpret_cast<void*
>(&
params),
212 reinterpret_cast<void*
>(&maxSearchSquareDistd),
213 reinterpret_cast<void*
>(&computeSplitDistances)};
215 int result = DISTANCE_COMPUTATION_RESULTS::SUCCESS;
222 additionalParameters,
params.multiThread, progressCb,
223 "Cloud-Cloud Distance",
params.maxThreadCount) == 0) {
225 result = DISTANCE_COMPUTATION_RESULTS::
226 ERROR_EXECUTE_FUNCTION_FOR_ALL_CELLS_AT_LEVEL_FAILURE;
229 if (comparedOctree && !compOctree) {
230 delete comparedOctree;
231 comparedOctree =
nullptr;
233 if (referenceOctree && !refOctree) {
234 delete referenceOctree;
235 referenceOctree =
nullptr;
249 assert(comparedCloud && referenceCloud);
251 unsigned nA = comparedCloud->
size();
252 unsigned nB = referenceCloud->
size();
264 for (
unsigned char k = 0; k < 3; k++) {
273 for (
unsigned char k = 0; k < 3; k++) {
278 if (minD.
u[k] > maxD.
u[k]) {
291 bool needToRecalculateOctreeA =
true;
293 needToRecalculateOctreeA =
false;
294 for (
unsigned char k = 0; k < 3; k++) {
297 needToRecalculateOctreeA =
true;
303 bool octreeACreated =
false;
304 if (needToRecalculateOctreeA) {
305 if (comparedOctree) {
306 comparedOctree->
clear();
308 comparedOctree =
new DgmOctree(comparedCloud);
309 octreeACreated =
true;
312 if (comparedOctree->
build(minD, maxD, &minPoints, &maxPoints,
314 if (octreeACreated) {
315 delete comparedOctree;
316 comparedOctree =
nullptr;
323 bool needToRecalculateOctreeB =
true;
325 needToRecalculateOctreeB =
false;
326 for (
unsigned char k = 0; k < 3; k++) {
329 needToRecalculateOctreeB =
true;
335 if (needToRecalculateOctreeB) {
336 bool octreeBCreated =
false;
337 if (referenceOctree) {
338 referenceOctree->
clear();
340 referenceOctree =
new DgmOctree(referenceCloud);
341 octreeBCreated =
true;
344 if (referenceOctree->
build(minD, maxD, &minPoints, &maxPoints,
346 if (octreeACreated) {
347 delete comparedOctree;
348 comparedOctree =
nullptr;
350 if (octreeBCreated) {
351 delete referenceOctree;
352 referenceOctree =
nullptr;
359 assert(comparedOctree && referenceOctree);
372 void** additionalParameters,
377 additionalParameters[0]);
379 reinterpret_cast<DgmOctree*
>(additionalParameters[1]);
382 additionalParameters[2]);
383 const double* maxSearchSquareDistd =
384 reinterpret_cast<double*
>(additionalParameters[3]);
385 bool computeSplitDistances =
386 *
reinterpret_cast<bool*
>(additionalParameters[4]);
406 for (
unsigned i = 0; i < pointCount; i++) {
418 if (squareDist >= 0) {
419 ScalarType
dist =
static_cast<ScalarType
>(sqrt(squareDist));
423 params->CPSet->setPointIndex(
428 if (computeSplitDistances) {
433 if (
params->splitDistances[0])
434 params->splitDistances[0]->setValue(
435 index,
static_cast<ScalarType
>(
437 if (
params->splitDistances[1])
438 params->splitDistances[1]->setValue(
439 index,
static_cast<ScalarType
>(
441 if (
params->splitDistances[2])
442 params->splitDistances[2]->setValue(
443 index,
static_cast<ScalarType
>(
468 void** additionalParameters,
473 additionalParameters[0]);
475 reinterpret_cast<DgmOctree*
>(additionalParameters[1]);
478 additionalParameters[2]);
479 const double* maxSearchSquareDistd =
480 reinterpret_cast<double*
>(additionalParameters[3]);
481 bool computeSplitDistances =
482 *
reinterpret_cast<bool*
>(additionalParameters[4]);
505 if (
params->useSphericalSearchForLocalModel) {
514 std::vector<const LocalModel*> models;
519 for (
unsigned i = 0; i < pointCount; ++i) {
532 double squareDistToNearestPoint =
537 if (squareDistToNearestPoint >= 0) {
538 ScalarType distToNearestPoint =
539 static_cast<ScalarType
>(sqrt(squareDistToNearestPoint));
548 if (
params->reuseExistingLocalModels) {
550 for (std::vector<const LocalModel*>::const_iterator it =
552 it != models.end(); ++it) {
555 if (((*it)->getCenter() - nearestPoint).norm2() <=
556 (*it)->getSquareSize()) {
570 bool inbounds =
false;
573 &nearestPoint, cellPos, cell.
level, inbounds);
593 if (
params->useSphericalSearchForLocalModel) {
599 kNN = referenceOctree
603 params->radiusForLocalModel),
604 params->reuseExistingLocalModels);
606 kNN = referenceOctree
620 const double& maxSquareDist =
628 params->localModel, Z, nearestPoint,
631 if (lm &&
params->reuseExistingLocalModels) {
635 models.push_back(lm);
636 }
catch (
const std::bad_alloc&) {
638 while (!models.empty()) {
639 delete models.back();
653 ScalarType distToModel =
656 computeSplitDistances ? &nearestModelPoint
663 if (distToNearestPoint <= distToModel) {
664 distPt = distToNearestPoint;
666 distPt = distToModel;
667 nearestPoint = nearestModelPoint;
670 if (!
params->reuseExistingLocalModels) {
676 if (computeSplitDistances) {
678 if (
params->splitDistances[0])
679 params->splitDistances[0]->setValue(
683 if (
params->splitDistances[1])
684 params->splitDistances[1]->setValue(
688 if (
params->splitDistances[2])
689 params->splitDistances[2]->setValue(
695 distPt = distToNearestPoint;
698 distPt =
static_cast<ScalarType
>(
703 params->CPSet->setPointIndex(
717 while (!models.empty()) {
718 delete models.back();
747 return DISTANCE_COMPUTATION_RESULTS::
748 ERROR_INVALID_OCTREE_AND_MESH_INTERSECTION;
755 return DISTANCE_COMPUTATION_RESULTS::
756 ERROR_INVALID_OCTREE_AND_MESH_INTERSECTION;
761 CCVector3 halfCellDimensions(cellLength / 2, cellLength / 2,
764 std::vector<CellToTest> cellsToTest(1);
765 unsigned cellsToTestCount = 0;
770 unsigned numberOfTriangles = mesh->
size();
777 sprintf(buffer,
"Triangles: %u", numberOfTriangles);
788 for (
unsigned n = 0; n < numberOfTriangles; ++n) {
793 CCVector3 AB = (*triPoints[1]) - (*triPoints[0]);
794 CCVector3 BC = (*triPoints[2]) - (*triPoints[1]);
795 CCVector3 CA = (*triPoints[0]) - (*triPoints[2]);
810 for (
int k = 0; k < 3; k++) {
813 std::min(cellPos[1].u[k], cellPos[2].u[k]));
816 std::max(cellPos[1].u[k], cellPos[2].u[k]));
820 assert(cellsToTest.capacity() != 0);
821 cellsToTestCount = 1;
824 _currentCell->
pos = minPos;
825 CCVector3 distanceToOctreeMinBorder = minBB - (*triPoints[0]);
842 static const double LOG_2 = log(2.0);
843 _currentCell->
level =
845 (maxSize > 1 ?
static_cast<unsigned char>(
ceil(
846 log(
static_cast<double>(maxSize)) /
852 while (cellsToTestCount != 0) {
853 _currentCell = &cellsToTest[--cellsToTestCount];
867 if ((currentCellPos.
x >=
879 Tuple3i cellPos = currentCellPos -
906 int halfCellSize = (_currentCell->
cellSize >> 1);
910 char pointsPosition[27];
912 char* _pointsPosition = pointsPosition;
913 for (
int i = 0; i < 3; ++i) {
914 AB.
x = distanceToOctreeMinBorder.
x +
919 for (
int j = 0; j < 3; ++j) {
920 AB.
y = distanceToOctreeMinBorder.
y +
925 for (
int k = 0; k < 3; ++k) {
926 AB.
z = distanceToOctreeMinBorder.
z +
934 = (AB.
dot(N) < 0 ? -1 : 1);
941 if (cellsToTestCount + 27 > cellsToTest.capacity()) {
944 std::max(cellsToTest.capacity() + 27,
945 2 * cellsToTest.capacity()));
946 }
catch (
const std::bad_alloc&) {
948 return DISTANCE_COMPUTATION_RESULTS::
954 CellToTest* _newCell = &cellsToTest[cellsToTestCount];
960 for (
int i = 0; i < 2; ++i) {
961 _newCell->
pos.
x = currentCellPos.
x + i * halfCellSize;
964 if (
static_cast<int>(_newCell->
pos.
x) + halfCellSize >=
966 static_cast<int>(_newCell->
pos.
x) <= maxPos.
x) {
967 for (
int j = 0; j < 2; ++j) {
969 currentCellPos.
y + j * halfCellSize;
970 if (
static_cast<int>(_newCell->
pos.
y) +
973 static_cast<int>(_newCell->
pos.
y) <=
975 for (
int k = 0; k < 2; ++k) {
976 _newCell->
pos.
z = currentCellPos.
z +
978 if (
static_cast<int>(_newCell->
pos.
z) +
981 static_cast<int>(_newCell->
pos.
z) <=
983 const char* _pointsPosition =
986 char sum = _pointsPosition[0] +
991 _pointsPosition[10] +
992 _pointsPosition[12] +
1003 [++cellsToTestCount] =
1032 unsigned& remainingPoints,
1034 std::vector<unsigned>& trianglesToTest,
1035 std::size_t& trianglesToTestCount,
1036 std::vector<ScalarType>& minDists,
1037 ScalarType maxRadius,
1039 Cloud2MeshDistancesComputationParams&
params) {
1041 assert(remainingPoints <= Yk.
size());
1042 assert(trianglesToTestCount <= trianglesToTest.size());
1044 bool firstComparisonDone = (trianglesToTestCount != 0);
1050 while (trianglesToTestCount != 0) {
1054 tri.
A, tri.
B, tri.
C);
1057 if (
params.signedDistances) {
1059 for (
unsigned j = 0; j < remainingPoints; ++j) {
1063 Yk.
getPoint(j), &tri,
true, _nearestPoint);
1067 min_d * min_d > dPTri * dPTri) {
1069 params.flipNormals ? -dPTri : dPTri);
1072 assert(_nearestPoint);
1080 for (
unsigned j = 0; j < remainingPoints; ++j) {
1084 Yk.
getPoint(j), &tri,
false, _nearestPoint);
1091 assert(_nearestPoint);
1102 if (firstComparisonDone) {
1104 for (
unsigned j = 0; j < remainingPoints; ++j) {
1106 ScalarType eligibleDist = minDists[j] + maxRadius;
1108 if (
params.signedDistances) {
1112 if (dPTri <= eligibleDist * eligibleDist) {
1117 assert(remainingPoints != 0);
1118 minDists[j] = minDists[--remainingPoints];
1132 return static_cast<int>(
1133 ceil(maxSearchDist / cellSize +
1134 static_cast<ScalarType
>((sqrt(2.0) - 1.0) / 2)));
1137 #ifdef ENABLE_CLOUD2MESH_DIST_MT
1140 static DgmOctree* s_octree_MT =
nullptr;
1143 static bool s_cellFunc_MT_success =
true;
1144 static cloudViewer::DistanceComputationTools::
1145 Cloud2MeshDistancesComputationParams s_params_MT;
1148 static std::vector<std::vector<bool>*> s_bitArrayPool_MT;
1149 static bool s_useBitArrays_MT =
true;
1150 static QMutex s_currentBitMaskMutex;
1153 if (!s_cellFunc_MT_success) {
1158 if (s_normProgressCb_MT && !s_normProgressCb_MT->
oneStep()) {
1159 s_cellFunc_MT_success =
false;
1168 unsigned remainingPoints = Yk.size();
1170 std::vector<ScalarType> minDists;
1172 minDists.resize(remainingPoints);
1173 }
catch (
const std::bad_alloc&) {
1175 s_cellFunc_MT_success =
false;
1185 Tuple3i signedDistToLowerBorder, signedDistToUpperBorder;
1186 signedDistToLowerBorder = startPos - s_intersection_MT->
minFillIndexes;
1187 signedDistToUpperBorder = s_intersection_MT->
maxFillIndexes - startPos;
1189 Tuple3i minDistToGridBoundaries, maxDistToGridBoundaries;
1190 for (
unsigned k = 0; k < 3; ++k) {
1191 minDistToGridBoundaries.
u[k] =
1193 std::max(0, -signedDistToUpperBorder.
u[k]));
1194 maxDistToGridBoundaries.
u[k] =
1196 std::max(0, signedDistToUpperBorder.
u[k]));
1198 int minDistToBoundaries =
std::max(
1199 minDistToGridBoundaries.
x,
1200 std::max(minDistToGridBoundaries.
y, minDistToGridBoundaries.
z));
1201 int maxDistToBoundaries =
std::max(
1202 maxDistToGridBoundaries.
x,
1203 std::max(maxDistToGridBoundaries.
y, maxDistToGridBoundaries.
z));
1204 int maxIntDist = maxDistToBoundaries;
1211 if (maxNeighbourhoodLength < maxIntDist)
1212 maxIntDist = maxNeighbourhoodLength;
1220 for (
unsigned j = 0; j < remainingPoints; ++j)
1221 Yk.setPointScalarValue(j, maxDistance);
1237 std::vector<unsigned> trianglesToTest;
1238 std::size_t trianglesToTestCount = 0;
1239 std::size_t trianglesToTestCapacity = 0;
1242 std::vector<bool>* bitArray =
nullptr;
1243 if (s_useBitArrays_MT) {
1244 const unsigned numTri = s_intersection_MT->
mesh->
size();
1245 s_currentBitMaskMutex.lock();
1246 if (s_bitArrayPool_MT.empty()) {
1247 bitArray =
new std::vector<bool>(numTri);
1249 bitArray = s_bitArrayPool_MT.back();
1250 s_bitArrayPool_MT.pop_back();
1252 s_currentBitMaskMutex.unlock();
1253 bitArray->assign(numTri,
false);
1258 Yk.placeIteratorAtBeginning();
1259 for (
unsigned j = 0; j < remainingPoints; ++j) {
1261 const CCVector3* tempPt = Yk.getCurrentPointCoordinates();
1265 *tempPt, cellLength, cellCenter);
1266 Yk.forwardIterator();
1270 ScalarType maxRadius = 0;
1271 for (
int dist = minDistToBoundaries;
1272 remainingPoints != 0 &&
dist <= maxIntDist;
1273 ++
dist, maxRadius +=
static_cast<ScalarType
>(cellLength)) {
1284 for (
int i = -a; i <= b; ++i) {
1286 Tuple3i cellPos(startPos.
x + i, 0, 0);
1288 for (
int j = -c; j <= d; j++) {
1289 cellPos.y = startPos.
y + j;
1294 for (
int k = -e; k <= f; k++) {
1296 cellPos.z = startPos.
z + k;
1301 if (trianglesToTestCount + triList->
indexes.size() >
1302 trianglesToTestCapacity) {
1303 trianglesToTestCapacity =
std::max(
1304 trianglesToTestCount +
1306 2 * trianglesToTestCount);
1307 trianglesToTest.resize(trianglesToTestCapacity);
1311 for (
unsigned p = 0; p < triList->
indexes.size();
1314 const unsigned indexTri =
1318 if (!(*bitArray)[indexTri]) {
1320 [trianglesToTestCount++] =
1322 (*bitArray)[indexTri] =
true;
1325 trianglesToTest[trianglesToTestCount++] =
1336 cellPos.z = startPos.
z - e;
1341 if (trianglesToTestCount + triList->
indexes.size() >
1342 trianglesToTestCapacity) {
1343 trianglesToTestCapacity =
std::max(
1344 trianglesToTestCount +
1346 2 * trianglesToTestCount);
1347 trianglesToTest.resize(trianglesToTestCapacity);
1351 for (
unsigned p = 0; p < triList->
indexes.size();
1354 const unsigned& indexTri =
1358 if (!(*bitArray)[indexTri]) {
1360 [trianglesToTestCount++] =
1362 (*bitArray)[indexTri] =
true;
1365 trianglesToTest[trianglesToTestCount++] =
1375 cellPos.z = startPos.
z + f;
1380 if (trianglesToTestCount + triList->
indexes.size() >
1381 trianglesToTestCapacity) {
1382 trianglesToTestCapacity =
std::max(
1383 trianglesToTestCount +
1385 2 * trianglesToTestCount);
1386 trianglesToTest.resize(trianglesToTestCapacity);
1390 for (
unsigned p = 0; p < triList->
indexes.size();
1393 const unsigned& indexTri =
1397 if (!(*bitArray)[indexTri]) {
1399 [trianglesToTestCount++] =
1401 (*bitArray)[indexTri] =
true;
1404 trianglesToTest[trianglesToTestCount++] =
1415 trianglesToTest, trianglesToTestCount,
1416 minDists, maxRadius, s_params_MT);
1421 s_currentBitMaskMutex.lock();
1422 s_bitArrayPool_MT.push_back(bitArray);
1423 s_currentBitMaskMutex.unlock();
1433 assert(intersection);
1434 assert(!
params.signedDistances ||
1438 assert(!
params.multiThread ||
1439 params.maxSearchDist <= 0);
1446 return DISTANCE_COMPUTATION_RESULTS::ERROR_NULL_OCTREE;
1451 assert(
params.maxSearchDist <= 0);
1452 assert(
params.useDistanceMap ==
false);
1457 return DISTANCE_COMPUTATION_RESULTS::ERROR_OUT_OF_MEMORY;
1461 #ifdef ENABLE_CLOUD2MESH_DIST_MT
1474 cellCodesAndIndexes,
true)) {
1476 return DISTANCE_COMPUTATION_RESULTS::
1477 ERROR_GET_CELL_CODES_AND_INDEXES_FAILURE;
1480 unsigned numberOfCells =
1481 static_cast<unsigned>(cellCodesAndIndexes.size());
1482 bool boundedSearch = (
params.maxSearchDist > 0);
1484 DgmOctree::cellsContainer::const_iterator pCodeAndIndex =
1485 cellCodesAndIndexes.begin();
1491 for (
unsigned i = 0; i < numberOfCells; ++i, ++pCodeAndIndex) {
1502 unsigned squareDist =
1506 ScalarType maxRadius =
1507 sqrt(
static_cast<ScalarType
>(squareDist)) * cellLength;
1509 if (boundedSearch && maxRadius >
params.maxSearchDist) {
1510 maxRadius =
params.maxSearchDist;
1514 for (
unsigned j = 0; j <
count; ++j) {
1521 return DISTANCE_COMPUTATION_RESULTS::SUCCESS;
1532 sprintf(buffer,
"Cells: %u", numberOfCells);
1535 ?
"Compute signed distances"
1536 :
"Compute distances");
1539 progressCb->
start();
1543 std::vector<unsigned> trianglesToTest;
1544 std::size_t trianglesToTestCount = 0;
1545 std::size_t trianglesToTestCapacity = 0;
1546 unsigned numberOfTriangles = mesh->
size();
1549 std::vector<unsigned> processTriangles;
1551 processTriangles.resize(numberOfTriangles, 0);
1552 }
catch (
const std::bad_alloc&) {
1557 std::vector<ScalarType> minDists;
1560 int maxNeighbourhoodLength = 0;
1561 if (boundedSearch) {
1563 params.maxSearchDist, cellLength);
1567 for (
unsigned cellIndex = 1; cellIndex <= numberOfCells;
1568 ++cellIndex, ++pCodeAndIndex)
1580 Tuple3i signedDistToLowerBorder, signedDistToUpperBorder;
1581 signedDistToLowerBorder = startPos - intersection->
minFillIndexes;
1582 signedDistToUpperBorder = intersection->
maxFillIndexes - startPos;
1584 Tuple3i minDistToGridBoundaries, maxDistToGridBoundaries;
1585 for (
unsigned char k = 0; k < 3; ++k) {
1586 minDistToGridBoundaries.
u[k] =
1588 std::max(0, -signedDistToUpperBorder.
u[k]));
1589 maxDistToGridBoundaries.
u[k] =
1591 std::max(0, signedDistToUpperBorder.
u[k]));
1593 int minDistToBoundaries =
1596 minDistToGridBoundaries.
z));
1597 int maxDistToBoundaries =
1600 maxDistToGridBoundaries.
z));
1601 int maxIntDist = maxDistToBoundaries;
1611 unsigned remainingPoints = Yk.
size();
1612 if (minDists.size() < remainingPoints) {
1614 minDists.resize(remainingPoints);
1615 }
catch (
const std::bad_alloc&)
1618 return DISTANCE_COMPUTATION_RESULTS::ERROR_OUT_OF_MEMORY;
1624 for (
unsigned j = 0; j < remainingPoints; ++j) {
1626 minDists[j] =
static_cast<ScalarType
>(
1628 *tempPt, cellLength, cellCenter));
1631 if (boundedSearch) {
1633 if (maxNeighbourhoodLength < maxIntDist)
1634 maxIntDist = maxNeighbourhoodLength;
1637 ScalarType maxDistance =
params.maxSearchDist;
1638 if (!
params.signedDistances) {
1640 maxDistance =
params.maxSearchDist *
params.maxSearchDist;
1643 for (
unsigned j = 0; j < remainingPoints; ++j)
1649 ScalarType maxRadius = 0;
1650 for (
int dist = minDistToBoundaries;
1651 dist <= maxIntDist && remainingPoints != 0;
1652 ++
dist, maxRadius +=
static_cast<ScalarType
>(cellLength)) {
1663 for (
int i = -a; i <= b; i++) {
1665 Tuple3i cellPos(startPos.
x + i, 0, 0);
1667 for (
int j = -c; j <= d; j++) {
1668 cellPos.
y = startPos.
y + j;
1673 for (
int k = -e; k <= f; k++) {
1675 cellPos.
z = startPos.
z + k;
1680 if (trianglesToTestCount +
1682 trianglesToTestCapacity) {
1683 trianglesToTestCapacity =
std::max(
1684 trianglesToTestCount +
1686 2 * trianglesToTestCount);
1687 trianglesToTest.resize(
1688 trianglesToTestCapacity);
1692 for (std::size_t p = 0;
1693 p < triList->
indexes.size(); ++p) {
1694 if (!processTriangles.empty()) {
1699 if (processTriangles[indexTri] !=
1702 [trianglesToTestCount++] =
1704 processTriangles[indexTri] =
1709 [trianglesToTestCount++] =
1720 cellPos.
z = startPos.
z - e;
1725 if (trianglesToTestCount +
1727 trianglesToTestCapacity) {
1728 trianglesToTestCapacity =
std::max(
1729 trianglesToTestCount +
1731 2 * trianglesToTestCount);
1732 trianglesToTest.resize(
1733 trianglesToTestCapacity);
1737 for (std::size_t p = 0;
1738 p < triList->
indexes.size(); ++p) {
1739 if (!processTriangles.empty()) {
1740 const unsigned& indexTri =
1744 if (processTriangles[indexTri] !=
1747 [trianglesToTestCount++] =
1749 processTriangles[indexTri] =
1754 [trianglesToTestCount++] =
1764 cellPos.
z = startPos.
z + f;
1769 if (trianglesToTestCount +
1771 trianglesToTestCapacity) {
1772 trianglesToTestCapacity =
std::max(
1773 trianglesToTestCount +
1775 2 * trianglesToTestCount);
1776 trianglesToTest.resize(
1777 trianglesToTestCapacity);
1781 for (std::size_t p = 0;
1782 p < triList->
indexes.size(); ++p) {
1783 if (!processTriangles.empty()) {
1784 const unsigned& indexTri =
1788 if (processTriangles[indexTri] !=
1791 [trianglesToTestCount++] =
1793 processTriangles[indexTri] =
1798 [trianglesToTestCount++] =
1809 trianglesToTest, trianglesToTestCount,
1810 minDists, maxRadius,
params);
1821 return DISTANCE_COMPUTATION_RESULTS::SUCCESS;
1823 #ifdef ENABLE_CLOUD2MESH_DIST_MT
1829 unsigned numberOfCells =
static_cast<unsigned>(cellsDescs.size());
1836 sprintf(buffer,
"Cells: %u", numberOfCells);
1841 progressCb->
start();
1846 s_cellFunc_MT_success =
true;
1848 s_intersection_MT = intersection;
1850 s_useBitArrays_MT =
true;
1856 int maxThreadCount =
params.maxThreadCount;
1857 if (maxThreadCount == 0) {
1858 maxThreadCount = QThread::idealThreadCount();
1860 QThreadPool::globalInstance()->setMaxThreadCount(maxThreadCount);
1861 QtConcurrent::blockingMap(cellsDescs, cloudMeshDistCellFunc_MT);
1863 s_octree_MT =
nullptr;
1864 s_normProgressCb_MT =
nullptr;
1865 s_intersection_MT =
nullptr;
1868 while (!s_bitArrayPool_MT.empty()) {
1869 delete s_bitArrayPool_MT.back();
1870 s_bitArrayPool_MT.pop_back();
1873 return (s_cellFunc_MT_success ? 0 : -2);
1880 ScalarType& aScalarValue) {
1882 aScalarValue = sqrt(aScalarValue);
1888 : trianglesToTestCount(0),
1889 trianglesToTestCapacity(0),
1890 numberOfTriangles(0) {
1891 numberOfTriangles = mesh.
size();
1893 processTriangles.resize(numberOfTriangles, 0);
1894 }
catch (
const std::bad_alloc&) {
1918 int maxNeighbourhoodLength) {
1921 Tuple3i signedDistToLowerBorder = localCellPos;
1926 Tuple3i minDistToGridBoundaries, maxDistToGridBoundaries;
1927 for (
unsigned char k = 0; k < 3; ++k) {
1928 minDistToGridBoundaries.
u[k] =
1930 std::max(0, -signedDistToUpperBorder.
u[k]));
1931 maxDistToGridBoundaries.
u[k] =
1933 std::max(0, signedDistToUpperBorder.
u[k]));
1935 int minDistToBoundaries =
std::max(
1936 minDistToGridBoundaries.
x,
1937 std::max(minDistToGridBoundaries.
y, minDistToGridBoundaries.
z));
1938 int maxDistToBoundaries =
std::max(
1939 maxDistToGridBoundaries.
x,
1940 std::max(maxDistToGridBoundaries.
y, maxDistToGridBoundaries.
z));
1949 Tuple3i startPos = localCellPos;
1952 std::vector<ScalarType> minDists;
1953 unsigned remainingPoints = Yk.
size();
1956 minDists.resize(remainingPoints);
1957 }
catch (
const std::bad_alloc&)
1960 return DistanceComputationTools::DISTANCE_COMPUTATION_RESULTS::
1961 ERROR_OUT_OF_MEMORY;
1966 for (
unsigned j = 0; j < remainingPoints; ++j) {
1968 minDists[j] =
static_cast<ScalarType
>(
1973 if (boundedSearch) {
1975 if (maxNeighbourhoodLength < maxDistToBoundaries)
1976 maxDistToBoundaries = maxNeighbourhoodLength;
1979 ScalarType maxDistance =
params.maxSearchDist;
1980 if (!
params.signedDistances) {
1982 maxDistance =
params.maxSearchDist *
params.maxSearchDist;
1985 for (
unsigned j = 0; j < remainingPoints; ++j) {
1993 ScalarType maxRadius = 0;
1994 for (
int dist = minDistToBoundaries;
1995 dist <= maxDistToBoundaries && remainingPoints != 0;
1996 ++
dist, maxRadius +=
static_cast<ScalarType
>(cellSize)) {
2007 for (
int i = -a; i <= b; i++) {
2009 Tuple3i localCellPos(startPos.
x + i, 0, 0);
2010 if (localCellPos.
x < 0 ||
2011 static_cast<unsigned>(localCellPos.
x) >= gridSize.
x)
2014 for (
int j = -c; j <= d; j++) {
2015 localCellPos.
y = startPos.
y + j;
2016 if (localCellPos.
y < 0 ||
2017 static_cast<unsigned>(localCellPos.
y) >= gridSize.
y)
2023 for (
int k = -e; k <= f; k++) {
2025 localCellPos.
z = startPos.
z + k;
2026 if (localCellPos.
z < 0 ||
2027 static_cast<unsigned>(localCellPos.
z) >= gridSize.
z)
2045 for (
unsigned indexTri : triList->
indexes) {
2070 localCellPos.
z = startPos.
z - e;
2071 if (localCellPos.
z < 0 ||
2072 static_cast<unsigned>(localCellPos.
z) >= gridSize.
z)
2090 for (
unsigned triIndex : triList->
indexes) {
2114 localCellPos.
z = startPos.
z + f;
2115 if (localCellPos.
z < 0 ||
2116 static_cast<unsigned>(localCellPos.
z) >= gridSize.
z)
2134 for (
unsigned triIndex : triList->
indexes) {
2159 Yk, remainingPoints, intersection->
mesh,
2161 minDists, maxRadius,
params)) {
2162 return DistanceComputationTools::DISTANCE_COMPUTATION_RESULTS::
2163 ERROR_OUT_OF_MEMORY;
2167 return DistanceComputationTools::DISTANCE_COMPUTATION_RESULTS::SUCCESS;
2172 ScalarType& distance,
2177 if (!intersection) {
2178 return DistanceComputationTools::DISTANCE_COMPUTATION_RESULTS::
2179 ERROR_INVALID_OCTREE_AND_MESH_INTERSECTION;
2184 return DistanceComputationTools::DISTANCE_COMPUTATION_RESULTS::
2185 ERROR_INVALID_OCTREE_AND_MESH_INTERSECTION;
2192 return DistanceComputationTools::DISTANCE_COMPUTATION_RESULTS::
2193 ERROR_NULL_REFERENCEMESH;
2198 return DistanceComputationTools::DISTANCE_COMPUTATION_RESULTS::
2202 bool boundedSearch = (
params.maxSearchDist > 0);
2206 return DistanceComputationTools::DISTANCE_COMPUTATION_RESULTS::
2207 ERROR_OUT_OF_MEMORY;
2211 return DistanceComputationTools::DISTANCE_COMPUTATION_RESULTS::
2212 ERROR_OUT_OF_MEMORY;
2217 return DistanceComputationTools::DISTANCE_COMPUTATION_RESULTS::
2218 ERROR_OUT_OF_MEMORY;
2225 int maxNeighbourhoodLength = 0;
2226 if (boundedSearch) {
2229 maxNeighbourhoodLength =
2238 intersection,
params, Yk, 1, cellPos, ttt, boundedSearch,
2239 maxNeighbourhoodLength);
2242 DistanceComputationTools::DISTANCE_COMPUTATION_RESULTS::SUCCESS) {
2249 return DistanceComputationTools::DISTANCE_COMPUTATION_RESULTS::SUCCESS;
2257 assert(!
params.signedDistances ||
2265 return DISTANCE_COMPUTATION_RESULTS::ERROR_NULL_OCTREE;
2268 if (!intersection) {
2269 return DISTANCE_COMPUTATION_RESULTS::
2270 ERROR_INVALID_OCTREE_AND_MESH_INTERSECTION;
2276 return DISTANCE_COMPUTATION_RESULTS::
2277 ERROR_INVALID_OCTREE_AND_MESH_INTERSECTION;
2280 if (
params.multiThread &&
2283 return DISTANCE_COMPUTATION_RESULTS::
2284 ERROR_INVALID_OCTREE_AND_MESH_INTERSECTION;
2289 return DISTANCE_COMPUTATION_RESULTS::
2290 ERROR_OCTREE_AND_MESH_INTERSECTION_MISMATCH;
2295 assert(
params.maxSearchDist <= 0);
2296 assert(
params.useDistanceMap ==
false);
2301 return DISTANCE_COMPUTATION_RESULTS::ERROR_OUT_OF_MEMORY;
2305 if (!
params.CPSet->enableScalarField()) {
2307 return DISTANCE_COMPUTATION_RESULTS::ERROR_OUT_OF_MEMORY;
2309 assert(
params.CPSet->getCurrentInScalarField());
2310 params.CPSet->getCurrentInScalarField()->fill(0);
2313 #ifdef ENABLE_CLOUD2MESH_DIST_MT
2315 #ifdef CV_CORE_LIB_USES_QT_CONCURRENT
2316 if (
params.multiThread) {
2317 if (
params.maxThreadCount == 0) {
2319 params.maxThreadCount = QThread::idealThreadCount();
2321 if (
params.maxThreadCount == 1) {
2324 params.multiThread =
false;
2336 return DISTANCE_COMPUTATION_RESULTS::ERROR_NULL_REFERENCEMESH;
2345 cellCodesAndIndexes,
true)) {
2347 return DISTANCE_COMPUTATION_RESULTS::ERROR_OUT_OF_MEMORY;
2350 unsigned numberOfCells =
2351 static_cast<unsigned>(cellCodesAndIndexes.size());
2352 bool boundedSearch = (
params.maxSearchDist > 0);
2354 DgmOctree::cellsContainer::const_iterator pCodeAndIndex =
2355 cellCodesAndIndexes.begin();
2361 for (
unsigned i = 0; i < numberOfCells; ++i, ++pCodeAndIndex) {
2372 unsigned squareDist =
2376 ScalarType maxRadius =
2377 sqrt(
static_cast<ScalarType
>(squareDist)) * cellSize;
2379 if (boundedSearch && maxRadius >
params.maxSearchDist) {
2380 maxRadius =
params.maxSearchDist;
2384 for (
unsigned j = 0; j <
count; ++j) {
2391 return DISTANCE_COMPUTATION_RESULTS::SUCCESS;
2402 snprintf(buffer, 32,
"Cells: %u", numberOfCells);
2405 ?
"Compute signed distances"
2406 :
"Compute distances");
2409 progressCb->
start();
2415 std::vector<ScalarType> minDists;
2418 int maxNeighbourhoodLength = 0;
2419 if (boundedSearch) {
2421 params.maxSearchDist, cellSize);
2425 for (
unsigned cellIndex = 1; cellIndex <= numberOfCells;
2426 ++cellIndex, ++pCodeAndIndex)
2430 &Yk, pCodeAndIndex->theIndex,
params.octreeLevel)) {
2431 return DISTANCE_COMPUTATION_RESULTS::
2432 ERROR_EXECUTE_GET_POINTS_IN_CELL_BY_INDEX_FAILURE;
2441 intersection,
params, Yk, cellIndex, cellPos, ttt,
2442 boundedSearch, maxNeighbourhoodLength);
2444 if (
result != DISTANCE_COMPUTATION_RESULTS::SUCCESS) {
2451 #if defined(CV_CORE_LIB_USES_QT_CONCURRENT)
2452 QCoreApplication::processEvents(
2453 QEventLoop::EventLoopExec);
2458 return DISTANCE_COMPUTATION_RESULTS::CANCELED_BY_USER;
2462 return DISTANCE_COMPUTATION_RESULTS::SUCCESS;
2464 #ifdef ENABLE_CLOUD2MESH_DIST_MT
2470 return DISTANCE_COMPUTATION_RESULTS::
2471 ERROR_GET_CELL_CODES_AND_INDEXES_FAILURE;
2474 unsigned numberOfCells =
static_cast<unsigned>(cellsDescs.size());
2481 snprintf(buffer, 32,
"Cells: %u", numberOfCells);
2486 progressCb->
start();
2493 return DISTANCE_COMPUTATION_RESULTS::SUCCESS;
2508 return DISTANCE_COMPUTATION_RESULTS::ERROR_NULL_COMPAREDCLOUD;
2511 if (pointCloud->
size() == 0) {
2513 return DISTANCE_COMPUTATION_RESULTS::ERROR_EMPTY_COMPAREDCLOUD;
2518 return DISTANCE_COMPUTATION_RESULTS::ERROR_NULL_REFERENCEMESH;
2521 if (mesh->
size() == 0) {
2523 return DISTANCE_COMPUTATION_RESULTS::ERROR_EMPTY_REFERENCEMESH;
2526 if (
params.signedDistances) {
2529 params.useDistanceMap =
false;
2534 params.useDistanceMap =
false;
2535 params.maxSearchDist = 0;
2549 for (
unsigned char k = 0; k < 3; ++k) {
2550 minBB.
u[k] =
std::min(meshMinBB.
u[k], cloudMinBB.
u[k]);
2551 maxBB.
u[k] =
std::max(meshMaxBB.
u[k], cloudMaxBB.
u[k]);
2555 minCubifiedBB = minBB;
2556 maxCubifiedBB = maxBB;
2563 bool rebuildTheOctree =
false;
2566 rebuildTheOctree =
true;
2571 for (
unsigned char k = 0; k < 3; ++k) {
2572 if (theOctreeMins.
u[k] != minCubifiedBB.
u[k] ||
2573 theOctreeMaxs.
u[k] != maxCubifiedBB.
u[k]) {
2574 rebuildTheOctree =
true;
2580 if (rebuildTheOctree) {
2582 if (
octree->
build(minCubifiedBB, maxCubifiedBB, &cloudMinBB,
2583 &cloudMaxBB, progressCb) <= 0) {
2584 return DISTANCE_COMPUTATION_RESULTS::ERROR_BUILD_OCTREE_FAILURE;
2590 intersection.
mesh = mesh;
2595 (maxCubifiedBB.
x - minCubifiedBB.
x) / (1 <<
params.octreeLevel);
2599 for (
unsigned char k = 0; k < 3; ++k) {
2601 floor((minBB.
u[k] - minCubifiedBB.
u[k]) / cellSize));
2603 floor((maxBB.
u[k] - minCubifiedBB.
u[k]) / cellSize));
2612 if (
params.useDistanceMap) {
2616 return DISTANCE_COMPUTATION_RESULTS::
2617 ERROR_INIT_DISTANCE_TRANSFORM_GRID_FAILURE;
2619 params.multiThread =
false;
2624 gridSize.
z, 0, 0)) {
2625 return DISTANCE_COMPUTATION_RESULTS::
2626 ERROR_INIT_PER_CELL_TRIANGLE_LIST_FAILURE;
2652 if (
result == DISTANCE_COMPUTATION_RESULTS::SUCCESS &&
2661 return DISTANCE_COMPUTATION_RESULTS::SUCCESS;
2673 assert(P && theTriangle);
2688 double b0 = -AP.
dot(AB);
2689 double b1 = -AP.
dot(AC);
2691 double t0 =
a01 * b1 -
a11 * b0;
2692 double t1 =
a01 * b0 -
a00 * b1;
2694 if (t0 + t1 <= det) {
2712 }
else if (-b1 >=
a11)
2726 }
else if (-b1 >=
a11)
2740 }
else if (-b0 >=
a00)
2753 double tmp0, tmp1, numer, denom;
2760 numer = tmp1 - tmp0;
2789 numer = tmp1 - tmp0;
2815 numer =
a11 + b1 -
a01 - b0;
2843 double squareDist = (Q - AP).norm2();
2845 ScalarType d =
static_cast<ScalarType
>(sqrt(squareDist));
2852 return (AP.
dot(N) < 0 ? -d : d);
2854 return static_cast<ScalarType
>(squareDist);
2862 std::numeric_limits<PointCoordinateType>::epsilon());
2864 return static_cast<ScalarType
>((
2866 planeEquation[3]) );
2872 assert(p && start && end);
2886 CCVector3 pProjectedOnLine = *start + t * line;
2887 vec = *p - pProjectedOnLine;
2890 distSq = vec.
norm2();
2905 bool signedDistances ,
2909 return DISTANCE_COMPUTATION_RESULTS::ERROR_NULL_COMPAREDCLOUD;
2913 return DISTANCE_COMPUTATION_RESULTS::ERROR_EMPTY_COMPAREDCLOUD;
2916 return DISTANCE_COMPUTATION_RESULTS::ERROR_ENABLE_SCALAR_FIELD_FAILURE;
2918 if (coneR1 < coneR2) {
2919 return DISTANCE_COMPUTATION_RESULTS::ERROR_CONE_R1_LT_CONE_R2;
2921 double dSumSq = 0.0;
2924 double axisLength = coneAxis.
normd();
2926 double delta =
static_cast<double>(coneR2) - coneR1;
2927 double rr1 =
static_cast<double>(coneR1) * coneR1;
2928 double rr2 =
static_cast<double>(coneR2) * coneR2;
2929 double coneLength = sqrt((axisLength * axisLength) + (delta * delta));
2933 for (
unsigned i = 0; i <
count; ++i) {
2936 double x = n.
dot(coneAxis);
2938 double yy = (n.
norm2d()) - xx;
2949 if (!solutionType) {
2955 if (!solutionType) {
2956 y = sqrt(yy) - coneR1;
2957 d = sqrt((y * y) + xx);
2970 if (!solutionType) {
2978 if (!solutionType) {
2979 y = sqrt(yy) - coneR1;
2986 d =
std::min(d,
static_cast<double>(
2995 y = sqrt(yy) - coneR1;
3001 if (!solutionType) {
3002 d = sqrt(y * y + xx);
3010 if (rx > coneLength) {
3011 if (!solutionType) {
3013 d = sqrt(ry * ry + rx * rx);
3018 if (!solutionType) {
3037 if (signedDistances) {
3045 *rms = sqrt(dSumSq /
count);
3047 return DISTANCE_COMPUTATION_RESULTS::SUCCESS;
3066 bool signedDistances ,
3070 return DISTANCE_COMPUTATION_RESULTS::ERROR_NULL_COMPAREDCLOUD;
3074 return DISTANCE_COMPUTATION_RESULTS::ERROR_EMPTY_COMPAREDCLOUD;
3077 return DISTANCE_COMPUTATION_RESULTS::ERROR_ENABLE_SCALAR_FIELD_FAILURE;
3079 double dSumSq = 0.0;
3081 CCVector3 cylinderCenter = (cylinderP1 + cylinderP2) / 2.;
3083 CCVector3 cylinderAxis = cylinderP2 - cylinderP1;
3084 double h = cylinderAxis.
normd() / 2.;
3086 double cylinderRadius2 =
3087 static_cast<double>(cylinderRadius) * cylinderRadius;
3089 for (
unsigned i = 0; i <
count; ++i) {
3095 double yy = (n.
norm2d()) - xx;
3099 if (yy >= cylinderRadius2) {
3100 if (!solutionType) {
3108 if (!solutionType) {
3110 std::abs(sqrt(yy) - cylinderRadius),
3119 if (yy >= cylinderRadius2) {
3120 if (!solutionType) {
3123 ((y - cylinderRadius) * (y - cylinderRadius)) +
3124 ((x - h) * (x - h)));
3130 if (!solutionType) {
3139 if (signedDistances) {
3147 *rms = sqrt(dSumSq /
count);
3150 return DISTANCE_COMPUTATION_RESULTS::SUCCESS;
3157 bool signedDistances ,
3160 return DISTANCE_COMPUTATION_RESULTS::ERROR_NULL_COMPAREDCLOUD;
3164 return DISTANCE_COMPUTATION_RESULTS::ERROR_EMPTY_COMPAREDCLOUD;
3167 return DISTANCE_COMPUTATION_RESULTS::ERROR_ENABLE_SCALAR_FIELD_FAILURE;
3169 double dSumSq = 0.0;
3170 for (
unsigned i = 0; i <
count; ++i) {
3172 double d = (*P - sphereCenter).normd() - sphereRadius;
3173 if (signedDistances) {
3181 *rms = sqrt(dSumSq /
count);
3184 return DISTANCE_COMPUTATION_RESULTS::SUCCESS;
3190 bool signedDistances ,
3192 assert(cloud && planeEquation);
3194 return DISTANCE_COMPUTATION_RESULTS::ERROR_NULL_COMPAREDCLOUD;
3196 if (!planeEquation) {
3197 return DISTANCE_COMPUTATION_RESULTS::NULL_PLANE_EQUATION;
3201 return DISTANCE_COMPUTATION_RESULTS::ERROR_EMPTY_COMPAREDCLOUD;
3204 return DISTANCE_COMPUTATION_RESULTS::ERROR_ENABLE_SCALAR_FIELD_FAILURE;
3212 std::numeric_limits<PointCoordinateType>::epsilon());
3214 return DISTANCE_COMPUTATION_RESULTS::ERROR_PLANE_NORMAL_LT_ZERO;
3216 double dSumSq = 0.0;
3217 for (
unsigned i = 0; i <
count; ++i) {
3221 if (signedDistances) {
3229 *rms = sqrt(dSumSq /
count);
3232 return DISTANCE_COMPUTATION_RESULTS::SUCCESS;
3253 return DISTANCE_COMPUTATION_RESULTS::ERROR_NULL_COMPAREDCLOUD;
3257 return DISTANCE_COMPUTATION_RESULTS::ERROR_EMPTY_COMPAREDCLOUD;
3260 return DISTANCE_COMPUTATION_RESULTS::ERROR_ENABLE_SCALAR_FIELD_FAILURE;
3262 if (widthX <= 0 || widthY <= 0) {
3263 return DISTANCE_COMPUTATION_RESULTS::ERROR_INVALID_PRIMITIVE_DIMENSIONS;
3270 widthXVec = rotationTransform * widthXVec;
3271 widthYVec = rotationTransform * widthYVec;
3272 normalVector = rotationTransform * normalVector;
3275 CCVector3 rectangleP0 = center - (widthXVec / 2) - (widthYVec / 2);
3276 CCVector3 rectangleP1 = center + (widthXVec / 2) - (widthYVec / 2);
3277 CCVector3 rectangleP3 = center - (widthXVec / 2) + (widthYVec / 2);
3278 CCVector3 e0 = rectangleP1 - rectangleP0;
3279 CCVector3 e1 = rectangleP3 - rectangleP0;
3281 for (
unsigned i = 0; i <
count; ++i) {
3288 dist -= (s / dot0) * e0;
3298 dist -= (t / dot1) * e1;
3305 if (signedDist && pe->
dot(normalVector) - planeDistance < 0) {
3311 *rms = sqrt(dSumSq /
count);
3313 return DISTANCE_COMPUTATION_RESULTS::SUCCESS;
3325 return DISTANCE_COMPUTATION_RESULTS::ERROR_NULL_COMPAREDCLOUD;
3329 return DISTANCE_COMPUTATION_RESULTS::ERROR_EMPTY_COMPAREDCLOUD;
3332 return DISTANCE_COMPUTATION_RESULTS::ERROR_ENABLE_SCALAR_FIELD_FAILURE;
3334 if (boxDimensions.
x <= 0 || boxDimensions.
y <= 0 || boxDimensions.
z <= 0) {
3335 return DISTANCE_COMPUTATION_RESULTS::ERROR_INVALID_PRIMITIVE_DIMENSIONS;
3345 u = rotationTransform * u;
3346 v = rotationTransform * v;
3347 w = rotationTransform * w;
3349 for (
unsigned i = 0; i <
count; ++i) {
3351 CCVector3 pointCenterDifference = (*p - boxCenter);
3353 pointCenterDifference.
dot(v),
3354 pointCenterDifference.
dot(w));
3355 bool insideBox =
false;
3356 if (p_inBoxCoords.
x > -hu && p_inBoxCoords.
x < hu &&
3357 p_inBoxCoords.
y > -hv && p_inBoxCoords.
y < hv &&
3358 p_inBoxCoords.
z > -hw && p_inBoxCoords.
z < hw) {
3363 if (p_inBoxCoords.
x < -hu) {
3364 dist.x = -(p_inBoxCoords.
x + hu);
3365 }
else if (p_inBoxCoords.
x > hu) {
3366 dist.x = p_inBoxCoords.
x - hu;
3367 }
else if (insideBox) {
3371 if (p_inBoxCoords.
y < -hv) {
3372 dist.y = -(p_inBoxCoords.
y + hv);
3373 }
else if (p_inBoxCoords.
y > hv) {
3374 dist.y = p_inBoxCoords.
y - hv;
3375 }
else if (insideBox) {
3379 if (p_inBoxCoords.
z < -hw) {
3380 dist.z = -(p_inBoxCoords.
z + hw);
3381 }
else if (p_inBoxCoords.
z > hw) {
3382 dist.z = p_inBoxCoords.
z - hw;
3383 }
else if (insideBox) {
3402 if (signedDist && insideBox) {
3408 *rms = sqrt(dSumSq /
count);
3410 return DISTANCE_COMPUTATION_RESULTS::SUCCESS;
3418 bool signedDistances ,
3420 if (discRadius < 0) {
3421 return DISTANCE_COMPUTATION_RESULTS::INVALID_INPUT;
3424 return DISTANCE_COMPUTATION_RESULTS::ERROR_NULL_COMPAREDCLOUD;
3428 return DISTANCE_COMPUTATION_RESULTS::ERROR_EMPTY_COMPAREDCLOUD;
3431 return DISTANCE_COMPUTATION_RESULTS::ERROR_ENABLE_SCALAR_FIELD_FAILURE;
3436 double dSumSq = 0.0;
3437 for (
unsigned i = 0; i <
count; ++i) {
3440 ScalarType dPlane = (*P - discCenter).
dot(
normal);
3442 ScalarType rProj = (pProj - discCenter).norm();
3446 if (rProj <= discRadius) {
3450 discCenter + discRadius * (pProj - discCenter) /
3453 d = (*P - pEdge).normd();
3455 d = (*P - pEdge).
dot(
normal) > 0 ? d : -d;
3457 if (signedDistances) {
3465 *rms = sqrt(dSumSq /
count);
3468 return DISTANCE_COMPUTATION_RESULTS::SUCCESS;
3477 return DISTANCE_COMPUTATION_RESULTS::ERROR_NULL_COMPAREDCLOUD;
3481 return DISTANCE_COMPUTATION_RESULTS::ERROR_EMPTY_COMPAREDCLOUD;
3484 return DISTANCE_COMPUTATION_RESULTS::ERROR_ENABLE_SCALAR_FIELD_FAILURE;
3487 ScalarType dSumSq = 0;
3488 for (
unsigned i = 0; i <
count; ++i) {
3491 for (
unsigned j = 0; j < polyline->
size() - 1; j++) {
3508 if (((startXMinusASq >= distSq) && (endXMinusASq >= distSq) &&
3510 ((startYMinusBSq >= distSq) && (endYMinusBSq >= distSq) &&
3512 ((startZMinusCSq >= distSq) && (endZMinusCSq >= distSq) &&
3516 if (std::isnan(distSq)) {
3529 *rms = sqrt(dSumSq /
count);
3531 return DISTANCE_COMPUTATION_RESULTS::SUCCESS;
3536 assert(cloud && planeEquation);
3540 if (
count == 0)
return 0;
3548 std::numeric_limits<PointCoordinateType>::epsilon());
3550 double dSumSq = 0.0;
3554 for (
unsigned i = 0; i <
count; ++i) {
3563 return static_cast<ScalarType
>(sqrt(dSumSq /
count));
3570 assert(cloud && planeEquation);
3571 assert(percent < 1.0f);
3575 if (
count == 0)
return 0;
3583 std::numeric_limits<PointCoordinateType>::epsilon());
3586 std::vector<PointCoordinateType> tail;
3587 std::size_t tailSize =
3588 static_cast<std::size_t
>(
ceil(
static_cast<float>(
count) * percent));
3589 tail.resize(tailSize);
3593 std::size_t pos = 0;
3594 for (
unsigned i = 0; i <
count; ++i) {
3600 if (pos < tailSize) {
3602 }
else if (tail.back() < d) {
3607 std::size_t maxPos = pos - 1;
3609 std::size_t maxIndex = maxPos;
3610 for (std::size_t j = 0; j < maxPos; ++j)
3611 if (tail[j] < tail[maxIndex]) maxIndex = j;
3613 if (maxPos != maxIndex)
std::swap(tail[maxIndex], tail[maxPos]);
3617 return static_cast<ScalarType
>(tail.back());
3622 assert(cloud && planeEquation);
3626 if (
count == 0)
return 0;
3634 std::numeric_limits<PointCoordinateType>::epsilon());
3640 for (
unsigned i = 0; i <
count; ++i) {
3648 return static_cast<ScalarType
>(maxDist);
3655 switch (measureType) {
3682 unsigned seedPointIndex,
3687 unsigned n = cloud->
size();
3688 if (n == 0 || seedPointIndex >= n)
return false;
3723 if (!comparedCloud || !referenceCloud)
3724 return DISTANCE_COMPUTATION_RESULTS::ERROR_NULL_COMPAREDCLOUD;
3726 unsigned nA = comparedCloud->
size();
3727 if (nA == 0)
return DISTANCE_COMPUTATION_RESULTS::ERROR_EMPTY_COMPAREDCLOUD;
3740 for (
unsigned i = 0; i < nA; ++i) {
3751 return DISTANCE_COMPUTATION_RESULTS::SUCCESS;
3762 if (
nullptr == comparedCloud) {
3763 return DISTANCE_COMPUTATION_RESULTS::ERROR_NULL_COMPAREDCLOUD;
3765 if (
nullptr == referenceCloud) {
3766 return DISTANCE_COMPUTATION_RESULTS::ERROR_NULL_REFERENCECLOUD;
3769 return DISTANCE_COMPUTATION_RESULTS::ERROR_OCTREE_LEVEL_LT_ONE;
3772 return DISTANCE_COMPUTATION_RESULTS::
3773 ERROR_OCTREE_LEVEL_GT_MAX_OCTREE_LEVEL;
3781 return DISTANCE_COMPUTATION_RESULTS::ERROR_SYNCHRONIZE_OCTREES_FAILURE;
3783 if (
nullptr == octreeA ||
nullptr == octreeB) {
3787 return DISTANCE_COMPUTATION_RESULTS::ERROR_INTERNAL;
3796 std::min(minIndexesA[1], minIndexesB[1]),
3797 std::min(minIndexesA[2], minIndexesB[2]));
3799 std::max(maxIndexesA[1], maxIndexesB[1]),
3800 std::max(maxIndexesA[2], maxIndexesB[2]));
3802 Tuple3ui boxSize(
static_cast<unsigned>(maxIndexes.
x - minIndexes.
x + 1),
3803 static_cast<unsigned>(maxIndexes.
y - minIndexes.
y + 1),
3804 static_cast<unsigned>(maxIndexes.
z - minIndexes.
z + 1));
3808 return DISTANCE_COMPUTATION_RESULTS::ERROR_OUT_OF_MEMORY;
3810 if (maxSearchDist > 0) {
3813 const ScalarType resetValue =
static_cast<ScalarType
>(maxSearchDist);
3814 for (
unsigned i = 0; i < comparedCloud->
size(); ++i) {
3829 while (!theCodes.empty()) {
3831 theCodes.pop_back();
3834 cellPos -= minIndexes;
3844 ScalarType cellSize =
3850 if (!compOctree)
delete octreeA;
3851 if (!refOctree)
delete octreeB;
3852 return DISTANCE_COMPUTATION_RESULTS::ERROR_GET_CELL_INDEXES_FAILURE;
3855 ScalarType maxD = 0;
3858 while (!theIndexes.empty()) {
3859 unsigned theIndex = theIndexes.back();
3860 theIndexes.pop_back();
3865 cellPos -= minIndexes;
3866 unsigned di = dtGrid.
getValue(cellPos);
3867 ScalarType d = sqrt(
static_cast<ScalarType
>(di)) * cellSize;
3868 if (d > maxD) maxD = d;
3871 if (maxSearchDist <= 0 || d < maxSearchDist) {
3873 for (
unsigned j = 0; j < Yk.
size(); ++j)
3878 result =
static_cast<int>(maxD);
3881 result = DISTANCE_COMPUTATION_RESULTS::
3882 ERROR_INIT_DISTANCE_TRANSFORM_GRID_FAILURE;
3901 bool onlyOrthogonal ) {
3909 if (
dot > squareLengthAB) {
3910 return onlyOrthogonal ? -
PC_ONE : (P - B).norm2();
constexpr unsigned char POINT_VISIBLE
constexpr PointCoordinateType PC_ONE
'1' as a PointCoordinateType value
constexpr unsigned CV_LOCAL_MODEL_MIN_SIZE[]
Min number of points to compute local models (see CV_LOCAL_MODEL_TYPES)
constexpr ScalarType NAN_VALUE
NaN as a ScalarType value.
Tuple3Tpl< int > Tuple3i
Tuple of 3 int values.
float PointCoordinateType
Type of the coordinates of a (N-D) point.
cmdLineReadable * params[]
Type dot(const Vector2Tpl &v) const
Dot product.
Type norm2() const
Returns vector square norm.
void normalize()
Sets vector norm to unity.
double normd() const
Returns vector norm (forces double precision output)
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)
static PointCoordinateType vnorm(const PointCoordinateType p[])
Vector3Tpl cross(const Vector3Tpl &v) const
Cross product.
static Vector3Tpl fromArray(const int a[3])
Constructor from an int array.
static double vdotd(const PointCoordinateType p[], const PointCoordinateType q[])
static PointCoordinateType vdot(const PointCoordinateType p[], const PointCoordinateType q[])
static PointCoordinateType vnorm2(const PointCoordinateType p[])
A kind of ReferenceCloud based on the DgmOctree::NeighboursSet structure.
The octree structure used throughout the library.
const int * getMaxFillIndexes(unsigned char level) const
unsigned CellCode
Type of the code of an octree cell.
GenericIndexedCloudPersist * associatedCloud() const
Returns the associated cloud.
std::vector< unsigned int > cellIndexesContainer
Octree cell indexes container.
void getCellPos(CellCode code, unsigned char level, Tuple3i &cellPos, bool isCodeTruncated) const
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
int findNeighborsInASphereStartingFromCell(NearestNeighboursSearchStruct &nNSS, double radius, bool sortValues=true) const
Advanced form of the nearest neighbours search algorithm (in a sphere)
virtual void clear()
Clears the octree.
void getTheCellPosWhichIncludesThePoint(const CCVector3 *thePoint, Tuple3i &cellPos) const
unsigned getNumberOfProjectedPoints() const
Returns the number of points projected into the octree.
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.
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)
const CCVector3 & getOctreeMins() const
Returns the lower boundaries of the octree.
int build(GenericProgressCallback *progressCb=nullptr)
Builds the structure.
const CCVector3 & getOctreeMaxs() const
Returns the higher boundaries of the octree.
std::vector< IndexAndCode > cellsContainer
Container of 'IndexAndCode' structures.
const CellCode & getCellCode(unsigned index) const
Returns the ith cell code.
bool getCellCodes(unsigned char level, cellCodesContainer &vec, bool truncatedCodes=false) const
bool getCellCodesAndIndexes(unsigned char level, cellsContainer &vec, bool truncatedCodes=false) const
Fast Marching algorithm for surface front propagation.
int propagate() override
Propagates the front.
int init(GenericCloud *theCloud, DgmOctree *theOctree, unsigned char gridLevel, bool constantAcceleration=false)
Initializes the grid with a point cloud (and ist corresponding octree)
bool setPropagationTimingsAsDistances()
Sets the propagation timings as distances for each point.
virtual bool setSeedCell(const Tuple3i &pos)
Sets a given cell as "seed".
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 void forEach(genericPointAction action)=0
Fast iteration mechanism.
virtual void placeIteratorAtBeginning()=0
Sets the cloud iterator at the beginning.
virtual unsigned char testVisibility(const CCVector3 &P) const
virtual const CCVector3 * getNextPoint()=0
Returns the next point (relatively to the global iterator position)
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 * getPoint(unsigned index) const =0
Returns the ith point.
A generic mesh with index-based vertex access.
virtual void getTriangleVertices(unsigned triangleIndex, CCVector3 &A, CCVector3 &B, CCVector3 &C) const =0
Returns the vertices of a given triangle.
virtual unsigned size() const =0
Returns the number of triangles.
virtual void getBoundingBox(CCVector3 &bbMin, CCVector3 &bbMax)=0
Returns the mesh bounding-box.
virtual GenericTriangle * _getNextTriangle()=0
Returns the next triangle (relatively to the global iterator position)
virtual void placeIteratorAtBeginning()=0
Places the mesh iterator at the beginning.
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.
A generic triangle interface.
virtual const CCVector3 * _getA() const =0
Returns the first vertex (A)
virtual const CCVector3 * _getC() const =0
Returns the third vertex (C)
virtual const CCVector3 * _getB() const =0
Returns the second vertex (B)
Simple 3D grid structure.
const GridElement & getValue(int i, int j, int k) const
Returns the value of a given cell (const version)
void setValue(int i, int j, int k, GridElement value)
Sets the value of a given cell.
Local modelization (generic interface)
static LocalModel * New(CV_LOCAL_MODEL_TYPES type, Neighbourhood &subset, const CCVector3 ¢er, PointCoordinateType squaredRadius)
Factory.
virtual ScalarType computeDistanceFromModelToPoint(const CCVector3 *P, CCVector3 *nearestPoint=nullptr) const =0
Compute the (unsigned) distance between a 3D point and this model.
bool oneStep()
Increments total progress value of a single unit.
void setPointScalarValue(unsigned pointIndex, ScalarType value) override
virtual bool reserve(unsigned newCapacity)
Reserves memory for the point database.
void addPoint(const CCVector3 &P)
Adds a 3D point to the database.
ScalarType getPointScalarValue(unsigned pointIndex) const override
bool enableScalarField() override
A very simple point cloud (no point duplication)
void setPointScalarValue(unsigned pointIndex, ScalarType value) override
Sets the ith point associated scalar value.
virtual ScalarType getCurrentPointScalarValue() const
Returns the current point associated scalar value.
virtual bool addPointIndex(unsigned globalIndex)
Point global index insertion mechanism.
void placeIteratorAtBeginning() override
Sets the cloud iterator at the beginning.
unsigned size() const override
Returns the number of points.
virtual void removeCurrentPointGlobalIndex()
Removes current element.
virtual unsigned getPointGlobalIndex(unsigned localIndex) const
const CCVector3 * getPointPersistentPtr(unsigned index) override
Returns the ith point as a persistent pointer.
virtual bool reserve(unsigned n)
Reserves some memory for hosting the point references.
const CCVector3 * getPoint(unsigned index) const override
Returns the ith point.
ScalarType getPointScalarValue(unsigned pointIndex) const override
Returns the ith point associated scalar value.
virtual void forwardIterator()
Forwards the local element iterator.
static bool ValidValue(ScalarType value)
Returns whether a scalar value is valid or not.
__host__ __device__ float dot(float2 a, float2 b)
__host__ __device__ int2 abs(int2 v)
static double dist(double x1, double y1, double x2, double y2)
MiniVec< float, N > floor(const MiniVec< float, N > &a)
MiniVec< float, N > ceil(const MiniVec< float, N > &a)
Generic file read and write utility for python interface.
bool GreaterThanEpsilon(float x)
Test a floating point number against our epsilon (a very small number).
bool LessThanEpsilon(float x)
Test a floating point number against our epsilon (a very small number).
void swap(cloudViewer::core::SmallVectorImpl< T > &LHS, cloudViewer::core::SmallVectorImpl< T > &RHS)
Implement std::swap in terms of SmallVector swap.
Tuple3i pos
Cell position.
unsigned char level
Subdivision level.
Helper structure for triangles to test.
std::vector< unsigned > processTriangles
TrianglesToTest(const GenericIndexedMesh &mesh)
std::size_t trianglesToTestCount
unsigned numberOfTriangles
std::vector< unsigned > trianglesToTest
std::size_t trianglesToTestCapacity
Association between an index and the code of an octree cell.
CellCode theCode
cell code
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.
SaitoSquaredDistanceTransform * distanceTransform
Distance transform.
GenericIndexedMesh * mesh
Mesh.
OctreeAndMeshIntersection()
Default constructor.
Tuple3i maxFillIndexes
Grid occupancy of mesh (maximum indexes for each dimension)
Tuple3i minFillIndexes
Grid occupancy of mesh (minimum indexes for each dimension)
DgmOctree * octree
Octree structure.
Grid3D< TriangleList * > perCellTriangleList
Array of FacesInCellPtr structures.
~OctreeAndMeshIntersection()
Destructor.
List of triangles (indexes)
bool push(unsigned index)
Adds a triangle index.
std::vector< unsigned > indexes
Triangles indexes.