More and more debugging for the CoM class. Now it should begin to be usable
This commit is contained in:
parent
cbb6b7e4b3
commit
6b11cc44d9
|
@ -47,7 +47,9 @@ int main(int argc,char ** argv )
|
||||||
{
|
{
|
||||||
MyMesh base, basecopy, poly;
|
MyMesh base, basecopy, poly;
|
||||||
int ret0 = tri::io::Importer<MyMesh>::Open(base,argv[1]);
|
int ret0 = tri::io::Importer<MyMesh>::Open(base,argv[1]);
|
||||||
if(ret0 != 0 )
|
int ret1 = 0;
|
||||||
|
if(argc>2) ret1 = tri::io::Importer<MyMesh>::Open(poly,argv[2]);
|
||||||
|
if(ret0 != 0 || ret1 != 0)
|
||||||
{
|
{
|
||||||
printf("Failed Loading\n");
|
printf("Failed Loading\n");
|
||||||
exit(-1);
|
exit(-1);
|
||||||
|
@ -55,10 +57,13 @@ int main(int argc,char ** argv )
|
||||||
|
|
||||||
tri::UpdateBounding<MyMesh>::Box(base);
|
tri::UpdateBounding<MyMesh>::Box(base);
|
||||||
printf( "Mesh %s has %i vert and %i faces\n", argv[1], base.VN(), base.FN() );
|
printf( "Mesh %s has %i vert and %i faces\n", argv[1], base.VN(), base.FN() );
|
||||||
|
printf( "Poly %s has %i vert and %i edges\n", argv[2], poly.VN(), poly.EN() );
|
||||||
|
if(poly.EN()==0) {
|
||||||
srand(time(0));
|
srand(time(0));
|
||||||
tri::CutTree<MyMesh> ct(base);
|
tri::CutTree<MyMesh> ct(base);
|
||||||
ct.BuildVisitTree(poly,rand()%base.fn);
|
ct.BuildVisitTree(poly,rand()%base.fn);
|
||||||
tri::io::ExporterPLY<MyMesh>::Save(poly,"tree.ply",tri::io::Mask::IOM_EDGEINDEX);
|
}
|
||||||
|
tri::io::ExporterPLY<MyMesh>::Save(poly,"0_cut_tree.ply",tri::io::Mask::IOM_EDGEINDEX);
|
||||||
|
|
||||||
tri::CoM<MyMesh> cc(base);
|
tri::CoM<MyMesh> cc(base);
|
||||||
cc.Init();
|
cc.Init();
|
||||||
|
@ -68,39 +73,38 @@ int main(int argc,char ** argv )
|
||||||
tri::CutMeshAlongNonFauxEdges<MyMesh>(basecopy);
|
tri::CutMeshAlongNonFauxEdges<MyMesh>(basecopy);
|
||||||
tri::io::ExporterPLY<MyMesh>::Save(basecopy,"base_cut_with_tree.ply");
|
tri::io::ExporterPLY<MyMesh>::Save(basecopy,"base_cut_with_tree.ply");
|
||||||
|
|
||||||
|
// Selected vertices are 'locked' during the smoothing.
|
||||||
|
cc.SelectBoundaryVertex(poly);
|
||||||
|
cc.SelectUniformlyDistributed(poly,20); // lock some vertices uniformly just for fun
|
||||||
|
|
||||||
|
// Two smoothing runs,
|
||||||
|
// the first that allows fast movement over the surface (long edges that can skim surface details)
|
||||||
cc.par.surfDistThr = base.bbox.Diag()/100.0;
|
cc.par.surfDistThr = base.bbox.Diag()/100.0;
|
||||||
cc.par.maxSimpEdgeLen = base.bbox.Diag()/40.0;
|
cc.par.maxSimpEdgeLen = base.bbox.Diag()/50.0;
|
||||||
cc.par.minRefEdgeLen = base.bbox.Diag()/80.0;
|
cc.par.minRefEdgeLen = base.bbox.Diag()/100.0;
|
||||||
cc.SmoothProject(poly,40,0.5, .7);
|
cc.SmoothProject(poly,10,0.7,.3);
|
||||||
|
tri::io::ExporterPLY<MyMesh>::Save(poly,"1_poly_smooth.ply",tri::io::Mask::IOM_EDGEINDEX+tri::io::Mask::IOM_VERTCOLOR+tri::io::Mask::IOM_VERTQUALITY);
|
||||||
|
|
||||||
|
// The second smooting run more accurate to adapt to the surface
|
||||||
|
cc.par.surfDistThr = base.bbox.Diag()/1000.0;
|
||||||
|
cc.par.maxSimpEdgeLen = base.bbox.Diag()/1000.0;
|
||||||
|
cc.par.minRefEdgeLen = base.bbox.Diag()/2000.0;
|
||||||
|
cc.SmoothProject(poly,10,0.01,.99);
|
||||||
|
tri::io::ExporterPLY<MyMesh>::Save(poly,"2_poly_smooth.ply",tri::io::Mask::IOM_EDGEINDEX+tri::io::Mask::IOM_VERTCOLOR+tri::io::Mask::IOM_VERTQUALITY);
|
||||||
|
|
||||||
Distribution<float> dist;
|
Distribution<float> dist;
|
||||||
cc.EvaluateHausdorffDistance(poly, dist );
|
cc.EvaluateHausdorffDistance(poly, dist );
|
||||||
|
|
||||||
// tri::io::ExporterPLY<MyMesh>::Save(poly,"poly_adapted.ply",tri::io::Mask::IOM_EDGEINDEX+tri::io::Mask::IOM_VERTCOLOR+tri::io::Mask::IOM_VERTQUALITY);
|
// Adapt the polyline to the mesh (in the end it will have vertices only on edges and vertices of the base mesh)
|
||||||
// cc.par.surfDistThr = base.bbox.Diag()/2000.0;
|
|
||||||
// cc.par.maxSimpEdgeLen = base.bbox.Diag()/100.0;
|
|
||||||
// cc.par.minRefEdgeLen = base.bbox.Diag()/200.0;
|
|
||||||
// cc.SmoothProject(poly,10,0.3, 0.7);
|
|
||||||
// cc.SmoothProject(poly,1,0.01, 0.99);
|
|
||||||
tri::io::ExporterPLY<MyMesh>::Save(poly,"poly_adapted2.ply",tri::io::Mask::IOM_EDGEINDEX+tri::io::Mask::IOM_VERTCOLOR+tri::io::Mask::IOM_VERTQUALITY);
|
|
||||||
std::vector<MyVertex*> newVertVec;
|
|
||||||
cc.SnapPolyline(poly);
|
|
||||||
tri::io::ExporterPLY<MyMesh>::Save(poly,"poly_snap.ply",tri::io::Mask::IOM_EDGEINDEX+tri::io::Mask::IOM_VERTCOLOR+tri::io::Mask::IOM_VERTQUALITY);
|
|
||||||
cc.RefineCurveByBaseMesh(poly);
|
cc.RefineCurveByBaseMesh(poly);
|
||||||
tri::io::ExporterPLY<MyMesh>::Save(poly,"poly_refined.ply",tri::io::Mask::IOM_EDGEINDEX+tri::io::Mask::IOM_VERTCOLOR+tri::io::Mask::IOM_VERTQUALITY);
|
tri::io::ExporterPLY<MyMesh>::Save(poly,"3_poly_refined.ply",tri::io::Mask::IOM_EDGEINDEX+tri::io::Mask::IOM_VERTCOLOR+tri::io::Mask::IOM_VERTQUALITY);
|
||||||
|
// Safely split the mesh with this refined polyline
|
||||||
cc.SplitMeshWithPolyline(poly);
|
cc.SplitMeshWithPolyline(poly);
|
||||||
cc.RefineCurveByBaseMesh(poly);
|
tri::io::ExporterPLY<MyMesh>::Save(base,"3_mesh_refined.ply",tri::io::Mask::IOM_VERTCOLOR+tri::io::Mask::IOM_VERTQUALITY);
|
||||||
tri::io::ExporterPLY<MyMesh>::Save(base,"base_refined.ply",tri::io::Mask::IOM_VERTCOLOR+tri::io::Mask::IOM_VERTQUALITY);
|
// Now the two meshes should have coincident edges
|
||||||
cc.SplitMeshWithPolyline(poly);
|
|
||||||
cc.RefineCurveByBaseMesh(poly);
|
|
||||||
cc.SplitMeshWithPolyline(poly);
|
|
||||||
cc.RefineCurveByBaseMesh(poly);
|
|
||||||
tri::io::ExporterPLY<MyMesh>::Save(base,"base_refined2.ply",tri::io::Mask::IOM_VERTCOLOR+tri::io::Mask::IOM_VERTQUALITY+tri::io::Mask::IOM_FACEFLAGS);
|
|
||||||
cc.MarkFauxEdgeWithPolyLine(poly);
|
cc.MarkFauxEdgeWithPolyLine(poly);
|
||||||
CutMeshAlongNonFauxEdges(base);
|
CutMeshAlongNonFauxEdges(base);
|
||||||
tri::io::ExporterPLY<MyMesh>::Save(base,"base_refined2_cut.ply",tri::io::Mask::IOM_VERTCOLOR+tri::io::Mask::IOM_VERTQUALITY);
|
tri::io::ExporterPLY<MyMesh>::Save(base,"4_mesh_cut.ply",tri::io::Mask::IOM_VERTCOLOR+tri::io::Mask::IOM_VERTQUALITY);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
|
@ -32,6 +32,7 @@
|
||||||
#include<vcg/complex/algorithms/clean.h>
|
#include<vcg/complex/algorithms/clean.h>
|
||||||
#include<vcg/complex/algorithms/refine.h>
|
#include<vcg/complex/algorithms/refine.h>
|
||||||
#include<vcg/complex/algorithms/create/platonic.h>
|
#include<vcg/complex/algorithms/create/platonic.h>
|
||||||
|
#include<vcg/complex/algorithms/point_sampling.h>
|
||||||
#include <vcg/space/index/grid_static_ptr.h>
|
#include <vcg/space/index/grid_static_ptr.h>
|
||||||
#include <vcg/space/index/kdtree/kdtree.h>
|
#include <vcg/space/index/kdtree/kdtree.h>
|
||||||
#include <vcg/math/histogram.h>
|
#include <vcg/math/histogram.h>
|
||||||
|
@ -74,7 +75,7 @@ public:
|
||||||
ScalarType surfDistThr; // Distance between surface and curve; used in simplify and refine
|
ScalarType surfDistThr; // Distance between surface and curve; used in simplify and refine
|
||||||
ScalarType polyDistThr; // Distance between the
|
ScalarType polyDistThr; // Distance between the
|
||||||
ScalarType minRefEdgeLen; // Minimal admitted Edge Lenght (used in refine: never make edge shorther than this value)
|
ScalarType minRefEdgeLen; // Minimal admitted Edge Lenght (used in refine: never make edge shorther than this value)
|
||||||
ScalarType maxSimpEdgeLen; // Minimal admitted Edge Lenght (used in simplify: never make edges longer than this value)
|
ScalarType maxSimpEdgeLen; // Maximal admitted Edge Lenght (used in simplify: never make edges longer than this value)
|
||||||
ScalarType maxSmoothDelta; // The maximum movement that is admitted during smoothing.
|
ScalarType maxSmoothDelta; // The maximum movement that is admitted during smoothing.
|
||||||
ScalarType maxSnapThr; // The maximum distance allowed when snapping a vertex of the polyline onto a mesh vertex
|
ScalarType maxSnapThr; // The maximum distance allowed when snapping a vertex of the polyline onto a mesh vertex
|
||||||
ScalarType gridBailout; // The maximum distance bailout used in grid sampling
|
ScalarType gridBailout; // The maximum distance bailout used in grid sampling
|
||||||
|
@ -115,21 +116,21 @@ public:
|
||||||
|
|
||||||
FaceType *GetClosestFace(const CoordType &p)
|
FaceType *GetClosestFace(const CoordType &p)
|
||||||
{
|
{
|
||||||
float closestDist;
|
ScalarType closestDist;
|
||||||
CoordType closestP;
|
CoordType closestP;
|
||||||
return vcg::tri::GetClosestFaceBase(base,uniformGrid,p, p.gridBailout, closestDist, closestP);
|
return vcg::tri::GetClosestFaceBase(base,uniformGrid,p, p.gridBailout, closestDist, closestP);
|
||||||
}
|
}
|
||||||
|
|
||||||
FaceType *GetClosestFaceIP(const CoordType &p, CoordType &ip)
|
FaceType *GetClosestFaceIP(const CoordType &p, CoordType &ip)
|
||||||
{
|
{
|
||||||
float closestDist;
|
ScalarType closestDist;
|
||||||
CoordType closestP,closestN;
|
CoordType closestP,closestN;
|
||||||
return vcg::tri::GetClosestFaceBase(base,uniformGrid,p, this->par.gridBailout, closestDist, closestP,closestN,ip);
|
return vcg::tri::GetClosestFaceBase(base,uniformGrid,p, this->par.gridBailout, closestDist, closestP,closestN,ip);
|
||||||
}
|
}
|
||||||
|
|
||||||
FaceType *GetClosestFacePoint(const CoordType &p, CoordType &closestP)
|
FaceType *GetClosestFacePoint(const CoordType &p, CoordType &closestP)
|
||||||
{
|
{
|
||||||
float closestDist;
|
ScalarType closestDist;
|
||||||
return vcg::tri::GetClosestFaceBase(base,uniformGrid,p, this->par.gridBailout, closestDist, closestP);
|
return vcg::tri::GetClosestFaceBase(base,uniformGrid,p, this->par.gridBailout, closestDist, closestP);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -171,7 +172,7 @@ public:
|
||||||
* @param poly
|
* @param poly
|
||||||
* @return true if all the edges of the polyline are snapped onto the mesh.
|
* @return true if all the edges of the polyline are snapped onto the mesh.
|
||||||
*
|
*
|
||||||
* Use this function toghether with the CutMeshAlongCrease function to actually cut the mesh with a snapped polyline.
|
* Use this function together with the CutMeshAlongCrease function to actually cut the mesh with a snapped polyline.
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
@ -183,7 +184,7 @@ public:
|
||||||
|
|
||||||
for(EdgeIterator ei=poly.edge.begin(); ei!=poly.edge.end();++ei)
|
for(EdgeIterator ei=poly.edge.begin(); ei!=poly.edge.end();++ei)
|
||||||
{
|
{
|
||||||
Point3f ip0,ip1;
|
CoordType ip0,ip1;
|
||||||
FaceType *f0 = GetClosestFaceIP(ei->cP(0),ip0);
|
FaceType *f0 = GetClosestFaceIP(ei->cP(0),ip0);
|
||||||
FaceType *f1 = GetClosestFaceIP(ei->cP(1),ip1);
|
FaceType *f1 = GetClosestFaceIP(ei->cP(1),ip1);
|
||||||
|
|
||||||
|
@ -191,40 +192,45 @@ public:
|
||||||
{
|
{
|
||||||
VertexPointer v0 = FindVertexSnap(f0,ip0);
|
VertexPointer v0 = FindVertexSnap(f0,ip0);
|
||||||
VertexPointer v1 = FindVertexSnap(f1,ip1);
|
VertexPointer v1 = FindVertexSnap(f1,ip1);
|
||||||
assert(v1>=0 && v0>=0 && v0!=v1);
|
assert(v1>0 && v0>0 && v0!=v1);
|
||||||
FacePointer ff0,ff1;
|
FacePointer ff0,ff1;
|
||||||
int e0,e1;
|
int e0,e1;
|
||||||
bool ret=face::FindSharedFaces<FaceType>(v0,v1,ff0,ff1,e0,e1);
|
bool ret=face::FindSharedFaces<FaceType>(v0,v1,ff0,ff1,e0,e1);
|
||||||
|
if(ret){
|
||||||
assert(ret);
|
assert(ret);
|
||||||
assert(ff0->V(e0)==v0 || ff0->V(e0)==v1);
|
assert(ff0->V(e0)==v0 || ff0->V(e0)==v1);
|
||||||
ff0->ClearF(e0);
|
ff0->ClearF(e0);
|
||||||
ff1->ClearF(e1);
|
ff1->ClearF(e1);
|
||||||
}
|
}
|
||||||
|
else {
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
else {
|
else {
|
||||||
assert(0);
|
assert(0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
float MinDistOnEdge(Point3f samplePnt, EdgeGrid &edgeGrid, MeshType &poly, Point3f &closestPoint)
|
ScalarType MinDistOnEdge(CoordType samplePnt, EdgeGrid &edgeGrid, MeshType &poly, CoordType &closestPoint)
|
||||||
{
|
{
|
||||||
float polyDist;
|
ScalarType polyDist;
|
||||||
EdgeType *cep = vcg::tri::GetClosestEdgeBase(poly,edgeGrid,samplePnt,par.gridBailout,polyDist,closestPoint);
|
EdgeType *cep = vcg::tri::GetClosestEdgeBase(poly,edgeGrid,samplePnt,par.gridBailout,polyDist,closestPoint);
|
||||||
return polyDist;
|
return polyDist;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Given an edge of a mesh, supposedly intersecting the polyline,
|
// Given an edge of a mesh, supposedly intersecting the polyline,
|
||||||
// we search on it the closest point to the polyline
|
// we search on it the closest point to the polyline
|
||||||
static float MinDistOnEdge(VertexType *v0,VertexType *v1, EdgeGrid &edgeGrid, MeshType &poly, Point3f &closestPoint)
|
static ScalarType MinDistOnEdge(VertexType *v0,VertexType *v1, EdgeGrid &edgeGrid, MeshType &poly, CoordType &closestPoint)
|
||||||
{
|
{
|
||||||
float minPolyDist = std::numeric_limits<ScalarType>::max();
|
ScalarType minPolyDist = std::numeric_limits<ScalarType>::max();
|
||||||
const float sampleNum = 50;
|
const ScalarType sampleNum = 50;
|
||||||
const float maxDist = poly.bbox.Diag()/10.0;
|
const ScalarType maxDist = poly.bbox.Diag()/10.0;
|
||||||
for(float k = 0;k<sampleNum+1;++k)
|
for(ScalarType k = 0;k<sampleNum+1;++k)
|
||||||
{
|
{
|
||||||
float polyDist;
|
ScalarType polyDist;
|
||||||
Point3f closestPPoly;
|
CoordType closestPPoly;
|
||||||
Point3f samplePnt = (v0->P()*k +v1->P()*(sampleNum-k))/sampleNum;
|
CoordType samplePnt = (v0->P()*k +v1->P()*(sampleNum-k))/sampleNum;
|
||||||
|
|
||||||
EdgeType *cep = vcg::tri::GetClosestEdgeBase(poly,edgeGrid,samplePnt,maxDist,polyDist,closestPPoly);
|
EdgeType *cep = vcg::tri::GetClosestEdgeBase(poly,edgeGrid,samplePnt,maxDist,polyDist,closestPPoly);
|
||||||
|
|
||||||
|
@ -266,12 +272,12 @@ public:
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
static Point3f QLerp(VertexType *v0, VertexType *v1)
|
static CoordType QLerp(VertexType *v0, VertexType *v1)
|
||||||
{
|
{
|
||||||
|
|
||||||
float qSum = fabs(v0->Q())+fabs(v1->Q());
|
ScalarType qSum = fabs(v0->Q())+fabs(v1->Q());
|
||||||
float w0 = (qSum - fabs(v0->Q()))/qSum;
|
ScalarType w0 = (qSum - fabs(v0->Q()))/qSum;
|
||||||
float w1 = (qSum - fabs(v1->Q()))/qSum;
|
ScalarType w1 = (qSum - fabs(v1->Q()))/qSum;
|
||||||
return v0->P()*w0 + v1->P()*w1;
|
return v0->P()*w0 + v1->P()*w1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -282,7 +288,8 @@ public:
|
||||||
* @param newVertVec the vector of the indexes of the snapped vertices
|
* @param newVertVec the vector of the indexes of the snapped vertices
|
||||||
*
|
*
|
||||||
* Polyline vertices can be snapped either on vertexes or on edges.
|
* Polyline vertices can be snapped either on vertexes or on edges.
|
||||||
*
|
* Usually the only points that we should allow to not be snapped are the endpoints and non manifold points.
|
||||||
|
* Vertexes are colored according to their snapping state
|
||||||
*/
|
*/
|
||||||
|
|
||||||
void SnapPolyline(MeshType &poly)
|
void SnapPolyline(MeshType &poly)
|
||||||
|
@ -294,7 +301,7 @@ public:
|
||||||
int borderCnt=0,midCnt=0,nonmanifCnt=0;
|
int borderCnt=0,midCnt=0,nonmanifCnt=0;
|
||||||
for(VertexIterator vi=poly.vert.begin(); vi!=poly.vert.end();++vi)
|
for(VertexIterator vi=poly.vert.begin(); vi!=poly.vert.end();++vi)
|
||||||
{
|
{
|
||||||
Point3f ip;
|
CoordType ip;
|
||||||
FaceType *f = GetClosestFaceIP(vi->cP(),ip);
|
FaceType *f = GetClosestFaceIP(vi->cP(),ip);
|
||||||
if(BarycentricSnap(ip))
|
if(BarycentricSnap(ip))
|
||||||
{
|
{
|
||||||
|
@ -321,6 +328,24 @@ public:
|
||||||
if(dupCnt) printf("SnapPolyline: Removed %i Duplicated vertices\n",dupCnt);
|
if(dupCnt) printf("SnapPolyline: Removed %i Duplicated vertices\n",dupCnt);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void SelectBoundaryVertex(MeshType &poly)
|
||||||
|
{
|
||||||
|
tri::UpdateSelection<MeshType>::VertexClear(poly);
|
||||||
|
tri::UpdateTopology<MeshType>::VertexEdge(poly);
|
||||||
|
ForEachVertex(poly, [&](VertexType &v){
|
||||||
|
if(edge::VEDegree<EdgeType>(&v)==1) v.SetS();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
void SelectUniformlyDistributed(MeshType &poly, int k)
|
||||||
|
{
|
||||||
|
tri::TrivialPointerSampler<MeshType> tps;
|
||||||
|
ScalarType samplingRadius = tri::Stat<MeshType>::ComputeEdgeLengthSum(poly)/ScalarType(k);
|
||||||
|
tri::SurfaceSampling<MeshType, typename tri::TrivialPointerSampler<MeshType> >::EdgeMeshUniform(poly,tps,samplingRadius);
|
||||||
|
for(int i=0;i<tps.sampleVec.size();++i)
|
||||||
|
tps.sampleVec[i]->SetS();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -398,7 +423,7 @@ public:
|
||||||
|
|
||||||
for(VertexIterator vi=poly.vert.begin(); vi!=poly.vert.end();++vi)
|
for(VertexIterator vi=poly.vert.begin(); vi!=poly.vert.end();++vi)
|
||||||
{
|
{
|
||||||
Point3f ip;
|
CoordType ip;
|
||||||
FaceType *f = GetClosestFaceIP(vi->cP(),ip);
|
FaceType *f = GetClosestFaceIP(vi->cP(),ip);
|
||||||
if(!BarycentricSnap(ip))
|
if(!BarycentricSnap(ip))
|
||||||
toSplitVec.push_back(std::make_pair(tri::Index(base,f),&*vi));
|
toSplitVec.push_back(std::make_pair(tri::Index(base,f),&*vi));
|
||||||
|
@ -424,7 +449,7 @@ public:
|
||||||
std::map<std::pair<CoordType,CoordType>, VertexPointer> edgeToPolyVertMap;
|
std::map<std::pair<CoordType,CoordType>, VertexPointer> edgeToPolyVertMap;
|
||||||
for(VertexIterator vi=poly.vert.begin(); vi!=poly.vert.end();++vi)
|
for(VertexIterator vi=poly.vert.begin(); vi!=poly.vert.end();++vi)
|
||||||
{
|
{
|
||||||
Point3f ip;
|
CoordType ip;
|
||||||
FaceType *f = GetClosestFaceIP(vi->cP(),ip);
|
FaceType *f = GetClosestFaceIP(vi->cP(),ip);
|
||||||
if(!BarycentricSnap(ip)) { assert(0); }
|
if(!BarycentricSnap(ip)) { assert(0); }
|
||||||
for(int i=0;i<3;++i)
|
for(int i=0;i<3;++i)
|
||||||
|
@ -493,26 +518,29 @@ public:
|
||||||
}
|
}
|
||||||
tri::Clean<MeshType>::RemoveDuplicateVertex(poly);
|
tri::Clean<MeshType>::RemoveDuplicateVertex(poly);
|
||||||
tri::Allocator<MeshType>::CompactEveryVector(poly);
|
tri::Allocator<MeshType>::CompactEveryVector(poly);
|
||||||
printf("SimplifyMidEdge %5i -> %5i %i mid %i ve \n",startVn,poly.vn,midEdgeCollapseCnt);
|
// printf("SimplifyMidEdge %5i -> %5i %i mid %i ve \n",startVn,poly.vn,midEdgeCollapseCnt);
|
||||||
} while(startVn>poly.vn);
|
} while(startVn>poly.vn);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief SimplifyMidFace remove all the vertices that in the mid of a face and between two of the points snapped onto the edges of the same face
|
* @brief SimplifyMidFace remove all the vertices that in the mid of a face
|
||||||
|
* and between two of the points snapped onto the edges of the same face
|
||||||
* @param poly
|
* @param poly
|
||||||
*
|
*
|
||||||
* It assumes that the mesh has been snapped and refined by the BaseMesh
|
* It assumes that the mesh has been snapped and refined by the BaseMesh
|
||||||
|
*
|
||||||
*/
|
*/
|
||||||
void SimplifyMidFace(MeshType &poly)
|
void SimplifyMidFace(MeshType &poly)
|
||||||
{
|
{
|
||||||
int startVn;
|
int startVn= poly.vn;;
|
||||||
|
int midFaceCollapseCnt=0;
|
||||||
|
int vertexEdgeCollapseCnt=0;
|
||||||
|
int curVn;
|
||||||
do
|
do
|
||||||
{
|
{
|
||||||
tri::Allocator<MeshType>::CompactEveryVector(poly);
|
tri::Allocator<MeshType>::CompactEveryVector(poly);
|
||||||
startVn = poly.vn;
|
curVn = poly.vn;
|
||||||
UpdateTopology<MeshType>::VertexEdge(poly);
|
UpdateTopology<MeshType>::VertexEdge(poly);
|
||||||
int midFaceCollapseCnt=0;
|
|
||||||
int vertexEdgeCollapseCnt=0;
|
|
||||||
for(int i =0; i<poly.vn;++i)
|
for(int i =0; i<poly.vn;++i)
|
||||||
{
|
{
|
||||||
std::vector<VertexPointer> starVecVp;
|
std::vector<VertexPointer> starVecVp;
|
||||||
|
@ -562,8 +590,8 @@ public:
|
||||||
edge::VEEdgeCollapse(poly,&(poly.vert[i]));
|
edge::VEEdgeCollapse(poly,&(poly.vert[i]));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
} while(curVn>poly.vn);
|
||||||
printf("SimplifyMidFace %5i -> %5i %i mid %i ve \n",startVn,poly.vn,midFaceCollapseCnt,vertexEdgeCollapseCnt);
|
printf("SimplifyMidFace %5i -> %5i %i mid %i ve \n",startVn,poly.vn,midFaceCollapseCnt,vertexEdgeCollapseCnt);
|
||||||
} while(startVn>poly.vn);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Simplify( MeshType &poly)
|
void Simplify( MeshType &poly)
|
||||||
|
@ -581,13 +609,13 @@ public:
|
||||||
edge::VVStarVE(&(poly.vert[i]),starVecVp);
|
edge::VVStarVE(&(poly.vert[i]),starVecVp);
|
||||||
if( (starVecVp.size()==2) && (!poly.vert[i].IsS()))
|
if( (starVecVp.size()==2) && (!poly.vert[i].IsS()))
|
||||||
{
|
{
|
||||||
float newSegLen = Distance(starVecVp[0]->P(), starVecVp[1]->P());
|
ScalarType newSegLen = Distance(starVecVp[0]->P(), starVecVp[1]->P());
|
||||||
Segment3f seg(starVecVp[0]->P(),starVecVp[1]->P());
|
Segment3f seg(starVecVp[0]->P(),starVecVp[1]->P());
|
||||||
float segDist;
|
ScalarType segDist;
|
||||||
Point3f closestPSeg;
|
CoordType closestPSeg;
|
||||||
SegmentPointDistance(seg,poly.vert[i].cP(),closestPSeg,segDist);
|
SegmentPointDistance(seg,poly.vert[i].cP(),closestPSeg,segDist);
|
||||||
Point3f fp,fn;
|
CoordType fp,fn;
|
||||||
float maxSurfDist = MaxSegDist(starVecVp[0], starVecVp[1],fp,fn);
|
ScalarType maxSurfDist = MaxSegDist(starVecVp[0], starVecVp[1],fp,fn);
|
||||||
|
|
||||||
if((maxSurfDist < par.surfDistThr) && (newSegLen < par.maxSimpEdgeLen) )
|
if((maxSurfDist < par.surfDistThr) && (newSegLen < par.maxSimpEdgeLen) )
|
||||||
{
|
{
|
||||||
|
@ -608,8 +636,8 @@ public:
|
||||||
tri::UpdateQuality<MeshType>::VertexConstant(poly,0);
|
tri::UpdateQuality<MeshType>::VertexConstant(poly,0);
|
||||||
for(int i =0; i<poly.edge.size();++i)
|
for(int i =0; i<poly.edge.size();++i)
|
||||||
{
|
{
|
||||||
Point3f farthestP, farthestN;
|
CoordType farthestP, farthestN;
|
||||||
float maxDist = MaxSegDist(poly.edge[i].V(0),poly.edge[i].V(1), farthestP, farthestN, &dist);
|
ScalarType maxDist = MaxSegDist(poly.edge[i].V(0),poly.edge[i].V(1), farthestP, farthestN, &dist);
|
||||||
poly.edge[i].V(0)->Q()+= maxDist;
|
poly.edge[i].V(0)->Q()+= maxDist;
|
||||||
poly.edge[i].V(1)->Q()+= maxDist;
|
poly.edge[i].V(1)->Q()+= maxDist;
|
||||||
}
|
}
|
||||||
|
@ -629,7 +657,8 @@ public:
|
||||||
* @return true if they have been snapped.
|
* @return true if they have been snapped.
|
||||||
*
|
*
|
||||||
* This is the VERY important function that is used everywhere.
|
* This is the VERY important function that is used everywhere.
|
||||||
* Given a barycentric coord of a point inside a triangle it decides if it should be "snapped" either onto an edge or on a vertex. *
|
* Given a barycentric coord of a point inside a triangle it decides if it should be "snapped" either onto an edge or on a vertex.
|
||||||
|
* It relies on the barycentricSnapThr parameter
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
bool BarycentricSnap(CoordType &ip)
|
bool BarycentricSnap(CoordType &ip)
|
||||||
|
@ -666,10 +695,10 @@ public:
|
||||||
*
|
*
|
||||||
* Note that we have to check the case where
|
* Note that we have to check the case where
|
||||||
*/
|
*/
|
||||||
bool TestSplitSegWithMesh(VertexType *v0, VertexType *v1, Point3f &splitPt)
|
bool TestSplitSegWithMesh(VertexType *v0, VertexType *v1, CoordType &splitPt)
|
||||||
{
|
{
|
||||||
Segment3f segPoly(v0->P(),v1->P());
|
Segment3f segPoly(v0->P(),v1->P());
|
||||||
const float sampleNum = 40;
|
const ScalarType sampleNum = 40;
|
||||||
CoordType ip0,ip1;
|
CoordType ip0,ip1;
|
||||||
|
|
||||||
FaceType *f0=GetClosestFaceIP(v0->P(),ip0);
|
FaceType *f0=GetClosestFaceIP(v0->P(),ip0);
|
||||||
|
@ -699,9 +728,9 @@ public:
|
||||||
|
|
||||||
CoordType bestSplitPt(0,0,0);
|
CoordType bestSplitPt(0,0,0);
|
||||||
ScalarType bestDist = std::numeric_limits<ScalarType>::max();
|
ScalarType bestDist = std::numeric_limits<ScalarType>::max();
|
||||||
for(float k = 1;k<sampleNum;++k)
|
for(ScalarType k = 1;k<sampleNum;++k)
|
||||||
{
|
{
|
||||||
Point3f samplePnt = segPoly.Lerp(k/sampleNum);
|
CoordType samplePnt = segPoly.Lerp(k/sampleNum);
|
||||||
CoordType ip;
|
CoordType ip;
|
||||||
FaceType *f=GetClosestFaceIP(samplePnt,ip);
|
FaceType *f=GetClosestFaceIP(samplePnt,ip);
|
||||||
// BarycentricEdgeSnap(ip);
|
// BarycentricEdgeSnap(ip);
|
||||||
|
@ -790,6 +819,7 @@ public:
|
||||||
PosType curPos=startPos;
|
PosType curPos=startPos;
|
||||||
do
|
do
|
||||||
{
|
{
|
||||||
|
assert(curPos.V()==f0->V(v0));
|
||||||
if(curPos.VFlip()==f1->V(v1)) return true;
|
if(curPos.VFlip()==f1->V(v1)) return true;
|
||||||
curPos.FlipE();
|
curPos.FlipE();
|
||||||
curPos.FlipF();
|
curPos.FlipF();
|
||||||
|
@ -816,7 +846,7 @@ public:
|
||||||
*
|
*
|
||||||
* Note that we have to check the case where
|
* Note that we have to check the case where
|
||||||
*/
|
*/
|
||||||
bool TestSplitSegWithMeshAdapt(VertexType *v0, VertexType *v1, Point3f &splitPt)
|
bool TestSplitSegWithMeshAdapt(VertexType *v0, VertexType *v1, CoordType &splitPt)
|
||||||
{
|
{
|
||||||
splitPt=(v0->P()+v1->P())/2.0;
|
splitPt=(v0->P()+v1->P())/2.0;
|
||||||
|
|
||||||
|
@ -831,6 +861,8 @@ public:
|
||||||
bool snap1=BarycentricSnap(ip1);
|
bool snap1=BarycentricSnap(ip1);
|
||||||
bool snapm=BarycentricSnap(ipm);
|
bool snapm=BarycentricSnap(ipm);
|
||||||
|
|
||||||
|
splitPt = fm->P(0)*ipm[0]+fm->P(1)*ipm[1]+fm->P(2)*ipm[2];
|
||||||
|
|
||||||
if(!snap0 && !snap1) {
|
if(!snap0 && !snap1) {
|
||||||
assert(f0!=f1);
|
assert(f0!=f1);
|
||||||
return true;
|
return true;
|
||||||
|
@ -839,7 +871,6 @@ public:
|
||||||
{
|
{
|
||||||
if(SnappedOnSameFace(f0,ip0,f1,ip1))
|
if(SnappedOnSameFace(f0,ip0,f1,ip1))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if(snap0) {
|
if(snap0) {
|
||||||
|
@ -852,14 +883,25 @@ public:
|
||||||
if(f1->V(i)==f0->V(v0)) return false;
|
if(f1->V(i)==f0->V(v0)) return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if(snap1) {
|
||||||
|
int e1,v1;
|
||||||
|
if (IsSnappedEdge(ip1,e1)) {
|
||||||
|
if(f1->FFp(e1) == f0) return false;
|
||||||
|
}
|
||||||
|
if(IsSnappedVertex(ip1,v1)) {
|
||||||
|
for(int i=0;i<3;++i)
|
||||||
|
if(f0->V(i)==f1->V(v1)) return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
bool TestSplitSegWithMeshAdaptOld(VertexType *v0, VertexType *v1, Point3f &splitPt)
|
bool TestSplitSegWithMeshAdaptOld(VertexType *v0, VertexType *v1, CoordType &splitPt)
|
||||||
{
|
{
|
||||||
Segment3f segPoly(v0->P(),v1->P());
|
Segment3f segPoly(v0->P(),v1->P());
|
||||||
const float sampleNum = 40;
|
const ScalarType sampleNum = 40;
|
||||||
CoordType ip0,ip1;
|
CoordType ip0,ip1;
|
||||||
FaceType *f0=GetClosestFaceIP(v0->P(),ip0);
|
FaceType *f0=GetClosestFaceIP(v0->P(),ip0);
|
||||||
FaceType *f1=GetClosestFaceIP(v1->P(),ip1);
|
FaceType *f1=GetClosestFaceIP(v1->P(),ip1);
|
||||||
|
@ -895,16 +937,16 @@ public:
|
||||||
|
|
||||||
// Given a segment find the maximum distance from it to the original surface.
|
// Given a segment find the maximum distance from it to the original surface.
|
||||||
// It is used to evaluate the Haustdorff distance of a Segment from the mesh.
|
// It is used to evaluate the Haustdorff distance of a Segment from the mesh.
|
||||||
float MaxSegDist(VertexType *v0, VertexType *v1, Point3f &farthestPointOnSurf, Point3f &farthestN, Distribution<ScalarType> *dist=0)
|
ScalarType MaxSegDist(VertexType *v0, VertexType *v1, CoordType &farthestPointOnSurf, CoordType &farthestN, Distribution<ScalarType> *dist=0)
|
||||||
{
|
{
|
||||||
float maxSurfDist = 0;
|
ScalarType maxSurfDist = 0;
|
||||||
const float sampleNum = 10;
|
const ScalarType sampleNum = 10;
|
||||||
const float maxDist = base.bbox.Diag()/10.0;
|
const ScalarType maxDist = base.bbox.Diag()/10.0;
|
||||||
for(float k = 1;k<sampleNum;++k)
|
for(ScalarType k = 1;k<sampleNum;++k)
|
||||||
{
|
{
|
||||||
float surfDist;
|
ScalarType surfDist;
|
||||||
Point3f closestPSurf;
|
CoordType closestPSurf;
|
||||||
Point3f samplePnt = (v0->P()*k +v1->P()*(sampleNum-k))/sampleNum;
|
CoordType samplePnt = (v0->P()*k +v1->P()*(sampleNum-k))/sampleNum;
|
||||||
FaceType *f = vcg::tri::GetClosestFaceBase(base,uniformGrid,samplePnt,maxDist, surfDist, closestPSurf);
|
FaceType *f = vcg::tri::GetClosestFaceBase(base,uniformGrid,samplePnt,maxDist, surfDist, closestPSurf);
|
||||||
if(dist)
|
if(dist)
|
||||||
dist->Add(surfDist);
|
dist->Add(surfDist);
|
||||||
|
@ -940,8 +982,8 @@ public:
|
||||||
EdgeType &ei = poly.edge[i];
|
EdgeType &ei = poly.edge[i];
|
||||||
if(edge::Length(ei)>par.minRefEdgeLen)
|
if(edge::Length(ei)>par.minRefEdgeLen)
|
||||||
{
|
{
|
||||||
Point3f farthestP, farthestN;
|
CoordType farthestP, farthestN;
|
||||||
float maxDist = MaxSegDist(ei.V(0),ei.V(1),farthestP, farthestN);
|
ScalarType maxDist = MaxSegDist(ei.V(0),ei.V(1),farthestP, farthestN);
|
||||||
if(maxDist > par.surfDistThr)
|
if(maxDist > par.surfDistThr)
|
||||||
{
|
{
|
||||||
edge::VEEdgeSplit(poly, &ei, farthestP, farthestN);
|
edge::VEEdgeSplit(poly, &ei, farthestP, farthestN);
|
||||||
|
@ -960,25 +1002,38 @@ public:
|
||||||
void RefineCurveByBaseMesh(MeshType &poly)
|
void RefineCurveByBaseMesh(MeshType &poly)
|
||||||
{
|
{
|
||||||
tri::Allocator<MeshType>::CompactEveryVector(poly);
|
tri::Allocator<MeshType>::CompactEveryVector(poly);
|
||||||
int lastEn;
|
std::vector<int> edgeToRefineVec;
|
||||||
do
|
for(int i=0; i<poly.en;++i)
|
||||||
{
|
edgeToRefineVec.push_back(i);
|
||||||
lastEn = poly.en;
|
int startEn=poly.en;
|
||||||
for(int i =0; i<lastEn;++i)
|
int iterCnt=0;
|
||||||
|
while (!edgeToRefineVec.empty() && iterCnt<100) {
|
||||||
|
iterCnt++;
|
||||||
|
std::vector<int> edgeToRefineVecNext;
|
||||||
|
for(int i=0; i<edgeToRefineVec.size();++i)
|
||||||
{
|
{
|
||||||
|
EdgeType &e = poly.edge[edgeToRefineVec[i]];
|
||||||
CoordType splitPt;
|
CoordType splitPt;
|
||||||
if(TestSplitSegWithMeshAdapt(poly.edge[i].V(0),poly.edge[i].V(1),splitPt))
|
if(TestSplitSegWithMeshAdapt(e.V(0),e.V(1),splitPt))
|
||||||
edge::VEEdgeSplit(poly, &poly.edge[i], splitPt);
|
{
|
||||||
|
edge::VEEdgeSplit(poly, &e, splitPt);
|
||||||
|
edgeToRefineVecNext.push_back(edgeToRefineVec[i]);
|
||||||
|
edgeToRefineVecNext.push_back(poly.en-1);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
printf("RefineCurveByBaseMesh %i en -> %i en\n",lastEn,poly.en); fflush(stdout);
|
|
||||||
tri::Allocator<MeshType>::CompactEveryVector(poly);
|
tri::Allocator<MeshType>::CompactEveryVector(poly);
|
||||||
} while(lastEn < poly.en);
|
swap(edgeToRefineVecNext,edgeToRefineVec);
|
||||||
|
printf("RefineCurveByBaseMesh %i en -> %i en\n",startEn,poly.en); fflush(stdout);
|
||||||
|
}
|
||||||
|
//
|
||||||
SimplifyMidFace(poly);
|
SimplifyMidFace(poly);
|
||||||
SimplifyMidEdge(poly);
|
SimplifyMidEdge(poly);
|
||||||
SnapPolyline(poly);
|
SnapPolyline(poly);
|
||||||
|
printf("RefineCurveByBaseMesh %i en -> %i en\n",startEn,poly.en); fflush(stdout);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief SmoothProject
|
* @brief SmoothProject
|
||||||
* @param poly
|
* @param poly
|
||||||
|
@ -1003,35 +1058,35 @@ public:
|
||||||
{
|
{
|
||||||
if(k==iterNum-1) projectWeight=1;
|
if(k==iterNum-1) projectWeight=1;
|
||||||
|
|
||||||
std::vector<Point3f> posVec(poly.vn,Point3f(0,0,0));
|
std::vector<CoordType> posVec(poly.vn,CoordType(0,0,0));
|
||||||
std::vector<int> cntVec(poly.vn,0);
|
std::vector<int> cntVec(poly.vn,0);
|
||||||
|
|
||||||
for(int i =0; i<poly.en;++i)
|
for(int i =0; i<poly.en;++i)
|
||||||
{
|
{
|
||||||
for(int j=0;j<2;++j)
|
for(int j=0;j<2;++j)
|
||||||
{
|
{
|
||||||
int vertInd = tri::Index(poly,poly.edge[i].V(j));
|
int vertInd = tri::Index(poly,poly.edge[i].V0(j));
|
||||||
posVec[vertInd] += poly.edge[i].V1(j)->P();
|
posVec[vertInd] += poly.edge[i].V1(j)->P();
|
||||||
cntVec[vertInd] += 1;
|
cntVec[vertInd] += 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const float maxDist = base.bbox.Diag()/10.0;
|
const ScalarType maxDist = base.bbox.Diag()/10.0;
|
||||||
for(int i=0; i<poly.vn; ++i)
|
for(int i=0; i<poly.vn; ++i)
|
||||||
if(!poly.vert[i].IsS())
|
if(!poly.vert[i].IsS())
|
||||||
{
|
{
|
||||||
Point3f smoothPos = (poly.vert[i].P() + posVec[i])/float(cntVec[i]+1);
|
CoordType smoothPos = (poly.vert[i].P() + posVec[i])/ScalarType(cntVec[i]+1);
|
||||||
|
|
||||||
Point3f newP = poly.vert[i].P()*(1.0-smoothWeight) + smoothPos *smoothWeight;
|
CoordType newP = poly.vert[i].P()*(1.0-smoothWeight) + smoothPos *smoothWeight;
|
||||||
|
|
||||||
Point3f delta = newP - poly.vert[i].P();
|
// CoordType delta = newP - poly.vert[i].P();
|
||||||
if(delta.Norm() > par.maxSmoothDelta)
|
// if(delta.Norm() > par.maxSmoothDelta)
|
||||||
{
|
// {
|
||||||
newP = poly.vert[i].P() + ( delta / delta.Norm()) * maxDist*0.5;
|
// newP = poly.vert[i].P() + ( delta / delta.Norm()) * maxDist*0.5;
|
||||||
}
|
// }
|
||||||
|
|
||||||
float minDist;
|
ScalarType minDist;
|
||||||
Point3f closestP;
|
CoordType closestP;
|
||||||
FaceType *f = vcg::tri::GetClosestFaceBase(base,uniformGrid,newP,maxDist, minDist, closestP);
|
FaceType *f = vcg::tri::GetClosestFaceBase(base,uniformGrid,newP,maxDist, minDist, closestP);
|
||||||
assert(f);
|
assert(f);
|
||||||
poly.vert[i].P() = newP*(1.0-projectWeight) +closestP*projectWeight;
|
poly.vert[i].P() = newP*(1.0-projectWeight) +closestP*projectWeight;
|
||||||
|
@ -1070,7 +1125,7 @@ public:
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
struct EdgePointSplit : public std::unary_function<face::Pos<FaceType> , Point3f>
|
struct EdgePointSplit : public std::unary_function<face::Pos<FaceType> , CoordType>
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
std::map<std::pair<CoordType,CoordType>, VertexPointer> &edgeToPolyVertMap;
|
std::map<std::pair<CoordType,CoordType>, VertexPointer> &edgeToPolyVertMap;
|
||||||
|
|
Loading…
Reference in New Issue