コード例 #1
0
void EditVirtualScanPlugin::go( void )
{
    assert( glArea && inputMeshModel );
    CMeshO* firstCloud = 0, *secondCloud = 0;
    MeshDocument* mDoc = glArea->meshDoc;
    MeshModel* tmpModel = 0;

    if( unifyClouds )
    {
        tmpModel = mDoc->addNewMesh( "VS Point Cloud", 0, false );
        firstCloud = &( tmpModel->cm );
        secondCloud = firstCloud;
    }
    else
    {
        tmpModel = mDoc->addNewMesh( "VS Uniform Samples", 0, false );
        firstCloud = &( tmpModel->cm );
        tmpModel = mDoc->addNewMesh( "VS Feature Samples", 0, false );
        secondCloud = &( tmpModel->cm );
    }

    MyGLWidget* tmpWidget = new MyGLWidget
                            ( &params, inputMeshModel, firstCloud, secondCloud, glArea );
    bool ok = tmpWidget->result;
    if( !ok )
    {
        QString errorMessage = tmpWidget->errorString;
        Log( errorMessage.toStdString().c_str() );
    }
    delete tmpWidget;
}
コード例 #2
0
ファイル: filter_ssynth.cpp プロジェクト: GuoXinxiao/meshlab
bool FilterSSynth::applyFilter(QAction*  filter, MeshDocument &md, RichParameterSet & par, vcg::CallBackPos *cb)
{
    md.addNewMesh("",this->filterName(ID(filter)));
    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;
    }
}
コード例 #3
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;
}
コード例 #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
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;
}
コード例 #7
0
ファイル: RandomFillFilter.cpp プロジェクト: Booley/nbis
void RandomFillFilter::addRandomObject(MeshDocument& md, MeshModel* filler, const vcg::Point3<float>& origin, int meshID){
    ostringstream meshName;
    meshName << "randomFillMesh" << meshID;
    MeshModel* meshCopy = md.addNewMesh(meshName.str().c_str());
    vcg::tri::Append<CMeshO,CMeshO>::Mesh(meshCopy->cm, filler->cm, false, true);
    meshCopy->cm.Tr = filler->cm.Tr;
    meshCopy->cm.Tr.SetColumn(3, meshCopy->cm.Tr.GetColumn3(3) + origin);
}
コード例 #8
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;
}
コード例 #9
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;
}
コード例 #10
0
// The Real Core Function doing the actual mesh processing.
bool FilterFunctionPlugin::applyFilter(QAction *filter, MeshDocument &md, RichParameterSet & par, vcg::CallBackPos *cb)
{
  if(this->getClass(filter) == MeshFilterInterface::MeshCreation)
       md.addNewMesh("",this->filterName(ID(filter)));
  MeshModel &m=*(md.mm());
	Q_UNUSED(cb);
	switch(ID(filter)) {
		case FF_VERT_SELECTION :
			{
				std::string expr = par.getString("condSelect").toStdString();
			
				// muparser initialization and explicitely define parser variables
				Parser p;
        setPerVertexVariables(p,m.cm);

				// set expression inserted by user as string (required by muparser)
				p.SetExpr(expr);

				int numvert = 0;
				time_t start = clock();

				// every parser variables is related to vertex coord and attributes.
				CMeshO::VertexIterator vi;
				for(vi = m.cm.vert.begin(); vi != m.cm.vert.end(); ++vi)if(!(*vi).IsD())
				{
					setAttributes(vi,m.cm);

					bool selected = false;

					// use parser to evaluate boolean function specified above
					// in case of fail, error dialog contains details of parser's error
					try { 
						selected = p.Eval();
					} catch(Parser::exception_type &e) {
						errorMessage = e.GetMsg().c_str();
  						return false;
					}

					// set vertex as selected or clear selection
					if(selected) { 
						(*vi).SetS();
						numvert++;
					} else (*vi).ClearS();
				}

				// strict face selection
				if(par.getBool("strictSelect"))
						tri::UpdateSelection<CMeshO>::FaceFromVertexStrict(m.cm); 
				else  
						tri::UpdateSelection<CMeshO>::FaceFromVertexLoose(m.cm); 
		
				// if succeded log stream contains number of vertices and time elapsed
				Log( "selected %d vertices in %.2f sec.", numvert, (clock() - start) / (float) CLOCKS_PER_SEC);
					
				return true;
			}
		break;

		case FF_FACE_SELECTION :
			{
				QString select = par.getString("condSelect");
			
				// muparser initialization and explicitely define parser variables
				Parser p;
        setPerFaceVariables(p,m.cm);

				// set expression inserted by user as string (required by muparser)
				p.SetExpr(select.toStdString());

				int numface = 0;
				time_t start = clock();

				// every parser variables is related to face attributes.
				CMeshO::FaceIterator fi;
				for(fi = m.cm.face.begin(); fi != m.cm.face.end(); ++fi)if(!(*fi).IsD())
				{
					setAttributes(fi,m.cm);

					bool selected = false;

					// use parser to evaluate boolean function specified above
					// in case of fail, error dialog contains details of parser's error
					try { 
						selected = p.Eval();
					} catch(Parser::exception_type &e) {
						errorMessage = e.GetMsg().c_str();
  						return false;
					}

					// set face as selected or clear selection
					if(selected) { 
						(*fi).SetS();
						numface++;
					} else (*fi).ClearS();
				}

				// if succeded log stream contains number of vertices and time elapsed
				Log( "selected %d faces in %.2f sec.", numface, (clock() - start) / (float) CLOCKS_PER_SEC);
					
				return true;
			}
		break;

		case FF_GEOM_FUNC :
		case FF_VERT_COLOR:
    case FF_VERT_NORMAL:
			{
        std::string func_x,func_y,func_z,func_a;
				// FF_VERT_COLOR : x = r, y = g, z = b
        // FF_VERT_NORMAL : x = r, y = g, z = b
        func_x = par.getString("x").toStdString();
        func_y = par.getString("y").toStdString();
        func_z = par.getString("z").toStdString();
        if(ID(filter) == FF_VERT_COLOR) func_a = par.getString("a").toStdString();

				// muparser initialization and explicitely define parser variables
				// function for x,y and z must use different parser and variables
        Parser p1,p2,p3,p4;

        setPerVertexVariables(p1,m.cm);
        setPerVertexVariables(p2,m.cm);
        setPerVertexVariables(p3,m.cm);
        setPerVertexVariables(p4,m.cm);

				p1.SetExpr(func_x);
				p2.SetExpr(func_y);
				p3.SetExpr(func_z);
        p4.SetExpr(func_a);

        double newx=0,newy=0,newz=0,newa=255;
				errorMessage = "";

				time_t start = clock();

				// every parser variables is related to vertex coord and attributes.
				CMeshO::VertexIterator vi;
				for(vi = m.cm.vert.begin(); vi != m.cm.vert.end(); ++vi)if(!(*vi).IsD())
				{
					setAttributes(vi,m.cm);

					// every function is evaluated by different parser.
					// errorMessage dialog contains errors for func x, func y and func z
          try { newx = p1.Eval(); }  catch(Parser::exception_type &e) { showParserError("1st func : ",e); }
          try { newy = p2.Eval(); }  catch(Parser::exception_type &e) { showParserError("2nd func : ",e); }
          try { newz = p3.Eval(); }  catch(Parser::exception_type &e) { showParserError("3rd func : ",e); }
          if(ID(filter) == FF_VERT_COLOR)
          {
            try { newa = p4.Eval(); } catch(Parser::exception_type &e) { showParserError("4th func : ",e); }
          }
          if(errorMessage != "") return false;

          if(ID(filter) == FF_GEOM_FUNC)  // set new vertex coord for this iteration
						(*vi).P() = Point3f(newx,newy,newz); 
          if(ID(filter) == FF_VERT_COLOR) // set new color for this iteration
            (*vi).C() = Color4b(newx,newy,newz,newa);
          if(ID(filter) == FF_VERT_NORMAL) // set new color for this iteration
            (*vi).N() = Point3f(newx,newy,newz);
          }

				if(ID(filter) == FF_GEOM_FUNC) {
					// update bounding box, normalize normals
					tri::UpdateNormals<CMeshO>::PerVertexNormalizedPerFace(m.cm);
					tri::UpdateNormals<CMeshO>::NormalizeFace(m.cm);
					tri::UpdateBounding<CMeshO>::Box(m.cm);
				}

				// if succeded log stream contains number of vertices processed and time elapsed
				Log( "%d vertices processed in %.2f sec.", m.cm.vn, (clock() - start) / (float) CLOCKS_PER_SEC);

				return true;
			}
		break;
		
		case FF_VERT_QUALITY:
			{
				std::string func_q = par.getString("q").toStdString();
				m.updateDataMask(MeshModel::MM_VERTQUALITY);
				
				// muparser initialization and define custom variables
				Parser p;
        setPerVertexVariables(p,m.cm);

				// set expression to calc with parser
				p.SetExpr(func_q);

				// every parser variables is related to vertex coord and attributes.
				time_t start = clock();
				CMeshO::VertexIterator vi;
        for(vi = m.cm.vert.begin(); vi != m.cm.vert.end(); ++vi)
        if(!(*vi).IsD())
				{
					setAttributes(vi,m.cm);

					// use parser to evaluate function specified above
					// in case of fail, errorMessage dialog contains details of parser's error
					try { 
						(*vi).Q() = p.Eval();
					} catch(Parser::exception_type &e) {
						errorMessage = e.GetMsg().c_str();
  						return false;
					}
				}

				// normalize quality with values in [0..1] 
        if(par.getBool("normalize")) tri::UpdateQuality<CMeshO>::VertexNormalize(m.cm);
				
				// map quality into per-vertex color
        if(par.getBool("map")) tri::UpdateColor<CMeshO>::VertexQualityRamp(m.cm);

				// if succeded log stream contains number of vertices and time elapsed
				Log( "%d vertices processed in %.2f sec.", m.cm.vn, (clock() - start) / (float) CLOCKS_PER_SEC);

				return true;
			}
		break;

		case FF_FACE_COLOR:
			{
				std::string func_r = par.getString("r").toStdString();
				std::string func_g = par.getString("g").toStdString();
				std::string func_b = par.getString("b").toStdString();
        std::string func_a = par.getString("a").toStdString();

				// muparser initialization and explicitely define parser variables
				// every function must uses own parser and variables
        Parser p1,p2,p3,p4;

        setPerFaceVariables(p1,m.cm);
        setPerFaceVariables(p2,m.cm);
        setPerFaceVariables(p3,m.cm);
        setPerFaceVariables(p4,m.cm);

				p1.SetExpr(func_r);
				p2.SetExpr(func_g);
				p3.SetExpr(func_b);
        p4.SetExpr(func_a);

				// RGB is related to every face
				CMeshO::FaceIterator fi;
        double newr=0,newg=0,newb=0,newa=255;
				errorMessage = "";

				time_t start = clock();

				// every parser variables is related to face attributes.
				for(fi = m.cm.face.begin(); fi != m.cm.face.end(); ++fi)if(!(*fi).IsD())
				{
					setAttributes(fi,m.cm);

					// evaluate functions to generate new color
					// in case of fail, error dialog contains details of parser's error
          try { newr = p1.Eval(); } catch(Parser::exception_type &e) { showParserError("func r: ",e); }
          try { newg = p2.Eval(); } catch(Parser::exception_type &e) { showParserError("func g: ",e); }
          try { newb = p3.Eval(); } catch(Parser::exception_type &e) { showParserError("func b: ",e); 	}
          try { newa = p4.Eval(); } catch(Parser::exception_type &e) { showParserError("func a: ",e); 	}

					if(errorMessage != "") return false;

					// set new color for this iteration
          (*fi).C() = Color4b(newr,newg,newb,newa);
				}

				// if succeded log stream contains number of vertices processed and time elapsed
				Log( "%d faces processed in %.2f sec.", m.cm.fn, (clock() - start) / (float) CLOCKS_PER_SEC);

				return true;

			}
		break;

		case FF_FACE_QUALITY:
			{
				std::string func_q = par.getString("q").toStdString();
				m.updateDataMask(MeshModel::MM_FACEQUALITY);

				// muparser initialization and define custom variables
				Parser pf;
        setPerFaceVariables(pf,m.cm);
					
				// set expression to calc with parser
          pf.SetExpr(func_q);

				time_t start = clock();
				errorMessage = "";

				// every parser variables is related to face attributes.
				CMeshO::FaceIterator fi;
				for(fi = m.cm.face.begin(); fi != m.cm.face.end(); ++fi)if(!(*fi).IsD())
				{
					setAttributes(fi,m.cm);

					// evaluate functions to generate new quality
					// in case of fail, error dialog contains details of parser's error
					try { (*fi).Q() = pf.Eval(); }
					catch(Parser::exception_type &e) {
						showParserError("func q: ",e);
					}
					if(errorMessage != "") return false;
				}

				// normalize quality with values in [0..1]
        if(par.getBool("normalize")) tri::UpdateQuality<CMeshO>::FaceNormalize(m.cm);

				// map quality into per-vertex color
        if(par.getBool("map")) tri::UpdateColor<CMeshO>::FaceQualityRamp(m.cm);

				// if succeded log stream contains number of faces processed and time elapsed
				Log( "%d faces processed in %.2f sec.", m.cm.fn, (clock() - start) / (float) CLOCKS_PER_SEC);

				return true;
			}
		break;

		case FF_DEF_VERT_ATTRIB :
			{
				std::string name = par.getString("name").toStdString();
				std::string expr = par.getString("expr").toStdString();

				// add per-vertex attribute with type float and name specified by user
        CMeshO::PerVertexAttributeHandle<float> h;
        if(tri::HasPerVertexAttribute(m.cm,name))
				{
          h = tri::Allocator<CMeshO>::GetPerVertexAttribute<float>(m.cm, name);
              if(!tri::Allocator<CMeshO>::IsValidHandle<float>(m.cm,h))
          {
          errorMessage = "attribute already exists with a different type";
					return false;
          }
				}
        else
          h = tri::Allocator<CMeshO>::AddPerVertexAttribute<float> (m.cm,name);

        std::vector<std::string> AllVertexAttribName;
        tri::Allocator<CMeshO>::GetAllPerVertexAttribute< float >(m.cm,AllVertexAttribName);
        qDebug("Now mesh has %i vertex float attribute",AllVertexAttribName.size());
				Parser p;
        setPerVertexVariables(p,m.cm);
				p.SetExpr(expr);

				time_t start = clock();

				// perform calculation of attribute's value with function specified by user
				CMeshO::VertexIterator vi;
				for(vi = m.cm.vert.begin(); vi != m.cm.vert.end(); ++vi)if(!(*vi).IsD())
				{
					setAttributes(vi,m.cm);

					// add new user-defined attribute
					try {
						h[vi] = p.Eval();
					} catch(Parser::exception_type &e) {
						errorMessage = e.GetMsg().c_str();
  						return false;
					}
				}

				// add string, double and handler to vector.
				// vectors keep tracks of new attributes and let muparser use explicit variables
				// it's possibile to use custom attributes in other filters
				v_attrNames.push_back(name);
				v_attrValue.push_back(0);
        v_handlers.push_back(h);

				// if succeded log stream contains number of vertices processed and time elapsed
				Log( "%d vertices processed in %.2f sec.", m.cm.vn, (clock() - start) / (float) CLOCKS_PER_SEC);

				return true;
			}
		break;

		case FF_DEF_FACE_ATTRIB :
			{
				std::string name = par.getString("name").toStdString();
				std::string expr = par.getString("expr").toStdString();
				
				// add per-face attribute with type float and name specified by user
        // add per-vertex attribute with type float and name specified by user
        CMeshO::PerFaceAttributeHandle<float> h;
        if(tri::HasPerFaceAttribute(m.cm,name))
        {
          h = tri::Allocator<CMeshO>::GetPerFaceAttribute<float>(m.cm, name);
          if(!tri::Allocator<CMeshO>::IsValidHandle<float>(m.cm,h))
          {
          errorMessage = "attribute already exists with a different type";
          return false;
          }
        }
        else
          h = tri::Allocator<CMeshO>::AddPerFaceAttribute<float> (m.cm,name);
				Parser p;
        setPerFaceVariables(p,m.cm);
				p.SetExpr(expr);

				time_t start = clock();

				// every parser variables is related to face attributes.
				CMeshO::FaceIterator fi;
				for(fi = m.cm.face.begin(); fi != m.cm.face.end(); ++fi)if(!(*fi).IsD())
				{
					setAttributes(fi,m.cm);

					// add new user-defined attribute
					try {
						h[fi] = p.Eval();
					} catch(Parser::exception_type &e) {
						errorMessage = e.GetMsg().c_str();
  						return false;
					}
				}

//				// add string, double and handler to vector.
//				// vectors keep tracks of new attributes and let muparser use explicit variables
//				// it's possibile to use custom attributes in other filters
//				f_attrNames.push_back(name);
//				f_attrValue.push_back(0);
//				fhandlers.push_back(h);

				// if succeded log stream contains number of vertices processed and time elapsed
				Log( "%d faces processed in %.2f sec.", m.cm.fn, (clock() - start) / (float) CLOCKS_PER_SEC);

				return true;
			}
		break;

		case FF_GRID : 
			{
				// obtain parameters to generate 2D Grid
				int w = par.getInt("numVertX");		 
				int h = par.getInt("numVertY");		 
				float wl = par.getFloat("absScaleX");	 
				float hl = par.getFloat("absScaleY");

				if(w <= 0 || h <= 0) {
					errorMessage = "number of vertices must be positive";
					return false;
				}

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

				// if "centered on origin" is checked than move generated Grid in (0,0,0)
				if(par.getBool("center")) 
				{
					// 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)
					{
						(*vi).P()[0] = (*vi).P()[0] - (wld * halfw);
						(*vi).P()[1] = (*vi).P()[1] - (hld * halfh);
					}
				}
				// update bounding box, normals
        Matrix44f rot; rot.SetRotateDeg(180,Point3f(0,1,0));
        tri::UpdatePosition<CMeshO>::Matrix(m.cm,rot,false);
				tri::UpdateNormals<CMeshO>::PerVertexNormalizedPerFace(m.cm);	
				tri::UpdateNormals<CMeshO>::NormalizeFace(m.cm);
				tri::UpdateBounding<CMeshO>::Box(m.cm);
				
				return true;
			}
		break;
		case FF_ISOSURFACE :
			{
					SimpleVolume<SimpleVoxel> 	volume;
		
					typedef vcg::tri::TrivialWalker<CMeshO, SimpleVolume<SimpleVoxel> >	MyWalker;
					typedef vcg::tri::MarchingCubes<CMeshO, MyWalker>	MyMarchingCubes;
					MyWalker walker;
		
					Box3d rbb;
					rbb.min[0]=par.getFloat("minX");
					rbb.min[1]=par.getFloat("minY");
					rbb.min[2]=par.getFloat("minZ");
					rbb.max[0]=par.getFloat("maxX");
					rbb.max[1]=par.getFloat("maxY");
					rbb.max[2]=par.getFloat("maxZ");
					double step=par.getFloat("voxelSize");
					Point3i siz= Point3i::Construct((rbb.max-rbb.min)*(1.0/step));
					
					Parser p;
					double x,y,z;
					p.DefineVar("x", &x);
					p.DefineVar("y", &y);
					p.DefineVar("z", &z);
					std::string expr = par.getString("expr").toStdString();
					p.SetExpr(expr);
					Log("Filling a Volume of %i %i %i",siz[0],siz[1],siz[2]);
					volume.Init(siz);
					for(double i=0;i<siz[0];i++)
						for(double j=0;j<siz[1];j++)
							for(double k=0;k<siz[2];k++)
							{
							 x = rbb.min[0]+step*i;
							 y = rbb.min[1]+step*j;
							 z = rbb.min[2]+step*k;
							 	try {
										volume.Val(i,j,k)=p.Eval();
										} catch(Parser::exception_type &e) {
												errorMessage = e.GetMsg().c_str();
												return false;
											}
							}
		
		// MARCHING CUBES
		Log("[MARCHING CUBES] Building mesh...");
		MyMarchingCubes					mc(m.cm, walker);
		walker.BuildMesh<MyMarchingCubes>(m.cm, volume, mc, 0);
		Matrix44f tr; tr.SetIdentity(); tr.SetTranslate(rbb.min[0],rbb.min[1],rbb.min[2]);
		Matrix44f sc; sc.SetIdentity(); sc.SetScale(step,step,step);
		tr=tr*sc;
		
		tri::UpdatePosition<CMeshO>::Matrix(m.cm,tr);
		tri::UpdateNormals<CMeshO>::PerVertexNormalizedPerFace(m.cm);																																			 
		tri::UpdateBounding<CMeshO>::Box(m.cm);					// updates bounding box		
		return true;

			}
		break;

		case FF_REFINE :
			{
				std::string condSelect = par.getString("condSelect").toStdString();
				
				std::string expr1 = par.getString("x").toStdString();
				std::string expr2 = par.getString("y").toStdString();
				std::string expr3 = par.getString("z").toStdString();

				bool errorMidPoint = false;
				bool errorEdgePred = false;
				std::string msg = "";

				// check parsing errors while creating two func obj
				// display error message
				MidPointCustom<CMeshO> mid = MidPointCustom<CMeshO>(m.cm,expr1,expr2,expr3,errorMidPoint,msg);
				CustomEdge<CMeshO> edge = CustomEdge<CMeshO>(condSelect,errorEdgePred,msg);
				if(errorMidPoint || errorEdgePred) 
				{
					errorMessage = msg.c_str();
					return false;
				}

				// Refine current mesh.
				// Only edge specified with CustomEdge pred are selected
				//  and the new vertex is choosen with MidPointCustom created above
				RefineE<CMeshO, MidPointCustom<CMeshO>, CustomEdge<CMeshO> >
					(m.cm, mid, edge, false, cb);

				m.clearDataMask( MeshModel::MM_VERTMARK);
				vcg::tri::UpdateNormals<CMeshO>::PerVertexNormalizedPerFace(m.cm);

				return true;
			}
		break;

		default : assert (0);
	}
	return false;
}
コード例 #11
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;
}
コード例 #12
0
ファイル: filter_create.cpp プロジェクト: Jerdak/meshlab
// The Real Core Function doing the actual mesh processing.
bool FilterCreate::applyFilter(QAction *filter, MeshDocument &md, RichParameterSet & par, vcg::CallBackPos * /*cb*/)
{
    MeshModel* m=md.addNewMesh("",this->filterName(ID(filter)));
  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_TORUS:
    {
      float hRadius=par.getFloat("hRadius");
      float vRadius=par.getFloat("vRadius");
      int hSubdiv=par.getInt("hSubdiv");
      int vSubdiv=par.getInt("vSubdiv");
      vcg::tri::Torus(m->cm,hRadius,vRadius,hSubdiv,vSubdiv);
        break;
    }
  case CR_RANDOM_SPHERE:
    {
    CMeshO tt;

    int pointNum = par.getInt("pointNum");
    int oversamplingFactor =100;
    if(pointNum <= 100) oversamplingFactor = 1000;
    if(pointNum >= 10000) oversamplingFactor = 50;
    if(pointNum >= 100000) oversamplingFactor = 20;

    vcg::math::MarsenneTwisterRNG rng;
    vcg::tri::Allocator<CMeshO>::AddVertices(tt,pointNum*50);
    for(CMeshO::VertexIterator vi=tt.vert.begin();vi!=tt.vert.end();++vi)
      vcg::math::GeneratePointOnUnitSphereUniform(rng,vi->P());
    vcg::tri::UpdateBounding<CMeshO>::Box(tt);

    const float SphereArea = 4*M_PI;
    float poissonRadius = 2.0*sqrt((SphereArea / float(pointNum*2))/M_PI);

    std::vector<vcg::Point3f> poissonSamples;
    vcg::tri::TrivialSampler<CMeshO> pdSampler(poissonSamples);
    vcg::tri::SurfaceSampling<CMeshO, vcg::tri::TrivialSampler<CMeshO> >::PoissonDiskParam pp;

    vcg::tri::SurfaceSampling<CMeshO,vcg::tri::TrivialSampler<CMeshO> >::PoissonDiskPruning(pdSampler, tt, poissonRadius, pp);
    m->cm.Clear();
    vcg::tri::Allocator<CMeshO>::AddVertices(m->cm,poissonSamples.size());
    for(size_t i=0;i<poissonSamples.size();++i)
    {
      m->cm.vert[i].P()=poissonSamples[i];
      m->cm.vert[i].N()=m->cm.vert[i].P();
    }
  } break;

  case CR_SPHERE:
    {
        int rec = par.getInt("subdiv");
        float radius = par.getFloat("radius");
        m->cm.face.EnableFFAdjacency();
        m->updateDataMask(MeshModel::MM_FACEFACETOPO);
        assert(vcg::tri::HasPerVertexTexCoord(m->cm) == false);
        vcg::tri::Sphere<CMeshO>(m->cm,rec);

		for(CMeshO::VertexIterator vi = m->cm.vert.begin();vi!= m->cm.vert.end();++vi)
		  vi->P()=vi->P()*radius;

		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::UpdateNormal<CMeshO>::PerVertexNormalizedPerFaceNormalized(m->cm);
    return true;
}
コード例 #13
0
ファイル: filter_waffle.cpp プロジェクト: 34985086/meshlab
bool ExtraFilter_SlicePlugin::applyFilter(QAction *filter, MeshDocument &m, RichParameterSet &parlst, vcg::CallBackPos *cb)
{
    vcg::tri::UpdateBounding<CMeshO>::Box(m.mm()->cm);

    switch(ID(filter))
    {
        case FP_WAFFLE_SLICE :
        {
            MeshModel* base = m.mm();
            CMeshO &cmBase = base->cm;
            Box3f &bbox = m.mm()->cm.bbox;

            if (tri::Clean<CMeshO>::CountNonManifoldEdgeFF(cmBase)>0 || (tri::Clean<CMeshO>::CountNonManifoldVertexFF(cmBase,false) != 0))
            {
                Log("Mesh is not two manifold, cannot apply filter");
                return false;
            }
            if(parlst.getFloat("spacing") >= 1)
            {
                Log("the selected distance between the planes is greater than 1. The filter had no effect");
                return false;
            }

            Point3f planeAxis(0,0,0);
            Axis axis = (Axis) parlst.getEnum("planeAxis");
            planeAxis[axis] = 1.0f;

            float length = parlst.getFloat("length");

            bool hideBase = parlst.getBool("hideBase");
            bool hideEdge = parlst.getBool("hideEdge");
            bool hidePlanes = parlst.getBool("hidePlanes");
            bool hideExtrudes = parlst.getBool("hideExtrudes");

            // set common SVG Properties
            const float maxdim=m.mm()->cm.bbox.Dim()[m.mm()->cm.bbox.MaxDim()];

            Point3f sizeCm=m.mm()->cm.bbox.Dim()*(length/maxdim);
            // to check for dimensions with custom axis
            Axis axisOrthog, axisJoint;
            Point2f sizeCmOrth;
            switch(axis)
            {
            case X:
                {
                    axisOrthog = (Axis) Succ<X>::value;
                    axisJoint = (Axis) Succ<Succ<X>::value>::value;
                    pr.sizeCm = Point2f(sizeCm[1],sizeCm[2]);
                    sizeCmOrth.X()=sizeCm[0];
                    sizeCmOrth.Y()=sizeCm[2];
                }
                break;
            case Y:
                {
                    axisOrthog = (Axis) Succ<Y>::value;
                    axisJoint = (Axis) Succ<Succ<Y>::value>::value;
                    pr.sizeCm = Point2f(sizeCm[0],sizeCm[2]);
                    sizeCmOrth.X()=sizeCm[0];
                    sizeCmOrth.Y()=sizeCm[1];
                }
                break;
            case Z:
                {
                    axisOrthog = (Axis) Succ<Z>::value;
                    axisJoint = (Axis) Succ<Succ<Z>::value>::value;
                    pr.sizeCm = Point2f(sizeCm[0],sizeCm[1]);
                    sizeCmOrth.X()=sizeCm[1];
                    sizeCmOrth.Y()=sizeCm[2];
                }
                break;
            }

            Log("sizecm %fx%f",pr.sizeCm[0],pr.sizeCm[1]);

            vector<CMeshO*> ev;

            const float planeDist = maxdim * parlst.getFloat("spacing");
            const int planeNum = (planeDist == 0) ? 1 : ( ((bbox.Dim()*planeAxis)/planeDist)+1 ); //evito la divisione per 0
            const float lengthDiag = bbox.Diag()/2.0;

            Segment2f lati[3]; //the rectangle is made up of three segments, the fourth side is ignored, so I never use it

            const float eps =planeDist*parlst.getFloat("eps");
            float epsTmp;
            float start;
            int rectNum;
            if(parlst.getFloat("eps") < 1)
            {
                start = - (planeNum/2) * planeDist;   //I have to go back from the center of half the length
                epsTmp = eps/2.0;
                generateRectSeg(0, epsTmp, bbox.Diag()*2, lati);
                rectNum = planeNum;
            }
            else
            {
                start = 0;
                epsTmp = bbox.Diag();
                generateRectSeg(0, bbox.Diag()*2, bbox.Diag()*2, lati);
                rectNum = 1;
                Log("thickness is greater than 1: the extrusions will overlap");
            }

            float planeOffset = parlst.getFloat("planeOffset");

            pr.lineWidthPt=200;
            pr.scale=2/maxdim;
            pr.numCol=(int)(max((int)sqrt(planeNum*1.0f),2)+1);
            pr.numRow=(int)(planeNum*1.0f/pr.numCol)+1;
            pr.projDir = planeAxis;
            pr.projCenter =  m.mm()->cm.bbox.Center();
            pr.enumeration = true;

            MeshModel* cap, *cap2, *extr;
            QString layername;


            for(int pl = 0; pl < 2; ++pl)
            {
//                Log("################## PLANE %i", pl);
                Plane3f slicingPlane;
                Point3f planeCenter = bbox.Center() + planeAxis*planeOffset*lengthDiag;
                int numAdd = 0;

//                int i=4;  //if I want to apply only the plan number i I decomment this variable and comment the cycle
                for(int i = 0; i < planeNum; ++i)   //cropping the plans
                {
//                    Log("######## LAYER %i", i);
                    planeCenter[axis] = start + planeDist*i;;

                    slicingPlane.Init(planeCenter,planeAxis);

                    layername.sprintf("EdgeMesh_%d_%d",pl,numAdd);
                    cap= m.addNewMesh("",qPrintable(layername));
                    vcg::IntersectionPlaneMesh<CMeshO, CMeshO, float>(base->cm, slicingPlane, cap->cm );

                    tri::Clean<CMeshO>::RemoveDuplicateVertex(cap->cm);
                    if(cap->cm.edge.size()>= 3)
                    {
                        Incastri temp;

//                        int j=1;      //if I want to apply only the rectangle number j I decomment this variable and comment the cycle
                        for(int j = 0; j <rectNum ; ++j)   //clipping the rectangles
                        {
//                            Log("#### RECTANGLE %i", j);
                            float newDist = start + planeDist*j;
                            modifyOnY(lati, newDist+epsTmp, newDist-epsTmp);

                            temp = subtraction(cap->cm, lati, axis, axisOrthog, axisJoint, planeCenter[axis]);

                            if(temp == NOT_PLANE) {Log("ATTENTION! The IntersectionPlaneMesh did not return a plane silhouette in the current plane!"); m.delMesh(cap); break;}
                            if(temp== NOT_SAGOME) {Log("ATTENTION! The IntersectionPlaneMesh did not return a simple closed silhouette for the plane %i, on axis %i",i, pl); m.delMesh(cap); break;}
                        }
                        if(temp > NOT_SAGOME)
                        {
                            ev.push_back(&(cap->cm));   //add the silhouette to those for export to SVG

                            layername.sprintf("CappedSlice_%d_%d",pl,numAdd);   //add the silhouettes converted in mesh
                            cap2= m.addNewMesh("",qPrintable(layername));
                            tri::CapEdgeMesh(cap->cm, cap2->cm);

                            layername.sprintf("Extruded_%d_%d",pl,numAdd++);      //add the mesh extruded
                            extr= m.addNewMesh("",qPrintable(layername));
                            cap2->updateDataMask(MeshModel::MM_FACEFACETOPO);
                            extr->updateDataMask(MeshModel::MM_FACEFACETOPO);
                            tri::UpdateTopology<CMeshO>::FaceFace(cap2->cm);
                            tri::ExtrudeBoundary<CMeshO>(cap2->cm,extr->cm,eps,planeAxis);

                            if(hideEdge) cap->visible =false;
                            if(hidePlanes) cap2->visible =false;
                            if(hideExtrudes) extr->visible =false;
                        }
                    }else m.delMesh(cap);   //if the intersection does not exist I reject the result
                }

                QString fname;//= parlst.getSaveFileName("filename");
                if(fname=="") fname.sprintf("Slice_%d.svg",pl);
                if (!fname.endsWith(".svg")) fname+=".svg";
                tri::io::ExporterSVG<CMeshO>::Save(ev, fname.toStdString().c_str(), pr);

                ev.clear();

                planeAxis[axis] = 0.0f;
                planeAxis[axisOrthog] = 1.0f;

                flipOnX(lati);

                pr.sizeCm = sizeCmOrth;
                pr.projDir = planeAxis;

                Axis aSwap = axis;
                axis = axisOrthog;
                axisOrthog = aSwap;
            }


            if(hideEdge) cap->visible =false;
            if(hidePlanes) cap2->visible =false;
            if(hideExtrudes) extr->visible =false;

            if(hideBase) base->visible =false;
            if(hideBase) base->visible =false;

        }
        break;
    }
    return true;
}
コード例 #14
0
ファイル: filter_poisson.cpp プロジェクト: GuoXinxiao/meshlab
// The Real Core Function doing the actual mesh processing.
// Move Vertex of a random quantity
bool PoissonPlugin::applyFilter(QAction *filter, MeshDocument &md, RichParameterSet & par, vcg::CallBackPos *cb)
{
	MeshModel &m=*md.mm();
  MeshModel &pm =*md.addNewMesh("","Poisson mesh");
  vector<Point3D<float> > Pts(m.cm.vn);
	vector<Point3D<float> > Nor(m.cm.vn); 	
	CoredVectorMeshData mesh;

	if (m.hasDataMask(MeshModel::MM_WEDGTEXCOORD)){
		m.clearDataMask(MeshModel::MM_WEDGTEXCOORD);
	}
	if (m.hasDataMask(MeshModel::MM_VERTTEXCOORD)){
		m.clearDataMask(MeshModel::MM_VERTTEXCOORD);
	}

    //Useless control on the normals. It can just avoid crashes derived from an importer setting up to [0.0f,0.0f,0.0f] the normal vectors of a mesh without per-vertex normal attribute.
    int zeronrm = 0;
    for(CMeshO::VertexIterator vi=m.cm.vert.begin(); vi!=m.cm.vert.end(); ++vi)
    {
        if(!(*vi).IsD())
        {
            if ((*vi).N() == vcg::Point3f(0.0f,0.0f,0.0f))
                ++zeronrm;
        }
    }

    if (zeronrm == m.cm.vn)
    {
        Log(GLLogStream::SYSTEM,"All the normal vectors are set to [0.0,0.0,0.0]. Poisson reconstruction filter requires a set of valid per-vertex normal. Filter will be aborted.");
        return false;
    }

    int cnt=0;
	for(CMeshO::VertexIterator vi=m.cm.vert.begin(); vi!=m.cm.vert.end(); ++vi)
	if(!(*vi).IsD()){
			(*vi).N().Normalize();
			for(int ii=0;ii<3;++ii){
					Pts[cnt].coords[ii]=(*vi).P()[ii];
					Nor[cnt].coords[ii]=(*vi).N()[ii];
			}
			++cnt;
		}
	assert(cnt==m.cm.vn);
	// Log function dump textual info in the lower part of the MeshLab screen. 
	PoissonParam pp;
	pp.Depth=par.getInt("OctDepth");
	pp.SamplesPerNode = par.getFloat("SamplesPerNode");
	pp.SolverDivide=par.getInt("SolverDivide");
	pp.Offset = par.getFloat("Offset");
	Point3D<float> center;
	float scale;
	
	int ret= Execute2(pp, Pts, Nor, mesh,center,scale,cb);
	mesh.resetIterator();
	int vm = mesh.outOfCorePointCount()+mesh.inCorePoints.size();
	int fm = mesh.triangleCount();

	Log("Successfully created a mesh of %i vert and %i faces",vm,fm);
	
	//m.cm.Clear();
	
	tri::Allocator<CMeshO>::AddVertices(pm.cm,vm);
	tri::Allocator<CMeshO>::AddFaces(pm.cm,fm);

  Point3D<float> p;
	int i;
	for (i=0; i < int(mesh.inCorePoints.size()); i++){
		p=mesh.inCorePoints[i];
		pm.cm.vert[i].P()[0] = p.coords[0]*scale+center.coords[0];
		pm.cm.vert[i].P()[1] = p.coords[1]*scale+center.coords[1];
		pm.cm.vert[i].P()[2] = p.coords[2]*scale+center.coords[2];
		}
	for (int ii=0; ii < mesh.outOfCorePointCount(); ii++){
		mesh.nextOutOfCorePoint(p);
		pm.cm.vert[ii+i].P()[0] = p.coords[0]*scale+center.coords[0];
		pm.cm.vert[ii+i].P()[1] = p.coords[1]*scale+center.coords[1];
		pm.cm.vert[ii+i].P()[2] = p.coords[2]*scale+center.coords[2];
	}

TriangleIndex tIndex;
int inCoreFlag;
int nr_faces=mesh.triangleCount();	
for (i=0; i < nr_faces; i++){
		//
		// create and fill a struct that the ply code can handle
		//
		mesh.nextTriangle(tIndex,inCoreFlag);
		if(!(inCoreFlag & CoredMeshData::IN_CORE_FLAG[0])){tIndex.idx[0]+=int(mesh.inCorePoints.size());}
		if(!(inCoreFlag & CoredMeshData::IN_CORE_FLAG[1])){tIndex.idx[1]+=int(mesh.inCorePoints.size());}
		if(!(inCoreFlag & CoredMeshData::IN_CORE_FLAG[2])){tIndex.idx[2]+=int(mesh.inCorePoints.size());}
		for(int j=0; j < 3; j++)
		{
			pm.cm.face[i].V(j) = &pm.cm.vert[tIndex.idx[j]];
		}
		//ply_put_element(ply, (void *) &ply_face);
		//delete[] ply_face.vertices;
	}  // for, write faces


//	for(int i=0;i<mesh.inCorePoints.size();++i){
//		mesh.triangles[i].idx[0]+=mesh.inCorePoints.size();
//		mesh.triangles[i].idx[1]+=mesh.inCorePoints.size();
//		mesh.triangles[i].idx[2]+=mesh.inCorePoints.size();
//		}
//	Build(m.cm,mesh.inCorePoints,mesh.triangles);
	Log("Successfully created a mesh of %i faces",pm.cm.vn);
	
	pm.UpdateBoxAndNormals();
	return true;
}
コード例 #15
0
ファイル: filter_csg.cpp プロジェクト: yuhan120483/dcba
bool FilterCSG::applyFilter(QAction *filter, MeshDocument &md, RichParameterSet & par, vcg::CallBackPos *cb)
{
    switch(ID(filter)) {
    case FP_CSG:
        {
            MeshModel *firstMesh = par.getMesh("FirstMesh");
            MeshModel *secondMesh = par.getMesh("SecondMesh");

            firstMesh->updateDataMask(MeshModel::MM_FACEFACETOPO | MeshModel::MM_FACENORMAL | MeshModel::MM_FACEQUALITY);
            secondMesh->updateDataMask(MeshModel::MM_FACEFACETOPO | MeshModel::MM_FACENORMAL | MeshModel::MM_FACEQUALITY);
            if (!isValid (firstMesh->cm, this->errorMessage) || !isValid (secondMesh->cm, this->errorMessage))
                return false;

            firstMesh->updateDataMask(MeshModel::MM_FACENORMAL | MeshModel::MM_FACEQUALITY);
            secondMesh->updateDataMask(MeshModel::MM_FACENORMAL | MeshModel::MM_FACEQUALITY);

            typedef CMeshO::ScalarType scalar;
            typedef Intercept<mpq_class,scalar> intercept;
            const scalar d = par.getFloat("Delta");
            const Point3f delta(d, d, d);
            const int subFreq = par.getInt("SubDelta");
            Log(0, "Rasterizing first volume...");
            InterceptVolume<intercept> v = InterceptSet3<intercept>(firstMesh->cm, delta, subFreq, cb);
            Log(0, "Rasterizing second volume...");
            InterceptVolume<intercept> tmp = InterceptSet3<intercept>(secondMesh->cm, delta, subFreq, cb);

            MeshModel *mesh;
            switch(par.getEnum("Operator")){
            case CSG_OPERATION_INTERSECTION:
                Log(0, "Intersection...");
                v &= tmp;
                mesh = md.addNewMesh("","intersection");
                break;

            case CSG_OPERATION_UNION:
                Log(0, "Union...");
                v |= tmp;
                mesh = md.addNewMesh("","union");
                break;

            case CSG_OPERATION_DIFFERENCE:
                Log(0, "Difference...");
                v -= tmp;
                mesh = md.addNewMesh("","difference");
                break;

            default:
                assert(0);
                return true;
            }

            Log(0, "Building mesh...");
            typedef vcg::intercept::Walker<CMeshO, intercept> MyWalker;
            MyWalker walker;
            if (par.getBool("Extended")) {
                mesh->updateDataMask(MeshModel::MM_FACEFACETOPO);
                typedef vcg::tri::ExtendedMarchingCubes<CMeshO, MyWalker> MyExtendedMarchingCubes;
                MyExtendedMarchingCubes mc(mesh->cm, walker);
                walker.BuildMesh<MyExtendedMarchingCubes>(mesh->cm, v, mc, cb);
            } else {
                typedef vcg::tri::MarchingCubes<CMeshO, MyWalker> MyMarchingCubes;
                MyWalker walker;
                MyMarchingCubes mc(mesh->cm, walker);
                walker.BuildMesh<MyMarchingCubes>(mesh->cm, v, mc, cb);
            }
            Log(0, "Done");

            vcg::tri::UpdateBounding<CMeshO>::Box(mesh->cm);
            vcg::tri::UpdateNormal<CMeshO>::PerFaceFromCurrentVertexNormal(mesh->cm);
        }
        return true;

    default:
        assert (0);
    }
    return true;
}
コード例 #16
0
ファイル: filter_sdf+.cpp プロジェクト: GuoXinxiao/meshlab
bool SdfPlugin::applyFilter(MeshDocument& md, RichParameterSet& pars, vcg::CallBackPos* cb){
  enum ONPRIMITIVE{ON_VERTICES, ON_FACES} onPrimitive;
  MeshModel* mm = md.mm();
  CMeshO& m = mm->cm;

  //--- Retrieve parameters
  float widenessRad = math::ToRad(pars.getFloat("coneWidth"));
  int raysPerCone = pars.getInt("numberRays");
  onPrimitive = (ONPRIMITIVE) pars.getEnum("onPrimitive");
  qDebug() << "which primitive?" << onPrimitive;
  float lo01pec = pars.getFloat("lowQuantile");
  float hi01pec = pars.getFloat("hiQuantile");
  assert( onPrimitive==ON_VERTICES && "Face mode not supported yet" );
  
  //--- 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);
  tri::UpdateNormals<CMeshO>::PerFaceNormalized(m);
  tri::UpdateNormals<CMeshO>::PerVertexAngleWeighted(m);
  tri::UpdateNormals<CMeshO>::NormalizeVertex(m);
  tri::UpdateFlags<CMeshO>::FaceProjection(m);
    
  //--- Enable & Reset the necessary attributes
  switch(onPrimitive){
    case ON_VERTICES:   
      // qDebug() << "initializing vert quality";
      mm->updateDataMask(MeshModel::MM_VERTQUALITY); 
      tri::UpdateQuality<CMeshO>::VertexConstant(m,0);
      break;
    case ON_FACES:   
      mm->updateDataMask(MeshModel::MM_FACEQUALITY); 
      tri::UpdateQuality<CMeshO>::FaceConstant(m,0);
      break; 
  }
  
  //--- Add the mesh to an indexing structure (fast ray intersection)
  Log("Initializing spatial accelleration...");
  mm->updateDataMask(MeshModel::MM_FACEMARK);
  TriMeshGrid static_grid; //TODO: rename spatial index
  static_grid.Set(m.face.begin(), m.face.end());
  Log("Initializing spatial accelleration... DONE!");
   
  // since we are measuring the interior of the shape
  // A ray should never go beyond this value 
  float maxDist=m.bbox.Diag();
  // This is a small number to avoid self-intersection during ray 
  // casting. It's a very common trick
  float epsilon = maxDist / 10000.0; 

  //--- Ray casting
  vector<Ray3f> cone;
  vector<float> coneSdf;
  Ray3f ray; 
  float t;
  for(unsigned int i=0; i<m.vert.size(); i++){
    CVertexO& v = m.vert[i];
    //--- Update progressbar
    cb( i/m.vert.size(), "Casting rays into volume...");
    
    //--- Generate the set of cones
    ray.Set( v.P(), -v.N() );
    ray.SetOrigin( ray.P(epsilon) );
    generateRayCone( ray, widenessRad, raysPerCone, cone, coneSdf, (i==266) );
        
    //--- Trace rays in cone
    float mind = +numeric_limits<float>::max();
    float maxd = -numeric_limits<float>::max();
    for(unsigned int j=0; j<cone.size(); j++){
      bool hasInt = tri::DoRay<CMeshO,TriMeshGrid>(m,static_grid,cone[j],maxDist,t);
      coneSdf[j] = (hasInt==true) ? t : numeric_limits<float>::quiet_NaN();
      mind = (hasInt && (t<mind)) ? t : mind;
      maxd = (hasInt && (t>maxd)) ? t : maxd;

      if( i==266 ){
        qDebug() << " sampled: " << coneSdf[j] 
                 << " dir: " << toString(cone[j].Direction())
                 << " hasInt: " << hasInt;
      }
    }
    
    //--- Compute per-cone statistics
    Histogram<float> H;
    H.Clear();
    H.SetRange( mind, maxd, 100);
    for(unsigned int j=0; j<cone.size(); j++)
      if(!math::IsNAN(coneSdf[j]))
        H.Add(coneSdf[j]);
    float loperc = H.Percentile(lo01pec);
    float hiperc = H.Percentile(hi01pec);

    if( i == 266){
      qDebug() << "percentiles: " << loperc << " " << hiperc;
    }
    
    
    //--- Compute average of samples, throwing away outliers
    if( i == 266) 
      qDebug() << "averaging samples";
    float totVal = 0, totCnt = 0;
    for(unsigned int j=0; j<coneSdf.size(); j++)
      if( !math::IsNAN(coneSdf[j]) ){
        // Histogram statistics valid only for dense sets (more 3 members..)
        if( coneSdf[j]<loperc || coneSdf[j]>hiperc && coneSdf.size()>3) 
          continue;
        
        // Weight giving more importance to aligned samples
        float weight = cone[j].Direction().dot( ray.Direction() );
        // Even more importance
        weight = powf( weight, 10 );
        
        if( i==266 ){
          qDebug() << "sampled: " << coneSdf[j] << "weight " << weight 
                   << " dir:" << toString(cone[j].Direction());
        }
        
        totVal += weight*coneSdf[j];
        totCnt += weight;
      } 
         
    //--- Save in mesh
    v.Q() = totCnt>0 ? (totVal/totCnt) : 0;
  }

  //----------------------------------------------------------------------------//
  // 
  //                          STEROIDS STARTS HERE 
  //
  //----------------------------------------------------------------------------//
  //--- Create the medial cloud by offsetting the samples of the medial amount
  MeshModel* medCloud = md.addNewMesh("medial cloud.obj", NULL, false);
  for(unsigned int i=0; i<m.vert.size(); i++){
    Ray3f r;
    r.Set(m.vert[i].P(), -m.vert[i].N());
    tri::Allocator<CMeshO>::AddVertices(medCloud->cm,1);
    medCloud->cm.vert.back().P() = r.P(m.vert[i].Q() / 2 );
  }
  
  //--- Data for distance queries
  vcg::tri::FaceTmark<CMeshO> mf; 
  mf.SetMesh( &m );
  vcg::face::PointDistanceBaseFunctor<float> PDistFunct;
    
  Log("querying real distances");
  
  // Query the location of closest point on the mesh, then measure the difference
  float allowedDiff = .02;
  vector<float> realdistances(m.vn, 0);
  for(unsigned int i=0; i<m.vert.size(); i++){
    Point3f currp = medCloud->cm.vert[i].P();
    float minDist = maxDist;
    Point3f closest;  
    GridClosest(static_grid, PDistFunct, mf, currp, maxDist, minDist, closest);  
    float difference = m.vert[i].Q()/2.0 - minDist;
    m.vert[i].Q() = exp( -powf(difference/allowedDiff,2) );
  }
 
  // Correct the viewmodel so that after this is done the original mesh
  // is shown in wireframe and the medial as a cloud.
  // mm->glw.cdm = vcg::GLW::DMWire; // show original mesh in wireframe
  medCloud->glw.cdm = vcg::GLW::DMPoints; // show cloud
  return true;
}
コード例 #17
0
ファイル: filter_create.cpp プロジェクト: bouffa/meshlab
// The Real Core Function doing the actual mesh processing.
bool FilterCreate::applyFilter(QAction *filter, MeshDocument &md, RichParameterSet & par, CallBackPos * /*cb*/)
{
	MeshModel & currM = *md.mm();
	MeshModel* m;

	switch(ID(filter))	 
	{
	case CR_TETRAHEDRON :
		m = md.addNewMesh("", this->filterName(ID(filter)));
		tri::Tetrahedron<CMeshO>(m->cm);
		break;
    case CR_ICOSAHEDRON:
		m = md.addNewMesh("", this->filterName(ID(filter)));
		tri::Icosahedron<CMeshO>(m->cm);
		break;
	case CR_DODECAHEDRON:
		m = md.addNewMesh("", this->filterName(ID(filter)));
		tri::Dodecahedron<CMeshO>(m->cm);
		m->updateDataMask(MeshModel::MM_POLYGONAL);
		break;
	case CR_OCTAHEDRON:
		m = md.addNewMesh("", this->filterName(ID(filter)));
		tri::Octahedron<CMeshO>(m->cm);
		break;
	case CR_ANNULUS:
		m = md.addNewMesh("", this->filterName(ID(filter)));
		tri::Annulus<CMeshO>(m->cm,par.getFloat("internalRadius"), par.getFloat("externalRadius"), par.getInt("sides"));
      break;

	case CR_TORUS:
    {
		m = md.addNewMesh("", this->filterName(ID(filter)));
		float hRadius=par.getFloat("hRadius");
		float vRadius=par.getFloat("vRadius");
		int hSubdiv=par.getInt("hSubdiv");
		int vSubdiv=par.getInt("vSubdiv");
		tri::Torus(m->cm,hRadius,vRadius,hSubdiv,vSubdiv);
	} break;

	case CR_FITPLANE:
	{
		Box3m selBox; //boundingbox of the selected vertices
		std::vector< Point3m > selected_pts; //copy of selected vertices, for plane fitting

		if (&currM == NULL)
		{
			errorMessage = "No mesh layer selected"; 
			return false;
		}

		if (currM.cm.svn == 0 && currM.cm.sfn == 0) // if no selection, fail
		{
			errorMessage = "No selection";
			return false;
		}

		m = md.addNewMesh("", "Fitted Plane");

		if (currM.cm.svn == 0 || currM.cm.sfn != 0)
		{
			tri::UpdateSelection<CMeshO>::VertexClear(currM.cm);
			tri::UpdateSelection<CMeshO>::VertexFromFaceLoose(currM.cm);
		}

		Point3m Naccum = Point3m(0.0, 0.0, 0.0);
		for (CMeshO::VertexIterator vi = currM.cm.vert.begin(); vi != currM.cm.vert.end(); ++vi)
		if (!(*vi).IsD() && (*vi).IsS())
		{
			Point3m p = (*vi).P();
			selBox.Add(p);
			selected_pts.push_back(p);
			Naccum = Naccum + (*vi).N();
		}
		Log("Using %i vertexes to build a fitting  plane", int(selected_pts.size()));
		Plane3m plane;
		FitPlaneToPointSet(selected_pts, plane);
		plane.Normalize();
		// check if normal of the interpolated plane is coherent with average normal of the used points, otherwise, flip
		// i do this because plane fitter does not take in account source noramls, and a fliped fit is terrible to see
		Naccum = (Naccum / (CMeshO::ScalarType)selected_pts.size()).Normalize();
		if ((plane.Direction() * Naccum) < 0.0)
			plane.Set(-plane.Direction(), -plane.Offset());

		float errorSum = 0;
		for (size_t i = 0; i < selected_pts.size(); ++i)
			errorSum += fabs(SignedDistancePlanePoint(plane, selected_pts[i]));
		Log("Fitting Plane avg error is %f", errorSum / float(selected_pts.size()));
		Log("Fitting Plane normal is [%f, %f, %f]", plane.Direction().X(), plane.Direction().Y(), plane.Direction().Z());
		Log("Fitting Plane offset is %f", plane.Offset());

		// find center of selection on plane
		Point3m centerP;
		for (size_t i = 0; i < selected_pts.size(); ++i)
		{
			centerP += plane.Projection(selected_pts[i]);
		}
		centerP /= selected_pts.size();
		Log("center [%f, %f, %f]", centerP.X(), centerP.Y(), centerP.Z());

		// find horizontal and vertical axis
		Point3m dirH, dirV;

		int orientation = par.getEnum("orientation");

		if (orientation == 0)
		{
			if ((plane.Direction().X() <= plane.Direction().Y()) && (plane.Direction().X() <= plane.Direction().Z()))
			dirH = Point3m(1.0, 0.0, 0.0) ^ plane.Direction();
			else if ((plane.Direction().Y() <= plane.Direction().X()) && (plane.Direction().Y() <= plane.Direction().Z()))
				dirH = Point3m(0.0, 1.0, 0.0) ^ plane.Direction();
			else
				dirH = Point3m(0.0, 0.0, 1.0) ^ plane.Direction();

			dirH.Normalize();
			dirV = dirH ^ plane.Direction();
			dirV.Normalize();
		}
		else
		{
			Matrix33m cov;
			vector<Point3m> PtVec;
			for (size_t i = 0; i < selected_pts.size(); ++i)
				PtVec.push_back(plane.Projection(selected_pts[i]));

			cov.Covariance(PtVec, centerP);
			Matrix33f eigenvecMatrix;
			Point3f eigenvecVector;
			Eigen::Matrix3d em;
			cov.ToEigenMatrix(em);
			Eigen::SelfAdjointEigenSolver<Eigen::Matrix3d> eig(em);
			Eigen::Vector3d c_val = eig.eigenvalues();
			Eigen::Matrix3d c_vec = eig.eigenvectors();

			eigenvecMatrix.FromEigenMatrix(c_vec);
			eigenvecVector.FromEigenVector(c_val);

			// max eigenvector is best horizontal axis, but is not guarantee is orthogonal to plane normal, so
			// I use eigenvector ^ plane direction and assign it to vertical plane axis
			if ((eigenvecVector[0]<=eigenvecVector[1]) && (eigenvecVector[0]<=eigenvecVector[2]))
				dirV = Point3m(eigenvecMatrix[0][0], eigenvecMatrix[0][1], eigenvecMatrix[0][2]) ^ plane.Direction();
			if ((eigenvecVector[1]<=eigenvecVector[0]) && (eigenvecVector[1]<=eigenvecVector[2]))
				dirV = Point3m(eigenvecMatrix[1][0], eigenvecMatrix[1][1], eigenvecMatrix[1][2]) ^ plane.Direction();
			else
				dirV = Point3m(eigenvecMatrix[2][0], eigenvecMatrix[2][1], eigenvecMatrix[2][2]) ^ plane.Direction();

			dirV.Normalize();
			dirH = plane.Direction() ^ dirV;
			dirH.Normalize();
		}

		Log("H [%f, %f, %f]", dirH.X(), dirH.Y(), dirH.Z());
		Log("V [%f, %f, %f]", dirV.X(), dirV.Y(), dirV.Z());


		// find extent
		float dimH = -1000000;
		float dimV = -1000000;
		for (size_t i = 0; i < selected_pts.size(); ++i)
		{
			Point3m pp = plane.Projection(selected_pts[i]);
			float distH = fabs(((pp - centerP) * dirH));
			float distV = fabs(((pp - centerP) * dirV));

			if (distH > dimH)
				dimH = distH;
			if (distV > dimV)
				dimV = distV;
		}
		float exScale = par.getFloat("extent");
		dimV = dimV * exScale;
		dimH = dimH * exScale;
		Log("extent on plane [%f, %f]", dimV, dimH);

		int vertNum = par.getInt("subdiv") + 1;
		if (vertNum <= 1) vertNum = 2;
		int numV, numH;
		numV = numH = vertNum;

		// UV vector, just in case
		float *UUs, *VVs;
		UUs = new float[numH*numV];
		VVs = new float[numH*numV];

		int vind = 0;
		for (int ir = 0; ir < numV; ir++)
		for (int ic = 0; ic < numH; ic++)
			{
				Point3m newP = (centerP + (dirV * -dimV) + (dirH * -dimH)); 
				newP = newP + (dirH * ic * (2.0 * dimH / (numH-1))) + (dirV * ir * (2.0 * dimV / (numV-1)));
				tri::Allocator<CMeshO>::AddVertex(m->cm, newP, plane.Direction());
				UUs[vind] = ic * (1.0 / (numH - 1));
				VVs[vind] = ir * (1.0 / (numV - 1));
				vind++;
			}
		
		FaceGrid(m->cm, numH, numV);

		bool hasUV = par.getBool("hasuv");
		if (hasUV)
		{
			m->updateDataMask(MeshModel::MM_WEDGTEXCOORD);

			CMeshO::FaceIterator fi;
			for (fi = m->cm.face.begin(); fi != m->cm.face.end(); ++fi)
			{
				for (int i = 0; i<3; ++i)
				{
					int vind = (*fi).V(i)->Index();
					(*fi).WT(i).U() = UUs[vind];
					(*fi).WT(i).V() = VVs[vind];
				}
			}
		}
		delete[] UUs;	// delete temporary UV storage
		delete[] VVs;

	} break;

	case CR_RANDOM_SPHERE:
	{
		int pointNum = par.getInt("pointNum");
		int sphereGenTech = par.getEnum("sphereGenTech");
		math::MarsenneTwisterRNG rng;
		m = md.addNewMesh("", this->filterName(ID(filter)));
		m->cm.Clear();
		std::vector<Point3m> sampleVec;


		switch(sphereGenTech)
		{
			case 0: // Montecarlo
			{
				for(int i=0;i<pointNum;++i)
					sampleVec.push_back(math::GeneratePointOnUnitSphereUniform<CMeshO::ScalarType>(rng));
			} break;
			case 1: // Poisson Disk
			{
				int oversamplingFactor =100;
				if(pointNum <= 100) oversamplingFactor = 1000;
				if(pointNum >= 10000) oversamplingFactor = 50;
				if(pointNum >= 100000) oversamplingFactor = 20;
				CMeshO tt;
				tri::Allocator<CMeshO>::AddVertices(tt,pointNum*oversamplingFactor);
				for(CMeshO::VertexIterator vi=tt.vert.begin();vi!=tt.vert.end();++vi)
					vi->P()=math::GeneratePointOnUnitSphereUniform<CMeshO::ScalarType>(rng);
				tri::UpdateBounding<CMeshO>::Box(tt);

				const float SphereArea = 4*M_PI;
				float poissonRadius = 2.0*sqrt((SphereArea / float(pointNum*2))/M_PI);

				std::vector<Point3m> sampleVec;
				tri::TrivialSampler<CMeshO> pdSampler(sampleVec);
				tri::SurfaceSampling<CMeshO, tri::TrivialSampler<CMeshO> >::PoissonDiskParam pp;
				tri::SurfaceSampling<CMeshO,tri::TrivialSampler<CMeshO> >::PoissonDiskPruning(pdSampler, tt, poissonRadius, pp);
			} break;
			case 2: // Disco Ball
				GenNormal<CMeshO::ScalarType>::DiscoBall(pointNum,sampleVec);
				break;
			case 3: // Recursive Oct
				GenNormal<CMeshO::ScalarType>::RecursiveOctahedron(pointNum,sampleVec);
				break;
			case 4: // Fibonacci
				GenNormal<CMeshO::ScalarType>::Fibonacci(pointNum,sampleVec);
				break;
		}
		for(size_t i=0;i<sampleVec.size();++i)
			tri::Allocator<CMeshO>::AddVertex(m->cm,sampleVec[i],sampleVec[i]);
	} break;

	case CR_SPHERE_CAP:
	{
		int rec = par.getInt("subdiv");
		const float angleDeg = par.getFloat("angle");
		m = md.addNewMesh("", this->filterName(ID(filter)));
		m->updateDataMask(MeshModel::MM_FACEFACETOPO);
		tri::UpdateTopology<CMeshO>::FaceFace(m->cm);
		tri::SphericalCap(m->cm,math::ToRad(angleDeg),rec);
	} break;

	case CR_SPHERE:
    {
		int rec = par.getInt("subdiv");
		float radius = par.getFloat("radius");
		m = md.addNewMesh("", this->filterName(ID(filter)));
		m->cm.face.EnableFFAdjacency();
		m->updateDataMask(MeshModel::MM_FACEFACETOPO);
		assert(tri::HasPerVertexTexCoord(m->cm) == false);
		tri::Sphere<CMeshO>(m->cm,rec);
		tri::UpdatePosition<CMeshO>::Scale(m->cm,radius);
	} break;

    case CR_BOX:
    {
      float sz=par.getFloat("size");
      Box3m b(Point3m(1,1,1)*(-sz/2),Point3m(1,1,1)*(sz/2));
	  m = md.addNewMesh("", this->filterName(ID(filter)));
      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");
		m = md.addNewMesh("", this->filterName(ID(filter)));
		tri::Cone<CMeshO>(m->cm, r0, r1, h, subdiv);
	} break;

	}//CASE FILTER

	tri::UpdateBounding<CMeshO>::Box(m->cm);
	tri::UpdateNormal<CMeshO>::PerVertexNormalizedPerFaceNormalized(m->cm);
    return true;
}
コード例 #18
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;
}
コード例 #19
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);
        m->updateDataMask(MeshModel::MM_VERTQUALITY); // needed to store patch index

        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;
        }
        tri::ParamEdgeCollapseParameter pecp;
        IsoParametrizator::ReturnCode ret=Parametrizator.Parametrize<CMeshO>(mesh,pecp,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);
            switch(ret)
            {
            case IsoParametrizator::MultiComponent:
                this->errorMessage="non possible parameterization because of multi componet mesh";
                return false;
            case IsoParametrizator::NonSizeCons:
                this->errorMessage="non possible parameterization because of non size consistent mesh";
                return false;
            case IsoParametrizator::NonManifoldE:
                this->errorMessage="non possible parameterization because of non manifold edges";
                return false;
            case IsoParametrizator::NonManifoldV:
                this->errorMessage="non possible parameterization because of non manifold vertices";
                return false;
            case IsoParametrizator::NonWatertigh:
                this->errorMessage="non possible parameterization because of non watertight mesh";
                return false;
            case IsoParametrizator::FailParam:
                this->errorMessage="non possible parameterization cause one of the following reasons:\n Topologycal noise \n Too Low resolution mesh \n Too Bad triangulation \n";
                return false;
            default:
                this->errorMessage="unknown error";
                return false;
            }
        }
        // At this point we are sure that everithing went ok so we can allocate surely the abstract
        AbstractMesh *abs_mesh = new AbstractMesh();
        ParamMesh *para_mesh = new ParamMesh();
        Parametrizator.ExportMeshes(*para_mesh,*abs_mesh);
        CMeshO::PerMeshAttributeHandle<IsoParametrization> isoPHandle;
        isoPHandle=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)
        {
            this->errorMessage="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 :
    {
        CMeshO::PerMeshAttributeHandle<IsoParametrization> isoPHandle =
            tri::Allocator<CMeshO>::FindPerMeshAttribute<IsoParametrization>(*mesh,"isoparametrization");

        bool b=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");
        if (!SamplingRate>2)
        {
            this->errorMessage="Sampling rate must be >1";
            return false;
        }
        MeshModel* mm=md.addNewMesh("","Re-meshed");

        CMeshO *rem=&mm->cm;
        DiamSampler DiamSampl;
        DiamSampl.Init(&isoPHandle());
        bool done=DiamSampl.SamplePos(SamplingRate);
        assert(done);
        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);
        tri::UpdateNormal<CMeshO>::PerFace(*rem);
        return true;
    }
    case ISOP_DIAMPARAM :
    {
        CMeshO::PerMeshAttributeHandle<IsoParametrization> isoPHandle =
            tri::Allocator<CMeshO>::FindPerMeshAttribute<IsoParametrization>(*mesh,"isoparametrization");
        bool b=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);
        tri::UpdateNormal<CMeshO>::PerFace(*rem);
        return true;
    }
    case ISOP_LOAD :
    {
        QString AbsName = par.getString("AbsName");
        m->updateDataMask(MeshModel::MM_WEDGTEXCOORD);
        m->updateDataMask(MeshModel::MM_VERTTEXCOORD);
        m->updateDataMask(MeshModel::MM_FACECOLOR);
        m->updateDataMask(MeshModel::MM_VERTQUALITY);
        m->updateDataMask(MeshModel::MM_FACEMARK);
        if(!QFile(m->fullName()).exists())
        {
            this->errorMessage="File not exists";
            return false;
        }
        CMeshO::PerMeshAttributeHandle<IsoParametrization> isoPHandle =
            tri::Allocator<CMeshO>::FindPerMeshAttribute<IsoParametrization>(*mesh,"isoparametrization");

        bool b=tri::Allocator<CMeshO>::IsValidHandle<IsoParametrization>(*mesh,isoPHandle);
        if (!b)
            isoPHandle=tri::Allocator<CMeshO>::AddPerMeshAttribute<IsoParametrization>(*mesh,"isoparametrization");

        QByteArray ba = AbsName.toLatin1();
        char *path=ba.data();
        AbstractMesh *abs_mesh = new AbstractMesh();
        ParamMesh *para_mesh = new ParamMesh();
        bool Done=isoPHandle().LoadBaseDomain<CMeshO>(path,mesh,para_mesh,abs_mesh,true);
        if (!Done)
        {
            this->errorMessage="Abstract domain doesnt fit well with the parametrized mesh";
            delete para_mesh;
            delete abs_mesh;
            return false;
        }
        return true;
    }
    case ISOP_SAVE :
    {
        m->updateDataMask(MeshModel::MM_VERTQUALITY);
        CMeshO::PerMeshAttributeHandle<IsoParametrization> isoPHandle =
            tri::Allocator<CMeshO>::FindPerMeshAttribute<IsoParametrization>(*mesh,"isoparametrization");

        bool b=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;
    }
    case ISOP_TRANSFER:
    {
        MeshModel *mmtrg = par.getMesh("targetMesh");
        MeshModel *mmsrc = par.getMesh("targetMesh");
        CMeshO *trgMesh=&mmtrg->cm;
        CMeshO *srcMesh=&mmsrc->cm;

        CMeshO::PerMeshAttributeHandle<IsoParametrization> isoPHandle =
            tri::Allocator<CMeshO>::FindPerMeshAttribute<IsoParametrization>(*mesh,"isoparametrization");

        bool b=tri::Allocator<CMeshO>::IsValidHandle<IsoParametrization>(*srcMesh,isoPHandle);
        if (!b)
        {
            this->errorMessage="Your source mesh must have the abstract isoparametrization. Use the Isoparametrization command.";
            return false;
        }
        IsoTransfer IsoTr;
        AbstractMesh *abs_mesh = isoPHandle().AbsMesh();
        ParamMesh *para_mesh = isoPHandle().ParaMesh();

        mmtrg->updateDataMask(MeshModel::MM_WEDGTEXCOORD);
        mmtrg->updateDataMask(MeshModel::MM_VERTTEXCOORD);
        mmtrg->updateDataMask(MeshModel::MM_FACECOLOR);
        mmtrg->updateDataMask(MeshModel::MM_VERTQUALITY);
        mmtrg->updateDataMask(MeshModel::MM_FACEMARK);
        IsoTr.Transfer<CMeshO>(isoPHandle(),*trgMesh);

        isoPHandle().Clear();
        tri::Allocator<CMeshO>::DeletePerMeshAttribute(*srcMesh,isoPHandle);

        isoPHandle=tri::Allocator<CMeshO>::AddPerMeshAttribute<IsoParametrization>(*trgMesh,"isoparametrization");
        isoPHandle().AbsMesh()=abs_mesh;
        isoPHandle().SetParamMesh<CMeshO>(trgMesh,para_mesh);

        return true;
    }
    }
    return false;
}