void remove_face_test_2() { CGAL_GRAPH_TRAITS_MEMBERS(T); Surface_fixture_2<T> f; // find the edge between x and v bool found; halfedge_descriptor e; boost::tie(e, found) = halfedge(f.x, f.w, f.m); assert(found); boost::tie(e, found) = halfedge(f.x, f.v, f.m); assert(found); assert(face(e, f.m) == f.f1); CGAL::Euler::remove_face(e,f.m); assert(CGAL::is_valid(f.m)); assert(CGAL::internal::exact_num_faces(f.m) == 3); assert(CGAL::internal::exact_num_edges(f.m) == 7); assert(CGAL::internal::exact_num_vertices(f.m) == 5); boost::tie(e, found) = halfedge(f.x, f.w, f.m); assert(found); assert(face(e,f.m) == boost::graph_traits<T>::null_face()); // check the boundary halfedge_descriptor n = next(e, f.m); while(n != e) { assert(face(n,f.m) == boost::graph_traits<T>::null_face() ); n = next(n, f.m); } }
void split_join_vertex_inverse() { CGAL_GRAPH_TRAITS_MEMBERS(T); Surface_fixture_3<T> f; halfedge_descriptor h, h1, h2; bool found; boost::tie(h, found) = halfedge(f.w, f.x, f.m); assert(found); CGAL::Euler::join_vertex(h,f.m); assert(CGAL::is_valid(f.m)); boost::tie(h1, found) = halfedge(f.z, f.x, f.m); assert(found); boost::tie(h2, found) = halfedge(f.v, f.x, f.m); assert(found); CGAL::Euler::join_vertex(CGAL::Euler::split_vertex(h1, h2,f.m),f.m); assert(CGAL::is_valid(f.m)); assert(CGAL::internal::exact_num_vertices(f.m)== 5); assert(CGAL::internal::exact_num_faces(f.m) == 2); assert(CGAL::internal::exact_num_edges(f.m) == 6); assert(CGAL::internal::exact_num_halfedges(f.m) == 12); assert(boost::distance(CGAL::halfedges_around_face(h1, f.m)) == 3); assert(boost::distance(CGAL::halfedges_around_face(h2, f.m)) == 3); }
void test_halfedge_around_face_iterator(const Graph& g) { CGAL_GRAPH_TRAITS_MEMBERS(Graph); face_iterator fit, fend; for(boost::tie(fit, fend) = faces(g); fit != fend; ++fit) { halfedge_around_face_iterator hafit, hafend; boost::tie(hafit, hafend) = CGAL::halfedges_around_face(halfedge(*fit, g), g); assert(std::distance(hafit, hafend) != 0); for(boost::tie(hafit, hafend) = CGAL::halfedges_around_face(halfedge(*fit, g), g); hafit != hafend; ++hafit) { assert(face(*hafit, g) == *fit); } } }
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); }
Vector3D Face::normal(void) const { Vector3D N(0., 0., 0.); HalfedgeCIter h = halfedge(); do { Vector3D pi = h->vertex()->position; Vector3D pj = h->next()->vertex()->position; N += cross(pi, pj); h = h->next(); } while (h != halfedge()); return N.unit(); }
double dynamics_mul::get_curvature(dsc_obj *obj, HMesh::Walker hew0){ // Find next edge on the boundary auto hew1 = hew0.next().opp(); while (1) { if (s_dsc->is_interface(hew1.halfedge())) { hew1 = hew1.opp(); break; } hew1 = hew1.next().opp(); } Vec2 p0 = obj->get_pos(hew0.vertex()) - obj->get_pos(hew0.opp().vertex()); Vec2 p1 = obj->get_pos(hew1.vertex()) - obj->get_pos(hew1.opp().vertex()); Vec2 norm0(p0[1], -p0[0]); norm0.normalize(); Vec2 norm1(p1[1], -p1[0]); norm1.normalize(); Vec2 norm = norm0 + norm1; norm.normalize(); double l0 = p0.length(); double l1 = p1.length(); double angle = std::atan2(CGLA::cross(p0, p1), DSC2D::Util::dot(p0, p1)); double curvature = angle / (l0/2.0 + l1/2.0); return curvature; }
void remove_face_test_1() { CGAL_GRAPH_TRAITS_MEMBERS(T); Surface_fixture_1<T> f; // find the edge between x and y bool found; halfedge_descriptor e; boost::tie(e, found) = halfedge(f.x, f.y, f.m); assert(found); assert(face(e, f.m) == f.f3); CGAL::Euler::remove_face(e,f.m); assert(CGAL::is_valid(f.m)); assert_EQUAL(degree(f.v, f.m) == 3); assert_EQUAL(degree(f.x, f.m) == 2); assert_EQUAL(CGAL::internal::exact_num_faces(f.m) == 2); assert_EQUAL(CGAL::internal::exact_num_edges(f.m) == 5); assert_EQUAL(CGAL::internal::exact_num_vertices(f.m) == 4); halfedge_iterator eb, ee; int count = 0; for(boost::tie(eb, ee) = halfedges(f.m); eb != ee; ++eb) { if(face(*eb,f.m) == boost::graph_traits<T>::null_face()) ++count; } assert(count == 4); }
// Interface length in node link double dynamics_mul::curve_length(Node_key nid, Vec2 new_pos){ double L = 0.0; for (auto hew = s_dsc->walker(nid); !hew.full_circle(); hew = hew.circulate_vertex_cw()) { if (s_dsc->is_interface(hew.halfedge())) { L += (s_dsc->get_pos(hew.vertex()) - new_pos).length(); } } return L; }
void join_vertex_interior_test() { CGAL_GRAPH_TRAITS_MEMBERS(T); Surface_fixture_3<T> f; halfedge_descriptor e; bool found; boost::tie(e, found) = halfedge(f.w, f.x, f.m); assert(found); CGAL::Euler::join_vertex(e,f.m); assert(CGAL::internal::exact_num_faces(f.m) == 2); assert(CGAL::internal::exact_num_vertices(f.m) == 5); assert(CGAL::internal::exact_num_edges(f.m) == 6); assert(boost::distance(CGAL::halfedges_around_face(halfedge(f.f1, f.m), f.m)) == 3); assert(boost::distance(CGAL::halfedges_around_face(halfedge(f.f2, f.m), f.m)) == 3); assert(degree(f.x, f.m) == 4); assert(CGAL::is_valid(f.m)); }
void dynamics_mul::compute_curvature_force(){ for (auto eid = s_dsc->halfedges_begin(); eid != s_dsc->halfedges_end(); eid++) { if (s_dsc->is_interface(*eid)) { auto hew0 = s_dsc->walker(*eid); // Find next edge on the boundary auto hew1 = hew0.next().opp(); while (1) { if (s_dsc->is_interface(hew1.halfedge())) { hew1 = hew1.opp(); break; } hew1 = hew1.next().opp(); } assert(hew0.halfedge() != hew1.halfedge()); Vec2 p0 = s_dsc->get_pos(hew0.vertex()) - s_dsc->get_pos(hew0.opp().vertex()); Vec2 p1 = s_dsc->get_pos(hew1.vertex()) - s_dsc->get_pos(hew1.opp().vertex()); Vec2 norm0(p0[1], -p0[0]); norm0.normalize(); Vec2 norm1(p1[1], -p1[0]); norm1.normalize(); Vec2 norm = norm0 + norm1; norm.normalize(); #ifdef DEBUG assert(norm.length() < 1.1 and norm.length() > 0.9); #endif double l0 = p0.length(); double l1 = p1.length(); double angle = std::atan2(CGLA::cross(p0, p1), DSC2D::Util::dot(p0, p1)); double curvature = angle / (l0/2.0 + l1/2.0); s_dsc->add_node_internal_force( hew0.vertex(), -norm*curvature*s_dsc->get_avg_edge_length()*g_param.alpha); } } }
void test_isolated_vertex() { Graph G; typedef boost::graph_traits< Graph > Traits; typedef typename Traits::vertex_descriptor vertex_descriptor; typedef typename Traits::halfedge_descriptor halfedge_descriptor; vertex_descriptor v = add_vertex(G); // the connectivity of v may be anything set_halfedge(v, Traits::null_halfedge(), G); halfedge_descriptor h = halfedge(v,G); CGAL_USE(h); }
void join_face_test() { CGAL_GRAPH_TRAITS_MEMBERS(T); Surface_fixture_1<T> f; bool found; halfedge_descriptor e; boost::tie(e, found) = halfedge(f.w, f.v, f.m); assert(found); // manually set the halfedge of f.f1 to the edge that is to be // removed to provoke a special case set_halfedge(f.f1, e, f.m); CGAL::Euler::join_face(e,f.m); assert(CGAL::internal::exact_num_faces(f.m) == 2); assert(CGAL::internal::exact_num_edges(f.m) == 6); CGAL::Halfedge_around_face_iterator<T> begin, end; boost::tie(begin, end) = CGAL::halfedges_around_face(halfedge(f.f1, f.m), f.m); assert(std::distance(begin, end) == 4); for(; begin != end; ++begin) { halfedge_descriptor hd = *begin; assert(face(hd, f.m) == f.f1); } face_iterator fit, fend; for(boost::tie(fit, fend) = faces(f.m); fit != fend; ++fit) { assert(*fit == f.f1 || *fit == f.f3); } assert(degree(f.w, f.m) == 2); assert(degree(f.v, f.m) == 3); assert(CGAL::is_valid(f.m)); }
void test_faces(const G& g) { typedef boost::graph_traits<G> Traits; typedef typename Traits::face_iterator face_iterator; typedef typename Traits::halfedge_descriptor halfedge_descriptor; typedef CGAL::Halfedge_around_face_iterator<G> halfedge_around_face_iterator; unsigned int count = 0; face_iterator fb, fe; for(boost::tie(fb, fe) = faces(g); fb != fe; ++fb) { ++count; // reverse look-up halfedge_descriptor assoc = halfedge(*fb, g); assert(face(assoc, g) == *fb); // check the enclosure halfedge_around_face_iterator encb, ence; for(boost::tie(encb, ence) = CGAL::halfedges_around_face(halfedge(*fb, g), g); encb != ence; ++encb) { assert(face(*encb, g) == *fb); } } assert(count == num_faces(g)); }
OutputIterator adjacent_vertices_V1(const Polyhedron& g, vertex_descriptor vd, OutputIterator out) { typename GraphTraits::halfedge_descriptor hb = halfedge(vd,g), done(hb); do { *out++ = source(hb,g); hb = opposite(next(hb,g),g); } while(hb!= done); return out; }
void split_vertex() { CGAL_GRAPH_TRAITS_MEMBERS(T); Surface_fixture_3<T> f; halfedge_descriptor h1, h2; bool found; boost::tie(h1, found) = halfedge(f.w, f.y, f.m); assert(found); boost::tie(h2, found) = halfedge(f.z, f.y, f.m); assert(found); assert(face(h2, f.m) == Traits::null_face()); // split border vertex y CGAL::Euler::split_vertex(h1, h2,f.m); assert(CGAL::is_valid(f.m)); assert(CGAL::internal::exact_num_vertices(f.m) == 7); assert(CGAL::internal::exact_num_edges(f.m) == 8); assert(boost::distance(CGAL::halfedges_around_face(h1, f.m)) == 5); assert(boost::distance(CGAL::halfedges_around_face(h2, f.m)) == 7); }
OutputIterator adjacent_vertices_V2(const Polyhedron& g, vertex_descriptor vd, OutputIterator out) { halfedge_around_target_iterator hi, he; for(boost::tie(hi, he) = halfedges_around_target(halfedge(vd,g),g); hi != he; ++hi) { *out++ = source(*hi,g); } return out; }
void Vertex::computeCentroid( void ) { // TODO Compute the average position of all neighbors of this vertex, and // TODO store it in Vertex::centroid. This value will be used for resampling. HalfedgeIter h = halfedge(); centroid.x = 0; centroid.y = 0; centroid.z = 0; do { h = h->twin(); Vector3D neighbor = h->vertex()->position; centroid += neighbor; h = h->next(); } while(h != halfedge()); //By convention, Vertex::degree() returns the face degree, //not the edge degree. The edge degree can be computed by finding the face //degree, and adding 1 if the vertex is a boundary vertex. int degree = this->degree(); if(isBoundary()) degree++; centroid /= (double)degree; }
ofMesh & ofxCGALSkinSurface::makeSkinSurfaceMesh() { std::list<Weighted_point> l; FT shrinkfactor = shrinkFactor; for(int i=0; i<points.size(); i++) { float px = points[i].point.x; float py = points[i].point.y; float pz = points[i].point.z; float radius = points[i].radius; l.push_front(Weighted_point(Bare_point(px, py, pz), radius * radius)); } Skin_surface_3 skin_surface(l.begin(), l.end(), shrinkfactor); Polyhedron p; CGAL::mesh_skin_surface_3(skin_surface, p); if(bSubdiv == true) { CGAL::subdivide_skin_surface_mesh_3(skin_surface, p); } mesh.clear(); map<Point_3, int> point_indices; int count = 0; for (auto it=p.vertices_begin(); it!=p.vertices_end(); ++it) { auto& p = it->point(); mesh.addVertex(ofVec3f(p.x(), p.y(), p.z())); point_indices[p] = count++; } for (auto it=p.facets_begin(); it!=p.facets_end(); ++it) { mesh.addIndex(point_indices[it->halfedge()->vertex()->point()]); mesh.addIndex(point_indices[it->halfedge()->next()->vertex()->point()]); mesh.addIndex(point_indices[it->halfedge()->prev()->vertex()->point()]); } }
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; }
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); }
void dynamics_mul::get_curvature(dsc_obj *obj, HMesh::Walker hew, double &Kcur, double &Kpre){ // Find preveous edge auto hew_pre = hew.prev().opp(); while (1) { if (obj->is_interface(hew_pre.halfedge())) { hew_pre = hew_pre.opp(); break; } hew_pre = hew_pre.prev().opp(); } Kcur = get_curvature(obj, hew); Kpre = get_curvature(obj, hew_pre); }
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; }
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; }
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); }
int main(int, char** argv) { LCC lcc; CGAL::read_off(argv[1], lcc); GraphTraits::vertex_descriptor vd = *(vertices(lcc).first); typedef boost::transform_iterator<Source<LCC>,halfedge_around_target_iterator> adjacent_vertex_iterator; halfedge_around_target_iterator hb,he; boost::tie(hb,he) = halfedges_around_target(halfedge(vd,lcc),lcc); adjacent_vertex_iterator avib, avie; avib = boost::make_transform_iterator(hb, Source<LCC>(lcc)); avie = boost::make_transform_iterator(he, Source<LCC>(lcc)); std::list<vertex_descriptor> V; std::copy(avib,avie, std::back_inserter(V)); return 0; }
void calculate_face_normals(const HalfedgeGraph& g, PointMap pm, NormalMap nm) { typedef boost::graph_traits<HalfedgeGraph> GraphTraits; typedef typename GraphTraits::face_iterator face_iterator; typedef typename GraphTraits::halfedge_descriptor halfedge_descriptor; typedef typename boost::property_traits<PointMap>::value_type point; typedef typename boost::property_traits<NormalMap>::value_type normal; face_iterator fb, fe; for(boost::tie(fb, fe) = faces(g); fb != fe; ++fb) { halfedge_descriptor edg = halfedge(*fb, g); halfedge_descriptor edgb = edg; point p0 = pm[target(edg, g)]; edg = next(edg, g); point p1 = pm[target(edg, g)]; edg = next(edg, g); point p2 = pm[target(edg, g)]; edg = next(edg, g); if(edg == edgb) { // triangle nm[*fb] = CGAL::unit_normal(p1, p2, p0); } else { // not a triangle normal n(CGAL::NULL_VECTOR); do { n = n + CGAL::normal(p1, p2, p0); p0 = p1; p1 = p2; edg = next(edg, g); p2 = pm[target(edg, g)]; } while(edg != edgb); nm[*fb] = n / CGAL::sqrt(n.squared_length()); } } }
int main(int argc, char** argv) { std::ifstream in((argc>1)?argv[1]:"cube.off"); Polyhedron P; in >> P; GraphTraits::vertex_descriptor vd = *(vertices(P).first); typedef boost::transform_iterator<Source<Polyhedron>,halfedge_around_target_iterator> adjacent_vertex_iterator; halfedge_around_target_iterator hb,he; boost::tie(hb,he) = halfedges_around_target(halfedge(vd,P),P); adjacent_vertex_iterator avib, avie; avib = boost::make_transform_iterator(hb, Source<Polyhedron>(P)); avie = boost::make_transform_iterator(he, Source<Polyhedron>(P)); std::list<vertex_descriptor> V; std::copy(avib,avie, std::back_inserter(V)); return 0; }
void test_halfedge_around_vertex_iterator(const Graph& g) { CGAL_GRAPH_TRAITS_MEMBERS(Graph); vertex_iterator vit, vend; for(boost::tie(vit, vend) = vertices(g); vit != vend; ++vit) { halfedge_around_target_iterator havit, havend; for(boost::tie(havit, havend) = CGAL::halfedges_around_target(halfedge(*vit, g), g); havit != havend; ++havit) { assert(target(*havit, g) == *vit); // check if we are really moving clockwise halfedge_around_target_iterator step = boost::next(havit); if(step != havend) { halfedge_descriptor stepd = *step; assert(stepd == opposite(next(*havit, g), g)); } } } }
void Surface_mesh:: adjust_outgoing_halfedge(Vertex v) { Halfedge h = halfedge(v); const Halfedge hh = h; if (h.is_valid()) { do { if (is_boundary(h)) { set_halfedge(v, h); return; } h = cw_rotated_halfedge(h); } while (h != hh); } }
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(); }