float Arc3DModel::ComputeDepthJumpThr(FloatImage &depthImgf, float percentile)
{
    Histogramf HH;
    HH.Clear();
    HH.SetRange(0,depthImgf.MaxVal()-depthImgf.MinVal(),10000);
    for(unsigned int i=1; i < static_cast<unsigned int>(depthImgf.v.size()); ++i)
        HH.Add(fabs(depthImgf.v[i]-depthImgf.v[i-1]));

    return HH.Percentile(percentile);
}
Exemple #2
0
/*
This function is used to choose remove outliers after each ICP iteration.
All the points with a distance over the given Percentile are discarded.
It uses two parameters
MaxPointNum an (unused) hard limit on the number of points that are choosen
MinPointNum the minimum number of points that have to be chosen to be usable

*/
bool AlignPair::ChoosePoints( 	vector<Point3d> &Ps,		// vertici corrispondenti su src (rossi)
																vector<Point3d> &Ns, 		// normali corrispondenti su src (rossi)
																vector<Point3d> &Pt,		// vertici scelti su trg (verdi) 
																vector<Point3d> &OPt,		// vertici scelti su trg (verdi) 
																double PassHi,
																Histogramf &H)
{
	const int N = ap.MaxPointNum;
  double newmaxd = H.Percentile(PassHi);
	//printf("%5.1f of the pairs has a distance less than %g and greater than %g (0..%g) avg %g\n",	Perc*100,newmind,newmaxd,H.maxv,H.Percentile(.5));
	int sz = Ps.size();
	int fnd=0;
	int lastgood=sz-1;
  math::SubtractiveRingRNG myrnd;
	while(fnd<N && fnd<lastgood)
	{
		int index = fnd+myrnd.generate(lastgood-fnd);
		double dd=Distance(Ps[index],Pt[index]);
    if(dd<=newmaxd)
		{
			swap(Ps[index],Ps[fnd]);
			swap(Ns[index],Ns[fnd]);
			swap(Pt[index],Pt[fnd]);
			swap(OPt[index],OPt[fnd]);
			++fnd;
		}
		else
		{
			swap(Ps[index],Ps[lastgood]);
			swap(Ns[index],Ns[lastgood]);
			swap(Pt[index],Pt[lastgood]);
			swap(OPt[index],OPt[lastgood]);
			lastgood--;
		}
	}
	Ps.resize(fnd);
	Ns.resize(fnd);
	Pt.resize(fnd);
	OPt.resize(fnd);
	printf("Scelte %i coppie tra le %i iniziali, scartate quelle con dist > %f\n",fnd,sz,newmaxd);
	
	if( (int)Ps.size()<ap.MinPointNum )		{
		printf("Troppi pochi punti!\n");
		Ps.clear();
		Ns.clear();
		Pt.clear();
		OPt.clear();
		return false;
	}
	return true;
}
void Arc3DModel::depthFilter(FloatImage &depthImgf, FloatImage &countImgf, float depthJumpThr,
    bool dilation, int dilationNumPasses, int dilationWinsize,
    bool erosion, int erosionNumPasses, int erosionWinsize)
{
    FloatImage depth;
    FloatImage depth2;
    int w = depthImgf.w;
    int h = depthImgf.h;

    depth=depthImgf;

    if (dilation)
    {
        for (int k = 0; k < dilationNumPasses; k++)
        {
            depth.Dilate(depth2, dilationWinsize / 2);
            depth=depth2;
        }
    }

    if (erosion)
    {
        for (int k = 0; k < erosionNumPasses; k++)
        {
            depth.Erode(depth2, erosionWinsize / 2);
            depth=depth2;
        }
    }

    Histogramf HH;
    HH.Clear();
    HH.SetRange(0,depthImgf.MaxVal()-depthImgf.MinVal(),10000);
    for(int i=1; i < static_cast<int>(depthImgf.v.size()); ++i)
        HH.Add(fabs(depthImgf.v[i]-depth.v[i-1]));

    int deletedCnt=0;

    depthJumpThr = HH.Percentile(0.8f);
    for (int y = 0; y < h; y++)
        for (int x = 0; x < w; x++)
        {
            if ((depthImgf.Val(x, y) - depth.Val(x, y)) / depthImgf.Val(x, y) > 0.6)
            {
                countImgf.Val(x, y) = 0.0f;
                ++deletedCnt;
            }
        }

        countImgf.convertToQImage().save("tmp_filteredcount.jpg","jpg");

}
Exemple #4
0
void EpochModel::depthFilter(FloatImage &depthImgf, FloatImage &countImgf, float depthJumpThr, 
														 bool dilation, int dilationNumPasses, int dilationWinsize,
														 bool erosion, int erosionNumPasses, int erosionWinsize)
{
	FloatImage depth;
	FloatImage depth2;
	int w = depthImgf.w;
	int h = depthImgf.h;
	
	depth=depthImgf;

	if (dilation)
	{
		for (int k = 0; k < dilationNumPasses; k++)
		{
			depth.Dilate(depth2, dilationWinsize / 2);
			depth=depth2;
		}
	}

	if (erosion)
	{
		for (int k = 0; k < erosionNumPasses; k++)
		{
			depth.Erode(depth2, erosionWinsize / 2);
			depth=depth2;
		}
	}

  Histogramf HH;
  HH.Clear();
  HH.SetRange(0,depthImgf.MaxVal()-depthImgf.MinVal(),10000);
  for(int i=1; i < static_cast<int>(depthImgf.v.size()); ++i)
    HH.Add(fabs(depthImgf.v[i]-depth.v[i-1]));

  if(logFP) fprintf(logFP,"**** Depth histogram 2 Min %f Max %f Avg %f Percentiles ((10)%f (25)%f (50)%f (75)%f (90)%f)\n",HH.MinV(),HH.MaxV(),HH.Avg(),
        HH.Percentile(.1),HH.Percentile(.25),HH.Percentile(.5),HH.Percentile(.75),HH.Percentile(.9));

  int deletedCnt=0;
  
  depthJumpThr = static_cast<float>(HH.Percentile(0.8));
	for (int y = 0; y < h; y++)
		for (int x = 0; x < w; x++)
		{
				if ((depthImgf.Val(x, y) - depth.Val(x, y)) / depthImgf.Val(x, y) > 0.6)
        {
					countImgf.Val(x, y) = 0.0f;
          ++deletedCnt;
        }
		}

	countImgf.convertToQImage().save("tmp_filteredcount.jpg","jpg");
  
  if(logFP) fprintf(logFP,"**** depthFilter: deleted %i on %i\n",deletedCnt,w*h);

}
Exemple #5
0
float EpochModel::ComputeDepthJumpThr(FloatImage &depthImgf, float percentile)
{
  Histogramf HH;
  HH.Clear();
  HH.SetRange(0,depthImgf.MaxVal()-depthImgf.MinVal(),10000);
  for(unsigned int i=1; i < static_cast<unsigned int>(depthImgf.v.size()); ++i)
    HH.Add(fabs(depthImgf.v[i]-depthImgf.v[i-1]));

  if(logFP) fprintf(logFP,"**** Depth histogram Min %f Max %f Avg %f Percentiles ((10)%f (25)%f (50)%f (75)%f (90)%f)\n",HH.MinV(),HH.MaxV(),HH.Avg(),
        HH.Percentile(.1),HH.Percentile(.25),HH.Percentile(.5),HH.Percentile(.75),HH.Percentile(.9));
  
  return HH.Percentile(percentile);
}
Exemple #6
0
bool AlignPair::Align(
						A2Grid &u,
            A2GridVert &uv,
  		const	Matrix44d &in,					// trasformazione Iniziale (che porta i punti di mov su fix)
						Matrix44d &out,					// trasformazione calcolata
						vector<Point3d> &Pfix,		// vertici corrispondenti su src (rossi)
						vector<Point3d> &Nfix, 		// normali corrispondenti su src (rossi)
						vector<Point3d> &OPmov,		// vertici scelti su trg (verdi) prima della trasformazione in ingresso (Original Point Target)
						vector<Point3d> &ONmov, 		// normali scelti su trg (verdi)
						Histogramf &H,
						AlignPair::Stat &as)
{	
  vector<char> beyondCntVec;    // vettore per marcare i movvert che sicuramente non si devono usare
	                      // ogni volta che un vertice si trova a distanza oltre max dist viene incrementato il suo contatore;
												// i movvert che sono stati scartati piu' di MaxCntDist volte non si guardano piu';
  const int maxBeyondCnt=3;
	vector< Point3d > movvert;
	vector< Point3d > movnorm;
	vector<Point3d> Pmov; // vertici scelti dopo la trasf iniziale
	status=SUCCESS;
	int tt0=clock();  

	out=in;
	
	int i;

	double CosAngleThr=cos(ap.MaxAngleRad);
	double StartMinDist=ap.MinDistAbs;
	int tt1=clock();  
	int ttsearch=0;
	int ttleast=0;
	int nc=0;
	as.clear();
	as.StartTime=clock();
			
	beyondCntVec.resize(mov->size(),0);

  /**************** BEGIN ICP LOOP ****************/
    do
	{	
		Stat::IterInfo ii;
		Box3d movbox;
		InitMov(movvert,movnorm,movbox,out);
		H.SetRange(0,StartMinDist,512,2.5);
		Pfix.clear();
		Nfix.clear();
		Pmov.clear();
		OPmov.clear();
		ONmov.clear();
		int tts0=clock();
		ii.MinDistAbs=StartMinDist;
    int LocSampleNum=min(ap.SampleNum,int(movvert.size()));
    Box3d fixbox;
    if(u.Empty()) fixbox = uv.bbox;
    else fixbox = u.bbox;
    for(i=0;i<LocSampleNum;++i)
    {
      if( beyondCntVec[i] < maxBeyondCnt )
        if(! fixbox.IsIn(movvert[i]) )
          beyondCntVec[i]=maxBeyondCnt+1;
      else
      {
        double error=StartMinDist;
        Point3d closestPoint, closestNormal;
        double maxd= StartMinDist;
        ii.SampleTested++;
        if(u.Empty()) // using the point cloud grid
        {
          A2Mesh::VertexPointer vp = tri::GetClosestVertex(*fix,uv,movvert[i], maxd, error);
          if(error>=StartMinDist) {
            ii.DistanceDiscarded++; ++beyondCntVec[i]; continue;
          }
          if(movnorm[i].dot(vp->N()) < CosAngleThr) {
              ii.AngleDiscarded++; continue;
          }
          closestPoint=vp->P();
          closestNormal=vp->N();
        }
        else // using the standard faces and grid
        {
          A2Mesh::FacePointer f=vcg::tri::GetClosestFaceBase<vcg::AlignPair::A2Mesh, vcg::AlignPair::A2Grid >(*fix, u, movvert[i], maxd, error, closestPoint);
          if(error>=StartMinDist) {
            ii.DistanceDiscarded++; ++beyondCntVec[i]; continue;
          }
          if(movnorm[i].dot(f->N()) < CosAngleThr) {
              ii.AngleDiscarded++; continue;
          }
          Point3d ip;
          InterpolationParameters<A2Face,double>(*f,f->N(),closestPoint, ip);
          const double IP_EPS = 0.00001;
          // If ip[i] == 0 it means that we are on the edge opposite to i
          if(	(fabs(ip[0])<=IP_EPS && f->IsB(1)) ||  (fabs(ip[1])<=IP_EPS && f->IsB(2)) || (fabs(ip[2])<=IP_EPS && f->IsB(0))   ){
            ii.BorderDiscarded++;  continue;
          }
          closestNormal = f->N();
        }
        // The sample was accepted. Store it.
        Pmov.push_back(movvert[i]);
        OPmov.push_back((*mov)[i].P());
        ONmov.push_back((*mov)[i].N());
        Nfix.push_back( closestNormal );
        Pfix.push_back( closestPoint );
        H.Add(float(error));
        ii.SampleUsed++;
      }
    } // End for each pmov
    int tts1=clock();
		//printf("Found %d pairs\n",(int)Pfix.size());
    if(!ChoosePoints(Pfix,Nfix,Pmov,OPmov,ap.PassHiFilter,H))
    if(int(Pfix.size())<ap.MinPointNum)
		{
			status = TOO_FEW_POINTS;
			ii.Time=clock();
			as.I.push_back(ii);
			return false;
		}
		Matrix44d newout;
		switch(ap.MatchMode) {
		case AlignPair::Param::MMSimilarity : ComputeRotoTranslationScalingMatchMatrix(newout,Pfix,OPmov); break;
		case AlignPair::Param::MMRigid   : ComputeRigidMatchMatrix(Pfix,OPmov,newout);   break;
			default :
						status = UNKNOWN_MODE;
						ii.Time=clock();
						as.I.push_back(ii);
						return false;
		}
					
//    double sum_before=0;
//    double sum_after=0;
//    for(unsigned int iii=0;iii<Pfix.size();++iii)
//    {
//      sum_before+=Distance(Pfix[iii], out*OPmov[iii]);
//      sum_after+=Distance(Pfix[iii], newout*OPmov[iii]);
//    }
//    //printf("Distance %f -> %f\n",sum_before/double(Pfix.size()),sum_after/double(Pfix.size()) ) ;
   
		// le passate successive utilizzano quindi come trasformazione iniziale questa appena trovata.
		// Nei prossimi cicli si parte da questa matrice come iniziale.
	  out=newout;

		assert(Pfix.size()==Pmov.size());
		int tts2=clock();
		ttsearch+=tts1-tts0;	
		ttleast +=tts2-tts1;
    ii.pcl50=H.Percentile(.5);
		ii.pclhi=H.Percentile(ap.PassHiFilter);
		ii.AVG=H.Avg();
		ii.RMS=H.RMS();
		ii.StdDev=H.StandardDeviation();
		ii.Time=clock();
		as.I.push_back(ii);
		nc++;
		// The distance of the next points to be considered is lowered according to the <ReduceFactor> parameter. 
		// We use 5 times the <ReduceFactor> percentile of the found points. 
    if(ap.ReduceFactorPerc<1) StartMinDist=max(ap.MinDistAbs*ap.MinMinDistPerc, min(StartMinDist,5.0*H.Percentile(ap.ReduceFactorPerc)));
	} 
	while ( 
		nc<=ap.MaxIterNum && 
		H.Percentile(.5) > ap.TrgDistAbs && 
		(nc<ap.EndStepNum+1 || ! as.Stable(ap.EndStepNum) ) 
		); 
 /**************** END ICP LOOP ****************/
	int tt2=clock();  
	Matrix44d ResCopy=out;
	Point3d scv,shv,rtv,trv;
	Decompose(ResCopy,scv,shv,rtv,trv);
  if(math::Abs(1-scv[0])>ap.MaxScale || math::Abs(1-scv[1])>ap.MaxScale || math::Abs(1-scv[2])>ap.MaxScale ) {
			status = TOO_MUCH_SCALE;
			return false;
		}
	if(shv[0]>ap.MaxShear || shv[1]>ap.MaxShear || shv[2]>ap.MaxShear ) {
			status = TOO_MUCH_SHEAR;
			return false;
		}
	printf("Grid %i %i %i - fn %i\n",u.siz[0],u.siz[1],u.siz[2],fix->fn);
  printf("Init %8.3f Loop %8.3f Search %8.3f least sqrt %8.3f\n",
         float(tt1-tt0)/CLOCKS_PER_SEC, float(tt2-tt1)/CLOCKS_PER_SEC,
         float(ttsearch)/CLOCKS_PER_SEC,float(ttleast)/CLOCKS_PER_SEC );

	return true;
}
bool ExtraMeshColorizePlugin::applyFilter(QAction *filter, MeshDocument &md, RichParameterSet & par, vcg::CallBackPos *cb){
 MeshModel &m=*(md.mm());
 switch(ID(filter)) {
  case CP_SATURATE_QUALITY:{
     m.updateDataMask(MeshModel::MM_VERTFACETOPO);
     tri::UpdateQuality<CMeshO>::VertexSaturate(m.cm, par.getFloat("gradientThr"));
     if(par.getBool("updateColor"))
     {
       Histogramf H;
       tri::Stat<CMeshO>::ComputePerVertexQualityHistogram(m.cm,H);
       m.updateDataMask(MeshModel::MM_VERTCOLOR);
       tri::UpdateColor<CMeshO>::VertexQualityRamp(m.cm,H.Percentile(0.1f),H.Percentile(0.9f));
     }
     Log("Saturated ");
   }
break;
  case CP_MAP_VQUALITY_INTO_COLOR:
     m.updateDataMask(MeshModel::MM_VERTCOLOR);
  case CP_CLAMP_QUALITY:
      {
      float RangeMin = par.getFloat("minVal");	
      float RangeMax = par.getFloat("maxVal");		
			bool usePerc = par.getDynamicFloat("perc")>0;
			
			Histogramf H;
			tri::Stat<CMeshO>::ComputePerVertexQualityHistogram(m.cm,H);

			float PercLo = H.Percentile(par.getDynamicFloat("perc")/100.f);
			float PercHi = H.Percentile(1.0-par.getDynamicFloat("perc")/100.f);
			
			if(par.getBool("zeroSym"))
				{
					RangeMin = min(RangeMin, -math::Abs(RangeMax));
					RangeMax = max(math::Abs(RangeMin), RangeMax);
					PercLo = min(PercLo, -math::Abs(PercHi));
					PercHi = max(math::Abs(PercLo), PercHi);
				}

      if(usePerc)
      {
        if(ID(filter)==CP_CLAMP_QUALITY) tri::UpdateQuality<CMeshO>::VertexClamp(m.cm,PercLo,PercHi);
                                    else tri::UpdateColor<CMeshO>::VertexQualityRamp(m.cm,PercLo,PercHi);
        Log("Quality Range: %f %f; Used (%f %f) percentile (%f %f) ",H.MinV(),H.MaxV(),PercLo,PercHi,par.getDynamicFloat("perc"),100-par.getDynamicFloat("perc"));
      } else {
        if(ID(filter)==CP_CLAMP_QUALITY) tri::UpdateQuality<CMeshO>::VertexClamp(m.cm,RangeMin,RangeMax);
                                    else tri::UpdateColor<CMeshO>::VertexQualityRamp(m.cm,RangeMin,RangeMax);
        Log("Quality Range: %f %f; Used (%f %f)",H.MinV(),H.MaxV(),RangeMin,RangeMax);
      }
      break;
    }
   case CP_MAP_FQUALITY_INTO_COLOR: {
       m.updateDataMask(MeshModel::MM_FACECOLOR);
       float RangeMin = par.getFloat("minVal");
       float RangeMax = par.getFloat("maxVal");
       float perc = par.getDynamicFloat("perc");

       Histogramf H;
       tri::Stat<CMeshO>::ComputePerFaceQualityHistogram(m.cm,H);
       float PercLo = H.Percentile(perc/100.f);
       float PercHi = H.Percentile(1.0-perc/100.f);

       // Make the range and percentile symmetric w.r.t. zero, so that
       // the value zero is always colored in yellow
       if(par.getBool("zeroSym")){
         RangeMin = min(RangeMin, -math::Abs(RangeMax));
         RangeMax = max(math::Abs(RangeMin), RangeMax);
         PercLo = min(PercLo, -math::Abs(PercHi));
         PercHi = max(math::Abs(PercLo), PercHi);
       }

       tri::UpdateColor<CMeshO>::FaceQualityRamp(m.cm,PercLo,PercHi);
       Log("Quality Range: %f %f; Used (%f %f) percentile (%f %f) ",
           H.MinV(), H.MaxV(), PercLo, PercHi, perc, 100-perc);
       break;
   }

  case CP_DISCRETE_CURVATURE:
    {
      m.updateDataMask(MeshModel::MM_FACEFACETOPO | MeshModel::MM_VERTCURV);
      m.updateDataMask(MeshModel::MM_VERTCOLOR | MeshModel::MM_VERTQUALITY);
      tri::UpdateFlags<CMeshO>::FaceBorderFromFF(m.cm);

      if ( tri::Clean<CMeshO>::CountNonManifoldEdgeFF(m.cm) > 0) {
				errorMessage = "Mesh has some not 2-manifold faces, Curvature computation requires manifoldness"; // text
				return false; // can't continue, mesh can't be processed
			}
			
			int delvert=tri::Clean<CMeshO>::RemoveUnreferencedVertex(m.cm);
			if(delvert) Log("Pre-Curvature Cleaning: Removed %d unreferenced vertices",delvert);
			tri::Allocator<CMeshO>::CompactVertexVector(m.cm);
			tri::UpdateCurvature<CMeshO>::MeanAndGaussian(m.cm);
      int curvType = par.getEnum("CurvatureType");
			
			switch(curvType){ 
          case 0: tri::UpdateQuality<CMeshO>::VertexFromMeanCurvature(m.cm);        Log( "Computed Mean Curvature");      break;
			    case 1: tri::UpdateQuality<CMeshO>::VertexFromGaussianCurvature(m.cm);    Log( "Computed Gaussian Curvature"); break;
          case 2: tri::UpdateQuality<CMeshO>::VertexFromRMSCurvature(m.cm);         Log( "Computed RMS Curvature"); break;
          case 3: tri::UpdateQuality<CMeshO>::VertexFromAbsoluteCurvature(m.cm);    Log( "Computed ABS Curvature"); break;
					default : assert(0);
      }      
      
      Histogramf H;
      tri::Stat<CMeshO>::ComputePerVertexQualityHistogram(m.cm,H);
      tri::UpdateColor<CMeshO>::VertexQualityRamp(m.cm,H.Percentile(0.1f),H.Percentile(0.9f));
      Log( "Curvature Range: %f %f (Used 90 percentile %f %f) ",H.MinV(),H.MaxV(),H.Percentile(0.1f),H.Percentile(0.9f));
    break;
    }  
   case CP_TRIANGLE_QUALITY:
   {
     m.updateDataMask(MeshModel::MM_FACECOLOR | MeshModel::MM_FACEQUALITY);
     CMeshO::FaceIterator fi;
     Distribution<float> distrib;
     float minV = 0;
     float maxV = 1.0;
     int metric = par.getEnum("Metric");
     if(metric ==4 || metric ==5 )
     {
       if(!m.hasDataMask(MeshModel::MM_VERTTEXCOORD) && !m.hasDataMask(MeshModel::MM_WEDGTEXCOORD))
       {
         this->errorMessage = "This metric need Texture Coordinate";
         return false;
       }
     }
     switch(metric){

       case 0: { //area / max edge
         minV = 0;
         maxV = sqrt(3.0f)/2.0f;
         for(fi=m.cm.face.begin();fi!=m.cm.face.end();++fi) if(!(*fi).IsD())
             (*fi).Q() = vcg::Quality((*fi).P(0), (*fi).P(1),(*fi).P(2));
       } break;

       case 1: { //inradius / circumradius
         for(fi=m.cm.face.begin();fi!=m.cm.face.end();++fi) if(!(*fi).IsD())
             (*fi).Q() = vcg::QualityRadii((*fi).P(0), (*fi).P(1), (*fi).P(2));
       } break;

       case 2: { //mean ratio
         for(fi=m.cm.face.begin();fi!=m.cm.face.end();++fi) if(!(*fi).IsD())
             (*fi).Q() = vcg::QualityMeanRatio((*fi).P(0), (*fi).P(1), (*fi).P(2));
       } break;

       case 3: { // AREA
         for(fi=m.cm.face.begin();fi!=m.cm.face.end();++fi) if(!(*fi).IsD())
           (*fi).Q() = vcg::DoubleArea((*fi))*0.5f;
         tri::Stat<CMeshO>::ComputePerFaceQualityMinMax(m.cm,minV,maxV);
       } break;

       case 4: { //TEXTURE Angle Distortion
         if(m.hasDataMask(MeshModel::MM_WEDGTEXCOORD))
         {
           for(fi=m.cm.face.begin();fi!=m.cm.face.end();++fi) if(!(*fi).IsD())
             (*fi).Q() = Distortion<CMeshO,true>::AngleDistortion(&*fi);
         } else {
           for(fi=m.cm.face.begin();fi!=m.cm.face.end();++fi) if(!(*fi).IsD())
             (*fi).Q() = Distortion<CMeshO,false>::AngleDistortion(&*fi);
         }
         tri::Stat<CMeshO>::ComputePerFaceQualityDistribution(m.cm,distrib);
         minV = distrib.Percentile(0.05);
         maxV = distrib.Percentile(0.95);
       } break;

       case 5: { //TEXTURE Area Distortion
         float areaScaleVal, edgeScaleVal;
         if(m.hasDataMask(MeshModel::MM_WEDGTEXCOORD))
         {
           Distortion<CMeshO,true>::MeshScalingFactor(m.cm, areaScaleVal,edgeScaleVal);
           for(fi=m.cm.face.begin();fi!=m.cm.face.end();++fi) if(!(*fi).IsD())
             (*fi).Q() = Distortion<CMeshO,true>::AreaDistortion(&*fi,areaScaleVal);
         } else {
           Distortion<CMeshO,false>::MeshScalingFactor(m.cm, areaScaleVal,edgeScaleVal);
           for(fi=m.cm.face.begin();fi!=m.cm.face.end();++fi) if(!(*fi).IsD())
             (*fi).Q() = Distortion<CMeshO,false>::AreaDistortion(&*fi,areaScaleVal);

         }
         tri::Stat<CMeshO>::ComputePerFaceQualityDistribution(m.cm,distrib);
         minV = distrib.Percentile(0.05);
         maxV = distrib.Percentile(0.95);
       } break;

       default: assert(0);
     }
     tri::UpdateColor<CMeshO>::FaceQualityRamp(m.cm,minV,maxV,false);
     break;
   }


  case CP_RANDOM_CONNECTED_COMPONENT:
   m.updateDataMask(MeshModel::MM_FACEFACETOPO);
   m.updateDataMask(MeshModel::MM_FACEMARK | MeshModel::MM_FACECOLOR);
   vcg::tri::UpdateColor<CMeshO>::FaceRandomConnectedComponent(m.cm);
   break;

 case CP_RANDOM_FACE:
     m.updateDataMask(MeshModel::MM_FACEFACETOPO);
     m.updateDataMask(MeshModel::MM_FACEMARK | MeshModel::MM_FACECOLOR);
    vcg::tri::UpdateColor<CMeshO>::MultiFaceRandom(m.cm);
    break;

  case CP_VERTEX_SMOOTH:
		{
		int iteration = par.getInt("iteration");
		tri::Smooth<CMeshO>::VertexColorLaplacian(m.cm,iteration,false,cb);
		}
		break;
  case CP_FACE_SMOOTH:
		{
    m.updateDataMask(MeshModel::MM_FACEFACETOPO);
		int iteration = par.getInt("iteration");
		tri::Smooth<CMeshO>::FaceColorLaplacian(m.cm,iteration,false,cb);
		}
		break;
  case CP_FACE_TO_VERTEX:
     m.updateDataMask(MeshModel::MM_VERTCOLOR);
     tri::UpdateColor<CMeshO>::VertexFromFace(m.cm);
		break;
	 case CP_VERTEX_TO_FACE:
     m.updateDataMask(MeshModel::MM_FACECOLOR);
     tri::UpdateColor<CMeshO>::FaceFromVertex(m.cm);
		 break;
  case CP_TEXTURE_TO_VERTEX:
		{
      m.updateDataMask(MeshModel::MM_VERTCOLOR);
      if(!HasPerWedgeTexCoord(m.cm)) break;
			CMeshO::FaceIterator fi; 
			QImage tex(m.cm.textures[0].c_str());
			for(fi=m.cm.face.begin();fi!=m.cm.face.end();++fi) if(!(*fi).IsD()) 
			{
				for (int i=0; i<3; i++)
				{
          // note the trick for getting only the fractional part of the uv with the correct wrapping (e.g. 1.5 -> 0.5 and -0.3 -> 0.7)
          vcg::Point2f newcoord((*fi).WT(i).P().X()-floor((*fi).WT(i).P().X()),(*fi).WT(i).P().Y()-floor((*fi).WT(i).P().Y()));
          QRgb val = tex.pixel(newcoord[0]*tex.width(),(1-newcoord[1])*tex.height()-1);
					(*fi).V(i)->C().SetRGB(qRed(val),qGreen(val),qBlue(val));
				}
			}
	    }
		
		break;
 }
	return true;
}
Exemple #8
0
			}
		}
	}

    pair<float,float> minmax;
    minmax = tri::Stat<CMeshO>::ComputePerFaceQualityMinMax(mm.cm);
    qDebug()<<minmax.first;
    qDebug()<<minmax.second;
    mm.updateDataMask(MeshModel::MM_FACECOLOR);
    float RangeMin = minmax.first;
    float RangeMax = minmax.second;
    float perc = 0.0;

    Histogramf H;
    tri::Stat<CMeshO>::ComputePerFaceQualityHistogram(mm.cm,H);
    float PercLo = H.Percentile(perc/100.f);
    float PercHi = H.Percentile(1.0-perc/100.f);

    tri::UpdateColor<CMeshO>::FaceQualityRamp(mm.cm,PercLo,PercHi);
    return true;
}

void EditAreslpPlugin::EndEdit(MeshModel &mm, GLArea *gla)
{
}

void EditAreslpPlugin::mousePressEvent(QMouseEvent *event, MeshModel &mm, GLArea *gla)
{
}

void EditAreslpPlugin::mouseMoveEvent(QMouseEvent *event, MeshModel &mm, GLArea *gla)