a48  2.0.2
example_stellarmesht.cc

This is an example of how to use the Stellar Mesh class together with items and stellar policy classes.

See also:
stellarmesht.hh
#include <iostream>
#include <set>
#include <map>

#include <cstring>

#include <mesh.hh>

typedef unsigned int uint;

template< class Traits >
class MyVertex : public a48::VertexT< Traits > {
public: uint id; float pos[3]; 
};

class MyTraits {
public:
    typedef MyVertex< MyTraits > vertex_type;
    typedef a48::HalfedgeT< MyTraits > halfedge_type;
    typedef a48::FaceT< MyTraits > face_type;
};

typedef a48::StellarMeshT< MyTraits > MyMesh; 

template< class Traits >
class MyItemsPolicy : public virtual a48::BaseItemsPolicy< Traits > {

    typedef typename Traits::vertex_type vertex_type;
    typedef typename Traits::halfedge_type halfedge_type;
    typedef typename Traits::face_type face_type;

public:

    unsigned int num_verts, num_faces;
    float *vertices;
    unsigned int *faces;

    MyItemsPolicy() {
        num_verts = 9; num_faces = 9;
        const float _vertices[] = {
            0.f, 0.f, 0.f,
            -1.f, -1.f, 0.f,
            1.f, -1.f, 0.f,
            1.f, 1.f, 0.f,
            -1.f, 1.f, 0.f,
            2.f, 0.f, 0.f,
            2.f, 1.f, 0.f,
            -2.f, 0.f, 0.f,
            -3.f, 1.f, 0.f
        };
        const uint _faces[] = {
            0, 1, 2,
            0, 2, 3,
            0, 3, 4,
            0, 4, 1,
            2, 5, 3,
            3, 5, 6,
            7, 1, 4,
            7, 8, 1,
            8, 7, 4
        };
        vertices = new float[ num_verts * 3 ];
        faces = new uint[ num_faces * 3 ];
        memcpy( vertices, _vertices, num_verts * 3 * sizeof(float) );
        memcpy( faces, _faces, num_faces * 3 * sizeof(uint) );
    }

    void set_vertex_attributes(const unsigned int& i, vertex_type *v) {
        v->id = i;
        v->pos[0] = vertices[ i*3 + 0 ];
        v->pos[1] = vertices[ i*3 + 1 ];
        v->pos[2] = vertices[ i*3 + 2 ];
    }

    ~MyItemsPolicy() {
        delete [] vertices;
        delete [] faces;
    }

    void set_vertex_attributes(vertex_type *v1, const vertex_type *v0) { }
    void set_halfedge_attributes(halfedge_type *h1, const halfedge_type *h0) { }
    void set_halfedge_attributes(halfedge_type *h, halfedge_type *o) { }
    void set_halfedge_attributes(const unsigned int& i, const unsigned int& j, const unsigned int& hi, halfedge_type *h) { }
    void set_face_attributes(face_type *f1, const face_type *f0) { }
    void set_face_attributes(const unsigned int& i, face_type *f) { }

};

template< class Traits >
class MyStellarPolicy : public virtual a48::BaseStellarPolicy< Traits > {

    typedef typename Traits::vertex_type vertex_type;
    typedef typename Traits::halfedge_type halfedge_type;
    typedef typename Traits::face_type face_type;

    typedef std::pair< uint, uint > edge_pair;
    typedef std::map< edge_pair, vertex_type > edge_map;

public:

    edge_map emap; 

    void sample_vertex(const halfedge_type *h, vertex_type *v) {
        uint id0 = h->vertex()->id;
        uint id1 = h->previous()->vertex()->id;
        if( id1 < id0 ) { uint idt = id0; id0 = id1; id1 = idt; }
        edge_pair e( id0, id1 );
        if( emap.find( e ) != emap.end() ) {
            v->id = emap[e].id;
            for (uint k=0; k<3; ++k) v->pos[k] = emap[e].pos[k];
            std::cout << "SAMPLING VERTEX\t(" << emap[e].id
                  << ") [" << emap[e].pos[0]
                  << " " << emap[e].pos[1]
                  << " " << emap[e].pos[2]
                  << " " << (emap[e].is_boundary() ? "b" : "i")
                  << " " << emap[e].degree()
                  << "]\n";
        }
    }

    void sample_vertex(const face_type *f, vertex_type *v) {
        sample_vertex( f->halfedge(), v );
        sample_vertex( f->halfedge()->next(), v );
        sample_vertex( f->halfedge()->previous(), v );
    }

    void remove_vertex(const halfedge_type *h, const vertex_type *v) {
        uint id0 = h->next()->opposite()->next()->vertex()->id;
        uint id1 = h->previous()->vertex()->id;
        if( id1 < id0 ) { uint idt = id0; id0 = id1; id1 = idt; }
        edge_pair e( id0, id1 );
        emap[e] = *v;
        std::cout << "REMOVE VERTEX (edge " << id0 << " " << id1;
        std::cout << ") (" << v->id
              << ") [" << emap[e].pos[0]
              << " " << emap[e].pos[1]
              << " " << emap[e].pos[2]
              << " " << (v->is_boundary() ? "b" : "i")
              << " " << v->degree()
              << "]\n";
    }

    void remove_vertex(const face_type *f, const vertex_type *v) {
        remove_vertex( f->halfedge(), v );
    }

    void flip_halfedge(const halfedge_type *h) {
        uint id0 = h->vertex()->id;
        uint id1 = h->previous()->vertex()->id;
        if( id1 < id0 ) { uint idt = id0; id0 = id1; id1 = idt; }
        edge_pair e( id0, id1 );
        if( emap.find( e ) != emap.end() ) {
            std::cout << "FLIPPING EDGE (edge " << id0 << " " << id1 << ")" << std::flush;
            id0 = h->next()->vertex()->id;
            id1 = h->opposite()->next()->vertex()->id;
            if( id1 < id0 ) { uint idt = id0; id0 = id1; id1 = idt; }
            edge_pair ne( id0, id1 );
            std::cout << " TO (edge " << id0 << " " << id1 << ")\n";
            emap[ne] = emap[e];
            emap.erase(e);
        }
    }

};


void show_mesh(const MyMesh& m) {

    std::cout << "_mesh_ Vertices: " << m.size_of_vertices() << std::endl;

    for (MyMesh::vertex_const_iterator vit = m.vertices_begin();
         vit != m.vertices_end(); ++vit) {

        std::cout << "\t(" << (*vit)->id
              << ") [" << (*vit)->pos[0]
              << " " << (*vit)->pos[1]
              << " " << (*vit)->pos[2]
              << " " << ((*vit)->is_boundary() ? "b" : "i")
              << " " << (*vit)->degree()
              << "]\n";

    }

    std::cout << "_mesh_ Halfedges: " << m.size_of_halfedges() << std::endl;

    for (MyMesh::halfedge_const_iterator hit = m.halfedges_begin();
         hit != m.halfedges_end(); ++hit) {

        std::cout << "\t[ " << (*hit)->from_vertex()->id
              << ":" << (*hit)->vertex()->id
              << " " << ((*hit)->is_boundary() ? "b" : "i")
              << " (" << (*hit)->face()->halfedge()->previous()->vertex()->id
              << ", " << (*hit)->face()->halfedge()->vertex()->id
              << ", " << (*hit)->face()->halfedge()->next()->vertex()->id
              << ") ]";

        if( !(*hit)->is_boundary() ) {
            std::cout << " / [ "
                  << (*hit)->opposite()->from_vertex()->id
                  << ":" << (*hit)->opposite()->vertex()->id
                  << " " << ((*hit)->opposite()->is_boundary() ? "b" : "i")
                  << "]";
        }

        std::cout << "\n";
        
    }

    std::cout << "_mesh_ Faces: " << m.size_of_faces() << std::endl;

    for (MyMesh::face_const_iterator fit = m.faces_begin();
         fit != m.faces_end(); ++fit) {

        std::cout << "\t[ " << (*fit)->halfedge()->previous()->vertex()->id
              << ", " << (*fit)->halfedge()->vertex()->id
              << ", " << (*fit)->halfedge()->next()->vertex()->id
              << " " << ((*fit)->is_boundary() ? "b" : "i")
              << " ]\n";

    }

    std::cout << "_mesh_ Vertices stars:" << std::endl;

    for (MyMesh::vertex_const_iterator vit = m.vertices_begin();
         vit != m.vertices_end(); ++vit) {

        std::cout << "\t(" << (*vit)->id << ")" << std::flush;

        for (const MyTraits::halfedge_type *hcurr = (*vit)->halfedge();
             hcurr != 0; hcurr = (*vit)->star_next(hcurr)) {

            std::cout << " [" << hcurr->from_vertex()->id
                  << ":" << hcurr->vertex()->id
                  << "]" << std::flush;

        }

        std::cout << "\n";

    }

}

int main(int argc, char* argv[]) {

    MyItemsPolicy< MyTraits > ip;
    MyStellarPolicy< MyTraits > sp;

    MyMesh m( &ip, &sp );

    m.set_base( ip.num_verts, ip.num_faces, ip.faces );

    show_mesh( m );

    const uint weld_ids[3] = { 0, 5, 7 };

    std::cout << "[test] Welding vertex: " << weld_ids[0] << "\n";

    for (MyMesh::vertex_const_iterator vit = m.vertices_begin();
         vit != m.vertices_end(); ++vit)
        if( (*vit)->id == weld_ids[0] ) { m.weld( *vit ); break; }

    show_mesh( m );

    std::cout << "[test] Welding vertex: " << weld_ids[1] << "\n";

    for (MyMesh::vertex_const_iterator vit = m.vertices_begin();
         vit != m.vertices_end(); ++vit)
        if( (*vit)->id == weld_ids[1] ) { m.weld( *vit ); break; }

    show_mesh( m );

    std::cout << "[test] Welding vertex: " << weld_ids[2] << "\n";

    for (MyMesh::vertex_const_iterator vit = m.vertices_begin();
         vit != m.vertices_end(); ++vit)
        if( (*vit)->id == weld_ids[2] ) { m.weld( *vit ); break; }

    show_mesh( m );

    uint fh_from_id = 1, fh_to_id = 3;

    std::cout << "[test] Flipping halfedge: "
          << fh_from_id << ":" << fh_to_id << "\n";

    for (MyMesh::halfedge_const_iterator hit = m.halfedges_begin();
         hit != m.halfedges_end(); ++hit) {

        if( (*hit)->from_vertex()->id == fh_from_id and
            (*hit)->vertex()->id == fh_to_id ) { m.flip( *hit ); break; }

    }

    show_mesh( m );

    uint sh_from_id = 2, sh_to_id = 6;

    std::cout << "[test] Splitting halfedge: "
          << sh_from_id << ":" << sh_to_id << "\n";

    for (MyMesh::halfedge_const_iterator hit = m.halfedges_begin();
         hit != m.halfedges_end(); ++hit) {

        if( (*hit)->from_vertex()->id == sh_from_id and
            (*hit)->vertex()->id == sh_to_id ) { m.split( *hit ); break; }

    }

    show_mesh( m );

    sh_from_id = 2; sh_to_id = 4;

    std::cout << "[test] Splitting halfedge: "
          << sh_from_id << ":" << sh_to_id << "\n";

    for (MyMesh::halfedge_const_iterator hit = m.halfedges_begin();
         hit != m.halfedges_end(); ++hit) {

        if( (*hit)->from_vertex()->id == sh_from_id and
            (*hit)->vertex()->id == sh_to_id ) { m.split( *hit ); break; }

    }

    show_mesh( m );

    uint sf_id[3] = { 8, 1, 4 };

    std::cout << "[test] Splitting face: [ "
          << sf_id[0] << ", " << sf_id[1] << ", " << sf_id[2] << " ]\n";

    for (MyMesh::face_const_iterator fit = m.faces_begin();
         fit != m.faces_end(); ++fit) {

        for (uint j = 0; j < 3; ++j)
            if( (*fit)->halfedge()->previous()->vertex()->id == sf_id[j] and
                (*fit)->halfedge()->vertex()->id == sf_id[(j+1)%3] and
                (*fit)->halfedge()->next()->vertex()->id == sf_id[(j+2)%3] ) {
                m.split( *fit );
                break;
            }

    }

    show_mesh( m );

    return 0;

}
 All Classes Namespaces Files Functions Typedefs