Program Listing for File read_mesh.cpp#

Return to documentation for file (pymembrane/cppmodule/src/read_mesh.cpp)

#include "read_mesh.hpp"
#include "mesh/computegeometry.hpp"
#include "../external/json_lib/json.hpp"
//operators
#include "mesh/meshoperators.hpp"

#include <pybind11/pybind11.h>
namespace py = pybind11;

void ReadMesh::__add_vertex(int id, real x, real y, real z, int type)
{
    //properties
    HE_VertexProp vertex;
    vertex.id = vertices.size();
    vertex.r.x = x;
    vertex.r.y = y;
    vertex.r.z = z;
    vertex.boundary = false;
    vertex.coordination = -1;
    vertex._hedge = -1;
    vertex.type = type;
    vertex.ip.x = 0;
    vertex.ip.y = 0;
    vertex.ip.z = 0;
    vertex.normal.x = 0.;
    vertex.normal.y = 0.;
    vertex.normal.z = 0.;
    vertices.push_back(vertex);
}
void ReadMesh::__add_face(int id, std::vector<int> verts, int orientation, int type)
{
    HE_FaceProp face; //Create new face
    face.id = id;
    face.outer = false;
    face.type = type;
    face.normal_reference.x = 0.0;
    face.normal_reference.y = 0.0;
    face.normal_reference.z = 1.0;

    int v1 = verts[0];
    int v2 = verts[1];
    int v3 = verts[2];

    if(orientation==-1)
    {
        int v_dummy = v2;
        v2 = v3;
        v3 = v_dummy;
    }
    verts[0] = v1;
    verts[1] = v2;
    verts[2] = v3;
    face.v1 = v1;
    face.v2 = v2;
    face.v3 = v3;
    //std::cout << v1 << " " << v2 << " " << v3 << std::endl;

    std::vector<HE_HalfEdgeProp> he_list;                         // Local storage for prev/next bookkeeping

    int N = verts.size();
    for (int i = 0; i < N; i++) // Loop over all vertices in the face
    {
        auto vi = verts[i];                                        //  First vertex
        auto vj = verts[(i + 1) % N];                              //  and its follower, that can be wrapped around
        //std::cout<< vi << " " << vj << std::endl;
        bool new_pair = false;                                     //  flag that checks if we created a new pair of half-edges

        HE_HalfEdgeProp he;     he.boundary=false;
        HE_HalfEdgeProp hep;    hep.boundary=false;
        std::pair<int,int> vij(vi,vj);
        std::pair<int,int> vji(vj,vi);
        if (hep_map.find(vij) == hep_map.end()) // if the half-edge does not exist
        {
            he.index = halfedges.size();        //create it
            hep.index = he.index + 1;           //and create its neighbour
            he.pair = hep.index;                //set them as pairs of each other
            hep.pair = he.index;
            hep.boundary = true;                //per construction, pair is boundary
            hep_map[vji] = hep.index;
            new_pair = true;                    //set new_pair flag to True for post-processing*/
        }
        else                                    //if the half-edge exists retrieve it
        {
            he = halfedges[hep_map[vij]];
            he.boundary = false;                //per construction, it cannat be boundary
            hep_map.erase(vij);
        }
        //Do the bookkeeping of the connectivity
        he.vert_from = vi;
        he.vert_to = vj;
        he.face = face.id;
        he_list.push_back(he);
        if(i > 0)
        {
            if(he_list[i-1].index>=halfedges.size()) std::cout << "error here if(i > 0)" << std::endl;
            he.prev = he_list[i-1].index;
            halfedges[he_list[i-1].index].next = he.index;
        }
        if(i == N-1)
        {
            if(he_list[0].index>=halfedges.size()) std::cout << "error here if(i == N-1)" << std::endl;
            he.next = he_list[0].index;
            halfedges[he_list[0].index].prev = he.index;
            face._hedge = he.index;
        }
        vertices[vi]._hedge = he.index;
        //Add new pair to the list of all half-edges
        if(new_pair)
        {
            halfedges.push_back(he);
            halfedges.push_back(hep);
        }
        else //Update the halfedge
        {
            halfedges[he.index] = he;
        }
        //construct the face and the vertices at the boundary
        if(he.boundary == false)
            face.outer = false;
    }
    faces.push_back(face);
}

int ReadMesh::__add_edge(const HE_HalfEdgeProp& he, const HE_HalfEdgeProp& he_pair)
{
    HE_EdgeProp edge;
    edge.id = edges.size();
    edge.i = he.vert_from;
    edge.j = he.vert_to;
    edge.boundary = false;
    if((he.boundary==true) || (he_pair.boundary==true))
    {
        edge.boundary = true;
        vertices[edge.i].boundary = true;
        vertices[edge.j].boundary = true;
    }
    edge.face_k = he.face;
    edge.face_l = he_pair.face;
    edge._hedge = he.index;
    edge.type = 0;
    edge.v0 = he.vert_to;
    edge.v2 = he.vert_from;
    int he_next = he.next;
    edge.v1 = halfedges[he_next].vert_to;
    int he_index_pair_next = he_pair.next;
    edge.v3 = halfedges[he_index_pair_next].vert_to;
    edges.push_back(edge);
    return(edge.id);
}
void ReadMesh::__build_boundary(void)
{
    // After all inner faces have been adde, what is left in the hep_map dictionary
    // are boundary edges.
    // We need to connect them to each other in the proper order
    close_surface = true;
    for(auto item : hep_map)
    {
        close_surface = false;
        auto vij = item.first;
        auto he = halfedges[hep_map[vij]];
        int i = vij.first;
        int j = vij.second;
        he.vert_from = i;
        he.vert_to = j;
        he.face = -1;
        auto v = vertices[j];
        auto hev = halfedges[v._hedge];
        while(!hev.boundary)
        {
            hev = halfedges[halfedges[hev.prev].pair];
        }
        he.next = hev.index;
        hev.prev = he.index;
        halfedges[he.index] = he;
        halfedges[hev.index] = hev;
    }
    Numhalfedges = halfedges.size();
}

void ReadMesh::__build_edges(void)
{
    std::map<std::pair<int,int>, int> edges_list;
    for(int index=0;index<halfedges.size();index++)
    {
        auto he = halfedges[index];
        auto he_pair = halfedges[he.pair];
        std::pair<int, int> vij(he.vert_from, he.vert_to);
        std::pair<int, int> vji(he.vert_to, he.vert_from);

        if (edges_list.find(vij) == edges_list.end())   // if the edge does not exist
        {
            int edge_id = __add_edge(he, he_pair);
            edges_list[vij] = edge_id;
            edges_list[vji] = edge_id;
            halfedges[index].edge = edge_id;
        }
        else                                            //if the edge exists retrieve it
        {
            halfedges[index].edge = edges_list[vij];
        }
    }

}

void ReadMesh::__build_mesh(std::string &faces_file, std::string &vertices_file)
{
    std::ifstream file_vertex(vertices_file, std::ios::in);
    if (file_vertex.good())
    {
        std::string str;
        int num_triangles = 0;
        while (getline(file_vertex, str))
        {
            std::istringstream ss(str);
            //std::cout<< str << "\n";
            real num;
            std::vector<real> aux;
            while (ss >> num)
            {
                aux.push_back(num);
                //std::cout<< num << "\t";
            }
            this->__add_vertex(aux[0], aux[1], aux[2], aux[3], aux[4]);
            //std::cout<< "vertex[" << vert.size()-1 << "] = < " << vert[vert.size()-1].x << "," << vert[vert.size()-1].y << "," << vert[vert.size()-1].z << " >\n";
        }
    }
    else
    {
        py::print("Error no vertex file is provided\n");
        exit(1);
    }

    std::ifstream file_triangles(faces_file, std::ios::in);
    if (file_triangles.good())
    {
        std::string str;
        int num_triangles = 0;
        while (getline(file_triangles, str))
        {
            std::istringstream ss(str);
            //std::cout<< str << "\n";
            int num;
            std::vector<int> aux;
            while (ss >> num)
            {
                aux.push_back(num);
            }
            std::vector<int> triangle = {aux[1], aux[2], aux[3]};
            __add_face(aux[0], triangle, aux[4], aux[5]);
        }
    }
    else
    {
        py::print("Error no triangles file is provided\n");
        exit(1);
    }
    this->__build_boundary();
    this->__build_edges();
    std::transform(vertices.begin(), vertices.end(), vertices.begin(), pymemb::reset_vertex_forces());
    std::transform(vertices.begin(), vertices.end(), vertices.begin(), pymemb::reset_vertex_energy());
    std::transform(vertices.begin(), vertices.end(), vertices.begin(), pymemb::reset_vertex_velocities());
    std::transform(vertices.begin(), vertices.end(), vertices.begin(), pymemb::reset_vertex_acceleration());
    std::transform(edges.begin(), edges.end(), edges.begin(), pymemb::reset_edge_energy());
    std::transform(faces.begin(), faces.end(), faces.begin(), pymemb::reset_face_energy());
}

void ReadMesh::__json_mesh(std::string& json_file)
{

}