bool ccMinimumSpanningTreeForNormsDirection::Process( ccPointCloud* cloud, CCLib::GenericProgressCallback* progressCb/*=0*/, CCLib::DgmOctree* _octree/*=0*/) { assert(cloud); if (!cloud->hasNormals()) { ccLog::Warning(QString("Cloud '%1' has no normals!").arg(cloud->getName())); return false; } //ask for parameter bool ok; #ifdef MST_USE_KNN unsigned kNN = static_cast<unsigned>(QInputDialog::getInt(0,"Neighborhood size", "Neighbors", 6, 1, 1000, 1, &ok)); if (!ok) return false; #else PointCoordinateType radius = static_cast<PointCoordinateType>(QInputDialog::getDouble(0,"Neighborhood radius", "radius", cloud->getOwnBB().getDiagNorm() * 0.01, 0, 1.0e9, 6, &ok)); if (!ok) return false; #endif //build octree if necessary CCLib::DgmOctree* octree = _octree; if (!octree) { octree = new CCLib::DgmOctree(cloud); if (octree->build(progressCb) <= 0) { ccLog::Warning(QString("Failed to compute octree on cloud '%1'").arg(cloud->getName())); delete octree; return false; } } #ifdef MST_USE_KNN uchar level = octree->findBestLevelForAGivenPopulationPerCell(kNN*2); #else uchar level = octree->findBestLevelForAGivenNeighbourhoodSizeExtraction(radius); #endif bool result = true; try { Graph graph; if (!graph.reserve(cloud->size())) { //not enough memory! result = false; } //parameters void* additionalParameters[3] = { reinterpret_cast<void*>(&graph), reinterpret_cast<void*>(cloud), #ifdef MST_USE_KNN reinterpret_cast<void*>(&kNN) #else reinterpret_cast<void*>(&radius) #endif }; if (octree->executeFunctionForAllCellsAtLevel( level, &ComputeMSTGraphAtLevel, additionalParameters, false, //not compatible with parallel strategies! progressCb, "Build Spanning Tree") == 0) { //something went wrong ccLog::Warning(QString("Failed to compute Spanning Tree on cloud '%1'").arg(cloud->getName())); result = false; } else { if (!ResolveNormalsWithMST(cloud,graph,progressCb)) { //something went wrong ccLog::Warning(QString("Failed to compute Minimum Spanning Tree on cloud '%1'").arg(cloud->getName())); result = false; } } } catch(...) { ccLog::Error(QString("Process failed on cloud '%1'").arg(cloud->getName())); result = false; } if (octree && !_octree) { delete octree; octree = 0; } return result; }
bool ccMinimumSpanningTreeForNormsDirection::OrientNormals( ccPointCloud* cloud, unsigned kNN/*=6*/, ccProgressDialog* progressDlg/*=0*/) { assert(cloud); if (!cloud->hasNormals()) { ccLog::Warning(QString("Cloud '%1' has no normals!").arg(cloud->getName())); return false; } //we need the octree if (!cloud->getOctree()) { if (!cloud->computeOctree(progressDlg)) { ccLog::Warning(QString("[orientNormalsWithMST] Could not compute octree on cloud '%1'").arg(cloud->getName())); return false; } } ccOctree::Shared octree = cloud->getOctree(); assert(octree); unsigned char level = octree->findBestLevelForAGivenPopulationPerCell(kNN*2); bool result = true; try { Graph graph; if (!graph.reserve(cloud->size())) { //not enough memory! result = false; } //parameters void* additionalParameters[3] = { reinterpret_cast<void*>(&graph), reinterpret_cast<void*>(cloud), reinterpret_cast<void*>(&kNN) }; if (octree->executeFunctionForAllCellsAtLevel( level, &ComputeMSTGraphAtLevel, additionalParameters, false, //not compatible with parallel strategies! progressDlg, "Build Spanning Tree") == 0) { //something went wrong ccLog::Warning(QString("Failed to compute Spanning Tree on cloud '%1'").arg(cloud->getName())); result = false; } else { if (!ResolveNormalsWithMST(cloud, graph, progressDlg)) { //something went wrong ccLog::Warning(QString("Failed to compute Minimum Spanning Tree on cloud '%1'").arg(cloud->getName())); result = false; } } } catch (...) { ccLog::Error(QString("Process failed on cloud '%1'").arg(cloud->getName())); result = false; } return result; }