From 7903dac87605a8d7ef7e09b050301d0d3be58481 Mon Sep 17 00:00:00 2001 From: Paolo Cignoni cignoni Date: Sun, 14 Dec 2008 13:52:49 +0000 Subject: [PATCH] The filter now creates two new layers containing the sliced parts. Works only on two-manifold meshes with only 1 slicing plane. --- .../filter_slice/filter_slice.cpp | 106 ++++++++++++++---- .../filter_slice/filter_slice.h | 7 +- .../filter_slice/filter_slice_functors.h | 23 ++-- 3 files changed, 105 insertions(+), 31 deletions(-) diff --git a/src/meshlabplugins/filter_slice/filter_slice.cpp b/src/meshlabplugins/filter_slice/filter_slice.cpp index 62234594a..b8d8018ff 100644 --- a/src/meshlabplugins/filter_slice/filter_slice.cpp +++ b/src/meshlabplugins/filter_slice/filter_slice.cpp @@ -22,15 +22,22 @@ ****************************************************************************/ #include "filter_slice.h" - +//#include #include #include -#include +#include +#include #include #include +#include +#include +#include + #include "filter_slice_functors.h" -//#include +#include +#include +#include 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 ev; - MeshModel *orig=m.mm(); m.mm()->visible=false; for(int i=0;icm.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 slicededge(slicingPlane); - SlicingFunction slicingfunc(slicingPlane); - - vcg::RefineE, SlicedEdge > + SlicedEdge slicededge(slicingPlane); + SlicingFunction slicingfunc(slicingPlane); + //after the RefineE call, the mesh will be half vertices selected + vcg::RefineE, SlicedEdge > (m.mm()->cm, slicingfunc, slicededge, false, cb); + vcg::tri::UpdateNormals::PerVertexPerFace(m.mm()->cm); + vcg::tri::UpdateSelection::VertexFromQualityRange(m.mm()->cm,VERTEX_LEFT,VERTEX_LEFT); + vcg::tri::UpdateSelection::FaceFromVertexLoose(m.mm()->cm); + createSlice(m); + capHole(m); + + vcg::tri::UpdateSelection::VertexFromQualityRange(m.mm()->cm,VERTEX_RIGHT,VERTEX_RIGHT); + vcg::tri::UpdateSelection::FaceFromVertexLoose(m.mm()->cm); + createSlice(m); + capHole(m); + + /* + this is for generating the svd slices MyEdgeMesh *edgeMesh = new MyEdgeMesh(); - vcg::Intersection(orig->cm, slicingPlane , *edgeMesh); + vcg::Intersection(m.mm()->cm, slicingPlane , *edgeMesh); vcg::edg::UpdateBounding::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::Save(ev, fname.toStdString().c_str(), pr); - vcg::tri::UpdateNormals::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::Mesh(destMesh->cm, m.mm()->cm, true); + destMesh->fileName = "newmesh.ply"; // mesh name + tri::UpdateBounding::Box(destMesh->cm); // updates bounding box + destMesh->cm.Tr = currentMesh->cm.Tr; // copy transformation +} + +void ExtraFilter_SlicePlugin::capHole(MeshDocument& m) +{ + + std::vector outline; + for(int i=0;icm.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 > outlines; + outlines.push_back(outline); + Log(0,"%d points",outline.size()); + // tesselation output (triangles indices) + std::vector indices; + + // compute triangles indices + glu_tesselator::tesselate(outlines, indices); + + // unroll input contours points + std::vector points; + + glu_tesselator::unroll(outlines, points); + + CMeshO::FaceIterator fi=tri::Allocator::AddFaces(m.mm()->cm,indices.size()); + Log(0,"%d new faces",indices.size()); + // create triangles + for (size_t i=0; iV0(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::FaceFace(m.mm()->cm); +} Q_EXPORT_PLUGIN(ExtraFilter_SlicePlugin) diff --git a/src/meshlabplugins/filter_slice/filter_slice.h b/src/meshlabplugins/filter_slice/filter_slice.h index 5e19ed557..e50746547 100644 --- a/src/meshlabplugins/filter_slice/filter_slice.h +++ b/src/meshlabplugins/filter_slice/filter_slice.h @@ -38,7 +38,8 @@ #include #include - + +#include //#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 diff --git a/src/meshlabplugins/filter_slice/filter_slice_functors.h b/src/meshlabplugins/filter_slice/filter_slice_functors.h index d68dc2880..aa9200159 100644 --- a/src/meshlabplugins/filter_slice/filter_slice_functors.h +++ b/src/meshlabplugins/filter_slice/filter_slice_functors.h @@ -2,29 +2,36 @@ #include #include + using namespace vcg; +enum { VERTEX_LEFT, VERTEX_RIGHT, VERTEX_SLICE }; + template class SlicedEdge { public: - SlicedEdge(const Plane3f &_p) + SlicedEdge(const Plane3f &_p) { p=_p; - } + } bool operator()(face::Pos 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(p,seg,pp); - } protected: Plane3f p; - Matrix44f rot; }; @@ -43,7 +50,7 @@ public : Point3f pp; Intersection(p,seg,pp); nv.P()=pp; - nv.Q()=3; + nv.Q()=VERTEX_SLICE; } // raw calculation for wedgeinterp