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); }
//********************************************************************************** //returns min coordinates Vector3r MinCoord(const shared_ptr<Shape>& cm1,const State& state1){ const Se3r& se3=state1.se3; Polyhedra* A = static_cast<Polyhedra*>(cm1.get()); //move and rotate CGAL structure Polyhedron Matrix3r rot_mat = (se3.orientation).toRotationMatrix(); Vector3r trans_vec = se3.position; Transformation t_rot_trans(rot_mat(0,0),rot_mat(0,1),rot_mat(0,2), trans_vec[0],rot_mat(1,0),rot_mat(1,1),rot_mat(1,2),trans_vec[1],rot_mat(2,0),rot_mat(2,1),rot_mat(2,2),trans_vec[2],1.); Polyhedron PA = A->GetPolyhedron(); std::transform( PA.points_begin(), PA.points_end(), PA.points_begin(), t_rot_trans); Vector3r minccord = trans_vec; for(Polyhedron::Vertex_iterator vi = PA.vertices_begin(); vi != PA.vertices_end(); ++vi){ if (vi->point()[0]<minccord[0]) minccord[0]=vi->point()[0]; if (vi->point()[1]<minccord[1]) minccord[1]=vi->point()[1]; if (vi->point()[2]<minccord[2]) minccord[2]=vi->point()[2]; } return minccord; }
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(); }
// a helper method for running different iterators void running_iterators( Polyhedron& P) { if ( P.size_of_facets() == 0) return; std::size_t nv = P.size_of_vertices(); std::cout << "The number of vertices in the Polyhedron: " << nv << std::endl; std::cout << "The number of facets in the Polyhedron: " << P.size_of_facets() << std::endl; std::cout << "The number of half edges in the Polyhedron: " << P.size_of_halfedges() << std::endl; std::cout << std:: endl; Polyhedron::Vertex_iterator last_v = P.vertices_end(); -- last_v; // the last of the old vertices Polyhedron::Edge_iterator last_e = P.edges_end(); -- last_e; // the last of the old edges Polyhedron::Facet_iterator last_f = P.facets_end(); -- last_f; // the last of the old facets int k = 0; Polyhedron::Facet_iterator f = P.facets_begin(); do { std::cout << "Printing a facet index: " << k++ << std::endl; f->halfedge(); } while ( f++ != last_f); std::cout << std::endl; // ------------------------------------------------- // traverse the vertices // ------------------------------------------------- std::cout << "Printing the vertex indices: " << std::endl; int n=0; for (Polyhedron::Vertex_iterator vi = P.vertices_begin(); vi != P.vertices_end(); ++vi) { Kernel::Point_3 p; p = vi->point(); std::cout << "Vertex index: " << n++ << std::endl; std::cout << "p.x() = " << p.x() << std::endl; std::cout << "p.y() = " << p.y() << std::endl; std::cout << "p.z() = " << p.z() << std::endl; } std::cout << std::endl; // ------------------------------------------------- // traverse the edges // ------------------------------------------------- std::cout << "Iterating over the edges.... " << std::endl; n=0; for (Polyhedron::Edge_iterator ei = P.edges_begin(); ei != P.edges_end(); ++ei) { ei->next(); Kernel::Point_3 p; p = ei->vertex()->point(); std::cout << "For edge index: " << n++ << std::endl; std::cout << "p.x() = " << p.x() << std::endl; std::cout << "p.y() = " << p.y() << std::endl; std::cout << "p.z() = " << p.z() << std::endl; } std::cout << std::endl; // ----------------------------------------------- // Do something else with the edge iterators // ----------------------------------------------- Polyhedron::Edge_iterator e = P.edges_begin(); ++ last_e; // make it the past-the-end position again while ( e != last_e) { Polyhedron::Halfedge_handle h = e; ++e; }; CGAL_postcondition( P.is_valid()); }
void Polyhedra::Initialize(){ if (init) return; bool isRandom = false; //get vertices int N = (int) v.size(); if (N==0) { //generate randomly while ((int) v.size()<4) GenerateRandomGeometry(); N = (int) v.size(); isRandom = true; } //compute convex hull of vertices std::vector<CGALpoint> points; points.resize(v.size()); for(int i=0;i<N;i++) { points[i] = CGALpoint(v[i][0],v[i][1],v[i][2]); } CGAL::convex_hull_3(points.begin(), points.end(), P); //connect triagular facets if possible std::transform(P.facets_begin(), P.facets_end(), P.planes_begin(),Plane_equation()); P = Simplify(P, 1E-9); //modify order of v according to CGAl polyhedron int i = 0; v.clear(); for (Polyhedron::Vertex_iterator vIter = P.vertices_begin(); vIter != P.vertices_end(); ++vIter, i++){ v.push_back(Vector3r(vIter->point().x(),vIter->point().y(),vIter->point().z())); } //list surface triangles for plotting faceTri.clear(); std::transform(P.facets_begin(), P.facets_end(), P.planes_begin(),Plane_equation()); for (Polyhedron::Facet_iterator fIter = P.facets_begin(); fIter != P.facets_end(); fIter++){ Polyhedron::Halfedge_around_facet_circulator hfc0; int n = fIter->facet_degree(); hfc0 = fIter->facet_begin(); int a = std::distance(P.vertices_begin(), hfc0->vertex()); for (int i=2; i<n; i++){ ++hfc0; faceTri.push_back(a); faceTri.push_back(std::distance(P.vertices_begin(), hfc0->vertex())); faceTri.push_back(std::distance(P.vertices_begin(), hfc0->next()->vertex())); } } //compute centroid and volume P_volume_centroid(P, &volume, ¢roid); //check vierd behavior of CGAL in tessalation if(isRandom && volume*1.75<4./3.*3.14*size[0]/2.*size[1]/2.*size[2]/2.) { v.clear(); seed = rand(); Initialize(); } Vector3r translation((-1)*centroid); //set centroid to be [0,0,0] for(int i=0;i<N;i++) { v[i] = v[i]-centroid; } if(isRandom) centroid = Vector3r::Zero(); Vector3r origin(0,0,0); //move and rotate also the CGAL structure Polyhedron Transformation t_trans(1.,0.,0.,translation[0],0.,1.,0.,translation[1],0.,0.,1.,translation[2],1.); std::transform( P.points_begin(), P.points_end(), P.points_begin(), t_trans); //compute inertia Real vtet; Vector3r ctet; Matrix3r Itet1, Itet2; Matrix3r inertia_tensor(Matrix3r::Zero()); for(int i=0; i<(int) faceTri.size(); i+=3){ vtet = std::abs((origin-v[faceTri[i+2]]).dot((v[faceTri[i]]-v[faceTri[i+2]]).cross(v[faceTri[i+1]]-v[faceTri[i+2]]))/6.); ctet = (origin+v[faceTri[i]]+v[faceTri[i+1]]+v[faceTri[i+2]]) / 4.; Itet1 = TetraInertiaTensor(origin-ctet, v[faceTri[i]]-ctet, v[faceTri[i+1]]-ctet, v[faceTri[i+2]]-ctet); ctet = ctet-origin; Itet2<< ctet[1]*ctet[1]+ctet[2]*ctet[2], -ctet[0]*ctet[1], -ctet[0]*ctet[2], -ctet[0]*ctet[1], ctet[0]*ctet[0]+ctet[2]*ctet[2], -ctet[2]*ctet[1], -ctet[0]*ctet[2], -ctet[2]*ctet[1], ctet[1]*ctet[1]+ctet[0]*ctet[0]; inertia_tensor = inertia_tensor + Itet1 + Itet2*vtet; } if(std::abs(inertia_tensor(0,1))+std::abs(inertia_tensor(0,2))+std::abs(inertia_tensor(1,2)) < 1E-13){ // no need to rotate, inertia already diagonal orientation = Quaternionr::Identity(); inertia = Vector3r(inertia_tensor(0,0),inertia_tensor(1,1),inertia_tensor(2,2)); }else{ // calculate eigenvectors of I Vector3r rot; Matrix3r I_rot(Matrix3r::Zero()), I_new(Matrix3r::Zero()); matrixEigenDecomposition(inertia_tensor,I_rot,I_new); // I_rot = eigenvectors of inertia_tensors in columns // I_new = eigenvalues on diagonal // set positove direction of vectors - otherwise reloading does not work Matrix3r sign(Matrix3r::Zero()); Real max_v_signed = I_rot(0,0); Real max_v = std::abs(I_rot(0,0)); if (max_v < std::abs(I_rot(1,0))) {max_v_signed = I_rot(1,0); max_v = std::abs(I_rot(1,0));} if (max_v < std::abs(I_rot(2,0))) {max_v_signed = I_rot(2,0); max_v = std::abs(I_rot(2,0));} sign(0,0) = max_v_signed/max_v; max_v_signed = I_rot(0,1); max_v = std::abs(I_rot(0,1)); if (max_v < std::abs(I_rot(1,1))) {max_v_signed = I_rot(1,1); max_v = std::abs(I_rot(1,1));} if (max_v < std::abs(I_rot(2,1))) {max_v_signed = I_rot(2,1); max_v = std::abs(I_rot(2,1));} sign(1,1) = max_v_signed/max_v; sign(2,2) = 1.; I_rot = I_rot*sign; // force the eigenvectors to be right-hand oriented Vector3r third = (I_rot.col(0)).cross(I_rot.col(1)); I_rot(0,2) = third[0]; I_rot(1,2) = third[1]; I_rot(2,2) = third[2]; inertia = Vector3r(I_new(0,0),I_new(1,1),I_new(2,2)); orientation = Quaternionr(I_rot); //rotate the voronoi cell so that x - is maximal inertia axis and z - is minimal inertia axis //orientation.normalize(); //not needed for(int i=0; i< (int) v.size();i++) { v[i] = orientation.conjugate()*v[i]; } //rotate also the CGAL structure Polyhedron Matrix3r rot_mat = (orientation.conjugate()).toRotationMatrix(); Transformation t_rot(rot_mat(0,0),rot_mat(0,1),rot_mat(0,2),rot_mat(1,0),rot_mat(1,1),rot_mat(1,2),rot_mat(2,0),rot_mat(2,1),rot_mat(2,2),1.); std::transform( P.points_begin(), P.points_end(), P.points_begin(), t_rot); } //initialization done init = 1; }
//********************************************************************************** //generate "packing" of non-overlapping balls vector<Vector3r> fillBoxByBalls_cpp(Vector3r minCoord, Vector3r maxCoord, Vector3r sizemin, Vector3r sizemax, Vector3r ratio, int seed, shared_ptr<Material> mat, int NumPoints){ vector<Vector3r> v; Polyhedra trialP; Polyhedron trial, trial_moved; srand(seed); int it = 0; vector<Polyhedron> polyhedrons; vector<vector<Vector3r> > vv; Vector3r position; bool intersection; int count = 0; Vector3r radii; bool fixed_ratio = 0; if (ratio[0] > 0 && ratio[1] > 0 && ratio[2]>0){ fixed_ratio = 1; sizemax[0] = min(min(sizemax[0]/ratio[0], sizemax[1]/ratio[1]), sizemax[2]/ratio[2]); sizemin[0] = max(max(sizemin[0]/ratio[0], sizemin[1]/ratio[1]), sizemin[2]/ratio[2]); } fixed_ratio = 1; //force spherical //it - number of trials to make packing possibly more/less dense Vector3r random_size; while (it<1000){ it = it+1; if (it == 1){ if (fixed_ratio) { double rrr = (rand()*(sizemax[0]-sizemin[0])/RAND_MAX + sizemin[0])/2.; radii = Vector3r(rrr,rrr,rrr); }else { radii = Vector3r(rand()*(sizemax[0]-sizemin[0])/2.,rand()*(sizemax[1]-sizemin[1])/2.,rand()*(sizemax[2]-sizemin[2])/2.)/RAND_MAX + sizemin/2.; } trialP.v = BallPoints(radii,NumPoints,rand()); trialP.Initialize(); trial = trialP.GetPolyhedron(); Matrix3r rot_mat = (trialP.GetOri()).toRotationMatrix(); Transformation t_rot(rot_mat(0,0),rot_mat(0,1),rot_mat(0,2),rot_mat(1,0),rot_mat(1,1),rot_mat(1,2),rot_mat(2,0),rot_mat(2,1),rot_mat(2,2),1.); std::transform( trial.points_begin(), trial.points_end(), trial.points_begin(), t_rot); } position = Vector3r(rand()*(maxCoord[0]-minCoord[0]),rand()*(maxCoord[1]-minCoord[1]),rand()*(maxCoord[2]-minCoord[2]))/RAND_MAX + minCoord; //move CGAL structure Polyhedron Transformation transl(CGAL::TRANSLATION, ToCGALVector(position)); trial_moved = trial; std::transform( trial_moved.points_begin(), trial_moved.points_end(), trial_moved.points_begin(), transl); //calculate plane equations std::transform( trial_moved.facets_begin(), trial_moved.facets_end(), trial_moved.planes_begin(),Plane_equation()); intersection = false; //call test with boundary for(Polyhedron::Vertex_iterator vi = trial_moved.vertices_begin(); (vi != trial_moved.vertices_end()) && (!intersection); vi++){ intersection = (vi->point().x()<minCoord[0]) || (vi->point().x()>maxCoord[0]) || (vi->point().y()<minCoord[1]) || (vi->point().y()>maxCoord[1]) || (vi->point().z()<minCoord[2]) || (vi->point().z()>maxCoord[2]); } //call test with other polyhedrons for(vector<Polyhedron>::iterator a = polyhedrons.begin(); (a != polyhedrons.end()) && (!intersection); a++){ intersection = do_intersect(*a,trial_moved); if (intersection) break; } if (!intersection){ polyhedrons.push_back(trial_moved); v.clear(); for(Polyhedron::Vertex_iterator vi = trial_moved.vertices_begin(); vi != trial_moved.vertices_end(); vi++){ v.push_back(FromCGALPoint(vi->point())); } vv.push_back(v); it = 0; count ++; } } cout << "generated " << count << " polyhedrons"<< endl; //can't be used - no information about material Scene* scene=Omega::instance().getScene().get(); for(vector<vector<Vector3r> >::iterator p=vv.begin(); p!=vv.end(); ++p){ shared_ptr<Body> BP = NewPolyhedra(*p, mat); BP->shape->color = Vector3r(double(rand())/RAND_MAX,double(rand())/RAND_MAX,double(rand())/RAND_MAX); scene->bodies->insert(BP); } return v; }