The filter now creates two new layers containing the sliced parts.

Works only on two-manifold meshes with only 1 slicing plane.
This commit is contained in:
Paolo Cignoni cignoni 2008-12-14 13:52:49 +00:00
parent 704a3893f2
commit 7903dac876
3 changed files with 105 additions and 31 deletions

View File

@ -22,15 +22,22 @@
****************************************************************************/
#include "filter_slice.h"
//#include <stdlib.h>
#include <vcg/complex/intersection.h>
#include <vcg/complex/edgemesh/update/bounding.h>
#include <vcg/complex/trimesh/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 <algorithm>
#include "filter_slice_functors.h"
//#include <wrap/gl/glu_tesselator.h>
#include <wrap/gl/glu_tesselator.h>
#include <vcg/complex/trimesh/allocate.h>
#include <vcg/space/planar_polygon_tessellation.h>
using namespace std;
using namespace vcg;
@ -91,7 +98,7 @@ void ExtraFilter_SlicePlugin::initParameterSet(QAction *filter, MeshModel &m, Fi
parlst.addEnum ("planeAxis", 0, metrics, tr("Axis"), tr("The Slicing plane will be done perpendicular to the axis"));
parlst.addFloat ("planeOffset", 0.0, "Cross plane offset", "Specify an offset of the cross-plane. The offset corresponds to the distance between the center of the object and the point where the plan crosses it. By default (Cross plane offset == 0), the plane crosses the center of the object, so the offset can be positive or negetive");
// Origin=0, BBox min=1, BBox center=2
parlst.addEnum ("relativeTo",0,QStringList()<<"Origin"<<"Bounding box min"<<"Bounding box Center","plane reference","Specify the reference from which the planes are shifted");
parlst.addEnum ("relativeTo",0,QStringList()<<"Bounding box Center"<<"Bounding box min"<<"Origin","plane reference","Specify the reference from which the planes are shifted");
//parlst.addBool ("absOffset",false,"Absolute offset", "if true the above offset is absolute is relative to the origin of the coordinate system, if false the offset is relative to the center of the bbox.");
parlst.addAbsPerc("planeDist", 0.0,0,m.cm.bbox.Diag(), "Distance between planes", "Step value between each plane for automatically generating cross-sections. Should be used with the bool selection above.");
parlst.addInt ("planeNum", 1, "Number of Planes", "Step value between each plane for automatically generating cross-sections. Should be used with the bool selection above.");
@ -138,42 +145,50 @@ bool ExtraFilter_SlicePlugin::applyFilter(QAction *filter, MeshDocument &m, Filt
pr.scale = 2.0/m.mm()->cm.bbox.Diag();
pr.lineWidthPt=200;
vector<MyEdgeMesh*> ev;
MeshModel *orig=m.mm();
m.mm()->visible=false;
for(int i=0;i<planeNum;++i)
{
//if(absOffset==false) planeCenter = m.cm.bbox.Center() + planeAxis*planeOffset*(m.cm.bbox.Diag()/2.0);
// else planeCenter = Point3f(0,0,0) + planeAxis*planeOffset;
switch(reference)
{
case 0: planeCenter = planeAxis*planeOffset; //origin
case 2: planeCenter = planeAxis*planeOffset; //origin
break;
case 1: planeCenter = m.mm()->cm.bbox.min+planeAxis*planeOffset*(m.mm()->cm.bbox.Diag()/2.0); //bbox min
break;
case 2: planeCenter = m.mm()->cm.bbox.Center()+ planeAxis*planeOffset*(m.mm()->cm.bbox.Diag()/2.0); //bbox min
case 0: planeCenter = m.mm()->cm.bbox.Center()+ planeAxis*planeOffset*(m.mm()->cm.bbox.Diag()/2.0); //bbox min
break;
}
planeCenter+=planeAxis*planeDist*i;
slicingPlane.Init(planeCenter,planeAxis);
Box3f &bb=m.mm()->cm.bbox;
Log(0,"Slicing a mesh with bb (%5.2f %5.2f %5.2f) - (%5.2f %5.2f %5.2f)",bb.min[0],bb.min[1],bb.min[2],bb.max[0],bb.max[1],bb.max[2]);
Log(0,"Crossing at (%5.2f %5.2f %5.2f)",planeCenter[0],planeCenter[1],planeCenter[2]);
slicingPlane.Init(planeCenter,planeAxis);
//clear the selection flags
SlicedEdge<CMeshO> slicededge(slicingPlane);
SlicingFunction<CMeshO> slicingfunc(slicingPlane);
vcg::RefineE<CMeshO, SlicingFunction<CMeshO>, SlicedEdge<CMeshO> >
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> >
(m.mm()->cm, slicingfunc, slicededge, false, cb);
vcg::tri::UpdateNormals<CMeshO>::PerVertexPerFace(m.mm()->cm);
vcg::tri::UpdateSelection<CMeshO>::VertexFromQualityRange(m.mm()->cm,VERTEX_LEFT,VERTEX_LEFT);
vcg::tri::UpdateSelection<CMeshO>::FaceFromVertexLoose(m.mm()->cm);
createSlice(m);
capHole(m);
vcg::tri::UpdateSelection<CMeshO>::VertexFromQualityRange(m.mm()->cm,VERTEX_RIGHT,VERTEX_RIGHT);
vcg::tri::UpdateSelection<CMeshO>::FaceFromVertexLoose(m.mm()->cm);
createSlice(m);
capHole(m);
/*
this is for generating the svd slices
MyEdgeMesh *edgeMesh = new MyEdgeMesh();
vcg::Intersection<CMeshO, MyEdgeMesh, float>(orig->cm, slicingPlane , *edgeMesh);
vcg::Intersection<CMeshO, MyEdgeMesh, float>(m.mm()->cm, slicingPlane , *edgeMesh);
vcg::edg::UpdateBounding<MyEdgeMesh>::Box(*edgeMesh);
ev.push_back(edgeMesh);
ev.push_back(edgeMesh);
*/
}
QString fname=parlst.getString("filename");
@ -183,7 +198,7 @@ bool ExtraFilter_SlicePlugin::applyFilter(QAction *filter, MeshDocument &m, Filt
fname+=".svg";
vcg::edg::io::ExporterSVG<MyEdgeMesh>::Save(ev, fname.toStdString().c_str(), pr);
vcg::tri::UpdateNormals<CMeshO>::PerFace(m.mm()->cm);
}
break;
}
@ -208,5 +223,54 @@ bool ExtraFilter_SlicePlugin::autoDialog(QAction *action)
default: return false;
}
}
void ExtraFilter_SlicePlugin::createSlice(MeshDocument& m)
{
MeshModel *mm= new MeshModel();
m.meshList.push_back(mm);
MeshModel *destMesh = m.meshList.back(); // destination = last
MeshModel *currentMesh = m.mm(); // source = current
tri::Append<CMeshO,CMeshO>::Mesh(destMesh->cm, m.mm()->cm, true);
destMesh->fileName = "newmesh.ply"; // mesh name
tri::UpdateBounding<CMeshO>::Box(destMesh->cm); // updates bounding box
destMesh->cm.Tr = currentMesh->cm.Tr; // copy transformation
}
void ExtraFilter_SlicePlugin::capHole(MeshDocument& m)
{
std::vector<Point3f> outline;
for(int i=0;i<m.mm()->cm.vert.size();i++)
if (m.mm()->cm.vert[i].Q()==VERTEX_SLICE)
outline.push_back(m.mm()->cm.vert[i].P());
// tesselation input: each outline represents a polygon contour
std::vector< std::vector<Point3f> > outlines;
outlines.push_back(outline);
Log(0,"%d points",outline.size());
// tesselation output (triangles indices)
std::vector<int> indices;
// compute triangles indices
glu_tesselator::tesselate(outlines, indices);
// unroll input contours points
std::vector<Point3f> points;
glu_tesselator::unroll(outlines, points);
CMeshO::FaceIterator fi=tri::Allocator<CMeshO>::AddFaces(m.mm()->cm,indices.size());
Log(0,"%d new faces",indices.size());
// create triangles
for (size_t i=0; i<indices.size(); i+=3,++fi)
{
(*&fi)->V0(0)->P()=points[ indices[i+0] ];
(*&fi)->V1(0)->P()=points[ indices[i+1] ];
(*&fi)->V2(0)->P()=points[ indices[i+2] ];
}
vcg::tri::UpdateTopology<CMeshO>::FaceFace(m.mm()->cm);
}
Q_EXPORT_PLUGIN(ExtraFilter_SlicePlugin)

View File

@ -38,7 +38,8 @@
#include <vcg/complex/edgemesh/base.h>
#include <wrap/io_edgemesh/export_svg.h>
#include <vcg/space/plane3.h>
//#include "svgpro.h"
@ -77,7 +78,9 @@ public:
virtual bool applyFilter(QAction * /* filter */, MeshModel &, FilterParameterSet & /*parent*/, vcg::CallBackPos *) { assert(0); return false;} ;
virtual const int getRequirements(QAction *){return MeshModel::MM_FACEFACETOPO;}
private:
SVGProperties pr;
SVGProperties pr;
void createSlice(MeshDocument& orig);
void capHole(MeshDocument& orig);
};
#endif

View File

@ -2,29 +2,36 @@
#include <vcg/math/matrix44.h>
#include <meshlab/meshmodel.h>
using namespace vcg;
enum { VERTEX_LEFT, VERTEX_RIGHT, VERTEX_SLICE };
template <class MESH_TYPE>
class SlicedEdge
{
public:
SlicedEdge(const Plane3f &_p)
SlicedEdge(const Plane3f &_p)
{
p=_p;
}
}
bool operator()(face::Pos<typename MESH_TYPE::FaceType> ep)
{
Point3f rotv1=rot*ep.f->V0(ep.z)->P();
Point3f rotv2=rot*ep.f->V1(ep.z)->P();
Point3f pp;
Point3f pp;
Segment3f seg(ep.f->V(ep.z)->P(),ep.f->V1(ep.z)->P());
if(Distance(ep.f->V0(ep.z)->P(),p)<0)
ep.f->V0(ep.z)->Q()=VERTEX_LEFT;
else
ep.f->V0(ep.z)->Q()=VERTEX_RIGHT;
if(Distance(ep.f->V1(ep.z)->P(),p)<0)
ep.f->V1(ep.z)->Q()=VERTEX_LEFT;
else
ep.f->V1(ep.z)->Q()=VERTEX_RIGHT;
return Intersection<Segment3f>(p,seg,pp);
}
protected:
Plane3f p;
Matrix44f rot;
};
@ -43,7 +50,7 @@ public :
Point3f pp;
Intersection<Segment3f>(p,seg,pp);
nv.P()=pp;
nv.Q()=3;
nv.Q()=VERTEX_SLICE;
}
// raw calculation for wedgeinterp