bool Cloud2CloudDist::Compute( const Cloth& cloth, const wl::PointCloud& pc, double class_threshold, std::vector<int>& groundIndexes, std::vector<int>& offGroundIndexes, unsigned N/*=3*/) { CCLib::SimpleCloud particlePoints; if (!particlePoints.reserve(static_cast<unsigned>(cloth.getSize()))) { //not enough memory return false; } for (int i = 0; i < cloth.getSize(); i++) { const Particle& particle = cloth.getParticleByIndex(i); particlePoints.addPoint(CCVector3(static_cast<PointCoordinateType>(particle.pos.x), 0, static_cast<PointCoordinateType>(particle.pos.z))); } CCLib::SimpleCloud pcPoints; if ( !pcPoints.reserve(static_cast<unsigned>(pc.size())) || !pcPoints.enableScalarField()) { //not enough memory return false; } for (size_t i = 0; i < pc.size(); i++) { const wl::Point& P = pc[i]; pcPoints.addPoint(CCVector3(P.x, 0, P.z)); } try { //we spatially 'synchronize' the cloud and particles octrees CCLib::DgmOctree *cloudOctree = 0, *particleOctree = 0; CCLib::DistanceComputationTools::SOReturnCode soCode = CCLib::DistanceComputationTools::synchronizeOctrees ( &particlePoints, &pcPoints, particleOctree, cloudOctree, 0, 0 ); if (soCode != CCLib::DistanceComputationTools::SYNCHRONIZED && soCode != CCLib::DistanceComputationTools::DISJOINT) { //not enough memory (or invalid input) return false; } //additional parameters void* additionalParameters[] = {(void*)(&cloth), (void*)(particleOctree), (void*)(&N) }; int octreeLevel = particleOctree->findBestLevelForAGivenPopulationPerCell(std::max<unsigned>(2, N)); int result = cloudOctree->executeFunctionForAllCellsAtLevel( octreeLevel, ComputeMeanNeighborAltitude, additionalParameters, true, 0, "Rasterization", QThread::idealThreadCount()); delete cloudOctree; cloudOctree = 0; delete particleOctree; particleOctree = 0; if (result == 0) { //something went wrong return false; } //now classify the points for (unsigned i = 0; i < pcPoints.size(); ++i) { if (std::fabs(pcPoints.getPointScalarValue(i) - pc[i].y) < class_threshold) { groundIndexes.push_back(i); } else { offGroundIndexes.push_back(i); } } } catch (const std::bad_alloc&) { //not enough memory return false; } return true; }
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; }