Corrections of include paths to comply the new folder arrangement of the VCG library (a first set of the many filters; removing useless includes)

This commit is contained in:
Paolo Cignoni cignoni 2011-04-03 23:44:39 +00:00
parent 4a8d3a71df
commit 3a2303e66d
22 changed files with 2908 additions and 2930 deletions

View File

@ -22,7 +22,7 @@
****************************************************************************/
#include "filter_plymc.h"
#include <vcg/complex/trimesh/append.h>
#include <vcg/complex/append.h>
#include <wrap/io_trimesh/export_vmi.h>
#include "plymc.h"

View File

@ -5,12 +5,12 @@ HEADERS += filter_plymc.h \
voxel.h \
plymc.h \
simplemeshprovider.h \
tri_edge_collapse_mc.h \
$$VCGDIR/vcg/complex/local_optimization/tri_edge_collapse.h
tri_edge_collapse_mc.h \
$$VCGDIR/vcg/algorithms/local_optimization/tri_edge_collapse.h
SOURCES += filter_plymc.cpp \
../../../../vcglib/wrap/ply/plylib.cpp
$$VCGDIR/wrap/ply/plylib.cpp
TARGET = filter_plymc
QT += opengl

View File

@ -30,28 +30,28 @@
#include <vcg/simplex/vertex/base.h>
#include <vcg/simplex/face/base.h>
#include <vcg/complex/used_types.h>
#include <vcg/complex/trimesh/base.h>
#include <vcg/complex/complex.h>
#include <vcg/complex/trimesh/update/position.h>
#include <vcg/complex/trimesh/update/normal.h>
#include <vcg/complex/trimesh/update/quality.h>
#include <vcg/complex/trimesh/update/edges.h>
#include <vcg/complex/trimesh/update/topology.h>
#include <vcg/complex/trimesh/update/flag.h>
#include <vcg/complex/trimesh/update/bounding.h>
#include <vcg/complex/algorithms/update/position.h>
#include <vcg/complex/algorithms/update/normal.h>
#include <vcg/complex/algorithms/update/quality.h>
#include <vcg/complex/algorithms/update/edges.h>
#include <vcg/complex/algorithms/update/topology.h>
#include <vcg/complex/algorithms/update/flag.h>
#include <vcg/complex/algorithms/update/bounding.h>
#include <vcg/math/histogram.h>
#include <vcg/complex/trimesh/clean.h>
#include <vcg/complex/algorithms/clean.h>
#include <wrap/io_trimesh/import.h>
#include <wrap/io_trimesh/export_ply.h>
#include <wrap/ply/plystuff.h>
#include <vcg/complex/trimesh/create/marching_cubes.h>
#include <vcg/complex/trimesh/create/extended_marching_cubes.h>
#include <vcg/complex/algorithms/create/marching_cubes.h>
#include <vcg/complex/algorithms/create/extended_marching_cubes.h>
#include "trivial_walker.h"
// local optimization
#include <vcg/complex/local_optimization.h>
#include <vcg/complex/local_optimization/tri_edge_collapse.h>
#include <vcg/complex/local_optimization/tri_edge_collapse_quadric.h>
#include <vcg/complex/algorithms/local_optimization.h>
#include <vcg/complex/algorithms/local_optimization/tri_edge_collapse.h>
#include <vcg/complex/algorithms/local_optimization/tri_edge_collapse_quadric.h>
#include <vcg/simplex/edge/base.h>
#include <stdarg.h>

View File

@ -41,7 +41,7 @@ add samplefilter
#include <time.h>
#include <common/interfaces.h>
#include <vcg/complex/trimesh/create/platonic.h>
#include <vcg/complex/algorithms/create/platonic.h>
#include "filter_poisson.h"
#include "src/Geometry.h"

View File

@ -34,12 +34,12 @@ $Log: samplefilter.cpp,v $
#include "filter_sampling.h"
#include <vcg/complex/trimesh/clean.h>
#include <vcg/complex/trimesh/point_sampling.h>
#include <vcg/complex/trimesh/create/resampler.h>
#include <vcg/complex/trimesh/clustering.h>
#include <vcg/complex/algorithms/clean.h>
#include <vcg/complex/algorithms/point_sampling.h>
#include <vcg/complex/algorithms/create/resampler.h>
#include <vcg/complex/algorithms/clustering.h>
#include <vcg/simplex/face/distance.h>
#include <vcg/complex/trimesh/geodesic.h>
#include <vcg/complex/algorithms/geodesic.h>
#include <vcg/space/index/grid_static_ptr.h>
#include "voronoi_clustering.h"
@ -54,7 +54,7 @@ using namespace std;
For example, you can compute Hausdorff distance (that is a sampler) using various
sampling strategies (montecarlo, stratified etc).
For further details see vcg/complex/trimesh/point_sampling.h header file.
For further details see vcg/complex/algorithms/point_sampling.h header file.
*/

View File

@ -1,7 +1,7 @@
include (../../shared.pri)
HEADERS += filter_sampling.h \
$$VCGDIR/vcg/complex/trimesh/point_sampling.h
$$VCGDIR/vcg/complex/algorithms/point_sampling.h
SOURCES += filter_sampling.cpp
TARGET = filter_sampling

View File

@ -1,11 +1,11 @@
#include <vcg/complex/trimesh/base.h>
#include <vcg/complex/trimesh/update/topology.h>
#include <vcg/complex/trimesh/update/edges.h>
#include <vcg/complex/trimesh/update/bounding.h>
#include <vcg/complex/trimesh/update/quality.h>
#include <vcg/complex/trimesh/update/color.h>
#include <vcg/complex/trimesh/update/flag.h>
#include <vcg/complex/trimesh/clean.h>
#include <vcg/complex/complex.h>
#include <vcg/complex/algorithms/update/topology.h>
#include <vcg/complex/algorithms/update/edges.h>
#include <vcg/complex/algorithms/update/bounding.h>
#include <vcg/complex/algorithms/update/quality.h>
#include <vcg/complex/algorithms/update/color.h>
#include <vcg/complex/algorithms/update/flag.h>
#include <vcg/complex/algorithms/clean.h>
#include <vcg/complex/intersection.h>
#include <vcg/space/index/grid_static_ptr.h>
#include <vcg/space/index/spatial_hashing.h>

View File

@ -1,15 +1,6 @@
#include <vcg/complex/trimesh/base.h>
#include <vcg/complex/trimesh/update/topology.h>
#include <vcg/complex/trimesh/update/edges.h>
#include <vcg/complex/trimesh/update/bounding.h>
#include <vcg/complex/trimesh/update/quality.h>
#include <vcg/complex/trimesh/update/color.h>
#include <vcg/complex/trimesh/update/flag.h>
#include <vcg/complex/trimesh/clean.h>
#include <vcg/complex/intersection.h>
#include <vcg/complex/algorithms/intersection.h>
#include <vcg/space/index/grid_static_ptr.h>
#include <vcg/space/index/spatial_hashing.h>
#include <vcg/math/matrix33.h>
#include <vcg/space/index/grid_static_ptr.h> // vcg::GridStaticPtr
#include <vcg/space/index/spatial_hashing.h> // vcg::SpatialHashTable
@ -107,7 +98,7 @@ bool SdfPlugin::applyFilter(MeshDocument& md, RichParameterSet& pars, vcg::CallB
float maxDist=m.bbox.Diag();
// This is a small number to avoid self-intersection during ray
// casting. It's a very common trick
float epsilon = maxDist / 10000.0;
float epsilon = maxDist / 1000.0;
//--- Ray casting
vector<Ray3f> cone;
@ -118,7 +109,7 @@ bool SdfPlugin::applyFilter(MeshDocument& md, RichParameterSet& pars, vcg::CallB
for(int i=0; i<m.vert.size(); i++){
CVertexO& v = m.vert[i];
//--- Update progressbar
cb( i/m.vert.size(), "Casting rays into volume...");
cb( 100*i/m.vert.size(), "Casting rays into volume...");
//--- Generate the set of cones
ray.Set( v.P(), -v.N() );
@ -148,7 +139,7 @@ bool SdfPlugin::applyFilter(MeshDocument& md, RichParameterSet& pars, vcg::CallB
//--- Compute average of samples, throwing away outliers
float totVal = 0, totCnt = 0;
for(unsigned int i=0; i<coneSdf.size(); i++)
if( !math::IsNAN(coneSdf[i]) && coneSdf[i]>loperc && coneSdf[i]<hiperc ){
if( !math::IsNAN(coneSdf[i]) && coneSdf[i]>=loperc && coneSdf[i]<=hiperc ){
totVal += coneSdf[i];
totCnt += 1;
}

View File

@ -1,6 +1,6 @@
include (../../shared.pri)
HEADERS += $$VCGDIR/vcg/complex/trimesh/clean.h\
HEADERS += $$VCGDIR/vcg/complex/algorithms/clean.h\
meshselect.h
SOURCES += meshselect.cpp

View File

@ -26,8 +26,8 @@
#include <stdlib.h>
#include <vcg/space/colorspace.h>
#include "meshselect.h"
#include <vcg/complex/trimesh/clean.h>
#include <vcg/complex/trimesh/stat.h>
#include <vcg/complex/algorithms/clean.h>
#include <vcg/complex/algorithms/stat.h>
using namespace vcg;

View File

@ -23,13 +23,12 @@
#include "filter_slice.h"
//#include <stdlib.h>
#include <vcg/complex/intersection.h>
#include <vcg/complex/algorithms/intersection.h>
#include <algorithm>
#include "filter_slice_functors.h"
#include <wrap/gl/glu_tesselator.h>
#include <vcg/complex/trimesh/allocate.h>
#include "kdtree.h"

View File

@ -30,12 +30,8 @@
#include <vcg/complex/edgemesh/base.h>
#include <vcg/complex/edgemesh/update/bounding.h>
#include <vcg/complex/trimesh/update/bounding.h>
#include <vcg/complex/trimesh/update/flag.h>
#include <vcg/complex/trimesh/refine.h>
#include <vcg/complex/trimesh/clean.h>
#include <vcg/complex/trimesh/append.h>
#include <vcg/complex/trimesh/update/selection.h>
#include <vcg/complex/algorithms/refine.h>
#include <vcg/complex/append.h>
#include <wrap/io_edgemesh/export_svg.h>
#include <vcg/space/plane3.h>

View File

@ -1,198 +1,198 @@
/****************************************************************************
* MeshLab o o *
* An extendible mesh processor o o *
* _ O _ *
* Copyright(C) 2005, 2009 \/)\/ *
* 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 SLICE_KD_TREE
#define SLICE_KD_TREE
#include <vcg/space/point3.h>
#include <vcg/complex/trimesh/update/bounding.h>
#include "filter_slice_functors.h"
#include "filter_slice.h"
template<typename MeshType>
class KDTree
{
protected:
KDTree<MeshType> *leftChild, *rightChild;
MeshType *slice;
MeshModel* mm;
Point3f planeAxis;
MeshDocument *m;
int axisIndex;
float eps;
QString name;
public:
bool delfather;
enum{X,Y,Z};
KDTree(MeshDocument *_m, MeshModel* _mm, float _eps, int _axisIndex=X)
{
name="";
m=_m;
mm=_mm;
eps=_eps;
planeAxis=Point3f(0,0,0);
leftChild=0;
rightChild=0;
slice=0;
axisIndex=_axisIndex;
assert(axisIndex>=0 && axisIndex<3);
planeAxis[axisIndex]=1;
delfather=false;
}
~KDTree(){}
KDTree<MeshType>* L(){return leftChild;}
KDTree<MeshType>* R(){return rightChild;}
MeshType* S(){return slice;}
void Slice(vcg::CallBackPos *cb)
{
Plane3f slicingPlane;
vcg::tri::UpdateBounding<CMeshO>::Box(mm->cm);
slicingPlane.Init(mm->cm.bbox.Center(),planeAxis);
actual_slice(slicingPlane,cb);
}
void actual_slice(Plane3f slicingPlane,vcg::CallBackPos *cb=0)
{
if (mm->cm.vn<=0)
return;
mm->updateDataMask(MeshModel::MM_FACEFACETOPO | MeshModel::MM_FACEFLAGBORDER);
if ( tri::Clean<CMeshO>::CountNonManifoldEdgeFF(mm->cm)>0 || tri::Clean<CMeshO>::CountNonManifoldVertexFF(mm->cm,false) != 0)
return;
if (rightChild!=0 && leftChild!=0)
{
//find a plane
Plane3f slicingPlane;
vcg::Box3f leftbox=leftChild->mm->cm.bbox;
vcg::Box3f rightbox=rightChild->mm->cm.bbox;
leftbox.Translate(planeAxis*((leftbox.Dim()*.2)*planeAxis));
rightbox.Translate(planeAxis*(-1)*((rightbox.Dim()*.2)*planeAxis));
leftbox.Intersect(rightbox);
slicingPlane.Init(leftbox.Center(),leftChild->planeAxis);
leftChild->actual_slice(slicingPlane,cb);
rightChild->actual_slice(slicingPlane,cb);
return;
}
//bool oriented;
//bool orientable;
//tolto per controllare le normali
//tri::Clean<CMeshO>::IsOrientedMesh(mm->cm, oriented,orientable);
//actual slicing
//vcg::tri::UpdateFlags<CMeshO>::FaceBorderFromNone(mm->cm);
SlicedEdge<CMeshO> slicededge(slicingPlane);
SlicingFunction<CMeshO> slicingfunc(slicingPlane);
//after the RefineE call, the mesh will be half vertices selected
vcg::RefineE<CMeshO, SlicingFunction<CMeshO>, SlicedEdge<CMeshO> >
(mm->cm, slicingfunc, slicededge, false, cb);
//vcg::tri::UpdateTopology<MeshType>::FaceFace(mm->cm);
vcg::tri::UpdateNormals<CMeshO>::PerVertexPerFace(mm->cm);
//vcg::tri::Clean<CMeshO>::RemoveDuplicateVertex(mm->cm);
vcg::tri::UpdateTopology<CMeshO>::FaceFace(mm->cm);
QString layername;
layername=name+"L.ply";
MeshModel *slice1= m->addNewMesh("",qPrintable(layername));
m->meshList.push_back(slice1); // mesh name
slice1->updateDataMask(MeshModel::MM_FACEFACETOPO | MeshModel::MM_FACEFLAGBORDER);
vcg::tri::UpdateSelection<CMeshO>::VertexFromQualityRange(mm->cm,VERTEX_LEFT,VERTEX_LEFT);
vcg::tri::UpdateSelection<CMeshO>::FaceFromVertexLoose(mm->cm);
//if (hideSlices)
//slice1->visible=false;
//createSlice(mm->cm,slice1);
tri::Append<CMeshO,CMeshO>::Mesh(slice1->cm, mm->cm, true);
tri::UpdateTopology<CMeshO>::FaceFace(slice1->cm);
tri::UpdateBounding<CMeshO>::Box(slice1->cm); // updates bounding box
slice1->cm.Tr = (mm->cm).Tr; // copy transformation
vcg::tri::UpdateFlags<CMeshO>::FaceBorderFromNone(slice1->cm);
layername=name+"_slice.ply";
MeshModel* cap= m->addNewMesh("",qPrintable(layername));
m->meshList.push_back(cap);
cap->updateDataMask(MeshModel::MM_FACEFACETOPO | MeshModel::MM_FACEFLAGBORDER);
ExtraFilter_SlicePlugin::capHole(slice1,cap);
if (eps!=0)
{
layername=name+"_extr.ply";
MeshModel* dup = m->addNewMesh("",qPrintable(layername));
m->meshList.push_back(dup);
dup->updateDataMask(MeshModel::MM_FACEFACETOPO | MeshModel::MM_FACEFLAGBORDER);
ExtraFilter_SlicePlugin::extrude(m,cap, dup, eps, planeAxis);
}
tri::Append<CMeshO,CMeshO>::Mesh(slice1->cm, cap->cm);
tri::Clean<CMeshO>::RemoveDuplicateVertex(slice1->cm);
vcg::tri::UpdateTopology<CMeshO>::FaceFace(slice1->cm);
vcg::tri::UpdateNormals<CMeshO>::PerVertexPerFace(slice1->cm);
layername=name+"R.ply";
MeshModel* slice2= m->addNewMesh("",qPrintable(layername));
m->meshList.push_back(slice2);
slice2->updateDataMask(MeshModel::MM_FACEFACETOPO | MeshModel::MM_FACEFLAGBORDER);
vcg::tri::UpdateSelection<CMeshO>::VertexFromQualityRange(mm->cm,VERTEX_RIGHT,VERTEX_RIGHT);
vcg::tri::UpdateSelection<CMeshO>::FaceFromVertexLoose(mm->cm);
//createSlice(mesh,slice2);
tri::Append<CMeshO,CMeshO>::Mesh(slice2->cm, mm->cm, true);
tri::UpdateTopology<CMeshO>::FaceFace(slice2->cm);
tri::UpdateBounding<CMeshO>::Box(slice2->cm); // updates bounding box
slice2->cm.Tr = (mm->cm).Tr; // copy transformation
tri::Clean<CMeshO>::FlipMesh(cap->cm);
vcg::tri::UpdateFlags<CMeshO>::FaceBorderFromNone(slice2->cm);
tri::Append<CMeshO,CMeshO>::Mesh(slice2->cm, cap->cm);
tri::Clean<CMeshO>::RemoveDuplicateVertex(slice2->cm);
vcg::tri::UpdateTopology<CMeshO>::FaceFace(slice2->cm);
vcg::tri::UpdateNormals<CMeshO>::PerVertexPerFace(slice2->cm);
leftChild=new KDTree<MeshType>(m,slice1,eps,(axisIndex+1)%3);
leftChild->delfather=delfather;
layername=name+"L";
leftChild->name=layername.toStdString().c_str();
rightChild=new KDTree<MeshType>(m,slice2,eps,(axisIndex+1)%3);
rightChild->delfather=delfather;
layername=name+"R";
rightChild->name=layername.toStdString().c_str();
slice1->visible=false;
slice1->updateDataMask(MeshModel::MM_FACEFACETOPO | MeshModel::MM_FACEFLAGBORDER);
vcg::tri::UpdateTopology<CMeshO>::FaceFace(slice1->cm);
vcg::tri::UpdateBounding<CMeshO>::Box(slice1->cm);
slice2->visible=false;
slice2->updateDataMask(MeshModel::MM_FACEFACETOPO | MeshModel::MM_FACEFLAGBORDER);
vcg::tri::UpdateTopology<CMeshO>::FaceFace(slice2->cm);
vcg::tri::UpdateBounding<CMeshO>::Box(slice2->cm);
cap->visible=false;
//if (delfather)
//m->delMesh(mm);
}
};
#endif
/****************************************************************************
* MeshLab o o *
* An extendible mesh processor o o *
* _ O _ *
* Copyright(C) 2005, 2009 \/)\/ *
* 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 SLICE_KD_TREE
#define SLICE_KD_TREE
#include <vcg/space/point3.h>
#include <vcg/complex/algorithms/update/bounding.h>
#include "filter_slice_functors.h"
#include "filter_slice.h"
template<typename MeshType>
class KDTree
{
protected:
KDTree<MeshType> *leftChild, *rightChild;
MeshType *slice;
MeshModel* mm;
Point3f planeAxis;
MeshDocument *m;
int axisIndex;
float eps;
QString name;
public:
bool delfather;
enum{X,Y,Z};
KDTree(MeshDocument *_m, MeshModel* _mm, float _eps, int _axisIndex=X)
{
name="";
m=_m;
mm=_mm;
eps=_eps;
planeAxis=Point3f(0,0,0);
leftChild=0;
rightChild=0;
slice=0;
axisIndex=_axisIndex;
assert(axisIndex>=0 && axisIndex<3);
planeAxis[axisIndex]=1;
delfather=false;
}
~KDTree(){}
KDTree<MeshType>* L(){return leftChild;}
KDTree<MeshType>* R(){return rightChild;}
MeshType* S(){return slice;}
void Slice(vcg::CallBackPos *cb)
{
Plane3f slicingPlane;
vcg::tri::UpdateBounding<CMeshO>::Box(mm->cm);
slicingPlane.Init(mm->cm.bbox.Center(),planeAxis);
actual_slice(slicingPlane,cb);
}
void actual_slice(Plane3f slicingPlane,vcg::CallBackPos *cb=0)
{
if (mm->cm.vn<=0)
return;
mm->updateDataMask(MeshModel::MM_FACEFACETOPO | MeshModel::MM_FACEFLAGBORDER);
if ( tri::Clean<CMeshO>::CountNonManifoldEdgeFF(mm->cm)>0 || tri::Clean<CMeshO>::CountNonManifoldVertexFF(mm->cm,false) != 0)
return;
if (rightChild!=0 && leftChild!=0)
{
//find a plane
Plane3f slicingPlane;
vcg::Box3f leftbox=leftChild->mm->cm.bbox;
vcg::Box3f rightbox=rightChild->mm->cm.bbox;
leftbox.Translate(planeAxis*((leftbox.Dim()*.2)*planeAxis));
rightbox.Translate(planeAxis*(-1)*((rightbox.Dim()*.2)*planeAxis));
leftbox.Intersect(rightbox);
slicingPlane.Init(leftbox.Center(),leftChild->planeAxis);
leftChild->actual_slice(slicingPlane,cb);
rightChild->actual_slice(slicingPlane,cb);
return;
}
//bool oriented;
//bool orientable;
//tolto per controllare le normali
//tri::Clean<CMeshO>::IsOrientedMesh(mm->cm, oriented,orientable);
//actual slicing
//vcg::tri::UpdateFlags<CMeshO>::FaceBorderFromNone(mm->cm);
SlicedEdge<CMeshO> slicededge(slicingPlane);
SlicingFunction<CMeshO> slicingfunc(slicingPlane);
//after the RefineE call, the mesh will be half vertices selected
vcg::RefineE<CMeshO, SlicingFunction<CMeshO>, SlicedEdge<CMeshO> >
(mm->cm, slicingfunc, slicededge, false, cb);
//vcg::tri::UpdateTopology<MeshType>::FaceFace(mm->cm);
vcg::tri::UpdateNormals<CMeshO>::PerVertexPerFace(mm->cm);
//vcg::tri::Clean<CMeshO>::RemoveDuplicateVertex(mm->cm);
vcg::tri::UpdateTopology<CMeshO>::FaceFace(mm->cm);
QString layername;
layername=name+"L.ply";
MeshModel *slice1= m->addNewMesh("",qPrintable(layername));
m->meshList.push_back(slice1); // mesh name
slice1->updateDataMask(MeshModel::MM_FACEFACETOPO | MeshModel::MM_FACEFLAGBORDER);
vcg::tri::UpdateSelection<CMeshO>::VertexFromQualityRange(mm->cm,VERTEX_LEFT,VERTEX_LEFT);
vcg::tri::UpdateSelection<CMeshO>::FaceFromVertexLoose(mm->cm);
//if (hideSlices)
//slice1->visible=false;
//createSlice(mm->cm,slice1);
tri::Append<CMeshO,CMeshO>::Mesh(slice1->cm, mm->cm, true);
tri::UpdateTopology<CMeshO>::FaceFace(slice1->cm);
tri::UpdateBounding<CMeshO>::Box(slice1->cm); // updates bounding box
slice1->cm.Tr = (mm->cm).Tr; // copy transformation
vcg::tri::UpdateFlags<CMeshO>::FaceBorderFromNone(slice1->cm);
layername=name+"_slice.ply";
MeshModel* cap= m->addNewMesh("",qPrintable(layername));
m->meshList.push_back(cap);
cap->updateDataMask(MeshModel::MM_FACEFACETOPO | MeshModel::MM_FACEFLAGBORDER);
ExtraFilter_SlicePlugin::capHole(slice1,cap);
if (eps!=0)
{
layername=name+"_extr.ply";
MeshModel* dup = m->addNewMesh("",qPrintable(layername));
m->meshList.push_back(dup);
dup->updateDataMask(MeshModel::MM_FACEFACETOPO | MeshModel::MM_FACEFLAGBORDER);
ExtraFilter_SlicePlugin::extrude(m,cap, dup, eps, planeAxis);
}
tri::Append<CMeshO,CMeshO>::Mesh(slice1->cm, cap->cm);
tri::Clean<CMeshO>::RemoveDuplicateVertex(slice1->cm);
vcg::tri::UpdateTopology<CMeshO>::FaceFace(slice1->cm);
vcg::tri::UpdateNormals<CMeshO>::PerVertexPerFace(slice1->cm);
layername=name+"R.ply";
MeshModel* slice2= m->addNewMesh("",qPrintable(layername));
m->meshList.push_back(slice2);
slice2->updateDataMask(MeshModel::MM_FACEFACETOPO | MeshModel::MM_FACEFLAGBORDER);
vcg::tri::UpdateSelection<CMeshO>::VertexFromQualityRange(mm->cm,VERTEX_RIGHT,VERTEX_RIGHT);
vcg::tri::UpdateSelection<CMeshO>::FaceFromVertexLoose(mm->cm);
//createSlice(mesh,slice2);
tri::Append<CMeshO,CMeshO>::Mesh(slice2->cm, mm->cm, true);
tri::UpdateTopology<CMeshO>::FaceFace(slice2->cm);
tri::UpdateBounding<CMeshO>::Box(slice2->cm); // updates bounding box
slice2->cm.Tr = (mm->cm).Tr; // copy transformation
tri::Clean<CMeshO>::FlipMesh(cap->cm);
vcg::tri::UpdateFlags<CMeshO>::FaceBorderFromNone(slice2->cm);
tri::Append<CMeshO,CMeshO>::Mesh(slice2->cm, cap->cm);
tri::Clean<CMeshO>::RemoveDuplicateVertex(slice2->cm);
vcg::tri::UpdateTopology<CMeshO>::FaceFace(slice2->cm);
vcg::tri::UpdateNormals<CMeshO>::PerVertexPerFace(slice2->cm);
leftChild=new KDTree<MeshType>(m,slice1,eps,(axisIndex+1)%3);
leftChild->delfather=delfather;
layername=name+"L";
leftChild->name=layername.toStdString().c_str();
rightChild=new KDTree<MeshType>(m,slice2,eps,(axisIndex+1)%3);
rightChild->delfather=delfather;
layername=name+"R";
rightChild->name=layername.toStdString().c_str();
slice1->visible=false;
slice1->updateDataMask(MeshModel::MM_FACEFACETOPO | MeshModel::MM_FACEFLAGBORDER);
vcg::tri::UpdateTopology<CMeshO>::FaceFace(slice1->cm);
vcg::tri::UpdateBounding<CMeshO>::Box(slice1->cm);
slice2->visible=false;
slice2->updateDataMask(MeshModel::MM_FACEFACETOPO | MeshModel::MM_FACEFLAGBORDER);
vcg::tri::UpdateTopology<CMeshO>::FaceFace(slice2->cm);
vcg::tri::UpdateBounding<CMeshO>::Box(slice2->cm);
cap->visible=false;
//if (delfather)
//m->delMesh(mm);
}
};
#endif

View File

@ -27,8 +27,8 @@
#include <QObject>
#include <QTime>
#include <vcg/complex/trimesh/attribute_seam.h>
#include <vcg/complex/trimesh/point_sampling.h>
#include <vcg/complex/algorithms/attribute_seam.h>
#include <vcg/complex/algorithms/point_sampling.h>
#include <vcg/space/triangle2.h>
#include <common/interfaces.h>

View File

@ -33,7 +33,7 @@ $Log: samplefilter.cpp,v $
#include <stdlib.h>
#include <meshlab/meshmodel.h>
#include <vcg/complex/trimesh/clean.h>
#include <vcg/complex/algorithms/clean.h>
#include "filter_texture.h"

View File

@ -26,7 +26,7 @@
#include <QtGui>
#include <common/interfaces.h>
#include <vcg/complex/trimesh/point_sampling.h>
#include <vcg/complex/algorithms/point_sampling.h>
#include <vcg/space/triangle2.h>
class VertexSampler

View File

@ -24,12 +24,9 @@
#include <QtGui>
#include "filter_unsharp.h"
#include <vcg/complex/trimesh/update/quality.h>
#include <vcg/complex/trimesh/update/color.h>
#include <vcg/complex/trimesh/update/selection.h>
#include <vcg/complex/trimesh/clean.h>
#include <vcg/complex/trimesh/smooth.h>
#include <vcg/complex/trimesh/crease_cut.h>
#include <vcg/complex/algorithms/clean.h>
#include <vcg/complex/algorithms/smooth.h>
#include <vcg/complex/algorithms/crease_cut.h>
using namespace vcg;

View File

@ -1,7 +1,7 @@
include (../../shared.pri)
HEADERS += filter_unsharp.h \
$$VCGDIR/vcg/complex/trimesh/crease_cut.h
$$VCGDIR/vcg/complex/algorithms/crease_cut.h
SOURCES += filter_unsharp.cpp

View File

@ -1,484 +1,484 @@
#ifndef VCGLIB_REGION_GROWING
#define VCGLIB_REGION_GROWING
#include <list>
#include <vector>
#include <vcg/complex/trimesh/allocate.h>
template <class FaceType>
struct FaceError{
FaceType * f;
float val;
FaceError(){};
FaceError(FaceType * _f,double _val):f(_f),val(_val){}
const bool operator <(const FaceError & o) const {return val < o.val;}
};
template<class MeshType>
struct Region{
Region():isd(false){}
typedef Region RegionType;
typedef typename MeshType MeshType;
typedef typename MeshType::FaceType FaceType;
typedef typename MeshType::FaceType::CoordType CoordType;
typedef typename MeshType::FaceType::ScalarType ScalarType;
typedef typename std::vector<typename MeshType::FaceType*>::iterator FaceIterator;
typedef typename std::list<Region*>::iterator AdjIterator;
typedef FaceError<FaceType> FaceError;
// adjacent regions
std::list<RegionType*> adj,nx_adj;
// some flag
bool isd;
// evaluate the gain if the triangle is added to the region
ScalarType Evaluate( FaceType & f);
// update the approximation error of the region
void UpdateError( );
// check if two regions are mergeable in one
// i.e. if they have the same planes and coincide i non extreme
ScalarType Mergeable( RegionType & tr);
// set the region as adjacent to this one
void Connect( RegionType * tr);
// compute the faces which are on the border
void ComputeOnBorder( std::vector<FaceType*> & onBorder);
// clean the list of adjacencies
void Clean();
// refit the plane
void Refit();
// keep the best % percentile
void CutOff( FaceType*f);
// restart from the best fitting face
void Restart();
void Decorate();
};
template < class RegionType>
class RegionGrower{
public:
RegionGrower():lastAdded(NULL),ave_error(-1),ave_var(-1),n_steps(0){}
typedef typename RegionType RegionType;
typedef typename RegionType::MeshType MeshType;
typedef typename RegionType::FaceType FaceType;
typedef typename FaceType::ScalarType ScalarType;
typedef typename std::list<RegionType> ::iterator TriRegIterator;
typedef typename std::list<RegionType*>::iterator AdjIterator;
typedef typename RegionType::FaceError FaceError;
std::list<RegionType> regions;
std::vector<RegionType*> workingset;
int n_faces,target_max_regions;
FaceType * lastAdded;
ScalarType ave_error // average error (over single regions' error)
,ave_var// average variance (over single regions' error)
,changed // faces that have changed from previous step ([0..1))
,err
,target_error; // taget error
FaceType * worst;
ScalarType worst_err ;
MeshType * m;
typename MeshType:: template PerFaceAttributeHandle<int*> attr_r;
typename MeshType:: template PerFaceAttributeHandle<int*> attr_r_old;
unsigned int n_steps;// number of steps done
struct CandiFace{
FaceType * f;
float val;
RegionType * r;
char inPlane; // a quale piano di r
CandiFace(){};
CandiFace(FaceType * _f,double _val,RegionType * _r):f(_f),val(_val),r(_r){}
const bool operator <(const CandiFace & o) const {return val < o.val;}
};
std::vector<CandiFace> facesheap;
std::vector<FaceError > faceserr;
struct ErrorEval {
void Add(const float & v){
if(!ns){
if(v < samples[i_min]) i_min = 0; else {++i_min;
if(v > samples[i_max]) i_max = 0;else ++i_max;
}
if(i_min == samples.size()) {i_min = 0; for(int i= 0; i < samples.size(); ++i) if(samples[i]<samples[i_min]) i_min = i; }
if(i_max == samples.size()) {i_max = 0; for(int i= 0; i < samples.size(); ++i) if(samples[i]>samples[i_max]) i_max = i; }
}
samples.pop_back();samples.push_front(v);
boxes.pop_back(); boxes.push_front(vcg::Point2f(samples[i_min],samples[i_max]));
++ns ;
}
float BoxOverlap(){
float maxsize = std::max( boxes.back()[1]-boxes.back()[0], (*boxes.begin())[1]-(*boxes.begin())[0]);
float overlap = std::max(0.f, std::min(boxes.back()[1],(*boxes.begin())[1])-std::max(boxes.back()[0],(*boxes.begin())[0]));
assert(overlap <= maxsize);
return (maxsize > 0.f)?overlap / maxsize:0.0;
}
float RelativeDecrease(){
if (ns<2) return std::numeric_limits<float>::max();
return (samples[0]<10e-22)?0.0:(samples[1]-samples[0])/samples[0];
}
void Init(int n ){
samples.clear();
boxes.clear();
for(int i = 0 ; i < n; ++i) samples.push_front(std::numeric_limits<float>::max());
for(int i = 0 ; i < n; ++i) boxes.push_front(vcg::Point2f(n,n-i));
i_max = i_min = 0;
ns = 0;
}
private:
int i_min,i_max; // index of min and max element in the queue
std::deque<float> samples;
std::deque<vcg::Point2f> boxes;
int ns;
};
ErrorEval erroreval;
// init
void Init(MeshType & mesh, int n_seeds,int max_regions, float max_err){
erroreval.Init(10);
m = &mesh;
vcg::tri::Allocator<MeshType>::CompactFaceVector(*m);
vcg::tri::UpdateTopology<MeshType>::FaceFace(*m);
float area = 0.f;
for(typename MeshType::FaceIterator fi = m->face.begin(); fi != m->face.end(); ++fi)
area += vcg::DoubleArea(*fi);
area/=2.f;
target_error = area*max_err*max_err;
target_max_regions = max_regions;
// tte an attibute that will store the address in ocme for the vertex
attr_r = vcg::tri::Allocator<MeshType>::template GetPerFaceAttribute<int*> (*m,"r");
if(!vcg::tri::Allocator<MeshType>::IsValidHandle(*m,attr_r))
attr_r = vcg::tri::Allocator<MeshType>::template AddPerFaceAttribute<int*> (*m,"r");
attr_r_old = vcg::tri::Allocator<MeshType>::template GetPerFaceAttribute<int*> (*m,"r_old");
if(!vcg::tri::Allocator<MeshType>::IsValidHandle(*m,attr_r_old))
attr_r_old = vcg::tri::Allocator<MeshType>::template AddPerFaceAttribute<int*> (*m,"r_old");
regions.clear();
for(int i = 0; i < m->face.size(); ++i){
attr_r[i] = NULL;
attr_r_old[i] = NULL;
if( (i%(m->fn/n_seeds))==0)
CreateRegion(&m->face[i]);
}
}
// add a region
void AddRegion(const RegionType & r){regions.push_back(r);}
// remove a region
void DeleteRegion(const typename std::list<RegionType>::iterator & ri){std::remove(ri);}
// initialize a region
void CreateRegion(FaceType * fi){
AddRegion(RegionType());
RegionType & tr =regions.back();
AddFaceToRegion(tr,fi);
tr.Refit();
tr.color = vcg::Color4b::Scatter(2000,(int)regions.size());
}
void AddFaceToRegion( RegionType & r, FaceType * f){
r.face.push_back(f);
attr_r[*f] = (int*) &r;
if(attr_r[*f]!=attr_r_old[*f]) ++r.changed;
attr_r_old[*f] = attr_r[*f];
++r.size;
}
void Merge(RegionType & r0,RegionType & r1){
assert(!r1.isd);
typename RegionType::FaceIterator fi;
AdjIterator ai;
for(fi = r1.face.begin();fi != r1.face.end(); ++fi)
AddFaceToRegion(r0,(*fi));
for(ai= r1.adj.begin(); ai != r1.adj.end();++ai)
if( !(*ai)->isd && (*ai)!=&r0)
r0.nx_adj.push_back(*ai);
r1.face.clear();
r1.isd = true;
r0.Refit();
}
void PushHeap(std::vector<FaceType*> & candi, RegionType & r){
typename std::vector<FaceType*>::iterator ci;
for(ci = candi.begin(); ci != candi.end(); ++ci)
{
facesheap.push_back(CandiFace( *ci,-r.Evaluate(*(*ci)), &r));
push_heap(facesheap.begin(),facesheap.end());
}
}
// the two regions are adjacent
void Connect(RegionType * r1,RegionType * r2){
assert(r1!=r2);
r1->Connect(r2);
r2->Connect(r1);
}
// for each region take the candidates and fill in facesheap
void Refill( ){
facesheap.clear();
typename std::list<RegionType>::iterator ri;
std::vector<FaceType*> candi;
for(ri = regions.begin(); ri != regions.end(); ++ri) if(!(*ri).isd)
{
candi.clear();
Candidates((*ri),candi);
PushHeap(candi,*ri);
}
std::make_heap(facesheap.begin(),facesheap.end());
}
void Candidates(RegionType & r, std::vector< typename RegionType::FaceType*> & c){
typename RegionType::FaceIterator fi;
for(fi = r.face.begin(); fi!= r.face.end(); ++fi)
for(int i = 0; i < 3; ++i)
if( ((*fi)->FFp(i) != (*fi) ) &&
(attr_r[(*fi)->FFp(i)] != (int*) &r) )
c.push_back((*fi)->FFp(i));
}
bool IsRelaxed(){
ScalarType _ave_error=0;
ScalarType _ave_var= 0;
ScalarType _changed = 0.0;
int nr=0;
typename std::list<RegionType>::iterator ri;
worst=NULL;;
worst_err = -1;
qDebug("working set size: %d\n",workingset.size());
for(ri = regions.begin(); ri != regions.end(); ++ri) if(!(*ri).isd){
++nr;
(*ri).UpdateError();
_ave_error+=(*ri).approx_err;
_ave_var+=(*ri).approx_var;
_changed+=(*ri).changed;
(*ri).changed=0;
if((*ri).worst.val*(*ri).size > worst_err){
worst = (*ri).worst.f;
worst_err = (*ri).worst.val*(*ri).size;
}
}
_ave_error/=nr;
_ave_var/=nr;
_changed/=n_faces;
erroreval.Add(_ave_error);
qDebug("Err:%f ov: %f-------",_ave_error,erroreval.BoxOverlap());
return (erroreval.BoxOverlap() > 0.5) || (erroreval.RelativeDecrease() < 0.1);
}
void GrowStepOnce(){
CandiFace cf;
typename std::list<RegionType>::iterator ri;
for(ri = regions.begin(); ri != regions.end(); ++ri) if(!(*ri).isd)
(*ri).Clean();
if(!facesheap.empty()){
std::vector<FaceType*> toAdd;
std::pop_heap(facesheap.begin(),facesheap.end());
cf = facesheap.back();
// qDebug("err:%f\n",cf.val);
facesheap.pop_back();
if (attr_r[*cf.f]==NULL){
lastAdded = cf.f;
AddFaceToRegion(*cf.r,cf.f); // adds to region
for(int i=0; i < 3;++i) // put the adjacent in the set of faces to possibly add
if( (attr_r[cf.f->FFp(i)] == NULL) )
toAdd.push_back(cf.f->FFp(i));
PushHeap(toAdd,*cf.r);
}
else
{
int * aa = attr_r[*cf.f] ;
if ( attr_r[*cf.f] != (int*)(cf.r) )
Connect((RegionType*)attr_r[*cf.f],(RegionType*)cf.r);
}
}
int h = (int)facesheap.size();
// qDebug("----> %d\n",h);
}
void GrowStep(){
CandiFace cf;
typename std::list<RegionType>::iterator ri;
n_steps++;
for(ri = regions.begin(); ri != regions.end(); ++ri) if(!(*ri).isd)
(*ri).Clean();
while(!facesheap.empty() ){
std::vector<FaceType*> toAdd;
std::pop_heap(facesheap.begin(),facesheap.end());
cf = facesheap.back();
//printf("err:%f\n",cf.val);
facesheap.pop_back();
if (attr_r[*cf.f]==NULL){
AddFaceToRegion( *cf.r,cf.f); // ads to region
lastAdded = &*cf.f;
for(int i=0; i < 3;++i) // put the adjacent in the set of faces to possibly add
if( attr_r[ *cf.f->FFp(i)] == NULL )
toAdd.push_back(cf.f->FFp(i));
else
if(attr_r[*cf.f->FFp(i)] != attr_r[*cf.f])
Connect((RegionType*)attr_r[*cf.f->FFp(i)],(RegionType*)cf.r);
PushHeap(toAdd,*cf.r);
}
else
{
if ( attr_r[*cf.f] != (int*)(cf.r) )
Connect((RegionType*)attr_r[*cf.f],(RegionType*)cf.r);
}
}
int h = (int) facesheap.size();
printf("----> %d\n",h);
}
unsigned int MergeStep(){
TriRegIterator tri;
unsigned int merged = 0;
typename RegionType::AdjIterator ai;
for(tri = regions.begin(); tri != regions.end(); ++tri)if(!(*tri).isd)
for(ai = (*tri).adj.begin(); ai != (*tri).adj.end(); ++ai) if(!(*ai)->isd)
if((*tri).Mergeable(*(*ai))){
Merge((*tri),*(*ai));
merged++;
}
for(tri = regions.begin(); tri != regions.end(); ++tri){
for(ai = (*tri).nx_adj.begin(); ai != (*tri).nx_adj.end();++ai)
if(!(*ai)->isd)
(*tri).adj.push_back(*ai);
(*tri).adj.sort();
(*tri).adj.unique();
}
return merged;
}
//void TeleportStep(){
// TriRegIterator tri;
// typename RegionType::AdjIterator ai;
// for(tri = regions.begin(); tri != regions.end(); ++tri)if(!(*tri).isd){
// std::vector<FaceType*> & onBorder
// ComputeOnBorder(onBorder);
// if(onBorder.empty
// }
//
//}
bool Restart(){
std::vector<FaceType*> candi;
TriRegIterator ri;
facesheap.clear();
if(IsRelaxed()){
if( (worst_err <= target_error) || (regions.size() >= target_max_regions))
return false;
else
{
erroreval.Init(10);
FaceError wrs;
wrs.f = worst;
wrs.val = worst_err;
printf("worst triangle error %f\n",worst_err);
CreateRegion(wrs.f);// CreateRegion changes wr->r
// reset state variables
ave_error=-1;
ave_var=-1;
err=0.0;
changed=0;
}
}
for(ri = regions.begin(); ri != regions.end(); )
if((*ri).isd)
ri = regions.erase(ri);
else
++ri;
for(ri = regions.begin(); ri != regions.end(); ++ri)
{
candi.clear();
(*ri).Refit(); // fit a plane to the region
Restart(*ri); // clear stuff in the region, move the seed to the best fitting to the plabne
Candidates(*ri,candi); // take the (three) faces candidatees
PushHeap(candi,(*ri)); // put the faces on to the heap
}
return true;
}
void Restart(RegionType &r){
if(!r.face.empty()){
r.size=0;
float b_err = r.Evaluate(*(*r.face.begin())),err;
FaceType* b_face =(*r.face.begin());
typename RegionType::FaceIterator fi;
for( fi = r.face.begin(); fi != r.face.end(); ++fi)
{
err = r.Evaluate(**fi);
if(err < b_err)
{
b_err = err;
b_face = *fi;
}
}
for( fi = r.face.begin(); fi != r.face.end(); ++fi) attr_r[(*fi)] = NULL;
r.face.clear();
r.adj.clear();
AddFaceToRegion(r,b_face);
r.Refit();
}
}
void MakeCharts(){
#ifndef VCGLIB_REGION_GROWING
#define VCGLIB_REGION_GROWING
#include <list>
#include <vector>
#include <vcg/complex/allocate.h>
template <class FaceType>
struct FaceError{
FaceType * f;
float val;
FaceError(){};
FaceError(FaceType * _f,double _val):f(_f),val(_val){}
const bool operator <(const FaceError & o) const {return val < o.val;}
};
template<class MeshType>
struct Region{
Region():isd(false){}
typedef Region RegionType;
typedef typename MeshType MeshType;
typedef typename MeshType::FaceType FaceType;
typedef typename MeshType::FaceType::CoordType CoordType;
typedef typename MeshType::FaceType::ScalarType ScalarType;
typedef typename std::vector<typename MeshType::FaceType*>::iterator FaceIterator;
typedef typename std::list<Region*>::iterator AdjIterator;
typedef FaceError<FaceType> FaceError;
// adjacent regions
std::list<RegionType*> adj,nx_adj;
// some flag
bool isd;
// evaluate the gain if the triangle is added to the region
ScalarType Evaluate( FaceType & f);
// update the approximation error of the region
void UpdateError( );
// check if two regions are mergeable in one
// i.e. if they have the same planes and coincide i non extreme
ScalarType Mergeable( RegionType & tr);
// set the region as adjacent to this one
void Connect( RegionType * tr);
// compute the faces which are on the border
void ComputeOnBorder( std::vector<FaceType*> & onBorder);
// clean the list of adjacencies
void Clean();
// refit the plane
void Refit();
// keep the best % percentile
void CutOff( FaceType*f);
// restart from the best fitting face
void Restart();
void Decorate();
};
template < class RegionType>
class RegionGrower{
public:
RegionGrower():lastAdded(NULL),ave_error(-1),ave_var(-1),n_steps(0){}
typedef typename RegionType RegionType;
typedef typename RegionType::MeshType MeshType;
typedef typename RegionType::FaceType FaceType;
typedef typename FaceType::ScalarType ScalarType;
typedef typename std::list<RegionType> ::iterator TriRegIterator;
typedef typename std::list<RegionType*>::iterator AdjIterator;
typedef typename RegionType::FaceError FaceError;
std::list<RegionType> regions;
std::vector<RegionType*> workingset;
int n_faces,target_max_regions;
FaceType * lastAdded;
ScalarType ave_error // average error (over single regions' error)
,ave_var// average variance (over single regions' error)
,changed // faces that have changed from previous step ([0..1))
,err
,target_error; // taget error
FaceType * worst;
ScalarType worst_err ;
MeshType * m;
typename MeshType:: template PerFaceAttributeHandle<int*> attr_r;
typename MeshType:: template PerFaceAttributeHandle<int*> attr_r_old;
unsigned int n_steps;// number of steps done
struct CandiFace{
FaceType * f;
float val;
RegionType * r;
char inPlane; // a quale piano di r
CandiFace(){};
CandiFace(FaceType * _f,double _val,RegionType * _r):f(_f),val(_val),r(_r){}
const bool operator <(const CandiFace & o) const {return val < o.val;}
};
std::vector<CandiFace> facesheap;
std::vector<FaceError > faceserr;
struct ErrorEval {
void Add(const float & v){
if(!ns){
if(v < samples[i_min]) i_min = 0; else {++i_min;
if(v > samples[i_max]) i_max = 0;else ++i_max;
}
if(i_min == samples.size()) {i_min = 0; for(int i= 0; i < samples.size(); ++i) if(samples[i]<samples[i_min]) i_min = i; }
if(i_max == samples.size()) {i_max = 0; for(int i= 0; i < samples.size(); ++i) if(samples[i]>samples[i_max]) i_max = i; }
}
samples.pop_back();samples.push_front(v);
boxes.pop_back(); boxes.push_front(vcg::Point2f(samples[i_min],samples[i_max]));
++ns ;
}
float BoxOverlap(){
float maxsize = std::max( boxes.back()[1]-boxes.back()[0], (*boxes.begin())[1]-(*boxes.begin())[0]);
float overlap = std::max(0.f, std::min(boxes.back()[1],(*boxes.begin())[1])-std::max(boxes.back()[0],(*boxes.begin())[0]));
assert(overlap <= maxsize);
return (maxsize > 0.f)?overlap / maxsize:0.0;
}
float RelativeDecrease(){
if (ns<2) return std::numeric_limits<float>::max();
return (samples[0]<10e-22)?0.0:(samples[1]-samples[0])/samples[0];
}
void Init(int n ){
samples.clear();
boxes.clear();
for(int i = 0 ; i < n; ++i) samples.push_front(std::numeric_limits<float>::max());
for(int i = 0 ; i < n; ++i) boxes.push_front(vcg::Point2f(n,n-i));
i_max = i_min = 0;
ns = 0;
}
private:
int i_min,i_max; // index of min and max element in the queue
std::deque<float> samples;
std::deque<vcg::Point2f> boxes;
int ns;
};
ErrorEval erroreval;
// init
void Init(MeshType & mesh, int n_seeds,int max_regions, float max_err){
erroreval.Init(10);
m = &mesh;
vcg::tri::Allocator<MeshType>::CompactFaceVector(*m);
vcg::tri::UpdateTopology<MeshType>::FaceFace(*m);
float area = 0.f;
for(typename MeshType::FaceIterator fi = m->face.begin(); fi != m->face.end(); ++fi)
area += vcg::DoubleArea(*fi);
area/=2.f;
target_error = area*max_err*max_err;
target_max_regions = max_regions;
// tte an attibute that will store the address in ocme for the vertex
attr_r = vcg::tri::Allocator<MeshType>::template GetPerFaceAttribute<int*> (*m,"r");
if(!vcg::tri::Allocator<MeshType>::IsValidHandle(*m,attr_r))
attr_r = vcg::tri::Allocator<MeshType>::template AddPerFaceAttribute<int*> (*m,"r");
attr_r_old = vcg::tri::Allocator<MeshType>::template GetPerFaceAttribute<int*> (*m,"r_old");
if(!vcg::tri::Allocator<MeshType>::IsValidHandle(*m,attr_r_old))
attr_r_old = vcg::tri::Allocator<MeshType>::template AddPerFaceAttribute<int*> (*m,"r_old");
regions.clear();
for(int i = 0; i < m->face.size(); ++i){
attr_r[i] = NULL;
attr_r_old[i] = NULL;
if( (i%(m->fn/n_seeds))==0)
CreateRegion(&m->face[i]);
}
}
// add a region
void AddRegion(const RegionType & r){regions.push_back(r);}
// remove a region
void DeleteRegion(const typename std::list<RegionType>::iterator & ri){std::remove(ri);}
// initialize a region
void CreateRegion(FaceType * fi){
AddRegion(RegionType());
RegionType & tr =regions.back();
AddFaceToRegion(tr,fi);
tr.Refit();
tr.color = vcg::Color4b::Scatter(2000,(int)regions.size());
}
void AddFaceToRegion( RegionType & r, FaceType * f){
r.face.push_back(f);
attr_r[*f] = (int*) &r;
if(attr_r[*f]!=attr_r_old[*f]) ++r.changed;
attr_r_old[*f] = attr_r[*f];
++r.size;
}
void Merge(RegionType & r0,RegionType & r1){
assert(!r1.isd);
typename RegionType::FaceIterator fi;
AdjIterator ai;
for(fi = r1.face.begin();fi != r1.face.end(); ++fi)
AddFaceToRegion(r0,(*fi));
for(ai= r1.adj.begin(); ai != r1.adj.end();++ai)
if( !(*ai)->isd && (*ai)!=&r0)
r0.nx_adj.push_back(*ai);
r1.face.clear();
r1.isd = true;
r0.Refit();
}
void PushHeap(std::vector<FaceType*> & candi, RegionType & r){
typename std::vector<FaceType*>::iterator ci;
for(ci = candi.begin(); ci != candi.end(); ++ci)
{
facesheap.push_back(CandiFace( *ci,-r.Evaluate(*(*ci)), &r));
push_heap(facesheap.begin(),facesheap.end());
}
}
// the two regions are adjacent
void Connect(RegionType * r1,RegionType * r2){
assert(r1!=r2);
r1->Connect(r2);
r2->Connect(r1);
}
// for each region take the candidates and fill in facesheap
void Refill( ){
facesheap.clear();
typename std::list<RegionType>::iterator ri;
std::vector<FaceType*> candi;
for(ri = regions.begin(); ri != regions.end(); ++ri) if(!(*ri).isd)
{
candi.clear();
Candidates((*ri),candi);
PushHeap(candi,*ri);
}
std::make_heap(facesheap.begin(),facesheap.end());
}
void Candidates(RegionType & r, std::vector< typename RegionType::FaceType*> & c){
typename RegionType::FaceIterator fi;
for(fi = r.face.begin(); fi!= r.face.end(); ++fi)
for(int i = 0; i < 3; ++i)
if( ((*fi)->FFp(i) != (*fi) ) &&
(attr_r[(*fi)->FFp(i)] != (int*) &r) )
c.push_back((*fi)->FFp(i));
}
bool IsRelaxed(){
ScalarType _ave_error=0;
ScalarType _ave_var= 0;
ScalarType _changed = 0.0;
int nr=0;
typename std::list<RegionType>::iterator ri;
worst=NULL;;
worst_err = -1;
qDebug("working set size: %d\n",workingset.size());
for(ri = regions.begin(); ri != regions.end(); ++ri) if(!(*ri).isd){
++nr;
(*ri).UpdateError();
_ave_error+=(*ri).approx_err;
_ave_var+=(*ri).approx_var;
_changed+=(*ri).changed;
(*ri).changed=0;
if((*ri).worst.val*(*ri).size > worst_err){
worst = (*ri).worst.f;
worst_err = (*ri).worst.val*(*ri).size;
}
}
_ave_error/=nr;
_ave_var/=nr;
_changed/=n_faces;
erroreval.Add(_ave_error);
qDebug("Err:%f ov: %f-------",_ave_error,erroreval.BoxOverlap());
return (erroreval.BoxOverlap() > 0.5) || (erroreval.RelativeDecrease() < 0.1);
}
void GrowStepOnce(){
CandiFace cf;
typename std::list<RegionType>::iterator ri;
for(ri = regions.begin(); ri != regions.end(); ++ri) if(!(*ri).isd)
(*ri).Clean();
if(!facesheap.empty()){
std::vector<FaceType*> toAdd;
std::pop_heap(facesheap.begin(),facesheap.end());
cf = facesheap.back();
// qDebug("err:%f\n",cf.val);
facesheap.pop_back();
if (attr_r[*cf.f]==NULL){
lastAdded = cf.f;
AddFaceToRegion(*cf.r,cf.f); // adds to region
for(int i=0; i < 3;++i) // put the adjacent in the set of faces to possibly add
if( (attr_r[cf.f->FFp(i)] == NULL) )
toAdd.push_back(cf.f->FFp(i));
PushHeap(toAdd,*cf.r);
}
else
{
int * aa = attr_r[*cf.f] ;
if ( attr_r[*cf.f] != (int*)(cf.r) )
Connect((RegionType*)attr_r[*cf.f],(RegionType*)cf.r);
}
}
int h = (int)facesheap.size();
// qDebug("----> %d\n",h);
}
void GrowStep(){
CandiFace cf;
typename std::list<RegionType>::iterator ri;
n_steps++;
for(ri = regions.begin(); ri != regions.end(); ++ri) if(!(*ri).isd)
(*ri).Clean();
while(!facesheap.empty() ){
std::vector<FaceType*> toAdd;
std::pop_heap(facesheap.begin(),facesheap.end());
cf = facesheap.back();
//printf("err:%f\n",cf.val);
facesheap.pop_back();
if (attr_r[*cf.f]==NULL){
AddFaceToRegion( *cf.r,cf.f); // ads to region
lastAdded = &*cf.f;
for(int i=0; i < 3;++i) // put the adjacent in the set of faces to possibly add
if( attr_r[ *cf.f->FFp(i)] == NULL )
toAdd.push_back(cf.f->FFp(i));
else
if(attr_r[*cf.f->FFp(i)] != attr_r[*cf.f])
Connect((RegionType*)attr_r[*cf.f->FFp(i)],(RegionType*)cf.r);
PushHeap(toAdd,*cf.r);
}
else
{
if ( attr_r[*cf.f] != (int*)(cf.r) )
Connect((RegionType*)attr_r[*cf.f],(RegionType*)cf.r);
}
}
int h = (int) facesheap.size();
printf("----> %d\n",h);
}
unsigned int MergeStep(){
TriRegIterator tri;
unsigned int merged = 0;
typename RegionType::AdjIterator ai;
for(tri = regions.begin(); tri != regions.end(); ++tri)if(!(*tri).isd)
for(ai = (*tri).adj.begin(); ai != (*tri).adj.end(); ++ai) if(!(*ai)->isd)
if((*tri).Mergeable(*(*ai))){
Merge((*tri),*(*ai));
merged++;
}
for(tri = regions.begin(); tri != regions.end(); ++tri){
for(ai = (*tri).nx_adj.begin(); ai != (*tri).nx_adj.end();++ai)
if(!(*ai)->isd)
(*tri).adj.push_back(*ai);
(*tri).adj.sort();
(*tri).adj.unique();
}
return merged;
}
//void TeleportStep(){
// TriRegIterator tri;
// typename RegionType::AdjIterator ai;
// for(tri = regions.begin(); tri != regions.end(); ++tri)if(!(*tri).isd){
// std::vector<FaceType*> & onBorder
// ComputeOnBorder(onBorder);
// if(onBorder.empty
// }
//
//}
bool Restart(){
std::vector<FaceType*> candi;
TriRegIterator ri;
facesheap.clear();
if(IsRelaxed()){
if( (worst_err <= target_error) || (regions.size() >= target_max_regions))
return false;
else
{
erroreval.Init(10);
FaceError wrs;
wrs.f = worst;
wrs.val = worst_err;
printf("worst triangle error %f\n",worst_err);
CreateRegion(wrs.f);// CreateRegion changes wr->r
// reset state variables
ave_error=-1;
ave_var=-1;
err=0.0;
changed=0;
}
}
for(ri = regions.begin(); ri != regions.end(); )
if((*ri).isd)
ri = regions.erase(ri);
else
++ri;
for(ri = regions.begin(); ri != regions.end(); ++ri)
{
candi.clear();
(*ri).Refit(); // fit a plane to the region
Restart(*ri); // clear stuff in the region, move the seed to the best fitting to the plabne
Candidates(*ri,candi); // take the (three) faces candidatees
PushHeap(candi,(*ri)); // put the faces on to the heap
}
return true;
}
void Restart(RegionType &r){
if(!r.face.empty()){
r.size=0;
float b_err = r.Evaluate(*(*r.face.begin())),err;
FaceType* b_face =(*r.face.begin());
typename RegionType::FaceIterator fi;
for( fi = r.face.begin(); fi != r.face.end(); ++fi)
{
err = r.Evaluate(**fi);
if(err < b_err)
{
b_err = err;
b_face = *fi;
}
}
for( fi = r.face.begin(); fi != r.face.end(); ++fi) attr_r[(*fi)] = NULL;
r.face.clear();
r.adj.clear();
AddFaceToRegion(r,b_face);
r.Refit();
}
}
void MakeCharts(){
this->Refill();
while(this->Restart()){
//do{
@ -487,7 +487,7 @@ void GrowStepOnce(){
}
//while(this->MergeStep());
}
};
#endif
};
#endif

View File

@ -35,12 +35,7 @@ $Log: samplefilter.cpp,v $
#include "region_growing.h"
#include "planar_region.h"
#include <vcg/complex/trimesh/clean.h>
#include <vcg/complex/trimesh/allocate.h>
#include <vcg/complex/trimesh/update/position.h>
#include <vcg/complex/trimesh/update/normal.h>
#include <vcg/complex/trimesh/update/bounding.h>
#include<vcg/complex/trimesh/append.h>
#include<vcg/complex/append.h>
using namespace vcg;

File diff suppressed because it is too large Load Diff

View File

@ -1,470 +1,470 @@
/****************************************************************************
* MeshLab o o *
* A versatile mesh processing toolbox o o *
* _ O _ *
* Copyright(C) 2005 \/)\/ *
* 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 FILTERZIPPERING_H
#define FILTERZIPPERING_H
#include <QObject>
#include <common/interfaces.h>
#include <vcg/space/distance3.h>
#include <vcg/complex/trimesh/closest.h>
#include <vcg/space/index/grid_static_ptr.h>
#define SAMPLES_PER_EDGE 5 //modificare, length/epsilon
// Polyline (set of consecutive segments)
struct polyline {
std::vector< vcg::Segment3<CMeshO::ScalarType> > edges; //polyline edges
std::vector< std::pair<int, int> > verts;
};
//Auxiliar info for triangulation
struct aux_info {
std::vector< polyline > conn; //Close components (to be triangulated)
std::vector< polyline > trash; //Close components (to be deleted)
std::vector< polyline > border; //Segment intersecting components
float eps; //epsilon
//Add segment c to border
virtual bool AddToBorder( vcg::Segment3<CMeshO::ScalarType> c, std::pair<int, int> v ) {
/****Insert new segment****/
//Search for segment S having S.P0() == c.P1 or S.P1 == c.P0()
if ( v.first == 4013 && v.second == 4015 )
int stop = 3;
if ( v.first == v.second ) return false;
if ( c.Length() < eps ) {
c.P0() = c.P1();
v.first = v.second;
//if segment is too short (it's basically a point) check if it's one of the vertices
for ( size_t i = 0; i < trash.size(); i ++ ) {
for ( size_t j = 0; j < trash[i].edges.size(); j ++ ) { //Only one trash component
if ( vcg::Distance<float>( trash[i].edges[j].P0(), c.P0() ) < eps ) return false;
}
}
}
if ( v.first == 4013 && v.second == 4013 )
int stop = 3;
//check if c doesn't lie on existing edges
//if it does, split edge
for ( size_t i = 0; i < trash.size(); i ++ ) {
for ( size_t j = 0; j < trash[i].edges.size(); j ++ ) { //Only one trash component
vcg::Segment3<CMeshO::ScalarType> a, b;
a = trash[i].edges[j]; b = c;
float tx0 = (float) (b.P0().X() - a.P0().X())/(a.P1().X() - a.P0().X());
float ty0 = (float) (b.P0().Y() - a.P0().Y())/(a.P1().Y() - a.P0().Y());
float tz0 = (float) (b.P0().Z() - a.P0().Z())/(a.P1().Z() - a.P0().Z());
if ( (fabs(tx0 - ty0) < eps ) && (fabs(ty0 - tz0) < eps) ) {
float tx1 = (float) (b.P1().X() - a.P0().X())/(a.P1().X() - a.P0().X());
float ty1 = (float) (b.P1().Y() - a.P0().Y())/(a.P1().Y() - a.P0().Y());
float tz1 = (float) (b.P1().Z() - a.P0().Z())/(a.P1().Z() - a.P0().Z());
if ( (fabs(tx1 - ty1) < eps) && (fabs(ty1 - tz1) < eps) ) {
if ( (tx0 < 0.0f + eps) && (tx1 > 1.0f - eps) ) return false; //external
if ( (tx1 < 0.0f + eps) && (tx0 > 1.0f - eps) ) return false; //external
if ( (tx0 >= 0.0f + eps) && (tx0 <= 1.0f - eps) && (tx1 >= 0.0f + eps) && (tx1 <= 1.0f - eps) ) {
//double split
if ( tx0 > tx1 ) { c.Flip(); v = std::make_pair( v.second, v.first ); }
//insert new edges
trash[i].edges.insert( trash[i].edges.begin() + j + 1, vcg::Segment3<CMeshO::ScalarType>( trash[i].edges[j].P0(), c.P0() ) );
trash[i].verts.insert( trash[i].verts.begin() + j + 1, std::make_pair( trash[i].verts[j].first, v.first ) );
trash[i].edges.insert( trash[i].edges.begin() + j + 2, c );
trash[i].verts.insert( trash[i].verts.begin() + j + 2, v );
trash[i].edges.insert( trash[i].edges.begin() + j + 3, vcg::Segment3<CMeshO::ScalarType>( c.P1(), trash[i].edges[j].P1() ) );
trash[i].verts.insert( trash[i].verts.begin() + j + 3, std::make_pair( v.second, trash[i].verts[j].second ) );
//erase old one
trash[i].edges.erase( trash[i].edges.begin() + j );
trash[i].verts.erase( trash[i].verts.begin() + j );
return true;
}
if ( (tx0 >= 0.0f + eps) && (tx0 <= 1.0f - eps) ) {
//single split in P0
//insert new edges
trash[i].edges.insert( trash[i].edges.begin() + j + 1, vcg::Segment3<CMeshO::ScalarType>( trash[i].edges[j].P0(), c.P0() ) );
trash[i].verts.insert( trash[i].verts.begin() + j + 1, std::make_pair( trash[i].verts[j].first, v.first ) );
trash[i].edges.insert( trash[i].edges.begin() + j + 2, vcg::Segment3<CMeshO::ScalarType>( c.P0(), trash[i].edges[j].P1() ) );
trash[i].verts.insert( trash[i].verts.begin() + j + 2, std::make_pair( v.first, trash[i].verts[j].second ) );
//erase old one
trash[i].edges.erase( trash[i].edges.begin() + j );
trash[i].verts.erase( trash[i].verts.begin() + j );
return true;
}
if ( (tx1 >= 0.0f + eps) && (tx1 <= 1.0f - eps) ) {
//single split in P1
//insert new edges
trash[i].edges.insert( trash[i].edges.begin() + j + 1, vcg::Segment3<CMeshO::ScalarType>( trash[i].edges[j].P0(), c.P1() ) );
trash[i].verts.insert( trash[i].verts.begin() + j + 1, std::make_pair( trash[i].verts[j].first, v.second ) );
trash[i].edges.insert( trash[i].edges.begin() + j + 2, vcg::Segment3<CMeshO::ScalarType>( c.P1(), trash[i].edges[j].P1() ) );
trash[i].verts.insert( trash[i].verts.begin() + j + 2, std::make_pair( v.second, trash[i].verts[j].second ) );
//erase old one
trash[i].edges.erase( trash[i].edges.begin() + j );
trash[i].verts.erase( trash[i].verts.begin() + j );
return true;
}
}
}
}
}
bool found = false;
for ( unsigned int j = 0; j < border.size(); j ++ ) {
for ( size_t i = 0; i < border[j].verts.size() && !found; i ++ ) {
if ( border[j].verts[i].first == v.second ) { found = true; border[j].edges.insert( border[j].edges.begin() + i, c ); border[j].verts.insert( border[j].verts.begin() + i, v ); } //insert before i-th element
else
if ( border[j].verts[i].second == v.first ) { found = true; border[j].edges.insert( border[j].edges.begin() + i + 1, c ); border[j].verts.insert( border[j].verts.begin() + i + 1, v ); } //insert after i-th element
}
}
if (!found) { //Create a new polyline ad add it to the border list
polyline nwpoly; nwpoly.edges.push_back( c ); nwpoly.verts.push_back( v ); border.push_back( nwpoly );
} else {
//Merge consecutive polylines into a single one
for ( unsigned int j = 0; j < border.size(); j ++ )
for ( unsigned int i = j+1; i < border.size(); i ++ ) {
if ( border[j].verts.front().first == border[i].verts.back().second ) {
border[j].edges.insert( border[j].edges.begin(), border[i].edges.begin(), border[i].edges.end() );
border[j].verts.insert( border[j].verts.begin(), border[i].verts.begin(), border[i].verts.end() );
border.erase(border.begin() + i);
}
else if ( border[j].verts.back().second == border[i].verts.front().first ) {
border[j].edges.insert( border[j].edges.end(), border[i].edges.begin(), border[i].edges.end() );
border[j].verts.insert( border[j].verts.end(), border[i].verts.begin(), border[i].verts.end() );
border.erase(border.begin() + i);
}
}
}//end if (!found)
for ( size_t k = 0; k < border.size(); k ++) {
for ( size_t i = 0; i < trash.size(); i ++ ) {
for ( size_t j = 0; j < trash[i].verts.size(); j ++ ) { //Only one trash component
if ( trash[i].verts[j].first == border[k].verts.back().second ) {
trash[i].edges[j].P0() = border[k].edges.back().P1();
//trash[i].edges.erase( trash[i].edges.begin() + j ); trash[i].verts.erase( trash[i].verts.begin() + j )
} else
if ( trash[i].verts[j].first == border[k].verts.front().first ) {
trash[i].edges[j].P0() = border[k].edges.front().P0();
//trash[i].edges.erase( trash[i].edges.begin() + j ); trash[i].verts.erase( trash[i].verts.begin() + j )
}
}
}
}
return true;
}//end AddToBorder
// Add c.component
virtual void AddCComponent( polyline c ) {
conn.push_back(c);
}
// Add t.component
virtual void AddTComponent( polyline t ) {
trash.push_back(t);
}
//Set eps
virtual void SetEps( float e ) {
eps = e;
}
// Set initial t.component
virtual void Init( CMeshO::FaceType f, int a, int b, int c ) {
if (!trash.empty()) return;
polyline tri; tri.edges.push_back( vcg::Segment3<CMeshO::ScalarType>(f.P(0), f.P(1)) );
tri.edges.push_back( vcg::Segment3<CMeshO::ScalarType>(f.P(1), f.P(2)) );
tri.edges.push_back( vcg::Segment3<CMeshO::ScalarType>(f.P(2), f.P(0)) );
tri.verts.push_back( std::make_pair(a, b) );
tri.verts.push_back( std::make_pair(b, c) );
tri.verts.push_back( std::make_pair(c, a) );
AddTComponent( tri );
}
// Remove c.component
virtual void RemoveCComponent( int i ) {
conn.erase( conn.begin() + i );
}
// Remove t.component
virtual void RemoveTComponent( int i ) {
trash.erase( trash.begin() + i );
}
// Number of c.component
virtual int nCComponent( ) {
return conn.size();
}
// Number of t.component
virtual size_t nTComponent( ) {
return trash.size();
}
// Add vertex in original triangle
virtual bool addVertex( CMeshO::VertexPointer v, int v_index ) {
int cnt = 0; int split = -1;
for ( size_t i = 0; i < trash.size(); i ++ ) { //one component only
for ( size_t j = 0; j < trash[i].verts.size(); j ++ ) { //search for closest edge
if ( trash[i].verts[j].first == v_index ) return false;
}
for ( size_t j = 0; j < trash[i].edges.size(); j ++ ) { //search for closest edge
//if ( vcg::SquaredDistance<float>( trash[i].edges[j], v->P() ) <= eps ) {
float dist;
vcg::Point3f clos;
vcg::SegmentPointSquaredDistance<float>(trash[i].edges[j], v->P(),clos,dist);
if (dist <= eps ) {
cnt++; split = j;
}
}
}
if (!cnt) return false;
if ( cnt == 1 ) { //one edge only -> split the edge
vcg::Segment3<CMeshO::ScalarType> splitting_edge = trash[0].edges[split];
std::pair<int, int> splitting_edge_v = trash[0].verts[split];
trash[0].edges.erase(trash[0].edges.begin()+split); //remove edge
trash[0].verts.erase(trash[0].verts.begin()+split);
//replace edge using two new edges
trash[0].edges.insert(trash[0].edges.begin()+split, vcg::Segment3<CMeshO::ScalarType>( splitting_edge.P0(), v->P() ) );
trash[0].edges.insert(trash[0].edges.begin()+split+1, vcg::Segment3<CMeshO::ScalarType>( v->P(), splitting_edge.P1() ) );
trash[0].verts.insert(trash[0].verts.begin()+split, std::make_pair( splitting_edge_v.first, v_index ) );
trash[0].verts.insert(trash[0].verts.begin()+split+1, std::make_pair( v_index, splitting_edge_v.second ) );
}
if ( cnt == 2 ) { // search for closest vertex and copy vertex coords
for ( size_t i = 0; i < trash.size(); i ++ ) { //one component only
for ( size_t j = 0; j < trash[i].edges.size(); j ++ ) { //search for closest edge
if ( vcg::Distance<float>( trash[i].edges[j].P0(), v->P() ) <= eps ) {
v->P() = trash[i].edges[j].P0();
}
}
}
}
return true;
}
};//end struct
class compareFaceQuality {
public:
compareFaceQuality() { };
bool operator () (const std::pair<CMeshO::FacePointer,char> f1, const std::pair<CMeshO::FacePointer,char> f2) {
//quality f1 < quality f2 return true
return ( f1.first->Q() > f2.first->Q() );
}
};
class FilterZippering : public QObject, public MeshFilterInterface
{
Q_OBJECT
Q_INTERFACES(MeshFilterInterface)
typedef vcg::GridStaticPtr<CMeshO::FaceType, CMeshO::ScalarType > MeshFaceGrid;
typedef vcg::GridStaticPtr<CMeshO::VertexType, CMeshO::ScalarType > MeshVertGrid;
public:
//Different operations in different plugins
enum { FP_REDUNDANCY,
FP_ZIPPERING };
FilterZippering();
virtual QString filterName(FilterIDType filter) const;
virtual QString filterInfo(FilterIDType filter) const;
virtual void initParameterSet(QAction *,MeshDocument &/*m*/, RichParameterSet & /*parent*/);
int getRequirements(QAction *action);
virtual bool applyFilter(QAction *filter, MeshDocument &md, RichParameterSet & /*parent*/, vcg::CallBackPos * cb) ;
FilterClass getClass(QAction *a);
virtual int postCondition( QAction */*a*/ ) const { return MeshModel::MM_FACEFACETOPO|MeshModel::MM_VERTNORMAL; }
private:
template <class ScalarType>
ScalarType SquaredDistance( vcg::Segment3<ScalarType> &s, vcg::Point3<ScalarType> &p);
template <class ScalarType>
vcg::Point3<ScalarType> ClosestPoint( vcg::Segment3<ScalarType> &s, vcg::Point3<ScalarType> &p);
bool checkRedundancy( CMeshO::FacePointer f, //face
MeshModel *a, //mesh A
MeshFaceGrid &grid, //grid A
CMeshO::ScalarType max_dist ); //Max search distance
bool simpleCheckRedundancy( CMeshO::FacePointer f, //face
MeshModel *a, //mesh A
MeshFaceGrid &grid, //grid A
CMeshO::ScalarType max_dist,//Max search distance
bool test );
bool isBorderVert( CMeshO::FacePointer f, int i);
bool isOnBorder( CMeshO::CoordType point, CMeshO::FacePointer f );
bool isOnEdge( CMeshO::CoordType point, CMeshO::FacePointer f );
bool isAdjacent( CMeshO::FacePointer f1, CMeshO::FacePointer f2 );
int sharesVertex( CMeshO::FacePointer f1, CMeshO::FacePointer f2 );
void handleBorder( aux_info &info, //Auxiliar information for triangulatio
vcg::Point3<CMeshO::ScalarType> N, //face normal (useful for proiection)
std::vector<CMeshO::CoordType> &coords, //output coords
std::vector<int> &output ); //output v. pointers
polyline cutComponent( polyline comp, //Component to be cut
polyline border, //border
vcg::Matrix44<CMeshO::ScalarType> rot_mat ); //Rotation matrix
int searchComponent( aux_info &info, //Auxiliar info
vcg::Point3<CMeshO::ScalarType> P0, //Start border point
vcg::Point3<CMeshO::ScalarType> P1, //End border point
bool &conn );
bool findIntersection( CMeshO::FacePointer currentF, //face
vcg::Segment3<float> edge, //edge
int last_split, //last splitted edge
int &splitted_edge, //currently splitted edge
vcg::Point3<CMeshO::ScalarType> &hit ); //approximate intersection point
//init unsorted queue
bool Init_q( std::vector< std::pair<CMeshO::FacePointer,char> >& queue, //the queue
MeshModel* a, //mesh A
MeshModel* b, //mesh B
bool fullProcess ); //fullProcess flag
//init priority queue (overload)
bool Init_pq( std::priority_queue< std::pair<CMeshO::FacePointer,char>, std::vector< std::pair<CMeshO::FacePointer,char> >, compareFaceQuality >& queue, //the queue
MeshModel* a, //mesh A
MeshModel* b, //mesh B
bool fullProcess );
//select redundant face (normal method, unsorted queue)
int selectRedundant( std::vector< std::pair<CMeshO::FacePointer,char> >& queue, //queue
MeshModel* a, //mesh A
MeshModel* b, //mesh B
float epsilon ); //max search distance
//select redundant face (normal method, priority queue)
int selectRedundant_pq( std::priority_queue< std::pair<CMeshO::FacePointer,char>, std::vector< std::pair<CMeshO::FacePointer,char> >, compareFaceQuality >& queue, //the queue
MeshModel* a, //mesh A
MeshModel* b, //mesh B
float epsilon ); //max search distance
//refine border of a mesh, splitting faces having two border edges
int refineBorder( MeshModel* m );
//project face of B on the surface of A
void projectFace( CMeshO::FacePointer f, //pointer to the face that will be projected
MeshModel* a, //mesh A
MeshFaceGrid grid_a, //grid on A
float max_dist, //max dist search
std::map< CMeshO::FacePointer, aux_info >& map_info, //map with auxiliar information
std::vector< CMeshO::FacePointer >& tbt_faces, //vector to-be-triangulated faces
std::vector< CMeshO::FacePointer >& tbr_faces, //vector to-be-removed faces
std::vector< int >& verts ); //vector of indices
//case 01: vertices of border edge project on the same face
void handleBorderEdgeSF ( std::pair< int, int >& current_edge, //current border edge
MeshModel* a, //mesh A
CMeshO::FacePointer startF, //face where first vertex lies
CMeshO::FacePointer endF, //face where second vertex lies
CMeshO::FacePointer splittingF, //splitting face
std::map< CMeshO::FacePointer, aux_info >& map_info, //map with auxiliar information
std::vector < std::pair< int, int > >& stack, //stack containing border edges
std::vector< int >& verts ); //vector of indices
//case 02: vertices of border edge project on adjacent faces
void handleBorderEdgeAF ( std::pair< int, int >& current_edge, //current border edge
MeshModel* a, //mesh A
CMeshO::FacePointer startF, //face where first vertex lies
CMeshO::FacePointer endF, //face where second vertex lies
CMeshO::FacePointer splittingF, //splitting face
std::map< CMeshO::FacePointer, aux_info >& map_info, //map with auxiliar information
std::vector < std::pair< int, int > >& stack, //stack containing border edges
std::vector< int >& verts ); //vector of indices
//case 03: vertices of border edge project on non-adjacent faces
void handleBorderEdgeNF ( std::pair< int, int >& current_edge, //current border edge
MeshModel* a, //mesh A
CMeshO::FacePointer startF, //face where first vertex lies
CMeshO::FacePointer endF, //face where second vertex lies
CMeshO::FacePointer splittingF, //splitting face
std::map< CMeshO::FacePointer, aux_info >& map_info, //map with auxiliar information
std::vector < std::pair< int, int > >& stack, //stack containing border edges
std::vector< int >& verts ); //vector of indices
//case 04: both vertices of current_edge project on another border edge
//return true if the whole current_edge project on border edge
bool handleBorderEdgeBB ( std::pair< int, int >& current_edge, //current border edge
MeshModel* a, //mesh A
MeshFaceGrid grid_a, //grid on A (needed for sampling)
float max_dist, //max search dist (needed for sampling)
vcg::Point3<CMeshO::ScalarType> closestStart, //closest point on startF
vcg::Point3<CMeshO::ScalarType> closestEnd, //closest point on endF
CMeshO::FacePointer startF, //face where first vertex lies
CMeshO::FacePointer endF, //face where second vertex lies
CMeshO::FacePointer splittingF, //splitting face
std::map< CMeshO::FacePointer, aux_info >& map_info, //map with auxiliar information
std::vector < std::pair< int, int > >& stack, //stack containing border edges
std::vector< int >& verts ); //vector of indices
//case 04: both vertices of current_edge project on another border edge
//return true if the whole current_edge project on border edge
bool handleBorderEdgeBB ( std::pair< int, int >& current_edge, //current border edge
MeshModel* a, //mesh A
MeshFaceGrid grid_a, //grid on A (needed for sampling)
float max_dist, //max search dist (needed for sampling)
CMeshO::FacePointer startF, //face where first vertex lies
CMeshO::FacePointer endF, //face where second vertex lies
CMeshO::FacePointer splittingF, //splitting face
std::map< CMeshO::FacePointer, aux_info >& map_info, //map with auxiliar information
std::vector < std::pair< int, int > >& stack, //stack containing border edges
std::vector< int >& verts ); //vector of indices
//case 05: one of the vertices doesn't project on the surface of the mesh
void handleBorderEdgeOB ( std::pair< int, int >& current_edge, //current border edge
int direction, //splitting direction (1 from start to end, 0 from end to start)
MeshModel* a, //mesh A
MeshFaceGrid grid_a, //grid on A (needed for sampling)
float max_dist, //max search dist (needed for sampling)
CMeshO::FacePointer startF, //face where first vertex lies
CMeshO::FacePointer endF, //face where second vertex lies
CMeshO::FacePointer splittingF, //splitting face
std::map< CMeshO::FacePointer, aux_info >& map_info, //map with auxiliar information
std::vector < std::pair< int, int > >& stack, //stack containing border edges
std::vector< CMeshO::FacePointer >& tbt_faces, //stack containing pointers to face that wille be retriangulated
std::vector< int >& verts ); //vector of indices
int preProcess ( std::vector< std::pair<CMeshO::FacePointer,char> >& queue, //queue
MeshModel* a,
MeshModel* b,
MeshFaceGrid grid_a, //grid on A
MeshFaceGrid grid_b, //grid on A
float max_dist ); //max dist search
int preProcess_pq ( std::priority_queue< std::pair<CMeshO::FacePointer,char>, std::vector< std::pair<CMeshO::FacePointer,char> >, compareFaceQuality >& queue, //the queue
MeshModel* a,
MeshModel* b,
MeshFaceGrid grid_a, //grid on A
MeshFaceGrid grid_b, //grid on A
float max_dist ); //max dist search
float eps;
int dbg_cnt;
};
#endif
/****************************************************************************
* MeshLab o o *
* A versatile mesh processing toolbox o o *
* _ O _ *
* Copyright(C) 2005 \/)\/ *
* 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 FILTERZIPPERING_H
#define FILTERZIPPERING_H
#include <QObject>
#include <common/interfaces.h>
#include <vcg/space/distance3.h>
#include <vcg/complex/algorithms/closest.h>
#include <vcg/space/index/grid_static_ptr.h>
#define SAMPLES_PER_EDGE 5 //modificare, length/epsilon
// Polyline (set of consecutive segments)
struct polyline {
std::vector< vcg::Segment3<CMeshO::ScalarType> > edges; //polyline edges
std::vector< std::pair<int, int> > verts;
};
//Auxiliar info for triangulation
struct aux_info {
std::vector< polyline > conn; //Close components (to be triangulated)
std::vector< polyline > trash; //Close components (to be deleted)
std::vector< polyline > border; //Segment intersecting components
float eps; //epsilon
//Add segment c to border
virtual bool AddToBorder( vcg::Segment3<CMeshO::ScalarType> c, std::pair<int, int> v ) {
/****Insert new segment****/
//Search for segment S having S.P0() == c.P1 or S.P1 == c.P0()
if ( v.first == 4013 && v.second == 4015 )
int stop = 3;
if ( v.first == v.second ) return false;
if ( c.Length() < eps ) {
c.P0() = c.P1();
v.first = v.second;
//if segment is too short (it's basically a point) check if it's one of the vertices
for ( size_t i = 0; i < trash.size(); i ++ ) {
for ( size_t j = 0; j < trash[i].edges.size(); j ++ ) { //Only one trash component
if ( vcg::Distance<float>( trash[i].edges[j].P0(), c.P0() ) < eps ) return false;
}
}
}
if ( v.first == 4013 && v.second == 4013 )
int stop = 3;
//check if c doesn't lie on existing edges
//if it does, split edge
for ( size_t i = 0; i < trash.size(); i ++ ) {
for ( size_t j = 0; j < trash[i].edges.size(); j ++ ) { //Only one trash component
vcg::Segment3<CMeshO::ScalarType> a, b;
a = trash[i].edges[j]; b = c;
float tx0 = (float) (b.P0().X() - a.P0().X())/(a.P1().X() - a.P0().X());
float ty0 = (float) (b.P0().Y() - a.P0().Y())/(a.P1().Y() - a.P0().Y());
float tz0 = (float) (b.P0().Z() - a.P0().Z())/(a.P1().Z() - a.P0().Z());
if ( (fabs(tx0 - ty0) < eps ) && (fabs(ty0 - tz0) < eps) ) {
float tx1 = (float) (b.P1().X() - a.P0().X())/(a.P1().X() - a.P0().X());
float ty1 = (float) (b.P1().Y() - a.P0().Y())/(a.P1().Y() - a.P0().Y());
float tz1 = (float) (b.P1().Z() - a.P0().Z())/(a.P1().Z() - a.P0().Z());
if ( (fabs(tx1 - ty1) < eps) && (fabs(ty1 - tz1) < eps) ) {
if ( (tx0 < 0.0f + eps) && (tx1 > 1.0f - eps) ) return false; //external
if ( (tx1 < 0.0f + eps) && (tx0 > 1.0f - eps) ) return false; //external
if ( (tx0 >= 0.0f + eps) && (tx0 <= 1.0f - eps) && (tx1 >= 0.0f + eps) && (tx1 <= 1.0f - eps) ) {
//double split
if ( tx0 > tx1 ) { c.Flip(); v = std::make_pair( v.second, v.first ); }
//insert new edges
trash[i].edges.insert( trash[i].edges.begin() + j + 1, vcg::Segment3<CMeshO::ScalarType>( trash[i].edges[j].P0(), c.P0() ) );
trash[i].verts.insert( trash[i].verts.begin() + j + 1, std::make_pair( trash[i].verts[j].first, v.first ) );
trash[i].edges.insert( trash[i].edges.begin() + j + 2, c );
trash[i].verts.insert( trash[i].verts.begin() + j + 2, v );
trash[i].edges.insert( trash[i].edges.begin() + j + 3, vcg::Segment3<CMeshO::ScalarType>( c.P1(), trash[i].edges[j].P1() ) );
trash[i].verts.insert( trash[i].verts.begin() + j + 3, std::make_pair( v.second, trash[i].verts[j].second ) );
//erase old one
trash[i].edges.erase( trash[i].edges.begin() + j );
trash[i].verts.erase( trash[i].verts.begin() + j );
return true;
}
if ( (tx0 >= 0.0f + eps) && (tx0 <= 1.0f - eps) ) {
//single split in P0
//insert new edges
trash[i].edges.insert( trash[i].edges.begin() + j + 1, vcg::Segment3<CMeshO::ScalarType>( trash[i].edges[j].P0(), c.P0() ) );
trash[i].verts.insert( trash[i].verts.begin() + j + 1, std::make_pair( trash[i].verts[j].first, v.first ) );
trash[i].edges.insert( trash[i].edges.begin() + j + 2, vcg::Segment3<CMeshO::ScalarType>( c.P0(), trash[i].edges[j].P1() ) );
trash[i].verts.insert( trash[i].verts.begin() + j + 2, std::make_pair( v.first, trash[i].verts[j].second ) );
//erase old one
trash[i].edges.erase( trash[i].edges.begin() + j );
trash[i].verts.erase( trash[i].verts.begin() + j );
return true;
}
if ( (tx1 >= 0.0f + eps) && (tx1 <= 1.0f - eps) ) {
//single split in P1
//insert new edges
trash[i].edges.insert( trash[i].edges.begin() + j + 1, vcg::Segment3<CMeshO::ScalarType>( trash[i].edges[j].P0(), c.P1() ) );
trash[i].verts.insert( trash[i].verts.begin() + j + 1, std::make_pair( trash[i].verts[j].first, v.second ) );
trash[i].edges.insert( trash[i].edges.begin() + j + 2, vcg::Segment3<CMeshO::ScalarType>( c.P1(), trash[i].edges[j].P1() ) );
trash[i].verts.insert( trash[i].verts.begin() + j + 2, std::make_pair( v.second, trash[i].verts[j].second ) );
//erase old one
trash[i].edges.erase( trash[i].edges.begin() + j );
trash[i].verts.erase( trash[i].verts.begin() + j );
return true;
}
}
}
}
}
bool found = false;
for ( unsigned int j = 0; j < border.size(); j ++ ) {
for ( size_t i = 0; i < border[j].verts.size() && !found; i ++ ) {
if ( border[j].verts[i].first == v.second ) { found = true; border[j].edges.insert( border[j].edges.begin() + i, c ); border[j].verts.insert( border[j].verts.begin() + i, v ); } //insert before i-th element
else
if ( border[j].verts[i].second == v.first ) { found = true; border[j].edges.insert( border[j].edges.begin() + i + 1, c ); border[j].verts.insert( border[j].verts.begin() + i + 1, v ); } //insert after i-th element
}
}
if (!found) { //Create a new polyline ad add it to the border list
polyline nwpoly; nwpoly.edges.push_back( c ); nwpoly.verts.push_back( v ); border.push_back( nwpoly );
} else {
//Merge consecutive polylines into a single one
for ( unsigned int j = 0; j < border.size(); j ++ )
for ( unsigned int i = j+1; i < border.size(); i ++ ) {
if ( border[j].verts.front().first == border[i].verts.back().second ) {
border[j].edges.insert( border[j].edges.begin(), border[i].edges.begin(), border[i].edges.end() );
border[j].verts.insert( border[j].verts.begin(), border[i].verts.begin(), border[i].verts.end() );
border.erase(border.begin() + i);
}
else if ( border[j].verts.back().second == border[i].verts.front().first ) {
border[j].edges.insert( border[j].edges.end(), border[i].edges.begin(), border[i].edges.end() );
border[j].verts.insert( border[j].verts.end(), border[i].verts.begin(), border[i].verts.end() );
border.erase(border.begin() + i);
}
}
}//end if (!found)
for ( size_t k = 0; k < border.size(); k ++) {
for ( size_t i = 0; i < trash.size(); i ++ ) {
for ( size_t j = 0; j < trash[i].verts.size(); j ++ ) { //Only one trash component
if ( trash[i].verts[j].first == border[k].verts.back().second ) {
trash[i].edges[j].P0() = border[k].edges.back().P1();
//trash[i].edges.erase( trash[i].edges.begin() + j ); trash[i].verts.erase( trash[i].verts.begin() + j )
} else
if ( trash[i].verts[j].first == border[k].verts.front().first ) {
trash[i].edges[j].P0() = border[k].edges.front().P0();
//trash[i].edges.erase( trash[i].edges.begin() + j ); trash[i].verts.erase( trash[i].verts.begin() + j )
}
}
}
}
return true;
}//end AddToBorder
// Add c.component
virtual void AddCComponent( polyline c ) {
conn.push_back(c);
}
// Add t.component
virtual void AddTComponent( polyline t ) {
trash.push_back(t);
}
//Set eps
virtual void SetEps( float e ) {
eps = e;
}
// Set initial t.component
virtual void Init( CMeshO::FaceType f, int a, int b, int c ) {
if (!trash.empty()) return;
polyline tri; tri.edges.push_back( vcg::Segment3<CMeshO::ScalarType>(f.P(0), f.P(1)) );
tri.edges.push_back( vcg::Segment3<CMeshO::ScalarType>(f.P(1), f.P(2)) );
tri.edges.push_back( vcg::Segment3<CMeshO::ScalarType>(f.P(2), f.P(0)) );
tri.verts.push_back( std::make_pair(a, b) );
tri.verts.push_back( std::make_pair(b, c) );
tri.verts.push_back( std::make_pair(c, a) );
AddTComponent( tri );
}
// Remove c.component
virtual void RemoveCComponent( int i ) {
conn.erase( conn.begin() + i );
}
// Remove t.component
virtual void RemoveTComponent( int i ) {
trash.erase( trash.begin() + i );
}
// Number of c.component
virtual int nCComponent( ) {
return conn.size();
}
// Number of t.component
virtual size_t nTComponent( ) {
return trash.size();
}
// Add vertex in original triangle
virtual bool addVertex( CMeshO::VertexPointer v, int v_index ) {
int cnt = 0; int split = -1;
for ( size_t i = 0; i < trash.size(); i ++ ) { //one component only
for ( size_t j = 0; j < trash[i].verts.size(); j ++ ) { //search for closest edge
if ( trash[i].verts[j].first == v_index ) return false;
}
for ( size_t j = 0; j < trash[i].edges.size(); j ++ ) { //search for closest edge
//if ( vcg::SquaredDistance<float>( trash[i].edges[j], v->P() ) <= eps ) {
float dist;
vcg::Point3f clos;
vcg::SegmentPointSquaredDistance<float>(trash[i].edges[j], v->P(),clos,dist);
if (dist <= eps ) {
cnt++; split = j;
}
}
}
if (!cnt) return false;
if ( cnt == 1 ) { //one edge only -> split the edge
vcg::Segment3<CMeshO::ScalarType> splitting_edge = trash[0].edges[split];
std::pair<int, int> splitting_edge_v = trash[0].verts[split];
trash[0].edges.erase(trash[0].edges.begin()+split); //remove edge
trash[0].verts.erase(trash[0].verts.begin()+split);
//replace edge using two new edges
trash[0].edges.insert(trash[0].edges.begin()+split, vcg::Segment3<CMeshO::ScalarType>( splitting_edge.P0(), v->P() ) );
trash[0].edges.insert(trash[0].edges.begin()+split+1, vcg::Segment3<CMeshO::ScalarType>( v->P(), splitting_edge.P1() ) );
trash[0].verts.insert(trash[0].verts.begin()+split, std::make_pair( splitting_edge_v.first, v_index ) );
trash[0].verts.insert(trash[0].verts.begin()+split+1, std::make_pair( v_index, splitting_edge_v.second ) );
}
if ( cnt == 2 ) { // search for closest vertex and copy vertex coords
for ( size_t i = 0; i < trash.size(); i ++ ) { //one component only
for ( size_t j = 0; j < trash[i].edges.size(); j ++ ) { //search for closest edge
if ( vcg::Distance<float>( trash[i].edges[j].P0(), v->P() ) <= eps ) {
v->P() = trash[i].edges[j].P0();
}
}
}
}
return true;
}
};//end struct
class compareFaceQuality {
public:
compareFaceQuality() { };
bool operator () (const std::pair<CMeshO::FacePointer,char> f1, const std::pair<CMeshO::FacePointer,char> f2) {
//quality f1 < quality f2 return true
return ( f1.first->Q() > f2.first->Q() );
}
};
class FilterZippering : public QObject, public MeshFilterInterface
{
Q_OBJECT
Q_INTERFACES(MeshFilterInterface)
typedef vcg::GridStaticPtr<CMeshO::FaceType, CMeshO::ScalarType > MeshFaceGrid;
typedef vcg::GridStaticPtr<CMeshO::VertexType, CMeshO::ScalarType > MeshVertGrid;
public:
//Different operations in different plugins
enum { FP_REDUNDANCY,
FP_ZIPPERING };
FilterZippering();
virtual QString filterName(FilterIDType filter) const;
virtual QString filterInfo(FilterIDType filter) const;
virtual void initParameterSet(QAction *,MeshDocument &/*m*/, RichParameterSet & /*parent*/);
int getRequirements(QAction *action);
virtual bool applyFilter(QAction *filter, MeshDocument &md, RichParameterSet & /*parent*/, vcg::CallBackPos * cb) ;
FilterClass getClass(QAction *a);
virtual int postCondition( QAction */*a*/ ) const { return MeshModel::MM_FACEFACETOPO|MeshModel::MM_VERTNORMAL; }
private:
template <class ScalarType>
ScalarType SquaredDistance( vcg::Segment3<ScalarType> &s, vcg::Point3<ScalarType> &p);
template <class ScalarType>
vcg::Point3<ScalarType> ClosestPoint( vcg::Segment3<ScalarType> &s, vcg::Point3<ScalarType> &p);
bool checkRedundancy( CMeshO::FacePointer f, //face
MeshModel *a, //mesh A
MeshFaceGrid &grid, //grid A
CMeshO::ScalarType max_dist ); //Max search distance
bool simpleCheckRedundancy( CMeshO::FacePointer f, //face
MeshModel *a, //mesh A
MeshFaceGrid &grid, //grid A
CMeshO::ScalarType max_dist,//Max search distance
bool test );
bool isBorderVert( CMeshO::FacePointer f, int i);
bool isOnBorder( CMeshO::CoordType point, CMeshO::FacePointer f );
bool isOnEdge( CMeshO::CoordType point, CMeshO::FacePointer f );
bool isAdjacent( CMeshO::FacePointer f1, CMeshO::FacePointer f2 );
int sharesVertex( CMeshO::FacePointer f1, CMeshO::FacePointer f2 );
void handleBorder( aux_info &info, //Auxiliar information for triangulatio
vcg::Point3<CMeshO::ScalarType> N, //face normal (useful for proiection)
std::vector<CMeshO::CoordType> &coords, //output coords
std::vector<int> &output ); //output v. pointers
polyline cutComponent( polyline comp, //Component to be cut
polyline border, //border
vcg::Matrix44<CMeshO::ScalarType> rot_mat ); //Rotation matrix
int searchComponent( aux_info &info, //Auxiliar info
vcg::Point3<CMeshO::ScalarType> P0, //Start border point
vcg::Point3<CMeshO::ScalarType> P1, //End border point
bool &conn );
bool findIntersection( CMeshO::FacePointer currentF, //face
vcg::Segment3<float> edge, //edge
int last_split, //last splitted edge
int &splitted_edge, //currently splitted edge
vcg::Point3<CMeshO::ScalarType> &hit ); //approximate intersection point
//init unsorted queue
bool Init_q( std::vector< std::pair<CMeshO::FacePointer,char> >& queue, //the queue
MeshModel* a, //mesh A
MeshModel* b, //mesh B
bool fullProcess ); //fullProcess flag
//init priority queue (overload)
bool Init_pq( std::priority_queue< std::pair<CMeshO::FacePointer,char>, std::vector< std::pair<CMeshO::FacePointer,char> >, compareFaceQuality >& queue, //the queue
MeshModel* a, //mesh A
MeshModel* b, //mesh B
bool fullProcess );
//select redundant face (normal method, unsorted queue)
int selectRedundant( std::vector< std::pair<CMeshO::FacePointer,char> >& queue, //queue
MeshModel* a, //mesh A
MeshModel* b, //mesh B
float epsilon ); //max search distance
//select redundant face (normal method, priority queue)
int selectRedundant_pq( std::priority_queue< std::pair<CMeshO::FacePointer,char>, std::vector< std::pair<CMeshO::FacePointer,char> >, compareFaceQuality >& queue, //the queue
MeshModel* a, //mesh A
MeshModel* b, //mesh B
float epsilon ); //max search distance
//refine border of a mesh, splitting faces having two border edges
int refineBorder( MeshModel* m );
//project face of B on the surface of A
void projectFace( CMeshO::FacePointer f, //pointer to the face that will be projected
MeshModel* a, //mesh A
MeshFaceGrid grid_a, //grid on A
float max_dist, //max dist search
std::map< CMeshO::FacePointer, aux_info >& map_info, //map with auxiliar information
std::vector< CMeshO::FacePointer >& tbt_faces, //vector to-be-triangulated faces
std::vector< CMeshO::FacePointer >& tbr_faces, //vector to-be-removed faces
std::vector< int >& verts ); //vector of indices
//case 01: vertices of border edge project on the same face
void handleBorderEdgeSF ( std::pair< int, int >& current_edge, //current border edge
MeshModel* a, //mesh A
CMeshO::FacePointer startF, //face where first vertex lies
CMeshO::FacePointer endF, //face where second vertex lies
CMeshO::FacePointer splittingF, //splitting face
std::map< CMeshO::FacePointer, aux_info >& map_info, //map with auxiliar information
std::vector < std::pair< int, int > >& stack, //stack containing border edges
std::vector< int >& verts ); //vector of indices
//case 02: vertices of border edge project on adjacent faces
void handleBorderEdgeAF ( std::pair< int, int >& current_edge, //current border edge
MeshModel* a, //mesh A
CMeshO::FacePointer startF, //face where first vertex lies
CMeshO::FacePointer endF, //face where second vertex lies
CMeshO::FacePointer splittingF, //splitting face
std::map< CMeshO::FacePointer, aux_info >& map_info, //map with auxiliar information
std::vector < std::pair< int, int > >& stack, //stack containing border edges
std::vector< int >& verts ); //vector of indices
//case 03: vertices of border edge project on non-adjacent faces
void handleBorderEdgeNF ( std::pair< int, int >& current_edge, //current border edge
MeshModel* a, //mesh A
CMeshO::FacePointer startF, //face where first vertex lies
CMeshO::FacePointer endF, //face where second vertex lies
CMeshO::FacePointer splittingF, //splitting face
std::map< CMeshO::FacePointer, aux_info >& map_info, //map with auxiliar information
std::vector < std::pair< int, int > >& stack, //stack containing border edges
std::vector< int >& verts ); //vector of indices
//case 04: both vertices of current_edge project on another border edge
//return true if the whole current_edge project on border edge
bool handleBorderEdgeBB ( std::pair< int, int >& current_edge, //current border edge
MeshModel* a, //mesh A
MeshFaceGrid grid_a, //grid on A (needed for sampling)
float max_dist, //max search dist (needed for sampling)
vcg::Point3<CMeshO::ScalarType> closestStart, //closest point on startF
vcg::Point3<CMeshO::ScalarType> closestEnd, //closest point on endF
CMeshO::FacePointer startF, //face where first vertex lies
CMeshO::FacePointer endF, //face where second vertex lies
CMeshO::FacePointer splittingF, //splitting face
std::map< CMeshO::FacePointer, aux_info >& map_info, //map with auxiliar information
std::vector < std::pair< int, int > >& stack, //stack containing border edges
std::vector< int >& verts ); //vector of indices
//case 04: both vertices of current_edge project on another border edge
//return true if the whole current_edge project on border edge
bool handleBorderEdgeBB ( std::pair< int, int >& current_edge, //current border edge
MeshModel* a, //mesh A
MeshFaceGrid grid_a, //grid on A (needed for sampling)
float max_dist, //max search dist (needed for sampling)
CMeshO::FacePointer startF, //face where first vertex lies
CMeshO::FacePointer endF, //face where second vertex lies
CMeshO::FacePointer splittingF, //splitting face
std::map< CMeshO::FacePointer, aux_info >& map_info, //map with auxiliar information
std::vector < std::pair< int, int > >& stack, //stack containing border edges
std::vector< int >& verts ); //vector of indices
//case 05: one of the vertices doesn't project on the surface of the mesh
void handleBorderEdgeOB ( std::pair< int, int >& current_edge, //current border edge
int direction, //splitting direction (1 from start to end, 0 from end to start)
MeshModel* a, //mesh A
MeshFaceGrid grid_a, //grid on A (needed for sampling)
float max_dist, //max search dist (needed for sampling)
CMeshO::FacePointer startF, //face where first vertex lies
CMeshO::FacePointer endF, //face where second vertex lies
CMeshO::FacePointer splittingF, //splitting face
std::map< CMeshO::FacePointer, aux_info >& map_info, //map with auxiliar information
std::vector < std::pair< int, int > >& stack, //stack containing border edges
std::vector< CMeshO::FacePointer >& tbt_faces, //stack containing pointers to face that wille be retriangulated
std::vector< int >& verts ); //vector of indices
int preProcess ( std::vector< std::pair<CMeshO::FacePointer,char> >& queue, //queue
MeshModel* a,
MeshModel* b,
MeshFaceGrid grid_a, //grid on A
MeshFaceGrid grid_b, //grid on A
float max_dist ); //max dist search
int preProcess_pq ( std::priority_queue< std::pair<CMeshO::FacePointer,char>, std::vector< std::pair<CMeshO::FacePointer,char> >, compareFaceQuality >& queue, //the queue
MeshModel* a,
MeshModel* b,
MeshFaceGrid grid_a, //grid on A
MeshFaceGrid grid_b, //grid on A
float max_dist ); //max dist search
float eps;
int dbg_cnt;
};
#endif