18 #include <Eigen/Dense>
43 #include <QCoreApplication>
44 #include <QElapsedTimer>
45 #include <QSharedPointer>
51 #include <unordered_map>
59 m_sfColorScaleDisplayed(
false),
60 m_currentDisplayedScalarField(
nullptr),
61 m_currentDisplayedScalarFieldIndex(-1),
62 m_visibilityCheckEnabled(
false),
76 const std::string&
name)
88 unsigned n = cloud->
size();
94 "[ccPointCloud::From] Not enough memory to duplicate "
101 for (
unsigned i = 0; i < n; i++) {
119 unsigned n = cloud->
size();
125 "[ccPointCloud] Not enough memory to duplicate cloud!");
130 for (
unsigned i = 0; i < n; i++) {
144 const std::vector<size_t>& indices,
147 assert(indices.size() <= sourceSize);
148 if (indices.size() == 0) {
154 invert ?
static_cast<unsigned int>(sourceSize - indices.size())
155 :
static_cast<unsigned int>(indices.size());
157 std::vector<bool> mask = std::vector<bool>(sourceSize, invert);
158 for (
size_t i : indices) {
163 unsigned sfCount =
sourceCloud->getNumberOfScalarFields();
168 "[ccPointCloud::From] Not enough memory to duplicate "
174 for (
unsigned i = 0; i < sourceSize; i++) {
184 "[ccPointCloud::From] Not enough "
185 "memory to duplicate cloud color!");
198 "[ccPointCloud::From] Not enough "
199 "memory to duplicate cloud normal!");
208 for (
unsigned k = 0; k < sfCount; ++k) {
211 static_cast<int>(k)));
217 assert(sfIndex >= 0);
228 static_cast<ScalarType
>(sf->
getValue(i)));
237 for (
unsigned k = 0; k < sfCount; ++k) {
252 sourceCloud->getCurrentDisplayedScalarFieldIndex());
260 std::vector<ccPointCloud::Grid::Shared>& grids) {
262 unsigned cellCount = scanGrid->w * scanGrid->h;
263 scanGrid->validCount = 0;
264 scanGrid->minValidIndex = -1;
265 scanGrid->maxValidIndex = -1;
266 int* _gridIndex = scanGrid->indexes.data();
267 for (
size_t j = 0; j < cellCount; ++j, ++_gridIndex) {
268 if (*_gridIndex >= 0) {
269 assert(
static_cast<size_t>(*_gridIndex) < newIndexMap.size());
270 *_gridIndex = newIndexMap[*_gridIndex];
271 if (*_gridIndex >= 0) {
272 if (scanGrid->validCount) {
273 scanGrid->minValidIndex =
274 std::min(scanGrid->minValidIndex,
275 static_cast<unsigned>(*_gridIndex));
276 scanGrid->maxValidIndex =
277 std::max(scanGrid->maxValidIndex,
278 static_cast<unsigned>(*_gridIndex));
280 scanGrid->minValidIndex = scanGrid->maxValidIndex =
281 static_cast<unsigned>(*_gridIndex);
283 ++scanGrid->validCount;
293 bool withChildEntities )
const {
299 static_cast<const GenericIndexedCloud*
>(
this)) {
300 CVLog::Error(
"[ccPointCloud::partialClone] Invalid parameters");
304 static constexpr
const char* DefaultSuffix =
".extract";
306 if (!cloneName.endsWith(
309 cloneName += DefaultSuffix;
319 result->importParametersFrom(
this);
322 unsigned selectionSize = selection->
size();
323 if (selectionSize != 0) {
324 if (!
result->reserveThePointsTable(selectionSize)) {
326 "[ccPointCloud::partialClone] Not enough memory to "
334 for (
unsigned i = 0; i < selectionSize; i++) {
342 if (
result->reserveTheRGBTable()) {
343 for (
unsigned i = 0; i < selectionSize; i++) {
350 "[ccPointCloud::partialClone] Not enough memory to "
358 if (
result->reserveTheNormsTable()) {
359 for (
unsigned i = 0; i < selectionSize; i++) {
366 "[ccPointCloud::partialClone] Not enough memory to "
374 if (
result->reserveTheFWFTable()) {
376 for (
unsigned i = 0; i < selectionSize; i++) {
380 if (!
result->fwfDescriptors().contains(
383 result->fwfDescriptors().insert(
387 result->waveforms().push_back(w);
391 }
catch (
const std::bad_alloc&) {
393 "[ccPointCloud::partialClone] Not enough memory to "
394 "copy waveform signals!");
400 "[ccPointCloud::partialClone] Not enough memory to "
401 "copy waveform signals!");
409 for (
unsigned k = 0; k < sfCount; ++k) {
420 result->getScalarField(sfIdx));
421 assert(currentScalarField);
422 if (currentScalarField->
resizeSafe(selectionSize)) {
427 for (
unsigned i = 0; i < selectionSize; i++)
440 result->deleteScalarField(sfIdx);
442 QString(
"[ccPointCloud::partialClone] Not "
443 "enough memory to copy scalar "
457 int sfIdx =
result->getScalarFieldIndexByName(
460 result->setCurrentDisplayedScalarField(sfIdx);
462 result->setCurrentDisplayedScalarField(
463 static_cast<int>(copiedSFCount) - 1);
470 std::vector<int> newIndexMap;
471 if (
gridCount() != 0 || withChildEntities) {
474 newIndexMap.resize(
size(), -1);
475 for (
unsigned i = 0; i < selectionSize; i++) {
478 }
catch (
const std::bad_alloc&) {
485 assert(newIndexMap.size() ==
size());
488 std::vector<Grid::Shared> newGrids;
490 for (
size_t i = 0; i <
gridCount(); ++i) {
492 if (scanGrid->validCount !=
507 if (scanGrid->validCount) {
508 result->addGrid(scanGrid);
511 }
catch (
const std::bad_alloc&) {
514 QString(
"[ccPointCloud::partialClone] Not enough "
515 "memory to copy the grid structure(s)"));
519 if (withChildEntities) {
520 assert(newIndexMap.size() ==
size());
553 bool ignoreChildren ) {
556 "[ccPointCloud::clone] Invalid destination cloud provided! Not "
557 "a ccPointCloud...");
565 bool ignoreChildren ) {
577 result->setCurrentDisplayedScalarField(
581 result->importParametersFrom(
this);
589 if (
this == &cloud) {
632 unsigned pointCountBefore,
633 bool ignoreChildren ) {
636 unsigned addedPoints = addedCloud->
size();
638 if (!
reserve(pointCountBefore + addedPoints)) {
639 CVLog::Error(
"[ccPointCloud::append] Not enough memory!");
649 if (
size() == pointCountBefore) {
654 for (
unsigned i = 0; i < addedPoints; i++) {
670 for (
unsigned i = 0; i < addedPoints; i++) {
679 for (
unsigned i = 0; i < pointCountBefore; i++) {
684 "[ccPointCloud::fusion] Not enough memory: failed "
685 "to allocate colors!");
692 for (
unsigned i = 0; i < addedPoints; i++) {
707 for (
unsigned i = 0; i < addedPoints; i++) {
716 for (
unsigned i = 0; i < pointCountBefore; i++) {
721 "[ccPointCloud::fusion] Not enough memory: failed "
722 "to allocate normals!");
729 for (
unsigned i = 0; i < addedPoints; i++) {
739 if (!addedCloud->
hasFWF()) {
741 for (
unsigned i = 0; i < addedPoints; i++) {
748 uint64_t fwfDataOffset = 0;
752 for (
unsigned i = 0; i < pointCountBefore; i++) {
760 "[ccPointCloud::fusion] Not enough memory: failed "
761 "to allocate waveforms!");
769 addedCloud->
fwfData()->size());
770 mergedContainer->insert(mergedContainer->end(),
773 mergedContainer->insert(mergedContainer->end(),
774 addedCloud->
fwfData()->begin(),
777 fwfDataOffset = addedCloud->
fwfData()->size();
778 }
catch (
const std::bad_alloc&) {
780 delete mergedContainer;
781 mergedContainer =
nullptr;
783 "[ccPointCloud::fusion] Not enough memory: failed "
784 "to merge waveform containers!");
791 size_t lostWaveformCount = 0;
794 QMap<uint8_t, uint8_t> descriptorIDMap;
799 assert(newKeyCount < 256);
808 std::queue<uint8_t> freeDescriptorIDs;
809 for (uint8_t k = 0; k < 255; ++k) {
811 freeDescriptorIDs.push(k);
813 if (freeDescriptorIDs.size() == newKeyCount) {
822 if (freeDescriptorIDs.empty()) {
824 "[ccPointCloud::fusion] Not enough "
825 "free FWF descriptor IDs on "
826 "destination cloud: some waveforms "
827 "won't be imported!");
830 uint8_t newKey = freeDescriptorIDs.front();
831 freeDescriptorIDs.pop();
832 descriptorIDMap.insert(
843 descriptorIDMap.insert(
852 }
catch (
const std::bad_alloc&) {
856 "[ccPointCloud::fusion] Not enough memory: failed "
857 "to copy waveform descriptors!");
862 for (
unsigned i = 0; i < addedPoints; i++) {
864 if (descriptorIDMap.contains(
885 if (lostWaveformCount) {
887 QString(
"[ccPointCloud::fusion] %1 waveform(s) "
888 "were lost in the fusion process")
889 .arg(lostWaveformCount));
898 if (sfCount != 0 || newSFCount != 0) {
899 std::vector<bool> sfUpdated(sfCount,
false);
902 for (
unsigned k = 0; k < newSFCount; ++k) {
912 assert(sameSF && sameSF->capacity() >=
913 pointCountBefore + addedPoints);
919 for (
unsigned i = 0; i < addedPoints; i++) {
929 assert(sfIdx <
static_cast<int>(sfCount));
930 sfUpdated[sfIdx] =
true;
937 if (newSF->
resizeSafe(pointCountBefore + addedPoints,
true,
940 for (
unsigned i = 0; i < addedPoints; i++) {
941 newSF->
setValue(pointCountBefore + i,
955 "[ccPointCloud::fusion] Not enough memory: "
956 "failed to allocate a copy of scalar field "
965 for (
unsigned j = 0; j < sfCount; ++j) {
973 ScalarType NaN = sf->
NaN();
974 for (
unsigned i = 0; i < addedPoints; i++) {
1007 (
gridCount() != 0 || pointCountBefore == 0)) {
1009 for (
size_t i = 0; i < addedCloud->
gridCount(); ++i) {
1012 otherGrid->validCount != 0)
1019 unsigned cellCount =
grid->w *
grid->h;
1020 int* _gridIndex =
grid->indexes.data();
1021 for (
size_t j = 0; j < cellCount; ++j, ++_gridIndex) {
1022 if (*_gridIndex >= 0) {
1025 static_cast<int>(pointCountBefore);
1030 grid->minValidIndex += pointCountBefore;
1031 grid->maxValidIndex += pointCountBefore;
1035 }
catch (
const std::bad_alloc&) {
1039 "memory: failed to copy the grid "
1040 "structure(s) from '%1'")
1052 QString(
"[ccPointCloud::fusion] Grid structure(s) will be "
1053 "dropped as the merged cloud is unstructured"));
1060 for (
size_t i = 0; i < addedPoints; i++)
1075 .norm2d() > 1.0e-6) {
1078 QString(
"[ccPointCloud::fusion] Global shift/scale "
1079 "information conflict: shift/scale of cloud "
1080 "'%1' will be ignored!")
1087 if (!ignoreChildren) {
1089 for (
unsigned c = 0; c < childrenCount; ++c) {
1116 QString(
"[ccPointCloud::fusion] Not enough memory: "
1117 "failed to clone sub mesh %1!")
1129 for (
unsigned j = 0; j < label->
size(); ++j) {
1131 if (P.
cloud == addedCloud)
1133 pointCountBefore + P.
index);
1181 for (
size_t i = 0; i <
m_grids.size(); ++i) {
1193 m_points.reserve(newNumberOfPoints);
1194 }
catch (
const std::bad_alloc&) {
1203 "[ccPointCloud::reserveTheRGBTable] Internal error: properties "
1204 "(re)allocation before points allocation is forbidden!");
1216 CVLog::Error(
"[ccPointCloud::reserveTheRGBTable] Not enough memory!");
1229 "[ccPointCloud::resizeTheRGBTable] Internal error: properties "
1230 "(re)allocation before points allocation is forbidden!");
1243 CVLog::Error(
"[ccPointCloud::resizeTheRGBTable] Not enough memory!");
1256 "[ccPointCloud::reserveTheNormsTable] Internal error: "
1257 "properties (re)allocation before points allocation is "
1271 CVLog::Error(
"[ccPointCloud::reserveTheNormsTable] Not enough memory!");
1284 "[ccPointCloud::resizeTheNormsTable] Internal error: "
1285 "properties (re)allocation before points allocation is "
1300 CVLog::Error(
"[ccPointCloud::resizeTheNormsTable] Not enough memory!");
1316 size_t initialCount =
m_fwfData->size();
1317 std::vector<size_t> usedIndexes;
1318 usedIndexes.resize(initialCount, 0);
1321 if (w.byteCount() == 0) {
1326 size_t start = w.dataOffset();
1327 size_t end = w.dataOffset() + w.byteCount();
1328 for (
size_t i = start; i < end; ++i) {
1333 size_t newIndex = 0;
1334 for (
size_t& index : usedIndexes) {
1341 if (newIndex >= initialCount) {
1343 CVLog::Print(QString(
"[ccPointCloud::compressFWFData] Cloud '%1': "
1344 "no need to compress FWF data")
1351 newContainer->reserve(newIndex);
1353 for (
size_t i = 0; i < initialCount; ++i) {
1354 if (usedIndexes[i]) {
1355 newContainer->push_back(
m_fwfData->at(i));
1361 uint64_t
offset = w.dataOffset();
1362 assert(usedIndexes[
offset] != 0);
1363 w.setDataOffset(usedIndexes[
offset] - 1);
1367 CVLog::Print(QString(
"[ccPointCloud::compressFWFData] Cloud '%1': FWF "
1368 "data compressed --> %2 / %3 (%4%)")
1372 .arg(100.0 - (newIndex * 100.0) / initialCount, 0,
1374 }
catch (
const std::bad_alloc&) {
1375 CVLog::Warning(
"[ccPointCloud::compressFWFData] Not enough memory!");
1385 "[ccPointCloud::reserveTheFWFTable] Internal error: properties "
1386 "(re)allocation before points allocation is forbidden!");
1392 }
catch (
const std::bad_alloc&) {
1393 CVLog::Error(
"[ccPointCloud::reserveTheFWFTable] Not enough memory!");
1436 "[ccPointCloud::resizeTheFWFTable] Internal error: properties "
1437 "(re)allocation before points allocation is forbidden!");
1443 }
catch (
const std::bad_alloc&) {
1444 CVLog::Error(
"[ccPointCloud::resizeTheFWFTable] Not enough memory!");
1454 if (newNumberOfPoints <
size())
return false;
1461 CVLog::Error(
"[ccPointCloud::reserve] Not enough memory!");
1470 return m_points.capacity() >= newNumberOfPoints &&
1478 if (newNumberOfPoints <
size() &&
isLocked())
return false;
1482 CVLog::Error(
"[ccPointCloud::resize] Not enough memory!");
1491 CVLog::Error(
"[ccPointCloud::resize] Not enough memory!");
1500 return m_points.size() == newNumberOfPoints &&
1514 unsigned pointIndex)
const {
1530 assert(pointIndex < m_currentDisplayedScalarField->currentSize());
1537 assert(
m_rgbColors && pointIndex < m_rgbColors->currentSize());
1544 assert(
m_rgbColors && pointIndex < m_rgbColors->currentSize());
1550 unsigned pointIndex)
const {
1551 assert(
m_normals && pointIndex < m_normals->currentSize());
1556 assert(
m_normals && pointIndex < m_normals->currentSize());
1562 assert(
m_normals && pointIndex < m_normals->currentSize());
1568 assert(
m_normals && pointIndex < m_normals->currentSize());
1576 for (
unsigned i = 0; i <
size(); ++i) {
1583 std::vector<CCVector3*>
normals;
1584 for (
unsigned i = 0; i < this->
size(); ++i) {
1595 for (
size_t i = 0; i <
normals.size(); ++i) {
1610 for (
size_t i = 0; i <
size(); i++) {
1617 const std::vector<Eigen::Vector3d>&
normals) {
1619 for (
size_t i = 0; i <
normals.size(); i++) {
1635 for (
size_t i = 0; i <
size(); i++) {
1643 for (
size_t i = 0; i <
colors.size(); i++) {
1650 assert(
m_rgbColors && pointIndex < m_rgbColors->currentSize());
1663 const Eigen::Vector3d& col) {
1673 assert(
m_normals && pointIndex < m_normals->currentSize());
1738 "[ccPointCloud::addEigenColors] Not enough memory!");
1773 "[ccPointCloud::addEigenNorms] Not enough memory!");
1784 for (
auto& N : Ns) {
1790 for (
auto& idx : idxes) {
1796 std::vector<CompressedNormType> temp;
1803 for (
unsigned int i = 0; i < static_cast<unsigned int>(
m_normals->size());
1839 CVLog::Warning(
"[ccPointCloud::convertNormalToRGB] Not enough memory!");
1842 const std::vector<ecvColor::Rgb>& normalHSV =
1846 CVLog::Warning(
"[ccPointCloud::convertNormalToRGB] Not enough memory!");
1852 for (
unsigned i = 0; i <
count; ++i) {
1870 for (
unsigned i = 0; i <
count; ++i) {
1874 double luminance = 0.2126 *
rgb.r + 0.7152 *
rgb.g + 0.0722 *
rgb.b;
1875 rgb.r =
rgb.g =
rgb.b =
static_cast<unsigned char>(
1876 std::max(std::min(luminance, 255.0), 0.0));
1887 if (!dipSF && !dipDirSF) {
1895 "[ccPointCloud::convertNormalToDipDirSFs] Not enough memory!");
1900 for (
unsigned i = 0; i <
count; ++i) {
1904 if (dipSF) dipSF->
setValue(i,
static_cast<ScalarType
>(dip));
1905 if (dipDirSF) dipDirSF->
setValue(i,
static_cast<ScalarType
>(dipDir));
1927 assert(r >= 0.0f && r <= 1.0f);
1928 assert(g >= 0.0f && g <= 1.0f);
1929 assert(b >= 0.0f && b <= 1.0f);
1958 if (freq == 0 || dim > 2)
1961 "[ccPointCloud::setRGBColorByBanding] Invalid parameter!");
1972 float bands = (2.0 *
M_PI) / freq;
1975 for (
unsigned i = 0; i <
count; i++) {
1978 float z = bands * P->
u[dim];
1998 if (!colorScale || heightDim > 2)
2000 CVLog::Error(
"[ccPointCloud::setRGBColorByHeight] Invalid parameter!");
2020 for (
unsigned i = 0; i <
count; i++) {
2022 double realtivePos = (Q->
u[heightDim] - minHeight) /
height;
2024 colorScale->getColorByRelativePos(realtivePos);
2040 bool mixWithExistingColor ) {
2043 "[ccPointCloud::setColorWithCurrentScalarField] No active "
2044 "scalar field or color scale!");
2050 if (!mixWithExistingColor || !
hasColors()) {
2055 for (
unsigned i = 0; i <
count; i++) {
2061 for (
unsigned i = 0; i <
count; i++) {
2095 for (
size_t i = 0; i <
m_grids.size(); ++i) {
2127 void** additionalParameters,
2136 additionalParameters[2]));
2138 unsigned char burntOutColorThresholdMin =
2140 unsigned char burntOutColorThresholdMax = 255 - burntOutColorThresholdMin;
2141 bool mean = filterParams.
filterType == ccPointCloud::RGB_FILTER_TYPES::MEAN;
2143 filterParams.
filterType == ccPointCloud::RGB_FILTER_TYPES::MEDIAN;
2146 double sigma2 = (2.0 * sigma) * sigma;
2147 double radius = 3.0 * sigma;
2171 cloudViewer::DgmOctree::NeighboursSet::iterator it =
2174 for (
unsigned i = 0; i < n; ++i, ++it) {
2185 bool bilateralFilter = (sigmaSF > 0.0) && !mean && !median;
2188 std::vector<unsigned char> rValues;
2189 std::vector<unsigned char> gValues;
2190 std::vector<unsigned char> bValues;
2191 std::vector<ScalarType> sfValues;
2193 for (
unsigned i = 0; i < n; ++i)
2195 ScalarType queryValue = 0;
2198 if (bilateralFilter) {
2215 nNSS, radius,
false);
2225 for (
unsigned j = 0; j < k; ++j, ++it) {
2228 if ((col.
r >= burntOutColorThresholdMax &&
2229 col.
g >= burntOutColorThresholdMax &&
2230 col.
b >= burntOutColorThresholdMax) ||
2231 (col.
r <= burntOutColorThresholdMin &&
2232 col.
g <= burntOutColorThresholdMin &&
2233 col.
b <= burntOutColorThresholdMin)) {
2237 rValues.push_back(col.
r);
2238 gValues.push_back(col.
g);
2239 bValues.push_back(col.
b);
2244 sfValues.push_back(val);
2249 if (rValues.size() != 0) {
2250 std::vector<unsigned char>::iterator medR =
2251 rValues.begin() + rValues.size() / 2;
2252 std::nth_element(rValues.begin(), medR, rValues.end());
2253 std::vector<unsigned char>::iterator medG =
2254 gValues.begin() + gValues.size() / 2;
2255 std::nth_element(gValues.begin(), medG, gValues.end());
2256 std::vector<unsigned char>::iterator medB =
2257 bValues.begin() + bValues.size() / 2;
2258 std::nth_element(bValues.begin(), medB, bValues.end());
2267 if (sfValues.size() != 0) {
2268 std::vector<ScalarType>::iterator medSF =
2269 sfValues.begin() + sfValues.size() / 2;
2270 std::nth_element(sfValues.begin(), medSF, sfValues.end());
2272 static_cast<ScalarType
>(*medSF));
2278 double sfWSum = 0.0;
2280 double wGrayscaleSum = 0.0;
2281 size_t nrOfGrayscale = 0;
2282 size_t nrOfUsedNeighbours = 0;
2284 for (
unsigned j = 0; j < k; ++j, ++it) {
2287 : exp(-(it->squareDistd) /
2292 if (bilateralFilter || applyToSF) {
2295 if (bilateralFilter) {
2296 double dSF = queryValue - val;
2297 weight *= exp(-(dSF * dSF) / sigmaSF2);
2299 sfSum += weight * val;
2306 if ((col.
r >= burntOutColorThresholdMax &&
2307 col.
g >= burntOutColorThresholdMax &&
2308 col.
b >= burntOutColorThresholdMax) ||
2309 (col.
r <= burntOutColorThresholdMin &&
2310 col.
g <= burntOutColorThresholdMin &&
2311 col.
b <= burntOutColorThresholdMin)) {
2315 rgbSum.
r += weight * col.
r;
2316 rgbSum.
g += weight * col.
g;
2317 rgbSum.
b += weight * col.
b;
2319 ++nrOfUsedNeighbours;
2322 double grayscaleMin = (col.
r / 3.0) + (col.
g / 3.0) +
2325 double grayscaleMax =
2328 if (
static_cast<double>(col.
r) >= grayscaleMin &&
2329 static_cast<double>(col.
g) >= grayscaleMin &&
2330 static_cast<double>(col.
b) >= grayscaleMin &&
2331 static_cast<double>(col.
r) <= grayscaleMax &&
2332 static_cast<double>(col.
g) <= grayscaleMax &&
2333 static_cast<double>(col.
b) <= grayscaleMax) {
2335 rgbGrayscaleSum.
r += weight * col.
r;
2336 rgbGrayscaleSum.
g += weight * col.
g;
2337 rgbGrayscaleSum.
b += weight * col.
b;
2338 wGrayscaleSum += weight;
2347 std::min(255.0, rgbSum.
r / wSum), 0.0)),
2349 std::min(255.0, rgbSum.
g / wSum), 0.0)),
2351 std::min(255.0, rgbSum.
b / wSum), 0.0)));
2357 if ((
static_cast<double>(nrOfGrayscale) >
2359 nrOfUsedNeighbours) &&
2360 wGrayscaleSum != 0) {
2363 rgbGrayscaleSum.
r / wGrayscaleSum),
2367 rgbGrayscaleSum.
g / wGrayscaleSum),
2371 rgbGrayscaleSum.
b / wGrayscaleSum),
2376 double wRGBSum = wSum - wGrayscaleSum;
2377 if (wRGBSum != 0.0) {
2380 (rgbSum.
r - rgbGrayscaleSum.
r) /
2385 (rgbSum.
g - rgbGrayscaleSum.
g) /
2390 (rgbSum.
b - rgbGrayscaleSum.
b) /
2401 if (sfWSum != 0.0) {
2404 static_cast<ScalarType
>(sfSum / sfWSum));
2422 unsigned n =
size();
2424 CVLog::Warning(
"[ccPointCloud::applyFilterToRGB] Cloud is empty");
2430 "[ccPointCloud::applyFilterToRGB] Cloud has no RGB color");
2436 "[ccPointCloud::applyFilterToRGB] A non-zero scalar field "
2437 "variance was set without an active 'input' scalar-field");
2445 "[ccPointCloud::applyFilterToRGB] Failed to compute the "
2455 unsigned char level =
2463 snprintf(infos, 32,
"Level: %i", level);
2469 void* additionalParameters[]{
reinterpret_cast<void*
>(&sigma),
2470 reinterpret_cast<void*
>(&sigmaSF),
2471 reinterpret_cast<void*
>(&filterParams)};
2473 bool success =
true;
2477 progressCb,
"Filter computation") == 0) {
2498 for (
unsigned i = 0; i <
count; i++) {
2504 bool recoded =
false;
2517 newNorms.emplace_back(newNormIndex);
2520 for (
unsigned j = 0; j <
count; j++) {
2548 grid->sensorPosition = transd *
grid->sensorPosition;
2554 if (w.descriptorID() != 0) {
2555 w.applyRigidTransformation(trans);
2584 for (
unsigned i = 0; i <
count; i++) *
point(i) += T;
2593 octree->translateBoundingBox(T);
2600 for (
size_t i = 0; i < kdtrees.size(); ++i) {
2601 static_cast<ccKdTree*
>(kdtrees[i])->translateBoundingBox(T);
2616 const Eigen::Vector3d& center) {
2625 const Eigen::Vector3d& center) {
2641 for (
unsigned i = 0; i <
count; i++) {
2643 P->
x = (P->
x - center.
x) * fx + center.
x;
2644 P->
y = (P->
y - center.
y) * fy + center.
y;
2645 P->
z = (P->
z - center.
z) * fz + center.
z;
2654 if (fx == fy && fx == fz && fx > 0) {
2656 octree->translateBoundingBox(centerInv);
2657 octree->multiplyBoundingBox(fx);
2658 octree->translateBoundingBox(center);
2669 if (fx == fy && fx == fz && fx > 0) {
2670 for (
size_t i = 0; i < kdtrees.size(); ++i) {
2679 for (
size_t i = 0; i < kdtrees.size(); ++i) {
2694 scaleAndReposition.
data()[0] = fx;
2695 scaleAndReposition.
data()[5] = fy;
2696 scaleAndReposition.
data()[10] = fz;
2700 scaleTrans = scaleAndReposition * transToCenter;
2708 grid->sensorPosition =
2754 assert(firstIndex <
size() && secondIndex <
size());
2756 if (firstIndex == secondIndex)
return;
2778 if (index >=
size()) {
2818 return static_cast<float>((sfVal - displayRange.
start()) /
2819 displayRange.
range());
2825 ScalarType relativeValue = 0;
2827 saturationRange.
start())
2831 (sfVal + saturationRange.
start()) / saturationRange.
max();
2834 (sfVal - saturationRange.
start()) / saturationRange.
max();
2836 return (1.0f + relativeValue) / 2;
2895 if (entityPickingMode) {
2912 bool colorMaterialEnabled =
false;
2923 colorMaterialEnabled =
true;
2947 if (sfIdx < 0)
return;
2949 context.sfColorScaleToDisplay =
2960 QSharedPointer<cloudViewer::ReferenceCloud> c(
2968 std::vector<ScalarType> values,
bool outside) {
2973 QSharedPointer<cloudViewer::ReferenceCloud> c(
2981 ScalarType maxVal) {
2983 CVLog::Error(QString(
"[Cloud %1] Visibility table could not be "
2991 CVLog::Error(QString(
"[Cloud %1] Internal error: no activated output "
2999 for (
unsigned i = 0; i <
count; ++i) {
3000 const ScalarType& val = sf->
getValue(i);
3001 if (val < minVal || val > maxVal || val != val)
3010 CVLog::Error(QString(
"[Cloud %1] Visibility table could not be "
3018 CVLog::Error(QString(
"[Cloud %1] Internal error: no activated output "
3026 for (
unsigned i = 0; i <
count; ++i) {
3027 const ScalarType& val = sf->
getValue(i);
3028 bool find_flag =
false;
3029 for (
auto label : values) {
3036 if (!find_flag || val != val)
3044 bool removeSelectedPoints ,
3046 std::vector<int>* newIndexesOfRemainingPoints ,
3052 QString(
"[Cloud %1] Visibility table not instantiated!")
3058 if (visTable->size() !=
size()) {
3059 CVLog::Error(QString(
"[Cloud %1] Invalid input visibility table")
3067 unsigned visiblePoints = 0;
3068 for (
size_t i = 0; i < visTable->size(); ++i) {
3073 if (visiblePoints ==
size()) {
3096 if (rc != selection) {
3104 "[ccPointCloud::createNewCloudFromVisibilitySelection] Failed "
3105 "to generate a subset cloud");
3109 static constexpr
const char* DefaultSuffix =
".segmented";
3111 if (!newName.endsWith(
3113 newName += DefaultSuffix;
3115 result->setName(newName);
3118 if (removeSelectedPoints) {
3121 "[ccPointCloud::createNewCloudFromVisibilitySelection] "
3122 "Can't remove selected points as cloud is locked");
3123 if (newIndexesOfRemainingPoints) {
3124 newIndexesOfRemainingPoints->clear();
3136 std::vector<int>* newIndexes ) {
3140 "[removeVisiblePoints] Visibility table not instantiated!");
3145 if (visTable->size() !=
size()) {
3147 "[removeVisiblePoints] Invalid input visibility table");
3152 std::vector<int> localNewIndexes;
3153 std::vector<int>* _newIndexes =
nullptr;
3156 if (newIndexes->empty()) {
3157 newIndexes->resize(
size());
3158 }
else if (newIndexes->size() !=
size()) {
3160 "[removeVisiblePoints] Input 'new indexes' has a wrong "
3164 _newIndexes = newIndexes;
3165 }
else if (!
m_grids.empty()) {
3167 localNewIndexes.resize(
size());
3168 _newIndexes = &localNewIndexes;
3170 }
catch (
const std::bad_alloc&) {
3171 CVLog::Error(
"[removeVisiblePoints] Not enough memory");
3180 unsigned lastPointIndex = 0;
3181 unsigned previousCount =
size();
3182 for (
unsigned i = 0; i < previousCount; ++i) {
3185 _newIndexes->at(i) = lastPointIndex;
3187 if (i != lastPointIndex) {
3191 }
else if (_newIndexes) {
3192 _newIndexes->at(i) = -1;
3198 assert(_newIndexes);
3205 if (
grid->validCount == 0) {
3206 grid->indexes.resize(0);
3263 bool mixWithExistingColor ) {
3266 "[ccPointCloud::setColorWithCurrentScalarField] No active "
3267 "scalar field or color scale!");
3273 if (!mixWithExistingColor || !
hasColors()) {
3277 for (
unsigned i = 0; i <
count; i++) {
3282 for (
unsigned i = 0; i <
count; i++) {
3310 QSharedPointer<cloudViewer::ReferenceCloud> CPSet;
3316 params.
CPSet = CPSet.data();
3323 static const char s_defaultTempSFName[] =
"CPSetComputationTempSF";
3327 CVLog::Warning(
"[ccPointCloud::ComputeCPSet] Not enough memory!");
3328 return QSharedPointer<cloudViewer::ReferenceCloud>(
nullptr);
3336 this, &otherCloud, params, progressCb);
3345 "[ccPointCloud::ComputeCPSet] Closest-point set computation "
3357 if (!otherCloud || otherCloud->
size() == 0) {
3359 "[ccPointCloud::interpolateColorsFrom] Invalid/empty input "
3370 if (fabs(dist.
x) > dimSum.
x / 2 || fabs(dist.
y) > dimSum.
y / 2 ||
3371 fabs(dist.
z) > dimSum.
z / 2) {
3373 "[ccPointCloud::interpolateColorsFrom] Clouds are too far from "
3374 "each other! Can't proceed.");
3380 QSharedPointer<cloudViewer::ReferenceCloud> CPSet =
3388 "[ccPointCloud::interpolateColorsFrom] Not enough memory!");
3393 unsigned CPSetSize = CPSet->size();
3394 assert(CPSetSize ==
size());
3395 for (
unsigned i = 0; i < CPSetSize; ++i) {
3396 unsigned index = CPSet->getPointGlobalIndex(i);
3408 unsigned char coneAxisDim,
3410 bool exportDeviationSF,
3411 double startAngle_deg,
3412 double stopAngle_deg,
3416 if (startAngle_deg >= stopAngle_deg)
3421 if (coneAxisDim > 2)
3428 dim.
z = coneAxisDim;
3429 dim.
x = (dim.
z < 2 ? dim.
z + 1 : 0);
3430 dim.
y = (dim.
x < 2 ? dim.
x + 1 : 0);
3432 unsigned numberOfPoints =
size();
3440 progressCb->
setInfo(qPrintable(QString(
"Number of points = %1").arg(numberOfPoints)));
3443 progressCb->
start();
3452 std::vector<CCVector3> unrolledPoints;
3455 unsigned newSize =
static_cast<unsigned>(
std::ceil((stopAngle_deg - startAngle_deg) / 360.0 *
size()));
3456 if (!duplicatedPoints.reserve(newSize))
3464 unrolledPoints.reserve(newSize);
3466 catch (
const std::bad_alloc&)
3474 std::vector<CCVector3> unrolledNormals;
3475 std::vector<ScalarType> deviationValues;
3484 unrolledNormals.resize(
size());
3485 deviationValues.resize(
size());
3487 catch (
const std::bad_alloc&)
3505 for (
unsigned i = 0; i < numberOfPoints; i++)
3512 double longitude_rad = atan2(
static_cast<double>(
CP.u[dim.
x]),
static_cast<double>(
CP.u[dim.
y]));
3517 Pout.
u[dim.
y] = u - radius;
3518 Pout.
u[dim.
z] = Pin->
u[dim.
z];
3528 double nLongitude_rad = atan2(
static_cast<double>(px),
static_cast<double>(
py));
3532 N2.
u[dim.
y] = nu - u;
3533 N2.
u[dim.
z] = N.
u[dim.
z];
3535 unrolledNormals[i] = N2;
3540 if (exportDeviationSF)
3542 deviationValues[i] =
static_cast<ScalarType
>(Pout.
u[dim.
y]);
3547 while (longitude_rad >= startAngle_rad)
3549 longitude_rad -= 2 *
M_PI;
3551 longitude_rad += 2 *
M_PI;
3554 for (; longitude_rad < stopAngle_rad; longitude_rad += 2 *
M_PI)
3557 if (duplicatedPoints.size() == duplicatedPoints.capacity())
3559 unsigned newSize = duplicatedPoints.size() + (1 << 20);
3560 if (!duplicatedPoints.reserve(newSize))
3568 unrolledPoints.reserve(newSize);
3570 catch (
const std::bad_alloc&)
3578 Pout.
u[dim.
x] = longitude_rad * radius;
3579 unrolledPoints.push_back(Pout);
3580 duplicatedPoints.addPointIndex(i);
3584 if (progressCb && !nprogress.oneStep())
3601 if (exportDeviationSF)
3609 CVLog::Warning(
"[unrollOnCylinder] Not enough memory to init the deviation scalar field");
3614 deviationSF =
clone->getScalarField(sfIdx);
3615 clone->setCurrentDisplayedScalarField(sfIdx);
3621 for (
unsigned i = 0; i < duplicatedPoints.size(); ++i)
3624 *P = unrolledPoints[i];
3626 unsigned globalIndex = duplicatedPoints.getPointGlobalIndex(i);
3629 clone->setPointNormal(i, unrolledNormals[globalIndex]);
3633 deviationSF->
setValue(i, deviationValues[globalIndex]);
3657 sqrt(AP.
u[dim.
x] * AP.
u[dim.
x] + AP.
u[dim.
y] * AP.
u[dim.
y]);
3659 phi_rad = atan2(AP.
u[dim.
y], AP.
u[dim.
x]);
3661 delta = APnorm_XY - radius;
3674 sqrt(AP.
u[dim.
x] * AP.
u[dim.
x] + AP.
u[dim.
y] * AP.
u[dim.
y]);
3686 phi_rad = atan2(AP.
u[dim.
y], AP.
u[dim.
x]);
3688 s = normAP * cos(gamma_rad);
3690 delta = normAP * sin(gamma_rad);
3697 bool exportDeviationSF ,
3698 double startAngle_deg ,
3699 double stopAngle_deg ,
3701 if (!params || params->
axisDim > 2 || startAngle_deg >= stopAngle_deg) {
3713 modeStr =
"Cylinder";
3722 modeStr =
"Straightened cone";
3732 dim.
x = (dim.
z < 2 ? dim.
z + 1 : 0);
3733 dim.
y = (dim.
x < 2 ? dim.
x + 1 : 0);
3735 unsigned numberOfPoints =
size();
3740 qPrintable(QString(
"Unroll (%1)").arg(modeStr)));
3741 progressCb->
setInfo(qPrintable(
3742 QString(
"Number of points = %1").arg(numberOfPoints)));
3745 progressCb->
start();
3750 std::vector<CCVector3> unrolledPoints;
3753 unsigned newSize =
static_cast<unsigned>(
3754 std::ceil((stopAngle_deg - startAngle_deg) / 360.0 *
size()));
3755 if (!duplicatedPoints.
reserve(newSize)) {
3761 unrolledPoints.reserve(newSize);
3762 }
catch (
const std::bad_alloc&) {
3768 std::vector<ScalarType> deviationValues;
3769 if (exportDeviationSF)
try {
3770 deviationValues.resize(
size());
3771 }
catch (
const std::bad_alloc&) {
3776 std::vector<CCVector3> unrolledNormals;
3782 unrolledNormals.resize(
size());
3783 }
catch (
const std::bad_alloc&) {
3799 for (
unsigned i = 0; i < numberOfPoints; i++) {
3811 AP = *Pin - cylParams->
center;
3817 Pout.
u[dim.
y] = -delta;
3818 Pout.
u[dim.
z] = Pin->
u[dim.
z];
3822 AP = *Pin - coneParams->
apex;
3827 Pout.
u[dim.
y] = -delta;
3829 Pout.
u[dim.
z] = coneParams->
apex.
u[dim.
z] - coneAbscissa;
3833 AP = *Pin - coneParams->
apex;
3838 Pout.
u[dim.
y] = -delta;
3840 Pout.
u[dim.
z] = coneParams->
apex.
u[dim.
z] - coneAbscissa;
3844 AP = *Pin - coneParams->
apex;
3853 Pout.
u[dim.
y] = -coneAbscissa * cos(theta_rad);
3854 Pout.
u[dim.
x] = coneAbscissa * sin(theta_rad);
3855 Pout.
u[dim.
z] = delta;
3876 (longitude2_rad - longitude_rad) * params->
radius);
3877 N2.
u[dim.
y] = -(delta2 - delta);
3878 N2.
u[dim.
z] = N.
u[dim.
z];
3889 (longitude2_rad - longitude_rad) * params->
radius);
3890 N2.
u[dim.
y] = -(delta2 - delta);
3891 N2.
u[dim.
z] = coneAbscissa - coneAbscissa2;
3902 (longitude2_rad * coneAbscissa -
3903 longitude_rad * coneAbscissa2) *
3905 N2.
u[dim.
y] = -(delta2 - delta);
3906 N2.
u[dim.
z] = coneAbscissa - coneAbscissa2;
3923 P2out.
u[dim.
x] = coneAbscissa2 * sin(theta2_rad);
3924 P2out.
u[dim.
y] = -coneAbscissa2 * cos(theta2_rad);
3925 P2out.
u[dim.
z] = delta2;
3935 unrolledNormals[i] = N2;
3939 if (exportDeviationSF) {
3940 deviationValues[i] =
static_cast<ScalarType
>(delta);
3945 double dLongitude_rad = longitude_rad;
3946 while (dLongitude_rad >= startAngle_rad) {
3947 dLongitude_rad -= 2 *
M_PI;
3949 dLongitude_rad += 2 *
M_PI;
3952 for (; dLongitude_rad < stopAngle_rad; dLongitude_rad += 2 *
M_PI) {
3954 if (duplicatedPoints.
size() == duplicatedPoints.
capacity()) {
3955 unsigned newSize = duplicatedPoints.
size() + (1 << 20);
3956 if (!duplicatedPoints.
reserve(newSize)) {
3962 unrolledPoints.reserve(newSize);
3963 }
catch (
const std::bad_alloc&) {
3973 Pout.
u[dim.
x] = dLongitude_rad * params->
radius;
3976 Pout.
u[dim.
x] = dLongitude_rad * coneAbscissa * sin_alpha;
3980 Pout.
u[dim.
x] = coneAbscissa * sin(dLongitude_rad);
3981 Pout.
u[dim.
y] = -coneAbscissa * cos(dLongitude_rad);
3990 unrolledPoints.push_back(Pout);
3995 if (progressCb && !nprogress.
oneStep()) {
4009 if (exportDeviationSF) {
4015 "[unrollOnCylinder] Not enough memory to init the "
4016 "deviation scalar field");
4020 deviationSF =
clone->getScalarField(sfIdx);
4021 clone->setCurrentDisplayedScalarField(sfIdx);
4027 for (
unsigned i = 0; i < duplicatedPoints.
size(); ++i) {
4029 *P = unrolledPoints[i];
4033 clone->setPointNormal(i, unrolledNormals[globalIndex]);
4036 deviationSF->
setValue(i, deviationValues[globalIndex]);
4052 ccPointCloud* ccPointCloud::unrollOnCone(
double coneAngle_deg,
4054 unsigned char coneAxisDim,
4055 bool developStraightenedCone,
4057 bool exportDeviationSF,
4060 if (coneAxisDim > 2)
4067 dim.
z = coneAxisDim;
4068 dim.
x = (dim.
z < 2 ? dim.
z + 1 : 0);
4069 dim.
y = (dim.
x < 2 ? dim.
x + 1 : 0);
4071 unsigned numberOfPoints =
size();
4079 progressCb->
setInfo(qPrintable(QString(
"Number of points = %1").arg(numberOfPoints)));
4082 progressCb->
start();
4092 if (exportDeviationSF)
4100 CVLog::Warning(
"[unrollOnCone] Not enough memory to init the deviation scalar field");
4105 deviationSF =
clone->getScalarField(sfIdx);
4107 clone->setCurrentDisplayedScalarField(sfIdx);
4114 for (
unsigned i = 0; i < numberOfPoints; i++)
4119 ProjectOnCone(*Pin, coneApex, alpha_rad, dim, s, delta, phi_rad);
4127 if (developStraightenedCone)
4130 Pout.
u[dim.
x] = (baseRadius + delta) * cos(phi_rad);
4131 Pout.
u[dim.
y] = (baseRadius + delta) * sin(phi_rad);
4132 Pout.
u[dim.
z] = coneApex.
u[dim.
z] - s;
4140 Pout.
u[dim.
y] = -s * cos(theta_rad);
4141 Pout.
u[dim.
x] = s * sin(theta_rad);
4142 Pout.
u[dim.
z] = delta;
4146 *
clone->point(i) = Pout;
4154 ProjectOnCone(*Pin + N, coneApex, alpha_rad, dim, s2, delta2, phi2_rad);
4157 if (developStraightenedCone)
4160 P2out.
u[dim.
x] = (baseRadius + delta2) * cos(phi2_rad);
4161 P2out.
u[dim.
y] = (baseRadius + delta2) * sin(phi2_rad);
4162 P2out.
u[dim.
z] = coneApex.
u[dim.
z] - s2;
4170 P2out.
u[dim.
y] = -s2 * cos(theta2_rad);
4171 P2out.
u[dim.
x] = s2 * sin(theta2_rad);
4172 P2out.
u[dim.
z] = delta2;
4178 clone->setPointNormal(i, N2);
4182 if (progressCb && !nprogress.oneStep())
4230 CVLog::Warning(QString(
"[ccPointCloud::addScalarField] Name '%1' "
4237 if (sf->size() <
m_points.size()) {
4239 CVLog::Warning(
"[ccPointCloud::addScalarField] Not enough memory!");
4243 if (sf->capacity() <
m_points.capacity())
4246 CVLog::Warning(
"[ccPointCloud::addScalarField] Not enough memory!");
4253 }
catch (
const std::bad_alloc&) {
4254 CVLog::Warning(
"[ccPointCloud::addScalarField] Not enough memory!");
4264 assert(out.isOpen() && (out.openMode() & QIODevice::WriteOnly));
4265 if (dataVersion < 27) {
4281 if (out.write((
const char*)&hasColorsArray,
sizeof(
bool)) < 0)
4283 if (hasColorsArray) {
4292 if (out.write((
const char*)&hasNormalsArray,
sizeof(
bool)) < 0)
4294 if (hasNormalsArray) {
4304 if (out.write((
const char*)&sfCount, 4) < 0)
return WriteError();
4307 for (uint32_t i = 0; i < sfCount; ++i) {
4310 if (!sf || !sf->
toFile(out, dataVersion))
return false;
4322 int32_t displayedScalarFieldIndex =
4324 if (out.write((
const char*)&displayedScalarFieldIndex, 4) < 0)
4335 for (uint32_t i = 0; i <
count; ++i) {
4337 if (g && !g->indexes.empty()) {
4338 if (!g->toFile(out, dataVersion)) {
4347 if (out.write((
const char*)&withFWF,
sizeof(
bool)) < 0) {
4352 uint32_t descriptorCount =
4354 if (out.write((
const char*)&descriptorCount, 4) < 0) {
4360 if (out.write((
const char*)&it.key(), 1) < 0) {
4364 if (!it.value().toFile(out, dataVersion)) {
4370 uint32_t waveformCount =
static_cast<uint32_t
>(
m_fwfWaveforms.size());
4371 if (out.write((
const char*)&waveformCount, 4) < 0) {
4375 if (!w.toFile(out, dataVersion)) {
4383 if (out.write((
const char*)&dataSize, 8) < 0) {
4387 out.write((
const char*)
m_fwfData->data(), dataSize) < 0) {
4397 : w(0), h(0), validCount(0), minValidIndex(0), maxValidIndex(0) {
4404 size_t scanSize =
static_cast<size_t>(rowCount) * colCount;
4406 indexes.resize(scanSize, -1);
4410 }
catch (
const std::bad_alloc&) {
4424 assert(!indexes.empty());
4425 indexes[row * w + col] = index;
4438 validCount = minValidIndex = maxValidIndex = 0;
4440 if (!indexes.empty()) {
4441 minValidIndex = std::numeric_limits<int>::max();
4442 for (
int index : indexes) {
4449 unsigned uIndex =
static_cast<unsigned>(index);
4450 if (uIndex < minValidIndex) {
4451 minValidIndex = uIndex;
4452 }
else if (uIndex > maxValidIndex) {
4453 maxValidIndex = uIndex;
4457 if (minValidIndex == std::numeric_limits<int>::max()) {
4465 if (
colors.size() ==
static_cast<size_t>(w) * h) {
4466 QImage
image(w, h, QImage::Format_ARGB32);
4467 for (
unsigned j = 0; j < h; ++j) {
4468 for (
unsigned i = 0; i < w; ++i) {
4470 image.setPixel(i, j, qRgb(col.
r, col.
g, col.
b));
4481 if (dataVersion < 41) {
4487 uint32_t _w =
static_cast<uint32_t
>(w);
4488 if (out.write((
const char*)&_w, 4) < 0)
return WriteError();
4490 uint32_t _h =
static_cast<uint32_t
>(h);
4491 if (out.write((
const char*)&_h, 4) < 0)
return WriteError();
4494 if (!sensorPosition.toFile(out, dataVersion))
return WriteError();
4497 const int* _index = indexes.data();
4498 for (uint32_t j = 0; j < w * h; ++j, ++_index) {
4499 int32_t index =
static_cast<int32_t
>(*_index);
4500 if (out.write((
const char*)&index, 4) < 0)
return WriteError();
4506 if (out.write((
const char*)&
hasColors, 1) < 0) {
4511 for (uint32_t j = 0; j <
colors.size(); ++j) {
4512 if (out.write((
const char*)
colors[j].rgb, 3) < 0)
4527 if (in.read((
char*)&_w, 4) < 0)
return ReadError();
4530 if (in.read((
char*)&_h, 4) < 0)
return ReadError();
4532 w =
static_cast<unsigned>(_w);
4533 h =
static_cast<unsigned>(_h);
4536 if (!sensorPosition.fromFile(in, dataVersion, flags, oldToNewIDMap))
4540 indexes.resize(
static_cast<size_t>(w) * h);
4541 }
catch (
const std::bad_alloc&) {
4546 int* _index = indexes.data();
4547 for (
size_t j = 0; j < static_cast<size_t>(w) * h; ++j, ++_index) {
4549 if (in.read((
char*)&index, 4) < 0)
return ReadError();
4556 std::min(minValidIndex,
static_cast<unsigned>(index));
4558 std::max(maxValidIndex,
static_cast<unsigned>(index));
4560 minValidIndex = maxValidIndex =
static_cast<unsigned>(index);
4572 colors.resize(indexes.size());
4573 }
catch (
const std::bad_alloc&) {
4577 for (uint32_t j = 0; j <
colors.size(); ++j) {
4586 return std::max(
static_cast<short>(41),
4587 sensorPosition.minimumFileVersion());
4592 std::max(
static_cast<short>(27),
4594 minVersion = std::max(
4604 minVersion = std::max(
4613 minVersion = std::max(minVersion,
static_cast<short>(41));
4614 minVersion = std::max(
4620 minVersion = std::max(minVersion,
static_cast<short>(44));
4622 minVersion = std::max(
4625 ->minimumFileVersion());
4629 minVersion = std::max(
4632 .minimumFileVersion());
4651 bool fileCoordIsDouble =
4653 if (!fileCoordIsDouble &&
4659 m_points, in, dataVersion,
"3D points");
4660 }
else if (fileCoordIsDouble &&
4666 m_points, in, dataVersion,
"3D points");
4670 m_points, in, dataVersion,
"3D points");
4679 unsigned nanPointsCount = 0;
4680 for (
unsigned i = 0; i <
size(); ++i) {
4688 if (nanPointsCount) {
4690 QString(
"[BIN] Cloud '%1' contains %2 NaN point(s)!")
4692 .arg(nanPointsCount));
4700 bool hasColorsArray =
false;
4701 if (in.read((
char*)&hasColorsArray,
sizeof(
bool)) < 0)
4703 if (hasColorsArray) {
4716 QSharedPointer<RGBAColorsTableType> oldRGBAColors(
4718 if (!oldRGBAColors->fromFile(in, dataVersion, flags,
4723 size_t count = oldRGBAColors->size();
4729 for (
size_t i = 0; i <
count; ++i) {
4731 oldRGBAColors->getValue(i)));
4741 bool hasNormalsArray =
false;
4742 if (in.read((
char*)&hasNormalsArray,
sizeof(
bool)) < 0)
4744 if (hasNormalsArray) {
4762 uint32_t sfCount = 0;
4763 if (in.read((
char*)&sfCount, 4) < 0)
return ReadError();
4766 for (uint32_t i = 0; i < sfCount; ++i) {
4768 if (!sf->
fromFile(in, dataVersion, flags, oldToNewIDMap)) {
4775 if (dataVersion < 27) {
4777 bool greyForNanScalarValues =
true;
4778 if (in.read((
char*)&greyForNanScalarValues,
sizeof(
bool)) < 0)
4784 ->showNaNValuesInGrey(greyForNanScalarValues);
4793 int32_t displayedScalarFieldIndex = 0;
4794 if (in.read((
char*)&displayedScalarFieldIndex, 4) < 0)
4796 if (displayedScalarFieldIndex < (int32_t)sfCount)
4801 if (dataVersion >= 41) {
4807 for (uint32_t i = 0; i <
count; ++i) {
4810 if (!g->fromFile(in, dataVersion, flags, oldToNewIDMap)) {
4819 if (dataVersion >= 44) {
4820 bool withFWF =
false;
4821 if (in.read((
char*)&withFWF,
sizeof(
bool)) < 0) {
4826 uint32_t descriptorCount = 0;
4827 if (in.read((
char*)&descriptorCount, 4) < 0) {
4830 for (uint32_t i = 0; i < descriptorCount; ++i) {
4833 if (in.read((
char*)&
id, 1) < 0) {
4838 if (!d.
fromFile(in, dataVersion, flags, oldToNewIDMap)) {
4846 uint32_t waveformCount = 0;
4847 if (in.read((
char*)&waveformCount, 4) < 0) {
4850 assert(waveformCount >=
size());
4853 }
catch (
const std::bad_alloc&) {
4856 for (uint32_t i = 0; i < waveformCount; ++i) {
4864 uint64_t dataSize = 0;
4865 if (in.read((
char*)&dataSize, 8) < 0) {
4868 if (dataSize != 0) {
4871 container->resize(dataSize);
4872 }
catch (
const std::bad_alloc&) {
4877 if (in.read((
char*)
m_fwfData->data(), dataSize) < 0) {
4920 for (
unsigned i = 0; i <
count; ++i) {
4922 bool pointIsInside = box.
contains(*P);
4923 if (inside == pointIsInside) {
4928 if (ref->
size() == 0) {
4957 std::vector<size_t> indices =
4960 for (
size_t index : indices) {
4964 if (ref->
size() == 0) {
4983 unsigned char orthoDim,
5007 unsigned char X = ((orthoDim + 1) % 3);
5008 unsigned char Y = ((
X + 1) % 3);
5010 for (
unsigned i = 0; i <
count; ++i) {
5014 bool pointIsInside =
5017 if (inside == pointIsInside) {
5022 if (ref->
size() == 0) {
5039 case GL_INVALID_ENUM:
5043 case GL_INVALID_VALUE:
5046 case GL_INVALID_OPERATION:
5049 case GL_STACK_OVERFLOW:
5052 case GL_STACK_UNDERFLOW:
5055 case GL_OUT_OF_MEMORY:
5058 case GL_INVALID_FRAMEBUFFER_OPERATION:
5060 "[%s] OpenGL error: invalid framebuffer operation",
5071 #define DONT_LOAD_NORMALS_IN_VBOS
5076 bool* reallocated ) {
5080 rgbShift = totalSizeBytes;
5084 normalShift = totalSizeBytes;
5097 setUsagePattern(QGLBuffer::DynamicDraw);
5103 CVLog::Warning(
"[ccPointCloud::VBO::init] Failed to bind VBO to active context!");
5108 if (totalSizeBytes !=
size())
5110 allocate(totalSizeBytes);
5112 *reallocated =
true;
5114 if (
size() != totalSizeBytes)
5116 CVLog::Warning(
"[ccPointCloud::VBO::init] Not enough (GPU) memory!");
5129 return totalSizeBytes;
5160 unsigned pointCount =
size();
5161 if (pointCount < 3) {
5162 CVLog::Warning(QString(
"[computeNormalsWithGrids] Cloud '%1' has not "
5170 std::vector<CCVector3> theNorms;
5173 theNorms.resize(pointCount, blankNorm);
5174 }
catch (
const std::bad_alloc&) {
5175 CVLog::Warning(
"[ccMesh::computePerVertexNormals] Not enough memory!");
5192 pDlg->setWindowTitle(QObject::tr(
"Normals computation"));
5193 pDlg->setAutoClose(
false);
5195 QCoreApplication::processEvents();
5204 for (
size_t gi = 0; gi <
gridCount(); ++gi) {
5206 if (scanGrid && scanGrid->indexes.empty()) {
5210 if (!scanGrid || scanGrid->h == 0 || scanGrid->w == 0 ||
5211 scanGrid->indexes.size() != scanGrid->h * scanGrid->w) {
5213 CVLog::Warning(QString(
"[computeNormalsWithGrids] Grid structure "
5221 pDlg->setLabelText(QObject::tr(
"Grid: %1 x %2")
5225 pDlg->setRange(0,
static_cast<int>(scanGrid->indexes.size()));
5226 QCoreApplication::processEvents();
5231 (scanGrid->sensorPosition
5232 .getTranslationAsVec3D() )
5235 for (
int j = 0; j < static_cast<int>(scanGrid->h) - 1; ++j) {
5236 for (
int i = 0; i < static_cast<int>(scanGrid->w) - 1; ++i) {
5239 const int& v0 = scanGrid->indexes[j * scanGrid->w + i];
5240 const int& v1 = scanGrid->indexes[j * scanGrid->w + (i + 1)];
5241 const int& v2 = scanGrid->indexes[(j + 1) * scanGrid->w + i];
5243 scanGrid->indexes[(j + 1) * scanGrid->w + (i + 1)];
5245 bool topo[4] = {v0 >= 0, v1 >= 0, v2 >= 0, v3 >= 0};
5250 for (
int j = 0; j < 4; ++j) {
5262 {v0, v2, v1}, {v0, v3, v1}, {v0, v2, v3}, {v1, v2, v3}};
5264 int tri[2] = {-1, -1};
5281 double d0 = (*
getPoint(v0) - sensorOrigin).normd();
5282 double d1 = (*
getPoint(v1) - sensorOrigin).normd();
5283 double d2 = (*
getPoint(v2) - sensorOrigin).normd();
5284 double d3 = (*
getPoint(v3) - sensorOrigin).normd();
5285 float ddiff1 = std::abs(d0 - d3);
5286 float ddiff2 = std::abs(d1 - d2);
5287 if (ddiff1 < ddiff2) {
5301 for (
int trCount = 0; trCount < 2; ++trCount) {
5302 int idx = tri[trCount];
5313 if (minTriangleAngle_deg > 0) {
5320 if (cosA > minAngleCos) {
5327 if (cosB > minAngleCos) {
5332 if (cosC > minAngleCos) {
5341 theNorms[t.
u[0]] += N;
5342 theNorms[t.
u[1]] += N;
5343 theNorms[t.
u[2]] += N;
5349 if (pDlg->wasCanceled()) {
5352 "[computeNormalsWithGrids] Process cancelled by "
5356 pDlg->setValue(
static_cast<unsigned>(j + 1) * scanGrid->w);
5364 for (
unsigned i = 0; i < pointCount; i++) {
5382 unsigned pointCount =
size();
5383 if (pointCount == 0) {
5384 CVLog::Warning(QString(
"[orientNormalsWithGrids] Cloud '%1' is empty")
5391 QString(
"[orientNormalsWithGrids] Cloud '%1' has no normals")
5396 CVLog::Warning(QString(
"[orientNormalsWithGrids] Cloud '%1' has no "
5397 "associated grid scan")
5404 pDlg->setWindowTitle(QObject::tr(
"Orienting normals"));
5405 pDlg->setLabelText(QObject::tr(
"Points: %L1").arg(pointCount));
5406 pDlg->setRange(0,
static_cast<int>(pointCount));
5408 QCoreApplication::processEvents();
5412 int progressIndex = 0;
5413 for (
size_t gi = 0; gi <
gridCount(); ++gi) {
5415 if (scanGrid && scanGrid->indexes.empty()) {
5419 if (!scanGrid || scanGrid->h == 0 || scanGrid->w == 0 ||
5420 scanGrid->indexes.size() != scanGrid->h * scanGrid->w) {
5422 CVLog::Warning(QString(
"[orientNormalsWithGrids] Grid structure "
5430 (scanGrid->sensorPosition
5431 .getTranslationAsVec3D() )
5434 const int* _indexGrid = scanGrid->indexes.data();
5435 for (
int j = 0; j < static_cast<int>(scanGrid->h); ++j) {
5436 for (
int i = 0; i < static_cast<int>(scanGrid->w);
5437 ++i, ++_indexGrid) {
5438 if (*_indexGrid >= 0) {
5439 unsigned pointIndex =
static_cast<unsigned>(*_indexGrid);
5440 assert(pointIndex <= pointCount);
5460 if (pDlg->wasCanceled()) {
5463 "[orientNormalsWithGrids] Process "
5464 "cancelled by user");
5467 pDlg->setValue(++progressIndex);
5480 int progressIndex = 0;
5481 for (
unsigned pointIndex = 0; pointIndex <
m_points.capacity();
5495 if (pDlg->wasCanceled()) {
5498 "[orientNormalsWithSensors] Process cancelled by user");
5501 pDlg->setValue(++progressIndex);
5515 CVLog::Warning(QString(
"[computeNormals] Could not compute octree for "
5522 QElapsedTimer eTimer;
5526 this, *normsIndexes, model, defaultRadius, preferredOrientation,
5529 CVLog::Warning(QString(
"[computeNormals] Failed to compute normals on "
5536 eTimer.elapsed() / 1000.0);
5540 CVLog::Error(QString(
"Not enough memory to compute normals on "
5553 for (
unsigned j = 0; j < normsIndexes->
currentSize(); j++) {
5560 normsIndexes =
nullptr;
5580 for (
size_t i = 0; i <
m_children.size(); ++i) {
5594 unsigned char bestVisibility = 255;
5595 for (
size_t i = 0; i <
m_children.size(); ++i) {
5603 else if (visibility < bestVisibility)
5604 bestVisibility = visibility;
5607 if (bestVisibility != 255)
return bestVisibility;
5634 minVal = maxVal = 0;
5644 pDlg->setWindowTitle(QObject::tr(
"FWF amplitude"));
5646 QObject::tr(
"Determining min and max FWF values\nPoints: ") +
5649 QCoreApplication::processEvents();
5653 bool firstTest =
true;
5654 for (
unsigned i = 0; i <
size(); ++i) {
5664 double wMinVal, wMaxVal;
5672 if (wMaxVal > maxVal) {
5675 if (wMinVal < minVal) {
5686 bool useCustomIntensityRange ,
5697 if (!useCustomIntensityRange) {
5702 double intRange = maxI - minI;
5703 if (intRange < 1.0e-6) {
5705 "[ccPointCloud::enhanceRGBWithIntensitySF] Intensity range is "
5710 for (
unsigned i = 0; i <
size(); ++i) {
5714 int I =
static_cast<int>(col.
r) +
static_cast<int>(col.
g) +
5715 static_cast<int>(col.
b);
5720 double newI = 255 * ((sf->
getValue(i) - minI) / intRange);
5723 double scale = (3 * newI) / I;
5726 std::min<ScalarType>(
scale * col.
r, 255), 0));
5728 std::min<ScalarType>(
scale * col.
g, 255), 0));
5730 std::min<ScalarType>(
scale * col.
b, 255), 0));
5740 const Grid&
grid,
double minTriangleAngle_deg )
const {
5743 (
grid.sensorPosition.getTranslationAsVec3D() )
5749 CVLog::Warning(
"[ccPointCloud::triangulateGrid] Not enough memory");
5758 for (
int j = 0; j < static_cast<int>(
grid.h) - 1; ++j) {
5759 for (
int i = 0; i < static_cast<int>(
grid.w) - 1; ++i) {
5760 const int& v0 =
grid.indexes[j *
grid.w + i];
5761 const int& v1 =
grid.indexes[j *
grid.w + (i + 1)];
5762 const int& v2 =
grid.indexes[(j + 1) *
grid.w + i];
5763 const int& v3 =
grid.indexes[(j + 1) *
grid.w + (i + 1)];
5765 bool topo[4] = {v0 >= 0, v1 >= 0, v2 >= 0, v3 >= 0};
5770 for (
int j = 0; j < 4; ++j) {
5782 {v0, v2, v1}, {v0, v3, v1}, {v0, v2, v3}, {v1, v2, v3}};
5784 int tri[2] = {-1, -1};
5801 double d0 = (*
getPoint(v0) - sensorOrigin).normd();
5802 double d1 = (*
getPoint(v1) - sensorOrigin).normd();
5803 double d2 = (*
getPoint(v2) - sensorOrigin).normd();
5804 double d3 = (*
getPoint(v3) - sensorOrigin).normd();
5805 float ddiff1 = std::abs(d0 - d3);
5806 float ddiff2 = std::abs(d1 - d2);
5807 if (ddiff1 < ddiff2) {
5821 for (
int trCount = 0; trCount < 2; ++trCount) {
5822 int idx = tri[trCount];
5829 if (minTriangleAngle_deg > 0) {
5840 if (cosA > minAngleCos) {
5847 if (cosB > minAngleCos) {
5852 if (cosC > minAngleCos) {
5862 if (mesh->
size() == 0) {
5877 if (!exportDims[0] && !exportDims[1] && !exportDims[2]) {
5883 const QString defaultSFName[3] = {
"Coord. X",
"Coord. Y",
"Coord. Z"};
5885 unsigned ptsCount =
size();
5888 for (
unsigned d = 0; d < 3; ++d) {
5889 if (!exportDims[d]) {
5899 "[ccPointCloud::exportCoordToSF] Not enough memory!");
5909 for (
unsigned k = 0; k < ptsCount; ++k) {
5910 ScalarType s =
static_cast<ScalarType
>(
getPoint(k)->
u[d]);
5925 unsigned pointCount =
size();
5927 if (!sf || sf->size() < pointCount) {
5932 for (
unsigned i = 0; i < pointCount; ++i) {
5940 : defaultValueForNaN;
5943 if (importDims[0]) P.
x = coord;
5944 if (importDims[1]) P.
y = coord;
5945 if (importDims[2]) P.
z = coord;
5954 if (!exportDims[0] && !exportDims[1] && !exportDims[2]) {
5965 const QString defaultSFName[3] = {
"Nx",
"Ny",
"Nz"};
5967 unsigned ptsCount =
static_cast<unsigned>(
m_normals->size());
5970 for (
unsigned d = 0; d < 3; ++d) {
5971 if (!exportDims[d]) {
5981 "[ccPointCloud::exportNormalToSF] Not enough memory!");
5991 for (
unsigned k = 0; k < ptsCount; ++k) {
6005 const std::vector<size_t>& indices,
bool invert )
const {
6006 auto output = std::make_shared<ccPointCloud>(
"pointCloud");
6012 unsigned int n =
size();
6014 unsigned int out_n = invert ?
static_cast<unsigned int>(n - indices.size())
6015 :
static_cast<unsigned int>(indices.size());
6017 std::vector<bool> mask = std::vector<bool>(n, invert);
6018 for (
size_t i : indices) {
6027 output->importParametersFrom(
this);
6031 if (!output->reserveThePointsTable(out_n)) {
6033 "[ccPointCloud::SelectByIndex] Not enough memory to "
6034 "duplicate cloud!");
6040 if (output->reserveTheRGBTable()) {
6044 "[ccPointCloud::SelectByIndex] Not enough memory to "
6045 "copy RGB colors!");
6052 if (output->reserveTheNormsTable()) {
6056 "[ccPointCloud::SelectByIndex] Not enough memory to "
6064 if (output->reserveTheFWFTable()) {
6067 output->fwfData() =
fwfData();
6068 }
catch (
const std::bad_alloc&) {
6070 "[ccPointCloud::SelectByIndex] Not enough memory "
6071 "to copy waveform signals!");
6072 output->clearFWFData();
6077 "[ccPointCloud::SelectByIndex] Not enough memory to "
6078 "copy waveform signals!");
6084 for (
unsigned i = 0; i < n; i++) {
6099 if (has_covariance) {
6106 if (!output->fwfDescriptors().contains(w.
descriptorID())) {
6108 output->fwfDescriptors().insert(
6112 output->waveforms().push_back(w);
6120 for (
unsigned k = 0; k < sfCount; ++k) {
6126 int sfIdx = output->addScalarField(sf->
getName());
6131 output->getScalarField(sfIdx));
6132 assert(currentScalarField);
6138 for (
unsigned i = 0; i < n; i++) {
6151 output->deleteScalarField(sfIdx);
6153 QString(
"[ccPointCloud::SelectByIndex] Not "
6154 "enough memory to copy scalar "
6163 if (copiedSFCount) {
6167 int sfIdx = output->getScalarFieldIndexByName(
6170 output->setCurrentDisplayedScalarField(sfIdx);
6172 output->setCurrentDisplayedScalarField(
6173 static_cast<int>(copiedSFCount) - 1);
6184 std::vector<int> newIndexMap(
size(), -1);
6186 for (
unsigned i = 0; i < out_n; i++) {
6192 std::vector<Grid::Shared> newGrids;
6194 for (
size_t i = 0; i <
gridCount(); ++i) {
6196 if (scanGrid->validCount !=
6211 if (scanGrid->validCount) {
6212 output->addGrid(scanGrid);
6215 }
catch (
const std::bad_alloc&) {
6218 QString(
"[ccPointCloud::SelectByIndex] Not enough "
6219 "memory to copy the grid structure(s)"));
6225 "ccPointCloud down sampled from {:d} points to {:d} points.",
6226 (
int)
size(), (
int)output->size());
constexpr unsigned char POINT_VISIBLE
constexpr unsigned char POINT_HIDDEN
constexpr ScalarType NAN_VALUE
NaN as a ScalarType value.
constexpr double EPSILON_VALUE
constexpr float MAX_POINT_SIZE_F
Vector3Tpl< PointCoordinateType > CCVector3
Default 3D Vector.
float PointCoordinateType
Type of the coordinates of a (N-D) point.
int64_t CV_CLASS_ENUM
Type of object type flags (64 bits)
std::shared_ptr< core::Tensor > image
virtual void link()
Increase counter.
virtual void release()
Decrease counter and deletes object when 0.
static bool Warning(const char *format,...)
Prints out a formatted warning message in console.
static bool Print(const char *format,...)
Prints out a formatted message in console.
static bool Error(const char *format,...)
Display an error dialog with formatted message.
Array of RGB colors for each point.
Array of compressed 3D normals (single index)
Array of RGBA colors for each point.
void normalize()
Sets vector norm to unity.
Type dot(const Vector3Tpl &v) const
Dot product.
Type norm() const
Returns vector norm.
static Vector3Tpl fromArray(const int a[3])
Constructor from an int array.
static void vadd(const PointCoordinateType p[], const PointCoordinateType q[], PointCoordinateType r[])
2D label (typically attached to points)
bool addPickedPoint(ccGenericPointCloud *cloud, unsigned pointIndex, bool entityCenter=false)
Adds a point to this label.
const PickedPoint & getPickedPoint(unsigned index) const
Returns a given point.
bool isCollapsed() const
Returns whether the label is collapsed or not.
const float * getPosition() const
Returns relative position.
void setCollapsed(bool state)
Whether to collapse label or not.
bool isPointLegendDisplayed() const
Returns whether the point(s) legend is displayed.
void setDisplayedIn2D(bool state)
Whether to display the label in 2D.
unsigned size() const
Returns current size.
void setPosition(float x, float y)
Sets relative position.
bool isDisplayedIn2D() const
Returns whether the label is displayed in 2D.
virtual QString getName() const override
Returns object name.
void displayPointLegend(bool state)
Whether to display the point(s) legend (title only)
Type & getValue(size_t index)
void fill(const Type &value)
bool isAllocated() const
Returns whether some memory has been allocated or not.
bool resizeSafe(size_t count, bool initNewElements=false, const Type *valueForNewElements=nullptr)
Resizes memory (no exception thrown)
bool reserveSafe(size_t count)
Reserves memory (no exception thrown)
void setValue(size_t index, const Type &value)
unsigned currentSize() const
void addElement(const Type &value)
void swap(size_t i1, size_t i2)
void clear(bool releaseMemory=false)
static ccBBox CreateFromPoints(const std::vector< CCVector3 > &points)
QSharedPointer< ccColorScale > Shared
Shared pointer type.
virtual bool colorsShown() const
Returns whether colors are shown or not.
virtual bool isVisible() const
Returns whether entity is visible or not.
virtual bool hasColors() const
Returns whether colors are enabled or not.
virtual void setVisible(bool state)
Sets entity visibility.
virtual bool sfShown() const
Returns whether active scalar field is visible.
virtual bool normalsShown() const
Returns whether normals are shown or not.
virtual bool hasNormals() const
Returns whether normals are enabled or not.
virtual bool isColorOverridden() const
virtual void enableTempColor(bool state)
Set temporary color activation state.
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.
ecvColor::Rgb m_tempColor
Temporary (unique) color.
static int OrientNormals(ccPointCloud *theCloud, unsigned char octreeLevel, ecvProgressDialog *progressCb=nullptr)
Static entry point (helper)
Ground-based Laser sensor.
PointCoordinateType getSensorRange() const
Returns the sensor max. range.
unsigned char checkVisibility(const CCVector3 &P) const override
void setSensorRange(PointCoordinateType range)
Sets the sensor max. range.
static ccGLMatrixTpl< float > FromEigenMatrix(const Eigen::Matrix< double, 4, 4 > &mat)
void applyRotation(Vector3Tpl< float > &vec) const
Applies rotation only to a 3D vector (in place) - float version.
T * data()
Returns a pointer to internal data.
void shiftRotationCenter(const Vector3Tpl< T > &vec)
Shifts rotation center.
void setRotation(const float Rt[9])
Sets Rotation from a float array.
void apply(float vec[3]) const
Applies transformation to a 3D vector (in place) - float version.
void setTranslation(const Vector3Tpl< float > &Tr)
Sets translation (float version)
virtual void toIdentity()
Sets matrix to identity.
Float version of ccGLMatrixTpl.
Double version of ccGLMatrixTpl.
void showNormals(bool state) override
Sets normals visibility.
A 3D cloud interface with associated features (color, normals, octree, etc.)
virtual const CCVector3 & getPointNormal(unsigned pointIndex) const =0
Returns normal corresponding to a given point.
virtual void deleteOctree()
Erases the octree.
bool fromFile_MeOnly(QFile &in, short dataVersion, int flags, LoadedIDMap &oldToNewIDMap) override
Loads own object data.
VisibilityTableType m_pointsVisibility
Per-point visibility table.
unsigned char getPointSize() const
Returns current point size.
virtual void refreshBB()=0
Forces bounding-box update.
virtual ccOctree::Shared computeOctree(cloudViewer::GenericProgressCallback *progressCb=nullptr, bool autoAddChild=true)
Computes the cloud octree.
virtual cloudViewer::ReferenceCloud * getTheVisiblePoints(const VisibilityTableType *visTable=nullptr, bool silent=false, cloudViewer::ReferenceCloud *selection=nullptr) const
Returns a ReferenceCloud equivalent to the visibility array.
virtual bool isVisibilityTableInstantiated() const
Returns whether the visibility array is allocated or not.
short minimumFileVersion_MeOnly() const override
virtual void clear()
Clears the entity from all its points and features.
bool toFile_MeOnly(QFile &out, short dataVersion) const override
Save own object data.
virtual const ecvColor::Rgb & getPointColor(unsigned pointIndex) const =0
Returns color corresponding to a given point.
virtual ccOctree::Shared getOctree() const
Returns the associated octree (if any)
ccBBox getOwnBB(bool withGLFeatures=false) override
Returns the entity's own bounding-box.
virtual bool resetVisibilityArray()
Resets the associated visibility array.
std::vector< unsigned char > VisibilityTableType
Array of "visibility" information for each point.
virtual const CompressedNormType & getPointNormalIndex(unsigned pointIndex) const =0
Returns compressed normal corresponding to a given point.
void importParametersFrom(const ccGenericPointCloud *cloud)
Imports the parameters from another cloud.
virtual void unallocateVisibilityArray()
Erases the points visibility information.
static bool CloneChildren(const ccHObject *sourceEntity, ccHObject *destEntity, std::vector< int > *newPointOrTriangleIndex=nullptr, const ccHObject *sourceEntityProxy=nullptr, ccHObject *destEntityProxy=nullptr)
Hierarchical CLOUDVIEWER Object.
virtual void notifyGeometryUpdate()
bool toFile(QFile &out, short dataVersion) const override
Saves data to binary stream.
ccGLMatrix m_glTransHistory
Cumulative GL transformation.
short minimumFileVersion() const override
Returns the minimum file version required to save this instance.
static void RotateCovariances(const Eigen::Matrix3d &R, std::vector< Eigen::Matrix3d > &covariances)
Rotate all covariance matrices with the rotation matrix R.
unsigned getChildrenNumber() const
Returns the number of children.
virtual void applyGLTransformation(const ccGLMatrix &trans)
Applies a GL transformation to the entity.
void transferChild(ccHObject *child, ccHObject &newParent)
Transfer a given child to another parent.
ccHObject * m_parent
Parent.
void removeChild(ccHObject *child)
unsigned filterChildren(Container &filteredChildren, bool recursive=false, CV_CLASS_ENUM filter=CV_TYPES::OBJECT, bool strict=false) const
Collects the children corresponding to a certain pattern.
virtual bool addChild(ccHObject *child, int dependencyFlags=DP_PARENT_OF_OTHER, int insertIndex=-1)
Adds a child.
bool fromFile(QFile &in, short dataVersion, int flags, LoadedIDMap &oldToNewIDMap) override
Loads data from binary stream.
std::vector< ccHObject * > Container
Standard instances container (for children, etc.)
static void TransformCovariances(const Eigen::Matrix4d &transformation, std::vector< Eigen::Matrix3d > &covariances)
Transforms all covariance matrices with the transformation.
ccHObject * getChild(unsigned childPos) const
Returns the ith child.
Container m_children
Children.
void translateBoundingBox(const CCVector3 &T)
Translates the bounding-box of the tree.
void multiplyBoundingBox(const PointCoordinateType multFactor)
Multiplies the bounding-box of the tree.
ccMesh * cloneMesh(ccGenericPointCloud *vertices=nullptr, ccMaterialSet *clonedMaterials=nullptr, NormsIndexesTableType *clonedNormsTable=nullptr, TextureCoordsContainer *cloneTexCoords=nullptr)
Clones this entity.
virtual unsigned size() const override
Returns the number of triangles.
bool reserve(std::size_t n)
Reserves the memory to store the vertex indexes (3 per triangle)
ccGenericPointCloud * getAssociatedCloud() const override
Returns the vertices cloud.
void shiftTriangleIndexes(unsigned shift)
Shifts all triangles indexes.
void addTriangle(unsigned i1, unsigned i2, unsigned i3)
Adds a triangle to the mesh.
void shrinkToFit()
Removes unused capacity.
static bool OrientNormals(ccPointCloud *cloud, unsigned kNN=6, ecvProgressDialog *progressDlg=0)
Main entry point.
static void InvertNormal(CompressedNormType &code)
Inverts a (compressed) normal.
const std::vector< ecvColor::Rgb > & getNormalHSVColorArray() const
Returns the HSV color array.
static void ConvertNormalToDipAndDipDir(const CCVector3 &N, PointCoordinateType &dip_deg, PointCoordinateType &dipDir_deg)
Converts a normal vector to geological 'dip direction & dip' parameters.
static bool ComputeCloudNormals(ccGenericPointCloud *cloud, NormsIndexesTableType &theNormsCodes, CV_LOCAL_MODEL_TYPES localModel, PointCoordinateType localRadius, Orientation preferredOrientation=UNDEFINED, cloudViewer::GenericProgressCallback *progressCb=nullptr, cloudViewer::DgmOctree *inputOctree=nullptr)
Computes normal at each point of a given cloud.
static const CCVector3 & GetNormal(unsigned normIndex)
Static access to ccNormalVectors::getNormal.
static unsigned GetNumberOfVectors()
Returns the number of compressed normal vectors.
Orientation
'Default' orientations
static ccNormalVectors * GetUniqueInstance()
Returns unique instance.
static CompressedNormType GetNormIndex(const PointCoordinateType N[])
Returns the compressed index corresponding to a normal vector.
static CCVector3 & GetNormalPtr(unsigned normIndex)
virtual bool isLocked() const
Returns whether the object is locked or not.
virtual QString getName() const
Returns object name.
virtual unsigned getUniqueID() const
Returns object unique ID.
bool isA(CV_CLASS_ENUM type) const
static CV_CLASS_ENUM ReadClassIDFromFile(QFile &in, short dataVersion)
Helper: reads out class ID from a binary stream.
virtual void setName(const QString &name)
Sets object name.
virtual void setEnabled(bool state)
Sets the "enabled" property.
virtual bool isEnabled() const
Returns whether the object is enabled or not.
bool isKindOf(CV_CLASS_ENUM type) const
QSharedPointer< ccOctree > Shared
Shared pointer.
L.O.D. (Level of Detail) structure.
void clear()
Clears the structure.
bool init(ccPointCloud *cloud)
Initializes the construction process (asynchronous)
int init(int count, bool withColors, bool withNormals, bool *reallocated=nullptr)
Inits the VBO.
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 drawMeOnly(CC_DRAW_CONTEXT &context) override
Draws the entity only (not its children)
void addEigenNorm(const Eigen::Vector3d &N)
std::vector< CCVector3 * > getPointNormalsPtr() const
void setCurrentDisplayedScalarField(int index)
Sets the currently displayed scalar field.
void addRGBColors(const std::vector< ecvColor::Rgb > &colors)
void setEigenColor(size_t index, const Eigen::Vector3d &color)
ccScalarField * m_currentDisplayedScalarField
Currently displayed scalar field.
ecvColor::Rgb & getPointColorPtr(size_t pointIndex)
void addColorRampInfo(CC_DRAW_CONTEXT &context)
Adds associated SF color ramp info to current GL context.
std::vector< ccWaveform > m_fwfWaveforms
Per-point waveform accessors.
std::vector< Eigen::Vector3d > getEigenNormals() const
bool sfColorScaleShown() const
Returns whether color scale should be displayed or not.
vboSet m_vboManager
Set of VBOs attached to this cloud.
std::vector< CompressedNormType > getNorms() const
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.
bool m_sfColorScaleDisplayed
void clearFWFData()
Clears all associated FWF data.
~ccPointCloud() override
Default destructor.
ScalarType getPointDisplayedDistance(unsigned pointIndex) const override
Returns scalar value associated to a given point.
virtual void removePoints(size_t index) override
bool resizeTheNormsTable()
Resizes the compressed normals array.
void addNorms(const std::vector< CCVector3 > &Ns)
void unallocateColors()
Erases the cloud colors.
NormsIndexesTableType * m_normals
Normals (compressed)
virtual void scale(PointCoordinateType fx, PointCoordinateType fy, PointCoordinateType fz, CCVector3 center=CCVector3(0, 0, 0)) override
Multiplies all coordinates by constant factors (one per dimension)
void deleteAllScalarFields() override
Deletes all scalar fields associated to this cloud.
void refreshBB() override
Forces bounding-box update.
bool initLOD()
Intializes the LOD structure.
void addEigenColor(const Eigen::Vector3d &color)
virtual ccBBox GetAxisAlignedBoundingBox() const override
Returns an axis-aligned bounding box of the geometry.
cloudViewer::ReferenceCloud * crop2D(const ccPolyline *poly, unsigned char orthoDim, bool inside=true)
Crops the cloud inside (or outside) a 2D polyline.
void getDrawingParameters(glDrawParams ¶ms) const override
Returns main OpenGL parameters for this entity.
void setEigenNormal(size_t index, const Eigen::Vector3d &normal)
void setPointNormalIndex(size_t pointIndex, CompressedNormType norm)
Sets a particular point compressed normal.
void addEigenNorms(const std::vector< Eigen::Vector3d > &normals)
bool orientNormalsTowardViewPoint(CCVector3 &VP, ecvProgressDialog *pDlg=nullptr)
Normals are forced to point to O.
bool HasCovariances() const
Returns 'true' if the point cloud contains per-point covariance matrix.
const ecvColor::Rgb * getScalarValueColor(ScalarType d) const override
Returns color corresponding to a given scalar value.
void setEigenColors(const std::vector< Eigen::Vector3d > &colors)
void setNormsTable(NormsIndexesTableType *norms)
Sets the (compressed) normals table.
ccPointCloudLOD * m_lod
L.O.D. structure.
Eigen::Vector3d getEigenNormal(size_t index) const
bool convertRGBToGreyScale()
Converts RGB to grey scale colors.
bool fromFile_MeOnly(QFile &in, short dataVersion, int flags, LoadedIDMap &oldToNewIDMap) override
Loads own object data.
void addNorm(const CCVector3 &N)
Pushes a normal vector on stack (shortcut)
NormsIndexesTableType * normals() const
Returns pointer on compressed normals indexes table.
ccPointCloud * unroll(UnrollMode mode, UnrollBaseParams *params, bool exportDeviationSF=false, double startAngle_deg=0.0, double stopAngle_deg=360.0, cloudViewer::GenericProgressCallback *progressCb=nullptr) const
Unrolls the cloud and its normals on a cylinder or a cone.
std::vector< CCVector3 > getPointNormals() const
short minimumFileVersion_MeOnly() const override
std::vector< ccWaveform > & waveforms()
Gives access to the associated FWF data.
ccPointCloud * partialClone(const cloudViewer::ReferenceCloud *selection, int *warnings=nullptr, bool withChildEntities=true) const
Creates a new point cloud object from a ReferenceCloud (selection)
ccScalarField * getCurrentDisplayedScalarField() const
Returns the currently displayed scalar (or 0 if none)
bool computeNormalsWithGrids(double minTriangleAngle_deg=1.0, ecvProgressDialog *pDlg=nullptr)
Compute the normals with the associated grid structure(s)
bool reserveTheFWFTable()
Reserves the FWF table.
QSharedPointer< const FWFDataContainer > SharedFWFDataContainer
const ccPointCloud & operator+=(const ccPointCloud &cloud)
ccWaveformProxy waveformProxy(unsigned index) const
Returns a proxy on a given waveform.
int addScalarField(const char *uniqueName) override
Creates a new scalar field and registers it.
bool interpolateColorsFrom(ccGenericPointCloud *cloud, cloudViewer::GenericProgressCallback *progressCb=nullptr, unsigned char octreeLevel=0)
Interpolate colors from another cloud (nearest neighbor only)
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)
void applyGLTransformation(const ccGLMatrix &trans) override
Applies a GL transformation to the entity.
bool resizeTheRGBTable(bool fillWithWhite=false)
Resizes the RGB colors array.
void normalsHaveChanged()
Notify a modification of normals display parameters or contents.
const ecvColor::Rgb * getPointScalarValueColor(unsigned pointIndex) const override
Returns color corresponding to a given point associated scalar value.
const ccPointCloud & append(ccPointCloud *cloud, unsigned pointCountBefore, bool ignoreChildren=false)
Appends a cloud to this one.
void notifyGeometryUpdate() override
virtual ccPointCloud & Rotate(const Eigen::Matrix3d &R, const Eigen::Vector3d ¢er) override
Apply rotation to the geometry coordinates and normals. Given a rotation matrix , and center ,...
void showSFColorsScale(bool state)
Sets whether color scale should be displayed or not.
unsigned char testVisibility(const CCVector3 &P) const override
void unalloactePoints()
Erases the cloud points.
int m_currentDisplayedScalarFieldIndex
Currently displayed scalar field index.
void invalidateBoundingBox() override
Invalidates bounding box.
bool computeNormalsWithOctree(CV_LOCAL_MODEL_TYPES model, ccNormalVectors::Orientation preferredOrientation, PointCoordinateType defaultRadius, ecvProgressDialog *pDlg=nullptr)
Compute the normals by approximating the local surface around each point.
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 resizeTheFWFTable()
Resizes the FWF table.
bool removeVisiblePoints(VisibilityTableType *visTable=nullptr, std::vector< int > *newIndexes=nullptr) override
Removes all the 'visible' points (as defined by the visibility array)
bool hasFWF() const
Returns whether the cloud has associated Full WaveForm data.
const CompressedNormType & getPointNormalIndex(unsigned pointIndex) const override
Returns compressed normal corresponding to a given point.
bool exportCoordToSF(bool exportDims[3])
Exports the specified coordinate dimension(s) to scalar field(s)
virtual ccPointCloud & Translate(const Eigen::Vector3d &translation, bool relative=true) override
Apply translation to the geometry coordinates.
ccPointCloud(QString name=QString())
Default constructor.
bool computeFWFAmplitude(double &minVal, double &maxVal, ecvProgressDialog *pDlg=nullptr) const
Computes the maximum amplitude of all associated waveforms.
void releaseVBOs()
Release VBOs.
bool orientNormalsWithMST(unsigned kNN=6, ecvProgressDialog *pDlg=nullptr)
Orient the normals with a Minimum Spanning Tree.
ccGenericPointCloud * createNewCloudFromVisibilitySelection(bool removeSelectedPoints=false, VisibilityTableType *visTable=nullptr, std::vector< int > *newIndexesOfRemainingPoints=nullptr, bool silent=false, cloudViewer::ReferenceCloud *selection=nullptr) override
bool colorize(float r, float g, float b)
Multiplies all color components of all points by coefficients.
static ccPointCloud * From(const cloudViewer::GenericIndexedCloud *cloud, const ccGenericPointCloud *sourceCloud=nullptr)
Creates a new point cloud object from a GenericIndexedCloud.
void setEigenNormals(const std::vector< Eigen::Vector3d > &normals)
void hidePointsByScalarValue(ScalarType minVal, ScalarType maxVal)
Hides points whose scalar values falls into an interval.
bool hasDisplayedScalarField() const override
Returns whether an active scalar field is available or not.
bool reserveTheNormsTable()
Reserves memory to store the compressed normals.
ccPointCloud & operator=(const ccPointCloud &cloud)
Fuses another 3D entity with this one.
virtual ccPointCloud & Scale(const double s, const Eigen::Vector3d ¢er) override
Apply scaling to the geometry coordinates. Given a scaling factor , and center , a given point is tr...
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.
bool reserveTheRGBTable()
Reserves memory to store the RGB colors.
bool compressFWFData()
Compresses the associated FWF data container.
std::shared_ptr< ccPointCloud > SelectByIndex(const std::vector< size_t > &indices, bool invert=false) const
Function to select points from input ccPointCloud into output ccPointCloud.
bool m_visibilityCheckEnabled
Whether visibility check is available or not (during comparison)
int getCurrentDisplayedScalarFieldIndex() const
Returns the currently displayed scalar field index (or -1 if none)
void clear() override
Clears the entity from all its points and features.
void addNormAtIndex(const PointCoordinateType *N, unsigned index)
Adds a normal vector to the one at a specific index.
void unallocateNorms()
Erases the cloud normals.
void swapPoints(unsigned firstIndex, unsigned secondIndex) override
virtual void applyRigidTransformation(const ccGLMatrix &trans) override
Applies a rigid transformation (rotation + translation)
bool toFile_MeOnly(QFile &out, short dataVersion) const override
Save own object data.
bool hasColors() const override
Returns whether colors are enabled or not.
std::vector< uint8_t > FWFDataContainer
Waveform data container.
unsigned getUniqueIDForDisplay() const override
Returns object unqiue ID used for display.
bool resize(unsigned numberOfPoints) override
Resizes all the active features arrays.
ccPointCloud * cloneThis(ccPointCloud *destCloud=nullptr, bool ignoreChildren=false)
Clones this entity.
std::vector< Grid::Shared > m_grids
Associated grid structure.
bool setRGBColorByHeight(unsigned char heightDim, ccColorScale::Shared colorScale)
Assigns color to points proportionnaly to their 'height'.
void setPointNormals(const std::vector< CCVector3 > &normals)
void deleteScalarField(int index) override
Deletes a specific scalar field.
const CCVector3 * getNormal(unsigned pointIndex) const override
If per-point normals are available, returns the one at a specific index.
void setPointColor(size_t pointIndex, const ecvColor::Rgb &col)
Sets a particular point color.
bool addGrid(Grid::Shared grid)
Adds an associated grid.
void setPointNormal(size_t pointIndex, const CCVector3 &N)
Sets a particular point normal (shortcut)
const CCVector3 & getPointNormal(unsigned pointIndex) const override
Returns normal corresponding to a given point.
SharedFWFDataContainer & fwfData()
Gives access to the associated FWF data container.
ColorsTableType * m_rgbColors
Colors.
SharedFWFDataContainer m_fwfData
Waveforms raw data storage.
Grid::Shared & grid(size_t gridIndex)
Returns an associated grid.
std::vector< Eigen::Matrix3d > covariances_
Covariance Matrix for each point.
Eigen::Vector3d getEigenColor(size_t index) const
void addEigenColors(const std::vector< Eigen::Vector3d > &colors)
ccMesh * triangulateGrid(const Grid &grid, double minTriangleAngle_deg=0.0) const
Meshes a scan grid.
FWFDescriptorSet m_fwfDescriptors
General waveform descriptors.
void addRGBColor(const ecvColor::Rgb &C)
Pushes an RGB color on stack.
bool convertCurrentScalarFieldToColors(bool mixWithExistingColor=false)
CCVector3 computeGravityCenter()
Returns the cloud gravity center.
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.
void addNormIndex(CompressedNormType index)
Pushes a compressed normal vector.
ccPointCloud * filterPointsByScalarValue(ScalarType minVal, ScalarType maxVal, bool outside=false)
Filters out points whose scalar values falls into an interval.
const ecvColor::Rgb & getPointColor(unsigned pointIndex) const override
Returns color corresponding to a given point.
virtual ccPointCloud & Transform(const Eigen::Matrix4d &trans) override
Apply transformation (4x4 matrix) to the geometry coordinates.
virtual ecvOrientedBBox GetOrientedBoundingBox() const override
void clearLOD()
Clears the LOD structure.
bool reserveThePointsTable(unsigned _numberOfPoints)
Reserves memory to store the points coordinates.
bool orientNormalsWithGrids(ecvProgressDialog *pDlg=nullptr)
Orient the normals with the associated grid structure(s)
bool setRGBColorWithCurrentScalarField(bool mixWithExistingColor=false)
Sets RGB colors with current scalar field (values & parameters)
CCVector3 & getPointNormalPtr(size_t pointIndex) const
std::vector< Eigen::Vector3d > getEigenColors() const
cloudViewer::ReferenceCloud * crop(const ccBBox &box, bool inside=true) override
Crops the cloud inside (or outside) a bounding box.
QSharedPointer< cloudViewer::ReferenceCloud > computeCPSet(ccGenericPointCloud &otherCloud, cloudViewer::GenericProgressCallback *progressCb=nullptr, unsigned char octreeLevel=0)
Computes the closest point of this cloud relatively to another cloud.
@ WRN_OUT_OF_MEM_FOR_COLORS
@ WRN_OUT_OF_MEM_FOR_NORMALS
void invertNormals()
Inverts normals (if any)
ccGenericPointCloud * clone(ccGenericPointCloud *destCloud=nullptr, bool ignoreChildren=false) override
Clones this entity.
size_t gridCount() const
Returns the number of associated grids.
Scalar field range structure.
A scalar field associated to display-related parameters.
const ccColorScale::Shared & getColorScale() const
Returns associated color scale.
void setGlobalShift(double shift)
Sets the global shift.
bool toFile(QFile &out, short dataVersion) const override
Saves data to binary stream.
double getGlobalShift() const
Returns the global shift (if any)
bool fromFile(QFile &in, short dataVersion, int flags, LoadedIDMap &oldToNewIDMap) override
Loads data from binary stream.
const ecvColor::Rgb * getColor(ScalarType value) const
void computeMinAndMax() override
Determines the min and max values.
void importParametersFrom(const ccScalarField *sf)
Imports the parameters from another scalar field.
const ecvColor::Rgb * getValueColor(unsigned index) const
Shortcut to getColor.
bool areNaNValuesShownInGrey() const
Returns whether NaN values are displayed in gray or hidden.
Generic sensor interface.
virtual void applyGLTransformation(const ccGLMatrix &trans) override
Applies a GL transformation to the entity.
static bool CorruptError()
Sends a custom error message (corrupted file) and returns 'false'.
QMultiMap< unsigned, unsigned > LoadedIDMap
Map of loaded unique IDs (old ID --> new ID)
static bool ReadError()
Sends a custom error message (read error) and returns 'false'.
@ DF_POINT_COORDS_64_BITS
static bool WriteError()
Sends a custom error message (write error) and returns 'false'.
static bool MemoryError()
Sends a custom error message (not enough memory) and returns 'false'.
static bool GenericArrayFromFile(std::vector< Type > &data, QFile &in, short dataVersion, const QString &verboseDescription)
Helper: loads a vector structure from file.
static bool GenericArrayToFile(const std::vector< Type > &data, QFile &out)
Helper: saves a vector to file.
static bool GenericArrayFromTypedFile(std::vector< Type > &data, QFile &in, short dataVersion, const QString &verboseDescription, FileComponentType *_autoOffset=nullptr)
static short GenericArrayToFileMinVersion()
Returns the minimum file version to save/load a 'generic array'.
bool isShifted() const
Returns whether the cloud is shifted or not.
virtual void setGlobalShift(double x, double y, double z)
Sets shift applied to original coordinates (information storage only)
virtual const CCVector3d & getGlobalShift() const
Returns the shift applied to original coordinates.
virtual void setGlobalScale(double scale)
virtual double getGlobalScale() const
Returns the scale applied to original coordinates.
Vector3Tpl< T > getDiagVec() const
Returns diagonal vector.
Vector3Tpl< T > getCenter() const
Returns center.
bool contains(const Vector3Tpl< T > &P) const
Returns whether a points is inside the box or not.
const Vector3Tpl< T > & minCorner() const
Returns min corner (const)
bool isValid() const
Returns whether bounding box is valid or not.
void getCellPos(CellCode code, unsigned char level, Tuple3i &cellPos, bool isCodeTruncated) const
unsigned char findBestLevelForAGivenNeighbourhoodSizeExtraction(PointCoordinateType radius) const
int findNeighborsInASphereStartingFromCell(NearestNeighboursSearchStruct &nNSS, double radius, bool sortValues=true) const
Advanced form of the nearest neighbours search algorithm (in a sphere)
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)
virtual void placeIteratorAtBeginning()=0
Sets the cloud iterator at the beginning.
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 bool hasPoints() const
A generic 3D point cloud with index-based point access.
virtual const CCVector3 * getPoint(unsigned index) const =0
Returns the ith point.
virtual void stop()=0
Notifies the fact that the process has ended.
virtual void setInfo(const char *infoStr)=0
Notifies some information about the ongoing process.
virtual void setMethodTitle(const char *methodTitle)=0
Notifies the algorithm title.
virtual bool textCanBeEdited() const
Returns whether the dialog title and info can be updated or not.
virtual void update(float percent)=0
Notifies the algorithm progress.
bool oneStep()
Increments total progress value of a single unit.
std::vector< size_t > GetPointIndicesWithinBoundingBox(const std::vector< Eigen::Vector3d > &points) const
Return indices to points that are within the bounding box.
std::vector< ScalarField * > m_scalarFields
Associated scalar fields.
std::vector< CCVector3 > m_points
3D Points database
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 reset()
Clears the cloud database.
virtual void swapPoints(unsigned firstIndex, unsigned secondIndex)
Swaps two points (and their associated scalar values!)
virtual void deleteScalarField(int index)
Deletes a specific scalar field.
virtual void invalidateBoundingBox()
Invalidates bounding box.
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 setPointScalarValue(unsigned pointIndex, ScalarType value) override
CCVector3 * point(unsigned index)
Returns non const access to a given point.
virtual bool reserve(unsigned newCapacity)
Reserves memory for the point database.
void setCurrentScalarField(int index)
Sets both the INPUT & OUTPUT scalar field.
void addPoint(const CCVector3 &P)
Adds a 3D point to the database.
const CCVector3 * getPointPersistentPtr(unsigned index) override
Returns the ith point as a persistent pointer.
unsigned size() const override
Returns the number of points.
virtual void deleteAllScalarFields()
Deletes all scalar fields associated to this cloud.
ScalarType getPointScalarValue(unsigned pointIndex) const override
int m_currentInScalarFieldIndex
Index of current scalar field used for input.
virtual bool resize(unsigned newCount)
Resizes the point database.
void setCurrentInScalarField(int index)
Sets the INPUT scalar field.
int m_currentOutScalarFieldIndex
Index of current scalar field used for output.
const CCVector3 * getPoint(unsigned index) const override
void addPoints(const std::vector< CCVector3 > &points)
A very simple point cloud (no point duplication)
virtual bool addPointIndex(unsigned globalIndex)
Point global index insertion mechanism.
virtual GenericIndexedCloudPersist * getAssociatedCloud()
Returns the associated (source) cloud.
unsigned size() const override
Returns the number of points.
virtual unsigned getPointGlobalIndex(unsigned localIndex) const
virtual bool resize(unsigned n)
Presets the size of the vector used to store point references.
virtual unsigned capacity() const
Returns max capacity.
virtual void clear(bool releaseMemory=false)
Clears the cloud.
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.
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.
void addElement(ScalarType value)
static ScalarType NaN()
Returns the specific NaN value.
ScalarType & getValue(std::size_t index)
void setValue(std::size_t index, ScalarType value)
const char * getName() const
Returns scalar field name.
bool reserveSafe(std::size_t count)
Reserves memory (no exception thrown)
bool resizeSafe(std::size_t count, bool initNewElements=false, ScalarType valueForNewElements=0)
Resizes memory (no exception thrown)
static bool ValidValue(ScalarType value)
Returns whether a scalar value is valid or not.
unsigned currentSize() const
ScalarType getMax() const
Returns the maximum value.
constexpr static RgbTpl FromEigen(const Eigen::Vector3d &t)
static Eigen::Vector3d ToEigen(const Type col[3])
virtual bool IsEmpty() const override
static ecvOrientedBBox CreateFromPoints(const std::vector< Eigen::Vector3d > &points)
Graphical progress indicator (thread-safe)
unsigned int CompressedNormType
Compressed normals type.
unsigned char ColorCompType
Default color components type (R,G and B)
#define MACRO_Draw2D(context)
#define MACRO_Draw3D(context)
#define MACRO_LightIsEnabled(context)
#define MACRO_Foreground(context)
#define MACRO_FastEntityPicking(context)
#define MACRO_EntityPicking(context)
std::vector< unsigned > LODIndexSet
L.O.D. indexes set.
static void ProjectOnCylinder(const CCVector3 &AP, const Tuple3ub &dim, PointCoordinateType radius, PointCoordinateType &delta, PointCoordinateType &phi_rad)
float GetSymmetricalNormalizedValue(const ScalarType &sfVal, const ccScalarField::Range &saturationRange)
void UpdateGridIndexes(const std::vector< int > &newIndexMap, std::vector< ccPointCloud::Grid::Shared > &grids)
float GetNormalizedValue(const ScalarType &sfVal, const ccScalarField::Range &displayRange)
static bool ComputeCellGaussianFilter(const cloudViewer::DgmOctree::octreeCell &cell, void **additionalParameters, cloudViewer::NormalizedProgress *nProgress=nullptr)
static void ProjectOnCone(const CCVector3 &AP, PointCoordinateType alpha_rad, const Tuple3ub &dim, PointCoordinateType &s, PointCoordinateType &delta, PointCoordinateType &phi_rad)
static const unsigned MAX_POINT_COUNT_PER_LOD_RENDER_PASS
Maximum number of points (per cloud) displayed in a single LOD iteration.
static bool CatchGLErrors(GLenum err, const char *context)
static const char s_deviationSFName[]
MiniVec< float, N > ceil(const MiniVec< float, N > &a)
float DegreesToRadians(int degrees)
Convert degrees to radians.
bool LessThanEpsilon(float x)
Test a floating point number against our epsilon (a very small number).
constexpr Rgb black(0, 0, 0)
constexpr Rgb white(MAX, MAX, MAX)
constexpr ColorCompType MAX
Max value of a single color component (default type)
Rgb FromRgbaToRgb(const Rgba &color)
Conversion from Rgba to Rgb.
DisplayDesc & operator=(const LODLevelDesc &desc)
Set operator.
DisplayDesc()
Default constructor.
LODIndexSet * indexMap
Map of indexes (to invert the natural order)
unsigned endIndex
Last index (excluded)
unsigned decimStep
Decimation step (for non-octree based LoD)
DisplayDesc(unsigned startIndex, unsigned count)
Constructor from a start index and a count value.
unsigned count
Index count for this level.
unsigned startIndex
Start index (refers to the 'indexes' table)
unsigned index
Point/triangle index.
ccGenericPointCloud * cloud
Cloud.
bool fromFile(QFile &in, short dataVersion, int flags, LoadedIDMap &oldToNewIDMap) override
Loads data from binary stream.
short minimumFileVersion() const override
Returns the minimum file version required to save this instance.
ccGLMatrixd sensorPosition
Sensor position (expressed relatively to the cloud points)
Grid()
Default constructor.
QImage toImage() const
Converts the grid to an RGB image (needs colors)
bool toFile(QFile &out, short dataVersion) const override
Saves data to binary stream.
void setIndex(unsigned row, unsigned col, int index)
Sets an index at a given position inside the grid.
void updateMinAndMaxValidIndexes()
Updates the min and max valid indexes.
void setColor(unsigned row, unsigned col, const ecvColor::Rgb &rgb)
Sets a color at a given position inside the grid.
bool init(unsigned rowCount, unsigned colCount, bool withRGB=false)
Inits the grid.
QSharedPointer< Grid > Shared
Shared type.
unsigned char blendGrayscaleThreshold
double blendGrayscalePercent
unsigned char burntOutColorThreshold
RGB_FILTER_TYPES filterType
PointCoordinateType radius
unrolling cylinder radius (or cone base radius)
unsigned char axisDim
unrolling cylinder/cone axis (X=0, Y=1 or Z=2)
double coneAngle_deg
Cone apex.
STATES state
Current state.
std::vector< VBO * > vbos
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.
Display parameters of a 3D entity.
bool showColors
Display colors.
bool showNorms
Display normals.
bool showSF
Display scalar field (prioritary on colors)