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;
}
Beispiel #2
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;
}