Raw File
Sampler.cpp
#include "Sampler.h"

Sampler::Sampler(SurfaceMesh::Model * srcMesh, SamplingMethod samplingMethod)
{
	if(srcMesh == NULL) 
		return;
	else
		mesh = srcMesh;

	method = samplingMethod;

    SurfaceMeshHelper h(mesh);
    farea = h.computeFaceAreas();
    points = h.getVector3VertexProperty(VPOINT);

    FaceBarycenterHelper fh(mesh);
    fcenter = fh.compute();

	mesh->update_face_normals();
	fnormal = mesh->get_face_property<Vector3>(FNORMAL);

	// Sample based on method selected
	if( method == RANDOM_BARYCENTRIC )
	{
        // Compute all faces area
        fprobability = mesh->face_property<Scalar>("f:probability", 0);
		this->totalMeshArea = 0;

		Surface_mesh::Face_iterator fit, fend = mesh->faces_end();
		for (fit = mesh->faces_begin(); fit != fend; ++fit)
            totalMeshArea += farea[fit];

        for (fit = mesh->faces_begin(); fit != fend; ++fit)
            fprobability[fit] = farea[fit] / totalMeshArea;

        interval = std::vector<AreaFace>(mesh->n_faces() + 1);
        interval[0] = AreaFace(0.0, Surface_mesh::Face(0));
		int i = 0;

		// Compute mesh area in a cumulative manner
        foreach(Face f, mesh->faces())
		{
            interval[f.idx()+1] = AreaFace(interval[i].area + fprobability[f], f);
			i++;
		}
	}
	else if( method ==  FACE_CENTER )
	{
		// No preparations needed..
	}
}

SamplePoint Sampler::getSample(double weight)
{
	SamplePoint sp;
	double r;
	double b[3];

	if( method == RANDOM_BARYCENTRIC )
	{
		// r, random point in the area
		r = uniform();

		// Find corresponding face
        std::vector<AreaFace>::iterator it = lower_bound(interval.begin(), interval.end(), AreaFace(qMin(r,interval.back().area)));
        Surface_mesh::Face f = it->f;

		// Add sample from that face
		RandomBaricentric(b);

        sp = SamplePoint( getBaryFace(f, b[0], b[1]), fnormal[f], weight, f.idx(), b[0], b[1]);
	}
	else if( method ==  FACE_CENTER )
	{
		int fcount = mesh->n_faces();

		int randTriIndex = (int) (fcount * (((double)rand()) / (double)RAND_MAX)) ;

		if( randTriIndex >= fcount )
			randTriIndex = fcount - 1;

        Surface_mesh::Face f(randTriIndex);

		// Get triangle center and normal
        sp = SamplePoint(fcenter[f], fnormal[f], farea[f], f.idx(), 1 / 3.0, 1 / 3.0);
	}

	return sp;
}

std::vector<SamplePoint> Sampler::getSamples(int numberSamples, double weight)
{
    std::vector<SamplePoint> samples(numberSamples);

	for(int i = 0; i < numberSamples; i++)
	{
		samples[i] = getSample(weight);
	}

	return samples;
}

Vector3 Sampler::getBaryFace( Surface_mesh::Face f, double U, double V )
{
    QVector<Vector3> v;
    Surface_mesh::Vertex_around_face_circulator vit = mesh->vertices(f),vend=vit;
    do{ v.push_back(points[vit]); } while(++vit != vend);

    if(U == 1.0) return v[1];
    if(V == 1.0) return v[2];

    double b1 = U;
    double b2 = V;
    double b3 = 1.0 - (U + V);

    Vector3 p;
    p.x() = (b1 * v[0].x()) + (b2 * v[1].x()) + (b3 * v[2].x());
    p.y() = (b1 * v[0].y()) + (b2 * v[1].y()) + (b3 * v[2].y());
    p.z() = (b1 * v[0].z()) + (b2 * v[1].z()) + (b3 * v[2].z());
    return p;
}
back to top