diff --git a/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/internal/Smoothing/implicit_shape_smoothing_impl.h b/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/internal/Smoothing/implicit_shape_smoothing_impl.h new file mode 100644 index 00000000000..b9de85baa9a --- /dev/null +++ b/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/internal/Smoothing/implicit_shape_smoothing_impl.h @@ -0,0 +1,627 @@ +#ifndef SMOOTHING_H +#define SMOOTHING_H + +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#include +#include +#include + +namespace CGAL { + +namespace Polygon_mesh_processing { + +namespace internal { +//Cotangent_value_Meyer> + +std::ostream& nl(std::ostream& out) +{ + return out << "\n"; +} + +template> +struct Edge_cotangent_weight : CotangentValue +{ + Edge_cotangent_weight(PolygonMesh& pmesh_, VertexPointMap vpmap_) + : CotangentValue(pmesh_, vpmap_) + {} + + PolygonMesh& pmesh() + { + return CotangentValue::pmesh(); + } + + typedef typename boost::graph_traits::halfedge_descriptor halfedge_descriptor; + typedef typename boost::graph_traits::vertex_descriptor vertex_descriptor; + + double operator()(halfedge_descriptor he) + { + if(is_border_edge(he, pmesh())) + { + halfedge_descriptor h1 = next(he, pmesh()); + vertex_descriptor vs = source(he, pmesh()); + vertex_descriptor vt = target(he, pmesh()); + vertex_descriptor v1 = target(h1, pmesh()); + + return (CotangentValue::operator ()(vs, v1, vt)); + } + else + { + halfedge_descriptor h1 = next(he, pmesh()); + halfedge_descriptor h2 = prev(opposite(he, pmesh()), pmesh()); + vertex_descriptor vs = source(he, pmesh()); + vertex_descriptor vt = target(he, pmesh()); + vertex_descriptor v1 = target(h1, pmesh()); + vertex_descriptor v2 = source(h2, pmesh()); + + return ( CotangentValue::operator()(vs, v1, vt) + CotangentValue::operator()(vs, v2, vt) ) / 2.0; + } + } +}; + + + + + + +template +struct Incident_area +{ + + Incident_area(PolygonMesh& mesh) : pmesh(mesh){} + + typedef typename boost::graph_traits::halfedge_descriptor halfedge_descriptor; + typedef typename boost::graph_traits::face_descriptor face_descriptor; + + double operator()(halfedge_descriptor he) + { + + halfedge_descriptor hopp = opposite(he, pmesh); + face_descriptor f1 = face(he, pmesh); + face_descriptor f2 = face(hopp, pmesh); + + double A1 = f1 == boost::graph_traits::null_face() ? 0 : face_area(f1, pmesh); + double A2 = f2 == boost::graph_traits::null_face() ? 0 : face_area(f2, pmesh); + + // todo: check degenerecies + //CGAL_assertion(A1>0 && A2>0); + + return A1 + A2; + } + + PolygonMesh& pmesh; + +}; + + + + + +template +class Shape_smoother{ + +// types +private: + + typedef typename GetGeomTraits::type GeomTraits; + typedef typename GeomTraits::FT NT; + typedef typename GeomTraits::Point_3 Point; + typedef typename GeomTraits::Triangle_3 Triangle; + + typedef typename boost::graph_traits::vertex_descriptor vertex_descriptor; + typedef typename boost::graph_traits::halfedge_descriptor halfedge_descriptor; + typedef typename boost::graph_traits::face_descriptor face_descriptor; + + // vertex index map + typedef typename boost::property_map::type IndexMap; + + //CGAL Sparse solver + typedef typename CGAL::Eigen_sparse_matrix::EigenType CEigenMatrix; + + typedef CGAL::Eigen_solver_traits< Eigen::SimplicialLDLT< CEigenMatrix > > Solver_traits; + //typedef CGAL::Eigen_solver_traits<> Solver_traits; //BicGSTAB + + typedef typename Solver_traits::Matrix Matrix; + typedef typename Solver_traits::Vector Vector; + + // Eigen sparse matrix & vector + typedef typename Eigen::SparseMatrix Eigen_matrix; + typedef typename Eigen::SparseVector Eigen_vector; + + + +// data +private: + + IndexMap vimap_ = get(boost::vertex_index, mesh_); + + // geometry data + PolygonMesh& mesh_; + VertexPointMap& vpmap_; + Edge_cotangent_weight weight_calculator_; + Incident_area inc_areas_calculator_; + + std::size_t nb_vert_; + + // linear solver + Solver_traits solver_; + + // constrained vertices + std::unordered_set constrained_vertices_; + + +public: + + Shape_smoother(PolygonMesh& mesh, VertexPointMap& vpmap) : mesh_(mesh), vpmap_(vpmap), + weight_calculator_(mesh, vpmap), + inc_areas_calculator_(mesh), + nb_vert_(static_cast(vertices(mesh).size())) + { } + + + Eigen_matrix calc_stiff_matrix() + { + Eigen_matrix L = stiff_matrix(); + return L; + } + + + void solve_system(Eigen::SparseMatrix& L) + { + + //gather_constrained_vertices(); + + Matrix A(nb_vert_, nb_vert_); + Vector Bx(nb_vert_); + Vector By(nb_vert_); + Vector Bz(nb_vert_); + Vector Xx(nb_vert_); + Vector Xy(nb_vert_); + Vector Xz(nb_vert_); + + + compute_coeff_matrix(A, L); + + //apply_constraints(A); + + + //extract_matrix(A); + + + compute_rhs(Bx, By, Bz); + + //extract_vectors(Bx,By,Bz); + + + NT dx, dy, dz; + if(!solver_.linear_solver(A, Bx, Xx, dx) || + !solver_.linear_solver(A, By, Xy, dy) || + !solver_.linear_solver(A, Bz, Xz, dz) ) + { + std::cerr<<"Could not solve linear system!"<::iterator it; + for(it = constrained_vertices_.begin(); it != constrained_vertices_.end(); ++it) + { + int i = get(vimap_, *it); + A.set_coef(i, i, 1.0); + + // also set all cols of the same row = 0 - not needed + //for(std::size_t j = 0; j> barycenters; + + for(face_descriptor f : faces(mesh_)) + { + Point tr_centroid = CGAL::centroid(triangle(f)); + barycenters.push_back(std::make_pair(tr_centroid, face_area(f, mesh_))); + } + + Point centroid = CGAL::barycenter(barycenters.begin(), barycenters.end()); + std::cout << "centroid= " << centroid << std::endl; + + for(std::size_t i=0; i < Xx.rows(); ++i) + { + Xx[i] -= centroid.x(); + Xy[i] -= centroid.y(); + Xz[i] -= centroid.z(); + } + + } + + void normalize_area(Vector& Xx, Vector& Xy, Vector& Xz) + { + + NT surface_area = area(faces(mesh_), mesh_); + + for(std::size_t i=0; i < Xx.rows(); ++i) + { + Xx[i] /= CGAL::sqrt(surface_area); + Xy[i] /= CGAL::sqrt(surface_area); + Xz[i] /= CGAL::sqrt(surface_area); + } + + + /* + Xx /= surface_area; + Xy /= surface_area; + Xz /= surface_area; + */ + + } + + + void update_map(Vector& Xx, Vector& Xy, Vector& Xz) + { + for (vertex_descriptor v : vertices(mesh_)) + { + int index = get(vimap_, v); + NT x_new = Xx[index]; + NT y_new = Xy[index]; + NT z_new = Xz[index]; + put(vpmap_, v, Point(x_new, y_new, z_new)); + } + } + + + + +}; + + +} + + + + + + + + + + + + + + + +} // PMP +} // CGAL + + +#endif // SMOOTHING_H diff --git a/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/shape_smoothing.h b/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/shape_smoothing.h new file mode 100644 index 00000000000..2be3c5ddd65 --- /dev/null +++ b/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/shape_smoothing.h @@ -0,0 +1,70 @@ +#include +#include + +#include + +namespace CGAL { + + +namespace Polygon_mesh_processing { + + + +template +void smooth_shape(PolygonMesh& mesh, int nb_iter) +{ + + // VPmap type + typedef typename boost::property_map::type VertexPointMap; + VertexPointMap vpmap = get(CGAL::vertex_point, mesh); + + internal::Shape_smoother smoother(mesh, vpmap); + + Eigen::SparseMatrix stiffness_matrix; + stiffness_matrix = smoother.calc_stiff_matrix(); + + for(unsigned int t=0; t +void solve_mcf_system(PolygonMesh& mesh, int nb_iter, Eigen::SparseMatrix& stiffness_matrix) +{ + + // VPmap type + typedef typename boost::property_map::type VertexPointMap; + VertexPointMap vpmap = get(CGAL::vertex_point, mesh); + + internal::Shape_smoother smoother(mesh, vpmap); + + for(unsigned int t=0; t +void setup_mcf_system(PolygonMesh& mesh, int nb_iter, Eigen::SparseMatrix& stiffness_matrix) +{ + + // VPmap type + typedef typename boost::property_map::type VertexPointMap; + VertexPointMap vpmap = get(CGAL::vertex_point, mesh); + + internal::Shape_smoother smoother(mesh, vpmap); + + stiffness_matrix = smoother.calc_stiff_matrix(); + +} + + + + +} //Polygon_mesh_processing + +} //CGAL