/**************************************************************************** * VCGLib o o * * Visual and Computer Graphics Library o o * * _ O _ * * Copyright(C) 2004-2016 \/)\/ * * Visual Computing Lab /\/| * * ISTI - Italian National Research Council | * * \ * * All rights reserved. * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU General Public License (http://www.gnu.org/licenses/gpl.txt) * * for more details. * * * ****************************************************************************/ #ifndef VCG__SKELETON_H #define VCG__SKELETON_H #include namespace vcg { namespace tri { template class SampledSkeleton { public: typedef typename MeshType::ScalarType ScalarType; typedef typename MeshType::BoxType BoxType; typedef typename MeshType::VertexIterator VertexIterator; typedef typename MeshType::VertexPointer VertexPointer; typedef typename MeshType::CoordType CoordType; typedef typename MeshType::FacePointer FacePointer; typedef typename MeshType::FaceType FaceType; typedef VoronoiVolumeSampling VoronoiVolumeSamplingType; SampledSkeleton(VoronoiVolumeSamplingType &_vvs):vvs(_vvs){} VoronoiVolumeSamplingType &vvs; /** * @brief Compute an evaulation of the thickness as distance from the medial axis. * It starts from a montecarlo volume sampling and try to search for the samples that can be part of the medial axis. * It use a sampled representation of the surface. A volume sample is considered part * of the medial axis if there are at least two points that are (almost) the same minimal distance to that point. * * */ void ThicknessEvaluator(float distThr, int smoothSize, int smoothIter, MeshType *skelM=0) { tri::UpdateQuality::VertexConstant(vvs.psd.poissonSurfaceMesh,0); std::vector medialSrc(vvs.psd.poissonSurfaceMesh.vert.size(),0); for(VertexIterator vi=vvs.montecarloVolumeMesh.vert.begin(); vi!=vvs.montecarloVolumeMesh.vert.end(); ++vi) { unsigned int ind; ScalarType sqdist; this->vvs.psd.surfTree->doQueryClosest(vi->P(),ind,sqdist); VertexPointer vp = &vvs.psd.poissonSurfaceMesh.vert[ind]; ScalarType minDist = math::Sqrt(sqdist); if(vp->Q() < minDist) { std::vector indVec; std::vector sqDistVec; this->vvs.psd.surfTree->doQueryDist( vi->P(), minDist*distThr,indVec,sqDistVec); if(indVec.size()>1) { for(size_t i=0;iQ() < minDist) { vp->Q()=minDist; medialSrc[indVec[i]]=&*vi; } } } } } // Now collect the vertexes of the volume mesh that are on the medial surface if(skelM) { tri::UpdateFlags::VertexClearV(vvs.montecarloVolumeMesh); for(size_t i=0;iSetV(); for(VertexIterator vi=vvs.montecarloVolumeMesh.vert.begin(); vi!=vvs.montecarloVolumeMesh.vert.end(); ++vi) if(vi->IsV()) tri::Allocator::AddVertex(*skelM,vi->P()); printf("Generated a medial surf of %i vertexes\n",skelM->vn); } tri::Smooth::PointCloudQualityMedian(vvs.psd.poissonSurfaceMesh); tri::Smooth::PointCloudQualityAverage(vvs.psd.poissonSurfaceMesh,smoothSize,smoothIter); tri::UpdateColor::PerVertexQualityRamp(vvs.psd.poissonSurfaceMesh); tri::RedetailSampler rs; rs.init(&vvs.psd.poissonSurfaceMesh); rs.dist_upper_bound = vvs.psd.poissonSurfaceMesh.bbox.Diag()*0.05 ; rs.qualityFlag = true; tri::SurfaceSampling >::VertexUniform(vvs.baseMesh, rs, vvs.baseMesh.vn, false); } void RefineSkeletonVolume(MeshType &skelMesh) { CoordType closestP; int trialNum=0; for(int i=0;iDistanceFromSurface(point, closestP); if(d<0){ vcg::tri::Allocator::AddVertex(vvs.montecarloVolumeMesh,point); vvs.montecarloVolumeMesh.vert.back().Q() = fabs(d); } } } }; // end class } // end namespace vcg } // end namespace vcg #endif // VCG__SKELETON_H