コード例 #1
0
ファイル: filter_topo.cpp プロジェクト: openpattreco/3rdParty
//
// Filter interface start up
//
void FilterTopoPlugin::initParameterSet(QAction *action, MeshDocument & md, RichParameterSet & parlst) 
{
	MeshModel *target= md.mm();
	foreach (target, md.meshList) 
		if (target != md.mm())  break;

	doc = &md;

	 switch(ID(action))	 {
		case FP_RE_TOPO :  
			// Iterations editbox
			parlst.addParam(new RichInt(	"it", 
							4,
							"Number of refinement iterations used to build the new mesh", 
							"As higher is this value, as well defined will be the new mesh. Consider that more than 5 iterations may slow down your system"));
			// Distance editbox
			parlst.addParam(new RichAbsPerc(	"dist", 0.3f, 0.01f, 0.99f, 
								"Incremental distance %", 
								"This param represents the % distance for the local search algorithm used for new vertices allocation. Generally, 0.25-0.30 is a good value"));
			// Topology mesh list
			parlst.addParam(new RichMesh(	"userMesh", md.mm(), 
							"Topology mesh",
							"This mesh will be used as the new base topology, and will be replaced by the new mesh"));
			// Original mesh list
			parlst.addParam(new RichMesh( "inMesh", target,
							"Original mesh",
							"The new mesh will be elaborated using this model"));
		break;
											
		default : assert(0); 
	}
}
コード例 #2
0
bool MeshDocumentFromNvm(MeshDocument &md, QString filename_nvm, QString model_filename)
{
  md.addNewMesh(model_filename,QString("model"));
  std::vector<vcg::Shotf> shots;
  const QString path = QFileInfo(filename_nvm).absolutePath();
  //const QString path_im = QFileInfo(image_list_filename).absolutePath()+QString("/");

  std::vector<std::string>   image_filenames;
  vcg::tri::io::ImporterNVM<CMeshO>::Open(md.mm()->cm,shots,image_filenames,qPrintable(filename_nvm));
  md.mm()->updateDataMask(MeshModel::MM_VERTCOLOR);

  QString curr_path = QDir::currentPath();
  //QFileInfo imi(image_list_filename);

  //QDir::setCurrent(imi.absoluteDir().absolutePath());
  QStringList image_filenames_q;
  for(unsigned int i  = 0; i < image_filenames.size(); ++i)
    image_filenames_q.push_back(QString::fromStdString(image_filenames[i]));

	for(size_t i=0 ; i<shots.size() ; i++){
			md.addNewRaster();
                        const QString fullpath_image_filename = image_filenames_q[i];
			md.rm()->addPlane(new Plane(fullpath_image_filename,Plane::RGBA));
			md.rm()->setLabel(image_filenames_q[i].section('/',1,2));
			md.rm()->shot = shots[i];
			/*md.rm()->shot.Intrinsics.ViewportPx[0]=md.rm()->currentPlane->image.width();
			md.rm()->shot.Intrinsics.ViewportPx[1]=md.rm()->currentPlane->image.height();
			md.rm()->shot.Intrinsics.CenterPx[0]=(int)((double)md.rm()->shot.Intrinsics.ViewportPx[0]/2.0f);
			md.rm()->shot.Intrinsics.CenterPx[1]=(int)((double)md.rm()->shot.Intrinsics.ViewportPx[1]/2.0f);*/

	}
        QDir::setCurrent(curr_path);

  return true;
}
コード例 #3
0
void AlignTools::buildParameterSet(MeshDocument &md,RichParameterSet & parlst)
{
	vcg::AlignPair::Param ICPParameters;
	AlignParameter::buildRichParameterSet(ICPParameters, parlst);

	parlst.addParam(new RichBool(UseMarkers, true, "Use Markers for Alignment","if true (default), then use the user picked markers to do an alignment (or pre alignment if you also use ICP)."));
	parlst.addParam(new RichBool(AllowScaling, false, "Scale the mesh","if true (false by default), in addition to the alignment, scale the mesh based on the points picked"));
	
	parlst.addParam(new RichBool(UseICP, true, "Use ICP for Alignment","if true (default), then use the ICP to align the two meshes."));
	
	parlst.addParam(new RichMesh (StuckMesh, md.mm(), &md,"Stuck Mesh",
			"The mesh that will not move."));
	parlst.addParam(new RichMesh (MeshToMove, md.mm(), &md, "Mesh to Move",
			"The mesh that will move to fit close to the Stuck Mesh."));
}
コード例 #4
0
bool MeshGridPlugin::applyFilter(QAction *algo, MeshDocument &md,
                                 RichParameterSet & par, vcg::CallBackPos *cb)
{

    int cols = par.getInt("numVertX");
    int rows = par.getInt("numVertY");

    float totalw = 1.0;
    float totalh = 1.0;
    int w = cols+1;
    int h = rows+1;
    float wl = 1.0/cols;
    float hl = 1.0/rows;

    qDebug("w %d h %d",w,h);
    if(w <= 0 || h <= 0) {
        return false;
    }

    md.addNewMesh("",QString("%1_%2").arg(rows).arg(cols));
    MeshModel &m=*(md.mm());



    // use Grid function to generate Grid
    std::vector<float> data(w*h,0);
    tri::Grid<CMeshO>(m.cm, w, h, 1, 1, &data[0]);


    {
        // move x and y
        double halfw = double(w-1)/2;
        double halfh = double(h-1)/2;
        double wld = wl/double(w);
        double hld = hl/float(h);


//      CMeshO::VertexIterator vi;
//      for(vi = m.cm.vert.begin(); vi != m.cm.vert.end(); ++vi)
//      {
//         // qDebug("pos x: %f y: %f",(*vi).P()[0],(*vi).P()[1]);
//        //(*vi).P()[0] = (*vi).P()[0] - (wld * halfw);
//        //(*vi).P()[1] = (*vi).P()[1] - (hld * halfh);
//        //  (*vi).P()[0] = (*vi).P()[0] - totalw/2;
//        //  (*vi).P()[1] = (*vi).P()[1] - totalh/2;
//         // qDebug("after pos x: %f y: %f",(*vi).P()[0],(*vi).P()[1]);
//      }
    }
    // update bounding box, normals
//   Matrix44f rot; rot.SetRotateDeg(180,Point3f(0,1,0));
//   tri::UpdatePosition<CMeshO>::Matrix(m.cm,rot,false);
    tri::UpdateNormal<CMeshO>::PerVertexNormalizedPerFace(m.cm);
    tri::UpdateNormal<CMeshO>::NormalizePerFace(m.cm);
    tri::UpdateBounding<CMeshO>::Box(m.cm);

    CMeshO::VertexIterator vi;


    return true;
}
コード例 #5
0
 bool FilterCreateIso::applyFilter(QAction *filter, MeshDocument &md, RichParameterSet & par, vcg::CallBackPos * cb)
 {
   md.addNewMesh("",this->filterName(ID(filter)));
   MeshModel &m=*(md.mm());
   if(filter->text() == filterName(FP_CREATEISO) )
   {

     SimpleVolume<SimpleVoxel<Scalarm> > 	volume;

     typedef vcg::tri::TrivialWalker<CMeshO, SimpleVolume<SimpleVoxel<Scalarm> >	> MyWalker;
     typedef vcg::tri::MarchingCubes<CMeshO, MyWalker>	MyMarchingCubes;
     MyWalker walker;

     const int gridSize=par.getInt("Resolution");
     // Simple initialization of the volume with some cool perlin noise
     volume.Init(Point3i(gridSize,gridSize,gridSize), Box3m(Point3m(0,0,0),Point3m(1,1,1)));
     for(int i=0;i<gridSize;i++)
       for(int j=0;j<gridSize;j++)
         for(int k=0;k<gridSize;k++)
           volume.Val(i,j,k)=(j-gridSize/2)*(j-gridSize/2)+(k-gridSize/2)*(k-gridSize/2) + i*gridSize/5*(float)math::Perlin::Noise(i*.2,j*.2,k*.2);

     printf("[MARCHING CUBES] Building mesh...");
     MyMarchingCubes mc(m.cm, walker);
     walker.BuildMesh<MyMarchingCubes>(m.cm, volume, mc, (gridSize*gridSize)/10,cb);
     m.UpdateBoxAndNormals();
   }
   return true;
 }
コード例 #6
0
ファイル: filter_ssynth.cpp プロジェクト: Booley/nbis
bool FilterSSynth::applyFilter(QAction*  filter, MeshDocument &md, RichParameterSet & par, vcg::CallBackPos *cb)
{
    QWidget *  parent=(QWidget*)this->parent();
    RichParameter* grammar=par.findParameter(QString("grammar"));
    RichParameter* seed=par.findParameter(QString("seed"));
    int sphereres=par.findParameter("sphereres")->val->getInt();
    this->renderTemplate=GetTemplate(sphereres);
    if(this->renderTemplate!=QString::Null()){
    QString path=ssynth(grammar->val->getString(),-50,seed->val->getInt(),cb);
    if(QFile::exists(path)){
    QFile file(path);
    int mask;
     QString name(file.fileName());
        openX3D(name,*(md.mm()),mask,cb);
    file.remove();
    return true;
        }
        else{
            QString message=QString("An error occurred during the mesh generation:" ).append(path);
            QMessageBox::critical(parent,"Error",message);
                return false;
        }
    }
    else{
        QMessageBox::critical(parent,"Error","Sphere resolution must be between 1 and 4"); return false;
    }
}
コード例 #7
0
ファイル: filter_fractal.cpp プロジェクト: GuoXinxiao/meshlab
void FilterFractal::initParameterSetForFractalDisplacement(QAction *filter, MeshDocument &md, RichParameterSet &par)
{
    bool terrain_filter = (ID(filter) == CR_FRACTAL_TERRAIN);

    if(terrain_filter) {
        par.addParam(new RichInt("steps", 8, "Subdivision steps:", "Defines the detail of the generated terrain. Allowed values are in range [2,9]. Use values from 6 to 9 to obtain reasonable results."));
        par.addParam(new RichDynamicFloat("maxHeight", 0.2, 0, 1, "Max height:", "Defines the maximum perturbation height as a fraction of the terrain's side."));
    } else {
        float diag = md.mm()->cm.bbox.Diag();
        par.addParam(new RichAbsPerc("maxHeight", 0.02 * diag, 0, 0.5*diag, "Max height:", "Defines the maximum height for the perturbation."));
    }

    par.addParam(new RichDynamicFloat("scale", 1, 0, 10, "Scale factor:", "Scales the fractal perturbation in and out. Values larger than 1 mean zoom out; values smaller than one mean zoom in."));
    if (!terrain_filter)
    {
        par.addParam(new RichInt("smoothingSteps", 5, "Normals smoothing steps:", "Face normals will be smoothed to make the perturbation more homogeneous. This parameter represents the number of smoothing steps." ));
    }
    par.addParam(new RichFloat("seed", 2, "Seed:", "By varying this seed, the terrain morphology will change.\nDon't change the seed if you want to refine the current terrain morphology by changing the other parameters."));

    QStringList algList;
    algList << "fBM (fractal Brownian Motion)" << "Standard multifractal" << "Heterogeneous multifractal" << "Hybrid multifractal terrain" << "Ridged multifractal terrain";
    par.addParam(new RichEnum("algorithm", 4, algList, "Algorithm", "The algorithm with which the fractal terrain will be generated."));
    par.addParam(new RichDynamicFloat("octaves", 8.0, 1.0, 20.0, "Octaves:", "The number of Perlin noise frequencies that will be used to generate the terrain. Reasonable values are in range [2,9]."));
    par.addParam(new RichFloat("lacunarity", 4.0, "Lacunarity:", "The gap between noise frequencies. This parameter is used in conjunction with fractal increment to compute the spectral weights that contribute to the noise in each octave."));
    par.addParam(new RichFloat("fractalIncrement", terrain_filter? 0.5 : 0.2, "Fractal increment:", "This parameter defines how rough the generated terrain will be. The range of reasonable values changes according to the used algorithm, however you can choose it in range [0.2, 1.5]."));
    par.addParam(new RichFloat("offset", 0.9, "Offset:", "This parameter controls the multifractality of the generated terrain. If offset is low, then the terrain will be smooth."));
    par.addParam(new RichFloat("gain", 2.5, "Gain:", "Ignored in all the algorithms except the ridged one. This parameter defines how hard the terrain will be."));
    par.addParam(new RichBool("saveAsQuality", false, "Save as vertex quality", "Saves the perturbation value as vertex quality."));
}
コード例 #8
0
ファイル: samplefilter.cpp プロジェクト: GuoXinxiao/meshlab
// The Real Core Function doing the actual mesh processing.
// Move Vertex of a random quantity
bool ExtraSamplePlugin::applyFilter(QAction */*filter*/, MeshDocument &md, RichParameterSet & par, vcg::CallBackPos *cb)
{
	CMeshO &m = md.mm()->cm;
	srand(time(NULL)); 
	const float max_displacement =par.getAbsPerc("Displacement");

	for(unsigned int i = 0; i< m.vert.size(); i++){
		 // Typical usage of the callback for showing a nice progress bar in the bottom. 
		 // First parameter is a 0..100 number indicating percentage of completion, the second is an info string.
		  cb(100*i/m.vert.size(), "Randomly Displacing...");

		float rndax = (float(2.0f*rand())/RAND_MAX - 1.0f ) *max_displacement;
		float rnday = (float(2.0f*rand())/RAND_MAX - 1.0f ) *max_displacement;
		float rndaz = (float(2.0f*rand())/RAND_MAX - 1.0f ) *max_displacement;
		m.vert[i].P() += vcg::Point3f(rndax,rnday,rndaz);
	}
	
	// Log function dump textual info in the lower part of the MeshLab screen. 
	Log("Successfully displaced %i vertices",m.vn);
	
	// to access to the parameters of the filter dialog simply use the getXXXX function of the FilterParameter Class
	if(par.getBool("UpdateNormals"))	
			vcg::tri::UpdateNormal<CMeshO>::PerVertexNormalizedPerFace(m);
	
	vcg::tri::UpdateBounding<CMeshO>::Box(m);
  
	return true;
}
コード例 #9
0
bool AlgoDemoPlugin::applyFilter(QAction *algo, MeshDocument &md,
                             RichParameterSet & par, vcg::CallBackPos *cb)
{

   MeshModel* pm  = md.mm();
   if(pm == NULL) return false;
   
   /*
   MainWindow* mainwindow;
    foreach (QWidget *widget, QApplication::topLevelWidgets())
    {
        MainWindow* mainwindow = dynamic_cast<MainWindow*>(widget);
        if (mainwindow)
        {
            break;
        }
    }
	if (mainwindow == NULL)
        {
            return false;
        }
		
    MeshModel* prm = mainwindow->newProjectAddMesh("resultant mesh","resultant mesh");
		

    GLArea* newGLA = mainwindow->newProject("resultant mesh");

    MeshModel* prm = newGLA->md()->addNewMesh("","resultant mesh",true);
	*/

   MeshModel* prm = md.addNewMesh("","resultant mesh",true);

    pm->cm.vert;         //vertics
    pm->cm.face;            //faces
    pm->cm.selVertVector;   //landmarks


    vcg::tri::Append<CMeshO,CMeshO>::MeshCopy(prm->cm,pm->cm);

    CMeshO::VertexIterator vi;
    for(vi = pm->cm.vert.begin(); vi != pm->cm.vert.end(); ++vi)
    {
        //prm->cm.addVertex (/*const aol::Vec3< RealType > &coords*/);
     // qDebug("pos x: %f y: %f",(*vi).P()[0],(*vi).P()[1]);
    //(*vi).P()[0] = (*vi).P()[0] - (wld * halfw);
    //(*vi).P()[1] = (*vi).P()[1] - (hld * halfh);
    //  (*vi).P()[0] = (*vi).P()[0] - totalw/2;
    //  (*vi).P()[1] = (*vi).P()[1] - totalh/2;
     // qDebug("after pos x: %f y: %f",(*vi).P()[0],(*vi).P()[1]);
    }
    CMeshO::FaceIterator vf;
    for(vf = pm->cm.face.begin(); vf!= pm->cm.face.end(); ++vf)
    {
				//(*vf).V()
    }

    
    return true;
}
コード例 #10
0
ファイル: filter_fractal.cpp プロジェクト: GuoXinxiao/meshlab
void FilterFractal::initParameterSetForCratersGeneration(MeshDocument &md, RichParameterSet &par)
{
    int meshCount = md.meshList.size();

    // tries to detect the target mesh
    MeshModel* target = md.mm();
    MeshModel* samples = md.mm();
    MeshModel* tmpMesh;
    if (samples->cm.fn != 0){ // this is probably not the samples layer
        for(int i=0; i<meshCount; i++)
        {
            tmpMesh = md.meshList.at(i);
            if (tmpMesh->cm.fn == 0)
            {
                samples = tmpMesh;
                break;
            }
        }
    }

    par.addParam(new RichMesh("target_mesh", target, &md, "Target mesh:", "The mesh on which craters will be generated."));
    par.addParam(new RichMesh("samples_mesh", samples, &md, "Samples layer:", "The samples that represent the central points of craters."));
    par.addParam(new RichInt("seed", 0, "Seed:", "The seed with which the random number generator is initialized. The random generator generates radius and depth for each crater into the given range."));
    par.addParam(new RichInt("smoothingSteps", 5, "Normals smoothing steps:", "Vertex normals are smoothed this number of times before generating craters."));

    QStringList algList;
    algList << "f1 (Gaussian)" << "f2 (Multiquadric)" << "f3";
    par.addParam(new RichEnum("rbf", 1, algList, "Radial function:", "The radial function used to generate craters."));

    par.addParam(new RichDynamicFloat("min_radius", 0.1, 0, 1, "Min crater radius:", "Defines the minimum radius of craters in range [0, 1]. Values near 0 mean very small craters."));
    par.addParam(new RichDynamicFloat("max_radius", 0.35, 0, 1, "Max crater radius:", "Defines the maximum radius of craters in range [0, 1]. Values near 1 mean very large craters."));
    par.addParam(new RichDynamicFloat("min_depth", 0.05, 0, 1, "Min crater depth:", "Defines the minimum depth of craters in range [0, 1]."));
    par.addParam(new RichDynamicFloat("max_depth", 0.15, 0, 1, "Max crater depth:", "Defines the maximum depth of craters in range [0, 1]. Values near 1 mean very deep craters."));
    par.addParam(new RichDynamicFloat("elevation", 0.4, 0, 1, "Elevation:", "Defines how much the crater rise itself from the mesh surface, giving an \"impact-effect\"."));

    QStringList blendList;
    blendList << "Exponential blending" << "Linear blending" << "Gaussian blending" << "f3 blending";
    par.addParam(new RichEnum("blend", 3, blendList, "Blending algorithm:", "The algorithm that is used to blend the perturbation towards the mesh surface."));
    par.addParam(new RichDynamicFloat("blendThreshold", 0.8, 0, 1, "Blending threshold:", "The fraction of craters radius beyond which the radial function is replaced with the blending function."));
    par.addParam(new RichBool("successiveImpacts", true, "Successive impacts", "If not checked, the impact-effects of generated craters will be superimposed with each other."));
    par.addParam(new RichBool("ppNoise", true, "Postprocessing noise", "Slightly perturbates the craters with a noise function."));
    par.addParam(new RichBool("invert", false, "Invert perturbation", "If checked, inverts the sign of radial perturbation to create bumps instead of craters."));
    par.addParam(new RichBool("save_as_quality", false, "Save as vertex quality", "Saves the perturbation as vertex quality."));
    return;
}
コード例 #11
0
bool MeshDocumentFromBundler(MeshDocument &md, QString filename_out,QString image_list_filename, QString model_filename)
{
    md.addNewMesh(model_filename,QString("model"));
    std::vector<Shotm> shots;
    const QString path = QFileInfo(filename_out).absolutePath();
    const QString path_im = QFileInfo(image_list_filename).absolutePath()+QString("/");

    std::vector<std::string>   image_filenames;
    vcg::tri::io::ImporterOUT<CMeshO>::Open(md.mm()->cm,shots,image_filenames, qUtf8Printable(filename_out), qUtf8Printable(image_list_filename));
    md.mm()->updateDataMask(MeshModel::MM_VERTCOLOR);

    QString curr_path = QDir::currentPath();
    QFileInfo imi(image_list_filename);

    //
    QStringList image_filenames_q;
    for(unsigned int i  = 0; i < image_filenames.size(); ++i)
    {
        QImageReader sizeImg(QString::fromStdString(image_filenames[i]));
        if(sizeImg.size()==QSize(-1,-1))
            image_filenames_q.push_back(path_im+QString::fromStdString(image_filenames[i]));
        else
            image_filenames_q.push_back(QString::fromStdString(image_filenames[i]));
    }
    QDir::setCurrent(imi.absoluteDir().absolutePath());

    for(size_t i=0 ; i<shots.size() ; i++)
    {
        md.addNewRaster();
        const QString fullpath_image_filename = image_filenames_q[int(i)];
        md.rm()->addPlane(new Plane(fullpath_image_filename,Plane::RGBA));
        int count=fullpath_image_filename.count('\\');
        if (count==0)
        {
            count=fullpath_image_filename.count('/');
            md.rm()->setLabel(fullpath_image_filename.section('/',count,1));
        }
        else
            md.rm()->setLabel(fullpath_image_filename.section('\\',count,1));
        md.rm()->shot = shots[i];
    }
    QDir::setCurrent(curr_path);

    return true;
}
コード例 #12
0
// Core 
bool FilterWebExportVMustPlugin::applyFilter(QAction *filter, MeshDocument &md, RichParameterSet & /*parent*/, vcg::CallBackPos * cb)
{
	if (ID(filter) == FP_WEB_EXPORT)
	{
		CMeshO &m=md.mm()->cm;

		QNetworkAccessManager NAManager;

		// STEP 1: check if the server works (by requesting the list of application templates)
		// (note that this list is not used)
		QUrl urlTest ("http://pipeline.v-must.net/api/v1/bundles");

		QNetworkRequest request1(urlTest);

		QNetworkReply *reply1 = NAManager.get(request1);
		QTimer timer;
		timer.setSingleShot(true);
		timer.start(5000);

		QEventLoop eventLoop;
		connect(reply1, SIGNAL(finished()), &eventLoop, SLOT(quit()));
		connect(&timer, SIGNAL(timeout()), &eventLoop, SLOT(quit()));
		eventLoop.exec();   // block the http request for 5 seconds

		delete reply1;

		if (timer.isActive())
		{
			timer.stop();

			// STEP 2: preparing the bucket for the processing

			QUrl urlBucket("http://pipeline.v-must.net/api/v1/buckets");
			QNetworkRequest request2(urlBucket);
			request2.setRawHeader("Accept", "application/json");
			request2.setRawHeader("Accept-Encoding", "gzip, deflate, compress");
			request2.setRawHeader("Content-Type", "application/octet-stream");
			request2.setRawHeader("Host", "pipelineserver.ltd");
			request2.setRawHeader("X-Filename", "test.ply");

			QNetworkReply *reply2 = NAManager.get(request2);
			connect(reply2, SIGNAL(finished()), &eventLoop, SLOT(quit()));
			eventLoop.exec();   // block the http request

			// STEP 3: launch the processing according to the selected template
		}
		else
		{
			QMessageBox::warning(0, tr("V-Must CIF API"), tr("Server is time out. Please, re-try later."));
		}



	}

	return true;
}
コード例 #13
0
void DecorateBackgroundPlugin::decorateDoc(QAction *a, MeshDocument &m, RichParameterSet * parset,GLArea *gla, QPainter *, GLLogStream &)
{
  static QString lastname("unitialized");
	switch(ID(a))
	{
	  case DP_SHOW_CUBEMAPPED_ENV :
		{
      if(!cm.IsValid() || (lastname != cubemapFileName ) )
      {
        qDebug( "Current CubeMapPath Dir: %s ",qPrintable(cubemapFileName));
        glewInit();
        bool ret = cm.Load(qPrintable(cubemapFileName));
        lastname=cubemapFileName;
        if(! ret ) return;
        //QMessageBox::warning(gla,"Cubemapped background decoration","Warning unable to load cube map images: " + cubemapFileName );
        cm.radius=10;
      }
			if(!cm.IsValid()) return;

      Matrix44f tr;
			glGetv(GL_MODELVIEW_MATRIX,tr);			
			// Remove the translation from the current matrix by simply padding the last column of the matrix
      tr.SetColumn(3,Point4f(0,0,0,1.0));
			//Remove the scaling from the the current matrix by adding an inverse scaling matrix
			float scale = 1.0/pow(tr.Determinant(),1.0f/3.0f);
			Matrix44f Scale; 
			Scale.SetDiagonal(scale);
			tr=tr*Scale;

			glMatrixMode(GL_PROJECTION);
			glPushMatrix();
			glMatrixMode(GL_MODELVIEW);
			glPushMatrix();
				cm.DrawEnvCube(tr);
			glPopMatrix();
			glMatrixMode(GL_PROJECTION);
			glPopMatrix();
			glMatrixMode(GL_MODELVIEW);
    } break;
  case DP_SHOW_GRID :
    {
      emit this->askViewerShot("me");
      Box3f bb=m.bbox();
      float scaleBB = parset->getFloat(BoxRatioParam());
      float majorTick = parset->getFloat(GridMajorParam());
      float minorTick = parset->getFloat(GridMinorParam());
      bool gridSnap = parset->getBool(GridSnapParam());
      bool backFlag = parset->getBool(GridBackParam());
      bool shadowFlag = parset->getBool(ShowShadowParam());
      Color4b backColor = parset->getColor4b(GridColorBackParam());
      Color4b frontColor = parset->getColor4b(GridColorFrontParam());
      bb.Offset((bb.max-bb.min)*(scaleBB-1.0));
      DrawGriddedCube(*m.mm(),bb,majorTick,minorTick,gridSnap,backFlag,shadowFlag,backColor,frontColor,gla);
    } break;
  }
}
コード例 #14
0
ファイル: filter_rangemap.cpp プロジェクト: CKehl/meshlab
// Core Function doing the actual mesh processing.
bool RangeMapPlugin::applyFilter(QAction *filter, MeshDocument &m, FilterParameterSet & par, vcg::CallBackPos *cb)
{
	CMeshO::FaceIterator   fi;

	switch(ID(filter))
  {
		case FP_SELECTBYANGLE : 
		{
			bool usecam = par.getBool("usecamera");
			Point3f viewpoint = par.getPoint3f("viewpoint");	

			// if usecamera but mesh does not have one
			if( usecam && !m.mm()->hasDataMask(MeshModel::MM_CAMERA) ) 
			{
				errorMessage = "Mesh has not a camera that can be used to compute view direction. Please set a view direction."; // text
				return false;
			}
			if(usecam)
			{
				viewpoint = m.mm()->cm.shot.GetViewPoint();
			}

			// angle threshold in radians
			float limit = cos( math::ToRad(par.getDynamicFloat("anglelimit")) );
			Point3f viewray;

			for(fi=m.mm()->cm.face.begin();fi!=m.mm()->cm.face.end();++fi)
				if(!(*fi).IsD())
				{
					viewray = viewpoint - Barycenter(*fi);
					viewray.Normalize();

					if((viewray.dot((*fi).N().Normalize())) < limit)
						fi->SetS();
				}

		}
		break;

	}

	return true;
}
コード例 #15
0
ファイル: filter_csg.cpp プロジェクト: yuhan120483/dcba
void FilterCSG::initParameterSet(QAction *action, MeshDocument & md, RichParameterSet & parlst)
{
    switch (ID(action)) {
    case FP_CSG:
        {
            MeshModel *target = md.mm();
            foreach (target, md.meshList)
                if (target != md.mm())
                    break;

            CMeshO::ScalarType mindim = min(md.mm()->cm.bbox.Dim().V(md.mm()->cm.bbox.MinDim()),
                                            target->cm.bbox.Dim().V(target->cm.bbox.MinDim()));

            parlst.addParam(new RichMesh("FirstMesh", md.mm(), &md, "First Mesh",
                                         "The first operand of the CSG operation"));
            parlst.addParam(new RichMesh("SecondMesh", target, &md, "Second Mesh",
                                         "The second operand of the CSG operation"));
            parlst.addParam(new RichAbsPerc("Delta", mindim / 100.0, 0, mindim,
                                            "Spacing between sampling lines",
                                            "This parameter controls the accuracy of the result and the speed of the computation."
                                            "The time and memory needed to perform the operation usually scale as the reciprocal square of this value."
                                            "For optimal results, this value should be at most half the the smallest feature (i.e. the highest frequency) you want to reproduce."));
            parlst.addParam(new RichInt("SubDelta", 32, "Discretization points per sample interval",
                                        "This is the number of points between the sampling lines to which the vertices can be rounded."
                                        "Increasing this can marginally increase the precision and decrease the speed of the operation."));
            parlst.addParam(new RichEnum("Operator", 0,
                                         QStringList() << "Intersection" << "Union" << "Difference", "Operator",
                                         "Intersection takes the volume shared between the two meshes; "
                                         "Union takes the volume included in at least one of the two meshes; "
                                         "Difference takes the volume included in the first mesh but not in the second one"));
            parlst.addParam(new RichBool("Extended", false, "Extended Marching Cubes",
                                         "Use extended marching cubes for surface reconstruction. "
                                         "It tries to improve the quality of the mesh by reconstructing the sharp features "
                                         "using the information in vertex normals"));
        }
        break;

    default:
        assert(0);
    }
}
コード例 #16
0
ファイル: cleanfilter.cpp プロジェクト: yuhan120483/dcba
void CleanFilter::initParameterSet(QAction *action,MeshDocument &md, RichParameterSet & parlst)
{ 
	pair<float,float> qualityRange;
  switch(ID(action))
  {
    case FP_BALL_PIVOTING :
		  parlst.addParam(new RichAbsPerc("BallRadius",(float)maxDiag1,0,md.mm()->cm.bbox.Diag(),"Pivoting Ball radius (0 autoguess)","The radius of the ball pivoting (rolling) over the set of points. Gaps that are larger than the ball radius will not be filled; similarly the small pits that are smaller than the ball radius will be filled."));
		  parlst.addParam(new RichFloat("Clustering",20.0f,"Clustering radius (% of ball radius)","To avoid the creation of too small triangles, if a vertex is found too close to a previous one, it is clustered/merged with it."));		  
		  parlst.addParam(new RichFloat("CreaseThr", 90.0f,"Angle Threshold (degrees)","If we encounter a crease angle that is too large we should stop the ball rolling"));
		  parlst.addParam(new RichBool("DeleteFaces",false,"Delete intial set of faces","if true all the initial faces of the mesh are deleted and the whole surface is rebuilt from scratch, other wise the current faces are used as a starting point. Useful if you run multiple times the algorithm with an incrasing ball radius."));
		  break;
    case FP_REMOVE_ISOLATED_DIAMETER:	 
		  parlst.addParam(new RichAbsPerc("MinComponentDiag",md.mm()->cm.bbox.Diag()/10.0,0,md.mm()->cm.bbox.Diag(),"Enter max diameter of isolated pieces","Delete all the connected components (floating pieces) with a diameter smaller than the specified one"));
		  break;
    case FP_REMOVE_ISOLATED_COMPLEXITY:	 
		  parlst.addParam(new RichInt("MinComponentSize",(int)minCC,"Enter minimum conn. comp size:","Delete all the connected components (floating pieces) composed by a number of triangles smaller than the specified one"));
		  break;
    case FP_REMOVE_WRT_Q:
          qualityRange=tri::Stat<CMeshO>::ComputePerVertexQualityMinMax(md.mm()->cm);
		  parlst.addParam(new RichAbsPerc("MaxQualityThr",(float)val1, qualityRange.first, qualityRange.second,"Delete all vertices with quality under:"));
		  break;
	case FP_MERGE_CLOSE_VERTEX :
		  parlst.addParam(new RichAbsPerc("Threshold",md.mm()->cm.bbox.Diag()/10000.0,0,md.mm()->cm.bbox.Diag()/100.0,"Merging distance","All the vertices that closer than this threshold are merged together. Use very small values, default values is 1/10000 of bounding box diagonal. "));
		  break;
    case FP_SNAP_MISMATCHED_BORDER:
    parlst.addParam(new RichFloat("EdgeDistRatio",1/100.0f,"Edge Distance Ratio", "Collapse edge when the edge / distance ratio is greater than this value. E.g. for default value 1000 two straight border edges are collapsed if the central vertex dist from the straight line composed by the two edges less than a 1/1000 of the sum of the edges lenght. Larger values enforce that only vertexes very close to the line are removed."));
    parlst.addParam(new RichBool("UnifyVertices",true,"UnifyVertices","if true the snap vertices are weld together."));
      break;
    case FP_REMOVE_TVERTEX_COLLAPSE :
    case FP_REMOVE_TVERTEX_FLIP :
       parlst.addParam(new RichFloat(
               "Threshold", 40, "Ratio", "Detects faces where the base/height ratio is lower than this value"));
       parlst.addParam(new RichBool(
               "Repeat", true, "Iterate until convergence", "Iterates the algorithm until it reaches convergence"));
       break;
    case FP_REMOVE_NON_MANIF_VERT :
       parlst.addParam(new RichFloat("VertDispRatio", 0, "Vertex Displacement Ratio", "When a vertex is split it is moved along the average vector going from its position to the baricyenter of the FF connected faces sharing it"));
       break;
  default: break; // do not add any parameter for the other filters
  }
}
コード例 #17
0
ファイル: filter_autoalign.cpp プロジェクト: Jerdak/meshlab
// This function define the needed parameters for each filter. Return true if the filter has some parameters
// it is called every time, so you can set the default value of parameters according to the mesh
// For each parmeter you need to define,
// - the name of the parameter,
// - the string shown in the dialog
// - the default value
// - a possibly long string describing the meaning of that parameter (shown as a popup help in the dialog)
void FilterAutoalign::initParameterSet(QAction *action,MeshDocument & md/*m*/, RichParameterSet & parlst)
{
   MeshModel *target;
   switch(ID(action))	 {
    case FP_AUTOALIGN :
        target= md.mm();
        foreach (target, md.meshList)
            if (target != md.mm())  break;

        parlst.addParam(new RichMesh ("FirstMesh", md.mm(),&md, "First Mesh",
                        "The mesh were the coplanar bases are sampled (it will contain the trasformation)"));
        parlst.addParam(new RichMesh ("SecondMesh", target,&md, "Second Mesh",
                        "The mesh were similar coplanar based are searched."));
        parlst.addParam(new RichFloat("overlapping",0.5f,"Estimated fraction of the\n first mesh overlapped by the second"));
        parlst.addParam(new RichFloat("tolerance [0.0,1.0]",0.3f,"Error tolerance"));
     break;
       case FP_BEST_ROTATION :
       target= md.mm();
       foreach (target, md.meshList)
       if (target != md.mm())  break;

       parlst.addParam(new RichMesh ("FirstMesh", md.mm(),&md, "First Mesh",
                       "The mesh that will be moved"));
       parlst.addParam(new RichMesh ("SecondMesh", target,&md, "Second Mesh",
                       "The mesh that will be kept fixed."));
       parlst.addParam(new RichInt("GridSize",10,"Grid Size", "The size of the uniform grid that is used for searching the best translation for a given rotation"));
       parlst.addParam(new RichInt("Rotation Num",64,"RotationNumber", "sss"));
       break;

   default: break; // do not add any parameter for the other filters
  }
}
コード例 #18
0
// This function define the needed parameters for each filter. Return true if the filter has some parameters
// it is called every time, so you can set the default value of parameters according to the mesh
// For each parameter you need to define, 
// - the name of the parameter, 
// - the string shown in the dialog 
// - the default value
// - a possibly long string describing the meaning of that parameter (shown as a popup help in the dialog)
void FilterPerceptualMetric::initParameterSet(QAction *action, MeshDocument & md, FilterParameterSet & parlst) 
{
	switch(ID(action))	 
	{
		case FP_ROUGHNESS_MULTISCALE :
		{
			MeshModel *refmesh = md.mm();
			foreach (refmesh, md.meshList) 
				if (refmesh != md.mm())  break;

			parlst.addMesh("ReferenceMesh", refmesh, "Reference Mesh",
				"The original mesh.");
			parlst.addMesh("InputMesh", md.mm(), "Mesh",
				"The mesh where the perceptual impairment of the processing is evaluated.");
		} break;
		
		case FP_ROUGHNESS_SMOOTHING :
		{
			MeshModel *refmesh = md.mm();
			foreach (refmesh, md.meshList) 
				if (refmesh != md.mm())  break;

			parlst.addMesh("ReferenceMesh", refmesh, "Reference Mesh",
				"The original mesh.");
			parlst.addMesh("InputMesh", md.mm(), "Mesh",
				"The mesh where the perceptual impairment of the processing is evaluated.");
		} break;

		case FP_STRAIN_ENERGY :  
		{
			MeshModel *refmesh = md.mm();
			foreach (refmesh, md.meshList) 
				if (refmesh != md.mm())  break;
		
			parlst.addMesh("ReferenceMesh", refmesh, "Reference Mesh",
				"The original mesh.");
			parlst.addMesh("InputMesh", md.mm(), "Mesh",
				"The mesh where the perceptual impairment of the processing is evaluated.");
		} break;

		default : assert(0); 
	}
}
コード例 #19
0
ファイル: filter_measure.cpp プロジェクト: Booley/nbis
// This function define the needed parameters for each filter. 
void FilterMeasurePlugin::initParameterSet(QAction *action, MeshDocument &m, RichParameterSet & par)
{
	 switch(ID(action))	 
	 {
   case FP_MEASURE_FACE_QUALITY_HISTOGRAM :
   case FP_MEASURE_VERTEX_QUALITY_HISTOGRAM:
         {
         pair<float,float> minmax = tri::Stat<CMeshO>::ComputePerVertexQualityMinMax(m.mm()->cm);
         par.addParam(new RichFloat("minVal",minmax.first,"Min","The value that is used as a lower bound for the set of bins (all the value smaller this one will be put in the first bin)"));
         par.addParam(new RichFloat("maxVal",minmax.second,"Max","The value that is used as a upper bound for the set of bins (all the value over this one will be put in the last bin)"));
         par.addParam(new RichInt("binNum",20,"Number of bins","Number of bins in which the range of values is subdivided"));
        } break;
	}
}
コード例 #20
0
bool FilterScreenedPoissonPlugin::applyFilter( const QString& filterName,MeshDocument& md,EnvWrap& env, vcg::CallBackPos* cb)
{
  if (filterName == "Screened Poisson Surface Reconstruction")
  {
    MeshModel *mm =md.mm();
    MeshModel *pm =md.addNewMesh("","Poisson mesh",false);
    md.setVisible(pm->id(),false);

    pm->updateDataMask(MeshModel::MM_VERTQUALITY);
    PoissonParam<Scalarm> pp;

    MeshModelPointStream<Scalarm> meshStream(mm->cm);
    MeshDocumentPointStream<Scalarm> documentStream(md);

    pp.MaxDepthVal = env.evalInt("depth");
    pp.FullDepthVal = env.evalInt("fullDepth");
    pp.CGDepthVal= env.evalInt("cgDepth");
    pp.ScaleVal = env.evalFloat("scale");
    pp.SamplesPerNodeVal = env.evalFloat("samplesPerNode");
    pp.PointWeightVal = env.evalFloat("pointWeight");
    pp.ItersVal = env.evalInt("iters");
    pp.ConfidenceFlag = env.evalBool("confidence");
    pp.NormalWeightsFlag = env.evalBool("nWeights");
    pp.DensityFlag = true;
    if(env.evalBool("visibleLayer"))
    {
      MeshModel *m=0;
      while(m=md.nextVisibleMesh(m))
        PoissonClean(m->cm, (pp.ConfidenceFlag || pp.NormalWeightsFlag));

      Execute<Scalarm>(&documentStream,pm->cm,pp,cb);
    }
    else
    {
      PoissonClean(mm->cm, (pp.ConfidenceFlag || pp.NormalWeightsFlag));
      Execute<Scalarm>(&meshStream,pm->cm,pp,cb);
    }
    pm->UpdateBoxAndNormals();
    md.setVisible(pm->id(),true);

    return true;
  }
  return false;
}
コード例 #21
0
ファイル: filter_sdfgpu.cpp プロジェクト: laiyinping/meshlab
void SdfGpuPlugin::setupMesh(MeshDocument& md, ONPRIMITIVE onPrimitive )
{
    MeshModel* mm = md.mm();
    CMeshO& m     = mm->cm;


    //If on vertices, do some cleaning first
    if( onPrimitive == ON_VERTICES )
    {
      int dup = tri::Clean<CMeshO>::RemoveDuplicateVertex(m);
      int unref =  tri::Clean<CMeshO>::RemoveUnreferencedVertex(m);
      if (dup > 0 || unref > 0) Log("Removed %i duplicate and %i unreferenced vertices\n",dup,unref);
    }

    //Updating mesh metadata
    tri::UpdateBounding<CMeshO>::Box(m);
    vcg::tri::Allocator<CMeshO>::CompactVertexVector(m);
    vcg::tri::Allocator<CMeshO>::CompactFaceVector(m);
    vcg::tri::UpdateNormals<CMeshO>::PerVertexAngleWeighted(m);


    //Enable & Reset the necessary attributes
    switch(onPrimitive)
    {
      case ON_VERTICES:
        mm->updateDataMask(MeshModel::MM_VERTQUALITY);
        tri::UpdateQuality<CMeshO>::VertexConstant(m,0);
        break;
      case ON_FACES:
        mm->updateDataMask(MeshModel::MM_FACEQUALITY);
        mm->updateDataMask(MeshModel::MM_FACENORMAL);
        mm->updateDataMask(MeshModel::MM_FACECOLOR);
        tri::UpdateQuality<CMeshO>::FaceConstant(m,0);
        break;
    }

 if(!vcg::tri::HasPerVertexAttribute(m,"maxQualityDir") && onPrimitive == ON_VERTICES)
       mMaxQualityDirPerVertex = vcg::tri::Allocator<CMeshO>::AddPerVertexAttribute<Point3f>(m,std::string("maxQualityDir"));
  else if(!vcg::tri::HasPerFaceAttribute(m,"maxQualityDir") && onPrimitive == ON_FACES)
        mMaxQualityDirPerFace = vcg::tri::Allocator<CMeshO>::AddPerFaceAttribute<Point3f>(m,std::string("maxQualityDir"));


}
コード例 #22
0
ファイル: filter_create.cpp プロジェクト: Booley/nbis
// The Real Core Function doing the actual mesh processing.
bool FilterCreate::applyFilter(QAction *filter, MeshDocument &md, RichParameterSet & par, vcg::CallBackPos * /*cb*/)
{
    MeshModel &m=(*md.mm());
  switch(ID(filter))	 {
    case CR_TETRAHEDRON :
      vcg::tri::Tetrahedron<CMeshO>(m.cm);
      break;
    case CR_ICOSAHEDRON:
      vcg::tri::Icosahedron<CMeshO>(m.cm);
      break;
    case CR_DODECAHEDRON:
      vcg::tri::Dodecahedron<CMeshO>(m.cm);
			m.updateDataMask(MeshModel::MM_POLYGONAL);
      break;
    case CR_OCTAHEDRON:
      vcg::tri::Octahedron<CMeshO>(m.cm);
      break;
    case CR_SPHERE:
      vcg::tri::Sphere<CMeshO>(m.cm);
      break;
    case CR_BOX:
    {
      float sz=par.getFloat("size");
      vcg::Box3f b(vcg::Point3f(1,1,1)*(sz/2),vcg::Point3f(1,1,1)*(-sz/2));
      vcg::tri::Box<CMeshO>(m.cm,b);
			m.updateDataMask(MeshModel::MM_POLYGONAL);

      break;
    }
    case CR_CONE:
      float r0=par.getFloat("r0");
      float r1=par.getFloat("r1");
      float h=par.getFloat("h");
      int subdiv=par.getInt("subdiv");
      vcg::tri::Cone<CMeshO>(m.cm,r0,r1,h,subdiv);
      break;
   }
 	 vcg::tri::UpdateBounding<CMeshO>::Box(m.cm);
   vcg::tri::UpdateNormals<CMeshO>::PerVertexNormalizedPerFaceNormalized(m.cm);
	return true;
}
コード例 #23
0
// This function define the needed parameters for each filter. Return true if the filter has some parameters
// it is called every time, so you can set the default value of parameters according to the mesh
// For each parameter you need to define, 
// - the name of the parameter, 
// - the string shown in the dialog 
// - the default value
// - a possibly long string describing the meaning of that parameter (shown as a popup help in the dialog)
void FilterWebExportVMustPlugin::initParameterSet(QAction *action, MeshDocument &md, RichParameterSet & parlst) 
{
	int meshCount = md.meshList.size();

	// tries to detect the target mesh
	MeshModel* target = md.mm();
  
	parlst.addParam(new RichMesh("target_mesh", target, &md, "Target mesh:", "The mesh to export."));

	templateNamesHR << "Basic Viewer" << "Standard Viewer" << "Fullsize Viewer" << "Radiance Scaling" <<
		"Walk Through" << "POP Geometry" << "Nexus conversion";
	parlst.addParam(new RichEnum("template", 1, templateNamesHR, "Web Template:", "Web template to use."));
	parlst.addParam(new RichString("notification_email", "*****@*****.**", "Notification email:", 
		"A link to download the exported model will be send at this email address."));

	// names to be used with the CIF API
	templateNames << "basic" << "standard" << "fullsize" << "radianceScaling" << "walkthrough" 
		<< "pop" << "nexus";

	return;
}
コード例 #24
0
bool SampleXMLFilterPlugin::applyFilter( const QString& filterName,MeshDocument& md,EnvWrap& env, vcg::CallBackPos* cb)
{
	if (filterName == "Random vertex displacement")
	{
		MeshModel &m=*md.mm();
		srand(time(NULL)); 
		const float max_displacement =env.evalFloat("Displacement");

		for(unsigned int i = 0; i< m.cm.vert.size(); i++)
		{
			// Typical usage of the callback for showing a nice progress bar in the bottom. 
		//	// First parameter is a 0..100 number indicating percentage of completion, the second is an info string.
			cb(100*i/m.cm.vert.size(), "Randomly Displacing...");

			float rndax = (float(2.0f*rand())/RAND_MAX - 1.0f ) *max_displacement;
			float rnday = (float(2.0f*rand())/RAND_MAX - 1.0f ) *max_displacement;
			float rndaz = (float(2.0f*rand())/RAND_MAX - 1.0f ) *max_displacement;
			m.cm.vert[i].P() += vcg::Point3f(rndax,rnday,rndaz);
			//if ( i % 1000 == 0)
			QList<int> meshlist;
			meshlist << m.id();
			md.updateRenderStateMeshes(meshlist,int(MeshModel::MM_VERTCOORD));
			if (intteruptreq)
				return true;
		}

		//// Log function dump textual info in the lower part of the MeshLab screen. 
		Log("Successfully displaced %i vertices",m.cm.vn);

		//// to access to the parameters of the filter dialog simply use the getXXXX function of the FilterParameter Class
		if(env.evalBool("UpdateNormals"))	
			vcg::tri::UpdateNormals<CMeshO>::PerVertexNormalizedPerFace(m.cm);
		
 		vcg::tri::UpdateBounding<CMeshO>::Box(m.cm);

		return true;
	}
	return false;
}
コード例 #25
0
// This function define the needed parameters for each filter. Return true if the filter has some parameters
// it is called every time, so you can set the default value of parameters according to the mesh
// For each parmeter you need to define,
// - the name of the parameter,
// - the string shown in the dialog
// - the default value
// - a possibly long string describing the meaning of that parameter (shown as a popup help in the dialog)
void FilterAutoalign::initParameterSet(QAction *action,MeshDocument & md/*m*/, RichParameterSet & parlst)
{
   MeshModel *target;
   switch(ID(action))	 {
    case FP_ALIGN_4PCS :
        target= md.mm();
        foreach (target, md.meshList)
            if (target != md.mm())  break;

        parlst.addParam(new RichMesh ("fixMesh", md.mm(),&md, "Fixed Mesh",
                        "The mesh were the coplanar bases are sampled (it will contain the trasformation)"));
        parlst.addParam(new RichMesh ("movMesh", target,&md, "Moving Mesh",
                        "The mesh were similar coplanar based are searched."));
        parlst.addParam(new RichFloat("overlap",0.5f,"Overlap %","Estimated fraction of the\n first mesh overlapped by the second"));
        parlst.addParam(new RichInt("sampleNum",1000,"Sample Num"));
        parlst.addParam(new RichFloat("tolerance",0.3f,"Error tolerance",""));
        parlst.addParam(new RichBool("showSample",true,"show subsamples",""));
        parlst.addParam(new RichInt("randSeed",0,"Random Seed","0 means the random generator it is intializised with internal clock to guarantee different result every time"));
     break;

       case FP_BEST_ROTATION :
       target= md.mm();
       foreach (target, md.meshList)
       if (target != md.mm())  break;

       parlst.addParam(new RichMesh ("fixMesh", md.mm(),&md, "Fix Mesh",
                       "The mesh that will be moved"));
       parlst.addParam(new RichMesh ("movMesh", target,&md, "Mov Mesh",
                       "The mesh that will be kept fixed."));
       parlst.addParam(new RichInt("searchRange",6,"Search Range", "The size of the uniform grid that is used for searching the best translation for a given rotation"));
       parlst.addParam(new RichInt("sampleSize",5000,"Sample Size", "The size of the uniform grid that is used for searching the best translation for a given rotation"));
       parlst.addParam(new RichInt("gridSize",100000,"Grid Size", "The size of the uniform grid that is used for searching the best translation for a given rotation"));
       parlst.addParam(new RichInt("RotationNumber",64,"Rotation Number", "sss"));
       break;

   default: break; // do not add any parameter for the other filters
  }
}
コード例 #26
0
ファイル: filter_measure.cpp プロジェクト: mylxiaoyi/meshlab
// Core Function doing the actual mesh processing.
bool FilterMeasurePlugin::applyFilter( const QString& filterName,MeshDocument& md,EnvWrap& env, vcg::CallBackPos * /*cb*/ )
{
    if (filterName == "Compute Topological Measures")
    {
        CMeshO &m=md.mm()->cm;
        tri::Allocator<CMeshO>::CompactFaceVector(m);
        tri::Allocator<CMeshO>::CompactVertexVector(m);
        md.mm()->updateDataMask(MeshModel::MM_FACEFACETOPO);
        md.mm()->updateDataMask(MeshModel::MM_VERTFACETOPO);

        int edgeManifNum = tri::Clean<CMeshO>::CountNonManifoldEdgeFF(m,true);
        int faceEdgeManif = tri::UpdateSelection<CMeshO>::FaceCount(m);
        tri::UpdateSelection<CMeshO>::VertexClear(m);
        tri::UpdateSelection<CMeshO>::FaceClear(m);

        int vertManifNum = tri::Clean<CMeshO>::CountNonManifoldVertexFF(m,true);
        tri::UpdateSelection<CMeshO>::FaceFromVertexLoose(m);
        int faceVertManif = tri::UpdateSelection<CMeshO>::FaceCount(m);
        int edgeNum=0,borderNum=0;
        tri::Clean<CMeshO>::CountEdges(m, edgeNum, borderNum);
        int holeNum;
        Log("V: %6i E: %6i F:%6i",m.vn,edgeNum,m.fn);
        int unrefVertNum = tri::Clean<CMeshO>::CountUnreferencedVertex(m);
        Log("Unreferenced Vertices %i",unrefVertNum);
        Log("Boundary Edges %i",borderNum);

        int connectedComponentsNum = tri::Clean<CMeshO>::CountConnectedComponents(m);
        Log("Mesh is composed by %i connected component(s)\n",connectedComponentsNum);

        if(edgeManifNum==0 && vertManifNum==0) {
            Log("Mesh is two-manifold ");
        }

        if(edgeManifNum!=0) Log("Mesh has %i non two manifold edges and %i faces are incident on these edges\n",edgeManifNum,faceEdgeManif);

        if(vertManifNum!=0) Log("Mesh has %i non two manifold vertexes and %i faces are incident on these vertices\n",vertManifNum,faceVertManif);

        // For Manifold meshes compute some other stuff
        if(vertManifNum==0 && edgeManifNum==0)
        {
            holeNum = tri::Clean<CMeshO>::CountHoles(m);
            Log("Mesh has %i holes",holeNum);

            int genus = tri::Clean<CMeshO>::MeshGenus(m.vn-unrefVertNum, edgeNum, m.fn, holeNum, connectedComponentsNum);
            Log("Genus is %i",genus);
        }
        else
        {
            Log("Mesh has a undefined number of holes (non 2-manifold mesh)");
            Log("Genus is undefined (non 2-manifold mesh)");
        }

        return true;
    }

    /************************************************************/
    if (filterName == "Compute Topological Measures for Quad Meshes")
    {
        CMeshO &m=md.mm()->cm;
        md.mm()->updateDataMask(MeshModel::MM_FACEFACETOPO);
        md.mm()->updateDataMask(MeshModel::MM_FACEQUALITY);

        if (! tri::Clean<CMeshO>::IsFFAdjacencyConsistent(m)) {
            this->errorMessage = "Error: mesh has a not consistent FF adjacency";
            return false;
        }
        if (! tri::Clean<CMeshO>::HasConsistentPerFaceFauxFlag(m)) {

            this->errorMessage = "QuadMesh problem: mesh has a not consistent FauxEdge tagging";
            return false;
        }

        int nQuads = tri::Clean<CMeshO>::CountBitQuads(m);
        int nTris = tri::Clean<CMeshO>::CountBitTris(m);
        int nPolys = tri::Clean<CMeshO>::CountBitPolygons(m);
        int nLargePolys = tri::Clean<CMeshO>::CountBitLargePolygons(m);
        if(nLargePolys>0) nQuads=0;

        Log("Mesh has %8i triangles \n",nTris);
        Log("         %8i quads \n",nQuads);
        Log("         %8i polygons \n",nPolys);
        Log("         %8i large polygons (with internal faux vertexes)",nLargePolys);

        if (! tri::Clean<CMeshO>::IsBitTriQuadOnly(m)) {
            this->errorMessage = "QuadMesh problem: the mesh is not TriQuadOnly";
            return false;
        }

        //
        //   i
        //
        //
        //   i+1     i+2
        tri::UpdateFlags<CMeshO>::FaceClearV(m);
        Distribution<float> AngleD; // angle distribution
        Distribution<float> RatioD; // ratio distribution
        tri::UpdateFlags<CMeshO>::FaceClearV(m);
        for(CMeshO::FaceIterator fi=m.face.begin(); fi!=m.face.end(); ++fi)
            if(!fi->IsV())
            {
                fi->SetV();
                // Collect the vertices
                Point3f qv[4];
                bool quadFound=false;
                for(int i=0; i<3; ++i)
                {
                    if((*fi).IsF(i) && !(*fi).IsF((i+1)%3) && !(*fi).IsF((i+2)%3) )
                    {
                        qv[0] = fi->V0(i)->P(),
                                qv[1] = fi->FFp(i)->V2( fi->FFi(i) )->P(),
                                        qv[2] = fi->V1(i)->P(),
                                                qv[3] = fi->V2(i)->P();
                        quadFound=true;
                    }
                }
                assert(quadFound);
                for(int i=0; i<4; ++i)
                    AngleD.Add(fabs(90-math::ToDeg(Angle(qv[(i+0)%4] - qv[(i+1)%4], qv[(i+2)%4] - qv[(i+1)%4]))));
                float edgeLen[4];

                for(int i=0; i<4; ++i)
                    edgeLen[i]=Distance(qv[(i+0)%4],qv[(i+1)%4]);
                std::sort(edgeLen,edgeLen+4);
                RatioD.Add(edgeLen[0]/edgeLen[3]);
            }

        Log("Right Angle Discrepancy  Avg %4.3f Min %4.3f Max %4.3f StdDev %4.3f Percentile 0.05 %4.3f percentile 95 %4.3f",
            AngleD.Avg(), AngleD.Min(), AngleD.Max(),AngleD.StandardDeviation(),AngleD.Percentile(0.05),AngleD.Percentile(0.95));

        Log("Quad Ratio   Avg %4.3f Min %4.3f Max %4.3f", RatioD.Avg(), RatioD.Min(), RatioD.Max());
        return true;
    }
    /************************************************************/
    if(filterName == "Compute Geometric Measures")
    {
        CMeshO &m=md.mm()->cm;
        tri::Inertia<CMeshO> I(m);
        float Area = tri::Stat<CMeshO>::ComputeMeshArea(m);
        float Volume = I.Mass();
        Log("Mesh Bounding Box Size %f %f %f", m.bbox.DimX(), m.bbox.DimY(), m.bbox.DimZ());
        Log("Mesh Bounding Box Diag %f ", m.bbox.Diag());
        Log("Mesh Volume  is %f", Volume);
        Log("Mesh Surface is %f", Area);
        Point3f bc=tri::Stat<CMeshO>::ComputeShellBarycenter(m);
        Log("Thin shell barycenter  %9.6f  %9.6f  %9.6f",bc[0],bc[1],bc[2]);

        if(Volume<=0) Log("Mesh is not 'solid', no information on barycenter and inertia tensor.");
        else
        {
            Log("Center of Mass  is %f %f %f", I.CenterOfMass()[0], I.CenterOfMass()[1], I.CenterOfMass()[2]);

            Matrix33f IT;
            I.InertiaTensor(IT);
            Log("Inertia Tensor is :");
            Log("    | %9.6f  %9.6f  %9.6f |",IT[0][0],IT[0][1],IT[0][2]);
            Log("    | %9.6f  %9.6f  %9.6f |",IT[1][0],IT[1][1],IT[1][2]);
            Log("    | %9.6f  %9.6f  %9.6f |",IT[2][0],IT[2][1],IT[2][2]);

            Matrix33f PCA;
            Point3f pcav;
            I.InertiaTensorEigen(PCA,pcav);
            Log("Principal axes are :");
            Log("    | %9.6f  %9.6f  %9.6f |",PCA[0][0],PCA[0][1],PCA[0][2]);
            Log("    | %9.6f  %9.6f  %9.6f |",PCA[1][0],PCA[1][1],PCA[1][2]);
            Log("    | %9.6f  %9.6f  %9.6f |",PCA[2][0],PCA[2][1],PCA[2][2]);

            Log("axis momenta are :");
            Log("    | %9.6f  %9.6f  %9.6f |",pcav[0],pcav[1],pcav[2]);
        }
        return true;
    }
    /************************************************************/
    if((filterName == "Per Vertex Quality Stat") || (filterName == "Per Face Quality Stat") )
    {
        CMeshO &m=md.mm()->cm;
        Distribution<float> DD;
        if(filterName == "Per Vertex Quality Stat")
            tri::Stat<CMeshO>::ComputePerVertexQualityDistribution(m, DD, false);
        else
            tri::Stat<CMeshO>::ComputePerFaceQualityDistribution(m, DD, false);

        Log("   Min %f Max %f",DD.Min(),DD.Max());
        Log("   Avg %f Med %f",DD.Avg(),DD.Percentile(0.5f));
        Log("   StdDev		%f",DD.StandardDeviation());
        Log("   Variance  %f",DD.Variance());
        return true;
    }

    if((filterName == "Per Vertex Quality Histogram") || (filterName == "Per Face Quality Histogram") )
    {
        CMeshO &m=md.mm()->cm;
        float RangeMin = env.evalFloat("HistMin");
        float RangeMax = env.evalFloat("HistMax");
        int binNum     = env.evalInt("binNum");

        Histogramf H;
        H.SetRange(RangeMin,RangeMax,binNum);
        if(filterName == "Per Vertex Quality Histogram")
        {
            for(CMeshO::VertexIterator vi = m.vert.begin(); vi != m.vert.end(); ++vi)
                if(!(*vi).IsD())
                {
                    assert(!math::IsNAN((*vi).Q()) && "You should never try to compute Histogram with Invalid Floating points numbers (NaN)");
                    H.Add((*vi).Q());
                }
        } else {
            for(CMeshO::FaceIterator fi = m.face.begin(); fi != m.face.end(); ++fi)
                if(!(*fi).IsD())
                {
                    assert(!math::IsNAN((*fi).Q()) && "You should never try to compute Histogram with Invalid Floating points numbers (NaN)");
                    H.Add((*fi).Q());
                }
        }
        Log("(         -inf..%15.7f) : %4.0f",RangeMin,H.BinCountInd(0));
        for(int i=1; i<=binNum; ++i)
            Log("[%15.7f..%15.7f) : %4.0f",H.BinLowerBound(i),H.BinUpperBound(i),H.BinCountInd(i));
        Log("[%15.7f..             +inf) : %4.0f",RangeMax,H.BinCountInd(binNum+1));
        return true;
    }
    return false;
}
コード例 #27
0
ファイル: filter_fractal.cpp プロジェクト: GuoXinxiao/meshlab
bool FilterFractal::applyFilter(QAction* filter, MeshDocument &md, RichParameterSet &par, vcg::CallBackPos* cb)
{
  if(this->getClass(filter) == MeshFilterInterface::MeshCreation)
       md.addNewMesh("",this->filterName(ID(filter)));
  switch(ID(filter))
    {
    case CR_FRACTAL_TERRAIN:
    case FP_FRACTAL_MESH:
        {
            MeshModel* mm = md.mm();
            float maxHeight = .0;
            int smoothingSteps = 0;

            if(ID(filter) == CR_FRACTAL_TERRAIN)
            {
                int steps = par.getInt("steps");
                steps = ((steps<2)? 2: steps);
                float gridSide = .0;
                FractalUtils<CMeshO>::GenerateGrid(mm->cm, steps, gridSide);
                maxHeight = par.getDynamicFloat("maxHeight") * gridSide;
            } else {
                maxHeight = par.getAbsPerc("maxHeight");
                smoothingSteps = par.getInt("smoothingSteps");
            }

            FractalUtils<CMeshO>::FractalArgs args
               (mm, par.getEnum("algorithm"),par.getFloat("seed"),
                par.getFloat("octaves"), par.getFloat("lacunarity"),
                par.getFloat("fractalIncrement"), par.getFloat("offset"), par.getFloat("gain"),
                maxHeight, par.getDynamicFloat("scale"), smoothingSteps, par.getBool("saveAsQuality"));

            if(args.saveAsQuality)
                mm->updateDataMask(MeshModel::MM_VERTQUALITY);
            return FractalUtils<CMeshO>::ComputeFractalPerturbation(mm->cm, args, cb);
        }
        break;
    case FP_CRATERS:
        {
            if (md.meshList.size() < 2) {
                errorMessage = "There must be at least two layers to apply the craters generation filter.";
                return false;
            }

            CMeshO* samples = &(par.getMesh("samples_mesh")->cm);
            if (samples->face.size() > 0) {
                errorMessage = "The sample layer selected should be a points cloud.";
                return false;
            }
            CMeshO* target = &(par.getMesh("target_mesh")->cm);
            if (samples == target) {
                errorMessage = "The sample layer and the target layer must be different.";
                return false;
            }

            float minRadius = par.getDynamicFloat("min_radius");
            float maxRadius = par.getDynamicFloat("max_radius");
            if (maxRadius <= minRadius)  {
                errorMessage =  "Min radius is greater than max radius.";
                return false;
            }

            float minDepth = par.getDynamicFloat("min_depth");
            float maxDepth = par.getDynamicFloat("max_depth");
            if (maxDepth <= minDepth) {
                errorMessage = "Min depth is greater than max depth.";
                return false;
            }

            // reads parameters
            CratersUtils<CMeshO>::CratersArgs args(par.getMesh("target_mesh"), par.getMesh("samples_mesh"), par.getEnum("rbf"),
                                    par.getInt("seed"), minRadius, maxRadius, minDepth, maxDepth,
                                    par.getInt("smoothingSteps"), par.getBool("save_as_quality"), par.getBool("invert"),
                                    par.getBool("ppNoise"), par.getBool("successiveImpacts"),
                                    par.getDynamicFloat("elevation"), par.getEnum("blend"),
                                    par.getDynamicFloat("blendThreshold"));

            return CratersUtils<CMeshO>::GenerateCraters(args, cb);
        }
        break;
    }
    return false;
}
コード例 #28
0
// The Real Core Function doing the actual mesh processing.
// Move Vertex of a random quantity
bool ExtraSamplePlugin::applyFilter(QAction *action, MeshDocument &md, RichParameterSet & par, vcg::CallBackPos *cb)
{
    switch(ID(action))	 {

    case FP_DECOMPOSER :
    {
        CMeshO &m = md.mm()->cm;
        CutMesh cm;
        vcg::tri::Append<CutMesh,CMeshO>::MeshCopy(cm,m);
        vcg::tri::Allocator<CutMesh>::CompactEveryVector(cm);
        vcg::tri::UpdateTopology<CutMesh>::FaceFace(cm);
        vcg::tri::UpdateTopology<CutMesh>::VertexFace(cm);
        vcg::tri::UpdateNormal<CutMesh>::PerFace(cm);

        //Get Parameters
        vcg::Point3f upperPoint = par.getPoint3f("upperPoint");
        vcg::Point3f lowerPoint = par.getPoint3f("lowerPoint");
        float dihedral = par.getDynamicFloat("dihedral");
        float ambient = par.getDynamicFloat("ambient");
        float geodesic = par.getDynamicFloat("geodesic");
        float geomin = par.getDynamicFloat("geo-factor-min");
        float geomax = par.getDynamicFloat("geo-factor-max");
        float elength = par.getDynamicFloat("e-length");
        CutMesh::FacePointer startFace = NULL;
        CutMesh::FacePointer endFace = NULL;



        //getting the closest faces to the passed point parameters
        TriMeshGrid grid;
        grid.Set(cm.face.begin(),cm.face.end());
        vcg::Point3<CutMesh::ScalarType> closest;
        float maxDist = cm.bbox.Diag();
        float minDist;
        startFace = vcg::tri::GetClosestFaceBase(cm, grid, upperPoint, maxDist, minDist, closest);
        endFace = vcg::tri::GetClosestFaceBase(cm, grid, lowerPoint, maxDist, minDist, closest);

        assert(startFace!=NULL && endFace!=NULL);

        std::vector<CutVertex::VertexPointer> seedVec;
        for(int i=0; i<3; i++)
            seedVec.push_back(startFace->V(i));

        //getting the geodesic distance from the start/end face and some other data
        //that will be used in the weight computation
        typename  CutMesh::template PerFaceAttributeHandle <float>  gfH1
                = vcg::tri::Allocator<CutMesh>::template AddPerFaceAttribute<float>(cm, std::string("GeoDis1"));
        vcg::tri::Geodesic<CutMesh>::Compute(cm, seedVec);

        float max1=0.0f;
        float maxq=0.0f;
        //getting also the maximum perFaceQuality value
        for(CutMesh::FaceIterator fit= cm.face.begin(); fit!=cm.face.end(); fit++){
            if(fit->Q()>=maxq)
                maxq=fit->Q();
            gfH1[fit] = (fit->V(0)->Q()+fit->V(1)->Q()+fit->V(2)->Q())/3.0f;
            if(gfH1[fit]>=max1)
                max1=gfH1[fit];
        }


        //this functor will be used to compute edge weights on the dual graph
        WeightFunctor<CutMesh> wf(ambient, dihedral, geodesic, elength, startFace, endFace, gfH1, max1, geomin, geomax, maxq);
        //start actual computation
        vcg::tri::GraphBuilder<CutMesh, WeightFunctor<CutMesh> >::Compute(cm, wf, startFace, endFace);
        vcg::tri::Allocator<CutMesh>::DeletePerFaceAttribute(cm,gfH1);
        vcg::tri::Append<CMeshO,CutMesh>::MeshCopy(m,cm);
        return true;
    }
    }
    return false;
}
コード例 #29
0
void FilterIsoParametrization::initParameterSet(QAction *a, MeshDocument& md, RichParameterSet & par)
{
  
  switch(ID(a))
  {
    case ISOP_PARAM:
    {
		par.addParam(new RichInt("targetAbstractMinFaceNum",100,"Abstract Min Mesh Size",
			"This number and the following one indicate the range face number of the abstract mesh that is used for the parametrization process.<br>"
			"The algorithm will choose the abstract mesh with the best number of triangles within the specified interval.<br>"
			"If the mesh has a very simple structure this range can be very low and strict;"
			"for a roughly spherical object if you specify a range of [8,8] faces you get a octahedral abstract mesh, e.g. a geometry image.<br>"
			"Large numbers (greater than 400) are usually not of practical use."));
		par.addParam(new RichInt("targetAbstractMaxFaceNum",200,"Abstract Max Mesh Size", "See above."));
		QStringList stopCriteriaList;
		stopCriteriaList.push_back("Best Heuristic");
		stopCriteriaList.push_back("Area + Angle");
		stopCriteriaList.push_back("Regularity");
		stopCriteriaList.push_back("L2");
		
		par.addParam(new RichEnum("stopCriteria", 0, stopCriteriaList, tr("Optimization Criteria"),
		        tr("<p style=\'white-space:pre\'>"
			        "Choose a metric to stop the parametrization within the interval<br>"
					"1: Best Heuristic : stop considering both isometry and number of faces of base domain<br>"
					"2: Area + Angle : stop at minimum area and angle distorsion<br>"
			        "3: Regularity : stop at minimum number of irregular vertices<br>"
			        "4: L2 : stop at minimum OneWay L2 Stretch Eff")));
		
		//par.addParam(new RichDynamicFloat("convergenceSpeed", 1, 1,4, "Convergence Speed", "This parameter controls the convergence speed/precision of the optimization of the texture coordinates. Larger the number slower the processing and ,eventually, slighly better results");
		par.addParam(new RichInt("convergenceSpeed",2, "Convergence Speed", "This parameter controls the convergence speed/precision of the optimization of the texture coordinates. Larger the number slower the processing and ,eventually, slighly better results"));
		par.addParam(new RichBool("DoubleStep",true,"Double Step","Use this bool to divide the parameterization in 2 steps. Double step makes the overall process faster and robust, but it may increase the distorsion"));
			break;
	}
	 case ISOP_REMESHING :
	{
		 par.addParam(new RichInt("SamplingRate",10,"Sampling Rate", "This specify the sampling rate for remeshing."));
		 break;
	}
	case ISOP_DIAMPARAM :
	{
		 par.addParam(new RichDynamicFloat("BorderSize",0.05f,0.01f,0.5f,"BorderSize ratio", "This specify the border for each diamond.<br>"
																"The bigger is the less triangles are splitted, but the more UV space is used."));								 
		break;										
	}
	case ISOP_LOAD : 
	{
		QFileInfo fi(md.mm()->fullName());
		QString fileName = fi.baseName();
		
		fileName = fileName.append(".abs");
		par.addParam(new RichString("AbsName", fileName, "Abstract Mesh file", "Set the abstract mesh as basedomain"));
		break;
	}
	case ISOP_SAVE : 
	{
		QFileInfo fi(md.mm()->fullName());
		QString fileName = fi.baseName();
		
		fileName = fileName.append(".abs");
		par.addParam(new RichString("AbsName", fileName, "Abstract Mesh file", "Set the abstract mesh as basedomain"));
		break;
	}
}
}
コード例 #30
0
bool FilterIsoParametrization::applyFilter(QAction *filter, MeshDocument& md, RichParameterSet & par, vcg::CallBackPos  *cb)
{
  MeshModel* m = md.mm();  //get current mesh from document
  CMeshO *mesh=&m->cm;
  switch(ID(filter))
  {
	case ISOP_PARAM :
	{

		int targetAbstractMinFaceNum = par.getInt("targetAbstractMinFaceNum");
		int targetAbstractMaxFaceNum = par.getInt("targetAbstractMaxFaceNum");
		int convergenceSpeed = par.getInt("convergenceSpeed");
		int stopCriteria=par.getEnum("stopCriteria");
		bool doublestep=par.getBool("DoubleStep");
		IsoParametrizator Parametrizator;

    m->updateDataMask(MeshModel::MM_FACEFACETOPO);

		bool isTXTenabled=m->hasDataMask(MeshModel::MM_VERTTEXCOORD);
		if (!isTXTenabled)
			m->updateDataMask(MeshModel::MM_VERTTEXCOORD);

		bool isVMarkenabled=m->hasDataMask(MeshModel::MM_VERTMARK);
		if (!isVMarkenabled)
			m->updateDataMask(MeshModel::MM_VERTMARK);

		bool isFMarkenabled=m->hasDataMask(MeshModel::MM_FACEMARK);
		if (!isFMarkenabled)
			m->updateDataMask(MeshModel::MM_FACEMARK);

		bool isVColorenabled=m->hasDataMask(MeshModel::MM_VERTCOLOR);
		if (!isVColorenabled)
			m->updateDataMask(MeshModel::MM_VERTCOLOR);

		bool isFColorenabled=m->hasDataMask(MeshModel::MM_FACECOLOR);
		if (!isFColorenabled)
			m->updateDataMask(MeshModel::MM_FACECOLOR);
		int tolerance = targetAbstractMaxFaceNum-targetAbstractMinFaceNum;
		switch (stopCriteria)
		{
			case 0:Parametrizator.SetParameters(cb,targetAbstractMinFaceNum,tolerance,IsoParametrizator::SM_Euristic,convergenceSpeed);break;
			case 1:Parametrizator.SetParameters(cb,targetAbstractMinFaceNum,tolerance,IsoParametrizator::SM_Corr,convergenceSpeed);break;
			case 2:Parametrizator.SetParameters(cb,targetAbstractMinFaceNum,tolerance,IsoParametrizator::SM_Reg,convergenceSpeed);break;
			case 3:Parametrizator.SetParameters(cb,targetAbstractMinFaceNum,tolerance,IsoParametrizator::SM_L2,convergenceSpeed);break;
			default:Parametrizator.SetParameters(cb,targetAbstractMinFaceNum,tolerance,IsoParametrizator::SM_Euristic,convergenceSpeed);break;
		}
		IsoParametrizator::ReturnCode ret=Parametrizator.Parametrize<CMeshO>(mesh,doublestep);
		
		if (ret==IsoParametrizator::Done)
		{
			Parametrizator.PrintAttributes();
			float aggregate,L2;
			int n_faces;
			Parametrizator.getValues(aggregate,L2,n_faces);
			Log("Num Faces of Abstract Domain: %d, One way stretch efficiency: %.4f, Area+Angle Distorsion %.4f  ",n_faces,L2,aggregate*100.f);
		}
		else
		{
			if (!isTXTenabled)
				m->clearDataMask(MeshModel::MM_VERTTEXCOORD);
			if (!isFMarkenabled)
				m->clearDataMask(MeshModel::MM_FACEMARK);
			if (!isVMarkenabled)
				m->clearDataMask(MeshModel::MM_VERTMARK);
			if (!isVColorenabled)
				m->clearDataMask(MeshModel::MM_VERTCOLOR);
			if (!isFColorenabled)
				m->clearDataMask(MeshModel::MM_FACECOLOR);
			if (ret==IsoParametrizator::NonPrecondition)
				this->errorMessage="non possible parameterization because of violated preconditions";
			else
			if (ret==IsoParametrizator::FailParam)
				this->errorMessage="non possible parameterization cause because missing the intepolation for some triangle of original the mesh (maybe due to topologycal noise)";
			return false;
		}
		Parametrizator.ExportMeshes(para_mesh,abs_mesh);
		isoPHandle=vcg::tri::Allocator<CMeshO>::AddPerMeshAttribute<IsoParametrization>(*mesh,"isoparametrization");
		bool isOK=isoPHandle().Init(&abs_mesh,&para_mesh);

		///copy back to original mesh
    isoPHandle().CopyParametrization<CMeshO>(mesh);

		if (!isOK)
		{
			Log("Problems gathering parameterization \n");
			return false;
		}
    if (!isVMarkenabled)
				m->clearDataMask(MeshModel::MM_VERTMARK);
		if (!isFMarkenabled)
				m->clearDataMask(MeshModel::MM_FACEMARK);
    return true;
	}
	case ISOP_REMESHING :
	{
		bool b=vcg::tri::Allocator<CMeshO>::IsValidHandle<IsoParametrization>(*mesh,isoPHandle);
		if (!b)
		{
			this->errorMessage="You must compute the Base domain before remeshing. Use the Isoparametrization command.";
			return false;
		}
		

		int SamplingRate=par.getInt("SamplingRate");
		MeshModel* mm=md.addNewMesh("Re-meshed");
		
		CMeshO *rem=&mm->cm;
		
		DiamSampl.Init(&isoPHandle());
		DiamSampl.SamplePos(SamplingRate);
		DiamSampl.GetMesh<CMeshO>(*rem);

		int n_diamonds,inFace,inEdge,inStar,n_merged;
		DiamSampl.getResData(n_diamonds,inFace,inEdge,inStar,n_merged);

		Log("INTERPOLATION DOMAINS");
		Log("In Face: %d \n",inFace);
		Log("In Diamond: %d \n",inEdge);
		Log("In Star: %d \n",inStar);
		Log("Merged %d vertices\n",n_merged);
		mm->updateDataMask(MeshModel::MM_FACEFACETOPO);
		mm->updateDataMask(MeshModel::MM_VERTFACETOPO);
		PrintStats(rem);
		vcg::tri::UpdateNormals<CMeshO>::PerFace(*rem);
		return true;
	}
	case ISOP_DIAMPARAM :
	{
		bool b=vcg::tri::Allocator<CMeshO>::IsValidHandle<IsoParametrization>(*mesh,isoPHandle);
		if (!b)
		{
			this->errorMessage="You must compute the Base domain before remeshing. Use the Isoparametrization command.";
			return false;
		}
		
		float border_size=par.getDynamicFloat("BorderSize");
		MeshModel* mm=md.addNewMesh("Diam-Parameterized");
		mm->updateDataMask(MeshModel::MM_WEDGTEXCOORD);
		mm->updateDataMask(MeshModel::MM_VERTCOLOR);
		CMeshO *rem=&mm->cm;
		DiamondParametrizator DiaPara;
		DiaPara.Init(&isoPHandle());
		DiaPara.SetCoordinates<CMeshO>(*rem,border_size);
		vcg::tri::UpdateNormals<CMeshO>::PerFace(*rem);
		return true;
	}
	case ISOP_LOAD : 
	{
		QString AbsName = par.getString("AbsName");
		bool isTXTenabled=m->hasDataMask(MeshModel::MM_VERTTEXCOORD);
		if (!isTXTenabled)
		{
			this->errorMessage="Per Vertex Text Coordinates are not enabled";
			return false;
		}
		if(!QFile(m->fullName()).exists())
		{
			this->errorMessage="File not exists";
			return false;
		}
		bool b=vcg::tri::Allocator<CMeshO>::IsValidHandle<IsoParametrization>(*mesh,isoPHandle);
		if (!b)
			isoPHandle=vcg::tri::Allocator<CMeshO>::AddPerMeshAttribute<IsoParametrization>(*mesh,"isoparametrization");

		QByteArray ba = AbsName.toLatin1();
		char *path=ba.data();
		bool Done=isoPHandle().LoadBaseDomain<CMeshO>(path,mesh,&para_mesh,true);
		if (!Done)
		{
			this->errorMessage="Abstract domain doesnt fit well with the parametrized mesh";
			return false;
		}
		return true;
	}
	case ISOP_SAVE : 
	{
		bool b=vcg::tri::Allocator<CMeshO>::IsValidHandle<IsoParametrization>(*mesh,isoPHandle);
		if (!b)
		{
			this->errorMessage="You must compute the Base domain before remeshing. Use the Isoparametrization command.";
			return false;
		}
		/*QString Qpath=m->fullName();*/

		QString AbsName = par.getString("AbsName");
		
		QByteArray ba = AbsName.toLatin1();
		char *path=ba.data();
		isoPHandle().SaveBaseDomain(path);
		return true;
	}
  }
  return false;
}