void Various_Processing_Component::Rotation (PolyhedronPtr pMesh, double xAxis, double yAxis, double zAxis, double angle) { // normalize the translation vector double normAxis = sqrt(xAxis*xAxis + yAxis*yAxis + zAxis*zAxis); xAxis = xAxis / normAxis; yAxis = yAxis / normAxis; zAxis = zAxis / normAxis; // construction of the rotation matrix double c = cos(angle/180.0*PI); double s = sin(angle/180.0*PI); double m00 = xAxis*xAxis + (1.0-xAxis*xAxis)*c; double m01 = xAxis*yAxis*(1.0-c) - zAxis*s; double m02 = xAxis*zAxis*(1.0-c) + yAxis*s; double m10 = xAxis*yAxis*(1.0-c) + zAxis*s; double m11 = yAxis*yAxis + (1.0-yAxis*yAxis)*c; double m12 = yAxis*zAxis*(1.0-c) - xAxis*s; double m20 = xAxis*zAxis*(1.0-c) - yAxis*s; double m21 = yAxis*zAxis*(1.0-c) + xAxis*s; double m22 = zAxis*zAxis + (1.0-zAxis*zAxis)*c; // realize rotation by applying general affine transformation through matrix multiplication Affine_transformation rotation(m00, m01, m02, m10, m11, m12, m20, m21, m22); std::transform(pMesh->points_begin(), pMesh->points_end(), pMesh->points_begin(), rotation); pMesh->compute_normals(); }
void Various_Processing_Component::UniformScaling (PolyhedronPtr pMesh, double scalingFactor) { Affine_transformation uniformScaling(CGAL::SCALING, scalingFactor); std::transform(pMesh->points_begin(), pMesh->points_end(), pMesh->points_begin(), uniformScaling); pMesh->compute_normals(); }
void Various_Processing_Component::LaplacianSmoothing (PolyhedronPtr pMesh, double deformFactor, int iteraNum, bool preserveBoundaries) { Vertex_iterator pVertex; int numVertex = pMesh->size_of_vertices(); Vector * newPositions = new Vector[numVertex]; for (int i=0; i<iteraNum; i++) { int n = 0; for (pVertex = pMesh->vertices_begin(); pVertex != pMesh->vertices_end(); pVertex++) { Vector currentVector = pVertex->point() - CGAL::ORIGIN; // do not smooth the boundary vertices if demanded by user bool is_border_vertex = false; bool stopFlag = false; Halfedge_around_vertex_circulator hav = (*pVertex).vertex_begin(); do { if (hav->is_border()==true) { is_border_vertex = true; stopFlag = true; } hav++; } while ((hav!=(*pVertex).vertex_begin())&&(stopFlag==false)); if ((preserveBoundaries==true)&&(is_border_vertex==true)) { newPositions[n] = currentVector; n++; continue; } std::size_t degree = (*pVertex).vertex_degree(); double alpha = 1.0/degree; Vector vectemp = Point3d(0,0,0) - CGAL::ORIGIN; Halfedge_around_vertex_circulator h = (*pVertex).vertex_begin(); do { vectemp = vectemp+(h->opposite()->vertex()->point()-CGAL::ORIGIN-currentVector)*alpha; ++h; } while (h != (*pVertex).vertex_begin()); newPositions[n] = currentVector + deformFactor*vectemp; n++; } n = 0; for (pVertex = pMesh->vertices_begin(); pVertex != pMesh->vertices_end(); pVertex++) { pVertex->point() = Point3d(0,0,0) + newPositions[n]; n++; } } delete [] newPositions; newPositions = 0; pMesh->compute_normals(); }
bool Various_Tools_Component::subdivide_catmull(PolyhedronPtr pMesh) { Polyhedron_subdivision<Polyhedron>::CatmullClark_subdivision(*pMesh,1); pMesh->compute_normals(); pMesh->compute_type(); return true; }
bool Various_Tools_Component::subdivide_loop(PolyhedronPtr pMesh) { Polyhedron_subdivision<Polyhedron>::Loop_subdivision(*pMesh,1); pMesh->compute_normals(); pMesh->compute_type(); return true; }
void Various_Processing_Component::Translation (PolyhedronPtr pMesh, double xTranslation, double yTranslation, double zTranslation) { Vector translationVector(xTranslation,yTranslation, zTranslation); Affine_transformation translation(CGAL::TRANSLATION, translationVector); std::transform(pMesh->points_begin(), pMesh->points_end(), pMesh->points_begin(), translation); pMesh->compute_normals(); }
bool Various_Tools_Component::subdivide_sqrt3Twice(PolyhedronPtr pMesh) { CSubdivider_sqrt3<Polyhedron,Enriched_kernel> subdivider; subdivider.subdivide(*pMesh,2); // two iterations pMesh->compute_normals(); pMesh->compute_type(); return true; }
void Various_Processing_Component::NoiseAdditionUniform (PolyhedronPtr pMesh, double noiseIntensity, bool preserveBoundaries) { // mesh centre calculation based on discrete "moment". //TODO: maybe in the future it will be based on volume moment. int numVertex = pMesh->size_of_vertices();; Vector centroid = Point3d(0,0,0) - CGAL::ORIGIN; double distancetoCentroid = 0.0; Vertex_iterator pVertex; for (pVertex = pMesh->vertices_begin(); pVertex != pMesh->vertices_end(); pVertex++) { Vector vectemp = pVertex->point() - CGAL::ORIGIN; centroid = centroid + vectemp; } centroid = centroid/numVertex; // calculate the average distance from vertices to mesh centre for (pVertex = pMesh->vertices_begin(); pVertex!= pMesh->vertices_end(); pVertex++) { Vector vectemp = pVertex->point() - CGAL::ORIGIN; distancetoCentroid = distancetoCentroid + (double)std::sqrt((vectemp - centroid) * (vectemp - centroid)); } distancetoCentroid = distancetoCentroid/numVertex; // add random uniform-distributed (between [-noiseLevel, +noiseLevel]) srand((unsigned)time(NULL)); double noisex, noisey, noisez; double noiseLevel = distancetoCentroid * noiseIntensity; for (pVertex = pMesh->vertices_begin(); pVertex!= pMesh->vertices_end(); pVertex++) { // keep boundaries untouched if demanded by user bool is_border_vertex = false; bool stopFlag = false; Halfedge_around_vertex_circulator hav = (*pVertex).vertex_begin(); do { if (hav->is_border()==true) { is_border_vertex = true; stopFlag = true; } hav++; } while ((hav!=(*pVertex).vertex_begin())&&(stopFlag==false)); if ((preserveBoundaries==true)&&(is_border_vertex==true)) continue; noisex = noiseLevel * (1.0*rand()/RAND_MAX-0.5)*2; noisey = noiseLevel * (1.0*rand()/RAND_MAX-0.5)*2; noisez = noiseLevel * (1.0*rand()/RAND_MAX-0.5)*2; Vector temp = Point3d(noisex, noisey, noisez) - CGAL::ORIGIN; pVertex->point() = pVertex->point() + temp; } // for correct rendering, we need to update the mesh normals pMesh->compute_normals(); }
void Implicit_Surface_Meshing_Component::BuildPolyhedron(const C2t3& c2t3,PolyhedronPtr pMesh) { Polyhedron_C2t3_Importer <Polyhedron::HalfedgeDS> builder (c2t3); pMesh->delegate(builder);//build the polyhedron //compute these properties in order to display the polyhedron in Mepp pMesh->compute_bounding_box(); pMesh->compute_normals(); pMesh->compute_type(); (void)pMesh->calc_nb_components(); (void)pMesh->calc_nb_boundaries(); }
void Various_Processing_Component::Subdivision (PolyhedronPtr pMesh, Subdivision_type subdivisionType, int depth) { if (subdivisionType==CATMULLCLARK) SubdivisionCatmullClark(pMesh, depth); else if (subdivisionType==LOOP) SubdivisionLoop(pMesh, depth); else if (subdivisionType==DOOSABIN) SubdivisionDooSabin(pMesh, depth); else if (subdivisionType==SQRT3) SubdivisionSqrt3(pMesh, depth); else if (subdivisionType==MIDPOINT) SubdivisionMidpoint(pMesh, depth); // after connectivity modification of the mesh, we need to update the related internal properties such as "m_pure_quad" or "m_pure_triangle" // other updates can be necessary depending on application pMesh->compute_type(); pMesh->compute_normals(); }
// TODO: fixing after quantization the potentially introduced degeneracies, such as removing the null surface facet void Various_Processing_Component::CoordinateQuantization (PolyhedronPtr pMesh, int bitDepth) { Vertex_iterator pVertex; double quantizationLevel = std::pow(2.0,bitDepth); pVertex = pMesh->vertices_begin(); Point3d point = pVertex->point(); double xmax = double(point.x()); double xmin = xmax; double ymax = double(point.y()); double ymin = ymax; double zmax = double(point.z()); double zmin = zmax; pVertex++; for (; pVertex != pMesh->vertices_end(); pVertex++) { point = pVertex->point(); double x = double(point.x()); double y = double(point.y()); double z = double(point.z()); if (x>xmax) xmax = x; if (x<xmin) xmin = x; if (y>ymax) ymax = y; if (y<ymin) ymin = y; if (z>zmax) zmax = z; if (z<zmin) zmin = z; } double xstep = (xmax-xmin)/quantizationLevel; double ystep = (ymax-ymin)/quantizationLevel; double zstep = (zmax-zmin)/quantizationLevel; for (pVertex = pMesh->vertices_begin(); pVertex != pMesh->vertices_end();pVertex++) { point = pVertex->point(); double x = double(point.x()); double y = double(point.y()); double z = double(point.z()); double xquantified, yquantified, zquantified; double xint = 1.0*std::floor((x-xmin)/xstep)*xstep + xmin; double xfrac = x - xint; if (xfrac<=(0.5*xstep)) xquantified = xint; else xquantified = xint + xstep; double yint = 1.0*std::floor((y-ymin)/ystep)*ystep + ymin; double yfrac = y - yint; if (yfrac<=(0.5*ystep)) yquantified = yint; else yquantified = yint +ystep; double zint = 1.0*std::floor((z-zmin)/zstep)*zstep + zmin; double zfrac = z - zint; if (zfrac<=(0.5*zstep)) zquantified = zint; else zquantified = zint + zstep; pVertex->point() = Point3d(xquantified,yquantified,zquantified); } pMesh->compute_normals(); }
// this time, we add Gaussian-distributed additive noise to the mesh vertex coordinates // the standard deviation of the Gaussian distribution is "noiseLevel = distancetoCentroid * noiseIntensity" void Various_Processing_Component::NoiseAdditionGaussian (PolyhedronPtr pMesh, double noiseIntensity, bool preserveBoundaries) { int numVertex = pMesh->size_of_vertices();; Vector centroid = Point3d(0,0,0) - CGAL::ORIGIN; double distancetoCentroid = 0.0; Vertex_iterator pVertex; for (pVertex = pMesh->vertices_begin(); pVertex != pMesh->vertices_end(); pVertex++) { Vector vectemp = pVertex->point() - CGAL::ORIGIN; centroid = centroid + vectemp; } centroid = centroid/numVertex; for (pVertex = pMesh->vertices_begin(); pVertex!= pMesh->vertices_end(); pVertex++) { Vector vectemp = pVertex->point() - CGAL::ORIGIN; distancetoCentroid = distancetoCentroid + (double)std::sqrt((vectemp - centroid) * (vectemp - centroid)); } distancetoCentroid = distancetoCentroid/numVertex; srand((unsigned)time(NULL)); double noisex, noisey, noisez; double * gaussNumbers = new double[3]; double noiseLevel = distancetoCentroid * noiseIntensity; for (pVertex = pMesh->vertices_begin(); pVertex!= pMesh->vertices_end(); pVertex++) { bool is_border_vertex = false; bool stopFlag = false; Halfedge_around_vertex_circulator hav = (*pVertex).vertex_begin(); do { if (hav->is_border()==true) { is_border_vertex = true; stopFlag = true; } hav++; } while ((hav!=(*pVertex).vertex_begin())&&(stopFlag==false)); if ((preserveBoundaries==true)&&(is_border_vertex==true)) continue; // pseudo-random Gaussian-distributed numbers generation from uniformly-distributed pseudo-random numbers double x, y, r2; for (int i=0; i<3; i++) { do { x = -1.0 + 2.0 * 1.0*rand()/RAND_MAX; y = -1.0 + 2.0 * 1.0*rand()/RAND_MAX; r2 = x * x + y * y; } while ((r2>1.0)||(r2==0.0)); gaussNumbers[i] = y * sqrt(-2.0 * log(r2) / r2); } noisex = noiseLevel * gaussNumbers[0]; noisey = noiseLevel * gaussNumbers[1]; noisez = noiseLevel * gaussNumbers[2]; Vector temp = Point3d(noisex, noisey, noisez) - CGAL::ORIGIN; pVertex->point() = pVertex->point() + temp; } pMesh->compute_normals(); delete [] gaussNumbers; gaussNumbers = 0; }