void ComputeGaussCurvature(Polyhedron::Vertex_iterator v1) { double theta(0.0); Point3d p1 = v1->point(); Point3d p2,p3; Vector3d v12, v13; Polyhedron::Halfedge_around_vertex_circulator first, curr, next; first = curr = v1->vertex_begin(); do { next = curr; next++; p2 = curr->opposite()->vertex()->point(); p3 = next->opposite()->vertex()->point(); v12 = p2-p1; v13 = p3-p1; theta += std::acos( dot(v12,v13) / (norm(v12)*norm(v13)) ); } while(++curr!=first); v1->set_gauss_curvature(2.0*M_PI - theta); }
Polyhedron::Halfedge_iterator GetHalfedge(Polyhedron::Vertex_iterator a, Polyhedron::Vertex_iterator b) { Polyhedron::Halfedge_around_vertex_circulator first, curr; first = curr = b->vertex_begin(); do { if(a == curr->opposite()->vertex()) return curr; } while(++curr!=first); throw std::runtime_error("[Polyhedron::GetHalfedge] Error, a is not connected to b."); }
void Polyhedron_demo_jet_fitting_plugin::on_actionEstimateCurvature_triggered() { // get active polyhedron const Scene_interface::Item_id index = scene->mainSelectionIndex(); Scene_polyhedron_item* poly_item = qobject_cast<Scene_polyhedron_item*>(scene->item(index)); if(!poly_item) return; // wait cursor QApplication::setOverrideCursor(Qt::WaitCursor); Polyhedron* pMesh = poly_item->polyhedron(); // types typedef CGAL::Monge_via_jet_fitting<Kernel> Fitting; typedef Fitting::Monge_form Monge_form; typedef Kernel::Point_3 Point; Scene_polylines_item* max_curv = new Scene_polylines_item; max_curv->setColor(Qt::red); max_curv->setName(tr("%1 (max curvatures)").arg(poly_item->name())); Scene_polylines_item* min_curv = new Scene_polylines_item; min_curv->setColor(Qt::green); min_curv->setName(tr("%1 (min curvatures)").arg(poly_item->name())); Polyhedron::Vertex_iterator v; for(v = pMesh->vertices_begin(); v != pMesh->vertices_end(); v++) { std::vector<Point> points; // pick central point const Point& central_point = v->point(); points.push_back(central_point); // compute min edge len around central vertex // to scale the ribbons used to display the directions typedef Kernel::FT FT; FT min_edge_len = std::numeric_limits<FT>::infinity(); Polyhedron::Halfedge_around_vertex_circulator he = v->vertex_begin(); Polyhedron::Halfedge_around_vertex_circulator end = he; CGAL_For_all(he,end) { const Point& p = he->opposite()->vertex()->point(); points.push_back(p); FT edge_len = std::sqrt(CGAL::squared_distance(central_point,p)); min_edge_len = edge_len < min_edge_len ? edge_len : min_edge_len; // avoids #undef min } if(points.size() > 5) { // estimate curvature by fitting Fitting monge_fit; const int dim_monge = 2; const int dim_fitting = 2; Monge_form monge_form = monge_fit(points.begin(),points.end(),dim_fitting,dim_monge); // make monge form comply with vertex normal (to get correct // orientation) typedef Kernel::Vector_3 Vector; Vector n = CGAL::Polygon_mesh_processing::compute_vertex_normal(v, *pMesh); monge_form.comply_wrt_given_normal(n); Vector umin = min_edge_len * monge_form.minimal_principal_direction(); Vector umax = min_edge_len * monge_form.maximal_principal_direction(); Scene_polylines_item::Polyline max_segment(2), min_segment(2); const double du = 0.2; max_segment[0] = central_point + du * umax; max_segment[1] = central_point - du * umax; min_segment[0] = central_point + du * umin; min_segment[1] = central_point - du * umin; max_curv->polylines.push_back(max_segment); min_curv->polylines.push_back(min_segment); } } scene->addItem(max_curv); scene->addItem(min_curv); max_curv->changed(); min_curv->changed(); // default cursor QApplication::restoreOverrideCursor(); }