Exemple #1
0
tensor<double, 3, 2> getTangent(const SurfaceMesh &mesh, SurfaceMesh::SimplexID<3> faceID)
{
    auto cover = mesh.get_name(faceID);
    auto vertexID = mesh.get_simplex_up({cover[0]});
    std::set<SurfaceMesh::KeyType> next(std::begin(cover)+1, std::end(cover));
    return surfacemesh_detail::getTangentF(mesh, (*vertexID).position, vertexID, next);
}
Exemple #2
0
Vector getNormal(const SurfaceMesh &mesh, SurfaceMesh::SimplexID<3> faceID)
{
    Vector norm;
    auto   name = mesh.get_name(faceID);

    // Get the three vertices
    auto a = *mesh.get_simplex_up({name[0]});
    auto b = *mesh.get_simplex_up({name[1]});
    auto c = *mesh.get_simplex_up({name[2]});

    if ((*faceID).orientation == 1)
    {
        norm = cross(c-b, a-b);
    }
    else if ((*faceID).orientation == -1)
    {
        norm = cross(a-b, c-b);
    }
    else
    {
        // std::cerr << "ERROR(getNormal): Orientation undefined, cannot compute "
                  // << "normal. Did you call compute_orientation()?" << std::endl;
        throw std::runtime_error("ERROR(getNormal): Orientation undefined, cannot compute normal. Did you call compute_orientation()?");
    }
    return norm;
}
Exemple #3
0
int main(int argc, char** argv) {
    QApplication application(argc,argv);
    if(argc!=2){
        cout << "One argument necessary, given: " << (argc-1) << endl;
        return EXIT_FAILURE;
    }
    
    SurfaceMesh mesh;
    bool ok = mesh.read(argv[1]);
    if(!ok){
        cout << "could not open file: " << argv[1] << endl;
        return EXIT_FAILURE;
    }
    
    ///--- Preprocess
    mesh.triangulate();
    mesh.update_vertex_normals();

    ///--- Shutdown on close GUI
    QObject::connect(&application, &QApplication::lastWindowClosed, &application, &QApplication::quit);
    
    Viewer viewer(mesh);
    viewer.setWindowTitle("OpenGP/apps/qglviewer");
    viewer.show();
    return application.exec();
}
Exemple #4
0
double getArea(const SurfaceMesh &mesh, SurfaceMesh::SimplexID<3> faceID)
{
    auto name = mesh.get_name(faceID);
    auto a = *mesh.get_simplex_up({name[0]});
    auto b = *mesh.get_simplex_up({name[1]});
    auto c = *mesh.get_simplex_up({name[2]});
    return getArea(a, b, c);
}
Exemple #5
0
Vector getNormal(const SurfaceMesh &mesh, SurfaceMesh::SimplexID<1> vertexID)
{
    Vector norm;
    auto   faces = mesh.up(mesh.up(vertexID));
    for (auto faceID : faces)
    {
        norm += getNormal(mesh, faceID);
    }
    // norm /= faces.size();
    return norm;
}
Exemple #6
0
void coarse(SurfaceMesh &mesh, double coarseRate, double flatRate, double denseWeight){
    // TODO: Check if all polygons are closed (0)
    std::cout << "Before coarsening: " << mesh.size<1>() << " " << mesh.size<2>() << " " << mesh.size<3>() << std::endl;

    // Compute the average edge length
    double avgLen = 0;
    if (denseWeight > 0){
        avgLen = surfacemesh_detail::getMeanEdgeLength(mesh);
    }

    double sparsenessRatio = 1;
    double flatnessRatio = 1;

    // Construct list of vertices to decimate
    std::vector<SurfaceMesh::SimplexID<1> > toRemove;
    for(auto vertexID : mesh.get_level_id<1>()){
        // Sparseness as coarsening criteria
        if(denseWeight > 0){
            // Get max length of edges.
            auto edges = mesh.up(vertexID);
            double maxLen = 0;
            for(auto edgeID : edges){
                auto name =  mesh.get_name(edgeID);
                auto v = *mesh.get_simplex_down(edgeID, name[0])
                         - *mesh.get_simplex_down(edgeID, name[1]);
                double tmpLen = std::sqrt(v|v);
                if(tmpLen > maxLen) maxLen = tmpLen;
            }
            sparsenessRatio = std::pow(maxLen/avgLen, denseWeight);
        }

        // Curvature as coarsening criteria
        if(flatRate > 0){
            auto lst = surfacemesh_detail::computeLocalStructureTensor(mesh, vertexID, RINGS);
            auto eigenvalues = surfacemesh_detail::getEigenvalues(lst).eigenvalues();
            // The closer this ratio is to 0 the flatter the local region.
            flatnessRatio = std::pow(eigenvalues[1]/eigenvalues[2], flatRate);
        }

        // Add vertex to delete list
        if(sparsenessRatio * flatnessRatio < coarseRate){
            toRemove.push_back(vertexID);
        }
    }

    std::cout << toRemove.size() << " vertices are marked to be removed." << std::endl;

    for(auto vertexID : toRemove){
        surfacemesh_detail::decimateVertex(mesh, vertexID);
    }

    std::cout << "After coarsening: " << mesh.size<1>() << " " << mesh.size<2>() << " " << mesh.size<3>() << std::endl;
}
Exemple #7
0
/**
 * @brief      Refine the mesh by quadrisection.
 *
 * Note that this function will delete all stored data on edges and faces. But
 * this can be easily fixed.
 *
 * @param      mesh  The mesh
 */
std::unique_ptr<SurfaceMesh> refineMesh(const SurfaceMesh &mesh){
    std::unique_ptr<SurfaceMesh> refinedMesh(new SurfaceMesh);

    // Copy over vertices to refinedMesh
    for (auto vertex : mesh.get_level_id<1>()){
        auto key = mesh.get_name(vertex);
        refinedMesh->insert(key, *vertex);
    }

    // Split edges and generate a map of names before to after
    std::map<std::array<int,2>, int> edgeMap;

    for(auto edge : mesh.get_level_id<2>()){
        auto edgeName = mesh.get_name(edge);
        auto v1 = *mesh.get_simplex_up({edgeName[0]});
        auto v2 = *mesh.get_simplex_up({edgeName[1]});

        auto newVertex = refinedMesh->add_vertex(Vertex(0.5*(v1+v2)));
        edgeMap.emplace(std::make_pair(edgeName, newVertex));
    }

    // Connect edges and face and copy data
    for(auto face : mesh.get_level_id<3>()){
        auto name = mesh.get_name(face);
        int a, b, c;

        // Skip checking if found
        auto it = edgeMap.find({name[0],name[1]});
        a = it->second;

        it = edgeMap.find({name[1],name[2]});
        b = it->second;

        it = edgeMap.find({name[0],name[2]});
        c = it->second;

        refinedMesh->insert({name[0], a});
        refinedMesh->insert({a, name[1]});

        refinedMesh->insert({name[1], b});
        refinedMesh->insert({b, name[2]});

        refinedMesh->insert({name[0], c});
        refinedMesh->insert({c, name[2]});

        refinedMesh->insert({a,b,c});
        refinedMesh->insert({name[0],a,c}, *face);
        refinedMesh->insert({name[1],a,b}, *face);
        refinedMesh->insert({name[2],b,c}, *face);
    }
    return refinedMesh;
}
Exemple #8
0
/**
 * http://research.microsoft.com/en-us/um/people/chazhang/publications/icip01_ChaZhang.pdf
 * http://chenlab.ece.cornell.edu/Publication/Cha/icip01_Cha.pdf
 */
double getVolume(const SurfaceMesh &mesh)
{
    bool orientError = false;
    double volume = 0;
    for (auto faceID : mesh.get_level_id<3>())
    {
        auto   name = mesh.get_name(faceID);
        auto   a = (*mesh.get_simplex_up({name[0]})).position;
        auto   b = (*mesh.get_simplex_up({name[1]})).position;
        auto   c = (*mesh.get_simplex_up({name[2]})).position;

        Vector norm;
        double tmp;
        if ((*faceID).orientation == 1)
        {
            // a->b->c
            norm = cross(b, c);
            tmp  = dot(a, norm);

        }
        else if ((*faceID).orientation == -1)
        {
            // c->b->a
            norm = cross(b, a);
            tmp  = dot(c, norm);
        }
        else
        {
            orientError = true;
        }

        // * Probably less efficient way #1
        // tmp = dot(a, getNormal(mesh, faceID));

        // * Less efficient way #2
        // norm = getNormalFromTangent(getTangent(mesh, faceID));
        // auto wedge = a^b^c;
        // tmp = std::sqrt(wedge|wedge);
        // auto sgn = dot((a+b+c)/3, norm);
        // if(sgn <= 0) {
        //     tmp = -1*tmp;
        // }
        volume += tmp;
    }
    if(orientError){
        std::cerr << "ERROR getVolume(): Orientation undefined for one or more "
                  << "simplices. Did you call compute_orientation()?" << std::endl;
    }
    return volume/6;
}
int main(void)
{
    // instantiate a SurfaceMesh object
    SurfaceMesh mesh;

    // instantiate 4 vertex handles
    SurfaceMesh::Vertex v0,v1,v2,v3;

    // add 4 vertices
    v0 = mesh.add_vertex(Vec3(0,0,0));
    v1 = mesh.add_vertex(Vec3(1,0,0));
    v2 = mesh.add_vertex(Vec3(0,1,0));
    v3 = mesh.add_vertex(Vec3(0,0,1));

    // add 4 triangular faces
    mesh.add_triangle(v0,v1,v3);
    mesh.add_triangle(v1,v2,v3);
    mesh.add_triangle(v2,v0,v3);
    mesh.add_triangle(v0,v2,v1);

    std::cout << "vertices: " << mesh.n_vertices() << std::endl;
    std::cout << "edges: "    << mesh.n_edges()    << std::endl;
    std::cout << "faces: "    << mesh.n_faces()    << std::endl;

    return 0;
}
Exemple #10
0
int main(int argc, char** argv) {
    std::string file = (argc>1) ? argv[1] : "bunny.obj";

    SurfaceMesh mesh;
    bool success = mesh.read(file);
    CHECK(success);

    auto points = mesh.get_vertex_property<Vec3>("v:point");
    Vec3 p(0,0,0);
    for (auto vit: mesh.vertices())
        p += points[vit];
    p /= mesh.n_vertices();

    std::cout << "barycenter: " << p << std::endl;
}
Exemple #11
0
void coarseIT(SurfaceMesh &mesh, double coarseRate, double flatRate, double denseWeight){
    std::cout << "Before coarsening: " << mesh.size<1>() << " " << mesh.size<2>() << " " << mesh.size<3>() << std::endl;

    // Compute the average edge length
    double avgLen = 0;
    if (denseWeight > 0){
        avgLen = surfacemesh_detail::getMeanEdgeLength(mesh);
    }

    double sparsenessRatio = 1;
    double flatnessRatio = 1;

    // Backup vertices so we can modify in place
    auto range = mesh.get_level_id<1>();
    const std::vector<SurfaceMesh::SimplexID<1> > Vertices(range.begin(), range.end());
    for(auto vertexID : Vertices) {
        // Sparseness as coarsening criteria
        if(denseWeight > 0){
            // Get max length of edges.
            auto edges = mesh.up(vertexID);
            double maxLen = 0;
            for(auto edgeID : edges){
                auto name =  mesh.get_name(edgeID);
                auto v = *mesh.get_simplex_down(edgeID, name[0])
                         - *mesh.get_simplex_down(edgeID, name[1]);
                double tmpLen = std::sqrt(v|v);
                if(tmpLen > maxLen) maxLen = tmpLen;
            }
            sparsenessRatio = std::pow(maxLen/avgLen, denseWeight);
        }

        // Curvature as coarsening criteria
        if(flatRate > 0){
            auto lst = surfacemesh_detail::computeLocalStructureTensor(mesh, vertexID, RINGS);
            auto eigenvalues = surfacemesh_detail::getEigenvalues(lst).eigenvalues();
            // The closer this ratio is to 0 the flatter the local region.
            flatnessRatio = std::pow(eigenvalues[1]/eigenvalues[2], flatRate);
        }

        // Check if we should delete
        if(sparsenessRatio * flatnessRatio < coarseRate){
            surfacemesh_detail::decimateVertex(mesh, vertexID);
        }
    }

    std::cout << "After coarsening: " << mesh.size<1>() << " " << mesh.size<2>() << " " << mesh.size<3>() << std::endl;
}
Exemple #12
0
bool simulation_load_render_mesh(const char* filename)
{
    SurfaceMesh* mesh = new SurfaceMesh;
    if (!read_mesh_obj(filename, mesh->positions, mesh->triangles, (render_meshes.empty() ? &mesh->texcoords : NULL))) // we use the texture only for the first OBJ
    {
        delete mesh;
        return false;
    }
    mesh->filename = filename;
    mesh->updateNormals();
    if (render_meshes.size()&1)
        mesh->color = TColor(0.15f, 0.15f, 0.15f, 1.0f);
    else
        mesh->color = TColor(0.8f, 0.8f, 0.8f, 1.0f);
    render_meshes.push_back(mesh);
    return true;
}
Exemple #13
0
bool hasHole(const SurfaceMesh &mesh){
    for(auto eID : mesh.get_level_id<2>()){
        auto cover = mesh.get_cover(eID);
        if(cover.size() != 2){
            return true;
        }
    }
    return false;
}
Exemple #14
0
std::tuple<double, double, int, int> getMinMaxAngles(
    const SurfaceMesh &mesh,
    int maxMinAngle,
    int minMaxAngle)
{
    double minAngle = 360;
    double maxAngle = 0;
    int small = 0;
    int large = 0;

    // for each triangle
    for(auto nid : mesh.get_level_id<3>()){
        auto name = mesh.get_name(nid);
        auto a = *mesh.get_simplex_up({name[0]});
        auto b = *mesh.get_simplex_up({name[1]});
        auto c = *mesh.get_simplex_up({name[2]});
        std::array<double, 3> angles;
        try{
            angles[0] = angle(a,b,c);
            angles[1] = angle(b,a,c);
            angles[2] = angle(a,c,b);
        }
        catch (std::runtime_error& e){
            throw std::runtime_error("ERROR(getMinMaxAngles): Cannot compute angles of face with zero area.");
        }

        for(double angle : angles){
            if (angle < minAngle){
                minAngle = angle;
            }
            if (angle > maxAngle){
                maxAngle = angle;
            }
            if (angle < maxMinAngle){
                ++small;
            }
            if (angle > minMaxAngle){
                ++large;
            }
        }
    }
    return std::make_tuple(minAngle, maxAngle, small, large);
}
Exemple #15
0
void print(const SurfaceMesh &mesh)
{
    std::cout << "Level: 1" << std::endl;
    for (auto node : mesh.get_level_id<1>())
    {
        std::cout << "    " << *node << std::endl;
    }
    std::cout << "Level: 2" << std::endl;
    for (auto node : mesh.get_level_id<2>())
    {
        auto name = mesh.get_name(node);
        std::cout << "    " << casc::to_string(name) << std::endl;
    }
    std::cout << "Level: 3" << std::endl;
    for (auto node : mesh.get_level_id<3>())
    {
        auto name = mesh.get_name(node);
        std::cout << "    " << casc::to_string(name) << std::endl;
    }
}
void VertexScalar::loadScalars()
{
	if (!mi) return;

	SurfaceMesh *mesh = mi->getMesh();
	if (!mesh) return;

	unsigned int i = 0;
	for (SurfaceMesh::VertexIter v_it = mesh->vertices_begin(); v_it!=mesh->vertices_end(); ++v_it) {
		if (i >= ps->size()) {
			ps->addParticle();
		}
		SurfaceMesh::TexCoord2D tc = mesh->texcoord2D(v_it);
		
		setScalar(i,tc[0]);

		i++;
	}
	for (unsigned int j = ps->size() - 1; j >= i; j--)
		ps->removeParticle(j);
}
Exemple #17
0
/// Entry point
int main(int argc, char** argv) {
    if(argc!=2) mFatal("usage: glfwviewer bunny.obj");
    int success = mesh.read(argv[1]);
    if(!success) mFatal() << "File not found";

    mesh.triangulate();
    mesh.update_vertex_normals();
    cout << "input: '" << argv[1] << "' num vertices " << mesh.vertices_size() << endl;
    cout << "BBOX: " << bounding_box(mesh) << endl;

    glfwInitWindowSize(_width, _height);
    if (glfwMakeWindow(__FILE__) == EXIT_FAILURE)
        return EXIT_FAILURE;

    glfwDisplayFunc(display);
    glfwTrackball(update_matrices, update_projection_matrix);
    init();
    glfwMainLoop();

    return EXIT_SUCCESS;
}
Exemple #18
0
int main(int argc, char *argv[])
{
	//Create and show the Qt OpenGL window
	QApplication app(argc, argv);
	OpenGLWidget openGLWidget(0);
	openGLWidget.show();

	//Create an empty volume and then place a sphere in it
	SimpleVolume<Density8> volData(PolyVox::Region(Vector3DInt32(0,0,0), Vector3DInt32(63, 63, 63)));
	createSphereInVolume(volData, 28);

	//Smooth the data
	smoothRegion<SimpleVolume, Density8>(volData, volData.getEnclosingRegion());
	smoothRegion<SimpleVolume, Density8>(volData, volData.getEnclosingRegion());
	smoothRegion<SimpleVolume, Density8>(volData, volData.getEnclosingRegion());

	RawVolume<Density8> volDataLowLOD(PolyVox::Region(Vector3DInt32(0,0,0), Vector3DInt32(15, 31, 31)));

	VolumeResampler<SimpleVolume, RawVolume, Density8> volumeResampler(&volData, PolyVox::Region(Vector3DInt32(0,0,0), Vector3DInt32(31, 63, 63)), &volDataLowLOD, volDataLowLOD.getEnclosingRegion());
	volumeResampler.execute();

	//Extract the surface
	SurfaceMesh<PositionMaterialNormal> meshLowLOD;
	SurfaceExtractor<RawVolume, Density8 > surfaceExtractor(&volDataLowLOD, volDataLowLOD.getEnclosingRegion(), &meshLowLOD);
	surfaceExtractor.execute();
	meshLowLOD.scaleVertices(2.0f);

	//Extract the surface
	SurfaceMesh<PositionMaterialNormal> meshHighLOD;
	SurfaceExtractor<SimpleVolume, Density8 > surfaceExtractorHigh(&volData, PolyVox::Region(Vector3DInt32(32,0,0), Vector3DInt32(63, 63, 63)), &meshHighLOD);
	surfaceExtractorHigh.execute();
	meshHighLOD.translateVertices(Vector3DFloat(32, 0, 0));

	//Pass the surface to the OpenGL window
	openGLWidget.setSurfaceMeshToRender(meshHighLOD);
	openGLWidget.setSurfaceMeshToRenderLowLOD(meshLowLOD);

	//Run the message pump.
	return app.exec();
}
int main(int /*argc*/, char** argv) {
    SurfaceMesh mesh;

    mesh.read(argv[1]);

    float mean_valence = 0.0f;
    unsigned int vertex_valence;

    // instantiate iterator and circulators
    SurfaceMesh::Vertex_iterator vit;
    SurfaceMesh::Vertex_around_vertex_circulator vc, vc_end;

    // loop over all vertices
    for (vit = mesh.vertices_begin(); vit != mesh.vertices_end(); ++vit) {
        // initialize circulators
        vc = mesh.vertices(*vit);
        vc_end = vc;

        // reset counter
        vertex_valence = 0;

        // loop over all incident vertices
        do {
            ++vertex_valence;
        } while (++vc != vc_end);

        // sum up vertex valences
        mean_valence += vertex_valence;
    }

    mean_valence /= mesh.n_vertices();

    std::cout << "mean valence: " << mean_valence << std::endl;
}
Exemple #20
0
int main(int argc, char** argv) {
    std::string in_file = (argc>1) ? argv[1] : "bunny.obj";
    std::string out_file = (argc>2) ? argv[2] : "output.obj";

    // instantiate a SurfaceMesh object
    SurfaceMesh mesh;

    // read a mesh specified as the first command line argument
    bool success = mesh.read(in_file);
    CHECK(success);

    // ...
    // do fancy stuff with the mesh
    // ...

    // write the mesh to the file specified as second argument
    mesh.write(out_file);
    CHECK(success);

    mLogger() << "read:" << in_file << "wrote:" << out_file;
    return EXIT_SUCCESS;
}
Exemple #21
0
void printQualityInfo(const std::string &filename, const SurfaceMesh &mesh){

    std::stringstream anglefilename;
    anglefilename << filename << ".angle";

    std::ofstream angleOut(anglefilename.str());
    if(!angleOut.is_open())
    {
        std::stringstream ss;
        ss << "Couldn't open file " << filename << ".angle";
        throw std::runtime_error(ss.str());
    }

    std::stringstream areafilename;
    areafilename << filename << ".area";
    std::ofstream areaOut(areafilename.str());
    if(!areaOut.is_open())
    {
        std::stringstream ss;
        ss << "Couldn't open file " << filename << ".area";
        throw std::runtime_error(ss.str());
    }

    for(auto faceID : mesh.get_level_id<3>()){
        auto name = mesh.get_name(faceID);
        auto a = *mesh.get_simplex_up({name[0]});
        auto b = *mesh.get_simplex_up({name[1]});
        auto c = *mesh.get_simplex_up({name[2]});

        areaOut << getArea(a,b,c) << "\n";
        // Print angles in degrees
        angleOut    << angle(a,b,c) << "\n"
                    << angle(b,a,c) << "\n"
                    << angle(a,c,b) << "\n";
    }
    areaOut.close();
    angleOut.close();
}
int main(int /*argc*/, char** argv)
{
    SurfaceMesh mesh;

    mesh.read(argv[1]);

    // get (pre-defined) property storing vertex positions
    SurfaceMesh::Vertex_property<Vec3> points = mesh.get_vertex_property<Vec3>("v:point");

    SurfaceMesh::Vertex_iterator vit, vend = mesh.vertices_end();

    Vec3 p(0,0,0);

    for (vit = mesh.vertices_begin(); vit != vend; ++vit)
    {
        // access point property like an array
        p += points[*vit];
    }

    p /= mesh.n_vertices();

    std::cout << "barycenter: " << p << std::endl;
}
void VertexScalar::saveScalars()
{
	if (!mi) return;

	SurfaceMesh *mesh = mi->getMesh();
	if (!mesh) return;

	SurfaceMesh::VertexIter v_it = mesh->vertices_begin(); 
	for (unsigned int i = 0; i < ps->size(); i++) {
		if (v_it == mesh->vertices_end()) {
			mesh->add_vertex(MyMesh::Point());
		} else {
			SurfaceMesh::TexCoord2D tc = mesh->texcoord2D(v_it);
			tc[0] = (SurfaceMesh::Scalar) getScalar(i);
			mesh->set_texcoord2D(v_it, tc);
			++v_it;
		}
	}
	while (v_it != mesh->vertices_end()) {
		SurfaceMesh::VertexIter extra = v_it;
		++v_it;	// could do this above but may be confusing
		mesh->delete_vertex(extra);
	}
}
Exemple #24
0
int main(int argc, char** argv){
    if(argc!=3){
        cout << "usage:" << endl << "isoremesh bunny.obj remeshed.obj" << endl;
        return EXIT_FAILURE;
    }
    std::string input(argv[1]);
    std::string output(argv[2]);
    
    ///--- Load mesh
    SurfaceMesh mesh;
    mesh.read(input);
    if(mesh.n_vertices()==0){
        cout << "Input mesh has 0 vertices" << endl;
        return EXIT_FAILURE;
    }
    
    ///--- Remesher is only for triangulations!
    mesh.triangulate();

    ///--- Compute bounding box
    Scalar bbox_diag_length = bounding_box(mesh).diagonal().norm();
    cout << "#vertices: " << mesh.n_vertices() << endl;
    cout << "bbox_diag_length: " << bbox_diag_length << endl;
            
    ///--- Perform remeshing    
    IsotropicRemesher remesher(mesh);
    remesher.num_iterations = 10;
    remesher.sharp_feature_deg = 45;
    remesher.longest_edge_length = 0.02*bbox_diag_length;
    remesher.keep_short_edges = false;
    remesher.reproject_to_surface = true;
    remesher.myout = &std::cout; ///< print output to...
    remesher.execute();
    
    ///--- Write to file
    mesh.write(output);
    return EXIT_SUCCESS;
}
OpenGLSurfaceMesh BuildOpenGLSurfaceMesh(const SurfaceMesh<PositionMaterialNormal>& mesh)
{
	//Represents our filled in OpenGL vertex and index buffer objects.
	OpenGLSurfaceMesh result;

	//The source
	result.sourceMesh = &mesh;

	//Convienient access to the vertices and indices
	const vector<PositionMaterialNormal>& vecVertices = mesh.getVertices();
	const vector<uint32_t>& vecIndices = mesh.getIndices();

	//If we have any indices...
	if(!vecIndices.empty())
	{
		//Create an OpenGL index buffer
		glGenBuffers(1, &result.indexBuffer);
		glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, result.indexBuffer);

		//Get a pointer to the first index
		GLvoid* pIndices = (GLvoid*)(&(vecIndices[0]));		

		//Fill the OpenGL index buffer with our data. 
		glBufferData(GL_ELEMENT_ARRAY_BUFFER, vecIndices.size() * sizeof(uint32_t), pIndices, GL_STATIC_DRAW);
	}

	result.noOfIndices = vecIndices.size();

	glGenBuffers(1, &result.vertexBuffer);
	glBindBuffer(GL_ARRAY_BUFFER, result.vertexBuffer);
	glBufferData(GL_ARRAY_BUFFER, vecVertices.size() * sizeof(GLfloat) * 9, 0, GL_STATIC_DRAW);
	GLfloat* ptr = (GLfloat*)glMapBuffer(GL_ARRAY_BUFFER, GL_READ_WRITE);

	for(vector<PositionMaterialNormal>::const_iterator iterVertex = vecVertices.begin(); iterVertex != vecVertices.end(); ++iterVertex)
	{
		const PositionMaterialNormal& vertex = *iterVertex;
		const Vector3DFloat& v3dVertexPos = vertex.getPosition();
		//const Vector3DFloat v3dRegionOffset(uRegionX * g_uRegionSideLength, uRegionY * g_uRegionSideLength, uRegionZ * g_uRegionSideLength);
		const Vector3DFloat v3dFinalVertexPos = v3dVertexPos + static_cast<Vector3DFloat>(mesh.m_Region.getLowerCorner());

		*ptr = v3dFinalVertexPos.getX();
		ptr++;
		*ptr = v3dFinalVertexPos.getY();
		ptr++;
		*ptr = v3dFinalVertexPos.getZ();
		ptr++;

		*ptr = vertex.getNormal().getX();
		ptr++;
		*ptr = vertex.getNormal().getY();
		ptr++;
		*ptr = vertex.getNormal().getZ();
		ptr++;

		uint8_t material = vertex.getMaterial() + 0.5;

		OpenGLColour colour = convertMaterialIDToColour(material);

		*ptr = colour.red;
		ptr++;
		*ptr = colour.green;
		ptr++;
		*ptr = colour.blue;
		ptr++;
	}

	glUnmapBuffer(GL_ARRAY_BUFFER);

	return result;
}
Exemple #26
0
/// OpenGL initialization
void init() {
    ///----------------------- DATA ----------------------------
    auto vpoints = mesh.get_vertex_property<Vec3>("v:point");
    auto vnormals = mesh.get_vertex_property<Vec3>("v:normal");
    assert(vpoints);
    assert(vnormals);

    ///---------------------- TRIANGLES ------------------------
    triangles.clear();
    for(auto f: mesh.faces())
        for(auto v: mesh.vertices(f))
            triangles.push_back(v.idx());

    ///---------------------- OPENGL GLOBALS--------------------
    glClearColor(1.0f, 1.0f, 1.0f, 0.0f); ///< background
    glEnable(GL_DEPTH_TEST); // Enable depth test
    // glDisable(GL_CULL_FACE); // Cull back-facing

    /// Compile the shaders
    programID = load_shaders("vshader.glsl", "fshader.glsl");
    if(!programID) exit(EXIT_FAILURE);
    glUseProgram( programID );

    ///---------------------- CAMERA ----------------------------
    {
        typedef Eigen::Vector3f vec3;
        typedef Eigen::Matrix4f mat4;

        update_projection_matrix();

        /// Define the view matrix (camera extrinsics)
        vec3 cam_pos(0,0,5);
        vec3 cam_look(0,0,-1); /// Remember: GL swaps viewdir
        vec3 cam_up(0,1,0);
        view = OpenGP::lookAt(cam_pos, cam_look, cam_up);
        // cout << view << endl;

        /// Define the modelview matrix
        model = mat4::Identity();
        // cout << model << endl;

        /// Set initial matrices
        set_uniform_matrix(programID,"M",model); ///< to get world coordinates
        set_uniform_matrix(programID,"MV",view*model); ///< to get camera coordinates
        set_uniform_matrix(programID,"MVP",projection*view*model); ///< to get clip coordinates
    }

    ///---------------------- LIGHT -----------------------------
    {
        Vec3 light_dir(0,0,1);
        set_uniform_vector(programID,"LDIR",light_dir); ///< to get camera coordinates
    }

    ///---------------------- VARRAY ----------------------------
    {
        GLuint VertexArrayID;
        glGenVertexArrays(1, &VertexArrayID);
        glBindVertexArray(VertexArrayID);
    }

    ///---------------------- BUFFERS ----------------------------
    GLuint vertexbuffer, normalbuffer, trianglebuffer;
    {
        /// Load mesh vertices
        glGenBuffers(1, &vertexbuffer);
        glBindBuffer(GL_ARRAY_BUFFER, vertexbuffer);
        glBufferData(GL_ARRAY_BUFFER, mesh.n_vertices() * sizeof(Vec3), vpoints.data(), GL_STATIC_DRAW);

        /// Load mesh normals
        glGenBuffers(1, &normalbuffer);
        glBindBuffer(GL_ARRAY_BUFFER, normalbuffer);
        glBufferData(GL_ARRAY_BUFFER, mesh.n_vertices() * sizeof(Vec3), vnormals.data(), GL_STATIC_DRAW);

        /// Triangle indexes buffer
        glGenBuffers(1, &trianglebuffer);
        glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, trianglebuffer);
        glBufferData(GL_ELEMENT_ARRAY_BUFFER, triangles.size() * sizeof(unsigned int), &triangles[0], GL_STATIC_DRAW);
    }

    ///---------------------- SHADER ATTRIBUTES ----------------------------
    {
        /// Vertex positions in shader variable "vposition"
        GLuint vposition = glGetAttribLocation(programID, "vposition");
        glEnableVertexAttribArray(vposition);
        glBindBuffer(GL_ARRAY_BUFFER, vertexbuffer);
        glVertexAttribPointer(vposition, 3, GL_FLOAT, DONT_NORMALIZE, ZERO_STRIDE, ZERO_BUFFER_OFFSET);

        /// Vertex normals in in shader variable "vnormal"
        GLuint vnormal = glGetAttribLocation(programID, "vnormal");
        glEnableVertexAttribArray(vnormal);
        glBindBuffer(GL_ARRAY_BUFFER, normalbuffer);
        glVertexAttribPointer(vnormal, 3, GL_FLOAT, DONT_NORMALIZE, ZERO_STRIDE, ZERO_BUFFER_OFFSET);
    }
}
// unit test
int main()
{
    // init output code
    int OUTPUT_CODE = 0; // 0 indicates success, 1 is failure

    // create the object
    SurfaceMesh  TM;

    // non-manifold 2-D mesh example
    TM.Reserve_Cells(7);
    TM.Append_Cell(0,1,5);
    TM.Append_Cell(5,2,1);
    TM.Append_Cell(1,5,3);
    TM.Append_Cell(4,5,1);
    TM.Append_Cell(9,6,5);
    TM.Append_Cell(9,5,7);
    TM.Append_Cell(8,9,5);

    // now add the vertex point coordinates
    TM.Init_Points(10);
    TM.Set_Coord(0, -0.5, 0.0,-1.0);
    TM.Set_Coord(1, -1.0, 0.0, 0.0);
    TM.Set_Coord(2, -0.5, 1.0, 0.0);
    TM.Set_Coord(3, -0.5, 0.0, 1.0);
    TM.Set_Coord(4, -0.5,-1.0, 0.0);
    TM.Set_Coord(5,  0.0, 0.0, 0.0);
    TM.Set_Coord(6,  0.5, 0.2, 1.0);
    TM.Set_Coord(7,  0.5,-0.1,-1.0);
    TM.Set_Coord(8,  0.5,-1.0, 0.0);
    TM.Set_Coord(9,  1.0, 0.0, 0.0);

    // now display coordinates
    cout << endl;
    TM.Display_Vtx_Coord();

    // we now stop adding cells
    TM.Finalize_v2hfs_DEBUG();

    // now display the half-facets (attached to vertices) of the intermediate structure 'v2hfs'
    cout << endl;
    TM.Display_v2hfs();

    // check 'v2hfs' against reference data
    VtxHalfFacetType v2hfs_REF[21];
    v2hfs_REF[ 0].Set(1,0,2);
    v2hfs_REF[ 1].Set(2,1,0);
    v2hfs_REF[ 2].Set(3,2,1);
    v2hfs_REF[ 3].Set(4,3,1);
    v2hfs_REF[ 4].Set(5,0,0);
    v2hfs_REF[ 5].Set(5,0,1);
    v2hfs_REF[ 6].Set(5,1,1);
    v2hfs_REF[ 7].Set(5,1,2);
    v2hfs_REF[ 8].Set(5,2,0);
    v2hfs_REF[ 9].Set(5,2,2);
    v2hfs_REF[10].Set(5,3,0);
    v2hfs_REF[11].Set(5,3,2);
    v2hfs_REF[12].Set(6,4,0);
    v2hfs_REF[13].Set(7,5,0);
    v2hfs_REF[14].Set(8,6,1);
    v2hfs_REF[15].Set(9,4,1);
    v2hfs_REF[16].Set(9,4,2);
    v2hfs_REF[17].Set(9,5,1);
    v2hfs_REF[18].Set(9,5,2);
    v2hfs_REF[19].Set(9,6,0);
    v2hfs_REF[20].Set(9,6,2);
    // error check
    const Vtx2HalfFacet_Mapping& c_V2HF_Map = TM.Get_v2hfs();
    const std::vector<VtxHalfFacetType>& c_v2hfs = c_V2HF_Map.Get_VtxMap();
    for (VtxIndType jj = 0; jj < c_v2hfs.size(); ++jj)
        if (!c_v2hfs[jj].Equal(v2hfs_REF[jj]))
        {
            cout << "Intermediate data 'v2hfs' failed!" << endl;
            OUTPUT_CODE = 1;
            break;
        }

    // fill out the sibling half-facet data in 'Cell'
    TM.Build_Sibling_HalfFacets_DEBUG();

    // display that cell connectivity data
    cout << endl;
    TM.Display_Cell();
    cout << endl;

    // check 'Cell' against reference data
    CellSimplexType<2> Cell_REF[7];
    HalfFacetType hf;
    // Cell #1
    Cell_REF[ 0].Set(0,0,hf.Set(1,1));
    Cell_REF[ 0].Set(1,1,hf.Set());
    Cell_REF[ 0].Set(2,5,hf.Set());
    // Cell #2
    Cell_REF[ 1].Set(0,5,hf.Set());
    Cell_REF[ 1].Set(1,2,hf.Set(2,2));
    Cell_REF[ 1].Set(2,1,hf.Set());
    // Cell #3
    Cell_REF[ 2].Set(0,1,hf.Set());
    Cell_REF[ 2].Set(1,5,hf.Set());
    Cell_REF[ 2].Set(2,3,hf.Set(3,0));
    // Cell #4
    Cell_REF[ 3].Set(0,4,hf.Set(0,0));
    Cell_REF[ 3].Set(1,5,hf.Set());
    Cell_REF[ 3].Set(2,1,hf.Set());
    // Cell #5
    Cell_REF[ 4].Set(0,9,hf.Set());
    Cell_REF[ 4].Set(1,6,hf.Set(5,2));
    Cell_REF[ 4].Set(2,5,hf.Set());
    // Cell #6
    Cell_REF[ 5].Set(0,9,hf.Set());
    Cell_REF[ 5].Set(1,5,hf.Set());
    Cell_REF[ 5].Set(2,7,hf.Set(6,0));
    // Cell #7
    Cell_REF[ 6].Set(0,8,hf.Set(4,1));
    Cell_REF[ 6].Set(1,9,hf.Set());
    Cell_REF[ 6].Set(2,5,hf.Set());
    // error check
    for (CellIndType cc = 0; cc < TM.Num_Cells(); ++cc)
    {
        const VtxIndType* C_vtx = NULL;
        const HalfFacetType* C_hf = NULL;
        TM.Get_Cell(cc, C_vtx, C_hf);
        if (!Cell_REF[cc].Equal(C_vtx, C_hf))
        {
            cout << "Cell connectivity (and sibling half-facets) is incorrect!" << endl;
            OUTPUT_CODE = 2;
            break;
        }
    }

    // generate the Vtx2HalfFacets data struct
    TM.Build_Vtx2HalfFacets_DEBUG();
    TM.Close(); // we can close it now, i.e. no more modifications

    // now display half-facets attached to vertices for final data structure
    TM.Display_Vtx2HalfFacets();
    cout << endl;

    // check 'Vtx2HalfFacets' against reference data
    VtxHalfFacetType Vtx2HalfFacets_REF[11];
    Vtx2HalfFacets_REF[ 0].Set(0,0,2);
    Vtx2HalfFacets_REF[ 1].Set(1,3,1);
    Vtx2HalfFacets_REF[ 2].Set(2,1,2);
    Vtx2HalfFacets_REF[ 3].Set(3,2,1);
    Vtx2HalfFacets_REF[ 4].Set(4,3,2);
    Vtx2HalfFacets_REF[ 5].Set(5,3,2);
    Vtx2HalfFacets_REF[ 6].Set(5,6,1);
    Vtx2HalfFacets_REF[ 7].Set(6,4,2);
    Vtx2HalfFacets_REF[ 8].Set(7,5,1);
    Vtx2HalfFacets_REF[ 9].Set(8,6,2);
    Vtx2HalfFacets_REF[10].Set(9,6,2);
    // error check
    const std::vector<VtxHalfFacetType>& c_Vtx2HF = TM.Get_Vtx2HalfFacets().Get_VtxMap();
    for (VtxIndType jj = 0; jj < c_Vtx2HF.size(); ++jj)
        if (!c_Vtx2HF[jj].Equal(Vtx2HalfFacets_REF[jj]))
        {
            cout << "'Vtx2HalfFacets' data is incorrect!" << endl;
            OUTPUT_CODE = 3;
            break;
        }

    // display cells attached to a vertex
    VtxIndType V_IN = 5;
    TM.Display_Cells_Attached_To_Vertex(V_IN);
    cout << endl;

    // check attached cells against reference data
    std::vector<CellIndType> cell_ind_1, cell_ind_2;
    TM.Get_Cells_Attached_To_Vertex(V_IN, 0, cell_ind_1);
    TM.Get_Cells_Attached_To_Vertex(V_IN, 4, cell_ind_2);
    const CellIndType cell_ind_1_REF[4] = {0, 1, 2, 3};
    const CellIndType cell_ind_2_REF[3] = {4, 5, 6};
    for (unsigned int jj = 0; jj < cell_ind_1.size(); ++jj)
        if (cell_ind_1[jj]!=cell_ind_1_REF[jj])
        {
            cout << "Cell attachment data is incorrect!" << endl;
            OUTPUT_CODE = 4;
            break;
        }
    for (unsigned int jj = 0; jj < cell_ind_2.size(); ++jj)
        if (cell_ind_2[jj]!=cell_ind_2_REF[jj])
        {
            cout << "Cell attachment data is incorrect!" << endl;
            OUTPUT_CODE = 5;
            break;
        }

    // display if two cells are facet connected
    const  VtxIndType V1 = 5;
    const CellIndType C1 = 0;
    const CellIndType C2 = 4;
    TM.Display_Two_Cells_Are_Facet_Connected(V1, C1, C2);
    cout << endl;

    // check facet connected cells against reference data
    const bool CHK_Facet_Connected = TM.Two_Cells_Are_Facet_Connected(V1, C1, C2);
    const bool CHK_Facet_Connected_REF = false;
    if (CHK_Facet_Connected!=CHK_Facet_Connected_REF)
    {
        cout << "Facet connected cell data is incorrect!" << endl;
        OUTPUT_CODE = 6;
    }

    // display half-facets attached to given half-facet
    HalfFacetType TEST_attached;
    TEST_attached.Set(1,1);
    TM.Display_HalfFacets_Attached_To_HalfFacet(TEST_attached);
    cout << endl;

    // check attached half-facets against reference data
    HalfFacetType attached_REF[4];
    attached_REF[0].Set(1,1);
    attached_REF[1].Set(2,2);
    attached_REF[2].Set(3,0);
    attached_REF[3].Set(0,0);
    std::vector<HalfFacetType> attached;
    TM.Get_HalfFacets_Attached_To_HalfFacet(TEST_attached, attached);
    for (unsigned int jj = 0; jj < attached.size(); ++jj)
        if (!attached[jj].Equal(attached_REF[jj]))
        {
            cout << "HalfFacet attachment data is incorrect!" << endl;
            OUTPUT_CODE = 7;
            break;
        }

    // check that half-facet has no neighbor
    TEST_attached.Set(4,2);
    TM.Get_HalfFacets_Attached_To_HalfFacet(TEST_attached, attached);
    if (attached.size()!=1)
    {
        cout << "HalfFacet attachment data is incorrect!" << endl;
        OUTPUT_CODE = 8;
    }
    else if (!TEST_attached.Equal(attached[0]))
    {
        cout << "HalfFacet attachment should only include the initial given half-facet..." << endl;
        cout << "          but it does not!" << endl;
        OUTPUT_CODE = 9;
    }

    // display non-manifold facets (edges)
    TM.Display_Nonmanifold_HalfFacets();
    cout << endl;

    // check non-manifold facets (edges) against reference data
    HalfFacetType non_manifold_hf_REF[2];
    non_manifold_hf_REF[0].Set(3,0);
    non_manifold_hf_REF[1].Set(6,0);
    std::vector<HalfFacetType> non_manifold_hf;
    TM.Get_Nonmanifold_HalfFacets(non_manifold_hf);
    for (unsigned int jj = 0; jj < non_manifold_hf.size(); ++jj)
        if (!non_manifold_hf[jj].Equal(non_manifold_hf_REF[jj]))
        {
            cout << "Non-manifold facet data is incorrect!" << endl;
            OUTPUT_CODE = 10;
            break;
        }

    // display non-manifold vertices
    TM.Display_Nonmanifold_Vertices();
    cout << endl;

    // check non-manifold vertices against reference data
    const VtxIndType non_manifold_vtx_REF[1] = {5};
    std::vector<VtxIndType> non_manifold_vtx;
    TM.Get_Nonmanifold_Vertices(non_manifold_vtx);
    for (unsigned int jj = 0; jj < non_manifold_vtx.size(); ++jj)
        if (non_manifold_vtx[jj]!=non_manifold_vtx_REF[jj])
        {
            cout << "Non-manifold vertex data is incorrect!" << endl;
            OUTPUT_CODE = 11;
            break;
        }

    TM.Display_Unique_Vertices();
    cout << endl;

    // check unique vertices against reference data
    std::vector<VtxIndType> uv;
    TM.Get_Unique_Vertices(uv);
    const VtxIndType uv_REF[10] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9};
    for (unsigned int jj = 0; jj < uv.size(); ++jj)
        if (uv[jj]!=uv_REF[jj])
        {
            cout << "Unique vertex data is incorrect!" << endl;
            OUTPUT_CODE = 12;
            break;
        }

    // display all edges in the mesh
    std::vector<MeshEdgeType> edges;
    TM.Get_Edges(edges);
    cout << "A unique list of edges in the mesh:" << endl;
    std::vector<MeshEdgeType>::const_iterator it;
    for (it = edges.begin(); it!=edges.end(); ++it)
    {
        cout << "[" << (*it).vtx[0] << ", " << (*it).vtx[1] << "]" << endl;
    }
    cout << endl;

    // test if a pair of vertices is connected by an edge
    cout << "Vtx #5 and Vtx #9 are connected." << endl;
    if (!TM.Is_Connected(5, 9))
    {
        cout << "Incorrect!  They are NOT connected!" << endl;
        OUTPUT_CODE = 13;
    }
    // test if a pair of vertices is connected by an edge
    cout << "Vtx #7 and Vtx #2 are NOT connected." << endl;
    if (TM.Is_Connected(7, 2))
    {
        cout << "Incorrect!  They ARE connected!" << endl;
        OUTPUT_CODE = 14;
    }
    cout << endl;

    // display all cells attached to an edge
    std::vector<CellIndType> attached_cells;
    MeshEdgeType EE;
    EE.Set(1,5);
    TM.Get_Cells_Attached_To_Edge(EE, attached_cells);
    cout << "Here are the cell indices of cells attached to the edge [1, 5]:" << endl;
    std::vector<CellIndType>::const_iterator ic;
    for (ic = attached_cells.begin(); ic!=attached_cells.end(); ++ic)
        cout << "Cell #" << (*ic) << endl;
    cout << endl;

    // display the free boundary
    std::vector<HalfFacetType> free_bdy;
    TM.Get_FreeBoundary(free_bdy);
    cout << "Here are the half-facets that lie on the free boundary:" << endl;
    std::vector<HalfFacetType>::const_iterator hfi;
    for (hfi = free_bdy.begin(); hfi!=free_bdy.end(); ++hfi)
    {
        (*hfi).Print();
        cout << endl;
    }
    cout << endl;

    if (OUTPUT_CODE==0)
        cout << "Unit test is successful!" << endl;
    else
        cout << "Unit test failed!" << endl;
    cout << endl;

    return OUTPUT_CODE;
}
    void operator()( const Grid & grid,
                     const unsigned dir,
                     const bool begin,
                     SurfaceMesh & surfaceMesh ) const
    {
        //! Sanity check of direction
        VERIFY_MSG( (dir < Grid::dim), "Input argument for direction wrong" );

        //! Dimensions of the grid
        const MultiIndexType gridSizes = grid.gridSizes();

        //! Multi-index component to compare with
        const int mIndexComp = ( begin == false ? 0 : gridSizes[dir]-1 );

        //! Number of elements in the structured grid
        const std::size_t numElements = MultiIndex::length( gridSizes );

        //! Number of elements on the requested surface
        const std::size_t numElementsOnSurface = numElements / gridSizes[ dir ];

        //! Construct parametric geometry of the element
        const unsigned surfaceID =
            detail_::convertToSurfaceID<VolumeElement::shape>( dir, begin );

        //! List of indices of the parameter space vertices which form the surface
        typename ParameterSurface::Surface
            parameterSurfaceIndices = ParameterSurface::surfaceTable[ surfaceID ];

        //! Interpolation points of the surface shape function
        boost::array< typename SurfaceShapeFun::VecDim,
                      SurfaceShapeFun::numFun> surfaceSupportPoints;
        SurfaceShapeFun::supportPoints( surfaceSupportPoints );

        
        //! Vertices of the parameter volume
        boost::array< typename LinearVolumeFun::VecDim,
                      LinearVolumeFun::numFun> volumeVertices;
        LinearVolumeFun::supportPoints( volumeVertices );

        // --> Reorder for hiearchical ordering
        //     Then, the object ParameterFaces< shape, dim-1> can be used and
        //     ParamaterSurface discarded.

        //! Iterator to surface mesh elements
        typename SurfaceMesh::ElementPtrIter surfElemIter
            = surfaceMesh.elementsBegin();

        //! Linear shape function on the surface simplex
        LinearSimplexFun linearSimplexFun;

        //! Hexahedra will have two triangles per face
        const unsigned numSurfElementsPerElement = 
            detail_::NumSimplicesPerElementSurface<VolumeElement::shape>::value;

        //! Temporary storage of surface elements and nodes
        std::vector<SurfaceElement*> surfaceElements;
        surfaceElements.reserve( numElementsOnSurface * numSurfElementsPerElement );
        std::vector<SurfaceNode*>    surfaceNodes;

        //! node counter
        std::size_t nodeCtr = 0;

        //! Go through all elements
        for ( std::size_t e = 0; e < numElements; e ++ ) {

            //! Construct multi-index from linear counter
            const MultiIndexType eM = MultiIndex::wrap( e, gridSizes );

            //! Check if on requested boundary surface
            const bool onBoundary = ( eM[ dir ] == mIndexComp );

            //! If so, construct the surface element(s)
            if ( onBoundary ) {

                //! Get pointer to volume element
                VolumeElement * vep = grid.elementPtr( eM );

                //! Go through elements on the surface of the volume element
                for ( unsigned se = 0; se < numSurfElementsPerElement; se ++ ) {

                    //! Create new surface element
                    SurfaceElement * surfElem = new SurfaceElement;

                    //! Extract the surface simplex's vertices
                    boost::array<unsigned, numSurfSimplexVertices> surfSimplex;
                    detail_::ExtractSurfaceSimplex<VolumeElement::shape>()( parameterSurfaceIndices,
                                                                            se, surfSimplex );

                    //! Set volume element pointer
                    surfElem -> setVolumeElementPointer( vep );

                    //! Access to surface elements geometry nodes
                    typename SurfaceElement::NodePtrIter nodePtrIter =
                        surfElem -> nodesBegin();

                    //! Go through the parameter points of the surface element
                    typename SurfaceElement::ParamIter paramIter =
                        surfElem -> parametricBegin();
                    typename SurfaceElement::ParamIter paramEnd  =
                        surfElem -> parametricEnd();

                    for ( unsigned p = 0; paramIter != paramEnd;
                          ++paramIter, ++nodePtrIter, p++ ) {

                        //! ..
                        typename base::Vector<surfaceDim>::Type eta
                            = surfaceSupportPoints[ p ];

                        typename LinearSimplexFun::FunArray phi;
                        linearSimplexFun.evaluate( eta, phi );

                        typename base::Vector<volumeDim>::Type xi
                            = base::constantVector<volumeDim>( 0. );

                        for ( unsigned s = 0; s < phi.size(); s ++ ) {
                            xi += phi[s] * volumeVertices[ surfSimplex[s] ];

                        }

                        *paramIter = xi;

                        //! evaluate geometry at the parameter point
                        const typename VolumeElement::Node::VecDim x =
                            base::Geometry<VolumeElement>()( vep, xi );

                        //! convert to vector and pass to node
                        std::vector<double> xV( x.size() );
                        for ( int d = 0; d < x.size(); d ++ )
                            xV[d] = x[d];

                        SurfaceNode * surfNode = new SurfaceNode;
                        surfNode -> setX( xV.begin() );
                        surfNode -> setID( nodeCtr++ );
                        
                        *nodePtrIter = surfNode;

                        surfaceNodes.push_back( surfNode );
                                                
                    } // end loop over surface element's nodes

                    //! Store element pointer
                    surfaceElements.push_back( surfElem );
                    
                } // end loop over simplices per volume element
                
            } // end condition if volume element lies on requested bdry

        }// end loop over all volume elements

        surfaceMesh.allocate( surfaceNodes.size(), surfaceElements.size() );

        std::copy( surfaceNodes.begin(), surfaceNodes.end(),
                   surfaceMesh.nodesBegin() );
        
        std::copy( surfaceElements.begin(), surfaceElements.end(),
                   surfaceMesh.elementsBegin() );
        
        return;
    }
Exemple #29
0
int getValence(const SurfaceMesh &mesh, const SurfaceMesh::SimplexID<1> vertexID)
{
    return mesh.get_cover(vertexID).size();
}
Exemple #30
0
void generateHistogram(const SurfaceMesh &mesh)
{
    // compute angle distribution
    std::array<double, 18> histogram;
    histogram.fill(0);
    for (auto face : mesh.get_level_id<3>())
    {
        auto   vertexIDs = mesh.get_name(face);
        // Unpack the ID's for convenience
        Vertex a = *mesh.get_simplex_up<1>({vertexIDs[0]});
        Vertex b = *mesh.get_simplex_up<1>({vertexIDs[1]});
        Vertex c = *mesh.get_simplex_up<1>({vertexIDs[2]});

        auto   binAngle = [&](double angle) -> int{
                return std::floor(angle/10);
            };
        histogram[binAngle(angle(a, b, c))]++;
        histogram[binAngle(angle(b, a, c))]++;
        histogram[binAngle(angle(c, a, b))]++;
    }

    int factor = mesh.size<3>()*3;
    std::for_each(histogram.begin(), histogram.end(), [&factor](double &n){
        n = 100.0*n/factor;
    });

    std::cout << "Angle Distribution:" << std::endl;
    for (int x = 0; x < 18; x++)
        std::cout << x*10 << "-" << (x+1)*10 << ": " << std::setprecision(2)
                  << std::fixed << histogram[x] << std::endl;
    std::cout << std::endl << std::endl;

    // compute the edge length distribution
    std::cout << "Edge Length Distribution:" << std::endl;
    std::vector<double> lengths;
    for (auto edge : mesh.get_level_id<2>())
    {
        auto   vertexIDs = mesh.down(edge);
        auto   t1  = *vertexIDs.cbegin();
        auto   t2  = *(++vertexIDs.cbegin());
        auto   v1  = *t1;
        auto   v2  = *t2;
        double len = magnitude(v2-v1);
        lengths.push_back(len);
    }
    std::sort(lengths.begin(), lengths.end());

    std::array<double, 20> histogramLength;
    histogramLength.fill(0);
    double                 interval = (lengths.back() - lengths.front())/20;
    double                 low = lengths.front();

    if (interval <= 0.0000001) // floating point roundoff prevention
    {
        std::cout << lengths.front() << ": " << 100 << std::endl << std::endl;
    }
    else
    {
        for (auto length : lengths)
        {
            histogramLength[std::floor((length-low)/interval)]++;
        }

        factor = mesh.size<2>();
        std::for_each(histogramLength.begin(), histogramLength.end(), [&factor](double &n){
            n = 100.0*n/factor;
        });

        for (int x = 0; x < 20; x++)
            std::cout << x*interval << "-" << (x+1)*interval << ": " << std::setprecision(2)
                      << std::fixed << histogramLength[x] << std::endl;
        std::cout << std::endl << std::endl;
    }

    // Compute the valence distribution
    std::array<double, 20> histogramValence;
    histogramValence.fill(0);

    for (auto vertexID : mesh.get_level_id<1>())
    {
        // TODO bounds checking here...
        histogramValence[getValence(mesh, vertexID)]++;
    }

    factor = mesh.size<1>();
    // std::for_each(histogramValence.begin(), histogramValence.end(),
    // [&factor](double& n){
    //         n = 100.0*n/factor;});
    std::cout << "Valence distribution:" << std::endl;
    for (int x = 0; x < 20; x++)
        std::cout << x << ": " << histogramValence[x] << std::endl;
    std::cout << std::endl << std::endl;
}