8 #include <QColorDialog>
9 #include <QElapsedTimer>
10 #include <QInputDialog>
11 #include <QMessageBox>
12 #include <QPushButton>
69 const QString& baseName) {
70 if (cloud ==
nullptr) {
75 QString
name = baseName;
80 name = QString(
"%1 #%2").arg(baseName).arg(++tries);
82 if (tries > 99)
return QString();
92 QColor colour = QColorDialog::getColor(
Qt::white, parent);
94 if (!colour.isValid())
return false;
96 while (!selectedEntities.empty()) {
98 selectedEntities.pop_back();
102 selectedEntities.push_back(ent->
getChild(i));
114 QString(
"[SetColor] Can't set color for mesh '%1' "
115 "(vertices are not accessible)")
124 cloud->
colorize(
static_cast<float>(colour.redF()),
125 static_cast<float>(colour.greenF()),
126 static_cast<float>(colour.blueF()));
177 QString(
"[SetColor] Can't change color of entity '%1'")
186 for (
ccHObject* ent : selectedEntities) {
187 bool lockedVertices =
false;
190 if (lockedVertices) {
192 ent->getName(), selectedEntities.size() == 1);
213 if (!dlg.exec())
return false;
223 QColor first, second;
233 for (
ccHObject* ent : selectedEntities) {
234 bool lockedVertices =
false;
237 if (lockedVertices) {
239 ent->getName(), selectedEntities.size() == 1);
247 bool success =
false;
254 ent->showColors(
true);
256 ent->setRedrawFlagRecursive(
true);
266 if (selectedEntities.size() != 1) {
274 if (!pointCloud || lockedVertices) {
275 if (lockedVertices && pointCloud)
294 if (selectedEntities.size() != 2) {
305 if (!cloud1 || !cloud2) {
312 "None of the selected entities has per-point or per-vertex "
317 "Both entities have colors! Remove the colors on the entity "
318 "you wish to import the colors to!");
333 "Destination cloud (or vertices) must be a real point cloud!");
339 if (
static_cast<ccPointCloud*
>(dest)->interpolateColorsFrom(source,
354 if (selectedEntities.size() != 2) {
365 if (!cloud1 || !cloud2) {
372 "None of the selected entities has per-point or per-vertex "
393 std::vector<int> sfIndexes;
397 sfIndexes.push_back(0);
398 }
else if (sfCount > 1) {
400 QStringList scalarFields;
402 for (
unsigned i = 0; i < sfCount; ++i) {
412 if (sfIndexes.empty()) {
419 }
catch (
const std::bad_alloc&) {
429 static int s_interpKNN = 6;
434 iDlg.knnSpinBox->setValue(s_interpKNN);
446 params.knn = s_interpKNN = iDlg.knnSpinBox->value();
447 params.radius = iDlg.radiusDoubleSpinBox->value();
448 params.sigma = iDlg.kernelDoubleSpinBox->value();
454 dest, source, sfIndexes,
params, &pDlg)) {
456 static_cast<int>(
std::min(sfCountBefore + 1,
470 for (
ccHObject* ent : selectedEntities) {
480 "no material/texture!")
485 QMessageBox::warning(parent,
"Mesh already has colors",
486 QString(
"Mesh '%1' already has "
487 "colors! Overwrite them?")
489 QMessageBox::Yes | QMessageBox::No,
490 QMessageBox::No) != QMessageBox::Yes) {
504 "convert texture on mesh '%1'!")
516 QString defaultSFName(
"Intensity");
518 bool useCustomIntensityRange =
false;
519 static double s_minI = 0.0, s_maxI = 1.0;
520 if (QMessageBox::question(parent,
"Intensity range",
521 "Do you want to define the theoretical intensity "
522 "range (yes)\nor use the actual one (no)?",
524 QMessageBox::No) == QMessageBox::Yes) {
527 "Theroetical intensity", parent);
528 if (!atdvDlg.exec()) {
532 s_minI = atdvDlg.doubleSpinBox1->value();
533 s_maxI = atdvDlg.doubleSpinBox2->value();
534 useCustomIntensityRange =
true;
537 for (
ccHObject* ent : selectedEntities) {
538 bool lockedVertices =
false;
540 if (!pc || lockedVertices) {
542 ent->getName(), selectedEntities.size() == 1);
549 .arg(ent->getName()));
554 "has no scalar field!")
555 .arg(ent->getName()));
562 if (!defaultSFName.isEmpty()) {
565 qPrintable(defaultSFName));
570 "Choose scalar field", parent);
578 sfIdx =
static_cast<int>(i);
583 if (!poeDlg.exec()) {
597 ent->showColors(
true);
599 ent->setRedrawFlagRecursive(
true);
602 "apply the process on entity '%1'!")
603 .arg(ent->getName()));
613 if (selectedEntities.empty()) {
618 std::vector<std::pair<ccHObject*, ccPointCloud*>> selectedCloudsWithColors;
621 for (
ccHObject* ent : selectedEntities) {
622 bool lockedVertices =
false;
624 if (!pc || lockedVertices) {
626 ent->getName(), selectedEntities.size() == 1);
633 ccPointCloud::RGB_FILTER_TYPES::BILATERAL) &&
638 selectedCloudsWithColors.push_back({ent, pc});
643 if (sigmaCloud < spatialSigma) {
644 spatialSigma = sigmaCloud;
653 if (selectedCloudsWithColors.empty()) {
655 ccPointCloud::RGB_FILTER_TYPES::BILATERAL)
657 "Select at least one cloud or mesh with RGB "
658 "colors and an active scalar field");
661 "Select at least one cloud or mesh with RGB colors");
665 double sigmaSF = -1.0;
666 if (filterParams.
filterType == ccPointCloud::RGB_FILTER_TYPES::BILATERAL) {
668 selectedCloudsWithColors.front()
669 .second->getCurrentDisplayedScalarField();
672 sigmaSF = sfRange / 4;
674 if (filterParams.
sigmaSF > 0) {
675 sigmaSF = filterParams.
sigmaSF;
679 QScopedPointer<ecvProgressDialog> pDlg;
684 ccPointCloud::RGB_FILTER_TYPES::BILATERAL) {
686 "Spatial sigma",
"Scalar sigma",
"Color threshold", DBL_MIN,
687 1.0e9, spatialSigma, sigmaSF,
690 dlg.setWindowTitle(
"RGB bilateral filter");
692 dlg.doubleSpinBox1->setStatusTip(
"3*sigma = 99.7% attenuation");
693 dlg.doubleSpinBox2->setStatusTip(
694 "Scalar sigma controls how much the filter behaves as a "
695 "Gaussian Filter\nSigma at +inf uses the whole range of "
697 dlg.doubleSpinBox3->setStatusTip(
698 "For averaging, it will only use colors for which all "
699 "components are in the range[threshold:255 - threshold]");
705 spatialSigma = dlg.doubleSpinBox1->value();
706 sigmaSF = dlg.doubleSpinBox2->value();
710 DBL_MIN, 1.0e9, spatialSigma,
713 dlg.setWindowTitle(
"RGB gaussian/mean/median filter");
715 dlg.doubleSpinBox1->setStatusTip(
"3*sigma = 99.7% attenuation");
716 dlg.doubleSpinBox2->setStatusTip(
717 "For averaging, it will only use colors for which all "
718 "components are in the range [threshold:255-threshold]");
724 spatialSigma = dlg.doubleSpinBox1->value();
731 pDlg->setAutoClose(
false);
734 for (
auto entAndPC : selectedCloudsWithColors) {
739 ccPointCloud::RGB_FILTER_TYPES::BILATERAL) ||
743 Q_ASSERT(outSfIdx >= 0);
750 Q_ASSERT(outSF !=
nullptr);
753 ccPointCloud::RGB_FILTER_TYPES::BILATERAL) {
754 sfName = QString(
"%1.bilsmooth(%2,%3)")
759 ccPointCloud::RGB_FILTER_TYPES::GAUSSIAN) {
760 sfName = QString(
"%1.smooth(%2)")
764 ccPointCloud::RGB_FILTER_TYPES::MEAN) {
765 sfName = QString(
"%1.meansmooth(%2)")
769 sfName = QString(
"%1.medsmooth(%2)")
783 QString(
"Failed to create scalar field for cloud "
784 "'%1' (not enough memory?)")
796 QString(
"Couldn't compute octree for cloud '%1'!")
802 QElapsedTimer eTimer;
806 filterParams, parent ? pDlg.data() :
nullptr);
808 static_cast<double>(eTimer.elapsed()) / 1000.0);
819 entAndPC.first->showColors(
true);
820 entAndPC.first->showSF(
false);
832 if (selectedEntities.empty())
return false;
838 if (spatialSigma < 0.0) {
845 double scalarFieldSigma = -1.0;
846 if (filterParams.
filterType == ccPointCloud::RGB_FILTER_TYPES::BILATERAL) {
855 if (filterParams.
sigmaSF == -1) {
857 scalarFieldSigma = range / 4;
859 scalarFieldSigma = filterParams.
sigmaSF;
865 ccPointCloud::RGB_FILTER_TYPES::BILATERAL) {
867 DBL_MIN, 1.0e9, spatialSigma,
868 scalarFieldSigma, 8,
nullptr, parent);
869 dlg.doubleSpinBox1->setStatusTip(
"3*sigma = 98% attenuation");
870 dlg.doubleSpinBox2->setStatusTip(
871 "Scalar field's sigma controls how much the filter behaves "
873 "Gaussian Filter\n sigma at +inf uses the whole range of "
875 if (!dlg.exec())
return false;
877 spatialSigma = dlg.doubleSpinBox1->value();
878 scalarFieldSigma = dlg.doubleSpinBox2->value();
881 spatialSigma = QInputDialog::getDouble(parent,
"Gaussian filter",
882 "sigma:", spatialSigma,
883 DBL_MIN, 1.0e9, 8, &ok);
884 if (!ok)
return false;
889 pDlg.setAutoClose(
false);
891 for (
ccHObject* ent : selectedEntities) {
892 bool lockedVertices =
false;
894 if (!pc || lockedVertices) {
896 ent->getName(), selectedEntities.size() == 1);
905 Q_ASSERT(outSfIdx >= 0);
909 Q_ASSERT(sf !=
nullptr);
913 ccPointCloud::RGB_FILTER_TYPES::BILATERAL) {
914 sfName = QString(
"%1.bilsmooth(%2,%3)")
917 .arg(scalarFieldSigma);
919 sfName = QString(
"%1.smooth(%2)")
931 "cloud '%1' (not enough memory?)")
941 QString(
"Couldn't compute octree for cloud '%1'!")
948 QString methodTitle =
950 ccPointCloud::RGB_FILTER_TYPES::BILATERAL)
951 ? QObject::tr(
"Bilateral filter")
952 : QObject::tr(
"Gaussian filter");
954 pDlg.
setInfo(QObject::tr(
"Processing cloud '%1'")
957 QCoreApplication::processEvents();
959 QElapsedTimer eTimer;
964 ccPointCloud::RGB_FILTER_TYPES::BILATERAL) {
969 pc, scalarFieldSigma, &pDlg,
octree.data());
975 pc, -1, &pDlg,
octree.data());
979 "[%s] Timing: %3.2f s.", qPrintable(methodTitle),
980 static_cast<double>(eTimer.elapsed()) / 1000.0);
990 ccPointCloud::RGB_FILTER_TYPES::BILATERAL)
991 ? QString(
"Failed to apply Bilateral "
992 "filter to cloud '%1'")
993 : QString(
"Failed to apply Gaussian filter "
999 "octree! (not enough memory?)")
1004 QString(
"Entity [%1] has no active scalar field!")
1016 filterParams.
filterType = ccPointCloud::RGB_FILTER_TYPES::BILATERAL;
1024 bool mixWithExistingColors =
false;
1026 QMessageBox::StandardButton answer = QMessageBox::warning(
1027 parent,
"Scalar Field to RGB",
"Mix with existing colors (if any)?",
1028 QMessageBox::Yes | QMessageBox::No | QMessageBox::Cancel,
1030 if (answer == QMessageBox::Yes)
1031 mixWithExistingColors =
true;
1032 else if (answer == QMessageBox::Cancel)
1035 for (
ccHObject* ent : selectedEntities) {
1038 bool lockedVertices =
false;
1040 if (lockedVertices) {
1042 ent->getName(), selectedEntities.size() == 1);
1045 if (cloud !=
nullptr)
1051 mixWithExistingColors)) {
1054 ent->setRedrawFlagRecursive(
true);
1065 static int s_randomColorsNumber = 256;
1068 s_randomColorsNumber =
1069 QInputDialog::getInt(parent,
"Random colors",
1070 "Number of random colors (will be regularly "
1071 "sampled over the SF interval):",
1072 s_randomColorsNumber, 2, INT_MAX, 16, &ok);
1073 if (!ok)
return false;
1074 Q_ASSERT(s_randomColorsNumber > 1);
1078 static_cast<unsigned>(s_randomColorsNumber))) {
1084 for (
int i = 0; i < s_randomColorsNumber; ++i) {
1090 for (
ccHObject* ent : selectedEntities) {
1093 bool lockedVertices =
false;
1095 if (lockedVertices) {
1097 ent->getName(), selectedEntities.size() == 1);
1100 if (cloud !=
nullptr)
1110 ScalarType minSF = sf->
getMin();
1111 ScalarType maxSF = sf->
getMax();
1114 (maxSF - minSF) / (s_randomColorsNumber - 1);
1115 if (step == 0) step =
static_cast<ScalarType
>(1.0);
1117 for (
unsigned i = 0; i < pc->
size(); ++i) {
1120 static_cast<unsigned>((val - minSF) / step);
1121 if (colIndex == s_randomColorsNumber) --colIndex;
1139 for (
ccHObject* ent : selectedEntities) {
1141 if (cloud !=
nullptr)
1146 if (sf ==
nullptr) {
1148 QString(
"Cloud %1 has no displayed scalar field!")
1151 const char* sfName = sf->
getName();
1153 QString newName = QInputDialog::getText(
1154 parent,
"SF name",
"name:", QLineEdit::Normal,
1155 QString(sfName ? sfName :
"unknown"), &ok);
1156 if (ok) sf->
setName(qPrintable(newName));
1165 for (
ccHObject* ent : selectedEntities) {
1167 if (cloud !=
nullptr)
1181 for (
unsigned j = 0; j < cloud->
size(); j++) {
1182 ScalarType idValue =
static_cast<ScalarType
>(j);
1196 const std::vector<std::vector<ScalarType>>& scalarsVector,
1197 const std::string&
name) {
1198 if (scalarsVector.size() != selectedEntities.size()) {
1202 size_t scalarIndex = 0;
1203 for (
ccHObject* ent : selectedEntities) {
1204 const std::vector<ScalarType>& scalars = scalarsVector[scalarIndex++];
1207 if (cloud !=
nullptr)
1210 if (scalars.size() != pc->
size()) {
1212 "entity[%1] points size, ignore it!")
1227 for (
unsigned j = 0; j < cloud->
size(); j++) {
1243 double out = QInputDialog::getDouble(
1244 parent, QObject::tr(
"SF --> coordinate"),
1245 QObject::tr(
"Enter the coordinate equivalent to NaN values:"),
1246 minSFValue, -1.0e9, 1.0e9, 6, &ok);
1252 "[SetSFAsCoord] By default the coordinate equivalent to NaN "
1253 "values will be the minimum SF value"));
1261 ectsDlg.warningLabel->setVisible(
false);
1262 ectsDlg.setWindowTitle(
"Export SF to coordinate(s)");
1264 if (!ectsDlg.exec())
return false;
1267 if (!importDim[0] && !importDim[1] && !importDim[2])
1272 ScalarType defaultValueForNaN =
NAN_VALUE;
1274 for (
ccHObject* ent : selectedEntities) {
1281 if (sf !=
nullptr) {
1282 if (std::isnan(defaultValueForNaN) &&
1286 defaultValueForNaN =
1308 if (!ectsDlg.exec()) {
1315 if (!exportDims[0] && !exportDims[1] && !exportDims[2])
1321 for (
ccHObject* entity : selectedEntities) {
1323 if (pc ==
nullptr) {
1334 entity->showSF(
true);
1343 bool* exportDimensions ) {
1344 bool exportDims[3] = {
false,
false,
false};
1345 if (exportDimensions) {
1346 exportDims[0] = exportDimensions[0];
1347 exportDims[1] = exportDimensions[1];
1348 exportDims[2] = exportDimensions[2];
1352 ectsDlg.setWindowTitle(QObject::tr(
"Export normals to SF(s)"));
1354 if (!ectsDlg.exec()) {
1358 exportDims[0] = ectsDlg.
exportX();
1359 exportDims[1] = ectsDlg.
exportY();
1360 exportDims[2] = ectsDlg.
exportZ();
1363 if (!exportDims[0] && !exportDims[1] && !exportDims[2])
1369 for (
ccHObject* entity : selectedEntities) {
1371 if (pc ==
nullptr) {
1378 QString(
"Cloud '%1' has no normals").arg(pc->
getName()));
1388 entity->showSF(
true);
1390 entity->setRedrawFlagRecursive(
true);
1398 Q_ASSERT(!selectedEntities.empty());
1400 ccHObject* entity = selectedEntities[0];
1401 bool lockedVertices;
1404 if (lockedVertices) {
1408 if (cloud ==
nullptr) {
1414 if (!sfaDlg.exec()) {
1418 if (!sfaDlg.
apply(cloud)) {
1429 std::unordered_set<ccPointCloud*> clouds;
1431 for (
ccHObject* ent : selectedEntities) {
1434 clouds.insert(cloud);
1437 if (clouds.empty())
return false;
1440 if (!dialog.exec())
return false;
1447 for (
const auto cloud : clouds) {
1448 std::vector<ccScalarField*>
fields(4);
1464 unsigned count = cloud->size();
1466 if (sf && !sf->reserveSafe(
count)) {
1468 "instantiate SF '%1' on cloud '%2'")
1469 .arg(sf->getName(), cloud->getName()));
1476 for (
unsigned j = 0; j < cloud->size(); ++j) {
1484 static_cast<ScalarType
>(rgb.
r + rgb.
g + rgb.
b) / 3);
1490 if (sf ==
nullptr)
continue;
1492 sf->computeMinAndMax();
1494 int sfIdx = cloud->getScalarFieldIndexByName(sf->getName());
1495 if (sfIdx >= 0) cloud->deleteScalarField(sfIdx);
1496 sfIdx = cloud->addScalarField(sf);
1497 Q_ASSERT(sfIdx >= 0);
1500 cloud->setCurrentDisplayedScalarField(sfIdx);
1501 cloud->showSF(
true);
1505 if (cloud->getParent() &&
1507 cloud->getParent()->showSF(
true);
1511 if (!fieldsStr.isEmpty()) fieldsStr.append(
", ");
1512 fieldsStr.append(sf->getName());
1515 QString(
"[sfFromColor] Failed to add scalar field '%1' "
1517 .arg(sf->getName(), cloud->getName()));
1523 if (!fieldsStr.isEmpty())
1524 CVLog::Print(QString(
"[sfFromColor] New scalar fields (%1) added "
1526 .arg(fieldsStr, cloud->getName()));
1535 for (
ccHObject* ent : selectedEntities) {
1540 if (mesh ==
nullptr)
continue;
1543 if (cloud ==
nullptr)
continue;
1557 "activated scalar field!")
1572 if (selectedEntities.empty()) {
1578 std::vector<ccPointCloud*> clouds;
1579 bool withScanGrid =
false;
1580 bool withSensor =
false;
1581 std::vector<ccMesh*> meshes;
1585 for (
const auto entity : selectedEntities) {
1588 clouds.push_back(cloud);
1591 withScanGrid =
true;
1599 if (defaultRadius == 0) {
1606 meshes.push_back(mesh);
1609 QString(
"Can't compute normals on sub-meshes! "
1610 "Select the parent mesh instead"));
1615 }
catch (
const std::bad_alloc&) {
1621 if (!clouds.empty()) {
1625 static int s_lastMSTNeighborCount = 6;
1626 static double s_lastMinGridAngle_deg = 1.0;
1634 if (clouds.size() == 1) {
1638 if (!ncDlg.exec())
return false;
1642 bool useGridStructure =
1645 double minGridAngle_deg = s_lastMinGridAngle_deg =
1650 bool orientNormalsWithGrids =
1652 bool orientNormalsWithSensors =
1660 pDlg.setAutoClose(
false);
1664 for (
auto cloud : clouds) {
1665 Q_ASSERT(cloud !=
nullptr);
1668 bool normalsAlreadyOriented =
false;
1670 if (useGridStructure && cloud->gridCount()) {
1673 newCloud->
reserve(cloud->size());
1674 for (
size_t gi=0; gi<cloud->gridCount(); ++gi)
1677 if (scanGrid && scanGrid->indexes.empty())
1684 const int* _indexGrid = scanGrid->indexes.
data();
1685 for (
int j = 0; j < static_cast<int>(scanGrid->h); ++j)
1687 for (
int i = 0; i < static_cast<int>(scanGrid->w); ++i, ++_indexGrid)
1689 if (*_indexGrid >= 0)
1691 unsigned pointIndex =
static_cast<unsigned>(*_indexGrid);
1692 const CCVector3* P = cloud->getPoint(pointIndex);
1704 normalsAlreadyOriented =
true;
1706 cloud->computeNormalsWithGrids(minGridAngle_deg, &pDlg);
1709 normalsAlreadyOriented =
1712 result = cloud->computeNormalsWithOctree(
1714 orientNormals ? preferredOrientation
1716 defaultRadius, &pDlg);
1721 if (
result && orientNormals && !normalsAlreadyOriented) {
1722 if (cloud->gridCount() && orientNormalsWithGrids) {
1725 result = cloud->orientNormalsWithGrids();
1726 }
else if (cloud->hasSensor() && orientNormalsWithSensors) {
1737 for (
unsigned i = 0; i < cloud->getChildrenNumber(); ++i) {
1744 result = cloud->orientNormalsTowardViewPoint(
1745 sensorPosition, &pDlg);
1752 result = cloud->orientNormalsWithMST(mstNeighbors, &pDlg);
1764 if (errors < clouds.size())
1766 "Failed to compute or orient the normals on some "
1767 "clouds! (see console)");
1770 "Failed to compute or orient the normals! (see "
1776 if (!meshes.empty()) {
1777 QMessageBox question(QMessageBox::Question,
"Mesh normals",
1778 "Compute per-vertex normals (smooth) or "
1779 "per-triangle (faceted)?",
1780 QMessageBox::NoButton, parent);
1782 QPushButton* perVertexButton =
1783 question.addButton(
"Per-vertex", QMessageBox::YesRole);
1784 QPushButton* perTriangleButton =
1785 question.addButton(
"Per-triangle", QMessageBox::NoRole);
1789 bool computePerVertexNormals =
1790 (question.clickedButton() == perVertexButton);
1792 for (
auto mesh : meshes) {
1793 Q_ASSERT(mesh !=
nullptr);
1801 mesh->clearTriNormals();
1802 mesh->showNormals(
false);
1803 bool result = mesh->computeNormals(computePerVertexNormals);
1808 QString(
"Failed to compute normals on mesh '%1'")
1809 .arg(mesh->getName()));
1819 for (
ccHObject* ent : selectedEntities) {
1829 bool lockedVertices;
1833 if (lockedVertices) {
1835 ent->getName(), selectedEntities.size() == 1);
1849 if (selectedEntities.empty()) {
1855 const int s_defaultLevel = 6;
1856 int value = QInputDialog::getInt(
1857 parent,
"Orient normals (FM)",
"Octree level", s_defaultLevel, 1,
1859 if (!ok)
return false;
1861 Q_ASSERT(value >= 0 && value <= 255);
1863 unsigned char level =
static_cast<unsigned char>(value);
1866 pDlg.setAutoClose(
false);
1869 for (
ccHObject* entity : selectedEntities) {
1892 "Normals have been oriented: you may still have to globally "
1893 "invert the cloud normals however (Edit > Normals > Invert).");
1901 if (selectedEntities.empty()) {
1907 static unsigned s_defaultKNN = 6;
1908 unsigned kNN =
static_cast<unsigned>(
1909 QInputDialog::getInt(parent,
"Neighborhood size",
"Neighbors",
1910 s_defaultKNN, 1, 1000, 1, &ok));
1911 if (!ok)
return false;
1916 pDlg.setAutoClose(
false);
1919 for (
ccHObject* entity : selectedEntities) {
1944 "Normals have been oriented: you may still have to globally "
1945 "invert the cloud normals however (Edit > Normals > Invert).");
1953 unsigned errorCount = 0;
1955 size_t selNum = selectedEntities.size();
1956 for (
size_t i = 0; i < selNum; ++i) {
1958 bool lockedVertices =
false;
1961 if (lockedVertices) {
1970 bool success =
true;
1988 if (dipSFIndex < 0) {
1990 "[ccEntityAction::convertNormalsTo] Not "
1999 if (dipDirSFIndex < 0)
2002 if (dipDirSFIndex < 0) {
2005 "[ccEntityAction::convertNormalsTo] Not "
2015 Q_ASSERT(dipSF && dipDirSF);
2044 "[ccEntityAction::convertNormalsTo] Internal "
2045 "error: unhandled destination!");
2075 std::unordered_set<ccGenericPointCloud*> clouds;
2078 for (
ccHObject* ent : selectedEntities) {
2080 bool lockedVertices =
false;
2084 if (cloud ==
nullptr) {
2088 if (lockedVertices) {
2090 ent->getName(), selectedEntities.size() == 1);
2093 clouds.insert(cloud);
2100 if (maxBoxSize < 0.0 || maxd > maxBoxSize) maxBoxSize = maxd;
2105 if (clouds.empty() || maxBoxSize < 0.0) {
2107 "[doActionComputeOctree] No eligible entities in selection!");
2112 const double minCellSize =
2116 if (!coDlg.exec())
return false;
2119 pDlg.setAutoClose(
false);
2125 for (
const auto cloud : clouds) {
2135 QElapsedTimer eTimer;
2140 octree = cloud->computeOctree(&pDlg);
2152 CCVector3 C = cloud->getOwnBB().getCenter();
2155 C +
CCVector3(halfBoxWidth, halfBoxWidth,
2158 cloud->deleteOctree();
2161 nullptr, &pDlg) > 0) {
2164 cloud->addChild(proxy);
2173 qint64 elapsedTime_ms = eTimer.elapsed();
2180 static_cast<double>(elapsedTime_ms) / 1000.0);
2181 cloud->setEnabled(
true);
2182 cloud->setRedraw(
true);
2189 QString(
"Octree computation on cloud '%1' failed!")
2190 .arg(cloud->getName()));
2203 for (
ccHObject* ent : selectedEntities) {
2227 ent->setRedraw(
true);
2233 ->getAssociatedCloud() ==
2236 "[doActionClearNormals] Can't remove per-vertex "
2237 "normals on a sub mesh!");
2245 ->unallocateNorms();
2253 bool lockedVertices;
2256 if (lockedVertices) {
2258 ent->getName(), selectedEntities.size() == 1);
2269 pointCloud->unallocateColors();
2270 ent->setRedrawFlagRecursive(
true);
2276 pointCloud->unallocateNorms();
2277 ent->setRedrawFlagRecursive(
true);
2283 pointCloud->deleteScalarField(
2285 ->getCurrentDisplayedScalarFieldIndex());
2286 ent->setRedrawFlagRecursive(
true);
2292 pointCloud->deleteAllScalarFields();
2293 ent->setRedrawFlagRecursive(
true);
2347 if (!poeDlg.exec()) {
2354 switch (distribIndex) {
2357 "Local Statistical Test (Gauss)",
2362 "Local Statistical Test (Weibull)",
2370 if (!sDlg->exec()) {
2371 sDlg->deleteLater();
2378 ScalarType a =
static_cast<ScalarType
>(sDlg->
getParam1());
2379 ScalarType b =
static_cast<ScalarType
>(sDlg->
getParam2());
2380 ScalarType c =
static_cast<ScalarType
>(sDlg->
getParam3());
2382 switch (distribIndex) {
2401 const double pChi2 = sDlg->
getProba();
2405 pDlg.setAutoClose(
false);
2407 for (
ccHObject* ent : selectedEntities) {
2409 if (pc ==
nullptr) {
2416 if (inSF ==
nullptr) {
2421 Q_ASSERT(inSF->capacity() != 0);
2435 if (chi2SfIdx < 0) {
2437 "Couldn't allocate a new scalar field for computing chi2 "
2438 "distances! Try to free some memory ...");
2449 QString(
"Couldn't compute octree for cloud '%1'!")
2455 QElapsedTimer eTimer;
2463 eTimer.elapsed() / 1000.0);
2474 chi2dist *= chi2dist;
2488 sDlg->deleteLater();
2499 if (!pDlg.exec())
return false;
2515 Q_ASSERT(distrib !=
nullptr);
2517 for (
ccHObject* ent : selectedEntities) {
2519 if (pc ==
nullptr) {
2526 if (sf ==
nullptr) {
2533 if (sfValidCount == 0) {
2536 "Scalar field '%1' of cloud %2 has no valid values")
2537 .arg(QString::fromStdString(sf->
getName()))
2542 Q_ASSERT(!sf->empty());
2545 QString description;
2546 const unsigned precision =
2555 QString(
"mean = %1 / std.dev. = %2")
2556 .arg(
normal->getMu(), 0,
'f', precision)
2557 .arg(sqrt(
normal->getSigma2()), 0,
'f',
2568 description = QString(
"a = %1 / b = %2 / shift = %3")
2569 .arg(a, 0,
'f', precision)
2570 .arg(b, 0,
'f', precision)
2573 CVLog::Print(QString(
"[Distribution fitting] Additional "
2574 "Weibull distrib. parameters: mode = "
2575 "%1 / skewness = %2")
2585 description.prepend(QString(
"%1: ").arg(distrib->
getName()));
2587 QString(
"[Distribution fitting] %1").arg(description));
2589 const unsigned numberOfClasses =
static_cast<unsigned>(
2590 ceil(sqrt(
static_cast<double>(pc->
size()))));
2591 std::vector<unsigned> histo;
2592 std::vector<double> npis;
2594 histo.resize(numberOfClasses, 0);
2595 npis.resize(numberOfClasses, 0.0);
2596 }
catch (
const std::bad_alloc&) {
2598 "[Distribution fitting] Not enough memory!");
2604 unsigned finalNumberOfClasses = 0;
2607 distrib, pc, 0, finalNumberOfClasses,
false,
2608 nullptr,
nullptr, histo.data(), npis.data());
2610 if (chi2dist >= 0.0) {
2612 "[Distribution fitting] %s: Chi2 Distance = %f",
2613 distrib->
getName(), chi2dist);
2616 "[Distribution fitting] Failed to compute Chi2 "
2624 unsigned n = pc->
size();
2625 double squareSum = 0;
2626 unsigned counter = 0;
2627 for (
unsigned i = 0; i < n; ++i) {
2630 squareSum +=
static_cast<double>(v) * v;
2636 double rms = sqrt(squareSum / counter);
2638 QString(
"Scalar field RMS = %1").arg(rms));
2644 hDlg->setWindowTitle(
"[Distribution fitting]");
2661 "compute distribution parameters!")
2677 if (selectedEntities.empty())
return false;
2681 int minPoints = 100;
2683 DBL_MIN, 1.0e9, 1, 1000000, eps, minPoints,
2684 8,
"DBScan Cluster", parent);
2686 dlg.doubleSpinBox->setStatusTip(
2687 "Density parameter that is used to find neighbouring points.");
2688 dlg.integerSpinBox->setStatusTip(
2689 "Minimum number of points to form a cluster");
2690 if (!dlg.exec())
return false;
2693 eps = dlg.doubleSpinBox->value();
2694 minPoints = dlg.integerSpinBox->value();
2697 std::vector<std::vector<int>> clusters;
2698 for (
ccHObject* ent : selectedEntities) {
2699 bool lockedVertices =
false;
2701 if (!pc || lockedVertices) {
2703 ent->getName(), selectedEntities.size() == 1);
2706 entities.push_back(pc);
2708 vector<int>::iterator itMax =
2709 std::max_element(clusters[clusters.size() - 1].begin(),
2710 clusters[clusters.size() - 1].end());
2711 int clusterNumber = *itMax + 1;
2714 .arg(clusterNumber));
2717 std::vector<std::vector<ScalarType>> scalarsVector;
2718 ccEntityAction::ConvertToScalarType<int>(clusters, scalarsVector);
2720 "DBSCANClusters")) {
2721 CVLog::Error(
"[ecvEntityAction::DBScanCluster] import sf failed!");
2725 "Clusters information has been imported to scalar field of "
2735 if (selectedEntities.empty())
return false;
2738 if (!dlg.exec())
return false;
2741 double distanceThreshold = dlg.distanceThresholdSpinbox->value();
2742 int ransacN = dlg.ransacNSpinBox->value();
2743 int iterations = dlg.iterationsSpinBox->value();
2744 bool extractInliers = dlg.inliersCheckBox->isChecked();
2745 bool extractOutliers = dlg.outliersCheckBox->isChecked();
2747 outEntities.clear();
2748 for (
ccHObject* ent : selectedEntities) {
2749 bool lockedVertices =
false;
2751 if (!pc || lockedVertices) {
2753 ent->getName(), selectedEntities.size() == 1);
2757 std::vector<size_t> inliers;
2758 Eigen::Vector4d planeModel;
2759 std::tie(planeModel, inliers) =
2760 pc->
SegmentPlane(distanceThreshold, ransacN, iterations);
2762 CVLog::Print(QString(
"[%1] Plane model: %2x + %3y + %4z + %5 = 0")
2763 .arg(ent->getName())
2767 .arg(planeModel(3)));
2768 if (extractInliers) {
2776 outEntities.push_back(cloud);
2779 if (extractOutliers) {
2785 outEntities.push_back(cloud);
2789 return !outEntities.empty();
2797 if (selectedEntities.empty())
return false;
2799 outEntities.clear();
2800 for (
ccHObject* ent : selectedEntities) {
2801 bool lockedVertices =
false;
2803 if (!pc || lockedVertices) {
2805 ent->getName(), selectedEntities.size() == 1);
2809 std::shared_ptr<ccMesh> mesh;
2810 std::vector<size_t> pt_map;
2814 QString(
"[ccEntityAction::ConvexHull] "
2815 "computing convex hull failed from cloud [%1]! ")
2821 outMesh->CreateInternalCloud();
2826 outMesh->
setName(
"ConvexHull");
2827 outEntities.push_back(outMesh);
2830 return !outEntities.empty();
2839 if (selectedEntities.empty())
return false;
2841 outEntities.clear();
2846 voxelSize = QInputDialog::getDouble(parent,
"voxel down sampling",
2847 "Voxel Size:", voxelSize, DBL_MIN,
2850 for (
ccHObject* ent : selectedEntities) {
2851 bool lockedVertices =
false;
2853 if (!pc || lockedVertices) {
2855 ent->getName(), selectedEntities.size() == 1);
2861 outEntities.push_back(out);
constexpr ScalarType NAN_VALUE
NaN as a ScalarType value.
Vector3Tpl< PointCoordinateType > CCVector3
Default 3D Vector.
float PointCoordinateType
Type of the coordinates of a (N-D) point.
std::vector< PCLPointField > fields
cmdLineReadable * params[]
static bool Warning(const char *format,...)
Prints out a formatted warning message in console.
static bool Print(const char *format,...)
Prints out a formatted message in console.
static bool Error(const char *format,...)
Display an error dialog with formatted message.
Array of RGB colors for each point.
ccHObjectContext removeObjectTemporarilyFromDBTree(ccHObject *obj) override
Removes object temporarily from DB tree.
void putObjectBackIntoDBTree(ccHObject *obj, const ccHObjectContext &context) override
Adds back object to DB tree.
Type & getValue(size_t index)
bool reserveSafe(size_t count)
Reserves memory (no exception thrown)
void addElement(const Type &value)
Generic dialog to query 3 (double) values.
Dialog to input 2 values with custom labels.
Dialog to define a color gradient (default, with 2 colors, banding, etc.)
double getBandingFrequency() const
Returns the frequency of the gradient ('Banding' mode)
GradientType
Gradient types.
void getColors(QColor &first, QColor &second) const
Returns the two colors of the gradient ('TwoColors' mode)
unsigned char getDimension() const
Returns the ramp dimension.
GradientType getType() const
Returns selected gradient type.
Dialog to change the color levels.
Color scale element: one value + one color.
static ccColorScale::Shared Create(const QString &name)
Creates a new color scale (with auto-generated unique id)
QSharedPointer< ccColorScale > Shared
Shared pointer type.
Color scales manager/container.
static ccColorScale::Shared GetDefaultScale(DEFAULT_SCALES scale=BGYR)
Returns a pre-defined color scale (static shortcut)
Dialog for octree computation.
ComputationMode getMode() const
Returns octree computation mode.
double getMinCellSize() const
Returns cell size at max level.
ccBBox getCustomBBox() const
Returns custom bbox.
virtual bool hasDisplayedScalarField() const
Returns whether an active scalar field is available or not.
virtual bool hasColors() const
Returns whether colors are enabled or not.
virtual void setVisible(bool state)
Sets entity visibility.
virtual bool hasNormals() const
Returns whether normals are enabled or not.
virtual void setRedraw(bool state)
Sets entity redraw mode.
virtual void showNormals(bool state)
Sets normals visibility.
virtual void showColors(bool state)
Sets colors visibility.
virtual void showSF(bool state)
Sets active scalarfield visibility.
virtual bool hasScalarFields() const
Returns whether one or more scalar fields are instantiated.
Dialog to choose which dimension(s) (X, Y or Z) should be exported as SF(s)
bool exportX() const
Returns whether X dimension should be exported.
bool exportZ() const
Returns whether Z dimension should be exported.
bool exportY() const
Returns whether Y dimension should be exported.
void setColor(const ecvColor::Rgb &rgb)
Sets the facet unique color.
T * data()
Returns a pointer to internal data.
ccGLMatrixTpl< T > inverse() const
Returns inverse transformation.
Double version of ccGLMatrixTpl.
void showNormals(bool state) override
Sets normals visibility.
virtual void showMaterials(bool state)
Sets whether textures should be displayed or not.
A 3D cloud interface with associated features (color, normals, octree, etc.)
virtual ccOctree::Shared computeOctree(cloudViewer::GenericProgressCallback *progressCb=nullptr, bool autoAddChild=true)
Computes the cloud octree.
ccBBox getOwnBB(bool withGLFeatures=false) override
Returns the entity's own bounding-box.
virtual ccOctree::Shared getOctree() const
Returns the associated octree (if any)
Generic primitive interface.
virtual void setColor(const ecvColor::Rgb &col)
Sets primitive color (shortcut)
static ccMesh * ToMesh(ccHObject *obj)
Converts current object to ccMesh (if possible)
static ccPointCloud * ToPointCloud(ccHObject *obj, bool *isLockedVertices=nullptr)
Converts current object to 'equivalent' ccPointCloud.
static ccGenericPrimitive * ToPrimitive(ccHObject *obj)
Converts current object to ccGenericPrimitive (if possible)
static ccPolyline * ToPolyline(ccHObject *obj)
Converts current object to ccPolyline (if possible)
static ccGenericPointCloud * ToGenericPointCloud(ccHObject *obj, bool *isLockedVertices=nullptr)
Converts current object to 'equivalent' ccGenericPointCloud.
static ccSensor * ToSensor(ccHObject *obj)
Converts current object to ccSensor (if possible)
static ccFacet * ToFacet(ccHObject *obj)
Converts current object to ccFacet (if possible)
Hierarchical CLOUDVIEWER Object.
bool isAncestorOf(const ccHObject *anObject) const
Returns true if the current object is an ancestor of the specified one.
unsigned getChildrenNumber() const
Returns the number of children.
virtual bool addChild(ccHObject *child, int dependencyFlags=DP_PARENT_OF_OTHER, int insertIndex=-1)
Adds a child.
virtual void toggleSF_recursive()
void setRedrawFlagRecursive(bool redraw=false)
virtual void toggleVisibility_recursive()
virtual void toggleColors_recursive()
ccHObject * getParent() const
Returns parent object.
virtual void toggleNormals_recursive()
virtual void toggleShowName_recursive()
std::vector< ccHObject * > Container
Standard instances container (for children, etc.)
ccHObject * getChild(unsigned childPos) const
Returns the ith child.
Encapsulating dialog for ccHistogramWindow.
ccHistogramWindow * window()
Returns encapsulated ccHistogramWindow.
void setTitle(const QString &str)
Sets title.
void setCurveValues(const std::vector< double > &curveValues)
Sets overlay curve values.
void setColorScale(ccColorScale::Shared scale)
Sets gradient color scale.
void refresh()
Updates the display.
void setColorScheme(HISTOGRAM_COLOR_SCHEME scheme)
Sets how the gradient bars should be colored.
void fromBinArray(const std::vector< unsigned > &histoValues, double minVal, double maxVal)
void setAxisLabels(const QString &xLabel, const QString &yLabel)
Sets axis labels.
Dialog for generic interpolation algorithms.
void setInterpolationMethod(ccPointCloudInterpolator::Parameters::Method method)
ccPointCloudInterpolator::Parameters::Method getInterpolationMethod() const
ccPointCloudInterpolator::Parameters::Algo getInterpolationAlgorithm() const
void setInterpolationAlgorithm(ccPointCloudInterpolator::Parameters::Algo algo)
Dialog to select one or multiple items.
void getSelectedIndexes(std::vector< int > &indexes) const
Returns selected indexes (multi-selection mode)
void setItems(const QStringList &items, int defaultSelectedIndex=0)
Sets the list of items.
bool hasMaterials() const override
bool processScalarField(MESH_SCALAR_FIELD_PROCESS process)
bool convertMaterialsToVertexColors()
Converts materials to vertex colors.
bool hasColors() const override
Returns whether colors are enabled or not.
MESH_SCALAR_FIELD_PROCESS
Mesh scalar field processes.
void clearTriNormals()
Removes per-triangle normals.
ccGenericPointCloud * getAssociatedCloud() const override
Returns the vertices cloud.
bool hasNormals() const override
Returns whether normals are enabled or not.
void invertNormals()
Inverts normals (if any)
bool hasTriNormals() const override
Returns whether the mesh has per-triangle normals.
Dialog for normal computation.
bool useScanGridsForComputation() const
Returns whether scan grids should be used for computation.
int getMSTNeighborCount() const
Returns the number of neighbors for Minimum Spanning Tree (MST)
bool orientNormals() const
Returns whether normals should be oriented or not.
void setMSTNeighborCount(int n)
Sets the number of neighbors for Minimum Spanning Tree (MST)
ccNormalVectors::Orientation getPreferredOrientation() const
Returns the preferred orientation (if any)
double getMinGridAngle_deg() const
Returns the min angle for grid triangles.
bool useScanGridsForOrientation() const
Returns whether scan grids should be used for normals orientation.
void setMinGridAngle_deg(double value)
Sets the min angle for grid triangles.
CV_LOCAL_MODEL_TYPES getLocalModel() const
Returns the local model chosen for normal computation.
void setCloud(ccPointCloud *cloud)
Sets the currently selected cloud (required for 'auto' feature)
bool useSensorsForOrientation() const
Returns whether scan grids should be used for normals computation.
void setRadius(PointCoordinateType radius)
Sets default value for local neighbourhood radius.
void setPreferredOrientation(ccNormalVectors::Orientation orientation)
Sets the preferred orientation.
bool useMSTOrientation() const
void setLocalModel(CV_LOCAL_MODEL_TYPES model)
Sets the local model chosen for normal computation.
PointCoordinateType getRadius() const
Returns local neighbourhood radius.
static PointCoordinateType GuessNaiveRadius(ccGenericPointCloud *cloud)
Orientation
'Default' orientations
@ UNDEFINED
Undefined (no orientation is required)
virtual bool isLocked() const
Returns whether the object is locked or not.
virtual QString getName() const
Returns object name.
bool isA(CV_CLASS_ENUM type) const
virtual void setName(const QString &name)
Sets object name.
virtual void setEnabled(bool state)
Sets the "enabled" property.
bool isKindOf(CV_CLASS_ENUM type) const
virtual void toggleActivation()
Toggles the "enabled" property.
QSharedPointer< ccOctree > Shared
Shared pointer.
Dialog to assign roles to two entities (e.g. compared/reference)
ccHObject * getFirstEntity()
Returns the first entity (new order)
Minimal dialog to pick one element in a list (combox box)
void addElement(const QString &elementName)
Add an element to the combo box.
int getSelectedIndex()
Returns the combo box current index (after completion)
void setDefaultIndex(int index)
Sets the combo box default index.
static bool InterpolateScalarFieldsFrom(ccPointCloud *destCloud, ccPointCloud *srccloud, const std::vector< int > &sfIndexes, const Parameters ¶ms, cloudViewer::GenericProgressCallback *progressCb=0, unsigned char octreeLevel=0)
Interpolate scalar fields from another cloud.
A 3D cloud and its associated features (color, normals, scalar fields, etc.)
bool applyFilterToRGB(PointCoordinateType sigma, PointCoordinateType sigmaSF, RgbFilterOptions filterParams, cloudViewer::GenericProgressCallback *progressCb=nullptr)
Applies a spatial Gaussian filter on RGB colors.
void setCurrentDisplayedScalarField(int index)
Sets the currently displayed scalar field.
bool setRGBColorByBanding(unsigned char dim, double freq)
Assigns color to points by 'banding'.
bool hasSensor() const
Returns whether the mesh as an associated sensor or not.
bool convertNormalToRGB()
Converts normals to RGB colors.
std::tuple< Eigen::Vector4d, std::vector< size_t > > SegmentPlane(const double distance_threshold=0.01, const int ransac_n=3, const int num_iterations=100) const
Segment ccPointCloud plane using the RANSAC algorithm.
bool convertRGBToGreyScale()
Converts RGB to grey scale colors.
double ComputeResolution() const
int addScalarField(const char *uniqueName) override
Creates a new scalar field and registers it.
bool hasNormals() const override
Returns whether normals are enabled or not.
bool enhanceRGBWithIntensitySF(int sfIdx, bool useCustomIntensityRange=false, double minI=0.0, double maxI=1.0)
bool resizeTheRGBTable(bool fillWithWhite=false)
Resizes the RGB colors array.
void invalidateBoundingBox() override
Invalidates bounding box.
bool orientNormalsWithFM(unsigned char level, ecvProgressDialog *pDlg=nullptr)
Orient normals with Fast Marching.
bool reserve(unsigned numberOfPoints) override
Reserves memory for all the active features.
bool exportCoordToSF(bool exportDims[3])
Exports the specified coordinate dimension(s) to scalar field(s)
std::vector< int > ClusterDBSCAN(double eps, size_t min_points, bool print_progress=false) const
Cluster ccPointCloud using the DBSCAN algorithm Ester et al., "A Density-Based Algorithm for Discover...
bool orientNormalsWithMST(unsigned kNN=6, ecvProgressDialog *pDlg=nullptr)
Orient the normals with a Minimum Spanning Tree.
bool colorize(float r, float g, float b)
Multiplies all color components of all points by coefficients.
bool hasDisplayedScalarField() const override
Returns whether an active scalar field is available or not.
bool convertNormalToDipDirSFs(ccScalarField *dipSF, ccScalarField *dipDirSF)
Converts normals to two scalar fields: 'dip' and 'dip direction'.
bool exportNormalToSF(bool exportDims[3])
Exports the specified normal dimension(s) to scalar field(s)
bool setCoordFromSF(bool importDims[3], cloudViewer::ScalarField *sf, PointCoordinateType defaultValueForNaN)
Sets coordinate(s) from a scalar field.
int getCurrentDisplayedScalarFieldIndex() const
Returns the currently displayed scalar field index (or -1 if none)
bool hasColors() const override
Returns whether colors are enabled or not.
static ccPointCloud * From(const cloudViewer::GenericIndexedCloud *cloud, const ccGenericPointCloud *sourceCloud=nullptr)
Creates a new point cloud object from a GenericIndexedCloud.
bool setRGBColorByHeight(unsigned char heightDim, ccColorScale::Shared colorScale)
Assigns color to points proportionnaly to their 'height'.
void deleteScalarField(int index) override
Deletes a specific scalar field.
void setPointColor(size_t pointIndex, const ecvColor::Rgb &col)
Sets a particular point color.
ccScalarField * getCurrentDisplayedScalarField() const
Returns the currently displayed scalar (or 0 if none)
std::shared_ptr< ccPointCloud > VoxelDownSample(double voxel_size)
Function to downsample input ccPointCloud into output ccPointCloud with a voxel.
bool setRGBColor(ColorCompType r, ColorCompType g, ColorCompType b)
Set a unique color for the whole cloud (shortcut)
bool hasScalarFields() const override
Returns whether one or more scalar fields are instantiated.
std::tuple< std::shared_ptr< ccMesh >, std::vector< size_t > > ComputeConvexHull() const
Function that computes the convex hull of the point cloud using qhull.
bool setRGBColorWithCurrentScalarField(bool mixWithExistingColor=false)
Sets RGB colors with current scalar field (values & parameters)
void invertNormals()
Inverts normals (if any)
size_t gridCount() const
Returns the number of associated grids.
const ecvColor::Rgb & getColor() const
Returns the polyline color.
void setColor(const ecvColor::Rgb &col)
Sets the polyline color.
bool apply(ccPointCloud *cloud)
Applies operation on a given cloud.
bool getCompositeStatus()
Returns if to export Composite channel as SF.
bool getBStatus()
Returns if to export B channel as SF.
bool getRStatus()
Returns if to export R channel as SF.
bool getGStatus()
Returns if to export G channel as SF.
A scalar field associated to display-related parameters.
const ccColorScale::Shared & getColorScale() const
Returns associated color scale.
void setMinDisplayed(ScalarType val)
Sets the minimum displayed value.
void setColorScale(ccColorScale::Shared scale)
Sets associated color scale.
void setSymmetricalScale(bool state)
Sets whether the color scale should be symmetrical or not.
void computeMinAndMax() override
Determines the min and max values.
void setSaturationStart(ScalarType val)
Sets the value at which to start color gradient.
Generic sensor interface.
bool getActiveAbsoluteCenter(CCVector3 &vec) const
Gets currently active absolute position.
Dialog for the Local Statistical Test tool.
int getNeighborsNumber() const
Returns the number of neighbors.
double getParam1() const
Returns 1st parameter value.
double getParam2() const
Returns 2nd parameter value.
double getParam3() const
Returns 3rd parameter value.
double getProba() const
Returns the associated probability.
double getDiagNormd() const
Returns diagonal length (double precision)
const Vector3Tpl< T > & maxCorner() const
Returns max corner (const)
const Vector3Tpl< T > & minCorner() const
Returns min corner (const)
bool isValid() const
Returns whether bounding box is valid or not.
static const int MAX_OCTREE_LEVEL
Max octree subdivision level.
virtual void clear()
Clears the octree.
int build(GenericProgressCallback *progressCb=nullptr)
Builds the structure.
virtual unsigned size() const =0
Returns the number of points.
A generic class to handle a probability distribution.
virtual bool computeParameters(const ScalarContainer &values)=0
Computes the distribution parameters from a set of values.
virtual const char * getName() const =0
Returns distribution name.
The Normal/Gaussian statistical distribution.
bool setParameters(ScalarType _mu, ScalarType _sigma2)
Sets the distribution parameters.
ScalarField * getCurrentOutScalarField() const
Returns the scalar field currently associated to the cloud output.
int getScalarFieldIndexByName(const char *name) const
Returns the index of a scalar field represented by its name.
void setCurrentOutScalarField(int index)
Sets the OUTPUT scalar field.
ScalarField * getScalarField(int index) const
Returns a pointer to a specific scalar field.
unsigned getNumberOfScalarFields() const
Returns the number of associated (and active) scalar fields.
void setCurrentScalarField(int index)
Sets both the INPUT & OUTPUT scalar field.
void addPoint(const CCVector3 &P)
Adds a 3D point to the database.
unsigned size() const override
const char * getScalarFieldName(int index) const
Returns the name of a specific scalar field.
ScalarType getPointScalarValue(unsigned pointIndex) const override
void setCurrentInScalarField(int index)
Sets the INPUT scalar field.
ScalarField * getCurrentInScalarField() const
Returns the scalar field currently associated to the cloud input.
bool isClosed() const
Returns whether the polyline is closed or not.
A simple scalar field (to be associated to a point cloud)
virtual void computeMinAndMax()
Determines the min and max values.
ScalarType getMin() const
Returns the minimum value.
std::size_t countValidValues() const
Returns the number of valid values in this scalar field.
ScalarType & getValue(std::size_t index)
void setValue(std::size_t index, ScalarType value)
const char * getName() const
Returns scalar field name.
void setName(const char *name)
Sets scalar field name.
static bool ValidValue(ScalarType value)
Returns whether a scalar value is valid or not.
unsigned currentSize() const
ScalarType getMax() const
Returns the maximum value.
The Weibull statistical parametric distribution.
ScalarType getValueShift() const
Returns the distribution value shift.
bool setParameters(ScalarType a, ScalarType b, ScalarType valueShift=0)
Sets the distribution parameters.
bool getParameters(ScalarType &a, ScalarType &b) const
Returns the distribution parameters.
double computeSkewness() const
Returns the distribution 'skewness'.
double computeMode() const
Returns the distribution 'mode'.
Dialog to input 2 values with custom labels.
static Rgb Random(bool lightOnly=true)
Generates a random color.
static const ParamStruct & Parameters()
Returns the stored values of each parameter.
Main application interface (for plugins)
virtual QMainWindow * getMainWindow()=0
Returns main window.
Graphical progress indicator (thread-safe)
virtual void start() override
virtual void setInfo(const char *infoStr) override
Notifies some information about the ongoing process.
virtual void setMethodTitle(const char *methodTitle) override
Notifies the algorithm title.
unsigned char ColorCompType
Default color components type (R,G and B)
#define CC_DEFAULT_ID_SF_NAME
#define CC_DEFAULT_DIP_SF_NAME
#define CC_CHI2_DISTANCES_DEFAULT_SF_NAME
#define CC_DEFAULT_DIP_DIR_SF_NAME
void ConvertToGroup(const ccHObject::Container &origin, ccHObject &dest, int dependencyFlags=ccHObject::DP_NONE)
Puts all entities inside a container in a group.
cloudViewer object type flags
constexpr QRegularExpression::PatternOption CaseInsensitive
bool VoxelSampling(const ccHObject::Container &selectedEntities, ccHObject::Container &outEntities, QWidget *parent)
bool exportNormalToSF(const ccHObject::Container &selectedEntities, QWidget *parent, bool *exportDimensions)
bool invertNormals(const ccHObject::Container &selectedEntities)
bool sfSetAsCoord(const ccHObject::Container &selectedEntities, QWidget *parent)
bool statisticalTest(const ccHObject::Container &selectedEntities, QWidget *parent)
static QString GetFirstAvailableSFName(const ccPointCloud *cloud, const QString &baseName)
bool sfRename(const ccHObject::Container &selectedEntities, QWidget *parent)
bool convertTextureToColor(const ccHObject::Container &selectedEntities, QWidget *parent)
bool computeOctree(const ccHObject::Container &selectedEntities, QWidget *parent)
bool orientNormalsFM(const ccHObject::Container &selectedEntities, QWidget *parent)
bool sfFromColor(const ccHObject::Container &selectedEntities, QWidget *parent)
bool changeColorLevels(const ccHObject::Container &selectedEntities, QWidget *parent)
bool computeStatParams(const ccHObject::Container &selectedEntities, QWidget *parent)
bool orientNormalsMST(const ccHObject::Container &selectedEntities, QWidget *parent)
bool interpolateColors(const ccHObject::Container &selectedEntities, QWidget *parent)
Interpolate colors from on entity and transfer them to another one.
bool sfBilateralFilter(const ccHObject::Container &selectedEntities, QWidget *parent)
bool rgbToGreyScale(const ccHObject::Container &selectedEntities)
bool ConvexHull(const ccHObject::Container &selectedEntities, ccHObject::Container &outEntities, QWidget *parent)
bool clearProperty(ccHObject::Container selectedEntities, CLEAR_PROPERTY property, QWidget *parent)
bool sfGaussianFilter(const ccHObject::Container &selectedEntities, ccPointCloud::RgbFilterOptions filterParams, QWidget *parent)
bool sfAddIdField(const ccHObject::Container &selectedEntities)
bool toggleProperty(const ccHObject::Container &selectedEntities, TOGGLE_PROPERTY property)
bool enhanceRGBWithIntensities(const ccHObject::Container &selectedEntities, QWidget *parent)
bool setColorGradient(const ccHObject::Container &selectedEntities, QWidget *parent)
bool exportCoordToSF(const ccHObject::Container &selectedEntities, QWidget *parent)
bool setColor(ccHObject::Container selectedEntities, bool colorize, QWidget *parent)
bool interpolateSFs(const ccHObject::Container &selectedEntities, ecvMainAppInterface *app)
Interpolate scalar fields from on entity and transfer them to another one.
bool RansacSegmentation(const ccHObject::Container &selectedEntities, ccHObject::Container &outEntities, QWidget *parent)
bool convertNormalsTo(const ccHObject::Container &selectedEntities, NORMAL_CONVERSION_DEST dest)
Converts a cloud's normals.
bool importToSF(const ccHObject::Container &selectedEntities, const std::vector< std::vector< ScalarType >> &scalarsVector, const std::string &name)
bool sfArithmetic(const ccHObject::Container &selectedEntities, QWidget *parent)
bool DBScanCluster(const ccHObject::Container &selectedEntities, QWidget *parent)
static PointCoordinateType GetDefaultValueForNaN(PointCoordinateType minSFValue, QWidget *parent)
NORMAL_CONVERSION_DEST
Normals conversion destinations.
bool processMeshSF(const ccHObject::Container &selectedEntities, ccMesh::MESH_SCALAR_FIELD_PROCESS process, QWidget *parent)
bool sfConvertToRandomRGB(const ccHObject::Container &selectedEntities, QWidget *parent)
bool computeNormals(const ccHObject::Container &selectedEntities, QWidget *parent)
bool sfConvertToRGB(const ccHObject::Container &selectedEntities, QWidget *parent)
bool rgbGaussianFilter(const ccHObject::Container &selectedEntities, ccPointCloud::RgbFilterOptions filterParams, QWidget *parent)
PointCoordinateType GetDefaultCloudKernelSize(ccGenericPointCloud *cloud, unsigned knn)
Returns a default first guess for algorithms kernel size (one cloud)
MiniVec< float, N > ceil(const MiniVec< float, N > &a)
constexpr Rgb white(MAX, MAX, MAX)
Rgb FromQColor(QColor qColor)
Conversion from QColor.
void DisplayLockedVerticesWarning(const QString &meshName, bool displayAsError)
Display a warning or error for locked verts.
void swap(cloudViewer::core::SmallVectorImpl< T > &LHS, cloudViewer::core::SmallVectorImpl< T > &RHS)
Implement std::swap in terms of SmallVector swap.
Generic interpolation parameters.
QSharedPointer< Grid > Shared
Shared type.
unsigned char burntOutColorThreshold
RGB_FILTER_TYPES filterType
unsigned displayedNumPrecision
Displayed numbers precision.
Backup "context" for an object.