Exemplo n.º 1
0
bool
Surface_mesh::
is_collapse_ok(Halfedge v0v1)
{
    Halfedge  v1v0(opposite_halfedge(v0v1));
    Vertex    v0(to_vertex(v1v0));
    Vertex    v1(to_vertex(v0v1));
    Vertex    vv, vl, vr;
    Halfedge  h1, h2;


    // the edges v1-vl and vl-v0 must not be both boundary edges
    if (!is_boundary(v0v1))
    {
        vl = to_vertex(next_halfedge(v0v1));
        h1 = next_halfedge(v0v1);
        h2 = next_halfedge(h1);
        if (is_boundary(opposite_halfedge(h1)) && is_boundary(opposite_halfedge(h2)))
            return false;
    }


    // the edges v0-vr and vr-v1 must not be both boundary edges
    if (!is_boundary(v1v0))
    {
        vr = to_vertex(next_halfedge(v1v0));
        h1 = next_halfedge(v1v0);
        h2 = next_halfedge(h1);
        if (is_boundary(opposite_halfedge(h1)) && is_boundary(opposite_halfedge(h2)))
            return false;
    }


    // if vl and vr are equal or both invalid -> fail
    if (vl == vr) return false;


    // edge between two boundary vertices should be a boundary edge
    if ( is_boundary(v0) && is_boundary(v1) &&
        !is_boundary(v0v1) && !is_boundary(v1v0))
        return false;


    // test intersection of the one-rings of v0 and v1
    Vertex_around_vertex_circulator vv_it, vv_end;
    vv_it = vv_end = vertices(v0);
    do
    {
        vv = vv_it;
        if (vv != v1 && vv != vl && vv != vr)
            if (find_halfedge(vv, v1).is_valid())
                return false;
    }
    while (++vv_it != vv_end);


    // passed all tests
    return true;
}
Exemplo n.º 2
0
void
Surface_mesh::
flip(Edge e)
{
    // CAUTION : Flipping a halfedge may result in
    // a non-manifold mesh, hence check for yourself
    // whether this operation is allowed or not!

    //let's make it sure it is actually checked
    assert(is_flip_ok(e));

    Halfedge a0 = halfedge(e, 0);
    Halfedge b0 = halfedge(e, 1);

    Halfedge a1 = next_halfedge(a0);
    Halfedge a2 = next_halfedge(a1);

    Halfedge b1 = next_halfedge(b0);
    Halfedge b2 = next_halfedge(b1);

    Vertex   va0 = to_vertex(a0);
    Vertex   va1 = to_vertex(a1);

    Vertex   vb0 = to_vertex(b0);
    Vertex   vb1 = to_vertex(b1);

    Face     fa  = face(a0);
    Face     fb  = face(b0);

    set_vertex(a0, va1);
    set_vertex(b0, vb1);

    set_next_halfedge(a0, a2);
    set_next_halfedge(a2, b1);
    set_next_halfedge(b1, a0);

    set_next_halfedge(b0, b2);
    set_next_halfedge(b2, a1);
    set_next_halfedge(a1, b0);

    set_face(a1, fb);
    set_face(b1, fa);

    set_halfedge(fa, a0);
    set_halfedge(fb, b0);

    if (halfedge(va0) == b0)
        set_halfedge(va0, a1);
    if (halfedge(vb0) == a0)
        set_halfedge(vb0, b1);
}
Exemplo n.º 3
0
void
Surface_mesh::
split(Face f, Vertex v)
{
    /*
     Split an arbitrary face into triangles by connecting each vertex of fh to vh.
     - fh will remain valid (it will become one of the triangles)
     - the halfedge handles of the new triangles will point to the old halfeges
     */

    Halfedge hend = halfedge(f);
    Halfedge h    = next_halfedge(hend);

    Halfedge hold = new_edge(to_vertex(hend), v);

    set_next_halfedge(hend, hold);
    set_face(hold, f);

    hold = opposite_halfedge(hold);

    while (h != hend)
    {
        Halfedge hnext = next_halfedge(h);

        Face fnew = new_face();
        set_halfedge(fnew, h);

        Halfedge hnew = new_edge(to_vertex(h), v);

        set_next_halfedge(hnew, hold);
        set_next_halfedge(hold, h);
        set_next_halfedge(h,    hnew);

        set_face(hnew, fnew);
        set_face(hold, fnew);
        set_face(h,    fnew);

        hold = opposite_halfedge(hnew);

        h = hnext;
    }

    set_next_halfedge(hold, hend);
    set_next_halfedge(next_halfedge(hend), hold);

    set_face(hold, f);

    set_halfedge(v, hold);
}
Exemplo n.º 4
0
void
Surface_mesh::
remove_loop(Halfedge h)
{
    Halfedge  h0 = h;
    Halfedge  h1 = next_halfedge(h0);

    Halfedge  o0 = opposite_halfedge(h0);
    Halfedge  o1 = opposite_halfedge(h1);

    Vertex    v0 = to_vertex(h0);
    Vertex    v1 = to_vertex(h1);

    Face      fh = face(h0);
    Face      fo = face(o0);



    // is it a loop ?
    assert ((next_halfedge(h1) == h0) && (h1 != o0));


    // halfedge -> halfedge
    set_next_halfedge(h1, next_halfedge(o0));
    set_next_halfedge(prev_halfedge(o0), h1);


    // halfedge -> face
    set_face(h1, fo);


    // vertex -> halfedge
    set_halfedge(v0, h1);  adjust_outgoing_halfedge(v0);
    set_halfedge(v1, o1);  adjust_outgoing_halfedge(v1);


    // face -> halfedge
    if (fo.is_valid() && halfedge(fo) == o0)
        set_halfedge(fo, h1);


    // delete stuff
    if (!edeleted_) edeleted_ = edge_property<bool>("e:deleted", false);
    if (!fdeleted_) fdeleted_ = face_property<bool>("f:deleted", false);
    if (fh.is_valid()) { fdeleted_[fh] = true; ++deleted_faces_; }
    edeleted_[edge(h0)] = true; ++deleted_edges_;
    garbage_ = true;
}
Exemplo n.º 5
0
void
Surface_mesh::
triangulate(Face f)
{
    /*
     Split an arbitrary face into triangles by connecting
     each vertex of fh after its second to vh.

     - fh will remain valid (it will become one of the
     triangles)
     - the halfedge handles of the new triangles will
     point to the old halfedges
     */

    Halfedge base_h  = halfedge(f);
    Vertex   start_v = from_vertex(base_h);
    Halfedge next_h  = next_halfedge(base_h);

    while (to_vertex(next_halfedge(next_h)) != start_v)
    {
        Halfedge next_next_h(next_halfedge(next_h));

        Face new_f = new_face();
        set_halfedge(new_f, base_h);

        Halfedge new_h = new_edge(to_vertex(next_h), start_v);

        set_next_halfedge(base_h, next_h);
        set_next_halfedge(next_h, new_h);
        set_next_halfedge(new_h,  base_h);

        set_face(base_h, new_f);
        set_face(next_h, new_f);
        set_face(new_h,  new_f);

        base_h = opposite_halfedge(new_h);
        next_h = next_next_h;
    }
    set_halfedge(f, base_h);  //the last face takes the handle _fh

    set_next_halfedge(base_h, next_h);
    set_next_halfedge(next_halfedge(next_h), base_h);

    set_face(base_h, f);
}
Exemplo n.º 6
0
Surface_mesh::Normal
Surface_mesh::
compute_face_normal(Face f) const
{
    Halfedge h = halfedge(f);
    Halfedge hend = h;

    Point p0 = vpoint_[to_vertex(h)];
    h = next_halfedge(h);
    Point p1 = vpoint_[to_vertex(h)];
    h = next_halfedge(h);
    Point p2 = vpoint_[to_vertex(h)];

    if (next_halfedge(h) == hend) // face is a triangle
    {
        p2-=p1;
        p0-=p1;
        return p2.cross(p0).normalized();
    }

    else // face is a general polygon
    {
        Normal n(0,0,0);

        hend = h;
        do
        {
            n += (p2-p1).cross(p0-p1);
            h  = next_halfedge(h);
            p0 = p1;
            p1 = p2;
            p2 = vpoint_[to_vertex(h)];
        }
        while (h != hend);

        return n.normalized();
    }
}
Exemplo n.º 7
0
bool
Surface_mesh::
is_flip_ok(Edge e) const
{
    // boundary edges cannot be flipped
    if (is_boundary(e)) return false;

    // check if the flipped edge is already present in the mesh

    Halfedge h0 = halfedge(e, 0);
    Halfedge h1 = halfedge(e, 1);

    Vertex v0 = to_vertex(next_halfedge(h0));
    Vertex v1 = to_vertex(next_halfedge(h1));

    if (v0 == v1)   // this is generally a bad sign !!!
        return false;

    if (find_halfedge(v0, v1).is_valid())
        return false;

    return true;
}
Exemplo n.º 8
0
Surface_mesh::Normal
Surface_mesh::
compute_vertex_normal(Vertex v) const
{
    Point     nn(0,0,0);
    Halfedge  h = halfedge(v);

    if (h.is_valid())
    {
        const Halfedge hend = h;
        const Point p0 = vpoint_[v];

        Point   n, p1, p2;
        Scalar  cosine, angle;

        do
        {
            if (!is_boundary(h))
            {
                p1 = vpoint_[to_vertex(h)];
                p1 -= p0;
                p1.normalize();

                p2 = vpoint_[from_vertex(prev_halfedge(h))];
                p2 -= p0;
                p2.normalize();

                cosine = p1.dot(p2) / sqrt(p1.dot(p1)*p2.dot(p2));
                if      (cosine < -1.0) cosine = -1.0;
                else if (cosine >  1.0) cosine =  1.0;
                angle = acos(cosine);

                n   = p1.cross(p2).normalized();
                n  *= angle;
                nn += n;
            }

            h  = cw_rotated_halfedge(h);
        }
        while (h != hend);

        nn.normalize();
    }

    return nn;
}
Exemplo n.º 9
0
Surface_mesh::Halfedge
Surface_mesh::
find_halfedge(Vertex start, Vertex end) const
{
    assert(is_valid(start) && is_valid(end));

    Halfedge h  = halfedge(start);
    const Halfedge hh = h;

    if (h.is_valid())
    {
        do
        {
            if (to_vertex(h) == end)
                return h;
            h = cw_rotated_halfedge(h);
        }
        while (h != hh);
    }

    return Halfedge();
}
Exemplo n.º 10
0
void
Surface_mesh::
split(Edge e, Vertex v)
{
    Halfedge h0 = halfedge(e, 0);
    Halfedge o0 = halfedge(e, 1);

    Vertex   v2 = to_vertex(o0);

    Halfedge e1 = new_edge(v, v2);
    Halfedge t1 = opposite_halfedge(e1);

    Face     f0 = face(h0);
    Face     f3 = face(o0);

    set_halfedge(v, h0);
    set_vertex(o0, v);

    if (!is_boundary(h0))
    {
        Halfedge h1 = next_halfedge(h0);
        Halfedge h2 = next_halfedge(h1);

        Vertex   v1 = to_vertex(h1);

        Halfedge e0 = new_edge(v, v1);
        Halfedge t0 = opposite_halfedge(e0);

        Face f1 = new_face();
        set_halfedge(f0, h0);
        set_halfedge(f1, h2);

        set_face(h1, f0);
        set_face(t0, f0);
        set_face(h0, f0);

        set_face(h2, f1);
        set_face(t1, f1);
        set_face(e0, f1);

        set_next_halfedge(h0, h1);
        set_next_halfedge(h1, t0);
        set_next_halfedge(t0, h0);

        set_next_halfedge(e0, h2);
        set_next_halfedge(h2, t1);
        set_next_halfedge(t1, e0);
    }
    else
    {
        set_next_halfedge(prev_halfedge(h0), t1);
        set_next_halfedge(t1, h0);
        // halfedge handle of _vh already is h0
    }


    if (!is_boundary(o0))
    {
        Halfedge o1 = next_halfedge(o0);
        Halfedge o2 = next_halfedge(o1);

        Vertex v3 = to_vertex(o1);

        Halfedge e2 = new_edge(v, v3);
        Halfedge t2 = opposite_halfedge(e2);

        Face f2 = new_face();
        set_halfedge(f2, o1);
        set_halfedge(f3, o0);

        set_face(o1, f2);
        set_face(t2, f2);
        set_face(e1, f2);

        set_face(o2, f3);
        set_face(o0, f3);
        set_face(e2, f3);

        set_next_halfedge(e1, o1);
        set_next_halfedge(o1, t2);
        set_next_halfedge(t2, e1);

        set_next_halfedge(o0, e2);
        set_next_halfedge(e2, o2);
        set_next_halfedge(o2, o0);
    }
    else
    {
        set_next_halfedge(e1, next_halfedge(o0));
        set_next_halfedge(o0, e1);
        set_halfedge(v, e1);
    }

    if (halfedge(v2) == h0)
        set_halfedge(v2, t1);
}
Exemplo n.º 11
0
void
Surface_mesh::
garbage_collection()
{
    if (!garbage_) return;

    int  i, i0, i1,
    nV(vertices_size()),
    nE(edges_size()),
    nH(halfedges_size()),
    nF(faces_size());

    Vertex    v;
    Halfedge  h;
    Face      f;

    if (!vdeleted_) vdeleted_ = vertex_property<bool>("v:deleted", false);
    if (!edeleted_) edeleted_ = edge_property<bool>("e:deleted", false);
    if (!fdeleted_) fdeleted_ = face_property<bool>("f:deleted", false);


    // setup handle mapping
    Vertex_property<Vertex>      vmap = add_vertex_property<Vertex>("v:garbage-collection");
    Halfedge_property<Halfedge>  hmap = add_halfedge_property<Halfedge>("h:garbage-collection");
    Face_property<Face>          fmap = add_face_property<Face>("f:garbage-collection");
    for (i=0; i<nV; ++i)
        vmap[Vertex(i)] = Vertex(i);
    for (i=0; i<nH; ++i)
        hmap[Halfedge(i)] = Halfedge(i);
    for (i=0; i<nF; ++i)
        fmap[Face(i)] = Face(i);



    // remove deleted vertices
    if (nV > 0)
    {
        i0=0;  i1=nV-1;

        while (1)
        {
            // find first deleted and last un-deleted
            while (!vdeleted_[Vertex(i0)] && i0 < i1)  ++i0;
            while ( vdeleted_[Vertex(i1)] && i0 < i1)  --i1;
            if (i0 >= i1) break;

            // swap
            vprops_.swap(i0, i1);

            //add
            for(unsigned int j = 0;j<map_2skel.size();j++)
            {
                if(map_2skel[j] == i0)
                    map_2skel[j] = i1;
                else if(map_2skel[j] == i1)
                    map_2skel[j] = i0;
            }
            //end
        };

        // remember new size
        nV = vdeleted_[Vertex(i0)] ? i0 : i0+1;
    }


    // remove deleted edges
    if (nE > 0)
    {
        i0=0;  i1=nE-1;

        while (1)
        {
            // find first deleted and last un-deleted
            while (!edeleted_[Edge(i0)] && i0 < i1)  ++i0;
            while ( edeleted_[Edge(i1)] && i0 < i1)  --i1;
            if (i0 >= i1) break;

            // swap
            eprops_.swap(i0, i1);
            hprops_.swap(2*i0,   2*i1);
            hprops_.swap(2*i0+1, 2*i1+1);
        };

        // remember new size
        nE = edeleted_[Edge(i0)] ? i0 : i0+1;
        nH = 2*nE;
    }


    // remove deleted faces
    if (nF > 0)
    {
        i0=0;  i1=nF-1;

        while (1)
        {
            // find 1st deleted and last un-deleted
            while (!fdeleted_[Face(i0)] && i0 < i1)  ++i0;
            while ( fdeleted_[Face(i1)] && i0 < i1)  --i1;
            if (i0 >= i1) break;

            // swap
            fprops_.swap(i0, i1);
        };

        // remember new size
        nF = fdeleted_[Face(i0)] ? i0 : i0+1;
    }


    // update vertex connectivity
    for (i=0; i<nV; ++i)
    {
        v = Vertex(i);
        if (!is_isolated(v))
            set_halfedge(v, hmap[halfedge(v)]);
    }


    // update halfedge connectivity
    for (i=0; i<nH; ++i)
    {
        h = Halfedge(i);
        set_vertex(h, vmap[to_vertex(h)]);
        set_next_halfedge(h, hmap[next_halfedge(h)]);
        if (!is_boundary(h))
            set_face(h, fmap[face(h)]);
    }


    // update handles of faces
    for (i=0; i<nF; ++i)
    {
        f = Face(i);
        set_halfedge(f, hmap[halfedge(f)]);
    }


    // remove handle maps
    remove_vertex_property(vmap);
    remove_halfedge_property(hmap);
    remove_face_property(fmap);


    // finally resize arrays
    vprops_.resize(nV); vprops_.free_memory();
    hprops_.resize(nH); hprops_.free_memory();
    eprops_.resize(nE); eprops_.free_memory();
    fprops_.resize(nF); fprops_.free_memory();

    deleted_vertices_ = deleted_edges_ = deleted_faces_ = 0;
    garbage_ = false;
}
Exemplo n.º 12
0
void
Surface_mesh::
remove_edge(Halfedge h)
{
    Halfedge  hn = next_halfedge(h);
    Halfedge  hp = prev_halfedge(h);

    Halfedge  o  = opposite_halfedge(h);
    Halfedge  on = next_halfedge(o);
    Halfedge  op = prev_halfedge(o);

    Face      fh = face(h);
    Face      fo = face(o);

    Vertex    vh = to_vertex(h);
    Vertex    vo = to_vertex(o);



    // halfedge -> vertex
    Halfedge_around_vertex_circulator vh_it, vh_end;
    vh_it = vh_end = halfedges(vo);
    do
    {
        set_vertex(opposite_halfedge(vh_it), vh);
    }
    while (++vh_it != vh_end);


    // halfedge -> halfedge
    set_next_halfedge(hp, hn);
    set_next_halfedge(op, on);


    // face -> halfedge
    if (fh.is_valid())  set_halfedge(fh, hn);
    if (fo.is_valid())  set_halfedge(fo, on);


    // vertex -> halfedge
    if (halfedge(vh) == o)  set_halfedge(vh, hn);
    adjust_outgoing_halfedge(vh);
    set_halfedge(vo, Halfedge());


    // delete stuff
    if (!vdeleted_) vdeleted_ = vertex_property<bool>("v:deleted", false);
    if (!edeleted_) edeleted_ = edge_property<bool>("e:deleted", false);
    vdeleted_[vo]      = true; ++deleted_vertices_;
    edeleted_[edge(h)] = true; ++deleted_edges_;
    garbage_ = true;

    //add
    for(unsigned int j = 0;j < map_2skel.size();j++)
    {
        if(map_2skel[j] == vo.idx())
        {
            //unsigned int tem = map_2skel[j];
            map_2skel[j] = vh.idx();
            //qDebug("vertex:[%d],change %d to %d",j,tem,vh.idx());
        }
    }
    //end
}
Exemplo n.º 13
0
void draw_it(const std::vector<std::vector<sf::Vertex>> & sims, float time, float height, std::string title)
{
	//http://www.sfml-dev.org/tutorials/2.1/start-vc.php
	//nb -s for static libs
	const float edge = 30.0f;
	const float lineWidth = 5.0f;
	const float width = 500.0f;
	const float x_scale = width/time;
	const auto bagColour = sf::Color(180, 120, 60);
    sf::RenderWindow window(sf::VideoMode(static_cast<int>(width + 2*edge), static_cast<int>(height + 2*edge)), title);
	window.clear(sf::Color::Black);

	sf::RectangleShape  left(sf::Vector2f(lineWidth, static_cast<float>(height)));
	left.setFillColor(bagColour);
	left.setPosition(edge, edge);
	window.draw(left);

	sf::RectangleShape  right(sf::Vector2f(lineWidth, static_cast<float>(height)));
	right.setFillColor(bagColour);
	right.setPosition(edge + width, edge);
	window.draw(right);

	sf::RectangleShape  base(sf::Vector2f(static_cast<float>(width) + lineWidth, lineWidth));
	base.setFillColor(bagColour);
	base.setPosition(edge, edge + height);
	window.draw(base);

	assert(sims.begin()->size());
	//TODO - and they are all the same
	size_t penultimate = sims.begin()->size() - 1;
	size_t last = 1;
    while (window.isOpen())
    {
        // check all the window's events that were triggered since the last iteration of the loop
        sf::Event event;
        while (window.pollEvent(event))
        {
            // "close requested" event: we close the window
            if (event.type == sf::Event::Closed)
                window.close();
			break;
        }

        window.clear();
		window.draw(left);
		window.draw(right);
		window.draw(base);
		last = std::min(++last, sims.begin()->size() - 1);
		for(const auto & points: sims)
		{
			bool out = false;
			for(size_t i=0; i < last; ++i)
			{
				out |= (points[i].position.y > height);//what about the edge?
				sf::Color colour = out ? sf::Color::Green: sf::Color::White;
				auto scaled_start = to_vertex(points[i], colour, edge + lineWidth, x_scale, height);
				auto scaled_point = to_vertex(points[i+1], colour, edge + lineWidth, x_scale, height);
				sf::Vertex line[] = {scaled_start, scaled_point};
				window.draw(line, 2, sf::Lines);
			}
		}
		window.display();
		std::this_thread::sleep_for(std::chrono::milliseconds(50));//set render rate... or whatever it's called
    }

}