Added voronoi filter

This commit is contained in:
Paolo Cignoni cignoni 2014-05-15 16:30:39 +00:00
parent 4909c6c404
commit b52bb4ec35
4 changed files with 540 additions and 0 deletions

View File

@ -0,0 +1,330 @@
/****************************************************************************
* 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. *
* *
****************************************************************************/
#include "filter_voronoi.h"
#include<vcg/complex/algorithms/voronoi_processing.h>
#include<vcg/complex/algorithms/update/curvature.h>
#include<vcg/complex/algorithms/update/quality.h>
#include<vcg/complex/algorithms/smooth.h>
#include<vcg/complex/algorithms/voronoi_volume_sampling.h>
// Constructor usually performs only two simple tasks of filling the two lists
// - typeList: with all the possible id of the filtering actions
// - actionList with the corresponding actions. If you want to add icons to your filtering actions you can do here by construction the QActions accordingly
using namespace vcg;
using namespace std;
namespace vcg {
namespace tri {
template <class MeshType>
void BuildExtrudedFaceShell(MeshType &mIn, MeshType &mOut, float height=0, float inset=0, bool smoothFlag=true )
{
typedef typename MeshType::VertexPointer VertexPointer;
typedef typename MeshType::CoordType CoordType;
if(height==0) height = mIn.bbox.Diag()/100.0f;
if(inset==0) inset = mIn.bbox.Diag()/100.0f;
tri::UpdateFlags<MeshType>::FaceClearV(mIn);
for(size_t i=0;i<mIn.face.size();++i) if(!mIn.face[i].IsV())
{
_SphMesh faceM;
CoordType bary = Barycenter(mIn.face[i]);
CoordType nf = mIn.face[i].N().Normalize();
nf = nf*height/2.0f;
std::vector<VertexPointer> vertVec;
tri::PolygonSupport<MeshType,MeshType>::ExtractPolygon(&(mIn.face[i]),vertVec);
size_t vn = vertVec.size();
// Add vertices (alternated top and bottom)
tri::Allocator<_SphMesh>::AddVertex(faceM, bary-nf);
tri::Allocator<_SphMesh>::AddVertex(faceM, bary+nf);
for(size_t j=0;j<vn;++j){
tri::Allocator<_SphMesh>::AddVertex(faceM, vertVec[j]->P()-nf);
tri::Allocator<_SphMesh>::AddVertex(faceM, vertVec[j]->P()+nf);
}
// Build top and bottom faces
for(size_t j=0;j<vn;++j)
tri::Allocator<_SphMesh>::AddFace(faceM, 0, 2+(j+0)*2, 2+((j+1)%vn)*2 );
for(size_t j=0;j<vn;++j)
tri::Allocator<_SphMesh>::AddFace(faceM, 1, 3+(j+0)*2, 3+((j+1)%vn)*2 );
// Build side strip
for(size_t j=0;j<vn;++j){
size_t j0=j;
size_t j1=(j+1)%vn;
tri::Allocator<_SphMesh>::AddFace(faceM, 2+ j0*2 + 0 , 2+ j0*2+1, 2+j1*2+0);
tri::Allocator<_SphMesh>::AddFace(faceM, 2+ j0*2 + 1 , 2+ j1*2+1, 2+j1*2+0);
}
for(size_t j=0;j<2*vn;++j)
faceM.face[j].SetS();
tri::UpdateTopology<_SphMesh>::FaceFace(faceM);
tri::UpdateFlags<_SphMesh>::FaceBorderFromFF(faceM);
tri::Refine(faceM, MidPoint<_SphMesh>(&faceM),0,true);
tri::Refine(faceM, MidPoint<_SphMesh>(&faceM),0,true);
tri::Append<MeshType,_SphMesh>::Mesh(mOut,faceM);
} // end main loop for each face;
}
};
};
FilterVoronoiPlugin::FilterVoronoiPlugin()
{
}
bool FilterVoronoiPlugin::applyFilter( const QString& filterName,MeshDocument& md,EnvWrap& env, vcg::CallBackPos* cb)
{
if(filterName == "Cross Field Coloring")
{
MeshModel &m=*md.mm();
m.updateDataMask(MeshModel::MM_VERTCOLOR);
m.updateDataMask(MeshModel::MM_VERTQUALITY);
for(CMeshO::VertexIterator vi=m.cm.vert.begin();vi!=m.cm.vert.end();++vi)
{
vi->Q() = Norm(vi->PD1()) / Norm(vi->PD2());
}
tri::UpdateColor<CMeshO>::PerVertexQualityRamp(m.cm);
return true;
}
if(filterName == "Cross Field Creation")
{
MeshModel &m=*md.mm();
m.updateDataMask(MeshModel::MM_VERTCURVDIR);
int crossType = env.evalEnum("crossType");
if(crossType == 0) // Linear Y
{
float range = m.cm.bbox.DimY();
for(int i=0;i<m.cm.vert.size();++i){
float q01 = .25f+(m.cm.vert[i].P().Y() - m.cm.bbox.min.Y())/(2.0f*range);
m.cm.vert[i].PD1()=Point3f(1,0,0)*q01;
m.cm.vert[i].PD2()=Point3f(0,1,0)*(sqrt(1-q01*q01));
}
}
if(crossType == 1) // Radial
{
tri::UpdateCurvature<CMeshO>::PerVertexBasicRadialCrossField(m.cm,2.0);
}
if(crossType == 2) // Curvature
{
}
return true;
}
if(filterName == "Voronoi Sampling")
{
MeshModel *om=md.addOrGetMesh("voro", "voro",false);
MeshModel *poly=md.addOrGetMesh("poly", "poly",false);
om->updateDataMask(MeshModel::MM_VERTCOLOR);
const int sampleNum =env.evalInt("sampleNum");
const int iterNum = env.evalInt("iterNum");
const float radiusVariance = env.evalFloat("radiusVariance");
const int distanceType=env.evalEnum("distanceType");
MeshModel &m=*md.mm();
m.updateDataMask(MeshModel::MM_FACEFACETOPO);
m.updateDataMask(MeshModel::MM_VERTFACETOPO);
m.updateDataMask(MeshModel::MM_VERTCURV);
m.updateDataMask(MeshModel::MM_VERTCURVDIR);
m.updateDataMask(MeshModel::MM_VERTCOLOR);
tri::UpdateCurvature<CMeshO>::PerVertexBasicRadialCrossField(m.cm);
// tri::EuclideanDistance<CMeshO> dd;
vector<CVertexO *> seedVec;
// tri::ClusteringSampler<CMeshO> cs(seedVec);
// tri::SurfaceSampling<CMeshO, vcg::tri::ClusteringSampler<CMeshO> >::SamplingRandomGenerator().initialize(randSeed);
vector<Point3f> pointVec;
float radius=0;
tri::PoissonSampling<CMeshO>(m.cm,pointVec,sampleNum,radius,radiusVariance);
tri::VoronoiProcessingParameter vpp;
vpp.geodesicRelaxFlag = (env.evalEnum("relaxType")==0);
vpp.colorStrategy = env.evalEnum("colorStrategy");
vpp.deleteUnreachedRegionFlag=true;
vpp.refinementRatio=10;
if(env.evalBool("preprocessFlag"))
{
tri::VoronoiProcessing<CMeshO>::PreprocessForVoronoi(m.cm,radius,vpp);
}
tri::VoronoiProcessing<CMeshO>::SeedToVertexConversion(m.cm,pointVec,seedVec);
QList<int> meshlist; meshlist << m.id();
if(distanceType==0) // Uniform Euclidean Distance
{
EuclideanDistance<CMeshO> dd;
for(int i=0;i<iterNum;++i)
{
cb(100*i/iterNum, "Relaxing...");
tri::VoronoiProcessing<CMeshO, EuclideanDistance<CMeshO> >::VoronoiRelaxing(m.cm, seedVec, 1,dd,vpp);
md.updateRenderStateMeshes(meshlist,int(MeshModel::MM_VERTCOLOR));
if (intteruptreq) return true;
}
// tri::VoronoiProcessing<CMeshO>::ConvertVoronoiDiagramToMesh(m.cm,om->cm,poly->cm,seedVec, vpp);
}
if(distanceType==1)
{
IsotropicDistance<CMeshO> id(m.cm,radiusVariance);
for(int i=0;i<iterNum;++i)
{
cb(100*i/iterNum, "Relaxing...");
tri::VoronoiProcessing<CMeshO, IsotropicDistance<CMeshO> >::VoronoiRelaxing(m.cm, seedVec, 1,id,vpp);
md.updateRenderStateMeshes(meshlist,int(MeshModel::MM_VERTCOLOR));
if (intteruptreq) return true;
}
// tri::VoronoiProcessing<CMeshO>::ConvertVoronoiDiagramToMesh(m.cm,om->cm,poly->cm,seedVec, vpp);
}
if(distanceType==2)
{
for(int i=0;i<iterNum;++i)
{
cb(100*i/iterNum, "Relaxing...");
BasicCrossFunctor<CMeshO> bcf(m.cm);
AnisotropicDistance<CMeshO> ad(m.cm,bcf);
tri::VoronoiProcessing<CMeshO, AnisotropicDistance<CMeshO> >::VoronoiRelaxing(m.cm, seedVec, 1, ad, vpp);
md.updateRenderStateMeshes(meshlist,int(MeshModel::MM_VERTCOLOR));
if (intteruptreq) return true;
}
// tri::VoronoiProcessing<CMeshO, AnisotropicDistance<CMeshO> >::ConvertVoronoiDiagramToMesh(m.cm,om->cm,seedVec, ad, vpp);
}
md.updateRenderStateMeshes(meshlist,int(MeshModel::MM_VERTCOLOR));
if (intteruptreq) return true;
om->UpdateBoxAndNormals();
return true;
}
if(filterName=="Volumetric Sampling") /******************************************************/
{
MeshModel *m= md.mm();
m->updateDataMask(MeshModel::MM_FACEMARK);
float sampleSurfRadius = env.evalFloat("sampleSurfRadius");
float poissonRadius = env.evalFloat("poissonRadius");
int sampleVolNum = env.evalInt("sampleVolNum");
int poissonFlag = env.evalBool("poissonFiltering");
MeshModel *mcVm= md.addOrGetMesh("Montecarlo Volume","Montecarlo Volume",false,RenderMode(GLW::DMPoints));
MeshModel *pVm= md.addOrGetMesh("Poisson Sampling","Poisson Sampling",false,RenderMode(GLW::DMPoints));
MeshModel *pSm= md.addOrGetMesh("Surface Sampling","Surface Sampling",false,RenderMode(GLW::DMPoints));
mcVm->updateDataMask(MeshModel::MM_VERTCOLOR | MeshModel::MM_VERTQUALITY);
pSm->updateDataMask(MeshModel::MM_VERTCOLOR | MeshModel::MM_VERTQUALITY);
VoronoiVolumeSampling<CMeshO> vvs(m->cm, pVm->cm);
Log("Sampling Surface at a radius %f ",sampleSurfRadius);
cb(1, "Init");
vvs.Init(sampleSurfRadius);
cb(30, "Sampling Volume...");
vvs.BuildVolumeSampling(sampleVolNum,0,poissonRadius,cb);
tri::Append<CMeshO,CMeshO>::MeshCopy(mcVm->cm,vvs.montecarloVolumeMesh);
tri::UpdateColor<CMeshO>::PerVertexQualityRamp(mcVm->cm);
vvs.ThicknessEvaluator();
tri::Append<CMeshO,CMeshO>::MeshCopy(pSm->cm,vvs.poissonSurfaceMesh);
return true;
}
if(filterName=="Voronoi Scaffolding") /******************************************************/
{
MeshModel *m= md.mm();
m->updateDataMask(MeshModel::MM_FACEMARK);
MeshModel *pm= md.addOrGetMesh("Poisson-disk Samples","Poisson-disk Samples",false,RenderMode(GLW::DMPoints));
MeshModel *mcVm= md.addOrGetMesh("Montecarlo Volume","Montecarlo Volume",false,RenderMode(GLW::DMPoints));
MeshModel *vsm= md.addOrGetMesh("Voronoi Seeds","Voronoi Seeds",false,RenderMode(GLW::DMPoints));
MeshModel *sm= md.addOrGetMesh("Scaffolding","Scaffolding",false,RenderMode(GLW::DMFlat));
pm->updateDataMask(m);
cb(10, "Sampling Surface...");
float sampleSurfRadius = env.evalFloat("sampleSurfRadius");
int sampleVolNum = env.evalInt("sampleVolNum");
int voronoiSeed = env.evalInt("voronoiSeed");
int voxelRes = env.evalInt("voxelRes");
float isoThr = env.evalFloat("isoThr");
int smoothStep = env.evalInt("smoothStep");
int relaxStep = env.evalInt("relaxStep");
int surfFlag = env.evalBool("surfFlag");
int elemType = env.evalEnum("elemType");
VoronoiVolumeSampling<CMeshO> vvs(m->cm,vsm->cm);
Log("Sampling Surface at a radius %f ",sampleSurfRadius);
vvs.Init(sampleSurfRadius);
cb(30, "Sampling Volume...");
float poissonVolumeRadius=0;
vvs.BuildVolumeSampling(sampleVolNum,voronoiSeed,poissonVolumeRadius);
Log("Base Poisson volume sampling at a radius %f ",poissonVolumeRadius);
cb(40, "Relaxing Volume...");
vvs.RelaxVoronoiSamples(relaxStep);
cb(50, "Building Scaffloding Volume...");
vvs.BuildScaffoldingMesh(sm->cm,voxelRes,isoThr,elemType,surfFlag);
cb(90, "Final Smoothing...");
tri::Smooth<CMeshO>::VertexCoordLaplacian(sm->cm, smoothStep);
sm->UpdateBoxAndNormals();
tri::Append<CMeshO,CMeshO>::MeshCopy(mcVm->cm,vvs.montecarloVolumeMesh);
tri::Append<CMeshO,CMeshO>::MeshCopy(pm->cm,vvs.poissonSurfaceMesh);
return true;
}
if(filterName=="Create Solid Wireframe") /******************************************************/
{
MeshModel *m= md.mm();
m->updateDataMask(MeshModel::MM_FACEFACETOPO);
MeshModel *sm= md.addOrGetMesh("Shell Mesh","Shell Mesh",false,RenderMode(GLW::DMFlat));
float edgeCylRadius = env.evalFloat("edgeCylRadius");
float vertCylRadius = env.evalFloat("vertCylRadius");
float vertSphRadius = env.evalFloat("vertSphRadius");
float faceExtHeight = env.evalFloat("faceExtHeight");
bool edgeCylFlag = env.evalBool("edgeCylFlag");
bool vertCylFlag = env.evalBool("vertCylFlag");
bool vertSphFlag = env.evalBool("vertSphFlag");
bool faceExtFlag = env.evalBool("faceExtFlag");
sm->cm.Clear();
sm->updateDataMask(MeshModel::MM_FACEFACETOPO);
tri::RequireFFAdjacency(sm->cm);
tri::UpdateNormal<CMeshO>::PerVertexNormalizedPerFace(m->cm);
tri::Clean<CMeshO>::RemoveUnreferencedVertex(m->cm);
tri::Allocator<CMeshO>::CompactEveryVector(m->cm);
if(edgeCylFlag) tri::BuildCylinderEdgeShell(m->cm,sm->cm,edgeCylRadius);
if(vertCylFlag) tri::BuildCylinderVertexShell(m->cm,sm->cm,vertCylRadius,edgeCylRadius);
if(vertSphFlag) tri::BuildSphereVertexShell(m->cm,sm->cm,vertSphRadius);
if(faceExtFlag) tri::BuildExtrudedFaceShell(m->cm,sm->cm,faceExtHeight);
sm->UpdateBoxAndNormals();
return true;
}
return false;
}
MESHLAB_PLUGIN_NAME_EXPORTER(FilterVoronoiPlugin)

View File

@ -0,0 +1,42 @@
/****************************************************************************
* 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 _FILTER_ICP_H_
#define _FILTER_ICP_H_
#include <common/interfaces.h>
//class QScriptEngine;
class FilterVoronoiPlugin : public MeshLabFilterInterface
{
Q_OBJECT
MESHLAB_PLUGIN_IID_EXPORTER(MESHLAB_FILTER_INTERFACE_IID)
Q_INTERFACES(MeshLabFilterInterface)
public:
FilterVoronoiPlugin();
bool applyFilter(const QString& filterName,MeshDocument& md,EnvWrap& env, vcg::CallBackPos* cb) ;
};
#endif

View File

@ -0,0 +1,11 @@
include (../../shared.pri)
HEADERS += filter_voronoi.h \
voronoi_volume_sampling.h
SOURCES += filter_voronoi.cpp
TARGET = filter_voronoi
PRE_TARGETDEPS += filter_voronoi.xml
macx:QMAKE_POST_LINK = "rsync -u "$$TARGET".xml ../../distrib/plugins/"$$TARGET".xml; rsync -u ../../distrib/plugins/"$$TARGET".xml "$$TARGET".xml"

View File

@ -0,0 +1,157 @@
<MESHLAB_FILTER_INTERFACE mfiVersion="2.0" >
<PLUGIN pluginName="VoronoiTechniques" pluginAuthor="Paolo Cignoni" pluginEmail="paolo.cignoni@isti.cnr.it">
<FILTER filterFunction="voronoiSampling" filterName="Voronoi Sampling" filterPre="MM_NONE" filterRasterArity="SingleRaster" filterClass="Sampling" filterPost="MM_VERTCOLOR | MM_VERTQUALITY" filterArity="SingleMesh" filterIsInterruptible="true">
<FILTER_HELP><![CDATA[Compute a sampling over a mesh and perform a Lloyd relaxation. It can]]></FILTER_HELP>
<FILTER_JSCODE><![CDATA[]]></FILTER_JSCODE>
<PARAM parName="iterNum" parIsImportant="true" parType="Int" parDefault="10">
<PARAM_HELP><![CDATA[ number of iterations ]]></PARAM_HELP>
<EDIT_GUI guiLabel="Iteration"/>
</PARAM>
<PARAM parName="sampleNum" parIsImportant="true" parType="Int" parDefault="10">
<PARAM_HELP><![CDATA[ Number of samples ]]></PARAM_HELP>
<EDIT_GUI guiLabel="Sample Num."/>
</PARAM>
<PARAM parName="radiusVariance" parIsImportant="true" parType="Real" parDefault="1">
<PARAM_HELP><![CDATA[The distance metric will vary along the surface between 1/x and x, linearly according to the scalar field specified by the quality. ]]></PARAM_HELP>
<EDIT_GUI guiLabel="Radius Variance"/>
</PARAM>
<PARAM parName="colorStrategy" parIsImportant="false" parType="Enum {None: 0 | Seed_Distance : 1 | Border_Distance : 2 | Region_Area : 3}" parDefault="1">
<PARAM_HELP><![CDATA[]]></PARAM_HELP>
<ENUM_GUI guiLabel="Color Strategy"/>
</PARAM>
<PARAM parName="distanceType" parIsImportant="true" parType="Enum { Euclidean : 0 | QualityWeighted : 1 | Anisotropic : 2}" parDefault="0">
<PARAM_HELP><![CDATA[]]></PARAM_HELP>
<ENUM_GUI guiLabel="distanceType"/>
</PARAM>
<PARAM parName="preprocessFlag" parIsImportant="false" parType="Boolean" parDefault="true">
<PARAM_HELP><![CDATA[]]></PARAM_HELP>
<CHECKBOX_GUI guiLabel="Preprocessing"/>
</PARAM>
<PARAM parName="relaxType" parIsImportant="true" parType="Enum { Geodesic : 0 | SquaredDistance : 1 }" parDefault="1">
<PARAM_HELP><![CDATA[
At each relaxation step we search for each voronoi region the new position of the seed.
According to the classical LLoyd relaxation strategy it should have been placed onto the
barycenter of the region. Over a surface we have two different strategies:
<ul>
<li> Geodesic: the seed is placed onto the vertex that maximize the geodesic distance from the border of the region </li>
<li> Squared Distance: the seed is placed in the vertex that minimize the squared sum of the distances from all the pints of the region.</li>
</ul>
]]></PARAM_HELP>
<ENUM_GUI guiLabel="Relax Type"/>
</PARAM>
</FILTER>
<FILTER filterFunction="volumeSampling" filterName="Volumetric Sampling" filterPre="MM_NONE" filterRasterArity="SingleRaster" filterClass="Sampling" filterPost="MM_VERTCOLOR | MM_VERTQUALITY" filterArity="SingleMesh" filterIsInterruptible="true">
<FILTER_HELP><![CDATA[Compute a volumetric sampling over a watertight mesh. ]]></FILTER_HELP>
<FILTER_JSCODE><![CDATA[]]></FILTER_JSCODE>
<PARAM parName="sampleSurfRadius" parIsImportant="true" parType="Real" parDefault="meshDoc.current().bboxDiag() / 500.0">
<PARAM_HELP><![CDATA[ Surface Sampling is used only as an optimization ]]></PARAM_HELP>
<ABSPERC_GUI guiLabel="Surface Sampling Radius." guiMin="0" guiMax="meshDoc.current().bboxDiag()"/>
</PARAM>
<PARAM parName="sampleVolNum" parIsImportant="true" parType="Int" parDefault="200000">
<PARAM_HELP><![CDATA[ Number of volumetric samples scattered inside the mesh and used for choosing the voronoi seeds and performing the Lloyd relaxation for having a centroidal voronoi diagram.]]></PARAM_HELP>
<EDIT_GUI guiLabel="Volume Sample Num."/>
</PARAM>
<PARAM parName="poissonFiltering" parIsImportant="true" parType="Boolean" parDefault="true">
<PARAM_HELP><![CDATA[ If true the base montecarlo sampling of the volume is filtered to get a poisson disk volumetric distribution ]]></PARAM_HELP>
<CHECKBOX_GUI guiLabel="Poisson Filtering"/>
</PARAM>
<PARAM parName="poissonRadius" parIsImportant="true" parType="Real" parDefault="meshDoc.current().bboxDiag() / 100.0">
<PARAM_HELP><![CDATA[ Number of voxel per side in the volumetric representation ]]></PARAM_HELP>
<ABSPERC_GUI guiLabel="Poisson Radius." guiMin="0" guiMax="meshDoc.current().bboxDiag()"/>
</PARAM>
</FILTER>
<FILTER filterFunction="voronoiScaffolding" filterName="Voronoi Scaffolding" filterPre="MM_NONE" filterRasterArity="SingleRaster" filterClass="Sampling" filterPost="MM_VERTCOLOR | MM_VERTQUALITY" filterArity="SingleMesh" filterIsInterruptible="true">
<FILTER_HELP><![CDATA[Compute a volumetric sampling over a watertight mesh]]></FILTER_HELP>
<FILTER_JSCODE><![CDATA[]]></FILTER_JSCODE>
<PARAM parName="sampleSurfRadius" parIsImportant="true" parType="Real" parDefault="meshDoc.current().bboxDiag() / 100.0">
<PARAM_HELP><![CDATA[ Surface Sampling is used only as an optimization ]]></PARAM_HELP>
<ABSPERC_GUI guiLabel="Surface Sampling Radius." guiMin="0" guiMax="meshDoc.current().bboxDiag()"/>
</PARAM>
<PARAM parName="sampleVolNum" parIsImportant="true" parType="Int" parDefault="100000">
<PARAM_HELP><![CDATA[ Number of volumetric samples scattered inside the mesh and used for choosing the voronoi seeds and performing the Lloyd relaxation for having a centroidal voronoi diagram.]]></PARAM_HELP>
<EDIT_GUI guiLabel="Volume Sample Num."/>
</PARAM>
<PARAM parName="voronoiSeed" parIsImportant="true" parType="Int" parDefault="20">
<PARAM_HELP><![CDATA[ Number of seeds of the voronoi cells ]]></PARAM_HELP>
<EDIT_GUI guiLabel="Voronoi Seed Num."/>
</PARAM>
<PARAM parName="voxelRes" parIsImportant="true" parType="Int" parDefault="50">
<PARAM_HELP><![CDATA[ Number of voxel per side in the volumetric representation ]]></PARAM_HELP>
<EDIT_GUI guiLabel="Volume Side Resolution."/>
</PARAM>
<PARAM parName="isoThr" parIsImportant="true" parType="Real" parDefault="1">
<PARAM_HELP><![CDATA[ Number of voxel per side in the volumetric representation ]]></PARAM_HELP>
<EDIT_GUI guiLabel="Width of the entity (in voxel)"/>
</PARAM>
<PARAM parName="smoothStep" parIsImportant="true" parType="Int" parDefault="3">
<PARAM_HELP><![CDATA[ Number of voxel per side in the volumetric representation ]]></PARAM_HELP>
<EDIT_GUI guiLabel="Smooth Step"/>
</PARAM>
<PARAM parName="relaxStep" parIsImportant="true" parType="Int" parDefault="5">
<PARAM_HELP><![CDATA[ Number of Lloyd relaxation step to get a better distribution of the voronoi seeds ]]></PARAM_HELP>
<EDIT_GUI guiLabel="Lloyd Relax Step"/>
</PARAM>
<PARAM parName="surfFlag" parIsImportant="true" parType="Boolean" parDefault="true">
<PARAM_HELP><![CDATA[ Number of voxel per side in the volumetric representation ]]></PARAM_HELP>
<CHECKBOX_GUI guiLabel="Add original surface"/>
</PARAM>
<PARAM parName="elemType" parIsImportant="true" parType="Enum { Seed : 0 | Edge : 1 | Face :2}" parDefault="1">
<PARAM_HELP><![CDATA[]]></PARAM_HELP>
<ENUM_GUI guiLabel="Voronoi Element"/>
</PARAM>
</FILTER>
<FILTER filterFunction="buildShell" filterName="Create Solid Wireframe" filterPre="MM_NONE" filterRasterArity="SingleRaster" filterClass="Meshing" filterPost="" filterArity="SingleMesh" filterIsInterruptible="false">
<FILTER_HELP><![CDATA[]]></FILTER_HELP>
<FILTER_JSCODE><![CDATA[]]></FILTER_JSCODE>
<PARAM parName="edgeCylFlag" parIsImportant="true" parType="Boolean" parDefault="true">
<PARAM_HELP><![CDATA[ If True all the edges are converted into cylinders ]]></PARAM_HELP>
<CHECKBOX_GUI guiLabel="Edge -> Cyl."/>
</PARAM>
<PARAM parName="edgeCylRadius" parIsImportant="true" parType="Real" parDefault="meshDoc.current().bboxDiag() / 100.0">
<PARAM_HELP><![CDATA[ The radius of the cylinder replacing each edge ]]></PARAM_HELP>
<ABSPERC_GUI guiLabel="Edge Cylinder Rad." guiMin="0" guiMax="meshDoc.current().bboxDiag()"/>
</PARAM>
<PARAM parName="vertCylFlag" parIsImportant="true" parType="Boolean" parDefault="false">
<PARAM_HELP><![CDATA[ If True all the vertexes are converted into cylinders ]]></PARAM_HELP>
<CHECKBOX_GUI guiLabel="Vertex -> Cyl."/>
</PARAM>
<PARAM parName="vertCylRadius" parIsImportant="true" parType="Real" parDefault="meshDoc.current().bboxDiag() / 100.0">
<PARAM_HELP><![CDATA[ The radius of the cylinder replacing each vertex ]]></PARAM_HELP>
<ABSPERC_GUI guiLabel="Vertex Cylinder Rad." guiMin="0" guiMax="meshDoc.current().bboxDiag()"/>
</PARAM>
<PARAM parName="vertSphFlag" parIsImportant="true" parType="Boolean" parDefault="true">
<PARAM_HELP><![CDATA[ If True all the vertexes are converted into sphere ]]></PARAM_HELP>
<CHECKBOX_GUI guiLabel="Vertex -> Sph."/>
</PARAM>
<PARAM parName="vertSphRadius" parIsImportant="true" parType="Real" parDefault="meshDoc.current().bboxDiag() / 100.0">
<PARAM_HELP><![CDATA[ The radius of the sphere replacing each vertex ]]></PARAM_HELP>
<ABSPERC_GUI guiLabel="Vertex Sphere Rad." guiMin="0" guiMax="meshDoc.current().bboxDiag()"/>
</PARAM>
<PARAM parName="faceExtFlag" parIsImportant="true" parType="Boolean" parDefault="true">
<PARAM_HELP><![CDATA[ If True all the faces are converted into prism ]]></PARAM_HELP>
<CHECKBOX_GUI guiLabel="Face -> Prism"/>
</PARAM>
<PARAM parName="faceExtHeight" parIsImportant="true" parType="Real" parDefault="meshDoc.current().bboxDiag() / 200.0">
<PARAM_HELP><![CDATA[ The radius of the sphere replacing each vertex ]]></PARAM_HELP>
<ABSPERC_GUI guiLabel="Face Prism Height." guiMin="0" guiMax="meshDoc.current().bboxDiag()"/>
</PARAM>
<PARAM parName="edgeFauxFlag" parIsImportant="true" parType="Boolean" parDefault="true">
<PARAM_HELP><![CDATA[ If true only the Non-Faux edges will be considered for conversion]]></PARAM_HELP>
<CHECKBOX_GUI guiLabel="Ignore Faux Edge."/>
</PARAM>
</FILTER>
<FILTER filterFunction="crossFieldCreation" filterName="Cross Field Creation" filterPre="MM_NONE" filterRasterArity="SingleRaster" filterClass="Normal" filterPost="MM_VERTCURVDIR" filterArity="SingleMesh" filterIsInterruptible="false">
<FILTER_HELP><![CDATA[]]></FILTER_HELP>
<FILTER_JSCODE><![CDATA[]]></FILTER_JSCODE>
<PARAM parName="crossType" parIsImportant="true" parType="Enum { Linear_Y : 0 | Radial : 1 | Curvature :2}" parDefault="0">
<PARAM_HELP><![CDATA[]]></PARAM_HELP>
<ENUM_GUI guiLabel="crossType"/>
</PARAM>
</FILTER>
<FILTER filterFunction="crossFieldColoring" filterName="Cross Field Coloring" filterPre="MM_VERTCURVDIR" filterRasterArity="SingleRaster" filterClass="Generic" filterPost="MM_VERTCOLOR" filterArity="SingleMesh" filterIsInterruptible="false">
<FILTER_HELP><![CDATA[]]></FILTER_HELP>
<FILTER_JSCODE><![CDATA[]]></FILTER_JSCODE>
</FILTER>
</PLUGIN>
</MESHLAB_FILTER_INTERFACE>