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::Vector_3 Vector_;
74 typedef typename K::Segment_3 Segment_;
75 typedef typename CGAL::Surface_mesh<Point_> Polyhedron_;
76 typedef typename CGAL::AABB_face_graph_triangle_primitive<Polyhedron_> Primitive_;
77 typedef typename CGAL::AABB_traits<K, Primitive_> Traits_;
78 typedef typename CGAL::AABB_tree<Traits_> Tree_;
79 typedef typename CGAL::Side_of_triangle_mesh<Polyhedron_, K> Point_inside_;
80 typedef typename CGAL::Aff_transformation_3<K> Transformation_;
81 typedef typename CGAL::AABB_traits<K, Primitive_>::Point_and_primitive_id Point_and_primitive_id_;
82 typedef std::optional< typename Tree_::template Intersection_and_primitive_id<Segment_>::Type > Segment_intersection_;
85 template<
typename DT_>
86 struct CGALWrapperData
88 typedef CGALTypeWrapper<DT_> TW_;
89 typename TW_::Polyhedron_ * _polyhedron;
90 typename TW_::Tree_ * _tree;
91 typename TW_::Point_inside_ * _inside_tester;
96 _inside_tester(nullptr)
100 CGALWrapperData(
const CGALWrapperData&) =
delete;
101 CGALWrapperData& operator=(
const CGALWrapperData&) =
delete;
103 void swap(CGALWrapperData& other)
105 std::swap(this->_polyhedron,
other._polyhedron);
106 std::swap(this->_tree,
other._tree);
107 std::swap(this->_inside_tester,
other._inside_tester);
110 CGALWrapperData(CGALWrapperData&& other) noexcept
111 : _polyhedron(
nullptr), _tree(
nullptr), _inside_tester(
nullptr)
116 CGALWrapperData& operator=(CGALWrapperData&& other)
noexcept
126 delete _inside_tester;
134 #ifdef FEAT_HAVE_QUADMATH
136 struct CGALTypeWrapper<__float128>
138 typedef double CGALDT_;
139 typedef typename CGAL::Simple_cartesian<double> K;
140 typedef typename K::Point_3 Point_;
141 typedef typename K::Vector_3 Vector_;
142 typedef typename K::Segment_3 Segment_;
143 typedef typename CGAL::Surface_mesh<Point_> Polyhedron_;
144 typedef typename CGAL::AABB_face_graph_triangle_primitive<Polyhedron_> Primitive_;
145 typedef typename CGAL::AABB_traits<K, Primitive_> Traits_;
146 typedef typename CGAL::AABB_tree<Traits_> Tree_;
147 typedef typename CGAL::Side_of_triangle_mesh<Polyhedron_, K> Point_inside_;
148 typedef typename CGAL::Aff_transformation_3<K> Transformation_;
149 typedef typename CGAL::AABB_traits<K, Primitive_>::Point_and_primitive_id Point_and_primitive_id_;
150 typedef std::optional< typename Tree_::template Intersection_and_primitive_id<Segment_>::Type > Segment_intersection_;
154 template<
typename DT_>
155 using PointTypeAlias =
typename FEAT::Geometry::template CGALWrapper<DT_>::PointType;
157 template<
typename DT_>
158 using TransformMatrixAlias =
typename FEAT::Geometry::template CGALWrapper<DT_>::TransformMatrix;
160 template<
typename DT_>
163 _expensive_intersection(false)
165 _parse_mesh(file, file_mode);
168 template<
typename DT_>
169 CGALWrapper<DT_>::CGALWrapper(
const String & filename, CGALFileMode file_mode) :
171 _expensive_intersection(false)
173 std::ifstream file(filename.c_str());
174 XASSERTM(file.is_open(),
"CGALWrapper: file read error: " + filename +
" !");
175 _parse_mesh(file, file_mode);
179 template<
typename DT_>
180 void CGALWrapper<DT_>::set_expensive_intersection(
bool expensive_test)
182 this->_expensive_intersection = expensive_test;
185 template <
typename DT_>
186 static CGALWrapperData<DT_> *from_topology(
187 const std::vector<
typename CGALWrapper<DT_>::PointType> &vertices,
188 const std::vector<std::array<Index, 3>> &faces)
190 using VertexType =
typename CGALTypeWrapper<DT_>::Point_;
191 using SurfaceMesh =
typename CGALTypeWrapper<DT_>::Polyhedron_;
192 using VertexIndex =
typename SurfaceMesh::Vertex_index;
193 using FaceIndex =
typename SurfaceMesh::Face_index;
195 auto* result =
new CGALWrapperData<DT_>;
196 result->_polyhedron =
new SurfaceMesh;
199 std::vector<VertexIndex> vs(vertices.size());
200 for(Index i(0); i < vertices.size(); i++)
202 VertexType vertex(vertices[i][0], vertices[i][1], vertices[i][2]);
203 vs[i] = result->_polyhedron->add_vertex(vertex);
207 for(
const std::array<Index, 3>& face : faces)
209 FaceIndex i = result->_polyhedron->add_face(vs[face[0]], vs[face[1]], vs[face[2]]);
211 XASSERTM(i != SurfaceMesh::null_face(),
"Failed to add face to surface mesh!");
217 template<
typename DT_>
218 CGALWrapper<DT_>::CGALWrapper(
219 const std::vector<
typename CGALWrapper<DT_>::PointType> &vertices,
220 const std::vector<std::array<Index, 3>> &faces) :
221 _cgal_data(from_topology<DT_>(vertices, faces)),
222 _expensive_intersection(false)
227 template<
typename DT_>
228 CGALWrapper<DT_>::CGALWrapper::~CGALWrapper()
231 delete (CGALWrapperData<DT_>*)_cgal_data;
235 template<
typename DT_>
236 bool CGALWrapper<DT_>::point_inside(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 return (*(cd->_inside_tester))(query) == CGAL::ON_BOUNDED_SIDE;
246 template<
typename DT_>
247 bool CGALWrapper<DT_>::point_not_outside(DT_ x, DT_ y, DT_ z)
const
249 typedef typename CGALTypeWrapper<DT_>::CGALDT_ IDT_;
250 typename CGALTypeWrapper<DT_>::Point_ query{IDT_(x), IDT_(y), IDT_(z)};
253 CGALWrapperData<DT_> * cd = (CGALWrapperData<DT_>*)_cgal_data;
254 CGAL::Bounded_side test_result = (*(cd->_inside_tester))(query);
255 return test_result != CGAL::ON_UNBOUNDED_SIDE;
258 template<
typename DT_>
259 DT_ CGALWrapper<DT_>::squared_distance(DT_ x, DT_ y, DT_ z)
const
261 typedef typename CGALTypeWrapper<DT_>::CGALDT_ IDT_;
262 typename CGALTypeWrapper<DT_>::Point_ query{IDT_(x), IDT_(y), IDT_(z)};
264 CGALWrapperData<DT_> * cd = (CGALWrapperData<DT_>*)_cgal_data;
265 return DT_(cd->_tree->squared_distance(query));
268 template<
typename DT_>
269 DT_ CGALWrapper<DT_>::squared_distance_to_feature(
const CGALFeature& f,
const PointType& p)
const
271 return (p - closest_point_on_feature(f, p)).norm_euclid_sqr();
275 template<
typename DT_>
276 typename CGALWrapper<DT_>::PointType CGALWrapper<DT_>::closest_point(
const PointType& point)
const
278 return closest_point(point[0], point[1], point[2]);
281 template<
typename DT_>
282 typename CGALWrapper<DT_>::PointType CGALWrapper<DT_>::closest_point(DT_ x, DT_ y, DT_ z)
const
284 typedef typename CGALTypeWrapper<DT_>::CGALDT_ IDT_;
285 typename CGALTypeWrapper<DT_>::Point_ query{IDT_(x), IDT_(y), IDT_(z)};
286 CGALWrapperData<DT_> * cd = (CGALWrapperData<DT_>*)_cgal_data;
287 typename CGALTypeWrapper<DT_>::Point_ n_point = cd->_tree->closest_point(query);
288 return PointType{{DT_(n_point[0]), DT_(n_point[1]), DT_(n_point[2])}};
291 template<
typename DT_>
292 typename CGALWrapper<DT_>::PointType CGALWrapper<DT_>::closest_point(
const PointType& point, PointType& primitive_grad)
const
294 typedef typename CGALTypeWrapper<DT_>::CGALDT_ IDT_;
295 typename CGALTypeWrapper<DT_>::Point_ query{IDT_(point[0]), IDT_(point[1]), IDT_(point[2])};
296 CGALWrapperData<DT_> * cd = (CGALWrapperData<DT_>*)_cgal_data;
297 const typename CGALTypeWrapper<DT_>::Point_and_primitive_id_& cl_p_query = cd->_tree->closest_point_and_primitive(query);
298 typename CGALTypeWrapper<DT_>::Polyhedron_::Face_index f = cl_p_query.second;
299 auto v = CGAL::Polygon_mesh_processing::compute_face_normal(f,*(cd->_polyhedron));
300 for(
int i = 0; i < 3; ++i)
301 primitive_grad[i] = DT_(v[i]);
302 return PointType{{DT_(cl_p_query.first[0]), DT_(cl_p_query.first[1]), DT_(cl_p_query.first[2])}};
305 template<
typename DT_>
306 typename CGALWrapper<DT_>::PointType
307 CGALWrapper<DT_>::closest_point_on_feature(
const CGALFeature& f,
const PointType& query)
const
309 using PolyhedronType =
typename CGALTypeWrapper<DT_>::Polyhedron_;
310 using VertexIndex =
typename PolyhedronType::Vertex_index;
312 CGALWrapperData<DT_>* cd = (CGALWrapperData<DT_>*)_cgal_data;
313 PolyhedronType* poly = cd->_polyhedron;
315 const auto to_feat_point = [](
const auto& p)
317 return PointType{p.x(), p.y(), p.z()};
320 PointType closest = to_feat_point(poly->point(VertexIndex(f[0])));
321 DT_ distance_to_closest = (query - closest).norm_euclid_sqr();
323 const auto closest_point_on_segment = [&](PointType start, PointType end, PointType q)
325 PointType segment = end - start;
326 PointType segment_dir = segment.normalize();
329 DT_ coefficient = Math::clamp(
dot(segment_dir, q - start), DT_(0.0), DT_(1.0));
331 return start + coefficient * segment_dir;
334 for(std::size_t i(0); i < f.size() - 1; i++)
336 PointType segment_start = to_feat_point(poly->point(VertexIndex(f[i])));
337 PointType segment_end = to_feat_point(poly->point(VertexIndex(f[i + 1])));
339 PointType closest_on_segment = closest_point_on_segment(segment_start, segment_end, query);
341 DT_ distance_to_segment = (query - closest_on_segment).norm_euclid_sqr();
342 if(distance_to_segment < distance_to_closest)
344 closest = closest_on_segment;
345 distance_to_closest = distance_to_segment;
352 template<
typename DT_>
353 typename CGALWrapper<DT_>::PointType CGALWrapper<DT_>::point(std::uint32_t idx)
const
355 using PolyhedronType =
typename CGALTypeWrapper<DT_>::Polyhedron_;
356 using VertexIndex =
typename PolyhedronType::Vertex_index;
358 const auto to_feat_point = [](
const auto& p)
360 return PointType{p.x(), p.y(), p.z()};
363 CGALWrapperData<DT_>* cd = (CGALWrapperData<DT_>*)_cgal_data;
365 return to_feat_point(cd->_polyhedron->point(VertexIndex(idx)));
368 template<
typename DT_>
369 std::vector<typename CGALWrapper<DT_>::PointType> CGALWrapper<DT_>::points()
const
371 std::vector<PointType> result(get_num_entities(0));
372 for(std::uint32_t i(0); i < result.size(); i++)
374 result[i] = point(i);
379 template<
typename DT_>
380 void CGALWrapper<DT_>::_parse_mesh(std::istream & file, CGALFileMode file_mode)
382 delete (CGALWrapperData<DT_>*)_cgal_data;
384 _cgal_data =
new CGALWrapperData<DT_>;
385 CGALWrapperData<DT_> * cd = (CGALWrapperData<DT_>*)_cgal_data;
387 cd->_polyhedron =
new typename CGALTypeWrapper<DT_>::Polyhedron_;
392 case CGALFileMode::fm_off:
393 status = CGAL::IO::read_OFF(file, *(cd->_polyhedron));
394 XASSERTM(status ==
true,
"CGAL::IO::read_OFF: read/parse error !");
396 case CGALFileMode::fm_obj:
397 status = CGAL::IO::read_OBJ(file, *(cd->_polyhedron));
398 XASSERTM(status ==
true,
"CGAL::IO::read_OBJ: read/parse error !");
401 XASSERTM(
false,
"CGAL FileMode not supported!");
408 template<
typename DT_>
411 using CGALDT =
typename CGALTypeWrapper<DT_>::CGALDT_;
412 using PolyhedronType =
typename CGALTypeWrapper<DT_>::Polyhedron_;
413 using VertexIndex =
typename PolyhedronType::Vertex_index;
414 using EdgeIndex =
typename PolyhedronType::Edge_index;
415 using HalfedgeIndex =
typename PolyhedronType::Halfedge_index;
416 using EdgeIsSharpMapType =
typename PolyhedronType::template Property_map<EdgeIndex, bool>;
420 auto* cd =
static_cast<CGALWrapperData<DT_>*
>(_cgal_data);
421 PolyhedronType* poly = cd->_polyhedron;
427 std::pair<EdgeIsSharpMapType, bool> map = poly->template add_property_map<EdgeIndex, bool>(
"e:is_sharp");
432 CGAL::Polygon_mesh_processing::detect_sharp_edges(*poly, CGALDT(critical_angle), map.first);
439 std::vector<VertexIndex> seeds;
441 for(VertexIndex v : poly->vertices())
443 Index incident_feature_edges(0);
445 for(HalfedgeIndex he : poly->halfedges_around_target(poly->halfedge(v)))
447 EdgeIndex edge = poly->edge(he);
450 incident_feature_edges++;
455 if(incident_feature_edges != 0 && incident_feature_edges != 2)
465 std::vector<bool> visited(poly->number_of_edges(),
false);
466 const auto flood_feature = [&](VertexIndex v, HalfedgeIndex h)
469 feature.push_back(
static_cast<std::uint32_t
>(v));
470 VertexIndex current = poly->source(h);
471 feature.push_back(
static_cast<std::uint32_t
>(current));
473 visited[poly->edge(h)] =
true;
475 while(current != v && std::find(seeds.begin(), seeds.end(), current) == seeds.end())
477 for(HalfedgeIndex he : poly->halfedges_around_target(poly->halfedge(current)))
479 EdgeIndex e = poly->edge(he);
480 if(!map.first[e] || visited[e])
487 current = poly->source(he);
488 feature.push_back(
static_cast<std::uint32_t
>(current));
500 for(VertexIndex seed : seeds)
502 for(HalfedgeIndex he : poly->halfedges_around_target(poly->halfedge(seed)))
504 EdgeIndex e = poly->edge(he);
505 if(map.first[e] && !visited[e])
508 result.push_back(flood_feature(seed, he));
516 for(EdgeIndex e : poly->edges())
518 if(map.first[e] && !visited[e])
520 HalfedgeIndex he = poly->halfedge(e);
521 VertexIndex start = poly->target(he);
523 result.push_back(flood_feature(start, he));
530 template<
typename DT_>
531 void CGALWrapper<DT_>::transform(
const TransformMatrix& scale_rot,
const PointType& translation, DT_ scale)
533 typedef typename CGALTypeWrapper<DT_>::CGALDT_ IDT_;
534 CGALWrapperData<DT_> * cd = (CGALWrapperData<DT_>*)_cgal_data;
538 typename CGALTypeWrapper<DT_>::Transformation_ trafo_mat{(IDT_)(scale_rot[0][0]), (IDT_)(scale_rot[0][1]), (IDT_)(scale_rot[0][2]), (IDT_)(translation[0]),
539 (IDT_)(scale_rot[1][0]), (IDT_)(scale_rot[1][1]), (IDT_)(scale_rot[1][2]), (IDT_)(translation[1]),
540 (IDT_)(scale_rot[2][0]), (IDT_)(scale_rot[2][1]), (IDT_)(scale_rot[2][2]), (IDT_)(translation[2]),
543 CGAL::Polygon_mesh_processing::transform(trafo_mat, *(cd->_polyhedron));
550 template<
typename DT_>
551 void CGALWrapper<DT_>::displace_vertices(
const std::vector<PointType>& offsets)
553 using Point =
typename CGALTypeWrapper<DT_>::Point_;
554 using Vector =
typename CGALTypeWrapper<DT_>::Vector_;
556 ASSERT(get_num_vertices() == offsets.size());
558 auto* cd =
static_cast<CGALWrapperData<DT_>*
>(_cgal_data);
562 for(
auto vertex_idx : cd->_polyhedron->vertices())
564 Point& vertex = cd->_polyhedron->point(vertex_idx);
565 const auto& offset = offsets[i++];
566 vertex += Vector(offset[0], offset[1], offset[2]);
571 template<
typename DT_>
572 Index CGALWrapper<DT_>::get_num_vertices()
const
574 auto* cd =
static_cast<CGALWrapperData<DT_>*
>(_cgal_data);
575 return cd->_polyhedron->number_of_vertices();
578 template<
typename DT_>
579 Index CGALWrapper<DT_>::get_num_entities(
int dim)
const
581 ASSERT(0<= dim && dim <= 2);
583 auto* cd =
static_cast<CGALWrapperData<DT_>*
>(_cgal_data);
586 case 0:
return cd->_polyhedron->number_of_vertices();
587 case 1:
return cd->_polyhedron->number_of_edges();
588 case 2:
return cd->_polyhedron->number_of_faces();
589 default:
XABORTM(
"Unsupported dimension!");
595 template<
typename DT_>
596 std::vector<typename CGALWrapper<DT_>::PointType> CGALWrapper<DT_>::outer_normals_at_faces()
const
598 using PolyhedronType =
typename CGALTypeWrapper<DT_>::Polyhedron_;
600 CGALWrapperData<DT_>* cd = (CGALWrapperData<DT_>*)_cgal_data;
601 PolyhedronType* poly = cd->_polyhedron;
603 std::vector<PointType> normals(this->get_num_entities(2));
604 for(
const auto facet : poly->faces())
606 auto outer_normal = CGAL::Polygon_mesh_processing::compute_face_normal(facet, *poly);
607 normals.at(facet) = PointType{outer_normal.x(), outer_normal.y(), outer_normal.z()};
613 template<
typename DT_>
614 Index CGALVerticesAroundFaceAdjactor<DT_>::get_num_nodes_domain()
const
616 return Index(_wrapper->get_num_entities(2));
619 template<
typename DT_>
620 Index CGALVerticesAroundFaceAdjactor<DT_>::get_num_nodes_image()
const
622 return Index(_wrapper->get_num_entities(0));
625 template<
typename DT_>
626 CGALValueIteratorWrapper<Index> CGALVerticesAroundFaceAdjactor<DT_>::image_begin(Index face)
const
628 using PolyhedronType =
typename CGALTypeWrapper<DT_>::Polyhedron_;
629 using FaceIndex =
typename PolyhedronType::Face_index;
631 ASSERT(face < _wrapper->get_num_entities(2));
633 auto* cd =
static_cast<CGALWrapperData<DT_>*
>(_wrapper->_cgal_data);
635 auto range = cd->_polyhedron->vertices_around_face(cd->_polyhedron->halfedge(FaceIndex(
typename PolyhedronType::size_type(face))));
636 return CGALValueIteratorWrapper<Index>([it = range.begin(), end = range.end()]()
mutable {
641 return std::optional<Index>(val);
645 return std::optional<Index>{};
650 template<
typename DT_>
651 CGALValueIteratorWrapper<Index> CGALVerticesAroundFaceAdjactor<DT_>::image_end(Index )
const
653 return CGALValueIteratorWrapper<Index>([]() {
return std::nullopt; });
656 template<
typename DT_>
657 CGALVerticesAroundFaceAdjactor<DT_> CGALWrapper<DT_>::vertices_around_face()
const
659 return CGALVerticesAroundFaceAdjactor<DT_>(
this);
662 template<
typename DT_>
663 std::size_t CGALWrapper<DT_>::bytes()
const
665 auto* cd =
static_cast<CGALWrapperData<DT_>*
>(_cgal_data);
668 constexpr std::size_t index_size =
sizeof(std::uint32_t);
671 constexpr std::size_t bytes_per_vertex = index_size +
sizeof(
typename CGALTypeWrapper<DT_>::Point_) +
sizeof(
bool);
674 constexpr std::size_t bytes_per_halfedge = 4 * index_size;
677 constexpr std::size_t bytes_per_edge =
sizeof(bool);
680 constexpr std::size_t bytes_per_face = index_size +
sizeof(bool);
682 std::size_t result = 0;
686 result += cd->_polyhedron->number_of_vertices() * bytes_per_vertex +
687 cd->_polyhedron->number_of_halfedges() * bytes_per_halfedge +
688 cd->_polyhedron->number_of_edges() * bytes_per_edge +
689 cd->_polyhedron->number_of_faces() * bytes_per_face;
692 if(cd->_tree !=
nullptr)
695 constexpr std::size_t bytes_per_primitive = 150;
697 result += cd->_tree->size() * bytes_per_primitive;
705 template<
typename DT_>
706 void CGALWrapper<DT_>::write_off(std::ostream& stream)
const
708 CGALWrapperData<DT_> * cd = (CGALWrapperData<DT_>*)_cgal_data;
711 status = CGAL::IO::write_OFF(stream, *(cd->_polyhedron));
713 throw FileError(
"Failed to write off file to stream");
716 template<
typename DT_>
717 void CGALWrapper<DT_>::_delete_tree()
719 CGALWrapperData<DT_> * cd = (CGALWrapperData<DT_>*)_cgal_data;
720 XASSERTM(cd->_polyhedron !=
nullptr,
"ERROR: Polyhedron is not initialized!");
721 delete cd->_inside_tester;
722 cd->_inside_tester =
nullptr;
727 template<
typename DT_>
728 void CGALWrapper<DT_>::_init_wrapper()
730 CGALWrapperData<DT_> * cd = (CGALWrapperData<DT_>*)_cgal_data;
731 XASSERTM(cd->_polyhedron !=
nullptr,
"ERROR: Polyhedron is not initialized!");
732 XASSERTM(cd->_tree ==
nullptr && cd->_inside_tester ==
nullptr,
"ERROR: Tree or Inside Tester are already initialized");
735 cd->_tree =
new typename CGALTypeWrapper<DT_>::Tree_(faces(*(cd->_polyhedron)).first, faces(*(cd->_polyhedron)).second, *(cd->_polyhedron));
736 cd->_tree->accelerate_distance_queries();
738 cd->_inside_tester =
new typename CGALTypeWrapper<DT_>::Point_inside_(*(cd->_tree));
741 template<
typename DT_>
742 CGALWrapper<DT_>::CGALWrapper(CGALWrapper<DT_>&& other) noexcept
743 : _cgal_data(
nullptr),
744 _expensive_intersection(
other._expensive_intersection)
746 std::swap(this->_cgal_data,
other._cgal_data);
749 template<
typename DT_>
750 CGALWrapper<DT_>& CGALWrapper<DT_>::operator=(CGALWrapper<DT_>&& other)
noexcept
752 this->_expensive_intersection =
other._expensive_intersection;
753 std::swap(this->_cgal_data,
other._cgal_data);
757 template<
typename DT_>
760 typename CGALTypeWrapper<DT_>::Point_ t(a[0], a[1], a[2]), z(b[0], b[1], b[2]);
761 typename CGALTypeWrapper<DT_>::Segment_ seg(t,z);
762 return static_cast<CGALWrapperData<DT_>*
>(this->_cgal_data)->_tree->do_intersect(seg);
767 template<
typename DT_>
770 typename CGALTypeWrapper<DT_>::Polyhedron_::Vertex_index vtx_desc[8];
771 for(std::size_t k = 0; k < std::size_t (8); ++k)
773 vtx_desc[k] = surface.add_vertex(
typename FEAT::Geometry::CGALTypeWrapper<DT_>::Point_(points[k][0], points[k][1], points[k][2]));
776 constexpr std::size_t faces[12][3] =
778 {0, 1, 2}, {1, 3, 2},
779 {6, 5, 4}, {7, 5, 6},
780 {0, 2, 4}, {2, 6, 4},
781 {3, 1, 5}, {3, 5, 7},
782 {4, 1, 0}, {5, 1, 4},
786 for(std::size_t f = 0; f < std::size_t(12); ++f)
788 surface.add_face(vtx_desc[faces[f][0]], vtx_desc[faces[f][1]], vtx_desc[faces[f][2]]);
793 template<
typename DT_>
796 typename CGALTypeWrapper<DT_>::Polyhedron_ hexaeder;
797 typedef typename CGALTypeWrapper<DT_>::Point_ Point;
798 Intern::template split_hexaeder_surface<DT_>(hexaeder, points);
799 const auto* tree =
static_cast<CGALWrapperData<DT_>*
>(this->_cgal_data)->_tree;
804 const auto* poly =
static_cast<CGALWrapperData<DT_>*
>(this->_cgal_data)->_polyhedron;
805 typename CGALTypeWrapper<DT_>::Point_inside_ inside(hexaeder);
806 auto res = inside(poly->point(*std::begin(poly->vertices())));
807 if(res == CGAL::ON_BOUNDED_SIDE || res == CGAL::ON_BOUNDARY)
814 auto boxA = hexaeder.point(*std::begin(hexaeder.vertices())).bbox();
815 for(
auto v : hexaeder.vertices())
817 boxA += hexaeder.point(v).bbox();
822 auto boxB = tree->bbox();
823 if(!CGAL::do_overlap(boxA, boxB))
832 for(std::size_t k = 0; k < 8u; ++k)
834 mid_point += points[k];
836 mid_point *= DT_(1)/DT_(8);
838 auto& inside_tester = *
static_cast<CGALWrapperData<DT_>*
>(this->_cgal_data)->_inside_tester;
839 if(inside_tester(Point(mid_point[0], mid_point[1], mid_point[2])) != CGAL::ON_UNBOUNDED_SIDE)
842 for(
auto v : hexaeder.vertices())
844 auto p = hexaeder.point(v);
845 if(inside_tester(p) != CGAL::ON_UNBOUNDED_SIDE)
850 if(!this->_expensive_intersection)
852 return tree->do_intersect(boxA);
857 std::list<typename FEAT::Geometry::CGALTypeWrapper<DT_>::Tree_::Primitive_id> primitives;
860 tree->all_intersected_primitives(boxA, std::back_inserter(primitives));
861 const auto* poly =
static_cast<CGALWrapperData<DT_>*
>(this->_cgal_data)->_polyhedron;
864 for(
const auto& sf: primitives)
866 std::array<Point, 3> triang;
869 for(
auto v : poly->vertices_around_face(poly->halfedge(sf)))
871 triang[k++] = poly->point(v);
874 CGAL::Triangle_3<typename CGALTypeWrapper<DT_>::K> triangle_s{triang[0], triang[1], triang[2]};
878 for(
auto f : hexaeder.faces())
882 for(
auto v : hexaeder.vertices_around_face(hexaeder.halfedge(f)))
884 triang[k++] = hexaeder.point(v);
887 CGAL::Triangle_3<typename CGALTypeWrapper<DT_>::K> triangle_a(triang[0], triang[1], triang[2]);
889 if(CGAL::do_intersect(triangle_s, triangle_a))
911#ifdef FEAT_HAVE_HALFMATH
917#ifdef FEAT_HAVE_QUADMATH
922#elif !defined(DOXYGEN)
925class ipo_foobar_geometry_cgal
929 ipo_foobar_geometry_cgal() :
934} ipo_barfoo_geometry_cgal;
#define ASSERT(expr)
Debug-Assertion macro definition.
#define XABORTM(msg)
Abortion macro definition with custom message.
#define XASSERTM(expr, msg)
Assertion macro definition with custom message.
Adjactor for vertices around a face.
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.