// Add semantics to Interior room polyhedra void set_semantic_InteriorLoD4(Polyhedron& polyhe) { std::transform( polyhe.facets_begin(), polyhe.facets_end(),polyhe.planes_begin(),Plane_Newel_equation()); for (Polyhedron::Facet_iterator fIt = polyhe.facets_begin(); fIt != polyhe.facets_end(); ++fIt) { // Iterate over faces Kernel::FT z = fIt->plane().orthogonal_vector().z(); if (z <= -HORIZONTAL_ANGLE_RANGE) fIt->semanticBLA = "FloorSurface"; else if (z >= HORIZONTAL_ANGLE_RANGE) fIt->semanticBLA = "CeilingSurface"; else fIt->semanticBLA = "InteriorWallSurface"; } }
int main() { std::list<Weighted_point> l; FT shrinkfactor = 0.5; l.push_front(Weighted_point(Bare_point(0, 0, 0), 1)); l.push_front(Weighted_point(Bare_point(0, 1, 0), 2)); l.push_front(Weighted_point(Bare_point(0, 0, 2), 1)); Skin_surface_3 skin_surface(l.begin(), l.end(), shrinkfactor); Polyhedron p; CGAL::mesh_skin_surface_3(skin_surface, p); for (Polyhedron::Facet_iterator fit = p.facets_begin(); fit != p.facets_end(); ++fit) { // Retrieve the generating simplex from the regular triangulation const Skin_surface_3::Simplex &s = fit->containing_simplex(); // Get the weighted points from the simplex Skin_surface_3::Weighted_point wp[4]; switch (s.dimension()) { case 0: { Skin_surface_3::Vertex_handle vh = s; wp[0] = vh->point(); break; } case 1: { Skin_surface_3::Edge e = s; wp[0] = e.first->vertex(e.second)->point(); wp[1] = e.first->vertex(e.third)->point(); break; } case 2: { Skin_surface_3::Facet f = s; wp[0] = f.first->vertex((f.second + 1) & 3)->point(); wp[1] = f.first->vertex((f.second + 2) & 3)->point(); wp[2] = f.first->vertex((f.second + 3) & 3)->point(); break; } case 3: { Skin_surface_3::Cell_handle ch = s; wp[0] = ch->vertex(0)->point(); wp[1] = ch->vertex(1)->point(); wp[2] = ch->vertex(2)->point(); wp[3] = ch->vertex(3)->point(); break; } } } return 0; }
// Remove small triangles with different semantics void remove_singularSemantics(Polyhedron& exteriorPolyhe) { double SMALL_TRIANGLE_LIMIT = 0.1; Polyhedron::Facet_iterator exfIt; // Iterate over exterior faces while (true) { bool newSemFound = false; for (exfIt = exteriorPolyhe.facets_begin(); exfIt != exteriorPolyhe.facets_end(); ++exfIt) { if (exfIt->area < SMALL_TRIANGLE_LIMIT) { std::map<std::string,double> semCountList; std::map<std::string,double>::iterator semCount; Polyhedron::Facet::Halfedge_around_facet_circulator itHDS = exfIt->facet_begin(); double maxArea = 0; std::string newSem; do { if (is_coplanar(itHDS,false)) { std::string otherSem = itHDS->opposite()->facet()->semanticBLA; // Compute sum of area if (is_coplanar(itHDS->opposite()->next(),true) || is_coplanar(itHDS->opposite()->prev(),true)) { semCount = semCountList.find(otherSem); if (semCount == semCountList.end()) semCountList[otherSem] = 1; // Might not be needed else ++(semCountList[otherSem]); } } } while (++itHDS != exfIt->facet_begin()); for (semCount = semCountList.begin();semCount!=semCountList.end();++semCount) { if (semCount->second > maxArea) { maxArea = semCount->second; newSem = semCount->first; } else if (semCount->second == maxArea && ((exfIt->semanticBLA=="Anything"&&semCount->first!="Anything")||semCount->first==exfIt->semanticBLA)) newSem = semCount->first; } if (maxArea > 0 && newSem!=exfIt->semanticBLA) { exfIt->semanticBLA = newSem; newSemFound = true; break; // Dafuq? is this correct? } } } if (!newSemFound) break; // Really? } }
double lloyd_step (std::vector<Point> &points) { std::vector<Plane> planes; for (size_t i = 0; i < points.size(); ++i) planes.push_back(tangent_plane(points[i])); Polyhedron P; CGAL::internal::halfspaces_intersection(planes.begin(), planes.end(), P, K()); size_t N = points.size(); points.clear(); double totarea = 0.0; double vararea = 0.0; for (Polyhedron::Facet_iterator it = P.facets_begin(); it != P.facets_end(); ++it) { Polyhedron::Halfedge_around_facet_circulator h0 = it->facet_begin(), hf = h0--, hs = hf; hs ++; double farea = 0.0; Vector fcentroid (CGAL::NULL_VECTOR); while(1) { const Point &a = h0->vertex()->point(), &b = hf->vertex()->point(), &c = hs->vertex()->point(); Vector v = CGAL::cross_product(b -a, c - a); double tarea = .5 * sqrt(v.squared_length()); farea += tarea; fcentroid = fcentroid + (tarea/3.0) * ((a - CGAL::ORIGIN) + (b - CGAL::ORIGIN) + (c - CGAL::ORIGIN)); if (hs == h0) break; ++hs; ++hf; } totarea += farea; vararea += pow(4.0 * M_PI / N - farea, 2.0); fcentroid = fcentroid/farea; points.push_back(project_back(CGAL::ORIGIN + fcentroid)); } std::cerr << "area = " << totarea << ", " << "vararea = " << vararea << "\n"; return vararea/totarea; }
int main(int argc, char** argv) { typedef boost::property_map< Polyhedron, CGAL::face_index_t >::const_type Face_index_map; std::ifstream in((argc>1)?argv[1]:"cube.off"); Polyhedron P; in >> P ; // initialize facet indices std::size_t i = 0; for(Polyhedron::Facet_iterator it = P.facets_begin(); it != P.facets_end(); ++it, ++i) { it->id() = i; } // Ad hoc property_map to store normals. Face_index_map is used to // map face_descriptors to a contiguous range of indices. See // http://www.boost.org/libs/property_map/doc/vector_property_map.html // for details. boost::vector_property_map<Vector, Face_index_map> normals(get(CGAL::face_index, P)); calculate_face_normals( P // Graph , get(CGAL::vertex_point, P) // map from vertex_descriptor to point , normals // map from face_descriptor to Vector_3 ); std::cout << "Normals" << std::endl; for(Polyhedron::Facet_iterator it = P.facets_begin(); it != P.facets_end(); ++it) { // Facet_iterator is a face_descriptor, so we can use it as the // key here std::cout << normals[it] << std::endl; } return 0; }
// 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; }
void set_semantic_AABB_C2V(Polyhedron& exteriorPolyhe,PolVector& polyVec) { if (exteriorPolyhe.is_pure_triangle()) { std::transform( exteriorPolyhe.facets_begin(), exteriorPolyhe.facets_end(),exteriorPolyhe.planes_begin(),Plane_equation()); std::vector<std::string> semList; std::vector<std::shared_ptr<AAbbTree>> treeList; // Build Trees. One for each semantic for(PolVector::iterator pvIt = polyVec.begin();pvIt!=polyVec.end();++pvIt) {// Get AABB trees of all semantics if (pvIt->is_pure_triangle()) { std::string semP = pvIt->facets_begin()->semanticBLA; std::vector<std::string>::iterator strIt = std::find(semList.begin(), semList.end(),semP); if (strIt==semList.end()) { // If new sematic semList.push_back(semP); // Add sem std::shared_ptr<AAbbTree> tree = std::make_shared<AAbbTree>(pvIt->facets_begin(),pvIt->facets_end()); // Create tree tree->accelerate_distance_queries(); // accelerate treeList.push_back(tree); // Add tree } else // If not new treeList[strIt-semList.begin()]->insert(pvIt->facets_begin(),pvIt->facets_end()); // Append to tree } else std::cerr << "ERROR: Not pure triangle (set_semantic_AABB2C2V)" << std::endl; } // For each facet calculate the least distance to each tree std::string semListStr = boost::algorithm::join((semList), " "); int percCount = 1; Polyhedron::Facet_iterator exfIt; // Iterate over exterior faces for (exfIt = exteriorPolyhe.facets_begin(); exfIt != exteriorPolyhe.facets_end(); ++exfIt,++percCount) { std::cout << "\r"<<semListStr<<". ("<<100*percCount/exteriorPolyhe.size_of_facets()<<"%)"; Vector_3 orthVec = exfIt->plane().orthogonal_vector(); normalizeVector(orthVec); //if (!normalizeVector(ortVec)) continue; std::vector<distSemFace> dsfList(semList.size()); Point_3 centerPoint = comp_facetCentroid(exfIt); // Compute centroid std::vector<Kernel::FT> leastSemDistances; for (int intIt=0;intIt<(int)treeList.size();++intIt) { // Loop over all trees AAbbTree::Point_and_primitive_id pp = treeList[intIt]->closest_point_and_primitive(centerPoint); dsfList[intIt].dist = CGAL::squared_distance(centerPoint,pp.first); // Store distance semantic and facet for each tree dsfList[intIt].sem = semList[intIt]; dsfList[intIt].fh = pp.second; } std::sort(dsfList.begin(),dsfList.end(),by_dist()); exfIt->leastSqDistance = dsfList[0].dist; // least sqrt distance if (exfIt->isMinkFacet = dsfList[0].dist > SEMANTIC_DISTANCE_THRESHOLD) { exfIt->semanticBLA = TO_DIST_SEMANTIC; // Default semantic if too distant continue; } else exfIt->semanticBLA = dsfList[0].sem; // Semantics of closest Vector_3 faceNormal; Kernel::FT faceSqArea; double minAngle = 10; Kernel::FT maxArea= 0; for (std::vector<distSemFace>::iterator slIt = dsfList.begin();slIt != dsfList.end();++slIt)// HANDLE ANYTHING AS LESS IMPORTANT if (slIt->dist < dsfList[0].dist+OVERLAP_DIST_THRESHOLD) { // Check if Equidistant pointVector facetPoints = comp_facetPoints(exfIt); CGAL::normal_vector_newell_3(facetPoints.begin(),facetPoints.end(),faceNormal); // Calculate normal vector, ortVec set to zero in newell double angle = comp_angle(orthVec,faceNormal); if (angle!=-1 && angle < minAngle+OVERLAP_ANGLE_THRESHOLD) { if (minAngle >= angle+OVERLAP_ANGLE_THRESHOLD) exfIt->equidistSems.clear(); if (angle < minAngle) minAngle = angle; faceSqArea = comp_facetSquaredArea(facetPoints); if (faceSqArea>maxArea-OVERLAP_AREA_THRESHOLD) { if (maxArea<=faceSqArea-OVERLAP_AREA_THRESHOLD) exfIt->equidistSems.clear(); if (faceSqArea>maxArea) maxArea = faceSqArea; exfIt->equidistSems.push_back(slIt->sem); // Add equidist semantics } } } } std::cout << "\r"<<semListStr<<". (100%)" << std::endl; }else std::cerr << "ERROR: Not pure triangle (set_semantic_AABB2C2V)" << std::endl; }