// Copyright (c) 2018 Liangliang Nan. All rights reserved. // // This file is part of CGAL (www.cgal.org) // // $URL: https://github.com/CGAL/cgal/blob/v5.1/Polygonal_surface_reconstruction/include/CGAL/internal/alpha_shape_mesh.h $ // $Id: alpha_shape_mesh.h 0779373 2020-03-26T13:31:46+01:00 Sébastien Loriot // SPDX-License-Identifier: LGPL-3.0-or-later OR LicenseRef-Commercial // // Author(s) : Liangliang Nan #ifndef CGAL_POLYGONAL_SURFACE_RECONSTRUCTION_ALPHA_SHAPE_MESH_H #define CGAL_POLYGONAL_SURFACE_RECONSTRUCTION_ALPHA_SHAPE_MESH_H #include #include #include #include #include // warn the user if he/she is using an unsupported version of CGAL #if CGAL_VERSION_NR < 1041100000 #error CGAL 4.11 or above is required (due to the breaking change in CGAL 4.11). Please update your code. #endif /*! \file alpha_shape_mesh.h */ namespace CGAL { namespace internal { /// \cond SKIP_IN_MANUA template class Alpha_shape; /// \endcond /// \cond SKIP_IN_MANUA /* A vertex class with an additional member representing its index */ template < class Gt, class VB = CGAL::Triangulation_hierarchy_vertex_base_2 > class AS_vertex_base : public VB { public: typedef VB Base; typedef typename VB::Vertex_handle Vertex_handle; typedef typename VB::Face_handle Face_handle; typedef typename VB::Point Point; template < typename TDS2 > struct Rebind_TDS { typedef typename VB::template Rebind_TDS::Other VB2; typedef AS_vertex_base Other; }; public: AS_vertex_base() : Base(), index_(-1) {} AS_vertex_base(const Point & p) : Base(p), index_(-1) {} AS_vertex_base(const Point & p, Face_handle f) : Base(f, p), index_(-1) {} AS_vertex_base(Face_handle f) : Base(f), index_(-1) {} void set_index(int idx) { index_ = idx; } int index() const { return index_; } private: int index_; }; template class Alpha_shape : public Alpha_shape_2 { public: typedef Alpha_shape_2 Parent_class; typedef typename Ht::Point_2 Point2; typedef typename Parent_class::Vertex_handle Vertex_handle; public: // constructs alpha shapes from the input points template Alpha_shape(InputIterator first, InputIterator beyond); }; /// \endcond /** * An Alpha Shape Mesh approximates the point covered region by a mesh representation. */ template class Alpha_shape_mesh { typedef typename Kernel::FT FT; typedef typename Kernel::Point_2 Point2; typedef typename Kernel::Point_3 Point3; typedef typename Kernel::Plane_3 Plane3; typedef CGAL::Surface_mesh Mesh3; typedef typename Mesh3::Vertex_index Vertex_descriptor; typedef CGAL::Alpha_shape_vertex_base_2 Avb; typedef AS_vertex_base Av; typedef CGAL::Triangulation_face_base_2 Tf; typedef CGAL::Alpha_shape_face_base_2 Af; typedef CGAL::Triangulation_default_data_structure_2 Tds; typedef CGAL::Delaunay_triangulation_2 Dt; typedef CGAL::Triangulation_hierarchy_2
Ht; public: /// Given a set of 3D points lying on 'plane', constructs alpha shapes from the /// the projection of the points onto 'plane' template Alpha_shape_mesh(InputIterator first, InputIterator beyond, const Plane3& plane); ~Alpha_shape_mesh() { delete alpha_shape_; } /// Extracts the 3D mesh representation of the alpha shapes bool extract_mesh(FT alpha_value, Mesh3& mesh); private: Alpha_shape* alpha_shape_; std::vector original_points_; }; ////////////////////////////////////////////////////////////////////////// // implementation template template Alpha_shape::Alpha_shape(InputIterator first, InputIterator beyond) { InputIterator it = first; for (int id = 0; it != beyond; ++it, ++id) { const Point2& p = *it; Vertex_handle vh = Traits::insert(p); if (vh->index() == -1) vh->set_index(id); else { // p was not inserted (there might be a duplicated point) } } if (Parent_class::dimension() == 2) { // Computes the associated _interval_face_map Parent_class::initialize_interval_face_map(); // Computes the associated _interval_edge_map Parent_class::initialize_interval_edge_map(); // Computes the associated _interval_vertex_map Parent_class::initialize_interval_vertex_map(); // Merges the two maps Parent_class::initialize_alpha_spectrum(); } } template template Alpha_shape_mesh::Alpha_shape_mesh(InputIterator first, InputIterator beyond, const Plane3& plane) { original_points_.clear(); std::vector pts; for (InputIterator it = first; it != beyond; ++it) { const Point3& p = *it; const Point2& q = plane.to_2d(p); pts.push_back(q); original_points_.push_back(&p); } alpha_shape_ = new Alpha_shape(pts.begin(), pts.end()); } template bool Alpha_shape_mesh::extract_mesh(FT alpha_value, Mesh3& mesh) { alpha_shape_->set_alpha(alpha_value); typedef std::vector Triangle; std::vector faces; typedef Alpha_shape Alpha_shape; typename Alpha_shape::Finite_faces_iterator fit = alpha_shape_->finite_faces_begin(); for (; fit != alpha_shape_->finite_faces_end(); ++fit) { if (alpha_shape_->classify(fit) == Alpha_shape::INTERIOR) { Triangle tri; for (int i = 0; i < 3; ++i) { typename Alpha_shape::Vertex_handle vh = fit->vertex(i); int idx = vh->index(); tri.push_back(idx); } faces.push_back(tri); } } if (faces.empty()) return false; mesh.clear(); std::vector descriptors(original_points_.size()); for (std::size_t i = 0; i < original_points_.size(); ++i) { const Point3* p = original_points_[i]; descriptors[i] = mesh.add_vertex(*p); } for (std::size_t i = 0; i < faces.size(); ++i) { std::vector face; const Triangle& tri = faces[i]; for (std::size_t j = 0; j < tri.size(); ++j) { std::size_t idx = tri[j]; face.push_back(descriptors[idx]); } mesh.add_face(face);; } return true; } } //namespace internal } //namespace CGAL #endif // CGAL_POLYGONAL_SURFACE_RECONSTRUCTION_ALPHA_SHAPE_MESH_H