14#define CGAL_HEADER_ONLY 1 
   16#ifdef FEAT_COMPILER_MICROSOFT 
   17#pragma warning(disable: 4244) 
   21#define CGAL_NO_DEPRECATION_WARNINGS 1 
   22#include <CGAL/Simple_cartesian.h> 
   23#include <CGAL/AABB_tree.h> 
   24#include <CGAL/AABB_traits.h>  
   25#include <CGAL/Surface_mesh.h> 
   26#include <CGAL/AABB_face_graph_triangle_primitive.h> 
   27#include <CGAL/algorithm.h> 
   28#include <CGAL/Side_of_triangle_mesh.h> 
   29#include <CGAL/Aff_transformation_3.h> 
   30#include <CGAL/Polygon_mesh_processing/transform.h> 
   31#include <CGAL/Polygon_mesh_processing/compute_normal.h> 
   32#include <CGAL/Polygon_mesh_processing/detect_features.h> 
   33#include <CGAL/Polygon_mesh_processing/IO/polygon_mesh_io.h> 
   38#ifndef CGAL_HAS_THREADS 
   39static_assert(
false, 
"No cgal multithreading support");
 
   42#ifndef BOOST_HAS_THREADS 
   43static_assert(
false, 
"Boost has no threads");
 
   48#ifdef FEAT_COMPILER_INTEL 
   49#pragma warning disable 3280 
   50#pragma warning disable 1224 
   53#ifdef FEAT_COMPILER_MICROSOFT 
   54#pragma warning(default: 4244) 
   59#include <kernel/geometry/cgal.hpp> 
   61#ifdef FEAT_HAVE_HALFMATH 
   62#include <kernel/util/half.hpp> 
   67  template<
typename DT_>
 
   68  struct CGALTypeWrapper
 
   71    typedef typename CGAL::Simple_cartesian<DT_> K;
 
   72    typedef typename K::Point_3 Point_;
 
   73    typedef typename K::Segment_3 Segment_;
 
   74    typedef typename CGAL::Surface_mesh<Point_> Polyhedron_;
 
   75    typedef typename CGAL::AABB_face_graph_triangle_primitive<Polyhedron_> Primitive_;
 
   76    typedef typename CGAL::AABB_traits<K, Primitive_> Traits_;
 
   77    typedef typename CGAL::AABB_tree<Traits_> Tree_;
 
   78    typedef typename CGAL::Side_of_triangle_mesh<Polyhedron_, K> Point_inside_;
 
   79    typedef typename CGAL::Aff_transformation_3<K> Transformation_;
 
   80    typedef typename CGAL::AABB_traits<K, Primitive_>::Point_and_primitive_id Point_and_primitive_id_;
 
   81    typedef std::optional< typename Tree_::template Intersection_and_primitive_id<Segment_>::Type > Segment_intersection_;
 
   84  template<
typename DT_>
 
   85  struct CGALWrapperData
 
   87    typedef CGALTypeWrapper<DT_> TW_;
 
   88    typename TW_::Polyhedron_ * _polyhedron;
 
   89    typename TW_::Tree_ * _tree;
 
   90    typename TW_::Point_inside_ * _inside_tester;
 
   95      _inside_tester(nullptr)
 
   99    CGALWrapperData(
const CGALWrapperData&) = 
delete;
 
  100    CGALWrapperData& operator=(
const CGALWrapperData&) = 
delete;
 
  102    void swap(CGALWrapperData& other)
 
  104      std::swap(this->_polyhedron, 
other._polyhedron);
 
  105      std::swap(this->_tree, 
other._tree);
 
  106      std::swap(this->_inside_tester, 
other._inside_tester);
 
  109    CGALWrapperData(CGALWrapperData&& other) noexcept
 
  110    : _polyhedron(
nullptr), _tree(
nullptr), _inside_tester(
nullptr)
 
  115    CGALWrapperData& operator=(CGALWrapperData&& other) 
noexcept 
  125        delete _inside_tester;
 
  133  #ifdef FEAT_HAVE_QUADMATH 
  135  struct CGALTypeWrapper<__float128>
 
  137    typedef double CGALDT_;
 
  138    typedef typename CGAL::Simple_cartesian<double> K;
 
  139    typedef typename K::Point_3 Point_;
 
  140    typedef typename K::Segment_3 Segment_;
 
  141    typedef typename CGAL::Surface_mesh<Point_> Polyhedron_;
 
  142    typedef typename CGAL::AABB_face_graph_triangle_primitive<Polyhedron_> Primitive_;
 
  143    typedef typename CGAL::AABB_traits<K, Primitive_> Traits_;
 
  144    typedef typename CGAL::AABB_tree<Traits_> Tree_;
 
  145    typedef typename CGAL::Side_of_triangle_mesh<Polyhedron_, K> Point_inside_;
 
  146    typedef typename CGAL::Aff_transformation_3<K> Transformation_;
 
  147    typedef typename CGAL::AABB_traits<K, Primitive_>::Point_and_primitive_id Point_and_primitive_id_;
 
  148    typedef std::optional< typename Tree_::template Intersection_and_primitive_id<Segment_>::Type > Segment_intersection_;
 
  152  template<
typename DT_>
 
  153  using PointTypeAlias = 
typename FEAT::Geometry::template CGALWrapper<DT_>::PointType;
 
  155  template<
typename DT_>
 
  156  using TransformMatrixAlias = 
typename FEAT::Geometry::template CGALWrapper<DT_>::TransformMatrix;
 
  158  template<
typename DT_>
 
  162    _parse_mesh(file, file_mode);
 
  165  template<
typename DT_>
 
  166  CGALWrapper<DT_>::CGALWrapper(
const String & filename, CGALFileMode file_mode) :
 
  169    std::ifstream file(filename.c_str());
 
  170    XASSERTM(file.is_open(), 
"CGALWrapper: file read error: " + filename + 
" !");
 
  171    _parse_mesh(file, file_mode);
 
  175  template <
typename DT_>
 
  176  static CGALWrapperData<DT_> *from_topology(
 
  177      const std::vector<
typename CGALWrapper<DT_>::PointType> &vertices,
 
  178      const std::vector<std::array<Index, 3>> &faces)
 
  180    using VertexType = 
typename CGALTypeWrapper<DT_>::Point_;
 
  181    using SurfaceMesh = 
typename CGALTypeWrapper<DT_>::Polyhedron_;
 
  182    using VertexIndex = 
typename SurfaceMesh::Vertex_index;
 
  183    using FaceIndex = 
typename SurfaceMesh::Face_index;
 
  185    auto* result = 
new CGALWrapperData<DT_>;
 
  186    result->_polyhedron = 
new SurfaceMesh;
 
  189    std::vector<VertexIndex> vs(vertices.size());
 
  190    for(Index i(0); i < vertices.size(); i++)
 
  192      VertexType vertex(vertices[i][0], vertices[i][1], vertices[i][2]);
 
  193      vs[i] = result->_polyhedron->add_vertex(vertex);
 
  197    for(
const std::array<Index, 3>& face : faces)
 
  199      FaceIndex i = result->_polyhedron->add_face(vs[face[0]], vs[face[1]], vs[face[2]]);
 
  201      XASSERTM(i != SurfaceMesh::null_face(), 
"Failed to add face to surface mesh!");
 
  207  template<
typename DT_>
 
  208  CGALWrapper<DT_>::CGALWrapper(
 
  209    const std::vector<
typename CGALWrapper<DT_>::PointType> &vertices,
 
  210    const std::vector<std::array<Index, 3>> &faces) :
 
  211    _cgal_data(from_topology<DT_>(vertices, faces))
 
  216  template<
typename DT_>
 
  217  CGALWrapper<DT_>::CGALWrapper::~CGALWrapper()
 
  220      delete (CGALWrapperData<DT_>*)_cgal_data;
 
  224  template<
typename DT_>
 
  225  bool CGALWrapper<DT_>::point_inside(DT_ x, DT_ y, DT_ z)
 const 
  227    typedef typename CGALTypeWrapper<DT_>::CGALDT_ IDT_;
 
  228    typename CGALTypeWrapper<DT_>::Point_ query{IDT_(x), IDT_(y), IDT_(z)};
 
  231    CGALWrapperData<DT_> * cd = (CGALWrapperData<DT_>*)_cgal_data;
 
  232    return (*(cd->_inside_tester))(query) == CGAL::ON_BOUNDED_SIDE;
 
  235  template<
typename DT_>
 
  236  bool CGALWrapper<DT_>::point_not_outside(DT_ x, DT_ y, DT_ z)
 const 
  238    typedef typename CGALTypeWrapper<DT_>::CGALDT_ IDT_;
 
  239    typename CGALTypeWrapper<DT_>::Point_ query{IDT_(x), IDT_(y), IDT_(z)};
 
  242    CGALWrapperData<DT_> * cd = (CGALWrapperData<DT_>*)_cgal_data;
 
  243    CGAL::Bounded_side test_result = (*(cd->_inside_tester))(query);
 
  244    return test_result != CGAL::ON_UNBOUNDED_SIDE;
 
  247  template<
typename DT_>
 
  248  DT_ CGALWrapper<DT_>::squared_distance(DT_ x, DT_ y, DT_ z)
 const 
  250    typedef typename CGALTypeWrapper<DT_>::CGALDT_ IDT_;
 
  251    typename CGALTypeWrapper<DT_>::Point_ query{IDT_(x), IDT_(y), IDT_(z)};
 
  253    CGALWrapperData<DT_> * cd = (CGALWrapperData<DT_>*)_cgal_data;
 
  254    return DT_(cd->_tree->squared_distance(query));
 
  257  template<
typename DT_>
 
  258  DT_ CGALWrapper<DT_>::squared_distance_to_feature(
const CGALFeature& f, 
const PointType& p)
 const 
  260    return (p - closest_point_on_feature(f, p)).norm_euclid_sqr();
 
  264  template<
typename DT_>
 
  265  typename CGALWrapper<DT_>::PointType CGALWrapper<DT_>::closest_point(
const PointType& point)
 const 
  267    return closest_point(point[0], point[1], point[2]);
 
  270  template<
typename DT_>
 
  271  typename CGALWrapper<DT_>::PointType CGALWrapper<DT_>::closest_point(DT_ x, DT_ y, DT_ z)
 const 
  273    typedef typename CGALTypeWrapper<DT_>::CGALDT_ IDT_;
 
  274    typename CGALTypeWrapper<DT_>::Point_ query{IDT_(x), IDT_(y), IDT_(z)};
 
  275    CGALWrapperData<DT_> * cd = (CGALWrapperData<DT_>*)_cgal_data;
 
  276    typename CGALTypeWrapper<DT_>::Point_ n_point = cd->_tree->closest_point(query);
 
  277    return PointType{{DT_(n_point[0]), DT_(n_point[1]), DT_(n_point[2])}};
 
  280  template<
typename DT_>
 
  281  typename CGALWrapper<DT_>::PointType CGALWrapper<DT_>::closest_point(
const PointType& point, PointType& primitive_grad)
 const 
  283    typedef typename CGALTypeWrapper<DT_>::CGALDT_ IDT_;
 
  284    typename CGALTypeWrapper<DT_>::Point_ query{IDT_(point[0]), IDT_(point[1]), IDT_(point[2])};
 
  285    CGALWrapperData<DT_> * cd = (CGALWrapperData<DT_>*)_cgal_data;
 
  286    const typename CGALTypeWrapper<DT_>::Point_and_primitive_id_& cl_p_query = cd->_tree->closest_point_and_primitive(query);
 
  287    typename CGALTypeWrapper<DT_>::Polyhedron_::Face_index f = cl_p_query.second;
 
  288    auto v = CGAL::Polygon_mesh_processing::compute_face_normal(f,*(cd->_polyhedron));
 
  289    for(
int i = 0; i < 3; ++i)
 
  290      primitive_grad[i] = DT_(v[i]);
 
  291    return PointType{{DT_(cl_p_query.first[0]), DT_(cl_p_query.first[1]), DT_(cl_p_query.first[2])}};
 
  294  template<
typename DT_>
 
  295  typename CGALWrapper<DT_>::PointType
 
  296  CGALWrapper<DT_>::closest_point_on_feature(
const CGALFeature& f, 
const PointType& query)
 const 
  298    using PolyhedronType = 
typename CGALTypeWrapper<DT_>::Polyhedron_;
 
  299    using VertexIndex = 
typename PolyhedronType::Vertex_index;
 
  301    CGALWrapperData<DT_>* cd = (CGALWrapperData<DT_>*)_cgal_data;
 
  302    PolyhedronType* poly = cd->_polyhedron;
 
  304    const auto to_feat_point = [](
const auto& p)
 
  306      return PointType{p.x(), p.y(), p.z()};
 
  309    PointType closest = to_feat_point(poly->point(VertexIndex(f[0])));
 
  310    DT_ distance_to_closest = (query - closest).norm_euclid_sqr();
 
  312    const auto closest_point_on_segment = [&](PointType start, PointType end, PointType q)
 
  314      PointType segment = end - start;
 
  315      PointType segment_dir = segment.normalize();
 
  318      DT_ coefficient = Math::clamp(
dot(segment_dir, q - start), DT_(0.0), DT_(1.0));
 
  320      return start + coefficient * segment_dir;
 
  323    for(std::size_t i(0); i < f.size() - 1; i++)
 
  325      PointType segment_start = to_feat_point(poly->point(VertexIndex(f[i])));
 
  326      PointType segment_end = to_feat_point(poly->point(VertexIndex(f[i + 1])));
 
  328      PointType closest_on_segment = closest_point_on_segment(segment_start, segment_end, query);
 
  330      DT_ distance_to_segment = (query - closest_on_segment).norm_euclid_sqr();
 
  331      if(distance_to_segment < distance_to_closest)
 
  333        closest = closest_on_segment;
 
  334        distance_to_closest = distance_to_segment;
 
  341  template<
typename DT_>
 
  342  typename CGALWrapper<DT_>::PointType CGALWrapper<DT_>::point(std::uint32_t idx)
 const 
  344    using PolyhedronType = 
typename CGALTypeWrapper<DT_>::Polyhedron_;
 
  345    using VertexIndex = 
typename PolyhedronType::Vertex_index;
 
  347    const auto to_feat_point = [](
const auto& p)
 
  349      return PointType{p.x(), p.y(), p.z()};
 
  352    CGALWrapperData<DT_>* cd = (CGALWrapperData<DT_>*)_cgal_data;
 
  354    return to_feat_point(cd->_polyhedron->point(VertexIndex(idx)));
 
  357  template<
typename DT_>
 
  358  void CGALWrapper<DT_>::_parse_mesh(std::istream & file, CGALFileMode file_mode)
 
  360    delete (CGALWrapperData<DT_>*)_cgal_data;
 
  362    _cgal_data = 
new CGALWrapperData<DT_>;
 
  363    CGALWrapperData<DT_> * cd = (CGALWrapperData<DT_>*)_cgal_data;
 
  365    cd->_polyhedron = 
new typename CGALTypeWrapper<DT_>::Polyhedron_;
 
  370      case CGALFileMode::fm_off:
 
  371        status = CGAL::IO::read_OFF(file, *(cd->_polyhedron));
 
  372        XASSERTM(status == 
true, 
"CGAL::IO::read_OFF: read/parse error !");
 
  374      case CGALFileMode::fm_obj:
 
  375        status = CGAL::IO::read_OBJ(file, *(cd->_polyhedron));
 
  376        XASSERTM(status == 
true, 
"CGAL::IO::read_OBJ: read/parse error !");
 
  379        XASSERTM(
false, 
"CGAL FileMode not supported!");
 
  386  template<
typename DT_>
 
  389    using PolyhedronType = 
typename CGALTypeWrapper<DT_>::Polyhedron_;
 
  390    using VertexIndex = 
typename PolyhedronType::Vertex_index;
 
  391    using EdgeIndex = 
typename PolyhedronType::Edge_index;
 
  392    using HalfedgeIndex = 
typename PolyhedronType::Halfedge_index;
 
  393    using EdgeIsSharpMapType = 
typename PolyhedronType::template Property_map<EdgeIndex, bool>;
 
  397    auto* cd = 
static_cast<CGALWrapperData<DT_>*
>(_cgal_data);
 
  398    PolyhedronType* poly = cd->_polyhedron;
 
  404    std::pair<EdgeIsSharpMapType, bool> map = poly->template add_property_map<EdgeIndex, bool>(
"e:is_sharp");
 
  409      CGAL::Polygon_mesh_processing::detect_sharp_edges(*poly, critical_angle, map.first);
 
  416    std::vector<VertexIndex> seeds;
 
  418    for(VertexIndex v : poly->vertices())
 
  420      Index incident_feature_edges(0);
 
  422      for(HalfedgeIndex he : poly->halfedges_around_target(poly->halfedge(v)))
 
  424        EdgeIndex edge = poly->edge(he);
 
  427          incident_feature_edges++;
 
  432      if(incident_feature_edges != 0 && incident_feature_edges != 2)
 
  442    std::vector<bool> visited(poly->number_of_edges(), 
false);
 
  443    const auto flood_feature = [&](VertexIndex v, HalfedgeIndex h)
 
  446      feature.push_back(
static_cast<std::uint32_t
>(v));
 
  447      VertexIndex current = poly->source(h);
 
  448      feature.push_back(
static_cast<std::uint32_t
>(current));
 
  450      visited[poly->edge(h)] = 
true;
 
  452      while(current != v && std::find(seeds.begin(), seeds.end(), current) == seeds.end())
 
  454        for(HalfedgeIndex he : poly->halfedges_around_target(poly->halfedge(current)))
 
  456          EdgeIndex e = poly->edge(he);
 
  457          if(!map.first[e] || visited[e])
 
  464          current = poly->source(he);
 
  465          feature.push_back(
static_cast<std::uint32_t
>(current));
 
  477    for(VertexIndex seed : seeds)
 
  479      for(HalfedgeIndex he : poly->halfedges_around_target(poly->halfedge(seed)))
 
  481        EdgeIndex e = poly->edge(he);
 
  482        if(map.first[e] && !visited[e])
 
  485          result.push_back(flood_feature(seed, he));
 
  493    for(EdgeIndex e : poly->edges())
 
  495      if(map.first[e] && !visited[e])
 
  497        HalfedgeIndex he = poly->halfedge(e);
 
  498        VertexIndex start = poly->target(he);
 
  500        result.push_back(flood_feature(start, he));
 
  507  template<
typename DT_>
 
  508  void CGALWrapper<DT_>::transform(
const TransformMatrix& scale_rot, 
const PointType& translation, DT_ scale)
 
  510    typedef typename CGALTypeWrapper<DT_>::CGALDT_ IDT_;
 
  511    CGALWrapperData<DT_> * cd = (CGALWrapperData<DT_>*)_cgal_data;
 
  515    typename CGALTypeWrapper<DT_>::Transformation_ trafo_mat{(IDT_)(scale_rot[0][0]), (IDT_)(scale_rot[0][1]), (IDT_)(scale_rot[0][2]), (IDT_)(translation[0]),
 
  516                              (IDT_)(scale_rot[1][0]), (IDT_)(scale_rot[1][1]), (IDT_)(scale_rot[1][2]), (IDT_)(translation[1]),
 
  517                              (IDT_)(scale_rot[2][0]), (IDT_)(scale_rot[2][1]), (IDT_)(scale_rot[2][2]), (IDT_)(translation[2]),
 
  520    CGAL::Polygon_mesh_processing::transform(trafo_mat, *(cd->_polyhedron));
 
  527  template<
typename DT_>
 
  528  std::size_t CGALWrapper<DT_>::bytes()
 const 
  530    auto* cd = 
static_cast<CGALWrapperData<DT_>*
>(_cgal_data);
 
  533    constexpr std::size_t index_size = 
sizeof(std::uint32_t);
 
  536    constexpr std::size_t bytes_per_vertex = index_size + 
sizeof(
typename CGALTypeWrapper<DT_>::Point_) + 
sizeof(
bool);
 
  539    constexpr std::size_t bytes_per_halfedge = 4 * index_size;
 
  542    constexpr std::size_t bytes_per_edge = 
sizeof(bool);
 
  545    constexpr std::size_t bytes_per_face = index_size + 
sizeof(bool);
 
  547    std::size_t result = 0;
 
  551      result += cd->_polyhedron->number_of_vertices() * bytes_per_vertex +
 
  552                cd->_polyhedron->number_of_halfedges() * bytes_per_halfedge +
 
  553                cd->_polyhedron->number_of_edges() * bytes_per_edge +
 
  554                cd->_polyhedron->number_of_faces() * bytes_per_face;
 
  557    if(cd->_tree != 
nullptr)
 
  560      constexpr std::size_t bytes_per_primitive = 150;
 
  562      result += cd->_tree->size() * bytes_per_primitive;
 
  570  template<
typename DT_>
 
  571  void CGALWrapper<DT_>::_delete_tree()
 
  573    CGALWrapperData<DT_> * cd = (CGALWrapperData<DT_>*)_cgal_data;
 
  574    XASSERTM(cd->_polyhedron != 
nullptr, 
"ERROR: Polyhedron is not initialized!");
 
  575    delete cd->_inside_tester;
 
  576    cd->_inside_tester = 
nullptr;
 
  581  template<
typename DT_>
 
  582  void CGALWrapper<DT_>::_init_wrapper()
 
  584    CGALWrapperData<DT_> * cd = (CGALWrapperData<DT_>*)_cgal_data;
 
  585    XASSERTM(cd->_polyhedron != 
nullptr, 
"ERROR: Polyhedron is not initialized!");
 
  586    XASSERTM(cd->_tree == 
nullptr && cd->_inside_tester == 
nullptr, 
"ERROR: Tree or Inside Tester are already initialized");
 
  589    cd->_tree = 
new typename CGALTypeWrapper<DT_>::Tree_(faces(*(cd->_polyhedron)).first, faces(*(cd->_polyhedron)).second, *(cd->_polyhedron));
 
  590    cd->_tree->accelerate_distance_queries();
 
  592    cd->_inside_tester = 
new typename CGALTypeWrapper<DT_>::Point_inside_(*(cd->_tree));
 
  595  template<
typename DT_>
 
  596  CGALWrapper<DT_>::CGALWrapper(CGALWrapper<DT_>&& other) noexcept
 
  597  : _cgal_data(
nullptr)
 
  599    std::swap(this->_cgal_data, 
other._cgal_data);
 
  602  template<
typename DT_>
 
  603  CGALWrapper<DT_>& CGALWrapper<DT_>::operator=(CGALWrapper<DT_>&& other) 
noexcept 
  605    std::swap(this->_cgal_data, 
other._cgal_data);
 
  609  template<
typename DT_>
 
  612    typename CGALTypeWrapper<DT_>::Point_ t(a[0], a[1], a[2]), z(b[0], b[1], b[2]);
 
  613    typename CGALTypeWrapper<DT_>::Segment_ seg(t,z);
 
  614    return static_cast<CGALWrapperData<DT_>*
>(this->_cgal_data)->_tree->do_intersect(seg);
 
  624#ifdef FEAT_HAVE_HALFMATH 
  627#ifdef FEAT_HAVE_QUADMATH 
  631#elif !defined(DOXYGEN) 
  634class ipo_foobar_geometry_cgal
 
  638  ipo_foobar_geometry_cgal() :
 
  643} ipo_barfoo_geometry_cgal;
 
#define XASSERTM(expr, msg)
Assertion macro definition with custom message.
Wrapper for the CGAL Library.
bool intersects_line(const PointType &a, const PointType &b) const
tests whether the cgal mesh intersects with the line segment a->b
CGALWrapper(const CGALWrapper &)=delete
rule of five
Tiny Vector class template.
std::vector< CGALFeature > CGALFeatureNetwork
A FeatureNetwork is a list of features.
std::vector< std::uint32_t > CGALFeature
A feature is an edge-path on a surface mesh, stored as a list of vertex indices.
@ other
generic/other permutation strategy
CUDA_HOST_DEVICE T_ dot(const T_ &a, const T_ &b)
Computes the dot-product of two scalars.
std::uint64_t Index
Index data type.