From 97651adbec0816a04645423a5296c00238a421d6 Mon Sep 17 00:00:00 2001 From: Jane Tournois Date: Mon, 5 Aug 2019 17:50:54 +0200 Subject: [PATCH 001/568] add very first version of tetrahedral remeshing package --- .../CGAL/boost/graph/parameters_interface.h | 4 + .../Tetrahedral_remeshing/CMakeLists.txt | 28 + .../tetrahedral_remeshing_example.cpp | 39 + .../Remeshing_cell_base.h | 137 ++ .../Remeshing_triangulation_3.h | 71 + .../Remeshing_vertex_base.h | 98 ++ .../CGAL/Tetrahedral_remeshing/Sizing_field.h | 44 + .../Uniform_sizing_field.h | 52 + .../internal/add_imaginary_layer.h | 248 ++++ .../internal/collapse_short_edges.h | 1030 +++++++++++++++ .../internal/compute_c3t3_statistics.h | 210 +++ .../internal/flip_edges.h | 1167 +++++++++++++++++ .../internal/smooth_vertices.h | 775 +++++++++++ .../internal/split_long_edges.h | 273 ++++ .../tetrahedral_adaptive_remeshing_impl.h | 423 ++++++ .../internal/tetrahedral_remeshing_helpers.h | 387 ++++++ .../internal/triangulation_3_helpers.h | 811 ++++++++++++ .../include/CGAL/tetrahedral_remeshing.h | 217 +++ 18 files changed, 6014 insertions(+) create mode 100644 Tetrahedral_remeshing/examples/Tetrahedral_remeshing/CMakeLists.txt create mode 100644 Tetrahedral_remeshing/examples/Tetrahedral_remeshing/tetrahedral_remeshing_example.cpp create mode 100644 Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/Remeshing_cell_base.h create mode 100644 Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/Remeshing_triangulation_3.h create mode 100644 Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/Remeshing_vertex_base.h create mode 100644 Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/Sizing_field.h create mode 100644 Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/Uniform_sizing_field.h create mode 100644 Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/add_imaginary_layer.h create mode 100644 Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/collapse_short_edges.h create mode 100644 Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/compute_c3t3_statistics.h create mode 100644 Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/flip_edges.h create mode 100644 Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/smooth_vertices.h create mode 100644 Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/split_long_edges.h create mode 100644 Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/tetrahedral_adaptive_remeshing_impl.h create mode 100644 Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/tetrahedral_remeshing_helpers.h create mode 100644 Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/triangulation_3_helpers.h create mode 100644 Tetrahedral_remeshing/include/CGAL/tetrahedral_remeshing.h diff --git a/BGL/include/CGAL/boost/graph/parameters_interface.h b/BGL/include/CGAL/boost/graph/parameters_interface.h index ebdce042e75..9f29000f296 100644 --- a/BGL/include/CGAL/boost/graph/parameters_interface.h +++ b/BGL/include/CGAL/boost/graph/parameters_interface.h @@ -137,6 +137,10 @@ CGAL_add_named_parameter(with_dihedral_angle_t, with_dihedral_angle, with_dihedr CGAL_add_named_parameter(optimize_anchor_location_t, optimize_anchor_location, optimize_anchor_location) CGAL_add_named_parameter(pca_plane_t, pca_plane, pca_plane) +// tetrahedral remeshing parameters +CGAL_add_named_parameter(protect_boundaries_t, protect_boundaries, protect_boundaries) +CGAL_add_named_parameter(cell_selector_t, cell_selector, cell_selector) + // output parameters CGAL_add_named_parameter(face_proxy_map_t, face_proxy_map, face_proxy_map) CGAL_add_named_parameter(proxies_t, proxies, proxies) diff --git a/Tetrahedral_remeshing/examples/Tetrahedral_remeshing/CMakeLists.txt b/Tetrahedral_remeshing/examples/Tetrahedral_remeshing/CMakeLists.txt new file mode 100644 index 00000000000..f771803899e --- /dev/null +++ b/Tetrahedral_remeshing/examples/Tetrahedral_remeshing/CMakeLists.txt @@ -0,0 +1,28 @@ +# Created by the script cgal_create_CMakeLists +# This is the CMake script for compiling a set of CGAL applications. + +cmake_minimum_required(VERSION 3.1...3.14) + +project( Tetrahedral_remeshing_Examples ) + +# CGAL and its components +find_package( CGAL REQUIRED ) +if ( NOT CGAL_FOUND ) + message(STATUS "This project requires the CGAL library, and will not be compiled.") + return() +endif() + +# Boost and its components +find_package( Boost REQUIRED ) +if ( NOT Boost_FOUND ) + message(STATUS "This project requires the Boost library, and will not be compiled.") + return() +endif() + + +# include for local directory +#include_directories( BEFORE include ) + +# Creating entries for all C++ files with "main" routine +# ########################################################## + create_single_source_cgal_program( "tetrahedral_remeshing_example.cpp" ) diff --git a/Tetrahedral_remeshing/examples/Tetrahedral_remeshing/tetrahedral_remeshing_example.cpp b/Tetrahedral_remeshing/examples/Tetrahedral_remeshing/tetrahedral_remeshing_example.cpp new file mode 100644 index 00000000000..409fefcf626 --- /dev/null +++ b/Tetrahedral_remeshing/examples/Tetrahedral_remeshing/tetrahedral_remeshing_example.cpp @@ -0,0 +1,39 @@ +#include + +#include +#include + +#include +#include + +typedef CGAL::Exact_predicates_inexact_constructions_kernel K; + +typedef CGAL::Tetrahedral_remeshing::Remeshing_triangulation_3 Triangulation; +//todo : add specialization for Cell_base without info +// (does not compile with `void` instead of `int`) + + +int main(int argc, char* argv[]) +{ + const char* filename = (argc > 1) ? argv[1] : "data/pig.off"; + float target_edge_length = (argc > 2) ? atof(argv[2]) : 2.f; + + std::ifstream input(filename, std::ios::in); + if (!input) + { + std::cerr << "File " << filename << " could not be found" << std::endl; + return EXIT_FAILURE; + } + + Triangulation tr; + input >> tr; + CGAL_assertion(tr.is_valid()); + + CGAL::tetrahedral_adaptive_remeshing(tr, target_edge_length); + + std::ofstream oFileT("output.tr.cgal", std::ios::out); + // writing file output; + oFileT << tr; + + return EXIT_SUCCESS; +} diff --git a/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/Remeshing_cell_base.h b/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/Remeshing_cell_base.h new file mode 100644 index 00000000000..db67688b216 --- /dev/null +++ b/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/Remeshing_cell_base.h @@ -0,0 +1,137 @@ +// Copyright (c) 2019 GeometryFactory (France). +// All rights reserved. +// +// This file is part of CGAL (www.cgal.org). +// You can redistribute it and/or modify it under the terms of the GNU +// General Public License as published by the Free Software Foundation, +// either version 3 of the License, or (at your option) any later version. +// +// Licensees holding a valid commercial license may use this file in +// accordance with the commercial license agreement provided with the software. +// +// This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE +// WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. +// +// $URL$ +// $Id$ +// SPDX-License-Identifier: GPL-3.0+ +// +// +// Author(s) : Jane Tournois + +#ifndef CGAL_TET_ADAPTIVE_REMESHING_CELL_BASE_H +#define CGAL_TET_ADAPTIVE_REMESHING_CELL_BASE_H + + +#include +#include + +#include + +namespace CGAL +{ +namespace Tetrahedral_remeshing +{ + template > + class Remeshing_cell_base + : public CGAL::Triangulation_cell_base_with_info_3 + + { + typedef CGAL::Triangulation_cell_base_with_info_3 Base; + typedef typename Base::Vertex_handle Vertex_handle; + typedef typename Base::Cell_handle Cell_handle; + + public: + typedef int Subdomain_index; + typedef std::pair Surface_patch_index; + + private: + Subdomain_index subdomain_index_; + // 0 is undefined + // -1 for infinite cells + // 1 to n for subdomains + // n + 1 for imaginary cells + std::size_t time_stamp_; + Input_cell input_cell_;//cell of input mesh, before remeshing + + public: + // To get correct cell type in TDS + template < class TDS2 > + struct Rebind_TDS + { + typedef typename Cb::template Rebind_TDS::Other Cb2; + typedef Remeshing_cell_base Other; + }; + + Remeshing_cell_base() + : subdomain_index_(0) + , time_stamp_(-1) + {} + + Remeshing_cell_base(Vertex_handle v0, + Vertex_handle v1, + Vertex_handle v2, + Vertex_handle v3) + : Base(v0, v1, v2, v3) + , subdomain_index_(0) + , time_stamp_(-1) + {} + + Remeshing_cell_base(Vertex_handle v0, + Vertex_handle v1, + Vertex_handle v2, + Vertex_handle v3, + Cell_handle n0, + Cell_handle n1, + Cell_handle n2, + Cell_handle n3) + : Base(v0, v1, v2, v3, n0, n1, n2, n3) + , subdomain_index_(0) + , time_stamp_(-1) + {} + + const Subdomain_index& subdomain_index() const + { + return subdomain_index_; + } + void set_subdomain_index(const Subdomain_index& si) + { + subdomain_index_ = si; + } + + void set_surface_patch_index(const int, const Surface_patch_index&) + {/*nothing to do because we use incident subdomain indices*/ } + + const Surface_patch_index surface_patch_index(const int& i) + { + const Subdomain_index& i1 = subdomain_index_; + const Subdomain_index& i2 = this->neighbor(i)->subdomain_index(); + if (i1 < i2) return std::make_pair(i1, i2); + else return std::make_pair(i2, i1); + } + + /// Returns true if facet lies on a surface patch + bool is_facet_on_surface(const int facet) const + { + CGAL_precondition(facet >= 0 && facet<4); + return this->subdomain_index() != this->neighbor(facet)->subdomain_index(); + } + + typedef Tag_true Has_timestamp; + std::size_t time_stamp() const { + return time_stamp_; + } + void set_time_stamp(const std::size_t& ts) { + time_stamp_ = ts; + } + + Input_cell& input_cell() { return input_cell_; } + const Input_cell& input_cell() const { return input_cell_; } + }; +}//end namespace Tetrahedral_remeshing +}//end namespace CGAL + +#endif //CGAL_TET_ADAPTIVE_REMESHING_CELL_BASE_H diff --git a/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/Remeshing_triangulation_3.h b/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/Remeshing_triangulation_3.h new file mode 100644 index 00000000000..f7a2f3223d2 --- /dev/null +++ b/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/Remeshing_triangulation_3.h @@ -0,0 +1,71 @@ +// Copyright (c) 2019 GeometryFactory (France). +// All rights reserved. +// +// This file is part of CGAL (www.cgal.org). +// You can redistribute it and/or modify it under the terms of the GNU +// General Public License as published by the Free Software Foundation, +// either version 3 of the License, or (at your option) any later version. +// +// Licensees holding a valid commercial license may use this file in +// accordance with the commercial license agreement provided with the software. +// +// This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE +// WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. +// +// $URL$ +// $Id$ +// SPDX-License-Identifier: GPL-3.0+ +// +// +// Author(s) : Jane Tournois + + +#ifndef CGAL_TETRAHEDRAL_REMESHING_TRIANGULATION_H +#define CGAL_TETRAHEDRAL_REMESHING_TRIANGULATION_H + +#include +#include +#include + +#include +#include + + +namespace CGAL +{ +namespace Tetrahedral_remeshing +{ + template > + class Remeshing_triangulation_3 + : public CGAL::Triangulation_3, + Remeshing_cell_base >::type::Cell, + Cb + > + > + > + { + typedef Remeshing_vertex_base RVb; + + typedef typename CGAL::Default::Get >::type Input_tr; + typedef typename Input_tr::Cell Input_cell; + typedef Remeshing_cell_base RCb; + + public: + typedef CGAL::Triangulation_data_structure_3 Tds; + typedef CGAL::Triangulation_3 Self; + typedef Self type; + }; + + +}//end namespace Tetrahedral_remeshing +}//end namespace CGAL + +#endif // CGAL_TETRAHEDRAL_REMESHING_TRIANGULATION_H diff --git a/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/Remeshing_vertex_base.h b/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/Remeshing_vertex_base.h new file mode 100644 index 00000000000..f9b74dd1a4f --- /dev/null +++ b/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/Remeshing_vertex_base.h @@ -0,0 +1,98 @@ +// Copyright (c) 2019 GeometryFactory (France). +// All rights reserved. +// +// This file is part of CGAL (www.cgal.org). +// You can redistribute it and/or modify it under the terms of the GNU +// General Public License as published by the Free Software Foundation, +// either version 3 of the License, or (at your option) any later version. +// +// Licensees holding a valid commercial license may use this file in +// accordance with the commercial license agreement provided with the software. +// +// This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE +// WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. +// +// $URL$ +// $Id$ +// SPDX-License-Identifier: GPL-3.0+ +// +// +// Author(s) : Jane Tournois + + +#ifndef CGAL_TET_ADAPTIVE_REMESHING_VERTEX_BASE_H +#define CGAL_TET_ADAPTIVE_REMESHING_VERTEX_BASE_H + +#include +#include + +namespace CGAL +{ +namespace Tetrahedral_remeshing +{ + namespace internal + { + class Fake_MD + { + public: + typedef int Index; + typedef int Surface_patch_index; + typedef int Subdomain_index; + }; + } + + template > + class Remeshing_vertex_base + : public CGAL::Mesh_vertex_base_3 + { + typedef CGAL::Mesh_vertex_base_3 Base; + + private: + short dimension_; + std::size_t time_stamp_; + + public: + Remeshing_vertex_base() : dimension_(-1) + // time_stamp_ // do not initialize + {} + typedef int Index; + + // To get correct vertex type in TDS + template < class TDS3 > + struct Rebind_TDS { + typedef typename Vb::template Rebind_TDS::Other Vb3; + typedef Remeshing_vertex_base Other; + }; + + // Returns the dimension of the lowest dimensional face of the input 3D + // complex that contains the vertex + int in_dimension() const { + if (dimension_ < -1) return -2 - dimension_; + else return dimension_; + } + + // Sets the dimension of the lowest dimensional face of the input 3D complex + // that contains the vertex + void set_dimension(const int dimension) { + CGAL_assertion(dimension < 4); + dimension_ = short(dimension); + } + + /// For the determinism of Compact_container iterators + ///@{ + typedef Tag_true Has_timestamp; + std::size_t time_stamp() const { + return time_stamp_; + } + void set_time_stamp(const std::size_t& ts) { + time_stamp_ = ts; + } + ///@} + + }; + +}//end namespace Tetrahedral_remeshing +}//end namespace CGAL + +#endif //CGAL_TET_ADAPTIVE_REMESHING_VERTEX_BASE_H diff --git a/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/Sizing_field.h b/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/Sizing_field.h new file mode 100644 index 00000000000..4d6cb39c01d --- /dev/null +++ b/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/Sizing_field.h @@ -0,0 +1,44 @@ +// Copyright (c) 2019 GeometryFactory (France). +// All rights reserved. +// +// This file is part of CGAL (www.cgal.org). +// You can redistribute it and/or modify it under the terms of the GNU +// General Public License as published by the Free Software Foundation, +// either version 3 of the License, or (at your option) any later version. +// +// Licensees holding a valid commercial license may use this file in +// accordance with the commercial license agreement provided with the software. +// +// This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE +// WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. +// +// $URL$ +// $Id$ +// SPDX-License-Identifier: GPL-3.0+ +// +// +// Author(s) : Jane Tournois + +#ifndef CGAL_SIZING_FIELD_H +#define CGAL_SIZING_FIELD_H + +namespace CGAL +{ + /*! + * Sizing field virtual class + */ + template + class Sizing_field + { + public: + typedef Kernel K; + typedef typename Kernel::FT FT; + typedef typename Kernel::Point_3 Point_3; + + public: + virtual FT operator()(const Point_3& p) const = 0; + }; + +}//end namespace CGAL + +#endif //CGAL_SIZING_FIELD_H diff --git a/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/Uniform_sizing_field.h b/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/Uniform_sizing_field.h new file mode 100644 index 00000000000..60e71b5783e --- /dev/null +++ b/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/Uniform_sizing_field.h @@ -0,0 +1,52 @@ +// Copyright (c) 2019 GeometryFactory (France). +// All rights reserved. +// +// This file is part of CGAL (www.cgal.org). +// You can redistribute it and/or modify it under the terms of the GNU +// General Public License as published by the Free Software Foundation, +// either version 3 of the License, or (at your option) any later version. +// +// Licensees holding a valid commercial license may use this file in +// accordance with the commercial license agreement provided with the software. +// +// This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE +// WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. +// +// $URL$ +// $Id$ +// SPDX-License-Identifier: GPL-3.0+ +// +// +// Author(s) : Jane Tournois + +#ifndef CGAL_UNIFORM_SIZING_FIELD_H +#define CGAL_UNIFORM_SIZING_FIELD_H + +#include + +namespace CGAL +{ + template + class Uniform_sizing_field : Sizing_field + { + private: + typedef Sizing_field Base; + public: + typedef typename Base::FT FT; + typedef typename Base::Point_3 Point_3; + + Uniform_sizing_field(const FT& size) + : m_size(size) + {} + + FT operator()(const Point_3&) const + { + return m_size; + } + private: + FT m_size; + }; + +}//end namespace CGAL + +#endif //CGAL_UNIFORM_SIZING_FIELD_H diff --git a/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/add_imaginary_layer.h b/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/add_imaginary_layer.h new file mode 100644 index 00000000000..ca8fc442527 --- /dev/null +++ b/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/add_imaginary_layer.h @@ -0,0 +1,248 @@ +// Copyright (c) 2019 GeometryFactory (France). +// All rights reserved. +// +// This file is part of CGAL (www.cgal.org). +// You can redistribute it and/or modify it under the terms of the GNU +// General Public License as published by the Free Software Foundation, +// either version 3 of the License, or (at your option) any later version. +// +// Licensees holding a valid commercial license may use this file in +// accordance with the commercial license agreement provided with the software. +// +// This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE +// WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. +// +// $URL$ +// $Id$ +// SPDX-License-Identifier: GPL-3.0+ +// +// +// Author(s) : Jane Tournois + +#ifndef CGAL_INTERNAL_ADD_IMAGINARY_LAYER_H +#define CGAL_INTERNAL_ADD_IMAGINARY_LAYER_H + +#include +#include + +#include + +#include +#include +#include + +namespace CGAL +{ +namespace Tetrahedral_remeshing +{ +namespace internal +{ + template + void set_labels_of_incident_cells(VertexIterator begin, + VertexIterator end, + const Tr& tr, + const int& label) + { + typedef typename Tr::Cell_handle Cell_handle; + for (VertexIterator vit = begin; vit != end; ++vit) + { + std::vector cells; + tr.finite_incident_cells(*vit, std::back_inserter(cells)); + + for (std::size_t i = 0; i < cells.size(); ++i) + cells[i]->set_subdomain_index(label); + } + } + + template + void set_dimension(VertexIterator begin, + VertexIterator end, + const short& dimension) + { + for (VertexIterator vit = begin; vit != end; ++vit) + (*vit)->set_dimension(dimension); + } + + template + OutputIterator insert_points(PointIterator begin, + PointIterator end, + Tr& tr, + OutputIterator oit) + { + CGAL_assertion(tr.is_valid()); + int i = 1; + for (PointIterator pit = begin; pit != end; ++pit, ++i) + { + *oit++ = tr.insert(*pit); + } + CGAL_assertion(tr.is_valid()); + +#ifdef CGAL_TETRAHEDRAL_REMESHING_VERBOSE + std::cout << "(" << i << " points inserted successfully)" << std::endl; +#endif + + return oit; + } + + template + OutputIterator compute_offset_points(const VertexNormalsMap& normals, + const double& offset, + OutputIterator oit) + { +#ifdef CGAL_TETRAHEDRAL_REMESHING_DEBUG + std::ofstream ofs("imaginary_points.off"); + ofs << "OFF" << std::endl; + ofs << normals.size() << " 0 0" << std::endl; +#endif + + for (typename VertexNormalsMap::const_iterator nit = normals.begin(); + nit != normals.end(); ++nit) + { + *oit++ = (*nit).first->point() + offset * (*nit).second; + +#ifdef CGAL_TETRAHEDRAL_REMESHING_DEBUG + ofs << ((*nit).first->point() + offset * (*nit).second) << std::endl; +#endif + } + +#ifdef CGAL_TETRAHEDRAL_REMESHING_DEBUG + ofs.close(); +#endif + return oit; + } + + template + void compute_normals_on_convex_hull(const T3& tr, + VertexNormalsMap& normals) + { +#ifdef CGAL_TETRAHEDRAL_REMESHING_DEBUG + std::ofstream ofs("imaginary_normals.xyz"); +#endif + namespace PMP = CGAL::Polygon_mesh_processing; + + typedef typename T3::Geom_traits Gt; + typedef typename Gt::Vector_3 Vector_3; + const Gt& gt = tr.geom_traits(); + + typedef typename T3::Vertex_handle Vertex_handle; + typedef typename T3::Facet Facet; + typedef typename T3::Finite_facets_iterator Finite_facets_iterator; + + boost::unordered_map fnormals; + for (Finite_facets_iterator fit = tr.finite_facets_begin(); + fit != tr.finite_facets_end(); + ++fit) + { + Facet f = *fit; + if (tr.is_infinite(f.first)) + { + f = tr.mirror_facet(f); + fnormals.insert(std::make_pair(f, normal(f, gt))); + } + else if (tr.is_infinite(f.first->neighbor(f.second))) + fnormals.insert(std::make_pair(f, normal(f, gt))); + } + + std::vector vertices; + tr.finite_adjacent_vertices(tr.infinite_vertex(), + std::back_inserter(vertices)); + for (std::size_t i = 0; i < vertices.size(); ++i) + { + Vertex_handle vi = vertices[i]; + std::vector inc_facets; + tr.finite_incident_facets(vi, std::back_inserter(inc_facets)); + + Vector_3 ni = gt.construct_vector_3_object()(CGAL::NULL_VECTOR); + for (std::size_t j = 0; j < inc_facets.size(); ++j) + { + typename boost::unordered_map::iterator + fnit = fnormals.find(inc_facets[j]); + if (fnit != fnormals.end()) + ni = gt.construct_sum_of_vectors_3_object()(ni, fnit->second); + else + { + //check for mirror_facet + fnit = fnormals.find(tr.mirror_facet(inc_facets[j])); + if (fnit != fnormals.end()) + ni = gt.construct_sum_of_vectors_3_object()(ni, fnit->second); + } + } + + if (!typename Gt::Equal_3()(ni, CGAL::NULL_VECTOR)) + { + ni = gt.construct_opposite_vector_3_object()(ni); + PMP::internal::normalize(ni, gt); + normals.insert(std::make_pair(vi, ni)); +#ifdef CGAL_TETRAHEDRAL_REMESHING_DEBUG + ofs << vi->point() << " " << ni << std::endl; +#endif + } + } +#ifdef CGAL_TETRAHEDRAL_REMESHING_DEBUG + ofs.close(); +#endif + } + + template + double compute_bbox_max_size(const Tr& tr) + { + typename Tr::Finite_vertices_iterator vit = tr.finite_vertices_begin(); + const typename Tr::Point& p = vit->point(); + CGAL::Bbox_3 bbox = p.bbox(); + ++vit; + for ( ; vit != tr.finite_vertices_end(); ++vit) + { + bbox = bbox + vit->point().bbox(); + } + + return (std::max)((std::max)(bbox.xmax() - bbox.xmin(), + bbox.ymax() - bbox.ymin()), + bbox.zmax() - bbox.zmin()); + + } + + template + void add_layer_of_imaginary_tets(T3& tr, const Index& imaginary_index) + { + typedef typename T3::Geom_traits Gt; + typedef typename Gt::Point_3 Point_3; + typedef typename Gt::Vector_3 Vector_3; + + typedef typename T3::Vertex_handle Vertex_handle; + + //compute normals + boost::unordered_map normals; + compute_normals_on_convex_hull(tr, normals); + + //compute bbox max size + const double& offset = 0.04 * compute_bbox_max_size(tr); + + //compute points to be inserted + std::vector offset_points; + compute_offset_points(normals, + offset, + std::back_inserter(offset_points)); + + //insert vertices on offset + //note we only need to insert them in the T3, because they + //are all outside convex hull. The rest of the T3 will not be modified + std::vector offset_vertices; + insert_points(offset_points.begin(), offset_points.end(), + tr, std::back_inserter(offset_vertices)); + + CGAL_assertion(tr.is_valid()); + + //set labels + set_labels_of_incident_cells(offset_vertices.begin(), + offset_vertices.end(), + tr, + imaginary_index); + + set_dimension(offset_vertices.begin(), offset_vertices.end(), 3); + } + +}//end namespace internal +}//end namespace Tetrahedral_remeshing +}//end namesapce CGAL + +#endif diff --git a/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/collapse_short_edges.h b/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/collapse_short_edges.h new file mode 100644 index 00000000000..ef3470aa616 --- /dev/null +++ b/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/collapse_short_edges.h @@ -0,0 +1,1030 @@ +// Copyright (c) 2019 GeometryFactory (France). +// All rights reserved. +// +// This file is part of CGAL (www.cgal.org). +// You can redistribute it and/or modify it under the terms of the GNU +// General Public License as published by the Free Software Foundation, +// either version 3 of the License, or (at your option) any later version. +// +// Licensees holding a valid commercial license may use this file in +// accordance with the commercial license agreement provided with the software. +// +// This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE +// WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. +// +// $URL$ +// $Id$ +// SPDX-License-Identifier: GPL-3.0+ +// +// +// Author(s) : Jane Tournois + +#ifndef CGAL_INTERNAL_COLLAPSE_SHORT_EDGES_H +#define CGAL_INTERNAL_COLLAPSE_SHORT_EDGES_H + +#include +#include +#include +#include +#include +#include + +#include + +#include +#include + +#include + + +namespace CGAL +{ +namespace Tetrahedral_remeshing +{ +namespace internal +{ + enum Edge_type { FEATURE, BOUNDARY, INSIDE, MIXTE, + NO_COLLAPSE, INVALID, IMAGINARY, MIXTE_IMAGINARY, HULL_EDGE }; + enum Collapse_type { TO_MIDPOINT, TO_V0, TO_V1, IMPOSSIBLE }; + enum Result_type { VALID, + V_PROBLEM, C_PROBLEM, E_PROBLEM, + TOPOLOGICAL_PROBLEM, ORIENTATION_PROBLEM, SHARED_NEIGHBOR_PROBLEM }; + + template + class CollapseTriangulation + { + typedef typename C3t3::Triangulation Tr; + typedef typename C3t3::Edge Edge; + typedef typename C3t3::Cell_handle Cell_handle; + typedef typename C3t3::Vertex_handle Vertex_handle; + typedef typename C3t3::Subdomain_index Subdomain_index; + typedef typename C3t3::Triangulation::Point Point_3; + typedef typename C3t3::Triangulation::Geom_traits::Vector_3 Vector_3; + + typedef CGAL::Triangulation_incremental_builder_3 Builder; + + public: + CollapseTriangulation(const C3t3& c3t3, + const Edge& edge, + Collapse_type _collapse_type) + { + v0_init = edge.first->vertex(edge.second); + v1_init = edge.first->vertex(edge.third); + + std::vector vertices_to_insert; + c3t3.triangulation().finite_incident_vertices(v0_init, + std::back_inserter(vertices_to_insert)); + vertices_to_insert.push_back(v0_init); + c3t3.triangulation().finite_incident_vertices(v1_init, + std::back_inserter(vertices_to_insert)); + + // create incremental builder + Builder builder(triangulation, true); + builder.begin_triangulation(3); + + collapse_type = _collapse_type; + + //To add the vertices only once + for (unsigned int i = 0; i < vertices_to_insert.size(); i++) + { + const Vertex_handle vh = vertices_to_insert[i]; + if (v2v.left.find(vh) == v2v.left.end()) + { + Vertex_handle new_vh = builder.add_vertex(); + new_vh->set_point(vh->point()); + new_vh->set_dimension(vh->in_dimension()); + + v2v.left.insert(std::make_pair(vh, new_vh)); + } + } + + std::vector cells_to_insert; + c3t3.triangulation().finite_incident_cells(v0_init, std::back_inserter(cells_to_insert)); + c3t3.triangulation().finite_incident_cells(v1_init, std::back_inserter(cells_to_insert)); + + //To add the cells only once + for (unsigned int i = 0; i < cells_to_insert.size(); i++) + { + const Cell_handle ch = cells_to_insert[i]; + if (c2c.left.find(ch) == c2c.left.end()) + { + Cell_handle new_ch = builder.add_cell(v2v.left.at(ch->vertex(0)), v2v.left.at(ch->vertex(1)), + v2v.left.at(ch->vertex(2)), v2v.left.at(ch->vertex(3))); + new_ch->set_subdomain_index(ch->subdomain_index()); + new_ch->info() = ch->info(); + + c2c.left.insert(std::make_pair(ch, new_ch)); + } + } + + // finished + builder.end_triangulation(); + } + + void update() + { + vh0 = v2v.left.at(v0_init); + vh1 = v2v.left.at(v1_init); + + Cell_handle ch; + int i0, i1; + not_an_edge = true; + if (triangulation.is_edge(vh0, vh1, ch, i0, i1)) + { + edge = Edge(ch, i0, i1); + not_an_edge = false; + } + + to_remove.clear(); + sharing_neighbor.clear(); + + typedef typename Tr::Cell_circulator Cell_circulator; + Cell_circulator circ = triangulation.incident_cells(edge); + Cell_circulator done = circ; + do + { + to_remove[circ] = true; + if (circ->neighbor(circ->index(vh0))->has_neighbor(circ->neighbor(circ->index(vh1)))) + { + sharing_neighbor[circ->neighbor(circ->index(vh0))] = true; + sharing_neighbor[circ->neighbor(circ->index(vh1))] = true; + } + } while (++circ != done); + + collapsed = false; + } + + Result_type collapse() + { + if (not_an_edge) + { + std::cout << "LocalTriangulation::Not an edge..." << std::endl; + return E_PROBLEM; + } + else + { + Vector_3 v0_new_pos = vec(vh0->point()); + + if (collapse_type == TO_MIDPOINT){ + v0_new_pos = v0_new_pos + 0.5 * Vector_3(vh0->point(), vh1->point()); + } + else if (collapse_type == TO_V1){ + v0_new_pos = vec(vh1->point()); + } + + boost::unordered_set invalid_cells; + + typedef typename Tr::Cell_circulator Cell_circulator; + Cell_circulator circ = triangulation.incident_cells(edge); + Cell_circulator done = circ; + + std::vector cells_to_remove; + + //Update the vertex before removing it + std::vector find_incident; + triangulation.incident_cells(vh0, std::back_inserter(find_incident)); + + std::vector cells_to_update; + triangulation.incident_cells(vh1, std::back_inserter(cells_to_update)); + +// Result_type r = VALID; + do + { + int v0_id = circ->index(vh0); + int v1_id = circ->index(vh1); + + Cell_handle n0_ch = circ->neighbor(v0_id); + Cell_handle n1_ch = circ->neighbor(v1_id); + + int ch_id_in_n0 = n0_ch->index(circ); + int ch_id_in_n1 = n1_ch->index(circ); + +// if (n0_ch->has_neighbor(n1_ch)) +// r = SHARED_NEIGHBOR_PROBLEM; + + //Update neighbors before removing cell + n0_ch->set_neighbor(ch_id_in_n0, n1_ch); + n1_ch->set_neighbor(ch_id_in_n1, n0_ch); + + Subdomain_index si_n0 = n0_ch->subdomain_index(); + Subdomain_index si_n1 = n1_ch->subdomain_index(); + Subdomain_index si = circ->subdomain_index(); + + if (si_n0 != si && si_n1 != si) + return TOPOLOGICAL_PROBLEM; + + if ( triangulation.is_infinite(n0_ch->vertex(ch_id_in_n0)) + && triangulation.is_infinite(n1_ch->vertex(ch_id_in_n1))) + return TOPOLOGICAL_PROBLEM; + + if ( triangulation.is_infinite(n0_ch) + && triangulation.is_infinite(n1_ch) + && !triangulation.is_infinite(circ)) + return TOPOLOGICAL_PROBLEM; + + cells_to_remove.push_back(circ); + + invalid_cells.insert(circ); + + } while (++circ != done); + + + vh0->set_point(Point_3(v0_new_pos.x(), v0_new_pos.y(), v0_new_pos.z())); + vh1->set_point(Point_3(v0_new_pos.x(), v0_new_pos.y(), v0_new_pos.z())); + + Vertex_handle infinite_vertex = triangulation.infinite_vertex(); + + bool v0_updated = false; + for (unsigned int i = 0; i < find_incident.size(); i++) + { + const Cell_handle ch = find_incident[i]; + if (invalid_cells.find(ch) == invalid_cells.end()) //valid cell + { + if (triangulation.is_infinite(ch)) + infinite_vertex->set_cell(ch); + else { + vh0->set_cell(ch); + v0_updated = true; + } + } + } + + //Update the vertex before removing it + for (unsigned int i = 0; i < cells_to_update.size(); i++) + { + Cell_handle & ch = cells_to_update[i]; + + if (invalid_cells.find(ch) == invalid_cells.end()) //valid cell + { + ch->set_vertex(ch->index(vh1), vh0); + + if (triangulation.is_infinite(ch)) + infinite_vertex->set_cell(ch); + else { + if (!v0_updated) { + vh0->set_cell(ch); + v0_updated = true; + } + } + } + } + + if (!v0_updated){ + std::cout << "CollapseTriangulation::PB i cell not valid!!!" << std::endl; + return V_PROBLEM; + } + triangulation.tds().delete_vertex(vh1); + + //Removing cells + for (unsigned int i = 0; i < cells_to_remove.size(); i++){ + triangulation.tds().delete_cell(cells_to_remove[i]); + } + + typedef typename Tr::Finite_cells_iterator Finite_cells_iterator; + for (Finite_cells_iterator cit = triangulation.finite_cells_begin(); + cit != triangulation.finite_cells_end(); ++cit) + { + if (!is_well_oriented(cit)) + return ORIENTATION_PROBLEM; + } + + typedef typename Tr::Cell_iterator Cell_iterator; + for (Cell_iterator cit = triangulation.cells_begin(); + cit != triangulation.cells_end(); ++cit) + { + if (!triangulation.tds().is_valid(cit, true)) + return C_PROBLEM; + } + + typedef typename Tr::Vertex_iterator Vertex_iterator; + for (Vertex_iterator vit = triangulation.vertices_begin(); + vit != triangulation.vertices_end(); ++vit) + { + if (!triangulation.tds().is_valid(vit, true)) + return V_PROBLEM; + } + + //int si_nb_vh0 = nb_incident_subdomains(vh0, c3t3); + //int si_nb_vh1 = nb_incident_subdomains(vh1, c3t3); + //int vertices_subdomain_nb_vh0 = std::max(si_nb_vh0, si_nb_vh1); + //bool is_on_hull_vh0 = is_on_hull(vh0, c3t3) || is_on_hull(vh1, c3t3); + + //if( is_valid_for_domains() ) + return VALID; + + // return TOPOLOGICAL_PROBLEM; + } + } + + protected: + + Vector_3 vec(const Point_3& p) + { + return Vector_3(p.x(), p.y(), p.z()); + } + + Tr triangulation; + boost::bimap v2v;/*vertex of main tr - vertex of collapse tr*/ + boost::bimap c2c;/*cell of main tr - cell of collapse tr*/ + + boost::unordered_map to_remove; //default is false + boost::unordered_map sharing_neighbor;//default is false + + Collapse_type collapse_type; + + Vertex_handle v0_init; + Vertex_handle v1_init; + + Vertex_handle vh0; + Vertex_handle vh1; + + Edge edge; + + bool collapsed; + bool not_an_edge; + }; + + + template + Collapse_type get_collapse_type(const typename C3t3::Edge& edge, + const C3t3& c3t3, + CellSelector cell_selector) + { + bool update_v0 = false; + bool update_v1 = false; + helpers::get_edge_info(edge, update_v0, update_v1, c3t3, cell_selector); + + if (update_v0 && update_v1) return TO_MIDPOINT; + else if (update_v0) return TO_V1; + else if (update_v1) return TO_V0; + else return IMPOSSIBLE; + } + + template + Edge_type get_edge_type(const typename C3t3::Edge& edge, + const C3t3& c3t3) + { + typedef typename C3t3::Vertex_handle Vertex_handle; + typedef typename C3t3::Triangulation::Cell_circulator Cell_circulator; + typedef typename C3t3::Subdomain_index Subdomain_index; + + const Vertex_handle & v0 = edge.first->vertex(edge.second); + const Vertex_handle & v1 = edge.first->vertex(edge.third); + + int dim0 = c3t3.in_dimension(v0); + int dim1 = c3t3.in_dimension(v1); + + bool is_v0_on_hull = is_on_hull(v0, c3t3); + bool is_v1_on_hull = is_on_hull(v1, c3t3); + + if (dim0 == 3 && dim1 == 3) + { + if (is_v0_on_hull && is_v1_on_hull) + { + Cell_circulator circ = c3t3.triangulation().incident_cells(edge); + Cell_circulator done = circ; + do + { + if (c3t3.triangulation().is_infinite(circ)) + return HULL_EDGE; + } + while (++circ != done); + return NO_COLLAPSE; + } + else if (is_v0_on_hull || is_v1_on_hull) + { + return MIXTE_IMAGINARY; + } + return INSIDE; + } + + if (dim0 == 2 && dim1 == 2) + { + Cell_circulator circ = c3t3.triangulation().incident_cells(edge); + Cell_circulator done = circ; + + std::vector indices; + do + { + Subdomain_index current_si = circ->subdomain_index(); + + if (std::find(indices.begin(), indices.end(), current_si) == indices.end()){ + indices.push_back(current_si); + } + + Subdomain_index si_n = circ->neighbor(circ->index(v0))->subdomain_index(); + if (si_n == + circ->neighbor(circ->index(v1))->subdomain_index() && si_n != current_si){ + return NO_COLLAPSE; + } + + } + while (++circ != done); + + std::size_t nb_si_v0 = nb_incident_subdomains(v0, c3t3); + std::size_t nb_si_v1 = nb_incident_subdomains(v1, c3t3); + + if (indices.size() >= (std::min)(nb_si_v0, nb_si_v1)){ + return BOUNDARY; + } + + return NO_COLLAPSE; + } + + if (dim0 == 3 && dim1 == 2) + { + if (is_v0_on_hull) + return NO_COLLAPSE; + return MIXTE; + } + + if (dim1 == 3 && dim0 == 2) + { + if (is_v1_on_hull) + return NO_COLLAPSE; + return MIXTE; + } + + //std::cerr << "ERROR : get_edge_type did not return anything valid!" << std::endl; + return NO_COLLAPSE; + } + + template + bool is_valid_collapse(const typename C3t3::Edge& edge, + const C3t3& c3t3) + { + typedef typename C3t3::Vertex_handle Vertex_handle; + typedef typename C3t3::Cell_handle Cell_handle; + typedef typename C3t3::Triangulation::Cell_circulator Cell_circulator; + + const Vertex_handle v0 = edge.first->vertex(edge.second); + const Vertex_handle v1 = edge.first->vertex(edge.third); + + Cell_circulator circ = c3t3.triangulation().incident_cells(edge); + Cell_circulator done = circ; + do + { + int v0_id = circ->index(v0); + int v1_id = circ->index(v1); + + Cell_handle n0_ch = circ->neighbor(v0_id); + Cell_handle n1_ch = circ->neighbor(v1_id); + + if ( n0_ch->has_vertex(v0) + || n1_ch->has_vertex(v1) + || n0_ch->has_neighbor(n1_ch)) + return false; + } + while (++circ != done); + + return true; + } + + template + bool is_valid_collapse(const typename C3t3::Edge& edge, + const Collapse_type& collapse_type, + const typename C3t3::Triangulation::Point& new_pos, + const C3t3& c3t3, + const bool /*protect_boundaries*/, + const typename C3t3::Subdomain_index& /*imaginary_index*/, + CellSelector cell_selector) + { + typedef typename C3t3::Vertex_handle Vertex_handle; + typedef typename C3t3::Cell_handle Cell_handle; + typedef typename C3t3::Triangulation::Point Point; + + Vertex_handle v0 = edge.first->vertex(edge.second); + Vertex_handle v1 = edge.first->vertex(edge.third); + + ////about protection of boundaries + //if (protect_boundaries) + //{ + // if (c3t3.is_in_complex(edge) + // || helpers::is_boundary(c3t3, edge, cell_selector)) + // return false; + //} + //we need to check that surfaces are not broken anyhow + bool v0_boundary = helpers::is_boundary_vertex(v0, c3t3, cell_selector); + bool v1_boundary = helpers::is_boundary_vertex(v1, c3t3, cell_selector); + if (collapse_type == TO_V0 && v1_boundary && !v0_boundary) + return false; + if (collapse_type == TO_V1 && v0_boundary && !v1_boundary) + return false; + if (collapse_type == TO_MIDPOINT && (v0_boundary ^ v1_boundary))//both or none to allow collapse + return false; + + std::vector cells_to_check; + if (collapse_type == TO_V1 || collapse_type == TO_MIDPOINT) + { + c3t3.triangulation().finite_incident_cells(v0, + std::back_inserter(cells_to_check)); + + for (std::size_t i = 0; i < cells_to_check.size(); i++) + { + const Cell_handle& ch = cells_to_check[i]; + if (!ch->has_vertex(v1)) + { + //check orientation + boost::array pts = { ch->vertex(0)->point(), + ch->vertex(1)->point(), + ch->vertex(2)->point(), + ch->vertex(3)->point()}; + pts[ch->index(v0)] = new_pos; + if (CGAL::orientation(pts[0], pts[1], pts[2], pts[3]) != CGAL::POSITIVE) + return false; + } + } + cells_to_check.clear(); + } + else if (collapse_type == TO_V0 || collapse_type == TO_MIDPOINT) + { + c3t3.triangulation().finite_incident_cells(v1, + std::back_inserter(cells_to_check)); + + for (std::size_t i = 0; i < cells_to_check.size(); i++) + { + const Cell_handle& ch = cells_to_check[i]; + if (!ch->has_vertex(v0)) + { + //check orientation + boost::array pts = { ch->vertex(0)->point(), + ch->vertex(1)->point(), + ch->vertex(2)->point(), + ch->vertex(3)->point() }; + pts[ch->index(v1)] = new_pos; + if (CGAL::orientation(pts[0], pts[1], pts[2], pts[3]) != CGAL::POSITIVE) + return false; + } + } + cells_to_check.clear(); + } + + return is_valid_collapse(edge, c3t3); + } + + template + bool are_edge_lengths_valid(const typename C3t3::Vertex_handle v1, + const typename C3t3::Vertex_handle v2, + const C3t3& c3t3, + const typename C3t3::Triangulation::Point& new_pos, + SqLengthMap& edges_sqlength, + const typename C3t3::Triangulation::Geom_traits::FT& sqhigh, + const typename C3t3::Subdomain_index& imaginary_index, + const bool /* adaptive */ = false) + { + //SqLengthMap::key_type is Vertex_handle + //SqLengthMap::value_type is double + typedef typename C3t3::Edge Edge; + typedef typename C3t3::Vertex_handle Vertex_handle; + + std::vector inc_edges; + c3t3.triangulation().finite_incident_edges(v1, + std::back_inserter(inc_edges)); + + for (std::size_t i = 0; i < inc_edges.size(); i++) + { + const Edge& ei = inc_edges[i]; + + if (is_imaginary(ei, c3t3, imaginary_index)) //should we also test outside cells? + continue; + + Vertex_handle ivh = ei.first->vertex(ei.second); + if (ivh == v1) + ivh = ei.first->vertex(ei.third); + + if (v2 != ivh && edges_sqlength.find(ivh) == edges_sqlength.end()) + { + double sqlen_i = CGAL::squared_distance(new_pos, ivh->point()); + + //if (adaptive){ + // if (is_boundary_edge(ei) || is_hull_edge(ei)){ + // if (sqlen_i > split_length) + // return false; + // } + // else if (sqlen_i > 4.*getAimedLength(ei, aimed_length) / 3.){// && is_in_complex(ei) ){ + // return false; + // } + //} + //else { + if (sqlen_i > sqhigh) { + return false; + } + //} + + edges_sqlength[ivh] = sqlen_i; + } + } + + return true; + } + + template + bool are_edge_lengths_valid(const typename C3t3::Edge& edge, + const C3t3& c3t3, + const Collapse_type& collapse_type, + const typename C3t3::Triangulation::Point& new_pos, + SqLengthMap& edges_sqlength, + const typename C3t3::Triangulation::Geom_traits::FT& sqhigh, + const typename C3t3::Subdomain_index& imaginary_index, + const bool adaptive = false) + { + //SqLengthMap::key_type is Vertex_handle + //SqLengthMap::value_type is double + + typedef typename C3t3::Vertex_handle Vertex_handle; + + edges_sqlength.clear(); + Vertex_handle v0 = edge.first->vertex(edge.second); + Vertex_handle v1 = edge.first->vertex(edge.third); + + if (collapse_type == TO_V1 || collapse_type == TO_MIDPOINT) + { + if (!are_edge_lengths_valid(v0, v1, c3t3, new_pos, + edges_sqlength, sqhigh, imaginary_index, adaptive)) + return false; + } + else if (collapse_type == TO_V0 || collapse_type == TO_MIDPOINT) + { + if (!are_edge_lengths_valid(v1, v0, c3t3, new_pos, + edges_sqlength, sqhigh, imaginary_index, adaptive)) + return false; + } + return true; + } + + template + typename C3t3::Vertex_handle + collapse(const typename C3t3::Cell_handle ch, const int to, const int from, + C3t3& c3t3) + { + typedef typename C3t3::Vertex_handle Vertex_handle; + typedef typename C3t3::Cell_handle Cell_handle; + typedef typename C3t3::Triangulation Tr; + typedef typename Tr::Cell_circulator Cell_circulator; + + Tr& tr = c3t3.triangulation(); + + Vertex_handle vh0 = ch->vertex(to); + Vertex_handle vh1 = ch->vertex(from); + + std::vector cells_to_remove; + + //Update the vertex before removing it + std::vector find_incident; + tr.incident_cells(vh0, std::back_inserter(find_incident)); + + std::vector cells_to_update; + tr.incident_cells(vh1, std::back_inserter(cells_to_update)); + +// if (vh1->in_dimension() == 2 && c3t3.is_in_complex(vh1)) +// std::cout << "Collapsing a feature vertex!!!!!!" << std::endl; + + boost::unordered_set invalid_cells; + bool valid = true; + Cell_circulator circ = tr.incident_cells(ch, to, from); + Cell_circulator done = circ; + do + { + int v0_id = circ->index(vh0); + int v1_id = circ->index(vh1); + + Cell_handle n0_ch = circ->neighbor(v0_id); + Cell_handle n1_ch = circ->neighbor(v1_id); + + int ch_id_in_n0 = n0_ch->index(circ); + int ch_id_in_n1 = n1_ch->index(circ); + + //Update neighbors before removing cell + n0_ch->set_neighbor(ch_id_in_n0, n1_ch); + n1_ch->set_neighbor(ch_id_in_n1, n0_ch); + + //Update vertices cell pointer + //if( !triangulation.is_infinite( n0_ch ) ) + int nb_on_boundary_n0 = 0; + for (int i = 0; i < 3; i++) + { + int vid = Tr::vertex_triple_index(ch_id_in_n0, i); + n0_ch->vertex(vid)->set_cell(n0_ch); + if (c3t3.in_dimension(n0_ch->vertex(vid))) + nb_on_boundary_n0++; + } + //else + int nb_on_boundary_n1 = 0; + for (int i = 0; i < 3; i++) + { + int vid = Tr::vertex_triple_index(ch_id_in_n1, i); + n1_ch->vertex(vid)->set_cell(n1_ch); + if (c3t3.in_dimension(n1_ch->vertex(vid))) + nb_on_boundary_n1++; + } + + if ( tr.is_infinite(n0_ch->vertex(ch_id_in_n0)) + && tr.is_infinite(n1_ch->vertex(ch_id_in_n1))) + return Vertex_handle(); + + cells_to_remove.push_back(circ); + + invalid_cells.insert(circ); + + } while (++circ != done); + + Vertex_handle infinite_vertex = tr.infinite_vertex(); + + bool v0_updated = false; + for (std::size_t i = 0; i < find_incident.size(); ++i) + { + const Cell_handle ch = find_incident[i]; + if (invalid_cells.find(ch) == invalid_cells.end())//valid cell + { + if (tr.is_infinite(ch)) + infinite_vertex->set_cell(ch); + //else { + vh0->set_cell(ch); + v0_updated = true; + //} + } + } + + //Update the vertex before removing it + for (std::size_t i = 0; i < cells_to_update.size(); ++i) + { + Cell_handle ch = cells_to_update[i]; + + if (invalid_cells.find(ch) == invalid_cells.end()) //valid cell + { + ch->set_vertex(ch->index(vh1), vh0); + + if (tr.is_infinite(ch)) + infinite_vertex->set_cell(ch); + //else { + if (!v0_updated) { + vh0->set_cell(ch); + v0_updated = true; + } + //} + } + } + + if (!v0_updated) + std::cout << "PB i cell not valid!!!" << std::endl; + c3t3.triangulation().tds().delete_vertex(vh1); + + //Removing cells + for (std::size_t i = 0; i < cells_to_remove.size(); i++) + { + if (cells_to_remove[i]->subdomain_index() > 0) + c3t3.remove_from_complex(cells_to_remove[i]); + c3t3.triangulation().tds().delete_cell(cells_to_remove[i]); + } + + if (!valid){ + std::cout << "Global triangulation collapse bug!!" << std::endl; + return Vertex_handle(); + } + + return vh0; + } + + + template + typename C3t3::Vertex_handle collapse(typename C3t3::Edge& edge, + const Collapse_type& collapse_type, + C3t3& c3t3) + { + typedef typename C3t3::Vertex_handle Vertex_handle; + typedef typename C3t3::Triangulation::Point Point_3; + + Vertex_handle vh0 = edge.first->vertex(edge.second); + Vertex_handle vh1 = edge.first->vertex(edge.third); + + int dim_vh0 = c3t3.in_dimension(vh0); + int dim_vh1 = c3t3.in_dimension(vh1); + + Vertex_handle vh = Vertex_handle(); + + Point_3 p0 = vh0->point(); + Point_3 p1 = vh1->point(); + + //Collapse at mid point + if (collapse_type == TO_MIDPOINT) + { + Point_3 new_position = CGAL::midpoint(vh0->point(), vh1->point()); + vh0->set_point(new_position); + vh1->set_point(new_position); + + vh = collapse(edge.first, edge.second, edge.third, c3t3); + c3t3.set_dimension(vh, std::min(dim_vh0, dim_vh1)); + } + else //Collapse at vertex + { + if (collapse_type == TO_V1) + { + vh0->set_point(p1); + vh = collapse(edge.first, edge.third, edge.second, c3t3); + c3t3.set_dimension(vh, std::min(dim_vh0, dim_vh1)); + } + else //Collapse at v0 + { + if (collapse_type == TO_V0) + { + vh1->set_point(p0); + vh = collapse(edge.first, edge.second, edge.third, c3t3); + c3t3.set_dimension(vh, std::min(dim_vh0, dim_vh1)); + } + else + CGAL_assertion(false); + } + } + return vh; + } + + template + typename C3t3::Vertex_handle collapse_edge(typename C3t3::Edge& edge, + C3t3& c3t3, + const typename C3t3::Triangulation::Geom_traits::FT& sqhigh, + const bool protect_boundaries, + const typename C3t3::Subdomain_index& imaginary_index, + CellSelector cell_selector) + { + typedef typename C3t3::Triangulation Tr; + typedef typename Tr::Point Point; + typedef typename Tr::Vertex_handle Vertex_handle; + + Vertex_handle v0 = edge.first->vertex(edge.second); + Vertex_handle v1 = edge.first->vertex(edge.third); + + Collapse_type collapse_type = get_collapse_type(edge, c3t3, cell_selector); + Edge_type edge_type = get_edge_type(edge, c3t3); + + if (collapse_type != IMPOSSIBLE && edge_type != NO_COLLAPSE) + { + Point new_pos; + switch(collapse_type) + { + case TO_V0: + new_pos = v0->point(); break; + case TO_V1: + new_pos = v1->point(); break; + default: + CGAL_assertion(collapse_type == TO_MIDPOINT); + new_pos = CGAL::midpoint(v0->point(), v1->point()); + } + + boost::unordered_map edges_sqlength_after_collapse; + if (is_valid_collapse(edge, collapse_type, new_pos, c3t3, + protect_boundaries, imaginary_index, cell_selector)) + { + if (are_edge_lengths_valid(edge, c3t3, collapse_type, new_pos, + edges_sqlength_after_collapse, sqhigh, + imaginary_index /*, adaptive = false*/)) + { + CollapseTriangulation local_tri(c3t3, edge, collapse_type); + local_tri.update(); + + Result_type res = local_tri.collapse(); + if (res == VALID) + return collapse(edge, collapse_type, c3t3); + } + } + } + + return Vertex_handle(); + } + + template + bool can_be_collapsed(const typename C3T3::Edge& e, + const C3T3& c3t3, + const bool protect_boundaries, + const typename C3T3::Subdomain_index& imaginary_index, + CellSelector cell_selector) + { +#ifdef CGAL_LIMITED_APERTURE_EDGE_SELECTION + if (CGAL::helpers::is_on_the_outer_box(e, c3t3, imaginary_index)) + return true; +#endif + + if (is_outside(e, c3t3, imaginary_index, cell_selector)) + return false; + if (is_imaginary(e, c3t3, imaginary_index)) + return false; + + if (protect_boundaries) + { + if (c3t3.is_in_complex(e)) + return false; + else if (helpers::is_boundary(c3t3, e, cell_selector)) + return false; + +#ifdef CGAL_TETRAHEDRAL_REMESHING_DEBUG + if (!is_inside(e, c3t3, imaginary_index, cell_selector)) + { + std::cerr << "e is not inside!?" << std::endl; + typename C3T3::Vertex_handle v1 = e.first->vertex(e.second); + typename C3T3::Vertex_handle v2 = e.first->vertex(e.third); + std::cerr << v1->point() << " " << v2->point() << std::endl; + } +#endif + + CGAL_assertion(is_inside(e, c3t3, imaginary_index, cell_selector)); + return true; + } + else + { + return true; + } + } + + template + void collapse_short_edges(C3T3& c3t3, + const typename C3T3::Triangulation::Geom_traits::FT& low, + const typename C3T3::Triangulation::Geom_traits::FT& high, + const bool protect_boundaries, + const typename C3T3::Subdomain_index& imaginary_index, + CellSelector cell_selector) + { + typedef typename C3T3::Triangulation T3; + typedef typename T3::Cell_handle Cell_handle; + typedef typename T3::Edge Edge; + typedef typename T3::Finite_edges_iterator Finite_edges_iterator; + typedef typename T3::Vertex_handle Vertex_handle; + typedef typename std::pair Edge_vv; + + typedef typename T3::Geom_traits::FT FT; + typedef boost::bimap< + boost::bimaps::set_of, + boost::bimaps::multiset_of > > Boost_bimap; + typedef typename Boost_bimap::value_type short_edge; + +#ifdef CGAL_TETRAHEDRAL_REMESHING_VERBOSE + std::cout << "Collapse short edges (" << low << ", " << high << ")..."; + std::cout.flush(); + std::size_t nb_collapses = 0; +#endif + const FT sq_low = low*low; + const FT sq_high = high*high; + + //collect long edges + T3& tr = c3t3.triangulation(); + Boost_bimap short_edges; + for (Finite_edges_iterator eit = tr.finite_edges_begin(); + eit != tr.finite_edges_end(); ++eit) + { + Edge e = *eit; + if (!can_be_collapsed(e, c3t3, protect_boundaries, imaginary_index, cell_selector)) + continue; + + double sqlen = tr.segment(e).squared_length(); + if (sqlen < sq_low) + short_edges.insert(short_edge(make_vertex_pair(e), sqlen)); + } + +#ifdef CGAL_TETRAHEDRAL_REMESHING_DEBUG + helpers::dump_edges(short_edges, "short_edges.polylines.txt"); +#endif + + while(!short_edges.empty()) + { + //the edge with shortest length + typename Boost_bimap::right_map::iterator eit = short_edges.right.begin(); + Edge_vv e = eit->second; + short_edges.right.erase(eit); + +#ifdef CGAL_TETRAHEDRAL_REMESHING_VERBOSE_PROGRESS + std::cout << "\rCollapse... (" << short_edges.left.size() << " short edges, "; + std::cout << nb_collapses << " collapses)"; + std::cout.flush(); +#endif + Cell_handle cell; + int i1, i2; + if ( tr.tds().is_vertex(e.first) + && tr.tds().is_vertex(e.second) + && tr.tds().is_edge(e.first, e.second, cell, i1, i2) + && tr.segment(Edge(cell, i1, i2)).squared_length() < sq_low) + { + Edge edge(cell, i1, i2); + + if (!can_be_collapsed(edge, c3t3, protect_boundaries, imaginary_index, cell_selector)) + continue; + +#ifdef CGAL_TETRAHEDRAL_REMESHING_VERBOSE + Vertex_handle vh = +#endif + collapse_edge(edge, c3t3, sq_high, + protect_boundaries, imaginary_index, cell_selector); + +#ifdef CGAL_TETRAHEDRAL_REMESHING_VERBOSE + if (vh != Vertex_handle()) + ++nb_collapses; +#endif + } + }//end loop on short_edges + +#ifdef CGAL_TETRAHEDRAL_REMESHING_VERBOSE + std::cout << " done (" << nb_collapses << " collapses)." << std::endl; +#endif + } +} +} +} + +#endif // CGAL_INTERNAL_COLLAPSE_SHORT_EDGES_H diff --git a/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/compute_c3t3_statistics.h b/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/compute_c3t3_statistics.h new file mode 100644 index 00000000000..0502f7716e8 --- /dev/null +++ b/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/compute_c3t3_statistics.h @@ -0,0 +1,210 @@ +// Copyright (c) 2018 GeometryFactory (France). +// All rights reserved. +// +// This file is part of CGAL (www.cgal.org). +// You can redistribute it and/or modify it under the terms of the GNU +// General Public License as published by the Free Software Foundation, +// either version 3 of the License, or (at your option) any later version. +// +// Licensees holding a valid commercial license may use this file in +// accordance with the commercial license agreement provided with the software. +// +// This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE +// WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. +// +// $URL$ +// $Id$ +// +// +// +//****************************************************************************** +// +//****************************************************************************** + +#include +#include +#include +#include + +#include + +namespace CGAL +{ +namespace Tetrahedral_adaptive_remeshing +{ +namespace internal +{ + template + void compute_statistics(const Triangulation& tr, + const typename Triangulation::Cell::Subdomain_index& imaginary_index, + CellSelector cell_selector, + const char* filename = "statistics_c3t3.txt") + { + typedef Triangulation Tr; + typedef typename Tr::Geom_traits Gt; + typedef typename Tr::Cell_handle Cell_handle; + typedef typename Tr::Vertex_handle Vertex_handle; + typedef typename Tr::Point Point; + typedef typename Tr::Finite_facets_iterator Finite_facets_iterator; + typedef typename Tr::Finite_cells_iterator Finite_cells_iterator; + typedef typename Tr::Cell::Subdomain_index Subdomain_index; + + std::size_t nb_edges = 0; + double total_edges = 0; + std::size_t nb_angle = 0; + double total_angle = 0; + + double min_edges_length = (std::numeric_limits::max)(); + double max_edges_length = 0.; + + double smallest_edge_radius = (std::numeric_limits::max)(); + double smallest_radius_radius = (std::numeric_limits::max)(); + double biggest_v_sma_cube = 0.; + double max_dihedral_angle = 0.; + double min_dihedral_angle = 180.; + + for (Finite_facets_iterator fit = tr.finite_facets_begin(); + fit != tr.finite_facets_end(); ++fit) + { + const Cell_handle cell = fit->first; + const int& index = fit->second; + if (!cell_selector(cell) || !cell_selector(cell->neighbor(index))) + continue; + + const Point& pa = (cell->vertex((index + 1) & 3)->point()); + const Point& pb = (cell->vertex((index + 2) & 3)->point()); + const Point& pc = (cell->vertex((index + 3) & 3)->point()); + + double edges[3]; + edges[0] = (CGAL::sqrt(CGAL::squared_distance(pa, pb))); + edges[1] = (CGAL::sqrt(CGAL::squared_distance(pa, pc))); + edges[2] = (CGAL::sqrt(CGAL::squared_distance(pb, pc))); + for (int i = 0; i < 3; ++i) + { + if (edges[i] < min_edges_length){ min_edges_length = edges[i]; } + if (edges[i] > max_edges_length){ max_edges_length = edges[i]; } + total_edges += edges[i]; + ++nb_edges; + } + } + + double mean_edges_length = total_edges / (double)nb_edges; + + typename Gt::Compute_approximate_dihedral_angle_3 approx_dihedral_angle + = tr.geom_traits().compute_approximate_dihedral_angle_3_object(); + + std::size_t nb_tets = 0; + boost::unordered_set selected_vertices; + std::vector sub_ids; + for (Finite_cells_iterator cit = tr.finite_cells_begin(); + cit != tr.finite_cells_end(); + ++cit) + { + const Subdomain_index& si = cit->subdomain_index(); + if (si == Subdomain_index() || si == imaginary_index || !cell_selector(cit)) + continue; + + ++nb_tets; + if (std::find(sub_ids.begin(), sub_ids.end(), si) == sub_ids.end()) + sub_ids.push_back(cit->subdomain_index()); + for (int i = 0; i < 4; ++i) + selected_vertices.insert(cit->vertex(i)); + + const Point& p0 = (cit->vertex(0)->point()); + const Point& p1 = (cit->vertex(1)->point()); + const Point& p2 = (cit->vertex(2)->point()); + const Point& p3 = (cit->vertex(3)->point()); + double v = CGAL::abs(CGAL::volume(p0, p1, p2, p3)); + double circumradius = CGAL::sqrt(CGAL::squared_radius(p0, p1, p2, p3)); + + //find shortest edge + double edges[6]; + edges[0] = CGAL::sqrt(CGAL::squared_distance(p0, p1)); + edges[1] = CGAL::sqrt(CGAL::squared_distance(p0, p2)); + edges[2] = CGAL::sqrt(CGAL::squared_distance(p0, p3)); + edges[3] = CGAL::sqrt(CGAL::squared_distance(p2, p1)); + edges[4] = CGAL::sqrt(CGAL::squared_distance(p2, p3)); + edges[5] = CGAL::sqrt(CGAL::squared_distance(p1, p3)); + + double min_edge = edges[0]; + for (int i = 1; i < 6; ++i) + { + if (edges[i] < min_edge) + min_edge = edges[i]; + } + + double sumar = CGAL::sqrt(CGAL::squared_area(p0, p1, p2)) + + CGAL::sqrt(CGAL::squared_area(p1, p2, p3)) + + CGAL::sqrt(CGAL::squared_area(p2, p3, p0)) + + CGAL::sqrt(CGAL::squared_area(p3, p1, p0)); + double inradius = 3. * v / sumar; + double smallest_edge_radius_ = min_edge / circumradius*CGAL::sqrt(6.) / 4.;//*sqrt(6)/4 so that the perfect tet ratio is 1 + double smallest_radius_radius_ = inradius / circumradius * 3.; //*3 so that the perfect tet ratio is 1 instead of 1/3 + double biggest_v_sma_cube_ = v / std::pow(min_edge, 3) * 6. * CGAL::sqrt(2.);//*6*sqrt(2) so that the perfect tet ratio is 1 instead + + if (smallest_edge_radius_ < smallest_edge_radius) + smallest_edge_radius = smallest_edge_radius_; + + if (smallest_radius_radius_ < smallest_radius_radius) + smallest_radius_radius = smallest_radius_radius_; + + if (biggest_v_sma_cube_ > biggest_v_sma_cube) + biggest_v_sma_cube = biggest_v_sma_cube_; + + double a = CGAL::to_double(CGAL::abs(approx_dihedral_angle(p0, p1, p2, p3))); + if (a < min_dihedral_angle) { min_dihedral_angle = a; } + if (a > max_dihedral_angle) { max_dihedral_angle = a; } + total_angle += a; + ++nb_angle; + a = CGAL::to_double(CGAL::abs(approx_dihedral_angle(p0, p2, p1, p3))); + if (a < min_dihedral_angle) { min_dihedral_angle = a; } + if (a > max_dihedral_angle) { max_dihedral_angle = a; } + total_angle += a; + ++nb_angle; + a = CGAL::to_double(CGAL::abs(approx_dihedral_angle(p0, p3, p1, p2))); + if (a < min_dihedral_angle) { min_dihedral_angle = a; } + if (a > max_dihedral_angle) { max_dihedral_angle = a; } + total_angle += a; + ++nb_angle; + a = CGAL::to_double(CGAL::abs(approx_dihedral_angle(p1, p2, p0, p3))); + if (a < min_dihedral_angle) { min_dihedral_angle = a; } + if (a > max_dihedral_angle) { max_dihedral_angle = a; } + total_angle += a; + ++nb_angle; + a = CGAL::to_double(CGAL::abs(approx_dihedral_angle(p1, p3, p0, p2))); + if (a < min_dihedral_angle) { min_dihedral_angle = a; } + if (a > max_dihedral_angle) { max_dihedral_angle = a; } + total_angle += a; + ++nb_angle; + a = CGAL::to_double(CGAL::abs(approx_dihedral_angle(p2, p3, p0, p1))); + if (a < min_dihedral_angle) { min_dihedral_angle = a; } + if (a > max_dihedral_angle) { max_dihedral_angle = a; } + total_angle += a; + ++nb_angle; + } + + std::size_t nb_subdomains = sub_ids.size(); + //std::size_t nb_vertices = d->c3t3.number_of_vertices_in_complex(); + + std::ofstream ofs(filename); + if (!ofs) + return; + + ofs << "Nb subdomains : " << nb_subdomains << std::endl; + ofs << "Total number of vertices : " << tr.number_of_vertices() << std::endl; + ofs << "Number of selected cells : " << nb_tets << std::endl; + ofs << "Number of selected vertices : " << selected_vertices.size() << std::endl; + ofs << std::endl; + ofs << "Min dihedral angle : " << min_dihedral_angle << std::endl; + ofs << "Max dihedral angle : " << max_dihedral_angle << std::endl; + ofs << std::endl; + ofs << "Shortest edge : " << min_edges_length << std::endl; + ofs << "Longest edge : " << max_edges_length << std::endl; + ofs << "Average edge length : " << mean_edges_length << std::endl; + + ofs.close(); + } + +}//end namespace internal +}//end namespace Tetrahedral_adaptive_remeshing +}//end namespace CGAL diff --git a/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/flip_edges.h b/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/flip_edges.h new file mode 100644 index 00000000000..fdec3e473ca --- /dev/null +++ b/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/flip_edges.h @@ -0,0 +1,1167 @@ +// Copyright (c) 2019 GeometryFactory (France). +// All rights reserved. +// +// This file is part of CGAL (www.cgal.org). +// You can redistribute it and/or modify it under the terms of the GNU +// General Public License as published by the Free Software Foundation, +// either version 3 of the License, or (at your option) any later version. +// +// Licensees holding a valid commercial license may use this file in +// accordance with the commercial license agreement provided with the software. +// +// This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE +// WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. +// +// $URL$ +// $Id$ +// SPDX-License-Identifier: GPL-3.0+ +// +// +// Author(s) : Jane Tournois + +#ifndef CGAL_INTERNAL_FLIP_EDGES_H +#define CGAL_INTERNAL_FLIP_EDGES_H + +#include +#include +#include + +#include +#include + +#include + +namespace CGAL +{ +namespace Tetrahedral_remeshing +{ +namespace internal +{ + enum Flip_Criterion{ MIN_ANGLE_BASED, AVERAGE_ANGLE_BASED, + VALENCE_BASED, VALENCE_MIN_DH_BASED }; + + template + void flip_inside_edges(std::vector&) + { + //TODO + } + + template + Sliver_removal_result flip_3_to_2(typename C3t3::Edge& edge, + C3t3& c3t3, + std::vector& vertices_around_edge, + const Flip_Criterion& criterion) + { + typedef typename C3t3::Triangulation Tr; + typedef typename C3t3::Facet Facet; + typedef typename C3t3::Vertex_handle Vertex_handle; + typedef typename C3t3::Cell_handle Cell_handle; + typedef typename Tr::Cell_circulator Cell_circulator; + typedef typename Tr::Geom_traits Gt; + typedef typename Gt::FT FT; + + //Edge to face flip + Tr& tr = c3t3.triangulation(); + + Cell_circulator circ = tr.incident_cells(edge); + Cell_circulator done = circ; + + Vertex_handle vh0 = edge.first->vertex(edge.second); + Vertex_handle vh1 = edge.first->vertex(edge.third); + + //Select 2 cells to keep and update and one to remove + Cell_handle ch0 = Cell_handle(circ++); + Cell_handle ch1 = Cell_handle(circ++); + Cell_handle cell_to_remove = Cell_handle(circ++); + if (circ != done) + { + std::cout << "Wrong flip function" << std::endl; + return NOT_FLIPPABLE; + } + + //Check structural validity + Cell_handle c; + int i0, i1, i3; + if (tr.is_facet(vertices_around_edge[0], vertices_around_edge[1], vertices_around_edge[2], + c, i0, i1, i3)) + return NOT_FLIPPABLE; + + //Check topological validity + if ( ch0->subdomain_index() != ch1->subdomain_index() + || ch0->subdomain_index() != cell_to_remove->subdomain_index() + || ch1->subdomain_index() != cell_to_remove->subdomain_index()) + return NOT_FLIPPABLE; + + circ = Cell_circulator(done); + + Vertex_handle vh2; + Vertex_handle vh3; + + for (int i = 0; i < 3; ++i){ + if (!ch0->has_vertex(vertices_around_edge[i])) + vh2 = vertices_around_edge[i]; + else if (!ch1->has_vertex(vertices_around_edge[i])) + vh3 = vertices_around_edge[i]; + } + + int vh0_id = ch0->index(vh0); + int vh1_id = ch1->index(vh1); + + //Check if flip valid + if (!is_well_oriented(vh2, + ch0->vertex(indices(vh0_id, 0)), + ch0->vertex(indices(vh0_id, 1)), + ch0->vertex(indices(vh0_id, 2))) + || !is_well_oriented(vh3, + ch1->vertex(indices(vh1_id, 0)), + ch1->vertex(indices(vh1_id, 1)), + ch1->vertex(indices(vh1_id, 2)))) + return NOT_FLIPPABLE; + + ///********************VALIDITY CHECK***************************/ + //double curr_min_dh; + //bool check_validity = false; + //std::vector pre_sliver_Removal_cells; + //if (check_validity){ + // pre_sliver_Removal_cells.clear(); + // pre_sliver_Removal_cells.push_back(K::Tetrahedron_3(ch0->vertex(0)->point(), ch0->vertex(1)->point(), ch0->vertex(2)->point(), ch0->vertex(3)->point())); + // pre_sliver_Removal_cells.push_back(K::Tetrahedron_3(ch1->vertex(0)->point(), ch1->vertex(1)->point(), ch1->vertex(2)->point(), ch1->vertex(3)->point())); + // pre_sliver_Removal_cells.push_back(K::Tetrahedron_3(cell_to_remove->vertex(0)->point(), cell_to_remove->vertex(1)->point(), + // cell_to_remove->vertex(2)->point(), cell_to_remove->vertex(3)->point())); + + // curr_min_dh = min_dihedral_angle(ch0); + // curr_min_dh = std::min(curr_min_dh, min_dihedral_angle(ch1)); + // curr_min_dh = std::min(curr_min_dh, min_dihedral_angle(cell_to_remove)); + + // pre_sliver_Removal_vertices.clear(); + // for (int i = 0; i < vertices_around_edge.size(); ++i){ + // pre_sliver_Removal_vertices.push_back(Point_3(vertices_around_edge[i]->point())); + // } + + // previous_edges.clear(); + // previous_edges.push_back(std::make_pair(vh0->point(), vh1->point())); + //} + /*************************************************************/ + + + if (criterion == MIN_ANGLE_BASED) + { + //Current worst dihedral angle + FT curr_min_dh = min_dihedral_angle(ch0); + curr_min_dh = (std::min)(curr_min_dh, min_dihedral_angle(ch1)); + curr_min_dh = (std::min)(curr_min_dh, min_dihedral_angle(cell_to_remove)); + + //Result worst dihedral angle + if (curr_min_dh > min_dihedral_angle(vh2, + ch0->vertex(indices(vh0_id, 0)), + ch0->vertex(indices(vh0_id, 1)), + ch0->vertex(indices(vh0_id, 2))) + || curr_min_dh > min_dihedral_angle(vh3, + ch1->vertex(indices(vh1_id, 0)), + ch1->vertex(indices(vh1_id, 1)), + ch1->vertex(indices(vh1_id, 2)))) + return NO_BEST_CONFIGURATION; + } + else if (criterion == AVERAGE_ANGLE_BASED) + { + //Current worst dihedral angle + double average_min_dh = min_dihedral_angle(ch0); + average_min_dh += min_dihedral_angle(ch1); + average_min_dh += min_dihedral_angle(cell_to_remove); + + average_min_dh /= 3.; + + FT new_average_min_dh = 0.5 * + (min_dihedral_angle(vh2, ch0->vertex(indices(vh0_id, 0)), + ch0->vertex(indices(vh0_id, 1)), + ch0->vertex(indices(vh0_id, 2))) + + min_dihedral_angle(vh3, ch1->vertex(indices(vh1_id, 0)), + ch1->vertex(indices(vh1_id, 1)), + ch1->vertex(indices(vh1_id, 2)))); + //Result worst dihedral angle + if (average_min_dh > new_average_min_dh) + return NO_BEST_CONFIGURATION; + } + + //Keep the facets + typedef CGAL::Triple Facet_vvv; + typedef boost::unordered_map FaceMapIndex; + + FaceMapIndex facet_map_indices; + std::vector facets; + do + { + int curr_vh0_id = circ->index(vh0); + Facet n_vh0_facet = tr.mirror_facet(Facet(circ, curr_vh0_id)); + Facet_vvv face0 = make_vertex_triple(circ->vertex(indices(curr_vh0_id, 0)), + circ->vertex(indices(curr_vh0_id, 1)), + circ->vertex(indices(curr_vh0_id, 2))); + + typename FaceMapIndex::iterator it = facet_map_indices.find(face0); + if (it == facet_map_indices.end()) + { + facet_map_indices[face0] = facets.size(); + facets.push_back(n_vh0_facet); + } + + int curr_vh1_id = circ->index(vh1); + Facet n_vh1_facet = tr.mirror_facet(Facet(circ, curr_vh1_id)); + Facet_vvv face1 = make_vertex_triple(circ->vertex(indices(curr_vh1_id, 0)), + circ->vertex(indices(curr_vh1_id, 1)), + circ->vertex(indices(curr_vh1_id, 2))); + it = facet_map_indices.find(face1); + if (it == facet_map_indices.end()) + { + facet_map_indices[face1] = facets.size(); + facets.push_back(n_vh1_facet); + } + } + while (++circ != done); + + /* + c3t3.remove_from_complex( ch0 ); + c3t3.remove_from_complex( ch1 ); + c3t3.remove_from_complex( cell_to_remove ); + + tr.flip(edge); + + for( int i = 0 ; i < facets.size() ; i ++ ){ + Cell_handle new_cell = facets[i].first->neighbor( facets[i].second ); + c3t3.add_to_complex( new_cell, si ); + } + */ + + //Update cells + ch0->set_vertex(vh0_id, vh2); + ch1->set_vertex(vh1_id, vh3); + + std::vector cells_to_update; + cells_to_update.push_back(ch0); + cells_to_update.push_back(ch1); + + //Update adjacencies and vertices' cells + for (std::size_t i = 0; i < cells_to_update.size(); ++i) + { + Cell_handle ch = cells_to_update[i]; + for (int v = 0; v < 4; ++v) + { + Facet_vvv face = make_vertex_triple(ch->vertex(indices(v, 0)), + ch->vertex(indices(v, 1)), + ch->vertex(indices(v, 2))); + typename FaceMapIndex::iterator it = facet_map_indices.find(face); + if (it == facet_map_indices.end()) + { + facet_map_indices[face] = facets.size(); + facets.push_back(Facet(ch, v)); + } + else + { + Facet facet = facets[it->second]; + //Update neighbor + facet.first->set_neighbor(facet.second, ch); + ch->set_neighbor(v, facet.first); + } + ch->vertex(v)->set_cell(ch); + } + } + + c3t3.remove_from_complex(cell_to_remove); + tr.tds().delete_cell(cell_to_remove); + + /********************VALIDITY CHECK***************************/ + //if (check_validity) + //{ + // post_sliver_Removal_cells.clear(); + // post_sliver_Removal_cells.push_back(ch0); + // post_sliver_Removal_cells.push_back(ch1); + + // double new_min_dh = min_dihedral_angle(ch0); + // new_min_dh = std::min(new_min_dh, min_dihedral_angle(ch1)); + + // post_sliver_Removal_vertices.clear(); + // post_sliver_Removal_vertices.push_back(vh2); + // post_sliver_Removal_vertices.push_back(vh3); + + // if (!is_well_oriented(ch0)) + // return INVALID_ORIENTATION; + // if (!is_well_oriented(ch1)) + // return INVALID_ORIENTATION; + // if (!tr.is_valid(ch0)) + // return INVALID_CELL; + // if (!tr.is_valid(ch1)) + // return INVALID_CELL; + + // for (int i = 0; i < 4; ++i){ + // if (!tr.is_valid(ch0->neighbor(i))) + // return INVALID_CELL; + // if (!tr.is_valid(ch1->neighbor(i))) + // return INVALID_CELL; + // if (!tr.tds().is_valid(ch0->vertex(i))) + // return INVALID_VERTEX; + // if (!tr.tds().is_valid(ch1->vertex(i))){ + // return INVALID_VERTEX; + // } + // } + + // if ((curr_min_dh - new_min_dh) > 0.01){ + // std::cout << "Three_to_two_flip::Flip not improving the quality: " << curr_min_dh << " to " << new_min_dh << std::endl; + // return INVALID_CELL; + // } + //} + /***********************************************************/ + + return VALID_FLIP; + } + + template + void find_best_flip_to_improve_dh(C3t3& c3t3, + typename C3t3::Edge& edge, + typename C3t3::Vertex_handle vh2, + typename C3t3::Vertex_handle vh3, + CandidatesQueue& candidates, + double curr_min_dh, + bool is_sliver_well_oriented = true, + int e_id = 0) + { + typedef typename C3t3::Triangulation Tr; + typedef typename C3t3::Vertex_handle Vertex_handle; + typedef typename C3t3::Cell_handle Cell_handle; + typedef typename C3t3::Facet Facet; + typedef typename Tr::Facet_circulator Facet_circulator; + typedef typename Tr::Cell_circulator Cell_circulator; + typedef typename Tr::Geom_traits Gt; + typedef typename Gt::FT FT; + + // std::cout << "find_best_flip_to_improve_dh boundary " << std::endl; + Tr& tr = c3t3.triangulation(); + + Vertex_handle vh0 = edge.first->vertex(edge.second); + Vertex_handle vh1 = edge.first->vertex(edge.third); + + Facet_circulator curr_fcirc = tr.incident_facets(edge); + Facet_circulator curr_fdone = curr_fcirc; + + //Only keep the possible flips + std::vector opposite_vertices; + int nb_cells_around_edge = 0; + do + { + Vertex_handle vh; + //Get the ids of the opposite vertices + for (int i = 0; i < 3; ++i) + { + Vertex_handle curr_vertex = curr_fcirc->first->vertex(indices(curr_fcirc->second, i)); + if ( curr_vertex != vh0 + && curr_vertex != vh1 + && (curr_vertex == vh2 || curr_vertex == vh3)) + { + vh = curr_vertex; + Facet_circulator facet_circulator(curr_fcirc); + Facet_circulator facet_done(curr_fcirc); + + facet_done--; + facet_circulator++; + facet_circulator++; + + bool is_edge = false; + do + { + //Get the ids of the opposite vertices + for (int i = 0; i < 3; ++i) + { + Vertex_handle curr_vertex = facet_circulator->first->vertex( + indices(facet_circulator->second, i)); + if (curr_vertex != vh0 && curr_vertex != vh1) + { + Cell_handle ch; + int i0, i1; + if (tr.is_edge(curr_vertex, vh, ch, i0, i1)) + is_edge = true; + } + } + } while (++facet_circulator != facet_done); + + if (!is_edge && !tr.is_infinite(vh)) + opposite_vertices.push_back(vh); + } + } + nb_cells_around_edge++; + } + while (++curr_fcirc != curr_fdone); + + if (nb_cells_around_edge < 4) + return; + + //Facets that will be used to create new cells i.e. all the facets opposite to vh1 and don't have vh + //Facets that will be used to update cells i.e. all the facets opposite to vh0 will be set to vh: facet.first->set_vertex( facet.second, vh ) + + Cell_circulator cell_circulator = tr.incident_cells(edge); + Cell_circulator done = cell_circulator; + + for (std::size_t i = 0; i < opposite_vertices.size(); ++i) + { + Vertex_handle vh = opposite_vertices[i]; + bool keep = true; + + std::vector facets; + do + { + //Store it if it do not have vh + if (!cell_circulator->has_vertex(vh)) + { + //Facets opposite to vh0 + Facet facet_vh0(cell_circulator, cell_circulator->index(vh0)); + + //Facets opposite to vh1 + Facet facet_vh1(cell_circulator, cell_circulator->index(vh1)); + + facets.push_back(facet_vh1); + facets.push_back(facet_vh0); + } + } while (++cell_circulator != done); + + + FT min_flip_dihedral_angle = (std::numeric_limits::max)(); + for (std::size_t i = 0; i < facets.size(); ++i) + { + const Facet& fi = facets[i]; + if (!tr.is_infinite(fi.first)) + { + if (is_well_oriented(vh, fi.first->vertex(indices(fi.second, 0)), + fi.first->vertex(indices(fi.second, 1)), + fi.first->vertex(indices(fi.second, 2)))) + { + min_flip_dihedral_angle = (std::min)(min_flip_dihedral_angle, + min_dihedral_angle(vh, fi.first->vertex(indices(fi.second, 0)), + fi.first->vertex(indices(fi.second, 1)), + fi.first->vertex(indices(fi.second, 2)))); + } + else + { + keep = false; + break; + } + } + } + + if (keep && (curr_min_dh < min_flip_dihedral_angle || !is_sliver_well_oriented)) + { + //std::cout << "vh " << vh->info() <<" old " << curr_min_dh << " min " << min_flip_dihedral_angle << std::endl; + candidates.push(std::make_pair(min_flip_dihedral_angle, std::make_pair(vh, e_id))); + } + } + } + + template + void find_best_flip_to_improve_dh(C3t3& c3t3, + typename C3t3::Edge& edge, + CandidatesQueue& candidates, + double curr_min_dh, + bool is_sliver_well_oriented = true, + int e_id = 0) + { + typedef typename C3t3::Triangulation Tr; + typedef typename C3t3::Vertex_handle Vertex_handle; + typedef typename C3t3::Cell_handle Cell_handle; + typedef typename C3t3::Facet Facet; + typedef typename Tr::Facet_circulator Facet_circulator; + typedef typename Tr::Cell_circulator Cell_circulator; + typedef typename Tr::Geom_traits Gt; + typedef typename Gt::FT FT; + + Tr& tr = c3t3.triangulation(); + + Vertex_handle vh0 = edge.first->vertex(edge.second); + Vertex_handle vh1 = edge.first->vertex(edge.third); + + Facet_circulator curr_fcirc = tr.incident_facets(edge); + Facet_circulator curr_fdone = curr_fcirc; + + //Only keep the possible flips + std::vector opposite_vertices; + int nb_cells_around_edge = 0; + do + { + Vertex_handle vh; + //Get the ids of the opposite vertices + for (int i = 0; i < 3; ++i) + { + Vertex_handle curr_vertex = curr_fcirc->first->vertex( + indices(curr_fcirc->second, i)); + if (curr_vertex != vh0 && curr_vertex != vh1) + { + vh = curr_vertex; + break; + } + } + + Facet_circulator facet_circulator = curr_fcirc; + Facet_circulator facet_done = curr_fcirc; + + facet_done--; + facet_circulator++; + facet_circulator++; + bool is_edge = false; + do + { + //Get the ids of the opposite vertices + for (int i = 0; i < 3; ++i) + { + Vertex_handle curr_vertex = facet_circulator->first->vertex( + indices(facet_circulator->second, i)); + if (curr_vertex != vh0 && curr_vertex != vh1) + { + Cell_handle ch; + int i0, i1; + if (tr.is_edge(curr_vertex, vh, ch, i0, i1)) + is_edge = true; + } + } + } while (++facet_circulator != facet_done); + + if (!is_edge && !tr.is_infinite(vh)) + opposite_vertices.push_back(vh); + + nb_cells_around_edge++; + } + while (++curr_fcirc != curr_fdone); + if (nb_cells_around_edge < 4) + return; + + //Facets that will be used to create new cells + // i.e. all the facets opposite to vh1 and don't have vh + //Facets that will be used to update cells + // i.e. all the facets opposite to vh0 will be set to vh: + // facet.first->set_vertex( facet.second, vh ) + + Cell_circulator cell_circulator = tr.incident_cells(edge); + Cell_circulator done = cell_circulator; + + for (std::size_t i = 0; i < opposite_vertices.size(); ++i) + { + Vertex_handle vh = opposite_vertices[i]; + bool keep = true; + + std::vector facets; + do + { + //Store it if it do not have vh + if (!cell_circulator->has_vertex(vh)) + { + //Facets opposite to vh0 + Facet facet_vh0(cell_circulator, cell_circulator->index(vh0)); + + //Facets opposite to vh1 + Facet facet_vh1(cell_circulator, cell_circulator->index(vh1)); + + facets.push_back(facet_vh1); + facets.push_back(facet_vh0); + } + } + while (++cell_circulator != done); + + FT min_flip_dihedral_angle = (std::numeric_limits::max)(); + for (std::size_t i = 0; i < facets.size(); ++i) + { + const Facet& fi = facets[i]; + if (!tr.is_infinite(fi.first)) + { + if (is_well_oriented(vh, fi.first->vertex(indices(fi.second, 0)), + fi.first->vertex(indices(fi.second, 1)), + fi.first->vertex(indices(fi.second, 2)))) + { + min_flip_dihedral_angle = (std::min)(min_flip_dihedral_angle, + min_dihedral_angle(vh, fi.first->vertex(indices(fi.second, 0)), + fi.first->vertex(indices(fi.second, 1)), + fi.first->vertex(indices(fi.second, 2)))); + } + else + { + keep = false; + break; + } + } + } + + if (keep && (curr_min_dh < min_flip_dihedral_angle || !is_sliver_well_oriented)) + { + //std::cout << "vh " << vh->info() <<" old " << curr_min_dh << " min " << min_flip_dihedral_angle << std::endl; + candidates.push(std::make_pair(min_flip_dihedral_angle, std::make_pair(vh, e_id))); + } + } + } + + template + Sliver_removal_result flip_n_to_m(C3t3& c3t3, + typename C3t3::Edge& edge, + typename C3t3::Vertex_handle vh, + bool check_validity = false) + { + CGAL_USE(check_validity); + // std::cout << "n_to_m_flip::start" << std::endl; + typedef typename C3t3::Triangulation Tr; + typedef typename C3t3::Vertex_handle Vertex_handle; + typedef typename C3t3::Cell_handle Cell_handle; + typedef typename C3t3::Facet Facet; + typedef typename Tr::Facet_circulator Facet_circulator; + typedef typename Tr::Cell_circulator Cell_circulator; + + Tr& tr = c3t3.triangulation(); + + Vertex_handle vh0 = edge.first->vertex(edge.second); + Vertex_handle vh1 = edge.first->vertex(edge.third); + + //This vertex will have its valence augmenting a lot, + //TODO take the best one + + //TODO!!!! Check that the created edges do not exist!!! + + Facet_circulator facet_circulator = tr.incident_facets(edge); + Facet_circulator done_facet_circulator = facet_circulator; + bool look_for_vh_iterator = true; + do + { + facet_circulator++; + + //Get the ids of the opposite vertices + for (int i = 0; i < 3; ++i) + { + if (facet_circulator->first->vertex(indices(facet_circulator->second, i)) == vh) + look_for_vh_iterator = false; + } + } while (facet_circulator != done_facet_circulator && look_for_vh_iterator); + + if (look_for_vh_iterator){ + std::cout << "Vertex not an opposite of the edge!!" << std::endl; + return NOT_FLIPPABLE; + } + + Facet_circulator facet_done(facet_circulator); + facet_done--; + facet_circulator++; + facet_circulator++; + + std::vector vertices_around_edge; + do + { + //Get the ids of the opposite vertices + for (int i = 0; i < 3; ++i) + { + Vertex_handle curr_vertex = facet_circulator->first->vertex( + indices(facet_circulator->second, i)); + if (curr_vertex != vh0 && curr_vertex != vh1) + { + Cell_handle ch; + int i0, i1; + if (tr.is_edge(curr_vertex, vh, ch, i0, i1)) + return NOT_FLIPPABLE; + + vertices_around_edge.push_back(curr_vertex); + } + } + } while (++facet_circulator != facet_done); + + + std::vector cells_around_edge; + std::vector to_remove; + + //Neighbors that will need to be updated after flip + std::vector neighbor_facets; + + //Facets that will be used to create new cells + // i.e. all the facets opposite to vh1 and don't have vh + std::vector facets_for_new_cells; + + //Facets that will be used to update cells + // i.e. all the facets opposite to vh0 will be set to vh : + // facet.first->set_vertex( facet.second, vh ) + std::vector facets_for_updated_cells; + + Cell_circulator cell_circulator = tr.incident_cells(edge); + Cell_circulator done = cell_circulator; + do + { + cells_around_edge.push_back(cell_circulator); + + //Facets opposite to vh0 + Facet facet_vh0(cell_circulator, cell_circulator->index(vh0)); + neighbor_facets.push_back(tr.mirror_facet(facet_vh0)); + + //Facets opposite to vh1 + Facet facet_vh1(cell_circulator, cell_circulator->index(vh1)); + neighbor_facets.push_back(tr.mirror_facet(facet_vh1)); + + //Store it if it do not have vh + if (cell_circulator->has_vertex(vh)){ + to_remove.push_back(cell_circulator); + } + else + { + facets_for_new_cells.push_back(facet_vh1); + facets_for_updated_cells.push_back(facet_vh0); + } + // + // if( ! is_well_oriented( cell_circulator ) ) + // return WRONG; + } + while (++cell_circulator != done); + + + for (std::size_t i = 0; i < cells_around_edge.size(); ++i) + { + Cell_handle ch = cells_around_edge[i]; + for (int v = 0; v < 4; v++) + { + Cell_handle neighbor = ch->neighbor(v); + if (std::find(cells_around_edge.begin(), cells_around_edge.end(), neighbor) + == cells_around_edge.end()) + { + //Facets opposite + Facet facet_vh(ch, v); + neighbor_facets.push_back(tr.mirror_facet(facet_vh)); + } + } + } + + //Check that the result will be valid + for (std::size_t i = 0; i < facets_for_new_cells.size(); ++i) + { + const Facet& fi = facets_for_new_cells[i]; + + if ( !tr.is_infinite(fi.first) + && !is_well_oriented(vh, fi.first->vertex(indices(fi.second, 0)), + fi.first->vertex(indices(fi.second, 1)), + fi.first->vertex(indices(fi.second, 2)))) + return NOT_FLIPPABLE; + } + for (std::size_t i = 0; i < facets_for_updated_cells.size(); ++i) + { + const Facet& fi = facets_for_updated_cells[i]; + + if ( !tr.is_infinite(fi.first) + && !is_well_oriented(vh, fi.first->vertex(indices(fi.second, 0)), + fi.first->vertex(indices(fi.second, 1)), + fi.first->vertex(indices(fi.second, 2)))) + return NOT_FLIPPABLE; + } + + ///********************VALIDITY CHECK***************************/ + //double current_min_dh = DBL_MAX; + + //if (check_validity){ + + // pre_sliver_Removal_cells.clear(); + // do{ + // pre_sliver_Removal_cells.push_back(K::Tetrahedron_3(cell_circulator->vertex(0)->point(), cell_circulator->vertex(1)->point(), + // cell_circulator->vertex(2)->point(), cell_circulator->vertex(3)->point())); + + // if (!tr.is_infinite(cell_circulator)) + // current_min_dh = std::min(current_min_dh, min_dihedral_angle(cell_circulator)); + // } while (++cell_circulator != done); + + // pre_sliver_Removal_vertices.clear(); + // pre_sliver_Removal_vertices.push_back(vh->point()); + + // previous_edges.clear(); + // previous_edges.push_back(std::make_pair(vh0->point(), vh1->point())); + //} + ///*************************************************************/ + + //Subdomain index? + typename C3t3::Subdomain_index subdomain = to_remove[0]->subdomain_index(); + typename C3t3::Triangulation::Cell::Info info = to_remove[0]->info(); + +#ifdef CGAL_TETRAHEDRAL_REMESHING_DEBUG + for (std::size_t i = 1; i < to_remove.size(); ++i) + CGAL_assertion(subdomain == to_remove[i]->subdomain_index()); +#endif + + std::vector cells_to_update; + + //Create new cells + for (std::size_t i = 0; i < facets_for_new_cells.size(); ++i) + { + const Facet& fi = facets_for_new_cells[i]; + + Cell_handle new_cell = tr.tds().create_cell(); + + for (int v = 0; v < 4; v++){ + new_cell->set_vertex(v, fi.first->vertex(v)); + } + + new_cell->set_vertex(fi.second, vh); + + c3t3.add_to_complex(new_cell, subdomain); + new_cell->info() = info; + cells_to_update.push_back(new_cell); + } + + //Update_existing cells + for (std::size_t i = 0; i < facets_for_updated_cells.size(); ++i) + { + const Facet& fi = facets_for_updated_cells[i]; + fi.first->set_vertex(fi.second, vh); + cells_to_update.push_back(fi.first); + } + + typedef CGAL::Triple Facet_vvv; + typedef boost::unordered_map FaceMapIndex; + + FaceMapIndex facet_map_indices; + std::vector facets; + + for (std::size_t i = 0; i < neighbor_facets.size(); ++i) + { + Cell_handle ch = neighbor_facets[i].first; + int v = neighbor_facets[i].second; + + Facet_vvv face = make_vertex_triple(ch->vertex(indices(v,0)), + ch->vertex(indices(v,1)), + ch->vertex(indices(v,2))); + typename FaceMapIndex::iterator it = facet_map_indices.find(face); + if (it == facet_map_indices.end()) + { + facet_map_indices[face] = facets.size(); + facets.push_back(Facet(ch, v)); + } + } + + //Update adjacencies and vertices cells + for (std::size_t i = 0; i < cells_to_update.size(); ++i) + { + Cell_handle ch = cells_to_update[i]; + for (int v = 0; v < 4; v++) + { + Facet_vvv face = make_vertex_triple(ch->vertex(indices(v,0)), + ch->vertex(indices(v,1)), + ch->vertex(indices(v,2))); + typename FaceMapIndex::iterator it = facet_map_indices.find(face); + if (it == facet_map_indices.end()) + { + facet_map_indices[face] = facets.size(); + facets.push_back(Facet(ch, v)); + } + else + { + Facet facet = facets[it->second]; + + //Update neighbor + facet.first->set_neighbor(facet.second, ch); + ch->set_neighbor(v, facet.first); + } + ch->vertex(v)->set_cell(ch); + } + } + + //Remove cells + for (std::size_t i = 0; i < to_remove.size(); ++i) + { + c3t3.remove_from_complex(to_remove[i]); + tr.tds().delete_cell(to_remove[i]); + } + + ///********************VALIDITY CHECK***************************/ + //if (check_validity){ + + // double new_min_dh = DBL_MAX; + + // post_sliver_Removal_cells.clear(); + // for (unsigned int i = 0; i < cells_to_update.size(); ++i){ + // post_sliver_Removal_cells.push_back(cells_to_update[i]); + + // if (!tr.is_infinite(cells_to_update[i])) + // new_min_dh = std::min(new_min_dh, min_dihedral_angle(cells_to_update[i])); + // } + + // post_sliver_Removal_vertices.clear(); + // for (unsigned int i = 0; i < vertices_around_edge.size(); ++i){ + // post_sliver_Removal_vertices.push_back(vertices_around_edge[i]); + // } + + // current_edges.clear(); + // for (unsigned int i = 0; i < vertices_around_edge.size(); ++i){ + // current_edges.push_back(std::make_pair(vertices_around_edge[i]->point(), vh->point())); + // } + + + // for (unsigned int i = 0; i < cells_to_update.size(); ++i){ + // if (!tr.is_valid(cells_to_update[i])) + // return INVALID_CELL; + + // for (int v = 0; v < 4; v++){ + // if (!tr.is_valid(cells_to_update[i]->neighbor(v))) + // return INVALID_CELL; + + // if (!tr.tds().is_valid(cells_to_update[i]->vertex(v))) + // return INVALID_VERTEX; + + // } + // } + + // if ((current_min_dh - new_min_dh) > 0.01){ + // std::cout << pre_sliver_Removal_cells.size() << " to " << post_sliver_Removal_cells.size() << " flip not improving the quality: " << + // current_min_dh << " to " << new_min_dh << std::endl; + // return INVALID_CELL; + // } + + //} + ///***********************************************************/ + + // std::cout << "n_to_m_flip::end with success" << std::endl; + + return VALID_FLIP; + } + + + template + Sliver_removal_result flip_n_to_m(typename C3t3::Edge& edge, + C3t3& c3t3, + std::vector& boundary_vertices, + const Flip_Criterion& criterion) + { + typedef typename C3t3::Vertex_handle Vertex_handle; + typedef typename C3t3::Triangulation::Cell_circulator Cell_circulator; + typedef typename C3t3::Triangulation::Geom_traits Gt; + typedef typename Gt::FT FT; + + Sliver_removal_result result = NOT_FLIPPABLE; + + typedef std::pair > Angle_and_vertex; + + //std::cout << "n_to_m_flip " << boundary_vertices.size() << std::endl; + if (criterion == MIN_ANGLE_BASED) + { + std::priority_queue candidates; + + Cell_circulator circ = c3t3.triangulation().incident_cells(edge); + Cell_circulator done = circ; + + FT curr_min_dh = min_dihedral_angle(circ++); + while (circ != done) + { + curr_min_dh = (std::min)(curr_min_dh, min_dihedral_angle(circ++)); + } + if (boundary_vertices.size() == 2) + find_best_flip_to_improve_dh(c3t3, edge, boundary_vertices[0], boundary_vertices[1], + candidates, curr_min_dh); + else + find_best_flip_to_improve_dh(c3t3, edge, candidates, curr_min_dh); + + bool flip_performed = false; + while (!candidates.empty() && !flip_performed) + { + Angle_and_vertex curr_cost_vpair = candidates.top(); + candidates.pop(); + + //std::cout << curr_min_dh << " old, current " << curr_cost_vpair.second.first->info() <<" and angle " << curr_cost_vpair.first << std::endl; + + if (curr_min_dh >= curr_cost_vpair.first) + return NO_BEST_CONFIGURATION; + + result = flip_n_to_m(c3t3, edge, curr_cost_vpair.second.first); + + if (result != NOT_FLIPPABLE) + flip_performed = true; + } + } + + return result; + } + + template + Sliver_removal_result find_best_flip(typename C3t3::Edge& edge, + C3t3& c3t3, + const Flip_Criterion& criterion) + { + typedef typename C3t3::Triangulation Tr; + typedef typename C3t3::Vertex_handle Vertex_handle; + typedef typename Tr::Facet_circulator Facet_circulator; + + Tr& tr = c3t3.triangulation(); + + Vertex_handle v0 = edge.first->vertex(edge.second); + Vertex_handle v1 = edge.first->vertex(edge.third); + + Facet_circulator circ = tr.incident_facets(edge); + Facet_circulator done = circ; + + //Identify the vertices around this edge + boost::unordered_set vertices_around_edge; + bool boundary_edge = false; + bool hull_edge = false; + + boost::unordered_set boundary_vertices; + boost::unordered_set hull_vertices; + do + { + //Get the ids of the opposite vertices + for (int i = 0; i < 3; ++i) + { + Vertex_handle vi = circ->first->vertex(indices(circ->second, i)); + if (vi != v0 && vi != v1) + { + vertices_around_edge.insert(vi); + + if ( circ->first->subdomain_index() + != circ->first->neighbor(circ->second)->subdomain_index()) + { + boundary_edge = true; + boundary_vertices.insert(vi); + } + + if ( tr.is_infinite(circ->first) + != tr.is_infinite(circ->first->neighbor(circ->second))) + { + hull_edge = true; + hull_vertices.insert(vi); + } + } + } + } + while (++circ != done); + + + //Check if not feature edge + if (boundary_vertices.size() > 2) + return NOT_FLIPPABLE; + + if (vertices_around_edge.size() == 3) + { + if (!boundary_edge && !hull_edge) + { + std::vector vertices; + vertices.insert(vertices.end(), vertices_around_edge.begin(), vertices_around_edge.end()); + return flip_3_to_2(edge, c3t3, vertices, criterion); + } + } + else + { + //TODO fix for hull edges + // if( hull_edge ) + // return n_to_m_flip( edge, hull_vertices, flip_criterion, check_validity ); + if (!hull_edge) + { + std::vector vertices; + vertices.insert(vertices.end(), boundary_vertices.begin(), boundary_vertices.end()); + return flip_n_to_m(edge, c3t3, vertices, criterion); + //return n_to_m_flip(edge, boundary_vertices, flip_criterion); + } + } + return NOT_FLIPPABLE; + } + + + template + std::size_t flip_all_edges(std::vector& edges, + C3t3& c3t3, + const Flip_Criterion& criterion) + { + typedef typename C3t3::Triangulation Tr; + typedef typename Tr::Vertex_handle Vertex_handle; + typedef typename Tr::Cell_handle Cell_handle; + typedef typename Tr::Edge Edge; + + Tr& tr = c3t3.triangulation(); + + std::size_t count = 0; + for (unsigned int i = 0; i < edges.size(); ++i) + { + const Vertex_handle vh0 = edges[i].first; + const Vertex_handle vh1 = edges[i].second; + + Cell_handle ch; + int i0, i1; + if (tr.is_edge(vh0, vh1, ch, i0, i1)) + { + Edge edge(ch, i0, i1); + + Sliver_removal_result res = find_best_flip(edge, c3t3, criterion); + if (res == INVALID_CELL || res == INVALID_VERTEX || res == INVALID_ORIENTATION) + { + std::cout << "FLIP PROBLEM!!!!" << std::endl; + return count; + } + if (res == VALID_FLIP) + { + ++count; +#ifdef CGAL_TETRAHEDRAL_REMESHING_VERBOSE_PROGRESS + std::cout << "\rFlip... ("; + std::cout << count << " flips)"; + std::cout.flush(); +#endif + } + } + } + return count; + } + + template + void flip_edges(C3T3& c3t3, + const typename C3T3::Subdomain_index& imaginary_index, + const bool protect_boundaries, + CellSelector cell_selector) + { + CGAL_USE(protect_boundaries); + typedef typename C3T3::Triangulation T3; + typedef typename T3::Vertex_handle Vertex_handle; + typedef typename std::pair Edge_vv; + +#ifdef CGAL_TETRAHEDRAL_REMESHING_VERBOSE + std::cout << "Flip edges..."; + std::cout.flush(); + std::size_t nb_flips = 0; +#endif + + const Flip_Criterion criterion = VALENCE_MIN_DH_BASED; + + //collect long edges + + //compute vertices normals map? + + // typedef typename C3T3::Surface_patch_index Surface_patch_index; + // typedef boost::unordered_map Spi_map; + //if (!protect_boundaries) + //{ + // std::cout << "\tBoundary flips" << std::endl; + // //Boundary flip + // std::vector boundary_vertices_valences; + // std::vector boundary_edges; + + // collectBoundaryEdges(boundary_edges); + + // computeVerticesValences(boundary_vertices_valences); + + // if (criterion == VALENCE_BASED) + // flipBoundaryEdges(boundary_edges, boundary_vertices_valences, VALENCE_BASED); + // else + // flipBoundaryEdges(boundary_edges, boundary_vertices_valences, MIN_ANGLE_BASED); + //} + +#ifdef CGAL_TETRAHEDRAL_REMESHING_VERBOSE + std::cout << "\tInside flips" << std::endl; +#endif + std::vector inside_edges; + CGAL::get_inside_edges(c3t3, imaginary_index, + cell_selector, + std::back_inserter(inside_edges)); + + if (criterion == VALENCE_BASED) + flip_inside_edges(inside_edges); + else + { +#ifdef CGAL_TETRAHEDRAL_REMESHING_VERBOSE + nb_flips = +#endif + flip_all_edges(inside_edges, c3t3, MIN_ANGLE_BASED); + } + +#ifdef CGAL_TETRAHEDRAL_REMESHING_VERBOSE + std::cout << " done (" << nb_flips << " flips)." << std::endl; +#endif + } + +}//namespace internal +}//namespace Tetrahedral_remeshing +}//namespace CGAL + +#endif // CGAL_INTERNAL_FLIP_EDGES_H diff --git a/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/smooth_vertices.h b/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/smooth_vertices.h new file mode 100644 index 00000000000..fb3c17e7ec2 --- /dev/null +++ b/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/smooth_vertices.h @@ -0,0 +1,775 @@ +// Copyright (c) 2017 GeometryFactory (France). +// All rights reserved. + +#ifndef CGAL_INTERNAL_SMOOTH_VERTICES_H +#define CGAL_INTERNAL_SMOOTH_VERTICES_H + +#include + +#include + +#include + +#include +#include + +namespace CGAL +{ +namespace Tetrahedral_remeshing +{ +namespace internal +{ + template + CGAL::Vector_3 project_on_tangent_plane(const CGAL::Point_3& gi, + const CGAL::Point_3& pi, + const CGAL::Vector_3& normal) + { + typedef typename Gt::Vector_3 Vector_3; + Vector_3 diff = pi - gi; + return Vector_3(gi, gi + (normal * diff) * normal); + } + + template + void compute_vertices_normals(const C3t3& c3t3, + VertexNormalsMap& normals_map) + { + typedef typename C3t3::Triangulation Tr; + typedef typename C3t3::Cell_handle Cell_handle; + typedef typename C3t3::Vertex_handle Vertex_handle; + typedef typename C3t3::Subdomain_index Subdomain_index; + typedef typename C3t3::Surface_patch_index Surface_patch_index; + typedef typename Tr::Finite_facets_iterator Finite_facets_iterator; + typedef typename Tr::Gt::Vector_3 Vector_3; + + const Tr& tr = c3t3.triangulation(); + + for (Finite_facets_iterator fit = tr.finite_facets_begin(); + fit != tr.finite_facets_end(); ++fit) + { + Cell_handle ch = fit->first; + Cell_handle n_ch = fit->first->neighbor(fit->second); + + Subdomain_index si = ch->subdomain_index(); + Subdomain_index si_mirror = n_ch->subdomain_index(); + + if (si != si_mirror || tr.is_infinite(ch) || tr.is_infinite(n_ch)) + { + Surface_patch_index surf_i = helpers::make_surface_patch_index(si, si_mirror); + for (int i = 0; i < 3; ++i) + { + Vertex_handle v_id = fit->first->vertex(indices(fit->second ,i)); + normals_map[v_id][surf_i] = CGAL::NULL_VECTOR; + } + } + } + + for (Finite_facets_iterator fit = tr.finite_facets_begin(); + fit != tr.finite_facets_end(); ++fit) + { + Cell_handle ch = fit->first; + Cell_handle n_ch = fit->first->neighbor(fit->second); + + Subdomain_index si = ch->subdomain_index(); + Subdomain_index si_mirror = n_ch->subdomain_index(); + + if (si != si_mirror || tr.is_infinite(ch) || tr.is_infinite(n_ch)) + { + Surface_patch_index surf_i = helpers::make_surface_patch_index(si, si_mirror); + + Vector_3 n = CGAL::normal(*fit, tr.geom_traits()); + + if (si < si_mirror || tr.is_infinite(ch)) + n = -1.*n; + + for (int i = 0; i < 3; ++i) + { + Vector_3& v_n = normals_map[fit->first->vertex(indices(fit->second, i))][surf_i]; + v_n = v_n + n; + } + } + } + + //normalize the computed normals + for (typename VertexNormalsMap::iterator vnm_it = normals_map.begin(); + vnm_it != normals_map.end(); ++vnm_it) + { + //value type is map + for (typename VertexNormalsMap::value_type::iterator it = vnm_it->begin(); + it != vnm_it->end(); ++it) + { + Vector_3& n = it->second; + n = n / CGAL::sqrt(n*n); + } + } + } + + + template + bool project(const SurfacePatchIndex& /* si */, + CGAL::Vector_3& gi, + CGAL::Vector_3& projected_point) + { +// if (subdomain_FMLS_indices.find(si) == subdomain_FMLS_indices.end()) +// return false; + typedef typename Gt::Vector_3 Vector_3; + typedef typename Gt::Point_3 Point_3; + + if (std::isnan(gi.x()) || std::isnan(gi.y()) || isnan(gi.z())) + { + std::cout << "Initial point error " << gi << std::endl; + return false; + } + + Vector_3 res_normal; + Point_3 point; + Point_3 result = CGAL::ORIGIN + gi; + + //FMLS& fmls = subdomain_FMLS[subdomain_FMLS_indices[si]]; + + // int it_nb = 0; + // const int max_it_nb = 5; + //const float epsilon = fmls.getPNScale() / 1000.; + + //do + //{ + // point = result; + + // //fmls.fastProjectionCPU(point, result, res_normal); + + // if (std::isnan(result[0]) || std::isnan(result[1]) || std::isnan(result[2])){ + // std::cout << "MLS error detected si size " << si.first << " - " << si.second + // << " : " << fmls.getPNSize() << std::endl; + // return false; + // } + + //} while ((result - point).getLength() > epsilon && ++it_nb < max_it_nb); + + projected_point = Vector_3(result.x(), result.y(), result.z()); + + return true; + } + + template + bool check_inversion_and_move(const VertexHandle v, + const CGAL::Vector_3& move, + const std::vector& cells) + { + const CGAL::Point_3 backup = v->point(); //backup v's position + v->set_point(backup + move); + + for (std::size_t i = 0; i < cells.size(); ++i) + { + CellHandle ci = cells[i]; + if (CGAL::POSITIVE != CGAL::orientation(ci->vertex(0)->point(), + ci->vertex(1)->point(), ci->vertex(2)->point(), ci->vertex(3)->point())) + { + v->set_point(backup); + return false; + } + } + return true; + } + + template + typename C3T3::Triangulation::Geom_traits::Vector_3 + move_3d(typename C3T3::Vertex_handle v, const C3T3& c3t3) + { + typedef typename C3T3::Edge Edge; + typedef typename C3T3::Vertex_handle Vertex_handle; + typedef typename C3T3::Triangulation::Geom_traits::Vector_3 Vector_3; + + Vector_3 move = CGAL::NULL_VECTOR; + + std::vector edges; + c3t3.triangulation().incident_edges(v, std::back_inserter(edges)); + + if (edges.empty()) + return move; + + BOOST_FOREACH(Edge e, edges) + { + Vertex_handle ve = (e.first->vertex(e.second) != v) + ? e.first->vertex(e.second) + : e.first->vertex(e.third); + move = move + Vector_3(CGAL::ORIGIN, ve->point()); + } + + return 1. / edges.size() * move; + } + + template + typename C3T3::Triangulation::Geom_traits::Vector_3 + move_2d(typename C3T3::Vertex_handle v, + const C3T3& c3t3, + const typename C3T3::Subdomain_index& imaginary_index) + { + typedef typename C3T3::Edge Edge; + typedef typename C3T3::Vertex_handle Vertex_handle; + typedef typename C3T3::Triangulation::Geom_traits::Vector_3 Vector_3; + + Vector_3 move = CGAL::NULL_VECTOR; + + std::vector edges; + c3t3.triangulation().incident_edges(v, std::back_inserter(edges)); + + if (edges.empty()) + return move; + + std::size_t nbe = 0; + BOOST_FOREACH(Edge e, edges) + { + if (CGAL::is_on_domain_hull(e, c3t3, imaginary_index)) + { + Vertex_handle ve = (e.first->vertex(e.second) != v) + ? e.first->vertex(e.second) + : e.first->vertex(e.third); + move = move + Vector_3(CGAL::ORIGIN, ve->point()); + ++nbe; + } + } + + if (nbe > 0) + return (1. / nbe) * move; + else + return CGAL::NULL_VECTOR; + } + + template + typename C3T3::Triangulation::Geom_traits::Vector_3 + move_1d(typename C3T3::Vertex_handle v, + const C3T3& c3t3, + const typename C3T3::Subdomain_index& /*imaginary_index*/) + { + typedef typename C3T3::Edge Edge; + typedef typename C3T3::Vertex_handle Vertex_handle; + typedef typename C3T3::Triangulation::Geom_traits::Vector_3 Vector_3; + + Vector_3 move = CGAL::NULL_VECTOR; + + std::vector edges; + c3t3.triangulation().incident_edges(v, std::back_inserter(edges)); + + if (edges.empty()) + return move; + + std::size_t nbe = 0; + BOOST_FOREACH(Edge e, edges) + { + if (!c3t3.is_in_complex(e)) + continue; + + Vertex_handle ve = (e.first->vertex(e.second) != v) + ? e.first->vertex(e.second) + : e.first->vertex(e.third); + + move = move + Vector_3(CGAL::ORIGIN, ve->point()); + ++nbe; + } + + if (nbe == 2) + return 0.5 * move; + else + return CGAL::NULL_VECTOR; + } + + template + void smooth_vertices_new(C3T3& c3t3, + const typename C3T3::Subdomain_index& imaginary_index, + const bool /*protect_boundaries*/, + CellSelector cell_selector) + { + typedef typename C3T3::Triangulation Tr; + typedef typename C3T3::Vertex_handle Vertex_handle; + typedef typename C3T3::Cell_handle Cell_handle; + typedef typename Tr::Finite_vertices_iterator Finite_vertices_iterator; + + typedef typename Tr::Geom_traits Gt; + typedef typename Gt::Point_3 Point_3; + typedef typename Gt::Vector_3 Vector_3; + +#ifdef CGAL_TETRAHEDRAL_REMESHING_VERBOSE + std::cout << "Smooth vertices..."; + std::cout.flush(); + std::size_t nb_done = 0; CGAL_USE(nb_done); +#endif + + Tr& tr = c3t3.triangulation(); + +#ifdef CGAL_TETRAHEDRAL_REMESHING_DEBUG + CGAL::debug::dump_vertices_by_dimension(c3t3.triangulation(), "c3t3_vertices_before_smoothing"); +#endif + + const std::size_t nbv = tr.number_of_vertices(); + boost::unordered_map vertex_id; + std::vector smoothing_vecs(nbv, CGAL::NULL_VECTOR); +// std::vector neighbors(nbv, -1); + + // generate ids for vertices + std::size_t id = 0; + for (Finite_vertices_iterator vit = tr.finite_vertices_begin(); + vit != tr.finite_vertices_end(); ++vit) + { + vertex_id[vit] = id++; + } + +#ifdef CGAL_TETRAHEDRAL_REMESHING_DEBUG + std::ofstream ofs_2d("moves_on_surface.polylines.txt"); + std::ofstream ofs_1d("moves_on_features.polylines.txt"); +#endif + + // compute move depending on underlying dimension + for (Finite_vertices_iterator vit = tr.finite_vertices_begin(); + vit != tr.finite_vertices_end(); ++vit) + { + switch (vit->in_dimension()) + { + case 3: + if (is_imaginary(vit, c3t3, imaginary_index) || !is_selected(vit, c3t3, cell_selector)) + break; + else + smoothing_vecs[vertex_id.at(vit)] = move_3d(vit, c3t3); + break; + + case 2: + smoothing_vecs[vertex_id.at(vit)] = move_2d(vit, c3t3, imaginary_index); +#ifdef CGAL_TETRAHEDRAL_REMESHING_DEBUG + if (smoothing_vecs[vertex_id.at(vit)] != CGAL::NULL_VECTOR) + ofs_2d << "2 " << vit->point() + << " " << (CGAL::ORIGIN + smoothing_vecs[vertex_id.at(vit)]) << std::endl; +#endif + break; + + case 1: + smoothing_vecs[vertex_id.at(vit)] = move_1d(vit, c3t3, imaginary_index); +#ifdef CGAL_TETRAHEDRAL_REMESHING_DEBUG + if (smoothing_vecs[vertex_id.at(vit)] != CGAL::NULL_VECTOR) + ofs_1d << "2 " << vit->point() + << " " << (CGAL::ORIGIN + smoothing_vecs[vertex_id.at(vit)]) << std::endl; +#endif + + default: + break; + } + } +#ifdef CGAL_TETRAHEDRAL_REMESHING_DEBUG + ofs_2d.close(); + ofs_1d.close(); +#endif + + // apply moves + for (Finite_vertices_iterator vit = tr.finite_vertices_begin(); + vit != tr.finite_vertices_end(); ++vit) + { + const std::size_t& vid = vertex_id.at(vit); + Point_3 new_pos = CGAL::ORIGIN + smoothing_vecs[vid]; + const Vector_3 move(vit->point(), new_pos); + + std::vector cells; + tr.finite_incident_cells(vit, std::back_inserter(cells)); + + double frac = 1.; + while (frac > 0.05 /// 1/16 = 0.0625 + && !check_inversion_and_move(vit, frac * move, cells)) + { + frac = 0.5 * frac; + } + } + +#ifdef CGAL_TETRAHEDRAL_REMESHING_DEBUG + CGAL::debug::dump_vertices_by_dimension(c3t3.triangulation(), "c3t3_vertices_after_smoothing"); +#endif + } + + template + void smooth_vertices(C3T3& c3t3, + const typename C3T3::Subdomain_index&, + const bool protect_boundaries, + CellSelector cell_selector) + { + typedef typename C3T3::Surface_patch_index Surface_patch_index; + typedef typename C3T3::Subdomain_index Subdomain_index; + typedef typename C3T3::Triangulation Tr; + typedef typename C3T3::Vertex_handle Vertex_handle; + typedef typename C3T3::Cell_handle Cell_handle; + typedef typename Tr::Finite_vertices_iterator Finite_vertices_iterator; + typedef typename Tr::Finite_edges_iterator Finite_edges_iterator; + + typedef typename Tr::Geom_traits Gt; + typedef typename Gt::Point_3 Point_3; + typedef typename Gt::Vector_3 Vector_3; + typedef typename Gt::FT FT; + +#ifdef CGAL_TETRAHEDRAL_REMESHING_VERBOSE + std::cout << "Smooth vertices..."; + std::cout.flush(); + std::size_t nb_done = 0; +#endif + + Tr& tr = c3t3.triangulation(); + + const std::size_t nbv = tr.number_of_vertices(); + boost::unordered_map vertex_id; + std::vector smoothing_vecs(nbv, CGAL::NULL_VECTOR); + std::vector neighbors(nbv, -1); + + //collect ids + std::size_t id = 0; + for (Finite_vertices_iterator vit = tr.finite_vertices_begin(); + vit != tr.finite_vertices_end(); ++vit) + { + vertex_id[vit] = id++; + } + + if (!protect_boundaries) + { + for (Finite_edges_iterator eit = tr.finite_edges_begin(); + eit != tr.finite_edges_end(); ++eit) + { + const Vertex_handle vh0 = eit->first->vertex(eit->second); + const Vertex_handle vh1 = eit->first->vertex(eit->third); + + const std::size_t& i0 = vertex_id.at(vh0); + const std::size_t& i1 = vertex_id.at(vh1); + + if (/*toRemesh != REMESH_IMAGINARY &&*/ c3t3.is_in_complex(*eit)) + { + if (!is_feature(vh0, c3t3)) + neighbors[i0] = std::max(0, neighbors[i0]); + if (!is_feature(vh1, c3t3)) + neighbors[i1] = std::max(0, neighbors[i1]); + + bool update_v0 = false, update_v1 = false; + + helpers::get_edge_info(*eit, update_v0, update_v1, c3t3, cell_selector); + if (update_v0) + { + const Point_3& p1 = vh1->point(); + smoothing_vecs[i0] = smoothing_vecs[i0] + Vector_3(p1.x(), p1.y(), p1.z()); + neighbors[i0]++; + } + if (update_v1) + { + const Point_3& p0 = vh0->point(); + smoothing_vecs[i1] = smoothing_vecs[i1] + Vector_3(p0.x(), p0.y(), p0.z()); + neighbors[i1]++; + } + } + } + + //collect a map of vertices subdomain indices + boost::unordered_map > vertices_subdomain_indices; + for (typename C3T3::Cell_iterator cit = c3t3.cells_in_complex_begin(); + cit != c3t3.cells_in_complex_end(); ++cit) + { + for (int i = 0; i < 4; ++i) + { + Vertex_handle vi = cit->vertex(i); + Subdomain_index si = cit->subdomain_index(); + + if (vertices_subdomain_indices.find(vi) == vertices_subdomain_indices.end()) + { + std::vector indices(1); + indices[0] = si; + vertices_subdomain_indices.insert(std::make_pair(vi, indices)); + } + else + { + std::vector& v_indices = vertices_subdomain_indices.at(vi); + if (std::find(v_indices.begin(), v_indices.end(), si) == v_indices.end()) + v_indices.push_back(si); + } + } + } + + //collect a map of vertices surface indices + boost::unordered_map > vertices_surface_indices; + for(typename C3T3::Facet_iterator fit = c3t3.facets_in_complex_begin(); + fit != c3t3.facets_in_complex_end(); ++fit) + { + Surface_patch_index surface_index + = helpers::make_surface_patch_index(fit->first->subdomain_index(), + fit->first->neighbor(fit->second)->subdomain_index()); + for (int i = 0; i < 3; ++i) + { + Vertex_handle vi = fit->first->vertex(indices(fit->second, i)); + if (vertices_subdomain_indices.at(vi).size() > 2) + { + if (vertices_surface_indices.find(vi) == vertices_surface_indices.end()) + { + std::vector indices(1); + indices[0] = surface_index; + vertices_surface_indices.insert(std::make_pair(vi, indices)); + } + else + { + std::vector& v_surface_indices = vertices_surface_indices.at(vi); + if (std::find(v_surface_indices.begin(), v_surface_indices.end(), surface_index) + == v_surface_indices.end()) + v_surface_indices.push_back(surface_index); + } + } + } + } + + //collect a map of normals at surface vertices + boost::unordered_map > vertices_normals; + for (Finite_vertices_iterator vit = tr.finite_vertices_begin(); + vit != tr.finite_vertices_end(); ++vit) + { + const std::size_t& vid = vertex_id.at(vit); + if (neighbors[vid] > 1) + { + Point_3 smoothed_position = CGAL::ORIGIN + smoothing_vecs[vid] / neighbors[vid]; + Vector_3 final_move = CGAL::NULL_VECTOR; + Point_3 final_position; + + std::size_t count = 0; + Point_3 current_pos = vit->point(); + + const std::vector& v_surface_indices = vertices_surface_indices[vit]; + for (std::size_t i = 0; i < v_surface_indices.size(); ++i) + { + const Surface_patch_index& si = v_surface_indices[i]; + + Vector_3 normal_projection + = project_on_tangent_plane(smoothed_position, current_pos, vertices_normals[vit][si]); + + //Check if the mls surface exists to avoid degenrated cases + Vector_3 mls_projection; + if (project(si, normal_projection, mls_projection)){ + final_move = final_move + mls_projection; + } + else { + final_move = final_move + normal_projection; + } + count++; + } + + if (count > 0) + final_position = CGAL::ORIGIN + final_move / static_cast(count); + else + final_position = smoothed_position; + + // move vertex + vit->set_point(final_position); + + } + else if (neighbors[vid] > 0) + { + Vector_3 final_move = CGAL::NULL_VECTOR; + Point_3 final_position; + + int count = 0; + Vector_3 current_move(CGAL::ORIGIN, vit->point()); + + const std::vector& v_surface_indices = vertices_surface_indices[vit]; + for (std::size_t i = 0; i < v_surface_indices.size(); ++i) + { + Surface_patch_index si = v_surface_indices[i]; + //Check if the mls surface exists to avoid degenrated cases + + Vector_3 mls_projection; + if (project(si, current_move, mls_projection)){ + final_move = final_move + mls_projection; + } + else { + final_move = final_move + current_move; + } + count++; + } + + if (count > 0) + final_position = CGAL::ORIGIN + final_move / count; + else + final_position = CGAL::ORIGIN + current_move; + + // move vertex + vit->set_point(final_position); + } + } + + smoothing_vecs.clear(); + smoothing_vecs.resize(nbv, CGAL::NULL_VECTOR); + + neighbors.clear(); + neighbors.resize(nbv, -1); + + for (Finite_edges_iterator eit = tr.finite_edges_begin(); + eit != tr.finite_edges_end(); ++eit) + { + const Vertex_handle vh0 = eit->first->vertex(eit->second); + const Vertex_handle vh1 = eit->first->vertex(eit->third); + + const std::size_t& i0 = vertex_id.at(vh0); + const std::size_t& i1 = vertex_id.at(vh1); + + if ((/*toRemesh != REMESH_IN_COMPLEX &&*/ is_on_hull(*eit, c3t3)) + || (/*toRemesh != REMESH_IMAGINARY &&*/ + helpers::is_boundary(c3t3, *eit, cell_selector) && !c3t3.is_in_complex(*eit))) + { + bool update_v0 = false, update_v1 = false; + if (!is_feature(vh0, c3t3)) + neighbors[i0] = (std::max)(0, neighbors[i0]); + if (!is_feature(vh1, c3t3)) + neighbors[i1] = (std::max)(0, neighbors[i1]); + + helpers::get_edge_info(*eit, update_v0, update_v1, c3t3, cell_selector); + if (update_v0) + { + const Point_3& p1 = vh1->point(); + smoothing_vecs[i0] = smoothing_vecs[i0] + Vector_3(p1.x(), p1.y(), p1.z()); + neighbors[i0]++; + } + if (update_v1) + { + const Point_3& p0 = vh0->point(); + smoothing_vecs[i1] = smoothing_vecs[i1] + Vector_3(p0.x(), p0.y(), p0.z()); + neighbors[i1]++; + } + } + } + + for (Finite_vertices_iterator vit = tr.finite_vertices_begin(); + vit != tr.finite_vertices_end(); ++vit) + { + const std::size_t& vid = vertex_id.at(vit); + + if (neighbors[vid] > 1) + { + Point_3 smoothed_position = CGAL::ORIGIN + smoothing_vecs[vid] / neighbors[vid]; + Point_3 current_pos = vit->point(); + Point_3 final_position = CGAL::ORIGIN; + + if (vit->in_dimension() == 3 && is_on_hull(vit, c3t3)) + { + Vector_3 final_move = project_on_tangent_plane( + smoothed_position, current_pos, vertices_normals[vit][Surface_patch_index()]); + final_position = CGAL::ORIGIN + final_move; + } + else { + // Surface_patch_index si = helpers::make_surface_patch_index( + // vertices_subdomain_indices[vit][0], vertices_subdomain_indices[vit][1]); + + // Vector_3 normal_projection = project_on_tangent_plane(smoothed_position, + // current_pos, + // vertices_normals[vit][si]); + //Vector_3 mls_projection; + //if (project(si, normal_projection, mls_projection) /*|| project( si, smoothed_position, mls_projection )*/){ + // final_position = mls_projection; + // //final_position = smoothed_position; + //} + //else { + final_position = smoothed_position; + //} + // std::cout << "MLS " << final_position[0] << " - " << final_position[1] << " : " << final_position[2] << std::endl; + } + /* + Normal_iterator it = vertices_normals[vit->info()].end(); + it--; + final_position = final_position + projectOnTangentPlane( smoothed_position, current_pos , it->second ); + */ + + vit->set_point(final_position); + } + else if (neighbors[vid] > 0) + { + if (vit->in_dimension() == 2) + { + // Surface_patch_index si = helpers::make_surface_patch_index( + // vertices_subdomain_indices[vit][0], + // vertices_subdomain_indices[vit][1]); + + Vector_3 current_pos(CGAL::ORIGIN, vit->point()); + Vector_3 mls_projection; +// if (project(si, current_pos, mls_projection) /*|| project( si, smoothed_position, mls_projection )*/){ +// vit->set_point(Point_3(mls_projection.x(), mls_projection.y(), mls_projection.z())); +// } + } + } + } + } + smoothing_vecs.clear(); + smoothing_vecs.resize(nbv, CGAL::NULL_VECTOR); + + neighbors.clear(); + neighbors.resize(nbv, 0); + + for (Finite_edges_iterator eit = tr.finite_edges_begin(); + eit != tr.finite_edges_end(); ++eit) + { + //bool in_complex = c3t3.is_in_complex(*eit); + //if ( toRemesh == REMESH_ALL + // || (toRemesh == REMESH_IN_COMPLEX && in_complex) + // || (toRemesh == REMESH_IMAGINARY && !in_complex)) + { + const Vertex_handle vh0 = eit->first->vertex(eit->second); + const Vertex_handle vh1 = eit->first->vertex(eit->third); + + const std::size_t& i0 = vertex_id.at(vh0); + const std::size_t& i1 = vertex_id.at(vh1); + + if (c3t3.in_dimension(vh0) == 3 && !is_on_hull(vh0, c3t3)) + { + const Point_3& p1 = vh1->point(); + smoothing_vecs[i0] = smoothing_vecs[i0] + Vector_3(CGAL::ORIGIN, p1); + neighbors[i0]++; + } + if (c3t3.in_dimension(vh1) == 3 && !is_on_hull(vh1, c3t3)) + { + const Point_3& p0 = vh0->point(); + smoothing_vecs[i1] = smoothing_vecs[i1] + Vector_3(CGAL::ORIGIN, p0); + neighbors[i1]++; + } + } + } + + for (Finite_vertices_iterator vit = tr.finite_vertices_begin(); + vit != tr.finite_vertices_end(); ++vit) + { + const std::size_t& vid = vertex_id.at(vit); + if (neighbors[vid] > 1) + { + if (smoothing_vecs[vid] != CGAL::NULL_VECTOR) + { +#ifdef CGAL_TETRAHEDRAL_REMESHING_VERBOSE + ++nb_done; +#endif + Point_3 new_pos = CGAL::ORIGIN + smoothing_vecs[vid] / neighbors[vid]; + const Vector_3 move(vit->point(), new_pos); + + std::vector cells; + tr.finite_incident_cells(vit, std::back_inserter(cells)); + + bool selected = true; + for (std::size_t i = 0; i < cells.size(); ++i) + { + if (!cell_selector(cells[i])) + { + selected = false; + break; + } + } + if (!selected) + continue; + + double frac = 1.; + while (frac > 0.05 /// 1/16 = 0.0625 + && !check_inversion_and_move(vit, frac * move, cells)) + { + frac = 0.5 * frac; + } + } + } + } + +#ifdef CGAL_TETRAHEDRAL_REMESHING_VERBOSE + std::cout << " done (" << nb_done << " vertices smoothed)." << std::endl; +#endif + } + +}//namespace internal +}//namespace Tetrahedral_adaptive_remeshing +}//namespace CGAL + +#endif //CGAL_INTERNAL_SMOOTH_VERTICES_H diff --git a/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/split_long_edges.h b/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/split_long_edges.h new file mode 100644 index 00000000000..0eaaa87df1a --- /dev/null +++ b/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/split_long_edges.h @@ -0,0 +1,273 @@ +// Copyright (c) 2019 GeometryFactory (France). +// All rights reserved. +// +// This file is part of CGAL (www.cgal.org). +// You can redistribute it and/or modify it under the terms of the GNU +// General Public License as published by the Free Software Foundation, +// either version 3 of the License, or (at your option) any later version. +// +// Licensees holding a valid commercial license may use this file in +// accordance with the commercial license agreement provided with the software. +// +// This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE +// WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. +// +// $URL$ +// $Id$ +// SPDX-License-Identifier: GPL-3.0+ +// +// +// Author(s) : Jane Tournois + +#ifndef CGAL_INTERNAL_SPLIT_LONG_EDGES_H +#define CGAL_INTERNAL_SPLIT_LONG_EDGES_H + +#include +#include +#include +#include + +#include + +#include +#include + +namespace CGAL +{ +namespace Tetrahedral_remeshing +{ +namespace internal +{ + template + typename C3t3::Vertex_handle split_edge(const typename C3t3::Edge& e, + C3t3& c3t3) + { + typedef typename C3t3::Triangulation Tr; + typedef typename C3t3::Subdomain_index Subdomain_index; + typedef typename Tr::Point Point; + typedef typename Tr::Facet Facet; + typedef typename Tr::Vertex_handle Vertex_handle; + typedef typename Tr::Cell_handle Cell_handle; + typedef typename Tr::Cell_circulator Cell_circulator; + typedef typename Tr::Cell::Info Cell_info; + + Tr& tr = c3t3.triangulation(); + Vertex_handle v1 = e.first->vertex(e.second); + Vertex_handle v2 = e.first->vertex(e.third); + + //backup subdomain info of incident cells before making changes + short dimension = (c3t3.is_in_complex(e)) ? 1 : 3; + boost::unordered_map > info; + + Cell_circulator circ = tr.incident_cells(e); + Cell_circulator end = circ; + Subdomain_index prev = c3t3.subdomain_index(circ); + Subdomain_index curr = prev; + do + { + //keys are the opposite facets to the ones not containing e, + //because they will not be modified + Facet opp_facet = tr.mirror_facet(Facet(circ, circ->index(v1))); + info.insert(std::make_pair(opp_facet, + std::make_pair(c3t3.subdomain_index(circ), circ->info()))); + + opp_facet = tr.mirror_facet(Facet(circ, circ->index(v2))); + info.insert(std::make_pair(opp_facet, + std::make_pair(c3t3.subdomain_index(circ), circ->info()))); + + ++circ; + prev = curr; + curr = c3t3.subdomain_index(circ); + + if (prev != curr && dimension == 3) + dimension = 2; + } while (circ != end); + + // insert midpoint + Vertex_handle new_v = tr.tds().insert_in_edge(e); + const Point m = CGAL::midpoint(v1->point(), v2->point()); + new_v->set_point(m); + + // update dimension + c3t3.set_dimension(new_v, dimension); + + // update c3t3 + std::vector new_cells; + tr.incident_cells(new_v, std::back_inserter(new_cells)); + for (std::size_t i = 0; i < new_cells.size(); ++i) + { + Cell_handle nci = new_cells[i]; + Facet fi(nci, nci->index(new_v)); + Subdomain_index n_index = info.at(tr.mirror_facet(fi)).first; + c3t3.set_subdomain_index(nci, n_index); + nci->info() = info.at(tr.mirror_facet(fi)).second; + } + + return new_v; + } + + template + bool can_be_split(const typename C3T3::Edge& e, + const C3T3& c3t3, + const bool protect_boundaries, + const typename C3T3::Subdomain_index& imaginary_index, + CellSelector cell_selector) + { + if (is_outside(e, c3t3, imaginary_index, cell_selector)) + return false; + if (is_imaginary(e, c3t3, imaginary_index)) + return false; + +#ifdef CGAL_LIMITED_APERTURE_EDGE_SELECTION + if (CGAL::helpers::is_on_the_outer_box(e, c3t3, imaginary_index)) + return true; +#endif + + if (protect_boundaries) + { + if (c3t3.is_in_complex(e)) + return false; + else if (helpers::is_boundary(c3t3, e, cell_selector)) + return false; + +#ifdef CGAL_TETRAHEDRAL_REMESHING_DEBUG + if (!is_inside(e, c3t3, imaginary_index, cell_selector)) + { + std::cerr << "e is not inside!?" << std::endl; + typename C3T3::Vertex_handle v1 = e.first->vertex(e.second); + typename C3T3::Vertex_handle v2 = e.first->vertex(e.third); + std::cerr << v1->point() << " " << v2->point() << std::endl; + } +#endif + + CGAL_assertion(is_inside(e, c3t3, imaginary_index, cell_selector)); + return true; + } + else + { + return true; + } + } + + template + void split_long_edges(C3T3& c3t3, + const typename C3T3::Triangulation::Geom_traits::FT& high, + const bool protect_boundaries, + const typename C3T3::Subdomain_index& imaginary_index, + CellSelector cell_selector) + { + typedef typename C3T3::Triangulation T3; + typedef typename T3::Cell_handle Cell_handle; + typedef typename T3::Edge Edge; + typedef typename T3::Finite_edges_iterator Finite_edges_iterator; + typedef typename T3::Vertex_handle Vertex_handle; + typedef typename std::pair Edge_vv; + + typedef typename T3::Geom_traits::FT FT; + typedef boost::bimap< + boost::bimaps::set_of, + boost::bimaps::multiset_of > > Boost_bimap; + typedef typename Boost_bimap::value_type long_edge; + +#ifdef CGAL_TETRAHEDRAL_REMESHING_VERBOSE + std::cout << "Split long edges (" << high << ")..."; + std::cout.flush(); + std::size_t nb_splits = 0; +#endif + const FT sq_high = high*high; + + //collect long edges + T3& tr = c3t3.triangulation(); + Boost_bimap long_edges; + for (Finite_edges_iterator eit = tr.finite_edges_begin(); + eit != tr.finite_edges_end(); ++eit) + { + Edge e = *eit; + if (!can_be_split(e, c3t3, protect_boundaries, imaginary_index, cell_selector)) + continue; + + FT sqlen = tr.segment(e).squared_length(); + if (sqlen > sq_high) + long_edges.insert(long_edge(make_vertex_pair(e), sqlen)); + } + +#ifdef CGAL_TETRAHEDRAL_REMESHING_DEBUG + helpers::dump_edges(long_edges, "long_edges.polylines.txt"); + + std::ofstream ofs("midpoints.off"); + ofs << "OFF" << std::endl; + ofs << long_edges.size() << " 0 0" << std::endl; +#endif + while(!long_edges.empty()) + { + //the edge with longest length + typename Boost_bimap::right_map::iterator eit = long_edges.right.begin(); + Edge_vv e = eit->second; +#ifdef CGAL_TETRAHEDRAL_REMESHING_VERBOSE_PROGRESS + const double sqlen = eit->first; +#endif + long_edges.right.erase(eit); + + Cell_handle cell; + int i1, i2; + if ( tr.tds().is_edge(e.first, e.second, cell, i1, i2)) + { + Edge edge(cell, i1, i2); + + //check that splittability has not changed + if (!can_be_split(edge, c3t3, protect_boundaries, imaginary_index, cell_selector)) + continue; + + Vertex_handle vh = split_edge(edge, c3t3); + //CGAL_assertion(tr.is_valid(true)); + +#ifdef CGAL_TETRAHEDRAL_REMESHING_DEBUG + ofs << vh->point() << std::endl; +#endif + if (vh != Vertex_handle()) + { +#if defined(CGAL_TETRAHEDRAL_REMESHING_VERBOSE_PROGRESS) \ + || defined(CGAL_TETRAHEDRAL_REMESHING_VERBOSE) + ++nb_splits; +#endif + ////insert newly created edges if needed + //std::vector new_edges; + //tr.incident_edges(vh, std::back_inserter(new_edges)); + // + //for (std::size_t i = 0; i < new_edges.size(); ++i) + //{ + // const Edge& ei = new_edges[i]; + // Segment seg(ei.first->vertex(ei.second)->point(), + // ei.first->vertex(ei.third)->point()); + // + // const FT sqlen_i = seg.squared_length(); + // if (sqlen_i > sq_high) + // long_edges.insert(long_edge(make_vertex_pair(ei), sqlen_i)); + //} + } + +#ifdef CGAL_TETRAHEDRAL_REMESHING_VERBOSE_PROGRESS + std::cout << "\rSplit (" << high << ")... (" + << long_edges.left.size() << " long edges, " + << "length = " << std::sqrt(sqlen) << ", " + << std::sqrt(CGAL::squared_distance(e.first->point(), e.second->point())) << ", " + << nb_splits << " splits)"; + std::cout.flush(); +#endif + } + }//end loop on long_edges + +#ifdef CGAL_TETRAHEDRAL_REMESHING_DEBUG + if(ofs.is_open()) + ofs.close(); +#endif + +#ifdef CGAL_TETRAHEDRAL_REMESHING_VERBOSE + std::cout << " done (" << nb_splits << " splits)." << std::endl; +#endif + } +} +} +} + +#endif // CGAL_INTERNAL_SPLIT_LONG_EDGES_H diff --git a/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/tetrahedral_adaptive_remeshing_impl.h b/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/tetrahedral_adaptive_remeshing_impl.h new file mode 100644 index 00000000000..5c418f079ba --- /dev/null +++ b/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/tetrahedral_adaptive_remeshing_impl.h @@ -0,0 +1,423 @@ +// Copyright (c) 2019 GeometryFactory (France). +// All rights reserved. +// +// This file is part of CGAL (www.cgal.org). +// You can redistribute it and/or modify it under the terms of the GNU +// General Public License as published by the Free Software Foundation, +// either version 3 of the License, or (at your option) any later version. +// +// Licensees holding a valid commercial license may use this file in +// accordance with the commercial license agreement provided with the software. +// +// This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE +// WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. +// +// $URL$ +// $Id$ +// SPDX-License-Identifier: GPL-3.0+ +// +// +// Author(s) : Jane Tournois + +#ifndef TETRAHEDRAL_REMESHING_IMPL_H +#define TETRAHEDRAL_REMESHING_IMPL_H + +#ifdef CGAL_TETRAHEDRAL_REMESHING_VERBOSE_PROGRESS +#define CGAL_TETRAHEDRAL_REMESHING_VERBOSE +#endif + +#include +#include + +#include +#include +#include +#include +#include + +#include + +#ifdef CGAL_TETRAHEDRAL_REMESHING_DEBUG +#include "../../../limited_aperture_helpers.h" +#endif + +namespace CGAL +{ +namespace Tetrahedral_remeshing +{ +namespace internal +{ + template + struct All_cells_selected + { + typedef typename Tr::Cell_handle argument_type; + typedef bool result_type; + result_type operator()(const argument_type) const + { + return true; + } + }; + + template + struct No_constraint_pmap + { + public: + typedef Primitive key_type; + typedef bool value_type; + typedef value_type& reference; + typedef boost::read_write_property_map_tag category; + + friend bool get(const No_constraint_pmap&, const key_type&) { + return false; + } + friend void put(No_constraint_pmap&, const key_type&, const bool) {} + }; + + template + class Adaptive_remesher + { + typedef Triangulation Tr; + typedef typename Tr::Geom_traits::FT FT; + + typedef int Corner_index; + typedef int Curve_segment_index; + typedef typename CGAL::Mesh_complex_3_in_triangulation_3 C3t3; + + typedef typename C3t3::Cell_handle Cell_handle; + typedef typename C3t3::Vertex_handle Vertex_handle; + typedef typename C3t3::Surface_patch_index Surface_patch_index; + typedef typename C3t3::Subdomain_index Subdomain_index; + + private: + const FT& m_target_edge_length; + const bool m_protect_boundaries; +// const bool m_adaptive;//adaptive sizing field TODO, outside remeshing + C3t3 m_c3t3; + Triangulation& m_tr; //backup to re-swap triangulations when done + CellSelector m_cell_selector; + Subdomain_index m_imaginary_index; + + public: + Adaptive_remesher(Triangulation& tr + , const FT& target_edge_length + , const bool protect_boundaries + , EdgeIsConstrainedMap ecmap + , CellSelector cell_selector +// , const bool adaptive + ) + : m_target_edge_length(target_edge_length) + , m_protect_boundaries(protect_boundaries) +// , m_adaptive(adaptive) + , m_c3t3() + , m_tr(tr) + , m_cell_selector(cell_selector) + { + m_c3t3.triangulation().swap(tr); + init_c3t3(ecmap); + +#ifdef CGAL_DUMP_REMESHING_STEPS + CGAL::debug::dump_without_imaginary(m_c3t3.triangulation(), + "00-init-no-imaginary.mesh", m_imaginary_index); +#endif + } + + const Subdomain_index& imaginary_index() const + { + return m_imaginary_index; + } + + void preprocess() + { +#ifdef CGAL_TETRAHEDRAL_REMESHING_VERBOSE + std::cout << "Preprocess..."; + std::cout.flush(); +#endif + + add_layer_of_imaginary_tets(tr(), m_imaginary_index); + CGAL_assertion(tr().is_valid(true)); + +#ifdef CGAL_DUMP_REMESHING_STEPS + CGAL::debug::dump_triangulation_cells(tr(), "0-preprocess.mesh"); + CGAL::debug::dump_without_imaginary(tr(), + "0-preprocess-no-imaginary.mesh", m_imaginary_index); +#endif +#ifdef CGAL_TETRAHEDRAL_REMESHING_VERBOSE + std::cout << "done." << std::endl; +#endif + } + + void split() + { + CGAL_assertion(check_vertex_dimensions()); + + FT emax = FT(4)/FT(3) * m_target_edge_length; + split_long_edges(m_c3t3, emax, m_protect_boundaries, m_imaginary_index, + m_cell_selector); + + CGAL_assertion(tr().is_valid(true)); +#ifdef CGAL_DUMP_REMESHING_STEPS + CGAL::debug::dump_triangulation_cells(tr(), "1-split.mesh"); + CGAL::debug::dump_without_imaginary(tr(), + "1-split-no-imaginary.mesh", m_imaginary_index); +#endif + } + + void collapse() + { + CGAL_assertion(check_vertex_dimensions()); + + FT emin = FT(4)/FT(5) * m_target_edge_length; + FT emax = FT(4)/FT(3) * m_target_edge_length; + collapse_short_edges(m_c3t3, emin, emax, m_protect_boundaries, + m_imaginary_index, + m_cell_selector); + + CGAL_assertion(tr().is_valid(true)); +#ifdef CGAL_DUMP_REMESHING_STEPS + CGAL::debug::dump_triangulation_cells(tr(), "2-collapse.mesh"); + CGAL::debug::dump_without_imaginary(tr(), + "2-collapse-no-imaginary.mesh", m_imaginary_index); +#endif + } + + void flip() + { + flip_edges(m_c3t3, m_imaginary_index, m_protect_boundaries, + m_cell_selector); + + CGAL_assertion(tr().is_valid(true)); +#ifdef CGAL_DUMP_REMESHING_STEPS + CGAL::debug::dump_triangulation_cells(tr(), "3-flip.mesh"); + CGAL::debug::dump_without_imaginary(tr(), + "3-flip-no-imaginary.mesh", m_imaginary_index); +#endif + } + + void smooth() + { + smooth_vertices_new(m_c3t3, m_imaginary_index, m_protect_boundaries, + m_cell_selector); + + CGAL_assertion(tr().is_valid(true)); +#ifdef CGAL_DUMP_REMESHING_STEPS + CGAL::debug::dump_triangulation_cells(tr(), "4-smooth.mesh"); + CGAL::debug::dump_without_imaginary(tr(), + "4-smooth-no-imaginary.mesh", m_imaginary_index); +#endif + } + + bool resolution_reached() + { + FT emax = FT(4) / FT(3) * m_target_edge_length; + FT emin = FT(4) / FT(5) * m_target_edge_length; + + FT sqmax = emax * emax; + FT sqmin = emin * emin; + + typedef typename Tr::Finite_edges_iterator Finite_edges_iterator; + for (Finite_edges_iterator eit = tr().finite_edges_begin(); + eit != tr().finite_edges_end(); + ++eit) + { + typename Tr::Edge e = *eit; + // skip protected edges + if (m_protect_boundaries) + { + if( m_c3t3.is_in_complex(e) + || helpers::is_boundary(m_c3t3, e, m_cell_selector)) + continue; + } + // skip imaginary edges + if (is_imaginary(e, m_c3t3, m_imaginary_index)) + continue; + + FT sqlen = tr().segment(e).squared_length(); + if (sqlen < sqmin || sqlen > sqmax) + return false; + } + std::cout << "Resolution reached" << std::endl; + return true; + } + + void postprocess() + { +#ifdef CGAL_TETRAHEDRAL_REMESHING_VERBOSE + std::cout << "Postprocess..."; + std::cout.flush(); +#endif + ///TODO + + CGAL_assertion(tr().is_valid(true)); +#ifdef CGAL_DUMP_REMESHING_STEPS + CGAL::debug::dump_triangulation_cells(tr(), "99-postprocess.mesh"); + CGAL::debug::dump_without_imaginary(tr(), + "99-postprocess-no-imaginary.mesh", m_imaginary_index); +#endif +#ifdef CGAL_TETRAHEDRAL_REMESHING_VERBOSE + std::cout << "done." << std::endl; +#endif + } + + void finalize() + { + m_tr.swap(m_c3t3.triangulation()); + } + + const Tr& triangulation() const + { + return m_c3t3.triangulation(); + } + + private: + Tr& tr() + { + return m_c3t3.triangulation(); + } + + void init_c3t3(const EdgeIsConstrainedMap& ecmap) + { +#ifdef CGAL_TETRAHEDRAL_REMESHING_DEBUG + std::size_t nbc = 0; + std::size_t nbf = 0; + std::size_t nbe = 0; + std::size_t nbv = 0; +#endif + + Subdomain_index max_si = tr().finite_cells_begin()->subdomain_index(); + + //tag cells (no imaginary cell yet) + typedef typename Tr::Finite_cells_iterator Finite_cells_iterator; + for (Finite_cells_iterator cit = tr().finite_cells_begin(); + cit != tr().finite_cells_end(); + ++cit) + { + if (cit->subdomain_index() != Subdomain_index()) + { + m_c3t3.add_to_complex(cit, cit->subdomain_index()); + max_si = (std::max)(max_si, cit->subdomain_index()); +#ifdef CGAL_TETRAHEDRAL_REMESHING_DEBUG + ++nbc; +#endif + } + + for (int i = 0; i < 4; ++i) + { + if (cit->vertex(i)->in_dimension() == -1) + cit->vertex(i)->set_dimension(3); + } + } + m_imaginary_index = max_si + 1; + + //tag facets + typedef typename Tr::Facet Facet; + typedef typename Tr::Finite_facets_iterator Finite_facets_iterator; + for (Finite_facets_iterator fit = tr().finite_facets_begin(); + fit != tr().finite_facets_end(); + ++fit) + { + Facet f = *fit; + Facet mf = tr().mirror_facet(f); + Subdomain_index s1 = f.first->subdomain_index(); + Subdomain_index s2 = mf.first->subdomain_index(); + if (s1 != s2) + { + if(s1 < s2) + m_c3t3.add_to_complex(f, helpers::make_surface_patch_index(s1, s2)); + else + m_c3t3.add_to_complex(f, helpers::make_surface_patch_index(s2, s1)); +#ifdef CGAL_TETRAHEDRAL_REMESHING_DEBUG + ++nbf; +#endif + const int i = f.second; + for (int j = 0; j < 3; ++j) + { + Vertex_handle vij = f.first->vertex(Tr::vertex_triple_index(i, j)); + if (vij->in_dimension() == -1 || vij->in_dimension() > 2) + vij->set_dimension(2); + } + } + } +#ifdef CGAL_TETRAHEDRAL_REMESHING_DEBUG + CGAL::debug::dump_facets_in_complex(m_c3t3, "facets_in_complex.off"); +#endif + + //tag edges + typedef typename Tr::Edge Edge; + typedef typename Tr::Finite_edges_iterator Finite_edges_iterator; + for (Finite_edges_iterator eit = tr().finite_edges_begin(); + eit != tr().finite_edges_end(); + ++eit) + { + Edge e = *eit; + if (get(ecmap, e) || nb_incident_subdomains(e, m_c3t3) > 2) + { + m_c3t3.add_to_complex(e, 1); +#ifdef CGAL_TETRAHEDRAL_REMESHING_DEBUG + ++nbe; +#endif + Vertex_handle v = e.first->vertex(e.second); + if(v->in_dimension() == -1 || v->in_dimension() > 1) + v->set_dimension(1); + + v = e.first->vertex(e.third); + if (v->in_dimension() == -1 || v->in_dimension() > 1) + v->set_dimension(1); + } + } +#ifdef CGAL_TETRAHEDRAL_REMESHING_DEBUG + CGAL::debug::dump_edges_in_complex(m_c3t3, "edges_in_complex.polylines.txt"); +#endif + + //tag vertices + typedef typename Tr::Finite_vertices_iterator Finite_vertices_iterator; + unsigned int corner_id = 0; + for (Finite_vertices_iterator vit = tr().finite_vertices_begin(); + vit != tr().finite_vertices_end(); + ++vit) + { + if (vit->in_dimension() == 0 || nb_incident_complex_edges(vit, m_c3t3) > 2) + { + m_c3t3.add_to_complex(vit, ++corner_id); +#ifdef CGAL_TETRAHEDRAL_REMESHING_DEBUG + ++nbv; +#endif + if (vit->in_dimension() == -1 || vit->in_dimension() > 0) + vit->set_dimension(0); + } + } + +#ifdef CGAL_TETRAHEDRAL_REMESHING_DEBUG + std::cout << "C3t3 ready :" << std::endl; + std::cout << "\t cells = " << nbc << std::endl; + std::cout << "\t facets = " << nbf << std::endl; + std::cout << "\t edges = " << nbe << std::endl; + std::cout << "\t vertices = " << nbv << std::endl; + + CGAL::debug::dump_vertices_by_dimension(m_c3t3.triangulation(), "c3t3_vertices_"); +#endif + } + + private: + + bool check_vertex_dimensions() + { + typename Tr::Finite_vertices_iterator vit; + for (vit = tr().finite_vertices_begin(); + vit != tr().finite_vertices_end(); ++vit) + { + if (vit->in_dimension() < 0 || vit->in_dimension() > 3) + return false; + } + return true; + } + + };//end class Adaptive_remesher +}//end namespace internal +}//end namespace Tetrahedral_remeshing +}//end namespace CGAL + +#endif //TETRAHEDRAL_REMESHING_IMPL_H diff --git a/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/tetrahedral_remeshing_helpers.h b/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/tetrahedral_remeshing_helpers.h new file mode 100644 index 00000000000..af55a30024c --- /dev/null +++ b/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/tetrahedral_remeshing_helpers.h @@ -0,0 +1,387 @@ +// Copyright (c) 2019 GeometryFactory (France). +// All rights reserved. +// +// This file is part of CGAL (www.cgal.org). +// You can redistribute it and/or modify it under the terms of the GNU +// General Public License as published by the Free Software Foundation, +// either version 3 of the License, or (at your option) any later version. +// +// Licensees holding a valid commercial license may use this file in +// accordance with the commercial license agreement provided with the software. +// +// This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE +// WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. +// +// $URL$ +// $Id$ +// SPDX-License-Identifier: GPL-3.0+ +// +// +// Author(s) : Jane Tournois + +#ifndef CGAL_INTERNAL_TET_REMESHING_HELPERS_H +#define CGAL_INTERNAL_TET_REMESHING_HELPERS_H + +#include + +namespace CGAL +{ +namespace Tetrahedral_remeshing +{ + enum Subdomain_relation { EQUAL, DIFFERENT, INCLUDED, INCLUDES }; + enum Sliver_removal_result { INVALID_ORIENTATION, INVALID_CELL, INVALID_VERTEX, + NOT_FLIPPABLE, EDGE_PROBLEM, VALID_FLIP, NO_BEST_CONFIGURATION, EXISTING_EDGE }; + +namespace helpers +{ + template + std::pair + make_surface_patch_index(const SubdomainIndex& s1, const SubdomainIndex& s2) + { + CGAL_assertion(s1 != s2); + if (s1 < s2) + return std::make_pair(s1, s2); + else + return std::make_pair(s2, s1); + } + + template + bool is_boundary(const C3T3& c3t3, + const typename C3T3::Triangulation::Edge& e, + CellSelector cell_selector) + { + typedef typename C3T3::Triangulation Tr; + typedef typename Tr::Facet_circulator Facet_circulator; + typedef typename Tr::Facet Facet; + + Facet_circulator fcirc = c3t3.triangulation().incident_facets(e); + Facet_circulator fend = fcirc; + std::vector boundary_facets; + + do + { + Facet f = *fcirc; + if (c3t3.is_in_complex(f)) + return true; + else if (cell_selector(f.first) // XOR + ^ cell_selector(f.first->neighbor(f.second))) + return true; + else if (c3t3.triangulation().is_infinite(f) //XOR + ^ c3t3.triangulation().is_infinite(f.first->neighbor(f.second))) + return true; + + ++fcirc; + } while (fcirc != fend); + + return false; + } + + template + bool is_boundary_edge(const typename C3t3::Vertex_handle& v0, + const typename C3t3::Vertex_handle& v1, + const C3t3& c3t3, + CellSelector cell_selector) + { + typedef typename C3t3::Edge Edge; + typedef typename C3t3::Cell_handle Cell_handle; + + Cell_handle cell; + int i0, i1; + if (c3t3.triangulation().tds().is_edge(v0, v1, cell, i0, i1)) + return is_boundary(c3t3, Edge(cell, i0, i1), cell_selector); + else + return false; + } + + template + bool is_boundary_vertex(const typename C3t3::Vertex_handle& v, + const C3t3& c3t3, + CellSelector cell_selector) + { + typedef typename C3t3::Facet Facet; + std::vector facets; + c3t3.triangulation().incident_facets(v, std::back_inserter(facets)); + + BOOST_FOREACH(Facet f, facets) + { + if (c3t3.is_in_complex(f)) + return true; + if (cell_selector(f.first) ^ cell_selector(f.first->neighbor(f.second))) + return true; + } + return false; + } + + template + bool is_edge_in_complex(const typename C3t3::Vertex_handle& v0, + const typename C3t3::Vertex_handle& v1, + const C3t3& c3t3, + CellSelector /*cell_selector*/) + { + typedef typename C3t3::Edge Edge; + typedef typename C3t3::Cell_handle Cell_handle; + + Cell_handle cell; + int i0, i1; + if (c3t3.triangulation().tds().is_edge(v0, v1, cell, i0, i1)) + return c3t3.is_in_complex(Edge(cell, i0, i1)); + else + return false; + } + + template + bool topology_test(const typename C3t3::Edge& edge, + const C3t3& c3t3, + CellSelector cell_selector) + { + typedef typename C3t3::Vertex_handle Vertex_handle; + typedef typename C3t3::Triangulation::Facet_circulator Facet_circulator; + typedef typename C3t3::Subdomain_index Subdomain_index; + + Vertex_handle v0 = edge.first->vertex(edge.second); + Vertex_handle v1 = edge.first->vertex(edge.third); + + Facet_circulator fcirc = c3t3.triangulation().incident_facets(edge); + Facet_circulator fdone = fcirc; + do + { + if (c3t3.triangulation().is_infinite(fcirc->first)) + continue; + + Subdomain_index si_circ = fcirc->first->subdomain_index(); + Subdomain_index si_neigh = fcirc->first->neighbor(fcirc->second)->subdomain_index(); + if (si_circ == si_neigh) + { + //Get the ids of the opposite vertices + for (int i = 1; i < 4; i++) + { + Vertex_handle vi = fcirc->first->vertex((fcirc->second + i) % 4); + if (vi != v0 && vi != v1 && nb_incident_subdomains(vi, c3t3) > 1) + { + if ( is_edge_in_complex(v0, vi, c3t3, cell_selector) + && is_edge_in_complex(v1, vi, c3t3, cell_selector)) + return false; + } + } + } + } while (++fcirc != fdone); + + return true; + } + + template + Subdomain_relation compare_subdomains(typename C3t3::Vertex_handle v0, + typename C3t3::Vertex_handle v1, + const C3t3& c3t3) + { + typedef typename C3t3::Subdomain_index Subdomain_index; + + std::vector subdomains_v0; + incident_subdomains(v0, c3t3, std::back_inserter(subdomains_v0)); + std::sort(subdomains_v0.begin(), subdomains_v0.end()); + + std::vector subdomains_v1; + incident_subdomains(v1, c3t3, std::back_inserter(subdomains_v1)); + std::sort(subdomains_v1.begin(), subdomains_v1.end()); + + if (subdomains_v0.size() == subdomains_v1.size()) + { + for (unsigned int i = 0; i < subdomains_v0.size(); i++) + if (subdomains_v0[i] != subdomains_v1[i]) + return DIFFERENT; + return EQUAL; + } + else + { + std::vector + intersection((std::min)(subdomains_v0.size(), subdomains_v1.size()), -1); + typename std::vector::iterator + end_it = std::set_intersection(subdomains_v0.begin(), subdomains_v0.end(), + subdomains_v1.begin(), subdomains_v1.end(), + intersection.begin()); + std::ptrdiff_t intersection_size = (end_it - intersection.begin()); + + if (subdomains_v0.size() > subdomains_v1.size() + && intersection_size == std::ptrdiff_t(subdomains_v1.size())) + { + return INCLUDES; + } + else if (intersection_size == std::ptrdiff_t(subdomains_v0.size())) { + return INCLUDED; + } + } + return DIFFERENT; + } + + + + template + void get_edge_info(const typename C3t3::Edge& edge, + bool& update_v0, + bool& update_v1, + const C3t3& c3t3, + CellSelector cell_selector) + { + typedef typename C3t3::Vertex_handle Vertex_handle; + + Vertex_handle v0 = edge.first->vertex(edge.second); + Vertex_handle v1 = edge.first->vertex(edge.third); + + int dim0 = c3t3.in_dimension(v0); + int dim1 = c3t3.in_dimension(v1); + + std::size_t nb_si_v0 = nb_incident_subdomains(v0, c3t3); + std::size_t nb_si_v1 = nb_incident_subdomains(v1, c3t3); + + update_v0 = false; + update_v1 = false; + + bool is_v0_on_hull = is_on_hull(v0, c3t3); + bool is_v1_on_hull = is_on_hull(v1, c3t3); + + //Same type imaginary or inside vertices + if (dim0 == 3 && dim1 == 3) + { + if (is_v0_on_hull && is_v1_on_hull)//both endvertices are on hull + { + if (is_on_hull(edge, c3t3)) //edge also is on hull + { + update_v0 = true; + update_v1 = true; + } + } + else + { + if (!is_v0_on_hull) //v0 not on hull + update_v0 = true; + if (!is_v1_on_hull) //v1 not on hull + update_v1 = true; + } + return; + } + //Feature edge case + if (nb_si_v0 > 2 && nb_si_v1 > 2) + { + if (c3t3.is_in_complex(edge)) + { + if (!topology_test(edge, c3t3, cell_selector)) + return; + + if (nb_si_v0 > nb_si_v1){ + update_v1 = true; + } + else if (nb_si_v1 > nb_si_v0){ + update_v0 = true; + } + else { + update_v0 = true; + update_v1 = true; + } + } + return; + } + + if (dim0 == 2 && dim1 == 2) + { + if (is_boundary(c3t3, edge, cell_selector)) + { + if (!topology_test(edge, c3t3, cell_selector)) + return; + Subdomain_relation subdomain_rel = compare_subdomains(v0, v1, c3t3); + + //Vertices on the same surface + if (subdomain_rel == INCLUDES){ + update_v1 = true; + } + else if (subdomain_rel == INCLUDED){ + update_v0 = true; + } + else if (subdomain_rel == EQUAL) + { + if (c3t3.number_of_edges() == 0) + { + update_v0 = true; + update_v1 = true; + } + else + { + bool v0_on_feature = is_on_feature(v0); + bool v1_on_feature = is_on_feature(v1); + + if (v0_on_feature && v1_on_feature){ + if (c3t3.is_in_complex(edge)){ + if (!c3t3.is_in_complex(v0)) + update_v0 = true; + if (!c3t3.is_in_complex(v1)) + update_v1 = true; + } + } + else { + if (!v0_on_feature){ + update_v0 = true; + } + if (!v1_on_feature){ + update_v1 = true; + } + } + } + } + } + + return; + } + //In the case of mixte edges + if (dim0 == 2 && dim1 == 3 && !is_v1_on_hull) { + update_v1 = true; + return; + } + + if (dim1 == 2 && dim0 == 3 && !is_v0_on_hull) { + update_v0 = true; + return; + } + } + + + template + void print_subdomain_indices(const C3T3& c3t3) + { + typedef typename C3T3::Triangulation Tr; + typedef typename Tr::Finite_cells_iterator Finite_cells_iterator; + + std::cout << "SUBDOMAINS : " << std::endl; + unsigned int line_id = 0; + for (Finite_cells_iterator cit = c3t3.triangulation().finite_cells_begin(); + cit != c3t3.triangulation().finite_cells_end(); + ++cit, ++line_id) + { + if (line_id % 10 == 0) + std::cout << std::endl; + std::cout << "\t" << cit->subdomain_index(); + } + + } + +#ifdef CGAL_TETRAHEDRAL_REMESHING_DEBUG + template + void dump_edges(const Bimap& edges, const char* filename) + { + std::ofstream ofs(filename); + ofs.precision(17); + + BOOST_FOREACH(typename Bimap::left_const_reference it, edges.left) + { + ofs << "2 " << it.first.first->point() + << " " << it.first.second->point() << std::endl; + } + + ofs.close(); + } +#endif + + +} +} +} + +#endif //CGAL_INTERNAL_TET_REMESHING_HELPERS_H diff --git a/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/triangulation_3_helpers.h b/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/triangulation_3_helpers.h new file mode 100644 index 00000000000..ddc363200fe --- /dev/null +++ b/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/triangulation_3_helpers.h @@ -0,0 +1,811 @@ +// Copyright (c) 2018 GeometryFactory (France). +// All rights reserved. +// +// This file is part of CGAL (www.cgal.org). +// You can redistribute it and/or modify it under the terms of the GNU +// General Public License as published by the Free Software Foundation, +// either version 3 of the License, or (at your option) any later version. +// +// Licensees holding a valid commercial license may use this file in +// accordance with the commercial license agreement provided with the software. +// +// This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE +// WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. +// +// $URL$ +// $Id$ +// +// +// Author(s) : Jane Tournois +// +//****************************************************************************** +// +//****************************************************************************** + +#ifndef CGAL_TRIANGULATION_3_HELPERS_H +#define CGAL_TRIANGULATION_3_HELPERS_H + +#include +#include +#include +#include +#include +#include + +#include +#include + +#include + +namespace CGAL +{ + namespace debug + { + template + void dump_facet(const Facet& f, OutputStream& os) + { + os << "4 "; + os << f.first->vertex((f.second + 1) % 4)->point() << " " + << f.first->vertex((f.second + 2) % 4)->point() << " " + << f.first->vertex((f.second + 3) % 4)->point() << " " + << f.first->vertex((f.second + 1) % 4)->point(); + os << std::endl; + } + + template + void dump_facets(const FacetRange& facets, const char* filename) + { + std::ofstream os(filename); + for (typename FacetRange::const_iterator fit = facets.begin(); + fit != facets.end(); ++fit) + { + typename FacetRange::value_type f = *fit; + dump_facet(f, os); + } + } + + template + void dump_polylines(const CellRange& cells, const char* filename) + { + std::ofstream ofs(filename); + if (!ofs) return; + + for (typename CellRange::const_iterator it = cells.begin(); + it != cells.end(); ++it) + { + for (int i = 0; i < 4; ++i) + dump_facet(std::make_pair(*it, i), ofs); + } + ofs.close(); + } + + } // end namespace debug (in ::CGAL) + + const int indices_table[4][3] = { { 3, 1, 2 }, + { 3, 2, 0 }, + { 3, 0, 1 }, + { 2, 1, 0 } }; + + int indices(const int& i, const int& j) + { + CGAL_assertion(i >= 0 && i < 4); + CGAL_assertion(j >= 0 && j < 3); + return indices_table[i][j]; + } + + template + typename Gt::FT dihedral_angle(const CGAL::Point_3& p, + const CGAL::Point_3& q, + const CGAL::Point_3& r, + const CGAL::Point_3& s) + { + return Gt().compute_approximate_dihedral_angle_3_object()(p,q,r,s); + } + + template + typename Gt::FT min_dihedral_angle(const CGAL::Point_3& p, + const CGAL::Point_3& q, + const CGAL::Point_3& r, + const CGAL::Point_3& s) + { + typedef typename Gt::FT FT; + FT a = CGAL::abs(dihedral_angle(p, q, r, s)); + FT min_dh = a; + + a = CGAL::abs(dihedral_angle(p, r, q, s)); + min_dh = (std::min)(a, min_dh); + + a = CGAL::abs(dihedral_angle(p, s, q, r)); + min_dh = (std::min)(a, min_dh); + + a = CGAL::abs(dihedral_angle(q, r, p, s)); + min_dh = (std::min)(a, min_dh); + + a = CGAL::abs(dihedral_angle(q, s, p, r)); + min_dh = (std::min)(a, min_dh); + + a = CGAL::abs(dihedral_angle(r, s, p, q)); + min_dh = (std::min)(a, min_dh); + + return min_dh; + } + + template + typename Gt::FT min_dihedral_angle(VertexHandle v0, + VertexHandle v1, + VertexHandle v2, + VertexHandle v3) + { + return min_dihedral_angle(v0->point(), + v1->point(), + v2->point(), + v3->point()); + } + + template + typename Gt::FT min_dihedral_angle(CellHandle c) + { + return min_dihedral_angle(c->vertex(0)->point(), + c->vertex(1)->point(), + c->vertex(2)->point(), + c->vertex(3)->point()); + } + + template + std::pair + make_vertex_pair(const typename Tr::Edge& e) + { + typedef typename Tr::Vertex_handle Vertex_handle; + Vertex_handle v1 = e.first->vertex(e.second); + Vertex_handle v2 = e.first->vertex(e.third); + if (v2 < v1) std::swap(v1, v2); + + return std::make_pair(v1, v2); + } + + template + std::pair make_vertex_pair(const Vh v1, const Vh v2) + { + if (v2 < v1) return std::make_pair(v2, v1); + else return std::make_pair(v1, v2); + } + + template + CGAL::Triple make_vertex_triple(const Vh vh0, const Vh vh1, const Vh vh2) + { + CGAL::Triple ft(vh0, vh1, vh2); + if (ft.template get<1>() < ft.template get<0>()) std::swap(ft.template get<0>(), ft.template get<1>()); + if (ft.template get<2>() < ft.template get<1>()) std::swap(ft.template get<1>(), ft.template get<2>()); + if (ft.template get<1>() < ft.template get<0>()) std::swap(ft.template get<0>(), ft.template get<1>()); + return ft; + } + + template + bool is_on_feature(const VertexHandle v) + { + return (v->in_dimension() == 1); + } + + template + CGAL::Orientation orientation(const CellHandle ch) + { + return CGAL::orientation(ch->vertex(0)->point(), ch->vertex(1)->point(), + ch->vertex(2)->point(), ch->vertex(3)->point()); + } + + template + bool is_well_oriented(const CellHandle ch) + { + return CGAL::POSITIVE == orientation(ch); + } + + template + bool is_well_oriented(const VertexHandle v0, const VertexHandle v1, + const VertexHandle v2, const VertexHandle v3) + { + return CGAL::POSITIVE == CGAL::orientation(v0->point(), v1->point(), + v2->point(), v3->point()); + } + + template + OutputIterator incident_subdomains(const typename C3t3::Vertex_handle v, + const C3t3& c3t3, + OutputIterator oit) + { + typedef typename C3t3::Triangulation::Cell_handle Cell_handle; + std::vector cells; + c3t3.triangulation().incident_cells(v, std::back_inserter(cells)); + + for (std::size_t i = 0; i < cells.size(); ++i) + *oit++ = cells[i]->subdomain_index(); + + return oit; + } + + template + OutputIterator incident_subdomains(const typename C3t3::Edge& e, + const C3t3& c3t3, + OutputIterator oit) + { + typedef typename C3t3::Triangulation::Cell_circulator Cell_circulator; + + Cell_circulator circ = c3t3.triangulation().incident_cells(e); + Cell_circulator end = circ; + do + { + *oit++ = circ->subdomain_index(); + } + while (++circ != end); + + return oit; + } + + template + std::size_t nb_incident_subdomains(const typename C3t3::Vertex_handle v, + const C3t3& c3t3) + { + typedef typename C3t3::Subdomain_index Subdomain_index; + + boost::unordered_set indices; + incident_subdomains(v, c3t3, std::inserter(indices, indices.begin())); + + return indices.size(); + } + + template + std::size_t nb_incident_subdomains(const typename C3t3::Edge& e, + const C3t3& c3t3) + { + typedef typename C3t3::Subdomain_index Subdomain_index; + + boost::unordered_set indices; + incident_subdomains(e, c3t3, std::inserter(indices, indices.begin())); + + return indices.size(); + } + + template + std::size_t nb_incident_complex_edges(const typename C3t3::Vertex_handle v, + const C3t3& c3t3) + { + typedef typename C3t3::Edge Edge; + boost::unordered_set edges; + c3t3.triangulation().incident_edges(v, + std::inserter(edges, edges.begin())); + + std::size_t count = 0; + for (typename boost::unordered_set::iterator eit = edges.begin(); + eit != edges.end(); + ++eit) + { + if (c3t3.is_in_complex(*eit)) + ++count; + } + return count; + } + + + template + bool is_feature(const typename C3t3::Vertex_handle v, + const typename C3t3::Vertex_handle neighbor, + const C3t3& c3t3) + { + typename C3t3::Cell_handle ch; + int i0, i1; + if (c3t3.triangulation().is_edge(v, neighbor, ch, i0, i1)) + { + typename C3t3::Edge edge(ch, i0, i1); + return c3t3.is_in_complex(edge); + } + return false; + } + + template + bool is_feature(const typename C3t3::Vertex_handle v, const C3t3& c3t3) + { + typedef typename C3t3::Edge Edge; + + if (nb_incident_subdomains(v, c3t3) > 2) + { + std::vector edges; + c3t3.triangulation().finite_incident_edges(v, std::back_inserter(edges)); + + int feature_count = 0; + BOOST_FOREACH(Edge ei, edges) + { + if (c3t3.is_in_complex(ei)) + { + feature_count++; + if (feature_count >= 3) + return true; + } + } + } + else if(c3t3.number_of_corners() > 0) + { + return c3t3.is_in_complex(v); + } + return false; + } + + /** + * returns true iff `v` is on the outer hull of c3t3.triangulation() + * i.e. finite and incident to at least one infinite cell + */ + template + bool is_on_hull(const typename C3t3::Vertex_handle v, + const C3t3& c3t3) + { + if (v == c3t3.triangulation().infinite_vertex()) + return true; + + //on hull == incident to infinite cell + typedef typename C3t3::Triangulation::Cell_handle Cell_handle; + + std::vector cells; + c3t3.triangulation().incident_cells(v, std::back_inserter(cells)); + for (std::size_t i = 0; i < cells.size(); ++i) + { + if (c3t3.triangulation().is_infinite(cells[i])) + return true; + } + return false; + } + + template + bool is_on_domain_hull(const typename C3t3::Vertex_handle v, + const C3t3& c3t3, + const typename C3t3::Subdomain_index& imaginary_index) + { + if (v == c3t3.triangulation().infinite_vertex()) + return false; + + //on hull == incident to infinite cell + typedef typename C3t3::Triangulation::Cell_handle Cell_handle; + + bool met_inside_cell = false; + bool met_outside_cell = false; + + std::vector cells; + c3t3.triangulation().incident_cells(v, std::back_inserter(cells)); + for (std::size_t i = 0; i < cells.size(); ++i) + { + if (c3t3.triangulation().is_infinite(cells[i]) + || !c3t3.is_in_complex(cells[i]) + || cells[i]->subdomain_index() == imaginary_index) + met_outside_cell = true; + else + met_inside_cell = true; + + if (met_inside_cell && met_outside_cell) + return true; + } + return false; + } + + /** + * returns true iff `edge` is on the outer hull + * of c3t3.triangulation() + * i.e. finite and incident to at least one infinite cell + */ + template + bool is_on_hull(const typename C3t3::Edge & edge, + const C3t3& c3t3) + { + typedef typename C3t3::Triangulation::Cell_circulator Cell_circulator; + Cell_circulator circ = c3t3.triangulation().incident_cells(edge); + Cell_circulator done = circ; + do + { + if (c3t3.triangulation().is_infinite(circ)) + return true; + } while (++circ != done); + + return false; + } + + template + bool is_on_domain_hull(const typename C3t3::Edge & edge, + const C3t3& c3t3, + const typename C3t3::Subdomain_index& imaginary_index) + { + typedef typename C3t3::Triangulation::Cell_circulator Cell_circulator; + + bool met_inside_cell = false; + bool met_outside_cell = false; + + Cell_circulator circ = c3t3.triangulation().incident_cells(edge); + Cell_circulator done = circ; + do + { + if (c3t3.triangulation().is_infinite(circ) + || !c3t3.is_in_complex(circ) + || circ->subdomain_index() == imaginary_index) + met_outside_cell = true; + else + met_inside_cell = true; + + if (met_inside_cell && met_outside_cell) + return true; + } while (++circ != done); + + return false; + } + + template + bool is_imaginary(const typename C3t3::Vertex_handle v, + const C3t3& c3t3, + const typename C3t3::Subdomain_index& imaginary_index) + { + typedef typename C3t3::Triangulation::Cell_handle Cell_handle; + + std::vector cells; + c3t3.triangulation().incident_cells(v, std::back_inserter(cells)); + + BOOST_FOREACH(Cell_handle c, cells) + { + if (c->subdomain_index() != imaginary_index) + return false; + } + return true; + } + + /** + * returns true off edge is fully imaginary + * i.e. if all its incident cells are not in the complex, + * and have their subdomain index == imaginary_index + */ + template + bool is_imaginary(const typename C3t3::Edge & edge, + const C3t3& c3t3, + const typename C3t3::Subdomain_index& imaginary_index) + { + typedef typename C3t3::Triangulation::Cell_circulator Cell_circulator; + Cell_circulator circ = c3t3.triangulation().incident_cells(edge); + Cell_circulator done = circ; + do + { + if ( c3t3.is_in_complex(circ) + && circ->subdomain_index() != imaginary_index) + return false; + } while (++circ != done); + + return true; + } + + template + bool is_outside(const typename C3t3::Edge & edge, + const C3t3& c3t3, + const typename C3t3::Subdomain_index& imaginary_index, + CellSelector cell_selector) + { + typedef typename C3t3::Triangulation::Cell_circulator Cell_circulator; + Cell_circulator circ = c3t3.triangulation().incident_cells(edge); + Cell_circulator done = circ; + do + { + // is cell infinite? + if (c3t3.triangulation().is_infinite(circ)) + continue; + // is cell imaginary? + if (c3t3.is_in_complex(circ) && circ->subdomain_index() == imaginary_index) + continue; + //circ does not belong to the selection + if (!cell_selector(circ)) + continue; + + //none of the above conditions was met + return false; + } + while (circ != done); + + return true; //all cells have met the loop conditions + } + + template + bool is_selected(const typename C3t3::Vertex_handle v, + const C3t3& c3t3, + CellSelector cell_selector) + { + typedef typename C3t3::Triangulation::Cell_handle Cell_handle; + + std::vector cells; + c3t3.triangulation().incident_cells(v, std::back_inserter(cells)); + + BOOST_FOREACH(Cell_handle c, cells) + { + if (!cell_selector(c)) + return false; + } + return true; + } + + template + bool is_inside(const typename C3t3::Edge& edge, + const C3t3& c3t3, + const typename C3t3::Subdomain_index& imaginary_index, + CellSelector cell_selector) + { + typedef typename C3t3::Triangulation::Cell_circulator Cell_circulator; + Cell_circulator circ = c3t3.triangulation().incident_cells(edge); + Cell_circulator done = circ; + + const typename C3t3::Subdomain_index si = circ->subdomain_index(); + if (si == imaginary_index || !c3t3.is_in_complex(circ) ) + return false; + do + { + if (c3t3.triangulation().is_infinite(circ)) + return false; + if (si != circ->subdomain_index()) + return false; + if (!cell_selector(circ)) + return false; + } + while (++circ != done); + + return true; + } + + template + bool is_convex(const Tr& tr, + const CGAL::Iso_cuboid_3& bbox, + typename Tr::Facet& facet) + { +#ifdef CGAL_LIMITED_APERTURE_DEBUG + bool res = true; +#endif + + typedef typename Tr::Cell_handle Cell_handle; + typedef typename Tr::Vertex_handle Vertex_handle; + typedef typename Tr::Facet Facet; + typedef typename Tr::Finite_facets_iterator Finite_facets_iterator; + +#ifdef CGAL_LIMITED_APERTURE_DEBUG + std::vector > tetra; +#endif + for (Finite_facets_iterator fit = tr.finite_facets_begin(); + fit != tr.finite_facets_end(); ++fit) + { + Facet f = *fit; + Facet mf = tr.mirror_facet(f); + if (!tr.is_infinite(f.first) && !tr.is_infinite(mf.first)) + continue; + + if (tr.is_infinite(mf.first)) + f = mf; + CGAL_assertion(tr.is_infinite(f.first)); + + boost::array vs; + for (int i = 0; i < 3; ++i) + vs[i] = f.first->vertex((f.second + i + 1) % 4); + if (f.second % 2 == 0) + std::swap(vs[0], vs[1]); + + Cell_handle fin_c = f.first->neighbor(f.second); + Vertex_handle v4 = fin_c->vertex(fin_c->index(f.first)); + + CGAL_assertion(!tr.is_infinite(fin_c)); + CGAL_assertion(!f.first->has_vertex(v4)); + + CGAL_assertion(CGAL::NEGATIVE + == CGAL::orientation(vs[0]->point(), vs[1]->point(), + vs[2]->point(), v4->point())); + + for (int i = 1; i < 4; ++i) + { + //nfi is neighbor of f on convex hull + Cell_handle ni = f.first->neighbor((f.second + i) % 4); + CGAL_assertion(tr.is_infinite(ni)); + + //collect points + Vertex_handle v3 = ni->vertex(ni->index(f.first)); + CGAL_assertion( v3 != vs[0] && v3 != vs[1] && v3 != vs[2] + && v3 != tr.infinite_vertex()); + CGAL_assertion(!f.first->has_vertex(v3)); + + CGAL::Orientation o2 = CGAL::orientation(vs[0]->point(), + vs[1]->point(), vs[2]->point(), v3->point()); + if (o2 == CGAL::POSITIVE) + { + facet = f; + + if (!bbox.is_degenerate() + && bbox.has_on_boundary(vs[0]->point()) + && bbox.has_on_boundary(vs[1]->point()) + && bbox.has_on_boundary(vs[2]->point())) + { + facet = Facet(ni, ni->index(tr.infinite_vertex())); + } + +#ifdef CGAL_LIMITED_APERTURE_DEBUG + boost::array tet = { vs[0], vs[1], vs[2], v3 }; + tetra.push_back(tet); + res = false; +#else + return false; +#endif + } + } + } + +#ifdef CGAL_LIMITED_APERTURE_DEBUG + std::ofstream ofs("non-convex-tets.polylines.txt"); + for (std::size_t i = 0; i < tetra.size(); ++i) + { + const boost::array& tet = tetra[i]; + ofs << "2 " << tet[0]->point() << " " << tet[1]->point() << std::endl; + ofs << "2 " << tet[0]->point() << " " << tet[2]->point() << std::endl; + ofs << "2 " << tet[0]->point() << " " << tet[3]->point() << std::endl; + ofs << "2 " << tet[1]->point() << " " << tet[2]->point() << std::endl; + ofs << "2 " << tet[1]->point() << " " << tet[3]->point() << std::endl; + ofs << "2 " << tet[2]->point() << " " << tet[3]->point() << std::endl; + } + ofs.close(); + return res; +#else + return true; +#endif + } + + template + bool is_convex(const Tr& tr) + { + typename Tr::Facet f; + typename Tr::Geom_traits::Iso_cuboid_3 bb(CGAL::ORIGIN, CGAL::ORIGIN); + return is_convex(tr, bb, f); + } + + template + typename Gt::Vector_3 normal(const Facet& f, const Gt& gt) + { + namespace PMP = CGAL::Polygon_mesh_processing; + typedef typename Gt::Vector_3 Vector; + typedef typename Gt::Point_3 Point; + + Point p0 = f.first->vertex((f.second + 1) % 4)->point(); + Point p1 = f.first->vertex((f.second + 2) % 4)->point(); + const Point& p2 = f.first->vertex((f.second + 3) % 4)->point(); + + //if (CGAL::POSITIVE != CGAL::orientation(p0, p1, p2, p3)) + if (f.second % 2 == 0)//equivalent to the commented orientation test + std::swap(p0, p1); + + Vector n = PMP::internal::triangle_normal(p0, p1, p2, gt); + + if (!typename Gt::Equal_3()(n, CGAL::NULL_VECTOR)) + PMP::internal::normalize(n, gt); + + return n; + } + + template + OutputIterator get_inside_edges(const C3t3& c3t3, + const typename C3t3::Subdomain_index& imaginary_index, + CellSelector cell_selector, + OutputIterator oit)/*holds pairs of Vertex_handles*/ + { + for (typename C3t3::Triangulation::Finite_edges_iterator + eit = c3t3.triangulation().finite_edges_begin(); + eit != c3t3.triangulation().finite_edges_end(); + ++eit) + { + const typename C3t3::Edge& e = *eit; + //if ( !c3t3.is_in_complex(e) + // && !is_boundary_edge(e, c3t3) + // && !is_on_hull(e, c3t3) + // && !is_imaginary(e, c3t3, imaginary_index)) + if (is_inside(e, c3t3, imaginary_index, cell_selector)) + { + *oit++ = make_vertex_pair(e); + } + } + return oit; + } + +namespace internal +{ + template + void add_to_incidence_map(const typename Tr::Cell_handle& c, + const int& index, + IncidentFacetsMap& incidence_map, + const bool verbose = false) + { + CGAL_USE(verbose); + typedef typename IncidentFacetsMap::key_type Vertex_set; + Vertex_set vertices; + vertices.insert(c->vertex((index + 1) % 4)); + vertices.insert(c->vertex((index + 2) % 4)); + vertices.insert(c->vertex((index + 3) % 4)); + CGAL_assertion(vertices.size() == 3); + +#ifdef CGAL_LIMITED_APERTURE_VERBOSE + if (verbose) + std::cout << "add_to_incidence_map facet : " << std::endl + << &*(c->vertex((index + 1) % 4)) << "\t" + << &*(c->vertex((index + 2) % 4)) << "\t" + << &*(c->vertex((index + 3) % 4)) << std::endl; +#endif + typename IncidentFacetsMap::iterator it = incidence_map.find(vertices); + if (it == incidence_map.end()) + { + std::vector facets(1); + facets[0] = typename Tr::Facet(c, index); + incidence_map.insert(std::make_pair(vertices, facets)); + } + else + { + it->second.push_back(typename Tr::Facet(c, index)); + +#ifdef CGAL_LIMITED_APERTURE_DEBUG + if (it->second.size() != 2) + { + std::cout << "size is " << it->second.size() << std::endl; + std::cout << "facet is " << std::endl; + for (typename Vertex_set::iterator vit = vertices.begin(); + vit != vertices.end(); + ++vit) + std::cout << (*vit)->point() << std::endl; + + std::vector bad_cells(it->second.size()); + for (std::size_t i = 0; i < it->second.size(); ++i) + { + bad_cells[i] = it->second[i].first; + std::cout << &*(it->second[i].first) << "\t" << it->second[i].second << std::endl; + std::cout + << "\t" << &*((it->second[i].first)->vertex(0)) + << "\t" << ((it->second[i].first)->vertex(0))->point() << std::endl + << "\t" << &*((it->second[i].first)->vertex(1)) + << "\t" << ((it->second[i].first)->vertex(1))->point() << std::endl + << "\t" << &*((it->second[i].first)->vertex(2)) + << "\t" << ((it->second[i].first)->vertex(2))->point() << std::endl + << "\t" << &*((it->second[i].first)->vertex(3)) + << "\t" << ((it->second[i].first)->vertex(3))->point() << std::endl + << std::endl; + } + CGAL::debug::dump_polylines(bad_cells, "bad_cells_in_incidence_map.polylines.txt"); + } +#endif + CGAL_assertion(it->second.size() == 2); + CGAL_assertion(it->second[0] != it->second[1]); + } + } + + template + typename Tr::Cell_handle + create_neighbor_infinite_cell(const typename Tr::Cell_handle c, + const int i, + Tr& tr) + { + CGAL_assertion(!tr.is_infinite(c)); + CGAL_assertion_code(std::size_t nbc = tr.number_of_cells()); + + typedef typename Tr::Cell_handle Cell_handle; + Cell_handle opp_c; + // the infinite cell that we are creating needs to be well oriented + if (i == 0 || i == 2) + { + opp_c = create_cell(c->vertex((i + 3) % 4), + tr.infinite_vertex(), + c->vertex((i + 1) % 4), + c->vertex((i + 2) % 4), tr); + } + else + { + opp_c = create_cell(tr.infinite_vertex(), + c->vertex((i + 1) % 4), + c->vertex((i + 2) % 4), + c->vertex((i + 3) % 4), tr); + } + tr.infinite_vertex()->set_cell(opp_c); + + CGAL_assertion(nbc + 1 == tr.number_of_cells()); + return opp_c; + } + + +}//end namespace internal + +}//end namespace CGAL + +#endif //CGAL_TRIANGULATION_3_HELPERS_H diff --git a/Tetrahedral_remeshing/include/CGAL/tetrahedral_remeshing.h b/Tetrahedral_remeshing/include/CGAL/tetrahedral_remeshing.h new file mode 100644 index 00000000000..b9077311888 --- /dev/null +++ b/Tetrahedral_remeshing/include/CGAL/tetrahedral_remeshing.h @@ -0,0 +1,217 @@ +// Copyright (c) 2019 GeometryFactory (France). +// All rights reserved. +// +// This file is part of CGAL (www.cgal.org). +// You can redistribute it and/or modify it under the terms of the GNU +// General Public License as published by the Free Software Foundation, +// either version 3 of the License, or (at your option) any later version. +// +// Licensees holding a valid commercial license may use this file in +// accordance with the commercial license agreement provided with the software. +// +// This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE +// WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. +// +// $URL$ +// $Id$ +// SPDX-License-Identifier: GPL-3.0+ +// +// +// Author(s) : Jane Tournois + +#ifndef TETRAHEDRAL_REMESHING_H +#define TETRAHEDRAL_REMESHING_H + + +#include +#include +#include +#include + +#include +#include + +#ifdef CGAL_DUMP_REMESHING_STEPS +#include +#endif + +namespace CGAL +{ + /*! + * remeshes a tetrahedral mesh. + * + * This operation sequentially performs edge splits, edge collapses, + * edge flips, smoothing and projection to the initial surface to generate + * a quality mesh with a prescribed edge length. + * + * @tparam Triangulation model of `Triangulation_3`, + * with cell base model of `TriangulationCellBaseWithInfo_3` + * + * @tparam NamedParameters a sequence of \ref pmp_namedparameters "Named Parameters" + + * @param np optional sequence of \ref pmp_namedparameters "Named Parameters" among the ones listed below + * \cgalNamedParamsBegin + * \cgalParamBegin{protect_boundaries} If `true`, the + * volume boundaries cannot be modified (no modification of boundaries in this version) + * \cgalParamEnd + * \cgalParamBegin{number_of_iterations} the number of iterations for the sequence of atomic operations + * performed (listed in the above description) + * \cgalParam + * \cgalParamBegin{cell_selector} a functor that returns a boolean setting whether the given + * `Triangulation::Cell_handle` should be part of the remeshing (by default, cells are all part + * of the remeshing) + * \cgalParamEnd + * \cgalNamedParamsEnd + */ + + // * @tparam SizingField model of `CGAL::Sizing_field` + + //* \cgalParamBegin{ adaptive } If `true`, size of elements adapts + //* .... + //* \cgalParamEnd + //* \cgalParamBegin{ edge_is_constrained_map } a property map containing the + //* constrained - or - not status of each edge of `tr`. A constrained edge can be split + //* or collapsed, but not flipped, nor its endpoints moved by smoothing. + //* \cgalParamEnd + //template + //void tetrahedral_adaptive_remeshing(Triangulation& tr, + // const SizingField& sizing_field, + // const NamedParameters& np) + template + void tetrahedral_adaptive_remeshing(Triangulation& tr, + const double& target_edge_length, + const NamedParameters& np) + { + typedef Triangulation Tr; + typedef typename Tr::Edge Edge; + + using boost::choose_param; + using boost::get_param; + + bool protect = choose_param(get_param(np, internal_np::protect_boundaries), + true); + // bool adaptive = choose_param(get_param(np, internal_np::adaptive_size), + // false); + std::size_t max_it = choose_param(get_param(np, internal_np::number_of_iterations), + 1); + + typedef typename boost::lookup_named_param_def < + internal_np::cell_selector_t, + NamedParameters, + Tetrahedral_remeshing::internal::All_cells_selected//default + > ::type SelectionFunctor; + SelectionFunctor cell_select + = choose_param(get_param(np, internal_np::cell_selector), + Tetrahedral_remeshing::internal::All_cells_selected()); + + typedef Tetrahedral_remeshing::internal::No_constraint_pmap No_constraint; + + typedef typename boost::lookup_named_param_def < + internal_np::edge_is_constrained_t, + NamedParameters, + No_constraint//default + > ::type ECMap; + ECMap ecmap = choose_param(get_param(np, internal_np::edge_is_constrained) + , No_constraint()); + + typedef Tetrahedral_remeshing::internal::Adaptive_remesher< + Tr, ECMap, SelectionFunctor> Remesher; + Remesher remesher(tr, target_edge_length, protect, ecmap + , cell_select + /*, adaptive*/); + +#ifdef CGAL_TETRAHEDRAL_REMESHING_VERBOSE + Tetrahedral_remeshing::internal::compute_statistics( + remesher.triangulation(), + remesher.imaginary_index(), cell_select, "statistics_begin.txt"); +#endif + + remesher.preprocess(); + + std::size_t it_nb = 0; + while (it_nb++ < max_it && !remesher.resolution_reached()) + { +#ifdef CGAL_TETRAHEDRAL_REMESHING_VERBOSE + std::cout << "# Iteration " << it_nb << " #" << std::endl; +#endif + remesher.split(); + remesher.collapse(); + remesher.flip(); + remesher.smooth(); + +#ifdef CGAL_TETRAHEDRAL_REMESHING_VERBOSE + std::cout << "# Iteration " << it_nb << " done : " + << remesher.triangulation().number_of_vertices() + << " vertices #" << std::endl; +#endif +#ifdef CGAL_DUMP_REMESHING_STEPS + std::ostringstream ossi; + ossi << "statistics_" << it_nb << ".txt"; + Tetrahedral_remeshing::internal::compute_statistics( + remesher.triangulation(), + remesher.imaginary_index(), cell_select, ossi.str().c_str()); +#endif + } + + std::size_t nb_extra_iterations = 3; + while (it_nb++ < max_it + nb_extra_iterations) + { + remesher.flip(); + remesher.smooth(); + +#ifdef CGAL_TETRAHEDRAL_REMESHING_VERBOSE + std::cout << "# Iteration " << it_nb << " (flip and smooth only) done : " + << remesher.triangulation().number_of_vertices() + << " vertices #" << std::endl; +#endif +#ifdef CGAL_DUMP_REMESHING_STEPS + std::ostringstream ossi; + ossi << "statistics_" << it_nb << ".txt"; + Tetrahedral_remeshing::internal::compute_statistics( + remesher.triangulation(), + remesher.imaginary_index(), cell_select, ossi.str().c_str()); +#endif + } + + remesher.postprocess(); + + remesher.finalize(); + +#ifdef CGAL_TETRAHEDRAL_REMESHING_VERBOSE + Tetrahedral_remeshing::internal::compute_statistics(tr, + remesher.imaginary_index(), cell_select, "statistics_end.txt"); +#endif + } + + + //template + //void tetrahedral_adaptive_remeshing(Triangulation& tr, + // const double& target_edge_length, + // const NamedParameters& np) + //{ + // typedef typename Triangulation::Geom_traits K; + // CGAL::Uniform_sizing_field sizing_field(target_edge_length); + // tetrahedral_adaptive_remeshing(tr, sizing_field, np); + //} + + //template + //void tetrahedral_adaptive_remeshing(Triangulation& tr, + // const SizingField& sizing_field) + //{ + // tetrahedral_adaptive_remeshing(tr, sizing_field, + // Polygon_mesh_processing::parameters::all_default()); + //} + + template + void tetrahedral_adaptive_remeshing(Triangulation& tr, + const double& target_edge_length) + { + tetrahedral_adaptive_remeshing(tr, target_edge_length, + Polygon_mesh_processing::parameters::all_default()); + } + +}//end namespace CGAL + +#endif //TETRAHEDRAL_REMESHING_H From 3cf0823ba36c2057718114ff2ea803c858780f20 Mon Sep 17 00:00:00 2001 From: Jane Tournois Date: Thu, 8 Aug 2019 11:19:15 +0200 Subject: [PATCH 002/568] add input --- .../tetrahedral_remeshing_example.cpp | 25 ++++++++++++++++--- 1 file changed, 22 insertions(+), 3 deletions(-) diff --git a/Tetrahedral_remeshing/examples/Tetrahedral_remeshing/tetrahedral_remeshing_example.cpp b/Tetrahedral_remeshing/examples/Tetrahedral_remeshing/tetrahedral_remeshing_example.cpp index 409fefcf626..8275d1f57a1 100644 --- a/Tetrahedral_remeshing/examples/Tetrahedral_remeshing/tetrahedral_remeshing_example.cpp +++ b/Tetrahedral_remeshing/examples/Tetrahedral_remeshing/tetrahedral_remeshing_example.cpp @@ -5,6 +5,7 @@ #include #include +#include typedef CGAL::Exact_predicates_inexact_constructions_kernel K; @@ -12,18 +13,36 @@ typedef CGAL::Tetrahedral_remeshing::Remeshing_triangulation_3 Triangula //todo : add specialization for Cell_base without info // (does not compile with `void` instead of `int`) +bool generate_input(const std::size_t& n, + const char* filename) +{ + typedef Triangulation::Point Point; + Triangulation tr; + + CGAL::Random rng; + while (tr.number_of_vertices() < n) + tr.insert(Point(rng.get_double(-1., 1.), rng.get_double(-1., 1.), rng.get_double(-1., 1.))); + + std::ofstream oFileT(filename, std::ios::out); + // writing file output; + oFileT << tr; + + return (!oFileT.bad()); +} int main(int argc, char* argv[]) { - const char* filename = (argc > 1) ? argv[1] : "data/pig.off"; - float target_edge_length = (argc > 2) ? atof(argv[2]) : 2.f; + generate_input(1000, "data/random_sphere_triangulation.cgal"); + + const char* filename = (argc > 1) ? argv[1] : "data/random_sphere_triangulation.cgal"; + float target_edge_length = (argc > 2) ? atof(argv[2]) : 0.1f; std::ifstream input(filename, std::ios::in); if (!input) { std::cerr << "File " << filename << " could not be found" << std::endl; return EXIT_FAILURE; - } + } Triangulation tr; input >> tr; From dc16af085bb8dc556c16fea312b4718f3b9e9c62 Mon Sep 17 00:00:00 2001 From: Jane Tournois Date: Thu, 8 Aug 2019 15:35:37 +0200 Subject: [PATCH 003/568] take any simple triangulation as input it is not needed to store `input_cell` in the general case --- .../tetrahedral_remeshing_example.cpp | 23 +++-- .../Remeshing_cell_base.h | 7 +- .../Remeshing_triangulation_3.h | 94 ++++++++++++++++--- 3 files changed, 97 insertions(+), 27 deletions(-) diff --git a/Tetrahedral_remeshing/examples/Tetrahedral_remeshing/tetrahedral_remeshing_example.cpp b/Tetrahedral_remeshing/examples/Tetrahedral_remeshing/tetrahedral_remeshing_example.cpp index 8275d1f57a1..d31c37e1f2f 100644 --- a/Tetrahedral_remeshing/examples/Tetrahedral_remeshing/tetrahedral_remeshing_example.cpp +++ b/Tetrahedral_remeshing/examples/Tetrahedral_remeshing/tetrahedral_remeshing_example.cpp @@ -3,25 +3,29 @@ #include #include +#include + #include #include + #include typedef CGAL::Exact_predicates_inexact_constructions_kernel K; -typedef CGAL::Tetrahedral_remeshing::Remeshing_triangulation_3 Triangulation; + +typedef CGAL::Triangulation_3 T3; +typedef CGAL::Tetrahedral_remeshing::Remeshing_triangulation_3 Remeshing_triangulation; //todo : add specialization for Cell_base without info // (does not compile with `void` instead of `int`) bool generate_input(const std::size_t& n, const char* filename) { - typedef Triangulation::Point Point; - Triangulation tr; - + T3 tr; CGAL::Random rng; + while (tr.number_of_vertices() < n) - tr.insert(Point(rng.get_double(-1., 1.), rng.get_double(-1., 1.), rng.get_double(-1., 1.))); + tr.insert(T3::Point(rng.get_double(-1., 1.), rng.get_double(-1., 1.), rng.get_double(-1., 1.))); std::ofstream oFileT(filename, std::ios::out); // writing file output; @@ -44,10 +48,13 @@ int main(int argc, char* argv[]) return EXIT_FAILURE; } - Triangulation tr; - input >> tr; - CGAL_assertion(tr.is_valid()); + T3 t3; + input >> t3; + CGAL_assertion(t3.is_valid()); + Remeshing_triangulation tr; + CGAL::Tetrahedral_remeshing::build_remeshing_triangulation(t3, tr); + CGAL::tetrahedral_adaptive_remeshing(tr, target_edge_length); std::ofstream oFileT("output.tr.cgal", std::ios::out); diff --git a/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/Remeshing_cell_base.h b/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/Remeshing_cell_base.h index db67688b216..6d8fe4f2221 100644 --- a/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/Remeshing_cell_base.h +++ b/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/Remeshing_cell_base.h @@ -34,7 +34,6 @@ namespace Tetrahedral_remeshing { template > class Remeshing_cell_base : public CGAL::Triangulation_cell_base_with_info_3 @@ -55,7 +54,6 @@ namespace Tetrahedral_remeshing // 1 to n for subdomains // n + 1 for imaginary cells std::size_t time_stamp_; - Input_cell input_cell_;//cell of input mesh, before remeshing public: // To get correct cell type in TDS @@ -63,7 +61,7 @@ namespace Tetrahedral_remeshing struct Rebind_TDS { typedef typename Cb::template Rebind_TDS::Other Cb2; - typedef Remeshing_cell_base Other; + typedef Remeshing_cell_base Other; }; Remeshing_cell_base() @@ -127,9 +125,6 @@ namespace Tetrahedral_remeshing void set_time_stamp(const std::size_t& ts) { time_stamp_ = ts; } - - Input_cell& input_cell() { return input_cell_; } - const Input_cell& input_cell() const { return input_cell_; } }; }//end namespace Tetrahedral_remeshing }//end namespace CGAL diff --git a/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/Remeshing_triangulation_3.h b/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/Remeshing_triangulation_3.h index f7a2f3223d2..4b7e97b845d 100644 --- a/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/Remeshing_triangulation_3.h +++ b/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/Remeshing_triangulation_3.h @@ -25,38 +25,33 @@ #include #include -#include #include #include +#include +#include + +#include +#include namespace CGAL { namespace Tetrahedral_remeshing { template > class Remeshing_triangulation_3 : public CGAL::Triangulation_3, - Remeshing_cell_base >::type::Cell, - Cb - > + Remeshing_cell_base > > { typedef Remeshing_vertex_base RVb; - - typedef typename CGAL::Default::Get >::type Input_tr; - typedef typename Input_tr::Cell Input_cell; - typedef Remeshing_cell_base RCb; + typedef Remeshing_cell_base RCb; public: typedef CGAL::Triangulation_data_structure_3 Tds; @@ -64,6 +59,79 @@ namespace Tetrahedral_remeshing typedef Self type; }; + namespace internal + { + template + struct Vertex_converter + { + //This operator is used to create the vertex from v_src. + typename TDS_tgt::Vertex operator()(const typename TDS_src::Vertex& v_src) const + { + typedef typename CGAL::Kernel_traits< + typename TDS_src::Vertex::Point>::Kernel GT_src; + typedef typename CGAL::Kernel_traits< + typename TDS_tgt::Vertex::Point>::Kernel GT_tgt; + CGAL::Cartesian_converter conv; + + typename TDS_tgt::Vertex v_tgt; + v_tgt.set_point(conv(v_src.point())); + v_tgt.set_time_stamp(-1); + v_tgt.set_dimension(3);//-1 if unset, 0,1,2, or 3 if set + return v_tgt; + } + //This operator is meant to be used in case heavy data should transferred to v_tgt. + void operator()(const typename TDS_src::Vertex& v_src, + typename TDS_tgt::Vertex& v_tgt) const + { + typedef typename CGAL::Kernel_traits< + typename TDS_src::Vertex::Point>::Kernel GT_src; + typedef typename CGAL::Kernel_traits< + typename TDS_tgt::Vertex::Point>::Kernel GT_tgt; + CGAL::Cartesian_converter conv; + + v_tgt.set_point(conv(v_src.point())); + v_tgt.set_dimension(3);//v_src.info()); + } + }; + + template + struct Cell_converter + { + //This operator is used to create the cell from c_src. + typename TDS_tgt::Cell operator()(const typename TDS_src::Cell& c_src) const + { + typename TDS_tgt::Cell c_tgt; +// c_tgt.info() = c_src.info(); + c_tgt.set_time_stamp(-1); + return c_tgt; + } + //This operator is meant to be used in case heavy data should transferred to c_tgt. + void operator()(const typename TDS_src::Cell& c_src, + typename TDS_tgt::Cell& c_tgt) const + { +// c_tgt.info() = c_src.info(); + } + }; + + } + + template + void build_remeshing_triangulation(const T3& tr, + Remeshing_triangulation_3& remeshing_tr) + { + typedef typename T3::Triangulation_data_structure Tds; + typedef Remeshing_triangulation_3::Tds RTds; + + remeshing_tr.clear(); + + remeshing_tr.set_infinite_vertex( + remeshing_tr.tds().copy_tds( + tr.tds(), + tr.infinite_vertex(), + internal::Vertex_converter(), + internal::Cell_converter())); + } + }//end namespace Tetrahedral_remeshing }//end namespace CGAL From da5febfac76585b2c0f74091625bf09e4a28e5db Mon Sep 17 00:00:00 2001 From: Jane Tournois Date: Thu, 5 Sep 2019 16:46:48 +0200 Subject: [PATCH 004/568] replace Point type to make it valid for non-weighted triangulations --- Mesh_3/include/CGAL/IO/File_medit.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Mesh_3/include/CGAL/IO/File_medit.h b/Mesh_3/include/CGAL/IO/File_medit.h index acb658a759b..6b4dfb092c3 100644 --- a/Mesh_3/include/CGAL/IO/File_medit.h +++ b/Mesh_3/include/CGAL/IO/File_medit.h @@ -754,7 +754,7 @@ output_to_medit(std::ostream& os, typedef typename Tr::Finite_vertices_iterator Finite_vertices_iterator; typedef typename Tr::Vertex_handle Vertex_handle; - typedef typename Tr::Weighted_point Weighted_point; + typedef typename Tr::Tds::Vertex::Point Point; const Tr& tr = c3t3.triangulation(); @@ -783,7 +783,7 @@ output_to_medit(std::ostream& os, ++vit) { V[vit] = inum++; - Weighted_point p = tr.point(vit); + Point p = tr.point(vit); os << CGAL::to_double(p.x()) << ' ' << CGAL::to_double(p.y()) << ' ' << CGAL::to_double(p.z()) << ' ' From e42fcff75481fa8d6150e2391050e920e33424c6 Mon Sep 17 00:00:00 2001 From: Jane Tournois Date: Thu, 5 Sep 2019 16:59:03 +0200 Subject: [PATCH 005/568] add operator<< and operator>> for IO --- .../Remeshing_cell_base.h | 51 ++++++++++++++++++- 1 file changed, 50 insertions(+), 1 deletion(-) diff --git a/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/Remeshing_cell_base.h b/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/Remeshing_cell_base.h index 6d8fe4f2221..928863d3153 100644 --- a/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/Remeshing_cell_base.h +++ b/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/Remeshing_cell_base.h @@ -125,7 +125,56 @@ namespace Tetrahedral_remeshing void set_time_stamp(const std::size_t& ts) { time_stamp_ = ts; } - }; + + }; + + + + template < class K, class Info, class Cb > + std::istream& + operator>>(std::istream &is, Remeshing_cell_base &c) + { + typename Remeshing_cell_base::Subdomain_index index; + if (is_ascii(is)) + is >> index; + else + read(is, index); + if (is) { + c.set_subdomain_index(index); +// for (int i = 0; i < 4; ++i) +// { +// typename Compact_mesh_cell_base_3::Surface_patch_index i2; +// if (is_ascii(is)) +// is >> iformat(i2); +// else +// { +// read(is, i2); +// } +// c.set_surface_patch_index(i, i2); +// } + } + return is; + } + + template < class K, class Info, class Cb > + std::ostream& + operator<<(std::ostream &os, const Remeshing_cell_base &c) + { + if (is_ascii(os)) + os << c.subdomain_index(); + else + write(os, c.subdomain_index()); + //for (int i = 0; i < 4; ++i) + //{ + // if (is_ascii(os)) + // os << ' ' << oformat(c.surface_patch_index(i)); + // else + // write(os, c.surface_patch_index(i)); + //} + return os; + } + + }//end namespace Tetrahedral_remeshing }//end namespace CGAL From 5716dcfc8863f25d336f7b9a14e2e87f1b9a36d5 Mon Sep 17 00:00:00 2001 From: Jane Tournois Date: Thu, 5 Sep 2019 17:01:05 +0200 Subject: [PATCH 006/568] fix namespaces --- .../internal/compute_c3t3_statistics.h | 4 +- .../tetrahedral_adaptive_remeshing_impl.h | 38 ++++++++++++------- 2 files changed, 26 insertions(+), 16 deletions(-) diff --git a/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/compute_c3t3_statistics.h b/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/compute_c3t3_statistics.h index 0502f7716e8..21b7bdfbc91 100644 --- a/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/compute_c3t3_statistics.h +++ b/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/compute_c3t3_statistics.h @@ -30,7 +30,7 @@ namespace CGAL { -namespace Tetrahedral_adaptive_remeshing +namespace Tetrahedral_remeshing { namespace internal { @@ -206,5 +206,5 @@ namespace internal } }//end namespace internal -}//end namespace Tetrahedral_adaptive_remeshing +}//end namespace Tetrahedral_remeshing }//end namespace CGAL diff --git a/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/tetrahedral_adaptive_remeshing_impl.h b/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/tetrahedral_adaptive_remeshing_impl.h index 5c418f079ba..1ec9d9ff7f2 100644 --- a/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/tetrahedral_adaptive_remeshing_impl.h +++ b/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/tetrahedral_adaptive_remeshing_impl.h @@ -56,6 +56,12 @@ namespace internal { return true; } + + typedef typename Tr::Cell::Subdomain_index Subdomain_index; + Subdomain_index subdomain_index(const argument_type c) const + { + return Subdomain_index(1); + } }; template @@ -120,7 +126,7 @@ namespace internal init_c3t3(ecmap); #ifdef CGAL_DUMP_REMESHING_STEPS - CGAL::debug::dump_without_imaginary(m_c3t3.triangulation(), + CGAL::Tetrahedral_remeshing::debug::dump_without_imaginary(m_c3t3.triangulation(), "00-init-no-imaginary.mesh", m_imaginary_index); #endif } @@ -141,8 +147,8 @@ namespace internal CGAL_assertion(tr().is_valid(true)); #ifdef CGAL_DUMP_REMESHING_STEPS - CGAL::debug::dump_triangulation_cells(tr(), "0-preprocess.mesh"); - CGAL::debug::dump_without_imaginary(tr(), + CGAL::Tetrahedral_remeshing::debug::dump_triangulation_cells(tr(), "0-preprocess.mesh"); + CGAL::Tetrahedral_remeshing::debug::dump_without_imaginary(tr(), "0-preprocess-no-imaginary.mesh", m_imaginary_index); #endif #ifdef CGAL_TETRAHEDRAL_REMESHING_VERBOSE @@ -160,8 +166,8 @@ namespace internal CGAL_assertion(tr().is_valid(true)); #ifdef CGAL_DUMP_REMESHING_STEPS - CGAL::debug::dump_triangulation_cells(tr(), "1-split.mesh"); - CGAL::debug::dump_without_imaginary(tr(), + CGAL::Tetrahedral_remeshing::debug::dump_triangulation_cells(tr(), "1-split.mesh"); + CGAL::Tetrahedral_remeshing::debug::dump_without_imaginary(tr(), "1-split-no-imaginary.mesh", m_imaginary_index); #endif } @@ -178,8 +184,9 @@ namespace internal CGAL_assertion(tr().is_valid(true)); #ifdef CGAL_DUMP_REMESHING_STEPS - CGAL::debug::dump_triangulation_cells(tr(), "2-collapse.mesh"); - CGAL::debug::dump_without_imaginary(tr(), + CGAL::Tetrahedral_remeshing::debug::dump_triangulation_cells(tr(), + "2-collapse.mesh"); + CGAL::Tetrahedral_remeshing::debug::dump_without_imaginary(tr(), "2-collapse-no-imaginary.mesh", m_imaginary_index); #endif } @@ -191,8 +198,9 @@ namespace internal CGAL_assertion(tr().is_valid(true)); #ifdef CGAL_DUMP_REMESHING_STEPS - CGAL::debug::dump_triangulation_cells(tr(), "3-flip.mesh"); - CGAL::debug::dump_without_imaginary(tr(), + CGAL::Tetrahedral_remeshing::debug::dump_triangulation_cells(tr(), + "3-flip.mesh"); + CGAL::Tetrahedral_remeshing::debug::dump_without_imaginary(tr(), "3-flip-no-imaginary.mesh", m_imaginary_index); #endif } @@ -204,8 +212,9 @@ namespace internal CGAL_assertion(tr().is_valid(true)); #ifdef CGAL_DUMP_REMESHING_STEPS - CGAL::debug::dump_triangulation_cells(tr(), "4-smooth.mesh"); - CGAL::debug::dump_without_imaginary(tr(), + CGAL::Tetrahedral_remeshing::debug::dump_triangulation_cells(tr(), + "4-smooth.mesh"); + CGAL::Tetrahedral_remeshing::debug::dump_without_imaginary(tr(), "4-smooth-no-imaginary.mesh", m_imaginary_index); #endif } @@ -253,8 +262,9 @@ namespace internal CGAL_assertion(tr().is_valid(true)); #ifdef CGAL_DUMP_REMESHING_STEPS - CGAL::debug::dump_triangulation_cells(tr(), "99-postprocess.mesh"); - CGAL::debug::dump_without_imaginary(tr(), + CGAL::Tetrahedral_remeshing::debug::dump_triangulation_cells(tr(), + "99-postprocess.mesh"); + CGAL::Tetrahedral_remeshing::debug::dump_without_imaginary(tr(), "99-postprocess-no-imaginary.mesh", m_imaginary_index); #endif #ifdef CGAL_TETRAHEDRAL_REMESHING_VERBOSE @@ -295,7 +305,7 @@ namespace internal cit != tr().finite_cells_end(); ++cit) { - if (cit->subdomain_index() != Subdomain_index()) + if (m_cell_selector(cit))//->subdomain_index() != Subdomain_index()) { m_c3t3.add_to_complex(cit, cit->subdomain_index()); max_si = (std::max)(max_si, cit->subdomain_index()); From 3fe06a2fa31985ae9c40ea3b0c6c6b3da4a81089 Mon Sep 17 00:00:00 2001 From: Jane Tournois Date: Fri, 13 Sep 2019 12:29:40 +0200 Subject: [PATCH 007/568] adapt the remesher code to the demo - make it work with Regular_triangulation and its Weighted_points - remove everything which was not needed about Surface_patch_index (1 is in the complex, 0 is not, and is_in_complex(facet) tests incident subdomains) --- .../Remeshing_cell_base.h | 13 +- .../internal/add_imaginary_layer.h | 6 +- .../internal/collapse_short_edges.h | 36 +- .../internal/smooth_vertices.h | 37 +- .../internal/split_long_edges.h | 2 +- .../tetrahedral_adaptive_remeshing_impl.h | 6 +- .../internal/tetrahedral_remeshing_helpers.h | 1404 +++++++++++++---- .../internal/triangulation_3_helpers.h | 62 +- 8 files changed, 1199 insertions(+), 367 deletions(-) diff --git a/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/Remeshing_cell_base.h b/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/Remeshing_cell_base.h index 928863d3153..e35625243a7 100644 --- a/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/Remeshing_cell_base.h +++ b/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/Remeshing_cell_base.h @@ -44,8 +44,8 @@ namespace Tetrahedral_remeshing typedef typename Base::Cell_handle Cell_handle; public: - typedef int Subdomain_index; - typedef std::pair Surface_patch_index; + typedef int Subdomain_index; + typedef int Surface_patch_index; private: Subdomain_index subdomain_index_; @@ -105,10 +105,11 @@ namespace Tetrahedral_remeshing const Surface_patch_index surface_patch_index(const int& i) { - const Subdomain_index& i1 = subdomain_index_; - const Subdomain_index& i2 = this->neighbor(i)->subdomain_index(); - if (i1 < i2) return std::make_pair(i1, i2); - else return std::make_pair(i2, i1); + CGAL_precondition(i >= 0 && i < 4); + if(is_facet_on_surface(i)) + return 1; + else + return 0; } /// Returns true if facet lies on a surface patch diff --git a/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/add_imaginary_layer.h b/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/add_imaginary_layer.h index ca8fc442527..6100b1a7fa3 100644 --- a/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/add_imaginary_layer.h +++ b/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/add_imaginary_layer.h @@ -69,11 +69,13 @@ namespace internal Tr& tr, OutputIterator oit) { + typedef typename Tr::Point Point; + CGAL_assertion(tr.is_valid()); int i = 1; for (PointIterator pit = begin; pit != end; ++pit, ++i) { - *oit++ = tr.insert(*pit); + *oit++ = tr.insert(Point(*pit)); } CGAL_assertion(tr.is_valid()); @@ -98,7 +100,7 @@ namespace internal for (typename VertexNormalsMap::const_iterator nit = normals.begin(); nit != normals.end(); ++nit) { - *oit++ = (*nit).first->point() + offset * (*nit).second; + *oit++ = point((*nit).first->point()) + offset * (*nit).second; #ifdef CGAL_TETRAHEDRAL_REMESHING_DEBUG ofs << ((*nit).first->point() + offset * (*nit).second) << std::endl; diff --git a/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/collapse_short_edges.h b/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/collapse_short_edges.h index ef3470aa616..045bf15e821 100644 --- a/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/collapse_short_edges.h +++ b/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/collapse_short_edges.h @@ -166,10 +166,10 @@ namespace internal Vector_3 v0_new_pos = vec(vh0->point()); if (collapse_type == TO_MIDPOINT){ - v0_new_pos = v0_new_pos + 0.5 * Vector_3(vh0->point(), vh1->point()); + v0_new_pos = v0_new_pos + 0.5 * Vector_3(point(vh0->point()), point(vh1->point())); } else if (collapse_type == TO_V1){ - v0_new_pos = vec(vh1->point()); + v0_new_pos = vec(point(vh1->point())); } boost::unordered_set invalid_cells; @@ -317,12 +317,6 @@ namespace internal } protected: - - Vector_3 vec(const Point_3& p) - { - return Vector_3(p.x(), p.y(), p.z()); - } - Tr triangulation; boost::bimap v2v;/*vertex of main tr - vertex of collapse tr*/ boost::bimap c2c;/*cell of main tr - cell of collapse tr*/ @@ -491,7 +485,7 @@ namespace internal { typedef typename C3t3::Vertex_handle Vertex_handle; typedef typename C3t3::Cell_handle Cell_handle; - typedef typename C3t3::Triangulation::Point Point; + typedef typename C3t3::Triangulation::Geom_traits::Point_3 Point; Vertex_handle v0 = edge.first->vertex(edge.second); Vertex_handle v1 = edge.first->vertex(edge.third); @@ -525,11 +519,11 @@ namespace internal if (!ch->has_vertex(v1)) { //check orientation - boost::array pts = { ch->vertex(0)->point(), - ch->vertex(1)->point(), - ch->vertex(2)->point(), - ch->vertex(3)->point()}; - pts[ch->index(v0)] = new_pos; + boost::array pts = { point(ch->vertex(0)->point()), + point(ch->vertex(1)->point()), + point(ch->vertex(2)->point()), + point(ch->vertex(3)->point())}; + pts[ch->index(v0)] = point(new_pos); if (CGAL::orientation(pts[0], pts[1], pts[2], pts[3]) != CGAL::POSITIVE) return false; } @@ -547,11 +541,11 @@ namespace internal if (!ch->has_vertex(v0)) { //check orientation - boost::array pts = { ch->vertex(0)->point(), - ch->vertex(1)->point(), - ch->vertex(2)->point(), - ch->vertex(3)->point() }; - pts[ch->index(v1)] = new_pos; + boost::array pts = { point(ch->vertex(0)->point()), + point(ch->vertex(1)->point()), + point(ch->vertex(2)->point()), + point(ch->vertex(3)->point()) }; + pts[ch->index(v1)] = point(new_pos); if (CGAL::orientation(pts[0], pts[1], pts[2], pts[3]) != CGAL::POSITIVE) return false; } @@ -808,7 +802,7 @@ namespace internal //Collapse at mid point if (collapse_type == TO_MIDPOINT) { - Point_3 new_position = CGAL::midpoint(vh0->point(), vh1->point()); + Point_3 new_position(CGAL::midpoint(point(vh0->point()), point(vh1->point()))); vh0->set_point(new_position); vh1->set_point(new_position); @@ -867,7 +861,7 @@ namespace internal new_pos = v1->point(); break; default: CGAL_assertion(collapse_type == TO_MIDPOINT); - new_pos = CGAL::midpoint(v0->point(), v1->point()); + new_pos = Point(CGAL::midpoint(point(v0->point()), point(v1->point()))); } boost::unordered_map edges_sqlength_after_collapse; diff --git a/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/smooth_vertices.h b/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/smooth_vertices.h index fb3c17e7ec2..4621c77a88b 100644 --- a/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/smooth_vertices.h +++ b/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/smooth_vertices.h @@ -149,19 +149,26 @@ namespace internal return true; } - template - bool check_inversion_and_move(const VertexHandle v, + template + bool check_inversion_and_move(const typename Tr::Vertex_handle v, const CGAL::Vector_3& move, - const std::vector& cells) + const std::vector& cells) { - const CGAL::Point_3 backup = v->point(); //backup v's position - v->set_point(backup + move); + typedef typename Tr::Cell_handle Cell_handle; - for (std::size_t i = 0; i < cells.size(); ++i) + const typename Tr::Point backup = v->point(); //backup v's position + typename Tr::Point new_pos(v->point().x() + move.x(), + v->point().y() + move.y(), + v->point().z() + move.z()); + //note that weight is lost in case of Regular_triangulation + v->set_point(new_pos); + + for (Cell_handle ci : cells) { - CellHandle ci = cells[i]; - if (CGAL::POSITIVE != CGAL::orientation(ci->vertex(0)->point(), - ci->vertex(1)->point(), ci->vertex(2)->point(), ci->vertex(3)->point())) + if (CGAL::POSITIVE != CGAL::orientation(point(ci->vertex(0)->point()), + point(ci->vertex(1)->point()), + point(ci->vertex(2)->point()), + point(ci->vertex(3)->point()))) { v->set_point(backup); return false; @@ -191,7 +198,7 @@ namespace internal Vertex_handle ve = (e.first->vertex(e.second) != v) ? e.first->vertex(e.second) : e.first->vertex(e.third); - move = move + Vector_3(CGAL::ORIGIN, ve->point()); + move = move + Vector_3(CGAL::ORIGIN, point(ve->point())); } return 1. / edges.size() * move; @@ -223,7 +230,7 @@ namespace internal Vertex_handle ve = (e.first->vertex(e.second) != v) ? e.first->vertex(e.second) : e.first->vertex(e.third); - move = move + Vector_3(CGAL::ORIGIN, ve->point()); + move = move + Vector_3(CGAL::ORIGIN, point(ve->point())); ++nbe; } } @@ -262,7 +269,7 @@ namespace internal ? e.first->vertex(e.second) : e.first->vertex(e.third); - move = move + Vector_3(CGAL::ORIGIN, ve->point()); + move = move + Vector_3(CGAL::ORIGIN, point(ve->point())); ++nbe; } @@ -361,15 +368,15 @@ namespace internal vit != tr.finite_vertices_end(); ++vit) { const std::size_t& vid = vertex_id.at(vit); - Point_3 new_pos = CGAL::ORIGIN + smoothing_vecs[vid]; - const Vector_3 move(vit->point(), new_pos); + const Point_3 new_pos = CGAL::ORIGIN + smoothing_vecs[vid]; + const Vector_3 move(point(vit->point()), new_pos); std::vector cells; tr.finite_incident_cells(vit, std::back_inserter(cells)); double frac = 1.; while (frac > 0.05 /// 1/16 = 0.0625 - && !check_inversion_and_move(vit, frac * move, cells)) + && !check_inversion_and_move(vit, frac * move, cells)) { frac = 0.5 * frac; } diff --git a/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/split_long_edges.h b/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/split_long_edges.h index 0eaaa87df1a..a04736e74b2 100644 --- a/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/split_long_edges.h +++ b/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/split_long_edges.h @@ -85,7 +85,7 @@ namespace internal // insert midpoint Vertex_handle new_v = tr.tds().insert_in_edge(e); - const Point m = CGAL::midpoint(v1->point(), v2->point()); + const Point m(CGAL::midpoint(point(v1->point()), point(v2->point()))); new_v->set_point(m); // update dimension diff --git a/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/tetrahedral_adaptive_remeshing_impl.h b/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/tetrahedral_adaptive_remeshing_impl.h index 1ec9d9ff7f2..9f091e40a94 100644 --- a/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/tetrahedral_adaptive_remeshing_impl.h +++ b/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/tetrahedral_adaptive_remeshing_impl.h @@ -95,7 +95,7 @@ namespace internal typedef typename C3t3::Cell_handle Cell_handle; typedef typename C3t3::Vertex_handle Vertex_handle; - typedef typename C3t3::Surface_patch_index Surface_patch_index; + typedef typename int Surface_patch_index; //only needed for is_in_complex() typedef typename C3t3::Subdomain_index Subdomain_index; private: @@ -336,9 +336,9 @@ namespace internal if (s1 != s2) { if(s1 < s2) - m_c3t3.add_to_complex(f, helpers::make_surface_patch_index(s1, s2)); + m_c3t3.add_to_complex(f, 1); else - m_c3t3.add_to_complex(f, helpers::make_surface_patch_index(s2, s1)); + m_c3t3.add_to_complex(f, 1); #ifdef CGAL_TETRAHEDRAL_REMESHING_DEBUG ++nbf; #endif diff --git a/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/tetrahedral_remeshing_helpers.h b/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/tetrahedral_remeshing_helpers.h index af55a30024c..e87dd8f5946 100644 --- a/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/tetrahedral_remeshing_helpers.h +++ b/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/tetrahedral_remeshing_helpers.h @@ -24,6 +24,11 @@ #include +#include +#include + +#include + namespace CGAL { namespace Tetrahedral_remeshing @@ -32,355 +37,1146 @@ namespace Tetrahedral_remeshing enum Sliver_removal_result { INVALID_ORIENTATION, INVALID_CELL, INVALID_VERTEX, NOT_FLIPPABLE, EDGE_PROBLEM, VALID_FLIP, NO_BEST_CONFIGURATION, EXISTING_EDGE }; -namespace helpers -{ - template - std::pair - make_surface_patch_index(const SubdomainIndex& s1, const SubdomainIndex& s2) + + namespace helpers { - CGAL_assertion(s1 != s2); - if (s1 < s2) - return std::make_pair(s1, s2); - else - return std::make_pair(s2, s1); - } - - template - bool is_boundary(const C3T3& c3t3, - const typename C3T3::Triangulation::Edge& e, - CellSelector cell_selector) - { - typedef typename C3T3::Triangulation Tr; - typedef typename Tr::Facet_circulator Facet_circulator; - typedef typename Tr::Facet Facet; - - Facet_circulator fcirc = c3t3.triangulation().incident_facets(e); - Facet_circulator fend = fcirc; - std::vector boundary_facets; - - do + template + bool is_boundary(const C3T3& c3t3, + const typename C3T3::Triangulation::Edge& e, + CellSelector cell_selector) { - Facet f = *fcirc; - if (c3t3.is_in_complex(f)) - return true; - else if (cell_selector(f.first) // XOR - ^ cell_selector(f.first->neighbor(f.second))) - return true; - else if (c3t3.triangulation().is_infinite(f) //XOR - ^ c3t3.triangulation().is_infinite(f.first->neighbor(f.second))) - return true; + typedef typename C3T3::Triangulation Tr; + typedef typename Tr::Facet_circulator Facet_circulator; + typedef typename Tr::Facet Facet; - ++fcirc; - } while (fcirc != fend); + Facet_circulator fcirc = c3t3.triangulation().incident_facets(e); + Facet_circulator fend = fcirc; + std::vector boundary_facets; - return false; - } - - template - bool is_boundary_edge(const typename C3t3::Vertex_handle& v0, - const typename C3t3::Vertex_handle& v1, - const C3t3& c3t3, - CellSelector cell_selector) - { - typedef typename C3t3::Edge Edge; - typedef typename C3t3::Cell_handle Cell_handle; - - Cell_handle cell; - int i0, i1; - if (c3t3.triangulation().tds().is_edge(v0, v1, cell, i0, i1)) - return is_boundary(c3t3, Edge(cell, i0, i1), cell_selector); - else - return false; - } - - template - bool is_boundary_vertex(const typename C3t3::Vertex_handle& v, - const C3t3& c3t3, - CellSelector cell_selector) - { - typedef typename C3t3::Facet Facet; - std::vector facets; - c3t3.triangulation().incident_facets(v, std::back_inserter(facets)); - - BOOST_FOREACH(Facet f, facets) - { - if (c3t3.is_in_complex(f)) - return true; - if (cell_selector(f.first) ^ cell_selector(f.first->neighbor(f.second))) - return true; - } - return false; - } - - template - bool is_edge_in_complex(const typename C3t3::Vertex_handle& v0, - const typename C3t3::Vertex_handle& v1, - const C3t3& c3t3, - CellSelector /*cell_selector*/) - { - typedef typename C3t3::Edge Edge; - typedef typename C3t3::Cell_handle Cell_handle; - - Cell_handle cell; - int i0, i1; - if (c3t3.triangulation().tds().is_edge(v0, v1, cell, i0, i1)) - return c3t3.is_in_complex(Edge(cell, i0, i1)); - else - return false; - } - - template - bool topology_test(const typename C3t3::Edge& edge, - const C3t3& c3t3, - CellSelector cell_selector) - { - typedef typename C3t3::Vertex_handle Vertex_handle; - typedef typename C3t3::Triangulation::Facet_circulator Facet_circulator; - typedef typename C3t3::Subdomain_index Subdomain_index; - - Vertex_handle v0 = edge.first->vertex(edge.second); - Vertex_handle v1 = edge.first->vertex(edge.third); - - Facet_circulator fcirc = c3t3.triangulation().incident_facets(edge); - Facet_circulator fdone = fcirc; - do - { - if (c3t3.triangulation().is_infinite(fcirc->first)) - continue; - - Subdomain_index si_circ = fcirc->first->subdomain_index(); - Subdomain_index si_neigh = fcirc->first->neighbor(fcirc->second)->subdomain_index(); - if (si_circ == si_neigh) + do { - //Get the ids of the opposite vertices - for (int i = 1; i < 4; i++) + Facet f = *fcirc; + if (c3t3.is_in_complex(f)) + return true; + else if (cell_selector(f.first) // XOR + ^ cell_selector(f.first->neighbor(f.second))) + return true; + else if (c3t3.triangulation().is_infinite(f) //XOR + ^ c3t3.triangulation().is_infinite(f.first->neighbor(f.second))) + return true; + + ++fcirc; + } while (fcirc != fend); + + return false; + } + + template + bool is_boundary_edge(const typename C3t3::Vertex_handle& v0, + const typename C3t3::Vertex_handle& v1, + const C3t3& c3t3, + CellSelector cell_selector) + { + typedef typename C3t3::Edge Edge; + typedef typename C3t3::Cell_handle Cell_handle; + + Cell_handle cell; + int i0, i1; + if (c3t3.triangulation().tds().is_edge(v0, v1, cell, i0, i1)) + return is_boundary(c3t3, Edge(cell, i0, i1), cell_selector); + else + return false; + } + + template + bool is_boundary_vertex(const typename C3t3::Vertex_handle& v, + const C3t3& c3t3, + CellSelector cell_selector) + { + typedef typename C3t3::Facet Facet; + std::vector facets; + c3t3.triangulation().incident_facets(v, std::back_inserter(facets)); + + BOOST_FOREACH(Facet f, facets) + { + if (c3t3.is_in_complex(f)) + return true; + if (cell_selector(f.first) ^ cell_selector(f.first->neighbor(f.second))) + return true; + } + return false; + } + + template + bool is_edge_in_complex(const typename C3t3::Vertex_handle& v0, + const typename C3t3::Vertex_handle& v1, + const C3t3& c3t3, + CellSelector /*cell_selector*/) + { + typedef typename C3t3::Edge Edge; + typedef typename C3t3::Cell_handle Cell_handle; + + Cell_handle cell; + int i0, i1; + if (c3t3.triangulation().tds().is_edge(v0, v1, cell, i0, i1)) + return c3t3.is_in_complex(Edge(cell, i0, i1)); + else + return false; + } + + template + bool topology_test(const typename C3t3::Edge& edge, + const C3t3& c3t3, + CellSelector cell_selector) + { + typedef typename C3t3::Vertex_handle Vertex_handle; + typedef typename C3t3::Triangulation::Facet_circulator Facet_circulator; + typedef typename C3t3::Subdomain_index Subdomain_index; + + Vertex_handle v0 = edge.first->vertex(edge.second); + Vertex_handle v1 = edge.first->vertex(edge.third); + + Facet_circulator fcirc = c3t3.triangulation().incident_facets(edge); + Facet_circulator fdone = fcirc; + do + { + if (c3t3.triangulation().is_infinite(fcirc->first)) + continue; + + Subdomain_index si_circ = fcirc->first->subdomain_index(); + Subdomain_index si_neigh = fcirc->first->neighbor(fcirc->second)->subdomain_index(); + if (si_circ == si_neigh) { - Vertex_handle vi = fcirc->first->vertex((fcirc->second + i) % 4); - if (vi != v0 && vi != v1 && nb_incident_subdomains(vi, c3t3) > 1) + //Get the ids of the opposite vertices + for (int i = 1; i < 4; i++) { - if ( is_edge_in_complex(v0, vi, c3t3, cell_selector) - && is_edge_in_complex(v1, vi, c3t3, cell_selector)) - return false; + Vertex_handle vi = fcirc->first->vertex((fcirc->second + i) % 4); + if (vi != v0 && vi != v1 && nb_incident_subdomains(vi, c3t3) > 1) + { + if (is_edge_in_complex(v0, vi, c3t3, cell_selector) + && is_edge_in_complex(v1, vi, c3t3, cell_selector)) + return false; + } } } - } - } while (++fcirc != fdone); + } while (++fcirc != fdone); - return true; - } - - template - Subdomain_relation compare_subdomains(typename C3t3::Vertex_handle v0, - typename C3t3::Vertex_handle v1, - const C3t3& c3t3) - { - typedef typename C3t3::Subdomain_index Subdomain_index; - - std::vector subdomains_v0; - incident_subdomains(v0, c3t3, std::back_inserter(subdomains_v0)); - std::sort(subdomains_v0.begin(), subdomains_v0.end()); - - std::vector subdomains_v1; - incident_subdomains(v1, c3t3, std::back_inserter(subdomains_v1)); - std::sort(subdomains_v1.begin(), subdomains_v1.end()); - - if (subdomains_v0.size() == subdomains_v1.size()) - { - for (unsigned int i = 0; i < subdomains_v0.size(); i++) - if (subdomains_v0[i] != subdomains_v1[i]) - return DIFFERENT; - return EQUAL; + return true; } - else + + template + Subdomain_relation compare_subdomains(typename C3t3::Vertex_handle v0, + typename C3t3::Vertex_handle v1, + const C3t3& c3t3) { - std::vector - intersection((std::min)(subdomains_v0.size(), subdomains_v1.size()), -1); - typename std::vector::iterator - end_it = std::set_intersection(subdomains_v0.begin(), subdomains_v0.end(), - subdomains_v1.begin(), subdomains_v1.end(), - intersection.begin()); - std::ptrdiff_t intersection_size = (end_it - intersection.begin()); + typedef typename C3t3::Subdomain_index Subdomain_index; - if (subdomains_v0.size() > subdomains_v1.size() - && intersection_size == std::ptrdiff_t(subdomains_v1.size())) + std::vector subdomains_v0; + incident_subdomains(v0, c3t3, std::back_inserter(subdomains_v0)); + std::sort(subdomains_v0.begin(), subdomains_v0.end()); + + std::vector subdomains_v1; + incident_subdomains(v1, c3t3, std::back_inserter(subdomains_v1)); + std::sort(subdomains_v1.begin(), subdomains_v1.end()); + + if (subdomains_v0.size() == subdomains_v1.size()) { - return INCLUDES; - } - else if (intersection_size == std::ptrdiff_t(subdomains_v0.size())) { - return INCLUDED; - } - } - return DIFFERENT; - } - - - - template - void get_edge_info(const typename C3t3::Edge& edge, - bool& update_v0, - bool& update_v1, - const C3t3& c3t3, - CellSelector cell_selector) - { - typedef typename C3t3::Vertex_handle Vertex_handle; - - Vertex_handle v0 = edge.first->vertex(edge.second); - Vertex_handle v1 = edge.first->vertex(edge.third); - - int dim0 = c3t3.in_dimension(v0); - int dim1 = c3t3.in_dimension(v1); - - std::size_t nb_si_v0 = nb_incident_subdomains(v0, c3t3); - std::size_t nb_si_v1 = nb_incident_subdomains(v1, c3t3); - - update_v0 = false; - update_v1 = false; - - bool is_v0_on_hull = is_on_hull(v0, c3t3); - bool is_v1_on_hull = is_on_hull(v1, c3t3); - - //Same type imaginary or inside vertices - if (dim0 == 3 && dim1 == 3) - { - if (is_v0_on_hull && is_v1_on_hull)//both endvertices are on hull - { - if (is_on_hull(edge, c3t3)) //edge also is on hull - { - update_v0 = true; - update_v1 = true; - } + for (unsigned int i = 0; i < subdomains_v0.size(); i++) + if (subdomains_v0[i] != subdomains_v1[i]) + return DIFFERENT; + return EQUAL; } else { - if (!is_v0_on_hull) //v0 not on hull - update_v0 = true; - if (!is_v1_on_hull) //v1 not on hull - update_v1 = true; - } - return; - } - //Feature edge case - if (nb_si_v0 > 2 && nb_si_v1 > 2) - { - if (c3t3.is_in_complex(edge)) - { - if (!topology_test(edge, c3t3, cell_selector)) - return; + std::vector + intersection((std::min)(subdomains_v0.size(), subdomains_v1.size()), -1); + typename std::vector::iterator + end_it = std::set_intersection(subdomains_v0.begin(), subdomains_v0.end(), + subdomains_v1.begin(), subdomains_v1.end(), + intersection.begin()); + std::ptrdiff_t intersection_size = (end_it - intersection.begin()); - if (nb_si_v0 > nb_si_v1){ - update_v1 = true; - } - else if (nb_si_v1 > nb_si_v0){ - update_v0 = true; - } - else { - update_v0 = true; - update_v1 = true; - } - } - return; - } - - if (dim0 == 2 && dim1 == 2) - { - if (is_boundary(c3t3, edge, cell_selector)) - { - if (!topology_test(edge, c3t3, cell_selector)) - return; - Subdomain_relation subdomain_rel = compare_subdomains(v0, v1, c3t3); - - //Vertices on the same surface - if (subdomain_rel == INCLUDES){ - update_v1 = true; - } - else if (subdomain_rel == INCLUDED){ - update_v0 = true; - } - else if (subdomain_rel == EQUAL) + if (subdomains_v0.size() > subdomains_v1.size() + && intersection_size == std::ptrdiff_t(subdomains_v1.size())) { - if (c3t3.number_of_edges() == 0) + return INCLUDES; + } + else if (intersection_size == std::ptrdiff_t(subdomains_v0.size())) { + return INCLUDED; + } + } + return DIFFERENT; + } + + + + template + void get_edge_info(const typename C3t3::Edge& edge, + bool& update_v0, + bool& update_v1, + const C3t3& c3t3, + CellSelector cell_selector) + { + typedef typename C3t3::Vertex_handle Vertex_handle; + + Vertex_handle v0 = edge.first->vertex(edge.second); + Vertex_handle v1 = edge.first->vertex(edge.third); + + int dim0 = c3t3.in_dimension(v0); + int dim1 = c3t3.in_dimension(v1); + + std::size_t nb_si_v0 = nb_incident_subdomains(v0, c3t3); + std::size_t nb_si_v1 = nb_incident_subdomains(v1, c3t3); + + update_v0 = false; + update_v1 = false; + + bool is_v0_on_hull = is_on_hull(v0, c3t3); + bool is_v1_on_hull = is_on_hull(v1, c3t3); + + //Same type imaginary or inside vertices + if (dim0 == 3 && dim1 == 3) + { + if (is_v0_on_hull && is_v1_on_hull)//both endvertices are on hull + { + if (is_on_hull(edge, c3t3)) //edge also is on hull { update_v0 = true; update_v1 = true; } - else - { - bool v0_on_feature = is_on_feature(v0); - bool v1_on_feature = is_on_feature(v1); + } + else + { + if (!is_v0_on_hull) //v0 not on hull + update_v0 = true; + if (!is_v1_on_hull) //v1 not on hull + update_v1 = true; + } + return; + } + //Feature edge case + if (nb_si_v0 > 2 && nb_si_v1 > 2) + { + if (c3t3.is_in_complex(edge)) + { + if (!topology_test(edge, c3t3, cell_selector)) + return; - if (v0_on_feature && v1_on_feature){ - if (c3t3.is_in_complex(edge)){ - if (!c3t3.is_in_complex(v0)) - update_v0 = true; - if (!c3t3.is_in_complex(v1)) - update_v1 = true; - } + if (nb_si_v0 > nb_si_v1) { + update_v1 = true; + } + else if (nb_si_v1 > nb_si_v0) { + update_v0 = true; + } + else { + update_v0 = true; + update_v1 = true; + } + } + return; + } + + if (dim0 == 2 && dim1 == 2) + { + if (is_boundary(c3t3, edge, cell_selector)) + { + if (!topology_test(edge, c3t3, cell_selector)) + return; + Subdomain_relation subdomain_rel = compare_subdomains(v0, v1, c3t3); + + //Vertices on the same surface + if (subdomain_rel == INCLUDES) { + update_v1 = true; + } + else if (subdomain_rel == INCLUDED) { + update_v0 = true; + } + else if (subdomain_rel == EQUAL) + { + if (c3t3.number_of_edges() == 0) + { + update_v0 = true; + update_v1 = true; } - else { - if (!v0_on_feature){ - update_v0 = true; + else + { + bool v0_on_feature = is_on_feature(v0); + bool v1_on_feature = is_on_feature(v1); + + if (v0_on_feature && v1_on_feature) { + if (c3t3.is_in_complex(edge)) { + if (!c3t3.is_in_complex(v0)) + update_v0 = true; + if (!c3t3.is_in_complex(v1)) + update_v1 = true; + } } - if (!v1_on_feature){ - update_v1 = true; + else { + if (!v0_on_feature) { + update_v0 = true; + } + if (!v1_on_feature) { + update_v1 = true; + } } } } } + + return; + } + //In the case of mixte edges + if (dim0 == 2 && dim1 == 3 && !is_v1_on_hull) { + update_v1 = true; + return; } - return; - } - //In the case of mixte edges - if (dim0 == 2 && dim1 == 3 && !is_v1_on_hull) { - update_v1 = true; - return; + if (dim1 == 2 && dim0 == 3 && !is_v0_on_hull) { + update_v0 = true; + return; + } } - if (dim1 == 2 && dim0 == 3 && !is_v0_on_hull) { - update_v0 = true; - return; - } - } - - template - void print_subdomain_indices(const C3T3& c3t3) - { - typedef typename C3T3::Triangulation Tr; - typedef typename Tr::Finite_cells_iterator Finite_cells_iterator; - - std::cout << "SUBDOMAINS : " << std::endl; - unsigned int line_id = 0; - for (Finite_cells_iterator cit = c3t3.triangulation().finite_cells_begin(); - cit != c3t3.triangulation().finite_cells_end(); - ++cit, ++line_id) + template + void print_subdomain_indices(const C3T3& c3t3) { - if (line_id % 10 == 0) - std::cout << std::endl; - std::cout << "\t" << cit->subdomain_index(); - } + typedef typename C3T3::Triangulation Tr; + typedef typename Tr::Finite_cells_iterator Finite_cells_iterator; - } + std::cout << "SUBDOMAINS : " << std::endl; + unsigned int line_id = 0; + for (Finite_cells_iterator cit = c3t3.triangulation().finite_cells_begin(); + cit != c3t3.triangulation().finite_cells_end(); + ++cit, ++line_id) + { + if (line_id % 10 == 0) + std::cout << std::endl; + std::cout << "\t" << cit->subdomain_index(); + } + + } #ifdef CGAL_TETRAHEDRAL_REMESHING_DEBUG - template - void dump_edges(const Bimap& edges, const char* filename) - { - std::ofstream ofs(filename); - ofs.precision(17); - - BOOST_FOREACH(typename Bimap::left_const_reference it, edges.left) + template + void dump_edges(const Bimap& edges, const char* filename) { - ofs << "2 " << it.first.first->point() - << " " << it.first.second->point() << std::endl; + std::ofstream ofs(filename); + ofs.precision(17); + + BOOST_FOREACH(typename Bimap::left_const_reference it, edges.left) + { + ofs << "2 " << it.first.first->point() + << " " << it.first.second->point() << std::endl; + } + + ofs.close(); + } +#endif + } + + namespace internal + { + template + bool insert_in_cells(const CellHandle c, CellsSet& cells) + { + std::set vertices; + for (int i = 0; i < 4; ++i) + vertices.insert(c->vertex(i)); + if (cells.find(vertices) != cells.end()) + return false; + cells.insert(vertices); + return true; + } + } // end internal + + namespace debug { + // forward-declaration + template + void dump_cells(const CellRange& cells, const char* filename); + } + namespace helpers + { + + template + void read_iso_cuboid(std::istream& is, + CGAL::Iso_cuboid_3& bbox) + { + typedef typename K::Point_3 Point_3; + Point_3 p1, p2; + double x, y, z; + is >> x >> y >> z; + p1 = Point_3(x, y, z); + is >> x >> y >> z; + p2 = Point_3(x, y, z); + + if (p1 < p2) + bbox = CGAL::Iso_cuboid_3(p1, p2); + else + bbox = CGAL::Iso_cuboid_3(p2, p1); + + CGAL_assertion(p1 != p2); } - ofs.close(); - } + template + void set_time_stamps(Tr& tr) + { + typedef typename Tr::Triangulation_data_structure::Vertex Vertex; + typedef typename Tr::Triangulation_data_structure::Cell Cell; + typedef typename Tr::Vertex_handle Vertex_handle; + typedef typename Tr::Cell_handle Cell_handle; + + CGAL::Time_stamper_impl v_ts; + for (typename Tr::All_vertices_iterator vit = tr.all_vertices_begin(); + vit != tr.all_vertices_end(); + ++vit) + { + Vertex_handle vh = vit; + Vertex* pv = &*vh; + v_ts.initialize_time_stamp(pv); + v_ts.set_time_stamp(pv); + } + CGAL::Time_stamper_impl c_ts; + for (typename Tr::All_cells_iterator cit = tr.all_cells_begin(); + cit != tr.all_cells_end(); + ++cit) + { + Cell_handle ch = cit; + Cell* pc = &*ch; + c_ts.initialize_time_stamp(pc); + c_ts.set_time_stamp(pc); + } + } + + template + struct Vertex_converter + { + //This operator is used to create the vertex from v_src. + typename TDS_tgt::Vertex operator()(const typename TDS_src::Vertex& v_src) const + { + typedef typename CGAL::Kernel_traits< + typename TDS_src::Vertex::Point>::Kernel GT_src; + typedef typename CGAL::Kernel_traits< + typename TDS_tgt::Vertex::Point>::Kernel GT_tgt; + CGAL::Cartesian_converter conv; + + typename TDS_tgt::Vertex v_tgt; + v_tgt.set_point(conv(v_src.point())); + v_tgt.set_time_stamp(-1); + v_tgt.set_dimension(v_src.info());//-1 if unset, 0,1,2, or 3 if set + return v_tgt; + } + //This operator is meant to be used in case heavy data should transferred to v_tgt. + void operator()(const typename TDS_src::Vertex& v_src, + typename TDS_tgt::Vertex& v_tgt) const + { + typedef typename CGAL::Kernel_traits< + typename TDS_src::Vertex::Point>::Kernel GT_src; + typedef typename CGAL::Kernel_traits< + typename TDS_tgt::Vertex::Point>::Kernel GT_tgt; + CGAL::Cartesian_converter conv; + + v_tgt.set_point(conv(v_src.point())); + v_tgt.set_dimension(v_src.info()); + } + }; + + template + struct Cell_converter + { + //This operator is used to create the cell from c_src. + typename TDS_tgt::Cell operator()(const typename TDS_src::Cell& c_src) const + { + typename TDS_tgt::Cell c_tgt; + c_tgt.info() = c_src.info(); + c_tgt.input_cell() = c_src; + c_tgt.set_time_stamp(-1); + return c_tgt; + } + //This operator is meant to be used in case heavy data should transferred to c_tgt. + void operator()(const typename TDS_src::Cell& c_src, + typename TDS_tgt::Cell& c_tgt) const + { + c_tgt.info() = c_src.info(); + c_tgt.input_cell() = c_src; + } + }; + + template + bool check_size_of_padding_box(const CellsSet& inside_cells, + const CGAL::Iso_cuboid_3& cuboid) + { + // all cells that are in intersecting_cells AND inside_cells + // should NOT be clipped + typedef typename CellsSet::value_type Cell_handle; + +#ifdef CGAL_LIMITED_APERTURE_DEBUG + std::vector cells; #endif + for (typename CellsSet::iterator cit = inside_cells.begin(); + cit != inside_cells.end(); ++cit) + { + Cell_handle c = *cit; + for (int i = 0; i < 4; ++i) + { + if (cuboid.has_on_unbounded_side(c->vertex(i)->point())) + { +#ifdef CGAL_LIMITED_APERTURE_DEBUG + cells.push_back(c); + break; +#else + return false; +#endif + } + } + } +#ifdef CGAL_LIMITED_APERTURE_DEBUG + debug::dump_cells(cells, "cells_from_padding_zone.mesh"); + return cells.empty(); +#else + return true; +#endif + } + +#ifdef CGAL_LIMITED_APERTURE_EDGE_SELECTION + + template + bool outer_box_criterion(const C3T3& c3t3, + CellCirculator circ, + CellCirculator end, + const typename C3T3::Subdomain_index& imaginary_index) + { + std::size_t nb_imaginary = 0; + std::size_t nb_total = 0; + std::size_t nb_padding = 0; + std::size_t nb_outside = 0; + do + { + if (circ->subdomain_index() == imaginary_index) + ++nb_imaginary; + else if (!c3t3.is_in_complex(circ)) + ++nb_outside; + else if (circ->info().padding()) + ++nb_padding; + + ++nb_total; + } while (++circ != end); + + return nb_padding > 0 && (nb_imaginary + nb_outside) < nb_total; + } + + template + bool is_on_the_outer_box(const typename C3T3::Edge& e, + const C3T3& c3t3, + const typename C3T3::Subdomain_index& imaginary_index) + { + typedef typename C3T3::Triangulation::Cell_circulator Cell_circulator; + Cell_circulator circ = c3t3.triangulation().incident_cells(e); + Cell_circulator end = circ; + + return outer_box_criterion(c3t3, circ, end, imaginary_index); + } + + template + bool is_on_the_outer_box(const typename C3T3::Vertex_handle& v, + const C3T3& c3t3, + const typename C3T3::Subdomain_index& imaginary_index) + { + std::vector cells; + c3t3.triangulation().incident_cells(v, std::back_inserter(cells)); + + return outer_box_criterion(c3t3, cells.begin(), cells.end(), imaginary_index); + } +#endif CGAL_LIMITED_APERTURE_EDGE_SELECTION + + }//end namespace helpers -} + namespace debug + { + template + void rebuild_with_insert(Tr& tr, const int nbv_max) + { + typedef typename Tr::Point Point; + std::vector points(tr.number_of_vertices()); + int index = 0; + for (typename Tr::Finite_vertices_iterator vit = tr.finite_vertices_begin(); + vit != tr.finite_vertices_end(); ++vit) + { + points[index++] = vit->point(); + } + + tr.clear(); + for (int i = 0; i < nbv_max; ++i) + tr.insert(points[i]); + } + + template + void check_validity(const Tr& tr) + { + CGAL_assertion(tr.is_valid(true)); + for (typename Tr::All_vertices_iterator vit = tr.all_vertices_begin(); + vit != tr.all_vertices_end(); + ++vit) + { + typename Tr::Cell_handle c = vit->cell(); + CGAL_assertion(c->has_vertex(vit)); + } + + std::ofstream ofs("extra_cells.polylines.txt"); + std::set extra_cells; + std::set > cells; + for (typename Tr::All_cells_iterator cit = tr.all_cells_begin(); + cit != tr.all_cells_end(); + ++cit) + { + typename Tr::Cell_handle c = cit; + for (int i = 0; i < 4; ++i) + { + typename Tr::Cell_handle ci = c->neighbor(i); + int j; + CGAL_assertion(c->has_neighbor(ci, j)); + CGAL_assertion(i == j); + j = ci->index(c); + CGAL_assertion(ci->neighbor(j) == c); + CGAL_assertion(ci->has_neighbor(c, j)); + } + if (!internal::insert_in_cells(c, cells)) + { + extra_cells.insert(c); + for (int j = 0; j < 4; ++j) + dump_facet(std::make_pair(c, j), ofs); + } + } + ofs.close(); + } + + template + void debug_infinite_facets(const ClippedCellsMap& clipped_cells, + const Tr& tr) + { + typedef typename Tr::Point Point; + //collect convex hull of tr edges (as pairs of ordered points) + std::vector/*ordered pair*/> ch_edges; + + for (typename ClippedCellsMap::const_iterator cmit = clipped_cells.begin(); + cmit != clipped_cells.end(); + ++cmit) + { + typedef typename ClippedCellsMap::mapped_type CellTr; + const CellTr& ctr = cmit->second; + + typename ClippedCellsMap::key_type cell = cmit->first; + + for (typename CellTr::Finite_edges_iterator eit = ctr.finite_edges_begin(); + eit != ctr.finite_edges_end(); + ++eit) + { + Point p1 = (eit->first)->vertex(eit->second)->point(); + Point p2 = (eit->first)->vertex(eit->third)->point(); + if (p2 < p1) + std::swap(p1, p2); //make sure that p1 <= p2 + + int vi = 0, vj = 0; + for (; vi < 4; ++vi) + { + if (cell->vertex(vi)->point() == p1) + break; + } + if (vi == 4) + continue; + for (; vj < 4; ++vj) + { + if (cell->vertex(vj)->point() == p2) + break; + } + if (vj == 4) + continue; + + int vk = Tr::next_around_edge(vi, vj); + int vl = Tr::next_around_edge(vj, vi); + if (tr.is_infinite(cell->neighbor(vk))) + ch_edges.push_back(std::make_pair(p1, p2)); + if (tr.is_infinite(cell->neighbor(vl))) + ch_edges.push_back(std::make_pair(p1, p2)); + } + } + + //check that each edge appears exactly twice + std::sort(ch_edges.begin(), ch_edges.end()); + bool twice_each = (ch_edges.size() % 2 == 0); + for (std::size_t i = 0; i < ch_edges.size() - 1; i = i + 2) + { + if (ch_edges[i] != ch_edges[i + 1]) + twice_each = false; + } + if (!twice_each) + { + for (std::size_t i = 0; i < ch_edges.size(); ++i) + { + std::cout << i << "\t" + << ch_edges[i].first << " " << ch_edges[i].second + << std::endl; + } + } + CGAL_assertion(twice_each); + } + + template + void dump_surface_off(const Tr& tr, const char* filename) + { + typedef typename Tr::Vertex_handle Vertex_handle; + typedef typename Tr::Cell_handle Cell_handle; + typedef typename Tr::Finite_facets_iterator Finite_facets_iterator; + typedef boost::bimap Bimap_t; + typedef typename Bimap_t::left_map::value_type value_type; + + //collect vertices + Bimap_t vertices; + std::size_t nbf = 0; + int index = 0; + for (Finite_facets_iterator fit = tr.finite_facets_begin(); + fit != tr.finite_facets_end(); ++fit) + { + Cell_handle c = fit->first; + int i = fit->second; + if (tr.is_infinite(c) || tr.is_infinite(c->neighbor(i))) + { + nbf++; + for (int j = 1; j < 4; ++j) + { + Vertex_handle vij = c->vertex((i + j) % 4); + if (vertices.left.find(vij) == vertices.left.end()) + vertices.left.insert(value_type(vij, index++)); + } + } + } + + //write header + std::ofstream ofs(filename); + ofs.precision(17); + ofs << "OFF" << std::endl; + ofs << vertices.left.size() << " " << nbf << " 0" << std::endl << std::endl; + + // write vertices + for (typename Bimap_t::right_iterator vit = vertices.right.begin(); + vit != vertices.right.end(); ++vit) + { + ofs << vit->second->point() << std::endl; + } + + //write facets + std::size_t nbf_print = 0; + for (Finite_facets_iterator fit = tr.finite_facets_begin(); + fit != tr.finite_facets_end(); ++fit) + { + Cell_handle c = fit->first; + int i = fit->second; + if (tr.is_infinite(c) || tr.is_infinite(c->neighbor(i))) + { + ofs << "3 " << vertices.left.at(c->vertex((i + 1) % 4)) << " " + << vertices.left.at(c->vertex((i + 2) % 4)) << " " + << vertices.left.at(c->vertex((i + 3) % 4)) << std::endl; + ++nbf_print; + } + } + CGAL_assertion(nbf == nbf_print); + + ofs.close(); + } + + template + void dump_cells_off(const Tr& tr, const char* filename) + { + typedef typename Tr::Vertex_handle Vertex_handle; + typedef typename Tr::Cell_handle Cell_handle; + typedef typename Tr::Finite_facets_iterator Finite_facets_iterator; + typedef typename Tr::Finite_vertices_iterator Finite_vertices_iterator; + typedef boost::bimap Bimap_t; + typedef typename Bimap_t::left_map::value_type value_type; + + //write header + std::ofstream ofs(filename); + ofs.precision(17); + ofs << "OFF" << std::endl; + ofs << tr.number_of_vertices() + << " " << tr.number_of_finite_facets() << " 0" << std::endl << std::endl; + + //collect and write vertices + Bimap_t vertices; + int index = 0; + for (Finite_vertices_iterator vit = tr.finite_vertices_begin(); + vit != tr.finite_vertices_end(); ++vit) + { + vertices.left.insert(value_type(vit, index++)); + ofs << vit->point().x() << " " + << vit->point().y() << " " + << vit->point().z() << std::endl; + } + + //write facets + for (Finite_facets_iterator fit = tr.finite_facets_begin(); + fit != tr.finite_facets_end(); ++fit) + { + Cell_handle c = fit->first; + int i = fit->second; + ofs << "3 " << vertices.left.at(c->vertex((i + 1) % 4)) << " " + << vertices.left.at(c->vertex((i + 2) % 4)) << " " + << vertices.left.at(c->vertex((i + 3) % 4)) << std::endl; + } + ofs.close(); + } + + template + void dump_cells(const CellRange& cells, + const IndexRange& indices, + const char* filename) + { + typedef typename Tr::Vertex_handle Vertex_handle; + typedef typename Tr::Point Point; + typedef boost::bimap Bimap_t; + typedef typename Bimap_t::left_map::value_type value_type; + + CGAL_assertion(indices.empty() || cells.size() == indices.size()); + + //collect vertices + Bimap_t vertices; + int index = 1; + for (typename CellRange::const_iterator cit = cells.begin(); + cit != cells.end(); + ++cit) + { + for (int i = 0; i < 4; ++i) + { + Vertex_handle vi = (*cit)->vertex(i); + if (vertices.left.find(vi) == vertices.left.end()) + vertices.left.insert(value_type(vi, index++)); + } + } + + //write cells + std::ofstream ofs(filename); + ofs.precision(17); + ofs << "MeshVersionFormatted 1" << std::endl; + ofs << "Dimension 3" << std::endl; + ofs << "Vertices" << std::endl << vertices.size() << std::endl; + for (typename Bimap_t::right_const_iterator vit = vertices.right.begin(); + vit != vertices.right.end(); + ++vit) + { + const Point& p = vit->second->point(); + ofs << p.x() << " " << p.y() << " " << p.z() << " 2" << std::endl; + } + ofs << "Tetrahedra " << std::endl << cells.size() << std::endl; + typename IndexRange::const_iterator iit = indices.begin(); + for (typename CellRange::const_iterator cit = cells.begin(); + cit != cells.end(); + ++cit) + { + ofs << vertices.left.at((*cit)->vertex(0)) + << " " << vertices.left.at((*cit)->vertex(1)) + << " " << vertices.left.at((*cit)->vertex(2)) + << " " << vertices.left.at((*cit)->vertex(3)); + + if (iit == indices.end()) + ofs << " 1" << std::endl; + else + { + // std::cerr << "Cell #" << (cit - cells.begin()) + // << " has original index " << *iit << std::endl; + ofs << " " << (*iit) << std::endl; + ++iit; + } + } + ofs << "End" << std::endl; + ofs.close(); + } + + template + void dump_cells(const CellRange& cells, const char* filename) + { + std::vector indices; + dump_cells(cells, indices, filename); + } + + template + void dump_cells_in_complex(const Tr& tr, const char* filename) + { + std::vector cells; + std::vector indices; + + for (typename Tr::Finite_cells_iterator cit = tr.finite_cells_begin(); + cit != tr.finite_cells_end(); ++cit) + { + if (cit->subdomain_index() > 0) + { + cells.push_back(cit); + indices.push_back(cit->subdomain_index()); + } + } + dump_cells(cells, indices, filename); + } + + template + void dump_facets_in_complex(const C3t3& c3t3, const char* filename) + { + typedef typename C3t3::Triangulation Tr; + typedef typename Tr::Vertex_handle Vertex_handle; + typedef typename Tr::Cell_handle Cell_handle; + typedef typename C3t3::Facets_in_complex_iterator Facets_in_complex_iterator; + typedef boost::bimap Bimap_t; + typedef typename Bimap_t::left_map::value_type value_type; + + //collect vertices + Bimap_t vertices; + std::size_t nbf = 0; + int index = 0; + for (Facets_in_complex_iterator fit = c3t3.facets_in_complex_begin(); + fit != c3t3.facets_in_complex_end(); ++fit) + { + Cell_handle c = fit->first; + int i = fit->second; + + nbf++; + for (int j = 1; j < 4; ++j) + { + Vertex_handle vij = c->vertex((i + j) % 4); + if (vertices.left.find(vij) == vertices.left.end()) + vertices.left.insert(value_type(vij, index++)); + } + } + + //write header + std::ofstream ofs(filename); + ofs.precision(17); + ofs << "OFF" << std::endl; + ofs << vertices.left.size() << " " << nbf << " 0" << std::endl << std::endl; + + // write vertices + for (typename Bimap_t::right_iterator vit = vertices.right.begin(); + vit != vertices.right.end(); ++vit) + { + ofs << vit->second->point() << std::endl; + } + + //write facets + std::size_t nbf_print = 0; + for (Facets_in_complex_iterator fit = c3t3.facets_in_complex_begin(); + fit != c3t3.facets_in_complex_end(); ++fit) + { + Cell_handle c = fit->first; + int i = fit->second; + ofs << "3 " << vertices.left.at(c->vertex((i + 1) % 4)) << " " + << vertices.left.at(c->vertex((i + 2) % 4)) << " " + << vertices.left.at(c->vertex((i + 3) % 4)) << std::endl; + ++nbf_print; + } + CGAL_assertion(nbf == nbf_print); + + ofs.close(); + } + + template + void dump_edges_in_complex(const C3T3& c3t3, const char* filename) + { + std::ofstream ofs(filename); + ofs.precision(17); + for (typename C3T3::Edges_in_complex_iterator eit = c3t3.edges_in_complex_begin(); + eit != c3t3.edges_in_complex_end(); ++eit) + { + const typename C3T3::Edge& e = *eit; + ofs << "2 " + << e.first->vertex(e.second)->point() << " " + << e.first->vertex(e.third)->point() << "\n"; + } + ofs.close(); + } + + template + void dump_vertices_by_dimension(const Tr& tr, const char* prefix) + { + typedef typename Tr::Vertex_handle Vertex_handle; + std::vector< std::vector > vertices_per_dimension(4); + + for (typename Tr::Finite_vertices_iterator + vit = tr.finite_vertices_begin(); + vit != tr.finite_vertices_end(); + ++vit) + { + //vertices_per_dimension[vit->info()].push_back(vit); + vertices_per_dimension[vit->in_dimension()].push_back(vit); + } + + for (int i = 0; i < 4; ++i) + { + //dimension is i + const std::vector& vertices_di = vertices_per_dimension[i]; + + std::cout << "Dimension " << i << " : " << vertices_di.size() << std::endl; + + std::ostringstream oss; + oss << prefix << "_dimension_" << i << ".off"; + + std::ofstream ofs(oss.str()); + ofs.precision(17); + ofs << "OFF" << std::endl; + ofs << vertices_di.size() << " 0 0" << std::endl << std::endl; + + for (std::size_t j = 0; j < vertices_di.size(); ++j) + { + ofs << vertices_di[j]->point() << std::endl; + } + + ofs.close(); + } + } + + template + void dump_triangulation_cells(const Tr& tr, const char* filename) + { + std::vector cells(tr.number_of_finite_cells()); + int i = 0; + for (typename Tr::Finite_cells_iterator cit = tr.finite_cells_begin(); + cit != tr.finite_cells_end(); ++cit) + { + cells[i++] = cit; + } + dump_cells(cells, filename); + } + + template + void dump_without_imaginary(const Tr& tr, const char* filename, + const int imaginary_index) + { + std::vector cells; + std::vector indices; + + for (typename Tr::Finite_cells_iterator cit = tr.finite_cells_begin(); + cit != tr.finite_cells_end(); ++cit) + { + if (cit->subdomain_index() > 0 + && cit->subdomain_index() != imaginary_index) + { + cells.push_back(cit); + indices.push_back(1); + //cit->info().padding() ? + //-1 : + //cit->info().original_index()); + } + } + dump_cells(cells, indices, filename); + } + + template + void dump_padding_cells(const Tr& tr, const char* filename) + { + std::vector cells; + std::vector indices; + + for (typename Tr::Finite_cells_iterator cit = tr.finite_cells_begin(); + cit != tr.finite_cells_end(); ++cit) + { + if (cit->info().padding()) + { + cells.push_back(cit); + if (cit->subdomain_index() > 0) + indices.push_back(cit->subdomain_index()); + else + indices.push_back(1); + } + } + dump_cells(cells, indices, filename); + } + + template + void dump_non_padding_plus_the_outer_bbox(const Tr& tr, + const Isocuboid& bbox, + const char* filename) + { + typedef typename Tr::Vertex_handle Vertex_handle; + typedef typename Tr::Point Point; + typedef boost::bimap Bimap_t; + typedef typename Bimap_t::left_map::value_type value_type; + + Bimap_t vertices; + int index = 9; // because we output first the 8 vertices of the + // bbox + std::size_t nb_of_cells = 0; + for (typename Tr::Finite_cells_iterator cit = tr.finite_cells_begin(); + cit != tr.finite_cells_end(); ++cit) + { + if (cit->info().padding()) { + continue; + } + ++nb_of_cells; + for (int i = 0; i < 4; ++i) + { + Vertex_handle vi = cit->vertex(i); + if (vertices.left.find(vi) == vertices.left.end()) + vertices.left.insert(value_type(vi, index++)); + } + } + std::ofstream ofs(filename); + ofs.precision(17); + ofs << "MeshVersionFormatted 1\n" + << "Dimension 3\n" + << "Vertices\n" + << vertices.size() + 8 << std::endl; + const CGAL::cpp11::array indices = { 0, 3, 2, 1, 5, 4, 7, 6 }; + for (int i = 0; i < 8; ++i) { + const typename Tr::Point_3 p = bbox[indices[i]]; + ofs << p.x() << " " << p.y() << " " << p.z() << " 1" << std::endl; + } + for (typename Bimap_t::right_const_iterator vit = vertices.right.begin(); + vit != vertices.right.end(); + ++vit) + { + const Point& p = vit->second->point(); + ofs << p.x() << " " << p.y() << " " << p.z() << " 2" << std::endl; + } + ofs << "Triangles\n" + << "12\n" + << "1 2 4 1\n" + << "4 2 3 1\n" + << "1 5 2 1\n" + << "2 5 6 1\n" + << "4 3 8 1\n" + << "8 3 7 1\n" + << "5 1 4 1\n" + << "8 5 4 1\n" + << "7 5 8 1\n" + << "7 6 5 1\n" + << "2 6 7 1\n" + << "3 2 7 1\n"; + ofs << "Tetrahedra" << std::endl << nb_of_cells << std::endl; + for (typename Tr::Finite_cells_iterator cit = tr.finite_cells_begin(); + cit != tr.finite_cells_end(); ++cit) + { + if (cit->info().padding()) continue; + ofs << vertices.left.at(cit->vertex(0)) << " " + << vertices.left.at(cit->vertex(1)) << " " + << vertices.left.at(cit->vertex(2)) << " " + << vertices.left.at(cit->vertex(3)) << " " + << cit->info().original_index() << std::endl; + } + ofs << "End" << std::endl; + ofs.close(); + } + + + template + void dump_edges(const VertexPairsSet& edges, const char* filename) + { + std::ofstream ofs(filename); + BOOST_FOREACH(typename VertexPairsSet::key_type vp, edges) + { + ofs << "2 " << vp.first->point() + << " " << vp.second->point() << std::endl; + } + ofs.close(); + } + }// end namespace debug + } } diff --git a/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/triangulation_3_helpers.h b/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/triangulation_3_helpers.h index ddc363200fe..d92e8ec4a89 100644 --- a/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/triangulation_3_helpers.h +++ b/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/triangulation_3_helpers.h @@ -27,8 +27,13 @@ #include #include +#include +#include #include +#include + #include + #include #include @@ -81,6 +86,31 @@ namespace CGAL } // end namespace debug (in ::CGAL) + template + CGAL::Point_3 point(const CGAL::Point_3& p) + { + return p; + } + template + CGAL::Point_3 point(const CGAL::Weighted_point_3& wp) + { + typename K::Construct_point_3 pt = K().construct_point_3_object(); + return pt(wp); + } + + template + CGAL::Vector_3 vec(const CGAL::Point_3& p) + { + typename K::Construct_vector_3 v = K().construct_vector_3_object(); + return v(CGAL::ORIGIN, p); + } + template + CGAL::Vector_3 vec(const CGAL::Weighted_point_3& wp) + { + return vec(point(wp)); + } + + const int indices_table[4][3] = { { 3, 1, 2 }, { 3, 2, 0 }, { 3, 0, 1 }, @@ -136,19 +166,19 @@ namespace CGAL VertexHandle v2, VertexHandle v3) { - return min_dihedral_angle(v0->point(), - v1->point(), - v2->point(), - v3->point()); + return min_dihedral_angle(point(v0->point()), + point(v1->point()), + point(v2->point()), + point(v3->point())); } template typename Gt::FT min_dihedral_angle(CellHandle c) { - return min_dihedral_angle(c->vertex(0)->point(), - c->vertex(1)->point(), - c->vertex(2)->point(), - c->vertex(3)->point()); + return min_dihedral_angle(point(c->vertex(0)->point()), + point(c->vertex(1)->point()), + point(c->vertex(2)->point()), + point(c->vertex(3)->point())); } template @@ -189,8 +219,10 @@ namespace CGAL template CGAL::Orientation orientation(const CellHandle ch) { - return CGAL::orientation(ch->vertex(0)->point(), ch->vertex(1)->point(), - ch->vertex(2)->point(), ch->vertex(3)->point()); + return CGAL::orientation(point(ch->vertex(0)->point()), + point(ch->vertex(1)->point()), + point(ch->vertex(2)->point()), + point(ch->vertex(3)->point())); } template @@ -203,8 +235,8 @@ namespace CGAL bool is_well_oriented(const VertexHandle v0, const VertexHandle v1, const VertexHandle v2, const VertexHandle v3) { - return CGAL::POSITIVE == CGAL::orientation(v0->point(), v1->point(), - v2->point(), v3->point()); + return CGAL::POSITIVE == CGAL::orientation(point(v0->point()), point(v1->point()), + point(v2->point()), point(v3->point())); } template @@ -663,9 +695,9 @@ namespace CGAL typedef typename Gt::Vector_3 Vector; typedef typename Gt::Point_3 Point; - Point p0 = f.first->vertex((f.second + 1) % 4)->point(); - Point p1 = f.first->vertex((f.second + 2) % 4)->point(); - const Point& p2 = f.first->vertex((f.second + 3) % 4)->point(); + Point p0 = point(f.first->vertex((f.second + 1) % 4)->point()); + Point p1 = point(f.first->vertex((f.second + 2) % 4)->point()); + const Point& p2 = point(f.first->vertex((f.second + 3) % 4)->point()); //if (CGAL::POSITIVE != CGAL::orientation(p0, p1, p2, p3)) if (f.second % 2 == 0)//equivalent to the commented orientation test From 15c21d5bd9024f086bf7cf2680fe04ebc1ead67f Mon Sep 17 00:00:00 2001 From: Jane Tournois Date: Fri, 13 Sep 2019 12:30:13 +0200 Subject: [PATCH 008/568] add examples --- .../Tetrahedral_remeshing/CMakeLists.txt | 5 + .../Tetrahedral_remeshing/generate_input.cpp | 84 +++++++++ .../tetrahedral_remeshing_example.cpp | 68 ++++---- ...tetrahedral_remeshing_of_one_subdomain.cpp | 66 ++++++++ .../tetrahedral_remeshing_with_features.cpp | 159 ++++++++++++++++++ 5 files changed, 344 insertions(+), 38 deletions(-) create mode 100644 Tetrahedral_remeshing/examples/Tetrahedral_remeshing/generate_input.cpp create mode 100644 Tetrahedral_remeshing/examples/Tetrahedral_remeshing/tetrahedral_remeshing_of_one_subdomain.cpp create mode 100644 Tetrahedral_remeshing/examples/Tetrahedral_remeshing/tetrahedral_remeshing_with_features.cpp diff --git a/Tetrahedral_remeshing/examples/Tetrahedral_remeshing/CMakeLists.txt b/Tetrahedral_remeshing/examples/Tetrahedral_remeshing/CMakeLists.txt index f771803899e..6f2cf7e1a12 100644 --- a/Tetrahedral_remeshing/examples/Tetrahedral_remeshing/CMakeLists.txt +++ b/Tetrahedral_remeshing/examples/Tetrahedral_remeshing/CMakeLists.txt @@ -26,3 +26,8 @@ endif() # Creating entries for all C++ files with "main" routine # ########################################################## create_single_source_cgal_program( "tetrahedral_remeshing_example.cpp" ) + create_single_source_cgal_program( "tetrahedral_remeshing_with_features.cpp") + create_single_source_cgal_program( "tetrahedral_remeshing_of_one_subdomain.cpp") + + create_single_source_cgal_program( "generate_input.cpp ") + create_single_source_cgal_program( "test_mesh_loader.cpp ") diff --git a/Tetrahedral_remeshing/examples/Tetrahedral_remeshing/generate_input.cpp b/Tetrahedral_remeshing/examples/Tetrahedral_remeshing/generate_input.cpp new file mode 100644 index 00000000000..47185fcb80e --- /dev/null +++ b/Tetrahedral_remeshing/examples/Tetrahedral_remeshing/generate_input.cpp @@ -0,0 +1,84 @@ +#include + +#include +#include + +#include +#include + +#include + +#include + + +typedef CGAL::Exact_predicates_inexact_constructions_kernel K; + +typedef CGAL::Tetrahedral_remeshing::Remeshing_triangulation_3 T3; +typedef int Corner_index; +typedef int Curve_segment_index; + +typedef CGAL::Mesh_complex_3_in_triangulation_3 C3t3; + + +int main(int argc, char* argv[]) +{ + const std::size_t nbv = 1000; + + int input_id = (argc > 1) ? atoi(argv[1]) : 1; + char* filename; + + T3 tr; + C3t3 c3t3; + c3t3.triangulation() = tr; + + CGAL::Random rng; + + if (input_id == 1) //sphere and only one subdomain + { + filename = "data/triangulation_one_subdomain.binary.cgal"; + + while (tr.number_of_vertices() < nbv) + tr.insert(T3::Point(rng.get_double(-1., 1.), rng.get_double(-1., 1.), rng.get_double(-1., 1.))); + + for (T3::Finite_cells_iterator cit = tr.finite_cells_begin(); + cit != tr.finite_cells_end(); ++cit) + { + c3t3.add_to_complex(cit, 1); + } + } + else if (input_id == 2) //sphere separated in 2 subdomains by a plane + { + filename = "data/triangulation_two_subdomains.binary.cgal"; + + while (c3t3.triangulation().number_of_vertices() < nbv) + c3t3.triangulation().insert( + T3::Point(rng.get_double(-1., 1.), rng.get_double(-1., 1.), rng.get_double(-1., 1.))); + + const K::Plane_3 plane(K::Point_3(0,0,0), K::Point_3(0,1,0), K::Point_3(0,0,1)); + + for (T3::Finite_cells_iterator cit = c3t3.triangulation().finite_cells_begin(); + cit != c3t3.triangulation().finite_cells_end(); ++cit) + { + int index; + if(plane.has_on_positive_side( + CGAL::centroid(cit->vertex(0)->point(), cit->vertex(1)->point(), + cit->vertex(2)->point(), cit->vertex(3)->point()))) + index = 1; + else + index = 2; + + c3t3.add_to_complex(cit, index); + } + } + + std::ofstream out(filename, std::ios_base::out | std::ios_base::binary); + CGAL::Mesh_3::save_binary_file(out, c3t3); + + std::string file_in(filename); + std::string file_out = file_in.substr(0, file_in.find_first_of(".")); + file_out.append(".mesh"); + std::ofstream medit_out(file_out.c_str(), std::ios_base::out); + c3t3.output_to_medit(medit_out); + + return (!out.bad()); +} diff --git a/Tetrahedral_remeshing/examples/Tetrahedral_remeshing/tetrahedral_remeshing_example.cpp b/Tetrahedral_remeshing/examples/Tetrahedral_remeshing/tetrahedral_remeshing_example.cpp index d31c37e1f2f..306f0e6b82f 100644 --- a/Tetrahedral_remeshing/examples/Tetrahedral_remeshing/tetrahedral_remeshing_example.cpp +++ b/Tetrahedral_remeshing/examples/Tetrahedral_remeshing/tetrahedral_remeshing_example.cpp @@ -1,65 +1,57 @@ +#define CGAL_TETRAHEDRAL_REMESHING_VERBOSE + #include #include #include - -#include +#include #include #include -#include +#include typedef CGAL::Exact_predicates_inexact_constructions_kernel K; - -typedef CGAL::Triangulation_3 T3; -typedef CGAL::Tetrahedral_remeshing::Remeshing_triangulation_3 Remeshing_triangulation; +typedef CGAL::Tetrahedral_remeshing::Remeshing_triangulation_3 T3; //todo : add specialization for Cell_base without info // (does not compile with `void` instead of `int`) +typedef int Corner_index; +typedef int Curve_segment_index; -bool generate_input(const std::size_t& n, - const char* filename) -{ - T3 tr; - CGAL::Random rng; +typedef CGAL::Mesh_complex_3_in_triangulation_3 C3t3; - while (tr.number_of_vertices() < n) - tr.insert(T3::Point(rng.get_double(-1., 1.), rng.get_double(-1., 1.), rng.get_double(-1., 1.))); - - std::ofstream oFileT(filename, std::ios::out); - // writing file output; - oFileT << tr; - - return (!oFileT.bad()); -} int main(int argc, char* argv[]) { - generate_input(1000, "data/random_sphere_triangulation.cgal"); - - const char* filename = (argc > 1) ? argv[1] : "data/random_sphere_triangulation.cgal"; + const char* filename = (argc > 1) ? argv[1] : "data/triangulation_one_subdomain.binary.cgal"; float target_edge_length = (argc > 2) ? atof(argv[2]) : 0.1f; - std::ifstream input(filename, std::ios::in); + std::ifstream input(filename, std::ios::in | std::ios::binary); + + C3t3 c3t3; if (!input) - { - std::cerr << "File " << filename << " could not be found" << std::endl; - return EXIT_FAILURE; - } + return false; - T3 t3; - input >> t3; - CGAL_assertion(t3.is_valid()); + if( !CGAL::Mesh_3::load_binary_file(input, c3t3)) + return false; - Remeshing_triangulation tr; - CGAL::Tetrahedral_remeshing::build_remeshing_triangulation(t3, tr); - - CGAL::tetrahedral_adaptive_remeshing(tr, target_edge_length); + CGAL::tetrahedral_adaptive_remeshing(c3t3.triangulation(), target_edge_length); - std::ofstream oFileT("output.tr.cgal", std::ios::out); - // writing file output; - oFileT << tr; + // save output + const std::string file_in(filename); + + // binary + std::string file_out = file_in.substr(0, file_in.find_first_of(".")); + file_out.append("_out.binary.cgal"); + std::ofstream out(file_out.c_str(), std::ios_base::out | std::ios_base::binary); + CGAL::Mesh_3::save_binary_file(out, c3t3); + + // ascii + file_out = file_in.substr(0, file_in.find_first_of(".")); + file_out.append("_out.mesh"); + std::ofstream medit_out(file_out.c_str(), std::ios_base::out); + c3t3.output_to_medit(medit_out); return EXIT_SUCCESS; } diff --git a/Tetrahedral_remeshing/examples/Tetrahedral_remeshing/tetrahedral_remeshing_of_one_subdomain.cpp b/Tetrahedral_remeshing/examples/Tetrahedral_remeshing/tetrahedral_remeshing_of_one_subdomain.cpp new file mode 100644 index 00000000000..b892bb4b44b --- /dev/null +++ b/Tetrahedral_remeshing/examples/Tetrahedral_remeshing/tetrahedral_remeshing_of_one_subdomain.cpp @@ -0,0 +1,66 @@ +#include + +#include +#include + +#include + +#include +#include + +#include + +typedef CGAL::Exact_predicates_inexact_constructions_kernel K; + + +typedef CGAL::Triangulation_3 T3; +typedef CGAL::Tetrahedral_remeshing::Remeshing_triangulation_3 Remeshing_triangulation; +//todo : add specialization for Cell_base without info +// (does not compile with `void` instead of `int`) + +bool generate_input(const std::size_t& n, + const char* filename) +{ + T3 tr; + CGAL::Random rng; + + while (tr.number_of_vertices() < n) + tr.insert(T3::Point(rng.get_double(-1., 1.), rng.get_double(-1., 1.), rng.get_double(-1., 1.))); + + std::ofstream oFileT(filename, std::ios::out); + // writing file output; + oFileT << tr; + + return (!oFileT.bad()); +} + +int main(int argc, char* argv[]) +{ + generate_input(1000, "data/random_sphere_triangulation.cgal"); + + const char* filename = (argc > 1) ? argv[1] : "data/random_sphere_triangulation.cgal"; + float target_edge_length = (argc > 2) ? atof(argv[2]) : 0.1f; + + std::ifstream input(filename, std::ios::in); + if (!input) + { + std::cerr << "File " << filename << " could not be found" << std::endl; + return EXIT_FAILURE; + } + + T3 t3; + input >> t3; + CGAL_assertion(t3.is_valid()); + + Remeshing_triangulation tr; + CGAL::Tetrahedral_remeshing::build_remeshing_triangulation(t3, tr); + + CGAL::tetrahedral_adaptive_remeshing(tr, target_edge_length); + + std::ofstream oFileT("output.tr.cgal", std::ios::out); + // writing file output; + oFileT << tr; + + return EXIT_SUCCESS; +} + diff --git a/Tetrahedral_remeshing/examples/Tetrahedral_remeshing/tetrahedral_remeshing_with_features.cpp b/Tetrahedral_remeshing/examples/Tetrahedral_remeshing/tetrahedral_remeshing_with_features.cpp new file mode 100644 index 00000000000..17362092cfe --- /dev/null +++ b/Tetrahedral_remeshing/examples/Tetrahedral_remeshing/tetrahedral_remeshing_with_features.cpp @@ -0,0 +1,159 @@ +#include +#include + +#define CGAL_TETRAHEDRAL_REMESHING_VERBOSE +#define CGAL_DUMP_REMESHING_STEPS + +#include + +#include +#include + +#include + +#include +#include + +#include + +typedef CGAL::Exact_predicates_inexact_constructions_kernel K; + +typedef CGAL::Tetrahedral_remeshing::Remeshing_triangulation_3 Remeshing_triangulation; +//todo : add specialization for Cell_base without info +// (does not compile with `void` instead of `int`) + +typedef Remeshing_triangulation::Point Point; +typedef Remeshing_triangulation::Vertex_handle Vertex_handle; +typedef Remeshing_triangulation::Cell_handle Cell_handle; +typedef Remeshing_triangulation::Edge Edge; + +template +class Constrained_edges_property_map +{ +public: + typedef bool value_type; + typedef bool reference; + typedef typename T3::Edge key_type; + typedef boost::read_write_property_map_tag category; + +private: + boost::unordered_set* m_set_ptr; + +public: + Constrained_edges_property_map() + : m_set_ptr(NULL) + {} + Constrained_edges_property_map(boost::unordered_set* set_) + : m_set_ptr(set_) + {} + +public: + friend void put(Constrained_edges_property_map& map, + const key_type& k, + const bool b) + { + CGAL_assertion(map.m_set_ptr != NULL); + if (b) map.m_set_ptr->insert(k); + else map.m_set_ptr->erase(k); + } + + friend const value_type get(const Constrained_edges_property_map& map, + const key_type& k) + { + CGAL_assertion(map.m_set_ptr != NULL); + return map.m_set_ptr->count(k); + } +}; + +void add_edge(Vertex_handle v1, + Vertex_handle v2, + const Remeshing_triangulation& tr, + boost::unordered_set& constraints) +{ + Cell_handle c; + int i, j; + if(tr.is_edge(v1, v2, c, i, j)) + constraints.insert(Edge(c, i, j)); +} + +void generate_input(const std::size_t& n, + const char* filename, + boost::unordered_set& constraints) +{ + Remeshing_triangulation tr; + CGAL::Random rng; + + // points in a sphere + while (tr.number_of_vertices() < n) + tr.insert(Point(rng.get_double(-1., 1.), rng.get_double(-1., 1.), rng.get_double(-1., 1.))); + // vertices of a larger cube + Vertex_handle v0 = tr.insert(Point(-2., -2., -2.)); + Vertex_handle v1 = tr.insert(Point(-2., -2., 2.)); + + Vertex_handle v2 = tr.insert(Point( 2., -2., -2.)); + Vertex_handle v3 = tr.insert(Point( 2., -2., 2.)); + + Vertex_handle v4 = tr.insert(Point(-2., 2., -2.)); + Vertex_handle v5 = tr.insert(Point(-2., 2., 2.)); + + Vertex_handle v6 = tr.insert(Point( 2., 2., -2.)); + Vertex_handle v7 = tr.insert(Point( 2., 2., 2.)); + + // writing file output + std::ofstream oFileT(filename, std::ios::out); + oFileT << tr; + oFileT.close(); + + // constrain cube edges + add_edge(v0, v1, tr, constraints); + add_edge(v1, v2, tr, constraints); + add_edge(v2, v3, tr, constraints); + add_edge(v3, v0, tr, constraints); + + add_edge(v4, v5, tr, constraints); + add_edge(v5, v6, tr, constraints); + add_edge(v6, v7, tr, constraints); + add_edge(v7, v4, tr, constraints); + + add_edge(v0, v4, tr, constraints); + add_edge(v1, v5, tr, constraints); + add_edge(v2, v6, tr, constraints); + add_edge(v3, v7, tr, constraints); +} + +int main(int argc, char* argv[]) +{ + boost::unordered_set constraints; + generate_input(1000, "data/sphere_in_cube.tr.cgal", constraints); + + const char* filename = (argc > 1) ? argv[1] : "data/sphere_in_cube.tr.cgal"; + float target_edge_length = (argc > 2) ? atof(argv[2]) : 0.1f; + + std::ifstream input(filename, std::ios::in); + if (!input) + { + std::cerr << "File " << filename << " could not be found" << std::endl; + return EXIT_FAILURE; + } + + Remeshing_triangulation t3; + input >> t3; + CGAL_assertion(t3.is_valid()); + + CGAL::Tetrahedral_remeshing::debug::dump_triangulation_cells(t3, + "tet_remeshing_with_features_before.mesh"); + + CGAL::tetrahedral_adaptive_remeshing(t3, target_edge_length, + CGAL::parameters::edge_is_constrained_map( + Constrained_edges_property_map(&constraints))); + + std::ofstream oFileT("output.tr.cgal", std::ios::out); + // writing file output; + oFileT << t3; + + CGAL::Tetrahedral_remeshing::debug::dump_triangulation_cells(t3, + "tet_remeshing_with_features_after.mesh"); + + return EXIT_SUCCESS; +} + From 197193bdbd73df56e49032af08a8899ae4c56399 Mon Sep 17 00:00:00 2001 From: Jane Tournois Date: Tue, 17 Sep 2019 13:56:38 +0200 Subject: [PATCH 009/568] fix more Point_3/Weighted_point_3 conflicts --- .../internal/compute_c3t3_statistics.h | 20 ++++++++++--------- .../internal/flip_edges.h | 12 +++++------ 2 files changed, 17 insertions(+), 15 deletions(-) diff --git a/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/compute_c3t3_statistics.h b/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/compute_c3t3_statistics.h index 21b7bdfbc91..f7ff862e2bf 100644 --- a/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/compute_c3t3_statistics.h +++ b/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/compute_c3t3_statistics.h @@ -28,6 +28,8 @@ #include +#include + namespace CGAL { namespace Tetrahedral_remeshing @@ -44,7 +46,7 @@ namespace internal typedef typename Tr::Geom_traits Gt; typedef typename Tr::Cell_handle Cell_handle; typedef typename Tr::Vertex_handle Vertex_handle; - typedef typename Tr::Point Point; + typedef typename Gt::Point_3 Point; typedef typename Tr::Finite_facets_iterator Finite_facets_iterator; typedef typename Tr::Finite_cells_iterator Finite_cells_iterator; typedef typename Tr::Cell::Subdomain_index Subdomain_index; @@ -71,9 +73,9 @@ namespace internal if (!cell_selector(cell) || !cell_selector(cell->neighbor(index))) continue; - const Point& pa = (cell->vertex((index + 1) & 3)->point()); - const Point& pb = (cell->vertex((index + 2) & 3)->point()); - const Point& pc = (cell->vertex((index + 3) & 3)->point()); + const Point& pa = point(cell->vertex((index + 1) & 3)->point()); + const Point& pb = point(cell->vertex((index + 2) & 3)->point()); + const Point& pc = point(cell->vertex((index + 3) & 3)->point()); double edges[3]; edges[0] = (CGAL::sqrt(CGAL::squared_distance(pa, pb))); @@ -110,11 +112,11 @@ namespace internal for (int i = 0; i < 4; ++i) selected_vertices.insert(cit->vertex(i)); - const Point& p0 = (cit->vertex(0)->point()); - const Point& p1 = (cit->vertex(1)->point()); - const Point& p2 = (cit->vertex(2)->point()); - const Point& p3 = (cit->vertex(3)->point()); - double v = CGAL::abs(CGAL::volume(p0, p1, p2, p3)); + const Point& p0 = point(cit->vertex(0)->point()); + const Point& p1 = point(cit->vertex(1)->point()); + const Point& p2 = point(cit->vertex(2)->point()); + const Point& p3 = point(cit->vertex(3)->point()); + double v = CGAL::abs(tr.tetrahedron(cit).volume()); double circumradius = CGAL::sqrt(CGAL::squared_radius(p0, p1, p2, p3)); //find shortest edge diff --git a/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/flip_edges.h b/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/flip_edges.h index fdec3e473ca..f2b72e8fba2 100644 --- a/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/flip_edges.h +++ b/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/flip_edges.h @@ -152,11 +152,11 @@ namespace internal curr_min_dh = (std::min)(curr_min_dh, min_dihedral_angle(cell_to_remove)); //Result worst dihedral angle - if (curr_min_dh > min_dihedral_angle(vh2, + if (curr_min_dh > min_dihedral_angle(vh2, ch0->vertex(indices(vh0_id, 0)), ch0->vertex(indices(vh0_id, 1)), ch0->vertex(indices(vh0_id, 2))) - || curr_min_dh > min_dihedral_angle(vh3, + || curr_min_dh > min_dihedral_angle(vh3, ch1->vertex(indices(vh1_id, 0)), ch1->vertex(indices(vh1_id, 1)), ch1->vertex(indices(vh1_id, 2)))) @@ -172,10 +172,10 @@ namespace internal average_min_dh /= 3.; FT new_average_min_dh = 0.5 * - (min_dihedral_angle(vh2, ch0->vertex(indices(vh0_id, 0)), + (min_dihedral_angle(vh2, ch0->vertex(indices(vh0_id, 0)), ch0->vertex(indices(vh0_id, 1)), ch0->vertex(indices(vh0_id, 2))) - + min_dihedral_angle(vh3, ch1->vertex(indices(vh1_id, 0)), + + min_dihedral_angle(vh3, ch1->vertex(indices(vh1_id, 0)), ch1->vertex(indices(vh1_id, 1)), ch1->vertex(indices(vh1_id, 2)))); //Result worst dihedral angle @@ -432,7 +432,7 @@ namespace internal fi.first->vertex(indices(fi.second, 2)))) { min_flip_dihedral_angle = (std::min)(min_flip_dihedral_angle, - min_dihedral_angle(vh, fi.first->vertex(indices(fi.second, 0)), + min_dihedral_angle(vh, fi.first->vertex(indices(fi.second, 0)), fi.first->vertex(indices(fi.second, 1)), fi.first->vertex(indices(fi.second, 2)))); } @@ -571,7 +571,7 @@ namespace internal fi.first->vertex(indices(fi.second, 2)))) { min_flip_dihedral_angle = (std::min)(min_flip_dihedral_angle, - min_dihedral_angle(vh, fi.first->vertex(indices(fi.second, 0)), + min_dihedral_angle(vh, fi.first->vertex(indices(fi.second, 0)), fi.first->vertex(indices(fi.second, 1)), fi.first->vertex(indices(fi.second, 2)))); } From aca0b6ef7d5e8654015969485c0ecf6d39230e1a Mon Sep 17 00:00:00 2001 From: Jane Tournois Date: Tue, 17 Sep 2019 13:57:14 +0200 Subject: [PATCH 010/568] add_to_complex() should not be used when subdomain_index is 0 --- Polyhedron/demo/Polyhedron/Plugins/Mesh_3/C3t3_io_plugin.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/Polyhedron/demo/Polyhedron/Plugins/Mesh_3/C3t3_io_plugin.cpp b/Polyhedron/demo/Polyhedron/Plugins/Mesh_3/C3t3_io_plugin.cpp index 4a7c004be2b..c421c77390b 100644 --- a/Polyhedron/demo/Polyhedron/Plugins/Mesh_3/C3t3_io_plugin.cpp +++ b/Polyhedron/demo/Polyhedron/Plugins/Mesh_3/C3t3_io_plugin.cpp @@ -130,7 +130,8 @@ Polyhedron_demo_c3t3_binary_io_plugin::load( ++cit) { CGAL_assertion(cit->info() >= 0); - item->c3t3().add_to_complex(cit, cit->info()); + if(cit->info() != 0) + item->c3t3().add_to_complex(cit, cit->info()); for(int i=0; i < 4; ++i) { if(cit->surface_patch_index(i)>0) From e723a46e7da64234b65e86cb843a116069dcffa0 Mon Sep 17 00:00:00 2001 From: Jane Tournois Date: Tue, 17 Sep 2019 13:57:41 +0200 Subject: [PATCH 011/568] add tetrahedral remeshing plugin --- .../Tetrahedral_remeshing/CMakeLists.txt | 10 + .../Tetrahedral_remeshing_plugin.cpp | 212 ++++++++++++++++++ 2 files changed, 222 insertions(+) create mode 100644 Polyhedron/demo/Polyhedron/Plugins/Tetrahedral_remeshing/CMakeLists.txt create mode 100644 Polyhedron/demo/Polyhedron/Plugins/Tetrahedral_remeshing/Tetrahedral_remeshing_plugin.cpp diff --git a/Polyhedron/demo/Polyhedron/Plugins/Tetrahedral_remeshing/CMakeLists.txt b/Polyhedron/demo/Polyhedron/Plugins/Tetrahedral_remeshing/CMakeLists.txt new file mode 100644 index 00000000000..638e8c0d660 --- /dev/null +++ b/Polyhedron/demo/Polyhedron/Plugins/Tetrahedral_remeshing/CMakeLists.txt @@ -0,0 +1,10 @@ +include( polyhedron_demo_macros ) + +remove_definitions(-DQT_STATICPLUGIN) + +qt5_wrap_cpp( VOLUME_MOC_OUTFILES ${CMAKE_CURRENT_SOURCE_DIR}/Volume_plane_thread.h ) +qt5_wrap_cpp( VOLUME_MOC_OUTFILES ${CMAKE_CURRENT_SOURCE_DIR}/Volume_plane_interface.h ) +#qt5_wrap_ui( meshingUI_FILES Meshing_dialog.ui Smoother_dialog.ui Local_optimizers_dialog.ui ) +polyhedron_demo_plugin(tetrahedral_remeshing_plugin Tetrahedral_remeshing_plugin KEYWORDS Tetrahedral_remeshing) +target_link_libraries(tetrahedral_remeshing_plugin + PUBLIC scene_c3t3_item ${OPENGL_gl_LIBRARY}) diff --git a/Polyhedron/demo/Polyhedron/Plugins/Tetrahedral_remeshing/Tetrahedral_remeshing_plugin.cpp b/Polyhedron/demo/Polyhedron/Plugins/Tetrahedral_remeshing/Tetrahedral_remeshing_plugin.cpp new file mode 100644 index 00000000000..d795e60dc15 --- /dev/null +++ b/Polyhedron/demo/Polyhedron/Plugins/Tetrahedral_remeshing/Tetrahedral_remeshing_plugin.cpp @@ -0,0 +1,212 @@ +#define CGAL_TETRAHEDRAL_REMESHING_VERBOSE + +#include + +#include + +#include "Scene_c3t3_item.h" +#include "C3t3_type.h" + +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +//#include "ui_Tetrahedral_remeshing_dialog.h" + +using namespace CGAL::Three; +class Polyhedron_demo_tetrahedral_remeshing_plugin : + public QObject, + public Polyhedron_demo_plugin_interface +{ + Q_OBJECT + Q_INTERFACES(CGAL::Three::Polyhedron_demo_plugin_interface) + Q_PLUGIN_METADATA(IID "com.geometryfactory.PolyhedronDemo.PluginInterface/1.0" FILE "tetrahedral_remeshing_plugin.json") + +public: + void init(QMainWindow* mainWindow, Scene_interface* scene_interface, Messages_interface*) + { + this->scene = scene_interface; + this->mw = mainWindow; + + actionTetrahedralRemeshing_ = new QAction("Tetrehedral Remeshing", mw); + if (actionTetrahedralRemeshing_) { + connect(actionTetrahedralRemeshing_, SIGNAL(triggered()), + this, SLOT(tetrahedral_remeshing())); + } + } + + QList actions() const { + return QList() << actionTetrahedralRemeshing_; + } + + bool applicable(QAction*) const + { + return qobject_cast(scene->item(scene->mainSelectionIndex())); + } + + +public Q_SLOTS: + void tetrahedral_remeshing() + { + const Scene_interface::Item_id index = scene->mainSelectionIndex(); + + Scene_c3t3_item* c3t3_item = + qobject_cast(scene->item(index)); + + if (c3t3_item) + { + // Create dialog box +// QDialog dialog(mw); +// Ui::Isotropic_remeshing_dialog ui +// = remeshing_dialog(&dialog, poly_item, selection_item); +// +// // Get values +// int i = dialog.exec(); +// if (i == QDialog::Rejected) +// { +// std::cout << "Remeshing aborted" << std::endl; +// return; +// } +// bool edges_only = ui.splitEdgesOnly_checkbox->isChecked(); +// bool preserve_duplicates = ui.preserveDuplicates_checkbox->isChecked(); +// double target_length = ui.edgeLength_dspinbox->value(); +// unsigned int nb_iter = ui.nbIterations_spinbox->value(); +// unsigned int nb_smooth = ui.nbSmoothing_spinbox->value(); +// bool protect = ui.protect_checkbox->isChecked(); +// bool smooth_features = ui.smooth1D_checkbox->isChecked(); + + bool ok; + double target_edge_length = QInputDialog::getDouble(mw, + tr("Tetrahedral remeshing"), + tr("target edge length = "), + 0.1, //value + 1e-10, //min + 2147483647,//max + 10,//decimals + &ok); + if (!ok) + { + std::cout << "Remeshing aborted" << std::endl; + return; + } + + // wait cursor + QApplication::setOverrideCursor(Qt::WaitCursor); + + QTime time; + time.start(); + + + Tr& tr = c3t3_item->c3t3().triangulation(); + + + CGAL::tetrahedral_adaptive_remeshing(tr, target_edge_length); + + std::cout << "ok (" << time.elapsed() << " ms)" << std::endl; + + c3t3_item->invalidateOpenGLBuffers(); + + Q_EMIT c3t3_item->itemChanged(); + + } + else + { + std::cout << "Can't remesh that type of thing" << std::endl; + } + + // default cursor + QApplication::restoreOverrideCursor(); + } + +private: + Scene_interface *scene; + QMainWindow* mw; + + //Ui::Isotropic_remeshing_dialog + //remeshing_dialog(QDialog* dialog, + // Scene_facegraph_item* poly_item, + // Scene_polyhedron_selection_item* selection_item = NULL) + //{ + // Ui::Isotropic_remeshing_dialog ui; + // ui.setupUi(dialog); + // connect(ui.buttonBox, SIGNAL(accepted()), dialog, SLOT(accept())); + // connect(ui.buttonBox, SIGNAL(rejected()), dialog, SLOT(reject())); + + // //connect checkbox to spinbox + // connect(ui.splitEdgesOnly_checkbox, SIGNAL(toggled(bool)), + // ui.nbIterations_spinbox, SLOT(setDisabled(bool))); + // connect(ui.splitEdgesOnly_checkbox, SIGNAL(toggled(bool)), + // ui.protect_checkbox, SLOT(setDisabled(bool))); + // connect(ui.protect_checkbox, SIGNAL(toggled(bool)), + // ui.smooth1D_checkbox, SLOT(setDisabled(bool))); + // connect(ui.splitEdgesOnly_checkbox, SIGNAL(toggled(bool)), + // ui.smooth1D_checkbox, SLOT(setDisabled(bool))); + // connect(ui.preserveDuplicates_checkbox, SIGNAL(toggled(bool)), + // ui.protect_checkbox, SLOT(setChecked(bool))); + // connect(ui.preserveDuplicates_checkbox, SIGNAL(toggled(bool)), + // ui.protect_checkbox, SLOT(setDisabled(bool))); + + // //Set default parameters + // Scene_interface::Bbox bbox = poly_item != NULL ? poly_item->bbox() + // : (selection_item != NULL ? selection_item->bbox() + // : scene->bbox()); + // ui.objectName->setText(poly_item != NULL ? poly_item->name() + // : (selection_item != NULL ? selection_item->name() + // : QString("Remeshing parameters"))); + + // ui.objectNameSize->setText( + // tr("Object bbox size (w,h,d): %1, %2, %3") + // .arg(bbox.xmax()-bbox.xmin(), 0, 'g', 3) + // .arg(bbox.ymax()-bbox.ymin(), 0, 'g', 3) + // .arg(bbox.zmax()-bbox.zmin(), 0, 'g', 3)); + + // double diago_length = CGAL::sqrt((bbox.xmax()-bbox.xmin())*(bbox.xmax()-bbox.xmin()) + // + (bbox.ymax()-bbox.ymin())*(bbox.ymax()-bbox.ymin()) + // + (bbox.zmax()-bbox.zmin())*(bbox.zmax()-bbox.zmin())); + // double log = std::log10(diago_length); + // unsigned int nb_decimals = (log > 0) ? 5 : (std::ceil(-log)+3); + + // ui.edgeLength_dspinbox->setDecimals(nb_decimals); + // ui.edgeLength_dspinbox->setSingleStep(1e-3); + // ui.edgeLength_dspinbox->setRange(1e-6 * diago_length, //min + // 2. * diago_length);//max + // ui.edgeLength_dspinbox->setValue(0.05 * diago_length); + + // std::ostringstream oss; + // oss << "Diagonal length of the Bbox of the selection to remesh is "; + // oss << diago_length << "." << std::endl; + // oss << "Default is 5% of it" << std::endl; + // ui.edgeLength_dspinbox->setToolTip(QString::fromStdString(oss.str())); + + // ui.nbIterations_spinbox->setSingleStep(1); + // ui.nbIterations_spinbox->setRange(1/*min*/, 1000/*max*/); + // ui.nbIterations_spinbox->setValue(1); + + // ui.protect_checkbox->setChecked(false); + // ui.smooth1D_checkbox->setChecked(true); + + // if (NULL != selection_item) + // { + // //do not preserve duplicates in selection mode + // ui.preserveDuplicates_checkbox->setDisabled(true); + // ui.preserveDuplicates_checkbox->setChecked(false); + // } + + // return ui; + //} + + +private: + QAction* actionTetrahedralRemeshing_; + +}; // end Polyhedron_demo_isotropic_remeshing_plugin + +#include "Tetrahedral_remeshing_plugin.moc" From 3940dd69ebe22f122343bc89f6fc70be848b43da Mon Sep 17 00:00:00 2001 From: Jane Tournois Date: Tue, 17 Sep 2019 15:13:30 +0200 Subject: [PATCH 012/568] Revert "replace Point type to make it valid for non-weighted triangulations" This reverts commit 74b12712faae74bf25fdec749049ecb13c517529. --- Mesh_3/include/CGAL/IO/File_medit.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Mesh_3/include/CGAL/IO/File_medit.h b/Mesh_3/include/CGAL/IO/File_medit.h index 6b4dfb092c3..6c3f2ced314 100644 --- a/Mesh_3/include/CGAL/IO/File_medit.h +++ b/Mesh_3/include/CGAL/IO/File_medit.h @@ -754,7 +754,7 @@ output_to_medit(std::ostream& os, typedef typename Tr::Finite_vertices_iterator Finite_vertices_iterator; typedef typename Tr::Vertex_handle Vertex_handle; - typedef typename Tr::Tds::Vertex::Point Point; + typedef typename Tr::Point Point; //can be weighted or not const Tr& tr = c3t3.triangulation(); From 1de540325dabc0fb05cdb5b43c89f0632b14dad8 Mon Sep 17 00:00:00 2001 From: Jane Tournois Date: Tue, 17 Sep 2019 15:43:06 +0200 Subject: [PATCH 013/568] fix typo and do not use Tr& --- .../Tetrahedral_remeshing_plugin.cpp | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/Polyhedron/demo/Polyhedron/Plugins/Tetrahedral_remeshing/Tetrahedral_remeshing_plugin.cpp b/Polyhedron/demo/Polyhedron/Plugins/Tetrahedral_remeshing/Tetrahedral_remeshing_plugin.cpp index d795e60dc15..773eafd087a 100644 --- a/Polyhedron/demo/Polyhedron/Plugins/Tetrahedral_remeshing/Tetrahedral_remeshing_plugin.cpp +++ b/Polyhedron/demo/Polyhedron/Plugins/Tetrahedral_remeshing/Tetrahedral_remeshing_plugin.cpp @@ -36,7 +36,7 @@ public: this->scene = scene_interface; this->mw = mainWindow; - actionTetrahedralRemeshing_ = new QAction("Tetrehedral Remeshing", mw); + actionTetrahedralRemeshing_ = new QAction("Tetrahedral Remeshing", mw); if (actionTetrahedralRemeshing_) { connect(actionTetrahedralRemeshing_, SIGNAL(triggered()), this, SLOT(tetrahedral_remeshing())); @@ -104,11 +104,7 @@ public Q_SLOTS: QTime time; time.start(); - - Tr& tr = c3t3_item->c3t3().triangulation(); - - - CGAL::tetrahedral_adaptive_remeshing(tr, target_edge_length); + CGAL::tetrahedral_adaptive_remeshing(c3t3_item->c3t3().triangulation(), target_edge_length); std::cout << "ok (" << time.elapsed() << " ms)" << std::endl; From ebb4a9982243a360bfba7c63469e8889ffca60af Mon Sep 17 00:00:00 2001 From: Jane Tournois Date: Thu, 19 Sep 2019 16:52:16 +0200 Subject: [PATCH 014/568] towards the use of remeshing with any input triangulation with subdomain_index --- .../Tetrahedral_remeshing/CMakeLists.txt | 4 +-- .../Remeshing_triangulation_3.h | 29 +++++++++++++++++-- .../internal/add_imaginary_layer.h | 2 +- .../tetrahedral_adaptive_remeshing_impl.h | 16 +++++----- 4 files changed, 37 insertions(+), 14 deletions(-) diff --git a/Tetrahedral_remeshing/examples/Tetrahedral_remeshing/CMakeLists.txt b/Tetrahedral_remeshing/examples/Tetrahedral_remeshing/CMakeLists.txt index 6f2cf7e1a12..de476499215 100644 --- a/Tetrahedral_remeshing/examples/Tetrahedral_remeshing/CMakeLists.txt +++ b/Tetrahedral_remeshing/examples/Tetrahedral_remeshing/CMakeLists.txt @@ -26,8 +26,8 @@ endif() # Creating entries for all C++ files with "main" routine # ########################################################## create_single_source_cgal_program( "tetrahedral_remeshing_example.cpp" ) - create_single_source_cgal_program( "tetrahedral_remeshing_with_features.cpp") - create_single_source_cgal_program( "tetrahedral_remeshing_of_one_subdomain.cpp") +# create_single_source_cgal_program( "tetrahedral_remeshing_with_features.cpp") + # create_single_source_cgal_program( "tetrahedral_remeshing_of_one_subdomain.cpp") create_single_source_cgal_program( "generate_input.cpp ") create_single_source_cgal_program( "test_mesh_loader.cpp ") diff --git a/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/Remeshing_triangulation_3.h b/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/Remeshing_triangulation_3.h index 4b7e97b845d..e781e8502ff 100644 --- a/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/Remeshing_triangulation_3.h +++ b/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/Remeshing_triangulation_3.h @@ -73,8 +73,10 @@ namespace Tetrahedral_remeshing typename TDS_tgt::Vertex::Point>::Kernel GT_tgt; CGAL::Cartesian_converter conv; + typedef typename TDS_tgt::Vertex::Point Tgt_point; + typename TDS_tgt::Vertex v_tgt; - v_tgt.set_point(conv(v_src.point())); + v_tgt.set_point(Tgt_point(conv(point(v_src.point())))); v_tgt.set_time_stamp(-1); v_tgt.set_dimension(3);//-1 if unset, 0,1,2, or 3 if set return v_tgt; @@ -89,7 +91,9 @@ namespace Tetrahedral_remeshing typename TDS_tgt::Vertex::Point>::Kernel GT_tgt; CGAL::Cartesian_converter conv; - v_tgt.set_point(conv(v_src.point())); + typedef typename TDS_tgt::Vertex::Point Tgt_point; + + v_tgt.set_point(Tgt_point(conv(point(v_src.point())))); v_tgt.set_dimension(3);//v_src.info()); } }; @@ -101,6 +105,7 @@ namespace Tetrahedral_remeshing typename TDS_tgt::Cell operator()(const typename TDS_src::Cell& c_src) const { typename TDS_tgt::Cell c_tgt; + c_tgt.set_subdomain_index(c_src.subdomain_index()); // c_tgt.info() = c_src.info(); c_tgt.set_time_stamp(-1); return c_tgt; @@ -109,7 +114,8 @@ namespace Tetrahedral_remeshing void operator()(const typename TDS_src::Cell& c_src, typename TDS_tgt::Cell& c_tgt) const { -// c_tgt.info() = c_src.info(); + c_tgt.set_subdomain_index(c_src.subdomain_index()); + // c_tgt.info() = c_src.info(); } }; @@ -132,6 +138,23 @@ namespace Tetrahedral_remeshing internal::Cell_converter())); } + template + void build_from_remeshing_triangulation( + const Remeshing_triangulation_3& remeshing_tr, + T3& tr) + { + typedef typename T3::Triangulation_data_structure Tds; + typedef Remeshing_triangulation_3::Tds RTds; + + tr.clear(); + + tr.set_infinite_vertex( + tr.tds().copy_tds( + remeshing_tr.tds(), + remeshing_tr.infinite_vertex(), + internal::Vertex_converter(), + internal::Cell_converter())); + } }//end namespace Tetrahedral_remeshing }//end namespace CGAL diff --git a/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/add_imaginary_layer.h b/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/add_imaginary_layer.h index 6100b1a7fa3..c35861d2752 100644 --- a/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/add_imaginary_layer.h +++ b/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/add_imaginary_layer.h @@ -217,7 +217,7 @@ namespace internal compute_normals_on_convex_hull(tr, normals); //compute bbox max size - const double& offset = 0.04 * compute_bbox_max_size(tr); + const double offset = 0.04 * compute_bbox_max_size(tr); //compute points to be inserted std::vector offset_points; diff --git a/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/tetrahedral_adaptive_remeshing_impl.h b/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/tetrahedral_adaptive_remeshing_impl.h index 9f091e40a94..4956841584f 100644 --- a/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/tetrahedral_adaptive_remeshing_impl.h +++ b/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/tetrahedral_adaptive_remeshing_impl.h @@ -51,16 +51,13 @@ namespace internal struct All_cells_selected { typedef typename Tr::Cell_handle argument_type; - typedef bool result_type; - result_type operator()(const argument_type) const - { - return true; - } - typedef typename Tr::Cell::Subdomain_index Subdomain_index; - Subdomain_index subdomain_index(const argument_type c) const + + typedef bool result_type; + + result_type operator()(const argument_type c) const { - return Subdomain_index(1); + return c->subdomain_index() != Subdomain_index(); } }; @@ -321,6 +318,9 @@ namespace internal } } m_imaginary_index = max_si + 1; + if(m_imaginary_index == 1) + std::cerr << "Warning : Maximal subdomain index is 0" << std::endl + << " Remeshing is likely to fail." << std::endl; //tag facets typedef typename Tr::Facet Facet; From 0fb3a44d2ed7b148ae686cbf3712bf54d6407b9f Mon Sep 17 00:00:00 2001 From: Jane Tournois Date: Thu, 19 Sep 2019 17:03:47 +0200 Subject: [PATCH 015/568] remeshing plugin should use Remeshing_triangulation using Mesh_triangulation_3 (which is an enriched Regular_triangulation_3) compiles, but the calls of tr.is_valid() fail since the triangulation is not regular anymore after remeshing we reconvert it back to the demo c3t3 triangulation type anyhow, to be able to display it, hoping that is_valid() will not be called later on --- .../Tetrahedral_remeshing_plugin.cpp | 19 +++++++++++++++++-- .../include/CGAL/tetrahedral_remeshing.h | 8 ++++++++ 2 files changed, 25 insertions(+), 2 deletions(-) diff --git a/Polyhedron/demo/Polyhedron/Plugins/Tetrahedral_remeshing/Tetrahedral_remeshing_plugin.cpp b/Polyhedron/demo/Polyhedron/Plugins/Tetrahedral_remeshing/Tetrahedral_remeshing_plugin.cpp index 773eafd087a..0639080cab6 100644 --- a/Polyhedron/demo/Polyhedron/Plugins/Tetrahedral_remeshing/Tetrahedral_remeshing_plugin.cpp +++ b/Polyhedron/demo/Polyhedron/Plugins/Tetrahedral_remeshing/Tetrahedral_remeshing_plugin.cpp @@ -1,4 +1,5 @@ #define CGAL_TETRAHEDRAL_REMESHING_VERBOSE +#define CGAL_DUMP_REMESHING_STEPS #include @@ -21,6 +22,7 @@ //#include "ui_Tetrahedral_remeshing_dialog.h" + using namespace CGAL::Three; class Polyhedron_demo_tetrahedral_remeshing_plugin : public QObject, @@ -56,6 +58,8 @@ public: public Q_SLOTS: void tetrahedral_remeshing() { + typedef CGAL::Tetrahedral_remeshing::Remeshing_triangulation_3 Remeshing_triangulation; + const Scene_interface::Item_id index = scene->mainSelectionIndex(); Scene_c3t3_item* c3t3_item = @@ -83,6 +87,7 @@ public Q_SLOTS: // bool protect = ui.protect_checkbox->isChecked(); // bool smooth_features = ui.smooth1D_checkbox->isChecked(); + bool ok; double target_edge_length = QInputDialog::getDouble(mw, tr("Tetrahedral remeshing"), @@ -104,10 +109,20 @@ public Q_SLOTS: QTime time; time.start(); - CGAL::tetrahedral_adaptive_remeshing(c3t3_item->c3t3().triangulation(), target_edge_length); + Remeshing_triangulation tr; + CGAL::Tetrahedral_remeshing::build_remeshing_triangulation(c3t3_item->c3t3().triangulation(), tr); - std::cout << "ok (" << time.elapsed() << " ms)" << std::endl; + std::cout << "Remeshing triangulation built (" << time.elapsed() << " ms)" << std::endl; + time.restart(); + CGAL::tetrahedral_adaptive_remeshing(tr, target_edge_length); + + std::cout << "Remeshing done (" << time.elapsed() << " ms)" << std::endl; + time.restart(); + + CGAL::Tetrahedral_remeshing::build_from_remeshing_triangulation(tr, c3t3_item->c3t3().triangulation()); + + std::cout << "Back conversion done (" << time.elapsed() << " ms)" << std::endl; c3t3_item->invalidateOpenGLBuffers(); Q_EMIT c3t3_item->itemChanged(); diff --git a/Tetrahedral_remeshing/include/CGAL/tetrahedral_remeshing.h b/Tetrahedral_remeshing/include/CGAL/tetrahedral_remeshing.h index b9077311888..566411a88df 100644 --- a/Tetrahedral_remeshing/include/CGAL/tetrahedral_remeshing.h +++ b/Tetrahedral_remeshing/include/CGAL/tetrahedral_remeshing.h @@ -84,6 +84,8 @@ namespace CGAL const double& target_edge_length, const NamedParameters& np) { + CGAL_assertion(tr.is_valid(true)); + typedef Triangulation Tr; typedef typename Tr::Edge Edge; @@ -116,6 +118,11 @@ namespace CGAL ECMap ecmap = choose_param(get_param(np, internal_np::edge_is_constrained) , No_constraint()); +#ifdef CGAL_TETRAHEDRAL_REMESHING_VERBOSE + std::cout << "Init tetrahedral remeshing..."; + std::cout.flush(); +#endif + typedef Tetrahedral_remeshing::internal::Adaptive_remesher< Tr, ECMap, SelectionFunctor> Remesher; Remesher remesher(tr, target_edge_length, protect, ecmap @@ -123,6 +130,7 @@ namespace CGAL /*, adaptive*/); #ifdef CGAL_TETRAHEDRAL_REMESHING_VERBOSE + std::cout << "done." << std::endl; Tetrahedral_remeshing::internal::compute_statistics( remesher.triangulation(), remesher.imaginary_index(), cell_select, "statistics_begin.txt"); From 5c0b40f59155575840405627224c437f9773e43e Mon Sep 17 00:00:00 2001 From: Jane Tournois Date: Fri, 20 Sep 2019 14:37:45 +0200 Subject: [PATCH 016/568] remove imaginary cells from the complex once remeshing is done --- .../internal/tetrahedral_adaptive_remeshing_impl.h | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/tetrahedral_adaptive_remeshing_impl.h b/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/tetrahedral_adaptive_remeshing_impl.h index 4956841584f..b82b590212b 100644 --- a/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/tetrahedral_adaptive_remeshing_impl.h +++ b/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/tetrahedral_adaptive_remeshing_impl.h @@ -255,7 +255,16 @@ namespace internal std::cout << "Postprocess..."; std::cout.flush(); #endif - ///TODO + //unset imaginary cells + typedef typename Tr::Finite_cells_iterator Finite_cells_iterator; + for (Finite_cells_iterator cit = tr().finite_cells_begin(); + cit != tr().finite_cells_end(); ++cit) + { + if (cit->subdomain_index() == m_imaginary_index) + { + m_c3t3.remove_from_complex(cit); + } + } CGAL_assertion(tr().is_valid(true)); #ifdef CGAL_DUMP_REMESHING_STEPS From 447a69e934d4e15ced17729af498af10a31c405c Mon Sep 17 00:00:00 2001 From: Jane Tournois Date: Fri, 20 Sep 2019 15:20:53 +0200 Subject: [PATCH 017/568] update c3t3 after remeshing in the demo --- .../Tetrahedral_remeshing_plugin.cpp | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/Polyhedron/demo/Polyhedron/Plugins/Tetrahedral_remeshing/Tetrahedral_remeshing_plugin.cpp b/Polyhedron/demo/Polyhedron/Plugins/Tetrahedral_remeshing/Tetrahedral_remeshing_plugin.cpp index 0639080cab6..c786f2443f4 100644 --- a/Polyhedron/demo/Polyhedron/Plugins/Tetrahedral_remeshing/Tetrahedral_remeshing_plugin.cpp +++ b/Polyhedron/demo/Polyhedron/Plugins/Tetrahedral_remeshing/Tetrahedral_remeshing_plugin.cpp @@ -123,18 +123,19 @@ public Q_SLOTS: CGAL::Tetrahedral_remeshing::build_from_remeshing_triangulation(tr, c3t3_item->c3t3().triangulation()); std::cout << "Back conversion done (" << time.elapsed() << " ms)" << std::endl; - c3t3_item->invalidateOpenGLBuffers(); - Q_EMIT c3t3_item->itemChanged(); + c3t3_item->c3t3_changed(); + c3t3_item->update_histogram(); + const Scene_interface::Item_id index = scene->mainSelectionIndex(); + this->scene->itemChanged(index); + // default cursor + QApplication::restoreOverrideCursor(); } else { std::cout << "Can't remesh that type of thing" << std::endl; } - - // default cursor - QApplication::restoreOverrideCursor(); } private: From d2466b9feeb065e0c81aaf3c5751a93b54ce4dba Mon Sep 17 00:00:00 2001 From: Jane Tournois Date: Thu, 26 Sep 2019 11:31:55 +0200 Subject: [PATCH 018/568] start cleaning Corner_index and Curve_segment_index are int by default in C3t3 --- .../tetrahedral_adaptive_remeshing_impl.h | 37 +++++++++---------- 1 file changed, 17 insertions(+), 20 deletions(-) diff --git a/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/tetrahedral_adaptive_remeshing_impl.h b/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/tetrahedral_adaptive_remeshing_impl.h index b82b590212b..0cdafd31e83 100644 --- a/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/tetrahedral_adaptive_remeshing_impl.h +++ b/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/tetrahedral_adaptive_remeshing_impl.h @@ -85,15 +85,12 @@ namespace internal typedef Triangulation Tr; typedef typename Tr::Geom_traits::FT FT; - typedef int Corner_index; - typedef int Curve_segment_index; - typedef typename CGAL::Mesh_complex_3_in_triangulation_3 C3t3; + typedef typename CGAL::Mesh_complex_3_in_triangulation_3 C3t3; typedef typename C3t3::Cell_handle Cell_handle; typedef typename C3t3::Vertex_handle Vertex_handle; - typedef typename int Surface_patch_index; //only needed for is_in_complex() typedef typename C3t3::Subdomain_index Subdomain_index; + typedef int Surface_patch_index; //only needed for is_in_complex() private: const FT& m_target_edge_length; @@ -303,7 +300,7 @@ namespace internal std::size_t nbv = 0; #endif - Subdomain_index max_si = tr().finite_cells_begin()->subdomain_index(); + Subdomain_index max_si = 0; //tag cells (no imaginary cell yet) typedef typename Tr::Finite_cells_iterator Finite_cells_iterator; @@ -319,7 +316,6 @@ namespace internal ++nbc; #endif } - for (int i = 0; i < 4; ++i) { if (cit->vertex(i)->in_dimension() == -1) @@ -327,7 +323,7 @@ namespace internal } } m_imaginary_index = max_si + 1; - if(m_imaginary_index == 1) + if(max_si == 0) std::cerr << "Warning : Maximal subdomain index is 0" << std::endl << " Remeshing is likely to fail." << std::endl; @@ -344,13 +340,8 @@ namespace internal Subdomain_index s2 = mf.first->subdomain_index(); if (s1 != s2) { - if(s1 < s2) - m_c3t3.add_to_complex(f, 1); - else - m_c3t3.add_to_complex(f, 1); -#ifdef CGAL_TETRAHEDRAL_REMESHING_DEBUG - ++nbf; -#endif + m_c3t3.add_to_complex(f, 1); + const int i = f.second; for (int j = 0; j < 3; ++j) { @@ -358,6 +349,9 @@ namespace internal if (vij->in_dimension() == -1 || vij->in_dimension() > 2) vij->set_dimension(2); } +#ifdef CGAL_TETRAHEDRAL_REMESHING_DEBUG + ++nbf; +#endif } } #ifdef CGAL_TETRAHEDRAL_REMESHING_DEBUG @@ -375,9 +369,7 @@ namespace internal if (get(ecmap, e) || nb_incident_subdomains(e, m_c3t3) > 2) { m_c3t3.add_to_complex(e, 1); -#ifdef CGAL_TETRAHEDRAL_REMESHING_DEBUG - ++nbe; -#endif + Vertex_handle v = e.first->vertex(e.second); if(v->in_dimension() == -1 || v->in_dimension() > 1) v->set_dimension(1); @@ -385,6 +377,9 @@ namespace internal v = e.first->vertex(e.third); if (v->in_dimension() == -1 || v->in_dimension() > 1) v->set_dimension(1); +#ifdef CGAL_TETRAHEDRAL_REMESHING_DEBUG + ++nbe; +#endif } } #ifdef CGAL_TETRAHEDRAL_REMESHING_DEBUG @@ -401,11 +396,13 @@ namespace internal if (vit->in_dimension() == 0 || nb_incident_complex_edges(vit, m_c3t3) > 2) { m_c3t3.add_to_complex(vit, ++corner_id); + + if (vit->in_dimension() == -1 || vit->in_dimension() > 0) + vit->set_dimension(0); + #ifdef CGAL_TETRAHEDRAL_REMESHING_DEBUG ++nbv; #endif - if (vit->in_dimension() == -1 || vit->in_dimension() > 0) - vit->set_dimension(0); } } From f40210d858c6b8f416cb68329bc607dff8245cf4 Mon Sep 17 00:00:00 2001 From: Jane Tournois Date: Thu, 26 Sep 2019 11:43:09 +0200 Subject: [PATCH 019/568] clean split() --- .../CGAL/Tetrahedral_remeshing/internal/split_long_edges.h | 3 ++- .../internal/tetrahedral_adaptive_remeshing_impl.h | 2 +- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/split_long_edges.h b/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/split_long_edges.h index a04736e74b2..3f0324f991b 100644 --- a/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/split_long_edges.h +++ b/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/split_long_edges.h @@ -250,7 +250,8 @@ namespace internal std::cout << "\rSplit (" << high << ")... (" << long_edges.left.size() << " long edges, " << "length = " << std::sqrt(sqlen) << ", " - << std::sqrt(CGAL::squared_distance(e.first->point(), e.second->point())) << ", " + << std::sqrt(CGAL::squared_distance(point(e.first->point()), + point(e.second->point()))) << ", " << nb_splits << " splits)"; std::cout.flush(); #endif diff --git a/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/tetrahedral_adaptive_remeshing_impl.h b/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/tetrahedral_adaptive_remeshing_impl.h index 0cdafd31e83..f5112a1fb59 100644 --- a/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/tetrahedral_adaptive_remeshing_impl.h +++ b/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/tetrahedral_adaptive_remeshing_impl.h @@ -154,7 +154,7 @@ namespace internal { CGAL_assertion(check_vertex_dimensions()); - FT emax = FT(4)/FT(3) * m_target_edge_length; + const FT emax = FT(4)/FT(3) * m_target_edge_length; split_long_edges(m_c3t3, emax, m_protect_boundaries, m_imaginary_index, m_cell_selector); From e4ee1e39267332c86a7687aa9e29b9b5d2c04c6c Mon Sep 17 00:00:00 2001 From: Jane Tournois Date: Thu, 26 Sep 2019 13:32:56 +0200 Subject: [PATCH 020/568] clean preprocess() point types --- .../internal/add_imaginary_layer.h | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/add_imaginary_layer.h b/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/add_imaginary_layer.h index c35861d2752..59c796333cd 100644 --- a/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/add_imaginary_layer.h +++ b/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/add_imaginary_layer.h @@ -206,11 +206,9 @@ namespace internal template void add_layer_of_imaginary_tets(T3& tr, const Index& imaginary_index) { - typedef typename T3::Geom_traits Gt; - typedef typename Gt::Point_3 Point_3; - typedef typename Gt::Vector_3 Vector_3; - - typedef typename T3::Vertex_handle Vertex_handle; + typedef typename T3::Vertex_handle Vertex_handle; + typedef typename T3::Point Point; + typedef typename T3::Geom_traits::Vector_3 Vector_3; //compute normals boost::unordered_map normals; @@ -220,7 +218,7 @@ namespace internal const double offset = 0.04 * compute_bbox_max_size(tr); //compute points to be inserted - std::vector offset_points; + std::vector offset_points; compute_offset_points(normals, offset, std::back_inserter(offset_points)); From 5a4b1a0d9becb8e08625ba5ad83cf8bea7bb8b38 Mon Sep 17 00:00:00 2001 From: Jane Tournois Date: Thu, 26 Sep 2019 14:48:29 +0200 Subject: [PATCH 021/568] clean typedefs and point types --- .../internal/collapse_short_edges.h | 65 +++++++++---------- 1 file changed, 31 insertions(+), 34 deletions(-) diff --git a/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/collapse_short_edges.h b/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/collapse_short_edges.h index 045bf15e821..cbb2a94d079 100644 --- a/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/collapse_short_edges.h +++ b/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/collapse_short_edges.h @@ -53,12 +53,12 @@ namespace internal template class CollapseTriangulation { - typedef typename C3t3::Triangulation Tr; - typedef typename C3t3::Edge Edge; - typedef typename C3t3::Cell_handle Cell_handle; - typedef typename C3t3::Vertex_handle Vertex_handle; - typedef typename C3t3::Subdomain_index Subdomain_index; - typedef typename C3t3::Triangulation::Point Point_3; + typedef typename C3t3::Triangulation Tr; + typedef typename C3t3::Edge Edge; + typedef typename C3t3::Cell_handle Cell_handle; + typedef typename C3t3::Vertex_handle Vertex_handle; + typedef typename C3t3::Subdomain_index Subdomain_index; + typedef typename C3t3::Triangulation::Point Point_3; typedef typename C3t3::Triangulation::Geom_traits::Vector_3 Vector_3; typedef CGAL::Triangulation_incremental_builder_3 Builder; @@ -85,9 +85,8 @@ namespace internal collapse_type = _collapse_type; //To add the vertices only once - for (unsigned int i = 0; i < vertices_to_insert.size(); i++) + for (Vertex_handle vh : vertices_to_insert) { - const Vertex_handle vh = vertices_to_insert[i]; if (v2v.left.find(vh) == v2v.left.end()) { Vertex_handle new_vh = builder.add_vertex(); @@ -103,9 +102,8 @@ namespace internal c3t3.triangulation().finite_incident_cells(v1_init, std::back_inserter(cells_to_insert)); //To add the cells only once - for (unsigned int i = 0; i < cells_to_insert.size(); i++) + for (Cell_handle ch : cells_to_insert) { - const Cell_handle ch = cells_to_insert[i]; if (c2c.left.find(ch) == c2c.left.end()) { Cell_handle new_ch = builder.add_cell(v2v.left.at(ch->vertex(0)), v2v.left.at(ch->vertex(1)), @@ -483,9 +481,9 @@ namespace internal const typename C3t3::Subdomain_index& /*imaginary_index*/, CellSelector cell_selector) { - typedef typename C3t3::Vertex_handle Vertex_handle; - typedef typename C3t3::Cell_handle Cell_handle; - typedef typename C3t3::Triangulation::Geom_traits::Point_3 Point; + typedef typename C3t3::Vertex_handle Vertex_handle; + typedef typename C3t3::Cell_handle Cell_handle; + typedef typename C3t3::Triangulation::Point Point; Vertex_handle v0 = edge.first->vertex(edge.second); Vertex_handle v1 = edge.first->vertex(edge.third); @@ -519,12 +517,13 @@ namespace internal if (!ch->has_vertex(v1)) { //check orientation - boost::array pts = { point(ch->vertex(0)->point()), - point(ch->vertex(1)->point()), - point(ch->vertex(2)->point()), - point(ch->vertex(3)->point())}; - pts[ch->index(v0)] = point(new_pos); - if (CGAL::orientation(pts[0], pts[1], pts[2], pts[3]) != CGAL::POSITIVE) + boost::array pts = { ch->vertex(0)->point(), + ch->vertex(1)->point(), + ch->vertex(2)->point(), + ch->vertex(3)->point()}; + pts[ch->index(v0)] = new_pos; + if (CGAL::orientation(point(pts[0]), point(pts[1]), + point(pts[2]), point(pts[3])) != CGAL::POSITIVE) return false; } } @@ -541,12 +540,14 @@ namespace internal if (!ch->has_vertex(v0)) { //check orientation - boost::array pts = { point(ch->vertex(0)->point()), - point(ch->vertex(1)->point()), - point(ch->vertex(2)->point()), - point(ch->vertex(3)->point()) }; - pts[ch->index(v1)] = point(new_pos); - if (CGAL::orientation(pts[0], pts[1], pts[2], pts[3]) != CGAL::POSITIVE) + //check orientation + boost::array pts = { ch->vertex(0)->point(), + ch->vertex(1)->point(), + ch->vertex(2)->point(), + ch->vertex(3)->point() }; + pts[ch->index(v1)] = new_pos; + if (CGAL::orientation(point(pts[0]), point(pts[1]), + point(pts[2]), point(pts[3])) != CGAL::POSITIVE) return false; } } @@ -568,8 +569,9 @@ namespace internal { //SqLengthMap::key_type is Vertex_handle //SqLengthMap::value_type is double - typedef typename C3t3::Edge Edge; - typedef typename C3t3::Vertex_handle Vertex_handle; + typedef typename C3t3::Triangulation::Geom_traits::FT FT; + typedef typename C3t3::Edge Edge; + typedef typename C3t3::Vertex_handle Vertex_handle; std::vector inc_edges; c3t3.triangulation().finite_incident_edges(v1, @@ -588,7 +590,7 @@ namespace internal if (v2 != ivh && edges_sqlength.find(ivh) == edges_sqlength.end()) { - double sqlen_i = CGAL::squared_distance(new_pos, ivh->point()); + FT sqlen_i = CGAL::squared_distance(new_pos, ivh->point()); //if (adaptive){ // if (is_boundary_edge(ei) || is_hull_edge(ei)){ @@ -892,11 +894,6 @@ namespace internal const typename C3T3::Subdomain_index& imaginary_index, CellSelector cell_selector) { -#ifdef CGAL_LIMITED_APERTURE_EDGE_SELECTION - if (CGAL::helpers::is_on_the_outer_box(e, c3t3, imaginary_index)) - return true; -#endif - if (is_outside(e, c3t3, imaginary_index, cell_selector)) return false; if (is_imaginary(e, c3t3, imaginary_index)) @@ -963,7 +960,7 @@ namespace internal for (Finite_edges_iterator eit = tr.finite_edges_begin(); eit != tr.finite_edges_end(); ++eit) { - Edge e = *eit; + const Edge& e = *eit; if (!can_be_collapsed(e, c3t3, protect_boundaries, imaginary_index, cell_selector)) continue; From 3ac4d6d4a645472cb830b4e61cc32707399e769c Mon Sep 17 00:00:00 2001 From: Jane Tournois Date: Mon, 30 Sep 2019 16:46:34 +0200 Subject: [PATCH 022/568] minor cleaning and commenting --- .../internal/flip_edges.h | 22 +- .../internal/smooth_vertices.h | 782 +++++++++--------- 2 files changed, 400 insertions(+), 404 deletions(-) diff --git a/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/flip_edges.h b/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/flip_edges.h index f2b72e8fba2..b81c011d01c 100644 --- a/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/flip_edges.h +++ b/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/flip_edges.h @@ -40,11 +40,11 @@ namespace internal enum Flip_Criterion{ MIN_ANGLE_BASED, AVERAGE_ANGLE_BASED, VALENCE_BASED, VALENCE_MIN_DH_BASED }; - template - void flip_inside_edges(std::vector&) - { - //TODO - } + //template + //void flip_inside_edges(std::vector&) + //{ + // //TODO + //} template Sliver_removal_result flip_3_to_2(typename C3t3::Edge& edge, @@ -1112,7 +1112,7 @@ namespace internal std::size_t nb_flips = 0; #endif - const Flip_Criterion criterion = VALENCE_MIN_DH_BASED; + //const Flip_Criterion criterion = VALENCE_MIN_DH_BASED; //collect long edges @@ -1145,15 +1145,15 @@ namespace internal cell_selector, std::back_inserter(inside_edges)); - if (criterion == VALENCE_BASED) - flip_inside_edges(inside_edges); - else - { + //if (criterion == VALENCE_BASED) + // flip_inside_edges(inside_edges); + //else + //{ #ifdef CGAL_TETRAHEDRAL_REMESHING_VERBOSE nb_flips = #endif flip_all_edges(inside_edges, c3t3, MIN_ANGLE_BASED); - } + //} #ifdef CGAL_TETRAHEDRAL_REMESHING_VERBOSE std::cout << " done (" << nb_flips << " flips)." << std::endl; diff --git a/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/smooth_vertices.h b/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/smooth_vertices.h index 4621c77a88b..846023a963d 100644 --- a/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/smooth_vertices.h +++ b/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/smooth_vertices.h @@ -289,15 +289,12 @@ namespace internal typedef typename C3T3::Vertex_handle Vertex_handle; typedef typename C3T3::Cell_handle Cell_handle; typedef typename Tr::Finite_vertices_iterator Finite_vertices_iterator; - - typedef typename Tr::Geom_traits Gt; - typedef typename Gt::Point_3 Point_3; - typedef typename Gt::Vector_3 Vector_3; + typedef typename C3T3::Point Point; + typedef typename Tr::Geom_traits::Vector_3 Vector_3; #ifdef CGAL_TETRAHEDRAL_REMESHING_VERBOSE std::cout << "Smooth vertices..."; std::cout.flush(); - std::size_t nb_done = 0; CGAL_USE(nb_done); #endif Tr& tr = c3t3.triangulation(); @@ -309,7 +306,6 @@ namespace internal const std::size_t nbv = tr.number_of_vertices(); boost::unordered_map vertex_id; std::vector smoothing_vecs(nbv, CGAL::NULL_VECTOR); -// std::vector neighbors(nbv, -1); // generate ids for vertices std::size_t id = 0; @@ -368,7 +364,7 @@ namespace internal vit != tr.finite_vertices_end(); ++vit) { const std::size_t& vid = vertex_id.at(vit); - const Point_3 new_pos = CGAL::ORIGIN + smoothing_vecs[vid]; + const Point new_pos(CGAL::ORIGIN + smoothing_vecs[vid]); const Vector_3 move(point(vit->point()), new_pos); std::vector cells; @@ -387,393 +383,393 @@ namespace internal #endif } - template - void smooth_vertices(C3T3& c3t3, - const typename C3T3::Subdomain_index&, - const bool protect_boundaries, - CellSelector cell_selector) - { - typedef typename C3T3::Surface_patch_index Surface_patch_index; - typedef typename C3T3::Subdomain_index Subdomain_index; - typedef typename C3T3::Triangulation Tr; - typedef typename C3T3::Vertex_handle Vertex_handle; - typedef typename C3T3::Cell_handle Cell_handle; - typedef typename Tr::Finite_vertices_iterator Finite_vertices_iterator; - typedef typename Tr::Finite_edges_iterator Finite_edges_iterator; - - typedef typename Tr::Geom_traits Gt; - typedef typename Gt::Point_3 Point_3; - typedef typename Gt::Vector_3 Vector_3; - typedef typename Gt::FT FT; - -#ifdef CGAL_TETRAHEDRAL_REMESHING_VERBOSE - std::cout << "Smooth vertices..."; - std::cout.flush(); - std::size_t nb_done = 0; -#endif - - Tr& tr = c3t3.triangulation(); - - const std::size_t nbv = tr.number_of_vertices(); - boost::unordered_map vertex_id; - std::vector smoothing_vecs(nbv, CGAL::NULL_VECTOR); - std::vector neighbors(nbv, -1); - - //collect ids - std::size_t id = 0; - for (Finite_vertices_iterator vit = tr.finite_vertices_begin(); - vit != tr.finite_vertices_end(); ++vit) - { - vertex_id[vit] = id++; - } - - if (!protect_boundaries) - { - for (Finite_edges_iterator eit = tr.finite_edges_begin(); - eit != tr.finite_edges_end(); ++eit) - { - const Vertex_handle vh0 = eit->first->vertex(eit->second); - const Vertex_handle vh1 = eit->first->vertex(eit->third); - - const std::size_t& i0 = vertex_id.at(vh0); - const std::size_t& i1 = vertex_id.at(vh1); - - if (/*toRemesh != REMESH_IMAGINARY &&*/ c3t3.is_in_complex(*eit)) - { - if (!is_feature(vh0, c3t3)) - neighbors[i0] = std::max(0, neighbors[i0]); - if (!is_feature(vh1, c3t3)) - neighbors[i1] = std::max(0, neighbors[i1]); - - bool update_v0 = false, update_v1 = false; - - helpers::get_edge_info(*eit, update_v0, update_v1, c3t3, cell_selector); - if (update_v0) - { - const Point_3& p1 = vh1->point(); - smoothing_vecs[i0] = smoothing_vecs[i0] + Vector_3(p1.x(), p1.y(), p1.z()); - neighbors[i0]++; - } - if (update_v1) - { - const Point_3& p0 = vh0->point(); - smoothing_vecs[i1] = smoothing_vecs[i1] + Vector_3(p0.x(), p0.y(), p0.z()); - neighbors[i1]++; - } - } - } - - //collect a map of vertices subdomain indices - boost::unordered_map > vertices_subdomain_indices; - for (typename C3T3::Cell_iterator cit = c3t3.cells_in_complex_begin(); - cit != c3t3.cells_in_complex_end(); ++cit) - { - for (int i = 0; i < 4; ++i) - { - Vertex_handle vi = cit->vertex(i); - Subdomain_index si = cit->subdomain_index(); - - if (vertices_subdomain_indices.find(vi) == vertices_subdomain_indices.end()) - { - std::vector indices(1); - indices[0] = si; - vertices_subdomain_indices.insert(std::make_pair(vi, indices)); - } - else - { - std::vector& v_indices = vertices_subdomain_indices.at(vi); - if (std::find(v_indices.begin(), v_indices.end(), si) == v_indices.end()) - v_indices.push_back(si); - } - } - } - - //collect a map of vertices surface indices - boost::unordered_map > vertices_surface_indices; - for(typename C3T3::Facet_iterator fit = c3t3.facets_in_complex_begin(); - fit != c3t3.facets_in_complex_end(); ++fit) - { - Surface_patch_index surface_index - = helpers::make_surface_patch_index(fit->first->subdomain_index(), - fit->first->neighbor(fit->second)->subdomain_index()); - for (int i = 0; i < 3; ++i) - { - Vertex_handle vi = fit->first->vertex(indices(fit->second, i)); - if (vertices_subdomain_indices.at(vi).size() > 2) - { - if (vertices_surface_indices.find(vi) == vertices_surface_indices.end()) - { - std::vector indices(1); - indices[0] = surface_index; - vertices_surface_indices.insert(std::make_pair(vi, indices)); - } - else - { - std::vector& v_surface_indices = vertices_surface_indices.at(vi); - if (std::find(v_surface_indices.begin(), v_surface_indices.end(), surface_index) - == v_surface_indices.end()) - v_surface_indices.push_back(surface_index); - } - } - } - } - - //collect a map of normals at surface vertices - boost::unordered_map > vertices_normals; - for (Finite_vertices_iterator vit = tr.finite_vertices_begin(); - vit != tr.finite_vertices_end(); ++vit) - { - const std::size_t& vid = vertex_id.at(vit); - if (neighbors[vid] > 1) - { - Point_3 smoothed_position = CGAL::ORIGIN + smoothing_vecs[vid] / neighbors[vid]; - Vector_3 final_move = CGAL::NULL_VECTOR; - Point_3 final_position; - - std::size_t count = 0; - Point_3 current_pos = vit->point(); - - const std::vector& v_surface_indices = vertices_surface_indices[vit]; - for (std::size_t i = 0; i < v_surface_indices.size(); ++i) - { - const Surface_patch_index& si = v_surface_indices[i]; - - Vector_3 normal_projection - = project_on_tangent_plane(smoothed_position, current_pos, vertices_normals[vit][si]); - - //Check if the mls surface exists to avoid degenrated cases - Vector_3 mls_projection; - if (project(si, normal_projection, mls_projection)){ - final_move = final_move + mls_projection; - } - else { - final_move = final_move + normal_projection; - } - count++; - } - - if (count > 0) - final_position = CGAL::ORIGIN + final_move / static_cast(count); - else - final_position = smoothed_position; - - // move vertex - vit->set_point(final_position); - - } - else if (neighbors[vid] > 0) - { - Vector_3 final_move = CGAL::NULL_VECTOR; - Point_3 final_position; - - int count = 0; - Vector_3 current_move(CGAL::ORIGIN, vit->point()); - - const std::vector& v_surface_indices = vertices_surface_indices[vit]; - for (std::size_t i = 0; i < v_surface_indices.size(); ++i) - { - Surface_patch_index si = v_surface_indices[i]; - //Check if the mls surface exists to avoid degenrated cases - - Vector_3 mls_projection; - if (project(si, current_move, mls_projection)){ - final_move = final_move + mls_projection; - } - else { - final_move = final_move + current_move; - } - count++; - } - - if (count > 0) - final_position = CGAL::ORIGIN + final_move / count; - else - final_position = CGAL::ORIGIN + current_move; - - // move vertex - vit->set_point(final_position); - } - } - - smoothing_vecs.clear(); - smoothing_vecs.resize(nbv, CGAL::NULL_VECTOR); - - neighbors.clear(); - neighbors.resize(nbv, -1); - - for (Finite_edges_iterator eit = tr.finite_edges_begin(); - eit != tr.finite_edges_end(); ++eit) - { - const Vertex_handle vh0 = eit->first->vertex(eit->second); - const Vertex_handle vh1 = eit->first->vertex(eit->third); - - const std::size_t& i0 = vertex_id.at(vh0); - const std::size_t& i1 = vertex_id.at(vh1); - - if ((/*toRemesh != REMESH_IN_COMPLEX &&*/ is_on_hull(*eit, c3t3)) - || (/*toRemesh != REMESH_IMAGINARY &&*/ - helpers::is_boundary(c3t3, *eit, cell_selector) && !c3t3.is_in_complex(*eit))) - { - bool update_v0 = false, update_v1 = false; - if (!is_feature(vh0, c3t3)) - neighbors[i0] = (std::max)(0, neighbors[i0]); - if (!is_feature(vh1, c3t3)) - neighbors[i1] = (std::max)(0, neighbors[i1]); - - helpers::get_edge_info(*eit, update_v0, update_v1, c3t3, cell_selector); - if (update_v0) - { - const Point_3& p1 = vh1->point(); - smoothing_vecs[i0] = smoothing_vecs[i0] + Vector_3(p1.x(), p1.y(), p1.z()); - neighbors[i0]++; - } - if (update_v1) - { - const Point_3& p0 = vh0->point(); - smoothing_vecs[i1] = smoothing_vecs[i1] + Vector_3(p0.x(), p0.y(), p0.z()); - neighbors[i1]++; - } - } - } - - for (Finite_vertices_iterator vit = tr.finite_vertices_begin(); - vit != tr.finite_vertices_end(); ++vit) - { - const std::size_t& vid = vertex_id.at(vit); - - if (neighbors[vid] > 1) - { - Point_3 smoothed_position = CGAL::ORIGIN + smoothing_vecs[vid] / neighbors[vid]; - Point_3 current_pos = vit->point(); - Point_3 final_position = CGAL::ORIGIN; - - if (vit->in_dimension() == 3 && is_on_hull(vit, c3t3)) - { - Vector_3 final_move = project_on_tangent_plane( - smoothed_position, current_pos, vertices_normals[vit][Surface_patch_index()]); - final_position = CGAL::ORIGIN + final_move; - } - else { - // Surface_patch_index si = helpers::make_surface_patch_index( - // vertices_subdomain_indices[vit][0], vertices_subdomain_indices[vit][1]); - - // Vector_3 normal_projection = project_on_tangent_plane(smoothed_position, - // current_pos, - // vertices_normals[vit][si]); - //Vector_3 mls_projection; - //if (project(si, normal_projection, mls_projection) /*|| project( si, smoothed_position, mls_projection )*/){ - // final_position = mls_projection; - // //final_position = smoothed_position; - //} - //else { - final_position = smoothed_position; - //} - // std::cout << "MLS " << final_position[0] << " - " << final_position[1] << " : " << final_position[2] << std::endl; - } - /* - Normal_iterator it = vertices_normals[vit->info()].end(); - it--; - final_position = final_position + projectOnTangentPlane( smoothed_position, current_pos , it->second ); - */ - - vit->set_point(final_position); - } - else if (neighbors[vid] > 0) - { - if (vit->in_dimension() == 2) - { - // Surface_patch_index si = helpers::make_surface_patch_index( - // vertices_subdomain_indices[vit][0], - // vertices_subdomain_indices[vit][1]); - - Vector_3 current_pos(CGAL::ORIGIN, vit->point()); - Vector_3 mls_projection; -// if (project(si, current_pos, mls_projection) /*|| project( si, smoothed_position, mls_projection )*/){ -// vit->set_point(Point_3(mls_projection.x(), mls_projection.y(), mls_projection.z())); +// template +// void smooth_vertices(C3T3& c3t3, +// const typename C3T3::Subdomain_index&, +// const bool protect_boundaries, +// CellSelector cell_selector) +// { +// typedef typename C3T3::Surface_patch_index Surface_patch_index; +// typedef typename C3T3::Subdomain_index Subdomain_index; +// typedef typename C3T3::Triangulation Tr; +// typedef typename C3T3::Vertex_handle Vertex_handle; +// typedef typename C3T3::Cell_handle Cell_handle; +// typedef typename Tr::Finite_vertices_iterator Finite_vertices_iterator; +// typedef typename Tr::Finite_edges_iterator Finite_edges_iterator; +// +// typedef typename Tr::Geom_traits Gt; +// typedef typename Gt::Point_3 Point_3; +// typedef typename Gt::Vector_3 Vector_3; +// typedef typename Gt::FT FT; +// +//#ifdef CGAL_TETRAHEDRAL_REMESHING_VERBOSE +// std::cout << "Smooth vertices..."; +// std::cout.flush(); +// std::size_t nb_done = 0; +//#endif +// +// Tr& tr = c3t3.triangulation(); +// +// const std::size_t nbv = tr.number_of_vertices(); +// boost::unordered_map vertex_id; +// std::vector smoothing_vecs(nbv, CGAL::NULL_VECTOR); +// std::vector neighbors(nbv, -1); +// +// //collect ids +// std::size_t id = 0; +// for (Finite_vertices_iterator vit = tr.finite_vertices_begin(); +// vit != tr.finite_vertices_end(); ++vit) +// { +// vertex_id[vit] = id++; +// } +// +// if (!protect_boundaries) +// { +// for (Finite_edges_iterator eit = tr.finite_edges_begin(); +// eit != tr.finite_edges_end(); ++eit) +// { +// const Vertex_handle vh0 = eit->first->vertex(eit->second); +// const Vertex_handle vh1 = eit->first->vertex(eit->third); +// +// const std::size_t& i0 = vertex_id.at(vh0); +// const std::size_t& i1 = vertex_id.at(vh1); +// +// if (/*toRemesh != REMESH_IMAGINARY &&*/ c3t3.is_in_complex(*eit)) +// { +// if (!is_feature(vh0, c3t3)) +// neighbors[i0] = std::max(0, neighbors[i0]); +// if (!is_feature(vh1, c3t3)) +// neighbors[i1] = std::max(0, neighbors[i1]); +// +// bool update_v0 = false, update_v1 = false; +// +// helpers::get_edge_info(*eit, update_v0, update_v1, c3t3, cell_selector); +// if (update_v0) +// { +// const Point_3& p1 = vh1->point(); +// smoothing_vecs[i0] = smoothing_vecs[i0] + Vector_3(p1.x(), p1.y(), p1.z()); +// neighbors[i0]++; +// } +// if (update_v1) +// { +// const Point_3& p0 = vh0->point(); +// smoothing_vecs[i1] = smoothing_vecs[i1] + Vector_3(p0.x(), p0.y(), p0.z()); +// neighbors[i1]++; +// } +// } +// } +// +// //collect a map of vertices subdomain indices +// boost::unordered_map > vertices_subdomain_indices; +// for (typename C3T3::Cell_iterator cit = c3t3.cells_in_complex_begin(); +// cit != c3t3.cells_in_complex_end(); ++cit) +// { +// for (int i = 0; i < 4; ++i) +// { +// Vertex_handle vi = cit->vertex(i); +// Subdomain_index si = cit->subdomain_index(); +// +// if (vertices_subdomain_indices.find(vi) == vertices_subdomain_indices.end()) +// { +// std::vector indices(1); +// indices[0] = si; +// vertices_subdomain_indices.insert(std::make_pair(vi, indices)); +// } +// else +// { +// std::vector& v_indices = vertices_subdomain_indices.at(vi); +// if (std::find(v_indices.begin(), v_indices.end(), si) == v_indices.end()) +// v_indices.push_back(si); +// } +// } +// } +// +// //collect a map of vertices surface indices +// boost::unordered_map > vertices_surface_indices; +// for(typename C3T3::Facet_iterator fit = c3t3.facets_in_complex_begin(); +// fit != c3t3.facets_in_complex_end(); ++fit) +// { +// Surface_patch_index surface_index +// = helpers::make_surface_patch_index(fit->first->subdomain_index(), +// fit->first->neighbor(fit->second)->subdomain_index()); +// for (int i = 0; i < 3; ++i) +// { +// Vertex_handle vi = fit->first->vertex(indices(fit->second, i)); +// if (vertices_subdomain_indices.at(vi).size() > 2) +// { +// if (vertices_surface_indices.find(vi) == vertices_surface_indices.end()) +// { +// std::vector indices(1); +// indices[0] = surface_index; +// vertices_surface_indices.insert(std::make_pair(vi, indices)); // } - } - } - } - } - smoothing_vecs.clear(); - smoothing_vecs.resize(nbv, CGAL::NULL_VECTOR); - - neighbors.clear(); - neighbors.resize(nbv, 0); - - for (Finite_edges_iterator eit = tr.finite_edges_begin(); - eit != tr.finite_edges_end(); ++eit) - { - //bool in_complex = c3t3.is_in_complex(*eit); - //if ( toRemesh == REMESH_ALL - // || (toRemesh == REMESH_IN_COMPLEX && in_complex) - // || (toRemesh == REMESH_IMAGINARY && !in_complex)) - { - const Vertex_handle vh0 = eit->first->vertex(eit->second); - const Vertex_handle vh1 = eit->first->vertex(eit->third); - - const std::size_t& i0 = vertex_id.at(vh0); - const std::size_t& i1 = vertex_id.at(vh1); - - if (c3t3.in_dimension(vh0) == 3 && !is_on_hull(vh0, c3t3)) - { - const Point_3& p1 = vh1->point(); - smoothing_vecs[i0] = smoothing_vecs[i0] + Vector_3(CGAL::ORIGIN, p1); - neighbors[i0]++; - } - if (c3t3.in_dimension(vh1) == 3 && !is_on_hull(vh1, c3t3)) - { - const Point_3& p0 = vh0->point(); - smoothing_vecs[i1] = smoothing_vecs[i1] + Vector_3(CGAL::ORIGIN, p0); - neighbors[i1]++; - } - } - } - - for (Finite_vertices_iterator vit = tr.finite_vertices_begin(); - vit != tr.finite_vertices_end(); ++vit) - { - const std::size_t& vid = vertex_id.at(vit); - if (neighbors[vid] > 1) - { - if (smoothing_vecs[vid] != CGAL::NULL_VECTOR) - { -#ifdef CGAL_TETRAHEDRAL_REMESHING_VERBOSE - ++nb_done; -#endif - Point_3 new_pos = CGAL::ORIGIN + smoothing_vecs[vid] / neighbors[vid]; - const Vector_3 move(vit->point(), new_pos); - - std::vector cells; - tr.finite_incident_cells(vit, std::back_inserter(cells)); - - bool selected = true; - for (std::size_t i = 0; i < cells.size(); ++i) - { - if (!cell_selector(cells[i])) - { - selected = false; - break; - } - } - if (!selected) - continue; - - double frac = 1.; - while (frac > 0.05 /// 1/16 = 0.0625 - && !check_inversion_and_move(vit, frac * move, cells)) - { - frac = 0.5 * frac; - } - } - } - } - -#ifdef CGAL_TETRAHEDRAL_REMESHING_VERBOSE - std::cout << " done (" << nb_done << " vertices smoothed)." << std::endl; -#endif - } +// else +// { +// std::vector& v_surface_indices = vertices_surface_indices.at(vi); +// if (std::find(v_surface_indices.begin(), v_surface_indices.end(), surface_index) +// == v_surface_indices.end()) +// v_surface_indices.push_back(surface_index); +// } +// } +// } +// } +// +// //collect a map of normals at surface vertices +// boost::unordered_map > vertices_normals; +// for (Finite_vertices_iterator vit = tr.finite_vertices_begin(); +// vit != tr.finite_vertices_end(); ++vit) +// { +// const std::size_t& vid = vertex_id.at(vit); +// if (neighbors[vid] > 1) +// { +// Point_3 smoothed_position = CGAL::ORIGIN + smoothing_vecs[vid] / neighbors[vid]; +// Vector_3 final_move = CGAL::NULL_VECTOR; +// Point_3 final_position; +// +// std::size_t count = 0; +// Point_3 current_pos = vit->point(); +// +// const std::vector& v_surface_indices = vertices_surface_indices[vit]; +// for (std::size_t i = 0; i < v_surface_indices.size(); ++i) +// { +// const Surface_patch_index& si = v_surface_indices[i]; +// +// Vector_3 normal_projection +// = project_on_tangent_plane(smoothed_position, current_pos, vertices_normals[vit][si]); +// +// //Check if the mls surface exists to avoid degenrated cases +// Vector_3 mls_projection; +// if (project(si, normal_projection, mls_projection)){ +// final_move = final_move + mls_projection; +// } +// else { +// final_move = final_move + normal_projection; +// } +// count++; +// } +// +// if (count > 0) +// final_position = CGAL::ORIGIN + final_move / static_cast(count); +// else +// final_position = smoothed_position; +// +// // move vertex +// vit->set_point(final_position); +// +// } +// else if (neighbors[vid] > 0) +// { +// Vector_3 final_move = CGAL::NULL_VECTOR; +// Point_3 final_position; +// +// int count = 0; +// Vector_3 current_move(CGAL::ORIGIN, vit->point()); +// +// const std::vector& v_surface_indices = vertices_surface_indices[vit]; +// for (std::size_t i = 0; i < v_surface_indices.size(); ++i) +// { +// Surface_patch_index si = v_surface_indices[i]; +// //Check if the mls surface exists to avoid degenrated cases +// +// Vector_3 mls_projection; +// if (project(si, current_move, mls_projection)){ +// final_move = final_move + mls_projection; +// } +// else { +// final_move = final_move + current_move; +// } +// count++; +// } +// +// if (count > 0) +// final_position = CGAL::ORIGIN + final_move / count; +// else +// final_position = CGAL::ORIGIN + current_move; +// +// // move vertex +// vit->set_point(final_position); +// } +// } +// +// smoothing_vecs.clear(); +// smoothing_vecs.resize(nbv, CGAL::NULL_VECTOR); +// +// neighbors.clear(); +// neighbors.resize(nbv, -1); +// +// for (Finite_edges_iterator eit = tr.finite_edges_begin(); +// eit != tr.finite_edges_end(); ++eit) +// { +// const Vertex_handle vh0 = eit->first->vertex(eit->second); +// const Vertex_handle vh1 = eit->first->vertex(eit->third); +// +// const std::size_t& i0 = vertex_id.at(vh0); +// const std::size_t& i1 = vertex_id.at(vh1); +// +// if ((/*toRemesh != REMESH_IN_COMPLEX &&*/ is_on_hull(*eit, c3t3)) +// || (/*toRemesh != REMESH_IMAGINARY &&*/ +// helpers::is_boundary(c3t3, *eit, cell_selector) && !c3t3.is_in_complex(*eit))) +// { +// bool update_v0 = false, update_v1 = false; +// if (!is_feature(vh0, c3t3)) +// neighbors[i0] = (std::max)(0, neighbors[i0]); +// if (!is_feature(vh1, c3t3)) +// neighbors[i1] = (std::max)(0, neighbors[i1]); +// +// helpers::get_edge_info(*eit, update_v0, update_v1, c3t3, cell_selector); +// if (update_v0) +// { +// const Point_3& p1 = vh1->point(); +// smoothing_vecs[i0] = smoothing_vecs[i0] + Vector_3(p1.x(), p1.y(), p1.z()); +// neighbors[i0]++; +// } +// if (update_v1) +// { +// const Point_3& p0 = vh0->point(); +// smoothing_vecs[i1] = smoothing_vecs[i1] + Vector_3(p0.x(), p0.y(), p0.z()); +// neighbors[i1]++; +// } +// } +// } +// +// for (Finite_vertices_iterator vit = tr.finite_vertices_begin(); +// vit != tr.finite_vertices_end(); ++vit) +// { +// const std::size_t& vid = vertex_id.at(vit); +// +// if (neighbors[vid] > 1) +// { +// Point_3 smoothed_position = CGAL::ORIGIN + smoothing_vecs[vid] / neighbors[vid]; +// Point_3 current_pos = vit->point(); +// Point_3 final_position = CGAL::ORIGIN; +// +// if (vit->in_dimension() == 3 && is_on_hull(vit, c3t3)) +// { +// Vector_3 final_move = project_on_tangent_plane( +// smoothed_position, current_pos, vertices_normals[vit][Surface_patch_index()]); +// final_position = CGAL::ORIGIN + final_move; +// } +// else { +// // Surface_patch_index si = helpers::make_surface_patch_index( +// // vertices_subdomain_indices[vit][0], vertices_subdomain_indices[vit][1]); +// +// // Vector_3 normal_projection = project_on_tangent_plane(smoothed_position, +// // current_pos, +// // vertices_normals[vit][si]); +// //Vector_3 mls_projection; +// //if (project(si, normal_projection, mls_projection) /*|| project( si, smoothed_position, mls_projection )*/){ +// // final_position = mls_projection; +// // //final_position = smoothed_position; +// //} +// //else { +// final_position = smoothed_position; +// //} +// // std::cout << "MLS " << final_position[0] << " - " << final_position[1] << " : " << final_position[2] << std::endl; +// } +// /* +// Normal_iterator it = vertices_normals[vit->info()].end(); +// it--; +// final_position = final_position + projectOnTangentPlane( smoothed_position, current_pos , it->second ); +// */ +// +// vit->set_point(final_position); +// } +// else if (neighbors[vid] > 0) +// { +// if (vit->in_dimension() == 2) +// { +// // Surface_patch_index si = helpers::make_surface_patch_index( +// // vertices_subdomain_indices[vit][0], +// // vertices_subdomain_indices[vit][1]); +// +// Vector_3 current_pos(CGAL::ORIGIN, vit->point()); +// Vector_3 mls_projection; +//// if (project(si, current_pos, mls_projection) /*|| project( si, smoothed_position, mls_projection )*/){ +//// vit->set_point(Point_3(mls_projection.x(), mls_projection.y(), mls_projection.z())); +//// } +// } +// } +// } +// } +// smoothing_vecs.clear(); +// smoothing_vecs.resize(nbv, CGAL::NULL_VECTOR); +// +// neighbors.clear(); +// neighbors.resize(nbv, 0); +// +// for (Finite_edges_iterator eit = tr.finite_edges_begin(); +// eit != tr.finite_edges_end(); ++eit) +// { +// //bool in_complex = c3t3.is_in_complex(*eit); +// //if ( toRemesh == REMESH_ALL +// // || (toRemesh == REMESH_IN_COMPLEX && in_complex) +// // || (toRemesh == REMESH_IMAGINARY && !in_complex)) +// { +// const Vertex_handle vh0 = eit->first->vertex(eit->second); +// const Vertex_handle vh1 = eit->first->vertex(eit->third); +// +// const std::size_t& i0 = vertex_id.at(vh0); +// const std::size_t& i1 = vertex_id.at(vh1); +// +// if (c3t3.in_dimension(vh0) == 3 && !is_on_hull(vh0, c3t3)) +// { +// const Point_3& p1 = vh1->point(); +// smoothing_vecs[i0] = smoothing_vecs[i0] + Vector_3(CGAL::ORIGIN, p1); +// neighbors[i0]++; +// } +// if (c3t3.in_dimension(vh1) == 3 && !is_on_hull(vh1, c3t3)) +// { +// const Point_3& p0 = vh0->point(); +// smoothing_vecs[i1] = smoothing_vecs[i1] + Vector_3(CGAL::ORIGIN, p0); +// neighbors[i1]++; +// } +// } +// } +// +// for (Finite_vertices_iterator vit = tr.finite_vertices_begin(); +// vit != tr.finite_vertices_end(); ++vit) +// { +// const std::size_t& vid = vertex_id.at(vit); +// if (neighbors[vid] > 1) +// { +// if (smoothing_vecs[vid] != CGAL::NULL_VECTOR) +// { +//#ifdef CGAL_TETRAHEDRAL_REMESHING_VERBOSE +// ++nb_done; +//#endif +// Point_3 new_pos = CGAL::ORIGIN + smoothing_vecs[vid] / neighbors[vid]; +// const Vector_3 move(vit->point(), new_pos); +// +// std::vector cells; +// tr.finite_incident_cells(vit, std::back_inserter(cells)); +// +// bool selected = true; +// for (std::size_t i = 0; i < cells.size(); ++i) +// { +// if (!cell_selector(cells[i])) +// { +// selected = false; +// break; +// } +// } +// if (!selected) +// continue; +// +// double frac = 1.; +// while (frac > 0.05 /// 1/16 = 0.0625 +// && !check_inversion_and_move(vit, frac * move, cells)) +// { +// frac = 0.5 * frac; +// } +// } +// } +// } +// +//#ifdef CGAL_TETRAHEDRAL_REMESHING_VERBOSE +// std::cout << " done (" << nb_done << " vertices smoothed)." << std::endl; +//#endif +// } }//namespace internal }//namespace Tetrahedral_adaptive_remeshing From 6af44bf121e0bb42d33c94ab069488b5bed52a65 Mon Sep 17 00:00:00 2001 From: Jane Tournois Date: Mon, 30 Sep 2019 17:13:14 +0200 Subject: [PATCH 023/568] remove obsolete code --- .../internal/tetrahedral_remeshing_helpers.h | 352 +----------------- .../internal/triangulation_3_helpers.h | 66 ---- 2 files changed, 1 insertion(+), 417 deletions(-) diff --git a/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/tetrahedral_remeshing_helpers.h b/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/tetrahedral_remeshing_helpers.h index e87dd8f5946..f3ec9340a1a 100644 --- a/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/tetrahedral_remeshing_helpers.h +++ b/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/tetrahedral_remeshing_helpers.h @@ -375,21 +375,6 @@ namespace Tetrahedral_remeshing #endif } - namespace internal - { - template - bool insert_in_cells(const CellHandle c, CellsSet& cells) - { - std::set vertices; - for (int i = 0; i < 4; ++i) - vertices.insert(c->vertex(i)); - if (cells.find(vertices) != cells.end()) - return false; - cells.insert(vertices); - return true; - } - } // end internal - namespace debug { // forward-declaration template @@ -397,27 +382,6 @@ namespace Tetrahedral_remeshing } namespace helpers { - - template - void read_iso_cuboid(std::istream& is, - CGAL::Iso_cuboid_3& bbox) - { - typedef typename K::Point_3 Point_3; - Point_3 p1, p2; - double x, y, z; - is >> x >> y >> z; - p1 = Point_3(x, y, z); - is >> x >> y >> z; - p2 = Point_3(x, y, z); - - if (p1 < p2) - bbox = CGAL::Iso_cuboid_3(p1, p2); - else - bbox = CGAL::Iso_cuboid_3(p2, p1); - - CGAL_assertion(p1 != p2); - } - template void set_time_stamps(Tr& tr) { @@ -502,226 +466,12 @@ namespace Tetrahedral_remeshing } }; - template - bool check_size_of_padding_box(const CellsSet& inside_cells, - const CGAL::Iso_cuboid_3& cuboid) - { - // all cells that are in intersecting_cells AND inside_cells - // should NOT be clipped - typedef typename CellsSet::value_type Cell_handle; - -#ifdef CGAL_LIMITED_APERTURE_DEBUG - std::vector cells; -#endif - for (typename CellsSet::iterator cit = inside_cells.begin(); - cit != inside_cells.end(); ++cit) - { - Cell_handle c = *cit; - for (int i = 0; i < 4; ++i) - { - if (cuboid.has_on_unbounded_side(c->vertex(i)->point())) - { -#ifdef CGAL_LIMITED_APERTURE_DEBUG - cells.push_back(c); - break; -#else - return false; -#endif - } - } - } -#ifdef CGAL_LIMITED_APERTURE_DEBUG - debug::dump_cells(cells, "cells_from_padding_zone.mesh"); - return cells.empty(); -#else - return true; -#endif - } - -#ifdef CGAL_LIMITED_APERTURE_EDGE_SELECTION - - template - bool outer_box_criterion(const C3T3& c3t3, - CellCirculator circ, - CellCirculator end, - const typename C3T3::Subdomain_index& imaginary_index) - { - std::size_t nb_imaginary = 0; - std::size_t nb_total = 0; - std::size_t nb_padding = 0; - std::size_t nb_outside = 0; - do - { - if (circ->subdomain_index() == imaginary_index) - ++nb_imaginary; - else if (!c3t3.is_in_complex(circ)) - ++nb_outside; - else if (circ->info().padding()) - ++nb_padding; - - ++nb_total; - } while (++circ != end); - - return nb_padding > 0 && (nb_imaginary + nb_outside) < nb_total; - } - - template - bool is_on_the_outer_box(const typename C3T3::Edge& e, - const C3T3& c3t3, - const typename C3T3::Subdomain_index& imaginary_index) - { - typedef typename C3T3::Triangulation::Cell_circulator Cell_circulator; - Cell_circulator circ = c3t3.triangulation().incident_cells(e); - Cell_circulator end = circ; - - return outer_box_criterion(c3t3, circ, end, imaginary_index); - } - - template - bool is_on_the_outer_box(const typename C3T3::Vertex_handle& v, - const C3T3& c3t3, - const typename C3T3::Subdomain_index& imaginary_index) - { - std::vector cells; - c3t3.triangulation().incident_cells(v, std::back_inserter(cells)); - - return outer_box_criterion(c3t3, cells.begin(), cells.end(), imaginary_index); - } -#endif CGAL_LIMITED_APERTURE_EDGE_SELECTION }//end namespace helpers namespace debug { - template - void rebuild_with_insert(Tr& tr, const int nbv_max) - { - typedef typename Tr::Point Point; - std::vector points(tr.number_of_vertices()); - int index = 0; - for (typename Tr::Finite_vertices_iterator vit = tr.finite_vertices_begin(); - vit != tr.finite_vertices_end(); ++vit) - { - points[index++] = vit->point(); - } - - tr.clear(); - for (int i = 0; i < nbv_max; ++i) - tr.insert(points[i]); - } - - template - void check_validity(const Tr& tr) - { - CGAL_assertion(tr.is_valid(true)); - for (typename Tr::All_vertices_iterator vit = tr.all_vertices_begin(); - vit != tr.all_vertices_end(); - ++vit) - { - typename Tr::Cell_handle c = vit->cell(); - CGAL_assertion(c->has_vertex(vit)); - } - - std::ofstream ofs("extra_cells.polylines.txt"); - std::set extra_cells; - std::set > cells; - for (typename Tr::All_cells_iterator cit = tr.all_cells_begin(); - cit != tr.all_cells_end(); - ++cit) - { - typename Tr::Cell_handle c = cit; - for (int i = 0; i < 4; ++i) - { - typename Tr::Cell_handle ci = c->neighbor(i); - int j; - CGAL_assertion(c->has_neighbor(ci, j)); - CGAL_assertion(i == j); - j = ci->index(c); - CGAL_assertion(ci->neighbor(j) == c); - CGAL_assertion(ci->has_neighbor(c, j)); - } - if (!internal::insert_in_cells(c, cells)) - { - extra_cells.insert(c); - for (int j = 0; j < 4; ++j) - dump_facet(std::make_pair(c, j), ofs); - } - } - ofs.close(); - } - - template - void debug_infinite_facets(const ClippedCellsMap& clipped_cells, - const Tr& tr) - { - typedef typename Tr::Point Point; - //collect convex hull of tr edges (as pairs of ordered points) - std::vector/*ordered pair*/> ch_edges; - - for (typename ClippedCellsMap::const_iterator cmit = clipped_cells.begin(); - cmit != clipped_cells.end(); - ++cmit) - { - typedef typename ClippedCellsMap::mapped_type CellTr; - const CellTr& ctr = cmit->second; - - typename ClippedCellsMap::key_type cell = cmit->first; - - for (typename CellTr::Finite_edges_iterator eit = ctr.finite_edges_begin(); - eit != ctr.finite_edges_end(); - ++eit) - { - Point p1 = (eit->first)->vertex(eit->second)->point(); - Point p2 = (eit->first)->vertex(eit->third)->point(); - if (p2 < p1) - std::swap(p1, p2); //make sure that p1 <= p2 - - int vi = 0, vj = 0; - for (; vi < 4; ++vi) - { - if (cell->vertex(vi)->point() == p1) - break; - } - if (vi == 4) - continue; - for (; vj < 4; ++vj) - { - if (cell->vertex(vj)->point() == p2) - break; - } - if (vj == 4) - continue; - - int vk = Tr::next_around_edge(vi, vj); - int vl = Tr::next_around_edge(vj, vi); - if (tr.is_infinite(cell->neighbor(vk))) - ch_edges.push_back(std::make_pair(p1, p2)); - if (tr.is_infinite(cell->neighbor(vl))) - ch_edges.push_back(std::make_pair(p1, p2)); - } - } - - //check that each edge appears exactly twice - std::sort(ch_edges.begin(), ch_edges.end()); - bool twice_each = (ch_edges.size() % 2 == 0); - for (std::size_t i = 0; i < ch_edges.size() - 1; i = i + 2) - { - if (ch_edges[i] != ch_edges[i + 1]) - twice_each = false; - } - if (!twice_each) - { - for (std::size_t i = 0; i < ch_edges.size(); ++i) - { - std::cout << i << "\t" - << ch_edges[i].first << " " << ch_edges[i].second - << std::endl; - } - } - CGAL_assertion(twice_each); - } - template void dump_surface_off(const Tr& tr, const char* filename) { @@ -1046,7 +796,7 @@ namespace Tetrahedral_remeshing template void dump_without_imaginary(const Tr& tr, const char* filename, - const int imaginary_index) + const int imaginary_index) { std::vector cells; std::vector indices; @@ -1059,111 +809,11 @@ namespace Tetrahedral_remeshing { cells.push_back(cit); indices.push_back(1); - //cit->info().padding() ? - //-1 : - //cit->info().original_index()); } } dump_cells(cells, indices, filename); } - template - void dump_padding_cells(const Tr& tr, const char* filename) - { - std::vector cells; - std::vector indices; - - for (typename Tr::Finite_cells_iterator cit = tr.finite_cells_begin(); - cit != tr.finite_cells_end(); ++cit) - { - if (cit->info().padding()) - { - cells.push_back(cit); - if (cit->subdomain_index() > 0) - indices.push_back(cit->subdomain_index()); - else - indices.push_back(1); - } - } - dump_cells(cells, indices, filename); - } - - template - void dump_non_padding_plus_the_outer_bbox(const Tr& tr, - const Isocuboid& bbox, - const char* filename) - { - typedef typename Tr::Vertex_handle Vertex_handle; - typedef typename Tr::Point Point; - typedef boost::bimap Bimap_t; - typedef typename Bimap_t::left_map::value_type value_type; - - Bimap_t vertices; - int index = 9; // because we output first the 8 vertices of the - // bbox - std::size_t nb_of_cells = 0; - for (typename Tr::Finite_cells_iterator cit = tr.finite_cells_begin(); - cit != tr.finite_cells_end(); ++cit) - { - if (cit->info().padding()) { - continue; - } - ++nb_of_cells; - for (int i = 0; i < 4; ++i) - { - Vertex_handle vi = cit->vertex(i); - if (vertices.left.find(vi) == vertices.left.end()) - vertices.left.insert(value_type(vi, index++)); - } - } - std::ofstream ofs(filename); - ofs.precision(17); - ofs << "MeshVersionFormatted 1\n" - << "Dimension 3\n" - << "Vertices\n" - << vertices.size() + 8 << std::endl; - const CGAL::cpp11::array indices = { 0, 3, 2, 1, 5, 4, 7, 6 }; - for (int i = 0; i < 8; ++i) { - const typename Tr::Point_3 p = bbox[indices[i]]; - ofs << p.x() << " " << p.y() << " " << p.z() << " 1" << std::endl; - } - for (typename Bimap_t::right_const_iterator vit = vertices.right.begin(); - vit != vertices.right.end(); - ++vit) - { - const Point& p = vit->second->point(); - ofs << p.x() << " " << p.y() << " " << p.z() << " 2" << std::endl; - } - ofs << "Triangles\n" - << "12\n" - << "1 2 4 1\n" - << "4 2 3 1\n" - << "1 5 2 1\n" - << "2 5 6 1\n" - << "4 3 8 1\n" - << "8 3 7 1\n" - << "5 1 4 1\n" - << "8 5 4 1\n" - << "7 5 8 1\n" - << "7 6 5 1\n" - << "2 6 7 1\n" - << "3 2 7 1\n"; - ofs << "Tetrahedra" << std::endl << nb_of_cells << std::endl; - for (typename Tr::Finite_cells_iterator cit = tr.finite_cells_begin(); - cit != tr.finite_cells_end(); ++cit) - { - if (cit->info().padding()) continue; - ofs << vertices.left.at(cit->vertex(0)) << " " - << vertices.left.at(cit->vertex(1)) << " " - << vertices.left.at(cit->vertex(2)) << " " - << vertices.left.at(cit->vertex(3)) << " " - << cit->info().original_index() << std::endl; - } - ofs << "End" << std::endl; - ofs.close(); - } - - template void dump_edges(const VertexPairsSet& edges, const char* filename) { diff --git a/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/triangulation_3_helpers.h b/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/triangulation_3_helpers.h index d92e8ec4a89..2e3632448c9 100644 --- a/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/triangulation_3_helpers.h +++ b/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/triangulation_3_helpers.h @@ -584,18 +584,11 @@ namespace CGAL const CGAL::Iso_cuboid_3& bbox, typename Tr::Facet& facet) { -#ifdef CGAL_LIMITED_APERTURE_DEBUG - bool res = true; -#endif - typedef typename Tr::Cell_handle Cell_handle; typedef typename Tr::Vertex_handle Vertex_handle; typedef typename Tr::Facet Facet; typedef typename Tr::Finite_facets_iterator Finite_facets_iterator; -#ifdef CGAL_LIMITED_APERTURE_DEBUG - std::vector > tetra; -#endif for (Finite_facets_iterator fit = tr.finite_facets_begin(); fit != tr.finite_facets_end(); ++fit) { @@ -650,34 +643,11 @@ namespace CGAL facet = Facet(ni, ni->index(tr.infinite_vertex())); } -#ifdef CGAL_LIMITED_APERTURE_DEBUG - boost::array tet = { vs[0], vs[1], vs[2], v3 }; - tetra.push_back(tet); - res = false; -#else return false; -#endif } } } - -#ifdef CGAL_LIMITED_APERTURE_DEBUG - std::ofstream ofs("non-convex-tets.polylines.txt"); - for (std::size_t i = 0; i < tetra.size(); ++i) - { - const boost::array& tet = tetra[i]; - ofs << "2 " << tet[0]->point() << " " << tet[1]->point() << std::endl; - ofs << "2 " << tet[0]->point() << " " << tet[2]->point() << std::endl; - ofs << "2 " << tet[0]->point() << " " << tet[3]->point() << std::endl; - ofs << "2 " << tet[1]->point() << " " << tet[2]->point() << std::endl; - ofs << "2 " << tet[1]->point() << " " << tet[3]->point() << std::endl; - ofs << "2 " << tet[2]->point() << " " << tet[3]->point() << std::endl; - } - ofs.close(); - return res; -#else return true; -#endif } template @@ -751,13 +721,6 @@ namespace internal vertices.insert(c->vertex((index + 3) % 4)); CGAL_assertion(vertices.size() == 3); -#ifdef CGAL_LIMITED_APERTURE_VERBOSE - if (verbose) - std::cout << "add_to_incidence_map facet : " << std::endl - << &*(c->vertex((index + 1) % 4)) << "\t" - << &*(c->vertex((index + 2) % 4)) << "\t" - << &*(c->vertex((index + 3) % 4)) << std::endl; -#endif typename IncidentFacetsMap::iterator it = incidence_map.find(vertices); if (it == incidence_map.end()) { @@ -769,35 +732,6 @@ namespace internal { it->second.push_back(typename Tr::Facet(c, index)); -#ifdef CGAL_LIMITED_APERTURE_DEBUG - if (it->second.size() != 2) - { - std::cout << "size is " << it->second.size() << std::endl; - std::cout << "facet is " << std::endl; - for (typename Vertex_set::iterator vit = vertices.begin(); - vit != vertices.end(); - ++vit) - std::cout << (*vit)->point() << std::endl; - - std::vector bad_cells(it->second.size()); - for (std::size_t i = 0; i < it->second.size(); ++i) - { - bad_cells[i] = it->second[i].first; - std::cout << &*(it->second[i].first) << "\t" << it->second[i].second << std::endl; - std::cout - << "\t" << &*((it->second[i].first)->vertex(0)) - << "\t" << ((it->second[i].first)->vertex(0))->point() << std::endl - << "\t" << &*((it->second[i].first)->vertex(1)) - << "\t" << ((it->second[i].first)->vertex(1))->point() << std::endl - << "\t" << &*((it->second[i].first)->vertex(2)) - << "\t" << ((it->second[i].first)->vertex(2))->point() << std::endl - << "\t" << &*((it->second[i].first)->vertex(3)) - << "\t" << ((it->second[i].first)->vertex(3))->point() << std::endl - << std::endl; - } - CGAL::debug::dump_polylines(bad_cells, "bad_cells_in_incidence_map.polylines.txt"); - } -#endif CGAL_assertion(it->second.size() == 2); CGAL_assertion(it->second[0] != it->second[1]); } From ebb94167625d90ff63d7d1e0660ec580f4b07832 Mon Sep 17 00:00:00 2001 From: Jane Tournois Date: Tue, 1 Oct 2019 14:39:23 +0200 Subject: [PATCH 024/568] reorganize helper headers and move all dump_***() functions to the same file --- .../internal/collapse_short_edges.h | 2 +- .../internal/smooth_vertices.h | 6 +- .../internal/split_long_edges.h | 2 +- .../tetrahedral_adaptive_remeshing_impl.h | 11 +- .../internal/tetrahedral_remeshing_helpers.h | 152 ++++++------------ .../internal/triangulation_3_helpers.h | 109 ------------- 6 files changed, 56 insertions(+), 226 deletions(-) diff --git a/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/collapse_short_edges.h b/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/collapse_short_edges.h index cbb2a94d079..d58482d8799 100644 --- a/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/collapse_short_edges.h +++ b/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/collapse_short_edges.h @@ -970,7 +970,7 @@ namespace internal } #ifdef CGAL_TETRAHEDRAL_REMESHING_DEBUG - helpers::dump_edges(short_edges, "short_edges.polylines.txt"); + debug::dump_edges(short_edges, "short_edges.polylines.txt"); #endif while(!short_edges.empty()) diff --git a/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/smooth_vertices.h b/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/smooth_vertices.h index 846023a963d..9b56db118e2 100644 --- a/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/smooth_vertices.h +++ b/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/smooth_vertices.h @@ -300,7 +300,8 @@ namespace internal Tr& tr = c3t3.triangulation(); #ifdef CGAL_TETRAHEDRAL_REMESHING_DEBUG - CGAL::debug::dump_vertices_by_dimension(c3t3.triangulation(), "c3t3_vertices_before_smoothing"); + CGAL::Tetrahedral_remeshing::debug::dump_vertices_by_dimension( + c3t3.triangulation(), "c3t3_vertices_before_smoothing"); #endif const std::size_t nbv = tr.number_of_vertices(); @@ -379,7 +380,8 @@ namespace internal } #ifdef CGAL_TETRAHEDRAL_REMESHING_DEBUG - CGAL::debug::dump_vertices_by_dimension(c3t3.triangulation(), "c3t3_vertices_after_smoothing"); + CGAL::Tetrahedral_remeshing::debug::dump_vertices_by_dimension( + c3t3.triangulation(), "c3t3_vertices_after_smoothing"); #endif } diff --git a/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/split_long_edges.h b/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/split_long_edges.h index 3f0324f991b..e069ab6c5b1 100644 --- a/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/split_long_edges.h +++ b/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/split_long_edges.h @@ -192,7 +192,7 @@ namespace internal } #ifdef CGAL_TETRAHEDRAL_REMESHING_DEBUG - helpers::dump_edges(long_edges, "long_edges.polylines.txt"); + debug::dump_edges(long_edges, "long_edges.polylines.txt"); std::ofstream ofs("midpoints.off"); ofs << "OFF" << std::endl; diff --git a/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/tetrahedral_adaptive_remeshing_impl.h b/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/tetrahedral_adaptive_remeshing_impl.h index f5112a1fb59..48c9ac28c9f 100644 --- a/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/tetrahedral_adaptive_remeshing_impl.h +++ b/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/tetrahedral_adaptive_remeshing_impl.h @@ -37,10 +37,6 @@ #include -#ifdef CGAL_TETRAHEDRAL_REMESHING_DEBUG -#include "../../../limited_aperture_helpers.h" -#endif - namespace CGAL { namespace Tetrahedral_remeshing @@ -355,7 +351,7 @@ namespace internal } } #ifdef CGAL_TETRAHEDRAL_REMESHING_DEBUG - CGAL::debug::dump_facets_in_complex(m_c3t3, "facets_in_complex.off"); + CGAL::Tetrahedral_remeshing::debug::dump_facets_in_complex(m_c3t3, "facets_in_complex.off"); #endif //tag edges @@ -383,7 +379,7 @@ namespace internal } } #ifdef CGAL_TETRAHEDRAL_REMESHING_DEBUG - CGAL::debug::dump_edges_in_complex(m_c3t3, "edges_in_complex.polylines.txt"); + CGAL::Tetrahedral_remeshing::debug::dump_edges_in_complex(m_c3t3, "edges_in_complex.polylines.txt"); #endif //tag vertices @@ -413,7 +409,8 @@ namespace internal std::cout << "\t edges = " << nbe << std::endl; std::cout << "\t vertices = " << nbv << std::endl; - CGAL::debug::dump_vertices_by_dimension(m_c3t3.triangulation(), "c3t3_vertices_"); + CGAL::Tetrahedral_remeshing::debug::dump_vertices_by_dimension( + m_c3t3.triangulation(), "c3t3_vertices_"); #endif } diff --git a/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/tetrahedral_remeshing_helpers.h b/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/tetrahedral_remeshing_helpers.h index f3ec9340a1a..8d39adb0533 100644 --- a/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/tetrahedral_remeshing_helpers.h +++ b/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/tetrahedral_remeshing_helpers.h @@ -24,9 +24,6 @@ #include -#include -#include - #include namespace CGAL @@ -354,10 +351,15 @@ namespace Tetrahedral_remeshing std::cout << std::endl; std::cout << "\t" << cit->subdomain_index(); } - } + } + + namespace debug + { + // forward-declaration + template + void dump_cells(const CellRange& cells, const char* filename); -#ifdef CGAL_TETRAHEDRAL_REMESHING_DEBUG template void dump_edges(const Bimap& edges, const char* filename) { @@ -369,109 +371,47 @@ namespace Tetrahedral_remeshing ofs << "2 " << it.first.first->point() << " " << it.first.second->point() << std::endl; } - ofs.close(); } -#endif - } - namespace debug { - // forward-declaration - template - void dump_cells(const CellRange& cells, const char* filename); - } - namespace helpers - { - template - void set_time_stamps(Tr& tr) + template + void dump_facet(const Facet& f, OutputStream& os) { - typedef typename Tr::Triangulation_data_structure::Vertex Vertex; - typedef typename Tr::Triangulation_data_structure::Cell Cell; - typedef typename Tr::Vertex_handle Vertex_handle; - typedef typename Tr::Cell_handle Cell_handle; + os << "4 "; + os << f.first->vertex((f.second + 1) % 4)->point() << " " + << f.first->vertex((f.second + 2) % 4)->point() << " " + << f.first->vertex((f.second + 3) % 4)->point() << " " + << f.first->vertex((f.second + 1) % 4)->point(); + os << std::endl; + } - CGAL::Time_stamper_impl v_ts; - for (typename Tr::All_vertices_iterator vit = tr.all_vertices_begin(); - vit != tr.all_vertices_end(); - ++vit) + template + void dump_facets(const FacetRange& facets, const char* filename) + { + std::ofstream os(filename); + for (typename FacetRange::const_iterator fit = facets.begin(); + fit != facets.end(); ++fit) { - Vertex_handle vh = vit; - Vertex* pv = &*vh; - v_ts.initialize_time_stamp(pv); - v_ts.set_time_stamp(pv); - } - CGAL::Time_stamper_impl c_ts; - for (typename Tr::All_cells_iterator cit = tr.all_cells_begin(); - cit != tr.all_cells_end(); - ++cit) - { - Cell_handle ch = cit; - Cell* pc = &*ch; - c_ts.initialize_time_stamp(pc); - c_ts.set_time_stamp(pc); + typename FacetRange::value_type f = *fit; + dump_facet(f, os); } } - template - struct Vertex_converter + template + void dump_polylines(const CellRange& cells, const char* filename) { - //This operator is used to create the vertex from v_src. - typename TDS_tgt::Vertex operator()(const typename TDS_src::Vertex& v_src) const + std::ofstream ofs(filename); + if (!ofs) return; + + for (typename CellRange::const_iterator it = cells.begin(); + it != cells.end(); ++it) { - typedef typename CGAL::Kernel_traits< - typename TDS_src::Vertex::Point>::Kernel GT_src; - typedef typename CGAL::Kernel_traits< - typename TDS_tgt::Vertex::Point>::Kernel GT_tgt; - CGAL::Cartesian_converter conv; - - typename TDS_tgt::Vertex v_tgt; - v_tgt.set_point(conv(v_src.point())); - v_tgt.set_time_stamp(-1); - v_tgt.set_dimension(v_src.info());//-1 if unset, 0,1,2, or 3 if set - return v_tgt; + for (int i = 0; i < 4; ++i) + dump_facet(std::make_pair(*it, i), ofs); } - //This operator is meant to be used in case heavy data should transferred to v_tgt. - void operator()(const typename TDS_src::Vertex& v_src, - typename TDS_tgt::Vertex& v_tgt) const - { - typedef typename CGAL::Kernel_traits< - typename TDS_src::Vertex::Point>::Kernel GT_src; - typedef typename CGAL::Kernel_traits< - typename TDS_tgt::Vertex::Point>::Kernel GT_tgt; - CGAL::Cartesian_converter conv; + ofs.close(); + } - v_tgt.set_point(conv(v_src.point())); - v_tgt.set_dimension(v_src.info()); - } - }; - - template - struct Cell_converter - { - //This operator is used to create the cell from c_src. - typename TDS_tgt::Cell operator()(const typename TDS_src::Cell& c_src) const - { - typename TDS_tgt::Cell c_tgt; - c_tgt.info() = c_src.info(); - c_tgt.input_cell() = c_src; - c_tgt.set_time_stamp(-1); - return c_tgt; - } - //This operator is meant to be used in case heavy data should transferred to c_tgt. - void operator()(const typename TDS_src::Cell& c_src, - typename TDS_tgt::Cell& c_tgt) const - { - c_tgt.info() = c_src.info(); - c_tgt.input_cell() = c_src; - } - }; - - - }//end namespace helpers - - - namespace debug - { template void dump_surface_off(const Tr& tr, const char* filename) { @@ -814,17 +754,17 @@ namespace Tetrahedral_remeshing dump_cells(cells, indices, filename); } - template - void dump_edges(const VertexPairsSet& edges, const char* filename) - { - std::ofstream ofs(filename); - BOOST_FOREACH(typename VertexPairsSet::key_type vp, edges) - { - ofs << "2 " << vp.first->point() - << " " << vp.second->point() << std::endl; - } - ofs.close(); - } + //template + //void dump_edges(const VertexPairsSet& edges, const char* filename) + //{ + // std::ofstream ofs(filename); + // BOOST_FOREACH(typename VertexPairsSet::key_type vp, edges) + // { + // ofs << "2 " << vp.first->point() + // << " " << vp.second->point() << std::endl; + // } + // ofs.close(); + //} }// end namespace debug } diff --git a/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/triangulation_3_helpers.h b/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/triangulation_3_helpers.h index 2e3632448c9..79543e2d224 100644 --- a/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/triangulation_3_helpers.h +++ b/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/triangulation_3_helpers.h @@ -44,48 +44,6 @@ namespace CGAL { - namespace debug - { - template - void dump_facet(const Facet& f, OutputStream& os) - { - os << "4 "; - os << f.first->vertex((f.second + 1) % 4)->point() << " " - << f.first->vertex((f.second + 2) % 4)->point() << " " - << f.first->vertex((f.second + 3) % 4)->point() << " " - << f.first->vertex((f.second + 1) % 4)->point(); - os << std::endl; - } - - template - void dump_facets(const FacetRange& facets, const char* filename) - { - std::ofstream os(filename); - for (typename FacetRange::const_iterator fit = facets.begin(); - fit != facets.end(); ++fit) - { - typename FacetRange::value_type f = *fit; - dump_facet(f, os); - } - } - - template - void dump_polylines(const CellRange& cells, const char* filename) - { - std::ofstream ofs(filename); - if (!ofs) return; - - for (typename CellRange::const_iterator it = cells.begin(); - it != cells.end(); ++it) - { - for (int i = 0; i < 4; ++i) - dump_facet(std::make_pair(*it, i), ofs); - } - ofs.close(); - } - - } // end namespace debug (in ::CGAL) - template CGAL::Point_3 point(const CGAL::Point_3& p) { @@ -705,73 +663,6 @@ namespace CGAL return oit; } -namespace internal -{ - template - void add_to_incidence_map(const typename Tr::Cell_handle& c, - const int& index, - IncidentFacetsMap& incidence_map, - const bool verbose = false) - { - CGAL_USE(verbose); - typedef typename IncidentFacetsMap::key_type Vertex_set; - Vertex_set vertices; - vertices.insert(c->vertex((index + 1) % 4)); - vertices.insert(c->vertex((index + 2) % 4)); - vertices.insert(c->vertex((index + 3) % 4)); - CGAL_assertion(vertices.size() == 3); - - typename IncidentFacetsMap::iterator it = incidence_map.find(vertices); - if (it == incidence_map.end()) - { - std::vector facets(1); - facets[0] = typename Tr::Facet(c, index); - incidence_map.insert(std::make_pair(vertices, facets)); - } - else - { - it->second.push_back(typename Tr::Facet(c, index)); - - CGAL_assertion(it->second.size() == 2); - CGAL_assertion(it->second[0] != it->second[1]); - } - } - - template - typename Tr::Cell_handle - create_neighbor_infinite_cell(const typename Tr::Cell_handle c, - const int i, - Tr& tr) - { - CGAL_assertion(!tr.is_infinite(c)); - CGAL_assertion_code(std::size_t nbc = tr.number_of_cells()); - - typedef typename Tr::Cell_handle Cell_handle; - Cell_handle opp_c; - // the infinite cell that we are creating needs to be well oriented - if (i == 0 || i == 2) - { - opp_c = create_cell(c->vertex((i + 3) % 4), - tr.infinite_vertex(), - c->vertex((i + 1) % 4), - c->vertex((i + 2) % 4), tr); - } - else - { - opp_c = create_cell(tr.infinite_vertex(), - c->vertex((i + 1) % 4), - c->vertex((i + 2) % 4), - c->vertex((i + 3) % 4), tr); - } - tr.infinite_vertex()->set_cell(opp_c); - - CGAL_assertion(nbc + 1 == tr.number_of_cells()); - return opp_c; - } - - -}//end namespace internal - }//end namespace CGAL #endif //CGAL_TRIANGULATION_3_HELPERS_H From 0281777dae70e88b15f43c19eedda9372a897490 Mon Sep 17 00:00:00 2001 From: Jane Tournois Date: Tue, 1 Oct 2019 17:01:24 +0200 Subject: [PATCH 025/568] more cleaning of helper files (merged) --- .../Remeshing_triangulation_3.h | 55 + .../internal/add_imaginary_layer.h | 2 - .../internal/collapse_short_edges.h | 8 +- .../internal/flip_edges.h | 6 +- .../internal/smooth_vertices.h | 9 +- .../internal/split_long_edges.h | 2 +- .../tetrahedral_adaptive_remeshing_impl.h | 5 +- .../internal/tetrahedral_remeshing_helpers.h | 1134 +++++++++++++---- .../internal/triangulation_3_helpers.h | 668 ---------- 9 files changed, 937 insertions(+), 952 deletions(-) delete mode 100644 Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/triangulation_3_helpers.h diff --git a/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/Remeshing_triangulation_3.h b/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/Remeshing_triangulation_3.h index e781e8502ff..0ea799be762 100644 --- a/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/Remeshing_triangulation_3.h +++ b/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/Remeshing_triangulation_3.h @@ -121,6 +121,61 @@ namespace Tetrahedral_remeshing } + template + struct Vertex_converter + { + //This operator is used to create the vertex from v_src. + typename TDS_tgt::Vertex operator()(const typename TDS_src::Vertex& v_src) const + { + typedef typename CGAL::Kernel_traits< + typename TDS_src::Vertex::Point>::Kernel GT_src; + typedef typename CGAL::Kernel_traits< + typename TDS_tgt::Vertex::Point>::Kernel GT_tgt; + CGAL::Cartesian_converter conv; + + typename TDS_tgt::Vertex v_tgt; + v_tgt.set_point(conv(v_src.point())); + v_tgt.set_time_stamp(-1); + v_tgt.set_dimension(v_src.info());//-1 if unset, 0,1,2, or 3 if set + return v_tgt; + } + //This operator is meant to be used in case heavy data should transferred to v_tgt. + void operator()(const typename TDS_src::Vertex& v_src, + typename TDS_tgt::Vertex& v_tgt) const + { + typedef typename CGAL::Kernel_traits< + typename TDS_src::Vertex::Point>::Kernel GT_src; + typedef typename CGAL::Kernel_traits< + typename TDS_tgt::Vertex::Point>::Kernel GT_tgt; + CGAL::Cartesian_converter conv; + + v_tgt.set_point(conv(v_src.point())); + v_tgt.set_dimension(v_src.info()); + } + }; + + template + struct Cell_converter + { + //This operator is used to create the cell from c_src. + typename TDS_tgt::Cell operator()(const typename TDS_src::Cell& c_src) const + { + typename TDS_tgt::Cell c_tgt; + c_tgt.info() = c_src.info(); + c_tgt.input_cell() = c_src; + c_tgt.set_time_stamp(-1); + return c_tgt; + } + //This operator is meant to be used in case heavy data should transferred to c_tgt. + void operator()(const typename TDS_src::Cell& c_src, + typename TDS_tgt::Cell& c_tgt) const + { + c_tgt.info() = c_src.info(); + c_tgt.input_cell() = c_src; + } + }; + + template void build_remeshing_triangulation(const T3& tr, Remeshing_triangulation_3& remeshing_tr) diff --git a/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/add_imaginary_layer.h b/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/add_imaginary_layer.h index 59c796333cd..db0a5760257 100644 --- a/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/add_imaginary_layer.h +++ b/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/add_imaginary_layer.h @@ -25,8 +25,6 @@ #include #include -#include - #include #include #include diff --git a/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/collapse_short_edges.h b/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/collapse_short_edges.h index d58482d8799..bf1f8844e1c 100644 --- a/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/collapse_short_edges.h +++ b/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/collapse_short_edges.h @@ -344,7 +344,7 @@ namespace internal { bool update_v0 = false; bool update_v1 = false; - helpers::get_edge_info(edge, update_v0, update_v1, c3t3, cell_selector); + get_edge_info(edge, update_v0, update_v1, c3t3, cell_selector); if (update_v0 && update_v1) return TO_MIDPOINT; else if (update_v0) return TO_V1; @@ -496,8 +496,8 @@ namespace internal // return false; //} //we need to check that surfaces are not broken anyhow - bool v0_boundary = helpers::is_boundary_vertex(v0, c3t3, cell_selector); - bool v1_boundary = helpers::is_boundary_vertex(v1, c3t3, cell_selector); + bool v0_boundary = is_boundary_vertex(v0, c3t3, cell_selector); + bool v1_boundary = is_boundary_vertex(v1, c3t3, cell_selector); if (collapse_type == TO_V0 && v1_boundary && !v0_boundary) return false; if (collapse_type == TO_V1 && v0_boundary && !v1_boundary) @@ -903,7 +903,7 @@ namespace internal { if (c3t3.is_in_complex(e)) return false; - else if (helpers::is_boundary(c3t3, e, cell_selector)) + else if (is_boundary(c3t3, e, cell_selector)) return false; #ifdef CGAL_TETRAHEDRAL_REMESHING_DEBUG diff --git a/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/flip_edges.h b/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/flip_edges.h index b81c011d01c..15f3507ef64 100644 --- a/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/flip_edges.h +++ b/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/flip_edges.h @@ -1141,9 +1141,9 @@ namespace internal std::cout << "\tInside flips" << std::endl; #endif std::vector inside_edges; - CGAL::get_inside_edges(c3t3, imaginary_index, - cell_selector, - std::back_inserter(inside_edges)); + get_inside_edges(c3t3, imaginary_index, + cell_selector, + std::back_inserter(inside_edges)); //if (criterion == VALENCE_BASED) // flip_inside_edges(inside_edges); diff --git a/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/smooth_vertices.h b/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/smooth_vertices.h index 9b56db118e2..111db448e02 100644 --- a/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/smooth_vertices.h +++ b/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/smooth_vertices.h @@ -54,7 +54,7 @@ namespace internal if (si != si_mirror || tr.is_infinite(ch) || tr.is_infinite(n_ch)) { - Surface_patch_index surf_i = helpers::make_surface_patch_index(si, si_mirror); + Surface_patch_index surf_i = make_surface_patch_index(si, si_mirror); for (int i = 0; i < 3; ++i) { Vertex_handle v_id = fit->first->vertex(indices(fit->second ,i)); @@ -74,7 +74,7 @@ namespace internal if (si != si_mirror || tr.is_infinite(ch) || tr.is_infinite(n_ch)) { - Surface_patch_index surf_i = helpers::make_surface_patch_index(si, si_mirror); + Surface_patch_index surf_i = make_surface_patch_index(si, si_mirror); Vector_3 n = CGAL::normal(*fit, tr.geom_traits()); @@ -225,7 +225,7 @@ namespace internal std::size_t nbe = 0; BOOST_FOREACH(Edge e, edges) { - if (CGAL::is_on_domain_hull(e, c3t3, imaginary_index)) + if (is_on_domain_hull(e, c3t3, imaginary_index)) { Vertex_handle ve = (e.first->vertex(e.second) != v) ? e.first->vertex(e.second) @@ -328,7 +328,8 @@ namespace internal switch (vit->in_dimension()) { case 3: - if (is_imaginary(vit, c3t3, imaginary_index) || !is_selected(vit, c3t3, cell_selector)) + if ( is_imaginary(vit, c3t3, imaginary_index) + || !is_selected(vit, c3t3, cell_selector)) break; else smoothing_vecs[vertex_id.at(vit)] = move_3d(vit, c3t3); diff --git a/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/split_long_edges.h b/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/split_long_edges.h index e069ab6c5b1..881c163c1b1 100644 --- a/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/split_long_edges.h +++ b/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/split_long_edges.h @@ -127,7 +127,7 @@ namespace internal { if (c3t3.is_in_complex(e)) return false; - else if (helpers::is_boundary(c3t3, e, cell_selector)) + else if (is_boundary(c3t3, e, cell_selector)) return false; #ifdef CGAL_TETRAHEDRAL_REMESHING_DEBUG diff --git a/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/tetrahedral_adaptive_remeshing_impl.h b/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/tetrahedral_adaptive_remeshing_impl.h index 48c9ac28c9f..a4973fd4cba 100644 --- a/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/tetrahedral_adaptive_remeshing_impl.h +++ b/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/tetrahedral_adaptive_remeshing_impl.h @@ -227,7 +227,7 @@ namespace internal if (m_protect_boundaries) { if( m_c3t3.is_in_complex(e) - || helpers::is_boundary(m_c3t3, e, m_cell_selector)) + || is_boundary(m_c3t3, e, m_cell_selector)) continue; } // skip imaginary edges @@ -389,7 +389,8 @@ namespace internal vit != tr().finite_vertices_end(); ++vit) { - if (vit->in_dimension() == 0 || nb_incident_complex_edges(vit, m_c3t3) > 2) + if ( vit->in_dimension() == 0 + || nb_incident_complex_edges(vit, m_c3t3) > 2) { m_c3t3.add_to_complex(vit, ++corner_id); diff --git a/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/tetrahedral_remeshing_helpers.h b/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/tetrahedral_remeshing_helpers.h index 8d39adb0533..ed2e4b156a8 100644 --- a/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/tetrahedral_remeshing_helpers.h +++ b/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/tetrahedral_remeshing_helpers.h @@ -24,7 +24,9 @@ #include -#include +#include +#include +#include namespace CGAL { @@ -34,326 +36,922 @@ namespace Tetrahedral_remeshing enum Sliver_removal_result { INVALID_ORIENTATION, INVALID_CELL, INVALID_VERTEX, NOT_FLIPPABLE, EDGE_PROBLEM, VALID_FLIP, NO_BEST_CONFIGURATION, EXISTING_EDGE }; - - namespace helpers + template + CGAL::Point_3 point(const CGAL::Point_3& p) { - template - bool is_boundary(const C3T3& c3t3, - const typename C3T3::Triangulation::Edge& e, - CellSelector cell_selector) + return p; + } + template + CGAL::Point_3 point(const CGAL::Weighted_point_3& wp) + { + typename K::Construct_point_3 pt = K().construct_point_3_object(); + return pt(wp); + } + + template + CGAL::Vector_3 vec(const CGAL::Point_3& p) + { + typename K::Construct_vector_3 v = K().construct_vector_3_object(); + return v(CGAL::ORIGIN, p); + } + template + CGAL::Vector_3 vec(const CGAL::Weighted_point_3& wp) + { + return vec(point(wp)); + } + + + const int indices_table[4][3] = { { 3, 1, 2 }, + { 3, 2, 0 }, + { 3, 0, 1 }, + { 2, 1, 0 } }; + + int indices(const int& i, const int& j) + { + CGAL_assertion(i >= 0 && i < 4); + CGAL_assertion(j >= 0 && j < 3); + return indices_table[i][j]; + } + + template + typename Gt::FT dihedral_angle(const CGAL::Point_3& p, + const CGAL::Point_3& q, + const CGAL::Point_3& r, + const CGAL::Point_3& s) + { + return Gt().compute_approximate_dihedral_angle_3_object()(p, q, r, s); + } + + template + typename Gt::FT min_dihedral_angle(const CGAL::Point_3& p, + const CGAL::Point_3& q, + const CGAL::Point_3& r, + const CGAL::Point_3& s) + { + typedef typename Gt::FT FT; + FT a = CGAL::abs(dihedral_angle(p, q, r, s)); + FT min_dh = a; + + a = CGAL::abs(dihedral_angle(p, r, q, s)); + min_dh = (std::min)(a, min_dh); + + a = CGAL::abs(dihedral_angle(p, s, q, r)); + min_dh = (std::min)(a, min_dh); + + a = CGAL::abs(dihedral_angle(q, r, p, s)); + min_dh = (std::min)(a, min_dh); + + a = CGAL::abs(dihedral_angle(q, s, p, r)); + min_dh = (std::min)(a, min_dh); + + a = CGAL::abs(dihedral_angle(r, s, p, q)); + min_dh = (std::min)(a, min_dh); + + return min_dh; + } + + template + typename Gt::FT min_dihedral_angle(VertexHandle v0, + VertexHandle v1, + VertexHandle v2, + VertexHandle v3) + { + return min_dihedral_angle(point(v0->point()), + point(v1->point()), + point(v2->point()), + point(v3->point())); + } + + template + typename Gt::FT min_dihedral_angle(CellHandle c) + { + return min_dihedral_angle(point(c->vertex(0)->point()), + point(c->vertex(1)->point()), + point(c->vertex(2)->point()), + point(c->vertex(3)->point())); + } + + template + std::pair + make_vertex_pair(const typename Tr::Edge& e) + { + typedef typename Tr::Vertex_handle Vertex_handle; + Vertex_handle v1 = e.first->vertex(e.second); + Vertex_handle v2 = e.first->vertex(e.third); + if (v2 < v1) std::swap(v1, v2); + + return std::make_pair(v1, v2); + } + + template + std::pair make_vertex_pair(const Vh v1, const Vh v2) + { + if (v2 < v1) return std::make_pair(v2, v1); + else return std::make_pair(v1, v2); + } + + template + CGAL::Triple make_vertex_triple(const Vh vh0, const Vh vh1, const Vh vh2) + { + CGAL::Triple ft(vh0, vh1, vh2); + if (ft.template get<1>() < ft.template get<0>()) std::swap(ft.template get<0>(), ft.template get<1>()); + if (ft.template get<2>() < ft.template get<1>()) std::swap(ft.template get<1>(), ft.template get<2>()); + if (ft.template get<1>() < ft.template get<0>()) std::swap(ft.template get<0>(), ft.template get<1>()); + return ft; + } + + template + bool is_on_feature(const VertexHandle v) + { + return (v->in_dimension() == 1); + } + + template + CGAL::Orientation orientation(const CellHandle ch) + { + return CGAL::orientation(point(ch->vertex(0)->point()), + point(ch->vertex(1)->point()), + point(ch->vertex(2)->point()), + point(ch->vertex(3)->point())); + } + + template + bool is_well_oriented(const CellHandle ch) + { + return CGAL::POSITIVE == orientation(ch); + } + + template + bool is_well_oriented(const VertexHandle v0, const VertexHandle v1, + const VertexHandle v2, const VertexHandle v3) + { + return CGAL::POSITIVE == CGAL::orientation(point(v0->point()), + point(v1->point()), + point(v2->point()), + point(v3->point())); + } + + + template + bool is_boundary(const C3T3& c3t3, + const typename C3T3::Triangulation::Edge& e, + CellSelector cell_selector) + { + typedef typename C3T3::Triangulation Tr; + typedef typename Tr::Facet_circulator Facet_circulator; + typedef typename Tr::Facet Facet; + + Facet_circulator fcirc = c3t3.triangulation().incident_facets(e); + Facet_circulator fend = fcirc; + std::vector boundary_facets; + + do { - typedef typename C3T3::Triangulation Tr; - typedef typename Tr::Facet_circulator Facet_circulator; - typedef typename Tr::Facet Facet; + Facet f = *fcirc; + if (c3t3.is_in_complex(f)) + return true; + else if (cell_selector(f.first) // XOR + ^ cell_selector(f.first->neighbor(f.second))) + return true; + else if (c3t3.triangulation().is_infinite(f) //XOR + ^ c3t3.triangulation().is_infinite(f.first->neighbor(f.second))) + return true; - Facet_circulator fcirc = c3t3.triangulation().incident_facets(e); - Facet_circulator fend = fcirc; - std::vector boundary_facets; + ++fcirc; + } while (fcirc != fend); - do - { - Facet f = *fcirc; - if (c3t3.is_in_complex(f)) - return true; - else if (cell_selector(f.first) // XOR - ^ cell_selector(f.first->neighbor(f.second))) - return true; - else if (c3t3.triangulation().is_infinite(f) //XOR - ^ c3t3.triangulation().is_infinite(f.first->neighbor(f.second))) - return true; + return false; + } - ++fcirc; - } while (fcirc != fend); + template + bool is_boundary_edge(const typename C3t3::Vertex_handle& v0, + const typename C3t3::Vertex_handle& v1, + const C3t3& c3t3, + CellSelector cell_selector) + { + typedef typename C3t3::Edge Edge; + typedef typename C3t3::Cell_handle Cell_handle; + Cell_handle cell; + int i0, i1; + if (c3t3.triangulation().tds().is_edge(v0, v1, cell, i0, i1)) + return is_boundary(c3t3, Edge(cell, i0, i1), cell_selector); + else return false; - } + } - template - bool is_boundary_edge(const typename C3t3::Vertex_handle& v0, - const typename C3t3::Vertex_handle& v1, - const C3t3& c3t3, - CellSelector cell_selector) + template + bool is_boundary_vertex(const typename C3t3::Vertex_handle& v, + const C3t3& c3t3, + CellSelector cell_selector) + { + typedef typename C3t3::Facet Facet; + std::vector facets; + c3t3.triangulation().incident_facets(v, std::back_inserter(facets)); + + BOOST_FOREACH(Facet f, facets) { - typedef typename C3t3::Edge Edge; - typedef typename C3t3::Cell_handle Cell_handle; - - Cell_handle cell; - int i0, i1; - if (c3t3.triangulation().tds().is_edge(v0, v1, cell, i0, i1)) - return is_boundary(c3t3, Edge(cell, i0, i1), cell_selector); - else - return false; + if (c3t3.is_in_complex(f)) + return true; + if (cell_selector(f.first) ^ cell_selector(f.first->neighbor(f.second))) + return true; } + return false; + } - template - bool is_boundary_vertex(const typename C3t3::Vertex_handle& v, - const C3t3& c3t3, - CellSelector cell_selector) - { - typedef typename C3t3::Facet Facet; - std::vector facets; - c3t3.triangulation().incident_facets(v, std::back_inserter(facets)); + template + bool is_edge_in_complex(const typename C3t3::Vertex_handle& v0, + const typename C3t3::Vertex_handle& v1, + const C3t3& c3t3, + CellSelector /*cell_selector*/) + { + typedef typename C3t3::Edge Edge; + typedef typename C3t3::Cell_handle Cell_handle; - BOOST_FOREACH(Facet f, facets) - { - if (c3t3.is_in_complex(f)) - return true; - if (cell_selector(f.first) ^ cell_selector(f.first->neighbor(f.second))) - return true; - } + Cell_handle cell; + int i0, i1; + if (c3t3.triangulation().tds().is_edge(v0, v1, cell, i0, i1)) + return c3t3.is_in_complex(Edge(cell, i0, i1)); + else return false; - } + } - template - bool is_edge_in_complex(const typename C3t3::Vertex_handle& v0, - const typename C3t3::Vertex_handle& v1, - const C3t3& c3t3, - CellSelector /*cell_selector*/) + template + bool topology_test(const typename C3t3::Edge& edge, + const C3t3& c3t3, + CellSelector cell_selector) + { + typedef typename C3t3::Vertex_handle Vertex_handle; + typedef typename C3t3::Triangulation::Facet_circulator Facet_circulator; + typedef typename C3t3::Subdomain_index Subdomain_index; + + Vertex_handle v0 = edge.first->vertex(edge.second); + Vertex_handle v1 = edge.first->vertex(edge.third); + + Facet_circulator fcirc = c3t3.triangulation().incident_facets(edge); + Facet_circulator fdone = fcirc; + do { - typedef typename C3t3::Edge Edge; - typedef typename C3t3::Cell_handle Cell_handle; + if (c3t3.triangulation().is_infinite(fcirc->first)) + continue; - Cell_handle cell; - int i0, i1; - if (c3t3.triangulation().tds().is_edge(v0, v1, cell, i0, i1)) - return c3t3.is_in_complex(Edge(cell, i0, i1)); - else - return false; - } - - template - bool topology_test(const typename C3t3::Edge& edge, - const C3t3& c3t3, - CellSelector cell_selector) - { - typedef typename C3t3::Vertex_handle Vertex_handle; - typedef typename C3t3::Triangulation::Facet_circulator Facet_circulator; - typedef typename C3t3::Subdomain_index Subdomain_index; - - Vertex_handle v0 = edge.first->vertex(edge.second); - Vertex_handle v1 = edge.first->vertex(edge.third); - - Facet_circulator fcirc = c3t3.triangulation().incident_facets(edge); - Facet_circulator fdone = fcirc; - do + Subdomain_index si_circ = fcirc->first->subdomain_index(); + Subdomain_index si_neigh = fcirc->first->neighbor(fcirc->second)->subdomain_index(); + if (si_circ == si_neigh) { - if (c3t3.triangulation().is_infinite(fcirc->first)) - continue; - - Subdomain_index si_circ = fcirc->first->subdomain_index(); - Subdomain_index si_neigh = fcirc->first->neighbor(fcirc->second)->subdomain_index(); - if (si_circ == si_neigh) + //Get the ids of the opposite vertices + for (int i = 1; i < 4; i++) { - //Get the ids of the opposite vertices - for (int i = 1; i < 4; i++) + Vertex_handle vi = fcirc->first->vertex((fcirc->second + i) % 4); + if (vi != v0 && vi != v1 && nb_incident_subdomains(vi, c3t3) > 1) { - Vertex_handle vi = fcirc->first->vertex((fcirc->second + i) % 4); - if (vi != v0 && vi != v1 && nb_incident_subdomains(vi, c3t3) > 1) - { - if (is_edge_in_complex(v0, vi, c3t3, cell_selector) - && is_edge_in_complex(v1, vi, c3t3, cell_selector)) - return false; - } + if (is_edge_in_complex(v0, vi, c3t3, cell_selector) + && is_edge_in_complex(v1, vi, c3t3, cell_selector)) + return false; } } - } while (++fcirc != fdone); + } + } while (++fcirc != fdone); - return true; - } + return true; + } - template - Subdomain_relation compare_subdomains(typename C3t3::Vertex_handle v0, - typename C3t3::Vertex_handle v1, - const C3t3& c3t3) + template + Subdomain_relation compare_subdomains(typename C3t3::Vertex_handle v0, + typename C3t3::Vertex_handle v1, + const C3t3& c3t3) + { + typedef typename C3t3::Subdomain_index Subdomain_index; + + std::vector subdomains_v0; + incident_subdomains(v0, c3t3, std::back_inserter(subdomains_v0)); + std::sort(subdomains_v0.begin(), subdomains_v0.end()); + + std::vector subdomains_v1; + incident_subdomains(v1, c3t3, std::back_inserter(subdomains_v1)); + std::sort(subdomains_v1.begin(), subdomains_v1.end()); + + if (subdomains_v0.size() == subdomains_v1.size()) { - typedef typename C3t3::Subdomain_index Subdomain_index; + for (unsigned int i = 0; i < subdomains_v0.size(); i++) + if (subdomains_v0[i] != subdomains_v1[i]) + return DIFFERENT; + return EQUAL; + } + else + { + std::vector + intersection((std::min)(subdomains_v0.size(), subdomains_v1.size()), -1); + typename std::vector::iterator + end_it = std::set_intersection(subdomains_v0.begin(), subdomains_v0.end(), + subdomains_v1.begin(), subdomains_v1.end(), + intersection.begin()); + std::ptrdiff_t intersection_size = (end_it - intersection.begin()); - std::vector subdomains_v0; - incident_subdomains(v0, c3t3, std::back_inserter(subdomains_v0)); - std::sort(subdomains_v0.begin(), subdomains_v0.end()); - - std::vector subdomains_v1; - incident_subdomains(v1, c3t3, std::back_inserter(subdomains_v1)); - std::sort(subdomains_v1.begin(), subdomains_v1.end()); - - if (subdomains_v0.size() == subdomains_v1.size()) + if (subdomains_v0.size() > subdomains_v1.size() + && intersection_size == std::ptrdiff_t(subdomains_v1.size())) { - for (unsigned int i = 0; i < subdomains_v0.size(); i++) - if (subdomains_v0[i] != subdomains_v1[i]) - return DIFFERENT; - return EQUAL; + return INCLUDES; + } + else if (intersection_size == std::ptrdiff_t(subdomains_v0.size())) { + return INCLUDED; + } + } + return DIFFERENT; + } + + + + template + void get_edge_info(const typename C3t3::Edge& edge, + bool& update_v0, + bool& update_v1, + const C3t3& c3t3, + CellSelector cell_selector) + { + typedef typename C3t3::Vertex_handle Vertex_handle; + + Vertex_handle v0 = edge.first->vertex(edge.second); + Vertex_handle v1 = edge.first->vertex(edge.third); + + int dim0 = c3t3.in_dimension(v0); + int dim1 = c3t3.in_dimension(v1); + + std::size_t nb_si_v0 = nb_incident_subdomains(v0, c3t3); + std::size_t nb_si_v1 = nb_incident_subdomains(v1, c3t3); + + update_v0 = false; + update_v1 = false; + + bool is_v0_on_hull = is_on_hull(v0, c3t3); + bool is_v1_on_hull = is_on_hull(v1, c3t3); + + //Same type imaginary or inside vertices + if (dim0 == 3 && dim1 == 3) + { + if (is_v0_on_hull && is_v1_on_hull)//both endvertices are on hull + { + if (is_on_hull(edge, c3t3)) //edge also is on hull + { + update_v0 = true; + update_v1 = true; + } } else { - std::vector - intersection((std::min)(subdomains_v0.size(), subdomains_v1.size()), -1); - typename std::vector::iterator - end_it = std::set_intersection(subdomains_v0.begin(), subdomains_v0.end(), - subdomains_v1.begin(), subdomains_v1.end(), - intersection.begin()); - std::ptrdiff_t intersection_size = (end_it - intersection.begin()); + if (!is_v0_on_hull) //v0 not on hull + update_v0 = true; + if (!is_v1_on_hull) //v1 not on hull + update_v1 = true; + } + return; + } + //Feature edge case + if (nb_si_v0 > 2 && nb_si_v1 > 2) + { + if (c3t3.is_in_complex(edge)) + { + if (!topology_test(edge, c3t3, cell_selector)) + return; - if (subdomains_v0.size() > subdomains_v1.size() - && intersection_size == std::ptrdiff_t(subdomains_v1.size())) - { - return INCLUDES; + if (nb_si_v0 > nb_si_v1) { + update_v1 = true; } - else if (intersection_size == std::ptrdiff_t(subdomains_v0.size())) { - return INCLUDED; + else if (nb_si_v1 > nb_si_v0) { + update_v0 = true; + } + else { + update_v0 = true; + update_v1 = true; } } - return DIFFERENT; + return; } - - - template - void get_edge_info(const typename C3t3::Edge& edge, - bool& update_v0, - bool& update_v1, - const C3t3& c3t3, - CellSelector cell_selector) + if (dim0 == 2 && dim1 == 2) { - typedef typename C3t3::Vertex_handle Vertex_handle; - - Vertex_handle v0 = edge.first->vertex(edge.second); - Vertex_handle v1 = edge.first->vertex(edge.third); - - int dim0 = c3t3.in_dimension(v0); - int dim1 = c3t3.in_dimension(v1); - - std::size_t nb_si_v0 = nb_incident_subdomains(v0, c3t3); - std::size_t nb_si_v1 = nb_incident_subdomains(v1, c3t3); - - update_v0 = false; - update_v1 = false; - - bool is_v0_on_hull = is_on_hull(v0, c3t3); - bool is_v1_on_hull = is_on_hull(v1, c3t3); - - //Same type imaginary or inside vertices - if (dim0 == 3 && dim1 == 3) + if (is_boundary(c3t3, edge, cell_selector)) { - if (is_v0_on_hull && is_v1_on_hull)//both endvertices are on hull + if (!topology_test(edge, c3t3, cell_selector)) + return; + Subdomain_relation subdomain_rel = compare_subdomains(v0, v1, c3t3); + + //Vertices on the same surface + if (subdomain_rel == INCLUDES) { + update_v1 = true; + } + else if (subdomain_rel == INCLUDED) { + update_v0 = true; + } + else if (subdomain_rel == EQUAL) { - if (is_on_hull(edge, c3t3)) //edge also is on hull + if (c3t3.number_of_edges() == 0) { update_v0 = true; update_v1 = true; } - } - else - { - if (!is_v0_on_hull) //v0 not on hull - update_v0 = true; - if (!is_v1_on_hull) //v1 not on hull - update_v1 = true; - } - return; - } - //Feature edge case - if (nb_si_v0 > 2 && nb_si_v1 > 2) - { - if (c3t3.is_in_complex(edge)) - { - if (!topology_test(edge, c3t3, cell_selector)) - return; - - if (nb_si_v0 > nb_si_v1) { - update_v1 = true; - } - else if (nb_si_v1 > nb_si_v0) { - update_v0 = true; - } - else { - update_v0 = true; - update_v1 = true; - } - } - return; - } - - if (dim0 == 2 && dim1 == 2) - { - if (is_boundary(c3t3, edge, cell_selector)) - { - if (!topology_test(edge, c3t3, cell_selector)) - return; - Subdomain_relation subdomain_rel = compare_subdomains(v0, v1, c3t3); - - //Vertices on the same surface - if (subdomain_rel == INCLUDES) { - update_v1 = true; - } - else if (subdomain_rel == INCLUDED) { - update_v0 = true; - } - else if (subdomain_rel == EQUAL) + else { - if (c3t3.number_of_edges() == 0) - { - update_v0 = true; - update_v1 = true; - } - else - { - bool v0_on_feature = is_on_feature(v0); - bool v1_on_feature = is_on_feature(v1); + bool v0_on_feature = is_on_feature(v0); + bool v1_on_feature = is_on_feature(v1); - if (v0_on_feature && v1_on_feature) { - if (c3t3.is_in_complex(edge)) { - if (!c3t3.is_in_complex(v0)) - update_v0 = true; - if (!c3t3.is_in_complex(v1)) - update_v1 = true; - } - } - else { - if (!v0_on_feature) { + if (v0_on_feature && v1_on_feature) { + if (c3t3.is_in_complex(edge)) { + if (!c3t3.is_in_complex(v0)) update_v0 = true; - } - if (!v1_on_feature) { + if (!c3t3.is_in_complex(v1)) update_v1 = true; - } + } + } + else { + if (!v0_on_feature) { + update_v0 = true; + } + if (!v1_on_feature) { + update_v1 = true; } } } } - - return; - } - //In the case of mixte edges - if (dim0 == 2 && dim1 == 3 && !is_v1_on_hull) { - update_v1 = true; - return; } - if (dim1 == 2 && dim0 == 3 && !is_v0_on_hull) { - update_v0 = true; - return; - } + return; + } + //In the case of mixte edges + if (dim0 == 2 && dim1 == 3 && !is_v1_on_hull) { + update_v1 = true; + return; } - - template - void print_subdomain_indices(const C3T3& c3t3) - { - typedef typename C3T3::Triangulation Tr; - typedef typename Tr::Finite_cells_iterator Finite_cells_iterator; - - std::cout << "SUBDOMAINS : " << std::endl; - unsigned int line_id = 0; - for (Finite_cells_iterator cit = c3t3.triangulation().finite_cells_begin(); - cit != c3t3.triangulation().finite_cells_end(); - ++cit, ++line_id) - { - if (line_id % 10 == 0) - std::cout << std::endl; - std::cout << "\t" << cit->subdomain_index(); - } + if (dim1 == 2 && dim0 == 3 && !is_v0_on_hull) { + update_v0 = true; + return; } } + template + OutputIterator incident_subdomains(const typename C3t3::Vertex_handle v, + const C3t3& c3t3, + OutputIterator oit) + { + typedef typename C3t3::Triangulation::Cell_handle Cell_handle; + std::vector cells; + c3t3.triangulation().incident_cells(v, std::back_inserter(cells)); + + for (std::size_t i = 0; i < cells.size(); ++i) + *oit++ = cells[i]->subdomain_index(); + + return oit; + } + + template + OutputIterator incident_subdomains(const typename C3t3::Edge& e, + const C3t3& c3t3, + OutputIterator oit) + { + typedef typename C3t3::Triangulation::Cell_circulator Cell_circulator; + + Cell_circulator circ = c3t3.triangulation().incident_cells(e); + Cell_circulator end = circ; + do + { + *oit++ = circ->subdomain_index(); + } while (++circ != end); + + return oit; + } + + template + std::size_t nb_incident_subdomains(const typename C3t3::Vertex_handle v, + const C3t3& c3t3) + { + typedef typename C3t3::Subdomain_index Subdomain_index; + + boost::unordered_set indices; + incident_subdomains(v, c3t3, std::inserter(indices, indices.begin())); + + return indices.size(); + } + + template + std::size_t nb_incident_subdomains(const typename C3t3::Edge& e, + const C3t3& c3t3) + { + typedef typename C3t3::Subdomain_index Subdomain_index; + + boost::unordered_set indices; + incident_subdomains(e, c3t3, std::inserter(indices, indices.begin())); + + return indices.size(); + } + + template + std::size_t nb_incident_complex_edges(const typename C3t3::Vertex_handle v, + const C3t3& c3t3) + { + typedef typename C3t3::Edge Edge; + boost::unordered_set edges; + c3t3.triangulation().incident_edges(v, + std::inserter(edges, edges.begin())); + + std::size_t count = 0; + for (typename boost::unordered_set::iterator eit = edges.begin(); + eit != edges.end(); + ++eit) + { + if (c3t3.is_in_complex(*eit)) + ++count; + } + return count; + } + + + template + bool is_feature(const typename C3t3::Vertex_handle v, + const typename C3t3::Vertex_handle neighbor, + const C3t3& c3t3) + { + typename C3t3::Cell_handle ch; + int i0, i1; + if (c3t3.triangulation().is_edge(v, neighbor, ch, i0, i1)) + { + typename C3t3::Edge edge(ch, i0, i1); + return c3t3.is_in_complex(edge); + } + return false; + } + + template + bool is_feature(const typename C3t3::Vertex_handle v, const C3t3& c3t3) + { + typedef typename C3t3::Edge Edge; + + if (nb_incident_subdomains(v, c3t3) > 2) + { + std::vector edges; + c3t3.triangulation().finite_incident_edges(v, std::back_inserter(edges)); + + int feature_count = 0; + BOOST_FOREACH(Edge ei, edges) + { + if (c3t3.is_in_complex(ei)) + { + feature_count++; + if (feature_count >= 3) + return true; + } + } + } + else if (c3t3.number_of_corners() > 0) + { + return c3t3.is_in_complex(v); + } + return false; + } + + /** + * returns true iff `v` is on the outer hull of c3t3.triangulation() + * i.e. finite and incident to at least one infinite cell + */ + template + bool is_on_hull(const typename C3t3::Vertex_handle v, + const C3t3& c3t3) + { + if (v == c3t3.triangulation().infinite_vertex()) + return true; + + //on hull == incident to infinite cell + typedef typename C3t3::Triangulation::Cell_handle Cell_handle; + + std::vector cells; + c3t3.triangulation().incident_cells(v, std::back_inserter(cells)); + for (std::size_t i = 0; i < cells.size(); ++i) + { + if (c3t3.triangulation().is_infinite(cells[i])) + return true; + } + return false; + } + + template + bool is_on_domain_hull(const typename C3t3::Vertex_handle v, + const C3t3& c3t3, + const typename C3t3::Subdomain_index& imaginary_index) + { + if (v == c3t3.triangulation().infinite_vertex()) + return false; + + on hull == incident to infinite cell + typedef typename C3t3::Triangulation::Cell_handle Cell_handle; + + bool met_inside_cell = false; + bool met_outside_cell = false; + + std::vector cells; + c3t3.triangulation().incident_cells(v, std::back_inserter(cells)); + for (std::size_t i = 0; i < cells.size(); ++i) + { + if (c3t3.triangulation().is_infinite(cells[i]) + || !c3t3.is_in_complex(cells[i]) + || cells[i]->subdomain_index() == imaginary_index) + met_outside_cell = true; + else + met_inside_cell = true; + + if (met_inside_cell && met_outside_cell) + return true; + } + return false; + } + + /** + * returns true iff `edge` is on the outer hull + * of c3t3.triangulation() + * i.e. finite and incident to at least one infinite cell + */ + template + bool is_on_hull(const typename C3t3::Edge & edge, + const C3t3& c3t3) + { + typedef typename C3t3::Triangulation::Cell_circulator Cell_circulator; + Cell_circulator circ = c3t3.triangulation().incident_cells(edge); + Cell_circulator done = circ; + do + { + if (c3t3.triangulation().is_infinite(circ)) + return true; + } while (++circ != done); + + return false; + } + + template + bool is_on_domain_hull(const typename C3t3::Edge & edge, + const C3t3& c3t3, + const typename C3t3::Subdomain_index& imaginary_index) + { + typedef typename C3t3::Triangulation::Cell_circulator Cell_circulator; + + bool met_inside_cell = false; + bool met_outside_cell = false; + + Cell_circulator circ = c3t3.triangulation().incident_cells(edge); + Cell_circulator done = circ; + do + { + if (c3t3.triangulation().is_infinite(circ) + || !c3t3.is_in_complex(circ) + || circ->subdomain_index() == imaginary_index) + met_outside_cell = true; + else + met_inside_cell = true; + + if (met_inside_cell && met_outside_cell) + return true; + } while (++circ != done); + + return false; + } + + template + bool is_imaginary(const typename C3t3::Vertex_handle v, + const C3t3& c3t3, + const typename C3t3::Subdomain_index& imaginary_index) + { + typedef typename C3t3::Triangulation::Cell_handle Cell_handle; + + std::vector cells; + c3t3.triangulation().incident_cells(v, std::back_inserter(cells)); + + BOOST_FOREACH(Cell_handle c, cells) + { + if (c->subdomain_index() != imaginary_index) + return false; + } + return true; + } + + /** + * returns true off edge is fully imaginary + * i.e. if all its incident cells are not in the complex, + * and have their subdomain index == imaginary_index + */ + template + bool is_imaginary(const typename C3t3::Edge & edge, + const C3t3& c3t3, + const typename C3t3::Subdomain_index& imaginary_index) + { + typedef typename C3t3::Triangulation::Cell_circulator Cell_circulator; + Cell_circulator circ = c3t3.triangulation().incident_cells(edge); + Cell_circulator done = circ; + do + { + if (c3t3.is_in_complex(circ) + && circ->subdomain_index() != imaginary_index) + return false; + } while (++circ != done); + + return true; + } + + template + bool is_outside(const typename C3t3::Edge & edge, + const C3t3& c3t3, + const typename C3t3::Subdomain_index& imaginary_index, + CellSelector cell_selector) + { + typedef typename C3t3::Triangulation::Cell_circulator Cell_circulator; + Cell_circulator circ = c3t3.triangulation().incident_cells(edge); + Cell_circulator done = circ; + do + { + // is cell infinite? + if (c3t3.triangulation().is_infinite(circ)) + continue; + // is cell imaginary? + if (c3t3.is_in_complex(circ) && circ->subdomain_index() == imaginary_index) + continue; + // circ does not belong to the selection + if (!cell_selector(circ)) + continue; + + // none of the above conditions was met + return false; + } while (circ != done); + + return true; //all cells have met the loop conditions + } + + template + bool is_selected(const typename C3t3::Vertex_handle v, + const C3t3& c3t3, + CellSelector cell_selector) + { + typedef typename C3t3::Triangulation::Cell_handle Cell_handle; + + std::vector cells; + c3t3.triangulation().incident_cells(v, std::back_inserter(cells)); + + BOOST_FOREACH(Cell_handle c, cells) + { + if (!cell_selector(c)) + return false; + } + return true; + } + + template + bool is_inside(const typename C3t3::Edge& edge, + const C3t3& c3t3, + const typename C3t3::Subdomain_index& imaginary_index, + CellSelector cell_selector) + { + typedef typename C3t3::Triangulation::Cell_circulator Cell_circulator; + Cell_circulator circ = c3t3.triangulation().incident_cells(edge); + Cell_circulator done = circ; + + const typename C3t3::Subdomain_index si = circ->subdomain_index(); + if (si == imaginary_index || !c3t3.is_in_complex(circ)) + return false; + do + { + if (c3t3.triangulation().is_infinite(circ)) + return false; + if (si != circ->subdomain_index()) + return false; + if (!cell_selector(circ)) + return false; + } while (++circ != done); + + return true; + } + + template + bool is_convex(const Tr& tr, + const CGAL::Iso_cuboid_3& bbox, + typename Tr::Facet& facet) + { + typedef typename Tr::Cell_handle Cell_handle; + typedef typename Tr::Vertex_handle Vertex_handle; + typedef typename Tr::Facet Facet; + typedef typename Tr::Finite_facets_iterator Finite_facets_iterator; + + for (Finite_facets_iterator fit = tr.finite_facets_begin(); + fit != tr.finite_facets_end(); ++fit) + { + Facet f = *fit; + Facet mf = tr.mirror_facet(f); + if (!tr.is_infinite(f.first) && !tr.is_infinite(mf.first)) + continue; + + if (tr.is_infinite(mf.first)) + f = mf; + CGAL_assertion(tr.is_infinite(f.first)); + + boost::array vs; + for (int i = 0; i < 3; ++i) + vs[i] = f.first->vertex((f.second + i + 1) % 4); + if (f.second % 2 == 0) + std::swap(vs[0], vs[1]); + + Cell_handle fin_c = f.first->neighbor(f.second); + Vertex_handle v4 = fin_c->vertex(fin_c->index(f.first)); + + CGAL_assertion(!tr.is_infinite(fin_c)); + CGAL_assertion(!f.first->has_vertex(v4)); + + CGAL_assertion(CGAL::NEGATIVE + == CGAL::orientation(vs[0]->point(), vs[1]->point(), + vs[2]->point(), v4->point())); + + for (int i = 1; i < 4; ++i) + { + nfi is neighbor of f on convex hull + Cell_handle ni = f.first->neighbor((f.second + i) % 4); + CGAL_assertion(tr.is_infinite(ni)); + + collect points + Vertex_handle v3 = ni->vertex(ni->index(f.first)); + CGAL_assertion(v3 != vs[0] && v3 != vs[1] && v3 != vs[2] + && v3 != tr.infinite_vertex()); + CGAL_assertion(!f.first->has_vertex(v3)); + + CGAL::Orientation o2 = CGAL::orientation(vs[0]->point(), + vs[1]->point(), vs[2]->point(), v3->point()); + if (o2 == CGAL::POSITIVE) + { + facet = f; + + if (!bbox.is_degenerate() + && bbox.has_on_boundary(vs[0]->point()) + && bbox.has_on_boundary(vs[1]->point()) + && bbox.has_on_boundary(vs[2]->point())) + { + facet = Facet(ni, ni->index(tr.infinite_vertex())); + } + + return false; + } + } + } + return true; + } + + template + bool is_convex(const Tr& tr) + { + typename Tr::Facet f; + typename Tr::Geom_traits::Iso_cuboid_3 bb(CGAL::ORIGIN, CGAL::ORIGIN); + return is_convex(tr, bb, f); + } + + template + typename Gt::Vector_3 normal(const Facet& f, const Gt& gt) + { + namespace PMP = CGAL::Polygon_mesh_processing; + typedef typename Gt::Vector_3 Vector; + typedef typename Gt::Point_3 Point; + + Point p0 = point(f.first->vertex((f.second + 1) % 4)->point()); + Point p1 = point(f.first->vertex((f.second + 2) % 4)->point()); + const Point& p2 = point(f.first->vertex((f.second + 3) % 4)->point()); + + if (f.second % 2 == 0)//equivalent to the commented orientation test + std::swap(p0, p1); + + Vector n = PMP::internal::triangle_normal(p0, p1, p2, gt); + + if (!typename Gt::Equal_3()(n, CGAL::NULL_VECTOR)) + PMP::internal::normalize(n, gt); + + return n; + } + + template + OutputIterator get_inside_edges(const C3t3& c3t3, + const typename C3t3::Subdomain_index& imaginary_index, + CellSelector cell_selector, + OutputIterator oit)/*holds pairs of Vertex_handles*/ + { + for (typename C3t3::Triangulation::Finite_edges_iterator + eit = c3t3.triangulation().finite_edges_begin(); + eit != c3t3.triangulation().finite_edges_end(); + ++eit) + { + const typename C3t3::Edge& e = *eit; +// if ( !c3t3.is_in_complex(e) +// && !is_boundary_edge(e, c3t3) +// && !is_on_hull(e, c3t3) +// && !is_imaginary(e, c3t3, imaginary_index)) + if (is_inside(e, c3t3, imaginary_index, cell_selector)) + { + *oit++ = make_vertex_pair(e); + } + } + return oit; + } + + namespace debug { // forward-declaration @@ -736,7 +1334,7 @@ namespace Tetrahedral_remeshing template void dump_without_imaginary(const Tr& tr, const char* filename, - const int imaginary_index) + const int imaginary_index) { std::vector cells; std::vector indices; @@ -765,9 +1363,9 @@ namespace Tetrahedral_remeshing // } // ofs.close(); //} - }// end namespace debug -} -} + } //namespace debug + } //namespace Tetrahedral_remeshing +} //namespace CGAL #endif //CGAL_INTERNAL_TET_REMESHING_HELPERS_H diff --git a/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/triangulation_3_helpers.h b/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/triangulation_3_helpers.h deleted file mode 100644 index 79543e2d224..00000000000 --- a/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/triangulation_3_helpers.h +++ /dev/null @@ -1,668 +0,0 @@ -// Copyright (c) 2018 GeometryFactory (France). -// All rights reserved. -// -// This file is part of CGAL (www.cgal.org). -// You can redistribute it and/or modify it under the terms of the GNU -// General Public License as published by the Free Software Foundation, -// either version 3 of the License, or (at your option) any later version. -// -// Licensees holding a valid commercial license may use this file in -// accordance with the commercial license agreement provided with the software. -// -// This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE -// WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. -// -// $URL$ -// $Id$ -// -// -// Author(s) : Jane Tournois -// -//****************************************************************************** -// -//****************************************************************************** - -#ifndef CGAL_TRIANGULATION_3_HELPERS_H -#define CGAL_TRIANGULATION_3_HELPERS_H - -#include -#include -#include -#include -#include -#include - -#include - -#include -#include - -#include -#include - -#include - -namespace CGAL -{ - template - CGAL::Point_3 point(const CGAL::Point_3& p) - { - return p; - } - template - CGAL::Point_3 point(const CGAL::Weighted_point_3& wp) - { - typename K::Construct_point_3 pt = K().construct_point_3_object(); - return pt(wp); - } - - template - CGAL::Vector_3 vec(const CGAL::Point_3& p) - { - typename K::Construct_vector_3 v = K().construct_vector_3_object(); - return v(CGAL::ORIGIN, p); - } - template - CGAL::Vector_3 vec(const CGAL::Weighted_point_3& wp) - { - return vec(point(wp)); - } - - - const int indices_table[4][3] = { { 3, 1, 2 }, - { 3, 2, 0 }, - { 3, 0, 1 }, - { 2, 1, 0 } }; - - int indices(const int& i, const int& j) - { - CGAL_assertion(i >= 0 && i < 4); - CGAL_assertion(j >= 0 && j < 3); - return indices_table[i][j]; - } - - template - typename Gt::FT dihedral_angle(const CGAL::Point_3& p, - const CGAL::Point_3& q, - const CGAL::Point_3& r, - const CGAL::Point_3& s) - { - return Gt().compute_approximate_dihedral_angle_3_object()(p,q,r,s); - } - - template - typename Gt::FT min_dihedral_angle(const CGAL::Point_3& p, - const CGAL::Point_3& q, - const CGAL::Point_3& r, - const CGAL::Point_3& s) - { - typedef typename Gt::FT FT; - FT a = CGAL::abs(dihedral_angle(p, q, r, s)); - FT min_dh = a; - - a = CGAL::abs(dihedral_angle(p, r, q, s)); - min_dh = (std::min)(a, min_dh); - - a = CGAL::abs(dihedral_angle(p, s, q, r)); - min_dh = (std::min)(a, min_dh); - - a = CGAL::abs(dihedral_angle(q, r, p, s)); - min_dh = (std::min)(a, min_dh); - - a = CGAL::abs(dihedral_angle(q, s, p, r)); - min_dh = (std::min)(a, min_dh); - - a = CGAL::abs(dihedral_angle(r, s, p, q)); - min_dh = (std::min)(a, min_dh); - - return min_dh; - } - - template - typename Gt::FT min_dihedral_angle(VertexHandle v0, - VertexHandle v1, - VertexHandle v2, - VertexHandle v3) - { - return min_dihedral_angle(point(v0->point()), - point(v1->point()), - point(v2->point()), - point(v3->point())); - } - - template - typename Gt::FT min_dihedral_angle(CellHandle c) - { - return min_dihedral_angle(point(c->vertex(0)->point()), - point(c->vertex(1)->point()), - point(c->vertex(2)->point()), - point(c->vertex(3)->point())); - } - - template - std::pair - make_vertex_pair(const typename Tr::Edge& e) - { - typedef typename Tr::Vertex_handle Vertex_handle; - Vertex_handle v1 = e.first->vertex(e.second); - Vertex_handle v2 = e.first->vertex(e.third); - if (v2 < v1) std::swap(v1, v2); - - return std::make_pair(v1, v2); - } - - template - std::pair make_vertex_pair(const Vh v1, const Vh v2) - { - if (v2 < v1) return std::make_pair(v2, v1); - else return std::make_pair(v1, v2); - } - - template - CGAL::Triple make_vertex_triple(const Vh vh0, const Vh vh1, const Vh vh2) - { - CGAL::Triple ft(vh0, vh1, vh2); - if (ft.template get<1>() < ft.template get<0>()) std::swap(ft.template get<0>(), ft.template get<1>()); - if (ft.template get<2>() < ft.template get<1>()) std::swap(ft.template get<1>(), ft.template get<2>()); - if (ft.template get<1>() < ft.template get<0>()) std::swap(ft.template get<0>(), ft.template get<1>()); - return ft; - } - - template - bool is_on_feature(const VertexHandle v) - { - return (v->in_dimension() == 1); - } - - template - CGAL::Orientation orientation(const CellHandle ch) - { - return CGAL::orientation(point(ch->vertex(0)->point()), - point(ch->vertex(1)->point()), - point(ch->vertex(2)->point()), - point(ch->vertex(3)->point())); - } - - template - bool is_well_oriented(const CellHandle ch) - { - return CGAL::POSITIVE == orientation(ch); - } - - template - bool is_well_oriented(const VertexHandle v0, const VertexHandle v1, - const VertexHandle v2, const VertexHandle v3) - { - return CGAL::POSITIVE == CGAL::orientation(point(v0->point()), point(v1->point()), - point(v2->point()), point(v3->point())); - } - - template - OutputIterator incident_subdomains(const typename C3t3::Vertex_handle v, - const C3t3& c3t3, - OutputIterator oit) - { - typedef typename C3t3::Triangulation::Cell_handle Cell_handle; - std::vector cells; - c3t3.triangulation().incident_cells(v, std::back_inserter(cells)); - - for (std::size_t i = 0; i < cells.size(); ++i) - *oit++ = cells[i]->subdomain_index(); - - return oit; - } - - template - OutputIterator incident_subdomains(const typename C3t3::Edge& e, - const C3t3& c3t3, - OutputIterator oit) - { - typedef typename C3t3::Triangulation::Cell_circulator Cell_circulator; - - Cell_circulator circ = c3t3.triangulation().incident_cells(e); - Cell_circulator end = circ; - do - { - *oit++ = circ->subdomain_index(); - } - while (++circ != end); - - return oit; - } - - template - std::size_t nb_incident_subdomains(const typename C3t3::Vertex_handle v, - const C3t3& c3t3) - { - typedef typename C3t3::Subdomain_index Subdomain_index; - - boost::unordered_set indices; - incident_subdomains(v, c3t3, std::inserter(indices, indices.begin())); - - return indices.size(); - } - - template - std::size_t nb_incident_subdomains(const typename C3t3::Edge& e, - const C3t3& c3t3) - { - typedef typename C3t3::Subdomain_index Subdomain_index; - - boost::unordered_set indices; - incident_subdomains(e, c3t3, std::inserter(indices, indices.begin())); - - return indices.size(); - } - - template - std::size_t nb_incident_complex_edges(const typename C3t3::Vertex_handle v, - const C3t3& c3t3) - { - typedef typename C3t3::Edge Edge; - boost::unordered_set edges; - c3t3.triangulation().incident_edges(v, - std::inserter(edges, edges.begin())); - - std::size_t count = 0; - for (typename boost::unordered_set::iterator eit = edges.begin(); - eit != edges.end(); - ++eit) - { - if (c3t3.is_in_complex(*eit)) - ++count; - } - return count; - } - - - template - bool is_feature(const typename C3t3::Vertex_handle v, - const typename C3t3::Vertex_handle neighbor, - const C3t3& c3t3) - { - typename C3t3::Cell_handle ch; - int i0, i1; - if (c3t3.triangulation().is_edge(v, neighbor, ch, i0, i1)) - { - typename C3t3::Edge edge(ch, i0, i1); - return c3t3.is_in_complex(edge); - } - return false; - } - - template - bool is_feature(const typename C3t3::Vertex_handle v, const C3t3& c3t3) - { - typedef typename C3t3::Edge Edge; - - if (nb_incident_subdomains(v, c3t3) > 2) - { - std::vector edges; - c3t3.triangulation().finite_incident_edges(v, std::back_inserter(edges)); - - int feature_count = 0; - BOOST_FOREACH(Edge ei, edges) - { - if (c3t3.is_in_complex(ei)) - { - feature_count++; - if (feature_count >= 3) - return true; - } - } - } - else if(c3t3.number_of_corners() > 0) - { - return c3t3.is_in_complex(v); - } - return false; - } - - /** - * returns true iff `v` is on the outer hull of c3t3.triangulation() - * i.e. finite and incident to at least one infinite cell - */ - template - bool is_on_hull(const typename C3t3::Vertex_handle v, - const C3t3& c3t3) - { - if (v == c3t3.triangulation().infinite_vertex()) - return true; - - //on hull == incident to infinite cell - typedef typename C3t3::Triangulation::Cell_handle Cell_handle; - - std::vector cells; - c3t3.triangulation().incident_cells(v, std::back_inserter(cells)); - for (std::size_t i = 0; i < cells.size(); ++i) - { - if (c3t3.triangulation().is_infinite(cells[i])) - return true; - } - return false; - } - - template - bool is_on_domain_hull(const typename C3t3::Vertex_handle v, - const C3t3& c3t3, - const typename C3t3::Subdomain_index& imaginary_index) - { - if (v == c3t3.triangulation().infinite_vertex()) - return false; - - //on hull == incident to infinite cell - typedef typename C3t3::Triangulation::Cell_handle Cell_handle; - - bool met_inside_cell = false; - bool met_outside_cell = false; - - std::vector cells; - c3t3.triangulation().incident_cells(v, std::back_inserter(cells)); - for (std::size_t i = 0; i < cells.size(); ++i) - { - if (c3t3.triangulation().is_infinite(cells[i]) - || !c3t3.is_in_complex(cells[i]) - || cells[i]->subdomain_index() == imaginary_index) - met_outside_cell = true; - else - met_inside_cell = true; - - if (met_inside_cell && met_outside_cell) - return true; - } - return false; - } - - /** - * returns true iff `edge` is on the outer hull - * of c3t3.triangulation() - * i.e. finite and incident to at least one infinite cell - */ - template - bool is_on_hull(const typename C3t3::Edge & edge, - const C3t3& c3t3) - { - typedef typename C3t3::Triangulation::Cell_circulator Cell_circulator; - Cell_circulator circ = c3t3.triangulation().incident_cells(edge); - Cell_circulator done = circ; - do - { - if (c3t3.triangulation().is_infinite(circ)) - return true; - } while (++circ != done); - - return false; - } - - template - bool is_on_domain_hull(const typename C3t3::Edge & edge, - const C3t3& c3t3, - const typename C3t3::Subdomain_index& imaginary_index) - { - typedef typename C3t3::Triangulation::Cell_circulator Cell_circulator; - - bool met_inside_cell = false; - bool met_outside_cell = false; - - Cell_circulator circ = c3t3.triangulation().incident_cells(edge); - Cell_circulator done = circ; - do - { - if (c3t3.triangulation().is_infinite(circ) - || !c3t3.is_in_complex(circ) - || circ->subdomain_index() == imaginary_index) - met_outside_cell = true; - else - met_inside_cell = true; - - if (met_inside_cell && met_outside_cell) - return true; - } while (++circ != done); - - return false; - } - - template - bool is_imaginary(const typename C3t3::Vertex_handle v, - const C3t3& c3t3, - const typename C3t3::Subdomain_index& imaginary_index) - { - typedef typename C3t3::Triangulation::Cell_handle Cell_handle; - - std::vector cells; - c3t3.triangulation().incident_cells(v, std::back_inserter(cells)); - - BOOST_FOREACH(Cell_handle c, cells) - { - if (c->subdomain_index() != imaginary_index) - return false; - } - return true; - } - - /** - * returns true off edge is fully imaginary - * i.e. if all its incident cells are not in the complex, - * and have their subdomain index == imaginary_index - */ - template - bool is_imaginary(const typename C3t3::Edge & edge, - const C3t3& c3t3, - const typename C3t3::Subdomain_index& imaginary_index) - { - typedef typename C3t3::Triangulation::Cell_circulator Cell_circulator; - Cell_circulator circ = c3t3.triangulation().incident_cells(edge); - Cell_circulator done = circ; - do - { - if ( c3t3.is_in_complex(circ) - && circ->subdomain_index() != imaginary_index) - return false; - } while (++circ != done); - - return true; - } - - template - bool is_outside(const typename C3t3::Edge & edge, - const C3t3& c3t3, - const typename C3t3::Subdomain_index& imaginary_index, - CellSelector cell_selector) - { - typedef typename C3t3::Triangulation::Cell_circulator Cell_circulator; - Cell_circulator circ = c3t3.triangulation().incident_cells(edge); - Cell_circulator done = circ; - do - { - // is cell infinite? - if (c3t3.triangulation().is_infinite(circ)) - continue; - // is cell imaginary? - if (c3t3.is_in_complex(circ) && circ->subdomain_index() == imaginary_index) - continue; - //circ does not belong to the selection - if (!cell_selector(circ)) - continue; - - //none of the above conditions was met - return false; - } - while (circ != done); - - return true; //all cells have met the loop conditions - } - - template - bool is_selected(const typename C3t3::Vertex_handle v, - const C3t3& c3t3, - CellSelector cell_selector) - { - typedef typename C3t3::Triangulation::Cell_handle Cell_handle; - - std::vector cells; - c3t3.triangulation().incident_cells(v, std::back_inserter(cells)); - - BOOST_FOREACH(Cell_handle c, cells) - { - if (!cell_selector(c)) - return false; - } - return true; - } - - template - bool is_inside(const typename C3t3::Edge& edge, - const C3t3& c3t3, - const typename C3t3::Subdomain_index& imaginary_index, - CellSelector cell_selector) - { - typedef typename C3t3::Triangulation::Cell_circulator Cell_circulator; - Cell_circulator circ = c3t3.triangulation().incident_cells(edge); - Cell_circulator done = circ; - - const typename C3t3::Subdomain_index si = circ->subdomain_index(); - if (si == imaginary_index || !c3t3.is_in_complex(circ) ) - return false; - do - { - if (c3t3.triangulation().is_infinite(circ)) - return false; - if (si != circ->subdomain_index()) - return false; - if (!cell_selector(circ)) - return false; - } - while (++circ != done); - - return true; - } - - template - bool is_convex(const Tr& tr, - const CGAL::Iso_cuboid_3& bbox, - typename Tr::Facet& facet) - { - typedef typename Tr::Cell_handle Cell_handle; - typedef typename Tr::Vertex_handle Vertex_handle; - typedef typename Tr::Facet Facet; - typedef typename Tr::Finite_facets_iterator Finite_facets_iterator; - - for (Finite_facets_iterator fit = tr.finite_facets_begin(); - fit != tr.finite_facets_end(); ++fit) - { - Facet f = *fit; - Facet mf = tr.mirror_facet(f); - if (!tr.is_infinite(f.first) && !tr.is_infinite(mf.first)) - continue; - - if (tr.is_infinite(mf.first)) - f = mf; - CGAL_assertion(tr.is_infinite(f.first)); - - boost::array vs; - for (int i = 0; i < 3; ++i) - vs[i] = f.first->vertex((f.second + i + 1) % 4); - if (f.second % 2 == 0) - std::swap(vs[0], vs[1]); - - Cell_handle fin_c = f.first->neighbor(f.second); - Vertex_handle v4 = fin_c->vertex(fin_c->index(f.first)); - - CGAL_assertion(!tr.is_infinite(fin_c)); - CGAL_assertion(!f.first->has_vertex(v4)); - - CGAL_assertion(CGAL::NEGATIVE - == CGAL::orientation(vs[0]->point(), vs[1]->point(), - vs[2]->point(), v4->point())); - - for (int i = 1; i < 4; ++i) - { - //nfi is neighbor of f on convex hull - Cell_handle ni = f.first->neighbor((f.second + i) % 4); - CGAL_assertion(tr.is_infinite(ni)); - - //collect points - Vertex_handle v3 = ni->vertex(ni->index(f.first)); - CGAL_assertion( v3 != vs[0] && v3 != vs[1] && v3 != vs[2] - && v3 != tr.infinite_vertex()); - CGAL_assertion(!f.first->has_vertex(v3)); - - CGAL::Orientation o2 = CGAL::orientation(vs[0]->point(), - vs[1]->point(), vs[2]->point(), v3->point()); - if (o2 == CGAL::POSITIVE) - { - facet = f; - - if (!bbox.is_degenerate() - && bbox.has_on_boundary(vs[0]->point()) - && bbox.has_on_boundary(vs[1]->point()) - && bbox.has_on_boundary(vs[2]->point())) - { - facet = Facet(ni, ni->index(tr.infinite_vertex())); - } - - return false; - } - } - } - return true; - } - - template - bool is_convex(const Tr& tr) - { - typename Tr::Facet f; - typename Tr::Geom_traits::Iso_cuboid_3 bb(CGAL::ORIGIN, CGAL::ORIGIN); - return is_convex(tr, bb, f); - } - - template - typename Gt::Vector_3 normal(const Facet& f, const Gt& gt) - { - namespace PMP = CGAL::Polygon_mesh_processing; - typedef typename Gt::Vector_3 Vector; - typedef typename Gt::Point_3 Point; - - Point p0 = point(f.first->vertex((f.second + 1) % 4)->point()); - Point p1 = point(f.first->vertex((f.second + 2) % 4)->point()); - const Point& p2 = point(f.first->vertex((f.second + 3) % 4)->point()); - - //if (CGAL::POSITIVE != CGAL::orientation(p0, p1, p2, p3)) - if (f.second % 2 == 0)//equivalent to the commented orientation test - std::swap(p0, p1); - - Vector n = PMP::internal::triangle_normal(p0, p1, p2, gt); - - if (!typename Gt::Equal_3()(n, CGAL::NULL_VECTOR)) - PMP::internal::normalize(n, gt); - - return n; - } - - template - OutputIterator get_inside_edges(const C3t3& c3t3, - const typename C3t3::Subdomain_index& imaginary_index, - CellSelector cell_selector, - OutputIterator oit)/*holds pairs of Vertex_handles*/ - { - for (typename C3t3::Triangulation::Finite_edges_iterator - eit = c3t3.triangulation().finite_edges_begin(); - eit != c3t3.triangulation().finite_edges_end(); - ++eit) - { - const typename C3t3::Edge& e = *eit; - //if ( !c3t3.is_in_complex(e) - // && !is_boundary_edge(e, c3t3) - // && !is_on_hull(e, c3t3) - // && !is_imaginary(e, c3t3, imaginary_index)) - if (is_inside(e, c3t3, imaginary_index, cell_selector)) - { - *oit++ = make_vertex_pair(e); - } - } - return oit; - } - -}//end namespace CGAL - -#endif //CGAL_TRIANGULATION_3_HELPERS_H From 0555674a97772325ea45f5db929436d46f410d6f Mon Sep 17 00:00:00 2001 From: Jane Tournois Date: Tue, 1 Oct 2019 17:26:30 +0200 Subject: [PATCH 026/568] initiate documentation --- .../doc/Tetrahedral_remeshing/Doxyfile.in | 28 +++++++++++++++++++ .../doc/Tetrahedral_remeshing/dependencies | 6 ++++ .../doc/Tetrahedral_remeshing/examples.txt | 5 ++++ 3 files changed, 39 insertions(+) create mode 100644 Tetrahedral_remeshing/doc/Tetrahedral_remeshing/Doxyfile.in create mode 100644 Tetrahedral_remeshing/doc/Tetrahedral_remeshing/dependencies create mode 100644 Tetrahedral_remeshing/doc/Tetrahedral_remeshing/examples.txt diff --git a/Tetrahedral_remeshing/doc/Tetrahedral_remeshing/Doxyfile.in b/Tetrahedral_remeshing/doc/Tetrahedral_remeshing/Doxyfile.in new file mode 100644 index 00000000000..ac44f761d3d --- /dev/null +++ b/Tetrahedral_remeshing/doc/Tetrahedral_remeshing/Doxyfile.in @@ -0,0 +1,28 @@ +@INCLUDE = ${CGAL_DOC_PACKAGE_DEFAULTS} +PROJECT_NAME = "CGAL ${CGAL_DOC_VERSION} - Tetrahedral Remeshing" + +#custom options for this package +EXTRACT_ALL = false +HIDE_UNDOC_CLASSES = true +WARN_IF_UNDOCUMENTED = false + +INPUT = ${CMAKE_SOURCE_DIR}/Tetrahedral_remeshing/doc/Tetrahedral_remeshing/ \ + ${CMAKE_SOURCE_DIR}/Tetrahedral_remeshing/include + +# macros to be used inside the code +ALIASES += "cgalNamedParamsBegin=
Named Parameters
" +ALIASES += "cgalNamedParamsEnd=
" +ALIASES += "cgalParamBegin{1}=\ref TETREMESH_\1 \"\1\"" +ALIASES += "cgalParamEnd=" + +#macros for NamedParameters.txt +ALIASES += "cgalNPTableBegin=
" +ALIASES += "cgalNPTableEnd=
" +ALIASES += "cgalNPBegin{1}=\1 " +ALIASES += "cgalNPEnd=" + +MACRO_EXPANSION = YES +EXPAND_ONLY_PREDEF = YES +EXPAND_AS_DEFINED = CGAL_PMP_NP_TEMPLATE_PARAMETERS \ + CGAL_PMP_NP_CLASS +EXCLUDE = ${CGAL_PACKAGE_INCLUDE_DIR}/CGAL/Tetrahedral_remeshing/internal diff --git a/Tetrahedral_remeshing/doc/Tetrahedral_remeshing/dependencies b/Tetrahedral_remeshing/doc/Tetrahedral_remeshing/dependencies new file mode 100644 index 00000000000..a4d5f76715e --- /dev/null +++ b/Tetrahedral_remeshing/doc/Tetrahedral_remeshing/dependencies @@ -0,0 +1,6 @@ +Manual +Kernel_23 +STL_Extension +Algebraic_foundations +Circulator +Stream_support diff --git a/Tetrahedral_remeshing/doc/Tetrahedral_remeshing/examples.txt b/Tetrahedral_remeshing/doc/Tetrahedral_remeshing/examples.txt new file mode 100644 index 00000000000..564cc8fafe8 --- /dev/null +++ b/Tetrahedral_remeshing/doc/Tetrahedral_remeshing/examples.txt @@ -0,0 +1,5 @@ +/*! + +\example Tetrahedral_remeshing/tetrahedral_remeshing_example.cpp + +*/ From e7c3ecc3c3f1e17499c6b1141328c0e00c5e9076 Mon Sep 17 00:00:00 2001 From: Jane Tournois Date: Thu, 3 Oct 2019 15:36:29 +0200 Subject: [PATCH 027/568] wip doc tetrahedral remeshing --- Documentation/doc/biblio/cgal_manual.bib | 8 +++ .../PackageDescription.txt | 56 +++++++++++++++++++ .../Tetrahedral_remeshing.txt | 29 ++++++++++ 3 files changed, 93 insertions(+) create mode 100644 Tetrahedral_remeshing/doc/Tetrahedral_remeshing/PackageDescription.txt create mode 100644 Tetrahedral_remeshing/doc/Tetrahedral_remeshing/Tetrahedral_remeshing.txt diff --git a/Documentation/doc/biblio/cgal_manual.bib b/Documentation/doc/biblio/cgal_manual.bib index ec232cbda8e..578f3c8405b 100644 --- a/Documentation/doc/biblio/cgal_manual.bib +++ b/Documentation/doc/biblio/cgal_manual.bib @@ -3045,6 +3045,14 @@ pages = "207--221" year={2012}, organization={Wiley Online Library} } + +@article{faraj2016mvr, + author = {Noura Faraj and Jean-Marc Thiery and Tamy Boubekeur}, + title = {Multi-Material Adaptive Volume Remesher}, + journal = {Compurer and Graphics Journal (proc. Shape Modeling International 2016)}, + year = {2016}, +} + % ---------------------------------------------------------------------------- % END OF BIBFILE % ---------------------------------------------------------------------------- diff --git a/Tetrahedral_remeshing/doc/Tetrahedral_remeshing/PackageDescription.txt b/Tetrahedral_remeshing/doc/Tetrahedral_remeshing/PackageDescription.txt new file mode 100644 index 00000000000..36baf1aa43f --- /dev/null +++ b/Tetrahedral_remeshing/doc/Tetrahedral_remeshing/PackageDescription.txt @@ -0,0 +1,56 @@ +// Tetrahedral Remeshing + +/// \defgroup PkgTetrahedralRemeshingRef Tetrahedral Remeshing Reference +/// \defgroup PkgTetrahedralRemeshingConcepts Concepts +/// \ingroup PkgTetrahedralRemeshingRef + +/// \defgroup PkgPACKAGEAlgorithmFunctions Remeshing Function +/// \ingroup PkgPACKAGE + +/// \defgroup PkgPACKAGETraitsClasses Traits Classes +/// \ingroup PkgPACKAGE + +/// \defgroup PkgPACKAGEMiscellaneous Miscellaneous +/// \ingroup PkgPACKAGE + +/*! +\addtogroup PkgTetrahedralRemeshingRef +\todo check generated documentation +\todo add pkg-small.png + +\cgalPkgDescriptionBegin{Tetrahedral Remeshing,PkgTetrahedralRemeshing} +\cgalPkgPicture{pkg-small.png} + +\cgalPkgSummaryBegin +\cgalPkgAuthors{Jane Tournois, Noura Faraj} +\cgalPkgDesc{PACKAGE DESCRIPTION. +The package provides a function for remeshing of tetrahedral meshes, +targetting high quality meshes with respect to dihedral angles.} +\cgalPkgManuals{Chapter_3D_Mesh_Generation,PkgTetrahedralRemeshingRef} +\cgalPkgSummaryEnd + +\cgalPkgShortInfoBegin +\cgalPkgSince{5.0} +\cgalPkgDependsOn{\ref PkgTriangulation3} +\cgalPkgBib{faraj2016mvr} +\cgalPkgLicense{\ref licensesGPL "GPL"} +\cgalPkgDemo{Polyhedron demo,polyhedron_3.zip} +\cgalPkgShortInfoEnd + +\cgalPkgDescriptionEnd + +\cgalClassifedRefPages + +\cgalCRPSection{Concepts} + +Here are the main concepts of this package: + +- `RemeshingTriangulation_3` +- `RemeshingCellBase_3` +- `RemeshingVertexBase_3` + +\cgalCRPSection{Function Templates} + +- `CGAL::tetrahedral_adaptive_remeshing()` + +*/ diff --git a/Tetrahedral_remeshing/doc/Tetrahedral_remeshing/Tetrahedral_remeshing.txt b/Tetrahedral_remeshing/doc/Tetrahedral_remeshing/Tetrahedral_remeshing.txt new file mode 100644 index 00000000000..b1fcb2351d5 --- /dev/null +++ b/Tetrahedral_remeshing/doc/Tetrahedral_remeshing/Tetrahedral_remeshing.txt @@ -0,0 +1,29 @@ +namespace CGAL { +/*! + +\mainpage User Manual +\anchor Chapter_Tetrahedral_Remeshing +\anchor userchaptertetrahedralremeshing +\authors Jane Tournois, Noura Faraj +\cgalAutoToc + +This chapter describes the tetrahedral remeshing algorithm... + +\section secmydefinitions Definitions + +Section on definitions here ... + +\section secmyexamples Examples + +\subsection myFirstExample First Example + +The following example shows ... + +\cgalExample{ } + +\cgalFigureBegin{figPck,bench.png} +Left: ... +\cgalFigureEnd + +*/ +} /* namespace CGAL */ From d93d36d07bd9825fafc1d7de3643719a789237bd Mon Sep 17 00:00:00 2001 From: Jane Tournois Date: Fri, 18 Oct 2019 11:45:24 +0200 Subject: [PATCH 028/568] wip doc --- .../doc/Tetrahedral_remeshing/Tetrahedral_remeshing.txt | 4 +++- Tetrahedral_remeshing/doc/Tetrahedral_remeshing/dependencies | 2 ++ Tetrahedral_remeshing/doc/Tetrahedral_remeshing/examples.txt | 2 ++ 3 files changed, 7 insertions(+), 1 deletion(-) diff --git a/Tetrahedral_remeshing/doc/Tetrahedral_remeshing/Tetrahedral_remeshing.txt b/Tetrahedral_remeshing/doc/Tetrahedral_remeshing/Tetrahedral_remeshing.txt index b1fcb2351d5..5cda601c921 100644 --- a/Tetrahedral_remeshing/doc/Tetrahedral_remeshing/Tetrahedral_remeshing.txt +++ b/Tetrahedral_remeshing/doc/Tetrahedral_remeshing/Tetrahedral_remeshing.txt @@ -19,7 +19,9 @@ Section on definitions here ... The following example shows ... -\cgalExample{ } +\cgalExample{tetrahedral_remeshing_example.cpp } +\cgalExample{tetrahedral_remeshing_of_one_subdomain.cpp } +\cgalExample{tetrahedral_remeshing_with_features.cpp } \cgalFigureBegin{figPck,bench.png} Left: ... diff --git a/Tetrahedral_remeshing/doc/Tetrahedral_remeshing/dependencies b/Tetrahedral_remeshing/doc/Tetrahedral_remeshing/dependencies index a4d5f76715e..a94d635557f 100644 --- a/Tetrahedral_remeshing/doc/Tetrahedral_remeshing/dependencies +++ b/Tetrahedral_remeshing/doc/Tetrahedral_remeshing/dependencies @@ -4,3 +4,5 @@ STL_Extension Algebraic_foundations Circulator Stream_support +Triangulation_3 +Triangulation_data_structure diff --git a/Tetrahedral_remeshing/doc/Tetrahedral_remeshing/examples.txt b/Tetrahedral_remeshing/doc/Tetrahedral_remeshing/examples.txt index 564cc8fafe8..e8c4a45bee1 100644 --- a/Tetrahedral_remeshing/doc/Tetrahedral_remeshing/examples.txt +++ b/Tetrahedral_remeshing/doc/Tetrahedral_remeshing/examples.txt @@ -1,5 +1,7 @@ /*! \example Tetrahedral_remeshing/tetrahedral_remeshing_example.cpp +\example Tetrahedral_remeshing/tetrahedral_remeshing_of_one_subdomain.cpp +\example Tetrahedral_remeshing/tetrahedral_remeshing_with_features.cpp */ From 71cbb8896d14c3e352e96b10f8be6fe13da25d06 Mon Sep 17 00:00:00 2001 From: Jane Tournois Date: Fri, 18 Oct 2019 13:54:01 +0200 Subject: [PATCH 029/568] wip doc --- .../Concepts/RemeshingCellBase_3.h | 37 ++++++++++++++++++ .../Concepts/RemeshingVertexBase_3.h | 38 +++++++++++++++++++ .../doc/Tetrahedral_remeshing/Doxyfile.in | 6 ++- .../PackageDescription.txt | 3 +- .../Tetrahedral_remeshing.txt | 6 +-- .../doc/Tetrahedral_remeshing/dependencies | 1 - 6 files changed, 83 insertions(+), 8 deletions(-) create mode 100644 Tetrahedral_remeshing/doc/Tetrahedral_remeshing/Concepts/RemeshingCellBase_3.h create mode 100644 Tetrahedral_remeshing/doc/Tetrahedral_remeshing/Concepts/RemeshingVertexBase_3.h diff --git a/Tetrahedral_remeshing/doc/Tetrahedral_remeshing/Concepts/RemeshingCellBase_3.h b/Tetrahedral_remeshing/doc/Tetrahedral_remeshing/Concepts/RemeshingCellBase_3.h new file mode 100644 index 00000000000..ded56939b5b --- /dev/null +++ b/Tetrahedral_remeshing/doc/Tetrahedral_remeshing/Concepts/RemeshingCellBase_3.h @@ -0,0 +1,37 @@ +/// \ingroup PkgTetrahedralRemeshingConcepts +/// \cgalConcept +/// +/// The concept `RemeshingCellBase_3` defines the requirements for the cell base +/// used in the triangulation given as input to the remeshing algorithm +/// +/// \cgalRefines `TriangulationCellBase_3`, `CopyConstructible` +/// \cgalHasModel `CGAL::Tetrahedral_remeshing::Remeshing_cell_base`. + + +class RemeshingCellBase_3 { +public: + /// Subdomain index + typedef unspecified_type Subdomain_index; + /// Surface patch index + typedef unspecified_type Surface_patch_index; + + /// @name Operations + /// @{ + /// Returns the index of the input subdomain that contains the cell `cell` + /// of the triangulation. + const Subdomain_index& subdomain_index() const; + + /// Sets the subdomain index of the cell. + void set_subdomain_index(const Subdomain_index& si); + + /// returns `Surface_patch_index` of facet `i`. + const Surface_patch_index surface_patch_index(const int&) const; + + /// sets `Surface_patch_index` of facet `i` to `index` + void set_surface_patch_index(const int i, const Surface_patch_index&) + + /// Returns `true` if the facet `i` lies on a surface patch + bool is_facet_on_surface(const int& i) const; + + /// @} +}; diff --git a/Tetrahedral_remeshing/doc/Tetrahedral_remeshing/Concepts/RemeshingVertexBase_3.h b/Tetrahedral_remeshing/doc/Tetrahedral_remeshing/Concepts/RemeshingVertexBase_3.h new file mode 100644 index 00000000000..f9810d6f517 --- /dev/null +++ b/Tetrahedral_remeshing/doc/Tetrahedral_remeshing/Concepts/RemeshingVertexBase_3.h @@ -0,0 +1,38 @@ +/// \ingroup PkgTetrahedralRemeshingConcepts +/// \cgalConcept +/// +/// The concept `RemeshingVertexBase_3` defines the requirements for the vertex base +/// used in the triangulation given as input to the remeshing algorithm +/// +/// \cgalRefines `TriangulationVertexBase_3`, `CopyConstructible` +/// \cgalHasModel `CGAL::Tetrahedral_remeshing::Remeshing_vertex_base`. + + +class RemeshingVertexBase_3 { +public: + + /// @name Operations + /// @{ + + /// Returns the dimension of the lowest dimensional face of the input 3D + /// complex that contains the vertex + int in_dimension() const; + + /// Sets the dimension of the lowest dimensional face of the input 3D complex + /// that contains the vertex + void set_dimension(const int dimension); + + /// Returns the number of incident facets + std::size_t number_of_incident_facets() const; + + /// Returns the number of subdomains to which belong incident cells + std::size_t number_of_incident_subdomains() const; + + /// Internal function that invalidates cache data stored for performance + void invalidate_cache(); + /// Internal function that sets cache data stored for performance + void set_cache(const std::size_t i, const std::size_t j); + + + /// @} +}; diff --git a/Tetrahedral_remeshing/doc/Tetrahedral_remeshing/Doxyfile.in b/Tetrahedral_remeshing/doc/Tetrahedral_remeshing/Doxyfile.in index ac44f761d3d..c25a5420726 100644 --- a/Tetrahedral_remeshing/doc/Tetrahedral_remeshing/Doxyfile.in +++ b/Tetrahedral_remeshing/doc/Tetrahedral_remeshing/Doxyfile.in @@ -6,8 +6,8 @@ EXTRACT_ALL = false HIDE_UNDOC_CLASSES = true WARN_IF_UNDOCUMENTED = false -INPUT = ${CMAKE_SOURCE_DIR}/Tetrahedral_remeshing/doc/Tetrahedral_remeshing/ \ - ${CMAKE_SOURCE_DIR}/Tetrahedral_remeshing/include +#INPUT = ${CMAKE_SOURCE_DIR}/Tetrahedral_remeshing/doc/Tetrahedral_remeshing/ \ +# ${CMAKE_SOURCE_DIR}/Tetrahedral_remeshing/include/CGAL # macros to be used inside the code ALIASES += "cgalNamedParamsBegin=
Named Parameters
" @@ -21,6 +21,8 @@ ALIASES += "cgalNPTableEnd=
" ALIASES += "cgalNPBegin{1}=\1 " ALIASES += "cgalNPEnd=" +EXAMPLE_PATH += ${CGAL_Tetrahedral_remeshing_EXAMPLE_DIR} + MACRO_EXPANSION = YES EXPAND_ONLY_PREDEF = YES EXPAND_AS_DEFINED = CGAL_PMP_NP_TEMPLATE_PARAMETERS \ diff --git a/Tetrahedral_remeshing/doc/Tetrahedral_remeshing/PackageDescription.txt b/Tetrahedral_remeshing/doc/Tetrahedral_remeshing/PackageDescription.txt index 36baf1aa43f..b4e069bcf48 100644 --- a/Tetrahedral_remeshing/doc/Tetrahedral_remeshing/PackageDescription.txt +++ b/Tetrahedral_remeshing/doc/Tetrahedral_remeshing/PackageDescription.txt @@ -23,7 +23,7 @@ \cgalPkgSummaryBegin \cgalPkgAuthors{Jane Tournois, Noura Faraj} -\cgalPkgDesc{PACKAGE DESCRIPTION. +\cgalPkgDesc{ The package provides a function for remeshing of tetrahedral meshes, targetting high quality meshes with respect to dihedral angles.} \cgalPkgManuals{Chapter_3D_Mesh_Generation,PkgTetrahedralRemeshingRef} @@ -45,7 +45,6 @@ targetting high quality meshes with respect to dihedral angles.} Here are the main concepts of this package: -- `RemeshingTriangulation_3` - `RemeshingCellBase_3` - `RemeshingVertexBase_3` diff --git a/Tetrahedral_remeshing/doc/Tetrahedral_remeshing/Tetrahedral_remeshing.txt b/Tetrahedral_remeshing/doc/Tetrahedral_remeshing/Tetrahedral_remeshing.txt index 5cda601c921..afcbcec6556 100644 --- a/Tetrahedral_remeshing/doc/Tetrahedral_remeshing/Tetrahedral_remeshing.txt +++ b/Tetrahedral_remeshing/doc/Tetrahedral_remeshing/Tetrahedral_remeshing.txt @@ -23,9 +23,9 @@ The following example shows ... \cgalExample{tetrahedral_remeshing_of_one_subdomain.cpp } \cgalExample{tetrahedral_remeshing_with_features.cpp } -\cgalFigureBegin{figPck,bench.png} -Left: ... -\cgalFigureEnd +#\cgalFigureBegin{figPck,bench.png} +#Left: ... +#\cgalFigureEnd */ } /* namespace CGAL */ diff --git a/Tetrahedral_remeshing/doc/Tetrahedral_remeshing/dependencies b/Tetrahedral_remeshing/doc/Tetrahedral_remeshing/dependencies index a94d635557f..12fc15e3f31 100644 --- a/Tetrahedral_remeshing/doc/Tetrahedral_remeshing/dependencies +++ b/Tetrahedral_remeshing/doc/Tetrahedral_remeshing/dependencies @@ -5,4 +5,3 @@ Algebraic_foundations Circulator Stream_support Triangulation_3 -Triangulation_data_structure From feb6305d609486a724921bfac3139c06d64f2719 Mon Sep 17 00:00:00 2001 From: Jane Tournois Date: Fri, 18 Oct 2019 15:29:00 +0200 Subject: [PATCH 030/568] wip doc --- .../Concepts/RemeshingCellBase_3.h | 2 +- .../doc/Tetrahedral_remeshing/Doxyfile.in | 16 ++--- .../Tetrahedral_remeshing/NamedParameters.txt | 58 +++++++++++++++++++ .../PackageDescription.txt | 4 +- .../Tetrahedral_remeshing.txt | 4 -- .../doc/Tetrahedral_remeshing/dependencies | 1 + .../include/CGAL/tetrahedral_remeshing.h | 30 ++++++---- 7 files changed, 87 insertions(+), 28 deletions(-) create mode 100644 Tetrahedral_remeshing/doc/Tetrahedral_remeshing/NamedParameters.txt diff --git a/Tetrahedral_remeshing/doc/Tetrahedral_remeshing/Concepts/RemeshingCellBase_3.h b/Tetrahedral_remeshing/doc/Tetrahedral_remeshing/Concepts/RemeshingCellBase_3.h index ded56939b5b..54e2512e344 100644 --- a/Tetrahedral_remeshing/doc/Tetrahedral_remeshing/Concepts/RemeshingCellBase_3.h +++ b/Tetrahedral_remeshing/doc/Tetrahedral_remeshing/Concepts/RemeshingCellBase_3.h @@ -4,7 +4,7 @@ /// The concept `RemeshingCellBase_3` defines the requirements for the cell base /// used in the triangulation given as input to the remeshing algorithm /// -/// \cgalRefines `TriangulationCellBase_3`, `CopyConstructible` +/// \cgalRefines `TriangulationCellBaseWithInfo_3`, `CopyConstructible` /// \cgalHasModel `CGAL::Tetrahedral_remeshing::Remeshing_cell_base`. diff --git a/Tetrahedral_remeshing/doc/Tetrahedral_remeshing/Doxyfile.in b/Tetrahedral_remeshing/doc/Tetrahedral_remeshing/Doxyfile.in index c25a5420726..ed678b488d2 100644 --- a/Tetrahedral_remeshing/doc/Tetrahedral_remeshing/Doxyfile.in +++ b/Tetrahedral_remeshing/doc/Tetrahedral_remeshing/Doxyfile.in @@ -6,13 +6,10 @@ EXTRACT_ALL = false HIDE_UNDOC_CLASSES = true WARN_IF_UNDOCUMENTED = false -#INPUT = ${CMAKE_SOURCE_DIR}/Tetrahedral_remeshing/doc/Tetrahedral_remeshing/ \ -# ${CMAKE_SOURCE_DIR}/Tetrahedral_remeshing/include/CGAL - # macros to be used inside the code ALIASES += "cgalNamedParamsBegin=
Named Parameters
" ALIASES += "cgalNamedParamsEnd=
" -ALIASES += "cgalParamBegin{1}=\ref TETREMESH_\1 \"\1\"" +ALIASES += "cgalParamBegin{1}=\ref Remeshing_\1 \"\1\"" ALIASES += "cgalParamEnd=" #macros for NamedParameters.txt @@ -21,10 +18,9 @@ ALIASES += "cgalNPTableEnd= " ALIASES += "cgalNPBegin{1}=\1 " ALIASES += "cgalNPEnd=" -EXAMPLE_PATH += ${CGAL_Tetrahedral_remeshing_EXAMPLE_DIR} - -MACRO_EXPANSION = YES -EXPAND_ONLY_PREDEF = YES -EXPAND_AS_DEFINED = CGAL_PMP_NP_TEMPLATE_PARAMETERS \ - CGAL_PMP_NP_CLASS EXCLUDE = ${CGAL_PACKAGE_INCLUDE_DIR}/CGAL/Tetrahedral_remeshing/internal + +#MACRO_EXPANSION = YES +#EXPAND_ONLY_PREDEF = YES +#EXPAND_AS_DEFINED = CGAL_PMP_NP_TEMPLATE_PARAMETERS \ +# CGAL_PMP_NP_CLASS diff --git a/Tetrahedral_remeshing/doc/Tetrahedral_remeshing/NamedParameters.txt b/Tetrahedral_remeshing/doc/Tetrahedral_remeshing/NamedParameters.txt new file mode 100644 index 00000000000..4199b1cc6dc --- /dev/null +++ b/Tetrahedral_remeshing/doc/Tetrahedral_remeshing/NamedParameters.txt @@ -0,0 +1,58 @@ +/*! +\defgroup Remeshing_namedparameters Named Parameters for Tetrahedral Remeshing +\ingroup PkgTetrahedralRemeshingRef + +\cgalHeading{How to use BGL Optional Named Parameters} + +The notion of named parameters was introduced in the BGL. +Details can be found from: https://www.boost.org/libs/graph/doc/bgl_named_params.html. +Named parameters enable the user to specify only those parameters which are really needed, by name, making the parameter ordering not required. +See also \ref bgl_namedparameters. + +The sequence of named parameters should start with `CGAL::parameters::`. +The function `#all_default()` can be used to indicate +that default values of optional named parameters are used. + + +\cgalHeading{List of Available Named Parameters} + +In this package, functions optional parameters are implemented as BGL optional named parameters and listed below. + +In the following, we assume that the following types are provided as template parameters of tetrahedral remeshing +functions. Note that the type may be more specific for some functions. + +
    +
  • `Triangulation` implements a `Triangulation_3` with specific vertex base and cell base.
  • +
+ +\cgalNPTableBegin + +\cgalNPBegin{number_of_iterations} \anchor Remeshing_number_of_iterations +the number of iterations for the full sequence of atomic operations +(edge splits, edge collapses, edge flips, smoothing and projection to the initial surface) +performed to reach the input target edge length while improving the quality of dihedral angles +in the mesh.\n +\b Type : `std::size_t` \n +\b Default value is `1` +\cgalNPEnd + +\cgalNPBegin{protect_boundaries} \anchor Remeshing_protect_boundaries +a boolean that states whether the boudaries should be modified by the remeshing +process. Boundaries are between the exterior and the interior, +between two subdomains, and between the areas selected or not for remeshing +(cf \ref \Remeshing_cell_selector). If `true` they cannot.\n +\b Type : `bool` \n +\b Default value is `true` +\cgalNPEnd + +\cgalNPBegin{cell_selector} \anchor Remeshing_cell_selector +a functor that takes a `Cell_handle` as parameter and returns a `bool` that states whether +a cell is part of the zone to the remeshed. Unselected cells will not be modified by +the remeshing algorithm.\n +\b Type : Unary function object with `Cell_handle` as argument type and `bool` as return type.\n +\b Default value is a function object that always returns `true`. +\cgalNPEnd + +\cgalNPTableEnd + +*/ diff --git a/Tetrahedral_remeshing/doc/Tetrahedral_remeshing/PackageDescription.txt b/Tetrahedral_remeshing/doc/Tetrahedral_remeshing/PackageDescription.txt index b4e069bcf48..af619ce6b81 100644 --- a/Tetrahedral_remeshing/doc/Tetrahedral_remeshing/PackageDescription.txt +++ b/Tetrahedral_remeshing/doc/Tetrahedral_remeshing/PackageDescription.txt @@ -19,14 +19,14 @@ \todo add pkg-small.png \cgalPkgDescriptionBegin{Tetrahedral Remeshing,PkgTetrahedralRemeshing} -\cgalPkgPicture{pkg-small.png} +\todo cgalPkgPicture{pkg-small.png} \cgalPkgSummaryBegin \cgalPkgAuthors{Jane Tournois, Noura Faraj} \cgalPkgDesc{ The package provides a function for remeshing of tetrahedral meshes, targetting high quality meshes with respect to dihedral angles.} -\cgalPkgManuals{Chapter_3D_Mesh_Generation,PkgTetrahedralRemeshingRef} +\cgalPkgManuals{Chapter_Tetrahedral_Remeshing,PkgTetrahedralRemeshingRef} \cgalPkgSummaryEnd \cgalPkgShortInfoBegin diff --git a/Tetrahedral_remeshing/doc/Tetrahedral_remeshing/Tetrahedral_remeshing.txt b/Tetrahedral_remeshing/doc/Tetrahedral_remeshing/Tetrahedral_remeshing.txt index afcbcec6556..97c3705bd09 100644 --- a/Tetrahedral_remeshing/doc/Tetrahedral_remeshing/Tetrahedral_remeshing.txt +++ b/Tetrahedral_remeshing/doc/Tetrahedral_remeshing/Tetrahedral_remeshing.txt @@ -23,9 +23,5 @@ The following example shows ... \cgalExample{tetrahedral_remeshing_of_one_subdomain.cpp } \cgalExample{tetrahedral_remeshing_with_features.cpp } -#\cgalFigureBegin{figPck,bench.png} -#Left: ... -#\cgalFigureEnd - */ } /* namespace CGAL */ diff --git a/Tetrahedral_remeshing/doc/Tetrahedral_remeshing/dependencies b/Tetrahedral_remeshing/doc/Tetrahedral_remeshing/dependencies index 12fc15e3f31..abbf00809e4 100644 --- a/Tetrahedral_remeshing/doc/Tetrahedral_remeshing/dependencies +++ b/Tetrahedral_remeshing/doc/Tetrahedral_remeshing/dependencies @@ -5,3 +5,4 @@ Algebraic_foundations Circulator Stream_support Triangulation_3 +BGL diff --git a/Tetrahedral_remeshing/include/CGAL/tetrahedral_remeshing.h b/Tetrahedral_remeshing/include/CGAL/tetrahedral_remeshing.h index 566411a88df..0d168229c6b 100644 --- a/Tetrahedral_remeshing/include/CGAL/tetrahedral_remeshing.h +++ b/Tetrahedral_remeshing/include/CGAL/tetrahedral_remeshing.h @@ -38,6 +38,7 @@ namespace CGAL { /*! + * \ingroup PkgTetrahedralRemeshingRef * remeshes a tetrahedral mesh. * * This operation sequentially performs edge splits, edge collapses, @@ -45,21 +46,28 @@ namespace CGAL * a quality mesh with a prescribed edge length. * * @tparam Triangulation model of `Triangulation_3`, - * with cell base model of `TriangulationCellBaseWithInfo_3` + * with cell base model of `RemeshingCellBase_3` + * and vertex base model of `RemeshingVertexBase_3`. * - * @tparam NamedParameters a sequence of \ref pmp_namedparameters "Named Parameters" - - * @param np optional sequence of \ref pmp_namedparameters "Named Parameters" among the ones listed below + * @tparam NamedParameters a sequence of \ref Remeshing_namedparameters "Named Parameters" + * + * @param tr the triangulation to the remeshed + * @param target_edge_length the uniform target edge length. This parameter provides a + * mesh density target for the remeshing algorithm. + * @param np optional sequence of \ref Remeshing_namedparameters "Named Parameters" + * among the ones listed below * \cgalNamedParamsBegin - * \cgalParamBegin{protect_boundaries} If `true`, the - * volume boundaries cannot be modified (no modification of boundaries in this version) - * \cgalParamEnd - * \cgalParamBegin{number_of_iterations} the number of iterations for the sequence of atomic operations + * \cgalParamBegin{number_of_iterations} the number of iterations for the full + * sequence of atomic operations * performed (listed in the above description) - * \cgalParam + * \cgalParamEnd + * \cgalParamBegin{protect_boundaries} If `true`, the + * volume boundaries cannot be modified + * \cgalParamEnd * \cgalParamBegin{cell_selector} a functor that returns a boolean setting whether the given - * `Triangulation::Cell_handle` should be part of the remeshing (by default, cells are all part - * of the remeshing) + * `Triangulation::Cell_handle` should be part of the remeshing. + * By default, all cells are all part + * of the remeshing. * \cgalParamEnd * \cgalNamedParamsEnd */ From ea34ae0a56d0a2d220763783ed3409159217cf09 Mon Sep 17 00:00:00 2001 From: Jane Tournois Date: Fri, 18 Oct 2019 15:39:51 +0200 Subject: [PATCH 031/568] wip doc continued --- .../Tetrahedral_remeshing/NamedParameters.txt | 7 ++-- .../PackageDescription.txt | 4 +-- .../Remeshing_cell_base.h | 4 +-- .../Remeshing_vertex_base.h | 33 ++++++++++++++++--- 4 files changed, 36 insertions(+), 12 deletions(-) diff --git a/Tetrahedral_remeshing/doc/Tetrahedral_remeshing/NamedParameters.txt b/Tetrahedral_remeshing/doc/Tetrahedral_remeshing/NamedParameters.txt index 4199b1cc6dc..b0a902892ec 100644 --- a/Tetrahedral_remeshing/doc/Tetrahedral_remeshing/NamedParameters.txt +++ b/Tetrahedral_remeshing/doc/Tetrahedral_remeshing/NamedParameters.txt @@ -6,11 +6,12 @@ The notion of named parameters was introduced in the BGL. Details can be found from: https://www.boost.org/libs/graph/doc/bgl_named_params.html. -Named parameters enable the user to specify only those parameters which are really needed, by name, making the parameter ordering not required. -See also \ref bgl_namedparameters. +Named parameters enable the user to specify only those parameters which are really needed, by name, +making the parameter ordering not required. +See \ref BGLNamedParameters for more information on how to use them. The sequence of named parameters should start with `CGAL::parameters::`. -The function `#all_default()` can be used to indicate +The function `CGAL::parameters::all_default()` can be used to indicate that default values of optional named parameters are used. diff --git a/Tetrahedral_remeshing/doc/Tetrahedral_remeshing/PackageDescription.txt b/Tetrahedral_remeshing/doc/Tetrahedral_remeshing/PackageDescription.txt index af619ce6b81..29c8523ee77 100644 --- a/Tetrahedral_remeshing/doc/Tetrahedral_remeshing/PackageDescription.txt +++ b/Tetrahedral_remeshing/doc/Tetrahedral_remeshing/PackageDescription.txt @@ -30,7 +30,7 @@ targetting high quality meshes with respect to dihedral angles.} \cgalPkgSummaryEnd \cgalPkgShortInfoBegin -\cgalPkgSince{5.0} +\cgalPkgSince{5.1} \cgalPkgDependsOn{\ref PkgTriangulation3} \cgalPkgBib{faraj2016mvr} \cgalPkgLicense{\ref licensesGPL "GPL"} @@ -43,8 +43,6 @@ targetting high quality meshes with respect to dihedral angles.} \cgalCRPSection{Concepts} -Here are the main concepts of this package: - - `RemeshingCellBase_3` - `RemeshingVertexBase_3` diff --git a/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/Remeshing_cell_base.h b/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/Remeshing_cell_base.h index e35625243a7..3c16da75676 100644 --- a/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/Remeshing_cell_base.h +++ b/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/Remeshing_cell_base.h @@ -103,7 +103,7 @@ namespace Tetrahedral_remeshing void set_surface_patch_index(const int, const Surface_patch_index&) {/*nothing to do because we use incident subdomain indices*/ } - const Surface_patch_index surface_patch_index(const int& i) + const Surface_patch_index surface_patch_index(const int& i) const { CGAL_precondition(i >= 0 && i < 4); if(is_facet_on_surface(i)) @@ -113,7 +113,7 @@ namespace Tetrahedral_remeshing } /// Returns true if facet lies on a surface patch - bool is_facet_on_surface(const int facet) const + bool is_facet_on_surface(const int& facet) const { CGAL_precondition(facet >= 0 && facet<4); return this->subdomain_index() != this->neighbor(facet)->subdomain_index(); diff --git a/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/Remeshing_vertex_base.h b/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/Remeshing_vertex_base.h index f9b74dd1a4f..4eddd26f9fb 100644 --- a/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/Remeshing_vertex_base.h +++ b/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/Remeshing_vertex_base.h @@ -24,7 +24,6 @@ #define CGAL_TET_ADAPTIVE_REMESHING_VERTEX_BASE_H #include -#include namespace CGAL { @@ -44,13 +43,14 @@ namespace Tetrahedral_remeshing template > class Remeshing_vertex_base - : public CGAL::Mesh_vertex_base_3 + : public Vb { - typedef CGAL::Mesh_vertex_base_3 Base; - private: short dimension_; std::size_t time_stamp_; + std::size_t number_of_incident_facets_; + std::size_t number_of_components_; + bool cache_validity_; public: Remeshing_vertex_base() : dimension_(-1) @@ -90,6 +90,31 @@ namespace Tetrahedral_remeshing } ///@} + // documented as invalidate_cache() + void invalidate_c2t3_cache() + { + cache_validity_ = false; + } + // documented as set_cache() + void set_cache(const std::size_t i, const std::size_t j) + { + number_of_incident_facets_ = i; + number_of_components_ = j; + cache_validity_ = true; + } + + // documented as number_of_incident_facets + std::size_t cached_number_of_incident_facets() const + { + return number_of_incident_facets_; + } + + // documented as number_of_incident_subdomains + std::size_t cached_number_of_components() const + { + return number_of_components_; + } + }; }//end namespace Tetrahedral_remeshing From fe5a669a0d57b21fc9eced93aac8831c44800f82 Mon Sep 17 00:00:00 2001 From: Jane Tournois Date: Fri, 18 Oct 2019 17:03:45 +0200 Subject: [PATCH 032/568] reference manual ready for review --- .../Concepts/RemeshingCellBase_3.h | 6 ++-- .../Tetrahedral_remeshing/NamedParameters.txt | 36 ++++++++++++++----- .../include/CGAL/tetrahedral_remeshing.h | 20 +++++------ 3 files changed, 41 insertions(+), 21 deletions(-) diff --git a/Tetrahedral_remeshing/doc/Tetrahedral_remeshing/Concepts/RemeshingCellBase_3.h b/Tetrahedral_remeshing/doc/Tetrahedral_remeshing/Concepts/RemeshingCellBase_3.h index 54e2512e344..6794e123497 100644 --- a/Tetrahedral_remeshing/doc/Tetrahedral_remeshing/Concepts/RemeshingCellBase_3.h +++ b/Tetrahedral_remeshing/doc/Tetrahedral_remeshing/Concepts/RemeshingCellBase_3.h @@ -17,8 +17,10 @@ public: /// @name Operations /// @{ - /// Returns the index of the input subdomain that contains the cell `cell` - /// of the triangulation. + /// Returns the index of the input subdomain of the triangulation + /// that contains the cell. + /// Cells with a non-zero `Subdomain_index` are considered as the "inside" + /// of the domain to be remeshed const Subdomain_index& subdomain_index() const; /// Sets the subdomain index of the cell. diff --git a/Tetrahedral_remeshing/doc/Tetrahedral_remeshing/NamedParameters.txt b/Tetrahedral_remeshing/doc/Tetrahedral_remeshing/NamedParameters.txt index b0a902892ec..49a83dde83b 100644 --- a/Tetrahedral_remeshing/doc/Tetrahedral_remeshing/NamedParameters.txt +++ b/Tetrahedral_remeshing/doc/Tetrahedral_remeshing/NamedParameters.txt @@ -28,7 +28,8 @@ functions. Note that the type may be more specific for some functions. \cgalNPTableBegin -\cgalNPBegin{number_of_iterations} \anchor Remeshing_number_of_iterations +\cgalNPBegin{number_of_iterations} +\anchor Remeshing_number_of_iterations the number of iterations for the full sequence of atomic operations (edge splits, edge collapses, edge flips, smoothing and projection to the initial surface) performed to reach the input target edge length while improving the quality of dihedral angles @@ -37,21 +38,38 @@ in the mesh.\n \b Default value is `1` \cgalNPEnd -\cgalNPBegin{protect_boundaries} \anchor Remeshing_protect_boundaries +\cgalNPBegin{protect_boundaries} +\anchor Remeshing_protect_boundaries a boolean that states whether the boudaries should be modified by the remeshing process. Boundaries are between the exterior and the interior, between two subdomains, and between the areas selected or not for remeshing -(cf \ref \Remeshing_cell_selector). If `true` they cannot.\n +(cf \ref Remeshing_cell_selector). If `true` they cannot.\n \b Type : `bool` \n \b Default value is `true` \cgalNPEnd -\cgalNPBegin{cell_selector} \anchor Remeshing_cell_selector -a functor that takes a `Cell_handle` as parameter and returns a `bool` that states whether -a cell is part of the zone to the remeshed. Unselected cells will not be modified by -the remeshing algorithm.\n -\b Type : Unary function object with `Cell_handle` as argument type and `bool` as return type.\n -\b Default value is a function object that always returns `true`. +\cgalNPBegin{edge_is_constrained_map} +\anchor Remeshing_edge_is_constrained_map +is a property map containing information about edges of the input triangulation +being marked as constrained or not. In `tetrahedral_adaptive_remeshing()`, +the marked edges are constrained.\n +Type: a class model of `ReadWritePropertyMap` with +`Triangulation::%Edge` as key type and +`bool` as value type. It must be default constructible.\n +Default: a default property map where no edge is constrained +\cgalNPEnd + +\cgalNPBegin{cell_is_selected_map} +\anchor Remeshing_cell_is_selected_map +is a property map containing information about cells of the input triangulation +being marked as selected or not for tetrahedral remeshing. +Only selected cells are modified (and possibly their neighbors if surfaces are +modified) by the remeshing process. Unselected cells will not be modified.\n +\b Type : a class model of `ReadWritePropertyMap` with +`Triangulation::%Cell_handle` as key type and `bool` as value type. +It must be default constructible.\n +Default: a default property map where all cells of the domain +(i.e. with a non-zero `Subdomain_index` are selected) \cgalNPEnd \cgalNPTableEnd diff --git a/Tetrahedral_remeshing/include/CGAL/tetrahedral_remeshing.h b/Tetrahedral_remeshing/include/CGAL/tetrahedral_remeshing.h index 0d168229c6b..1e4224f0313 100644 --- a/Tetrahedral_remeshing/include/CGAL/tetrahedral_remeshing.h +++ b/Tetrahedral_remeshing/include/CGAL/tetrahedral_remeshing.h @@ -61,13 +61,17 @@ namespace CGAL * sequence of atomic operations * performed (listed in the above description) * \cgalParamEnd - * \cgalParamBegin{protect_boundaries} If `true`, the - * volume boundaries cannot be modified + * \cgalParamBegin{protect_boundaries} If `true`, the volume boundaries cannot be modified * \cgalParamEnd - * \cgalParamBegin{cell_selector} a functor that returns a boolean setting whether the given - * `Triangulation::Cell_handle` should be part of the remeshing. - * By default, all cells are all part - * of the remeshing. + * \cgalParamBegin{edge_is_constrained_map} a property map containing the + * constrained - or - not status of each edge of `tr`. A constrained edge can be split + * or collapsed, but not flipped, nor its endpoints moved by smoothing + * \cgalParamEnd + * \cgalParamBegin{cell_is_selected_map} a property map containing the + * selected - or - not status for each cell of `tr` for remeshing. + * Only selected cells are modified (and possibly their neighbors if surfaces are + * modified) by remeshing. + * By default, all inside cells are selected. * \cgalParamEnd * \cgalNamedParamsEnd */ @@ -77,10 +81,6 @@ namespace CGAL //* \cgalParamBegin{ adaptive } If `true`, size of elements adapts //* .... //* \cgalParamEnd - //* \cgalParamBegin{ edge_is_constrained_map } a property map containing the - //* constrained - or - not status of each edge of `tr`. A constrained edge can be split - //* or collapsed, but not flipped, nor its endpoints moved by smoothing. - //* \cgalParamEnd //template From 3d83914017ef3be105c8cc16a9125f7f8857cc92 Mon Sep 17 00:00:00 2001 From: Jane Tournois Date: Mon, 2 Dec 2019 10:44:25 +0100 Subject: [PATCH 033/568] wip : start implementing Laurent's review --- .../Concepts/RemeshingVertexBase_3.h | 11 +++-- .../PackageDescription.txt | 3 ++ .../Remeshing_cell_base.h | 41 ++++++++++++++----- .../Remeshing_vertex_base.h | 7 ++-- 4 files changed, 45 insertions(+), 17 deletions(-) diff --git a/Tetrahedral_remeshing/doc/Tetrahedral_remeshing/Concepts/RemeshingVertexBase_3.h b/Tetrahedral_remeshing/doc/Tetrahedral_remeshing/Concepts/RemeshingVertexBase_3.h index f9810d6f517..0a426121a12 100644 --- a/Tetrahedral_remeshing/doc/Tetrahedral_remeshing/Concepts/RemeshingVertexBase_3.h +++ b/Tetrahedral_remeshing/doc/Tetrahedral_remeshing/Concepts/RemeshingVertexBase_3.h @@ -22,17 +22,20 @@ public: /// that contains the vertex void set_dimension(const int dimension); - /// Returns the number of incident facets + /// Returns the number of incident facets, + /// stored in a cache variable std::size_t number_of_incident_facets() const; - /// Returns the number of subdomains to which belong incident cells + /// Returns the number of subdomains to which belong incident cells, + /// stored in a cache variable std::size_t number_of_incident_subdomains() const; /// Internal function that invalidates cache data stored for performance void invalidate_cache(); - /// Internal function that sets cache data stored for performance - void set_cache(const std::size_t i, const std::size_t j); + /// Internal function that sets cache data stored for performance + void set_cache(const std::size_t& nb_incident_facets, + const std::size_t& nb_incident_subdomains); /// @} }; diff --git a/Tetrahedral_remeshing/doc/Tetrahedral_remeshing/PackageDescription.txt b/Tetrahedral_remeshing/doc/Tetrahedral_remeshing/PackageDescription.txt index 29c8523ee77..b37acfbbdae 100644 --- a/Tetrahedral_remeshing/doc/Tetrahedral_remeshing/PackageDescription.txt +++ b/Tetrahedral_remeshing/doc/Tetrahedral_remeshing/PackageDescription.txt @@ -4,6 +4,9 @@ /// \defgroup PkgTetrahedralRemeshingConcepts Concepts /// \ingroup PkgTetrahedralRemeshingRef +/// \defgroup PkgTetrahedralRemeshingClasses Classes +/// \ingroup PkgTetrahedralRemeshingRef + /// \defgroup PkgPACKAGEAlgorithmFunctions Remeshing Function /// \ingroup PkgPACKAGE diff --git a/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/Remeshing_cell_base.h b/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/Remeshing_cell_base.h index 3c16da75676..67c6b3dbfe8 100644 --- a/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/Remeshing_cell_base.h +++ b/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/Remeshing_cell_base.h @@ -32,14 +32,35 @@ namespace CGAL { namespace Tetrahedral_remeshing { - template` is a model of the concept `RemeshingCellBase_3`. +It is designed to serve as cell base class for the 3D triangulation +used in the tetrahedral remeshing process. + +\tparam Gt is the geometric traits class. +It has to be a model of the concept `RemeshingTriangulationTraits_3`. + +\tparam Info is the information the user would like to add to a cell. +It has to be `DefaultConstructible` and `Assignable`. + +\tparam Cb is a cell base class from which `Triangulation_cell_base_with_info_3` derives. +It must be a model of the `TriangulationCellBase_3` concept. +It has the default value `Triangulation_cell_base_3`. + +\cgalModels `RemeshingCellBase_3` +\cgalRefines `Triangulation_cell_base_with_info_3` + +*/ + template > + typename Cb = CGAL::Triangulation_cell_base_3 > class Remeshing_cell_base - : public CGAL::Triangulation_cell_base_with_info_3 + : public CGAL::Triangulation_cell_base_with_info_3 { - typedef CGAL::Triangulation_cell_base_with_info_3 Base; + typedef CGAL::Triangulation_cell_base_with_info_3 Base; typedef typename Base::Vertex_handle Vertex_handle; typedef typename Base::Cell_handle Cell_handle; @@ -61,7 +82,7 @@ namespace Tetrahedral_remeshing struct Rebind_TDS { typedef typename Cb::template Rebind_TDS::Other Cb2; - typedef Remeshing_cell_base Other; + typedef Remeshing_cell_base Other; }; Remeshing_cell_base() @@ -131,11 +152,11 @@ namespace Tetrahedral_remeshing - template < class K, class Info, class Cb > + template < class Gt, class Info, class Cb > std::istream& - operator>>(std::istream &is, Remeshing_cell_base &c) + operator>>(std::istream &is, Remeshing_cell_base &c) { - typename Remeshing_cell_base::Subdomain_index index; + typename Remeshing_cell_base::Subdomain_index index; if (is_ascii(is)) is >> index; else @@ -157,9 +178,9 @@ namespace Tetrahedral_remeshing return is; } - template < class K, class Info, class Cb > + template < class Gt, class Info, class Cb > std::ostream& - operator<<(std::ostream &os, const Remeshing_cell_base &c) + operator<<(std::ostream &os, const Remeshing_cell_base &c) { if (is_ascii(os)) os << c.subdomain_index(); diff --git a/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/Remeshing_vertex_base.h b/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/Remeshing_vertex_base.h index 4eddd26f9fb..4907bfb0913 100644 --- a/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/Remeshing_vertex_base.h +++ b/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/Remeshing_vertex_base.h @@ -96,10 +96,11 @@ namespace Tetrahedral_remeshing cache_validity_ = false; } // documented as set_cache() - void set_cache(const std::size_t i, const std::size_t j) + void set_cache(const std::size_t& nb_incident_facets, + const std::size_t& nb_incident_subdomains); { - number_of_incident_facets_ = i; - number_of_components_ = j; + number_of_incident_facets_ = nb_incident_facets; + number_of_components_ = nb_incident_subdomains; cache_validity_ = true; } From 51eea5fcf03907cf3dbbfa8e1a9007528fb51bf0 Mon Sep 17 00:00:00 2001 From: Jane Tournois Date: Fri, 13 Dec 2019 16:07:39 +0100 Subject: [PATCH 034/568] wip documentation after review of Pierre & Laurent --- .../Concepts/RemeshingVertexBase_3.h | 2 +- .../Tetrahedral_remeshing/NamedParameters.txt | 21 ++++--- .../Tetrahedral_remeshing/CMakeLists.txt | 2 +- .../Tetrahedral_remeshing/generate_input.cpp | 62 +++++++++++-------- .../tetrahedral_remeshing_example.cpp | 47 +++++++++----- .../Remeshing_cell_base.h | 6 +- .../Remeshing_triangulation_3.h | 42 +++++++++++-- .../Remeshing_vertex_base.h | 23 ++++++- .../include/CGAL/tetrahedral_remeshing.h | 38 +++++++++--- 9 files changed, 176 insertions(+), 67 deletions(-) diff --git a/Tetrahedral_remeshing/doc/Tetrahedral_remeshing/Concepts/RemeshingVertexBase_3.h b/Tetrahedral_remeshing/doc/Tetrahedral_remeshing/Concepts/RemeshingVertexBase_3.h index 0a426121a12..28418808342 100644 --- a/Tetrahedral_remeshing/doc/Tetrahedral_remeshing/Concepts/RemeshingVertexBase_3.h +++ b/Tetrahedral_remeshing/doc/Tetrahedral_remeshing/Concepts/RemeshingVertexBase_3.h @@ -2,7 +2,7 @@ /// \cgalConcept /// /// The concept `RemeshingVertexBase_3` defines the requirements for the vertex base -/// used in the triangulation given as input to the remeshing algorithm +/// used in the triangulation given as input to the remeshing algorithm. /// /// \cgalRefines `TriangulationVertexBase_3`, `CopyConstructible` /// \cgalHasModel `CGAL::Tetrahedral_remeshing::Remeshing_vertex_base`. diff --git a/Tetrahedral_remeshing/doc/Tetrahedral_remeshing/NamedParameters.txt b/Tetrahedral_remeshing/doc/Tetrahedral_remeshing/NamedParameters.txt index 49a83dde83b..890fb50bb05 100644 --- a/Tetrahedral_remeshing/doc/Tetrahedral_remeshing/NamedParameters.txt +++ b/Tetrahedral_remeshing/doc/Tetrahedral_remeshing/NamedParameters.txt @@ -40,22 +40,26 @@ in the mesh.\n \cgalNPBegin{protect_boundaries} \anchor Remeshing_protect_boundaries -a boolean that states whether the boudaries should be modified by the remeshing +a Boolean that states whether the boundaries should be preserved by the remeshing process. Boundaries are between the exterior and the interior, between two subdomains, and between the areas selected or not for remeshing -(cf \ref Remeshing_cell_selector). If `true` they cannot.\n +(cf \ref Remeshing_cell_is_selected_map). +If `true`, they are preserved. Otherwise, they can be modified.\n \b Type : `bool` \n -\b Default value is `true` +\b Default value is `false` \cgalNPEnd \cgalNPBegin{edge_is_constrained_map} \anchor Remeshing_edge_is_constrained_map is a property map containing information about edges of the input triangulation -being marked as constrained or not. In `tetrahedral_adaptive_remeshing()`, -the marked edges are constrained.\n +being marked as constrained or not.\n Type: a class model of `ReadWritePropertyMap` with -`Triangulation::%Edge` as key type and -`bool` as value type. It must be default constructible.\n +`std::pair` as key type and +`bool` as value type. +During the meshing process, the set of constrained edges evolves consistently with +edge splits and collapses, so the property map must be writable. +It must be default constructible. +\n Default: a default property map where no edge is constrained \cgalNPEnd @@ -67,6 +71,9 @@ Only selected cells are modified (and possibly their neighbors if surfaces are modified) by the remeshing process. Unselected cells will not be modified.\n \b Type : a class model of `ReadWritePropertyMap` with `Triangulation::%Cell_handle` as key type and `bool` as value type. +During the meshing process, the set of selected cells evolves consistently with +the atomic operations that are performed, +so the property map must be writable. It must be default constructible.\n Default: a default property map where all cells of the domain (i.e. with a non-zero `Subdomain_index` are selected) diff --git a/Tetrahedral_remeshing/examples/Tetrahedral_remeshing/CMakeLists.txt b/Tetrahedral_remeshing/examples/Tetrahedral_remeshing/CMakeLists.txt index de476499215..c56d226c62f 100644 --- a/Tetrahedral_remeshing/examples/Tetrahedral_remeshing/CMakeLists.txt +++ b/Tetrahedral_remeshing/examples/Tetrahedral_remeshing/CMakeLists.txt @@ -26,7 +26,7 @@ endif() # Creating entries for all C++ files with "main" routine # ########################################################## create_single_source_cgal_program( "tetrahedral_remeshing_example.cpp" ) -# create_single_source_cgal_program( "tetrahedral_remeshing_with_features.cpp") + create_single_source_cgal_program( "tetrahedral_remeshing_with_features.cpp") # create_single_source_cgal_program( "tetrahedral_remeshing_of_one_subdomain.cpp") create_single_source_cgal_program( "generate_input.cpp ") diff --git a/Tetrahedral_remeshing/examples/Tetrahedral_remeshing/generate_input.cpp b/Tetrahedral_remeshing/examples/Tetrahedral_remeshing/generate_input.cpp index 47185fcb80e..9af134b860f 100644 --- a/Tetrahedral_remeshing/examples/Tetrahedral_remeshing/generate_input.cpp +++ b/Tetrahedral_remeshing/examples/Tetrahedral_remeshing/generate_input.cpp @@ -4,21 +4,38 @@ #include #include -#include - -#include #include typedef CGAL::Exact_predicates_inexact_constructions_kernel K; - typedef CGAL::Tetrahedral_remeshing::Remeshing_triangulation_3 T3; -typedef int Corner_index; -typedef int Curve_segment_index; -typedef CGAL::Mesh_complex_3_in_triangulation_3 C3t3; +bool load_binary_triangulation(std::istream& is, T3& t3) +{ + std::string s; + if (!(is >> s)) return false; + bool binary = (s == "binary"); + if (binary) { + if (!(is >> s)) return false; + } + if (s != "CGAL" || !(is >> s) || s != "c3t3") + return false; + + std::getline(is, s); + if (binary) CGAL::set_binary_mode(is); + is >> t3; + return bool(is); +} + +bool save_binary_triangulation(std::ostream& os, const T3& t3) +{ + typedef T3::Geom_traits::FT FT; + os << "binary CGAL c3t3\n"; + CGAL::set_binary_mode(os); + return !!(os << t3); +} int main(int argc, char* argv[]) { @@ -28,8 +45,6 @@ int main(int argc, char* argv[]) char* filename; T3 tr; - C3t3 c3t3; - c3t3.triangulation() = tr; CGAL::Random rng; @@ -43,42 +58,39 @@ int main(int argc, char* argv[]) for (T3::Finite_cells_iterator cit = tr.finite_cells_begin(); cit != tr.finite_cells_end(); ++cit) { - c3t3.add_to_complex(cit, 1); + cit->set_subdomain_index(1); } } else if (input_id == 2) //sphere separated in 2 subdomains by a plane { filename = "data/triangulation_two_subdomains.binary.cgal"; - while (c3t3.triangulation().number_of_vertices() < nbv) - c3t3.triangulation().insert( + while (tr.number_of_vertices() < nbv) + tr.insert( T3::Point(rng.get_double(-1., 1.), rng.get_double(-1., 1.), rng.get_double(-1., 1.))); const K::Plane_3 plane(K::Point_3(0,0,0), K::Point_3(0,1,0), K::Point_3(0,0,1)); - for (T3::Finite_cells_iterator cit = c3t3.triangulation().finite_cells_begin(); - cit != c3t3.triangulation().finite_cells_end(); ++cit) + for (T3::Finite_cells_iterator cit = tr.finite_cells_begin(); + cit != tr.finite_cells_end(); ++cit) { - int index; if(plane.has_on_positive_side( CGAL::centroid(cit->vertex(0)->point(), cit->vertex(1)->point(), cit->vertex(2)->point(), cit->vertex(3)->point()))) - index = 1; + cit->set_subdomain_index(1); else - index = 2; - - c3t3.add_to_complex(cit, index); + cit->set_subdomain_index(2); } } std::ofstream out(filename, std::ios_base::out | std::ios_base::binary); - CGAL::Mesh_3::save_binary_file(out, c3t3); + save_binary_triangulation(out, tr); - std::string file_in(filename); - std::string file_out = file_in.substr(0, file_in.find_first_of(".")); - file_out.append(".mesh"); - std::ofstream medit_out(file_out.c_str(), std::ios_base::out); - c3t3.output_to_medit(medit_out); +// std::string file_in(filename); +// std::string file_out = file_in.substr(0, file_in.find_first_of(".")); +// file_out.append(".mesh"); +// std::ofstream medit_out(file_out.c_str(), std::ios_base::out); +// c3t3.output_to_medit(medit_out); return (!out.bad()); } diff --git a/Tetrahedral_remeshing/examples/Tetrahedral_remeshing/tetrahedral_remeshing_example.cpp b/Tetrahedral_remeshing/examples/Tetrahedral_remeshing/tetrahedral_remeshing_example.cpp index 306f0e6b82f..47d4bd79e2f 100644 --- a/Tetrahedral_remeshing/examples/Tetrahedral_remeshing/tetrahedral_remeshing_example.cpp +++ b/Tetrahedral_remeshing/examples/Tetrahedral_remeshing/tetrahedral_remeshing_example.cpp @@ -9,18 +9,35 @@ #include #include -#include typedef CGAL::Exact_predicates_inexact_constructions_kernel K; typedef CGAL::Tetrahedral_remeshing::Remeshing_triangulation_3 T3; -//todo : add specialization for Cell_base without info -// (does not compile with `void` instead of `int`) -typedef int Corner_index; -typedef int Curve_segment_index; -typedef CGAL::Mesh_complex_3_in_triangulation_3 C3t3; +bool load_binary_triangulation(std::istream& is, T3& t3) +{ + std::string s; + if (!(is >> s)) return false; + bool binary = (s == "binary"); + if (binary) { + if (!(is >> s)) return false; + } + if (s != "CGAL" || !(is >> s) || s != "c3t3") + return false; + std::getline(is, s); + if (binary) CGAL::set_binary_mode(is); + is >> t3; + return bool(is); +} + +bool save_binary_triangulation(std::ostream& os, const T3& t3) +{ + typedef T3::Geom_traits::FT FT; + os << "binary CGAL c3t3\n"; + CGAL::set_binary_mode(os); + return !!(os << t3); +} int main(int argc, char* argv[]) { @@ -29,14 +46,14 @@ int main(int argc, char* argv[]) std::ifstream input(filename, std::ios::in | std::ios::binary); - C3t3 c3t3; + T3 t3; if (!input) return false; - if( !CGAL::Mesh_3::load_binary_file(input, c3t3)) + if( !load_binary_triangulation(input, t3)) return false; - CGAL::tetrahedral_adaptive_remeshing(c3t3.triangulation(), target_edge_length); + CGAL::tetrahedral_adaptive_remeshing(t3, target_edge_length); // save output const std::string file_in(filename); @@ -45,13 +62,13 @@ int main(int argc, char* argv[]) std::string file_out = file_in.substr(0, file_in.find_first_of(".")); file_out.append("_out.binary.cgal"); std::ofstream out(file_out.c_str(), std::ios_base::out | std::ios_base::binary); - CGAL::Mesh_3::save_binary_file(out, c3t3); + save_binary_triangulation(out, t3); - // ascii - file_out = file_in.substr(0, file_in.find_first_of(".")); - file_out.append("_out.mesh"); - std::ofstream medit_out(file_out.c_str(), std::ios_base::out); - c3t3.output_to_medit(medit_out); + //// ascii + //file_out = file_in.substr(0, file_in.find_first_of(".")); + //file_out.append("_out.mesh"); + //std::ofstream medit_out(file_out.c_str(), std::ios_base::out); + //c3t3.output_to_medit(medit_out); return EXIT_SUCCESS; } diff --git a/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/Remeshing_cell_base.h b/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/Remeshing_cell_base.h index 67c6b3dbfe8..143ea139ee1 100644 --- a/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/Remeshing_cell_base.h +++ b/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/Remeshing_cell_base.h @@ -35,7 +35,7 @@ namespace Tetrahedral_remeshing /*! \ingroup PkgTetrahedralRemeshingClasses -The class `Remeshing_cell_base` is a model of the concept `RemeshingCellBase_3`. +The class `Remeshing_cell_base` is a model of the concept `RemeshingCellBase_3`. It is designed to serve as cell base class for the 3D triangulation used in the tetrahedral remeshing process. @@ -45,7 +45,7 @@ It has to be a model of the concept `RemeshingTriangulationTraits_3`. \tparam Info is the information the user would like to add to a cell. It has to be `DefaultConstructible` and `Assignable`. -\tparam Cb is a cell base class from which `Triangulation_cell_base_with_info_3` derives. +\tparam Cb is a cell base class from which `Remeshing_cell_base` derives. It must be a model of the `TriangulationCellBase_3` concept. It has the default value `Triangulation_cell_base_3`. @@ -133,7 +133,7 @@ It has the default value `Triangulation_cell_base_3`. return 0; } - /// Returns true if facet lies on a surface patch + /// Returns `true` if facet lies on a surface patch bool is_facet_on_surface(const int& facet) const { CGAL_precondition(facet >= 0 && facet<4); diff --git a/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/Remeshing_triangulation_3.h b/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/Remeshing_triangulation_3.h index 0ea799be762..f717942545b 100644 --- a/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/Remeshing_triangulation_3.h +++ b/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/Remeshing_triangulation_3.h @@ -31,6 +31,7 @@ #include #include +#include #include #include @@ -39,22 +40,53 @@ namespace CGAL { namespace Tetrahedral_remeshing { + /*! + \ingroup PkgTetrahedralRemeshingClasses + + The class `Remeshing_triangulation_3` + is a class template which provides the triangulation type to be used + for the 3D triangulation + used in the tetrahedral remeshing process. + + \tparam Gt is the geometric traits class. + It has to be a model of the concept `RemeshingTriangulationTraits_3`. + + \tparam Info is the information the user would like to add to a cell. + It has to be `DefaultConstructible` and `Assignable`. + + \tparam Concurrency_tag enables sequential versus parallel implementation of the + triangulation data structure. + Possible values are `Sequential_tag` (the default) and `Parallel_tag`. + + \tparam Cb is a cell base class from which `Remeshing_cell_base` derives. + It must be a model of the `TriangulationCellBase_3` concept. + It has the default value `Triangulation_cell_base_3`. + + \tparam Vb is a vertex base class deriving from `Triangulation_vertex_base_3`. + It must be a model of the `TriangulationVertexBase_3` concept. + It has the default value `Triangulation_vertex_base_3`. + + \cgalRefines `Triangulation_3` + + */ template > + typename Info, + typename Concurrency_tag = CGAL::Sequential_tag, + typename Cb = CGAL::Triangulation_cell_base_3, + typename Vb = CGAL::Triangulation_vertex_base_3 > class Remeshing_triangulation_3 : public CGAL::Triangulation_3, + Remeshing_vertex_base, Remeshing_cell_base > > { - typedef Remeshing_vertex_base RVb; + typedef Remeshing_vertex_base RVb; typedef Remeshing_cell_base RCb; public: - typedef CGAL::Triangulation_data_structure_3 Tds; + typedef CGAL::Triangulation_data_structure_3 Tds; typedef CGAL::Triangulation_3 Self; typedef Self type; }; diff --git a/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/Remeshing_vertex_base.h b/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/Remeshing_vertex_base.h index 4907bfb0913..57d2a143ba7 100644 --- a/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/Remeshing_vertex_base.h +++ b/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/Remeshing_vertex_base.h @@ -40,6 +40,25 @@ namespace Tetrahedral_remeshing }; } + /*! + \ingroup PkgTetrahedralRemeshingClasses + + The class `Remeshing_vertex_base` is a model of the concept `RemeshingVertexBase_3`. + It is designed to serve as vertex base class for the 3D triangulation + used in the tetrahedral remeshing process. + + \tparam Gt is the geometric traits class. + It has to be a model of the concept `RemeshingTriangulationTraits_3`. + + \tparam Vb is a vertex base class from which `Remeshing_vertex_base` derives. + It must be a model of the `TriangulationVertexBase_3` concept. + It has the default value `Triangulation_vertex_base_3`. + + \cgalModels `RemeshingVertexBase_3` + \cgalRefines `Triangulation_vertex_base_3` + + */ + template > class Remeshing_vertex_base @@ -96,8 +115,8 @@ namespace Tetrahedral_remeshing cache_validity_ = false; } // documented as set_cache() - void set_cache(const std::size_t& nb_incident_facets, - const std::size_t& nb_incident_subdomains); + void set_c2t3_cache(const std::size_t& nb_incident_facets, + const std::size_t& nb_incident_subdomains) { number_of_incident_facets_ = nb_incident_facets; number_of_components_ = nb_incident_subdomains; diff --git a/Tetrahedral_remeshing/include/CGAL/tetrahedral_remeshing.h b/Tetrahedral_remeshing/include/CGAL/tetrahedral_remeshing.h index 1e4224f0313..2ae275180cc 100644 --- a/Tetrahedral_remeshing/include/CGAL/tetrahedral_remeshing.h +++ b/Tetrahedral_remeshing/include/CGAL/tetrahedral_remeshing.h @@ -41,11 +41,28 @@ namespace CGAL * \ingroup PkgTetrahedralRemeshingRef * remeshes a tetrahedral mesh. * - * This operation sequentially performs edge splits, edge collapses, - * edge flips, smoothing and projection to the initial surface to generate - * a quality mesh with a prescribed edge length. + * This function takes as input a 3-dimensional triangulation + * and performs a sequence of atomic operations + * in order to generate as output a quality mesh with a prescribed edge length. + * These atomic operations are performed as follows : + * - edge splits, until all edges satisfy a prescribed length criterion, + * - edge collapses, ntil all edges satisfy a prescribed length criterion, + * - edge flips, to locally improve dihedral angles, until they can't be improved by flipping, + * - global smoothing by vertex relocations, + * - re-projection of boundary vertices to the initial surface. * - * @tparam Triangulation model of `Triangulation_3`, + * This remeshing function can deal with multi-domains and preserves the geometry of + * subdomains throughout the remeshing process. Subdomains are defined by indices that + * are stored in the cells of the input triangulation, following the `RemeshingCellBase_3` + * concept. + * The surfacic interfaces between subdomains are formed by facets which two incident cells + * have different subdomain indices. + * The edges where three or more subdomains meet form feature polylines, + * and are considered as constrained edges. + * + * + * @tparam Triangulation a 3-dimensional triangulation + * deriving from `Triangulation_3`, * with cell base model of `RemeshingCellBase_3` * and vertex base model of `RemeshingVertexBase_3`. * @@ -61,19 +78,24 @@ namespace CGAL * sequence of atomic operations * performed (listed in the above description) * \cgalParamEnd - * \cgalParamBegin{protect_boundaries} If `true`, the volume boundaries cannot be modified + * \cgalParamBegin{protect_boundaries} If `true`, none of the volume boundaries can be modified. + * Otherwise, the geometry is preserved, but atomic operations can be performed on the + * surfaces, and along feature polylines. * \cgalParamEnd * \cgalParamBegin{edge_is_constrained_map} a property map containing the * constrained - or - not status of each edge of `tr`. A constrained edge can be split - * or collapsed, but not flipped, nor its endpoints moved by smoothing + * or collapsed, but not flipped. +todo//// * Its endpoints could be moved by smoothing * \cgalParamEnd * \cgalParamBegin{cell_is_selected_map} a property map containing the * selected - or - not status for each cell of `tr` for remeshing. * Only selected cells are modified (and possibly their neighbors if surfaces are * modified) by remeshing. - * By default, all inside cells are selected. + * By default, all cells with a non-zero `Subdomain_index` are selected. * \cgalParamEnd * \cgalNamedParamsEnd + + * @todo implement 1D smoothing for constrained edges */ // * @tparam SizingField model of `CGAL::Sizing_field` @@ -101,7 +123,7 @@ namespace CGAL using boost::get_param; bool protect = choose_param(get_param(np, internal_np::protect_boundaries), - true); + false); // bool adaptive = choose_param(get_param(np, internal_np::adaptive_size), // false); std::size_t max_it = choose_param(get_param(np, internal_np::number_of_iterations), From cd77b55210d933e1cecd527025b2cdf4bc6cff8f Mon Sep 17 00:00:00 2001 From: Jane Tournois Date: Fri, 13 Dec 2019 17:00:07 +0100 Subject: [PATCH 035/568] replace constrained map of edges by constrained map of pairs of vertices because there are more than one representation of the same Edge, all around it --- .../Tetrahedral_remeshing/NamedParameters.txt | 1 + .../tetrahedral_remeshing_with_features.cpp | 17 +++++++++-------- .../tetrahedral_adaptive_remeshing_impl.h | 3 ++- .../internal/tetrahedral_remeshing_helpers.h | 18 ++++++++---------- .../include/CGAL/tetrahedral_remeshing.h | 4 ++-- 5 files changed, 22 insertions(+), 21 deletions(-) diff --git a/Tetrahedral_remeshing/doc/Tetrahedral_remeshing/NamedParameters.txt b/Tetrahedral_remeshing/doc/Tetrahedral_remeshing/NamedParameters.txt index 890fb50bb05..51ddbf316c2 100644 --- a/Tetrahedral_remeshing/doc/Tetrahedral_remeshing/NamedParameters.txt +++ b/Tetrahedral_remeshing/doc/Tetrahedral_remeshing/NamedParameters.txt @@ -56,6 +56,7 @@ being marked as constrained or not.\n Type: a class model of `ReadWritePropertyMap` with `std::pair` as key type and `bool` as value type. +The pairs must be ordered to ensure consistency. During the meshing process, the set of constrained edges evolves consistently with edge splits and collapses, so the property map must be writable. It must be default constructible. diff --git a/Tetrahedral_remeshing/examples/Tetrahedral_remeshing/tetrahedral_remeshing_with_features.cpp b/Tetrahedral_remeshing/examples/Tetrahedral_remeshing/tetrahedral_remeshing_with_features.cpp index 17362092cfe..d631499c460 100644 --- a/Tetrahedral_remeshing/examples/Tetrahedral_remeshing/tetrahedral_remeshing_with_features.cpp +++ b/Tetrahedral_remeshing/examples/Tetrahedral_remeshing/tetrahedral_remeshing_with_features.cpp @@ -1,5 +1,6 @@ #include #include +#include #define CGAL_TETRAHEDRAL_REMESHING_VERBOSE #define CGAL_DUMP_REMESHING_STEPS @@ -9,7 +10,7 @@ #include #include -#include +//#include #include #include @@ -19,8 +20,6 @@ typedef CGAL::Exact_predicates_inexact_constructions_kernel K; typedef CGAL::Tetrahedral_remeshing::Remeshing_triangulation_3 Remeshing_triangulation; -//todo : add specialization for Cell_base without info -// (does not compile with `void` instead of `int`) typedef Remeshing_triangulation::Point Point; typedef Remeshing_triangulation::Vertex_handle Vertex_handle; @@ -33,7 +32,7 @@ class Constrained_edges_property_map public: typedef bool value_type; typedef bool reference; - typedef typename T3::Edge key_type; + typedef std::pair key_type; typedef boost::read_write_property_map_tag category; private: @@ -53,6 +52,7 @@ public: const bool b) { CGAL_assertion(map.m_set_ptr != NULL); + CGAL_assertion(k.first < k.second); if (b) map.m_set_ptr->insert(k); else map.m_set_ptr->erase(k); } @@ -61,6 +61,7 @@ public: const key_type& k) { CGAL_assertion(map.m_set_ptr != NULL); + CGAL_assertion(k.first < k.second); return map.m_set_ptr->count(k); } }; @@ -68,17 +69,17 @@ public: void add_edge(Vertex_handle v1, Vertex_handle v2, const Remeshing_triangulation& tr, - boost::unordered_set& constraints) + boost::unordered_set >& constraints) { Cell_handle c; int i, j; if(tr.is_edge(v1, v2, c, i, j)) - constraints.insert(Edge(c, i, j)); + constraints.insert(std::make_pair(c->vertex(i), c->vertex(j))); } void generate_input(const std::size_t& n, const char* filename, - boost::unordered_set& constraints) + boost::unordered_set >& constraints) { Remeshing_triangulation tr; CGAL::Random rng; @@ -123,7 +124,7 @@ void generate_input(const std::size_t& n, int main(int argc, char* argv[]) { - boost::unordered_set constraints; + boost::unordered_set > constraints; generate_input(1000, "data/sphere_in_cube.tr.cgal", constraints); const char* filename = (argc > 1) ? argv[1] : "data/sphere_in_cube.tr.cgal"; diff --git a/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/tetrahedral_adaptive_remeshing_impl.h b/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/tetrahedral_adaptive_remeshing_impl.h index a4973fd4cba..7fd14f89f42 100644 --- a/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/tetrahedral_adaptive_remeshing_impl.h +++ b/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/tetrahedral_adaptive_remeshing_impl.h @@ -362,7 +362,8 @@ namespace internal ++eit) { Edge e = *eit; - if (get(ecmap, e) || nb_incident_subdomains(e, m_c3t3) > 2) + if (get(ecmap, CGAL::Tetrahedral_remeshing::make_vertex_pair(e)) + || nb_incident_subdomains(e, m_c3t3) > 2) { m_c3t3.add_to_complex(e, 1); diff --git a/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/tetrahedral_remeshing_helpers.h b/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/tetrahedral_remeshing_helpers.h index ed2e4b156a8..22068a8eb11 100644 --- a/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/tetrahedral_remeshing_helpers.h +++ b/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/tetrahedral_remeshing_helpers.h @@ -131,6 +131,13 @@ namespace Tetrahedral_remeshing point(c->vertex(3)->point())); } + template + std::pair make_vertex_pair(const Vh v1, const Vh v2) + { + if (v2 < v1) return std::make_pair(v2, v1); + else return std::make_pair(v1, v2); + } + template std::pair make_vertex_pair(const typename Tr::Edge& e) @@ -138,16 +145,7 @@ namespace Tetrahedral_remeshing typedef typename Tr::Vertex_handle Vertex_handle; Vertex_handle v1 = e.first->vertex(e.second); Vertex_handle v2 = e.first->vertex(e.third); - if (v2 < v1) std::swap(v1, v2); - - return std::make_pair(v1, v2); - } - - template - std::pair make_vertex_pair(const Vh v1, const Vh v2) - { - if (v2 < v1) return std::make_pair(v2, v1); - else return std::make_pair(v1, v2); + return make_vertex_pair(v1, v2); } template diff --git a/Tetrahedral_remeshing/include/CGAL/tetrahedral_remeshing.h b/Tetrahedral_remeshing/include/CGAL/tetrahedral_remeshing.h index 2ae275180cc..06b1a828b4f 100644 --- a/Tetrahedral_remeshing/include/CGAL/tetrahedral_remeshing.h +++ b/Tetrahedral_remeshing/include/CGAL/tetrahedral_remeshing.h @@ -117,7 +117,6 @@ todo//// * Its endpoints could be moved by smoothing CGAL_assertion(tr.is_valid(true)); typedef Triangulation Tr; - typedef typename Tr::Edge Edge; using boost::choose_param; using boost::get_param; @@ -138,7 +137,8 @@ todo//// * Its endpoints could be moved by smoothing = choose_param(get_param(np, internal_np::cell_selector), Tetrahedral_remeshing::internal::All_cells_selected()); - typedef Tetrahedral_remeshing::internal::No_constraint_pmap No_constraint; + typedef std::pair Edge_vv; + typedef Tetrahedral_remeshing::internal::No_constraint_pmap No_constraint; typedef typename boost::lookup_named_param_def < internal_np::edge_is_constrained_t, From fb71408aed612eb59b3fd2a06b99963d66538e0c Mon Sep 17 00:00:00 2001 From: Jane Tournois Date: Mon, 16 Dec 2019 17:20:28 +0100 Subject: [PATCH 036/568] replace cell_base_with_info by a visitor the goal is to let a visitor deal with external cell info it also simplifies the API --- .../Tetrahedral_remeshing/generate_input.cpp | 2 +- .../tetrahedral_remeshing_example.cpp | 2 +- ...tetrahedral_remeshing_of_one_subdomain.cpp | 2 +- .../tetrahedral_remeshing_with_features.cpp | 2 +- .../Remeshing_cell_base.h | 12 ++--- .../Remeshing_triangulation_3.h | 52 +++++++++++++++---- .../internal/collapse_short_edges.h | 4 +- .../internal/flip_edges.h | 4 +- .../internal/split_long_edges.h | 15 +++--- 9 files changed, 61 insertions(+), 34 deletions(-) diff --git a/Tetrahedral_remeshing/examples/Tetrahedral_remeshing/generate_input.cpp b/Tetrahedral_remeshing/examples/Tetrahedral_remeshing/generate_input.cpp index 9af134b860f..971f0401dfa 100644 --- a/Tetrahedral_remeshing/examples/Tetrahedral_remeshing/generate_input.cpp +++ b/Tetrahedral_remeshing/examples/Tetrahedral_remeshing/generate_input.cpp @@ -9,7 +9,7 @@ typedef CGAL::Exact_predicates_inexact_constructions_kernel K; -typedef CGAL::Tetrahedral_remeshing::Remeshing_triangulation_3 T3; +typedef CGAL::Tetrahedral_remeshing::Remeshing_triangulation_3 T3; bool load_binary_triangulation(std::istream& is, T3& t3) diff --git a/Tetrahedral_remeshing/examples/Tetrahedral_remeshing/tetrahedral_remeshing_example.cpp b/Tetrahedral_remeshing/examples/Tetrahedral_remeshing/tetrahedral_remeshing_example.cpp index 47d4bd79e2f..dc014048bc1 100644 --- a/Tetrahedral_remeshing/examples/Tetrahedral_remeshing/tetrahedral_remeshing_example.cpp +++ b/Tetrahedral_remeshing/examples/Tetrahedral_remeshing/tetrahedral_remeshing_example.cpp @@ -12,7 +12,7 @@ typedef CGAL::Exact_predicates_inexact_constructions_kernel K; -typedef CGAL::Tetrahedral_remeshing::Remeshing_triangulation_3 T3; +typedef CGAL::Tetrahedral_remeshing::Remeshing_triangulation_3 T3; bool load_binary_triangulation(std::istream& is, T3& t3) { diff --git a/Tetrahedral_remeshing/examples/Tetrahedral_remeshing/tetrahedral_remeshing_of_one_subdomain.cpp b/Tetrahedral_remeshing/examples/Tetrahedral_remeshing/tetrahedral_remeshing_of_one_subdomain.cpp index b892bb4b44b..de784042d75 100644 --- a/Tetrahedral_remeshing/examples/Tetrahedral_remeshing/tetrahedral_remeshing_of_one_subdomain.cpp +++ b/Tetrahedral_remeshing/examples/Tetrahedral_remeshing/tetrahedral_remeshing_of_one_subdomain.cpp @@ -14,7 +14,7 @@ typedef CGAL::Exact_predicates_inexact_constructions_kernel K; typedef CGAL::Triangulation_3 T3; -typedef CGAL::Tetrahedral_remeshing::Remeshing_triangulation_3 Remeshing_triangulation; +typedef CGAL::Tetrahedral_remeshing::Remeshing_triangulation_3 Remeshing_triangulation; //todo : add specialization for Cell_base without info // (does not compile with `void` instead of `int`) diff --git a/Tetrahedral_remeshing/examples/Tetrahedral_remeshing/tetrahedral_remeshing_with_features.cpp b/Tetrahedral_remeshing/examples/Tetrahedral_remeshing/tetrahedral_remeshing_with_features.cpp index d631499c460..bab18193749 100644 --- a/Tetrahedral_remeshing/examples/Tetrahedral_remeshing/tetrahedral_remeshing_with_features.cpp +++ b/Tetrahedral_remeshing/examples/Tetrahedral_remeshing/tetrahedral_remeshing_with_features.cpp @@ -19,7 +19,7 @@ typedef CGAL::Exact_predicates_inexact_constructions_kernel K; -typedef CGAL::Tetrahedral_remeshing::Remeshing_triangulation_3 Remeshing_triangulation; +typedef CGAL::Tetrahedral_remeshing::Remeshing_triangulation_3 Remeshing_triangulation; typedef Remeshing_triangulation::Point Point; typedef Remeshing_triangulation::Vertex_handle Vertex_handle; diff --git a/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/Remeshing_cell_base.h b/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/Remeshing_cell_base.h index 143ea139ee1..67e50c8e501 100644 --- a/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/Remeshing_cell_base.h +++ b/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/Remeshing_cell_base.h @@ -24,7 +24,6 @@ #include -#include #include @@ -54,13 +53,12 @@ It has the default value `Triangulation_cell_base_3`. */ template > class Remeshing_cell_base - : public CGAL::Triangulation_cell_base_with_info_3 + : public Cb { - typedef CGAL::Triangulation_cell_base_with_info_3 Base; + typedef Cb Base; typedef typename Base::Vertex_handle Vertex_handle; typedef typename Base::Cell_handle Cell_handle; @@ -82,7 +80,7 @@ It has the default value `Triangulation_cell_base_3`. struct Rebind_TDS { typedef typename Cb::template Rebind_TDS::Other Cb2; - typedef Remeshing_cell_base Other; + typedef Remeshing_cell_base Other; }; Remeshing_cell_base() @@ -154,7 +152,7 @@ It has the default value `Triangulation_cell_base_3`. template < class Gt, class Info, class Cb > std::istream& - operator>>(std::istream &is, Remeshing_cell_base &c) + operator>>(std::istream &is, Remeshing_cell_base &c) { typename Remeshing_cell_base::Subdomain_index index; if (is_ascii(is)) @@ -180,7 +178,7 @@ It has the default value `Triangulation_cell_base_3`. template < class Gt, class Info, class Cb > std::ostream& - operator<<(std::ostream &os, const Remeshing_cell_base &c) + operator<<(std::ostream &os, const Remeshing_cell_base &c) { if (is_ascii(os)) os << c.subdomain_index(); diff --git a/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/Remeshing_triangulation_3.h b/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/Remeshing_triangulation_3.h index f717942545b..e98b4c3941b 100644 --- a/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/Remeshing_triangulation_3.h +++ b/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/Remeshing_triangulation_3.h @@ -40,6 +40,24 @@ namespace CGAL { namespace Tetrahedral_remeshing { + class Default_remeshing_visitor + { + public: + template + void before_split(const Tr& tr, + const typename Tr::Edge& e) {} + template + void after_split(const Tr& tr, + const typename Tr::Vertex_handle new_v) {} + template + void after_add_cell(CellHandleOld co, + CellHandleNew cn) const {} + template + void before_flip(const CellHandle c) {} + template + void after_flip(CellHandle c) {} + }; + /*! \ingroup PkgTetrahedralRemeshingClasses @@ -70,25 +88,37 @@ namespace Tetrahedral_remeshing */ template, - typename Vb = CGAL::Triangulation_vertex_base_3 > + typename Vb = CGAL::Triangulation_vertex_base_3 +#ifndef DOXYGEN_RUNNING + , typename Cell_visitor = Default_remeshing_visitor +#endif + > class Remeshing_triangulation_3 : public CGAL::Triangulation_3, - Remeshing_cell_base + Remeshing_cell_base > > { - typedef Remeshing_vertex_base RVb; - typedef Remeshing_cell_base RCb; + typedef Remeshing_vertex_base RVb; + typedef Remeshing_cell_base RCb; public: typedef CGAL::Triangulation_data_structure_3 Tds; - typedef CGAL::Triangulation_3 Self; - typedef Self type; + typedef CGAL::Triangulation_3 Self; + typedef Self type; + + private: + Cell_visitor m_visitor; + + public: + Cell_visitor& visitor() + { + return m_visitor; + } }; namespace internal @@ -208,9 +238,9 @@ namespace Tetrahedral_remeshing }; - template + template void build_remeshing_triangulation(const T3& tr, - Remeshing_triangulation_3& remeshing_tr) + Remeshing_triangulation_3& remeshing_tr) { typedef typename T3::Triangulation_data_structure Tds; typedef Remeshing_triangulation_3::Tds RTds; @@ -225,9 +255,9 @@ namespace Tetrahedral_remeshing internal::Cell_converter())); } - template + template void build_from_remeshing_triangulation( - const Remeshing_triangulation_3& remeshing_tr, + const Remeshing_triangulation_3& remeshing_tr, T3& tr) { typedef typename T3::Triangulation_data_structure Tds; diff --git a/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/collapse_short_edges.h b/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/collapse_short_edges.h index bf1f8844e1c..56b9e8251e7 100644 --- a/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/collapse_short_edges.h +++ b/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/collapse_short_edges.h @@ -64,7 +64,7 @@ namespace internal typedef CGAL::Triangulation_incremental_builder_3 Builder; public: - CollapseTriangulation(const C3t3& c3t3, + CollapseTriangulation(C3t3& c3t3, const Edge& edge, Collapse_type _collapse_type) { @@ -109,7 +109,7 @@ namespace internal Cell_handle new_ch = builder.add_cell(v2v.left.at(ch->vertex(0)), v2v.left.at(ch->vertex(1)), v2v.left.at(ch->vertex(2)), v2v.left.at(ch->vertex(3))); new_ch->set_subdomain_index(ch->subdomain_index()); - new_ch->info() = ch->info(); + c3t3.triangulation().visitor().after_add_cell(ch, new_ch); c2c.left.insert(std::make_pair(ch, new_ch)); } diff --git a/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/flip_edges.h b/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/flip_edges.h index 15f3507ef64..11e982fda20 100644 --- a/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/flip_edges.h +++ b/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/flip_edges.h @@ -769,7 +769,7 @@ namespace internal //Subdomain index? typename C3t3::Subdomain_index subdomain = to_remove[0]->subdomain_index(); - typename C3t3::Triangulation::Cell::Info info = to_remove[0]->info(); + tr.visitor().before_flip(to_remove[0]); #ifdef CGAL_TETRAHEDRAL_REMESHING_DEBUG for (std::size_t i = 1; i < to_remove.size(); ++i) @@ -792,7 +792,7 @@ namespace internal new_cell->set_vertex(fi.second, vh); c3t3.add_to_complex(new_cell, subdomain); - new_cell->info() = info; + tr.visitor().after_flip(new_cell); cells_to_update.push_back(new_cell); } diff --git a/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/split_long_edges.h b/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/split_long_edges.h index 881c163c1b1..4b69c116935 100644 --- a/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/split_long_edges.h +++ b/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/split_long_edges.h @@ -49,7 +49,6 @@ namespace internal typedef typename Tr::Vertex_handle Vertex_handle; typedef typename Tr::Cell_handle Cell_handle; typedef typename Tr::Cell_circulator Cell_circulator; - typedef typename Tr::Cell::Info Cell_info; Tr& tr = c3t3.triangulation(); Vertex_handle v1 = e.first->vertex(e.second); @@ -57,7 +56,8 @@ namespace internal //backup subdomain info of incident cells before making changes short dimension = (c3t3.is_in_complex(e)) ? 1 : 3; - boost::unordered_map > info; + boost::unordered_map info; + tr.visitor().before_split(c3t3.triangulation(), e); Cell_circulator circ = tr.incident_cells(e); Cell_circulator end = circ; @@ -68,12 +68,10 @@ namespace internal //keys are the opposite facets to the ones not containing e, //because they will not be modified Facet opp_facet = tr.mirror_facet(Facet(circ, circ->index(v1))); - info.insert(std::make_pair(opp_facet, - std::make_pair(c3t3.subdomain_index(circ), circ->info()))); + info.insert(std::make_pair(opp_facet, c3t3.subdomain_index(circ))); opp_facet = tr.mirror_facet(Facet(circ, circ->index(v2))); - info.insert(std::make_pair(opp_facet, - std::make_pair(c3t3.subdomain_index(circ), circ->info()))); + info.insert(std::make_pair(opp_facet, c3t3.subdomain_index(circ))); ++circ; prev = curr; @@ -92,15 +90,16 @@ namespace internal c3t3.set_dimension(new_v, dimension); // update c3t3 + tr.visitor().after_split(tr, new_v); + std::vector new_cells; tr.incident_cells(new_v, std::back_inserter(new_cells)); for (std::size_t i = 0; i < new_cells.size(); ++i) { Cell_handle nci = new_cells[i]; Facet fi(nci, nci->index(new_v)); - Subdomain_index n_index = info.at(tr.mirror_facet(fi)).first; + Subdomain_index n_index = info.at(tr.mirror_facet(fi)); c3t3.set_subdomain_index(nci, n_index); - nci->info() = info.at(tr.mirror_facet(fi)).second; } return new_v; From 911cd4a82ffafa5ac53d13923c31f58445d89514 Mon Sep 17 00:00:00 2001 From: Jane Tournois Date: Tue, 17 Dec 2019 10:30:58 +0100 Subject: [PATCH 037/568] reintroduce examples and simplify converters --- .../Tetrahedral_remeshing/CMakeLists.txt | 2 +- .../tetrahedral_remeshing_with_features.cpp | 1 - .../Remeshing_triangulation_3.h | 16 ++++++++-------- 3 files changed, 9 insertions(+), 10 deletions(-) diff --git a/Tetrahedral_remeshing/examples/Tetrahedral_remeshing/CMakeLists.txt b/Tetrahedral_remeshing/examples/Tetrahedral_remeshing/CMakeLists.txt index c56d226c62f..6f2cf7e1a12 100644 --- a/Tetrahedral_remeshing/examples/Tetrahedral_remeshing/CMakeLists.txt +++ b/Tetrahedral_remeshing/examples/Tetrahedral_remeshing/CMakeLists.txt @@ -27,7 +27,7 @@ endif() # ########################################################## create_single_source_cgal_program( "tetrahedral_remeshing_example.cpp" ) create_single_source_cgal_program( "tetrahedral_remeshing_with_features.cpp") - # create_single_source_cgal_program( "tetrahedral_remeshing_of_one_subdomain.cpp") + create_single_source_cgal_program( "tetrahedral_remeshing_of_one_subdomain.cpp") create_single_source_cgal_program( "generate_input.cpp ") create_single_source_cgal_program( "test_mesh_loader.cpp ") diff --git a/Tetrahedral_remeshing/examples/Tetrahedral_remeshing/tetrahedral_remeshing_with_features.cpp b/Tetrahedral_remeshing/examples/Tetrahedral_remeshing/tetrahedral_remeshing_with_features.cpp index bab18193749..630f2f64011 100644 --- a/Tetrahedral_remeshing/examples/Tetrahedral_remeshing/tetrahedral_remeshing_with_features.cpp +++ b/Tetrahedral_remeshing/examples/Tetrahedral_remeshing/tetrahedral_remeshing_with_features.cpp @@ -10,7 +10,6 @@ #include #include -//#include #include #include diff --git a/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/Remeshing_triangulation_3.h b/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/Remeshing_triangulation_3.h index e98b4c3941b..68a8c240cbc 100644 --- a/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/Remeshing_triangulation_3.h +++ b/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/Remeshing_triangulation_3.h @@ -167,7 +167,7 @@ namespace Tetrahedral_remeshing typename TDS_tgt::Cell operator()(const typename TDS_src::Cell& c_src) const { typename TDS_tgt::Cell c_tgt; - c_tgt.set_subdomain_index(c_src.subdomain_index()); + c_tgt.set_subdomain_index(1);//c_src.subdomain_index()); // c_tgt.info() = c_src.info(); c_tgt.set_time_stamp(-1); return c_tgt; @@ -176,7 +176,7 @@ namespace Tetrahedral_remeshing void operator()(const typename TDS_src::Cell& c_src, typename TDS_tgt::Cell& c_tgt) const { - c_tgt.set_subdomain_index(c_src.subdomain_index()); +// c_tgt.set_subdomain_index(c_src.subdomain_index()); // c_tgt.info() = c_src.info(); } }; @@ -198,7 +198,7 @@ namespace Tetrahedral_remeshing typename TDS_tgt::Vertex v_tgt; v_tgt.set_point(conv(v_src.point())); v_tgt.set_time_stamp(-1); - v_tgt.set_dimension(v_src.info());//-1 if unset, 0,1,2, or 3 if set +// v_tgt.set_dimension(v_src.info());//-1 if unset, 0,1,2, or 3 if set return v_tgt; } //This operator is meant to be used in case heavy data should transferred to v_tgt. @@ -212,7 +212,7 @@ namespace Tetrahedral_remeshing CGAL::Cartesian_converter conv; v_tgt.set_point(conv(v_src.point())); - v_tgt.set_dimension(v_src.info()); +// v_tgt.set_dimension(v_src.info()); } }; @@ -223,7 +223,7 @@ namespace Tetrahedral_remeshing typename TDS_tgt::Cell operator()(const typename TDS_src::Cell& c_src) const { typename TDS_tgt::Cell c_tgt; - c_tgt.info() = c_src.info(); +// c_tgt.info() = c_src.info(); c_tgt.input_cell() = c_src; c_tgt.set_time_stamp(-1); return c_tgt; @@ -232,7 +232,7 @@ namespace Tetrahedral_remeshing void operator()(const typename TDS_src::Cell& c_src, typename TDS_tgt::Cell& c_tgt) const { - c_tgt.info() = c_src.info(); +// c_tgt.info() = c_src.info(); c_tgt.input_cell() = c_src; } }; @@ -243,7 +243,7 @@ namespace Tetrahedral_remeshing Remeshing_triangulation_3& remeshing_tr) { typedef typename T3::Triangulation_data_structure Tds; - typedef Remeshing_triangulation_3::Tds RTds; + typedef Remeshing_triangulation_3::Tds RTds; remeshing_tr.clear(); @@ -261,7 +261,7 @@ namespace Tetrahedral_remeshing T3& tr) { typedef typename T3::Triangulation_data_structure Tds; - typedef Remeshing_triangulation_3::Tds RTds; + typedef Remeshing_triangulation_3::Tds RTds; tr.clear(); From a6e30d0e71ba84b3cb5b057dbe69934d528b9ae5 Mon Sep 17 00:00:00 2001 From: Jane Tournois Date: Tue, 17 Dec 2019 10:31:14 +0100 Subject: [PATCH 038/568] fix warnings in the doc --- Tetrahedral_remeshing/doc/Tetrahedral_remeshing/Doxyfile.in | 6 ++++-- .../doc/Tetrahedral_remeshing/Tetrahedral_remeshing.txt | 6 +++--- 2 files changed, 7 insertions(+), 5 deletions(-) diff --git a/Tetrahedral_remeshing/doc/Tetrahedral_remeshing/Doxyfile.in b/Tetrahedral_remeshing/doc/Tetrahedral_remeshing/Doxyfile.in index ed678b488d2..a7812ca0fd3 100644 --- a/Tetrahedral_remeshing/doc/Tetrahedral_remeshing/Doxyfile.in +++ b/Tetrahedral_remeshing/doc/Tetrahedral_remeshing/Doxyfile.in @@ -2,8 +2,8 @@ PROJECT_NAME = "CGAL ${CGAL_DOC_VERSION} - Tetrahedral Remeshing" #custom options for this package -EXTRACT_ALL = false -HIDE_UNDOC_CLASSES = true +EXTRACT_ALL = false +HIDE_UNDOC_CLASSES = true WARN_IF_UNDOCUMENTED = false # macros to be used inside the code @@ -18,6 +18,8 @@ ALIASES += "cgalNPTableEnd= " ALIASES += "cgalNPBegin{1}=\1 " ALIASES += "cgalNPEnd=" +EXAMPLE_PATH += ${CGAL_Tetrahedral_remeshing_EXAMPLE_DIR} + EXCLUDE = ${CGAL_PACKAGE_INCLUDE_DIR}/CGAL/Tetrahedral_remeshing/internal #MACRO_EXPANSION = YES diff --git a/Tetrahedral_remeshing/doc/Tetrahedral_remeshing/Tetrahedral_remeshing.txt b/Tetrahedral_remeshing/doc/Tetrahedral_remeshing/Tetrahedral_remeshing.txt index 97c3705bd09..d59a10d19fe 100644 --- a/Tetrahedral_remeshing/doc/Tetrahedral_remeshing/Tetrahedral_remeshing.txt +++ b/Tetrahedral_remeshing/doc/Tetrahedral_remeshing/Tetrahedral_remeshing.txt @@ -19,9 +19,9 @@ Section on definitions here ... The following example shows ... -\cgalExample{tetrahedral_remeshing_example.cpp } -\cgalExample{tetrahedral_remeshing_of_one_subdomain.cpp } -\cgalExample{tetrahedral_remeshing_with_features.cpp } +\cgalExample{Tetrahedral_remeshing/tetrahedral_remeshing_example.cpp } +\cgalExample{Tetrahedral_remeshing/tetrahedral_remeshing_of_one_subdomain.cpp } +\cgalExample{Tetrahedral_remeshing/tetrahedral_remeshing_with_features.cpp } */ } /* namespace CGAL */ From ad85942c0b9f143e802bca31b0ab2209235af36c Mon Sep 17 00:00:00 2001 From: Jane Tournois Date: Tue, 17 Dec 2019 16:00:09 +0100 Subject: [PATCH 039/568] move Vertex_converter and cell_converter to the user code : the plugin --- .../Tetrahedral_remeshing_plugin.cpp | 95 ++++++++++++++++++- .../Remeshing_triangulation_3.h | 56 +---------- 2 files changed, 93 insertions(+), 58 deletions(-) diff --git a/Polyhedron/demo/Polyhedron/Plugins/Tetrahedral_remeshing/Tetrahedral_remeshing_plugin.cpp b/Polyhedron/demo/Polyhedron/Plugins/Tetrahedral_remeshing/Tetrahedral_remeshing_plugin.cpp index c786f2443f4..b926b8bf5fc 100644 --- a/Polyhedron/demo/Polyhedron/Plugins/Tetrahedral_remeshing/Tetrahedral_remeshing_plugin.cpp +++ b/Polyhedron/demo/Polyhedron/Plugins/Tetrahedral_remeshing/Tetrahedral_remeshing_plugin.cpp @@ -22,6 +22,95 @@ //#include "ui_Tetrahedral_remeshing_dialog.h" +namespace CGAL { + + namespace internal { + + template + struct Vertex_converter + { + typename TDS_tgt::Vertex operator()(const typename TDS_src::Vertex& v_src) const + { + typedef typename CGAL::Kernel_traits< + typename TDS_src::Vertex::Point>::Kernel GT_src; + typedef typename CGAL::Kernel_traits< + typename TDS_tgt::Vertex::Point>::Kernel GT_tgt; + CGAL::Cartesian_converter conv; + + typedef typename TDS_tgt::Vertex::Point Tgt_point; + + typename TDS_tgt::Vertex v_tgt; + v_tgt.set_point(Tgt_point(conv(v_src.point()))); + v_tgt.set_time_stamp(-1); +// v_tgt.set_dimension(v_src.dimension()); + return v_tgt; + } + void operator()(const typename TDS_src::Vertex& v_src, + typename TDS_tgt::Vertex& v_tgt) const + { + typedef typename CGAL::Kernel_traits< + typename TDS_src::Vertex::Point>::Kernel GT_src; + typedef typename CGAL::Kernel_traits< + typename TDS_tgt::Vertex::Point>::Kernel GT_tgt; + CGAL::Cartesian_converter conv; + + typedef typename TDS_tgt::Vertex::Point Tgt_point; + + v_tgt.set_point(Tgt_point(conv(v_src.point()))); +// v_tgt.set_dimension(v_src.dimension()); + } + }; + + template + struct Cell_converter + { + typename TDS_tgt::Cell operator()(const typename TDS_src::Cell& c_src) const + { + typename TDS_tgt::Cell c_tgt; + c_tgt.set_subdomain_index(c_src.subdomain_index()); + c_tgt.set_time_stamp(-1); + return c_tgt; + } + void operator()(const typename TDS_src::Cell& c_src, + typename TDS_tgt::Cell& c_tgt) const + { + c_tgt.set_subdomain_index(c_src.subdomain_index()); + } + }; + + template + void build_remeshing_triangulation(const T3& tr, + Remeshing_tr& remeshing_tr) + { + typedef typename T3::Triangulation_data_structure Tds; + typedef typename Remeshing_tr::Tds RTds; + + remeshing_tr.clear(); + remeshing_tr.set_infinite_vertex( + remeshing_tr.tds().copy_tds( + tr.tds(), + tr.infinite_vertex(), + Vertex_converter(), + Cell_converter())); + } + + template + void build_from_remeshing_triangulation(const Remeshing_tr& remeshing_tr, + T3& tr) + { + typedef typename T3::Triangulation_data_structure Tds; + typedef typename Remeshing_tr::Tds RTds; + + tr.clear(); + tr.set_infinite_vertex( + tr.tds().copy_tds( + remeshing_tr.tds(), + remeshing_tr.infinite_vertex(), + Vertex_converter(), + Cell_converter())); + } + } +} using namespace CGAL::Three; class Polyhedron_demo_tetrahedral_remeshing_plugin : @@ -58,7 +147,7 @@ public: public Q_SLOTS: void tetrahedral_remeshing() { - typedef CGAL::Tetrahedral_remeshing::Remeshing_triangulation_3 Remeshing_triangulation; + typedef CGAL::Tetrahedral_remeshing::Remeshing_triangulation_3 Remeshing_triangulation; const Scene_interface::Item_id index = scene->mainSelectionIndex(); @@ -110,7 +199,7 @@ public Q_SLOTS: time.start(); Remeshing_triangulation tr; - CGAL::Tetrahedral_remeshing::build_remeshing_triangulation(c3t3_item->c3t3().triangulation(), tr); + CGAL::internal::build_remeshing_triangulation(c3t3_item->c3t3().triangulation(), tr); std::cout << "Remeshing triangulation built (" << time.elapsed() << " ms)" << std::endl; time.restart(); @@ -120,7 +209,7 @@ public Q_SLOTS: std::cout << "Remeshing done (" << time.elapsed() << " ms)" << std::endl; time.restart(); - CGAL::Tetrahedral_remeshing::build_from_remeshing_triangulation(tr, c3t3_item->c3t3().triangulation()); + CGAL::internal::build_from_remeshing_triangulation(tr, c3t3_item->c3t3().triangulation()); std::cout << "Back conversion done (" << time.elapsed() << " ms)" << std::endl; diff --git a/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/Remeshing_triangulation_3.h b/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/Remeshing_triangulation_3.h index 68a8c240cbc..77f23d66fb8 100644 --- a/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/Remeshing_triangulation_3.h +++ b/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/Remeshing_triangulation_3.h @@ -182,61 +182,7 @@ namespace Tetrahedral_remeshing }; } - - template - struct Vertex_converter - { - //This operator is used to create the vertex from v_src. - typename TDS_tgt::Vertex operator()(const typename TDS_src::Vertex& v_src) const - { - typedef typename CGAL::Kernel_traits< - typename TDS_src::Vertex::Point>::Kernel GT_src; - typedef typename CGAL::Kernel_traits< - typename TDS_tgt::Vertex::Point>::Kernel GT_tgt; - CGAL::Cartesian_converter conv; - - typename TDS_tgt::Vertex v_tgt; - v_tgt.set_point(conv(v_src.point())); - v_tgt.set_time_stamp(-1); -// v_tgt.set_dimension(v_src.info());//-1 if unset, 0,1,2, or 3 if set - return v_tgt; - } - //This operator is meant to be used in case heavy data should transferred to v_tgt. - void operator()(const typename TDS_src::Vertex& v_src, - typename TDS_tgt::Vertex& v_tgt) const - { - typedef typename CGAL::Kernel_traits< - typename TDS_src::Vertex::Point>::Kernel GT_src; - typedef typename CGAL::Kernel_traits< - typename TDS_tgt::Vertex::Point>::Kernel GT_tgt; - CGAL::Cartesian_converter conv; - - v_tgt.set_point(conv(v_src.point())); -// v_tgt.set_dimension(v_src.info()); - } - }; - - template - struct Cell_converter - { - //This operator is used to create the cell from c_src. - typename TDS_tgt::Cell operator()(const typename TDS_src::Cell& c_src) const - { - typename TDS_tgt::Cell c_tgt; -// c_tgt.info() = c_src.info(); - c_tgt.input_cell() = c_src; - c_tgt.set_time_stamp(-1); - return c_tgt; - } - //This operator is meant to be used in case heavy data should transferred to c_tgt. - void operator()(const typename TDS_src::Cell& c_src, - typename TDS_tgt::Cell& c_tgt) const - { -// c_tgt.info() = c_src.info(); - c_tgt.input_cell() = c_src; - } - }; - + template void build_remeshing_triangulation(const T3& tr, From cbce3b9237083be11e15e522633883d7a78c6e9f Mon Sep 17 00:00:00 2001 From: Jane Tournois Date: Tue, 17 Dec 2019 17:33:32 +0100 Subject: [PATCH 040/568] first introduction of an API for future sizing function --- .../tetrahedral_remeshing_with_features.cpp | 2 +- .../tetrahedral_adaptive_remeshing_impl.h | 21 ++++++++++++------- .../include/CGAL/tetrahedral_remeshing.h | 18 ++++++++++++++-- 3 files changed, 30 insertions(+), 11 deletions(-) diff --git a/Tetrahedral_remeshing/examples/Tetrahedral_remeshing/tetrahedral_remeshing_with_features.cpp b/Tetrahedral_remeshing/examples/Tetrahedral_remeshing/tetrahedral_remeshing_with_features.cpp index 630f2f64011..b1b7c88c2b4 100644 --- a/Tetrahedral_remeshing/examples/Tetrahedral_remeshing/tetrahedral_remeshing_with_features.cpp +++ b/Tetrahedral_remeshing/examples/Tetrahedral_remeshing/tetrahedral_remeshing_with_features.cpp @@ -127,7 +127,7 @@ int main(int argc, char* argv[]) generate_input(1000, "data/sphere_in_cube.tr.cgal", constraints); const char* filename = (argc > 1) ? argv[1] : "data/sphere_in_cube.tr.cgal"; - float target_edge_length = (argc > 2) ? atof(argv[2]) : 0.1f; + double target_edge_length = (argc > 2) ? atof(argv[2]) : 0.1; std::ifstream input(filename, std::ios::in); if (!input) diff --git a/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/tetrahedral_adaptive_remeshing_impl.h b/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/tetrahedral_adaptive_remeshing_impl.h index 7fd14f89f42..55e9cd8f0d4 100644 --- a/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/tetrahedral_adaptive_remeshing_impl.h +++ b/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/tetrahedral_adaptive_remeshing_impl.h @@ -73,6 +73,7 @@ namespace internal }; template @@ -89,7 +90,7 @@ namespace internal typedef int Surface_patch_index; //only needed for is_in_complex() private: - const FT& m_target_edge_length; + const SizingFunction& m_sizing; const bool m_protect_boundaries; // const bool m_adaptive;//adaptive sizing field TODO, outside remeshing C3t3 m_c3t3; @@ -99,13 +100,13 @@ namespace internal public: Adaptive_remesher(Triangulation& tr - , const FT& target_edge_length + , const SizingFunction& sizing , const bool protect_boundaries , EdgeIsConstrainedMap ecmap , CellSelector cell_selector // , const bool adaptive ) - : m_target_edge_length(target_edge_length) + : m_sizing(sizing) , m_protect_boundaries(protect_boundaries) // , m_adaptive(adaptive) , m_c3t3() @@ -150,7 +151,8 @@ namespace internal { CGAL_assertion(check_vertex_dimensions()); - const FT emax = FT(4)/FT(3) * m_target_edge_length; + const FT target_edge_length = m_sizing(CGAL::ORIGIN); + const FT emax = FT(4)/FT(3) * target_edge_length; split_long_edges(m_c3t3, emax, m_protect_boundaries, m_imaginary_index, m_cell_selector); @@ -166,8 +168,9 @@ namespace internal { CGAL_assertion(check_vertex_dimensions()); - FT emin = FT(4)/FT(5) * m_target_edge_length; - FT emax = FT(4)/FT(3) * m_target_edge_length; + const FT target_edge_length = m_sizing(CGAL::ORIGIN); + FT emin = FT(4)/FT(5) * target_edge_length; + FT emax = FT(4)/FT(3) * target_edge_length; collapse_short_edges(m_c3t3, emin, emax, m_protect_boundaries, m_imaginary_index, m_cell_selector); @@ -211,8 +214,10 @@ namespace internal bool resolution_reached() { - FT emax = FT(4) / FT(3) * m_target_edge_length; - FT emin = FT(4) / FT(5) * m_target_edge_length; + const FT target_edge_length = m_sizing(CGAL::ORIGIN); + + FT emax = FT(4) / FT(3) * target_edge_length; + FT emin = FT(4) / FT(5) * target_edge_length; FT sqmax = emax * emax; FT sqmin = emin * emin; diff --git a/Tetrahedral_remeshing/include/CGAL/tetrahedral_remeshing.h b/Tetrahedral_remeshing/include/CGAL/tetrahedral_remeshing.h index 06b1a828b4f..46078b5b4ae 100644 --- a/Tetrahedral_remeshing/include/CGAL/tetrahedral_remeshing.h +++ b/Tetrahedral_remeshing/include/CGAL/tetrahedral_remeshing.h @@ -113,6 +113,20 @@ todo//// * Its endpoints could be moved by smoothing void tetrahedral_adaptive_remeshing(Triangulation& tr, const double& target_edge_length, const NamedParameters& np) + { + tetrahedral_adaptive_remeshing( + tr, + [target_edge_length](const typename Triangulation::Point& p) + {return target_edge_length;}, + np); + } + + template + void tetrahedral_adaptive_remeshing(Triangulation& tr, + const SizingFunction& sizing, + const NamedParameters& np) { CGAL_assertion(tr.is_valid(true)); @@ -154,8 +168,8 @@ todo//// * Its endpoints could be moved by smoothing #endif typedef Tetrahedral_remeshing::internal::Adaptive_remesher< - Tr, ECMap, SelectionFunctor> Remesher; - Remesher remesher(tr, target_edge_length, protect, ecmap + Tr, SizingFunction, ECMap, SelectionFunctor> Remesher; + Remesher remesher(tr, sizing, protect, ecmap , cell_select /*, adaptive*/); From e2857aa9e5c7992298023fb4e967433059824f6f Mon Sep 17 00:00:00 2001 From: Jane Tournois Date: Thu, 19 Dec 2019 15:04:24 +0100 Subject: [PATCH 041/568] introduce dialog options UI for tetrahedral remeshing --- .../Tetrahedral_remeshing/CMakeLists.txt | 6 +- .../Tetrahedral_remeshing_dialog.ui | 210 ++++++++++++++++++ .../Tetrahedral_remeshing_plugin.cpp | 151 +++++-------- 3 files changed, 266 insertions(+), 101 deletions(-) create mode 100644 Polyhedron/demo/Polyhedron/Plugins/Tetrahedral_remeshing/Tetrahedral_remeshing_dialog.ui diff --git a/Polyhedron/demo/Polyhedron/Plugins/Tetrahedral_remeshing/CMakeLists.txt b/Polyhedron/demo/Polyhedron/Plugins/Tetrahedral_remeshing/CMakeLists.txt index 638e8c0d660..6b018456711 100644 --- a/Polyhedron/demo/Polyhedron/Plugins/Tetrahedral_remeshing/CMakeLists.txt +++ b/Polyhedron/demo/Polyhedron/Plugins/Tetrahedral_remeshing/CMakeLists.txt @@ -4,7 +4,9 @@ remove_definitions(-DQT_STATICPLUGIN) qt5_wrap_cpp( VOLUME_MOC_OUTFILES ${CMAKE_CURRENT_SOURCE_DIR}/Volume_plane_thread.h ) qt5_wrap_cpp( VOLUME_MOC_OUTFILES ${CMAKE_CURRENT_SOURCE_DIR}/Volume_plane_interface.h ) -#qt5_wrap_ui( meshingUI_FILES Meshing_dialog.ui Smoother_dialog.ui Local_optimizers_dialog.ui ) -polyhedron_demo_plugin(tetrahedral_remeshing_plugin Tetrahedral_remeshing_plugin KEYWORDS Tetrahedral_remeshing) + +qt5_wrap_ui( tetRemeshingUI_FILES Tetrahedral_remeshing_dialog.ui) +polyhedron_demo_plugin(tetrahedral_remeshing_plugin Tetrahedral_remeshing_plugin ${tetRemeshingUI_FILES} + KEYWORDS Tetrahedral_remeshing) target_link_libraries(tetrahedral_remeshing_plugin PUBLIC scene_c3t3_item ${OPENGL_gl_LIBRARY}) diff --git a/Polyhedron/demo/Polyhedron/Plugins/Tetrahedral_remeshing/Tetrahedral_remeshing_dialog.ui b/Polyhedron/demo/Polyhedron/Plugins/Tetrahedral_remeshing/Tetrahedral_remeshing_dialog.ui new file mode 100644 index 00000000000..351de08c508 --- /dev/null +++ b/Polyhedron/demo/Polyhedron/Plugins/Tetrahedral_remeshing/Tetrahedral_remeshing_dialog.ui @@ -0,0 +1,210 @@ + + + Tetrahedral_remeshing_dialog + + + true + + + + 0 + 0 + 376 + 259 + + + + Isotropic remeshing criteria + + + + + + + 15 + 75 + true + + + + NO OBJECT + + + + + + + No size + + + + + + + Tetrahedral remeshing + + + + + + Protect boundaries + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + + + + + + 110 + 0 + + + + 1 + + + + + + + + + + false + + + + + + + Qt::Vertical + + + QSizePolicy::Maximum + + + + 20 + 40 + + + + + + + + Number of Main iterations + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + nbIterations_spinbox + + + + + + + Target edge length + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + edgeLength_dspinbox + + + + + + + + 110 + 0 + + + + 1000.000000000000000 + + + 0.100000000000000 + + + + + + + + + + Qt::Vertical + + + QSizePolicy::MinimumExpanding + + + + 0 + 0 + + + + + + + + Qt::Horizontal + + + QDialogButtonBox::Cancel|QDialogButtonBox::Ok + + + + + + + edgeLength_dspinbox + nbIterations_spinbox + protect_checkbox + buttonBox + + + + + buttonBox + accepted() + Tetrahedral_remeshing_dialog + accept() + + + 397 + 333 + + + 157 + 195 + + + + + buttonBox + rejected() + Tetrahedral_remeshing_dialog + reject() + + + 397 + 333 + + + 286 + 195 + + + + + diff --git a/Polyhedron/demo/Polyhedron/Plugins/Tetrahedral_remeshing/Tetrahedral_remeshing_plugin.cpp b/Polyhedron/demo/Polyhedron/Plugins/Tetrahedral_remeshing/Tetrahedral_remeshing_plugin.cpp index b926b8bf5fc..37060762ace 100644 --- a/Polyhedron/demo/Polyhedron/Plugins/Tetrahedral_remeshing/Tetrahedral_remeshing_plugin.cpp +++ b/Polyhedron/demo/Polyhedron/Plugins/Tetrahedral_remeshing/Tetrahedral_remeshing_plugin.cpp @@ -20,7 +20,7 @@ #include #include -//#include "ui_Tetrahedral_remeshing_dialog.h" +#include "ui_Tetrahedral_remeshing_dialog.h" namespace CGAL { @@ -143,7 +143,6 @@ public: return qobject_cast(scene->item(scene->mainSelectionIndex())); } - public Q_SLOTS: void tetrahedral_remeshing() { @@ -157,40 +156,20 @@ public Q_SLOTS: if (c3t3_item) { // Create dialog box -// QDialog dialog(mw); -// Ui::Isotropic_remeshing_dialog ui -// = remeshing_dialog(&dialog, poly_item, selection_item); -// -// // Get values -// int i = dialog.exec(); -// if (i == QDialog::Rejected) -// { -// std::cout << "Remeshing aborted" << std::endl; -// return; -// } -// bool edges_only = ui.splitEdgesOnly_checkbox->isChecked(); -// bool preserve_duplicates = ui.preserveDuplicates_checkbox->isChecked(); -// double target_length = ui.edgeLength_dspinbox->value(); -// unsigned int nb_iter = ui.nbIterations_spinbox->value(); -// unsigned int nb_smooth = ui.nbSmoothing_spinbox->value(); -// bool protect = ui.protect_checkbox->isChecked(); -// bool smooth_features = ui.smooth1D_checkbox->isChecked(); + QDialog dialog(mw); + Ui::Tetrahedral_remeshing_dialog ui + = tet_remeshing_dialog(&dialog, c3t3_item); - - bool ok; - double target_edge_length = QInputDialog::getDouble(mw, - tr("Tetrahedral remeshing"), - tr("target edge length = "), - 0.1, //value - 1e-10, //min - 2147483647,//max - 10,//decimals - &ok); - if (!ok) + // Get values + int i = dialog.exec(); + if (i == QDialog::Rejected) { std::cout << "Remeshing aborted" << std::endl; return; } + double target_length = ui.edgeLength_dspinbox->value(); + unsigned int nb_iter = ui.nbIterations_spinbox->value(); + bool protect = ui.protect_checkbox->isChecked(); // wait cursor QApplication::setOverrideCursor(Qt::WaitCursor); @@ -204,7 +183,10 @@ public Q_SLOTS: std::cout << "Remeshing triangulation built (" << time.elapsed() << " ms)" << std::endl; time.restart(); - CGAL::tetrahedral_adaptive_remeshing(tr, target_edge_length); + + CGAL::tetrahedral_adaptive_remeshing(tr, target_length, + CGAL::parameters::protect_boundaries(protect) + .number_of_iterations(nb_iter)); std::cout << "Remeshing done (" << time.elapsed() << " ms)" << std::endl; time.restart(); @@ -214,8 +196,6 @@ public Q_SLOTS: std::cout << "Back conversion done (" << time.elapsed() << " ms)" << std::endl; c3t3_item->c3t3_changed(); - c3t3_item->update_histogram(); - const Scene_interface::Item_id index = scene->mainSelectionIndex(); this->scene->itemChanged(index); // default cursor @@ -231,83 +211,56 @@ private: Scene_interface *scene; QMainWindow* mw; - //Ui::Isotropic_remeshing_dialog - //remeshing_dialog(QDialog* dialog, - // Scene_facegraph_item* poly_item, - // Scene_polyhedron_selection_item* selection_item = NULL) - //{ - // Ui::Isotropic_remeshing_dialog ui; - // ui.setupUi(dialog); - // connect(ui.buttonBox, SIGNAL(accepted()), dialog, SLOT(accept())); - // connect(ui.buttonBox, SIGNAL(rejected()), dialog, SLOT(reject())); + Ui::Tetrahedral_remeshing_dialog + tet_remeshing_dialog(QDialog* dialog, + Scene_c3t3_item* c3t3_item) + { + Ui::Tetrahedral_remeshing_dialog ui; + ui.setupUi(dialog); + connect(ui.buttonBox, SIGNAL(accepted()), dialog, SLOT(accept())); + connect(ui.buttonBox, SIGNAL(rejected()), dialog, SLOT(reject())); - // //connect checkbox to spinbox - // connect(ui.splitEdgesOnly_checkbox, SIGNAL(toggled(bool)), - // ui.nbIterations_spinbox, SLOT(setDisabled(bool))); - // connect(ui.splitEdgesOnly_checkbox, SIGNAL(toggled(bool)), - // ui.protect_checkbox, SLOT(setDisabled(bool))); - // connect(ui.protect_checkbox, SIGNAL(toggled(bool)), - // ui.smooth1D_checkbox, SLOT(setDisabled(bool))); - // connect(ui.splitEdgesOnly_checkbox, SIGNAL(toggled(bool)), - // ui.smooth1D_checkbox, SLOT(setDisabled(bool))); - // connect(ui.preserveDuplicates_checkbox, SIGNAL(toggled(bool)), - // ui.protect_checkbox, SLOT(setChecked(bool))); - // connect(ui.preserveDuplicates_checkbox, SIGNAL(toggled(bool)), - // ui.protect_checkbox, SLOT(setDisabled(bool))); + //Set default parameters + Scene_interface::Bbox bbox = c3t3_item->bbox(); + ui.objectName->setText(c3t3_item->name()); - // //Set default parameters - // Scene_interface::Bbox bbox = poly_item != NULL ? poly_item->bbox() - // : (selection_item != NULL ? selection_item->bbox() - // : scene->bbox()); - // ui.objectName->setText(poly_item != NULL ? poly_item->name() - // : (selection_item != NULL ? selection_item->name() - // : QString("Remeshing parameters"))); + ui.objectNameSize->setText( + tr("Object bbox size (w,h,d): %1, %2, %3") + .arg(bbox.xmax()-bbox.xmin(), 0, 'g', 3) + .arg(bbox.ymax()-bbox.ymin(), 0, 'g', 3) + .arg(bbox.zmax()-bbox.zmin(), 0, 'g', 3)); - // ui.objectNameSize->setText( - // tr("Object bbox size (w,h,d): %1, %2, %3") - // .arg(bbox.xmax()-bbox.xmin(), 0, 'g', 3) - // .arg(bbox.ymax()-bbox.ymin(), 0, 'g', 3) - // .arg(bbox.zmax()-bbox.zmin(), 0, 'g', 3)); + double diago_length = CGAL::sqrt((bbox.xmax()-bbox.xmin())*(bbox.xmax()-bbox.xmin()) + + (bbox.ymax()-bbox.ymin())*(bbox.ymax()-bbox.ymin()) + + (bbox.zmax()-bbox.zmin())*(bbox.zmax()-bbox.zmin())); + double log = std::log10(diago_length); + unsigned int nb_decimals = (log > 0) ? 5 : (std::ceil(-log)+3); - // double diago_length = CGAL::sqrt((bbox.xmax()-bbox.xmin())*(bbox.xmax()-bbox.xmin()) - // + (bbox.ymax()-bbox.ymin())*(bbox.ymax()-bbox.ymin()) - // + (bbox.zmax()-bbox.zmin())*(bbox.zmax()-bbox.zmin())); - // double log = std::log10(diago_length); - // unsigned int nb_decimals = (log > 0) ? 5 : (std::ceil(-log)+3); + ui.edgeLength_dspinbox->setDecimals(nb_decimals); + ui.edgeLength_dspinbox->setSingleStep(1e-3); + ui.edgeLength_dspinbox->setRange(1e-6 * diago_length, //min + 2. * diago_length);//max + ui.edgeLength_dspinbox->setValue(0.05 * diago_length); - // ui.edgeLength_dspinbox->setDecimals(nb_decimals); - // ui.edgeLength_dspinbox->setSingleStep(1e-3); - // ui.edgeLength_dspinbox->setRange(1e-6 * diago_length, //min - // 2. * diago_length);//max - // ui.edgeLength_dspinbox->setValue(0.05 * diago_length); + std::ostringstream oss; + oss << "Diagonal length of the Bbox of the triangulation to remesh is "; + oss << diago_length << "." << std::endl; + oss << "Default is 5% of it" << std::endl; + ui.edgeLength_dspinbox->setToolTip(QString::fromStdString(oss.str())); - // std::ostringstream oss; - // oss << "Diagonal length of the Bbox of the selection to remesh is "; - // oss << diago_length << "." << std::endl; - // oss << "Default is 5% of it" << std::endl; - // ui.edgeLength_dspinbox->setToolTip(QString::fromStdString(oss.str())); + ui.nbIterations_spinbox->setSingleStep(1); + ui.nbIterations_spinbox->setRange(1/*min*/, 1000/*max*/); + ui.nbIterations_spinbox->setValue(1); - // ui.nbIterations_spinbox->setSingleStep(1); - // ui.nbIterations_spinbox->setRange(1/*min*/, 1000/*max*/); - // ui.nbIterations_spinbox->setValue(1); + ui.protect_checkbox->setChecked(false); - // ui.protect_checkbox->setChecked(false); - // ui.smooth1D_checkbox->setChecked(true); - - // if (NULL != selection_item) - // { - // //do not preserve duplicates in selection mode - // ui.preserveDuplicates_checkbox->setDisabled(true); - // ui.preserveDuplicates_checkbox->setChecked(false); - // } - - // return ui; - //} + return ui; + } private: QAction* actionTetrahedralRemeshing_; -}; // end Polyhedron_demo_isotropic_remeshing_plugin +}; // end Polyhedron_demo_tetrahedral_remeshing_plugin #include "Tetrahedral_remeshing_plugin.moc" From 87d01eb7cdf3e6ba65ac4ce2536edb6506682226 Mon Sep 17 00:00:00 2001 From: Jane Tournois Date: Thu, 19 Dec 2019 15:57:53 +0100 Subject: [PATCH 042/568] add RemeshingTriangulationTraits_3 and start using the concept preprocess() is done --- .../Concepts/RemeshingTriangulationTraits_3.h | 117 ++++++++++++++++++ .../Remeshing_triangulation_3.h | 30 ++--- .../internal/add_imaginary_layer.h | 15 ++- 3 files changed, 142 insertions(+), 20 deletions(-) create mode 100644 Tetrahedral_remeshing/doc/Tetrahedral_remeshing/Concepts/RemeshingTriangulationTraits_3.h diff --git a/Tetrahedral_remeshing/doc/Tetrahedral_remeshing/Concepts/RemeshingTriangulationTraits_3.h b/Tetrahedral_remeshing/doc/Tetrahedral_remeshing/Concepts/RemeshingTriangulationTraits_3.h new file mode 100644 index 00000000000..747700cd8d0 --- /dev/null +++ b/Tetrahedral_remeshing/doc/Tetrahedral_remeshing/Concepts/RemeshingTriangulationTraits_3.h @@ -0,0 +1,117 @@ + +/*! +\ingroup PkgTetrahedralRemeshingConcepts +\cgalConcept + +\cgalRefines TriangulationTraits_3 + +The concept `RemeshingTriangulationTraits_3` is the first template parameter +of the class Remeshing_triangulation_3. It defines the geometric objects (points, segments, +triangles and tetrahedra) forming the triangulation together with a few +geometric predicates and constructions on these objects. + +\cgalHasModel All models of `Kernel`. + +\sa `CGAL::Triangulation_3` +*/ + +class RemeshingTriangulationTraits_3 { +public: + +/// \name Types +/// @{ + +/*! +A constructor object model of `ConstructCrossProductVector_3` +*/ +typedef unspecified_type Construct_cross_product_vector_3; + +/*! +A constructor object model of `ConstructVector_3` +*/ +typedef unspecified_type Construct_vector_3; + +/*! +A constructor object model of `ConstructScaledVector_3 ` +*/ +typedef unspecified_type Construct_scaled_vector_3; + +/*! +A constructor object model of `ConstructSumOfVectors_3` +*/ +typedef unspecified_type Construct_sum_of_vectors_3; + +/*! +A constructor object model of `ConstructOppositeVector_3` +*/ +typedef unspecified_type Construct_opposite_vector_3; + +/*! +A constructor object model of `ComputeSquaredLength_3` +*/ +typedef unspecified_type Compute_squared_length_3; + +/*! +A constructor object model of `ConstructDividedVector_3` +*/ +typedef unspecified_type Construct_divided_vector_3; + +/*! +A constructor object model of `ConstructTranslatedPoint_3` +*/ +typedef unspecified_type Construct_translated_point_3; + +/////*! +////A predicate object that must provide the function operator +//// +////`Comparison_result operator()(Point_3 p, Point_3 q)`, +//// +////which returns `EQUAL` if the two points are equal. Otherwise it must +////return a consistent order for any two points chosen in a same line. +////*/ +////typedef unspecified_type Compare_xyz_3; + + +/// @} + + +/// \name Operations +/// The following functions give access to the predicate and construction objects: +/// @{ + +/*! +*/ +Construct_cross_product_vector_3 construct_cross_product_vector_3_object(); + +/*! +*/ +Construct_vector_3 construct_vector_3_object(); + +/*! +*/ +Construct_scaled_vector_3 construct_scaled_vector_3_object(); + +/*! +*/ +Construct_sum_of_vectors_3 construct_sum_of_vectors_3_object(); + +/*! +*/ +Construct_opposite_vector_3 construct_opposite_vector_3_object(); + +/*! +*/ +Compute_squared_length_3 compute_squared_length_3_object(); + +/*! +*/ +Construct_divided_vector_3 construct_divided_vector_3_object(); + +/*! +*/ +Construct_translated_point_3 construct_translated_point_3_object(); + +/// @} + +}; /* end RemeshingTriangulationTraits_3 */ + diff --git a/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/Remeshing_triangulation_3.h b/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/Remeshing_triangulation_3.h index 77f23d66fb8..ede95b4d6d1 100644 --- a/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/Remeshing_triangulation_3.h +++ b/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/Remeshing_triangulation_3.h @@ -87,28 +87,28 @@ namespace Tetrahedral_remeshing \cgalRefines `Triangulation_3` */ - template, - typename Vb = CGAL::Triangulation_vertex_base_3 + typename Cb = CGAL::Triangulation_cell_base_3, + typename Vb = CGAL::Triangulation_vertex_base_3 #ifndef DOXYGEN_RUNNING , typename Cell_visitor = Default_remeshing_visitor #endif > class Remeshing_triangulation_3 - : public CGAL::Triangulation_3, - Remeshing_cell_base + Remeshing_vertex_base, + Remeshing_cell_base > > { - typedef Remeshing_vertex_base RVb; - typedef Remeshing_cell_base RCb; + typedef Remeshing_vertex_base RVb; + typedef Remeshing_cell_base RCb; public: typedef CGAL::Triangulation_data_structure_3 Tds; - typedef CGAL::Triangulation_3 Self; + typedef CGAL::Triangulation_3 Self; typedef Self type; private: @@ -184,12 +184,12 @@ namespace Tetrahedral_remeshing } - template + template void build_remeshing_triangulation(const T3& tr, - Remeshing_triangulation_3& remeshing_tr) + Remeshing_triangulation_3& remeshing_tr) { typedef typename T3::Triangulation_data_structure Tds; - typedef Remeshing_triangulation_3::Tds RTds; + typedef Remeshing_triangulation_3::Tds RTds; remeshing_tr.clear(); @@ -201,13 +201,13 @@ namespace Tetrahedral_remeshing internal::Cell_converter())); } - template + template void build_from_remeshing_triangulation( - const Remeshing_triangulation_3& remeshing_tr, + const Remeshing_triangulation_3& remeshing_tr, T3& tr) { typedef typename T3::Triangulation_data_structure Tds; - typedef Remeshing_triangulation_3::Tds RTds; + typedef Remeshing_triangulation_3::Tds RTds; tr.clear(); diff --git a/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/add_imaginary_layer.h b/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/add_imaginary_layer.h index db0a5760257..bbe4bfc5504 100644 --- a/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/add_imaginary_layer.h +++ b/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/add_imaginary_layer.h @@ -84,10 +84,11 @@ namespace internal return oit; } - template + template OutputIterator compute_offset_points(const VertexNormalsMap& normals, const double& offset, - OutputIterator oit) + OutputIterator oit, + const Gt& gt) { #ifdef CGAL_TETRAHEDRAL_REMESHING_DEBUG std::ofstream ofs("imaginary_points.off"); @@ -95,13 +96,16 @@ namespace internal ofs << normals.size() << " 0 0" << std::endl; #endif + typename Gt::Construct_translated_point_3 translate + = gt.construct_translated_point_3_object(); + for (typename VertexNormalsMap::const_iterator nit = normals.begin(); nit != normals.end(); ++nit) { - *oit++ = point((*nit).first->point()) + offset * (*nit).second; + *oit++ = translate(point((*nit).first->point()), offset * (*nit).second); #ifdef CGAL_TETRAHEDRAL_REMESHING_DEBUG - ofs << ((*nit).first->point() + offset * (*nit).second) << std::endl; + ofs << translate(point((*nit).first->point()), offset * (*nit).second) << std::endl; #endif } @@ -219,7 +223,8 @@ namespace internal std::vector offset_points; compute_offset_points(normals, offset, - std::back_inserter(offset_points)); + std::back_inserter(offset_points), + tr.geom_traits()); //insert vertices on offset //note we only need to insert them in the T3, because they From 1e7d4a22894624df920264af5faebc559026906f Mon Sep 17 00:00:00 2001 From: Jane Tournois Date: Fri, 20 Dec 2019 11:09:38 +0100 Subject: [PATCH 043/568] use the triangulation traits class in split, collapse and flip steps --- .../Concepts/RemeshingTriangulationTraits_3.h | 18 ++++ .../internal/collapse_short_edges.h | 7 +- .../internal/flip_edges.h | 41 +++---- .../internal/split_long_edges.h | 13 ++- .../internal/tetrahedral_remeshing_helpers.h | 101 +++++++++--------- 5 files changed, 101 insertions(+), 79 deletions(-) diff --git a/Tetrahedral_remeshing/doc/Tetrahedral_remeshing/Concepts/RemeshingTriangulationTraits_3.h b/Tetrahedral_remeshing/doc/Tetrahedral_remeshing/Concepts/RemeshingTriangulationTraits_3.h index 747700cd8d0..425aedd9905 100644 --- a/Tetrahedral_remeshing/doc/Tetrahedral_remeshing/Concepts/RemeshingTriangulationTraits_3.h +++ b/Tetrahedral_remeshing/doc/Tetrahedral_remeshing/Concepts/RemeshingTriangulationTraits_3.h @@ -61,6 +61,16 @@ A constructor object model of `ConstructTranslatedPoint_3` */ typedef unspecified_type Construct_translated_point_3; +/*! +A constructor object model of `ConstructMidpoint_3` +*/ +typedef unspecified_type Construct_midpoint_3; + +/*! +A constructor obeject model of `ComputeApproximateDihedralAngle_3` +*/ +typedef unspecified_type Compute_approximate_dihedral_angle_3; + /////*! ////A predicate object that must provide the function operator //// @@ -111,6 +121,14 @@ Construct_divided_vector_3 construct_divided_vector_3_object(); */ Construct_translated_point_3 construct_translated_point_3_object(); +/*! +*/ +Construct_midpoint_3 construct_midpoint_3_object(); + +/*! +*/ +Compute_approximate_dihedral_angle_3 compute_approximate_dihedral_angle_3_object(); + /// @} }; /* end RemeshingTriangulationTraits_3 */ diff --git a/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/collapse_short_edges.h b/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/collapse_short_edges.h index 56b9e8251e7..be1d0c4c2c2 100644 --- a/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/collapse_short_edges.h +++ b/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/collapse_short_edges.h @@ -282,7 +282,7 @@ namespace internal for (Finite_cells_iterator cit = triangulation.finite_cells_begin(); cit != triangulation.finite_cells_end(); ++cit) { - if (!is_well_oriented(cit)) + if (!is_well_oriented(triangulation, cit)) return ORIENTATION_PROBLEM; } @@ -940,6 +940,7 @@ namespace internal typedef typename T3::Vertex_handle Vertex_handle; typedef typename std::pair Edge_vv; + typedef typename T3::Geom_traits Gt; typedef typename T3::Geom_traits::FT FT; typedef boost::bimap< boost::bimaps::set_of, @@ -964,7 +965,9 @@ namespace internal if (!can_be_collapsed(e, c3t3, protect_boundaries, imaginary_index, cell_selector)) continue; - double sqlen = tr.segment(e).squared_length(); + typename Gt::Compute_squared_length_3 sql + = tr.geom_traits().compute_squared_length_3_object(); + FT sqlen = sql(tr.segment(e)); if (sqlen < sq_low) short_edges.insert(short_edge(make_vertex_pair(e), sqlen)); } diff --git a/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/flip_edges.h b/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/flip_edges.h index 11e982fda20..aea972b57b5 100644 --- a/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/flip_edges.h +++ b/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/flip_edges.h @@ -108,11 +108,11 @@ namespace internal int vh1_id = ch1->index(vh1); //Check if flip valid - if (!is_well_oriented(vh2, + if (!is_well_oriented(tr, vh2, ch0->vertex(indices(vh0_id, 0)), ch0->vertex(indices(vh0_id, 1)), ch0->vertex(indices(vh0_id, 2))) - || !is_well_oriented(vh3, + || !is_well_oriented(tr, vh3, ch1->vertex(indices(vh1_id, 0)), ch1->vertex(indices(vh1_id, 1)), ch1->vertex(indices(vh1_id, 2)))) @@ -147,16 +147,16 @@ namespace internal if (criterion == MIN_ANGLE_BASED) { //Current worst dihedral angle - FT curr_min_dh = min_dihedral_angle(ch0); - curr_min_dh = (std::min)(curr_min_dh, min_dihedral_angle(ch1)); - curr_min_dh = (std::min)(curr_min_dh, min_dihedral_angle(cell_to_remove)); + FT curr_min_dh = min_dihedral_angle(tr, ch0); + curr_min_dh = (std::min)(curr_min_dh, min_dihedral_angle(tr, ch1)); + curr_min_dh = (std::min)(curr_min_dh, min_dihedral_angle(tr, cell_to_remove)); //Result worst dihedral angle - if (curr_min_dh > min_dihedral_angle(vh2, + if (curr_min_dh > min_dihedral_angle(tr, vh2, ch0->vertex(indices(vh0_id, 0)), ch0->vertex(indices(vh0_id, 1)), ch0->vertex(indices(vh0_id, 2))) - || curr_min_dh > min_dihedral_angle(vh3, + || curr_min_dh > min_dihedral_angle(tr, vh3, ch1->vertex(indices(vh1_id, 0)), ch1->vertex(indices(vh1_id, 1)), ch1->vertex(indices(vh1_id, 2)))) @@ -165,17 +165,17 @@ namespace internal else if (criterion == AVERAGE_ANGLE_BASED) { //Current worst dihedral angle - double average_min_dh = min_dihedral_angle(ch0); - average_min_dh += min_dihedral_angle(ch1); - average_min_dh += min_dihedral_angle(cell_to_remove); + double average_min_dh = min_dihedral_angle(tr, ch0); + average_min_dh += min_dihedral_angle(tr, ch1); + average_min_dh += min_dihedral_angle(tr, cell_to_remove); average_min_dh /= 3.; FT new_average_min_dh = 0.5 * - (min_dihedral_angle(vh2, ch0->vertex(indices(vh0_id, 0)), + (min_dihedral_angle(tr, vh2, ch0->vertex(indices(vh0_id, 0)), ch0->vertex(indices(vh0_id, 1)), ch0->vertex(indices(vh0_id, 2))) - + min_dihedral_angle(vh3, ch1->vertex(indices(vh1_id, 0)), + + min_dihedral_angle(tr, vh3, ch1->vertex(indices(vh1_id, 0)), ch1->vertex(indices(vh1_id, 1)), ch1->vertex(indices(vh1_id, 2)))); //Result worst dihedral angle @@ -427,12 +427,12 @@ namespace internal const Facet& fi = facets[i]; if (!tr.is_infinite(fi.first)) { - if (is_well_oriented(vh, fi.first->vertex(indices(fi.second, 0)), + if (is_well_oriented(tr, vh, fi.first->vertex(indices(fi.second, 0)), fi.first->vertex(indices(fi.second, 1)), fi.first->vertex(indices(fi.second, 2)))) { min_flip_dihedral_angle = (std::min)(min_flip_dihedral_angle, - min_dihedral_angle(vh, fi.first->vertex(indices(fi.second, 0)), + min_dihedral_angle(tr, vh, fi.first->vertex(indices(fi.second, 0)), fi.first->vertex(indices(fi.second, 1)), fi.first->vertex(indices(fi.second, 2)))); } @@ -566,12 +566,12 @@ namespace internal const Facet& fi = facets[i]; if (!tr.is_infinite(fi.first)) { - if (is_well_oriented(vh, fi.first->vertex(indices(fi.second, 0)), + if (is_well_oriented(tr, vh, fi.first->vertex(indices(fi.second, 0)), fi.first->vertex(indices(fi.second, 1)), fi.first->vertex(indices(fi.second, 2)))) { min_flip_dihedral_angle = (std::min)(min_flip_dihedral_angle, - min_dihedral_angle(vh, fi.first->vertex(indices(fi.second, 0)), + min_dihedral_angle(tr, vh, fi.first->vertex(indices(fi.second, 0)), fi.first->vertex(indices(fi.second, 1)), fi.first->vertex(indices(fi.second, 2)))); } @@ -729,7 +729,7 @@ namespace internal const Facet& fi = facets_for_new_cells[i]; if ( !tr.is_infinite(fi.first) - && !is_well_oriented(vh, fi.first->vertex(indices(fi.second, 0)), + && !is_well_oriented(tr, vh, fi.first->vertex(indices(fi.second, 0)), fi.first->vertex(indices(fi.second, 1)), fi.first->vertex(indices(fi.second, 2)))) return NOT_FLIPPABLE; @@ -739,7 +739,7 @@ namespace internal const Facet& fi = facets_for_updated_cells[i]; if ( !tr.is_infinite(fi.first) - && !is_well_oriented(vh, fi.first->vertex(indices(fi.second, 0)), + && !is_well_oriented(tr, vh, fi.first->vertex(indices(fi.second, 0)), fi.first->vertex(indices(fi.second, 1)), fi.first->vertex(indices(fi.second, 2)))) return NOT_FLIPPABLE; @@ -923,6 +923,7 @@ namespace internal typedef typename C3t3::Triangulation::Cell_circulator Cell_circulator; typedef typename C3t3::Triangulation::Geom_traits Gt; typedef typename Gt::FT FT; + typename C3t3::Triangulation& tr = c3t3.triangulation(); Sliver_removal_result result = NOT_FLIPPABLE; @@ -936,10 +937,10 @@ namespace internal Cell_circulator circ = c3t3.triangulation().incident_cells(edge); Cell_circulator done = circ; - FT curr_min_dh = min_dihedral_angle(circ++); + FT curr_min_dh = min_dihedral_angle(tr, circ++); while (circ != done) { - curr_min_dh = (std::min)(curr_min_dh, min_dihedral_angle(circ++)); + curr_min_dh = (std::min)(curr_min_dh, min_dihedral_angle(tr, circ++)); } if (boundary_vertices.size() == 2) find_best_flip_to_improve_dh(c3t3, edge, boundary_vertices[0], boundary_vertices[1], diff --git a/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/split_long_edges.h b/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/split_long_edges.h index 4b69c116935..5596786baf6 100644 --- a/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/split_long_edges.h +++ b/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/split_long_edges.h @@ -83,7 +83,8 @@ namespace internal // insert midpoint Vertex_handle new_v = tr.tds().insert_in_edge(e); - const Point m(CGAL::midpoint(point(v1->point()), point(v2->point()))); + const Point m = tr.geom_traits().construct_midpoint_3_object() + (point(v1->point()), point(v2->point())); new_v->set_point(m); // update dimension @@ -117,11 +118,6 @@ namespace internal if (is_imaginary(e, c3t3, imaginary_index)) return false; -#ifdef CGAL_LIMITED_APERTURE_EDGE_SELECTION - if (CGAL::helpers::is_on_the_outer_box(e, c3t3, imaginary_index)) - return true; -#endif - if (protect_boundaries) { if (c3t3.is_in_complex(e)) @@ -162,6 +158,7 @@ namespace internal typedef typename T3::Vertex_handle Vertex_handle; typedef typename std::pair Edge_vv; + typedef typename T3::Geom_traits Gt; typedef typename T3::Geom_traits::FT FT; typedef boost::bimap< boost::bimaps::set_of, @@ -185,7 +182,9 @@ namespace internal if (!can_be_split(e, c3t3, protect_boundaries, imaginary_index, cell_selector)) continue; - FT sqlen = tr.segment(e).squared_length(); + typename Gt::Compute_squared_length_3 sql + = tr.geom_traits().compute_squared_length_3_object(); + FT sqlen = sql(tr.segment(e)); if (sqlen > sq_high) long_edges.insert(long_edge(make_vertex_pair(e), sqlen)); } diff --git a/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/tetrahedral_remeshing_helpers.h b/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/tetrahedral_remeshing_helpers.h index 22068a8eb11..c7ee3c66a57 100644 --- a/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/tetrahedral_remeshing_helpers.h +++ b/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/tetrahedral_remeshing_helpers.h @@ -73,62 +73,68 @@ namespace Tetrahedral_remeshing return indices_table[i][j]; } - template - typename Gt::FT dihedral_angle(const CGAL::Point_3& p, - const CGAL::Point_3& q, - const CGAL::Point_3& r, - const CGAL::Point_3& s) + template + typename Tr::Geom_traits::FT dihedral_angle(const Tr& tr, + const typename Tr::Point& p, + const typename Tr::Point& q, + const typename Tr::Point& r, + const typename Tr::Point& s) { - return Gt().compute_approximate_dihedral_angle_3_object()(p, q, r, s); + return tr.geom_traits().compute_approximate_dihedral_angle_3_object()(p, q, r, s); } - template - typename Gt::FT min_dihedral_angle(const CGAL::Point_3& p, - const CGAL::Point_3& q, - const CGAL::Point_3& r, - const CGAL::Point_3& s) + template + typename Tr::Geom_traits::FT min_dihedral_angle(const Tr& tr, + const typename Tr::Point& p, + const typename Tr::Point& q, + const typename Tr::Point& r, + const typename Tr::Point& s) { - typedef typename Gt::FT FT; - FT a = CGAL::abs(dihedral_angle(p, q, r, s)); + typedef typename Tr::Geom_traits::FT FT; + FT a = CGAL::abs(dihedral_angle(tr, p, q, r, s)); FT min_dh = a; - a = CGAL::abs(dihedral_angle(p, r, q, s)); + a = CGAL::abs(dihedral_angle(tr, p, r, q, s)); min_dh = (std::min)(a, min_dh); - a = CGAL::abs(dihedral_angle(p, s, q, r)); + a = CGAL::abs(dihedral_angle(tr, p, s, q, r)); min_dh = (std::min)(a, min_dh); - a = CGAL::abs(dihedral_angle(q, r, p, s)); + a = CGAL::abs(dihedral_angle(tr, q, r, p, s)); min_dh = (std::min)(a, min_dh); - a = CGAL::abs(dihedral_angle(q, s, p, r)); + a = CGAL::abs(dihedral_angle(tr, q, s, p, r)); min_dh = (std::min)(a, min_dh); - a = CGAL::abs(dihedral_angle(r, s, p, q)); + a = CGAL::abs(dihedral_angle(tr, r, s, p, q)); min_dh = (std::min)(a, min_dh); return min_dh; } - template - typename Gt::FT min_dihedral_angle(VertexHandle v0, - VertexHandle v1, - VertexHandle v2, - VertexHandle v3) + template + typename Tr::Geom_traits::FT min_dihedral_angle(const Tr& tr, + const typename Tr::Vertex_handle v0, + const typename Tr::Vertex_handle v1, + const typename Tr::Vertex_handle v2, + const typename Tr::Vertex_handle v3) { - return min_dihedral_angle(point(v0->point()), - point(v1->point()), - point(v2->point()), - point(v3->point())); + return min_dihedral_angle(tr, + point(v0->point()), + point(v1->point()), + point(v2->point()), + point(v3->point())); } - template - typename Gt::FT min_dihedral_angle(CellHandle c) + template + typename Tr::Geom_traits::FT min_dihedral_angle(const Tr& tr, + const typename Tr::Cell_handle c) { - return min_dihedral_angle(point(c->vertex(0)->point()), - point(c->vertex(1)->point()), - point(c->vertex(2)->point()), - point(c->vertex(3)->point())); + return min_dihedral_angle(tr, + point(c->vertex(0)->point()), + point(c->vertex(1)->point()), + point(c->vertex(2)->point()), + point(c->vertex(3)->point())); } template @@ -164,32 +170,27 @@ namespace Tetrahedral_remeshing return (v->in_dimension() == 1); } - template - CGAL::Orientation orientation(const CellHandle ch) + template + bool is_well_oriented(const Tr& tr, const typename Tr::Cell_handle ch) { - return CGAL::orientation(point(ch->vertex(0)->point()), - point(ch->vertex(1)->point()), - point(ch->vertex(2)->point()), - point(ch->vertex(3)->point())); + return is_well_oriented(tr, ch->vertex(0), ch->vertex(1), + ch->vertex(2), ch->vertex(3)); } - template - bool is_well_oriented(const CellHandle ch) + template + bool is_well_oriented(const Tr& tr, + const typename Tr::Vertex_handle v0, + const typename Tr::Vertex_handle v1, + const typename Tr::Vertex_handle v2, + const typename Tr::Vertex_handle v3) { - return CGAL::POSITIVE == orientation(ch); - } - - template - bool is_well_oriented(const VertexHandle v0, const VertexHandle v1, - const VertexHandle v2, const VertexHandle v3) - { - return CGAL::POSITIVE == CGAL::orientation(point(v0->point()), + return CGAL::POSITIVE == tr.geom_traits().orientation_3_object()( + point(v0->point()), point(v1->point()), point(v2->point()), point(v3->point())); } - template bool is_boundary(const C3T3& c3t3, const typename C3T3::Triangulation::Edge& e, From fe270e450979c6babf285c3fbdc3e4b019d72e45 Mon Sep 17 00:00:00 2001 From: Jane Tournois Date: Fri, 20 Dec 2019 11:50:03 +0100 Subject: [PATCH 044/568] use geom traits in smoothing --- .../internal/smooth_vertices.h | 52 +++++++++++++++---- 1 file changed, 43 insertions(+), 9 deletions(-) diff --git a/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/smooth_vertices.h b/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/smooth_vertices.h index 111db448e02..fce72c88c9f 100644 --- a/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/smooth_vertices.h +++ b/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/smooth_vertices.h @@ -183,7 +183,10 @@ namespace internal { typedef typename C3T3::Edge Edge; typedef typename C3T3::Vertex_handle Vertex_handle; - typedef typename C3T3::Triangulation::Geom_traits::Vector_3 Vector_3; + typedef typename C3T3::Triangulation::Geom_traits Gt; + typedef typename Gt::Vector_3 Vector_3; + + const Gt& gt = c3t3.triangulation().geom_traits(); Vector_3 move = CGAL::NULL_VECTOR; @@ -193,15 +196,22 @@ namespace internal if (edges.empty()) return move; + typename Gt::Construct_vector_3 vec + = gt.construct_vector_3_object(); + typename Gt::Construct_sum_of_vectors_3 sum + = gt.construct_sum_of_vectors_3_object(); + BOOST_FOREACH(Edge e, edges) { Vertex_handle ve = (e.first->vertex(e.second) != v) ? e.first->vertex(e.second) : e.first->vertex(e.third); - move = move + Vector_3(CGAL::ORIGIN, point(ve->point())); + move = sum(move, Vector_3(CGAL::ORIGIN, point(ve->point()))); } - return 1. / edges.size() * move; + typename Gt::Construct_scaled_vector_3 scale + = gt.construct_scaled_vector_3_object(); + return scale(move, 1. / edges.size()); } template @@ -212,7 +222,10 @@ namespace internal { typedef typename C3T3::Edge Edge; typedef typename C3T3::Vertex_handle Vertex_handle; - typedef typename C3T3::Triangulation::Geom_traits::Vector_3 Vector_3; + typedef typename C3T3::Triangulation::Geom_traits Gt; + typedef typename Gt::Vector_3 Vector_3; + + const Gt& gt = c3t3.triangulation().geom_traits(); Vector_3 move = CGAL::NULL_VECTOR; @@ -222,6 +235,11 @@ namespace internal if (edges.empty()) return move; + typename Gt::Construct_vector_3 vec + = gt.construct_vector_3_object(); + typename Gt::Construct_sum_of_vectors_3 sum + = gt.construct_sum_of_vectors_3_object(); + std::size_t nbe = 0; BOOST_FOREACH(Edge e, edges) { @@ -230,13 +248,17 @@ namespace internal Vertex_handle ve = (e.first->vertex(e.second) != v) ? e.first->vertex(e.second) : e.first->vertex(e.third); - move = move + Vector_3(CGAL::ORIGIN, point(ve->point())); + move = sum(move, vec(CGAL::ORIGIN, point(ve->point()))); ++nbe; } } if (nbe > 0) - return (1. / nbe) * move; + { + typename Gt::Construct_scaled_vector_3 scale + = gt.construct_scaled_vector_3_object(); + return scale(move, 1. / nbe); + } else return CGAL::NULL_VECTOR; } @@ -249,7 +271,10 @@ namespace internal { typedef typename C3T3::Edge Edge; typedef typename C3T3::Vertex_handle Vertex_handle; - typedef typename C3T3::Triangulation::Geom_traits::Vector_3 Vector_3; + typedef typename C3T3::Triangulation::Geom_traits Gt; + typedef typename Gt::Vector_3 Vector_3; + + const Gt& gt = c3t3.triangulation().geom_traits(); Vector_3 move = CGAL::NULL_VECTOR; @@ -259,6 +284,11 @@ namespace internal if (edges.empty()) return move; + typename Gt::Construct_vector_3 vec + = gt.construct_vector_3_object(); + typename Gt::Construct_sum_of_vectors_3 sum + = gt.construct_sum_of_vectors_3_object(); + std::size_t nbe = 0; BOOST_FOREACH(Edge e, edges) { @@ -269,12 +299,16 @@ namespace internal ? e.first->vertex(e.second) : e.first->vertex(e.third); - move = move + Vector_3(CGAL::ORIGIN, point(ve->point())); + move = sum(move, vec(CGAL::ORIGIN, point(ve->point()))); ++nbe; } if (nbe == 2) - return 0.5 * move; + { + typename Gt::Construct_scaled_vector_3 scale + = gt.construct_scaled_vector_3_object(); + return scale(move, 0.5); + } else return CGAL::NULL_VECTOR; } From 27c67b70dbff8077e35bcc7928f0b9789d77a116 Mon Sep 17 00:00:00 2001 From: Jane Tournois Date: Fri, 20 Dec 2019 17:13:13 +0100 Subject: [PATCH 045/568] wip user manual --- .../Concepts/RemeshingTriangulationTraits_3.h | 4 +- .../Tetrahedral_remeshing.txt | 61 +++++++++++++++++-- .../tetrahedral_remeshing_example.cpp | 15 ++--- .../Remeshing_triangulation_3.h | 10 ++- .../include/CGAL/tetrahedral_remeshing.h | 16 +++-- 5 files changed, 75 insertions(+), 31 deletions(-) diff --git a/Tetrahedral_remeshing/doc/Tetrahedral_remeshing/Concepts/RemeshingTriangulationTraits_3.h b/Tetrahedral_remeshing/doc/Tetrahedral_remeshing/Concepts/RemeshingTriangulationTraits_3.h index 425aedd9905..26667f9b3a4 100644 --- a/Tetrahedral_remeshing/doc/Tetrahedral_remeshing/Concepts/RemeshingTriangulationTraits_3.h +++ b/Tetrahedral_remeshing/doc/Tetrahedral_remeshing/Concepts/RemeshingTriangulationTraits_3.h @@ -6,8 +6,8 @@ \cgalRefines TriangulationTraits_3 The concept `RemeshingTriangulationTraits_3` is the first template parameter -of the class Remeshing_triangulation_3. It defines the geometric objects (points, segments, -triangles and tetrahedra) forming the triangulation together with a few +of the class `Remeshing_triangulation_3`. It defines the geometric objects +(points, segments, triangles and tetrahedra) forming the triangulation together with a few geometric predicates and constructions on these objects. \cgalHasModel All models of `Kernel`. diff --git a/Tetrahedral_remeshing/doc/Tetrahedral_remeshing/Tetrahedral_remeshing.txt b/Tetrahedral_remeshing/doc/Tetrahedral_remeshing/Tetrahedral_remeshing.txt index d59a10d19fe..40d63c467a7 100644 --- a/Tetrahedral_remeshing/doc/Tetrahedral_remeshing/Tetrahedral_remeshing.txt +++ b/Tetrahedral_remeshing/doc/Tetrahedral_remeshing/Tetrahedral_remeshing.txt @@ -7,20 +7,69 @@ namespace CGAL { \authors Jane Tournois, Noura Faraj \cgalAutoToc -This chapter describes the tetrahedral remeshing algorithm... +\section secTetRemeshing Multi-Material Tetrahedral Remeshing -\section secmydefinitions Definitions +This package implements an algorithm for quality tetrahedral remeshing, +introduced by N.Faraj et al in%\cgalCite{faraj2016mvr}. +This practical iterative remeshing algorithm is designed to remesh +multi-material tetrahedral meshes, by iteratively performing a sequence of simple +elementary operations such as edge collapses, edge splits, edge flips, +and vertex relocations following a Laplacian smoothing. +The algorithm results in high quality isotropic meshes, with the desired mesh density, +while preserving the input geometric polyline and surfacic features. -Section on definitions here ... +Specific remeshing rules have been designed to satisfy the following criteria. +First, the algorithm preserves the geometric complex topology, including +multi-material surface patches and polyline features. Polyline features +can be defined as intersections between more than two subdomains, or listed by +the user. Second, it has been made possible to remesh only a selection of cells, +instead of remeshing the whole domain, while preserving or remeshing the +interface surfaces between the preserved and the remeshed tetrahedra. -\section secmyexamples Examples +All the local atomic operations that are performed by the algorithm +preserve the input topology of the geometric complex. -\subsection myFirstExample First Example +The tetrahedral remeshing algorithm improves the quality of dihedral angles, +while targetting the user-defined uniform sizing field and preserving the +topology of the feature complex. -The following example shows ... + +\section secTetRemeshingAPI API + +The tetrahedral remeshing algorithm is implemented as a single free function that +takes only two parameters : the input triangulation, and the desired edge length, +which drives the remeshing process. + +\ref BGLNamedParameters are used to deal with optional parameters. +The page \ref Remeshing_namedparameters describes their usage +and provides a list of the parameters that are used in this package for tuning +of the remeshing process and results. + + +\section secTetRemeshingExamples Examples + +\subsection ssecEx1 Tetrahedral Remeshing Example + +The following example shows the simplest use of the tetrahedral remeshing function. +The only needed parameter is a given target edge length that will drive the remeshing process +towards a high quality tetrahedral mesh with improved dihedral angles, and a more +uniform mesh, with edge lengths getting closer to the input parameter value. \cgalExample{Tetrahedral_remeshing/tetrahedral_remeshing_example.cpp } + + +\subsection ssecEx2 Tetrahedral Remeshing of A Selection + +Optional BGL named parameters can be used to get more precise +control on the remeshing process. In this example, a triangulation with two subdomains +(defined by indices stored in cells) is given as input, but only one of its subdomains +is remeshed. + \cgalExample{Tetrahedral_remeshing/tetrahedral_remeshing_of_one_subdomain.cpp } + + +\subsection ssecEx3 Tetrahedral Remeshing With Polyline Features + \cgalExample{Tetrahedral_remeshing/tetrahedral_remeshing_with_features.cpp } */ diff --git a/Tetrahedral_remeshing/examples/Tetrahedral_remeshing/tetrahedral_remeshing_example.cpp b/Tetrahedral_remeshing/examples/Tetrahedral_remeshing/tetrahedral_remeshing_example.cpp index dc014048bc1..b786380e7f3 100644 --- a/Tetrahedral_remeshing/examples/Tetrahedral_remeshing/tetrahedral_remeshing_example.cpp +++ b/Tetrahedral_remeshing/examples/Tetrahedral_remeshing/tetrahedral_remeshing_example.cpp @@ -1,14 +1,13 @@ -#define CGAL_TETRAHEDRAL_REMESHING_VERBOSE +//#define CGAL_TETRAHEDRAL_REMESHING_VERBOSE #include -#include -#include -#include - #include #include +#include +#include +#include typedef CGAL::Exact_predicates_inexact_constructions_kernel K; @@ -64,11 +63,5 @@ int main(int argc, char* argv[]) std::ofstream out(file_out.c_str(), std::ios_base::out | std::ios_base::binary); save_binary_triangulation(out, t3); - //// ascii - //file_out = file_in.substr(0, file_in.find_first_of(".")); - //file_out.append("_out.mesh"); - //std::ofstream medit_out(file_out.c_str(), std::ios_base::out); - //c3t3.output_to_medit(medit_out); - return EXIT_SUCCESS; } diff --git a/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/Remeshing_triangulation_3.h b/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/Remeshing_triangulation_3.h index ede95b4d6d1..623b7513f53 100644 --- a/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/Remeshing_triangulation_3.h +++ b/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/Remeshing_triangulation_3.h @@ -69,9 +69,6 @@ namespace Tetrahedral_remeshing \tparam Gt is the geometric traits class. It has to be a model of the concept `RemeshingTriangulationTraits_3`. - \tparam Info is the information the user would like to add to a cell. - It has to be `DefaultConstructible` and `Assignable`. - \tparam Concurrency_tag enables sequential versus parallel implementation of the triangulation data structure. Possible values are `Sequential_tag` (the default) and `Parallel_tag`. @@ -91,9 +88,9 @@ namespace Tetrahedral_remeshing typename Concurrency_tag = CGAL::Sequential_tag, typename Cb = CGAL::Triangulation_cell_base_3, typename Vb = CGAL::Triangulation_vertex_base_3 -#ifndef DOXYGEN_RUNNING + /// \cond SKIP_IN_MANUAL , typename Cell_visitor = Default_remeshing_visitor -#endif + /// \endcond > class Remeshing_triangulation_3 : public CGAL::Triangulation_3 Tds; typedef CGAL::Triangulation_3 Self; - typedef Self type; private: Cell_visitor m_visitor; + /// \cond SKIP_IN_MANUAL public: Cell_visitor& visitor() { return m_visitor; } + /// \endcond }; namespace internal diff --git a/Tetrahedral_remeshing/include/CGAL/tetrahedral_remeshing.h b/Tetrahedral_remeshing/include/CGAL/tetrahedral_remeshing.h index 46078b5b4ae..85403b891e8 100644 --- a/Tetrahedral_remeshing/include/CGAL/tetrahedral_remeshing.h +++ b/Tetrahedral_remeshing/include/CGAL/tetrahedral_remeshing.h @@ -43,7 +43,7 @@ namespace CGAL * * This function takes as input a 3-dimensional triangulation * and performs a sequence of atomic operations - * in order to generate as output a quality mesh with a prescribed edge length. + * in order to generate as output a high quality mesh with a prescribed density. * These atomic operations are performed as follows : * - edge splits, until all edges satisfy a prescribed length criterion, * - edge collapses, ntil all edges satisfy a prescribed length criterion, @@ -51,8 +51,11 @@ namespace CGAL * - global smoothing by vertex relocations, * - re-projection of boundary vertices to the initial surface. * - * This remeshing function can deal with multi-domains and preserves the geometry of - * subdomains throughout the remeshing process. Subdomains are defined by indices that + * This remeshing function can deal with multi-domains, multi-material boundaries and features. + * It preserves the geometry of + * subdomains throughout the remeshing process. + * + * Subdomains are defined by indices that * are stored in the cells of the input triangulation, following the `RemeshingCellBase_3` * concept. * The surfacic interfaces between subdomains are formed by facets which two incident cells @@ -63,9 +66,10 @@ namespace CGAL * * @tparam Triangulation a 3-dimensional triangulation * deriving from `Triangulation_3`, - * with cell base model of `RemeshingCellBase_3` + * with geometric traits model of `RemeshingTriangulationTraits_3`, + * cell base model of `RemeshingCellBase_3` * and vertex base model of `RemeshingVertexBase_3`. - * + * * @tparam NamedParameters a sequence of \ref Remeshing_namedparameters "Named Parameters" * * @param tr the triangulation to the remeshed @@ -85,7 +89,6 @@ namespace CGAL * \cgalParamBegin{edge_is_constrained_map} a property map containing the * constrained - or - not status of each edge of `tr`. A constrained edge can be split * or collapsed, but not flipped. -todo//// * Its endpoints could be moved by smoothing * \cgalParamEnd * \cgalParamBegin{cell_is_selected_map} a property map containing the * selected - or - not status for each cell of `tr` for remeshing. @@ -96,6 +99,7 @@ todo//// * Its endpoints could be moved by smoothing * \cgalNamedParamsEnd * @todo implement 1D smoothing for constrained edges + * @todo implement sizing field instead of uniform target edge length */ // * @tparam SizingField model of `CGAL::Sizing_field` From 92ac1cf2d9791ff30d6621ab92bd38fd808c3720 Mon Sep 17 00:00:00 2001 From: Jane Tournois Date: Mon, 23 Dec 2019 16:45:16 +0100 Subject: [PATCH 046/568] user manual : make better examples --- .../Tetrahedral_remeshing.txt | 10 +++- .../Tetrahedral_remeshing/CMakeLists.txt | 1 - ...e_input.cpp => tetrahedral_remeshing_io.h} | 28 +++++----- ...tetrahedral_remeshing_of_one_subdomain.cpp | 53 ++++++++----------- .../tetrahedral_remeshing_with_features.cpp | 21 +++----- .../include/CGAL/tetrahedral_remeshing.h | 12 +++++ 6 files changed, 64 insertions(+), 61 deletions(-) rename Tetrahedral_remeshing/examples/Tetrahedral_remeshing/{generate_input.cpp => tetrahedral_remeshing_io.h} (85%) diff --git a/Tetrahedral_remeshing/doc/Tetrahedral_remeshing/Tetrahedral_remeshing.txt b/Tetrahedral_remeshing/doc/Tetrahedral_remeshing/Tetrahedral_remeshing.txt index 40d63c467a7..1e45d225a7e 100644 --- a/Tetrahedral_remeshing/doc/Tetrahedral_remeshing/Tetrahedral_remeshing.txt +++ b/Tetrahedral_remeshing/doc/Tetrahedral_remeshing/Tetrahedral_remeshing.txt @@ -62,14 +62,20 @@ uniform mesh, with edge lengths getting closer to the input parameter value. Optional BGL named parameters can be used to get more precise control on the remeshing process. In this example, a triangulation with two subdomains -(defined by indices stored in cells) is given as input, but only one of its subdomains -is remeshed. +(defined by indices stored in cells) is given as input, but only one +(defined by the `Subdomain_index` 2) +of its subdomains is remeshed. \cgalExample{Tetrahedral_remeshing/tetrahedral_remeshing_of_one_subdomain.cpp } \subsection ssecEx3 Tetrahedral Remeshing With Polyline Features +Optional BGL named parameters can be used to get more precise +control on the remeshing process. In this example, a triangulation +with polyline features that should be preserved - though resampled - +during the remeshing process. + \cgalExample{Tetrahedral_remeshing/tetrahedral_remeshing_with_features.cpp } */ diff --git a/Tetrahedral_remeshing/examples/Tetrahedral_remeshing/CMakeLists.txt b/Tetrahedral_remeshing/examples/Tetrahedral_remeshing/CMakeLists.txt index 6f2cf7e1a12..6801b2b9bbe 100644 --- a/Tetrahedral_remeshing/examples/Tetrahedral_remeshing/CMakeLists.txt +++ b/Tetrahedral_remeshing/examples/Tetrahedral_remeshing/CMakeLists.txt @@ -29,5 +29,4 @@ endif() create_single_source_cgal_program( "tetrahedral_remeshing_with_features.cpp") create_single_source_cgal_program( "tetrahedral_remeshing_of_one_subdomain.cpp") - create_single_source_cgal_program( "generate_input.cpp ") create_single_source_cgal_program( "test_mesh_loader.cpp ") diff --git a/Tetrahedral_remeshing/examples/Tetrahedral_remeshing/generate_input.cpp b/Tetrahedral_remeshing/examples/Tetrahedral_remeshing/tetrahedral_remeshing_io.h similarity index 85% rename from Tetrahedral_remeshing/examples/Tetrahedral_remeshing/generate_input.cpp rename to Tetrahedral_remeshing/examples/Tetrahedral_remeshing/tetrahedral_remeshing_io.h index 971f0401dfa..e052780e7fb 100644 --- a/Tetrahedral_remeshing/examples/Tetrahedral_remeshing/generate_input.cpp +++ b/Tetrahedral_remeshing/examples/Tetrahedral_remeshing/tetrahedral_remeshing_io.h @@ -1,17 +1,12 @@ -#include + +#include +#include #include #include -#include - -#include - - -typedef CGAL::Exact_predicates_inexact_constructions_kernel K; -typedef CGAL::Tetrahedral_remeshing::Remeshing_triangulation_3 T3; - +template bool load_binary_triangulation(std::istream& is, T3& t3) { std::string s; @@ -29,6 +24,7 @@ bool load_binary_triangulation(std::istream& is, T3& t3) return bool(is); } +template bool save_binary_triangulation(std::ostream& os, const T3& t3) { typedef T3::Geom_traits::FT FT; @@ -37,15 +33,17 @@ bool save_binary_triangulation(std::ostream& os, const T3& t3) return !!(os << t3); } -int main(int argc, char* argv[]) +template +void save_ascii_triangulation(const char* filename, const T3& t3) { - const std::size_t nbv = 1000; + CGAL::Tetrahedral_remeshing::debug::dump_triangulation_cells( + t3, filename); +} - int input_id = (argc > 1) ? atoi(argv[1]) : 1; +template +int generate_input(int input_id, std::size_t nbv, T3& tr) +{ char* filename; - - T3 tr; - CGAL::Random rng; if (input_id == 1) //sphere and only one subdomain diff --git a/Tetrahedral_remeshing/examples/Tetrahedral_remeshing/tetrahedral_remeshing_of_one_subdomain.cpp b/Tetrahedral_remeshing/examples/Tetrahedral_remeshing/tetrahedral_remeshing_of_one_subdomain.cpp index de784042d75..ee37365dad1 100644 --- a/Tetrahedral_remeshing/examples/Tetrahedral_remeshing/tetrahedral_remeshing_of_one_subdomain.cpp +++ b/Tetrahedral_remeshing/examples/Tetrahedral_remeshing/tetrahedral_remeshing_of_one_subdomain.cpp @@ -10,36 +10,32 @@ #include +#include "tetrahedral_remeshing_io.h" + typedef CGAL::Exact_predicates_inexact_constructions_kernel K; - -typedef CGAL::Triangulation_3 T3; typedef CGAL::Tetrahedral_remeshing::Remeshing_triangulation_3 Remeshing_triangulation; -//todo : add specialization for Cell_base without info -// (does not compile with `void` instead of `int`) -bool generate_input(const std::size_t& n, - const char* filename) +struct Cells_of_subdomain { - T3 tr; - CGAL::Random rng; +private: + int m_subdomain; - while (tr.number_of_vertices() < n) - tr.insert(T3::Point(rng.get_double(-1., 1.), rng.get_double(-1., 1.), rng.get_double(-1., 1.))); +public: + Cells_of_subdomain(const int& subdomain) + : m_subdomain(subdomain) + {} - std::ofstream oFileT(filename, std::ios::out); - // writing file output; - oFileT << tr; - - return (!oFileT.bad()); -} + const bool operator()(Remeshing_triangulation::Cell_handle c) + { + return m_subdomain == c->subdomain_index(); + } +}; int main(int argc, char* argv[]) { - generate_input(1000, "data/random_sphere_triangulation.cgal"); - - const char* filename = (argc > 1) ? argv[1] : "data/random_sphere_triangulation.cgal"; - float target_edge_length = (argc > 2) ? atof(argv[2]) : 0.1f; + const char* filename = "data/triangulation_two_subdomains.binary.cgal"; + float target_edge_length = (argc > 1) ? atof(argv[1]) : 0.1f; std::ifstream input(filename, std::ios::in); if (!input) @@ -48,19 +44,16 @@ int main(int argc, char* argv[]) return EXIT_FAILURE; } - T3 t3; - input >> t3; - CGAL_assertion(t3.is_valid()); - Remeshing_triangulation tr; - CGAL::Tetrahedral_remeshing::build_remeshing_triangulation(t3, tr); - - CGAL::tetrahedral_adaptive_remeshing(tr, target_edge_length); + generate_input(2, 1000, tr); - std::ofstream oFileT("output.tr.cgal", std::ios::out); - // writing file output; - oFileT << tr; + CGAL::tetrahedral_adaptive_remeshing(tr, target_edge_length, + CGAL::parameters::cell_selector(Cells_of_subdomain(2))); + std::ofstream oFileT("output.binary.cgal", std::ios::out); + save_binary_triangulation(oFileT, tr); + + std::cout << "done" << std::endl; return EXIT_SUCCESS; } diff --git a/Tetrahedral_remeshing/examples/Tetrahedral_remeshing/tetrahedral_remeshing_with_features.cpp b/Tetrahedral_remeshing/examples/Tetrahedral_remeshing/tetrahedral_remeshing_with_features.cpp index b1b7c88c2b4..985ecdea48c 100644 --- a/Tetrahedral_remeshing/examples/Tetrahedral_remeshing/tetrahedral_remeshing_with_features.cpp +++ b/Tetrahedral_remeshing/examples/Tetrahedral_remeshing/tetrahedral_remeshing_with_features.cpp @@ -1,7 +1,3 @@ -#include -#include -#include - #define CGAL_TETRAHEDRAL_REMESHING_VERBOSE #define CGAL_DUMP_REMESHING_STEPS @@ -10,12 +6,17 @@ #include #include - #include #include #include +#include +#include +#include + +#include "tetrahedral_remeshing_io.h" + typedef CGAL::Exact_predicates_inexact_constructions_kernel K; typedef CGAL::Tetrahedral_remeshing::Remeshing_triangulation_3 Remeshing_triangulation; @@ -140,19 +141,13 @@ int main(int argc, char* argv[]) input >> t3; CGAL_assertion(t3.is_valid()); - CGAL::Tetrahedral_remeshing::debug::dump_triangulation_cells(t3, - "tet_remeshing_with_features_before.mesh"); + save_ascii_triangulation("tet_remeshing_with_features_before.mesh", t3); CGAL::tetrahedral_adaptive_remeshing(t3, target_edge_length, CGAL::parameters::edge_is_constrained_map( Constrained_edges_property_map(&constraints))); - std::ofstream oFileT("output.tr.cgal", std::ios::out); - // writing file output; - oFileT << t3; - - CGAL::Tetrahedral_remeshing::debug::dump_triangulation_cells(t3, - "tet_remeshing_with_features_after.mesh"); + save_ascii_triangulation("tet_remeshing_with_features_after.mesh", t3); return EXIT_SUCCESS; } diff --git a/Tetrahedral_remeshing/include/CGAL/tetrahedral_remeshing.h b/Tetrahedral_remeshing/include/CGAL/tetrahedral_remeshing.h index 85403b891e8..ab4edc25a81 100644 --- a/Tetrahedral_remeshing/include/CGAL/tetrahedral_remeshing.h +++ b/Tetrahedral_remeshing/include/CGAL/tetrahedral_remeshing.h @@ -125,6 +125,18 @@ namespace CGAL np); } + template + void tetrahedral_adaptive_remeshing(Triangulation& tr, + const float& target_edge_length, + const NamedParameters& np) + { + tetrahedral_adaptive_remeshing( + tr, + [target_edge_length](const typename Triangulation::Point& p) + {return target_edge_length; }, + np); + } + template From 0eb3fb2848e8664b501d7fd9e33500c7147c28a1 Mon Sep 17 00:00:00 2001 From: Jane Tournois Date: Thu, 9 Jan 2020 15:21:21 +0100 Subject: [PATCH 047/568] complete examples --- .../Tetrahedral_remeshing/CMakeLists.txt | 5 ----- .../tetrahedral_remeshing_with_features.cpp | 16 ++++++++++++++-- 2 files changed, 14 insertions(+), 7 deletions(-) diff --git a/Tetrahedral_remeshing/examples/Tetrahedral_remeshing/CMakeLists.txt b/Tetrahedral_remeshing/examples/Tetrahedral_remeshing/CMakeLists.txt index 6801b2b9bbe..855e5acbde1 100644 --- a/Tetrahedral_remeshing/examples/Tetrahedral_remeshing/CMakeLists.txt +++ b/Tetrahedral_remeshing/examples/Tetrahedral_remeshing/CMakeLists.txt @@ -20,13 +20,8 @@ if ( NOT Boost_FOUND ) endif() -# include for local directory -#include_directories( BEFORE include ) - # Creating entries for all C++ files with "main" routine # ########################################################## create_single_source_cgal_program( "tetrahedral_remeshing_example.cpp" ) create_single_source_cgal_program( "tetrahedral_remeshing_with_features.cpp") create_single_source_cgal_program( "tetrahedral_remeshing_of_one_subdomain.cpp") - - create_single_source_cgal_program( "test_mesh_loader.cpp ") diff --git a/Tetrahedral_remeshing/examples/Tetrahedral_remeshing/tetrahedral_remeshing_with_features.cpp b/Tetrahedral_remeshing/examples/Tetrahedral_remeshing/tetrahedral_remeshing_with_features.cpp index 985ecdea48c..18fa43ee700 100644 --- a/Tetrahedral_remeshing/examples/Tetrahedral_remeshing/tetrahedral_remeshing_with_features.cpp +++ b/Tetrahedral_remeshing/examples/Tetrahedral_remeshing/tetrahedral_remeshing_with_features.cpp @@ -122,13 +122,23 @@ void generate_input(const std::size_t& n, add_edge(v3, v7, tr, constraints); } +void set_subdomain(Remeshing_triangulation& tr, const int index) +{ + for (Remeshing_triangulation::Finite_cells_iterator cit = tr.finite_cells_begin(); + cit != tr.finite_cells_end(); ++cit) + { + cit->set_subdomain_index(index); + } +} + int main(int argc, char* argv[]) { boost::unordered_set > constraints; generate_input(1000, "data/sphere_in_cube.tr.cgal", constraints); const char* filename = (argc > 1) ? argv[1] : "data/sphere_in_cube.tr.cgal"; - double target_edge_length = (argc > 2) ? atof(argv[2]) : 0.1; + double target_edge_length = (argc > 2) ? atof(argv[2]) : 0.02; + int nb_iter = (argc > 3) ? atoi(argv[3]) : 1; std::ifstream input(filename, std::ios::in); if (!input) @@ -139,13 +149,15 @@ int main(int argc, char* argv[]) Remeshing_triangulation t3; input >> t3; + set_subdomain(t3, 1); CGAL_assertion(t3.is_valid()); save_ascii_triangulation("tet_remeshing_with_features_before.mesh", t3); CGAL::tetrahedral_adaptive_remeshing(t3, target_edge_length, CGAL::parameters::edge_is_constrained_map( - Constrained_edges_property_map(&constraints))); + Constrained_edges_property_map(&constraints)) + .number_of_iterations(nb_iter)); save_ascii_triangulation("tet_remeshing_with_features_after.mesh", t3); From 2bc950041cda6fbc34bfda283c49fdec26178fef Mon Sep 17 00:00:00 2001 From: Jane Tournois Date: Thu, 9 Jan 2020 15:21:53 +0100 Subject: [PATCH 048/568] add validity check --- .../examples/Tetrahedral_remeshing/tetrahedral_remeshing_io.h | 3 +++ 1 file changed, 3 insertions(+) diff --git a/Tetrahedral_remeshing/examples/Tetrahedral_remeshing/tetrahedral_remeshing_io.h b/Tetrahedral_remeshing/examples/Tetrahedral_remeshing/tetrahedral_remeshing_io.h index e052780e7fb..e42f07740ff 100644 --- a/Tetrahedral_remeshing/examples/Tetrahedral_remeshing/tetrahedral_remeshing_io.h +++ b/Tetrahedral_remeshing/examples/Tetrahedral_remeshing/tetrahedral_remeshing_io.h @@ -36,6 +36,9 @@ bool save_binary_triangulation(std::ostream& os, const T3& t3) template void save_ascii_triangulation(const char* filename, const T3& t3) { + if (!t3.is_valid(true)) + std::cerr << "Invalid triangulation!" << std::endl; + CGAL::Tetrahedral_remeshing::debug::dump_triangulation_cells( t3, filename); } From fcdb6612bec67c16605810c351c05282aec9fa52 Mon Sep 17 00:00:00 2001 From: Jane Tournois Date: Thu, 9 Jan 2020 15:22:38 +0100 Subject: [PATCH 049/568] c3t3 subdomain indices need to be updated in the c3t3 item after remeshing --- .../Tetrahedral_remeshing_plugin.cpp | 37 ++++++++++++++++++- 1 file changed, 36 insertions(+), 1 deletion(-) diff --git a/Polyhedron/demo/Polyhedron/Plugins/Tetrahedral_remeshing/Tetrahedral_remeshing_plugin.cpp b/Polyhedron/demo/Polyhedron/Plugins/Tetrahedral_remeshing/Tetrahedral_remeshing_plugin.cpp index 37060762ace..13ffe77fcf9 100644 --- a/Polyhedron/demo/Polyhedron/Plugins/Tetrahedral_remeshing/Tetrahedral_remeshing_plugin.cpp +++ b/Polyhedron/demo/Polyhedron/Plugins/Tetrahedral_remeshing/Tetrahedral_remeshing_plugin.cpp @@ -1,5 +1,6 @@ #define CGAL_TETRAHEDRAL_REMESHING_VERBOSE #define CGAL_DUMP_REMESHING_STEPS +#define CGAL_TETRAHEDRAL_REMESHING_DEBUG #include @@ -109,6 +110,39 @@ namespace CGAL { Vertex_converter(), Cell_converter())); } + + void update_c3t3(C3t3& c3t3) + { + for (typename C3t3::Triangulation::Finite_facets_iterator + fit = c3t3.triangulation().finite_facets_begin(); + fit != c3t3.triangulation().finite_facets_end(); + ++fit) + { + typename C3t3::Triangulation::Facet f = *fit; + typename C3t3::Triangulation::Cell::Subdomain_index + s1 = f.first->subdomain_index(), + s2 = f.first->neighbor(f.second)->subdomain_index(); + if (s1 != s2) + { + if (s1 > s2) + std::swap(s1, s2); + c3t3.add_to_complex(f, s1 + 100 * s2);// std::make_pair(s1, s2)); + } + } + for (typename C3t3::Triangulation::Finite_cells_iterator + cit = c3t3.triangulation().finite_cells_begin(); + cit != c3t3.triangulation().finite_cells_end(); + ++cit) + { + typename C3t3::Triangulation::Cell::Subdomain_index + si = cit->subdomain_index(); + if (si != 0) + { + cit->set_subdomain_index(0);//o.w. add_to_complex() does nothing + c3t3.add_to_complex(cit, si); + } + } + } } } @@ -183,7 +217,6 @@ public Q_SLOTS: std::cout << "Remeshing triangulation built (" << time.elapsed() << " ms)" << std::endl; time.restart(); - CGAL::tetrahedral_adaptive_remeshing(tr, target_length, CGAL::parameters::protect_boundaries(protect) .number_of_iterations(nb_iter)); @@ -191,7 +224,9 @@ public Q_SLOTS: std::cout << "Remeshing done (" << time.elapsed() << " ms)" << std::endl; time.restart(); + c3t3_item->c3t3().clear(); CGAL::internal::build_from_remeshing_triangulation(tr, c3t3_item->c3t3().triangulation()); + CGAL::internal::update_c3t3(c3t3_item->c3t3()); std::cout << "Back conversion done (" << time.elapsed() << " ms)" << std::endl; From b0549946f53f57df471de743847de0e2e9669510 Mon Sep 17 00:00:00 2001 From: Jane Tournois Date: Thu, 9 Jan 2020 15:23:34 +0100 Subject: [PATCH 050/568] add dump helpers and fix existing dump functions --- .../internal/tetrahedral_remeshing_helpers.h | 65 ++++++++++++++----- .../include/CGAL/tetrahedral_remeshing.h | 22 +++++-- 2 files changed, 65 insertions(+), 22 deletions(-) diff --git a/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/tetrahedral_remeshing_helpers.h b/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/tetrahedral_remeshing_helpers.h index c7ee3c66a57..aab9182c0d9 100644 --- a/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/tetrahedral_remeshing_helpers.h +++ b/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/tetrahedral_remeshing_helpers.h @@ -73,14 +73,14 @@ namespace Tetrahedral_remeshing return indices_table[i][j]; } - template - typename Tr::Geom_traits::FT dihedral_angle(const Tr& tr, - const typename Tr::Point& p, - const typename Tr::Point& q, - const typename Tr::Point& r, - const typename Tr::Point& s) + template + typename Gt::FT dihedral_angle(const Point& p, + const Point& q, + const Point& r, + const Point& s, + const Gt& gt) { - return tr.geom_traits().compute_approximate_dihedral_angle_3_object()(p, q, r, s); + return gt.compute_approximate_dihedral_angle_3_object()(p, q, r, s); } template @@ -91,22 +91,22 @@ namespace Tetrahedral_remeshing const typename Tr::Point& s) { typedef typename Tr::Geom_traits::FT FT; - FT a = CGAL::abs(dihedral_angle(tr, p, q, r, s)); + FT a = CGAL::abs(dihedral_angle(p, q, r, s, tr.geom_traits())); FT min_dh = a; - a = CGAL::abs(dihedral_angle(tr, p, r, q, s)); + a = CGAL::abs(dihedral_angle(p, r, q, s, tr.geom_traits())); min_dh = (std::min)(a, min_dh); - a = CGAL::abs(dihedral_angle(tr, p, s, q, r)); + a = CGAL::abs(dihedral_angle(p, s, q, r, tr.geom_traits())); min_dh = (std::min)(a, min_dh); - a = CGAL::abs(dihedral_angle(tr, q, r, p, s)); + a = CGAL::abs(dihedral_angle(q, r, p, s, tr.geom_traits())); min_dh = (std::min)(a, min_dh); - a = CGAL::abs(dihedral_angle(tr, q, s, p, r)); + a = CGAL::abs(dihedral_angle(q, s, p, r, tr.geom_traits())); min_dh = (std::min)(a, min_dh); - a = CGAL::abs(dihedral_angle(tr, r, s, p, q)); + a = CGAL::abs(dihedral_angle(r, s, p, q, tr.geom_traits())); min_dh = (std::min)(a, min_dh); return min_dh; @@ -1169,8 +1169,6 @@ namespace Tetrahedral_remeshing ofs << " 1" << std::endl; else { - // std::cerr << "Cell #" << (cit - cells.begin()) - // << " has original index " << *iit << std::endl; ofs << " " << (*iit) << std::endl; ++iit; } @@ -1279,6 +1277,35 @@ namespace Tetrahedral_remeshing ofs.close(); } + template + void dump_cells_with_small_dihedral_angle(const Tr& tr, + const double angle_bound, + const int imaginary_index, + CellSelector cell_select, + const char* filename) + { + typedef typename Tr::Cell_handle Cell_handle; + typedef typename Tr::Cell::Subdomain_index Subdomain_index; + std::vector cells; + std::vector indices; + + for (typename Tr::Finite_cells_iterator cit = tr.finite_cells_begin(); + cit != tr.finite_cells_end(); ++cit) + { + Cell_handle c = cit; + if ( c->subdomain_index() != Subdomain_index() + && cell_select(c) + && min_dihedral_angle(tr, c) < angle_bound) + { + + cells.push_back(c); + indices.push_back(c->subdomain_index()); + } + } + std::cout << "bad cells : " << cells.size() << std::endl; + dump_cells(cells, indices, filename); + } + template void dump_vertices_by_dimension(const Tr& tr, const char* prefix) { @@ -1322,13 +1349,15 @@ namespace Tetrahedral_remeshing void dump_triangulation_cells(const Tr& tr, const char* filename) { std::vector cells(tr.number_of_finite_cells()); + std::vector indices(tr.number_of_finite_cells()); int i = 0; for (typename Tr::Finite_cells_iterator cit = tr.finite_cells_begin(); cit != tr.finite_cells_end(); ++cit) { - cells[i++] = cit; + cells[i] = cit; + indices[i++] = cit->subdomain_index(); } - dump_cells(cells, filename); + dump_cells(cells, indices, filename); } template @@ -1345,7 +1374,7 @@ namespace Tetrahedral_remeshing && cit->subdomain_index() != imaginary_index) { cells.push_back(cit); - indices.push_back(1); + indices.push_back(cit->subdomain_index()); } } dump_cells(cells, indices, filename); diff --git a/Tetrahedral_remeshing/include/CGAL/tetrahedral_remeshing.h b/Tetrahedral_remeshing/include/CGAL/tetrahedral_remeshing.h index ab4edc25a81..d290f8cb2ce 100644 --- a/Tetrahedral_remeshing/include/CGAL/tetrahedral_remeshing.h +++ b/Tetrahedral_remeshing/include/CGAL/tetrahedral_remeshing.h @@ -179,6 +179,11 @@ namespace CGAL , No_constraint()); #ifdef CGAL_TETRAHEDRAL_REMESHING_VERBOSE + std::cout << "Tetrahedral remeshing (" + << "nb_iter = " << max_it + << "protect = " << std::boolalpha << protect << ", " + << ")" << std::endl; + std::cout << "Init tetrahedral remeshing..."; std::cout.flush(); #endif @@ -199,13 +204,16 @@ namespace CGAL remesher.preprocess(); std::size_t it_nb = 0; - while (it_nb++ < max_it && !remesher.resolution_reached()) + while (it_nb++ < max_it) { #ifdef CGAL_TETRAHEDRAL_REMESHING_VERBOSE std::cout << "# Iteration " << it_nb << " #" << std::endl; #endif - remesher.split(); - remesher.collapse(); + if (!remesher.resolution_reached()) + { + remesher.split(); + remesher.collapse(); + } remesher.flip(); remesher.smooth(); @@ -246,10 +254,16 @@ namespace CGAL remesher.postprocess(); remesher.finalize(); + //remesher.triangulation() is now empty +#ifdef CGAL_TETRAHEDRAL_REMESHING_DEBUG + const double angle_bound = 5.0; + Tetrahedral_remeshing::debug::dump_cells_with_small_dihedral_angle(tr, + angle_bound, remesher.imaginary_index(), cell_select, "bad_cells.mesh"); +#endif #ifdef CGAL_TETRAHEDRAL_REMESHING_VERBOSE Tetrahedral_remeshing::internal::compute_statistics(tr, - remesher.imaginary_index(), cell_select, "statistics_end.txt"); + remesher.imaginary_index(), cell_select, "statistics_end.txt"); #endif } From 94b1fe8618bf419951e9fc13f23d5af3bb488ef1 Mon Sep 17 00:00:00 2001 From: Jane Tournois Date: Fri, 10 Jan 2020 13:24:29 +0100 Subject: [PATCH 051/568] user manual --- .../Tetrahedral_remeshing.txt | 13 +++++++++++-- .../Tetrahedral_remeshing/fig/bimba_back.png | Bin 0 -> 45073 bytes .../fig/bimba_back_small.png | Bin 0 -> 26205 bytes .../fig/tetrahedral_remeshing_before_after.png | Bin 0 -> 163815 bytes 4 files changed, 11 insertions(+), 2 deletions(-) create mode 100644 Tetrahedral_remeshing/doc/Tetrahedral_remeshing/fig/bimba_back.png create mode 100644 Tetrahedral_remeshing/doc/Tetrahedral_remeshing/fig/bimba_back_small.png create mode 100644 Tetrahedral_remeshing/doc/Tetrahedral_remeshing/fig/tetrahedral_remeshing_before_after.png diff --git a/Tetrahedral_remeshing/doc/Tetrahedral_remeshing/Tetrahedral_remeshing.txt b/Tetrahedral_remeshing/doc/Tetrahedral_remeshing/Tetrahedral_remeshing.txt index 1e45d225a7e..08c5bfcbb56 100644 --- a/Tetrahedral_remeshing/doc/Tetrahedral_remeshing/Tetrahedral_remeshing.txt +++ b/Tetrahedral_remeshing/doc/Tetrahedral_remeshing/Tetrahedral_remeshing.txt @@ -31,7 +31,15 @@ preserve the input topology of the geometric complex. The tetrahedral remeshing algorithm improves the quality of dihedral angles, while targetting the user-defined uniform sizing field and preserving the -topology of the feature complex. +topology of the feature complex, as highlighted by Figure \cgalFigureRef{Remesh_liver}. + + +\cgalFigureBegin{Remesh_liver, tetrahedral_remeshing_before_after.png} +Tetrahedral mesh, modified by our uniform tetrahedral remeshing method. +(Left) Before remeshing, dihedral angles were in the interval [1.3; 177.8]. +(Right) After remeshing and keeping the same density, +dihedral angles were are the interval [9.5; 161.9]. +\cgalFigureEnd \section secTetRemeshingAPI API @@ -74,7 +82,8 @@ of its subdomains is remeshed. Optional BGL named parameters can be used to get more precise control on the remeshing process. In this example, a triangulation with polyline features that should be preserved - though resampled - -during the remeshing process. +during the remeshing process. It would also be possible to preserve +the input polyline features exactly. \cgalExample{Tetrahedral_remeshing/tetrahedral_remeshing_with_features.cpp } diff --git a/Tetrahedral_remeshing/doc/Tetrahedral_remeshing/fig/bimba_back.png b/Tetrahedral_remeshing/doc/Tetrahedral_remeshing/fig/bimba_back.png new file mode 100644 index 0000000000000000000000000000000000000000..45ec300bc67111019e564dee4971037b003a498d GIT binary patch literal 45073 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 literal 0 HcmV?d00001 diff --git a/Tetrahedral_remeshing/doc/Tetrahedral_remeshing/fig/bimba_back_small.png b/Tetrahedral_remeshing/doc/Tetrahedral_remeshing/fig/bimba_back_small.png new file mode 100644 index 0000000000000000000000000000000000000000..5cfbd7e3fd8da8705837dfc17cd6dd6e4f04e095 GIT binary patch literal 26205 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 M07*qoM6N<$f^sX_O8@`> literal 0 HcmV?d00001 diff --git a/Tetrahedral_remeshing/doc/Tetrahedral_remeshing/fig/tetrahedral_remeshing_before_after.png b/Tetrahedral_remeshing/doc/Tetrahedral_remeshing/fig/tetrahedral_remeshing_before_after.png new file mode 100644 index 0000000000000000000000000000000000000000..de0380aaad475bfead4cfc1d78700a1f0a761e75 GIT binary patch literal 163815 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
km*z~OSo-+j({;a1lpG1 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 U2xQ#&mjRfRn7nAMuwl^u0cG3{0ssI2 literal 0 HcmV?d00001 From 1c51a62a1551b5dba95dc3f00120feddce795940 Mon Sep 17 00:00:00 2001 From: Jane Tournois Date: Thu, 16 Jan 2020 13:24:02 +0100 Subject: [PATCH 052/568] reintroduce FLMS smoothing on surfaces code compiles but crashes in the smoothing step in the demo --- .../Tetrahedral_remeshing/internal/FMLS.h | 587 ++++++++++++ .../Tetrahedral_remeshing/internal/Vec3D.h | 376 ++++++++ .../internal/smooth_vertices.h | 851 +++++++++--------- .../internal/tetrahedral_remeshing_helpers.h | 12 + .../include/CGAL/tetrahedral_remeshing.h | 4 +- 5 files changed, 1395 insertions(+), 435 deletions(-) create mode 100644 Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/FMLS.h create mode 100644 Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/Vec3D.h diff --git a/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/FMLS.h b/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/FMLS.h new file mode 100644 index 00000000000..8938949b2a1 --- /dev/null +++ b/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/FMLS.h @@ -0,0 +1,587 @@ +#ifndef CGAL_TETRAHEDRAL_REMESHING_FMLS_H +#define CGAL_TETRAHEDRAL_REMESHING_FMLS_H + +// ------------------------------------------- +// FMLS +// A Fast Moving Least Square operator for 3D +// points sets. +// +// Copyright (C) 2006-2011 Tamy Boubekeur +// All rights reserved. +// ------------------------------------------- + +// ------------------------------------------- +// Disclaimer: this code is dirty in the +// meaning that there is no attention paid to +// proper class attribute access, memory +// management or optimisation of any kind. It +// is designed for quick-and-dirty testing +// purpose. +// ------------------------------------------- + +#include +#include + +#include +#include + + +#include "Vec3D.h" + +namespace CGAL +{ + namespace Tetrahedral_remeshing + { + namespace internal + { + // -------------------------------------------------------------- + // CPU Memory Code + // -------------------------------------------------------------- + + template + void freeCPUResource(T** res) { + if (*res != NULL) { + free(*res); + *res = NULL; + } + } + + // -------------------------------------------------------------- + // MLS Projection + // -------------------------------------------------------------- + + inline float wendland(float x, float h) + { + x = CGAL::abs(x); + if (x < h) + return CGAL::square(CGAL::square(1 - x / h)) * (4 * x / h + 1); + else + return 0.0; + } + + inline void setPNSample(float* p, unsigned int i, + float x, float y, float z, + float nx, float ny, float nz) + { + p[6 * i] = x; + p[6 * i + 1] = y; + p[6 * i + 2] = z; + p[6 * i + 3] = nx; + p[6 * i + 4] = ny; + p[6 * i + 5] = nz; + } + + inline void weightedPointCombination(const Vec3Df& x, const Vec3Df& pi, const Vec3Df& ni, + float sigma_s, bool bilateral, float sigma_r, + bool hermite, + Vec3Df& c, Vec3Df& nc, float& sumW) + { + float w = wendland(Vec3Df::distance(x, pi), sigma_s); + if (bilateral) + w *= wendland((x - x.projectOn(ni, pi)).getLength(), sigma_r); + if (hermite) + c += w * x.projectOn(ni, pi); + else + c += w * pi; + nc += w * ni; + sumW += w; + } + + class FMLS + { + public: + // FMLS provide MLS projection and filtering from a point set. + // The underlying data structure is a simple list of float in the PN format + // A PN object is a list of 6xfloat32 chunk : + // x0,y0,z0,nx0,ny0,nz0,x1,y1,z1,nx1,ny1,nz1,... + // with {xi,yi,zi} the position and {nxi,nyi,nzi} the normal vector of the + // i-th point sample. A PN can be read from and write to file directly + // (identity serialization) and is handled as a simple float32 pointer. + // + // Use the 'fast*' methods. Brute force methods are inserted only for comparison. + // + // Memory policy: a FMLS class manages itself al its belonging objects. + // Therefore, PN and filtered PN lists are the property of this class, and should + // be copied if modified outside the class. + FMLS() + { + PN = NULL; + PNSize = 0; + PNScale = 1.0f; + MLSRadius = 0.1f; + bilateralRange = 0.05f; + bilateral = false; + hermite = false; + numIter = 1; + } + ~FMLS() + { + freeCPUMemory(); + } + + // -------------------------------------------------------------- + // Main Interface + // -------------------------------------------------------------- + + float* createPN(unsigned int size) + { + return (float*)malloc(size * SURFEL_SIZE); + } + + float* clonePN() + { + float* clone = createPN(PNSize); + memcpy(clone, PN, PNSize * SURFEL_SIZE); + return clone; + } + + void loadPN(const char* filename) + { + freeCPUMemory(); + FILE* file = fopen(filename, "r"); + if (!file) + throw Exception("Cannot read file" + std::string(filename)); + fseek(file, 0, SEEK_END); + unsigned int numOfByte = ftell(file); + fseek(file, 0, SEEK_SET); + PNSize = numOfByte / SURFEL_SIZE; + PN = createPN(PNSize); + fread(PN, SURFEL_SIZE, PNSize, file); + fclose(file); + + computePNScale(); + grid.clear(); + grid.init(PN, PNSize, MLSRadius * PNScale); + } + + void setPN(float* newPN, unsigned int newPNSize) + { + freeCPUMemory(); + PN = newPN; + PNSize = newPNSize; + computePNScale(); + grid.clear(); + grid.init(PN, PNSize, MLSRadius * PNScale); + } + + void setPN(float* newPN, unsigned int newPNSize, float pointSpacing) + { + freeCPUMemory(); + PN = newPN; + PNSize = newPNSize; + computePNScale(); + MLSRadius = 3 * pointSpacing / PNScale; + grid.clear(); + grid.init(PN, PNSize, MLSRadius * PNScale); + } + + static void savePN(float* pn, unsigned int size, const char* filename) + { + FILE* file = fopen(filename, "w"); + if (!file) + throw Exception("Cannot write to file" + std::string(filename)); + fwrite(pn, SURFEL_SIZE, size, file); + fclose(file); + } + + template + void fastProjectionCPU(const CGAL::Point_3& vp, + CGAL::Point_3& vq, + CGAL::Vector_3& vn) + { + Vec3Df p(vp.x(), vp.y(), vp.z()); + Vec3Df q(vq.x(), vq.y(), vq.z()); + Vec3Df n(vn.x(), vn.y(), vn.z()); + fastProjectionCPU(p, q, n); + + vq = CGAL::Point_3(q[0], q[1], q[2]); + vn = CGAL::Vector_3(n[0], n[1], n[2]); + } + + // Compute, according to the current point sampling stored in FMLS, the MLS projection + // of p and store the resulting position in q and normal in n. + void fastProjectionCPU(const Vec3Df& p, Vec3Df& q, Vec3Df& n) + { + float sigma_s = PNScale * MLSRadius; + float sigma_r = bilateralRange; + Vec3Df g = (p - Vec3Df(grid.getMinMax()[0], grid.getMinMax()[1], grid.getMinMax()[2])) / sigma_s; + for (unsigned int j = 0; j < 3; j++) { + g[j] = floor(g[j]); + if (g[j] < 0.f) + g[j] = 0.f; + if (g[j] >= grid.getRes()[j]) + g[j] = grid.getRes()[j] - 1; + } + unsigned int minIt[3], maxIt[3]; + for (unsigned int j = 0; j < 3; j++) { + if (((unsigned int)g[j]) == 0) + minIt[j] = 0; + else + minIt[j] = ((unsigned int)g[j]) - 1; + if (((unsigned int)g[j]) == (grid.getRes()[j] - 1)) + maxIt[j] = (grid.getRes()[j] - 1); + else + maxIt[j] = ((unsigned int)g[j]) + 1; + } + Vec3Df c; + float sumW = 0.f; + unsigned int it[3]; + for (it[0] = minIt[0]; it[0] <= maxIt[0]; it[0]++) + for (it[1] = minIt[1]; it[1] <= maxIt[1]; it[1]++) + for (it[2] = minIt[2]; it[2] <= maxIt[2]; it[2]++) { + unsigned int gridIndex = grid.getLUTElement(it[0], it[1], it[2]); + if (gridIndex == 2 * PNSize) + continue; + unsigned int neigh = grid.getCellIndicesSize(it[0], it[1], it[2]); + for (unsigned int j = 0; j < neigh; j++) { + unsigned int k = grid.getIndicesElement(it[0], it[1], it[2], j); + Vec3Df pk(PN[6 * k], PN[6 * k + 1], PN[6 * k + 2]); + Vec3Df nk(PN[6 * k + 3], PN[6 * k + 4], PN[6 * k + 5]); + weightedPointCombination(p, pk, nk, sigma_s, bilateral, sigma_r, hermite, c, n, sumW); + } + } + if (sumW == 0.f) { + n = Vec3Df(1.f, 0.f, 0.f); + q = p; + } + else { + c /= sumW; + n.normalize(); + q = p.projectOn(n, c); + } + } + + // Compute the MLS projection of the list of point stored in pv and store the resulting + // positions and normal in qv. qv must be preallocated to stroe 6*pvSize float32. + // The strid indicates the offsets in qv (the defautl value of 3 means that the qv + // is compact: pv={x0,y0,z0,x1,y1,z1...}. If pv contains also normals for instance, + // the stride should be set to 6. + void fastProjectionCPU(const float* pv, unsigned int pvSize, + float* qv, unsigned int stride = 3) + { +#pragma omp parallel for + for (int i = 0; i < int(pvSize); i++) { + Vec3Df p(pv[stride * i], pv[stride * i + 1], pv[stride * i + 2]); + Vec3Df q, n; + for (unsigned int j = 0; j < numIter; j++) { + q = Vec3Df(); + n = Vec3Df(); + fastProjectionCPU(p, q, n); + p = q; + } + setPNSample(qv, i, q[0], q[1], q[2], n[0], n[1], n[2]); + } + + } + + // Brute force version. O(PNSize) complexity. For comparison only. + void projectionCPU(const Vec3Df& x, Vec3Df& q, Vec3Df& n) + { + float sigma_s = MLSRadius * PNScale; + float sigma_r = bilateralRange; + Vec3Df p(x); + for (unsigned int k = 0; k < numIter; k++) { + Vec3Df c; + n = Vec3Df();; + float sumW = 0.f; + for (unsigned int j = 0; j < PNSize; j++) { + Vec3Df pj(PN[6 * j], PN[6 * j + 1], PN[6 * j + 2]); + Vec3Df nj(PN[6 * j + 3], PN[6 * j + 4], PN[6 * j + 5]); + weightedPointCombination(p, pj, nj, sigma_s, bilateral, sigma_r, hermite, c, n, sumW); + } + c /= sumW; + n.normalize(); + q = p.projectOn(n, c); + p = q; + } + + } + // Brute force version. O(pvSize*PNSize) complexity. For comparison only. + void projectionCPU(const float* pv, unsigned int pvSize, + float* qv, unsigned int stride = 3) + { +#pragma omp parallel for + for (int i = 0; i < int(pvSize); i++) { + Vec3Df p(pv[stride * i], pv[stride * i + 1], pv[stride * i + 2]); + Vec3Df q, n; + for (unsigned int j = 0; j < numIter; j++) { + q = Vec3Df(); + n = Vec3Df(); + projectionCPU(p, q, n); + p = q; + } + setPNSample(qv, i, q[0], q[1], q[2], n[0], n[1], n[2]); + } + } + + + // -------------------------------------------------------------------- + // Filtering by applying MLS projection on the input point set itself. + // -------------------------------------------------------------------- + // The 'filter*_*' methods apply the MLS projection to the PN samples themselves, + // providing a low pass (or feature preserving, dependeing on the options) + // version which can be gathered using 'getFilteredPN ()' afterwards. + void fastFilterCPU(float* fPN) + { + fastProjectionCPU(PN, PNSize, fPN, 6); + } + + void filterCPU(float* fPN) // Brute force method. O(PNSize^2) complexity. For comparison only. + { + projectionCPU(PN, PNSize, fPN, 6); + } + + // -------------------------------------------------------------- + // Accessors + // -------------------------------------------------------------- + + // Number of elements of the PN. One elemnt is a 6-float32 chunk. + inline unsigned int getPNSize() const { return PNSize; } + inline float* getPN() { return PN; } + inline const float* getPN() const { return PN; } + + // Min/Max corners of PN's bounding volume + inline const float* getMinMax() const { return grid.getMinMax(); } + // Radius of the bounding sphere of the PN + inline float getPNScale() const { return PNScale; } + // Normalized MLS support size + inline float getMLSRadius() const { return MLSRadius; } + inline void setMLSRadius(float s) { MLSRadius = s; grid.clear(); grid.init(PN, PNSize, MLSRadius * PNScale); } + // Bilateral weighting for feature preservation (inspired by [Jones 2003]). + inline bool isBilateral() const { return bilateral; } + inline void toggleBilateral(bool b) { bilateral = b; } + // Bilateral support size for the range weight + inline float getBilateralRange() const { return bilateralRange; } + inline void setBilateralRange(float r) { bilateralRange = r; } + // Hermite interpolation [Alexa 2009] + inline bool isHermite() const { return hermite; } + inline void toggleHermite(bool b) { hermite = b; } + // Fix number of iterations of the MLS projection + inline unsigned int getNumOfIter() const { return numIter; } + inline void setNumOfIter(unsigned int i) { numIter = i; } + + // -------------------------------------------------------------- + // Misc. + // -------------------------------------------------------------- + + // Size of a point sample in bytes (6xfloat32: 3 for position and normal + static const unsigned int SURFEL_SIZE = 24; + + class Exception { + private: + std::string msg; + public: + inline Exception(const std::string& msg) : msg(msg) {} + virtual ~Exception() {} + inline const std::string getMessage() const { return std::string("[FMLS][Error]: ") + msg; } + }; + + private: + + void computePNScale() + { + Vec3Df c; + for (unsigned int i = 0; i < PNSize; i++) + c += Vec3Df(PN[6 * i], PN[6 * i + 1], PN[6 * i + 2]); + c /= PNSize; + PNScale = 0.f; + for (unsigned int i = 0; i < PNSize; i++) { + float r = Vec3Df::distance(c, Vec3Df(PN[6 * i], PN[6 * i + 1], PN[6 * i + 2])); + if (r > PNScale) + PNScale = r; + } + } + + // -------------------------------------------------------------- + // 3D Grid Structure + // -------------------------------------------------------------- + // -------------------------------------------------------------- + // Grid data structure for fast r-ball neighborhood query + // -------------------------------------------------------------- + + class Grid + { + public: + Grid() + { + cellSize = 1.f; + LUTSize = 0; + LUT = NULL; + indicesSize = 0; + indices = NULL; + } + ~Grid() + { + clear(); + } + + void init(float* PN, unsigned int PNSize, float sigma_s) + { + cellSize = sigma_s; + for (unsigned int i = 0; i < 3; i++) { + minMax[i] = PN[i]; + minMax[3 + i] = PN[i]; + } + for (unsigned int i = 0; i < PNSize; i++) + for (unsigned int j = 0; j < 3; j++) { + if (PN[6 * i + j] < minMax[j]) + minMax[j] = PN[6 * i + j]; + if (PN[6 * i + j] > minMax[3 + j]) + minMax[3 + j] = PN[6 * i + j]; + } + for (unsigned int i = 0; i < 3; i++) { + minMax[i] -= 0.001; + minMax[3 + i] += 0.001; + } + for (unsigned int i = 0; i < 3; i++) + res[i] = (unsigned int)ceil((minMax[3 + i] - minMax[i]) / cellSize); + LUTSize = res[0] * res[1] * res[2]; + unsigned int gridLUTNumOfByte = LUTSize * sizeof(unsigned int); + LUT = (unsigned int*)malloc(gridLUTNumOfByte); + memset(LUT, 0, gridLUTNumOfByte); + unsigned int nonEmptyCells = 0; + Vec3Df gMin(minMax[0], minMax[1], minMax[2]); + Vec3Df gMax(minMax[3], minMax[4], minMax[5]); + for (unsigned int i = 0; i < PNSize; i++) { + unsigned int index = getLUTIndex(Vec3Df(PN[6 * i], PN[6 * i + 1], PN[6 * i + 2])); + if (LUT[index] == 0) + nonEmptyCells++; + LUT[index]++; + } + indicesSize = PNSize + nonEmptyCells; + indices = (unsigned int*)malloc(indicesSize * sizeof(unsigned int)); + unsigned int cpt = 0; + for (unsigned int i = 0; i < res[0]; i++) + for (unsigned int j = 0; j < res[1]; j++) + for (unsigned int k = 0; k < res[2]; k++) { + unsigned int index = getLUTIndex(i, j, k); + if (LUT[index] != 0) { + indices[cpt] = LUT[index]; + LUT[index] = cpt; + cpt += indices[cpt] + 1; + indices[cpt - 1] = 0; // local iterator for subsequent filling + } + else + LUT[index] = 2 * PNSize; + } + for (unsigned int i = 0; i < PNSize; i++) { + Vec3Df p = Vec3Df(PN[6 * i], PN[6 * i + 1], PN[6 * i + 2]); + unsigned int indicesIndex = getLUTElement(p); + unsigned int totalCount = indices[indicesIndex]; + unsigned int countIndex = indicesIndex + totalCount; + unsigned int currentCount = indices[countIndex]; + if (currentCount < indices[indicesIndex]) + indices[countIndex]++; + unsigned int pIndex = indicesIndex + 1 + currentCount; + indices[pIndex] = i; + } + } + + void clear() + { + if (LUT != NULL) + free(LUT); + if (indices != NULL) + free(indices); + cellSize = 1.f; + LUTSize = 0; + LUT = NULL; + indicesSize = 0; + indices = NULL; + } + + // Accessors + + inline const float* getMinMax() const { return minMax; } + inline const unsigned int* getRes() const { return res; } + inline float getCellSize() const { return cellSize; } + inline unsigned int* getLUT() { return LUT; } + inline const unsigned int* getLUT() const { return LUT; } + inline unsigned int getLUTSize() const { return LUTSize; } + inline unsigned int getLUTIndex(unsigned int i, + unsigned int j, + unsigned int k) const + { + return k * res[0] * res[1] + j * res[0] + i; + } + inline unsigned int getLUTElement(unsigned int i, + unsigned int j, + unsigned int k) const + { + return LUT[getLUTIndex(i, j, k)]; + } + unsigned int getLUTIndex(const Vec3Df& x) const + { + Vec3Df p = (x - Vec3Df(minMax[0], minMax[1], minMax[2])) / cellSize; + for (unsigned int j = 0; j < 3; j++) { + p[j] = floor(p[j]); + if (p[j] < 0) + p[j] = 0.f; + if (p[j] >= res[j]) + p[j] = res[j] - 1; + } + unsigned index = ((unsigned int)floor(p[2])) * res[0] * res[1] + + ((unsigned int)floor(p[1])) * res[0] + + ((unsigned int)floor(p[0])); + return index; + } + inline unsigned int getLUTElement(const Vec3Df& x) const { + return LUT[getLUTIndex(x)]; + } + inline unsigned int* getIndices() { return indices; } + inline const unsigned int* getIndices() const { return indices; } + inline unsigned int getIndicesSize() const { return indicesSize; } + inline unsigned int getCellIndicesSize(unsigned int i, + unsigned int j, + unsigned int k) const { + return indices[getLUTElement(i, j, k)]; + } + inline unsigned int getIndicesElement(unsigned int i, + unsigned int j, + unsigned int k, + unsigned int e) const { + return indices[getLUTElement(i, j, k) + 1 + e]; + } + + private: + float minMax[6]; + float cellSize; + unsigned int res[3]; + unsigned int LUTSize; + unsigned int* LUT; // 3D Index Look-Up Table + unsigned int indicesSize; + unsigned int* indices; // 3D Grid data + }; + + + // -------------------------------------------------------------- + // Memory Managment + // -------------------------------------------------------------- + + void freeCPUMemory() + { + if (PN != NULL) + freeCPUResource(&PN); + PNSize = 0; + } + + // -------------------------------------------------------------- + // CPU Data + // -------------------------------------------------------------- + + float* PN; + unsigned int PNSize; + float PNScale; // size of the bounding sphere radius + float MLSRadius; + float bilateralRange; + bool bilateral; + bool hermite; + unsigned int numIter; + Grid grid; + }; + + } + } +} + +#endif //CGAL_TETRAHEDRAL_REMESHING_FMLS_H diff --git a/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/Vec3D.h b/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/Vec3D.h new file mode 100644 index 00000000000..00a42c8b527 --- /dev/null +++ b/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/Vec3D.h @@ -0,0 +1,376 @@ +// -------------------------------------------------------------------------- +// gMini, +// a minimal Glut/OpenGL app to extend +// +// Copyright(C) 2007-2009 +// Tamy Boubekeur +// +// All rights reserved. +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 2 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License (http://www.gnu.org/licenses/gpl.txt) +// for more details. +// +// -------------------------------------------------------------------------- + +#pragma once + +#include +#include + +template class Vec3D; + +template bool operator!= (const Vec3D & p1, const Vec3D & p2) { + return (p1[0] != p2[0] || p1[1] != p2[1] || p1[2] != p2[2]); +} + +template const Vec3D operator* (const Vec3D & p, double factor) { + return Vec3D (p[0] * factor, p[1] * factor, p[2] * factor); +} + +template const Vec3D operator* (double factor, const Vec3D & p) { + return Vec3D (p[0] * factor, p[1] * factor, p[2] * factor); +} + +template const Vec3D operator* (const Vec3D & p1, const Vec3D & p2) { + return Vec3D (p1[0] * p2[0], p1[1] * p2[1], p1[2] * p2[2]); +} + +template const Vec3D operator+ (const Vec3D & p1, const Vec3D & p2) { + return Vec3D (p1[0] + p2[0], p1[1] + p2[1], p1[2] + p2[2]); +} + +template const Vec3D operator- (const Vec3D & p1, const Vec3D & p2) { + return Vec3D (p1[0] - p2[0], p1[1] - p2[1], p1[2] - p2[2]); +} + +template const Vec3D operator- (const Vec3D & p) { + return Vec3D (-p[0], -p[1], -p[2]); +} + +template const Vec3D operator/ (const Vec3D & p, double divisor) { + return Vec3D (p[0]/divisor, p[1]/divisor, p[2]/divisor); +} + +template bool operator== (const Vec3D & p1, const Vec3D & p2) { + return (p1[0] == p2[0] && p1[1] == p2[1] && p1[2] == p2[2]); +} + +template bool operator< (const Vec3D & a, const Vec3D & b) { + return (a[0] < b[0] && a[1] < b[1] && a[2] < b[2]); +} + +template bool operator>= (const Vec3D & a, const Vec3D & b) { + return (a[0] >= b[0] || a[1] >= b[1] || a[2] >= b[2]); +} + +/** + * Vector in 3 dimensions, with basics operators overloaded. + */ +template +class Vec3D{ + public: + inline Vec3D (void) { + p[0] = p[1] = p[2] = T (); + } + inline Vec3D (T p0, T p1, T p2) { + p[0] = p0; + p[1] = p1; + p[2] = p2; + }; + inline Vec3D (const Vec3D & v) { + init (v[0], v[1], v[2]); + } + inline Vec3D (T* pp) { + p[0] = pp[0]; + p[1] = pp[1]; + p[2] = pp[2]; + }; + // --------- + // Operators + // --------- + // typedef Eigen::Matrix Vector3; + // + // inline operator Vector3() { // FIXME + // return Vector3(p[0], p[1], p[2]); + // } + inline operator T*() { + return p; + } + inline operator const T*() const { + return p; + } + inline T& operator[] (int Index) { + return (p[Index]); + }; + inline const T& operator[] (int Index) const { + return (p[Index]); + }; + inline Vec3D& operator= (const Vec3D & P) { + p[0] = P[0]; + p[1] = P[1]; + p[2] = P[2]; + return (*this); + }; + inline Vec3D& operator+= (const Vec3D & P) { + p[0] += P[0]; + p[1] += P[1]; + p[2] += P[2]; + return (*this); + }; + inline Vec3D& operator-= (const Vec3D & P) { + p[0] -= P[0]; + p[1] -= P[1]; + p[2] -= P[2]; + return (*this); + }; + inline Vec3D& operator*= (const Vec3D & P) { + p[0] *= P[0]; + p[1] *= P[1]; + p[2] *= P[2]; + return (*this); + }; + inline Vec3D& operator*= (T s) { + p[0] *= s; + p[1] *= s; + p[2] *= s; + return (*this); + }; + inline Vec3D& operator/= (const Vec3D & P) { + p[0] /= P[0]; + p[1] /= P[1]; + p[2] /= P[2]; + return (*this); + }; + inline Vec3D& operator/= (T s) { + p[0] /= s; + p[1] /= s; + p[2] /= s; + return (*this); + }; + + //--------------------------------------------------------------- + + inline Vec3D & init (T x, T y, T z) { + p[0] = x; + p[1] = y; + p[2] = z; + return (*this); + }; + inline T getSquaredLength() const { + return (dotProduct (*this, *this)); + }; + inline T getLength() const { + return (T)sqrt (getSquaredLength()); + }; + /// Return length after normalization + inline T normalize (void) { + T length = getLength(); + if (length == 0.0f) + return 0; + T rezLength = 1.0f / length; + p[0] *= rezLength; + p[1] *= rezLength; + p[2] *= rezLength; + return length; + }; + inline void fromTo (const Vec3D & P1, const Vec3D & P2) { + p[0] = P2[0] - P1[0]; + p[1] = P2[1] - P1[1]; + p[2] = P2[2] - P1[2]; + }; + inline double transProduct (const Vec3D & v) const { + return (p[0]*v[0] + p[1]*v[1] + p[2]*v[2]); + } + inline void getTwoOrthogonals (Vec3D & u, Vec3D & v) const { + if (fabs(p[0]) < fabs(p[1])) { + if (fabs(p[0]) < fabs(p[2])) + u = Vec3D (0, -p[2], p[1]); + else + u = Vec3D (-p[1], p[0], 0); + } else { + if (fabs(p[1]) < fabs(p[2])) + u = Vec3D (p[2], 0, -p[0]); + else + u = Vec3D(-p[1], p[0], 0); + } + v = crossProduct (*this, u); + } + inline Vec3D projectOn (const Vec3D & N, const Vec3D & P) const { + T w = dotProduct (((*this) - P), N); + return (*this) - (N * w); + } + static inline Vec3D segment (const Vec3D & a, const Vec3D & b) { + Vec3D r; + r[0] = b[0] - a[0]; + r[1] = b[1] - a[1]; + r[2] = b[2] - a[2]; + return r; + }; + static inline Vec3D crossProduct(const Vec3D & a, const Vec3D & b) { + Vec3D result; + result[0] = a[1] * b[2] - a[2] * b[1]; + result[1] = a[2] * b[0] - a[0] * b[2]; + result[2] = a[0] * b[1] - a[1] * b[0]; + return(result); + } + static inline void computeRepere(const Vec3D & n, const T& theta, Vec3D& x, Vec3D& y, Vec3D& z) + { + z = n; + x = z; + if(x[2] == 0) + { + x = Vec3D(0,0,1); + } + else if(x[1]==0) + { + x = Vec3D(1,0,0); + } + else + { + x[2] = -(x[0] + x[1])/x[2]; + x[0] = x[1] = 1; + } + y = Vec3D::crossProduct(z,x); + y.normalize(); + x = Vec3D::crossProduct(y,z); + x.normalize(); + + Vec3D xp = cos(theta)*x + sin(theta)*y, yp = cos(theta)*y - sin(theta)*x; + x = xp; + y = yp; + x.normalize(); + y.normalize(); + } + static inline T dotProduct(const Vec3D & a, const Vec3D & b) { + return (a[0] * b[0] + a[1] * b[1] + a[2] * b[2]); + } + static inline T squaredDistance (const Vec3D &v1, const Vec3D &v2) { + Vec3D tmp = v1 - v2; + return (tmp.getSquaredLength()); + } + static inline T distance (const Vec3D &v1, const Vec3D &v2) { + Vec3D tmp = v1 - v2; + return (tmp.getLength()); + } + static inline Vec3D interpolate (const Vec3D & u, const Vec3D & v, T alpha) { + return (u * (1.0f - alpha) + v * alpha); + } + static inline Vec3D rotate(const Vec3D & v, const Vec3D & axes, double theta = 0.0) { + double c = cos(theta), s = sin(theta); + const double &x = axes[0], &y = axes[1], &z = axes[2]; + double x2 = x*x, y2 = y*y, z2 = z*z; + return Vec3D((x2+(1-x2)*c)*v[0] + (x*y*(1-c)-z*s)*v[1] + (x*z*(1-c)+y*s)*v[2], + (x*y*(1-c)+z*s)*v[0] + (y2+(1-y2)*c)*v[1] + (y*z*(1-c)-x*s)*v[2], + (x*z*(1-c)-y*s)*v[0] + (y*z*(1-c)+x*s)*v[1] + (z2+(1-z2)*c)*v[2]); + } + static inline Vec3D changeReference(const Vec3D & v, const Vec3D & x, const Vec3D & y, const Vec3D & z) { + return Vec3D(dotProduct(v,x),dotProduct(v,y),dotProduct(v,z)); + } + static inline Vec3D changeReference(const Vec3D & v, const Vec3D & c, const Vec3D & x, const Vec3D & y, const Vec3D & z) { + Vec3D vn = v-c; + return Vec3D(dotProduct(vn,x),dotProduct(vn,y),dotProduct(vn,z)); + } + + + // cartesion to polar coordinates + // result: + // [0] = length + // [1] = angle with z-axis + // [2] = angle of projection into x,y, plane with x-axis + static inline Vec3D cartesianToPolar (const Vec3D &v) { + Vec3D polar; + polar[0] = v.getLength(); + if (v[2] > 0.0f) + polar[1] = (T) atan (sqrt (v[0] * v[0] + v[1] * v[1]) / v[2]); + else if (v[2] < 0.0f) + polar[1] = (T) atan (sqrt (v[0] * v[0] + v[1] * v[1]) / v[2]) + M_PI; + else + polar[1] = M_PI * 0.5f; + if (v[0] > 0.0f) + polar[2] = (T) atan (v[1] / v[0]); + else if (v[0] < 0.0f) + polar[2] = (T) atan (v[1] / v[0]) + M_PI; + else if (v[1] > 0) + polar[2] = M_PI * 0.5f; + else + polar[2] = -M_PI * 0.5; + return polar; + } + + // polar to cartesion coordinates + // input: + // [0] = length + // [1] = angle with z-axis + // [2] = angle of projection into x,y, plane with x-axis + static inline Vec3D polarToCartesian (const Vec3D & v) { + Vec3D cart; + cart[0] = v[0] * (T) sin (v[1]) * (T) cos (v[2]); + cart[1] = v[0] * (T) sin (v[1]) * (T) sin (v[2]); + cart[2] = v[0] * (T) cos (v[1]); + return cart; + } + static inline Vec3D projectOntoVector (const Vec3D & v1, const Vec3D & v2) { + return v2 * dotProduct (v1, v2); + } + inline Vec3D transformIn (const Vec3D & pos, const Vec3D & n, const Vec3D & u, const Vec3D & v) const { + Vec3D q = (*this) - pos; + return Vec3D (u[0]*q[0] + u[1]*q[1] + u[2]*q[2], + v[0]*q[0] + v[1]*q[1] + v[2]*q[2], + n[0]*q[0] + n[1]*q[1] + n[2]*q[2]); + } + + protected: + T p[3]; +}; + +template inline void swap (Vec3D & P, Vec3D & Q) { + Vec3D tmp = P; + P = Q; + Q = tmp; +} + +template std::ostream & operator<< (std::ostream & output, const Vec3D & v) { + output << v[0] << " " << v[1] << " " << v[2]; + return output; +} + +template void read (std::istream & input, Vec3D & v) { + float val[3]; + input.read((char*)val, 3*sizeof(float)); + v[0] = val[0]; + v[1] = val[1]; + v[2] = val[2]; +} + +template void write (std::ostream & output, const Vec3D & v) { + float val = v[0]; + output.write((char*)(&val), sizeof(float)); + val = v[1]; + output.write((char*)(&val), sizeof(float)); + val = v[2]; + output.write((char*)(&val), sizeof(float)); +} + +template std::istream & operator>> (std::istream & input, Vec3D & v) { + input >> v[0] >> v[1] >> v[2]; + return input; +} + +typedef Vec3D Vec3Dd; +typedef Vec3D Vec3Df; +typedef Vec3D Vec3Di; + +// Some Emacs-Hints -- please don't remove: +// +// Local Variables: +// mode:C++ +// tab-width:4 +// End: diff --git a/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/smooth_vertices.h b/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/smooth_vertices.h index fce72c88c9f..42ee5034bce 100644 --- a/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/smooth_vertices.h +++ b/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/smooth_vertices.h @@ -7,9 +7,13 @@ #include #include +#include +#include -#include +#include +#include +#include #include #include @@ -19,14 +23,82 @@ namespace Tetrahedral_remeshing { namespace internal { + template + std::pair + make_surface_index(const SubdomainIndex& s1, + const SubdomainIndex& s2) + { + if (s1 < s2) + return std::make_pair(s1, s2); + else + return std::make_pair(s2, s1); + } + template CGAL::Vector_3 project_on_tangent_plane(const CGAL::Point_3& gi, const CGAL::Point_3& pi, const CGAL::Vector_3& normal) { - typedef typename Gt::Vector_3 Vector_3; - Vector_3 diff = pi - gi; - return Vector_3(gi, gi + (normal * diff) * normal); + typename Gt::Construct_vector_3 + vec = Gt().construct_vector_3_object(); + typename Gt::Construct_scaled_vector_3 + scale = Gt().construct_scaled_vector_3_object(); + return scale(normal, CGAL::scalar_product(normal, vec(gi, pi))); + } + + template + typename C3t3::Triangulation::Geom_traits::Vector_3 + compute_vertex_normal(const typename C3t3::Vertex_handle v, + const C3t3& c3t3) + { + typedef typename C3t3::Subdomain_index Subdomain_index; + typedef typename C3t3::Triangulation::Facet Facet; + typedef typename C3t3::Triangulation::Cell_handle Cell_handle; + typedef typename C3t3::Triangulation::Geom_traits Gt; + typedef typename Gt::Vector_3 Vector_3; + typedef std::pair< Subdomain_index, Subdomain_index> Surface_index; + + typename Gt::Construct_opposite_vector_3 + opp = c3t3.triangulation().geom_traits().construct_opposite_vector_3_object(); + typename Gt::Construct_sum_of_vectors_3 + sum = c3t3.triangulation().geom_traits().construct_sum_of_vectors_3_object(); + typename Gt::Construct_scaled_vector_3 + scale = c3t3.triangulation().geom_traits().construct_scaled_vector_3_object(); + typename Gt::Compute_squared_length_3 + sqlen = c3t3.triangulation().geom_traits().compute_squared_length_3_object(); + + std::vector facets; + c3t3.triangulation().incident_facets(v, std::back_inserter(facets)); + + Vector_3 normal = CGAL::NULL_VECTOR; + + for (Facet f : facets) + { + Cell_handle ch = f.first; + Cell_handle n_ch = f.first->neighbor(f.second); + + Subdomain_index si = ch->subdomain_index(); + Subdomain_index si_mirror = n_ch->subdomain_index(); + + if (si != si_mirror + || c3t3.triangulation().is_infinite(ch) + || c3t3.triangulation().is_infinite(n_ch)) + { + Surface_index surf_i = make_surface_index(si, si_mirror); + + Vector_3 n = facet_normal(c3t3.triangulation(), f); + + if (si < si_mirror || c3t3.triangulation().is_infinite(ch)) + n = opp(n); + + normal = sum(normal, n); + } + } + + if (normal != CGAL::NULL_VECTOR) + return scale(normal, 1. / CGAL::sqrt(sqlen(normal))); + else + return CGAL::NULL_VECTOR; } template @@ -37,9 +109,9 @@ namespace internal typedef typename C3t3::Cell_handle Cell_handle; typedef typename C3t3::Vertex_handle Vertex_handle; typedef typename C3t3::Subdomain_index Subdomain_index; - typedef typename C3t3::Surface_patch_index Surface_patch_index; typedef typename Tr::Finite_facets_iterator Finite_facets_iterator; - typedef typename Tr::Gt::Vector_3 Vector_3; + typedef typename Tr::Geom_traits::Vector_3 Vector_3; + typedef std::pair Surface_index; const Tr& tr = c3t3.triangulation(); @@ -54,7 +126,7 @@ namespace internal if (si != si_mirror || tr.is_infinite(ch) || tr.is_infinite(n_ch)) { - Surface_patch_index surf_i = make_surface_patch_index(si, si_mirror); + Surface_index surf_i = make_surface_index(si, si_mirror); for (int i = 0; i < 3; ++i) { Vertex_handle v_id = fit->first->vertex(indices(fit->second ,i)); @@ -74,9 +146,9 @@ namespace internal if (si != si_mirror || tr.is_infinite(ch) || tr.is_infinite(n_ch)) { - Surface_patch_index surf_i = make_surface_patch_index(si, si_mirror); + Surface_index surf_i = make_surface_index(si, si_mirror); - Vector_3 n = CGAL::normal(*fit, tr.geom_traits()); + Vector_3 n = CGAL::Tetrahedral_remeshing::facet_normal(tr, *fit); if (si < si_mirror || tr.is_infinite(ch)) n = -1.*n; @@ -93,9 +165,9 @@ namespace internal for (typename VertexNormalsMap::iterator vnm_it = normals_map.begin(); vnm_it != normals_map.end(); ++vnm_it) { - //value type is map - for (typename VertexNormalsMap::value_type::iterator it = vnm_it->begin(); - it != vnm_it->end(); ++it) + //mapped_type is map + for (typename VertexNormalsMap::mapped_type::iterator it = vnm_it->second.begin(); + it != vnm_it->second.end(); ++it) { Vector_3& n = it->second; n = n / CGAL::sqrt(n*n); @@ -104,51 +176,274 @@ namespace internal } - template - bool project(const SurfacePatchIndex& /* si */, - CGAL::Vector_3& gi, - CGAL::Vector_3& projected_point) + template + std::pair + surface_index(const typename C3t3::Vertex_handle v, const C3t3& c3t3) { -// if (subdomain_FMLS_indices.find(si) == subdomain_FMLS_indices.end()) -// return false; - typedef typename Gt::Vector_3 Vector_3; - typedef typename Gt::Point_3 Point_3; + typedef typename C3t3::Triangulation::Facet Facet; + typedef typename C3t3::Triangulation::Cell_handle Cell_handle; + typedef typename C3t3::Subdomain_index Subdomain_index; - if (std::isnan(gi.x()) || std::isnan(gi.y()) || isnan(gi.z())) + std::vector facets; + c3t3.triangulation().incident_facets(v, std::back_inserter(facets)); + + for (Facet f : facets) { - std::cout << "Initial point error " << gi << std::endl; - return false; + Cell_handle ch = f.first; + Cell_handle n_ch = f.first->neighbor(f.second); + + Subdomain_index si = ch->subdomain_index(); + Subdomain_index si_mirror = n_ch->subdomain_index(); + + if (si != si_mirror + || c3t3.triangulation().is_infinite(ch) + || c3t3.triangulation().is_infinite(n_ch)) + { + return make_surface_index(si, si_mirror); + } + } + CGAL_assertion(false); + return make_surface_index(0, 0); + } + + template + const boost::unordered_set + subdomain_indices(const typename C3t3::Vertex_handle v, const C3t3& c3t3) + { + typedef typename C3t3::Triangulation::Cell_handle Cell_handle; + + std::vector cells; + c3t3.triangulation().incident_cells(v, std::back_inserter(cells)); + + boost::unordered_set res; + for (Cell_handle c : cells) + { + if (c3t3.is_in_complex(c)) + res.insert(c->subdomain_index()); + } + return res; + } + + template + void createMLSSurfaces(const C3t3& c3t3, + FMLSVector& subdomain_FMLS, + SurfaceIndexMap& subdomain_FMLS_indices) + { + typedef typename C3t3::Subdomain_index Subdomain_index; + typedef typename C3t3::Triangulation Tr; + typedef typename Tr::Geom_traits Gt; + typedef typename Tr::Edge Edge; + typedef typename Tr::Vertex_handle Vertex_handle; + typedef typename Gt::Point_3 Point_3; + typedef typename Gt::Vector_3 Vector_3; + + typedef std::pair Surface_index; + + const Tr& tr = c3t3.triangulation(); + + SurfaceIndexMap current_subdomain_FMLS_indices; + + SurfaceIndexMap subdomain_sample_numbers; + + //Count the number of vertices for each boundary surface (i.e. one per label) + for (typename Tr::Finite_vertices_iterator vit = tr.finite_vertices_begin(); + vit != tr.finite_vertices_end(); ++vit) + { + if (c3t3.in_dimension(vit) == 2) + { + const boost::unordered_set& v_subdomain_indices = subdomain_indices(vit, c3t3); + if (v_subdomain_indices.size() == 2) + { + boost::unordered_set::const_iterator si_it = v_subdomain_indices.cbegin(); + Subdomain_index s1 = *si_it; + ++si_it; + Subdomain_index s2 = *si_it; + + subdomain_sample_numbers[make_surface_index(s1, s2)]++; + } + } } + std::vector< float* > pns; + + int count = 0; + //Memory allocation for the point plus normals of the point samples + for (typename SurfaceIndexMap::iterator it = subdomain_sample_numbers.begin(); + it != subdomain_sample_numbers.end(); ++it) + { + current_subdomain_FMLS_indices[it->first] = count; + pns.push_back(new float[it->second * 6]); + count++; + } + + boost::unordered_map > vertices_normals; + compute_vertices_normals(c3t3, vertices_normals); + + std::vector current_v_count(count, 0); + std::vector point_spacing(count, 0); + std::vector point_spacing_count(count, 0); + + //Allocation of the PN + for (typename Tr::Finite_vertices_iterator vit = tr.finite_vertices_begin(); + vit != tr.finite_vertices_end(); ++vit) + { + boost::unordered_set vertices_subdomain_indices + = subdomain_indices(vit, c3t3); + if (vertices_subdomain_indices.size() == 2) + { + Subdomain_index s1 = *(vertices_subdomain_indices.begin()); + Subdomain_index s2 = *(++vertices_subdomain_indices.begin()); + + Surface_index surf_i = make_surface_index(s1, s2); + + int fmls_id = current_subdomain_FMLS_indices[surf_i]; + + Point_3& point = vit->point(); + + pns[fmls_id][6 * current_v_count[fmls_id]] = point.x(); + pns[fmls_id][6 * current_v_count[fmls_id] + 1] = point.y(); + pns[fmls_id][6 * current_v_count[fmls_id] + 2] = point.z(); + + Vector_3& normal = vertices_normals[vit][surf_i]; + + pns[fmls_id][6 * current_v_count[fmls_id] + 3] = normal.x(); + pns[fmls_id][6 * current_v_count[fmls_id] + 4] = normal.y(); + pns[fmls_id][6 * current_v_count[fmls_id] + 5] = normal.z(); + + current_v_count[fmls_id]++; + } + } + + typedef std::pair Edge_VV; + typedef std::map EdgeMapIndex; + EdgeMapIndex edgeMap; + + for (typename C3t3::Facet_iterator fit = c3t3.facets_begin(); + fit != c3t3.facets_end(); ++fit) + { + for (int i = 0; i < 2; i++) + { + for (int j = i + 1; j < 3; j++) + { + Edge edge(fit->first, indices(fit->second, i), indices(fit->second, j)); + + Vertex_handle vh0 = edge.first->vertex(edge.second); + Vertex_handle vh1 = edge.first->vertex(edge.third); + Edge_VV evv = make_vertex_pair(vh1, vh0); + + if ( subdomain_indices(vh0, c3t3).size() == 2 + && subdomain_indices(vh1, c3t3).size() == 2 + && edgeMap.find(evv) == edgeMap.end()) + { + edgeMap[evv] = 0; + Surface_index surf_i = make_surface_index( + fit->first->subdomain_index(), + fit->first->neighbor(fit->second)->subdomain_index()); + int fmls_id = current_subdomain_FMLS_indices[surf_i]; + + point_spacing[fmls_id] += CGAL::sqrt(tr.segment(edge).squared_length()); + point_spacing_count[fmls_id] ++; + } + } + } + } + + int nb_of_mls_to_create = 0; + double average_point_spacing = 0; + + //Cretaing the actual MLS surfaces + for (SurfaceIndexMap::iterator it = current_subdomain_FMLS_indices.begin(); + it != current_subdomain_FMLS_indices.end(); ++it) + { + if (current_v_count[it->second] > 3) + { + nb_of_mls_to_create++; + + double current_point_spacing = point_spacing[it->second] / point_spacing_count[it->second]; + point_spacing[it->second] = current_point_spacing; + + average_point_spacing += current_point_spacing; + } + } + + average_point_spacing = average_point_spacing / nb_of_mls_to_create; + + subdomain_FMLS.resize(nb_of_mls_to_create, FMLS()); + + count = 0; + //Cretaing the actual MLS surfaces + for (SurfaceIndexMap::iterator it = current_subdomain_FMLS_indices.begin(); + it != current_subdomain_FMLS_indices.end(); ++it) + { + if (current_v_count[it->second] > 3) + { + double current_point_spacing = point_spacing[it->second]; + + //subdomain_FMLS[count].toggleHermite(true); + subdomain_FMLS[count].setPN(pns[it->second], current_v_count[it->second], current_point_spacing); + // subdomain_FMLS[count].toggleHermite(true); + subdomain_FMLS_indices[it->first] = count; + + count++; + } + else { + std::cout << "Problem of number for MLS : " << current_v_count[it->second] << std::endl; + } + } + } + + template + bool project(const typename C3t3& c3t3, + const typename C3t3::Vertex_handle& v, + typename C3t3::Triangulation::Geom_traits::Vector_3& gi, + typename C3t3::Triangulation::Geom_traits::Vector_3& projected_point, + FMLSVector& subdomain_FMLS, + SurfaceIndexMap& subdomain_FMLS_indices) + { + typedef typename C3t3::Triangulation::Geom_traits::Point_3 Point_3; + typedef typename C3t3::Triangulation::Geom_traits::Vector_3 Vector_3; + typedef typename C3t3::Subdomain_index Subdomain_index; + + std::pair si = surface_index(v, c3t3); + + if (subdomain_FMLS_indices.find(si) == subdomain_FMLS_indices.end()) + return false; + + Point_3 point(gi.x(), gi.y(), gi.z()); + Vector_3 res_normal; - Point_3 point; - Point_3 result = CGAL::ORIGIN + gi; + Point_3 result(point); - //FMLS& fmls = subdomain_FMLS[subdomain_FMLS_indices[si]]; + FMLS& fmls = subdomain_FMLS[subdomain_FMLS_indices[si]]; - // int it_nb = 0; - // const int max_it_nb = 5; - //const float epsilon = fmls.getPNScale() / 1000.; + int it_nb = 0; - //do - //{ - // point = result; + float epsilon = fmls.getPNScale() / 1000.; + float sq_eps = epsilon * epsilon; - // //fmls.fastProjectionCPU(point, result, res_normal); + do + { + point = result; - // if (std::isnan(result[0]) || std::isnan(result[1]) || std::isnan(result[2])){ - // std::cout << "MLS error detected si size " << si.first << " - " << si.second - // << " : " << fmls.getPNSize() << std::endl; - // return false; - // } + fmls.fastProjectionCPU(point, result, res_normal); - //} while ((result - point).getLength() > epsilon && ++it_nb < max_it_nb); + if (std::isnan(result[0]) || std::isnan(result[1]) || std::isnan(result[2])) { + std::cout << "MLS error detected si size " << si.first << " - " << si.second + << " : " << fmls.getPNSize() << std::endl; + return false; + } - projected_point = Vector_3(result.x(), result.y(), result.z()); + it_nb++; + + } while (CGAL::squared_distance(result, point) > sq_eps && it_nb < 5); + + projected_point = Vector_3(result[0], result[1], result[2]); return true; } + template bool check_inversion_and_move(const typename Tr::Vertex_handle v, const CGAL::Vector_3& move, @@ -177,6 +472,52 @@ namespace internal return true; } + template + bool project(const C3t3& c3t3, + const typename C3t3::Vertex_handle v, + typename C3t3::Triangulation::Geom_traits::Vector_3& gi, + typename C3t3::Triangulation::Geom_traits::Vector_3& projected_point ) + { + typedef typename C3t3::Subdomain_index Subdomain_index; + + const std::pair si = surface_index(v); + if( subdomain_FMLS_indices.find( si ) == subdomain_FMLS_indices.end() ) + return false; + + Vec3Df point( gi.x(), gi.y(), gi.z() ); + if( isnan(point[0]) || isnan(point[1]) || isnan(point[2]) ){ + std::cout << "Initial point error " << point << std::endl; + return false; + } + + Vec3Df res_normal; + Vec3Df result(point); + + FMLS & fmls = subdomain_FMLS[ subdomain_FMLS_indices[ si ] ]; + + int it_nb = 0; + + float epsilon = fmls.getPNScale() /1000.; + + do{ + point = result; + + fmls.fastProjectionCPU( point, result, res_normal ); + + if( isnan(result[0]) || isnan(result[1]) || isnan(result[2]) ){ + std::cout << "MLS error detected si size " << si.first << " - " << si.second << " : " << fmls.getPNSize() << std::endl; + return false; + } + + it_nb++; + + }while ( (result - point).getLength() > epsilon && it_nb < 5 ); + + projected_point = K::Vector_3( result[0], result[1], result[2] ); + + return true; +} + template typename C3T3::Triangulation::Geom_traits::Vector_3 move_3d(typename C3T3::Vertex_handle v, const C3T3& c3t3) @@ -220,13 +561,16 @@ namespace internal const C3T3& c3t3, const typename C3T3::Subdomain_index& imaginary_index) { - typedef typename C3T3::Edge Edge; - typedef typename C3T3::Vertex_handle Vertex_handle; + typedef typename C3T3::Subdomain_index Subdomain_index; + typedef typename C3T3::Edge Edge; + typedef typename C3T3::Vertex_handle Vertex_handle; typedef typename C3T3::Triangulation::Geom_traits Gt; - typedef typename Gt::Vector_3 Vector_3; + typedef typename Gt::Vector_3 Vector_3; + typedef typename Gt::Point_3 Point_3; const Gt& gt = c3t3.triangulation().geom_traits(); + const Point_3& pos = point(v->point()); Vector_3 move = CGAL::NULL_VECTOR; std::vector edges; @@ -243,7 +587,7 @@ namespace internal std::size_t nbe = 0; BOOST_FOREACH(Edge e, edges) { - if (is_on_domain_hull(e, c3t3, imaginary_index)) +// if (is_on_domain_hull(e, c3t3, imaginary_index)) { Vertex_handle ve = (e.first->vertex(e.second) != v) ? e.first->vertex(e.second) @@ -253,11 +597,33 @@ namespace internal } } + typedef std::pair Surface_index; + typedef std::map SurfaceIndexMap; + SurfaceIndexMap subdomain_FMLS_indices; + std::vector< FMLS > subdomain_FMLS; + createMLSSurfaces(c3t3, subdomain_FMLS, subdomain_FMLS_indices); + if (nbe > 0) { typename Gt::Construct_scaled_vector_3 scale = gt.construct_scaled_vector_3_object(); - return scale(move, 1. / nbe); + move = scale(move, 1. / nbe); + + Vector_3 normal = compute_vertex_normal(v, c3t3); + + Vector_3 normal_projection = project_on_tangent_plane( + pos + move, //smoothed position + pos, //current position + normal); + + Vector_3 mls_projection; + if (project(c3t3, v, normal_projection, mls_projection, + subdomain_FMLS, subdomain_FMLS_indices)) + move = move + mls_projection; + else + move = move + normal_projection; + + return move; } else return CGAL::NULL_VECTOR; @@ -316,7 +682,7 @@ namespace internal template void smooth_vertices_new(C3T3& c3t3, const typename C3T3::Subdomain_index& imaginary_index, - const bool /*protect_boundaries*/, + const bool protect_boundaries, CellSelector cell_selector) { typedef typename C3T3::Triangulation Tr; @@ -370,6 +736,9 @@ namespace internal break; case 2: + if (protect_boundaries) + break; + smoothing_vecs[vertex_id.at(vit)] = move_2d(vit, c3t3, imaginary_index); #ifdef CGAL_TETRAHEDRAL_REMESHING_DEBUG if (smoothing_vecs[vertex_id.at(vit)] != CGAL::NULL_VECTOR) @@ -379,6 +748,9 @@ namespace internal break; case 1: + if (protect_boundaries) + break; + smoothing_vecs[vertex_id.at(vit)] = move_1d(vit, c3t3, imaginary_index); #ifdef CGAL_TETRAHEDRAL_REMESHING_DEBUG if (smoothing_vecs[vertex_id.at(vit)] != CGAL::NULL_VECTOR) @@ -420,393 +792,6 @@ namespace internal #endif } -// template -// void smooth_vertices(C3T3& c3t3, -// const typename C3T3::Subdomain_index&, -// const bool protect_boundaries, -// CellSelector cell_selector) -// { -// typedef typename C3T3::Surface_patch_index Surface_patch_index; -// typedef typename C3T3::Subdomain_index Subdomain_index; -// typedef typename C3T3::Triangulation Tr; -// typedef typename C3T3::Vertex_handle Vertex_handle; -// typedef typename C3T3::Cell_handle Cell_handle; -// typedef typename Tr::Finite_vertices_iterator Finite_vertices_iterator; -// typedef typename Tr::Finite_edges_iterator Finite_edges_iterator; -// -// typedef typename Tr::Geom_traits Gt; -// typedef typename Gt::Point_3 Point_3; -// typedef typename Gt::Vector_3 Vector_3; -// typedef typename Gt::FT FT; -// -//#ifdef CGAL_TETRAHEDRAL_REMESHING_VERBOSE -// std::cout << "Smooth vertices..."; -// std::cout.flush(); -// std::size_t nb_done = 0; -//#endif -// -// Tr& tr = c3t3.triangulation(); -// -// const std::size_t nbv = tr.number_of_vertices(); -// boost::unordered_map vertex_id; -// std::vector smoothing_vecs(nbv, CGAL::NULL_VECTOR); -// std::vector neighbors(nbv, -1); -// -// //collect ids -// std::size_t id = 0; -// for (Finite_vertices_iterator vit = tr.finite_vertices_begin(); -// vit != tr.finite_vertices_end(); ++vit) -// { -// vertex_id[vit] = id++; -// } -// -// if (!protect_boundaries) -// { -// for (Finite_edges_iterator eit = tr.finite_edges_begin(); -// eit != tr.finite_edges_end(); ++eit) -// { -// const Vertex_handle vh0 = eit->first->vertex(eit->second); -// const Vertex_handle vh1 = eit->first->vertex(eit->third); -// -// const std::size_t& i0 = vertex_id.at(vh0); -// const std::size_t& i1 = vertex_id.at(vh1); -// -// if (/*toRemesh != REMESH_IMAGINARY &&*/ c3t3.is_in_complex(*eit)) -// { -// if (!is_feature(vh0, c3t3)) -// neighbors[i0] = std::max(0, neighbors[i0]); -// if (!is_feature(vh1, c3t3)) -// neighbors[i1] = std::max(0, neighbors[i1]); -// -// bool update_v0 = false, update_v1 = false; -// -// helpers::get_edge_info(*eit, update_v0, update_v1, c3t3, cell_selector); -// if (update_v0) -// { -// const Point_3& p1 = vh1->point(); -// smoothing_vecs[i0] = smoothing_vecs[i0] + Vector_3(p1.x(), p1.y(), p1.z()); -// neighbors[i0]++; -// } -// if (update_v1) -// { -// const Point_3& p0 = vh0->point(); -// smoothing_vecs[i1] = smoothing_vecs[i1] + Vector_3(p0.x(), p0.y(), p0.z()); -// neighbors[i1]++; -// } -// } -// } -// -// //collect a map of vertices subdomain indices -// boost::unordered_map > vertices_subdomain_indices; -// for (typename C3T3::Cell_iterator cit = c3t3.cells_in_complex_begin(); -// cit != c3t3.cells_in_complex_end(); ++cit) -// { -// for (int i = 0; i < 4; ++i) -// { -// Vertex_handle vi = cit->vertex(i); -// Subdomain_index si = cit->subdomain_index(); -// -// if (vertices_subdomain_indices.find(vi) == vertices_subdomain_indices.end()) -// { -// std::vector indices(1); -// indices[0] = si; -// vertices_subdomain_indices.insert(std::make_pair(vi, indices)); -// } -// else -// { -// std::vector& v_indices = vertices_subdomain_indices.at(vi); -// if (std::find(v_indices.begin(), v_indices.end(), si) == v_indices.end()) -// v_indices.push_back(si); -// } -// } -// } -// -// //collect a map of vertices surface indices -// boost::unordered_map > vertices_surface_indices; -// for(typename C3T3::Facet_iterator fit = c3t3.facets_in_complex_begin(); -// fit != c3t3.facets_in_complex_end(); ++fit) -// { -// Surface_patch_index surface_index -// = helpers::make_surface_patch_index(fit->first->subdomain_index(), -// fit->first->neighbor(fit->second)->subdomain_index()); -// for (int i = 0; i < 3; ++i) -// { -// Vertex_handle vi = fit->first->vertex(indices(fit->second, i)); -// if (vertices_subdomain_indices.at(vi).size() > 2) -// { -// if (vertices_surface_indices.find(vi) == vertices_surface_indices.end()) -// { -// std::vector indices(1); -// indices[0] = surface_index; -// vertices_surface_indices.insert(std::make_pair(vi, indices)); -// } -// else -// { -// std::vector& v_surface_indices = vertices_surface_indices.at(vi); -// if (std::find(v_surface_indices.begin(), v_surface_indices.end(), surface_index) -// == v_surface_indices.end()) -// v_surface_indices.push_back(surface_index); -// } -// } -// } -// } -// -// //collect a map of normals at surface vertices -// boost::unordered_map > vertices_normals; -// for (Finite_vertices_iterator vit = tr.finite_vertices_begin(); -// vit != tr.finite_vertices_end(); ++vit) -// { -// const std::size_t& vid = vertex_id.at(vit); -// if (neighbors[vid] > 1) -// { -// Point_3 smoothed_position = CGAL::ORIGIN + smoothing_vecs[vid] / neighbors[vid]; -// Vector_3 final_move = CGAL::NULL_VECTOR; -// Point_3 final_position; -// -// std::size_t count = 0; -// Point_3 current_pos = vit->point(); -// -// const std::vector& v_surface_indices = vertices_surface_indices[vit]; -// for (std::size_t i = 0; i < v_surface_indices.size(); ++i) -// { -// const Surface_patch_index& si = v_surface_indices[i]; -// -// Vector_3 normal_projection -// = project_on_tangent_plane(smoothed_position, current_pos, vertices_normals[vit][si]); -// -// //Check if the mls surface exists to avoid degenrated cases -// Vector_3 mls_projection; -// if (project(si, normal_projection, mls_projection)){ -// final_move = final_move + mls_projection; -// } -// else { -// final_move = final_move + normal_projection; -// } -// count++; -// } -// -// if (count > 0) -// final_position = CGAL::ORIGIN + final_move / static_cast(count); -// else -// final_position = smoothed_position; -// -// // move vertex -// vit->set_point(final_position); -// -// } -// else if (neighbors[vid] > 0) -// { -// Vector_3 final_move = CGAL::NULL_VECTOR; -// Point_3 final_position; -// -// int count = 0; -// Vector_3 current_move(CGAL::ORIGIN, vit->point()); -// -// const std::vector& v_surface_indices = vertices_surface_indices[vit]; -// for (std::size_t i = 0; i < v_surface_indices.size(); ++i) -// { -// Surface_patch_index si = v_surface_indices[i]; -// //Check if the mls surface exists to avoid degenrated cases -// -// Vector_3 mls_projection; -// if (project(si, current_move, mls_projection)){ -// final_move = final_move + mls_projection; -// } -// else { -// final_move = final_move + current_move; -// } -// count++; -// } -// -// if (count > 0) -// final_position = CGAL::ORIGIN + final_move / count; -// else -// final_position = CGAL::ORIGIN + current_move; -// -// // move vertex -// vit->set_point(final_position); -// } -// } -// -// smoothing_vecs.clear(); -// smoothing_vecs.resize(nbv, CGAL::NULL_VECTOR); -// -// neighbors.clear(); -// neighbors.resize(nbv, -1); -// -// for (Finite_edges_iterator eit = tr.finite_edges_begin(); -// eit != tr.finite_edges_end(); ++eit) -// { -// const Vertex_handle vh0 = eit->first->vertex(eit->second); -// const Vertex_handle vh1 = eit->first->vertex(eit->third); -// -// const std::size_t& i0 = vertex_id.at(vh0); -// const std::size_t& i1 = vertex_id.at(vh1); -// -// if ((/*toRemesh != REMESH_IN_COMPLEX &&*/ is_on_hull(*eit, c3t3)) -// || (/*toRemesh != REMESH_IMAGINARY &&*/ -// helpers::is_boundary(c3t3, *eit, cell_selector) && !c3t3.is_in_complex(*eit))) -// { -// bool update_v0 = false, update_v1 = false; -// if (!is_feature(vh0, c3t3)) -// neighbors[i0] = (std::max)(0, neighbors[i0]); -// if (!is_feature(vh1, c3t3)) -// neighbors[i1] = (std::max)(0, neighbors[i1]); -// -// helpers::get_edge_info(*eit, update_v0, update_v1, c3t3, cell_selector); -// if (update_v0) -// { -// const Point_3& p1 = vh1->point(); -// smoothing_vecs[i0] = smoothing_vecs[i0] + Vector_3(p1.x(), p1.y(), p1.z()); -// neighbors[i0]++; -// } -// if (update_v1) -// { -// const Point_3& p0 = vh0->point(); -// smoothing_vecs[i1] = smoothing_vecs[i1] + Vector_3(p0.x(), p0.y(), p0.z()); -// neighbors[i1]++; -// } -// } -// } -// -// for (Finite_vertices_iterator vit = tr.finite_vertices_begin(); -// vit != tr.finite_vertices_end(); ++vit) -// { -// const std::size_t& vid = vertex_id.at(vit); -// -// if (neighbors[vid] > 1) -// { -// Point_3 smoothed_position = CGAL::ORIGIN + smoothing_vecs[vid] / neighbors[vid]; -// Point_3 current_pos = vit->point(); -// Point_3 final_position = CGAL::ORIGIN; -// -// if (vit->in_dimension() == 3 && is_on_hull(vit, c3t3)) -// { -// Vector_3 final_move = project_on_tangent_plane( -// smoothed_position, current_pos, vertices_normals[vit][Surface_patch_index()]); -// final_position = CGAL::ORIGIN + final_move; -// } -// else { -// // Surface_patch_index si = helpers::make_surface_patch_index( -// // vertices_subdomain_indices[vit][0], vertices_subdomain_indices[vit][1]); -// -// // Vector_3 normal_projection = project_on_tangent_plane(smoothed_position, -// // current_pos, -// // vertices_normals[vit][si]); -// //Vector_3 mls_projection; -// //if (project(si, normal_projection, mls_projection) /*|| project( si, smoothed_position, mls_projection )*/){ -// // final_position = mls_projection; -// // //final_position = smoothed_position; -// //} -// //else { -// final_position = smoothed_position; -// //} -// // std::cout << "MLS " << final_position[0] << " - " << final_position[1] << " : " << final_position[2] << std::endl; -// } -// /* -// Normal_iterator it = vertices_normals[vit->info()].end(); -// it--; -// final_position = final_position + projectOnTangentPlane( smoothed_position, current_pos , it->second ); -// */ -// -// vit->set_point(final_position); -// } -// else if (neighbors[vid] > 0) -// { -// if (vit->in_dimension() == 2) -// { -// // Surface_patch_index si = helpers::make_surface_patch_index( -// // vertices_subdomain_indices[vit][0], -// // vertices_subdomain_indices[vit][1]); -// -// Vector_3 current_pos(CGAL::ORIGIN, vit->point()); -// Vector_3 mls_projection; -//// if (project(si, current_pos, mls_projection) /*|| project( si, smoothed_position, mls_projection )*/){ -//// vit->set_point(Point_3(mls_projection.x(), mls_projection.y(), mls_projection.z())); -//// } -// } -// } -// } -// } -// smoothing_vecs.clear(); -// smoothing_vecs.resize(nbv, CGAL::NULL_VECTOR); -// -// neighbors.clear(); -// neighbors.resize(nbv, 0); -// -// for (Finite_edges_iterator eit = tr.finite_edges_begin(); -// eit != tr.finite_edges_end(); ++eit) -// { -// //bool in_complex = c3t3.is_in_complex(*eit); -// //if ( toRemesh == REMESH_ALL -// // || (toRemesh == REMESH_IN_COMPLEX && in_complex) -// // || (toRemesh == REMESH_IMAGINARY && !in_complex)) -// { -// const Vertex_handle vh0 = eit->first->vertex(eit->second); -// const Vertex_handle vh1 = eit->first->vertex(eit->third); -// -// const std::size_t& i0 = vertex_id.at(vh0); -// const std::size_t& i1 = vertex_id.at(vh1); -// -// if (c3t3.in_dimension(vh0) == 3 && !is_on_hull(vh0, c3t3)) -// { -// const Point_3& p1 = vh1->point(); -// smoothing_vecs[i0] = smoothing_vecs[i0] + Vector_3(CGAL::ORIGIN, p1); -// neighbors[i0]++; -// } -// if (c3t3.in_dimension(vh1) == 3 && !is_on_hull(vh1, c3t3)) -// { -// const Point_3& p0 = vh0->point(); -// smoothing_vecs[i1] = smoothing_vecs[i1] + Vector_3(CGAL::ORIGIN, p0); -// neighbors[i1]++; -// } -// } -// } -// -// for (Finite_vertices_iterator vit = tr.finite_vertices_begin(); -// vit != tr.finite_vertices_end(); ++vit) -// { -// const std::size_t& vid = vertex_id.at(vit); -// if (neighbors[vid] > 1) -// { -// if (smoothing_vecs[vid] != CGAL::NULL_VECTOR) -// { -//#ifdef CGAL_TETRAHEDRAL_REMESHING_VERBOSE -// ++nb_done; -//#endif -// Point_3 new_pos = CGAL::ORIGIN + smoothing_vecs[vid] / neighbors[vid]; -// const Vector_3 move(vit->point(), new_pos); -// -// std::vector cells; -// tr.finite_incident_cells(vit, std::back_inserter(cells)); -// -// bool selected = true; -// for (std::size_t i = 0; i < cells.size(); ++i) -// { -// if (!cell_selector(cells[i])) -// { -// selected = false; -// break; -// } -// } -// if (!selected) -// continue; -// -// double frac = 1.; -// while (frac > 0.05 /// 1/16 = 0.0625 -// && !check_inversion_and_move(vit, frac * move, cells)) -// { -// frac = 0.5 * frac; -// } -// } -// } -// } -// -//#ifdef CGAL_TETRAHEDRAL_REMESHING_VERBOSE -// std::cout << " done (" << nb_done << " vertices smoothed)." << std::endl; -//#endif -// } }//namespace internal }//namespace Tetrahedral_adaptive_remeshing diff --git a/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/tetrahedral_remeshing_helpers.h b/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/tetrahedral_remeshing_helpers.h index aab9182c0d9..175bc7a70e6 100644 --- a/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/tetrahedral_remeshing_helpers.h +++ b/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/tetrahedral_remeshing_helpers.h @@ -137,6 +137,18 @@ namespace Tetrahedral_remeshing point(c->vertex(3)->point())); } + template + typename Tr::Geom_traits::Vector_3 facet_normal(const Tr& tr, + const typename Tr::Facet& f) + { + const typename Tr::Geom_traits gt = tr.geom_traits(); + typename Tr::Geom_traits::Construct_normal_3 cn + = gt.construct_normal_3_object(); + return cn(point(f.first->vertex((f.second + 1) % 4)->point()), + point(f.first->vertex((f.second + 2) % 4)->point()), + point(f.first->vertex((f.second + 3) % 4)->point())); + } + template std::pair make_vertex_pair(const Vh v1, const Vh v2) { diff --git a/Tetrahedral_remeshing/include/CGAL/tetrahedral_remeshing.h b/Tetrahedral_remeshing/include/CGAL/tetrahedral_remeshing.h index d290f8cb2ce..e3a6b172186 100644 --- a/Tetrahedral_remeshing/include/CGAL/tetrahedral_remeshing.h +++ b/Tetrahedral_remeshing/include/CGAL/tetrahedral_remeshing.h @@ -234,8 +234,8 @@ namespace CGAL std::size_t nb_extra_iterations = 3; while (it_nb++ < max_it + nb_extra_iterations) { - remesher.flip(); - remesher.smooth(); +// remesher.flip(); +// remesher.smooth(); #ifdef CGAL_TETRAHEDRAL_REMESHING_VERBOSE std::cout << "# Iteration " << it_nb << " (flip and smooth only) done : " From 2a8335b60bbb7baeba6fb977cb045bd885dc3a14 Mon Sep 17 00:00:00 2001 From: Jane Tournois Date: Fri, 17 Jan 2020 10:39:44 +0100 Subject: [PATCH 053/568] wip smoothing --- .../internal/smooth_vertices.h | 45 +++++++++++-------- 1 file changed, 27 insertions(+), 18 deletions(-) diff --git a/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/smooth_vertices.h b/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/smooth_vertices.h index 42ee5034bce..4c435066988 100644 --- a/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/smooth_vertices.h +++ b/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/smooth_vertices.h @@ -115,6 +115,9 @@ namespace internal const Tr& tr = c3t3.triangulation(); + typename Tr::Geom_traits::Construct_opposite_vector_3 + opp = tr.geom_traits().construct_opposite_vector_3_object(); + for (Finite_facets_iterator fit = tr.finite_facets_begin(); fit != tr.finite_facets_end(); ++fit) { @@ -151,11 +154,12 @@ namespace internal Vector_3 n = CGAL::Tetrahedral_remeshing::facet_normal(tr, *fit); if (si < si_mirror || tr.is_infinite(ch)) - n = -1.*n; + n = opp(n); for (int i = 0; i < 3; ++i) { - Vector_3& v_n = normals_map[fit->first->vertex(indices(fit->second, i))][surf_i]; + Vertex_handle v_id = fit->first->vertex(indices(fit->second, i)); + Vector_3& v_n = normals_map[v_id][surf_i]; v_n = v_n + n; } } @@ -555,11 +559,12 @@ namespace internal return scale(move, 1. / edges.size()); } - template + template typename C3T3::Triangulation::Geom_traits::Vector_3 move_2d(typename C3T3::Vertex_handle v, const C3T3& c3t3, - const typename C3T3::Subdomain_index& imaginary_index) + const typename C3T3::Subdomain_index& imaginary_index, + const CellSelector cell_selector) { typedef typename C3T3::Subdomain_index Subdomain_index; typedef typename C3T3::Edge Edge; @@ -570,12 +575,10 @@ namespace internal const Gt& gt = c3t3.triangulation().geom_traits(); - const Point_3& pos = point(v->point()); - Vector_3 move = CGAL::NULL_VECTOR; - std::vector edges; c3t3.triangulation().incident_edges(v, std::back_inserter(edges)); + Vector_3 move = CGAL::NULL_VECTOR; if (edges.empty()) return move; @@ -585,9 +588,9 @@ namespace internal = gt.construct_sum_of_vectors_3_object(); std::size_t nbe = 0; - BOOST_FOREACH(Edge e, edges) + for(Edge e : edges) { -// if (is_on_domain_hull(e, c3t3, imaginary_index)) + if(!c3t3.is_in_complex(e) && is_boundary(c3t3, e, cell_selector)) { Vertex_handle ve = (e.first->vertex(e.second) != v) ? e.first->vertex(e.second) @@ -597,23 +600,29 @@ namespace internal } } - typedef std::pair Surface_index; - typedef std::map SurfaceIndexMap; - SurfaceIndexMap subdomain_FMLS_indices; - std::vector< FMLS > subdomain_FMLS; - createMLSSurfaces(c3t3, subdomain_FMLS, subdomain_FMLS_indices); - if (nbe > 0) { + // WIP in this section + + typedef std::pair Surface_index; + typedef std::map SurfaceIndexMap; + SurfaceIndexMap subdomain_FMLS_indices; + std::vector< FMLS > subdomain_FMLS; + //createMLSSurfaces(c3t3, subdomain_FMLS, subdomain_FMLS_indices); + typename Gt::Construct_scaled_vector_3 scale = gt.construct_scaled_vector_3_object(); move = scale(move, 1. / nbe); + const Point_3 current_pos = point(v->point()); + const Point_3 smoothed_position = current_pos + move; + Point_3 final_position = CGAL::ORIGIN; + Vector_3 normal = compute_vertex_normal(v, c3t3); Vector_3 normal_projection = project_on_tangent_plane( - pos + move, //smoothed position - pos, //current position + smoothed_position, //smoothed position + current_pos, //current position normal); Vector_3 mls_projection; @@ -739,7 +748,7 @@ namespace internal if (protect_boundaries) break; - smoothing_vecs[vertex_id.at(vit)] = move_2d(vit, c3t3, imaginary_index); + smoothing_vecs[vertex_id.at(vit)] = move_2d(vit, c3t3, imaginary_index, cell_selector); #ifdef CGAL_TETRAHEDRAL_REMESHING_DEBUG if (smoothing_vecs[vertex_id.at(vit)] != CGAL::NULL_VECTOR) ofs_2d << "2 " << vit->point() From 56003ec27ea019b478b28ace7e66875d6cc13f8a Mon Sep 17 00:00:00 2001 From: Jane Tournois Date: Mon, 20 Jan 2020 10:05:21 +0100 Subject: [PATCH 054/568] apply Laurent's review and rename some parameters --- BGL/include/CGAL/boost/graph/parameters_interface.h | 2 +- .../Tetrahedral_remeshing_plugin.cpp | 2 +- .../Concepts/RemeshingCellBase_3.h | 2 +- .../doc/Tetrahedral_remeshing/NamedParameters.txt | 9 +++++---- .../Tetrahedral_remeshing/Tetrahedral_remeshing.txt | 7 ++++--- .../tetrahedral_remeshing_example.cpp | 4 ++-- .../tetrahedral_remeshing_with_features.cpp | 5 ++--- .../CGAL/Tetrahedral_remeshing/Remeshing_cell_base.h | 4 ---- .../Tetrahedral_remeshing/Remeshing_triangulation_3.h | 6 +++--- .../Tetrahedral_remeshing/Remeshing_vertex_base.h | 11 ----------- .../include/CGAL/tetrahedral_remeshing.h | 9 +++++---- 11 files changed, 24 insertions(+), 37 deletions(-) diff --git a/BGL/include/CGAL/boost/graph/parameters_interface.h b/BGL/include/CGAL/boost/graph/parameters_interface.h index 9f29000f296..371c9db021c 100644 --- a/BGL/include/CGAL/boost/graph/parameters_interface.h +++ b/BGL/include/CGAL/boost/graph/parameters_interface.h @@ -138,7 +138,7 @@ CGAL_add_named_parameter(optimize_anchor_location_t, optimize_anchor_location, o CGAL_add_named_parameter(pca_plane_t, pca_plane, pca_plane) // tetrahedral remeshing parameters -CGAL_add_named_parameter(protect_boundaries_t, protect_boundaries, protect_boundaries) +CGAL_add_named_parameter(remesh_boundaries_t, remesh_boundaries, remesh_boundaries) CGAL_add_named_parameter(cell_selector_t, cell_selector, cell_selector) // output parameters diff --git a/Polyhedron/demo/Polyhedron/Plugins/Tetrahedral_remeshing/Tetrahedral_remeshing_plugin.cpp b/Polyhedron/demo/Polyhedron/Plugins/Tetrahedral_remeshing/Tetrahedral_remeshing_plugin.cpp index 13ffe77fcf9..c75285b8e39 100644 --- a/Polyhedron/demo/Polyhedron/Plugins/Tetrahedral_remeshing/Tetrahedral_remeshing_plugin.cpp +++ b/Polyhedron/demo/Polyhedron/Plugins/Tetrahedral_remeshing/Tetrahedral_remeshing_plugin.cpp @@ -218,7 +218,7 @@ public Q_SLOTS: time.restart(); CGAL::tetrahedral_adaptive_remeshing(tr, target_length, - CGAL::parameters::protect_boundaries(protect) + CGAL::parameters::remesh_boundaries(!protect) .number_of_iterations(nb_iter)); std::cout << "Remeshing done (" << time.elapsed() << " ms)" << std::endl; diff --git a/Tetrahedral_remeshing/doc/Tetrahedral_remeshing/Concepts/RemeshingCellBase_3.h b/Tetrahedral_remeshing/doc/Tetrahedral_remeshing/Concepts/RemeshingCellBase_3.h index 6794e123497..0dd0d1822a1 100644 --- a/Tetrahedral_remeshing/doc/Tetrahedral_remeshing/Concepts/RemeshingCellBase_3.h +++ b/Tetrahedral_remeshing/doc/Tetrahedral_remeshing/Concepts/RemeshingCellBase_3.h @@ -4,7 +4,7 @@ /// The concept `RemeshingCellBase_3` defines the requirements for the cell base /// used in the triangulation given as input to the remeshing algorithm /// -/// \cgalRefines `TriangulationCellBaseWithInfo_3`, `CopyConstructible` +/// \cgalRefines `TriangulationCellBase_3`, `CopyConstructible` /// \cgalHasModel `CGAL::Tetrahedral_remeshing::Remeshing_cell_base`. diff --git a/Tetrahedral_remeshing/doc/Tetrahedral_remeshing/NamedParameters.txt b/Tetrahedral_remeshing/doc/Tetrahedral_remeshing/NamedParameters.txt index 51ddbf316c2..35611019fc2 100644 --- a/Tetrahedral_remeshing/doc/Tetrahedral_remeshing/NamedParameters.txt +++ b/Tetrahedral_remeshing/doc/Tetrahedral_remeshing/NamedParameters.txt @@ -38,13 +38,14 @@ in the mesh.\n \b Default value is `1` \cgalNPEnd -\cgalNPBegin{protect_boundaries} +\cgalNPBegin{remeshing_boundaries} \anchor Remeshing_protect_boundaries -a Boolean that states whether the boundaries should be preserved by the remeshing +a Boolean that states whether the boundaries should be remeshed or +exactly preserved by the remeshing process. Boundaries are between the exterior and the interior, between two subdomains, and between the areas selected or not for remeshing (cf \ref Remeshing_cell_is_selected_map). -If `true`, they are preserved. Otherwise, they can be modified.\n +If `true`, they are remeshed. Otherwise, they cannot be modified by the remeshing process.\n \b Type : `bool` \n \b Default value is `false` \cgalNPEnd @@ -77,7 +78,7 @@ the atomic operations that are performed, so the property map must be writable. It must be default constructible.\n Default: a default property map where all cells of the domain -(i.e. with a non-zero `Subdomain_index` are selected) +(i.e. with a non-zero `Subdomain_index`) are selected. \cgalNPEnd \cgalNPTableEnd diff --git a/Tetrahedral_remeshing/doc/Tetrahedral_remeshing/Tetrahedral_remeshing.txt b/Tetrahedral_remeshing/doc/Tetrahedral_remeshing/Tetrahedral_remeshing.txt index 08c5bfcbb56..995b3270785 100644 --- a/Tetrahedral_remeshing/doc/Tetrahedral_remeshing/Tetrahedral_remeshing.txt +++ b/Tetrahedral_remeshing/doc/Tetrahedral_remeshing/Tetrahedral_remeshing.txt @@ -10,13 +10,13 @@ namespace CGAL { \section secTetRemeshing Multi-Material Tetrahedral Remeshing This package implements an algorithm for quality tetrahedral remeshing, -introduced by N.Faraj et al in%\cgalCite{faraj2016mvr}. +introduced by N.Faraj et al in \cgalCite{faraj2016mvr}. This practical iterative remeshing algorithm is designed to remesh multi-material tetrahedral meshes, by iteratively performing a sequence of simple elementary operations such as edge collapses, edge splits, edge flips, and vertex relocations following a Laplacian smoothing. The algorithm results in high quality isotropic meshes, with the desired mesh density, -while preserving the input geometric polyline and surfacic features. +while preserving the input geometric linear and surfacic features. Specific remeshing rules have been designed to satisfy the following criteria. First, the algorithm preserves the geometric complex topology, including @@ -33,7 +33,6 @@ The tetrahedral remeshing algorithm improves the quality of dihedral angles, while targetting the user-defined uniform sizing field and preserving the topology of the feature complex, as highlighted by Figure \cgalFigureRef{Remesh_liver}. - \cgalFigureBegin{Remesh_liver, tetrahedral_remeshing_before_after.png} Tetrahedral mesh, modified by our uniform tetrahedral remeshing method. (Left) Before remeshing, dihedral angles were in the interval [1.3; 177.8]. @@ -41,6 +40,8 @@ Tetrahedral mesh, modified by our uniform tetrahedral remeshing method. dihedral angles were are the interval [9.5; 161.9]. \cgalFigureEnd +Experimental evidence show that a higher number of remeshing iterations +lead to a mesh with a better fitted sizing criterion, and higher quality dihedral angles. \section secTetRemeshingAPI API diff --git a/Tetrahedral_remeshing/examples/Tetrahedral_remeshing/tetrahedral_remeshing_example.cpp b/Tetrahedral_remeshing/examples/Tetrahedral_remeshing/tetrahedral_remeshing_example.cpp index b786380e7f3..a9f6922d80a 100644 --- a/Tetrahedral_remeshing/examples/Tetrahedral_remeshing/tetrahedral_remeshing_example.cpp +++ b/Tetrahedral_remeshing/examples/Tetrahedral_remeshing/tetrahedral_remeshing_example.cpp @@ -47,10 +47,10 @@ int main(int argc, char* argv[]) T3 t3; if (!input) - return false; + return EXIT_FAILURE; if( !load_binary_triangulation(input, t3)) - return false; + return EXIT_FAILURE; CGAL::tetrahedral_adaptive_remeshing(t3, target_edge_length); diff --git a/Tetrahedral_remeshing/examples/Tetrahedral_remeshing/tetrahedral_remeshing_with_features.cpp b/Tetrahedral_remeshing/examples/Tetrahedral_remeshing/tetrahedral_remeshing_with_features.cpp index 18fa43ee700..a1947b7e2cc 100644 --- a/Tetrahedral_remeshing/examples/Tetrahedral_remeshing/tetrahedral_remeshing_with_features.cpp +++ b/Tetrahedral_remeshing/examples/Tetrahedral_remeshing/tetrahedral_remeshing_with_features.cpp @@ -26,7 +26,6 @@ typedef Remeshing_triangulation::Vertex_handle Vertex_handle; typedef Remeshing_triangulation::Cell_handle Cell_handle; typedef Remeshing_triangulation::Edge Edge; -template class Constrained_edges_property_map { public: @@ -74,7 +73,7 @@ void add_edge(Vertex_handle v1, Cell_handle c; int i, j; if(tr.is_edge(v1, v2, c, i, j)) - constraints.insert(std::make_pair(c->vertex(i), c->vertex(j))); + constraints.insert(std::make_pair(v1, v2)); } void generate_input(const std::size_t& n, @@ -156,7 +155,7 @@ int main(int argc, char* argv[]) CGAL::tetrahedral_adaptive_remeshing(t3, target_edge_length, CGAL::parameters::edge_is_constrained_map( - Constrained_edges_property_map(&constraints)) + Constrained_edges_property_map(&constraints)) .number_of_iterations(nb_iter)); save_ascii_triangulation("tet_remeshing_with_features_after.mesh", t3); diff --git a/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/Remeshing_cell_base.h b/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/Remeshing_cell_base.h index 67e50c8e501..85f11d1981e 100644 --- a/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/Remeshing_cell_base.h +++ b/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/Remeshing_cell_base.h @@ -41,15 +41,11 @@ used in the tetrahedral remeshing process. \tparam Gt is the geometric traits class. It has to be a model of the concept `RemeshingTriangulationTraits_3`. -\tparam Info is the information the user would like to add to a cell. -It has to be `DefaultConstructible` and `Assignable`. - \tparam Cb is a cell base class from which `Remeshing_cell_base` derives. It must be a model of the `TriangulationCellBase_3` concept. It has the default value `Triangulation_cell_base_3`. \cgalModels `RemeshingCellBase_3` -\cgalRefines `Triangulation_cell_base_with_info_3` */ template Date: Tue, 21 Jan 2020 17:19:48 +0100 Subject: [PATCH 055/568] fix named parameter name --- .../doc/Tetrahedral_remeshing/NamedParameters.txt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Tetrahedral_remeshing/doc/Tetrahedral_remeshing/NamedParameters.txt b/Tetrahedral_remeshing/doc/Tetrahedral_remeshing/NamedParameters.txt index 35611019fc2..999a7b1eb62 100644 --- a/Tetrahedral_remeshing/doc/Tetrahedral_remeshing/NamedParameters.txt +++ b/Tetrahedral_remeshing/doc/Tetrahedral_remeshing/NamedParameters.txt @@ -38,8 +38,8 @@ in the mesh.\n \b Default value is `1` \cgalNPEnd -\cgalNPBegin{remeshing_boundaries} -\anchor Remeshing_protect_boundaries +\cgalNPBegin{remesh_boundaries} +\anchor Remeshing_remesh_boundaries a Boolean that states whether the boundaries should be remeshed or exactly preserved by the remeshing process. Boundaries are between the exterior and the interior, From e5dfe077b6a82658c19a2124068ccc88e1b9d4b5 Mon Sep 17 00:00:00 2001 From: Jane Tournois Date: Tue, 21 Jan 2020 17:21:30 +0100 Subject: [PATCH 056/568] use MeshVertexBase_3 and MeshCellBase_3 the code uses a C3t3 so let's use the actual vertex base and cell base needed by C3t3, instead of copied simplified versions --- .../Concepts/RemeshingCellBase_3.h | 39 ------- .../Concepts/RemeshingVertexBase_3.h | 41 ------- .../PackageDescription.txt | 14 ++- .../doc/Tetrahedral_remeshing/dependencies | 2 + .../Remeshing_cell_base.h | 108 +++++------------- .../Remeshing_triangulation_3.h | 13 ++- .../Remeshing_vertex_base.h | 87 +++----------- .../include/CGAL/tetrahedral_remeshing.h | 6 +- 8 files changed, 66 insertions(+), 244 deletions(-) delete mode 100644 Tetrahedral_remeshing/doc/Tetrahedral_remeshing/Concepts/RemeshingCellBase_3.h delete mode 100644 Tetrahedral_remeshing/doc/Tetrahedral_remeshing/Concepts/RemeshingVertexBase_3.h diff --git a/Tetrahedral_remeshing/doc/Tetrahedral_remeshing/Concepts/RemeshingCellBase_3.h b/Tetrahedral_remeshing/doc/Tetrahedral_remeshing/Concepts/RemeshingCellBase_3.h deleted file mode 100644 index 0dd0d1822a1..00000000000 --- a/Tetrahedral_remeshing/doc/Tetrahedral_remeshing/Concepts/RemeshingCellBase_3.h +++ /dev/null @@ -1,39 +0,0 @@ -/// \ingroup PkgTetrahedralRemeshingConcepts -/// \cgalConcept -/// -/// The concept `RemeshingCellBase_3` defines the requirements for the cell base -/// used in the triangulation given as input to the remeshing algorithm -/// -/// \cgalRefines `TriangulationCellBase_3`, `CopyConstructible` -/// \cgalHasModel `CGAL::Tetrahedral_remeshing::Remeshing_cell_base`. - - -class RemeshingCellBase_3 { -public: - /// Subdomain index - typedef unspecified_type Subdomain_index; - /// Surface patch index - typedef unspecified_type Surface_patch_index; - - /// @name Operations - /// @{ - /// Returns the index of the input subdomain of the triangulation - /// that contains the cell. - /// Cells with a non-zero `Subdomain_index` are considered as the "inside" - /// of the domain to be remeshed - const Subdomain_index& subdomain_index() const; - - /// Sets the subdomain index of the cell. - void set_subdomain_index(const Subdomain_index& si); - - /// returns `Surface_patch_index` of facet `i`. - const Surface_patch_index surface_patch_index(const int&) const; - - /// sets `Surface_patch_index` of facet `i` to `index` - void set_surface_patch_index(const int i, const Surface_patch_index&) - - /// Returns `true` if the facet `i` lies on a surface patch - bool is_facet_on_surface(const int& i) const; - - /// @} -}; diff --git a/Tetrahedral_remeshing/doc/Tetrahedral_remeshing/Concepts/RemeshingVertexBase_3.h b/Tetrahedral_remeshing/doc/Tetrahedral_remeshing/Concepts/RemeshingVertexBase_3.h deleted file mode 100644 index 28418808342..00000000000 --- a/Tetrahedral_remeshing/doc/Tetrahedral_remeshing/Concepts/RemeshingVertexBase_3.h +++ /dev/null @@ -1,41 +0,0 @@ -/// \ingroup PkgTetrahedralRemeshingConcepts -/// \cgalConcept -/// -/// The concept `RemeshingVertexBase_3` defines the requirements for the vertex base -/// used in the triangulation given as input to the remeshing algorithm. -/// -/// \cgalRefines `TriangulationVertexBase_3`, `CopyConstructible` -/// \cgalHasModel `CGAL::Tetrahedral_remeshing::Remeshing_vertex_base`. - - -class RemeshingVertexBase_3 { -public: - - /// @name Operations - /// @{ - - /// Returns the dimension of the lowest dimensional face of the input 3D - /// complex that contains the vertex - int in_dimension() const; - - /// Sets the dimension of the lowest dimensional face of the input 3D complex - /// that contains the vertex - void set_dimension(const int dimension); - - /// Returns the number of incident facets, - /// stored in a cache variable - std::size_t number_of_incident_facets() const; - - /// Returns the number of subdomains to which belong incident cells, - /// stored in a cache variable - std::size_t number_of_incident_subdomains() const; - - /// Internal function that invalidates cache data stored for performance - void invalidate_cache(); - - /// Internal function that sets cache data stored for performance - void set_cache(const std::size_t& nb_incident_facets, - const std::size_t& nb_incident_subdomains); - - /// @} -}; diff --git a/Tetrahedral_remeshing/doc/Tetrahedral_remeshing/PackageDescription.txt b/Tetrahedral_remeshing/doc/Tetrahedral_remeshing/PackageDescription.txt index b37acfbbdae..8900712c8bb 100644 --- a/Tetrahedral_remeshing/doc/Tetrahedral_remeshing/PackageDescription.txt +++ b/Tetrahedral_remeshing/doc/Tetrahedral_remeshing/PackageDescription.txt @@ -7,9 +7,6 @@ /// \defgroup PkgTetrahedralRemeshingClasses Classes /// \ingroup PkgTetrahedralRemeshingRef -/// \defgroup PkgPACKAGEAlgorithmFunctions Remeshing Function -/// \ingroup PkgPACKAGE - /// \defgroup PkgPACKAGETraitsClasses Traits Classes /// \ingroup PkgPACKAGE @@ -34,7 +31,7 @@ targetting high quality meshes with respect to dihedral angles.} \cgalPkgShortInfoBegin \cgalPkgSince{5.1} -\cgalPkgDependsOn{\ref PkgTriangulation3} +\cgalPkgDependsOn{\ref PkgTriangulation3, PkgMesh3} \cgalPkgBib{faraj2016mvr} \cgalPkgLicense{\ref licensesGPL "GPL"} \cgalPkgDemo{Polyhedron demo,polyhedron_3.zip} @@ -46,8 +43,13 @@ targetting high quality meshes with respect to dihedral angles.} \cgalCRPSection{Concepts} -- `RemeshingCellBase_3` -- `RemeshingVertexBase_3` +- `RemeshingTriangulationTraits_3` + +\cgalCRPSection{Classes} + +- `CGAL::Tetrahedral_remeshing::Remeshing_vertex_base` +- `CGAL::Tetrahedral_remeshing::Remeshing_cell_base` +- `CGAL::Tetrahedral_remeshing::Remeshing_triangulation_3` \cgalCRPSection{Function Templates} diff --git a/Tetrahedral_remeshing/doc/Tetrahedral_remeshing/dependencies b/Tetrahedral_remeshing/doc/Tetrahedral_remeshing/dependencies index abbf00809e4..30913764fab 100644 --- a/Tetrahedral_remeshing/doc/Tetrahedral_remeshing/dependencies +++ b/Tetrahedral_remeshing/doc/Tetrahedral_remeshing/dependencies @@ -6,3 +6,5 @@ Circulator Stream_support Triangulation_3 BGL +Mesh_3 +TDS_3 diff --git a/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/Remeshing_cell_base.h b/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/Remeshing_cell_base.h index 85f11d1981e..d9998b6e2a3 100644 --- a/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/Remeshing_cell_base.h +++ b/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/Remeshing_cell_base.h @@ -22,19 +22,26 @@ #ifndef CGAL_TET_ADAPTIVE_REMESHING_CELL_BASE_H #define CGAL_TET_ADAPTIVE_REMESHING_CELL_BASE_H - -#include - -#include +#include namespace CGAL { namespace Tetrahedral_remeshing { - /*! + namespace internal + { + struct Fake_MD_C + { + typedef int Subdomain_index; + typedef int Surface_patch_index; + typedef int Index; + }; + } + +/*! \ingroup PkgTetrahedralRemeshingClasses -The class `Remeshing_cell_base` is a model of the concept `RemeshingCellBase_3`. +The class `Remeshing_cell_base` is a model of the concept `MeshCellBase_3`. It is designed to serve as cell base class for the 3D triangulation used in the tetrahedral remeshing process. @@ -45,31 +52,20 @@ It has to be a model of the concept `RemeshingTriangulationTraits_3`. It must be a model of the `TriangulationCellBase_3` concept. It has the default value `Triangulation_cell_base_3`. -\cgalModels `RemeshingCellBase_3` +\cgalModels `MeshCellBase_3` */ template > class Remeshing_cell_base - : public Cb - +#ifndef DOXYGEN_RUNNING + : public CGAL::Mesh_cell_base_3 +#endif { - typedef Cb Base; + typedef CGAL::Mesh_cell_base_3 Base; typedef typename Base::Vertex_handle Vertex_handle; typedef typename Base::Cell_handle Cell_handle; - public: - typedef int Subdomain_index; - typedef int Surface_patch_index; - - private: - Subdomain_index subdomain_index_; - // 0 is undefined - // -1 for infinite cells - // 1 to n for subdomains - // n + 1 for imaginary cells - std::size_t time_stamp_; - public: // To get correct cell type in TDS template < class TDS2 > @@ -79,78 +75,26 @@ It has the default value `Triangulation_cell_base_3`. typedef Remeshing_cell_base Other; }; - Remeshing_cell_base() - : subdomain_index_(0) - , time_stamp_(-1) - {} - - Remeshing_cell_base(Vertex_handle v0, - Vertex_handle v1, - Vertex_handle v2, - Vertex_handle v3) - : Base(v0, v1, v2, v3) - , subdomain_index_(0) - , time_stamp_(-1) - {} - - Remeshing_cell_base(Vertex_handle v0, - Vertex_handle v1, - Vertex_handle v2, - Vertex_handle v3, - Cell_handle n0, - Cell_handle n1, - Cell_handle n2, - Cell_handle n3) - : Base(v0, v1, v2, v3, n0, n1, n2, n3) - , subdomain_index_(0) - , time_stamp_(-1) - {} - - const Subdomain_index& subdomain_index() const - { - return subdomain_index_; - } - void set_subdomain_index(const Subdomain_index& si) - { - subdomain_index_ = si; - } - - void set_surface_patch_index(const int, const Surface_patch_index&) - {/*nothing to do because we use incident subdomain indices*/ } - - const Surface_patch_index surface_patch_index(const int& i) const - { - CGAL_precondition(i >= 0 && i < 4); - if(is_facet_on_surface(i)) - return 1; - else - return 0; - } + using Base::Base; +#ifndef DOXYGEN_RUNNING + /// TODO : remove this function from here /// Returns `true` if facet lies on a surface patch - bool is_facet_on_surface(const int& facet) const + bool is_facet_on_surface(const int facet) const { CGAL_precondition(facet >= 0 && facet<4); return this->subdomain_index() != this->neighbor(facet)->subdomain_index(); } - - typedef Tag_true Has_timestamp; - std::size_t time_stamp() const { - return time_stamp_; - } - void set_time_stamp(const std::size_t& ts) { - time_stamp_ = ts; - } - +#endif }; - template < class Gt, class Info, class Cb > + template < class Gt, class Cb > std::istream& operator>>(std::istream &is, Remeshing_cell_base &c) { - typename Remeshing_cell_base::Subdomain_index index; + typename Remeshing_cell_base::Subdomain_index index; if (is_ascii(is)) is >> index; else @@ -172,7 +116,7 @@ It has the default value `Triangulation_cell_base_3`. return is; } - template < class Gt, class Info, class Cb > + template < class Gt, class Cb > std::ostream& operator<<(std::ostream &os, const Remeshing_cell_base &c) { diff --git a/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/Remeshing_triangulation_3.h b/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/Remeshing_triangulation_3.h index 59ab0c68edb..bf856202f22 100644 --- a/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/Remeshing_triangulation_3.h +++ b/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/Remeshing_triangulation_3.h @@ -77,7 +77,7 @@ namespace Tetrahedral_remeshing It must be a model of the `TriangulationCellBase_3` concept. It has the default value `Triangulation_cell_base_3`. - \tparam Vb is a vertex base class deriving from `Triangulation_vertex_base_3`. + \tparam Vb is a vertex base class from which `Remeshing_vertex_base` derives. It must be a model of the `TriangulationVertexBase_3` concept. It has the default value `Triangulation_vertex_base_3`. @@ -100,12 +100,13 @@ namespace Tetrahedral_remeshing > > { - typedef Remeshing_vertex_base RVb; - typedef Remeshing_cell_base RCb; - public: - typedef CGAL::Triangulation_data_structure_3 Tds; - typedef CGAL::Triangulation_3 Self; + typedef Remeshing_vertex_base Remeshing_Vb; + typedef Remeshing_cell_base Remeshing_Cb; + + typedef CGAL::Triangulation_data_structure_3< + Remeshing_Vb, Remeshing_Cb, Concurrency_tag> Tds; + typedef CGAL::Triangulation_3 Self; private: Cell_visitor m_visitor; diff --git a/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/Remeshing_vertex_base.h b/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/Remeshing_vertex_base.h index 7812e7d51ca..eb1d10bf802 100644 --- a/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/Remeshing_vertex_base.h +++ b/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/Remeshing_vertex_base.h @@ -23,16 +23,26 @@ #ifndef CGAL_TET_ADAPTIVE_REMESHING_VERTEX_BASE_H #define CGAL_TET_ADAPTIVE_REMESHING_VERTEX_BASE_H -#include +#include namespace CGAL { namespace Tetrahedral_remeshing { + namespace internal + { + struct Fake_MD_V + { + typedef int Subdomain_index; + typedef int Surface_patch_index; + typedef int Index; + }; + } + /*! \ingroup PkgTetrahedralRemeshingClasses - The class `Remeshing_vertex_base` is a model of the concept `RemeshingVertexBase_3`. + The class `Remeshing_vertex_base` is a model of the concept `MeshVertexBase_3`. It is designed to serve as vertex base class for the 3D triangulation used in the tetrahedral remeshing process. @@ -43,29 +53,20 @@ namespace Tetrahedral_remeshing It must be a model of the `TriangulationVertexBase_3` concept. It has the default value `Triangulation_vertex_base_3`. - \cgalModels `RemeshingVertexBase_3` - \cgalRefines `Triangulation_vertex_base_3` - + \cgalModels `MeshVertexBase_3` + \cgalRefines `Triangulation_vertex_base_3` */ template > class Remeshing_vertex_base - : public Vb +#ifndef DOXYGEN_RUNNING + : public CGAL::Mesh_vertex_base_3 +#endif { - private: - short dimension_; - std::size_t time_stamp_; - std::size_t number_of_incident_facets_; - std::size_t number_of_components_; - bool cache_validity_; + typedef CGAL::Mesh_vertex_base_3 Base; public: - Remeshing_vertex_base() : dimension_(-1) - // time_stamp_ // do not initialize - {} - typedef int Index; - // To get correct vertex type in TDS template < class TDS3 > struct Rebind_TDS { @@ -73,60 +74,10 @@ namespace Tetrahedral_remeshing typedef Remeshing_vertex_base Other; }; - // Returns the dimension of the lowest dimensional face of the input 3D - // complex that contains the vertex - int in_dimension() const { - if (dimension_ < -1) return -2 - dimension_; - else return dimension_; - } - - // Sets the dimension of the lowest dimensional face of the input 3D complex - // that contains the vertex - void set_dimension(const int dimension) { - CGAL_assertion(dimension < 4); - dimension_ = short(dimension); - } - - /// For the determinism of Compact_container iterators - ///@{ - typedef Tag_true Has_timestamp; - std::size_t time_stamp() const { - return time_stamp_; - } - void set_time_stamp(const std::size_t& ts) { - time_stamp_ = ts; - } - ///@} - - // documented as invalidate_cache() - void invalidate_c2t3_cache() - { - cache_validity_ = false; - } - // documented as set_cache() - void set_c2t3_cache(const std::size_t& nb_incident_facets, - const std::size_t& nb_incident_subdomains) - { - number_of_incident_facets_ = nb_incident_facets; - number_of_components_ = nb_incident_subdomains; - cache_validity_ = true; - } - - // documented as number_of_incident_facets - std::size_t cached_number_of_incident_facets() const - { - return number_of_incident_facets_; - } - - // documented as number_of_incident_subdomains - std::size_t cached_number_of_components() const - { - return number_of_components_; - } - }; }//end namespace Tetrahedral_remeshing + }//end namespace CGAL #endif //CGAL_TET_ADAPTIVE_REMESHING_VERTEX_BASE_H diff --git a/Tetrahedral_remeshing/include/CGAL/tetrahedral_remeshing.h b/Tetrahedral_remeshing/include/CGAL/tetrahedral_remeshing.h index c32badcd2d3..76bae99267f 100644 --- a/Tetrahedral_remeshing/include/CGAL/tetrahedral_remeshing.h +++ b/Tetrahedral_remeshing/include/CGAL/tetrahedral_remeshing.h @@ -67,8 +67,10 @@ namespace CGAL * @tparam Triangulation a 3-dimensional triangulation * deriving from `Triangulation_3`, * with geometric traits model of `RemeshingTriangulationTraits_3`, - * cell base model of `RemeshingCellBase_3` - * and vertex base model of `RemeshingVertexBase_3`. + * cell base model of `MeshCellBase_3` + * and vertex base model of `MeshVertexBase_3`. + * The class `Remeshing_triangulation_3` is a helper triangulation class that fits all + * these requirements. * * @tparam NamedParameters a sequence of \ref Remeshing_namedparameters "Named Parameters" * From c7c8b246357016b91c4a0053f9cee980428f5575 Mon Sep 17 00:00:00 2001 From: Jane Tournois Date: Thu, 23 Jan 2020 14:12:00 +0100 Subject: [PATCH 057/568] reintroduce set_dimension() in vertex converter --- .../Tetrahedral_remeshing/Tetrahedral_remeshing_plugin.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Polyhedron/demo/Polyhedron/Plugins/Tetrahedral_remeshing/Tetrahedral_remeshing_plugin.cpp b/Polyhedron/demo/Polyhedron/Plugins/Tetrahedral_remeshing/Tetrahedral_remeshing_plugin.cpp index c75285b8e39..15db0d5bd5f 100644 --- a/Polyhedron/demo/Polyhedron/Plugins/Tetrahedral_remeshing/Tetrahedral_remeshing_plugin.cpp +++ b/Polyhedron/demo/Polyhedron/Plugins/Tetrahedral_remeshing/Tetrahedral_remeshing_plugin.cpp @@ -43,7 +43,7 @@ namespace CGAL { typename TDS_tgt::Vertex v_tgt; v_tgt.set_point(Tgt_point(conv(v_src.point()))); v_tgt.set_time_stamp(-1); -// v_tgt.set_dimension(v_src.dimension()); + v_tgt.set_dimension(v_src.in_dimension()); return v_tgt; } void operator()(const typename TDS_src::Vertex& v_src, @@ -58,7 +58,7 @@ namespace CGAL { typedef typename TDS_tgt::Vertex::Point Tgt_point; v_tgt.set_point(Tgt_point(conv(v_src.point()))); -// v_tgt.set_dimension(v_src.dimension()); + v_tgt.set_dimension(v_src.in_dimension()); } }; From abe46686d8dbfaddd038770fedc6a532d084e478 Mon Sep 17 00:00:00 2001 From: Jane Tournois Date: Thu, 23 Jan 2020 17:52:34 +0100 Subject: [PATCH 058/568] move visitor to a private named parameter this way we can use the triangulation output by Mesh_3 in a straightforward manner, without converting it to a Remeshing_triangulation_3 also make sure that it compiles with the Regular_triangulation used in the Mesh_3 demo plugin and fix a doc typo --- .../CGAL/boost/graph/parameters_interface.h | 1 + .../Tetrahedral_remeshing_plugin.cpp | 135 +----------------- .../Remeshing_triangulation_3.h | 32 ----- .../internal/add_imaginary_layer.h | 4 +- .../internal/collapse_short_edges.h | 22 +-- .../internal/flip_edges.h | 35 +++-- .../internal/split_long_edges.h | 27 ++-- .../tetrahedral_adaptive_remeshing_impl.h | 27 +++- .../internal/tetrahedral_remeshing_helpers.h | 40 +++--- .../include/CGAL/tetrahedral_remeshing.h | 17 ++- 10 files changed, 108 insertions(+), 232 deletions(-) diff --git a/BGL/include/CGAL/boost/graph/parameters_interface.h b/BGL/include/CGAL/boost/graph/parameters_interface.h index 371c9db021c..8a10b3de0cf 100644 --- a/BGL/include/CGAL/boost/graph/parameters_interface.h +++ b/BGL/include/CGAL/boost/graph/parameters_interface.h @@ -140,6 +140,7 @@ CGAL_add_named_parameter(pca_plane_t, pca_plane, pca_plane) // tetrahedral remeshing parameters CGAL_add_named_parameter(remesh_boundaries_t, remesh_boundaries, remesh_boundaries) CGAL_add_named_parameter(cell_selector_t, cell_selector, cell_selector) +CGAL_add_named_parameter(remeshing_visitor_t, remeshing_visitor, remeshing_visitor) // output parameters CGAL_add_named_parameter(face_proxy_map_t, face_proxy_map, face_proxy_map) diff --git a/Polyhedron/demo/Polyhedron/Plugins/Tetrahedral_remeshing/Tetrahedral_remeshing_plugin.cpp b/Polyhedron/demo/Polyhedron/Plugins/Tetrahedral_remeshing/Tetrahedral_remeshing_plugin.cpp index 15db0d5bd5f..59239618a18 100644 --- a/Polyhedron/demo/Polyhedron/Plugins/Tetrahedral_remeshing/Tetrahedral_remeshing_plugin.cpp +++ b/Polyhedron/demo/Polyhedron/Plugins/Tetrahedral_remeshing/Tetrahedral_remeshing_plugin.cpp @@ -23,128 +23,6 @@ #include "ui_Tetrahedral_remeshing_dialog.h" -namespace CGAL { - - namespace internal { - - template - struct Vertex_converter - { - typename TDS_tgt::Vertex operator()(const typename TDS_src::Vertex& v_src) const - { - typedef typename CGAL::Kernel_traits< - typename TDS_src::Vertex::Point>::Kernel GT_src; - typedef typename CGAL::Kernel_traits< - typename TDS_tgt::Vertex::Point>::Kernel GT_tgt; - CGAL::Cartesian_converter conv; - - typedef typename TDS_tgt::Vertex::Point Tgt_point; - - typename TDS_tgt::Vertex v_tgt; - v_tgt.set_point(Tgt_point(conv(v_src.point()))); - v_tgt.set_time_stamp(-1); - v_tgt.set_dimension(v_src.in_dimension()); - return v_tgt; - } - void operator()(const typename TDS_src::Vertex& v_src, - typename TDS_tgt::Vertex& v_tgt) const - { - typedef typename CGAL::Kernel_traits< - typename TDS_src::Vertex::Point>::Kernel GT_src; - typedef typename CGAL::Kernel_traits< - typename TDS_tgt::Vertex::Point>::Kernel GT_tgt; - CGAL::Cartesian_converter conv; - - typedef typename TDS_tgt::Vertex::Point Tgt_point; - - v_tgt.set_point(Tgt_point(conv(v_src.point()))); - v_tgt.set_dimension(v_src.in_dimension()); - } - }; - - template - struct Cell_converter - { - typename TDS_tgt::Cell operator()(const typename TDS_src::Cell& c_src) const - { - typename TDS_tgt::Cell c_tgt; - c_tgt.set_subdomain_index(c_src.subdomain_index()); - c_tgt.set_time_stamp(-1); - return c_tgt; - } - void operator()(const typename TDS_src::Cell& c_src, - typename TDS_tgt::Cell& c_tgt) const - { - c_tgt.set_subdomain_index(c_src.subdomain_index()); - } - }; - - template - void build_remeshing_triangulation(const T3& tr, - Remeshing_tr& remeshing_tr) - { - typedef typename T3::Triangulation_data_structure Tds; - typedef typename Remeshing_tr::Tds RTds; - - remeshing_tr.clear(); - remeshing_tr.set_infinite_vertex( - remeshing_tr.tds().copy_tds( - tr.tds(), - tr.infinite_vertex(), - Vertex_converter(), - Cell_converter())); - } - - template - void build_from_remeshing_triangulation(const Remeshing_tr& remeshing_tr, - T3& tr) - { - typedef typename T3::Triangulation_data_structure Tds; - typedef typename Remeshing_tr::Tds RTds; - - tr.clear(); - tr.set_infinite_vertex( - tr.tds().copy_tds( - remeshing_tr.tds(), - remeshing_tr.infinite_vertex(), - Vertex_converter(), - Cell_converter())); - } - - void update_c3t3(C3t3& c3t3) - { - for (typename C3t3::Triangulation::Finite_facets_iterator - fit = c3t3.triangulation().finite_facets_begin(); - fit != c3t3.triangulation().finite_facets_end(); - ++fit) - { - typename C3t3::Triangulation::Facet f = *fit; - typename C3t3::Triangulation::Cell::Subdomain_index - s1 = f.first->subdomain_index(), - s2 = f.first->neighbor(f.second)->subdomain_index(); - if (s1 != s2) - { - if (s1 > s2) - std::swap(s1, s2); - c3t3.add_to_complex(f, s1 + 100 * s2);// std::make_pair(s1, s2)); - } - } - for (typename C3t3::Triangulation::Finite_cells_iterator - cit = c3t3.triangulation().finite_cells_begin(); - cit != c3t3.triangulation().finite_cells_end(); - ++cit) - { - typename C3t3::Triangulation::Cell::Subdomain_index - si = cit->subdomain_index(); - if (si != 0) - { - cit->set_subdomain_index(0);//o.w. add_to_complex() does nothing - c3t3.add_to_complex(cit, si); - } - } - } - } -} using namespace CGAL::Three; class Polyhedron_demo_tetrahedral_remeshing_plugin : @@ -211,13 +89,8 @@ public Q_SLOTS: QTime time; time.start(); - Remeshing_triangulation tr; - CGAL::internal::build_remeshing_triangulation(c3t3_item->c3t3().triangulation(), tr); - - std::cout << "Remeshing triangulation built (" << time.elapsed() << " ms)" << std::endl; - time.restart(); - - CGAL::tetrahedral_adaptive_remeshing(tr, target_length, + CGAL::tetrahedral_adaptive_remeshing(c3t3_item->c3t3().triangulation(), + target_length, CGAL::parameters::remesh_boundaries(!protect) .number_of_iterations(nb_iter)); @@ -225,10 +98,6 @@ public Q_SLOTS: time.restart(); c3t3_item->c3t3().clear(); - CGAL::internal::build_from_remeshing_triangulation(tr, c3t3_item->c3t3().triangulation()); - CGAL::internal::update_c3t3(c3t3_item->c3t3()); - - std::cout << "Back conversion done (" << time.elapsed() << " ms)" << std::endl; c3t3_item->c3t3_changed(); this->scene->itemChanged(index); diff --git a/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/Remeshing_triangulation_3.h b/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/Remeshing_triangulation_3.h index bf856202f22..9cc108b7462 100644 --- a/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/Remeshing_triangulation_3.h +++ b/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/Remeshing_triangulation_3.h @@ -40,24 +40,6 @@ namespace CGAL { namespace Tetrahedral_remeshing { - class Default_remeshing_visitor - { - public: - template - void before_split(const Tr& tr, - const typename Tr::Edge& e) {} - template - void after_split(const Tr& tr, - const typename Tr::Vertex_handle new_v) {} - template - void after_add_cell(CellHandleOld co, - CellHandleNew cn) const {} - template - void before_flip(const CellHandle c) {} - template - void after_flip(CellHandle c) {} - }; - /*! \ingroup PkgTetrahedralRemeshingClasses @@ -88,9 +70,6 @@ namespace Tetrahedral_remeshing typename Concurrency_tag = CGAL::Sequential_tag, typename Cb = CGAL::Triangulation_cell_base_3, typename Vb = CGAL::Triangulation_vertex_base_3 - /// \cond SKIP_IN_MANUAL - , typename Cell_visitor = Default_remeshing_visitor - /// \endcond > class Remeshing_triangulation_3 : public CGAL::Triangulation_3 Tds; typedef CGAL::Triangulation_3 Self; - - private: - Cell_visitor m_visitor; - - /// \cond SKIP_IN_MANUAL - public: - Cell_visitor& visitor() - { - return m_visitor; - } - /// \endcond }; namespace internal diff --git a/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/add_imaginary_layer.h b/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/add_imaginary_layer.h index bbe4bfc5504..7c28e36b60a 100644 --- a/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/add_imaginary_layer.h +++ b/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/add_imaginary_layer.h @@ -209,7 +209,7 @@ namespace internal void add_layer_of_imaginary_tets(T3& tr, const Index& imaginary_index) { typedef typename T3::Vertex_handle Vertex_handle; - typedef typename T3::Point Point; + typedef typename T3::Geom_traits::Point_3 Point_3; typedef typename T3::Geom_traits::Vector_3 Vector_3; //compute normals @@ -220,7 +220,7 @@ namespace internal const double offset = 0.04 * compute_bbox_max_size(tr); //compute points to be inserted - std::vector offset_points; + std::vector offset_points; compute_offset_points(normals, offset, std::back_inserter(offset_points), diff --git a/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/collapse_short_edges.h b/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/collapse_short_edges.h index be1d0c4c2c2..571568f81fb 100644 --- a/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/collapse_short_edges.h +++ b/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/collapse_short_edges.h @@ -50,7 +50,7 @@ namespace internal V_PROBLEM, C_PROBLEM, E_PROBLEM, TOPOLOGICAL_PROBLEM, ORIENTATION_PROBLEM, SHARED_NEIGHBOR_PROBLEM }; - template + template class CollapseTriangulation { typedef typename C3t3::Triangulation Tr; @@ -66,7 +66,8 @@ namespace internal public: CollapseTriangulation(C3t3& c3t3, const Edge& edge, - Collapse_type _collapse_type) + Collapse_type _collapse_type, + Visitor& visitor) { v0_init = edge.first->vertex(edge.second); v1_init = edge.first->vertex(edge.third); @@ -109,7 +110,7 @@ namespace internal Cell_handle new_ch = builder.add_cell(v2v.left.at(ch->vertex(0)), v2v.left.at(ch->vertex(1)), v2v.left.at(ch->vertex(2)), v2v.left.at(ch->vertex(3))); new_ch->set_subdomain_index(ch->subdomain_index()); - c3t3.triangulation().visitor().after_add_cell(ch, new_ch); + visitor.after_add_cell(ch, new_ch); c2c.left.insert(std::make_pair(ch, new_ch)); } @@ -834,13 +835,14 @@ namespace internal return vh; } - template + template typename C3t3::Vertex_handle collapse_edge(typename C3t3::Edge& edge, C3t3& c3t3, const typename C3t3::Triangulation::Geom_traits::FT& sqhigh, const bool protect_boundaries, const typename C3t3::Subdomain_index& imaginary_index, - CellSelector cell_selector) + CellSelector cell_selector, + Visitor& visitor) { typedef typename C3t3::Triangulation Tr; typedef typename Tr::Point Point; @@ -874,7 +876,7 @@ namespace internal edges_sqlength_after_collapse, sqhigh, imaginary_index /*, adaptive = false*/)) { - CollapseTriangulation local_tri(c3t3, edge, collapse_type); + CollapseTriangulation local_tri(c3t3, edge, collapse_type, visitor); local_tri.update(); Result_type res = local_tri.collapse(); @@ -925,13 +927,14 @@ namespace internal } } - template + template void collapse_short_edges(C3T3& c3t3, const typename C3T3::Triangulation::Geom_traits::FT& low, const typename C3T3::Triangulation::Geom_traits::FT& high, const bool protect_boundaries, const typename C3T3::Subdomain_index& imaginary_index, - CellSelector cell_selector) + CellSelector cell_selector, + Visitor& visitor) { typedef typename C3T3::Triangulation T3; typedef typename T3::Cell_handle Cell_handle; @@ -1004,7 +1007,8 @@ namespace internal Vertex_handle vh = #endif collapse_edge(edge, c3t3, sq_high, - protect_boundaries, imaginary_index, cell_selector); + protect_boundaries, imaginary_index, cell_selector, + visitor); #ifdef CGAL_TETRAHEDRAL_REMESHING_VERBOSE if (vh != Vertex_handle()) diff --git a/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/flip_edges.h b/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/flip_edges.h index aea972b57b5..2bfc8df12e1 100644 --- a/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/flip_edges.h +++ b/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/flip_edges.h @@ -591,10 +591,11 @@ namespace internal } } - template + template Sliver_removal_result flip_n_to_m(C3t3& c3t3, typename C3t3::Edge& edge, typename C3t3::Vertex_handle vh, + Visitor& visitor, bool check_validity = false) { CGAL_USE(check_validity); @@ -769,7 +770,7 @@ namespace internal //Subdomain index? typename C3t3::Subdomain_index subdomain = to_remove[0]->subdomain_index(); - tr.visitor().before_flip(to_remove[0]); + visitor.before_flip(to_remove[0]); #ifdef CGAL_TETRAHEDRAL_REMESHING_DEBUG for (std::size_t i = 1; i < to_remove.size(); ++i) @@ -792,7 +793,7 @@ namespace internal new_cell->set_vertex(fi.second, vh); c3t3.add_to_complex(new_cell, subdomain); - tr.visitor().after_flip(new_cell); + visitor.after_flip(new_cell); cells_to_update.push_back(new_cell); } @@ -913,11 +914,12 @@ namespace internal } - template + template Sliver_removal_result flip_n_to_m(typename C3t3::Edge& edge, C3t3& c3t3, std::vector& boundary_vertices, - const Flip_Criterion& criterion) + const Flip_Criterion& criterion, + Visitor& visitor) { typedef typename C3t3::Vertex_handle Vertex_handle; typedef typename C3t3::Triangulation::Cell_circulator Cell_circulator; @@ -959,7 +961,7 @@ namespace internal if (curr_min_dh >= curr_cost_vpair.first) return NO_BEST_CONFIGURATION; - result = flip_n_to_m(c3t3, edge, curr_cost_vpair.second.first); + result = flip_n_to_m(c3t3, edge, curr_cost_vpair.second.first, visitor); if (result != NOT_FLIPPABLE) flip_performed = true; @@ -969,10 +971,11 @@ namespace internal return result; } - template + template Sliver_removal_result find_best_flip(typename C3t3::Edge& edge, C3t3& c3t3, - const Flip_Criterion& criterion) + const Flip_Criterion& criterion, + Visitor& visitor) { typedef typename C3t3::Triangulation Tr; typedef typename C3t3::Vertex_handle Vertex_handle; @@ -1044,7 +1047,7 @@ namespace internal { std::vector vertices; vertices.insert(vertices.end(), boundary_vertices.begin(), boundary_vertices.end()); - return flip_n_to_m(edge, c3t3, vertices, criterion); + return flip_n_to_m(edge, c3t3, vertices, criterion, visitor); //return n_to_m_flip(edge, boundary_vertices, flip_criterion); } } @@ -1052,10 +1055,11 @@ namespace internal } - template + template std::size_t flip_all_edges(std::vector& edges, C3t3& c3t3, - const Flip_Criterion& criterion) + const Flip_Criterion& criterion, + Visitor& visitor) { typedef typename C3t3::Triangulation Tr; typedef typename Tr::Vertex_handle Vertex_handle; @@ -1076,7 +1080,7 @@ namespace internal { Edge edge(ch, i0, i1); - Sliver_removal_result res = find_best_flip(edge, c3t3, criterion); + Sliver_removal_result res = find_best_flip(edge, c3t3, criterion, visitor); if (res == INVALID_CELL || res == INVALID_VERTEX || res == INVALID_ORIENTATION) { std::cout << "FLIP PROBLEM!!!!" << std::endl; @@ -1096,11 +1100,12 @@ namespace internal return count; } - template + template void flip_edges(C3T3& c3t3, const typename C3T3::Subdomain_index& imaginary_index, const bool protect_boundaries, - CellSelector cell_selector) + CellSelector cell_selector, + Visitor& visitor) { CGAL_USE(protect_boundaries); typedef typename C3T3::Triangulation T3; @@ -1153,7 +1158,7 @@ namespace internal #ifdef CGAL_TETRAHEDRAL_REMESHING_VERBOSE nb_flips = #endif - flip_all_edges(inside_edges, c3t3, MIN_ANGLE_BASED); + flip_all_edges(inside_edges, c3t3, MIN_ANGLE_BASED, visitor); //} #ifdef CGAL_TETRAHEDRAL_REMESHING_VERBOSE diff --git a/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/split_long_edges.h b/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/split_long_edges.h index 5596786baf6..7aab960ccfc 100644 --- a/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/split_long_edges.h +++ b/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/split_long_edges.h @@ -42,13 +42,13 @@ namespace internal typename C3t3::Vertex_handle split_edge(const typename C3t3::Edge& e, C3t3& c3t3) { - typedef typename C3t3::Triangulation Tr; - typedef typename C3t3::Subdomain_index Subdomain_index; - typedef typename Tr::Point Point; - typedef typename Tr::Facet Facet; - typedef typename Tr::Vertex_handle Vertex_handle; - typedef typename Tr::Cell_handle Cell_handle; - typedef typename Tr::Cell_circulator Cell_circulator; + typedef typename C3t3::Triangulation Tr; + typedef typename C3t3::Subdomain_index Subdomain_index; + typedef typename Tr::Geom_traits::Point_3 Point; + typedef typename Tr::Facet Facet; + typedef typename Tr::Vertex_handle Vertex_handle; + typedef typename Tr::Cell_handle Cell_handle; + typedef typename Tr::Cell_circulator Cell_circulator; Tr& tr = c3t3.triangulation(); Vertex_handle v1 = e.first->vertex(e.second); @@ -57,7 +57,6 @@ namespace internal //backup subdomain info of incident cells before making changes short dimension = (c3t3.is_in_complex(e)) ? 1 : 3; boost::unordered_map info; - tr.visitor().before_split(c3t3.triangulation(), e); Cell_circulator circ = tr.incident_cells(e); Cell_circulator end = circ; @@ -85,14 +84,11 @@ namespace internal Vertex_handle new_v = tr.tds().insert_in_edge(e); const Point m = tr.geom_traits().construct_midpoint_3_object() (point(v1->point()), point(v2->point())); - new_v->set_point(m); + new_v->set_point(typename Tr::Point(m)); // update dimension c3t3.set_dimension(new_v, dimension); - // update c3t3 - tr.visitor().after_split(tr, new_v); - std::vector new_cells; tr.incident_cells(new_v, std::back_inserter(new_cells)); for (std::size_t i = 0; i < new_cells.size(); ++i) @@ -144,12 +140,13 @@ namespace internal } } - template + template void split_long_edges(C3T3& c3t3, const typename C3T3::Triangulation::Geom_traits::FT& high, const bool protect_boundaries, const typename C3T3::Subdomain_index& imaginary_index, - CellSelector cell_selector) + CellSelector cell_selector, + Visitor& visitor) { typedef typename C3T3::Triangulation T3; typedef typename T3::Cell_handle Cell_handle; @@ -216,7 +213,9 @@ namespace internal if (!can_be_split(edge, c3t3, protect_boundaries, imaginary_index, cell_selector)) continue; + visitor.before_split(tr, edge); Vertex_handle vh = split_edge(edge, c3t3); + visitor.after_split(tr, vh); //CGAL_assertion(tr.is_valid(true)); #ifdef CGAL_TETRAHEDRAL_REMESHING_DEBUG diff --git a/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/tetrahedral_adaptive_remeshing_impl.h b/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/tetrahedral_adaptive_remeshing_impl.h index 55e9cd8f0d4..d21e990a4c1 100644 --- a/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/tetrahedral_adaptive_remeshing_impl.h +++ b/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/tetrahedral_adaptive_remeshing_impl.h @@ -43,6 +43,23 @@ namespace Tetrahedral_remeshing { namespace internal { + class Default_remeshing_visitor + { + public: + template + void before_split(const Tr& tr, const typename Tr::Edge& e) {} + template + void after_split(const Tr& tr, const typename Tr::Vertex_handle new_v) {} + + template + void after_add_cell(CellHandleOld co, CellHandleNew cn) const {} + + template + void before_flip(const CellHandle c) {} + template + void after_flip(CellHandle c) {} + }; + template struct All_cells_selected { @@ -76,6 +93,7 @@ namespace internal , typename SizingFunction , typename EdgeIsConstrainedMap , typename CellSelector + , typename Visitor > class Adaptive_remesher { @@ -97,6 +115,7 @@ namespace internal Triangulation& m_tr; //backup to re-swap triangulations when done CellSelector m_cell_selector; Subdomain_index m_imaginary_index; + Visitor& m_visitor; public: Adaptive_remesher(Triangulation& tr @@ -104,6 +123,7 @@ namespace internal , const bool protect_boundaries , EdgeIsConstrainedMap ecmap , CellSelector cell_selector + , Visitor& visitor // , const bool adaptive ) : m_sizing(sizing) @@ -112,6 +132,7 @@ namespace internal , m_c3t3() , m_tr(tr) , m_cell_selector(cell_selector) + , m_visitor(visitor) { m_c3t3.triangulation().swap(tr); init_c3t3(ecmap); @@ -154,7 +175,7 @@ namespace internal const FT target_edge_length = m_sizing(CGAL::ORIGIN); const FT emax = FT(4)/FT(3) * target_edge_length; split_long_edges(m_c3t3, emax, m_protect_boundaries, m_imaginary_index, - m_cell_selector); + m_cell_selector, m_visitor); CGAL_assertion(tr().is_valid(true)); #ifdef CGAL_DUMP_REMESHING_STEPS @@ -173,7 +194,7 @@ namespace internal FT emax = FT(4)/FT(3) * target_edge_length; collapse_short_edges(m_c3t3, emin, emax, m_protect_boundaries, m_imaginary_index, - m_cell_selector); + m_cell_selector, m_visitor); CGAL_assertion(tr().is_valid(true)); #ifdef CGAL_DUMP_REMESHING_STEPS @@ -187,7 +208,7 @@ namespace internal void flip() { flip_edges(m_c3t3, m_imaginary_index, m_protect_boundaries, - m_cell_selector); + m_cell_selector, m_visitor); CGAL_assertion(tr().is_valid(true)); #ifdef CGAL_DUMP_REMESHING_STEPS diff --git a/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/tetrahedral_remeshing_helpers.h b/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/tetrahedral_remeshing_helpers.h index 175bc7a70e6..384499f376b 100644 --- a/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/tetrahedral_remeshing_helpers.h +++ b/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/tetrahedral_remeshing_helpers.h @@ -83,30 +83,30 @@ namespace Tetrahedral_remeshing return gt.compute_approximate_dihedral_angle_3_object()(p, q, r, s); } - template - typename Tr::Geom_traits::FT min_dihedral_angle(const Tr& tr, - const typename Tr::Point& p, - const typename Tr::Point& q, - const typename Tr::Point& r, - const typename Tr::Point& s) + template + typename Geom_traits::FT min_dihedral_angle(const Point& p, + const Point& q, + const Point& r, + const Point& s, + const Geom_traits& gt) { - typedef typename Tr::Geom_traits::FT FT; - FT a = CGAL::abs(dihedral_angle(p, q, r, s, tr.geom_traits())); + typedef typename Geom_traits::FT FT; + FT a = CGAL::abs(dihedral_angle(p, q, r, s, gt)); FT min_dh = a; - a = CGAL::abs(dihedral_angle(p, r, q, s, tr.geom_traits())); + a = CGAL::abs(dihedral_angle(p, r, q, s, gt)); min_dh = (std::min)(a, min_dh); - a = CGAL::abs(dihedral_angle(p, s, q, r, tr.geom_traits())); + a = CGAL::abs(dihedral_angle(p, s, q, r, gt)); min_dh = (std::min)(a, min_dh); - a = CGAL::abs(dihedral_angle(q, r, p, s, tr.geom_traits())); + a = CGAL::abs(dihedral_angle(q, r, p, s, gt)); min_dh = (std::min)(a, min_dh); - a = CGAL::abs(dihedral_angle(q, s, p, r, tr.geom_traits())); + a = CGAL::abs(dihedral_angle(q, s, p, r, gt)); min_dh = (std::min)(a, min_dh); - a = CGAL::abs(dihedral_angle(r, s, p, q, tr.geom_traits())); + a = CGAL::abs(dihedral_angle(r, s, p, q, gt)); min_dh = (std::min)(a, min_dh); return min_dh; @@ -119,11 +119,11 @@ namespace Tetrahedral_remeshing const typename Tr::Vertex_handle v2, const typename Tr::Vertex_handle v3) { - return min_dihedral_angle(tr, - point(v0->point()), + return min_dihedral_angle(point(v0->point()), point(v1->point()), point(v2->point()), - point(v3->point())); + point(v3->point()), + tr.geom_traits()); } template @@ -131,10 +131,10 @@ namespace Tetrahedral_remeshing const typename Tr::Cell_handle c) { return min_dihedral_angle(tr, - point(c->vertex(0)->point()), - point(c->vertex(1)->point()), - point(c->vertex(2)->point()), - point(c->vertex(3)->point())); + c->vertex(0), + c->vertex(1), + c->vertex(2), + c->vertex(3)); } template diff --git a/Tetrahedral_remeshing/include/CGAL/tetrahedral_remeshing.h b/Tetrahedral_remeshing/include/CGAL/tetrahedral_remeshing.h index 76bae99267f..d9189e715c2 100644 --- a/Tetrahedral_remeshing/include/CGAL/tetrahedral_remeshing.h +++ b/Tetrahedral_remeshing/include/CGAL/tetrahedral_remeshing.h @@ -56,7 +56,7 @@ namespace CGAL * subdomains throughout the remeshing process. * * Subdomains are defined by indices that - * are stored in the cells of the input triangulation, following the `RemeshingCellBase_3` + * are stored in the cells of the input triangulation, following the `MeshCellBase_3` * concept. * The surfacic interfaces between subdomains are formed by facets which two incident cells * have different subdomain indices. @@ -181,6 +181,15 @@ namespace CGAL ECMap ecmap = choose_param(get_param(np, internal_np::edge_is_constrained) , No_constraint()); + typedef typename boost::lookup_named_param_def < + internal_np::remeshing_visitor_t, + NamedParameters, + Tetrahedral_remeshing::internal::Default_remeshing_visitor + > ::type Visitor; + Visitor visitor + = choose_param(get_param(np, internal_np::remeshing_visitor), + Tetrahedral_remeshing::internal::Default_remeshing_visitor()); + #ifdef CGAL_TETRAHEDRAL_REMESHING_VERBOSE std::cout << "Tetrahedral remeshing (" << "nb_iter = " << max_it @@ -192,9 +201,9 @@ namespace CGAL #endif typedef Tetrahedral_remeshing::internal::Adaptive_remesher< - Tr, SizingFunction, ECMap, SelectionFunctor> Remesher; + Tr, SizingFunction, ECMap, SelectionFunctor, Visitor> Remesher; Remesher remesher(tr, sizing, protect, ecmap - , cell_select + , cell_select, visitor /*, adaptive*/); #ifdef CGAL_TETRAHEDRAL_REMESHING_VERBOSE @@ -218,7 +227,7 @@ namespace CGAL remesher.collapse(); } remesher.flip(); - remesher.smooth(); +// remesher.smooth(); #ifdef CGAL_TETRAHEDRAL_REMESHING_VERBOSE std::cout << "# Iteration " << it_nb << " done : " From b4a3dc181d774db7887b1d1fdeb9f7148173fb40 Mon Sep 17 00:00:00 2001 From: Jane Tournois Date: Fri, 24 Jan 2020 11:10:44 +0100 Subject: [PATCH 059/568] add facet_is_constrained_map to constrain facets --- .../CGAL/boost/graph/parameters_interface.h | 1 + .../tetrahedral_adaptive_remeshing_impl.h | 13 ++++++++---- .../include/CGAL/tetrahedral_remeshing.h | 20 ++++++++++++++++--- 3 files changed, 27 insertions(+), 7 deletions(-) diff --git a/BGL/include/CGAL/boost/graph/parameters_interface.h b/BGL/include/CGAL/boost/graph/parameters_interface.h index 8a10b3de0cf..bceb10acb97 100644 --- a/BGL/include/CGAL/boost/graph/parameters_interface.h +++ b/BGL/include/CGAL/boost/graph/parameters_interface.h @@ -140,6 +140,7 @@ CGAL_add_named_parameter(pca_plane_t, pca_plane, pca_plane) // tetrahedral remeshing parameters CGAL_add_named_parameter(remesh_boundaries_t, remesh_boundaries, remesh_boundaries) CGAL_add_named_parameter(cell_selector_t, cell_selector, cell_selector) +CGAL_add_named_parameter(facet_is_constrained_t, facet_is_constrained, facet_is_constrained_map) CGAL_add_named_parameter(remeshing_visitor_t, remeshing_visitor, remeshing_visitor) // output parameters diff --git a/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/tetrahedral_adaptive_remeshing_impl.h b/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/tetrahedral_adaptive_remeshing_impl.h index d21e990a4c1..038d8e40cad 100644 --- a/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/tetrahedral_adaptive_remeshing_impl.h +++ b/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/tetrahedral_adaptive_remeshing_impl.h @@ -92,6 +92,7 @@ namespace internal template @@ -122,6 +123,7 @@ namespace internal , const SizingFunction& sizing , const bool protect_boundaries , EdgeIsConstrainedMap ecmap + , FacetIsConstrainedMap fcmap , CellSelector cell_selector , Visitor& visitor // , const bool adaptive @@ -135,7 +137,7 @@ namespace internal , m_visitor(visitor) { m_c3t3.triangulation().swap(tr); - init_c3t3(ecmap); + init_c3t3(ecmap, fcmap); #ifdef CGAL_DUMP_REMESHING_STEPS CGAL::Tetrahedral_remeshing::debug::dump_without_imaginary(m_c3t3.triangulation(), @@ -313,7 +315,8 @@ namespace internal return m_c3t3.triangulation(); } - void init_c3t3(const EdgeIsConstrainedMap& ecmap) + void init_c3t3(const EdgeIsConstrainedMap& ecmap, + const FacetIsConstrainedMap& fcmap) { #ifdef CGAL_TETRAHEDRAL_REMESHING_DEBUG std::size_t nbc = 0; @@ -330,7 +333,7 @@ namespace internal cit != tr().finite_cells_end(); ++cit) { - if (m_cell_selector(cit))//->subdomain_index() != Subdomain_index()) + if (m_cell_selector(cit)) { m_c3t3.add_to_complex(cit, cit->subdomain_index()); max_si = (std::max)(max_si, cit->subdomain_index()); @@ -360,7 +363,9 @@ namespace internal Facet mf = tr().mirror_facet(f); Subdomain_index s1 = f.first->subdomain_index(); Subdomain_index s2 = mf.first->subdomain_index(); - if (s1 != s2) + if ( s1 != s2 + || get(fcmap, f) + || get(fcmap, mf) ) { m_c3t3.add_to_complex(f, 1); diff --git a/Tetrahedral_remeshing/include/CGAL/tetrahedral_remeshing.h b/Tetrahedral_remeshing/include/CGAL/tetrahedral_remeshing.h index d9189e715c2..890baac6b25 100644 --- a/Tetrahedral_remeshing/include/CGAL/tetrahedral_remeshing.h +++ b/Tetrahedral_remeshing/include/CGAL/tetrahedral_remeshing.h @@ -92,6 +92,10 @@ namespace CGAL * constrained - or - not status of each edge of `tr`. A constrained edge can be split * or collapsed, but not flipped. * \cgalParamEnd + * \cgalParamBegin{facet_is_constrained_map} a property map containing the + * constrained - or - not status of each facet of `tr`. A constrained facet can be split + * or collapsed, but not flipped. + * \cgalParamEnd * \cgalParamBegin{cell_is_selected_map} a property map containing the * selected - or - not status for each cell of `tr` for remeshing. * Only selected cells are modified (and possibly their neighbors if surfaces are @@ -172,7 +176,6 @@ namespace CGAL typedef std::pair Edge_vv; typedef Tetrahedral_remeshing::internal::No_constraint_pmap No_constraint; - typedef typename boost::lookup_named_param_def < internal_np::edge_is_constrained_t, NamedParameters, @@ -181,6 +184,16 @@ namespace CGAL ECMap ecmap = choose_param(get_param(np, internal_np::edge_is_constrained) , No_constraint()); + typedef typename Tr::Facet Facet; + typedef Tetrahedral_remeshing::internal::No_constraint_pmap No_facet; + typedef typename boost::lookup_named_param_def < + internal_np::facet_is_constrained_t, + NamedParameters, + No_facet//default + > ::type FCMap; + FCMap fcmap = choose_param(get_param(np, internal_np::facet_is_constrained) + , No_facet()); + typedef typename boost::lookup_named_param_def < internal_np::remeshing_visitor_t, NamedParameters, @@ -201,8 +214,9 @@ namespace CGAL #endif typedef Tetrahedral_remeshing::internal::Adaptive_remesher< - Tr, SizingFunction, ECMap, SelectionFunctor, Visitor> Remesher; - Remesher remesher(tr, sizing, protect, ecmap + Tr, SizingFunction, ECMap, FCMap, SelectionFunctor, Visitor> Remesher; + Remesher remesher(tr, sizing, protect + , ecmap, fcmap , cell_select, visitor /*, adaptive*/); From c01952b98c4120a8a1219ad417448116b9bc331d Mon Sep 17 00:00:00 2001 From: Jane Tournois Date: Fri, 24 Jan 2020 11:33:21 +0100 Subject: [PATCH 060/568] use Triangulation_3 explicitly to make sure the base class is used before that, one could give a DT3 or a RT3 to the remeshing function. Remeshing would then make the triangulation invalid with respect to the Delaunay or Regular criterion, though the TDS would remain valid. Now it is clear that we do not expect nor return anything but a valid T3. --- .../include/CGAL/tetrahedral_remeshing.h | 49 ++++++++++--------- 1 file changed, 26 insertions(+), 23 deletions(-) diff --git a/Tetrahedral_remeshing/include/CGAL/tetrahedral_remeshing.h b/Tetrahedral_remeshing/include/CGAL/tetrahedral_remeshing.h index 890baac6b25..b5801bf077c 100644 --- a/Tetrahedral_remeshing/include/CGAL/tetrahedral_remeshing.h +++ b/Tetrahedral_remeshing/include/CGAL/tetrahedral_remeshing.h @@ -22,6 +22,8 @@ #ifndef TETRAHEDRAL_REMESHING_H #define TETRAHEDRAL_REMESHING_H +#include +#include #include #include @@ -109,50 +111,50 @@ namespace CGAL */ // * @tparam SizingField model of `CGAL::Sizing_field` - //* \cgalParamBegin{ adaptive } If `true`, size of elements adapts //* .... //* \cgalParamEnd - //template - //void tetrahedral_adaptive_remeshing(Triangulation& tr, - // const SizingField& sizing_field, - // const NamedParameters& np) - template - void tetrahedral_adaptive_remeshing(Triangulation& tr, - const double& target_edge_length, - const NamedParameters& np) + template + void tetrahedral_adaptive_remeshing( + CGAL::Triangulation_3& tr, + const double& target_edge_length, + const NamedParameters& np) { + typedef CGAL::Triangulation_3 Triangulation; tetrahedral_adaptive_remeshing( tr, - [target_edge_length](const typename Triangulation::Point& p) + [target_edge_length](const Triangulation::Point& p) {return target_edge_length;}, np); } - template - void tetrahedral_adaptive_remeshing(Triangulation& tr, + template + void tetrahedral_adaptive_remeshing( + CGAL::Triangulation_3& tr, const float& target_edge_length, const NamedParameters& np) { + typedef CGAL::Triangulation_3 Triangulation; tetrahedral_adaptive_remeshing( tr, - [target_edge_length](const typename Triangulation::Point& p) + [target_edge_length](const Triangulation::Point& p) {return target_edge_length; }, np); } - template - void tetrahedral_adaptive_remeshing(Triangulation& tr, - const SizingFunction& sizing, - const NamedParameters& np) + void tetrahedral_adaptive_remeshing( + CGAL::Triangulation_3& tr, + const SizingFunction& sizing, + const NamedParameters& np) { CGAL_assertion(tr.is_valid(true)); - typedef Triangulation Tr; + typedef CGAL::Triangulation_3 Tr; using boost::choose_param; using boost::get_param; @@ -312,9 +314,10 @@ namespace CGAL // Polygon_mesh_processing::parameters::all_default()); //} - template - void tetrahedral_adaptive_remeshing(Triangulation& tr, - const double& target_edge_length) + template + void tetrahedral_adaptive_remeshing( + CGAL::Triangulation_3& tr, + const double& target_edge_length) { tetrahedral_adaptive_remeshing(tr, target_edge_length, Polygon_mesh_processing::parameters::all_default()); From 69e64e5b0c69a939bbce5873207c898942389eb0 Mon Sep 17 00:00:00 2001 From: Jane Tournois Date: Fri, 24 Jan 2020 17:03:11 +0100 Subject: [PATCH 061/568] add the ability to use a C3t3 directly in the remesher instead of extracting the triangulation first --- .../internal/smooth_vertices.h | 4 +- .../tetrahedral_adaptive_remeshing_impl.h | 138 +++++++-- .../include/CGAL/tetrahedral_remeshing.h | 269 +++++++++++------- 3 files changed, 288 insertions(+), 123 deletions(-) diff --git a/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/smooth_vertices.h b/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/smooth_vertices.h index 4c435066988..905faa068c2 100644 --- a/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/smooth_vertices.h +++ b/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/smooth_vertices.h @@ -698,7 +698,7 @@ namespace internal typedef typename C3T3::Vertex_handle Vertex_handle; typedef typename C3T3::Cell_handle Cell_handle; typedef typename Tr::Finite_vertices_iterator Finite_vertices_iterator; - typedef typename C3T3::Point Point; + typedef typename Tr::Geom_traits::Point_3 Point_3; typedef typename Tr::Geom_traits::Vector_3 Vector_3; #ifdef CGAL_TETRAHEDRAL_REMESHING_VERBOSE @@ -781,7 +781,7 @@ namespace internal vit != tr.finite_vertices_end(); ++vit) { const std::size_t& vid = vertex_id.at(vit); - const Point new_pos(CGAL::ORIGIN + smoothing_vecs[vid]); + const Point_3 new_pos = CGAL::ORIGIN + smoothing_vecs[vid]; const Vector_3 move(point(vit->point()), new_pos); std::vector cells; diff --git a/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/tetrahedral_adaptive_remeshing_impl.h b/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/tetrahedral_adaptive_remeshing_impl.h index 038d8e40cad..cf975571b20 100644 --- a/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/tetrahedral_adaptive_remeshing_impl.h +++ b/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/tetrahedral_adaptive_remeshing_impl.h @@ -95,29 +95,32 @@ namespace internal , typename FacetIsConstrainedMap , typename CellSelector , typename Visitor - > + , typename CornerIndex = int + , typename CurveIndex = int + > class Adaptive_remesher { typedef Triangulation Tr; typedef typename Tr::Geom_traits::FT FT; - typedef typename CGAL::Mesh_complex_3_in_triangulation_3 C3t3; + typedef CGAL::Mesh_complex_3_in_triangulation_3 C3t3; typedef typename C3t3::Cell_handle Cell_handle; typedef typename C3t3::Vertex_handle Vertex_handle; typedef typename C3t3::Subdomain_index Subdomain_index; - typedef int Surface_patch_index; //only needed for is_in_complex() + typedef typename C3t3::Surface_patch_index Surface_patch_index; private: + C3t3 m_c3t3; const SizingFunction& m_sizing; const bool m_protect_boundaries; -// const bool m_adaptive;//adaptive sizing field TODO, outside remeshing - C3t3 m_c3t3; - Triangulation& m_tr; //backup to re-swap triangulations when done CellSelector m_cell_selector; Subdomain_index m_imaginary_index; Visitor& m_visitor; + Triangulation* m_tr_pbackup; //backup to re-swap triangulations when done + C3t3* m_c3t3_pbackup; + public: Adaptive_remesher(Triangulation& tr , const SizingFunction& sizing @@ -126,17 +129,43 @@ namespace internal , FacetIsConstrainedMap fcmap , CellSelector cell_selector , Visitor& visitor -// , const bool adaptive ) - : m_sizing(sizing) + : m_c3t3() + , m_sizing(sizing) , m_protect_boundaries(protect_boundaries) -// , m_adaptive(adaptive) - , m_c3t3() - , m_tr(tr) , m_cell_selector(cell_selector) , m_visitor(visitor) + , m_c3t3_pbackup(NULL) + , m_tr_pbackup(&tr) { m_c3t3.triangulation().swap(tr); + + init_c3t3(ecmap, fcmap); + +#ifdef CGAL_DUMP_REMESHING_STEPS + CGAL::Tetrahedral_remeshing::debug::dump_without_imaginary(m_c3t3.triangulation(), + "00-init-no-imaginary.mesh", m_imaginary_index); +#endif + } + + Adaptive_remesher(C3t3& c3t3 + , const SizingFunction& sizing + , const bool protect_boundaries + , EdgeIsConstrainedMap ecmap + , FacetIsConstrainedMap fcmap + , CellSelector cell_selector + , Visitor& visitor + ) + : m_c3t3() + , m_sizing(sizing) + , m_protect_boundaries(protect_boundaries) + , m_cell_selector(cell_selector) + , m_visitor(visitor) + , m_c3t3_pbackup(&c3t3) + , m_tr_pbackup(NULL) + { + m_c3t3.swap(c3t3); + init_c3t3(ecmap, fcmap); #ifdef CGAL_DUMP_REMESHING_STEPS @@ -301,20 +330,13 @@ namespace internal void finalize() { - m_tr.swap(m_c3t3.triangulation()); - } - - const Tr& triangulation() const - { - return m_c3t3.triangulation(); - } - - private: - Tr& tr() - { - return m_c3t3.triangulation(); + if (m_c3t3_pbackup != NULL) + m_c3t3_pbackup->swap(m_c3t3); + else + m_tr_pbackup->swap(m_c3t3.triangulation()); } +private: void init_c3t3(const EdgeIsConstrainedMap& ecmap, const FacetIsConstrainedMap& fcmap) { @@ -365,7 +387,8 @@ namespace internal Subdomain_index s2 = mf.first->subdomain_index(); if ( s1 != s2 || get(fcmap, f) - || get(fcmap, mf) ) + || get(fcmap, mf) + || (m_c3t3_pbackup == NULL && f.first->is_facet_on_surface(f.second))) { m_c3t3.add_to_complex(f, 1); @@ -461,6 +484,73 @@ namespace internal return true; } + + public: + Tr& tr() + { + return m_c3t3.triangulation(); + } + const Tr& tr() const + { + return m_c3t3.triangulation(); + } + + void remesh(const std::size_t& max_it, + const std::size_t& nb_extra_iterations) + { + preprocess(); + + std::size_t it_nb = 0; + while (it_nb++ < max_it) + { +#ifdef CGAL_TETRAHEDRAL_REMESHING_VERBOSE + std::cout << "# Iteration " << it_nb << " #" << std::endl; +#endif + if (!resolution_reached()) + { + split(); + collapse(); + } + flip(); + smooth(); + +#ifdef CGAL_TETRAHEDRAL_REMESHING_VERBOSE + std::cout << "# Iteration " << it_nb << " done : " + << tr().number_of_vertices() + << " vertices #" << std::endl; +#endif +#ifdef CGAL_DUMP_REMESHING_STEPS + std::ostringstream ossi; + ossi << "statistics_" << it_nb << ".txt"; + Tetrahedral_remeshing::internal::compute_statistics( + tr(), imaginary_index(), m_cell_selector, ossi.str().c_str()); +#endif + } + + while (it_nb++ < max_it + nb_extra_iterations) + { + // flip(); + // smooth(); + +#ifdef CGAL_TETRAHEDRAL_REMESHING_VERBOSE + std::cout << "# Iteration " << it_nb << " (flip and smooth only) done : " + << tr().number_of_vertices() + << " vertices #" << std::endl; +#endif +#ifdef CGAL_DUMP_REMESHING_STEPS + std::ostringstream ossi; + ossi << "statistics_" << it_nb << ".txt"; + Tetrahedral_remeshing::internal::compute_statistics( + tr(), imaginary_index(), m_cell_selector, ossi.str().c_str()); +#endif + } + + postprocess(); //remove imaginary cells + + finalize(); + //triangulation() is now empty + } + };//end class Adaptive_remesher }//end namespace internal }//end namespace Tetrahedral_remeshing diff --git a/Tetrahedral_remeshing/include/CGAL/tetrahedral_remeshing.h b/Tetrahedral_remeshing/include/CGAL/tetrahedral_remeshing.h index b5801bf077c..c1c1d98b9ba 100644 --- a/Tetrahedral_remeshing/include/CGAL/tetrahedral_remeshing.h +++ b/Tetrahedral_remeshing/include/CGAL/tetrahedral_remeshing.h @@ -39,6 +39,9 @@ namespace CGAL { + /////////////////////////////////////////////////// + ///////////////// TRIANGULATION_3 ///////////////// + /////////////////////////////////////////////////// /*! * \ingroup PkgTetrahedralRemeshingRef * remeshes a tetrahedral mesh. @@ -66,17 +69,17 @@ namespace CGAL * and are considered as constrained edges. * * - * @tparam Triangulation a 3-dimensional triangulation - * deriving from `Triangulation_3`, - * with geometric traits model of `RemeshingTriangulationTraits_3`, - * cell base model of `MeshCellBase_3` - * and vertex base model of `MeshVertexBase_3`. - * The class `Remeshing_triangulation_3` is a helper triangulation class that fits all - * these requirements. - * + * @tparam Traits is the geometric traits, model of `RemeshingTriangulationTraits_3` + * @tparam TDS is the triangulation data structure, model of ` TriangulationDataStructure_3`, + * with cell base model of `MeshCellBase_3` + * and vertex base model of `MeshVertexBase_3`. + * @tparam SLDS is an optional parameter for `Triangulation_3`, that + * specifies the type of the spatial lock data structure. * @tparam NamedParameters a sequence of \ref Remeshing_namedparameters "Named Parameters" * - * @param tr the triangulation to the remeshed + * @param tr the triangulation to the remeshed, of type `Triangulation_3`. + * `Remeshing_triangulation` is a helper class that satisfies all the requirements + * of its template parameters. * @param target_edge_length the uniform target edge length. This parameter provides a * mesh density target for the remeshing algorithm. * @param np optional sequence of \ref Remeshing_namedparameters "Named Parameters" @@ -109,11 +112,6 @@ namespace CGAL * @todo implement 1D smoothing for constrained edges * @todo implement sizing field instead of uniform target edge length */ - - // * @tparam SizingField model of `CGAL::Sizing_field` - //* \cgalParamBegin{ adaptive } If `true`, size of elements adapts - //* .... - //* \cgalParamEnd template void tetrahedral_adaptive_remeshing( @@ -128,7 +126,7 @@ namespace CGAL {return target_edge_length;}, np); } - + template void tetrahedral_adaptive_remeshing( @@ -177,14 +175,14 @@ namespace CGAL Tetrahedral_remeshing::internal::All_cells_selected()); typedef std::pair Edge_vv; - typedef Tetrahedral_remeshing::internal::No_constraint_pmap No_constraint; + typedef Tetrahedral_remeshing::internal::No_constraint_pmap No_edge; typedef typename boost::lookup_named_param_def < internal_np::edge_is_constrained_t, NamedParameters, - No_constraint//default + No_edge//default > ::type ECMap; - ECMap ecmap = choose_param(get_param(np, internal_np::edge_is_constrained) - , No_constraint()); + ECMap ecmap = choose_param(get_param(np, internal_np::edge_is_constrained), + No_edge()); typedef typename Tr::Facet Facet; typedef Tetrahedral_remeshing::internal::No_constraint_pmap No_facet; @@ -193,8 +191,8 @@ namespace CGAL NamedParameters, No_facet//default > ::type FCMap; - FCMap fcmap = choose_param(get_param(np, internal_np::facet_is_constrained) - , No_facet()); + FCMap fcmap = choose_param(get_param(np, internal_np::facet_is_constrained), + No_facet()); typedef typename boost::lookup_named_param_def < internal_np::remeshing_visitor_t, @@ -219,70 +217,19 @@ namespace CGAL Tr, SizingFunction, ECMap, FCMap, SelectionFunctor, Visitor> Remesher; Remesher remesher(tr, sizing, protect , ecmap, fcmap - , cell_select, visitor - /*, adaptive*/); + , cell_select + , visitor); #ifdef CGAL_TETRAHEDRAL_REMESHING_VERBOSE std::cout << "done." << std::endl; Tetrahedral_remeshing::internal::compute_statistics( - remesher.triangulation(), + remesher.tr(), remesher.imaginary_index(), cell_select, "statistics_begin.txt"); #endif - remesher.preprocess(); - - std::size_t it_nb = 0; - while (it_nb++ < max_it) - { -#ifdef CGAL_TETRAHEDRAL_REMESHING_VERBOSE - std::cout << "# Iteration " << it_nb << " #" << std::endl; -#endif - if (!remesher.resolution_reached()) - { - remesher.split(); - remesher.collapse(); - } - remesher.flip(); -// remesher.smooth(); - -#ifdef CGAL_TETRAHEDRAL_REMESHING_VERBOSE - std::cout << "# Iteration " << it_nb << " done : " - << remesher.triangulation().number_of_vertices() - << " vertices #" << std::endl; -#endif -#ifdef CGAL_DUMP_REMESHING_STEPS - std::ostringstream ossi; - ossi << "statistics_" << it_nb << ".txt"; - Tetrahedral_remeshing::internal::compute_statistics( - remesher.triangulation(), - remesher.imaginary_index(), cell_select, ossi.str().c_str()); -#endif - } - + // perform remeshing std::size_t nb_extra_iterations = 3; - while (it_nb++ < max_it + nb_extra_iterations) - { -// remesher.flip(); -// remesher.smooth(); - -#ifdef CGAL_TETRAHEDRAL_REMESHING_VERBOSE - std::cout << "# Iteration " << it_nb << " (flip and smooth only) done : " - << remesher.triangulation().number_of_vertices() - << " vertices #" << std::endl; -#endif -#ifdef CGAL_DUMP_REMESHING_STEPS - std::ostringstream ossi; - ossi << "statistics_" << it_nb << ".txt"; - Tetrahedral_remeshing::internal::compute_statistics( - remesher.triangulation(), - remesher.imaginary_index(), cell_select, ossi.str().c_str()); -#endif - } - - remesher.postprocess(); - - remesher.finalize(); - //remesher.triangulation() is now empty + remesher.remesh(max_it, nb_extra_iterations); #ifdef CGAL_TETRAHEDRAL_REMESHING_DEBUG const double angle_bound = 5.0; @@ -295,34 +242,162 @@ namespace CGAL #endif } - - //template - //void tetrahedral_adaptive_remeshing(Triangulation& tr, - // const double& target_edge_length, - // const NamedParameters& np) - //{ - // typedef typename Triangulation::Geom_traits K; - // CGAL::Uniform_sizing_field sizing_field(target_edge_length); - // tetrahedral_adaptive_remeshing(tr, sizing_field, np); - //} - - //template - //void tetrahedral_adaptive_remeshing(Triangulation& tr, - // const SizingField& sizing_field) - //{ - // tetrahedral_adaptive_remeshing(tr, sizing_field, - // Polygon_mesh_processing::parameters::all_default()); - //} - template void tetrahedral_adaptive_remeshing( CGAL::Triangulation_3& tr, const double& target_edge_length) { tetrahedral_adaptive_remeshing(tr, target_edge_length, - Polygon_mesh_processing::parameters::all_default()); + CGAL::parameters::all_default()); } + /////////////////////////////////////////////////// + /////// MESH_COMPLEX_3_IN_TRIANGULATION_3 ///////// + /////////////////////////////////////////////////// + + template + void tetrahedral_adaptive_remeshing( + CGAL::Mesh_complex_3_in_triangulation_3& c3t3, + const double& target_edge_length, + const NamedParameters& np) + { + tetrahedral_adaptive_remeshing( + c3t3, + [target_edge_length](const typename Tr::Point& p) + {return target_edge_length; }, + np); + } + + template + void tetrahedral_adaptive_remeshing( + CGAL::Mesh_complex_3_in_triangulation_3& c3t3, + const float& target_edge_length, + const NamedParameters& np) + { + tetrahedral_adaptive_remeshing( + c3t3, + [target_edge_length](const typename Tr::Point& p) + {return target_edge_length; }, + np); + } + + template + void tetrahedral_adaptive_remeshing( + CGAL::Mesh_complex_3_in_triangulation_3& c3t3, + const double& target_edge_length) + { + return tetrahedral_adaptive_remeshing(c3t3, target_edge_length, + CGAL::parameters::all_default()); + } + + template + void tetrahedral_adaptive_remeshing( + CGAL::Mesh_complex_3_in_triangulation_3& c3t3, + const SizingFunction& sizing, + const NamedParameters& np) + { + CGAL_assertion(tr.is_valid(true)); + + using boost::choose_param; + using boost::get_param; + + bool remesh_surfaces = choose_param(get_param(np, internal_np::remesh_boundaries), + true); + bool protect = !remesh_surfaces; + std::size_t max_it = choose_param(get_param(np, internal_np::number_of_iterations), 1); + + typedef typename boost::lookup_named_param_def < + internal_np::cell_selector_t, + NamedParameters, + Tetrahedral_remeshing::internal::All_cells_selected//default + > ::type SelectionFunctor; + SelectionFunctor cell_select + = choose_param(get_param(np, internal_np::cell_selector), + Tetrahedral_remeshing::internal::All_cells_selected()); + + typedef std::pair Edge_vv; + typedef Tetrahedral_remeshing::internal::No_constraint_pmap No_edge; + typedef typename boost::lookup_named_param_def < + internal_np::edge_is_constrained_t, + NamedParameters, + No_edge//default + > ::type ECMap; + ECMap ecmap = choose_param(get_param(np, internal_np::edge_is_constrained), + No_edge()); + + typedef typename Tr::Facet Facet; + typedef Tetrahedral_remeshing::internal::No_constraint_pmap No_facet; + typedef typename boost::lookup_named_param_def < + internal_np::facet_is_constrained_t, + NamedParameters, + No_facet//default + > ::type FCMap; + FCMap fcmap = choose_param(get_param(np, internal_np::facet_is_constrained), + No_facet()); + + typedef typename boost::lookup_named_param_def < + internal_np::remeshing_visitor_t, + NamedParameters, + Tetrahedral_remeshing::internal::Default_remeshing_visitor + > ::type Visitor; + Visitor visitor + = choose_param(get_param(np, internal_np::remeshing_visitor), + Tetrahedral_remeshing::internal::Default_remeshing_visitor()); + +#ifdef CGAL_TETRAHEDRAL_REMESHING_VERBOSE + std::cout << "Tetrahedral remeshing (" + << "nb_iter = " << max_it + << "protect = " << std::boolalpha << protect << ", " + << ")" << std::endl; + + std::cout << "Init tetrahedral remeshing..."; + std::cout.flush(); +#endif + + typedef Tetrahedral_remeshing::internal::Adaptive_remesher< + Tr, SizingFunction, ECMap, FCMap, SelectionFunctor, + Visitor, + CornerIndex, CurveIndex + > Remesher; + Remesher remesher(c3t3, sizing, protect + , ecmap, fcmap + , cell_select + , visitor); + +#ifdef CGAL_TETRAHEDRAL_REMESHING_VERBOSE + std::cout << "done." << std::endl; + Tetrahedral_remeshing::internal::compute_statistics( + remesher.tr(), + remesher.imaginary_index(), cell_select, "statistics_begin.txt"); +#endif + + // perform remeshing + std::size_t nb_extra_iterations = 3; + remesher.remesh(max_it, nb_extra_iterations); + +#ifdef CGAL_TETRAHEDRAL_REMESHING_DEBUG + const double angle_bound = 5.0; + Tetrahedral_remeshing::debug::dump_cells_with_small_dihedral_angle( + c3t3.triangulation(), + angle_bound, remesher.imaginary_index(), cell_select, "bad_cells.mesh"); +#endif +#ifdef CGAL_TETRAHEDRAL_REMESHING_VERBOSE + Tetrahedral_remeshing::internal::compute_statistics( + c3t3.triangulation(), + remesher.imaginary_index(), cell_select, "statistics_end.txt"); +#endif + } + + }//end namespace CGAL #endif //TETRAHEDRAL_REMESHING_H From b996cbd020eea242a03b7b237036baa738a844ac Mon Sep 17 00:00:00 2001 From: Jane Tournois Date: Fri, 24 Jan 2020 17:04:53 +0100 Subject: [PATCH 062/568] document facet_is_constrained_map --- .../doc/Tetrahedral_remeshing/NamedParameters.txt | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/Tetrahedral_remeshing/doc/Tetrahedral_remeshing/NamedParameters.txt b/Tetrahedral_remeshing/doc/Tetrahedral_remeshing/NamedParameters.txt index 999a7b1eb62..34fb4118d82 100644 --- a/Tetrahedral_remeshing/doc/Tetrahedral_remeshing/NamedParameters.txt +++ b/Tetrahedral_remeshing/doc/Tetrahedral_remeshing/NamedParameters.txt @@ -65,6 +65,18 @@ It must be default constructible. Default: a default property map where no edge is constrained \cgalNPEnd +\cgalNPBegin{facet_is_constrained_map} +\anchor Remeshing_facet_is_constrained_map +is a property map containing information about facets of the input triangulation +being marked as constrained or not.\n +Type: a class model of `ReadPropertyMap` with +`Triangulation::%Facet` as key type and `bool` as value type. +It is not updated throughout the remeshing process. +It must be default constructible. +\n +Default: a default property map where no facet is constrained +\cgalNPEnd + \cgalNPBegin{cell_is_selected_map} \anchor Remeshing_cell_is_selected_map is a property map containing information about cells of the input triangulation From bac4b84e85405e6769c3af3885678b66f25ecc9d Mon Sep 17 00:00:00 2001 From: Jane Tournois Date: Fri, 24 Jan 2020 17:07:33 +0100 Subject: [PATCH 063/568] update plugin --- .../Tetrahedral_remeshing_plugin.cpp | 20 ++++++++++--------- 1 file changed, 11 insertions(+), 9 deletions(-) diff --git a/Polyhedron/demo/Polyhedron/Plugins/Tetrahedral_remeshing/Tetrahedral_remeshing_plugin.cpp b/Polyhedron/demo/Polyhedron/Plugins/Tetrahedral_remeshing/Tetrahedral_remeshing_plugin.cpp index 59239618a18..cac694edaf8 100644 --- a/Polyhedron/demo/Polyhedron/Plugins/Tetrahedral_remeshing/Tetrahedral_remeshing_plugin.cpp +++ b/Polyhedron/demo/Polyhedron/Plugins/Tetrahedral_remeshing/Tetrahedral_remeshing_plugin.cpp @@ -12,6 +12,9 @@ #include #include +#include +#include + #include #include #include @@ -23,7 +26,6 @@ #include "ui_Tetrahedral_remeshing_dialog.h" - using namespace CGAL::Three; class Polyhedron_demo_tetrahedral_remeshing_plugin : public QObject, @@ -34,6 +36,9 @@ class Polyhedron_demo_tetrahedral_remeshing_plugin : Q_PLUGIN_METADATA(IID "com.geometryfactory.PolyhedronDemo.PluginInterface/1.0" FILE "tetrahedral_remeshing_plugin.json") public: + typedef CGAL::Tetrahedral_remeshing::Remeshing_triangulation_3 Remeshing_triangulation; + + void init(QMainWindow* mainWindow, Scene_interface* scene_interface, Messages_interface*) { this->scene = scene_interface; @@ -58,8 +63,6 @@ public: public Q_SLOTS: void tetrahedral_remeshing() { - typedef CGAL::Tetrahedral_remeshing::Remeshing_triangulation_3 Remeshing_triangulation; - const Scene_interface::Item_id index = scene->mainSelectionIndex(); Scene_c3t3_item* c3t3_item = @@ -89,16 +92,15 @@ public Q_SLOTS: QTime time; time.start(); - CGAL::tetrahedral_adaptive_remeshing(c3t3_item->c3t3().triangulation(), - target_length, - CGAL::parameters::remesh_boundaries(!protect) - .number_of_iterations(nb_iter)); + CGAL::tetrahedral_adaptive_remeshing( + c3t3_item->c3t3(), + target_length, + CGAL::parameters::remesh_boundaries(!protect) + .number_of_iterations(nb_iter)); std::cout << "Remeshing done (" << time.elapsed() << " ms)" << std::endl; time.restart(); - c3t3_item->c3t3().clear(); - c3t3_item->c3t3_changed(); this->scene->itemChanged(index); From ee7e7459de892a4b29c41d0fb071a5e7a30662b4 Mon Sep 17 00:00:00 2001 From: Jane Tournois Date: Tue, 28 Jan 2020 09:54:52 +0100 Subject: [PATCH 064/568] remove useless typedef --- .../Tetrahedral_remeshing/Tetrahedral_remeshing_plugin.cpp | 3 --- 1 file changed, 3 deletions(-) diff --git a/Polyhedron/demo/Polyhedron/Plugins/Tetrahedral_remeshing/Tetrahedral_remeshing_plugin.cpp b/Polyhedron/demo/Polyhedron/Plugins/Tetrahedral_remeshing/Tetrahedral_remeshing_plugin.cpp index cac694edaf8..a78b34c8aa2 100644 --- a/Polyhedron/demo/Polyhedron/Plugins/Tetrahedral_remeshing/Tetrahedral_remeshing_plugin.cpp +++ b/Polyhedron/demo/Polyhedron/Plugins/Tetrahedral_remeshing/Tetrahedral_remeshing_plugin.cpp @@ -36,9 +36,6 @@ class Polyhedron_demo_tetrahedral_remeshing_plugin : Q_PLUGIN_METADATA(IID "com.geometryfactory.PolyhedronDemo.PluginInterface/1.0" FILE "tetrahedral_remeshing_plugin.json") public: - typedef CGAL::Tetrahedral_remeshing::Remeshing_triangulation_3 Remeshing_triangulation; - - void init(QMainWindow* mainWindow, Scene_interface* scene_interface, Messages_interface*) { this->scene = scene_interface; From bb0a407ed0ab0ab1eb298e2ac2f965abec20bece Mon Sep 17 00:00:00 2001 From: Jane Tournois Date: Tue, 28 Jan 2020 09:55:20 +0100 Subject: [PATCH 065/568] improve doc --- .../doc/Tetrahedral_remeshing/NamedParameters.txt | 14 ++++++++------ .../include/CGAL/tetrahedral_remeshing.h | 7 ++++--- 2 files changed, 12 insertions(+), 9 deletions(-) diff --git a/Tetrahedral_remeshing/doc/Tetrahedral_remeshing/NamedParameters.txt b/Tetrahedral_remeshing/doc/Tetrahedral_remeshing/NamedParameters.txt index 34fb4118d82..953042d5f33 100644 --- a/Tetrahedral_remeshing/doc/Tetrahedral_remeshing/NamedParameters.txt +++ b/Tetrahedral_remeshing/doc/Tetrahedral_remeshing/NamedParameters.txt @@ -41,13 +41,15 @@ in the mesh.\n \cgalNPBegin{remesh_boundaries} \anchor Remeshing_remesh_boundaries a Boolean that states whether the boundaries should be remeshed or -exactly preserved by the remeshing -process. Boundaries are between the exterior and the interior, -between two subdomains, and between the areas selected or not for remeshing -(cf \ref Remeshing_cell_is_selected_map). -If `true`, they are remeshed. Otherwise, they cannot be modified by the remeshing process.\n +exactly preserved by the remeshing process. +Boundaries are between the exterior and the interior, +between two subdomains, between the areas selected or not for remeshing +(cf \ref Remeshing_cell_is_selected_map), +or defined by \ref Remeshing_edge_is_constrained_map +and \ref Remeshing_facet_is_constrained_map. +If `true`, they are remeshed. Otherwise, they cannot be modified at all by the remeshing process.\n \b Type : `bool` \n -\b Default value is `false` +\b Default value is `true` \cgalNPEnd \cgalNPBegin{edge_is_constrained_map} diff --git a/Tetrahedral_remeshing/include/CGAL/tetrahedral_remeshing.h b/Tetrahedral_remeshing/include/CGAL/tetrahedral_remeshing.h index c1c1d98b9ba..d8bebde4155 100644 --- a/Tetrahedral_remeshing/include/CGAL/tetrahedral_remeshing.h +++ b/Tetrahedral_remeshing/include/CGAL/tetrahedral_remeshing.h @@ -70,7 +70,8 @@ namespace CGAL * * * @tparam Traits is the geometric traits, model of `RemeshingTriangulationTraits_3` - * @tparam TDS is the triangulation data structure, model of ` TriangulationDataStructure_3`, + * @tparam TDS is the triangulation data structure for `Triangulation_3`, + * model of ` TriangulationDataStructure_3`, * with cell base model of `MeshCellBase_3` * and vertex base model of `MeshVertexBase_3`. * @tparam SLDS is an optional parameter for `Triangulation_3`, that @@ -90,8 +91,8 @@ namespace CGAL * performed (listed in the above description) * \cgalParamEnd * \cgalParamBegin{remesh_boundaries} If `false`, none of the volume boundaries can be modified. - * Otherwise, the geometry is preserved, but atomic operations can be performed on the - * surfaces, and along feature polylines. + * Otherwise, the topology is preserved, but atomic operations can be performed on the + * surfaces, and along feature polylines, such that boundaries are remeshed. * \cgalParamEnd * \cgalParamBegin{edge_is_constrained_map} a property map containing the * constrained - or - not status of each edge of `tr`. A constrained edge can be split From d3db64f6800d5ee029ff56e6039a4346caa0fc3b Mon Sep 17 00:00:00 2001 From: Jane Tournois Date: Tue, 28 Jan 2020 09:58:56 +0100 Subject: [PATCH 066/568] add binary dump --- .../internal/tetrahedral_adaptive_remeshing_impl.h | 6 ++++++ .../internal/tetrahedral_remeshing_helpers.h | 10 ++++++++++ 2 files changed, 16 insertions(+) diff --git a/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/tetrahedral_adaptive_remeshing_impl.h b/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/tetrahedral_adaptive_remeshing_impl.h index cf975571b20..35c55bfaf02 100644 --- a/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/tetrahedral_adaptive_remeshing_impl.h +++ b/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/tetrahedral_adaptive_remeshing_impl.h @@ -193,6 +193,7 @@ namespace internal CGAL::Tetrahedral_remeshing::debug::dump_triangulation_cells(tr(), "0-preprocess.mesh"); CGAL::Tetrahedral_remeshing::debug::dump_without_imaginary(tr(), "0-preprocess-no-imaginary.mesh", m_imaginary_index); + CGAL::Tetrahedral_remeshing::debug::dump_binary(m_c3t3, "0-preprocess.binary.cgal"); #endif #ifdef CGAL_TETRAHEDRAL_REMESHING_VERBOSE std::cout << "done." << std::endl; @@ -213,6 +214,7 @@ namespace internal CGAL::Tetrahedral_remeshing::debug::dump_triangulation_cells(tr(), "1-split.mesh"); CGAL::Tetrahedral_remeshing::debug::dump_without_imaginary(tr(), "1-split-no-imaginary.mesh", m_imaginary_index); + CGAL::Tetrahedral_remeshing::debug::dump_binary(m_c3t3, "1-split.binary.cgal"); #endif } @@ -233,6 +235,7 @@ namespace internal "2-collapse.mesh"); CGAL::Tetrahedral_remeshing::debug::dump_without_imaginary(tr(), "2-collapse-no-imaginary.mesh", m_imaginary_index); + CGAL::Tetrahedral_remeshing::debug::dump_binary(m_c3t3, "2-collapse.binary.cgal"); #endif } @@ -247,6 +250,7 @@ namespace internal "3-flip.mesh"); CGAL::Tetrahedral_remeshing::debug::dump_without_imaginary(tr(), "3-flip-no-imaginary.mesh", m_imaginary_index); + CGAL::Tetrahedral_remeshing::debug::dump_binary(m_c3t3, "3-flip.binary.cgal"); #endif } @@ -261,6 +265,7 @@ namespace internal "4-smooth.mesh"); CGAL::Tetrahedral_remeshing::debug::dump_without_imaginary(tr(), "4-smooth-no-imaginary.mesh", m_imaginary_index); + CGAL::Tetrahedral_remeshing::debug::dump_binary(m_c3t3, "4-smooth.binary.cgal"); #endif } @@ -322,6 +327,7 @@ namespace internal "99-postprocess.mesh"); CGAL::Tetrahedral_remeshing::debug::dump_without_imaginary(tr(), "99-postprocess-no-imaginary.mesh", m_imaginary_index); + CGAL::Tetrahedral_remeshing::debug::dump_binary(m_c3t3, "99-postprocess.binary.cgal"); #endif #ifdef CGAL_TETRAHEDRAL_REMESHING_VERBOSE std::cout << "done." << std::endl; diff --git a/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/tetrahedral_remeshing_helpers.h b/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/tetrahedral_remeshing_helpers.h index 384499f376b..315a876f72c 100644 --- a/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/tetrahedral_remeshing_helpers.h +++ b/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/tetrahedral_remeshing_helpers.h @@ -28,6 +28,8 @@ #include #include +#include + namespace CGAL { namespace Tetrahedral_remeshing @@ -1392,6 +1394,14 @@ namespace Tetrahedral_remeshing dump_cells(cells, indices, filename); } + template + void dump_binary(const C3t3& c3t3, const char* filename) + { + std::ofstream os(filename); + CGAL::Mesh_3::save_binary_file(os, c3t3); + os.close(); + } + //template //void dump_edges(const VertexPairsSet& edges, const char* filename) //{ From f53639ef83925f4957b13723ec6816a591fb2ab0 Mon Sep 17 00:00:00 2001 From: Jane Tournois Date: Tue, 28 Jan 2020 17:50:14 +0100 Subject: [PATCH 067/568] use new API for named parameters --- .../include/CGAL/tetrahedral_remeshing.h | 36 +++++++++---------- 1 file changed, 18 insertions(+), 18 deletions(-) diff --git a/Tetrahedral_remeshing/include/CGAL/tetrahedral_remeshing.h b/Tetrahedral_remeshing/include/CGAL/tetrahedral_remeshing.h index d8bebde4155..7abe69062e0 100644 --- a/Tetrahedral_remeshing/include/CGAL/tetrahedral_remeshing.h +++ b/Tetrahedral_remeshing/include/CGAL/tetrahedral_remeshing.h @@ -30,7 +30,7 @@ #include #include -#include +#include #include #ifdef CGAL_DUMP_REMESHING_STEPS @@ -155,15 +155,15 @@ namespace CGAL typedef CGAL::Triangulation_3 Tr; - using boost::choose_param; - using boost::get_param; + using parameters::choose_parameter; + using parameters::get_parameter; - bool remesh_surfaces = choose_param(get_param(np, internal_np::remesh_boundaries), + bool remesh_surfaces = choose_parameter(get_parameter(np, internal_np::remesh_boundaries), true); bool protect = !remesh_surfaces; - // bool adaptive = choose_param(get_param(np, internal_np::adaptive_size), + // bool adaptive = choose_parameter(get_parameter(np, internal_np::adaptive_size), // false); - std::size_t max_it = choose_param(get_param(np, internal_np::number_of_iterations), + std::size_t max_it = choose_parameter(get_parameter(np, internal_np::number_of_iterations), 1); typedef typename boost::lookup_named_param_def < @@ -172,7 +172,7 @@ namespace CGAL Tetrahedral_remeshing::internal::All_cells_selected//default > ::type SelectionFunctor; SelectionFunctor cell_select - = choose_param(get_param(np, internal_np::cell_selector), + = choose_parameter(get_parameter(np, internal_np::cell_selector), Tetrahedral_remeshing::internal::All_cells_selected()); typedef std::pair Edge_vv; @@ -182,7 +182,7 @@ namespace CGAL NamedParameters, No_edge//default > ::type ECMap; - ECMap ecmap = choose_param(get_param(np, internal_np::edge_is_constrained), + ECMap ecmap = choose_parameter(get_parameter(np, internal_np::edge_is_constrained), No_edge()); typedef typename Tr::Facet Facet; @@ -192,7 +192,7 @@ namespace CGAL NamedParameters, No_facet//default > ::type FCMap; - FCMap fcmap = choose_param(get_param(np, internal_np::facet_is_constrained), + FCMap fcmap = choose_parameter(get_parameter(np, internal_np::facet_is_constrained), No_facet()); typedef typename boost::lookup_named_param_def < @@ -201,7 +201,7 @@ namespace CGAL Tetrahedral_remeshing::internal::Default_remeshing_visitor > ::type Visitor; Visitor visitor - = choose_param(get_param(np, internal_np::remeshing_visitor), + = choose_parameter(get_parameter(np, internal_np::remeshing_visitor), Tetrahedral_remeshing::internal::Default_remeshing_visitor()); #ifdef CGAL_TETRAHEDRAL_REMESHING_VERBOSE @@ -308,13 +308,13 @@ namespace CGAL { CGAL_assertion(tr.is_valid(true)); - using boost::choose_param; - using boost::get_param; + using parameters::get_parameter; + using parameters::choose_parameter; - bool remesh_surfaces = choose_param(get_param(np, internal_np::remesh_boundaries), + bool remesh_surfaces = choose_parameter(get_parameter(np, internal_np::remesh_boundaries), true); bool protect = !remesh_surfaces; - std::size_t max_it = choose_param(get_param(np, internal_np::number_of_iterations), 1); + std::size_t max_it = choose_parameter(get_parameter(np, internal_np::number_of_iterations), 1); typedef typename boost::lookup_named_param_def < internal_np::cell_selector_t, @@ -322,7 +322,7 @@ namespace CGAL Tetrahedral_remeshing::internal::All_cells_selected//default > ::type SelectionFunctor; SelectionFunctor cell_select - = choose_param(get_param(np, internal_np::cell_selector), + = choose_parameter(get_parameter(np, internal_np::cell_selector), Tetrahedral_remeshing::internal::All_cells_selected()); typedef std::pair Edge_vv; @@ -332,7 +332,7 @@ namespace CGAL NamedParameters, No_edge//default > ::type ECMap; - ECMap ecmap = choose_param(get_param(np, internal_np::edge_is_constrained), + ECMap ecmap = choose_parameter(get_parameter(np, internal_np::edge_is_constrained), No_edge()); typedef typename Tr::Facet Facet; @@ -342,7 +342,7 @@ namespace CGAL NamedParameters, No_facet//default > ::type FCMap; - FCMap fcmap = choose_param(get_param(np, internal_np::facet_is_constrained), + FCMap fcmap = choose_parameter(get_parameter(np, internal_np::facet_is_constrained), No_facet()); typedef typename boost::lookup_named_param_def < @@ -351,7 +351,7 @@ namespace CGAL Tetrahedral_remeshing::internal::Default_remeshing_visitor > ::type Visitor; Visitor visitor - = choose_param(get_param(np, internal_np::remeshing_visitor), + = choose_parameter(get_parameter(np, internal_np::remeshing_visitor), Tetrahedral_remeshing::internal::Default_remeshing_visitor()); #ifdef CGAL_TETRAHEDRAL_REMESHING_VERBOSE From a791ea131e6716f021cf14adc5498ea995c142d8 Mon Sep 17 00:00:00 2001 From: Jane Tournois Date: Thu, 30 Jan 2020 11:13:47 +0100 Subject: [PATCH 068/568] test the validity of the TDS only when the input is a c3t3, the internal triangulation can be Delaunay or Regular remeshing it breaks its validity "on purpose", do we should not test triangulation validity --- .../internal/tetrahedral_adaptive_remeshing_impl.h | 12 ++++++------ .../include/CGAL/tetrahedral_remeshing.h | 2 +- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/tetrahedral_adaptive_remeshing_impl.h b/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/tetrahedral_adaptive_remeshing_impl.h index 35c55bfaf02..a8399c1e539 100644 --- a/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/tetrahedral_adaptive_remeshing_impl.h +++ b/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/tetrahedral_adaptive_remeshing_impl.h @@ -187,7 +187,7 @@ namespace internal #endif add_layer_of_imaginary_tets(tr(), m_imaginary_index); - CGAL_assertion(tr().is_valid(true)); + CGAL_assertion(tr().tds().is_valid(true)); #ifdef CGAL_DUMP_REMESHING_STEPS CGAL::Tetrahedral_remeshing::debug::dump_triangulation_cells(tr(), "0-preprocess.mesh"); @@ -209,7 +209,7 @@ namespace internal split_long_edges(m_c3t3, emax, m_protect_boundaries, m_imaginary_index, m_cell_selector, m_visitor); - CGAL_assertion(tr().is_valid(true)); + CGAL_assertion(tr().tds().is_valid(true)); #ifdef CGAL_DUMP_REMESHING_STEPS CGAL::Tetrahedral_remeshing::debug::dump_triangulation_cells(tr(), "1-split.mesh"); CGAL::Tetrahedral_remeshing::debug::dump_without_imaginary(tr(), @@ -229,7 +229,7 @@ namespace internal m_imaginary_index, m_cell_selector, m_visitor); - CGAL_assertion(tr().is_valid(true)); + CGAL_assertion(tr().tds().is_valid(true)); #ifdef CGAL_DUMP_REMESHING_STEPS CGAL::Tetrahedral_remeshing::debug::dump_triangulation_cells(tr(), "2-collapse.mesh"); @@ -244,7 +244,7 @@ namespace internal flip_edges(m_c3t3, m_imaginary_index, m_protect_boundaries, m_cell_selector, m_visitor); - CGAL_assertion(tr().is_valid(true)); + CGAL_assertion(tr().tds().is_valid(true)); #ifdef CGAL_DUMP_REMESHING_STEPS CGAL::Tetrahedral_remeshing::debug::dump_triangulation_cells(tr(), "3-flip.mesh"); @@ -259,7 +259,7 @@ namespace internal smooth_vertices_new(m_c3t3, m_imaginary_index, m_protect_boundaries, m_cell_selector); - CGAL_assertion(tr().is_valid(true)); + CGAL_assertion(tr().tds().is_valid(true)); #ifdef CGAL_DUMP_REMESHING_STEPS CGAL::Tetrahedral_remeshing::debug::dump_triangulation_cells(tr(), "4-smooth.mesh"); @@ -321,7 +321,7 @@ namespace internal } } - CGAL_assertion(tr().is_valid(true)); + CGAL_assertion(tr().tds().is_valid(true)); #ifdef CGAL_DUMP_REMESHING_STEPS CGAL::Tetrahedral_remeshing::debug::dump_triangulation_cells(tr(), "99-postprocess.mesh"); diff --git a/Tetrahedral_remeshing/include/CGAL/tetrahedral_remeshing.h b/Tetrahedral_remeshing/include/CGAL/tetrahedral_remeshing.h index 7abe69062e0..e1d89e09cc5 100644 --- a/Tetrahedral_remeshing/include/CGAL/tetrahedral_remeshing.h +++ b/Tetrahedral_remeshing/include/CGAL/tetrahedral_remeshing.h @@ -306,7 +306,7 @@ namespace CGAL const SizingFunction& sizing, const NamedParameters& np) { - CGAL_assertion(tr.is_valid(true)); + CGAL_assertion(c3t3.triangulation().tds().is_valid(true)); using parameters::get_parameter; using parameters::choose_parameter; From 2e5174f349d0100205bdf6eb575bff3e2df8e401 Mon Sep 17 00:00:00 2001 From: Jane Tournois Date: Thu, 30 Jan 2020 13:19:35 +0100 Subject: [PATCH 069/568] fix binary ofstream --- .../internal/tetrahedral_remeshing_helpers.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/tetrahedral_remeshing_helpers.h b/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/tetrahedral_remeshing_helpers.h index 315a876f72c..f60a54a84ac 100644 --- a/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/tetrahedral_remeshing_helpers.h +++ b/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/tetrahedral_remeshing_helpers.h @@ -1397,7 +1397,7 @@ namespace Tetrahedral_remeshing template void dump_binary(const C3t3& c3t3, const char* filename) { - std::ofstream os(filename); + std::ofstream os(filename, std::ios::binary | std::ios::out); CGAL::Mesh_3::save_binary_file(os, c3t3); os.close(); } From 7a3ec25e59405297351581ef771f27bd48861eba Mon Sep 17 00:00:00 2001 From: Jane Tournois Date: Thu, 30 Jan 2020 14:45:08 +0100 Subject: [PATCH 070/568] update c3t3_item display after remeshing --- .../Tetrahedral_remeshing/Tetrahedral_remeshing_plugin.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Polyhedron/demo/Polyhedron/Plugins/Tetrahedral_remeshing/Tetrahedral_remeshing_plugin.cpp b/Polyhedron/demo/Polyhedron/Plugins/Tetrahedral_remeshing/Tetrahedral_remeshing_plugin.cpp index a78b34c8aa2..e2aaa8d3738 100644 --- a/Polyhedron/demo/Polyhedron/Plugins/Tetrahedral_remeshing/Tetrahedral_remeshing_plugin.cpp +++ b/Polyhedron/demo/Polyhedron/Plugins/Tetrahedral_remeshing/Tetrahedral_remeshing_plugin.cpp @@ -96,8 +96,8 @@ public Q_SLOTS: .number_of_iterations(nb_iter)); std::cout << "Remeshing done (" << time.elapsed() << " ms)" << std::endl; - time.restart(); + c3t3_item->invalidateOpenGLBuffers(); c3t3_item->c3t3_changed(); this->scene->itemChanged(index); From ea2c06a317e1f3a41c8139d56a767ebc9bd27bde Mon Sep 17 00:00:00 2001 From: Jane Tournois Date: Thu, 30 Jan 2020 14:45:51 +0100 Subject: [PATCH 071/568] avoid generation of a second cut plane for the c3t3 after display update --- Polyhedron/demo/Polyhedron/Scene_c3t3_item.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/Polyhedron/demo/Polyhedron/Scene_c3t3_item.cpp b/Polyhedron/demo/Polyhedron/Scene_c3t3_item.cpp index 685893acac1..a4505e4c698 100644 --- a/Polyhedron/demo/Polyhedron/Scene_c3t3_item.cpp +++ b/Polyhedron/demo/Polyhedron/Scene_c3t3_item.cpp @@ -1454,7 +1454,7 @@ void Scene_c3t3_item_priv::computeElements() alphaSlider->setMaximum(255); alphaSlider->setValue(255); } - + positions_poly.clear(); normals.clear(); f_colors.clear(); @@ -1466,6 +1466,7 @@ void Scene_c3t3_item_priv::computeElements() //The grid { + positions_grid.resize(0); float x = (2 * (float)complex_diag()) / 10.0; float y = (2 * (float)complex_diag()) / 10.0; From e82ea5de96bc1beb186449cff4998ebe7cfa5b2b Mon Sep 17 00:00:00 2001 From: Laurent Rineau Date: Wed, 29 Jan 2020 17:13:11 +0100 Subject: [PATCH 072/568] Add move-semantic to Compact_container That required a refactoring the timestamper feature. And the explanation why is quite long... Let's do it. The CGAL triangulations use the `Rebind_TDS` feature. During the instanciation of `Compact_container` it is important that `T` is allowed to be incomplete, otherwise the circular dependencies between TDS and Vertex/Cell cannot be resolved by the compiler. In previous implementation of the timestamper, to allow `T` to be an incomplete type, the compact container only carried a *point* to the time stamper, allocated on the heap. A moved-from compact container would only be valid if one recreated a time stamper for it on the head in the move-constructor. As I want move operations to be `noexcept`, I needed to change that implementation. Now the triangulation always carries a time stamp counter (`std::size`), independently of the type `T`, and the time stamper is an empty class, with static methods. That allows `T` to be incomplete during the declaration of `Compact_container`. --- .../include/CGAL/Compact_container.h | 148 +++++++++++------- .../CGAL/Concurrent_compact_container.h | 59 ++++--- STL_Extension/include/CGAL/Time_stamper.h | 33 +--- .../STL_Extension/test_Compact_container.cpp | 14 +- .../test_Concurrent_compact_container.cpp | 4 + 5 files changed, 147 insertions(+), 111 deletions(-) diff --git a/STL_Extension/include/CGAL/Compact_container.h b/STL_Extension/include/CGAL/Compact_container.h index ee83c6c4d0b..86dd6e45fe5 100644 --- a/STL_Extension/include/CGAL/Compact_container.h +++ b/STL_Extension/include/CGAL/Compact_container.h @@ -25,6 +25,7 @@ #include #include #include +#include #include #include @@ -223,7 +224,8 @@ class Compact_container public: typedef typename Default::Get< TimeStamper_, CGAL::Time_stamper_impl >::type - Time_stamper_impl; + Time_stamper; + typedef Time_stamper Time_stamper_impl; // backward-compatibility typedef T value_type; typedef Allocator allocator_type; @@ -250,16 +252,14 @@ public: explicit Compact_container(const Allocator &a = Allocator()) : alloc(a) - , time_stamper(new Time_stamper_impl()) { - init (); + init(); } template < class InputIterator > Compact_container(InputIterator first, InputIterator last, const Allocator & a = Allocator()) : alloc(a) - , time_stamper(new Time_stamper_impl()) { init(); std::copy(first, last, CGAL::inserter(*this)); @@ -268,14 +268,19 @@ public: // The copy constructor and assignment operator preserve the iterator order Compact_container(const Compact_container &c) : alloc(c.get_allocator()) - , time_stamper(new Time_stamper_impl()) { init(); block_size = c.block_size; - *time_stamper = *c.time_stamper; + time_stamp = c.time_stamp.load(); std::copy(c.begin(), c.end(), CGAL::inserter(*this)); } + Compact_container(Compact_container&& c) noexcept + : alloc(c.get_allocator()) + { + c.swap(*this); + } + Compact_container & operator=(const Compact_container &c) { if (&c != this) { @@ -285,10 +290,16 @@ public: return *this; } + Compact_container & operator=(Compact_container&& c) noexcept + { + Self tmp(std::move(c)); + tmp.swap(*this); + return *this; + } + ~Compact_container() { clear(); - delete time_stamper; } bool is_used(const_iterator ptr) const @@ -328,17 +339,8 @@ public: return all_items[block_number].first[index_in_block]; } - void swap(Self &c) - { - std::swap(alloc, c.alloc); - std::swap(capacity_, c.capacity_); - std::swap(size_, c.size_); - std::swap(block_size, c.block_size); - std::swap(first_item, c.first_item); - std::swap(last_item, c.last_item); - std::swap(free_list, c.free_list); - all_items.swap(c.all_items); - std::swap(time_stamper, c.time_stamper); + friend void swap(Compact_container& a, Compact_container b) { + a.swap(b); } iterator begin() { return iterator(first_item, 0, 0); } @@ -383,7 +385,7 @@ public: new (ret) value_type(args...); CGAL_assertion(type(ret) == USED); ++size_; - time_stamper->set_time_stamp(ret); + Time_stamper::set_time_stamp(ret, time_stamp); return iterator(ret, 0); } @@ -397,7 +399,7 @@ public: std::allocator_traits::construct(alloc, ret, t); CGAL_assertion(type(ret) == USED); ++size_; - time_stamper->set_time_stamp(ret); + Time_stamper::set_time_stamp(ret, time_stamp); return iterator(ret, 0); } @@ -652,7 +654,21 @@ public: static bool is_begin_or_end(const_pointer ptr) { return type(ptr)==START_END; } + void swap(Self &c) + { + std::swap(alloc, c.alloc); + std::swap(capacity_, c.capacity_); + std::swap(size_, c.size_); + std::swap(block_size, c.block_size); + std::swap(first_item, c.first_item); + std::swap(last_item, c.last_item); + std::swap(free_list, c.free_list); + all_items.swap(c.all_items); + // non-atomic swap of time_stamp: + c.time_stamp = time_stamp.exchange(c.time_stamp.load()); + } +private: // We store a vector of pointers to all allocated blocks and their sizes. // Knowing all pointers, we don't have to walk to the end of a block to reach // the pointer to the next block. @@ -660,7 +676,9 @@ public: // by walking through the block till its end. // This opens up the possibility for the compiler to optimize the clear() // function considerably when has_trivial_destructor. - typedef std::vector > All_items; + using All_items = std::vector >; + + using time_stamp_t = std::atomic; void init() { @@ -671,21 +689,18 @@ public: first_item = nullptr; last_item = nullptr; all_items = All_items(); - time_stamper->reset(); + time_stamp = 0; } allocator_type alloc; - size_type capacity_; - size_type size_; - size_type block_size; - pointer free_list; - pointer first_item; - pointer last_item; - All_items all_items; - - // This is a pointer, so that the definition of Compact_container does - // not require a complete type `T`. - Time_stamper_impl* time_stamper; + size_type capacity_ = 0; + size_type size_ = 0; + size_type block_size = Increment_policy::first_block_size; + pointer free_list = nullptr; + pointer first_item = nullptr; + pointer last_item = nullptr; + All_items all_items = {}; + time_stamp_t time_stamp = {}; }; template < class T, class Allocator, class Increment_policy, class TimeStamper > @@ -759,7 +774,7 @@ void Compact_container::allocate_ne for (size_type i = block_size; i >= 1; --i) { EraseCounterStrategy::set_erase_counter(*(new_block + i), 0); - time_stamper->initialize_time_stamp(new_block + i); + Time_stamper::initialize_time_stamp(new_block + i); put_on_free_list(new_block + i); } // We insert this new block at the end. @@ -839,7 +854,6 @@ namespace internal { template < class DSC, bool Const > class CC_iterator { - typedef typename DSC::iterator iterator; typedef CC_iterator Self; public: typedef DSC CC; @@ -861,26 +875,52 @@ namespace internal { m_ptr.p = nullptr; } - // Either a harmless copy-ctor, - // or a conversion from iterator to const_iterator. - CC_iterator (const iterator &it) + CC_iterator (const CC_iterator &it) #ifdef CGAL_COMPACT_CONTAINER_DEBUG_TIME_STAMP - : ts(Time_stamper_impl::time_stamp(it.operator->())) + : ts(Time_stamper::time_stamp(it.operator->())) #endif { m_ptr.p = it.operator->(); } - // Same for assignment operator (otherwise MipsPro warns) - CC_iterator & operator= (const iterator &it) - { - m_ptr.p = it.operator->(); + // Converting constructor from mutable to constant iterator + template + CC_iterator(const CC_iterator< + typename std::enable_if<(Const && !OtherConst), DSC>::type, + OtherConst> &const_it) #ifdef CGAL_COMPACT_CONTAINER_DEBUG_TIME_STAMP - ts = Time_stamper_impl::time_stamp(it.operator->()); + : ts(Time_stamper::time_stamp(const_it.operator->())) +#endif + { + m_ptr.p = const_it.operator->(); + } + + // Assignment operator from mutable to constant iterator + template + CC_iterator & operator= (const CC_iterator< + typename std::enable_if<(Const && !OtherConst), DSC>::type, + OtherConst> &const_it) + { + m_ptr.p = const_it.operator->(); +#ifdef CGAL_COMPACT_CONTAINER_DEBUG_TIME_STAMP + ts = Time_stamper::time_stamp(const_it.operator->()); #endif return *this; } + CC_iterator(CC_iterator&& it) noexcept +#ifdef CGAL_COMPACT_CONTAINER_DEBUG_TIME_STAMP + : ts(Time_stamper::time_stamp(it.operator->())) +#endif + { + m_ptr.p = it.operator->(); + it.m_ptr.p = nullptr; + } + + ~CC_iterator() = default; + CC_iterator& operator=(const CC_iterator&) = default; + CC_iterator& operator=(CC_iterator&&) = default; + // Construction from nullptr CC_iterator (std::nullptr_t CGAL_assertion_code(n)) #ifdef CGAL_COMPACT_CONTAINER_DEBUG_TIME_STAMP @@ -893,7 +933,7 @@ namespace internal { private: - typedef typename DSC::Time_stamper_impl Time_stamper_impl; + typedef typename DSC::Time_stamper Time_stamper; #ifdef CGAL_COMPACT_CONTAINER_DEBUG_TIME_STAMP std::size_t ts; #endif @@ -925,7 +965,7 @@ namespace internal { increment(); #ifdef CGAL_COMPACT_CONTAINER_DEBUG_TIME_STAMP else - ts = Time_stamper_impl::time_stamp(m_ptr.p); + ts = Time_stamper::time_stamp(m_ptr.p); #endif // CGAL_COMPACT_CONTAINER_DEBUG_TIME_STAMP } @@ -938,7 +978,7 @@ namespace internal { m_ptr.p = ptr; #ifdef CGAL_COMPACT_CONTAINER_DEBUG_TIME_STAMP if(ptr != nullptr){ - ts = Time_stamper_impl::time_stamp(m_ptr.p); + ts = Time_stamper::time_stamp(m_ptr.p); } #endif // end CGAL_COMPACT_CONTAINER_DEBUG_TIME_STAMP } @@ -959,7 +999,7 @@ namespace internal { DSC::type(m_ptr.p) == DSC::START_END) { #ifdef CGAL_COMPACT_CONTAINER_DEBUG_TIME_STAMP - ts = Time_stamper_impl::time_stamp(m_ptr.p); + ts = Time_stamper::time_stamp(m_ptr.p); #endif return; } @@ -983,7 +1023,7 @@ namespace internal { DSC::type(m_ptr.p) == DSC::START_END) { #ifdef CGAL_COMPACT_CONTAINER_DEBUG_TIME_STAMP - ts = Time_stamper_impl::time_stamp(m_ptr.p); + ts = Time_stamper::time_stamp(m_ptr.p); #endif return; } @@ -1022,7 +1062,7 @@ namespace internal { #ifdef CGAL_COMPACT_CONTAINER_DEBUG_TIME_STAMP bool is_time_stamp_valid() const { - return (ts == 0) || (ts == Time_stamper_impl::time_stamp(m_ptr.p)); + return (ts == 0) || (ts == Time_stamper::time_stamp(m_ptr.p)); } #endif // CGAL_COMPACT_CONTAINER_DEBUG_TIME_STAMP @@ -1036,7 +1076,7 @@ namespace internal { #ifdef CGAL_COMPACT_CONTAINER_DEBUG_TIME_STAMP assert( is_time_stamp_valid() ); #endif - return Time_stamper_impl::less(m_ptr.p, other.m_ptr.p); + return Time_stamper::less(m_ptr.p, other.m_ptr.p); } bool operator>(const CC_iterator& other) const @@ -1044,7 +1084,7 @@ namespace internal { #ifdef CGAL_COMPACT_CONTAINER_DEBUG_TIME_STAMP assert( is_time_stamp_valid() ); #endif - return Time_stamper_impl::less(other.m_ptr.p, m_ptr.p); + return Time_stamper::less(other.m_ptr.p, m_ptr.p); } bool operator<=(const CC_iterator& other) const @@ -1052,7 +1092,7 @@ namespace internal { #ifdef CGAL_COMPACT_CONTAINER_DEBUG_TIME_STAMP assert( is_time_stamp_valid() ); #endif - return Time_stamper_impl::less(m_ptr.p, other.m_ptr.p) + return Time_stamper::less(m_ptr.p, other.m_ptr.p) || (*this == other); } @@ -1061,7 +1101,7 @@ namespace internal { #ifdef CGAL_COMPACT_CONTAINER_DEBUG_TIME_STAMP assert( is_time_stamp_valid() ); #endif - return Time_stamper_impl::less(other.m_ptr.p, m_ptr.p) + return Time_stamper::less(other.m_ptr.p, m_ptr.p) || (*this == other); } diff --git a/STL_Extension/include/CGAL/Concurrent_compact_container.h b/STL_Extension/include/CGAL/Concurrent_compact_container.h index 5fad68c1719..c9ee56954b7 100644 --- a/STL_Extension/include/CGAL/Concurrent_compact_container.h +++ b/STL_Extension/include/CGAL/Concurrent_compact_container.h @@ -210,7 +210,8 @@ class Concurrent_compact_container typedef Concurrent_compact_container_traits Traits; public: - typedef CGAL::Time_stamper_impl Time_stamper_impl; + typedef CGAL::Time_stamper_impl Time_stamper; + typedef Time_stamper Time_stamper_impl; // backward compatibility typedef T value_type; typedef Allocator allocator_type; @@ -241,7 +242,6 @@ public: explicit Concurrent_compact_container(const Allocator &a = Allocator()) : m_alloc(a) - , m_time_stamper(new Time_stamper_impl()) { init (); } @@ -250,7 +250,6 @@ public: Concurrent_compact_container(InputIterator first, InputIterator last, const Allocator & a = Allocator()) : m_alloc(a) - , m_time_stamper(new Time_stamper_impl()) { init(); std::copy(first, last, CGAL::inserter(*this)); @@ -259,13 +258,18 @@ public: // The copy constructor and assignment operator preserve the iterator order Concurrent_compact_container(const Concurrent_compact_container &c) : m_alloc(c.get_allocator()) - , m_time_stamper(new Time_stamper_impl()) { init(); m_block_size = c.m_block_size; std::copy(c.begin(), c.end(), CGAL::inserter(*this)); } + Concurrent_compact_container(Concurrent_compact_container&& c) noexcept + : m_alloc(c.get_allocator()) + { + c.swap(*this); + } + Concurrent_compact_container & operator=(const Concurrent_compact_container &c) { if (&c != this) { @@ -275,10 +279,16 @@ public: return *this; } + Concurrent_compact_container & operator=(Concurrent_compact_container&& c) noexcept + { + Self tmp(std::move(c)); + tmp.swap(*this); + return *this; + } + ~Concurrent_compact_container() { clear(); - delete m_time_stamper; } bool is_used(const_iterator ptr) const @@ -290,11 +300,8 @@ public: { std::swap(m_alloc, c.m_alloc); #if CGAL_CONCURRENT_COMPACT_CONTAINER_APPROXIMATE_SIZE - { // non-atomic swap - size_type other_capacity = c.m_capacity; - c.m_capacity = size_type(m_capacity); - m_capacity = other_capacity; - } + // non-atomic swap of m_capacity + c.m_capacity = m_capacity.exchange(c.m_capacity.load()); #else // not CGAL_CONCURRENT_COMPACT_CONTAINER_APPROXIMATE_SIZE std::swap(m_capacity, c.m_capacity); #endif // not CGAL_CONCURRENT_COMPACT_CONTAINER_APPROXIMATE_SIZE @@ -304,7 +311,12 @@ public: std::swap(m_last_item, c.m_last_item); std::swap(m_free_lists, c.m_free_lists); m_all_items.swap(c.m_all_items); - std::swap(m_time_stamper, c.m_time_stamper); + // non-atomic swap of m_time_stamp + c.m_time_stamp = m_time_stamp.exchange(c.m_time_stamp.load()); + } + + friend void swap(Concurrent_compact_container& a, Concurrent_compact_container& b) { + a.swap(b); } iterator begin() { return iterator(m_first_item, 0, 0); } @@ -544,7 +556,7 @@ private: { CGAL_assertion(type(ret) == USED); fl->dec_size(); - m_time_stamper->set_time_stamp(ret); + Time_stamper::set_time_stamp(ret, m_time_stamp); return iterator(ret, 0); } @@ -619,8 +631,9 @@ private: // by walking through the block till its end. // This opens up the possibility for the compiler to optimize the clear() // function considerably when has_trivial_destructor. - typedef std::vector > All_items; + using All_items = std::vector >; + using time_stamp_t = std::atomic; void init() { @@ -636,25 +649,23 @@ private: m_first_item = nullptr; m_last_item = nullptr; m_all_items = All_items(); - m_time_stamper->reset(); + m_time_stamp = 0; } allocator_type m_alloc; #if CGAL_CONCURRENT_COMPACT_CONTAINER_APPROXIMATE_SIZE - std::atomic m_capacity; + std::atomic m_capacity = {}; #else // not CGAL_CONCURRENT_COMPACT_CONTAINER_APPROXIMATE_SIZE - size_type m_capacity; + size_type m_capacity = {}; #endif // not CGAL_CONCURRENT_COMPACT_CONTAINER_APPROXIMATE_SIZE - size_type m_block_size; + size_type m_block_size = CGAL_INIT_CONCURRENT_COMPACT_CONTAINER_BLOCK_SIZE; Free_lists m_free_lists; - pointer m_first_item; - pointer m_last_item; - All_items m_all_items; + pointer m_first_item = nullptr; + pointer m_last_item = nullptr; + All_items m_all_items = {}; mutable Mutex m_mutex; + time_stamp_t m_time_stamp = {}; - // This is a pointer, so that the definition of Compact_container does - // not require a complete type `T`. - Time_stamper_impl* m_time_stamper; }; template < class T, class Allocator > @@ -770,7 +781,7 @@ void Concurrent_compact_container:: for (size_type i = old_block_size; i >= 1; --i) { EraseCounterStrategy::set_erase_counter(*(new_block + i), 0); - m_time_stamper->initialize_time_stamp(new_block + i); + Time_stamper::initialize_time_stamp(new_block + i); put_on_free_list(new_block + i, fl); } } diff --git a/STL_Extension/include/CGAL/Time_stamper.h b/STL_Extension/include/CGAL/Time_stamper.h index 6d65ec3cfb1..f0cfe44a574 100644 --- a/STL_Extension/include/CGAL/Time_stamper.h +++ b/STL_Extension/include/CGAL/Time_stamper.h @@ -28,26 +28,12 @@ constexpr size_t rounded_down_log2(size_t n) template struct Time_stamper { - Time_stamper() - : time_stamp_() {} - - Time_stamper(const Time_stamper& ts) - : time_stamp_() - { - time_stamp_ = std::size_t(ts.time_stamp_); - } - - Time_stamper& operator=(const Time_stamper& ts) - { - time_stamp_ = std::size_t(ts.time_stamp_); - return *this; - } - static void initialize_time_stamp(T* pt) { pt->set_time_stamp(std::size_t(-1)); } - void set_time_stamp(T* pt) { + template + static void set_time_stamp(T* pt, time_stamp_t& time_stamp_) { if(pt->time_stamp() == std::size_t(-1)) { const std::size_t new_ts = time_stamp_++; pt->set_time_stamp(new_ts); @@ -96,23 +82,14 @@ struct Time_stamper return time_stamp(p_t1) < time_stamp(p_t2); } } - - void reset() { - time_stamp_ = 0; - } -private: -#ifdef CGAL_NO_ATOMIC - std::size_t time_stamp_; -#else - CGAL::cpp11::atomic time_stamp_; -#endif }; // end class template Time_stamper template struct No_time_stamp { public: - void set_time_stamp(T*) {} + template + static void set_time_stamp(T*, time_stamp_t&) {} static bool less(const T* p_t1,const T* p_t2) { return p_t1 < p_t2; } @@ -130,8 +107,6 @@ public: constexpr std::size_t shift = internal::rounded_down_log2(sizeof(T)); return reinterpret_cast(p) >> shift; } - - void reset() {} }; // end class template No_time_stamp // That class template is an auxiliary class. It has a diff --git a/STL_Extension/test/STL_Extension/test_Compact_container.cpp b/STL_Extension/test/STL_Extension/test_Compact_container.cpp index 117b5d1ec44..3d370105a6a 100644 --- a/STL_Extension/test/STL_Extension/test_Compact_container.cpp +++ b/STL_Extension/test/STL_Extension/test_Compact_container.cpp @@ -4,6 +4,7 @@ #include #include #include +#include #include #include @@ -83,6 +84,11 @@ inline bool check_empty(const Cont &c) template < class Cont > void test(const Cont &) { + static_assert(std::is_nothrow_move_constructible::value, + "move cstr is missing"); + static_assert(std::is_nothrow_move_assignable::value, + "move assignment is missing"); + // Testing if all types are provided. typename Cont::value_type t0; @@ -319,22 +325,22 @@ int main() // Check the time stamper policies if(! boost::is_base_of, - C1::Time_stamper_impl>::value) + C1::Time_stamper>::value) { std::cerr << "Error timestamper of C1\n"; return 1; } if(! boost::is_base_of, - C2::Time_stamper_impl>::value) + C2::Time_stamper>::value) { std::cerr << "Error timestamper of C2\n"; return 1; } if(! boost::is_base_of, - C3::Time_stamper_impl>::value) + C3::Time_stamper>::value) { std::cerr << "Error timestamper of C3\n"; return 1; } if(! boost::is_base_of, - C4::Time_stamper_impl>::value) + C4::Time_stamper>::value) { std::cerr << "Error timestamper of C4\n"; return 1; } diff --git a/STL_Extension/test/STL_Extension/test_Concurrent_compact_container.cpp b/STL_Extension/test/STL_Extension/test_Concurrent_compact_container.cpp index afe1de689da..8db20f3b173 100644 --- a/STL_Extension/test/STL_Extension/test_Concurrent_compact_container.cpp +++ b/STL_Extension/test/STL_Extension/test_Concurrent_compact_container.cpp @@ -183,6 +183,10 @@ private: template < class Cont > void test(const Cont &) { + static_assert(std::is_nothrow_move_constructible::value, + "move cstr is missing"); + static_assert(std::is_nothrow_move_assignable::value, + "move assignment is missing"); // Testing if all types are provided. typename Cont::value_type t0; From 3b564a20f81d1da1e4b11fe1402f7aa5b246b59d Mon Sep 17 00:00:00 2001 From: Laurent Rineau Date: Fri, 31 Jan 2020 11:11:19 +0100 Subject: [PATCH 073/568] Add move-semantic to TDS_3 --- .../CGAL/Triangulation_data_structure_3.h | 19 +++++++++++ .../test/TDS_3/include/CGAL/_test_cls_tds_3.h | 33 +++++++++++++++++++ 2 files changed, 52 insertions(+) diff --git a/TDS_3/include/CGAL/Triangulation_data_structure_3.h b/TDS_3/include/CGAL/Triangulation_data_structure_3.h index e971ee6a7db..f7b145f014d 100644 --- a/TDS_3/include/CGAL/Triangulation_data_structure_3.h +++ b/TDS_3/include/CGAL/Triangulation_data_structure_3.h @@ -230,6 +230,15 @@ public: copy_tds(tds); } + Triangulation_data_structure_3(Tds && tds) + noexcept(noexcept(Cell_range(std::move(tds._cells))) && + noexcept(Vertex_range(std::move(tds._vertices)))) + : _dimension(std::exchange(tds._dimension, -2)) + , _cells(std::move(tds._cells)) + , _vertices(std::move(tds._vertices)) + { + } + Tds & operator= (const Tds & tds) { if (&tds != this) { @@ -239,6 +248,16 @@ public: return *this; } + Tds & operator= (Tds && tds) + noexcept(noexcept(Tds(std::move(tds)))) + { + Tds tmp(std::move(tds)); + swap(tmp); + return *this; + } + + ~Triangulation_data_structure_3() = default; // for the rule-of-five + size_type number_of_vertices() const { return vertices().size(); } int dimension() const {return _dimension;} diff --git a/TDS_3/test/TDS_3/include/CGAL/_test_cls_tds_3.h b/TDS_3/test/TDS_3/include/CGAL/_test_cls_tds_3.h index a8b8fe41dbe..bdf03c645d8 100644 --- a/TDS_3/test/TDS_3/include/CGAL/_test_cls_tds_3.h +++ b/TDS_3/test/TDS_3/include/CGAL/_test_cls_tds_3.h @@ -26,6 +26,11 @@ template void _test_cls_tds_3( const Tds &) { + static_assert(std::is_nothrow_move_constructible::value, + "move cstr is missing"); + static_assert(std::is_nothrow_move_assignable::value, + "move assignment is missing"); + typedef typename Tds::Vertex_range Vertex_range; typedef typename Tds::Cell_range Cell_range; @@ -115,6 +120,34 @@ _test_cls_tds_3( const Tds &) std::cout << "ok" << std::endl; assert(tds6.is_valid()); + // Test move-constructors and move-assignments + { + Tds tds7 = tds5; + Tds tds8{std::move(tds7)}; + Tds tds9 = tds5; + Tds tds10; + tds10 = std::move(tds9); + Tds tds11 = Tds(tds5); // construct from a temporary + Tds tds12 = std::move(tds11); + + assert(tds7.is_valid()); + assert(tds8.is_valid()); + assert(tds9.is_valid()); + assert(tds10.is_valid()); + assert(tds11.is_valid()); + assert(tds12.is_valid()); + assert(tds7.dimension()==-2); + assert(tds8.dimension()==2); + assert(tds9.dimension()==-2); + assert(tds10.dimension()==2); + assert(tds11.dimension()==-2); + assert(tds12.dimension()==2); + tds11.~Tds(); + // check tds12 is still valid after the destruction of tds11 + assert(tds12.is_valid()); + assert(tds12.dimension()==2); + } + std::cout << " Insert are tested in test_triangulation_3 " << std::endl; std::cout << " Iterator and circulator are tested in test_triangulation_3 " << std::endl; From b56cdcb743465a3c9f4fdff83ca6230b76a1763f Mon Sep 17 00:00:00 2001 From: Laurent Rineau Date: Fri, 31 Jan 2020 11:23:37 +0100 Subject: [PATCH 074/568] Add move-semantic to CGAL (non-periodic) 3D triangulations - For `Triangulation_3`, the rule-of-zero cannot be used, because of the infinite vertex. A special copy-constructor and copy-assignment operators are required. But one can `= default the move-constructor and move-assignment operator, as well as the destructor. - For `Delaunay_triangulation_3`, the rule-of-zero is sufficient. Nothing to do. - For `Regular_triangulation_3`, the `hidden_point_visitor` data member is a function that is constructed with the `this` pointer, so the rule-of-zero cannot be used. Probably the move-constructor and move-assignment operator could be explicitly defaulted. --- ...angulation_cell_base_with_circumcenter_3.h | 15 +++++++++++ .../include/CGAL/Regular_triangulation_3.h | 27 ++++++++++++++++--- .../include/CGAL/Triangulation_3.h | 21 ++++++++------- .../include/CGAL/_test_cls_delaunay_3.h | 6 +++++ .../include/CGAL/_test_cls_regular_3.h | 7 +++++ .../include/CGAL/_test_cls_triangulation_3.h | 6 +++++ 6 files changed, 70 insertions(+), 12 deletions(-) diff --git a/Triangulation_3/include/CGAL/Delaunay_triangulation_cell_base_with_circumcenter_3.h b/Triangulation_3/include/CGAL/Delaunay_triangulation_cell_base_with_circumcenter_3.h index 6c9c6a6e4ea..44610ed6de8 100644 --- a/Triangulation_3/include/CGAL/Delaunay_triangulation_cell_base_with_circumcenter_3.h +++ b/Triangulation_3/include/CGAL/Delaunay_triangulation_cell_base_with_circumcenter_3.h @@ -63,6 +63,13 @@ public: : Cb(c), circumcenter_(c.circumcenter_ != nullptr ? new Point(*(c.circumcenter_)) : nullptr) {} + Delaunay_triangulation_cell_base_with_circumcenter_3 + (Delaunay_triangulation_cell_base_with_circumcenter_3 &&c) + : Cb(std::move(c)), circumcenter_(nullptr) + { + std::swap(circumcenter_, c.circumcenter_); + } + Delaunay_triangulation_cell_base_with_circumcenter_3& operator=(const Delaunay_triangulation_cell_base_with_circumcenter_3 &c) { @@ -71,6 +78,14 @@ public: return *this; } + Delaunay_triangulation_cell_base_with_circumcenter_3& + operator=(Delaunay_triangulation_cell_base_with_circumcenter_3 &&c) + { + Delaunay_triangulation_cell_base_with_circumcenter_3 tmp=std::move(c); + std::swap(tmp, *this); + return *this; + } + Delaunay_triangulation_cell_base_with_circumcenter_3( Vertex_handle v0, Vertex_handle v1, Vertex_handle v2, Vertex_handle v3) diff --git a/Triangulation_3/include/CGAL/Regular_triangulation_3.h b/Triangulation_3/include/CGAL/Regular_triangulation_3.h index 17cabad626a..3d56833e370 100644 --- a/Triangulation_3/include/CGAL/Regular_triangulation_3.h +++ b/Triangulation_3/include/CGAL/Regular_triangulation_3.h @@ -193,21 +193,42 @@ public: CGAL_triangulation_postcondition(is_valid()); } + Regular_triangulation_3(Regular_triangulation_3&& rt) + noexcept(noexcept(Tr_Base(std::move(rt)))) + : Tr_Base(std::move(rt)), hidden_point_visitor(this) + { + CGAL_triangulation_postcondition(is_valid()); + } + + ~Regular_triangulation_3() = default; + void swap(Regular_triangulation_3& tr) + noexcept(noexcept(this->Tr_Base::swap(tr))) { // The 'vertices' and 'hidden_points' members of 'hidden_point_visitor' should be empty // as they are only filled (and cleared) during the insertion of a point. // Hidden points are not stored there, but rather in cells. Thus, the only thing that must be set // is the triangulation pointer. Hidden_point_visitor new_hpv(this); - std::swap(hidden_point_visitor, new_hpv); + using std::swap; + swap(hidden_point_visitor, new_hpv); Tr_Base::swap(tr); } - Regular_triangulation_3& operator=(Regular_triangulation_3 tr) + Regular_triangulation_3& operator=(const Regular_triangulation_3& tr) { - swap(tr); + Regular_triangulation_3 copy(tr); + copy.swap(*this); + return *this; + } + + Regular_triangulation_3& operator=(Regular_triangulation_3&& tr) + noexcept(noexcept(Regular_triangulation_3(std::move(tr))) && + noexcept(std::declval().swap(*this))) + { + Regular_triangulation_3 copy(std::move(tr)); + copy.swap(*this); return *this; } diff --git a/Triangulation_3/include/CGAL/Triangulation_3.h b/Triangulation_3/include/CGAL/Triangulation_3.h index 6941c6c8acf..07cc5761a31 100644 --- a/Triangulation_3/include/CGAL/Triangulation_3.h +++ b/Triangulation_3/include/CGAL/Triangulation_3.h @@ -728,6 +728,9 @@ public: CGAL_triangulation_expensive_postcondition(*this == tr); } + Triangulation_3(Triangulation_3&& tr) = default; + ~Triangulation_3() = default; + template < typename InputIterator > Triangulation_3(InputIterator first, InputIterator last, const GT& gt = GT(), Lock_data_structure *lock_ds = nullptr) @@ -754,21 +757,21 @@ public: init_tds(); } - Triangulation_3& operator=(Triangulation_3 tr) + Triangulation_3& operator=(const Triangulation_3& tr) { - // Because the parameter tr is passed by value, the triangulation passed - // as argument has been copied. - // The following 'swap' consumes the *copy* and the original triangulation - // is left untouched. - swap(tr); + Triangulation_3 copy(tr); + swap(copy); return *this; } + Triangulation_3& operator=(Triangulation_3&& tr) = default; + // HELPING FUNCTIONS - void swap(Triangulation_3& tr) + void swap(Triangulation_3& tr) noexcept { - std::swap(tr._gt, _gt); - std::swap(tr.infinite, infinite); + using std::swap; + swap(tr._gt, _gt); + swap(tr.infinite, infinite); _tds.swap(tr._tds); Base::swap(tr); } diff --git a/Triangulation_3/test/Triangulation_3/include/CGAL/_test_cls_delaunay_3.h b/Triangulation_3/test/Triangulation_3/include/CGAL/_test_cls_delaunay_3.h index e2c9029eb10..a6b5ded18a7 100644 --- a/Triangulation_3/test/Triangulation_3/include/CGAL/_test_cls_delaunay_3.h +++ b/Triangulation_3/test/Triangulation_3/include/CGAL/_test_cls_delaunay_3.h @@ -19,6 +19,7 @@ #include #include #include +#include #include #include @@ -170,6 +171,11 @@ _test_cls_delaunay_3(const Triangulation &) { typedef Triangulation Cls; + static_assert(std::is_nothrow_move_constructible::value, + "move cstr is missing"); + static_assert(std::is_nothrow_move_assignable::value, + "move assignment is missing"); + typedef typename Test_location_policy::Location_policy Location_policy; // We assume the traits class has been tested already diff --git a/Triangulation_3/test/Triangulation_3/include/CGAL/_test_cls_regular_3.h b/Triangulation_3/test/Triangulation_3/include/CGAL/_test_cls_regular_3.h index 3c646b27be4..6c5793d0de2 100644 --- a/Triangulation_3/test/Triangulation_3/include/CGAL/_test_cls_regular_3.h +++ b/Triangulation_3/test/Triangulation_3/include/CGAL/_test_cls_regular_3.h @@ -15,12 +15,19 @@ #include #include #include +#include #include template void _test_cls_regular_3(const Triangulation &) { typedef Triangulation Cls; + + static_assert(std::is_nothrow_move_constructible::value, + "move cstr is missing"); + static_assert(std::is_nothrow_move_assignable::value, + "move assignment is missing"); + typedef typename Triangulation::Geom_traits Gt; CGAL_USE_TYPE(Gt); diff --git a/Triangulation_3/test/Triangulation_3/include/CGAL/_test_cls_triangulation_3.h b/Triangulation_3/test/Triangulation_3/include/CGAL/_test_cls_triangulation_3.h index 3d647fcad94..b73de19db78 100644 --- a/Triangulation_3/test/Triangulation_3/include/CGAL/_test_cls_triangulation_3.h +++ b/Triangulation_3/test/Triangulation_3/include/CGAL/_test_cls_triangulation_3.h @@ -15,6 +15,7 @@ #include #include #include +#include #include "_test_cls_iterator.h" #include "_test_cls_circulator.h" @@ -79,6 +80,11 @@ _test_cls_triangulation_3(const Triangulation &) { typedef Triangulation Cls; + static_assert(std::is_nothrow_move_constructible::value, + "move cstr is missing"); + static_assert(std::is_nothrow_move_assignable::value, + "move assignment is missing"); + // We assume the traits class has been tested already // actually, any traits is good if it has been tested From db55548830a3feec3b34749d0dce6f6a2b13d8af Mon Sep 17 00:00:00 2001 From: Laurent Rineau Date: Fri, 31 Jan 2020 11:08:58 +0100 Subject: [PATCH 075/568] Fix a conversion warning --- .../test/STL_Extension/test_Concurrent_compact_container.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/STL_Extension/test/STL_Extension/test_Concurrent_compact_container.cpp b/STL_Extension/test/STL_Extension/test_Concurrent_compact_container.cpp index 8db20f3b173..37003ba37a5 100644 --- a/STL_Extension/test/STL_Extension/test_Concurrent_compact_container.cpp +++ b/STL_Extension/test/STL_Extension/test_Concurrent_compact_container.cpp @@ -161,7 +161,7 @@ public: { m_iterators[i] = m_cont.insert(m_values[i]); // Random-pick an element to erase - int index_to_erase = rand() % m_values.size(); + auto index_to_erase = rand() % m_values.size(); // If it exists bool comparand = false; if (m_free_elements[index_to_erase].compare_exchange_weak(comparand, true) ) From 2717864bd7906e476b8a59fc08388a546a314797 Mon Sep 17 00:00:00 2001 From: Laurent Rineau Date: Fri, 31 Jan 2020 11:11:39 +0100 Subject: [PATCH 076/568] Fix warnings cppcoreguidelines-special-member-functions (clang-tidy) - Remove trivial copy-constructors that prevents the compiler to generate the other special member functions. --- .../include/CGAL/Concurrent_compact_container.h | 9 ++------- .../test_Concurrent_compact_container.cpp | 17 ----------------- .../CGAL/Triangulation_data_structure_3.h | 15 +++++++++------ .../include/CGAL/Delaunay_triangulation_3.h | 17 ----------------- .../include/CGAL/Regular_triangulation_3.h | 17 ----------------- 5 files changed, 11 insertions(+), 64 deletions(-) diff --git a/STL_Extension/include/CGAL/Concurrent_compact_container.h b/STL_Extension/include/CGAL/Concurrent_compact_container.h index c9ee56954b7..e968312c453 100644 --- a/STL_Extension/include/CGAL/Concurrent_compact_container.h +++ b/STL_Extension/include/CGAL/Concurrent_compact_container.h @@ -114,6 +114,8 @@ namespace CCC_internal { // Free list (head and size) template< typename pointer, typename size_type, typename CCC > class Free_list { + // Not that the implicitly-defined member functions copy the + // pointer, and not the pointed data. public: Free_list() : m_head(nullptr), m_size(0) { #if CGAL_CONCURRENT_COMPACT_CONTAINER_APPROXIMATE_SIZE @@ -150,13 +152,6 @@ public: #endif // CGAL_CONCURRENT_COMPACT_CONTAINER_APPROXIMATE_SIZE } bool empty() { return size() == 0; } - // Warning: copy the pointer, not the data! - Free_list& operator= (const Free_list& other) - { - m_head = other.m_head; - m_size = other.m_size; - return *this; - } void merge(Free_list &other) { diff --git a/STL_Extension/test/STL_Extension/test_Concurrent_compact_container.cpp b/STL_Extension/test/STL_Extension/test_Concurrent_compact_container.cpp index 37003ba37a5..0795806ac2b 100644 --- a/STL_Extension/test/STL_Extension/test_Concurrent_compact_container.cpp +++ b/STL_Extension/test/STL_Extension/test_Concurrent_compact_container.cpp @@ -33,7 +33,6 @@ struct Node_1 : public CGAL::Compact_container_base { Node_1() {} - Node_1(const Node_1& o) : time_stamp_(o.time_stamp_) {} bool operator==(const Node_1 &) const { return true; } bool operator!=(const Node_1 &) const { return false; } bool operator< (const Node_1 &) const { return false; } @@ -89,11 +88,6 @@ public: : m_values(values), m_cont(cont), m_iterators(iterators) {} - Insert_in_CCC_functor(const Insert_in_CCC_functor &other) - : m_values(other.m_values), m_cont(other.m_cont), - m_iterators(other.m_iterators) - {} - void operator() (const tbb::blocked_range& r) const { for( size_t i = r.begin() ; i != r.end() ; ++i) @@ -118,11 +112,6 @@ public: : m_cont(cont), m_iterators(iterators) {} - Erase_in_CCC_functor(const Erase_in_CCC_functor &other) - : m_cont(other.m_cont), - m_iterators(other.m_iterators) - {} - void operator() (const tbb::blocked_range& r) const { for( size_t i = r.begin() ; i != r.end() ; ++i) @@ -149,12 +138,6 @@ public: m_free_elements(free_elements), m_num_erasures(num_erasures) {} - Insert_and_erase_in_CCC_functor(const Insert_and_erase_in_CCC_functor &other) - : m_values(other.m_values), m_cont(other.m_cont), - m_iterators(other.m_iterators), m_free_elements(other.m_free_elements), - m_num_erasures(other.m_num_erasures) - {} - void operator() (const tbb::blocked_range& r) const { for( size_t i = r.begin() ; i != r.end() ; ++i) diff --git a/TDS_3/include/CGAL/Triangulation_data_structure_3.h b/TDS_3/include/CGAL/Triangulation_data_structure_3.h index f7b145f014d..f0c35a7a1e3 100644 --- a/TDS_3/include/CGAL/Triangulation_data_structure_3.h +++ b/TDS_3/include/CGAL/Triangulation_data_structure_3.h @@ -935,12 +935,6 @@ public: *output++ = e; return *this; } - Facet_it& operator=(const Facet_it& f) { - output = f.output; - filter = f.filter; - return *this; - } - Facet_it(const Facet_it&)=default; }; Facet_it facet_it() { return Facet_it(output, filter); @@ -1065,6 +1059,15 @@ public: } } + // Implement the rule-of-five, to please the diagnostic + // `cppcoreguidelines-special-member-functions` of clang-tidy. + // Instead of defaulting those special member functions, let's + // delete them, to prevent any misuse. + Vertex_extractor(const Vertex_extractor&) = delete; + Vertex_extractor(Vertex_extractor&&) = delete; + Vertex_extractor& operator=(const Vertex_extractor&) = delete; + Vertex_extractor& operator=(Vertex_extractor&&) = delete; + ~Vertex_extractor() { for(std::size_t i=0; i < tmp_vertices.size(); ++i){ diff --git a/Triangulation_3/include/CGAL/Delaunay_triangulation_3.h b/Triangulation_3/include/CGAL/Delaunay_triangulation_3.h index 70764f7bfa0..4f1de418ff2 100644 --- a/Triangulation_3/include/CGAL/Delaunay_triangulation_3.h +++ b/Triangulation_3/include/CGAL/Delaunay_triangulation_3.h @@ -887,11 +887,6 @@ protected: : m_dt(dt), m_points(points), m_tls_hint(tls_hint) {} - // Constructor - Insert_point(const Insert_point& ip) - : m_dt(ip.m_dt), m_points(ip.m_points), m_tls_hint(ip.m_tls_hint) - {} - // operator() void operator()(const tbb::blocked_range& r) const { @@ -967,12 +962,6 @@ protected: m_tls_hint(tls_hint) {} - // Constructor - Insert_point_with_info(const Insert_point_with_info& ip) - : m_dt(ip.m_dt), m_points(ip.m_points), m_infos(ip.m_infos), - m_indices(ip.m_indices), m_tls_hint(ip.m_tls_hint) - {} - // operator() void operator()(const tbb::blocked_range& r) const { @@ -1046,12 +1035,6 @@ protected: m_vertices_to_remove_sequentially(vertices_to_remove_sequentially) {} - // Constructor - Remove_point(const Remove_point& rp) - : m_dt(rp.m_dt), m_vertices(rp.m_vertices), - m_vertices_to_remove_sequentially(rp.m_vertices_to_remove_sequentially) - {} - // operator() void operator()(const tbb::blocked_range& r) const { diff --git a/Triangulation_3/include/CGAL/Regular_triangulation_3.h b/Triangulation_3/include/CGAL/Regular_triangulation_3.h index 3d56833e370..22122a53e41 100644 --- a/Triangulation_3/include/CGAL/Regular_triangulation_3.h +++ b/Triangulation_3/include/CGAL/Regular_triangulation_3.h @@ -1408,11 +1408,6 @@ protected: : m_rt(rt), m_points(points), m_tls_hint(tls_hint) {} - // Constructor - Insert_point(const Insert_point& ip) - : m_rt(ip.m_rt), m_points(ip.m_points), m_tls_hint(ip.m_tls_hint) - {} - // operator() void operator()(const tbb::blocked_range& r) const { @@ -1519,12 +1514,6 @@ protected: m_tls_hint(tls_hint) {} - // Constructor - Insert_point_with_info(const Insert_point_with_info &ip) - : m_rt(ip.m_rt), m_points(ip.m_points), m_infos(ip.m_infos), - m_indices(ip.m_indices), m_tls_hint(ip.m_tls_hint) - {} - // operator() void operator()(const tbb::blocked_range& r) const { @@ -1636,12 +1625,6 @@ protected: m_vertices_to_remove_sequentially(vertices_to_remove_sequentially) {} - // Constructor - Remove_point(const Remove_point& rp) - : m_rt(rp.m_rt), m_vertices(rp.m_vertices), - m_vertices_to_remove_sequentially(rp.m_vertices_to_remove_sequentially) - {} - // operator() void operator()(const tbb::blocked_range& r) const { From b311ab59edf7b77849b11266404020cc90693c63 Mon Sep 17 00:00:00 2001 From: Laurent Rineau Date: Fri, 31 Jan 2020 11:13:57 +0100 Subject: [PATCH 077/568] [modernize-use-nullptr] (clang-tidy) --- .../STL_Extension/test_Concurrent_compact_container.cpp | 2 +- Triangulation_3/include/CGAL/Triangulation_3.h | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/STL_Extension/test/STL_Extension/test_Concurrent_compact_container.cpp b/STL_Extension/test/STL_Extension/test_Concurrent_compact_container.cpp index 0795806ac2b..84a65304eb1 100644 --- a/STL_Extension/test/STL_Extension/test_Concurrent_compact_container.cpp +++ b/STL_Extension/test/STL_Extension/test_Concurrent_compact_container.cpp @@ -60,7 +60,7 @@ public: int rnd; Node_2() - : p(NULL), rnd(CGAL::get_default_random().get_int(0, 100)) {} + : p(nullptr), rnd(CGAL::get_default_random().get_int(0, 100)) {} bool operator==(const Node_2 &n) const { return rnd == n.rnd; } bool operator!=(const Node_2 &n) const { return rnd != n.rnd; } diff --git a/Triangulation_3/include/CGAL/Triangulation_3.h b/Triangulation_3/include/CGAL/Triangulation_3.h index 07cc5761a31..9f6b7301666 100644 --- a/Triangulation_3/include/CGAL/Triangulation_3.h +++ b/Triangulation_3/include/CGAL/Triangulation_3.h @@ -179,7 +179,7 @@ public: void *get_lock_data_structure() const { - return 0; + return nullptr; } void set_lock_data_structure(void *) const {} @@ -245,7 +245,7 @@ protected: public: bool is_parallel() const { - return m_lock_ds != 0; + return m_lock_ds != nullptr; } // LOCKS @@ -1139,7 +1139,7 @@ public: typename std::iterator_traits::value_type, Point > - >::type* = NULL) + >::type* = nullptr) #else template < class InputIterator > std::ptrdiff_t insert(InputIterator first, InputIterator last) From 290c3a2011c08a7a9b8f18a0880b1828fdb8001e Mon Sep 17 00:00:00 2001 From: Laurent Rineau Date: Fri, 31 Jan 2020 13:19:06 +0100 Subject: [PATCH 078/568] I forgot Triangulation_hierarchy_3 (Fast_location)! Note that a move-from object of class `Triangulation_hierarchy_3` is not really valid. I have just verified that it can be destroyed. Even a call to `clear()` on a moved-from hierarchy will segfault! To be fixed later... --- .../include/CGAL/Triangulation_hierarchy_3.h | 61 ++++++++++++------- 1 file changed, 38 insertions(+), 23 deletions(-) diff --git a/Triangulation_3/include/CGAL/Triangulation_hierarchy_3.h b/Triangulation_3/include/CGAL/Triangulation_hierarchy_3.h index 5e554cd14c5..f936cacdda8 100644 --- a/Triangulation_3/include/CGAL/Triangulation_hierarchy_3.h +++ b/Triangulation_3/include/CGAL/Triangulation_hierarchy_3.h @@ -51,6 +51,8 @@ #include #include +#include + #endif //CGAL_TRIANGULATION_3_DONT_INSERT_RANGE_OF_POINTS_WITH_INFO namespace CGAL { @@ -92,7 +94,7 @@ public: private: // here is the stack of triangulations which form the hierarchy - Tr_Base* hierarchy[maxlevel]; + std::array hierarchy; boost::rand48 random; void set_up_down(Vertex_handle up, Vertex_handle down) @@ -107,6 +109,18 @@ public: Triangulation_hierarchy_3(const Triangulation_hierarchy_3& tr); + Triangulation_hierarchy_3(Triangulation_hierarchy_3&& other) + noexcept( noexcept(Tr_Base(std::move(other))) ) + : Tr_Base(std::move(other)) + , random(std::move(other.random)) + { + hierarchy[0] = this; + for(int i=1; i Triangulation_hierarchy_3(InputIterator first, InputIterator last, const Geom_traits& traits = Geom_traits()) @@ -125,9 +139,30 @@ public: return *this; } - ~Triangulation_hierarchy_3(); + Triangulation_hierarchy_3 & operator=(Triangulation_hierarchy_3&& tr) + noexcept( noexcept(Triangulation_hierarchy_3(std::move(tr))) && + noexcept(this->swap(std::declval())) ) + { + Triangulation_hierarchy_3 tmp(std::move(tr)); + swap(tmp); + return *this; + } - void swap(Triangulation_hierarchy_3 &tr); + ~Triangulation_hierarchy_3() + { + clear(); + for(int i=1; iTr_Base::swap(tr))) + { + Tr_Base::swap(tr); + for(int i=1; i &tr) } } -template -void -Triangulation_hierarchy_3:: -swap(Triangulation_hierarchy_3 &tr) -{ - Tr_Base::swap(tr); - for(int i=1; i -Triangulation_hierarchy_3:: -~Triangulation_hierarchy_3() -{ - clear(); - for(int i=1; i void Triangulation_hierarchy_3:: From f7218dadd692e9f20af27aef063f32cd50d1e578 Mon Sep 17 00:00:00 2001 From: Laurent Rineau Date: Fri, 31 Jan 2020 14:19:49 +0100 Subject: [PATCH 079/568] Do not use swap for the move-assignment of TDS_3 We can write the operator easily without swap. --- TDS_3/include/CGAL/Triangulation_data_structure_3.h | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/TDS_3/include/CGAL/Triangulation_data_structure_3.h b/TDS_3/include/CGAL/Triangulation_data_structure_3.h index f0c35a7a1e3..82744371605 100644 --- a/TDS_3/include/CGAL/Triangulation_data_structure_3.h +++ b/TDS_3/include/CGAL/Triangulation_data_structure_3.h @@ -251,8 +251,9 @@ public: Tds & operator= (Tds && tds) noexcept(noexcept(Tds(std::move(tds)))) { - Tds tmp(std::move(tds)); - swap(tmp); + _cells = std::move(tds._cells); + _vertices = std::move(tds._vertices); + _dimension = std::exchange(tds._dimension, -2); return *this; } From aed73efb46f6fb21e46bfd789d1432133a4d87aa Mon Sep 17 00:00:00 2001 From: Laurent Rineau Date: Fri, 31 Jan 2020 14:20:39 +0100 Subject: [PATCH 080/568] Move-semantic for TDS_2 --- .../CGAL/Triangulation_data_structure_2.h | 35 +++++++++++++++---- .../test/TDS_2/include/CGAL/_test_cls_tds_2.h | 33 +++++++++++++++++ 2 files changed, 62 insertions(+), 6 deletions(-) diff --git a/TDS_2/include/CGAL/Triangulation_data_structure_2.h b/TDS_2/include/CGAL/Triangulation_data_structure_2.h index 303115158b2..9eb67f85818 100644 --- a/TDS_2/include/CGAL/Triangulation_data_structure_2.h +++ b/TDS_2/include/CGAL/Triangulation_data_structure_2.h @@ -105,8 +105,13 @@ protected: public: Triangulation_data_structure_2(); Triangulation_data_structure_2(const Tds &tds); + Triangulation_data_structure_2(Triangulation_data_structure_2&& tds) + noexcept(noexcept(Face_range(std::move(tds._faces))) && + noexcept(Vertex_range(std::move(tds._vertices)))); + ~Triangulation_data_structure_2(); Tds& operator= (const Tds &tds); + Tds& operator= (Tds&& tds) noexcept(noexcept(Tds(std::move(tds)))); void swap(Tds &tds); //ACCESS FUNCTIONS @@ -642,9 +647,6 @@ public: Triangulation_default_data_structure_2(const Geom_traits& = Geom_traits()) : Tds() {} - - Triangulation_default_data_structure_2(const Tdds &tdds) - : Tds(tdds) {} }; //for backward compatibility @@ -657,8 +659,6 @@ public: typedef Triangulation_data_structure_using_list_2 Tdsul; Triangulation_data_structure_using_list_2(): Tds() {} - Triangulation_data_structure_using_list_2(const Tdsul &tdsul) - : Tds(tdsul) {} }; @@ -675,6 +675,17 @@ Triangulation_data_structure_2(const Tds &tds) copy_tds(tds); } +template < class Vb, class Fb> +Triangulation_data_structure_2 :: +Triangulation_data_structure_2(Tds &&tds) + noexcept(noexcept(Face_range(std::move(tds._faces))) && + noexcept(Vertex_range(std::move(tds._vertices)))) + : _dimension(std::exchange(tds._dimension, -2)) + , _faces(std::move(tds._faces)) + , _vertices(std::move(tds._vertices)) +{ +} + template < class Vb, class Fb> Triangulation_data_structure_2 :: ~Triangulation_data_structure_2() @@ -682,7 +693,7 @@ Triangulation_data_structure_2 :: clear(); } -//assignement +//copy-assignment template < class Vb, class Fb> Triangulation_data_structure_2& Triangulation_data_structure_2 :: @@ -692,6 +703,18 @@ operator= (const Tds &tds) return *this; } +//move-assignment +template < class Vb, class Fb> +Triangulation_data_structure_2& +Triangulation_data_structure_2 :: +operator= (Tds &&tds) noexcept(noexcept(Tds(std::move(tds)))) +{ + _faces = std::move(tds._faces); + _vertices = std::move(tds._vertices); + _dimension = std::exchange(tds._dimension, -2); + return *this; +} + template < class Vb, class Fb> void Triangulation_data_structure_2:: diff --git a/TDS_2/test/TDS_2/include/CGAL/_test_cls_tds_2.h b/TDS_2/test/TDS_2/include/CGAL/_test_cls_tds_2.h index 78bce69ebf8..44d04c40a9c 100644 --- a/TDS_2/test/TDS_2/include/CGAL/_test_cls_tds_2.h +++ b/TDS_2/test/TDS_2/include/CGAL/_test_cls_tds_2.h @@ -44,6 +44,11 @@ template void _test_cls_tds_2( const Tds &) { + static_assert(std::is_nothrow_move_constructible::value, + "move cstr is missing"); + static_assert(std::is_nothrow_move_assignable::value, + "move assignment is missing"); + typedef typename Tds::Vertex_range Vertex_range; typedef typename Tds::Face_range Face_range; @@ -128,6 +133,34 @@ _test_cls_tds_2( const Tds &) assert(tds3.dimension()== 1); assert(tds3.number_of_vertices() == 4); assert(tds3.is_valid() ); + + // Test move-constructors and move-assignments + { + Tds tds7 = tds3; + Tds tds8{std::move(tds7)}; + Tds tds9 = tds3; + Tds tds10; + tds10 = std::move(tds9); + Tds tds11 = Tds(tds3); // construct from a temporary + Tds tds12 = std::move(tds11); + + assert(tds7.is_valid()); + assert(tds8.is_valid()); + assert(tds9.is_valid()); + assert(tds10.is_valid()); + assert(tds11.is_valid()); + assert(tds12.is_valid()); + assert(tds7.dimension()==-2); + assert(tds8.dimension()==1); + assert(tds9.dimension()==-2); + assert(tds10.dimension()==1); + assert(tds11.dimension()==-2); + assert(tds12.dimension()==1); + tds11.~Tds(); + // check tds12 is still valid after the destruction of tds11 + assert(tds12.is_valid()); + assert(tds12.dimension()==1); + } Vertex_handle w4 = tds4.insert_first(); Vertex_handle v4_1 = tds4.insert_second(); From 14b8930f791318365a55ac48d3ff226d8554ea7a Mon Sep 17 00:00:00 2001 From: Laurent Rineau Date: Fri, 31 Jan 2020 14:49:31 +0100 Subject: [PATCH 081/568] Fix a clang-tidy warning by using nullptr instead of 0 --- Spatial_sorting/include/CGAL/spatial_sort.h | 3 ++- TDS_2/include/CGAL/Triangulation_data_structure_2.h | 2 +- .../include/CGAL/Constrained_triangulation_2.h | 10 +++++----- Triangulation_2/include/CGAL/Triangulation_2.h | 6 +++--- 4 files changed, 11 insertions(+), 10 deletions(-) diff --git a/Spatial_sorting/include/CGAL/spatial_sort.h b/Spatial_sorting/include/CGAL/spatial_sort.h index 8aa44ff6af7..891889e4b50 100644 --- a/Spatial_sorting/include/CGAL/spatial_sort.h +++ b/Spatial_sorting/include/CGAL/spatial_sort.h @@ -118,7 +118,8 @@ void spatial_sort (RandomAccessIterator begin, RandomAccessIterator end, typedef std::iterator_traits ITraits; typedef typename ITraits::value_type value_type; - internal::spatial_sort(begin, end, k, policy, static_cast (0), + internal::spatial_sort(begin, end, k, policy, + static_cast (nullptr), threshold_hilbert,threshold_multiscale,ratio); } diff --git a/TDS_2/include/CGAL/Triangulation_data_structure_2.h b/TDS_2/include/CGAL/Triangulation_data_structure_2.h index 9eb67f85818..680ab3579e9 100644 --- a/TDS_2/include/CGAL/Triangulation_data_structure_2.h +++ b/TDS_2/include/CGAL/Triangulation_data_structure_2.h @@ -822,7 +822,7 @@ is_edge(Vertex_handle va, Vertex_handle vb, { Face_handle fc = va->face(); Face_handle start = fc; - if (fc == 0) return false; + if (fc == nullptr) return false; int inda, indb; do { inda=fc->index(va); diff --git a/Triangulation_2/include/CGAL/Constrained_triangulation_2.h b/Triangulation_2/include/CGAL/Constrained_triangulation_2.h index 4805a68e33e..9fe6473e79a 100644 --- a/Triangulation_2/include/CGAL/Constrained_triangulation_2.h +++ b/Triangulation_2/include/CGAL/Constrained_triangulation_2.h @@ -556,7 +556,7 @@ public: { Edge_circulator ec=incident_edges(v), done(ec); bool are_there = false; - if (ec == 0) return are_there; + if (ec == nullptr) return are_there; do { if(is_constrained(*ec)) { *out++ = *ec; @@ -572,7 +572,7 @@ public: OutputItEdges incident_constraints(Vertex_handle v, OutputItEdges out) const { Edge_circulator ec=incident_edges(v), done(ec); - if (ec == 0) return out; + if (ec == nullptr) return out; do { if(is_constrained(*ec)) *out++ = *ec; ec++; @@ -1064,7 +1064,7 @@ update_constraints_incident(Vertex_handle va, //dimension() ==2 int cwi, ccwi, indf; Face_circulator fc=incident_faces(va), done(fc); - CGAL_triangulation_assertion(fc != 0); + CGAL_triangulation_assertion(fc != nullptr); do { indf = fc->index(va); cwi=cw(indf); @@ -1091,7 +1091,7 @@ clear_constraints_incident(Vertex_handle va) Edge_circulator ec=incident_edges(va), done(ec); Face_handle f; int indf; - if ( ec != 0){ + if ( ec != nullptr){ do { f = (*ec).first ; indf = (*ec).second; @@ -1278,7 +1278,7 @@ Constrained_triangulation_2:: remove_incident_constraints(Vertex_handle v) { Edge_circulator ec=incident_edges(v), done(ec); - if (ec == 0) return; + if (ec == nullptr) return; do { if(is_constrained(*ec)) { remove_constrained_edge((*ec).first, (*ec).second);} diff --git a/Triangulation_2/include/CGAL/Triangulation_2.h b/Triangulation_2/include/CGAL/Triangulation_2.h index de91b826848..62c1d72902d 100644 --- a/Triangulation_2/include/CGAL/Triangulation_2.h +++ b/Triangulation_2/include/CGAL/Triangulation_2.h @@ -625,7 +625,7 @@ std::ptrdiff_t insert(InputIterator first, InputIterator last, typename std::iterator_traits::value_type, Point > - >::type* = NULL) + >::type* = nullptr) #else template < class InputIterator > std::ptrdiff_t @@ -1013,7 +1013,7 @@ includes_edge(Vertex_handle va, Vertex_handle vb, Orientation orient; int indv; Edge_circulator ec = incident_edges(va), done(ec); - if (ec != 0) { + if (ec != nullptr) { do { //find the index of the other vertex of *ec indv = 3 - ((*ec).first)->index(va) - (*ec).second ; @@ -2602,7 +2602,7 @@ march_locate_2D_LFC(Face_handle start, }else { lfc = Line_face_circulator(start->vertex(0), this, t); } - if(lfc==0 || lfc.collinear_outside()){ + if(lfc==nullptr || lfc.collinear_outside()){ // point t lies outside or on the convex hull // we walk on the convex hull to find it out Face_circulator fc = incident_faces(infinite_vertex()); From 75ec5c0da7cca2a393040025a3d85d2f9ac45f6d Mon Sep 17 00:00:00 2001 From: Laurent Rineau Date: Fri, 31 Jan 2020 15:37:57 +0100 Subject: [PATCH 082/568] Add move-semantic to T_2, CT_2, Dt_2, and CDT_2 Still todo: `Constrained_triangulation_plus_2`, and `Triangulation_hierarchy_2`. --- .../CGAL/Constrained_Delaunay_triangulation_2.h | 13 +++++++++++++ .../include/CGAL/Constrained_triangulation_2.h | 11 +++++++++++ .../include/CGAL/Delaunay_triangulation_2.h | 5 +++++ Triangulation_2/include/CGAL/Triangulation_2.h | 5 +++++ .../CGAL/_test_cls_const_Del_triangulation_2.h | 5 +++++ .../CGAL/_test_cls_constrained_triangulation_2.h | 5 +++++ .../CGAL/_test_cls_delaunay_triangulation_2.h | 5 +++++ .../include/CGAL/_test_cls_triangulation_2.h | 4 ++++ .../Triangulation_2/include/CGAL/_test_traits.h | 7 ------- 9 files changed, 53 insertions(+), 7 deletions(-) diff --git a/Triangulation_2/include/CGAL/Constrained_Delaunay_triangulation_2.h b/Triangulation_2/include/CGAL/Constrained_Delaunay_triangulation_2.h index a3d3af22911..5749e72c58e 100644 --- a/Triangulation_2/include/CGAL/Constrained_Delaunay_triangulation_2.h +++ b/Triangulation_2/include/CGAL/Constrained_Delaunay_triangulation_2.h @@ -141,6 +141,19 @@ public: virtual ~Constrained_Delaunay_triangulation_2() {} + // Ensure rule-of-five: define the copy- and move- constructors + // as well as the copy- and move- assignment operators. + Constrained_Delaunay_triangulation_2( + const Constrained_Delaunay_triangulation_2 &) = default; + Constrained_Delaunay_triangulation_2( + Constrained_Delaunay_triangulation_2 &&) = default; + + Constrained_Delaunay_triangulation_2 & + operator=(const Constrained_Delaunay_triangulation_2 &) = default; + + Constrained_Delaunay_triangulation_2 & + operator=(Constrained_Delaunay_triangulation_2 &&) = default; + // FLIPS bool is_flipable(Face_handle f, int i, bool perturb = true) const; void flip(Face_handle& f, int i); diff --git a/Triangulation_2/include/CGAL/Constrained_triangulation_2.h b/Triangulation_2/include/CGAL/Constrained_triangulation_2.h index 9fe6473e79a..4198a2dff18 100644 --- a/Triangulation_2/include/CGAL/Constrained_triangulation_2.h +++ b/Triangulation_2/include/CGAL/Constrained_triangulation_2.h @@ -201,6 +201,17 @@ public: //TODO Is that destructor correct ? virtual ~Constrained_triangulation_2() {} + // Ensure rule-of-five: define the copy- and move- constructors + // as well as the copy- and move- assignment operators. + Constrained_triangulation_2(const Constrained_triangulation_2 &) = default; + Constrained_triangulation_2(Constrained_triangulation_2 &&) = default; + + Constrained_triangulation_2 & + operator=(const Constrained_triangulation_2 &) = default; + + Constrained_triangulation_2 & + operator=(Constrained_triangulation_2 &&) = default; + Constrained_edges_iterator constrained_edges_begin() const { diff --git a/Triangulation_2/include/CGAL/Delaunay_triangulation_2.h b/Triangulation_2/include/CGAL/Delaunay_triangulation_2.h index b570e082a0c..dd85df9acb0 100644 --- a/Triangulation_2/include/CGAL/Delaunay_triangulation_2.h +++ b/Triangulation_2/include/CGAL/Delaunay_triangulation_2.h @@ -90,6 +90,11 @@ public: : Triangulation_2(tr) { CGAL_triangulation_postcondition(is_valid()); } + Delaunay_triangulation_2(Delaunay_triangulation_2&&) = default; + Delaunay_triangulation_2& operator=(const Delaunay_triangulation_2&) = default; + Delaunay_triangulation_2& operator=(Delaunay_triangulation_2&&) = default; + ~Delaunay_triangulation_2() = default; + template Delaunay_triangulation_2(InputIterator first, InputIterator last, const Gt& gt = Gt()) diff --git a/Triangulation_2/include/CGAL/Triangulation_2.h b/Triangulation_2/include/CGAL/Triangulation_2.h index 62c1d72902d..fa892beffc0 100644 --- a/Triangulation_2/include/CGAL/Triangulation_2.h +++ b/Triangulation_2/include/CGAL/Triangulation_2.h @@ -241,6 +241,7 @@ public: // CONSTRUCTORS Triangulation_2(const Geom_traits& geom_traits=Geom_traits()); Triangulation_2(const Triangulation_2 &tr); + Triangulation_2(Triangulation_2&&) = default; template Triangulation_2(InputIterator first, InputIterator last, @@ -253,6 +254,10 @@ public: //Assignement Triangulation_2 &operator=(const Triangulation_2 &tr); + Triangulation_2 &operator=(Triangulation_2 &&) = default; + + // Destructor + ~Triangulation_2() = default; //Helping void copy_triangulation(const Triangulation_2 &tr); diff --git a/Triangulation_2/test/Triangulation_2/include/CGAL/_test_cls_const_Del_triangulation_2.h b/Triangulation_2/test/Triangulation_2/include/CGAL/_test_cls_const_Del_triangulation_2.h index bdd49c1c738..6581267f164 100644 --- a/Triangulation_2/test/Triangulation_2/include/CGAL/_test_cls_const_Del_triangulation_2.h +++ b/Triangulation_2/test/Triangulation_2/include/CGAL/_test_cls_const_Del_triangulation_2.h @@ -30,6 +30,11 @@ template void _test_cls_const_Del_triangulation(const Triangul&) { + static_assert(std::is_nothrow_move_constructible::value, + "move cstr is missing"); + static_assert(std::is_nothrow_move_assignable::value, + "move assignment is missing"); + //typedef Triangulation Cls; typedef typename Triangul::Geom_traits Gt; diff --git a/Triangulation_2/test/Triangulation_2/include/CGAL/_test_cls_constrained_triangulation_2.h b/Triangulation_2/test/Triangulation_2/include/CGAL/_test_cls_constrained_triangulation_2.h index eaa9e936e1c..1fe1183d3db 100644 --- a/Triangulation_2/test/Triangulation_2/include/CGAL/_test_cls_constrained_triangulation_2.h +++ b/Triangulation_2/test/Triangulation_2/include/CGAL/_test_cls_constrained_triangulation_2.h @@ -92,6 +92,11 @@ template void _test_cls_constrained_triangulation(const Triang &) { + static_assert(std::is_nothrow_move_constructible::value, + "move cstr is missing"); + static_assert(std::is_nothrow_move_assignable::value, + "move assignment is missing"); + // typedef Triangulation Cls; typedef typename Triang::Geom_traits Gt; diff --git a/Triangulation_2/test/Triangulation_2/include/CGAL/_test_cls_delaunay_triangulation_2.h b/Triangulation_2/test/Triangulation_2/include/CGAL/_test_cls_delaunay_triangulation_2.h index 2204331cfe8..f9cc6fcb2aa 100644 --- a/Triangulation_2/test/Triangulation_2/include/CGAL/_test_cls_delaunay_triangulation_2.h +++ b/Triangulation_2/test/Triangulation_2/include/CGAL/_test_cls_delaunay_triangulation_2.h @@ -39,6 +39,11 @@ template void _test_cls_delaunay_triangulation_2( const Del & ) { + static_assert(std::is_nothrow_move_constructible::value, + "move cstr is missing"); + static_assert(std::is_nothrow_move_assignable::value, + "move assignment is missing"); + //typedef Del Delaunay; typedef typename Del::Point Point; typedef typename Del::Locate_type Locate_type; diff --git a/Triangulation_2/test/Triangulation_2/include/CGAL/_test_cls_triangulation_2.h b/Triangulation_2/test/Triangulation_2/include/CGAL/_test_cls_triangulation_2.h index ce242c40be3..498ff9139be 100644 --- a/Triangulation_2/test/Triangulation_2/include/CGAL/_test_cls_triangulation_2.h +++ b/Triangulation_2/test/Triangulation_2/include/CGAL/_test_cls_triangulation_2.h @@ -39,6 +39,10 @@ template void _test_cls_triangulation_2( const Triangul & ) { + static_assert(std::is_nothrow_move_constructible::value, + "move cstr is missing"); + static_assert(std::is_nothrow_move_assignable::value, + "move assignment is missing"); //typedef Triangulation Cls; // We assume the traits class has been tested already diff --git a/Triangulation_2/test/Triangulation_2/include/CGAL/_test_traits.h b/Triangulation_2/test/Triangulation_2/include/CGAL/_test_traits.h index 10e712567e9..4eaf0541a29 100644 --- a/Triangulation_2/test/Triangulation_2/include/CGAL/_test_traits.h +++ b/Triangulation_2/test/Triangulation_2/include/CGAL/_test_traits.h @@ -36,7 +36,6 @@ protected: double _x, _y; public: Triangulation_test_point() {} - Triangulation_test_point(const Point &p) : _x(p.test_x()), _y(p.test_y()) {} Triangulation_test_point(double x, double y) : _x(x), _y(y) {} Triangulation_test_point(double hx, double hy, double hw) : _x(hx/hw), _y(hy/hw) @@ -47,7 +46,6 @@ public: bool compare(const Point &p) const { return test_x()==p.test_x() && test_y()==p.test_y(); } bool uncompare(const Point &p) const { return !compare(p); } - Point &operator=(const Point &p) { _x=p.test_x(); _y=p.test_y(); return *this; } void test_set(TESTFT x, TESTFT y) { _x=x; _y=y; } bool operator==(const Point &p) const {return this->compare(p);} }; @@ -436,11 +434,6 @@ public: typedef Triangulation_test_Construct_ray_2 Construct_ray_2; - _Triangulation_test_traits() {} - _Triangulation_test_traits(const _Triangulation_test_traits &) {} - _Triangulation_test_traits &operator= - (const _Triangulation_test_traits &) { return *this; } - Less_x_2 less_x_2_object() const { return Less_x_2();} From 94be80c2ebfbbf1becd6fcde854868e3195823d6 Mon Sep 17 00:00:00 2001 From: Laurent Rineau Date: Fri, 31 Jan 2020 16:27:41 +0100 Subject: [PATCH 083/568] fix clang-tidy warnings --- .../include/CGAL/Constrained_triangulation_plus_2.h | 4 ++-- .../internal/Polyline_constraint_hierarchy_2.h | 8 ++------ .../include/CGAL/Triangulation_hierarchy_2.h | 2 +- .../CGAL/Triangulation_hierarchy_vertex_base_2.h | 10 +++++----- 4 files changed, 10 insertions(+), 14 deletions(-) diff --git a/Triangulation_2/include/CGAL/Constrained_triangulation_plus_2.h b/Triangulation_2/include/CGAL/Constrained_triangulation_plus_2.h index dad024bd902..79e3553a324 100644 --- a/Triangulation_2/include/CGAL/Constrained_triangulation_plus_2.h +++ b/Triangulation_2/include/CGAL/Constrained_triangulation_plus_2.h @@ -398,7 +398,7 @@ public: ++beg; Face_container fc(*this); - Constraint_id head = 0, tail = 0; + Constraint_id head = nullptr, tail = nullptr; if(pos != beg){ // split off head --pos; @@ -479,7 +479,7 @@ public: return pos; } - Constraint_id head = 0, tail = 0; + Constraint_id head = nullptr, tail = nullptr; Vertices_in_constraint_iterator bit = vertices_in_constraint_begin(cid); Vertices_in_constraint_iterator pred = pos; --pred; diff --git a/Triangulation_2/include/CGAL/Triangulation_2/internal/Polyline_constraint_hierarchy_2.h b/Triangulation_2/include/CGAL/Triangulation_2/internal/Polyline_constraint_hierarchy_2.h index 91d58c4b9dc..e7eb16a5372 100644 --- a/Triangulation_2/include/CGAL/Triangulation_2/internal/Polyline_constraint_hierarchy_2.h +++ b/Triangulation_2/include/CGAL/Triangulation_2/internal/Polyline_constraint_hierarchy_2.h @@ -154,10 +154,6 @@ public: public: Context() : enclosing(nullptr) {} - Context(const Context& hc) - : enclosing(hc.enclosing), pos(hc.pos) - {} - Vertex_it vertices_begin()const { return enclosing->skip_begin();} Vertex_it current()const {return pos;} Vertex_it vertices_end()const {return enclosing->skip_end();} @@ -499,7 +495,7 @@ swap(Constraint_id first, Constraint_id second){ // and replace the context of the constraint for(Context_iterator ctit=hcl->begin(); ctit != hcl->end(); ctit++) { if(ctit->enclosing == first.vl_ptr()){ - ctit->enclosing = 0; + ctit->enclosing = nullptr; break; } } @@ -530,7 +526,7 @@ swap(Constraint_id first, Constraint_id second){ // and replace the context of the constraint for(Context_iterator ctit=hcl->begin(); ctit != hcl->end(); ctit++) { - if(ctit->enclosing == 0){ + if(ctit->enclosing == nullptr){ ctit->enclosing = second.vl_ptr(); break; } diff --git a/Triangulation_2/include/CGAL/Triangulation_hierarchy_2.h b/Triangulation_2/include/CGAL/Triangulation_hierarchy_2.h index 30fa8deac9b..a8262f522e2 100644 --- a/Triangulation_2/include/CGAL/Triangulation_hierarchy_2.h +++ b/Triangulation_2/include/CGAL/Triangulation_hierarchy_2.h @@ -724,7 +724,7 @@ locate_in_all(const Point& p, level--; } - for (int i=level+1; i 0) { pos[level]=position=hierarchy[level]->locate(p, position); // locate at that level from "position" diff --git a/Triangulation_2/include/CGAL/Triangulation_hierarchy_vertex_base_2.h b/Triangulation_2/include/CGAL/Triangulation_hierarchy_vertex_base_2.h index e70c3851c51..65f15868cbf 100644 --- a/Triangulation_2/include/CGAL/Triangulation_hierarchy_vertex_base_2.h +++ b/Triangulation_2/include/CGAL/Triangulation_hierarchy_vertex_base_2.h @@ -41,13 +41,13 @@ public: }; Triangulation_hierarchy_vertex_base_2() - : Base(), _up(0), _down(0) + : Base() {} Triangulation_hierarchy_vertex_base_2(const Point & p, Face_handle f) - : Base(p,f), _up(0), _down(0) + : Base(p,f) {} Triangulation_hierarchy_vertex_base_2(const Point & p) - : Base(p), _up(0), _down(0) + : Base(p) {} Vertex_handle up() {return _up;} @@ -57,8 +57,8 @@ public: private: - Vertex_handle _up; // same vertex one level above - Vertex_handle _down; // same vertex one level below + Vertex_handle _up = nullptr; // same vertex one level above + Vertex_handle _down = nullptr; // same vertex one level below }; } //namespace CGAL From 20bb2c8428821cd80dd0d00103b2113f75634612 Mon Sep 17 00:00:00 2001 From: Laurent Rineau Date: Fri, 31 Jan 2020 16:28:07 +0100 Subject: [PATCH 084/568] Add move-semantic to CT_plus_2 and Tr_hierarchy_2 --- .../CGAL/Constrained_triangulation_plus_2.h | 4 +++ .../Polyline_constraint_hierarchy_2.h | 4 ++- .../include/CGAL/Triangulation_hierarchy_2.h | 32 +++++++++++++++++-- .../include/CGAL/Triangulation_hierarchy_3.h | 13 +++++--- 4 files changed, 45 insertions(+), 8 deletions(-) diff --git a/Triangulation_2/include/CGAL/Constrained_triangulation_plus_2.h b/Triangulation_2/include/CGAL/Constrained_triangulation_plus_2.h index 79e3553a324..00128211057 100644 --- a/Triangulation_2/include/CGAL/Constrained_triangulation_plus_2.h +++ b/Triangulation_2/include/CGAL/Constrained_triangulation_plus_2.h @@ -216,6 +216,8 @@ public: , hierarchy(Vh_less_xy(this)) { copy_triangulation(ctp);} + Constrained_triangulation_plus_2(Constrained_triangulation_plus_2&&) = default; + virtual ~Constrained_triangulation_plus_2() {} Constrained_triangulation_plus_2 & operator=(const Constrained_triangulation_plus_2& ctp) @@ -224,6 +226,8 @@ public: return *this; } + Constrained_triangulation_plus_2& operator=(Constrained_triangulation_plus_2&&) = default; + template Constrained_triangulation_plus_2(InputIterator first, InputIterator last, diff --git a/Triangulation_2/include/CGAL/Triangulation_2/internal/Polyline_constraint_hierarchy_2.h b/Triangulation_2/include/CGAL/Triangulation_2/internal/Polyline_constraint_hierarchy_2.h index e7eb16a5372..bf89ead3c58 100644 --- a/Triangulation_2/include/CGAL/Triangulation_2/internal/Polyline_constraint_hierarchy_2.h +++ b/Triangulation_2/include/CGAL/Triangulation_2/internal/Polyline_constraint_hierarchy_2.h @@ -182,10 +182,12 @@ public: : comp(comp) , sc_to_c_map(Pair_compare(comp)) { } - Polyline_constraint_hierarchy_2(const Polyline_constraint_hierarchy_2& ch); + Polyline_constraint_hierarchy_2(const Polyline_constraint_hierarchy_2& ch); + Polyline_constraint_hierarchy_2(Polyline_constraint_hierarchy_2&&) = default; ~Polyline_constraint_hierarchy_2(){ clear();} void clear(); Polyline_constraint_hierarchy_2& operator=(const Polyline_constraint_hierarchy_2& ch); + Polyline_constraint_hierarchy_2& operator=(Polyline_constraint_hierarchy_2&& ch) = default; // Query bool is_subconstrained_edge(T va, T vb) const; diff --git a/Triangulation_2/include/CGAL/Triangulation_hierarchy_2.h b/Triangulation_2/include/CGAL/Triangulation_hierarchy_2.h index a8262f522e2..9dfb0e4e010 100644 --- a/Triangulation_2/include/CGAL/Triangulation_hierarchy_2.h +++ b/Triangulation_2/include/CGAL/Triangulation_hierarchy_2.h @@ -37,6 +37,7 @@ #include #include #include +#include namespace CGAL { @@ -83,13 +84,25 @@ public: private: // here is the stack of triangulations which form the hierarchy - Tr_Base* hierarchy[Triangulation_hierarchy_2__maxlevel]; + std::array hierarchy; boost::rand48 random; public: Triangulation_hierarchy_2(const Geom_traits& traits = Geom_traits()); Triangulation_hierarchy_2(const Triangulation_hierarchy_2& tr); + Triangulation_hierarchy_2(Triangulation_hierarchy_2&& other) + noexcept( noexcept(Tr_Base(std::move(other))) ) + : Tr_Base(std::move(other)) + , random(std::move(other.random)) + { + hierarchy[0] = this; + for(int i=1; i Triangulation_hierarchy_2(InputIterator first, InputIterator beyond, const Geom_traits& traits = Geom_traits()) @@ -103,11 +116,25 @@ public: } Triangulation_hierarchy_2 &operator=(const Triangulation_hierarchy_2& tr); + + Triangulation_hierarchy_2 & operator=(Triangulation_hierarchy_2&& other) + noexcept( noexcept(Triangulation_hierarchy_2(std::move(other))) ) + { + static_cast(*this) = std::move(other); + hierarchy[0] = this; + for(int i=1; iTr_Base::swap(tr))); void clear(); // CHECKING @@ -366,6 +393,7 @@ template void Triangulation_hierarchy_2:: swap(Triangulation_hierarchy_2 &tr) + noexcept(noexcept(this->Tr_Base::swap(tr))) { Tr_Base* temp; Tr_Base::swap(tr); diff --git a/Triangulation_3/include/CGAL/Triangulation_hierarchy_3.h b/Triangulation_3/include/CGAL/Triangulation_hierarchy_3.h index f936cacdda8..e92fbf94e07 100644 --- a/Triangulation_3/include/CGAL/Triangulation_hierarchy_3.h +++ b/Triangulation_3/include/CGAL/Triangulation_hierarchy_3.h @@ -139,12 +139,15 @@ public: return *this; } - Triangulation_hierarchy_3 & operator=(Triangulation_hierarchy_3&& tr) - noexcept( noexcept(Triangulation_hierarchy_3(std::move(tr))) && - noexcept(this->swap(std::declval())) ) + Triangulation_hierarchy_3 & operator=(Triangulation_hierarchy_3&& other) + noexcept( noexcept(Triangulation_hierarchy_3(std::move(other))) ) { - Triangulation_hierarchy_3 tmp(std::move(tr)); - swap(tmp); + static_cast(*this) = std::move(other); + hierarchy[0] = this; + for(int i=1; i Date: Fri, 31 Jan 2020 16:55:05 +0100 Subject: [PATCH 085/568] fix surface patch and subdomain indices during split all of them should be restored after split, which creates twice as many cells and is likely to recycle old cells, with their outdated c3t3 indices --- .../internal/split_long_edges.h | 105 +++++++++++++----- 1 file changed, 79 insertions(+), 26 deletions(-) diff --git a/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/split_long_edges.h b/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/split_long_edges.h index 7aab960ccfc..308a7f75593 100644 --- a/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/split_long_edges.h +++ b/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/split_long_edges.h @@ -42,8 +42,9 @@ namespace internal typename C3t3::Vertex_handle split_edge(const typename C3t3::Edge& e, C3t3& c3t3) { - typedef typename C3t3::Triangulation Tr; - typedef typename C3t3::Subdomain_index Subdomain_index; + typedef typename C3t3::Triangulation Tr; + typedef typename C3t3::Subdomain_index Subdomain_index; + typedef typename C3t3::Surface_patch_index Surface_patch_index; typedef typename Tr::Geom_traits::Point_3 Point; typedef typename Tr::Facet Facet; typedef typename Tr::Vertex_handle Vertex_handle; @@ -51,33 +52,52 @@ namespace internal typedef typename Tr::Cell_circulator Cell_circulator; Tr& tr = c3t3.triangulation(); - Vertex_handle v1 = e.first->vertex(e.second); - Vertex_handle v2 = e.first->vertex(e.third); + const Vertex_handle v1 = e.first->vertex(e.second); + const Vertex_handle v2 = e.first->vertex(e.third); //backup subdomain info of incident cells before making changes short dimension = (c3t3.is_in_complex(e)) ? 1 : 3; - boost::unordered_map info; + boost::unordered_map cells_info; + boost::unordered_map > facets_info; Cell_circulator circ = tr.incident_cells(e); Cell_circulator end = circ; - Subdomain_index prev = c3t3.subdomain_index(circ); - Subdomain_index curr = prev; do { + const int index_v1 = circ->index(v1); + const int index_v2 = circ->index(v2); + //keys are the opposite facets to the ones not containing e, //because they will not be modified - Facet opp_facet = tr.mirror_facet(Facet(circ, circ->index(v1))); - info.insert(std::make_pair(opp_facet, c3t3.subdomain_index(circ))); + const Subdomain_index subdomain = c3t3.subdomain_index(circ); + const Facet opp_facet1 = tr.mirror_facet(Facet(circ, index_v1)); + const Facet opp_facet2 = tr.mirror_facet(Facet(circ, index_v2)); - opp_facet = tr.mirror_facet(Facet(circ, circ->index(v2))); - info.insert(std::make_pair(opp_facet, c3t3.subdomain_index(circ))); + // volume data + cells_info.insert(std::make_pair(opp_facet1, subdomain)); + cells_info.insert(std::make_pair(opp_facet2, subdomain)); + if (c3t3.is_in_complex(circ)) + c3t3.remove_from_complex(circ); + + // surface data for facets of the cells to be split + const int findex = CGAL::Triangulation_utils_3::next_around_edge(index_v1, index_v2); + if (c3t3.is_in_complex(circ, findex)) + { + if (dimension == 3) + dimension = 2; + } + Surface_patch_index patch = c3t3.surface_patch_index(circ, findex); + Vertex_handle opp_vertex = circ->vertex(findex); + facets_info.insert(std::make_pair(opp_facet1, + std::make_pair(opp_vertex, patch))); + facets_info.insert(std::make_pair(opp_facet2, + std::make_pair(opp_vertex, patch))); + + if(c3t3.is_in_complex(circ, findex)) + c3t3.remove_from_complex(circ, findex); ++circ; - prev = curr; - curr = c3t3.subdomain_index(circ); - if (prev != curr && dimension == 3) - dimension = 2; } while (circ != end); // insert midpoint @@ -85,18 +105,54 @@ namespace internal const Point m = tr.geom_traits().construct_midpoint_3_object() (point(v1->point()), point(v2->point())); new_v->set_point(typename Tr::Point(m)); + new_v->set_dimension(dimension); - // update dimension - c3t3.set_dimension(new_v, dimension); - + // update c3t3 with subdomain and surface patch indices std::vector new_cells; tr.incident_cells(new_v, std::back_inserter(new_cells)); - for (std::size_t i = 0; i < new_cells.size(); ++i) + for (Cell_handle new_cell : new_cells) { - Cell_handle nci = new_cells[i]; - Facet fi(nci, nci->index(new_v)); - Subdomain_index n_index = info.at(tr.mirror_facet(fi)); - c3t3.set_subdomain_index(nci, n_index); + const Facet fi(new_cell, new_cell->index(new_v)); + const Facet mfi = tr.mirror_facet(fi); + + //get subdomain info back + CGAL_assertion(cells_info.find(mfi) != cells_info.end()); + Subdomain_index n_index = cells_info.at(mfi); + if (Subdomain_index() != n_index) + c3t3.add_to_complex(new_cell, n_index); + else + new_cell->set_subdomain_index(Subdomain_index()); + + // get surface info back + CGAL_assertion(facets_info.find(mfi) != facets_info.end()); + const std::pair v_and_opp_patch = facets_info.at(mfi); + + // facet opposite to new_v (status wrt c3t3 is unchanged) + new_cell->set_surface_patch_index(new_cell->index(new_v), + mfi.first->surface_patch_index(mfi.second)); + + // new half-facet (added or not to c3t3 depending on the stored surface patch index) + if (Surface_patch_index() == v_and_opp_patch.second) + new_cell->set_surface_patch_index(new_cell->index(v_and_opp_patch.first), + Surface_patch_index()); + else + c3t3.add_to_complex(new_cell, + new_cell->index(v_and_opp_patch.first), + v_and_opp_patch.second); + + // newly created internal facet + for (int i = 0; i < 4; ++i) + { + const Vertex_handle vi = new_cell->vertex(i); + if (vi == v1 || vi == v2) + { + new_cell->set_surface_patch_index(i, Surface_patch_index()); + break; + } + } + + //the 4th facet (new_v, v_and_opp_patch.first, v1 or v2) + // will have its patch tagged from the other side, if needed } return new_v; @@ -111,8 +167,6 @@ namespace internal { if (is_outside(e, c3t3, imaginary_index, cell_selector)) return false; - if (is_imaginary(e, c3t3, imaginary_index)) - return false; if (protect_boundaries) { @@ -216,7 +270,6 @@ namespace internal visitor.before_split(tr, edge); Vertex_handle vh = split_edge(edge, c3t3); visitor.after_split(tr, vh); - //CGAL_assertion(tr.is_valid(true)); #ifdef CGAL_TETRAHEDRAL_REMESHING_DEBUG ofs << vh->point() << std::endl; From d59ef5021d4259903c4d92bad4dbb108f1da8345 Mon Sep 17 00:00:00 2001 From: Jane Tournois Date: Mon, 3 Feb 2020 16:47:28 +0100 Subject: [PATCH 086/568] fix split() step by fixing is_outside(edge) - go on removing stuff about imaginary vertices - after this commit, split() is fixed and collapse() causes holes on the surface --- .../internal/collapse_short_edges.h | 8 +-- .../internal/split_long_edges.h | 31 ++------ .../tetrahedral_adaptive_remeshing_impl.h | 56 ++++++++------- .../internal/tetrahedral_remeshing_helpers.h | 72 ++++++------------- 4 files changed, 62 insertions(+), 105 deletions(-) diff --git a/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/collapse_short_edges.h b/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/collapse_short_edges.h index 571568f81fb..d5a4c2e7465 100644 --- a/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/collapse_short_edges.h +++ b/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/collapse_short_edges.h @@ -896,9 +896,7 @@ namespace internal const typename C3T3::Subdomain_index& imaginary_index, CellSelector cell_selector) { - if (is_outside(e, c3t3, imaginary_index, cell_selector)) - return false; - if (is_imaginary(e, c3t3, imaginary_index)) + if (is_outside(e, c3t3, cell_selector)) return false; if (protect_boundaries) @@ -909,7 +907,7 @@ namespace internal return false; #ifdef CGAL_TETRAHEDRAL_REMESHING_DEBUG - if (!is_inside(e, c3t3, imaginary_index, cell_selector)) + if (!is_inside(e, c3t3, cell_selector)) { std::cerr << "e is not inside!?" << std::endl; typename C3T3::Vertex_handle v1 = e.first->vertex(e.second); @@ -918,7 +916,7 @@ namespace internal } #endif - CGAL_assertion(is_inside(e, c3t3, imaginary_index, cell_selector)); + CGAL_assertion(is_inside(e, c3t3, cell_selector)); return true; } else diff --git a/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/split_long_edges.h b/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/split_long_edges.h index 308a7f75593..aaea7f9a177 100644 --- a/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/split_long_edges.h +++ b/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/split_long_edges.h @@ -162,10 +162,9 @@ namespace internal bool can_be_split(const typename C3T3::Edge& e, const C3T3& c3t3, const bool protect_boundaries, - const typename C3T3::Subdomain_index& imaginary_index, CellSelector cell_selector) { - if (is_outside(e, c3t3, imaginary_index, cell_selector)) + if (is_outside(e, c3t3, cell_selector)) return false; if (protect_boundaries) @@ -176,7 +175,7 @@ namespace internal return false; #ifdef CGAL_TETRAHEDRAL_REMESHING_DEBUG - if (!is_inside(e, c3t3, imaginary_index, cell_selector)) + if (!is_inside(e, c3t3, cell_selector)) { std::cerr << "e is not inside!?" << std::endl; typename C3T3::Vertex_handle v1 = e.first->vertex(e.second); @@ -185,7 +184,7 @@ namespace internal } #endif - CGAL_assertion(is_inside(e, c3t3, imaginary_index, cell_selector)); + CGAL_assertion(is_inside(e, c3t3, cell_selector)); return true; } else @@ -198,7 +197,6 @@ namespace internal void split_long_edges(C3T3& c3t3, const typename C3T3::Triangulation::Geom_traits::FT& high, const bool protect_boundaries, - const typename C3T3::Subdomain_index& imaginary_index, CellSelector cell_selector, Visitor& visitor) { @@ -230,7 +228,7 @@ namespace internal eit != tr.finite_edges_end(); ++eit) { Edge e = *eit; - if (!can_be_split(e, c3t3, protect_boundaries, imaginary_index, cell_selector)) + if (!can_be_split(e, c3t3, protect_boundaries, cell_selector)) continue; typename Gt::Compute_squared_length_3 sql @@ -264,7 +262,7 @@ namespace internal Edge edge(cell, i1, i2); //check that splittability has not changed - if (!can_be_split(edge, c3t3, protect_boundaries, imaginary_index, cell_selector)) + if (!can_be_split(edge, c3t3, protect_boundaries, cell_selector)) continue; visitor.before_split(tr, edge); @@ -274,27 +272,12 @@ namespace internal #ifdef CGAL_TETRAHEDRAL_REMESHING_DEBUG ofs << vh->point() << std::endl; #endif - if (vh != Vertex_handle()) - { + #if defined(CGAL_TETRAHEDRAL_REMESHING_VERBOSE_PROGRESS) \ || defined(CGAL_TETRAHEDRAL_REMESHING_VERBOSE) + if (vh != Vertex_handle()) ++nb_splits; #endif - ////insert newly created edges if needed - //std::vector new_edges; - //tr.incident_edges(vh, std::back_inserter(new_edges)); - // - //for (std::size_t i = 0; i < new_edges.size(); ++i) - //{ - // const Edge& ei = new_edges[i]; - // Segment seg(ei.first->vertex(ei.second)->point(), - // ei.first->vertex(ei.third)->point()); - // - // const FT sqlen_i = seg.squared_length(); - // if (sqlen_i > sq_high) - // long_edges.insert(long_edge(make_vertex_pair(ei), sqlen_i)); - //} - } #ifdef CGAL_TETRAHEDRAL_REMESHING_VERBOSE_PROGRESS std::cout << "\rSplit (" << high << ")... (" diff --git a/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/tetrahedral_adaptive_remeshing_impl.h b/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/tetrahedral_adaptive_remeshing_impl.h index a8399c1e539..c72c8395b3f 100644 --- a/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/tetrahedral_adaptive_remeshing_impl.h +++ b/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/tetrahedral_adaptive_remeshing_impl.h @@ -145,6 +145,7 @@ namespace internal #ifdef CGAL_DUMP_REMESHING_STEPS CGAL::Tetrahedral_remeshing::debug::dump_without_imaginary(m_c3t3.triangulation(), "00-init-no-imaginary.mesh", m_imaginary_index); + CGAL::Tetrahedral_remeshing::debug::dump_binary(m_c3t3, "00-init.binary.cgal"); #endif } @@ -169,8 +170,9 @@ namespace internal init_c3t3(ecmap, fcmap); #ifdef CGAL_DUMP_REMESHING_STEPS - CGAL::Tetrahedral_remeshing::debug::dump_without_imaginary(m_c3t3.triangulation(), - "00-init-no-imaginary.mesh", m_imaginary_index); + //CGAL::Tetrahedral_remeshing::debug::dump_without_imaginary(m_c3t3.triangulation(), + // "00-init-no-imaginary.mesh", m_imaginary_index); + CGAL::Tetrahedral_remeshing::debug::dump_binary(m_c3t3, "00-init.binary.cgal"); #endif } @@ -179,26 +181,26 @@ namespace internal return m_imaginary_index; } - void preprocess() - { -#ifdef CGAL_TETRAHEDRAL_REMESHING_VERBOSE - std::cout << "Preprocess..."; - std::cout.flush(); -#endif - - add_layer_of_imaginary_tets(tr(), m_imaginary_index); - CGAL_assertion(tr().tds().is_valid(true)); - -#ifdef CGAL_DUMP_REMESHING_STEPS - CGAL::Tetrahedral_remeshing::debug::dump_triangulation_cells(tr(), "0-preprocess.mesh"); - CGAL::Tetrahedral_remeshing::debug::dump_without_imaginary(tr(), - "0-preprocess-no-imaginary.mesh", m_imaginary_index); - CGAL::Tetrahedral_remeshing::debug::dump_binary(m_c3t3, "0-preprocess.binary.cgal"); -#endif -#ifdef CGAL_TETRAHEDRAL_REMESHING_VERBOSE - std::cout << "done." << std::endl; -#endif - } +// void preprocess() +// { +//#ifdef CGAL_TETRAHEDRAL_REMESHING_VERBOSE +// std::cout << "Preprocess..."; +// std::cout.flush(); +//#endif +// +// add_layer_of_imaginary_tets(tr(), m_imaginary_index); +// CGAL_assertion(tr().tds().is_valid(true)); +// +//#ifdef CGAL_DUMP_REMESHING_STEPS +// CGAL::Tetrahedral_remeshing::debug::dump_triangulation_cells(tr(), "0-preprocess.mesh"); +// CGAL::Tetrahedral_remeshing::debug::dump_without_imaginary(tr(), +// "0-preprocess-no-imaginary.mesh", m_imaginary_index); +// CGAL::Tetrahedral_remeshing::debug::dump_binary(m_c3t3, "0-preprocess.binary.cgal"); +//#endif +//#ifdef CGAL_TETRAHEDRAL_REMESHING_VERBOSE +// std::cout << "done." << std::endl; +//#endif +// } void split() { @@ -206,7 +208,7 @@ namespace internal const FT target_edge_length = m_sizing(CGAL::ORIGIN); const FT emax = FT(4)/FT(3) * target_edge_length; - split_long_edges(m_c3t3, emax, m_protect_boundaries, m_imaginary_index, + split_long_edges(m_c3t3, emax, m_protect_boundaries, m_cell_selector, m_visitor); CGAL_assertion(tr().tds().is_valid(true)); @@ -504,7 +506,7 @@ private: void remesh(const std::size_t& max_it, const std::size_t& nb_extra_iterations) { - preprocess(); +// preprocess(); std::size_t it_nb = 0; while (it_nb++ < max_it) @@ -517,8 +519,8 @@ private: split(); collapse(); } - flip(); - smooth(); +// flip(); +// smooth(); #ifdef CGAL_TETRAHEDRAL_REMESHING_VERBOSE std::cout << "# Iteration " << it_nb << " done : " @@ -551,7 +553,7 @@ private: #endif } - postprocess(); //remove imaginary cells +// postprocess(); //remove imaginary cells finalize(); //triangulation() is now empty diff --git a/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/tetrahedral_remeshing_helpers.h b/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/tetrahedral_remeshing_helpers.h index f60a54a84ac..caebebdd128 100644 --- a/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/tetrahedral_remeshing_helpers.h +++ b/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/tetrahedral_remeshing_helpers.h @@ -731,17 +731,7 @@ namespace Tetrahedral_remeshing const C3t3& c3t3, const typename C3t3::Subdomain_index& imaginary_index) { - typedef typename C3t3::Triangulation::Cell_handle Cell_handle; - - std::vector cells; - c3t3.triangulation().incident_cells(v, std::back_inserter(cells)); - - BOOST_FOREACH(Cell_handle c, cells) - { - if (c->subdomain_index() != imaginary_index) - return false; - } - return true; + return false; } /** @@ -754,24 +744,13 @@ namespace Tetrahedral_remeshing const C3t3& c3t3, const typename C3t3::Subdomain_index& imaginary_index) { - typedef typename C3t3::Triangulation::Cell_circulator Cell_circulator; - Cell_circulator circ = c3t3.triangulation().incident_cells(edge); - Cell_circulator done = circ; - do - { - if (c3t3.is_in_complex(circ) - && circ->subdomain_index() != imaginary_index) - return false; - } while (++circ != done); - - return true; + return false; } template bool is_outside(const typename C3t3::Edge & edge, - const C3t3& c3t3, - const typename C3t3::Subdomain_index& imaginary_index, - CellSelector cell_selector) + const C3t3& c3t3, + CellSelector cell_selector) { typedef typename C3t3::Triangulation::Cell_circulator Cell_circulator; Cell_circulator circ = c3t3.triangulation().incident_cells(edge); @@ -779,20 +758,18 @@ namespace Tetrahedral_remeshing do { // is cell infinite? - if (c3t3.triangulation().is_infinite(circ)) - continue; - // is cell imaginary? - if (c3t3.is_in_complex(circ) && circ->subdomain_index() == imaginary_index) - continue; + if (!c3t3.triangulation().is_infinite(circ)) + return false; + // is cell in complex? + if (c3t3.is_in_complex(circ)) + return false; // circ does not belong to the selection - if (!cell_selector(circ)) - continue; + if (cell_selector(circ)) + return false; - // none of the above conditions was met - return false; } while (circ != done); - return true; //all cells have met the loop conditions + return false; //all incident cells are outside or infinite } template @@ -815,17 +792,14 @@ namespace Tetrahedral_remeshing template bool is_inside(const typename C3t3::Edge& edge, - const C3t3& c3t3, - const typename C3t3::Subdomain_index& imaginary_index, - CellSelector cell_selector) + const C3t3& c3t3, + CellSelector cell_selector) { typedef typename C3t3::Triangulation::Cell_circulator Cell_circulator; Cell_circulator circ = c3t3.triangulation().incident_cells(edge); Cell_circulator done = circ; const typename C3t3::Subdomain_index si = circ->subdomain_index(); - if (si == imaginary_index || !c3t3.is_in_complex(circ)) - return false; do { if (c3t3.triangulation().is_infinite(circ)) @@ -956,7 +930,7 @@ namespace Tetrahedral_remeshing // && !is_boundary_edge(e, c3t3) // && !is_on_hull(e, c3t3) // && !is_imaginary(e, c3t3, imaginary_index)) - if (is_inside(e, c3t3, imaginary_index, cell_selector)) + if (is_inside(e, c3t3, cell_selector)) { *oit++ = make_vertex_pair(e); } @@ -979,8 +953,8 @@ namespace Tetrahedral_remeshing BOOST_FOREACH(typename Bimap::left_const_reference it, edges.left) { - ofs << "2 " << it.first.first->point() - << " " << it.first.second->point() << std::endl; + ofs << "2 " << point(it.first.first->point()) + << " " << point(it.first.second->point()) << std::endl; } ofs.close(); } @@ -989,10 +963,10 @@ namespace Tetrahedral_remeshing void dump_facet(const Facet& f, OutputStream& os) { os << "4 "; - os << f.first->vertex((f.second + 1) % 4)->point() << " " - << f.first->vertex((f.second + 2) % 4)->point() << " " - << f.first->vertex((f.second + 3) % 4)->point() << " " - << f.first->vertex((f.second + 1) % 4)->point(); + os << point(f.first->vertex((f.second + 1) % 4)->point()) << " " + << point(f.first->vertex((f.second + 2) % 4)->point()) << " " + << point(f.first->vertex((f.second + 3) % 4)->point()) << " " + << point(f.first->vertex((f.second + 1) % 4)->point()); os << std::endl; } @@ -1063,7 +1037,7 @@ namespace Tetrahedral_remeshing for (typename Bimap_t::right_iterator vit = vertices.right.begin(); vit != vertices.right.end(); ++vit) { - ofs << vit->second->point() << std::endl; + ofs << point(vit->second->point()) << std::endl; } //write facets @@ -1255,7 +1229,7 @@ namespace Tetrahedral_remeshing for (typename Bimap_t::right_iterator vit = vertices.right.begin(); vit != vertices.right.end(); ++vit) { - ofs << vit->second->point() << std::endl; + ofs << point(vit->second->point()) << std::endl; } //write facets From 4261d4635bc76ac19d51a495d7e6ff26641ac8c4 Mon Sep 17 00:00:00 2001 From: Laurent Rineau Date: Tue, 4 Feb 2020 10:12:29 +0100 Subject: [PATCH 087/568] Less use of swap --- ...angulation_cell_base_with_circumcenter_3.h | 7 +++---- .../include/CGAL/Regular_triangulation_3.h | 21 ++++++++----------- 2 files changed, 12 insertions(+), 16 deletions(-) diff --git a/Triangulation_3/include/CGAL/Delaunay_triangulation_cell_base_with_circumcenter_3.h b/Triangulation_3/include/CGAL/Delaunay_triangulation_cell_base_with_circumcenter_3.h index 44610ed6de8..7c4239af9b2 100644 --- a/Triangulation_3/include/CGAL/Delaunay_triangulation_cell_base_with_circumcenter_3.h +++ b/Triangulation_3/include/CGAL/Delaunay_triangulation_cell_base_with_circumcenter_3.h @@ -65,9 +65,8 @@ public: Delaunay_triangulation_cell_base_with_circumcenter_3 (Delaunay_triangulation_cell_base_with_circumcenter_3 &&c) - : Cb(std::move(c)), circumcenter_(nullptr) + : Cb(std::move(c)), circumcenter_(std::exchange(c.circumcenter_, nullptr)) { - std::swap(circumcenter_, c.circumcenter_); } Delaunay_triangulation_cell_base_with_circumcenter_3& @@ -81,8 +80,8 @@ public: Delaunay_triangulation_cell_base_with_circumcenter_3& operator=(Delaunay_triangulation_cell_base_with_circumcenter_3 &&c) { - Delaunay_triangulation_cell_base_with_circumcenter_3 tmp=std::move(c); - std::swap(tmp, *this); + Cb::operator=(std::move(c)); + circumcenter_ = std::exchange(c.circumcenter_, nullptr); return *this; } diff --git a/Triangulation_3/include/CGAL/Regular_triangulation_3.h b/Triangulation_3/include/CGAL/Regular_triangulation_3.h index 22122a53e41..8502a68264d 100644 --- a/Triangulation_3/include/CGAL/Regular_triangulation_3.h +++ b/Triangulation_3/include/CGAL/Regular_triangulation_3.h @@ -205,14 +205,13 @@ public: void swap(Regular_triangulation_3& tr) noexcept(noexcept(this->Tr_Base::swap(tr))) { - // The 'vertices' and 'hidden_points' members of 'hidden_point_visitor' should be empty - // as they are only filled (and cleared) during the insertion of a point. - // Hidden points are not stored there, but rather in cells. Thus, the only thing that must be set - // is the triangulation pointer. - Hidden_point_visitor new_hpv(this); - using std::swap; - swap(hidden_point_visitor, new_hpv); - + // The 'vertices' and 'hidden_points' members of + // 'hidden_point_visitor' should be empty as they are only filled + // (and cleared) during the insertion of a point. Hidden points + // are not stored there, but rather in cells. Thus, the only thing + // that must be set is the triangulation pointer, and it is + // already correctly set. There is nothing to do about + // 'hidden_point_visitor'. Tr_Base::swap(tr); } @@ -224,11 +223,9 @@ public: } Regular_triangulation_3& operator=(Regular_triangulation_3&& tr) - noexcept(noexcept(Regular_triangulation_3(std::move(tr))) && - noexcept(std::declval().swap(*this))) + noexcept(noexcept(Regular_triangulation_3(std::move(tr)))) { - Regular_triangulation_3 copy(std::move(tr)); - copy.swap(*this); + Tr_Base::operator=(std::move(tr)); return *this; } From fea1bb946f4402000f73a145843106433dc41661 Mon Sep 17 00:00:00 2001 From: Jane Tournois Date: Tue, 4 Feb 2020 10:39:57 +0100 Subject: [PATCH 088/568] collapse does not break surfaces anymore --- .../internal/collapse_short_edges.h | 103 +++++++++++------- 1 file changed, 66 insertions(+), 37 deletions(-) diff --git a/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/collapse_short_edges.h b/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/collapse_short_edges.h index d5a4c2e7465..842b5846240 100644 --- a/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/collapse_short_edges.h +++ b/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/collapse_short_edges.h @@ -479,7 +479,6 @@ namespace internal const typename C3t3::Triangulation::Point& new_pos, const C3t3& c3t3, const bool /*protect_boundaries*/, - const typename C3t3::Subdomain_index& /*imaginary_index*/, CellSelector cell_selector) { typedef typename C3t3::Vertex_handle Vertex_handle; @@ -565,7 +564,6 @@ namespace internal const typename C3t3::Triangulation::Point& new_pos, SqLengthMap& edges_sqlength, const typename C3t3::Triangulation::Geom_traits::FT& sqhigh, - const typename C3t3::Subdomain_index& imaginary_index, const bool /* adaptive */ = false) { //SqLengthMap::key_type is Vertex_handle @@ -582,9 +580,6 @@ namespace internal { const Edge& ei = inc_edges[i]; - if (is_imaginary(ei, c3t3, imaginary_index)) //should we also test outside cells? - continue; - Vertex_handle ivh = ei.first->vertex(ei.second); if (ivh == v1) ivh = ei.first->vertex(ei.third); @@ -622,7 +617,6 @@ namespace internal const typename C3t3::Triangulation::Point& new_pos, SqLengthMap& edges_sqlength, const typename C3t3::Triangulation::Geom_traits::FT& sqhigh, - const typename C3t3::Subdomain_index& imaginary_index, const bool adaptive = false) { //SqLengthMap::key_type is Vertex_handle @@ -637,26 +631,60 @@ namespace internal if (collapse_type == TO_V1 || collapse_type == TO_MIDPOINT) { if (!are_edge_lengths_valid(v0, v1, c3t3, new_pos, - edges_sqlength, sqhigh, imaginary_index, adaptive)) + edges_sqlength, sqhigh, adaptive)) return false; } else if (collapse_type == TO_V0 || collapse_type == TO_MIDPOINT) { if (!are_edge_lengths_valid(v1, v0, c3t3, new_pos, - edges_sqlength, sqhigh, imaginary_index, adaptive)) + edges_sqlength, sqhigh, adaptive)) return false; } return true; } + template + void merge_surface_patch_indices(typename C3t3::Facet& f1, + typename C3t3::Facet& f2, + C3t3& c3t3) + { + const bool in_cx_f1 = c3t3.is_in_complex(f1); + const bool in_cx_f2 = c3t3.is_in_complex(f2); + + if (in_cx_f1 && !in_cx_f2) + { + typename C3t3::Surface_patch_index patch = c3t3.surface_patch_index(f1); + c3t3.remove_from_complex(f1); + c3t3.add_to_complex(f1, patch); + c3t3.add_to_complex(f2, patch); + } + else if (in_cx_f2 && !in_cx_f1) + { + typename C3t3::Surface_patch_index patch = c3t3.surface_patch_index(f2); + c3t3.remove_from_complex(f2); + c3t3.add_to_complex(f1, patch); + c3t3.add_to_complex(f2, patch); + } + else + { + CGAL_assertion( + //f1 and f2 are not both in complex + !(in_cx_f1 && in_cx_f2) + // unless they are on the same surface + || c3t3.surface_patch_index(f1) == c3t3.surface_patch_index(f2)); + } + } + template typename C3t3::Vertex_handle - collapse(const typename C3t3::Cell_handle ch, const int to, const int from, + collapse(const typename C3t3::Cell_handle ch, + const int to, const int from, C3t3& c3t3) { + typedef typename C3t3::Triangulation Tr; typedef typename C3t3::Vertex_handle Vertex_handle; typedef typename C3t3::Cell_handle Cell_handle; - typedef typename C3t3::Triangulation Tr; + typedef typename C3t3::Facet Facet; typedef typename Tr::Cell_circulator Cell_circulator; Tr& tr = c3t3.triangulation(); @@ -682,14 +710,19 @@ namespace internal Cell_circulator done = circ; do { - int v0_id = circ->index(vh0); - int v1_id = circ->index(vh1); + const int v0_id = circ->index(vh0); + const int v1_id = circ->index(vh1); Cell_handle n0_ch = circ->neighbor(v0_id); Cell_handle n1_ch = circ->neighbor(v1_id); - int ch_id_in_n0 = n0_ch->index(circ); - int ch_id_in_n1 = n1_ch->index(circ); + const int ch_id_in_n0 = n0_ch->index(circ); + const int ch_id_in_n1 = n1_ch->index(circ); + + //Merge surface patch indices + merge_surface_patch_indices(Facet(n0_ch, ch_id_in_n0), + Facet(n1_ch, ch_id_in_n1), + c3t3); //Update neighbors before removing cell n0_ch->set_neighbor(ch_id_in_n0, n1_ch); @@ -725,12 +758,11 @@ namespace internal } while (++circ != done); - Vertex_handle infinite_vertex = tr.infinite_vertex(); + const Vertex_handle infinite_vertex = tr.infinite_vertex(); bool v0_updated = false; - for (std::size_t i = 0; i < find_incident.size(); ++i) + for (const Cell_handle ch : find_incident) { - const Cell_handle ch = find_incident[i]; if (invalid_cells.find(ch) == invalid_cells.end())//valid cell { if (tr.is_infinite(ch)) @@ -743,10 +775,8 @@ namespace internal } //Update the vertex before removing it - for (std::size_t i = 0; i < cells_to_update.size(); ++i) + for (const Cell_handle ch : cells_to_update) { - Cell_handle ch = cells_to_update[i]; - if (invalid_cells.find(ch) == invalid_cells.end()) //valid cell { ch->set_vertex(ch->index(vh1), vh0); @@ -764,14 +794,16 @@ namespace internal if (!v0_updated) std::cout << "PB i cell not valid!!!" << std::endl; + + // Delete vertex c3t3.triangulation().tds().delete_vertex(vh1); - //Removing cells - for (std::size_t i = 0; i < cells_to_remove.size(); i++) + // Delete cells + for (Cell_handle cell_to_remove : cells_to_remove) { - if (cells_to_remove[i]->subdomain_index() > 0) - c3t3.remove_from_complex(cells_to_remove[i]); - c3t3.triangulation().tds().delete_cell(cells_to_remove[i]); + if (cell_to_remove->subdomain_index() > 0) + c3t3.remove_from_complex(cell_to_remove); + c3t3.triangulation().tds().delete_cell(cell_to_remove); } if (!valid){ @@ -810,7 +842,7 @@ namespace internal vh1->set_point(new_position); vh = collapse(edge.first, edge.second, edge.third, c3t3); - c3t3.set_dimension(vh, std::min(dim_vh0, dim_vh1)); + c3t3.set_dimension(vh, (std::min)(dim_vh0, dim_vh1)); } else //Collapse at vertex { @@ -818,7 +850,7 @@ namespace internal { vh0->set_point(p1); vh = collapse(edge.first, edge.third, edge.second, c3t3); - c3t3.set_dimension(vh, std::min(dim_vh0, dim_vh1)); + c3t3.set_dimension(vh, (std::min)(dim_vh0, dim_vh1)); } else //Collapse at v0 { @@ -826,7 +858,7 @@ namespace internal { vh1->set_point(p0); vh = collapse(edge.first, edge.second, edge.third, c3t3); - c3t3.set_dimension(vh, std::min(dim_vh0, dim_vh1)); + c3t3.set_dimension(vh, (std::min)(dim_vh0, dim_vh1)); } else CGAL_assertion(false); @@ -840,7 +872,6 @@ namespace internal C3t3& c3t3, const typename C3t3::Triangulation::Geom_traits::FT& sqhigh, const bool protect_boundaries, - const typename C3t3::Subdomain_index& imaginary_index, CellSelector cell_selector, Visitor& visitor) { @@ -870,11 +901,11 @@ namespace internal boost::unordered_map edges_sqlength_after_collapse; if (is_valid_collapse(edge, collapse_type, new_pos, c3t3, - protect_boundaries, imaginary_index, cell_selector)) + protect_boundaries, cell_selector)) { if (are_edge_lengths_valid(edge, c3t3, collapse_type, new_pos, - edges_sqlength_after_collapse, sqhigh, - imaginary_index /*, adaptive = false*/)) + edges_sqlength_after_collapse, sqhigh + /*, adaptive = false*/)) { CollapseTriangulation local_tri(c3t3, edge, collapse_type, visitor); local_tri.update(); @@ -893,7 +924,6 @@ namespace internal bool can_be_collapsed(const typename C3T3::Edge& e, const C3T3& c3t3, const bool protect_boundaries, - const typename C3T3::Subdomain_index& imaginary_index, CellSelector cell_selector) { if (is_outside(e, c3t3, cell_selector)) @@ -930,7 +960,6 @@ namespace internal const typename C3T3::Triangulation::Geom_traits::FT& low, const typename C3T3::Triangulation::Geom_traits::FT& high, const bool protect_boundaries, - const typename C3T3::Subdomain_index& imaginary_index, CellSelector cell_selector, Visitor& visitor) { @@ -963,7 +992,7 @@ namespace internal eit != tr.finite_edges_end(); ++eit) { const Edge& e = *eit; - if (!can_be_collapsed(e, c3t3, protect_boundaries, imaginary_index, cell_selector)) + if (!can_be_collapsed(e, c3t3, protect_boundaries, cell_selector)) continue; typename Gt::Compute_squared_length_3 sql @@ -998,14 +1027,14 @@ namespace internal { Edge edge(cell, i1, i2); - if (!can_be_collapsed(edge, c3t3, protect_boundaries, imaginary_index, cell_selector)) + if (!can_be_collapsed(edge, c3t3, protect_boundaries, cell_selector)) continue; #ifdef CGAL_TETRAHEDRAL_REMESHING_VERBOSE Vertex_handle vh = #endif collapse_edge(edge, c3t3, sq_high, - protect_boundaries, imaginary_index, cell_selector, + protect_boundaries, cell_selector, visitor); #ifdef CGAL_TETRAHEDRAL_REMESHING_VERBOSE From b66b83f52cee635b7646465af77404ec93a96937 Mon Sep 17 00:00:00 2001 From: Jane Tournois Date: Tue, 4 Feb 2020 12:19:18 +0100 Subject: [PATCH 089/568] fix is_outside(edge) and in the meantime surfaces protection --- .../internal/tetrahedral_remeshing_helpers.h | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/tetrahedral_remeshing_helpers.h b/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/tetrahedral_remeshing_helpers.h index caebebdd128..a3657fbf435 100644 --- a/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/tetrahedral_remeshing_helpers.h +++ b/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/tetrahedral_remeshing_helpers.h @@ -757,19 +757,17 @@ namespace Tetrahedral_remeshing Cell_circulator done = circ; do { - // is cell infinite? - if (!c3t3.triangulation().is_infinite(circ)) - return false; // is cell in complex? if (c3t3.is_in_complex(circ)) return false; - // circ does not belong to the selection + // does circ belong to the selection? if (cell_selector(circ)) return false; + ++circ; } while (circ != done); - return false; //all incident cells are outside or infinite + return true; //all incident cells are outside or infinite } template From a9e254efb411ed8e288e2f6518872a4164305f77 Mon Sep 17 00:00:00 2001 From: Jane Tournois Date: Tue, 4 Feb 2020 15:29:49 +0100 Subject: [PATCH 090/568] flip does not break surfaces anymore --- .../internal/flip_edges.h | 46 ++++++++++++++----- .../tetrahedral_adaptive_remeshing_impl.h | 14 ++---- 2 files changed, 37 insertions(+), 23 deletions(-) diff --git a/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/flip_edges.h b/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/flip_edges.h index 2bfc8df12e1..eb05bd0aa6c 100644 --- a/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/flip_edges.h +++ b/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/flip_edges.h @@ -977,14 +977,16 @@ namespace internal const Flip_Criterion& criterion, Visitor& visitor) { - typedef typename C3t3::Triangulation Tr; - typedef typename C3t3::Vertex_handle Vertex_handle; - typedef typename Tr::Facet_circulator Facet_circulator; + typedef typename C3t3::Triangulation Tr; + typedef typename C3t3::Vertex_handle Vertex_handle; + typedef typename C3t3::Facet Facet; + typedef typename C3t3::Surface_patch_index Surface_patch_index; + typedef typename Tr::Facet_circulator Facet_circulator; Tr& tr = c3t3.triangulation(); - Vertex_handle v0 = edge.first->vertex(edge.second); - Vertex_handle v1 = edge.first->vertex(edge.third); + const Vertex_handle v0 = edge.first->vertex(edge.second); + const Vertex_handle v1 = edge.first->vertex(edge.third); Facet_circulator circ = tr.incident_facets(edge); Facet_circulator done = circ; @@ -996,6 +998,7 @@ namespace internal boost::unordered_set boundary_vertices; boost::unordered_set hull_vertices; + boost::unordered_set mirror_facets; do { //Get the ids of the opposite vertices @@ -1021,6 +1024,10 @@ namespace internal } } } + mirror_facets.insert( + tr.mirror_facet(Facet(circ->first, circ->first->index(v0)))); + mirror_facets.insert( + tr.mirror_facet(Facet(circ->first, circ->first->index(v1)))); } while (++circ != done); @@ -1029,13 +1036,15 @@ namespace internal if (boundary_vertices.size() > 2) return NOT_FLIPPABLE; + // perform flip when possible + Sliver_removal_result res = NOT_FLIPPABLE; if (vertices_around_edge.size() == 3) { if (!boundary_edge && !hull_edge) { std::vector vertices; vertices.insert(vertices.end(), vertices_around_edge.begin(), vertices_around_edge.end()); - return flip_3_to_2(edge, c3t3, vertices, criterion); + res = flip_3_to_2(edge, c3t3, vertices, criterion); } } else @@ -1047,11 +1056,25 @@ namespace internal { std::vector vertices; vertices.insert(vertices.end(), boundary_vertices.begin(), boundary_vertices.end()); - return flip_n_to_m(edge, c3t3, vertices, criterion, visitor); + res = flip_n_to_m(edge, c3t3, vertices, criterion, visitor); //return n_to_m_flip(edge, boundary_vertices, flip_criterion); } } - return NOT_FLIPPABLE; + + if (res == VALID_FLIP) + { + for (Facet f : mirror_facets) + { + if (c3t3.is_in_complex(f)) + { + Surface_patch_index patch = c3t3.surface_patch_index(f); + c3t3.remove_from_complex(f); + c3t3.add_to_complex(f, patch); + } + } + } + + return res; } @@ -1102,7 +1125,6 @@ namespace internal template void flip_edges(C3T3& c3t3, - const typename C3T3::Subdomain_index& imaginary_index, const bool protect_boundaries, CellSelector cell_selector, Visitor& visitor) @@ -1147,9 +1169,9 @@ namespace internal std::cout << "\tInside flips" << std::endl; #endif std::vector inside_edges; - get_inside_edges(c3t3, imaginary_index, - cell_selector, - std::back_inserter(inside_edges)); + get_inside_edges(c3t3, + cell_selector, + std::back_inserter(inside_edges)); //if (criterion == VALENCE_BASED) // flip_inside_edges(inside_edges); diff --git a/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/tetrahedral_adaptive_remeshing_impl.h b/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/tetrahedral_adaptive_remeshing_impl.h index c72c8395b3f..9fb1006c6db 100644 --- a/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/tetrahedral_adaptive_remeshing_impl.h +++ b/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/tetrahedral_adaptive_remeshing_impl.h @@ -214,8 +214,6 @@ namespace internal CGAL_assertion(tr().tds().is_valid(true)); #ifdef CGAL_DUMP_REMESHING_STEPS CGAL::Tetrahedral_remeshing::debug::dump_triangulation_cells(tr(), "1-split.mesh"); - CGAL::Tetrahedral_remeshing::debug::dump_without_imaginary(tr(), - "1-split-no-imaginary.mesh", m_imaginary_index); CGAL::Tetrahedral_remeshing::debug::dump_binary(m_c3t3, "1-split.binary.cgal"); #endif } @@ -228,30 +226,24 @@ namespace internal FT emin = FT(4)/FT(5) * target_edge_length; FT emax = FT(4)/FT(3) * target_edge_length; collapse_short_edges(m_c3t3, emin, emax, m_protect_boundaries, - m_imaginary_index, m_cell_selector, m_visitor); CGAL_assertion(tr().tds().is_valid(true)); #ifdef CGAL_DUMP_REMESHING_STEPS CGAL::Tetrahedral_remeshing::debug::dump_triangulation_cells(tr(), "2-collapse.mesh"); - CGAL::Tetrahedral_remeshing::debug::dump_without_imaginary(tr(), - "2-collapse-no-imaginary.mesh", m_imaginary_index); CGAL::Tetrahedral_remeshing::debug::dump_binary(m_c3t3, "2-collapse.binary.cgal"); #endif } void flip() { - flip_edges(m_c3t3, m_imaginary_index, m_protect_boundaries, + flip_edges(m_c3t3, m_protect_boundaries, m_cell_selector, m_visitor); CGAL_assertion(tr().tds().is_valid(true)); #ifdef CGAL_DUMP_REMESHING_STEPS - CGAL::Tetrahedral_remeshing::debug::dump_triangulation_cells(tr(), - "3-flip.mesh"); - CGAL::Tetrahedral_remeshing::debug::dump_without_imaginary(tr(), - "3-flip-no-imaginary.mesh", m_imaginary_index); + CGAL::Tetrahedral_remeshing::debug::dump_triangulation_cells(tr(), "3-flip.mesh"); CGAL::Tetrahedral_remeshing::debug::dump_binary(m_c3t3, "3-flip.binary.cgal"); #endif } @@ -519,7 +511,7 @@ private: split(); collapse(); } -// flip(); + flip(); // smooth(); #ifdef CGAL_TETRAHEDRAL_REMESHING_VERBOSE From 9d527321c4b5d2804d14665113e2dc9c8d4f5c03 Mon Sep 17 00:00:00 2001 From: Jane Tournois Date: Tue, 4 Feb 2020 15:30:04 +0100 Subject: [PATCH 091/568] cleaning --- .../internal/tetrahedral_remeshing_helpers.h | 9 ++------- 1 file changed, 2 insertions(+), 7 deletions(-) diff --git a/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/tetrahedral_remeshing_helpers.h b/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/tetrahedral_remeshing_helpers.h index a3657fbf435..1852a3e05e1 100644 --- a/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/tetrahedral_remeshing_helpers.h +++ b/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/tetrahedral_remeshing_helpers.h @@ -914,9 +914,8 @@ namespace Tetrahedral_remeshing template OutputIterator get_inside_edges(const C3t3& c3t3, - const typename C3t3::Subdomain_index& imaginary_index, - CellSelector cell_selector, - OutputIterator oit)/*holds pairs of Vertex_handles*/ + CellSelector cell_selector, + OutputIterator oit)/*holds Edges*/ { for (typename C3t3::Triangulation::Finite_edges_iterator eit = c3t3.triangulation().finite_edges_begin(); @@ -924,10 +923,6 @@ namespace Tetrahedral_remeshing ++eit) { const typename C3t3::Edge& e = *eit; -// if ( !c3t3.is_in_complex(e) -// && !is_boundary_edge(e, c3t3) -// && !is_on_hull(e, c3t3) -// && !is_imaginary(e, c3t3, imaginary_index)) if (is_inside(e, c3t3, cell_selector)) { *oit++ = make_vertex_pair(e); From dc496f5db6340ad6e8d9f12ccf0c8f2aa5501153 Mon Sep 17 00:00:00 2001 From: Jane Tournois Date: Tue, 4 Feb 2020 16:32:32 +0100 Subject: [PATCH 092/568] add "peeling" of ultra-thin surface slivers --- .../tetrahedral_adaptive_remeshing_impl.h | 34 +++++++++++++------ 1 file changed, 23 insertions(+), 11 deletions(-) diff --git a/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/tetrahedral_adaptive_remeshing_impl.h b/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/tetrahedral_adaptive_remeshing_impl.h index 9fb1006c6db..652b75b9138 100644 --- a/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/tetrahedral_adaptive_remeshing_impl.h +++ b/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/tetrahedral_adaptive_remeshing_impl.h @@ -298,34 +298,46 @@ namespace internal return true; } - void postprocess() + //peel off slivers + std::size_t postprocess(const double sliver_angle = 0.1) { + if (m_protect_boundaries) + return 0; + #ifdef CGAL_TETRAHEDRAL_REMESHING_VERBOSE std::cout << "Postprocess..."; std::cout.flush(); #endif - //unset imaginary cells + + std::size_t nb_slivers_peel = 0; typedef typename Tr::Finite_cells_iterator Finite_cells_iterator; for (Finite_cells_iterator cit = tr().finite_cells_begin(); cit != tr().finite_cells_end(); ++cit) { - if (cit->subdomain_index() == m_imaginary_index) + if(m_c3t3.is_in_complex(cit) && min_dihedral_angle(tr(), cit) < sliver_angle) { - m_c3t3.remove_from_complex(cit); + for (int i = 0; i < 4; ++i) + { + if (!m_c3t3.is_in_complex(cit->neighbor(i))) + { + m_c3t3.remove_from_complex(cit); + ++nb_slivers_peel; + } + } } } CGAL_assertion(tr().tds().is_valid(true)); + #ifdef CGAL_DUMP_REMESHING_STEPS - CGAL::Tetrahedral_remeshing::debug::dump_triangulation_cells(tr(), - "99-postprocess.mesh"); - CGAL::Tetrahedral_remeshing::debug::dump_without_imaginary(tr(), - "99-postprocess-no-imaginary.mesh", m_imaginary_index); + CGAL::Tetrahedral_remeshing::debug::dump_triangulation_cells(tr(), "99-postprocess.mesh"); CGAL::Tetrahedral_remeshing::debug::dump_binary(m_c3t3, "99-postprocess.binary.cgal"); #endif #ifdef CGAL_TETRAHEDRAL_REMESHING_VERBOSE + std::cout << "(peeling removed " << nb_slivers_peel << " slivers)" << std::endl; std::cout << "done." << std::endl; #endif + return nb_slivers_peel; } void finalize() @@ -529,7 +541,7 @@ private: while (it_nb++ < max_it + nb_extra_iterations) { - // flip(); + flip(); // smooth(); #ifdef CGAL_TETRAHEDRAL_REMESHING_VERBOSE @@ -545,10 +557,10 @@ private: #endif } -// postprocess(); //remove imaginary cells + postprocess(); //peel off boundary slivers finalize(); - //triangulation() is now empty + //Warning : triangulation() is now empty } };//end class Adaptive_remesher From 575f8111c35786ded70e89457c81d6333b1b1f5b Mon Sep 17 00:00:00 2001 From: Jane Tournois Date: Tue, 4 Feb 2020 16:51:54 +0100 Subject: [PATCH 093/568] remove imaginary stuff, and use CGAL internal named parameters --- .../internal/compute_c3t3_statistics.h | 3 +- .../internal/flip_edges.h | 3 -- .../tetrahedral_adaptive_remeshing_impl.h | 48 ++----------------- .../internal/tetrahedral_remeshing_helpers.h | 42 ---------------- .../include/CGAL/tetrahedral_remeshing.h | 21 ++++---- 5 files changed, 15 insertions(+), 102 deletions(-) diff --git a/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/compute_c3t3_statistics.h b/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/compute_c3t3_statistics.h index f7ff862e2bf..24ea5574b04 100644 --- a/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/compute_c3t3_statistics.h +++ b/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/compute_c3t3_statistics.h @@ -38,7 +38,6 @@ namespace internal { template void compute_statistics(const Triangulation& tr, - const typename Triangulation::Cell::Subdomain_index& imaginary_index, CellSelector cell_selector, const char* filename = "statistics_c3t3.txt") { @@ -103,7 +102,7 @@ namespace internal ++cit) { const Subdomain_index& si = cit->subdomain_index(); - if (si == Subdomain_index() || si == imaginary_index || !cell_selector(cit)) + if (si == Subdomain_index() || !cell_selector(cit)) continue; ++nb_tets; diff --git a/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/flip_edges.h b/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/flip_edges.h index eb05bd0aa6c..17616f849be 100644 --- a/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/flip_edges.h +++ b/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/flip_edges.h @@ -1165,9 +1165,6 @@ namespace internal // flipBoundaryEdges(boundary_edges, boundary_vertices_valences, MIN_ANGLE_BASED); //} -#ifdef CGAL_TETRAHEDRAL_REMESHING_VERBOSE - std::cout << "\tInside flips" << std::endl; -#endif std::vector inside_edges; get_inside_edges(c3t3, cell_selector, diff --git a/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/tetrahedral_adaptive_remeshing_impl.h b/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/tetrahedral_adaptive_remeshing_impl.h index 652b75b9138..e70c1246a73 100644 --- a/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/tetrahedral_adaptive_remeshing_impl.h +++ b/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/tetrahedral_adaptive_remeshing_impl.h @@ -29,7 +29,6 @@ #include #include -#include #include #include #include @@ -115,7 +114,6 @@ namespace internal const SizingFunction& m_sizing; const bool m_protect_boundaries; CellSelector m_cell_selector; - Subdomain_index m_imaginary_index; Visitor& m_visitor; Triangulation* m_tr_pbackup; //backup to re-swap triangulations when done @@ -143,8 +141,6 @@ namespace internal init_c3t3(ecmap, fcmap); #ifdef CGAL_DUMP_REMESHING_STEPS - CGAL::Tetrahedral_remeshing::debug::dump_without_imaginary(m_c3t3.triangulation(), - "00-init-no-imaginary.mesh", m_imaginary_index); CGAL::Tetrahedral_remeshing::debug::dump_binary(m_c3t3, "00-init.binary.cgal"); #endif } @@ -170,38 +166,10 @@ namespace internal init_c3t3(ecmap, fcmap); #ifdef CGAL_DUMP_REMESHING_STEPS - //CGAL::Tetrahedral_remeshing::debug::dump_without_imaginary(m_c3t3.triangulation(), - // "00-init-no-imaginary.mesh", m_imaginary_index); CGAL::Tetrahedral_remeshing::debug::dump_binary(m_c3t3, "00-init.binary.cgal"); #endif } - const Subdomain_index& imaginary_index() const - { - return m_imaginary_index; - } - -// void preprocess() -// { -//#ifdef CGAL_TETRAHEDRAL_REMESHING_VERBOSE -// std::cout << "Preprocess..."; -// std::cout.flush(); -//#endif -// -// add_layer_of_imaginary_tets(tr(), m_imaginary_index); -// CGAL_assertion(tr().tds().is_valid(true)); -// -//#ifdef CGAL_DUMP_REMESHING_STEPS -// CGAL::Tetrahedral_remeshing::debug::dump_triangulation_cells(tr(), "0-preprocess.mesh"); -// CGAL::Tetrahedral_remeshing::debug::dump_without_imaginary(tr(), -// "0-preprocess-no-imaginary.mesh", m_imaginary_index); -// CGAL::Tetrahedral_remeshing::debug::dump_binary(m_c3t3, "0-preprocess.binary.cgal"); -//#endif -//#ifdef CGAL_TETRAHEDRAL_REMESHING_VERBOSE -// std::cout << "done." << std::endl; -//#endif -// } - void split() { CGAL_assertion(check_vertex_dimensions()); @@ -250,15 +218,13 @@ namespace internal void smooth() { - smooth_vertices_new(m_c3t3, m_imaginary_index, m_protect_boundaries, + smooth_vertices_new(m_c3t3, -1, m_protect_boundaries, m_cell_selector); CGAL_assertion(tr().tds().is_valid(true)); #ifdef CGAL_DUMP_REMESHING_STEPS CGAL::Tetrahedral_remeshing::debug::dump_triangulation_cells(tr(), "4-smooth.mesh"); - CGAL::Tetrahedral_remeshing::debug::dump_without_imaginary(tr(), - "4-smooth-no-imaginary.mesh", m_imaginary_index); CGAL::Tetrahedral_remeshing::debug::dump_binary(m_c3t3, "4-smooth.binary.cgal"); #endif } @@ -286,9 +252,6 @@ namespace internal || is_boundary(m_c3t3, e, m_cell_selector)) continue; } - // skip imaginary edges - if (is_imaginary(e, m_c3t3, m_imaginary_index)) - continue; FT sqlen = tr().segment(e).squared_length(); if (sqlen < sqmin || sqlen > sqmax) @@ -361,7 +324,7 @@ private: Subdomain_index max_si = 0; - //tag cells (no imaginary cell yet) + //tag cells typedef typename Tr::Finite_cells_iterator Finite_cells_iterator; for (Finite_cells_iterator cit = tr().finite_cells_begin(); cit != tr().finite_cells_end(); @@ -381,7 +344,6 @@ private: cit->vertex(i)->set_dimension(3); } } - m_imaginary_index = max_si + 1; if(max_si == 0) std::cerr << "Warning : Maximal subdomain index is 0" << std::endl << " Remeshing is likely to fail." << std::endl; @@ -510,8 +472,6 @@ private: void remesh(const std::size_t& max_it, const std::size_t& nb_extra_iterations) { -// preprocess(); - std::size_t it_nb = 0; while (it_nb++ < max_it) { @@ -535,7 +495,7 @@ private: std::ostringstream ossi; ossi << "statistics_" << it_nb << ".txt"; Tetrahedral_remeshing::internal::compute_statistics( - tr(), imaginary_index(), m_cell_selector, ossi.str().c_str()); + tr(), m_cell_selector, ossi.str().c_str()); #endif } @@ -553,7 +513,7 @@ private: std::ostringstream ossi; ossi << "statistics_" << it_nb << ".txt"; Tetrahedral_remeshing::internal::compute_statistics( - tr(), imaginary_index(), m_cell_selector, ossi.str().c_str()); + tr(), m_cell_selector, ossi.str().c_str()); #endif } diff --git a/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/tetrahedral_remeshing_helpers.h b/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/tetrahedral_remeshing_helpers.h index 1852a3e05e1..956b89fe565 100644 --- a/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/tetrahedral_remeshing_helpers.h +++ b/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/tetrahedral_remeshing_helpers.h @@ -726,27 +726,6 @@ namespace Tetrahedral_remeshing return false; } - template - bool is_imaginary(const typename C3t3::Vertex_handle v, - const C3t3& c3t3, - const typename C3t3::Subdomain_index& imaginary_index) - { - return false; - } - - /** - * returns true off edge is fully imaginary - * i.e. if all its incident cells are not in the complex, - * and have their subdomain index == imaginary_index - */ - template - bool is_imaginary(const typename C3t3::Edge & edge, - const C3t3& c3t3, - const typename C3t3::Subdomain_index& imaginary_index) - { - return false; - } - template bool is_outside(const typename C3t3::Edge & edge, const C3t3& c3t3, @@ -1261,7 +1240,6 @@ namespace Tetrahedral_remeshing template void dump_cells_with_small_dihedral_angle(const Tr& tr, const double angle_bound, - const int imaginary_index, CellSelector cell_select, const char* filename) { @@ -1341,26 +1319,6 @@ namespace Tetrahedral_remeshing dump_cells(cells, indices, filename); } - template - void dump_without_imaginary(const Tr& tr, const char* filename, - const int imaginary_index) - { - std::vector cells; - std::vector indices; - - for (typename Tr::Finite_cells_iterator cit = tr.finite_cells_begin(); - cit != tr.finite_cells_end(); ++cit) - { - if (cit->subdomain_index() > 0 - && cit->subdomain_index() != imaginary_index) - { - cells.push_back(cit); - indices.push_back(cit->subdomain_index()); - } - } - dump_cells(cells, indices, filename); - } - template void dump_binary(const C3t3& c3t3, const char* filename) { diff --git a/Tetrahedral_remeshing/include/CGAL/tetrahedral_remeshing.h b/Tetrahedral_remeshing/include/CGAL/tetrahedral_remeshing.h index e1d89e09cc5..e3942a0a011 100644 --- a/Tetrahedral_remeshing/include/CGAL/tetrahedral_remeshing.h +++ b/Tetrahedral_remeshing/include/CGAL/tetrahedral_remeshing.h @@ -166,7 +166,7 @@ namespace CGAL std::size_t max_it = choose_parameter(get_parameter(np, internal_np::number_of_iterations), 1); - typedef typename boost::lookup_named_param_def < + typedef typename internal_np::Lookup_named_param_def < internal_np::cell_selector_t, NamedParameters, Tetrahedral_remeshing::internal::All_cells_selected//default @@ -177,7 +177,7 @@ namespace CGAL typedef std::pair Edge_vv; typedef Tetrahedral_remeshing::internal::No_constraint_pmap No_edge; - typedef typename boost::lookup_named_param_def < + typedef typename internal_np::Lookup_named_param_def < internal_np::edge_is_constrained_t, NamedParameters, No_edge//default @@ -187,7 +187,7 @@ namespace CGAL typedef typename Tr::Facet Facet; typedef Tetrahedral_remeshing::internal::No_constraint_pmap No_facet; - typedef typename boost::lookup_named_param_def < + typedef typename internal_np::Lookup_named_param_def < internal_np::facet_is_constrained_t, NamedParameters, No_facet//default @@ -195,7 +195,7 @@ namespace CGAL FCMap fcmap = choose_parameter(get_parameter(np, internal_np::facet_is_constrained), No_facet()); - typedef typename boost::lookup_named_param_def < + typedef typename internal_np::Lookup_named_param_def < internal_np::remeshing_visitor_t, NamedParameters, Tetrahedral_remeshing::internal::Default_remeshing_visitor @@ -224,8 +224,7 @@ namespace CGAL #ifdef CGAL_TETRAHEDRAL_REMESHING_VERBOSE std::cout << "done." << std::endl; Tetrahedral_remeshing::internal::compute_statistics( - remesher.tr(), - remesher.imaginary_index(), cell_select, "statistics_begin.txt"); + remesher.tr(), cell_select, "statistics_begin.txt"); #endif // perform remeshing @@ -235,11 +234,11 @@ namespace CGAL #ifdef CGAL_TETRAHEDRAL_REMESHING_DEBUG const double angle_bound = 5.0; Tetrahedral_remeshing::debug::dump_cells_with_small_dihedral_angle(tr, - angle_bound, remesher.imaginary_index(), cell_select, "bad_cells.mesh"); + angle_bound, cell_select, "bad_cells.mesh"); #endif #ifdef CGAL_TETRAHEDRAL_REMESHING_VERBOSE Tetrahedral_remeshing::internal::compute_statistics(tr, - remesher.imaginary_index(), cell_select, "statistics_end.txt"); + cell_select, "statistics_end.txt"); #endif } @@ -378,7 +377,7 @@ namespace CGAL std::cout << "done." << std::endl; Tetrahedral_remeshing::internal::compute_statistics( remesher.tr(), - remesher.imaginary_index(), cell_select, "statistics_begin.txt"); + cell_select, "statistics_begin.txt"); #endif // perform remeshing @@ -389,12 +388,12 @@ namespace CGAL const double angle_bound = 5.0; Tetrahedral_remeshing::debug::dump_cells_with_small_dihedral_angle( c3t3.triangulation(), - angle_bound, remesher.imaginary_index(), cell_select, "bad_cells.mesh"); + angle_bound, cell_select, "bad_cells.mesh"); #endif #ifdef CGAL_TETRAHEDRAL_REMESHING_VERBOSE Tetrahedral_remeshing::internal::compute_statistics( c3t3.triangulation(), - remesher.imaginary_index(), cell_select, "statistics_end.txt"); + cell_select, "statistics_end.txt"); #endif } From 74243bae584ae8991431fe9b0bebb7dd1ad3163d Mon Sep 17 00:00:00 2001 From: Jane Tournois Date: Thu, 6 Feb 2020 11:19:27 +0100 Subject: [PATCH 094/568] fix is_inside(edge) by taking care also of facets that are in complex though incident to the same subdomain on both sides --- .../Tetrahedral_remeshing/Tetrahedral_remeshing_plugin.cpp | 2 +- .../internal/tetrahedral_remeshing_helpers.h | 7 +++++++ 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/Polyhedron/demo/Polyhedron/Plugins/Tetrahedral_remeshing/Tetrahedral_remeshing_plugin.cpp b/Polyhedron/demo/Polyhedron/Plugins/Tetrahedral_remeshing/Tetrahedral_remeshing_plugin.cpp index e2aaa8d3738..abb1b2a9e7c 100644 --- a/Polyhedron/demo/Polyhedron/Plugins/Tetrahedral_remeshing/Tetrahedral_remeshing_plugin.cpp +++ b/Polyhedron/demo/Polyhedron/Plugins/Tetrahedral_remeshing/Tetrahedral_remeshing_plugin.cpp @@ -1,6 +1,6 @@ #define CGAL_TETRAHEDRAL_REMESHING_VERBOSE #define CGAL_DUMP_REMESHING_STEPS -#define CGAL_TETRAHEDRAL_REMESHING_DEBUG +//#define CGAL_TETRAHEDRAL_REMESHING_DEBUG #include diff --git a/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/tetrahedral_remeshing_helpers.h b/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/tetrahedral_remeshing_helpers.h index 956b89fe565..10c127aa9bf 100644 --- a/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/tetrahedral_remeshing_helpers.h +++ b/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/tetrahedral_remeshing_helpers.h @@ -772,6 +772,9 @@ namespace Tetrahedral_remeshing const C3t3& c3t3, CellSelector cell_selector) { + const typename C3t3::Vertex_handle vs = edge.first->vertex(edge.second); + const typename C3t3::Vertex_handle vt = edge.first->vertex(edge.third); + typedef typename C3t3::Triangulation::Cell_circulator Cell_circulator; Cell_circulator circ = c3t3.triangulation().incident_cells(edge); Cell_circulator done = circ; @@ -785,6 +788,10 @@ namespace Tetrahedral_remeshing return false; if (!cell_selector(circ)) return false; + if (c3t3.is_in_complex( + circ, + CGAL::Triangulation_utils_3::next_around_edge(circ->index(vs), circ->index(vt)))) + return false; } while (++circ != done); return true; From 9eb178247ddaaf4bbb10207aba70c7a95ad31141 Mon Sep 17 00:00:00 2001 From: Jane Tournois Date: Thu, 6 Feb 2020 11:20:41 +0100 Subject: [PATCH 095/568] remove is_convex(tr) that has become useless --- .../internal/tetrahedral_remeshing_helpers.h | 79 ------------------- 1 file changed, 79 deletions(-) diff --git a/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/tetrahedral_remeshing_helpers.h b/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/tetrahedral_remeshing_helpers.h index 10c127aa9bf..aacce434561 100644 --- a/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/tetrahedral_remeshing_helpers.h +++ b/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/tetrahedral_remeshing_helpers.h @@ -797,85 +797,6 @@ namespace Tetrahedral_remeshing return true; } - template - bool is_convex(const Tr& tr, - const CGAL::Iso_cuboid_3& bbox, - typename Tr::Facet& facet) - { - typedef typename Tr::Cell_handle Cell_handle; - typedef typename Tr::Vertex_handle Vertex_handle; - typedef typename Tr::Facet Facet; - typedef typename Tr::Finite_facets_iterator Finite_facets_iterator; - - for (Finite_facets_iterator fit = tr.finite_facets_begin(); - fit != tr.finite_facets_end(); ++fit) - { - Facet f = *fit; - Facet mf = tr.mirror_facet(f); - if (!tr.is_infinite(f.first) && !tr.is_infinite(mf.first)) - continue; - - if (tr.is_infinite(mf.first)) - f = mf; - CGAL_assertion(tr.is_infinite(f.first)); - - boost::array vs; - for (int i = 0; i < 3; ++i) - vs[i] = f.first->vertex((f.second + i + 1) % 4); - if (f.second % 2 == 0) - std::swap(vs[0], vs[1]); - - Cell_handle fin_c = f.first->neighbor(f.second); - Vertex_handle v4 = fin_c->vertex(fin_c->index(f.first)); - - CGAL_assertion(!tr.is_infinite(fin_c)); - CGAL_assertion(!f.first->has_vertex(v4)); - - CGAL_assertion(CGAL::NEGATIVE - == CGAL::orientation(vs[0]->point(), vs[1]->point(), - vs[2]->point(), v4->point())); - - for (int i = 1; i < 4; ++i) - { - nfi is neighbor of f on convex hull - Cell_handle ni = f.first->neighbor((f.second + i) % 4); - CGAL_assertion(tr.is_infinite(ni)); - - collect points - Vertex_handle v3 = ni->vertex(ni->index(f.first)); - CGAL_assertion(v3 != vs[0] && v3 != vs[1] && v3 != vs[2] - && v3 != tr.infinite_vertex()); - CGAL_assertion(!f.first->has_vertex(v3)); - - CGAL::Orientation o2 = CGAL::orientation(vs[0]->point(), - vs[1]->point(), vs[2]->point(), v3->point()); - if (o2 == CGAL::POSITIVE) - { - facet = f; - - if (!bbox.is_degenerate() - && bbox.has_on_boundary(vs[0]->point()) - && bbox.has_on_boundary(vs[1]->point()) - && bbox.has_on_boundary(vs[2]->point())) - { - facet = Facet(ni, ni->index(tr.infinite_vertex())); - } - - return false; - } - } - } - return true; - } - - template - bool is_convex(const Tr& tr) - { - typename Tr::Facet f; - typename Tr::Geom_traits::Iso_cuboid_3 bb(CGAL::ORIGIN, CGAL::ORIGIN); - return is_convex(tr, bb, f); - } - template typename Gt::Vector_3 normal(const Facet& f, const Gt& gt) { From 83df2cea52e7acfa4b67b5d9b8222e848d2d9965 Mon Sep 17 00:00:00 2001 From: Jane Tournois Date: Thu, 6 Feb 2020 11:27:07 +0100 Subject: [PATCH 096/568] rename is_inside(edge) to is_internal(edge) for more readability --- .../Tetrahedral_remeshing/internal/collapse_short_edges.h | 4 ++-- .../CGAL/Tetrahedral_remeshing/internal/flip_edges.h | 2 +- .../CGAL/Tetrahedral_remeshing/internal/split_long_edges.h | 4 ++-- .../internal/tetrahedral_remeshing_helpers.h | 6 +++--- 4 files changed, 8 insertions(+), 8 deletions(-) diff --git a/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/collapse_short_edges.h b/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/collapse_short_edges.h index 842b5846240..3abd2e90ece 100644 --- a/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/collapse_short_edges.h +++ b/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/collapse_short_edges.h @@ -937,7 +937,7 @@ namespace internal return false; #ifdef CGAL_TETRAHEDRAL_REMESHING_DEBUG - if (!is_inside(e, c3t3, cell_selector)) + if (!is_internal(e, c3t3, cell_selector)) { std::cerr << "e is not inside!?" << std::endl; typename C3T3::Vertex_handle v1 = e.first->vertex(e.second); @@ -946,7 +946,7 @@ namespace internal } #endif - CGAL_assertion(is_inside(e, c3t3, cell_selector)); + CGAL_assertion(is_internal(e, c3t3, cell_selector)); return true; } else diff --git a/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/flip_edges.h b/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/flip_edges.h index 17616f849be..0070fad5696 100644 --- a/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/flip_edges.h +++ b/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/flip_edges.h @@ -1166,7 +1166,7 @@ namespace internal //} std::vector inside_edges; - get_inside_edges(c3t3, + get_internal_edges(c3t3, cell_selector, std::back_inserter(inside_edges)); diff --git a/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/split_long_edges.h b/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/split_long_edges.h index aaea7f9a177..44a67a4ee09 100644 --- a/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/split_long_edges.h +++ b/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/split_long_edges.h @@ -175,7 +175,7 @@ namespace internal return false; #ifdef CGAL_TETRAHEDRAL_REMESHING_DEBUG - if (!is_inside(e, c3t3, cell_selector)) + if (!is_internal(e, c3t3, cell_selector)) { std::cerr << "e is not inside!?" << std::endl; typename C3T3::Vertex_handle v1 = e.first->vertex(e.second); @@ -184,7 +184,7 @@ namespace internal } #endif - CGAL_assertion(is_inside(e, c3t3, cell_selector)); + CGAL_assertion(is_internal(e, c3t3, cell_selector)); return true; } else diff --git a/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/tetrahedral_remeshing_helpers.h b/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/tetrahedral_remeshing_helpers.h index aacce434561..637bbb51bb6 100644 --- a/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/tetrahedral_remeshing_helpers.h +++ b/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/tetrahedral_remeshing_helpers.h @@ -768,7 +768,7 @@ namespace Tetrahedral_remeshing } template - bool is_inside(const typename C3t3::Edge& edge, + bool is_internal(const typename C3t3::Edge& edge, const C3t3& c3t3, CellSelector cell_selector) { @@ -820,7 +820,7 @@ namespace Tetrahedral_remeshing } template - OutputIterator get_inside_edges(const C3t3& c3t3, + OutputIterator get_internal_edges(const C3t3& c3t3, CellSelector cell_selector, OutputIterator oit)/*holds Edges*/ { @@ -830,7 +830,7 @@ namespace Tetrahedral_remeshing ++eit) { const typename C3t3::Edge& e = *eit; - if (is_inside(e, c3t3, cell_selector)) + if (is_internal(e, c3t3, cell_selector)) { *oit++ = make_vertex_pair(e); } From 62c390c354e4c9cf3ea1c3bbba72852308c4eb93 Mon Sep 17 00:00:00 2001 From: Jane Tournois Date: Thu, 6 Feb 2020 16:44:23 +0100 Subject: [PATCH 097/568] use c++11 for loops, add const when possible, and rename containers --- .../internal/flip_edges.h | 43 +++++++++---------- 1 file changed, 21 insertions(+), 22 deletions(-) diff --git a/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/flip_edges.h b/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/flip_edges.h index 0070fad5696..83e90cd3828 100644 --- a/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/flip_edges.h +++ b/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/flip_edges.h @@ -49,7 +49,7 @@ namespace internal template Sliver_removal_result flip_3_to_2(typename C3t3::Edge& edge, C3t3& c3t3, - std::vector& vertices_around_edge, + const std::vector& vertices_around_edge, const Flip_Criterion& criterion) { typedef typename C3t3::Triangulation Tr; @@ -87,13 +87,12 @@ namespace internal return NOT_FLIPPABLE; //Check topological validity - if ( ch0->subdomain_index() != ch1->subdomain_index() - || ch0->subdomain_index() != cell_to_remove->subdomain_index() + const typename C3t3::Subdomain_index subdomain = ch0->subdomain_index(); + if ( subdomain != ch1->subdomain_index() + || subdomain != cell_to_remove->subdomain_index() || ch1->subdomain_index() != cell_to_remove->subdomain_index()) return NOT_FLIPPABLE; - circ = Cell_circulator(done); - Vertex_handle vh2; Vertex_handle vh3; @@ -188,7 +187,8 @@ namespace internal typedef boost::unordered_map FaceMapIndex; FaceMapIndex facet_map_indices; - std::vector facets; + std::vector mirror_facets; + circ = Cell_circulator(done); do { int curr_vh0_id = circ->index(vh0); @@ -200,8 +200,8 @@ namespace internal typename FaceMapIndex::iterator it = facet_map_indices.find(face0); if (it == facet_map_indices.end()) { - facet_map_indices[face0] = facets.size(); - facets.push_back(n_vh0_facet); + facet_map_indices[face0] = mirror_facets.size(); + mirror_facets.push_back(n_vh0_facet); } int curr_vh1_id = circ->index(vh1); @@ -212,8 +212,8 @@ namespace internal it = facet_map_indices.find(face1); if (it == facet_map_indices.end()) { - facet_map_indices[face1] = facets.size(); - facets.push_back(n_vh1_facet); + facet_map_indices[face1] = mirror_facets.size(); + mirror_facets.push_back(n_vh1_facet); } } while (++circ != done); @@ -235,14 +235,15 @@ namespace internal ch0->set_vertex(vh0_id, vh2); ch1->set_vertex(vh1_id, vh3); + // "New" cells are not created, only modified/updated std::vector cells_to_update; cells_to_update.push_back(ch0); cells_to_update.push_back(ch1); //Update adjacencies and vertices' cells - for (std::size_t i = 0; i < cells_to_update.size(); ++i) + for (Cell_handle ch : cells_to_update) { - Cell_handle ch = cells_to_update[i]; + for (int v = 0; v < 4; ++v) { Facet_vvv face = make_vertex_triple(ch->vertex(indices(v, 0)), @@ -251,15 +252,16 @@ namespace internal typename FaceMapIndex::iterator it = facet_map_indices.find(face); if (it == facet_map_indices.end()) { - facet_map_indices[face] = facets.size(); - facets.push_back(Facet(ch, v)); + facet_map_indices[face] = mirror_facets.size(); + mirror_facets.push_back(Facet(ch, v)); } else { - Facet facet = facets[it->second]; + Facet mirror_facet = mirror_facets[it->second]; + //Update neighbor - facet.first->set_neighbor(facet.second, ch); - ch->set_neighbor(v, facet.first); + mirror_facet.first->set_neighbor(mirror_facet.second, ch); + ch->set_neighbor(v, mirror_facet.first); } ch->vertex(v)->set_cell(ch); } @@ -1092,14 +1094,11 @@ namespace internal Tr& tr = c3t3.triangulation(); std::size_t count = 0; - for (unsigned int i = 0; i < edges.size(); ++i) + for (const VertexPair vp : edges) { - const Vertex_handle vh0 = edges[i].first; - const Vertex_handle vh1 = edges[i].second; - Cell_handle ch; int i0, i1; - if (tr.is_edge(vh0, vh1, ch, i0, i1)) + if (tr.is_edge(vp.first, vp.second, ch, i0, i1)) { Edge edge(ch, i0, i1); From d345c2fe51e5bf2db64843f83a86f1829c2b726d Mon Sep 17 00:00:00 2001 From: Jane Tournois Date: Thu, 6 Feb 2020 17:41:03 +0100 Subject: [PATCH 098/568] flip_3_to_2 does not break surfaces anymore updating the outer hull of the set of modified cells is not enough, "internal" facets should also be updated --- .../internal/flip_edges.h | 68 +++++++++++++------ 1 file changed, 46 insertions(+), 22 deletions(-) diff --git a/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/flip_edges.h b/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/flip_edges.h index 83e90cd3828..048de9b1129 100644 --- a/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/flip_edges.h +++ b/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/flip_edges.h @@ -22,15 +22,17 @@ #ifndef CGAL_INTERNAL_FLIP_EDGES_H #define CGAL_INTERNAL_FLIP_EDGES_H -#include -#include -#include - #include #include #include +#include +#include + +#include +#include + namespace CGAL { namespace Tetrahedral_remeshing @@ -185,14 +187,19 @@ namespace internal //Keep the facets typedef CGAL::Triple Facet_vvv; typedef boost::unordered_map FaceMapIndex; + boost::unordered_set outer_mirror_facets; FaceMapIndex facet_map_indices; std::vector mirror_facets; circ = Cell_circulator(done); do { + // facet opposite to vh0 int curr_vh0_id = circ->index(vh0); Facet n_vh0_facet = tr.mirror_facet(Facet(circ, curr_vh0_id)); + + outer_mirror_facets.insert(n_vh0_facet); + Facet_vvv face0 = make_vertex_triple(circ->vertex(indices(curr_vh0_id, 0)), circ->vertex(indices(curr_vh0_id, 1)), circ->vertex(indices(curr_vh0_id, 2))); @@ -204,8 +211,12 @@ namespace internal mirror_facets.push_back(n_vh0_facet); } + // facet opposite to vh1 int curr_vh1_id = circ->index(vh1); Facet n_vh1_facet = tr.mirror_facet(Facet(circ, curr_vh1_id)); + + outer_mirror_facets.insert(n_vh1_facet); + Facet_vvv face1 = make_vertex_triple(circ->vertex(indices(curr_vh1_id, 0)), circ->vertex(indices(curr_vh1_id, 1)), circ->vertex(indices(curr_vh1_id, 2))); @@ -243,7 +254,6 @@ namespace internal //Update adjacencies and vertices' cells for (Cell_handle ch : cells_to_update) { - for (int v = 0; v < 4; ++v) { Facet_vvv face = make_vertex_triple(ch->vertex(indices(v, 0)), @@ -267,9 +277,40 @@ namespace internal } } + // Update c3t3 c3t3.remove_from_complex(cell_to_remove); tr.tds().delete_cell(cell_to_remove); + for (Cell_handle c : cells_to_update) + { + //their subdomain indices have not been modified because we kept the same cells + //surface patch indices need to be fixed though + for (int i = 0; i < 4; ++i) + { + const Facet f(c, i); + const Facet mf = tr.mirror_facet(f); + if (outer_mirror_facets.find(mf) == outer_mirror_facets.end()) + { + //we are inside the modified zone, c3t3 info is not valid anymore + if (c3t3.is_in_complex(f)) + c3t3.remove_from_complex(f); + if (c3t3.is_in_complex(mf)) + c3t3.remove_from_complex(mf); + } + else + { + //we are on the border of the modified zone, c3t3 info is valid outside, + //on mirror facet + const typename C3t3::Surface_patch_index patch = c3t3.surface_patch_index(mf); + if (c3t3.is_in_complex(mf)) + { + c3t3.remove_from_complex(mf); + c3t3.add_to_complex(mf, patch); + } + } + } + } + /********************VALIDITY CHECK***************************/ //if (check_validity) //{ @@ -1000,7 +1041,6 @@ namespace internal boost::unordered_set boundary_vertices; boost::unordered_set hull_vertices; - boost::unordered_set mirror_facets; do { //Get the ids of the opposite vertices @@ -1026,10 +1066,6 @@ namespace internal } } } - mirror_facets.insert( - tr.mirror_facet(Facet(circ->first, circ->first->index(v0)))); - mirror_facets.insert( - tr.mirror_facet(Facet(circ->first, circ->first->index(v1)))); } while (++circ != done); @@ -1063,18 +1099,6 @@ namespace internal } } - if (res == VALID_FLIP) - { - for (Facet f : mirror_facets) - { - if (c3t3.is_in_complex(f)) - { - Surface_patch_index patch = c3t3.surface_patch_index(f); - c3t3.remove_from_complex(f); - c3t3.add_to_complex(f, patch); - } - } - } return res; } From 707cdae9edf0f85bafbd6ec0fd53ccca71efb34a Mon Sep 17 00:00:00 2001 From: Jane Tournois Date: Fri, 7 Feb 2020 10:02:38 +0100 Subject: [PATCH 099/568] use c++11 for loops --- .../internal/flip_edges.h | 36 ++++++++----------- 1 file changed, 15 insertions(+), 21 deletions(-) diff --git a/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/flip_edges.h b/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/flip_edges.h index 048de9b1129..3a85f824dcb 100644 --- a/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/flip_edges.h +++ b/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/flip_edges.h @@ -751,9 +751,8 @@ namespace internal while (++cell_circulator != done); - for (std::size_t i = 0; i < cells_around_edge.size(); ++i) + for (Cell_handle ch : cells_around_edge) { - Cell_handle ch = cells_around_edge[i]; for (int v = 0; v < 4; v++) { Cell_handle neighbor = ch->neighbor(v); @@ -768,20 +767,16 @@ namespace internal } //Check that the result will be valid - for (std::size_t i = 0; i < facets_for_new_cells.size(); ++i) + for (const Facet& fi : facets_for_new_cells) { - const Facet& fi = facets_for_new_cells[i]; - if ( !tr.is_infinite(fi.first) && !is_well_oriented(tr, vh, fi.first->vertex(indices(fi.second, 0)), fi.first->vertex(indices(fi.second, 1)), fi.first->vertex(indices(fi.second, 2)))) return NOT_FLIPPABLE; } - for (std::size_t i = 0; i < facets_for_updated_cells.size(); ++i) + for (const Facet& fi : facets_for_updated_cells) { - const Facet& fi = facets_for_updated_cells[i]; - if ( !tr.is_infinite(fi.first) && !is_well_oriented(tr, vh, fi.first->vertex(indices(fi.second, 0)), fi.first->vertex(indices(fi.second, 1)), @@ -823,10 +818,8 @@ namespace internal std::vector cells_to_update; //Create new cells - for (std::size_t i = 0; i < facets_for_new_cells.size(); ++i) + for (const Facet& fi : facets_for_new_cells) { - const Facet& fi = facets_for_new_cells[i]; - Cell_handle new_cell = tr.tds().create_cell(); for (int v = 0; v < 4; v++){ @@ -841,9 +834,8 @@ namespace internal } //Update_existing cells - for (std::size_t i = 0; i < facets_for_updated_cells.size(); ++i) + for (const Facet& fi : facets_for_updated_cells) { - const Facet& fi = facets_for_updated_cells[i]; fi.first->set_vertex(fi.second, vh); cells_to_update.push_back(fi.first); } @@ -854,10 +846,10 @@ namespace internal FaceMapIndex facet_map_indices; std::vector facets; - for (std::size_t i = 0; i < neighbor_facets.size(); ++i) + for (const Facet& f : neighbor_facets) { - Cell_handle ch = neighbor_facets[i].first; - int v = neighbor_facets[i].second; + Cell_handle ch = f.first; + int v = f.second; Facet_vvv face = make_vertex_triple(ch->vertex(indices(v,0)), ch->vertex(indices(v,1)), @@ -871,9 +863,8 @@ namespace internal } //Update adjacencies and vertices cells - for (std::size_t i = 0; i < cells_to_update.size(); ++i) + for (Cell_handle ch : cells_to_update) { - Cell_handle ch = cells_to_update[i]; for (int v = 0; v < 4; v++) { Facet_vvv face = make_vertex_triple(ch->vertex(indices(v,0)), @@ -898,12 +889,15 @@ namespace internal } //Remove cells - for (std::size_t i = 0; i < to_remove.size(); ++i) + for (Cell_handle ch : to_remove) { - c3t3.remove_from_complex(to_remove[i]); - tr.tds().delete_cell(to_remove[i]); + c3t3.remove_from_complex(ch); + tr.tds().delete_cell(ch); } + //Update c3t3 + + ///********************VALIDITY CHECK***************************/ //if (check_validity){ From 9ae27914cf971e71aa5962cf56820a9dd5b80166 Mon Sep 17 00:00:00 2001 From: Jane Tournois Date: Fri, 7 Feb 2020 11:35:31 +0100 Subject: [PATCH 100/568] fix the c3t3 surfaces in flip_n_to_m --- .../internal/flip_edges.h | 53 ++++++++++++------- 1 file changed, 33 insertions(+), 20 deletions(-) diff --git a/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/flip_edges.h b/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/flip_edges.h index 3a85f824dcb..83ce655fbf7 100644 --- a/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/flip_edges.h +++ b/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/flip_edges.h @@ -710,7 +710,7 @@ namespace internal std::vector to_remove; //Neighbors that will need to be updated after flip - std::vector neighbor_facets; + boost::unordered_set neighbor_facets; //Facets that will be used to create new cells // i.e. all the facets opposite to vh1 and don't have vh @@ -729,11 +729,11 @@ namespace internal //Facets opposite to vh0 Facet facet_vh0(cell_circulator, cell_circulator->index(vh0)); - neighbor_facets.push_back(tr.mirror_facet(facet_vh0)); + neighbor_facets.insert(tr.mirror_facet(facet_vh0)); //Facets opposite to vh1 Facet facet_vh1(cell_circulator, cell_circulator->index(vh1)); - neighbor_facets.push_back(tr.mirror_facet(facet_vh1)); + neighbor_facets.insert(tr.mirror_facet(facet_vh1)); //Store it if it do not have vh if (cell_circulator->has_vertex(vh)){ @@ -750,22 +750,6 @@ namespace internal } while (++cell_circulator != done); - - for (Cell_handle ch : cells_around_edge) - { - for (int v = 0; v < 4; v++) - { - Cell_handle neighbor = ch->neighbor(v); - if (std::find(cells_around_edge.begin(), cells_around_edge.end(), neighbor) - == cells_around_edge.end()) - { - //Facets opposite - Facet facet_vh(ch, v); - neighbor_facets.push_back(tr.mirror_facet(facet_vh)); - } - } - } - //Check that the result will be valid for (const Facet& fi : facets_for_new_cells) { @@ -895,7 +879,36 @@ namespace internal tr.tds().delete_cell(ch); } - //Update c3t3 + // Update c3t3 + for (Cell_handle c : cells_to_update) + { + //their subdomain indices have not been modified because we kept the same cells + //surface patch indices need to be fixed though + for (int i = 0; i < 4; ++i) + { + const Facet f(c, i); + const Facet mf = tr.mirror_facet(f); + if (neighbor_facets.find(mf) == neighbor_facets.end()) + { + //we are inside the modified zone, c3t3 info is not valid anymore + if (c3t3.is_in_complex(f)) + c3t3.remove_from_complex(f); + if (c3t3.is_in_complex(mf)) + c3t3.remove_from_complex(mf); + } + else + { + //we are on the border of the modified zone, c3t3 info is valid outside, + //on mirror facet + const typename C3t3::Surface_patch_index patch = c3t3.surface_patch_index(mf); + if (c3t3.is_in_complex(mf)) + { + c3t3.remove_from_complex(mf); + c3t3.add_to_complex(mf, patch); + } + } + } + } ///********************VALIDITY CHECK***************************/ From 22e07a4a329300a2faf6eb78c3e32d7fd0fcc3a5 Mon Sep 17 00:00:00 2001 From: Jane Tournois Date: Fri, 7 Feb 2020 12:16:28 +0100 Subject: [PATCH 101/568] factor code --- .../internal/flip_edges.h | 103 ++++++++---------- 1 file changed, 45 insertions(+), 58 deletions(-) diff --git a/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/flip_edges.h b/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/flip_edges.h index 83ce655fbf7..5163c5f90ce 100644 --- a/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/flip_edges.h +++ b/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/flip_edges.h @@ -48,6 +48,49 @@ namespace internal // //TODO //} + //outer_mirror_facets contains the set of facets of the outer hull + //of the set of cells modified by the flip operation, + //"seen from" outside + //i.e. for each facet f among those, f.first has not been modified by flip + template + void update_c3t3_facets(C3t3& c3t3, + const CellSet& cells_to_update, + const FacetSet& outer_mirror_facets) + { + typedef typename C3t3::Facet Facet; + typedef typename C3t3::Cell_handle Cell_handle; + + for (Cell_handle c : cells_to_update) + { + //their subdomain indices have not been modified because we kept the same cells + //surface patch indices need to be fixed though + for (int i = 0; i < 4; ++i) + { + const Facet f(c, i); + const Facet mf = c3t3.triangulation().mirror_facet(f); + if (outer_mirror_facets.find(mf) == outer_mirror_facets.end()) + { + //we are inside the modified zone, c3t3 info is not valid anymore + if (c3t3.is_in_complex(f)) + c3t3.remove_from_complex(f); + if (c3t3.is_in_complex(mf)) + c3t3.remove_from_complex(mf); + } + else + { + //we are on the border of the modified zone, c3t3 info is valid outside, + //on mirror facet + const typename C3t3::Surface_patch_index patch = c3t3.surface_patch_index(mf); + if (c3t3.is_in_complex(mf)) + { + c3t3.remove_from_complex(mf); + c3t3.add_to_complex(mf, patch); + } + } + } + } + } + template Sliver_removal_result flip_3_to_2(typename C3t3::Edge& edge, C3t3& c3t3, @@ -281,35 +324,7 @@ namespace internal c3t3.remove_from_complex(cell_to_remove); tr.tds().delete_cell(cell_to_remove); - for (Cell_handle c : cells_to_update) - { - //their subdomain indices have not been modified because we kept the same cells - //surface patch indices need to be fixed though - for (int i = 0; i < 4; ++i) - { - const Facet f(c, i); - const Facet mf = tr.mirror_facet(f); - if (outer_mirror_facets.find(mf) == outer_mirror_facets.end()) - { - //we are inside the modified zone, c3t3 info is not valid anymore - if (c3t3.is_in_complex(f)) - c3t3.remove_from_complex(f); - if (c3t3.is_in_complex(mf)) - c3t3.remove_from_complex(mf); - } - else - { - //we are on the border of the modified zone, c3t3 info is valid outside, - //on mirror facet - const typename C3t3::Surface_patch_index patch = c3t3.surface_patch_index(mf); - if (c3t3.is_in_complex(mf)) - { - c3t3.remove_from_complex(mf); - c3t3.add_to_complex(mf, patch); - } - } - } - } + update_c3t3_facets(c3t3, cells_to_update, outer_mirror_facets); /********************VALIDITY CHECK***************************/ //if (check_validity) @@ -880,35 +895,7 @@ namespace internal } // Update c3t3 - for (Cell_handle c : cells_to_update) - { - //their subdomain indices have not been modified because we kept the same cells - //surface patch indices need to be fixed though - for (int i = 0; i < 4; ++i) - { - const Facet f(c, i); - const Facet mf = tr.mirror_facet(f); - if (neighbor_facets.find(mf) == neighbor_facets.end()) - { - //we are inside the modified zone, c3t3 info is not valid anymore - if (c3t3.is_in_complex(f)) - c3t3.remove_from_complex(f); - if (c3t3.is_in_complex(mf)) - c3t3.remove_from_complex(mf); - } - else - { - //we are on the border of the modified zone, c3t3 info is valid outside, - //on mirror facet - const typename C3t3::Surface_patch_index patch = c3t3.surface_patch_index(mf); - if (c3t3.is_in_complex(mf)) - { - c3t3.remove_from_complex(mf); - c3t3.add_to_complex(mf, patch); - } - } - } - } + update_c3t3_facets(c3t3, cells_to_update, neighbor_facets); ///********************VALIDITY CHECK***************************/ From 14b326bbe46a26f199df676092a68f604ad7d67f Mon Sep 17 00:00:00 2001 From: Jane Tournois Date: Fri, 7 Feb 2020 15:39:31 +0100 Subject: [PATCH 102/568] "far points" of Mesh_3 have dimension -1 deal with those, and keep their dimension "invalid" to be able to detect them --- .../tetrahedral_adaptive_remeshing_impl.h | 54 ++++++++++++------- .../internal/tetrahedral_remeshing_helpers.h | 16 +++--- 2 files changed, 44 insertions(+), 26 deletions(-) diff --git a/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/tetrahedral_adaptive_remeshing_impl.h b/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/tetrahedral_adaptive_remeshing_impl.h index e70c1246a73..c3b1191054b 100644 --- a/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/tetrahedral_adaptive_remeshing_impl.h +++ b/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/tetrahedral_adaptive_remeshing_impl.h @@ -170,6 +170,11 @@ namespace internal #endif } + bool input_is_c3t3() const + { + return m_c3t3_pbackup != NULL; + } + void split() { CGAL_assertion(check_vertex_dimensions()); @@ -338,10 +343,13 @@ private: ++nbc; #endif } - for (int i = 0; i < 4; ++i) + if (!input_is_c3t3()) { - if (cit->vertex(i)->in_dimension() == -1) - cit->vertex(i)->set_dimension(3); + for (int i = 0; i < 4; ++i) + { + if (cit->vertex(i)->in_dimension() == -1) + cit->vertex(i)->set_dimension(3); + } } } if(max_si == 0) @@ -366,12 +374,15 @@ private: { m_c3t3.add_to_complex(f, 1); - const int i = f.second; - for (int j = 0; j < 3; ++j) + if (!input_is_c3t3()) { - Vertex_handle vij = f.first->vertex(Tr::vertex_triple_index(i, j)); - if (vij->in_dimension() == -1 || vij->in_dimension() > 2) - vij->set_dimension(2); + const int i = f.second; + for (int j = 0; j < 3; ++j) + { + Vertex_handle vij = f.first->vertex(Tr::vertex_triple_index(i, j)); + if (vij->in_dimension() == -1 || vij->in_dimension() > 2) + vij->set_dimension(2); + } } #ifdef CGAL_TETRAHEDRAL_REMESHING_DEBUG ++nbf; @@ -395,13 +406,16 @@ private: { m_c3t3.add_to_complex(e, 1); - Vertex_handle v = e.first->vertex(e.second); - if(v->in_dimension() == -1 || v->in_dimension() > 1) - v->set_dimension(1); + if (!input_is_c3t3()) + { + Vertex_handle v = e.first->vertex(e.second); + if (v->in_dimension() == -1 || v->in_dimension() > 1) + v->set_dimension(1); - v = e.first->vertex(e.third); - if (v->in_dimension() == -1 || v->in_dimension() > 1) - v->set_dimension(1); + v = e.first->vertex(e.third); + if (v->in_dimension() == -1 || v->in_dimension() > 1) + v->set_dimension(1); + } #ifdef CGAL_TETRAHEDRAL_REMESHING_DEBUG ++nbe; #endif @@ -423,9 +437,11 @@ private: { m_c3t3.add_to_complex(vit, ++corner_id); - if (vit->in_dimension() == -1 || vit->in_dimension() > 0) - vit->set_dimension(0); - + if (!input_is_c3t3()) + { + if (vit->in_dimension() == -1 || vit->in_dimension() > 0) + vit->set_dimension(0); + } #ifdef CGAL_TETRAHEDRAL_REMESHING_DEBUG ++nbv; #endif @@ -452,7 +468,9 @@ private: for (vit = tr().finite_vertices_begin(); vit != tr().finite_vertices_end(); ++vit) { - if (vit->in_dimension() < 0 || vit->in_dimension() > 3) + // dimension is -1 for Mesh_3 "far points" + // for other vertices, it is in [0; 3] + if (vit->in_dimension() < -1 || vit->in_dimension() > 3) return false; } return true; diff --git a/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/tetrahedral_remeshing_helpers.h b/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/tetrahedral_remeshing_helpers.h index 637bbb51bb6..c8d370d07a4 100644 --- a/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/tetrahedral_remeshing_helpers.h +++ b/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/tetrahedral_remeshing_helpers.h @@ -564,15 +564,12 @@ namespace Tetrahedral_remeshing { typedef typename C3t3::Edge Edge; boost::unordered_set edges; - c3t3.triangulation().incident_edges(v, - std::inserter(edges, edges.begin())); + c3t3.triangulation().finite_incident_edges(v, std::inserter(edges, edges.begin())); std::size_t count = 0; - for (typename boost::unordered_set::iterator eit = edges.begin(); - eit != edges.end(); - ++eit) + for (const Edge& e : edges) { - if (c3t3.is_in_complex(*eit)) + if (c3t3.is_in_complex(e)) ++count; } return count; @@ -605,7 +602,7 @@ namespace Tetrahedral_remeshing c3t3.triangulation().finite_incident_edges(v, std::back_inserter(edges)); int feature_count = 0; - BOOST_FOREACH(Edge ei, edges) + for(const Edge& ei : edges) { if (c3t3.is_in_complex(ei)) { @@ -1204,7 +1201,10 @@ namespace Tetrahedral_remeshing vit != tr.finite_vertices_end(); ++vit) { - //vertices_per_dimension[vit->info()].push_back(vit); + if (vit->in_dimension() == -1) + continue;//far point + CGAL_assertion(vit->in_dimension() >= 0 && vit->in_dimension() < 4); + vertices_per_dimension[vit->in_dimension()].push_back(vit); } From d0baa099d067e8ec08af79bd94945f5044b92b5b Mon Sep 17 00:00:00 2001 From: Jane Tournois Date: Fri, 7 Feb 2020 16:49:35 +0100 Subject: [PATCH 103/568] remove max_si computation, not needed anymore also fix the count of c3t3 simplices in init_c3t3 (protected by debug macro anyway) --- .../tetrahedral_adaptive_remeshing_impl.h | 21 ++++++++++++------- 1 file changed, 14 insertions(+), 7 deletions(-) diff --git a/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/tetrahedral_adaptive_remeshing_impl.h b/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/tetrahedral_adaptive_remeshing_impl.h index c3b1191054b..acce57d6bda 100644 --- a/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/tetrahedral_adaptive_remeshing_impl.h +++ b/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/tetrahedral_adaptive_remeshing_impl.h @@ -327,8 +327,6 @@ private: std::size_t nbv = 0; #endif - Subdomain_index max_si = 0; - //tag cells typedef typename Tr::Finite_cells_iterator Finite_cells_iterator; for (Finite_cells_iterator cit = tr().finite_cells_begin(); @@ -338,7 +336,7 @@ private: if (m_cell_selector(cit)) { m_c3t3.add_to_complex(cit, cit->subdomain_index()); - max_si = (std::max)(max_si, cit->subdomain_index()); + #ifdef CGAL_TETRAHEDRAL_REMESHING_DEBUG ++nbc; #endif @@ -351,10 +349,11 @@ private: cit->vertex(i)->set_dimension(3); } } +#ifdef CGAL_TETRAHEDRAL_REMESHING_DEBUG + else if (input_is_c3t3() && m_c3t3.is_in_complex(cit)) + ++nbc; +#endif } - if(max_si == 0) - std::cerr << "Warning : Maximal subdomain index is 0" << std::endl - << " Remeshing is likely to fail." << std::endl; //tag facets typedef typename Tr::Facet Facet; @@ -367,7 +366,7 @@ private: Facet mf = tr().mirror_facet(f); Subdomain_index s1 = f.first->subdomain_index(); Subdomain_index s2 = mf.first->subdomain_index(); - if ( s1 != s2 + if (s1 != s2 || get(fcmap, f) || get(fcmap, mf) || (m_c3t3_pbackup == NULL && f.first->is_facet_on_surface(f.second))) @@ -388,6 +387,10 @@ private: ++nbf; #endif } +#ifdef CGAL_TETRAHEDRAL_REMESHING_DEBUG + else if (input_is_c3t3() && m_c3t3.is_in_complex(f)) + ++nbf; +#endif } #ifdef CGAL_TETRAHEDRAL_REMESHING_DEBUG CGAL::Tetrahedral_remeshing::debug::dump_facets_in_complex(m_c3t3, "facets_in_complex.off"); @@ -420,6 +423,10 @@ private: ++nbe; #endif } +#ifdef CGAL_TETRAHEDRAL_REMESHING_DEBUG + else if (input_is_c3t3() && m_c3t3.is_in_complex(e)) + ++nbe; +#endif } #ifdef CGAL_TETRAHEDRAL_REMESHING_DEBUG CGAL::Tetrahedral_remeshing::debug::dump_edges_in_complex(m_c3t3, "edges_in_complex.polylines.txt"); From 8bacd01349557b8236b26a003a73407784f343b4 Mon Sep 17 00:00:00 2001 From: Jane Tournois Date: Fri, 7 Feb 2020 16:49:59 +0100 Subject: [PATCH 104/568] minor cout fix --- Tetrahedral_remeshing/include/CGAL/tetrahedral_remeshing.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Tetrahedral_remeshing/include/CGAL/tetrahedral_remeshing.h b/Tetrahedral_remeshing/include/CGAL/tetrahedral_remeshing.h index e3942a0a011..9d38f8089ce 100644 --- a/Tetrahedral_remeshing/include/CGAL/tetrahedral_remeshing.h +++ b/Tetrahedral_remeshing/include/CGAL/tetrahedral_remeshing.h @@ -207,7 +207,7 @@ namespace CGAL #ifdef CGAL_TETRAHEDRAL_REMESHING_VERBOSE std::cout << "Tetrahedral remeshing (" << "nb_iter = " << max_it - << "protect = " << std::boolalpha << protect << ", " + << ", protect = " << std::boolalpha << protect << ")" << std::endl; std::cout << "Init tetrahedral remeshing..."; From 24082a71142f11c5b853d6f2b0f822bba6b85ecd Mon Sep 17 00:00:00 2001 From: Laurent Rineau Date: Wed, 12 Feb 2020 16:30:26 +0100 Subject: [PATCH 105/568] Fix compilation errors, with a few compiler ``` include/CGAL/Triangulation_hierarchy_3.h:163:23: error: invalid use of 'this' at top level noexcept(noexcept(this->Tr_Base::swap(tr))) ^~~~ ``` That is actually the subject of a C++ Defect: http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#1207 Anyway, this was used only for the `noexcept` specification of `swap` functions, and I no longer use `swap` for the move semantic. I can remove those noexcept` specifications. --- Triangulation_2/include/CGAL/Triangulation_hierarchy_2.h | 4 +--- Triangulation_3/include/CGAL/Regular_triangulation_3.h | 1 - Triangulation_3/include/CGAL/Triangulation_hierarchy_3.h | 1 - 3 files changed, 1 insertion(+), 5 deletions(-) diff --git a/Triangulation_2/include/CGAL/Triangulation_hierarchy_2.h b/Triangulation_2/include/CGAL/Triangulation_hierarchy_2.h index 9dfb0e4e010..91ca9486b0a 100644 --- a/Triangulation_2/include/CGAL/Triangulation_hierarchy_2.h +++ b/Triangulation_2/include/CGAL/Triangulation_hierarchy_2.h @@ -133,8 +133,7 @@ public: //Helping void copy_triangulation(const Triangulation_hierarchy_2 &tr); - void swap(Triangulation_hierarchy_2 &tr) - noexcept(noexcept(this->Tr_Base::swap(tr))); + void swap(Triangulation_hierarchy_2 &tr); void clear(); // CHECKING @@ -393,7 +392,6 @@ template void Triangulation_hierarchy_2:: swap(Triangulation_hierarchy_2 &tr) - noexcept(noexcept(this->Tr_Base::swap(tr))) { Tr_Base* temp; Tr_Base::swap(tr); diff --git a/Triangulation_3/include/CGAL/Regular_triangulation_3.h b/Triangulation_3/include/CGAL/Regular_triangulation_3.h index 8502a68264d..dfa28cf61e6 100644 --- a/Triangulation_3/include/CGAL/Regular_triangulation_3.h +++ b/Triangulation_3/include/CGAL/Regular_triangulation_3.h @@ -203,7 +203,6 @@ public: ~Regular_triangulation_3() = default; void swap(Regular_triangulation_3& tr) - noexcept(noexcept(this->Tr_Base::swap(tr))) { // The 'vertices' and 'hidden_points' members of // 'hidden_point_visitor' should be empty as they are only filled diff --git a/Triangulation_3/include/CGAL/Triangulation_hierarchy_3.h b/Triangulation_3/include/CGAL/Triangulation_hierarchy_3.h index e92fbf94e07..a395e1c13e9 100644 --- a/Triangulation_3/include/CGAL/Triangulation_hierarchy_3.h +++ b/Triangulation_3/include/CGAL/Triangulation_hierarchy_3.h @@ -160,7 +160,6 @@ public: }; void swap(Triangulation_hierarchy_3 &tr) - noexcept(noexcept(this->Tr_Base::swap(tr))) { Tr_Base::swap(tr); for(int i=1; i Date: Thu, 13 Feb 2020 12:10:52 +0100 Subject: [PATCH 106/568] fix iteration counting --- .../internal/tetrahedral_adaptive_remeshing_impl.h | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/tetrahedral_adaptive_remeshing_impl.h b/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/tetrahedral_adaptive_remeshing_impl.h index acce57d6bda..d4aa4fc2a0c 100644 --- a/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/tetrahedral_adaptive_remeshing_impl.h +++ b/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/tetrahedral_adaptive_remeshing_impl.h @@ -498,8 +498,9 @@ private: const std::size_t& nb_extra_iterations) { std::size_t it_nb = 0; - while (it_nb++ < max_it) + while (it_nb < max_it) { + ++it_nb; #ifdef CGAL_TETRAHEDRAL_REMESHING_VERBOSE std::cout << "# Iteration " << it_nb << " #" << std::endl; #endif @@ -524,8 +525,10 @@ private: #endif } - while (it_nb++ < max_it + nb_extra_iterations) + while (it_nb < max_it + nb_extra_iterations) { + ++it_nb; + flip(); // smooth(); From a7c2de7521d2e3bb6972fdcff2f355f6c58b1196 Mon Sep 17 00:00:00 2001 From: Jane Tournois Date: Thu, 13 Feb 2020 12:12:48 +0100 Subject: [PATCH 107/568] improve/fix collapse step the topology_test was too restrictive and now makes better use of the info stored in the C3t3 this commit also moves collapse-specific code to the corresponding file (instead of the general "helpers" header) --- .../internal/collapse_short_edges.h | 248 ++++++++++++++- .../internal/tetrahedral_remeshing_helpers.h | 297 +----------------- 2 files changed, 258 insertions(+), 287 deletions(-) diff --git a/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/collapse_short_edges.h b/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/collapse_short_edges.h index 3abd2e90ece..c43c2ed069d 100644 --- a/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/collapse_short_edges.h +++ b/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/collapse_short_edges.h @@ -306,7 +306,7 @@ namespace internal //int si_nb_vh0 = nb_incident_subdomains(vh0, c3t3); //int si_nb_vh1 = nb_incident_subdomains(vh1, c3t3); //int vertices_subdomain_nb_vh0 = std::max(si_nb_vh0, si_nb_vh1); - //bool is_on_hull_vh0 = is_on_hull(vh0, c3t3) || is_on_hull(vh1, c3t3); + //bool is_on_hull_vh0 = is_on_convex_hull(vh0, c3t3) || is_on_convex_hull(vh1, c3t3); //if( is_valid_for_domains() ) return VALID; @@ -337,6 +337,219 @@ namespace internal bool not_an_edge; }; + template + bool topology_test(const typename C3t3::Edge& edge, + const C3t3& c3t3, + const CellSelector& cell_selector) + { + typedef typename C3t3::Vertex_handle Vertex_handle; + typedef typename C3t3::Cell_handle Cell_handle; + typedef typename C3t3::Edge Edge; + typedef typename C3t3::Facet Facet; + typedef typename C3t3::Triangulation::Facet_circulator Facet_circulator; + + const Vertex_handle v0 = edge.first->vertex(edge.second); + const Vertex_handle v1 = edge.first->vertex(edge.third); + + // the "topology test" checks that : + // no incident non-boundary facet has 3 boundary edges + // no incident boundary facet has 3 feature edges + + Facet_circulator fcirc = c3t3.triangulation().incident_facets(edge); + Facet_circulator fdone = fcirc; + do + { + if (c3t3.triangulation().is_infinite(fcirc->first)) + continue; + + const Facet& f = *fcirc; + if (is_boundary(c3t3, f, cell_selector)) + //boundary : check that facet does not have 3 feature edges + { + //Get the ids of the opposite vertices + for (int i = 1; i < 4; i++) + { + Vertex_handle vi = f.first->vertex((f.second + i) % 4); + if (vi != v0 && vi != v1 && nb_incident_subdomains(vi, c3t3) > 1) + { + if (is_edge_in_complex(v0, vi, c3t3) + && is_edge_in_complex(v1, vi, c3t3)) + return false; + } + } + } + else //non-boundary : check that facet does not have 3 boundary edges + { + const Cell_handle circ = f.first; + const int i = f.second; + if ( is_boundary(c3t3, Edge(circ, (i + 1) % 4, (i + 2) % 4), cell_selector) + && is_boundary(c3t3, Edge(circ, (i + 2) % 4, (i + 3) % 4), cell_selector) + && is_boundary(c3t3, Edge(circ, (i + 3) % 4, (i + 1) % 4), cell_selector)) + return false; + } + } while (++fcirc != fdone); + + return true; + } + + + template + Subdomain_relation compare_subdomains(const typename C3t3::Vertex_handle v0, + const typename C3t3::Vertex_handle v1, + const C3t3& c3t3) + { + typedef typename C3t3::Subdomain_index Subdomain_index; + + std::vector subdomains_v0; + incident_subdomains(v0, c3t3, std::back_inserter(subdomains_v0)); + std::sort(subdomains_v0.begin(), subdomains_v0.end()); + + std::vector subdomains_v1; + incident_subdomains(v1, c3t3, std::back_inserter(subdomains_v1)); + std::sort(subdomains_v1.begin(), subdomains_v1.end()); + + if (subdomains_v0.size() == subdomains_v1.size()) + { + for (unsigned int i = 0; i < subdomains_v0.size(); i++) + if (subdomains_v0[i] != subdomains_v1[i]) + return DIFFERENT; + return EQUAL; + } + else + { + std::vector + intersection((std::min)(subdomains_v0.size(), subdomains_v1.size()), -1); + typename std::vector::iterator + end_it = std::set_intersection(subdomains_v0.begin(), subdomains_v0.end(), + subdomains_v1.begin(), subdomains_v1.end(), + intersection.begin()); + std::ptrdiff_t intersection_size = (end_it - intersection.begin()); + + if (subdomains_v0.size() > subdomains_v1.size() + && intersection_size == std::ptrdiff_t(subdomains_v1.size())) + { + return INCLUDES; + } + else if (intersection_size == std::ptrdiff_t(subdomains_v0.size())) { + return INCLUDED; + } + } + return DIFFERENT; + } + + template + void get_edge_info_for_collapse(const typename C3t3::Edge& edge, + bool& update_v0, + bool& update_v1, + const C3t3& c3t3, + const CellSelector& cell_selector) + { + typedef typename C3t3::Vertex_handle Vertex_handle; + + update_v0 = false; + update_v1 = false; + + const Vertex_handle v0 = edge.first->vertex(edge.second); + const Vertex_handle v1 = edge.first->vertex(edge.third); + + const int dim0 = c3t3.in_dimension(v0); + const int dim1 = c3t3.in_dimension(v1); + + if (dim0 == 3) + { + CGAL_assertion(!is_on_convex_hull(v0, c3t3)); + update_v0 = true; + if (dim1 == 3) + { + CGAL_assertion(!is_on_convex_hull(v1, c3t3)); + update_v1 = true; + return; + } + else // dim1 is 2, 1, or 0 + return; + } + else if (dim1 == 3) + { + update_v1 = true; + return; + } + + // from now on, all cases lie on surfaces, or between surfaces + CGAL_assertion(dim0 != 3 && dim1 != 3); + + //feature edges and feature vertices + if (dim0 < 2 || dim1 < 2) + { + if (c3t3.is_in_complex(edge)) + { + if (!topology_test(edge, c3t3, cell_selector)) + return; + + const std::size_t nb_si_v0 = nb_incident_subdomains(v0, c3t3); + const std::size_t nb_si_v1 = nb_incident_subdomains(v1, c3t3); + + if (nb_si_v0 > nb_si_v1) { + update_v1 = true; + } + else if (nb_si_v1 > nb_si_v0) { + update_v0 = true; + } + else { + update_v0 = true; + update_v1 = true; + } + } + return; + } + + if (dim0 == 2 && dim1 == 2) + { + if (is_boundary(c3t3, edge, cell_selector)) + { + if (!topology_test(edge, c3t3, cell_selector)) + return; + Subdomain_relation subdomain_rel = compare_subdomains(v0, v1, c3t3); + + //Vertices on the same surface + if (subdomain_rel == INCLUDES) { + update_v1 = true; + } + else if (subdomain_rel == INCLUDED) { + update_v0 = true; + } + else if (subdomain_rel == EQUAL) + { + if (c3t3.number_of_edges() == 0) + { + update_v0 = true; + update_v1 = true; + } + else + { + const bool v0_on_feature = is_on_feature(v0); + const bool v1_on_feature = is_on_feature(v1); + + if (v0_on_feature && v1_on_feature) { + if (c3t3.is_in_complex(edge)) { + if (!c3t3.is_in_complex(v0)) + update_v0 = true; + if (!c3t3.is_in_complex(v1)) + update_v1 = true; + } + } + else { + if (!v0_on_feature) { + update_v0 = true; + } + if (!v1_on_feature) { + update_v1 = true; + } + } + } + } + } + } + } template Collapse_type get_collapse_type(const typename C3t3::Edge& edge, @@ -345,7 +558,7 @@ namespace internal { bool update_v0 = false; bool update_v1 = false; - get_edge_info(edge, update_v0, update_v1, c3t3, cell_selector); + get_edge_info_for_collapse(edge, update_v0, update_v1, c3t3, cell_selector); if (update_v0 && update_v1) return TO_MIDPOINT; else if (update_v0) return TO_V1; @@ -367,8 +580,8 @@ namespace internal int dim0 = c3t3.in_dimension(v0); int dim1 = c3t3.in_dimension(v1); - bool is_v0_on_hull = is_on_hull(v0, c3t3); - bool is_v1_on_hull = is_on_hull(v1, c3t3); + bool is_v0_on_hull = is_on_convex_hull(v0, c3t3); + bool is_v1_on_hull = is_on_convex_hull(v1, c3t3); if (dim0 == 3 && dim1 == 3) { @@ -1004,6 +1217,10 @@ namespace internal #ifdef CGAL_TETRAHEDRAL_REMESHING_DEBUG debug::dump_edges(short_edges, "short_edges.polylines.txt"); + + std::ofstream short_success("short_collapse_success.polylines.txt"); + std::ofstream short_fail("short_collapse_fail.polylines.txt"); + std::ofstream short_cancel("short_collapse_canceled.polylines.txt"); #endif while(!short_edges.empty()) @@ -1025,24 +1242,43 @@ namespace internal && tr.tds().is_edge(e.first, e.second, cell, i1, i2) && tr.segment(Edge(cell, i1, i2)).squared_length() < sq_low) { +#ifdef CGAL_TETRAHEDRAL_REMESHING_DEBUG + const typename T3::Point p1 = e.first->point(); + const typename T3::Point p2 = e.second->point(); +#endif + Edge edge(cell, i1, i2); if (!can_be_collapsed(edge, c3t3, protect_boundaries, cell_selector)) + { +#ifdef CGAL_TETRAHEDRAL_REMESHING_DEBUG + short_cancel << "2 " << point(p1) << " " << point(p2) << std::endl; +#endif continue; - + } #ifdef CGAL_TETRAHEDRAL_REMESHING_VERBOSE Vertex_handle vh = #endif collapse_edge(edge, c3t3, sq_high, - protect_boundaries, cell_selector, + protect_boundaries, cell_selector, visitor); #ifdef CGAL_TETRAHEDRAL_REMESHING_VERBOSE if (vh != Vertex_handle()) ++nb_collapses; +#endif +#ifdef CGAL_TETRAHEDRAL_REMESHING_DEBUG + if (vh != Vertex_handle()) + short_success << "2 " << point(p1) << " " << point(p2) << std::endl; + else + short_fail << "2 " << point(p1) << " " << point(p2) << std::endl; #endif } }//end loop on short_edges +#ifdef CGAL_TETRAHEDRAL_REMESHING_DEBUG + short_success.close(); + short_fail.close(); +#endif #ifdef CGAL_TETRAHEDRAL_REMESHING_VERBOSE std::cout << " done (" << nb_collapses << " collapses)." << std::endl; diff --git a/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/tetrahedral_remeshing_helpers.h b/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/tetrahedral_remeshing_helpers.h index c8d370d07a4..e331cfa1559 100644 --- a/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/tetrahedral_remeshing_helpers.h +++ b/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/tetrahedral_remeshing_helpers.h @@ -205,6 +205,15 @@ namespace Tetrahedral_remeshing point(v3->point())); } + template + bool is_boundary(const C3T3& c3t3, + const typename C3T3::Facet& f, + const CellSelector& cell_selector) + { + return c3t3.is_in_complex(f) + || cell_selector(f.first) != cell_selector(f.first->neighbor(f.second)); + } + template bool is_boundary(const C3T3& c3t3, const typename C3T3::Triangulation::Edge& e, @@ -272,11 +281,10 @@ namespace Tetrahedral_remeshing return false; } - template + template bool is_edge_in_complex(const typename C3t3::Vertex_handle& v0, - const typename C3t3::Vertex_handle& v1, - const C3t3& c3t3, - CellSelector /*cell_selector*/) + const typename C3t3::Vertex_handle& v1, + const C3t3& c3t3) { typedef typename C3t3::Edge Edge; typedef typename C3t3::Cell_handle Cell_handle; @@ -289,219 +297,6 @@ namespace Tetrahedral_remeshing return false; } - template - bool topology_test(const typename C3t3::Edge& edge, - const C3t3& c3t3, - CellSelector cell_selector) - { - typedef typename C3t3::Vertex_handle Vertex_handle; - typedef typename C3t3::Triangulation::Facet_circulator Facet_circulator; - typedef typename C3t3::Subdomain_index Subdomain_index; - - Vertex_handle v0 = edge.first->vertex(edge.second); - Vertex_handle v1 = edge.first->vertex(edge.third); - - Facet_circulator fcirc = c3t3.triangulation().incident_facets(edge); - Facet_circulator fdone = fcirc; - do - { - if (c3t3.triangulation().is_infinite(fcirc->first)) - continue; - - Subdomain_index si_circ = fcirc->first->subdomain_index(); - Subdomain_index si_neigh = fcirc->first->neighbor(fcirc->second)->subdomain_index(); - if (si_circ == si_neigh) - { - //Get the ids of the opposite vertices - for (int i = 1; i < 4; i++) - { - Vertex_handle vi = fcirc->first->vertex((fcirc->second + i) % 4); - if (vi != v0 && vi != v1 && nb_incident_subdomains(vi, c3t3) > 1) - { - if (is_edge_in_complex(v0, vi, c3t3, cell_selector) - && is_edge_in_complex(v1, vi, c3t3, cell_selector)) - return false; - } - } - } - } while (++fcirc != fdone); - - return true; - } - - template - Subdomain_relation compare_subdomains(typename C3t3::Vertex_handle v0, - typename C3t3::Vertex_handle v1, - const C3t3& c3t3) - { - typedef typename C3t3::Subdomain_index Subdomain_index; - - std::vector subdomains_v0; - incident_subdomains(v0, c3t3, std::back_inserter(subdomains_v0)); - std::sort(subdomains_v0.begin(), subdomains_v0.end()); - - std::vector subdomains_v1; - incident_subdomains(v1, c3t3, std::back_inserter(subdomains_v1)); - std::sort(subdomains_v1.begin(), subdomains_v1.end()); - - if (subdomains_v0.size() == subdomains_v1.size()) - { - for (unsigned int i = 0; i < subdomains_v0.size(); i++) - if (subdomains_v0[i] != subdomains_v1[i]) - return DIFFERENT; - return EQUAL; - } - else - { - std::vector - intersection((std::min)(subdomains_v0.size(), subdomains_v1.size()), -1); - typename std::vector::iterator - end_it = std::set_intersection(subdomains_v0.begin(), subdomains_v0.end(), - subdomains_v1.begin(), subdomains_v1.end(), - intersection.begin()); - std::ptrdiff_t intersection_size = (end_it - intersection.begin()); - - if (subdomains_v0.size() > subdomains_v1.size() - && intersection_size == std::ptrdiff_t(subdomains_v1.size())) - { - return INCLUDES; - } - else if (intersection_size == std::ptrdiff_t(subdomains_v0.size())) { - return INCLUDED; - } - } - return DIFFERENT; - } - - - - template - void get_edge_info(const typename C3t3::Edge& edge, - bool& update_v0, - bool& update_v1, - const C3t3& c3t3, - CellSelector cell_selector) - { - typedef typename C3t3::Vertex_handle Vertex_handle; - - Vertex_handle v0 = edge.first->vertex(edge.second); - Vertex_handle v1 = edge.first->vertex(edge.third); - - int dim0 = c3t3.in_dimension(v0); - int dim1 = c3t3.in_dimension(v1); - - std::size_t nb_si_v0 = nb_incident_subdomains(v0, c3t3); - std::size_t nb_si_v1 = nb_incident_subdomains(v1, c3t3); - - update_v0 = false; - update_v1 = false; - - bool is_v0_on_hull = is_on_hull(v0, c3t3); - bool is_v1_on_hull = is_on_hull(v1, c3t3); - - //Same type imaginary or inside vertices - if (dim0 == 3 && dim1 == 3) - { - if (is_v0_on_hull && is_v1_on_hull)//both endvertices are on hull - { - if (is_on_hull(edge, c3t3)) //edge also is on hull - { - update_v0 = true; - update_v1 = true; - } - } - else - { - if (!is_v0_on_hull) //v0 not on hull - update_v0 = true; - if (!is_v1_on_hull) //v1 not on hull - update_v1 = true; - } - return; - } - //Feature edge case - if (nb_si_v0 > 2 && nb_si_v1 > 2) - { - if (c3t3.is_in_complex(edge)) - { - if (!topology_test(edge, c3t3, cell_selector)) - return; - - if (nb_si_v0 > nb_si_v1) { - update_v1 = true; - } - else if (nb_si_v1 > nb_si_v0) { - update_v0 = true; - } - else { - update_v0 = true; - update_v1 = true; - } - } - return; - } - - if (dim0 == 2 && dim1 == 2) - { - if (is_boundary(c3t3, edge, cell_selector)) - { - if (!topology_test(edge, c3t3, cell_selector)) - return; - Subdomain_relation subdomain_rel = compare_subdomains(v0, v1, c3t3); - - //Vertices on the same surface - if (subdomain_rel == INCLUDES) { - update_v1 = true; - } - else if (subdomain_rel == INCLUDED) { - update_v0 = true; - } - else if (subdomain_rel == EQUAL) - { - if (c3t3.number_of_edges() == 0) - { - update_v0 = true; - update_v1 = true; - } - else - { - bool v0_on_feature = is_on_feature(v0); - bool v1_on_feature = is_on_feature(v1); - - if (v0_on_feature && v1_on_feature) { - if (c3t3.is_in_complex(edge)) { - if (!c3t3.is_in_complex(v0)) - update_v0 = true; - if (!c3t3.is_in_complex(v1)) - update_v1 = true; - } - } - else { - if (!v0_on_feature) { - update_v0 = true; - } - if (!v1_on_feature) { - update_v1 = true; - } - } - } - } - } - - return; - } - //In the case of mixte edges - if (dim0 == 2 && dim1 == 3 && !is_v1_on_hull) { - update_v1 = true; - return; - } - - if (dim1 == 2 && dim0 == 3 && !is_v0_on_hull) { - update_v0 = true; - return; - } - } - template OutputIterator incident_subdomains(const typename C3t3::Vertex_handle v, const C3t3& c3t3, @@ -624,7 +419,7 @@ namespace Tetrahedral_remeshing * i.e. finite and incident to at least one infinite cell */ template - bool is_on_hull(const typename C3t3::Vertex_handle v, + bool is_on_convex_hull(const typename C3t3::Vertex_handle v, const C3t3& c3t3) { if (v == c3t3.triangulation().infinite_vertex()) @@ -635,40 +430,9 @@ namespace Tetrahedral_remeshing std::vector cells; c3t3.triangulation().incident_cells(v, std::back_inserter(cells)); - for (std::size_t i = 0; i < cells.size(); ++i) + for (Cell_handle ci : cells) { - if (c3t3.triangulation().is_infinite(cells[i])) - return true; - } - return false; - } - - template - bool is_on_domain_hull(const typename C3t3::Vertex_handle v, - const C3t3& c3t3, - const typename C3t3::Subdomain_index& imaginary_index) - { - if (v == c3t3.triangulation().infinite_vertex()) - return false; - - on hull == incident to infinite cell - typedef typename C3t3::Triangulation::Cell_handle Cell_handle; - - bool met_inside_cell = false; - bool met_outside_cell = false; - - std::vector cells; - c3t3.triangulation().incident_cells(v, std::back_inserter(cells)); - for (std::size_t i = 0; i < cells.size(); ++i) - { - if (c3t3.triangulation().is_infinite(cells[i]) - || !c3t3.is_in_complex(cells[i]) - || cells[i]->subdomain_index() == imaginary_index) - met_outside_cell = true; - else - met_inside_cell = true; - - if (met_inside_cell && met_outside_cell) + if (c3t3.triangulation().is_infinite(ci)) return true; } return false; @@ -680,7 +444,7 @@ namespace Tetrahedral_remeshing * i.e. finite and incident to at least one infinite cell */ template - bool is_on_hull(const typename C3t3::Edge & edge, + bool is_on_convex_hull(const typename C3t3::Edge & edge, const C3t3& c3t3) { typedef typename C3t3::Triangulation::Cell_circulator Cell_circulator; @@ -694,35 +458,6 @@ namespace Tetrahedral_remeshing return false; } - - template - bool is_on_domain_hull(const typename C3t3::Edge & edge, - const C3t3& c3t3, - const typename C3t3::Subdomain_index& imaginary_index) - { - typedef typename C3t3::Triangulation::Cell_circulator Cell_circulator; - - bool met_inside_cell = false; - bool met_outside_cell = false; - - Cell_circulator circ = c3t3.triangulation().incident_cells(edge); - Cell_circulator done = circ; - do - { - if (c3t3.triangulation().is_infinite(circ) - || !c3t3.is_in_complex(circ) - || circ->subdomain_index() == imaginary_index) - met_outside_cell = true; - else - met_inside_cell = true; - - if (met_inside_cell && met_outside_cell) - return true; - } while (++circ != done); - - return false; - } - template bool is_outside(const typename C3t3::Edge & edge, const C3t3& c3t3, From b2686b35cc408beed49d6c884330dc063fb81c4d Mon Sep 17 00:00:00 2001 From: Jane Tournois Date: Thu, 13 Feb 2020 12:13:10 +0100 Subject: [PATCH 108/568] fix cout --- .../include/CGAL/tetrahedral_remeshing.h | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/Tetrahedral_remeshing/include/CGAL/tetrahedral_remeshing.h b/Tetrahedral_remeshing/include/CGAL/tetrahedral_remeshing.h index 9d38f8089ce..d467862b6da 100644 --- a/Tetrahedral_remeshing/include/CGAL/tetrahedral_remeshing.h +++ b/Tetrahedral_remeshing/include/CGAL/tetrahedral_remeshing.h @@ -206,8 +206,8 @@ namespace CGAL #ifdef CGAL_TETRAHEDRAL_REMESHING_VERBOSE std::cout << "Tetrahedral remeshing (" - << "nb_iter = " << max_it - << ", protect = " << std::boolalpha << protect + << "nb_iter = " << max_it << ", " + << "protect = " << std::boolalpha << protect << ")" << std::endl; std::cout << "Init tetrahedral remeshing..."; @@ -355,8 +355,8 @@ namespace CGAL #ifdef CGAL_TETRAHEDRAL_REMESHING_VERBOSE std::cout << "Tetrahedral remeshing (" - << "nb_iter = " << max_it - << "protect = " << std::boolalpha << protect << ", " + << "nb_iter = " << max_it << ", " + << "protect = " << std::boolalpha << protect << ")" << std::endl; std::cout << "Init tetrahedral remeshing..."; From 628b80007730a4222ffd78961b0925a1531c679d Mon Sep 17 00:00:00 2001 From: Jane Tournois Date: Fri, 14 Feb 2020 11:31:46 +0100 Subject: [PATCH 109/568] move back to helpers file the functions that are needed by smoothing --- .../internal/collapse_short_edges.h | 161 +----------------- .../internal/tetrahedral_remeshing_helpers.h | 158 +++++++++++++++++ 2 files changed, 159 insertions(+), 160 deletions(-) diff --git a/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/collapse_short_edges.h b/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/collapse_short_edges.h index c43c2ed069d..7c790bd56bb 100644 --- a/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/collapse_short_edges.h +++ b/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/collapse_short_edges.h @@ -392,165 +392,6 @@ namespace internal return true; } - - template - Subdomain_relation compare_subdomains(const typename C3t3::Vertex_handle v0, - const typename C3t3::Vertex_handle v1, - const C3t3& c3t3) - { - typedef typename C3t3::Subdomain_index Subdomain_index; - - std::vector subdomains_v0; - incident_subdomains(v0, c3t3, std::back_inserter(subdomains_v0)); - std::sort(subdomains_v0.begin(), subdomains_v0.end()); - - std::vector subdomains_v1; - incident_subdomains(v1, c3t3, std::back_inserter(subdomains_v1)); - std::sort(subdomains_v1.begin(), subdomains_v1.end()); - - if (subdomains_v0.size() == subdomains_v1.size()) - { - for (unsigned int i = 0; i < subdomains_v0.size(); i++) - if (subdomains_v0[i] != subdomains_v1[i]) - return DIFFERENT; - return EQUAL; - } - else - { - std::vector - intersection((std::min)(subdomains_v0.size(), subdomains_v1.size()), -1); - typename std::vector::iterator - end_it = std::set_intersection(subdomains_v0.begin(), subdomains_v0.end(), - subdomains_v1.begin(), subdomains_v1.end(), - intersection.begin()); - std::ptrdiff_t intersection_size = (end_it - intersection.begin()); - - if (subdomains_v0.size() > subdomains_v1.size() - && intersection_size == std::ptrdiff_t(subdomains_v1.size())) - { - return INCLUDES; - } - else if (intersection_size == std::ptrdiff_t(subdomains_v0.size())) { - return INCLUDED; - } - } - return DIFFERENT; - } - - template - void get_edge_info_for_collapse(const typename C3t3::Edge& edge, - bool& update_v0, - bool& update_v1, - const C3t3& c3t3, - const CellSelector& cell_selector) - { - typedef typename C3t3::Vertex_handle Vertex_handle; - - update_v0 = false; - update_v1 = false; - - const Vertex_handle v0 = edge.first->vertex(edge.second); - const Vertex_handle v1 = edge.first->vertex(edge.third); - - const int dim0 = c3t3.in_dimension(v0); - const int dim1 = c3t3.in_dimension(v1); - - if (dim0 == 3) - { - CGAL_assertion(!is_on_convex_hull(v0, c3t3)); - update_v0 = true; - if (dim1 == 3) - { - CGAL_assertion(!is_on_convex_hull(v1, c3t3)); - update_v1 = true; - return; - } - else // dim1 is 2, 1, or 0 - return; - } - else if (dim1 == 3) - { - update_v1 = true; - return; - } - - // from now on, all cases lie on surfaces, or between surfaces - CGAL_assertion(dim0 != 3 && dim1 != 3); - - //feature edges and feature vertices - if (dim0 < 2 || dim1 < 2) - { - if (c3t3.is_in_complex(edge)) - { - if (!topology_test(edge, c3t3, cell_selector)) - return; - - const std::size_t nb_si_v0 = nb_incident_subdomains(v0, c3t3); - const std::size_t nb_si_v1 = nb_incident_subdomains(v1, c3t3); - - if (nb_si_v0 > nb_si_v1) { - update_v1 = true; - } - else if (nb_si_v1 > nb_si_v0) { - update_v0 = true; - } - else { - update_v0 = true; - update_v1 = true; - } - } - return; - } - - if (dim0 == 2 && dim1 == 2) - { - if (is_boundary(c3t3, edge, cell_selector)) - { - if (!topology_test(edge, c3t3, cell_selector)) - return; - Subdomain_relation subdomain_rel = compare_subdomains(v0, v1, c3t3); - - //Vertices on the same surface - if (subdomain_rel == INCLUDES) { - update_v1 = true; - } - else if (subdomain_rel == INCLUDED) { - update_v0 = true; - } - else if (subdomain_rel == EQUAL) - { - if (c3t3.number_of_edges() == 0) - { - update_v0 = true; - update_v1 = true; - } - else - { - const bool v0_on_feature = is_on_feature(v0); - const bool v1_on_feature = is_on_feature(v1); - - if (v0_on_feature && v1_on_feature) { - if (c3t3.is_in_complex(edge)) { - if (!c3t3.is_in_complex(v0)) - update_v0 = true; - if (!c3t3.is_in_complex(v1)) - update_v1 = true; - } - } - else { - if (!v0_on_feature) { - update_v0 = true; - } - if (!v1_on_feature) { - update_v1 = true; - } - } - } - } - } - } - } - template Collapse_type get_collapse_type(const typename C3t3::Edge& edge, const C3t3& c3t3, @@ -558,7 +399,7 @@ namespace internal { bool update_v0 = false; bool update_v1 = false; - get_edge_info_for_collapse(edge, update_v0, update_v1, c3t3, cell_selector); + get_edge_info(edge, update_v0, update_v1, c3t3, cell_selector); if (update_v0 && update_v1) return TO_MIDPOINT; else if (update_v0) return TO_V1; diff --git a/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/tetrahedral_remeshing_helpers.h b/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/tetrahedral_remeshing_helpers.h index e331cfa1559..c676bfd3f05 100644 --- a/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/tetrahedral_remeshing_helpers.h +++ b/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/tetrahedral_remeshing_helpers.h @@ -570,6 +570,164 @@ namespace Tetrahedral_remeshing return oit; } + template + void get_edge_info(const typename C3t3::Edge& edge, + bool& update_v0, + bool& update_v1, + const C3t3& c3t3, + const CellSelector& cell_selector) + { + typedef typename C3t3::Vertex_handle Vertex_handle; + + update_v0 = false; + update_v1 = false; + + const Vertex_handle v0 = edge.first->vertex(edge.second); + const Vertex_handle v1 = edge.first->vertex(edge.third); + + const int dim0 = c3t3.in_dimension(v0); + const int dim1 = c3t3.in_dimension(v1); + + if (dim0 == 3) + { + CGAL_assertion(!is_on_convex_hull(v0, c3t3)); + update_v0 = true; + if (dim1 == 3) + { + CGAL_assertion(!is_on_convex_hull(v1, c3t3)); + update_v1 = true; + return; + } + else // dim1 is 2, 1, or 0 + return; + } + else if (dim1 == 3) + { + update_v1 = true; + return; + } + + // from now on, all cases lie on surfaces, or between surfaces + CGAL_assertion(dim0 != 3 && dim1 != 3); + + //feature edges and feature vertices + if (dim0 < 2 || dim1 < 2) + { + if (c3t3.is_in_complex(edge)) + { + if (!topology_test(edge, c3t3, cell_selector)) + return; + + const std::size_t nb_si_v0 = nb_incident_subdomains(v0, c3t3); + const std::size_t nb_si_v1 = nb_incident_subdomains(v1, c3t3); + + if (nb_si_v0 > nb_si_v1) { + update_v1 = true; + } + else if (nb_si_v1 > nb_si_v0) { + update_v0 = true; + } + else { + update_v0 = true; + update_v1 = true; + } + } + return; + } + + if (dim0 == 2 && dim1 == 2) + { + if (is_boundary(c3t3, edge, cell_selector)) + { + if (!topology_test(edge, c3t3, cell_selector)) + return; + Subdomain_relation subdomain_rel = compare_subdomains(v0, v1, c3t3); + + //Vertices on the same surface + if (subdomain_rel == INCLUDES) { + update_v1 = true; + } + else if (subdomain_rel == INCLUDED) { + update_v0 = true; + } + else if (subdomain_rel == EQUAL) + { + if (c3t3.number_of_edges() == 0) + { + update_v0 = true; + update_v1 = true; + } + else + { + const bool v0_on_feature = is_on_feature(v0); + const bool v1_on_feature = is_on_feature(v1); + + if (v0_on_feature && v1_on_feature) { + if (c3t3.is_in_complex(edge)) { + if (!c3t3.is_in_complex(v0)) + update_v0 = true; + if (!c3t3.is_in_complex(v1)) + update_v1 = true; + } + } + else { + if (!v0_on_feature) { + update_v0 = true; + } + if (!v1_on_feature) { + update_v1 = true; + } + } + } + } + } + } + } + + template + Subdomain_relation compare_subdomains(const typename C3t3::Vertex_handle v0, + const typename C3t3::Vertex_handle v1, + const C3t3& c3t3) + { + typedef typename C3t3::Subdomain_index Subdomain_index; + + std::vector subdomains_v0; + incident_subdomains(v0, c3t3, std::back_inserter(subdomains_v0)); + std::sort(subdomains_v0.begin(), subdomains_v0.end()); + + std::vector subdomains_v1; + incident_subdomains(v1, c3t3, std::back_inserter(subdomains_v1)); + std::sort(subdomains_v1.begin(), subdomains_v1.end()); + + if (subdomains_v0.size() == subdomains_v1.size()) + { + for (unsigned int i = 0; i < subdomains_v0.size(); i++) + if (subdomains_v0[i] != subdomains_v1[i]) + return DIFFERENT; + return EQUAL; + } + else + { + std::vector + intersection((std::min)(subdomains_v0.size(), subdomains_v1.size()), -1); + typename std::vector::iterator + end_it = std::set_intersection(subdomains_v0.begin(), subdomains_v0.end(), + subdomains_v1.begin(), subdomains_v1.end(), + intersection.begin()); + std::ptrdiff_t intersection_size = (end_it - intersection.begin()); + + if (subdomains_v0.size() > subdomains_v1.size() + && intersection_size == std::ptrdiff_t(subdomains_v1.size())) + { + return INCLUDES; + } + else if (intersection_size == std::ptrdiff_t(subdomains_v0.size())) { + return INCLUDED; + } + } + return DIFFERENT; + } + namespace debug { From 2ef615d65d5fa5447bad5a36e847f8e182b7e16d Mon Sep 17 00:00:00 2001 From: Jane Tournois Date: Fri, 14 Feb 2020 11:32:27 +0100 Subject: [PATCH 110/568] reset smoothing function to its initial version and make sure it compiles with C3t3 requirements and a regular triangulation --- .../internal/smooth_vertices.h | 1394 ++++++++--------- .../tetrahedral_adaptive_remeshing_impl.h | 7 +- 2 files changed, 683 insertions(+), 718 deletions(-) diff --git a/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/smooth_vertices.h b/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/smooth_vertices.h index 905faa068c2..a902ac35a98 100644 --- a/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/smooth_vertices.h +++ b/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/smooth_vertices.h @@ -7,803 +7,769 @@ #include #include -#include -#include #include -#include -#include #include #include namespace CGAL { -namespace Tetrahedral_remeshing -{ -namespace internal -{ - template - std::pair - make_surface_index(const SubdomainIndex& s1, - const SubdomainIndex& s2) + namespace Tetrahedral_remeshing { - if (s1 < s2) - return std::make_pair(s1, s2); - else - return std::make_pair(s2, s1); - } - - template - CGAL::Vector_3 project_on_tangent_plane(const CGAL::Point_3& gi, - const CGAL::Point_3& pi, - const CGAL::Vector_3& normal) - { - typename Gt::Construct_vector_3 - vec = Gt().construct_vector_3_object(); - typename Gt::Construct_scaled_vector_3 - scale = Gt().construct_scaled_vector_3_object(); - return scale(normal, CGAL::scalar_product(normal, vec(gi, pi))); - } - - template - typename C3t3::Triangulation::Geom_traits::Vector_3 - compute_vertex_normal(const typename C3t3::Vertex_handle v, - const C3t3& c3t3) - { - typedef typename C3t3::Subdomain_index Subdomain_index; - typedef typename C3t3::Triangulation::Facet Facet; - typedef typename C3t3::Triangulation::Cell_handle Cell_handle; - typedef typename C3t3::Triangulation::Geom_traits Gt; - typedef typename Gt::Vector_3 Vector_3; - typedef std::pair< Subdomain_index, Subdomain_index> Surface_index; - - typename Gt::Construct_opposite_vector_3 - opp = c3t3.triangulation().geom_traits().construct_opposite_vector_3_object(); - typename Gt::Construct_sum_of_vectors_3 - sum = c3t3.triangulation().geom_traits().construct_sum_of_vectors_3_object(); - typename Gt::Construct_scaled_vector_3 - scale = c3t3.triangulation().geom_traits().construct_scaled_vector_3_object(); - typename Gt::Compute_squared_length_3 - sqlen = c3t3.triangulation().geom_traits().compute_squared_length_3_object(); - - std::vector facets; - c3t3.triangulation().incident_facets(v, std::back_inserter(facets)); - - Vector_3 normal = CGAL::NULL_VECTOR; - - for (Facet f : facets) + namespace internal { - Cell_handle ch = f.first; - Cell_handle n_ch = f.first->neighbor(f.second); - - Subdomain_index si = ch->subdomain_index(); - Subdomain_index si_mirror = n_ch->subdomain_index(); - - if (si != si_mirror - || c3t3.triangulation().is_infinite(ch) - || c3t3.triangulation().is_infinite(n_ch)) + template + CGAL::Vector_3 project_on_tangent_plane(const CGAL::Point_3& gi, + const CGAL::Point_3& pi, + const CGAL::Vector_3& normal) { - Surface_index surf_i = make_surface_index(si, si_mirror); - - Vector_3 n = facet_normal(c3t3.triangulation(), f); - - if (si < si_mirror || c3t3.triangulation().is_infinite(ch)) - n = opp(n); - - normal = sum(normal, n); + typedef typename Gt::Vector_3 Vector_3; + Vector_3 diff = pi - gi; + return Vector_3(gi, gi + (normal * diff) * normal); } - } - if (normal != CGAL::NULL_VECTOR) - return scale(normal, 1. / CGAL::sqrt(sqlen(normal))); - else - return CGAL::NULL_VECTOR; - } - - template - void compute_vertices_normals(const C3t3& c3t3, - VertexNormalsMap& normals_map) - { - typedef typename C3t3::Triangulation Tr; - typedef typename C3t3::Cell_handle Cell_handle; - typedef typename C3t3::Vertex_handle Vertex_handle; - typedef typename C3t3::Subdomain_index Subdomain_index; - typedef typename Tr::Finite_facets_iterator Finite_facets_iterator; - typedef typename Tr::Geom_traits::Vector_3 Vector_3; - typedef std::pair Surface_index; - - const Tr& tr = c3t3.triangulation(); - - typename Tr::Geom_traits::Construct_opposite_vector_3 - opp = tr.geom_traits().construct_opposite_vector_3_object(); - - for (Finite_facets_iterator fit = tr.finite_facets_begin(); - fit != tr.finite_facets_end(); ++fit) - { - Cell_handle ch = fit->first; - Cell_handle n_ch = fit->first->neighbor(fit->second); - - Subdomain_index si = ch->subdomain_index(); - Subdomain_index si_mirror = n_ch->subdomain_index(); - - if (si != si_mirror || tr.is_infinite(ch) || tr.is_infinite(n_ch)) + template + void compute_vertices_normals(const C3t3& c3t3, + VertexNormalsMap& normals_map) { - Surface_index surf_i = make_surface_index(si, si_mirror); - for (int i = 0; i < 3; ++i) + typedef typename C3t3::Triangulation Tr; + typedef typename C3t3::Cell_handle Cell_handle; + typedef typename C3t3::Vertex_handle Vertex_handle; + typedef typename C3t3::Subdomain_index Subdomain_index; + typedef typename C3t3::Surface_patch_index Surface_patch_index; + typedef typename Tr::Finite_facets_iterator Finite_facets_iterator; + typedef typename Tr::Gt::Vector_3 Vector_3; + + const Tr& tr = c3t3.triangulation(); + + for (Finite_facets_iterator fit = tr.finite_facets_begin(); + fit != tr.finite_facets_end(); ++fit) { - Vertex_handle v_id = fit->first->vertex(indices(fit->second ,i)); - normals_map[v_id][surf_i] = CGAL::NULL_VECTOR; - } - } - } + Cell_handle ch = fit->first; + Cell_handle n_ch = fit->first->neighbor(fit->second); - for (Finite_facets_iterator fit = tr.finite_facets_begin(); - fit != tr.finite_facets_end(); ++fit) - { - Cell_handle ch = fit->first; - Cell_handle n_ch = fit->first->neighbor(fit->second); + Subdomain_index si = ch->subdomain_index(); + Subdomain_index si_mirror = n_ch->subdomain_index(); - Subdomain_index si = ch->subdomain_index(); - Subdomain_index si_mirror = n_ch->subdomain_index(); - - if (si != si_mirror || tr.is_infinite(ch) || tr.is_infinite(n_ch)) - { - Surface_index surf_i = make_surface_index(si, si_mirror); - - Vector_3 n = CGAL::Tetrahedral_remeshing::facet_normal(tr, *fit); - - if (si < si_mirror || tr.is_infinite(ch)) - n = opp(n); - - for (int i = 0; i < 3; ++i) - { - Vertex_handle v_id = fit->first->vertex(indices(fit->second, i)); - Vector_3& v_n = normals_map[v_id][surf_i]; - v_n = v_n + n; - } - } - } - - //normalize the computed normals - for (typename VertexNormalsMap::iterator vnm_it = normals_map.begin(); - vnm_it != normals_map.end(); ++vnm_it) - { - //mapped_type is map - for (typename VertexNormalsMap::mapped_type::iterator it = vnm_it->second.begin(); - it != vnm_it->second.end(); ++it) - { - Vector_3& n = it->second; - n = n / CGAL::sqrt(n*n); - } - } - } - - - template - std::pair - surface_index(const typename C3t3::Vertex_handle v, const C3t3& c3t3) - { - typedef typename C3t3::Triangulation::Facet Facet; - typedef typename C3t3::Triangulation::Cell_handle Cell_handle; - typedef typename C3t3::Subdomain_index Subdomain_index; - - std::vector facets; - c3t3.triangulation().incident_facets(v, std::back_inserter(facets)); - - for (Facet f : facets) - { - Cell_handle ch = f.first; - Cell_handle n_ch = f.first->neighbor(f.second); - - Subdomain_index si = ch->subdomain_index(); - Subdomain_index si_mirror = n_ch->subdomain_index(); - - if (si != si_mirror - || c3t3.triangulation().is_infinite(ch) - || c3t3.triangulation().is_infinite(n_ch)) - { - return make_surface_index(si, si_mirror); - } - } - CGAL_assertion(false); - return make_surface_index(0, 0); - } - - template - const boost::unordered_set - subdomain_indices(const typename C3t3::Vertex_handle v, const C3t3& c3t3) - { - typedef typename C3t3::Triangulation::Cell_handle Cell_handle; - - std::vector cells; - c3t3.triangulation().incident_cells(v, std::back_inserter(cells)); - - boost::unordered_set res; - for (Cell_handle c : cells) - { - if (c3t3.is_in_complex(c)) - res.insert(c->subdomain_index()); - } - return res; - } - - template - void createMLSSurfaces(const C3t3& c3t3, - FMLSVector& subdomain_FMLS, - SurfaceIndexMap& subdomain_FMLS_indices) - { - typedef typename C3t3::Subdomain_index Subdomain_index; - typedef typename C3t3::Triangulation Tr; - typedef typename Tr::Geom_traits Gt; - typedef typename Tr::Edge Edge; - typedef typename Tr::Vertex_handle Vertex_handle; - typedef typename Gt::Point_3 Point_3; - typedef typename Gt::Vector_3 Vector_3; - - typedef std::pair Surface_index; - - const Tr& tr = c3t3.triangulation(); - - SurfaceIndexMap current_subdomain_FMLS_indices; - - SurfaceIndexMap subdomain_sample_numbers; - - //Count the number of vertices for each boundary surface (i.e. one per label) - for (typename Tr::Finite_vertices_iterator vit = tr.finite_vertices_begin(); - vit != tr.finite_vertices_end(); ++vit) - { - if (c3t3.in_dimension(vit) == 2) - { - const boost::unordered_set& v_subdomain_indices = subdomain_indices(vit, c3t3); - if (v_subdomain_indices.size() == 2) - { - boost::unordered_set::const_iterator si_it = v_subdomain_indices.cbegin(); - Subdomain_index s1 = *si_it; - ++si_it; - Subdomain_index s2 = *si_it; - - subdomain_sample_numbers[make_surface_index(s1, s2)]++; - } - } - } - - std::vector< float* > pns; - - int count = 0; - //Memory allocation for the point plus normals of the point samples - for (typename SurfaceIndexMap::iterator it = subdomain_sample_numbers.begin(); - it != subdomain_sample_numbers.end(); ++it) - { - current_subdomain_FMLS_indices[it->first] = count; - pns.push_back(new float[it->second * 6]); - count++; - } - - boost::unordered_map > vertices_normals; - compute_vertices_normals(c3t3, vertices_normals); - - std::vector current_v_count(count, 0); - std::vector point_spacing(count, 0); - std::vector point_spacing_count(count, 0); - - //Allocation of the PN - for (typename Tr::Finite_vertices_iterator vit = tr.finite_vertices_begin(); - vit != tr.finite_vertices_end(); ++vit) - { - boost::unordered_set vertices_subdomain_indices - = subdomain_indices(vit, c3t3); - if (vertices_subdomain_indices.size() == 2) - { - Subdomain_index s1 = *(vertices_subdomain_indices.begin()); - Subdomain_index s2 = *(++vertices_subdomain_indices.begin()); - - Surface_index surf_i = make_surface_index(s1, s2); - - int fmls_id = current_subdomain_FMLS_indices[surf_i]; - - Point_3& point = vit->point(); - - pns[fmls_id][6 * current_v_count[fmls_id]] = point.x(); - pns[fmls_id][6 * current_v_count[fmls_id] + 1] = point.y(); - pns[fmls_id][6 * current_v_count[fmls_id] + 2] = point.z(); - - Vector_3& normal = vertices_normals[vit][surf_i]; - - pns[fmls_id][6 * current_v_count[fmls_id] + 3] = normal.x(); - pns[fmls_id][6 * current_v_count[fmls_id] + 4] = normal.y(); - pns[fmls_id][6 * current_v_count[fmls_id] + 5] = normal.z(); - - current_v_count[fmls_id]++; - } - } - - typedef std::pair Edge_VV; - typedef std::map EdgeMapIndex; - EdgeMapIndex edgeMap; - - for (typename C3t3::Facet_iterator fit = c3t3.facets_begin(); - fit != c3t3.facets_end(); ++fit) - { - for (int i = 0; i < 2; i++) - { - for (int j = i + 1; j < 3; j++) - { - Edge edge(fit->first, indices(fit->second, i), indices(fit->second, j)); - - Vertex_handle vh0 = edge.first->vertex(edge.second); - Vertex_handle vh1 = edge.first->vertex(edge.third); - Edge_VV evv = make_vertex_pair(vh1, vh0); - - if ( subdomain_indices(vh0, c3t3).size() == 2 - && subdomain_indices(vh1, c3t3).size() == 2 - && edgeMap.find(evv) == edgeMap.end()) + if (c3t3.is_in_complex(fit)) { - edgeMap[evv] = 0; - Surface_index surf_i = make_surface_index( - fit->first->subdomain_index(), - fit->first->neighbor(fit->second)->subdomain_index()); - int fmls_id = current_subdomain_FMLS_indices[surf_i]; + Surface_patch_index surf_i = c3t3.surface_patch_index(fit); + for (int i = 0; i < 3; ++i) + { + Vertex_handle v_id = fit->first->vertex(indices(fit->second, i)); + normals_map[v_id][surf_i] = CGAL::NULL_VECTOR; + } + } + } - point_spacing[fmls_id] += CGAL::sqrt(tr.segment(edge).squared_length()); - point_spacing_count[fmls_id] ++; + for (Finite_facets_iterator fit = tr.finite_facets_begin(); + fit != tr.finite_facets_end(); ++fit) + { + Cell_handle ch = fit->first; + Cell_handle n_ch = fit->first->neighbor(fit->second); + + Subdomain_index si = ch->subdomain_index(); + Subdomain_index si_mirror = n_ch->subdomain_index(); + + if (c3t3.is_in_complex(fit)) + { + Surface_patch_index surf_i = c3t3.surface_patch_index(fit); + + Vector_3 n = CGAL::normal(*fit, tr.geom_traits()); + + if (si < si_mirror || tr.is_infinite(ch)) + n = -1. * n; + + for (int i = 0; i < 3; ++i) + { + Vector_3& v_n = normals_map[fit->first->vertex(indices(fit->second, i))][surf_i]; + v_n = v_n + n; + } + } + } + + //normalize the computed normals + for (typename VertexNormalsMap::iterator vnm_it = normals_map.begin(); + vnm_it != normals_map.end(); ++vnm_it) + { + //value type is map + for (typename VertexNormalsMap::value_type::iterator it = vnm_it->begin(); + it != vnm_it->end(); ++it) + { + Vector_3& n = it->second; + n = n / CGAL::sqrt(n * n); } } } - } - int nb_of_mls_to_create = 0; - double average_point_spacing = 0; - //Cretaing the actual MLS surfaces - for (SurfaceIndexMap::iterator it = current_subdomain_FMLS_indices.begin(); - it != current_subdomain_FMLS_indices.end(); ++it) - { - if (current_v_count[it->second] > 3) + template + bool project(const SurfacePatchIndex& /* si */, + CGAL::Vector_3& gi, + CGAL::Vector_3& projected_point) { - nb_of_mls_to_create++; + // if (subdomain_FMLS_indices.find(si) == subdomain_FMLS_indices.end()) + // return false; + typedef typename Gt::Vector_3 Vector_3; + typedef typename Gt::Point_3 Point_3; - double current_point_spacing = point_spacing[it->second] / point_spacing_count[it->second]; - point_spacing[it->second] = current_point_spacing; - - average_point_spacing += current_point_spacing; - } - } - - average_point_spacing = average_point_spacing / nb_of_mls_to_create; - - subdomain_FMLS.resize(nb_of_mls_to_create, FMLS()); - - count = 0; - //Cretaing the actual MLS surfaces - for (SurfaceIndexMap::iterator it = current_subdomain_FMLS_indices.begin(); - it != current_subdomain_FMLS_indices.end(); ++it) - { - if (current_v_count[it->second] > 3) - { - double current_point_spacing = point_spacing[it->second]; - - //subdomain_FMLS[count].toggleHermite(true); - subdomain_FMLS[count].setPN(pns[it->second], current_v_count[it->second], current_point_spacing); - // subdomain_FMLS[count].toggleHermite(true); - subdomain_FMLS_indices[it->first] = count; - - count++; - } - else { - std::cout << "Problem of number for MLS : " << current_v_count[it->second] << std::endl; - } - } - } - - template - bool project(const typename C3t3& c3t3, - const typename C3t3::Vertex_handle& v, - typename C3t3::Triangulation::Geom_traits::Vector_3& gi, - typename C3t3::Triangulation::Geom_traits::Vector_3& projected_point, - FMLSVector& subdomain_FMLS, - SurfaceIndexMap& subdomain_FMLS_indices) - { - typedef typename C3t3::Triangulation::Geom_traits::Point_3 Point_3; - typedef typename C3t3::Triangulation::Geom_traits::Vector_3 Vector_3; - typedef typename C3t3::Subdomain_index Subdomain_index; - - std::pair si = surface_index(v, c3t3); - - if (subdomain_FMLS_indices.find(si) == subdomain_FMLS_indices.end()) - return false; - - Point_3 point(gi.x(), gi.y(), gi.z()); - - Vector_3 res_normal; - Point_3 result(point); - - FMLS& fmls = subdomain_FMLS[subdomain_FMLS_indices[si]]; - - int it_nb = 0; - - float epsilon = fmls.getPNScale() / 1000.; - float sq_eps = epsilon * epsilon; - - do - { - point = result; - - fmls.fastProjectionCPU(point, result, res_normal); - - if (std::isnan(result[0]) || std::isnan(result[1]) || std::isnan(result[2])) { - std::cout << "MLS error detected si size " << si.first << " - " << si.second - << " : " << fmls.getPNSize() << std::endl; - return false; - } - - it_nb++; - - } while (CGAL::squared_distance(result, point) > sq_eps && it_nb < 5); - - projected_point = Vector_3(result[0], result[1], result[2]); - - return true; - } - - - template - bool check_inversion_and_move(const typename Tr::Vertex_handle v, - const CGAL::Vector_3& move, - const std::vector& cells) - { - typedef typename Tr::Cell_handle Cell_handle; - - const typename Tr::Point backup = v->point(); //backup v's position - typename Tr::Point new_pos(v->point().x() + move.x(), - v->point().y() + move.y(), - v->point().z() + move.z()); - //note that weight is lost in case of Regular_triangulation - v->set_point(new_pos); - - for (Cell_handle ci : cells) - { - if (CGAL::POSITIVE != CGAL::orientation(point(ci->vertex(0)->point()), - point(ci->vertex(1)->point()), - point(ci->vertex(2)->point()), - point(ci->vertex(3)->point()))) - { - v->set_point(backup); - return false; - } - } - return true; - } - - template - bool project(const C3t3& c3t3, - const typename C3t3::Vertex_handle v, - typename C3t3::Triangulation::Geom_traits::Vector_3& gi, - typename C3t3::Triangulation::Geom_traits::Vector_3& projected_point ) - { - typedef typename C3t3::Subdomain_index Subdomain_index; - - const std::pair si = surface_index(v); - if( subdomain_FMLS_indices.find( si ) == subdomain_FMLS_indices.end() ) - return false; - - Vec3Df point( gi.x(), gi.y(), gi.z() ); - if( isnan(point[0]) || isnan(point[1]) || isnan(point[2]) ){ - std::cout << "Initial point error " << point << std::endl; - return false; - } - - Vec3Df res_normal; - Vec3Df result(point); - - FMLS & fmls = subdomain_FMLS[ subdomain_FMLS_indices[ si ] ]; - - int it_nb = 0; - - float epsilon = fmls.getPNScale() /1000.; - - do{ - point = result; - - fmls.fastProjectionCPU( point, result, res_normal ); - - if( isnan(result[0]) || isnan(result[1]) || isnan(result[2]) ){ - std::cout << "MLS error detected si size " << si.first << " - " << si.second << " : " << fmls.getPNSize() << std::endl; - return false; + if (std::isnan(gi.x()) || std::isnan(gi.y()) || isnan(gi.z())) + { + std::cout << "Initial point error " << gi << std::endl; + return false; } - it_nb++; + Vector_3 res_normal; + Point_3 point; + Point_3 result = CGAL::ORIGIN + gi; - }while ( (result - point).getLength() > epsilon && it_nb < 5 ); + //FMLS& fmls = subdomain_FMLS[subdomain_FMLS_indices[si]]; - projected_point = K::Vector_3( result[0], result[1], result[2] ); + // int it_nb = 0; + // const int max_it_nb = 5; + //const float epsilon = fmls.getPNScale() / 1000.; - return true; -} + //do + //{ + // point = result; - template - typename C3T3::Triangulation::Geom_traits::Vector_3 - move_3d(typename C3T3::Vertex_handle v, const C3T3& c3t3) - { - typedef typename C3T3::Edge Edge; - typedef typename C3T3::Vertex_handle Vertex_handle; - typedef typename C3T3::Triangulation::Geom_traits Gt; - typedef typename Gt::Vector_3 Vector_3; + // //fmls.fastProjectionCPU(point, result, res_normal); - const Gt& gt = c3t3.triangulation().geom_traits(); + // if (std::isnan(result[0]) || std::isnan(result[1]) || std::isnan(result[2])){ + // std::cout << "MLS error detected si size " << si.first << " - " << si.second + // << " : " << fmls.getPNSize() << std::endl; + // return false; + // } - Vector_3 move = CGAL::NULL_VECTOR; + //} while ((result - point).getLength() > epsilon && ++it_nb < max_it_nb); - std::vector edges; - c3t3.triangulation().incident_edges(v, std::back_inserter(edges)); + projected_point = Vector_3(result.x(), result.y(), result.z()); - if (edges.empty()) - return move; - - typename Gt::Construct_vector_3 vec - = gt.construct_vector_3_object(); - typename Gt::Construct_sum_of_vectors_3 sum - = gt.construct_sum_of_vectors_3_object(); - - BOOST_FOREACH(Edge e, edges) - { - Vertex_handle ve = (e.first->vertex(e.second) != v) - ? e.first->vertex(e.second) - : e.first->vertex(e.third); - move = sum(move, Vector_3(CGAL::ORIGIN, point(ve->point()))); - } - - typename Gt::Construct_scaled_vector_3 scale - = gt.construct_scaled_vector_3_object(); - return scale(move, 1. / edges.size()); - } - - template - typename C3T3::Triangulation::Geom_traits::Vector_3 - move_2d(typename C3T3::Vertex_handle v, - const C3T3& c3t3, - const typename C3T3::Subdomain_index& imaginary_index, - const CellSelector cell_selector) - { - typedef typename C3T3::Subdomain_index Subdomain_index; - typedef typename C3T3::Edge Edge; - typedef typename C3T3::Vertex_handle Vertex_handle; - typedef typename C3T3::Triangulation::Geom_traits Gt; - typedef typename Gt::Vector_3 Vector_3; - typedef typename Gt::Point_3 Point_3; - - const Gt& gt = c3t3.triangulation().geom_traits(); - - std::vector edges; - c3t3.triangulation().incident_edges(v, std::back_inserter(edges)); - - Vector_3 move = CGAL::NULL_VECTOR; - if (edges.empty()) - return move; - - typename Gt::Construct_vector_3 vec - = gt.construct_vector_3_object(); - typename Gt::Construct_sum_of_vectors_3 sum - = gt.construct_sum_of_vectors_3_object(); - - std::size_t nbe = 0; - for(Edge e : edges) - { - if(!c3t3.is_in_complex(e) && is_boundary(c3t3, e, cell_selector)) - { - Vertex_handle ve = (e.first->vertex(e.second) != v) - ? e.first->vertex(e.second) - : e.first->vertex(e.third); - move = sum(move, vec(CGAL::ORIGIN, point(ve->point()))); - ++nbe; + return true; } - } - if (nbe > 0) - { - // WIP in this section + template + bool check_inversion_and_move(const typename Tr::Vertex_handle v, + const CGAL::Vector_3& move, + const CellVector& cells, + const Tr& tr) + { + const typename Tr::Point backup = v->point(); //backup v's position + const typename Tr::Point new_pos(point(backup) + move); + v->set_point(new_pos); - typedef std::pair Surface_index; - typedef std::map SurfaceIndexMap; - SurfaceIndexMap subdomain_FMLS_indices; - std::vector< FMLS > subdomain_FMLS; - //createMLSSurfaces(c3t3, subdomain_FMLS, subdomain_FMLS_indices); + for(const typename CellVector::value_type& ci : cells) + { + if (CGAL::POSITIVE != CGAL::orientation(point(ci->vertex(0)->point()), + point(ci->vertex(1)->point()), + point(ci->vertex(2)->point()), + point(ci->vertex(3)->point()))) + { + v->set_point(backup); + return false; + } + } + return true; + } - typename Gt::Construct_scaled_vector_3 scale - = gt.construct_scaled_vector_3_object(); - move = scale(move, 1. / nbe); + template + typename C3T3::Triangulation::Geom_traits::Vector_3 + move_3d(typename C3T3::Vertex_handle v, const C3T3& c3t3) + { + typedef typename C3T3::Edge Edge; + typedef typename C3T3::Vertex_handle Vertex_handle; + typedef typename C3T3::Triangulation::Geom_traits::Vector_3 Vector_3; - const Point_3 current_pos = point(v->point()); - const Point_3 smoothed_position = current_pos + move; - Point_3 final_position = CGAL::ORIGIN; + Vector_3 move = CGAL::NULL_VECTOR; - Vector_3 normal = compute_vertex_normal(v, c3t3); + std::vector edges; + c3t3.triangulation().incident_edges(v, std::back_inserter(edges)); - Vector_3 normal_projection = project_on_tangent_plane( - smoothed_position, //smoothed position - current_pos, //current position - normal); + if (edges.empty()) + return move; - Vector_3 mls_projection; - if (project(c3t3, v, normal_projection, mls_projection, - subdomain_FMLS, subdomain_FMLS_indices)) - move = move + mls_projection; - else - move = move + normal_projection; + BOOST_FOREACH(Edge e, edges) + { + Vertex_handle ve = (e.first->vertex(e.second) != v) + ? e.first->vertex(e.second) + : e.first->vertex(e.third); + move = move + Vector_3(CGAL::ORIGIN, ve->point()); + } - return move; - } - else - return CGAL::NULL_VECTOR; - } + return 1. / edges.size() * move; + } - template - typename C3T3::Triangulation::Geom_traits::Vector_3 - move_1d(typename C3T3::Vertex_handle v, - const C3T3& c3t3, - const typename C3T3::Subdomain_index& /*imaginary_index*/) - { - typedef typename C3T3::Edge Edge; - typedef typename C3T3::Vertex_handle Vertex_handle; - typedef typename C3T3::Triangulation::Geom_traits Gt; - typedef typename Gt::Vector_3 Vector_3; + template + typename C3T3::Triangulation::Geom_traits::Vector_3 + move_2d(typename C3T3::Vertex_handle v, + const C3T3& c3t3, + const typename C3T3::Subdomain_index& imaginary_index) + { + typedef typename C3T3::Edge Edge; + typedef typename C3T3::Vertex_handle Vertex_handle; + typedef typename C3T3::Triangulation::Geom_traits::Vector_3 Vector_3; - const Gt& gt = c3t3.triangulation().geom_traits(); + Vector_3 move = CGAL::NULL_VECTOR; - Vector_3 move = CGAL::NULL_VECTOR; + std::vector edges; + c3t3.triangulation().incident_edges(v, std::back_inserter(edges)); - std::vector edges; - c3t3.triangulation().incident_edges(v, std::back_inserter(edges)); + if (edges.empty()) + return move; - if (edges.empty()) - return move; + std::size_t nbe = 0; + BOOST_FOREACH(Edge e, edges) + { + if (CGAL::is_on_domain_hull(e, c3t3, imaginary_index)) + { + Vertex_handle ve = (e.first->vertex(e.second) != v) + ? e.first->vertex(e.second) + : e.first->vertex(e.third); + move = move + Vector_3(CGAL::ORIGIN, ve->point()); + ++nbe; + } + } - typename Gt::Construct_vector_3 vec - = gt.construct_vector_3_object(); - typename Gt::Construct_sum_of_vectors_3 sum - = gt.construct_sum_of_vectors_3_object(); + if (nbe > 0) + return (1. / nbe) * move; + else + return CGAL::NULL_VECTOR; + } - std::size_t nbe = 0; - BOOST_FOREACH(Edge e, edges) - { - if (!c3t3.is_in_complex(e)) - continue; + template + typename C3T3::Triangulation::Geom_traits::Vector_3 + move_1d(typename C3T3::Vertex_handle v, + const C3T3& c3t3, + const typename C3T3::Subdomain_index& /*imaginary_index*/) + { + typedef typename C3T3::Edge Edge; + typedef typename C3T3::Vertex_handle Vertex_handle; + typedef typename C3T3::Triangulation::Geom_traits::Vector_3 Vector_3; - Vertex_handle ve = (e.first->vertex(e.second) != v) - ? e.first->vertex(e.second) - : e.first->vertex(e.third); + Vector_3 move = CGAL::NULL_VECTOR; - move = sum(move, vec(CGAL::ORIGIN, point(ve->point()))); - ++nbe; - } + std::vector edges; + c3t3.triangulation().incident_edges(v, std::back_inserter(edges)); - if (nbe == 2) - { - typename Gt::Construct_scaled_vector_3 scale - = gt.construct_scaled_vector_3_object(); - return scale(move, 0.5); - } - else - return CGAL::NULL_VECTOR; - } + if (edges.empty()) + return move; - template - void smooth_vertices_new(C3T3& c3t3, - const typename C3T3::Subdomain_index& imaginary_index, - const bool protect_boundaries, - CellSelector cell_selector) - { - typedef typename C3T3::Triangulation Tr; - typedef typename C3T3::Vertex_handle Vertex_handle; - typedef typename C3T3::Cell_handle Cell_handle; - typedef typename Tr::Finite_vertices_iterator Finite_vertices_iterator; - typedef typename Tr::Geom_traits::Point_3 Point_3; - typedef typename Tr::Geom_traits::Vector_3 Vector_3; + std::size_t nbe = 0; + BOOST_FOREACH(Edge e, edges) + { + if (!c3t3.is_in_complex(e)) + continue; + + Vertex_handle ve = (e.first->vertex(e.second) != v) + ? e.first->vertex(e.second) + : e.first->vertex(e.third); + + move = move + Vector_3(CGAL::ORIGIN, ve->point()); + ++nbe; + } + + if (nbe == 2) + return 0.5 * move; + else + return CGAL::NULL_VECTOR; + } + + template + void smooth_vertices_new(C3T3& c3t3, + const typename C3T3::Subdomain_index& imaginary_index, + const bool /*protect_boundaries*/, + CellSelector cell_selector) + { + typedef typename C3T3::Triangulation Tr; + typedef typename C3T3::Vertex_handle Vertex_handle; + typedef typename C3T3::Cell_handle Cell_handle; + typedef typename Tr::Finite_vertices_iterator Finite_vertices_iterator; + + typedef typename Tr::Geom_traits Gt; + typedef typename Gt::Point_3 Point_3; + typedef typename Gt::Vector_3 Vector_3; #ifdef CGAL_TETRAHEDRAL_REMESHING_VERBOSE - std::cout << "Smooth vertices..."; - std::cout.flush(); + std::cout << "Smooth vertices..."; + std::cout.flush(); + std::size_t nb_done = 0; CGAL_USE(nb_done); #endif - Tr& tr = c3t3.triangulation(); + Tr& tr = c3t3.triangulation(); #ifdef CGAL_TETRAHEDRAL_REMESHING_DEBUG - CGAL::Tetrahedral_remeshing::debug::dump_vertices_by_dimension( - c3t3.triangulation(), "c3t3_vertices_before_smoothing"); + CGAL::debug::dump_vertices_by_dimension(c3t3.triangulation(), "c3t3_vertices_before_smoothing"); #endif - const std::size_t nbv = tr.number_of_vertices(); - boost::unordered_map vertex_id; - std::vector smoothing_vecs(nbv, CGAL::NULL_VECTOR); + const std::size_t nbv = tr.number_of_vertices(); + boost::unordered_map vertex_id; + std::vector smoothing_vecs(nbv, CGAL::NULL_VECTOR); + // std::vector neighbors(nbv, -1); - // generate ids for vertices - std::size_t id = 0; - for (Finite_vertices_iterator vit = tr.finite_vertices_begin(); - vit != tr.finite_vertices_end(); ++vit) - { - vertex_id[vit] = id++; - } + // generate ids for vertices + std::size_t id = 0; + for (Finite_vertices_iterator vit = tr.finite_vertices_begin(); + vit != tr.finite_vertices_end(); ++vit) + { + vertex_id[vit] = id++; + } #ifdef CGAL_TETRAHEDRAL_REMESHING_DEBUG - std::ofstream ofs_2d("moves_on_surface.polylines.txt"); - std::ofstream ofs_1d("moves_on_features.polylines.txt"); + std::ofstream ofs_2d("moves_on_surface.polylines.txt"); + std::ofstream ofs_1d("moves_on_features.polylines.txt"); #endif - // compute move depending on underlying dimension - for (Finite_vertices_iterator vit = tr.finite_vertices_begin(); - vit != tr.finite_vertices_end(); ++vit) - { - switch (vit->in_dimension()) - { - case 3: - if ( is_imaginary(vit, c3t3, imaginary_index) - || !is_selected(vit, c3t3, cell_selector)) - break; - else - smoothing_vecs[vertex_id.at(vit)] = move_3d(vit, c3t3); - break; + // compute move depending on underlying dimension + for (Finite_vertices_iterator vit = tr.finite_vertices_begin(); + vit != tr.finite_vertices_end(); ++vit) + { + switch (vit->in_dimension()) + { + case 3: + if (is_imaginary(vit, c3t3, imaginary_index) || !is_selected(vit, c3t3, cell_selector)) + break; + else + smoothing_vecs[vertex_id.at(vit)] = move_3d(vit, c3t3); + break; - case 2: - if (protect_boundaries) - break; - - smoothing_vecs[vertex_id.at(vit)] = move_2d(vit, c3t3, imaginary_index, cell_selector); + case 2: + smoothing_vecs[vertex_id.at(vit)] = move_2d(vit, c3t3, imaginary_index); #ifdef CGAL_TETRAHEDRAL_REMESHING_DEBUG - if (smoothing_vecs[vertex_id.at(vit)] != CGAL::NULL_VECTOR) - ofs_2d << "2 " << vit->point() - << " " << (CGAL::ORIGIN + smoothing_vecs[vertex_id.at(vit)]) << std::endl; + if (smoothing_vecs[vertex_id.at(vit)] != CGAL::NULL_VECTOR) + ofs_2d << "2 " << vit->point() + << " " << (CGAL::ORIGIN + smoothing_vecs[vertex_id.at(vit)]) << std::endl; #endif - break; + break; - case 1: - if (protect_boundaries) - break; - - smoothing_vecs[vertex_id.at(vit)] = move_1d(vit, c3t3, imaginary_index); + case 1: + smoothing_vecs[vertex_id.at(vit)] = move_1d(vit, c3t3, imaginary_index); #ifdef CGAL_TETRAHEDRAL_REMESHING_DEBUG - if (smoothing_vecs[vertex_id.at(vit)] != CGAL::NULL_VECTOR) - ofs_1d << "2 " << vit->point() - << " " << (CGAL::ORIGIN + smoothing_vecs[vertex_id.at(vit)]) << std::endl; + if (smoothing_vecs[vertex_id.at(vit)] != CGAL::NULL_VECTOR) + ofs_1d << "2 " << vit->point() + << " " << (CGAL::ORIGIN + smoothing_vecs[vertex_id.at(vit)]) << std::endl; #endif - default: - break; + default: + break; + } + } +#ifdef CGAL_TETRAHEDRAL_REMESHING_DEBUG + ofs_2d.close(); + ofs_1d.close(); +#endif + + // apply moves + for (Finite_vertices_iterator vit = tr.finite_vertices_begin(); + vit != tr.finite_vertices_end(); ++vit) + { + const std::size_t& vid = vertex_id.at(vit); + Point_3 new_pos = CGAL::ORIGIN + smoothing_vecs[vid]; + const Vector_3 move(vit->point(), new_pos); + + std::vector cells; + tr.finite_incident_cells(vit, std::back_inserter(cells)); + + double frac = 1.; + while (frac > 0.05 /// 1/16 = 0.0625 + && !check_inversion_and_move(vit, frac * move, cells)) + { + frac = 0.5 * frac; + } + } + +#ifdef CGAL_TETRAHEDRAL_REMESHING_DEBUG + CGAL::debug::dump_vertices_by_dimension(c3t3.triangulation(), "c3t3_vertices_after_smoothing"); +#endif } - } -#ifdef CGAL_TETRAHEDRAL_REMESHING_DEBUG - ofs_2d.close(); - ofs_1d.close(); -#endif - // apply moves - for (Finite_vertices_iterator vit = tr.finite_vertices_begin(); - vit != tr.finite_vertices_end(); ++vit) - { - const std::size_t& vid = vertex_id.at(vit); - const Point_3 new_pos = CGAL::ORIGIN + smoothing_vecs[vid]; - const Vector_3 move(point(vit->point()), new_pos); - - std::vector cells; - tr.finite_incident_cells(vit, std::back_inserter(cells)); - - double frac = 1.; - while (frac > 0.05 /// 1/16 = 0.0625 - && !check_inversion_and_move(vit, frac * move, cells)) + template + void smooth_vertices(C3T3& c3t3, + const bool protect_boundaries, + CellSelector cell_selector) { - frac = 0.5 * frac; - } - } + typedef typename C3T3::Surface_patch_index Surface_patch_index; + typedef typename C3T3::Subdomain_index Subdomain_index; + typedef typename C3T3::Triangulation Tr; + typedef typename C3T3::Vertex_handle Vertex_handle; + typedef typename C3T3::Cell_handle Cell_handle; + typedef typename C3T3::Facet Facet; + typedef typename Tr::Finite_vertices_iterator Finite_vertices_iterator; + typedef typename Tr::Finite_edges_iterator Finite_edges_iterator; -#ifdef CGAL_TETRAHEDRAL_REMESHING_DEBUG - CGAL::Tetrahedral_remeshing::debug::dump_vertices_by_dimension( - c3t3.triangulation(), "c3t3_vertices_after_smoothing"); + typedef typename Tr::Geom_traits Gt; + typedef typename Gt::Point_3 Point_3; + typedef typename Gt::Vector_3 Vector_3; + typedef typename Gt::FT FT; + +#ifdef CGAL_TETRAHEDRAL_REMESHING_VERBOSE + std::cout << "Smooth vertices..."; + std::cout.flush(); + std::size_t nb_done = 0; #endif - } + Tr& tr = c3t3.triangulation(); -}//namespace internal -}//namespace Tetrahedral_adaptive_remeshing + const std::size_t nbv = tr.number_of_vertices(); + boost::unordered_map vertex_id; + std::vector smoothing_vecs(nbv, CGAL::NULL_VECTOR); + std::vector neighbors(nbv, -1); + + //collect ids + std::size_t id = 0; + for (Finite_vertices_iterator vit = tr.finite_vertices_begin(); + vit != tr.finite_vertices_end(); ++vit) + { + vertex_id[vit] = id++; + } + + if (!protect_boundaries) + { + for (Finite_edges_iterator eit = tr.finite_edges_begin(); + eit != tr.finite_edges_end(); ++eit) + { + const Vertex_handle vh0 = eit->first->vertex(eit->second); + const Vertex_handle vh1 = eit->first->vertex(eit->third); + + const std::size_t& i0 = vertex_id.at(vh0); + const std::size_t& i1 = vertex_id.at(vh1); + + if (/*toRemesh != REMESH_IMAGINARY &&*/ c3t3.is_in_complex(*eit)) + { + if (!is_feature(vh0, c3t3)) + neighbors[i0] = std::max(0, neighbors[i0]); + if (!is_feature(vh1, c3t3)) + neighbors[i1] = std::max(0, neighbors[i1]); + + bool update_v0 = false, update_v1 = false; + + get_edge_info(*eit, update_v0, update_v1, c3t3, cell_selector); + if (update_v0) + { + const Point_3& p1 = point(vh1->point()); + smoothing_vecs[i0] = smoothing_vecs[i0] + Vector_3(p1.x(), p1.y(), p1.z()); + neighbors[i0]++; + } + if (update_v1) + { + const Point_3& p0 = point(vh0->point()); + smoothing_vecs[i1] = smoothing_vecs[i1] + Vector_3(p0.x(), p0.y(), p0.z()); + neighbors[i1]++; + } + } + } + + //collect a map of vertices subdomain indices + boost::unordered_map > vertices_subdomain_indices; + for (typename C3T3::Cell_iterator cit = c3t3.cells_in_complex_begin(); + cit != c3t3.cells_in_complex_end(); ++cit) + { + for (int i = 0; i < 4; ++i) + { + Vertex_handle vi = cit->vertex(i); + Subdomain_index si = cit->subdomain_index(); + + if (vertices_subdomain_indices.find(vi) == vertices_subdomain_indices.end()) + { + std::vector indices(1); + indices[0] = si; + vertices_subdomain_indices.insert(std::make_pair(vi, indices)); + } + else + { + std::vector& v_indices = vertices_subdomain_indices.at(vi); + if (std::find(v_indices.begin(), v_indices.end(), si) == v_indices.end()) + v_indices.push_back(si); + } + } + } + + //collect a map of vertices surface indices + boost::unordered_map > vertices_surface_indices; + for (typename C3T3::Facet_iterator fit = c3t3.facets_in_complex_begin(); + fit != c3t3.facets_in_complex_end(); ++fit) + { + const Facet f = *fit; + Surface_patch_index surface_index = c3t3.surface_patch_index(f); + for (int i = 0; i < 3; ++i) + { + Vertex_handle vi = fit->first->vertex(indices(f.second, i)); + if (vertices_subdomain_indices.at(vi).size() > 2) + { + if (vertices_surface_indices.find(vi) == vertices_surface_indices.end()) + { + std::vector indices(1); + indices[0] = surface_index; + vertices_surface_indices.insert(std::make_pair(vi, indices)); + } + else + { + std::vector& v_surface_indices = vertices_surface_indices.at(vi); + if (std::find(v_surface_indices.begin(), v_surface_indices.end(), surface_index) + == v_surface_indices.end()) + v_surface_indices.push_back(surface_index); + } + } + } + } + + //collect a map of normals at surface vertices + boost::unordered_map > vertices_normals; + for (Finite_vertices_iterator vit = tr.finite_vertices_begin(); + vit != tr.finite_vertices_end(); ++vit) + { + const std::size_t& vid = vertex_id.at(vit); + if (neighbors[vid] > 1) + { + Point_3 smoothed_position = CGAL::ORIGIN + smoothing_vecs[vid] / neighbors[vid]; + Vector_3 final_move = CGAL::NULL_VECTOR; + Point_3 final_position; + + std::size_t count = 0; + const Point_3 current_pos = point(vit->point()); + + const std::vector& v_surface_indices = vertices_surface_indices[vit]; + for (std::size_t i = 0; i < v_surface_indices.size(); ++i) + { + const Surface_patch_index& si = v_surface_indices[i]; + + Vector_3 normal_projection + = project_on_tangent_plane(smoothed_position, current_pos, vertices_normals[vit][si]); + + //Check if the mls surface exists to avoid degenrated cases + Vector_3 mls_projection; + if (project(si, normal_projection, mls_projection)) { + final_move = final_move + mls_projection; + } + else { + final_move = final_move + normal_projection; + } + count++; + } + + if (count > 0) + final_position = CGAL::ORIGIN + final_move / static_cast(count); + else + final_position = smoothed_position; + + // move vertex + vit->set_point(typename Tr::Point(final_position)); + + } + else if (neighbors[vid] > 0) + { + Vector_3 final_move = CGAL::NULL_VECTOR; + Point_3 final_position; + + int count = 0; + Vector_3 current_move(CGAL::ORIGIN, point(vit->point())); + + const std::vector& v_surface_indices = vertices_surface_indices[vit]; + for (std::size_t i = 0; i < v_surface_indices.size(); ++i) + { + Surface_patch_index si = v_surface_indices[i]; + //Check if the mls surface exists to avoid degenrated cases + + Vector_3 mls_projection; + if (project(si, current_move, mls_projection)) { + final_move = final_move + mls_projection; + } + else { + final_move = final_move + current_move; + } + count++; + } + + if (count > 0) + final_position = CGAL::ORIGIN + final_move / count; + else + final_position = CGAL::ORIGIN + current_move; + + // move vertex + vit->set_point(typename Tr::Point(final_position)); + } + } + + smoothing_vecs.clear(); + smoothing_vecs.resize(nbv, CGAL::NULL_VECTOR); + + neighbors.clear(); + neighbors.resize(nbv, -1); + + for (Finite_edges_iterator eit = tr.finite_edges_begin(); + eit != tr.finite_edges_end(); ++eit) + { + const Vertex_handle vh0 = eit->first->vertex(eit->second); + const Vertex_handle vh1 = eit->first->vertex(eit->third); + + const std::size_t& i0 = vertex_id.at(vh0); + const std::size_t& i1 = vertex_id.at(vh1); + + if (is_boundary(c3t3, *eit, cell_selector) && !c3t3.is_in_complex(*eit)) + { + bool update_v0 = false, update_v1 = false; + if (!is_feature(vh0, c3t3)) + neighbors[i0] = (std::max)(0, neighbors[i0]); + if (!is_feature(vh1, c3t3)) + neighbors[i1] = (std::max)(0, neighbors[i1]); + + get_edge_info(*eit, update_v0, update_v1, c3t3, cell_selector); + if (update_v0) + { + const Point_3& p1 = point(vh1->point()); + smoothing_vecs[i0] = smoothing_vecs[i0] + Vector_3(p1.x(), p1.y(), p1.z()); + neighbors[i0]++; + } + if (update_v1) + { + const Point_3& p0 = point(vh0->point()); + smoothing_vecs[i1] = smoothing_vecs[i1] + Vector_3(p0.x(), p0.y(), p0.z()); + neighbors[i1]++; + } + } + } + + for (Finite_vertices_iterator vit = tr.finite_vertices_begin(); + vit != tr.finite_vertices_end(); ++vit) + { + const std::size_t& vid = vertex_id.at(vit); + + if (neighbors[vid] > 1) + { + Point_3 smoothed_position = CGAL::ORIGIN + smoothing_vecs[vid] / neighbors[vid]; + const Point_3& current_pos = point(vit->point()); + Point_3 final_position = CGAL::ORIGIN; + + if (vit->in_dimension() == 3 && is_on_convex_hull(vit, c3t3)) + { + Vector_3 final_move = project_on_tangent_plane( + smoothed_position, current_pos, vertices_normals[vit][Surface_patch_index()]); + final_position = CGAL::ORIGIN + final_move; + } + else { + // Surface_patch_index si = helpers::make_surface_patch_index( + // vertices_subdomain_indices[vit][0], vertices_subdomain_indices[vit][1]); + + // Vector_3 normal_projection = project_on_tangent_plane(smoothed_position, + // current_pos, + // vertices_normals[vit][si]); + //Vector_3 mls_projection; + //if (project(si, normal_projection, mls_projection) /*|| project( si, smoothed_position, mls_projection )*/){ + // final_position = mls_projection; + // //final_position = smoothed_position; + //} + //else { + final_position = smoothed_position; + //} + // std::cout << "MLS " << final_position[0] << " - " << final_position[1] << " : " << final_position[2] << std::endl; + } + /* + Normal_iterator it = vertices_normals[vit->info()].end(); + it--; + final_position = final_position + projectOnTangentPlane( smoothed_position, current_pos , it->second ); + */ + + vit->set_point(typename Tr::Point(final_position)); + } + else if (neighbors[vid] > 0) + { + if (vit->in_dimension() == 2) + { + // Surface_patch_index si = helpers::make_surface_patch_index( + // vertices_subdomain_indices[vit][0], + // vertices_subdomain_indices[vit][1]); + + Vector_3 current_pos(CGAL::ORIGIN, point(vit->point())); + Vector_3 mls_projection; + // if (project(si, current_pos, mls_projection) /*|| project( si, smoothed_position, mls_projection )*/){ + // vit->set_point(Point_3(mls_projection.x(), mls_projection.y(), mls_projection.z())); + // } + } + } + } + } + smoothing_vecs.clear(); + smoothing_vecs.resize(nbv, CGAL::NULL_VECTOR); + + neighbors.clear(); + neighbors.resize(nbv, 0); + + for (Finite_edges_iterator eit = tr.finite_edges_begin(); + eit != tr.finite_edges_end(); ++eit) + { + //bool in_complex = c3t3.is_in_complex(*eit); + //if ( toRemesh == REMESH_ALL + // || (toRemesh == REMESH_IN_COMPLEX && in_complex) + // || (toRemesh == REMESH_IMAGINARY && !in_complex)) + { + const Vertex_handle vh0 = eit->first->vertex(eit->second); + const Vertex_handle vh1 = eit->first->vertex(eit->third); + + const std::size_t& i0 = vertex_id.at(vh0); + const std::size_t& i1 = vertex_id.at(vh1); + + if (c3t3.in_dimension(vh0) == 3 && !is_on_convex_hull(vh0, c3t3)) + { + const Point_3& p1 = point(vh1->point()); + smoothing_vecs[i0] = smoothing_vecs[i0] + Vector_3(CGAL::ORIGIN, p1); + neighbors[i0]++; + } + if (c3t3.in_dimension(vh1) == 3 && !is_on_convex_hull(vh1, c3t3)) + { + const Point_3& p0 = point(vh0->point()); + smoothing_vecs[i1] = smoothing_vecs[i1] + Vector_3(CGAL::ORIGIN, p0); + neighbors[i1]++; + } + } + } + + for (Finite_vertices_iterator vit = tr.finite_vertices_begin(); + vit != tr.finite_vertices_end(); ++vit) + { + const std::size_t& vid = vertex_id.at(vit); + if (neighbors[vid] > 1) + { + if (smoothing_vecs[vid] != CGAL::NULL_VECTOR) + { +#ifdef CGAL_TETRAHEDRAL_REMESHING_VERBOSE + ++nb_done; +#endif + Point_3 new_pos = CGAL::ORIGIN + smoothing_vecs[vid] / neighbors[vid]; + const Vector_3 move(point(vit->point()), new_pos); + + std::vector cells; + tr.finite_incident_cells(vit, std::back_inserter(cells)); + + bool selected = true; + for (std::size_t i = 0; i < cells.size(); ++i) + { + if (!cell_selector(cells[i])) + { + selected = false; + break; + } + } + if (!selected) + continue; + + double frac = 1.; + while (frac > 0.05 /// 1/16 = 0.0625 + && !check_inversion_and_move(vit, frac * move, cells, tr)) + { + frac = 0.5 * frac; + } + } + } + } + +#ifdef CGAL_TETRAHEDRAL_REMESHING_VERBOSE + std::cout << " done (" << nb_done << " vertices smoothed)." << std::endl; +#endif + } + + }//namespace internal + }//namespace Tetrahedral_adaptive_remeshing }//namespace CGAL #endif //CGAL_INTERNAL_SMOOTH_VERTICES_H diff --git a/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/tetrahedral_adaptive_remeshing_impl.h b/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/tetrahedral_adaptive_remeshing_impl.h index d4aa4fc2a0c..69475d65b26 100644 --- a/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/tetrahedral_adaptive_remeshing_impl.h +++ b/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/tetrahedral_adaptive_remeshing_impl.h @@ -223,8 +223,7 @@ namespace internal void smooth() { - smooth_vertices_new(m_c3t3, -1, m_protect_boundaries, - m_cell_selector); + smooth_vertices(m_c3t3, m_protect_boundaries, m_cell_selector); CGAL_assertion(tr().tds().is_valid(true)); #ifdef CGAL_DUMP_REMESHING_STEPS @@ -510,7 +509,7 @@ private: collapse(); } flip(); -// smooth(); + smooth(); #ifdef CGAL_TETRAHEDRAL_REMESHING_VERBOSE std::cout << "# Iteration " << it_nb << " done : " @@ -530,7 +529,7 @@ private: ++it_nb; flip(); - // smooth(); + smooth(); #ifdef CGAL_TETRAHEDRAL_REMESHING_VERBOSE std::cout << "# Iteration " << it_nb << " (flip and smooth only) done : " From bb76c17ae566dad11a26a7931a3357693ff31eda Mon Sep 17 00:00:00 2001 From: Jane Tournois Date: Fri, 14 Feb 2020 17:02:59 +0100 Subject: [PATCH 111/568] use FMLS in smoothing, and revert to an older version fix compilation with c3t3 this version is buggy and produces nan, I don't know why yet so smoothing is commented out --- .../Tetrahedral_remeshing/internal/FMLS.h | 263 ++++++++++++ .../internal/smooth_vertices.h | 406 +++++++++--------- .../tetrahedral_adaptive_remeshing_impl.h | 4 +- .../internal/tetrahedral_remeshing_helpers.h | 36 +- 4 files changed, 501 insertions(+), 208 deletions(-) diff --git a/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/FMLS.h b/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/FMLS.h index 8938949b2a1..2dc1856c19a 100644 --- a/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/FMLS.h +++ b/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/FMLS.h @@ -24,10 +24,15 @@ #include #include +#include +#include + +#include #include "Vec3D.h" + namespace CGAL { namespace Tetrahedral_remeshing @@ -580,6 +585,264 @@ namespace CGAL Grid grid; }; + + template + void createMLSSurfaces(Subdomain__FMLS& subdomain_FMLS, + Subdomain__FMLS_indices& subdomain_FMLS_indices, + VerticesNormalsMap& vertices_normals, + const C3t3& c3t3, + int upsample = 0) + { +// upsample = 0; + typedef typename C3t3::Surface_patch_index Surface_index; + typedef typename C3t3::Subdomain_index Subdomain_index; + typedef typename C3t3::Triangulation Tr; + typedef typename Tr::Edge Edge; + typedef typename Tr::Vertex_handle Vertex_handle; + typedef typename Tr::Geom_traits Gt; + typedef typename Gt::Point_3 Point_3; + typedef typename Gt::Vector_3 Vector_3; + + const Tr& tr = c3t3.triangulation(); + + //createAreaWeightedUpSampledMLSSurfaces(0); + //return ; + subdomain_FMLS.clear(); + subdomain_FMLS_indices.clear(); + + typedef boost::unordered_map SurfaceIndexMap; + + SurfaceIndexMap current_subdomain_FMLS_indices; + SurfaceIndexMap subdomain_sample_numbers; + + //Count the number of vertices for each boundary surface (i.e. one per label) + for (typename Tr::Finite_vertices_iterator vit = tr.finite_vertices_begin(); + vit != tr.finite_vertices_end(); ++vit) + { + if (vit->in_dimension() == 2) + { + const Surface_index si = surface_patch_index(vit, c3t3); + subdomain_sample_numbers[si]++; + } + } + + //if (upsample > 0) { + // std::cout << "Up sampling MLS " << upsample << std::endl; + // for (C3t3_with_info::Facet_iterator fit = c3t3_with_info.facets_begin(); fit != c3t3_with_info.facets_end(); ++fit) { + // Surface_index surf_i = triangulated_domain.make_surface_index(fit->first->subdomain_index(), + // fit->first->neighbor(fit->second)->subdomain_index()); + // if (upsample == 1) + // subdomain_sample_numbers[surf_i] ++; + // else if (upsample == 2) + // subdomain_sample_numbers[surf_i] += 4; + // } + //} + + std::vector< float* > pns; + + int count = 0; + //Memory allocation for the point plus normals of the point samples + for (typename SurfaceIndexMap::iterator it = subdomain_sample_numbers.begin(); + it != subdomain_sample_numbers.end(); ++it) + { + current_subdomain_FMLS_indices[it->first] = count; + pns.push_back(new float[it->second * 6]); + count++; + } + + std::vector current_v_count(count, 0); + std::vector point_spacing(count, 0); + std::vector point_spacing_count(count, 0); + + //Allocation of the PN + for (typename Tr::Finite_vertices_iterator vit = tr.finite_vertices_begin(); + vit != tr.finite_vertices_end(); ++vit) + { + if (vit->in_dimension() == 2) + { + const Surface_index surf_i = surface_patch_index(vit, c3t3); + + int fmls_id = current_subdomain_FMLS_indices[surf_i]; + + const Point_3& p = point(vit->point()); + + pns[fmls_id][6 * current_v_count[fmls_id]] = p.x(); + pns[fmls_id][6 * current_v_count[fmls_id] + 1] = p.y(); + pns[fmls_id][6 * current_v_count[fmls_id] + 2] = p.z(); + + const Vector_3& normal = vertices_normals[vit][surf_i]; + + pns[fmls_id][6 * current_v_count[fmls_id] + 3] = normal.x(); + pns[fmls_id][6 * current_v_count[fmls_id] + 4] = normal.y(); + pns[fmls_id][6 * current_v_count[fmls_id] + 5] = normal.z(); + + current_v_count[fmls_id]++; + } + } + + typedef std::pair Edge_vv; + typedef boost::unordered_map EdgeMapIndex; + if (upsample == 0) + { + EdgeMapIndex edgeMap; + + for (typename C3t3::Facets_in_complex_iterator fit = c3t3.facets_in_complex_begin(); + fit != c3t3.facets_in_complex_end(); ++fit) + { + for (int i = 0; i < 2; i++) + { + for (int j = i + 1; j < 3; j++) + { + Edge edge(fit->first, indices(fit->second,i), indices(fit->second,j)); + + Vertex_handle vh0 = edge.first->vertex(edge.second); + Vertex_handle vh1 = edge.first->vertex(edge.third); + Edge_vv e = make_vertex_pair(vh0, vh1); + if ( vh0->in_dimension() == 2 + && vh1->in_dimension() == 2 + && edgeMap.find(e) == edgeMap.end()) + { + edgeMap[e] = 0; + Surface_index surf_i = c3t3.surface_patch_index(*fit); + int fmls_id = current_subdomain_FMLS_indices[surf_i]; + + point_spacing[fmls_id] += CGAL::approximate_sqrt( + CGAL::squared_distance(point(vh0->point()), point(vh1->point()))); + point_spacing_count[fmls_id] ++; + } + } + } + } + } + +// if (upsample > 0) { +// +// for (C3t3_with_info::Facet_iterator fit = c3t3_with_info.facets_begin(); fit != c3t3_with_info.facets_end(); ++fit) { +// +// Surface_index surf_i = triangulated_domain.make_surface_index(fit->first->subdomain_index(), +// fit->first->neighbor(fit->second)->subdomain_index()); +// +// int fmls_id = current_subdomain_FMLS_indices[surf_i]; +// +// Vertex_handle vhs[3] = { fit->first->vertex(indices[fit->second][0]), +// fit->first->vertex(indices[fit->second][1]), +// fit->first->vertex(indices[fit->second][2]) }; +// K::Vector_3 points[3] = { PointToVector(vhs[0]->point()), PointToVector(vhs[1]->point()), PointToVector(vhs[2]->point()) }; +// K::Vector_3 normals[3] = { vertices_normals[vhs[0]->info()][surf_i], vertices_normals[vhs[1]->info()][surf_i], vertices_normals[vhs[2]->info()][surf_i] }; +// +// std::vector points_to_add; +// std::vector n_points_to_add; +// +// //Add the barycenter of the facet +// K::Vector_3 barycenter = (points[0] + points[1] + points[2]) / 3.; +// K::Vector_3 n_barycenter = (normals[0] + normals[1] + normals[2]); +// +// barycenter = (points[0] + points[1] + points[2]) / 3.; +// n_barycenter = (normals[0] + normals[1] + normals[2]); +// +// n_barycenter = n_barycenter / CGAL::sqrt((n_barycenter * n_barycenter)); +// +// points_to_add.push_back(barycenter); +// n_points_to_add.push_back(n_barycenter); +// +// if (upsample == 1) { +// for (int i = 0; i < 3; i++) { +// K::Vector_3 space_1 = barycenter - points[i]; +// +// point_spacing[fmls_id] += CGAL::to_double(CGAL::sqrt(space_1 * space_1)); +// point_spacing_count[fmls_id] ++; +// } +// } +// else if (upsample == 2) { +// for (int i = 0; i < 3; i++) { +// +// int i1 = (i + 1) % 3; +// int i2 = (i + 2) % 3; +// +// K::Vector_3 p = (barycenter + points[i1] + points[i2]) / 3.; +// K::Vector_3 n = (n_barycenter + normals[i1] + normals[i2]); +// +// n = n / CGAL::sqrt(n * n); +// +// points_to_add.push_back(p); +// n_points_to_add.push_back(n); +// +// K::Vector_3 space_1 = p - barycenter; +// K::Vector_3 space_2 = p - points[i1]; +// K::Vector_3 space_3 = p - points[i2]; +// +// point_spacing[fmls_id] += CGAL::to_double(CGAL::sqrt(space_1 * space_1)); +// point_spacing[fmls_id] += CGAL::to_double(CGAL::sqrt(space_2 * space_2)); +// point_spacing[fmls_id] += CGAL::to_double(CGAL::sqrt(space_3 * space_3)); +// +// point_spacing_count[fmls_id] += 3; +// } +// } +// for (unsigned int i = 0; i < points_to_add.size(); i++) { +// K::Vector_3& point = points_to_add[i]; +// +// pns[fmls_id][6 * current_v_count[fmls_id]] = point.x(); +// pns[fmls_id][6 * current_v_count[fmls_id] + 1] = point.y(); +// pns[fmls_id][6 * current_v_count[fmls_id] + 2] = point.z(); +// +// K::Vector_3& normal = n_points_to_add[i]; +// +// pns[fmls_id][6 * current_v_count[fmls_id] + 3] = normal.x(); +// pns[fmls_id][6 * current_v_count[fmls_id] + 4] = normal.y(); +// pns[fmls_id][6 * current_v_count[fmls_id] + 5] = normal.z(); +// +// current_v_count[fmls_id]++; +// } +// } +// } + + + int nb_of_mls_to_create = 0; + double average_point_spacing = 0; + + //Cretaing the actual MLS surfaces + for (typename SurfaceIndexMap::iterator it = current_subdomain_FMLS_indices.begin(); + it != current_subdomain_FMLS_indices.end(); ++it) + { + if (current_v_count[it->second] > 3) + { + nb_of_mls_to_create++; + + double current_point_spacing = point_spacing[it->second] / point_spacing_count[it->second]; + point_spacing[it->second] = current_point_spacing; + + average_point_spacing += current_point_spacing; + } + } + + average_point_spacing = average_point_spacing / nb_of_mls_to_create; + + subdomain_FMLS.resize(nb_of_mls_to_create, FMLS()); + + count = 0; + //Cretaing the actual MLS surfaces + for (typename SurfaceIndexMap::iterator it = current_subdomain_FMLS_indices.begin(); + it != current_subdomain_FMLS_indices.end(); ++it) + { + if (current_v_count[it->second] > 3) + { + double current_point_spacing = point_spacing[it->second]; + + //subdomain_FMLS[count].toggleHermite(true); + subdomain_FMLS[count].setPN(pns[it->second], current_v_count[it->second], current_point_spacing); + // subdomain_FMLS[count].toggleHermite(true); + subdomain_FMLS_indices[it->first] = count; + + count++; + } + else { + std::cout << "Problem of number for MLS : " << current_v_count[it->second] << std::endl; + } + } + } } } } diff --git a/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/smooth_vertices.h b/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/smooth_vertices.h index a902ac35a98..660daaf15bd 100644 --- a/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/smooth_vertices.h +++ b/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/smooth_vertices.h @@ -7,6 +7,7 @@ #include #include +#include #include @@ -21,8 +22,8 @@ namespace CGAL { template CGAL::Vector_3 project_on_tangent_plane(const CGAL::Point_3& gi, - const CGAL::Point_3& pi, - const CGAL::Vector_3& normal) + const CGAL::Point_3& pi, + const CGAL::Vector_3& normal) { typedef typename Gt::Vector_3 Vector_3; Vector_3 diff = pi - gi; @@ -31,7 +32,7 @@ namespace CGAL template void compute_vertices_normals(const C3t3& c3t3, - VertexNormalsMap& normals_map) + VertexNormalsMap& normals_map) { typedef typename C3t3::Triangulation Tr; typedef typename C3t3::Cell_handle Cell_handle; @@ -39,25 +40,26 @@ namespace CGAL typedef typename C3t3::Subdomain_index Subdomain_index; typedef typename C3t3::Surface_patch_index Surface_patch_index; typedef typename Tr::Finite_facets_iterator Finite_facets_iterator; - typedef typename Tr::Gt::Vector_3 Vector_3; + typedef typename Tr::Facet Facet; + typedef typename Tr::Geom_traits::Vector_3 Vector_3; + + typename Tr::Geom_traits::Construct_opposite_vector_3 + opp = c3t3.triangulation().geom_traits().construct_opposite_vector_3_object(); + typename Tr::Geom_traits::Construct_scaled_vector_3 + scale = c3t3.triangulation().geom_traits().construct_scaled_vector_3_object(); const Tr& tr = c3t3.triangulation(); for (Finite_facets_iterator fit = tr.finite_facets_begin(); fit != tr.finite_facets_end(); ++fit) { - Cell_handle ch = fit->first; - Cell_handle n_ch = fit->first->neighbor(fit->second); - - Subdomain_index si = ch->subdomain_index(); - Subdomain_index si_mirror = n_ch->subdomain_index(); - - if (c3t3.is_in_complex(fit)) + const Facet& f = *fit; + if (c3t3.is_in_complex(f)) { - Surface_patch_index surf_i = c3t3.surface_patch_index(fit); + Surface_patch_index surf_i = c3t3.surface_patch_index(f); for (int i = 0; i < 3; ++i) { - Vertex_handle v_id = fit->first->vertex(indices(fit->second, i)); + Vertex_handle v_id = f.first->vertex(indices(f.second, i)); normals_map[v_id][surf_i] = CGAL::NULL_VECTOR; } } @@ -66,24 +68,26 @@ namespace CGAL for (Finite_facets_iterator fit = tr.finite_facets_begin(); fit != tr.finite_facets_end(); ++fit) { - Cell_handle ch = fit->first; - Cell_handle n_ch = fit->first->neighbor(fit->second); + const Facet& f = *fit; + + Cell_handle ch = f.first; + Cell_handle n_ch = f.first->neighbor(f.second); Subdomain_index si = ch->subdomain_index(); Subdomain_index si_mirror = n_ch->subdomain_index(); - if (c3t3.is_in_complex(fit)) + if (c3t3.is_in_complex(f)) { - Surface_patch_index surf_i = c3t3.surface_patch_index(fit); + Surface_patch_index surf_i = c3t3.surface_patch_index(f); - Vector_3 n = CGAL::normal(*fit, tr.geom_traits()); + Vector_3 n = CGAL::Tetrahedral_remeshing::normal(f, tr.geom_traits()); - if (si < si_mirror || tr.is_infinite(ch)) - n = -1. * n; + if (si < si_mirror || tr.is_infinite(ch)) // todo : fix this condition + n = opp(n); for (int i = 0; i < 3; ++i) { - Vector_3& v_n = normals_map[fit->first->vertex(indices(fit->second, i))][surf_i]; + Vector_3& v_n = normals_map[f.first->vertex(indices(f.second, i))][surf_i]; v_n = v_n + n; } } @@ -91,26 +95,32 @@ namespace CGAL //normalize the computed normals for (typename VertexNormalsMap::iterator vnm_it = normals_map.begin(); - vnm_it != normals_map.end(); ++vnm_it) + vnm_it != normals_map.end(); ++vnm_it) { //value type is map - for (typename VertexNormalsMap::value_type::iterator it = vnm_it->begin(); - it != vnm_it->end(); ++it) + for (typename VertexNormalsMap::mapped_type::iterator it = vnm_it->second.begin(); + it != vnm_it->second.end(); ++it) { Vector_3& n = it->second; - n = n / CGAL::sqrt(n * n); + n = scale(n, 1. / CGAL::approximate_sqrt(n * n)); } } } - template - bool project(const SurfacePatchIndex& /* si */, - CGAL::Vector_3& gi, - CGAL::Vector_3& projected_point) + template + bool project(const SurfacePatchIndex& si, + const CGAL::Vector_3& gi, + CGAL::Vector_3& projected_point, + Subdomain__FMLS& subdomain_FMLS, + Subdomain__FMLS_indices& subdomain_FMLS_indices) { - // if (subdomain_FMLS_indices.find(si) == subdomain_FMLS_indices.end()) - // return false; + if (subdomain_FMLS_indices.find(si) == subdomain_FMLS_indices.end()) + return false; + typedef typename Gt::Vector_3 Vector_3; typedef typename Gt::Point_3 Point_3; @@ -124,25 +134,25 @@ namespace CGAL Point_3 point; Point_3 result = CGAL::ORIGIN + gi; - //FMLS& fmls = subdomain_FMLS[subdomain_FMLS_indices[si]]; + CGAL::Tetrahedral_remeshing::internal::FMLS& fmls = subdomain_FMLS[subdomain_FMLS_indices[si]]; - // int it_nb = 0; - // const int max_it_nb = 5; - //const float epsilon = fmls.getPNScale() / 1000.; + int it_nb = 0; + const int max_it_nb = 5; + const float epsilon = fmls.getPNScale() / 1000.; + const float sq_eps = CGAL::square(epsilon); - //do - //{ - // point = result; + do + { + point = result; - // //fmls.fastProjectionCPU(point, result, res_normal); + fmls.fastProjectionCPU(point, result, res_normal); - // if (std::isnan(result[0]) || std::isnan(result[1]) || std::isnan(result[2])){ - // std::cout << "MLS error detected si size " << si.first << " - " << si.second - // << " : " << fmls.getPNSize() << std::endl; - // return false; - // } - - //} while ((result - point).getLength() > epsilon && ++it_nb < max_it_nb); + if (std::isnan(result[0]) || std::isnan(result[1]) || std::isnan(result[2])){ + std::cout << "MLS error detected si size " << si + << " : " << fmls.getPNSize() << std::endl; + return false; + } + } while (CGAL::squared_distance(result, point) > sq_eps && ++it_nb < max_it_nb); projected_point = Vector_3(result.x(), result.y(), result.z()); @@ -275,113 +285,110 @@ namespace CGAL return CGAL::NULL_VECTOR; } - template - void smooth_vertices_new(C3T3& c3t3, - const typename C3T3::Subdomain_index& imaginary_index, - const bool /*protect_boundaries*/, - CellSelector cell_selector) - { - typedef typename C3T3::Triangulation Tr; - typedef typename C3T3::Vertex_handle Vertex_handle; - typedef typename C3T3::Cell_handle Cell_handle; - typedef typename Tr::Finite_vertices_iterator Finite_vertices_iterator; - - typedef typename Tr::Geom_traits Gt; - typedef typename Gt::Point_3 Point_3; - typedef typename Gt::Vector_3 Vector_3; - -#ifdef CGAL_TETRAHEDRAL_REMESHING_VERBOSE - std::cout << "Smooth vertices..."; - std::cout.flush(); - std::size_t nb_done = 0; CGAL_USE(nb_done); -#endif - - Tr& tr = c3t3.triangulation(); - -#ifdef CGAL_TETRAHEDRAL_REMESHING_DEBUG - CGAL::debug::dump_vertices_by_dimension(c3t3.triangulation(), "c3t3_vertices_before_smoothing"); -#endif - - const std::size_t nbv = tr.number_of_vertices(); - boost::unordered_map vertex_id; - std::vector smoothing_vecs(nbv, CGAL::NULL_VECTOR); - // std::vector neighbors(nbv, -1); - - // generate ids for vertices - std::size_t id = 0; - for (Finite_vertices_iterator vit = tr.finite_vertices_begin(); - vit != tr.finite_vertices_end(); ++vit) - { - vertex_id[vit] = id++; - } - -#ifdef CGAL_TETRAHEDRAL_REMESHING_DEBUG - std::ofstream ofs_2d("moves_on_surface.polylines.txt"); - std::ofstream ofs_1d("moves_on_features.polylines.txt"); -#endif - - // compute move depending on underlying dimension - for (Finite_vertices_iterator vit = tr.finite_vertices_begin(); - vit != tr.finite_vertices_end(); ++vit) - { - switch (vit->in_dimension()) - { - case 3: - if (is_imaginary(vit, c3t3, imaginary_index) || !is_selected(vit, c3t3, cell_selector)) - break; - else - smoothing_vecs[vertex_id.at(vit)] = move_3d(vit, c3t3); - break; - - case 2: - smoothing_vecs[vertex_id.at(vit)] = move_2d(vit, c3t3, imaginary_index); -#ifdef CGAL_TETRAHEDRAL_REMESHING_DEBUG - if (smoothing_vecs[vertex_id.at(vit)] != CGAL::NULL_VECTOR) - ofs_2d << "2 " << vit->point() - << " " << (CGAL::ORIGIN + smoothing_vecs[vertex_id.at(vit)]) << std::endl; -#endif - break; - - case 1: - smoothing_vecs[vertex_id.at(vit)] = move_1d(vit, c3t3, imaginary_index); -#ifdef CGAL_TETRAHEDRAL_REMESHING_DEBUG - if (smoothing_vecs[vertex_id.at(vit)] != CGAL::NULL_VECTOR) - ofs_1d << "2 " << vit->point() - << " " << (CGAL::ORIGIN + smoothing_vecs[vertex_id.at(vit)]) << std::endl; -#endif - - default: - break; - } - } -#ifdef CGAL_TETRAHEDRAL_REMESHING_DEBUG - ofs_2d.close(); - ofs_1d.close(); -#endif - - // apply moves - for (Finite_vertices_iterator vit = tr.finite_vertices_begin(); - vit != tr.finite_vertices_end(); ++vit) - { - const std::size_t& vid = vertex_id.at(vit); - Point_3 new_pos = CGAL::ORIGIN + smoothing_vecs[vid]; - const Vector_3 move(vit->point(), new_pos); - - std::vector cells; - tr.finite_incident_cells(vit, std::back_inserter(cells)); - - double frac = 1.; - while (frac > 0.05 /// 1/16 = 0.0625 - && !check_inversion_and_move(vit, frac * move, cells)) - { - frac = 0.5 * frac; - } - } - -#ifdef CGAL_TETRAHEDRAL_REMESHING_DEBUG - CGAL::debug::dump_vertices_by_dimension(c3t3.triangulation(), "c3t3_vertices_after_smoothing"); -#endif - } +// template +// void smooth_vertices_new(C3T3& c3t3, +// const typename C3T3::Subdomain_index& imaginary_index, +// const bool /*protect_boundaries*/, +// CellSelector cell_selector) +// { +// typedef typename C3T3::Triangulation Tr; +// typedef typename C3T3::Vertex_handle Vertex_handle; +// typedef typename C3T3::Cell_handle Cell_handle; +// typedef typename Tr::Finite_vertices_iterator Finite_vertices_iterator; +// +// typedef typename Tr::Geom_traits Gt; +// typedef typename Gt::Point_3 Point_3; +// typedef typename Gt::Vector_3 Vector_3; +// +//#ifdef CGAL_TETRAHEDRAL_REMESHING_VERBOSE +// std::cout << "Smooth vertices..."; +// std::cout.flush(); +// std::size_t nb_done = 0; CGAL_USE(nb_done); +//#endif +// +// Tr& tr = c3t3.triangulation(); +// +//#ifdef CGAL_TETRAHEDRAL_REMESHING_DEBUG +// CGAL::debug::dump_vertices_by_dimension(c3t3.triangulation(), "c3t3_vertices_before_smoothing"); +//#endif +// +// const std::size_t nbv = tr.number_of_vertices(); +// boost::unordered_map vertex_id; +// std::vector smoothing_vecs(nbv, CGAL::NULL_VECTOR); +// // std::vector neighbors(nbv, -1); +// +// // generate ids for vertices +// std::size_t id = 0; +// for (Finite_vertices_iterator vit = tr.finite_vertices_begin(); +// vit != tr.finite_vertices_end(); ++vit) +// { +// vertex_id[vit] = id++; +// } +// +//#ifdef CGAL_TETRAHEDRAL_REMESHING_DEBUG +// std::ofstream ofs_2d("moves_on_surface.polylines.txt"); +// std::ofstream ofs_1d("moves_on_features.polylines.txt"); +//#endif +// +// // compute move depending on underlying dimension +// for (Finite_vertices_iterator vit = tr.finite_vertices_begin(); +// vit != tr.finite_vertices_end(); ++vit) +// { +// switch (vit->in_dimension()) +// { +// case 3: +// if (is_imaginary(vit, c3t3, imaginary_index) || !is_selected(vit, c3t3, cell_selector)) +// break; +// else +// smoothing_vecs[vertex_id.at(vit)] = move_3d(vit, c3t3); +// break; +// +// case 2: +// smoothing_vecs[vertex_id.at(vit)] = move_2d(vit, c3t3, imaginary_index); +//#ifdef CGAL_TETRAHEDRAL_REMESHING_DEBUG +// if (smoothing_vecs[vertex_id.at(vit)] != CGAL::NULL_VECTOR) +// ofs_2d << "2 " << vit->point() +// << " " << (CGAL::ORIGIN + smoothing_vecs[vertex_id.at(vit)]) << std::endl; +//#endif +// break; +// +// case 1: +// smoothing_vecs[vertex_id.at(vit)] = move_1d(vit, c3t3, imaginary_index); +//#ifdef CGAL_TETRAHEDRAL_REMESHING_DEBUG +// if (smoothing_vecs[vertex_id.at(vit)] != CGAL::NULL_VECTOR) +// ofs_1d << "2 " << vit->point() +// << " " << (CGAL::ORIGIN + smoothing_vecs[vertex_id.at(vit)]) << std::endl; +//#endif +// +// default: +// break; +// } +// } +//#ifdef CGAL_TETRAHEDRAL_REMESHING_DEBUG +// ofs_2d.close(); +// ofs_1d.close(); +//#endif +// +// // apply moves +// for (Finite_vertices_iterator vit = tr.finite_vertices_begin(); +// vit != tr.finite_vertices_end(); ++vit) +// { +// const std::size_t& vid = vertex_id.at(vit); +// Point_3 new_pos = CGAL::ORIGIN + smoothing_vecs[vid]; +// const Vector_3 move(vit->point(), new_pos); +// +// std::vector cells; +// tr.finite_incident_cells(vit, std::back_inserter(cells)); +// +// double frac = 1.; +// while (frac > 0.05 /// 1/16 = 0.0625 +// && !check_inversion_and_move(vit, frac * move, cells)) +// { +// frac = 0.5 * frac; +// } +// } +// +// } template void smooth_vertices(C3T3& c3t3, @@ -434,12 +441,12 @@ namespace CGAL const std::size_t& i0 = vertex_id.at(vh0); const std::size_t& i1 = vertex_id.at(vh1); - if (/*toRemesh != REMESH_IMAGINARY &&*/ c3t3.is_in_complex(*eit)) + if (c3t3.is_in_complex(*eit)) { if (!is_feature(vh0, c3t3)) - neighbors[i0] = std::max(0, neighbors[i0]); + neighbors[i0] = (std::max)(0, neighbors[i0]); if (!is_feature(vh1, c3t3)) - neighbors[i1] = std::max(0, neighbors[i1]); + neighbors[i1] = (std::max)(0, neighbors[i1]); bool update_v0 = false, update_v1 = false; @@ -464,11 +471,10 @@ namespace CGAL for (typename C3T3::Cell_iterator cit = c3t3.cells_in_complex_begin(); cit != c3t3.cells_in_complex_end(); ++cit) { + const Subdomain_index si = cit->subdomain_index(); for (int i = 0; i < 4; ++i) { - Vertex_handle vi = cit->vertex(i); - Subdomain_index si = cit->subdomain_index(); - + const Vertex_handle vi = cit->vertex(i); if (vertices_subdomain_indices.find(vi) == vertices_subdomain_indices.end()) { std::vector indices(1); @@ -489,11 +495,11 @@ namespace CGAL for (typename C3T3::Facet_iterator fit = c3t3.facets_in_complex_begin(); fit != c3t3.facets_in_complex_end(); ++fit) { - const Facet f = *fit; + const Facet& f = *fit; Surface_patch_index surface_index = c3t3.surface_patch_index(f); for (int i = 0; i < 3; ++i) { - Vertex_handle vi = fit->first->vertex(indices(f.second, i)); + const Vertex_handle vi = f.first->vertex(indices(f.second, i)); if (vertices_subdomain_indices.at(vi).size() > 2) { if (vertices_surface_indices.find(vi) == vertices_surface_indices.end()) @@ -506,7 +512,7 @@ namespace CGAL { std::vector& v_surface_indices = vertices_surface_indices.at(vi); if (std::find(v_surface_indices.begin(), v_surface_indices.end(), surface_index) - == v_surface_indices.end()) + == v_surface_indices.end()) v_surface_indices.push_back(surface_index); } } @@ -516,15 +522,26 @@ namespace CGAL //collect a map of normals at surface vertices boost::unordered_map > vertices_normals; + compute_vertices_normals(c3t3, vertices_normals); + + // Build MLS Surfaces + std::vector < CGAL::Tetrahedral_remeshing::internal::FMLS > subdomain_FMLS; + boost::unordered_map subdomain_FMLS_indices; + createMLSSurfaces(subdomain_FMLS, + subdomain_FMLS_indices, + vertices_normals, + c3t3); + + // Smooth for (Finite_vertices_iterator vit = tr.finite_vertices_begin(); - vit != tr.finite_vertices_end(); ++vit) + vit != tr.finite_vertices_end(); ++vit) { const std::size_t& vid = vertex_id.at(vit); if (neighbors[vid] > 1) { Point_3 smoothed_position = CGAL::ORIGIN + smoothing_vecs[vid] / neighbors[vid]; Vector_3 final_move = CGAL::NULL_VECTOR; - Point_3 final_position; + Point_3 final_position = CGAL::ORIGIN; std::size_t count = 0; const Point_3 current_pos = point(vit->point()); @@ -539,7 +556,7 @@ namespace CGAL //Check if the mls surface exists to avoid degenrated cases Vector_3 mls_projection; - if (project(si, normal_projection, mls_projection)) { + if (project(si, normal_projection, mls_projection, subdomain_FMLS, subdomain_FMLS_indices)) { final_move = final_move + mls_projection; } else { @@ -572,7 +589,7 @@ namespace CGAL //Check if the mls surface exists to avoid degenrated cases Vector_3 mls_projection; - if (project(si, current_move, mls_projection)) { + if (project(si, current_move, mls_projection, subdomain_FMLS, subdomain_FMLS_indices)) { final_move = final_move + mls_projection; } else { @@ -648,27 +665,21 @@ namespace CGAL final_position = CGAL::ORIGIN + final_move; } else { - // Surface_patch_index si = helpers::make_surface_patch_index( - // vertices_subdomain_indices[vit][0], vertices_subdomain_indices[vit][1]); + const Surface_patch_index si = surface_patch_index(vit, c3t3); - // Vector_3 normal_projection = project_on_tangent_plane(smoothed_position, - // current_pos, - // vertices_normals[vit][si]); - //Vector_3 mls_projection; - //if (project(si, normal_projection, mls_projection) /*|| project( si, smoothed_position, mls_projection )*/){ - // final_position = mls_projection; - // //final_position = smoothed_position; - //} - //else { - final_position = smoothed_position; - //} + Vector_3 normal_projection = project_on_tangent_plane(smoothed_position, + current_pos, + vertices_normals[vit][si]); + Vector_3 mls_projection; + if (project(si, normal_projection, mls_projection, subdomain_FMLS, subdomain_FMLS_indices) + /*|| project( si, smoothed_position, mls_projection )*/){ + final_position = CGAL::ORIGIN + mls_projection; + } + else { + final_position = smoothed_position; + } // std::cout << "MLS " << final_position[0] << " - " << final_position[1] << " : " << final_position[2] << std::endl; } - /* - Normal_iterator it = vertices_normals[vit->info()].end(); - it--; - final_position = final_position + projectOnTangentPlane( smoothed_position, current_pos , it->second ); - */ vit->set_point(typename Tr::Point(final_position)); } @@ -676,15 +687,16 @@ namespace CGAL { if (vit->in_dimension() == 2) { - // Surface_patch_index si = helpers::make_surface_patch_index( - // vertices_subdomain_indices[vit][0], - // vertices_subdomain_indices[vit][1]); + const Surface_patch_index si = surface_patch_index(vit, c3t3); - Vector_3 current_pos(CGAL::ORIGIN, point(vit->point())); + const Vector_3 current_pos(CGAL::ORIGIN, point(vit->point())); Vector_3 mls_projection; - // if (project(si, current_pos, mls_projection) /*|| project( si, smoothed_position, mls_projection )*/){ - // vit->set_point(Point_3(mls_projection.x(), mls_projection.y(), mls_projection.z())); - // } + if (project(si, current_pos, mls_projection, subdomain_FMLS, subdomain_FMLS_indices) + /*|| project( si, smoothed_position, mls_projection )*/) + { + const typename Tr::Point new_pos(CGAL::ORIGIN + mls_projection); + vit->set_point(new_pos); + } } } } @@ -698,10 +710,7 @@ namespace CGAL for (Finite_edges_iterator eit = tr.finite_edges_begin(); eit != tr.finite_edges_end(); ++eit) { - //bool in_complex = c3t3.is_in_complex(*eit); - //if ( toRemesh == REMESH_ALL - // || (toRemesh == REMESH_IN_COMPLEX && in_complex) - // || (toRemesh == REMESH_IMAGINARY && !in_complex)) + if ( !is_outside(*eit, c3t3, cell_selector)) { const Vertex_handle vh0 = eit->first->vertex(eit->second); const Vertex_handle vh1 = eit->first->vertex(eit->third); @@ -742,9 +751,9 @@ namespace CGAL tr.finite_incident_cells(vit, std::back_inserter(cells)); bool selected = true; - for (std::size_t i = 0; i < cells.size(); ++i) + for (const Cell_handle ci : cells) { - if (!cell_selector(cells[i])) + if (!cell_selector(ci)) { selected = false; break; @@ -765,6 +774,9 @@ namespace CGAL #ifdef CGAL_TETRAHEDRAL_REMESHING_VERBOSE std::cout << " done (" << nb_done << " vertices smoothed)." << std::endl; +#endif +#ifdef CGAL_TETRAHEDRAL_REMESHING_DEBUG + CGAL::debug::dump_vertices_by_dimension(c3t3.triangulation(), "c3t3_vertices_after_smoothing"); #endif } diff --git a/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/tetrahedral_adaptive_remeshing_impl.h b/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/tetrahedral_adaptive_remeshing_impl.h index 69475d65b26..9110596fe71 100644 --- a/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/tetrahedral_adaptive_remeshing_impl.h +++ b/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/tetrahedral_adaptive_remeshing_impl.h @@ -509,7 +509,7 @@ private: collapse(); } flip(); - smooth(); +// smooth(); #ifdef CGAL_TETRAHEDRAL_REMESHING_VERBOSE std::cout << "# Iteration " << it_nb << " done : " @@ -529,7 +529,7 @@ private: ++it_nb; flip(); - smooth(); +// smooth(); #ifdef CGAL_TETRAHEDRAL_REMESHING_VERBOSE std::cout << "# Iteration " << it_nb << " (flip and smooth only) done : " diff --git a/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/tetrahedral_remeshing_helpers.h b/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/tetrahedral_remeshing_helpers.h index c676bfd3f05..0791098e531 100644 --- a/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/tetrahedral_remeshing_helpers.h +++ b/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/tetrahedral_remeshing_helpers.h @@ -271,7 +271,7 @@ namespace Tetrahedral_remeshing std::vector facets; c3t3.triangulation().incident_facets(v, std::back_inserter(facets)); - BOOST_FOREACH(Facet f, facets) + BOOST_FOREACH(const Facet& f, facets) { if (c3t3.is_in_complex(f)) return true; @@ -281,6 +281,23 @@ namespace Tetrahedral_remeshing return false; } + template + typename C3t3::Surface_patch_index surface_patch_index(const typename C3t3::Vertex_handle v, + const C3t3& c3t3) + { + typedef typename C3t3::Surface_patch_index Surface_patch_index; + typedef typename C3t3::Facet Facet; + std::vector facets; + c3t3.triangulation().incident_facets(v, std::back_inserter(facets)); + + BOOST_FOREACH(const Facet& f, facets) + { + if (c3t3.is_in_complex(f)) + return c3t3.surface_patch_index(f); + } + return Surface_patch_index(); + } + template bool is_edge_in_complex(const typename C3t3::Vertex_handle& v0, const typename C3t3::Vertex_handle& v1, @@ -391,7 +408,11 @@ namespace Tetrahedral_remeshing { typedef typename C3t3::Edge Edge; - if (nb_incident_subdomains(v, c3t3) > 2) + if (c3t3.number_of_corners() > 0) + { + return c3t3.is_in_complex(v); + } + else if (nb_incident_subdomains(v, c3t3) > 2) { std::vector edges; c3t3.triangulation().finite_incident_edges(v, std::back_inserter(edges)); @@ -407,10 +428,6 @@ namespace Tetrahedral_remeshing } } } - else if (c3t3.number_of_corners() > 0) - { - return c3t3.is_in_complex(v); - } return false; } @@ -458,6 +475,7 @@ namespace Tetrahedral_remeshing return false; } + template bool is_outside(const typename C3t3::Edge & edge, const C3t3& c3t3, @@ -493,10 +511,10 @@ namespace Tetrahedral_remeshing BOOST_FOREACH(Cell_handle c, cells) { - if (!cell_selector(c)) - return false; + if (cell_selector(c)) + return true; } - return true; + return false; } template From 0c40f7a458e832f6ace10866cc8ef799c39028fe Mon Sep 17 00:00:00 2001 From: Laurent Rineau Date: Wed, 19 Feb 2020 16:27:10 +0100 Subject: [PATCH 112/568] "Fix" for dumb MSVC compilers https://cgal.geometryfactory.com/CGAL/testsuite/CGAL-5.1-Ic-77/Triangulation_2/TestReport_afabri_x64_Cygwin-Windows10_MSVC2015-Debug-64bits.gz My guess is that the compiler short-circuits `Const &&` when the argument `Const` is `false`, and then the expression `Const && !OtherConst` is no-longer dependent on the argument `OtherConst`. That "fix" just turn `Const && !OtherConst` to `!OtherConst && Const`. --- STL_Extension/include/CGAL/Compact_container.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/STL_Extension/include/CGAL/Compact_container.h b/STL_Extension/include/CGAL/Compact_container.h index 86dd6e45fe5..6c135a9f36f 100644 --- a/STL_Extension/include/CGAL/Compact_container.h +++ b/STL_Extension/include/CGAL/Compact_container.h @@ -886,7 +886,7 @@ namespace internal { // Converting constructor from mutable to constant iterator template CC_iterator(const CC_iterator< - typename std::enable_if<(Const && !OtherConst), DSC>::type, + typename std::enable_if<(!OtherConst && Const), DSC>::type, OtherConst> &const_it) #ifdef CGAL_COMPACT_CONTAINER_DEBUG_TIME_STAMP : ts(Time_stamper::time_stamp(const_it.operator->())) @@ -898,7 +898,7 @@ namespace internal { // Assignment operator from mutable to constant iterator template CC_iterator & operator= (const CC_iterator< - typename std::enable_if<(Const && !OtherConst), DSC>::type, + typename std::enable_if<(!OtherConst && Const), DSC>::type, OtherConst> &const_it) { m_ptr.p = const_it.operator->(); From 20910607d50406778149b815bf98b631a229f93b Mon Sep 17 00:00:00 2001 From: Laurent Rineau Date: Fri, 21 Feb 2020 14:22:44 +0100 Subject: [PATCH 113/568] std::set and std::map are not nothrow-move-constructible --- .../include/CGAL/_test_cls_const_Del_triangulation_2.h | 9 +++++++-- .../include/CGAL/_test_cls_constrained_triangulation_2.h | 9 +++++++-- 2 files changed, 14 insertions(+), 4 deletions(-) diff --git a/Triangulation_2/test/Triangulation_2/include/CGAL/_test_cls_const_Del_triangulation_2.h b/Triangulation_2/test/Triangulation_2/include/CGAL/_test_cls_const_Del_triangulation_2.h index 6581267f164..25e9cac0432 100644 --- a/Triangulation_2/test/Triangulation_2/include/CGAL/_test_cls_const_Del_triangulation_2.h +++ b/Triangulation_2/test/Triangulation_2/include/CGAL/_test_cls_const_Del_triangulation_2.h @@ -30,8 +30,13 @@ template void _test_cls_const_Del_triangulation(const Triangul&) { - static_assert(std::is_nothrow_move_constructible::value, - "move cstr is missing"); + // The following assertion is commented, because, in CT_plus_2, + // one uses `std::set` and `std::map`, and their move-constructors + // may throw. + // + // static_assert(std::is_nothrow_move_constructible::value, + // "move cstr is missing"); + static_assert(std::is_nothrow_move_assignable::value, "move assignment is missing"); diff --git a/Triangulation_2/test/Triangulation_2/include/CGAL/_test_cls_constrained_triangulation_2.h b/Triangulation_2/test/Triangulation_2/include/CGAL/_test_cls_constrained_triangulation_2.h index 1fe1183d3db..0d854e4188e 100644 --- a/Triangulation_2/test/Triangulation_2/include/CGAL/_test_cls_constrained_triangulation_2.h +++ b/Triangulation_2/test/Triangulation_2/include/CGAL/_test_cls_constrained_triangulation_2.h @@ -92,8 +92,13 @@ template void _test_cls_constrained_triangulation(const Triang &) { - static_assert(std::is_nothrow_move_constructible::value, - "move cstr is missing"); + // The following assertion is commented, because, in CT_plus_2, + // one uses `std::set` and `std::map`, and their move-constructors + // may throw. + // + // static_assert(std::is_nothrow_move_constructible::value, + // "move cstr is missing"); + static_assert(std::is_nothrow_move_assignable::value, "move assignment is missing"); From a060fb639644ca2742e68b832545c140d03f89e9 Mon Sep 17 00:00:00 2001 From: Laurent Rineau Date: Fri, 21 Feb 2020 14:23:18 +0100 Subject: [PATCH 114/568] Fix segfault in the dtor of a moved-from Triangulation_hierarchy_2 --- Triangulation_2/include/CGAL/Triangulation_hierarchy_2.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Triangulation_2/include/CGAL/Triangulation_hierarchy_2.h b/Triangulation_2/include/CGAL/Triangulation_hierarchy_2.h index 91ca9486b0a..1fbe3957270 100644 --- a/Triangulation_2/include/CGAL/Triangulation_hierarchy_2.h +++ b/Triangulation_2/include/CGAL/Triangulation_hierarchy_2.h @@ -417,8 +417,8 @@ void Triangulation_hierarchy_2:: clear() { - for(int i=0;iclear(); + for(int i=0;iclear(); } From baefa0d30742872928c2987617422cb0db50d14c Mon Sep 17 00:00:00 2001 From: Jane Tournois Date: Fri, 28 Feb 2020 11:46:53 +0100 Subject: [PATCH 115/568] fix cout --- .../CGAL/Tetrahedral_remeshing/internal/split_long_edges.h | 2 -- 1 file changed, 2 deletions(-) diff --git a/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/split_long_edges.h b/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/split_long_edges.h index 44a67a4ee09..6d7615f80e7 100644 --- a/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/split_long_edges.h +++ b/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/split_long_edges.h @@ -283,8 +283,6 @@ namespace internal std::cout << "\rSplit (" << high << ")... (" << long_edges.left.size() << " long edges, " << "length = " << std::sqrt(sqlen) << ", " - << std::sqrt(CGAL::squared_distance(point(e.first->point()), - point(e.second->point()))) << ", " << nb_splits << " splits)"; std::cout.flush(); #endif From 9517760261b66ef66650ab920b7e5bb17d90e164 Mon Sep 17 00:00:00 2001 From: Jane Tournois Date: Fri, 28 Feb 2020 13:32:02 +0100 Subject: [PATCH 116/568] fix example missing const and remove useless code --- .../tetrahedral_remeshing_of_one_subdomain.cpp | 12 ++---------- 1 file changed, 2 insertions(+), 10 deletions(-) diff --git a/Tetrahedral_remeshing/examples/Tetrahedral_remeshing/tetrahedral_remeshing_of_one_subdomain.cpp b/Tetrahedral_remeshing/examples/Tetrahedral_remeshing/tetrahedral_remeshing_of_one_subdomain.cpp index ee37365dad1..c17a444cbb2 100644 --- a/Tetrahedral_remeshing/examples/Tetrahedral_remeshing/tetrahedral_remeshing_of_one_subdomain.cpp +++ b/Tetrahedral_remeshing/examples/Tetrahedral_remeshing/tetrahedral_remeshing_of_one_subdomain.cpp @@ -19,14 +19,14 @@ typedef CGAL::Tetrahedral_remeshing::Remeshing_triangulation_3 Remeshing_tria struct Cells_of_subdomain { private: - int m_subdomain; + const int m_subdomain; public: Cells_of_subdomain(const int& subdomain) : m_subdomain(subdomain) {} - const bool operator()(Remeshing_triangulation::Cell_handle c) + const bool operator()(Remeshing_triangulation::Cell_handle c) const { return m_subdomain == c->subdomain_index(); } @@ -34,16 +34,8 @@ public: int main(int argc, char* argv[]) { - const char* filename = "data/triangulation_two_subdomains.binary.cgal"; float target_edge_length = (argc > 1) ? atof(argv[1]) : 0.1f; - std::ifstream input(filename, std::ios::in); - if (!input) - { - std::cerr << "File " << filename << " could not be found" << std::endl; - return EXIT_FAILURE; - } - Remeshing_triangulation tr; generate_input(2, 1000, tr); From a7b745a44681c36d3dda658c103476a847d8e80d Mon Sep 17 00:00:00 2001 From: Jane Tournois Date: Fri, 28 Feb 2020 13:40:00 +0100 Subject: [PATCH 117/568] fix init_c3t3() and the collapse() step * the code of collapse() is made simpler because the C3t3 already embeds a lot of topology information that we do not need to re-test * init_c3t3() now fixes the dimension() of vertices because it was not always properly set in the input c3t3 * add counters in the plugin to understand why some collapse of very short edges fail --- .../Tetrahedral_remeshing_plugin.cpp | 49 +- .../internal/collapse_short_edges.h | 474 ++++++++---------- .../tetrahedral_adaptive_remeshing_impl.h | 58 +-- .../internal/tetrahedral_remeshing_helpers.h | 106 +++- 4 files changed, 389 insertions(+), 298 deletions(-) diff --git a/Polyhedron/demo/Polyhedron/Plugins/Tetrahedral_remeshing/Tetrahedral_remeshing_plugin.cpp b/Polyhedron/demo/Polyhedron/Plugins/Tetrahedral_remeshing/Tetrahedral_remeshing_plugin.cpp index abb1b2a9e7c..4ba6649e96b 100644 --- a/Polyhedron/demo/Polyhedron/Plugins/Tetrahedral_remeshing/Tetrahedral_remeshing_plugin.cpp +++ b/Polyhedron/demo/Polyhedron/Plugins/Tetrahedral_remeshing/Tetrahedral_remeshing_plugin.cpp @@ -1,6 +1,7 @@ #define CGAL_TETRAHEDRAL_REMESHING_VERBOSE #define CGAL_DUMP_REMESHING_STEPS -//#define CGAL_TETRAHEDRAL_REMESHING_DEBUG +#define CGAL_TETRAHEDRAL_REMESHING_DEBUG +#define CGAL_TETRAHEDRAL_REMESHING_VERBOSE_PROGRESS #include @@ -26,6 +27,21 @@ #include "ui_Tetrahedral_remeshing_dialog.h" +#ifdef CGAL_DEBUG_TET_REMESHING_IN_PLUGIN +std::size_t nb_topology_test = 0; +std::size_t nb_impossible = 0; +std::size_t nb_valid_collapse = 0; +std::size_t nb_invalid_collapse = 0; +std::size_t nb_invalid_lengths = 0; +std::size_t nb_invalid_collapse_short = 0; +std::size_t nb_orientation_v0 = 0; +std::size_t nb_orientation_v1 = 0; +std::size_t nb_orientation_midpoint = 0; +std::size_t nb_test_v0 = 0; +std::size_t nb_test_v1 = 0; +std::size_t nb_test_midpoint = 0; +#endif + using namespace CGAL::Three; class Polyhedron_demo_tetrahedral_remeshing_plugin : public QObject, @@ -103,6 +119,37 @@ public Q_SLOTS: // default cursor QApplication::restoreOverrideCursor(); + +#ifdef CGAL_DEBUG_TET_REMESHING_IN_PLUGIN + std::cout << "nb_topology_test = " << nb_topology_test << std::endl; + std::cout << "nb_impossible = " << nb_impossible << std::endl; + + std::cout << "nb_invalid_collapse_short = " << nb_invalid_collapse_short << std::endl; + + std::cout << "nb_orientation_fail_v0 = " << nb_orientation_v0 << std::endl; + std::cout << "nb_orientation_fail_v1 = " << nb_orientation_v1 << std::endl; + std::cout << "nb_orientation_fail_midpoint = " << nb_orientation_midpoint << std::endl; + + std::cout << "nb_test_v0 = " << nb_test_v0 << std::endl; + std::cout << "nb_test_v1 = " << nb_test_v1 << std::endl; + std::cout << "nb_test_midpoint = " << nb_test_midpoint << std::endl; + std::cout << std::endl; + + if (nb_test_v0 > 0) + std::cout << "nb_orientation_v0 / nb_test_v0 = " + << ((float)nb_orientation_v0 / (float)nb_test_v0) << std::endl; + if (nb_test_v1 > 1) + std::cout << "nb_orientation_v1 / nb_test_v1 = " + << ((float)nb_orientation_v1 / (float)nb_test_v1) << std::endl; + if (nb_test_midpoint > 0) + std::cout << "nb_orientation_midpoint / nb_test_midpoint = " + << ((float)nb_orientation_midpoint / (float)nb_test_midpoint) << std::endl; + + std::cout << std::endl; + std::cout << "nb_valid_collapse = " << nb_valid_collapse << std::endl; + std::cout << "nb_invalid_collapse = " << nb_invalid_collapse << std::endl; + std::cout << "nb_invalid_lengths = " << nb_invalid_lengths << std::endl; +#endif } else { diff --git a/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/collapse_short_edges.h b/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/collapse_short_edges.h index 7c790bd56bb..6d36127e64f 100644 --- a/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/collapse_short_edges.h +++ b/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/collapse_short_edges.h @@ -337,60 +337,7 @@ namespace internal bool not_an_edge; }; - template - bool topology_test(const typename C3t3::Edge& edge, - const C3t3& c3t3, - const CellSelector& cell_selector) - { - typedef typename C3t3::Vertex_handle Vertex_handle; - typedef typename C3t3::Cell_handle Cell_handle; - typedef typename C3t3::Edge Edge; - typedef typename C3t3::Facet Facet; - typedef typename C3t3::Triangulation::Facet_circulator Facet_circulator; - const Vertex_handle v0 = edge.first->vertex(edge.second); - const Vertex_handle v1 = edge.first->vertex(edge.third); - - // the "topology test" checks that : - // no incident non-boundary facet has 3 boundary edges - // no incident boundary facet has 3 feature edges - - Facet_circulator fcirc = c3t3.triangulation().incident_facets(edge); - Facet_circulator fdone = fcirc; - do - { - if (c3t3.triangulation().is_infinite(fcirc->first)) - continue; - - const Facet& f = *fcirc; - if (is_boundary(c3t3, f, cell_selector)) - //boundary : check that facet does not have 3 feature edges - { - //Get the ids of the opposite vertices - for (int i = 1; i < 4; i++) - { - Vertex_handle vi = f.first->vertex((f.second + i) % 4); - if (vi != v0 && vi != v1 && nb_incident_subdomains(vi, c3t3) > 1) - { - if (is_edge_in_complex(v0, vi, c3t3) - && is_edge_in_complex(v1, vi, c3t3)) - return false; - } - } - } - else //non-boundary : check that facet does not have 3 boundary edges - { - const Cell_handle circ = f.first; - const int i = f.second; - if ( is_boundary(c3t3, Edge(circ, (i + 1) % 4, (i + 2) % 4), cell_selector) - && is_boundary(c3t3, Edge(circ, (i + 2) % 4, (i + 3) % 4), cell_selector) - && is_boundary(c3t3, Edge(circ, (i + 3) % 4, (i + 1) % 4), cell_selector)) - return false; - } - } while (++fcirc != fdone); - - return true; - } template Collapse_type get_collapse_type(const typename C3t3::Edge& edge, @@ -407,94 +354,61 @@ namespace internal else return IMPOSSIBLE; } - template - Edge_type get_edge_type(const typename C3t3::Edge& edge, - const C3t3& c3t3) - { - typedef typename C3t3::Vertex_handle Vertex_handle; - typedef typename C3t3::Triangulation::Cell_circulator Cell_circulator; - typedef typename C3t3::Subdomain_index Subdomain_index; + //template + //Edge_type get_edge_type(const typename C3t3::Edge& edge, + // const C3t3& c3t3) + //{ + // typedef typename C3t3::Vertex_handle Vertex_handle; + // typedef typename C3t3::Triangulation::Cell_circulator Cell_circulator; + // typedef typename C3t3::Subdomain_index Subdomain_index; - const Vertex_handle & v0 = edge.first->vertex(edge.second); - const Vertex_handle & v1 = edge.first->vertex(edge.third); + // const Vertex_handle & v0 = edge.first->vertex(edge.second); + // const Vertex_handle & v1 = edge.first->vertex(edge.third); - int dim0 = c3t3.in_dimension(v0); - int dim1 = c3t3.in_dimension(v1); + // const int dim0 = c3t3.in_dimension(v0); + // const int dim1 = c3t3.in_dimension(v1); - bool is_v0_on_hull = is_on_convex_hull(v0, c3t3); - bool is_v1_on_hull = is_on_convex_hull(v1, c3t3); + // const bool is_v0_on_hull = is_on_convex_hull(v0, c3t3); + // const bool is_v1_on_hull = is_on_convex_hull(v1, c3t3); - if (dim0 == 3 && dim1 == 3) - { - if (is_v0_on_hull && is_v1_on_hull) - { - Cell_circulator circ = c3t3.triangulation().incident_cells(edge); - Cell_circulator done = circ; - do - { - if (c3t3.triangulation().is_infinite(circ)) - return HULL_EDGE; - } - while (++circ != done); - return NO_COLLAPSE; - } - else if (is_v0_on_hull || is_v1_on_hull) - { - return MIXTE_IMAGINARY; - } - return INSIDE; - } + // if (c3t3.is_in_complex(edge)) + // return FEATURE; - if (dim0 == 2 && dim1 == 2) - { - Cell_circulator circ = c3t3.triangulation().incident_cells(edge); - Cell_circulator done = circ; + // else if (dim0 == 3 && dim1 == 3) + // return INSIDE; - std::vector indices; - do - { - Subdomain_index current_si = circ->subdomain_index(); + // else if (dim0 == 2 && dim1 == 2) + // { + // Cell_circulator circ = c3t3.triangulation().incident_cells(edge); + // Cell_circulator done = circ; - if (std::find(indices.begin(), indices.end(), current_si) == indices.end()){ - indices.push_back(current_si); - } + // std::vector indices; + // do + // { + // Subdomain_index current_si = circ->subdomain_index(); - Subdomain_index si_n = circ->neighbor(circ->index(v0))->subdomain_index(); - if (si_n == - circ->neighbor(circ->index(v1))->subdomain_index() && si_n != current_si){ - return NO_COLLAPSE; - } + // if (std::find(indices.begin(), indices.end(), current_si) == indices.end()) { + // indices.push_back(current_si); + // } - } - while (++circ != done); + // Subdomain_index si_n0 = circ->neighbor(circ->index(v0))->subdomain_index(); + // Subdomain_index si_n1 = circ->neighbor(circ->index(v1))->subdomain_index(); + // if (si_n0 == si_n1 && si_n0 != current_si) + // return NO_COLLAPSE; - std::size_t nb_si_v0 = nb_incident_subdomains(v0, c3t3); - std::size_t nb_si_v1 = nb_incident_subdomains(v1, c3t3); + // } while (++circ != done); - if (indices.size() >= (std::min)(nb_si_v0, nb_si_v1)){ - return BOUNDARY; - } + // const std::size_t nb_si_v0 = nb_incident_subdomains(v0, c3t3); + // const std::size_t nb_si_v1 = nb_incident_subdomains(v1, c3t3); - return NO_COLLAPSE; - } + // if (indices.size() >= (std::min)(nb_si_v0, nb_si_v1)) { + // return BOUNDARY; + // } + // } - if (dim0 == 3 && dim1 == 2) - { - if (is_v0_on_hull) - return NO_COLLAPSE; - return MIXTE; - } - - if (dim1 == 3 && dim0 == 2) - { - if (is_v1_on_hull) - return NO_COLLAPSE; - return MIXTE; - } - - //std::cerr << "ERROR : get_edge_type did not return anything valid!" << std::endl; - return NO_COLLAPSE; - } + // //std::cerr << "ERROR : get_edge_type did not return anything valid!" << std::endl; + // return NO_COLLAPSE; + //} template bool is_valid_collapse(const typename C3t3::Edge& edge, @@ -517,57 +431,56 @@ namespace internal Cell_handle n0_ch = circ->neighbor(v0_id); Cell_handle n1_ch = circ->neighbor(v1_id); - if ( n0_ch->has_vertex(v0) + if (n0_ch->has_vertex(v0) || n1_ch->has_vertex(v1) || n0_ch->has_neighbor(n1_ch)) + { +#ifdef CGAL_DEBUG_TET_REMESHING_IN_PLUGIN + if (c3t3.is_in_complex(edge)) + ++nb_invalid_collapse_short; +#endif return false; + } } while (++circ != done); return true; } - template + template bool is_valid_collapse(const typename C3t3::Edge& edge, const Collapse_type& collapse_type, const typename C3t3::Triangulation::Point& new_pos, - const C3t3& c3t3, - const bool /*protect_boundaries*/, - CellSelector cell_selector) + const C3t3& c3t3) { typedef typename C3t3::Vertex_handle Vertex_handle; typedef typename C3t3::Cell_handle Cell_handle; typedef typename C3t3::Triangulation::Point Point; - Vertex_handle v0 = edge.first->vertex(edge.second); - Vertex_handle v1 = edge.first->vertex(edge.third); + const Vertex_handle v0 = edge.first->vertex(edge.second); + const Vertex_handle v1 = edge.first->vertex(edge.third); + +#ifdef CGAL_DEBUG_TET_REMESHING_IN_PLUGIN + const bool in_cx = c3t3.is_in_complex(edge); + if (in_cx) + { + if (collapse_type == TO_MIDPOINT) + nb_test_midpoint++; + else if (collapse_type == TO_V1) + nb_test_v1++; + else + nb_test_v0++; + } +#endif - ////about protection of boundaries - //if (protect_boundaries) - //{ - // if (c3t3.is_in_complex(edge) - // || helpers::is_boundary(c3t3, edge, cell_selector)) - // return false; - //} - //we need to check that surfaces are not broken anyhow - bool v0_boundary = is_boundary_vertex(v0, c3t3, cell_selector); - bool v1_boundary = is_boundary_vertex(v1, c3t3, cell_selector); - if (collapse_type == TO_V0 && v1_boundary && !v0_boundary) - return false; - if (collapse_type == TO_V1 && v0_boundary && !v1_boundary) - return false; - if (collapse_type == TO_MIDPOINT && (v0_boundary ^ v1_boundary))//both or none to allow collapse - return false; - - std::vector cells_to_check; if (collapse_type == TO_V1 || collapse_type == TO_MIDPOINT) { + std::vector cells_to_check; c3t3.triangulation().finite_incident_cells(v0, std::back_inserter(cells_to_check)); - for (std::size_t i = 0; i < cells_to_check.size(); i++) + for (const Cell_handle ch : cells_to_check) { - const Cell_handle& ch = cells_to_check[i]; if (!ch->has_vertex(v1)) { //check orientation @@ -576,48 +489,66 @@ namespace internal ch->vertex(2)->point(), ch->vertex(3)->point()}; pts[ch->index(v0)] = new_pos; - if (CGAL::orientation(point(pts[0]), point(pts[1]), - point(pts[2]), point(pts[3])) != CGAL::POSITIVE) + if (CGAL::orientation(point(pts[0]), point(pts[1]), point(pts[2]), point(pts[3])) + != CGAL::POSITIVE) + { +#ifdef CGAL_DEBUG_TET_REMESHING_IN_PLUGIN + if (in_cx) + { + if (collapse_type == TO_MIDPOINT) + nb_orientation_midpoint++; + else + nb_orientation_v1++; + } +#endif return false; + } } } - cells_to_check.clear(); } - else if (collapse_type == TO_V0 || collapse_type == TO_MIDPOINT) + if (collapse_type == TO_V0 || collapse_type == TO_MIDPOINT) { + std::vector cells_to_check; c3t3.triangulation().finite_incident_cells(v1, - std::back_inserter(cells_to_check)); + std::back_inserter(cells_to_check)); - for (std::size_t i = 0; i < cells_to_check.size(); i++) + for (const Cell_handle ch : cells_to_check) { - const Cell_handle& ch = cells_to_check[i]; if (!ch->has_vertex(v0)) { - //check orientation //check orientation boost::array pts = { ch->vertex(0)->point(), ch->vertex(1)->point(), ch->vertex(2)->point(), ch->vertex(3)->point() }; pts[ch->index(v1)] = new_pos; - if (CGAL::orientation(point(pts[0]), point(pts[1]), - point(pts[2]), point(pts[3])) != CGAL::POSITIVE) + if (CGAL::orientation(point(pts[0]), point(pts[1]), point(pts[2]), point(pts[3])) + != CGAL::POSITIVE) + { +#ifdef CGAL_DEBUG_TET_REMESHING_IN_PLUGIN + if (in_cx) + { + if (collapse_type == TO_MIDPOINT) + nb_orientation_midpoint++; + else + nb_orientation_v0++; + } +#endif return false; + } } } - cells_to_check.clear(); } return is_valid_collapse(edge, c3t3); } - template - bool are_edge_lengths_valid(const typename C3t3::Vertex_handle v1, - const typename C3t3::Vertex_handle v2, + template + bool are_edge_lengths_valid(const typename C3t3::Edge& edge, const C3t3& c3t3, const typename C3t3::Triangulation::Point& new_pos, - SqLengthMap& edges_sqlength, const typename C3t3::Triangulation::Geom_traits::FT& sqhigh, + const CellSelector& cell_selector, const bool /* adaptive */ = false) { //SqLengthMap::key_type is Vertex_handle @@ -626,21 +557,31 @@ namespace internal typedef typename C3t3::Edge Edge; typedef typename C3t3::Vertex_handle Vertex_handle; + const Vertex_handle v1 = edge.first->vertex(edge.second); + const Vertex_handle v2 = edge.first->vertex(edge.third); + + boost::unordered_map edges_sqlength_after_collapse; + std::vector inc_edges; c3t3.triangulation().finite_incident_edges(v1, std::back_inserter(inc_edges)); + c3t3.triangulation().finite_incident_edges(v2, + std::back_inserter(inc_edges)); - for (std::size_t i = 0; i < inc_edges.size(); i++) + for (const Edge& ei : inc_edges) { - const Edge& ei = inc_edges[i]; + if (is_outside(ei, c3t3, cell_selector)) + continue; - Vertex_handle ivh = ei.first->vertex(ei.second); - if (ivh == v1) - ivh = ei.first->vertex(ei.third); + Vertex_handle vh = ei.first->vertex(ei.second); + if (vh == v1 || vh == v2) + vh = ei.first->vertex(ei.third); + if (vh == v1 || vh == v2) + continue; - if (v2 != ivh && edges_sqlength.find(ivh) == edges_sqlength.end()) + if (edges_sqlength_after_collapse.find(vh) == edges_sqlength_after_collapse.end()) { - FT sqlen_i = CGAL::squared_distance(new_pos, ivh->point()); + const FT sqlen = CGAL::squared_distance(new_pos, point(vh->point())); //if (adaptive){ // if (is_boundary_edge(ei) || is_hull_edge(ei)){ @@ -652,51 +593,18 @@ namespace internal // } //} //else { - if (sqlen_i > sqhigh) { + + if (sqlen > sqhigh) { return false; } //} - - edges_sqlength[ivh] = sqlen_i; + edges_sqlength_after_collapse[vh] = sqlen; } } return true; } - template - bool are_edge_lengths_valid(const typename C3t3::Edge& edge, - const C3t3& c3t3, - const Collapse_type& collapse_type, - const typename C3t3::Triangulation::Point& new_pos, - SqLengthMap& edges_sqlength, - const typename C3t3::Triangulation::Geom_traits::FT& sqhigh, - const bool adaptive = false) - { - //SqLengthMap::key_type is Vertex_handle - //SqLengthMap::value_type is double - - typedef typename C3t3::Vertex_handle Vertex_handle; - - edges_sqlength.clear(); - Vertex_handle v0 = edge.first->vertex(edge.second); - Vertex_handle v1 = edge.first->vertex(edge.third); - - if (collapse_type == TO_V1 || collapse_type == TO_MIDPOINT) - { - if (!are_edge_lengths_valid(v0, v1, c3t3, new_pos, - edges_sqlength, sqhigh, adaptive)) - return false; - } - else if (collapse_type == TO_V0 || collapse_type == TO_MIDPOINT) - { - if (!are_edge_lengths_valid(v1, v0, c3t3, new_pos, - edges_sqlength, sqhigh, adaptive)) - return false; - } - return true; - } - template void merge_surface_patch_indices(typename C3t3::Facet& f1, typename C3t3::Facet& f2, @@ -880,13 +788,13 @@ namespace internal Vertex_handle vh0 = edge.first->vertex(edge.second); Vertex_handle vh1 = edge.first->vertex(edge.third); - int dim_vh0 = c3t3.in_dimension(vh0); - int dim_vh1 = c3t3.in_dimension(vh1); + const int dim_vh0 = c3t3.in_dimension(vh0); + const int dim_vh1 = c3t3.in_dimension(vh1); Vertex_handle vh = Vertex_handle(); - Point_3 p0 = vh0->point(); - Point_3 p1 = vh1->point(); + const Point_3 p0 = vh0->point(); + const Point_3 p1 = vh1->point(); //Collapse at mid point if (collapse_type == TO_MIDPOINT) @@ -933,44 +841,87 @@ namespace internal typedef typename Tr::Point Point; typedef typename Tr::Vertex_handle Vertex_handle; - Vertex_handle v0 = edge.first->vertex(edge.second); - Vertex_handle v1 = edge.first->vertex(edge.third); + const Vertex_handle v0 = edge.first->vertex(edge.second); + const Vertex_handle v1 = edge.first->vertex(edge.third); Collapse_type collapse_type = get_collapse_type(edge, c3t3, cell_selector); - Edge_type edge_type = get_edge_type(edge, c3t3); - if (collapse_type != IMPOSSIBLE && edge_type != NO_COLLAPSE) +#ifdef CGAL_DEBUG_TET_REMESHING_IN_PLUGIN + const bool in_cx = c3t3.is_in_complex(edge); + if (in_cx && collapse_type == IMPOSSIBLE) + nb_impossible++; +#endif + + if (collapse_type == IMPOSSIBLE) + return Vertex_handle(); + + Point new_pos; + switch(collapse_type) { - Point new_pos; - switch(collapse_type) - { - case TO_V0: - new_pos = v0->point(); break; - case TO_V1: - new_pos = v1->point(); break; - default: - CGAL_assertion(collapse_type == TO_MIDPOINT); - new_pos = Point(CGAL::midpoint(point(v0->point()), point(v1->point()))); - } + case TO_V0: + new_pos = v0->point(); break; + case TO_V1: + new_pos = v1->point(); break; + default: + CGAL_assertion(collapse_type == TO_MIDPOINT); + new_pos = Point(CGAL::midpoint(point(v0->point()), point(v1->point()))); + } - boost::unordered_map edges_sqlength_after_collapse; - if (is_valid_collapse(edge, collapse_type, new_pos, c3t3, - protect_boundaries, cell_selector)) + if (!is_valid_collapse(edge, collapse_type, new_pos, c3t3)) + { +#ifdef TET_REMESHING_COLLAPSE_FALLBACK_EXPERIMENTS + if (collapse_type == TO_MIDPOINT) { - if (are_edge_lengths_valid(edge, c3t3, collapse_type, new_pos, - edges_sqlength_after_collapse, sqhigh - /*, adaptive = false*/)) + // with TO_MIDPOINT, we are authorized to test TO_V0 and TO_V1 + if (is_valid_collapse(edge, TO_V0, v0->point(), c3t3)) { - CollapseTriangulation local_tri(c3t3, edge, collapse_type, visitor); - local_tri.update(); - - Result_type res = local_tri.collapse(); - if (res == VALID) - return collapse(edge, collapse_type, c3t3); + collapse_type = TO_V0; + new_pos = v0->point(); } + else if (is_valid_collapse(edge, TO_V1, v1->point(), c3t3)) + { + collapse_type = TO_V1; + new_pos = v1->point(); + } + else + { +#ifdef CGAL_DEBUG_TET_REMESHING_IN_PLUGIN + if (in_cx) + nb_invalid_collapse++; +#endif + return Vertex_handle(); + } + } + else +#endif //TET_REMESHING_COLLAPSE_FALLBACK_EXPERIMENTS + { +#ifdef CGAL_DEBUG_TET_REMESHING_IN_PLUGIN + if (in_cx) + nb_invalid_collapse++; +#endif + return Vertex_handle(); } } + if (are_edge_lengths_valid(edge, c3t3, new_pos, sqhigh, cell_selector/*, adaptive = false*/)) + { + CollapseTriangulation local_tri(c3t3, edge, collapse_type, visitor); + local_tri.update(); + + Result_type res = local_tri.collapse(); + if (res == VALID) + { +#ifdef CGAL_DEBUG_TET_REMESHING_IN_PLUGIN + if (in_cx) + nb_valid_collapse++; +#endif + return collapse(edge, collapse_type, c3t3); + } + } +#ifdef CGAL_DEBUG_TET_REMESHING_IN_PLUGIN + else if (in_cx) + nb_invalid_lengths++; +#endif return Vertex_handle(); } @@ -1031,6 +982,10 @@ namespace internal boost::bimaps::multiset_of > > Boost_bimap; typedef typename Boost_bimap::value_type short_edge; + T3& tr = c3t3.triangulation(); + typename Gt::Compute_squared_length_3 sql + = tr.geom_traits().compute_squared_length_3_object(); + #ifdef CGAL_TETRAHEDRAL_REMESHING_VERBOSE std::cout << "Collapse short edges (" << low << ", " << high << ")..."; std::cout.flush(); @@ -1040,7 +995,6 @@ namespace internal const FT sq_high = high*high; //collect long edges - T3& tr = c3t3.triangulation(); Boost_bimap short_edges; for (Finite_edges_iterator eit = tr.finite_edges_begin(); eit != tr.finite_edges_end(); ++eit) @@ -1049,8 +1003,6 @@ namespace internal if (!can_be_collapsed(e, c3t3, protect_boundaries, cell_selector)) continue; - typename Gt::Compute_squared_length_3 sql - = tr.geom_traits().compute_squared_length_3_object(); FT sqlen = sql(tr.segment(e)); if (sqlen < sq_low) short_edges.insert(short_edge(make_vertex_pair(e), sqlen)); @@ -1069,10 +1021,12 @@ namespace internal //the edge with shortest length typename Boost_bimap::right_map::iterator eit = short_edges.right.begin(); Edge_vv e = eit->second; + FT sqlen = eit->first; short_edges.right.erase(eit); #ifdef CGAL_TETRAHEDRAL_REMESHING_VERBOSE_PROGRESS std::cout << "\rCollapse... (" << short_edges.left.size() << " short edges, "; + std::cout << std::sqrt(sqlen) << ", "; std::cout << nb_collapses << " collapses)"; std::cout.flush(); #endif @@ -1097,17 +1051,29 @@ namespace internal #endif continue; } -#ifdef CGAL_TETRAHEDRAL_REMESHING_VERBOSE - Vertex_handle vh = -#endif - collapse_edge(edge, c3t3, sq_high, - protect_boundaries, cell_selector, - visitor); + + Vertex_handle vh = collapse_edge(edge, c3t3, sq_high, + protect_boundaries, cell_selector, + visitor); + if (vh != Vertex_handle()) + { + std::vector incident_short; + c3t3.triangulation().finite_incident_edges(vh, + std::back_inserter(incident_short)); + for (const Edge& eshort : incident_short) + { + if (!can_be_collapsed(eshort, c3t3, protect_boundaries, cell_selector)) + continue; + + const FT sqlen = sql(tr.segment(eshort)); + if (sqlen < sq_low) + short_edges.insert(short_edge(make_vertex_pair(eshort), sqlen)); + } #ifdef CGAL_TETRAHEDRAL_REMESHING_VERBOSE - if (vh != Vertex_handle()) ++nb_collapses; #endif + } #ifdef CGAL_TETRAHEDRAL_REMESHING_DEBUG if (vh != Vertex_handle()) short_success << "2 " << point(p1) << " " << point(p2) << std::endl; diff --git a/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/tetrahedral_adaptive_remeshing_impl.h b/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/tetrahedral_adaptive_remeshing_impl.h index 9110596fe71..6bef6364223 100644 --- a/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/tetrahedral_adaptive_remeshing_impl.h +++ b/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/tetrahedral_adaptive_remeshing_impl.h @@ -361,10 +361,10 @@ private: fit != tr().finite_facets_end(); ++fit) { - Facet f = *fit; - Facet mf = tr().mirror_facet(f); - Subdomain_index s1 = f.first->subdomain_index(); - Subdomain_index s2 = mf.first->subdomain_index(); + const Facet f = *fit; + const Facet mf = tr().mirror_facet(f); + const Subdomain_index s1 = f.first->subdomain_index(); + const Subdomain_index s2 = mf.first->subdomain_index(); if (s1 != s2 || get(fcmap, f) || get(fcmap, mf) @@ -372,24 +372,17 @@ private: { m_c3t3.add_to_complex(f, 1); - if (!input_is_c3t3()) + const int i = f.second; + for (int j = 0; j < 3; ++j) { - const int i = f.second; - for (int j = 0; j < 3; ++j) - { - Vertex_handle vij = f.first->vertex(Tr::vertex_triple_index(i, j)); - if (vij->in_dimension() == -1 || vij->in_dimension() > 2) - vij->set_dimension(2); - } + Vertex_handle vij = f.first->vertex(Tr::vertex_triple_index(i, j)); + if (vij->in_dimension() == -1 || vij->in_dimension() > 2) + vij->set_dimension(2); } #ifdef CGAL_TETRAHEDRAL_REMESHING_DEBUG ++nbf; #endif } -#ifdef CGAL_TETRAHEDRAL_REMESHING_DEBUG - else if (input_is_c3t3() && m_c3t3.is_in_complex(f)) - ++nbf; -#endif } #ifdef CGAL_TETRAHEDRAL_REMESHING_DEBUG CGAL::Tetrahedral_remeshing::debug::dump_facets_in_complex(m_c3t3, "facets_in_complex.off"); @@ -402,30 +395,25 @@ private: eit != tr().finite_edges_end(); ++eit) { - Edge e = *eit; + const Edge& e = *eit; if (get(ecmap, CGAL::Tetrahedral_remeshing::make_vertex_pair(e)) - || nb_incident_subdomains(e, m_c3t3) > 2) + || nb_incident_subdomains(e, m_c3t3) > 2 + || nb_incident_surface_patches(e, m_c3t3) > 1) { m_c3t3.add_to_complex(e, 1); - if (!input_is_c3t3()) - { - Vertex_handle v = e.first->vertex(e.second); - if (v->in_dimension() == -1 || v->in_dimension() > 1) - v->set_dimension(1); + Vertex_handle v = e.first->vertex(e.second); + if (v->in_dimension() == -1 || v->in_dimension() > 1) + v->set_dimension(1); + + v = e.first->vertex(e.third); + if (v->in_dimension() == -1 || v->in_dimension() > 1) + v->set_dimension(1); - v = e.first->vertex(e.third); - if (v->in_dimension() == -1 || v->in_dimension() > 1) - v->set_dimension(1); - } #ifdef CGAL_TETRAHEDRAL_REMESHING_DEBUG ++nbe; #endif } -#ifdef CGAL_TETRAHEDRAL_REMESHING_DEBUG - else if (input_is_c3t3() && m_c3t3.is_in_complex(e)) - ++nbe; -#endif } #ifdef CGAL_TETRAHEDRAL_REMESHING_DEBUG CGAL::Tetrahedral_remeshing::debug::dump_edges_in_complex(m_c3t3, "edges_in_complex.polylines.txt"); @@ -443,11 +431,9 @@ private: { m_c3t3.add_to_complex(vit, ++corner_id); - if (!input_is_c3t3()) - { - if (vit->in_dimension() == -1 || vit->in_dimension() > 0) - vit->set_dimension(0); - } + if (vit->in_dimension() == -1 || vit->in_dimension() > 0) + vit->set_dimension(0); + #ifdef CGAL_TETRAHEDRAL_REMESHING_DEBUG ++nbv; #endif diff --git a/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/tetrahedral_remeshing_helpers.h b/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/tetrahedral_remeshing_helpers.h index 0791098e531..05514efb627 100644 --- a/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/tetrahedral_remeshing_helpers.h +++ b/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/tetrahedral_remeshing_helpers.h @@ -249,7 +249,7 @@ namespace Tetrahedral_remeshing bool is_boundary_edge(const typename C3t3::Vertex_handle& v0, const typename C3t3::Vertex_handle& v1, const C3t3& c3t3, - CellSelector cell_selector) + const CellSelector& cell_selector) { typedef typename C3t3::Edge Edge; typedef typename C3t3::Cell_handle Cell_handle; @@ -271,7 +271,7 @@ namespace Tetrahedral_remeshing std::vector facets; c3t3.triangulation().incident_facets(v, std::back_inserter(facets)); - BOOST_FOREACH(const Facet& f, facets) + for(const Facet& f : facets) { if (c3t3.is_in_complex(f)) return true; @@ -290,7 +290,7 @@ namespace Tetrahedral_remeshing std::vector facets; c3t3.triangulation().incident_facets(v, std::back_inserter(facets)); - BOOST_FOREACH(const Facet& f, facets) + for(const Facet& f : facets) { if (c3t3.is_in_complex(f)) return c3t3.surface_patch_index(f); @@ -346,6 +346,27 @@ namespace Tetrahedral_remeshing return oit; } + template + OutputIterator incident_surface_patches(const typename C3t3::Edge& e, + const C3t3& c3t3, + OutputIterator oit) + { + typedef typename C3t3::Triangulation::Facet_circulator Facet_circulator; + typedef typename C3t3::Triangulation::Facet Facet; + + Facet_circulator circ = c3t3.triangulation().incident_facets(e); + Facet_circulator end = circ; + do + { + const Facet& f = *circ; + if(c3t3.is_in_complex(f)) + *oit++ = c3t3.surface_patch_index(f); + } + while (++circ != end); + + return oit; + } + template std::size_t nb_incident_subdomains(const typename C3t3::Vertex_handle v, const C3t3& c3t3) @@ -370,6 +391,18 @@ namespace Tetrahedral_remeshing return indices.size(); } + template + std::size_t nb_incident_surface_patches(const typename C3t3::Edge& e, + const C3t3& c3t3) + { + typedef typename C3t3::Surface_patch_index Surface_patch_index; + + boost::unordered_set indices; + incident_surface_patches(e, c3t3, std::inserter(indices, indices.begin())); + + return indices.size(); + } + template std::size_t nb_incident_complex_edges(const typename C3t3::Vertex_handle v, const C3t3& c3t3) @@ -509,7 +542,7 @@ namespace Tetrahedral_remeshing std::vector cells; c3t3.triangulation().incident_cells(v, std::back_inserter(cells)); - BOOST_FOREACH(Cell_handle c, cells) + for(Cell_handle c : cells) { if (cell_selector(c)) return true; @@ -588,6 +621,61 @@ namespace Tetrahedral_remeshing return oit; } + template + bool topology_test(const typename C3t3::Edge& edge, + const C3t3& c3t3, + const CellSelector& cell_selector) + { + typedef typename C3t3::Vertex_handle Vertex_handle; + typedef typename C3t3::Cell_handle Cell_handle; + typedef typename C3t3::Edge Edge; + typedef typename C3t3::Facet Facet; + typedef typename C3t3::Triangulation::Facet_circulator Facet_circulator; + + const Vertex_handle v0 = edge.first->vertex(edge.second); + const Vertex_handle v1 = edge.first->vertex(edge.third); + + // the "topology test" checks that : + // no incident non-boundary facet has 3 boundary edges + // no incident boundary facet has 3 feature edges + + Facet_circulator fcirc = c3t3.triangulation().incident_facets(edge); + Facet_circulator fdone = fcirc; + do + { + if (c3t3.triangulation().is_infinite(fcirc->first)) + continue; + + const Facet& f = *fcirc; + if (is_boundary(c3t3, f, cell_selector)) + //boundary : check that facet does not have 3 feature edges + { + //Get the ids of the opposite vertices + for (int i = 1; i < 4; i++) + { + Vertex_handle vi = f.first->vertex((f.second + i) % 4); + if (vi != v0 && vi != v1 && nb_incident_subdomains(vi, c3t3) > 1) + { + if (is_edge_in_complex(v0, vi, c3t3) + && is_edge_in_complex(v1, vi, c3t3)) + return false; + } + } + } + else //non-boundary : check that facet does not have 3 boundary edges + { + const Cell_handle circ = f.first; + const int i = f.second; + if (is_boundary(c3t3, Edge(circ, (i + 1) % 4, (i + 2) % 4), cell_selector) + && is_boundary(c3t3, Edge(circ, (i + 2) % 4, (i + 3) % 4), cell_selector) + && is_boundary(c3t3, Edge(circ, (i + 3) % 4, (i + 1) % 4), cell_selector)) + return false; + } + } while (++fcirc != fdone); + + return true; + } + template void get_edge_info(const typename C3t3::Edge& edge, bool& update_v0, @@ -634,8 +722,12 @@ namespace Tetrahedral_remeshing if (c3t3.is_in_complex(edge)) { if (!topology_test(edge, c3t3, cell_selector)) + { +#ifdef CGAL_DEBUG_TET_REMESHING_IN_PLUGIN + nb_topology_test++; +#endif return; - + } const std::size_t nb_si_v0 = nb_incident_subdomains(v0, c3t3); const std::size_t nb_si_v1 = nb_incident_subdomains(v1, c3t3); @@ -1134,9 +1226,9 @@ namespace Tetrahedral_remeshing ofs << "OFF" << std::endl; ofs << vertices_di.size() << " 0 0" << std::endl << std::endl; - for (std::size_t j = 0; j < vertices_di.size(); ++j) + for (Vertex_handle vj : vertices_di) { - ofs << vertices_di[j]->point() << std::endl; + ofs << point(vj->point()) << std::endl; } ofs.close(); From 1c6d251859e5368db008247da3ed594b056c22d7 Mon Sep 17 00:00:00 2001 From: Jane Tournois Date: Fri, 28 Feb 2020 13:45:06 +0100 Subject: [PATCH 118/568] fix conversion warning --- .../include/CGAL/Tetrahedral_remeshing/internal/FMLS.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/FMLS.h b/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/FMLS.h index 2dc1856c19a..64404c223ca 100644 --- a/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/FMLS.h +++ b/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/FMLS.h @@ -435,8 +435,8 @@ namespace CGAL minMax[3 + j] = PN[6 * i + j]; } for (unsigned int i = 0; i < 3; i++) { - minMax[i] -= 0.001; - minMax[3 + i] += 0.001; + minMax[i] -= 0.001f; + minMax[3 + i] += 0.001f; } for (unsigned int i = 0; i < 3; i++) res[i] = (unsigned int)ceil((minMax[3 + i] - minMax[i]) / cellSize); From e3d7f7946db42f52317b23fcc150a39dcde76e53 Mon Sep 17 00:00:00 2001 From: Laurent Rineau Date: Fri, 28 Feb 2020 14:01:20 +0100 Subject: [PATCH 119/568] CC_iterator(CC_iterator&&) is now `= default` That fixes a segmentation fault with Visual Studio in Skin Surface Meshing. --- STL_Extension/include/CGAL/Compact_container.h | 10 +--------- 1 file changed, 1 insertion(+), 9 deletions(-) diff --git a/STL_Extension/include/CGAL/Compact_container.h b/STL_Extension/include/CGAL/Compact_container.h index 6c135a9f36f..f6946fc2758 100644 --- a/STL_Extension/include/CGAL/Compact_container.h +++ b/STL_Extension/include/CGAL/Compact_container.h @@ -908,15 +908,7 @@ namespace internal { return *this; } - CC_iterator(CC_iterator&& it) noexcept -#ifdef CGAL_COMPACT_CONTAINER_DEBUG_TIME_STAMP - : ts(Time_stamper::time_stamp(it.operator->())) -#endif - { - m_ptr.p = it.operator->(); - it.m_ptr.p = nullptr; - } - + CC_iterator(CC_iterator&& it) = default; ~CC_iterator() = default; CC_iterator& operator=(const CC_iterator&) = default; CC_iterator& operator=(CC_iterator&&) = default; From ad6de493048007e8e61e3022a0b1389ddd054767 Mon Sep 17 00:00:00 2001 From: Jane Tournois Date: Fri, 28 Feb 2020 14:28:20 +0100 Subject: [PATCH 120/568] and const's and use range iterators in smoothing and remove outdated code --- .../internal/smooth_vertices.h | 324 +++--------------- 1 file changed, 53 insertions(+), 271 deletions(-) diff --git a/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/smooth_vertices.h b/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/smooth_vertices.h index 660daaf15bd..7e45d8c23ac 100644 --- a/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/smooth_vertices.h +++ b/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/smooth_vertices.h @@ -50,13 +50,11 @@ namespace CGAL const Tr& tr = c3t3.triangulation(); - for (Finite_facets_iterator fit = tr.finite_facets_begin(); - fit != tr.finite_facets_end(); ++fit) + for (const Facet& f : tr.finite_facets()) { - const Facet& f = *fit; if (c3t3.is_in_complex(f)) { - Surface_patch_index surf_i = c3t3.surface_patch_index(f); + const Surface_patch_index surf_i = c3t3.surface_patch_index(f); for (int i = 0; i < 3; ++i) { Vertex_handle v_id = f.first->vertex(indices(f.second, i)); @@ -65,20 +63,17 @@ namespace CGAL } } - for (Finite_facets_iterator fit = tr.finite_facets_begin(); - fit != tr.finite_facets_end(); ++fit) + for (const Facet& f : tr.finite_facets()) { - const Facet& f = *fit; + const Cell_handle ch = f.first; + const Cell_handle n_ch = f.first->neighbor(f.second); - Cell_handle ch = f.first; - Cell_handle n_ch = f.first->neighbor(f.second); - - Subdomain_index si = ch->subdomain_index(); - Subdomain_index si_mirror = n_ch->subdomain_index(); + const Subdomain_index si = ch->subdomain_index(); + const Subdomain_index si_mirror = n_ch->subdomain_index(); if (c3t3.is_in_complex(f)) { - Surface_patch_index surf_i = c3t3.surface_patch_index(f); + const Surface_patch_index surf_i = c3t3.surface_patch_index(f); Vector_3 n = CGAL::Tetrahedral_remeshing::normal(f, tr.geom_traits()); @@ -183,212 +178,6 @@ namespace CGAL return true; } - template - typename C3T3::Triangulation::Geom_traits::Vector_3 - move_3d(typename C3T3::Vertex_handle v, const C3T3& c3t3) - { - typedef typename C3T3::Edge Edge; - typedef typename C3T3::Vertex_handle Vertex_handle; - typedef typename C3T3::Triangulation::Geom_traits::Vector_3 Vector_3; - - Vector_3 move = CGAL::NULL_VECTOR; - - std::vector edges; - c3t3.triangulation().incident_edges(v, std::back_inserter(edges)); - - if (edges.empty()) - return move; - - BOOST_FOREACH(Edge e, edges) - { - Vertex_handle ve = (e.first->vertex(e.second) != v) - ? e.first->vertex(e.second) - : e.first->vertex(e.third); - move = move + Vector_3(CGAL::ORIGIN, ve->point()); - } - - return 1. / edges.size() * move; - } - - template - typename C3T3::Triangulation::Geom_traits::Vector_3 - move_2d(typename C3T3::Vertex_handle v, - const C3T3& c3t3, - const typename C3T3::Subdomain_index& imaginary_index) - { - typedef typename C3T3::Edge Edge; - typedef typename C3T3::Vertex_handle Vertex_handle; - typedef typename C3T3::Triangulation::Geom_traits::Vector_3 Vector_3; - - Vector_3 move = CGAL::NULL_VECTOR; - - std::vector edges; - c3t3.triangulation().incident_edges(v, std::back_inserter(edges)); - - if (edges.empty()) - return move; - - std::size_t nbe = 0; - BOOST_FOREACH(Edge e, edges) - { - if (CGAL::is_on_domain_hull(e, c3t3, imaginary_index)) - { - Vertex_handle ve = (e.first->vertex(e.second) != v) - ? e.first->vertex(e.second) - : e.first->vertex(e.third); - move = move + Vector_3(CGAL::ORIGIN, ve->point()); - ++nbe; - } - } - - if (nbe > 0) - return (1. / nbe) * move; - else - return CGAL::NULL_VECTOR; - } - - template - typename C3T3::Triangulation::Geom_traits::Vector_3 - move_1d(typename C3T3::Vertex_handle v, - const C3T3& c3t3, - const typename C3T3::Subdomain_index& /*imaginary_index*/) - { - typedef typename C3T3::Edge Edge; - typedef typename C3T3::Vertex_handle Vertex_handle; - typedef typename C3T3::Triangulation::Geom_traits::Vector_3 Vector_3; - - Vector_3 move = CGAL::NULL_VECTOR; - - std::vector edges; - c3t3.triangulation().incident_edges(v, std::back_inserter(edges)); - - if (edges.empty()) - return move; - - std::size_t nbe = 0; - BOOST_FOREACH(Edge e, edges) - { - if (!c3t3.is_in_complex(e)) - continue; - - Vertex_handle ve = (e.first->vertex(e.second) != v) - ? e.first->vertex(e.second) - : e.first->vertex(e.third); - - move = move + Vector_3(CGAL::ORIGIN, ve->point()); - ++nbe; - } - - if (nbe == 2) - return 0.5 * move; - else - return CGAL::NULL_VECTOR; - } - -// template -// void smooth_vertices_new(C3T3& c3t3, -// const typename C3T3::Subdomain_index& imaginary_index, -// const bool /*protect_boundaries*/, -// CellSelector cell_selector) -// { -// typedef typename C3T3::Triangulation Tr; -// typedef typename C3T3::Vertex_handle Vertex_handle; -// typedef typename C3T3::Cell_handle Cell_handle; -// typedef typename Tr::Finite_vertices_iterator Finite_vertices_iterator; -// -// typedef typename Tr::Geom_traits Gt; -// typedef typename Gt::Point_3 Point_3; -// typedef typename Gt::Vector_3 Vector_3; -// -//#ifdef CGAL_TETRAHEDRAL_REMESHING_VERBOSE -// std::cout << "Smooth vertices..."; -// std::cout.flush(); -// std::size_t nb_done = 0; CGAL_USE(nb_done); -//#endif -// -// Tr& tr = c3t3.triangulation(); -// -//#ifdef CGAL_TETRAHEDRAL_REMESHING_DEBUG -// CGAL::debug::dump_vertices_by_dimension(c3t3.triangulation(), "c3t3_vertices_before_smoothing"); -//#endif -// -// const std::size_t nbv = tr.number_of_vertices(); -// boost::unordered_map vertex_id; -// std::vector smoothing_vecs(nbv, CGAL::NULL_VECTOR); -// // std::vector neighbors(nbv, -1); -// -// // generate ids for vertices -// std::size_t id = 0; -// for (Finite_vertices_iterator vit = tr.finite_vertices_begin(); -// vit != tr.finite_vertices_end(); ++vit) -// { -// vertex_id[vit] = id++; -// } -// -//#ifdef CGAL_TETRAHEDRAL_REMESHING_DEBUG -// std::ofstream ofs_2d("moves_on_surface.polylines.txt"); -// std::ofstream ofs_1d("moves_on_features.polylines.txt"); -//#endif -// -// // compute move depending on underlying dimension -// for (Finite_vertices_iterator vit = tr.finite_vertices_begin(); -// vit != tr.finite_vertices_end(); ++vit) -// { -// switch (vit->in_dimension()) -// { -// case 3: -// if (is_imaginary(vit, c3t3, imaginary_index) || !is_selected(vit, c3t3, cell_selector)) -// break; -// else -// smoothing_vecs[vertex_id.at(vit)] = move_3d(vit, c3t3); -// break; -// -// case 2: -// smoothing_vecs[vertex_id.at(vit)] = move_2d(vit, c3t3, imaginary_index); -//#ifdef CGAL_TETRAHEDRAL_REMESHING_DEBUG -// if (smoothing_vecs[vertex_id.at(vit)] != CGAL::NULL_VECTOR) -// ofs_2d << "2 " << vit->point() -// << " " << (CGAL::ORIGIN + smoothing_vecs[vertex_id.at(vit)]) << std::endl; -//#endif -// break; -// -// case 1: -// smoothing_vecs[vertex_id.at(vit)] = move_1d(vit, c3t3, imaginary_index); -//#ifdef CGAL_TETRAHEDRAL_REMESHING_DEBUG -// if (smoothing_vecs[vertex_id.at(vit)] != CGAL::NULL_VECTOR) -// ofs_1d << "2 " << vit->point() -// << " " << (CGAL::ORIGIN + smoothing_vecs[vertex_id.at(vit)]) << std::endl; -//#endif -// -// default: -// break; -// } -// } -//#ifdef CGAL_TETRAHEDRAL_REMESHING_DEBUG -// ofs_2d.close(); -// ofs_1d.close(); -//#endif -// -// // apply moves -// for (Finite_vertices_iterator vit = tr.finite_vertices_begin(); -// vit != tr.finite_vertices_end(); ++vit) -// { -// const std::size_t& vid = vertex_id.at(vit); -// Point_3 new_pos = CGAL::ORIGIN + smoothing_vecs[vid]; -// const Vector_3 move(vit->point(), new_pos); -// -// std::vector cells; -// tr.finite_incident_cells(vit, std::back_inserter(cells)); -// -// double frac = 1.; -// while (frac > 0.05 /// 1/16 = 0.0625 -// && !check_inversion_and_move(vit, frac * move, cells)) -// { -// frac = 0.5 * frac; -// } -// } -// -// } template void smooth_vertices(C3T3& c3t3, @@ -401,8 +190,7 @@ namespace CGAL typedef typename C3T3::Vertex_handle Vertex_handle; typedef typename C3T3::Cell_handle Cell_handle; typedef typename C3T3::Facet Facet; - typedef typename Tr::Finite_vertices_iterator Finite_vertices_iterator; - typedef typename Tr::Finite_edges_iterator Finite_edges_iterator; + typedef typename Tr::Edge Edge; typedef typename Tr::Geom_traits Gt; typedef typename Gt::Point_3 Point_3; @@ -424,24 +212,22 @@ namespace CGAL //collect ids std::size_t id = 0; - for (Finite_vertices_iterator vit = tr.finite_vertices_begin(); - vit != tr.finite_vertices_end(); ++vit) + for (const Vertex_handle v : tr.finite_vertex_handles()) { - vertex_id[vit] = id++; + vertex_id[v] = id++; } if (!protect_boundaries) { - for (Finite_edges_iterator eit = tr.finite_edges_begin(); - eit != tr.finite_edges_end(); ++eit) + for (const Edge& e : tr.finite_edges()) { - const Vertex_handle vh0 = eit->first->vertex(eit->second); - const Vertex_handle vh1 = eit->first->vertex(eit->third); + const Vertex_handle vh0 = e.first->vertex(e.second); + const Vertex_handle vh1 = e.first->vertex(e.third); const std::size_t& i0 = vertex_id.at(vh0); const std::size_t& i1 = vertex_id.at(vh1); - if (c3t3.is_in_complex(*eit)) + if (c3t3.is_in_complex(e)) { if (!is_feature(vh0, c3t3)) neighbors[i0] = (std::max)(0, neighbors[i0]); @@ -450,7 +236,7 @@ namespace CGAL bool update_v0 = false, update_v1 = false; - get_edge_info(*eit, update_v0, update_v1, c3t3, cell_selector); + get_edge_info(e, update_v0, update_v1, c3t3, cell_selector); if (update_v0) { const Point_3& p1 = point(vh1->point()); @@ -533,10 +319,9 @@ namespace CGAL c3t3); // Smooth - for (Finite_vertices_iterator vit = tr.finite_vertices_begin(); - vit != tr.finite_vertices_end(); ++vit) + for (Vertex_handle v : tr.finite_vertex_handles()) { - const std::size_t& vid = vertex_id.at(vit); + const std::size_t& vid = vertex_id.at(v); if (neighbors[vid] > 1) { Point_3 smoothed_position = CGAL::ORIGIN + smoothing_vecs[vid] / neighbors[vid]; @@ -544,15 +329,15 @@ namespace CGAL Point_3 final_position = CGAL::ORIGIN; std::size_t count = 0; - const Point_3 current_pos = point(vit->point()); + const Point_3 current_pos = point(v->point()); - const std::vector& v_surface_indices = vertices_surface_indices[vit]; + const std::vector& v_surface_indices = vertices_surface_indices[v]; for (std::size_t i = 0; i < v_surface_indices.size(); ++i) { const Surface_patch_index& si = v_surface_indices[i]; Vector_3 normal_projection - = project_on_tangent_plane(smoothed_position, current_pos, vertices_normals[vit][si]); + = project_on_tangent_plane(smoothed_position, current_pos, vertices_normals[v][si]); //Check if the mls surface exists to avoid degenrated cases Vector_3 mls_projection; @@ -571,7 +356,7 @@ namespace CGAL final_position = smoothed_position; // move vertex - vit->set_point(typename Tr::Point(final_position)); + v->set_point(typename Tr::Point(final_position)); } else if (neighbors[vid] > 0) @@ -580,9 +365,9 @@ namespace CGAL Point_3 final_position; int count = 0; - Vector_3 current_move(CGAL::ORIGIN, point(vit->point())); + Vector_3 current_move(CGAL::ORIGIN, point(v->point())); - const std::vector& v_surface_indices = vertices_surface_indices[vit]; + const std::vector& v_surface_indices = vertices_surface_indices[v]; for (std::size_t i = 0; i < v_surface_indices.size(); ++i) { Surface_patch_index si = v_surface_indices[i]; @@ -604,7 +389,7 @@ namespace CGAL final_position = CGAL::ORIGIN + current_move; // move vertex - vit->set_point(typename Tr::Point(final_position)); + v->set_point(typename Tr::Point(final_position)); } } @@ -614,16 +399,15 @@ namespace CGAL neighbors.clear(); neighbors.resize(nbv, -1); - for (Finite_edges_iterator eit = tr.finite_edges_begin(); - eit != tr.finite_edges_end(); ++eit) + for (const Edge& e : tr.finite_edges()) { - const Vertex_handle vh0 = eit->first->vertex(eit->second); - const Vertex_handle vh1 = eit->first->vertex(eit->third); + const Vertex_handle vh0 = e.first->vertex(e.second); + const Vertex_handle vh1 = e.first->vertex(e.third); const std::size_t& i0 = vertex_id.at(vh0); const std::size_t& i1 = vertex_id.at(vh1); - if (is_boundary(c3t3, *eit, cell_selector) && !c3t3.is_in_complex(*eit)) + if (is_boundary(c3t3, e, cell_selector) && !c3t3.is_in_complex(e)) { bool update_v0 = false, update_v1 = false; if (!is_feature(vh0, c3t3)) @@ -631,7 +415,7 @@ namespace CGAL if (!is_feature(vh1, c3t3)) neighbors[i1] = (std::max)(0, neighbors[i1]); - get_edge_info(*eit, update_v0, update_v1, c3t3, cell_selector); + get_edge_info(e, update_v0, update_v1, c3t3, cell_selector); if (update_v0) { const Point_3& p1 = point(vh1->point()); @@ -647,29 +431,28 @@ namespace CGAL } } - for (Finite_vertices_iterator vit = tr.finite_vertices_begin(); - vit != tr.finite_vertices_end(); ++vit) + for (Vertex_handle v : tr.finite_vertex_handles()) { - const std::size_t& vid = vertex_id.at(vit); + const std::size_t& vid = vertex_id.at(v); if (neighbors[vid] > 1) { Point_3 smoothed_position = CGAL::ORIGIN + smoothing_vecs[vid] / neighbors[vid]; - const Point_3& current_pos = point(vit->point()); + const Point_3& current_pos = point(v->point()); Point_3 final_position = CGAL::ORIGIN; - if (vit->in_dimension() == 3 && is_on_convex_hull(vit, c3t3)) + if (v->in_dimension() == 3 && is_on_convex_hull(v, c3t3)) { Vector_3 final_move = project_on_tangent_plane( - smoothed_position, current_pos, vertices_normals[vit][Surface_patch_index()]); + smoothed_position, current_pos, vertices_normals[v][Surface_patch_index()]); final_position = CGAL::ORIGIN + final_move; } else { - const Surface_patch_index si = surface_patch_index(vit, c3t3); + const Surface_patch_index si = surface_patch_index(v, c3t3); Vector_3 normal_projection = project_on_tangent_plane(smoothed_position, current_pos, - vertices_normals[vit][si]); + vertices_normals[v][si]); Vector_3 mls_projection; if (project(si, normal_projection, mls_projection, subdomain_FMLS, subdomain_FMLS_indices) /*|| project( si, smoothed_position, mls_projection )*/){ @@ -681,21 +464,21 @@ namespace CGAL // std::cout << "MLS " << final_position[0] << " - " << final_position[1] << " : " << final_position[2] << std::endl; } - vit->set_point(typename Tr::Point(final_position)); + v->set_point(typename Tr::Point(final_position)); } else if (neighbors[vid] > 0) { - if (vit->in_dimension() == 2) + if (v->in_dimension() == 2) { - const Surface_patch_index si = surface_patch_index(vit, c3t3); + const Surface_patch_index si = surface_patch_index(v, c3t3); - const Vector_3 current_pos(CGAL::ORIGIN, point(vit->point())); + const Vector_3 current_pos(CGAL::ORIGIN, point(v->point())); Vector_3 mls_projection; if (project(si, current_pos, mls_projection, subdomain_FMLS, subdomain_FMLS_indices) /*|| project( si, smoothed_position, mls_projection )*/) { const typename Tr::Point new_pos(CGAL::ORIGIN + mls_projection); - vit->set_point(new_pos); + v->set_point(new_pos); } } } @@ -707,13 +490,12 @@ namespace CGAL neighbors.clear(); neighbors.resize(nbv, 0); - for (Finite_edges_iterator eit = tr.finite_edges_begin(); - eit != tr.finite_edges_end(); ++eit) + for (const Edge& e : tr.finite_edges()) { - if ( !is_outside(*eit, c3t3, cell_selector)) + if ( !is_outside(e, c3t3, cell_selector)) { - const Vertex_handle vh0 = eit->first->vertex(eit->second); - const Vertex_handle vh1 = eit->first->vertex(eit->third); + const Vertex_handle vh0 = e.first->vertex(e.second); + const Vertex_handle vh1 = e.first->vertex(e.third); const std::size_t& i0 = vertex_id.at(vh0); const std::size_t& i1 = vertex_id.at(vh1); @@ -733,10 +515,9 @@ namespace CGAL } } - for (Finite_vertices_iterator vit = tr.finite_vertices_begin(); - vit != tr.finite_vertices_end(); ++vit) + for (Vertex_handle v : tr.finite_vertex_handles()) { - const std::size_t& vid = vertex_id.at(vit); + const std::size_t& vid = vertex_id.at(v); if (neighbors[vid] > 1) { if (smoothing_vecs[vid] != CGAL::NULL_VECTOR) @@ -745,10 +526,10 @@ namespace CGAL ++nb_done; #endif Point_3 new_pos = CGAL::ORIGIN + smoothing_vecs[vid] / neighbors[vid]; - const Vector_3 move(point(vit->point()), new_pos); + const Vector_3 move(point(v->point()), new_pos); std::vector cells; - tr.finite_incident_cells(vit, std::back_inserter(cells)); + tr.finite_incident_cells(v, std::back_inserter(cells)); bool selected = true; for (const Cell_handle ci : cells) @@ -764,7 +545,7 @@ namespace CGAL double frac = 1.; while (frac > 0.05 /// 1/16 = 0.0625 - && !check_inversion_and_move(vit, frac * move, cells, tr)) + && !check_inversion_and_move(v, frac * move, cells, tr)) { frac = 0.5 * frac; } @@ -776,7 +557,8 @@ namespace CGAL std::cout << " done (" << nb_done << " vertices smoothed)." << std::endl; #endif #ifdef CGAL_TETRAHEDRAL_REMESHING_DEBUG - CGAL::debug::dump_vertices_by_dimension(c3t3.triangulation(), "c3t3_vertices_after_smoothing"); + CGAL::Tetrahedral_remeshing::debug::dump_vertices_by_dimension( + c3t3.triangulation(), "c3t3_vertices_after_smoothing"); #endif } From 593489a614d6fe174796957f6c54683a66e19ecf Mon Sep 17 00:00:00 2001 From: Jane Tournois Date: Fri, 28 Feb 2020 16:51:00 +0100 Subject: [PATCH 121/568] wip smoothing using FMLS reorganize code to have smaller functions, use c++11 for loops on ranges, constify variables... --- .../Tetrahedral_remeshing/internal/FMLS.h | 16 +- .../internal/smooth_vertices.h | 167 +++++++++++------- .../tetrahedral_adaptive_remeshing_impl.h | 4 +- .../internal/tetrahedral_remeshing_helpers.h | 2 +- 4 files changed, 110 insertions(+), 79 deletions(-) diff --git a/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/FMLS.h b/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/FMLS.h index 64404c223ca..559aff5ec8d 100644 --- a/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/FMLS.h +++ b/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/FMLS.h @@ -592,7 +592,7 @@ namespace CGAL typename C3t3> void createMLSSurfaces(Subdomain__FMLS& subdomain_FMLS, Subdomain__FMLS_indices& subdomain_FMLS_indices, - VerticesNormalsMap& vertices_normals, + const VerticesNormalsMap& vertices_normals, const C3t3& c3t3, int upsample = 0) { @@ -619,8 +619,7 @@ namespace CGAL SurfaceIndexMap subdomain_sample_numbers; //Count the number of vertices for each boundary surface (i.e. one per label) - for (typename Tr::Finite_vertices_iterator vit = tr.finite_vertices_begin(); - vit != tr.finite_vertices_end(); ++vit) + for (const Vertex_handle vit : tr.finite_vertex_handles()) { if (vit->in_dimension() == 2) { @@ -658,8 +657,7 @@ namespace CGAL std::vector point_spacing_count(count, 0); //Allocation of the PN - for (typename Tr::Finite_vertices_iterator vit = tr.finite_vertices_begin(); - vit != tr.finite_vertices_end(); ++vit) + for (Vertex_handle vit : tr.finite_vertex_handles()) { if (vit->in_dimension() == 2) { @@ -673,7 +671,7 @@ namespace CGAL pns[fmls_id][6 * current_v_count[fmls_id] + 1] = p.y(); pns[fmls_id][6 * current_v_count[fmls_id] + 2] = p.z(); - const Vector_3& normal = vertices_normals[vit][surf_i]; + const Vector_3& normal = vertices_normals.at(vit).at(surf_i); pns[fmls_id][6 * current_v_count[fmls_id] + 3] = normal.x(); pns[fmls_id][6 * current_v_count[fmls_id] + 4] = normal.y(); @@ -689,8 +687,8 @@ namespace CGAL { EdgeMapIndex edgeMap; - for (typename C3t3::Facets_in_complex_iterator fit = c3t3.facets_in_complex_begin(); - fit != c3t3.facets_in_complex_end(); ++fit) + for (typename C3t3::Facet_iterator fit = c3t3.facets_begin(); + fit != c3t3.facets_end(); ++fit) { for (int i = 0; i < 2; i++) { @@ -823,7 +821,7 @@ namespace CGAL subdomain_FMLS.resize(nb_of_mls_to_create, FMLS()); count = 0; - //Cretaing the actual MLS surfaces + //Creating the actual MLS surfaces for (typename SurfaceIndexMap::iterator it = current_subdomain_FMLS_indices.begin(); it != current_subdomain_FMLS_indices.end(); ++it) { diff --git a/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/smooth_vertices.h b/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/smooth_vertices.h index 7e45d8c23ac..b2a76230733 100644 --- a/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/smooth_vertices.h +++ b/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/smooth_vertices.h @@ -129,7 +129,8 @@ namespace CGAL Point_3 point; Point_3 result = CGAL::ORIGIN + gi; - CGAL::Tetrahedral_remeshing::internal::FMLS& fmls = subdomain_FMLS[subdomain_FMLS_indices[si]]; + CGAL::Tetrahedral_remeshing::internal::FMLS& + fmls = subdomain_FMLS[subdomain_FMLS_indices.at(si)]; int it_nb = 0; const int max_it_nb = 5; @@ -178,6 +179,82 @@ namespace CGAL return true; } + template + void collect_vertices_subdomain_indices( + const C3T3& c3t3, + boost::unordered_map< + typename C3T3::Vertex_handle, + std::vector >& vertices_subdomain_indices) + { + typedef typename C3T3::Subdomain_index Subdomain_index; + typedef typename C3T3::Vertex_handle Vertex_handle; + + for (typename C3T3::Cell_iterator cit = c3t3.cells_in_complex_begin(); + cit != c3t3.cells_in_complex_end(); ++cit) + { + const Subdomain_index si = cit->subdomain_index(); + for (int i = 0; i < 4; ++i) + { + const Vertex_handle vi = cit->vertex(i); + if (vertices_subdomain_indices.find(vi) == vertices_subdomain_indices.end()) + { + std::vector indices(1); + indices[0] = si; + vertices_subdomain_indices.insert(std::make_pair(vi, indices)); + } + else + { + std::vector& v_indices = vertices_subdomain_indices.at(vi); + if (std::find(v_indices.begin(), v_indices.end(), si) == v_indices.end()) + v_indices.push_back(si); + } + } + } + } + + template + void collect_vertices_surface_indices( + const C3T3& c3t3, + const boost::unordered_map< + typename C3T3::Vertex_handle, + std::vector >& vertices_subdomain_indices, + boost::unordered_map< + typename C3T3::Vertex_handle, + std::vector >& vertices_surface_indices) + { + typedef typename C3T3::Surface_patch_index Surface_patch_index; + typedef typename C3T3::Vertex_handle Vertex_handle; + typedef typename C3T3::Facet Facet; + + for (typename C3T3::Facet_iterator fit = c3t3.facets_in_complex_begin(); + fit != c3t3.facets_in_complex_end(); ++fit) + { + const Facet& f = *fit; + const Surface_patch_index surface_index = c3t3.surface_patch_index(f); + + for (int i = 0; i < 3; ++i) + { + const Vertex_handle vi = f.first->vertex(indices(f.second, i)); + if (vertices_subdomain_indices.at(vi).size() > 2) + { + if (vertices_surface_indices.find(vi) == vertices_surface_indices.end()) + { + std::vector indices(1); + indices[0] = surface_index; + vertices_surface_indices.insert(std::make_pair(vi, indices)); + } + else + { + std::vector& v_surface_indices = vertices_surface_indices.at(vi); + if (std::find(v_surface_indices.begin(), v_surface_indices.end(), surface_index) + == v_surface_indices.end()) + v_surface_indices.push_back(surface_index); + } + } + } + } + } + template void smooth_vertices(C3T3& c3t3, @@ -205,6 +282,28 @@ namespace CGAL Tr& tr = c3t3.triangulation(); + //collect a map of vertices subdomain indices + boost::unordered_map > vertices_subdomain_indices; + collect_vertices_subdomain_indices(c3t3, vertices_subdomain_indices); + + //collect a map of vertices surface indices + boost::unordered_map > vertices_surface_indices; + collect_vertices_surface_indices(c3t3, vertices_subdomain_indices, vertices_surface_indices); + + //collect a map of normals at surface vertices + boost::unordered_map > vertices_normals; + compute_vertices_normals(c3t3, vertices_normals); + + // Build MLS Surfaces + std::vector < CGAL::Tetrahedral_remeshing::internal::FMLS > subdomain_FMLS; + boost::unordered_map subdomain_FMLS_indices; + createMLSSurfaces(subdomain_FMLS, + subdomain_FMLS_indices, + vertices_normals, + c3t3); + + //smooth() const std::size_t nbv = tr.number_of_vertices(); boost::unordered_map vertex_id; std::vector smoothing_vecs(nbv, CGAL::NULL_VECTOR); @@ -252,72 +351,6 @@ namespace CGAL } } - //collect a map of vertices subdomain indices - boost::unordered_map > vertices_subdomain_indices; - for (typename C3T3::Cell_iterator cit = c3t3.cells_in_complex_begin(); - cit != c3t3.cells_in_complex_end(); ++cit) - { - const Subdomain_index si = cit->subdomain_index(); - for (int i = 0; i < 4; ++i) - { - const Vertex_handle vi = cit->vertex(i); - if (vertices_subdomain_indices.find(vi) == vertices_subdomain_indices.end()) - { - std::vector indices(1); - indices[0] = si; - vertices_subdomain_indices.insert(std::make_pair(vi, indices)); - } - else - { - std::vector& v_indices = vertices_subdomain_indices.at(vi); - if (std::find(v_indices.begin(), v_indices.end(), si) == v_indices.end()) - v_indices.push_back(si); - } - } - } - - //collect a map of vertices surface indices - boost::unordered_map > vertices_surface_indices; - for (typename C3T3::Facet_iterator fit = c3t3.facets_in_complex_begin(); - fit != c3t3.facets_in_complex_end(); ++fit) - { - const Facet& f = *fit; - Surface_patch_index surface_index = c3t3.surface_patch_index(f); - for (int i = 0; i < 3; ++i) - { - const Vertex_handle vi = f.first->vertex(indices(f.second, i)); - if (vertices_subdomain_indices.at(vi).size() > 2) - { - if (vertices_surface_indices.find(vi) == vertices_surface_indices.end()) - { - std::vector indices(1); - indices[0] = surface_index; - vertices_surface_indices.insert(std::make_pair(vi, indices)); - } - else - { - std::vector& v_surface_indices = vertices_surface_indices.at(vi); - if (std::find(v_surface_indices.begin(), v_surface_indices.end(), surface_index) - == v_surface_indices.end()) - v_surface_indices.push_back(surface_index); - } - } - } - } - - //collect a map of normals at surface vertices - boost::unordered_map > vertices_normals; - compute_vertices_normals(c3t3, vertices_normals); - - // Build MLS Surfaces - std::vector < CGAL::Tetrahedral_remeshing::internal::FMLS > subdomain_FMLS; - boost::unordered_map subdomain_FMLS_indices; - createMLSSurfaces(subdomain_FMLS, - subdomain_FMLS_indices, - vertices_normals, - c3t3); - // Smooth for (Vertex_handle v : tr.finite_vertex_handles()) { diff --git a/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/tetrahedral_adaptive_remeshing_impl.h b/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/tetrahedral_adaptive_remeshing_impl.h index 6bef6364223..d5b63c6d477 100644 --- a/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/tetrahedral_adaptive_remeshing_impl.h +++ b/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/tetrahedral_adaptive_remeshing_impl.h @@ -495,7 +495,7 @@ private: collapse(); } flip(); -// smooth(); + smooth(); #ifdef CGAL_TETRAHEDRAL_REMESHING_VERBOSE std::cout << "# Iteration " << it_nb << " done : " @@ -515,7 +515,7 @@ private: ++it_nb; flip(); -// smooth(); + smooth(); #ifdef CGAL_TETRAHEDRAL_REMESHING_VERBOSE std::cout << "# Iteration " << it_nb << " (flip and smooth only) done : " diff --git a/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/tetrahedral_remeshing_helpers.h b/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/tetrahedral_remeshing_helpers.h index 05514efb627..4a669719eb3 100644 --- a/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/tetrahedral_remeshing_helpers.h +++ b/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/tetrahedral_remeshing_helpers.h @@ -181,7 +181,7 @@ namespace Tetrahedral_remeshing template bool is_on_feature(const VertexHandle v) { - return (v->in_dimension() == 1); + return (v->in_dimension() == 1 || v->in_dimension() == 0); } template From 8ffa2ef69db257207907c5773482ea16067111e1 Mon Sep 17 00:00:00 2001 From: Marc Glisse Date: Fri, 6 Dec 2019 23:58:11 +0100 Subject: [PATCH 122/568] Only use Eigen's determinant as a last resort. --- .../include/CGAL/NewKernel_d/LA_eigen/LA.h | 47 ++++++++++++++++++- 1 file changed, 46 insertions(+), 1 deletion(-) diff --git a/NewKernel_d/include/CGAL/NewKernel_d/LA_eigen/LA.h b/NewKernel_d/include/CGAL/NewKernel_d/LA_eigen/LA.h index 57507b27815..a9d954d1cc0 100644 --- a/NewKernel_d/include/CGAL/NewKernel_d/LA_eigen/LA.h +++ b/NewKernel_d/include/CGAL/NewKernel_d/LA_eigen/LA.h @@ -30,6 +30,7 @@ #include #include #include +#include namespace CGAL { @@ -114,14 +115,58 @@ template struct LA_eigen { } template static NT determinant(Mat_ const&m,bool=false){ + switch(m.rows()){ + //case 0: + // return 1; + case 1: + return m(0,0); + case 2: + return CGAL::determinant( + m(0,0),m(0,1), + m(1,0),m(1,1)); + case 3: + return CGAL::determinant( + m(0,0),m(0,1),m(0,2), + m(1,0),m(1,1),m(1,2), + m(2,0),m(2,1),m(2,2)); + case 4: + return CGAL::determinant( + m(0,0),m(0,1),m(0,2),m(0,3), + m(1,0),m(1,1),m(1,2),m(1,3), + m(2,0),m(2,1),m(2,2),m(2,3), + m(3,0),m(3,1),m(3,2),m(3,3)); + case 5: + return CGAL::determinant( + m(0,0),m(0,1),m(0,2),m(0,3),m(0,4), + m(1,0),m(1,1),m(1,2),m(1,3),m(1,4), + m(2,0),m(2,1),m(2,2),m(2,3),m(2,4), + m(3,0),m(3,1),m(3,2),m(3,3),m(3,4), + m(4,0),m(4,1),m(4,2),m(4,3),m(4,4)); + case 6: + return CGAL::determinant( + m(0,0),m(0,1),m(0,2),m(0,3),m(0,4),m(0,5), + m(1,0),m(1,1),m(1,2),m(1,3),m(1,4),m(1,5), + m(2,0),m(2,1),m(2,2),m(2,3),m(2,4),m(2,5), + m(3,0),m(3,1),m(3,2),m(3,3),m(3,4),m(3,5), + m(4,0),m(4,1),m(4,2),m(4,3),m(4,4),m(4,5), + m(5,0),m(5,1),m(5,2),m(5,3),m(5,4),m(5,5)); + default: +#if __cpp_if_constexpr >= 201606L + // Avoid compiling the LU decomposition for nothing + if constexpr (Mat_::MaxRowsAtCompileTime >= 1 && Mat_::MaxRowsAtCompileTime <= 6) { + CGAL_ASSUME(false); + } + else +#endif return m.determinant(); + } } template static typename Same_uncertainty_nt::type sign_of_determinant(Mat_ const&m,bool=false) { - return CGAL::sign(m.determinant()); + return CGAL::sign(LA_eigen::determinant(m)); } template static int rank(Mat_ const&m){ From b1c2910b9ee7649ca01132730e1553f4ccedf1c3 Mon Sep 17 00:00:00 2001 From: Marc Glisse Date: Sat, 7 Dec 2019 19:47:08 +0100 Subject: [PATCH 123/568] Use a ring bignum type for a couple of filtered predicates. --- NewKernel_d/include/CGAL/Epick_d.h | 25 ++++++++++- .../CGAL/NewKernel_d/Cartesian_filter_K.h | 44 ++++++++++++++----- .../CGAL/NewKernel_d/Filtered_predicate2.h | 3 +- .../include/CGAL/NewKernel_d/Lazy_cartesian.h | 2 +- NewKernel_d/include/CGAL/typeset.h | 15 ++++++- 5 files changed, 70 insertions(+), 19 deletions(-) diff --git a/NewKernel_d/include/CGAL/Epick_d.h b/NewKernel_d/include/CGAL/Epick_d.h index 5728e41e745..d4421196b86 100644 --- a/NewKernel_d/include/CGAL/Epick_d.h +++ b/NewKernel_d/include/CGAL/Epick_d.h @@ -48,8 +48,15 @@ struct Epick_d_help1 CGAL_CONSTEXPR Epick_d_help1(int d):CGAL_BASE(d){} }; #undef CGAL_BASE +// determinant is only safe for use with integers with this condition, see LA_eigen/LA.h +#if __cpp_if_constexpr >= 201606L #define CGAL_BASE \ - Cartesian_static_filters,Epick_d_help2 > + Cartesian_filter_K< \ + Epick_d_help1, \ + Cartesian_base_d, \ + Cartesian_base_d::Type, Dim>, \ + typename Functors_without_division::type \ + > template struct Epick_d_help2 : CGAL_BASE @@ -58,10 +65,24 @@ struct Epick_d_help2 CGAL_CONSTEXPR Epick_d_help2(int d):CGAL_BASE(d){} }; #undef CGAL_BASE +#define CGAL_BASE \ + Cartesian_static_filters,Epick_d_help3 > +#else +#define CGAL_BASE \ + Cartesian_static_filters,Epick_d_help3 > +#endif +template +struct Epick_d_help3 +: CGAL_BASE +{ + constexpr Epick_d_help3(){} + constexpr Epick_d_help3(int d):CGAL_BASE(d){} +}; +#undef CGAL_BASE #define CGAL_BASE \ Kernel_d_interface< \ Cartesian_wrap< \ - Epick_d_help2, \ + Epick_d_help3, \ Epick_d > > template struct Epick_d diff --git a/NewKernel_d/include/CGAL/NewKernel_d/Cartesian_filter_K.h b/NewKernel_d/include/CGAL/NewKernel_d/Cartesian_filter_K.h index 7fa283baf11..6ebb0e9daa3 100644 --- a/NewKernel_d/include/CGAL/NewKernel_d/Cartesian_filter_K.h +++ b/NewKernel_d/include/CGAL/NewKernel_d/Cartesian_filter_K.h @@ -29,28 +29,48 @@ namespace CGAL { -template < typename Base_, typename AK_, typename EK_ > + // It would be nicer to write the table in the other direction: Orientation_of_points_tag is good up to 6, Side_of_oriented_sphere_tag up to 5, etc. +template struct Functors_without_division { typedef typeset<> type; }; +template<> struct Functors_without_division> { + typedef typeset type; +}; +template<> struct Functors_without_division> { + typedef typeset type; +}; +template<> struct Functors_without_division> { + typedef typeset type; +}; +template<> struct Functors_without_division> { + typedef typeset type; +}; +template<> struct Functors_without_division> { + typedef typeset type; +}; +template<> struct Functors_without_division> { + typedef typeset type; +}; + +template < typename Base_, typename AK_, typename EK_, typename Pred_list = typeset_all > struct Cartesian_filter_K : public Base_, - private Store_kernel, private Store_kernel2 + private Store_kernel { CGAL_CONSTEXPR Cartesian_filter_K(){} CGAL_CONSTEXPR Cartesian_filter_K(int d):Base_(d){} //FIXME: or do we want an instance of AK and EK belonging to this kernel, //instead of a reference to external ones? - CGAL_CONSTEXPR Cartesian_filter_K(AK_ const&a,EK_ const&b):Base_(),Store_kernel(a),Store_kernel2(b){} - CGAL_CONSTEXPR Cartesian_filter_K(int d,AK_ const&a,EK_ const&b):Base_(d),Store_kernel(a),Store_kernel2(b){} + CGAL_CONSTEXPR Cartesian_filter_K(AK_ const&,EK_ const&b):Base_(),Store_kernel(b){} + CGAL_CONSTEXPR Cartesian_filter_K(int d,AK_ const&,EK_ const&b):Base_(d),Store_kernel(b){} typedef Base_ Kernel_base; typedef AK_ AK; typedef EK_ EK; - typedef typename Store_kernel::reference_type AK_rt; - AK_rt approximate_kernel()const{return this->kernel();} - typedef typename Store_kernel2::reference2_type EK_rt; - EK_rt exact_kernel()const{return this->kernel2();} + static_assert(internal::Do_not_store_kernel::value, "Only handle stateless kernels as AK"); + AK approximate_kernel()const{return {};} + typedef typename Store_kernel::reference_type EK_rt; + EK_rt exact_kernel()const{return this->Store_kernel::kernel();} // MSVC is too dumb to perform the empty base optimization. typedef boost::mpl::and_< internal::Do_not_store_kernel, - internal::Do_not_store_kernel, internal::Do_not_store_kernel > Do_not_store_kernel; //TODO: C2A/C2E could be able to convert *this into this->kernel() or this->kernel2(). @@ -61,12 +81,12 @@ struct Cartesian_filter_K : public Base_, // TODO: only fix some types, based on some criterion? template struct Type : Get_type {}; - template::type> struct Functor : + template::type, bool=Pred_list::template contains::value> struct Functor : Inherit_functor {}; - template struct Functor { + template struct Functor { typedef typename Get_functor::type AP; typedef typename Get_functor::type EP; - typedef Filtered_predicate2 type; + typedef Filtered_predicate2 type; }; // TODO: // template struct Functor : diff --git a/NewKernel_d/include/CGAL/NewKernel_d/Filtered_predicate2.h b/NewKernel_d/include/CGAL/NewKernel_d/Filtered_predicate2.h index 920a7d70735..3570ee3a254 100644 --- a/NewKernel_d/include/CGAL/NewKernel_d/Filtered_predicate2.h +++ b/NewKernel_d/include/CGAL/NewKernel_d/Filtered_predicate2.h @@ -49,7 +49,7 @@ namespace CGAL { // - Some caching could be done at the Point_2 level. -template +template class Filtered_predicate2 { //TODO: pack (at least use a tuple) @@ -76,7 +76,6 @@ public: Filtered_predicate2() {} - template Filtered_predicate2(const K& k) : ep(k.exact_kernel()), ap(k.approximate_kernel()), c2e(k,k.exact_kernel()), c2a(k,k.approximate_kernel()) {} diff --git a/NewKernel_d/include/CGAL/NewKernel_d/Lazy_cartesian.h b/NewKernel_d/include/CGAL/NewKernel_d/Lazy_cartesian.h index bce1522a0fe..fdaa08c1209 100644 --- a/NewKernel_d/include/CGAL/NewKernel_d/Lazy_cartesian.h +++ b/NewKernel_d/include/CGAL/NewKernel_d/Lazy_cartesian.h @@ -142,7 +142,7 @@ struct Lazy_cartesian : Dimension_base, template struct Functor { typedef typename Get_functor::type FA; typedef typename Get_functor::type FE; - typedef Filtered_predicate2 type; + typedef Filtered_predicate2 type; }; template struct Functor { typedef typename Get_functor::type FA; diff --git a/NewKernel_d/include/CGAL/typeset.h b/NewKernel_d/include/CGAL/typeset.h index 1bba56618e9..fb88973e387 100644 --- a/NewKernel_d/include/CGAL/typeset.h +++ b/NewKernel_d/include/CGAL/typeset.h @@ -55,6 +55,11 @@ namespace CGAL { template using contains = std::false_type; template using add = typeset; }; + struct typeset_all { + typedef typeset_all type; + template using contains = std::true_type; + template using add = typeset_all; + }; #else template struct typeset; template template struct typeset::add : typeset {}; + struct typeset_all { + typedef typeset_all type; + template struct contains : public std::true_type {}; + template struct add : public typeset_all {}; + }; #endif template struct typeset_union_ : typeset_union_::type, typename T2::tail> {}; template struct typeset_union_ > : T {}; + template struct typeset_union_ : typeset_all {}; template struct typeset_intersection_ { @@ -100,8 +111,8 @@ namespace CGAL { #endif typename U::template add::type, U>::type type; }; - template - struct typeset_intersection_,T> : typeset<> {}; + template struct typeset_intersection_, T> : typeset<> {}; + template struct typeset_intersection_ : T {}; #ifdef CGAL_CXX11 template From a3719c362861ed7cb0a6e466a320adce9538b4a4 Mon Sep 17 00:00:00 2001 From: Andreas Fabri Date: Mon, 2 Mar 2020 12:52:23 +0000 Subject: [PATCH 124/568] Compile in C++03 and C++14 --- NewKernel_d/include/CGAL/Epick_d.h | 4 ++-- .../include/CGAL/NewKernel_d/Cartesian_filter_K.h | 14 +++++++------- NewKernel_d/include/CGAL/typeset.h | 6 ++++-- 3 files changed, 13 insertions(+), 11 deletions(-) diff --git a/NewKernel_d/include/CGAL/Epick_d.h b/NewKernel_d/include/CGAL/Epick_d.h index d4421196b86..1c8fa985ac3 100644 --- a/NewKernel_d/include/CGAL/Epick_d.h +++ b/NewKernel_d/include/CGAL/Epick_d.h @@ -75,8 +75,8 @@ template struct Epick_d_help3 : CGAL_BASE { - constexpr Epick_d_help3(){} - constexpr Epick_d_help3(int d):CGAL_BASE(d){} + CGAL_CONSTEXPR Epick_d_help3(){} + CGAL_CONSTEXPR Epick_d_help3(int d):CGAL_BASE(d){} }; #undef CGAL_BASE #define CGAL_BASE \ diff --git a/NewKernel_d/include/CGAL/NewKernel_d/Cartesian_filter_K.h b/NewKernel_d/include/CGAL/NewKernel_d/Cartesian_filter_K.h index 6ebb0e9daa3..f931da3f15d 100644 --- a/NewKernel_d/include/CGAL/NewKernel_d/Cartesian_filter_K.h +++ b/NewKernel_d/include/CGAL/NewKernel_d/Cartesian_filter_K.h @@ -31,22 +31,22 @@ namespace CGAL { // It would be nicer to write the table in the other direction: Orientation_of_points_tag is good up to 6, Side_of_oriented_sphere_tag up to 5, etc. template struct Functors_without_division { typedef typeset<> type; }; -template<> struct Functors_without_division> { +template<> struct Functors_without_division > { typedef typeset type; }; -template<> struct Functors_without_division> { +template<> struct Functors_without_division > { typedef typeset type; }; -template<> struct Functors_without_division> { +template<> struct Functors_without_division > { typedef typeset type; }; -template<> struct Functors_without_division> { +template<> struct Functors_without_division > { typedef typeset type; }; -template<> struct Functors_without_division> { +template<> struct Functors_without_division > { typedef typeset type; }; -template<> struct Functors_without_division> { +template<> struct Functors_without_division > { typedef typeset type; }; @@ -63,7 +63,7 @@ struct Cartesian_filter_K : public Base_, typedef Base_ Kernel_base; typedef AK_ AK; typedef EK_ EK; - static_assert(internal::Do_not_store_kernel::value, "Only handle stateless kernels as AK"); + CGAL_static_assertion_msg(internal::Do_not_store_kernel::value, "Only handle stateless kernels as AK"); AK approximate_kernel()const{return {};} typedef typename Store_kernel::reference_type EK_rt; EK_rt exact_kernel()const{return this->Store_kernel::kernel();} diff --git a/NewKernel_d/include/CGAL/typeset.h b/NewKernel_d/include/CGAL/typeset.h index fb88973e387..a08c6c48215 100644 --- a/NewKernel_d/include/CGAL/typeset.h +++ b/NewKernel_d/include/CGAL/typeset.h @@ -88,8 +88,10 @@ namespace CGAL { struct typeset::add : typeset {}; struct typeset_all { typedef typeset_all type; - template struct contains : public std::true_type {}; - template struct add : public typeset_all {}; + template struct contains : public boost::true_type {}; + template struct add { + typedef typeset_all type; + }; }; #endif From 3e6ece5e4b17c2c8e7780e421b5261ddadb00b16 Mon Sep 17 00:00:00 2001 From: Andreas Fabri Date: Mon, 2 Mar 2020 16:09:33 +0000 Subject: [PATCH 125/568] VC++ does not yet provide __cpp_if_constexpr --- NewKernel_d/include/CGAL/Epick_d.h | 2 +- NewKernel_d/include/CGAL/NewKernel_d/LA_eigen/LA.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/NewKernel_d/include/CGAL/Epick_d.h b/NewKernel_d/include/CGAL/Epick_d.h index 1c8fa985ac3..0f96ce6fde1 100644 --- a/NewKernel_d/include/CGAL/Epick_d.h +++ b/NewKernel_d/include/CGAL/Epick_d.h @@ -49,7 +49,7 @@ struct Epick_d_help1 }; #undef CGAL_BASE // determinant is only safe for use with integers with this condition, see LA_eigen/LA.h -#if __cpp_if_constexpr >= 201606L +#if _MSC_VER >= 1911 || __cpp_if_constexpr >= 201606L #define CGAL_BASE \ Cartesian_filter_K< \ Epick_d_help1, \ diff --git a/NewKernel_d/include/CGAL/NewKernel_d/LA_eigen/LA.h b/NewKernel_d/include/CGAL/NewKernel_d/LA_eigen/LA.h index a9d954d1cc0..5a3f6b1642d 100644 --- a/NewKernel_d/include/CGAL/NewKernel_d/LA_eigen/LA.h +++ b/NewKernel_d/include/CGAL/NewKernel_d/LA_eigen/LA.h @@ -151,7 +151,7 @@ template struct LA_eigen { m(4,0),m(4,1),m(4,2),m(4,3),m(4,4),m(4,5), m(5,0),m(5,1),m(5,2),m(5,3),m(5,4),m(5,5)); default: -#if __cpp_if_constexpr >= 201606L +#if _MSC_VER >= 1911 || __cpp_if_constexpr >= 201606L // Avoid compiling the LU decomposition for nothing if constexpr (Mat_::MaxRowsAtCompileTime >= 1 && Mat_::MaxRowsAtCompileTime <= 6) { CGAL_ASSUME(false); From 5ce802f65803be2d50b1b7eb881781fa6ae70b8b Mon Sep 17 00:00:00 2001 From: Laurent Rineau Date: Mon, 2 Mar 2020 17:40:46 +0100 Subject: [PATCH 126/568] Fix compilation error: CGAL_ASSUME->CGAL_assume --- NewKernel_d/include/CGAL/NewKernel_d/LA_eigen/LA.h | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/NewKernel_d/include/CGAL/NewKernel_d/LA_eigen/LA.h b/NewKernel_d/include/CGAL/NewKernel_d/LA_eigen/LA.h index 5a3f6b1642d..082e84263b5 100644 --- a/NewKernel_d/include/CGAL/NewKernel_d/LA_eigen/LA.h +++ b/NewKernel_d/include/CGAL/NewKernel_d/LA_eigen/LA.h @@ -31,6 +31,7 @@ #include #include #include +#include namespace CGAL { @@ -154,7 +155,7 @@ template struct LA_eigen { #if _MSC_VER >= 1911 || __cpp_if_constexpr >= 201606L // Avoid compiling the LU decomposition for nothing if constexpr (Mat_::MaxRowsAtCompileTime >= 1 && Mat_::MaxRowsAtCompileTime <= 6) { - CGAL_ASSUME(false); + CGAL_assume(false); } else #endif From 5d053dba1aa9f11e60473ce2002b8f1ec8242240 Mon Sep 17 00:00:00 2001 From: Andreas Fabri Date: Mon, 2 Mar 2020 20:56:22 +0000 Subject: [PATCH 127/568] Add determinant 7x7 --- Kernel_23/include/CGAL/determinant.h | 77 +++++++++++++++++++ .../CGAL/NewKernel_d/Cartesian_filter_K.h | 2 +- .../include/CGAL/NewKernel_d/LA_eigen/LA.h | 9 +++ 3 files changed, 87 insertions(+), 1 deletion(-) diff --git a/Kernel_23/include/CGAL/determinant.h b/Kernel_23/include/CGAL/determinant.h index c91ea8d32e5..a88d697894a 100644 --- a/Kernel_23/include/CGAL/determinant.h +++ b/Kernel_23/include/CGAL/determinant.h @@ -211,6 +211,83 @@ determinant( return m012345; } +template +RT +determinant( + const RT& a00, const RT& a01, const RT& a02, const RT& a03, const RT& a04, + const RT& a05, const RT& a06, + const RT& a10, const RT& a11, const RT& a12, const RT& a13, const RT& a14, + const RT& a15, const RT& a16, + const RT& a20, const RT& a21, const RT& a22, const RT& a23, const RT& a24, + const RT& a25, const RT& a26, + const RT& a30, const RT& a31, const RT& a32, const RT& a33, const RT& a34, + const RT& a35, const RT& a36, + const RT& a40, const RT& a41, const RT& a42, const RT& a43, const RT& a44, + const RT& a45, const RT& a46, + const RT& a50, const RT& a51, const RT& a52, const RT& a53, const RT& a54, + const RT& a55, const RT& a56, + const RT& a60, const RT& a61, const RT& a62, const RT& a63, const RT& a64, + const RT& a65, const RT& a66) +{ + return a00 * determinant( + a11, a12, a13, a14, a15, a16, + a21, a22, a23, a24, a25, a26, + a31, a32, a33, a34, a35, a36, + a41, a42, a43, a44, a45, a46, + a51, a52, a53, a54, a55, a56, + a61, a62, a63, a64, a65, a66) + + - a10 * determinant(a01, a02, a03, a04, a05, a06, + + a21, a22, a23, a24, a25, a26, + a31, a32, a33, a34, a35, a36, + a41, a42, a43, a44, a45, a46, + a51, a52, a53, a54, a55, a56, + a61, a62, a63, a64, a65, a66) + + + a20 * determinant(a01, a02, a03, a04, a05, a06, + a11, a12, a13, a14, a15, a16, + + a31, a32, a33, a34, a35, a36, + a41, a42, a43, a44, a45, a46, + a51, a52, a53, a54, a55, a56, + a61, a62, a63, a64, a65, a66) + + - a30 * determinant(a01, a02, a03, a04, a05, a06, + a11, a12, a13, a14, a15, a16, + a21, a22, a23, a24, a25, a26, + + a41, a42, a43, a44, a45, a46, + a51, a52, a53, a54, a55, a56, + a61, a62, a63, a64, a65, a66) + + + a40 * determinant(a01, a02, a03, a04, a05, a06, + a11, a12, a13, a14, a15, a16, + a21, a22, a23, a24, a25, a26, + a31, a32, a33, a34, a35, a36, + + a51, a52, a53, a54, a55, a56, + a61, a62, a63, a64, a65, a66) + + - a50 * determinant(a01, a02, a03, a04, a05, a06, + a11, a12, a13, a14, a15, a16, + a21, a22, a23, a24, a25, a26, + a31, a32, a33, a34, a35, a36, + a41, a42, a43, a44, a45, a46, + + a61, a62, a63, a64, a65, a66) + + + a60 * determinant(a01, a02, a03, a04, a05, a06, + a11, a12, a13, a14, a15, a16, + a21, a22, a23, a24, a25, a26, + a31, a32, a33, a34, a35, a36, + a41, a42, a43, a44, a45, a46, + a51, a52, a53, a54, a55, a56 + + ); +} + + } //namespace CGAL #endif // CGAL_DETERMINANT_H diff --git a/NewKernel_d/include/CGAL/NewKernel_d/Cartesian_filter_K.h b/NewKernel_d/include/CGAL/NewKernel_d/Cartesian_filter_K.h index f931da3f15d..baff656bc69 100644 --- a/NewKernel_d/include/CGAL/NewKernel_d/Cartesian_filter_K.h +++ b/NewKernel_d/include/CGAL/NewKernel_d/Cartesian_filter_K.h @@ -49,7 +49,7 @@ template<> struct Functors_without_division > { template<> struct Functors_without_division > { typedef typeset type; }; - + template < typename Base_, typename AK_, typename EK_, typename Pred_list = typeset_all > struct Cartesian_filter_K : public Base_, private Store_kernel diff --git a/NewKernel_d/include/CGAL/NewKernel_d/LA_eigen/LA.h b/NewKernel_d/include/CGAL/NewKernel_d/LA_eigen/LA.h index 082e84263b5..9261ed89609 100644 --- a/NewKernel_d/include/CGAL/NewKernel_d/LA_eigen/LA.h +++ b/NewKernel_d/include/CGAL/NewKernel_d/LA_eigen/LA.h @@ -151,6 +151,15 @@ template struct LA_eigen { m(3,0),m(3,1),m(3,2),m(3,3),m(3,4),m(3,5), m(4,0),m(4,1),m(4,2),m(4,3),m(4,4),m(4,5), m(5,0),m(5,1),m(5,2),m(5,3),m(5,4),m(5,5)); + case 7: + return CGAL::determinant( + m(0,0),m(0,1),m(0,2),m(0,3),m(0,4),m(0,5),m(0,6), + m(1,0),m(1,1),m(1,2),m(1,3),m(1,4),m(1,5),m(1,6), + m(2,0),m(2,1),m(2,2),m(2,3),m(2,4),m(2,5),m(2,6), + m(3,0),m(3,1),m(3,2),m(3,3),m(3,4),m(3,5),m(3,6), + m(4,0),m(4,1),m(4,2),m(4,3),m(4,4),m(4,5),m(4,6), + m(5,0),m(5,1),m(5,2),m(5,3),m(5,4),m(5,5),m(5,6), + m(6,0),m(6,1),m(6,2),m(6,3),m(6,4),m(6,5),m(6,6)); default: #if _MSC_VER >= 1911 || __cpp_if_constexpr >= 201606L // Avoid compiling the LU decomposition for nothing From f8df87532187b0efe5f80214ccfdb0ed6f531347 Mon Sep 17 00:00:00 2001 From: Andreas Fabri Date: Tue, 3 Mar 2020 14:53:34 +0000 Subject: [PATCH 128/568] Now Mpzf is used for up to Delaunay_d<6> --- NewKernel_d/include/CGAL/Epick_d.h | 7 ++----- .../CGAL/NewKernel_d/Cartesian_filter_K.h | 2 +- .../include/CGAL/NewKernel_d/LA_eigen/LA.h | 17 +++++++++-------- 3 files changed, 12 insertions(+), 14 deletions(-) diff --git a/NewKernel_d/include/CGAL/Epick_d.h b/NewKernel_d/include/CGAL/Epick_d.h index 0f96ce6fde1..cc16803352b 100644 --- a/NewKernel_d/include/CGAL/Epick_d.h +++ b/NewKernel_d/include/CGAL/Epick_d.h @@ -49,7 +49,7 @@ struct Epick_d_help1 }; #undef CGAL_BASE // determinant is only safe for use with integers with this condition, see LA_eigen/LA.h -#if _MSC_VER >= 1911 || __cpp_if_constexpr >= 201606L + #define CGAL_BASE \ Cartesian_filter_K< \ Epick_d_help1, \ @@ -67,10 +67,7 @@ struct Epick_d_help2 #undef CGAL_BASE #define CGAL_BASE \ Cartesian_static_filters,Epick_d_help3 > -#else -#define CGAL_BASE \ - Cartesian_static_filters,Epick_d_help3 > -#endif + template struct Epick_d_help3 : CGAL_BASE diff --git a/NewKernel_d/include/CGAL/NewKernel_d/Cartesian_filter_K.h b/NewKernel_d/include/CGAL/NewKernel_d/Cartesian_filter_K.h index baff656bc69..a79c8f78c37 100644 --- a/NewKernel_d/include/CGAL/NewKernel_d/Cartesian_filter_K.h +++ b/NewKernel_d/include/CGAL/NewKernel_d/Cartesian_filter_K.h @@ -47,7 +47,7 @@ template<> struct Functors_without_division > { typedef typeset type; }; template<> struct Functors_without_division > { - typedef typeset type; + typedef typeset type; }; template < typename Base_, typename AK_, typename EK_, typename Pred_list = typeset_all > diff --git a/NewKernel_d/include/CGAL/NewKernel_d/LA_eigen/LA.h b/NewKernel_d/include/CGAL/NewKernel_d/LA_eigen/LA.h index 9261ed89609..79a273d237f 100644 --- a/NewKernel_d/include/CGAL/NewKernel_d/LA_eigen/LA.h +++ b/NewKernel_d/include/CGAL/NewKernel_d/LA_eigen/LA.h @@ -115,6 +115,13 @@ template struct LA_eigen { return (int)v.cols(); } + template static NT determinant_aux(Mat_ const& m, Tag_true) { + CGAL_assume(false); + } + template static NT determinant_aux(Mat_ const& m, Tag_false) { + return m.determinant(); + } + template static NT determinant(Mat_ const&m,bool=false){ switch(m.rows()){ //case 0: @@ -161,14 +168,8 @@ template struct LA_eigen { m(5,0),m(5,1),m(5,2),m(5,3),m(5,4),m(5,5),m(5,6), m(6,0),m(6,1),m(6,2),m(6,3),m(6,4),m(6,5),m(6,6)); default: -#if _MSC_VER >= 1911 || __cpp_if_constexpr >= 201606L - // Avoid compiling the LU decomposition for nothing - if constexpr (Mat_::MaxRowsAtCompileTime >= 1 && Mat_::MaxRowsAtCompileTime <= 6) { - CGAL_assume(false); - } - else -#endif - return m.determinant(); + return determinant_aux(m, Boolean_tag<(Mat_::MaxRowsAtCompileTime >= 1 && Mat_::MaxRowsAtCompileTime <= 7)>()); + } } From 60038951fa65988fd4fa917d69566caf9e1018bd Mon Sep 17 00:00:00 2001 From: Laurent Rineau Date: Fri, 6 Mar 2020 09:23:31 +0100 Subject: [PATCH 129/568] Fix a warning [-Wreturn-type] > warning: control reaches end of non-void function [-Wreturn-type] --- NewKernel_d/include/CGAL/NewKernel_d/LA_eigen/LA.h | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/NewKernel_d/include/CGAL/NewKernel_d/LA_eigen/LA.h b/NewKernel_d/include/CGAL/NewKernel_d/LA_eigen/LA.h index 79a273d237f..7e1ba4c77ca 100644 --- a/NewKernel_d/include/CGAL/NewKernel_d/LA_eigen/LA.h +++ b/NewKernel_d/include/CGAL/NewKernel_d/LA_eigen/LA.h @@ -115,12 +115,12 @@ template struct LA_eigen { return (int)v.cols(); } - template static NT determinant_aux(Mat_ const& m, Tag_true) { - CGAL_assume(false); - } - template static NT determinant_aux(Mat_ const& m, Tag_false) { - return m.determinant(); - } + template static CGAL_NORETURN NT determinant_aux(Mat_ const&, Tag_true) { + CGAL_error(); + } + template static NT determinant_aux(Mat_ const& m, Tag_false) { + return m.determinant(); + } template static NT determinant(Mat_ const&m,bool=false){ switch(m.rows()){ From 0dfd416395cf8beb748949cf271f2b11d880809c Mon Sep 17 00:00:00 2001 From: Laurent Rineau Date: Fri, 6 Mar 2020 09:26:54 +0100 Subject: [PATCH 130/568] Use [[noreturn]] directly --- Installation/include/CGAL/config.h | 10 +++------- NewKernel_d/include/CGAL/NewKernel_d/LA_eigen/LA.h | 2 +- STL_Extension/include/CGAL/assertions.h | 6 +++--- 3 files changed, 7 insertions(+), 11 deletions(-) diff --git a/Installation/include/CGAL/config.h b/Installation/include/CGAL/config.h index a215cbbf4e5..d70989b2ffb 100644 --- a/Installation/include/CGAL/config.h +++ b/Installation/include/CGAL/config.h @@ -546,13 +546,9 @@ using std::max; #endif // Macro to specify a 'noreturn' attribute. -#if defined(__GNUG__) || __has_attribute(__noreturn__) -# define CGAL_NORETURN __attribute__ ((__noreturn__)) -#elif defined (_MSC_VER) -# define CGAL_NORETURN __declspec(noreturn) -#else -# define CGAL_NORETURN -#endif +// (This macro existed in CGAL before we switched to C++11. Let's keep +// the macro defined for backward-compatibility. That cannot harm.) +#define CGAL_NORETURN [[noreturn]] // Macro to specify [[no_unique_address]] if supported #if __has_cpp_attribute(no_unique_address) diff --git a/NewKernel_d/include/CGAL/NewKernel_d/LA_eigen/LA.h b/NewKernel_d/include/CGAL/NewKernel_d/LA_eigen/LA.h index b65f47e85d0..a096445fc4a 100644 --- a/NewKernel_d/include/CGAL/NewKernel_d/LA_eigen/LA.h +++ b/NewKernel_d/include/CGAL/NewKernel_d/LA_eigen/LA.h @@ -102,7 +102,7 @@ template struct LA_eigen { return (int)v.cols(); } - template static CGAL_NORETURN NT determinant_aux(Mat_ const&, Tag_true) { + template static [[noreturn]] NT determinant_aux(Mat_ const&, Tag_true) { CGAL_error(); } template static NT determinant_aux(Mat_ const& m, Tag_false) { diff --git a/STL_Extension/include/CGAL/assertions.h b/STL_Extension/include/CGAL/assertions.h index 393a85b3484..812318028cc 100644 --- a/STL_Extension/include/CGAL/assertions.h +++ b/STL_Extension/include/CGAL/assertions.h @@ -54,9 +54,9 @@ namespace CGAL { // ===================== // failure functions // ----------------- -CGAL_EXPORT CGAL_NORETURN void assertion_fail ( const char*, const char*, int, const char* = "") ; -CGAL_EXPORT CGAL_NORETURN void precondition_fail ( const char*, const char*, int, const char* = "") ; -CGAL_EXPORT CGAL_NORETURN void postcondition_fail ( const char*, const char*, int, const char* = "") ; +CGAL_EXPORT [[noreturn]] void assertion_fail ( const char*, const char*, int, const char* = "") ; +CGAL_EXPORT [[noreturn]] void precondition_fail ( const char*, const char*, int, const char* = "") ; +CGAL_EXPORT [[noreturn]] void postcondition_fail ( const char*, const char*, int, const char* = "") ; // warning function // ---------------- From 473eeb1bd8eae9df91aa9873b86af68af4f603ee Mon Sep 17 00:00:00 2001 From: Laurent Rineau Date: Fri, 6 Mar 2020 09:43:12 +0100 Subject: [PATCH 131/568] Fix the position of the attribute (gcc warned) --- NewKernel_d/include/CGAL/NewKernel_d/LA_eigen/LA.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/NewKernel_d/include/CGAL/NewKernel_d/LA_eigen/LA.h b/NewKernel_d/include/CGAL/NewKernel_d/LA_eigen/LA.h index a096445fc4a..c3e65ea4ff8 100644 --- a/NewKernel_d/include/CGAL/NewKernel_d/LA_eigen/LA.h +++ b/NewKernel_d/include/CGAL/NewKernel_d/LA_eigen/LA.h @@ -102,7 +102,7 @@ template struct LA_eigen { return (int)v.cols(); } - template static [[noreturn]] NT determinant_aux(Mat_ const&, Tag_true) { + template static NT determinant_aux [[noreturn]] (Mat_ const&, Tag_true) { CGAL_error(); } template static NT determinant_aux(Mat_ const& m, Tag_false) { From e3a97e1e6298ed8fdd9a8d868abd7bdbb25a175a Mon Sep 17 00:00:00 2001 From: Laurent Rineau Date: Fri, 6 Mar 2020 10:31:11 +0100 Subject: [PATCH 132/568] Fix [-Wconversion] warnings with gcc --- .../CGAL/NewKernel_d/Cartesian_LA_functors.h | 4 ++-- .../include/CGAL/NewKernel_d/Lazy_cartesian.h | 20 +++++++++---------- NewKernel_d/include/CGAL/argument_swaps.h | 4 ++-- 3 files changed, 14 insertions(+), 14 deletions(-) diff --git a/NewKernel_d/include/CGAL/NewKernel_d/Cartesian_LA_functors.h b/NewKernel_d/include/CGAL/NewKernel_d/Cartesian_LA_functors.h index 17738e15332..ef0b7fffcd6 100644 --- a/NewKernel_d/include/CGAL/NewKernel_d/Cartesian_LA_functors.h +++ b/NewKernel_d/include/CGAL/NewKernel_d/Cartesian_LA_functors.h @@ -58,7 +58,7 @@ template struct Construct_LA_vector } template typename std::enable_if::value && - std::is_same, Dimension>::value, + std::is_same, Dimension>::value, result_type>::type operator()(U&&...u)const{ return typename Constructor::Values()(std::forward(u)...); @@ -66,7 +66,7 @@ template struct Construct_LA_vector //template::value>::type,class=typename std::enable_if<(sizeof...(U)==static_dim+1)>::type,class=void> template typename std::enable_if::value && - std::is_same, Dimension>::value, + std::is_same, Dimension>::value, result_type>::type operator()(U&&...u)const{ return Apply_to_last_then_rest()(typename Constructor::Values_divide(),std::forward(u)...); diff --git a/NewKernel_d/include/CGAL/NewKernel_d/Lazy_cartesian.h b/NewKernel_d/include/CGAL/NewKernel_d/Lazy_cartesian.h index 254a9bf4b84..d095d703a9e 100644 --- a/NewKernel_d/include/CGAL/NewKernel_d/Lazy_cartesian.h +++ b/NewKernel_d/include/CGAL/NewKernel_d/Lazy_cartesian.h @@ -56,10 +56,10 @@ namespace internal { // Whenever a construction takes iterator pairs as input, whether they point to double of Lazy objects, copy the ranges inside the lazy result so they are available for update_exact(). We analyze the input to try and guess where iterator pairs are. I would prefer if each functor had a specific signature (no overload in this layer) so we wouldn't have to guess. namespace Lazy_internal { templatestruct typelist{}; -templatestruct arg_i{}; -templatestruct arg_i_begin{}; -templatestruct arg_i_end{}; -templatestruct arg_i_ip1_range{}; +templatestruct arg_i{}; +templatestruct arg_i_begin{}; +templatestruct arg_i_end{}; +templatestruct arg_i_ip1_range{}; templatestruct analyze_args; templatestruct analyze_args> { typedef T creator; @@ -73,24 +73,24 @@ struct analyze_args,typelist,typelist,std::enab analyze_args>,typelist,arg_i_end>,typelist> {}; template using analyze_args_for_lazy = analyze_args,typelist<>,typelist>; templatestruct extract1; -templatestruct extract1,T>:std::tuple_element{}; -templatestruct extract1,T>{ +templatestruct extract1,T>:std::tuple_element{}; +templatestruct extract1,T>{ typedef std::tuple_element_t E; typedef std::remove_cv_t> It; typedef typename std::iterator_traits::value_type element_type; // TODO: find a way to use an array of the right size, at least for the most frequent constructions typedef std::vector type; }; -templatedecltype(auto) +templatedecltype(auto) do_extract(arg_i,std::tupleconst&t) {return std::get(t);} -templatedecltype(auto) +templatedecltype(auto) do_extract(arg_i_begin,std::tupleconst&t) {return std::begin(std::get(t));} -templatedecltype(auto) +templatedecltype(auto) do_extract(arg_i_end,std::tupleconst&t) {return std::end(std::get(t));} -templatedecltype(auto) +templatedecltype(auto) do_extract(arg_i_ip1_range,std::tupleconst&t) { typedef std::tuple L; diff --git a/NewKernel_d/include/CGAL/argument_swaps.h b/NewKernel_d/include/CGAL/argument_swaps.h index 28b183b353c..8eea20ddf03 100644 --- a/NewKernel_d/include/CGAL/argument_swaps.h +++ b/NewKernel_d/include/CGAL/argument_swaps.h @@ -18,9 +18,9 @@ namespace CGAL { namespace internal { -template struct Apply_to_last_then_rest_; +template struct Apply_to_last_then_rest_; -template +template struct Apply_to_last_then_rest_ { typedef typename Apply_to_last_then_rest_::result_type result_type; inline result_type operator()(F&&f,T&&t,U&&...u)const{ From 535a50217f963ef69fa821c51c596088c6cd0e53 Mon Sep 17 00:00:00 2001 From: Jane Tournois Date: Fri, 6 Mar 2020 17:11:45 +0100 Subject: [PATCH 133/568] avoid iterating twice --- .../internal/smooth_vertices.h | 39 ++++++++++--------- 1 file changed, 20 insertions(+), 19 deletions(-) diff --git a/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/smooth_vertices.h b/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/smooth_vertices.h index b2a76230733..85175b0114d 100644 --- a/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/smooth_vertices.h +++ b/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/smooth_vertices.h @@ -54,36 +54,37 @@ namespace CGAL { if (c3t3.is_in_complex(f)) { - const Surface_patch_index surf_i = c3t3.surface_patch_index(f); - for (int i = 0; i < 3; ++i) - { - Vertex_handle v_id = f.first->vertex(indices(f.second, i)); - normals_map[v_id][surf_i] = CGAL::NULL_VECTOR; - } - } - } + const Cell_handle ch = f.first; + const Cell_handle n_ch = f.first->neighbor(f.second); - for (const Facet& f : tr.finite_facets()) - { - const Cell_handle ch = f.first; - const Cell_handle n_ch = f.first->neighbor(f.second); + const Subdomain_index si = ch->subdomain_index(); + const Subdomain_index si_mirror = n_ch->subdomain_index(); - const Subdomain_index si = ch->subdomain_index(); - const Subdomain_index si_mirror = n_ch->subdomain_index(); - - if (c3t3.is_in_complex(f)) - { const Surface_patch_index surf_i = c3t3.surface_patch_index(f); Vector_3 n = CGAL::Tetrahedral_remeshing::normal(f, tr.geom_traits()); if (si < si_mirror || tr.is_infinite(ch)) // todo : fix this condition n = opp(n); + else if (si == si_mirror) + { + std::cout << "Check normal!" << std::endl; + } for (int i = 0; i < 3; ++i) { - Vector_3& v_n = normals_map[f.first->vertex(indices(f.second, i))][surf_i]; - v_n = v_n + n; + const Vertex_handle vi = f.first->vertex(indices(f.second, i)); + typename VertexNormalsMap::iterator patch_vector_it = normals_map.find(vi); + + if (patch_vector_it == normals_map.end() + || patch_vector_it->second.find(surf_i) == patch_vector_it->second.end()) + { + normals_map[vi][surf_i] = CGAL::NULL_VECTOR; + } + else + { + normals_map[vi][surf_i] += n; + } } } } From 440fc9da294ff4c390c000a731a616081f7c253a Mon Sep 17 00:00:00 2001 From: Jane Tournois Date: Fri, 6 Mar 2020 17:12:16 +0100 Subject: [PATCH 134/568] remove useless include --- .../Tetrahedral_remeshing/Tetrahedral_remeshing_plugin.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/Polyhedron/demo/Polyhedron/Plugins/Tetrahedral_remeshing/Tetrahedral_remeshing_plugin.cpp b/Polyhedron/demo/Polyhedron/Plugins/Tetrahedral_remeshing/Tetrahedral_remeshing_plugin.cpp index 4ba6649e96b..bfc70f4bf7c 100644 --- a/Polyhedron/demo/Polyhedron/Plugins/Tetrahedral_remeshing/Tetrahedral_remeshing_plugin.cpp +++ b/Polyhedron/demo/Polyhedron/Plugins/Tetrahedral_remeshing/Tetrahedral_remeshing_plugin.cpp @@ -10,7 +10,6 @@ #include "Scene_c3t3_item.h" #include "C3t3_type.h" -#include #include #include From 6e58599054a42da145313a74ea08735d5c88007a Mon Sep 17 00:00:00 2001 From: Jane Tournois Date: Mon, 9 Mar 2020 11:43:58 +0100 Subject: [PATCH 135/568] add package_info --- Tetrahedral_remeshing/package_info/copyright | 1 + .../package_info/dependencies | 24 +++++++++++++++++++ .../package_info/license.txt | 1 + Tetrahedral_remeshing/package_info/maintainer | 1 + 4 files changed, 27 insertions(+) create mode 100644 Tetrahedral_remeshing/package_info/copyright create mode 100644 Tetrahedral_remeshing/package_info/dependencies create mode 100644 Tetrahedral_remeshing/package_info/license.txt create mode 100644 Tetrahedral_remeshing/package_info/maintainer diff --git a/Tetrahedral_remeshing/package_info/copyright b/Tetrahedral_remeshing/package_info/copyright new file mode 100644 index 00000000000..d76cdbe60d6 --- /dev/null +++ b/Tetrahedral_remeshing/package_info/copyright @@ -0,0 +1 @@ +GeometryFactory (France) \ No newline at end of file diff --git a/Tetrahedral_remeshing/package_info/dependencies b/Tetrahedral_remeshing/package_info/dependencies new file mode 100644 index 00000000000..ac9cf1d15bf --- /dev/null +++ b/Tetrahedral_remeshing/package_info/dependencies @@ -0,0 +1,24 @@ +AABB_tree +Algebraic_foundations +Arithmetic_kernel +Cartesian_kernel +Circulator +Distance_2 +Distance_3 +Filtered_kernel +Generator +Homogeneous_kernel +Installation +Interval_support +Kernel_23 +Modular_arithmetic +Number_types +Polygon_mesh_processing +Profiling_tools +Property_map +STL_Extension +Spatial_searching +Stream_support +TDS_3 +Triangulation_3 +Union_find diff --git a/Tetrahedral_remeshing/package_info/license.txt b/Tetrahedral_remeshing/package_info/license.txt new file mode 100644 index 00000000000..8bb8efcb72b --- /dev/null +++ b/Tetrahedral_remeshing/package_info/license.txt @@ -0,0 +1 @@ +GPL (v3 or later) diff --git a/Tetrahedral_remeshing/package_info/maintainer b/Tetrahedral_remeshing/package_info/maintainer new file mode 100644 index 00000000000..dd58aa4afc8 --- /dev/null +++ b/Tetrahedral_remeshing/package_info/maintainer @@ -0,0 +1 @@ +Jane Tournois From fbf790637eb2904189826a141750494eb44c24df Mon Sep 17 00:00:00 2001 From: Laurent Rineau Date: Mon, 9 Mar 2020 16:32:26 +0100 Subject: [PATCH 136/568] Patch for MSVC and clang --- STL_Extension/include/CGAL/assertions.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/STL_Extension/include/CGAL/assertions.h b/STL_Extension/include/CGAL/assertions.h index 812318028cc..62d941f609a 100644 --- a/STL_Extension/include/CGAL/assertions.h +++ b/STL_Extension/include/CGAL/assertions.h @@ -54,9 +54,9 @@ namespace CGAL { // ===================== // failure functions // ----------------- -CGAL_EXPORT [[noreturn]] void assertion_fail ( const char*, const char*, int, const char* = "") ; -CGAL_EXPORT [[noreturn]] void precondition_fail ( const char*, const char*, int, const char* = "") ; -CGAL_EXPORT [[noreturn]] void postcondition_fail ( const char*, const char*, int, const char* = "") ; +[[noreturn]] CGAL_EXPORT void assertion_fail ( const char*, const char*, int, const char* = "") ; +[[noreturn]] CGAL_EXPORT void precondition_fail ( const char*, const char*, int, const char* = "") ; +[[noreturn]] CGAL_EXPORT void postcondition_fail ( const char*, const char*, int, const char* = "") ; // warning function // ---------------- From 378554e5a748f326a3ca84f17ea43ad8a2becd2a Mon Sep 17 00:00:00 2001 From: Laurent Rineau Date: Fri, 6 Mar 2020 16:42:23 +0100 Subject: [PATCH 137/568] Change the API of `for_compact_container`/`Compact_container_traits` Now, we have a proper pair of getter/setter, and the `void` pointer is get by a `reinterpret_cast`, instead of a union. Cc: @mglisse --- .../include/CGAL/Cell_attribute.h | 8 +- Combinatorial_map/include/CGAL/Dart.h | 4 +- .../include/CGAL/Regular_complex_d.h | 4 +- .../include/CGAL/Interval_skip_list.h | 4 +- .../include/CGAL/Compact_mesh_cell_base_3.h | 2 +- .../Periodic_3_triangulation_ds_cell_base_3.h | 2 +- ...eriodic_3_triangulation_ds_vertex_base_3.h | 4 +- .../cc_benchmark.cpp | 2 +- .../STL_Extension/CGAL/Compact_container.h | 13 ++- .../CGAL/Concurrent_compact_container.h | 8 +- .../include/CGAL/Compact_container.h | 99 +++++++++---------- .../CGAL/Concurrent_compact_container.h | 6 +- .../STL_Extension/test_Compact_container.cpp | 2 +- .../test_Compact_container_is_used.cpp | 2 +- .../test_Concurrent_compact_container.cpp | 2 +- .../Concepts/TriangulationDSFaceBase_2.h | 2 +- .../Concepts/TriangulationDSVertexBase_2.h | 2 +- .../CGAL/Triangulation_ds_face_base_2.h | 2 +- .../CGAL/Triangulation_ds_vertex_base_2.h | 2 +- .../Concepts/TriangulationDSCellBase_3.h | 2 +- .../Concepts/TriangulationDSVertexBase_3.h | 2 +- .../CGAL/Triangulation_ds_cell_base_3.h | 2 +- .../CGAL/Triangulation_ds_vertex_base_3.h | 4 +- .../Concepts/TriangulationDSFullCell.h | 2 +- .../Concepts/TriangulationDSVertex.h | 2 +- .../TDS_full_cell_default_storage_policy.h | 2 +- .../include/CGAL/Triangulation_ds_full_cell.h | 2 +- .../include/CGAL/Triangulation_ds_vertex.h | 2 +- .../CGAL/internal/Static_or_dynamic_array.h | 6 +- 29 files changed, 96 insertions(+), 100 deletions(-) diff --git a/Combinatorial_map/include/CGAL/Cell_attribute.h b/Combinatorial_map/include/CGAL/Cell_attribute.h index 3b239c5f1f9..db0fe4d3917 100644 --- a/Combinatorial_map/include/CGAL/Cell_attribute.h +++ b/Combinatorial_map/include/CGAL/Cell_attribute.h @@ -197,8 +197,8 @@ namespace CGAL { void * for_compact_container() const { return vp; } - void * & for_compact_container() - { return vp; } + void for_compact_container(void *p) + { vp = p; } private: /// Reference counting: the number of darts linked to this cell. @@ -310,8 +310,8 @@ namespace CGAL { void * for_compact_container() const { return mdart.for_compact_container(); } - void * & for_compact_container() - { return mdart.for_compact_container(); } + void for_compact_container(void *p) + { mdart.for_compact_container(p); } private: /// The dart handle associated with the cell. diff --git a/Combinatorial_map/include/CGAL/Dart.h b/Combinatorial_map/include/CGAL/Dart.h index 04d2044c481..2b13b9d7911 100644 --- a/Combinatorial_map/include/CGAL/Dart.h +++ b/Combinatorial_map/include/CGAL/Dart.h @@ -105,8 +105,8 @@ namespace CGAL { void * for_compact_container() const { return mf[0].for_compact_container(); } - void * & for_compact_container() - { return mf[0].for_compact_container(); } + void for_compact_container(void *p) + { mf[0].for_compact_container(p); } Dart_handle get_f(unsigned int i) const { diff --git a/Convex_hull_d/include/CGAL/Regular_complex_d.h b/Convex_hull_d/include/CGAL/Regular_complex_d.h index c0365871c2b..ee50aefc331 100644 --- a/Convex_hull_d/include/CGAL/Regular_complex_d.h +++ b/Convex_hull_d/include/CGAL/Regular_complex_d.h @@ -87,7 +87,7 @@ public: void* pp; void* for_compact_container() const { return pp; } - void* & for_compact_container() { return pp; } + void for_compact_container(void *p) { pp = p; } #ifdef CGAL_USE_LEDA LEDA_MEMORY(RC_vertex_d) @@ -153,7 +153,7 @@ public: void* pp; void* for_compact_container() const { return pp; } - void* & for_compact_container() { return pp; } + void for_compact_container(void *p) { pp = p; } #if 0 struct Point_const_iterator { diff --git a/Interval_skip_list/include/CGAL/Interval_skip_list.h b/Interval_skip_list/include/CGAL/Interval_skip_list.h index 172e48ebf3f..1c13f5d5cde 100644 --- a/Interval_skip_list/include/CGAL/Interval_skip_list.h +++ b/Interval_skip_list/include/CGAL/Interval_skip_list.h @@ -115,7 +115,7 @@ class Interval_for_container : public Interval_ {} void * for_compact_container() const { return p; } - void * & for_compact_container() { return p; } + void for_compact_container(void *ptr) { p = ptr; } }; @@ -457,7 +457,7 @@ class Interval_for_container : public Interval_ public: #ifdef CGAL_ISL_USE_CCC void * for_compact_container() const { return p; } - void * & for_compact_container() { return p; } + void for_compact_container(void *ptr) { p = ptr; } #endif bool operator==(const IntervalListElt& e) diff --git a/Mesh_3/include/CGAL/Compact_mesh_cell_base_3.h b/Mesh_3/include/CGAL/Compact_mesh_cell_base_3.h index ae091b60be3..cea2e2405ba 100644 --- a/Mesh_3/include/CGAL/Compact_mesh_cell_base_3.h +++ b/Mesh_3/include/CGAL/Compact_mesh_cell_base_3.h @@ -491,7 +491,7 @@ public: // For use by Compact_container. void * for_compact_container() const { return N[0].for_compact_container(); } - void * & for_compact_container() { return N[0].for_compact_container(); } + void for_compact_container(void *p) { N[0].for_compact_container(p); } // TDS internal data access functions. TDS_data& tds_data() { return _tds_data; } diff --git a/Periodic_3_triangulation_3/include/CGAL/Periodic_3_triangulation_ds_cell_base_3.h b/Periodic_3_triangulation_3/include/CGAL/Periodic_3_triangulation_ds_cell_base_3.h index f8f32f0e820..e69b2fe8dba 100644 --- a/Periodic_3_triangulation_3/include/CGAL/Periodic_3_triangulation_ds_cell_base_3.h +++ b/Periodic_3_triangulation_3/include/CGAL/Periodic_3_triangulation_ds_cell_base_3.h @@ -233,7 +233,7 @@ public: // For use by Compact_container. void * for_compact_container() const { return N[0].for_compact_container(); } - void * & for_compact_container() { return N[0].for_compact_container(); } + void for_compact_container(void *p) { N[0].for_compact_container(p); } // TDS internal data access functions. TDS_data& tds_data() { return _tds_data; } diff --git a/Periodic_3_triangulation_3/include/CGAL/Periodic_3_triangulation_ds_vertex_base_3.h b/Periodic_3_triangulation_3/include/CGAL/Periodic_3_triangulation_ds_vertex_base_3.h index 539c3278bf3..e264e523063 100644 --- a/Periodic_3_triangulation_3/include/CGAL/Periodic_3_triangulation_ds_vertex_base_3.h +++ b/Periodic_3_triangulation_3/include/CGAL/Periodic_3_triangulation_ds_vertex_base_3.h @@ -80,8 +80,8 @@ public: // For use by the Compact_container. void * for_compact_container() const { return _c.for_compact_container(); } - void * & for_compact_container() - { return _c.for_compact_container(); } + void for_compact_container(void *p) + { _c.for_compact_container(p); } private: Cell_handle _c; diff --git a/STL_Extension/benchmark/compact_container_benchmark/cc_benchmark.cpp b/STL_Extension/benchmark/compact_container_benchmark/cc_benchmark.cpp index 8daa0bcf94e..3158f09b096 100644 --- a/STL_Extension/benchmark/compact_container_benchmark/cc_benchmark.cpp +++ b/STL_Extension/benchmark/compact_container_benchmark/cc_benchmark.cpp @@ -26,7 +26,7 @@ struct Truc { Truc(int v = 0) : value(v), /*value2(v), */p(NULL) {} void * for_compact_container() const { return p; } - void * & for_compact_container() { return p; } + void for_compact_container(void *ptr) { p = ptr; } int value; int value2; diff --git a/STL_Extension/doc/STL_Extension/CGAL/Compact_container.h b/STL_Extension/doc/STL_Extension/CGAL/Compact_container.h index a4d4d902bb8..b29bdf8887c 100644 --- a/STL_Extension/doc/STL_Extension/CGAL/Compact_container.h +++ b/STL_Extension/doc/STL_Extension/CGAL/Compact_container.h @@ -30,10 +30,9 @@ Returns the pointer necessary for `Compact_container_traits`. void * for_compact_container() const; /*! -Returns a reference to the pointer necessary for -`Compact_container_traits`. +Sets the pointer necessary for `Compact_container_traits` to `p`. */ -void * & for_compact_container(); +void for_compact_container(void* p); /// @} @@ -796,7 +795,7 @@ types `T` to make them usable with the default `Compact_container_traits`. `void * t.for_compact_container() const;` -`void *& t.for_compact_container();`. +`void t.for_compact_container(void *);`. */ @@ -820,11 +819,11 @@ static void * pointer(const T &t); /// \name Operations /// @{ /*! -Returns a reference to the pointer held by `t`. -The template version defines this function as: `return t.for_compact_container();` +Sets the pointer held by `t` to `p`. +The template version defines this function as: `t.for_compact_container(p);` */ -static void * & pointer(T &t); + static void set_pointer(T &t, void* p); diff --git a/STL_Extension/doc/STL_Extension/CGAL/Concurrent_compact_container.h b/STL_Extension/doc/STL_Extension/CGAL/Concurrent_compact_container.h index 74c2ce4d5d7..8f55b19bb7f 100644 --- a/STL_Extension/doc/STL_Extension/CGAL/Concurrent_compact_container.h +++ b/STL_Extension/doc/STL_Extension/CGAL/Concurrent_compact_container.h @@ -22,7 +22,7 @@ types `T` to make them usable with the default `Concurrent_compact_container`. `T` is any type providing the following member functions: `void * t.for_compact_container() const;` -`void *& t.for_compact_container();`. +`void t.for_compact_container(void *);`. */ template< typename T > struct Concurrent_compact_container_traits { @@ -40,11 +40,11 @@ struct Concurrent_compact_container_traits { /// \name Operations /// @{ /*! - Returns a reference to the pointer held by `t`. - The template version defines this function as: `return t.for_compact_container();` + Sets the pointer held by `t` to `p`. + The template version defines this function as: `t.for_compact_container(p);` */ - static void * & pointer(T &t); + static void set_pointer(T &t, void* p); /// @} diff --git a/STL_Extension/include/CGAL/Compact_container.h b/STL_Extension/include/CGAL/Compact_container.h index f6946fc2758..2781d5befe9 100644 --- a/STL_Extension/include/CGAL/Compact_container.h +++ b/STL_Extension/include/CGAL/Compact_container.h @@ -149,15 +149,15 @@ public: Compact_container_base() : p(nullptr) {} void * for_compact_container() const { return p; } - void * & for_compact_container() { return p; } + void for_compact_container(void* ptr) { p = ptr; } }; // The traits class describes the way to access the pointer. // It can be specialized. template < class T > struct Compact_container_traits { - static void * pointer(const T &t) { return t.for_compact_container(); } - static void * & pointer(T &t) { return t.for_compact_container(); } + static void * pointer(const T &t) { return t.for_compact_container(); } + static void set_pointer(T &t, void* p) { t.for_compact_container(p); } }; namespace internal { @@ -645,8 +645,8 @@ private: // This out of range compare is always true and causes lots of // unnecessary warnings. // CGAL_precondition(0 <= t && t < 4); - Traits::pointer(*ptr) = reinterpret_cast - (reinterpret_cast(clean_pointer((char *) p)) + (int) t); + Traits::set_pointer(*ptr, reinterpret_cast + (reinterpret_cast(clean_pointer((char *) p)) + (int) t)); } public: @@ -872,7 +872,7 @@ namespace internal { : ts(0) #endif { - m_ptr.p = nullptr; + m_ptr = nullptr; } CC_iterator (const CC_iterator &it) @@ -880,7 +880,7 @@ namespace internal { : ts(Time_stamper::time_stamp(it.operator->())) #endif { - m_ptr.p = it.operator->(); + m_ptr = it.operator->(); } // Converting constructor from mutable to constant iterator @@ -892,7 +892,7 @@ namespace internal { : ts(Time_stamper::time_stamp(const_it.operator->())) #endif { - m_ptr.p = const_it.operator->(); + m_ptr = const_it.operator->(); } // Assignment operator from mutable to constant iterator @@ -901,7 +901,7 @@ namespace internal { typename std::enable_if<(!OtherConst && Const), DSC>::type, OtherConst> &const_it) { - m_ptr.p = const_it.operator->(); + m_ptr = const_it.operator->(); #ifdef CGAL_COMPACT_CONTAINER_DEBUG_TIME_STAMP ts = Time_stamper::time_stamp(const_it.operator->()); #endif @@ -920,7 +920,7 @@ namespace internal { #endif { CGAL_assertion (n == nullptr); - m_ptr.p = nullptr; + m_ptr = nullptr; } private: @@ -929,10 +929,7 @@ namespace internal { #ifdef CGAL_COMPACT_CONTAINER_DEBUG_TIME_STAMP std::size_t ts; #endif - union { - pointer p; - void *vp; - } m_ptr; + pointer m_ptr; // Only Compact_container and Concurrent_compact_container should // access these constructors. @@ -948,16 +945,16 @@ namespace internal { : ts(0) #endif { - m_ptr.p = ptr; - if (m_ptr.p == nullptr) // empty container. + m_ptr = ptr; + if (m_ptr == nullptr) // empty container. return; - ++(m_ptr.p); // if not empty, p = start - if (DSC::type(m_ptr.p) == DSC::FREE) + ++(m_ptr); // if not empty, p = start + if (DSC::type(m_ptr) == DSC::FREE) increment(); #ifdef CGAL_COMPACT_CONTAINER_DEBUG_TIME_STAMP else - ts = Time_stamper::time_stamp(m_ptr.p); + ts = Time_stamper::time_stamp(m_ptr); #endif // CGAL_COMPACT_CONTAINER_DEBUG_TIME_STAMP } @@ -967,10 +964,10 @@ namespace internal { : ts(0) #endif { - m_ptr.p = ptr; + m_ptr = ptr; #ifdef CGAL_COMPACT_CONTAINER_DEBUG_TIME_STAMP if(ptr != nullptr){ - ts = Time_stamper::time_stamp(m_ptr.p); + ts = Time_stamper::time_stamp(m_ptr); } #endif // end CGAL_COMPACT_CONTAINER_DEBUG_TIME_STAMP } @@ -979,49 +976,49 @@ namespace internal { void increment() { // It's either pointing to end(), or valid. - CGAL_assertion_msg(m_ptr.p != nullptr, + CGAL_assertion_msg(m_ptr != nullptr, "Incrementing a singular iterator or an empty container iterator ?"); - CGAL_assertion_msg(DSC::type(m_ptr.p) != DSC::START_END, + CGAL_assertion_msg(DSC::type(m_ptr) != DSC::START_END, "Incrementing end() ?"); // If it's not end(), then it's valid, we can do ++. do { - ++(m_ptr.p); - if (DSC::type(m_ptr.p) == DSC::USED || - DSC::type(m_ptr.p) == DSC::START_END) + ++(m_ptr); + if (DSC::type(m_ptr) == DSC::USED || + DSC::type(m_ptr) == DSC::START_END) { #ifdef CGAL_COMPACT_CONTAINER_DEBUG_TIME_STAMP - ts = Time_stamper::time_stamp(m_ptr.p); + ts = Time_stamper::time_stamp(m_ptr); #endif return; } - if (DSC::type(m_ptr.p) == DSC::BLOCK_BOUNDARY) - m_ptr.p = DSC::clean_pointee(m_ptr.p); + if (DSC::type(m_ptr) == DSC::BLOCK_BOUNDARY) + m_ptr = DSC::clean_pointee(m_ptr); } while (true); } void decrement() { // It's either pointing to end(), or valid. - CGAL_assertion_msg(m_ptr.p != nullptr, + CGAL_assertion_msg(m_ptr != nullptr, "Decrementing a singular iterator or an empty container iterator ?"); - CGAL_assertion_msg(DSC::type(m_ptr.p - 1) != DSC::START_END, + CGAL_assertion_msg(DSC::type(m_ptr - 1) != DSC::START_END, "Decrementing begin() ?"); // If it's not begin(), then it's valid, we can do --. do { - --m_ptr.p; - if (DSC::type(m_ptr.p) == DSC::USED || - DSC::type(m_ptr.p) == DSC::START_END) + --m_ptr; + if (DSC::type(m_ptr) == DSC::USED || + DSC::type(m_ptr) == DSC::START_END) { #ifdef CGAL_COMPACT_CONTAINER_DEBUG_TIME_STAMP - ts = Time_stamper::time_stamp(m_ptr.p); + ts = Time_stamper::time_stamp(m_ptr); #endif return; } - if (DSC::type(m_ptr.p) == DSC::BLOCK_BOUNDARY) - m_ptr.p = DSC::clean_pointee(m_ptr.p); + if (DSC::type(m_ptr) == DSC::BLOCK_BOUNDARY) + m_ptr = DSC::clean_pointee(m_ptr); } while (true); } @@ -1029,9 +1026,9 @@ namespace internal { Self & operator++() { - CGAL_assertion_msg(m_ptr.p != nullptr, + CGAL_assertion_msg(m_ptr != nullptr, "Incrementing a singular iterator or an empty container iterator ?"); - /* CGAL_assertion_msg(DSC::type(m_ptr.p) == DSC::USED, + /* CGAL_assertion_msg(DSC::type(m_ptr) == DSC::USED, "Incrementing an invalid iterator."); */ increment(); return *this; @@ -1039,10 +1036,10 @@ namespace internal { Self & operator--() { - CGAL_assertion_msg(m_ptr.p != nullptr, + CGAL_assertion_msg(m_ptr != nullptr, "Decrementing a singular iterator or an empty container iterator ?"); - /*CGAL_assertion_msg(DSC::type(m_ptr.p) == DSC::USED - || DSC::type(m_ptr.p) == DSC::START_END, + /*CGAL_assertion_msg(DSC::type(m_ptr) == DSC::USED + || DSC::type(m_ptr) == DSC::START_END, "Decrementing an invalid iterator.");*/ decrement(); return *this; @@ -1054,13 +1051,13 @@ namespace internal { #ifdef CGAL_COMPACT_CONTAINER_DEBUG_TIME_STAMP bool is_time_stamp_valid() const { - return (ts == 0) || (ts == Time_stamper::time_stamp(m_ptr.p)); + return (ts == 0) || (ts == Time_stamper::time_stamp(m_ptr)); } #endif // CGAL_COMPACT_CONTAINER_DEBUG_TIME_STAMP - reference operator*() const { return *(m_ptr.p); } + reference operator*() const { return *(m_ptr); } - pointer operator->() const { return (m_ptr.p); } + pointer operator->() const { return (m_ptr); } // For std::less... bool operator<(const CC_iterator& other) const @@ -1068,7 +1065,7 @@ namespace internal { #ifdef CGAL_COMPACT_CONTAINER_DEBUG_TIME_STAMP assert( is_time_stamp_valid() ); #endif - return Time_stamper::less(m_ptr.p, other.m_ptr.p); + return Time_stamper::less(m_ptr, other.m_ptr); } bool operator>(const CC_iterator& other) const @@ -1076,7 +1073,7 @@ namespace internal { #ifdef CGAL_COMPACT_CONTAINER_DEBUG_TIME_STAMP assert( is_time_stamp_valid() ); #endif - return Time_stamper::less(other.m_ptr.p, m_ptr.p); + return Time_stamper::less(other.m_ptr, m_ptr); } bool operator<=(const CC_iterator& other) const @@ -1084,7 +1081,7 @@ namespace internal { #ifdef CGAL_COMPACT_CONTAINER_DEBUG_TIME_STAMP assert( is_time_stamp_valid() ); #endif - return Time_stamper::less(m_ptr.p, other.m_ptr.p) + return Time_stamper::less(m_ptr, other.m_ptr) || (*this == other); } @@ -1093,13 +1090,13 @@ namespace internal { #ifdef CGAL_COMPACT_CONTAINER_DEBUG_TIME_STAMP assert( is_time_stamp_valid() ); #endif - return Time_stamper::less(other.m_ptr.p, m_ptr.p) + return Time_stamper::less(other.m_ptr, m_ptr) || (*this == other); } // Can itself be used for bit-squatting. - void * for_compact_container() const { return (m_ptr.vp); } - void * & for_compact_container() { return (m_ptr.vp); } + void * for_compact_container() const { return m_ptr; } + void for_compact_container(void* p) { m_ptr = static_cast(p); } }; template < class DSC, bool Const1, bool Const2 > diff --git a/STL_Extension/include/CGAL/Concurrent_compact_container.h b/STL_Extension/include/CGAL/Concurrent_compact_container.h index e968312c453..4d644e547b8 100644 --- a/STL_Extension/include/CGAL/Concurrent_compact_container.h +++ b/STL_Extension/include/CGAL/Concurrent_compact_container.h @@ -66,7 +66,7 @@ template class has_##X { \ template < class T > struct Concurrent_compact_container_traits { static void * pointer(const T &t) { return t.for_compact_container(); } - static void * & pointer(T &t) { return t.for_compact_container(); } + static void set_pointer(T &t, void* p) { t.for_compact_container(p); } }; namespace CCC_internal { @@ -613,8 +613,8 @@ private: // This out of range compare is always true and causes lots of // unnecessary warnings. // CGAL_precondition(0 <= t && t < 4); - Traits::pointer(*ptr) = reinterpret_cast - (reinterpret_cast(clean_pointer((char *) p)) + (int) t); + Traits::set_pointer(*ptr, reinterpret_cast + (reinterpret_cast(clean_pointer((char *) p)) + (int) t)); } typedef tbb::queuing_mutex Mutex; diff --git a/STL_Extension/test/STL_Extension/test_Compact_container.cpp b/STL_Extension/test/STL_Extension/test_Compact_container.cpp index 3d370105a6a..e84d79fecfc 100644 --- a/STL_Extension/test/STL_Extension/test_Compact_container.cpp +++ b/STL_Extension/test/STL_Extension/test_Compact_container.cpp @@ -72,7 +72,7 @@ public: bool operator< (const Node_2 &n) const { return rnd < n.rnd; } void * for_compact_container() const { return p_cc; } - void * & for_compact_container() { return p_cc; } + void for_compact_container(void *p) { p_cc = p; } }; template < class Cont > diff --git a/STL_Extension/test/STL_Extension/test_Compact_container_is_used.cpp b/STL_Extension/test/STL_Extension/test_Compact_container_is_used.cpp index aac89dc61d5..2d810602cde 100644 --- a/STL_Extension/test/STL_Extension/test_Compact_container_is_used.cpp +++ b/STL_Extension/test/STL_Extension/test_Compact_container_is_used.cpp @@ -15,7 +15,7 @@ public: {} void * for_compact_container() const { return p_cc; } - void * & for_compact_container() { return p_cc; } + void for_compact_container(void *p) { p_cc = p; } }; int main() diff --git a/STL_Extension/test/STL_Extension/test_Concurrent_compact_container.cpp b/STL_Extension/test/STL_Extension/test_Concurrent_compact_container.cpp index 84a65304eb1..95f92dba74c 100644 --- a/STL_Extension/test/STL_Extension/test_Concurrent_compact_container.cpp +++ b/STL_Extension/test/STL_Extension/test_Concurrent_compact_container.cpp @@ -67,7 +67,7 @@ public: bool operator< (const Node_2 &n) const { return rnd < n.rnd; } void * for_compact_container() const { return p_cc; } - void * & for_compact_container() { return p_cc; } + void for_compact_container(void *p) { p_cc = p; } }; template < class Cont > diff --git a/TDS_2/doc/TDS_2/Concepts/TriangulationDSFaceBase_2.h b/TDS_2/doc/TDS_2/Concepts/TriangulationDSFaceBase_2.h index 8ef6ea99deb..71ae4e585af 100644 --- a/TDS_2/doc/TDS_2/Concepts/TriangulationDSFaceBase_2.h +++ b/TDS_2/doc/TDS_2/Concepts/TriangulationDSFaceBase_2.h @@ -183,7 +183,7 @@ void * for_compact_container() const; /*! */ -void * & for_compact_container(); +void for_compact_container(void *p); /// @} diff --git a/TDS_2/doc/TDS_2/Concepts/TriangulationDSVertexBase_2.h b/TDS_2/doc/TDS_2/Concepts/TriangulationDSVertexBase_2.h index e7915a48888..dcd30aa9f07 100644 --- a/TDS_2/doc/TDS_2/Concepts/TriangulationDSVertexBase_2.h +++ b/TDS_2/doc/TDS_2/Concepts/TriangulationDSVertexBase_2.h @@ -118,7 +118,7 @@ void * for_compact_container() const; /*! */ -void * & for_compact_container(); +void for_compact_container(void* p); /// @} diff --git a/TDS_2/include/CGAL/Triangulation_ds_face_base_2.h b/TDS_2/include/CGAL/Triangulation_ds_face_base_2.h index 8de378eec8f..8aeb12f876e 100644 --- a/TDS_2/include/CGAL/Triangulation_ds_face_base_2.h +++ b/TDS_2/include/CGAL/Triangulation_ds_face_base_2.h @@ -79,7 +79,7 @@ public: // For use by Compact_container. void * for_compact_container() const {return N[0].for_compact_container(); } - void * & for_compact_container() { return N[0].for_compact_container();} + void for_compact_container(void* p) { N[0].for_compact_container(p);} static int ccw(int i) {return Triangulation_cw_ccw_2::ccw(i);} diff --git a/TDS_2/include/CGAL/Triangulation_ds_vertex_base_2.h b/TDS_2/include/CGAL/Triangulation_ds_vertex_base_2.h index 6b4906e6566..ceabf7c4294 100644 --- a/TDS_2/include/CGAL/Triangulation_ds_vertex_base_2.h +++ b/TDS_2/include/CGAL/Triangulation_ds_vertex_base_2.h @@ -49,7 +49,7 @@ public: // For use by the Compact_container. void * for_compact_container() const { return _f.for_compact_container(); } - void * & for_compact_container() { return _f.for_compact_container(); } + void for_compact_container(void* p) { _f.for_compact_container(p); } private: Face_handle _f; diff --git a/TDS_3/doc/TDS_3/Concepts/TriangulationDSCellBase_3.h b/TDS_3/doc/TDS_3/Concepts/TriangulationDSCellBase_3.h index 2856e1d70bd..9b9bffacd71 100644 --- a/TDS_3/doc/TDS_3/Concepts/TriangulationDSCellBase_3.h +++ b/TDS_3/doc/TDS_3/Concepts/TriangulationDSCellBase_3.h @@ -136,7 +136,7 @@ void * for_compact_container() const; /*! */ -void * & for_compact_container(); +void for_compact_container(void *p); /// @} diff --git a/TDS_3/doc/TDS_3/Concepts/TriangulationDSVertexBase_3.h b/TDS_3/doc/TDS_3/Concepts/TriangulationDSVertexBase_3.h index e1d35cb88fc..c7b68ec9175 100644 --- a/TDS_3/doc/TDS_3/Concepts/TriangulationDSVertexBase_3.h +++ b/TDS_3/doc/TDS_3/Concepts/TriangulationDSVertexBase_3.h @@ -116,7 +116,7 @@ void * for_compact_container() const; /*! */ -void * & for_compact_container(); +void for_compact_container(void *); /*! Inputs the non-combinatorial information given by the vertex. diff --git a/TDS_3/include/CGAL/Triangulation_ds_cell_base_3.h b/TDS_3/include/CGAL/Triangulation_ds_cell_base_3.h index e6ad17ca862..f8449c7eb8c 100644 --- a/TDS_3/include/CGAL/Triangulation_ds_cell_base_3.h +++ b/TDS_3/include/CGAL/Triangulation_ds_cell_base_3.h @@ -180,7 +180,7 @@ public: // For use by Compact_container. void * for_compact_container() const { return N[0].for_compact_container(); } - void * & for_compact_container() { return N[0].for_compact_container(); } + void for_compact_container(void* p) { N[0].for_compact_container(p); } // TDS internal data access functions. TDS_data& tds_data() { return _tds_data; } diff --git a/TDS_3/include/CGAL/Triangulation_ds_vertex_base_3.h b/TDS_3/include/CGAL/Triangulation_ds_vertex_base_3.h index d6c5d38a057..f338340b50a 100644 --- a/TDS_3/include/CGAL/Triangulation_ds_vertex_base_3.h +++ b/TDS_3/include/CGAL/Triangulation_ds_vertex_base_3.h @@ -59,8 +59,8 @@ public: // For use by the Compact_container. void * for_compact_container() const { return _c.for_compact_container(); } - void * & for_compact_container() - { return _c.for_compact_container(); } + void for_compact_container(void* p) + { _c.for_compact_container(p); } private: Cell_handle _c; diff --git a/Triangulation/doc/Triangulation/Concepts/TriangulationDSFullCell.h b/Triangulation/doc/Triangulation/Concepts/TriangulationDSFullCell.h index df05688010a..b25a2a7a81c 100644 --- a/Triangulation/doc/Triangulation/Concepts/TriangulationDSFullCell.h +++ b/Triangulation/doc/Triangulation/Concepts/TriangulationDSFullCell.h @@ -107,7 +107,7 @@ void * for_compact_container() const; /*! */ -void * & for_compact_container(); +void for_compact_container(void *p); /// @} diff --git a/Triangulation/doc/Triangulation/Concepts/TriangulationDSVertex.h b/Triangulation/doc/Triangulation/Concepts/TriangulationDSVertex.h index 0366254ca89..903da560d1c 100644 --- a/Triangulation/doc/Triangulation/Concepts/TriangulationDSVertex.h +++ b/Triangulation/doc/Triangulation/Concepts/TriangulationDSVertex.h @@ -106,7 +106,7 @@ void * for_compact_container() const; /*! */ -void * & for_compact_container(); +void for_compact_container(void *p); /// @} diff --git a/Triangulation/include/CGAL/TDS_full_cell_default_storage_policy.h b/Triangulation/include/CGAL/TDS_full_cell_default_storage_policy.h index d5f0735c8e8..3b6508f6017 100644 --- a/Triangulation/include/CGAL/TDS_full_cell_default_storage_policy.h +++ b/Triangulation/include/CGAL/TDS_full_cell_default_storage_policy.h @@ -44,7 +44,7 @@ struct TFC_data< Vertex_handle, Full_cell_handle, Dimen, TDS_full_cell_default_s : vertices_(dmax+1), neighbors_(dmax+1) {} void* for_compact_container() const { return vertices_.for_compact_container(); } - void* & for_compact_container() { return vertices_.for_compact_container(); } + void for_compact_container(void *p){ vertices_.for_compact_container(p); } int dimension() const { return ( vertices_.size() - 1 ); } void set_mirror_index(const int, const int) {} #ifdef BOOST_NO_INT64_T diff --git a/Triangulation/include/CGAL/Triangulation_ds_full_cell.h b/Triangulation/include/CGAL/Triangulation_ds_full_cell.h index 125cc2e443f..83b48a441d5 100644 --- a/Triangulation/include/CGAL/Triangulation_ds_full_cell.h +++ b/Triangulation/include/CGAL/Triangulation_ds_full_cell.h @@ -204,7 +204,7 @@ public: TDS_data & tds_data() { return tds_data_; } /* Concept */ void* for_compact_container() const { return combinatorics_.for_compact_container(); } - void* & for_compact_container() { return combinatorics_.for_compact_container(); } + void for_compact_container(void* p){ combinatorics_.for_compact_container(p); } bool is_valid(bool verbose = false, int = 0) const /* Concept */ { diff --git a/Triangulation/include/CGAL/Triangulation_ds_vertex.h b/Triangulation/include/CGAL/Triangulation_ds_vertex.h index a4f47d05647..c57bfbed51a 100644 --- a/Triangulation/include/CGAL/Triangulation_ds_vertex.h +++ b/Triangulation/include/CGAL/Triangulation_ds_vertex.h @@ -102,7 +102,7 @@ public: public: // FOR MEMORY MANAGEMENT void* for_compact_container() const { return full_cell_.for_compact_container(); } - void* & for_compact_container() { return full_cell_.for_compact_container(); } + void for_compact_container(void *p){ full_cell_.for_compact_container(p); } }; // end of Triangulation_ds_vertex diff --git a/Triangulation/include/CGAL/internal/Static_or_dynamic_array.h b/Triangulation/include/CGAL/internal/Static_or_dynamic_array.h index f198464e874..54fca5abaea 100644 --- a/Triangulation/include/CGAL/internal/Static_or_dynamic_array.h +++ b/Triangulation/include/CGAL/internal/Static_or_dynamic_array.h @@ -66,9 +66,9 @@ struct S_or_D_array< Containee, Dimension_tag< D >, WithCompactContainerHelper > { return (*this)[0].for_compact_container(); } - void* & for_compact_container() + void for_compact_container(void *p) { - return (*this)[0].for_compact_container(); + (*this)[0].for_compact_container(p); } }; @@ -101,7 +101,7 @@ struct S_or_D_array< Containee, Dynamic_dimension_tag, true > {} void* fcc_; void* for_compact_container() const { return fcc_; } - void* & for_compact_container() { return fcc_; } + void for_compact_container(void* p) { fcc_ = p; } }; } // end of namespace internal From 1eba82246e824cfa10934ad750ce781d325d84e6 Mon Sep 17 00:00:00 2001 From: Laurent Rineau Date: Mon, 9 Mar 2020 17:35:12 +0100 Subject: [PATCH 138/568] Rule of zero for CC_iterator This commit is the one fixing the mis-compilation by MSVC 2015. --- STL_Extension/include/CGAL/Compact_container.h | 13 ------------- 1 file changed, 13 deletions(-) diff --git a/STL_Extension/include/CGAL/Compact_container.h b/STL_Extension/include/CGAL/Compact_container.h index 2781d5befe9..1536c229ded 100644 --- a/STL_Extension/include/CGAL/Compact_container.h +++ b/STL_Extension/include/CGAL/Compact_container.h @@ -875,14 +875,6 @@ namespace internal { m_ptr = nullptr; } - CC_iterator (const CC_iterator &it) -#ifdef CGAL_COMPACT_CONTAINER_DEBUG_TIME_STAMP - : ts(Time_stamper::time_stamp(it.operator->())) -#endif - { - m_ptr = it.operator->(); - } - // Converting constructor from mutable to constant iterator template CC_iterator(const CC_iterator< @@ -908,11 +900,6 @@ namespace internal { return *this; } - CC_iterator(CC_iterator&& it) = default; - ~CC_iterator() = default; - CC_iterator& operator=(const CC_iterator&) = default; - CC_iterator& operator=(CC_iterator&&) = default; - // Construction from nullptr CC_iterator (std::nullptr_t CGAL_assertion_code(n)) #ifdef CGAL_COMPACT_CONTAINER_DEBUG_TIME_STAMP From f85e8549cf165740bd1b44faed37c5f033ccd0cc Mon Sep 17 00:00:00 2001 From: Jane Tournois Date: Tue, 10 Mar 2020 11:42:47 +0100 Subject: [PATCH 139/568] make smoothing code as close as possible to original MAD mesher code to fix bugs with this version : - internal smoothing works perfectly - surface smoothing is still broken --- .../internal/smooth_vertices.h | 151 +++++++++--------- .../internal/tetrahedral_remeshing_helpers.h | 2 +- 2 files changed, 79 insertions(+), 74 deletions(-) diff --git a/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/smooth_vertices.h b/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/smooth_vertices.h index 85175b0114d..65d7f4a765c 100644 --- a/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/smooth_vertices.h +++ b/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/smooth_vertices.h @@ -8,6 +8,7 @@ #include #include +#include #include @@ -21,13 +22,13 @@ namespace CGAL namespace internal { template - CGAL::Vector_3 project_on_tangent_plane(const CGAL::Point_3& gi, - const CGAL::Point_3& pi, + CGAL::Vector_3 project_on_tangent_plane(const CGAL::Vector_3& gi, + const CGAL::Vector_3& pi, const CGAL::Vector_3& normal) { - typedef typename Gt::Vector_3 Vector_3; + typedef CGAL::Vector_3 Vector_3; Vector_3 diff = pi - gi; - return Vector_3(gi, gi + (normal * diff) * normal); + return gi + (normal * diff) * normal; } template @@ -126,9 +127,9 @@ namespace CGAL return false; } - Vector_3 res_normal; - Point_3 point; - Point_3 result = CGAL::ORIGIN + gi; + Vec3Df point(gi.x(), gi.y(), gi.z()); + Vec3Df res_normal; + Vec3Df result(point); CGAL::Tetrahedral_remeshing::internal::FMLS& fmls = subdomain_FMLS[subdomain_FMLS_indices.at(si)]; @@ -148,10 +149,11 @@ namespace CGAL std::cout << "MLS error detected si size " << si << " : " << fmls.getPNSize() << std::endl; return false; + } } - } while (CGAL::squared_distance(result, point) > sq_eps && ++it_nb < max_it_nb); + while ((result - point).getSquaredLength() > sq_eps && ++it_nb < max_it_nb); - projected_point = Vector_3(result.x(), result.y(), result.z()); + projected_point = Vector_3(result[0], result[1], result[2]); return true; } @@ -307,7 +309,7 @@ namespace CGAL //smooth() const std::size_t nbv = tr.number_of_vertices(); boost::unordered_map vertex_id; - std::vector smoothing_vecs(nbv, CGAL::NULL_VECTOR); + std::vector smoothed_positions(nbv, CGAL::NULL_VECTOR); std::vector neighbors(nbv, -1); //collect ids @@ -340,13 +342,13 @@ namespace CGAL if (update_v0) { const Point_3& p1 = point(vh1->point()); - smoothing_vecs[i0] = smoothing_vecs[i0] + Vector_3(p1.x(), p1.y(), p1.z()); + smoothed_positions[i0] = smoothed_positions[i0] + Vector_3(p1.x(), p1.y(), p1.z()); neighbors[i0]++; } if (update_v1) { const Point_3& p0 = point(vh0->point()); - smoothing_vecs[i1] = smoothing_vecs[i1] + Vector_3(p0.x(), p0.y(), p0.z()); + smoothed_positions[i1] = smoothed_positions[i1] + Vector_3(p0.x(), p0.y(), p0.z()); neighbors[i1]++; } } @@ -358,77 +360,75 @@ namespace CGAL const std::size_t& vid = vertex_id.at(v); if (neighbors[vid] > 1) { - Point_3 smoothed_position = CGAL::ORIGIN + smoothing_vecs[vid] / neighbors[vid]; - Vector_3 final_move = CGAL::NULL_VECTOR; - Point_3 final_position = CGAL::ORIGIN; + Vector_3 smoothed_position = smoothed_positions[vid] / neighbors[vid]; + Vector_3 final_position = CGAL::NULL_VECTOR; std::size_t count = 0; - const Point_3 current_pos = point(v->point()); + const Vector_3 current_pos(CGAL::ORIGIN, point(v->point())); const std::vector& v_surface_indices = vertices_surface_indices[v]; - for (std::size_t i = 0; i < v_surface_indices.size(); ++i) + for (const Surface_patch_index& si : v_surface_indices) { - const Surface_patch_index& si = v_surface_indices[i]; - Vector_3 normal_projection = project_on_tangent_plane(smoothed_position, current_pos, vertices_normals[v][si]); //Check if the mls surface exists to avoid degenrated cases Vector_3 mls_projection; if (project(si, normal_projection, mls_projection, subdomain_FMLS, subdomain_FMLS_indices)) { - final_move = final_move + mls_projection; + std::cout << "project OK" << std::endl; + final_position = final_position + mls_projection; } else { - final_move = final_move + normal_projection; + final_position = final_position + normal_projection; } count++; } if (count > 0) - final_position = CGAL::ORIGIN + final_move / static_cast(count); + final_position = final_position / static_cast(count); else final_position = smoothed_position; // move vertex - v->set_point(typename Tr::Point(final_position)); + v->set_point(typename Tr::Point( + final_position.x(), final_position.y(), final_position.z())); } else if (neighbors[vid] > 0) { - Vector_3 final_move = CGAL::NULL_VECTOR; - Point_3 final_position; + Vector_3 final_position = CGAL::NULL_VECTOR; int count = 0; - Vector_3 current_move(CGAL::ORIGIN, point(v->point())); + const Vector_3 current_pos(CGAL::ORIGIN, point(v->point())); const std::vector& v_surface_indices = vertices_surface_indices[v]; - for (std::size_t i = 0; i < v_surface_indices.size(); ++i) + for (const Surface_patch_index si : v_surface_indices) { - Surface_patch_index si = v_surface_indices[i]; //Check if the mls surface exists to avoid degenrated cases Vector_3 mls_projection; - if (project(si, current_move, mls_projection, subdomain_FMLS, subdomain_FMLS_indices)) { - final_move = final_move + mls_projection; + if (project(si, current_pos, mls_projection, subdomain_FMLS, subdomain_FMLS_indices)) { + final_position = final_position + mls_projection; } else { - final_move = final_move + current_move; + final_position = final_position + current_pos; } count++; } if (count > 0) - final_position = CGAL::ORIGIN + final_move / count; + final_position = final_position / static_cast(count); else - final_position = CGAL::ORIGIN + current_move; + final_position = current_pos; // move vertex - v->set_point(typename Tr::Point(final_position)); + v->set_point( + typename Tr::Point(final_position.x(), final_position.y(), final_position.z())); } } - smoothing_vecs.clear(); - smoothing_vecs.resize(nbv, CGAL::NULL_VECTOR); + smoothed_positions.clear(); + smoothed_positions.resize(nbv, CGAL::NULL_VECTOR); neighbors.clear(); neighbors.resize(nbv, -1); @@ -453,13 +453,13 @@ namespace CGAL if (update_v0) { const Point_3& p1 = point(vh1->point()); - smoothing_vecs[i0] = smoothing_vecs[i0] + Vector_3(p1.x(), p1.y(), p1.z()); + smoothed_positions[i0] = smoothed_positions[i0] + Vector_3(p1.x(), p1.y(), p1.z()); neighbors[i0]++; } if (update_v1) { const Point_3& p0 = point(vh0->point()); - smoothing_vecs[i1] = smoothing_vecs[i1] + Vector_3(p0.x(), p0.y(), p0.z()); + smoothed_positions[i1] = smoothed_positions[i1] + Vector_3(p0.x(), p0.y(), p0.z()); neighbors[i1]++; } } @@ -471,18 +471,18 @@ namespace CGAL if (neighbors[vid] > 1) { - Point_3 smoothed_position = CGAL::ORIGIN + smoothing_vecs[vid] / neighbors[vid]; - const Point_3& current_pos = point(v->point()); - Point_3 final_position = CGAL::ORIGIN; + Vector_3 smoothed_position = smoothed_positions[vid] / static_cast(neighbors[vid]); + const Vector_3 current_pos(CGAL::ORIGIN, point(v->point())); + Vector_3 final_position = CGAL::NULL_VECTOR; if (v->in_dimension() == 3 && is_on_convex_hull(v, c3t3)) { - Vector_3 final_move = project_on_tangent_plane( + final_position = project_on_tangent_plane( smoothed_position, current_pos, vertices_normals[v][Surface_patch_index()]); - final_position = CGAL::ORIGIN + final_move; } else { const Surface_patch_index si = surface_patch_index(v, c3t3); + CGAL_assertion(si != Surface_patch_index()); Vector_3 normal_projection = project_on_tangent_plane(smoothed_position, current_pos, @@ -490,7 +490,7 @@ namespace CGAL Vector_3 mls_projection; if (project(si, normal_projection, mls_projection, subdomain_FMLS, subdomain_FMLS_indices) /*|| project( si, smoothed_position, mls_projection )*/){ - final_position = CGAL::ORIGIN + mls_projection; + final_position = mls_projection; } else { final_position = smoothed_position; @@ -498,7 +498,8 @@ namespace CGAL // std::cout << "MLS " << final_position[0] << " - " << final_position[1] << " : " << final_position[2] << std::endl; } - v->set_point(typename Tr::Point(final_position)); + v->set_point(typename Tr::Point( + final_position.x(), final_position.y(), final_position.z())); } else if (neighbors[vid] > 0) { @@ -518,8 +519,9 @@ namespace CGAL } } } - smoothing_vecs.clear(); - smoothing_vecs.resize(nbv, CGAL::NULL_VECTOR); + + smoothed_positions.clear(); + smoothed_positions.resize(nbv, CGAL::NULL_VECTOR); neighbors.clear(); neighbors.resize(nbv, 0); @@ -537,13 +539,13 @@ namespace CGAL if (c3t3.in_dimension(vh0) == 3 && !is_on_convex_hull(vh0, c3t3)) { const Point_3& p1 = point(vh1->point()); - smoothing_vecs[i0] = smoothing_vecs[i0] + Vector_3(CGAL::ORIGIN, p1); + smoothed_positions[i0] = smoothed_positions[i0] + Vector_3(CGAL::ORIGIN, p1); neighbors[i0]++; } if (c3t3.in_dimension(vh1) == 3 && !is_on_convex_hull(vh1, c3t3)) { const Point_3& p0 = point(vh0->point()); - smoothing_vecs[i1] = smoothing_vecs[i1] + Vector_3(CGAL::ORIGIN, p0); + smoothed_positions[i1] = smoothed_positions[i1] + Vector_3(CGAL::ORIGIN, p0); neighbors[i1]++; } } @@ -554,36 +556,39 @@ namespace CGAL const std::size_t& vid = vertex_id.at(v); if (neighbors[vid] > 1) { - if (smoothing_vecs[vid] != CGAL::NULL_VECTOR) - { +// if (smoothed_positions[vid] != CGAL::NULL_VECTOR) +// { #ifdef CGAL_TETRAHEDRAL_REMESHING_VERBOSE ++nb_done; #endif - Point_3 new_pos = CGAL::ORIGIN + smoothing_vecs[vid] / neighbors[vid]; - const Vector_3 move(point(v->point()), new_pos); + const Vector_3 point = smoothed_positions[vid] / static_cast(neighbors[vid]); + v->set_point(typename Tr::Point(point.x(), point.y(), point.z())); - std::vector cells; - tr.finite_incident_cells(v, std::back_inserter(cells)); + //Point_3 new_pos = CGAL::ORIGIN + smoothed_positions[vid] / neighbors[vid]; + //const Vector_3 move(point(v->point()), new_pos); - bool selected = true; - for (const Cell_handle ci : cells) - { - if (!cell_selector(ci)) - { - selected = false; - break; - } - } - if (!selected) - continue; + //std::vector cells; + //tr.finite_incident_cells(v, std::back_inserter(cells)); - double frac = 1.; - while (frac > 0.05 /// 1/16 = 0.0625 - && !check_inversion_and_move(v, frac * move, cells, tr)) - { - frac = 0.5 * frac; - } - } + //bool selected = true; + //for (const Cell_handle ci : cells) + //{ + // if (!cell_selector(ci)) + // { + // selected = false; + // break; + // } + //} + //if (!selected) + // continue; + + //double frac = 1.; + //while (frac > 0.05 /// 1/16 = 0.0625 + // && !check_inversion_and_move(v, frac * move, cells, tr)) + //{ + // frac = 0.5 * frac; + //} +// } } } diff --git a/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/tetrahedral_remeshing_helpers.h b/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/tetrahedral_remeshing_helpers.h index 4a669719eb3..fc91bca5f12 100644 --- a/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/tetrahedral_remeshing_helpers.h +++ b/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/tetrahedral_remeshing_helpers.h @@ -445,7 +445,7 @@ namespace Tetrahedral_remeshing { return c3t3.is_in_complex(v); } - else if (nb_incident_subdomains(v, c3t3) > 2) + else if (nb_incident_subdomains(v, c3t3) > 3) { std::vector edges; c3t3.triangulation().finite_incident_edges(v, std::back_inserter(edges)); From eb1a8778a05982239c5053e54ab002562af1f9a4 Mon Sep 17 00:00:00 2001 From: Jane Tournois Date: Tue, 10 Mar 2020 16:37:00 +0100 Subject: [PATCH 140/568] wip make code as similar as possible to initial code --- .../Tetrahedral_remeshing/internal/FMLS.h | 42 ++- .../internal/smooth_vertices.h | 252 +++++++++++++++--- 2 files changed, 225 insertions(+), 69 deletions(-) diff --git a/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/FMLS.h b/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/FMLS.h index 559aff5ec8d..ee615754f0f 100644 --- a/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/FMLS.h +++ b/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/FMLS.h @@ -29,8 +29,7 @@ #include #include - -#include "Vec3D.h" +#include namespace CGAL @@ -189,20 +188,6 @@ namespace CGAL fclose(file); } - template - void fastProjectionCPU(const CGAL::Point_3& vp, - CGAL::Point_3& vq, - CGAL::Vector_3& vn) - { - Vec3Df p(vp.x(), vp.y(), vp.z()); - Vec3Df q(vq.x(), vq.y(), vq.z()); - Vec3Df n(vn.x(), vn.y(), vn.z()); - fastProjectionCPU(p, q, n); - - vq = CGAL::Point_3(q[0], q[1], q[2]); - vn = CGAL::Vector_3(n[0], n[1], n[2]); - } - // Compute, according to the current point sampling stored in FMLS, the MLS projection // of p and store the resulting position in q and normal in n. void fastProjectionCPU(const Vec3Df& p, Vec3Df& q, Vec3Df& n) @@ -585,18 +570,19 @@ namespace CGAL Grid grid; }; - template void createMLSSurfaces(Subdomain__FMLS& subdomain_FMLS, Subdomain__FMLS_indices& subdomain_FMLS_indices, const VerticesNormalsMap& vertices_normals, - const C3t3& c3t3, - int upsample = 0) + const VerticesSubdomainIndices& vertices_subdomain_indices, + const C3t3& c3t3) { -// upsample = 0; + const int upsample = 0; + typedef typename C3t3::Surface_patch_index Surface_index; typedef typename C3t3::Subdomain_index Subdomain_index; typedef typename C3t3::Triangulation Tr; @@ -623,11 +609,15 @@ namespace CGAL { if (vit->in_dimension() == 2) { - const Surface_index si = surface_patch_index(vit, c3t3); - subdomain_sample_numbers[si]++; + const std::vector& v_subdomain_indices = vertices_subdomain_indices.at(vit); + if (v_subdomain_indices.size() == 2) + { + const Surface_index si = surface_patch_index(vit, c3t3); + subdomain_sample_numbers[si]++; + } } } - + //if (upsample > 0) { // std::cout << "Up sampling MLS " << upsample << std::endl; // for (C3t3_with_info::Facet_iterator fit = c3t3_with_info.facets_begin(); fit != c3t3_with_info.facets_end(); ++fit) { @@ -659,7 +649,7 @@ namespace CGAL //Allocation of the PN for (Vertex_handle vit : tr.finite_vertex_handles()) { - if (vit->in_dimension() == 2) + if (vertices_subdomain_indices.at(vit).size() == 2) { const Surface_index surf_i = surface_patch_index(vit, c3t3); @@ -699,8 +689,8 @@ namespace CGAL Vertex_handle vh0 = edge.first->vertex(edge.second); Vertex_handle vh1 = edge.first->vertex(edge.third); Edge_vv e = make_vertex_pair(vh0, vh1); - if ( vh0->in_dimension() == 2 - && vh1->in_dimension() == 2 + if ( vertices_subdomain_indices.at(vh0).size() == 2 + && vertices_subdomain_indices.at(vh1).size() == 2 && edgeMap.find(e) == edgeMap.end()) { edgeMap[e] = 0; diff --git a/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/smooth_vertices.h b/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/smooth_vertices.h index 65d7f4a765c..6eb21bbb49a 100644 --- a/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/smooth_vertices.h +++ b/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/smooth_vertices.h @@ -191,28 +191,50 @@ namespace CGAL { typedef typename C3T3::Subdomain_index Subdomain_index; typedef typename C3T3::Vertex_handle Vertex_handle; + typedef typename C3T3::Triangulation Tr; - for (typename C3T3::Cell_iterator cit = c3t3.cells_in_complex_begin(); - cit != c3t3.cells_in_complex_end(); ++cit) + for (typename Tr::Facet f : c3t3.triangulation().finite_facets()) { - const Subdomain_index si = cit->subdomain_index(); - for (int i = 0; i < 4; ++i) + const Subdomain_index si_0 = f.first->subdomain_index(); + const Subdomain_index si_1 = f.first->neighbor(f.second)->subdomain_index(); + + for (int i = 0; i < 3; i++) { - const Vertex_handle vi = cit->vertex(i); - if (vertices_subdomain_indices.find(vi) == vertices_subdomain_indices.end()) - { - std::vector indices(1); - indices[0] = si; - vertices_subdomain_indices.insert(std::make_pair(vi, indices)); - } - else - { - std::vector& v_indices = vertices_subdomain_indices.at(vi); - if (std::find(v_indices.begin(), v_indices.end(), si) == v_indices.end()) - v_indices.push_back(si); - } + Vertex_handle vi = f.first->vertex(indices(f.second, i)); + std::vector& v_subdomain_indices = vertices_subdomain_indices[vi]; + + if (std::find(v_subdomain_indices.begin(), v_subdomain_indices.end(), si_0) == v_subdomain_indices.end()) + v_subdomain_indices.push_back(si_0); + + if (std::find(v_subdomain_indices.begin(), v_subdomain_indices.end(), si_1) == v_subdomain_indices.end()) + v_subdomain_indices.push_back(si_1); } } + + + + ////////////////////////////////////////////////////////////////////// + //for (typename C3T3::Cell_iterator cit = c3t3.cells_in_complex_begin(); + // cit != c3t3.cells_in_complex_end(); ++cit) + //{ + // const Subdomain_index si = cit->subdomain_index(); + // for (int i = 0; i < 4; ++i) + // { + // const Vertex_handle vi = cit->vertex(i); + // if (vertices_subdomain_indices.find(vi) == vertices_subdomain_indices.end()) + // { + // std::vector indices(1); + // indices[0] = si; + // vertices_subdomain_indices.insert(std::make_pair(vi, indices)); + // } + // else + // { + // std::vector& v_indices = vertices_subdomain_indices.at(vi); + // if (std::find(v_indices.begin(), v_indices.end(), si) == v_indices.end()) + // v_indices.push_back(si); + // } + // } + //} } template @@ -229,36 +251,151 @@ namespace CGAL typedef typename C3T3::Vertex_handle Vertex_handle; typedef typename C3T3::Facet Facet; - for (typename C3T3::Facet_iterator fit = c3t3.facets_in_complex_begin(); - fit != c3t3.facets_in_complex_end(); ++fit) + for (typename C3T3::Facet_iterator fit = c3t3.facets_begin(); + fit != c3t3.facets_end(); ++fit) { - const Facet& f = *fit; - const Surface_patch_index surface_index = c3t3.surface_patch_index(f); + Surface_patch_index surface_index = c3t3.surface_patch_index(*fit); - for (int i = 0; i < 3; ++i) + for (int i = 0; i < 3; i++) { - const Vertex_handle vi = f.first->vertex(indices(f.second, i)); + Vertex_handle vi = fit->first->vertex(indices(fit->second, i)); + if (vertices_subdomain_indices.at(vi).size() > 2) { - if (vertices_surface_indices.find(vi) == vertices_surface_indices.end()) - { - std::vector indices(1); - indices[0] = surface_index; - vertices_surface_indices.insert(std::make_pair(vi, indices)); - } - else - { - std::vector& v_surface_indices = vertices_surface_indices.at(vi); - if (std::find(v_surface_indices.begin(), v_surface_indices.end(), surface_index) - == v_surface_indices.end()) - v_surface_indices.push_back(surface_index); + std::vector& v_surface_indices = vertices_surface_indices[vi]; + + if (std::find(v_surface_indices.begin(), v_surface_indices.end(), surface_index) == v_surface_indices.end()) + v_surface_indices.push_back(surface_index); + } + } + } + + //for (typename C3T3::Facet_iterator fit = c3t3.facets_in_complex_begin(); + // fit != c3t3.facets_in_complex_end(); ++fit) + //{ + // const Facet& f = *fit; + // const Surface_patch_index surface_index = c3t3.surface_patch_index(f); + + // for (int i = 0; i < 3; ++i) + // { + // const Vertex_handle vi = f.first->vertex(indices(f.second, i)); + // if (vertices_subdomain_indices.at(vi).size() > 2) + // { + // if (vertices_surface_indices.find(vi) == vertices_surface_indices.end()) + // { + // std::vector indices(1); + // indices[0] = surface_index; + // vertices_surface_indices.insert(std::make_pair(vi, indices)); + // } + // else + // { + // std::vector& v_surface_indices = vertices_surface_indices.at(vi); + // if (std::find(v_surface_indices.begin(), v_surface_indices.end(), surface_index) + // == v_surface_indices.end()) + // v_surface_indices.push_back(surface_index); + // } + // } + // } + //} + } + + template + bool is_feature_MAD(const typename C3t3::Edge& edge, + const VerticesSubdomainsMap& vertices_subdomain_indices, + const C3t3& c3t3) + { + typedef typename C3t3::Vertex_handle Vertex_handle; + typedef typename C3t3::Triangulation::Cell_circulator Cell_circulator; + typedef typename C3t3::Subdomain_index Subdomain_index; + + const typename C3t3::Triangulation& triangulation = c3t3.triangulation(); + + Vertex_handle vh0 = edge.first->vertex(edge.second); + Vertex_handle vh1 = edge.first->vertex(edge.third); + + int dim_vh0 = c3t3.in_dimension(vh0); + int dim_vh1 = c3t3.in_dimension(vh1); + + const int nb_si_vh0 = vertices_subdomain_indices.at(vh0).size(); + const int nb_si_vh1 = vertices_subdomain_indices.at(vh1).size(); + + if (nb_si_vh0 > 2 && nb_si_vh1 > 2) + { + Cell_circulator cell_circulator = triangulation.incident_cells(edge); + Cell_circulator done(cell_circulator); + + std::vector si; + do + { + Subdomain_index current_si = cell_circulator->subdomain_index(); + + if (std::find(si.begin(), si.end(), current_si) == si.end()) + si.push_back(current_si); + + if (si.size() > 2) + return true; + + } while (++cell_circulator != done); + + } + else if (c3t3.number_of_edges() > 0 && dim_vh0 == 1 && dim_vh1 == 1) + { + if(c3t3.is_in_complex(edge)) + return true; + } + return false; + } + + template + bool is_feature_MAD(const typename C3t3::Vertex_handle vh0, + const typename C3t3::Vertex_handle vh1, + const VerticesSubdomainsMap& vertices_subdomain_indices, + const C3t3& c3t3) + { + typename C3t3::Cell_handle ch; + int i0, i1; + + if (c3t3.triangulation().is_edge(vh0, vh1, ch, i0, i1)) + { + typename C3t3::Edge edge(ch, i0, i1); + return is_feature_MAD(edge, vertices_subdomain_indices, c3t3); + } + + return false; + } + + template + bool is_feature_MAD(const typename C3t3::Vertex_handle vh, + const VerticesSubdomainsMap& vertices_subdomain_indices, + const C3t3& c3t3) + { + typedef typename C3t3::Vertex_handle Vertex_handle; + + const typename C3t3::Triangulation& triangulation = c3t3.triangulation(); + + if (vertices_subdomain_indices.at(vh).size() > 3) + { + std::vector neighbors; + triangulation.finite_incident_vertices(vh, std::back_inserter(neighbors)); + + int feature_count = 0; + for (Vertex_handle neighbor : neighbors) + { + if (is_feature_MAD(vh, neighbor, vertices_subdomain_indices, c3t3)) + { + feature_count++; + if (feature_count >= 3) { + return true; } } } } + else if (c3t3.number_of_corners() > 0 && c3t3.in_dimension(vh)) { + return c3t3.is_in_complex(vh); + } + return false; } - template void smooth_vertices(C3T3& c3t3, const bool protect_boundaries, @@ -277,6 +414,11 @@ namespace CGAL typedef typename Gt::Vector_3 Vector_3; typedef typename Gt::FT FT; +#ifdef CGAL_TETRAHEDRAL_REMESHING_DEBUG + std::ofstream os_surf("smooth_surfaces.polylines.txt"); + std::ofstream os_vol("smooth_volume.polylines.txt"); +#endif + #ifdef CGAL_TETRAHEDRAL_REMESHING_VERBOSE std::cout << "Smooth vertices..."; std::cout.flush(); @@ -304,6 +446,7 @@ namespace CGAL createMLSSurfaces(subdomain_FMLS, subdomain_FMLS_indices, vertices_normals, + vertices_subdomain_indices, c3t3); //smooth() @@ -329,11 +472,11 @@ namespace CGAL const std::size_t& i0 = vertex_id.at(vh0); const std::size_t& i1 = vertex_id.at(vh1); - if (c3t3.is_in_complex(e)) + if (is_feature_MAD(e, vertices_subdomain_indices, c3t3))//c3t3.is_in_complex(e)) { - if (!is_feature(vh0, c3t3)) + if (!is_feature_MAD(vh0, vertices_subdomain_indices, c3t3)) neighbors[i0] = (std::max)(0, neighbors[i0]); - if (!is_feature(vh1, c3t3)) + if (!is_feature_MAD(vh1, vertices_subdomain_indices, c3t3)) neighbors[i1] = (std::max)(0, neighbors[i1]); bool update_v0 = false, update_v1 = false; @@ -389,6 +532,9 @@ namespace CGAL else final_position = smoothed_position; +#ifdef CGAL_TETRAHEDRAL_REMESHING_DEBUG + os_surf << "2 " << current_pos << " " << final_position << std::endl, +#endif // move vertex v->set_point(typename Tr::Point( final_position.x(), final_position.y(), final_position.z())); @@ -421,6 +567,9 @@ namespace CGAL else final_position = current_pos; +#ifdef CGAL_TETRAHEDRAL_REMESHING_DEBUG + os_surf << "2 " << current_pos << " " << final_position << std::endl, +#endif // move vertex v->set_point( typename Tr::Point(final_position.x(), final_position.y(), final_position.z())); @@ -444,9 +593,9 @@ namespace CGAL if (is_boundary(c3t3, e, cell_selector) && !c3t3.is_in_complex(e)) { bool update_v0 = false, update_v1 = false; - if (!is_feature(vh0, c3t3)) + if (!is_feature_MAD(vh0, vertices_subdomain_indices, c3t3)) neighbors[i0] = (std::max)(0, neighbors[i0]); - if (!is_feature(vh1, c3t3)) + if (!is_feature_MAD(vh1, vertices_subdomain_indices, c3t3)) neighbors[i1] = (std::max)(0, neighbors[i1]); get_edge_info(e, update_v0, update_v1, c3t3, cell_selector); @@ -498,6 +647,9 @@ namespace CGAL // std::cout << "MLS " << final_position[0] << " - " << final_position[1] << " : " << final_position[2] << std::endl; } +#ifdef CGAL_TETRAHEDRAL_REMESHING_DEBUG + os_surf << "2 " << current_pos << " " << final_position << std::endl, +#endif v->set_point(typename Tr::Point( final_position.x(), final_position.y(), final_position.z())); } @@ -514,12 +666,18 @@ namespace CGAL { const typename Tr::Point new_pos(CGAL::ORIGIN + mls_projection); v->set_point(new_pos); + +#ifdef CGAL_TETRAHEDRAL_REMESHING_DEBUG + os_surf << "2 " << current_pos << " " << new_pos << std::endl; +#endif } } } } } + //end if(!protect_boundaries) + smoothed_positions.clear(); smoothed_positions.resize(nbv, CGAL::NULL_VECTOR); @@ -561,9 +719,15 @@ namespace CGAL #ifdef CGAL_TETRAHEDRAL_REMESHING_VERBOSE ++nb_done; #endif - const Vector_3 point = smoothed_positions[vid] / static_cast(neighbors[vid]); - v->set_point(typename Tr::Point(point.x(), point.y(), point.z())); +#ifdef CGAL_TETRAHEDRAL_REMESHING_DEBUG + os_vol << "2 " << point(v->point()); +#endif + const Vector_3 p = smoothed_positions[vid] / static_cast(neighbors[vid]); + v->set_point(typename Tr::Point(p.x(), p.y(), p.z())); +#ifdef CGAL_TETRAHEDRAL_REMESHING_DEBUG + os_vol << " " << point(v->point()) << std::endl; +#endif //Point_3 new_pos = CGAL::ORIGIN + smoothed_positions[vid] / neighbors[vid]; //const Vector_3 move(point(v->point()), new_pos); @@ -598,6 +762,8 @@ namespace CGAL #ifdef CGAL_TETRAHEDRAL_REMESHING_DEBUG CGAL::Tetrahedral_remeshing::debug::dump_vertices_by_dimension( c3t3.triangulation(), "c3t3_vertices_after_smoothing"); + os_surf.close(); + os_vol.close(); #endif } From 096b724ec1c8d3e865828bc84743c2944f73050d Mon Sep 17 00:00:00 2001 From: Jane Tournois Date: Fri, 13 Mar 2020 14:26:05 +0100 Subject: [PATCH 141/568] uncomment and adapt code with upsample > 0 --- .../Tetrahedral_remeshing/internal/FMLS.h | 193 +++++++++--------- 1 file changed, 100 insertions(+), 93 deletions(-) diff --git a/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/FMLS.h b/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/FMLS.h index ee615754f0f..55d33b1ac48 100644 --- a/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/FMLS.h +++ b/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/FMLS.h @@ -581,7 +581,7 @@ namespace CGAL const VerticesSubdomainIndices& vertices_subdomain_indices, const C3t3& c3t3) { - const int upsample = 0; + const int upsample = 0; // can be 0, 1 or 2 typedef typename C3t3::Surface_patch_index Surface_index; typedef typename C3t3::Subdomain_index Subdomain_index; @@ -618,17 +618,19 @@ namespace CGAL } } - //if (upsample > 0) { - // std::cout << "Up sampling MLS " << upsample << std::endl; - // for (C3t3_with_info::Facet_iterator fit = c3t3_with_info.facets_begin(); fit != c3t3_with_info.facets_end(); ++fit) { - // Surface_index surf_i = triangulated_domain.make_surface_index(fit->first->subdomain_index(), - // fit->first->neighbor(fit->second)->subdomain_index()); - // if (upsample == 1) - // subdomain_sample_numbers[surf_i] ++; - // else if (upsample == 2) - // subdomain_sample_numbers[surf_i] += 4; - // } - //} + if (upsample > 0) + { + std::cout << "Up sampling MLS " << upsample << std::endl; + for (typename C3t3::Facet_iterator fit = c3t3.facets_begin(); + fit != c3t3.facets_end(); ++fit) + { + const Surface_index surf_i = c3t3.surface_patch_index(*fit); + if (upsample == 1) + subdomain_sample_numbers[surf_i] ++; + else if (upsample == 2) + subdomain_sample_numbers[surf_i] += 4; + } + } std::vector< float* > pns; @@ -653,7 +655,7 @@ namespace CGAL { const Surface_index surf_i = surface_patch_index(vit, c3t3); - int fmls_id = current_subdomain_FMLS_indices[surf_i]; + const int fmls_id = current_subdomain_FMLS_indices[surf_i]; const Point_3& p = point(vit->point()); @@ -706,86 +708,91 @@ namespace CGAL } } -// if (upsample > 0) { -// -// for (C3t3_with_info::Facet_iterator fit = c3t3_with_info.facets_begin(); fit != c3t3_with_info.facets_end(); ++fit) { -// -// Surface_index surf_i = triangulated_domain.make_surface_index(fit->first->subdomain_index(), -// fit->first->neighbor(fit->second)->subdomain_index()); -// -// int fmls_id = current_subdomain_FMLS_indices[surf_i]; -// -// Vertex_handle vhs[3] = { fit->first->vertex(indices[fit->second][0]), -// fit->first->vertex(indices[fit->second][1]), -// fit->first->vertex(indices[fit->second][2]) }; -// K::Vector_3 points[3] = { PointToVector(vhs[0]->point()), PointToVector(vhs[1]->point()), PointToVector(vhs[2]->point()) }; -// K::Vector_3 normals[3] = { vertices_normals[vhs[0]->info()][surf_i], vertices_normals[vhs[1]->info()][surf_i], vertices_normals[vhs[2]->info()][surf_i] }; -// -// std::vector points_to_add; -// std::vector n_points_to_add; -// -// //Add the barycenter of the facet -// K::Vector_3 barycenter = (points[0] + points[1] + points[2]) / 3.; -// K::Vector_3 n_barycenter = (normals[0] + normals[1] + normals[2]); -// -// barycenter = (points[0] + points[1] + points[2]) / 3.; -// n_barycenter = (normals[0] + normals[1] + normals[2]); -// -// n_barycenter = n_barycenter / CGAL::sqrt((n_barycenter * n_barycenter)); -// -// points_to_add.push_back(barycenter); -// n_points_to_add.push_back(n_barycenter); -// -// if (upsample == 1) { -// for (int i = 0; i < 3; i++) { -// K::Vector_3 space_1 = barycenter - points[i]; -// -// point_spacing[fmls_id] += CGAL::to_double(CGAL::sqrt(space_1 * space_1)); -// point_spacing_count[fmls_id] ++; -// } -// } -// else if (upsample == 2) { -// for (int i = 0; i < 3; i++) { -// -// int i1 = (i + 1) % 3; -// int i2 = (i + 2) % 3; -// -// K::Vector_3 p = (barycenter + points[i1] + points[i2]) / 3.; -// K::Vector_3 n = (n_barycenter + normals[i1] + normals[i2]); -// -// n = n / CGAL::sqrt(n * n); -// -// points_to_add.push_back(p); -// n_points_to_add.push_back(n); -// -// K::Vector_3 space_1 = p - barycenter; -// K::Vector_3 space_2 = p - points[i1]; -// K::Vector_3 space_3 = p - points[i2]; -// -// point_spacing[fmls_id] += CGAL::to_double(CGAL::sqrt(space_1 * space_1)); -// point_spacing[fmls_id] += CGAL::to_double(CGAL::sqrt(space_2 * space_2)); -// point_spacing[fmls_id] += CGAL::to_double(CGAL::sqrt(space_3 * space_3)); -// -// point_spacing_count[fmls_id] += 3; -// } -// } -// for (unsigned int i = 0; i < points_to_add.size(); i++) { -// K::Vector_3& point = points_to_add[i]; -// -// pns[fmls_id][6 * current_v_count[fmls_id]] = point.x(); -// pns[fmls_id][6 * current_v_count[fmls_id] + 1] = point.y(); -// pns[fmls_id][6 * current_v_count[fmls_id] + 2] = point.z(); -// -// K::Vector_3& normal = n_points_to_add[i]; -// -// pns[fmls_id][6 * current_v_count[fmls_id] + 3] = normal.x(); -// pns[fmls_id][6 * current_v_count[fmls_id] + 4] = normal.y(); -// pns[fmls_id][6 * current_v_count[fmls_id] + 5] = normal.z(); -// -// current_v_count[fmls_id]++; -// } -// } -// } + if (upsample > 0) + { + for (typename C3t3::Facet_iterator fit = c3t3.facets_begin(); + fit != c3t3.facets_end(); ++fit) + { + const Surface_index surf_i = c3t3.surface_patch_index(*fit); + + const int fmls_id = current_subdomain_FMLS_indices[surf_i]; + + Vertex_handle vhs[3] = { fit->first->vertex(indices(fit->second, 0)), + fit->first->vertex(indices(fit->second, 1)), + fit->first->vertex(indices(fit->second, 2)) }; + Vector_3 points[3] = { Vector_3(CGAL::ORIGIN, point(vhs[0]->point())), + Vector_3(CGAL::ORIGIN, point(vhs[0]->point())), + Vector_3(CGAL::ORIGIN, point(vhs[0]->point())) }; + Vector_3 normals[3] = { vertices_normals.at(vhs[0]).at(surf_i), + vertices_normals.at(vhs[1]).at(surf_i), + vertices_normals.at(vhs[2]).at(surf_i) }; + + std::vector points_to_add; + std::vector n_points_to_add; + + //Add the barycenter of the facet + Vector_3 barycenter = (points[0] + points[1] + points[2]) / 3.; + Vector_3 n_barycenter = (normals[0] + normals[1] + normals[2]); + + n_barycenter = n_barycenter / CGAL::sqrt((n_barycenter * n_barycenter)); + + points_to_add.push_back(barycenter); + n_points_to_add.push_back(n_barycenter); + + if (upsample == 1) + { + for (int i = 0; i < 3; i++) + { + Vector_3 space_1 = barycenter - points[i]; + + point_spacing[fmls_id] += CGAL::to_double(CGAL::sqrt(space_1 * space_1)); + point_spacing_count[fmls_id] ++; + } + } + else if (upsample == 2) + { + for (int i = 0; i < 3; i++) + { + int i1 = (i + 1) % 3; + int i2 = (i + 2) % 3; + + Vector_3 p = (barycenter + points[i1] + points[i2]) / 3.; + Vector_3 n = (n_barycenter + normals[i1] + normals[i2]); + + n = n / CGAL::sqrt(n * n); + + points_to_add.push_back(p); + n_points_to_add.push_back(n); + + Vector_3 space_1 = p - barycenter; + Vector_3 space_2 = p - points[i1]; + Vector_3 space_3 = p - points[i2]; + + point_spacing[fmls_id] += CGAL::to_double(CGAL::sqrt(space_1 * space_1)); + point_spacing[fmls_id] += CGAL::to_double(CGAL::sqrt(space_2 * space_2)); + point_spacing[fmls_id] += CGAL::to_double(CGAL::sqrt(space_3 * space_3)); + + point_spacing_count[fmls_id] += 3; + } + } + for (unsigned int i = 0; i < points_to_add.size(); i++) + { + Vector_3& point = points_to_add[i]; + + pns[fmls_id][6 * current_v_count[fmls_id]] = point.x(); + pns[fmls_id][6 * current_v_count[fmls_id] + 1] = point.y(); + pns[fmls_id][6 * current_v_count[fmls_id] + 2] = point.z(); + + Vector_3& normal = n_points_to_add[i]; + + pns[fmls_id][6 * current_v_count[fmls_id] + 3] = normal.x(); + pns[fmls_id][6 * current_v_count[fmls_id] + 4] = normal.y(); + pns[fmls_id][6 * current_v_count[fmls_id] + 5] = normal.z(); + + current_v_count[fmls_id]++; + } + } + } int nb_of_mls_to_create = 0; From a8a74c4e199a8a9fba33258e571518b47c90b3f9 Mon Sep 17 00:00:00 2001 From: Jane Tournois Date: Fri, 13 Mar 2020 14:32:14 +0100 Subject: [PATCH 142/568] sum of normals starts with n, not NULL_VECTOR and add dump of normals for debugging purposes --- .../internal/smooth_vertices.h | 29 ++++++++++++++++--- 1 file changed, 25 insertions(+), 4 deletions(-) diff --git a/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/smooth_vertices.h b/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/smooth_vertices.h index 6eb21bbb49a..b6402c24a88 100644 --- a/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/smooth_vertices.h +++ b/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/smooth_vertices.h @@ -69,7 +69,7 @@ namespace CGAL n = opp(n); else if (si == si_mirror) { - std::cout << "Check normal!" << std::endl; + std::cout << "TODO : Check normal when subdomain is the same on both sides" << std::endl; } for (int i = 0; i < 3; ++i) @@ -80,7 +80,7 @@ namespace CGAL if (patch_vector_it == normals_map.end() || patch_vector_it->second.find(surf_i) == patch_vector_it->second.end()) { - normals_map[vi][surf_i] = CGAL::NULL_VECTOR; + normals_map[vi][surf_i] = n; } else { @@ -90,6 +90,11 @@ namespace CGAL } } +#ifdef CGAL_TETRAHEDRAL_REMESHING_DEBUG + std::ofstream os("dump_normals.polylines.txt"); + std::ofstream osn("dump_normals_normalized.polylines.txt"); +#endif + //normalize the computed normals for (typename VertexNormalsMap::iterator vnm_it = normals_map.begin(); vnm_it != normals_map.end(); ++vnm_it) @@ -99,9 +104,24 @@ namespace CGAL it != vnm_it->second.end(); ++it) { Vector_3& n = it->second; - n = scale(n, 1. / CGAL::approximate_sqrt(n * n)); + +#ifdef CGAL_TETRAHEDRAL_REMESHING_DEBUG + auto p = point(vnm_it->first->point()); + os << "2 " << p << " " << (p + n) << std::endl; +#endif + + CGAL::Tetrahedral_remeshing::normalize(n, c3t3.triangulation().geom_traits()); + +#ifdef CGAL_TETRAHEDRAL_REMESHING_DEBUG + osn << "2 " << p << " " << (p + n) << std::endl; +#endif } } + +#ifdef CGAL_TETRAHEDRAL_REMESHING_DEBUG + os.close(); + osn.close(); +#endif } @@ -417,6 +437,8 @@ namespace CGAL #ifdef CGAL_TETRAHEDRAL_REMESHING_DEBUG std::ofstream os_surf("smooth_surfaces.polylines.txt"); std::ofstream os_vol("smooth_volume.polylines.txt"); + std::ofstream os_mls("smooth_mls_projections.txt"); + std::ofstream os_normal("smooth_normal_projections.txt"); #endif #ifdef CGAL_TETRAHEDRAL_REMESHING_VERBOSE @@ -518,7 +540,6 @@ namespace CGAL //Check if the mls surface exists to avoid degenrated cases Vector_3 mls_projection; if (project(si, normal_projection, mls_projection, subdomain_FMLS, subdomain_FMLS_indices)) { - std::cout << "project OK" << std::endl; final_position = final_position + mls_projection; } else { From ad0c8d7680a3e83a842ab731ea579f522c2de0f7 Mon Sep 17 00:00:00 2001 From: Jane Tournois Date: Fri, 13 Mar 2020 14:43:41 +0100 Subject: [PATCH 143/568] fix orientation of normals --- .../internal/tetrahedral_remeshing_helpers.h | 38 ++++++++++++++----- 1 file changed, 29 insertions(+), 9 deletions(-) diff --git a/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/tetrahedral_remeshing_helpers.h b/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/tetrahedral_remeshing_helpers.h index fc91bca5f12..ca701da6e7c 100644 --- a/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/tetrahedral_remeshing_helpers.h +++ b/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/tetrahedral_remeshing_helpers.h @@ -580,6 +580,15 @@ namespace Tetrahedral_remeshing return true; } + template + void normalize(typename Gt::Vector_3& v, const Gt& gt) + { + namespace PMP = CGAL::Polygon_mesh_processing; + + if (!typename Gt::Equal_3()(v, CGAL::NULL_VECTOR)) + PMP::internal::normalize(v, gt); + } + template typename Gt::Vector_3 normal(const Facet& f, const Gt& gt) { @@ -587,19 +596,30 @@ namespace Tetrahedral_remeshing typedef typename Gt::Vector_3 Vector; typedef typename Gt::Point_3 Point; - Point p0 = point(f.first->vertex((f.second + 1) % 4)->point()); - Point p1 = point(f.first->vertex((f.second + 2) % 4)->point()); - const Point& p2 = point(f.first->vertex((f.second + 3) % 4)->point()); + const int i = f.second; - if (f.second % 2 == 0)//equivalent to the commented orientation test - std::swap(p0, p1); + const Point& pa = point(f.first->vertex(indices(i, 0))->point()); + const Point& pb = point(f.first->vertex(indices(i, 1))->point()); + const Point& pc = point(f.first->vertex(indices(i, 2))->point()); - Vector n = PMP::internal::triangle_normal(p0, p1, p2, gt); - - if (!typename Gt::Equal_3()(n, CGAL::NULL_VECTOR)) - PMP::internal::normalize(n, gt); + Vector n = CGAL::cross_product(pb - pa, pc - pa); + n = n / CGAL::sqrt(n * n); return n; + +// Point p0 = point(f.first->vertex((f.second + 1) % 4)->point()); +// Point p1 = point(f.first->vertex((f.second + 2) % 4)->point()); +// const Point& p2 = point(f.first->vertex((f.second + 3) % 4)->point()); +// +// //if (f.second % 2 == 0)//equivalent to the commented orientation test +// // std::swap(p0, p1); +// +// Vector n = PMP::internal::triangle_normal(p0, p1, p2, gt); +// +// if (!typename Gt::Equal_3()(n, CGAL::NULL_VECTOR)) +// PMP::internal::normalize(n, gt); + +// return n; } template From f42174367046e99ae97a039013140243519ede74 Mon Sep 17 00:00:00 2001 From: Jane Tournois Date: Fri, 13 Mar 2020 15:24:06 +0100 Subject: [PATCH 144/568] fix indices in access to points --- .../include/CGAL/Tetrahedral_remeshing/internal/FMLS.h | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/FMLS.h b/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/FMLS.h index 55d33b1ac48..db68da62ad6 100644 --- a/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/FMLS.h +++ b/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/FMLS.h @@ -581,7 +581,7 @@ namespace CGAL const VerticesSubdomainIndices& vertices_subdomain_indices, const C3t3& c3t3) { - const int upsample = 0; // can be 0, 1 or 2 + const int upsample = 1; // can be 0, 1 or 2 typedef typename C3t3::Surface_patch_index Surface_index; typedef typename C3t3::Subdomain_index Subdomain_index; @@ -696,8 +696,8 @@ namespace CGAL && edgeMap.find(e) == edgeMap.end()) { edgeMap[e] = 0; - Surface_index surf_i = c3t3.surface_patch_index(*fit); - int fmls_id = current_subdomain_FMLS_indices[surf_i]; + const Surface_index surf_i = c3t3.surface_patch_index(*fit); + const int fmls_id = current_subdomain_FMLS_indices[surf_i]; point_spacing[fmls_id] += CGAL::approximate_sqrt( CGAL::squared_distance(point(vh0->point()), point(vh1->point()))); @@ -721,8 +721,8 @@ namespace CGAL fit->first->vertex(indices(fit->second, 1)), fit->first->vertex(indices(fit->second, 2)) }; Vector_3 points[3] = { Vector_3(CGAL::ORIGIN, point(vhs[0]->point())), - Vector_3(CGAL::ORIGIN, point(vhs[0]->point())), - Vector_3(CGAL::ORIGIN, point(vhs[0]->point())) }; + Vector_3(CGAL::ORIGIN, point(vhs[1]->point())), + Vector_3(CGAL::ORIGIN, point(vhs[2]->point())) }; Vector_3 normals[3] = { vertices_normals.at(vhs[0]).at(surf_i), vertices_normals.at(vhs[1]).at(surf_i), vertices_normals.at(vhs[2]).at(surf_i) }; From 0ca5574c3fbed8e0e716c79bdea366b243b9904f Mon Sep 17 00:00:00 2001 From: Jane Tournois Date: Fri, 13 Mar 2020 15:24:23 +0100 Subject: [PATCH 145/568] add const --- .../CGAL/Tetrahedral_remeshing/internal/smooth_vertices.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/smooth_vertices.h b/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/smooth_vertices.h index b6402c24a88..e30fb059ecd 100644 --- a/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/smooth_vertices.h +++ b/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/smooth_vertices.h @@ -274,11 +274,11 @@ namespace CGAL for (typename C3T3::Facet_iterator fit = c3t3.facets_begin(); fit != c3t3.facets_end(); ++fit) { - Surface_patch_index surface_index = c3t3.surface_patch_index(*fit); + const Surface_patch_index surface_index = c3t3.surface_patch_index(*fit); for (int i = 0; i < 3; i++) { - Vertex_handle vi = fit->first->vertex(indices(fit->second, i)); + const Vertex_handle vi = fit->first->vertex(indices(fit->second, i)); if (vertices_subdomain_indices.at(vi).size() > 2) { From 0b030ed9bd1e0f37cb4f53b6be15173af0c5b1d9 Mon Sep 17 00:00:00 2001 From: Jane Tournois Date: Mon, 16 Mar 2020 14:29:37 +0100 Subject: [PATCH 146/568] use vertices_surface_indices instead of the assumption that a surface is incident to two subdomains There can always be a surface incident to 2 subvolumes with the same index --- .../Tetrahedral_remeshing/internal/FMLS.h | 49 ++++++++++++------- 1 file changed, 31 insertions(+), 18 deletions(-) diff --git a/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/FMLS.h b/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/FMLS.h index db68da62ad6..6d7dd2beb00 100644 --- a/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/FMLS.h +++ b/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/FMLS.h @@ -25,12 +25,13 @@ #include #include #include - -#include +#include #include #include +#include + namespace CGAL { @@ -574,14 +575,16 @@ namespace CGAL typename Subdomain__FMLS_indices, typename VerticesNormalsMap, typename VerticesSubdomainIndices, + typename VerticesSurfaceIndices, typename C3t3> void createMLSSurfaces(Subdomain__FMLS& subdomain_FMLS, Subdomain__FMLS_indices& subdomain_FMLS_indices, const VerticesNormalsMap& vertices_normals, const VerticesSubdomainIndices& vertices_subdomain_indices, + const VerticesSurfaceIndices& vertices_surface_indices, const C3t3& c3t3) { - const int upsample = 1; // can be 0, 1 or 2 + const int upsample = 2; // can be 0, 1 or 2 typedef typename C3t3::Surface_patch_index Surface_index; typedef typename C3t3::Subdomain_index Subdomain_index; @@ -592,6 +595,9 @@ namespace CGAL typedef typename Gt::Point_3 Point_3; typedef typename Gt::Vector_3 Vector_3; + typedef typename VerticesSurfaceIndices::mapped_type VertexSurfaces; + typedef typename VerticesSurfaceIndices::const_iterator VerticesSurfaceIterator; + const Tr& tr = c3t3.triangulation(); //createAreaWeightedUpSampledMLSSurfaces(0); @@ -607,14 +613,16 @@ namespace CGAL //Count the number of vertices for each boundary surface (i.e. one per label) for (const Vertex_handle vit : tr.finite_vertex_handles()) { - if (vit->in_dimension() == 2) + VerticesSurfaceIterator sit = vertices_surface_indices.find(vit); + if (sit == vertices_surface_indices.end()) + continue; + + const VertexSurfaces& v_surface_indices = vertices_surface_indices.at(vit); + CGAL_assertion(vit->in_dimension() <= 2); + + for(const Surface_index& si : v_surface_indices) { - const std::vector& v_subdomain_indices = vertices_subdomain_indices.at(vit); - if (v_subdomain_indices.size() == 2) - { - const Surface_index si = surface_patch_index(vit, c3t3); - subdomain_sample_numbers[si]++; - } + subdomain_sample_numbers[si]++; } } @@ -651,10 +659,15 @@ namespace CGAL //Allocation of the PN for (Vertex_handle vit : tr.finite_vertex_handles()) { - if (vertices_subdomain_indices.at(vit).size() == 2) - { - const Surface_index surf_i = surface_patch_index(vit, c3t3); + VerticesSurfaceIterator sit = vertices_surface_indices.find(vit); + if (sit == vertices_surface_indices.end()) + continue; + const VertexSurfaces& v_surface_indices = vertices_surface_indices.at(vit); + CGAL_assertion(vit->in_dimension() <= 2); + + for (const Surface_index& surf_i : v_surface_indices) + { const int fmls_id = current_subdomain_FMLS_indices[surf_i]; const Point_3& p = point(vit->point()); @@ -674,10 +687,9 @@ namespace CGAL } typedef std::pair Edge_vv; - typedef boost::unordered_map EdgeMapIndex; if (upsample == 0) { - EdgeMapIndex edgeMap; + std::unordered_set > edgeMap; for (typename C3t3::Facet_iterator fit = c3t3.facets_begin(); fit != c3t3.facets_end(); ++fit) @@ -691,11 +703,12 @@ namespace CGAL Vertex_handle vh0 = edge.first->vertex(edge.second); Vertex_handle vh1 = edge.first->vertex(edge.third); Edge_vv e = make_vertex_pair(vh0, vh1); - if ( vertices_subdomain_indices.at(vh0).size() == 2 - && vertices_subdomain_indices.at(vh1).size() == 2 + if ( vertices_surface_indices.find(vh0) != vertices_surface_indices.end() + && vertices_surface_indices.find(vh1) != vertices_surface_indices.end() && edgeMap.find(e) == edgeMap.end()) { - edgeMap[e] = 0; + edgeMap.insert(e); + const Surface_index surf_i = c3t3.surface_patch_index(*fit); const int fmls_id = current_subdomain_FMLS_indices[surf_i]; From 08383dbf2df256566f7c9c5f03839c154033440b Mon Sep 17 00:00:00 2001 From: Jane Tournois Date: Mon, 16 Mar 2020 14:34:22 +0100 Subject: [PATCH 147/568] do not add to complex an edge that already is it's the case when the input is a c3t3 with edge protection --- .../internal/tetrahedral_adaptive_remeshing_impl.h | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/tetrahedral_adaptive_remeshing_impl.h b/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/tetrahedral_adaptive_remeshing_impl.h index d5b63c6d477..89eb8ee7163 100644 --- a/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/tetrahedral_adaptive_remeshing_impl.h +++ b/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/tetrahedral_adaptive_remeshing_impl.h @@ -396,6 +396,15 @@ private: ++eit) { const Edge& e = *eit; + + if (m_c3t3.is_in_complex(e)) + { + CGAL_assertion(m_c3t3.in_dimension(e.first->vertex(e.second)) <= 1); + CGAL_assertion(m_c3t3.in_dimension(e.first->vertex(e.third)) <= 1); + ++nbe; + continue; + } + if (get(ecmap, CGAL::Tetrahedral_remeshing::make_vertex_pair(e)) || nb_incident_subdomains(e, m_c3t3) > 2 || nb_incident_surface_patches(e, m_c3t3) > 1) From 3e7f75b3dbf0549ed0a4adc3b221a1a3f786d61d Mon Sep 17 00:00:00 2001 From: Jane Tournois Date: Tue, 17 Mar 2020 06:54:47 +0100 Subject: [PATCH 148/568] use surface indices instead of subdomain indices when it makes more sense - when we have surface indices, there is no need to count subdomains around, - use c3t3 complex information instead of re-evaluating it various cleaning and comments --- .../Tetrahedral_remeshing/internal/FMLS.h | 3 - .../internal/smooth_vertices.h | 148 +++--------------- 2 files changed, 24 insertions(+), 127 deletions(-) diff --git a/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/FMLS.h b/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/FMLS.h index 6d7dd2beb00..d3608b16fb9 100644 --- a/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/FMLS.h +++ b/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/FMLS.h @@ -574,20 +574,17 @@ namespace CGAL template void createMLSSurfaces(Subdomain__FMLS& subdomain_FMLS, Subdomain__FMLS_indices& subdomain_FMLS_indices, const VerticesNormalsMap& vertices_normals, - const VerticesSubdomainIndices& vertices_subdomain_indices, const VerticesSurfaceIndices& vertices_surface_indices, const C3t3& c3t3) { const int upsample = 2; // can be 0, 1 or 2 typedef typename C3t3::Surface_patch_index Surface_index; - typedef typename C3t3::Subdomain_index Subdomain_index; typedef typename C3t3::Triangulation Tr; typedef typename Tr::Edge Edge; typedef typename Tr::Vertex_handle Vertex_handle; diff --git a/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/smooth_vertices.h b/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/smooth_vertices.h index e30fb059ecd..f5de15c7da2 100644 --- a/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/smooth_vertices.h +++ b/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/smooth_vertices.h @@ -213,48 +213,19 @@ namespace CGAL typedef typename C3T3::Vertex_handle Vertex_handle; typedef typename C3T3::Triangulation Tr; - for (typename Tr::Facet f : c3t3.triangulation().finite_facets()) + for (typename C3T3::Cell_iterator cit = c3t3.cells_begin(); + cit != c3t3.cells_end(); ++cit) { - const Subdomain_index si_0 = f.first->subdomain_index(); - const Subdomain_index si_1 = f.first->neighbor(f.second)->subdomain_index(); - - for (int i = 0; i < 3; i++) + const Subdomain_index& si = cit->subdomain_index(); + for (int i = 0; i < 4; ++i) { - Vertex_handle vi = f.first->vertex(indices(f.second, i)); - std::vector& v_subdomain_indices = vertices_subdomain_indices[vi]; + const Vertex_handle vi = cit->vertex(i); - if (std::find(v_subdomain_indices.begin(), v_subdomain_indices.end(), si_0) == v_subdomain_indices.end()) - v_subdomain_indices.push_back(si_0); - - if (std::find(v_subdomain_indices.begin(), v_subdomain_indices.end(), si_1) == v_subdomain_indices.end()) - v_subdomain_indices.push_back(si_1); + std::vector& v_indices = vertices_subdomain_indices[vi]; + if (std::find(v_indices.begin(), v_indices.end(), si) == v_indices.end()) + v_indices.push_back(si); } } - - - - ////////////////////////////////////////////////////////////////////// - //for (typename C3T3::Cell_iterator cit = c3t3.cells_in_complex_begin(); - // cit != c3t3.cells_in_complex_end(); ++cit) - //{ - // const Subdomain_index si = cit->subdomain_index(); - // for (int i = 0; i < 4; ++i) - // { - // const Vertex_handle vi = cit->vertex(i); - // if (vertices_subdomain_indices.find(vi) == vertices_subdomain_indices.end()) - // { - // std::vector indices(1); - // indices[0] = si; - // vertices_subdomain_indices.insert(std::make_pair(vi, indices)); - // } - // else - // { - // std::vector& v_indices = vertices_subdomain_indices.at(vi); - // if (std::find(v_indices.begin(), v_indices.end(), si) == v_indices.end()) - // v_indices.push_back(si); - // } - // } - //} } template @@ -274,49 +245,17 @@ namespace CGAL for (typename C3T3::Facet_iterator fit = c3t3.facets_begin(); fit != c3t3.facets_end(); ++fit) { - const Surface_patch_index surface_index = c3t3.surface_patch_index(*fit); + const Surface_patch_index& surface_index = c3t3.surface_patch_index(*fit); for (int i = 0; i < 3; i++) { const Vertex_handle vi = fit->first->vertex(indices(fit->second, i)); - if (vertices_subdomain_indices.at(vi).size() > 2) - { - std::vector& v_surface_indices = vertices_surface_indices[vi]; - - if (std::find(v_surface_indices.begin(), v_surface_indices.end(), surface_index) == v_surface_indices.end()) - v_surface_indices.push_back(surface_index); - } + std::vector& v_surface_indices = vertices_surface_indices[vi]; + if (std::find(v_surface_indices.begin(), v_surface_indices.end(), surface_index) == v_surface_indices.end()) + v_surface_indices.push_back(surface_index); } } - - //for (typename C3T3::Facet_iterator fit = c3t3.facets_in_complex_begin(); - // fit != c3t3.facets_in_complex_end(); ++fit) - //{ - // const Facet& f = *fit; - // const Surface_patch_index surface_index = c3t3.surface_patch_index(f); - - // for (int i = 0; i < 3; ++i) - // { - // const Vertex_handle vi = f.first->vertex(indices(f.second, i)); - // if (vertices_subdomain_indices.at(vi).size() > 2) - // { - // if (vertices_surface_indices.find(vi) == vertices_surface_indices.end()) - // { - // std::vector indices(1); - // indices[0] = surface_index; - // vertices_surface_indices.insert(std::make_pair(vi, indices)); - // } - // else - // { - // std::vector& v_surface_indices = vertices_surface_indices.at(vi); - // if (std::find(v_surface_indices.begin(), v_surface_indices.end(), surface_index) - // == v_surface_indices.end()) - // v_surface_indices.push_back(surface_index); - // } - // } - // } - //} } template @@ -324,46 +263,7 @@ namespace CGAL const VerticesSubdomainsMap& vertices_subdomain_indices, const C3t3& c3t3) { - typedef typename C3t3::Vertex_handle Vertex_handle; - typedef typename C3t3::Triangulation::Cell_circulator Cell_circulator; - typedef typename C3t3::Subdomain_index Subdomain_index; - - const typename C3t3::Triangulation& triangulation = c3t3.triangulation(); - - Vertex_handle vh0 = edge.first->vertex(edge.second); - Vertex_handle vh1 = edge.first->vertex(edge.third); - - int dim_vh0 = c3t3.in_dimension(vh0); - int dim_vh1 = c3t3.in_dimension(vh1); - - const int nb_si_vh0 = vertices_subdomain_indices.at(vh0).size(); - const int nb_si_vh1 = vertices_subdomain_indices.at(vh1).size(); - - if (nb_si_vh0 > 2 && nb_si_vh1 > 2) - { - Cell_circulator cell_circulator = triangulation.incident_cells(edge); - Cell_circulator done(cell_circulator); - - std::vector si; - do - { - Subdomain_index current_si = cell_circulator->subdomain_index(); - - if (std::find(si.begin(), si.end(), current_si) == si.end()) - si.push_back(current_si); - - if (si.size() > 2) - return true; - - } while (++cell_circulator != done); - - } - else if (c3t3.number_of_edges() > 0 && dim_vh0 == 1 && dim_vh1 == 1) - { - if(c3t3.is_in_complex(edge)) - return true; - } - return false; + return c3t3.is_in_complex(edge); } template @@ -468,7 +368,7 @@ namespace CGAL createMLSSurfaces(subdomain_FMLS, subdomain_FMLS_indices, vertices_normals, - vertices_subdomain_indices, + vertices_surface_indices, c3t3); //smooth() @@ -486,6 +386,8 @@ namespace CGAL if (!protect_boundaries) { + /////////////// EDGES IN COMPLEX ////////////////// + //collect neighbors for (const Edge& e : tr.finite_edges()) { const Vertex_handle vh0 = e.first->vertex(e.second); @@ -494,7 +396,7 @@ namespace CGAL const std::size_t& i0 = vertex_id.at(vh0); const std::size_t& i1 = vertex_id.at(vh1); - if (is_feature_MAD(e, vertices_subdomain_indices, c3t3))//c3t3.is_in_complex(e)) + if (is_feature_MAD(e, vertices_subdomain_indices, c3t3)) { if (!is_feature_MAD(vh0, vertices_subdomain_indices, c3t3)) neighbors[i0] = (std::max)(0, neighbors[i0]); @@ -571,7 +473,7 @@ namespace CGAL const std::vector& v_surface_indices = vertices_surface_indices[v]; for (const Surface_patch_index si : v_surface_indices) { - //Check if the mls surface exists to avoid degenrated cases + //Check if the mls surface exists to avoid degenerated cases Vector_3 mls_projection; if (project(si, current_pos, mls_projection, subdomain_FMLS, subdomain_FMLS_indices)) { @@ -603,6 +505,7 @@ namespace CGAL neighbors.clear(); neighbors.resize(nbv, -1); + /////////////// EDGES ON SURFACE, BUT NOT IN COMPLEX ////////////////// for (const Edge& e : tr.finite_edges()) { const Vertex_handle vh0 = e.first->vertex(e.second); @@ -696,8 +599,7 @@ namespace CGAL } } } - - //end if(!protect_boundaries) +//// end if(!protect_boundaries) smoothed_positions.clear(); smoothed_positions.resize(nbv, CGAL::NULL_VECTOR); @@ -705,6 +607,7 @@ namespace CGAL neighbors.clear(); neighbors.resize(nbv, 0); + ////////////// INTERNAL VERTICES /////////////////////// for (const Edge& e : tr.finite_edges()) { if ( !is_outside(e, c3t3, cell_selector)) @@ -715,13 +618,13 @@ namespace CGAL const std::size_t& i0 = vertex_id.at(vh0); const std::size_t& i1 = vertex_id.at(vh1); - if (c3t3.in_dimension(vh0) == 3 && !is_on_convex_hull(vh0, c3t3)) + if (c3t3.in_dimension(vh0) == 3) { const Point_3& p1 = point(vh1->point()); smoothed_positions[i0] = smoothed_positions[i0] + Vector_3(CGAL::ORIGIN, p1); neighbors[i0]++; } - if (c3t3.in_dimension(vh1) == 3 && !is_on_convex_hull(vh1, c3t3)) + if (c3t3.in_dimension(vh1) == 3) { const Point_3& p0 = point(vh0->point()); smoothed_positions[i1] = smoothed_positions[i1] + Vector_3(CGAL::ORIGIN, p0); @@ -733,10 +636,8 @@ namespace CGAL for (Vertex_handle v : tr.finite_vertex_handles()) { const std::size_t& vid = vertex_id.at(v); - if (neighbors[vid] > 1) + if (c3t3.in_dimension(v) == 3 && neighbors[vid] > 1) { -// if (smoothed_positions[vid] != CGAL::NULL_VECTOR) -// { #ifdef CGAL_TETRAHEDRAL_REMESHING_VERBOSE ++nb_done; #endif @@ -773,7 +674,6 @@ namespace CGAL //{ // frac = 0.5 * frac; //} -// } } } From 74070d3356b91d4326143cd690ce7eba4e3cbcfa Mon Sep 17 00:00:00 2001 From: Simon Giraudot Date: Mon, 9 Mar 2020 11:56:03 +0100 Subject: [PATCH 149/568] First version of clustering algorithm --- .../CGAL/boost/graph/named_params_helper.h | 13 ++ .../CGAL/boost/graph/parameters_interface.h | 1 + .../Point_set_processing_3/CMakeLists.txt | 5 +- .../clustering_example.cpp | 56 +++++ .../include/CGAL/cluster_point_set.h | 199 ++++++++++++++++++ 5 files changed, 273 insertions(+), 1 deletion(-) create mode 100644 Point_set_processing_3/examples/Point_set_processing_3/clustering_example.cpp create mode 100644 Point_set_processing_3/include/CGAL/cluster_point_set.h diff --git a/BGL/include/CGAL/boost/graph/named_params_helper.h b/BGL/include/CGAL/boost/graph/named_params_helper.h index 4c432a311c6..f5cdbf4ca63 100644 --- a/BGL/include/CGAL/boost/graph/named_params_helper.h +++ b/BGL/include/CGAL/boost/graph/named_params_helper.h @@ -23,6 +23,7 @@ #include #include +#include #include #include @@ -427,6 +428,18 @@ namespace CGAL { > ::type type; }; + template + class GetNeighborhood + { + public: + typedef Emptyset_iterator Empty; + typedef typename internal_np::Lookup_named_param_def < + internal_np::neighborhood_t, + NamedParameters, + Empty//default + > ::type type; + }; + } // namespace Point_set_processing_3 template diff --git a/BGL/include/CGAL/boost/graph/parameters_interface.h b/BGL/include/CGAL/boost/graph/parameters_interface.h index ebdce042e75..4e3232830b1 100644 --- a/BGL/include/CGAL/boost/graph/parameters_interface.h +++ b/BGL/include/CGAL/boost/graph/parameters_interface.h @@ -122,6 +122,7 @@ CGAL_add_named_parameter(plane_index_t, plane_index_map, plane_index_map) CGAL_add_named_parameter(select_percentage_t, select_percentage, select_percentage) CGAL_add_named_parameter(require_uniform_sampling_t, require_uniform_sampling, require_uniform_sampling) CGAL_add_named_parameter(point_is_constrained_t, point_is_constrained, point_is_constrained_map) +CGAL_add_named_parameter(neighborhood_t, neighborhood, neighborhood) // List of named parameters used in Surface_mesh_approximation package CGAL_add_named_parameter(verbose_level_t, verbose_level, verbose_level) diff --git a/Point_set_processing_3/examples/Point_set_processing_3/CMakeLists.txt b/Point_set_processing_3/examples/Point_set_processing_3/CMakeLists.txt index c2da826d49b..2b174b46f19 100644 --- a/Point_set_processing_3/examples/Point_set_processing_3/CMakeLists.txt +++ b/Point_set_processing_3/examples/Point_set_processing_3/CMakeLists.txt @@ -54,6 +54,7 @@ if ( CGAL_FOUND ) create_single_source_cgal_program( "edge_aware_upsample_point_set_example.cpp" ) create_single_source_cgal_program( "structuring_example.cpp" ) create_single_source_cgal_program( "callback_example.cpp" ) + create_single_source_cgal_program( "clustering_example.cpp" ) set(needed_cxx_features cxx_rvalue_references cxx_variadic_templates) create_single_source_cgal_program( "read_ply_points_with_colors_example.cpp" CXX_FEATURES ${needed_cxx_features} ) @@ -66,6 +67,7 @@ if ( CGAL_FOUND ) include_directories(${LASZIP_INCLUDE_DIR}) create_single_source_cgal_program( "read_las_example.cpp" CXX_FEATURES ${needed_cxx_features} ) target_link_libraries(read_las_example PRIVATE ${LASLIB_LIBRARIES}) + target_link_libraries(clustering_example PRIVATE ${LASLIB_LIBRARIES}) else() message(STATUS "NOTICE : the LAS reader test requires LASlib and will not be compiled.") endif() @@ -92,7 +94,8 @@ if ( CGAL_FOUND ) normals_example jet_smoothing_example normal_estimation - callback_example) + callback_example + clustering_example) if(TBB_FOUND AND TARGET ${target}) CGAL_target_use_TBB(${target}) endif() diff --git a/Point_set_processing_3/examples/Point_set_processing_3/clustering_example.cpp b/Point_set_processing_3/examples/Point_set_processing_3/clustering_example.cpp new file mode 100644 index 00000000000..ad6712a4670 --- /dev/null +++ b/Point_set_processing_3/examples/Point_set_processing_3/clustering_example.cpp @@ -0,0 +1,56 @@ +#include +#include +#include +#include +#include + +#include +#include + +using Kernel = CGAL::Exact_predicates_inexact_constructions_kernel; +using Point_3 = Kernel::Point_3; +using Point_set = CGAL::Point_set_3; + +int main (int argc, char** argv) +{ + std::ifstream ifile (argv[1], std::ios_base::binary); + Point_set points; + ifile >> points; + + Point_set::Property_map cluster_map = points.add_property_map ("cluster", -1).first; + + double spacing = CGAL::compute_average_spacing (points, 12); + + std::cerr << "Spacing = " << spacing << std::endl; + + std::vector > adjacencies; + + CGAL::Real_timer t; + t.start(); + std::size_t nb_clusters + = CGAL::cluster_point_set (points, cluster_map, 0, + points.parameters().neighbor_radius(spacing). + neighborhood (std::back_inserter (adjacencies))); + t.stop(); + std::cerr << "Found " << nb_clusters << " clusters with " << adjacencies.size() + << " adjacencies in " << t.time() << " seconds" << std::endl; + + Point_set::Property_map red = points.add_property_map("red", 0).first; + Point_set::Property_map green = points.add_property_map("green", 0).first; + Point_set::Property_map blue = points.add_property_map("blue", 0).first; + + for (Point_set::Index idx : points) + { + CGAL::Random rand (cluster_map[idx]); + + red[idx] = rand.get_int(64, 192); + green[idx] = rand.get_int(64, 192); + blue[idx] = rand.get_int(64, 192); + } + + std::ofstream ofile ("out.ply", std::ios_base::binary); + CGAL::set_binary_mode (ofile); + ofile << points; + + return EXIT_SUCCESS; +} diff --git a/Point_set_processing_3/include/CGAL/cluster_point_set.h b/Point_set_processing_3/include/CGAL/cluster_point_set.h new file mode 100644 index 00000000000..c15c38cec2c --- /dev/null +++ b/Point_set_processing_3/include/CGAL/cluster_point_set.h @@ -0,0 +1,199 @@ +// Copyright (c) 2020 GeometryFactory Sarl (France). +// All rights reserved. +// +// This file is part of CGAL (www.cgal.org). +// +// $URL$ +// $Id$ +// SPDX-License-Identifier: GPL-3.0-or-later OR LicenseRef-Commercial +// +// Author(s) : Simon Giraudot + +#ifndef CGAL_CLUSTER_POINT_SET_H +#define CGAL_CLUSTER_POINT_SET_H + +#include + +#include +#include +#include +#include + +#include + +namespace CGAL +{ + +namespace Point_set_processing_3 +{ + +namespace internal +{ + +// Trick to both compile version with Emptyset_iterator and with +// user-provided OutputIterator. Many output iterators (such as +// `std::back_insert_iterator`) cannot be default constructed, which +// makes the mechanism `choose_param(get_param(...),Default())` fails. +template +OutputIterator get_neighborhood (const NamedParameters& np, OutputIterator*) +{ + return CGAL::parameters::get_parameter(np, internal_np::neighborhood); +} + +template +CGAL::Emptyset_iterator get_neighborhood (const NamedParameters&, CGAL::Emptyset_iterator*) +{ + return CGAL::Emptyset_iterator(); +} + +} // namespace internal + +} // namespace Point_set_processing_3 + +template +std::size_t cluster_point_set (PointRange& points, + ClusterMap cluster_map, + unsigned int k, + const NamedParameters& np) +{ + using parameters::choose_parameter; + using parameters::get_parameter; + + // basic geometric types + typedef typename PointRange::iterator iterator; + typedef typename iterator::value_type value_type; + typedef typename Point_set_processing_3::GetPointMap::type PointMap; + typedef typename Point_set_processing_3::GetK::Kernel Kernel; + typedef typename Point_set_processing_3::GetNeighborhood::type Neighborhood; + typedef typename GetSvdTraits::type SvdTraits; + + CGAL_static_assertion_msg(!(boost::is_same::NoTraits>::value), + "Error: no SVD traits"); + + PointMap point_map = choose_parameter(get_parameter(np, internal_np::point_map), PointMap()); + typename Kernel::FT neighbor_radius = choose_parameter(get_parameter(np, internal_np::neighbor_radius), + typename Kernel::FT(0)); + typename Kernel::FT factor = choose_parameter(get_parameter(np, internal_np::attraction_factor), + typename Kernel::FT(2)); + + const std::function& callback = choose_parameter(get_parameter(np, internal_np::callback), + std::function()); + + double callback_factor = 1.; + if (!std::is_same::Empty>::value) + callback_factor = 0.5; + + typedef typename Kernel::Point_3 Point; + + // types for K nearest neighbors search structure + typedef Point_set_processing_3::internal::Neighbor_query Neighbor_query; + + // precondition: at least one element in the container. + // to fix: should have at least three distinct points + // but this is costly to check + CGAL_point_set_processing_precondition(points.begin() != points.end()); + + // precondition: at least 2 nearest neighbors + CGAL_point_set_processing_precondition(k >= 2); + + // Init cluster map with -1 + for (const value_type& p : points) + put (cluster_map, p, -1); + + Neighbor_query neighbor_query (points, point_map); + + std::queue todo; + std::size_t nb_clusters = 0; + + // Flooding algorithm from each point + std::size_t done = 0; + std::size_t size = points.size(); + + for (iterator it = points.begin(); it != points.end(); ++ it) + { + const value_type& p = *it; + + if (get (cluster_map, p) != -1) + continue; + + todo.push (it); + + while (!todo.empty()) + { + iterator current = todo.front(); + todo.pop(); + + if (get (cluster_map, *current) != -1) + continue; + + put (cluster_map, *current, nb_clusters); + ++ done; + + if (callback && !callback (callback_factor * (done + 1) / double(size))) + return (nb_clusters + 1); + + neighbor_query.get_iterators (get (point_map, *current), k, neighbor_radius, + boost::make_function_output_iterator + ([&](const iterator& it) { todo.push(it); })); + + } + + ++ nb_clusters; + } + + if (!std::is_same::Empty>::value) + { + Neighborhood neighborhood = Point_set_processing_3::internal::get_neighborhood(np, (Neighborhood*)(nullptr)); + k *= factor; + neighbor_radius *= factor; + + std::vector neighbors; + std::vector > adjacencies; + + done = 0; + for (const value_type& p : points) + { + std::size_t c0 = get (cluster_map, p); + + neighbors.clear(); + neighbor_query.get_iterators (get (point_map, p), k, neighbor_radius, + std::back_inserter (neighbors)); + + for (const iterator& it : neighbors) + { + std::size_t c1 = get (cluster_map, *it); + if (c0 < c1) + adjacencies.push_back (std::make_pair (c0, c1)); + else if (c0 > c1) + adjacencies.push_back (std::make_pair (c1, c0)); + // else c0 == c1, ignore + } + + ++ done; + if (callback && !callback (callback_factor + callback_factor * (done + 1) / double(size))) + return nb_clusters; + } + std::sort (adjacencies.begin(), adjacencies.end()); + auto last = std::unique (adjacencies.begin(), adjacencies.end()); + std::copy (adjacencies.begin(), last, neighborhood); + } + + return nb_clusters; +} + +template +std::size_t cluster_point_set (PointRange& points, + ClusterMap cluster_map, + unsigned int k) +{ + return cluster_point_set (points, cluster_map, k, + CGAL::Point_set_processing_3::parameters::all_default(points)); +} + +} // namespace CGAL + + +#endif // CGAL_CLUSTER_POINT_SET_H From 2bfac0bc86a9c81955f6c3398b64772ede7765a3 Mon Sep 17 00:00:00 2001 From: Simon Giraudot Date: Mon, 9 Mar 2020 12:44:49 +0100 Subject: [PATCH 150/568] Reference manual for cluster_point_set() --- .../PackageDescription.txt | 1 + .../include/CGAL/cluster_point_set.h | 45 +++++++++++++++++++ 2 files changed, 46 insertions(+) diff --git a/Point_set_processing_3/doc/Point_set_processing_3/PackageDescription.txt b/Point_set_processing_3/doc/Point_set_processing_3/PackageDescription.txt index dc3bf7ab968..cfe7e23f2a5 100644 --- a/Point_set_processing_3/doc/Point_set_processing_3/PackageDescription.txt +++ b/Point_set_processing_3/doc/Point_set_processing_3/PackageDescription.txt @@ -52,6 +52,7 @@ format. - `CGAL::estimate_local_k_neighbor_scales()` - `CGAL::estimate_local_range_scales()` - `CGAL::remove_outliers()` +- `CGAL::cluster_point_set()` - `CGAL::grid_simplify_point_set()` - `CGAL::random_simplify_point_set()` - `CGAL::hierarchy_simplify_point_set()` diff --git a/Point_set_processing_3/include/CGAL/cluster_point_set.h b/Point_set_processing_3/include/CGAL/cluster_point_set.h index c15c38cec2c..b1d30c8654f 100644 --- a/Point_set_processing_3/include/CGAL/cluster_point_set.h +++ b/Point_set_processing_3/include/CGAL/cluster_point_set.h @@ -24,6 +24,8 @@ namespace CGAL { + +/// \cond SKIP_IN_MANUAL namespace Point_set_processing_3 { @@ -49,7 +51,47 @@ CGAL::Emptyset_iterator get_neighborhood (const NamedParameters&, CGAL::Emptyset } // namespace internal } // namespace Point_set_processing_3 +/// \endcond +// ---------------------------------------------------------------------------- +// Public section +// ---------------------------------------------------------------------------- + +/** + \ingroup PkgPointSetProcessing3Algorithms + Identifies simply connected clusters on a nearest neighbors graph. + + \tparam PointRange is a model of `Range`. The value type of its + iterator is the key type of the named parameter `point_map`. + \tparam ClusterMap is a model of `ReadWritePropertyMap` with value + type `std::size_t`. + + \param points input point range. + \param cluster_map maps each point to the index of the cluster it belongs to. + \param k number of neighbors. + \param np optional sequence of \ref psp_namedparameters "Named Parameters" among the ones listed below. + + \cgalNamedParamsBegin + \cgalParamBegin{point_map} a model of `ReadablePropertyMap` with value type `geom_traits::Point_3`. + If this parameter is omitted, `CGAL::Identity_property_map` is used.\cgalParamEnd + \cgalParamBegin{callback} an instance of + `std::function`. It is called regularly when the + algorithm is running: the current advancement (between 0. and + 1.) is passed as parameter. If it returns `true`, then the + algorithm continues its execution normally; if it returns + `false`, the algorithm is stopped and the number of already + computed clusters is returned.\cgalParamEnd + \cgalParamBegin{neighbor_radius} spherical neighborhood radius. If + provided, the neighborhood of a query point is computed with a fixed spherical + radius instead of a fixed number of neighbors. In that case, the parameter + `k` is used as a limit on the number of points returned by each spherical + query (to avoid overly large number of points in high density areas). If no + limit is wanted, use `k=0`.\cgalParamEnd + \cgalParamBegin{geom_traits} an instance of a geometric traits class, model of `Kernel`\cgalParamEnd + \cgalNamedParamsEnd + + \return the number of clusters identified. +*/ template std::size_t cluster_point_set (PointRange& points, ClusterMap cluster_map, @@ -184,6 +226,8 @@ std::size_t cluster_point_set (PointRange& points, return nb_clusters; } +/// \cond SKIP_IN_MANUAL +// overload with default NP template std::size_t cluster_point_set (PointRange& points, ClusterMap cluster_map, @@ -192,6 +236,7 @@ std::size_t cluster_point_set (PointRange& points, return cluster_point_set (points, cluster_map, k, CGAL::Point_set_processing_3::parameters::all_default(points)); } +/// \endcond } // namespace CGAL From 61ee057c40a35813d036c6f8b67f3a7432fb77c2 Mon Sep 17 00:00:00 2001 From: Simon Giraudot Date: Mon, 9 Mar 2020 16:41:01 +0100 Subject: [PATCH 151/568] Add clustering plugin --- .../Plugins/Point_set/CMakeLists.txt | 3 + .../Point_set/Point_set_clustering_plugin.cpp | 176 ++++++++++++++++++ 2 files changed, 179 insertions(+) create mode 100644 Polyhedron/demo/Polyhedron/Plugins/Point_set/Point_set_clustering_plugin.cpp diff --git a/Polyhedron/demo/Polyhedron/Plugins/Point_set/CMakeLists.txt b/Polyhedron/demo/Polyhedron/Plugins/Point_set/CMakeLists.txt index 12b2e9f9056..005a075bf7f 100644 --- a/Polyhedron/demo/Polyhedron/Plugins/Point_set/CMakeLists.txt +++ b/Polyhedron/demo/Polyhedron/Plugins/Point_set/CMakeLists.txt @@ -77,6 +77,9 @@ endif() polyhedron_demo_plugin(point_set_wlop_plugin Point_set_wlop_plugin ${point_set_wlopFILES} KEYWORDS PointSetProcessing) target_link_libraries(point_set_wlop_plugin PUBLIC scene_points_with_normal_item scene_callback_signaler) + polyhedron_demo_plugin(point_set_clustering_plugin Point_set_clustering_plugin KEYWORDS PointSetProcessing) + target_link_libraries(point_set_clustering_plugin PUBLIC scene_points_with_normal_item scene_callback_signaler) + polyhedron_demo_plugin(merge_point_sets_plugin Merge_point_sets_plugin KEYWORDS PointSetProcessing Classification) target_link_libraries(merge_point_sets_plugin PUBLIC scene_points_with_normal_item) diff --git a/Polyhedron/demo/Polyhedron/Plugins/Point_set/Point_set_clustering_plugin.cpp b/Polyhedron/demo/Polyhedron/Plugins/Point_set/Point_set_clustering_plugin.cpp new file mode 100644 index 00000000000..71599e9f6e2 --- /dev/null +++ b/Polyhedron/demo/Polyhedron/Plugins/Point_set/Point_set_clustering_plugin.cpp @@ -0,0 +1,176 @@ +#include "config.h" +#include "Scene_points_with_normal_item.h" +#include +#include +#include + +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include "run_with_qprogressdialog.h" + +struct Clustering_functor + : public Functor_with_signal_callback +{ + Point_set* points; + Point_set::Property_map cluster_map; + const int nb_neighbors; + const double neighbor_radius; + boost::shared_ptr result; + + Clustering_functor (Point_set* points, const int nb_neighbors, + const double neighbor_radius, + Point_set::Property_map cluster_map) + : points (points), cluster_map (cluster_map), + nb_neighbors (nb_neighbors), neighbor_radius (neighbor_radius), + result (new std::size_t(0)) { } + + void operator()() + { + *result = CGAL::cluster_point_set (*points, cluster_map, nb_neighbors, + points->parameters().neighbor_radius(neighbor_radius). + callback(*(this->callback()))); + } +}; + +using namespace CGAL::Three; + +class Polyhedron_demo_point_set_clustering_plugin : + public QObject, + public Polyhedron_demo_plugin_helper +{ + Q_OBJECT + Q_INTERFACES(CGAL::Three::Polyhedron_demo_plugin_interface) + Q_PLUGIN_METADATA(IID "com.geometryfactory.PolyhedronDemo.PluginInterface/1.0") + + QAction* actionCluster; + +public: + void init(QMainWindow* mainWindow, CGAL::Three::Scene_interface* scene_interface, Messages_interface*) { + + scene = scene_interface; + mw = mainWindow; + actionCluster = new QAction(tr("Cluster Point Set"), mainWindow); + actionCluster->setObjectName("actionCluster"); + actionCluster->setProperty("subMenuName","Point Set Processing"); + autoConnectActions(); + } + + QList actions() const { + return QList() << actionCluster; + } + + bool applicable(QAction* action) const { + Scene_points_with_normal_item* item = qobject_cast(scene->item(scene->mainSelectionIndex())); + return item; + } + +public Q_SLOTS: + void on_actionCluster_triggered(); + +}; // end + +void Polyhedron_demo_point_set_clustering_plugin::on_actionCluster_triggered() +{ + const CGAL::Three::Scene_interface::Item_id index = scene->mainSelectionIndex(); + + Scene_points_with_normal_item* item = + qobject_cast(scene->item(index)); + + if(item) + { + // Gets point set + Point_set* points = item->point_set(); + if(points == NULL) + return; + + QMultipleInputDialog dialog ("Clustering", mw); + QSpinBox* nb_neighbors = dialog.add ("Number of neighbors (0 = use radius):"); + nb_neighbors->setRange (0, 10000000); + nb_neighbors->setValue (12); + QDoubleSpinBox* neighbor_radius = dialog.add ("Neighbor radius (0 = use number):"); + neighbor_radius->setRange (0, 10000000); + neighbor_radius->setValue (0); + QSpinBox* min_nb = dialog.add ("Minimum number of points per cluster:"); + min_nb->setRange (1, 10000000); + min_nb->setValue (1); + + if (!dialog.exec()) + return; + + QApplication::setOverrideCursor(Qt::BusyCursor); + QApplication::processEvents(); + CGAL::Real_timer task_timer; task_timer.start(); + + Point_set::Property_map + cluster_map = points->add_property_map ("cluster_point_set_property_map").first; + + // Computes average spacing + Clustering_functor functor (points, nb_neighbors->value(), neighbor_radius->value(), cluster_map); + run_with_qprogressdialog (functor, "Clustering...", mw); + + std::size_t nb_clusters = *functor.result; + + CGAL::Random rand(static_cast(time(0))); + + Scene_group_item* group = new Scene_group_item(QString("%1 (clusters)").arg(item->name())); + scene->addItem(group); + + std::vector new_items; + new_items.reserve (nb_clusters); + for (std::size_t i = 0; i < nb_clusters; ++ i) + { + Scene_points_with_normal_item* new_item = new Scene_points_with_normal_item; + new_item->point_set()->copy_properties (*points); + unsigned char r, g, b; + r = static_cast(64 + rand.get_int(0, 192)); + g = static_cast(64 + rand.get_int(0, 192)); + b = static_cast(64 + rand.get_int(0, 192)); + new_item->setRgbColor(r, g, b); + new_item->setName (QString("Cluster %1 of %2").arg(i).arg(item->name())); + new_items.push_back (new_item); + } + + for (Point_set::Index idx : *points) + new_items[cluster_map[idx]]->point_set()->insert (*points, idx); + + for (Scene_points_with_normal_item* new_item : new_items) + { + if (new_item->point_set()->size() >= min_nb->value()) + { + scene->addItem(new_item); + scene->changeGroup (new_item, group); + } + else + delete new_item; + } + + std::size_t memory = CGAL::Memory_sizer().virtual_size(); + std::cerr << "Number of clusters = " << nb_clusters << " (" + << task_timer.time() << " seconds, " + << (memory>>20) << " Mb allocated)" + << std::endl; + QApplication::restoreOverrideCursor(); + + item->setVisible (false); + item->invalidateOpenGLBuffers(); + scene->itemChanged(item); + } +} + + + +#include "Point_set_clustering_plugin.moc" From 5cf4b4acfd99f57a40d5aa5462523ba1e038ac0a Mon Sep 17 00:00:00 2001 From: Simon Giraudot Date: Tue, 10 Mar 2020 13:39:04 +0100 Subject: [PATCH 152/568] Improve plugin --- .../Point_set/Point_set_clustering_plugin.cpp | 117 ++++++++++++++---- 1 file changed, 90 insertions(+), 27 deletions(-) diff --git a/Polyhedron/demo/Polyhedron/Plugins/Point_set/Point_set_clustering_plugin.cpp b/Polyhedron/demo/Polyhedron/Plugins/Point_set/Point_set_clustering_plugin.cpp index 71599e9f6e2..565c7e7e572 100644 --- a/Polyhedron/demo/Polyhedron/Plugins/Point_set/Point_set_clustering_plugin.cpp +++ b/Polyhedron/demo/Polyhedron/Plugins/Point_set/Point_set_clustering_plugin.cpp @@ -17,6 +17,7 @@ #include #include #include +#include #include @@ -108,6 +109,15 @@ void Polyhedron_demo_point_set_clustering_plugin::on_actionCluster_triggered() min_nb->setRange (1, 10000000); min_nb->setValue (1); + QCheckBox* add_property = dialog.add ("Add a \"cluster\" property to the input item"); + add_property->setChecked (true); + + QCheckBox* gen_color = dialog.add ("Generate one colored point set"); + gen_color->setChecked (true); + + QCheckBox* gen_sub = dialog.add ("Generate N point subsets"); + gen_sub->setChecked (false); + if (!dialog.exec()) return; @@ -115,7 +125,12 @@ void Polyhedron_demo_point_set_clustering_plugin::on_actionCluster_triggered() QApplication::processEvents(); CGAL::Real_timer task_timer; task_timer.start(); - Point_set::Property_map + Point_set::Property_map cluster_map; + + if (add_property->isChecked()) + cluster_map = points->add_property_map ("cluster_map").first; + else + // Use long name to avoid overwriting potentially existing map cluster_map = points->add_property_map ("cluster_point_set_property_map").first; // Computes average spacing @@ -124,39 +139,87 @@ void Polyhedron_demo_point_set_clustering_plugin::on_actionCluster_triggered() std::size_t nb_clusters = *functor.result; - CGAL::Random rand(static_cast(time(0))); - Scene_group_item* group = new Scene_group_item(QString("%1 (clusters)").arg(item->name())); - scene->addItem(group); - + Scene_group_item* group; std::vector new_items; - new_items.reserve (nb_clusters); - for (std::size_t i = 0; i < nb_clusters; ++ i) - { - Scene_points_with_normal_item* new_item = new Scene_points_with_normal_item; - new_item->point_set()->copy_properties (*points); - unsigned char r, g, b; - r = static_cast(64 + rand.get_int(0, 192)); - g = static_cast(64 + rand.get_int(0, 192)); - b = static_cast(64 + rand.get_int(0, 192)); - new_item->setRgbColor(r, g, b); - new_item->setName (QString("Cluster %1 of %2").arg(i).arg(item->name())); - new_items.push_back (new_item); - } - for (Point_set::Index idx : *points) - new_items[cluster_map[idx]]->point_set()->insert (*points, idx); - - for (Scene_points_with_normal_item* new_item : new_items) + if (gen_sub->isChecked()) { - if (new_item->point_set()->size() >= min_nb->value()) + group = new Scene_group_item(QString("%1 (clusters)").arg(item->name())); + scene->addItem(group); + new_items.reserve (nb_clusters); + for (std::size_t i = 0; i < nb_clusters; ++ i) { - scene->addItem(new_item); - scene->changeGroup (new_item, group); + Scene_points_with_normal_item* new_item = new Scene_points_with_normal_item; + new_item->point_set()->copy_properties (*points); + CGAL::Random rand(i); + unsigned char r, g, b; + r = static_cast(64 + rand.get_int(0, 192)); + g = static_cast(64 + rand.get_int(0, 192)); + b = static_cast(64 + rand.get_int(0, 192)); + new_item->setRgbColor(r, g, b); + new_item->setName (QString("Cluster %1 of %2").arg(i).arg(item->name())); + new_items.push_back (new_item); } - else - delete new_item; } + + std::vector cluster_size (nb_clusters, 0); + for (Point_set::Index idx : *points) + { + if (gen_sub->isChecked()) + new_items[cluster_map[idx]]->point_set()->insert (*points, idx); + cluster_size[cluster_map[idx]] ++; + } + + if (gen_color->isChecked()) + { + Scene_points_with_normal_item* colored; + Point_set::Property_map red, green, blue; + + colored = new Scene_points_with_normal_item; + colored->setName (QString("%1 (clustering)").arg(item->name())); + + red = colored->point_set()->add_property_map("red", 0).first; + green = colored->point_set()->add_property_map("green", 0).first; + blue = colored->point_set()->add_property_map("blue", 0).first; + colored->point_set()->check_colors(); + + colored->point_set()->reserve (points->size()); + + for (Point_set::Index idx : *points) + { + Point_set::Index iidx = *(colored->point_set()->insert (points->point(idx))); + if (cluster_size[cluster_map[idx]] >= min_nb->value()) + { + CGAL::Random rand(cluster_map[idx]); + unsigned char r, g, b; + r = static_cast(64 + rand.get_int(0, 192)); + g = static_cast(64 + rand.get_int(0, 192)); + b = static_cast(64 + rand.get_int(0, 192)); + red[iidx] = r; + green[iidx] = g; + blue[iidx] = b; + } + } + scene->addItem(colored); + } + + if (gen_sub->isChecked()) + { + for (Scene_points_with_normal_item* new_item : new_items) + { + if (new_item->point_set()->size() >= min_nb->value()) + { + scene->addItem(new_item); + scene->changeGroup (new_item, group); + } + else + delete new_item; + } + } + + if (!add_property->isChecked()) + points->remove_property_map (cluster_map); std::size_t memory = CGAL::Memory_sizer().virtual_size(); std::cerr << "Number of clusters = " << nb_clusters << " (" From 7cba1cc1aac1585d7d1506740e2a9b1779bc0194 Mon Sep 17 00:00:00 2001 From: Simon Giraudot Date: Tue, 10 Mar 2020 14:40:41 +0100 Subject: [PATCH 153/568] Document cluster_point_set() --- .../CGAL/boost/graph/named_params_helper.h | 4 +- .../CGAL/boost/graph/parameters_interface.h | 2 +- .../NamedParameters.txt | 9 ++++- .../PackageDescription.txt | 2 +- .../Point_set_processing_3.txt | 16 ++++++++ .../doc/Point_set_processing_3/examples.txt | 1 + .../clustering_example.cpp | 14 ++++--- .../include/CGAL/cluster_point_set.h | 40 ++++++++++++------- 8 files changed, 63 insertions(+), 25 deletions(-) diff --git a/BGL/include/CGAL/boost/graph/named_params_helper.h b/BGL/include/CGAL/boost/graph/named_params_helper.h index f5cdbf4ca63..2bfe81a3d83 100644 --- a/BGL/include/CGAL/boost/graph/named_params_helper.h +++ b/BGL/include/CGAL/boost/graph/named_params_helper.h @@ -429,12 +429,12 @@ namespace CGAL { }; template - class GetNeighborhood + class GetAdjacencies { public: typedef Emptyset_iterator Empty; typedef typename internal_np::Lookup_named_param_def < - internal_np::neighborhood_t, + internal_np::adjacencies_t, NamedParameters, Empty//default > ::type type; diff --git a/BGL/include/CGAL/boost/graph/parameters_interface.h b/BGL/include/CGAL/boost/graph/parameters_interface.h index 4e3232830b1..6aca16a7090 100644 --- a/BGL/include/CGAL/boost/graph/parameters_interface.h +++ b/BGL/include/CGAL/boost/graph/parameters_interface.h @@ -122,7 +122,7 @@ CGAL_add_named_parameter(plane_index_t, plane_index_map, plane_index_map) CGAL_add_named_parameter(select_percentage_t, select_percentage, select_percentage) CGAL_add_named_parameter(require_uniform_sampling_t, require_uniform_sampling, require_uniform_sampling) CGAL_add_named_parameter(point_is_constrained_t, point_is_constrained, point_is_constrained_map) -CGAL_add_named_parameter(neighborhood_t, neighborhood, neighborhood) +CGAL_add_named_parameter(adjacencies_t, adjacencies, adjacencies) // List of named parameters used in Surface_mesh_approximation package CGAL_add_named_parameter(verbose_level_t, verbose_level, verbose_level) diff --git a/Point_set_processing_3/doc/Point_set_processing_3/NamedParameters.txt b/Point_set_processing_3/doc/Point_set_processing_3/NamedParameters.txt index e2c64e40efb..a262ab6c54e 100644 --- a/Point_set_processing_3/doc/Point_set_processing_3/NamedParameters.txt +++ b/Point_set_processing_3/doc/Point_set_processing_3/NamedParameters.txt @@ -140,7 +140,7 @@ is the minimum distance for a point to be considered as outlier \cgalNPEnd \cgalNPBegin{attraction_factor} \anchor PSP_attraction_factor -multiple of a tolerance `epsilon` used to connect simplices. +multiplication factor used for adjacency computations. \b Type: floating scalar value\n Default value: `3` \cgalNPEnd @@ -191,6 +191,13 @@ Constrained points are left unaltered and are used as seeds in `mst_orient_norma Default value: a property map with only the highest point constrained. \cgalNPEnd +\cgalNPBegin{adjacencies} \anchor PSP_adjacencies +is an output iterator used to store adjacencies.\n +\b Type: a class model of `OutputIterator` that accepts objects of +type `std::pair`. \n +Default value: `CGAL::Emptyset_iterator`. +\cgalNPEnd + \cgalNPTableEnd */ diff --git a/Point_set_processing_3/doc/Point_set_processing_3/PackageDescription.txt b/Point_set_processing_3/doc/Point_set_processing_3/PackageDescription.txt index cfe7e23f2a5..4d66256942b 100644 --- a/Point_set_processing_3/doc/Point_set_processing_3/PackageDescription.txt +++ b/Point_set_processing_3/doc/Point_set_processing_3/PackageDescription.txt @@ -55,7 +55,7 @@ format. - `CGAL::cluster_point_set()` - `CGAL::grid_simplify_point_set()` - `CGAL::random_simplify_point_set()` -- `CGAL::hierarchy_simplify_point_set()` +- `CGAL::hierarchy_simplify_point_set()` - `CGAL::wlop_simplify_and_regularize_point_set()` - `CGAL::jet_smooth_point_set()` - `CGAL::bilateral_smooth_point_set()` diff --git a/Point_set_processing_3/doc/Point_set_processing_3/Point_set_processing_3.txt b/Point_set_processing_3/doc/Point_set_processing_3/Point_set_processing_3.txt index 275ecf450fb..3bb77da6a41 100644 --- a/Point_set_processing_3/doc/Point_set_processing_3/Point_set_processing_3.txt +++ b/Point_set_processing_3/doc/Point_set_processing_3/Point_set_processing_3.txt @@ -314,7 +314,23 @@ points in the domain. \cgalExample{Point_set_processing_3/scale_estimation_2d_example.cpp} +\section Point_set_processing_3Clustering Clustering +If an input point set represents several objects which are spatially +separated, a clustering algorithm can be applied to identify simply +connected clusters on a nearest neighbors graph. + +The clustering is stored in a cluster map which associates each input +point with the index of the cluster it belongs to: users can then use +this map however they find it relevant to their use case, for example +segmenting the input point set into several (one per cluster). + +\subsection Point_set_processing_3Example_clustering Example + +In the following example, clusters (and adjacencies between them) are +computed and stored as colors in a PLY file: + +\cgalExample{Point_set_processing_3/clustering_example.cpp} \section Point_set_processing_3OutlierRemoval Outlier Removal diff --git a/Point_set_processing_3/doc/Point_set_processing_3/examples.txt b/Point_set_processing_3/doc/Point_set_processing_3/examples.txt index 43849ae022c..b34a2fae0c2 100644 --- a/Point_set_processing_3/doc/Point_set_processing_3/examples.txt +++ b/Point_set_processing_3/doc/Point_set_processing_3/examples.txt @@ -6,6 +6,7 @@ \example Point_set_processing_3/average_spacing_example.cpp \example Point_set_processing_3/scale_estimation_example.cpp \example Point_set_processing_3/scale_estimation_2d_example.cpp +\example Point_set_processing_3/clustering_example.cpp \example Point_set_processing_3/remove_outliers_example.cpp \example Point_set_processing_3/grid_simplification_example.cpp \example Point_set_processing_3/grid_simplify_indices.cpp diff --git a/Point_set_processing_3/examples/Point_set_processing_3/clustering_example.cpp b/Point_set_processing_3/examples/Point_set_processing_3/clustering_example.cpp index ad6712a4670..8ec3cc7e69d 100644 --- a/Point_set_processing_3/examples/Point_set_processing_3/clustering_example.cpp +++ b/Point_set_processing_3/examples/Point_set_processing_3/clustering_example.cpp @@ -13,36 +13,40 @@ using Point_set = CGAL::Point_set_3; int main (int argc, char** argv) { + // Read input file std::ifstream ifile (argv[1], std::ios_base::binary); Point_set points; ifile >> points; + // Add a cluster map Point_set::Property_map cluster_map = points.add_property_map ("cluster", -1).first; + // Compute average spacing double spacing = CGAL::compute_average_spacing (points, 12); - std::cerr << "Spacing = " << spacing << std::endl; + // Adjacencies stored in vector std::vector > adjacencies; - + + // Compute clusters CGAL::Real_timer t; t.start(); std::size_t nb_clusters = CGAL::cluster_point_set (points, cluster_map, 0, points.parameters().neighbor_radius(spacing). - neighborhood (std::back_inserter (adjacencies))); + adjacencies (std::back_inserter (adjacencies))); t.stop(); std::cerr << "Found " << nb_clusters << " clusters with " << adjacencies.size() << " adjacencies in " << t.time() << " seconds" << std::endl; + // Output a colored PLY file Point_set::Property_map red = points.add_property_map("red", 0).first; Point_set::Property_map green = points.add_property_map("green", 0).first; Point_set::Property_map blue = points.add_property_map("blue", 0).first; - for (Point_set::Index idx : points) { + // One color per cluster CGAL::Random rand (cluster_map[idx]); - red[idx] = rand.get_int(64, 192); green[idx] = rand.get_int(64, 192); blue[idx] = rand.get_int(64, 192); diff --git a/Point_set_processing_3/include/CGAL/cluster_point_set.h b/Point_set_processing_3/include/CGAL/cluster_point_set.h index b1d30c8654f..ef344707637 100644 --- a/Point_set_processing_3/include/CGAL/cluster_point_set.h +++ b/Point_set_processing_3/include/CGAL/cluster_point_set.h @@ -37,13 +37,13 @@ namespace internal // `std::back_insert_iterator`) cannot be default constructed, which // makes the mechanism `choose_param(get_param(...),Default())` fails. template -OutputIterator get_neighborhood (const NamedParameters& np, OutputIterator*) +OutputIterator get_adjacencies (const NamedParameters& np, OutputIterator*) { - return CGAL::parameters::get_parameter(np, internal_np::neighborhood); + return CGAL::parameters::get_parameter(np, internal_np::adjacencies); } template -CGAL::Emptyset_iterator get_neighborhood (const NamedParameters&, CGAL::Emptyset_iterator*) +CGAL::Emptyset_iterator get_adjacencies (const NamedParameters&, CGAL::Emptyset_iterator*) { return CGAL::Emptyset_iterator(); } @@ -87,6 +87,16 @@ CGAL::Emptyset_iterator get_neighborhood (const NamedParameters&, CGAL::Emptyset `k` is used as a limit on the number of points returned by each spherical query (to avoid overly large number of points in high density areas). If no limit is wanted, use `k=0`.\cgalParamEnd + \cgalParamBegin{attraction_factor} used to compute adjacencies + between clusters. Adjacencies are computed using a nearest + neighbor graph built similarly to the one used for clustering, + using `attraction_factor * k` and `attraction_factor * + nearest_neighbors` as parameters. %Default value is `2`.\cgalParamEnd + \cgalParamBegin{adjacencies} model of `OutputIterator` that + accepts objects of type `std::pair`. Each pair contains the indices of two adjacent + clusters. If this parameter is not used, adjacencies are not + computed at all.\cgalParamEnd \cgalParamBegin{geom_traits} an instance of a geometric traits class, model of `Kernel`\cgalParamEnd \cgalNamedParamsEnd @@ -106,7 +116,7 @@ std::size_t cluster_point_set (PointRange& points, typedef typename iterator::value_type value_type; typedef typename Point_set_processing_3::GetPointMap::type PointMap; typedef typename Point_set_processing_3::GetK::Kernel Kernel; - typedef typename Point_set_processing_3::GetNeighborhood::type Neighborhood; + typedef typename Point_set_processing_3::GetAdjacencies::type Adjacencies; typedef typename GetSvdTraits::type SvdTraits; CGAL_static_assertion_msg(!(boost::is_same()); double callback_factor = 1.; - if (!std::is_same::Empty>::value) + if (!std::is_same::Empty>::value) callback_factor = 0.5; typedef typename Kernel::Point_3 Point; @@ -185,15 +195,15 @@ std::size_t cluster_point_set (PointRange& points, ++ nb_clusters; } - if (!std::is_same::Empty>::value) + if (!std::is_same::Empty>::value) { - Neighborhood neighborhood = Point_set_processing_3::internal::get_neighborhood(np, (Neighborhood*)(nullptr)); + Adjacencies adjacencies = Point_set_processing_3::internal::get_adjacencies(np, (Adjacencies*)(nullptr)); k *= factor; neighbor_radius *= factor; std::vector neighbors; - std::vector > adjacencies; + std::vector > adj; done = 0; for (const value_type& p : points) @@ -208,9 +218,9 @@ std::size_t cluster_point_set (PointRange& points, { std::size_t c1 = get (cluster_map, *it); if (c0 < c1) - adjacencies.push_back (std::make_pair (c0, c1)); + adj.push_back (std::make_pair (c0, c1)); else if (c0 > c1) - adjacencies.push_back (std::make_pair (c1, c0)); + adj.push_back (std::make_pair (c1, c0)); // else c0 == c1, ignore } @@ -218,9 +228,9 @@ std::size_t cluster_point_set (PointRange& points, if (callback && !callback (callback_factor + callback_factor * (done + 1) / double(size))) return nb_clusters; } - std::sort (adjacencies.begin(), adjacencies.end()); - auto last = std::unique (adjacencies.begin(), adjacencies.end()); - std::copy (adjacencies.begin(), last, neighborhood); + std::sort (adj.begin(), adj.end()); + auto last = std::unique (adj.begin(), adj.end()); + std::copy (adj.begin(), last, adjacencies); } return nb_clusters; From 80e8283706eddca4c15dd9a2d6cdaf3ae821da42 Mon Sep 17 00:00:00 2001 From: Simon Giraudot Date: Thu, 12 Mar 2020 09:59:49 +0100 Subject: [PATCH 154/568] Fix errors --- .../examples/Point_set_processing_3/clustering_example.cpp | 2 ++ Point_set_processing_3/include/CGAL/cluster_point_set.h | 3 +++ 2 files changed, 5 insertions(+) diff --git a/Point_set_processing_3/examples/Point_set_processing_3/clustering_example.cpp b/Point_set_processing_3/examples/Point_set_processing_3/clustering_example.cpp index 8ec3cc7e69d..737913b6521 100644 --- a/Point_set_processing_3/examples/Point_set_processing_3/clustering_example.cpp +++ b/Point_set_processing_3/examples/Point_set_processing_3/clustering_example.cpp @@ -7,6 +7,8 @@ #include #include +#include + using Kernel = CGAL::Exact_predicates_inexact_constructions_kernel; using Point_3 = Kernel::Point_3; using Point_set = CGAL::Point_set_3; diff --git a/Point_set_processing_3/include/CGAL/cluster_point_set.h b/Point_set_processing_3/include/CGAL/cluster_point_set.h index ef344707637..a538dbccccd 100644 --- a/Point_set_processing_3/include/CGAL/cluster_point_set.h +++ b/Point_set_processing_3/include/CGAL/cluster_point_set.h @@ -19,6 +19,9 @@ #include #include +#include +#include + #include namespace CGAL From c4e62d70e8a7e5f726051c609c9c88354f23cff5 Mon Sep 17 00:00:00 2001 From: Simon Giraudot Date: Mon, 16 Mar 2020 16:32:38 +0100 Subject: [PATCH 155/568] Remove K parameter and update doc from reviews --- .../Point_set_processing_3.txt | 5 ++- .../clustering_example.cpp | 2 +- .../include/CGAL/cluster_point_set.h | 41 +++++++++++-------- .../Point_set/Point_set_clustering_plugin.cpp | 22 +++++----- STL_Extension/include/CGAL/iterator.h | 29 +++++++++++++ 5 files changed, 69 insertions(+), 30 deletions(-) diff --git a/Point_set_processing_3/doc/Point_set_processing_3/Point_set_processing_3.txt b/Point_set_processing_3/doc/Point_set_processing_3/Point_set_processing_3.txt index 3bb77da6a41..5c3f2c50733 100644 --- a/Point_set_processing_3/doc/Point_set_processing_3/Point_set_processing_3.txt +++ b/Point_set_processing_3/doc/Point_set_processing_3/Point_set_processing_3.txt @@ -317,8 +317,9 @@ points in the domain. \section Point_set_processing_3Clustering Clustering If an input point set represents several objects which are spatially -separated, a clustering algorithm can be applied to identify simply -connected clusters on a nearest neighbors graph. +separated, a clustering algorithm can be applied to identify connected +components on a nearest neighbors graph built using a query sphere of +fixed radius centered on each point. The clustering is stored in a cluster map which associates each input point with the index of the cluster it belongs to: users can then use diff --git a/Point_set_processing_3/examples/Point_set_processing_3/clustering_example.cpp b/Point_set_processing_3/examples/Point_set_processing_3/clustering_example.cpp index 737913b6521..d6d2b406cde 100644 --- a/Point_set_processing_3/examples/Point_set_processing_3/clustering_example.cpp +++ b/Point_set_processing_3/examples/Point_set_processing_3/clustering_example.cpp @@ -34,7 +34,7 @@ int main (int argc, char** argv) CGAL::Real_timer t; t.start(); std::size_t nb_clusters - = CGAL::cluster_point_set (points, cluster_map, 0, + = CGAL::cluster_point_set (points, cluster_map, points.parameters().neighbor_radius(spacing). adjacencies (std::back_inserter (adjacencies))); t.stop(); diff --git a/Point_set_processing_3/include/CGAL/cluster_point_set.h b/Point_set_processing_3/include/CGAL/cluster_point_set.h index a538dbccccd..ee13377a4ef 100644 --- a/Point_set_processing_3/include/CGAL/cluster_point_set.h +++ b/Point_set_processing_3/include/CGAL/cluster_point_set.h @@ -62,7 +62,8 @@ CGAL::Emptyset_iterator get_adjacencies (const NamedParameters&, CGAL::Emptyset_ /** \ingroup PkgPointSetProcessing3Algorithms - Identifies simply connected clusters on a nearest neighbors graph. + Identifies connected components on a nearest neighbors graph built + using a query sphere of fixed radius centered on each point. \tparam PointRange is a model of `Range`. The value type of its iterator is the key type of the named parameter `point_map`. @@ -71,7 +72,6 @@ CGAL::Emptyset_iterator get_adjacencies (const NamedParameters&, CGAL::Emptyset_ \param points input point range. \param cluster_map maps each point to the index of the cluster it belongs to. - \param k number of neighbors. \param np optional sequence of \ref psp_namedparameters "Named Parameters" among the ones listed below. \cgalNamedParamsBegin @@ -84,17 +84,14 @@ CGAL::Emptyset_iterator get_adjacencies (const NamedParameters&, CGAL::Emptyset_ algorithm continues its execution normally; if it returns `false`, the algorithm is stopped and the number of already computed clusters is returned.\cgalParamEnd - \cgalParamBegin{neighbor_radius} spherical neighborhood radius. If - provided, the neighborhood of a query point is computed with a fixed spherical - radius instead of a fixed number of neighbors. In that case, the parameter - `k` is used as a limit on the number of points returned by each spherical - query (to avoid overly large number of points in high density areas). If no - limit is wanted, use `k=0`.\cgalParamEnd + \cgalParamBegin{neighbor_radius} spherical neighborhood + radius. If no value is provided, the default value is 1% of the + bounding box diagonal.\cgalParamEnd \cgalParamBegin{attraction_factor} used to compute adjacencies between clusters. Adjacencies are computed using a nearest neighbor graph built similarly to the one used for clustering, - using `attraction_factor * k` and `attraction_factor * - nearest_neighbors` as parameters. %Default value is `2`.\cgalParamEnd + using `attraction_factor * neighbor_radius` as + parameter. %Default value is `2`.\cgalParamEnd \cgalParamBegin{adjacencies} model of `OutputIterator` that accepts objects of type `std::pair`. Each pair contains the indices of two adjacent @@ -108,7 +105,6 @@ CGAL::Emptyset_iterator get_adjacencies (const NamedParameters&, CGAL::Emptyset_ template std::size_t cluster_point_set (PointRange& points, ClusterMap cluster_map, - unsigned int k, const NamedParameters& np) { using parameters::choose_parameter; @@ -128,7 +124,7 @@ std::size_t cluster_point_set (PointRange& points, PointMap point_map = choose_parameter(get_parameter(np, internal_np::point_map), PointMap()); typename Kernel::FT neighbor_radius = choose_parameter(get_parameter(np, internal_np::neighbor_radius), - typename Kernel::FT(0)); + typename Kernel::FT(-1)); typename Kernel::FT factor = choose_parameter(get_parameter(np, internal_np::attraction_factor), typename Kernel::FT(2)); @@ -150,8 +146,20 @@ std::size_t cluster_point_set (PointRange& points, // but this is costly to check CGAL_point_set_processing_precondition(points.begin() != points.end()); - // precondition: at least 2 nearest neighbors - CGAL_point_set_processing_precondition(k >= 2); + // If no radius is given, init with 1% of bbox diagonal + std::cerr << neighbor_radius << std::endl; + if (neighbor_radius < 0) + { + CGAL::Bbox_3 bbox = CGAL::bbox_3 (CGAL::make_transform_iterator_from_property_map (points.begin(), point_map), + CGAL::make_transform_iterator_from_property_map (points.end(), point_map)); + + neighbor_radius = 0.01 * CGAL::approximate_sqrt + ((bbox.xmax() - bbox.xmin()) * (bbox.xmax() - bbox.xmin()) + + (bbox.ymax() - bbox.ymin()) * (bbox.ymax() - bbox.ymin()) + + (bbox.zmax() - bbox.zmin()) * (bbox.zmax() - bbox.zmin())); + + std::cerr << neighbor_radius << std::endl; + } // Init cluster map with -1 for (const value_type& p : points) @@ -189,7 +197,7 @@ std::size_t cluster_point_set (PointRange& points, if (callback && !callback (callback_factor * (done + 1) / double(size))) return (nb_clusters + 1); - neighbor_query.get_iterators (get (point_map, *current), k, neighbor_radius, + neighbor_query.get_iterators (get (point_map, *current), 0, neighbor_radius, boost::make_function_output_iterator ([&](const iterator& it) { todo.push(it); })); @@ -202,7 +210,6 @@ std::size_t cluster_point_set (PointRange& points, typename Point_set_processing_3::GetAdjacencies::Empty>::value) { Adjacencies adjacencies = Point_set_processing_3::internal::get_adjacencies(np, (Adjacencies*)(nullptr)); - k *= factor; neighbor_radius *= factor; std::vector neighbors; @@ -214,7 +221,7 @@ std::size_t cluster_point_set (PointRange& points, std::size_t c0 = get (cluster_map, p); neighbors.clear(); - neighbor_query.get_iterators (get (point_map, p), k, neighbor_radius, + neighbor_query.get_iterators (get (point_map, p), 0, neighbor_radius, std::back_inserter (neighbors)); for (const iterator& it : neighbors) diff --git a/Polyhedron/demo/Polyhedron/Plugins/Point_set/Point_set_clustering_plugin.cpp b/Polyhedron/demo/Polyhedron/Plugins/Point_set/Point_set_clustering_plugin.cpp index 565c7e7e572..17986cf4e8a 100644 --- a/Polyhedron/demo/Polyhedron/Plugins/Point_set/Point_set_clustering_plugin.cpp +++ b/Polyhedron/demo/Polyhedron/Plugins/Point_set/Point_set_clustering_plugin.cpp @@ -28,20 +28,19 @@ struct Clustering_functor { Point_set* points; Point_set::Property_map cluster_map; - const int nb_neighbors; const double neighbor_radius; boost::shared_ptr result; - Clustering_functor (Point_set* points, const int nb_neighbors, + Clustering_functor (Point_set* points, const double neighbor_radius, Point_set::Property_map cluster_map) : points (points), cluster_map (cluster_map), - nb_neighbors (nb_neighbors), neighbor_radius (neighbor_radius), + neighbor_radius (neighbor_radius), result (new std::size_t(0)) { } void operator()() { - *result = CGAL::cluster_point_set (*points, cluster_map, nb_neighbors, + *result = CGAL::cluster_point_set (*points, cluster_map, points->parameters().neighbor_radius(neighbor_radius). callback(*(this->callback()))); } @@ -99,10 +98,7 @@ void Polyhedron_demo_point_set_clustering_plugin::on_actionCluster_triggered() return; QMultipleInputDialog dialog ("Clustering", mw); - QSpinBox* nb_neighbors = dialog.add ("Number of neighbors (0 = use radius):"); - nb_neighbors->setRange (0, 10000000); - nb_neighbors->setValue (12); - QDoubleSpinBox* neighbor_radius = dialog.add ("Neighbor radius (0 = use number):"); + QDoubleSpinBox* neighbor_radius = dialog.add ("Neighbor radius (0 = automatic):"); neighbor_radius->setRange (0, 10000000); neighbor_radius->setValue (0); QSpinBox* min_nb = dialog.add ("Minimum number of points per cluster:"); @@ -132,13 +128,19 @@ void Polyhedron_demo_point_set_clustering_plugin::on_actionCluster_triggered() else // Use long name to avoid overwriting potentially existing map cluster_map = points->add_property_map ("cluster_point_set_property_map").first; + + // Default value + if (neighbor_radius->value() == 0) + { + neighbor_radius->setRange (-1, 10000000); + neighbor_radius->setValue(-1); + } // Computes average spacing - Clustering_functor functor (points, nb_neighbors->value(), neighbor_radius->value(), cluster_map); + Clustering_functor functor (points, neighbor_radius->value(), cluster_map); run_with_qprogressdialog (functor, "Clustering...", mw); std::size_t nb_clusters = *functor.result; - Scene_group_item* group; std::vector new_items; diff --git a/STL_Extension/include/CGAL/iterator.h b/STL_Extension/include/CGAL/iterator.h index 4875fb69aa5..35ec75f6c4f 100644 --- a/STL_Extension/include/CGAL/iterator.h +++ b/STL_Extension/include/CGAL/iterator.h @@ -1480,6 +1480,35 @@ struct Range_iterator_type { typedef typename RangeRef::iterato template struct Range_iterator_type { typedef typename RangeRef::const_iterator type; }; +// Syntaxic sugar for transform_iterator+pmap_to_unary_function +template +typename boost::transform_iterator, Iterator> +make_transform_iterator_from_property_map (Iterator it, Pmap pmap) +{ + return boost::make_transform_iterator (it, CGAL::Property_map_to_unary_function(pmap)); +} + +// Syntaxic sugar for make_range+transform_iterator+pmap_to_unary_function +template +CGAL::Iterator_range, + typename Range::const_iterator> > +make_transform_range_from_property_map (const Range& range, Pmap pmap) +{ + return CGAL::make_range + (make_transform_iterator_from_property_map (range.begin(), pmap), + make_transform_iterator_from_property_map (range.end(), pmap)); +} + +// Syntaxic sugar for make_range+transform_iterator+pmap_to_unary_function +template +CGAL::Iterator_range, + typename Range::iterator> > +make_transform_range_from_property_map (Range& range, Pmap pmap) +{ + return CGAL::make_range + (make_transform_iterator_from_property_map (range.begin(), pmap), + make_transform_iterator_from_property_map (range.end(), pmap)); +} } //namespace CGAL From b1966323e40c143aeb0666bdcdb7747fd777ea54 Mon Sep 17 00:00:00 2001 From: Simon Giraudot Date: Tue, 17 Mar 2020 09:20:07 +0100 Subject: [PATCH 156/568] Do not fallback on k=3 if sphere is empty for clustering --- .../internal/Neighbor_query.h | 17 ++++++++++------- .../include/CGAL/cluster_point_set.h | 4 ++-- 2 files changed, 12 insertions(+), 9 deletions(-) diff --git a/Point_set_processing_3/include/CGAL/Point_set_processing_3/internal/Neighbor_query.h b/Point_set_processing_3/include/CGAL/Point_set_processing_3/internal/Neighbor_query.h index 1160fb3a3e5..eaa35bce79c 100644 --- a/Point_set_processing_3/include/CGAL/Point_set_processing_3/internal/Neighbor_query.h +++ b/Point_set_processing_3/include/CGAL/Point_set_processing_3/internal/Neighbor_query.h @@ -103,7 +103,7 @@ public: template void get_iterators (const Point_3& query, unsigned int k, FT neighbor_radius, - OutputIterator output) const + OutputIterator output, bool fallback_k_is_sphere_empty = true) const { if (neighbor_radius != FT(0)) { @@ -133,13 +133,16 @@ public: catch (const Maximum_points_reached_exception&) { } - // Fallback, if less than 3 points are return, search for the 3 - // first points - if (nb < 3) - k = 3; - // Else, no need to search for K nearest neighbors - else + if (fallback_k_is_sphere_empty) + { + // Fallback, if less than 3 points are return, search for the 3 + // first points + if (nb < 3) + k = 3; + // Else, no need to search for K nearest neighbors + else k = 0; + } } if (k != 0) diff --git a/Point_set_processing_3/include/CGAL/cluster_point_set.h b/Point_set_processing_3/include/CGAL/cluster_point_set.h index ee13377a4ef..c6008b8e4e8 100644 --- a/Point_set_processing_3/include/CGAL/cluster_point_set.h +++ b/Point_set_processing_3/include/CGAL/cluster_point_set.h @@ -199,7 +199,7 @@ std::size_t cluster_point_set (PointRange& points, neighbor_query.get_iterators (get (point_map, *current), 0, neighbor_radius, boost::make_function_output_iterator - ([&](const iterator& it) { todo.push(it); })); + ([&](const iterator& it) { todo.push(it); }), false); } @@ -222,7 +222,7 @@ std::size_t cluster_point_set (PointRange& points, neighbors.clear(); neighbor_query.get_iterators (get (point_map, p), 0, neighbor_radius, - std::back_inserter (neighbors)); + std::back_inserter (neighbors), false); for (const iterator& it : neighbors) { From 88e3fd47310be60bbe8a29bd70af7f380ccd8f7a Mon Sep 17 00:00:00 2001 From: Simon Giraudot Date: Tue, 17 Mar 2020 09:21:45 +0100 Subject: [PATCH 157/568] Remove garbage cerr --- Point_set_processing_3/include/CGAL/cluster_point_set.h | 3 --- 1 file changed, 3 deletions(-) diff --git a/Point_set_processing_3/include/CGAL/cluster_point_set.h b/Point_set_processing_3/include/CGAL/cluster_point_set.h index c6008b8e4e8..fd6e27afe27 100644 --- a/Point_set_processing_3/include/CGAL/cluster_point_set.h +++ b/Point_set_processing_3/include/CGAL/cluster_point_set.h @@ -147,7 +147,6 @@ std::size_t cluster_point_set (PointRange& points, CGAL_point_set_processing_precondition(points.begin() != points.end()); // If no radius is given, init with 1% of bbox diagonal - std::cerr << neighbor_radius << std::endl; if (neighbor_radius < 0) { CGAL::Bbox_3 bbox = CGAL::bbox_3 (CGAL::make_transform_iterator_from_property_map (points.begin(), point_map), @@ -157,8 +156,6 @@ std::size_t cluster_point_set (PointRange& points, ((bbox.xmax() - bbox.xmin()) * (bbox.xmax() - bbox.xmin()) + (bbox.ymax() - bbox.ymin()) * (bbox.ymax() - bbox.ymin()) + (bbox.zmax() - bbox.zmin()) * (bbox.zmax() - bbox.zmin())); - - std::cerr << neighbor_radius << std::endl; } // Init cluster map with -1 From 0e67264624ae7b217538e975878646c4289cbbe6 Mon Sep 17 00:00:00 2001 From: Simon Giraudot Date: Tue, 17 Mar 2020 10:06:00 +0100 Subject: [PATCH 158/568] Update from review --- .../Point_set_processing_3.txt | 12 +++++++++++- .../Point_set_processing_3/fig/clustering.png | Bin 0 -> 145016 bytes .../internal/Neighbor_query.h | 17 +++++++---------- .../include/CGAL/cluster_point_set.h | 2 +- .../Point_set/Point_set_clustering_plugin.cpp | 2 +- 5 files changed, 20 insertions(+), 13 deletions(-) create mode 100644 Point_set_processing_3/doc/Point_set_processing_3/fig/clustering.png diff --git a/Point_set_processing_3/doc/Point_set_processing_3/Point_set_processing_3.txt b/Point_set_processing_3/doc/Point_set_processing_3/Point_set_processing_3.txt index 5c3f2c50733..2de6c16e556 100644 --- a/Point_set_processing_3/doc/Point_set_processing_3/Point_set_processing_3.txt +++ b/Point_set_processing_3/doc/Point_set_processing_3/Point_set_processing_3.txt @@ -324,7 +324,17 @@ fixed radius centered on each point. The clustering is stored in a cluster map which associates each input point with the index of the cluster it belongs to: users can then use this map however they find it relevant to their use case, for example -segmenting the input point set into several (one per cluster). +segmenting the input point set into several (one per +cluster). \cgalFigureRef{Point_set_processing_3figclustering} shows different clustering +outputs. + +\cgalFigureBegin{Point_set_processing_3figclustering,clustering.png} +Point Set Clustering outputs (one color per cluster). Top: input point +set and clustering using a neighbor radius of 1.5 (147 clusters +extracted). Bottom: clustering with neighbor radius 3.0 (37 clusters +extracted), and with neighbor radius 6.0 (5 clusters extracted). +\cgalFigureEnd + \subsection Point_set_processing_3Example_clustering Example diff --git a/Point_set_processing_3/doc/Point_set_processing_3/fig/clustering.png b/Point_set_processing_3/doc/Point_set_processing_3/fig/clustering.png new file mode 100644 index 0000000000000000000000000000000000000000..e50b92a005934866901cc9ee070500ca81bc8d5e GIT binary patch literal 145016 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


Wk6&NAI!{<(|h%^7uSZlka z$jG-FHKkHT{{N!wR+IeP+M_3RbaHMze7R=JX!^)M7=z4?e{Td`RSOLr6sJNI2^q&r z6EVrlNGTW^BmEM7Jk)lmQSA=vP01}vP43>ARhG;BBVtOo~dL%NC3`kr0_E8-x;5K&@90hL@8x@Y_v39D+&kRuA8w6UDy;(7;zU(Q^lb0*KukL^ z1idlK4HwXuyR_&w6wiM9jl<;{m zXQXdrWf|!vw?1br`^_~*mt;jiEK(CR`%0y#AfH}mYelx6H_cpGF2LN<=GAKDAC32N z1}h^+P(=(OOFz-xeHV73g@AO+()pR&pA>7Xc4uYe+Wd>jJND?fhB$3?a2ecEyofta zoY?k+`g!NG5Ze85oTUmv+N2>o`xaZ>Vl`M=I{WP9%d#>fOr9;6P|kx3U$H7)A2&{) zc>b-K*;4~Q8c0e^m_IYVoTLU$4SbY5b?U-PQ(>WOYvzWNu4*P!POJ9S?XC9JysgdI zP}2}mRkruu+ii_^C07*naRHhDXf07gdWB?(;PpKX!L>zBL zLp7I&(d&8~a(L48z(llXOWzK7kqI@y zukYa_DV0apjD%up54w>QdRr3o322Nz7(ljnAXjpBbrSgsgo2z=oh)Cm*K*bD+U6DG zVy!mG&SfXF^-|Hi0`jE!M-kEc9(7Z$6-r3YXoZ?s(%2eYtRl;jT~o5QTtfP!oOVUn z(wxmAi(XUmRWWbm44fMxNc0W4m zE`ux|L)sTnhpw+bc2CgV7P2)kkUP){%AJdq+B0*{P8Md)K4TZ2oyirAtaw>eHj(ZV zv+#EKOnha0;PhJf^tIodIkS3=oC=>hGyNY|pTF+N;i)q-r$AIRS+O;xx|sj;2oKvE zF||@nLsTg$LanBimCZ?|e$jxcU_%A{(QJA0!A$zr)BhJ`N4N-6OsT{qXql<9vs{-uKOi3$;x(hGPWsE0%|+1AL1G7|nRqK+N*-8Lt}? z^2DSDmG`I=21wL-X+R!6U{PP(%_P1Ri2xSa^6;rnOKRYq7CjnVz1w7Yd%b0Qu5uuu zZYN_&5go=d&b^Bu+a1bVB&o$o_0VdIV_`{}=4d~c3I_GykkmQGwa^I!5*o8GlJEpV zj3*jvB;rJGct7dIypr0;`EcD!a-DQAmGZ0TN;(-pPteh69=1}6Xn%^{q7mLDbh)&O z&Y5drQpl5}fD5K#>d=D~yWiYIlOUo6R=i?Y@^;pMoFXW-e7zup;3{dhDCF1jY&8qW zQ;6T(K*~&;EE@1Of&rqAoS8?UD#e?1I2aoGK+kMX5PDj z1KE6JQN)$y!H*zcME;|ewgusfIJ<*B5NpHTHRXx`@ygDBc2)RavSG`Ut%9xRGA z3t`;yWxzxGB;+5ws^nYu#TcLN+M` zP|hAHLICHnNQ(DJF~SLjcn{5Z9E1&;kUTWs;1UYsvG6Y}EkhvBV|g-sFhLSPpx2Qq z*~Cvohf=U#|H|ER?srxH@=qxm`XflbMaB|Htz{yqOv?~~)RLc(qCqD@gI~&EG@l5> z0vLf4395nP@j!qKgc1Ro=#&tBPz{!+CBnp#Tq5o?Fn4&W`=C1<2*f@dM>=%Ck@Qr8 z_5cJpMj~lCL4oQvLtsLrI>r;~1Eid6ZJFu%VhQQzl3bmvmSi-|yGs`pG`^Hcq?eWo zM%uO~kx5q4HKF{kBy}lup^P+mp==-^$YvI)@imjRb4smHTPsxOgnCY?rt8&`yL^~d z>PW9-O}Ti_>bD|iU34ujYI)Eu8s%bDODhKQNa)~S{xCkj-1R?dj8aB|@Cw58%$#=l z@=X15@y@enFAF9Vmug1N4IPx0?1Eg@md?yxJ{P{EO^uKL;oPM&r>=)Tx^!L}`Hl0@ z^9utXofx^aswfpjsh3!H&Hc*GE_YZfflx)juGOkyC2b;-shEnaX^Y5+AgtGv!senW zY7dxd(x_uez)2siHcCVna?^1_chf{5{!kOHpPO3kOU-(t9Z|l~`DSJ9_Ofw;3>gHB z&|7o{OSLfIrBzHKFv&+d7-J#B;djGV-jL*R$bgEGfCYHwbF-)7F-UN{Usqd@by3lw zf*yW#m`fq*4qIOdkF7sCDeJFS5z?X&f(-ikNT-E(V`x`furs4#bg)0Al75O#K#+u% zD3`)~lwZX>G)*8VVmOwdqqrXQOJtBD>7W#eArj2A^4&fh%_M3tvt42$%F)ht#xh_e zVh_?yfT3xO;izB&ou!9{1ff$I`hl{t((cv>g+)UEO@Z!GMJ;EuOIj99n3Gu(NiR{Z z7ll&6&aQp)fsCS=w-vFP1|{wC&78ubfr!{cF|Sri=&4)XuySP+`Ew<0=L|#)r2=|d z`C=s5OLK1XPrve!a z%On~o2003U21D$UAz-~D=|CnG3l2Gnj73v0CQSq+hG|Jzdn^b@V>HRA(F8;}j$_>L z0U)Y$`6=i~4}cI+EMEn)VCHHX0)c7dHuHvwNJN3TZ1#%lInc~&pox8{^sj9zvC%{? zy5y5rDi`ggJY?%IXS%2>)!9nbO}wg!B22nj=aq|4THNli`NcTW(gtXCWaB5R^^3LA zRrz*F6Y@~}GrNz7NIaQ&&6Lm1$cz8`Gn)3SX3m_|=H$1YDV)7rLiS{>pp>fxuyZG? zx6ci-#f|W#)#+2y%3B}JhMBcf1Jw}&#%E^(*N>KqH6-$?V9O>uhj^l1Edm09pqUkR zJGWQV3=vU`QF8ZtRo8ZQ1LQPgYNo3T!96Y#F zw#0Gc|0)dqD}_3oA&yH(dsND61qjFME|xdYt`jGc8L#7`fFJ=+#9R5crm5qt>m-%H zq?8BT9-Q0okdSsskbBm#kRBnB6G6)VcoT0m#w^$=wEL$%9N_vL&I1lf1;}RAkNGi9 z!uW}vAr7H{9MS`%)1s4&|%=T2`=ZD>Zhpo~|f)dx?d~iZF*6%;st>EszyK0E(#cJ9xiUupg6&rG&8Gi+|eD$KH(8DR)YWdG_o~C0|wwmn*JGLaZsnY39t__3*WMdp5iUypM``&D^JAqR(Fz*@1Fh6EHc4~lp{HvDefDZbaEW1 zRw~7H>LlrScpZ~S+`^+T@BZ#?->%(3S5qOYK@4+E>iBV&w>mJ!$0Ix9Be(O#-PkGD z;s6a~Oebi44+oL4pntWsE5-#GP&0qlRO}?^h(xudIDarRMnnUu<>#yeB!^4_6&#xw zb259NGw6_Xifc%c9x{N%NU9})O^_3QjP_F!iIF53ZE13@^>acQfbQVj{4^_$l6smf?v?IIbhecoVz!U zb%VND*}iBBXofdU5lke#Z1L+4Qd?QN)*;CaOyCS0p!muLSwY7T9tW;%lQ@LVZk=>OeMH6aD778Y4iU~Us3>I0a z*qT`TqpD&5Y7}cbZq(s4G023(2-T;@h^_8!+6QR9Zyg?=b%v1}pb{;hCfwqOU;k-G z#;l;k^;n%8^0ToBL0i2YSNpy}4 zIpB{-x?i#=%%TY(qJZGSTN7@L6s}W6)aAwtbg2^(eka=UAnPG^zAB=LK3h%OtX9p} zwY2LZaf{;rW-5Gn5 z6G-GY6kY<*`3OmI!q}# zBb(`ttTPHQ^S~>T;7PfnXF`>MV)}H>5g4ICwIB@$>qgTUw#E$y>h`V`G#vZIr+1Dt z3haiYL+mc-fGm5dVpgCLPOu~YHni~ z)`nKoHF_=*cnrvOE!>Q=AuS`&YLsKp{L}HPU8*D=xW;e*-}zI&{hdEkHLKSc+rxuD zRsH_Jbz6XM7g)o?7naxlvv_Iw#tT1v<`?h2{cpG5{?;$tt1lQ!Z@uzeZ|B*Uw_m<` zU~kdsfHt&3*YbyTKyn4)#@M%ds%=3t_T~Ow;Hv268yHANh7)#&P6*@rm_o~`9OUt* z7ryExmrRV;=MQJarQ+eVcsRR$zUrO5?Ivrs&H&%*g9iVr>c*i-lKfHyCAnUXmzR%f9|lY7irR0)cl7L>Fu zCFN=cib=10UXOGXy5_ucnx99cPj|e0xic$t@{*J-%BiA~VRBU#(rGTom`t+Dra@TD ziF0$+^jtM77c)6Y%y3>}CBu~Da=w(vnaMOOrlnj;;B`vf>*h=ZGlD5+^$EjI6jqQ# zIn7G4lmV1G0^`xfc33H!sTr=rgFfRygj#29;WQv()$L8c-wZMOx2(OM(}d>WXoy_% zkAC;SzkR7u1FXBupSHVh9sErfZIYHJ_+fiA=sAs=uOT`F^$aQ2R((M04}sJ? zzF9Y<^h-eJS$ojcDBaOC!n)?X>e!o>TQ`t+p>wp=Qz{U2H2erdf2i6ow(J+b6Lfoj zW;X%Vh}N(UuD^I=D-4G%!}vq-*>8P+Xm8I1i?~2!+S^Bp3%(rg* zu&e#WcZY^Ein&wGz)yCI>I1Yc1RBySXIQrle|H2mCu})}Iyis;*=emwWE7DRRZie{ z-BW3hX#3&ALov#T%6W5ElxJaa5$0AF^U>VG&OGV>Vi%Gp@Q{^%GyU+vSM-!p%IY(c zmjjd)Xz`iqB+)6(%9XO1Svy;V(i~h{&Xkjt@_p}`k9cR-A+O7G(fTaRa$ZJ+SrMi@ zF6W_R$kTc*sn7qR3O0_IUNWHvtNf)SZa^=$6=~x!!wDBj8Z03MwE81vA2qjyg`uq;n zrpK8vH|WzdKI73I`Zc%Jg28BfJ#-qBRqOTbnrgLzrqOQTCBsl{sr9b4r9smjbZI?8 zn`o7`1t@yaUm7T2tT8I<4NF72tApA+P>Ddf>H zMD#2s4G9_eyqMxUb6k{IB;lb5rG$Cf9|)iKxQv7!M?v|7TAV@jkYAoo>A5_QpHNOJ z>TXUYSf1ijtC<*%j8C6HACSY{6s; zay6?+)dHY&;(1w)_&k(KO3H&YFVa{Tvy_t%v#O%xoniz~xJwC&hKu$%?2|wrjyJ(= zP|El^!pr~kJX$h!RNa9)#{oU~AUe8QI8ehacU-r+y>PG>v~0I#J1yd6BlHk_fgSqY zext7%R7N}KYPG;>;0ld>-R@9)-FhWxQEMnbn1dpDyR+1PE#KEg>;7%Q<|BnOyghW)TUB4ClpnAKb^M&!8#+ft#yV=kvw58`Yc?t5F(R zd#97@RFlX=5O~Bn4vpALN>V};rUX7?%4PD(N>-Oo6@(+fW1@0i5wp6Kmz60QavV1= zDBL}lSs8@F`njCPO_zaZ_a8m81dvB+Hz!0MKP9hsIvrWen@Uly<`5ptYCa)(_!XI& z5v%ed;zoxnRZN{_O-N-GUM$ERcEZR}MUX|gs3UiSoFM6(RF!0bN0E}D_t-z_I%pdP zTOo3rE$S_*+jf22R>OwVrwa3M_vu&aA+qSk9U=Vfzdv@bxb!5zc#Q;&hBc@(45(?? zO_$K8f0W{=tFY;YyUF%O@bVlEKQN{adIDgi*t=1Ne9{mf13+O!4dGG4F33_Iy zqw9J{x!Q@=JBQC4!d3CT|Ko4_KoeN38fZ61s;U~UapUT{u>QgbUU}+Jqa(KN80CkB zTAk`yHUKr3?Hp($&9*gr1pTf0QThGJC>An=eV8jM=e^DuGpVd+V0Jy4HuJ=iyad&w zpI@JxxuZeqIHP{F%T<^MHVcd8C?gc-pp%3}eCG&AVMc0ONBy0ILc?B zT0z54gOZH6j8`n02@`cQYLLT>s3+xeQsI(vF|Fts&&+sP{&Z)h(TrZ=6(Q}(vlA{? zRTvo(Rb_f#E?1)hii3nwta{%1A|lI0aedMAR%T5z%?XjR|3EPd>qs!%wkpNgX-^E0d-4CqB&*CNe-gU867TM zIVr=kd_V4?GmuDk_h2i)px)4|29>)ajlOQ9A-C?#5Ps}HYYY5ZV71V?t%i#v&9A|* zZPjczEaxZ;xAk4 zo)SKqs->drIe;zK?hOMp;bC)feGlo7Z{W3B2q+G??Qm$U{c!)P0?IQYT)p}e?=V`r z`ivP}g!i6_ez64j3$B(8#6?gIba@M|k7zZUWxTES9MGDRvE2tXfWCbILzGZ$Fi>!5 zq(3Z2qpG&BUq`$|%{8i@)Imxdcr;}sDNfFJ*s?jR6c>TdP;1j7s%^CTOL-8zPdXnq zr%<;G^OMr{@*Ls-JefzWA0>4Wf93S^MTl#x@R_^>@*-qeD(pM*N-}?>W00S{!ZISG zR}(rUI^|hmB@Zh}B|R6h883|lB^%+(d8j#r?VUYn*ozf|Tx zW;>;`4=kTq*tzt`mCPc?LzJwdjEW$-7D0lCOkNg6CC^s%YQ{@d4|6%FR;&3=2dZUY ztC5+j@~o`OMUSs4fVWxTOu0Hm<1fsqh?O`=Hgjgmi_q~QS;B80v%Y^)l}?AQek-mB zQLSC*swmW9GpL1jJ#LWgW9)Q4xrCQSM8QU27zZuQuh}D1+Hr+rT|)tY65MFr76brY z(l_mX-9MD|xbbIonzLf`$G)bzwVF}uTH0Ukym0xaW%L8|1*BK-i}&E_GqC?Qhsr^tm}gLZ?~b!0j63 zi=bWyH&AaEL7zaRgICbG61hV@&t}jk5Ch~nF{29^s)NrI<@6_yXu!}2x@^vSxqI)s z_z;s`yl@7IJ<=V^H*qRWm7inPO*l2{KY1jW#n8(!dFE zM@n8y2xgKu(+YZ(S>zLy)BQYX9S>UqC80}y^^7JfOXMDWPC@AotbB@d1`MpIVVh&4{^Ph9y^iYB=xJfo@f)Z^ z!se%)U%3Gal-9v$b8EN0+h`4Is=s9;iX0%jZ_>E)@JOf}pV1n(SK&HtpvAMKyLN92 z)B!ruxO)J#fR^htpx?A#eHC7fYqy3i*BJI1r*x3^05y4h_I3URXzpoSn(wy^7e5_J zEp6=g4Qp6yHk!My{q4WrkFH|uHEBFR{Mz?)no75{4(mUGrK=G6e%lV;d^gfmZPV4% zQFn}B>o--^@ePY6l%f#dqFZ%f*B}Jkb!;SZL(3rdaCea?8mNMt@PrQHaY`jVRLw&* zkv@O8@`RVv_48t$@uqcT7kui|*mJr>U9H=>a}VW;iHlq+hfEDY!<>`R`0JI)r&QweX2c*>)4iPB5p%GTLh2Za(^vMdDB>fYxWByf!OWtM z)uf7xAmaUc70E1^RjP5!md%U=LP?Y)4xr4lqGA?BT|gcx7r9Om5H+erMHZ`7bIO}k zShH%Pd&n%S$aLu4Ihl~s4s123`*t%7o8PP(ZX@Us3>fvWHKcaZ`lq=^yga9Vpw=5r zwZ5fpZ2^jWtw%P}?bEyjWEUGKQ|#ffUyP0bWejRN?5aT@`Fd0B*6i!_)W)t>uLtOk zE$!B;eWy-5YeZ?e{?VSp6CcWr!MF}a-7)&1Z}flv+Xpnrq^kkGozu5r1BL@1wi+-r zf~ITxng*X(BOEP7(Nz=Pv#FB69r-_g@5ilhH~@EG84i9TYq&>=bHffde1C-eaOgtM zwgla zi%wC6b-SF29tQT`?zY^tLg zodcsBg4*d$uqX+s4#QE)R=@qzu=gvY5l}%S`k7jDQELZ1!)QWa8_;W6s7Q=YxqNih z^R6C3?iI}%+YQ^&oDt9{)e#CaZ8)->;ZUXRK^v}1SFw71e*_M4u?_Htb{zo=+*YU> zj;{tzlg5?Ck>&)oSOr?jaef_f12U;IBK}oBcX|En!dD+#yGOjV49Fio!GfY355T41 zi8D+0?RW0kQNFTMz2xP~(R2q<#G8|)DG-amlG;VO5v3wIb0k1eH&dR0&HV0J9@144 z4fg&A&OPAK1}T=4=r%=%Po%*E}fBo=Tu!+n(<5Io>O?<~#>Tholq~s|r=K zRIanu`?${lFaf#8F&Wf%BE68XDdR)ltkt6 z{nfdbR|~R2Gbz$lbP>I(E4m`_)w~B7E|jFCpeLOKL+rXuL#s)U?|t)|T{_e3ww-3T zTX$+h6eULe6Fr2KbGQ*|wQgGjG=TabY>}ySyOaYN?1h^a^vGfk&`ea)sjXvEw0C{G z0sf|1>rwinuW7YHpvOIFqzalk zdK`)rK4I$U{>r)PQ>$n8zjAJQjsZnyDpaDFmia6>2o=?Pz?4iSA?ju21n1SGEi_%X z?rYD#x%d3RF1U5*)dRHEnt>eNa6iq6$Za$Wxi*p-*C!o6=%XL_^}t6}Uk|NjNUIFc zWen*0=qbi+ri2`fSX_Tt8&NH9tJ}1KO$%w3+pj_Y)mFV5Hb>!65xhEpQz~?$PAwd? zvcMaB_h0#~U+paZMfgYi+MY$VQbhV{HevuBN&5r$Gs^~}_;O=w)3rl{L-Z-s?vDCOY% ziarhHd$)_{&LJ(Ch4fsM6TTO(xj3hPOrYOkPKDIR{*8tPdC9UlEql{6Z;dHJHH}!I zFrt~%kDeo?%yK?LN6cS<+#_&yRc5>_3-f#@8%69x+f1TbO36|}ujJwbFf^~zobm49 zO?UD#WOyYZLxDxjP*}K9WKlV1A(B`brofx+NF_kNrLcEpJ?Q<3MDCIpLH@i_`cVW-Dy^+ zhNvcx7Jc*2?fN&HF6s^>BU*PHCqH_7pLqnfd585PH1u|<61Rqtd!)8PxE@;d5pwtD zZTDzcZZouc!KfA(8>pJYn$zD5KcGqz)ITwk+qF;S9>LK#YS`;~3ok(D zYhb^<^!4(ysb`I_7J#j(u!UHrhIE#N>cYAEw+DLHw+POhO>2ZGv_WTcRM!g|gdQOV z220fr)M3{ewAFz@%&@PzBim9DQt8PEG$Y6F$FtzuCn7y~D6^)QsS0_>v0$q4aOz_w}XwC@rH4Qqmjw#5R>vmnn?uvLn*!}v6h`XtmaDQ6fa@i zW(DB5D;F+AXx1i*{bE^G@>L}<0XC}ea1sIvaz~+JD@Bxrsw{U(0?o!smw1U2bS0Dlfk0*;0+ zpjin+7}j8jgamvWYzQp~N2FB7h#NPlUKYZmjN;JNtW*6wwCjjvZm%D-Ui_1tI=p=o zjrr>DPyH0$rUWKf{gI>fiB77c;3Vl43vtc1Lqd;{JyLDULG*}Mw^^FC7X(AQ-S<(# zY5kUA^tS2;z6<>(T-V?LX_k-ZL7#WzI>`IFJqYjSAbMJcq*z`wXT?cUf=r3}$+>7& z-+t_qk9H3)9{-4SMq<|AW$(Yl&J~69qJHmo1f?8CZb(vtyPVLYgwB*BfdQF^TrQe2 zBNXdtS>a7NYno^7NY3N0)klD33T8E-7bfvsAJB83V+=G~0x@qwSu%4nmnxY8qEx!G z%9oYJ4*70=MHf19L70fscQ2ur=)@MuWEFoWbrZi`tiVXs5~>@hR82jj@2owJS1IUl z=@MMhI~gHDzxK>253&MfVPw55vs|2TGE>ss-miyYlp1BJgQErg|NZ$cw4Q$#aijGq z#qA$BNLL&7Lu0Es-0d2#*8Dts3*}5m^ri*f76s~fV4RCKqJdqbP3Y(Xd#Jdk5jBeG^|ZJT4?Y^~1tj@7dto#8>}x_Jy7IzqRPUW^5Zn!VknHs~cD& zSKUJlxI2K*@{a+2D~te+%1F@RhG^^nyOui)$9*ldsh$R9mc5Dp20bcS!_ZOFV)Qsr z1ItnECM8Gld)B`zg3M8yA7uqmP|rvCOr8dG!sGYte=@Q8@QaZN!aYw5X{MUX&d;u- zR}eo;s!E}Zij<~IU6G*_O1k7Fs@{~&(bi?pOh*_SMy zrWYwAg2W0$R#75}hb)S8iVR2pPR@L0-9)LvDx%=!bYKJyzgQGd5z!HMB;OSdH7ZRE zwp<%E!Z+U>ee*|KVC;rQ%{T$~2Ni^mVz)CV)@jeM=pxoZ1BsmPbZ=U3FJ_*d z`qwZ2z3P8=%4^+xdx(bpssS66v?OtHl8qjk(L1^u*Rr;J|9OkXGISl(-b1_wzSHe0 z1M(U|kER8CmW#l707lpC)BK3Q7&VR(KzAKIx=3?J%%sAnq-qMawVVMIqnGcQ+^x$B zRv+G3n5};Gnmo57Clw*f6%+e&=q9{^5Rw+6glVQbMPw+cNXUS6_N%Bu(s?vZB}Ee% z4yOc+-)m38wdL3c%%z9*63fh|=cEJ*mH0jM8RgXR3PDHa=L<@XHyVmale^!My7w=?d=7%mz?L{AJ>A0O&Pw8yEA{kp&8fv zY75%`F!>Kv|FtWxY`8QuZg)&_w0YDAMbVs=ciNNs8?V0uDs>i;*g*W)ZNV7EjW9SG zB{V*$8wdSXtG+d=`}mq8y`r8TK!!s{{npewuY4EUR=B(bH!l2CdB%0RufdDY22K0x zOX{BM1kgKKc~^K#y{^)-pfDVuty|B(P1iDJNGhTNqPDjJoXj1FfX2E z;nHKP=}4XiK0e2#*(PNWw?us<~L^h>+NmF5YJ`Fi^8TqNFWF#KjkFp?^BDPeX z!7pbL#XQTIJYq;xQrJ_q8%>V5+Ek<$N~MRMSb8wMy_TQjc|k5Px?H;O;JpIXOL3X$ zDO1Uvs6$asJ_M2{qDQglXLC`pTwdXHNiPbNzDyQDqLZ)>G4TF1eMw>G%qP8-IVhh8 zSd?URa??9;H80w6Tf?CL{5PYzg}eccp{2rI07SLJy`WjA!=N76GrIMn+FR7E{NL0K zxIPMK8Q|Eh!9gQzp=zyx*8TOXufFkmoLe3at-9-MB6%^|RxoPX{rcD+I!43VG@M$y z*6sIiI?k&u(weyP@6?ax5N@pf$y8$a_5bytV?2>l-_~=_z7oE$`1Pshq5hZuIBH+t zKni&>2WkHKo3864Uf5fH*tM;pihwe53>tz5+9ueey^r>C^|~lHw1zXZ!Yx{Lh@vO7 zJ}gx{Ngm`(C(6j>Ihx)-?L|o?w*pN0GZ#@#Kw&*0arh*AOc=b*6Gd-TgeBAvMM#Tg ze2!}-4+SR5BlDhu)qApRTDWvSod8$z5ek*W(uMTm%Z#8bt>TL^DOpMv3Q3dAMCq!+ zc;-A_HZPoV;(@trg3MBiKb76jWG+WveQfDWRVbKBL5>QS9^c_oR0e{Ni%TcOBce^> z6Vb_3ZKOPfoM%wnv>F z0hJe0B~iRBP;1{cO54G8OKsnt0^}6`H`i4m__lt~q=MX@I;NsSHEg;@Ym9Jl>-9H& zwtMrRUjH?EjoYMh$bNI!Y>m`bK$EwI?X98T-Mv}Y?9K7bF7yxJRU3|F$f+bc8e@+< z^6go1?YlYeh3P+;&b{B;|3&69e0`z#Ot2CD>SlZvTs!F%3EXy#UBd-h3^yd=G#pT6 zW!+H&a`?XO-@(-S7LANB{EbhLad&r+X$2jmGpi?MTEmp#_*^u1*U{u?Wx3l!kQ9)! zI>&dW1%5t~83pkJDF}KBoADS)K?ungy^DpNhd_TwLE(-%9VLqN=K%jN8HG*9+k zEGua2V&|loBzkbz$uC}d!dns-%f;2h&Y9}^EC4GmEt(=K@QE}ZeIk3(#m_So3;7V0 zwi~Dn1_N3l)(q}mJ!`8l7=2KX71k_?^=d2s@VCS(+?G#SkQNGaSBnEJdd<&Xeg9_` z{0z}*Na>O-*YDQrb<5rwQ89eG->P+Qw$3s%ymDjzhW7hYDdqc#<$wJD5Y1qO#K?u<;G~zNI!)WCTN@~D23prRfW~07Yk@Vi zcYVhSG>49~KRF`Vt3&YA%YYyl+3w|V9wvSEPO>2SOxi4 z_577Hb0-ezh^d4j=ueAF(K;<2NA-14I=nYJd}8~;rL|Rd^$KKIFtaj#D?X`+=(L5e zDjhNP`)JXlItmL{b=|s;@$oZghk*!8kysTzTZClQ+Pb;Wf2e0lD!=r1fXn&{v zIDLbX_RU|dO{*SUOTF8AfBoOA{^ISYfB&b6HJUYw?pV{BTkgpN2*DUB2&WzyevE2C zU8A94T}^8m+E5*a*7X>PVQ}}$-c6*-)FHc)L0hKHoEb0^dZHswm-n|n{fBGH5wMYr z@>_tCv@fn)!mlwG7P6PWa?$LhQJz307oiG4AIgXwhP(C19O{z&dG@IXEY)$+sShhfjMDJ+Tf6Sz&3-;c);i2&Xl%L$qUFY(Z8M3#%EBmn!;F zB`U}uAiWc-;>oF-KJhrbS=qcjK7K+6c+pxEnfijhum+tcL6-7}C6(L9U0>kg22L#q z>;9mJgn3+}!8>RX&Bl?5ep>F`rwvMjAXLZbDIGhHcY5R7>}y)~-&r(aYXEM`9icqm zK*2#(yTq+t|MlL_-gx8nUmK|7`=LhB)o5BkhdTzPT+}YvV&4V-L$!VCkAtY@Xf}G- zYlHo7C*a@)y2J8cyfzArMXEEmGDYFN}> z5{3su)o~1?>wIAcNhlcJy<{g}Hj{cMqfau`BLCUxER-M^k}+0O5k-l8`QCgrnT66r zJ4_{FRv@8JPA=0?GBPA3DHDnFm%lP?Dp|cU@0HREt68tg>K7Ad*I@0OxxG-xN*%hW zD3~7^Y&t=XMrGxvd(a|+VpifFc=}8#|6s<166?t`9$)liMj+zHr9sSR7EeAAl$PI8 zOT3vCK$$*zk;i>hq8(L0RCOxC{KEbbPrtIDOLK6MPLqTlpcO%Qm)twFZRl%3({gH) z^uM#R-+ljAFaFK{#h9ocdfg)xLcgfOYXn;dufMLr&(z?xckG}2?C-jk-*Sf6>wP*P z2#1535z`&t_;~oW;$c6hdxY1=2uRvnSAIXS@b~{};Q&U>(XGvqty;G(=WjV}Kit5Z z-%|T0zan|XkADpC(n|n;{^rpafBfceXy(xfK5TaR0uBPqN|X^H*%8xF%s^5^yOi_r znIdFDxpJjKU4aa*q^pZbSpw951Oeum41>RE< z-s%|!Sr(YlI4J#n!awt$K7nX2Ani`t%IZ7kR{!XQ@81?vFPq4K`|ot+hG4Wy3j|s>|K^G&-FP+nuD$>50P33G2%VosPRTWWAo#tX;}XFv>zuJQJMMIANtE5Zr^-(|Lqrk0srRe zuPl<(@VDA8F21N)Lk9uNQBOKWNIPx>Bm{vsZyo*pr8nWnFMZB$_}v_YTG1C_wqs65 zayrVD@C!7R>eD4`JfPT&_!J-}P^)>4GS}stl2yEnRBaXN*}SZ3GJ>u-Gg4d$eAFdpu#|fGpi|q zPG{2+lo-SSR^%&kn#SJ=%n2Q2;ziLXcmT$TyQ`zg=W!W-E3~)BG3o|QWN*T_=4=_R zaW~o#UUz_2IENvsj3%=3xAHH*+x_UqFfQYu**(y!*@JlJ$T0Zz>lVE62D0{G>+k-~ zKpXAWQHR$dY@;h89>t^M(3d`D?6uGFc??Q1Zn@5Dq2Kj?_2iSc{$yc9YYXsN!xz7A z5ACitra>;w7YrsDDx0dr1K@ zk&+f@3vC*BmPwZ4h6pC2MEVl)8K|zloG$Vyj*PTegxo!k%`x!gifDSr>Q^Yj_LFq} zD}Q`Ur+L~wTafuk=jOpo@sm;!gaqD@4q09=#fv{B$%G;YY>FERQzWHp1wMWOa7+Q@j=(kA~H!S9_G`$f9ul?UM{SavkYI8fD zi2zOThrb@|zVpUw@K3Letu`F|m;W-@1g(#R%8j$r;P(Q2n$ZZtJ5H9|(|(pv4MV%; zQui>mp4Ud^jRUyZ^+)KzL)SOnr>ulqYpSOh0TH%s_~(4w%|XnI;-LugRCF=FpAbEo z^?9h2qe*mZ1sFi1=-3=+RU<6v=8P_9JT6B&G8gkym6&7XTscaMURhVDx4gQV7R+hM zlz?V`p1nVV5{1U$NL2Zr{GN9-0>Vsu=%#tW2gU>}Wm#v)i(n3}iCMO4k$KGXA2x06 zI<&hqG>*EcKZAf+8l|^emfHvs0o*!Ojg0F23$Nbl_d&Bf%B6HIBvZR>I_7LOq5t|D z_3=BXLTLDd2KB$AOnZD7_Mt-z)X-?EcZ%av!(l7HH$bMQ?xFS>gYhe83;lTyv>_!d z-KI;wL#=n>ArL|Hz&PDNmGSs?up0kh{COPYya-BUBGC~cA;I}7BucAO(fXqv25^Np zkJcpZ?|)zbPjpD>&eFslk2S?PPfkXB4uMB6GjaXZz5A8S5|g7&Z&0Ah!}|J6r9`HR zl7KC7NPCvpCwIW)Z$du>l0CIQjc##xj+}da>2o?r5P%kfMoTRQUFbLLO^p%} z7{K?&!?+acBP}7?9#wp!GxX4rENC4-&GPF$bd8`EqOgAduS)MX`sxmi34V4DQQ6q{vbll-~ z=9ReP)~We4HrE|&wcy0QH#R~TpMsA4@~t0y8~^izxA2d*K8J&#No80X)fR6=77k%u z2YwMzLws_-I!EoKY{5f`@%Uq~y&bJ~Xbr*{K(WGbh#XOF1@dK&Ru8TK{z}SnViKL% zhUs;E)&x{3^9Uz82oeeuB`q^4KAS3)(q@#%C*)Eg`s2q;sHE7ZFEE`92SNeNd6@tU zZy=!@9i^QPL}cDPdP~wp3=1r$Bm}uc6RboKv%0`39&>QQ8^(&qv@;CI!W~i zA0NSz=y(J2?QiFO+Y#J%4VI(N4f$FPdOdUjyn=1T({XaABRWd`>o&abSJ3LlM`ASMnSKT8t)2>X=Z)8HzVTZ3 zpHQPTyERQ~k7)Lx)2OTMrj1-J?7DRFb?mo&2tUWC8OCFS@FI9$R*fc0*I)U*`>F#f zUcY77ssY9bH2dW0zpwg7I-Qn2!`;y22S12^|G#g2K8i&@=xP~qi@-3zENz<)Y{yn9 z^B~A(vSXf?IthLCVOV}7T3Cn{IxyFP3~73p0zSd=NfP7|Pp=6L~16|(M9F{05^ zrzG-}h+ugrR6tiuLD0Qwfr_u>8A%a@h_5I`I(&+}s^)7F|+cpbvsnSXfI_K!w3wA|6A8%qjs22`Wx)F}Tr+6|!lj@A9yJI2JW zS>c9epelFN4YhCBS^!-@qQASjIoqwJgo@d;WU zB9~!q1uj_k!2c#Ta~Jj2h01%MNUUj=q{(co;edqoWOG& zrS@s)D6b<3f}T~XS*oc84s}Qb-U$&zM?{m;CMVJ$6SKrdUWpaN)kt7LI7@46Id5Hr z>YVq_b>chFplgNCy*YX5=Y!@q>OXq!c?*92eozDB`j3A!0Athd$H!8wc!Fo!Mx1~_ zyy*Z5OpV$)(9W$J(U6>p;y*1{vnY?!u;IE7noG4MRIsEGCqp?vFWe<4^5f?1Q7Z^r zyGFlfXm+#hBjXE)YKV+T>-i|TVRWjgydmrwp{mjFT-w)Ba|kR(wK(Tk!@KE@ou+&A z#FIS;(Q3YC8IECC4tn{hWmtym@A}~u9ffN)0!!FDg^vHq$7kBy86h)#l+ZiVAm4wP zS-fwy`jvuy?JKMM_g#kV`^1I&E-9Dq*^dx2=5#M5dr765gw9kI^}*^TSUd-vOH`(U zO1)SmEGZVLkeAJXJ|mz6Nmhx#u@dkV(jtf=QW~n$7=(`oiO?z5{$u;zVVpg`umG!P zy-EnI%sv1BAOJ~3K~$Q$uFAQHBLCTS{Oa}t3$TAw_%gYRNH5LP=oAUjDhr;>h&u5t zS>e!4QHM<76EZr-a=8;*aHJfW{*^00Ls894rz2fkyVTi-3#d*tZ9S}wpjn4{ z-)RS<8j>xbfx0Nx=_EC@+M&Da`x_XtyLOB&%I=B$#JL_&#-kfTGXx)ne?Pu$RYk+rsL9W- zIR{;>d2;gRA8{(XOOsL{q~#2jF*JNI+Tn0G*4l>MM>jdeZicVizYY4b{%I5o$xOP6 zwhyywrTn+%a(|rSZ~e{%_}cG8<=Zq!F)4aDF zbh%3~2lt z$z7DMMobmhqK8nUS9C~r;ECnsRq&oNcOE=<_hT(Z(C0O$E$gMf-um%#5!@P%-+T_>7KG3JH*G7_?6}UtqT?wP!z~qd z+vA!`9lMA%C_6A#H<9JL;buTPqtUVvFE(8oKG)x)yyQXcD1g)0(U0k2{G!&T*Q0X4 zKgTE*P}Qh?4ecA>w!d|P9xfvo;46_6A}cyLpl0!S3j&I(rW@M3bU)Te4L@%@Ar*!( zCAbbYs(vG^`KP|bSCFGD+}pueZ^HWaZ>ri-#8;st0aKC_P%Q$6S2^vita~%GdmQE` zN&&7d!}spl*}1SI%fJ?v@AoL;^KmN^YL}IH<@_QfILc&HSu@WZ=Hop4j1UiMuR@li z;heb=m3qkej?6_eQhEG0SqE7Hq$?kEE}5L7Fr6sJMMWO+Ij>yQfl<)c;LOsq3(LRB z`X?X#Q_!g(WWHpUvJ%gmG>@cILJt?>%?(om@-4GkDVW~8`NiV={?6y;QRp1wUt)~@ zc4Wq!l`$0ppLJ zRvl0YVBD(O!`InP&jw={)Pi`X)!j+~X+Z9f5;R&@JwTT-5RDob_K~k)nD3)Pau5Jo z4)nDz2)th)H9{iY+XvWw*n~$f{AQjo;mIk|(o)rABbo7(!~_9FVxvNp42-FGS$+FL zzPPOcZB(f@(uH{UZOc76^7OW=)9t& z6?1WgG<%6A?t1vo3S$a|NI}6-iv0vprN9E>k&sj59LW`OE>8C3tmiTEtw;86d&ABj z!#=XW2XD{2-ChHaiBYfozm)j>T%m0A6M*z(art*r?fH_DXf-h_9agC9K? zX@~(vgpnVC;lPbU_Lz3Gsg560@t~z5RQO1c)Gp#jh!#pyQUb6JC|i#D*55=4J@#88 z7>3X`d{hdkO^iMSE%am{y?|l4dk_rws6z!I1$BGSj!pkVyB;H{QR6LVw=;yqbErUO zmxf298xWqw6H&H&*tKXB=-7>&4_TjPjNrHSxP6M{?L{X)r@W{q3I&oHB>@9ESurn|Gdk!d9CebW;=`xhN=%+0nn%GQc=O=# z61_x3A;NlJC2ODP&4q|5jW zkR$jKJjTbr?|4u*h#R7!-lSdWy&>(oM02eh;g9~$HwQnDYL3wz+XEU%FnT_;hE(o- zfWji41Q+_?$2QvUk_w?dtC(}3Wux-wjwq`*LPPC^qutO(JZTuzo=#Pah)f7uE#KWh z#~L{p))9AFag(>z_1zYdHlGIQ3>!2!?w}XA_!7$s{iD20*GJ(*M*znT(s0Q5N2r7> zYmDx6ut9l#&@@}sXgx@{5kDy&yzU0S&7VW;Aj?mE+VM(UI3=42CE`2`?x`x|1R+(5 zQo1lxFw+Gys|(qPOUDD=W~e+0Nec~`&PI$tWmZgy&Q@sw!W=q6iOGYK0=W`-_$L~E z))N>-&e8!F%&xX}$M;uRnh2KaRiod;j(3@BP=l@m|aJsUjYOu^raI zZc~i+>ps#JBc4$mv|QK<-C7u^Jr%98VG|f(@a|hd-Eokmb>q_BUKd82D&m0E3fvY= zmm3>{E>e267svZe7daTwEBqguau}iAi#3h0OE(xcf-Y+Rt>g3DfC>O^GaiFvhT0+^ zp)m@GNxmA=Ji}q1a-S$gf?bPJIKE0{{NZocK_+l*?NierCD}`(iRzFQq!N`&37pQR zJqE+M4(SS13JKOU85G<)vMVoz@mbfi9d8OqOC%z5UQt-jWKB8m!P+^L6((aUg$Oty zN+9{K03%USgNtXF=%^{!TqnUqb2-SRqopLQ2$5c94yR?v6iInhGf=?`<||RYNHc^` z#B^vzB9fy5bWj@Kv;Sy*Vdra-lzjYXRJ;!7E}23#(j|qTL7O2DIZ_x|%;dZ~%7%Xn4)W>b9py*APlr@$H|(Nj51{+rA2h9h{|8ZP4{p8`S;OCZ z>A%woPt~F+wrzFXHb`xwVpd(Ma75!Dj$qHGK|4@KmQOvYeH*Mj8Y6_}Z=r#VWdP+vTz5DQ586(%Ps^ya0fe+W)}fXW8WG<@5fhGSm@nG?F1kVh8-Bmv z_Pgq+ecbgF3lv8SLfZ&8FcNIw%{u6&p*9M^=|Q+l?I}acLa!M@t7U7OzhwmZ)XF-6 zxX*-B2o_itEn6oE;6cKptg}EnWU>V>DX`i2DOpxQO~6!%@!-=_9UAqPsz9+4XTXui zy-e@KvGnB9JoV*DY28dk=zV5JJU%g*WO?WQd1XJVTz-59wjY3AUf~5wv@nTZ5$Ds{P~5_8&9H3$_c^Q~233??hi73~(3}oWh zdR19mKo^L%!Hkq>=kWz|vb_o(-e9T(QPwN*N<0;w#hWbY_+^;^FI`pSf@~H{C?yn+ zn}O&{>LDo6H+|>&QG*Ay{&j6qAP6giKBf9J3#pa8`|tl_I~*gg`tDWd#{W!{tk93P z9J06#%ESlPKhEmaQAmyG!1=$*X3OwWG6`oIWXtz?FawM)@e=MJXYwbo8t#&wI4U zGo2Nfb$p^Z<>~XfJ`*X(!%~sXe6)U?Rwa{D(3qSGffV{uG_8DSltTP(U0|BTN zN$?at-e9Bf9+%Kj>zD;XHQ?rjssx_MW*((&hahAKsi@5l9ofqtE5_;7 z2I47HB^n9L3m~9QG4U;C(8px6#Ot0iS4K`Y`I0&aigL{%d9mx#MgonvmeUPUf}_0H z)rh|v$f*ANq-D{>!2Y%Gt2f5TtLkxH9RJ*n|I+_>W?|T*^D3(zgqk0=13>?2eWZKV zRe{Ek(sF|yopw={#&SVD(n(rqHB|?xo`&~3!{rVvF;l$4?|rQMo0$I|Ef3Vhsi1i*^`=RC%K+rmXJ9;KIY34gkzUjp* z%)X<;)!vLZnYHLpjE=!-DBz8F21sB*BP0ZHHmHMR-18xDY1&-a*c)nyXqzEnOguw@ zh?3p6+)bMj+{6sgixF*T!1Smc4iRHE9MVb#HBs$?--CnxZ~t5V*$z^C;@z(;!NYo# zt^zNkVRKn9XQC)2$sEODo&hn7Is~#Ms{BS8gfgBhf?3k>38S&O9jqStcdtdg>$H?QP>0llsC7ql5Zn(49m$nwvi49zr}kCLa=ZSQ z*Fnf+FI|MiOYrbA6wvMq`aB#id9bofdn%`(dS*X*@S&-BEWR^$cMYRGL zv$IuYMlul~=GhN}vdns{02O?}6e(tb>AYLiFqNAUn=2sL{^~mtjD0lSzPOPz4*MRg-YJT}^1t_NQe>#yUL`u0*LEZ;b zx-JwE?8I!j;SaQ!jlrF@$7=Blp-4XMw>Ybq~fy`s0yGI z?kEOBSuihq1ytJ#(JgZ)S7A=u%{6x3ghG*#(lJ3|2nA&gcg5qd_2d~w#mVoPMmw7 z8Cx{#-PS@F+~FZdE71ldpYc)#ffgMX55eDZ0PzNSpN+^>r?W8PcK&X>M#0v6qaHxb zAmWGqV|5WBG_8+xup7`E?1l>Ap6lbaLZb_NzM-PBq6XqI?OOO!JU+ug`K#1T!KF;)3|x6go@1bs*7>vhNKnwyrKzLWy^Dq`F(wi$iKBBYA?wKr z4>;ZRS%u|AhddZP_rp#PvhJMDkbm{vc|}(=wL3Mz#ZCO zs_*(|Q>I~pjMn=x zs8NK@yyBH~q(_sZUMH%on%CJZ<*Xqa@4m!;CY_SK{ch+Q1-uR-2dW)jo>1M#Jh_>N zIvssUk6j}wDRdf)zl6$!kcdmg!*+NUu1!n&jN;K=o9uomRh8LjVzM&5oKHcClTd&N z1!R4lRMh!M6UhYr#XLd>#@#&(+XxB{Vu4085m9OT4F}q7zmE2J;3B_w;)Ul%BWxZ} zS&7xAsBRea_W{zfJ&fTF^fYucN^D~YKWMp{1p#V@=IyrCfHoon?DZ+JXdQqX#-nU0 zxrhIQ5@D#3Yv5H;$A>*|(FX%`oQ*L#h>JjRy$kgrHDsZP@i&Jqsc|hn!$qRyAXbIi zp4J?r?>X-H%lFN`OHaDzMJ9N1yjVPbeD87u7uFzG_O_{ZYybXrc%Y-4S%SO?of0fh zPZm?r!aX1^>f!@WaSuJkuvGt~u#uON(7Gvx(;70ChG*$n59NrQRgS|rz85+g?FSKf zlcDO7NKctjR;MH&ihY?iBi1B#hF&C~Oko*d5mt0L-X@sh=xmCkC+WH*>*)p9Pb$>B zUJ}qNbcnJ*b8@-(u*#I+U*IE{ygPwy502+30D%In7;BBu;OsG#PW1<{+lbA2=(?Ns zsAgNJPP!w%-73^Sq`$jBQh0~5AsahlTH&wOEh`Mi(8M51oe&w|37>0AKS*2=Lzog zOr~dgZVvG@lkU_`?+idJZ3Df-!T=`F=#DW+U=sR6ncm$w0~bPyoW6tqAP!0^QX@S^ z=Ge1v+rjw+2kS7&9Ry*Spa$i&#;+@ja_Gua8L^=9G1=NBs)eI!keg~ltQ=dc;i7ab zc2%+T?)!a|Y{#+FvE#IrSkIP3Q4~qld!P6He7?WlRo4F(=h(mcSM2exTzp|q>xDf{ zFfHf4{%8G1pXlu0zqAKP(RgbrNkE{?V2W;^9}EaGJpp^ssaDZ`9OOCe*uQq1ix$xE ztpgqOiDBQ7gDn6^2WS+MtV4Jv8=4ukMAaosmPD`e43ClE1K{Zaf=dsvbNfJ799#md zpt}o?v^`vHVp0lb+-`pHz!7#YzN+@Wv&_DB5eq&xFJ5J5e>hyn!FJ=_Ai~TgtP_;u z;EWYXRy=QFh)|bfLyj!T)g3JH0J;{2Tv{7Go?laE=wS`pvG1^037uh1JCGn(XQ9nC zJa$l!0F8hc7c>y_+yMiH0X(h84{Hm-5_K^Jco1{9GXT*?76vR1j{}|S;gQTJXFwuF z8WzO^d+VZ8U?-1H0?6Z!?}v>a)@2`{(Z}?q7M^>?Pd{F|xe)P%-(6;ZahGTV;gRb1$JsN#%}#$KK~Nm*H&1ms)qV?PHmK``aZD4gf_`7xY=LY?69EhR zK(mQq!UOojRuvxANva1hg9@8A%r0TDZ((n;xp#pLPpVm%0vmUTodOh(SCdoC1dxn9 z8moI-fIkMpW9A@6K9ZROn;4+1_P==079Mh?Z&LXx%u56vtvKpdc??zX2q;=5Opkf%7Z)2qJOca74 z!6tD%43zi4ezhWRHpgfTZtOy7V&^4Ho0_xl`Q8R?VfNY%~&4cMv z0Yag{J+BOilGO;kHmH4uCriO|pxH6)$N~*v@WYxKR_J>ndY5INg|d%Ms-73}lbOZLu(@}9`Otx+1y)lTbF z6EM(OIE==HchfrDY3=FbshIG9&cP0{G249$~|49_9vw!N~>`Zh2Y#))bghB1Y3qZ6`wKMFW zv(+}Pb1qqG-RuF|96|@!5jIKq<0gD&Q?2UWJ{SrV7PANYOEU}`Ek4xY{Thz64)0(7 zv%N3;{z7#bex3k7!ffFgb_(DG#0=CuWr-|dSV?So+|FZ8`yi%N75L?@>;cLgiZJVc^ zi5Tq-s1uvqX-r%Ug0$%%q#o)9jaOEA*t;aQ49Afi)p311<}>uTeW5JGK)V+LSHh;c zJj04%Er;u{t`{LR@I=vehPIr@TBc_Jg8ULLTl+@ zGug|7d(9)*^s_adBzy5(S2nxn>eBE0vuE}%j4z!1=DzWZodf%4#!sUkpn9tRojujB z{qrX4?@eZAHc?$1Jj{}*R)Xrh$~t>lAMFP`03E?g*vTOQ{lOkuLaTwUw=Xm>J~AIy z|KwHctgEnR^|!uevL7B}-fO?a91|DM#tBH27(D!7SnQ2|WI@j# zfQeWk%maI|;$!tUwsZiX^&)o03-vi$bIi795f$tQHL*p={2(@gc2Q>@qb42(E`Y0b z=eUy>a|@k(hM{xtiR$>d)}cd7PaHv? z(b6OR@gwYs1uoYQAHZBJbeb+N?QH>rS~}3j@C16LX3<2j8w*VqxH}5?(ekN&^GJfV zhD)>Pw(UIB?<{mgwf9;ur7hgX0{ipFM6433ZUjFLW*~LR(5N5}*-5cuo z*;ePk6ec{f1503?`kjZ+i-pgHG;MZof1%Gd7kIi!Ct+WTF|38&yx5*Qd(39fyyCz5 zF6;g6)n9$>tgGXZIJg>raqO>v1Q874b^huivuv!60`e1BC@wtmQOXq?p|7yWWSGHd z`B-#|ounf1jWwuv5}nw|XyuI#=002KYsK6KIo$>{?S zrpBxLnwVI7cpTHxrw(tz(VA)Xr%~MbRfT1m_Hk0w{)w74H%|~VslMBEQ0DS-eAOJ~3 zK~&Wa=3`-J#l6kVL*wWqZh?@8=juPy=^So?S?PT2Z}~Eev)>siJ)i#ctQ4O8oA{aU z{!{dXtr$I;D(B&%QLnuy)^ zV%d8+&R<(yo5T4y``vo@)4z3&|C@hmo$s;Ncr}Q#5-I_%eWw1(cd+gc^^PzHw z$3RLG*)g*sSl%9{eR!y|0V?QPGFf(TuQy_ig(jw$ zM}#*`MCWUa#sL<+Z}Gx&-H)IBE5uO4Wr2<>7$bN}7lVPeiKYkT36_+Yn4^MOh|0|! z5zR1E5FJ~i8?ex~l-P_M>Ns9}CbUAdMecxC=K?qZJbv&cx$d`f^L7qb4^|J4&+Y}Q zabN~j!0ZvgMS^Wa_p$!oK4zWl?Ox9wFgV^~ z=ME-#Fh`Xqu7Cz#SVFu3al@qe4lMDR))vcZ9RgX=WUc2rA8~Xp92kFc*s<{9A29X@ z!!D4=pZ#)KjZXl`@n6`_{P^eJ{o&8q@gK+k!{4x9zPgFx0-zy9Sij`kNR_bHv&pN& z)gZv;2Nssof(FNUpAzE%2AIa{GPo5O1Lh1cizHZy!!`>5U6_c1C9?zG(|S1Y@DA+Y zc2k<)9oBlJ)jG)7evtRen1O z)rGA-+x%G!%*2hP9{0(DSnnDrLf|JDNXKDyc~&HVLH;<0is*v^5E$Qo0ZUVpC3f+v zZ26D+ojrJLGdomGV6O*>fo0shy#l5f?rY(}2II}@fxVsC!(aqDSjKUx%FZoeqv!=} zT-fPMwb+q^7$fJExlMeQDz?Zvu!-5ahZt7b0=yQ`1-8JFCKg#?*uDzS)#}`$78A(gvf(ngXBTriLIZ>{>&YRycr6Q;zH6^OjqO51Bwv=#dKOlG zV0Y2^2#??4KCdVyn7Os}ESLcwfK_UMi3xfBA{ZOB&1Fl-^*RN-X+0K)55`sh1c1E! zG+Ta>Z9ddYo@|}{{bl4-z?PZ|Y|klRV6Dy}EE8Xv!kk=e-7qu74z)Jn$Jngu@G>6Q zHnWd`7HJ(?NcLg!6t=PkD}s*V=HAZCL0&lszu5$*|4||LtY=duJJ*q;ZZt{wTpc?5OVxu9RcEnJ^?0@Q5NHpE@rom$;vec`-v#VUJ;jp4P3&a?I9Y14&Quej z(Laz>XEzggraf2yve~MFx!}jLv4buCWwzNG@1v<|jbl0&!mi)he9%x4oZogOIlRz= zV#76H`nDVo%!u)pB4`-wzg%Vi`hV?4|MTBk|8X6axxI=V8)6od9@a1shbxQ~77txc zK*Iu!gK0m%=o_Q4ae-CI--DO%E(+6SocfWI%0fhA9zto;y#SU4{ zU%hiVauj|Zt;=0gz@O01<#-qsbUhY>jsdk1Xc0d!%0rHZ$LN4EK|=-Xjle@Og(}9j zCpIuHY*yXF!rcdF+(Lu&zq-|h2guLCS=QkpI=sJ?V8fm26ttl(=;M%qg%Nk5VXkxiLESayMpM`zjIR{t>4rq=TFjD7Rv^=}_w z%fEZB|Il)OrawFE{05w>-|8b>S^`ZEXs9;P{e`*jhtVD(eBc{2GuY$$(Is|ne+TGY zYqr0Ojq4+19trV;&5sPMR9cBqSnCcyoQ>BIqB*d+qqYH1&~zp@nB#{^7yDKZ<|FJL zict+Iz#fZ!8_Phz%;32QZOY>Lcq=~_<-KVFTs+L+a(fTrb-x`zUiiw=%cq-3wR3|j zbqQTjt$Vhm!~P1`Zqetr2=)`jhxv9dZdkTCKp!ttc_tTP zhgt*4Lm*)%-Y|Y}FZ?Y5vYD{6f5^{*WeW?Kz&^Zhc$hhBVtyh|wwmf-mmciNR%K_8 zV`m3E1N=|M`;WiCP954rsR8=^@G11qVlwa4;qUA}aCqs|;p!py?b+p}Q*3iDh?7GY z=18{tlWy+9;TD6c0h1#<4?SAhx@-CA4fga|7R9kV;O<$c8@YJSCkyf5^Z{)9Xa*eO zd3De&0SgD1km75@Q)*onsQHO%IB!vi z$7d|@;P*J|@2!I3NI;!5my+Z_AB&Vwh@Tqf-!i03z{Fl&W=q&Gnp>LI;iR+YN%rmE zVXf~yvkq{XJ%yS-8DHStq7Tm|3oWeU*qw||9F|8(7gMYP9bpoxEIA*tAD?IK#}f}$ zv=^bg;7uC%u~H7NkurH`+jn`Ts|o~d#leucL1G&#JL)~hz&JW)T49G>z=@}`ZjVKh zw|mKNYe9bccmnIU(>l1sj{Jx%97?d!LY1{1>9B7sV4t=Fv!J12>u>f?wKk`KhCRAG zJl1xzpKP~(#wLax);ZO}^U+@TIy?In#(oDl)-vV-x4!vPw*1HIAZgg_62?IuKo9O6 z=nuWe`H*R2qmY>TzQ&KM0dnDYnlG!I(*sDC3j+C;fBb2ynfkYEU7`P=O3_YYltX87E{b(MYf+5Y1{ zV4WBG$wS0O`kFKkkqzOOlOd)PCx$5d> zay8jkoMNC5r@UveH zp8#7Xn7pknHfXothbz(b=e}MF8x3|Z_NM^|#y&tP?8h+2GW)${cK9HBXn`&5!y0ln zzKlEn?0(id(qa1(JQnTLUhFH&((GFCrc;rno1-9cf)^POq&vy1NVRyMhr!ZW&1mLL7;=u=) ztPb{NA3te1X@LScy?dcQ)4&tWnH0q~KTDutv3Mm6u!D(*XOBB7Z(p*aqevN$xQiuz zAvUBAEPi|r_Po;g3DAULpfRv^FX?BrAm4hHo&6K`?AH?Z%rmTdnk|iQe&t@8T-NauoVLy`vJ6S;UM-&?>w=@ ze(NG@U1g`g-D1Ceu@9o9^Sk~2^G$5M_-#x+oWYdeYIXNw-~H%HJ*?`}L99zW2iG!V zCuY7D4@?$WG1hc2HAd)IHnw<=z)nyXgXvn2SJ8rg0qu<);2eVbW!H+_B|yMt{2}Y? z`_``xg8=#ZI!3_HeFdPw3u4dyK3o2y_5MQ%mdavJA21C~tk_`3f2YsBcaDAcBKyHl zS@QhLZ2t`V(W8ukYOgM^2duQ|-i{uC!<0i;<)^B7b8K+N+inRbd00|7JiZp||5TGN zelQxci&^n)hgW;FhY9azA`Ec^_U<+POctb%-O`WnazCu(Yq8`aF7D*`Mb>{h*?hXi z_Mc|^(QUPfuB~&tIy||$xpf-NGv5M$EMX7dev5S;YO$?`5WD!e+YtiAqS*d90&6e` z*w(qoJ}7Rx$GemmtUc^S0_cc_h2r71KMI@odJfOTh2K+GcCY7W)*#8t$-?+%GSj-Y z^KY`VXOllY&JD~Tzrdb9%@3>@j_>{8)-tBKYc%c|!3tx8AK`p`MD6W93820G1~2p2 zda!yML$vF`y;lHfetj8$(3x%BkjMM@mHqq*2kJG=)& zcQBjQxiR_UdM{C5jTnjJm1y@m{e}Rt$@=||-*;`an!FwL?)VLkPs;lk^lou{&hGd; zEeQ7NneBg+AKfS+_{j#l?CCc*FwoK4y$m}CAkBXAXlwV{?3fV+yrbvt*eL)31>WBk z4?74T=5F@j&H~8HEJPhPUgi+5r{>M(6Ps9zw7*z6+3@ zF>Du|S+Tw=)^`R#t^z~qiU=9b;_p?#M5*agVvVM6S?bDV7U-+XS@ zgnSP3;oO}cYx9Gx`PkeA$UUXJx}@KgBkP0bo_q5I+q`fAO#27B>-t^|&ycBkm-BJr zx$XJb+y%(Jnhzq|QvGf=EOz1pJ}ZC|`2WE!+qyUVm84kGT>)eh=3o=&xT;PnHcy2el=AO)lq}zd^wD0OTs{V5q5FdO>p1ZmWkbA** zWuj7rYATWLB3%hY$a5EPPA?2ZD zM>Q3V(zuIVK07|-`oLCQ z*O4s6GVgTL+T`TwxvfvT6zemOP?dFNsczdL2DJ_OPK^l6#P#`Ly8!vjgGxkm{rP|~ zOQu98#vKFX12E|LaiV|W#O?zB%<~}=;(NGHSrV1&gx=kJpkeP{cypIxeZ~>jWlOgS zHEb3!)1a!Un)01Qsrt{I7-~YkVLkUjf0tu@reR1nwY0k8un_Esp_$~){8`+ixHTbf z_MiLUKDG$?QUGLS-ehqMcEfauMXiS6sjB+^Bq0*duFcLDNQ=0oC)$|Y2zwgf6fb*wwdwC+FG|KPb3 zn-}Re%tP8uItj{zbT$a0%spuB56+?HdJKl4^=#qM^Cr%vsimp(dx_9PQ zyztzGKI~g>et`crVMf>oCw38Xmktx@TGwEhk3cd3Af$U|rBfd~cVTlA?8gV7KL8pqsGFWR}H!C-Qi32u|Vf4>{eGV zz}|JCf8y#cEUpcen4f;bG3P#NEZjM&Y0jP2-d>vzupyfOj{8`QuyX*C3_lW9UQfiz zwfjC1DzP!=-h3Y=_ML-rtMp)No7&v9A2%9>9wVP}g~x_;^L#{g>F(PKUz?BJI0%f5 z%KG-L+BU~p`(&~es_l=9#NE~n_h{JLWGVKxd#U`IbJTnE;}?t4B3)pdAiBZdxP7=4qWy?&BsonSQTM|RWjv@C#u?$VMlh!)x8}t;Gkgwk<}F|c0!XV)KFAaF=UmW3HR&9m!eJT zPV-`|Z5xXXz=u#21u+k11nh{AuM~fcA!!ilbAEUFPaZT3hSxm2b)qN@RZ%Pj29YJx zt^b;I1xxz8TPs?m`+xyt+ikT`22hNOLK*;)&hR0?*D_b{$tP`j!{IBR&z@S>9#CWA z05l9r6rz|4SP>Y264h}(5hL+6ba}?-(x*4J=mQ3jE$gwkWi~P#9>BCRLJ_!@kP*bn zYUNYJ*@Mre$8$WdKbY|78ZzL4$jGtahM_8|NvKMwq&eZI2|D#YpA+QB=ikbE2Lfc1 zl>r)njdD37l*M#j6!Mv33D6>D@+DC2_v&nEe433)sZ`1r*RS8h$3Oi0fBO%&fZds& z%-0`4fY=g2NLa3_+Ju;tG>B~xRilbwJDPegjYI5NmTi2j-tB{1=JN)Mq}mT2KsH1X z%|#Ju8R3uZT;F${@uU* zcen5gXu3W(FF$Z+F3S}7lwxU0Xc5C8il)$pq}QqA(>j%ZU0x_ogx~vgM`PKhLHN+r zhUs;$JImgD?#)}oZW|Uhg$N!jfFx{9;HpEY2$ixZ0yc{Ibh#*$fNEt*WwD%W55_RG zn0(Zrgs9u-yT3T|YvtQwSsY?xC~<(l70aLK2Ut0yHyZMpdH2D>M}VqaRWzHr4xtuR zY?ZjCWGg_jZ1*F13%5eST!<(C7{6Xl_Z%t_cp?0+sD!ApW!JZ!@RlWojz(>p%C`s> ze~AII$<~Sjw;%a(UKlNdNEh=ZArCi1LCj>*+@r;ZSOmzFM35%M>!VaDmdfQ)ZF;d- zscnt5#oA(Rbz@_(vbtJZ$FZ?qt7UFL2Onv81$fdtXq@$1?}c?`PV=>uIqg9@Q!_GQ z)e_6lZ9}R%lA%(wA(=K&DbX}s&BHyP$f`w%Zc&x0jcdbPacs-6ZC`R4Ue_Cr*zX4I zUL5z@LEyy^j5zFinhcmwZWx3rM531I-tHtG*P)6!pthmK4-P=Uejq+F#j=no4dIa9 zMg)h(N50EkzyI18J|LC4ez%AZK?Q@)EDpytaHP}tDqA0Te>zhxiMN(H(N99O=RrMw zaPSc*h!08~qFDr&Ev#CZ$Q%(w#;;olQ3>q-_ygSiZyu5YKa__Oq zOl5toEL4g@UI3_-1o!~e4@x5~g540f%}D3Q3R(CxmK6%Q47vgkWJ2k70Erd7r#o{G ziU}D2zXG#hgYj?(3F{7xBXq5L7=O^I&AMjn+6IkSto872xG*b57{-q3HGBiC1X>i$ z(tH;5BsY#+sclIBXh4_0V2>=vl5N{=0Ehr%s{V2Np{c4$8kB32+q-k)y3P#S2=6;U z62|U*KehkwzudIYR`amM=gaURsj@CC}ZNskLWCd&-tSEIGYzWm1Pc_Xtpn%k6 zKjcOKbk1d?NR?OMdPQBot=K+5$DR*7w-+)uv{#rD*mRf~ z-YY}-;fhyTT+g-kY+nN9j>CXKINcpK`2m98unGZj`VrZ?7w)EcV@#YL78U?Jx#YrwrgOcygiwZw7-9tBn< zNda&7JbNkf^F=jXxxpSj;GYlX&xd;Jy?xOz9vu><%3dtvo-wNaPh zwhIcxWqyN(Y)%eXTe1R1C2QWHZpb3bF_=Zv9+TRR%REVqBBkLm-}ZE{FVu+JHl-|_ zGkdIUt=R3M2>F-*0n(*V12NMeHhz_ECoy`&(g|t7W=V7s88hlbI){+g-5o?vzB%fIniy%j8LJf3BCaINye6fv8iGkp# ztYg8O=Cc|?iyd4f~}{Xwbi)HTOZBumx0 zsuUWA5-{0?rB5WE!P2+jrU7)R=QEpv#?Y*l7-WiLIF5!%imp3w70&^prA9Ot^wf%b|1E_6Xo+nyDd}RL#&NHyqqgfV}=X0Oa-B z>o@H)_l*CRklmE>0tgRrt(dO>M_Px)o(5@M2HUV9r1NZT6zm5>u2)P68yn&xKthDK zv#|j@Y-16bU@24l#e|qzWu@#ZYVPP8xm>*V9r+>S?%C*%k7u(wCda_>GNUfENl@0f=g_GpiYgbg|${Q0@zg!p*UwI!?i1?bA zN~h6s2qQ0M#gkx1#>8SiGqfWZF)6JM_W*!i1(;jD$lYJ4M7)T3x}yi4Qg?m7uKD*f zEz7egQ7v84J|Rx#M|Yd36seM;%EX9e$9D|VR~28C14A}Jm-sPqCf@-$LM4+q_+1Y# zh3hr~X8YS~Ah1FfyCLyyy$zBCHhK-=!H0fJOaS4+pA%c#vLZmTNMp-~+paTj-enD| zy`AgRj+t+{M(k6|jo?*c_dWt-70~e)PnBv2l3P2pA~RH#xx0KHi#)%iTp0xgUQXo` zkm*GMaFQwK!A_LGgsf+PZ2{3*1b}SRl6-j$en~8|a!T0hfs)A-M_H-7NQ3mrUns_F z6cc)s%jEr3AvbxYP{_R^g8n!Pyegdoy^+ox%jU9$Y+5X2UV1E#9yBaoOk=iJ9^kQ2 z8eJXDmn+F=W}^t82{m9HLuX0MoS(44eU<5fOiZdaT$Q-DX=EQZVo4!)86f~fD8Qs# z$B-?1-efAV9NFwi#GyJ+D{Y0bIZKIrX};$=Ebt%Vazv;} zjUhTH5-a^SMgwDmhzzP5hK_+od?2-1Y{gzZw9UY%Tiv)pdp4MnpuwnqZ9Y`SK9~9U z)BxF71;SB!3jUYMT#I~Uw%|%=bl!6nu4O8v(ToT}WN{HhJFu!6 zm=ad1jh0|P$0WtYj5G0Y!DW?EA)k~*&RF?5a)QyDon@-yYw zSn8EYFc(?+2H1~dV>v;X%w%&Ju_S;L868bu1^XiwF&HlZQWlepxF`VU8%0Mkru?QV zxFiQ&y%7P;hV=t`7aQEq^1>JhM@&g<5Z#fbo7P5X=#0R8cy}8h=*dWfES*qKv%R|Q z7({h7+4o7;aYNAFip3nSVKa@JFAoe0Je0LfNn`eQ+&i{lKk-zDpq?RHo?FoUx;jio zRBmKiLx5n4m!ez1$XL&)%Q7IQZpdMz>D@Vps)jlz`L0Q&c?Ta5`?iG#EWjT;U_CYn z?jt}zgZ#zfTIneuTCcDE%WIh!9@tUS9)RrX*|1&RdnIm2N#Ct7g>Rght!zlpha$Q!w@>3gd31MgQs5#6`le;$T2LqF6cekZ( z@c3Z9k{&JP^BXlWvzS?B<@_43tBQbKfJ9aHz8&&h7;5I$^Sbe zrphe8v9_@R91U}Jvv0U3M+(}D6UxYo($9d2{A}#x^kp(VR{8U>S4KokO3b7RBdN(3 zbD3;v`lz^`7c*kHHcV@*04i(AYDHWvF0PibxUp8kFg?aW=I2~j8)yNmYx?|stxq2` z>;UM06k5C>qK@(y%f&%BNIon+!c0Q%@*N`0QK@TCyROH+OuI^eNly+nY{Q@dHJGc_ zEe5Qq%Ora)=t)!xW#B@QrQ$ZPN=|G=VazPhCxIOUF;i4SlerP0@a8z2K!ckWxygvA z8d0TsjKM<(;DPJQbLXf(==oBx(hcoiLsC6!m}K9BKhyIprpByMx8%$#+>nU*TD{c`zE7;$ALgGNYyPs+i&)-%O8zKh7#ZrFcrH2bb`Df{)xsz`^ zTuQ62WyYq*jy*g!k)K4B0aim89m!>dLZ&d9$$`))7lB8Km2?rk0PCVqt5nMQ6t;?h zH&hnHRkj8yB$$`42@g*X*nJ(br44MLv^vs_n8sAX^(1#4SgEkYNjvi29RC#xVrYOg0lFMOT!ELpK)0J&kx>ik{0uhzh1WQ5U733ISY zMKM!LiDi+Of>iQrwQ|0)cun!dy|8EfBC@WK9{W{zK1C>fZFG$l@$CtV@TrC@OzdjX z^s6VQ-yNH{qFf%!O=_1XN5&?yr8HKQV8kPn%8lf5W0PYOxx&em07gPAf&vorwKb6a zV7*vg05ifyGmB!T!Y~k0EV5YFZ{Ei5BS3nl!@A}i^M;PzShnQABB~jqH?;wK>s>CG zz|(L>4NLPR$)%u!CF&4f3gXbH>#5%LfL$DfF<{45vBQ4YkO@d@g~c{pmv|1=Zpc}f z4(dhGRif(@jEFW&n#Vx7LbhY)!=T78FamEMh!-_2jcUDE0r=Yu){qsjl$O$?lE*K5 z!@%I<=YN^+z=G7CTC9~|x8Cw$QCV`BZYp6H_ALW8o4eE>JoOyw&x=J-sPHghB`IdW zgn(cNtPI%=3kI&`>hnY=GHp;oLqjs&(Fv;1bxiKvsBHLK+le!0ni8S!lFRSfihB9V zW!RLiT%kvE!{ieDoXus&3MrwGo1Dnz@+F}N*vNzC0h>`_Wx#4Jl^HE#Q59IS#eA_+ z%qL9$n2T=iep(Sn_uab3+${l82Oi7M4K)2n=F0O>iyYUHR1*Vf4HF%Ouq|C4!%&AH7QlXB zPW?-TiOCTV=-EO_%+^YIVdSx^;>24Q)2{RC;_+9ba8%3#*%KI0JV7WHE4N&u_cPsu z-gs=2>%M7fKZT3y|->7WM~HGrE999tohO>eo}dY6_g{mJ$rx@uvSktcN=&Q+ zg%8)CBlU(Po4z)$I5IjJm3gZnNwy;?7MOIHFqj%Z$z^LyNQ)D%6+|(YD+m+Wk(Y8A z@%Y53cyc6LD2(P)V};|{lpy}SMBe@RWg@+nfbvo3 zH6x1ip&HgO-0a3HcetlIb8vMVj-kMk)>I2zL(h znQGq=KGslwWHP|~Qy@PotE1wguv&WQ;p|KK#j)vp;b;M_u4+;VU4sfN0}Za12G`c8 z^IQZ1>tEIzRC2nMXc$}e994!(E!i+Vh6`Jc2OFwsUpb2ODmO6(9P4~REQ|>g!e};| zohXiE#IcdF%*0r>FgZDr&Yg$pk#ZA?blDvwY2aRT)irXvO}OFs{*C|$;8am0H;||lfZ>FmjD>ijFj0;U8jpYY6zI-w19SkZs|E1|X~X|P36*qziB zyt*o)MB|CnV0{R={Aw21)kv<80+@(`Ffvxi9UU1vn$6`-judi2VI-T)A4`vAMD=85 z`pS!ACo{)hR8RhSIU|A{*YI+jOtz z_2=l|Efp%|HL;XEmKO?ztT2|(j~&f{R!B{Z<=kI@^t50`6j^f(EIWh!3s`Dh<6qUf zPE-?S1AQZPN`M%{#jkU>AsMDpW7yU_kDx=0*yI$!u1f7RIiOh+uFg-SrAv6?XP<2oX`F9?nNx2Sx((!Q-{wU9?_7j;|0$ zaUEB;G=*vy{sxkREQ;`sqxOoV*p>_;TUKE{z^1_UA9f{G(PztdF%{kmm|+9n3CssU zDvWpF@567vPi%em|9xGF}hfeDEfOAdTB86>$0kQ#dTi|HAR#Q+!!$4sb+qmV zP8C5*uVL5;IIspYs9O8XnuI}X#F*EVA+}K!dB(07Kng4t;n|meo z;?a?bY)UT_G6kSlk4=t@)+@<}*TeTAdcMc@W*% zpN(Z+OO3$DW;2h8#+Z;R6dn`DvKe9QGP&~NB%K~9936XQI*a{LDmxh;FdufTsB^As zxIW`vyqgWo$MoYZg=}oE%=5ikS9y?v8w8zSWBx7dP`Kgn`7pNU1I#qmJ{fS$ZJZCZ zG%^Pl!Kx>fs~3a^7!};UR9(hiKIn!XJ{s)^rk?)?zy7KqJWAyziS6)%4kFW1&`QgGkW0bbTZ6FMnf55jXAA73LeRMve zn>&ESD>ifCzjR~Uwk`T2JLvj=1#WRa6C#5kN=$e(=nxV+mV_QJhlj#&KIFP( zvXj}W`gDhYHy%V-#P$slGybMS>@0E9e8j`p zO&qeWgCV4WEs=oEtHv;9@o^+CkDd9 zp|)ywQRLV|ivsuiI~XATwi8!XElDG7X2(P6(O$WI=qVmxzM2G^jpVFI)PW1*Tseu} z-Sh;|nh9W36IlWHRqF2_OQoiB55G~Eo}NyPyz&cMku3Oty$D2y%)5;_oIFk2zZuiP|)(aF0bH@2D__l5Sf_ojtS{EPNs7O5IpHzIy*v-oy?vb5ppAA z(_=uca;c+*$%$NUa%B1n(To@WT7Cb;v4=-;+1Ez0uWBcy#*PI@cbkr@T3x16m$^~6 z6*v5Z`CvV_r_AAexDAQAu%o-%^-5%@B!(?@}I5y>LeH`Gu4e#2r zAn5#^H+L>TwpnbQU~0c)fhv^4$g!PZ4yMF&>o=j>rOZ?;UzTw9LBC&D1#?Se%NDV7 zn|NM$QSftxqi>B(PQH}O7GBDY9UC1Lr!$%9m-0CmOoRv0QG3f($iP*J-Ij@M1IY!0 z%~RhTW7ro18^kKgyF@eJCB#%N5p zy_*zEoms@{g1$C~-oQY{r7l@pD->3v=3wlBqVI`o3mpUk?D2|a$^o-=msy%-IfO=l z6x#zk;t*MKu)Bl8-BWx%hKpL|Q9hY+ex%AOrdffElzAjj8RlNWuBKDodU4p|Gz4>^ zJH*D?DMJRLhBbz|a=ouyL#1Z8qX7~yAW6g`*zT)mYxTM>TT*OjB(PP=IaUx49E#cS z(L8an6$V@Z7v#2c@}%n$$#LF)?csD<90j@T6h@A|bTm6Ln$Dffk32lNmd{P6Go@TU z#nvvK*>-ommGG9hK&-<6sG4ipo}~3cI!^*kGk^h0KmpYG6-AOYTfVgN;k>3fK$Q)U zC-XKvnadPkIy#cZO7v2?ytXQci+Qn7DvSA4zPMHtgw>KLiskg;uiCv*>ZOwx$1YzX z9CMd1V~lLRaT~|tf87BQk`U%Yrgg$}szzpAGrNjOVx7u88!q{9KA3Gpo&nrZa&1XQ zJ?+7Kz_w#|32|438@3KBxD6{6Y%^^CJRRL|;kqiO4q7<|m9o7sRo2^@j{xVxGgkmD zVMwL^ae}T0J;#}E|k6l0HU~t+R#>{*ioq6Q!Nszb>@w>}=J^DljPvp@604}JgbOCMf( z`@@J`x^!v#B33e)$|~3j%xbBO7HgHvMygaRmrBLeRJjbcM64k|z-SH6oO&nfY8Wi$ zE=XP-3L9N-$MUNI*5fpQe})oXysEl^POvMM zXMVO3GJSb8D<92uJu3p4bI0M10?QRL|y^etic~m zA{!`Uk7#laNIyujIxt}m=LRfz8z%m@v?E zz`KU>Sm)JD3dS4^jcnIx5X->RL2i7-k6nqu(0i}O&J925s+uK9ifYT$irdsOw+xVN z*^+9YW#Tf$Hf$0pUC%UnreidK6zWdos7k;renhULW1)#&=Y~zu>iC}OAaQI z^0oB}z#@~+7mGq_7!dr2|IP7z*i12M5A!(OTKT3WnLDy!b)ERKAvbIy``ED)g9Zjh z51pZ_)|U8uP+yW=uophehi?$j8nV-s6_}6fcEiAo9-_KBY7mU)4bwsKPrq?7#viTx z_UeJ`vF@1w3<$j;Xk51%eqfj@juJ*dE8;jF=7zPYjFCV?(|PjNyses^%4prOWZfIs zwh@?`ZmY%|*H6qh+-^_B{1pT|PQ}*yB~l~afdJ{%H5$OKf?3YmR&NSbaVSy24Dz~s zxa45Wi30=+6r1j$>fp%9>|PLXGgOyriv$z3hzvw6wAj>PLw7mCd6Fk z*u<+_Jt2net~NKf0K&h3m3Ys8&u77u;f zRHw0oUY~704_@gud<5J@1oNT7e8{}XZD`0kpu#YR4+eB79=+ZXS0CoK$rjEcFaVt= znh?z}Kj9AtD`AIDj}4T$z%gL|9I7=?JEpF15ouUfoyRVQlCnoJn?*-|7JSw0w#QU= z#WYmQx7C2@PF=M^If{Gw)-y@64r)-~#2OIs-I0+@ zHg_!d#)OzDj0s$SY!vfJ4Q~DN*e0u0Rx6d&Ekp5lSA$FMd4BZXr4RqE_#r^yy|+P_ zUjpC&asU_~!mYJSe(+v2_z(qp5&M(?3`8MctRyU7E(^u7SXsrY-i(lE<PXi-oJJQu?lhWSibRjvb2fUO!fE*<7W zMK3uBb97m4QF)jTGHh$ejsGy+3N4VXUW-cbJ|jc>Vd}gd$&*9oyS=u{_n(1j*}hAx zb_l%Gwd;;Bz^T}p6h)PdodyuwU~)q-v3&;9aevy1zsf!M)Kkz^ z#oa!bTWWz$4=hP{&?7R8Nz{9nU&~^DhIgh@6M`tDMn=RDv5*sgo)ag9u|lSt$&QVt z(`B|%1MLhXs8npdRZbR%4G*!!XsuF7i~qWG>1~kUm;T?UGCu@_0IRyhydNJcuYwAR z*oT+=zsdY301U|WORSQ|hS*qijvY(#A_MzT7Ly71sZO^-H%Z|F13#+TX zLM_W3;xc9y%m>;Ij@IFyXmG=)c{>dtn6l&gE`!yBg?d~4Q*r6*!>EyOVET@tg37|k zM}5G9crt7)b);iPVAJ^Xcv4@AK32%G?} zQzTk%58g}gJhjS3k{8l|4xt2~C@lhD%Glc{4{`*L;we`0wbfx+)c^i}8j&f%#DWUJ zRK|9du548>dFsY~@?B`YW>8ABXigOC-_77kHmPbKF6&)oa{wsE9w zqW^*~cw=5h0B_EPc;LGJjtOaPDz;`?&<57%>*YIb+qB3RiNL||;T#$!3 zU5N-~N@J#s^8FwPW6-cE?4;>9^f7BA;sO(hFvuHmoU-E|TaWM`kYXJj$TDFPa+Ir6 zTw;xF6hMVc9eC01Q7#X>R=|2~oHXz;LEUrC0lzA(HXHJz)kpPnbmPHl1@=35_J!(V zwNfdqHsGuFq*BbV#U53QI1#M{AOPFE7{FN+AXXZPDT|eb)q44jMhPtI-!GI0BxgC-6=ToR&z)938+zWv1sSLu1U~ z)c#Sm1p(qEigH1Ws}u_w%wIC$0gfijFyh1_GM`5PKAbzu<=O|99TW++v`{_-OK7nd zA`a-J)Pxd#HFUU7n0COff+)b;%5jMDE+C;XF{hrI#eOb@9~#Yl>L$a8i9j4UEStYF ziFw<87+^vp2T%vmHMe6vRR5p`V&dtH01}e;3-C{c76cMX2naKrBta7C784%0a6(M> z#X`3fnDCh6bhC38R`0y`yU%J{s}CMlSO4Efx106lGEVDQ06ai_Q12q2!d=~JtrWw{ z58K`4`f|PK*;DTSQ)v~x4aiektd+1=Xt{ExUB!D?E-#d7pY;)Cs)gOX@$Q^jEfj-0 zD+~2Wdw*qbZ@<;*?zQ2=A*h>`ehUDk+h2JaD>IJ7`Z?G`F81C;$5!xq_`yGBoHve> zjNotqaKBU*aULSas6t5b4&Iz%FDfv4j_nW=pz$#%#e@}=HJB#tqY+`oZi-bP!Lu>U zS~(&d;m-n21(6XNjmeA=Ofp)W_2I0+r^n*+j43cCU5uzLNX4)CV9Y~dMeP;N zy(ONQnyHFsnc{JxbN~!CRU!+f{&=j_(-@WZi^?l}1s=}J;mCeH66K1{{_zYXH$3fO zVl-92p#Ce?AiJpLFm~vs6w}>2u3<4!Lc-J~Lz`m7G4^DA^l%mS_iFIyOa1VX99(cN z>ucK7ON&Nx6$> z-o13@Os%}|*HdC75?zj8;hmt-ZG+0b)j0T9u2((ZnakjsAvzW?K->->RlYB zj(vt!>TP(e(y=%;C|6`xAsY&>$Z{%Yc zfl=QG)*=F*CT)i28kl`c7#4(v9#PXG{_bJim13H-KR+Yn*sTVL6!D2pokU~7D_CGu zMDs?Zs2c~Wg#{t=IG^xbpMlB&D56-FQv}P1LsL-{l+5#k=hcBy=Zq>YGZK56si^{v zB@#&)2*3zSeV=z6lZAC);iwWAfx~cbaW_5w4~QTsafEi!{Gl z#z$e05C@`ye*k3`&qIu^)bGItE;W}LkKVgKxi9_E(nM?RK|~gAS|p<&}PQ1+@C|N~>b)_4Zs4 z9>lU}K(4UxA&y+2zHGkp{6NnB@eCw$9I0^XIG$+&Q*xOFHiK1d)8d#G*29CR?zzC^ zRU8nT>F(n$N*b_^g%;cAn$OAVR7H4Hx%qxoKGg$lZEr9x}5hNf6IDSf9ksuZT!PTy7BI3h!cT%4O*&GgF zJ*1^An~faeL6uFyDO!bsl(%qaVosCWFz4P@rVfFLss+Xb^50Piy7 z=LH}W0h%z=E*s@C8jlU=#XNDN+=vNIPBQS+b z`?v-)hi#Y_(JJho4*J}oiE;b{s6G5&gnBWCB6Z>Q2^MN%K@E6*M!+LrBr8MP+;s;a-IPuIWi6vh!~JGyy%01fPvi~Tn-T9 zkRZviUuZJ5ibPT{5hpX_CtB07nsTYlOgO%_KA$_Iq7U3O&*)JHhxvNYqMwbDFD5J| zUIJXrchxI45bbi17aC8m6%Z@qx;f}T45;UTf;ji_04V%{?|RtV0hushtE)b0l*;Ai z#Rt`M&8oh3L2>8y2M>Jb-rdh1eK86i4O&^dYx`dhT6jcQ?$%rON%=lJMx}e$wv(0n zmH)i6+FxDV*?D}avAg@}?)}Dt`=!T?#;i1m?|!mV{>|M_cX#Xm?cK%4|M`>MOK1Mv zs<%sD{kgUZcef9CRB2b?tuk3rUld1$gZ;%iswZPw5<#f9j|4csv_xHk3n~MPsIn zq%UNV2p2pSM%1t?3K$3)OT=GX5A3*wicva0@_PK;2I9|6R0o(z;)AP-u*M8?d*C?= zMMxaG4u~&;?<{plXersME>sqmFV;3bXnsz|t4r^l2;N)#>UV@x8>NOltan$ZT5g>^HzRezspJPY#z?Dj@3*C;gTFV5QW4QmNPLRXgZc z_f{(Pa;x6jTbUdk^I$^66k9&fBC!ekb_AeX$utkm3)_-v;QNdTHstb^8VJ=#>p@^G zm~{&nhxH&DM-G6ojAO@@>Ct*ju>p$zthf~u-`SWK30W@YXi?V*!PK;end4;kbVkq! z9wd>*(bHMRGK*0$<{nMJndcE94Fx)pOpQ~tYXEc-{?PLi+e;0xBFHExSdoZrn`4zI zcWfSuaUvW!V}anrrU?O?4v7#do9})j3muX$tcDNRd_BC72gIG)7e;MpJaXxQ2`Nwg z$m{X<8VE)g4#F@7*E9xon1u6+F;pMZd5sZChZyR`b6bEG>5|ku+FD$wJp8D(w(;ol zmJ`AbykN+dm;BCq?@!&O>9ig;*S=mH90IW_S)5$^WHR{E2dy>|pTAD*l5iCZL&tz{F4Lh>(&fhHSgJfyW zSSERKUMn#UCWVKQGaP?F;^*0lERZb5^$>ts@hdeDjG_z21qVyy3=1t0qg_WCx5#Z* z#&JaK5QfkK`p}uXiN3634E7JFxxc6Lv!HyS(D*Upw+8@^fY{HkXApfvd(G092qX_%Oo^}PM41zUj!iX9>AX^-Q(+IKVU&ell zQKT$$gpK63FNMH%?XIy7EqXW1Gk}@rM#?!72zuU{6oXfo#_D<;{{t(9i-pP_yR#Q* z?tyRwiD`s`-b3FJsf|UBU9Ghadt5#RYb|m<(%`7LAL3uK5JANA<_A*g^Ym&A5PKo~ z)aBlfydHm_f#h*fz0Bt4rYW{h=bn?QkmlGHmk}qqeHP4|IAa8N(1U91K5D{NtW_(l z(J0^EsBQ$_fHrGiK4@;#%+|)k%hw*(+PpT%%6pZ4TdhxU0Qy%IkR6>R7z1_}EW8>19-JQnSQ@AgNX^R;sI)Dl?O>ZwNG)~hQkdjrrN%eLGtciZ)Dd(W1h_TI(mI60_C5QS7Q z-^Zl^-1fe~YU3cngG8U}P`=thg$i~KnXd<#fx5t|@K}c!s3HmM-YNVX+%C@5AxZ2O zHMT{HX;CnUF*;BlSTUlo@D@CND1mLM(8)kf@Tuh@OMzF%&e+Bg=w~5vXUtiV*a8m$ zGCv^vC}a$HM2{LKBJ0BT*Ip4c$8*C7a717o$~-k%gJ|~>Kx-k>>6j~KnW9=25b~@u z+yUa_wuUwExsTb6xE>6LA-=pG*mKBr8COC~U!{ShfS{BNL80PFI+uhh3$N&axse73 zkh)wZgm#dEh;FO+Ym%WKz4*EX89((31{ zZ6H=%3qrjZRx=o2sS^kh9DhFDxqI_c?NWLD{E3aT>)X4H$2WI&d%HVf=i0lU-tFzw zE?ul#+O1u@xxT(uxp{VD*IoGJ@%qiPCvLu3z8RD%wWX!n;+uDe*IwJOU?AI63k~jTde?6Vr_c~V#qwHv52>lqC=13MVHc}jtn8@ZQ&Vlh<&M#2IRObeA>H2 zO*tqgD_{d{XT)g3wUNrV(M)b1+y7}cDjp0-mhjoUz=FLz7R0Jv#JQGIfCZ84l_H3b zc|BCYGaaMq7)G(>Zh-D;1kh@gcQ*clI4J_V!AAVVd-QQ>p|((NE;SY}ocOx5)m&Mr zZ8g4VG+@d6=4We7_R+o18@NaJRzQLL6~jIJ5KS&SGQd{H2}8&Dv{VAf2VgdgrA3 z(fY~3-UJ?HaCkUb=(h)ze!X374O;!@ofpiuB$7lvVx$VF3+*-0A!R^z@NZLO=Il)47_RP0uec?|G+=QxgG|mQGq!H zF*pP4s1Pc`vGOSajt0ID5i%>hfSiKwHh{0nE!w$xkwWDG8Wdrc@n>yyv7$sg?J)X$ zh*S{Jr`3y~(g8!T7dr@du)EDnCLf)vVKHrq zHkvE{Pp#E$Tw9GFJ=$8nTc)b9aj`zTv*q1S>|j!#42nsz-6zX+yRv9k_Uy`_Kd@(B z`{dHDd%EWC?(ClV1gzrhi8s#dTwLwEQQHB6RlBsaasJWL*_(~uz|Y(hpI%$v*}1m+ zZgc1HnVqxsrPE8*rG@J0%Bi!pm3FIKU8%Gu<;e=XO)T)Ms@(^xe42)pvSh@=gge+i zkaLQ4Jd`O+JW1`yJe#7bnPgx%=p&=iD>V@18B~85#Ze#@V%XgvCW`e)C<+SdCG$?o zxE=`UN0n8ikS)BJ-i)UTU{Wf?>4u<$b)09J%#wo5k8;ke^sw6k&tl+QBy#0E&7^4a z3U}uh1EY(^*BooC=7)MH;xPU+hYv}Ch6NZnEBKvP$Q;oVjLFs* zVQH_vZ@XRKSRh39?0>JdmO--vgsk;CH!r<`L93nJU%hdDt@LT{&FIwH%@da%U)$N; zIJ>huymqRybP0^*@ouN{rr9}jdgsJCsQCMfwfYCYI=!^GuvjS?H=e9l`>pCq3q*Q( zx!lI6RvBz&`FQVL>0lCehO_hn%DrHSGg|>KR470njwrfOSWcHlGIHIK^j~p}2)JSE zIU>i_U9cWUkzCIPjx!YwtOpIS(GMms@dDDHHt^Jp8th?+)wy68H1i9BL@;A^JDTW=V+cNJK_4@Qp>`7zLZx<9fbE@IVXU7_Y+QBK*n|*p(M+T`wOJXP8b!o^g|>Q(g$xoX6nNIF2p&yjEVQ zRCMz~W98n)QsdF$YSmv_u7C81immrZP;J(l<|DyUdsxiLY`0rDYp`0~-|yRj-K+1d zycSlQXUmTtzkBKNC%b2xOUrj}cGlaa^E;nD{>`P%sim8{ozIrnch(<&TK@EtYde=t z>@@y9f=~Vka8qO3bcKZ^H-GBSagEDctZd%E{a~F2oz`l0C7N$zX_%TW87dEVd5mkHp)0YFL*l4z!xsX4tHSR zderkd+J_H+%Nz$S=~>j{0IWVmTE=2fxIlXe;0VA6!;V`N*25D74{^Yo0hSA3gi)aF zE2LPLHV)6O!_%LQbW9yFc8N$G(CGH1*@l^-?&&S zeQ@cGotu7ey4-85?^f0trSs<-Z@zYV^YPi;O7ro>o8>b*@adm-9$%|}<6~_sr%q-m!%n3L zA{;D&aabOW#7zUFi()+rVl3e=001BWNklBz2QT$P^nfgJiHyBxV`#ytM=Z5)zx!dwYXZke6jSPbnf$uZPmQ@ zmz8dN@}%7@wQLD@@a0w8+COYhR_gYv6TP+5H_u<&?sT^Q(s}c&=il@SCe_(Jzi=94 z`fg)wwS4}3>3pZtib*Z_!v|jDiy6sBew)$v; z{q|wEZ|hHcr#!U~M}w$x0v@76(}KBpcq{On*TZ}{DtW}`?hSpw!IH24Uxj-ta}QLIZb?Cck61auGu?ci}00qGM( zXKXxd5Bw0D(otgwn8(Dwk>SUTYfO)QtiSxp#jMChI5}|=8q}ij52I%u_>GsKc-L-Q2 ztHxGi)VO`2_0ihuYP=R)eDH9saj)^Q|kcH#e4Uc5d!&eA=sB+*t2`Ea}`Fu626roz2D5o$AI3;8;tY({Ju> zmli6uMyXtCEG;cHHm;S|FYklw?+#jBdsu(cU$O1w$)JAt;%ght4z?5Urc#7L3Krp! z7m!}=$I_ErDu*L%P&@?#_XTe{kTaKx?N@k~Zs>NdToPjrFXogS|5+5X(M&i24WAbd z``Ey2sHuZ`CB*r8BOr~Dak)Ff(-5L~z*4E9M>>H@JMoaZk! zUI{6Sv1yDyFT)LLrOM*Qm!;dwjr%7zF6!k<>7OodG#lfE=0o$4J<^%$&*P_uhxo4x zoA>bW>#y65`)$x4hxNYws`{(NwN7Jg>6ClAcDJ;CwtTvF;@bbw_|@q*AD7p9CqKA( zYTdimao5A{+09P8QC{!(-l?UvR%vPJ#QJNcQmIy3Tx&E>ua|7ST`#vM-9G%Yb|1d9 z-MwcP^4EE5I-dv1z#@S3aD8qRMJ~bvY^wo;LIy148na!c;+Pm0GnP_8!dKQXD>iz* z9y+0cZ(sCR7M!f%;Zf(3qxR@TL;xS!^PLp5gv6BIDd>chfPsvue>?@y6rMOvwWDI2 zQ!5M>hob(Tk5ZE!C(lE;(x=>&KJfvCgs+vysTqRA!8y1^<0rzsXN`%d?^|jDS6j@9 zoMMZnXnun8;tgyJaDlU;uOc@%k6kOUh5-Aq0rv%hs10J83OEK-DUY%AarVj#WLWgc zuu5&`oI11VbJv;9;CiOpHtHQwQs-{HQd%TS?6cbKhPu2_d(b_%ap$x0#@e*qBrGL? zlc}CQwzt~t=fq&XbEDq*@K@Ko^PTgh^-gvDgY!Gr8kbL>-&w4kEuCLI;a^&RT-)fB zSASJH?=GBQuU$M{b2ol=v$n9*T&$d`G|z6FJ+*r3RHxFc@3q^L{$aP=1}iL0Cgs6l zzjgTRi128RVopg2`=0yQlmOiBoeza@xgav|adagGtXJ5t5L~BH+;@gb8Xwe1?^V@O zNk79Dmr{Ber(`xhwjLR*$Joo|QN1h3rlPD5d&YT0W2;hZsfhhd677JpCd^Ir3+o}D zQpaaUZ-#l=H8|r74+jGYvV-a)aDrE9A3z8){B7 zE%VqKU&MCiBz7~iv9g;lWhLYwJ{VJ8$niLedN4a5GN0bo6MN8s`mnX2&qJ#<;sMB)L5p)x>2{g!~R@(M(e=;dO*{dRK z9o_!#|2WT%6NUk4S3CeM>fO6_@0~jimZ74_!~#>6Bp&BFDxgDfUH~JoAYNoBc{Ssp z4S{P3RNft1wS9bZgUzUDmd&(brYJoJ;^_Gd{Cp9CDy)2rP-1`$r-C>pCO*kx`W@>r z#eq>S^|Q$Jf($@5)CfWvNKc4m$q8np8z0+pVT({rv2g>oQxOc434J^X$69S79BwkK z88n{F0t~?&q~0{)FF<3l1F*+|@WBgVR}^;R%9XcnzUI$TLLz}%R>wA;IP-T00;RVxXl)IP>v? z&&TC}MR8_a3y)@ubh1%ueQC{s&5sd8J;d@gH{{$1$$?jKplw&K+_~{ZjF~dP=NOF@ zb8(O;tVak^$(0cuCN> zP;K6=waWhOuWmQp^2X&0OO1!uHWn^EA_*3L8}{9YoXx)6ZSjl+9p!>bd0nNx4_f2)6<85!R>Qz8+e8c*KVjk1`r?SHYE^7UvFuhs{4h zp-?ggu|Q+`-6*I;iY?ACR-6fN8isJD#w>EA!iEai^dy6=3;qRsydu(NIiQA4+@k00X2F_$M1D!y(0?=hhPZ+ zD}E;g%kdM}b$bTvqLXxbK`%s$y4F11IlFqc)46zUW8-|axzg}vhVKN68i@D4xQ16`v;6*rUVDTb$JhKp6}}<9ysPj8 zxb}`2GM_qDg>bKqkbs7O@Ho|JXcNqaaK-TpPv9Z8akm|8WS#=#l>p1R#~cSbpEto zu5=G4)jsw~vF&ypd%oM17B&-V9e@4~)mRkmgNO{phqtaW%J1Fz0v#Y${s1ksI7bfT z7LkGj4O5wQr59%*0FF!i?8St}{3zh?Qyvw%WCZ&$$f^032SO-kk{Cc5K*u<=#_{RY z$9xh-gz)Bb>hKW6!EemScRDP}{24}6Qvnn$W<`*g2|K0{th%4lI0Q*;XyA&O0AU?R z9z3^zIgB2qf1%yrL5!1S9yK-#V-v&_I0r?wVL9AS{K61hfM=bBF2yd_g8iE-Z!@3$ zmm5)$N6b)0nVi8D2&ML-Fw#)~>%oA&Kd*i|V+FGT%bbqP-#plGI0zI)>eMh^4 zG>9YP1DlGy&URGXOrSV*LMo;L&w$%D>z(3zoJ&%iEvX=l^jj@@nDyL_@%DlaT8 zR2R#o+G{_nHBa2Uy>?>Kp0w-LHr#+%Rjl1Rob20vcmJ^Z#6CYqPZM8wJQhBSbV$U# zJAVXgcd!NzHiIq>s{Am6bRPLn_%pDm4DR4B+5GBue}y^++K znK(GGi9N_bmuERYCKU1%h%DiWaAlyRBd*-}Bd}g#uqz};bfCj{)Pe#C+ILpqsm{rpZ_|x8(FnjoLLU(Y zQ9}dq+KxAS+iu!HfawICUL1AYua*~UOSJ|dNUc^|tW|33*B1ZzN!wPJ0YbWadtJbh zYPZ@4k_9L-X+Ix=ZaD0Fj)UZk=W{WoEW$xxz^s7ka*t!ac;ZY!eFj7Ydc+*+vz&WU zGD8ITN$`F+Fd(NRaASqH(mzpWGjYU)B#1%J%V9mRetc%Rd?ApP#c|Q!IWNv_^^_I` zE}%dtnPT$p5cB19Sd<^B^t-Sw!F;L|E`dJ-SI*ObdQl4dQ>z{!iGdfdx#V=pIS77i zt7(EE6`68H8qQ1BDJ!zGaH*P-6reK41O6;)-JepHK!LBJ8a5Nbt z+#Pyaa`=KrG538xR18COf-q2sI>!9cFbC%*xniKPnD!MmAkPB>;CFPW`qLQ5Gm15J z#$!TM>I-63;AYzCB`-!!fcPEmx69SbrKQ$AXYqFR;#zaHwAffIU#wL6L&(bX)a)f5n#jEA4*2JQ-B&Wd9g>w8Bh7M`6D+6&oHn zGLlhIRE-&X5$hS@2%9Iu=PZme-;9(L5@Qm9q8fIHWLPBwz8L2v@~pVW7qUKJ@n=77 zF;C*eAi~tlk>tSeZJ>yoFNA7R8^FGwX$L$p_Q%DM%8Wc6Lg*O+D3H&#(|pFf?^zGc zguq5})Of_siu{b$t7y=0vaEKDW4fqFG96JIO2@5@$2VfTlepjb+jRWe17H4BP6#x_1teP2RM&m>SdGoE1prB^{%Ok|c z7*iJ@?m`_Er?pgy0OS*FKb8S63qc8ixAMVu0}+FZ0_-5L9tSp!eg?&VuYvrhPre;OjHXuj6!-?F9+Ti3(gAFBve#;?mHVwlRs9+n*16hJbJc5p zWFIybwSmiJF(V=SPVJfwfggh*0BCrJ#{~(*rUF zpT(=CTCLGo>Mk`FN~@){yQkl*eRRSe?yYoJ27PR%Se~r(`@k51TeT*3e{$U0YU_s) zHN(IF!=;P^Si6$xF~|=UT5w3}04vd{3b+Ptta;JAU*g8#5q$KyGgi(E!BSY0T+i%G zZj%J$O#a+s%~ERR-%nFWsmXV0*IZ{n%mM<)AxR93ilsvlI#Y!sjw8<14Cg+joy&ST3WBblTlj;BpAUbA#ql%hXTLyYQ^Ad^N7-t57d@S^!Id*BBEb~P&c5QsTJsnks1+mHhHVyKEg$zy} z{xjw=S$j`$krRdmwb%@5nt!AJ{G?m0ZM5F|-FDizyj0gGYvRP(xfAtLZKG6PU8oB1 zLw+j0XObD7ee^o90Z5od9d9!QjnT8P{V`hQxxPod;0b3c=_dvCS>F-UR#TS$!fnY^hP&8fI`OE_xUGc@qRm^z{I=@4K(*&fqylw+-kH{;l?MqpoOCWWHgD)*_B z&$qLqw~Nrj^HQL+h^?g7%l@W=#20qHab`;87;*xN$1L#!EN~uU;W$sf;rlrOSrw2e z1sXDS3)`5Fmn!=HBz{0L@jbBw&Zdl!Wb81KYY+4%rqP0o1pQ2WbQLL6DT$fXPJ;c~ zVe8I_@{ATf7UnXnhxL7MJ`5Y#IVLh`>M1$4Qg~+DW;PaZCGbg151u`5V5B9zdNf|MK>%g!A9%l;H!?7UHwctg0n2IEIR2C2=o|(I$ z^8vca^Nwa2u7^oyJjwnR1NqZ``qS}E-x`3G{2cbu&o6*+2oK{}qdcRz1Hp@%p+E;Lu*mvW(O@mI1StEG>cwx6gx0ixgkMLMM zN>Q5ln=_E>b8OLgxUM@9Qmx+YQsY!(@$?c75-FdomCiSpPX1qiolNSL6@bBZrTt{` zR<87HT4HOkw28Oq=Z7Z<9V(J_A#4-mn`124@QNw-Y zvzhfZDD2^jK~234*uf$h0!netCHT}pjj@HpjT;yep)Peun&`-7AU4cMd1J7~u@r); z85xgYAt;CS0CvYb02g>jp=U?YN;aHhGANK4LO2jJ^7O)KI!^uu1o_inUlQou$s=qC0-d?GfS8E^rOM7E&<1giVmsiJ2OF^mm`HArE>OEG;jsEuX!= z`r6XcsY_=sUjAyo-0t@Gy5;U(*RH^S<$k?CSRUAC-QtQpklMu8V>}X11U8lxj&?cH zR0(PnJe}}j?7oR@#X)*LXr+Eg{BLP~h zra08tX4}&c?khLgOb3)H{~HcVzS##VWwDmI3wsyiShhF%Hu|h3_k@c*bU_kO*l0Mw z1uHZ}0DCnorb4-a|2+?$!Zx!Uu1V%gBBtBMlNP8`m;r@?=RpXdlwl_E!2-eOhtl+< z7f%Ub0L91hXh^iggshMTdTcji6HiCmCL39nZKj*Ch*Lhc>ezM2qs%5Q5M1DmBkB6s z$V7Tvb6-jYh=ICK8%!>R^%y3A9me&6lsQWH!WqNEXpk(#1cKtLcT)^>Fb62^Xqx9> zZ7B;m_V5KEIQD?-!DDL_?$(W^{vl!BpAUY%-~V~WLmB3X0Y?X(n4t$NE#y=Eu}~iH zRZ%;)xTt?ti_3qxx43n$#8xX`KJq9_@rW&UzV~byw0AGw>|tu6*NK8ogxlXm3g!2P z7}-tHLQ>El9UbB?g&luW4?FiyHM?)FuGMO%PL^xkrSi?C#_CGDe%K#$yVZU8SOo|< zeA2J)VJ%4eSg(fE&n-42i-brVh2xV*>?-BpCeTW`GN;lg8?iC-Bk89`hE}mrYC@$0 z7J`E_!tjK~3fviE+%qZslExZ#g;SFNIVdY?U&hlB19u5znavCb%ltuk*$3c76Yb2n z|F-EgY1- zGg8jTNoKBe%!o+fK(6P51~YW5d`)6S#}vpAf{rg4S3a8;NnsOU3W^2TYaWl2*vXS5 zrYfJo{t*c`R-0pi&6xwc080i1Pdpi8%Dlo#UN+-Y$HLVKkSJ*tnF4YdV^t zbp|2)nQw;1OM+O1T!%gwaPDOBi1-mUe^0fYY1qXWQj8N54q;(J|eVskU_b zVx!SK`=?8%8|xSEuP>in|L^;gecNt<7zb80=-O7d3h#sEL(uK^IZWcARl=1FweZqF z&A1!7pv09nI^`5N)wZjI$$diw_z2@gdbpit9GsCOP3Qz-v#n3dy>G!@%ACN#{! zQsG610ZTwm2S7bFA7ga@dL3#aP@df2DTa{xyUtg|0y0Gx5(OkRy@aQZm`~K{tgJ&Po*(^=NBm_}A8ydSA z3_CVRJ8|6chntDF308yl14a{`zP7knDZRFOvQk;7R4S#Vd#BvhQ-eW!1t4(HF4;l9 zU+s5W)wbPh_sfUfV-pXkwuHt!RDd8@5@j?`!4#PEJpgN^4h(gDo5Vhkfb#~R1bM;~ z>`=g$BY&ax001BWNkl2;g`M2K>C}z@8k% z3;v#m&huF=tvrCwz#6$WU@K#PlsGbWL7p-|7^1+rc+s{f8dDatbBmHG<7xsfQX`N~ zr8k=~`NxD7H#WK&tz(_H!;6h#D+BkMuzdcL;xmoqF+5iZeFl zIt`_#0ijYZdaxeBf#gF%U1Mh414%%O7tvAMTfy78gFdC~n_>xN-l{ zmmpMU*uC<{$nx&!Spvj7O>8ood2#4jZ?e!RmrIK$8@ErFURzr#?RD0NrV|CYcsQaxjn4*e$TxiD8)|`&*gmY;s5GEk5K! z9Swm?N&ElZ5g*@*^tKvdt@=<4p|%xO26&4ik~v1jR&5(Bd;rojm3E57N^+c99nB7G z9$OjwYsMZbqKV)-r#`j5lKNnKbbv!T?TqLV$p0uduq|L`QFvGe+y~ny(~uhOYft7W ztcUt>#?5RdIfw@AznC24YN~`)Q|`K;KwKVSYO3eN;LW{YBxQo5tC4}IXbjI?nK3-& zXe!2{?3ka;=^g3$h&|3&@f_e%T=3osxchGW11`^R60AKn}0AeCi+e2_dpwE>vWU&2576>8^c2GJ`fcQE>c+oh+_At3UFhHBt4@xyToJX?y z%jddI5M&(lZwMzg@Vriu?UtvPsj@jcydb{AJptOC9Iodso- z8ZwQ4oQ4xGrxIh0?vqyktMlFN%EHgO?b6C#zuJsjaeD<6$a1&d@AoU9IsRJ45ex0U zUD;oG4j@Q*lvFwj0Ytz^Tmy7^M$EmftJiN`zk2J|)vF&~zkc=Vb@*`S*7Y0L@78J*e;&xtePCB$`sJzEOqO=dje zKQQ?O;{dS(5a(k)7I0n?corLwDr!duMuN8{4jU7NHF>@RoX-W(0%|?L83kaL0Uv8W zF+WZ^W%@0wAeU)EBiJ9Hm}!(IjDqQmWIoDiBI2pR#E-ld9q05XCw5pg)w zAf>4Sj)pM+b??UeZ(n);{VP}Adj0LUfARk7zkKWcw|{-({a;_Xb;r$=jDG+6pRe5V zxe9|nE9QmK(8qrFE~Z~&c^6<<3}!R7c@Hi+PEO2tpsC|yL>>n*Z0A5p^B;yFhyT29 zlda23%a6v6855u+RIzd5aWU=1F4*sKW3jnY^sRPNpjWi@S_`(1ZQdJogao#y4y zb_z1f|LG>bAKEgGjXsUz2f-NH?MZ8;+qe76?S35)0~Azol5YExKJcr(`lLKKw!Bl= zYbF5QtYHhMAh@{{kN)`1_21vRe(TnUSK;;!{`(K_%x_med~H}2P;nV%Ky87Q%`7`8Q1-~CXGCN%r$Z1c;6;s5Kd_)mq!tmuWyUoLb%7!p zHywjONF7aM8F1HgIf-bjO@bkCcdjIt+Z@&*VbnD;!{??5f{vB8e@n=8qhB2VN6uCd-98Wt$W^oo$JYSED ziVRewW~P^LV5cJg;S?)%*w)vM;^EBa)KUX*M~{AIxf)?g^X#WHkiBxf4#-h%RTpraRLfe>;mfT_dD8Ef4i68XbStg> zuC15aU@ka$sxnj-Gk4s z{{A|e&42i?u#>`WKD=6B%&i-De$TGTdtbcA?tSf0j8RE54(T%wn_=iABPzlqZa1DJKMpu34PASa{BT3BNSLlf|E~+%ctr zfQ{`5tTyp+0ICo`%yWu4#u<*=bX5-AY8!-iq+eD-Tw;Y9V^KcFa&$fnKm6a`e(RT4 z-UcK1<=gN7{=?U=Pww2fvUTUmjjJEN{r=S}Z@vH4`~T+1a`5){TW`Pp)?2^)<*)Bt z-}>;zjXUrC?#3TIxK#E)>6AZj*Pr4N%^XgoqlVuq0RC13(c0pKtI&tnNu&qjiig00 zz3G_5&Sz_-wOYfgT~N2ZwR39?w$^%3zWpd?5#L(+?QkofrFQz0)@bi7RI2rr_I|xS zm`v(j9L0mZeYz`qwvL0{%H8_J4ysS~Y`5B78MIysWJ(D-VkBg|Z4@YoFk-hpzIEr` z)!%-7lCUsvXhQ1wd>DsrXhIUF2Bh-GTYr4##`w;S-`_%O`uNs6xBl(d?`(Z| z=N)$ay{)V7UA_9p{8+WR4dzJ%WAKeys|1WP{(&WjdT41#OvnRe{V*`vi4{1|X%jhq(jFx|`u zCW?Sz7?QBrOHhWBNqj!0STAhoNQc6|^5K;m_ddLF@0WM}2I zPLcv^i{Ib+FK=D>mm9x+|Hdyq{P4>455Y#Rzjfo6S6<(G``7e;*?Rr`>$BU()`RmS z98uuNbPQT0-JJa}12M+RqEDCbtfE9_j&^K9Xp|H6yOW?lu2nYHE`AOlPV)N2wN-oW z11b_abjD1V9$=n@_{mn|u)kk#9fB6GmfQ7mWua29W2)|6*|xir`hIs(=}smSi$@~+ zt=9hGWM$>WmT_9BK!BbjJ}A0r53FDKLCU=^BQYA^x$|!YXLh=sVP`)M;@u8WIL=2T z4fzG_87VZw^f>u7oANEG^__qy4uErOOJ4oMu_(|HlfXm6c!&-x`+@ru)I%ga#Z*ULbrZ>{mQ?KUO%=TPwNk` z-)W5PRib=qf3Sflu-BYuqOF6)zXE+1A-TA)wmMk7$X4$)8=p7(e_A-~Z?MMT^0L{6 zr9%}q;M(?n!v36x^=fOSJs9k@Dtm)vJTqSz?6=#PVtLqa*(#0&sjigv29xD(dw@f9 zk7v4vW;{c-OSKp&o+>W`F`~Ba-FoNxt*h5ReCPVsRY92DPQhd2zz1WtbyeeodUN2pT=L{~272e2M0r@(mw>w_g9n>%VyKL+Mfr z=ok<%F=2pbW)w8Vl<67p%VCuGf$s{fG^q2~lfp4h$m76|-oN6e7VP7#_g^Hd)4wy_ z{aX!0#KM(u<)!jxgwsR=(E=wxzOf^zq zkmTlg{7U@TU8L%uJ<4#a)~n@8wQVPRE7fYGXOz~vgQvXMA(tO4|AQmFjH1jw-Z9oU$E54pl zLgI{YhWO4ffSJ2o(3vMd6ZKN9;*dM`g%cPy{*l*1IDj665XPy46V+`jQHO|Bf_=<_ z={QSgX#!uwc?#V7co6JBQO8e-%%uQKP=M9pP)GdzU%Y=qUw`}8ASh_S7@h_RS0%32 z6jp^#;X&Mtdqzv1&>S3{VU|)EN`jr|SRi6P^Zuf|qU+)xj)6!Dl7asS24Vr6T}8$z zm}7=#GZs9QNj-US|D${5=HcpAW5t}@2lH5|B<%}PEgNs$U3#)w;Y)46L6K}9-;+OP ztB=3hK3GKsFl2v%@v3%z&-UwmFoS-5G8ydEfoOp$>2|BF!5#>ZwyjTIib!Ifksce) zJuZX>7C)7@uD|on);m`(+`4rY+b9AJ&WMzJic%%iQ-7K>SeiJLF|ae(c_bK8m*O~Y z556C=6e|*3oiS77@E+x^O(RS*Ob&41^z2`E5o7?)k;Y?B{r|MR&yO9)l`i-%c)^W{ z*%{zgg3nA{mK#=$)qwfjHr=oL>5 zi^FhOva?3pDVC{;Gp&7IQV2uQbL-(U129Ee4X&7;wui!B1bjY*M`@ifS^nAI{D&X@ zcsWxN);wlmyi#|t}%XNHT`xZ290YJnatoVDE7-}}KE;@-9N)|<61A0LHR?tS?F z{oAj8_^Ld9)xGxfvv;-hzH)l~pEmyHQMn7(IKB-GIXXJ}!9@vjxp(8tCQ9!63 z9Uq@k7vZ%pAD%vX^pu0lLd`orR5tCc10J+~(EkSY{WJA5K|N@5p%l4Syp>8X9{!<4 zIEhB+1+@1718S)Trog!=XaMC!<=D_t*Pbfl)~$CDu%m|Fr%O=8PR5H*>7`@$1Q962 zVcdDd9}ulfZ>tC;IG8)gRD-yvI@{Pmbf)4$jg@U>ZidGC%G&flQKNgE7pw6OM0e2* z4nLhFtxHdtZNpYTx(uoGIYGed^wjm71Tq|IYQYM^)BKoz{>z{J3ih~@J|}z7lw=Eg zbU1-t3H-fd9`=~&hMj&Rg{h4(g6Y=5I2}GZj)Oy_r>y!O#suV4Go7uwu@`-|`0`|WGy%~z^xf1W11v-hrj@YeUs z7ofgt_l@21hd&O{dUSkx>n=Ru-r3#L)7u+)x_9gBI`nzDdGpIhcgq_Oj&I%t?Yeh# zyA*)Q*DKe`f5-3Q-uuRN3ehJ@XLrdou5VX4&~~^v%3Y(yn1@-=%wAo)q=wNT7WL6o zUKmhi0t7@aX*4*0U}_SwjRz6>fySEodb)HNsU0Rb)8l}&&b@Rh!qcvqjvIzE0l$Df z0P(gNB-P{g~mg#4A+OTx{1}>8cygRP+ z-mMa$iP;q{$DGuNU&#-6BC)jx4wAFeV-J@zd{So5dudyLDOgiGjQ7;gUL=*GyqtrC z&=n<)ym($cKua;>-A6Hc%*m|p11KjbsLMKJNTEJo8`Ua zRA4V~{Cx%OAx&x)8tB|WyLJWuPl>7qLfzHdsLn?CwxuoSwsPegUEzqK~yil(gXOC}1lG>Ax%p7qdxK*S1g-kLY=+QNO=vVYzln z$?}_b&u-m2zIAr<*3I(e+41#L5V9w}{lENoLE*jQAWfYNh{e*{-ngIr^rt_)b9U!2 zPXh_q;Sg)^lU~iz9#W+vbR&xgjYA2E=b905Zdimhz3=wE*(qc3shQ9bPYO}(sgt)I z&(ZeZVL@(VTGgbnVp=p^ZA060zeoJN(L?cQImmYkyY5Gxdm zCnfwr7JV4;Tz~Q(|Lm`S_NzPAQ)w>c93wYE${~SS1rRZ%9XKyu5VRMdZZ&g|h1QDL zGRG<$#cJkU$YMPL$J6T(=5t=C`SS7_WF<}NGfh=t4UHGHRWQ}{S00$}eQ@XKUGv&6 ze*2pLaQygf|Muy>yxM+Re*XH;o4KLs?YnQj;MJ^D2JlKlDGc)yqq7I)-o0z5XP32AFiFYG^ zVnOj)yV%k1z3sBJSv1tnzUQF8z;k0qR|~=58;xsa2mbbCp44w$2Tp&pJ-*FBK6}!+ zg`oy$FZ9;m2`V8UeE8<|YoC1f#hrVWUwixEtDoLH`tsHJzK!+t?zN9U3(%`IAmk5A zx}7bdUK=-ZSNYIOF@`0kN^3{cRu=6 zk&O*z$1H*?t@Q?F;xxCAE>3clzUiqz4K?vC&D#Le5R>n18TD_?n$CT2S z*28FVb*ISs$)C_Tkmn8p#L_$y(Svj|$r}p>4A>Jg!sGj;vfUx@k+V=oZcWow(fpx3 za9(z+aIS{dou%x2*h#^CRpUSR+1j!nzcR%|2wSUfu2XqD5|l^(va zhFJJ$MX8lcCEBjFK%F)s`kVp7R zXMi3d@&xLryNO2Ui7xFRzFdYx5uNCuJWR72`aOP<9rwyqRj5>NhUL;-|I1wSUUCp4 z97|e4@3W39VZ`^o?>>6v`29D2`PN&Xz4lsu@6BJl8~^TI_v*bjZ<===F%XW@4(b~U z6e)PxnQC*I$IT020p*&aW0L}939d%`pxGgFY5i=~3Vy{@cnTIFsfylbgG(Mp)8a#!kRx^#zuSBaf)J8UqtBT@>3LL~# zD`KetMo9IIWh=$ZfDj?|g*us*G#4NJE+PO|$<@l@Tb)j&2hAydvj;xLp*$V`sDw(i zP`wxTb~uLTCCju@y5)zg#!Q!5#P?6;SRB918n|w)-a0^PV+RwoT!j1QI|o}ypYh0Y zu#)Q1$sSr~&1ci~xxgHQ+d=c&Xm*J!M5JXLmPx}aBH5!K8)tVpCU{+wc^8B`tQXhs zzR)OLE56e;FCe=K>)x}hSksQzPw(Hn`4`i>pWJ(ezkYgOicfF7`TqCkv@eH9hRF}E{qDxi+t-heuirSjvAM;3>+B4ua(4ScIX%5`eD~qmQMr9|cKz(e z8%Gby!!u}=r{r#MB8)>aEEyRZo3#D+|Kq1W#`CpJS61fB1iF4a#m)7B|BbYJYDe$RM`6z<73%6$32{*xAD6zE zKA)6MgE6JNJbkh1XzueQ6V+jeNvhQx&i?ezenGME2lb*EaIOS(c4+ zR^*2I2X)y;&=(%Gu^=N;tThwfxjD3W0NGg^09qnU@GDD8t<-*tJkfs#2MMyUu``q% z+}5I&zq;|GFHT=`AHMRN*Wdc(t)I(}@7VYM;{E3AwfDbh${T<8sVbZ}S<^mA?0)z6 zPk0FRlEpj6 zCD5JeLI3Q(g3ZDSicyfO)5$hPL^E%DAMq{+AKeIZK-CR$D9P#o{AngRSf_fn*T8a| z1?|AGARG_UDK~?~$#b$1i)p@78SiR$Ru-nY=H7&LgE&pJx8l9_wWvzzo5a zT60i8`PIK@W9mqKXZS{H5)QQnSyV0$Dj&R`oWt8Ulmji%Da5?A571Ip^$o;KsG!WP zBQfZDL|h9$S_40?5DDN{>N{uB@gQJp39g}_MBHa)x_<4Whwrt^|Ngu8-s-;pNqhA6 z{Xh8`e_g-v&O1k6j+NvQ3>=~0iKFnlU;qB+7Zq~Lu26+U!kZP@b9>@qLwR4}B;&NY z2vK&;JMZTzt`#I_VS|Fyr5R%&-cV&mg8RSw)+gWpIQ_`|)!Xk0|3z)iUjGene=u7q z3H|@}tH}CU4MU zbAO>r^-E*Oyhm^cdMKLr3FYahih&zSzt7+}%yQmx#W|xvnAPGN!Qu#!m%|gZF6ys} zEas-THp3{bV>HLBatUY3mD=}Y4=DhBB{tUkHY|;S$mP9)LrJF*2?xVHgq)bA@YOhS zi@##wfX8_f%aYC4lPM5)4162DNBFYI^Zt@XS5We{k6ZKe#BAYK%76Rc7=YSDwgeS3 z>p;$?-DZ!_o0zCJuuNir1Li=J<07vn&qjQUm{afE+S1rdvv&YgK&!t@hiS0Ah%Er$ zLA~@WY-LaW;#ivL-GH)-gx)(llMRDFUIbk-8*~u z;Oshl<>B4qa(w;a1KPuOjv(}}I20WY$_*{GBSY*U#MZzNlN*X*dacz-=rHgT5G%mCdyUXFLwFqi_ zSqE7`AcSi&h?ZQe??Gi{Q4 zkpKW707*naR6fhj)p&cfjkXq|zqnw@9ui>g=%w9QaGsXZ+x4Q83~^&VK&~L}4{&8` zJG&^oLdB|onIQ*(DZ4Q>KADrEWvpo+FR;wJpu1dXE@t$#4~@bD55^@$bq*~^R?k@d|-<4ngx_It-qAtE#TUtwv0B zp+(m+P<8+aI^(ksxrsmzNHVbYp&T@hEl5ISYwKfc#sBy5_usqs%Ju87hL3LlhQD%b zvTD++x63h3|Ce8uyGM^6UOziNyK(yP=+QB>$Jv*Z9N9Gb*?Uxf?c6@OeobwFK9?>5 zx*(gFpIsY+Mj=R^!gWfU(dJS z`fsn_RyW_gU+nd_KfZQ{rb<#+NS9Z#{HNcMr+FH8gFt~`)*C||q7z7#h}?Bu*~>uX zbrVjhXq-6o3E&NvR|ivNp-ltZ@me`yd>a*aZyvq+{>|&}-uqa5`Py&F$L|;Q`EK~~ z93tqF_e)^M`OVgs<>tN9Teoj~HSFhn!L4;pfz27{jE+MQg7Yol@10q^oOMe&(CktY zZqUArUmt6OAZbQR^IT(+7N(KF?6waIV3M85qk+842UiR$lRQM%;aFI0ji)xk@9ZCA zJ%~~VXrxvdKd^{LUD5bL2$C$7WR}WMXz`k=DzC$4k6b@_;e-Rf9ZdXAmmvTETSr^I z?ZoI#r?aw;toQiVbp}&!I*?kE4%Jet(kshBP~2`ToH6*2rMsKPRdk12BrvnAtT@Y!*S%>O_~ebxs>c5ts5-J+@u@1vWZ_y2{vo1WCp~v)6!T7Qkps!priMCX%+=~ByYX- z){R$wCwTs#w|x+wjqKIqFQ|^-<{Ok9A+Y%J`1Ho3AHs+kaNoD#8 zY%e!suAzf01W^>O8|Gdp+5czAQwMcAMD^5;vrac#&To&o)5MiF|nj>{_@|8>qV;5G3X*4AKs!$9qatPCXi`M!5)0Q`ly}`j+ku zrsvq>1vN;=xSeXv=5liU7r*$yo9^95!<%n^HdI!8n#J(x$LY>(_0HKRul)A-*0$wZ z3jS2a_V<7PyX~BS>h*ZjTIQY#Jn`8PvT6&$zALj|af0&2l=Mzd(B!%_S%>oAHA9uNSCjQPLcp<#R|l+&auVj*!G+E_b>p-=I(=|-_rWpk0(p4j zshv3i0k(2>H$Z|qC2cc04hz|(GJy+ip-92AS7Rx6ekpk}f!}Z{0R~t0GCA7(J(mWG zFla=prWVHLmQ{9W1iqV3S@lKlLTRBtQnBBuPSXR(8@vfJquD68pp`krpD&){X<>R%-yAPPS(!22Lc*~i3bSl@;1qpKPZcJ38LE&CVjXI@MG}dwmNZZb zCLZ?MSQ^-}XR7+-wQGO%!7q$l!CR_nd<8y}v-or@XAjTovF;WcpZMt3-Mja0y-}_m zm(xo*kSynnh##RIS~!5ore9bnv>_Fdh?aL(Ly0)be%DHSxqV`teP@I8_K@dZyE-gJ zxBw**CT^tEx15;rr$?x44#_MFb*&UHU_+aBOC9emQEf3cCTHuS{ZuhJ%Vt z0wlFMH&(NZk7n$cOTqzc2iD-k83a3%T2Q=QH>bh{^ytM3&FS1HMesq>SjwlDYVx$Y zv4sI_?-M@&qrJdE*1orX^NZ>Ldq5DeMm{~$cpjyjM6kM~ZkSGDHqy=T>uG|Nhswvv zS}JLE!=}F0S}5S$-oYOJ02-6!^qm|ei)oe{S)JcK`t934zhCZu?tVENVe3a@*n-2~ zy#o-3Dl;u?#@tvvOZPAZ;v1`IWv<);>Mjc)u`V9|?_yO3x?uF(A{!bATHz@zl|!g8 zweJS7%i6{U9=H^F|4SV@PSh7o7Lsxjny*%eL01^}Jas@Sa{z`=AwQ;5NO#2lG!t<5}xY zx3EVzc}5i|-FnUt-cYT9gY75Pmex$|IyQ5SSey@iQF3ObtKo%-FTG97Mfe5_TstB5 zHg-_qhbAaq_Kg7(e@e58@40NciR1Ds;c@K)pC z1^b-oc`u|vF7^w@{qo`W?|t#nyW?B$#27drgVkv4+d`e12wG zZm7nxr*fLw5riG)2$^ovP`fL~F2?e??c2pfoBmR9KC1zD)^h*Yg7C?ccw z`I%?H^RaMehtygNW>xv##9aa%QpWRD_G@F;or44yZbDe&S#%I62R;iGm{<&O41prX zlSSyrBB(N#o?Ed?&=VcbVejbLQeOg#oU_b1&X*UnJ87aUonH6=c4wNFf)IR(soa?f z_GQlMP4ffF`uUP13{{}g1?8yn)G=`0#r4FyVx{=b1Z9})OFCI&Fd=wYHPEb|lQbHq zw2SLA$LzmwEmk&qW!ilI^!}Si|LsrS_TT$adWA9${m(yaAHmht!|%QS!SzQ%_q)Ko zejIzY7ffPju{~V_!~hl+&Y)N}U~@Z#ei8;BkCbj*qtd$dk@G&E~KQt=lOh z?gz+QZI~{uTee|Vxd!QTILwtxl7>k-%4$hRhNJwu(qOVKfOaw*hYnQWAj+CE&3d&u zOkgPZDuBj-FVrPZVhPm>(b<3%e`lSpRiTY)pbd>M%(hLYHKEWPqJyXa32FL@t8c$IpT4i}moL8m>Mw7<`Ni$m|NX6xKL4dR zw0uks^4TQ2u}f!1h9GNL2Juxk)sS`NAOfG=ZWV2*tgpN#Hv&}+byPaFlikq>%k$VN zKfCkVvDT;We_p;&?lU7|fif%Ni%Yfe+W_}R<=Sa^aP#c=?t>doQmnKGWRo70vNi96W{@U%_!$ANoo=riAQ-L-?}5Bv+!$Wgg;o z-#^nX3aa&XEY6kB9`Q7F@uV#MOHV1j*iSe%L$kOB*4F}OoEsyu1HCKMf8O)q&=lDl z=0PxU8pPq*FDFdu9FBH9TDt08=~8atIK47Jyt63bJ|>(*1vGJmt}h~@bnRge`*^Rp zc*0dwN9ciOd99ZK7K8lk@MscZ@lI;JupP*P0XFZ&XBk|yAE6rNe9{L)p0Ou53-7PiV*LF6BNpGYg;*2Gh$RTQvELcW{cAE zw|V1%K>%jDZKstE(8MQhkhIl=jR+va0Zt1_cZz9X0}|aQ`85 zyOz-u$)=&wOx4kXd%>98Y50p%crJC~T8<(nLlevna(mtNDSL>Gu`f8|M!lSa#Bp0m zRlCw2Lc-|>lWUwX_qb0ZPV>)Sz1JAhXVa(nP&S)1e*4g;6{^DmF(bk%huBN?>{LSZ z#_^O(cUWkjchS(E8q7e;Rk!eUM6)4XBs_ES>^HZCfB(buS(-k4%ZoQZDW6<_-`{>a zz4ykWa`)z=N5>D#(dp(QcfVRBb$02FH`AD6rMzIS2iAJ9)T*<>dDpXwC!7L0U2q0# zHE@F&BRO0Gyjj~CEL(BO9h6JQe8Wp}DTj{Maw2jMh)9`gc1w#l?Wf}V?GH+d;&J6H zB>YW*ko|6)UwRG;HBZ6>8*$F*Yy&$EA>!L9N6ulX9KsUYXuW{ zvj*yL2qzEm)}o2WGA+#b_~SI`y0vos5r@)40{q_TmRRb{l>20B_cVDTNo zZx0~T=Du>NGsW*Eb(%WoK-_3n(t+1XRfFHxmit&yc?cE$N|S0y&8?O494{e8Xlzp* zMj^*4WhJF<5j+s95gaU(;~>&GWN`~OUD}A)60HYHQT_5Z^mJQ)0ZYHENIwZ-jynX% z9+5;r!+CC-=(=^cMg~F^D=KNLosxm2^qdL2noSLYF%gA2dO_plDjRw1EuQ*R&4UEQ z#43ko0lwqxfw0o7-1Bap3yxN2sNQZ^+UfXz1?ERE$R1xjmh$z*RiOdy$LAsh3Zz^= z27-L;AaNUIF^49B>3N8Pz4LaS#Owu6jK|#}ae#-TMj{2-F%08Q8m55W_@`Aof)`gT zwmJZU+}JN1Z(}a!{b6*s>8-k#^@+?JVr-W$X_xWgV2bE=oZ9pGrN321VX`z}M_ zHz`(&r7<08=Mc{Tj!)1dyUWzjqobU4l@i5`5ft;}se79FtM&1zq2$Y@3MlfTBE9dT zmBxWsG{)Ny z296mPmNLjxJtqS8v+sf!!7&AnK8*^9^`gwYTWq&diSh)q;^#TJG_Vwv?aa{d_K7s| zq-@@g6SuTVlP9BR)n?OEck}Y-Tzx=$oKH77ugH1?A#zsA<%!i)VW@$&QbOn7%5d_riVX*5x?s&x`!dtsVxqPnEz>0F z=K#~ksVkISK|HhOP(rtE`vX^C;LErO?Hi?3aBHgd(B@{w8x@ZDsxR`~9;z)s#-;Q! zw99iE;oxk!@v%dULZAY=g*M^2umoS15;!!mpb;AN+_}Ir!tK;9jeR0(x!sr{z|m!$ z5#Fm{sDW#+OZ)5u_3{UK0N?}8K~46s!q51XnmD(0H%2bR183jB9*v+StN822dKk=h zW)KSU4}ol|L78SJOxfxp9n_$LJcPRse#^fZ zyyaTsuu`3GfRLL`Ky{^`EUi}B$VQXQ%iU##Cc_(hrA(}o(1iuc&Qd|Htr%jT&_FXKb5M0^HD?IQ z(>QR~MNtokz{U7OV>5l$22Rip%*S1r5A+~xQ-PWRZ*oGwQj{KthJoI2a2!FYe5+O+ z4H!@4Q?8cGXJ>K5aBB4&!nB!eZUc^;YhG&hPentZho0QRP9zFrlZAFof*)^9f^$`t ztmrcKITF(r&|(g<8mk$Ckk*%$RA*YoGkdyjgh^r-9ET?@M&Tr+ZcgfJzwW!}BXlE> zMXR~$2WAD=iC=NG+%A$9$djsr>^Y~}xB$M!p!B62WHC;+7QO+FZU@;?`e`@K;16`` z$ovd<*{Ag+NZ=0u!nd%8hdnyrbg^Brv^6{DD#kVxI3P_4faNSr>eC4Vh0H#&v4(pF)T5NoIKU=^F!<|T?ZVEcJjz(zaGQ`Pl-h;mXp z83(zTZl>bYd4~9jJ0}O*;=lXWY0!*Tmc5R)x4rU)*~&PlO=RbnccA{o~Jva44U* z1mt86cBz69+x90LL=-M_wFuakmV9tU^EkUnH?UdK8gj%7s+PR4hfg&3GpZrVZWVHE zyaEi%m)NZUA?Tri6dtSejgbA6nhm&PFeY_A91zo(0gq(HB6e9L?aXD_>EOg9 zXgV@AlYpl<-d&Vg76oOXLF|j-DR`AYeGy7j2+r!osySIAf-z{3W<~kNm&l}VlDe>2 zID{&&bHF*|bMQNQDHbO1X^T*Zr}`}?b(@GfInP!-z{HU)AZmzvm1>x1K)Mc~OyxZ3 z(QjR)%(I!~z}G)?+|!jI&LhAVG+gzaEDb-5&<*ny*@}fAbU0Ug=}brcwk+n_(x4y8 zb*k*QB;vu23$tBgBsa$FNPQec6Qqj+HvoR#n86?ri*0>ZH&VMtrqr%Gzle)wHeSM6 zC@);JcaMX5=Sq(FCjBx)qs&PB!i+ zw@`(=D}Z!L_Q|%AOaet2+$4l z72Ao;%ok_~UrR^zgLprAZV=I)Sl7;oK^rEZHx?!JAZ^=N zDgg79rT(2}Dq$=Oq`kLmZzjG({LWG;+ma@?_~Z8c5rNdh9ghlk*Y^ADulxRKh8XONWqD<&j(i z{2)xpk>s6aEU~A@v`}LN$@ugV9LrZLhZr|TrY&93>VpJ5Ckw@**LklYEy{E30Y-ch zG9-gvcsMBPeXPdFOiP15X$p58mS)hk5{-LY^?snf!vJqM3B^MIPz8Std8s~{bOA$!nZ;(2Uk+yVCR zt1h*IAhe>Rd&TX8yKGG}sFIbAK%=0V?0dQku-?;56(LG$G9Bjoy8r+n07*naR2+ZP z*|S=m!r`8;x`NGzFb75*e71G%f=2+hC8&|E10n1#s!L-H+EV}vdc8$UZk!qy7mVl zVi4yy?Y=B_K}e$16uvrXsEkmmyn^xWLk7u(+{~6{NV#n#H!N%>RLc#GDf3VprhNo z^RAxp@>9ErEoXv{(b3(LqijfUG!9iIJ|}av!M-()c@Q*P!Ia%$*+~fQ*qIEhZm4!D z0zDROwh~GjAu3u)8?WIzvuulLdZi{wZ7LS;9C2?WqTo)8n|nuMw%C3Jt*4^2HkMt2 zY{+!?pogrpwb^xaaZPz3enkgSR*TG367$SyC9hrq$BpAISNkXU0oa1i-+o(c=yn`X z12kha_ut9H5vOzkG0B!G!>Yc8WR@DoaLtl#GJ*Y2%J@D_J@FA|k>l6d?k2;s-mj)z zax4L7;%cfeu$+~T?dTP(s$#7d*+F9z&WBzW)lOz#+%U`?Vu5n4Q{*8#3RnoR{-8Pr z&R$DeeZsvB<5J|B8P1Rou3mwyH0s3pAWVQ#DdB|tSvieQYO>h!soRX+R>CQ-RHJAP ze1#IHOi1QV_e9z%1f1CH4qvx5SW7#ozcprCN9vbHnngsVh7jd!nk%z}5*N$#zz{d^ zkCFzAht3rvluk_Ep5BJf_| zLo_s|J8LQ+E?(gX)lmq~t>(hJ69ibpsl8N5re_JdEUd04Pc5kf9AL=`Ho$Y<+p@sY zZU!>p^gyAl4#E&eki3J#KkYhEj|S_@EU!qhJX`VtB%WcIDO3eu(pVY{dzdR%=%Rfc z$sjxbtvw|R9$r0{4a+r^Ps6NzMGMbri|3(O8I9CTsS0>e#0ZPbB9lWox)o*k`c=0? z_X4BT4BiIk^R}KQ%XDR$qTD3Yyf3Pw>0yqt_cj;@a-lg1>^ijTGRWE1Ksu%@)mUUL z7GMHi6UwhbV**(*0hQ1>J)o=*ofWLNqZSMM29JH?GaM{#=?(iZHrtb+8Dr3~uK1$t<;z z0~ll{^5j6cAbUd)gn|9G`a!InE!zmQg=gCO)|FA@p($Nonl^6sDE#WYQM(}LnH8#< z@?zf6*!&q{yJ@<9D5~PFPYX>8ukfKe0GFx=qSI*8egtOEj0mgZYDa}0`v3+tQXwHN z>A~@#E$C)jvAbLFeHt=h1?gAWjm{P6TlJx<7_C7qR*Bwi3x{S3+FR+O zODB+lke{>ZC~!e}0nBN(f~8EucDJQZu51zdk$os9OFqdF>KPQi8t00`@$8`~Ue2nb zk{5CsYT27Xxww{;`qyCYtDfDQ4?s1VfqJqmC&2wtMgP)zltyZZA80->@WfI-t&ks20P$a4 zGg_CMh@+%MAX2#iKd4}#KSwD}r9B=$S4+F;R+wIk(m?`3gUpa`j!)ZF`vU*AEbm>Q zkf+Y=A*(CjJvfz(oC^^+;?{1fy`LHc#oi%^O^}Aw0rWa5*8>>LRAwc+4kCgNQRUL5 z5rm0{Xgs9>A@C&_fj17S7P6eyk$ABLzyr<3bJLVTZk1Z;2Y`3&!LT%fCJld{<9Y=L z0eH~RkF@na_!@EvYRm#mVr-IwP*ijPo-U{VzkYo|Wz1Lc0dWc%e}+ulu;P^ISW(_qJK4&Dl+}T+tptRS@sV zH92-3F`g#>H#Xayp%Iy_uLZ~(go2EFnw6tF?{V;o--j6d65IenoT;pYQ#*Pn$#=6g zD|cQab}VMlH0K7iq@65a9999Zbl%UYrz9&R_Oj@41Q!_HQugc$*VM2_Lzjvpja3{; zCNC9D0N_&wDXd1N0V@9Kc9X{wn8HQCGCu48gDc(s0}@xw*UHn?8sck-G8y=r-P^JH z${xl7$MY^j^#I@@&P_d21w4Q!#l3Ttvpk-U#4}aC8ltZrPiTO0+EIoowN&(nADC=q zYf$sfH8NWGpB+4_EKQm4aR(OVYM;Xh0c!H9DD{W8kGL9328BKh1zu}hvmoYCIXW+^ zWXXhP^#ffMSqPGqCZf?29Z=+8eH<;MB74#v&!F+%p>yw;oG;9#Ep0*rwqLw8B0i)6my>K;x`#Z8v>#Z| z-6fulX`-(1%o3F7+7)%xgfv?QmqVAsN!I-sNbXoyrBQFXr<|tH; z_fJSWgiXA!ftsrd9iCQ?G;7IFJ7LK+%?HlZr3MmJ!EOg1O_@|&Xet%hmY%}|sgO_L zFCo`?rc3N_5<$6N@V&zxGYxBmEC;U$QwzV$ZR|Ak4{&5^GDKoEeoLjfrB(N(qml?} z(xu^SkmdMP?qU=|pjg`YiJ8aCL?m7HAmqk66bDMf2(AP6_>Vx}~}T0m5~!t-FH0jN*qOm+mNpJ$pT;HyAj`GO9z zH6S?9nNVn8_QE3F3DU$Ka6?A5YqBfzHIy7@AWXVKuzafgiM(0FOK&JRB;w-Hon{mw{#872oDg=JARMl1HMl%88w*@gG#Fl4jp0DRir~DGSZ)BT)^tifBxu;6f6LsvHnl7kvPQq#@RHSwTl0 z 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 m8Do7xT%@G>8Dsr0000 void get_iterators (const Point_3& query, unsigned int k, FT neighbor_radius, - OutputIterator output, bool fallback_k_is_sphere_empty = true) const + OutputIterator output, bool fallback_k_if_sphere_empty = true) const { if (neighbor_radius != FT(0)) { @@ -133,16 +133,13 @@ public: catch (const Maximum_points_reached_exception&) { } - if (fallback_k_is_sphere_empty) - { - // Fallback, if less than 3 points are return, search for the 3 - // first points - if (nb < 3) - k = 3; - // Else, no need to search for K nearest neighbors - else + // Fallback, if less than 3 points are return, search for the 3 + // first points + if (fallback_k_if_sphere_empty && nb < 3) + k = 3; + // Else, no need to search for K nearest neighbors + else k = 0; - } } if (k != 0) diff --git a/Point_set_processing_3/include/CGAL/cluster_point_set.h b/Point_set_processing_3/include/CGAL/cluster_point_set.h index fd6e27afe27..6d25eb54d2c 100644 --- a/Point_set_processing_3/include/CGAL/cluster_point_set.h +++ b/Point_set_processing_3/include/CGAL/cluster_point_set.h @@ -196,7 +196,7 @@ std::size_t cluster_point_set (PointRange& points, neighbor_query.get_iterators (get (point_map, *current), 0, neighbor_radius, boost::make_function_output_iterator - ([&](const iterator& it) { todo.push(it); }), false); + ([&](const iterator& it) { todo.push(it); }), true); } diff --git a/Polyhedron/demo/Polyhedron/Plugins/Point_set/Point_set_clustering_plugin.cpp b/Polyhedron/demo/Polyhedron/Plugins/Point_set/Point_set_clustering_plugin.cpp index 17986cf4e8a..b4b11d6b1bd 100644 --- a/Polyhedron/demo/Polyhedron/Plugins/Point_set/Point_set_clustering_plugin.cpp +++ b/Polyhedron/demo/Polyhedron/Plugins/Point_set/Point_set_clustering_plugin.cpp @@ -193,7 +193,7 @@ void Polyhedron_demo_point_set_clustering_plugin::on_actionCluster_triggered() Point_set::Index iidx = *(colored->point_set()->insert (points->point(idx))); if (cluster_size[cluster_map[idx]] >= min_nb->value()) { - CGAL::Random rand(cluster_map[idx]); + CGAL::Random rand(cluster_map[idx] + 1); unsigned char r, g, b; r = static_cast(64 + rand.get_int(0, 192)); g = static_cast(64 + rand.get_int(0, 192)); From 5060fb8fb1524a48f06f2bb53471efa3416e1622 Mon Sep 17 00:00:00 2001 From: Jane Tournois Date: Tue, 17 Mar 2020 13:29:27 +0100 Subject: [PATCH 159/568] fix get_edge_info and protect corners --- .../internal/tetrahedral_remeshing_helpers.h | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/tetrahedral_remeshing_helpers.h b/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/tetrahedral_remeshing_helpers.h index ca701da6e7c..36c79eb2ff9 100644 --- a/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/tetrahedral_remeshing_helpers.h +++ b/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/tetrahedral_remeshing_helpers.h @@ -752,14 +752,18 @@ namespace Tetrahedral_remeshing const std::size_t nb_si_v1 = nb_incident_subdomains(v1, c3t3); if (nb_si_v0 > nb_si_v1) { - update_v1 = true; + if (!c3t3.is_in_complex(v1)) + update_v1 = true; } else if (nb_si_v1 > nb_si_v0) { - update_v0 = true; + if (!c3t3.is_in_complex(v0)) + update_v0 = true; } else { - update_v0 = true; - update_v1 = true; + if (!c3t3.is_in_complex(v0)) + update_v0 = true; + if (!c3t3.is_in_complex(v1)) + update_v1 = true; } } return; From 2645c1b47ab1adb607614c2a4792464d2879a5f7 Mon Sep 17 00:00:00 2001 From: Jane Tournois Date: Tue, 17 Mar 2020 15:37:06 +0100 Subject: [PATCH 160/568] fix is_boundary(edge) facets that have exactly one incident cell which is infinite are facets of the convex hull, not of the domain boundary --- .../internal/tetrahedral_remeshing_helpers.h | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/tetrahedral_remeshing_helpers.h b/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/tetrahedral_remeshing_helpers.h index 36c79eb2ff9..7f35514a02d 100644 --- a/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/tetrahedral_remeshing_helpers.h +++ b/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/tetrahedral_remeshing_helpers.h @@ -235,12 +235,8 @@ namespace Tetrahedral_remeshing else if (cell_selector(f.first) // XOR ^ cell_selector(f.first->neighbor(f.second))) return true; - else if (c3t3.triangulation().is_infinite(f) //XOR - ^ c3t3.triangulation().is_infinite(f.first->neighbor(f.second))) - return true; - ++fcirc; - } while (fcirc != fend); + } while (++fcirc != fend); return false; } From 09ad664cb0062bf626e5cc479555cffb63b9a818 Mon Sep 17 00:00:00 2001 From: Jane Tournois Date: Tue, 17 Mar 2020 15:58:10 +0100 Subject: [PATCH 161/568] computing circumradius of degenerate cell crashes, avoid it --- .../internal/compute_c3t3_statistics.h | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/compute_c3t3_statistics.h b/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/compute_c3t3_statistics.h index 24ea5574b04..4d6a92c438d 100644 --- a/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/compute_c3t3_statistics.h +++ b/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/compute_c3t3_statistics.h @@ -116,7 +116,14 @@ namespace internal const Point& p2 = point(cit->vertex(2)->point()); const Point& p3 = point(cit->vertex(3)->point()); double v = CGAL::abs(tr.tetrahedron(cit).volume()); - double circumradius = CGAL::sqrt(CGAL::squared_radius(p0, p1, p2, p3)); + if (v == 0.) + { + std::cout << "degenerate cell :\n\t"; + std::cout << p0 << "\n\t" << p1 << "\n\t" << p2 << "\n\t" << p3 << std::endl; + } + double circumradius = (v == 0.) + ? CGAL::sqrt(CGAL::squared_radius(p0, p1, p2)) + : CGAL::sqrt(CGAL::squared_radius(p0, p1, p2, p3)); //find shortest edge double edges[6]; From bd6c8c03e1f8c254d28651f0b885ecc2f443b2e0 Mon Sep 17 00:00:00 2001 From: Jane Tournois Date: Tue, 17 Mar 2020 15:58:38 +0100 Subject: [PATCH 162/568] add missing const --- .../internal/tetrahedral_remeshing_helpers.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/tetrahedral_remeshing_helpers.h b/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/tetrahedral_remeshing_helpers.h index 7f35514a02d..5d7bc9cb394 100644 --- a/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/tetrahedral_remeshing_helpers.h +++ b/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/tetrahedral_remeshing_helpers.h @@ -229,7 +229,7 @@ namespace Tetrahedral_remeshing do { - Facet f = *fcirc; + const Facet& f = *fcirc; if (c3t3.is_in_complex(f)) return true; else if (cell_selector(f.first) // XOR From 94ed9b6f34cf15960e6a09fb777759cf9240b878 Mon Sep 17 00:00:00 2001 From: Jane Tournois Date: Tue, 17 Mar 2020 16:11:32 +0100 Subject: [PATCH 163/568] simplify smoothing code is_feature_MAD is not needed anymore because it corresponds to the info stored in the c3t3 --- .../internal/smooth_vertices.h | 165 +++++------------- 1 file changed, 40 insertions(+), 125 deletions(-) diff --git a/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/smooth_vertices.h b/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/smooth_vertices.h index f5de15c7da2..bf63e383a70 100644 --- a/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/smooth_vertices.h +++ b/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/smooth_vertices.h @@ -258,64 +258,6 @@ namespace CGAL } } - template - bool is_feature_MAD(const typename C3t3::Edge& edge, - const VerticesSubdomainsMap& vertices_subdomain_indices, - const C3t3& c3t3) - { - return c3t3.is_in_complex(edge); - } - - template - bool is_feature_MAD(const typename C3t3::Vertex_handle vh0, - const typename C3t3::Vertex_handle vh1, - const VerticesSubdomainsMap& vertices_subdomain_indices, - const C3t3& c3t3) - { - typename C3t3::Cell_handle ch; - int i0, i1; - - if (c3t3.triangulation().is_edge(vh0, vh1, ch, i0, i1)) - { - typename C3t3::Edge edge(ch, i0, i1); - return is_feature_MAD(edge, vertices_subdomain_indices, c3t3); - } - - return false; - } - - template - bool is_feature_MAD(const typename C3t3::Vertex_handle vh, - const VerticesSubdomainsMap& vertices_subdomain_indices, - const C3t3& c3t3) - { - typedef typename C3t3::Vertex_handle Vertex_handle; - - const typename C3t3::Triangulation& triangulation = c3t3.triangulation(); - - if (vertices_subdomain_indices.at(vh).size() > 3) - { - std::vector neighbors; - triangulation.finite_incident_vertices(vh, std::back_inserter(neighbors)); - - int feature_count = 0; - for (Vertex_handle neighbor : neighbors) - { - if (is_feature_MAD(vh, neighbor, vertices_subdomain_indices, c3t3)) - { - feature_count++; - if (feature_count >= 3) { - return true; - } - } - } - } - else if (c3t3.number_of_corners() > 0 && c3t3.in_dimension(vh)) { - return c3t3.is_in_complex(vh); - } - return false; - } - template void smooth_vertices(C3T3& c3t3, const bool protect_boundaries, @@ -390,22 +332,22 @@ namespace CGAL //collect neighbors for (const Edge& e : tr.finite_edges()) { - const Vertex_handle vh0 = e.first->vertex(e.second); - const Vertex_handle vh1 = e.first->vertex(e.third); - - const std::size_t& i0 = vertex_id.at(vh0); - const std::size_t& i1 = vertex_id.at(vh1); - - if (is_feature_MAD(e, vertices_subdomain_indices, c3t3)) + if (c3t3.is_in_complex(e)) { - if (!is_feature_MAD(vh0, vertices_subdomain_indices, c3t3)) + const Vertex_handle vh0 = e.first->vertex(e.second); + const Vertex_handle vh1 = e.first->vertex(e.third); + + const std::size_t& i0 = vertex_id.at(vh0); + const std::size_t& i1 = vertex_id.at(vh1); + + if (!c3t3.is_in_complex(vh0)) neighbors[i0] = (std::max)(0, neighbors[i0]); - if (!is_feature_MAD(vh1, vertices_subdomain_indices, c3t3)) + if (!c3t3.is_in_complex(vh1)) neighbors[i1] = (std::max)(0, neighbors[i1]); bool update_v0 = false, update_v1 = false; - get_edge_info(e, update_v0, update_v1, c3t3, cell_selector); + if (update_v0) { const Point_3& p1 = point(vh1->point()); @@ -508,28 +450,32 @@ namespace CGAL /////////////// EDGES ON SURFACE, BUT NOT IN COMPLEX ////////////////// for (const Edge& e : tr.finite_edges()) { - const Vertex_handle vh0 = e.first->vertex(e.second); - const Vertex_handle vh1 = e.first->vertex(e.third); - - const std::size_t& i0 = vertex_id.at(vh0); - const std::size_t& i1 = vertex_id.at(vh1); - if (is_boundary(c3t3, e, cell_selector) && !c3t3.is_in_complex(e)) { - bool update_v0 = false, update_v1 = false; - if (!is_feature_MAD(vh0, vertices_subdomain_indices, c3t3)) + const Vertex_handle vh0 = e.first->vertex(e.second); + const Vertex_handle vh1 = e.first->vertex(e.third); + + const std::size_t& i0 = vertex_id.at(vh0); + const std::size_t& i1 = vertex_id.at(vh1); + + const bool on_feature_0 = is_on_feature(vh0); + const bool on_feature_1 = is_on_feature(vh1); + + if (!on_feature_0) neighbors[i0] = (std::max)(0, neighbors[i0]); - if (!is_feature_MAD(vh1, vertices_subdomain_indices, c3t3)) + if (!on_feature_1) neighbors[i1] = (std::max)(0, neighbors[i1]); + bool update_v0 = false, update_v1 = false; get_edge_info(e, update_v0, update_v1, c3t3, cell_selector); - if (update_v0) + + if (update_v0 && !on_feature_0) { const Point_3& p1 = point(vh1->point()); smoothed_positions[i0] = smoothed_positions[i0] + Vector_3(p1.x(), p1.y(), p1.z()); neighbors[i0]++; } - if (update_v1) + if (update_v1 && !on_feature_1) { const Point_3& p0 = point(vh0->point()); smoothed_positions[i1] = smoothed_positions[i1] + Vector_3(p0.x(), p0.y(), p0.z()); @@ -542,7 +488,7 @@ namespace CGAL { const std::size_t& vid = vertex_id.at(v); - if (neighbors[vid] > 1) + if (v->in_dimension() == 2 && neighbors[vid] > 1) { Vector_3 smoothed_position = smoothed_positions[vid] / static_cast(neighbors[vid]); const Vector_3 current_pos(CGAL::ORIGIN, point(v->point())); @@ -561,14 +507,12 @@ namespace CGAL current_pos, vertices_normals[v][si]); Vector_3 mls_projection; - if (project(si, normal_projection, mls_projection, subdomain_FMLS, subdomain_FMLS_indices) - /*|| project( si, smoothed_position, mls_projection )*/){ + if (project(si, normal_projection, mls_projection, subdomain_FMLS, subdomain_FMLS_indices)){ final_position = mls_projection; } else { final_position = smoothed_position; } - // std::cout << "MLS " << final_position[0] << " - " << final_position[1] << " : " << final_position[2] << std::endl; } #ifdef CGAL_TETRAHEDRAL_REMESHING_DEBUG @@ -577,24 +521,19 @@ namespace CGAL v->set_point(typename Tr::Point( final_position.x(), final_position.y(), final_position.z())); } - else if (neighbors[vid] > 0) + else if (v->in_dimension() == 2 && neighbors[vid] > 0) { - if (v->in_dimension() == 2) - { - const Surface_patch_index si = surface_patch_index(v, c3t3); + const Surface_patch_index si = surface_patch_index(v, c3t3); - const Vector_3 current_pos(CGAL::ORIGIN, point(v->point())); - Vector_3 mls_projection; - if (project(si, current_pos, mls_projection, subdomain_FMLS, subdomain_FMLS_indices) - /*|| project( si, smoothed_position, mls_projection )*/) - { - const typename Tr::Point new_pos(CGAL::ORIGIN + mls_projection); - v->set_point(new_pos); + const Vector_3 current_pos(CGAL::ORIGIN, point(v->point())); + Vector_3 mls_projection; + if (project(si, current_pos, mls_projection, subdomain_FMLS, subdomain_FMLS_indices)) { + const typename Tr::Point new_pos(CGAL::ORIGIN + mls_projection); + v->set_point(new_pos); #ifdef CGAL_TETRAHEDRAL_REMESHING_DEBUG - os_surf << "2 " << current_pos << " " << new_pos << std::endl; + os_surf << "2 " << current_pos << " " << new_pos << std::endl; #endif - } } } } @@ -639,41 +578,17 @@ namespace CGAL if (c3t3.in_dimension(v) == 3 && neighbors[vid] > 1) { #ifdef CGAL_TETRAHEDRAL_REMESHING_VERBOSE - ++nb_done; + ++nb_done; #endif #ifdef CGAL_TETRAHEDRAL_REMESHING_DEBUG - os_vol << "2 " << point(v->point()); + os_vol << "2 " << point(v->point()); #endif - const Vector_3 p = smoothed_positions[vid] / static_cast(neighbors[vid]); - v->set_point(typename Tr::Point(p.x(), p.y(), p.z())); + const Vector_3 p = smoothed_positions[vid] / static_cast(neighbors[vid]); + v->set_point(typename Tr::Point(p.x(), p.y(), p.z())); #ifdef CGAL_TETRAHEDRAL_REMESHING_DEBUG - os_vol << " " << point(v->point()) << std::endl; + os_vol << " " << point(v->point()) << std::endl; #endif - //Point_3 new_pos = CGAL::ORIGIN + smoothed_positions[vid] / neighbors[vid]; - //const Vector_3 move(point(v->point()), new_pos); - - //std::vector cells; - //tr.finite_incident_cells(v, std::back_inserter(cells)); - - //bool selected = true; - //for (const Cell_handle ci : cells) - //{ - // if (!cell_selector(ci)) - // { - // selected = false; - // break; - // } - //} - //if (!selected) - // continue; - - //double frac = 1.; - //while (frac > 0.05 /// 1/16 = 0.0625 - // && !check_inversion_and_move(v, frac * move, cells, tr)) - //{ - // frac = 0.5 * frac; - //} } } From cd69e12d814c5987d426180da7b82debb5cc547a Mon Sep 17 00:00:00 2001 From: Jane Tournois Date: Tue, 17 Mar 2020 16:37:07 +0100 Subject: [PATCH 164/568] replace clear+resize by assign --- .../internal/smooth_vertices.h | 14 ++++---------- .../include/CGAL/tetrahedral_remeshing.h | 4 ++-- 2 files changed, 6 insertions(+), 12 deletions(-) diff --git a/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/smooth_vertices.h b/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/smooth_vertices.h index bf63e383a70..b80153b2966 100644 --- a/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/smooth_vertices.h +++ b/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/smooth_vertices.h @@ -441,11 +441,8 @@ namespace CGAL } } - smoothed_positions.clear(); - smoothed_positions.resize(nbv, CGAL::NULL_VECTOR); - - neighbors.clear(); - neighbors.resize(nbv, -1); + smoothed_positions.assign(nbv, CGAL::NULL_VECTOR); + neighbors.assign(nbv, -1); /////////////// EDGES ON SURFACE, BUT NOT IN COMPLEX ////////////////// for (const Edge& e : tr.finite_edges()) @@ -540,11 +537,8 @@ namespace CGAL } //// end if(!protect_boundaries) - smoothed_positions.clear(); - smoothed_positions.resize(nbv, CGAL::NULL_VECTOR); - - neighbors.clear(); - neighbors.resize(nbv, 0); + smoothed_positions.assign(nbv, CGAL::NULL_VECTOR); + neighbors.assign(nbv, 0); ////////////// INTERNAL VERTICES /////////////////////// for (const Edge& e : tr.finite_edges()) diff --git a/Tetrahedral_remeshing/include/CGAL/tetrahedral_remeshing.h b/Tetrahedral_remeshing/include/CGAL/tetrahedral_remeshing.h index d467862b6da..6e036fc0222 100644 --- a/Tetrahedral_remeshing/include/CGAL/tetrahedral_remeshing.h +++ b/Tetrahedral_remeshing/include/CGAL/tetrahedral_remeshing.h @@ -228,7 +228,7 @@ namespace CGAL #endif // perform remeshing - std::size_t nb_extra_iterations = 3; + std::size_t nb_extra_iterations = 0;// 3; remesher.remesh(max_it, nb_extra_iterations); #ifdef CGAL_TETRAHEDRAL_REMESHING_DEBUG @@ -381,7 +381,7 @@ namespace CGAL #endif // perform remeshing - std::size_t nb_extra_iterations = 3; + std::size_t nb_extra_iterations = 0;// 3; remesher.remesh(max_it, nb_extra_iterations); #ifdef CGAL_TETRAHEDRAL_REMESHING_DEBUG From b8c9abd234af792af5240ddcec8c3f6862e4b895 Mon Sep 17 00:00:00 2001 From: Jane Tournois Date: Wed, 18 Mar 2020 08:19:48 +0100 Subject: [PATCH 165/568] check normals per patch with dump --- .../internal/smooth_vertices.h | 20 +++++++++++++++---- 1 file changed, 16 insertions(+), 4 deletions(-) diff --git a/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/smooth_vertices.h b/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/smooth_vertices.h index b80153b2966..56e6bd2ec19 100644 --- a/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/smooth_vertices.h +++ b/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/smooth_vertices.h @@ -92,7 +92,8 @@ namespace CGAL #ifdef CGAL_TETRAHEDRAL_REMESHING_DEBUG std::ofstream os("dump_normals.polylines.txt"); - std::ofstream osn("dump_normals_normalized.polylines.txt"); + boost::unordered_map > ons_map; #endif //normalize the computed normals @@ -101,7 +102,7 @@ namespace CGAL { //value type is map for (typename VertexNormalsMap::mapped_type::iterator it = vnm_it->second.begin(); - it != vnm_it->second.end(); ++it) + it != vnm_it->second.end(); ++it) { Vector_3& n = it->second; @@ -113,14 +114,25 @@ namespace CGAL CGAL::Tetrahedral_remeshing::normalize(n, c3t3.triangulation().geom_traits()); #ifdef CGAL_TETRAHEDRAL_REMESHING_DEBUG - osn << "2 " << p << " " << (p + n) << std::endl; + const Surface_patch_index si = it->first; + if (ons_map.find(si) == ons_map.end()) + ons_map[si] = std::vector(); + ons_map[si].push_back(typename Tr::Geom_traits::Segment_3(p, p+n)); #endif } } #ifdef CGAL_TETRAHEDRAL_REMESHING_DEBUG os.close(); - osn.close(); + for (auto& kv : ons_map) + { + std::ostringstream oss; + oss << "dump_normals_normalized_" << kv.first << ".polylines.txt"; + std::ofstream ons(oss.str()); + for(auto s : kv.second) + ons << "2 " << s.source() << " " << s.target() << std::endl; + ons.close(); + } #endif } From 8423de8b956ab50191752198f4f3f01a0cb44b12 Mon Sep 17 00:00:00 2001 From: Simon Giraudot Date: Wed, 18 Mar 2020 14:57:53 +0100 Subject: [PATCH 166/568] Slightly modify algo/structures to accept 2D points as well --- .../internal/Neighbor_query.h | 15 ++++- .../internal/bbox_diagonal.h | 59 +++++++++++++++++++ .../include/CGAL/cluster_point_set.h | 13 +--- 3 files changed, 73 insertions(+), 14 deletions(-) create mode 100644 Point_set_processing_3/include/CGAL/Point_set_processing_3/internal/bbox_diagonal.h diff --git a/Point_set_processing_3/include/CGAL/Point_set_processing_3/internal/Neighbor_query.h b/Point_set_processing_3/include/CGAL/Point_set_processing_3/internal/Neighbor_query.h index a5cb067a5a0..f5758b40c85 100644 --- a/Point_set_processing_3/include/CGAL/Point_set_processing_3/internal/Neighbor_query.h +++ b/Point_set_processing_3/include/CGAL/Point_set_processing_3/internal/Neighbor_query.h @@ -14,6 +14,7 @@ #include +#include #include #include #include @@ -39,7 +40,12 @@ public: typedef PointMap Point_map; typedef typename Kernel::FT FT; + typedef typename boost::property_traits::value_type Point; + + typedef typename Kernel::Point_2 Point_2; typedef typename Kernel::Point_3 Point_3; + + typedef std::is_same Is_2d; typedef typename Range_iterator_type::type input_iterator; typedef typename input_iterator::value_type value_type; @@ -64,7 +70,10 @@ public: } }; - typedef CGAL::Search_traits_3 Tree_traits_base; + typedef typename std::conditional, + CGAL::Search_traits_3 >::type Tree_traits_base; + typedef CGAL::Search_traits_adapter Tree_traits; typedef CGAL::Sliding_midpoint Splitter; typedef CGAL::Distance_adapter > Distance; @@ -102,7 +111,7 @@ public: PointMap point_map() const { return m_point_map; } template - void get_iterators (const Point_3& query, unsigned int k, FT neighbor_radius, + void get_iterators (const Point& query, unsigned int k, FT neighbor_radius, OutputIterator output, bool fallback_k_if_sphere_empty = true) const { if (neighbor_radius != FT(0)) @@ -163,7 +172,7 @@ public: } template - void get_points (const Point_3& query, unsigned int k, FT neighbor_radius, + void get_points (const Point& query, unsigned int k, FT neighbor_radius, OutputIterator output) const { return get_iterators(query, k, neighbor_radius, diff --git a/Point_set_processing_3/include/CGAL/Point_set_processing_3/internal/bbox_diagonal.h b/Point_set_processing_3/include/CGAL/Point_set_processing_3/internal/bbox_diagonal.h new file mode 100644 index 00000000000..5f02c1c91fc --- /dev/null +++ b/Point_set_processing_3/include/CGAL/Point_set_processing_3/internal/bbox_diagonal.h @@ -0,0 +1,59 @@ +// Copyright (c) 2020 GeometryFactory (France). +// All rights reserved. +// +// This file is part of CGAL (www.cgal.org). +// +// $URL$ +// $Id$ +// SPDX-License-Identifier: GPL-3.0-or-later OR LicenseRef-Commercial +// +// Author(s) : Simon Giraudot + +#ifndef CGAL_PSP_INTERNAL_BBOX_DIAGONAL_H +#define CGAL_PSP_INTERNAL_BBOX_DIAGONAL_H + +#include + +namespace CGAL +{ +namespace Point_set_processing_3 +{ +namespace internal +{ + +template +double bbox_diagonal (const PointRange& points, PointMap point_map, const typename Kernel::Point_2&) +{ + CGAL::Bbox_2 bbox = CGAL::bbox_2 (CGAL::make_transform_iterator_from_property_map (points.begin(), point_map), + CGAL::make_transform_iterator_from_property_map (points.end(), point_map)); + + return CGAL::approximate_sqrt + ((bbox.xmax() - bbox.xmin()) * (bbox.xmax() - bbox.xmin()) + + (bbox.ymax() - bbox.ymin()) * (bbox.ymax() - bbox.ymin())); +} + +template +double bbox_diagonal (const PointRange& points, PointMap point_map, const typename Kernel::Point_3&) +{ + CGAL::Bbox_3 bbox = CGAL::bbox_3 (CGAL::make_transform_iterator_from_property_map (points.begin(), point_map), + CGAL::make_transform_iterator_from_property_map (points.end(), point_map)); + + return CGAL::approximate_sqrt + ((bbox.xmax() - bbox.xmin()) * (bbox.xmax() - bbox.xmin()) + + (bbox.ymax() - bbox.ymin()) * (bbox.ymax() - bbox.ymin()) + + (bbox.zmax() - bbox.zmin()) * (bbox.zmax() - bbox.zmin())); +} + +template +double bbox_diagonal (const PointRange& points, PointMap point_map) +{ + typedef typename boost::property_traits::value_type Point; + return bbox_diagonal::Kernel> (points, point_map, Point()); +} + +} // namespace internal +} // namespace Point_set_processing_3 +} // namespace CGAL + + +#endif // CGAL_PSP_INTERNAL_BBOX_DIAGONAL_H diff --git a/Point_set_processing_3/include/CGAL/cluster_point_set.h b/Point_set_processing_3/include/CGAL/cluster_point_set.h index 6d25eb54d2c..c06979fe106 100644 --- a/Point_set_processing_3/include/CGAL/cluster_point_set.h +++ b/Point_set_processing_3/include/CGAL/cluster_point_set.h @@ -17,6 +17,7 @@ #include #include #include +#include #include #include @@ -136,8 +137,6 @@ std::size_t cluster_point_set (PointRange& points, typename Point_set_processing_3::GetAdjacencies::Empty>::value) callback_factor = 0.5; - typedef typename Kernel::Point_3 Point; - // types for K nearest neighbors search structure typedef Point_set_processing_3::internal::Neighbor_query Neighbor_query; @@ -148,15 +147,7 @@ std::size_t cluster_point_set (PointRange& points, // If no radius is given, init with 1% of bbox diagonal if (neighbor_radius < 0) - { - CGAL::Bbox_3 bbox = CGAL::bbox_3 (CGAL::make_transform_iterator_from_property_map (points.begin(), point_map), - CGAL::make_transform_iterator_from_property_map (points.end(), point_map)); - - neighbor_radius = 0.01 * CGAL::approximate_sqrt - ((bbox.xmax() - bbox.xmin()) * (bbox.xmax() - bbox.xmin()) - + (bbox.ymax() - bbox.ymin()) * (bbox.ymax() - bbox.ymin()) - + (bbox.zmax() - bbox.zmin()) * (bbox.zmax() - bbox.zmin())); - } + neighbor_radius = 0.01 * Point_set_processing_3::internal::bbox_diagonal (points, point_map); // Init cluster map with -1 for (const value_type& p : points) From 8ede983726de7fb0dbbff52a16907bc87bb735fb Mon Sep 17 00:00:00 2001 From: Jane Tournois Date: Thu, 19 Mar 2020 13:49:20 +0100 Subject: [PATCH 167/568] keep 1d complex valid throughout the collapse step --- .../internal/collapse_short_edges.h | 32 +++++++++++++++++++ 1 file changed, 32 insertions(+) diff --git a/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/collapse_short_edges.h b/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/collapse_short_edges.h index 6d36127e64f..049f2a7bd6e 100644 --- a/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/collapse_short_edges.h +++ b/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/collapse_short_edges.h @@ -736,6 +736,36 @@ namespace internal } } + // update complex edges + const std::array, 6> edges + = { 0,1, 0,2, 0,3, 1,2, 1,3, 2,3 }; //vertex indices in cells + const Vertex_handle vkept = vh0; + const Vertex_handle vdeleted = vh1; + for (const Cell_handle ch : cells_to_update) + { + for (const std::array& ei : edges) + { + Vertex_handle eiv0 = ch->vertex(ei[0]); + Vertex_handle eiv1 = ch->vertex(ei[1]); + if (eiv1 == vdeleted) //replace eiv1 by vkept + { + if (c3t3.is_in_complex(eiv0, eiv1)) + { + c3t3.add_to_complex(eiv0, vkept, c3t3.curve_index(eiv0, eiv1)); + c3t3.remove_from_complex(eiv0, eiv1); + } + } + else if (eiv0 == vdeleted) //replace eiv0 by vkept + { + if (c3t3.is_in_complex(eiv0, eiv1)) + { + c3t3.add_to_complex(vkept, eiv1, c3t3.curve_index(eiv0, eiv1)); + c3t3.remove_from_complex(eiv0, eiv1); + } + } + } + } + //Update the vertex before removing it for (const Cell_handle ch : cells_to_update) { @@ -763,8 +793,10 @@ namespace internal // Delete cells for (Cell_handle cell_to_remove : cells_to_remove) { + // remove cell if (cell_to_remove->subdomain_index() > 0) c3t3.remove_from_complex(cell_to_remove); + c3t3.triangulation().tds().delete_cell(cell_to_remove); } From 90653caddcbcfa90cad89652fb6eb216d90208fd Mon Sep 17 00:00:00 2001 From: Jane Tournois Date: Thu, 19 Mar 2020 16:10:24 +0100 Subject: [PATCH 168/568] fix smoothing! for each vertex : - on complex edges, collect incident complex edges - on surfaces, collect incident surface edges - inside volume, collect incident volume edges --- .../internal/smooth_vertices.h | 87 ++++++++----------- 1 file changed, 38 insertions(+), 49 deletions(-) diff --git a/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/smooth_vertices.h b/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/smooth_vertices.h index 56e6bd2ec19..b0b0cc5afc1 100644 --- a/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/smooth_vertices.h +++ b/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/smooth_vertices.h @@ -290,9 +290,8 @@ namespace CGAL #ifdef CGAL_TETRAHEDRAL_REMESHING_DEBUG std::ofstream os_surf("smooth_surfaces.polylines.txt"); + std::ofstream os_surf0("smooth_surfaces0.polylines.txt"); std::ofstream os_vol("smooth_volume.polylines.txt"); - std::ofstream os_mls("smooth_mls_projections.txt"); - std::ofstream os_normal("smooth_normal_projections.txt"); #endif #ifdef CGAL_TETRAHEDRAL_REMESHING_VERBOSE @@ -352,21 +351,21 @@ namespace CGAL const std::size_t& i0 = vertex_id.at(vh0); const std::size_t& i1 = vertex_id.at(vh1); + const bool on_feature_v0 = is_on_feature(vh0); + const bool on_feature_v1 = is_on_feature(vh1); + if (!c3t3.is_in_complex(vh0)) neighbors[i0] = (std::max)(0, neighbors[i0]); if (!c3t3.is_in_complex(vh1)) neighbors[i1] = (std::max)(0, neighbors[i1]); - bool update_v0 = false, update_v1 = false; - get_edge_info(e, update_v0, update_v1, c3t3, cell_selector); - - if (update_v0) + if (!c3t3.is_in_complex(vh0) && on_feature_v1) { const Point_3& p1 = point(vh1->point()); smoothed_positions[i0] = smoothed_positions[i0] + Vector_3(p1.x(), p1.y(), p1.z()); neighbors[i0]++; } - if (update_v1) + if (!c3t3.is_in_complex(vh1) && on_feature_v0) { const Point_3& p0 = point(vh0->point()); smoothed_positions[i1] = smoothed_positions[i1] + Vector_3(p0.x(), p0.y(), p0.z()); @@ -412,10 +411,9 @@ namespace CGAL #ifdef CGAL_TETRAHEDRAL_REMESHING_DEBUG os_surf << "2 " << current_pos << " " << final_position << std::endl, #endif - // move vertex - v->set_point(typename Tr::Point( - final_position.x(), final_position.y(), final_position.z())); - + // move vertex + v->set_point(typename Tr::Point( + final_position.x(), final_position.y(), final_position.z())); } else if (neighbors[vid] > 0) { @@ -447,9 +445,9 @@ namespace CGAL #ifdef CGAL_TETRAHEDRAL_REMESHING_DEBUG os_surf << "2 " << current_pos << " " << final_position << std::endl, #endif - // move vertex - v->set_point( - typename Tr::Point(final_position.x(), final_position.y(), final_position.z())); + // move vertex + v->set_point( + typename Tr::Point(final_position.x(), final_position.y(), final_position.z())); } } @@ -467,24 +465,21 @@ namespace CGAL const std::size_t& i0 = vertex_id.at(vh0); const std::size_t& i1 = vertex_id.at(vh1); - const bool on_feature_0 = is_on_feature(vh0); - const bool on_feature_1 = is_on_feature(vh1); + const bool on_feature_v0 = is_on_feature(vh0); + const bool on_feature_v1 = is_on_feature(vh1); - if (!on_feature_0) + if (!on_feature_v0) neighbors[i0] = (std::max)(0, neighbors[i0]); - if (!on_feature_1) + if (!on_feature_v1) neighbors[i1] = (std::max)(0, neighbors[i1]); - bool update_v0 = false, update_v1 = false; - get_edge_info(e, update_v0, update_v1, c3t3, cell_selector); - - if (update_v0 && !on_feature_0) + if (!on_feature_v0) { const Point_3& p1 = point(vh1->point()); smoothed_positions[i0] = smoothed_positions[i0] + Vector_3(p1.x(), p1.y(), p1.z()); neighbors[i0]++; } - if (update_v1 && !on_feature_1) + if (!on_feature_v1) { const Point_3& p0 = point(vh0->point()); smoothed_positions[i1] = smoothed_positions[i1] + Vector_3(p0.x(), p0.y(), p0.z()); @@ -495,44 +490,38 @@ namespace CGAL for (Vertex_handle v : tr.finite_vertex_handles()) { - const std::size_t& vid = vertex_id.at(v); + if (v->in_dimension() != 2) + continue; - if (v->in_dimension() == 2 && neighbors[vid] > 1) + const std::size_t& vid = vertex_id.at(v); + if (neighbors[vid] > 1) { Vector_3 smoothed_position = smoothed_positions[vid] / static_cast(neighbors[vid]); const Vector_3 current_pos(CGAL::ORIGIN, point(v->point())); Vector_3 final_position = CGAL::NULL_VECTOR; - if (v->in_dimension() == 3 && is_on_convex_hull(v, c3t3)) - { - final_position = project_on_tangent_plane( - smoothed_position, current_pos, vertices_normals[v][Surface_patch_index()]); - } - else { - const Surface_patch_index si = surface_patch_index(v, c3t3); - CGAL_assertion(si != Surface_patch_index()); + const Surface_patch_index si = surface_patch_index(v, c3t3); + CGAL_assertion(si != Surface_patch_index()); - Vector_3 normal_projection = project_on_tangent_plane(smoothed_position, - current_pos, - vertices_normals[v][si]); - Vector_3 mls_projection; - if (project(si, normal_projection, mls_projection, subdomain_FMLS, subdomain_FMLS_indices)){ - final_position = mls_projection; - } - else { - final_position = smoothed_position; - } - } + Vector_3 normal_projection = project_on_tangent_plane(smoothed_position, + current_pos, + vertices_normals[v][si]); + Vector_3 mls_projection; + if (project(si, normal_projection, mls_projection, subdomain_FMLS, subdomain_FMLS_indices)) + final_position = mls_projection; + else + final_position = smoothed_position; #ifdef CGAL_TETRAHEDRAL_REMESHING_DEBUG os_surf << "2 " << current_pos << " " << final_position << std::endl, #endif - v->set_point(typename Tr::Point( - final_position.x(), final_position.y(), final_position.z())); + v->set_point(typename Tr::Point( + final_position.x(), final_position.y(), final_position.z())); } - else if (v->in_dimension() == 2 && neighbors[vid] > 0) + else if (neighbors[vid] > 0) { const Surface_patch_index si = surface_patch_index(v, c3t3); + CGAL_assertion(si != Surface_patch_index()); const Vector_3 current_pos(CGAL::ORIGIN, point(v->point())); Vector_3 mls_projection; @@ -541,7 +530,7 @@ namespace CGAL v->set_point(new_pos); #ifdef CGAL_TETRAHEDRAL_REMESHING_DEBUG - os_surf << "2 " << current_pos << " " << new_pos << std::endl; + os_surf0 << "2 " << current_pos << " " << current_pos << std::endl; #endif } } @@ -550,7 +539,7 @@ namespace CGAL //// end if(!protect_boundaries) smoothed_positions.assign(nbv, CGAL::NULL_VECTOR); - neighbors.assign(nbv, 0); + neighbors.assign(nbv, -1); ////////////// INTERNAL VERTICES /////////////////////// for (const Edge& e : tr.finite_edges()) From 543ac2380554299dd3aca7ac9d01db38ba2ee583 Mon Sep 17 00:00:00 2001 From: Jane Tournois Date: Thu, 19 Mar 2020 16:15:31 +0100 Subject: [PATCH 169/568] protect add_to_complex(vertex) with a condition --- .../internal/tetrahedral_adaptive_remeshing_impl.h | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/tetrahedral_adaptive_remeshing_impl.h b/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/tetrahedral_adaptive_remeshing_impl.h index 89eb8ee7163..4e0b324fac0 100644 --- a/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/tetrahedral_adaptive_remeshing_impl.h +++ b/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/tetrahedral_adaptive_remeshing_impl.h @@ -438,7 +438,8 @@ private: if ( vit->in_dimension() == 0 || nb_incident_complex_edges(vit, m_c3t3) > 2) { - m_c3t3.add_to_complex(vit, ++corner_id); + if(!m_c3t3.is_in_complex(vit)) + m_c3t3.add_to_complex(vit, ++corner_id); if (vit->in_dimension() == -1 || vit->in_dimension() > 0) vit->set_dimension(0); From 62641ded1557b6dbbc8d3fd51d07d798f7f96ed9 Mon Sep 17 00:00:00 2001 From: Jane Tournois Date: Thu, 19 Mar 2020 16:16:51 +0100 Subject: [PATCH 170/568] simplify is_boundary(edge) --- .../internal/tetrahedral_remeshing_helpers.h | 14 +++++--------- 1 file changed, 5 insertions(+), 9 deletions(-) diff --git a/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/tetrahedral_remeshing_helpers.h b/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/tetrahedral_remeshing_helpers.h index 5d7bc9cb394..b94742f2f7d 100644 --- a/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/tetrahedral_remeshing_helpers.h +++ b/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/tetrahedral_remeshing_helpers.h @@ -225,18 +225,14 @@ namespace Tetrahedral_remeshing Facet_circulator fcirc = c3t3.triangulation().incident_facets(e); Facet_circulator fend = fcirc; - std::vector boundary_facets; do { const Facet& f = *fcirc; - if (c3t3.is_in_complex(f)) + if (is_boundary(c3t3, f, cell_selector)) return true; - else if (cell_selector(f.first) // XOR - ^ cell_selector(f.first->neighbor(f.second))) - return true; - - } while (++fcirc != fend); + } + while (++fcirc != fend); return false; } @@ -1179,8 +1175,8 @@ namespace Tetrahedral_remeshing { const typename C3T3::Edge& e = *eit; ofs << "2 " - << e.first->vertex(e.second)->point() << " " - << e.first->vertex(e.third)->point() << "\n"; + << point(e.first->vertex(e.second)->point()) << " " + << point(e.first->vertex(e.third)->point()) << "\n"; } ofs.close(); } From 0f7a0eac64275b9080c0badc7dc357f706c0c541 Mon Sep 17 00:00:00 2001 From: Jane Tournois Date: Thu, 19 Mar 2020 16:37:02 +0100 Subject: [PATCH 171/568] add missing ifdef macro --- .../internal/tetrahedral_adaptive_remeshing_impl.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/tetrahedral_adaptive_remeshing_impl.h b/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/tetrahedral_adaptive_remeshing_impl.h index 4e0b324fac0..325d2384ddc 100644 --- a/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/tetrahedral_adaptive_remeshing_impl.h +++ b/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/tetrahedral_adaptive_remeshing_impl.h @@ -401,7 +401,9 @@ private: { CGAL_assertion(m_c3t3.in_dimension(e.first->vertex(e.second)) <= 1); CGAL_assertion(m_c3t3.in_dimension(e.first->vertex(e.third)) <= 1); +#ifdef CGAL_TETRAHEDRAL_REMESHING_DEBUG ++nbe; +#endif continue; } From 3f6abd4ff7e4a8cbb7f81be35f5c2a3a9d67c9e6 Mon Sep 17 00:00:00 2001 From: Jane Tournois Date: Fri, 20 Mar 2020 06:37:38 +0100 Subject: [PATCH 172/568] fix smoothing of 3d vertices count neighbors from 0, not -1, because there is no pre-counting as it is done for surfaces --- .../CGAL/Tetrahedral_remeshing/internal/smooth_vertices.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/smooth_vertices.h b/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/smooth_vertices.h index b0b0cc5afc1..5b090db0afc 100644 --- a/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/smooth_vertices.h +++ b/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/smooth_vertices.h @@ -539,7 +539,7 @@ namespace CGAL //// end if(!protect_boundaries) smoothed_positions.assign(nbv, CGAL::NULL_VECTOR); - neighbors.assign(nbv, -1); + neighbors.assign(nbv, 0/*for dim 3 vertices, start counting directly from 0*/); ////////////// INTERNAL VERTICES /////////////////////// for (const Edge& e : tr.finite_edges()) From cee1b435e79a5dcbae9e6b322047067956e6597e Mon Sep 17 00:00:00 2001 From: Jane Tournois Date: Wed, 25 Mar 2020 07:55:12 +0100 Subject: [PATCH 173/568] not all edges should be update wrt the c3t3 --- .../Tetrahedral_remeshing/internal/collapse_short_edges.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/collapse_short_edges.h b/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/collapse_short_edges.h index 049f2a7bd6e..469e45c5dcf 100644 --- a/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/collapse_short_edges.h +++ b/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/collapse_short_edges.h @@ -747,7 +747,7 @@ namespace internal { Vertex_handle eiv0 = ch->vertex(ei[0]); Vertex_handle eiv1 = ch->vertex(ei[1]); - if (eiv1 == vdeleted) //replace eiv1 by vkept + if (eiv1 == vdeleted && eiv0 != vkept) //replace eiv1 by vkept { if (c3t3.is_in_complex(eiv0, eiv1)) { @@ -755,7 +755,7 @@ namespace internal c3t3.remove_from_complex(eiv0, eiv1); } } - else if (eiv0 == vdeleted) //replace eiv0 by vkept + else if (eiv0 == vdeleted && eiv1 != vkept) //replace eiv0 by vkept { if (c3t3.is_in_complex(eiv0, eiv1)) { From 66d3c1492f55e7f5340e66c780c42820425051fd Mon Sep 17 00:00:00 2001 From: Jane Tournois Date: Wed, 25 Mar 2020 13:33:27 +0100 Subject: [PATCH 174/568] compute consistently oriented normals on surface patches walk on facets with same surface patch index, with no "crossing" of complex edges, and a normal that evolves while walking to keep a smooth transition between neighbor facets --- .../internal/smooth_vertices.h | 177 ++++++++++++++---- 1 file changed, 145 insertions(+), 32 deletions(-) diff --git a/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/smooth_vertices.h b/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/smooth_vertices.h index 5b090db0afc..b06872fcd17 100644 --- a/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/smooth_vertices.h +++ b/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/smooth_vertices.h @@ -31,17 +31,99 @@ namespace CGAL return gi + (normal * diff) * normal; } - template + template + bool find_adjacent_facet_on_surface(const typename C3t3::Facet& f, + const typename C3t3::Edge& edge, + typename C3t3::Facet& neighbor, + const C3t3& c3t3, + const CellSelector& cell_selector) + { + CGAL_assertion(is_boundary(c3t3, f, cell_selector)); + + typedef typename C3t3::Facet Facet; + typedef typename C3t3::Triangulation::Facet_circulator Facet_circulator; + + if (c3t3.is_in_complex(edge)) + return false; //do not "cross" complex edges + //they are likely to be sharp and not to follow the > 0 dot product criterion + + const typename C3t3::Surface_patch_index& patch = c3t3.surface_patch_index(f); + const typename C3t3::Facet& mf = c3t3.triangulation().mirror_facet(f); + + Facet_circulator fcirc = c3t3.triangulation().incident_facets(edge); + Facet_circulator fend = fcirc; + do + { + const Facet fi = *fcirc; + if ( f != fi + && mf != fi + && is_boundary(c3t3, fi, cell_selector) + && patch == c3t3.surface_patch_index(fi)) + { + neighbor = fi; + return true; + } + } while (++fcirc != fend); + + return false; + } + + template + void compute_neighbors_normals(const typename C3t3::Facet& f, + const typename FacetNormalsMap::mapped_type& reference_normal, + FacetNormalsMap& fnormals, + const C3t3& c3t3, + const CellSelector& cell_selector) + { + typedef typename C3t3::Triangulation Tr; + typedef typename C3t3::Facet Facet; + typedef typename C3t3::Edge Edge; + typedef typename FacetNormalsMap::mapped_type Vector_3; + + typename Tr::Geom_traits::Construct_opposite_vector_3 + opp = c3t3.triangulation().geom_traits().construct_opposite_vector_3_object(); + typename Tr::Geom_traits::Compute_scalar_product_3 + scalar_product = c3t3.triangulation().geom_traits().compute_scalar_product_3_object(); + + if ( fnormals.find(f) != fnormals.end() + || fnormals.find(c3t3.triangulation().mirror_facet(f)) != fnormals.end()) + return; + + Vector_3 n = CGAL::Tetrahedral_remeshing::normal(f, c3t3.triangulation().geom_traits()); + if (scalar_product(n, reference_normal) < 0.) + n = opp(n); + fnormals[f] = n; + + // update complex edges + const typename C3t3::Cell_handle ch = f.first; + const std::array, 3> edges + = { (f.second + 1) % 4, (f.second + 2) % 4, //edge 1-2 + (f.second + 2) % 4, (f.second + 3) % 4, //edge 2-3 + (f.second + 3) % 4, (f.second + 1) % 4 //edge 3-1 + }; //vertex indices in cells + + for (const std::array& ei : edges) + { + Facet neighbor; + Edge edge(ch, ei[0], ei[1]); + if (find_adjacent_facet_on_surface(f, edge, neighbor, c3t3, cell_selector)) + compute_neighbors_normals(neighbor, n, fnormals, c3t3, cell_selector); + } + } + + template void compute_vertices_normals(const C3t3& c3t3, - VertexNormalsMap& normals_map) + VertexNormalsMap& normals_map, + const CellSelector& cell_selector) { typedef typename C3t3::Triangulation Tr; typedef typename C3t3::Cell_handle Cell_handle; typedef typename C3t3::Vertex_handle Vertex_handle; typedef typename C3t3::Subdomain_index Subdomain_index; typedef typename C3t3::Surface_patch_index Surface_patch_index; - typedef typename Tr::Finite_facets_iterator Finite_facets_iterator; + typedef typename Tr::Facet_circulator Facet_circulator; typedef typename Tr::Facet Facet; + typedef typename Tr::Edge Edge; typedef typename Tr::Geom_traits::Vector_3 Vector_3; typename Tr::Geom_traits::Construct_opposite_vector_3 @@ -51,46 +133,77 @@ namespace CGAL const Tr& tr = c3t3.triangulation(); +#ifdef CGAL_TETRAHEDRAL_REMESHING_DEBUG + std::ofstream os1("dump_start_facets.polylines.txt"); +#endif + //collect all normals + boost::unordered_map fnormals; for (const Facet& f : tr.finite_facets()) { - if (c3t3.is_in_complex(f)) + if (fnormals.size() == tr.number_of_finite_facets()) + break; + CGAL_assertion(fnormals.size() < tr.number_of_finite_facets()); + + if (!is_boundary(c3t3, f, cell_selector)) + continue; + + const Facet& mf = tr.mirror_facet(f); + if ( fnormals.find(f) != fnormals.end() + || fnormals.find(mf) != fnormals.end()) + continue;// already computed + +#ifdef CGAL_TETRAHEDRAL_REMESHING_DEBUG + os1 << "4 " << point(f.first->vertex((f.second + 1) % 4)->point()) + << " " << point(f.first->vertex((f.second + 2) % 4)->point()) + << " " << point(f.first->vertex((f.second + 3) % 4)->point()) + << " " << point(f.first->vertex((f.second + 1) % 4)->point()) << std::endl; +#endif + + Vector_3 ref = CGAL::Tetrahedral_remeshing::normal(f, tr.geom_traits()); + if ( c3t3.triangulation().is_infinite(f.first) + || c3t3.subdomain_index(f.first) < c3t3.subdomain_index(mf.first)) + ref = opp(ref); + + compute_neighbors_normals(f, ref, fnormals, c3t3, cell_selector); + } + +#ifdef CGAL_TETRAHEDRAL_REMESHING_DEBUG + os1.close(); + std::ofstream osf("dump_facet_normals.polylines.txt"); +#endif + for (const auto& fn : fnormals) + { + const Facet& f = fn.first; + const Vector_3& n = fn.second; + +#ifdef CGAL_TETRAHEDRAL_REMESHING_DEBUG + typename Tr::Geom_traits::Point_3 fc + = CGAL::centroid(point(f.first->vertex(indices(f.second, 0))->point()), + point(f.first->vertex(indices(f.second, 1))->point()), + point(f.first->vertex(indices(f.second, 2))->point())); + osf << "2 " << fc << " " << (fc + n) << std::endl; +#endif + const Surface_patch_index& surf_i = c3t3.surface_patch_index(f); + + for (int i = 0; i < 3; ++i) { - const Cell_handle ch = f.first; - const Cell_handle n_ch = f.first->neighbor(f.second); + const Vertex_handle vi = f.first->vertex(indices(f.second, i)); + typename VertexNormalsMap::iterator patch_vector_it = normals_map.find(vi); - const Subdomain_index si = ch->subdomain_index(); - const Subdomain_index si_mirror = n_ch->subdomain_index(); - - const Surface_patch_index surf_i = c3t3.surface_patch_index(f); - - Vector_3 n = CGAL::Tetrahedral_remeshing::normal(f, tr.geom_traits()); - - if (si < si_mirror || tr.is_infinite(ch)) // todo : fix this condition - n = opp(n); - else if (si == si_mirror) + if (patch_vector_it == normals_map.end() + || patch_vector_it->second.find(surf_i) == patch_vector_it->second.end()) { - std::cout << "TODO : Check normal when subdomain is the same on both sides" << std::endl; + normals_map[vi][surf_i] = n; } - - for (int i = 0; i < 3; ++i) + else { - const Vertex_handle vi = f.first->vertex(indices(f.second, i)); - typename VertexNormalsMap::iterator patch_vector_it = normals_map.find(vi); - - if (patch_vector_it == normals_map.end() - || patch_vector_it->second.find(surf_i) == patch_vector_it->second.end()) - { - normals_map[vi][surf_i] = n; - } - else - { - normals_map[vi][surf_i] += n; - } + normals_map[vi][surf_i] += n; } } } #ifdef CGAL_TETRAHEDRAL_REMESHING_DEBUG + osf.close(); std::ofstream os("dump_normals.polylines.txt"); boost::unordered_map > ons_map; @@ -313,7 +426,7 @@ namespace CGAL //collect a map of normals at surface vertices boost::unordered_map > vertices_normals; - compute_vertices_normals(c3t3, vertices_normals); + compute_vertices_normals(c3t3, vertices_normals, cell_selector); // Build MLS Surfaces std::vector < CGAL::Tetrahedral_remeshing::internal::FMLS > subdomain_FMLS; From 6bcb145163fb47ea1babca0dbcb3998556471d2d Mon Sep 17 00:00:00 2001 From: Jane Tournois Date: Thu, 26 Mar 2020 13:23:11 +0100 Subject: [PATCH 175/568] speedup computation of facet normals just counting the number of normals to be computed is 50 times faster than testing find(f) and find(mf) successfully a lot of times this is a first shot and can definitely be improved a lot --- .../internal/smooth_vertices.h | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/smooth_vertices.h b/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/smooth_vertices.h index b06872fcd17..f1544822c81 100644 --- a/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/smooth_vertices.h +++ b/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/smooth_vertices.h @@ -136,13 +136,21 @@ namespace CGAL #ifdef CGAL_TETRAHEDRAL_REMESHING_DEBUG std::ofstream os1("dump_start_facets.polylines.txt"); #endif - //collect all normals + + std::size_t nb_of_boundary_facets = 0; + for (const Facet& f : tr.finite_facets()) + { + if (is_boundary(c3t3, f, cell_selector)) + ++nb_of_boundary_facets; + } + + //collect all facet normals boost::unordered_map fnormals; for (const Facet& f : tr.finite_facets()) { - if (fnormals.size() == tr.number_of_finite_facets()) + if (fnormals.size() == nb_of_boundary_facets) break; - CGAL_assertion(fnormals.size() < tr.number_of_finite_facets()); + CGAL_assertion(fnormals.size() < nb_of_boundary_facets); if (!is_boundary(c3t3, f, cell_selector)) continue; From b6c00b74b962d4922d51bc6a289e1244c53398dd Mon Sep 17 00:00:00 2001 From: Jane Tournois Date: Thu, 26 Mar 2020 13:31:05 +0100 Subject: [PATCH 176/568] use boost::optional instead of returning a boolean and a facet if boolean is true --- .../internal/smooth_vertices.h | 24 +++++++++---------- 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/smooth_vertices.h b/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/smooth_vertices.h index f1544822c81..d2b72d25742 100644 --- a/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/smooth_vertices.h +++ b/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/smooth_vertices.h @@ -11,6 +11,7 @@ #include #include +#include #include #include @@ -32,11 +33,11 @@ namespace CGAL } template - bool find_adjacent_facet_on_surface(const typename C3t3::Facet& f, - const typename C3t3::Edge& edge, - typename C3t3::Facet& neighbor, - const C3t3& c3t3, - const CellSelector& cell_selector) + boost::optional + find_adjacent_facet_on_surface(const typename C3t3::Facet& f, + const typename C3t3::Edge& edge, + const C3t3& c3t3, + const CellSelector& cell_selector) { CGAL_assertion(is_boundary(c3t3, f, cell_selector)); @@ -44,7 +45,7 @@ namespace CGAL typedef typename C3t3::Triangulation::Facet_circulator Facet_circulator; if (c3t3.is_in_complex(edge)) - return false; //do not "cross" complex edges + return {}; //do not "cross" complex edges //they are likely to be sharp and not to follow the > 0 dot product criterion const typename C3t3::Surface_patch_index& patch = c3t3.surface_patch_index(f); @@ -60,12 +61,11 @@ namespace CGAL && is_boundary(c3t3, fi, cell_selector) && patch == c3t3.surface_patch_index(fi)) { - neighbor = fi; - return true; + return fi; } } while (++fcirc != fend); - return false; + return {}; } template @@ -104,10 +104,10 @@ namespace CGAL for (const std::array& ei : edges) { - Facet neighbor; Edge edge(ch, ei[0], ei[1]); - if (find_adjacent_facet_on_surface(f, edge, neighbor, c3t3, cell_selector)) - compute_neighbors_normals(neighbor, n, fnormals, c3t3, cell_selector); + if (boost::optional neighbor + = find_adjacent_facet_on_surface(f, edge, c3t3, cell_selector)) + compute_neighbors_normals(*neighbor, n, fnormals, c3t3, cell_selector); } } From 91f1b1e7dd1968fc0bd727713044d76045199be4 Mon Sep 17 00:00:00 2001 From: Jane Tournois Date: Thu, 26 Mar 2020 13:43:17 +0100 Subject: [PATCH 177/568] remove debug code --- .../internal/smooth_vertices.h | 14 ++------------ 1 file changed, 2 insertions(+), 12 deletions(-) diff --git a/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/smooth_vertices.h b/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/smooth_vertices.h index d2b72d25742..acf6b5888ad 100644 --- a/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/smooth_vertices.h +++ b/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/smooth_vertices.h @@ -133,10 +133,6 @@ namespace CGAL const Tr& tr = c3t3.triangulation(); -#ifdef CGAL_TETRAHEDRAL_REMESHING_DEBUG - std::ofstream os1("dump_start_facets.polylines.txt"); -#endif - std::size_t nb_of_boundary_facets = 0; for (const Facet& f : tr.finite_facets()) { @@ -158,14 +154,9 @@ namespace CGAL const Facet& mf = tr.mirror_facet(f); if ( fnormals.find(f) != fnormals.end() || fnormals.find(mf) != fnormals.end()) + { continue;// already computed - -#ifdef CGAL_TETRAHEDRAL_REMESHING_DEBUG - os1 << "4 " << point(f.first->vertex((f.second + 1) % 4)->point()) - << " " << point(f.first->vertex((f.second + 2) % 4)->point()) - << " " << point(f.first->vertex((f.second + 3) % 4)->point()) - << " " << point(f.first->vertex((f.second + 1) % 4)->point()) << std::endl; -#endif + } Vector_3 ref = CGAL::Tetrahedral_remeshing::normal(f, tr.geom_traits()); if ( c3t3.triangulation().is_infinite(f.first) @@ -176,7 +167,6 @@ namespace CGAL } #ifdef CGAL_TETRAHEDRAL_REMESHING_DEBUG - os1.close(); std::ofstream osf("dump_facet_normals.polylines.txt"); #endif for (const auto& fn : fnormals) From cde5ec9e4827b0f03b8d7fb357a848272685bb88 Mon Sep 17 00:00:00 2001 From: Jane Tournois Date: Thu, 26 Mar 2020 15:34:11 +0100 Subject: [PATCH 178/568] speedup normals computation this new solution avoids all the calls to map.find(facet) first fill a map with boundary facets and NULL_VECTOR the associated normal facets are made canonical (with comparison of their 2 incident cells) to make sure we always consider the same facet --- .../internal/smooth_vertices.h | 43 ++++++++----------- .../internal/tetrahedral_remeshing_helpers.h | 9 ++++ 2 files changed, 27 insertions(+), 25 deletions(-) diff --git a/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/smooth_vertices.h b/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/smooth_vertices.h index acf6b5888ad..c32f77e37ad 100644 --- a/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/smooth_vertices.h +++ b/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/smooth_vertices.h @@ -61,7 +61,7 @@ namespace CGAL && is_boundary(c3t3, fi, cell_selector) && patch == c3t3.surface_patch_index(fi)) { - return fi; + return canonical_facet(fi); //"canonical" is important } } while (++fcirc != fend); @@ -85,8 +85,9 @@ namespace CGAL typename Tr::Geom_traits::Compute_scalar_product_3 scalar_product = c3t3.triangulation().geom_traits().compute_scalar_product_3_object(); - if ( fnormals.find(f) != fnormals.end() - || fnormals.find(c3t3.triangulation().mirror_facet(f)) != fnormals.end()) + CGAL_assertion(is_boundary(c3t3, f, cell_selector)); + + if (fnormals[f] != CGAL::NULL_VECTOR) return; Vector_3 n = CGAL::Tetrahedral_remeshing::normal(f, c3t3.triangulation().geom_traits()); @@ -117,13 +118,9 @@ namespace CGAL const CellSelector& cell_selector) { typedef typename C3t3::Triangulation Tr; - typedef typename C3t3::Cell_handle Cell_handle; typedef typename C3t3::Vertex_handle Vertex_handle; - typedef typename C3t3::Subdomain_index Subdomain_index; typedef typename C3t3::Surface_patch_index Surface_patch_index; - typedef typename Tr::Facet_circulator Facet_circulator; typedef typename Tr::Facet Facet; - typedef typename Tr::Edge Edge; typedef typename Tr::Geom_traits::Vector_3 Vector_3; typename Tr::Geom_traits::Construct_opposite_vector_3 @@ -133,30 +130,26 @@ namespace CGAL const Tr& tr = c3t3.triangulation(); - std::size_t nb_of_boundary_facets = 0; - for (const Facet& f : tr.finite_facets()) - { - if (is_boundary(c3t3, f, cell_selector)) - ++nb_of_boundary_facets; - } - //collect all facet normals boost::unordered_map fnormals; for (const Facet& f : tr.finite_facets()) { - if (fnormals.size() == nb_of_boundary_facets) - break; - CGAL_assertion(fnormals.size() < nb_of_boundary_facets); - - if (!is_boundary(c3t3, f, cell_selector)) - continue; - - const Facet& mf = tr.mirror_facet(f); - if ( fnormals.find(f) != fnormals.end() - || fnormals.find(mf) != fnormals.end()) + if (is_boundary(c3t3, f, cell_selector)) { - continue;// already computed + const Facet cf = canonical_facet(f); + fnormals[cf] = CGAL::NULL_VECTOR; } + } + + for (const auto& fn : fnormals) + { + const Vector_3& n = fn.second; + if (n != CGAL::NULL_VECTOR) + continue; //already computed + + const Facet& f = fn.first; + const Facet& mf = tr.mirror_facet(f); + CGAL_assertion(is_boundary(c3t3, f, cell_selector)); Vector_3 ref = CGAL::Tetrahedral_remeshing::normal(f, tr.geom_traits()); if ( c3t3.triangulation().is_infinite(f.first) diff --git a/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/tetrahedral_remeshing_helpers.h b/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/tetrahedral_remeshing_helpers.h index b94742f2f7d..fa6ba03f8a9 100644 --- a/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/tetrahedral_remeshing_helpers.h +++ b/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/tetrahedral_remeshing_helpers.h @@ -178,6 +178,15 @@ namespace Tetrahedral_remeshing return ft; } + template + Facet canonical_facet(const Facet& f) + { + const typename Facet::first_type c = f.first; + const int i = f.second; + const typename Facet::first_type c2 = c->neighbor(i); + return (c2 < c) ? std::make_pair(c2, c2->index(c)) : std::make_pair(c, i); + } + template bool is_on_feature(const VertexHandle v) { From a9324d4128d96b22d25cc8ac93a4c56d5026b173 Mon Sep 17 00:00:00 2001 From: Jane Tournois Date: Thu, 26 Mar 2020 15:58:45 +0100 Subject: [PATCH 179/568] get 3 extra iterations of flip/smooth back --- Tetrahedral_remeshing/include/CGAL/tetrahedral_remeshing.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Tetrahedral_remeshing/include/CGAL/tetrahedral_remeshing.h b/Tetrahedral_remeshing/include/CGAL/tetrahedral_remeshing.h index 6e036fc0222..abf66abd2cc 100644 --- a/Tetrahedral_remeshing/include/CGAL/tetrahedral_remeshing.h +++ b/Tetrahedral_remeshing/include/CGAL/tetrahedral_remeshing.h @@ -228,7 +228,7 @@ namespace CGAL #endif // perform remeshing - std::size_t nb_extra_iterations = 0;// 3; + std::size_t nb_extra_iterations = 3; remesher.remesh(max_it, nb_extra_iterations); #ifdef CGAL_TETRAHEDRAL_REMESHING_DEBUG From 8dab9317d00680747eadfdf60098647b6b3b5d37 Mon Sep 17 00:00:00 2001 From: Jane Tournois Date: Thu, 26 Mar 2020 16:35:22 +0100 Subject: [PATCH 180/568] remove outdated code --- .../internal/smooth_vertices.h | 23 ------------------- 1 file changed, 23 deletions(-) diff --git a/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/smooth_vertices.h b/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/smooth_vertices.h index c32f77e37ad..aae18ac2f66 100644 --- a/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/smooth_vertices.h +++ b/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/smooth_vertices.h @@ -294,29 +294,6 @@ namespace CGAL return true; } - template - bool check_inversion_and_move(const typename Tr::Vertex_handle v, - const CGAL::Vector_3& move, - const CellVector& cells, - const Tr& tr) - { - const typename Tr::Point backup = v->point(); //backup v's position - const typename Tr::Point new_pos(point(backup) + move); - v->set_point(new_pos); - - for(const typename CellVector::value_type& ci : cells) - { - if (CGAL::POSITIVE != CGAL::orientation(point(ci->vertex(0)->point()), - point(ci->vertex(1)->point()), - point(ci->vertex(2)->point()), - point(ci->vertex(3)->point()))) - { - v->set_point(backup); - return false; - } - } - return true; - } template void collect_vertices_subdomain_indices( From d1a323c730050c74ca0d31c303e7f06bd37a2c0f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9bastien=20Loriot?= Date: Thu, 26 Mar 2020 19:24:14 +0100 Subject: [PATCH 181/568] extra run of the script to remove tabs and trailing whitespaces --- .../include/CGAL/Cell_attribute.h | 6 +- Combinatorial_map/include/CGAL/Dart.h | 2 +- .../include/CGAL/Regular_complex_d.h | 160 ++-- .../include/CGAL/Interval_skip_list.h | 640 ++++++------- .../include/CGAL/Compact_mesh_cell_base_3.h | 12 +- .../cc_benchmark.cpp | 10 +- .../STL_Extension/CGAL/Compact_container.h | 850 +++++++++--------- .../CGAL/Concurrent_compact_container.h | 348 +++---- .../CGAL/Concurrent_compact_container.h | 2 +- .../STL_Extension/test_Compact_container.cpp | 2 +- .../test_Concurrent_compact_container.cpp | 30 +- .../Concepts/TriangulationDSFaceBase_2.h | 186 ++-- .../Concepts/TriangulationDSVertexBase_2.h | 126 +-- .../CGAL/Triangulation_data_structure_2.h | 670 +++++++------- .../CGAL/Triangulation_ds_face_base_2.h | 132 +-- .../CGAL/Triangulation_ds_vertex_base_2.h | 6 +- .../test/TDS_2/include/CGAL/_test_cls_tds_2.h | 138 +-- .../Concepts/TriangulationDSCellBase_3.h | 110 +-- .../Concepts/TriangulationDSVertexBase_3.h | 94 +- .../CGAL/Triangulation_data_structure_3.h | 172 ++-- .../CGAL/Triangulation_ds_cell_base_3.h | 4 +- .../CGAL/Triangulation_ds_vertex_base_3.h | 10 +- .../test/TDS_3/include/CGAL/_test_cls_tds_3.h | 96 +- .../Concepts/TriangulationDSFullCell.h | 60 +- .../Concepts/TriangulationDSVertex.h | 62 +- .../include/CGAL/Triangulation_ds_vertex.h | 2 +- .../CGAL/Constrained_triangulation_plus_2.h | 300 +++---- .../include/CGAL/Delaunay_triangulation_2.h | 4 +- .../Polyline_constraint_hierarchy_2.h | 202 ++--- .../include/CGAL/Triangulation_hierarchy_2.h | 162 ++-- .../Triangulation_hierarchy_vertex_base_2.h | 2 +- .../_test_cls_const_Del_triangulation_2.h | 40 +- .../_test_cls_constrained_triangulation_2.h | 42 +- .../CGAL/_test_cls_delaunay_triangulation_2.h | 66 +- .../include/CGAL/_test_cls_triangulation_2.h | 190 ++-- .../include/CGAL/_test_traits.h | 88 +- .../include/CGAL/Delaunay_triangulation_3.h | 4 +- ...angulation_cell_base_with_circumcenter_3.h | 4 +- .../include/CGAL/Regular_triangulation_3.h | 4 +- .../include/CGAL/Triangulation_hierarchy_3.h | 98 +- .../include/CGAL/_test_cls_delaunay_3.h | 200 ++--- .../include/CGAL/_test_cls_regular_3.h | 98 +- .../include/CGAL/_test_cls_triangulation_3.h | 246 ++--- 43 files changed, 2840 insertions(+), 2840 deletions(-) diff --git a/Combinatorial_map/include/CGAL/Cell_attribute.h b/Combinatorial_map/include/CGAL/Cell_attribute.h index db0fe4d3917..8fa4def7b3c 100644 --- a/Combinatorial_map/include/CGAL/Cell_attribute.h +++ b/Combinatorial_map/include/CGAL/Cell_attribute.h @@ -86,8 +86,8 @@ namespace CGAL { protected: void set_id(std::size_t id) { m_id=id; } - - protected: + + protected: /// id of the cell std::size_t m_id; }; @@ -96,7 +96,7 @@ namespace CGAL { template <> class Add_id {}; - + /// Cell_attribute_without_info template diff --git a/Combinatorial_map/include/CGAL/Dart.h b/Combinatorial_map/include/CGAL/Dart.h index 2b13b9d7911..bfc21e7b25a 100644 --- a/Combinatorial_map/include/CGAL/Dart.h +++ b/Combinatorial_map/include/CGAL/Dart.h @@ -113,7 +113,7 @@ namespace CGAL { assert(i<=dimension); return mf[i]; } - + protected: /** Default constructor: no real initialisation, * because this is done in the combinatorial map class. diff --git a/Convex_hull_d/include/CGAL/Regular_complex_d.h b/Convex_hull_d/include/CGAL/Regular_complex_d.h index ee50aefc331..4a5a32b1213 100644 --- a/Convex_hull_d/include/CGAL/Regular_complex_d.h +++ b/Convex_hull_d/include/CGAL/Regular_complex_d.h @@ -6,7 +6,7 @@ // $URL$ // $Id$ // SPDX-License-Identifier: GPL-3.0-or-later OR LicenseRef-Commercial -// +// // // Author(s) : Michael Seel //--------------------------------------------------------------------- @@ -49,13 +49,13 @@ template class Regular_complex_d; template class Convex_hull_d; #define forall_rc_vertices(x,RC)\ -for(x = (RC).vertices_begin(); x != (RC).vertices_end(); ++x) +for(x = (RC).vertices_begin(); x != (RC).vertices_end(); ++x) #define forall_rc_simplices(x,RC)\ -for(x = (RC).simplices_begin(); x != (RC).simplices_end(); ++x) +for(x = (RC).simplices_begin(); x != (RC).simplices_end(); ++x) template -class RC_vertex_d +class RC_vertex_d { typedef RC_vertex_d Self; typedef typename Refs::Point_d Point_d; @@ -96,7 +96,7 @@ public: template -class RC_simplex_d +class RC_simplex_d { typedef RC_simplex_d Self; typedef typename Refs::Point_d Point_d; typedef typename Refs::Vertex_handle Vertex_handle; @@ -107,7 +107,7 @@ class RC_simplex_d protected: std::vector vertices; // array of vertices std::vector neighbors; // opposite simplices - std::vector opposite_vertices; + std::vector opposite_vertices; // indices of opposite vertices //------ only for convex hulls ------------------ @@ -122,7 +122,7 @@ protected: void set_vertex(int i, Vertex_handle v) { vertices[i] = v; } void set_neighbor(int i, Simplex_handle s) { neighbors[i]=s; } - void set_opposite_vertex_index(int i, int index) + void set_opposite_vertex_index(int i, int index) { opposite_vertices[i]=index; } //------ only for convex hulls ------------------ @@ -132,23 +132,23 @@ protected: //------ only for convex hulls ------------------ public: - typedef typename std::vector::const_iterator + typedef typename std::vector::const_iterator VIV_iterator; struct Point_from_VIV_iterator { typedef Vertex_handle argument_type; typedef Point_d result_type; - result_type& operator()(argument_type& x) const + result_type& operator()(argument_type& x) const { return x->point(); } - const result_type& operator()(const argument_type& x) const + const result_type& operator()(const argument_type& x) const { return x->point(); } }; typedef CGAL::Iterator_project Point_const_iterator; - Point_const_iterator points_begin() const + Point_const_iterator points_begin() const { return Point_const_iterator(vertices.begin()); } - Point_const_iterator points_end() const + Point_const_iterator points_end() const { return Point_const_iterator(vertices.end()); } void* pp; @@ -164,12 +164,12 @@ public: typedef const Point_d* pointer; typedef const Point_d& reference; - typedef typename std::vector::const_iterator + typedef typename std::vector::const_iterator ra_vertex_iterator; Point_const_iterator() : _it() {} Point_const_iterator(ra_vertex_iterator it) : _it(it) {} - + value_type operator*() const { return (*_it)->point(); } pointer operator->() const { return &(operator*()); } @@ -180,9 +180,9 @@ public: self& operator+=(difference_type i) { _it+=i; return *this; } self& operator-=(difference_type i) { _it-=i; return *this; } - self operator+(difference_type i) const + self operator+(difference_type i) const { self tmp=*this; tmp+=i; return tmp; } - self operator-(difference_type i) const + self operator-(difference_type i) const { self tmp=*this; tmp-=i; return tmp; } difference_type operator-(self x) const { return _it-x._it; } @@ -193,28 +193,28 @@ public: bool operator<(self x) const { (x - *this) > 0; } private: - ra_vertex_iterator _it; + ra_vertex_iterator _it; }; // Point_const_iterator - Point_const_iterator points_begin() const + Point_const_iterator points_begin() const { return Point_const_iterator(vertices.begin()); } - Point_const_iterator points_end() const + Point_const_iterator points_end() const { return Point_const_iterator(vertices.end()); } #endif - + RC_simplex_d() : pp(nullptr) {} - RC_simplex_d(int dmax) : + RC_simplex_d(int dmax) : vertices(dmax+1), neighbors(dmax+1), opposite_vertices(dmax+1), pp(nullptr) - { for (int i = 0; i <= dmax; i++) { - neighbors[i] = Simplex_handle(); - vertices[i] = Vertex_handle(); + { for (int i = 0; i <= dmax; i++) { + neighbors[i] = Simplex_handle(); + vertices[i] = Vertex_handle(); opposite_vertices[i] = -1; } visited_ = false; } - ~RC_simplex_d() {} + ~RC_simplex_d() {} void print(std::ostream& O=std::cout) const { @@ -228,10 +228,10 @@ public: } #ifdef CGAL_USE_LEDA - LEDA_MEMORY(RC_simplex_d) + LEDA_MEMORY(RC_simplex_d) #endif -}; +}; template std::ostream& operator<<(std::ostream& O, const RC_simplex_d& s) @@ -239,7 +239,7 @@ std::ostream& operator<<(std::ostream& O, const RC_simplex_d& s) /*{\Manpage {Regular_complex_d}{R}{Regular Simplicial Complex}{C}}*/ -/*{\Mdefinition +/*{\Mdefinition An instance |\Mvar| of type |\Mname| is a regular abstract or concrete simplicial complex. An abstract simplicial complex is a family |\Mvar| @@ -255,7 +255,7 @@ neighbors if they share $k-1$ vertices. A complex is connected if its set of maximal simplices forms a connected set under the neighboring relation. A simplicial complex is called \emph{regular} if all maximal simplices in the complex have the same dimension and if the -complex is connected. +complex is connected. A concrete simplicial complex is an abstract simplicial complex in which a point in some ambient space is associated with each vertex. @@ -275,7 +275,7 @@ All maximal simplices in a regular simplicial complex have the same dimension, which we denote |dcur|. For each maximal simplex\cgalFootnote{we drop the adjective maximal in the sequel} in |\Mvar| there is an item of type |RC_simplex_d| and for each vertex -there is an item of type |rc_vertex|. Each maximal simplex has |1+dcur| +there is an item of type |rc_vertex|. Each maximal simplex has |1+dcur| vertices indexed from $0$ to |dcur|. For any simplex $s$ and any index $i$, |C.vertex_of(s,i)| returns the $i$-th vertex of $s$. There may or may not be a simplex $t$ opposite to (the vertex with index) @@ -286,7 +286,7 @@ set. The function |C.opposite(s,i)| returns $t$ if it exists and returns |nil| otherwise. If $t$ exists then $s$ and $t$ share |dcur| vertices, namely all but vertex $i$ of $s$ and vertex |C.opposite_vertex(s,i)| of $t$. Assume that $t = |C.opposite(s,i)|$ -exists and let |j = C.opposite_vertex(s,i)|. Then |s = C.opposite(t,j)| +exists and let |j = C.opposite_vertex(s,i)|. Then |s = C.opposite(t,j)| and |i = C.opposite_vertex(t,j)| and \begin{eqnarray*} \lefteqn{\{|C.vertex_of(s,0)|,|C.vertex_of(s,1)|,\ldots, @@ -318,7 +318,7 @@ sharing a face. template class Regular_complex_d -{ +{ typedef Regular_complex_d Self; public: /*{\Mtypes 4}*/ @@ -364,11 +364,11 @@ protected: private: - Regular_complex_d(const Regular_complex_d& ); - Regular_complex_d& operator=(const Regular_complex_d& ); + Regular_complex_d(const Regular_complex_d& ); + Regular_complex_d& operator=(const Regular_complex_d& ); void clean_dynamic_memory() - { + { vertices_.clear(); simplices_.clear(); } @@ -377,7 +377,7 @@ public: /*{\Mcreation}*/ -Regular_complex_d(int d = 2, const R& Kernel = R()) +Regular_complex_d(int d = 2, const R& Kernel = R()) /*{\Mcreate creates an instance |\Mvar| of type |\Mtype|. The dimension of the underlying space is $d$ and |\Mvar| is initialized to the empty regular complex. Thus |dcur| equals $-1$. The traits class @@ -399,7 +399,7 @@ the traits class is to be found at the end of this manual page.}*/ /* In the destructor for |Regular_complex_d|, we have to release the storage which was allocated for the simplices and the vertices. */ -/*{\Mtext The data type |\Mtype| offers neither copy constructor nor +/*{\Mtext The data type |\Mtype| offers neither copy constructor nor assignment operator.}*/ /*{\Moperations 3 3}*/ @@ -412,39 +412,39 @@ int current_dimension() const { return dcur; } /*{\Mop returns the current dimension of the simplices in the complex.}*/ -Vertex_handle vertex(Simplex_handle s, int i) const +Vertex_handle vertex(Simplex_handle s, int i) const /*{\Mop returns the $i$-th vertex of $s$.\\ \precond $0 \leq i \leq |current_dimension|$. }*/ { CGAL_assertion(0<=i&&i<=dcur); return s->vertex(i); } -Vertex_const_handle vertex(Simplex_const_handle s, int i) const +Vertex_const_handle vertex(Simplex_const_handle s, int i) const { CGAL_assertion(0<=i&&i<=dcur); return s->vertex(i); } -Point_d associated_point(Vertex_handle v) const +Point_d associated_point(Vertex_handle v) const /*{\Mop returns the point associated with vertex |v|.}*/ { return v->point(); } -Point_d associated_point(Vertex_const_handle v) const +Point_d associated_point(Vertex_const_handle v) const { return v->point(); } -int index(Vertex_handle v) const +int index(Vertex_handle v) const /*{\Mop returns the index of $v$ in |C.simplex(v)|.}*/ { return v->index(); } -int index(Vertex_const_handle v) const +int index(Vertex_const_handle v) const { return v->index(); } -Simplex_handle simplex(Vertex_handle v) const +Simplex_handle simplex(Vertex_handle v) const /*{\Mop returns a simplex of which $v$ is a vertex. Note that this simplex is not unique. }*/ -{ return v->simplex(); } +{ return v->simplex(); } -Simplex_const_handle simplex(Vertex_const_handle v) const -{ return v->simplex(); } +Simplex_const_handle simplex(Vertex_const_handle v) const +{ return v->simplex(); } Point_d associated_point(Simplex_handle s, int i) const /*{\Mop same as |C.associated_point(C.vertex(s,i))|.}*/ @@ -453,13 +453,13 @@ Point_d associated_point(Simplex_handle s, int i) const Point_d associated_point(Simplex_const_handle s, int i) const { return associated_point(vertex(s,i)); } -Simplex_handle opposite_simplex(Simplex_handle s,int i) const +Simplex_handle opposite_simplex(Simplex_handle s,int i) const /*{\Mop returns the simplex opposite to the $i$-th vertex of $s$ (|Simplex_handle()| is there is no such simplex).\\ \precond $0 \leq i \leq |dcur|$. }*/ { CGAL_assertion(0<=i&&i<=dcur); return s->neighbor(i); } -Simplex_const_handle opposite_simplex(Simplex_const_handle s,int i) const +Simplex_const_handle opposite_simplex(Simplex_const_handle s,int i) const { CGAL_assertion(0<=i&&i<=dcur); return s->neighbor(i); } @@ -484,35 +484,35 @@ to be used with care as they may invalidate the data structure.}*/ void clear(int d = 0) /*{\Mop reinitializes |\Mvar| to the empty complex in dimension |dim|.}*/ { clean_dynamic_memory(); - dmax = d; dcur = -1; + dmax = d; dcur = -1; } void set_current_dimension(int d) { dcur = d; } /*{\Mop sets |dcur| to |d|. }*/ -Simplex_handle new_simplex() +Simplex_handle new_simplex() /*{\Mop adds a new simplex to |\Mvar| and returns it. The new simplex has no vertices yet.}*/ -{ +{ Simplex s(dmax); Simplex_handle h = simplices_.insert(s); return h; } -Vertex_handle new_vertex() +Vertex_handle new_vertex() /*{\Mop adds a new vertex to |\Mvar| and returns it. The new vertex has no associated simplex nor index yet. The associated point is the point |Regular_complex_d::nil_point| which is a static member of class |Regular_complex_d.|}*/ -{ - return vertices_.emplace(nil_point); +{ + return vertices_.emplace(nil_point); } -Vertex_handle new_vertex(const Point_d& p) +Vertex_handle new_vertex(const Point_d& p) /*{\Mop adds a new vertex to |\Mvar| and returns it. The new vertex has |p| as the associated point, but is has no associated simplex nor index yet.}*/ -{ +{ return vertices_.emplace(p); } @@ -520,7 +520,7 @@ void associate_vertex_with_simplex(Simplex_handle s, int i, Vertex_handle v) /*{\Mop sets the $i$-th vertex of |s| to |v| and records this fact in $v$. The latter occurs only if $v$ is non-nil.}*/ { s -> set_vertex(i,v); - if ( v != Vertex_handle() ) { + if ( v != Vertex_handle() ) { v -> set_simplex(s); v -> set_index(i); } } @@ -563,7 +563,7 @@ Size_type number_of_vertices() const { return this->vertices_.size();} Size_type number_of_simplices() const { return this->simplices_.size();} void print_statistics(std::ostream& os = std::cout) const -{ +{ os << "Regular_complex_d - statistic" << std::endl; os << "number of vertices = " << number_of_vertices() << std::endl; os << "number of simplices = " << number_of_simplices() << std::endl; @@ -595,7 +595,7 @@ std::list all_simplices() forall_rc_simplices(it,*this) res.push_back(it); return res; } -std::list all_simplices() const +std::list all_simplices() const { std::list res; Simplex_const_iterator it; forall_rc_simplices(it,*this) res.push_back(it); return res; } @@ -606,7 +606,7 @@ std::list all_vertices() forall_rc_vertices(it,*this) res.push_back(it); return res; } -std::list all_vertices() const +std::list all_vertices() const { std::list res; Vertex_const_iterator it; forall_rc_vertices(it,*this) res.push_back(it); return res; } @@ -619,18 +619,18 @@ static const Point_d nil_point; }; // Regular_complex_d // init static member: -template +template const typename Regular_complex_d::Point_d Regular_complex_d::nil_point; template void Regular_complex_d::check_topology() const -{ - Simplex_const_handle s,t; +{ + Simplex_const_handle s,t; Vertex_const_handle v; - int i,j,k; + int i,j,k; if (dcur == -1) { - if (!vertices_.empty() || !simplices_.empty() ) + if (!vertices_.empty() || !simplices_.empty() ) CGAL_error_msg( "check_topology: dcur is -1 but there are vertices or simplices"); } @@ -643,26 +643,26 @@ void Regular_complex_d::check_topology() const for(i = 0; i <= dcur; i++) { for (j = i + 1; j <= dcur; j++) { if (vertex(s,i) == vertex(s,j)) - CGAL_error_msg( "check_topology: a simplex with two equal vertices"); + CGAL_error_msg( "check_topology: a simplex with two equal vertices"); } } } forall_rc_simplices(s,*this) { for(i = 0; i <= dcur; i++) { - if ((t = opposite_simplex(s,i)) != Simplex_const_handle()) { - int l = index_of_opposite_vertex(s,i); - if (s != opposite_simplex(t,l) || + if ((t = opposite_simplex(s,i)) != Simplex_const_handle()) { + int l = index_of_opposite_vertex(s,i); + if (s != opposite_simplex(t,l) || i != index_of_opposite_vertex(t,l)) - CGAL_error_msg( "check_topology: neighbor relation is not symmetric"); + CGAL_error_msg( "check_topology: neighbor relation is not symmetric"); for (j = 0; j <= dcur; j++) { if (j != i) { // j must also occur as a vertex of t - for (k = 0; k <= dcur && + for (k = 0; k <= dcur && ( vertex(s,j) != vertex(t,k) || k == l); k++) {} - if (k > dcur) - CGAL_error_msg( "check_topology: too few shared vertices."); + if (k > dcur) + CGAL_error_msg( "check_topology: too few shared vertices."); } } } @@ -672,11 +672,11 @@ void Regular_complex_d::check_topology() const template void Regular_complex_d::check_topology_and_geometry() const -{ +{ check_topology(); Vertex_const_handle v; forall_rc_vertices(v,*this) { - if ( v == Vertex_const_handle() || + if ( v == Vertex_const_handle() || associated_point(v).identical(Regular_complex_d::nil_point) ) CGAL_error_msg("check_topology_and_geometry: \ vertex with nil_point or no associated point."); @@ -687,7 +687,7 @@ void Regular_complex_d::check_topology_and_geometry() const Simplex_const_handle s; forall_rc_simplices(s,*this) { std::vector A(dcur + 1); - for (int i = 0; i <= dcur; i++) + for (int i = 0; i <= dcur; i++) A[i] = associated_point(s,i); if ( !affinely_independent(A.begin(),A.end()) ) CGAL_error_msg("check_topology_and_geometry: \ @@ -696,13 +696,13 @@ void Regular_complex_d::check_topology_and_geometry() const } -/*{\Mtext +/*{\Mtext \headerline{Iteration Statements} -{\bf forall\_rc\_simplices}($s,C$) +{\bf forall\_rc\_simplices}($s,C$) $\{$ ``the simplices of $C$ are successively assigned to $s$'' $\}$ -{\bf forall\_rc\_vertices}($v,C$) +{\bf forall\_rc\_vertices}($v,C$) $\{$ ``the vertices of $C$ are successively assigned to $v$'' $\}$ }*/ diff --git a/Interval_skip_list/include/CGAL/Interval_skip_list.h b/Interval_skip_list/include/CGAL/Interval_skip_list.h index 1c13f5d5cde..a445981a3f2 100644 --- a/Interval_skip_list/include/CGAL/Interval_skip_list.h +++ b/Interval_skip_list/include/CGAL/Interval_skip_list.h @@ -6,7 +6,7 @@ // $URL$ // $Id$ // SPDX-License-Identifier: GPL-3.0-or-later OR LicenseRef-Commercial -// +// // // Author(s) : Andreas Fabri @@ -48,7 +48,7 @@ namespace CGAL { template class IntervalSLnode; - const int MAX_FORWARD = 48; // Maximum number of forward pointers + const int MAX_FORWARD = 48; // Maximum number of forward pointers @@ -62,7 +62,7 @@ namespace CGAL { Value key; IntervalSLnode** forward; // array of forward pointers - IntervalList** markers; // array of interval markers, + IntervalList** markers; // array of interval markers, // one for each pointer IntervalList* eqMarkers; // markers for node itself int ownerCount; // number of interval end points with value equal to key @@ -79,19 +79,19 @@ namespace CGAL { void print(std::ostream& os) const; - const Value& + const Value& getValue() { return key; } - + // number of levels of this node - int - level() const + int + level() const { return(topLevel+1); } - + bool isHeader() const { @@ -99,7 +99,7 @@ namespace CGAL { } void deleteMarks(IntervalList* l); - + ~IntervalSLnode(); // destructor }; @@ -111,9 +111,9 @@ class Interval_for_container : public Interval_ void * p; public: Interval_for_container(const Interval_& i) - : Interval_(i), p(nullptr) + : Interval_(i), p(nullptr) {} - + void * for_compact_container() const { return p; } void for_compact_container(void *ptr) { p = ptr; } }; @@ -133,7 +133,7 @@ class Interval_for_container : public Interval_ typedef typename std::list::iterator Interval_handle; #else Compact_container > container; - typedef typename Compact_container >::iterator + typedef typename Compact_container >::iterator Interval_handle; #endif @@ -151,139 +151,139 @@ class Interval_for_container : public Interval_ // place markers for Interval I. I must have been inserted in the list. // left is the left endpoint of I and right is the right endpoint if I. // *** needs to be fixed: - void placeMarkers(IntervalSLnode* left, - IntervalSLnode* right, - const Interval_handle& I); + void placeMarkers(IntervalSLnode* left, + IntervalSLnode* right, + const Interval_handle& I); // remove markers for Interval I - void removeMarkers(const Interval_handle& I); + void removeMarkers(const Interval_handle& I); // adjust markers after insertion of x with update vector "update" - void adjustMarkersOnInsert(IntervalSLnode* x, - IntervalSLnode** update); + void adjustMarkersOnInsert(IntervalSLnode* x, + IntervalSLnode** update); // adjust markers to prepare for deletion of x, which has update vector // "update" - void adjustMarkersOnDelete(IntervalSLnode* x, - IntervalSLnode** update); + void adjustMarkersOnDelete(IntervalSLnode* x, + IntervalSLnode** update); // remove node x, which has updated vector update. - void remove(IntervalSLnode* x, - IntervalSLnode** update); + void remove(IntervalSLnode* x, + IntervalSLnode** update); // remove markers for Interval I starting at left, the left endpoint // of I, and and stopping at the right endpoint of I. - Interval_handle removeMarkers(IntervalSLnode* left, - const Interval& I); + Interval_handle removeMarkers(IntervalSLnode* left, + const Interval& I); // Remove markers for interval m from the edges and nodes on the // level i path from l to r. void removeMarkFromLevel(const Interval& m, int i, - IntervalSLnode *l, - IntervalSLnode* r); + IntervalSLnode *l, + IntervalSLnode* r); - // Search for search key, and return a pointer to the - // intervalSLnode x found, as well as setting the update vector - // showing pointers into x. - IntervalSLnode* search(const Value& searchKey, - IntervalSLnode** update); + // Search for search key, and return a pointer to the + // intervalSLnode x found, as well as setting the update vector + // showing pointers into x. + IntervalSLnode* search(const Value& searchKey, + IntervalSLnode** update); - - // insert a new single value - // into list, returning a pointer to its location. + + // insert a new single value + // into list, returning a pointer to its location. IntervalSLnode* insert(const Value& searchKey); - // insert an interval into list + // insert an interval into list void insert(const Interval_handle& I); public: friend class IntervalSLnode; - Interval_skip_list(); - + Interval_skip_list(); + template Interval_skip_list(InputIterator b, InputIterator e) { maxLevel = 0; header = new IntervalSLnode(MAX_FORWARD); for (int i = 0; i< MAX_FORWARD; i++) { - header->forward[i] = 0; + header->forward[i] = 0; } for(; b!= e; ++b){ - insert(*b); + insert(*b); } } - ~Interval_skip_list(); + ~Interval_skip_list(); void clear(); - int size() const + int size() const { return container.size(); } - + // return node containing // Value if found, otherwise null - IntervalSLnode* search(const Value& searchKey); + IntervalSLnode* search(const Value& searchKey); template - OutputIterator + OutputIterator find_intervals(const Value& searchKey, OutputIterator out ) { IntervalSLnode* x = header; - for(int i=maxLevel; - i >= 0 && (x->isHeader() || (x->key != searchKey)); i--) { - while (x->forward[i] != 0 && (searchKey >= x->forward[i]->key)) { - x = x->forward[i]; - } - // Pick up markers on edge as you drop down a level, unless you are at - // the searchKey node already, in which case you pick up the - // eqMarkers just prior to exiting loop. - if(!x->isHeader() && (x->key != searchKey)) { - out = x->markers[i]->copy(out); - } else if (!x->isHeader()) { // we're at searchKey - out = x->eqMarkers->copy(out); - } + for(int i=maxLevel; + i >= 0 && (x->isHeader() || (x->key != searchKey)); i--) { + while (x->forward[i] != 0 && (searchKey >= x->forward[i]->key)) { + x = x->forward[i]; + } + // Pick up markers on edge as you drop down a level, unless you are at + // the searchKey node already, in which case you pick up the + // eqMarkers just prior to exiting loop. + if(!x->isHeader() && (x->key != searchKey)) { + out = x->markers[i]->copy(out); + } else if (!x->isHeader()) { // we're at searchKey + out = x->eqMarkers->copy(out); + } } return out; } - + bool is_contained(const Value& searchKey) const { IntervalSLnode* x = header; - for(int i=maxLevel; - i >= 0 && (x->isHeader() || (x->key != searchKey)); i--) { - while (x->forward[i] != 0 && (searchKey >= x->forward[i]->key)) { - x = x->forward[i]; - } - // Pick up markers on edge as you drop down a level, unless you are at - // the searchKey node already, in which case you pick up the - // eqMarkers just prior to exiting loop. - if(!x->isHeader() && (x->key != searchKey)) { - return true; - } else if (!x->isHeader()) { // we're at searchKey - return true; - } + for(int i=maxLevel; + i >= 0 && (x->isHeader() || (x->key != searchKey)); i--) { + while (x->forward[i] != 0 && (searchKey >= x->forward[i]->key)) { + x = x->forward[i]; + } + // Pick up markers on edge as you drop down a level, unless you are at + // the searchKey node already, in which case you pick up the + // eqMarkers just prior to exiting loop. + if(!x->isHeader() && (x->key != searchKey)) { + return true; + } else if (!x->isHeader()) { // we're at searchKey + return true; + } } return false; } - + void insert(const Interval& I); @@ -292,8 +292,8 @@ class Interval_for_container : public Interval_ { int i = 0; for(; b!= e; ++b){ - insert(*b); - ++i; + insert(*b); + ++i; } return i; } @@ -306,7 +306,7 @@ class Interval_for_container : public Interval_ #ifdef CGAL_ISL_USE_LIST typedef typename std::list::const_iterator const_iterator; #else - typedef typename + typedef typename Compact_container >::const_iterator const_iterator; #endif @@ -318,7 +318,7 @@ class Interval_for_container : public Interval_ { return container.end(); } - + }; @@ -333,7 +333,7 @@ class Interval_for_container : public Interval_ typedef typename std::list::iterator Interval_handle; #else - typedef typename Compact_container >::iterator + typedef typename Compact_container >::iterator Interval_handle; #endif @@ -382,7 +382,7 @@ class Interval_for_container : public Interval_ } void erase_list_element(ILE_handle I) - { + { #ifdef CGAL_ISL_USE_CCC compact_container.erase(I); #else @@ -398,21 +398,21 @@ class Interval_for_container : public Interval_ ILE_handle get_next(ILE_handle element); void copy(IntervalList* from); // add contents of "from" to self - - + + template OutputIterator copy(OutputIterator out) const { ILE_handle e = header; - while(e!= nullptr) { - out = *(e->I); - ++out; - e = e->next; + while(e!= nullptr) { + out = *(e->I); + ++out; + e = e->next; } return out; } - + bool contains(const Interval_handle& I) const; void clear(); // delete elements of self to make self an empty list. @@ -424,10 +424,10 @@ class Interval_for_container : public Interval_ #ifdef CGAL_ISL_USE_CCC template - Compact_container > + Compact_container > IntervalList::compact_container; #endif - + @@ -439,7 +439,7 @@ class Interval_for_container : public Interval_ typedef typename std::list::iterator Interval_handle; #else - typedef typename Compact_container >::iterator + typedef typename Compact_container >::iterator Interval_handle; #endif @@ -464,7 +464,7 @@ class Interval_for_container : public Interval_ { return ( ((*I) == (*(e.I))) && (next == e.next)); } - + friend class IntervalList; @@ -474,7 +474,7 @@ class Interval_for_container : public Interval_ ~IntervalListElt(); - void + void set_next(ILE_handle nextElt) { next = nextElt; @@ -508,7 +508,7 @@ class Interval_for_container : public Interval_ for(int i=0; i<=levels; i++) { forward[i] = 0; // initialize an empty interval list - markers[i] = new IntervalList(); + markers[i] = new IntervalList(); } } @@ -526,7 +526,7 @@ class Interval_for_container : public Interval_ for(int i=0; i<=levels; i++) { forward[i] = 0; // initialize an empty interval list - markers[i] = new IntervalList(); + markers[i] = new IntervalList(); } } @@ -586,8 +586,8 @@ class Interval_for_container : public Interval_ } template - std::ostream& operator<<(std::ostream& os, - const Interval_skip_list& isl) + std::ostream& operator<<(std::ostream& os, + const Interval_skip_list& isl) { isl.print(os); return os; @@ -610,7 +610,7 @@ template void IntervalList::copy(IntervalList* from) { ILE_handle e = from->header; - while(e!=nullptr) { + while(e!=nullptr) { insert(e->I); e = e->next; } @@ -621,7 +621,7 @@ template void IntervalList::clear() { ILE_handle x = header; - ILE_handle y; + ILE_handle y; while(x!= nullptr) { // was 0 y = x; x = x->next; @@ -631,11 +631,11 @@ template } template - IntervalSLnode* + IntervalSLnode* Interval_skip_list::insert(const Value& searchKey) { - // array for maintaining update pointers - IntervalSLnode* update[MAX_FORWARD]; + // array for maintaining update pointers + IntervalSLnode* update[MAX_FORWARD]; IntervalSLnode* x; int i; @@ -646,18 +646,18 @@ template // put a new node in the list for this searchKey int newLevel = randomLevel(); if (newLevel > maxLevel){ - for(i=maxLevel+1; i<=newLevel; i++){ - update[i] = header; - header->markers[i]->clear(); - } - maxLevel = newLevel; + for(i=maxLevel+1; i<=newLevel; i++){ + update[i] = header; + header->markers[i]->clear(); + } + maxLevel = newLevel; } x = new IntervalSLnode(searchKey, newLevel); // add x to the list for(i=0; i<=newLevel; i++) { - x->forward[i] = update[i]->forward[i]; - update[i]->forward[i] = x; + x->forward[i] = update[i]->forward[i]; + update[i]->forward[i] = x; } // adjust markers to maintain marker invariant @@ -673,10 +673,10 @@ template // node x has just been inserted, with update vector `update.' template - void + void Interval_skip_list::adjustMarkersOnInsert (IntervalSLnode* x, - IntervalSLnode** update) + IntervalSLnode** update) { // Phase 1: place markers on edges leading out of x as needed. @@ -684,14 +684,14 @@ template // If a marker has to be promoted from level i to i+1 of higher, place it // in the promoted set at each step. - IntervalList promoted; + IntervalList promoted; // list of intervals that identify markers being // promoted, initially empty. - IntervalList newPromoted; + IntervalList newPromoted; // temporary set to hold newly promoted markers. - - IntervalList removePromoted; + + IntervalList removePromoted; // holding place for elements to be removed from promoted list. IntervalList tempMarkList; // temporary mark list @@ -701,41 +701,41 @@ template for(i=0; (i<= x->level() - 2) && x->forward[i+1]!=0; i++) { IntervalList* markList = update[i]->markers[i]; for(m = markList->get_first(); m != nullptr ; m = markList->get_next(m)) { - if(m->getInterval()->contains_interval(x->key,x->forward[i+1]->key)) { - // promote m - - // remove m from level i path from x->forward[i] to x->forward[i+1] - removeMarkFromLevel(*m->getInterval(), - i, - x->forward[i], - x->forward[i+1]); - // add m to newPromoted - newPromoted.insert(m->getInterval()); - } else { - // place m on the level i edge out of x - x->markers[i]->insert(m->getInterval()); - // do *not* place m on x->forward[i]; it must already be there. - } + if(m->getInterval()->contains_interval(x->key,x->forward[i+1]->key)) { + // promote m + + // remove m from level i path from x->forward[i] to x->forward[i+1] + removeMarkFromLevel(*m->getInterval(), + i, + x->forward[i], + x->forward[i+1]); + // add m to newPromoted + newPromoted.insert(m->getInterval()); + } else { + // place m on the level i edge out of x + x->markers[i]->insert(m->getInterval()); + // do *not* place m on x->forward[i]; it must already be there. + } } - + for(m = promoted.get_first(); m != nullptr; m = promoted.get_next(m)) { - if(!m->getInterval()->contains_interval(x->key, x->forward[i+1]->key)){ - // Then m does not need to be promoted higher. - // Place m on the level i edge out of x and remove m from promoted. - x->markers[i]->insert(m->getInterval()); - // mark x->forward[i] if needed - if(m->getInterval()->contains(x->forward[i]->key)) - x->forward[i]->eqMarkers->insert(m->getInterval()); - removePromoted.insert(m->getInterval()); - } else { - // continue to promote m - // Remove m from the level i path from x->forward[i] - // to x->forward[i+1]. - removeMarkFromLevel(*(m->getInterval()), - i, - x->forward[i], - x->forward[i+1]); - } + if(!m->getInterval()->contains_interval(x->key, x->forward[i+1]->key)){ + // Then m does not need to be promoted higher. + // Place m on the level i edge out of x and remove m from promoted. + x->markers[i]->insert(m->getInterval()); + // mark x->forward[i] if needed + if(m->getInterval()->contains(x->forward[i]->key)) + x->forward[i]->eqMarkers->insert(m->getInterval()); + removePromoted.insert(m->getInterval()); + } else { + // continue to promote m + // Remove m from the level i path from x->forward[i] + // to x->forward[i+1]. + removeMarkFromLevel(*(m->getInterval()), + i, + x->forward[i], + x->forward[i+1]); + } } promoted.removeAll(&removePromoted); removePromoted.clear(); @@ -744,68 +744,68 @@ template } // Combine the promoted set and updated[i]->markers[i] // and install them as the set of markers on the top edge out of x - // that is non-null. - + // that is non-null. + x->markers[i]->copy(&promoted); x->markers[i]->copy(update[i]->markers[i]); for(m=promoted.get_first(); m!=nullptr; m=promoted.get_next(m)) if(m->getInterval()->contains(x->forward[i]->key)) x->forward[i]->eqMarkers->insert(m->getInterval()); - + // Phase 2: place markers on edges leading into x as needed. - + // Markers on edges leading into x may need to be promoted as high as // the top edge coming into x, but never higher. - + promoted.clear(); - + for (i=0; (i <= x->level() - 2) && !update[i+1]->isHeader(); i++) { tempMarkList.copy(update[i]->markers[i]); - for(m = tempMarkList.get_first(); - m != nullptr; - m = tempMarkList.get_next(m)){ - if(m->getInterval()->contains_interval(update[i+1]->key,x->key)) { - // m needs to be promoted - // add m to newPromoted - newPromoted.insert(m->getInterval()); - - // Remove m from the path of level i edges between updated[i+1] - // and x (it will be on all those edges or else the invariant - // would have previously been violated. - removeMarkFromLevel(*(m->getInterval()),i,update[i+1],x); - } + for(m = tempMarkList.get_first(); + m != nullptr; + m = tempMarkList.get_next(m)){ + if(m->getInterval()->contains_interval(update[i+1]->key,x->key)) { + // m needs to be promoted + // add m to newPromoted + newPromoted.insert(m->getInterval()); + + // Remove m from the path of level i edges between updated[i+1] + // and x (it will be on all those edges or else the invariant + // would have previously been violated. + removeMarkFromLevel(*(m->getInterval()),i,update[i+1],x); + } } tempMarkList.clear(); // reclaim storage - + for(m = promoted.get_first(); m != nullptr; m = promoted.get_next(m)) { - if (!update[i]->isHeader() && - m->getInterval()->contains_interval(update[i]->key,x->key) && - !update[i+1]->isHeader() && - ! m->getInterval()->contains_interval(update[i+1]->key,x->key) ) { - // Place m on the level i edge between update[i] and x, and - // remove m from promoted. - update[i]->markers[i]->insert(m->getInterval()); - // mark update[i] if needed - if(m->getInterval()->contains(update[i]->key)) - update[i]->eqMarkers->insert(m->getInterval()); - removePromoted.insert(m->getInterval()); - } else { - // Strip m from the level i path from update[i+1] to x. - removeMarkFromLevel(*(m->getInterval()),i,update[i+1],x); - } - + if (!update[i]->isHeader() && + m->getInterval()->contains_interval(update[i]->key,x->key) && + !update[i+1]->isHeader() && + ! m->getInterval()->contains_interval(update[i+1]->key,x->key) ) { + // Place m on the level i edge between update[i] and x, and + // remove m from promoted. + update[i]->markers[i]->insert(m->getInterval()); + // mark update[i] if needed + if(m->getInterval()->contains(update[i]->key)) + update[i]->eqMarkers->insert(m->getInterval()); + removePromoted.insert(m->getInterval()); + } else { + // Strip m from the level i path from update[i+1] to x. + removeMarkFromLevel(*(m->getInterval()),i,update[i+1],x); + } + } // remove non-promoted marks from promoted promoted.removeAll(&removePromoted); removePromoted.clear(); // reclaim storage - + // add newPromoted to promoted and make newPromoted empty promoted.copy(&newPromoted); - newPromoted.clear(); + newPromoted.clear(); } - + /* Assertion: i=x->level()-1 OR update[i+1] is the header. - + If i=x->level()-1 then either x has only one level, or the top-level pointer into x must not be from the header, since otherwise we would have stopped on the previous iteration. If x has 1 level, then @@ -822,22 +822,22 @@ template update[i]->markers[i]->copy(&promoted); for(m=promoted.get_first(); m!=nullptr; m=promoted.get_next(m)) if(m->getInterval()->contains(update[i]->key)) - update[i]->eqMarkers->insert(m->getInterval()); + update[i]->eqMarkers->insert(m->getInterval()); // Place markers on x for all intervals the cross x. // (Since x is a new node, every marker coming into x must also leave x). for(i=0; ilevel(); i++) x->eqMarkers->copy(x->markers[i]); - + promoted.clear(); // reclaim storage - + } // end adjustMarkersOnInsert template void Interval_skip_list::adjustMarkersOnDelete (IntervalSLnode* x, - IntervalSLnode** update) + IntervalSLnode** update) { // x is node being deleted. It is still in the list. // update is the update vector for x. @@ -852,13 +852,13 @@ template for(i=x->level()-1; i>=0; i--){ // find marks on edge into x at level i to be demoted - for(m=update[i]->markers[i]->get_first(); m!=nullptr; - m=update[i]->markers[i]->get_next(m)){ - if(x->forward[i]==0 || - ! m->getInterval()->contains_interval(update[i]->key, - x->forward[i]->key)){ - newDemoted.insert(m->getInterval()); - } + for(m=update[i]->markers[i]->get_first(); m!=nullptr; + m=update[i]->markers[i]->get_next(m)){ + if(x->forward[i]==0 || + ! m->getInterval()->contains_interval(update[i]->key, + x->forward[i]->key)){ + newDemoted.insert(m->getInterval()); + } } // Remove newly demoted marks from edge. update[i]->markers[i]->removeAll(&newDemoted); @@ -867,26 +867,26 @@ template // Place previously demoted marks on this level as needed. for(m=demoted.get_first(); m!=nullptr; m=demoted.get_next(m)){ - // Place mark on level i from update[i+1] to update[i], not including - // update[i+1] itself, since it already has a mark if it needs one. - for(y=update[i+1]; y!=0 && y!=update[i]; y=y->forward[i]) { - if (y!=update[i+1] && m->getInterval()->contains(y->key)) - y->eqMarkers->insert(m->getInterval()); - y->markers[i]->insert(m->getInterval()); - } - if(y!=0 && y!=update[i+1] && m->getInterval()->contains(y->key)) - y->eqMarkers->insert(m->getInterval()); + // Place mark on level i from update[i+1] to update[i], not including + // update[i+1] itself, since it already has a mark if it needs one. + for(y=update[i+1]; y!=0 && y!=update[i]; y=y->forward[i]) { + if (y!=update[i+1] && m->getInterval()->contains(y->key)) + y->eqMarkers->insert(m->getInterval()); + y->markers[i]->insert(m->getInterval()); + } + if(y!=0 && y!=update[i+1] && m->getInterval()->contains(y->key)) + y->eqMarkers->insert(m->getInterval()); - // if this is the lowest level m needs to be placed on, - // then place m on the level i edge out of update[i] - // and remove m from the demoted set. - if(x->forward[i]!=0 && - m->getInterval()->contains_interval(update[i]->key, - x->forward[i]->key)) - { - update[i]->markers[i]->insert(m->getInterval()); - tempRemoved.insert(m->getInterval()); - } + // if this is the lowest level m needs to be placed on, + // then place m on the level i edge out of update[i] + // and remove m from the demoted set. + if(x->forward[i]!=0 && + m->getInterval()->contains_interval(update[i]->key, + x->forward[i]->key)) + { + update[i]->markers[i]->insert(m->getInterval()); + tempRemoved.insert(m->getInterval()); + } } demoted.removeAll(&tempRemoved); tempRemoved.clear(); @@ -895,36 +895,36 @@ template } // Phase 2: lower markers on edges to the right of D as needed - + demoted.clear(); // newDemoted is already empty for(i=x->level()-1; i>=0; i--){ for(m=x->markers[i]->get_first(); m!=nullptr ; m=x->markers[i]->get_next(m)){ - if(x->forward[i]!=0 && - (update[i]->isHeader() || - !m->getInterval()->contains_interval(update[i]->key, - x->forward[i]->key))) - { - newDemoted.insert(m->getInterval()); - } + if(x->forward[i]!=0 && + (update[i]->isHeader() || + !m->getInterval()->contains_interval(update[i]->key, + x->forward[i]->key))) + { + newDemoted.insert(m->getInterval()); + } } for(m=demoted.get_first(); m!= nullptr; m=demoted.get_next(m)){ - // Place mark on level i from x->forward[i] to x->forward[i+1]. - // Don't place a mark directly on x->forward[i+1] since it is already - // marked. - for(y=x->forward[i];y!=x->forward[i+1];y=y->forward[i]){ - y->eqMarkers->insert(m->getInterval()); - y->markers[i]->insert(m->getInterval()); - } + // Place mark on level i from x->forward[i] to x->forward[i+1]. + // Don't place a mark directly on x->forward[i+1] since it is already + // marked. + for(y=x->forward[i];y!=x->forward[i+1];y=y->forward[i]){ + y->eqMarkers->insert(m->getInterval()); + y->markers[i]->insert(m->getInterval()); + } - if(x->forward[i]!=0 && !update[i]->isHeader() && - m->getInterval()->contains_interval(update[i]->key, - x->forward[i]->key)) - { - tempRemoved.insert(m->getInterval()); - } + if(x->forward[i]!=0 && !update[i]->isHeader() && + m->getInterval()->contains_interval(update[i]->key, + x->forward[i]->key)) + { + tempRemoved.insert(m->getInterval()); + } } demoted.removeAll(&tempRemoved); demoted.copy(&newDemoted); @@ -945,8 +945,8 @@ template template bool Interval_skip_list::remove(const Interval& I) { - // arrays for maintaining update pointers - IntervalSLnode* update[MAX_FORWARD]; + // arrays for maintaining update pointers + IntervalSLnode* update[MAX_FORWARD]; IntervalSLnode* left = search(I.inf(),update); if(left==0 || left->ownerCount <= 0) { @@ -972,9 +972,9 @@ template } template - void - Interval_skip_list::remove(IntervalSLnode* x, - IntervalSLnode** update) + void + Interval_skip_list::remove(IntervalSLnode* x, + IntervalSLnode** update) { // Remove interval skip list node x. The markers that the interval // x belongs to have already been removed. @@ -991,13 +991,13 @@ template template - IntervalSLnode* + IntervalSLnode* Interval_skip_list::search(const Value& searchKey) { IntervalSLnode* x = header; for(int i=maxLevel; i >= 0; i--) { while (x->forward[i] != 0 && (x->forward[i]->key < searchKey)) { - x = x->forward[i]; + x = x->forward[i]; } } x = x->forward[0]; @@ -1008,16 +1008,16 @@ template } template - IntervalSLnode* - Interval_skip_list::search(const Value& searchKey, - IntervalSLnode** update) + IntervalSLnode* + Interval_skip_list::search(const Value& searchKey, + IntervalSLnode** update) { IntervalSLnode* x = header; // Find location of searchKey, building update vector indicating // pointers to change on insertion. for(int i=maxLevel; i >= 0; i--) { while (x->forward[i] != 0 && (x->forward[i]->key < searchKey)) { - x = x->forward[i]; + x = x->forward[i]; } update[i] = x; } @@ -1057,10 +1057,10 @@ template template - void - Interval_skip_list::placeMarkers(IntervalSLnode* left, - IntervalSLnode* right, - const Interval_handle& I) + void + Interval_skip_list::placeMarkers(IntervalSLnode* left, + IntervalSLnode* right, + const Interval_handle& I) { // Place markers for the interval I. left is the left endpoint // of I and right is the right endpoint of I, so it isn't necessary @@ -1071,45 +1071,45 @@ template int i = 0; // start at level 0 and go up while(x->forward[i]!=0 && I->contains_interval(x->key,x->forward[i]->key)){ // find level to put mark on - while(i!=x->level()-1 + while(i!=x->level()-1 && x->forward[i+1] != 0 && I->contains_interval(x->key,x->forward[i+1]->key)) - i++; + i++; // Mark current level i edge since it is the highest edge out of // x that contains I, except in the case where current level i edge // is null, in which case it should never be marked. - if (x->forward[i] != 0) { - x->markers[i]->insert(I); - x = x->forward[i]; - // Add I to eqMarkers set on node unless currently at right endpoint - // of I and I doesn't contain right endpoint. - if (I->contains(x->key)) x->eqMarkers->insert(I); + if (x->forward[i] != 0) { + x->markers[i]->insert(I); + x = x->forward[i]; + // Add I to eqMarkers set on node unless currently at right endpoint + // of I and I doesn't contain right endpoint. + if (I->contains(x->key)) x->eqMarkers->insert(I); } } // mark non-ascending path while(x->key != right->key) { // find level to put mark on - while(i!=0 && (x->forward[i] == 0 || - !I->contains_interval(x->key,x->forward[i]->key))) - i--; - // At this point, we can assert that i=0 or x->forward[i]!=0 and - // I contains - // (x->key,x->forward[i]->key). In addition, x is between left and + while(i!=0 && (x->forward[i] == 0 || + !I->contains_interval(x->key,x->forward[i]->key))) + i--; + // At this point, we can assert that i=0 or x->forward[i]!=0 and + // I contains + // (x->key,x->forward[i]->key). In addition, x is between left and // right so i=0 implies I contains (x->key,x->forward[i]->key). // Hence, the interval must be marked. Note that it is impossible // for us to be at the end of the list because x->key is not equal // to right->key. x->markers[i]->insert(I); x = x->forward[i]; - if (I->contains(x->key)) x->eqMarkers->insert(I); + if (I->contains(x->key)) x->eqMarkers->insert(I); } } // end placeMarkers template - typename Interval_skip_list::Interval_handle - Interval_skip_list::removeMarkers(IntervalSLnode* left, - const Interval& I) + typename Interval_skip_list::Interval_handle + Interval_skip_list::removeMarkers(IntervalSLnode* left, + const Interval& I) { // Remove markers for interval I, which has left as it's left // endpoint, following a staircase pattern. @@ -1120,55 +1120,55 @@ template IntervalSLnode* x = left; if (I.contains(x->key)) { if(x->eqMarkers->remove(I, tmp)){ - res = tmp; + res = tmp; } } int i = 0; // start at level 0 and go up while(x->forward[i]!=0 && I.contains_interval(x->key,x->forward[i]->key)) { // find level to take mark from - while(i!=x->level()-1 + while(i!=x->level()-1 && x->forward[i+1] != 0 && I.contains_interval(x->key,x->forward[i+1]->key)) - i++; + i++; // Remove mark from current level i edge since it is the highest edge out // of x that contains I, except in the case where current level i edge // is null, in which case there are no markers on it. - if (x->forward[i] != 0) { - if(x->markers[i]->remove(I, tmp)){ - res = tmp; - } - x = x->forward[i]; - // remove I from eqMarkers set on node unless currently at right - // endpoint of I and I doesn't contain right endpoint. - if (I.contains(x->key)){ - if(x->eqMarkers->remove(I, tmp)){ - res = tmp; - } - } + if (x->forward[i] != 0) { + if(x->markers[i]->remove(I, tmp)){ + res = tmp; + } + x = x->forward[i]; + // remove I from eqMarkers set on node unless currently at right + // endpoint of I and I doesn't contain right endpoint. + if (I.contains(x->key)){ + if(x->eqMarkers->remove(I, tmp)){ + res = tmp; + } + } } } // remove marks from non-ascending path while(x->key != I.sup()) { // find level to remove mark from - while(i!=0 && (x->forward[i] == 0 || - ! I.contains_interval(x->key,x->forward[i]->key))) - i--; - // At this point, we can assert that i=0 or x->forward[i]!=0 and - // I contains - // (x->key,x->forward[i]->key). In addition, x is between left and + while(i!=0 && (x->forward[i] == 0 || + ! I.contains_interval(x->key,x->forward[i]->key))) + i--; + // At this point, we can assert that i=0 or x->forward[i]!=0 and + // I contains + // (x->key,x->forward[i]->key). In addition, x is between left and // right so i=0 implies I contains (x->key,x->forward[i]->key). - // Hence, the interval is marked and the mark must be removed. - // Note that it is impossible for us to be at the end of the list + // Hence, the interval is marked and the mark must be removed. + // Note that it is impossible for us to be at the end of the list // because x->key is not equal to right->key. if(x->markers[i]->remove(I, tmp)){ - res = tmp; + res = tmp; } x = x->forward[i]; if (I.contains(x->key)){ - if(x->eqMarkers->remove(I, tmp)){ - res = tmp; - } + if(x->eqMarkers->remove(I, tmp)){ + res = tmp; + } } } CGAL_assertion(*res == I); @@ -1176,10 +1176,10 @@ template } template - void + void Interval_skip_list::removeMarkFromLevel(const Interval& m, int i, - IntervalSLnode *l, - IntervalSLnode* r) + IntervalSLnode *l, + IntervalSLnode* r) { IntervalSLnode *x; for(x=l; x!=0 && x!=r; x=x->forward[i]) { @@ -1196,7 +1196,7 @@ template { boost::geometric_distribution<> proba(0.5); boost::variate_generator > die(random, proba); - + return (std::min)(die(), (int)maxLevel)+1; } @@ -1219,24 +1219,24 @@ template os << "forward pointers:\n"; for(i=0; i<=topLevel; i++) { - os << "forward[" << i << "] = "; - if(forward[i] != nullptr) { - os << forward[i]->getValue(); - } else { - os << "nullptr"; - } - os << std::endl; + os << "forward[" << i << "] = "; + if(forward[i] != nullptr) { + os << forward[i]->getValue(); + } else { + os << "nullptr"; + } + os << std::endl; } os << "markers:\n"; for(i=0; i<=topLevel; i++) { - os << "markers[" << i << "] = "; - if(markers[i] != nullptr) { - markers[i]->print(os); - } else { - os << "nullptr"; - } - os << "\n"; + os << "markers[" << i << "] = "; + if(markers[i] != nullptr) { + markers[i]->print(os); + } else { + os << "nullptr"; + } + os << "\n"; } os << "EQ markers: "; eqMarkers->print(os); @@ -1263,7 +1263,7 @@ template while(x != nullptr && *(x->getInterval()) != I) { last = x; x = x->next; - } + } if(x==nullptr) { return false; } else if (last==nullptr) { @@ -1310,20 +1310,20 @@ template // We need the default constructor for the compact_container template - inline + inline IntervalListElt::IntervalListElt() : next(nullptr) {} template - inline + inline IntervalListElt::IntervalListElt(const Interval_handle& anInterval) : I(anInterval), next(nullptr) {} template - inline + inline IntervalListElt::~IntervalListElt() {} @@ -1338,7 +1338,7 @@ template template inline - + typename IntervalList::ILE_handle IntervalList::get_next(ILE_handle element) { @@ -1368,7 +1368,7 @@ template } template - inline + inline bool IntervalList::contains(const Interval_handle& I) const { ILE_handle x = header; diff --git a/Mesh_3/include/CGAL/Compact_mesh_cell_base_3.h b/Mesh_3/include/CGAL/Compact_mesh_cell_base_3.h index cea2e2405ba..0146470513f 100644 --- a/Mesh_3/include/CGAL/Compact_mesh_cell_base_3.h +++ b/Mesh_3/include/CGAL/Compact_mesh_cell_base_3.h @@ -208,7 +208,7 @@ public: { CGAL_precondition(facet>=0 && facet<4); char current_bits = bits_; - + while (!bits_.compare_exchange_weak(current_bits, current_bits | char(1 << facet))) { current_bits = bits_; @@ -319,7 +319,7 @@ public: #endif , surface_center_index_table_() , sliver_value_(FT(0.)) - , subdomain_index_() + , subdomain_index_() , sliver_cache_validity_(false) {} @@ -656,14 +656,14 @@ public: public: Cell_handle next_intrusive() const { return next_intrusive_; } void set_next_intrusive(Cell_handle c) - { - next_intrusive_ = c; + { + next_intrusive_ = c; } Cell_handle previous_intrusive() const { return previous_intrusive_; } void set_previous_intrusive(Cell_handle c) - { - previous_intrusive_ = c; + { + previous_intrusive_ = c; } #endif // CGAL_INTRUSIVE_LIST diff --git a/STL_Extension/benchmark/compact_container_benchmark/cc_benchmark.cpp b/STL_Extension/benchmark/compact_container_benchmark/cc_benchmark.cpp index 3158f09b096..4186c723d3e 100644 --- a/STL_Extension/benchmark/compact_container_benchmark/cc_benchmark.cpp +++ b/STL_Extension/benchmark/compact_container_benchmark/cc_benchmark.cpp @@ -77,7 +77,7 @@ class Change_array_functor > public: Change_array_functor(std::vector &v) : m_v(v) {} - + Change_array_functor(const Change_array_functor &caf) : m_v(caf.m_v) {} @@ -161,7 +161,7 @@ double change_array(Array_t &v, Sequential_with_forward_access_tag) CGAL::Real_timer t; t.start(); typename Array_t::iterator it = v.begin(), it_end = v.end(); - + for ( ; it != it_end ; ++it) compute_the_thing(*it); @@ -213,14 +213,14 @@ void benchmark(Array_t &v) double seq_time_random = change_array(v, Sequential_with_random_access_tag()); std::cout << "* Parallel_for algorithm => "; double parallel_for_time = change_array(v, Parallel_for_tag()); - std::cout << "Speed-up parallel_for (operator[]) = " + std::cout << "Speed-up parallel_for (operator[]) = " << seq_time_random/parallel_for_time << std::endl << std::endl; - + std::cout << "* Sequential algorithm (forward access) => "; double seq_time_fw = change_array(v, Sequential_with_forward_access_tag()); std::cout << "* Parallel_do algorithm => "; double parallel_do_time = change_array(v, Parallel_do_tag()); - std::cout << "Speed-up parallel_do (iterators) = " + std::cout << "Speed-up parallel_do (iterators) = " << seq_time_fw/parallel_do_time << std::endl << std::endl; } diff --git a/STL_Extension/doc/STL_Extension/CGAL/Compact_container.h b/STL_Extension/doc/STL_Extension/CGAL/Compact_container.h index b29bdf8887c..98a1af5ceb6 100644 --- a/STL_Extension/doc/STL_Extension/CGAL/Compact_container.h +++ b/STL_Extension/doc/STL_Extension/CGAL/Compact_container.h @@ -9,32 +9,32 @@ namespace CGAL { -The class `Compact_container_base` can be used as a base class for -your own type `T`, so that `T` can be used directly within -`Compact_container`. This class stores a `void *` -pointer only for this purpose, so it may not be the most memory efficient -way to achieve this goal. The other ways are to provide in `T` the -necessary member functions so that the template -`Compact_container_traits` works, or to specialize it for the -particular type `T` that you want to use. +The class `Compact_container_base` can be used as a base class for +your own type `T`, so that `T` can be used directly within +`Compact_container`. This class stores a `void *` +pointer only for this purpose, so it may not be the most memory efficient +way to achieve this goal. The other ways are to provide in `T` the +necessary member functions so that the template +`Compact_container_traits` works, or to specialize it for the +particular type `T` that you want to use. */ class Compact_container_base { public: -/// \name Operations -/// @{ +/// \name Operations +/// @{ /*! -Returns the pointer necessary for `Compact_container_traits`. -*/ -void * for_compact_container() const; +Returns the pointer necessary for `Compact_container_traits`. +*/ +void * for_compact_container() const; /*! Sets the pointer necessary for `Compact_container_traits` to `p`. -*/ +*/ void for_compact_container(void* p); -/// @} +/// @} @@ -46,81 +46,81 @@ namespace CGAL { /*! \ingroup CompactContainer -An object of the class `Compact_container` -is a container of objects of type `T`. +An object of the class `Compact_container` +is a container of objects of type `T`. -This container matches all the -standard requirements for reversible containers, except that -the complexity of its iterator increment and decrement operations -is not always guaranteed to be amortized constant time. +This container matches all the +standard requirements for reversible containers, except that +the complexity of its iterator increment and decrement operations +is not always guaranteed to be amortized constant time. -This container is not a standard sequence nor associative container, -which means the elements are stored in no particular order, and it is not -possible to specify a particular place in the iterator sequence where to -insert new objects. However, all dereferenceable iterators are -still valid after calls to `insert()` and `erase()`, except those -that have been erased (it behaves similarly to `std::list`). +This container is not a standard sequence nor associative container, +which means the elements are stored in no particular order, and it is not +possible to specify a particular place in the iterator sequence where to +insert new objects. However, all dereferenceable iterators are +still valid after calls to `insert()` and `erase()`, except those +that have been erased (it behaves similarly to `std::list`). -The main feature of this container is that it is very memory efficient: -its memory size is `N*sizeof(T)+o(N)`, where `N` is the maximum size -that the container has had in its past history, its `capacity()` -(the memory of erased elements is not deallocated until destruction of the -container or a call to `clear()`). This container has been developed in -order to store large graph-like data structures like the triangulation and -the halfedge data structures. +The main feature of this container is that it is very memory efficient: +its memory size is `N*sizeof(T)+o(N)`, where `N` is the maximum size +that the container has had in its past history, its `capacity()` +(the memory of erased elements is not deallocated until destruction of the +container or a call to `clear()`). This container has been developed in +order to store large graph-like data structures like the triangulation and +the halfedge data structures. -It supports bidirectional iterators and allows a constant time amortized -`insert()` operation. You cannot specify where to insert new objects -(i.e.\ you don't know where they will end up in the iterator sequence, -although `insert()` returns an iterator pointing to the newly inserted -object). You can erase any element with a constant time complexity. +It supports bidirectional iterators and allows a constant time amortized +`insert()` operation. You cannot specify where to insert new objects +(i.e.\ you don't know where they will end up in the iterator sequence, +although `insert()` returns an iterator pointing to the newly inserted +object). You can erase any element with a constant time complexity. -Summary of the differences with `std::list`: it is more compact in -memory since it doesn't store two additional pointers for the iterator needs. -It doesn't deallocate elements until the destruction or `clear()` of the -container. The iterator does not have constant amortized time complexity for -the increment and decrement operations in all cases, only when not too many -elements have not been freed (i.e.\ when the `size()` is close to the -`capacity()`). Iterating from `begin()` to `end()` takes -`O(capacity())` time, not `size()`. In the case where the container -has a small `size()` compared to its `capacity()`, we advise to -"defragment the memory" by copying the container if the iterator performance -is needed. +Summary of the differences with `std::list`: it is more compact in +memory since it doesn't store two additional pointers for the iterator needs. +It doesn't deallocate elements until the destruction or `clear()` of the +container. The iterator does not have constant amortized time complexity for +the increment and decrement operations in all cases, only when not too many +elements have not been freed (i.e.\ when the `size()` is close to the +`capacity()`). Iterating from `begin()` to `end()` takes +`O(capacity())` time, not `size()`. In the case where the container +has a small `size()` compared to its `capacity()`, we advise to +"defragment the memory" by copying the container if the iterator performance +is needed. -The iterators themselves can be used as `T`, they provide the necessary -functions to be used by `Compact_container_traits`. Moreover, they -also provide a default constructor value which is not singular: it is -copyable, comparable, and guaranteed to be unique under comparison -(like `nullptr` for pointers). This makes them suitable for use in -geometric graphs like handles to vertices in triangulations. +The iterators themselves can be used as `T`, they provide the necessary +functions to be used by `Compact_container_traits`. Moreover, they +also provide a default constructor value which is not singular: it is +copyable, comparable, and guaranteed to be unique under comparison +(like `nullptr` for pointers). This makes them suitable for use in +geometric graphs like handles to vertices in triangulations. -In addition, in a way inspired from the Boost.Intrusive containers, it is -possible to construct iterators from references to values in containers -using the `iterator_to` and `s_iterator_to` functions. +In addition, in a way inspired from the Boost.Intrusive containers, it is +possible to construct iterators from references to values in containers +using the `iterator_to` and `s_iterator_to` functions. -The objects stored in the `Compact_container` can optionally store an +The objects stored in the `Compact_container` can optionally store an "erase counter". If it exists, i.e.\ if the object is a model of the -`ObjectWithEraseCounter` concept, each time an object is erased from the +`ObjectWithEraseCounter` concept, each time an object is erased from the container, the erase counter of the object will be incremented. -For example, this erase counter can be exploited using the `CC_safe_handle` +For example, this erase counter can be exploited using the `CC_safe_handle` helper class, so that one can know if a handle is still pointing to the same element. -Note that this is meaningful only because the -`CGAL::Compact_container` doesn't +Note that this is meaningful only because the +`CGAL::Compact_container` doesn't deallocate elements until the destruction or clear() of the container. \cgalHeading{Parameters} -The parameter `T` is required to have a copy constructor and an -assignment operator. It also needs to provide access to an internal -pointer via `Compact_container_traits`. +The parameter `T` is required to have a copy constructor and an +assignment operator. It also needs to provide access to an internal +pointer via `Compact_container_traits`. -The equality test and the relational order require the operators -`==` and `<` for `T` respectively. +The equality test and the relational order require the operators +`==` and `<` for `T` respectively. -The parameter `Allocator` has to match the standard allocator -requirements, with value type `T`. This parameter has the default -value `CGAL_ALLOCATOR(T)`. +The parameter `Allocator` has to match the standard allocator +requirements, with value type `T`. This parameter has the default +value `CGAL_ALLOCATOR(T)`. */ template< typename T, typename Allocator > @@ -128,388 +128,388 @@ class Compact_container { public: -/// \name Types -/// @{ +/// \name Types +/// @{ /*! -*/ -typedef unspecified_type value_type; -/// @} +*/ +typedef unspecified_type value_type; +/// @} -/// \name Types -/// @{ +/// \name Types +/// @{ /*! -*/ -typedef unspecified_type reference; -/// @} +*/ +typedef unspecified_type reference; +/// @} -/// \name Types -/// @{ +/// \name Types +/// @{ /*! -*/ -typedef unspecified_type const_reference; -/// @} +*/ +typedef unspecified_type const_reference; +/// @} -/// \name Types -/// @{ +/// \name Types +/// @{ /*! -*/ -typedef unspecified_type pointer; -/// @} +*/ +typedef unspecified_type pointer; +/// @} -/// \name Types -/// @{ +/// \name Types +/// @{ /*! -*/ -typedef unspecified_type const_pointer; -/// @} +*/ +typedef unspecified_type const_pointer; +/// @} -/// \name Types -/// @{ +/// \name Types +/// @{ /*! -*/ -typedef unspecified_type size_type; -/// @} +*/ +typedef unspecified_type size_type; +/// @} -/// \name Types -/// @{ +/// \name Types +/// @{ /*! -*/ -typedef unspecified_type difference_type; -/// @} +*/ +typedef unspecified_type difference_type; +/// @} -/// \name Types -/// @{ +/// \name Types +/// @{ /*! -*/ -typedef unspecified_type iterator; -/// @} +*/ +typedef unspecified_type iterator; +/// @} -/// \name Types -/// @{ +/// \name Types +/// @{ /*! -*/ -typedef unspecified_type const_iterator; -/// @} +*/ +typedef unspecified_type const_iterator; +/// @} -/// \name Types -/// @{ +/// \name Types +/// @{ /*! -*/ -typedef unspecified_type reverse_iterator; -/// @} +*/ +typedef unspecified_type reverse_iterator; +/// @} -/// \name Types -/// @{ +/// \name Types +/// @{ /*! -*/ -typedef unspecified_type const_reverse_iterator; -/// @} +*/ +typedef unspecified_type const_reverse_iterator; +/// @} -/// \name Types -/// @{ +/// \name Types +/// @{ /*! -*/ -typedef unspecified_type allocator_type; -/// @} +*/ +typedef unspecified_type allocator_type; +/// @} -/// \name Creation -/// @{ +/// \name Creation +/// @{ /*! -introduces an empty container `cc`, eventually specifying a particular -allocator `a` as well. -*/ -explicit Compact_container(const Allocator &a = Allocator()); +introduces an empty container `cc`, eventually specifying a particular +allocator `a` as well. +*/ +explicit Compact_container(const Allocator &a = Allocator()); -/// @} +/// @} -/// \name Creation -/// @{ +/// \name Creation +/// @{ /*! -a container with copies from the range [`first,last`), eventually -specifying a particular allocator. -*/ -template Compact_container( -InputIterator first, InputIterator last, -const Allocator &a = Allocator()); +a container with copies from the range [`first,last`), eventually +specifying a particular allocator. +*/ +template Compact_container( +InputIterator first, InputIterator last, +const Allocator &a = Allocator()); -/// @} +/// @} -/// \name Creation -/// @{ +/// \name Creation +/// @{ /*! -copy constructor. Each item in `cc2` is copied. The allocator -is copied. The iterator order is preserved. -*/ -Compact_container(const Compact_container &cc2); +copy constructor. Each item in `cc2` is copied. The allocator +is copied. The iterator order is preserved. +*/ +Compact_container(const Compact_container &cc2); -/// @} +/// @} -/// \name Creation -/// @{ +/// \name Creation +/// @{ /*! -assignment. Each item in `cc2` is copied. The allocator is copied. -Each item in `c` is deleted. The iterator order is preserved. -*/ -Compact_container & operator=(const -Compact_container &cc2); +assignment. Each item in `cc2` is copied. The allocator is copied. +Each item in `c` is deleted. The iterator order is preserved. +*/ +Compact_container & operator=(const +Compact_container &cc2); -/// @} +/// @} -/// \name Creation -/// @{ +/// \name Creation +/// @{ /*! -swaps the contents of `cc` and `cc2` in constant time -complexity. No exception is thrown. -*/ -void swap(Compact_container &cc2); +swaps the contents of `cc` and `cc2` in constant time +complexity. No exception is thrown. +*/ +void swap(Compact_container &cc2); -/// @} +/// @} -/// \name Creation -/// @{ +/// \name Creation +/// @{ /*! -if `value` is less than or equal to `capacity()`, this call -has no effect. Otherwise, it is a request for allocation of -additional memory so that then `capacity()` is greater than or -equal to value. `size()` is unchanged. -*/ -void reserve(size_type value); +if `value` is less than or equal to `capacity()`, this call +has no effect. Otherwise, it is a request for allocation of +additional memory so that then `capacity()` is greater than or +equal to value. `size()` is unchanged. +*/ +void reserve(size_type value); -/// @} +/// @} -/// \name Access Member Functions -/// @{ +/// \name Access Member Functions +/// @{ /*! -returns a mutable iterator referring to the first element in `cc`. -*/ -iterator begin(); +returns a mutable iterator referring to the first element in `cc`. +*/ +iterator begin(); -/// @} +/// @} -/// \name Access Member Functions -/// @{ +/// \name Access Member Functions +/// @{ /*! -returns a constant iterator referring to the first element in `cc`. -*/ -const_iterator begin() const; +returns a constant iterator referring to the first element in `cc`. +*/ +const_iterator begin() const; -/// @} +/// @} -/// \name Access Member Functions -/// @{ +/// \name Access Member Functions +/// @{ /*! -returns a mutable iterator which is the past-end-value of `cc`. -*/ -iterator end(); +returns a mutable iterator which is the past-end-value of `cc`. +*/ +iterator end(); -/// @} +/// @} -/// \name Access Member Functions -/// @{ +/// \name Access Member Functions +/// @{ /*! -returns a constant iterator which is the past-end-value of `cc`. -*/ -const_iterator end() const; +returns a constant iterator which is the past-end-value of `cc`. +*/ +const_iterator end() const; -/// @} +/// @} -/// \name Access Member Functions -/// @{ +/// \name Access Member Functions +/// @{ /*! -*/ -reverse_iterator rbegin(); +*/ +reverse_iterator rbegin(); -/// @} +/// @} -/// \name Access Member Functions -/// @{ +/// \name Access Member Functions +/// @{ /*! -*/ -const_reverse_iterator rbegin() const; +*/ +const_reverse_iterator rbegin() const; -/// @} +/// @} -/// \name Access Member Functions -/// @{ +/// \name Access Member Functions +/// @{ /*! -*/ -reverse_iterator rend(); +*/ +reverse_iterator rend(); -/// @} +/// @} -/// \name Access Member Functions -/// @{ +/// \name Access Member Functions +/// @{ /*! -*/ -const_reverse_iterator rend() const; +*/ +const_reverse_iterator rend() const; -/// @} +/// @} -/// \name Access Member Functions -/// @{ +/// \name Access Member Functions +/// @{ /*! -returns an iterator which points to `value`. -*/ -iterator iterator_to(reference value) const; +returns an iterator which points to `value`. +*/ +iterator iterator_to(reference value) const; -/// @} +/// @} -/// \name Access Member Functions -/// @{ +/// \name Access Member Functions +/// @{ /*! -returns an iterator which points to `value`. -*/ -const_iterator iterator_to(const_reference value) const; +returns an iterator which points to `value`. +*/ +const_iterator iterator_to(const_reference value) const; -/// @} +/// @} -/// \name Access Member Functions -/// @{ +/// \name Access Member Functions +/// @{ /*! -returns an iterator which points to `value`; -*/ -static iterator s_iterator_to(reference value); +returns an iterator which points to `value`; +*/ +static iterator s_iterator_to(reference value); -/// @} +/// @} -/// \name Access Member Functions -/// @{ +/// \name Access Member Functions +/// @{ /*! -returns an iterator which points to `value`; -*/ -static const_iterator s_iterator_to(const_reference value); +returns an iterator which points to `value`; +*/ +static const_iterator s_iterator_to(const_reference value); -/// @} +/// @} -/// \name Access Member Functions -/// @{ +/// \name Access Member Functions +/// @{ /*! -returns `true` iff `cc` is empty. -*/ -bool empty() const; +returns `true` iff `cc` is empty. +*/ +bool empty() const; -/// @} +/// @} -/// \name Access Member Functions -/// @{ +/// \name Access Member Functions +/// @{ /*! -returns the number of items in `cc`. -*/ -size_type size() const; +returns the number of items in `cc`. +*/ +size_type size() const; -/// @} +/// @} -/// \name Access Member Functions -/// @{ +/// \name Access Member Functions +/// @{ /*! returns the maximum possible size of the container `cc`. This is the allocator's max_size value. -*/ -size_type max_size() const; +*/ +size_type max_size() const; -/// @} - - -/// \name Access Member Functions -/// @{ -/*! -returns the total number of elements that `cc` can hold without requiring -reallocation. -*/ -size_type capacity() const; /// @} -/// \name Access Member Functions -/// @{ + +/// \name Access Member Functions +/// @{ +/*! +returns the total number of elements that `cc` can hold without requiring +reallocation. +*/ +size_type capacity() const; +/// @} + +/// \name Access Member Functions +/// @{ /*! returns true if the element `pos` is used (i.e.\ valid). @@ -525,243 +525,243 @@ returns true if the element at position `i` in the container is used bool is_used(size_type i) const; -/// @} +/// @} -/// \name Access Member Functions -/// @{ +/// \name Access Member Functions +/// @{ /*! -returns the element at pos `i` in the container. +returns the element at pos `i` in the container. \pre `is_used(i) == true` and \f$ 0 \leq \f$ `i` \f$ < \f$ `capacity()` -*/ +*/ const T& operator[] (size_type i) const; /// @} -/// \name Access Member Functions -/// @{ +/// \name Access Member Functions +/// @{ /*! -returns the element at pos `i` in the container. +returns the element at pos `i` in the container. \pre `is_used(i) == true` and \f$ 0 \leq \f$ `i` \f$ < \f$ `capacity()` -*/ +*/ T& operator[] (size_type i); -/// @} +/// @} -/// \name Access Member Functions -/// @{ +/// \name Access Member Functions +/// @{ /*! -returns the allocator. -*/ -Allocator get_allocator() const; +returns the allocator. +*/ +Allocator get_allocator() const; -/// @} +/// @} -/// \name Insertion -/// @{ +/// \name Insertion +/// @{ /*! -inserts a copy of `t` in `cc` and returns the iterator pointing -to it. -*/ -iterator insert(const T& t); +inserts a copy of `t` in `cc` and returns the iterator pointing +to it. +*/ +iterator insert(const T& t); -/// @} +/// @} -/// \name Insertion -/// @{ +/// \name Insertion +/// @{ /*! -inserts the range [`first, last`) in `cc`. -*/ -template -void insert(InputIterator first, InputIterator last); +inserts the range [`first, last`) in `cc`. +*/ +template +void insert(InputIterator first, InputIterator last); -/// @} +/// @} -/// \name Insertion -/// @{ +/// \name Insertion +/// @{ /*! -erases all the elements of `cc`, then inserts the range -[`first, last`) in `cc`. -*/ -template -void assign(InputIterator first, InputIterator last); +erases all the elements of `cc`, then inserts the range +[`first, last`) in `cc`. +*/ +template +void assign(InputIterator first, InputIterator last); -/// @} +/// @} -/// \name Insertion -/// @{ +/// \name Insertion +/// @{ /*! -constructs an object of type `T` with the constructor that takes -`t1` as argument, inserts it in `cc`, and returns the iterator pointing -to it. Overloads of this member function are defined that take additional -arguments, up to 9. -*/ -template < class T1 > -iterator emplace(const T1& t1); +constructs an object of type `T` with the constructor that takes +`t1` as argument, inserts it in `cc`, and returns the iterator pointing +to it. Overloads of this member function are defined that take additional +arguments, up to 9. +*/ +template < class T1 > +iterator emplace(const T1& t1); -/// @} +/// @} -/// \name Removal -/// @{ +/// \name Removal +/// @{ /*! -removes the item pointed by `pos` from `cc`. -*/ -void erase(iterator pos); +removes the item pointed by `pos` from `cc`. +*/ +void erase(iterator pos); -/// @} +/// @} -/// \name Removal -/// @{ +/// \name Removal +/// @{ /*! -removes the items from the range [`first, last`) from `cc`. -*/ -void erase(iterator first, iterator last); +removes the items from the range [`first, last`) from `cc`. +*/ +void erase(iterator first, iterator last); -/// @} +/// @} -/// \name Removal -/// @{ +/// \name Removal +/// @{ /*! -all items in `cc` are deleted, and the memory is deallocated. -After this call, `cc` is in the same state as if just default -constructed. -*/ -void clear(); +all items in `cc` are deleted, and the memory is deallocated. +After this call, `cc` is in the same state as if just default +constructed. +*/ +void clear(); -/// @} +/// @} -/// \name Ownership testing -/// The following functions are mostly helpful for efficient debugging, since -/// their complexity is \f$ O(\sqrt{\mathrm{c.capacity()}})\f$. -/// @{ +/// \name Ownership testing +/// The following functions are mostly helpful for efficient debugging, since +/// their complexity is \f$ O(\sqrt{\mathrm{c.capacity()}})\f$. +/// @{ /*! * returns whether `pos` is in the range `[cc.begin(), cc.end()]` (`cc.end()` included). - */ -bool owns(const_iterator pos); + */ +bool owns(const_iterator pos); /*! - * returns whether `pos` is in the range `[cc.begin(), cc`.end())` (`cc.end()` excluded). - */ -bool owns_dereferencable(const_iterator pos); + * returns whether `pos` is in the range `[cc.begin(), cc`.end())` (`cc.end()` excluded). + */ +bool owns_dereferencable(const_iterator pos); -/// @} +/// @} -/// \name Merging -/// @{ +/// \name Merging +/// @{ /*! -adds the items of `cc2` to the end of `cc` and `cc2` becomes empty. -The time complexity is O(`cc`.`capacity()`-`cc`.`size()`). -\pre `cc2` must not be the same as `cc`, and the allocators of `cc` and `cc2` must be compatible: `cc.get_allocator() == cc2.get_allocator()`. -*/ -void merge(Compact_container &cc); +adds the items of `cc2` to the end of `cc` and `cc2` becomes empty. +The time complexity is O(`cc`.`capacity()`-`cc`.`size()`). +\pre `cc2` must not be the same as `cc`, and the allocators of `cc` and `cc2` must be compatible: `cc.get_allocator() == cc2.get_allocator()`. +*/ +void merge(Compact_container &cc); -/// @} +/// @} -/// \name Comparison Operations -/// @{ +/// \name Comparison Operations +/// @{ /*! -test for equality: Two containers are equal, iff they have the -same size and if their corresponding elements are equal. -*/ -bool operator==(const Compact_container &cc) const; +test for equality: Two containers are equal, iff they have the +same size and if their corresponding elements are equal. +*/ +bool operator==(const Compact_container &cc) const; -/// @} +/// @} -/// \name Comparison Operations -/// @{ +/// \name Comparison Operations +/// @{ /*! -test for inequality: returns `!(c == cc)`. -*/ -bool operator!=(const Compact_container &cc) const; +test for inequality: returns `!(c == cc)`. +*/ +bool operator!=(const Compact_container &cc) const; -/// @} +/// @} -/// \name Comparison Operations -/// @{ +/// \name Comparison Operations +/// @{ /*! -compares in lexicographical order. -*/ -bool operator<(const Compact_container &cc2) const; +compares in lexicographical order. +*/ +bool operator<(const Compact_container &cc2) const; -/// @} +/// @} -/// \name Comparison Operations -/// @{ +/// \name Comparison Operations +/// @{ /*! -returns `cc2 (const Compact_container &cc2) const; +returns `cc2 (const Compact_container &cc2) const; -/// @} +/// @} -/// \name Comparison Operations -/// @{ +/// \name Comparison Operations +/// @{ /*! - returns `!(cc > cc2)`. -*/ -bool operator<=(const Compact_container &cc2) const; + returns `!(cc > cc2)`. +*/ +bool operator<=(const Compact_container &cc2) const; -/// @} +/// @} -/// \name Comparison Operations -/// @{ +/// \name Comparison Operations +/// @{ /*! -returns `!(cc < cc2)`. -*/ -bool operator>=(const Compact_container &cc2) const; +returns `!(cc < cc2)`. +*/ +bool operator>=(const Compact_container &cc2) const; -/// @} +/// @} @@ -775,68 +775,68 @@ namespace CGAL { -The traits class `Compact_container_traits` provides -the way to access the internal pointer required for `T` to be -used in a `Compact_container`. Note that this -pointer needs to be accessible even when the object is not constructed, -which means it has to reside in the same memory place as `T`. +The traits class `Compact_container_traits` provides +the way to access the internal pointer required for `T` to be +used in a `Compact_container`. Note that this +pointer needs to be accessible even when the object is not constructed, +which means it has to reside in the same memory place as `T`. -You can specialize this class for your own type `T` -if the default template is not suitable. +You can specialize this class for your own type `T` +if the default template is not suitable. -You can also use `Compact_container_base` as base class for your own -types `T` to make them usable with the default `Compact_container_traits`. +You can also use `Compact_container_base` as base class for your own +types `T` to make them usable with the default `Compact_container_traits`. \cgalHeading{Parameters} -`T` is any type providing the following member functions: +`T` is any type providing the following member functions: -`void * t.for_compact_container() const;` +`void * t.for_compact_container() const;` -`void t.for_compact_container(void *);`. +`void t.for_compact_container(void *);`. */ template< typename T > struct Compact_container_traits { -/// \name Operations -/// @{ +/// \name Operations +/// @{ /*! -Returns the pointer held by `t`. +Returns the pointer held by `t`. The template version defines this function as: `return t.for_compact_container(); ` -*/ -static void * pointer(const T &t); +*/ +static void * pointer(const T &t); -/// @} +/// @} -/// \name Operations -/// @{ +/// \name Operations +/// @{ /*! -Sets the pointer held by `t` to `p`. -The template version defines this function as: `t.for_compact_container(p);` +Sets the pointer held by `t` to `p`. +The template version defines this function as: `t.for_compact_container(p);` -*/ - static void set_pointer(T &t, void* p); +*/ + static void set_pointer(T &t, void* p); -/// @} +/// @} }; /* end Compact_container_traits */ /*! -returns a hash value for the pointee of `i`. +returns a hash value for the pointee of `i`. \relates Compact_container -*/ +*/ template std::size_t hash_value(const Compact_container::iterator i); diff --git a/STL_Extension/doc/STL_Extension/CGAL/Concurrent_compact_container.h b/STL_Extension/doc/STL_Extension/CGAL/Concurrent_compact_container.h index 8f55b19bb7f..65e853f489a 100644 --- a/STL_Extension/doc/STL_Extension/CGAL/Concurrent_compact_container.h +++ b/STL_Extension/doc/STL_Extension/CGAL/Concurrent_compact_container.h @@ -6,47 +6,47 @@ namespace CGAL { /*! \ingroup CompactContainer -The traits class `Concurrent_compact_container_traits` provides -the way to access the internal pointer required for `T` to be -used in a `Concurrent_compact_container`. Note that this -pointer needs to be accessible even when the object is not constructed, -which means it has to reside in the same memory place as `T`. +The traits class `Concurrent_compact_container_traits` provides +the way to access the internal pointer required for `T` to be +used in a `Concurrent_compact_container`. Note that this +pointer needs to be accessible even when the object is not constructed, +which means it has to reside in the same memory place as `T`. -You can specialize this class for your own type `T` -if the default template is not suitable. +You can specialize this class for your own type `T` +if the default template is not suitable. -You can also use `Compact_container_base` as base class for your own -types `T` to make them usable with the default `Concurrent_compact_container`. +You can also use `Compact_container_base` as base class for your own +types `T` to make them usable with the default `Concurrent_compact_container`. \cgalHeading{Parameters} -`T` is any type providing the following member functions: -`void * t.for_compact_container() const;` +`T` is any type providing the following member functions: +`void * t.for_compact_container() const;` `void t.for_compact_container(void *);`. */ template< typename T > struct Concurrent_compact_container_traits { -/// \name Operations -/// @{ - /*! - Returns the pointer held by `t`. - The template version defines this function as: `return t.for_compact_container(); - */ - static void * pointer(const T &t); +/// \name Operations +/// @{ + /*! + Returns the pointer held by `t`. + The template version defines this function as: `return t.for_compact_container(); + */ + static void * pointer(const T &t); -/// @} +/// @} -/// \name Operations -/// @{ - /*! +/// \name Operations +/// @{ + /*! Sets the pointer held by `t` to `p`. The template version defines this function as: `t.for_compact_container(p);` - */ + */ static void set_pointer(T &t, void* p); -/// @} +/// @} }; /* end Concurrent_compact_container_traits */ @@ -54,82 +54,82 @@ struct Concurrent_compact_container_traits { /*! \ingroup CompactContainer -An object of the class `Concurrent_compact_container` +An object of the class `Concurrent_compact_container` is a container of objects of type `T`, which allows to call `insert` and `erase` operations concurrently. Other operations are not concurrency-safe. For example, one should not parse the container while others are modifying it. -It matches all the -standard requirements for reversible containers, except that -the complexity of its iterator increment and decrement operations -is not always guaranteed to be amortized constant time. +It matches all the +standard requirements for reversible containers, except that +the complexity of its iterator increment and decrement operations +is not always guaranteed to be amortized constant time. -This container is not a standard sequence nor associative container, -which means the elements are stored in no particular order, and it is not -possible to specify a particular place in the iterator sequence where to -insert new objects. However, all dereferenceable iterators are -still valid after calls to `insert()` and `erase()`, except those -that have been erased (it behaves similarly to `std::list`). +This container is not a standard sequence nor associative container, +which means the elements are stored in no particular order, and it is not +possible to specify a particular place in the iterator sequence where to +insert new objects. However, all dereferenceable iterators are +still valid after calls to `insert()` and `erase()`, except those +that have been erased (it behaves similarly to `std::list`). -The main feature of this container is that it is very memory efficient: -its memory size is `N*sizeof(T)+o(N)`, where `N` is the maximum size -that the container has had in its past history, its `capacity()` -(the memory of erased elements is not deallocated until destruction of the -container or a call to `clear()`). This container has been developed in -order to store large graph-like data structures like the triangulation and -the halfedge data structures. +The main feature of this container is that it is very memory efficient: +its memory size is `N*sizeof(T)+o(N)`, where `N` is the maximum size +that the container has had in its past history, its `capacity()` +(the memory of erased elements is not deallocated until destruction of the +container or a call to `clear()`). This container has been developed in +order to store large graph-like data structures like the triangulation and +the halfedge data structures. -It supports bidirectional iterators and allows a constant time amortized -`insert()` operation. You cannot specify where to insert new objects -(i.e.\ you don't know where they will end up in the iterator sequence, -although `insert()` returns an iterator pointing to the newly inserted -object). You can erase any element with a constant time complexity. +It supports bidirectional iterators and allows a constant time amortized +`insert()` operation. You cannot specify where to insert new objects +(i.e.\ you don't know where they will end up in the iterator sequence, +although `insert()` returns an iterator pointing to the newly inserted +object). You can erase any element with a constant time complexity. -Summary of the differences with `std::list`: it is more compact in -memory since it doesn't store two additional pointers for the iterator needs. -It doesn't deallocate elements until the destruction or `clear()` of the -container. The iterator does not have constant amortized time complexity for -the increment and decrement operations in all cases, only when not too many -elements have not been freed (i.e.\ when the `size()` is close to the -`capacity()`). Iterating from `begin()` to `end()` takes -`O(capacity())` time, not `size()`. In the case where the container -has a small `size()` compared to its `capacity()`, we advise to -\"defragment the memory\" by copying the container if the iterator performance -is needed. +Summary of the differences with `std::list`: it is more compact in +memory since it doesn't store two additional pointers for the iterator needs. +It doesn't deallocate elements until the destruction or `clear()` of the +container. The iterator does not have constant amortized time complexity for +the increment and decrement operations in all cases, only when not too many +elements have not been freed (i.e.\ when the `size()` is close to the +`capacity()`). Iterating from `begin()` to `end()` takes +`O(capacity())` time, not `size()`. In the case where the container +has a small `size()` compared to its `capacity()`, we advise to +\"defragment the memory\" by copying the container if the iterator performance +is needed. -The iterators themselves can be used as `T`, they provide the necessary -functions to be used by `Compact_container_traits`. Moreover, they -also provide a default constructor value which is not singular: it is -copyable, comparable, and guaranteed to be unique under comparison -(like `NULL` for pointers). This makes them suitable for use in -geometric graphs like handles to vertices in triangulations. +The iterators themselves can be used as `T`, they provide the necessary +functions to be used by `Compact_container_traits`. Moreover, they +also provide a default constructor value which is not singular: it is +copyable, comparable, and guaranteed to be unique under comparison +(like `NULL` for pointers). This makes them suitable for use in +geometric graphs like handles to vertices in triangulations. -In addition, in a way inspired from the Boost.Intrusive containers, it is -possible to construct iterators from references to values in containers -using the `iterator_to` and `s_iterator_to` functions. +In addition, in a way inspired from the Boost.Intrusive containers, it is +possible to construct iterators from references to values in containers +using the `iterator_to` and `s_iterator_to` functions. -The objects stored in the `Concurrent_compact_container` can optionally store an +The objects stored in the `Concurrent_compact_container` can optionally store an "erase counter". If it exists, i.e.\ if the object is a model of the -`ObjectWithEraseCounter` concept, each time an object is erased from the +`ObjectWithEraseCounter` concept, each time an object is erased from the container, the erase counter of the object will be incremented. -For example, this erase counter can be exploited using the `CC_safe_handle` +For example, this erase counter can be exploited using the `CC_safe_handle` helper class, so that one can know if a handle is still pointing to the same element. -Note that this is meaningful only because the -`CGAL::Concurrent_compact_container` doesn't +Note that this is meaningful only because the +`CGAL::Concurrent_compact_container` doesn't deallocate elements until the destruction or clear() of the container. \cgalHeading{Parameters} -The parameter `T` is required to have a copy constructor and an -assignment operator. It also needs to provide access to an internal -pointer via `Compact_container_traits`. +The parameter `T` is required to have a copy constructor and an +assignment operator. It also needs to provide access to an internal +pointer via `Compact_container_traits`. -The equality test and the relational order require the operators -`==` and `<` for `T` respectively. +The equality test and the relational order require the operators +`==` and `<` for `T` respectively. -The parameter `Allocator` has to match the standard allocator -requirements, with value type `T`. This parameter has the default +The parameter `Allocator` has to match the standard allocator +requirements, with value type `T`. This parameter has the default value `CGAL_ALLOCATOR(T)`. */ @@ -138,8 +138,8 @@ template < class T, class Allocator > class Concurrent_compact_container { public: -/// \name Types -/// @{ +/// \name Types +/// @{ typedef unspecified_type value_type; typedef unspecified_type allocator_type; typedef unspecified_type reference; @@ -152,48 +152,48 @@ public: typedef unspecified_type const_iterator; typedef unspecified_type reverse_iterator; typedef unspecified_type const_reverse_iterator; -/// @} +/// @} -/// \name Creation -/// @{ -/*! -introduces an empty container `ccc`, eventually specifying a particular -allocator `a` as well. -*/ +/// \name Creation +/// @{ +/*! +introduces an empty container `ccc`, eventually specifying a particular +allocator `a` as well. +*/ explicit Concurrent_compact_container(const Allocator &a = Allocator()); -/*! -a container with copies from the range [`first,last`), eventually -specifying a particular allocator. -*/ +/*! +a container with copies from the range [`first,last`), eventually +specifying a particular allocator. +*/ template < class InputIterator > Concurrent_compact_container(InputIterator first, InputIterator last, const Allocator & a = Allocator()); -/*! -copy constructor. Each item in `ccc2` is copied. The allocator -is copied. The iterator order is preserved. -*/ +/*! +copy constructor. Each item in `ccc2` is copied. The allocator +is copied. The iterator order is preserved. +*/ // The copy constructor and assignment operator preserve the iterator order Concurrent_compact_container(const Concurrent_compact_container &ccc2); - -/*! -assignment. Each item in `ccc2` is copied. The allocator is copied. -Each item in `ccc` is deleted. The iterator order is preserved. -*/ + +/*! +assignment. Each item in `ccc2` is copied. The allocator is copied. +Each item in `ccc` is deleted. The iterator order is preserved. +*/ Concurrent_compact_container & operator=(const Concurrent_compact_container &ccc2); -/*! -swaps the contents of `ccc` and `ccc2` in constant time -complexity. No exception is thrown. -*/ +/*! +swaps the contents of `ccc` and `ccc2` in constant time +complexity. No exception is thrown. +*/ void swap(Self &ccc2); - -/// @} -/// \name Access Member Functions -/// @{ +/// @} + +/// \name Access Member Functions +/// @{ /*! returns true if the element `pos` is used (i.e.\ valid). @@ -206,16 +206,16 @@ complexity. No exception is thrown. const_iterator begin() const; /// returns a mutable iterator which is the past-end-value of `ccc`. iterator end(); - /// returns a constant iterator which is the past-end-value of `ccc`. + /// returns a constant iterator which is the past-end-value of `ccc`. const_iterator end(); - /// returns a mutable reverse iterator referring to the reverse beginning in `ccc`. + /// returns a mutable reverse iterator referring to the reverse beginning in `ccc`. reverse_iterator rbegin(); /// returns a constant reverse iterator referring to the reverse beginning in `ccc`. const_reverse_iterator rbegin() const; /// returns a mutable reverse iterator which is the reverse past-end-value of `ccc`. reverse_iterator rend(); - /// returns a constant reverse iterator which is the reverse past-end-value of `ccc`. + /// returns a constant reverse iterator which is the reverse past-end-value of `ccc`. const_reverse_iterator rend() const; /// returns an iterator which points to `value`. @@ -227,106 +227,106 @@ complexity. No exception is thrown. /// returns a constant iterator which points to `value`. static const_iterator s_iterator_to(const_reference value); - /// returns `true` iff `ccc` is empty. + /// returns `true` iff `ccc` is empty. bool empty() const; - /// returns the number of items in `ccc`. + /// returns the number of items in `ccc`. /// Note: do not call this function while others are inserting/erasing elements size_type size() const; /// returns the maximum possible size of the container `ccc`. /// This is the allocator's max_size value - size_type max_size() const; - /// returns the total number of elements that `ccc` can hold without requiring reallocation. + size_type max_size() const; + /// returns the total number of elements that `ccc` can hold without requiring reallocation. size_type capacity() const; /// returns the allocator - Allocator get_allocator() const; + Allocator get_allocator() const; -/// @} +/// @} -/// \name Insertion -/// @{ - /*! - constructs an object of type `T` with the constructor that takes - `t1` as argument, inserts it in `ccc`, and returns the iterator pointing - to it. Overloads of this member function are defined that take additional - arguments, up to 9. - */ - template < class T1 > - iterator emplace(const T1& t1); - - /*! - inserts a copy of `t` in `ccc` and returns the iterator pointing - to it. - */ +/// \name Insertion +/// @{ + /*! + constructs an object of type `T` with the constructor that takes + `t1` as argument, inserts it in `ccc`, and returns the iterator pointing + to it. Overloads of this member function are defined that take additional + arguments, up to 9. + */ + template < class T1 > + iterator emplace(const T1& t1); + + /*! + inserts a copy of `t` in `ccc` and returns the iterator pointing + to it. + */ iterator insert(const T &t); /// inserts the range [`first, last`) in `ccc`. template < class InputIterator > void insert(InputIterator first, InputIterator last); - /*! - erases all the elements of `ccc`, then inserts the range - [`first, last`) in `ccc`. + /*! + erases all the elements of `ccc`, then inserts the range + [`first, last`) in `ccc`. */ template < class InputIterator > void assign(InputIterator first, InputIterator last); -/// @} +/// @} -/// \name Removal +/// \name Removal /// @{ /// removes the item pointed by `pos` from `ccc`. void erase(iterator x); /// removes the items from the range [`first, last`) from `ccc`. void erase(iterator first, iterator last); - /*! - all items in `ccc` are deleted, and the memory is deallocated. - After this call, `ccc` is in the same state as if just default - constructed. - */ + /*! + all items in `ccc` are deleted, and the memory is deallocated. + After this call, `ccc` is in the same state as if just default + constructed. + */ void clear(); -/// @} +/// @} -/// \name Ownership testing -/// The following functions are mostly helpful for efficient debugging, since -/// their complexity is \f$ O(\sqrt{\mathrm{c.capacity()}})\f$. -/// @{ +/// \name Ownership testing +/// The following functions are mostly helpful for efficient debugging, since +/// their complexity is \f$ O(\sqrt{\mathrm{c.capacity()}})\f$. +/// @{ /// returns whether `pos` is in the range `[ccc.begin(), ccc.end()]` (`ccc.end()` included). - bool owns(const_iterator pos); - /// returns whether `pos` is in the range `[ccc.begin(), ccc`.end())` (`ccc.end()` excluded). - bool owns_dereferencable(const_iterator pos); - -/// @} - -/// \name Merging -/// @{ -/*! -adds the items of `ccc2` to the end of `ccc` and `ccc2` becomes empty. -The time complexity is O(`ccc`.`capacity()`-`ccc`.`size()`). -\pre `ccc2` must not be the same as `ccc`, and the allocators of `ccc` and `ccc2` must be compatible: `ccc.get_allocator() == ccc2.get_allocator()`. -*/ -void merge(Concurrent_compact_container &ccc2); + bool owns(const_iterator pos); + /// returns whether `pos` is in the range `[ccc.begin(), ccc`.end())` (`ccc.end()` excluded). + bool owns_dereferencable(const_iterator pos); /// @} - -/// \name Comparison Operations -/// @{ - /*! - test for equality: Two containers are equal, iff they have the - same size and if their corresponding elements are equal. - */ - bool operator==(const Concurrent_compact_container &ccc2) const; - /// test for inequality: returns `!(ccc == ccc2)`. + +/// \name Merging +/// @{ +/*! +adds the items of `ccc2` to the end of `ccc` and `ccc2` becomes empty. +The time complexity is O(`ccc`.`capacity()`-`ccc`.`size()`). +\pre `ccc2` must not be the same as `ccc`, and the allocators of `ccc` and `ccc2` must be compatible: `ccc.get_allocator() == ccc2.get_allocator()`. +*/ +void merge(Concurrent_compact_container &ccc2); + +/// @} + +/// \name Comparison Operations +/// @{ + /*! + test for equality: Two containers are equal, iff they have the + same size and if their corresponding elements are equal. + */ + bool operator==(const Concurrent_compact_container &ccc2) const; + /// test for inequality: returns `!(ccc == ccc2)`. bool operator!=(const Concurrent_compact_container &ccc2) const; - /// compares in lexicographical order. - bool operator<(const Concurrent_compact_container &ccc2) const; + /// compares in lexicographical order. + bool operator<(const Concurrent_compact_container &ccc2) const; /// returns `ccc2 < ccc`. bool operator>(const Concurrent_compact_container &ccc2) const; /// returns `!(ccc > ccc2)`. bool operator<=(const Concurrent_compact_container &ccc2) const; /// returns `!(ccc < ccc2)`. bool operator>=(const Concurrent_compact_container &ccc2) const; -/// @} +/// @} }; /* end Concurrent_compact_container */ } /* end namespace CGAL */ diff --git a/STL_Extension/include/CGAL/Concurrent_compact_container.h b/STL_Extension/include/CGAL/Concurrent_compact_container.h index 4d644e547b8..e14d57eb739 100644 --- a/STL_Extension/include/CGAL/Concurrent_compact_container.h +++ b/STL_Extension/include/CGAL/Concurrent_compact_container.h @@ -71,7 +71,7 @@ struct Concurrent_compact_container_traits { namespace CCC_internal { CGAL_GENERATE_MEMBER_DETECTOR(increment_erase_counter); - + // A basic "no erase counter" strategy template class Erase_counter_strategy { diff --git a/STL_Extension/test/STL_Extension/test_Compact_container.cpp b/STL_Extension/test/STL_Extension/test_Compact_container.cpp index e84d79fecfc..7be7166feff 100644 --- a/STL_Extension/test/STL_Extension/test_Compact_container.cpp +++ b/STL_Extension/test/STL_Extension/test_Compact_container.cpp @@ -238,7 +238,7 @@ void test(const Cont &) c11.reserve(v1.size()); for(typename Vect::const_iterator it = v1.begin(); it != v1.end(); ++it) c11.insert(*it); - + assert(c11.size() == v1.size()); assert(c10 == c11); diff --git a/STL_Extension/test/STL_Extension/test_Concurrent_compact_container.cpp b/STL_Extension/test/STL_Extension/test_Concurrent_compact_container.cpp index 95f92dba74c..d4fa4a1467a 100644 --- a/STL_Extension/test/STL_Extension/test_Concurrent_compact_container.cpp +++ b/STL_Extension/test/STL_Extension/test_Concurrent_compact_container.cpp @@ -6,7 +6,7 @@ int main() { - std::cout << + std::cout << "NOTICE: this test needs CGAL_LINKED_WITH_TBB, and will not be tested." << std::endl; return 0; @@ -56,7 +56,7 @@ class Node_2 }; public: - + int rnd; Node_2() @@ -85,9 +85,9 @@ class Insert_in_CCC_functor public: Insert_in_CCC_functor( const Values_vec &values, Cont &cont, Iterators_vec &iterators) - : m_values(values), m_cont(cont), m_iterators(iterators) + : m_values(values), m_cont(cont), m_iterators(iterators) {} - + void operator() (const tbb::blocked_range& r) const { for( size_t i = r.begin() ; i != r.end() ; ++i) @@ -109,9 +109,9 @@ class Erase_in_CCC_functor public: Erase_in_CCC_functor( Cont &cont, Iterators_vec &iterators) - : m_cont(cont), m_iterators(iterators) + : m_cont(cont), m_iterators(iterators) {} - + void operator() (const tbb::blocked_range& r) const { for( size_t i = r.begin() ; i != r.end() ; ++i) @@ -137,7 +137,7 @@ public: : m_values(values), m_cont(cont), m_iterators(iterators), m_free_elements(free_elements), m_num_erasures(num_erasures) {} - + void operator() (const tbb::blocked_range& r) const { for( size_t i = r.begin() ; i != r.end() ; ++i) @@ -318,7 +318,7 @@ void test(const Cont &) c11.reserve(v1.size()); for(typename Vect::const_iterator it = v1.begin(); it != v1.end(); ++it) c11.insert(*it); - + assert(c11.size() == v1.size()); assert(c10 == c11);*/ @@ -336,7 +336,7 @@ void test(const Cont &) c9.erase(c9.begin(), c9.end()); assert(check_empty(c9)); - + std::cout << "Testing parallel insertion" << std::endl; { Cont c11; @@ -347,7 +347,7 @@ void test(const Cont &) Insert_in_CCC_functor(v11, c11, iterators) ); assert(c11.size() == v11.size()); - + std::cout << "Testing parallel erasure" << std::endl; tbb::parallel_for( tbb::blocked_range( 0, v11.size() ), @@ -361,13 +361,13 @@ void test(const Cont &) Cont c12; Vect v12(1000000); std::vector > free_elements(v12.size()); - for(typename std::vector >::iterator - it = free_elements.begin(), end = free_elements.end(); it != end; ++it) + for(typename std::vector >::iterator + it = free_elements.begin(), end = free_elements.end(); it != end; ++it) { *it = true; } - - std::atomic num_erasures; + + std::atomic num_erasures; num_erasures = 0; std::vector iterators(v12.size()); tbb::parallel_for( @@ -425,7 +425,7 @@ int main() n.rnd = i; cc2.insert(n); } - + std::cout << "cc1 capacity: " << cc1.capacity() << std::endl; std::cout << "cc1 size: " << cc1.size() << std::endl; for(CCC::const_iterator it = cc1.begin(), end = cc1.end(); it != end; ++it) { diff --git a/TDS_2/doc/TDS_2/Concepts/TriangulationDSFaceBase_2.h b/TDS_2/doc/TDS_2/Concepts/TriangulationDSFaceBase_2.h index 71ae4e585af..edb509658cd 100644 --- a/TDS_2/doc/TDS_2/Concepts/TriangulationDSFaceBase_2.h +++ b/TDS_2/doc/TDS_2/Concepts/TriangulationDSFaceBase_2.h @@ -5,53 +5,53 @@ \cgalRefines `TriangulationDataStructure_2::Face` -The concept `TriangulationDSFaceBase_2` describes the requirements for +The concept `TriangulationDSFaceBase_2` describes the requirements for the face base class of a `CGAL::Triangulation_data_structure_2`. -Note that if the `CGAL::Triangulation_data_structure_2` -is plugged into a triangulation class, -the face base class may have additional geometric -requirements depending on the triangulation class. +Note that if the `CGAL::Triangulation_data_structure_2` +is plugged into a triangulation class, +the face base class may have additional geometric +requirements depending on the triangulation class. -At the base level, +At the base level, (see Sections \ref Section_2D_Triangulations_Software_Design -and \ref TDS_2D_default ), -a face stores handles -on its three vertices and on the three neighboring faces. -The vertices and neighbors are indexed 0,1 and 2. -Neighbor `i` lies opposite to vertex `i`. +and \ref TDS_2D_default ), +a face stores handles +on its three vertices and on the three neighboring faces. +The vertices and neighbors are indexed 0,1 and 2. +Neighbor `i` lies opposite to vertex `i`. -Since the `CGAL::Triangulation_data_structure_2` is the class -which defines the handle -types, the face base class has to be somehow -parameterized by the triangulation -data structure. But since the `CGAL::Triangulation_data_structure_2` -itself is parameterized by the face and vertex -base classes, there is a cycle in the definition of these classes. -In order -to break the cycle, the base classes for faces and vertices -which are plugged in to instantiate a -`CGAL::Triangulation_data_structure_2` +Since the `CGAL::Triangulation_data_structure_2` is the class +which defines the handle +types, the face base class has to be somehow +parameterized by the triangulation +data structure. But since the `CGAL::Triangulation_data_structure_2` +itself is parameterized by the face and vertex +base classes, there is a cycle in the definition of these classes. +In order +to break the cycle, the base classes for faces and vertices +which are plugged in to instantiate a +`CGAL::Triangulation_data_structure_2` use `void` as triangulation -data structure parameter. Then, -the `CGAL::Triangulation_data_structure_2` -uses a rebind mechanism (similar to the one specified in -`std::allocator`) in order to plug itself -as parameter in the face and vertex base classes. -This mechanism requires that the base class provides -a templated nested class `Rebind_TDS` that -itself provides -the subtype `Rebind_TDS::Other` -which is the rebound version of the base class. -This rebound base class is the class -that the `CGAL::Triangulation_data_structure_2` -actually uses as a base class for the class -`CGAL::Triangulation_data_structure_2::Face`. +data structure parameter. Then, +the `CGAL::Triangulation_data_structure_2` +uses a rebind mechanism (similar to the one specified in +`std::allocator`) in order to plug itself +as parameter in the face and vertex base classes. +This mechanism requires that the base class provides +a templated nested class `Rebind_TDS` that +itself provides +the subtype `Rebind_TDS::Other` +which is the rebound version of the base class. +This rebound base class is the class +that the `CGAL::Triangulation_data_structure_2` +actually uses as a base class for the class +`CGAL::Triangulation_data_structure_2::Face`. \cgalHasModel `CGAL::Triangulation_ds_face_base_2` -\sa `TriangulationDSVertexBase_2` -\sa `CGAL::Triangulation_data_structure_2` +\sa `TriangulationDSVertexBase_2` +\sa `CGAL::Triangulation_data_structure_2` */ @@ -59,60 +59,60 @@ class TriangulationDSFaceBase_2 { public: -/// \name Types +/// \name Types /// The concept `TriangulationDSFaceBase_2` has to provide the /// following types. /// @{ /*! -This template class has to define a type `Rebind_TDS::%Other` which is the -rebound face base, where the -`CGAL::Triangulation_data_structure_2` is actually plugged in. -This type `Other` will be the actual base -of the class `CGAL::Triangulation_data_structure_2::Face`. +This template class has to define a type `Rebind_TDS::%Other` which is the +rebound face base, where the +`CGAL::Triangulation_data_structure_2` is actually plugged in. +This type `Other` will be the actual base +of the class `CGAL::Triangulation_data_structure_2::Face`. \note It can be implemented using a nested template class. \sa Section \ref TDS_2TheRebindMechanism -*/ -template +*/ +template using Rebind_TDS = unspecified_type; /*! -*/ -typedef TriangulationDataStructure_2 Triangulation_data_structure; +*/ +typedef TriangulationDataStructure_2 Triangulation_data_structure; /*! -*/ -typedef TriangulationDataStructure_2::Vertex_handle Vertex_handle; +*/ +typedef TriangulationDataStructure_2::Vertex_handle Vertex_handle; /*! -*/ -typedef TriangulationDataStructure_2::Face_handle Face_handle; +*/ +typedef TriangulationDataStructure_2::Face_handle Face_handle; -/// @} +/// @} -/// \name Creation +/// \name Creation /// @{ /*! -default constructor. -*/ +default constructor. +*/ TriangulationDSFaceBase_2(); /*! -Initializes the vertices with `v0, v1, v2` and the neighbors -with `Face_handle()`. -*/ +Initializes the vertices with `v0, v1, v2` and the neighbors +with `Face_handle()`. +*/ TriangulationDSFaceBase_2(Vertex_handle v0, Vertex_handle v1, Vertex_handle v2); /*! -initializes the vertices with `v0,v1, v2` and the neighbors with -`n0, n1, n2`. -*/ +initializes the vertices with `v0,v1, v2` and the neighbors with +`n0, n1, n2`. +*/ TriangulationDSFaceBase_2(Vertex_handle v0, Vertex_handle v1, Vertex_handle v2, @@ -120,55 +120,55 @@ TriangulationDSFaceBase_2(Vertex_handle v0, Face_handle n1, Face_handle n2); -/// @} +/// @} -/// \name Access Functions +/// \name Access Functions /// @{ /*! -returns the dimension. -*/ -int dimension(); +returns the dimension. +*/ +int dimension(); -/// @} +/// @} -/// \name Orientation +/// \name Orientation /// @{ /*! -Changes the orientation of the face by exchanging `vertex(0)` -with `vertex(1)` and `neighbor(0)` with `neighbor(1)`. -*/ -void reorient(); +Changes the orientation of the face by exchanging `vertex(0)` +with `vertex(1)` and `neighbor(0)` with `neighbor(1)`. +*/ +void reorient(); /*! -performs a counterclockwise permutation of the -vertices and neighbors of the face. -*/ -void ccw_permute(); +performs a counterclockwise permutation of the +vertices and neighbors of the face. +*/ +void ccw_permute(); /*! -performs a clockwise permutation of the -vertices and neighbors of the face. -*/ -void cw_permute(); +performs a clockwise permutation of the +vertices and neighbors of the face. +*/ +void cw_permute(); -/// @} +/// @} -/// \name Checking +/// \name Checking /// @{ /*! -performs any required test on a face. +performs any required test on a face. -If `verbose` is set to `true`, messages are printed to give -a precise indication of the kind of invalidity encountered. -*/ -bool is_valid(bool verbose = false) const; +If `verbose` is set to `true`, messages are printed to give +a precise indication of the kind of invalidity encountered. +*/ +bool is_valid(bool verbose = false) const; -/// @} +/// @} -/// \name Various +/// \name Various /// These member functions are required by /// `CGAL::Triangulation_data_structure_2` because it uses /// `CGAL::Compact_container` to store its faces. See the documentation of @@ -177,12 +177,12 @@ bool is_valid(bool verbose = false) const; /*! -*/ -void * for_compact_container() const; +*/ +void * for_compact_container() const; /*! -*/ +*/ void for_compact_container(void *p); /// @} diff --git a/TDS_2/doc/TDS_2/Concepts/TriangulationDSVertexBase_2.h b/TDS_2/doc/TDS_2/Concepts/TriangulationDSVertexBase_2.h index dcd30aa9f07..37f979d4717 100644 --- a/TDS_2/doc/TDS_2/Concepts/TriangulationDSVertexBase_2.h +++ b/TDS_2/doc/TDS_2/Concepts/TriangulationDSVertexBase_2.h @@ -5,49 +5,49 @@ \cgalRefines `TriangulationDataStructure_2::Vertex` -The concept `TriangulationDSVertexBase_2` describes the requirements for the +The concept `TriangulationDSVertexBase_2` describes the requirements for the vertex base class of a `CGAL::Triangulation_data_structure_2`. -Note that if the `CGAL::Triangulation_data_structure_2` -is plugged into a triangulation class, -the vertex base class may have additional geometric -requirements depending on the triangulation class. +Note that if the `CGAL::Triangulation_data_structure_2` +is plugged into a triangulation class, +the vertex base class may have additional geometric +requirements depending on the triangulation class. -At the base level, -provides access to one of its incident -faces through a `Face_handle`. +At the base level, +provides access to one of its incident +faces through a `Face_handle`. -Since the `CGAL::Triangulation_data_structure_2` is the class -which defines the handle -types, the vertex base class has to be somehow -parameterized by the triangulation -data structure. But since the `CGAL::Triangulation_data_structure_2` -itself is parameterized by the face and vertex -base classes, there is a cycle in the definition of these classes. -In order -to break the cycle, the base classes for faces and vertices -which are plugged in to instantiate a -`Triangulation_data_structure_2` -use `void` as triangulation -data structure parameter. Then, -the `CGAL::Triangulation_data_structure_2` -uses a rebind mechanism (similar to the one specified in -`std::allocator`) in order to plug itself -as parameter in the face and vertex base classes. -This mechanism requires that the base class provides -a templated nested class `Rebind_TDS` that -itself provides -the subtype `Rebind_TDS::Other` -which is the rebound version of the base class. -This rebound base class is the class -that the `CGAL::Triangulation_data_structure_2` -actually uses as a base class for the class -of `CGAL::Triangulation_data_structure_2::Vertex`. +Since the `CGAL::Triangulation_data_structure_2` is the class +which defines the handle +types, the vertex base class has to be somehow +parameterized by the triangulation +data structure. But since the `CGAL::Triangulation_data_structure_2` +itself is parameterized by the face and vertex +base classes, there is a cycle in the definition of these classes. +In order +to break the cycle, the base classes for faces and vertices +which are plugged in to instantiate a +`Triangulation_data_structure_2` +use `void` as triangulation +data structure parameter. Then, +the `CGAL::Triangulation_data_structure_2` +uses a rebind mechanism (similar to the one specified in +`std::allocator`) in order to plug itself +as parameter in the face and vertex base classes. +This mechanism requires that the base class provides +a templated nested class `Rebind_TDS` that +itself provides +the subtype `Rebind_TDS::Other` +which is the rebound version of the base class. +This rebound base class is the class +that the `CGAL::Triangulation_data_structure_2` +actually uses as a base class for the class +of `CGAL::Triangulation_data_structure_2::Vertex`. \cgalHasModel `CGAL::Triangulation_ds_vertex_base_2` -\sa `TriangulationDSFaceBase_2` -\sa `CGAL::Triangulation_data_structure_2` +\sa `TriangulationDSFaceBase_2` +\sa `CGAL::Triangulation_data_structure_2` */ @@ -55,55 +55,55 @@ class TriangulationDSVertexBase_2 { public: -/// \name Types +/// \name Types /// The concept `TriangulationDSVertexBase_2` has to provide the following types. /// @{ /*! -This template class has to define a type `Rebind_TDS::%Other` which is the -rebound vertex base , where the actual -`CGAL::Triangulation_data_structure_2` is plugged in. -This type `Other` will be the actual base -of the class `CGAL::Triangulation_data_structure_2::Vertex`. +This template class has to define a type `Rebind_TDS::%Other` which is the +rebound vertex base , where the actual +`CGAL::Triangulation_data_structure_2` is plugged in. +This type `Other` will be the actual base +of the class `CGAL::Triangulation_data_structure_2::Vertex`. \note It can be implemented using a nested template class. \sa Section \ref TDS_2TheRebindMechanism -*/ -template +*/ +template using Rebind_TDS = unspecified_type; /*! -*/ -typedef TriangulationDataStructure_2 Triangulation_data_structure; +*/ +typedef TriangulationDataStructure_2 Triangulation_data_structure; /*! -*/ -typedef TriangulationDataStructure_2::Vertex_handle Vertex_handle; +*/ +typedef TriangulationDataStructure_2::Vertex_handle Vertex_handle; /*! -*/ -typedef TriangulationDataStructure_2::Face_handle Face_handle; +*/ +typedef TriangulationDataStructure_2::Face_handle Face_handle; -/// @} +/// @} -/// \name Creation +/// \name Creation /// @{ /*! -default constructor. -*/ -TriangulationDSVertexBase_2(); +default constructor. +*/ +TriangulationDSVertexBase_2(); /*! -Constructs a vertex pointing to face `f`. -*/ -TriangulationDSVertexBase_2(Face_handle f); +Constructs a vertex pointing to face `f`. +*/ +TriangulationDSVertexBase_2(Face_handle f); -/// @} +/// @} -/// \name Various +/// \name Various /// These member functions are required by /// `CGAL::Triangulation_data_structure_2` because it uses /// `CGAL::Compact_container` to store its faces. See the documentation of @@ -112,12 +112,12 @@ TriangulationDSVertexBase_2(Face_handle f); /*! -*/ -void * for_compact_container() const; +*/ +void * for_compact_container() const; /*! -*/ +*/ void for_compact_container(void* p); /// @} diff --git a/TDS_2/include/CGAL/Triangulation_data_structure_2.h b/TDS_2/include/CGAL/Triangulation_data_structure_2.h index 680ab3579e9..a62f800c697 100644 --- a/TDS_2/include/CGAL/Triangulation_data_structure_2.h +++ b/TDS_2/include/CGAL/Triangulation_data_structure_2.h @@ -6,7 +6,7 @@ // $URL$ // $Id$ // SPDX-License-Identifier: GPL-3.0-or-later OR LicenseRef-Commercial -// +// // // Author(s) : Mariette Yvinec @@ -29,7 +29,7 @@ #include #include #include - + #include #include @@ -40,11 +40,11 @@ #include #include -namespace CGAL { +namespace CGAL { -template < class Vb = Triangulation_ds_vertex_base_2<>, +template < class Vb = Triangulation_ds_vertex_base_2<>, class Fb = Triangulation_ds_face_base_2<> > -class Triangulation_data_structure_2 +class Triangulation_data_structure_2 :public Triangulation_cw_ccw_2 { typedef Triangulation_data_structure_2 Tds; @@ -71,7 +71,7 @@ public: typedef Vertex_base Vertex; typedef Face_base Face; - + typedef Compact_container Face_range; typedef Compact_container Vertex_range; @@ -89,7 +89,7 @@ public: typedef Iterator_range > Vertex_handles; typedef Iterator_range > Face_handles; typedef Iterator_range Edges; - + typedef Vertex_iterator Vertex_handle; typedef Face_iterator Face_handle; typedef std::pair Edge; @@ -103,7 +103,7 @@ protected: //CREATORS - DESTRUCTORS public: - Triangulation_data_structure_2(); + Triangulation_data_structure_2(); Triangulation_data_structure_2(const Tds &tds); Triangulation_data_structure_2(Triangulation_data_structure_2&& tds) noexcept(noexcept(Face_range(std::move(tds._faces))) && @@ -117,7 +117,7 @@ public: //ACCESS FUNCTIONS // We need the const_cast<>s because TDS is not const-correct. Face_range& faces() { return _faces;} - Face_range& faces() const + Face_range& faces() const { return const_cast(this)->_faces;} Vertex_range& vertices() {return _vertices;} Vertex_range& vertices() const @@ -128,21 +128,21 @@ public: size_type number_of_faces() const ; size_type number_of_edges() const; size_type number_of_full_dim_faces() const; //number of faces stored by tds - + // TEST FEATURES bool is_vertex(Vertex_handle v) const; bool is_edge(Face_handle fh, int i) const; bool is_edge(Vertex_handle va, Vertex_handle vb) const; - bool is_edge(Vertex_handle va, Vertex_handle vb, - Face_handle& fr, int& i) const; + bool is_edge(Vertex_handle va, Vertex_handle vb, + Face_handle& fr, int& i) const; bool is_face(Face_handle fh) const; - bool is_face(Vertex_handle v1, - Vertex_handle v2, - Vertex_handle v3) const; - bool is_face(Vertex_handle v1, - Vertex_handle v2, - Vertex_handle v3, - Face_handle& fr) const; + bool is_face(Vertex_handle v1, + Vertex_handle v2, + Vertex_handle v3) const; + bool is_face(Vertex_handle v1, + Vertex_handle v2, + Vertex_handle v3, + Face_handle& fr) const; // ITERATORS AND CIRCULATORS public: @@ -163,7 +163,7 @@ public: if (dimension() < 2) return faces_end(); return faces().begin(); } - + Face_iterator faces_end() const { return faces().end(); } @@ -171,7 +171,7 @@ public: Face_handles face_handles() const { return make_prevent_deref_range(faces_begin(),faces_end()); } - + Vertex_iterator vertices_begin() const { return vertices().begin(); } @@ -183,7 +183,7 @@ public: Vertex_handles vertex_handles() const { return make_prevent_deref_range(vertices_begin(),vertices_end()); } - + Edge_iterator edges_begin() const { return Edge_iterator(this); } @@ -196,18 +196,18 @@ public: return Edges(edges_begin(),edges_end()); } - Face_circulator incident_faces(Vertex_handle v, - Face_handle f = Face_handle()) const{ + Face_circulator incident_faces(Vertex_handle v, + Face_handle f = Face_handle()) const{ return Face_circulator(v,f); } - Vertex_circulator incident_vertices(Vertex_handle v, - Face_handle f = Face_handle()) const - { - return Vertex_circulator(v,f); + Vertex_circulator incident_vertices(Vertex_handle v, + Face_handle f = Face_handle()) const + { + return Vertex_circulator(v,f); } - Edge_circulator incident_edges(Vertex_handle v, - Face_handle f = Face_handle()) const{ + Edge_circulator incident_edges(Vertex_handle v, + Face_handle f = Face_handle()) const{ return Edge_circulator(v,f); } @@ -215,19 +215,19 @@ public: int count = 0; Vertex_circulator vc = incident_vertices(v), done(vc); if ( ! vc.is_empty()) { - do { - count += 1; + do { + count += 1; } while (++vc != done); } return count; } - + Vertex_handle mirror_vertex(Face_handle f, int i) const { CGAL_triangulation_precondition ( f->neighbor(i) != Face_handle() - && f->dimension() >= 1); + && f->dimension() >= 1); return f->neighbor(i)->vertex(mirror_index(f,i)); } @@ -236,7 +236,7 @@ public: { // return the index of opposite vertex in neighbor(i); CGAL_triangulation_precondition (f->neighbor(i) != Face_handle() && - f->dimension() >= 1); + f->dimension() >= 1); if (f->dimension() == 1) { CGAL_assertion(i<=1); const int j = f->neighbor(i)->index(f->vertex((i==0) ? 1 : 0)); @@ -246,8 +246,8 @@ public: return ccw( f->neighbor(i)->index(f->vertex(ccw(i)))); } - Edge - mirror_edge(const Edge e) const + Edge + mirror_edge(const Edge e) const { CGAL_triangulation_precondition(e.first->neighbor(e.second) != Face_handle() && e.first->dimension() >= 1); @@ -257,17 +257,17 @@ public: // MODIFY void flip(Face_handle f, int i); - + Vertex_handle insert_first(); Vertex_handle insert_second(); Vertex_handle insert_in_face(Face_handle f); Vertex_handle insert_in_edge(Face_handle f, int i); - Vertex_handle insert_dim_up(Vertex_handle w = Vertex_handle(), - bool orient=true); + Vertex_handle insert_dim_up(Vertex_handle w = Vertex_handle(), + bool orient=true); void remove_degree_3(Vertex_handle v, Face_handle f = Face_handle()); - void remove_1D(Vertex_handle v); - + void remove_1D(Vertex_handle v); + void remove_second(Vertex_handle v); void remove_first(Vertex_handle v); void remove_dim_down(Vertex_handle v); @@ -279,45 +279,45 @@ public: // template< class EdgeIt> // Vertex_handle star_hole(EdgeIt edge_begin,EdgeIt edge_end); - + // template< class EdgeIt> // void star_hole(Vertex_handle v, EdgeIt edge_begin, EdgeIt edge_end); // template< class EdgeIt, class FaceIt> -// Vertex_handle star_hole(EdgeIt edge_begin, -// EdgeIt edge_end, -// FaceIt face_begin, -// FaceIt face_end); - +// Vertex_handle star_hole(EdgeIt edge_begin, +// EdgeIt edge_end, +// FaceIt face_begin, +// FaceIt face_end); + // template< class EdgeIt, class FaceIt> // void star_hole(Vertex_handle v, -// EdgeIt edge_begin, -// EdgeIt edge_end, -// FaceIt face_begin, -// FaceIt face_end); - +// EdgeIt edge_begin, +// EdgeIt edge_end, +// FaceIt face_begin, +// FaceIt face_end); + Vertex_handle create_vertex(); Vertex_handle create_vertex(const Vertex &v); - Vertex_handle create_vertex(Vertex_handle v); //calls copy constructor + Vertex_handle create_vertex(Vertex_handle v); //calls copy constructor Face_handle create_face(); Face_handle create_face(const Face& f); - Face_handle create_face(Face_handle f); //calls copy constructor + Face_handle create_face(Face_handle f); //calls copy constructor - Face_handle create_face(Face_handle f1, int i1, - Face_handle f2, int i2, - Face_handle f3, int i3); - Face_handle create_face(Face_handle f1, int i1, - Face_handle f2, int i2); + Face_handle create_face(Face_handle f1, int i1, + Face_handle f2, int i2, + Face_handle f3, int i3); + Face_handle create_face(Face_handle f1, int i1, + Face_handle f2, int i2); Face_handle create_face(Face_handle f1, int i1, Vertex_handle v); - Face_handle create_face(Vertex_handle v1, - Vertex_handle v2, - Vertex_handle v3); - Face_handle create_face(Vertex_handle v1, - Vertex_handle v2, - Vertex_handle v3, - Face_handle f1, - Face_handle f2, - Face_handle f3); + Face_handle create_face(Vertex_handle v1, + Vertex_handle v2, + Vertex_handle v3); + Face_handle create_face(Vertex_handle v1, + Vertex_handle v2, + Vertex_handle v3, + Face_handle f1, + Face_handle f2, + Face_handle f3); void set_adjacency(Face_handle f0, int i0, Face_handle f1, int i1) const; @@ -357,14 +357,14 @@ public: // CHECKING bool is_valid(bool verbose = false, int level = 0) const; - + // HELPING private: typedef std::pair Vh_pair; public: - void set_adjacency(Face_handle fh, - int ih, - std::map< Vh_pair, Edge>& edge_map); + void set_adjacency(Face_handle fh, + int ih, + std::map< Vh_pair, Edge>& edge_map); void reorient_faces(); private: bool dim_down_precondition(Face_handle f, int i); @@ -422,12 +422,12 @@ public: // I/O Vertex_handle file_input(std::istream& is, bool skip_first=false); void file_output(std::ostream& os, - Vertex_handle v = Vertex_handle(), - bool skip_first=false) const; + Vertex_handle v = Vertex_handle(), + bool skip_first=false) const; Vertex_handle off_file_input(std::istream& is, bool verbose=false); void vrml_output(std::ostream& os, - Vertex_handle v = Vertex_handle(), - bool skip_first=false) const; + Vertex_handle v = Vertex_handle(), + bool skip_first=false) const; // SETTING (had to make them public for use in remove from Triangulations) void set_dimension (int n) {_dimension = n ;} @@ -438,7 +438,7 @@ public: /************* START OF MODIFICATIONS ***************/ template< class FaceIt > - Vertex_handle insert_in_hole(FaceIt face_begin, FaceIt face_end) + Vertex_handle insert_in_hole(FaceIt face_begin, FaceIt face_end) { Vertex_handle newv = create_vertex(); insert_in_hole(newv, face_begin, face_end); @@ -447,7 +447,7 @@ public: template< class FaceIt > - void insert_in_hole(Vertex_handle v, FaceIt face_begin, FaceIt face_end) + void insert_in_hole(Vertex_handle v, FaceIt face_begin, FaceIt face_end) { CGAL_triangulation_precondition(dimension() == 2); @@ -468,8 +468,8 @@ public: ii = newi; } } while(!found_boundary); - // Now we have found ONE edge on the boundary. - // From that one edge we must walk on the boundary + // Now we have found ONE edge on the boundary. + // From that one edge we must walk on the boundary // of the hole until we've covered the whole thing. bool complete_walk = false; @@ -491,14 +491,14 @@ public: } while (!complete_walk); // At this point, bdry_edges contains the edges that define // the boundary of the hole with a specific ordering: for any - // two consecutive edges in the vector e1 = (f1, i1), - // e2 = (f2, i2) it holds that + // two consecutive edges in the vector e1 = (f1, i1), + // e2 = (f2, i2) it holds that // f1->vertex(cw(i1)) == f2->vertex(ccw(i2)) for (unsigned int jj = 0; jj < bdry_edges.size(); jj++) { Face_handle fh = bdry_edges[jj].first; int idx = bdry_edges[jj].second; - + Vertex_handle v1 = fh->vertex(ccw(idx)); Vertex_handle v2 = fh->vertex(cw(idx)); @@ -536,7 +536,7 @@ public: template< class EdgeIt> Vertex_handle star_hole(EdgeIt edge_begin, EdgeIt edge_end) - // creates a new vertex + // creates a new vertex // and stars from it // the hole described by the range [edge_begin,edge_end[ // the triangulation is assumed to have dim=2 @@ -546,30 +546,30 @@ public: star_hole(newv, edge_begin, edge_end); return newv; } - + template< class EdgeIt> void star_hole(Vertex_handle v, EdgeIt edge_begin, EdgeIt edge_end) // uses vertex v // to star the hole described by the range [edge_begin,edge_end[ // the triangulation is assumed to have dim=2 // the hole is supposed to be ccw oriented - { + { std::list empty_list; - star_hole(v, - edge_begin, - edge_end, - empty_list.begin(), - empty_list.end()); - return; + star_hole(v, + edge_begin, + edge_end, + empty_list.begin(), + empty_list.end()); + return; } template< class EdgeIt, class FaceIt> - Vertex_handle star_hole(EdgeIt edge_begin, - EdgeIt edge_end, - FaceIt face_begin, - FaceIt face_end) - // creates a new vertex + Vertex_handle star_hole(EdgeIt edge_begin, + EdgeIt edge_end, + FaceIt face_begin, + FaceIt face_end) + // creates a new vertex // and stars from it // the hole described by the range [edge_begin,edge_end[ // reusing the faces in the range [face_begin,face_end[ @@ -580,13 +580,13 @@ public: star_hole(newv, edge_begin, edge_end, face_begin, face_end); return newv; } - + template< class EdgeIt, class FaceIt> void star_hole(Vertex_handle newv, - EdgeIt edge_begin, - EdgeIt edge_end, - FaceIt face_begin, - FaceIt face_end) + EdgeIt edge_begin, + EdgeIt edge_end, + FaceIt face_begin, + FaceIt face_end) // uses vertex v // to star the hole described by the range [edge_begin,edge_end[ // reusing the faces in the range [face_begin,face_end[ @@ -602,7 +602,7 @@ public: fn->vertex(cw(in))->set_face(fn); Face_handle first_f = reset_or_create_face(fn, in , newv, fit, face_end); Face_handle previous_f=first_f, next_f; - ++eit; + ++eit; for( ; eit != edge_end ; eit++) { fn = (*eit).first; @@ -615,35 +615,35 @@ public: set_adjacency(next_f, 0, first_f, 1); newv->set_face(first_f); - return; + return; } private: template< class FaceIt> - Face_handle reset_or_create_face(Face_handle fn, - int in, - Vertex_handle v, - FaceIt& fit, - const FaceIt& face_end) + Face_handle reset_or_create_face(Face_handle fn, + int in, + Vertex_handle v, + FaceIt& fit, + const FaceIt& face_end) { if (fit == face_end) return create_face(fn, in, v); (*fit)->set_vertices(fn->vertex(cw(in)), fn->vertex(ccw(in)), v); (*fit)->set_neighbors(Face_handle(),Face_handle(),fn); fn->set_neighbor(in, *fit); - return *fit++; + return *fit++; } }; //for backward compatibility template < class Gt , class Vb, class Fb> -class Triangulation_default_data_structure_2 +class Triangulation_default_data_structure_2 : public Triangulation_data_structure_2 { public: typedef Triangulation_data_structure_2 Tds; typedef Triangulation_default_data_structure_2 Tdds; - typedef Gt Geom_traits; + typedef Gt Geom_traits; Triangulation_default_data_structure_2(const Geom_traits& = Geom_traits()) : Tds() {} @@ -658,13 +658,13 @@ public: typedef Triangulation_data_structure_2 Tds; typedef Triangulation_data_structure_using_list_2 Tdsul; - Triangulation_data_structure_using_list_2(): Tds() {} + Triangulation_data_structure_using_list_2(): Tds() {} }; - + template < class Vb, class Fb> Triangulation_data_structure_2 :: -Triangulation_data_structure_2() +Triangulation_data_structure_2() : _dimension(-2) { } @@ -693,7 +693,7 @@ Triangulation_data_structure_2 :: clear(); } -//copy-assignment +//copy-assignment template < class Vb, class Fb> Triangulation_data_structure_2& Triangulation_data_structure_2 :: @@ -701,9 +701,9 @@ operator= (const Tds &tds) { copy_tds(tds); return *this; -} +} -//move-assignment +//move-assignment template < class Vb, class Fb> Triangulation_data_structure_2& Triangulation_data_structure_2 :: @@ -713,7 +713,7 @@ operator= (Tds &&tds) noexcept(noexcept(Tds(std::move(tds)))) _vertices = std::move(tds._vertices); _dimension = std::exchange(tds._dimension, -2); return *this; -} +} template < class Vb, class Fb> void @@ -740,17 +740,17 @@ swap(Tds &tds) //ACCESS FUNCTIONS template -inline +inline typename Triangulation_data_structure_2::size_type Triangulation_data_structure_2 :: -number_of_faces() const +number_of_faces() const { if (dimension() < 2) return 0; return faces().size(); } template -inline +inline typename Triangulation_data_structure_2::size_type Triangulation_data_structure_2:: number_of_edges() const @@ -761,7 +761,7 @@ number_of_edges() const default: return 0; } } - + template typename Triangulation_data_structure_2::size_type Triangulation_data_structure_2:: @@ -804,23 +804,23 @@ is_edge(Vertex_handle va, Vertex_handle vb) const Vertex_circulator vc = incident_vertices(va), done(vc); if ( vc == 0) return false; do { - if( vb == vc ) {return true;} + if( vb == vc ) {return true;} } while (++vc != done); return false; } - + template bool Triangulation_data_structure_2:: -is_edge(Vertex_handle va, Vertex_handle vb, - Face_handle &fr, int & i) const +is_edge(Vertex_handle va, Vertex_handle vb, + Face_handle &fr, int & i) const // assume va is a vertex of t // returns true (false) if the line segment ab is (is not) an edge of t // if true is returned (fr,i) is the edge ab // with face fr on the right of a->b { - Face_handle fc = va->face(); + Face_handle fc = va->face(); Face_handle start = fc; if (fc == nullptr) return false; int inda, indb; @@ -838,7 +838,7 @@ is_edge(Vertex_handle va, Vertex_handle vb, } template -inline bool +inline bool Triangulation_data_structure_2:: is_face(Face_handle fh) const { @@ -849,23 +849,23 @@ is_face(Face_handle fh) const } template -inline bool +inline bool Triangulation_data_structure_2:: -is_face(Vertex_handle v1, - Vertex_handle v2, - Vertex_handle v3) const +is_face(Vertex_handle v1, + Vertex_handle v2, + Vertex_handle v3) const { Face_handle f; return is_face(v1,v2,v3,f); } template -bool +bool Triangulation_data_structure_2:: -is_face(Vertex_handle v1, - Vertex_handle v2, - Vertex_handle v3, - Face_handle &f) const +is_face(Vertex_handle v1, + Vertex_handle v2, + Vertex_handle v3, + Face_handle &f) const { if (dimension() != 2) return false; int i; @@ -876,7 +876,7 @@ is_face(Vertex_handle v1, int ind1= f->index(v1); int ind2= f->index(v2); if (v3 == f->vertex(3-ind1-ind2)) { return true;} - return false; + return false; } template @@ -887,19 +887,19 @@ flip(Face_handle f, int i) CGAL_triangulation_precondition( dimension()==2); Face_handle n = f->neighbor(i); int ni = mirror_index(f,i); //ni = n->index(f); - + Vertex_handle v_cw = f->vertex(cw(i)); Vertex_handle v_ccw = f->vertex(ccw(i)); // bl == bottom left, tr == top right Face_handle tr = f->neighbor(ccw(i)); - int tri = mirror_index(f,ccw(i)); + int tri = mirror_index(f,ccw(i)); Face_handle bl = n->neighbor(ccw(ni)); - int bli = mirror_index(n,ccw(ni)); - + int bli = mirror_index(n,ccw(ni)); + f->set_vertex(cw(i), n->vertex(ni)); n->set_vertex(cw(ni), f->vertex(i)); - + // update the neighborhood relations set_adjacency(f, i, bl, bli); set_adjacency(f, ccw(i), n, ccw(ni)); @@ -908,29 +908,29 @@ flip(Face_handle f, int i) if(v_cw->face() == f) { v_cw->set_face(n); } - + if(v_ccw->face() == n) { v_ccw->set_face(f); } } - + template < class Vb, class Fb> typename Triangulation_data_structure_2::Vertex_handle Triangulation_data_structure_2:: insert_first( ) { CGAL_triangulation_precondition( number_of_vertices() == 0 && - dimension()==-2 ); + dimension()==-2 ); return insert_dim_up(); } template < class Vb, class Fb> -typename Triangulation_data_structure_2::Vertex_handle +typename Triangulation_data_structure_2::Vertex_handle Triangulation_data_structure_2:: insert_second() { CGAL_triangulation_precondition( number_of_vertices() == 1 && - dimension()==-1 ); + dimension()==-1 ); return insert_dim_up(); } @@ -948,10 +948,10 @@ insert_in_face(Face_handle f) Vertex_handle v0 = f->vertex(0); Vertex_handle v2 = f->vertex(2); Vertex_handle v1 = f->vertex(1); - + Face_handle n1 = f->neighbor(1); Face_handle n2 = f->neighbor(2); - + Face_handle f1 = create_face(v0, v, v2, f, n1, Face_handle()); Face_handle f2 = create_face(v0, v1, v, f, Face_handle(), n2); @@ -981,11 +981,11 @@ Triangulation_data_structure_2:: insert_in_edge(Face_handle f, int i) //insert in the edge opposite to vertex i of face f { - CGAL_triangulation_precondition(f != Face_handle() && dimension() >= 1); + CGAL_triangulation_precondition(f != Face_handle() && dimension() >= 1); if (dimension() == 1) {CGAL_triangulation_precondition(i == 2);} - if (dimension() == 2) {CGAL_triangulation_precondition(i == 0 || - i == 1 || - i == 2);} + if (dimension() == 2) {CGAL_triangulation_precondition(i == 0 || + i == 1 || + i == 2);} Vertex_handle v; if (dimension() == 1) { v = create_vertex(); @@ -1002,7 +1002,7 @@ insert_in_edge(Face_handle f, int i) Face_handle n = f->neighbor(i); int in = mirror_index(f,i); //n->index(f); v = insert_in_face(f); - flip(n,in); + flip(n,in); } return v; @@ -1014,9 +1014,9 @@ typename Triangulation_data_structure_2::Vertex_handle Triangulation_data_structure_2:: insert_dim_up(Vertex_handle w, bool orient) { - // the following function insert + // the following function insert // a vertex v which is outside the affine hull of Tds - // The triangulation will be starred from v and w + // The triangulation will be starred from v and w // ( geometrically w= // the infinite vertex ) // w=nullptr for first and second insertions // orient governs the orientation of the resulting triangulation @@ -1027,8 +1027,8 @@ insert_dim_up(Vertex_handle w, bool orient) Face_handle f2; const int dim = dimension(); //it is the resulting dimension - - switch (dim) { + + switch (dim) { case -1: f1 = create_face(v,Vertex_handle(),Vertex_handle()); v->set_face(f1); @@ -1043,64 +1043,64 @@ insert_dim_up(Vertex_handle w, bool orient) case 2 : { std::list faces_list; - Face_iterator ib= face_iterator_base_begin(); + Face_iterator ib= face_iterator_base_begin(); Face_iterator ib_end = face_iterator_base_end(); for (; ib != ib_end ; ++ib){ - faces_list.push_back( ib); + faces_list.push_back( ib); } - + std::list to_delete; typename std::list::iterator lfit = faces_list.begin(); Face_handle f, g; for ( ; lfit != faces_list.end() ; ++lfit) { - f = * lfit; - g = create_face(f); //calls copy constructor of face - f->set_vertex(dim,v); - g->set_vertex(dim,w); - set_adjacency(f, dim, g, dim); - if (f->has_vertex(w)) to_delete.push_back(g); // flat face to delete + f = * lfit; + g = create_face(f); //calls copy constructor of face + f->set_vertex(dim,v); + g->set_vertex(dim,w); + set_adjacency(f, dim, g, dim); + if (f->has_vertex(w)) to_delete.push_back(g); // flat face to delete } lfit = faces_list.begin(); for ( ; lfit != faces_list.end() ; ++lfit) { - f = * lfit; - g = f->neighbor(dim); - for(int j = 0; j < dim ; ++j) { - g->set_neighbor(j, f->neighbor(j)->neighbor(dim)); - } + f = * lfit; + g = f->neighbor(dim); + for(int j = 0; j < dim ; ++j) { + g->set_neighbor(j, f->neighbor(j)->neighbor(dim)); + } } // couldn't unify the code for reorientation mater - lfit = faces_list.begin() ; + lfit = faces_list.begin() ; if (dim == 1){ - if (orient) { - (*lfit)->reorient(); ++lfit ; (*lfit)->neighbor(1)->reorient(); - } - else { - (*lfit)->neighbor(1)->reorient(); ++lfit ; (*lfit)->reorient(); - } + if (orient) { + (*lfit)->reorient(); ++lfit ; (*lfit)->neighbor(1)->reorient(); + } + else { + (*lfit)->neighbor(1)->reorient(); ++lfit ; (*lfit)->reorient(); + } } else { // dimension == 2 - for( ;lfit != faces_list.end(); ++lfit ) { - if (orient) {(*lfit)->neighbor(2)->reorient();} - else { (*lfit)->reorient();} - } + for( ;lfit != faces_list.end(); ++lfit ) { + if (orient) {(*lfit)->neighbor(2)->reorient();} + else { (*lfit)->reorient();} + } } lfit = to_delete.begin(); int i1, i2; for ( ;lfit != to_delete.end(); ++lfit){ - f = *lfit ; - int j ; - if (f->vertex(0) == w) {j=0;} - else {j=1;} - f1= f->neighbor(dim); i1= mirror_index(f,dim); //f1->index(f); - f2= f->neighbor(j); i2= mirror_index(f,j); //f2->index(f); - set_adjacency(f1, i1, f2, i2); - delete_face(f); + f = *lfit ; + int j ; + if (f->vertex(0) == w) {j=0;} + else {j=1;} + f1= f->neighbor(dim); i1= mirror_index(f,dim); //f1->index(f); + f2= f->neighbor(j); i2= mirror_index(f,j); //f2->index(f); + set_adjacency(f1, i1, f2, i2); + delete_face(f); } - + v->set_face( *(faces_list.begin())); } break; @@ -1122,42 +1122,42 @@ remove_degree_3(Vertex_handle v, Face_handle f) if (f == Face_handle()) {f= v->face();} else { CGAL_triangulation_assertion( f->has_vertex(v));} - + int i = f->index(v); Face_handle left = f->neighbor(cw(i)); - int li = mirror_index(f,cw(i)); + int li = mirror_index(f,cw(i)); Face_handle right = f->neighbor(ccw(i)); - int ri = mirror_index(f,ccw(i)); + int ri = mirror_index(f,ccw(i)); Face_handle ll, rr; Vertex_handle q = left->vertex(li); CGAL_triangulation_assertion( left->vertex(li) == right->vertex(ri)); - + ll = left->neighbor(cw(li)); if(ll != Face_handle()) { - int lli = mirror_index(left,cw(li)); + int lli = mirror_index(left,cw(li)); ll->set_neighbor(lli, f); - } + } f->set_neighbor(cw(i), ll); - if (f->vertex(ccw(i))->face() == left) f->vertex(ccw(i))->set_face(f); - + if (f->vertex(ccw(i))->face() == left) f->vertex(ccw(i))->set_face(f); + rr = right->neighbor(ccw(ri)); if(rr != Face_handle()) { int rri = mirror_index(right,ccw(ri)); //rr->index(right); rr->set_neighbor(rri, f); - } + } f->set_neighbor(ccw(i), rr); - if (f->vertex(cw(i))->face() == right) f->vertex(cw(i))->set_face(f); - + if (f->vertex(cw(i))->face() == right) f->vertex(cw(i))->set_face(f); + f->set_vertex(i, q); if (q->face() == right || q->face() == left) { q->set_face(f); } delete_face(right); delete_face(left); - + delete_vertex(v); -} +} template void @@ -1167,7 +1167,7 @@ dim_down(Face_handle f, int i) CGAL_triangulation_expensive_precondition( is_valid() ); CGAL_triangulation_precondition( dimension() == 2 ); CGAL_triangulation_precondition( number_of_vertices() > 3 ); - CGAL_triangulation_precondition( degree( f->vertex(i) ) == + CGAL_triangulation_precondition( degree( f->vertex(i) ) == number_of_vertices()-1 ); Vertex_handle v = f->vertex(i); @@ -1200,12 +1200,12 @@ dim_down(Face_handle f, int i) Vertex_handle v1 = f->vertex(1); f->set_vertex(1, v); Face_handle fl = create_face(v, v1, Vertex_handle(), - n0, f, Face_handle()); + n0, f, Face_handle()); f->set_neighbor(0, fl); n0->set_neighbor(1, fl); v->set_face(f); } - + template void Triangulation_data_structure_2:: @@ -1213,7 +1213,7 @@ remove_dim_down(Vertex_handle v) { Face_handle f; switch( dimension()){ - case -1: + case -1: delete_face(v->face()); break; case 0: @@ -1223,7 +1223,7 @@ remove_dim_down(Vertex_handle v) break; case 1: case 2: -// CGAL_triangulation_precondition ( +// CGAL_triangulation_precondition ( // (dimension() == 1 && number_of_vertices() == 3) || // (dimension() == 2 && number_of_vertices() > 3) ); // the faces incident to v are down graded one dimension @@ -1241,15 +1241,15 @@ remove_dim_down(Vertex_handle v) for( ; lfit != to_downgrade.end() ; ++lfit) { f = *lfit; j = f->index(v); if (dimension() == 1) { - if (j == 0) f->reorient(); - f->set_vertex(1,Vertex_handle()); - f->set_neighbor(1, Face_handle()); + if (j == 0) f->reorient(); + f->set_vertex(1,Vertex_handle()); + f->set_neighbor(1, Face_handle()); } else { //dimension() == 2 - if (j == 0) f->cw_permute(); - else if(j == 1) f->ccw_permute(); - f->set_vertex(2, Vertex_handle()); - f->set_neighbor(2, Face_handle()); + if (j == 0) f->cw_permute(); + else if(j == 1) f->ccw_permute(); + f->set_vertex(2, Vertex_handle()); + f->set_neighbor(2, Face_handle()); } f->vertex(0)->set_face(f); } @@ -1258,7 +1258,7 @@ remove_dim_down(Vertex_handle v) for( ; lfit != to_delete.end() ; ++lfit) { delete_face(*lfit); } - } + } delete_vertex(v); set_dimension(dimension() -1); return; @@ -1266,11 +1266,11 @@ remove_dim_down(Vertex_handle v) template < class Vb, class Fb> void -Triangulation_data_structure_2:: +Triangulation_data_structure_2:: remove_1D(Vertex_handle v) { CGAL_triangulation_precondition( dimension() == 1 && - number_of_vertices() > 3); + number_of_vertices() > 3); Face_handle f = v->face(); int i = f->index(v); if (i==0) {f = f->neighbor(1);} @@ -1292,21 +1292,21 @@ Triangulation_data_structure_2:: remove_second(Vertex_handle v) { CGAL_triangulation_precondition(number_of_vertices()== 2 && - dimension() == 0); + dimension() == 0); remove_dim_down(v); return; } - + template inline void Triangulation_data_structure_2:: remove_first(Vertex_handle v) { - CGAL_triangulation_precondition(number_of_vertices()== 1 && - dimension() == -1); + CGAL_triangulation_precondition(number_of_vertices()== 1 && + dimension() == -1); remove_dim_down(v); - return; + return; } template @@ -1328,9 +1328,9 @@ star_hole(Vertex_handle newv, List_edges& hole) // the triangulation is assumed to have dim=2 // hole is supposed to be ccw oriented { - + star_hole(newv, hole.begin(), hole.end()); - return; + return; } template @@ -1341,7 +1341,7 @@ make_hole(Vertex_handle v, List_edges& hole) // and return the dscription of the hole in hole { CGAL_triangulation_precondition(dimension() == 2); - std::list to_delete; + std::list to_delete; Face_handle f, fn; int i =0, in =0; @@ -1427,14 +1427,14 @@ create_face( Face_handle fh) template typename Triangulation_data_structure_2::Face_handle Triangulation_data_structure_2:: -create_face(Face_handle f1, int i1, - Face_handle f2, int i2, - Face_handle f3, int i3) +create_face(Face_handle f1, int i1, + Face_handle f2, int i2, + Face_handle f3, int i3) { Face_handle newf = faces().emplace(f1->vertex(cw(i1)), - f2->vertex(cw(i2)), - f3->vertex(cw(i3)), - f2, f3, f1); + f2->vertex(cw(i2)), + f3->vertex(cw(i3)), + f2, f3, f1); f1->set_neighbor(i1,newf); f2->set_neighbor(i2,newf); f3->set_neighbor(i3,newf); @@ -1447,9 +1447,9 @@ Triangulation_data_structure_2:: create_face(Face_handle f1, int i1, Face_handle f2, int i2) { Face_handle newf = faces().emplace(f1->vertex(cw(i1)), - f2->vertex(cw(i2)), - f2->vertex(ccw(i2)), - f2, Face_handle(), f1); + f2->vertex(cw(i2)), + f2->vertex(ccw(i2)), + f2, Face_handle(), f1); f1->set_neighbor(i1,newf); f2->set_neighbor(i2,newf); return newf; @@ -1481,7 +1481,7 @@ template typename Triangulation_data_structure_2::Face_handle Triangulation_data_structure_2:: create_face(Vertex_handle v1, Vertex_handle v2, Vertex_handle v3, - Face_handle f1, Face_handle f2, Face_handle f3) + Face_handle f1, Face_handle f2, Face_handle f3) { Face_handle newf = faces().emplace(v1, v2, v3, f1, f2, f3); @@ -1508,7 +1508,7 @@ delete_face(Face_handle f) CGAL_triangulation_expensive_precondition( dimension() != 2 || is_face(f)); CGAL_triangulation_expensive_precondition( dimension() != 1 || is_edge(f,2)); CGAL_triangulation_expensive_precondition( dimension() != 0 || - is_vertex(f->vertex(0)) ); + is_vertex(f->vertex(0)) ); faces().erase(f); } @@ -1660,7 +1660,7 @@ join_vertices(Face_handle f, int i, Vertex_handle v) CGAL_triangulation_precondition( i >= 0 && i <= 2 ); // this methods does the "join"-operation and preserves - // the vertex v among the two vertices that define the edge (f, i) + // the vertex v among the two vertices that define the edge (f, i) Vertex_handle v1 = f->vertex( ccw(i) ); Vertex_handle v2 = f->vertex( cw(i) ); @@ -1679,7 +1679,7 @@ join_vertices(Face_handle f, int i, Vertex_handle v) remove_degree_3(v2, f->neighbor(ccw(i))); return v1; } - + /* // The following drawing corrsponds to the variables // used in this part... @@ -1695,10 +1695,10 @@ join_vertices(Face_handle f, int i, Vertex_handle v) // / \ / \ // / \ g / \ // / bl \ / br \ - // / \ / \ + // / \ / \ // *---------*---------* // ibl j=v4 ibr - // + // // The situation after the "join"-operation is as follows: // // i @@ -1711,9 +1711,9 @@ join_vertices(Face_handle f, int i, Vertex_handle v) // * v1 // /|\ // / | \ - // / | \ + // / | \ // / bl|br \ - // / | \ + // / | \ // *-----*-----* // */ @@ -1735,7 +1735,7 @@ join_vertices(Face_handle f, int i, Vertex_handle v) int ibr = mirror_index(g, cw(j) ); // we need to store the faces adjacent to v2 as well as the - // indices of v2 w.r.t. these faces, so that afterwards we can set + // indices of v2 w.r.t. these faces, so that afterwards we can set // v1 to be the vertex for these faces std::vector star_faces_of_v2; std::vector star_indices_of_v2; @@ -1766,7 +1766,7 @@ join_vertices(Face_handle f, int i, Vertex_handle v) star_faces_of_v2[k]->set_vertex( id, v1 ); } - // then make sure that all the vertices have correct pointers to + // then make sure that all the vertices have correct pointers to // faces Vertex_handle v3 = f->vertex(i); Vertex_handle v4 = g->vertex(j); @@ -1812,7 +1812,7 @@ insert_degree_2(Face_handle f, int i) // i / \ // * / \ // / \ / f \ - // / \ / _____ \ + // / \ / _____ \ // / f \ / / f1 \ \ // / \ |/ v \| // v0=ccw(i) *---------* v1=cw(i) ===> v0 *----*----* v1 @@ -1893,16 +1893,16 @@ bool Triangulation_data_structure_2:: is_valid(bool verbose, int level) const { - if(number_of_vertices() == 0){ + if(number_of_vertices() == 0){ return (dimension() == -2); } - + bool result = (dimension()>= -1); CGAL_triangulation_assertion(result); //count and test the validity of the faces (for positive dimensions) - Face_iterator ib = face_iterator_base_begin(); + Face_iterator ib = face_iterator_base_begin(); Face_iterator ib_end = face_iterator_base_end(); size_type count_stored_faces =0; for ( ; ib != ib_end ; ++ib){ @@ -1912,11 +1912,11 @@ is_valid(bool verbose, int level) const CGAL_triangulation_assertion(result); } } - + result = result && (count_stored_faces == number_of_full_dim_faces()); CGAL_triangulation_assertion( - count_stored_faces == number_of_full_dim_faces()); - + count_stored_faces == number_of_full_dim_faces()); + // vertex count size_type vertex_count = 0; for(Vertex_iterator vit = vertices_begin(); vit != vertices_end(); @@ -1928,10 +1928,10 @@ is_valid(bool verbose, int level) const } result = result && (number_of_vertices() == vertex_count); CGAL_triangulation_assertion( number_of_vertices() == vertex_count ); - + //edge count size_type edge_count = 0; - for(Edge_iterator eit = edges_begin(); eit != edges_end(); ++eit) { + for(Edge_iterator eit = edges_begin(); eit != edges_end(); ++eit) { ++edge_count; } @@ -1940,9 +1940,9 @@ is_valid(bool verbose, int level) const for(Face_iterator fit = faces_begin(); fit != faces_end(); ++fit) { ++face_count; } - + switch(dimension()) { - case -1: + case -1: result = result && vertex_count == 1 && face_count == 0 && edge_count == 0; CGAL_triangulation_assertion(result); @@ -1978,7 +1978,7 @@ copy_tds(const TDS_src& tds_src, const ConvertVertex& convert_vertex, const ConvertFace& convert_face) { - if (vert != typename TDS_src::Vertex_handle()) + if (vert != typename TDS_src::Vertex_handle()) CGAL_triangulation_precondition( tds_src.is_vertex(vert)); clear(); @@ -1987,9 +1987,9 @@ copy_tds(const TDS_src& tds_src, // Number of pointers to cell/vertex to copy per cell. int dim = (std::max)(1, dimension() + 1); - + if(n == 0) {return Vertex_handle();} - + //initializes maps Unique_hash_map vmap; Unique_hash_map fmap; @@ -2002,7 +2002,7 @@ copy_tds(const TDS_src& tds_src, convert_vertex(*vit1, *vh); } - //create faces + //create faces typename TDS_src::Face_iterator fit1 = tds_src.faces().begin(); for( ; fit1 != tds_src.faces_end(); ++fit1) { Face_handle fh = create_face( convert_face(*fit1) ); @@ -2010,7 +2010,7 @@ copy_tds(const TDS_src& tds_src, convert_face(*fit1, *fh); } - //link vertices to a cell + //link vertices to a cell vit1 = tds_src.vertices_begin(); for ( ; vit1 != tds_src.vertices_end(); vit1++) { vmap[vit1]->set_face(fmap[vit1->face()]); @@ -2020,11 +2020,11 @@ copy_tds(const TDS_src& tds_src, fit1 = tds_src.faces().begin(); for ( ; fit1 != tds_src.faces_end(); ++fit1) { for (int j = 0; j < dim ; ++j) { - fmap[fit1]->set_vertex(j, vmap[fit1->vertex(j)] ); - fmap[fit1]->set_neighbor(j, fmap[fit1->neighbor(j)]); + fmap[fit1]->set_vertex(j, vmap[fit1->vertex(j)] ); + fmap[fit1]->set_neighbor(j, fmap[fit1->neighbor(j)]); } } - + // remove the post condition because it is false when copying the // TDS of a regular triangulation because of hidden vertices // CGAL_triangulation_postcondition( is_valid() ); @@ -2039,7 +2039,7 @@ namespace internal { namespace TDS_2{ Vertex_tgt operator()(const Vertex_src& src) const { return Vertex_tgt( src.point() ); } - + void operator()(const Vertex_src&,Vertex_tgt&) const {} }; @@ -2048,27 +2048,27 @@ namespace internal { namespace TDS_2{ { Face_tgt operator()(const Face_src& /*src*/) const { return Face_tgt(); - } - + } + void operator()(const Face_src&,Face_tgt&) const {} }; - + template struct Default_vertex_converter { const Vertex& operator()(const Vertex& src) const { return src; } - + void operator()(const Vertex&,Vertex&) const {} }; - + template struct Default_face_converter{ const Face& operator()(const Face& src) const { return src; - } - + } + void operator()(const Face&,Face&) const {} }; } } //namespace internal::TDS_2 @@ -2095,7 +2095,7 @@ file_output( std::ostream& os, Vertex_handle v, bool skip_first) const // if non nullptr, v is the vertex to be output first // if skip_first is true, the point in the first vertex is not output // (it may be for instance the infinite vertex of the triangulation) - + size_type n = number_of_vertices(); size_type m = number_of_full_dim_faces(); if(is_ascii(os)) os << n << ' ' << m << ' ' << dimension() << std::endl; @@ -2106,7 +2106,7 @@ file_output( std::ostream& os, Vertex_handle v, bool skip_first) const Unique_hash_map F; - // first vertex + // first vertex int inum = 0; if ( v != Vertex_handle()) { V[v] = inum++; @@ -2116,14 +2116,14 @@ file_output( std::ostream& os, Vertex_handle v, bool skip_first) const if(is_ascii(os)) os << std::endl; } } - + // other vertices for( Vertex_iterator vit= vertices_begin(); vit != vertices_end() ; ++vit) { if ( v != vit ) { - V[vit] = inum++; - // os << vit->point(); - os << *vit; - if(is_ascii(os)) os << "\n"; + V[vit] = inum++; + // os << vit->point(); + os << *vit; + if(is_ascii(os)) os << "\n"; } } if(is_ascii(os)) os << "\n"; @@ -2142,7 +2142,7 @@ file_output( std::ostream& os, Vertex_handle v, bool skip_first) const if(is_ascii(os)) os << "\n"; } if(is_ascii(os)) os << "\n"; - + // neighbor pointers of the faces for( Face_iterator it = face_iterator_base_begin(); it != face_iterator_base_end(); ++it) { @@ -2167,7 +2167,7 @@ file_input( std::istream& is, bool skip_first) // if skip_first is true, a first vertex is added (infinite_vertex) //set this first vertex as infinite_Vertex if(number_of_vertices() != 0) clear(); - + size_type n, m; int d; is >> n >> m >> d; @@ -2189,7 +2189,7 @@ file_input( std::istream& is, bool skip_first) V[i] = create_vertex(); is >> *(V[i]); } - + // Creation of the faces int index; int dim = (dimension() == -1 ? 1 : dimension() + 1); @@ -2197,27 +2197,27 @@ file_input( std::istream& is, bool skip_first) for(i = 0; i < m; ++i) { F[i] = create_face() ; for(int j = 0; j < dim ; ++j){ - is >> index; - F[i]->set_vertex(j, V[index]); - // The face pointer of vertices is set too often, - // but otherwise we had to use a further map - V[index]->set_face(F[i]); + is >> index; + F[i]->set_vertex(j, V[index]); + // The face pointer of vertices is set too often, + // but otherwise we had to use a further map + V[index]->set_face(F[i]); } // read in non combinatorial info of the face is >> *(F[i]) ; } } - // Setting the neighbor pointers + // Setting the neighbor pointers { for(i = 0; i < m; ++i) { for(int j = 0; j < dimension()+1; ++j){ - is >> index; - F[i]->set_neighbor(j, F[index]); + is >> index; + F[i]->set_neighbor(j, F[index]); } } } - + return V[0]; } @@ -2266,11 +2266,11 @@ vrml_output( std::ostream& os, Vertex_handle v, bool skip_infinite) const // faces for(fit= faces_begin(); fit != faces_end(); ++fit) { if (!skip_infinite || !fit->has_vertex(v)) { - os << "\t\t\t"; - os << vmap[(*fit).vertex(0)] << ", "; - os << vmap[(*fit).vertex(1)] << ", "; - os << vmap[(*fit).vertex(2)] << ", "; - os << "-1, " << std::endl; + os << "\t\t\t"; + os << vmap[(*fit).vertex(0)] << ", "; + os << vmap[(*fit).vertex(1)] << ", "; + os << vmap[(*fit).vertex(2)] << ", "; + os << "-1, " << std::endl; } } os << "\t\t]" << std::endl; @@ -2294,8 +2294,8 @@ off_file_input( std::istream& is, bool verbose) if (! is) { if (scanner.verbose()) { std::cerr << " " << std::endl; - std::cerr << "TDS::off_file_input" << std::endl; - std::cerr << " input error: file format is not OFF." << std::endl; + std::cerr << "TDS::off_file_input" << std::endl; + std::cerr << " input error: file format is not OFF." << std::endl; } return vinf; } @@ -2330,10 +2330,10 @@ off_file_input( std::istream& is, bool verbose) scanner.scan_facet( no, i); if( ! is || no != 3) { if ( scanner.verbose()) { - std::cerr << " " << std::endl; - std::cerr << "TDS::off_file_input" << std::endl; - std::cerr << "facet " << i << "does not have 3 vertices." - << std::endl; + std::cerr << " " << std::endl; + std::cerr << "TDS::off_file_input" << std::endl; + std::cerr << "facet " << i << "does not have 3 vertices." + << std::endl; } is.clear( std::ios::badbit); return vinf; @@ -2347,7 +2347,7 @@ off_file_input( std::istream& is, bool verbose) } for (std::size_t ih = 0; ih < no; ++ih) { - set_adjacency(fh, ih, edge_map); + set_adjacency(fh, ih, edge_map); } } @@ -2358,9 +2358,9 @@ off_file_input( std::istream& is, bool verbose) while (!edge_map.empty()) { Face_handle fh = edge_map.begin()->second.first; int ih = edge_map.begin()->second.second; - Face_handle fn = create_face( vinf, - fh->vertex(cw(ih)), - fh->vertex(ccw(ih))); + Face_handle fn = create_face( vinf, + fh->vertex(cw(ih)), + fh->vertex(ccw(ih))); vinf->set_face(fn); set_adjacency(fn, 0, fh, ih); set_adjacency(fn, 1, inf_edge_map); @@ -2369,8 +2369,8 @@ off_file_input( std::istream& is, bool verbose) } CGAL_triangulation_assertion(inf_edge_map.empty()); } - - + + // coherent orientation reorient_faces(); return vinf; @@ -2380,16 +2380,16 @@ off_file_input( std::istream& is, bool verbose) template < class Vb, class Fb> void Triangulation_data_structure_2:: -set_adjacency(Face_handle fh, - int ih, - std::map< Vh_pair, Edge>& edge_map) +set_adjacency(Face_handle fh, + int ih, + std::map< Vh_pair, Edge>& edge_map) { // set adjacency to (fh,ih) using the the map edge_map // or insert (fh,ih) in edge map Vertex_handle vhcw = fh->vertex(cw(ih)); - Vertex_handle vhccw = fh->vertex(ccw(ih)); - Vh_pair vhp = vhcw < vhccw ? - std::make_pair(vhcw, vhccw) + Vertex_handle vhccw = fh->vertex(ccw(ih)); + Vh_pair vhp = vhcw < vhccw ? + std::make_pair(vhcw, vhccw) : std::make_pair(vhccw, vhcw) ; typename std::map::iterator emapit = edge_map.find(vhp); if (emapit == edge_map.end()) {// not found, insert edge @@ -2399,7 +2399,7 @@ set_adjacency(Face_handle fh, Edge e = emapit->second; set_adjacency( fh,ih, e.first, e.second); edge_map.erase(emapit); - } + } } @@ -2409,9 +2409,9 @@ void Triangulation_data_structure_2:: reorient_faces() { - // reorient the faces of a triangulation + // reorient the faces of a triangulation // needed for example in off_file_input - // because the genus is not known, the number of faces + // because the genus is not known, the number of faces std::set oriented_set; std::stack st; Face_iterator fit = faces_begin(); @@ -2419,7 +2419,7 @@ reorient_faces() while (0 != nf) { while ( !oriented_set.insert(fit).second ){ - ++fit; // find a germ for non oriented components + ++fit; // find a germ for non oriented components } // orient component --nf; @@ -2428,25 +2428,25 @@ reorient_faces() Face_handle fh = st.top(); st.pop(); for(int ih = 0 ; ih < 3 ; ++ih){ - Face_handle fn = fh->neighbor(ih); - if (oriented_set.insert(fn).second){ - int in = fn->index(fh); - if (fn->vertex(cw(in)) != fh->vertex(ccw(ih))) fn->reorient(); + Face_handle fn = fh->neighbor(ih); + if (oriented_set.insert(fn).second){ + int in = fn->index(fh); + if (fn->vertex(cw(in)) != fh->vertex(ccw(ih))) fn->reorient(); --nf; - st.push(fn); - } + st.push(fn); + } } } } return; } - + template < class Vb, class Fb> std::istream& -operator>>(std::istream& is, - Triangulation_data_structure_2& tds) +operator>>(std::istream& is, + Triangulation_data_structure_2& tds) { tds.file_input(is); return is; @@ -2455,14 +2455,14 @@ operator>>(std::istream& is, template < class Vb, class Fb> std::ostream& -operator<<(std::ostream& os, - const Triangulation_data_structure_2 &tds) +operator<<(std::ostream& os, + const Triangulation_data_structure_2 &tds) { tds.file_output(os); return os; } -} //namespace CGAL +} //namespace CGAL #endif //CGAL_TRIANGULATION_DATA_STRUCTURE_2_H diff --git a/TDS_2/include/CGAL/Triangulation_ds_face_base_2.h b/TDS_2/include/CGAL/Triangulation_ds_face_base_2.h index 8aeb12f876e..aa69ccfef05 100644 --- a/TDS_2/include/CGAL/Triangulation_ds_face_base_2.h +++ b/TDS_2/include/CGAL/Triangulation_ds_face_base_2.h @@ -6,7 +6,7 @@ // $URL$ // $Id$ // SPDX-License-Identifier: GPL-3.0-or-later OR LicenseRef-Commercial -// +// // // Author(s) : Mariette Yvinec @@ -21,10 +21,10 @@ #include #include -namespace CGAL { +namespace CGAL { template < typename TDS = void> -class Triangulation_ds_face_base_2 +class Triangulation_ds_face_base_2 { public: typedef TDS Triangulation_data_structure; @@ -32,7 +32,7 @@ public: typedef typename TDS::Face_handle Face_handle; template - struct Rebind_TDS { typedef Triangulation_ds_face_base_2 Other; }; + struct Rebind_TDS { typedef Triangulation_ds_face_base_2 Other; }; private: Vertex_handle V[3]; @@ -40,21 +40,21 @@ private: public: Triangulation_ds_face_base_2(); - Triangulation_ds_face_base_2(Vertex_handle v0, - Vertex_handle v1, - Vertex_handle v2); - Triangulation_ds_face_base_2(Vertex_handle v0, - Vertex_handle v1, - Vertex_handle v2, - Face_handle n0, - Face_handle n1, - Face_handle n2); + Triangulation_ds_face_base_2(Vertex_handle v0, + Vertex_handle v1, + Vertex_handle v2); + Triangulation_ds_face_base_2(Vertex_handle v0, + Vertex_handle v1, + Vertex_handle v2, + Face_handle n0, + Face_handle n1, + Face_handle n2); Vertex_handle vertex(int i) const; bool has_vertex(Vertex_handle v) const; bool has_vertex(Vertex_handle v, int& i) const ; int index(Vertex_handle v) const ; - + Face_handle neighbor(int i) const ; bool has_neighbor(Face_handle n) const; bool has_neighbor(Face_handle n, int& i) const; @@ -69,14 +69,14 @@ public: void reorient(); void ccw_permute(); void cw_permute(); - + int dimension() const; //the following trivial is_valid to allow - // the user of derived face base classes + // the user of derived face base classes // to add their own purpose checking bool is_valid(bool /* verbose */ = false, int /* level */ = 0) const {return true;} - + // For use by Compact_container. void * for_compact_container() const {return N[0].for_compact_container(); } void for_compact_container(void* p) { N[0].for_compact_container(p);} @@ -96,9 +96,9 @@ Triangulation_ds_face_base_2() template Triangulation_ds_face_base_2 :: -Triangulation_ds_face_base_2( Vertex_handle v0, - Vertex_handle v1, - Vertex_handle v2) +Triangulation_ds_face_base_2( Vertex_handle v0, + Vertex_handle v1, + Vertex_handle v2) { set_vertices(v0, v1, v2); set_neighbors(); @@ -106,12 +106,12 @@ Triangulation_ds_face_base_2( Vertex_handle v0, template Triangulation_ds_face_base_2 :: -Triangulation_ds_face_base_2(Vertex_handle v0, - Vertex_handle v1, - Vertex_handle v2, - Face_handle n0, - Face_handle n1, - Face_handle n2) +Triangulation_ds_face_base_2(Vertex_handle v0, + Vertex_handle v1, + Vertex_handle v2, + Face_handle n0, + Face_handle n1, + Face_handle n2) { set_vertices(v0, v1, v2); set_neighbors(n0, n1, n2); @@ -119,14 +119,14 @@ Triangulation_ds_face_base_2(Vertex_handle v0, template -inline +inline typename Triangulation_ds_face_base_2::Vertex_handle Triangulation_ds_face_base_2:: vertex(int i) const { CGAL_triangulation_precondition( i == 0 || i == 1 || i == 2); return V[i]; -} +} template @@ -136,10 +136,10 @@ has_vertex(Vertex_handle v) const { return (V[0] == v) || (V[1] == v) || (V[2]== v); } - + template inline bool -Triangulation_ds_face_base_2 :: +Triangulation_ds_face_base_2 :: has_vertex(Vertex_handle v, int& i) const { if (v == V[0]) { @@ -156,10 +156,10 @@ has_vertex(Vertex_handle v, int& i) const } return false; } - -template + +template inline int -Triangulation_ds_face_base_2 :: +Triangulation_ds_face_base_2 :: index(Vertex_handle v) const { if (v == V[0]) return 0; @@ -168,27 +168,27 @@ index(Vertex_handle v) const return 2; } -template -inline -typename Triangulation_ds_face_base_2::Face_handle +template +inline +typename Triangulation_ds_face_base_2::Face_handle Triangulation_ds_face_base_2:: neighbor(int i) const { CGAL_triangulation_precondition( i == 0 || i == 1 || i == 2); return N[i]; } - -template -inline bool + +template +inline bool Triangulation_ds_face_base_2 :: has_neighbor(Face_handle n) const { return (N[0] == n) || (N[1] == n) || (N[2] == n); } - - -template -inline bool + + +template +inline bool Triangulation_ds_face_base_2 :: has_neighbor(Face_handle n, int& i) const { @@ -207,10 +207,10 @@ has_neighbor(Face_handle n, int& i) const return false; } - - -template -inline int + + +template +inline int Triangulation_ds_face_base_2 :: index(Face_handle n) const { @@ -219,19 +219,19 @@ index(Face_handle n) const CGAL_triangulation_assertion( n == N[2] ); return 2; } - -template + +template inline void -Triangulation_ds_face_base_2 :: +Triangulation_ds_face_base_2 :: set_vertex(int i, Vertex_handle v) { CGAL_triangulation_precondition( i == 0 || i == 1 || i == 2); V[i] = v; } - -template + +template inline void -Triangulation_ds_face_base_2 :: +Triangulation_ds_face_base_2 :: set_neighbor(int i, Face_handle n) { CGAL_triangulation_precondition( i == 0 || i == 1 || i == 2); @@ -247,27 +247,27 @@ set_vertices() V[0] = V[1] = V[2] = Vertex_handle(); } -template +template inline void -Triangulation_ds_face_base_2 :: +Triangulation_ds_face_base_2 :: set_vertices(Vertex_handle v0, Vertex_handle v1, Vertex_handle v2) { V[0] = v0; V[1] = v1; V[2] = v2; } - -template + +template inline void -Triangulation_ds_face_base_2 :: +Triangulation_ds_face_base_2 :: set_neighbors() { N[0] = N[1] = N[2] = Face_handle(); } - -template + +template inline void -Triangulation_ds_face_base_2 :: +Triangulation_ds_face_base_2 :: set_neighbors(Face_handle n0,Face_handle n1, Face_handle n2) { CGAL_triangulation_precondition( this != &*n0 ); @@ -280,7 +280,7 @@ set_neighbors(Face_handle n0,Face_handle n1, Face_handle n2) template void -Triangulation_ds_face_base_2 :: +Triangulation_ds_face_base_2 :: reorient() { //exchange the vertices 0 and 1 @@ -289,7 +289,7 @@ reorient() } template -inline void +inline void Triangulation_ds_face_base_2 :: ccw_permute() { @@ -299,7 +299,7 @@ ccw_permute() template -inline void +inline void Triangulation_ds_face_base_2 :: cw_permute() { @@ -309,7 +309,7 @@ cw_permute() template < class TDS> -inline int +inline int Triangulation_ds_face_base_2 :: dimension() const { @@ -349,6 +349,6 @@ public: -} //namespace CGAL +} //namespace CGAL #endif //CGAL_DS_TRIANGULATION_FACE_BASE_2_H diff --git a/TDS_2/include/CGAL/Triangulation_ds_vertex_base_2.h b/TDS_2/include/CGAL/Triangulation_ds_vertex_base_2.h index ceabf7c4294..ba0386f747f 100644 --- a/TDS_2/include/CGAL/Triangulation_ds_vertex_base_2.h +++ b/TDS_2/include/CGAL/Triangulation_ds_vertex_base_2.h @@ -6,7 +6,7 @@ // $URL$ // $Id$ // SPDX-License-Identifier: GPL-3.0-or-later OR LicenseRef-Commercial -// +// // // Author(s) : Mariette Yvinec @@ -24,7 +24,7 @@ namespace CGAL { template < class TDS = void > -class Triangulation_ds_vertex_base_2 +class Triangulation_ds_vertex_base_2 { public: @@ -42,7 +42,7 @@ public: void set_face(Face_handle f) { _f = f ;} //the following trivial is_valid to allow - // the user of derived face base classes + // the user of derived face base classes // to add their own purpose checking bool is_valid(bool /*verbose*/=false, int /*level*/= 0) const {return face() != Face_handle();} diff --git a/TDS_2/test/TDS_2/include/CGAL/_test_cls_tds_2.h b/TDS_2/test/TDS_2/include/CGAL/_test_cls_tds_2.h index 44d04c40a9c..619b959937e 100644 --- a/TDS_2/test/TDS_2/include/CGAL/_test_cls_tds_2.h +++ b/TDS_2/test/TDS_2/include/CGAL/_test_cls_tds_2.h @@ -7,10 +7,10 @@ // intended for general use. // // ---------------------------------------------------------------------------- -// +// // release : // release_date : -// +// // file : test/Triangulation/include/CGAL/_test_cls_tds_2.h // source : $URL$ // revision : $Id$ @@ -51,7 +51,7 @@ _test_cls_tds_2( const Tds &) typedef typename Tds::Vertex_range Vertex_range; typedef typename Tds::Face_range Face_range; - + typedef typename Tds::Vertex Vertex; typedef typename Tds::Face Face; typedef typename Tds::Edge Edge; @@ -61,7 +61,7 @@ _test_cls_tds_2( const Tds &) typedef typename Tds::Vertex_iterator Vertex_iterator; typedef typename Tds::Face_iterator Face_iterator; typedef typename Tds::Edge_iterator Edge_iterator; - + typedef typename Tds::Vertex_circulator Vertex_circulator; typedef typename Tds::Face_circulator Face_circulator; typedef typename Tds::Edge_circulator Edge_circulator; @@ -71,7 +71,7 @@ _test_cls_tds_2( const Tds &) CGAL_USE_TYPE(Edge); CGAL_USE_TYPE(Edge_iterator); CGAL_USE_TYPE(Edge_circulator); - + // Test subclasses CGAL::_test_cls_tds_vertex( Tds()); CGAL::_test_cls_tds_face( Tds()); @@ -80,17 +80,17 @@ _test_cls_tds_2( const Tds &) std::cout << " constructors" << std::endl; Tds tds0; Tds tds1; - Tds tds2(tds1); + Tds tds2(tds1); Tds tds3 = tds1; Tds tds4 ; tds4.swap(tds1); tds1.is_valid(); tds1.clear(); tds1.is_valid(); - // (), = and swap to be tested later again with non trivial tds + // (), = and swap to be tested later again with non trivial tds + - // misc. std::cout << " miscellaneous" << std::endl; assert( tds1.ccw(0) == 1 ); @@ -99,21 +99,21 @@ _test_cls_tds_2( const Tds &) assert( tds1.cw(0) == 2 ); assert( tds1.cw(1) == 0 ); assert( tds1.cw(2) == 1 ); - + // test insert, remove and flip - // tds1 , tds2 0 dim + // tds1 , tds2 0 dim // tds3 1 dim // tds4 2dim std::cout << " insert and flip" << std::endl; Vertex_handle w1 = tds1.insert_first(); - assert(tds1.dimension()== -1); + assert(tds1.dimension()== -1); assert(tds1.number_of_vertices() == 1); assert(tds1.is_valid() ); Vertex_handle w2 = tds2.insert_first(); Vertex_handle v2 = tds2.insert_second(); - assert(tds2.dimension()== 0); + assert(tds2.dimension()== 0); assert(tds2.number_of_vertices() == 2); assert(tds2.is_valid() ); @@ -161,7 +161,7 @@ _test_cls_tds_2( const Tds &) assert(tds12.is_valid()); assert(tds12.dimension()==1); } - + Vertex_handle w4 = tds4.insert_first(); Vertex_handle v4_1 = tds4.insert_second(); Vertex_handle v4_2 = tds4.insert_dim_up(w4,true); @@ -184,7 +184,7 @@ _test_cls_tds_2( const Tds &) // Find the edge v4_1v4_2 for insertion fc = tds4.incident_faces(v4_1); int ic; - while(! (fc->has_vertex(v4_2, ic ) && ic == tds4.ccw(fc->index(v4_1)))) + while(! (fc->has_vertex(v4_2, ic ) && ic == tds4.ccw(fc->index(v4_1)))) fc++; Vertex_handle v4_5 = tds4.insert_in_edge(fc, ic); assert(tds4.is_valid() ); @@ -199,17 +199,17 @@ _test_cls_tds_2( const Tds &) Vertex_handle u4 = tds4.insert_in_face(v4_1->face()); tds4.remove_degree_3(u4); assert(tds4.is_valid() ); - + Vertex_handle u3 = tds3.insert_in_edge(v3->face(),2); tds3.remove_1D(u3); assert(tds3.is_valid() ); - + //remove_second, remove first tds2.remove_second(v2); assert(tds2.is_valid() && tds2.number_of_vertices()==1); v2 = tds2.insert_second(); tds1.remove_first(w1); - assert(tds1.is_valid()&& tds1.number_of_vertices()==0); + assert(tds1.is_valid()&& tds1.number_of_vertices()==0); w1 = tds1.insert_first(); // make_hole, star_hole @@ -221,7 +221,7 @@ _test_cls_tds_2( const Tds &) // insert_in_hole - // Count also the faces with the vertex at infinity! + // Count also the faces with the vertex at infinity! // // 1 |------| 3 1 |------| 3 // |\ | |\ /| @@ -231,9 +231,9 @@ _test_cls_tds_2( const Tds &) // | \ | | / \ | // | \| |/ \| // 2 |------| 0 2 |------| 0 - // - // - + // + // + std::cout << " insert_in_hole" << std::endl; Tds td45; Vertex_handle v045 = td45.insert_first(); @@ -348,7 +348,7 @@ _test_cls_tds_2( const Tds &) assert(td5.dimension() == 1); assert(td5.is_valid()); Vertex_handle v5_4 = td5.insert_dim_up(); - Face_handle f5_1 = v5_4->face(); + Face_handle f5_1 = v5_4->face(); i = f5_1->index(v5_4); td5.dim_down(f5_1, i); assert(td5.dimension() == 1); @@ -357,20 +357,20 @@ _test_cls_tds_2( const Tds &) //access std::cout << " test access" << std::endl; assert(tds0.dimension() <= -1 && tds0.number_of_vertices() == 0 && - tds0.number_of_faces()== 0 && tds0.number_of_edges() == 0 && - tds0.number_of_full_dim_faces() == 0); + tds0.number_of_faces()== 0 && tds0.number_of_edges() == 0 && + tds0.number_of_full_dim_faces() == 0); assert(tds1.dimension() == -1 && tds1.number_of_vertices() == 1 && - tds1.number_of_faces()== 0 && tds1.number_of_edges() == 0 && - tds1.number_of_full_dim_faces() == 1); + tds1.number_of_faces()== 0 && tds1.number_of_edges() == 0 && + tds1.number_of_full_dim_faces() == 1); assert(tds2.dimension() == 0 && tds2.number_of_vertices() == 2 && - tds2.number_of_faces()== 0 && tds2.number_of_edges() == 0 && - tds2.number_of_full_dim_faces() == 2); + tds2.number_of_faces()== 0 && tds2.number_of_edges() == 0 && + tds2.number_of_full_dim_faces() == 2); assert(tds3.dimension() == 1 && tds3.number_of_vertices() == 4 && - tds3.number_of_faces()== 0 && tds3.number_of_edges() == 4 && - tds3.number_of_full_dim_faces() == 4); + tds3.number_of_faces()== 0 && tds3.number_of_edges() == 4 && + tds3.number_of_full_dim_faces() == 4); assert(tds4.dimension() == 2 && tds4.number_of_vertices() == 6 && - tds4.number_of_faces()== 8 && tds4.number_of_edges() == 12 && - tds4.number_of_full_dim_faces() == 8); + tds4.number_of_faces()== 8 && tds4.number_of_edges() == 12 && + tds4.number_of_full_dim_faces() == 8); // Containers Vertex_range & vertex_c = tds4.vertices(); @@ -378,7 +378,7 @@ _test_cls_tds_2( const Tds &) assert(vertex_c.size() == 6); assert(face_c.size() == 8); - + //clear(), swap() and copy_constructor and copy std::cout << " clear, swap, assign and copy " << std::endl; Tds tds1b(tds1); @@ -447,7 +447,7 @@ _test_cls_tds_2( const Tds &) assert (tds4.is_vertex(v4_5)); assert (tds3.is_vertex(v3)); assert (tds2.is_vertex(v2)); - + // test compatibility of iterators and circulators with handle() Vertex_iterator vit=tds4.vertices_begin(); assert(tds4.is_vertex(vit)); @@ -465,43 +465,43 @@ _test_cls_tds_2( const Tds &) std::cout << " output to a file" << std::endl; std::ofstream of0("file_tds0"); - CGAL::set_ascii_mode(of0); - of0 << tds0 ; + CGAL::set_ascii_mode(of0); + of0 << tds0 ; of0.close(); std::ofstream of1("file_tds1"); - CGAL::set_ascii_mode(of1); - of1 << tds1 ; + CGAL::set_ascii_mode(of1); + of1 << tds1 ; of1.close(); std::ofstream of2("file_tds2"); - CGAL::set_ascii_mode(of2); - of2 << tds2 ; + CGAL::set_ascii_mode(of2); + of2 << tds2 ; of2.close(); std::ofstream of3("file_tds3"); - CGAL::set_ascii_mode(of3); - of3 << tds3 ; + CGAL::set_ascii_mode(of3); + of3 << tds3 ; of3.close(); std::ofstream of4("file_tds4"); - CGAL::set_ascii_mode(of4); - of4 << tds4 ; + CGAL::set_ascii_mode(of4); + of4 << tds4 ; of4.close(); std::cout << " input from a file" << std::endl; std::ifstream if0("file_tds0"); CGAL::set_ascii_mode(if0); Tds tds0f; if0 >> tds0f ; assert( tds0f.is_valid()); std::ifstream if1("file_tds1"); CGAL::set_ascii_mode(if1); - Tds tds1f; if1 >> tds1f; + Tds tds1f; if1 >> tds1f; assert( tds1f.is_valid()); - std::ifstream if2("file_tds2"); + std::ifstream if2("file_tds2"); CGAL::set_ascii_mode(if2); - Tds tds2f; if2 >> tds2f ; + Tds tds2f; if2 >> tds2f ; assert( tds2f.is_valid()); - std::ifstream if3("file_tds3"); + std::ifstream if3("file_tds3"); CGAL::set_ascii_mode(if3); - Tds tds3f; if3 >> tds3f ; + Tds tds3f; if3 >> tds3f ; assert( tds3f.is_valid()); - std::ifstream if4("file_tds4"); + std::ifstream if4("file_tds4"); CGAL::set_ascii_mode(if4); - Tds tds4f; if4 >> tds4f ; + Tds tds4f; if4 >> tds4f ; assert( tds4f.is_valid()); // vrml input-output @@ -542,17 +542,17 @@ _test_tds_circulators( const Tds& tds) Vertex_handle vh; for( Vertex_iterator vit = tds.vertices_begin(); - vit != tds.vertices_end(); vit++) { - + vit != tds.vertices_end(); vit++) { + Face_circulator fc = tds.incident_faces(vit), fdone(fc); Face_circulator fc2 = tds.incident_faces(vit); assert(fc2 == fc); if (! fc.is_empty()) { do { - f = *fc; - fh = fc; - vh = fc->vertex(0); - countf +=1; + f = *fc; + fh = fc; + vh = fc->vertex(0); + countf +=1; } while (++fc != fdone); } @@ -561,9 +561,9 @@ _test_tds_circulators( const Tds& tds) if (! ec.is_empty()) assert( ec2 == ec); if (! ec.is_empty()) { do { - e = *ec; - fh = ec->first; - counte +=1; + e = *ec; + fh = ec->first; + counte +=1; } while (++ec != edone); } @@ -573,21 +573,21 @@ _test_tds_circulators( const Tds& tds) if (! vc.is_empty()) assert( vc == vc2); if (! vc.is_empty()) { do { - v = *vc; - vh = vc; - fh = vc->face(); - countv +=1; - countvv +=1; + v = *vc; + vh = vc; + fh = vc->face(); + countv +=1; + countvv +=1; } while (++vc != vdone); } assert( tds.degree(vit) == countvv); - } - + } + assert( countf == 3 * tds.number_of_faces()); assert( counte == 2 * tds.number_of_edges()); assert( countv == counte); - + } template< class Tds> @@ -631,7 +631,7 @@ _test_tds_iterators( const Tds& tds) } assert(nv == 0); - + for (Face_iterator fitp = tds.faces_begin(); fitp != tds.faces_end(); ++fitp) { diff --git a/TDS_3/doc/TDS_3/Concepts/TriangulationDSCellBase_3.h b/TDS_3/doc/TDS_3/Concepts/TriangulationDSCellBase_3.h index 9b9bffacd71..0c7108a3d67 100644 --- a/TDS_3/doc/TDS_3/Concepts/TriangulationDSCellBase_3.h +++ b/TDS_3/doc/TDS_3/Concepts/TriangulationDSCellBase_3.h @@ -13,29 +13,29 @@ is plugged into a triangulation class, the face base class may have additional geometric requirements depending on the triangulation class. -At the base level -(see the Software Design sections of the Chapters \ref Triangulation3secdesign "Triangulation" -and \ref TDS3secdesign "Triangulation Datastructure"), -a cell stores handles to its four vertices and to its four neighbor cells. -The vertices and neighbors are indexed 0, 1, 2 and 3. Neighbor `i` -lies opposite to vertex `i`. +At the base level +(see the Software Design sections of the Chapters \ref Triangulation3secdesign "Triangulation" +and \ref TDS3secdesign "Triangulation Datastructure"), +a cell stores handles to its four vertices and to its four neighbor cells. +The vertices and neighbors are indexed 0, 1, 2 and 3. Neighbor `i` +lies opposite to vertex `i`. -Since the Triangulation data structure is the class which defines the handle -types, the cell base class has to be somehow parameterized by the Triangulation -data structure. But since it is itself parameterized by the cell and vertex -base classes, there is a cycle in the definition of these classes. In order -to break the cycle, the base classes for vertex and cell which are given as -arguments for the Triangulation data structure use `void` as Triangulation -data structure parameter, and the Triangulation data structure then uses a -rebind-like mechanism (similar to the one specified in -`std::allocator`) in order to put itself as parameter to the vertex and -cell classes. The rebound base classes so obtained are the classes -which are used as base classes for the final vertex and cell classes. -More information can be found in Section \ref TDS3secdesign. +Since the Triangulation data structure is the class which defines the handle +types, the cell base class has to be somehow parameterized by the Triangulation +data structure. But since it is itself parameterized by the cell and vertex +base classes, there is a cycle in the definition of these classes. In order +to break the cycle, the base classes for vertex and cell which are given as +arguments for the Triangulation data structure use `void` as Triangulation +data structure parameter, and the Triangulation data structure then uses a +rebind-like mechanism (similar to the one specified in +`std::allocator`) in order to put itself as parameter to the vertex and +cell classes. The rebound base classes so obtained are the classes +which are used as base classes for the final vertex and cell classes. +More information can be found in Section \ref TDS3secdesign. \cgalHasModel `CGAL::Triangulation_ds_cell_base_3` -\sa `TriangulationDSVertexBase_3` +\sa `TriangulationDSVertexBase_3` \sa `CGAL::Triangulation_data_structure_3` */ @@ -44,13 +44,13 @@ class TriangulationDSCellBase_3 { public: -/// \name Types +/// \name Types /// A model of the concept `TriangulationDSCellBase_3` has to provide the following types. /// @{ /*! This template class has to define a type `Rebind_TDS::%Other` which is the -rebound cell, that is, the one whose `Triangulation_data_structure` +rebound cell, that is, the one whose `Triangulation_data_structure` will be the actually used one. `Rebind_TDS::%Other` will be the real base class of `Triangulation_data_structure_3::Cell`. \note It can be implemented using a nested template class. @@ -61,63 +61,63 @@ using Rebind_TDS = unspecified_type; /*! -*/ -typedef TriangulationDataStructure_3 Triangulation_data_structure; +*/ +typedef TriangulationDataStructure_3 Triangulation_data_structure; /*! -*/ -typedef TriangulationDataStructure_3::Vertex_handle Vertex_handle; +*/ +typedef TriangulationDataStructure_3::Vertex_handle Vertex_handle; /*! -*/ -typedef TriangulationDataStructure_3::Cell_handle Cell_handle; +*/ +typedef TriangulationDataStructure_3::Cell_handle Cell_handle; -/// @} +/// @} -/// \name Creation +/// \name Creation /// @{ /*! -Default constructor -*/ +Default constructor +*/ TriangulationDSCellBase_3(); /*! -Initializes the vertices with `v0, v1, v2, v3`. Neighbors are -initialized to the default constructed handle. -*/ +Initializes the vertices with `v0, v1, v2, v3`. Neighbors are +initialized to the default constructed handle. +*/ TriangulationDSCellBase_3( Vertex_handle v0, Vertex_handle v1, Vertex_handle v2, Vertex_handle v3); /*! -Initializes the vertices with `v0, v1, v2, v3` and the neighbors with -`n0, n1, n2, n3`. -*/ +Initializes the vertices with `v0, v1, v2, v3` and the neighbors with +`n0, n1, n2, n3`. +*/ TriangulationDSCellBase_3( Vertex_handle v0, Vertex_handle v1, Vertex_handle v2, Vertex_handle v3, Cell_handle n0, Cell_handle n1, Cell_handle n2, Cell_handle n3); -/// @} +/// @} -/// \name Checking +/// \name Checking /// @{ /*! -Performs any desired geometric test on a cell. +Performs any desired geometric test on a cell. \cgalDebugFunction \cgalDebugBegin -When `verbose` is set to `true`, messages are printed to give -a precise indication of the kind of invalidity encountered. `level` -increases the level of testing. +When `verbose` is set to `true`, messages are printed to give +a precise indication of the kind of invalidity encountered. `level` +increases the level of testing. \cgalDebugEnd -*/ -bool is_valid(bool verbose = false, int level = 0) const; +*/ +bool is_valid(bool verbose = false, int level = 0) const; -/// @} +/// @} /// \name Members for Compact_container /// \cgalAdvancedBegin @@ -130,12 +130,12 @@ bool is_valid(bool verbose = false, int level = 0) const; /*! -*/ -void * for_compact_container() const; +*/ +void * for_compact_container() const; /*! -*/ +*/ void for_compact_container(void *p); /// @} @@ -144,14 +144,14 @@ void for_compact_container(void *p); /// @{ /*! -Inputs the possible non combinatorial information given by the cell. -*/ -istream& operator>> (istream& is, TriangulationDSCellBase_3 & c); +Inputs the possible non combinatorial information given by the cell. +*/ +istream& operator>> (istream& is, TriangulationDSCellBase_3 & c); /*! -Outputs the possible non combinatorial information given by the cell. -*/ -ostream& operator<< (ostream& os, const TriangulationDSCellBase_3 & c); +Outputs the possible non combinatorial information given by the cell. +*/ +ostream& operator<< (ostream& os, const TriangulationDSCellBase_3 & c); /// @} diff --git a/TDS_3/doc/TDS_3/Concepts/TriangulationDSVertexBase_3.h b/TDS_3/doc/TDS_3/Concepts/TriangulationDSVertexBase_3.h index c7b68ec9175..9435ee7e9e5 100644 --- a/TDS_3/doc/TDS_3/Concepts/TriangulationDSVertexBase_3.h +++ b/TDS_3/doc/TDS_3/Concepts/TriangulationDSVertexBase_3.h @@ -11,22 +11,22 @@ of a CGAL::Triangulation_data_structure_3. Note that if the `CGAL::Triangulation_data_structure_3` is plugged into a triangulation class, the vertex base class may have additional geometric requirements depending on the triangulation class. -At the bottom level of 3D-triangulations -(see Sections \ref Triangulation3secdesign and \ref TDS3secdesign), -a vertex provides access to one of its incident cells through a handle. +At the bottom level of 3D-triangulations +(see Sections \ref Triangulation3secdesign and \ref TDS3secdesign), +a vertex provides access to one of its incident cells through a handle. -Since the Triangulation data structure is the class which defines the handle -types, the vertex base class has to be somehow parameterized by the -Triangulation data structure. But since it is itself parameterized by the cell -and vertex base classes, there is a cycle in the definition of these classes. -In order to break the cycle, the base classes for vertex and cell which are -given as arguments for the Triangulation data structure use `void` as -Triangulation data structure parameter, and the Triangulation data structure -then uses a rebind-like mechanism (similar to the one specified in -`std::allocator`) in order to put itself as parameter to the vertex and -cell classes. The rebound base classes so obtained are the classes which -are used as base classes for the final vertex and cell classes. -More information can be found in Section \ref TDS3secdesign. +Since the Triangulation data structure is the class which defines the handle +types, the vertex base class has to be somehow parameterized by the +Triangulation data structure. But since it is itself parameterized by the cell +and vertex base classes, there is a cycle in the definition of these classes. +In order to break the cycle, the base classes for vertex and cell which are +given as arguments for the Triangulation data structure use `void` as +Triangulation data structure parameter, and the Triangulation data structure +then uses a rebind-like mechanism (similar to the one specified in +`std::allocator`) in order to put itself as parameter to the vertex and +cell classes. The rebound base classes so obtained are the classes which +are used as base classes for the final vertex and cell classes. +More information can be found in Section \ref TDS3secdesign. \cgalHasModel `CGAL::Triangulation_ds_vertex_base_3` @@ -39,65 +39,65 @@ class TriangulationDSVertexBase_3 { public: -/// \name Types +/// \name Types /// @{ /*! This template class has to define a type `Rebind_TDS::%Other` which is the -rebound vertex, that is, the one whose `Triangulation_data_structure` +rebound vertex, that is, the one whose `Triangulation_data_structure` will be the actually used one. `Rebind_TDS::%Other` will be the real base class of `Triangulation_data_structure_3::Vertex`. \note It can be implemented using a nested template class. \sa Section \ref tds3cyclic -*/ +*/ template -using Rebind_TDS = unspecified_type; +using Rebind_TDS = unspecified_type; /*! -*/ -typedef TriangulationDataStructure_3 Triangulation_data_structure; +*/ +typedef TriangulationDataStructure_3 Triangulation_data_structure; /*! -*/ -typedef TriangulationDataStructure_3::Vertex_handle Vertex_handle; +*/ +typedef TriangulationDataStructure_3::Vertex_handle Vertex_handle; /*! -*/ -typedef TriangulationDataStructure_3::Cell_handle Cell_handle; +*/ +typedef TriangulationDataStructure_3::Cell_handle Cell_handle; -/// @} +/// @} -/// \name Creation +/// \name Creation /// @{ /*! -Default constructor. -*/ +Default constructor. +*/ TriangulationDSVertexBase_3(); /*! -Constructs a vertex pointing to cell `c`. -*/ +Constructs a vertex pointing to cell `c`. +*/ TriangulationDSVertexBase_3(Cell_handle c); -/// @} +/// @} -/// \name Checking +/// \name Checking /// @{ /*! \cgalDebugFunction \cgalDebugBegin -Performs any desired test on a vertex. Checks that the -pointer to an incident cell is not the default constructed handle. +Performs any desired test on a vertex. Checks that the +pointer to an incident cell is not the default constructed handle. \cgalDebugEnd -*/ -bool is_valid(bool verbose=false, int level=0) const; +*/ +bool is_valid(bool verbose=false, int level=0) const; -/// @} +/// @} /// \name Members for Compact_container /// \cgalAdvancedBegin @@ -110,23 +110,23 @@ bool is_valid(bool verbose=false, int level=0) const; /*! -*/ -void * for_compact_container() const; +*/ +void * for_compact_container() const; /*! -*/ +*/ void for_compact_container(void *); /*! -Inputs the non-combinatorial information given by the vertex. -*/ -istream& operator>> (istream& is, TriangulationDSVertexBase_3 & v); +Inputs the non-combinatorial information given by the vertex. +*/ +istream& operator>> (istream& is, TriangulationDSVertexBase_3 & v); /*! -Outputs the non-combinatorial information given by the vertex. -*/ -ostream& operator<< (ostream& os, const TriangulationDSVertexBase_3 & v); +Outputs the non-combinatorial information given by the vertex. +*/ +ostream& operator<< (ostream& os, const TriangulationDSVertexBase_3 & v); /// @} diff --git a/TDS_3/include/CGAL/Triangulation_data_structure_3.h b/TDS_3/include/CGAL/Triangulation_data_structure_3.h index 82744371605..b97d7487663 100644 --- a/TDS_3/include/CGAL/Triangulation_data_structure_3.h +++ b/TDS_3/include/CGAL/Triangulation_data_structure_3.h @@ -118,7 +118,7 @@ private: friend class internal::Triangulation_ds_facet_circulator_3; public: - + // Cells // N.B.: Concurrent_compact_container requires TBB #ifdef CGAL_LINKED_WITH_TBB @@ -147,7 +147,7 @@ public: typedef Compact_container Vertex_range; #endif - + typedef typename Cell_range::size_type size_type; typedef typename Cell_range::difference_type difference_type; @@ -165,7 +165,7 @@ public: typedef Iterator_range Facets; typedef Iterator_range Edges; - + //private: // In 2D only : typedef internal::Triangulation_ds_face_circulator_3 Face_circulator; @@ -217,7 +217,7 @@ public: a6=v6; } }; -//#endif +//#endif public: @@ -595,7 +595,7 @@ public: //INSERTION - + // Create a finite cell with v1, v2, v3 and v4 // Precondition: v1, v2, v3 and v4 MUST BE positively oriented Vertex_handle insert_first_finite_cell( @@ -656,9 +656,9 @@ public: Cell_handles cell_handles() const { - return make_prevent_deref_range(cells_begin(), cells_end()); + return make_prevent_deref_range(cells_begin(), cells_end()); } - + Cell_iterator raw_cells_begin() const { return cells().begin(); @@ -685,7 +685,7 @@ public: { return Facets(facets_begin(), facets_end()); } - + Edge_iterator edges_begin() const { if ( dimension() < 1 ) @@ -702,7 +702,7 @@ public: { return Edges(edges_begin(), edges_end()); } - + Vertex_iterator vertices_begin() const { return vertices().begin(); @@ -715,9 +715,9 @@ public: Vertex_handles vertex_handles() const { - return make_prevent_deref_range(vertices_begin(), vertices_end()); + return make_prevent_deref_range(vertices_begin(), vertices_end()); } - + // CIRCULATOR METHODS // cells around an edge @@ -796,16 +796,16 @@ private: IncidentFacetIterator> it) const { CGAL_triangulation_precondition(dimension() == 3); - + std::stack cell_stack; cell_stack.push(d); d->tds_data().mark_in_conflict(); *it.first++ = d; - + do { Cell_handle c = cell_stack.top(); cell_stack.pop(); - + for (int i=0; i<4; ++i) { if (c->vertex(i) == v) continue; @@ -852,7 +852,7 @@ private: ++head; } while(head != tail); } - + void just_incident_cells_3(Vertex_handle v, std::vector& cells) const { @@ -1002,7 +1002,7 @@ public: Filter filter; public: Vertex_extractor(Vertex_handle _v, OutputIterator _output, const Tds* _t, Filter _filter): - v(_v), treat(_output), t(_t), filter(_filter) + v(_v), treat(_output), t(_t), filter(_filter) { #if ( BOOST_VERSION >= 105000 ) tmp_vertices.reserve(64); @@ -1046,15 +1046,15 @@ public: void operator()(Cell_handle c) { for (int j=0; j<= t->dimension(); ++j) { - Vertex_handle w = c->vertex(j); - if(filter(w)) - continue; - if (w != v){ + Vertex_handle w = c->vertex(j); + if(filter(w)) + continue; + if (w != v){ if(! w->visited_for_vertex_extractor){ w->visited_for_vertex_extractor = true; tmp_vertices.push_back(w); - treat(c, v, j); + treat(c, v, j); } } } @@ -1134,7 +1134,7 @@ public: void incident_cells_3(Vertex_handle v, std::vector& cells) const { - just_incident_cells_3(v, cells); + just_incident_cells_3(v, cells); typename std::vector::iterator cit,end; for(cit = cells.begin(), end = cells.end(); cit != end; @@ -1143,7 +1143,7 @@ public: (*cit)->tds_data().clear(); } } - + template OutputIterator incident_cells_threadsafe(Vertex_handle v, OutputIterator cells, Filter f = Filter()) const @@ -1176,7 +1176,7 @@ public: { return incident_facets(v, facets); } - + template OutputIterator incident_facets_threadsafe(Vertex_handle v, OutputIterator facets, Filter f = Filter()) const @@ -1235,7 +1235,7 @@ public: template OutputIterator incident_edges_threadsafe(Vertex_handle v, OutputIterator edges, - Filter f = Filter()) const + Filter f = Filter()) const { CGAL_triangulation_precondition( v != Vertex_handle() ); CGAL_triangulation_precondition( dimension() >= 1 ); @@ -1346,11 +1346,11 @@ public: { (*cit)->tds_data().clear(); visit(*cit); - } + } return visit.result(); } - + template OutputIterator visit_incident_cells_threadsafe( @@ -1378,14 +1378,14 @@ public: ++cit) { visit(*cit); - } + } return visit.result(); } - + template OutputIterator - visit_incident_cells(Vertex_handle v, OutputIterator output, + visit_incident_cells(Vertex_handle v, OutputIterator output, std::vector &cells, Filter f) const { CGAL_triangulation_precondition( v != Vertex_handle() ); @@ -1442,7 +1442,7 @@ public: } return visit.result(); } - + // For dimension 3 only template OutputVertexIterator @@ -1455,12 +1455,12 @@ public: CGAL_triangulation_expensive_precondition( is_vertex(v) ); CGAL_triangulation_expensive_precondition( is_valid() ); - return + return visit_incident_cells < Vertex_extractor, - OutputVertexIterator, - VertexFilter, + OutputVertexIterator, + VertexFilter, internal::Has_member_visited::value>, OutputVertexIterator >(v, vertices, cells, f); @@ -1497,7 +1497,7 @@ public: template Vertex_handle copy_tds(const TDS_src&, typename TDS_src::Vertex_handle,const ConvertVertex&,const ConvertCell&); - + void swap(Tds & tds); void clear(); @@ -1708,9 +1708,9 @@ non_recursive_create_star_3(Vertex_handle v, Cell_handle c, int li, int prev_ind cnew->set_vertex(li, v); Cell_handle c_li = c->neighbor(li); set_adjacency(cnew, li, c_li, c_li->index(c)); - + std::stack adjacency_info_stack; - + int ii=0; do { @@ -1751,14 +1751,14 @@ non_recursive_create_star_3(Vertex_handle v, Cell_handle c, int li, int prev_ind cnew = create_cell(c->vertex(0),c->vertex(1),c->vertex(2),c->vertex(3)); cnew->set_vertex(li, v); c_li = c->neighbor(li); - set_adjacency(cnew, li, c_li, c_li->index(c)); + set_adjacency(cnew, li, c_li, c_li->index(c)); continue; } set_adjacency(nnn, zzz, cnew, ii); } while (++ii==4){ if ( adjacency_info_stack.empty() ) return cnew; - Cell_handle nnn=cnew; + Cell_handle nnn=cnew; int zzz; adjacency_info_stack.top().update_variables(zzz,cnew,ii,c,li,prev_ind2); adjacency_info_stack.pop(); @@ -2615,7 +2615,7 @@ Triangulation_data_structure_3::insert_first_finite_cell( Vertex_handle &v0, Vertex_handle &v1, Vertex_handle &v2, Vertex_handle &v3, Vertex_handle v_infinite) { - CGAL_triangulation_precondition( + CGAL_triangulation_precondition( (v_infinite == Vertex_handle() && dimension() == -2) || (v_infinite != Vertex_handle() && dimension() == -1)); @@ -2965,32 +2965,32 @@ insert_increase_dimension(Vertex_handle star) CGAL_assertion(i==0 || i==1); int j = (i == 0) ? 1 : 0; Cell_handle d = c->neighbor(j); - + c->set_vertex(2,v); Cell_handle e = c->neighbor(i); Cell_handle cnew = c; Cell_handle enew = Cell_handle(); - + while( e != d ){ enew = create_cell(); enew->set_vertex(i,e->vertex(j)); enew->set_vertex(j,e->vertex(i)); enew->set_vertex(2,star); - + set_adjacency(enew, i, cnew, j); // false at the first iteration of the loop where it should // be neighbor 2 // it is corrected after the loop set_adjacency(enew, 2, e, 2); // neighbor j will be set during next iteration of the loop - + e->set_vertex(2,v); e = e->neighbor(i); cnew = enew; } - + d->set_vertex(2,v); set_adjacency(enew, j, d, 2); @@ -3308,7 +3308,7 @@ decrease_dimension(Cell_handle c, int i) for( ; lfit != to_downgrade.end(); ++lfit) { Cell_handle f = *lfit; int j = f->index(w); - int k; + int k; if (f->has_vertex(v, k)) f->set_vertex(k, w); if (j != dimension()) { f->set_vertex(j, f->vertex(dimension())); @@ -3337,13 +3337,13 @@ decrease_dimension(Cell_handle c, int i) Vertex_handle v0 = c->vertex(0); Vertex_handle v1 = c->vertex(1); Vertex_handle v2 = c->vertex(2); - + int i0 = 0, i1 = 0, i2 = 0; - + for(int i=0; i<3; i++) if(n0->neighbor(i) == c) { i0 = i; break; } for(int i=0; i<3; i++) if(n1->neighbor(i) == c) { i1 = i; break; } for(int i=0; i<3; i++) if(n2->neighbor(i) == c) { i2 = i; break; } - + Cell_handle c1 = create_cell(v, v0, v1, Vertex_handle()); Cell_handle c2 = create_cell(v, v1, v2, Vertex_handle()); @@ -3354,42 +3354,42 @@ decrease_dimension(Cell_handle c, int i) //Cell_handle c3 = create_cell(v, v2, v0, Vertex_handle()); Cell_handle c3 = c; - + c1->set_neighbor(0, n2); n2->set_neighbor(i2, c1); - c1->set_neighbor(1, c2); + c1->set_neighbor(1, c2); c1->set_neighbor(2, c3); c1->set_neighbor(3, Cell_handle()); - + c2->set_neighbor(0, n0); n0->set_neighbor(i0, c2); - c2->set_neighbor(1, c3); + c2->set_neighbor(1, c3); c2->set_neighbor(2, c1); c2->set_neighbor(3, Cell_handle()); - + c3->set_neighbor(0, n1); n1->set_neighbor(i1, c3); - c3->set_neighbor(1, c1); + c3->set_neighbor(1, c1); c3->set_neighbor(2, c2); c3->set_neighbor(3, Cell_handle()); - + v->set_cell(c1); v0->set_cell(c1); v1->set_cell(c1); v2->set_cell(c2); } - + if(dimension() == 1) { Cell_handle n0 = c->neighbor(0); Cell_handle n1 = c->neighbor(1); Vertex_handle v0 = c->vertex(0); Vertex_handle v1 = c->vertex(1); - + int i0 = 0 , i1 = 0; - + for(int i=0; i<2; i++) if(n0->neighbor(i) == c) { i0 = i; break; } for(int i=0; i<2; i++) if(n1->neighbor(i) == c) { i1 = i; break; } - + Cell_handle c1 = create_cell(v0, v, Vertex_handle(), Vertex_handle()); - + c->set_vertex(0, v); c->set_vertex(1, v1); c->set_vertex(2, Vertex_handle()); @@ -3397,22 +3397,22 @@ decrease_dimension(Cell_handle c, int i) //Cell_handle c2 = create_cell(v, v1, Vertex_handle(), Vertex_handle()); Cell_handle c2 = c; - - c1->set_neighbor(0, c2); + + c1->set_neighbor(0, c2); c1->set_neighbor(1, n1); n1->set_neighbor(i1, c1); c1->set_neighbor(2, Cell_handle()); c1->set_neighbor(3, Cell_handle()); - + c2->set_neighbor(0, n0); n0->set_neighbor(i0, c2); - c2->set_neighbor(1, c1); + c2->set_neighbor(1, c1); c2->set_neighbor(2, Cell_handle()); c2->set_neighbor(3, Cell_handle()); - + v->set_cell(c1); v0->set_cell(c1); v1->set_cell(c2); } - + CGAL_triangulation_postcondition(is_valid()); } @@ -3435,14 +3435,14 @@ is_valid(bool verbose, int level ) const switch ( dimension() ) { case 3: { - + if(number_of_vertices() <= 4) { if (verbose) std::cerr << "wrong number of vertices" << std::endl; CGAL_triangulation_assertion(false); return false; } - + size_type vertex_count; if ( ! count_vertices(vertex_count,verbose,level) ) return false; @@ -3475,16 +3475,16 @@ is_valid(bool verbose, int level ) const } case 2: { - + if(number_of_vertices() <= 3) { if (verbose) std::cerr << "wrong number of vertices" << std::endl; CGAL_triangulation_assertion(false); return false; } - + size_type vertex_count; - + if ( ! count_vertices(vertex_count,verbose,level) ) return false; if ( number_of_vertices() != vertex_count ) { @@ -3521,14 +3521,14 @@ is_valid(bool verbose, int level ) const } case 1: { - + if(number_of_vertices() <= 1) { if (verbose) std::cerr << "wrong number of vertices" << std::endl; CGAL_triangulation_assertion(false); return false; } - + size_type vertex_count; if ( ! count_vertices(vertex_count,verbose,level) ) return false; @@ -3815,7 +3815,7 @@ is_valid(Cell_handle c, bool verbose, int level) const CGAL_triangulation_assertion(false); return false; } - + int j1n=4,j2n=4,j3n=4; if ( ! n->has_vertex(c->vertex((i+1)&3),j1n) ) { if (verbose) { std::cerr << "vertex " << ((i+1)&3) @@ -3838,14 +3838,14 @@ is_valid(Cell_handle c, bool verbose, int level) const CGAL_triangulation_assertion(false); return false; } - + if ( in+j1n+j2n+j3n != 6) { if (verbose) { std::cerr << "sum of the indices != 6 " << std::endl; } CGAL_triangulation_assertion(false); return false; } - + // tests whether the orientations of this and n are consistent if ( ((i+in)&1) == 0 ) { // i and in have the same parity if ( j1n == ((in+1)&3) ) { @@ -3928,7 +3928,7 @@ copy_tds(const TDS_src& tds, size_type n = tds.number_of_vertices(); set_dimension(tds.dimension()); - if (n == 0) return Vertex_handle(); + if (n == 0) return Vertex_handle(); // Number of pointers to cell/vertex to copy per cell. int dim = (std::max)(1, dimension() + 1); @@ -3945,7 +3945,7 @@ copy_tds(const TDS_src& tds, Unique_hash_map< typename TDS_src::Vertex_handle,Vertex_handle > V; Unique_hash_map< typename TDS_src::Cell_handle,Cell_handle > F; - + for (i=0; i <= n-1; ++i){ Vertex_handle vh=create_vertex( convert_vertex(*TV[i]) ); V[ TV[i] ] = vh; @@ -3987,7 +3987,7 @@ namespace internal { namespace TDS_3{ Vertex_tgt operator()(const Vertex_src& src) const { return Vertex_tgt(src.point()); } - + void operator()(const Vertex_src&,Vertex_tgt&) const {} }; @@ -3997,26 +3997,26 @@ namespace internal { namespace TDS_3{ Cell_tgt operator()(const Cell_src&) const { return Cell_tgt(); } - + void operator()(const Cell_src&,Cell_tgt&) const {} }; - + template struct Default_vertex_converter { const Vertex& operator()(const Vertex& src) const { return src; } - + void operator()(const Vertex&,Vertex&) const {} }; - + template struct Default_cell_converter{ const Cell& operator()(const Cell& src) const { return src; - } - + } + void operator()(const Cell&,Cell&) const {} }; } } //namespace internal::TDS_3 diff --git a/TDS_3/include/CGAL/Triangulation_ds_cell_base_3.h b/TDS_3/include/CGAL/Triangulation_ds_cell_base_3.h index f8449c7eb8c..63607e3cb02 100644 --- a/TDS_3/include/CGAL/Triangulation_ds_cell_base_3.h +++ b/TDS_3/include/CGAL/Triangulation_ds_cell_base_3.h @@ -38,7 +38,7 @@ public: template struct Rebind_TDS { typedef Triangulation_ds_cell_base_3 Other; }; - Triangulation_ds_cell_base_3() + Triangulation_ds_cell_base_3() { #ifdef SHOW_REMAINING_BAD_ELEMENT_IN_RED mark = -1; @@ -185,7 +185,7 @@ public: // TDS internal data access functions. TDS_data& tds_data() { return _tds_data; } const TDS_data& tds_data() const { return _tds_data; } - + #ifdef SHOW_REMAINING_BAD_ELEMENT_IN_RED int mark; int mark2; diff --git a/TDS_3/include/CGAL/Triangulation_ds_vertex_base_3.h b/TDS_3/include/CGAL/Triangulation_ds_vertex_base_3.h index f338340b50a..3322157b797 100644 --- a/TDS_3/include/CGAL/Triangulation_ds_vertex_base_3.h +++ b/TDS_3/include/CGAL/Triangulation_ds_vertex_base_3.h @@ -31,17 +31,17 @@ public: template struct Rebind_TDS { typedef Triangulation_ds_vertex_base_3 Other; }; - + Triangulation_ds_vertex_base_3() - : _c(), visited_for_vertex_extractor(false) + : _c(), visited_for_vertex_extractor(false) {} Triangulation_ds_vertex_base_3(Cell_handle c) - : _c(c), visited_for_vertex_extractor(false) + : _c(c), visited_for_vertex_extractor(false) {} - Cell_handle cell() const - { return _c; } + Cell_handle cell() const + { return _c; } void set_cell(Cell_handle c) { diff --git a/TDS_3/test/TDS_3/include/CGAL/_test_cls_tds_3.h b/TDS_3/test/TDS_3/include/CGAL/_test_cls_tds_3.h index bdf03c645d8..1364bf8b137 100644 --- a/TDS_3/test/TDS_3/include/CGAL/_test_cls_tds_3.h +++ b/TDS_3/test/TDS_3/include/CGAL/_test_cls_tds_3.h @@ -6,7 +6,7 @@ // $URL$ // $Id$ // SPDX-License-Identifier: GPL-3.0-or-later OR LicenseRef-Commercial -// +// // // Author(s) : Francois Rebufat // Monique Teillaud @@ -69,14 +69,14 @@ _test_cls_tds_3( const Tds &) _test_cell_tds_3(Tds()); std::cout << " Testing TDS " << std::endl; - + // Test constructors std::cout << " constructors" << std::endl; Tds tds1; Tds tds2; // Test I/O for dimension -2 - // the other dimensions are not tested here + // the other dimensions are not tested here // (they are implicitely tested in triangulation) Tds tdsfromfile; std::cout << " I/O" << std::endl; @@ -191,7 +191,7 @@ _test_cls_tds_3( const Tds &) std::vector Cell_v; for (cit = tds6.cells_begin(); cit != tds6.cells_end(); ++cit) Cell_v.push_back(cit); - + for (typename std::vector::const_iterator ccit = Cell_v.begin(); ccit != Cell_v.end(); ++ccit) { for ( i=0; i<4; i++ ) { @@ -203,30 +203,30 @@ _test_cls_tds_3( const Tds &) tds6.incident_vertices( (*ccit)->vertex(i), std::inserter(set_of_vertices_old, set_of_vertices_old.begin() ) ); - if ( set_of_vertices_old.find(tds6.mirror_vertex(*ccit, i)) - == set_of_vertices_old.end() ) { - nbflips++; - tds6.flip_flippable( *ccit, i ); - assert(tds6.is_valid()); -// if ( tds6.flip( cit, i ) ) { -// tds6.is_valid(true); -// nbflips++; -// } + if ( set_of_vertices_old.find(tds6.mirror_vertex(*ccit, i)) + == set_of_vertices_old.end() ) { + nbflips++; + tds6.flip_flippable( *ccit, i ); + assert(tds6.is_valid()); +// if ( tds6.flip( cit, i ) ) { +// tds6.is_valid(true); +// nbflips++; +// } } - // correct name + // correct name std::set< Vertex_handle > set_of_vertices; tds6.adjacent_vertices( (*ccit)->vertex(i), std::inserter(set_of_vertices, set_of_vertices.begin() ) ); - if ( set_of_vertices.find(tds6.mirror_vertex(*ccit, i)) - == set_of_vertices.end() ) { - nbflips++; - tds6.flip_flippable( *ccit, i ); - assert(tds6.is_valid()); -// if ( tds6.flip( cit, i ) ) { -// tds6.is_valid(true); -// nbflips++; -// } + if ( set_of_vertices.find(tds6.mirror_vertex(*ccit, i)) + == set_of_vertices.end() ) { + nbflips++; + tds6.flip_flippable( *ccit, i ); + assert(tds6.is_valid()); +// if ( tds6.flip( cit, i ) ) { +// tds6.is_valid(true); +// nbflips++; +// } } } } @@ -241,13 +241,13 @@ _test_cls_tds_3( const Tds &) // old name (up to CGAL 3.4) // kept for backwards compatibility but not documented tds6.incident_vertices - ( (*ccit)->vertex(i), std::back_inserter(vector_of_vertices_old)); - // correct name + ( (*ccit)->vertex(i), std::back_inserter(vector_of_vertices_old)); + // correct name tds6.adjacent_vertices - ( (*ccit)->vertex(i), std::back_inserter(vector_of_vertices)); + ( (*ccit)->vertex(i), std::back_inserter(vector_of_vertices)); tds6.incident_edges - ( (*ccit)->vertex(i), std::back_inserter(vector_of_edges)); + ( (*ccit)->vertex(i), std::back_inserter(vector_of_edges)); assert(vector_of_edges.size() == vector_of_vertices_old.size()); assert(vector_of_edges.size() == vector_of_vertices.size()); @@ -259,7 +259,7 @@ _test_cls_tds_3( const Tds &) assert(tds6.number_of_vertices()==8); // std::cout << tds6.number_of_cells()<< " cells" << std::endl; - nbflips=0; + nbflips=0; bool flipped; int j; cit = tds6.cells_begin(); @@ -272,13 +272,13 @@ _test_cls_tds_3( const Tds &) next_cell = ++cit; --cit; while ( (! flipped) && (i<4) ) { if ( (i!=j) ) { - // The Intel compiler has a bug and needs the explicit handle. - Cell_handle ch = cit; - flipped = tds6.flip( ch, i, j ) ; - if (flipped) { - nbflips++; - assert(tds6.is_valid()); - } + // The Intel compiler has a bug and needs the explicit handle. + Cell_handle ch = cit; + flipped = tds6.flip( ch, i, j ) ; + if (flipped) { + nbflips++; + assert(tds6.is_valid()); + } } if ( j==3 ) { i++; j=0; } else j++; @@ -311,44 +311,44 @@ _test_cls_tds_3( const Tds &) assert(tds7.dimension() == 1); assert(tds7.is_valid()); Vertex_handle v7_4 = tds7.insert_increase_dimension(v7_3); - Cell_handle fb = v7_4->cell(); + Cell_handle fb = v7_4->cell(); i7 = fb->index(v7_4); tds7.decrease_dimension(fb, i7); assert(tds7.dimension() == 1); assert(tds7.is_valid()); - Vertex_handle v7_5 = tds7.insert_increase_dimension(v7_4); + Vertex_handle v7_5 = tds7.insert_increase_dimension(v7_4); assert(tds7.dimension() == 2); assert(tds7.is_valid()); - Vertex_handle v7_6 = tds7.insert_increase_dimension(v7_5); + Vertex_handle v7_6 = tds7.insert_increase_dimension(v7_5); assert(tds7.dimension() == 3); assert(tds7.is_valid()); - Cell_handle fc = v7_6->cell(); + Cell_handle fc = v7_6->cell(); i7 = fc->index(v7_6); tds7.decrease_dimension(fc, i7); assert(tds7.dimension() == 2); - assert(tds7.is_valid()); - Vertex_handle v7_7 = tds7.insert_increase_dimension(v7_6); + assert(tds7.is_valid()); + Vertex_handle v7_7 = tds7.insert_increase_dimension(v7_6); assert(tds7.dimension() == 3); - assert(tds7.is_valid()); - Cell_handle fd = v7_7->cell(); + assert(tds7.is_valid()); + Cell_handle fd = v7_7->cell(); i7 = fd->index(v7_7); tds7.decrease_dimension(fd, i7); assert(tds7.dimension() == 2); assert(tds7.is_valid()); Cell_handle fe = v7_7->cell(); - i7 = fe->index(v7_7); + i7 = fe->index(v7_7); tds7.insert_in_facet(fe, i7); assert(tds7.dimension() == 2); assert(tds7.is_valid()); - Vertex_handle v7_8 = tds7.insert_increase_dimension(v7_7); + Vertex_handle v7_8 = tds7.insert_increase_dimension(v7_7); assert(tds7.dimension() == 3); - assert(tds7.is_valid()); - Cell_handle ff = v7_8->cell(); + assert(tds7.is_valid()); + Cell_handle ff = v7_8->cell(); i7 = ff->index(v7_8); tds7.decrease_dimension(ff, i7); assert(tds7.dimension() == 2); assert(tds7.is_valid()); - + // tds1.clear(); // tds2.clear(); // tds3.clear(); diff --git a/Triangulation/doc/Triangulation/Concepts/TriangulationDSFullCell.h b/Triangulation/doc/Triangulation/Concepts/TriangulationDSFullCell.h index b25a2a7a81c..3c32f97f7c5 100644 --- a/Triangulation/doc/Triangulation/Concepts/TriangulationDSFullCell.h +++ b/Triangulation/doc/Triangulation/Concepts/TriangulationDSFullCell.h @@ -3,35 +3,35 @@ \ingroup PkgTriangulationsConcepts \cgalConcept -The concept `TriangulationDSFullCell` describes the requirements for the +The concept `TriangulationDSFullCell` describes the requirements for the full cell class of a `CGAL::Triangulation_data_structure`. It refines the concept `TriangulationDataStructure::FullCell`. -Since the `CGAL::Triangulation_data_structure` is the class +Since the `CGAL::Triangulation_data_structure` is the class which defines the handle types, the full cell base class has to be somehow parameterized by the triangulation -data structure. But since the `CGAL::Triangulation_data_structure` -itself is parameterized by the cell and vertex -base classes, there is a cycle in the definition of these classes. -In order -to break the cycle, the base classes for cells and vertices -which are plugged in to instantiate a -`Triangulation_data_structure` -use a `void` as triangulation -data structure parameter. Then, -the `CGAL::Triangulation_data_structure` -uses a rebind mechanism (similar to the one specified in -`std::allocator`) in order to plug itself -as parameter in the full cell and vertex base classes. -This mechanism requires that the base class provides -a templated nested class `Rebind_TDS` that -itself provides -the subtype `Rebind_TDS::Other` -which is the rebound version of the base class. -This rebound base class is the class -that the `CGAL::Triangulation_data_structure` -actually uses as a base class for the class +data structure. But since the `CGAL::Triangulation_data_structure` +itself is parameterized by the cell and vertex +base classes, there is a cycle in the definition of these classes. +In order +to break the cycle, the base classes for cells and vertices +which are plugged in to instantiate a +`Triangulation_data_structure` +use a `void` as triangulation +data structure parameter. Then, +the `CGAL::Triangulation_data_structure` +uses a rebind mechanism (similar to the one specified in +`std::allocator`) in order to plug itself +as parameter in the full cell and vertex base classes. +This mechanism requires that the base class provides +a templated nested class `Rebind_TDS` that +itself provides +the subtype `Rebind_TDS::Other` +which is the rebound version of the base class. +This rebound base class is the class +that the `CGAL::Triangulation_data_structure` +actually uses as a base class for the class of `CGAL::Triangulation_data_structure::Vertex`. \cgalRefines `TriangulationDataStructure::FullCell` @@ -42,7 +42,7 @@ of `CGAL::Triangulation_data_structure::Vertex`. \sa `TriangulationDSVertex` \sa `TriangulationDSFace` \sa `TriangulationDataStructure` -\sa `TriangulationDataStructure::FullCell` +\sa `TriangulationDataStructure::FullCell` */ class TriangulationDSFullCell { @@ -50,7 +50,7 @@ public: /// \name Types /// @{ - + /*! The `Triangulation_data_structure` in which the `TriangulationDSFullCell` is defined/used. @@ -59,15 +59,15 @@ Must be a model of the `TriangulationDataStructure` concept. typedef unspecified_type Triangulation_data_structure; /*! -This nested template class has to define a type `Rebind_TDS::%Other` -which is the rebound vertex, that is, the one +This nested template class has to define a type `Rebind_TDS::%Other` +which is the rebound vertex, that is, the one that will be actually used by `Triangulation_data_structure`. -The `Rebind_TDS::%Other` type will be the real +The `Rebind_TDS::%Other` type will be the real base class of `Triangulation_data_structure::Full_cell`. \note It can be implemented using a nested template class. */ -template -using Rebind_TDS = unspecified_type; +template +using Rebind_TDS = unspecified_type; /// @} diff --git a/Triangulation/doc/Triangulation/Concepts/TriangulationDSVertex.h b/Triangulation/doc/Triangulation/Concepts/TriangulationDSVertex.h index 903da560d1c..5e3def7d9bd 100644 --- a/Triangulation/doc/Triangulation/Concepts/TriangulationDSVertex.h +++ b/Triangulation/doc/Triangulation/Concepts/TriangulationDSVertex.h @@ -3,35 +3,35 @@ \ingroup PkgTriangulationsConcepts \cgalConcept -The concept `TriangulationDSVertex` describes the requirements for the +The concept `TriangulationDSVertex` describes the requirements for the vertex base class of a `CGAL::Triangulation_data_structure`. It refines the concept `TriangulationDataStructure::Vertex`. -Since the `CGAL::Triangulation_data_structure` is the class +Since the `CGAL::Triangulation_data_structure` is the class which defines the handle types, the vertex base class has to be somehow parameterized by the triangulation -data structure. But since the `CGAL::Triangulation_data_structure` -itself is parameterized by the cell and vertex -base classes, there is a cycle in the definition of these classes. -In order -to break the cycle, the base classes for cells and vertices -which are plugged in to instantiate a -`Triangulation_data_structure` -use a `void` as triangulation -data structure parameter. Then, -the `CGAL::Triangulation_data_structure` -uses a rebind mechanism (similar to the one specified in -`std::allocator`) in order to plug itself -as parameter in the full cell and vertex base classes. -This mechanism requires that the base class provides -a templated nested class `Rebind_TDS` that -itself provides -the subtype `Rebind_TDS::Other` -which is the rebound version of the base class. -This rebound base class is the class -that the `CGAL::Triangulation_data_structure` -actually uses as a base class for the class +data structure. But since the `CGAL::Triangulation_data_structure` +itself is parameterized by the cell and vertex +base classes, there is a cycle in the definition of these classes. +In order +to break the cycle, the base classes for cells and vertices +which are plugged in to instantiate a +`Triangulation_data_structure` +use a `void` as triangulation +data structure parameter. Then, +the `CGAL::Triangulation_data_structure` +uses a rebind mechanism (similar to the one specified in +`std::allocator`) in order to plug itself +as parameter in the full cell and vertex base classes. +This mechanism requires that the base class provides +a templated nested class `Rebind_TDS` that +itself provides +the subtype `Rebind_TDS::Other` +which is the rebound version of the base class. +This rebound base class is the class +that the `CGAL::Triangulation_data_structure` +actually uses as a base class for the class of `CGAL::Triangulation_data_structure::Vertex`. \cgalRefines `TriangulationDataStructure::Vertex` @@ -42,15 +42,15 @@ of `CGAL::Triangulation_data_structure::Vertex`. \sa `TriangulationDSFullCell` \sa `TriangulationDSFace` \sa `TriangulationDataStructure` -\sa `TriangulationDataStructure::Vertex` +\sa `TriangulationDataStructure::Vertex` */ class TriangulationDSVertex { public: - + /// \name Types /// @{ - + /*! The `Triangulation_data_structure` in which the vertex is @@ -61,15 +61,15 @@ Must be a model of the `TriangulationDataStructure` concept. typedef unspecified_type Triangulation_data_structure; /*! -This nested template class has to define a type `Rebind_TDS::%Other` -which is the rebound vertex, that is, the one -that will be actually used by `Triangulation_data_structure`. +This nested template class has to define a type `Rebind_TDS::%Other` +which is the rebound vertex, that is, the one +that will be actually used by `Triangulation_data_structure`. The `Rebind_TDS::%Other` type will be the real base class of `Triangulation_data_structure::Vertex`. \note It can be implemented using a nested template class. */ -template -using Rebind_TDS = unspecified_type; +template +using Rebind_TDS = unspecified_type; /// @} diff --git a/Triangulation/include/CGAL/Triangulation_ds_vertex.h b/Triangulation/include/CGAL/Triangulation_ds_vertex.h index c57bfbed51a..aaa1e2067fc 100644 --- a/Triangulation/include/CGAL/Triangulation_ds_vertex.h +++ b/Triangulation/include/CGAL/Triangulation_ds_vertex.h @@ -26,7 +26,7 @@ namespace CGAL { * 'Triangulation_ds_vertex' */ template< class TDS = void > -class Triangulation_ds_vertex +class Triangulation_ds_vertex { typedef Triangulation_ds_vertex Self; diff --git a/Triangulation_2/include/CGAL/Constrained_triangulation_plus_2.h b/Triangulation_2/include/CGAL/Constrained_triangulation_plus_2.h index 00128211057..a061c6b66b3 100644 --- a/Triangulation_2/include/CGAL/Constrained_triangulation_plus_2.h +++ b/Triangulation_2/include/CGAL/Constrained_triangulation_plus_2.h @@ -6,7 +6,7 @@ // $URL$ // $Id$ // SPDX-License-Identifier: GPL-3.0-or-later OR LicenseRef-Commercial -// +// // // Author(s) : Andreas Fabri, Mariette Yvinec @@ -56,25 +56,25 @@ public: } }; // end class template Pct2_vertex_handle_less_xy -// Tr the base triangulation class +// Tr the base triangulation class // Tr has to be Constrained or Constrained_Delaunay with Constrained_triangulation_plus_vertex_base template < class Tr_ = Default > -class Constrained_triangulation_plus_2 - : public -Default::Get< Tr_, Constrained_Delaunay_triangulation_2< +class Constrained_triangulation_plus_2 + : public +Default::Get< Tr_, Constrained_Delaunay_triangulation_2< Exact_predicates_inexact_constructions_kernel - , Triangulation_data_structure_2< + , Triangulation_data_structure_2< Triangulation_vertex_base_2 , Constrained_triangulation_face_base_2 > , CGAL::Exact_predicates_tag > >::type { - typedef typename - Default::Get< Tr_, Constrained_Delaunay_triangulation_2< + typedef typename + Default::Get< Tr_, Constrained_Delaunay_triangulation_2< Exact_predicates_inexact_constructions_kernel - , Triangulation_data_structure_2< + , Triangulation_data_structure_2< Triangulation_vertex_base_2 , Constrained_triangulation_face_base_2 > @@ -88,7 +88,7 @@ Default::Get< Tr_, Constrained_Delaunay_triangulation_2< typedef typename CDT::Vertex_handle Vertex_handle; typedef typename CDT::Face_handle Face_handle; private: - typedef boost::tuple TFace; + typedef boost::tuple TFace; std::vector faces; CDT& cdt; @@ -110,8 +110,8 @@ Default::Get< Tr_, Constrained_Delaunay_triangulation_2< void write_faces(OutputIterator out) { - for(typename std::vector::reverse_iterator - it = faces.rbegin(); it != faces.rend(); ++it) { + for(typename std::vector::reverse_iterator + it = faces.rbegin(); it != faces.rend(); ++it) { Face_handle fh; if(cdt.is_face(boost::get<0>(*it), boost::get<1>(*it), boost::get<2>(*it), fh)){ *out++ = fh; @@ -126,7 +126,7 @@ public: typedef Constrained_triangulation_plus_2 Self; typedef Tr Base; - + #ifndef CGAL_CFG_USING_BASE_MEMBER_BUG_2 using Triangulation::vertices_begin; using Triangulation::vertices_end; @@ -169,29 +169,29 @@ public: typedef Tag_false Periodic_tag; // for user interface with the constraint hierarchy - typedef typename Constraint_hierarchy::Vertex_it + typedef typename Constraint_hierarchy::Vertex_it Vertices_in_constraint_iterator; typedef Iterator_range Vertices_in_constraint; - + typedef typename Constraint_hierarchy::Point_it Points_in_constraint_iterator; typedef Iterator_range Points_in_constraint; - + typedef typename Constraint_hierarchy::Context Context; typedef typename Constraint_hierarchy::Context_iterator Context_iterator; typedef Iterator_range Contexts; - + typedef typename Constraint_hierarchy::C_iterator Constraint_iterator; typedef Iterator_range Constraints; - + typedef typename Constraint_hierarchy::Subconstraint_iterator Subconstraint_iterator; typedef Iterator_range Subconstraints; - - typedef typename Constraint_hierarchy::Constraint_id Constraint_id; - + + typedef typename Constraint_hierarchy::Constraint_id Constraint_id; + typedef std::pair Subconstraint; - + using Triangulation::geom_traits; using Triangulation::cw; using Triangulation::ccw; @@ -199,14 +199,14 @@ public: protected: Constraint_hierarchy hierarchy; - + public: Constraint_hierarchy& hierarchy_ref() { return hierarchy; } - Constrained_triangulation_plus_2(const Geom_traits& gt=Geom_traits()) + Constrained_triangulation_plus_2(const Geom_traits& gt=Geom_traits()) : Triangulation(gt) , hierarchy(Vh_less_xy(this)) { } @@ -230,8 +230,8 @@ public: template Constrained_triangulation_plus_2(InputIterator first, - InputIterator last, - const Geom_traits& gt=Geom_traits() ) + InputIterator last, + const Geom_traits& gt=Geom_traits() ) : Triangulation(gt) , hierarchy(Vh_less_xy(this)) { @@ -241,7 +241,7 @@ public: Constrained_triangulation_plus_2(const std::list > &constraints, - const Geom_traits& gt=Geom_traits() ) + const Geom_traits& gt=Geom_traits() ) : Triangulation(gt) , hierarchy(Vh_less_xy(this)) { @@ -254,12 +254,12 @@ public: void swap(Constrained_triangulation_plus_2 &ctp); // INSERTION - Vertex_handle insert(const Point& a, - Face_handle start = Face_handle() ); + Vertex_handle insert(const Point& a, + Face_handle start = Face_handle() ); Vertex_handle insert(const Point& p, - Locate_type lt, - Face_handle loc, int li ); - + Locate_type lt, + Face_handle loc, int li ); + Constraint_id insert_constraint(const Point& a, const Point& b) { Vertex_handle va= insert(a); @@ -267,14 +267,14 @@ public: // close to point a // Otherwise, to start here is as good as elsewhere Vertex_handle vb = insert(b, va->face()); - return insert_constraint(va, vb); + return insert_constraint(va, vb); } - Constraint_id insert_constraint(const Constraint& c) + Constraint_id insert_constraint(const Constraint& c) { return insert_constraint(c.first, c.second); } - + Constraint_id insert_constraint(Vertex_handle va, Vertex_handle vb) { // protects against inserting a zero length constraint @@ -283,7 +283,7 @@ public: } // protects against inserting twice the same constraint Constraint_id cid = hierarchy.insert_constraint_old_API(va, vb); - if (va != vb && (cid != Constraint_id(nullptr)) ) insert_subconstraint(va,vb); + if (va != vb && (cid != Constraint_id(nullptr)) ) insert_subconstraint(va,vb); return cid; } @@ -330,7 +330,7 @@ public: } // for backward compatibility - // not const Point&, because otherwise VC6/7 messes it up with + // not const Point&, because otherwise VC6/7 messes it up with // the insert that takes an iterator range Constraint_id insert(Point a, Point b) { return insert_constraint(a, b); } Constraint_id insert(Vertex_handle va, Vertex_handle vb) { return insert_constraint(va,vb); } @@ -357,8 +357,8 @@ public: Vertices_in_constraint_iterator - insert_vertex_in_constraint(Constraint_id cid, Vertices_in_constraint_iterator pos, - Vertex_handle vh) + insert_vertex_in_constraint(Constraint_id cid, Vertices_in_constraint_iterator pos, + Vertex_handle vh) { return insert_vertex_in_constraint(cid, pos, vh, Emptyset_iterator()); } @@ -372,8 +372,8 @@ public: template Vertices_in_constraint_iterator - remove_vertex_from_constraint(Constraint_id cid, Vertices_in_constraint_iterator pos, - OutputIterator out) + remove_vertex_from_constraint(Constraint_id cid, Vertices_in_constraint_iterator pos, + OutputIterator out) { if(pos == vertices_in_constraint_begin(cid)){ ++pos; @@ -414,7 +414,7 @@ public: ++pos; tail = hierarchy.split(cid,pos); } - + Constraint_id aux = insert_constraint(a, b, std::back_inserter(fc)); pos = vertices_in_constraint_end(aux); --pos; @@ -439,8 +439,8 @@ public: // Writes the modified faces to out template Vertices_in_constraint_iterator - insert_vertex_in_constraint(Constraint_id cid, Vertices_in_constraint_iterator pos, - Vertex_handle vh, OutputIterator out) + insert_vertex_in_constraint(Constraint_id cid, Vertices_in_constraint_iterator pos, + Vertex_handle vh, OutputIterator out) { // Insertion before the first vertex if(pos == vertices_in_constraint_begin(cid)){ @@ -448,7 +448,7 @@ public: Constraint_id head = insert_constraint(vh, *pos, out); hierarchy.concatenate2(head, cid); return vertices_in_constraint_begin(cid); - } + } // Insertion after the last vertex if(pos == vertices_in_constraint_end(cid)){ @@ -461,7 +461,7 @@ public: return pos; } Vertex_handle b = *pos; - --pos; + --pos; Vertex_handle a = *pos; ++pos; Face_container fc(*this); @@ -470,7 +470,7 @@ public: vcit = beg; ++beg; // If the constraint consists only of a segment, and we want to insert - // in the middle + // in the middle if((pos == vcit) && (beg == vertices_in_constraint_end(cid))){ //std::cout << "insertion in constraint which is a segment" << std::endl; Constraint_id aux1 = insert_constraint(a, vh, std::back_inserter(fc)); @@ -481,7 +481,7 @@ public: remove_constraint(aux1, std::back_inserter(fc)); fc.write_faces(out); return pos; - + } Constraint_id head = nullptr, tail = nullptr; Vertices_in_constraint_iterator bit = vertices_in_constraint_begin(cid); @@ -500,9 +500,9 @@ public: --eit; if(pos != eit){ //std::cout << "split tail" << std::endl; - tail = split(cid, pos); + tail = split(cid, pos); } - + // make the new constraint Constraint_id aux1 = insert_constraint(a, vh, std::back_inserter(fc)); Constraint_id aux2 = insert_constraint(vh, b, std::back_inserter(fc)); @@ -538,7 +538,7 @@ public: hint = vh->face(); // no duplicates if(vertices.empty() || (vertices.back() != vh)){ - vertices.push_back(vh); + vertices.push_back(vh); } } int n = vertices.size(); @@ -546,24 +546,24 @@ public: return nullptr; } Constraint_id ca = hierarchy.insert_constraint(vertices[0],vertices[1]); - insert_subconstraint(vertices[0],vertices[1], std::back_inserter(fc)); + insert_subconstraint(vertices[0],vertices[1], std::back_inserter(fc)); if(n>2){ for(int j=1; jfixed() = true; // Vertices_in_constraint_iterator end = boost::prior(vertices_in_constraint_end(ca)); // end->fixed() = true; fc.write_faces(out); - + return ca; } @@ -579,7 +579,7 @@ private: hint = vh->face(); // no duplicates if(vertices.empty() || (vertices.back() != vh)){ - vertices.push_back(vh); + vertices.push_back(vh); } } if(is_polygon && (vertices.size()>1) && (vertices.front() != vertices.back())){ @@ -591,26 +591,26 @@ private: return nullptr; } CGAL_assertion(n >= 2); - + Constraint_id ca = hierarchy.insert_constraint(vertices[0],vertices[1]); - insert_subconstraint(vertices[0],vertices[1]); + insert_subconstraint(vertices[0],vertices[1]); if(n>2){ for(std::size_t j=1; jfixed() = true; // vertices.back()->fixed() = true; return ca; } - + public: - + void file_output(std::ostream& os) const { @@ -635,9 +635,9 @@ public: void file_input(std::istream& is) { - + is >> static_cast(*this); - + std::vector V; V.reserve(number_of_vertices()); for(Vertex_iterator vit = vertices_begin(); vit != vertices_end() ; ++vit){ @@ -650,7 +650,7 @@ public: while(is >> n){ is >> i0 >> i1; cid = insert_constraint(V[i0],V[i1]); - + for(int i = 2; i < n; i++){ i0 = i1; is >> i1; @@ -660,7 +660,7 @@ public: } } - + template typename Constrained_triangulation_plus_2::Constraint_id insert_constraint(Vertex_handle va, Vertex_handle vb, OutputIterator out) @@ -671,11 +671,11 @@ public: } // protects against inserting twice the same constraint Constraint_id cid = hierarchy.insert_constraint(va, vb); - if (va != vb && (cid != nullptr) ) insert_subconstraint(va,vb,out); - + if (va != vb && (cid != nullptr) ) insert_subconstraint(va,vb,out); + for(Vertices_in_constraint_iterator vcit = vertices_in_constraint_begin(cid); - vcit != vertices_in_constraint_end(cid); - vcit++){ + vcit != vertices_in_constraint_end(cid); + vcit++){ insert_incident_faces(vcit, out); } return cid; @@ -700,26 +700,26 @@ public: Vertex_handle vaa, Vertex_handle vbb, Exact_predicates_tag); - + // REMOVAL template void remove_constraint(Constraint_id cid, OutputIterator out) { std::list vertices(hierarchy.vertices_in_constraint_begin(cid), - hierarchy.vertices_in_constraint_end(cid)); + hierarchy.vertices_in_constraint_end(cid)); hierarchy.remove_constraint(cid); - for(typename std::list::iterator it = vertices.begin(), - succ = it; - ++succ != vertices.end(); - ++it){ + for(typename std::list::iterator it = vertices.begin(), + succ = it; + ++succ != vertices.end(); + ++it){ if(! is_subconstraint(*it, *succ)){ // this checks whether other constraints pass - Face_handle fh; - int i; - bool b = Triangulation::is_edge(*it, *succ, fh, i); - CGAL_assume(b); - Triangulation::remove_constrained_edge(fh,i, out); // this does also flipping if necessary. + Face_handle fh; + int i; + bool b = Triangulation::is_edge(*it, *succ, fh, i); + CGAL_assume(b); + Triangulation::remove_constrained_edge(fh,i, out); // this does also flipping if necessary. } } } @@ -728,18 +728,18 @@ public: remove_constraint(cid, Emptyset_iterator()); } - + void simplify(Vertices_in_constraint_iterator v) { Vertices_in_constraint_iterator u = boost::prior(v); Vertices_in_constraint_iterator w = boost::next(v); bool unew = (*u != *w); hierarchy.simplify(u,v,w); - + Triangulation::remove_incident_constraints(*v); - + Triangulation::remove(*v); - + if(unew){ Triangulation::insert_constraint(*u, *w); } @@ -763,10 +763,10 @@ public: // split a constraint in two constraints, so that vcit becomes the first // vertex of the new constraint - // returns the new constraint + // returns the new constraint Constraint_id split(Constraint_id first, Vertices_in_constraint_iterator vcit); - + // Query of the constraint hierarchy Constraint_iterator constraints_begin() const; Constraint_iterator constraints_end() const; @@ -774,7 +774,7 @@ public: { return Constraints(constraints_begin(),constraints_end()); } - + Subconstraint_iterator subconstraints_begin() const; Subconstraint_iterator subconstraints_end() const; @@ -782,31 +782,31 @@ public: { return Subconstraints(subconstraints_begin(),subconstraints_end()); } - - Context context(Vertex_handle va, Vertex_handle vb); //AF: const; - bool is_subconstraint(Vertex_handle va, - Vertex_handle vb); - size_type number_of_enclosing_constraints(Vertex_handle va, + Context context(Vertex_handle va, Vertex_handle vb); //AF: const; + + bool is_subconstraint(Vertex_handle va, + Vertex_handle vb); + size_type number_of_enclosing_constraints(Vertex_handle va, Vertex_handle vb) const; - Context_iterator contexts_begin(Vertex_handle va, - Vertex_handle vb) const; - Context_iterator contexts_end(Vertex_handle va, - Vertex_handle vb) const; + Context_iterator contexts_begin(Vertex_handle va, + Vertex_handle vb) const; + Context_iterator contexts_end(Vertex_handle va, + Vertex_handle vb) const; Contexts contexts(Vertex_handle va, Vertex_handle vb) const { return Contexts(contexts_begin(va,vb),contexts_end(va,vb)); } - + Vertices_in_constraint_iterator vertices_in_constraint_begin(Constraint_id cid) const; Vertices_in_constraint_iterator vertices_in_constraint_end(Constraint_id cid) const; - + Vertices_in_constraint vertices_in_constraint(Constraint_id cid) const { return Vertices_in_constraint(vertices_in_constraint_begin(cid), vertices_in_constraint_end(cid)); } - + Points_in_constraint_iterator points_in_constraint_begin(Constraint_id cid) const; Points_in_constraint_iterator points_in_constraint_end(Constraint_id cid) const ; @@ -842,12 +842,12 @@ protected: fc++; }while(fc != done); } - } + } void insert_subconstraint(Vertex_handle vaa, - Vertex_handle vbb) + Vertex_handle vbb) { insert_subconstraint(vaa,vbb,Emptyset_iterator()); } @@ -858,9 +858,9 @@ insert_subconstraint(Vertex_handle vaa, template void insert_subconstraint(Vertex_handle vaa, - Vertex_handle vbb, - OutputItertator out) - // insert the subconstraint [vaa vbb] + Vertex_handle vbb, + OutputItertator out) + // insert the subconstraint [vaa vbb] // it will eventually be split into several subconstraints { std::stack > stack; @@ -870,7 +870,7 @@ insert_subconstraint(Vertex_handle vaa, boost::tie(vaa,vbb) = stack.top(); stack.pop(); CGAL_triangulation_precondition( vaa != vbb); - + Vertex_handle vi; Face_handle fr; @@ -883,11 +883,11 @@ insert_subconstraint(Vertex_handle vaa, } continue; } - + List_faces intersected_faces; List_edges conflict_boundary_ab, conflict_boundary_ba; - - bool intersection = this->find_intersected_faces( + + bool intersection = this->find_intersected_faces( vaa, vbb, intersected_faces, conflict_boundary_ab, @@ -897,10 +897,10 @@ insert_subconstraint(Vertex_handle vaa, if ( intersection) { if (vi != vaa && vi != vbb) { hierarchy.split_constraint(vaa,vbb,vi); - stack.push(std::make_pair(vaa,vi)); - stack.push(std::make_pair(vi,vbb)); + stack.push(std::make_pair(vaa,vi)); + stack.push(std::make_pair(vi,vbb)); } - else stack.push(std::make_pair(vaa,vbb)); + else stack.push(std::make_pair(vaa,vbb)); continue; } @@ -941,7 +941,7 @@ insert_subconstraint(Vertex_handle vaa, if (vi != vbb) { hierarchy.split_constraint(vaa,vbb,vi); - stack.push(std::make_pair(vi,vbb)); + stack.push(std::make_pair(vi,vbb)); } } } @@ -958,7 +958,7 @@ public: #if defined(_MSC_VER) std::ptrdiff_t insert(InputIterator first, InputIterator last, int i = 0) #else - std::ptrdiff_t insert(InputIterator first, InputIterator last) + std::ptrdiff_t insert(InputIterator first, InputIterator last) #endif { #if defined(_MSC_VER) @@ -987,7 +987,7 @@ copy_triangulation(const Constrained_triangulation_plus_2 &ctp) { Base::copy_triangulation(ctp); //the following assumes that the triangulation and its copy - // iterate on their vertices in the same order + // iterate on their vertices in the same order std::map vmap; Vertex_iterator vit = ctp.vertices_begin(); Vertex_iterator vvit = this->vertices_begin(); @@ -1008,7 +1008,7 @@ swap(Constrained_triangulation_plus_2 &ctp) } template < class Tr > -inline +inline typename Constrained_triangulation_plus_2::Vertex_handle Constrained_triangulation_plus_2:: insert(const Point& a, Face_handle start) @@ -1046,17 +1046,17 @@ insert(const Point& a, Locate_type lt, Face_handle loc, int li) } template -typename Constrained_triangulation_plus_2:: Vertex_handle +typename Constrained_triangulation_plus_2:: Vertex_handle Constrained_triangulation_plus_2:: -intersect(Face_handle f, int i, - Vertex_handle vaa, - Vertex_handle vbb) +intersect(Face_handle f, int i, + Vertex_handle vaa, + Vertex_handle vbb) { return intersect(f, i, vaa, vbb, Intersection_tag()); } template -typename Constrained_triangulation_plus_2:: Vertex_handle +typename Constrained_triangulation_plus_2:: Vertex_handle Constrained_triangulation_plus_2:: intersect(Face_handle, int, Vertex_handle, @@ -1080,13 +1080,13 @@ intersect(Face_handle, int, } template -typename Constrained_triangulation_plus_2:: Vertex_handle +typename Constrained_triangulation_plus_2:: Vertex_handle Constrained_triangulation_plus_2:: -intersect(Face_handle f, int i, - Vertex_handle vaa, - Vertex_handle vbb, - Exact_intersections_tag) -// compute the intersection of the constraint edge (f,i) +intersect(Face_handle f, int i, + Vertex_handle vaa, + Vertex_handle vbb, + Exact_intersections_tag) +// compute the intersection of the constraint edge (f,i) // with the subconstraint (vaa,vbb) being inserted // insert the intersection point // (the constraint edge (f,i) will be split in hierarchy by insert) @@ -1114,16 +1114,16 @@ intersect(Face_handle f, int i, CGAL_triangulation_assertion(ok); Vertex_handle vi = insert(pi, Triangulation::EDGE, f, i); - return vi; + return vi; } template -typename Constrained_triangulation_plus_2::Vertex_handle +typename Constrained_triangulation_plus_2::Vertex_handle Constrained_triangulation_plus_2:: -intersect(Face_handle f, int i, - Vertex_handle vaa, - Vertex_handle vbb, - Exact_predicates_tag) +intersect(Face_handle f, int i, + Vertex_handle vaa, + Vertex_handle vbb, + Exact_predicates_tag) { Vertex_handle vcc, vdd; vcc = f->vertex(cw(i)); @@ -1145,7 +1145,7 @@ intersect(Face_handle f, int i, case 0 : vi = vaa; break; case 1 : vi = vbb; break; case 2 : vi = vcc; break; - case 3 : vi = vdd; break; + case 3 : vi = vdd; break; } if(vi == vaa || vi == vbb) { Triangulation::remove_constrained_edge(f, i); @@ -1158,15 +1158,15 @@ intersect(Face_handle f, int i, // vi == vc or vi == vd may happen even if intersection==true // due to approximate construction of the intersection - if (vi != vcc && vi != vdd) { + if (vi != vcc && vi != vdd) { hierarchy.split_constraint(vcc,vdd,vi); - insert_subconstraint(vcc,vi); + insert_subconstraint(vcc,vi); insert_subconstraint(vi, vdd); - } + } else { insert_subconstraint(vcc,vdd); } - return vi; + return vi; } // CONCATENATE AND SPLIT @@ -1181,7 +1181,7 @@ Constrained_triangulation_plus_2::concatenate(Constraint_id first, Constrain // split a constraint in two constraints, so that vcit becomes the first // vertex of the new constraint - // returns the new constraint + // returns the new constraint template typename Constrained_triangulation_plus_2::Constraint_id Constrained_triangulation_plus_2::split(Constraint_id first, Vertices_in_constraint_iterator vcit) @@ -1192,8 +1192,8 @@ Constrained_triangulation_plus_2::split(Constraint_id first, Vertices_in_con template std::ostream & -operator<<(std::ostream& os, - const Constrained_triangulation_plus_2 &ct) +operator<<(std::ostream& os, + const Constrained_triangulation_plus_2 &ct) { ct.file_output(os); return os ; @@ -1201,8 +1201,8 @@ operator<<(std::ostream& os, template std::istream & -operator>>(std::istream& is, - Constrained_triangulation_plus_2 &ct) +operator>>(std::istream& is, + Constrained_triangulation_plus_2 &ct) { ct.file_input(is); return is ; @@ -1262,13 +1262,13 @@ context(Vertex_handle va, Vertex_handle vb) // AF: const template -inline +inline typename Constrained_triangulation_plus_2::size_type Constrained_triangulation_plus_2:: number_of_enclosing_constraints(Vertex_handle va, Vertex_handle vb) const { - return static_cast - (hierarchy.number_of_enclosing_constraints(va,vb)); + return static_cast + (hierarchy.number_of_enclosing_constraints(va,vb)); } template @@ -1276,7 +1276,7 @@ inline bool Constrained_triangulation_plus_2:: is_subconstraint(Vertex_handle va, Vertex_handle vb) { - return hierarchy.is_subconstrained_edge(va,vb); + return hierarchy.is_subconstrained_edge(va,vb); } diff --git a/Triangulation_2/include/CGAL/Delaunay_triangulation_2.h b/Triangulation_2/include/CGAL/Delaunay_triangulation_2.h index dd85df9acb0..c8fc845f01b 100644 --- a/Triangulation_2/include/CGAL/Delaunay_triangulation_2.h +++ b/Triangulation_2/include/CGAL/Delaunay_triangulation_2.h @@ -327,10 +327,10 @@ public: #ifndef CGAL_TRIANGULATION_2_DONT_INSERT_RANGE_OF_POINTS_WITH_INFO private: - + using Triangulation::top_get_first; using Triangulation::top_get_second; - + template std::ptrdiff_t insert_with_info(InputIterator first,InputIterator last) { diff --git a/Triangulation_2/include/CGAL/Triangulation_2/internal/Polyline_constraint_hierarchy_2.h b/Triangulation_2/include/CGAL/Triangulation_2/internal/Polyline_constraint_hierarchy_2.h index bf89ead3c58..c3c26ce2470 100644 --- a/Triangulation_2/include/CGAL/Triangulation_2/internal/Polyline_constraint_hierarchy_2.h +++ b/Triangulation_2/include/CGAL/Triangulation_2/internal/Polyline_constraint_hierarchy_2.h @@ -6,7 +6,7 @@ // $URL$ // $Id$ // SPDX-License-Identifier: GPL-3.0-or-later OR LicenseRef-Commercial -// +// // // Author(s) : Andreas Fabri, Olivier Billet, Mariette Yvinec @@ -19,8 +19,8 @@ #include #include #include -#include -#include +#include +#include #include #include @@ -57,11 +57,11 @@ private: typedef std::list Constraint_list; public: - // the base line is always - class Point_it + // the base line is always + class Point_it : public boost::iterator_adaptor< Point_it - , typename Vertex_list::all_iterator + , typename Vertex_list::all_iterator , const Point > { @@ -74,10 +74,10 @@ public: }; // only nodes with a vertex_handle that is still in the triangulation - class Vertex_it + class Vertex_it : public boost::iterator_adaptor< Vertex_it - , typename Vertex_list::skip_iterator + , typename Vertex_list::skip_iterator , Vertex_handle , boost::use_default , Vertex_handle> @@ -106,11 +106,11 @@ public: Vertex_list* vl_ptr() const {return second;} operator std::pair,Vertex_list*>() - { + { if (second!=nullptr){ return std::make_pair(std::make_pair(second->front().vertex(), second->back().vertex()),second); - } + } return std::make_pair(std::make_pair(Vertex_handle(),Vertex_handle()),second); } @@ -159,24 +159,24 @@ public: Vertex_it vertices_end()const {return enclosing->skip_end();} Constraint_id id() { return enclosing; } std::size_t number_of_vertices() const {return enclosing->skip_size(); } - }; + }; typedef std::list Context_list; typedef typename Context_list::iterator Context_iterator; typedef std::set Constraint_set; typedef std::map Sc_to_c_map; + Pair_compare> Sc_to_c_map; typedef typename Constraint_set::iterator C_iterator; typedef typename Sc_to_c_map::const_iterator Sc_iterator; typedef Sc_iterator Subconstraint_iterator; - + private: // data for the 1d hierarchy Compare comp; Constraint_set constraint_set; Sc_to_c_map sc_to_c_map; - + public: Polyline_constraint_hierarchy_2(const Compare& comp) : comp(comp) @@ -189,7 +189,7 @@ public: Polyline_constraint_hierarchy_2& operator=(const Polyline_constraint_hierarchy_2& ch); Polyline_constraint_hierarchy_2& operator=(Polyline_constraint_hierarchy_2&& ch) = default; - // Query + // Query bool is_subconstrained_edge(T va, T vb) const; bool is_constrained_edge(T va, T vb) const; bool is_constrained_vertex(T v) const; @@ -217,7 +217,7 @@ public: Context_iterator contexts_end(T va, T vb) const; std::size_t number_of_constraints() const { return constraint_set.size();} std::size_t number_of_subconstraints()const {return sc_to_c_map.size();} - + // insert/remove void add_Steiner(T va, T vb, T vx); @@ -246,31 +246,31 @@ public: // iterators Subconstraint_iterator subconstraint_begin() const - { - return sc_to_c_map.begin(); + { + return sc_to_c_map.begin(); } Subconstraint_iterator subconstraint_end() const - { - return sc_to_c_map.end(); + { + return sc_to_c_map.end(); } Sc_iterator sc_begin() const{ return sc_to_c_map.begin(); } Sc_iterator sc_end() const{ return sc_to_c_map.end(); } C_iterator c_begin() const{ return constraint_set.begin(); } C_iterator c_end() const{ return constraint_set.end(); } - + // Helper functions void copy(const Polyline_constraint_hierarchy_2& ch); void copy(const Polyline_constraint_hierarchy_2& ch, std::map& vmap); void swap(Polyline_constraint_hierarchy_2& ch); -private: +private: Edge make_edge(T va, T vb) const; Vertex_it get_pos(T va, T vb) const; - bool get_contexts(T va, T vb, - Context_iterator& ctxt, - Context_iterator& past) const; + bool get_contexts(T va, T vb, + Context_iterator& ctxt, + Context_iterator& past) const; bool get_contexts(T va, T vb, Context_list*&) const; @@ -347,8 +347,8 @@ copy(const Polyline_constraint_hierarchy_2& ch1, std::mapskip_begin(); Vertex_it aux = cit1->enclosing->skip_begin(); while( aux != cit1->pos) { - ++aux; - ++ctxt2.pos; + ++aux; + ++ctxt2.pos; } hcl2->push_back(ctxt2); } @@ -435,8 +435,8 @@ enclosing_constraints(T vaa, T vbb , Constraint_list& hcl) const Context_iterator hcit, past; if ( !get_contexts(vaa,vbb, hcit ,past)) return false; for (; hcit!=past; hcit++) { - hcl.push_back(make_edge(hcit->enclosing->front(), - hcit->enclosing->back())); + hcl.push_back(make_edge(hcit->enclosing->front(), + hcit->enclosing->back())); } return true; } @@ -452,7 +452,7 @@ context(T va, T vb) } template -std::size_t +std::size_t Polyline_constraint_hierarchy_2:: number_of_enclosing_constraints(T va, T vb) const { @@ -476,19 +476,19 @@ template typename Polyline_constraint_hierarchy_2::Context_iterator Polyline_constraint_hierarchy_2:: contexts_end(T va, T vb) const -{ +{ Context_iterator first, last; if( !get_contexts(va,vb,first,last)) CGAL_triangulation_assertion(false); return last; -} +} template void Polyline_constraint_hierarchy_2:: swap(Constraint_id first, Constraint_id second){ // We have to look at all subconstraints - for(Vertex_it it = first.vl_ptr()->skip_begin(), succ = it, end = first.vl_ptr()->skip_end(); - ++succ != end; + for(Vertex_it it = first.vl_ptr()->skip_begin(), succ = it, end = first.vl_ptr()->skip_end(); + ++succ != end; ++it){ typename Sc_to_c_map::iterator scit = sc_to_c_map.find(make_edge(*it,*succ)); CGAL_triangulation_assertion(scit != sc_to_c_map.end()); @@ -497,14 +497,14 @@ swap(Constraint_id first, Constraint_id second){ // and replace the context of the constraint for(Context_iterator ctit=hcl->begin(); ctit != hcl->end(); ctit++) { if(ctit->enclosing == first.vl_ptr()){ - ctit->enclosing = nullptr; - break; + ctit->enclosing = nullptr; + break; } } } // We have to look at all subconstraints - for(Vertex_it it = second.vl_ptr()->skip_begin(), succ = it, end = second.vl_ptr()->skip_end(); - ++succ != end; + for(Vertex_it it = second.vl_ptr()->skip_begin(), succ = it, end = second.vl_ptr()->skip_end(); + ++succ != end; ++it){ typename Sc_to_c_map::iterator scit = sc_to_c_map.find(make_edge(*it,*succ)); CGAL_triangulation_assertion(scit != sc_to_c_map.end()); @@ -513,14 +513,14 @@ swap(Constraint_id first, Constraint_id second){ // and replace the context of the constraint for(Context_iterator ctit=hcl->begin(); ctit != hcl->end(); ctit++) { if(ctit->enclosing == second.vl_ptr()){ - ctit->enclosing = first.vl_ptr(); - break; + ctit->enclosing = first.vl_ptr(); + break; } } - } + } // We have to look at all subconstraints - for(Vertex_it it = first.vl_ptr()->skip_begin(), succ = it, end = first.vl_ptr()->skip_end(); - ++succ != end; + for(Vertex_it it = first.vl_ptr()->skip_begin(), succ = it, end = first.vl_ptr()->skip_end(); + ++succ != end; ++it){ typename Sc_to_c_map::iterator scit = sc_to_c_map.find(make_edge(*it,*succ)); CGAL_triangulation_assertion(scit != sc_to_c_map.end()); @@ -529,8 +529,8 @@ swap(Constraint_id first, Constraint_id second){ // and replace the context of the constraint for(Context_iterator ctit=hcl->begin(); ctit != hcl->end(); ctit++) { if(ctit->enclosing == nullptr){ - ctit->enclosing = second.vl_ptr(); - break; + ctit->enclosing = second.vl_ptr(); + break; } } } @@ -543,10 +543,10 @@ void Polyline_constraint_hierarchy_2:: remove_constraint(Constraint_id cid){ constraint_set.erase(cid); - + // We have to look at all subconstraints - for(Vertex_it it = cid.vl_ptr()->skip_begin(), succ = it, end = cid.vl_ptr()->skip_end(); - ++succ != end; + for(Vertex_it it = cid.vl_ptr()->skip_begin(), succ = it, end = cid.vl_ptr()->skip_end(); + ++succ != end; ++it){ typename Sc_to_c_map::iterator scit = sc_to_c_map.find(make_edge(*it,*succ)); CGAL_triangulation_assertion(scit != sc_to_c_map.end()); @@ -555,8 +555,8 @@ remove_constraint(Constraint_id cid){ // and remove the context of the constraint for(Context_iterator ctit=hcl->begin(); ctit != hcl->end(); ctit++) { if(ctit->enclosing == cid.vl_ptr()){ - hcl->erase(ctit); - break; + hcl->erase(ctit); + break; } } // If the constraint passes several times through the same subconstraint, @@ -603,12 +603,12 @@ void Polyline_constraint_hierarchy_2::simplify(Vertex_it uc, CGAL_assertion_msg( vw_sc_iter != sc_to_c_map.end(), "not a subconstraint" ); Context_list* vw_hcl = vw_sc_iter->second; CGAL_assertion_msg((u == w) || (vw_hcl->size() == 1), "more than one constraint passing through the subconstraint" ); - + Vertex_list* vertex_list = uv_hcl->front().id().vl_ptr(); CGAL_assertion_msg(vertex_list == vw_hcl->front().id().vl_ptr(), "subconstraints from different polyline constraints" ); // Remove the list item which points to v vertex_list->skip(vc.base()); - + if(u != w){ // Remove the entries for [u,v] and [v,w] sc_to_c_map.erase(uv_sc_iter); @@ -628,8 +628,8 @@ std::size_t Polyline_constraint_hierarchy_2::remove_points_without_corresponding_vertex(Constraint_id cid) { std::size_t n = 0; - for(Point_it it = points_in_constraint_begin(cid); - it != points_in_constraint_end(cid); ++it) { + for(Point_it it = points_in_constraint_begin(cid); + it != points_in_constraint_end(cid); ++it) { if(cid.vl_ptr()->is_skipped(it.base())) { it = cid.vl_ptr()->erase(it.base()); ++n; @@ -657,8 +657,8 @@ Polyline_constraint_hierarchy_2::concatenate(Constraint_id firs constraint_set.erase(first); constraint_set.erase(second); // We have to look at all subconstraints - for(Vertex_it it = second.vl_ptr()->skip_begin(), succ = it, end = second.vl_ptr()->skip_end(); - ++succ != end; + for(Vertex_it it = second.vl_ptr()->skip_begin(), succ = it, end = second.vl_ptr()->skip_end(); + ++succ != end; ++it){ typename Sc_to_c_map::iterator scit = sc_to_c_map.find(make_edge(*it,*succ)); CGAL_triangulation_assertion(scit != sc_to_c_map.end()); @@ -667,8 +667,8 @@ Polyline_constraint_hierarchy_2::concatenate(Constraint_id firs // and replace the context of the constraint for(Context_iterator ctit=hcl->begin(); ctit != hcl->end(); ctit++) { if(ctit->enclosing == second.vl_ptr()){ - ctit->enclosing = first.vl_ptr(); - break; + ctit->enclosing = first.vl_ptr(); + break; } } } @@ -682,8 +682,8 @@ Polyline_constraint_hierarchy_2::concatenate(Constraint_id firs // Note that for VC8 with iterator debugging the iterators pointing into second // are NOT valid So we have to update them - for(Vertex_it it = back_it, succ = it, end = first.vl_ptr()->skip_end(); - ++succ != end; + for(Vertex_it it = back_it, succ = it, end = first.vl_ptr()->skip_end(); + ++succ != end; ++it){ typename Sc_to_c_map::iterator scit = sc_to_c_map.find(make_edge(*it,*succ)); CGAL_triangulation_assertion(scit != sc_to_c_map.end()); @@ -692,8 +692,8 @@ Polyline_constraint_hierarchy_2::concatenate(Constraint_id firs // and update pos in the context of the constraint for(Context_iterator ctit=hcl->begin(); ctit != hcl->end(); ctit++) { if(ctit->enclosing == first.vl_ptr()){ - ctit->pos = it; - break; + ctit->pos = it; + break; } } } @@ -706,12 +706,12 @@ Polyline_constraint_hierarchy_2::concatenate(Constraint_id firs template typename Polyline_constraint_hierarchy_2::Constraint_id Polyline_constraint_hierarchy_2::concatenate2(Constraint_id first, Constraint_id second) -{ +{ constraint_set.erase(first); constraint_set.erase(second); // We have to look at all subconstraints - for(Vertex_it it = first.vl_ptr()->skip_begin(), succ = it, end = first.vl_ptr()->skip_end(); - ++succ != end; + for(Vertex_it it = first.vl_ptr()->skip_begin(), succ = it, end = first.vl_ptr()->skip_end(); + ++succ != end; ++it){ typename Sc_to_c_map::iterator scit = sc_to_c_map.find(make_edge(*it,*succ)); CGAL_triangulation_assertion(scit != sc_to_c_map.end()); @@ -720,8 +720,8 @@ Polyline_constraint_hierarchy_2::concatenate2(Constraint_id fir // and replace the context of the constraint for(Context_iterator ctit=hcl->begin(); ctit != hcl->end(); ctit++) { if(ctit->enclosing == first.vl_ptr()){ - ctit->enclosing = second.vl_ptr(); - break; + ctit->enclosing = second.vl_ptr(); + break; } } } @@ -734,8 +734,8 @@ Polyline_constraint_hierarchy_2::concatenate2(Constraint_id fir // Note that for VC8 with iterator debugging the iterators pointing into second // are NOT valid So we have to update them - for(Vertex_it it = second.vl_ptr()->skip_begin(), succ = it, end = back_it; - ++succ != end; + for(Vertex_it it = second.vl_ptr()->skip_begin(), succ = it, end = back_it; + ++succ != end; ++it){ typename Sc_to_c_map::iterator scit = sc_to_c_map.find(make_edge(*it,*succ)); CGAL_triangulation_assertion(scit != sc_to_c_map.end()); @@ -744,8 +744,8 @@ Polyline_constraint_hierarchy_2::concatenate2(Constraint_id fir // and update pos in the context of the constraint for(Context_iterator ctit=hcl->begin(); ctit != hcl->end(); ctit++) { if(ctit->enclosing == second.vl_ptr()){ - ctit->pos = it; - break; + ctit->pos = it; + break; } } } @@ -758,7 +758,7 @@ Polyline_constraint_hierarchy_2::concatenate2(Constraint_id fir // split a constraint in two constraints, so that vcit becomes the first // vertex of the new constraint - // returns the new constraint + // returns the new constraint template typename Polyline_constraint_hierarchy_2::Constraint_id Polyline_constraint_hierarchy_2::split(Constraint_id first, Vertex_it vcit) @@ -775,8 +775,8 @@ Polyline_constraint_hierarchy_2::split(Constraint_id first, Ver constraint_set.insert(first); constraint_set.insert(second); // We have to look at all subconstraints - for(Vertex_it it = second->skip_begin(), succ = it, end = second->skip_end(); - ++succ != end; + for(Vertex_it it = second->skip_begin(), succ = it, end = second->skip_end(); + ++succ != end; ++it){ typename Sc_to_c_map::iterator scit = sc_to_c_map.find(make_edge(*it,*succ)); CGAL_triangulation_assertion(scit != sc_to_c_map.end()); @@ -785,8 +785,8 @@ Polyline_constraint_hierarchy_2::split(Constraint_id first, Ver // and replace the context of the constraint for(Context_iterator ctit=hcl->begin(); ctit != hcl->end(); ctit++) { if(ctit->enclosing == first.vl_ptr()){ - ctit->enclosing = second; - break; + ctit->enclosing = second; + break; } } } @@ -809,8 +809,8 @@ Polyline_constraint_hierarchy_2::split2(Constraint_id first, Ve constraint_set.insert(first); constraint_set.insert(second); // We have to look at all subconstraints - for(Vertex_it it = second->skip_begin(), succ = it, end = second->skip_end(); - ++succ != end; + for(Vertex_it it = second->skip_begin(), succ = it, end = second->skip_end(); + ++succ != end; ++it){ typename Sc_to_c_map::iterator scit = sc_to_c_map.find(make_edge(*it,*succ)); CGAL_triangulation_assertion(scit != sc_to_c_map.end()); @@ -819,8 +819,8 @@ Polyline_constraint_hierarchy_2::split2(Constraint_id first, Ve // and replace the context of the constraint for(Context_iterator ctit=hcl->begin(); ctit != hcl->end(); ctit++) { if(ctit->enclosing == first.vl_ptr()){ - ctit->enclosing = second; - break; + ctit->enclosing = second; + break; } } } @@ -837,7 +837,7 @@ typename Polyline_constraint_hierarchy_2::Vertex_list* Polyline_constraint_hierarchy_2:: insert_constraint(T va, T vb){ Edge he = make_edge(va, vb); - Vertex_list* children = new Vertex_list; + Vertex_list* children = new Vertex_list; Context_list* fathers; typename Sc_to_c_map::iterator scit = sc_to_c_map.find(he); @@ -859,14 +859,14 @@ insert_constraint(T va, T vb){ return children; } - + template typename Polyline_constraint_hierarchy_2::Vertex_list* Polyline_constraint_hierarchy_2:: insert_constraint_old_API(T va, T vb){ Edge he = make_edge(va, vb); - Vertex_list* children = new Vertex_list; + Vertex_list* children = new Vertex_list; Context_list* fathers; typename Sc_to_c_map::iterator scit = sc_to_c_map.find(he); @@ -970,7 +970,7 @@ remove_Steiner(T v, T va, T vb) { // remove a Steiner point CGAL_precondition(!is_constrained_vertex(v)); - + Context_list* hcl1; Context_list* hcl2; if(!get_contexts(va,v,hcl1)) CGAL_triangulation_assertion(false); @@ -994,7 +994,7 @@ remove_Steiner(T v, T va, T vb) /* same as add_Steiner - precondition : va,vb est une souscontrainte. + precondition : va,vb est une souscontrainte. */ template void Polyline_constraint_hierarchy_2:: @@ -1004,7 +1004,7 @@ split_constraint(T va, T vb, T vc){ template -void +void Polyline_constraint_hierarchy_2:: add_Steiner(T va, T vb, T vc){ Context_list* hcl=nullptr; @@ -1020,11 +1020,11 @@ add_Steiner(T va, T vb, T vc){ ++pos; pos = ctit->enclosing->insert(pos.base(), Node(vc)); --pos; - + // set ctxt to the context of (vc,vb) // change *ctit in hcl to the context of (va,vc) // add ctxt to hcl2 list - ctxt.enclosing = ctit->enclosing; + ctxt.enclosing = ctit->enclosing; if(*pos == va) { ctit->pos = pos; ctxt.pos = ++pos; @@ -1049,8 +1049,8 @@ add_Steiner(T va, T vb, T vc){ delete hcl2; } else sc_to_c_map.insert(std::make_pair(make_edge(vc,vb), hcl2)); - - + + sc_to_c_map.erase(make_edge(va,vb)); return; } @@ -1081,15 +1081,15 @@ template inline bool Polyline_constraint_hierarchy_2:: -get_contexts(T va, T vb, - Context_iterator& ctxt, - Context_iterator& past) const +get_contexts(T va, T vb, + Context_iterator& ctxt, + Context_iterator& past) const { Context_list* hcl; if (!get_contexts(va,vb,hcl)) return false; ctxt = hcl->begin(); past = hcl->end(); - return true; + return true; } @@ -1122,7 +1122,7 @@ template void Polyline_constraint_hierarchy_2:: print() const -{ +{ C_iterator hcit; std::map vertex_num; int num = 0; @@ -1138,7 +1138,7 @@ print() const // for(; vnit != vertex_num.end(); vnit++) { // vnit->second = ++num; // std::cerr << "vertex num " << num << " " << vnit->first->point() -// << std::endl; +// << std::endl; // } C_iterator cit=c_begin(); @@ -1161,19 +1161,19 @@ print() const std::cout << std::endl ; for(;scit != sc_end(); scit++){ std::cout << "subconstraint " ; - std::cout << vertex_num[scit->first.first] << " " - << vertex_num[scit->first.second]; + std::cout << vertex_num[scit->first.first] << " " + << vertex_num[scit->first.second]; Context_iterator cb, ce; get_contexts(scit->first.first, scit->first.second, cb, ce); - + std::cout << " enclosing " ; - for(; cb != ce; cb++) { + for(; cb != ce; cb++) { std::cout << cb->id().vl_ptr(); std::cout << " " ; } std::cout << std::endl ; } - return; + return; } diff --git a/Triangulation_2/include/CGAL/Triangulation_hierarchy_2.h b/Triangulation_2/include/CGAL/Triangulation_hierarchy_2.h index 1fbe3957270..d776047064a 100644 --- a/Triangulation_2/include/CGAL/Triangulation_hierarchy_2.h +++ b/Triangulation_2/include/CGAL/Triangulation_hierarchy_2.h @@ -6,7 +6,7 @@ // $URL$ // $Id$ // SPDX-License-Identifier: GPL-3.0-or-later OR LicenseRef-Commercial -// +// // // Author(s) : Olivier Devillers // Mariette Yvinec @@ -105,10 +105,10 @@ public: template Triangulation_hierarchy_2(InputIterator first, InputIterator beyond, - const Geom_traits& traits = Geom_traits()) + const Geom_traits& traits = Geom_traits()) : Tr_Base(traits) - { - hierarchy[0] = this; + { + hierarchy[0] = this; for(int i=1;i std::ptrdiff_t insert(InputIterator first, InputIterator last) { @@ -205,26 +205,26 @@ protected: // some internal methods // GIVING NEW FACES template - Vertex_handle insert_and_give_new_faces(const Point &p, + Vertex_handle insert_and_give_new_faces(const Point &p, OutputItFaces fit, Face_handle start = Face_handle() ); template Vertex_handle insert_and_give_new_faces(const Point& p, Locate_type lt, - Face_handle loc, int li, + Face_handle loc, int li, OutputItFaces fit); template - void remove_and_give_new_faces(Vertex_handle v, + void remove_and_give_new_faces(Vertex_handle v, OutputItFaces fit); - + template - Vertex_handle move_if_no_collision_and_give_new_faces(Vertex_handle v, - const Point &p, OutputItFaces fit); + Vertex_handle move_if_no_collision_and_give_new_faces(Vertex_handle v, + const Point &p, OutputItFaces fit); public: - + //LOCATE Face_handle locate(const Point& p, @@ -273,18 +273,18 @@ private: // systematique instanciation template void add_hidden_vertices_into_map(Tag, - std::map& V) + std::map& V) { - for (typename Tr_Base::Hidden_vertices_iterator - it=hierarchy[0]->hidden_vertices_begin(); - it != hierarchy[0]->hidden_vertices_end(); ++it) { + for (typename Tr_Base::Hidden_vertices_iterator + it=hierarchy[0]->hidden_vertices_begin(); + it != hierarchy[0]->hidden_vertices_end(); ++it) { if (it->up() != Vertex_handle()) V[ it->up()->down() ] = it; } } - - + + void add_hidden_vertices_into_map(Tag_false , - std::map& ) + std::map& ) {return;} }; @@ -294,8 +294,8 @@ template Triangulation_hierarchy_2:: Triangulation_hierarchy_2(const Geom_traits& traits) : Tr_Base(traits) -{ - hierarchy[0] = this; +{ + hierarchy[0] = this; for(int i=1;i Triangulation_hierarchy_2:: Triangulation_hierarchy_2(const Triangulation_hierarchy_2 &tr) : Tr_Base() -{ +{ // create an empty triangulation to be able to delete it ! - hierarchy[0] = this; + hierarchy[0] = this; for(int i=1;i @@ -335,14 +335,14 @@ copy_triangulation(const Triangulation_hierarchy_2 &tr) for(int i=0;icopy_triangulation(*tr.hierarchy[i]); } - + //up and down have been copied in straightforward way // compute a map at lower level std::map V; { - for( Finite_vertices_iterator it=hierarchy[0]->finite_vertices_begin(); - it != hierarchy[0]->finite_vertices_end(); ++it) { + for( Finite_vertices_iterator it=hierarchy[0]->finite_vertices_begin(); + it != hierarchy[0]->finite_vertices_end(); ++it) { if (it->up() != Vertex_handle()) V[ it->up()->down() ] = it; } } @@ -351,15 +351,15 @@ copy_triangulation(const Triangulation_hierarchy_2 &tr) { for(int i=1;ifinite_vertices_begin(); - it != hierarchy[i]->finite_vertices_end(); ++it) { - // down pointer goes in original instead in copied triangulation - it->set_down(V[it->down()]); - // make reverse link - it->down()->set_up(it); - // I think the next line is unnecessary (my) - // make map for next level - if (it->up()!= Vertex_handle() ) V[ it->up()->down() ] = it; + for( Finite_vertices_iterator it=hierarchy[i]->finite_vertices_begin(); + it != hierarchy[i]->finite_vertices_end(); ++it) { + // down pointer goes in original instead in copied triangulation + it->set_down(V[it->down()]); + // make reverse link + it->down()->set_up(it); + // I think the next line is unnecessary (my) + // make map for next level + if (it->up()!= Vertex_handle() ) V[ it->up()->down() ] = it; } } } @@ -369,7 +369,7 @@ copy_triangulation(const Triangulation_hierarchy_2 &tr) /* void */ /* Triangulation_hierarchy_2:: */ /* add_hidden_vertices_into_map(Tag_false, */ -/* std::map& V) { */ +/* std::map& V) { */ /* return; */ /* } */ @@ -378,10 +378,10 @@ copy_triangulation(const Triangulation_hierarchy_2 &tr) /* void */ /* Triangulation_hierarchy_2:: */ /* add_hidden_vertices_into_map(Tag_true, */ -/* std::map& V) */ +/* std::map& V) */ /* { */ /* for (typename Tr_Base::Hidden_vertices_iterator */ -/* it=hierarchy[0]->hidden_vertices_begin(); */ +/* it=hierarchy[0]->hidden_vertices_begin(); */ /* it != hierarchy[0]->hidden_vertices_end(); ++it) { */ /* if (it->up() != Vertex_handle()) V[ it->up()->down() ] = it; */ /* } */ @@ -407,7 +407,7 @@ Triangulation_hierarchy_2:: ~Triangulation_hierarchy_2() { clear(); - for(int i= 1; inumber_of_vertices() << std::endl; + std::cout << "number_of_vertices " + << hierarchy[i]->number_of_vertices() << std::endl; result = result && hierarchy[i]->is_valid(verbose,level); } //verify that lower level has no down pointers - for( it = hierarchy[0]->finite_vertices_begin(); - it != hierarchy[0]->finite_vertices_end(); ++it) + for( it = hierarchy[0]->finite_vertices_begin(); + it != hierarchy[0]->finite_vertices_end(); ++it) result = result && ( it->down() == Vertex_handle()); //verify that other levels have down pointer and reciprocal link is fine for(i=1;ifinite_vertices_begin(); - it != hierarchy[i]->finite_vertices_end(); ++it) - result = result && - ( &*(it->down()->up()) == &*(it) ); + for( it = hierarchy[i]->finite_vertices_begin(); + it != hierarchy[i]->finite_vertices_end(); ++it) + result = result && + ( &*(it->down()->up()) == &*(it) ); //verify that levels have up pointer and reciprocal link is fine for(i=0;ifinite_vertices_begin(); - it != hierarchy[i]->finite_vertices_end(); ++it) + for( it = hierarchy[i]->finite_vertices_begin(); + it != hierarchy[i]->finite_vertices_end(); ++it) result = result && ( it->up() == Vertex_handle() || - &*it == &*(it->up())->down() ); + &*it == &*(it->up())->down() ); return result; } - + template typename Triangulation_hierarchy_2::Vertex_handle Triangulation_hierarchy_2:: @@ -471,7 +471,7 @@ insert(const Point &p, Face_handle loc) Vertex_handle vertex=hierarchy[0]->Tr_Base::insert(p,lt,positions[0],i); Vertex_handle previous=vertex; Vertex_handle first = vertex; - + int level = 1; while (level <= vertex_level ){ vertex=hierarchy[level]->Tr_Base::insert(p,positions[level]); @@ -488,7 +488,7 @@ typename Triangulation_hierarchy_2::Vertex_handle Triangulation_hierarchy_2:: insert(const Point& p, Locate_type lt, - Face_handle loc, + Face_handle loc, int li ) { int vertex_level = random_level(); @@ -526,7 +526,7 @@ push_back(const Point &p) } template -void +void Triangulation_hierarchy_2:: remove(Vertex_handle v ) { @@ -534,7 +534,7 @@ remove(Vertex_handle v ) int l = 0 ; while(1){ hierarchy[l++]->remove(v); - if (u == Vertex_handle()) break; + if (u == Vertex_handle()) break; if (l >= Triangulation_hierarchy_2__maxlevel) break; v=u; u=v->up(); } @@ -551,15 +551,15 @@ remove_and_give_new_faces(Vertex_handle v, OutputItFaces fit) while(1){ if(l==0) hierarchy[l++]->remove_and_give_new_faces(v, fit); else hierarchy[l++]->remove(v); - if (u == Vertex_handle()) break; + if (u == Vertex_handle()) break; if (l >= Triangulation_hierarchy_2__maxlevel) break; v=u; u=v->up(); - } + } } template -inline void +inline void Triangulation_hierarchy_2:: remove_degree_3(Vertex_handle v ) { @@ -567,7 +567,7 @@ remove_degree_3(Vertex_handle v ) } template -inline void +inline void Triangulation_hierarchy_2:: remove_first(Vertex_handle v ) { @@ -575,7 +575,7 @@ remove_first(Vertex_handle v ) } template -inline void +inline void Triangulation_hierarchy_2:: remove_second(Vertex_handle v ) { @@ -591,7 +591,7 @@ move_if_no_collision(Vertex_handle v, const Point &p) { while(1) { Vertex_handle w = hierarchy[l++]->move_if_no_collision(v, p); if(w != v) return w; - if (u == Vertex_handle()) break; + if (u == Vertex_handle()) break; if (l >= Triangulation_hierarchy_2__maxlevel) break; v=u; u=v->up(); } @@ -615,21 +615,21 @@ template template typename Triangulation_hierarchy_2::Vertex_handle Triangulation_hierarchy_2:: -move_if_no_collision_and_give_new_faces(Vertex_handle v, const Point &p, +move_if_no_collision_and_give_new_faces(Vertex_handle v, const Point &p, OutputItFaces oif) { Vertex_handle u=v->up(), norm = v; int l = 0 ; while(1){ Vertex_handle w; - if(l == 0) - w = + if(l == 0) + w = hierarchy[l++]->move_if_no_collision_and_give_new_faces(v, p, oif); else w = hierarchy[l++]->move_if_no_collision(v, p); if(w != v) return w; - if (u == Vertex_handle()) break; + if (u == Vertex_handle()) break; if (l >= Triangulation_hierarchy_2__maxlevel) break; v=u; u=v->up(); } @@ -654,7 +654,7 @@ Triangulation_hierarchy_2::insert_and_give_new_faces(const Point &p, hierarchy[0]->Tr_Base::insert_and_give_new_faces(p,lt,positions[0],i,oif); Vertex_handle previous=vertex; Vertex_handle first = vertex; - + int level = 1; while (level <= vertex_level ){ vertex=hierarchy[level]->Tr_Base::insert(p,positions[level]); @@ -674,7 +674,7 @@ Triangulation_hierarchy_2:: insert_and_give_new_faces(const Point &p, Locate_type lt, Face_handle loc, - int li, + int li, OutputItFaces oif) { int vertex_level = random_level(); @@ -739,14 +739,14 @@ locate_in_all(const Point& p, typename Geom_traits::Construct_point_2 construct_point = geom_traits().construct_point_2_object(); - + // find the highest level with enough vertices that is at the same time 2D - while ( (hierarchy[--level]->number_of_vertices() - < static_cast (Triangulation_hierarchy_2__minsize )) - || (hierarchy[level]->dimension()<2) ){ + while ( (hierarchy[--level]->number_of_vertices() + < static_cast (Triangulation_hierarchy_2__minsize )) + || (hierarchy[level]->dimension()<2) ){ if ( ! level) break; // do not go below 0 } - if((level>0) && (hierarchy[level]->dimension()<2)){ + if((level>0) && (hierarchy[level]->dimension()<2)){ level--; } @@ -772,10 +772,10 @@ locate_in_all(const Point& p, } // compare to vertex 2, but only if the triangulation is 2D, because otherwise vertex(2) is nullptr if ( (hierarchy[level]->dimension()==2) && (! hierarchy[level]->is_infinite(position->vertex(2)))){ - if ( closer( construct_point(p), - construct_point(position->vertex(2)->point()), - construct_point(nearest->point())) == SMALLER ){ - nearest = position->vertex(2); + if ( closer( construct_point(p), + construct_point(position->vertex(2)->point()), + construct_point(nearest->point())) == SMALLER ){ + nearest = position->vertex(2); } } // go at the same vertex on level below @@ -783,7 +783,7 @@ locate_in_all(const Point& p, position = nearest->face(); // incident face --level; } - pos[0]=hierarchy[0]->locate(p,lt,li,loc == Face_handle() ? position : loc); // at level 0 + pos[0]=hierarchy[0]->locate(p,lt,li,loc == Face_handle() ? position : loc); // at level 0 } template diff --git a/Triangulation_2/include/CGAL/Triangulation_hierarchy_vertex_base_2.h b/Triangulation_2/include/CGAL/Triangulation_hierarchy_vertex_base_2.h index 65f15868cbf..e1e30c53706 100644 --- a/Triangulation_2/include/CGAL/Triangulation_hierarchy_vertex_base_2.h +++ b/Triangulation_2/include/CGAL/Triangulation_hierarchy_vertex_base_2.h @@ -6,7 +6,7 @@ // $URL$ // $Id$ // SPDX-License-Identifier: GPL-3.0-or-later OR LicenseRef-Commercial -// +// // // Author(s) : Olivier Devillers // Mariette Yvinec diff --git a/Triangulation_2/test/Triangulation_2/include/CGAL/_test_cls_const_Del_triangulation_2.h b/Triangulation_2/test/Triangulation_2/include/CGAL/_test_cls_const_Del_triangulation_2.h index 25e9cac0432..ccc193bad99 100644 --- a/Triangulation_2/test/Triangulation_2/include/CGAL/_test_cls_const_Del_triangulation_2.h +++ b/Triangulation_2/test/Triangulation_2/include/CGAL/_test_cls_const_Del_triangulation_2.h @@ -9,10 +9,10 @@ // intended for general use. // // ---------------------------------------------------------------------------- -// +// // release : // release_date : -// +// // file : test/Triangulation/include/CGAL/_test_cls_const_Del_tr.. // source : $URL$ // revision : $Id$ @@ -27,7 +27,7 @@ #include template -void +void _test_cls_const_Del_triangulation(const Triangul&) { // The following assertion is commented, because, in CT_plus_2, @@ -74,7 +74,7 @@ _test_cls_const_Del_triangulation(const Triangul&) Point(0,2), Point(1,2), Point(2,2), Point(3,2),Point(4,2), Point(4,3), Point(3,3), Point(2,3), Point(1,3),Point(0,3) }; - for (int m=0; m<19; m++) + for (int m=0; m<19; m++) l.push_back(Constraint(lpt[m],lpt[m+1])); Triangul T2(l); assert( T2.dimension() == 2 ); @@ -88,22 +88,22 @@ _test_cls_const_Del_triangulation(const Triangul&) std::back_insert_iterator > c_inserter(conflicts); std::back_insert_iterator > be_inserter(hole_bd); std::pair >, - std::back_insert_iterator > > + std::back_insert_iterator > > pit(c_inserter,be_inserter); c_inserter = T2.get_conflicts(Point(1,1,2), std::back_inserter(conflicts)); conflicts.clear(); - pit = T2.get_conflicts_and_boundary(Point(1,1,2), - std::back_inserter(conflicts), - std::back_inserter(hole_bd)); + pit = T2.get_conflicts_and_boundary(Point(1,1,2), + std::back_inserter(conflicts), + std::back_inserter(hole_bd)); c_inserter = pit.first; be_inserter = pit.second; assert(hole_bd.size() == conflicts.size() + 2); conflicts.clear(); hole_bd.clear(); - T2.get_conflicts(Point(0,1,2), - std::back_inserter(conflicts)); - T2.get_boundary_of_conflicts(Point(0,1,2), - std::back_inserter(hole_bd)); + T2.get_conflicts(Point(0,1,2), + std::back_inserter(conflicts)); + T2.get_boundary_of_conflicts(Point(0,1,2), + std::back_inserter(hole_bd)); assert(hole_bd.size() == conflicts.size() + 2); conflicts.clear(); std::size_t nch = hole_bd.size(); @@ -119,14 +119,14 @@ _test_cls_const_Del_triangulation(const Triangul&) // test insertion through get_conflicts + star_hole conflicts.clear(); hole_bd.clear(); - T2.get_conflicts_and_boundary(Point(0,1,2), - std::back_inserter(conflicts), - std::back_inserter(hole_bd)); - T2.star_hole(Point(0,1,2), - hole_bd.begin(), - hole_bd.end(), - conflicts.begin(), - conflicts.end()); + T2.get_conflicts_and_boundary(Point(0,1,2), + std::back_inserter(conflicts), + std::back_inserter(hole_bd)); + T2.star_hole(Point(0,1,2), + hole_bd.begin(), + hole_bd.end(), + conflicts.begin(), + conflicts.end()); assert(T2.is_valid()); //test remove_constrained_edge diff --git a/Triangulation_2/test/Triangulation_2/include/CGAL/_test_cls_constrained_triangulation_2.h b/Triangulation_2/test/Triangulation_2/include/CGAL/_test_cls_constrained_triangulation_2.h index 0d854e4188e..76512ccb669 100644 --- a/Triangulation_2/test/Triangulation_2/include/CGAL/_test_cls_constrained_triangulation_2.h +++ b/Triangulation_2/test/Triangulation_2/include/CGAL/_test_cls_constrained_triangulation_2.h @@ -9,10 +9,10 @@ // intended for general use. // // ---------------------------------------------------------------------------- -// +// // release : // release_date : -// +// // file : test/Triangulation/include/CGAL/_test_cls_constrained... // source : $URL$ // revision : $Id$ @@ -89,7 +89,7 @@ _test_cdt_throwing(const Pt& p0, const Pt& p1, const Pt& p2, const Pt& p3, } template -void +void _test_cls_constrained_triangulation(const Triang &) { // The following assertion is commented, because, in CT_plus_2, @@ -142,7 +142,7 @@ _test_cls_constrained_triangulation(const Triang &) assert( T0_1.dimension() == -1 ); assert( T0_1.number_of_vertices() == 0 ); assert( T0_1.is_valid() ); - + l.push_back(Constraint(Point(0,0),Point(0,0))); Triang T0_2(l); assert( T0_2.dimension() == 0 ); @@ -159,7 +159,7 @@ _test_cls_constrained_triangulation(const Triang &) assert( T1_1.dimension() == 1 ); assert( T1_1.number_of_vertices() == 4 ); assert( T1_1.is_valid() ); - + l.erase(l.begin(),l.end()); for (m=0; m<4; m++) l.push_back(Constraint(Point(3*m, 2*m),Point(3*(m+1),2*(m+1)) )); @@ -178,7 +178,7 @@ _test_cls_constrained_triangulation(const Triang &) assert( T2_1.dimension() == 2 ); assert( T2_1.number_of_vertices() == 5); assert( T2_1.is_valid() ); - + l.erase(l.begin(),l.end()); Point lpt[20] = { @@ -187,14 +187,14 @@ _test_cls_constrained_triangulation(const Triang &) Point(0,2), Point(1,2), Point(2,2), Point(3,2),Point(4,2), Point(4,3), Point(3,3), Point(2,3), Point(1,3),Point(0,3) }; - for (m=0;m<19;m++) + for (m=0;m<19;m++) l.push_back(Constraint(lpt[m],lpt[m+1])); Triang T2_2(l); assert( T2_2.dimension() == 2 ); assert( T2_2.number_of_vertices() == 20); assert( T2_2.is_valid() ); - + // Build triangulation with iterator std::cout << " with input iterator" << std::endl; list_iterator first=l.begin(); @@ -237,7 +237,7 @@ _test_cls_constrained_triangulation(const Triang &) std::ofstream of1_2("T12.triangulation"); CGAL::set_ascii_mode(of1_2); of1_2 << T1_2; of1_2.close(); - + std::ofstream of2_1("T21.triangulation"); CGAL::set_ascii_mode(of2_1); of2_1 << T2_1; of2_1.close(); @@ -273,18 +273,18 @@ _test_cls_constrained_triangulation(const Triang &) All_faces_iterator fit2 = T2_2.all_faces_begin(); All_faces_iterator fit2_bis = T2_4.all_faces_begin(); for( ; fit2 != T2_2.all_faces_end(); ++fit2, ++fit2_bis) { - for(int i=0; i<3 ; i++) + for(int i=0; i<3 ; i++) assert( fit2->is_constrained(i) == fit2_bis->is_constrained(i) ); } - - - + + + // remove_constraint and remove _1 dim std::cout << "remove_constrained_edge and remove 1-dim" << std::endl; Face_handle fh; int ih; Vertex_handle vha, vhb; - Locate_type lt; + Locate_type lt; int li; fh = T1_2.locate(Point(0,0),lt,li); assert( lt == Triang::VERTEX ); vha = fh->vertex(li); @@ -305,14 +305,14 @@ _test_cls_constrained_triangulation(const Triang &) vha = fh->vertex(li); List_edges edges; assert(T1_2.are_there_incident_constraints(vha, - std::back_inserter(edges))); + std::back_inserter(edges))); List_edges ic_edges; std::back_insert_iterator inserter(ic_edges); inserter = T1_2.incident_constraints(vha, inserter); - assert(ic_edges.size() == 1); + assert(ic_edges.size() == 1); T1_2.remove_incident_constraints(vha); inserter = T1_2.incident_constraints(vha, inserter ); - assert(ic_edges.size() == 1); + assert(ic_edges.size() == 1); T1_2.remove(vha); assert(T1_2.is_valid()); @@ -330,7 +330,7 @@ _test_cls_constrained_triangulation(const Triang &) T2_2.insert(lpt[m], lpt[m+1]); assert(T2_2.is_valid()); fh = T2_2.locate(lpt[m+1],lt,li); assert( lt == Triang::VERTEX ); - vhb = fh->vertex(li); + vhb = fh->vertex(li); assert(T2_2.are_there_incident_constraints(vhb)); T2_2.remove_incident_constraints(vhb); T2_2.remove(vhb); @@ -341,12 +341,12 @@ _test_cls_constrained_triangulation(const Triang &) edges.clear(); ic_edges.clear(); assert(T2_2.are_there_incident_constraints(vha)); - assert(T2_2.are_there_incident_constraints(vha, - std::back_inserter(edges))); + assert(T2_2.are_there_incident_constraints(vha, + std::back_inserter(edges))); ic_edges.clear(); inserter = std::back_insert_iterator(ic_edges); inserter = T2_2.incident_constraints(vha,inserter); - assert(ic_edges.size() == 2); + assert(ic_edges.size() == 2); T2_2.remove_incident_constraints(vha); inserter = T2_2.incident_constraints(vha, inserter); assert(ic_edges.size() == 2); diff --git a/Triangulation_2/test/Triangulation_2/include/CGAL/_test_cls_delaunay_triangulation_2.h b/Triangulation_2/test/Triangulation_2/include/CGAL/_test_cls_delaunay_triangulation_2.h index f9cc6fcb2aa..3d116c10900 100644 --- a/Triangulation_2/test/Triangulation_2/include/CGAL/_test_cls_delaunay_triangulation_2.h +++ b/Triangulation_2/test/Triangulation_2/include/CGAL/_test_cls_delaunay_triangulation_2.h @@ -7,10 +7,10 @@ // intended for general use. // // ---------------------------------------------------------------------------- -// +// // release : // release_date : -// +// // source : $URL$ // file : include/CGAL/_test_cls_delaunay_triangulation_2.C // revision : $Id$ @@ -64,14 +64,14 @@ _test_cls_delaunay_triangulation_2( const Del & ) for (m=0; m<20; m++) T1.insert( Point(3*m, 2*m) ); assert( T1.is_valid() ); - + Del T2; for (m=0; m<20; m++) for (p=0; p<20; p++) - // T2.insert( Point(3*m+p, m-2*p) ); - T2.insert(Point(m,p)); + // T2.insert( Point(3*m+p, m-2*p) ); + T2.insert(Point(m,p)); assert( T2.is_valid() ); - + Del T3; // All these points are on a circle of radius 325 Point pt[28] = { @@ -84,15 +84,15 @@ _test_cls_delaunay_triangulation_2( const Del & ) Point(-36,323), Point(-80,315), Point(-91,312), Point(-125,300), Point(-165,280), Point(-195,260), Point(-204,253) }; - for (m=0; m<28; m++) + for (m=0; m<28; m++) T3.insert( Point(pt[m]) ); assert( T3.is_valid() ); - + // test nearest_vertex Vertex_handle vnn; Face_handle cible; - int i; + int i; Locate_type lt; cible = T2.locate(Point(0,0,1),lt,i); assert( lt == Del::VERTEX); @@ -112,21 +112,21 @@ _test_cls_delaunay_triangulation_2( const Del & ) std::back_insert_iterator > c_inserter(conflicts); std::back_insert_iterator > be_inserter(hole_bd); std::pair >, - std::back_insert_iterator > > + std::back_insert_iterator > > pit(c_inserter,be_inserter); c_inserter = T2.get_conflicts(Point(1,1,2), std::back_inserter(conflicts)); conflicts.clear(); - pit = T2.get_conflicts_and_boundary(Point(1,1,2), - std::back_inserter(conflicts), - std::back_inserter(hole_bd)); + pit = T2.get_conflicts_and_boundary(Point(1,1,2), + std::back_inserter(conflicts), + std::back_inserter(hole_bd)); c_inserter = pit.first; be_inserter = pit.second; assert(hole_bd.size() == conflicts.size() + 2); conflicts.clear(); hole_bd.clear(); T2.get_conflicts(Point(0,1,2), std::back_inserter(conflicts)); - T2.get_boundary_of_conflicts(Point(0,1,2), - std::back_inserter(hole_bd)); + T2.get_boundary_of_conflicts(Point(0,1,2), + std::back_inserter(hole_bd)); assert(hole_bd.size() == conflicts.size() + 2); conflicts.clear(); hole_bd.clear(); @@ -160,7 +160,7 @@ _test_cls_delaunay_triangulation_2( const Del & ) while(curr != hole_bd.end()); T2.star_hole (Point(1,1,2), hole_bd.begin(), hole_bd.end(), - conflicts.begin(), conflicts.end() ); + conflicts.begin(), conflicts.end() ); assert(T2.is_valid()); @@ -208,7 +208,7 @@ _test_cls_delaunay_triangulation_2( const Del & ) std::cout << " displacements" << std::endl; std::cout << " degenerate cases: " << std::endl; - + Del TM_0, TM_1; Vertex_handle tmv1 = TM_0.insert(Point(0,0)); Vertex_handle tmv2 = TM_0.insert(Point(1,0)); @@ -234,7 +234,7 @@ _test_cls_delaunay_triangulation_2( const Del & ) TM_0.move_if_no_collision(tmv3, Point(2, 0)); assert(TM_0.tds().is_valid()); assert(TM_0.is_valid()); - assert(TM_0.dimension() == 1); + assert(TM_0.dimension() == 1); Vertex_handle tmv4 = TM_0.insert(Point(1,1)); assert(TM_0.dimension() == 2); @@ -308,7 +308,7 @@ _test_cls_delaunay_triangulation_2( const Del & ) TM_0.move_if_no_collision(tmv4, Point(1, 2)); assert(TM_0.tds().is_valid()); assert(TM_0.is_valid()); - assert(TM_0.dimension() == 1); + assert(TM_0.dimension() == 1); TM_0.move_if_no_collision(tmv4, Point(3, 0)); assert(TM_0.tds().is_valid()); @@ -334,7 +334,7 @@ _test_cls_delaunay_triangulation_2( const Del & ) TM_1.insert(points.begin(), points.end()); Vertex_handle vTM_1; for(int i=0; i<5; i++) { - for(typename Del::Finite_vertices_iterator + for(typename Del::Finite_vertices_iterator fvi = TM_1.finite_vertices_begin(); fvi != TM_1.finite_vertices_end(); fvi++) { Point p = Point(rand()%30000, rand()%30000); @@ -345,7 +345,7 @@ _test_cls_delaunay_triangulation_2( const Del & ) // A simple test to see if move return the good vertex // when there is a collision - assert(TM_1.move(TM_1.finite_vertices_begin(), vTM_1->point()) == vTM_1); + assert(TM_1.move(TM_1.finite_vertices_begin(), vTM_1->point()) == vTM_1); } @@ -362,10 +362,10 @@ _test_delaunay_duality( const Del &T ) Face_iterator fit; for (fit = T.finite_faces_begin(); fit != T.finite_faces_end(); ++fit) { - assert( T.side_of_oriented_circle(fit, T.dual(fit)) == - CGAL::ON_POSITIVE_SIDE ); + assert( T.side_of_oriented_circle(fit, T.dual(fit)) == + CGAL::ON_POSITIVE_SIDE ); } - + // Test dual(edge iterator) Edge_iterator eit; for (eit = T.finite_edges_begin(); eit != T.finite_edges_end(); ++eit) @@ -376,11 +376,11 @@ _test_delaunay_duality( const Del &T ) typename Gt::Line_2 l; if ( CGAL::assign(s,o) ) { assert( ! T.is_infinite((*eit).first) ); - assert( ! T.is_infinite(((*eit).first)->neighbor((*eit).second )) ); - } + assert( ! T.is_infinite(((*eit).first)->neighbor((*eit).second )) ); + } else if ( CGAL::assign(l,o) ) { assert( T.dimension() == 1 ); - } + } else { assert( CGAL::assign(r,o) ); } @@ -388,15 +388,15 @@ _test_delaunay_duality( const Del &T ) // Test dual(edge circulator) Edge_circulator ec=T.incident_edges(T.finite_vertices_begin()), done(ec); - if ( !ec.is_empty() ) - do + if ( !ec.is_empty() ) + do { if (! T.is_infinite(ec)){ - CGAL::Object o = T.dual(ec); - typename Gt::Ray_2 r; + CGAL::Object o = T.dual(ec); + typename Gt::Ray_2 r; typename Gt::Segment_2 s; - typename Gt::Line_2 l; - assert( CGAL::assign(s,o) || CGAL::assign(r,o) || CGAL::assign(l,o) ); + typename Gt::Line_2 l; + assert( CGAL::assign(s,o) || CGAL::assign(r,o) || CGAL::assign(l,o) ); } ++ec; } while ( ec == done); diff --git a/Triangulation_2/test/Triangulation_2/include/CGAL/_test_cls_triangulation_2.h b/Triangulation_2/test/Triangulation_2/include/CGAL/_test_cls_triangulation_2.h index 498ff9139be..ebfa74d1bb0 100644 --- a/Triangulation_2/test/Triangulation_2/include/CGAL/_test_cls_triangulation_2.h +++ b/Triangulation_2/test/Triangulation_2/include/CGAL/_test_cls_triangulation_2.h @@ -7,14 +7,14 @@ // intended for general use. // // ---------------------------------------------------------------------------- -// +// // release : // release_date : -// -// source : +// +// source : // file : include/CGAL/_test_cls_triangulation_2.C -// revision : -// revision_date : +// revision : +// revision_date : // author(s) : Herve Bronnimann (Herve.Bronnimann@sophia.inria.fr) @@ -62,7 +62,7 @@ _test_cls_triangulation_2( const Triangul & ) typedef std::pair Edge; - typedef typename Triangul::Finite_vertices_iterator + typedef typename Triangul::Finite_vertices_iterator Finite_vertices_iterator; typedef typename Triangul::Finite_faces_iterator Finite_faces_iterator; typedef typename Triangul::Finite_edges_iterator Finite_edges_iterator; @@ -74,7 +74,7 @@ _test_cls_triangulation_2( const Triangul & ) typedef typename Triangul::Line_face_circulator Line_face_circulator; typedef typename Triangul::Locate_type Locate_type; - + CGAL_USE_TYPE(Gt); CGAL_USE_TYPE(Vertex); CGAL_USE_TYPE(Face); @@ -116,19 +116,19 @@ _test_cls_triangulation_2( const Triangul & ) l.push_back(p1); l.push_back(p2); l.push_back(p3); l.push_back(p4); l.push_back(p5); l.push_back(p6); l.push_back(p7); l.push_back(p8); l.push_back(p9); - + std::vector v; v.push_back(p0); v.push_back(p1); v.push_back(p2); v.push_back(p3); v.push_back(p4); v.push_back(p5); v.push_back(p6); v.push_back(p7); v.push_back(p8); v.push_back(p9); - - + + /*****************************/ /***** CONSTRUCTORS (1) ******/ std::cout << " constructors(1)" << std::endl; Triangul T1; - assert( T1.dimension() == -1 ); + assert( T1.dimension() == -1 ); assert( T1.number_of_vertices() == 0 ); Triangul T3(T1); @@ -138,7 +138,7 @@ _test_cls_triangulation_2( const Triangul & ) /**************************/ /******* INSERTIONS *******/ - + // Tk denotes a k-dimensional triangulation // the handle returned when inserting pj into Tk_n is called vk_n_j // the asserts at the end of the insert() are to avoid compiler @@ -148,14 +148,14 @@ _test_cls_triangulation_2( const Triangul & ) /******* 0-dimensional triangulations ******/ std::cout << " insertions 0-dim" << std::endl; - + Triangul T0_0; assert( T0_0.dimension() == -1 ); assert( T0_0.number_of_vertices() == 0 ); assert( T0_0.number_of_faces() == 0); assert( T0_0.is_valid() ); - Triangul T0_1; + Triangul T0_1; Vertex_handle v0_1_0 = T0_1.insert(p0); assert( v0_1_0 != NULL ); assert( T0_1.dimension() == 0 ); assert( T0_1.number_of_vertices() == 1 ); @@ -163,19 +163,19 @@ _test_cls_triangulation_2( const Triangul & ) assert( T0_1.is_valid() ); // test insert_first() - Triangul T0_2; + Triangul T0_2; Vertex_handle v0_2_0 = T0_2.insert_first(p0); assert( v0_2_0 != NULL ); assert( T0_2.dimension() == 0 ); assert( T0_2.number_of_vertices() == 1 ); assert( T0_2.number_of_faces() == 0); assert( T0_2.is_valid() ); - + /******** 1-dimensional triangulations ******/ // T1_n denotes a 1-dimensional triangulation with n vertices // when there are several, we use T1_n_p std::cout << " insertions 1-dim" << std::endl; - + Triangul T1_2; Vertex_handle v1_2_1 = T1_2.insert(p1); Vertex_handle v1_2_2 = T1_2.insert(p2); @@ -183,7 +183,7 @@ _test_cls_triangulation_2( const Triangul & ) assert( T1_2.number_of_vertices() == 2 ); assert( T1_2.number_of_faces() == 0 ); assert( T1_2.is_valid() ); - + // p1,p3,p2 [endpoints first] Triangul T1_3_0; Vertex_handle v1_3_0_1 = T1_3_0.insert(p1); assert( v1_3_0_1 != NULL ); @@ -193,7 +193,7 @@ _test_cls_triangulation_2( const Triangul & ) assert( T1_3_0.number_of_vertices() == 3 ); assert( T1_3_0.number_of_faces() == 0 ); assert( T1_3_0.is_valid() ); - + // p1,p2,p3 [middle point first] Triangul T1_3_1; Vertex_handle v1_3_1_1 = T1_3_1.insert(p1); assert( v1_3_1_1 != NULL ); @@ -216,38 +216,38 @@ _test_cls_triangulation_2( const Triangul & ) assert( T1_5.is_valid() ); // test insert_second() - Triangul T1_6 = T0_2; + Triangul T1_6 = T0_2; Vertex_handle v1_6_2 = T1_6.insert_second(p3); assert( v1_6_2 != NULL ); assert( T1_6.dimension() == 1 ); assert( T1_6.number_of_vertices() == 2 ); - assert( T1_6.is_valid() ); - - /******** 2-dimensional triangulations ******/ + assert( T1_6.is_valid() ); + + /******** 2-dimensional triangulations ******/ std::cout << " insertions 2-dim" << std::endl; - + Triangul T2_1; Vertex_handle v2_1_0 = T2_1.insert(p0); Vertex_handle v2_1_1 = T2_1.insert(p1); Vertex_handle v2_1_2 = T2_1.insert(p2); Vertex_handle v2_1_3 = T2_1.insert(p3); // on the edge p1,p2, on the convex hull Vertex_handle v2_1_4 = T2_1.insert(p4); // outside, with two visible collineaar edges - Vertex_handle v2_1_5 = T2_1.insert(p5); + Vertex_handle v2_1_5 = T2_1.insert(p5); Vertex_handle v2_1_6 = T2_1.insert(p6); // outside, collinear with p2,p5 Vertex_handle v2_1_7 = T2_1.insert(p7); // outside with two visible collinear edges - // but also collinear with and extending p0,p5 - Vertex_handle v2_1_8 = T2_1.insert(p8); + // but also collinear with and extending p0,p5 + Vertex_handle v2_1_8 = T2_1.insert(p8); Vertex_handle v2_1_9 = T2_1.insert(p9); // inside, on the edge p6,p7 Vertex_handle v2_1_10 = T2_1.insert(p10); // inside the face p2,p4,p6 assert( T2_1.dimension() == 2 ); assert( T2_1.number_of_vertices() == 11 ); #ifndef CGAL_NO_DEPRECATED_CODE - assert( T2_1.number_of_faces() == 2 * 12 - 4 + assert( T2_1.number_of_faces() == 2 * 12 - 4 - T2_1.infinite_vertex()->degree() ); #endif - assert( T2_1.number_of_faces() == 2 * 12 - 4 + assert( T2_1.number_of_faces() == 2 * 12 - 4 - T2_1.degree(T2_1.infinite_vertex()) ); - + // test is_valid for 2-triangulations assert( T2_1.is_valid() ); @@ -272,7 +272,7 @@ _test_cls_triangulation_2( const Triangul & ) assert( T2_3.dimension() == 2 ); assert( T2_3.number_of_vertices() == 11 ); assert( T2_3.is_valid() ); - + // make sure inserting on a previous point does not insert it again assert( T2_3.insert(p10) == v2_3_10 ); assert( T2_3.number_of_vertices() == 11 ); @@ -303,7 +303,7 @@ _test_cls_triangulation_2( const Triangul & ) assert( T2_6.dimension() == 2 ); assert( T2_6.number_of_vertices() == 10 ); assert( T2_6.is_valid() ); - + // test grid insert Triangul T2_7; int m, p; @@ -328,7 +328,7 @@ _test_cls_triangulation_2( const Triangul & ) int fli = ff->index(f2); T2_8.flip(ff,fli); assert( T2_8.is_valid() ); - + //make_hole star_hole std::list hole; T2_3.make_hole(v2_3_10, hole); @@ -341,7 +341,7 @@ _test_cls_triangulation_2( const Triangul & ) std::cout << " displacements" << std::endl; std::cout << " degenerate cases: " << std::endl; - + Triangul TM_0, TM_1; Vertex_handle tmv1 = TM_0.insert(Point(0,0)); Vertex_handle tmv2 = TM_0.insert(Point(1,0)); @@ -418,7 +418,7 @@ _test_cls_triangulation_2( const Triangul & ) TM_0.move_if_no_collision(tmv4, Point(1, 2)); assert(TM_0.tds().is_valid()); assert(TM_0.is_valid()); - assert(TM_0.dimension() == 1); + assert(TM_0.dimension() == 1); TM_0.move_if_no_collision(tmv4, Point(3, 0)); assert(TM_0.tds().is_valid()); @@ -442,9 +442,9 @@ _test_cls_triangulation_2( const Triangul & ) points.push_back(Point(rand()%30000, rand()%30000)); } TM_1.insert(points.begin(), points.end()); - Vertex_handle vTM_1; + Vertex_handle vTM_1; for(int i=0; i<5; i++) { - for(typename Triangul::Finite_vertices_iterator + for(typename Triangul::Finite_vertices_iterator fvi = TM_1.finite_vertices_begin(); fvi != TM_1.finite_vertices_end(); fvi++) { Point p = Point(rand()%30000, rand()%30000); @@ -486,13 +486,13 @@ _test_cls_triangulation_2( const Triangul & ) assert( T2_1_1.dimension() == 2 ); assert( T2_1_1.number_of_vertices() == 11 ); assert( T2_1_1.is_valid() ); - + // test assignment operator Triangul T2_1_4 = T2_1; assert( T2_1_4.dimension() == 2 ); assert( T2_1_4.number_of_vertices() == 11 ); assert( T2_1_4.is_valid() ); - + /*********************************************/ /****** FINITE/INFINITE VERTICES/FACES *******/ @@ -538,16 +538,16 @@ _test_cls_triangulation_2( const Triangul & ) /******** POINT LOCATIONS ************/ // Locate_type lt; // see above - + // Check point location in 0-dimensional triangulations // No need because of precondition (at least two vertices) - + // Check point location in 1-dimensional triangulations std::cout << " point locations 1-dim" << std::endl; Triangul T1_3_2; T1_3_2.insert(p1); T1_3_2.insert(p2); - T1_3_2.insert(p9); + T1_3_2.insert(p9); f = T1_3_2.locate(p1,lt,li); assert( lt == Triangul::VERTEX ); assert( T1_3_2.xy_equal(f->vertex(li)->point(), p1) ); f = T1_3_2.locate(p2,lt,li); assert( lt == Triangul::VERTEX ); @@ -566,7 +566,7 @@ _test_cls_triangulation_2( const Triangul & ) f = T1_3_2.locate(p5,lt,li); assert( lt == Triangul::OUTSIDE_AFFINE_HULL ); f = T1_3_2.locate(p4,lt,li); assert( lt == Triangul::OUTSIDE_AFFINE_HULL ); f = T1_3_2.locate(p6,lt,li); assert( lt == Triangul::OUTSIDE_AFFINE_HULL ); - + // Check point location in 2-dimensional triangulations std::cout << " point locations 2-dim" << std::endl; @@ -601,35 +601,35 @@ _test_cls_triangulation_2( const Triangul & ) assert( T2_1.oriented_side(f,p12) == CGAL::ON_POSITIVE_SIDE ); f = T2_1.locate(p13,lt,li,f); assert( lt == Triangul::OUTSIDE_CONVEX_HULL ); assert( T2_1.orientation(p13, - f->vertex(f->ccw(li))->point(), - f->vertex(f->cw(li))->point()) - == CGAL::COUNTERCLOCKWISE); + f->vertex(f->ccw(li))->point(), + f->vertex(f->cw(li))->point()) + == CGAL::COUNTERCLOCKWISE); f = T2_1.locate(p14,lt,li); assert( lt == Triangul::OUTSIDE_CONVEX_HULL ); assert( T2_1.orientation(p14, - f->vertex(f->ccw(li))->point(), - f->vertex(f->cw(li))->point()) - == CGAL::COUNTERCLOCKWISE); + f->vertex(f->ccw(li))->point(), + f->vertex(f->cw(li))->point()) + == CGAL::COUNTERCLOCKWISE); f = T2_1.locate(p15,lt,li); assert( lt == Triangul::OUTSIDE_CONVEX_HULL ); assert( T2_1.orientation(p15, - f->vertex(f->ccw(li))->point(), - f->vertex(f->cw(li))->point()) - == CGAL::COUNTERCLOCKWISE); + f->vertex(f->ccw(li))->point(), + f->vertex(f->cw(li))->point()) + == CGAL::COUNTERCLOCKWISE); // test grid locate for (m=0; m<1; m++) for (p=0; p<1; p++) { - Point q= Point(m*px+p*qx, m*py+p*qy, 1); - f = T2_7.locate(q,lt,li); assert( lt == Triangul::VERTEX ); - assert( T2_7.xy_equal(f->vertex(li)->point(), q) ); + Point q= Point(m*px+p*qx, m*py+p*qy, 1); + f = T2_7.locate(q,lt,li); assert( lt == Triangul::VERTEX ); + assert( T2_7.xy_equal(f->vertex(li)->point(), q) ); } for (m=0; m<1; m++) for (p=0; p<1; p++) { - Point q= Point(2*m*px+(2*p+1)*qx, 2*m*py+(2*p+1)*qy, 2); - Point r= Point(m*px+p*qx, m*py+p*qy, 1); - Point s= Point(m*px+(p+1)*qx, m*py+(p+1)*qy, 1); - f = T2_7.locate(q,lt,li); assert( lt == Triangul::EDGE ); + Point q= Point(2*m*px+(2*p+1)*qx, 2*m*py+(2*p+1)*qy, 2); + Point r= Point(m*px+p*qx, m*py+p*qy, 1); + Point s= Point(m*px+(p+1)*qx, m*py+(p+1)*qy, 1); + f = T2_7.locate(q,lt,li); assert( lt == Triangul::EDGE ); assert( (T2_7.xy_equal(f->vertex(f->ccw(li))->point(), r) && T2_7.xy_equal(f->vertex(f->cw(li))->point(), s)) || (T2_7.xy_equal(f->vertex(f->ccw(li))->point(), s) @@ -639,9 +639,9 @@ _test_cls_triangulation_2( const Triangul & ) for (m=0; m<1; m++) for (p=0; p<1; p++) { - Point q= Point((50*m+1)*px+(50*p+1)*qx, (50*m+1)*py+(50*p+1)*qy, 50); - f = T2_7.locate(q,lt,li); assert( lt == Triangul::FACE ); - assert( T2_7.oriented_side(f,q) == CGAL::ON_POSITIVE_SIDE ); + Point q= Point((50*m+1)*px+(50*p+1)*qx, (50*m+1)*py+(50*p+1)*qy, 50); + f = T2_7.locate(q,lt,li); assert( lt == Triangul::FACE ); + assert( T2_7.oriented_side(f,q) == CGAL::ON_POSITIVE_SIDE ); } /*************************/ @@ -664,7 +664,7 @@ _test_cls_triangulation_2( const Triangul & ) Finite_faces_iterator fit = T2_7.finite_faces_begin(); assert(!T2_7.is_infinite(fit)); while(!T2_7.is_infinite(fit->neighbor(0)) ) ++fit; - + /***************************/ /******* Circulators *******/ @@ -681,7 +681,7 @@ _test_cls_triangulation_2( const Triangul & ) _test_circulators(T2_5); _test_circulators(T2_6); _test_circulators(T2_7); - + // Line_face_circulator std::cout << " line face circulator " << std::endl; _test_line_face_circulator(Triangul()); @@ -735,9 +735,9 @@ _test_cls_triangulation_2( const Triangul & ) assert(fc==fc2); //fc.print(); n=0; - do { - //fc2.print(); - fc2++ ; + do { + //fc2.print(); + fc2++ ; n = n+1;} while (fc2 != fc); assert(n==3); @@ -770,75 +770,75 @@ _test_cls_triangulation_2( const Triangul & ) /******** I/O *******/ std::cout << " output to a file" << std::endl; std::ofstream of0_0("T00.triangulation", std::ios::out); - CGAL::set_ascii_mode(of0_0); + CGAL::set_ascii_mode(of0_0); of0_0 << T0_0; of0_0.close(); std::ofstream of0_1("T01.triangulation"); - CGAL::set_ascii_mode(of0_1); + CGAL::set_ascii_mode(of0_1); of0_1 << T0_1; of0_1.close(); std::ofstream of1_2("T12.triangulation"); - CGAL::set_ascii_mode(of1_2); + CGAL::set_ascii_mode(of1_2); of1_2 << T1_2; of1_2.close(); std::ofstream of1_5("T15.triangulation"); - CGAL::set_ascii_mode(of1_5); + CGAL::set_ascii_mode(of1_5); of1_5 << T1_5; of1_5.close(); std::ofstream of1_6("T16.triangulation"); - CGAL::set_ascii_mode(of1_6); + CGAL::set_ascii_mode(of1_6); of1_6 << T1_6; of1_6.close(); std::ofstream of2_1("T21.triangulation"); - CGAL::set_ascii_mode(of2_1); + CGAL::set_ascii_mode(of2_1); of2_1 << T2_1; of2_1.close(); std::ofstream of2_3("T23.triangulation"); - CGAL::set_ascii_mode(of2_3); + CGAL::set_ascii_mode(of2_3); of2_3 << T2_3; of2_3.close(); std::ofstream of2_5("T25.triangulation"); - CGAL::set_ascii_mode(of2_5); + CGAL::set_ascii_mode(of2_5); of2_5 << T2_5; of2_5.close(); std::ofstream of2_6("T26.triangulation"); - CGAL::set_ascii_mode(of2_6); + CGAL::set_ascii_mode(of2_6); of2_6 << T2_6; of2_6.close(); std::cout << " input from a file" << std::endl; std::ifstream if0_0("T00.triangulation"); CGAL::set_ascii_mode(if0_0); Triangul T0_0_copy; if0_0 >> T0_0_copy; assert( T0_0_copy.is_valid() && - T0_0_copy.number_of_vertices() == T0_0.number_of_vertices() ); + T0_0_copy.number_of_vertices() == T0_0.number_of_vertices() ); std::ifstream if0_1("T01.triangulation"); CGAL::set_ascii_mode(if0_1); Triangul T0_1_copy; if0_1 >> T0_1_copy; assert( T0_1_copy.is_valid() && - T0_1_copy.number_of_vertices() == T0_1.number_of_vertices() ); - std::ifstream if1_2("T12.triangulation"); CGAL::set_ascii_mode(if1_2); + T0_1_copy.number_of_vertices() == T0_1.number_of_vertices() ); + std::ifstream if1_2("T12.triangulation"); CGAL::set_ascii_mode(if1_2); Triangul T1_2_copy; if1_2 >> T1_2_copy; assert( T1_2_copy.is_valid() && - T1_2_copy.number_of_vertices() == T1_2.number_of_vertices() ); - std::ifstream if1_5("T15.triangulation"); CGAL::set_ascii_mode(if1_5); + T1_2_copy.number_of_vertices() == T1_2.number_of_vertices() ); + std::ifstream if1_5("T15.triangulation"); CGAL::set_ascii_mode(if1_5); Triangul T1_5_copy; if1_5 >> T1_5_copy; assert( T1_5_copy.is_valid() && - T1_5_copy.number_of_vertices() == T1_5.number_of_vertices() ); + T1_5_copy.number_of_vertices() == T1_5.number_of_vertices() ); std::ifstream if1_6("T16.triangulation"); CGAL::set_ascii_mode(if1_6); Triangul T1_6_copy; if1_6 >> T1_6_copy; assert( T1_6_copy.is_valid() && - T1_6_copy.number_of_vertices() == T1_6.number_of_vertices() ); + T1_6_copy.number_of_vertices() == T1_6.number_of_vertices() ); std::ifstream if2_1("T21.triangulation"); CGAL::set_ascii_mode(if2_1); Triangul T2_1_copy; if2_1 >> T2_1_copy; assert( T2_1_copy.is_valid() && - T2_1_copy.number_of_vertices() == T2_1.number_of_vertices() ); + T2_1_copy.number_of_vertices() == T2_1.number_of_vertices() ); std::ifstream if2_3("T23.triangulation"); CGAL::set_ascii_mode(if2_3); Triangul T2_3_copy; if2_3 >> T2_3_copy; assert( T2_3_copy.is_valid() && - T2_3_copy.number_of_vertices() == T2_3.number_of_vertices() ); - std::ifstream if2_5("T25.triangulation"); CGAL::set_ascii_mode(if2_5); + T2_3_copy.number_of_vertices() == T2_3.number_of_vertices() ); + std::ifstream if2_5("T25.triangulation"); CGAL::set_ascii_mode(if2_5); Triangul T2_5_copy; if2_5 >> T2_5_copy; assert( T2_5_copy.is_valid() && - T2_5_copy.number_of_vertices() == T2_5.number_of_vertices() ); + T2_5_copy.number_of_vertices() == T2_5.number_of_vertices() ); std::ifstream if2_6("T26.triangulation"); CGAL::set_ascii_mode(if2_6); Triangul T2_6_copy; if2_6 >> T2_6_copy; assert( T2_6_copy.is_valid() && - T2_6_copy.number_of_vertices() == T2_6.number_of_vertices() ); + T2_6_copy.number_of_vertices() == T2_6.number_of_vertices() ); + - /**********************/ - /***** REMOVALS *******/ + /***** REMOVALS *******/ std::cout << " removals" << std::endl; // test remove_first() @@ -882,13 +882,13 @@ _test_cls_triangulation_2( const Triangul & ) T2_3.remove(v2_3_0); assert(T2_3.is_valid()); T2_3.remove(v2_3_1); assert(T2_3.is_valid()); T2_3.remove(v2_3_9); assert(T2_3.is_valid()); - T2_3.remove(v2_3_8); assert(T2_3.is_valid()); - T2_3.remove(v2_3_5); assert(T2_3.is_valid()); + T2_3.remove(v2_3_8); assert(T2_3.is_valid()); + T2_3.remove(v2_3_5); assert(T2_3.is_valid()); T2_3.remove(v2_3_3); assert(T2_3.is_valid()); T2_3.remove(v2_3_4); assert(T2_3.is_valid()); T2_3.remove(v2_3_2); assert(T2_3.is_valid()); T2_3.remove(v2_3_6); assert(T2_3.is_valid()); - T2_3.remove(v2_3_7); assert(T2_3.is_valid()); + T2_3.remove(v2_3_7); assert(T2_3.is_valid()); T2_3.remove(v2_3_10); assert(T2_3.is_valid()); assert( T2_3.number_of_vertices() == 0 ); @@ -896,7 +896,7 @@ _test_cls_triangulation_2( const Triangul & ) for (i=T2_4.number_of_vertices(); i>0; i--) T2_4.remove(T2_4.finite_vertex()); assert( T2_4.number_of_vertices() == 0 ); - + T2_5.clear(); assert( T2_5.number_of_vertices() == 0 ); @@ -905,7 +905,7 @@ _test_cls_triangulation_2( const Triangul & ) T2_6.remove(T2_6.finite_vertex()); } assert( T2_6.number_of_vertices() == 0 ); - + for (i=T2_7.number_of_vertices(); i>0; i--) T2_7.remove(T2_7.finite_vertex()); assert( T2_7.number_of_vertices() == 0 ); diff --git a/Triangulation_2/test/Triangulation_2/include/CGAL/_test_traits.h b/Triangulation_2/test/Triangulation_2/include/CGAL/_test_traits.h index 4eaf0541a29..b472c7fc8d2 100644 --- a/Triangulation_2/test/Triangulation_2/include/CGAL/_test_traits.h +++ b/Triangulation_2/test/Triangulation_2/include/CGAL/_test_traits.h @@ -7,14 +7,14 @@ // intended for general use. // // ---------------------------------------------------------------------------- -// +// // release : // release_date : -// -// source : +// +// source : // file : include/CGAL/_test_types.h -// revision : -// revision_date : +// revision : +// revision_date : // author(s) : Herve Bronnimann (Herve.Bronnimann@sophia.inria.fr) // // coordinator : INRIA Sophia-Antipolis @@ -38,12 +38,12 @@ public: Triangulation_test_point() {} Triangulation_test_point(double x, double y) : _x(x), _y(y) {} Triangulation_test_point(double hx, double hy, double hw) : - _x(hx/hw), _y(hy/hw) + _x(hx/hw), _y(hy/hw) {} TESTFT test_x() const { return _x; } TESTFT test_y() const { return _y; } - bool compare(const Point &p) const + bool compare(const Point &p) const { return test_x()==p.test_x() && test_y()==p.test_y(); } bool uncompare(const Point &p) const { return !compare(p); } void test_set(TESTFT x, TESTFT y) { _x=x; _y=y; } @@ -61,7 +61,7 @@ class Triangulation_test_segment { : _p(p), _q(q) {} void test_set(const Point &p, const Point &q) { _p=p; _q=q; } - + }; class Triangulation_test_line { @@ -78,10 +78,10 @@ class Triangulation_test_line { Point second_point() const {return _q;} // Triangulation_test_direction direction() { -// return Triangulation_test_direction(_p,_q); +// return Triangulation_test_direction(_p,_q); // } // Triangulation_test_line opposite() { -// return Triangulation_test_line(_q, _p); +// return Triangulation_test_line(_q, _p); // } // void test_set(const Point &p, const Point &q) { _p=p; _q=q; } }; @@ -96,10 +96,10 @@ public: Triangulation_test_direction() {} Triangulation_test_direction(const Point &p, const Point &q) : _p(p), _q(q) {} - Triangulation_test_direction(const Line &l) + Triangulation_test_direction(const Line &l) : _p(l.first_point()), _q(l.second_point()) {} // Triangulation_test_direction perpendicular(const CGAL::Orientation &) const { -// return *this; +// return *this; // } // void test_set(const Point &p, const Point &q) { _p=p; _q=q; } }; @@ -143,7 +143,7 @@ public: typedef Triangulation_test_point Point; typedef bool result_type; - bool operator()( const Point& p, const Point& q) const + bool operator()( const Point& p, const Point& q) const { return (p.test_x() < q.test_x()); } @@ -166,7 +166,7 @@ public: typedef Triangulation_test_point Point; typedef CGAL::Comparison_result result_type; - CGAL::Comparison_result operator()( const Point& p, const Point& q) const + CGAL::Comparison_result operator()( const Point& p, const Point& q) const { if (p.test_x() < q.test_x()) return CGAL::SMALLER; else if (p.test_x() > q.test_x()) return CGAL::LARGER; @@ -180,7 +180,7 @@ public: typedef Triangulation_test_point Point; typedef CGAL::Comparison_result result_type; - CGAL::Comparison_result operator()( const Point& p, const Point& q) const + CGAL::Comparison_result operator()( const Point& p, const Point& q) const { if (p.test_y() < q.test_y()) return CGAL::SMALLER; else if (p.test_y() > q.test_y()) return CGAL::LARGER; @@ -195,11 +195,11 @@ public: typedef CGAL::Orientation result_type; CGAL::Orientation - operator()( const Point& p, const Point& q, const Point& r) const + operator()( const Point& p, const Point& q, const Point& r) const { typedef Point::TESTFT RT; - RT det = (q.test_x()-p.test_x()) * (r.test_y()-p.test_y()) - - (r.test_x()-p.test_x()) * (q.test_y()-p.test_y()); + RT det = (q.test_x()-p.test_x()) * (r.test_y()-p.test_y()) + - (r.test_x()-p.test_x()) * (q.test_y()-p.test_y()); if ( det < RT(0) ) return CGAL::CLOCKWISE; if ( RT(0) < det ) return CGAL::COUNTERCLOCKWISE; return CGAL::COLLINEAR; @@ -213,10 +213,10 @@ public: typedef Triangulation_test_point Point; typedef CGAL::Orientation result_type; - CGAL::Oriented_side operator() (const Point &p, - const Point &q, - const Point &r, - const Point &t) const + CGAL::Oriented_side operator() (const Point &p, + const Point &q, + const Point &r, + const Point &t) const { typedef Point::TESTFT RT; @@ -228,17 +228,17 @@ public: RT ry( r.test_y()); RT tx( t.test_x()); RT ty( t.test_y()); - + RT RT0(0); RT RT1(1); RT det = CGAL::determinant(px, py, px*px + py*py, RT1, - qx, qy, qx*qx + qy*qy, RT1, - rx, ry, rx*rx + ry*ry, RT1, - tx, ty, tx*tx + ty*ty, RT1); + qx, qy, qx*qx + qy*qy, RT1, + rx, ry, rx*rx + ry*ry, RT1, + tx, ty, tx*tx + ty*ty, RT1); return (det @@ -406,7 +406,7 @@ public: private: using Tr_Base::top_get_first; using Tr_Base::top_get_second; - + template std::ptrdiff_t insert_with_info(InputIterator first, InputIterator last) { diff --git a/Triangulation_3/include/CGAL/Delaunay_triangulation_cell_base_with_circumcenter_3.h b/Triangulation_3/include/CGAL/Delaunay_triangulation_cell_base_with_circumcenter_3.h index 7c4239af9b2..14fc74d8490 100644 --- a/Triangulation_3/include/CGAL/Delaunay_triangulation_cell_base_with_circumcenter_3.h +++ b/Triangulation_3/include/CGAL/Delaunay_triangulation_cell_base_with_circumcenter_3.h @@ -86,12 +86,12 @@ public: } Delaunay_triangulation_cell_base_with_circumcenter_3( - Vertex_handle v0, Vertex_handle v1, + Vertex_handle v0, Vertex_handle v1, Vertex_handle v2, Vertex_handle v3) : Cb(v0, v1, v2, v3), circumcenter_(nullptr) {} Delaunay_triangulation_cell_base_with_circumcenter_3( - Vertex_handle v0, Vertex_handle v1, + Vertex_handle v0, Vertex_handle v1, Vertex_handle v2, Vertex_handle v3, Cell_handle n0, Cell_handle n1, Cell_handle n2, Cell_handle n3) diff --git a/Triangulation_3/include/CGAL/Regular_triangulation_3.h b/Triangulation_3/include/CGAL/Regular_triangulation_3.h index dfa28cf61e6..bbb71277314 100644 --- a/Triangulation_3/include/CGAL/Regular_triangulation_3.h +++ b/Triangulation_3/include/CGAL/Regular_triangulation_3.h @@ -429,7 +429,7 @@ public: #ifndef CGAL_TRIANGULATION_3_DONT_INSERT_RANGE_OF_POINTS_WITH_INFO private: - + //top stands for tuple-or-pair template const Weighted_point& top_get_first(const std::pair& pair) const { return pair.first; } @@ -442,7 +442,7 @@ private: template const Info& top_get_second(const boost::tuple& tuple) const { return boost::get<1>(tuple); } - + // Functor to go from an index of a container of Weighted_point to // the corresponding Bare_point template diff --git a/Triangulation_3/include/CGAL/Triangulation_hierarchy_3.h b/Triangulation_3/include/CGAL/Triangulation_hierarchy_3.h index a395e1c13e9..dbfa04367b0 100644 --- a/Triangulation_3/include/CGAL/Triangulation_hierarchy_3.h +++ b/Triangulation_3/include/CGAL/Triangulation_hierarchy_3.h @@ -228,7 +228,7 @@ public: for (int level = 1; level <= vertex_level; ++level) { v = hints[level] = hierarchy[level]->insert (*p, hints[level]); - set_up_down(v, prev); + set_up_down(v, prev); prev = v; } } @@ -392,34 +392,34 @@ public: // some internal methods // GIVING NEW FACES template - Vertex_handle insert_and_give_new_cells(const Point &p, + Vertex_handle insert_and_give_new_cells(const Point &p, OutputItCells fit, Cell_handle start = Cell_handle() ); - + template Vertex_handle insert_and_give_new_cells(const Point& p, OutputItCells /* fit */, Vertex_handle hint) { - return insert_and_give_new_cells(p, hint == Vertex_handle() ? - this->infinite_cell() : hint->cell()); + return insert_and_give_new_cells(p, hint == Vertex_handle() ? + this->infinite_cell() : hint->cell()); } template Vertex_handle insert_and_give_new_cells(const Point& p, Locate_type lt, - Cell_handle c, int li, int lj, + Cell_handle c, int li, int lj, OutputItCells fit); template - void remove_and_give_new_cells(Vertex_handle v, + void remove_and_give_new_cells(Vertex_handle v, OutputItCells fit); template - Vertex_handle move_if_no_collision_and_give_new_cells(Vertex_handle v, + Vertex_handle move_if_no_collision_and_give_new_cells(Vertex_handle v, const Point &p, OutputItCells fit); - -public: + +public: //LOCATE @@ -451,7 +451,7 @@ protected: }; void locate(const Point& p, Locate_type& lt, int& li, int& lj, - locs pos[maxlevel], Cell_handle start = Cell_handle ()) const; + locs pos[maxlevel], Cell_handle start = Cell_handle ()) const; int random_level(); }; @@ -489,12 +489,12 @@ Triangulation_hierarchy_3(const Triangulation_hierarchy_3 &tr) for(int j=1; jfinite_vertices_begin(), - end = hierarchy[j]->finite_vertices_end(); it != end; ++it) { - // current it->down() pointer goes in original instead in copied triangulation - set_up_down(it, V[it->down()]); - // make map for next level - if (it->up() != Vertex_handle()) - V[ it->up()->down() ] = it; + end = hierarchy[j]->finite_vertices_end(); it != end; ++it) { + // current it->down() pointer goes in original instead in copied triangulation + set_up_down(it, V[it->down()]); + // make map for next level + if (it->up() != Vertex_handle()) + V[ it->up()->down() ] = it; } } } @@ -517,7 +517,7 @@ is_valid(bool verbose, int level) const // verify correctness of triangulation at all levels for(int i=0; iis_valid(verbose, level); + result = result && hierarchy[i]->is_valid(verbose, level); // verify that lower level has no down pointers for( Finite_vertices_iterator it = hierarchy[0]->finite_vertices_begin(), @@ -527,15 +527,15 @@ is_valid(bool verbose, int level) const // verify that other levels has down pointer and reciprocal link is fine for(int j=1; jfinite_vertices_begin(), - end = hierarchy[j]->finite_vertices_end(); it != end; ++it) + end = hierarchy[j]->finite_vertices_end(); it != end; ++it) result = result && &*(it) == &*(it->down()->up()); // verify that other levels has down pointer and reciprocal link is fine for(int k=0; kfinite_vertices_begin(), - end = hierarchy[k]->finite_vertices_end(); it != end; ++it) + end = hierarchy[k]->finite_vertices_end(); it != end; ++it) result = result && ( it->up() == Vertex_handle() || - &*it == &*(it->up())->down() ); + &*it == &*(it->up())->down() ); return result; } @@ -553,10 +553,10 @@ insert(const Point &p, Cell_handle start) locate(p, lt, i, j, positions, start); // insert at level 0 Vertex_handle vertex = hierarchy[0]->insert(p, - positions[0].lt, - positions[0].pos, - positions[0].li, - positions[0].lj); + positions[0].lt, + positions[0].pos, + positions[0].li, + positions[0].lj); Vertex_handle previous = vertex; Vertex_handle first = vertex; @@ -566,10 +566,10 @@ insert(const Point &p, Cell_handle start) vertex = hierarchy[level]->insert(p); else vertex = hierarchy[level]->insert(p, - positions[level].lt, - positions[level].pos, - positions[level].li, - positions[level].lj); + positions[level].lt, + positions[level].pos, + positions[level].li, + positions[level].lj); set_up_down(vertex, previous); previous=vertex; level++; @@ -636,13 +636,13 @@ insert(const Point &p, Locate_type lt, Cell_handle loc, int li, int lj) int level = 1; while (level <= vertex_level ){ if (positions[level].pos == Cell_handle()) - vertex = hierarchy[level]->insert(p); + vertex = hierarchy[level]->insert(p); else - vertex = hierarchy[level]->insert(p, - positions[level].lt, - positions[level].pos, - positions[level].li, - positions[level].lj); + vertex = hierarchy[level]->insert(p, + positions[level].lt, + positions[level].pos, + positions[level].li, + positions[level].lj); set_up_down(vertex, previous); previous=vertex; level++; @@ -655,12 +655,12 @@ template template typename Triangulation_hierarchy_3::Vertex_handle Triangulation_hierarchy_3:: -insert_and_give_new_cells(const Point &p, Locate_type lt, Cell_handle loc, +insert_and_give_new_cells(const Point &p, Locate_type lt, Cell_handle loc, int li, int lj, OutputItCells fit) { int vertex_level = random_level(); // insert at level 0 - Vertex_handle vertex = + Vertex_handle vertex = hierarchy[0]->insert_and_give_new_cells(p,lt,loc,li,lj,fit); Vertex_handle previous = vertex; Vertex_handle first = vertex; @@ -675,9 +675,9 @@ insert_and_give_new_cells(const Point &p, Locate_type lt, Cell_handle loc, int level = 1; while (level <= vertex_level ){ if (positions[level].pos == Cell_handle()) - vertex = hierarchy[level]->insert(p); + vertex = hierarchy[level]->insert(p); else - vertex = hierarchy[level]->insert(p, + vertex = hierarchy[level]->insert(p, positions[level].lt, positions[level].pos, positions[level].li, @@ -700,7 +700,7 @@ remove(Vertex_handle v) Vertex_handle u = v->up(); hierarchy[l]->remove(v); if (u == Vertex_handle()) - break; + break; v = u; } } @@ -718,7 +718,7 @@ remove_and_give_new_cells(Vertex_handle v, OutputItCells fit) if(l) hierarchy[l]->remove(v); else hierarchy[l]->remove_and_give_new_cells(v, fit); if (u == Vertex_handle()) - break; + break; v = u; } } @@ -728,7 +728,7 @@ typename Triangulation_hierarchy_3::Vertex_handle Triangulation_hierarchy_3:: move_if_no_collision(Vertex_handle v, const Point & p) { - CGAL_triangulation_precondition(!this->is_infinite(v)); + CGAL_triangulation_precondition(!this->is_infinite(v)); if(v->point() == p) return v; Vertex_handle ans; for (int l = 0; l < maxlevel; ++l) { @@ -765,13 +765,13 @@ Triangulation_hierarchy_3:: move_if_no_collision_and_give_new_cells( Vertex_handle v, const Point & p, OutputItCells fit) { - CGAL_triangulation_precondition(!is_infinite(v)); + CGAL_triangulation_precondition(!is_infinite(v)); if(v->point() == p) return v; Vertex_handle ans; for (int l = 0; l < maxlevel; ++l) { Vertex_handle u = v->up(); if(l) hierarchy[l]->move_if_no_collision(v, p); - else ans = + else ans = hierarchy[l]->move_if_no_collision_and_give_new_cells(v, p, fit); if(ans != v) return ans; if (u == Vertex_handle()) @@ -818,7 +818,7 @@ locate(const Point& p, Locate_type& lt, int& li, int& lj, // find the highest level with enough vertices while (hierarchy[--level]->number_of_vertices() < (size_type) minsize) { if ( ! level) - break; // do not go below 0 + break; // do not go below 0 } for (int i=level+1; ilocate(p, - pos[level].lt, - pos[level].li, - pos[level].lj, - position); + pos[level].lt, + pos[level].li, + pos[level].lj, + position); // find the nearest vertex. Vertex_handle nearest = hierarchy[level]->nearest_vertex_in_cell(p, position); diff --git a/Triangulation_3/test/Triangulation_3/include/CGAL/_test_cls_delaunay_3.h b/Triangulation_3/test/Triangulation_3/include/CGAL/_test_cls_delaunay_3.h index a6b5ded18a7..f7d4579828c 100644 --- a/Triangulation_3/test/Triangulation_3/include/CGAL/_test_cls_delaunay_3.h +++ b/Triangulation_3/test/Triangulation_3/include/CGAL/_test_cls_delaunay_3.h @@ -6,7 +6,7 @@ // $URL$ // $Id$ // SPDX-License-Identifier: GPL-3.0-or-later OR LicenseRef-Commercial -// +// // // Author(s) : Francois Rebufat, Monique Teillaud, Sylvain Pion // Mariette Yvinec @@ -38,12 +38,12 @@ template < typename T, typename Weighted_tag = typename T::Weighted_tag > struct Test_location_policy { - typedef typename T::Location_policy Location_policy; + typedef typename T::Location_policy Location_policy; }; template < typename T > struct Test_location_policy { - struct Location_policy{}; + struct Location_policy{}; }; template < typename T, typename P > @@ -156,8 +156,8 @@ void test_conflicts(T& T3_13, const P *q) T3_13.insert_in_hole(q[i], C.begin(), C.end(), F.begin()->first, F.begin()->second); else { - // alternately test the overload which takes a Vertex_handle. - Vertex_handle v = T3_13.tds().create_vertex(); + // alternately test the overload which takes a Vertex_handle. + Vertex_handle v = T3_13.tds().create_vertex(); T3_13.insert_in_hole(q[i], C.begin(), C.end(), F.begin()->first, F.begin()->second, v); } @@ -203,7 +203,7 @@ _test_cls_delaunay_3(const Triangulation &) typedef typename Cls::size_type size_type; typedef typename Cls::Vertex_handle Vertex_handle; - typedef typename Cls::Cell_handle Cell_handle; + typedef typename Cls::Cell_handle Cell_handle; typedef typename Cls::Vertex_iterator Vertex_iterator; typedef typename Cls::Cell_iterator Cell_iterator; typedef typename Cls::Locate_type Locate_type; @@ -243,22 +243,22 @@ _test_cls_delaunay_3(const Triangulation &) l3.push_back(ppp[i]); // Points for T2_0 : - Point p1=Point(5,5,0); + Point p1=Point(5,5,0); Point p2=Point(4,4,0); Point p3=Point(6,6,0); // 1- dimensional until this point Point p4=Point(5,3,0); // 2-dimensional - Point p5=Point(5,7,0); - Point p6=Point(5,4,0); - Point p7=Point(5,6,0); - Point p8=Point(0,0,0); - Point p9=Point(5,5,0); + Point p5=Point(5,7,0); + Point p6=Point(5,4,0); + Point p7=Point(5,6,0); + Point p8=Point(0,0,0); + Point p9=Point(5,5,0); // Points for T3_1 : - Point q[22] = + Point q[22] = { Point(0,0,0), Point(4,4,0), Point(0,4,0), Point(4,0,0), Point(1,3,1), Point(3,1,1), Point(3,3,1), Point(1,1,1), Point(2,2,2), - Point(1,3,3), Point(3,1,3), Point(3,3,3), Point(1,1,3), + Point(1,3,3), Point(3,1,3), Point(3,3,3), Point(1,1,3), Point(0,0,4), Point(4,4,4), Point(0,4,4), Point(4,0,4), Point(1,3,5), Point(3,1,5), Point(3,3,5), Point(1,1,5), Point(2,2,6)}; @@ -269,14 +269,14 @@ _test_cls_delaunay_3(const Triangulation &) // for (a=0;a!=10;a++) // for (b=0;b!=10;b++) // for (d=0;d!=10;d++) -// lp.push_back(Point(a*b-d*a + (a-b)*10 +a ,a-b+d +5*b, -// a*a-d*d+b)); +// lp.push_back(Point(a*b-d*a + (a-b)*10 +a ,a-b+d +5*b, +// a*a-d*d+b)); for (a=0;a!=10;a++) for (b=0;b!=10;b++) for (d=0;d!=5;d++) - lp.push_back(Point(a*b-d*a + (a-b)*10 +a ,a-b+d +5*b, - a*a-d*d+b)); + lp.push_back(Point(a*b-d*a + (a-b)*10 +a ,a-b+d +5*b, + a*a-d*d+b)); // Points for T3_2 : @@ -284,8 +284,8 @@ _test_cls_delaunay_3(const Triangulation &) for (a=0;a!=4;a++) for (b=0;b!=4;b++) for (d=0;d!=4;d++) - lp2.push_back(Point((a*b-d*a)*10 +a ,(a-b+d +5*b)*100, - a*a-d*d-b)); + lp2.push_back(Point((a*b-d*a)*10 +a ,(a-b+d +5*b)*100, + a*a-d*d-b)); //######################################################################## @@ -296,7 +296,7 @@ _test_cls_delaunay_3(const Triangulation &) std::cout << " Constructor " << std::endl; // Beginning with an empty triangulation and adding point until reaching // 3-dimentional triangulation. - Cls T0; + Cls T0; assert(T0.dimension() == -1); assert(T0.number_of_vertices() == 0); assert(T0.is_valid()); @@ -326,7 +326,7 @@ _test_cls_delaunay_3(const Triangulation &) Cls Tfromfile; std::cout << " I/O" << std::endl; { - std::ofstream oFileT2("Test2_triangulation_IO_3",std::ios::out); + std::ofstream oFileT2("Test2_triangulation_IO_3",std::ios::out); oFileT2 << T0 << std::endl; } std::ifstream iFileT2("Test2_triangulation_IO_3",std::ios::in); @@ -409,13 +409,13 @@ _test_cls_delaunay_3(const Triangulation &) assert(T0.dimension() == 3); assert(T0.number_of_vertices() == 4); assert(T0.is_valid()); - + // copy constructor Cls T1(T0); assert(T1.dimension() == 3); assert(T1.number_of_vertices() == 4); assert(T1.is_valid()); - + T1.clear(); assert(T1.dimension() == -1); assert(T1.number_of_vertices() == 0); @@ -424,7 +424,7 @@ _test_cls_delaunay_3(const Triangulation &) // Affectation : - T1=T0; + T1=T0; assert(T1.dimension() == 3); assert(T1.number_of_vertices() == 4); assert(T1.is_valid()); @@ -439,7 +439,7 @@ _test_cls_delaunay_3(const Triangulation &) assert(T0.number_of_vertices() == 0); assert(T0.is_valid()); T0.swap(T1); - + assert(T0.dimension() == 3); assert(T0.number_of_vertices() == 4); assert(T0.is_valid()); @@ -484,7 +484,7 @@ _test_cls_delaunay_3(const Triangulation &) } std::cout << " Constructor9 " << std::endl; - // 2-dimensional triangulations + // 2-dimensional triangulations Cls T2_0; v0=T2_0.insert(p1); @@ -538,8 +538,8 @@ _test_cls_delaunay_3(const Triangulation &) for (m=0; m<20; m++) for (n=0; n<20; n++) { - qq[m+20*n] = Point(m*px+(int)n*qx, m*py+(int)n*qy, 1); - T2_1.insert( qq[m+20*n] ); + qq[m+20*n] = Point(m*px+(int)n*qx, m*py+(int)n*qy, 1); + T2_1.insert( qq[m+20*n] ); } assert( T2_1.number_of_vertices() == m*n ); assert( T2_1.dimension()==2 ); @@ -553,30 +553,30 @@ _test_cls_delaunay_3(const Triangulation &) Point r[225]; for (z=0 ; z<5 ; z++) for (y=0 ; y<5 ; y++) - for (x=0 ; x<5 ; x++) - { - r[x+5*y+25*z] = Point(x,y,z); - v0=T3_0.insert(r[x+5*y+25*z]); - } + for (x=0 ; x<5 ; x++) + { + r[x+5*y+25*z] = Point(x,y,z); + v0=T3_0.insert(r[x+5*y+25*z]); + } assert(T3_0.is_valid()); assert(T3_0.number_of_vertices()==125); assert(T3_0.dimension()==3); if (del) { std::cout << " deletion in Delaunay - grid case - (dim 3) " << - std::endl; + std::endl; Cls Tdel( T3_0 ); - + std::vector vertices; for (Finite_vertices_iterator vi = Tdel.finite_vertices_begin(); - vi != Tdel.finite_vertices_end(); ++vi) + vi != Tdel.finite_vertices_end(); ++vi) vertices.push_back(vi); size_type n = Tdel.number_of_vertices(); size_type m = Tdel.remove(vertices.begin(), vertices.end()); assert(m == n - Tdel.number_of_vertices()); assert(Tdel.is_valid(false)); - std::cout << " successfull" << std::endl; + std::cout << " successfull" << std::endl; } @@ -650,33 +650,33 @@ _test_cls_delaunay_3(const Triangulation &) Cell_handle c2 = T3_13.infinite_vertex()->cell(); for (int x = -1; x < 7; ++x) for (int y = -1; y < 7; ++y) - for (int z = -1; z < 7; ++z) { - Point p(x, y, z); - Vertex_handle v = nearest_vertex(T3_13, p); - for (typename Cls::Finite_vertices_iterator - fvit = T3_13.finite_vertices_begin(); - fvit != T3_13.finite_vertices_end(); ++fvit){ - - assert(CGAL::squared_distance(p, + for (int z = -1; z < 7; ++z) { + Point p(x, y, z); + Vertex_handle v = nearest_vertex(T3_13, p); + for (typename Cls::Finite_vertices_iterator + fvit = T3_13.finite_vertices_begin(); + fvit != T3_13.finite_vertices_end(); ++fvit){ + + assert(CGAL::squared_distance(p, v->point()) <= CGAL::squared_distance(p, fvit->point())); } Vertex_handle v1 = nearest_vertex_in_cell(T3_13, p, c1) ; - int i1 = c1->index(v1); - for(int i=0; i<4; ++i) { - if (i != i1) - assert(CGAL::squared_distance(p, v1->point()) <= + int i1 = c1->index(v1); + for(int i=0; i<4; ++i) { + if (i != i1) + assert(CGAL::squared_distance(p, v1->point()) <= CGAL::squared_distance(p, c1->vertex(i)->point())); - } - Vertex_handle v2 = nearest_vertex_in_cell(T3_13, p, c2); - int i2 = c2->index(v2); - for(int i=0; i<4; ++i) { - if (i != i2 && c2->vertex(i) != T3_13.infinite_vertex()) - assert(CGAL::squared_distance(p, v2->point()) <= + } + Vertex_handle v2 = nearest_vertex_in_cell(T3_13, p, c2); + int i2 = c2->index(v2); + for(int i=0; i<4; ++i) { + if (i != i2 && c2->vertex(i) != T3_13.infinite_vertex()) + assert(CGAL::squared_distance(p, v2->point()) <= CGAL::squared_distance(p, c2->vertex(i)->point())); - } - } + } + } } { @@ -737,19 +737,19 @@ _test_cls_delaunay_3(const Triangulation &) else if (count < 100) std::cout << count << '\b' << '\b' ; - else + else if (count < 1000) std::cout << count << '\b' << '\b' << '\b' ; else - std::cout << count << std::endl; + std::cout << count << std::endl; std::cout.flush(); } std::cout << std::endl; assert(T3_2.is_valid()); assert(T3_2.dimension()==3); assert(T3_2.number_of_vertices()==500); - - + + Point p110(-5,5,0), p111(-2,-5,2), p112(-2,-9,6), p113(4,8,9), p114(5,-6,0), p115(3,0,5), p116(-9,0,-10), p117(1,6,-2), p118(-3,2,-4), p119(3,-3,-1); @@ -774,16 +774,16 @@ _test_cls_delaunay_3(const Triangulation &) Vertex_handle v; while ( T3_5.number_of_vertices() >= 1 ) { if ( T3_5.dimension() == 3 ) - v = T3_5.infinite_cell()->vertex - ( (T3_5.infinite_cell()->index( T3_5.infinite_vertex() ) +1 )&3 ); + v = T3_5.infinite_cell()->vertex + ( (T3_5.infinite_cell()->index( T3_5.infinite_vertex() ) +1 )&3 ); else if ( T3_5.dimension() == 2 ) - v = T3_5.infinite_cell()->vertex - ( (T3_5.infinite_cell()->index( T3_5.infinite_vertex() ) +1 )%3 ); + v = T3_5.infinite_cell()->vertex + ( (T3_5.infinite_cell()->index( T3_5.infinite_vertex() ) +1 )%3 ); else if ( T3_5.dimension() == 1 ) - v = T3_5.infinite_cell()->vertex - ( (T3_5.infinite_cell()->index( T3_5.infinite_vertex() ) +1 )%2 ); - else - v = T3_5.infinite_cell()->neighbor(0)->vertex(0); + v = T3_5.infinite_cell()->vertex + ( (T3_5.infinite_cell()->index( T3_5.infinite_vertex() ) +1 )%2 ); + else + v = T3_5.infinite_cell()->neighbor(0)->vertex(0); T3_5.remove( v ); } @@ -809,18 +809,18 @@ _test_cls_delaunay_3(const Triangulation &) // bool success(true); // if (del) { // std::cout << " deletion in a Delaunay of " -// << T3_4.number_of_vertices() << " random points"; +// << T3_4.number_of_vertices() << " random points"; // Vertex_handle v; // while ( T3_4.number_of_vertices() >= 1 ) { // if ( T3_4.dimension() > 1 ) -// v = T3_4.infinite_cell()->vertex -// ( (T3_4.infinite_cell()->index( T3_4.infinite_vertex() ) +1 )&3 ); +// v = T3_4.infinite_cell()->vertex +// ( (T3_4.infinite_cell()->index( T3_4.infinite_vertex() ) +1 )&3 ); // else -// if ( T3_4.dimension() == 1 ) -// v = T3_4.infinite_cell()->vertex -// ( (T3_4.infinite_cell()->index( T3_4.infinite_vertex() ) +1 )%2 ); -// else -// v = T3_4.infinite_cell()->neighbor(0)->vertex(0); +// if ( T3_4.dimension() == 1 ) +// v = T3_4.infinite_cell()->vertex +// ( (T3_4.infinite_cell()->index( T3_4.infinite_vertex() ) +1 )%2 ); +// else +// v = T3_4.infinite_cell()->neighbor(0)->vertex(0); // success = T3_4.remove( v ); // } @@ -847,10 +847,10 @@ _test_cls_delaunay_3(const Triangulation &) _test_vertex_iterator(T3_1); _test_triangulation_iterator(T3_1); _test_vertex_iterator(T3_0); - _test_triangulation_iterator(T3_0); - _test_vertex_iterator(T3_2); - _test_triangulation_iterator(T3_2); - + _test_triangulation_iterator(T3_0); + _test_vertex_iterator(T3_2); + _test_triangulation_iterator(T3_2); + std::cout << " Testing Circulator "<< std::endl; _test_circulator(T0); @@ -886,7 +886,7 @@ _test_cls_delaunay_3(const Triangulation &) assert(T4.is_Gabriel(e)); assert(T4.is_edge(v2,v3,c,i,j)); assert(T4.is_Gabriel(c,i,j)); - + std::cout <<" Test dual (minimal test for now)" << std::endl; // We only test return types and instantiation, basically. @@ -915,32 +915,32 @@ _test_cls_delaunay_3(const Triangulation &) Cls Ta (q, q+22), Tb(q, q+22); assert(Ta == Tb); for (Finite_vertices_iterator ita = Ta.finite_vertices_begin(), - itb = Tb.finite_vertices_begin(), - end = Ta.finite_vertices_end(); - ita != end; ++ita, ++itb) + itb = Tb.finite_vertices_begin(), + end = Ta.finite_vertices_end(); + ita != end; ++ita, ++itb) assert(ita->point() == itb->point()); for (Finite_cells_iterator ita = Ta.finite_cells_begin(), - itb = Tb.finite_cells_begin(), - end = Ta.finite_cells_end(); - ita != end; ++ita, ++itb) { + itb = Tb.finite_cells_begin(), + end = Ta.finite_cells_end(); + ita != end; ++ita, ++itb) { assert(ita->vertex(0)->point() == itb->vertex(0)->point()); assert(ita->vertex(1)->point() == itb->vertex(1)->point()); assert(ita->vertex(2)->point() == itb->vertex(2)->point()); assert(ita->vertex(3)->point() == itb->vertex(3)->point()); } } - + /**********************/ /******* MOVE *********/ std::cout << " displacements" << std::endl; std::cout << " degenerate cases: " << std::endl; - + Cls TM_0; Vertex_handle tmv1 = TM_0.insert(Point(0,0,0)); Vertex_handle tmv2 = TM_0.insert(Point(0,1,0)); - TM_0.move_if_no_collision(tmv1, Point(0, 2, 1)); + TM_0.move_if_no_collision(tmv1, Point(0, 2, 1)); assert(TM_0.tds().is_valid()); assert(TM_0.is_valid()); assert(TM_0.dimension() == 1); @@ -1056,7 +1056,7 @@ _test_cls_delaunay_3(const Triangulation &) TM_0.move_if_no_collision(tmv4, Point(0, 1, 2)); assert(TM_0.tds().is_valid()); assert(TM_0.is_valid()); - assert(TM_0.dimension() == 1); + assert(TM_0.dimension() == 1); TM_0.move_if_no_collision(tmv4, Point(0, 3, 0)); assert(TM_0.tds().is_valid()); @@ -1133,7 +1133,7 @@ _test_cls_delaunay_3(const Triangulation &) TM_1.insert(points.begin(), points.end()); Vertex_handle vTM_1; for(int i=0; i<2; i++) { - for(typename Cls::Finite_vertices_iterator + for(typename Cls::Finite_vertices_iterator fvi = TM_1.finite_vertices_begin(); fvi != TM_1.finite_vertices_end(); fvi++) { Point p = Point(0, 0, rand()%30000); @@ -1151,9 +1151,9 @@ _test_cls_delaunay_3(const Triangulation &) points.push_back(Point(0, rand()%30000, rand()%30000)); } TM_2.insert(points.begin(), points.end()); - Vertex_handle vTM_2; + Vertex_handle vTM_2; for(int i=0; i<2; i++) { - for(typename Cls::Finite_vertices_iterator + for(typename Cls::Finite_vertices_iterator fvi = TM_2.finite_vertices_begin(); fvi != TM_2.finite_vertices_end(); fvi++) { Point p = Point(0, rand()%30000, rand()%30000); @@ -1164,7 +1164,7 @@ _test_cls_delaunay_3(const Triangulation &) assert(TM_2.is_valid()); std::cout << " random 3D: " << std::endl; - Cls TM_3; + Cls TM_3; // non-degenerate cases points.clear(); TM_3.clear(); for(int count=0; count<50; count++) { @@ -1173,10 +1173,10 @@ _test_cls_delaunay_3(const Triangulation &) TM_3.insert(points.begin(), points.end()); assert(TM_3.is_valid()); - + Vertex_handle vTM_3; for(int i=0; i<2; i++) { - for(typename Cls::Finite_vertices_iterator + for(typename Cls::Finite_vertices_iterator fvi = TM_3.finite_vertices_begin(); fvi != TM_3.finite_vertices_end(); fvi++) { Point p = Point(rand()%30000, rand()%30000, rand()%30000); @@ -1191,7 +1191,7 @@ _test_cls_delaunay_3(const Triangulation &) // Test remove cluster { - _test_remove_cluster(); + _test_remove_cluster(); } } diff --git a/Triangulation_3/test/Triangulation_3/include/CGAL/_test_cls_regular_3.h b/Triangulation_3/test/Triangulation_3/include/CGAL/_test_cls_regular_3.h index 6c5793d0de2..fba2db023fd 100644 --- a/Triangulation_3/test/Triangulation_3/include/CGAL/_test_cls_regular_3.h +++ b/Triangulation_3/test/Triangulation_3/include/CGAL/_test_cls_regular_3.h @@ -6,7 +6,7 @@ // $URL$ // $Id$ // SPDX-License-Identifier: GPL-3.0-or-later OR LicenseRef-Commercial -// +// // // Author(s) : Monique Teillaud (Monique.Teillaud@sophia.inria.fr) @@ -48,7 +48,7 @@ _test_cls_regular_3(const Triangulation &) Cls T1; std::cout << " number of inserted points : " ; for ( m=0; m<5; m++) { - if ( (m%2)== 0 ) + if ( (m%2)== 0 ) T1.insert( Weighted_point( Bare_point( 2*m,0,0 ), 2 ) ); else T1.insert( Weighted_point( Bare_point( -2*m+1,0,0 ), 2 ) ); count++; @@ -56,18 +56,18 @@ _test_cls_regular_3(const Triangulation &) std::cout << count << '\b' ; else if (count < 100) - std::cout << count << '\b' << '\b' ; + std::cout << count << '\b' << '\b' ; else - std::cout << count << '\b' << '\b' << '\b' ; + std::cout << count << '\b' << '\b' << '\b' ; std::cout.flush(); } assert( T1.is_valid() ); - std::cout << std::endl << " number of vertices : " - << T1.number_of_vertices() << std::endl; + std::cout << std::endl << " number of vertices : " + << T1.number_of_vertices() << std::endl; std::cout << " number of inserted points : " ; for ( m=0; m<5; m++) { - if ( (m%2)== 0 ) + if ( (m%2)== 0 ) T1.insert( Weighted_point( Bare_point( 2*m+1,0,0 ), 5 ) ); else T1.insert( Weighted_point( Bare_point( -2*m+1,0,0 ), 5 ) ); count++; @@ -75,18 +75,18 @@ _test_cls_regular_3(const Triangulation &) std::cout << count << '\b' ; else if (count < 100) - std::cout << count << '\b' << '\b' ; + std::cout << count << '\b' << '\b' ; else - std::cout << count << '\b' << '\b' << '\b' ; - std::cout.flush(); + std::cout << count << '\b' << '\b' << '\b' ; + std::cout.flush(); } assert( T1.is_valid() ); - std::cout << std::endl << " number of vertices : " - << T1.number_of_vertices() << std::endl; + std::cout << std::endl << " number of vertices : " + << T1.number_of_vertices() << std::endl; std::cout << " number of inserted points : " ; for ( m=0; m<10; m++) { - if ( (m%2)== 0 ) + if ( (m%2)== 0 ) T1.insert( Weighted_point( Bare_point( m,0,0 ), 1 ) ); else T1.insert( Weighted_point( Bare_point( -m,0,0 ), 1 ) ); count++; @@ -94,14 +94,14 @@ _test_cls_regular_3(const Triangulation &) std::cout << count << '\b' ; else if (count < 100) - std::cout << count << '\b' << '\b' ; + std::cout << count << '\b' << '\b' ; else - std::cout << count << '\b' << '\b' << '\b' ; - std::cout.flush(); + std::cout << count << '\b' << '\b' << '\b' ; + std::cout.flush(); } assert( T1.is_valid() ); - std::cout << std::endl << " number of vertices : " - << T1.number_of_vertices() << std::endl; + std::cout << std::endl << " number of vertices : " + << T1.number_of_vertices() << std::endl; assert( T1.dimension()==1 ); std::cout << " test dimension 2 " << std::endl; @@ -116,12 +116,12 @@ _test_cls_regular_3(const Triangulation &) T2.insert( Weighted_point( Bare_point(m*px+n*qx, m*py+n*qy, 0), 1 ) ); count++; if (count <10) - std::cout << count << '\b' ; + std::cout << count << '\b' ; else - if (count < 100) - std::cout << count << '\b' << '\b' ; - else - std::cout << count << '\b' << '\b' << '\b' ; + if (count < 100) + std::cout << count << '\b' << '\b' ; + else + std::cout << count << '\b' << '\b' << '\b' ; std::cout.flush(); } for (m=10; m<20; m++) @@ -129,12 +129,12 @@ _test_cls_regular_3(const Triangulation &) T2.insert( Weighted_point( Bare_point(m*px+n*qx, m*py+n*qy, 0), -1 ) ); count++; if (count <10) - std::cout << count << '\b' ; + std::cout << count << '\b' ; else - if (count < 100) - std::cout << count << '\b' << '\b' ; - else - std::cout << count << '\b' << '\b' << '\b' ; + if (count < 100) + std::cout << count << '\b' << '\b' ; + else + std::cout << count << '\b' << '\b' << '\b' ; std::cout.flush(); } for (m=0; m<10; m++) @@ -142,12 +142,12 @@ _test_cls_regular_3(const Triangulation &) T2.insert( Weighted_point( Bare_point(m*px+n*qx, m*py+n*qy, 0), -2 ) ); count++; if (count <10) - std::cout << count << '\b' ; + std::cout << count << '\b' ; else - if (count < 100) - std::cout << count << '\b' << '\b' ; - else - std::cout << count << '\b' << '\b' << '\b' ; + if (count < 100) + std::cout << count << '\b' << '\b' ; + else + std::cout << count << '\b' << '\b' << '\b' ; std::cout.flush(); } for (m=10; m<20; m++) @@ -155,17 +155,17 @@ _test_cls_regular_3(const Triangulation &) T2.insert( Weighted_point( Bare_point(m*px+n*qx, m*py+n*qy, 0), 5 ) ); count++; if (count <10) - std::cout << count << '\b' ; + std::cout << count << '\b' ; else - if (count < 100) - std::cout << count << '\b' << '\b' ; - else - std::cout << count << '\b' << '\b' << '\b' ; + if (count < 100) + std::cout << count << '\b' << '\b' ; + else + std::cout << count << '\b' << '\b' << '\b' ; std::cout.flush(); } - - std::cout << std::endl << " number of vertices : " - << T2.number_of_vertices() << std::endl; + + std::cout << std::endl << " number of vertices : " + << T2.number_of_vertices() << std::endl; assert( T2.dimension()==2 ); assert( T2.is_valid() ); @@ -178,10 +178,10 @@ _test_cls_regular_3(const Triangulation &) for (a=0;a!=10;a++) for (b=0;b!=10;b++) for (d=0;d!=10;d++) - lp.push_back(Weighted_point( Bare_point(a*b-d*a + (a-b)*10 +a , - a-b+d +5*b, - a*a-d*d+b), - a*b-a*d) ); + lp.push_back(Weighted_point( Bare_point(a*b-d*a + (a-b)*10 +a , + a-b+d +5*b, + a*a-d*d+b), + a*b-a*d) ); typename list_point::iterator it; count = 0 ; std::cout << " number of inserted points : " ; @@ -193,16 +193,16 @@ _test_cls_regular_3(const Triangulation &) else if (count < 100) std::cout << count << '\b' << '\b' ; - else + else if (count < 1000) std::cout << count << '\b' << '\b' << '\b' ; else - std::cout << count << std::endl; + std::cout << count << std::endl; std::cout.flush(); } - std::cout << " number of vertices : " - << T.number_of_vertices() << std::endl; + std::cout << " number of vertices : " + << T.number_of_vertices() << std::endl; assert(T.is_valid()); assert(T.dimension()==3); } diff --git a/Triangulation_3/test/Triangulation_3/include/CGAL/_test_cls_triangulation_3.h b/Triangulation_3/test/Triangulation_3/include/CGAL/_test_cls_triangulation_3.h index b73de19db78..ded18a9175f 100644 --- a/Triangulation_3/test/Triangulation_3/include/CGAL/_test_cls_triangulation_3.h +++ b/Triangulation_3/test/Triangulation_3/include/CGAL/_test_cls_triangulation_3.h @@ -6,7 +6,7 @@ // $URL$ // $Id$ // SPDX-License-Identifier: GPL-3.0-or-later OR LicenseRef-Commercial -// +// // // Author(s) : Francois Rebufat @@ -25,7 +25,7 @@ #include template -bool check_all_are_finite(Triangulation* tr, const Container& cont) +bool check_all_are_finite(Triangulation* tr, const Container& cont) { for(typename Container::const_iterator it = cont.begin(), end = cont.end(); it != end; ++it) @@ -38,7 +38,7 @@ bool check_all_are_finite(Triangulation* tr, const Container& cont) template void _test_cls_triangulation_3_input_output(const Triangulation & T, - const char* filename) + const char* filename) { const int dim = T.dimension(); const typename Triangulation::size_type n = T.number_of_vertices(); @@ -102,7 +102,7 @@ _test_cls_triangulation_3(const Triangulation &) typedef typename Cls::difference_type difference_type; typedef typename Cls::Vertex_handle Vertex_handle; - typedef typename Cls::Cell_handle Cell_handle; + typedef typename Cls::Cell_handle Cell_handle; typedef typename Cls::Vertex_iterator Vertex_iterator; typedef typename Cls::Cell_iterator Cell_iterator; // typedef typename Cls::Point_iterator Point_iterator; @@ -142,22 +142,22 @@ _test_cls_triangulation_3(const Triangulation &) l3.push_back(ppp[i]); // Points for T2_0 : - Point p1=Point(5,5,0); + Point p1=Point(5,5,0); Point p2=Point(4,4,0); Point p3=Point(6,6,0); // 1- dimensional until this point Point p4=Point(5,3,0); // 2-dimensional - Point p5=Point(5,7,0); - Point p6=Point(5,4,0); - Point p7=Point(5,6,0); - Point p8=Point(0,0,0); - Point p9=Point(5,5,0); + Point p5=Point(5,7,0); + Point p6=Point(5,4,0); + Point p7=Point(5,6,0); + Point p8=Point(0,0,0); + Point p9=Point(5,5,0); // Points for T3_1 : - Point q[22] = + Point q[22] = { Point(0,0,0), Point(4,4,0), Point(0,4,0), Point(4,0,0), Point(1,3,1), Point(3,1,1), Point(3,3,1), Point(1,1,1), Point(2,2,2), - Point(1,3,3), Point(3,1,3), Point(3,3,3), Point(1,1,3), + Point(1,3,3), Point(3,1,3), Point(3,3,3), Point(1,1,3), Point(0,0,4), Point(4,4,4), Point(0,4,4), Point(4,0,4), Point(1,3,5), Point(3,1,5), Point(3,3,5), Point(1,1,5), Point(2,2,6)}; @@ -168,14 +168,14 @@ _test_cls_triangulation_3(const Triangulation &) // for (a=0;a!=10;a++) // for (b=0;b!=10;b++) // for (d=0;d!=10;d++) -// lp.push_back(Point(a*b-d*a + (a-b)*10 +a ,a-b+d +5*b, -// a*a-d*d+b)); +// lp.push_back(Point(a*b-d*a + (a-b)*10 +a ,a-b+d +5*b, +// a*a-d*d+b)); for (a=0;a!=10;a++) for (b=0;b!=10;b++) for (d=0;d!=5;d++) - lp.push_back(Point(a*b-d*a + (a-b)*10 +a ,a-b+d +5*b, - a*a-d*d+b)); + lp.push_back(Point(a*b-d*a + (a-b)*10 +a ,a-b+d +5*b, + a*a-d*d+b)); // Points for T3_2 : @@ -183,8 +183,8 @@ _test_cls_triangulation_3(const Triangulation &) for (a=0;a!=4;a++) for (b=0;b!=4;b++) for (d=0;d!=4;d++) - lp2.push_back(Point((a*b-d*a)*10 +a ,(a-b+d +5*b)*100, - a*a-d*d-b)); + lp2.push_back(Point((a*b-d*a)*10 +a ,(a-b+d +5*b)*100, + a*a-d*d-b)); //######################################################################## @@ -195,13 +195,13 @@ _test_cls_triangulation_3(const Triangulation &) std::cout << " Constructor " << std::endl; // Beginning with an empty triangulation and adding points until reaching // 3-dimensional triangulation. - Cls T0; + Cls T0; assert(T0.dimension() == -1); assert(T0.number_of_vertices() == 0); assert(T0.is_valid()); if (! del) // to avoid doing the following tests for both Delaunay - // and non Delaunay triangulations + // and non Delaunay triangulations { _test_cls_triangulation_3_input_output(T0, "Test1_triangulation_IO_3"); } @@ -214,7 +214,7 @@ _test_cls_triangulation_3(const Triangulation &) assert(T0.is_valid()); if (! del) // to avoid doing the following tests for both Delaunay - // and non Delaunay triangulations + // and non Delaunay triangulations { _test_cls_triangulation_3_input_output(T0, "Test2_triangulation_IO_3"); } @@ -228,7 +228,7 @@ _test_cls_triangulation_3(const Triangulation &) assert(T0.is_valid()); if (! del) // to avoid doing the following tests for both Delaunay - // and non Delaunay triangulations + // and non Delaunay triangulations { _test_cls_triangulation_3_input_output(T0, "Test3_triangulation_IO_3"); } @@ -242,7 +242,7 @@ _test_cls_triangulation_3(const Triangulation &) assert(T0.is_valid()); if (! del) // to avoid doing the following tests for both Delaunay - // and non Delaunay triangulations + // and non Delaunay triangulations { _test_cls_triangulation_3_input_output(T0, "Test4_triangulation_IO_3"); } @@ -256,7 +256,7 @@ _test_cls_triangulation_3(const Triangulation &) assert(T0.is_valid()); if (! del) // to avoid doing the following tests for both Delaunay - // and non Delaunay triangulations + // and non Delaunay triangulations { _test_cls_triangulation_3_input_output(T0, "Test5_triangulation_IO_3"); } @@ -268,7 +268,7 @@ _test_cls_triangulation_3(const Triangulation &) assert(T0.dimension() == 3); assert(T0.number_of_vertices() == 4); assert(T0.is_valid()); - + // copy constructor Cls T1(T0); assert(T1.dimension() == 3); @@ -280,7 +280,7 @@ _test_cls_triangulation_3(const Triangulation &) assert(T0 == T1); assert(T1 == T0); assert(T1 == T1); - + T1.clear(); assert(T1.dimension() == -1); assert(T1.number_of_vertices() == 0); @@ -289,7 +289,7 @@ _test_cls_triangulation_3(const Triangulation &) // Assignment - T1=T0; + T1=T0; assert(T1.dimension() == 3); assert(T1.number_of_vertices() == 4); assert(T1.is_valid()); @@ -304,7 +304,7 @@ _test_cls_triangulation_3(const Triangulation &) assert(T0.number_of_vertices() == 0); assert(T0.is_valid()); T0.swap(T1); - + assert(T0.dimension() == 3); assert(T0.number_of_vertices() == 4); assert(T0.is_valid()); @@ -344,13 +344,13 @@ _test_cls_triangulation_3(const Triangulation &) assert(T1_2.is_valid()); if (! del) // to avoid doing the following tests for both Delaunay - // and non Delaunay triangulations + // and non Delaunay triangulations { _test_cls_triangulation_3_input_output(T1_2, "Test6_triangulation_IO_3"); } std::cout << " Constructor9 " << std::endl; - // 2-dimensional triangulations + // 2-dimensional triangulations Cls T2_0; v0=T2_0.insert(p1); @@ -381,7 +381,7 @@ _test_cls_triangulation_3(const Triangulation &) assert(T2_0.number_of_vertices()==8); if (! del) // to avoid doing the following tests for both Delaunay - // and non Delaunay triangulations + // and non Delaunay triangulations { _test_cls_triangulation_3_input_output(T2_0, "Test7_triangulation_IO_3"); } @@ -396,8 +396,8 @@ _test_cls_triangulation_3(const Triangulation &) for (m=0; m<20; m++) for (n=0; n<20; n++) { - qq[m+20*n] = Point(m*px+(int)n*qx, m*py+(int)n*qy, 1); - T2_1.insert( qq[m+20*n] ); + qq[m+20*n] = Point(m*px+(int)n*qx, m*py+(int)n*qy, 1); + T2_1.insert( qq[m+20*n] ); } assert( T2_1.number_of_vertices() == m*n ); assert( T2_1.dimension()==2 ); @@ -411,11 +411,11 @@ _test_cls_triangulation_3(const Triangulation &) Point r[225]; for (z=0 ; z<5 ; z++) for (y=0 ; y<5 ; y++) - for (x=0 ; x<5 ; x++) - { - r[x+5*y+25*z] = Point(x,y,z); - v0=T3_0.insert(r[x+5*y+25*z]); - } + for (x=0 ; x<5 ; x++) + { + r[x+5*y+25*z] = Point(x,y,z); + v0=T3_0.insert(r[x+5*y+25*z]); + } assert(T3_0.is_valid()); assert(T3_0.number_of_vertices()==125); assert(T3_0.dimension()==3); @@ -430,7 +430,7 @@ _test_cls_triangulation_3(const Triangulation &) assert(T3_1.dimension()==3); if (! del) // to avoid doing the following tests for both Delaunay - // and non Delaunay triangulations + // and non Delaunay triangulations { _test_cls_triangulation_3_input_output(T3_1, "Test8_triangulation_IO_3"); } @@ -470,19 +470,19 @@ _test_cls_triangulation_3(const Triangulation &) else if (count < 100) std::cout << count << '\b' << '\b' ; - else + else if (count < 1000) std::cout << count << '\b' << '\b' << '\b' ; else - std::cout << count << std::endl; + std::cout << count << std::endl; std::cout.flush(); } std::cout << std::endl; assert(T3_2.is_valid()); assert(T3_2.dimension()==3); assert(T3_2.number_of_vertices()==500); - - + + Point p110(-5,5,0), p111(-2,-5,2), p112(-2,-9,6), p113(4,8,9), p114(5,-6,0), p115(3,0,5), p116(-9,0,-10), p117(1,6,-2), p118(-3,2,-4), p119(3,-3,-1); @@ -497,7 +497,7 @@ _test_cls_triangulation_3(const Triangulation &) v0=T3_5.insert(p117); v0=T3_5.insert(p118, v0->cell()); // testing with the hint v0=T3_5.insert(p119, v0); // testing with the hint - + assert(T3_5.is_valid()); assert(T3_5.number_of_vertices()==10); @@ -519,18 +519,18 @@ _test_cls_triangulation_3(const Triangulation &) // bool success(true); // if (del) { // std::cout << " deletion in a Delaunay of " -// << T3_4.number_of_vertices() << " random points"; +// << T3_4.number_of_vertices() << " random points"; // Vertex_handle v; // while ( T3_4.number_of_vertices() >= 1 ) { // if ( T3_4.dimension() > 1 ) -// v = T3_4.infinite_cell()->vertex -// ( (T3_4.infinite_cell()->index( T3_4.infinite_vertex() ) +1 )&3 ); +// v = T3_4.infinite_cell()->vertex +// ( (T3_4.infinite_cell()->index( T3_4.infinite_vertex() ) +1 )&3 ); // else -// if ( T3_4.dimension() == 1 ) -// v = T3_4.infinite_cell()->vertex -// ( (T3_4.infinite_cell()->index( T3_4.infinite_vertex() ) +1 )%2 ); -// else -// v = T3_4.infinite_cell()->neighbor(0)->vertex(0); +// if ( T3_4.dimension() == 1 ) +// v = T3_4.infinite_cell()->vertex +// ( (T3_4.infinite_cell()->index( T3_4.infinite_vertex() ) +1 )%2 ); +// else +// v = T3_4.infinite_cell()->neighbor(0)->vertex(0); // success = T3_4.remove( v ); // } @@ -594,10 +594,10 @@ _test_cls_triangulation_3(const Triangulation &) assert(T0.dimension() == 3); assert(T0.number_of_vertices() == 4); assert(T0.is_valid()); - + c= Ti.locate(Point(50,50,50),lt,li,lj); - + Point p24(50,50,50); v0= Ti.insert_outside_convex_hull(p24,c); assert(Ti.is_valid()); @@ -621,7 +621,7 @@ _test_cls_triangulation_3(const Triangulation &) // ################## Operations + newly created cells ################ // Small test for inserting and returning the newly created cells - // (the code is mainly the usual insert + incident_{edges,facets,cells} + // (the code is mainly the usual insert + incident_{edges,facets,cells} // depending on the dimension) std::cout << " Test insertion + newly created cells: " << std::endl; @@ -630,7 +630,7 @@ _test_cls_triangulation_3(const Triangulation &) // dimension 1 Cls TAI1; for(int i=0; i<50; i++) - { + { double x = (double) (2*i); TAI1.insert(Point(x, x, x)); } @@ -639,9 +639,9 @@ _test_cls_triangulation_3(const Triangulation &) { lis_tai1.clear(); double x = (double) (2*i - 1); - Vertex_handle taiv = + Vertex_handle taiv = TAI1.insert_and_give_new_cells( - Point(x, x, x), + Point(x, x, x), std::back_inserter(lis_tai1)); CGAL_USE(taiv); assert(TAI1.is_valid()); @@ -652,16 +652,16 @@ _test_cls_triangulation_3(const Triangulation &) Cell_handle c = lis_tai1.front(); lis_tai1.pop_front(); assert(TAI1.tds().is_simplex(c)); - } + } } TAI1.clear(); - std::cout << " 2 dimensions" << std::endl; + std::cout << " 2 dimensions" << std::endl; CGAL::Random grand; for(int i=0; i<50; i++) - { + { double x = grand.get_double(); - double y = grand.get_double(); + double y = grand.get_double(); TAI1.insert(Point(x, y, 0)); } for(int i=0; i<50; i++) @@ -669,9 +669,9 @@ _test_cls_triangulation_3(const Triangulation &) lis_tai1.clear(); double x = grand.get_double(); double y = grand.get_double(); - Vertex_handle taiv = + Vertex_handle taiv = TAI1.insert_and_give_new_cells( - Point(x, y, 0), + Point(x, y, 0), std::back_inserter(lis_tai1)); CGAL_USE(taiv); assert(TAI1.is_valid()); @@ -681,16 +681,16 @@ _test_cls_triangulation_3(const Triangulation &) Cell_handle c = lis_tai1.front(); lis_tai1.pop_front(); assert(TAI1.tds().is_simplex(c)); - } - } + } + } TAI1.clear(); - std::cout << " 3 dimensions" << std::endl; + std::cout << " 3 dimensions" << std::endl; for(int i=0; i<50; i++) - { + { double x = grand.get_double(); - double y = grand.get_double(); - double z = grand.get_double(); + double y = grand.get_double(); + double z = grand.get_double(); TAI1.insert(Point(x, y, z)); } for(int i=0; i<50; i++) @@ -698,10 +698,10 @@ _test_cls_triangulation_3(const Triangulation &) lis_tai1.clear(); double x = grand.get_double(); double y = grand.get_double(); - double z = grand.get_double(); - Vertex_handle taiv = + double z = grand.get_double(); + Vertex_handle taiv = TAI1.insert_and_give_new_cells( - Point(x, y, z), + Point(x, y, z), std::back_inserter(lis_tai1)); CGAL_USE(taiv); assert(TAI1.is_valid()); @@ -711,20 +711,20 @@ _test_cls_triangulation_3(const Triangulation &) Cell_handle c = lis_tai1.front(); lis_tai1.pop_front(); assert(TAI1.tds().is_simplex(c)); - } - } - TAI1.clear(); + } + } + TAI1.clear(); // the other two insertion methods is exactly the same // with different version of the basic insert method // Vertex_handle insert_and_give_new_cells(const Point& p, // OutputItCells fit, - // Vertex_handle hint) + // Vertex_handle hint) // Vertex_handle insert_and_give_new_cells(const Point& p, - // Locate_type lt, Cell_handle c, int li, int lj, + // Locate_type lt, Cell_handle c, int li, int lj, // OutputItCells fit - - + + // ################################################################## @@ -734,9 +734,9 @@ _test_cls_triangulation_3(const Triangulation &) c=T0.infinite_cell(); assert(T0.is_infinite(c)); int ind=c->index(T0.infinite_vertex()); - - Facet f ; - for (i=0;i<4;i++) + + Facet f ; + for (i=0;i<4;i++) if (i!=ind) { assert(T0.is_infinite(c,i)); f=Facet(c,i); @@ -744,11 +744,11 @@ _test_cls_triangulation_3(const Triangulation &) } int j; - for (i=0;i<4;i++) - for (j=0;i<4;i++) + for (i=0;i<4;i++) + for (j=0;i<4;i++) if ((i!=j) && ((i==ind) || (j==ind))) { - assert(T0.is_infinite(c,i,j)); - assert(T0.is_infinite(Edge(c,i,j))); + assert(T0.is_infinite(c,i,j)); + assert(T0.is_infinite(Edge(c,i,j))); } @@ -768,9 +768,9 @@ _test_cls_triangulation_3(const Triangulation &) assert(d->vertex(j) == T0.mirror_vertex(c,i)); assert(Facet(d,j) == T0.mirror_facet(Facet(c,i))); } - - - + + + // geometric functions std::cout << "Geometric functions " << std::endl; c= T0.locate(Point(50,0,1),lt,li,lj); @@ -796,7 +796,7 @@ _test_cls_triangulation_3(const Triangulation &) c= T0.locate(Point(20,0,2),lt,li,lj); Point pt3 = c->vertex(0)->point(); assert(pt2==pt3); - + if (! del) { // Delaunay should not be flipped // or it will not be Delaunay any longer --> not valid std::cout << " Test flip " << std::endl; @@ -812,15 +812,15 @@ _test_cls_triangulation_3(const Triangulation &) flipped = false; i=0; j=1; next_cell = ++cit; --cit; while ( (! flipped) && (i<4) ) { - if ( (i!=j) ) { - flipped = T3_1.flip( cit, i, j ) ; - if (flipped) { - nbflips++; - assert(T3_1.is_valid()); - } - } - if ( j==3 ) { i++; j=0; } - else j++; + if ( (i!=j) ) { + flipped = T3_1.flip( cit, i, j ) ; + if (flipped) { + nbflips++; + assert(T3_1.is_valid()); + } + } + if ( j==3 ) { i++; j=0; } + else j++; } cit = next_cell; } @@ -831,22 +831,22 @@ _test_cls_triangulation_3(const Triangulation &) // NOTE : the triangulation is modified during loop // --> the cell_iterator does not mean a lot for ( i=0; i<4; i++ ) { - flipped = T3_1.flip( cit, i ); - if (flipped) { - nbflips++; - assert(T3_1.is_valid()); - } + flipped = T3_1.flip( cit, i ); + if (flipped) { + nbflips++; + assert(T3_1.is_valid()); + } } } std::cout << nbflips << " flips 2-3" << std::endl; } - + // Finite incident_* in dimension 2 test std::cout << " Testing finite_incident_* in dim 2 "<< std::endl; Cls* T2[2]; T2[0] = &T2_0; T2[1] = &T2_1; - + for(int k = 0; k < 2; ++k) { std::cout << " with triangulation " << k + 1 << ": "; @@ -860,13 +860,13 @@ _test_cls_triangulation_3(const Triangulation &) f_edges.clear(); f_facets.clear(); f_cells.clear(); - + for(Finite_vertices_iterator i = T2[k]->finite_vertices_begin(); - i != T2[k]->finite_vertices_end(); ++i) { + i != T2[k]->finite_vertices_end(); ++i) { // old name (up to CGAL 3.4) // kept for backwards compatibility but not documented T2[k]->finite_incident_vertices(i, std::back_inserter(f_vertices_old)); - // correct name + // correct name T2[k]->finite_adjacent_vertices(i, std::back_inserter(f_vertices)); assert(check_all_are_finite(T2[k], f_vertices)); T2[k]->finite_incident_edges(i, std::back_inserter(f_edges)); @@ -896,14 +896,14 @@ _test_cls_triangulation_3(const Triangulation &) assert(2*nb_f_edges == f_edges.size()); assert(3*nb_f_facets == f_facets.size()); assert(3*nb_f_facets == f_cells.size()); - + typename Cls::size_type nb_f_vertices = T2[k]->number_of_vertices(); - + // Euler relation assert(nb_f_vertices - nb_f_edges + nb_f_facets == 1); std::cout << "ok\n"; } - + // Finite incident_* to vertex test std::cout << " Testing finite_incident_* in dim 3 "<< std::endl; @@ -928,13 +928,13 @@ _test_cls_triangulation_3(const Triangulation &) f_edges.clear(); f_facets.clear(); f_cells.clear(); - + for(Finite_vertices_iterator i = T3[k]->finite_vertices_begin(); - i != T3[k]->finite_vertices_end(); ++i) { + i != T3[k]->finite_vertices_end(); ++i) { // old name (up to CGAL 3.4) // kept for backwards compatibility but not documented T3[k]->finite_incident_vertices(i, std::back_inserter(f_vertices_old)); - // correct name + // correct name T3[k]->finite_adjacent_vertices(i, std::back_inserter(f_vertices)); assert(check_all_are_finite(T3[k], f_vertices)); T3[k]->finite_incident_edges(i, std::back_inserter(f_edges)); @@ -963,16 +963,16 @@ _test_cls_triangulation_3(const Triangulation &) ++nb_f_cells; ++fcit; } - + // incidences assert(f_edges.size() == f_vertices_old.size()); assert(f_edges.size() == f_vertices.size()); assert(2*nb_f_edges == f_edges.size()); assert(3*nb_f_facets == f_facets.size()); assert(4*nb_f_cells == f_cells.size()); - + typename Cls::size_type nb_f_vertices = T3[k]->number_of_vertices(); - + // Euler relation assert(nb_f_vertices - nb_f_edges + nb_f_facets - nb_f_cells == 1); std::cout << "ok\n"; @@ -995,11 +995,11 @@ _test_cls_triangulation_3(const Triangulation &) _test_vertex_iterator(T3_1); _test_triangulation_iterator(T3_1); _test_vertex_iterator(T3_0); - _test_triangulation_iterator(T3_0); - _test_vertex_iterator(T3_2); - _test_triangulation_iterator(T3_2); + _test_triangulation_iterator(T3_0); + _test_vertex_iterator(T3_2); + _test_triangulation_iterator(T3_2); _test_vertex_iterator(T3_3); - _test_triangulation_iterator(T3_3); + _test_triangulation_iterator(T3_3); std::cout << " Testing Circulator "<< std::endl; _test_circulator(T0); From 077a588bf2ec20bd1f4bbfda44def4617d01beaa Mon Sep 17 00:00:00 2001 From: Jane Tournois Date: Fri, 27 Mar 2020 07:54:20 +0100 Subject: [PATCH 182/568] during smoothing, always reproject to the input surface instead of reprojecting to the evolving surface this prevents from smoothing the shape again and again and "losing" features --- .../Tetrahedral_remeshing/internal/FMLS.h | 4 +- .../internal/smooth_vertices.h | 222 +++++++----------- .../tetrahedral_adaptive_remeshing_impl.h | 7 +- 3 files changed, 98 insertions(+), 135 deletions(-) diff --git a/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/FMLS.h b/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/FMLS.h index d3608b16fb9..58e30f055ee 100644 --- a/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/FMLS.h +++ b/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/FMLS.h @@ -191,7 +191,7 @@ namespace CGAL // Compute, according to the current point sampling stored in FMLS, the MLS projection // of p and store the resulting position in q and normal in n. - void fastProjectionCPU(const Vec3Df& p, Vec3Df& q, Vec3Df& n) + void fastProjectionCPU(const Vec3Df& p, Vec3Df& q, Vec3Df& n) const { float sigma_s = PNScale * MLSRadius; float sigma_r = bilateralRange; @@ -248,7 +248,7 @@ namespace CGAL // is compact: pv={x0,y0,z0,x1,y1,z1...}. If pv contains also normals for instance, // the stride should be set to 6. void fastProjectionCPU(const float* pv, unsigned int pvSize, - float* qv, unsigned int stride = 3) + float* qv, unsigned int stride = 3) const { #pragma omp parallel for for (int i = 0; i < int(pvSize); i++) { diff --git a/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/smooth_vertices.h b/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/smooth_vertices.h index aae18ac2f66..8b1052212ce 100644 --- a/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/smooth_vertices.h +++ b/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/smooth_vertices.h @@ -22,41 +22,78 @@ namespace CGAL { namespace internal { - template - CGAL::Vector_3 project_on_tangent_plane(const CGAL::Vector_3& gi, - const CGAL::Vector_3& pi, - const CGAL::Vector_3& normal) + template + class Tetrahedral_remeshing_smoother + { + typedef typename C3t3::Triangulation Tr; + typedef typename C3t3::Surface_patch_index Surface_patch_index; + typedef typename Tr::Vertex_handle Vertex_handle; + typedef typename Tr::Edge Edge; + typedef typename Tr::Facet Facet; + + typedef typename Tr::Geom_traits Gt; + typedef typename Gt::Vector_3 Vector_3; + typedef typename Gt::Point_3 Point_3; + + private: + std::vector < CGAL::Tetrahedral_remeshing::internal::FMLS > subdomain_FMLS; + boost::unordered_map subdomain_FMLS_indices; + + public: + template + void init(const C3t3& c3t3, const CellSelector& cell_selector) + { + //collect a map of vertices surface indices + boost::unordered_map > vertices_surface_indices; + collect_vertices_surface_indices(c3t3, vertices_surface_indices); + + //collect a map of normals at surface vertices + boost::unordered_map > vertices_normals; + compute_vertices_normals(c3t3, vertices_normals, cell_selector); + + // Build MLS Surfaces + createMLSSurfaces(subdomain_FMLS, + subdomain_FMLS_indices, + vertices_normals, + vertices_surface_indices, + c3t3); + } + + private: + + Vector_3 project_on_tangent_plane(const Vector_3& gi, + const Vector_3& pi, + const Vector_3& normal) { - typedef CGAL::Vector_3 Vector_3; Vector_3 diff = pi - gi; return gi + (normal * diff) * normal; } - template - boost::optional - find_adjacent_facet_on_surface(const typename C3t3::Facet& f, - const typename C3t3::Edge& edge, - const C3t3& c3t3, - const CellSelector& cell_selector) + template + boost::optional + find_adjacent_facet_on_surface(const Facet& f, + const Edge& edge, + const C3t3& c3t3, + const CellSelector& cell_selector) { CGAL_assertion(is_boundary(c3t3, f, cell_selector)); - typedef typename C3t3::Facet Facet; - typedef typename C3t3::Triangulation::Facet_circulator Facet_circulator; + typedef typename Tr::Facet_circulator Facet_circulator; if (c3t3.is_in_complex(edge)) return {}; //do not "cross" complex edges //they are likely to be sharp and not to follow the > 0 dot product criterion - const typename C3t3::Surface_patch_index& patch = c3t3.surface_patch_index(f); - const typename C3t3::Facet& mf = c3t3.triangulation().mirror_facet(f); + const Surface_patch_index& patch = c3t3.surface_patch_index(f); + const Facet& mf = c3t3.triangulation().mirror_facet(f); Facet_circulator fcirc = c3t3.triangulation().incident_facets(edge); - Facet_circulator fend = fcirc; + Facet_circulator fend = fcirc; do { const Facet fi = *fcirc; - if ( f != fi + if (f != fi && mf != fi && is_boundary(c3t3, fi, cell_selector) && patch == c3t3.surface_patch_index(fi)) @@ -68,18 +105,13 @@ namespace CGAL return {}; } - template - void compute_neighbors_normals(const typename C3t3::Facet& f, - const typename FacetNormalsMap::mapped_type& reference_normal, - FacetNormalsMap& fnormals, - const C3t3& c3t3, - const CellSelector& cell_selector) + template + void compute_neighbors_normals(const Facet& f, + const typename Vector_3& reference_normal, + FacetNormalsMap& fnormals, + const C3t3& c3t3, + const CellSelector& cell_selector) { - typedef typename C3t3::Triangulation Tr; - typedef typename C3t3::Facet Facet; - typedef typename C3t3::Edge Edge; - typedef typename FacetNormalsMap::mapped_type Vector_3; - typename Tr::Geom_traits::Construct_opposite_vector_3 opp = c3t3.triangulation().geom_traits().construct_opposite_vector_3_object(); typename Tr::Geom_traits::Compute_scalar_product_3 @@ -112,17 +144,11 @@ namespace CGAL } } - template + template void compute_vertices_normals(const C3t3& c3t3, VertexNormalsMap& normals_map, const CellSelector& cell_selector) { - typedef typename C3t3::Triangulation Tr; - typedef typename C3t3::Vertex_handle Vertex_handle; - typedef typename C3t3::Surface_patch_index Surface_patch_index; - typedef typename Tr::Facet Facet; - typedef typename Tr::Geom_traits::Vector_3 Vector_3; - typename Tr::Geom_traits::Construct_opposite_vector_3 opp = c3t3.triangulation().geom_traits().construct_opposite_vector_3_object(); typename Tr::Geom_traits::Construct_scaled_vector_3 @@ -152,7 +178,7 @@ namespace CGAL CGAL_assertion(is_boundary(c3t3, f, cell_selector)); Vector_3 ref = CGAL::Tetrahedral_remeshing::normal(f, tr.geom_traits()); - if ( c3t3.triangulation().is_infinite(f.first) + if (c3t3.triangulation().is_infinite(f.first) || c3t3.subdomain_index(f.first) < c3t3.subdomain_index(mf.first)) ref = opp(ref); @@ -170,8 +196,8 @@ namespace CGAL #ifdef CGAL_TETRAHEDRAL_REMESHING_DEBUG typename Tr::Geom_traits::Point_3 fc = CGAL::centroid(point(f.first->vertex(indices(f.second, 0))->point()), - point(f.first->vertex(indices(f.second, 1))->point()), - point(f.first->vertex(indices(f.second, 2))->point())); + point(f.first->vertex(indices(f.second, 1))->point()), + point(f.first->vertex(indices(f.second, 2))->point())); osf << "2 " << fc << " " << (fc + n) << std::endl; #endif const Surface_patch_index& surf_i = c3t3.surface_patch_index(f); @@ -202,7 +228,7 @@ namespace CGAL //normalize the computed normals for (typename VertexNormalsMap::iterator vnm_it = normals_map.begin(); - vnm_it != normals_map.end(); ++vnm_it) + vnm_it != normals_map.end(); ++vnm_it) { //value type is map for (typename VertexNormalsMap::mapped_type::iterator it = vnm_it->second.begin(); @@ -221,7 +247,7 @@ namespace CGAL const Surface_patch_index si = it->first; if (ons_map.find(si) == ons_map.end()) ons_map[si] = std::vector(); - ons_map[si].push_back(typename Tr::Geom_traits::Segment_3(p, p+n)); + ons_map[si].push_back(typename Tr::Geom_traits::Segment_3(p, p + n)); #endif } } @@ -233,30 +259,20 @@ namespace CGAL std::ostringstream oss; oss << "dump_normals_normalized_" << kv.first << ".polylines.txt"; std::ofstream ons(oss.str()); - for(auto s : kv.second) + for (auto s : kv.second) ons << "2 " << s.source() << " " << s.target() << std::endl; ons.close(); - } + } #endif } - - template - bool project(const SurfacePatchIndex& si, - const CGAL::Vector_3& gi, - CGAL::Vector_3& projected_point, - Subdomain__FMLS& subdomain_FMLS, - Subdomain__FMLS_indices& subdomain_FMLS_indices) + bool project(const Surface_patch_index& si, + const Vector_3& gi, + Vector_3& projected_point) { if (subdomain_FMLS_indices.find(si) == subdomain_FMLS_indices.end()) return false; - typedef typename Gt::Vector_3 Vector_3; - typedef typename Gt::Point_3 Point_3; - if (std::isnan(gi.x()) || std::isnan(gi.y()) || isnan(gi.z())) { std::cout << "Initial point error " << gi << std::endl; @@ -267,7 +283,7 @@ namespace CGAL Vec3Df res_normal; Vec3Df result(point); - CGAL::Tetrahedral_remeshing::internal::FMLS& + const CGAL::Tetrahedral_remeshing::internal::FMLS& fmls = subdomain_FMLS[subdomain_FMLS_indices.at(si)]; int it_nb = 0; @@ -281,61 +297,24 @@ namespace CGAL fmls.fastProjectionCPU(point, result, res_normal); - if (std::isnan(result[0]) || std::isnan(result[1]) || std::isnan(result[2])){ + if (std::isnan(result[0]) || std::isnan(result[1]) || std::isnan(result[2])) { std::cout << "MLS error detected si size " << si - << " : " << fmls.getPNSize() << std::endl; + << " : " << fmls.getPNSize() << std::endl; return false; } - } - while ((result - point).getSquaredLength() > sq_eps && ++it_nb < max_it_nb); + } while ((result - point).getSquaredLength() > sq_eps&& ++it_nb < max_it_nb); projected_point = Vector_3(result[0], result[1], result[2]); return true; } - - template - void collect_vertices_subdomain_indices( - const C3T3& c3t3, - boost::unordered_map< - typename C3T3::Vertex_handle, - std::vector >& vertices_subdomain_indices) - { - typedef typename C3T3::Subdomain_index Subdomain_index; - typedef typename C3T3::Vertex_handle Vertex_handle; - typedef typename C3T3::Triangulation Tr; - - for (typename C3T3::Cell_iterator cit = c3t3.cells_begin(); - cit != c3t3.cells_end(); ++cit) - { - const Subdomain_index& si = cit->subdomain_index(); - for (int i = 0; i < 4; ++i) - { - const Vertex_handle vi = cit->vertex(i); - - std::vector& v_indices = vertices_subdomain_indices[vi]; - if (std::find(v_indices.begin(), v_indices.end(), si) == v_indices.end()) - v_indices.push_back(si); - } - } - } - - template void collect_vertices_surface_indices( - const C3T3& c3t3, - const boost::unordered_map< - typename C3T3::Vertex_handle, - std::vector >& vertices_subdomain_indices, - boost::unordered_map< - typename C3T3::Vertex_handle, - std::vector >& vertices_surface_indices) + const C3t3& c3t3, + boost::unordered_map >& vertices_surface_indices) { - typedef typename C3T3::Surface_patch_index Surface_patch_index; - typedef typename C3T3::Vertex_handle Vertex_handle; - typedef typename C3T3::Facet Facet; - - for (typename C3T3::Facet_iterator fit = c3t3.facets_begin(); + for (typename C3t3::Facet_iterator fit = c3t3.facets_begin(); fit != c3t3.facets_end(); ++fit) { const Surface_patch_index& surface_index = c3t3.surface_patch_index(*fit); @@ -351,22 +330,13 @@ namespace CGAL } } + public: template void smooth_vertices(C3T3& c3t3, - const bool protect_boundaries, - CellSelector cell_selector) + const bool protect_boundaries, + CellSelector cell_selector) { - typedef typename C3T3::Surface_patch_index Surface_patch_index; - typedef typename C3T3::Subdomain_index Subdomain_index; - typedef typename C3T3::Triangulation Tr; - typedef typename C3T3::Vertex_handle Vertex_handle; typedef typename C3T3::Cell_handle Cell_handle; - typedef typename C3T3::Facet Facet; - typedef typename Tr::Edge Edge; - - typedef typename Tr::Geom_traits Gt; - typedef typename Gt::Point_3 Point_3; - typedef typename Gt::Vector_3 Vector_3; typedef typename Gt::FT FT; #ifdef CGAL_TETRAHEDRAL_REMESHING_DEBUG @@ -383,28 +353,15 @@ namespace CGAL Tr& tr = c3t3.triangulation(); - //collect a map of vertices subdomain indices - boost::unordered_map > vertices_subdomain_indices; - collect_vertices_subdomain_indices(c3t3, vertices_subdomain_indices); - //collect a map of vertices surface indices boost::unordered_map > vertices_surface_indices; - collect_vertices_surface_indices(c3t3, vertices_subdomain_indices, vertices_surface_indices); + collect_vertices_surface_indices(c3t3, vertices_surface_indices); //collect a map of normals at surface vertices boost::unordered_map > vertices_normals; compute_vertices_normals(c3t3, vertices_normals, cell_selector); - // Build MLS Surfaces - std::vector < CGAL::Tetrahedral_remeshing::internal::FMLS > subdomain_FMLS; - boost::unordered_map subdomain_FMLS_indices; - createMLSSurfaces(subdomain_FMLS, - subdomain_FMLS_indices, - vertices_normals, - vertices_surface_indices, - c3t3); - //smooth() const std::size_t nbv = tr.number_of_vertices(); boost::unordered_map vertex_id; @@ -475,7 +432,7 @@ namespace CGAL //Check if the mls surface exists to avoid degenrated cases Vector_3 mls_projection; - if (project(si, normal_projection, mls_projection, subdomain_FMLS, subdomain_FMLS_indices)) { + if (project(si, normal_projection, mls_projection)) { final_position = final_position + mls_projection; } else { @@ -509,7 +466,7 @@ namespace CGAL //Check if the mls surface exists to avoid degenerated cases Vector_3 mls_projection; - if (project(si, current_pos, mls_projection, subdomain_FMLS, subdomain_FMLS_indices)) { + if (project(si, current_pos, mls_projection)) { final_position = final_position + mls_projection; } else { @@ -588,7 +545,7 @@ namespace CGAL current_pos, vertices_normals[v][si]); Vector_3 mls_projection; - if (project(si, normal_projection, mls_projection, subdomain_FMLS, subdomain_FMLS_indices)) + if (project(si, normal_projection, mls_projection)) final_position = mls_projection; else final_position = smoothed_position; @@ -606,7 +563,7 @@ namespace CGAL const Vector_3 current_pos(CGAL::ORIGIN, point(v->point())); Vector_3 mls_projection; - if (project(si, current_pos, mls_projection, subdomain_FMLS, subdomain_FMLS_indices)) { + if (project(si, current_pos, mls_projection)) { const typename Tr::Point new_pos(CGAL::ORIGIN + mls_projection); v->set_point(new_pos); @@ -617,7 +574,7 @@ namespace CGAL } } } -//// end if(!protect_boundaries) + //// end if(!protect_boundaries) smoothed_positions.assign(nbv, CGAL::NULL_VECTOR); neighbors.assign(nbv, 0/*for dim 3 vertices, start counting directly from 0*/); @@ -625,7 +582,7 @@ namespace CGAL ////////////// INTERNAL VERTICES /////////////////////// for (const Edge& e : tr.finite_edges()) { - if ( !is_outside(e, c3t3, cell_selector)) + if (!is_outside(e, c3t3, cell_selector)) { const Vertex_handle vh0 = e.first->vertex(e.second); const Vertex_handle vh1 = e.first->vertex(e.third); @@ -679,6 +636,7 @@ namespace CGAL #endif } + };//end class Tetrahedral_remeshing_smoother }//namespace internal }//namespace Tetrahedral_adaptive_remeshing }//namespace CGAL diff --git a/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/tetrahedral_adaptive_remeshing_impl.h b/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/tetrahedral_adaptive_remeshing_impl.h index 325d2384ddc..1a2a5b4a317 100644 --- a/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/tetrahedral_adaptive_remeshing_impl.h +++ b/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/tetrahedral_adaptive_remeshing_impl.h @@ -109,12 +109,15 @@ namespace internal typedef typename C3t3::Subdomain_index Subdomain_index; typedef typename C3t3::Surface_patch_index Surface_patch_index; + typedef typename Tetrahedral_remeshing_smoother Smoother; + private: C3t3 m_c3t3; const SizingFunction& m_sizing; const bool m_protect_boundaries; CellSelector m_cell_selector; Visitor& m_visitor; + Smoother m_vertex_smoother;//initialized with initial surface Triangulation* m_tr_pbackup; //backup to re-swap triangulations when done C3t3* m_c3t3_pbackup; @@ -139,6 +142,7 @@ namespace internal m_c3t3.triangulation().swap(tr); init_c3t3(ecmap, fcmap); + m_vertex_smoother.init(m_c3t3, m_cell_selector); #ifdef CGAL_DUMP_REMESHING_STEPS CGAL::Tetrahedral_remeshing::debug::dump_binary(m_c3t3, "00-init.binary.cgal"); @@ -164,6 +168,7 @@ namespace internal m_c3t3.swap(c3t3); init_c3t3(ecmap, fcmap); + m_vertex_smoother.init(m_c3t3, m_cell_selector); #ifdef CGAL_DUMP_REMESHING_STEPS CGAL::Tetrahedral_remeshing::debug::dump_binary(m_c3t3, "00-init.binary.cgal"); @@ -223,7 +228,7 @@ namespace internal void smooth() { - smooth_vertices(m_c3t3, m_protect_boundaries, m_cell_selector); + m_vertex_smoother.smooth_vertices(m_c3t3, m_protect_boundaries, m_cell_selector); CGAL_assertion(tr().tds().is_valid(true)); #ifdef CGAL_DUMP_REMESHING_STEPS From 69cf0372800f722a879c0977f05b753d7a2f0b8e Mon Sep 17 00:00:00 2001 From: Jane Tournois Date: Fri, 27 Mar 2020 07:54:43 +0100 Subject: [PATCH 183/568] extra iterations re-introduced --- Tetrahedral_remeshing/include/CGAL/tetrahedral_remeshing.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Tetrahedral_remeshing/include/CGAL/tetrahedral_remeshing.h b/Tetrahedral_remeshing/include/CGAL/tetrahedral_remeshing.h index abf66abd2cc..d467862b6da 100644 --- a/Tetrahedral_remeshing/include/CGAL/tetrahedral_remeshing.h +++ b/Tetrahedral_remeshing/include/CGAL/tetrahedral_remeshing.h @@ -381,7 +381,7 @@ namespace CGAL #endif // perform remeshing - std::size_t nb_extra_iterations = 0;// 3; + std::size_t nb_extra_iterations = 3; remesher.remesh(max_it, nb_extra_iterations); #ifdef CGAL_TETRAHEDRAL_REMESHING_DEBUG From 822bc55640e0bfcc1dd1f100fd7e3400406f6c92 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9bastien=20Loriot?= Date: Fri, 27 Mar 2020 08:28:48 +0100 Subject: [PATCH 184/568] extra run of the script to remove tabs and trailing whitespaces --- Kernel_23/include/CGAL/determinant.h | 22 +- .../CGAL/NewKernel_d/Cartesian_LA_functors.h | 422 +++++++++--------- .../CGAL/NewKernel_d/Cartesian_filter_K.h | 4 +- .../CGAL/NewKernel_d/Filtered_predicate2.h | 12 +- .../include/CGAL/NewKernel_d/LA_eigen/LA.h | 304 ++++++------- .../include/CGAL/NewKernel_d/Lazy_cartesian.h | 120 ++--- NewKernel_d/include/CGAL/argument_swaps.h | 38 +- NewKernel_d/include/CGAL/typeset.h | 6 +- STL_Extension/include/CGAL/assertions.h | 12 +- 9 files changed, 470 insertions(+), 470 deletions(-) diff --git a/Kernel_23/include/CGAL/determinant.h b/Kernel_23/include/CGAL/determinant.h index bce915e4b14..e5e66e5e141 100644 --- a/Kernel_23/include/CGAL/determinant.h +++ b/Kernel_23/include/CGAL/determinant.h @@ -1,16 +1,16 @@ -// Copyright (c) 1999 +// Copyright (c) 1999 // Utrecht University (The Netherlands), // ETH Zurich (Switzerland), // INRIA Sophia-Antipolis (France), // Max-Planck-Institute Saarbruecken (Germany), -// and Tel-Aviv University (Israel). All rights reserved. +// and Tel-Aviv University (Israel). All rights reserved. // // This file is part of CGAL (www.cgal.org) // // $URL$ // $Id$ // SPDX-License-Identifier: LGPL-3.0-or-later OR LicenseRef-Commercial -// +// // // Author(s) : Sylvain Pion // Stefan Schirra @@ -227,7 +227,7 @@ determinant( a41, a42, a43, a44, a45, a46, a51, a52, a53, a54, a55, a56, a61, a62, a63, a64, a65, a66) - + - a10 * determinant(a01, a02, a03, a04, a05, a06, a21, a22, a23, a24, a25, a26, @@ -235,7 +235,7 @@ determinant( a41, a42, a43, a44, a45, a46, a51, a52, a53, a54, a55, a56, a61, a62, a63, a64, a65, a66) - + + a20 * determinant(a01, a02, a03, a04, a05, a06, a11, a12, a13, a14, a15, a16, @@ -243,7 +243,7 @@ determinant( a41, a42, a43, a44, a45, a46, a51, a52, a53, a54, a55, a56, a61, a62, a63, a64, a65, a66) - + - a30 * determinant(a01, a02, a03, a04, a05, a06, a11, a12, a13, a14, a15, a16, a21, a22, a23, a24, a25, a26, @@ -251,7 +251,7 @@ determinant( a41, a42, a43, a44, a45, a46, a51, a52, a53, a54, a55, a56, a61, a62, a63, a64, a65, a66) - + + a40 * determinant(a01, a02, a03, a04, a05, a06, a11, a12, a13, a14, a15, a16, a21, a22, a23, a24, a25, a26, @@ -259,15 +259,15 @@ determinant( a51, a52, a53, a54, a55, a56, a61, a62, a63, a64, a65, a66) - + - a50 * determinant(a01, a02, a03, a04, a05, a06, a11, a12, a13, a14, a15, a16, a21, a22, a23, a24, a25, a26, a31, a32, a33, a34, a35, a36, a41, a42, a43, a44, a45, a46, - + a61, a62, a63, a64, a65, a66) - + + a60 * determinant(a01, a02, a03, a04, a05, a06, a11, a12, a13, a14, a15, a16, a21, a22, a23, a24, a25, a26, @@ -278,7 +278,7 @@ determinant( ); } - + } //namespace CGAL #endif // CGAL_DETERMINANT_H diff --git a/NewKernel_d/include/CGAL/NewKernel_d/Cartesian_LA_functors.h b/NewKernel_d/include/CGAL/NewKernel_d/Cartesian_LA_functors.h index ef0b7fffcd6..a379cee7ed9 100644 --- a/NewKernel_d/include/CGAL/NewKernel_d/Cartesian_LA_functors.h +++ b/NewKernel_d/include/CGAL/NewKernel_d/Cartesian_LA_functors.h @@ -27,266 +27,266 @@ namespace CartesianDVectorBase { template struct Construct_LA_vector : private Store_kernel { - //CGAL_FUNCTOR_INIT_IGNORE(Construct_LA_vector) - CGAL_FUNCTOR_INIT_STORE(Construct_LA_vector) - typedef R_ R; - typedef typename R::Constructor Constructor; - typedef typename Get_type::type RT; - typedef typename Get_type::type FT; - typedef typename R::Vector_ result_type; - typedef typename R_::Default_ambient_dimension Dimension; - result_type operator()(int d)const{ - CGAL_assertion(check_dimension_eq(d,this->kernel().dimension())); - return typename Constructor::Dimension()(d); - } - result_type operator()()const{ - return typename Constructor::Dimension()((std::max)(0,this->kernel().dimension())); - } - result_type operator()(int d, Zero_ const&)const{ - CGAL_assertion(check_dimension_eq(d,this->kernel().dimension())); - return typename Constructor::Dimension()(d); - } - result_type operator()(Zero_ const&)const{ - // Makes no sense for an unknown dimension. - return typename Constructor::Dimension()(this->kernel().dimension()); - } - result_type operator()(result_type const& v)const{ - return v; - } - result_type operator()(result_type&& v)const{ - return std::move(v); - } - template - typename std::enable_if::value && - std::is_same, Dimension>::value, - result_type>::type - operator()(U&&...u)const{ - return typename Constructor::Values()(std::forward(u)...); - } - //template::value>::type,class=typename std::enable_if<(sizeof...(U)==static_dim+1)>::type,class=void> - template - typename std::enable_if::value && - std::is_same, Dimension>::value, - result_type>::type - operator()(U&&...u)const{ - return Apply_to_last_then_rest()(typename Constructor::Values_divide(),std::forward(u)...); - } - template inline - typename std::enable_if_t::value,result_type> operator() - (Iter f,Iter g,Cartesian_tag t)const - { - return this->operator()((int)std::distance(f,g),f,g,t); - } - template inline - typename std::enable_if_t::value,result_type> operator() - (int d,Iter f,Iter g,Cartesian_tag)const - { - CGAL_assertion(d==std::distance(f,g)); - CGAL_assertion(check_dimension_eq(d,this->kernel().dimension())); - return typename Constructor::Iterator()(d,f,g); - } - template inline - typename std::enable_if_t::value,result_type> operator() - (Iter f,Iter g,Homogeneous_tag)const - { - --g; - return this->operator()((int)std::distance(f,g),f,g,*g); - } - template inline - typename std::enable_if_t::value,result_type> operator() - (int d,Iter f,Iter g,Homogeneous_tag)const - { - --g; - return this->operator()(d,f,g,*g); - } - template inline - typename std::enable_if_t::value,result_type> operator() - (Iter f,Iter g)const - { - // Shouldn't it try comparing dist(f,g) to the dimension if it is known? - return this->operator()(f,g,typename R::Rep_tag()); - } - template inline - typename std::enable_if_t::value,result_type> operator() - (int d,Iter f,Iter g)const - { - return this->operator()(d,f,g,typename R::Rep_tag()); - } + //CGAL_FUNCTOR_INIT_IGNORE(Construct_LA_vector) + CGAL_FUNCTOR_INIT_STORE(Construct_LA_vector) + typedef R_ R; + typedef typename R::Constructor Constructor; + typedef typename Get_type::type RT; + typedef typename Get_type::type FT; + typedef typename R::Vector_ result_type; + typedef typename R_::Default_ambient_dimension Dimension; + result_type operator()(int d)const{ + CGAL_assertion(check_dimension_eq(d,this->kernel().dimension())); + return typename Constructor::Dimension()(d); + } + result_type operator()()const{ + return typename Constructor::Dimension()((std::max)(0,this->kernel().dimension())); + } + result_type operator()(int d, Zero_ const&)const{ + CGAL_assertion(check_dimension_eq(d,this->kernel().dimension())); + return typename Constructor::Dimension()(d); + } + result_type operator()(Zero_ const&)const{ + // Makes no sense for an unknown dimension. + return typename Constructor::Dimension()(this->kernel().dimension()); + } + result_type operator()(result_type const& v)const{ + return v; + } + result_type operator()(result_type&& v)const{ + return std::move(v); + } + template + typename std::enable_if::value && + std::is_same, Dimension>::value, + result_type>::type + operator()(U&&...u)const{ + return typename Constructor::Values()(std::forward(u)...); + } + //template::value>::type,class=typename std::enable_if<(sizeof...(U)==static_dim+1)>::type,class=void> + template + typename std::enable_if::value && + std::is_same, Dimension>::value, + result_type>::type + operator()(U&&...u)const{ + return Apply_to_last_then_rest()(typename Constructor::Values_divide(),std::forward(u)...); + } + template inline + typename std::enable_if_t::value,result_type> operator() + (Iter f,Iter g,Cartesian_tag t)const + { + return this->operator()((int)std::distance(f,g),f,g,t); + } + template inline + typename std::enable_if_t::value,result_type> operator() + (int d,Iter f,Iter g,Cartesian_tag)const + { + CGAL_assertion(d==std::distance(f,g)); + CGAL_assertion(check_dimension_eq(d,this->kernel().dimension())); + return typename Constructor::Iterator()(d,f,g); + } + template inline + typename std::enable_if_t::value,result_type> operator() + (Iter f,Iter g,Homogeneous_tag)const + { + --g; + return this->operator()((int)std::distance(f,g),f,g,*g); + } + template inline + typename std::enable_if_t::value,result_type> operator() + (int d,Iter f,Iter g,Homogeneous_tag)const + { + --g; + return this->operator()(d,f,g,*g); + } + template inline + typename std::enable_if_t::value,result_type> operator() + (Iter f,Iter g)const + { + // Shouldn't it try comparing dist(f,g) to the dimension if it is known? + return this->operator()(f,g,typename R::Rep_tag()); + } + template inline + typename std::enable_if_t::value,result_type> operator() + (int d,Iter f,Iter g)const + { + return this->operator()(d,f,g,typename R::Rep_tag()); + } - // Last homogeneous coordinate given separately - template inline - typename std::enable_if_t::value,result_type> operator() - (int d,Iter f,Iter g,NT const&l)const - { - CGAL_assertion(d==std::distance(f,g)); - CGAL_assertion(check_dimension_eq(d,this->kernel().dimension())); - // RT? better be safe for now - return typename Constructor::Iterator()(d,CGAL::make_transforming_iterator(f,Divide(l)),CGAL::make_transforming_iterator(g,Divide(l))); - } - template inline - typename std::enable_if_t::value,result_type> operator() - (Iter f,Iter g,NT const&l)const - { - return this->operator()((int)std::distance(f,g),f,g,l); - } + // Last homogeneous coordinate given separately + template inline + typename std::enable_if_t::value,result_type> operator() + (int d,Iter f,Iter g,NT const&l)const + { + CGAL_assertion(d==std::distance(f,g)); + CGAL_assertion(check_dimension_eq(d,this->kernel().dimension())); + // RT? better be safe for now + return typename Constructor::Iterator()(d,CGAL::make_transforming_iterator(f,Divide(l)),CGAL::make_transforming_iterator(g,Divide(l))); + } + template inline + typename std::enable_if_t::value,result_type> operator() + (Iter f,Iter g,NT const&l)const + { + return this->operator()((int)std::distance(f,g),f,g,l); + } }; template struct Compute_cartesian_coordinate { - CGAL_FUNCTOR_INIT_IGNORE(Compute_cartesian_coordinate) - typedef R_ R; - typedef typename Get_type::type RT; - typedef typename R::Vector_ first_argument_type; - typedef int second_argument_type; - typedef Tag_true Is_exact; - typedef decltype(std::declval()[0]) result_type; + CGAL_FUNCTOR_INIT_IGNORE(Compute_cartesian_coordinate) + typedef R_ R; + typedef typename Get_type::type RT; + typedef typename R::Vector_ first_argument_type; + typedef int second_argument_type; + typedef Tag_true Is_exact; + typedef decltype(std::declval()[0]) result_type; - template - result_type operator()(first_argument_type const& v,index_type i)const{ - return v[i]; - } + template + result_type operator()(first_argument_type const& v,index_type i)const{ + return v[i]; + } }; template struct Construct_cartesian_const_iterator { - CGAL_FUNCTOR_INIT_IGNORE(Construct_cartesian_const_iterator) - typedef R_ R; - typedef typename R::Vector_ argument_type; - typedef typename R::LA_vector S_; - typedef typename R::Point_cartesian_const_iterator result_type; - // same as Vector - typedef Tag_true Is_exact; + CGAL_FUNCTOR_INIT_IGNORE(Construct_cartesian_const_iterator) + typedef R_ R; + typedef typename R::Vector_ argument_type; + typedef typename R::LA_vector S_; + typedef typename R::Point_cartesian_const_iterator result_type; + // same as Vector + typedef Tag_true Is_exact; - result_type operator()(argument_type const& v,Begin_tag)const{ - return S_::vector_begin(v); - } - result_type operator()(argument_type const& v,End_tag)const{ - return S_::vector_end(v); - } + result_type operator()(argument_type const& v,Begin_tag)const{ + return S_::vector_begin(v); + } + result_type operator()(argument_type const& v,End_tag)const{ + return S_::vector_end(v); + } }; template struct Midpoint { - CGAL_FUNCTOR_INIT_IGNORE(Midpoint) - typedef R_ R; - typedef typename Get_type::type first_argument_type; - typedef typename Get_type::type second_argument_type; - typedef typename Get_type::type result_type; + CGAL_FUNCTOR_INIT_IGNORE(Midpoint) + typedef R_ R; + typedef typename Get_type::type first_argument_type; + typedef typename Get_type::type second_argument_type; + typedef typename Get_type::type result_type; - result_type operator()(result_type const& a, result_type const& b)const{ - return (a+b)/2; - } + result_type operator()(result_type const& a, result_type const& b)const{ + return (a+b)/2; + } }; template struct Sum_of_vectors { - CGAL_FUNCTOR_INIT_IGNORE(Sum_of_vectors) - typedef R_ R; - typedef typename Get_type::type first_argument_type; - typedef typename Get_type::type second_argument_type; - typedef typename Get_type::type result_type; + CGAL_FUNCTOR_INIT_IGNORE(Sum_of_vectors) + typedef R_ R; + typedef typename Get_type::type first_argument_type; + typedef typename Get_type::type second_argument_type; + typedef typename Get_type::type result_type; - result_type operator()(result_type const& a, result_type const& b)const{ - return a+b; - } + result_type operator()(result_type const& a, result_type const& b)const{ + return a+b; + } }; template struct Difference_of_vectors { - CGAL_FUNCTOR_INIT_IGNORE(Difference_of_vectors) - typedef R_ R; - typedef typename Get_type::type first_argument_type; - typedef typename Get_type::type second_argument_type; - typedef typename Get_type::type result_type; + CGAL_FUNCTOR_INIT_IGNORE(Difference_of_vectors) + typedef R_ R; + typedef typename Get_type::type first_argument_type; + typedef typename Get_type::type second_argument_type; + typedef typename Get_type::type result_type; - result_type operator()(result_type const& a, result_type const& b)const{ - return a-b; - } + result_type operator()(result_type const& a, result_type const& b)const{ + return a-b; + } }; template struct Opposite_vector { - CGAL_FUNCTOR_INIT_IGNORE(Opposite_vector) - typedef R_ R; - typedef typename Get_type::type result_type; - typedef typename Get_type::type argument_type; + CGAL_FUNCTOR_INIT_IGNORE(Opposite_vector) + typedef R_ R; + typedef typename Get_type::type result_type; + typedef typename Get_type::type argument_type; - result_type operator()(result_type const& v)const{ - return -v; - } + result_type operator()(result_type const& v)const{ + return -v; + } }; template struct Scalar_product { - CGAL_FUNCTOR_INIT_IGNORE(Scalar_product) - typedef R_ R; - typedef typename R::LA_vector LA; - typedef typename Get_type::type result_type; - typedef typename Get_type::type first_argument_type; - typedef typename Get_type::type second_argument_type; + CGAL_FUNCTOR_INIT_IGNORE(Scalar_product) + typedef R_ R; + typedef typename R::LA_vector LA; + typedef typename Get_type::type result_type; + typedef typename Get_type::type first_argument_type; + typedef typename Get_type::type second_argument_type; - result_type operator()(first_argument_type const& a, second_argument_type const& b)const{ - return LA::dot_product(a,b); - } + result_type operator()(first_argument_type const& a, second_argument_type const& b)const{ + return LA::dot_product(a,b); + } }; template struct Squared_distance_to_origin_stored { - CGAL_FUNCTOR_INIT_IGNORE(Squared_distance_to_origin_stored) - typedef R_ R; - typedef typename R::LA_vector LA; - typedef typename Get_type::type result_type; - typedef typename Get_type::type argument_type; + CGAL_FUNCTOR_INIT_IGNORE(Squared_distance_to_origin_stored) + typedef R_ R; + typedef typename R::LA_vector LA; + typedef typename Get_type::type result_type; + typedef typename Get_type::type argument_type; - result_type operator()(argument_type const& a)const{ - return LA::squared_norm(a); - } + result_type operator()(argument_type const& a)const{ + return LA::squared_norm(a); + } }; template struct Squared_distance_to_origin_via_dotprod { - CGAL_FUNCTOR_INIT_IGNORE(Squared_distance_to_origin_via_dotprod) - typedef R_ R; - typedef typename R::LA_vector LA; - typedef typename Get_type::type result_type; - typedef typename Get_type::type argument_type; + CGAL_FUNCTOR_INIT_IGNORE(Squared_distance_to_origin_via_dotprod) + typedef R_ R; + typedef typename R::LA_vector LA; + typedef typename Get_type::type result_type; + typedef typename Get_type::type argument_type; - result_type operator()(argument_type const& a)const{ - return LA::dot_product(a,a); - } + result_type operator()(argument_type const& a)const{ + return LA::dot_product(a,a); + } }; template struct Orientation_of_vectors { - CGAL_FUNCTOR_INIT_IGNORE(Orientation_of_vectors) - typedef R_ R; - typedef typename R::Vector_cartesian_const_iterator first_argument_type; - typedef typename R::Vector_cartesian_const_iterator second_argument_type; - typedef typename Get_type::type result_type; - typedef typename R::LA_vector LA; + CGAL_FUNCTOR_INIT_IGNORE(Orientation_of_vectors) + typedef R_ R; + typedef typename R::Vector_cartesian_const_iterator first_argument_type; + typedef typename R::Vector_cartesian_const_iterator second_argument_type; + typedef typename Get_type::type result_type; + typedef typename R::LA_vector LA; - template - result_type operator()(Iter const& f, Iter const& e) const { - return LA::determinant_of_iterators_to_vectors(f,e); - } + template + result_type operator()(Iter const& f, Iter const& e) const { + return LA::determinant_of_iterators_to_vectors(f,e); + } }; template struct Orientation_of_points { - CGAL_FUNCTOR_INIT_IGNORE(Orientation_of_points) - typedef R_ R; - typedef typename R::Point_cartesian_const_iterator first_argument_type; - typedef typename R::Point_cartesian_const_iterator second_argument_type; - typedef typename Get_type::type result_type; - typedef typename R::LA_vector LA; + CGAL_FUNCTOR_INIT_IGNORE(Orientation_of_points) + typedef R_ R; + typedef typename R::Point_cartesian_const_iterator first_argument_type; + typedef typename R::Point_cartesian_const_iterator second_argument_type; + typedef typename Get_type::type result_type; + typedef typename R::LA_vector LA; - template - result_type operator()(Iter const& f, Iter const& e) const { - return LA::determinant_of_iterators_to_points(f,e); - } + template + result_type operator()(Iter const& f, Iter const& e) const { + return LA::determinant_of_iterators_to_points(f,e); + } }; template struct PV_dimension { - CGAL_FUNCTOR_INIT_IGNORE(PV_dimension) - typedef R_ R; - typedef typename R::Vector_ argument_type; - typedef int result_type; - typedef typename R::LA_vector LA; - typedef Tag_true Is_exact; + CGAL_FUNCTOR_INIT_IGNORE(PV_dimension) + typedef R_ R; + typedef typename R::Vector_ argument_type; + typedef int result_type; + typedef typename R::LA_vector LA; + typedef Tag_true Is_exact; - template - result_type operator()(T const& v) const { - return LA::size_of_vector(v); - } + template + result_type operator()(T const& v) const { + return LA::size_of_vector(v); + } }; template struct Identity_functor { diff --git a/NewKernel_d/include/CGAL/NewKernel_d/Cartesian_filter_K.h b/NewKernel_d/include/CGAL/NewKernel_d/Cartesian_filter_K.h index b78070b2faa..ad57f2e541e 100644 --- a/NewKernel_d/include/CGAL/NewKernel_d/Cartesian_filter_K.h +++ b/NewKernel_d/include/CGAL/NewKernel_d/Cartesian_filter_K.h @@ -40,7 +40,7 @@ template<> struct Functors_without_division > { template<> struct Functors_without_division > { typedef typeset type; }; - + template < typename Base_, typename AK_, typename EK_, typename Pred_list = typeset_all > struct Cartesian_filter_K : public Base_, private Store_kernel @@ -81,7 +81,7 @@ struct Cartesian_filter_K : public Base_, }; // TODO: // template struct Functor : -// Kernel_base::template Functor {}; +// Kernel_base::template Functor {}; // TODO: // detect when Less_cartesian_coordinate doesn't need filtering }; diff --git a/NewKernel_d/include/CGAL/NewKernel_d/Filtered_predicate2.h b/NewKernel_d/include/CGAL/NewKernel_d/Filtered_predicate2.h index 49d1cf45740..c3d2281ad96 100644 --- a/NewKernel_d/include/CGAL/NewKernel_d/Filtered_predicate2.h +++ b/NewKernel_d/include/CGAL/NewKernel_d/Filtered_predicate2.h @@ -78,12 +78,12 @@ public: { Protect_FPU_rounding p; try - { - // No forward here, the arguments may still be needed - auto res = ap(c2a(args)...); - if (is_certain(res)) - return get_certain(res); - } + { + // No forward here, the arguments may still be needed + auto res = ap(c2a(args)...); + if (is_certain(res)) + return get_certain(res); + } catch (Uncertain_conversion_exception&) {} } CGAL_BRANCH_PROFILER_BRANCH(tmp); diff --git a/NewKernel_d/include/CGAL/NewKernel_d/LA_eigen/LA.h b/NewKernel_d/include/CGAL/NewKernel_d/LA_eigen/LA.h index c3e65ea4ff8..4bff70e2f5c 100644 --- a/NewKernel_d/include/CGAL/NewKernel_d/LA_eigen/LA.h +++ b/NewKernel_d/include/CGAL/NewKernel_d/LA_eigen/LA.h @@ -30,189 +30,189 @@ namespace CGAL { // Dim_ real dimension // Max_dim_ upper bound on the dimension template struct LA_eigen { - typedef NT_ NT; - typedef Dim_ Dimension; - typedef Max_dim_ Max_dimension; - enum { dimension = Eigen_dimension::value }; - enum { max_dimension = Eigen_dimension::value }; - template< class D2, class D3=D2 > - struct Rebind_dimension { - typedef LA_eigen< NT, D2, D3 > Other; - }; - template struct Property : boost::false_type {}; - template struct Property : boost::true_type {}; - template struct Property : boost::true_type {}; - template struct Property : boost::true_type {}; + typedef NT_ NT; + typedef Dim_ Dimension; + typedef Max_dim_ Max_dimension; + enum { dimension = Eigen_dimension::value }; + enum { max_dimension = Eigen_dimension::value }; + template< class D2, class D3=D2 > + struct Rebind_dimension { + typedef LA_eigen< NT, D2, D3 > Other; + }; + template struct Property : boost::false_type {}; + template struct Property : boost::true_type {}; + template struct Property : boost::true_type {}; + template struct Property : boost::true_type {}; - typedef Eigen::Matrix::value,1,Eigen::ColMajor|Eigen::AutoAlign,Eigen_dimension::value,1> Vector; - typedef Eigen::Matrix Dynamic_vector; - typedef Construct_eigen Construct_vector; + typedef Eigen::Matrix::value,1,Eigen::ColMajor|Eigen::AutoAlign,Eigen_dimension::value,1> Vector; + typedef Eigen::Matrix Dynamic_vector; + typedef Construct_eigen Construct_vector; #if (EIGEN_WORLD_VERSION>=3) - typedef NT const* Vector_const_iterator; + typedef NT const* Vector_const_iterator; #else - typedef Iterator_from_indices Vector_const_iterator; + typedef Iterator_from_indices Vector_const_iterator; #endif - templatestatic Vector_const_iterator vector_begin(Vec_ const&a){ + templatestatic Vector_const_iterator vector_begin(Vec_ const&a){ #if (EIGEN_WORLD_VERSION>=3) - return &a[0]; + return &a[0]; #else - return Vector_const_iterator(a,0); + return Vector_const_iterator(a,0); #endif - } + } - templatestatic Vector_const_iterator vector_end(Vec_ const&a){ + templatestatic Vector_const_iterator vector_end(Vec_ const&a){ #if (EIGEN_WORLD_VERSION>=3) - // FIXME: Isn't that dangerous if a is an expression and not a concrete vector? - return &a[0]+a.size(); + // FIXME: Isn't that dangerous if a is an expression and not a concrete vector? + return &a[0]+a.size(); #else - return Vector_const_iterator(a,a.size()); + return Vector_const_iterator(a,a.size()); #endif - } + } - typedef Eigen::Matrix Square_matrix; - typedef Eigen::Matrix Dynamic_matrix; - //TODO: don't pass on the values of Max_* for an expensive NT + typedef Eigen::Matrix Square_matrix; + typedef Eigen::Matrix Dynamic_matrix; + //TODO: don't pass on the values of Max_* for an expensive NT // typedef ... Constructor // typedef ... Accessor #if 0 - private: - template class Canonicalize_vector { - typedef typename Dimension_eigen::type S1; - typedef typename Dimension_eigen::type S2; - public: - typedef typename Vector::type type; - }; - public: + private: + template class Canonicalize_vector { + typedef typename Dimension_eigen::type S1; + typedef typename Dimension_eigen::type S2; + public: + typedef typename Vector::type type; + }; + public: #endif - templatestatic int size_of_vector(Vec_ const&v){ - return (int)v.size(); - } + templatestatic int size_of_vector(Vec_ const&v){ + return (int)v.size(); + } - templatestatic NT dot_product(Vec_ const&a,Vec_ const&b){ - return a.dot(b); - } + templatestatic NT dot_product(Vec_ const&a,Vec_ const&b){ + return a.dot(b); + } - template static int rows(Vec_ const&v) { - return (int)v.rows(); - } - template static int columns(Vec_ const&v) { - return (int)v.cols(); - } + template static int rows(Vec_ const&v) { + return (int)v.rows(); + } + template static int columns(Vec_ const&v) { + return (int)v.cols(); + } - template static NT determinant_aux [[noreturn]] (Mat_ const&, Tag_true) { - CGAL_error(); - } - template static NT determinant_aux(Mat_ const& m, Tag_false) { - return m.determinant(); - } - - template static NT determinant(Mat_ const&m,bool=false){ - switch(m.rows()){ - //case 0: - // return 1; - case 1: - return m(0,0); - case 2: - return CGAL::determinant( - m(0,0),m(0,1), - m(1,0),m(1,1)); - case 3: - return CGAL::determinant( - m(0,0),m(0,1),m(0,2), - m(1,0),m(1,1),m(1,2), - m(2,0),m(2,1),m(2,2)); - case 4: - return CGAL::determinant( - m(0,0),m(0,1),m(0,2),m(0,3), - m(1,0),m(1,1),m(1,2),m(1,3), - m(2,0),m(2,1),m(2,2),m(2,3), - m(3,0),m(3,1),m(3,2),m(3,3)); - case 5: - return CGAL::determinant( - m(0,0),m(0,1),m(0,2),m(0,3),m(0,4), - m(1,0),m(1,1),m(1,2),m(1,3),m(1,4), - m(2,0),m(2,1),m(2,2),m(2,3),m(2,4), - m(3,0),m(3,1),m(3,2),m(3,3),m(3,4), - m(4,0),m(4,1),m(4,2),m(4,3),m(4,4)); - case 6: - return CGAL::determinant( - m(0,0),m(0,1),m(0,2),m(0,3),m(0,4),m(0,5), - m(1,0),m(1,1),m(1,2),m(1,3),m(1,4),m(1,5), - m(2,0),m(2,1),m(2,2),m(2,3),m(2,4),m(2,5), - m(3,0),m(3,1),m(3,2),m(3,3),m(3,4),m(3,5), - m(4,0),m(4,1),m(4,2),m(4,3),m(4,4),m(4,5), - m(5,0),m(5,1),m(5,2),m(5,3),m(5,4),m(5,5)); - case 7: - return CGAL::determinant( - m(0,0),m(0,1),m(0,2),m(0,3),m(0,4),m(0,5),m(0,6), - m(1,0),m(1,1),m(1,2),m(1,3),m(1,4),m(1,5),m(1,6), - m(2,0),m(2,1),m(2,2),m(2,3),m(2,4),m(2,5),m(2,6), - m(3,0),m(3,1),m(3,2),m(3,3),m(3,4),m(3,5),m(3,6), - m(4,0),m(4,1),m(4,2),m(4,3),m(4,4),m(4,5),m(4,6), - m(5,0),m(5,1),m(5,2),m(5,3),m(5,4),m(5,5),m(5,6), - m(6,0),m(6,1),m(6,2),m(6,3),m(6,4),m(6,5),m(6,6)); - default: + template static NT determinant_aux [[noreturn]] (Mat_ const&, Tag_true) { + CGAL_error(); + } + template static NT determinant_aux(Mat_ const& m, Tag_false) { + return m.determinant(); + } + + template static NT determinant(Mat_ const&m,bool=false){ + switch(m.rows()){ + //case 0: + // return 1; + case 1: + return m(0,0); + case 2: + return CGAL::determinant( + m(0,0),m(0,1), + m(1,0),m(1,1)); + case 3: + return CGAL::determinant( + m(0,0),m(0,1),m(0,2), + m(1,0),m(1,1),m(1,2), + m(2,0),m(2,1),m(2,2)); + case 4: + return CGAL::determinant( + m(0,0),m(0,1),m(0,2),m(0,3), + m(1,0),m(1,1),m(1,2),m(1,3), + m(2,0),m(2,1),m(2,2),m(2,3), + m(3,0),m(3,1),m(3,2),m(3,3)); + case 5: + return CGAL::determinant( + m(0,0),m(0,1),m(0,2),m(0,3),m(0,4), + m(1,0),m(1,1),m(1,2),m(1,3),m(1,4), + m(2,0),m(2,1),m(2,2),m(2,3),m(2,4), + m(3,0),m(3,1),m(3,2),m(3,3),m(3,4), + m(4,0),m(4,1),m(4,2),m(4,3),m(4,4)); + case 6: + return CGAL::determinant( + m(0,0),m(0,1),m(0,2),m(0,3),m(0,4),m(0,5), + m(1,0),m(1,1),m(1,2),m(1,3),m(1,4),m(1,5), + m(2,0),m(2,1),m(2,2),m(2,3),m(2,4),m(2,5), + m(3,0),m(3,1),m(3,2),m(3,3),m(3,4),m(3,5), + m(4,0),m(4,1),m(4,2),m(4,3),m(4,4),m(4,5), + m(5,0),m(5,1),m(5,2),m(5,3),m(5,4),m(5,5)); + case 7: + return CGAL::determinant( + m(0,0),m(0,1),m(0,2),m(0,3),m(0,4),m(0,5),m(0,6), + m(1,0),m(1,1),m(1,2),m(1,3),m(1,4),m(1,5),m(1,6), + m(2,0),m(2,1),m(2,2),m(2,3),m(2,4),m(2,5),m(2,6), + m(3,0),m(3,1),m(3,2),m(3,3),m(3,4),m(3,5),m(3,6), + m(4,0),m(4,1),m(4,2),m(4,3),m(4,4),m(4,5),m(4,6), + m(5,0),m(5,1),m(5,2),m(5,3),m(5,4),m(5,5),m(5,6), + m(6,0),m(6,1),m(6,2),m(6,3),m(6,4),m(6,5),m(6,6)); + default: return determinant_aux(m, Boolean_tag<(Mat_::MaxRowsAtCompileTime >= 1 && Mat_::MaxRowsAtCompileTime <= 7)>()); - } - } + } + } - template static typename - Same_uncertainty_nt::type - sign_of_determinant(Mat_ const&m,bool=false) - { - return CGAL::sign(LA_eigen::determinant(m)); - } + template static typename + Same_uncertainty_nt::type + sign_of_determinant(Mat_ const&m,bool=false) + { + return CGAL::sign(LA_eigen::determinant(m)); + } - template static int rank(Mat_ const&m){ - // return m.rank(); - // This one uses sqrt so cannot be used with Gmpq - // TODO: use different algo for different NT? - // Eigen::ColPivHouseholderQR decomp(m); - Eigen::FullPivLU decomp(m); - // decomp.setThreshold(0); - return static_cast(decomp.rank()); - } + template static int rank(Mat_ const&m){ + // return m.rank(); + // This one uses sqrt so cannot be used with Gmpq + // TODO: use different algo for different NT? + // Eigen::ColPivHouseholderQR decomp(m); + Eigen::FullPivLU decomp(m); + // decomp.setThreshold(0); + return static_cast(decomp.rank()); + } - // m*a==b - template - static void solve(DV&a, DM const&m, V const& b){ - //a = m.colPivHouseholderQr().solve(b); - a = m.fullPivLu().solve(b); - } - template - static bool solve_and_check(DV&a, DM const&m, V const& b){ - //a = m.colPivHouseholderQr().solve(b); - a = m.fullPivLu().solve(b); - return b.isApprox(m*a); - } + // m*a==b + template + static void solve(DV&a, DM const&m, V const& b){ + //a = m.colPivHouseholderQr().solve(b); + a = m.fullPivLu().solve(b); + } + template + static bool solve_and_check(DV&a, DM const&m, V const& b){ + //a = m.colPivHouseholderQr().solve(b); + a = m.fullPivLu().solve(b); + return b.isApprox(m*a); + } - static Dynamic_matrix basis(Dynamic_matrix const&m){ - return m.fullPivLu().image(m); - } + static Dynamic_matrix basis(Dynamic_matrix const&m){ + return m.fullPivLu().image(m); + } - template static Vector homogeneous_add(Vec1 const&a,Vec2 const&b){ - //TODO: use compile-time size when available - int d=a.size(); - Vector v(d); - v << b[d-1]*a.topRows(d-1)+a[d-1]*b.topRows(d-1), a[d-1]*b[d-1]; - return v; - } + template static Vector homogeneous_add(Vec1 const&a,Vec2 const&b){ + //TODO: use compile-time size when available + int d=a.size(); + Vector v(d); + v << b[d-1]*a.topRows(d-1)+a[d-1]*b.topRows(d-1), a[d-1]*b[d-1]; + return v; + } - template static Vector homogeneous_sub(Vec1 const&a,Vec2 const&b){ - int d=a.size(); - Vector v(d); - v << b[d-1]*a.topRows(d-1)-a[d-1]*b.topRows(d-1), a[d-1]*b[d-1]; - return v; - } + template static Vector homogeneous_sub(Vec1 const&a,Vec2 const&b){ + int d=a.size(); + Vector v(d); + v << b[d-1]*a.topRows(d-1)-a[d-1]*b.topRows(d-1), a[d-1]*b[d-1]; + return v; + } - template static std::pair homogeneous_dot_product(Vec1 const&a,Vec2 const&b){ - int d=a.size(); - return make_pair(a.topRows(d-1).dot(b.topRows(d-1)), a[d-1]*b[d-1]); - } + template static std::pair homogeneous_dot_product(Vec1 const&a,Vec2 const&b){ + int d=a.size(); + return make_pair(a.topRows(d-1).dot(b.topRows(d-1)), a[d-1]*b[d-1]); + } }; } diff --git a/NewKernel_d/include/CGAL/NewKernel_d/Lazy_cartesian.h b/NewKernel_d/include/CGAL/NewKernel_d/Lazy_cartesian.h index d095d703a9e..56ecd5df953 100644 --- a/NewKernel_d/include/CGAL/NewKernel_d/Lazy_cartesian.h +++ b/NewKernel_d/include/CGAL/NewKernel_d/Lazy_cartesian.h @@ -199,19 +199,19 @@ struct Lazy_cartesian_types typedef typename typeset_intersection< typename AK_::Object_list, typename EK_::Object_list - >::type Object_list; + >::type Object_list; typedef typename typeset_intersection< typename AK_::Iterator_list, typename EK_::Iterator_list - >::type Iterator_list; + >::type Iterator_list; template ::type> struct Type {}; template struct Type { - typedef Lazy< - typename Get_type::type, - typename Get_type::type, - E2A_> type; + typedef Lazy< + typename Get_type::type, + typename Get_type::type, + E2A_> type; }; template struct Type { typedef CGAL::Lazy_exact_nt::type> type; @@ -225,12 +225,12 @@ struct Lazy_cartesian_types // TODO: we should use Lazy_construction2, but this seems ok for now, we never construct iterators from iterators. typedef typename internal::Lazy_construction_maybe_nt< - Kernel_, AF, EF, is_NT_tag::value - >::type nth_elem; + Kernel_, AF, EF, is_NT_tag::value + >::type nth_elem; typedef Iterator_from_indices< - const typename Type::container>::type, - const V, V, nth_elem + const typename Type::container>::type, + const V, V, nth_elem > type; }; }; @@ -288,39 +288,39 @@ struct Lazy_cartesian : // Check that Approximate_kernel agrees with all that... template::type> struct Functor { - typedef Null_functor type; + typedef Null_functor type; }; - //FIXME: what do we do with D here? + //FIXME: what do we do with D here? template struct Functor { - typedef typename Get_functor::type FA; - typedef typename Get_functor::type FE; - typedef Filtered_predicate2 type; + typedef typename Get_functor::type FA; + typedef typename Get_functor::type FE; + typedef Filtered_predicate2 type; }; template struct Functor { - typedef Lazy_construction2 type; + typedef Lazy_construction2 type; }; template struct Functor { - typedef Lazy_construction2 type; + typedef Lazy_construction2 type; }; template struct Functor { - typedef typename Get_functor::type FA; - struct type { - FA fa; - type(){} - type(Kernel const&k):fa(k.approximate_kernel()){} - template - int operator()(P const&p)const{return fa(CGAL::approx(p));} - }; + typedef typename Get_functor::type FA; + struct type { + FA fa; + type(){} + type(Kernel const&k):fa(k.approximate_kernel()){} + template + int operator()(P const&p)const{return fa(CGAL::approx(p));} + }; }; template struct Functor { - typedef typename Get_functor::type FA; - struct type { - FA fa; - type(){} - type(Kernel const&k):fa(k.approximate_kernel()){} - template - int operator()(V const&v)const{return fa(CGAL::approx(v));} - }; + typedef typename Get_functor::type FA; + struct type { + FA fa; + type(){} + type(Kernel const&k):fa(k.approximate_kernel()){} + template + int operator()(V const&v)const{return fa(CGAL::approx(v));} + }; }; template struct Functor { // Don't filter that one, as there is no guarantee that the interval @@ -332,19 +332,19 @@ struct Lazy_cartesian : typedef typename Get_type::type ET; typedef typename Base::template Type::type V; // Lazy struct type { - FE fe; - type(){} - type(Kernel const&k):fe(k.exact_kernel()){} - template - void operator()(Iter i, Iter e, Oter o)const{ - fe(CGAL::exact(i), CGAL::exact(e), - boost::make_function_output_iterator( - [&o](ET const&v){ - *o++ = V(new Lazy_rep_0(v)); - } - ) - ); - } + FE fe; + type(){} + type(Kernel const&k):fe(k.exact_kernel()){} + template + void operator()(Iter i, Iter e, Oter o)const{ + fe(CGAL::exact(i), CGAL::exact(e), + boost::make_function_output_iterator( + [&o](ET const&v){ + *o++ = V(new Lazy_rep_0(v)); + } + ) + ); + } }; }; @@ -354,22 +354,22 @@ struct Lazy_cartesian : // This is really specific to point/vector coordinate iterators template struct Construct_iter : private Store_kernel { - Construct_iter(){} - Construct_iter(Kernel const&k):Store_kernel(k){} - //FIXME: pass the kernel to the functor in the iterator - typedef U result_type; - template - result_type operator()(T const& t,Begin_tag)const{ - return result_type(t,0,this->kernel()); - } - template - result_type operator()(T const& t,End_tag)const{ - typedef typename Get_functor::type PD; - return result_type(t,PD(this->kernel().approximate_kernel())(CGAL::approx(t)),this->kernel()); - } + Construct_iter(){} + Construct_iter(Kernel const&k):Store_kernel(k){} + //FIXME: pass the kernel to the functor in the iterator + typedef U result_type; + template + result_type operator()(T const& t,Begin_tag)const{ + return result_type(t,0,this->kernel()); + } + template + result_type operator()(T const& t,End_tag)const{ + typedef typename Get_functor::type PD; + return result_type(t,PD(this->kernel().approximate_kernel())(CGAL::approx(t)),this->kernel()); + } }; template struct Functor { - typedef Construct_iter::type>::type> type; + typedef Construct_iter::type>::type> type; }; diff --git a/NewKernel_d/include/CGAL/argument_swaps.h b/NewKernel_d/include/CGAL/argument_swaps.h index 8eea20ddf03..a6f2cd8d794 100644 --- a/NewKernel_d/include/CGAL/argument_swaps.h +++ b/NewKernel_d/include/CGAL/argument_swaps.h @@ -22,33 +22,33 @@ template struct Apply_to_last_then_rest_; template struct Apply_to_last_then_rest_ { - typedef typename Apply_to_last_then_rest_::result_type result_type; - inline result_type operator()(F&&f,T&&t,U&&...u)const{ - return Apply_to_last_then_rest_()( - std::forward(f), - std::forward(u)..., - std::forward(t)); - } + typedef typename Apply_to_last_then_rest_::result_type result_type; + inline result_type operator()(F&&f,T&&t,U&&...u)const{ + return Apply_to_last_then_rest_()( + std::forward(f), + std::forward(u)..., + std::forward(t)); + } }; template struct Apply_to_last_then_rest_<0,F,T,U...> { - typedef decltype(std::declval()(std::declval(), std::declval()...)) result_type; - inline result_type operator()(F&&f,T&&t,U&&...u)const{ - return std::forward(f)(std::forward(t), std::forward(u)...); - } + typedef decltype(std::declval()(std::declval(), std::declval()...)) result_type; + inline result_type operator()(F&&f,T&&t,U&&...u)const{ + return std::forward(f)(std::forward(t), std::forward(u)...); + } }; } // namespace internal struct Apply_to_last_then_rest { - template inline - typename internal::Apply_to_last_then_rest_::result_type - operator()(F&&f,T&&t,U&&...u)const{ - return internal::Apply_to_last_then_rest_()( - std::forward(f), - std::forward(t), - std::forward(u)...); - } + template inline + typename internal::Apply_to_last_then_rest_::result_type + operator()(F&&f,T&&t,U&&...u)const{ + return internal::Apply_to_last_then_rest_()( + std::forward(f), + std::forward(t), + std::forward(u)...); + } }; } // namespace CGAL diff --git a/NewKernel_d/include/CGAL/typeset.h b/NewKernel_d/include/CGAL/typeset.h index 084ec3aabba..77c37c89c39 100644 --- a/NewKernel_d/include/CGAL/typeset.h +++ b/NewKernel_d/include/CGAL/typeset.h @@ -33,7 +33,7 @@ namespace CGAL { std::conditional< contains::value, typeset, - typeset + typeset >::type; }; template<> struct typeset<> { @@ -58,8 +58,8 @@ namespace CGAL { typedef typename T1::head H; typedef typename typeset_intersection_::type U; typedef typename - std::conditional::value, - typename U::template add::type, U>::type type; + std::conditional::value, + typename U::template add::type, U>::type type; }; template struct typeset_intersection_, T> : typeset<> {}; template struct typeset_intersection_ : T {}; diff --git a/STL_Extension/include/CGAL/assertions.h b/STL_Extension/include/CGAL/assertions.h index 62d941f609a..caa0237fc7d 100644 --- a/STL_Extension/include/CGAL/assertions.h +++ b/STL_Extension/include/CGAL/assertions.h @@ -1,9 +1,9 @@ -// Copyright (c) 1999 +// Copyright (c) 1999 // Utrecht University (The Netherlands), // ETH Zurich (Switzerland), // INRIA Sophia-Antipolis (France), // Max-Planck-Institute Saarbruecken (Germany), -// and Tel-Aviv University (Israel). All rights reserved. +// and Tel-Aviv University (Israel). All rights reserved. // // This file is part of CGAL (www.cgal.org) // @@ -131,7 +131,7 @@ inline bool possibly(Uncertain c); # define CGAL_static_assertion(EX) \ BOOST_STATIC_ASSERT(true) CGAL_UNUSED - + # define CGAL_static_assertion_msg(EX,MSG) \ BOOST_STATIC_ASSERT(true) CGAL_UNUSED @@ -139,14 +139,14 @@ inline bool possibly(Uncertain c); # define CGAL_static_assertion(EX) \ BOOST_STATIC_ASSERT(EX) CGAL_UNUSED - + # define CGAL_static_assertion_msg(EX,MSG) \ BOOST_STATIC_ASSERT(EX) CGAL_UNUSED # endif // no CGAL_NO_ASSERTIONS #endif // if CGAL_CFG_NO_CPP0X_STATIC_ASSERT is true - + #if defined(CGAL_NO_ASSERTIONS) || !defined(CGAL_CHECK_EXACTNESS) # define CGAL_exactness_assertion(EX) (static_cast(0)) # define CGAL_exactness_assertion_msg(EX,MSG) (static_cast(0)) @@ -223,7 +223,7 @@ inline bool possibly(Uncertain c); # define CGAL_expensive_precondition_code(CODE) CODE #endif // CGAL_NO_PRECONDITIONS -#if defined(CGAL_NO_PRECONDITIONS) || !defined(CGAL_CHECK_EXACTNESS) || !defined(CGAL_CHECK_EXPENSIVE) +#if defined(CGAL_NO_PRECONDITIONS) || !defined(CGAL_CHECK_EXACTNESS) || !defined(CGAL_CHECK_EXPENSIVE) # define CGAL_expensive_exactness_precondition(EX) (static_cast(0)) # define CGAL_expensive_exactness_precondition_msg(EX,MSG) (static_cast(0)) # define CGAL_expensive_exactness_precondition_code(CODE) From 30104c60327ce3a345c5d399e676b1d8609e31ac Mon Sep 17 00:00:00 2001 From: Ahmed Essam Date: Wed, 4 Mar 2020 07:51:57 +0200 Subject: [PATCH 185/568] Fix bug in matching roots --- .../CGAL/Arr_geometry_traits/Bezier_cache.h | 41 ++++++++----------- 1 file changed, 18 insertions(+), 23 deletions(-) diff --git a/Arrangement_on_surface_2/include/CGAL/Arr_geometry_traits/Bezier_cache.h b/Arrangement_on_surface_2/include/CGAL/Arr_geometry_traits/Bezier_cache.h index 52ece90b03d..17feaab3db6 100644 --- a/Arrangement_on_surface_2/include/CGAL/Arr_geometry_traits/Bezier_cache.h +++ b/Arrangement_on_surface_2/include/CGAL/Arr_geometry_traits/Bezier_cache.h @@ -258,7 +258,7 @@ private: const Polynomial& polyY_1, const Integer& normY_1, const Polynomial& polyX_2, const Integer& normX_2, const Polynomial& polyY_2, const Integer& normY_2, - Parameter_list& s_vals) const; + Parameter_list& s_vals, bool find_out_of_range=false) const; /*! * Compute all s-parameter values of the self intersection of (X(s), Y(s)) @@ -414,7 +414,7 @@ _Bezier_cache::get_intersections do_ovlp = _intersection_params (polyX_2, normX_2, polyY_2, normY_2, polyX_1, normX_1, polyY_1, normY_1, - t_vals); + t_vals, true); CGAL_assertion (! do_ovlp); @@ -464,21 +464,14 @@ _Bezier_cache::get_intersections const Algebraic one (1); unsigned int k; - //pointers are used to set the list pts1_ptr as the one with the less values - Point_list* pts1_ptr=&pts1; - Point_list* pts2_ptr=&pts2; - bool swapt=pts1.size() > pts2.size(); - if (swapt) - std::swap(pts1_ptr,pts2_ptr); - - for (pit1 = pts1_ptr->begin(); pit1 != pts1_ptr->end(); ++pit1) + for (pit1 = pts1.begin(); pit1 != pts1.end(); ++pit1) { // Construct a vector of distances from the current point to all other // points in the pts2 list. - const int n_pts2 = static_cast(pts2_ptr->size()); + const int n_pts2 = static_cast(pts2.size()); std::vector dist_vec (n_pts2); - for (k = 0, pit2 = pts2_ptr->begin(); pit2 != pts2_ptr->end(); k++, ++pit2) + for (k = 0, pit2 = pts2.begin(); pit2 != pts2.end(); k++, ++pit2) { // Compute the approximate distance between the teo current points. dx = pit1->app_x - pit2->app_x; @@ -515,7 +508,7 @@ _Bezier_cache::get_intersections pit1->y = pit2->y; // Remove this point from pts2, as we found a match for it. - pts2_ptr->erase (pit2); + pts2.erase (pit2); found = true; } } @@ -535,17 +528,15 @@ _Bezier_cache::get_intersections pit1->y = pit2->y; // Remove this point from pts2, as we found a match for it. - pts2_ptr->erase (pit2); + pts2.erase (pit2); } // Check that s- and t-values both lie in the legal range of [0,1]. - CGAL_assertion(CGAL::sign (s) != NEGATIVE && CGAL::compare (s, one) != LARGER && - CGAL::sign (t) != NEGATIVE && CGAL::compare (t, one) != LARGER); - - if (!swapt) + if(CGAL::sign (s) != NEGATIVE && CGAL::compare (s, one) != LARGER && + CGAL::sign (t) != NEGATIVE && CGAL::compare (t, one) != LARGER) + { info.first.push_back (Intersection_point_2 (s, t,pit1->x, pit1->y)); - else - info.first.push_back (Intersection_point_2 (t, s,pit1->x, pit1->y)); + } } info.second = false; @@ -589,7 +580,7 @@ bool _Bezier_cache::_intersection_params const Polynomial& polyY_1, const Integer& normY_1, const Polynomial& polyX_2, const Integer& normX_2, const Polynomial& polyY_2, const Integer& normY_2, - Parameter_list& s_vals) const + Parameter_list& s_vals, bool find_out_of_range) const { // Clear the output parameter list. if (! s_vals.empty()) @@ -640,8 +631,12 @@ bool _Bezier_cache::_intersection_params } // Compute the roots of the resultant polynomial and mark that the curves do - // not overlap. The roots we are interested in must be in the interval [0,1]. - nt_traits.compute_polynomial_roots (res,0,1,std::back_inserter (s_vals)); + // not overlap. The roots we are interested in are usually in the interval [0,1]. + if (find_out_of_range) + nt_traits.compute_polynomial_roots (res,std::back_inserter (s_vals)); + else + nt_traits.compute_polynomial_roots (res,0,1,std::back_inserter (s_vals)); + return (false); } From bccba2d76f264a26799c427096c604b28128efd0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9bastien=20Loriot?= Date: Fri, 27 Mar 2020 09:56:00 +0100 Subject: [PATCH 186/568] extra run of the script to remove tabs and trailing whitespaces --- Kernel_23/include/CGAL/determinant.h | 22 +- .../CGAL/NewKernel_d/Cartesian_filter_K.h | 4 +- .../CGAL/NewKernel_d/Filtered_predicate2.h | 22 +- .../include/CGAL/NewKernel_d/LA_eigen/LA.h | 308 +++++++++--------- .../include/CGAL/NewKernel_d/Lazy_cartesian.h | 70 ++-- NewKernel_d/include/CGAL/typeset.h | 8 +- 6 files changed, 217 insertions(+), 217 deletions(-) diff --git a/Kernel_23/include/CGAL/determinant.h b/Kernel_23/include/CGAL/determinant.h index a88d697894a..6ae01fe02d7 100644 --- a/Kernel_23/include/CGAL/determinant.h +++ b/Kernel_23/include/CGAL/determinant.h @@ -1,9 +1,9 @@ -// Copyright (c) 1999 +// Copyright (c) 1999 // Utrecht University (The Netherlands), // ETH Zurich (Switzerland), // INRIA Sophia-Antipolis (France), // Max-Planck-Institute Saarbruecken (Germany), -// and Tel-Aviv University (Israel). All rights reserved. +// and Tel-Aviv University (Israel). All rights reserved. // // This file is part of CGAL (www.cgal.org); you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public License as @@ -19,7 +19,7 @@ // $URL$ // $Id$ // SPDX-License-Identifier: LGPL-3.0+ -// +// // // Author(s) : Sylvain Pion // Stefan Schirra @@ -236,7 +236,7 @@ determinant( a41, a42, a43, a44, a45, a46, a51, a52, a53, a54, a55, a56, a61, a62, a63, a64, a65, a66) - + - a10 * determinant(a01, a02, a03, a04, a05, a06, a21, a22, a23, a24, a25, a26, @@ -244,7 +244,7 @@ determinant( a41, a42, a43, a44, a45, a46, a51, a52, a53, a54, a55, a56, a61, a62, a63, a64, a65, a66) - + + a20 * determinant(a01, a02, a03, a04, a05, a06, a11, a12, a13, a14, a15, a16, @@ -252,7 +252,7 @@ determinant( a41, a42, a43, a44, a45, a46, a51, a52, a53, a54, a55, a56, a61, a62, a63, a64, a65, a66) - + - a30 * determinant(a01, a02, a03, a04, a05, a06, a11, a12, a13, a14, a15, a16, a21, a22, a23, a24, a25, a26, @@ -260,7 +260,7 @@ determinant( a41, a42, a43, a44, a45, a46, a51, a52, a53, a54, a55, a56, a61, a62, a63, a64, a65, a66) - + + a40 * determinant(a01, a02, a03, a04, a05, a06, a11, a12, a13, a14, a15, a16, a21, a22, a23, a24, a25, a26, @@ -268,15 +268,15 @@ determinant( a51, a52, a53, a54, a55, a56, a61, a62, a63, a64, a65, a66) - + - a50 * determinant(a01, a02, a03, a04, a05, a06, a11, a12, a13, a14, a15, a16, a21, a22, a23, a24, a25, a26, a31, a32, a33, a34, a35, a36, a41, a42, a43, a44, a45, a46, - + a61, a62, a63, a64, a65, a66) - + + a60 * determinant(a01, a02, a03, a04, a05, a06, a11, a12, a13, a14, a15, a16, a21, a22, a23, a24, a25, a26, @@ -287,7 +287,7 @@ determinant( ); } - + } //namespace CGAL #endif // CGAL_DETERMINANT_H diff --git a/NewKernel_d/include/CGAL/NewKernel_d/Cartesian_filter_K.h b/NewKernel_d/include/CGAL/NewKernel_d/Cartesian_filter_K.h index a79c8f78c37..21b31e97691 100644 --- a/NewKernel_d/include/CGAL/NewKernel_d/Cartesian_filter_K.h +++ b/NewKernel_d/include/CGAL/NewKernel_d/Cartesian_filter_K.h @@ -49,7 +49,7 @@ template<> struct Functors_without_division > { template<> struct Functors_without_division > { typedef typeset type; }; - + template < typename Base_, typename AK_, typename EK_, typename Pred_list = typeset_all > struct Cartesian_filter_K : public Base_, private Store_kernel @@ -90,7 +90,7 @@ struct Cartesian_filter_K : public Base_, }; // TODO: // template struct Functor : -// Kernel_base::template Functor {}; +// Kernel_base::template Functor {}; // TODO: // detect when Less_cartesian_coordinate doesn't need filtering }; diff --git a/NewKernel_d/include/CGAL/NewKernel_d/Filtered_predicate2.h b/NewKernel_d/include/CGAL/NewKernel_d/Filtered_predicate2.h index 3570ee3a254..e476d01b751 100644 --- a/NewKernel_d/include/CGAL/NewKernel_d/Filtered_predicate2.h +++ b/NewKernel_d/include/CGAL/NewKernel_d/Filtered_predicate2.h @@ -90,12 +90,12 @@ public: { Protect_FPU_rounding p; try - { - // No forward here, the arguments may still be needed - Ares res = ap(c2a(args)...); - if (is_certain(res)) - return get_certain(res); - } + { + // No forward here, the arguments may still be needed + Ares res = ap(c2a(args)...); + if (is_certain(res)) + return get_certain(res); + } catch (Uncertain_conversion_exception&) {} } CGAL_BRANCH_PROFILER_BRANCH(tmp); @@ -114,11 +114,11 @@ public: { \ Protect_FPU_rounding p; \ try \ - { \ - Ares res = ap(BOOST_PP_ENUM(N,CGAL_VAR,c2a)); \ - if (is_certain(res)) \ - return get_certain(res); \ - } \ + { \ + Ares res = ap(BOOST_PP_ENUM(N,CGAL_VAR,c2a)); \ + if (is_certain(res)) \ + return get_certain(res); \ + } \ catch (Uncertain_conversion_exception&) {} \ } \ CGAL_BRANCH_PROFILER_BRANCH(tmp); \ diff --git a/NewKernel_d/include/CGAL/NewKernel_d/LA_eigen/LA.h b/NewKernel_d/include/CGAL/NewKernel_d/LA_eigen/LA.h index 7e1ba4c77ca..758a6260f13 100644 --- a/NewKernel_d/include/CGAL/NewKernel_d/LA_eigen/LA.h +++ b/NewKernel_d/include/CGAL/NewKernel_d/LA_eigen/LA.h @@ -39,193 +39,193 @@ namespace CGAL { // Dim_ real dimension // Max_dim_ upper bound on the dimension template struct LA_eigen { - typedef NT_ NT; - typedef Dim_ Dimension; - typedef Max_dim_ Max_dimension; - enum { dimension = Eigen_dimension::value }; - enum { max_dimension = Eigen_dimension::value }; - template< class D2, class D3=D2 > - struct Rebind_dimension { - typedef LA_eigen< NT, D2, D3 > Other; - }; - template struct Property : boost::false_type {}; - template struct Property : boost::true_type {}; - template struct Property : boost::true_type {}; - template struct Property : boost::true_type {}; + typedef NT_ NT; + typedef Dim_ Dimension; + typedef Max_dim_ Max_dimension; + enum { dimension = Eigen_dimension::value }; + enum { max_dimension = Eigen_dimension::value }; + template< class D2, class D3=D2 > + struct Rebind_dimension { + typedef LA_eigen< NT, D2, D3 > Other; + }; + template struct Property : boost::false_type {}; + template struct Property : boost::true_type {}; + template struct Property : boost::true_type {}; + template struct Property : boost::true_type {}; - typedef Eigen::Matrix::value,1,Eigen::ColMajor|Eigen::AutoAlign,Eigen_dimension::value,1> Vector; - typedef Eigen::Matrix Dynamic_vector; - typedef Construct_eigen Construct_vector; + typedef Eigen::Matrix::value,1,Eigen::ColMajor|Eigen::AutoAlign,Eigen_dimension::value,1> Vector; + typedef Eigen::Matrix Dynamic_vector; + typedef Construct_eigen Construct_vector; #if (EIGEN_WORLD_VERSION>=3) - typedef NT const* Vector_const_iterator; + typedef NT const* Vector_const_iterator; #else - typedef Iterator_from_indices Vector_const_iterator; + > Vector_const_iterator; #endif - templatestatic Vector_const_iterator vector_begin(Vec_ const&a){ + templatestatic Vector_const_iterator vector_begin(Vec_ const&a){ #if (EIGEN_WORLD_VERSION>=3) - return &a[0]; + return &a[0]; #else - return Vector_const_iterator(a,0); + return Vector_const_iterator(a,0); #endif - } + } - templatestatic Vector_const_iterator vector_end(Vec_ const&a){ + templatestatic Vector_const_iterator vector_end(Vec_ const&a){ #if (EIGEN_WORLD_VERSION>=3) - // FIXME: Isn't that dangerous if a is an expression and not a concrete vector? - return &a[0]+a.size(); + // FIXME: Isn't that dangerous if a is an expression and not a concrete vector? + return &a[0]+a.size(); #else - return Vector_const_iterator(a,a.size()); + return Vector_const_iterator(a,a.size()); #endif - } + } - typedef Eigen::Matrix Square_matrix; - typedef Eigen::Matrix Dynamic_matrix; - //TODO: don't pass on the values of Max_* for an expensive NT + typedef Eigen::Matrix Square_matrix; + typedef Eigen::Matrix Dynamic_matrix; + //TODO: don't pass on the values of Max_* for an expensive NT // typedef ... Constructor // typedef ... Accessor #if 0 - private: - template class Canonicalize_vector { - typedef typename Dimension_eigen::type S1; - typedef typename Dimension_eigen::type S2; - public: - typedef typename Vector::type type; - }; - public: + private: + template class Canonicalize_vector { + typedef typename Dimension_eigen::type S1; + typedef typename Dimension_eigen::type S2; + public: + typedef typename Vector::type type; + }; + public: #endif - templatestatic int size_of_vector(Vec_ const&v){ - return (int)v.size(); - } + templatestatic int size_of_vector(Vec_ const&v){ + return (int)v.size(); + } - templatestatic NT dot_product(Vec_ const&a,Vec_ const&b){ - return a.dot(b); - } + templatestatic NT dot_product(Vec_ const&a,Vec_ const&b){ + return a.dot(b); + } - template static int rows(Vec_ const&v) { - return (int)v.rows(); - } - template static int columns(Vec_ const&v) { - return (int)v.cols(); - } + template static int rows(Vec_ const&v) { + return (int)v.rows(); + } + template static int columns(Vec_ const&v) { + return (int)v.cols(); + } - template static CGAL_NORETURN NT determinant_aux(Mat_ const&, Tag_true) { - CGAL_error(); - } - template static NT determinant_aux(Mat_ const& m, Tag_false) { - return m.determinant(); - } - - template static NT determinant(Mat_ const&m,bool=false){ - switch(m.rows()){ - //case 0: - // return 1; - case 1: - return m(0,0); - case 2: - return CGAL::determinant( - m(0,0),m(0,1), - m(1,0),m(1,1)); - case 3: - return CGAL::determinant( - m(0,0),m(0,1),m(0,2), - m(1,0),m(1,1),m(1,2), - m(2,0),m(2,1),m(2,2)); - case 4: - return CGAL::determinant( - m(0,0),m(0,1),m(0,2),m(0,3), - m(1,0),m(1,1),m(1,2),m(1,3), - m(2,0),m(2,1),m(2,2),m(2,3), - m(3,0),m(3,1),m(3,2),m(3,3)); - case 5: - return CGAL::determinant( - m(0,0),m(0,1),m(0,2),m(0,3),m(0,4), - m(1,0),m(1,1),m(1,2),m(1,3),m(1,4), - m(2,0),m(2,1),m(2,2),m(2,3),m(2,4), - m(3,0),m(3,1),m(3,2),m(3,3),m(3,4), - m(4,0),m(4,1),m(4,2),m(4,3),m(4,4)); - case 6: - return CGAL::determinant( - m(0,0),m(0,1),m(0,2),m(0,3),m(0,4),m(0,5), - m(1,0),m(1,1),m(1,2),m(1,3),m(1,4),m(1,5), - m(2,0),m(2,1),m(2,2),m(2,3),m(2,4),m(2,5), - m(3,0),m(3,1),m(3,2),m(3,3),m(3,4),m(3,5), - m(4,0),m(4,1),m(4,2),m(4,3),m(4,4),m(4,5), - m(5,0),m(5,1),m(5,2),m(5,3),m(5,4),m(5,5)); - case 7: - return CGAL::determinant( - m(0,0),m(0,1),m(0,2),m(0,3),m(0,4),m(0,5),m(0,6), - m(1,0),m(1,1),m(1,2),m(1,3),m(1,4),m(1,5),m(1,6), - m(2,0),m(2,1),m(2,2),m(2,3),m(2,4),m(2,5),m(2,6), - m(3,0),m(3,1),m(3,2),m(3,3),m(3,4),m(3,5),m(3,6), - m(4,0),m(4,1),m(4,2),m(4,3),m(4,4),m(4,5),m(4,6), - m(5,0),m(5,1),m(5,2),m(5,3),m(5,4),m(5,5),m(5,6), - m(6,0),m(6,1),m(6,2),m(6,3),m(6,4),m(6,5),m(6,6)); - default: + template static CGAL_NORETURN NT determinant_aux(Mat_ const&, Tag_true) { + CGAL_error(); + } + template static NT determinant_aux(Mat_ const& m, Tag_false) { + return m.determinant(); + } + + template static NT determinant(Mat_ const&m,bool=false){ + switch(m.rows()){ + //case 0: + // return 1; + case 1: + return m(0,0); + case 2: + return CGAL::determinant( + m(0,0),m(0,1), + m(1,0),m(1,1)); + case 3: + return CGAL::determinant( + m(0,0),m(0,1),m(0,2), + m(1,0),m(1,1),m(1,2), + m(2,0),m(2,1),m(2,2)); + case 4: + return CGAL::determinant( + m(0,0),m(0,1),m(0,2),m(0,3), + m(1,0),m(1,1),m(1,2),m(1,3), + m(2,0),m(2,1),m(2,2),m(2,3), + m(3,0),m(3,1),m(3,2),m(3,3)); + case 5: + return CGAL::determinant( + m(0,0),m(0,1),m(0,2),m(0,3),m(0,4), + m(1,0),m(1,1),m(1,2),m(1,3),m(1,4), + m(2,0),m(2,1),m(2,2),m(2,3),m(2,4), + m(3,0),m(3,1),m(3,2),m(3,3),m(3,4), + m(4,0),m(4,1),m(4,2),m(4,3),m(4,4)); + case 6: + return CGAL::determinant( + m(0,0),m(0,1),m(0,2),m(0,3),m(0,4),m(0,5), + m(1,0),m(1,1),m(1,2),m(1,3),m(1,4),m(1,5), + m(2,0),m(2,1),m(2,2),m(2,3),m(2,4),m(2,5), + m(3,0),m(3,1),m(3,2),m(3,3),m(3,4),m(3,5), + m(4,0),m(4,1),m(4,2),m(4,3),m(4,4),m(4,5), + m(5,0),m(5,1),m(5,2),m(5,3),m(5,4),m(5,5)); + case 7: + return CGAL::determinant( + m(0,0),m(0,1),m(0,2),m(0,3),m(0,4),m(0,5),m(0,6), + m(1,0),m(1,1),m(1,2),m(1,3),m(1,4),m(1,5),m(1,6), + m(2,0),m(2,1),m(2,2),m(2,3),m(2,4),m(2,5),m(2,6), + m(3,0),m(3,1),m(3,2),m(3,3),m(3,4),m(3,5),m(3,6), + m(4,0),m(4,1),m(4,2),m(4,3),m(4,4),m(4,5),m(4,6), + m(5,0),m(5,1),m(5,2),m(5,3),m(5,4),m(5,5),m(5,6), + m(6,0),m(6,1),m(6,2),m(6,3),m(6,4),m(6,5),m(6,6)); + default: return determinant_aux(m, Boolean_tag<(Mat_::MaxRowsAtCompileTime >= 1 && Mat_::MaxRowsAtCompileTime <= 7)>()); - } - } + } + } - template static typename - Same_uncertainty_nt::type - sign_of_determinant(Mat_ const&m,bool=false) - { - return CGAL::sign(LA_eigen::determinant(m)); - } + template static typename + Same_uncertainty_nt::type + sign_of_determinant(Mat_ const&m,bool=false) + { + return CGAL::sign(LA_eigen::determinant(m)); + } - template static int rank(Mat_ const&m){ - // return m.rank(); - // This one uses sqrt so cannot be used with Gmpq - // TODO: use different algo for different NT? - // Eigen::ColPivHouseholderQR decomp(m); - Eigen::FullPivLU decomp(m); - // decomp.setThreshold(0); - return static_cast(decomp.rank()); - } + template static int rank(Mat_ const&m){ + // return m.rank(); + // This one uses sqrt so cannot be used with Gmpq + // TODO: use different algo for different NT? + // Eigen::ColPivHouseholderQR decomp(m); + Eigen::FullPivLU decomp(m); + // decomp.setThreshold(0); + return static_cast(decomp.rank()); + } - // m*a==b - template - static void solve(DV&a, DM const&m, V const& b){ - //a = m.colPivHouseholderQr().solve(b); - a = m.fullPivLu().solve(b); - } - template - static bool solve_and_check(DV&a, DM const&m, V const& b){ - //a = m.colPivHouseholderQr().solve(b); - a = m.fullPivLu().solve(b); - return b.isApprox(m*a); - } + // m*a==b + template + static void solve(DV&a, DM const&m, V const& b){ + //a = m.colPivHouseholderQr().solve(b); + a = m.fullPivLu().solve(b); + } + template + static bool solve_and_check(DV&a, DM const&m, V const& b){ + //a = m.colPivHouseholderQr().solve(b); + a = m.fullPivLu().solve(b); + return b.isApprox(m*a); + } - static Dynamic_matrix basis(Dynamic_matrix const&m){ - return m.fullPivLu().image(m); - } + static Dynamic_matrix basis(Dynamic_matrix const&m){ + return m.fullPivLu().image(m); + } - template static Vector homogeneous_add(Vec1 const&a,Vec2 const&b){ - //TODO: use compile-time size when available - int d=a.size(); - Vector v(d); - v << b[d-1]*a.topRows(d-1)+a[d-1]*b.topRows(d-1), a[d-1]*b[d-1]; - return v; - } + template static Vector homogeneous_add(Vec1 const&a,Vec2 const&b){ + //TODO: use compile-time size when available + int d=a.size(); + Vector v(d); + v << b[d-1]*a.topRows(d-1)+a[d-1]*b.topRows(d-1), a[d-1]*b[d-1]; + return v; + } - template static Vector homogeneous_sub(Vec1 const&a,Vec2 const&b){ - int d=a.size(); - Vector v(d); - v << b[d-1]*a.topRows(d-1)-a[d-1]*b.topRows(d-1), a[d-1]*b[d-1]; - return v; - } + template static Vector homogeneous_sub(Vec1 const&a,Vec2 const&b){ + int d=a.size(); + Vector v(d); + v << b[d-1]*a.topRows(d-1)-a[d-1]*b.topRows(d-1), a[d-1]*b[d-1]; + return v; + } - template static std::pair homogeneous_dot_product(Vec1 const&a,Vec2 const&b){ - int d=a.size(); - return make_pair(a.topRows(d-1).dot(b.topRows(d-1)), a[d-1]*b[d-1]); - } + template static std::pair homogeneous_dot_product(Vec1 const&a,Vec2 const&b){ + int d=a.size(); + return make_pair(a.topRows(d-1).dot(b.topRows(d-1)), a[d-1]*b[d-1]); + } }; } diff --git a/NewKernel_d/include/CGAL/NewKernel_d/Lazy_cartesian.h b/NewKernel_d/include/CGAL/NewKernel_d/Lazy_cartesian.h index fdaa08c1209..34e866ceea1 100644 --- a/NewKernel_d/include/CGAL/NewKernel_d/Lazy_cartesian.h +++ b/NewKernel_d/include/CGAL/NewKernel_d/Lazy_cartesian.h @@ -67,20 +67,20 @@ struct Lazy_cartesian_types typedef typename typeset_intersection< typename AK_::Object_list, typename EK_::Object_list - >::type Object_list; + >::type Object_list; typedef typename typeset_intersection< typename AK_::Iterator_list, typename EK_::Iterator_list - >::type Iterator_list; + >::type Iterator_list; template ::type> struct Type {}; template struct Type { - typedef Lazy< - typename Get_type::type, - typename Get_type::type, - typename Get_type::type, - E2A_> type; + typedef Lazy< + typename Get_type::type, + typename Get_type::type, + typename Get_type::type, + E2A_> type; }; template struct Type { typedef CGAL::Lazy_exact_nt::type> type; @@ -93,12 +93,12 @@ struct Lazy_cartesian_types typedef typename Select_nth_element_functor::type EF; typedef typename internal::Lazy_construction_maybe_nt< - Kernel_, AF, EF, is_NT_tag::value - >::type nth_elem; + Kernel_, AF, EF, is_NT_tag::value + >::type nth_elem; typedef Iterator_from_indices< - const typename Type::container>::type, - const V, V, nth_elem + const typename Type::container>::type, + const V, V, nth_elem > type; }; }; @@ -136,23 +136,23 @@ struct Lazy_cartesian : Dimension_base, // Check that Approximate_kernel agrees with all that... template::type> struct Functor { - typedef Null_functor type; + typedef Null_functor type; }; - //FIXME: what do we do with D here? + //FIXME: what do we do with D here? template struct Functor { - typedef typename Get_functor::type FA; - typedef typename Get_functor::type FE; - typedef Filtered_predicate2 type; + typedef typename Get_functor::type FA; + typedef typename Get_functor::type FE; + typedef Filtered_predicate2 type; }; template struct Functor { - typedef typename Get_functor::type FA; - typedef typename Get_functor::type FE; - typedef Lazy_construction_nt type; + typedef typename Get_functor::type FA; + typedef typename Get_functor::type FE; + typedef Lazy_construction_nt type; }; template struct Functor { - typedef typename Get_functor::type FA; - typedef typename Get_functor::type FE; - typedef Lazy_construction type; + typedef typename Get_functor::type FA; + typedef typename Get_functor::type FE; + typedef Lazy_construction type; }; //typedef typename Iterator::type Point_cartesian_const_iterator; @@ -160,21 +160,21 @@ struct Lazy_cartesian : Dimension_base, template struct Construct_iter : private Store_kernel { - Construct_iter(){} - Construct_iter(Kernel const&k):Store_kernel(k){} - //FIXME: pass the kernel to the functor in the iterator - typedef U result_type; - template - result_type operator()(T const& t,Begin_tag)const{ - return result_type(t,0,this->kernel()); - } - template - result_type operator()(T const& t,End_tag)const{ - return result_type(t,Self().dimension(),this->kernel()); - } + Construct_iter(){} + Construct_iter(Kernel const&k):Store_kernel(k){} + //FIXME: pass the kernel to the functor in the iterator + typedef U result_type; + template + result_type operator()(T const& t,Begin_tag)const{ + return result_type(t,0,this->kernel()); + } + template + result_type operator()(T const& t,End_tag)const{ + return result_type(t,Self().dimension(),this->kernel()); + } }; template struct Functor { - typedef Construct_iter::type>::type> type; + typedef Construct_iter::type>::type> type; }; diff --git a/NewKernel_d/include/CGAL/typeset.h b/NewKernel_d/include/CGAL/typeset.h index a08c6c48215..c18796f8a39 100644 --- a/NewKernel_d/include/CGAL/typeset.h +++ b/NewKernel_d/include/CGAL/typeset.h @@ -47,7 +47,7 @@ namespace CGAL { std::conditional< contains::value, typeset, - typeset + typeset >::type; }; template<> struct typeset<> { @@ -107,11 +107,11 @@ namespace CGAL { typedef typename typeset_intersection_::type U; typedef typename #ifdef CGAL_CXX11 - std::conditional::value, + std::conditional::value, #else - boost::mpl::if_, + boost::mpl::if_, #endif - typename U::template add::type, U>::type type; + typename U::template add::type, U>::type type; }; template struct typeset_intersection_, T> : typeset<> {}; template struct typeset_intersection_ : T {}; From 0040436ae3e7eab54ecb618db78cd97ac71e3c36 Mon Sep 17 00:00:00 2001 From: Andreas Fabri Date: Fri, 27 Mar 2020 10:57:48 +0100 Subject: [PATCH 187/568] Add non-recursive determinant for 7x7 matrix --- Kernel_23/include/CGAL/determinant.h | 301 ++++++++++++++++++----- Kernel_23/test/Kernel_23/determinant.cpp | 15 ++ 2 files changed, 258 insertions(+), 58 deletions(-) create mode 100644 Kernel_23/test/Kernel_23/determinant.cpp diff --git a/Kernel_23/include/CGAL/determinant.h b/Kernel_23/include/CGAL/determinant.h index e5e66e5e141..cce36365429 100644 --- a/Kernel_23/include/CGAL/determinant.h +++ b/Kernel_23/include/CGAL/determinant.h @@ -205,77 +205,262 @@ determinant( template RT determinant( - const RT& a00, const RT& a01, const RT& a02, const RT& a03, const RT& a04, - const RT& a05, const RT& a06, - const RT& a10, const RT& a11, const RT& a12, const RT& a13, const RT& a14, - const RT& a15, const RT& a16, - const RT& a20, const RT& a21, const RT& a22, const RT& a23, const RT& a24, - const RT& a25, const RT& a26, - const RT& a30, const RT& a31, const RT& a32, const RT& a33, const RT& a34, - const RT& a35, const RT& a36, - const RT& a40, const RT& a41, const RT& a42, const RT& a43, const RT& a44, - const RT& a45, const RT& a46, - const RT& a50, const RT& a51, const RT& a52, const RT& a53, const RT& a54, - const RT& a55, const RT& a56, - const RT& a60, const RT& a61, const RT& a62, const RT& a63, const RT& a64, - const RT& a65, const RT& a66) + const RT& a00, const RT& a01, const RT& a02, const RT& a03, const RT& a04, const RT& a05, const RT& a06, + const RT& a10, const RT& a11, const RT& a12, const RT& a13, const RT& a14, const RT& a15, const RT& a16, + const RT& a20, const RT& a21, const RT& a22, const RT& a23, const RT& a24, const RT& a25, const RT& a26, + const RT& a30, const RT& a31, const RT& a32, const RT& a33, const RT& a34, const RT& a35, const RT& a36, + const RT& a40, const RT& a41, const RT& a42, const RT& a43, const RT& a44, const RT& a45, const RT& a46, + const RT& a50, const RT& a51, const RT& a52, const RT& a53, const RT& a54, const RT& a55, const RT& a56, + const RT& a60, const RT& a61, const RT& a62, const RT& a63, const RT& a64, const RT& a65, const RT& a66) { - return a00 * determinant( - a11, a12, a13, a14, a15, a16, - a21, a22, a23, a24, a25, a26, - a31, a32, a33, a34, a35, a36, - a41, a42, a43, a44, a45, a46, - a51, a52, a53, a54, a55, a56, - a61, a62, a63, a64, a65, a66) +// First compute the det2x2 + const RT m01 = a00*a11 - a10*a01; + const RT m02 = a00*a21 - a20*a01; + const RT m03 = a00*a31 - a30*a01; + const RT m04 = a00*a41 - a40*a01; + const RT m05 = a00*a51 - a50*a01; + const RT m06 = a00*a61 - a60*a01; + + const RT m12 = a10*a21 - a20*a11; + const RT m13 = a10*a31 - a30*a11; + const RT m14 = a10*a41 - a40*a11; + const RT m15 = a10*a51 - a50*a11; + const RT m16 = a10*a61 - a60*a11; + + const RT m23 = a20*a31 - a30*a21; + const RT m24 = a20*a41 - a40*a21; + const RT m25 = a20*a51 - a50*a21; + const RT m26 = a20*a61 - a60*a21; - - a10 * determinant(a01, a02, a03, a04, a05, a06, + const RT m34 = a30*a41 - a40*a31; + const RT m35 = a30*a51 - a50*a31; + const RT m36 = a30*a61 - a60*a31; + + const RT m45 = a40*a51 - a50*a41; + const RT m46 = a40*a61 - a60*a41; - a21, a22, a23, a24, a25, a26, - a31, a32, a33, a34, a35, a36, - a41, a42, a43, a44, a45, a46, - a51, a52, a53, a54, a55, a56, - a61, a62, a63, a64, a65, a66) + const RT m56 = a50*a61 - a60*a51; + +// Now compute the minors of rank 3 + const RT m012 = m01*a22 - m02*a12 + m12*a02; + const RT m013 = m01*a32 - m03*a12 + m13*a02; + const RT m014 = m01*a42 - m04*a12 + m14*a02; + const RT m015 = m01*a52 - m05*a12 + m15*a02; + const RT m016 = m01*a62 - m06*a12 + m16*a02; + + const RT m023 = m02*a32 - m03*a22 + m23*a02; + const RT m024 = m02*a42 - m04*a22 + m24*a02; + const RT m025 = m02*a52 - m05*a22 + m25*a02; + const RT m026 = m02*a62 - m06*a22 + m26*a02; + const RT m034 = m03*a42 - m04*a32 + m34*a02; + const RT m035 = m03*a52 - m05*a32 + m35*a02; + const RT m036 = m03*a62 - m06*a32 + m36*a02; + + const RT m045 = m04*a52 - m05*a42 + m45*a02; + const RT m046 = m04*a62 - m06*a42 + m46*a02; + + const RT m056 = m05*a62 - m06*a52 + m56*a02; - + a20 * determinant(a01, a02, a03, a04, a05, a06, - a11, a12, a13, a14, a15, a16, + + const RT m123 = m12*a32 - m13*a22 + m23*a12; + const RT m124 = m12*a42 - m14*a22 + m24*a12; + const RT m125 = m12*a52 - m15*a22 + m25*a12; + const RT m126 = m12*a62 - m16*a22 + m26*a12; + + const RT m134 = m13*a42 - m14*a32 + m34*a12; + const RT m135 = m13*a52 - m15*a32 + m35*a12; + const RT m136 = m13*a62 - m16*a32 + m36*a12; + + const RT m145 = m14*a52 - m15*a42 + m45*a12; + const RT m146 = m14*a62 - m16*a42 + m46*a12; - a31, a32, a33, a34, a35, a36, - a41, a42, a43, a44, a45, a46, - a51, a52, a53, a54, a55, a56, - a61, a62, a63, a64, a65, a66) + const RT m156 = m15*a62 - m16*a52 + m56*a12; + + const RT m234 = m23*a42 - m24*a32 + m34*a22; + const RT m235 = m23*a52 - m25*a32 + m35*a22; + const RT m236 = m23*a62 - m26*a32 + m36*a22; + + const RT m245 = m24*a52 - m25*a42 + m45*a22; + const RT m246 = m24*a62 - m26*a42 + m46*a22; - - a30 * determinant(a01, a02, a03, a04, a05, a06, - a11, a12, a13, a14, a15, a16, - a21, a22, a23, a24, a25, a26, + const RT m256 = m25*a62 - m26*a52 + m56*a22; + + const RT m345 = m34*a52 - m35*a42 + m45*a32; + const RT m346 = m34*a62 - m36*a42 + m46*a32; + + const RT m356 = m35*a62 - m36*a52 + m56*a32; + + const RT m456 = m45*a62 - m46*a52 + m56*a42; + +// Now compute the minors of rank 4 + const RT m0123 = m012*a33 - m013*a23 + m023*a13 - m123*a03; - a41, a42, a43, a44, a45, a46, - a51, a52, a53, a54, a55, a56, - a61, a62, a63, a64, a65, a66) + const RT m0124 = m012*a43 - m014*a23 + m024*a13 - m124*a03; + const RT m0125 = m012*a53 - m015*a23 + m025*a13 - m125*a03; + const RT m0126 = m012*a63 - m016*a23 + m026*a13 - m126*a03; - + a40 * determinant(a01, a02, a03, a04, a05, a06, - a11, a12, a13, a14, a15, a16, - a21, a22, a23, a24, a25, a26, - a31, a32, a33, a34, a35, a36, + const RT m0134 = m013*a43 - m014*a33 + m034*a13 - m134*a03; + const RT m0135 = m013*a53 - m015*a33 + m035*a13 - m135*a03; + const RT m0136 = m013*a63 - m016*a33 + m036*a13 - m136*a03; - a51, a52, a53, a54, a55, a56, - a61, a62, a63, a64, a65, a66) + const RT m0145 = m014*a53 - m015*a43 + m045*a13 - m145*a03; + const RT m0146 = m014*a63 - m016*a43 + m046*a13 - m146*a03; + + const RT m0156 = m015*a63 - m016*a53 + m056*a13 - m156*a03; - - a50 * determinant(a01, a02, a03, a04, a05, a06, - a11, a12, a13, a14, a15, a16, - a21, a22, a23, a24, a25, a26, - a31, a32, a33, a34, a35, a36, - a41, a42, a43, a44, a45, a46, + const RT m0234 = m023*a43 - m024*a33 + m034*a23 - m234*a03; + const RT m0235 = m023*a53 - m025*a33 + m035*a23 - m235*a03; + const RT m0236 = m023*a63 - m026*a33 + m036*a23 - m236*a03; + + const RT m0245 = m024*a53 - m025*a43 + m045*a23 - m245*a03; + const RT m0246 = m024*a63 - m026*a43 + m046*a23 - m246*a03; + + const RT m0256 = m025*a63 - m026*a53 + m056*a23 - m256*a03; - a61, a62, a63, a64, a65, a66) + const RT m0345 = m034*a53 - m035*a43 + m045*a33 - m345*a03; + const RT m0346 = m034*a63 - m036*a43 + m046*a33 - m346*a03; + + const RT m0356 = m035*a63 - m036*a53 + m056*a33 - m356*a03; - + a60 * determinant(a01, a02, a03, a04, a05, a06, - a11, a12, a13, a14, a15, a16, - a21, a22, a23, a24, a25, a26, - a31, a32, a33, a34, a35, a36, - a41, a42, a43, a44, a45, a46, - a51, a52, a53, a54, a55, a56 + const RT m0456 = m045*a63 - m046*a53 + m056*a43 - m456*a03; + + const RT m1234 = m123*a43 - m124*a33 + m134*a23 - m234*a13; + const RT m1235 = m123*a53 - m125*a33 + m135*a23 - m235*a13; + const RT m1236 = m123*a63 - m126*a33 + m136*a23 - m236*a13; + + const RT m1245 = m124*a53 - m125*a43 + m145*a23 - m245*a13; + const RT m1246 = m124*a63 - m126*a43 + m146*a23 - m246*a13; + + const RT m1256 = m125*a63 - m126*a53 + m156*a23 - m256*a13; - ); + const RT m1345 = m134*a53 - m135*a43 + m145*a33 - m345*a13; + const RT m1346 = m134*a63 - m136*a43 + m146*a33 - m346*a13; + + const RT m1356 = m135*a63 - m136*a53 + m156*a33 - m356*a13; + const RT m1456 = m145*a63 - m146*a53 + m156*a43 - m456*a13; + + const RT m2345 = m234*a53 - m235*a43 + m245*a33 - m345*a23; + const RT m2346 = m234*a63 - m236*a43 + m246*a33 - m346*a23; + + const RT m2356 = m235*a63 - m236*a53 + m256*a33 - m356*a23; + const RT m2456 = m245*a63 - m246*a53 + m256*a43 - m456*a23; + + const RT m3456 = m345*a63 - m346*a53 + m356*a43 - m456*a33; + + + // Now compute the minors of rank 5 + const RT m01234 = m0123*a44 - m0124*a34 + m0134*a24 - m0234*a14 + m1234*a04; + + const RT m01235 = m0123*a54 - m0125*a34 + m0135*a24 - m0235*a14 + m1235*a04; + + const RT m01236 = m0123*a64 - m0126*a34 + m0136*a24 - m0236*a14 + m1236*a04; + + const RT m01245 = m0124*a54 - m0125*a44 + m0145*a24 - m0245*a14 + m1245*a04; + const RT m01246 = m0124*a64 - m0126*a44 + m0146*a24 - m0246*a14 + m1246*a04; + + const RT m01256 = m0125*a64 - m0126*a54 + m0156*a24 - m0256*a14 + m1256*a04; + + const RT m01345 = m0134*a54 - m0135*a44 + m0145*a34 - m0345*a14 + m1345*a04; + const RT m01346 = m0134*a64 - m0136*a44 + m0146*a34 - m0346*a14 + m1346*a04; + + const RT m01356 = m0135*a64 - m0136*a54 + m0156*a34 - m0356*a14 + m1356*a04; + const RT m01456 = m0145*a64 - m0146*a54 + m0156*a44 - m0456*a14 + m1456*a04; + + const RT m02345 = m0234*a54 - m0235*a44 + m0245*a34 - m0345*a24 + m2345*a04; + const RT m02346 = m0234*a64 - m0236*a44 + m0246*a34 - m0346*a24 + m2346*a04; + + const RT m02356 = m0235*a64 - m0236*a54 + m0256*a34 - m0356*a24 + m2356*a04; + const RT m02456 = m0245*a64 - m0246*a54 + m0256*a44 - m0456*a24 + m2456*a04; + const RT m03456 = m0345*a64 - m0346*a54 + m0356*a44 - m0456*a34 + m3456*a04; + + const RT m12345 = m1234*a54 - m1235*a44 + m1245*a34 - m1345*a24 + m2345*a14; + const RT m12346 = m1234*a64 - m1236*a44 + m1246*a34 - m1346*a24 + m2346*a14; + + + const RT m12356 = m1235*a64 - m1236*a54 + m1256*a34 - m1356*a24 + m2356*a14; + const RT m12456 = m1245*a64 - m1246*a54 + m1256*a44 - m1456*a24 + m2456*a14; + const RT m13456 = m1345*a64 - m1346*a54 + m1356*a44 - m1456*a34 + m3456*a14; + + const RT m23456 = m2345*a64 - m2346*a54 + m2356*a44 - m2456*a34 + m3456*a24; + +// Now compute the minors of rank 6 + const RT m012345 = m01234*a55 - m01235*a45 + m01245*a35 - m01345*a25 + m02345*a15 - m12345*a05; + const RT m012346 = m01234*a65 - m01236*a45 + m01246*a35 - m01346*a25 + m02346*a15 - m12346*a05; + const RT m012356 = m01235*a65 - m01236*a55 + m01256*a35 - m01356*a25 + m02356*a15 - m12356*a05; + const RT m012456 = m01245*a65 - m01246*a55 + m01256*a45 - m01456*a25 + m02456*a15 - m12456*a05; + const RT m013456 = m01345*a65 - m01346*a55 + m01356*a45 - m01456*a35 + m03456*a15 - m13456*a05; + const RT m023456 = m02345*a65 - m02346*a55 + m02356*a45 - m02456*a35 + m03456*a25 - m23456*a05; + const RT m123456 = m12345*a65 - m12346*a55 + m12356*a45 - m12456*a35 + m13456*a25 - m23456*a15; + + + // Now compute the minors of rank 7 + const RT m0123456 = m012345 * a66 - m012346 * a56 + m012356 * a46 - m012456 * a36 + m013456 * a26 - m023456 * a16 + m123456 * a06; + +#ifdef CGAL_CHECK_DETERMINANT + + { + const RT r1 = a06 * determinant( + a10, a11, a12, a13, a14, a15, + a20, a21, a22, a23, a24, a25, + a30, a31, a32, a33, a34, a35, + a40, a41, a42, a43, a44, a45, + a50, a51, a52, a53, a54, a55, + a60, a61, a62, a63, a64, a65); + + const RT r2 = - a16 * determinant(a00, a01, a02, a03, a04, a05, + + a20, a21, a22, a23, a24, a25, + a30, a31, a32, a33, a34, a35, + a40, a41, a42, a43, a44, a45, + a50, a51, a52, a53, a54, a55, + a60, a61, a62, a63, a64, a65); + + const RT r3= a26 * determinant(a00, a01, a02, a03, a04, a05, + a10, a11, a12, a13, a14, a15, + + a30, a31, a32, a33, a34, a35, + a40, a41, a42, a43, a44, a45, + a50, a51, a52, a53, a54, a55, + a60, a61, a62, a63, a64, a65); + + const RT r4 = - a36 * determinant(a00, a01, a02, a03, a04, a05, + a10, a11, a12, a13, a14, a15, + a20, a21, a22, a23, a24, a25, + + a40, a41, a42, a43, a44, a45, + a50, a51, a52, a53, a54, a55, + a60, a61, a62, a63, a64, a65); + + const RT r5 = a46 * determinant(a00, a01, a02, a03, a04, a05, + a10, a11, a12, a13, a14, a15, + a20, a21, a22, a23, a24, a25, + a30, a31, a32, a33, a34, a35, + + a50, a51, a52, a53, a54, a55, + a60, a61, a62, a63, a64, a65); + + const RT r6 = - a56 * determinant(a00, a01, a02, a03, a04, a05, + a10, a11, a12, a13, a14, a15, + a20, a21, a22, a23, a24, a25, + a30, a31, a32, a33, a34, a35, + a40, a41, a42, a43, a44, a45, + + a60, a61, a62, a63, a64, a65); + + const RT r7 = a66 * determinant(a00, a01, a02, a03, a04, a05, + a10, a11, a12, a13, a14, a15, + a20, a21, a22, a23, a24, a25, + a30, a31, a32, a33, a34, a35, + a40, a41, a42, a43, a44, a45, + a50, a51, a52, a53, a54, a55 + ); + + const RT rt = r1 + r2 + r3 + r4 + r5 + r6 + r7; + CGAL_assertion(rt == m0123456); + } +#endif + + return m0123456; } diff --git a/Kernel_23/test/Kernel_23/determinant.cpp b/Kernel_23/test/Kernel_23/determinant.cpp new file mode 100644 index 00000000000..ba11ec6fef2 --- /dev/null +++ b/Kernel_23/test/Kernel_23/determinant.cpp @@ -0,0 +1,15 @@ +#define CGAL_CHECK_DETERMINANT + +#include + +int main() +{ + assert(CGAL::determinant(4, 5, 1, 4, 6, 3, 1, + 4, 3, 6, 4, 2, 7, 3, + 6, 3, 3, 6, 2, 4, 5, + 1, 4, 3, 5, 5, 6 ,1, + 1, 3, 2, 7, 9, 6, 1, + 7, 6, 5, 4, 6, 2, 2, + 2, 3, 5, 7, 4, 3, 3) == 763); + return 0; +} From a0ee6b7ca91f6e60784c813350156b41cb4dfa71 Mon Sep 17 00:00:00 2001 From: Jane Tournois Date: Fri, 27 Mar 2020 15:05:27 +0100 Subject: [PATCH 188/568] use more boost::optional --- .../internal/smooth_vertices.h | 50 ++++++++----------- 1 file changed, 20 insertions(+), 30 deletions(-) diff --git a/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/smooth_vertices.h b/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/smooth_vertices.h index 8b1052212ce..64a1b681de2 100644 --- a/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/smooth_vertices.h +++ b/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/smooth_vertices.h @@ -266,18 +266,11 @@ namespace CGAL #endif } - bool project(const Surface_patch_index& si, - const Vector_3& gi, - Vector_3& projected_point) + boost::optional project(const Surface_patch_index& si, + const Vector_3& gi) { - if (subdomain_FMLS_indices.find(si) == subdomain_FMLS_indices.end()) - return false; - - if (std::isnan(gi.x()) || std::isnan(gi.y()) || isnan(gi.z())) - { - std::cout << "Initial point error " << gi << std::endl; - return false; - } + CGAL_assertion(subdomain_FMLS_indices.find(si) != subdomain_FMLS_indices.end()); + CGAL_assertion(!std::isnan(gi.x()) && !std::isnan(gi.y()) && !std::isnan(gi.z())); Vec3Df point(gi.x(), gi.y(), gi.z()); Vec3Df res_normal; @@ -300,13 +293,11 @@ namespace CGAL if (std::isnan(result[0]) || std::isnan(result[1]) || std::isnan(result[2])) { std::cout << "MLS error detected si size " << si << " : " << fmls.getPNSize() << std::endl; - return false; + return {}; } } while ((result - point).getSquaredLength() > sq_eps&& ++it_nb < max_it_nb); - projected_point = Vector_3(result[0], result[1], result[2]); - - return true; + return Vector_3(result[0], result[1], result[2]); } void collect_vertices_surface_indices( @@ -430,10 +421,9 @@ namespace CGAL Vector_3 normal_projection = project_on_tangent_plane(smoothed_position, current_pos, vertices_normals[v][si]); - //Check if the mls surface exists to avoid degenrated cases - Vector_3 mls_projection; - if (project(si, normal_projection, mls_projection)) { - final_position = final_position + mls_projection; + //Check if the mls surface exists to avoid degenerated cases + if (boost::optional mls_projection = project(si, normal_projection)) { + final_position = final_position + *mls_projection; } else { final_position = final_position + normal_projection; @@ -465,9 +455,8 @@ namespace CGAL { //Check if the mls surface exists to avoid degenerated cases - Vector_3 mls_projection; - if (project(si, current_pos, mls_projection)) { - final_position = final_position + mls_projection; + if (boost::optional mls_projection = project(si, current_pos)) { + final_position = final_position + *mls_projection; } else { final_position = final_position + current_pos; @@ -542,11 +531,11 @@ namespace CGAL CGAL_assertion(si != Surface_patch_index()); Vector_3 normal_projection = project_on_tangent_plane(smoothed_position, - current_pos, - vertices_normals[v][si]); - Vector_3 mls_projection; - if (project(si, normal_projection, mls_projection)) - final_position = mls_projection; + current_pos, + vertices_normals[v][si]); + + if (boost::optional mls_projection = project(si, normal_projection)) + final_position = final_position + *mls_projection; else final_position = smoothed_position; @@ -562,9 +551,10 @@ namespace CGAL CGAL_assertion(si != Surface_patch_index()); const Vector_3 current_pos(CGAL::ORIGIN, point(v->point())); - Vector_3 mls_projection; - if (project(si, current_pos, mls_projection)) { - const typename Tr::Point new_pos(CGAL::ORIGIN + mls_projection); + + if (boost::optional mls_projection = project(si, current_pos)) + { + const typename Tr::Point new_pos(CGAL::ORIGIN + *mls_projection); v->set_point(new_pos); #ifdef CGAL_TETRAHEDRAL_REMESHING_DEBUG From 04adcb982f01752f014ebc6817e38e456b1df411 Mon Sep 17 00:00:00 2001 From: Efi Fogel Date: Sun, 29 Mar 2020 12:34:33 +0300 Subject: [PATCH 189/568] Cleaned up --- .../include/CGAL/Arr_segment_traits_2.h | 510 ++++++++---------- 1 file changed, 228 insertions(+), 282 deletions(-) diff --git a/Arrangement_on_surface_2/include/CGAL/Arr_segment_traits_2.h b/Arrangement_on_surface_2/include/CGAL/Arr_segment_traits_2.h index a9f3506ea29..dc43ac8fa0e 100644 --- a/Arrangement_on_surface_2/include/CGAL/Arr_segment_traits_2.h +++ b/Arrangement_on_surface_2/include/CGAL/Arr_segment_traits_2.h @@ -7,9 +7,9 @@ // $Id$ // SPDX-License-Identifier: GPL-3.0-or-later OR LicenseRef-Commercial // -// Author(s) : Ron Wein -// Efi Fogel -// Waqar Khan +// Author(s): Ron Wein +// Efi Fogel +// Waqar Khan #ifndef CGAL_ARR_SEGMENT_TRAITS_2_H #define CGAL_ARR_SEGMENT_TRAITS_2_H @@ -32,11 +32,10 @@ namespace CGAL { -template +template class Arr_segment_2; -/*! - * \class A traits class for maintaining an arrangement of segments, avoiding +/*! \class A traits class for maintaining an arrangement of segments, avoiding * cascading of computations as much as possible. * * The class is derived from the parameterized kernel to extend the traits @@ -79,17 +78,17 @@ public: typedef typename Kernel::Point_2 Point_2; protected: - Line_2 l; // The line that supports the segment. - Point_2 ps; // The source point of the segment. - Point_2 pt; // The target point of the segment. - bool is_pt_max; // Is the target (lexicographically) larger - // than the source. - bool is_vert; // Is this a vertical segment. - bool is_degen; // Is the segment degenerate (a single point). + Line_2 m_l; // The line that supports the segment. + Point_2 m_ps; // The source point of the segment. + Point_2 m_pt; // The target point of the segment. + bool m_is_pt_max; // Is the target (lexicographically) larger + // than the source. + bool m_is_vert; // Is this a vertical segment. + bool m_is_degen; // Is the segment degenerate (a single point). public: /*! Default constructor. */ - _Segment_cached_2() : is_vert(false), is_degen(true) {} + _Segment_cached_2() : m_is_vert(false), m_is_degen(true) {} /*! Constructor from a segment. * \param seg The segment. @@ -97,50 +96,46 @@ public: */ _Segment_cached_2(const Segment_2& seg) { - Kernel kernel; + Kernel kernel; + auto construct_vertex = kernel.construct_vertex_2_object(); - typename Kernel_::Construct_vertex_2 - construct_vertex = kernel.construct_vertex_2_object(); + m_ps = construct_vertex(seg, 0); + m_pt = construct_vertex(seg, 1); - ps = construct_vertex(seg, 0); - pt = construct_vertex(seg, 1); + Comparison_result res = kernel.compare_xy_2_object()(m_ps, m_pt); + m_is_degen = (res == EQUAL); + m_is_pt_max = (res == SMALLER); - Comparison_result res = kernel.compare_xy_2_object()(ps, pt); - is_degen = (res == EQUAL); - is_pt_max = (res == SMALLER); - - CGAL_precondition_msg (! is_degen, + CGAL_precondition_msg (! m_is_degen, "Cannot construct a degenerate segment."); - l = kernel.construct_line_2_object()(seg); - is_vert = kernel.is_vertical_2_object()(seg); + m_l = kernel.construct_line_2_object()(seg); + m_is_vert = kernel.is_vertical_2_object()(seg); } - /*! - * Construct a segment from two end-points. + /*! Construct a segment from two end-points. * \param source The source point. * \param target The target point. * \param The two points must not be equal. */ _Segment_cached_2(const Point_2& source, const Point_2& target) : - ps(source), - pt(target) + m_ps(source), + m_pt(target) { - Kernel kernel; + Kernel kernel; - Comparison_result res = kernel.compare_xy_2_object()(ps, pt); - is_degen = (res == EQUAL); - is_pt_max = (res == SMALLER); + Comparison_result res = kernel.compare_xy_2_object()(m_ps, m_pt); + m_is_degen = (res == EQUAL); + m_is_pt_max = (res == SMALLER); - CGAL_precondition_msg(! is_degen, + CGAL_precondition_msg(! m_is_degen, "Cannot construct a degenerate segment."); - l = kernel.construct_line_2_object()(source, target); - is_vert = kernel.is_vertical_2_object()(l); + m_l = kernel.construct_line_2_object()(source, target); + m_is_vert = kernel.is_vertical_2_object()(m_l); } - /*! - * Construct a segment from two end-points on a supporting line. + /*! Construct a segment from two end-points on a supporting line. * \param supp_line The supporting line. * \param source The source point. * \param target The target point. @@ -148,60 +143,56 @@ public: */ _Segment_cached_2(const Line_2& supp_line, const Point_2& source, const Point_2& target) : - l(supp_line), - ps(source), - pt(target) + m_l(supp_line), + m_ps(source), + m_pt(target) { - Kernel kernel; + Kernel kernel; - CGAL_precondition( - Segment_assertions::_assert_is_point_on(source, l, - Has_exact_division()) && - Segment_assertions::_assert_is_point_on(target,l, - Has_exact_division()) - ); + CGAL_precondition + (Segment_assertions::_assert_is_point_on(source, m_l, + Has_exact_division()) && + Segment_assertions::_assert_is_point_on(target, m_l, + Has_exact_division())); - is_vert = kernel.is_vertical_2_object()(l); + m_is_vert = kernel.is_vertical_2_object()(m_l); - Comparison_result res = kernel.compare_xy_2_object()(ps, pt); - is_degen = (res == EQUAL); - is_pt_max = (res == SMALLER); + Comparison_result res = kernel.compare_xy_2_object()(m_ps, m_pt); + m_is_degen = (res == EQUAL); + m_is_pt_max = (res == SMALLER); - CGAL_precondition_msg(! is_degen, + CGAL_precondition_msg(! m_is_degen, "Cannot construct a degenerate segment."); } - /*! - * Assignment operator. + /*! Assignment operator. * \param seg the source segment to copy from * \pre The segment is not degenerate. */ - const _Segment_cached_2& operator= (const Segment_2& seg) + const _Segment_cached_2& operator=(const Segment_2& seg) { - Kernel kernel; + Kernel kernel; + auto construct_vertex = kernel.construct_vertex_2_object(); - typename Kernel_::Construct_vertex_2 - construct_vertex = kernel.construct_vertex_2_object(); + m_ps = construct_vertex(seg, 0); + m_pt = construct_vertex(seg, 1); - ps = construct_vertex(seg, 0); - pt = construct_vertex(seg, 1); + Comparison_result res = kernel.compare_xy_2_object()(m_ps, m_pt); + m_is_degen = (res == EQUAL); + m_is_pt_max = (res == SMALLER); - Comparison_result res = kernel.compare_xy_2_object()(ps, pt); - is_degen = (res == EQUAL); - is_pt_max = (res == SMALLER); - - CGAL_precondition_msg(! is_degen, + CGAL_precondition_msg(! m_is_degen, "Cannot construct a degenerate segment."); - l = kernel.construct_line_2_object()(seg); - is_vert = kernel.is_vertical_2_object()(seg); + m_l = kernel.construct_line_2_object()(seg); + m_is_vert = kernel.is_vertical_2_object()(seg); return (*this); } /*! Obtain the (lexicographically) left endpoint. */ - const Point_2& left() const { return (is_pt_max ? ps : pt); } + const Point_2& left() const { return (m_is_pt_max ? m_ps : m_pt); } /*! Set the (lexicographically) left endpoint. * \param p The point to set. @@ -209,22 +200,19 @@ public: */ void set_left(const Point_2& p) { - CGAL_precondition (! is_degen); - CGAL_precondition_code ( - Kernel kernel; - ); + CGAL_precondition(! m_is_degen); + CGAL_precondition_code(Kernel kernel); CGAL_precondition - (Segment_assertions::_assert_is_point_on (p, l, - Has_exact_division()) && - kernel.compare_xy_2_object() (p, right()) == SMALLER); + (Segment_assertions::_assert_is_point_on(p, m_l, Has_exact_division()) && + (kernel.compare_xy_2_object()(p, right()) == SMALLER)); - if (is_pt_max) ps = p; - else pt = p; + if (m_is_pt_max) m_ps = p; + else m_pt = p; } /*! Obtain the (lexicographically) right endpoint. */ - const Point_2& right() const { return (is_pt_max ? pt : ps); } + const Point_2& right() const { return (m_is_pt_max ? m_pt : m_ps); } /*! Set the (lexicographically) right endpoint. * \param p The point to set. @@ -232,38 +220,35 @@ public: */ void set_right(const Point_2& p) { - CGAL_precondition(! is_degen); - CGAL_precondition_code( - Kernel kernel; - ); + CGAL_precondition(! m_is_degen); + CGAL_precondition_code(Kernel kernel); CGAL_precondition - (Segment_assertions::_assert_is_point_on (p, l, - Has_exact_division()) && - kernel.compare_xy_2_object() (p, left()) == LARGER); + (Segment_assertions::_assert_is_point_on(p, m_l, Has_exact_division()) && + (kernel.compare_xy_2_object()(p, left()) == LARGER)); - if (is_pt_max) pt = p; - else ps = p; + if (m_is_pt_max) m_pt = p; + else m_ps = p; } /*! Obtain the supporting line. */ const Line_2& line() const { - CGAL_precondition(! is_degen); - return (l); + CGAL_precondition(! m_is_degen); + return m_l; } /*! Determine whether the curve is vertical. */ bool is_vertical() const { - CGAL_precondition(! is_degen); - return (is_vert); + CGAL_precondition(! m_is_degen); + return m_is_vert; } /*! Determine whether the curve is directed lexicographic from left to right */ - bool is_directed_right() const { return (is_pt_max); } + bool is_directed_right() const { return (m_is_pt_max); } /*! Determine whether the given point is in the x-range of the segment. * \param p The query point. @@ -271,12 +256,12 @@ public: */ bool is_in_x_range(const Point_2& p) const { - Kernel kernel; - typename Kernel_::Compare_x_2 compare_x = kernel.compare_x_2_object(); - const Comparison_result res1 = compare_x(p, left()); + Kernel kernel; + typename Kernel_::Compare_x_2 compare_x = kernel.compare_x_2_object(); + const Comparison_result res1 = compare_x(p, left()); - if (res1 == SMALLER) return (false); - else if (res1 == EQUAL) return (true); + if (res1 == SMALLER) return false; + else if (res1 == EQUAL) return true; const Comparison_result res2 = compare_x(p, right()); return (res2 != LARGER); @@ -288,14 +273,14 @@ public: */ bool is_in_y_range(const Point_2& p) const { - Kernel kernel; - typename Kernel_::Compare_y_2 compare_y = kernel.compare_y_2_object(); - const Comparison_result res1 = compare_y (p, left()); + Kernel kernel; + typename Kernel_::Compare_y_2 compare_y = kernel.compare_y_2_object(); + const Comparison_result res1 = compare_y(p, left()); - if (res1 == SMALLER) return (false); - else if (res1 == EQUAL) return (true); + if (res1 == SMALLER) return false; + else if (res1 == EQUAL) return true; - const Comparison_result res2 = compare_y (p, right()); + const Comparison_result res2 = compare_y(p, right()); return (res2 != LARGER); } }; @@ -329,23 +314,21 @@ public: friend class Arr_segment_traits_2; public: - /*! - * Compare the x-coordinates of two points. + /*! Compare the x-coordinates of two points. * \param p1 The first point. * \param p2 The second point. * \return LARGER if x(p1) > x(p2); * SMALLER if x(p1) < x(p2); * EQUAL if x(p1) = x(p2). */ - Comparison_result operator() (const Point_2& p1, const Point_2& p2) const + Comparison_result operator()(const Point_2& p1, const Point_2& p2) const { const Kernel& kernel = m_traits; - return (kernel.compare_x_2_object()(p1, p2)); } }; - /*! Get a Compare_x_2 functor object. */ + /*! Obtain a Compare_x_2 functor object. */ Compare_x_2 compare_x_2_object() const { return Compare_x_2(*this); } class Compare_xy_2 { @@ -363,8 +346,7 @@ public: friend class Arr_segment_traits_2; public: - /*! - * Compare two points lexicographically: by x, then by y. + /*! Compare two points lexicographically: by x, then by y. * \param p1 The first point. * \param p2 The second point. * \return LARGER if x(p1) > x(p2), or if x(p1) = x(p2) and y(p1) > y(p2); @@ -378,13 +360,12 @@ public: } }; - /*! Get a Compare_xy_2 functor object. */ + /*! Obtain a Compare_xy_2 functor object. */ Compare_xy_2 compare_xy_2_object() const { return Compare_xy_2(*this); } class Construct_min_vertex_2 { public: - /*! - * Get the left endpoint of the x-monotone curve (segment). + /*! Obtain the left endpoint of the x-monotone curve (segment). * \param cv The curve. * \return The left endpoint. */ @@ -392,29 +373,27 @@ public: { return (cv.left()); } }; - /*! Get a Construct_min_vertex_2 functor object. */ + /*! Obtain a Construct_min_vertex_2 functor object. */ Construct_min_vertex_2 construct_min_vertex_2_object() const { return Construct_min_vertex_2(); } class Construct_max_vertex_2 { public: - /*! - * Get the right endpoint of the x-monotone curve (segment). + /*! Obtain the right endpoint of the x-monotone curve (segment). * \param cv The curve. * \return The right endpoint. */ - const Point_2& operator() (const X_monotone_curve_2& cv) const + const Point_2& operator()(const X_monotone_curve_2& cv) const { return (cv.right()); } }; - /*! Get a Construct_max_vertex_2 functor object. */ + /*! Obtain a Construct_max_vertex_2 functor object. */ Construct_max_vertex_2 construct_max_vertex_2_object() const { return Construct_max_vertex_2(); } class Is_vertical_2 { public: - /*! - * Check whether the given x-monotone curve is a vertical segment. + /*! Check whether the given x-monotone curve is a vertical segment. * \param cv The curve. * \return (true) if the curve is a vertical segment; (false) otherwise. */ @@ -422,9 +401,8 @@ public: { return (cv.is_vertical()); } }; - /*! Get an Is_vertical_2 functor object. */ - Is_vertical_2 is_vertical_2_object () const - { return Is_vertical_2(); } + /*! Obtain an Is_vertical_2 functor object. */ + Is_vertical_2 is_vertical_2_object () const { return Is_vertical_2(); } class Compare_y_at_x_2 { protected: @@ -441,8 +419,7 @@ public: friend class Arr_segment_traits_2; public: - /*! - * Return the location of the given point with respect to the input curve. + /*! Return the location of the given point with respect to the input curve. * \param cv The curve. * \param p The point. * \pre p is in the x-range of cv. @@ -453,27 +430,26 @@ public: Comparison_result operator()(const Point_2& p, const X_monotone_curve_2& cv) const { - CGAL_precondition (cv.is_in_x_range(p)); + CGAL_precondition(cv.is_in_x_range(p)); const Kernel& kernel = m_traits; if (! cv.is_vertical()) { // Compare p with the segment's supporting line. - CGAL_assertion( kernel.compare_x_2_object()(cv.left(), cv.right()) == SMALLER ); + CGAL_assertion_code(auto cmp_x = kernel.compare_x_2_object()); + CGAL_assertion(cmp_x(cv.left(), cv.right()) == SMALLER); return kernel.orientation_2_object()(cv.left(), cv.right(), p); } - else { - // Compare with the vertical segment's end-points. - typename Kernel::Compare_y_2 compare_y = kernel.compare_y_2_object(); - Comparison_result res1 = compare_y(p, cv.left()); - Comparison_result res2 = compare_y(p, cv.right()); - return (res1 == res2) ? res1 : EQUAL; - } + // Compare with the vertical segment's end-points. + typename Kernel::Compare_y_2 compare_y = kernel.compare_y_2_object(); + Comparison_result res1 = compare_y(p, cv.left()); + Comparison_result res2 = compare_y(p, cv.right()); + return (res1 == res2) ? res1 : EQUAL; } }; - /*! Get a Compare_y_at_x_2 functor object. */ + /*! Obtain a Compare_y_at_x_2 functor object. */ Compare_y_at_x_2 compare_y_at_x_2_object() const { return Compare_y_at_x_2(*this); } @@ -492,8 +468,7 @@ public: friend class Arr_segment_traits_2; public: - /*! - * Compare the y value of two x-monotone curves immediately to the left + /*! Compare the y value of two x-monotone curves immediately to the left * of their intersection point. * \param cv1 The first curve. * \param cv2 The second curve. @@ -511,14 +486,10 @@ public: // Make sure that p lies on both curves, and that both are defined to its // left (so their left endpoint is lexicographically smaller than p). - CGAL_precondition_code( - typename Kernel::Compare_xy_2 compare_xy = - kernel.compare_xy_2_object(); - ); + CGAL_precondition_code(auto compare_xy = kernel.compare_xy_2_object()); - CGAL_precondition( - (m_traits.compare_y_at_x_2_object()(p, cv1) == EQUAL) && - (m_traits.compare_y_at_x_2_object()(p, cv2) == EQUAL)); + CGAL_precondition((m_traits.compare_y_at_x_2_object()(p, cv1) == EQUAL) && + (m_traits.compare_y_at_x_2_object()(p, cv2) == EQUAL)); CGAL_precondition(compare_xy(cv1.left(), p) == SMALLER && compare_xy(cv2.left(), p) == SMALLER); @@ -532,8 +503,8 @@ public: } }; - /*! Get a Compare_y_at_x_left_2 functor object. */ - Compare_y_at_x_left_2 compare_y_at_x_left_2_object () const + /*! Obtain a Compare_y_at_x_left_2 functor object. */ + Compare_y_at_x_left_2 compare_y_at_x_left_2_object() const { return Compare_y_at_x_left_2(*this); } class Compare_y_at_x_right_2 { @@ -551,8 +522,7 @@ public: friend class Arr_segment_traits_2; public: - /*! - * Compare the y value of two x-monotone curves immediately to the right + /*! Compare the y value of two x-monotone curves immediately to the right * of their intersection point. * \param cv1 The first curve. * \param cv2 The second curve. @@ -570,14 +540,10 @@ public: // Make sure that p lies on both curves, and that both are defined to its // right (so their right endpoint is lexicographically larger than p). - CGAL_precondition_code ( - typename Kernel::Compare_xy_2 compare_xy = - kernel.compare_xy_2_object(); - ); + CGAL_precondition_code(auto compare_xy = kernel.compare_xy_2_object()); - CGAL_precondition( - (m_traits.compare_y_at_x_2_object()(p, cv1) == EQUAL) && - (m_traits.compare_y_at_x_2_object()(p, cv2) == EQUAL)); + CGAL_precondition((m_traits.compare_y_at_x_2_object()(p, cv1) == EQUAL) && + (m_traits.compare_y_at_x_2_object()(p, cv2) == EQUAL)); CGAL_precondition(compare_xy(cv1.right(), p) == LARGER && compare_xy(cv2.right(), p) == LARGER); @@ -589,7 +555,7 @@ public: } }; - /*! Get a Compare_y_at_x_right_2 functor object. */ + /*! Obtain a Compare_y_at_x_right_2 functor object. */ Compare_y_at_x_right_2 compare_y_at_x_right_2_object() const { return Compare_y_at_x_right_2(*this); } @@ -608,8 +574,8 @@ public: friend class Arr_segment_traits_2; public: - /*! - * Check if the two x-monotone curves are the same (have the same graph). + /*! Check whether the two x-monotone curves are the same (have the same + * graph). * \param cv1 The first curve. * \param cv2 The second curve. * \return (true) if the two curves are the same; (false) otherwise. @@ -629,14 +595,14 @@ public: * \param p2 The second point. * \return (true) if the two point are the same; (false) otherwise. */ - bool operator() (const Point_2& p1, const Point_2& p2) const + bool operator()(const Point_2& p1, const Point_2& p2) const { const Kernel& kernel = m_traits; return (kernel.equal_2_object()(p1, p2)); } }; - /*! Get an Equal_2 functor object. */ + /*! Obtain an Equal_2 functor object. */ Equal_2 equal_2_object() const { return Equal_2(*this); } //@} @@ -645,25 +611,23 @@ public: class Make_x_monotone_2 { public: - /*! - * Cut the given curve into x-monotone subcurves and insert them into the + /*! Cut the given curve into x-monotone subcurves and insert them into the * given output iterator. As segments are always x_monotone, only one * object will be contained in the iterator. * \param cv The curve. * \param oi The output iterator, whose value-type is Object. * \return The past-the-end iterator. */ - template + template OutputIterator operator()(const Curve_2& cv, OutputIterator oi) const { // Wrap the segment with an object. - *oi = make_object (cv); - ++oi; - return (oi); + *oi++ = make_object(cv); + return oi; } }; - /*! Get a Make_x_monotone_2 functor object. */ + /*! Obtain a Make_x_monotone_2 functor object. */ Make_x_monotone_2 make_x_monotone_2_object() const { return Make_x_monotone_2(); } @@ -682,8 +646,7 @@ public: friend class Arr_segment_traits_2; public: - /*! - * Split a given x-monotone curve at a given point into two sub-curves. + /*! Split a given x-monotone curve at a given point into two sub-curves. * \param cv The curve to split * \param p The split point. * \param c1 Output: The left resulting subcurve (p is its right endpoint). @@ -694,28 +657,24 @@ public: X_monotone_curve_2& c1, X_monotone_curve_2& c2) const { // Make sure that p lies on the interior of the curve. - CGAL_precondition_code ( - const Kernel& kernel = m_traits; - typename Kernel::Compare_xy_2 compare_xy = - kernel.compare_xy_2_object(); - ); + CGAL_precondition_code(const Kernel& kernel = m_traits; + auto compare_xy = kernel.compare_xy_2_object()); - CGAL_precondition( - (m_traits.compare_y_at_x_2_object()(p, cv) == EQUAL) && - compare_xy(cv.left(), p) == SMALLER && - compare_xy(cv.right(), p) == LARGER); + CGAL_precondition((m_traits.compare_y_at_x_2_object()(p, cv) == EQUAL) && + compare_xy(cv.left(), p) == SMALLER && + compare_xy(cv.right(), p) == LARGER); // Perform the split. c1 = cv; - c1.set_right (p); + c1.set_right(p); c2 = cv; - c2.set_left (p); + c2.set_left(p); } }; - /*! Get a Split_2 functor object. */ - Split_2 split_2_object () const { return Split_2(*this); } + /*! Obtain a Split_2 functor object. */ + Split_2 split_2_object() const { return Split_2(*this); } class Intersect_2 { protected: @@ -732,8 +691,7 @@ public: friend class Arr_segment_traits_2; public: - /*! - * Find the intersections of the two given curves and insert them into the + /*! Find the intersections of the two given curves and insert them into the * given output iterator. As two segments may intersect only once, only a * single intersection will be contained in the iterator. * \param cv1 The first curve. @@ -741,58 +699,55 @@ public: * \param oi The output iterator. * \return The past-the-end iterator. */ - template - OutputIterator operator() (const X_monotone_curve_2& cv1, - const X_monotone_curve_2& cv2, - OutputIterator oi) const + template + OutputIterator operator()(const X_monotone_curve_2& cv1, + const X_monotone_curve_2& cv2, + OutputIterator oi) const { + typedef std::pair Intersection_point; + // Intersect the two supporting lines. const Kernel& kernel = m_traits; CGAL::Object obj = kernel.intersect_2_object()(cv1.line(), cv2.line()); - if (obj.is_empty()) { - // The supporting line are parallel lines and do not intersect: - return (oi); - } + // The supporting line are parallel lines and do not intersect: + if (obj.is_empty()) return oi; // Check if we have a single intersection point. - const Point_2 *ip = object_cast (&obj); + const Point_2* ip = object_cast(&obj); if (ip != nullptr) { // Check if the intersection point ip lies on both segments. - const bool ip_on_cv1 = cv1.is_vertical() ? cv1.is_in_y_range(*ip) : - cv1.is_in_x_range(*ip); + const bool ip_on_cv1 = cv1.is_vertical() ? + cv1.is_in_y_range(*ip) : cv1.is_in_x_range(*ip); if (ip_on_cv1) { - const bool ip_on_cv2 = cv2.is_vertical() ? cv2.is_in_y_range(*ip) : - cv2.is_in_x_range(*ip); + const bool ip_on_cv2 = cv2.is_vertical() ? + cv2.is_in_y_range(*ip) : cv2.is_in_x_range(*ip); if (ip_on_cv2) { // Create a pair representing the point with its multiplicity, // which is always 1 for line segments. - std::pair ip_mult (*ip, 1); + Intersection_point ip_mult(*ip, 1); *oi = make_object (ip_mult); oi++; } } - return (oi); + return oi; } // In this case, the two supporting lines overlap. // The overlapping segment is therefore [p_l,p_r], where p_l is the // rightmost of the two left endpoints and p_r is the leftmost of the // two right endpoints. - typename Kernel::Compare_xy_2 compare_xy = kernel.compare_xy_2_object(); - Point_2 p_l, p_r; - - if (compare_xy (cv1.left(), cv2.left()) == SMALLER) p_l = cv2.left(); - else p_l = cv1.left(); - - if (compare_xy (cv1.right(), cv2.right()) == SMALLER) p_r = cv1.right(); - else p_r = cv2.right(); + auto compare_xy = kernel.compare_xy_2_object(); + Point_2 p_l = (compare_xy(cv1.left(), cv2.left()) == SMALLER) ? + cv2.left() : cv1.left(); + Point_2 p_r = (compare_xy(cv1.right(), cv2.right()) == SMALLER) ? + cv1.right() : cv2.right(); // Examine the resulting segment. - const Comparison_result res = compare_xy (p_l, p_r); + const Comparison_result res = compare_xy(p_l, p_r); if (res == SMALLER) { // We have discovered an overlapping segment: @@ -800,34 +755,33 @@ public: // cv1 and cv2 have the same directions, maintain this direction // in the overlap segment if (cv1.is_directed_right()) { - X_monotone_curve_2 overlap_seg(cv1.line(), p_l, p_r); + X_monotone_curve_2 overlap_seg(cv1.line(), p_l, p_r); *oi++ = make_object(overlap_seg); + return oi; } - else { - X_monotone_curve_2 overlap_seg(cv1.line(), p_r, p_l); - *oi++ = make_object(overlap_seg); - } - } - else { - // cv1 and cv2 have opposite directions, the overlap segment - // will be directed from left to right - X_monotone_curve_2 overlap_seg(cv1.line(), p_l, p_r); + X_monotone_curve_2 overlap_seg(cv1.line(), p_r, p_l); *oi++ = make_object(overlap_seg); + return oi; } + // cv1 and cv2 have opposite directions, the overlap segment + // will be directed from left to right + X_monotone_curve_2 overlap_seg(cv1.line(), p_l, p_r); + *oi++ = make_object(overlap_seg); + return oi; } - else if (res == EQUAL) { + if (res == EQUAL) { // The two segment have the same supporting line, but they just share // a common endpoint. Thus we have an intersection point, but we leave // the multiplicity of this point undefined. - std::pair ip_mult(p_r, 0); + Intersection_point ip_mult(p_r, 0); *oi++ = make_object(ip_mult); } - return (oi); + return oi; } }; - /*! Get an Intersect_2 functor object. */ + /*! Obtain an Intersect_2 functor object. */ Intersect_2 intersect_2_object() const { return Intersect_2(*this); } class Are_mergeable_2 { @@ -845,8 +799,7 @@ public: friend class Arr_segment_traits_2; public: - /*! - * Check whether it is possible to merge two given x-monotone curves. + /*! Check whether it is possible to merge two given x-monotone curves. * \param cv1 The first curve. * \param cv2 The second curve. * \return (true) if the two curves are mergeable, that is, if they are @@ -856,20 +809,20 @@ public: bool operator()(const X_monotone_curve_2& cv1, const X_monotone_curve_2& cv2) const { - if (!m_traits.equal_2_object()(cv1.right(), cv2.left()) && - !m_traits.equal_2_object()(cv2.right(), cv1.left())) + const Kernel& kernel = m_traits; + typename Kernel::Equal_2 equal = kernel.equal_2_object(); + if (! equal(cv1.right(), cv2.left()) && + ! equal(cv2.right(), cv1.left())) return false; // Check whether the two curves have the same supporting line. - const Kernel& kernel = m_traits; - typename Kernel::Equal_2 equal = kernel.equal_2_object(); return (equal(cv1.line(), cv2.line()) || equal(cv1.line(), kernel.construct_opposite_line_2_object()(cv2.line()))); } }; - /*! Get an Are_mergeable_2 functor object. */ + /*! Obtain an Are_mergeable_2 functor object. */ Are_mergeable_2 are_mergeable_2_object() const { return Are_mergeable_2(*this); } @@ -891,8 +844,7 @@ public: friend class Arr_segment_traits_2; public: - /*! - * Merge two given x-monotone curves into a single curve (segment). + /*! Merge two given x-monotone curves into a single curve (segment). * \param cv1 The first curve. * \param cv2 The second curve. * \param c Output: The merged curve. @@ -904,25 +856,26 @@ public: { CGAL_precondition(m_traits.are_mergeable_2_object()(cv1, cv2)); - Equal_2 equal = m_traits.equal_2_object(); + const Kernel& kernel = m_traits; + auto equal = kernel.equal_2_object(); // Check which curve extends to the right of the other. if (equal(cv1.right(), cv2.left())) { // cv2 extends cv1 to the right. c = cv1; c.set_right(cv2.right()); + return; } - else { - CGAL_precondition(equal(cv2.right(), cv1.left())); - // cv1 extends cv2 to the right. - c = cv2; - c.set_right(cv1.right()); - } + CGAL_precondition(equal(cv2.right(), cv1.left())); + + // cv1 extends cv2 to the right. + c = cv2; + c.set_right(cv1.right()); } }; - /*! Get a Merge_2 functor object. */ + /*! Obtain a Merge_2 functor object. */ Merge_2 merge_2_object() const { return Merge_2(*this); } //@} @@ -932,8 +885,7 @@ public: class Approximate_2 { public: - /*! - * Return an approximation of a point coordinate. + /*! Obtain an approximation of a point coordinate. * \param p The exact point. * \param i The coordinate index (either 0 or 1). * \pre i is either 0 or 1. @@ -947,13 +899,12 @@ public: } }; - /*! Get an Approximate_2 functor object. */ + /*! Obtain an Approximate_2 functor object. */ Approximate_2 approximate_2_object() const { return Approximate_2(); } class Construct_x_monotone_curve_2 { public: - /*! - * Return an x-monotone curve connecting the two given endpoints. + /*! Obtain an x-monotone curve connecting the two given endpoints. * \param p The first point. * \param q The second point. * \pre p and q must not be the same. @@ -963,7 +914,7 @@ public: { return (X_monotone_curve_2(p, q)); } }; - /*! Get a Construct_x_monotone_curve_2 functor object. */ + /*! Obtain a Construct_x_monotone_curve_2 functor object. */ Construct_x_monotone_curve_2 construct_x_monotone_curve_2_object() const { return Construct_x_monotone_curve_2(); } //@} @@ -1011,41 +962,37 @@ public: // exchange src and tgt IF they do not conform with the direction X_monotone_curve_2 trimmed_segment; - if (xcv.is_directed_right() && compare_x_2(src, tgt) == LARGER) trimmed_segment = X_monotone_curve_2(tgt, src); - else if (!xcv.is_directed_right() && compare_x_2(src, tgt) == SMALLER ) + else if (! xcv.is_directed_right() && (compare_x_2(src, tgt) == SMALLER)) trimmed_segment = X_monotone_curve_2(tgt, src); else trimmed_segment = X_monotone_curve_2(src, tgt); - return (trimmed_segment); + return trimmed_segment; } }; - //get a Trim_2 functor object + /*! Obtain a Trim_2 functor object */ Trim_2 trim_2_object() const { return Trim_2(*this); } - class Compare_endpoints_xy_2 - { + class Compare_endpoints_xy_2 { public: - /*! - * Compare the endpoints of an $x$-monotone curve lexicographically. + /*! Compare the endpoints of an $x$-monotone curve lexicographically. * (assuming the curve has a designated source and target points). * \param cv The curve. * \return SMALLER if the curve is directed right; * LARGER if the curve is directed left. */ - Comparison_result operator() (const X_monotone_curve_2& cv) const + Comparison_result operator()(const X_monotone_curve_2& cv) const { return (cv.is_directed_right()) ? (SMALLER) : (LARGER); } }; - /*! Get a Compare_endpoints_xy_2 functor object. */ + /*! Obtain a Compare_endpoints_xy_2 functor object. */ Compare_endpoints_xy_2 compare_endpoints_xy_2_object() const { return Compare_endpoints_xy_2(); } class Construct_opposite_2 { public: - /*! - * Construct an opposite x-monotone (with swapped source and target). + /*! Construct an opposite x-monotone (with swapped source and target). * \param cv The curve. * \return The opposite curve. */ @@ -1053,17 +1000,16 @@ public: { return (cv.flip()); } }; - /*! Get a Construct_opposite_2 functor object. */ + /*! Obtain a Construct_opposite_2 functor object. */ Construct_opposite_2 construct_opposite_2_object() const { return Construct_opposite_2(); } //@} }; -/*! - * \class A representation of a segment, as used by the Arr_segment_traits_2 +/*! \class A representation of a segment, as used by the Arr_segment_traits_2 * traits-class. */ -template +template class Arr_segment_2 : public Arr_segment_traits_2::_Segment_cached_2 { @@ -1089,7 +1035,7 @@ public: * \pre The two points are not the same. */ Arr_segment_2(const Point_2& source, const Point_2& target) : - Base(source,target) + Base(source, target) {} /*! Construct a segment from a line and two end-points. @@ -1101,7 +1047,7 @@ public: */ Arr_segment_2(const Line_2& line, const Point_2& source, const Point_2& target) : - Base(line,source,target) + Base(line,source, target) {} /*! Cast to a segment. @@ -1109,8 +1055,8 @@ public: operator Segment_2() const { Kernel kernel; - Segment_2 seg = kernel.construct_segment_2_object()(this->ps, this->pt); - return (seg); + Segment_2 seg = kernel.construct_segment_2_object()(this->m_ps, this->m_pt); + return seg; } /*! Create a bounding box for the segment. @@ -1118,37 +1064,37 @@ public: Bbox_2 bbox() const { Kernel kernel; - Segment_2 seg = kernel.construct_segment_2_object()(this->ps, this->pt); - return (kernel.construct_bbox_2_object() (seg)); + Segment_2 seg = kernel.construct_segment_2_object()(this->m_ps, this->m_pt); + return (kernel.construct_bbox_2_object()(seg)); } /*! Obtain the segment source. */ - const Point_2& source() const { return (this->ps); } + const Point_2& source() const { return (this->m_ps); } /*! Obtain the segment target. */ - const Point_2& target() const { return (this->pt); } + const Point_2& target() const { return (this->m_pt); } /*! Flip the segment (swap its source and target). */ Arr_segment_2 flip() const { - Arr_segment_2 opp; - opp.l = this->l; - opp.ps = this->pt; - opp.pt = this->ps; - opp.is_pt_max = !(this->is_pt_max); - opp.is_vert = this->is_vert; - opp.is_degen = this->is_degen; + Arr_segment_2 opp; + opp.m_l = this->m_l; + opp.m_ps = this->m_pt; + opp.m_pt = this->m_ps; + opp.m_is_pt_max = !(this->m_is_pt_max); + opp.m_is_vert = this->m_is_vert; + opp.m_is_degen = this->m_is_degen; - return (opp); + return opp; } }; /*! Exporter for the segment class used by the traits-class. */ -template +template OutputStream& operator<<(OutputStream& os, const Arr_segment_2& seg) { os << static_cast(seg); @@ -1157,13 +1103,13 @@ OutputStream& operator<<(OutputStream& os, const Arr_segment_2& seg) /*! Importer for the segment class used by the traits-class. */ -template +template InputStream& operator>>(InputStream& is, Arr_segment_2& seg) { typename Kernel::Segment_2 kernel_seg; is >> kernel_seg; seg = kernel_seg; - return (is); + return is; } } //namespace CGAL From f5f3440fc010f1d9c154ba124ad14687b13c6cf4 Mon Sep 17 00:00:00 2001 From: Efi Fogel Date: Sun, 29 Mar 2020 13:02:24 +0300 Subject: [PATCH 190/568] Used correct result of intersection --- .../include/CGAL/Arr_segment_traits_2.h | 28 +++++++++++-------- 1 file changed, 17 insertions(+), 11 deletions(-) diff --git a/Arrangement_on_surface_2/include/CGAL/Arr_segment_traits_2.h b/Arrangement_on_surface_2/include/CGAL/Arr_segment_traits_2.h index dc43ac8fa0e..1d2df8e9979 100644 --- a/Arrangement_on_surface_2/include/CGAL/Arr_segment_traits_2.h +++ b/Arrangement_on_surface_2/include/CGAL/Arr_segment_traits_2.h @@ -22,13 +22,17 @@ * The segment traits-class for the arrangement package. */ +#include + +#include +#include + #include #include #include #include #include #include -#include namespace CGAL { @@ -705,17 +709,19 @@ public: OutputIterator oi) const { typedef std::pair Intersection_point; + typedef boost::variant + Intersection_variant; + typedef boost::optional Intersection_result; // Intersect the two supporting lines. const Kernel& kernel = m_traits; - CGAL::Object obj = kernel.intersect_2_object()(cv1.line(), cv2.line()); + auto res = kernel.intersect_2_object()(cv1.line(), cv2.line()); // The supporting line are parallel lines and do not intersect: - if (obj.is_empty()) return oi; + if (! res) return oi; // Check if we have a single intersection point. - const Point_2* ip = object_cast(&obj); - + const Point_2* ip = boost::get(&*res); if (ip != nullptr) { // Check if the intersection point ip lies on both segments. const bool ip_on_cv1 = cv1.is_vertical() ? @@ -729,8 +735,7 @@ public: // Create a pair representing the point with its multiplicity, // which is always 1 for line segments. Intersection_point ip_mult(*ip, 1); - *oi = make_object (ip_mult); - oi++; + *oi++ = make_object(ip_mult); } } return oi; @@ -747,9 +752,9 @@ public: cv1.right() : cv2.right(); // Examine the resulting segment. - const Comparison_result res = compare_xy(p_l, p_r); + const Comparison_result cmp_res = compare_xy(p_l, p_r); - if (res == SMALLER) { + if (cmp_res == SMALLER) { // We have discovered an overlapping segment: if (cv1.is_directed_right() == cv2.is_directed_right()) { // cv1 and cv2 have the same directions, maintain this direction @@ -765,16 +770,17 @@ public: } // cv1 and cv2 have opposite directions, the overlap segment // will be directed from left to right - X_monotone_curve_2 overlap_seg(cv1.line(), p_l, p_r); + X_monotone_curve_2 overlap_seg(cv1.line(), p_l, p_r); *oi++ = make_object(overlap_seg); return oi; } - if (res == EQUAL) { + if (cmp_res == EQUAL) { // The two segment have the same supporting line, but they just share // a common endpoint. Thus we have an intersection point, but we leave // the multiplicity of this point undefined. Intersection_point ip_mult(p_r, 0); *oi++ = make_object(ip_mult); + return oi; } return oi; From 077829724a8c6ef8eb0aedafaac8aa14dce6b4d5 Mon Sep 17 00:00:00 2001 From: Efi Fogel Date: Sun, 29 Mar 2020 13:25:18 +0300 Subject: [PATCH 191/568] Cleaned up; used result_of when computing intersections. --- .../CGAL/Arr_non_caching_segment_traits_2.h | 179 ++++++++---------- .../include/CGAL/Arr_segment_traits_2.h | 10 +- 2 files changed, 82 insertions(+), 107 deletions(-) diff --git a/Arrangement_on_surface_2/include/CGAL/Arr_non_caching_segment_traits_2.h b/Arrangement_on_surface_2/include/CGAL/Arr_non_caching_segment_traits_2.h index 2e567fc241a..aa790b8ade9 100644 --- a/Arrangement_on_surface_2/include/CGAL/Arr_non_caching_segment_traits_2.h +++ b/Arrangement_on_surface_2/include/CGAL/Arr_non_caching_segment_traits_2.h @@ -7,9 +7,9 @@ // $Id$ // SPDX-License-Identifier: GPL-3.0-or-later OR LicenseRef-Commercial // -// Author(s) : Efi Fogel -// Ron Wein -// (base on old version by: Iddo Hanniel) +// Author(s): Efi Fogel +// Ron Wein +// (base on old version by: Iddo Hanniel) #ifndef CGAL_ARR_NON_CACHING_SEGMENT_TRAITS_H #define CGAL_ARR_NON_CACHING_SEGMENT_TRAITS_H @@ -39,7 +39,7 @@ namespace CGAL { * A model of the ArrangementTraits_2 concept that handles general * line segments. */ -template +template class Arr_non_caching_segment_traits_2 : public Arr_non_caching_segment_basic_traits_2 { @@ -114,12 +114,10 @@ public: /*! \class * A functor for splitting curves into x-monotone pieces. */ - class Make_x_monotone_2 - { + class Make_x_monotone_2 { public: - /*! - * Cut the given segment into x-monotone subcurves and insert them into + /*! Cut the given segment into x-monotone subcurves and insert them into * the given output iterator. As segments are always x_monotone, only one * x-monotone curve is inserted into the output iterator. * \param cv The segment. @@ -127,54 +125,47 @@ public: * object is a wrapper of an X_monotone_curve_2 object. * \return The past-the-end iterator. */ - template - OutputIterator operator()(const Curve_2 & cv, OutputIterator oi) const + template + OutputIterator operator()(const Curve_2& cv, OutputIterator oi) const { - *oi = make_object (cv); - ++oi; - return (oi); + *oi++ = make_object(cv); + return oi; } }; - /*! Get a Make_x_monotone_2 functor object. */ + /*! Obtain a Make_x_monotone_2 functor object. */ Make_x_monotone_2 make_x_monotone_2_object() const - { - return Make_x_monotone_2(); - } + { return Make_x_monotone_2(); } /*! \class * A functor for splitting a segment into two segements. */ - class Split_2 - { + class Split_2 { typedef Arr_non_caching_segment_traits_2 Self; - public: - /*! - * Split a given x-monotone curve at a given point into two sub-curves. + public: + /*! Split a given x-monotone curve at a given point into two sub-curves. * \param cv The curve to split * \param p The split point. * \param c1 Output: The left resulting subcurve (p is its right endpoint). * \param c2 Output: The right resulting subcurve (p is its left endpoint). * \pre p lies on cv but is not one of its end-points. */ - void operator()(const X_monotone_curve_2 & cv, const Point_2 & p, - X_monotone_curve_2 & c1, X_monotone_curve_2 & c2) const + void operator()(const X_monotone_curve_2& cv, const Point_2& p, + X_monotone_curve_2& c1, X_monotone_curve_2& c2) const { Base base; // Make sure that p lies on the interior of the curve. - CGAL_precondition_code ( - Compare_xy_2 compare_xy = base.compare_xy_2_object(); - ); + CGAL_precondition_code(auto compare_xy = base.compare_xy_2_object()); Construct_min_vertex_2 min_vertex = base.construct_min_vertex_2_object(); Construct_max_vertex_2 max_vertex = base.construct_max_vertex_2_object(); - const Point_2 & left = min_vertex(cv); - const Point_2 & right = max_vertex(cv); + const Point_2& left = min_vertex(cv); + const Point_2& right = max_vertex(cv); CGAL_precondition - (Segment_assertions::_assert_is_point_on(p, cv, Has_exact_division())&& + (Segment_assertions::_assert_is_point_on(p, cv, Has_exact_division()) && compare_xy(left, p) == SMALLER && compare_xy(right, p) == LARGER); @@ -182,31 +173,36 @@ public: base.construct_segment_2_object(); Self self; - if(self.compare_endpoints_xy_2_object()(cv) == SMALLER) - { + if (self.compare_endpoints_xy_2_object()(cv) == SMALLER) { c1 = construct_segment(left, p); c2 = construct_segment(p, right); } - else - { + else { c1 = construct_segment(p, left); c2 = construct_segment(right, p); } } }; - /*! Get a Split_2 functor object. */ - Split_2 split_2_object() const - { - return Split_2(); - } + /*! Obtain a Split_2 functor object. */ + Split_2 split_2_object() const { return Split_2(); } /*! \class * A functor for computing intersections. */ - class Intersect_2 - { - typedef Arr_non_caching_segment_traits_2 Self; + class Intersect_2 { + protected: + typedef Arr_non_caching_segment_traits_2 Traits; + + /*! The traits (in case it has state) */ + const Traits& m_traits; + + /*! Constructor + * \param traits the traits (in case it has state) + */ + Intersect_2(const Traits& traits) : m_traits(traits) {} + + friend class Arr_non_caching_segment_traits_2; public: /*! Find the intersections of the two given segments and insert them into @@ -217,67 +213,54 @@ public: * \param oi The output iterator. * \return The past-the-end iterator. */ - template - OutputIterator operator()(const X_monotone_curve_2 & cv1, - const X_monotone_curve_2 & cv2, + template + OutputIterator operator()(const X_monotone_curve_2& cv1, + const X_monotone_curve_2& cv2, OutputIterator oi) const { - Base base; - Object res = base.intersect_2_object()(cv1, cv2); + typedef std::pair Intersection_point; + + const Kernel& kernel = m_traits; + Object res = kernel.intersect_2_object()(cv1, cv2); // There is no intersection: - if (res.is_empty()) - return (oi); + if (res.is_empty()) return oi; // Chack if the intersection is a point: - const Point_2 *ip; - - if ((ip = object_cast (&res)) != nullptr) - { + const Point_2* ip = object_cast(&res); + if (ip != nullptr) { // Create a pair representing the point with its multiplicity, // which is always 1 for line segments for all practical purposes. // If the two segments intersect at their endpoints, then the // multiplicity is undefined, but we deliberately ignore it for // efficieny reasons. - std::pair ip_mult(*ip, 1); - *oi = make_object (ip_mult); - ++oi; + Intersection_point ip_mult(*ip, 1); + *oi++ = make_object(ip_mult); + return oi; } - else - { - // The intersection is a segment. - const X_monotone_curve_2 *ov = object_cast(&res); - CGAL_assertion (ov != nullptr); + // The intersection is a segment. + const X_monotone_curve_2* ov = object_cast(&res); + CGAL_assertion(ov != nullptr); - Self self; - Comparison_result cmp1 = self.compare_endpoints_xy_2_object()(cv1); - Comparison_result cmp2 = self.compare_endpoints_xy_2_object()(cv2); + Comparison_result cmp1 = m_traits.compare_endpoints_xy_2_object()(cv1); + Comparison_result cmp2 = m_traits.compare_endpoints_xy_2_object()(cv2); - if(cmp1 == cmp2) - { - // cv1 and cv2 have the same directions, maintain this direction - // in the overlap segment - if(self.compare_endpoints_xy_2_object()(*ov) != cmp1) - { - Kernel k; - res = make_object(k.construct_opposite_segment_2_object()(*ov)); - } + if (cmp1 == cmp2) { + // cv1 and cv2 have the same directions, maintain this direction + // in the overlap segment + if (m_traits.compare_endpoints_xy_2_object()(*ov) != cmp1) { + res = make_object(kernel.construct_opposite_segment_2_object()(*ov)); } - - *oi = res; - ++oi; } - return (oi); + *oi++ = res; + return oi; } }; - /*! Get an Intersect_2 functor object. */ - Intersect_2 intersect_2_object() const - { - return Intersect_2(); - } + /*! Obtain an Intersect_2 functor object. */ + Intersect_2 intersect_2_object() const { return Intersect_2(*this); } /*! \class * A functor for testing whether two segments are mergeable. @@ -297,24 +280,22 @@ public: friend class Arr_non_caching_segment_traits_2; public: - - /*! - * Check whether it is possible to merge two given x-monotone curves. + /*! Check whether it is possible to merge two given x-monotone curves. * \param cv1 The first curve. * \param cv2 The second curve. * \return (true) if the two curves are mergeable, that is, if they are * supported by the same line; (false) otherwise. * \pre cv1 and cv2 share a common endpoint. */ - bool operator()(const X_monotone_curve_2 & cv1, - const X_monotone_curve_2 & cv2) const + bool operator()(const X_monotone_curve_2& cv1, + const X_monotone_curve_2& cv2) const { const Base* base = m_traits; Equal_2 equal = base->equal_2_object(); Construct_min_vertex_2 min_vertex = base->construct_min_vertex_2_object(); Construct_max_vertex_2 max_vertex = base->construct_max_vertex_2_object(); - if (!equal(max_vertex(cv1), min_vertex(cv2)) && - !equal(max_vertex(cv2), min_vertex(cv1))) + if (! equal(max_vertex(cv1), min_vertex(cv2)) && + ! equal(max_vertex(cv2), min_vertex(cv1))) return false; // Check if the two curves have the same supporting line. @@ -344,16 +325,15 @@ public: friend class Arr_non_caching_segment_traits_2; public: - /*! - * Merge two given segments into a single segment. + /*! Merge two given segments into a single segment. * \param cv1 The first curve. * \param cv2 The second curve. * \param c Output: The merged curve. * \pre The two curves are mergeable. */ - void operator()(const X_monotone_curve_2 & cv1, - const X_monotone_curve_2 & cv2, - X_monotone_curve_2 & c) const + void operator()(const X_monotone_curve_2& cv1, + const X_monotone_curve_2& cv2, + X_monotone_curve_2& c) const { CGAL_precondition(m_traits->are_mergeable_2_object()(cv2, cv1)); @@ -390,12 +370,9 @@ public: /*! Obtain a Construct_opposite_2 functor object */ Construct_opposite_2 construct_opposite_2_object() const - { - return Construct_opposite_2(); - } + { return Construct_opposite_2(); } - class Compare_endpoints_xy_2 - { + class Compare_endpoints_xy_2 { public: /*! * Compare the two endpoints of a given curve lexigoraphically. @@ -417,9 +394,7 @@ public: /*! Obtain a Compare_endpoints_xy_2 functor object */ Compare_endpoints_xy_2 compare_endpoints_xy_2_object() const - { - return Compare_endpoints_xy_2(); - } + { return Compare_endpoints_xy_2(); } //@} }; diff --git a/Arrangement_on_surface_2/include/CGAL/Arr_segment_traits_2.h b/Arrangement_on_surface_2/include/CGAL/Arr_segment_traits_2.h index 1d2df8e9979..11f7aea6dae 100644 --- a/Arrangement_on_surface_2/include/CGAL/Arr_segment_traits_2.h +++ b/Arrangement_on_surface_2/include/CGAL/Arr_segment_traits_2.h @@ -735,7 +735,7 @@ public: // Create a pair representing the point with its multiplicity, // which is always 1 for line segments. Intersection_point ip_mult(*ip, 1); - *oi++ = make_object(ip_mult); + *oi++ = Intersection_result(ip_mult); } } return oi; @@ -761,17 +761,17 @@ public: // in the overlap segment if (cv1.is_directed_right()) { X_monotone_curve_2 overlap_seg(cv1.line(), p_l, p_r); - *oi++ = make_object(overlap_seg); + *oi++ = Intersection_result(overlap_seg); return oi; } X_monotone_curve_2 overlap_seg(cv1.line(), p_r, p_l); - *oi++ = make_object(overlap_seg); + *oi++ = Intersection_result(overlap_seg); return oi; } // cv1 and cv2 have opposite directions, the overlap segment // will be directed from left to right X_monotone_curve_2 overlap_seg(cv1.line(), p_l, p_r); - *oi++ = make_object(overlap_seg); + *oi++ = Intersection_result(overlap_seg); return oi; } if (cmp_res == EQUAL) { @@ -779,7 +779,7 @@ public: // a common endpoint. Thus we have an intersection point, but we leave // the multiplicity of this point undefined. Intersection_point ip_mult(p_r, 0); - *oi++ = make_object(ip_mult); + *oi++ = Intersection_result(ip_mult); return oi; } From dc0cab62a482d658bcd1fa684689bd69569df2a9 Mon Sep 17 00:00:00 2001 From: Efi Fogel Date: Sun, 29 Mar 2020 13:31:26 +0300 Subject: [PATCH 192/568] Fixed Intersect_2 to return optional of variant (instead of CGAL::Object) --- .../CGAL/Arr_non_caching_segment_traits_2.h | 19 +++++++++++++------ 1 file changed, 13 insertions(+), 6 deletions(-) diff --git a/Arrangement_on_surface_2/include/CGAL/Arr_non_caching_segment_traits_2.h b/Arrangement_on_surface_2/include/CGAL/Arr_non_caching_segment_traits_2.h index aa790b8ade9..aa3483255de 100644 --- a/Arrangement_on_surface_2/include/CGAL/Arr_non_caching_segment_traits_2.h +++ b/Arrangement_on_surface_2/include/CGAL/Arr_non_caching_segment_traits_2.h @@ -27,6 +27,9 @@ * functors required by the concept it models. */ +#include +#include + #include #include #include @@ -219,15 +222,18 @@ public: OutputIterator oi) const { typedef std::pair Intersection_point; + typedef boost::variant + Intersection_variant; + typedef boost::optional Intersection_result; const Kernel& kernel = m_traits; - Object res = kernel.intersect_2_object()(cv1, cv2); + auto res = kernel.intersect_2_object()(cv1, cv2); // There is no intersection: - if (res.is_empty()) return oi; + if (! res) return oi; // Chack if the intersection is a point: - const Point_2* ip = object_cast(&res); + const Point_2* ip = boost::get(&*res); if (ip != nullptr) { // Create a pair representing the point with its multiplicity, // which is always 1 for line segments for all practical purposes. @@ -235,12 +241,12 @@ public: // multiplicity is undefined, but we deliberately ignore it for // efficieny reasons. Intersection_point ip_mult(*ip, 1); - *oi++ = make_object(ip_mult); + *oi++ = Intersection_result(ip_mult); return oi; } // The intersection is a segment. - const X_monotone_curve_2* ov = object_cast(&res); + const X_monotone_curve_2* ov = boost::get(&*res); CGAL_assertion(ov != nullptr); Comparison_result cmp1 = m_traits.compare_endpoints_xy_2_object()(cv1); @@ -250,7 +256,8 @@ public: // cv1 and cv2 have the same directions, maintain this direction // in the overlap segment if (m_traits.compare_endpoints_xy_2_object()(*ov) != cmp1) { - res = make_object(kernel.construct_opposite_segment_2_object()(*ov)); + auto ctr_opposite = kernel.construct_opposite_segment_2_object(); + res = Intersection_result(ctr_opposite(*ov)); } } From 11059b4f843fab11e5c12327191a8e95c20576f6 Mon Sep 17 00:00:00 2001 From: Efi Fogel Date: Sun, 29 Mar 2020 13:33:08 +0300 Subject: [PATCH 193/568] Fixed typo --- Arrangement_on_surface_2/include/CGAL/Arr_segment_traits_2.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Arrangement_on_surface_2/include/CGAL/Arr_segment_traits_2.h b/Arrangement_on_surface_2/include/CGAL/Arr_segment_traits_2.h index 11f7aea6dae..955d67ae84f 100644 --- a/Arrangement_on_surface_2/include/CGAL/Arr_segment_traits_2.h +++ b/Arrangement_on_surface_2/include/CGAL/Arr_segment_traits_2.h @@ -619,7 +619,7 @@ public: * given output iterator. As segments are always x_monotone, only one * object will be contained in the iterator. * \param cv The curve. - * \param oi The output iterator, whose value-type is Object. + * \param oi The output iterator, whose value-type is optional From 78fbe290d1843eb48cb68d4972317436f9f14b4a Mon Sep 17 00:00:00 2001 From: Jane Tournois Date: Mon, 30 Mar 2020 13:59:59 +0200 Subject: [PATCH 194/568] avoid dependency on PMP for computing normals --- .../internal/tetrahedral_remeshing_helpers.h | 44 ++++++++----------- 1 file changed, 18 insertions(+), 26 deletions(-) diff --git a/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/tetrahedral_remeshing_helpers.h b/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/tetrahedral_remeshing_helpers.h index fa6ba03f8a9..601577824cb 100644 --- a/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/tetrahedral_remeshing_helpers.h +++ b/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/tetrahedral_remeshing_helpers.h @@ -584,43 +584,35 @@ namespace Tetrahedral_remeshing template void normalize(typename Gt::Vector_3& v, const Gt& gt) { - namespace PMP = CGAL::Polygon_mesh_processing; + typedef typename Gt::FT FT; - if (!typename Gt::Equal_3()(v, CGAL::NULL_VECTOR)) - PMP::internal::normalize(v, gt); + const FT norm = CGAL::approximate_sqrt(gt.compute_squared_length_3_object()(v)); + if (norm != FT(0)) + v = gt.construct_divided_vector_3_object()(v, norm); } template typename Gt::Vector_3 normal(const Facet& f, const Gt& gt) { - namespace PMP = CGAL::Polygon_mesh_processing; - typedef typename Gt::Vector_3 Vector; + typedef typename Gt::Vector_3 Vector_3; typedef typename Gt::Point_3 Point; + typedef typename Gt::FT FT; - const int i = f.second; + Point p0 = point(f.first->vertex((f.second + 1) % 4)->point()); + Point p1 = point(f.first->vertex((f.second + 2) % 4)->point()); + const Point& p2 = point(f.first->vertex((f.second + 3) % 4)->point()); - const Point& pa = point(f.first->vertex(indices(i, 0))->point()); - const Point& pb = point(f.first->vertex(indices(i, 1))->point()); - const Point& pc = point(f.first->vertex(indices(i, 2))->point()); + if (f.second % 2 == 0)//equivalent to the commented orientation test + std::swap(p0, p1); - Vector n = CGAL::cross_product(pb - pa, pc - pa); - n = n / CGAL::sqrt(n * n); + Vector_3 n = gt.construct_cross_product_vector_3_object()( + gt.construct_vector_3_object()(p1, p2), + gt.construct_vector_3_object()(p1, p0)); - return n; - -// Point p0 = point(f.first->vertex((f.second + 1) % 4)->point()); -// Point p1 = point(f.first->vertex((f.second + 2) % 4)->point()); -// const Point& p2 = point(f.first->vertex((f.second + 3) % 4)->point()); -// -// //if (f.second % 2 == 0)//equivalent to the commented orientation test -// // std::swap(p0, p1); -// -// Vector n = PMP::internal::triangle_normal(p0, p1, p2, gt); -// -// if (!typename Gt::Equal_3()(n, CGAL::NULL_VECTOR)) -// PMP::internal::normalize(n, gt); - -// return n; + //cross-product(AB, AC)'s norm is the area of the parallelogram + //formed by these 2 vectors. + //the triangle's area is half of it + return gt.construct_scaled_vector_3_object()(n, FT(1) / FT(2)); } template From 3310ef054d1d93c5ae9a7b68c8326dc6cc945847 Mon Sep 17 00:00:00 2001 From: Jane Tournois Date: Mon, 30 Mar 2020 15:45:51 +0200 Subject: [PATCH 195/568] disable smoothing on sharp edges for now reprojection does projection on incident patches successively, and this tends to smooth the shape of complex polylines, though this is not desired it seems that 1d smoothing does not really improve the quality nor complexity of the output mesh, so let's disable it for now --- .../internal/smooth_vertices.h | 218 +++++++++--------- 1 file changed, 109 insertions(+), 109 deletions(-) diff --git a/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/smooth_vertices.h b/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/smooth_vertices.h index 64a1b681de2..457cb7f5d15 100644 --- a/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/smooth_vertices.h +++ b/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/smooth_vertices.h @@ -368,115 +368,115 @@ namespace CGAL if (!protect_boundaries) { - /////////////// EDGES IN COMPLEX ////////////////// - //collect neighbors - for (const Edge& e : tr.finite_edges()) - { - if (c3t3.is_in_complex(e)) - { - const Vertex_handle vh0 = e.first->vertex(e.second); - const Vertex_handle vh1 = e.first->vertex(e.third); - - const std::size_t& i0 = vertex_id.at(vh0); - const std::size_t& i1 = vertex_id.at(vh1); - - const bool on_feature_v0 = is_on_feature(vh0); - const bool on_feature_v1 = is_on_feature(vh1); - - if (!c3t3.is_in_complex(vh0)) - neighbors[i0] = (std::max)(0, neighbors[i0]); - if (!c3t3.is_in_complex(vh1)) - neighbors[i1] = (std::max)(0, neighbors[i1]); - - if (!c3t3.is_in_complex(vh0) && on_feature_v1) - { - const Point_3& p1 = point(vh1->point()); - smoothed_positions[i0] = smoothed_positions[i0] + Vector_3(p1.x(), p1.y(), p1.z()); - neighbors[i0]++; - } - if (!c3t3.is_in_complex(vh1) && on_feature_v0) - { - const Point_3& p0 = point(vh0->point()); - smoothed_positions[i1] = smoothed_positions[i1] + Vector_3(p0.x(), p0.y(), p0.z()); - neighbors[i1]++; - } - } - } - - // Smooth - for (Vertex_handle v : tr.finite_vertex_handles()) - { - const std::size_t& vid = vertex_id.at(v); - if (neighbors[vid] > 1) - { - Vector_3 smoothed_position = smoothed_positions[vid] / neighbors[vid]; - Vector_3 final_position = CGAL::NULL_VECTOR; - - std::size_t count = 0; - const Vector_3 current_pos(CGAL::ORIGIN, point(v->point())); - - const std::vector& v_surface_indices = vertices_surface_indices[v]; - for (const Surface_patch_index& si : v_surface_indices) - { - Vector_3 normal_projection - = project_on_tangent_plane(smoothed_position, current_pos, vertices_normals[v][si]); - - //Check if the mls surface exists to avoid degenerated cases - if (boost::optional mls_projection = project(si, normal_projection)) { - final_position = final_position + *mls_projection; - } - else { - final_position = final_position + normal_projection; - } - count++; - } - - if (count > 0) - final_position = final_position / static_cast(count); - else - final_position = smoothed_position; - -#ifdef CGAL_TETRAHEDRAL_REMESHING_DEBUG - os_surf << "2 " << current_pos << " " << final_position << std::endl, -#endif - // move vertex - v->set_point(typename Tr::Point( - final_position.x(), final_position.y(), final_position.z())); - } - else if (neighbors[vid] > 0) - { - Vector_3 final_position = CGAL::NULL_VECTOR; - - int count = 0; - const Vector_3 current_pos(CGAL::ORIGIN, point(v->point())); - - const std::vector& v_surface_indices = vertices_surface_indices[v]; - for (const Surface_patch_index si : v_surface_indices) - { - //Check if the mls surface exists to avoid degenerated cases - - if (boost::optional mls_projection = project(si, current_pos)) { - final_position = final_position + *mls_projection; - } - else { - final_position = final_position + current_pos; - } - count++; - } - - if (count > 0) - final_position = final_position / static_cast(count); - else - final_position = current_pos; - -#ifdef CGAL_TETRAHEDRAL_REMESHING_DEBUG - os_surf << "2 " << current_pos << " " << final_position << std::endl, -#endif - // move vertex - v->set_point( - typename Tr::Point(final_position.x(), final_position.y(), final_position.z())); - } - } +// /////////////// EDGES IN COMPLEX ////////////////// +// //collect neighbors +// for (const Edge& e : tr.finite_edges()) +// { +// if (c3t3.is_in_complex(e)) +// { +// const Vertex_handle vh0 = e.first->vertex(e.second); +// const Vertex_handle vh1 = e.first->vertex(e.third); +// +// const std::size_t& i0 = vertex_id.at(vh0); +// const std::size_t& i1 = vertex_id.at(vh1); +// +// const bool on_feature_v0 = is_on_feature(vh0); +// const bool on_feature_v1 = is_on_feature(vh1); +// +// if (!c3t3.is_in_complex(vh0)) +// neighbors[i0] = (std::max)(0, neighbors[i0]); +// if (!c3t3.is_in_complex(vh1)) +// neighbors[i1] = (std::max)(0, neighbors[i1]); +// +// if (!c3t3.is_in_complex(vh0) && on_feature_v1) +// { +// const Point_3& p1 = point(vh1->point()); +// smoothed_positions[i0] = smoothed_positions[i0] + Vector_3(p1.x(), p1.y(), p1.z()); +// neighbors[i0]++; +// } +// if (!c3t3.is_in_complex(vh1) && on_feature_v0) +// { +// const Point_3& p0 = point(vh0->point()); +// smoothed_positions[i1] = smoothed_positions[i1] + Vector_3(p0.x(), p0.y(), p0.z()); +// neighbors[i1]++; +// } +// } +// } +// +// // Smooth +// for (Vertex_handle v : tr.finite_vertex_handles()) +// { +// const std::size_t& vid = vertex_id.at(v); +// if (neighbors[vid] > 1) +// { +// Vector_3 smoothed_position = smoothed_positions[vid] / neighbors[vid]; +// Vector_3 final_position = CGAL::NULL_VECTOR; +// +// std::size_t count = 0; +// const Vector_3 current_pos(CGAL::ORIGIN, point(v->point())); +// +// const std::vector& v_surface_indices = vertices_surface_indices[v]; +// for (const Surface_patch_index& si : v_surface_indices) +// { +// Vector_3 normal_projection +// = project_on_tangent_plane(smoothed_position, current_pos, vertices_normals[v][si]); +// +// //Check if the mls surface exists to avoid degenerated cases +// if (boost::optional mls_projection = project(si, normal_projection)) { +// final_position = final_position + *mls_projection; +// } +// else { +// final_position = final_position + normal_projection; +// } +// count++; +// } +// +// if (count > 0) +// final_position = final_position / static_cast(count); +// else +// final_position = smoothed_position; +// +//#ifdef CGAL_TETRAHEDRAL_REMESHING_DEBUG +// os_surf << "2 " << current_pos << " " << final_position << std::endl, +//#endif +// // move vertex +// v->set_point(typename Tr::Point( +// final_position.x(), final_position.y(), final_position.z())); +// } +// else if (neighbors[vid] > 0) +// { +// Vector_3 final_position = CGAL::NULL_VECTOR; +// +// int count = 0; +// const Vector_3 current_pos(CGAL::ORIGIN, point(v->point())); +// +// const std::vector& v_surface_indices = vertices_surface_indices[v]; +// for (const Surface_patch_index si : v_surface_indices) +// { +// //Check if the mls surface exists to avoid degenerated cases +// +// if (boost::optional mls_projection = project(si, current_pos)) { +// final_position = final_position + *mls_projection; +// } +// else { +// final_position = final_position + current_pos; +// } +// count++; +// } +// +// if (count > 0) +// final_position = final_position / static_cast(count); +// else +// final_position = current_pos; +// +//#ifdef CGAL_TETRAHEDRAL_REMESHING_DEBUG +// os_surf << "2 " << current_pos << " " << final_position << std::endl, +//#endif +// // move vertex +// v->set_point( +// typename Tr::Point(final_position.x(), final_position.y(), final_position.z())); +// } +// } smoothed_positions.assign(nbv, CGAL::NULL_VECTOR); neighbors.assign(nbv, -1); From c1fed0bd0b435e1fc4130ac424e6bb19152f0846 Mon Sep 17 00:00:00 2001 From: Efi Fogel Date: Tue, 31 Mar 2020 17:30:55 +0300 Subject: [PATCH 196/568] Cleaned up --- .../CGAL/Arr_circle_segment_traits_2.h | 43 +++++++------------ 1 file changed, 15 insertions(+), 28 deletions(-) diff --git a/Arrangement_on_surface_2/include/CGAL/Arr_circle_segment_traits_2.h b/Arrangement_on_surface_2/include/CGAL/Arr_circle_segment_traits_2.h index dc8dc0d5e78..2b5a25cd5e0 100644 --- a/Arrangement_on_surface_2/include/CGAL/Arr_circle_segment_traits_2.h +++ b/Arrangement_on_surface_2/include/CGAL/Arr_circle_segment_traits_2.h @@ -7,9 +7,10 @@ // $Id$ // SPDX-License-Identifier: GPL-3.0-or-later OR LicenseRef-Commercial // -// Author(s) : Ron Wein -// Baruch Zukerman -// Waqar Khan +// Author(s): Ron Wein +// Baruch Zukerman +// Waqar Khan +// Efi Fogel #ifndef CGAL_ARR_CIRCLE_SEGMENT_TRAITS_2_H #define CGAL_ARR_CIRCLE_SEGMENT_TRAITS_2_H @@ -546,21 +547,15 @@ public: return Split_2(); } - class Intersect_2 - { + class Intersect_2 { private: - - Intersection_map& _inter_map; // The map of intersection points. + Intersection_map& _inter_map; // The map of intersection points. public: - /*! Constructor. */ - Intersect_2 (Intersection_map& map) : - _inter_map (map) - {} + Intersect_2(Intersection_map& map) : _inter_map(map) {} - /*! - * Find the intersections of the two given curves and insert them to the + /*! Find the intersections of the two given curves and insert them to the * given output iterator. As two segments may itersect only once, only a * single will be contained in the iterator. * \param cv1 The first curve. @@ -568,20 +563,15 @@ public: * \param oi The output iterator. * \return The past-the-end iterator. */ - template - OutputIterator operator() (const X_monotone_curve_2& cv1, - const X_monotone_curve_2& cv2, - OutputIterator oi) const - { - return (cv1.intersect (cv2, oi, &_inter_map)); - } + template + OutputIterator operator()(const X_monotone_curve_2& cv1, + const X_monotone_curve_2& cv2, + OutputIterator oi) const + { return (cv1.intersect(cv2, oi, &_inter_map)); } }; /*! Get an Intersect_2 functor object. */ - Intersect_2 intersect_2_object () const - { - return (Intersect_2 (inter_map)); - } + Intersect_2 intersect_2_object() const { return (Intersect_2(inter_map)); } class Are_mergeable_2 { @@ -706,14 +696,11 @@ public: friend class Arr_circle_segment_traits_2; public: - /*!\brief - * Returns a trimmed version of an arc - * + /*! Obtain a trimmed version of an arc * \param xcv The arc * \param src the new first endpoint * \param tgt the new second endpoint * \return The trimmed arc - * * \pre src != tgt * \pre both points must be interior and must lie on \c cv */ From 523fcfdbc59673ce8bc765ac66eb51510cd59102 Mon Sep 17 00:00:00 2001 From: Efi Fogel Date: Tue, 31 Mar 2020 17:32:38 +0300 Subject: [PATCH 197/568] Cleaned up --- .../include/CGAL/Arr_conic_traits_2.h | 42 +++++++------------ 1 file changed, 15 insertions(+), 27 deletions(-) diff --git a/Arrangement_on_surface_2/include/CGAL/Arr_conic_traits_2.h b/Arrangement_on_surface_2/include/CGAL/Arr_conic_traits_2.h index f1640b280b0..cc26c045a84 100644 --- a/Arrangement_on_surface_2/include/CGAL/Arr_conic_traits_2.h +++ b/Arrangement_on_surface_2/include/CGAL/Arr_conic_traits_2.h @@ -8,8 +8,8 @@ // SPDX-License-Identifier: GPL-3.0-or-later OR LicenseRef-Commercial // // -// Author(s) : Ron Wein -// Waqar Khan +// Author(s): Ron Wein +// Waqar Khan #ifndef CGAL_ARR_CONIC_TRAITS_2_H #define CGAL_ARR_CONIC_TRAITS_2_H @@ -22,6 +22,8 @@ * The conic traits-class for the arrangement package. */ +#include + #include #include #include @@ -29,8 +31,6 @@ #include #include -#include - namespace CGAL { /*! @@ -88,8 +88,7 @@ private: // Type definition for the intersection points mapping. typedef typename X_monotone_curve_2::Conic_id Conic_id; - typedef typename X_monotone_curve_2::Intersection_point_2 - Intersection_point_2; + typedef typename X_monotone_curve_2::Intersection_point Intersection_point; typedef typename X_monotone_curve_2::Intersection_map Intersection_map; mutable Intersection_map inter_map; // Mapping conic pairs to their @@ -604,21 +603,15 @@ public: return Split_2(); } - class Intersect_2 - { + class Intersect_2 { private: - - Intersection_map& _inter_map; // The map of intersection points. + Intersection_map& _inter_map; // The map of intersection points. public: - /*! Constructor. */ - Intersect_2 (Intersection_map& map) : - _inter_map (map) - {} + Intersect_2(Intersection_map& map) : _inter_map(map) {} - /*! - * Find the intersections of the two given curves and insert them to the + /*! Find the intersections of the two given curves and insert them to the * given output iterator. As two segments may itersect only once, only a * single will be contained in the iterator. * \param cv1 The first curve. @@ -626,20 +619,15 @@ public: * \param oi The output iterator. * \return The past-the-end iterator. */ - template - OutputIterator operator() (const X_monotone_curve_2& cv1, - const X_monotone_curve_2& cv2, - OutputIterator oi) const - { - return (cv1.intersect (cv2, _inter_map, oi)); - } + template + OutputIterator operator()(const X_monotone_curve_2& cv1, + const X_monotone_curve_2& cv2, + OutputIterator oi) const + { return (cv1.intersect(cv2, _inter_map, oi)); } }; /*! Get an Intersect_2 functor object. */ - Intersect_2 intersect_2_object () const - { - return (Intersect_2 (inter_map)); - } + Intersect_2 intersect_2_object () const { return (Intersect_2(inter_map)); } class Are_mergeable_2 { From 58276edba3808882bce09f99956ffccefe08d801 Mon Sep 17 00:00:00 2001 From: Efi Fogel Date: Tue, 31 Mar 2020 18:34:28 +0300 Subject: [PATCH 198/568] Cleaned up and Fixed intersection return type --- .../CGAL/Arr_circular_line_arc_traits_2.h | 101 +- .../include/CGAL/Arr_curve_data_traits_2.h | 37 +- .../Arr_geodesic_arc_on_sphere_traits_2.h | 40 +- .../CGAL/Arr_geometry_traits/Bezier_cache.h | 16 +- .../Arr_geometry_traits/Bezier_x_monotone_2.h | 1772 +++++++-------- .../Arr_geometry_traits/Circle_segment_2.h | 1963 +++++++---------- .../Conic_x_monotone_arc_2.h | 800 +++---- .../CGAL/Arr_geometry_traits/Rational_arc_2.h | 145 +- .../include/CGAL/Arr_linear_traits_2.h | 1210 ++++------ .../CGAL/Arr_non_caching_segment_traits_2.h | 23 +- .../include/CGAL/Arr_polycurve_traits_2.h | 166 +- .../CGAL/Arr_rat_arc/Rational_arc_d_1.h | 142 +- .../include/CGAL/Arr_segment_traits_2.h | 6 +- .../include/CGAL/Arr_tracing_traits_2.h | 34 +- .../Arrangement_2/Arrangement_zone_2_impl.h | 42 +- .../include/CGAL/Arrangement_zone_2.h | 30 +- .../Curved_kernel_via_analysis_2_functors.h | 23 +- .../Arrangement_on_surface_2/Traits_test.h | 42 +- 18 files changed, 2752 insertions(+), 3840 deletions(-) diff --git a/Arrangement_on_surface_2/include/CGAL/Arr_circular_line_arc_traits_2.h b/Arrangement_on_surface_2/include/CGAL/Arr_circular_line_arc_traits_2.h index 654f86e3e30..f64bcbfc867 100644 --- a/Arrangement_on_surface_2/include/CGAL/Arr_circular_line_arc_traits_2.h +++ b/Arrangement_on_surface_2/include/CGAL/Arr_circular_line_arc_traits_2.h @@ -47,9 +47,9 @@ namespace CGAL { object_to_object_variant(const std::vector& res1, OutputIterator res2) { - for(std::vector::const_iterator it = res1.begin(); - it != res1.end(); ++it ){ - if(const Arc1 *arc = CGAL::object_cast< Arc1 >(&*it)){ + for (std::vector::const_iterator it = res1.begin(); + it != res1.end(); ++it ) { + if (const Arc1 *arc = CGAL::object_cast< Arc1 >(&*it)){ boost::variant< Arc1, Arc2 > v = *arc; *res2++ = make_object(v); } @@ -64,29 +64,27 @@ namespace CGAL { return res2; } - - template - class In_x_range_2 + template + OutputIterator + object_to_object_variant1(const std::vector& res, + OutputIterator oi) { - public: - typedef typename CircularKernel::Circular_arc_point_2 - Circular_arc_point_2; - typedef bool result_type; + typedef IntersectionPoint Intersection_point; + typedef XMonotoneCurve X_monotone_curve_2; + typedef boost::variant + Intersection_result; - result_type - operator()(const boost::variant< Arc1, Arc2 > &a, - const Circular_arc_point_2 &p) const - { - if ( const Arc1* arc1 = boost::get( &a ) ){ - return CircularKernel().in_x_range_2_object()(*arc1, p); - } - else { - const Arc2* arc2 = boost::get( &a ); - return CircularKernel().in_x_range_2_object()(*arc2, p); + for (auto it = res.begin(); it != res.end(); ++it) { + if (const Arc* arc = boost::get(&*it)) { + X_monotone_curve_2 cv = *arc; + *oi++ = Intersection_result(cv); } + else *oi++ = Intersection_result(*it); } - }; - + return oi; + } template class Compare_y_to_right_2 @@ -277,7 +275,7 @@ namespace CGAL { CircularKernel() .make_x_monotone_2_object()(*arc1,std::back_inserter(container)); return object_to_object_variant - (container, res); + (container, res); } else { const Arc2* arc2 = boost::get( &A ); @@ -285,65 +283,48 @@ namespace CGAL { CircularKernel() .make_x_monotone_2_object()(*arc2,std::back_inserter(container)); return object_to_object_variant - (container, res); + (container, res); } } }; - - template class Intersect_2 { public: - typedef typename CircularKernel::Circular_arc_point_2 - Circular_arc_point_2; + typedef typename CircularKernel::Circular_arc_point_2 + Circular_arc_point_2; template < class OutputIterator > OutputIterator operator()(const boost::variant< Arc1, Arc2 > &c1, const boost::variant< Arc1, Arc2 > &c2, - OutputIterator res) const + OutputIterator oi) const { + typedef CircularKernel CK; + typedef unsigned int Multiplicity; + typedef std::pair + Intersection_point; + typedef boost::variant X_monotone_curve_2; + if ( const Arc1* arc1 = boost::get( &c1 ) ){ if ( const Arc1* arc2 = boost::get( &c2 ) ){ - std::vector container; - CircularKernel() - .intersect_2_object()(*arc1,*arc2,std::back_inserter(container)); - return object_to_object_variant - (container, res); - } - else if ( const Arc2* arc2 = boost::get( &c2 ) ){ - std::vector container; - CircularKernel() - .intersect_2_object()(*arc1,*arc2,std::back_inserter(container)); - return object_to_object_variant - (container, res); - } - } - else { - const Arc2* arc1e = boost::get( &c1 ); - if ( const Arc1* arc2 = boost::get( &c2 ) ){ - std::vector container; - CircularKernel() - .intersect_2_object()(*arc1e,*arc2,std::back_inserter(container)); - return object_to_object_variant - (container, res); + return CircularKernel().intersect_2_object()(*arc1, *arc2, oi); } const Arc2* arc2 = boost::get( &c2 ); - std::vector container; - CircularKernel() - .intersect_2_object()(*arc1e,*arc2,std::back_inserter(container)); - return object_to_object_variant - (container, res); + return CircularKernel().intersect_2_object()(*arc1, *arc2, oi); } - CGAL_error(); - return res;//for no warning + + const Arc2* arc1e = boost::get( &c1 ); + if ( const Arc1* arc2 = boost::get( &c2 ) ){ + return CircularKernel().intersect_2_object()(*arc1e, *arc2, oi); + } + const Arc2* arc2 = boost::get( &c2 ); + return CircularKernel().intersect_2_object()(*arc1e, *arc2, oi); } }; - template class Split_2 { @@ -533,7 +514,7 @@ namespace CGAL { typedef unsigned int Multiplicity; typedef CGAL::Tag_false Has_left_category; - typedef CGAL::Tag_false Has_merge_category; + typedef CGAL::Tag_false Has_merge_category; typedef CGAL::Tag_false Has_do_intersect_category; typedef Arr_oblivious_side_tag Left_side_category; diff --git a/Arrangement_on_surface_2/include/CGAL/Arr_curve_data_traits_2.h b/Arrangement_on_surface_2/include/CGAL/Arr_curve_data_traits_2.h index 877444cb066..5be881f3601 100644 --- a/Arrangement_on_surface_2/include/CGAL/Arr_curve_data_traits_2.h +++ b/Arrangement_on_surface_2/include/CGAL/Arr_curve_data_traits_2.h @@ -7,8 +7,8 @@ // $Id$ // SPDX-License-Identifier: GPL-3.0-or-later OR LicenseRef-Commercial // -// Author(s) : Ron Wein -// Efi Fogel +// Author(s): Ron Wein +// Efi Fogel #ifndef CGAL_ARR_CURVE_DATA_TRAITS_2_H #define CGAL_ARR_CURVE_DATA_TRAITS_2_H @@ -193,35 +193,40 @@ public: * \param oi The output iterator. * \return The past-the-end iterator. */ - template + template OutputIterator operator()(const X_monotone_curve_2& cv1, const X_monotone_curve_2& cv2, OutputIterator oi) const { + typedef std::pair Intersection_point; + typedef boost::variant + Intersection_result; + typedef boost::variant + Intersection_base_result; + // Use the base functor to obtain all intersection objects. - std::list base_objects; + std::list base_objects; m_base.intersect_2_object()(cv1, cv2, std::back_inserter(base_objects)); // Stop if the list is empty: if (base_objects.empty()) return oi; // Go over all intersection objects and prepare the output. - const Base_x_monotone_curve_2* base_cv; - for (typename std::list::const_iterator it = - base_objects.begin(); it != base_objects.end(); ++it) - { - if ((base_cv = object_cast(&(*it))) != nullptr) { + for (const auto& item : base_objects) { + const Base_x_monotone_curve_2* base_cv = + boost::get(&item); + if (base_cv != nullptr) { // The current intersection object is an overlapping x-monotone // curve: Merge the data fields of both intersecting curves and // associate the result with the overlapping curve. - X_monotone_curve_2 cv(*base_cv, Merge() (cv1.data(), cv2.data())); - *oi++ = make_object(cv); - } - else { - // The current intersection object is an intersection point: - // Copy it as is. - *oi++ = *it; + X_monotone_curve_2 cv(*base_cv, Merge()(cv1.data(), cv2.data())); + *oi++ = Intersection_result(cv); + continue; } + // The current intersection object is an intersection point: + // Copy it as is. + const Intersection_point* ip = boost::get(&item); + *oi++ = Intersection_result(*ip); } return oi; diff --git a/Arrangement_on_surface_2/include/CGAL/Arr_geodesic_arc_on_sphere_traits_2.h b/Arrangement_on_surface_2/include/CGAL/Arr_geodesic_arc_on_sphere_traits_2.h index 8dff925bff6..9b511d4b7b4 100644 --- a/Arrangement_on_surface_2/include/CGAL/Arr_geodesic_arc_on_sphere_traits_2.h +++ b/Arrangement_on_surface_2/include/CGAL/Arr_geodesic_arc_on_sphere_traits_2.h @@ -7,7 +7,7 @@ // $Id$ // SPDX-License-Identifier: GPL-3.0-or-later OR LicenseRef-Commercial // -// Author(s) : Efi Fogel +// Author(s) : Efi Fogel #ifndef CGAL_ARR_GEODESIC_ARC_ON_SPHERE_TRAITS_2_H #define CGAL_ARR_GEODESIC_ARC_ON_SPHERE_TRAITS_2_H @@ -1646,7 +1646,10 @@ public: Project project, OutputIterator oi) const { - typedef std::pair Point_2_pair; + typedef std::pair Intersection_point; + typedef boost::variant + Intersection_result; + const Kernel* kernel = m_traits; typename Kernel::Equal_2 equal = kernel->equal_2_object(); @@ -1658,7 +1661,7 @@ public: if (equal(l1, l2)) { const Point_2& trg = (in_between(r1, l2, r2)) ? r1_3 : r2_3; X_monotone_curve_2 xc(l1_3, trg, normal, vertical, true); - *oi++ = make_object(xc); + *oi++ = Intersection_result(xc); return oi; } @@ -1668,29 +1671,29 @@ public: if (l1_eq_start || (!l2_eq_start && in_between(l1, start, l2))) { // The following applies only to full circles: if (l1_eq_start && equal(r2, start)) - *oi++ = make_object(Point_2_pair(r2_3, 1)); + *oi++ = Intersection_result(Intersection_point(r2_3, 1)); if (in_between(r1, l1, l2)) return oi; // no intersection if (equal(r1, l2)) { - *oi++ = make_object(Point_2_pair(r1_3, 1)); + *oi++ = Intersection_result(Intersection_point(r1_3, 1)); return oi; } const Point_2& trg = (in_between(r1, l2, r2)) ? r1_3 : r2_3; X_monotone_curve_2 xc(l2_3, trg, normal, vertical, true); - *oi++ = make_object(xc); + *oi++ = Intersection_result(xc); return oi; } CGAL_assertion(l2_eq_start || in_between(l2, start, l1)); // The following applies only to full circles: if (l2_eq_start && equal(r1, start)) - *oi++ = make_object(Point_2_pair(r1_3, 1)); + *oi++ = Intersection_result(Intersection_point(r1_3, 1)); if (in_between(r2, l2, l1)) return oi; // no intersection if (equal(r2, l1)) { - *oi++ = make_object(Point_2_pair(r2_3, 1)); + *oi++ = Intersection_result(Intersection_point(r2_3, 1)); return oi; } const Point_2& trg = (in_between(r1, l2, r2)) ? r1_3 : r2_3; X_monotone_curve_2 xc(l1_3, trg, normal, vertical, true); - *oi++ = make_object(xc); + *oi++ = Intersection_result(xc); return oi; } @@ -1784,9 +1787,12 @@ public: typedef Arr_geodesic_arc_on_sphere_traits_2 Traits; typedef typename Kernel::Counterclockwise_in_between_2 Counterclockwise_in_between_2; - typedef typename Kernel::Equal_3 Equal_3; + typedef typename Kernel::Equal_3 Equal_3; + + typedef std::pair Intersection_point; + typedef boost::variant + Intersection_result; - typedef std::pair Point_2_pair; const Kernel* kernel = m_traits; Equal_3 equal_3 = kernel->equal_3_object(); @@ -1810,9 +1816,9 @@ public: (res && (xc1.is_directed_right() != xc2.is_directed_right()))) { if (xc1.left().is_min_boundary() && xc2.left().is_min_boundary()) - *oi++ = make_object(Point_2_pair(xc1.left(), 1)); + *oi++ = Intersection_result(Intersection_point(xc1.left(), 1)); if (xc1.right().is_max_boundary() && xc2.right().is_max_boundary()) - *oi++ = make_object(Point_2_pair(xc1.right(), 1)); + *oi++ = Intersection_result(Intersection_point(xc1.right(), 1)); return oi; } @@ -1820,11 +1826,11 @@ public: * the other arc is completely overlapping. */ if (xc1.left().is_min_boundary() && xc1.right().is_max_boundary()) { - *oi++ = make_object(xc2); + *oi++ = Intersection_result(xc2); return oi; } if (xc2.left().is_min_boundary() && xc2.right().is_max_boundary()) { - *oi++ = make_object(xc1); + *oi++ = Intersection_result(xc1); return oi; } /*! Find an endpoint that does not coincide with a pole, and project @@ -1877,14 +1883,14 @@ public: // Determine which one of the two directions: Point_2 ed(v.direction()); if (is_in_between(ed, xc1) && is_in_between(ed, xc2)) { - *oi++ = make_object(Point_2_pair(ed, 1)); + *oi++ = Intersection_result(Intersection_point(ed, 1)); return oi; } Vector_3 vo(kernel->construct_opposite_vector_3_object()(v)); Point_2 edo(vo.direction()); if (is_in_between(edo, xc1) && is_in_between(edo, xc2)) { - *oi++ = make_object(Point_2_pair(edo, 1)); + *oi++ = Intersection_result(Intersection_point(edo, 1)); return oi; } return oi; diff --git a/Arrangement_on_surface_2/include/CGAL/Arr_geometry_traits/Bezier_cache.h b/Arrangement_on_surface_2/include/CGAL/Arr_geometry_traits/Bezier_cache.h index 87a104c032f..3910c36249d 100644 --- a/Arrangement_on_surface_2/include/CGAL/Arr_geometry_traits/Bezier_cache.h +++ b/Arrangement_on_surface_2/include/CGAL/Arr_geometry_traits/Bezier_cache.h @@ -52,11 +52,11 @@ public: /// \name Type definitions for the intersection-point mapping. //@{ - /*! \struct Intersection_point_2 + /*! \struct Intersection_point * Representation of an intersection point (in both parameter and physical * spaces). */ - struct Intersection_point_2 + struct Intersection_point { Algebraic s; // The parameter for the first curve. Algebraic t; // The parameter for the second curve. @@ -64,7 +64,7 @@ public: Algebraic y; // The y-coordinate. /*! Constructor. */ - Intersection_point_2 (const Algebraic& _s, const Algebraic& _t, + Intersection_point (const Algebraic& _s, const Algebraic& _t, const Algebraic& _x, const Algebraic& _y) : s(_s), t(_t), x(_x), y(_y) @@ -73,7 +73,7 @@ public: typedef std::pair Curve_pair; typedef std::pair Parameter_pair; - typedef std::list Intersection_list; + typedef std::list Intersection_list; typedef typename Intersection_list::const_iterator Intersection_iter; @@ -378,7 +378,7 @@ _Bezier_cache::get_intersections CGAL::compare (nt_traits.evaluate_at (polyY_1, *t_it), y) == EQUAL) { - info.first.push_back (Intersection_point_2 (*s_it, *t_it, + info.first.push_back (Intersection_point (*s_it, *t_it, x / denX, y / denY)); } } @@ -535,10 +535,8 @@ _Bezier_cache::get_intersections CGAL_assertion(CGAL::sign (s) != NEGATIVE && CGAL::compare (s, one) != LARGER && CGAL::sign (t) != NEGATIVE && CGAL::compare (t, one) != LARGER); - if (!swapt) - info.first.push_back (Intersection_point_2 (s, t,pit1->x, pit1->y)); - else - info.first.push_back (Intersection_point_2 (t, s,pit1->x, pit1->y)); + if (!swapt) info.first.push_back(Intersection_point(s, t,pit1->x, pit1->y)); + else info.first.push_back(Intersection_point(t, s,pit1->x, pit1->y)); } info.second = false; diff --git a/Arrangement_on_surface_2/include/CGAL/Arr_geometry_traits/Bezier_x_monotone_2.h b/Arrangement_on_surface_2/include/CGAL/Arr_geometry_traits/Bezier_x_monotone_2.h index 70bbc9801d4..ca3431e83b9 100644 --- a/Arrangement_on_surface_2/include/CGAL/Arr_geometry_traits/Bezier_x_monotone_2.h +++ b/Arrangement_on_surface_2/include/CGAL/Arr_geometry_traits/Bezier_x_monotone_2.h @@ -7,8 +7,8 @@ // $Id$ // SPDX-License-Identifier: GPL-3.0-or-later OR LicenseRef-Commercial // -// Author(s) : Ron Wein -// Iddo Hanniel +// Author(s): Ron Wein +// Iddo Hanniel #ifndef CGAL_BEZIER_X_MONOTONE_2_H #define CGAL_BEZIER_X_MONOTONE_2_H @@ -85,27 +85,24 @@ private: typedef typename Bezier_cache::Intersection_iter Intersect_iter; // Representation of an intersection point with its multiplicity: - typedef std::pair Intersection_point_2; + typedef std::pair Intersection_point; /*! \class Less_intersection_point * Comparison functor for intersection points. */ - class Less_intersection_point - { + class Less_intersection_point { private: - Bezier_cache *p_cache; + Bezier_cache* p_cache; public: - Less_intersection_point (Bezier_cache& cache) : - p_cache (&cache) - {} + Less_intersection_point(Bezier_cache& cache) : p_cache(&cache) {} - bool operator() (const Intersection_point_2& ip1, - const Intersection_point_2& ip2) const + bool operator()(const Intersection_point& ip1, + const Intersection_point& ip2) const { // Use an xy-lexicographic comparison. - return (ip1.first.compare_xy (ip2.first, *p_cache) == SMALLER); + return (ip1.first.compare_xy(ip2.first, *p_cache) == SMALLER); } }; @@ -117,7 +114,7 @@ private: */ struct Less_curve_pair { - bool operator() (const Curve_pair& cp1, const Curve_pair& cp2) const + bool operator()(const Curve_pair& cp1, const Curve_pair& cp2) const { // Compare the pairs of IDs lexicographically. return (cp1.first < cp2.first || @@ -128,34 +125,32 @@ private: /*! \struct Subcurve * For the usage of the _exact_vertical_position() function. */ - struct Subcurve - { - std::list control_points; - Rational t_min; - Rational t_max; + struct Subcurve { + std::list control_points; + Rational t_min; + Rational t_max; /*! Get the rational bounding box of the subcurve. */ - void bbox (Rational& x_min, Rational& y_min, - Rational& x_max, Rational& y_max) const + void bbox(Rational& x_min, Rational& y_min, + Rational& x_max, Rational& y_max) const { - typename std::list::const_iterator pit = + typename std::list::const_iterator pit = control_points.begin(); - CGAL_assertion (pit != control_points.end()); + CGAL_assertion(pit != control_points.end()); x_min = x_max = pit->x(); y_min = y_max = pit->y(); - for (++pit; pit != control_points.end(); ++pit) - { - if (CGAL::compare (x_min, pit->x()) == LARGER) + for (++pit; pit != control_points.end(); ++pit) { + if (CGAL::compare(x_min, pit->x()) == LARGER) x_min = pit->x(); - else if (CGAL::compare (x_max, pit->x()) == SMALLER) + else if (CGAL::compare(x_max, pit->x()) == SMALLER) x_max = pit->x(); - if (CGAL::compare (y_min, pit->y()) == LARGER) + if (CGAL::compare(y_min, pit->y()) == LARGER) y_min = pit->y(); - else if (CGAL::compare (y_max, pit->y()) == SMALLER) + else if (CGAL::compare(y_max, pit->y()) == SMALLER) y_max = pit->y(); } @@ -189,10 +184,10 @@ private: public: /*! Default constructor. */ - _Bezier_x_monotone_2 () : + _Bezier_x_monotone_2() : _xid(0), - _dir_right (false), - _is_vert (false) + _dir_right(false), + _is_vert(false) {} /*! @@ -209,80 +204,56 @@ public: * \pre B should be an originator of both ps and pt. * \pre xid is a non-zero serial number. */ - _Bezier_x_monotone_2 (const Curve_2& B, unsigned int xid, - const Point_2& ps, const Point_2& pt, - Bezier_cache& cache); + _Bezier_x_monotone_2(const Curve_2& B, unsigned int xid, + const Point_2& ps, const Point_2& pt, + Bezier_cache& cache); /*! * Get the supporting Bezier curve. */ - const Curve_2& supporting_curve () const - { - return (_curve); - } + const Curve_2& supporting_curve() const { return (_curve); } /*! * Get the x-monotone ID of the curve. */ - unsigned int xid () const - { - return (_xid); - } + unsigned int xid() const { return (_xid); } /*! * Get the source point. */ - const Point_2& source () const - { - return (_ps); - } + const Point_2& source() const { return (_ps); } /*! * Get the target point. */ - const Point_2& target () const - { - return (_pt); - } + const Point_2& target() const { return (_pt); } /*! * Get the left endpoint (the lexicographically smaller one). */ - const Point_2& left () const - { - return (_dir_right ? _ps : _pt); - } + const Point_2& left() const { return (_dir_right ? _ps : _pt); } /*! * Get the right endpoint (the lexicographically larger one). */ - const Point_2& right () const - { - return (_dir_right ? _pt : _ps); - } + const Point_2& right() const { return (_dir_right ? _pt : _ps); } /*! * Check if the subcurve is a vertical segment. */ - bool is_vertical () const - { - return (_is_vert); - } + bool is_vertical() const { return (_is_vert); } /*! * Check if the subcurve is directed from left to right. */ - bool is_directed_right () const - { - return (_dir_right); - } + bool is_directed_right() const { return (_dir_right); } /*! * Get the approximate parameter range defining the curve. * \return A pair of t_src and t_trg, where B(t_src) is the source point * and B(t_trg) is the target point. */ - std::pair parameter_range () const; + std::pair parameter_range() const; /*! * Get the relative position of the query point with respect to the subcurve. @@ -293,8 +264,8 @@ public: * LARGER if the point is above the arc; * EQUAL if p lies on the arc. */ - Comparison_result point_position (const Point_2& p, - Bezier_cache& cache) const; + Comparison_result point_position(const Point_2& p, + Bezier_cache& cache) const; /*! * Compare the relative y-position of two x-monotone subcurve to the right @@ -307,9 +278,9 @@ public: * EQUAL in case of an overlap (should not happen); * LARGER if (*this) lies above cv to the right of p. */ - Comparison_result compare_to_right (const Self& cv, - const Point_2& p, - Bezier_cache& cache) const; + Comparison_result compare_to_right(const Self& cv, + const Point_2& p, + Bezier_cache& cache) const; /*! * Compare the relative y-position of two x-monotone subcurve to the left @@ -322,106 +293,90 @@ public: * EQUAL in case of an overlap (should not happen); * LARGER if (*this) lies above cv to the right of p. */ - Comparison_result compare_to_left (const Self& cv, - const Point_2& p, - Bezier_cache& cache) const; + Comparison_result compare_to_left(const Self& cv, + const Point_2& p, + Bezier_cache& cache) const; - /*! - * Check whether the two subcurves are equal (have the same graph). + /*! Check whether the two subcurves are equal (have the same graph). * \param cv The other subcurve. * \param cache Caches the vertical tangency points and intersection points. * \return (true) if the two subcurves have the same graph; * (false) otherwise. */ - bool equals (const Self& cv, - Bezier_cache& cache) const; + bool equals(const Self& cv, Bezier_cache& cache) const; - /*! - * Compute the intersections with the given subcurve. + /*! Compute the intersections with the given subcurve. * \param cv The other subcurve. * \param inter_map Caches the bounded intersection points. * \param cache Caches the vertical tangency points and intersection points. * \param oi The output iterator. * \return The past-the-end iterator. */ - template - OutputIterator intersect (const Self& cv, - Intersection_map& inter_map, - Bezier_cache& cache, - OutputIterator oi) const + template + OutputIterator intersect(const Self& cv, + Intersection_map& inter_map, + Bezier_cache& cache, + OutputIterator oi) const { + typedef boost::variant Intersection_result; + // In case we have two x-monotone subcurves of the same Bezier curve, // check if they have a common left endpoint. - if (_curve.is_same (cv._curve)) - { - if (left().is_same (cv.left()) || left().is_same (cv.right())) - { - *oi = CGAL::make_object (Intersection_point_2 (left(), 0)); - ++oi; - } + if (_curve.is_same(cv._curve)) { + if (left().is_same(cv.left()) || left().is_same(cv.right())) + *oi++ = Intersection_result(Intersection_point(left(), 0)); } // Compute the intersections of the two sucurves. Note that for caching // purposes we always apply the _intersect() function on the subcurve whose // curve ID is smaller. - std::vector ipts; - Self ovlp_cv; - bool do_ovlp; + std::vector ipts; + Self ovlp_cv; + bool do_ovlp; if (_curve.id() <= cv._curve.id()) - do_ovlp = _intersect (cv, inter_map, cache, ipts, ovlp_cv); + do_ovlp = _intersect(cv, inter_map, cache, ipts, ovlp_cv); else - do_ovlp = cv._intersect (*this, inter_map, cache, ipts, ovlp_cv); + do_ovlp = cv._intersect(*this, inter_map, cache, ipts, ovlp_cv); // In case of overlap, just report the overlapping subcurve. - if (do_ovlp) - { - *oi = CGAL::make_object (ovlp_cv); - ++oi; - return (oi); + if (do_ovlp) { + *oi++ = Intersection_result(ovlp_cv); + return oi; } // If we have a set of intersection points, sort them in ascending // xy-lexicorgraphical order, and insert them to the output iterator. - typename std::vector::const_iterator ip_it; - - std::sort (ipts.begin(), ipts.end(), Less_intersection_point (cache)); - for (ip_it = ipts.begin(); ip_it != ipts.end(); ++ip_it) - { - *oi = CGAL::make_object (*ip_it); - ++oi; + std::sort(ipts.begin(), ipts.end(), Less_intersection_point(cache)); + for (auto ip_it = ipts.begin(); ip_it != ipts.end(); ++ip_it) { + *oi++ = Intersection_result(*ip_it); } // In case we have two x-monotone subcurves of the same Bezier curve, // check if they have a common right endpoint. - if (_curve.is_same (cv._curve)) - { - if (right().is_same (cv.left()) || right().is_same (cv.right())) - { - *oi = CGAL::make_object (Intersection_point_2 (right(), 0)); - ++oi; + if (_curve.is_same(cv._curve)) { + if (right().is_same(cv.left()) || right().is_same(cv.right())) { + *oi++ = Intersection_result(Intersection_point(right(), 0)); } } - return (oi); + return oi; } - /*! - * Split the subcurve into two at a given split point. + /*! Split the subcurve into two at a given split point. * \param p The split point. * \param c1 Output: The first resulting arc, lying to the left of p. * \param c2 Output: The first resulting arc, lying to the right of p. * \pre p lies in the interior of the subcurve (not one of its endpoints). */ - void split (const Point_2& p, - Self& c1, Self& c2) const; + void split(const Point_2& p, Self& c1, Self& c2) const; /*! * Check if the two subcurves are mergeable. * \param cv The other subcurve. * \return Whether the two subcurves can be merged. */ - bool can_merge_with (const Self& cv) const; + bool can_merge_with(const Self& cv) const; /*! * Merge the current arc with the given arc. @@ -429,13 +384,13 @@ public: * \pre The two arcs are mergeable. * \return The merged arc. */ - Self merge (const Self& cv) const; + Self merge(const Self& cv) const; /*! * Flip the subcurve (swap its source and target points). * \return The flipped subcurve. */ - Self flip () const + Self flip() const { // Note that we just swap the source and target of the original subcurve // and do not touch the supporting Beizer curve. @@ -445,7 +400,7 @@ public: cv._pt = this->_ps; cv._dir_right = ! this->_dir_right; - return (cv); + return cv; } Self trim(const Point_2& src, const Point_2& tgt) const @@ -460,26 +415,21 @@ public: } private: - - /*! - * Check if the given t-value is in the range of the subcurve. + /*! Check if the given t-value is in the range of the subcurve. * \param t The parameter value. * \param cache Caches the vertical tangency points and intersection points. * \return If t in the parameter-range of the subcurve. */ - bool _is_in_range (const Algebraic& t, - Bezier_cache& cache) const; + bool _is_in_range(const Algebraic& t, Bezier_cache& cache) const; - /*! - * Check if the given point lies in the range of this x-monotone subcurve. + /*! Check if the given point lies in the range of this x-monotone subcurve. * \param p The point, which lies on the supporting Bezier curve. * \param is_certain Output: Is the answer we provide is certain. * \return Whether p is on the x-monotone subcurve. */ - bool _is_in_range (const Point_2& p, bool& is_certain) const; + bool _is_in_range(const Point_2& p, bool& is_certain) const; - /*! - * Given a point p that lies on the supporting Bezier curve (X(t), Y(t)), + /*! Given a point p that lies on the supporting Bezier curve (X(t), Y(t)), * determine whether p lies within the t-range of the x-monotone subcurve. * If so, the value t0 such that p = (X(t0), Y(t0)) is also computed. * \param p The point, which lies on the supporting Bezier curve. @@ -488,23 +438,20 @@ private: * \param is_endpoint Output: Whether p equals on the of the endpoints. * \return Whether p lies in the t-range of the subcurve. */ - bool _is_in_range (const Point_2& p, - Bezier_cache& cache, - Algebraic& t0, - bool& is_endpoint) const; + bool _is_in_range(const Point_2& p, + Bezier_cache& cache, + Algebraic& t0, + bool& is_endpoint) const; - /*! - * Compute a y-coordinate of a point on the x-monotone subcurve with a + /*! Compute a y-coordinate of a point on the x-monotone subcurve with a * given x-coordinate. * \param x0 The given x-coodinate. * \param cache Caches the vertical tangency points and intersection points. * \return The y-coordinate. */ - Algebraic _get_y (const Rational& x0, - Bezier_cache& cache) const; + Algebraic _get_y(const Rational& x0, Bezier_cache& cache) const; - /*! - * Compare the slopes of the subcurve with another given Bezier subcurve at + /*! Compare the slopes of the subcurve with another given Bezier subcurve at * their given intersection point. * \param cv The other subcurve. * \param p The intersection point. @@ -515,20 +462,18 @@ private: * EQUAL if the two slopes are equal; * LARGER if (*this) slope is greater than cv's. */ - Comparison_result _compare_slopes (const Self& cv, - const Point_2& p, - Bezier_cache& cache) const; + Comparison_result _compare_slopes(const Self& cv, + const Point_2& p, + Bezier_cache& cache) const; - /*! - * Get the range of t-value over which the subcurve is defined. + /*! Get the range of t-value over which the subcurve is defined. * \param cache Caches the vertical tangency points and intersection points. * \return A pair comprised of the t-value for the source point and the * t-value for the target point. */ - std::pair _t_range (Bezier_cache& cache) const; + std::pair _t_range(Bezier_cache& cache) const; - /*! - * Compare the relative y-position of two x-monotone subcurve to the right + /*! Compare the relative y-position of two x-monotone subcurve to the right * (or to the left) of their intersection point, whose multiplicity is * greater than 1. * \param cv The other subcurve. @@ -543,25 +488,22 @@ private: * EQUAL in case of an overlap (should not happen); * LARGER if (*this) lies above cv next to p. */ - Comparison_result _compare_to_side (const Self& cv, - const Point_2& p, - bool to_right, - Bezier_cache& cache) const; + Comparison_result _compare_to_side(const Self& cv, + const Point_2& p, + bool to_right, + Bezier_cache& cache) const; - /*! - * Clip the control polygon of the supporting Bezier curve such that it + /*! Clip the control polygon of the supporting Bezier curve such that it * fits the current x-monotone subcurve. * \param ctrl Output: The clipped control polygon. * \param t_min Output: The minimal t-value of the clipped curve. * \param t_max Output: The maximal t-value of the clipped curve. */ - void _clip_control_polygon - (typename Bounding_traits::Control_points& ctrl, - typename Bounding_traits::NT& t_min, - typename Bounding_traits::NT& t_max) const; + void _clip_control_polygon(typename Bounding_traits::Control_points& ctrl, + typename Bounding_traits::NT& t_min, + typename Bounding_traits::NT& t_max) const; - /*! - * Approximate the intersection points between the supporting Bezier curves + /*! Approximate the intersection points between the supporting Bezier curves * of the given x-monotone curves. * \param cv The x-monotone curve we intersect. * \param inter_pts Output: An output list of intersection points between @@ -571,11 +513,10 @@ private: * between the subcurves are approximated. * \return Whether all intersection points where successfully approximated. */ - bool _approximate_intersection_points (const Self& cv, - std::list& inter_pts) const; + bool _approximate_intersection_points(const Self& cv, + std::list& inter_pts) const; - /*! - * Compute the intersections with the given subcurve. + /*! Compute the intersections with the given subcurve. * \param cv The other subcurve. * \param inter_map Caches the bounded intersection points. * \param cache Caches the vertical tangency points and intersection points. @@ -583,14 +524,13 @@ private: * \param ovlp_cv Output: An overlapping subcurve (if exists). * \return Whether an overlap has occurred. */ - bool _intersect (const Self& cv, - Intersection_map& inter_map, - Bezier_cache& cache, - std::vector& ipts, - Self& ovlp_cv) const; + bool _intersect(const Self& cv, + Intersection_map& inter_map, + Bezier_cache& cache, + std::vector& ipts, + Self& ovlp_cv) const; - /*! - * Compute the exact vertical position of the given point with respect to + /*! Compute the exact vertical position of the given point with respect to * the x-monotone curve. * \param p The point. * \param force_exact Sould we force an exact result. @@ -598,64 +538,63 @@ private: * LARGER if the point is above the curve; * EQUAL if p lies on the curve. */ - Comparison_result _exact_vertical_position (const Point_2& p, - bool + Comparison_result _exact_vertical_position(const Point_2& p, + bool #if !defined(CGAL_NO_ASSERTIONS) - force_exact + force_exact #endif - ) const; + ) const; }; /*! * Exporter for Bezier curves. */ -template +template std::ostream& -operator<< (std::ostream& os, - const _Bezier_x_monotone_2& cv) +operator<<(std::ostream& os, + const _Bezier_x_monotone_2 + & cv) { os << cv.supporting_curve() << " [" << cv.xid() << "] | " << cv.source() << " --> " << cv.target(); - return (os); + return os; } // --------------------------------------------------------------------------- // Constructor given two endpoints. // -template -_Bezier_x_monotone_2::_Bezier_x_monotone_2 - (const Curve_2& B, unsigned int xid, - const Point_2& ps, const Point_2& pt, - Bezier_cache& cache) : - _curve (B), - _xid (xid), - _ps (ps), - _pt (pt), - _is_vert (false) +template +_Bezier_x_monotone_2:: +_Bezier_x_monotone_2(const Curve_2& B, unsigned int xid, + const Point_2& ps, const Point_2& pt, + Bezier_cache& cache) : + _curve(B), + _xid(xid), + _ps(ps), + _pt(pt), + _is_vert(false) { - CGAL_precondition (xid > 0); + CGAL_precondition(xid > 0); // Get the originators of the point that correspond to the curve B. - Originator_iterator ps_org = ps.get_originator (B, _xid); - CGAL_precondition (ps_org != ps.originators_end()); + Originator_iterator ps_org = ps.get_originator(B, _xid); + CGAL_precondition(ps_org != ps.originators_end()); - Originator_iterator pt_org = pt.get_originator (B, _xid); - CGAL_precondition (pt_org != pt.originators_end()); + Originator_iterator pt_org = pt.get_originator(B, _xid); + CGAL_precondition(pt_org != pt.originators_end()); // Check if the subcurve is directed left or right. - const Comparison_result res = _ps.compare_x (_pt, cache); + const Comparison_result res = _ps.compare_x(_pt, cache); - if (res == EQUAL) - { + if (res == EQUAL) { // We have a vertical segment. Check if the source is below the target. _is_vert = true; - _dir_right = (CGAL::compare (_ps.y(), _pt.y()) == SMALLER); + _dir_right = (CGAL::compare(_ps.y(), _pt.y()) == SMALLER); } else { @@ -665,89 +604,83 @@ _Bezier_x_monotone_2::_Bezier_x_monotone_2 // Check if the value of the parameter t increases when we traverse the // curve from left to right: If the curve is directed to the right, we // check if t_src < t_trg, otherwise we check whether t_src > t_trg. - Comparison_result t_res; + Comparison_result t_res; - if (CGAL::compare (ps_org->point_bound().t_max, - pt_org->point_bound().t_min) == SMALLER || - CGAL::compare (ps_org->point_bound().t_min, - pt_org->point_bound().t_max) == LARGER) + if (CGAL::compare(ps_org->point_bound().t_max, + pt_org->point_bound().t_min) == SMALLER || + CGAL::compare(ps_org->point_bound().t_min, + pt_org->point_bound().t_max) == LARGER) { // Perform the comparison assuming that the possible parameter // values do not overlap. - t_res = CGAL::compare (ps_org->point_bound().t_min, + t_res = CGAL::compare(ps_org->point_bound().t_min, pt_org->point_bound().t_min); } - else - { + else { // In this case both exact parameter values must be known. // We use them to perform an exact comparison. - CGAL_assertion (ps_org->has_parameter() && pt_org->has_parameter()); + CGAL_assertion(ps_org->has_parameter() && pt_org->has_parameter()); - t_res = CGAL::compare (ps_org->parameter(), pt_org->parameter()); + t_res = CGAL::compare(ps_org->parameter(), pt_org->parameter()); } - CGAL_precondition (t_res != EQUAL); + CGAL_precondition(t_res != EQUAL); - if (_dir_right) - _inc_to_right = (t_res == SMALLER); - else - _inc_to_right = (t_res == LARGER); + if (_dir_right) _inc_to_right = (t_res == SMALLER); + else _inc_to_right = (t_res == LARGER); } // --------------------------------------------------------------------------- // Get the approximate parameter range defining the curve. // -template +template std::pair -_Bezier_x_monotone_2::parameter_range () const +_Bezier_x_monotone_2::parameter_range() const { // First try to use the approximate representation of the endpoints. - Originator_iterator s_org = _ps.get_originator (_curve, _xid); - CGAL_assertion (s_org != _ps.originators_end()); + Originator_iterator s_org = _ps.get_originator(_curve, _xid); + CGAL_assertion(s_org != _ps.originators_end()); - Originator_iterator t_org = _pt.get_originator (_curve, _xid); - CGAL_assertion (t_org != _pt.originators_end()); + Originator_iterator t_org = _pt.get_originator(_curve, _xid); + CGAL_assertion(t_org != _pt.originators_end()); - double t_src = (CGAL::to_double (s_org->point_bound().t_min) + - CGAL::to_double (s_org->point_bound().t_max)) / 2; - double t_trg = (CGAL::to_double (t_org->point_bound().t_min) + - CGAL::to_double (t_org->point_bound().t_max)) / 2; + double t_src = (CGAL::to_double(s_org->point_bound().t_min) + + CGAL::to_double(s_org->point_bound().t_max)) / 2; + double t_trg = (CGAL::to_double(t_org->point_bound().t_min) + + CGAL::to_double(t_org->point_bound().t_max)) / 2; - return (std::make_pair (t_src, t_trg)); + return (std::make_pair(t_src, t_trg)); } // --------------------------------------------------------------------------- // Get the relative position of the query point with respect to the subcurve. // -template +template Comparison_result -_Bezier_x_monotone_2::point_position - (const Point_2& p, - Bezier_cache& cache) const +_Bezier_x_monotone_2:: +point_position(const Point_2& p, Bezier_cache& cache) const { Nt_traits nt_traits; //First check if the bezier is a vertical segment - if (is_vertical()) - { - if (! p.is_exact()) p.make_exact (cache); - if (! _ps.is_exact()) _ps.make_exact (cache); - if (! _pt.is_exact()) _ps.make_exact (cache); + if (is_vertical()) { + if (! p.is_exact()) p.make_exact(cache); + if (! _ps.is_exact()) _ps.make_exact(cache); + if (! _pt.is_exact()) _ps.make_exact(cache); - if (p.is_rational() && _ps.is_rational() && _pt.is_rational()) - { + if (p.is_rational() && _ps.is_rational() && _pt.is_rational()) { const Rat_point_2& rat_p = (Rat_point_2) p; const Rat_point_2& rat_ps = (Rat_point_2) _ps; const Rat_point_2& rat_pt = (Rat_point_2) _pt; - Comparison_result res1 = (CGAL::compare (rat_p.y(), rat_ps.y())); - Comparison_result res2 = (CGAL::compare (rat_p.y(), rat_pt.y())); - return (res1==res2 ? res1:EQUAL); + Comparison_result res1 = (CGAL::compare(rat_p.y(), rat_ps.y())); + Comparison_result res2 = (CGAL::compare(rat_p.y(), rat_pt.y())); + return (res1== res2 ? res1:EQUAL); } - Comparison_result res1 = (CGAL::compare (p.y(), _ps.y())); - Comparison_result res2 = (CGAL::compare (p.y(), _pt.y())); - return (res1==res2 ? res1:EQUAL); + Comparison_result res1 = (CGAL::compare(p.y(), _ps.y())); + Comparison_result res2 = (CGAL::compare(p.y(), _pt.y())); + return (res1== res2 ? res1:EQUAL); } if (p.identical(_ps)) { @@ -757,106 +690,99 @@ _Bezier_x_monotone_2::point_position // Then check whether the bezier is an horizontal segment or // if p has the same x-coordinate as one of the endpoint - const Comparison_result res1 = p.compare_x (_ps, cache); + const Comparison_result res1 = p.compare_x(_ps, cache); if (res1 == EQUAL || nt_traits.degree(_curve.y_polynomial()) <= 0) { - if (! p.is_exact()) p.make_exact (cache); - if (! _ps.is_exact()) _ps.make_exact (cache); + if (! p.is_exact()) p.make_exact(cache); + if (! _ps.is_exact()) _ps.make_exact(cache); // If both point are rational, compare their rational y-coordinates. if (p.is_rational() && _ps.is_rational()) { - const Rat_point_2& rat_p = (Rat_point_2) p; - const Rat_point_2& rat_ps = (Rat_point_2) _ps; + const Rat_point_2& rat_p = (Rat_point_2) p; + const Rat_point_2& rat_ps = (Rat_point_2) _ps; - return (CGAL::compare (rat_p.y(), rat_ps.y())); + return (CGAL::compare(rat_p.y(), rat_ps.y())); } // Compare the algebraic y-coordinates. - return (CGAL::compare (p.y(), _ps.y())); + return (CGAL::compare(p.y(), _ps.y())); } - if (p.identical(_pt)) { - return EQUAL; - } + if (p.identical(_pt)) return EQUAL; - const Comparison_result res2 = p.compare_x (_pt, cache); + const Comparison_result res2 = p.compare_x(_pt, cache); - if (res2 == EQUAL) - { + if (res2 == EQUAL) { // In this case both points must be exact. - CGAL_assertion (p.is_exact() && _pt.is_exact()); + CGAL_assertion(p.is_exact() && _pt.is_exact()); // If both point are rational, compare their rational y-coordinates. - if (p.is_rational() && _pt.is_rational()) - { - const Rat_point_2& rat_p = (Rat_point_2) p; - const Rat_point_2& rat_pt = (Rat_point_2) _pt; + if (p.is_rational() && _pt.is_rational()) { + const Rat_point_2& rat_p = (Rat_point_2) p; + const Rat_point_2& rat_pt = (Rat_point_2) _pt; - return (CGAL::compare (rat_p.y(), rat_pt.y())); + return (CGAL::compare(rat_p.y(), rat_pt.y())); } // Compare the algebraic y-coordinates. - return (CGAL::compare (p.y(), _pt.y())); + return (CGAL::compare(p.y(), _pt.y())); } // Make sure that p is in the x-range of our subcurve. - CGAL_precondition (res1 != res2); + CGAL_precondition(res1 != res2); // Check for the case when curve is an originator of the point. - Originator_iterator p_org = p.get_originator (_curve, _xid); + Originator_iterator p_org = p.get_originator(_curve, _xid); - if (p_org != p.originators_end()) - { + if (p_org != p.originators_end()) { CGAL_assertion_code - (Originator_iterator ps_org = _ps.get_originator (_curve, _xid); + (Originator_iterator ps_org = _ps.get_originator(_curve, _xid); CGAL_assertion(ps_org != _ps.originators_end()); - Originator_iterator pt_org = _pt.get_originator (_curve, _xid); + Originator_iterator pt_org = _pt.get_originator(_curve, _xid); CGAL_assertion(pt_org != _pt.originators_end())); // Check if the point is in the parameter range of this subcurve. // First try an approximate check of the parameter bounds. - bool correct_res; - bool in_range = false; + bool correct_res; + bool in_range = false; - in_range = _is_in_range (p, correct_res); + in_range = _is_in_range(p, correct_res); - if (! correct_res) - { + if (! correct_res) { // Perform the comparsion in an exact manner. if (! p.is_exact()) - p.make_exact (cache); + p.make_exact(cache); - CGAL_assertion (p_org->has_parameter()); + CGAL_assertion(p_org->has_parameter()); - in_range = _is_in_range (p_org->parameter(), cache); + in_range = _is_in_range(p_org->parameter(), cache); } - if (in_range) - return (EQUAL); + if (in_range) return (EQUAL); } // Call the vertical-position function that uses the bounding-boxes // to evaluate the comparsion result. - typename Bounding_traits::Control_points cp; + typename Bounding_traits::Control_points cp; - std::copy (_curve.control_points_begin(), _curve.control_points_end(), - std::back_inserter(cp)); + std::copy(_curve.control_points_begin(), _curve.control_points_end(), + std::back_inserter(cp)); - Originator_iterator ps_org = _ps.get_originator (_curve, _xid); - CGAL_assertion (ps_org != _ps.originators_end()); + Originator_iterator ps_org = _ps.get_originator(_curve, _xid); + CGAL_assertion(ps_org != _ps.originators_end()); - Originator_iterator pt_org = _pt.get_originator (_curve, _xid); - CGAL_assertion (pt_org != _pt.originators_end()); + Originator_iterator pt_org = _pt.get_originator(_curve, _xid); + CGAL_assertion(pt_org != _pt.originators_end()); - Comparison_result res_bound = EQUAL; - typename Bounding_traits::NT x_min, y_min, x_max, y_max; - bool can_refine; + Comparison_result res_bound = EQUAL; + typename Bounding_traits::NT x_min, y_min, x_max, y_max; + bool can_refine; - p.get_bbox (x_min, y_min, x_max, y_max); + p.get_bbox(x_min, y_min, x_max, y_max); - if (CGAL::compare (ps_org->point_bound().t_max, + if (CGAL::compare(ps_org->point_bound().t_max, pt_org->point_bound().t_min) == SMALLER) { // Examine the parameter range of the originator of the source point @@ -866,14 +792,13 @@ _Bezier_x_monotone_2::point_position can_refine = ! _ps.is_exact(); do { - const Rat_point_2& ps = _curve (ps_org->point_bound().t_max); + const Rat_point_2& ps = _curve(ps_org->point_bound().t_max); - if ((_dir_right && CGAL::compare (ps.x(), x_min) != LARGER) || - (! _dir_right && CGAL::compare (ps.x(), x_max) != SMALLER)) + if ((_dir_right && CGAL::compare(ps.x(), x_min) != LARGER) || + (! _dir_right && CGAL::compare(ps.x(), x_max) != SMALLER)) break; - if (can_refine) - can_refine = _ps.refine(); + if (can_refine) can_refine = _ps.refine(); } while (can_refine); // Examine the parameter range of the originator of the target point @@ -883,10 +808,10 @@ _Bezier_x_monotone_2::point_position can_refine = ! _pt.is_exact(); do { - const Rat_point_2& pt = _curve (pt_org->point_bound().t_min); + const Rat_point_2& pt = _curve(pt_org->point_bound().t_min); - if ((_dir_right && CGAL::compare (pt.x(), x_max) != SMALLER) || - (! _dir_right && CGAL::compare (pt.x(), x_min) != LARGER)) + if ((_dir_right && CGAL::compare(pt.x(), x_max) != SMALLER) || + (! _dir_right && CGAL::compare(pt.x(), x_min) != LARGER)) break; if (can_refine) @@ -896,11 +821,11 @@ _Bezier_x_monotone_2::point_position // In this case the parameter value of the source is smaller than the // target's, so we compare the point with the subcurve of B defined over // the proper parameter range. - res_bound = p.vertical_position (cp, + res_bound = p.vertical_position(cp, ps_org->point_bound().t_max, pt_org->point_bound().t_min); } - else if (CGAL::compare (pt_org->point_bound().t_max, + else if (CGAL::compare(pt_org->point_bound().t_max, ps_org->point_bound().t_min) == SMALLER) { // Examine the parameter range of the originator of the source point @@ -908,12 +833,11 @@ _Bezier_x_monotone_2::point_position // lies to the left of p if the curve is directed from left to right // (or to the right of p, if the subcurve is directed from right to left). can_refine = ! _ps.is_exact(); - do - { - const Rat_point_2& ps = _curve (ps_org->point_bound().t_min); + do { + const Rat_point_2& ps = _curve(ps_org->point_bound().t_min); - if ((_dir_right && CGAL::compare (ps.x(), x_min) != LARGER) || - (! _dir_right && CGAL::compare (ps.x(), x_max) != SMALLER)) + if ((_dir_right && CGAL::compare(ps.x(), x_min) != LARGER) || + (! _dir_right && CGAL::compare(ps.x(), x_max) != SMALLER)) break; if (can_refine) @@ -925,12 +849,11 @@ _Bezier_x_monotone_2::point_position // lies to the right of p if the curve is directed from left to right // (or to the left of p, if the subcurve is directed from right to left). can_refine = ! _pt.is_exact(); - do - { - const Rat_point_2& pt = _curve (pt_org->point_bound().t_max); + do { + const Rat_point_2& pt = _curve(pt_org->point_bound().t_max); - if ((_dir_right && CGAL::compare (pt.x(), x_max) != SMALLER) || - (! _dir_right && CGAL::compare (pt.x(), x_min) != LARGER)) + if ((_dir_right && CGAL::compare(pt.x(), x_max) != SMALLER) || + (! _dir_right && CGAL::compare(pt.x(), x_min) != LARGER)) break; if (can_refine) @@ -940,7 +863,7 @@ _Bezier_x_monotone_2::point_position // In this case the parameter value of the source is large than the // target's, so we compare the point with the subcurve of B defined over // the proper parameter range. - res_bound = p.vertical_position (cp, + res_bound = p.vertical_position(cp, pt_org->point_bound().t_max, ps_org->point_bound().t_min); } @@ -959,13 +882,14 @@ _Bezier_x_monotone_2::point_position std::vector roots; std::pair prange = parameter_range(); - nt_traits.compute_polynomial_roots (poly_x,prange.first,prange.second,std::back_inserter(roots)); + nt_traits.compute_polynomial_roots(poly_x,prange.first,prange.second, std::back_inserter(roots)); - CGAL_assertion(roots.size()==1); //p is in the range and the curve is x-monotone + //p is in the range and the curve is x-monotone + CGAL_assertion(roots.size() == 1); return CGAL::compare( ((Rat_point_2) p).y(), - nt_traits.evaluate_at (_curve.y_polynomial(), *roots.begin()) + nt_traits.evaluate_at(_curve.y_polynomial(), *roots.begin()) ); } @@ -973,22 +897,22 @@ _Bezier_x_monotone_2::point_position // p lies of the given subcurve. We take one of p's originating curves and // compute its intersections with our x-monotone curve. if (! p.is_exact()) - p.make_exact (cache); + p.make_exact(cache); - CGAL_assertion (p.originators_begin() != p.originators_end()); + CGAL_assertion(p.originators_begin() != p.originators_end()); Originator org = *(p.originators_begin()); bool do_ovlp; bool swap_order = (_curve.id() > org.curve().id()); const Intersect_list& inter_list = (! swap_order ? - (cache.get_intersections (_curve.id(), + (cache.get_intersections(_curve.id(), _curve.x_polynomial(), _curve.x_norm(), _curve.y_polynomial(), _curve.y_norm(), org.curve().id(), org.curve().x_polynomial(), org.curve().x_norm(), org.curve().y_polynomial(), org.curve().y_norm(), do_ovlp)) : - (cache.get_intersections (org.curve().id(), + (cache.get_intersections(org.curve().id(), org.curve().x_polynomial(), org.curve().x_norm(), org.curve().y_polynomial(), org.curve().y_norm(), _curve.id(), @@ -996,29 +920,24 @@ _Bezier_x_monotone_2::point_position _curve.y_polynomial(), _curve.y_norm(), do_ovlp))); - if (do_ovlp) - return (EQUAL); + if (do_ovlp) return EQUAL; // Go over the intersection points and look for p there. - Intersect_iter iit; - - for (iit = inter_list.begin(); iit != inter_list.end(); ++iit) - { + for (auto iit = inter_list.begin(); iit != inter_list.end(); ++iit) { // Get the parameter of the originator and compare it to p's parameter. - const Algebraic& s = swap_order ? iit->s : iit->t; + const Algebraic& s = swap_order ? iit->s : iit->t; - if (CGAL::compare (s, org.parameter()) == EQUAL) - { + if (CGAL::compare(s, org.parameter()) == EQUAL) { // Add this curve as an originator for p. - const Algebraic& t = swap_order ? iit->t : iit->s; + const Algebraic& t = swap_order ? iit->t : iit->s; - CGAL_assertion (_is_in_range (t, cache)); + CGAL_assertion(_is_in_range(t, cache)); - Point_2& pt = const_cast (p); + Point_2& pt = const_cast(p); pt.add_originator (Originator (_curve, _xid, t)); // The point p lies on the subcurve. - return (EQUAL); + return EQUAL; } } @@ -1027,21 +946,14 @@ _Bezier_x_monotone_2::point_position // between the curve and the point. (This case should be very rare.) // Note that we first try to work with inexact endpoint representation, and // only if we fail we make the endpoints of the x-monotone curves exact. - if (! p.is_exact()) - p.make_exact (cache); + if (! p.is_exact()) p.make_exact (cache); - Comparison_result exact_res = _exact_vertical_position (p, false); + Comparison_result exact_res = _exact_vertical_position(p, false); + if (exact_res != EQUAL) return (exact_res); + if (! _ps.is_exact()) _ps.make_exact(cache); + if (! _pt.is_exact()) _pt.make_exact(cache); - if (exact_res != EQUAL) - return (exact_res); - - if (! _ps.is_exact()) - _ps.make_exact (cache); - - if (! _pt.is_exact()) - _pt.make_exact (cache); - - return (_exact_vertical_position (p, true)); + return (_exact_vertical_position(p, true)); } // --------------------------------------------------------------------------- @@ -1050,57 +962,45 @@ _Bezier_x_monotone_2::point_position // template Comparison_result -_Bezier_x_monotone_2::compare_to_right - (const Self& cv, - const Point_2& p, - Bezier_cache& cache) const +_Bezier_x_monotone_2:: +compare_to_right(const Self& cv, + const Point_2& p, + Bezier_cache& cache) const { CGAL_precondition (p.compare_xy (right(), cache) != LARGER); CGAL_precondition (p.compare_xy (cv.right(), cache) != LARGER); - if (this == &cv) - return (EQUAL); + if (this == &cv) return EQUAL; // Make sure that p is incident to both curves (either equals the left // endpoint or lies in the curve interior). Note that this is important to // carry out these tests, as it assures us the eventually both curves are // originators of p. - if (! p.equals (left(), cache)) - { - if (point_position (p, cache) != EQUAL) - { + if (! p.equals (left(), cache)) { + if (point_position (p, cache) != EQUAL) { CGAL_precondition_msg (false, "p is not on cv1"); } } - if (! p.equals (cv.left(), cache)) - { - if (cv.point_position (p, cache) != EQUAL) - { + if (! p.equals (cv.left(), cache)) { + if (cv.point_position (p, cache) != EQUAL) { CGAL_precondition_msg (false, "p is not on cv2"); } } // Check for vertical subcurves. A vertical segment is above any other // x-monotone subcurve to the right of their common endpoint. - if (is_vertical()) - { - if (cv.is_vertical()) - // Both are vertical segments with a common endpoint, so they overlap: - return (EQUAL); - + if (is_vertical()) { + // Both are vertical segments with a common endpoint, so they overlap: + if (cv.is_vertical()) return (EQUAL); return (LARGER); } - else if (cv.is_vertical()) - { - return (SMALLER); - } + else if (cv.is_vertical()) return (SMALLER); // Check if both subcurves originate from the same Bezier curve. - Nt_traits nt_traits; + Nt_traits nt_traits; - if (_curve.is_same (cv._curve)) - { + if (_curve.is_same (cv._curve)) { // Get the originator, and check whether p is a vertical tangency // point of this originator (otherwise it is a self-intersection point, // and we proceed as if it is a regular intersection point). @@ -1108,24 +1008,20 @@ _Bezier_x_monotone_2::compare_to_right CGAL_assertion (org != p.originators_end()); - if (org->point_bound().type == Bez_point_bound::VERTICAL_TANGENCY_PT) - { + if (org->point_bound().type == Bez_point_bound::VERTICAL_TANGENCY_PT) { CGAL_assertion (_inc_to_right != cv._inc_to_right); - if (! p.is_exact()) - { + if (! p.is_exact()) { // Comparison based on the control polygon of the bounded vertical // tangency point, using the fact this polygon is y-monotone. const typename Bounding_traits::Control_points& cp = org->point_bound().ctrl; - if (_inc_to_right) - { - return (CGAL::compare (cp.back().y(), cp.front().y())); + if (_inc_to_right) { + return (CGAL::compare(cp.back().y(), cp.front().y())); } - else - { - return (CGAL::compare (cp.front().y(), cp.back().y())); + else { + return (CGAL::compare(cp.front().y(), cp.back().y())); } } @@ -1134,14 +1030,14 @@ _Bezier_x_monotone_2::compare_to_right // In this case we know that we have a vertical tangency at t0, so // X'(t0) = 0. We evaluate the sign of Y'(t0) in order to find the // vertical position of the two subcurves to the right of this point. - CGAL_assertion (org->has_parameter()); + CGAL_assertion(org->has_parameter()); - const Algebraic& t0 = org->parameter(); - Polynomial polyY_der = nt_traits.derive (_curve.y_polynomial()); - const CGAL::Sign sign_der = - CGAL::sign (nt_traits.evaluate_at (polyY_der, t0)); + const Algebraic& t0 = org->parameter(); + Polynomial polyY_der = nt_traits.derive(_curve.y_polynomial()); + const CGAL::Sign sign_der = + CGAL::sign(nt_traits.evaluate_at(polyY_der, t0)); - CGAL_assertion (sign_der != CGAL::ZERO); + CGAL_assertion(sign_der != CGAL::ZERO); if (_inc_to_right) return ((sign_der == CGAL::POSITIVE) ? LARGER : SMALLER); @@ -1153,28 +1049,27 @@ _Bezier_x_monotone_2::compare_to_right // Compare the slopes of the two supporting curves at p. In the general // case, the slopes are not equal and their comparison gives us the // vertical order to p's right. - Comparison_result slope_res = _compare_slopes (cv, p, cache); + Comparison_result slope_res = _compare_slopes(cv, p, cache); - if (slope_res != EQUAL) - return (slope_res); + if (slope_res != EQUAL) return (slope_res); // Compare the two subcurves by choosing some point to the right of p // and comparing the vertical position there. Comparison_result right_res; - if (right().compare_x (cv.right(), cache) != LARGER) + if (right().compare_x(cv.right(), cache) != LARGER) { - right_res = _compare_to_side (cv, p, + right_res = _compare_to_side(cv, p, true, // Compare to p's right. cache); } else { - right_res = cv._compare_to_side (*this, p, + right_res = cv._compare_to_side(*this, p, true, // Compare to p's right. cache); - right_res = CGAL::opposite (right_res); + right_res = CGAL::opposite(right_res); } return (right_res); @@ -1191,8 +1086,8 @@ _Bezier_x_monotone_2::compare_to_left const Point_2& p, Bezier_cache& cache) const { - CGAL_precondition (p.compare_xy (left(), cache) != SMALLER); - CGAL_precondition (p.compare_xy (cv.left(), cache) != SMALLER); + CGAL_precondition(p.compare_xy(left(), cache) != SMALLER); + CGAL_precondition(p.compare_xy(cv.left(), cache) != SMALLER); if (this == &cv) return (EQUAL); @@ -1201,19 +1096,19 @@ _Bezier_x_monotone_2::compare_to_left // endpoint or lies in the curve interior). Note that this is important to // carry out these tests, as it assures us the eventually both curves are // originators of p. - if (! p.equals (right(), cache)) + if (! p.equals(right(), cache)) { - if (point_position (p, cache) != EQUAL) + if (point_position(p, cache) != EQUAL) { - CGAL_precondition_msg (false, "p is not on cv1"); + CGAL_precondition_msg(false, "p is not on cv1"); } } - if (! p.equals (cv.right(), cache)) + if (! p.equals(cv.right(), cache)) { - if (cv.point_position (p, cache) != EQUAL) + if (cv.point_position(p, cache) != EQUAL) { - CGAL_precondition_msg (false, "p is not on cv2"); + CGAL_precondition_msg(false, "p is not on cv2"); } } @@ -1235,15 +1130,15 @@ _Bezier_x_monotone_2::compare_to_left // Check if both subcurves originate from the same Bezier curve. Nt_traits nt_traits; - if (_curve.is_same (cv._curve)) + if (_curve.is_same(cv._curve)) { // Get the originator, and check whether p is a vertical tangency // point of this originator (otherwise it is a self-intersection point, // and we proceed as if it is a regular intersection point). - Originator_iterator org = p.get_originator (_curve, _xid); + Originator_iterator org = p.get_originator(_curve, _xid); - CGAL_assertion (org != p.originators_end()); - CGAL_assertion (_inc_to_right != cv._inc_to_right); + CGAL_assertion(org != p.originators_end()); + CGAL_assertion(_inc_to_right != cv._inc_to_right); if (org->point_bound().type == Bez_point_bound::VERTICAL_TANGENCY_PT) { @@ -1269,14 +1164,14 @@ _Bezier_x_monotone_2::compare_to_left // In this case we know that we have a vertical tangency at t0, so // X'(t0) = 0. We evaluate the sign of Y'(t0) in order to find the // vertical position of the two subcurves to the right of this point. - CGAL_assertion (org->has_parameter()); + CGAL_assertion(org->has_parameter()); const Algebraic& t0 = org->parameter(); - Polynomial polyY_der = nt_traits.derive (_curve.y_polynomial()); + Polynomial polyY_der = nt_traits.derive(_curve.y_polynomial()); const CGAL::Sign sign_der = - CGAL::sign (nt_traits.evaluate_at (polyY_der, t0)); + CGAL::sign(nt_traits.evaluate_at(polyY_der, t0)); - CGAL_assertion (sign_der != CGAL::ZERO); + CGAL_assertion(sign_der != CGAL::ZERO); if (_inc_to_right) return ((sign_der == CGAL::NEGATIVE) ? LARGER : SMALLER); @@ -1289,7 +1184,7 @@ _Bezier_x_monotone_2::compare_to_left // case, the slopes are not equal and their comparison gives us the // vertical order to p's right; note that we swap the order of the curves // to obtains their position to the left. - Comparison_result slope_res = cv._compare_slopes (*this, p, cache); + Comparison_result slope_res = cv._compare_slopes(*this, p, cache); if (slope_res != EQUAL) return (slope_res); @@ -1298,18 +1193,18 @@ _Bezier_x_monotone_2::compare_to_left // and compareing the vertical position there. Comparison_result left_res; - if (left().compare_x (cv.left(), cache) != SMALLER) + if (left().compare_x(cv.left(), cache) != SMALLER) { - left_res = _compare_to_side (cv, p, + left_res = _compare_to_side(cv, p, false, // Compare to p's left. cache); } else { - left_res = cv._compare_to_side (*this, p, + left_res = cv._compare_to_side(*this, p, false, // Compare to p's left. cache); - left_res = CGAL::opposite (left_res); + left_res = CGAL::opposite(left_res); } return (left_res); @@ -1324,7 +1219,7 @@ bool _Bezier_x_monotone_2::equals Bezier_cache& cache) const { // Check if the two subcurves have overlapping supporting curves. - if (! _curve.is_same (cv._curve)) + if (! _curve.is_same(cv._curve)) { //special case when curves are vertical if (cv.is_vertical()){ @@ -1334,7 +1229,7 @@ bool _Bezier_x_monotone_2::equals } // Check whether the two curves have the same support: - if (! _curve.has_same_support (cv._curve)) + if (! _curve.has_same_support(cv._curve)) return (false); // Mark that the two curves overlap in the cache. @@ -1342,14 +1237,14 @@ bool _Bezier_x_monotone_2::equals const Curve_id id2 = cv._curve.id(); if (id1 < id2) - cache.mark_as_overlapping (id1, id2); + cache.mark_as_overlapping(id1, id2); else - cache.mark_as_overlapping (id2, id1); + cache.mark_as_overlapping(id2, id1); } // Check for equality of the endpoints. - return (left().equals (cv.left(), cache) && - right().equals (cv.right(), cache)); + return (left().equals(cv.left(), cache) && + right().equals(cv.right(), cache)); } // --------------------------------------------------------------------------- @@ -1405,9 +1300,9 @@ bool _Bezier_x_monotone_2::can_merge_with { // Note that we only allow merging subcurves of the same originating // Bezier curve (overlapping curves will not do in this case). - return (_curve.is_same (cv._curve) && + return (_curve.is_same(cv._curve) && _xid == cv._xid && - (right().is_same (cv.left()) || left().is_same (cv.right()))); + (right().is_same(cv.left()) || left().is_same(cv.right()))); return (false); } @@ -1420,28 +1315,22 @@ typename _Bezier_x_monotone_2::Self _Bezier_x_monotone_2::merge (const Self& cv) const { - CGAL_precondition (_curve.is_same (cv._curve)); - CGAL_precondition (_xid == cv._xid); + CGAL_precondition(_curve.is_same(cv._curve)); + CGAL_precondition(_xid == cv._xid); - Self res = *this; + Self res = *this; - if (right().is_same (cv.left())) - { + if (right().is_same(cv.left())) { // Extend the subcurve to the right. - if (_dir_right) - res._pt = cv.right(); - else - res._ps = cv.right(); + if (_dir_right) res._pt = cv.right(); + else res._ps = cv.right(); } - else - { - CGAL_precondition (left().is_same (cv.right())); + else { + CGAL_precondition(left().is_same(cv.right())); // Extend the subcurve to the left. - if (_dir_right) - res._ps = cv.left(); - else - res._pt = cv.left(); + if (_dir_right) res._ps = cv.left(); + else res._pt = cv.left(); } return (res); @@ -1450,42 +1339,35 @@ _Bezier_x_monotone_2::merge // --------------------------------------------------------------------------- // Check if the given t-value is in the range of the subcurve. // -template -bool _Bezier_x_monotone_2::_is_in_range - (const Algebraic& t, - Bezier_cache& cache) const +template +bool _Bezier_x_monotone_2:: +_is_in_range(const Algebraic& t, Bezier_cache& cache) const { // First try to use the approximate representation of the endpoints. - Originator_iterator s_org = _ps.get_originator (_curve, _xid); - CGAL_assertion (s_org != _ps.originators_end()); + Originator_iterator s_org = _ps.get_originator(_curve, _xid); + CGAL_assertion(s_org != _ps.originators_end()); - Originator_iterator t_org = _pt.get_originator (_curve, _xid); - CGAL_assertion (t_org != _pt.originators_end()); + Originator_iterator t_org = _pt.get_originator (_curve, _xid); + CGAL_assertion(t_org != _pt.originators_end()); - Nt_traits nt_traits; + Nt_traits nt_traits; - bool p_lt_ps = - (CGAL::compare (t, nt_traits.convert (s_org->point_bound().t_min)) == - SMALLER); - bool p_gt_ps = - (CGAL::compare (t, nt_traits.convert (s_org->point_bound().t_max)) == - LARGER); - bool p_lt_pt = - (CGAL::compare (t, nt_traits.convert (t_org->point_bound().t_min)) == - SMALLER); - bool p_gt_pt = - (CGAL::compare (t, nt_traits.convert (t_org->point_bound().t_max)) == - LARGER); + bool p_lt_ps = + CGAL::compare(t, nt_traits.convert(s_org->point_bound().t_min)) == SMALLER; + bool p_gt_ps = + CGAL::compare(t, nt_traits.convert(s_org->point_bound().t_max)) == LARGER; + bool p_lt_pt = + CGAL::compare(t, nt_traits.convert(t_org->point_bound().t_min)) == SMALLER; + bool p_gt_pt = + CGAL::compare(t, nt_traits.convert(t_org->point_bound().t_max)) == LARGER; - if ((p_gt_ps && p_lt_pt) || (p_lt_ps && p_gt_pt)) - { + if ((p_gt_ps && p_lt_pt) || (p_lt_ps && p_gt_pt)) { // The point p is definitely in the x-range of the subcurve, as its // parameter is between the source and target parameters. - return (true); + return true; } - if ((p_lt_ps && p_lt_pt) || (p_gt_ps && p_gt_pt)) - { + if ((p_lt_ps && p_lt_pt) || (p_gt_ps && p_gt_pt)) { // The point p is definitely not in the x-range of the subcurve, // as its parameter is smaller than both source and target parameter // (or greater than both of them). @@ -1506,60 +1388,54 @@ bool _Bezier_x_monotone_2::_is_in_range // --------------------------------------------------------------------------- // Check if the given point lies in the range of this x-monotone subcurve. // -template -bool _Bezier_x_monotone_2::_is_in_range - (const Point_2& p, - bool& is_certain) const +template +bool _Bezier_x_monotone_2:: +_is_in_range(const Point_2& p, bool& is_certain) const { is_certain = true; // Check the easy case that p is one of the subcurve endpoints. - if (p.is_same(_ps) || p.is_same(_pt)) - return true; + if (p.is_same(_ps) || p.is_same(_pt)) return true; // Compare the parameter of p with the parameters of the endpoints. - Originator_iterator p_org = p.get_originator (_curve, _xid); + Originator_iterator p_org = p.get_originator(_curve, _xid); - if (p_org == p.originators_end()) - { - CGAL_assertion (p.get_originator (_curve) != p.originators_end()); + if (p_org == p.originators_end()) { + CGAL_assertion(p.get_originator(_curve) != p.originators_end()); // In this case a different x-monotone curve of the supporting Bezier // curve is an originator of the point, so we know that p does not // lie in the range of our x-monotone subcurve. - return (false); + return false; } - Originator_iterator s_org = _ps.get_originator (_curve, _xid); - CGAL_assertion (s_org != _ps.originators_end()); + Originator_iterator s_org = _ps.get_originator(_curve, _xid); + CGAL_assertion(s_org != _ps.originators_end()); - Originator_iterator t_org = _pt.get_originator (_curve, _xid); - CGAL_assertion (t_org != _pt.originators_end()); + Originator_iterator t_org = _pt.get_originator(_curve, _xid); + CGAL_assertion(t_org != _pt.originators_end()); - bool can_refine_p = ! p.is_exact(); - bool can_refine_s = ! _ps.is_exact(); - bool can_refine_t = ! _pt.is_exact(); + bool can_refine_p = ! p.is_exact(); + bool can_refine_s = ! _ps.is_exact(); + bool can_refine_t = ! _pt.is_exact(); - while (can_refine_p || can_refine_s || can_refine_t) - { - bool p_lt_ps = (CGAL::compare (p_org->point_bound().t_max, - s_org->point_bound().t_min) == SMALLER); - bool p_gt_ps = (CGAL::compare (p_org->point_bound().t_min, - s_org->point_bound().t_max) == LARGER); - bool p_lt_pt = (CGAL::compare (p_org->point_bound().t_max, - t_org->point_bound().t_min) == SMALLER); - bool p_gt_pt = (CGAL::compare (p_org->point_bound().t_min, - t_org->point_bound().t_max) == LARGER); + while (can_refine_p || can_refine_s || can_refine_t) { + bool p_lt_ps = (CGAL::compare(p_org->point_bound().t_max, + s_org->point_bound().t_min) == SMALLER); + bool p_gt_ps = (CGAL::compare(p_org->point_bound().t_min, + s_org->point_bound().t_max) == LARGER); + bool p_lt_pt = (CGAL::compare(p_org->point_bound().t_max, + t_org->point_bound().t_min) == SMALLER); + bool p_gt_pt = (CGAL::compare(p_org->point_bound().t_min, + t_org->point_bound().t_max) == LARGER); - if ((p_gt_ps && p_lt_pt) || (p_lt_ps && p_gt_pt)) - { + if ((p_gt_ps && p_lt_pt) || (p_lt_ps && p_gt_pt)) { // The point p is definitely in the x-range of the subcurve, as its // parameter is between the source and target parameters. return (true); } - if ((p_lt_ps && p_lt_pt) || (p_gt_ps && p_gt_pt)) - { + if ((p_lt_ps && p_lt_pt) || (p_gt_ps && p_gt_pt)) { // The point p is definitely not in the x-range of the subcurve, // as its parameter is smaller than both source and target parameter // (or greater than both of them). @@ -1567,19 +1443,14 @@ bool _Bezier_x_monotone_2::_is_in_range } // Try to refine the points. - if (can_refine_p) - can_refine_p = p.refine(); - - if (can_refine_s) - can_refine_s = _ps.refine(); - - if (can_refine_t) - can_refine_t = _pt.refine(); + if (can_refine_p) can_refine_p = p.refine(); + if (can_refine_s) can_refine_s = _ps.refine(); + if (can_refine_t) can_refine_t = _pt.refine(); } // If we reached here, we do not have a certain answer. is_certain = false; - return (false); + return false; } // --------------------------------------------------------------------------- @@ -1587,35 +1458,32 @@ bool _Bezier_x_monotone_2::_is_in_range // determine whether p lies within the t-range of the x-monotone subcurve. // If so, the value t0 such that p = (X(t0), Y(t0)) is also computed. // -template -bool _Bezier_x_monotone_2::_is_in_range - (const Point_2& p, - Bezier_cache& cache, - Algebraic& t0, - bool& is_endpoint) const +template +bool _Bezier_x_monotone_2:: +_is_in_range(const Point_2& p, + Bezier_cache& cache, + Algebraic& t0, + bool& is_endpoint) const { // The given point p must be rational, otherwise there is no point checking // whether it lies in the interior of the curve. - if (! p.is_rational()) - { + if (! p.is_rational()) { is_endpoint = false; - return (false); + return false; } - const Rat_point_2& rat_p = (Rat_point_2) p; + const Rat_point_2& rat_p = (Rat_point_2) p; // Determine the parameter range [t_min, t_max] for our x-monotone // subcurve. - std::pair t_range = _t_range (cache); - Algebraic t_min, t_max; + std::pair t_range = _t_range (cache); + Algebraic t_min, t_max; - if ((_dir_right && _inc_to_right) || (! _dir_right && ! _inc_to_right)) - { + if ((_dir_right && _inc_to_right) || (! _dir_right && ! _inc_to_right)) { t_min = t_range.first; t_max = t_range.second; } - else - { + else { t_min = t_range.second; t_max = t_range.first; } @@ -1623,90 +1491,78 @@ bool _Bezier_x_monotone_2::_is_in_range // The given point p must lie on (X(t), Y(t)) for some t-value. Obtain the // parameter value t0 for that point. We start by computing all t-values // such that X(t) equals the x-coordinate of p. - Nt_traits nt_traits; - std::list t_vals; - typename std::list::iterator t_iter; - Comparison_result res1, res2; - Algebraic y0; + Nt_traits nt_traits; + std::list t_vals; + typename std::list::iterator t_iter; + Comparison_result res1, res2; + Algebraic y0; - if ( is_vertical() ){ - if ( compare(rat_p.x(),left().x())==EQUAL ){ - _curve.get_t_at_y (rat_p.y(), std::back_inserter(t_vals)); + if (is_vertical()){ + if ( compare(rat_p.x(),left().x()) == EQUAL) { + _curve.get_t_at_y(rat_p.y(), std::back_inserter(t_vals)); - for (t_iter = t_vals.begin(); t_iter != t_vals.end(); ++t_iter) - { + for (t_iter = t_vals.begin(); t_iter != t_vals.end(); ++t_iter) { // Compare the current t-value with t_min. - res1 = CGAL::compare (t_min, *t_iter); + res1 = CGAL::compare(t_min, *t_iter); - if (res1 == LARGER) - continue; + if (res1 == LARGER) continue; - - if (res1 == EQUAL) - { + if (res1 == EQUAL) { t0 = t_min; is_endpoint = true; return (true); } // Compare the current t-value with t_max. - res2 = CGAL::compare (t_max, *t_iter); + res2 = CGAL::compare(t_max, *t_iter); - if (res2 == EQUAL) - { + if (res2 == EQUAL) { t0 = t_max; is_endpoint = true; - return (true); + return true; } - if (res2 == LARGER) - { + if (res2 == LARGER) { t0 = *t_iter; is_endpoint = false; - return (true); + return true; } } } is_endpoint = false; - return (false); + return false; } - _curve.get_t_at_x (rat_p.x(), std::back_inserter(t_vals)); - CGAL_assertion (! t_vals.empty() ); + _curve.get_t_at_x(rat_p.x(), std::back_inserter(t_vals)); + CGAL_assertion(! t_vals.empty() ); - for (t_iter = t_vals.begin(); t_iter != t_vals.end(); ++t_iter) - { + for (t_iter = t_vals.begin(); t_iter != t_vals.end(); ++t_iter) { // Compare the current t-value with t_min. res1 = CGAL::compare (t_min, *t_iter); - if (res1 == LARGER) - continue; + if (res1 == LARGER) continue; // Make sure the y-coordinates match. - y0 = nt_traits.evaluate_at (_curve.y_polynomial(), *t_iter) / - nt_traits.convert (_curve.y_norm()); + y0 = nt_traits.evaluate_at(_curve.y_polynomial(), *t_iter) / + nt_traits.convert(_curve.y_norm()); - if (CGAL::compare (nt_traits.convert (rat_p.y()), y0) == EQUAL) - { - if (res1 == EQUAL) - { + if (CGAL::compare(nt_traits.convert(rat_p.y()), y0) == EQUAL) { + if (res1 == EQUAL) { t0 = t_min; is_endpoint = true; - return (true); + return true; } // Compare the current t-value with t_max. res2 = CGAL::compare (t_max, *t_iter); - if (res2 == EQUAL) - { + if (res2 == EQUAL) { t0 = t_max; is_endpoint = true; return (true); } - if (res2 == LARGER) - { + if (res2 == LARGER) { t0 = *t_iter; is_endpoint = false; return (true); @@ -1717,53 +1573,48 @@ bool _Bezier_x_monotone_2::_is_in_range // In this case, we have not found a t-value in the range of our subcurve, // so p does not lie on the subcurve: is_endpoint = false; - return (false); + return false; } // --------------------------------------------------------------------------- // Compute a y-coordinate of a point on the x-monotone subcurve with a // given x-coordinate. // -template +template typename _Bezier_x_monotone_2::Algebraic -_Bezier_x_monotone_2::_get_y - (const Rational& x0, - Bezier_cache& cache) const +_Bezier_x_monotone_2:: +_get_y(const Rational& x0, Bezier_cache& cache) const { // Obtain the t-values for with the x-coordinates of the supporting // curve equal x0. - std::list t_vals; + std::list t_vals; - _curve.get_t_at_x (x0, std::back_inserter(t_vals)); + _curve.get_t_at_x(x0, std::back_inserter(t_vals)); // Find a t-value that is in the range of the current curve. - Nt_traits nt_traits; - typename std::list::iterator t_iter; - std::pair t_range = _t_range (cache); - const Algebraic& t_src = t_range.first; - const Algebraic& t_trg = t_range.second; - Comparison_result res1, res2; + Nt_traits nt_traits; + typename std::list::iterator t_iter; + std::pair t_range = _t_range (cache); + const Algebraic& t_src = t_range.first; + const Algebraic& t_trg = t_range.second; + Comparison_result res1, res2; - for (t_iter = t_vals.begin(); t_iter != t_vals.end(); ++t_iter) - { + for (t_iter = t_vals.begin(); t_iter != t_vals.end(); ++t_iter) { res1 = CGAL::compare (*t_iter, t_src); - if (res1 == EQUAL) - { + if (res1 == EQUAL) { // Return the y-coordinate of the source point: return (_ps.y()); } res2 = CGAL::compare (*t_iter, t_trg); - if (res2 == EQUAL) - { + if (res2 == EQUAL) { // Return the y-coordinate of the source point: return (_pt.y()); } - if (res1 != res2) - { + if (res1 != res2) { // We found a t-value in the range of our x-monotone subcurve. // Use this value to compute the y-coordinate. return (nt_traits.evaluate_at (_curve.y_polynomial(), *t_iter) / @@ -1773,42 +1624,38 @@ _Bezier_x_monotone_2::_get_y // If we reached here, x0 is not in the x-range of our subcurve. CGAL_error(); - return (0); + return 0; } // --------------------------------------------------------------------------- // Compare the slopes of the subcurve with another given Bezier subcurve at // their given intersection point. // -template +template Comparison_result -_Bezier_x_monotone_2::_compare_slopes - (const Self& cv, - const Point_2& p, - Bezier_cache& cache) const +_Bezier_x_monotone_2:: +_compare_slopes(const Self& cv, const Point_2& p, Bezier_cache& cache) const { // Get the originators of p. - Originator_iterator org1 = p.get_originator (_curve, _xid); - const bool valid_org1 = (org1 != p.originators_end()); + Originator_iterator org1 = p.get_originator(_curve, _xid); + const bool valid_org1 = (org1 != p.originators_end()); - Originator_iterator org2 = p.get_originator (cv._curve, cv._xid); - const bool valid_org2 = (org2 != p.originators_end()); + Originator_iterator org2 = p.get_originator(cv._curve, cv._xid); + const bool valid_org2 = (org2 != p.originators_end()); - CGAL_assertion (valid_org1 || valid_org2); + CGAL_assertion(valid_org1 || valid_org2); // If the point is only approximated, we can carry out a comparison using // an approximate number type. - if (valid_org1 && valid_org2 && ! p.is_exact()) - { + if (valid_org1 && valid_org2 && ! p.is_exact()) { // If the point is inexact, we assume it is a bounded intersection // point of two curves, and therefore the bounding angle these curves // span do not overlap. - const Bez_point_bound& bound1 = org1->point_bound(); - const Bez_point_bound& bound2 = org2->point_bound(); - Bounding_traits bound_tr; + const Bez_point_bound& bound1 = org1->point_bound(); + const Bez_point_bound& bound2 = org2->point_bound(); + Bounding_traits bound_tr; - return (bound_tr.compare_slopes_at_intersection_point (bound1, - bound2)); + return (bound_tr.compare_slopes_at_intersection_point(bound1, bound2)); } // Obtain the parameter values t1 and t2 that correspond to the point p. @@ -1817,17 +1664,15 @@ _Bezier_x_monotone_2::_compare_slopes // it must be a ratioal point!) and lies in its interior. In this // (degenerate) case we compute the parameter value and set the appropriate // originator for p. - Nt_traits nt_traits; - Algebraic t1; - Algebraic t2; + Nt_traits nt_traits; + Algebraic t1; + Algebraic t2; - if (valid_org1) - { + if (valid_org1) { CGAL_assertion (org1->has_parameter()); t1 = org1->parameter(); } - else - { + else { bool is_endpoint1; CGAL_assertion_code (bool in_range1 =) _is_in_range (p, cache, t1, is_endpoint1); @@ -1835,66 +1680,60 @@ _Bezier_x_monotone_2::_compare_slopes p.add_originator (Originator (_curve, _xid, t1)); } - if (valid_org2) - { + if (valid_org2) { CGAL_assertion (org2->has_parameter()); t2 = org2->parameter(); } - else - { - bool is_endpoint2; - CGAL_assertion_code (bool in_range2 =) - cv._is_in_range (p, cache, t2, is_endpoint2); - CGAL_assertion (in_range2); - p.add_originator (Originator (cv._curve, cv._xid, t2)); + else { + bool is_endpoint2; + CGAL_assertion_code(bool in_range2 =) + cv._is_in_range(p, cache, t2, is_endpoint2); + CGAL_assertion(in_range2); + p.add_originator(Originator (cv._curve, cv._xid, t2)); } // The slope of (X(t), Y(t)) at t0 is given by Y'(t0)/X'(t0). // Compute the slope of (*this). // Note that we take special care of the case X'(t0) = 0, when the tangent // is vertical and its slope is +/- oo. - Polynomial derivX = nt_traits.derive (_curve.x_polynomial()); - Polynomial derivY = nt_traits.derive (_curve.y_polynomial()); - Algebraic numer1 = nt_traits.evaluate_at (derivY, t1) * - nt_traits.convert (_curve.x_norm()); - Algebraic denom1 = nt_traits.evaluate_at (derivX, t1) * - nt_traits.convert (_curve.y_norm()); - CGAL::Sign inf_slope1 = CGAL::ZERO; - Algebraic slope1; + Polynomial derivX = nt_traits.derive(_curve.x_polynomial()); + Polynomial derivY = nt_traits.derive(_curve.y_polynomial()); + Algebraic numer1 = nt_traits.evaluate_at(derivY, t1) * + nt_traits.convert (_curve.x_norm()); + Algebraic denom1 = nt_traits.evaluate_at(derivX, t1) * + nt_traits.convert (_curve.y_norm()); + CGAL::Sign inf_slope1 = CGAL::ZERO; + Algebraic slope1; - if (CGAL::sign (denom1) == CGAL::ZERO) - { - inf_slope1 = is_directed_right() ? CGAL::sign (numer1) : CGAL::opposite( CGAL::sign (numer1) ); + if (CGAL::sign (denom1) == CGAL::ZERO) { + inf_slope1 = is_directed_right() ? + CGAL::sign(numer1) : CGAL::opposite(CGAL::sign(numer1)); // If both derivatives are zero, we cannot perform the comparison: - if (inf_slope1 == CGAL::ZERO) - return (EQUAL); + if (inf_slope1 == CGAL::ZERO) return EQUAL; } - else - { + else { slope1 = numer1 / denom1; } // Compute the slope of the other subcurve. derivX = nt_traits.derive (cv._curve.x_polynomial()); derivY = nt_traits.derive (cv._curve.y_polynomial()); - Algebraic numer2 = nt_traits.evaluate_at (derivY, t2) * - nt_traits.convert (cv._curve.x_norm()); - Algebraic denom2 = nt_traits.evaluate_at (derivX, t2) * - nt_traits.convert (cv._curve.y_norm()); - CGAL::Sign inf_slope2 = CGAL::ZERO; - Algebraic slope2; + Algebraic numer2 = nt_traits.evaluate_at (derivY, t2) * + nt_traits.convert (cv._curve.x_norm()); + Algebraic denom2 = nt_traits.evaluate_at (derivX, t2) * + nt_traits.convert (cv._curve.y_norm()); + CGAL::Sign inf_slope2 = CGAL::ZERO; + Algebraic slope2; - if (CGAL::sign (denom2) == CGAL::ZERO) - { - inf_slope2 = cv.is_directed_right() ? CGAL::sign (numer2) : CGAL::opposite( CGAL::sign (numer2) ); + if (CGAL::sign (denom2) == CGAL::ZERO) { + inf_slope2 = cv.is_directed_right() ? + CGAL::sign (numer2) : CGAL::opposite( CGAL::sign (numer2) ); // If both derivatives are zero, we cannot perform the comparison: - if (inf_slope2 == CGAL::ZERO) - return (EQUAL); + if (inf_slope2 == CGAL::ZERO) return (EQUAL); } - else - { + else { slope2 = numer2 / denom2; } @@ -1905,11 +1744,9 @@ _Bezier_x_monotone_2::_compare_slopes if (inf_slope1 == CGAL::NEGATIVE) return (inf_slope2 == CGAL::NEGATIVE ? EQUAL : SMALLER); - if (inf_slope2 == CGAL::POSITIVE) - return (SMALLER); + if (inf_slope2 == CGAL::POSITIVE) return (SMALLER); - if (inf_slope2 == CGAL::NEGATIVE) - return (LARGER); + if (inf_slope2 == CGAL::NEGATIVE) return (LARGER); // Compare the slopes. return (CGAL::compare (slope1, slope2)); @@ -1918,29 +1755,25 @@ _Bezier_x_monotone_2::_compare_slopes // --------------------------------------------------------------------------- // Get the range of t-value over which the subcurve is defined. // -template +template std::pair::Algebraic, typename _Bezier_x_monotone_2::Algebraic> -_Bezier_x_monotone_2::_t_range - (Bezier_cache& cache) const +_Bezier_x_monotone_2:: +_t_range(Bezier_cache& cache) const { - Originator_iterator ps_org = _ps.get_originator (_curve, _xid); + Originator_iterator ps_org = _ps.get_originator(_curve, _xid); CGAL_assertion(ps_org != _ps.originators_end()); - Originator_iterator pt_org = _pt.get_originator (_curve, _xid); + Originator_iterator pt_org = _pt.get_originator(_curve, _xid); CGAL_assertion(pt_org != _pt.originators_end()); // Make sure that the two endpoints are exact. - if (! ps_org->has_parameter()) - _ps.make_exact (cache); + if (! ps_org->has_parameter()) _ps.make_exact (cache); + if (! pt_org->has_parameter()) _pt.make_exact (cache); - if (! pt_org->has_parameter()) - _pt.make_exact (cache); - - return (std::make_pair (ps_org->parameter(), - pt_org->parameter())); + return (std::make_pair(ps_org->parameter(), pt_org->parameter())); } // --------------------------------------------------------------------------- @@ -1948,18 +1781,18 @@ _Bezier_x_monotone_2::_t_range // (or to the left) of their intersection point, whose multiplicity is // greater than 1. // -template +template Comparison_result -_Bezier_x_monotone_2::_compare_to_side - (const Self& cv, - const Point_2& p, - bool to_right, - Bezier_cache& cache) const +_Bezier_x_monotone_2:: +_compare_to_side(const Self& cv, + const Point_2& p, + bool to_right, + Bezier_cache& cache) const { // Get the intersection points of the two curves from the cache. Note that // we make sure that the ID of this->_curve is smaller than of cv's curve ID. - const bool no_swap_curves = (_curve.id() <= cv._curve.id()); - bool do_ovlp; + const bool no_swap_curves = (_curve.id() <= cv._curve.id()); + bool do_ovlp; const Intersect_list& inter_list = (no_swap_curves ? (cache.get_intersections (_curve.id(), @@ -1983,40 +1816,36 @@ _Bezier_x_monotone_2::_compare_to_side CGAL_assertion (org != p.originators_end()); CGAL_assertion (org->has_parameter()); - const Algebraic& t0 = org->parameter(); + const Algebraic& t0 = org->parameter(); // Get the parameter range of the curve. - const std::pair& range = _t_range (cache); - const Algebraic& t_src = range.first; - const Algebraic& t_trg = range.second; + const std::pair& range = _t_range (cache); + const Algebraic& t_src = range.first; + const Algebraic& t_trg = range.second; // Find the next intersection point that lies to the right of p. - Intersect_iter iit; - Algebraic next_t; - Comparison_result res = CGAL::EQUAL; - bool found = false; + Intersect_iter iit; + Algebraic next_t; + Comparison_result res = CGAL::EQUAL; + bool found = false; - for (iit = inter_list.begin(); iit != inter_list.end(); ++iit) - { + for (iit = inter_list.begin(); iit != inter_list.end(); ++iit) { // Check if the current point lies to the right (left) of p. We do so by // considering its originating parameter value s (or t, if we swapped // the curves). - const Algebraic& t = (no_swap_curves ? (iit->s) : iit->t); + const Algebraic& t = (no_swap_curves ? (iit->s) : iit->t); - res = CGAL::compare (t, t0); + res = CGAL::compare(t, t0); if ((to_right && ((_inc_to_right && res == LARGER) || (! _inc_to_right && res == SMALLER))) || (! to_right && ((_inc_to_right && res == SMALLER) || (! _inc_to_right && res == LARGER)))) { - if (! found) - { + if (! found) { next_t = t; found = true; } - else - { + else { // If we have already located an intersection point to the right // (left) of p, choose the leftmost (rightmost) of the two points. res = CGAL::compare (t, next_t); @@ -2034,12 +1863,9 @@ _Bezier_x_monotone_2::_compare_to_side // If the next intersection point occurs before the right (left) endpoint // of the subcurve, keep it. Otherwise, take the parameter value at // the endpoint. - if (found) - { - if (to_right == _dir_right) - res = CGAL::compare (t_trg, next_t); - else - res = CGAL::compare (t_src, next_t); + if (found) { + if (to_right == _dir_right) res = CGAL::compare (t_trg, next_t); + else res = CGAL::compare (t_src, next_t); } if (! found || @@ -2054,10 +1880,10 @@ _Bezier_x_monotone_2::_compare_to_side // Find a rational value between t0 and t_next. Using this value, we // a point with rational coordinates on our subcurve. We also locate a point // on the other curve with the same x-coordinates. - Nt_traits nt_traits; - const Rational& mid_t = nt_traits.rational_in_interval (t0, next_t); - const Rat_point_2& q1 = _curve (mid_t); - const Algebraic& y2 = cv._get_y (q1.x(), cache); + Nt_traits nt_traits; + const Rational& mid_t = nt_traits.rational_in_interval(t0, next_t); + const Rat_point_2& q1 = _curve(mid_t); + const Algebraic& y2 = cv._get_y(q1.x(), cache); // We now just have to compare the y-coordinates of the two points we have // computed. @@ -2068,33 +1894,32 @@ _Bezier_x_monotone_2::_compare_to_side // Clip the control polygon of the supporting Bezier curve such that it fits // the current x-monotone subcurve. // -template -void _Bezier_x_monotone_2::_clip_control_polygon - (typename Bounding_traits::Control_points& ctrl, - typename Bounding_traits::NT& t_min, - typename Bounding_traits::NT& t_max) const +template +void _Bezier_x_monotone_2:: +_clip_control_polygon(typename Bounding_traits::Control_points& ctrl, + typename Bounding_traits::NT& t_min, + typename Bounding_traits::NT& t_max) const { // Start from the control polygon of the supporting curve. ctrl.clear(); - std::copy (_curve.control_points_begin(), _curve.control_points_end(), - std::back_inserter (ctrl)); + std::copy(_curve.control_points_begin(), _curve.control_points_end(), + std::back_inserter(ctrl)); // The x-monotone subcurve is defined over a parameter range // 0 <= t_min < t_max <= 1. Determine the endpoint with minimal t-value and // the one with maximal t-value. - const Point_2& p_min = (_inc_to_right ? left() : right()); - Originator_iterator org_min = p_min.get_originator (_curve, _xid); - const Point_2& p_max = (_inc_to_right ? right() : left()); - Originator_iterator org_max = p_max.get_originator (_curve, _xid); - bool clipped_min = false; + const Point_2& p_min = (_inc_to_right ? left() : right()); + Originator_iterator org_min = p_min.get_originator(_curve, _xid); + const Point_2& p_max = (_inc_to_right ? right() : left()); + Originator_iterator org_max = p_max.get_originator(_curve, _xid); + bool clipped_min = false; - CGAL_assertion (org_min != p_min.originators_end()); - CGAL_assertion (org_max != p_max.originators_end()); + CGAL_assertion(org_min != p_min.originators_end()); + CGAL_assertion(org_max != p_max.originators_end()); // Check if t_min = 0. If so, there is no need to clip. if (! (org_min->point_bound().type == Bez_point_bound::RATIONAL_PT && - CGAL::sign (org_min->point_bound().t_min) == CGAL::ZERO)) + CGAL::sign(org_min->point_bound().t_min) == CGAL::ZERO)) { // It is possible that the paramater range of the originator is too large. // We therefore make sure it fits the current bounding box of the point @@ -2103,22 +1928,20 @@ void _Bezier_x_monotone_2point_bound().t_max; - de_Casteljau_2 (ctrl.begin(), ctrl.end(), - t_min, - std::back_inserter(cp_a), - std::front_inserter(cp_b)); + de_Casteljau_2(ctrl.begin(), ctrl.end(), + t_min, + std::back_inserter(cp_a), + std::front_inserter(cp_b)); ctrl.clear(); - std::copy (cp_b.begin(), cp_b.end(), - std::back_inserter (ctrl)); + std::copy(cp_b.begin(), cp_b.end(), std::back_inserter (ctrl)); clipped_min = true; } - else - { + else { t_min = 0; } @@ -2136,27 +1959,21 @@ void _Bezier_x_monotone_2point_bound().t_min - t_min) / (1 - t_min); } - else - { + else { t_max = org_max->point_bound().t_min; } - de_Casteljau_2 (ctrl.begin(), ctrl.end(), - t_max, - std::back_inserter(cp_a), - std::front_inserter(cp_b)); + de_Casteljau_2(ctrl.begin(), ctrl.end(), t_max, + std::back_inserter(cp_a), std::front_inserter(cp_b)); ctrl.clear(); - std::copy (cp_a.begin(), cp_a.end(), - std::back_inserter (ctrl)); + std::copy(cp_a.begin(), cp_a.end(), std::back_inserter (ctrl)); t_max = org_max->point_bound().t_min; } - else - { + else { t_max = 1; } @@ -2166,11 +1983,10 @@ void _Bezier_x_monotone_2 -bool _Bezier_x_monotone_2::_approximate_intersection_points - (const Self& cv, - std::list& inter_pts) const +template +bool _Bezier_x_monotone_2:: +_approximate_intersection_points(const Self& cv, + std::list& inter_pts) const { typedef typename Bounding_traits::Intersection_point Intersection_point; @@ -2178,16 +1994,15 @@ bool _Bezier_x_monotone_2_curve; - const Curve_2& B2 = cv._curve; - typename Bounding_traits::Control_points cp1; - typename Bounding_traits::NT t_min1 = 0, t_max1 = 1; + const Curve_2& B1 = this->_curve; + const Curve_2& B2 = cv._curve; + typename Bounding_traits::Control_points cp1; + typename Bounding_traits::NT t_min1 = 0, t_max1 = 1; typename Bounding_traits::Control_points cp2; - typename Bounding_traits::NT t_min2 = 0, t_max2 = 1; - bool is_self_intersection = false; + typename Bounding_traits::NT t_min2 = 0, t_max2 = 1; + bool is_self_intersection = false; - if (! B1.is_same (B2)) - { + if (! B1.is_same (B2)) { // In case B1 and B2 are different curves, use their full control polygons // in order to approximate all intersection points between the two // supporting Bezier curves. @@ -2196,8 +2011,7 @@ bool _Bezier_x_monotone_2 ipt_bounds; + Bounding_traits bound_tr; + std::list ipt_bounds; - bound_tr.compute_intersection_points (cp1, cp2, - std::back_inserter (ipt_bounds)); + bound_tr.compute_intersection_points(cp1, cp2, std::back_inserter(ipt_bounds)); // Construct the approximated points. - typename std::list::const_iterator iter; - - for (iter = ipt_bounds.begin(); iter != ipt_bounds.end(); ++iter) - { + for (auto iter = ipt_bounds.begin(); iter != ipt_bounds.end(); ++iter) { const Bez_point_bound& bound1 = iter->bound1; const Bez_point_bound& bound2 = iter->bound2; const Bez_point_bbox& bbox = iter->bbox; // In case it is impossible to further refine the point, stop here. - if (! bound1.can_refine || ! bound2.can_refine) - return (false); + if (! bound1.can_refine || ! bound2.can_refine) return false; // Create the approximated intersection point. - Point_2 pt; + Point_2 pt; if (bound1.type == Bounding_traits::Bez_point_bound::RATIONAL_PT && bound2.type == Bounding_traits::Bez_point_bound::RATIONAL_PT) { - CGAL_assertion (CGAL::compare (bound1.t_min, bound1.t_max) == EQUAL); - CGAL_assertion (CGAL::compare (bound2.t_min, bound2.t_max) == EQUAL); - Rational t1 = bound1.t_min; - Rational t2 = bound2.t_min; - Nt_traits nt_traits; + CGAL_assertion (CGAL::compare(bound1.t_min, bound1.t_max) == EQUAL); + CGAL_assertion (CGAL::compare(bound2.t_min, bound2.t_max) == EQUAL); + Rational t1 = bound1.t_min; + Rational t2 = bound2.t_min; + Nt_traits nt_traits; - if (is_self_intersection) - { + if (is_self_intersection) { // Set the originators with the curve x-monotone IDs. // Note that the parameter values we have computed relate to the // parameter range [t_min1, t_max1] and [t_min2, t_max2], respectively, @@ -2248,63 +2056,60 @@ bool _Bezier_x_monotone_2 -bool _Bezier_x_monotone_2::_intersect - (const Self& cv, - Intersection_map& inter_map, - Bezier_cache& cache, - std::vector& ipts, - Self& ovlp_cv) const +template +bool _Bezier_x_monotone_2:: +_intersect(const Self& cv, + Intersection_map& inter_map, + Bezier_cache& cache, + std::vector& ipts, + Self& ovlp_cv) const { - CGAL_precondition (_curve.id() <= cv._curve.id()); + CGAL_precondition(_curve.id() <= cv._curve.id()); ipts.clear(); @@ -2312,115 +2117,96 @@ bool _Bezier_x_monotone_2::_intersect // first check if this base curve is not self-intersecting. If this is the // case we can avoid any attempt of computing intersection points between // the two subcurves. - const bool self_intersect = (_curve.id() == cv._curve.id()); + const bool self_intersect = (_curve.id() == cv._curve.id()); - if (self_intersect) - { - if (_xid == cv._xid) - return (false); - - if (_curve.has_no_self_intersections()) - return (false); + if (self_intersect) { + if (_xid == cv._xid) return false; + if (_curve.has_no_self_intersections()) return false; } // Construct the pair of curve IDs and look for it in the intersection map. - Curve_pair curve_pair (_curve.id(), cv._curve.id()); - Intersection_map_iterator map_iter = inter_map.find (curve_pair); - std::list inter_pts; - bool app_ok = true; + Curve_pair curve_pair(_curve.id(), cv._curve.id()); + Intersection_map_iterator map_iter = inter_map.find(curve_pair); + std::list inter_pts; + bool app_ok = true; - if (map_iter != inter_map.end()) - { + if (map_iter != inter_map.end()) { // Get the intersection points between the two supporting curves as stored // in the map. inter_pts = map_iter->second; } - else - { + else { // Approximate the intersection points and store them in the map. // Note that we do not store approximated self-intersections in the map, // as they realte only to the pecific x-monotone curves, and not to the // entire curve. - app_ok = _approximate_intersection_points (cv, - inter_pts); + app_ok = _approximate_intersection_points(cv, inter_pts); - if (app_ok && ! self_intersect) - inter_map[curve_pair] = inter_pts; + if (app_ok && ! self_intersect) inter_map[curve_pair] = inter_pts; } // Try to approximate the intersection points. - bool in_range1, in_range2; - bool correct_res; + bool in_range1, in_range2; + bool correct_res; - if (app_ok) - { + if (app_ok) { // Approximations are computed using de Casteljau subdivision and // filtering using skewed bounding boxes. A property of these bboxes - // if that it can fail in the following cases: (i) there are two intersection - // points lying very close together, (ii) there exists an intersection point - // whose multiplicity is greater than 1, or (iii) the curves overlap. - // If the approximation went OK, then we know that we have a simple - // intersection point (with multiplicity 1) if intersection point - // is not rational (otherwise it is unknown: at this point, an intersection point - // is rational if it was found as a control point during the de Casteljau subdivision) + // if that it can fail in the following cases: (i) there are two + // intersection points lying very close together, (ii) there exists an + // intersection point whose multiplicity is greater than 1, or (iii) the + // curves overlap. If the approximation went OK, then we know that we have + // a simple intersection point (with multiplicity 1) if intersection point + // is not rational (otherwise it is unknown: at this point, an intersection + // point is rational if it was found as a control point during the de + // Casteljau subdivision) // We go over the points and report the ones lying in the parameter // ranges of both curves. Note that in case of self-intersections, // all points we get are in the respective parameter range of the curves. typename std::list::iterator pit; - for (pit = inter_pts.begin(); pit != inter_pts.end(); ++pit) - { + for (pit = inter_pts.begin(); pit != inter_pts.end(); ++pit) { // Check if the point is in the range of this curve - first using // its parameter bounds, and if we fail we perform an exact check. - if (! self_intersect) - { - in_range1 = _is_in_range (*pit, correct_res); + if (! self_intersect) { + in_range1 = _is_in_range(*pit, correct_res); } - else - { + else { in_range1 = true; correct_res = true; } - if (! correct_res) - { - if (! pit->is_exact()) - pit->make_exact (cache); + if (! correct_res) { + if (! pit->is_exact()) pit->make_exact(cache); - Originator_iterator p_org = pit->get_originator (_curve, _xid); + Originator_iterator p_org = pit->get_originator (_curve, _xid); CGAL_assertion (p_org != pit->originators_end()); - in_range1 = _is_in_range (p_org->parameter(), cache); + in_range1 = _is_in_range(p_org->parameter(), cache); } - if (! in_range1) - continue; + if (! in_range1) continue; // Check if the point is in the range of the other curve - first using // its parameter bounds, and if we fail we perform an exact check. - if (! self_intersect) - { + if (! self_intersect) { in_range2 = cv._is_in_range (*pit, correct_res); } - else - { + else { in_range2 = true; correct_res = true; } - if (! correct_res) - { - if (! pit->is_exact()) - pit->make_exact (cache); + if (! correct_res) { + if (! pit->is_exact()) pit->make_exact (cache); Originator_iterator p_org = pit->get_originator (cv._curve, cv._xid); - CGAL_assertion (p_org != pit->originators_end()); + CGAL_assertion(p_org != pit->originators_end()); - in_range2 = cv._is_in_range (p_org->parameter(), cache); + in_range2 = cv._is_in_range(p_org->parameter(), cache); } - if (in_range1 && in_range2) - { + if (in_range1 && in_range2) { // In case the originators of the intersection point are not marked // with x-monotone identifiers, mark them now as we know in which // subcurves they lie. @@ -2428,17 +2214,17 @@ bool _Bezier_x_monotone_2::_intersect CGAL_assertion (p_org1 != pit->originators_end()); if (p_org1->xid() == 0) - pit->update_originator_xid (*p_org1, _xid); + pit->update_originator_xid(*p_org1, _xid); Originator_iterator p_org2 = pit->get_originator (cv._curve, cv._xid); CGAL_assertion (p_org2 != pit->originators_end()); if (p_org2->xid() == 0) - pit->update_originator_xid (*p_org2, cv._xid); + pit->update_originator_xid(*p_org2, cv._xid); // The point lies within the parameter range of both curves, so we // report it as a valid intersection point with multiplicity 1 or unknown. - ipts.push_back (Intersection_point_2 (*pit, pit->is_rational()?0:1)); + ipts.push_back(Intersection_point(*pit, pit->is_rational() ? 0 : 1)); } } @@ -2448,34 +2234,30 @@ bool _Bezier_x_monotone_2::_intersect // We did not succeed in isolate the approximate intersection points. // We therefore resort to the exact procedure and exactly compute them. - bool do_ovlp; - const Intersect_list& inter_list = - cache.get_intersections (_curve.id(), - _curve.x_polynomial(), _curve.x_norm(), - _curve.y_polynomial(), _curve.y_norm(), - cv._curve.id(), - cv._curve.x_polynomial(), cv._curve.x_norm(), - cv._curve.y_polynomial(), cv._curve.y_norm(), - do_ovlp); + bool do_ovlp; + const Intersect_list& inter_list = + cache.get_intersections(_curve.id(), + _curve.x_polynomial(), _curve.x_norm(), + _curve.y_polynomial(), _curve.y_norm(), + cv._curve.id(), + cv._curve.x_polynomial(), cv._curve.x_norm(), + cv._curve.y_polynomial(), cv._curve.y_norm(), + do_ovlp); - if (do_ovlp) - { + if (do_ovlp) { // Check the case of co-inciding endpoints - if (left().equals (cv.left(), cache)) - { - if (right().equals (cv.right(), cache)) - { + if (left().equals (cv.left(), cache)) { + if (right().equals (cv.right(), cache)) { // The two curves entirely overlap one another: ovlp_cv = cv; - return (true); + return true; } - Algebraic t_right; - bool is_endpoint; + Algebraic t_right; + bool is_endpoint; - if (_is_in_range (cv.right(), cache, t_right, is_endpoint)) - { - CGAL_assertion (! is_endpoint); + if (_is_in_range(cv.right(), cache, t_right, is_endpoint)) { + CGAL_assertion(! is_endpoint); // Case 1 - *this: s +-----------+ t // cv: s'+=====+ t' @@ -2483,13 +2265,12 @@ bool _Bezier_x_monotone_2::_intersect // Take cv as the overlapping subcurve, and add originators for its // right endpoint referring to *this. ovlp_cv = cv; - ovlp_cv.right().add_originator (Originator (_curve, _xid, t_right)); + ovlp_cv.right().add_originator(Originator(_curve, _xid, t_right)); - return (true); + return true; } - else if (cv._is_in_range (right(), cache, t_right, is_endpoint)) - { - CGAL_assertion (! is_endpoint); + else if (cv._is_in_range(right(), cache, t_right, is_endpoint)) { + CGAL_assertion(! is_endpoint); // Case 2 - *this: s +----+ t // cv: s'+==========+ t' @@ -2497,24 +2278,21 @@ bool _Bezier_x_monotone_2::_intersect // Take this as the overlapping subcurve, and add originators for its // right endpoint referring to cv. ovlp_cv = *this; - ovlp_cv.right().add_originator (Originator (cv._curve, cv._xid, - t_right)); + ovlp_cv.right().add_originator(Originator(cv._curve, cv._xid, t_right)); - return (true); + return true; } // In this case the two curves do not overlap, but have a common left // endpoint. - ipts.push_back (Intersection_point_2 (left(), 0)); + ipts.push_back(Intersection_point(left(), 0)); return (false); } - else if (right().equals (cv.right(), cache)) - { - Algebraic t_left; - bool is_endpoint; + else if (right().equals (cv.right(), cache)) { + Algebraic t_left; + bool is_endpoint; - if (_is_in_range (cv.left(), cache, t_left, is_endpoint)) - { + if (_is_in_range (cv.left(), cache, t_left, is_endpoint)) { CGAL_assertion (! is_endpoint); // Case 3 - *this: s +-----------+ t @@ -2527,9 +2305,8 @@ bool _Bezier_x_monotone_2::_intersect return (true); } - else if (cv._is_in_range (left(), cache, t_left, is_endpoint)) - { - CGAL_assertion (! is_endpoint); + else if (cv._is_in_range(left(), cache, t_left, is_endpoint)) { + CGAL_assertion(! is_endpoint); // Case 4 - *this: s +----+ t // cv: s'+==========+ t' @@ -2537,30 +2314,26 @@ bool _Bezier_x_monotone_2::_intersect // Take this as the overlapping subcurve, and add originators for its // left endpoint referring to cv. ovlp_cv = *this; - ovlp_cv.left().add_originator (Originator (cv._curve, cv._xid, - t_left)); + ovlp_cv.left().add_originator(Originator(cv._curve, cv._xid, t_left)); - return (true); + return true; } // In this case the two curves do not overlap, but have a common right // endpoint. - ipts.push_back (Intersection_point_2 (right(), 0)); - return (false); + ipts.push_back(Intersection_point(right(), 0)); + return false; } // If we reached here, none of the endpoints coincide. // Check the possible overlap scenarios. - Point_2 ovrp_src, ovlp_trg; - Algebraic t_cv_src; - Algebraic t_cv_trg; - bool is_endpoint = false; + Point_2 ovrp_src, ovlp_trg; + Algebraic t_cv_src; + Algebraic t_cv_trg; + bool is_endpoint = false; - if (_is_in_range (cv._ps, cache, t_cv_src, is_endpoint) && - ! is_endpoint) - { - if (_is_in_range (cv._pt, cache, t_cv_trg, is_endpoint) && - ! is_endpoint) + if (_is_in_range (cv._ps, cache, t_cv_src, is_endpoint) && ! is_endpoint) { + if (_is_in_range (cv._pt, cache, t_cv_trg, is_endpoint) && ! is_endpoint) { // Case 5 - *this: s +-----------+ t // cv: s' +=====+ t' @@ -2568,32 +2341,30 @@ bool _Bezier_x_monotone_2::_intersect // Take cv as the overlapping subcurve, and add originators for its // endpoints referring to *this. ovlp_cv = cv; - ovlp_cv._ps.add_originator (Originator (_curve, _xid, t_cv_src)); - ovlp_cv._pt.add_originator (Originator (_curve, _xid, t_cv_trg)); + ovlp_cv._ps.add_originator(Originator (_curve, _xid, t_cv_src)); + ovlp_cv._pt.add_originator(Originator (_curve, _xid, t_cv_trg)); - return (true); + return true; } - else - { + else { // Case 6 - *this: s +-----------+ t // cv: s' +=====+ t' // // Use *this as a base, and replace its source point. ovlp_cv = *this; ovlp_cv._ps = cv._ps; - ovlp_cv._ps.add_originator (Originator (_curve, _xid, t_cv_src)); + ovlp_cv._ps.add_originator(Originator (_curve, _xid, t_cv_src)); // Add an originator to the target point, referring to cv: - CGAL_assertion_code (bool pt_in_cv_range =) - cv._is_in_range (ovlp_cv._pt, cache, t_cv_trg, is_endpoint); - CGAL_assertion (pt_in_cv_range); - ovlp_cv._pt.add_originator (Originator (cv._curve, cv._xid, t_cv_trg)); + CGAL_assertion_code(bool pt_in_cv_range =) + cv._is_in_range(ovlp_cv._pt, cache, t_cv_trg, is_endpoint); + CGAL_assertion(pt_in_cv_range); + ovlp_cv._pt.add_originator(Originator(cv._curve, cv._xid, t_cv_trg)); - return (true); + return true; } } - else if (_is_in_range (cv._pt, cache, t_cv_trg, is_endpoint) && - ! is_endpoint) + else if (_is_in_range(cv._pt, cache, t_cv_trg, is_endpoint) && ! is_endpoint) { // Case 7 - *this: s +-----------+ t // cv: s' +=====+ t' @@ -2605,14 +2376,14 @@ bool _Bezier_x_monotone_2::_intersect // Add an originator to the source point, referring to cv: CGAL_assertion_code (bool ps_in_cv_range =) - cv._is_in_range (ovlp_cv._ps, cache, t_cv_src, is_endpoint); + cv._is_in_range(ovlp_cv._ps, cache, t_cv_src, is_endpoint); CGAL_assertion (ps_in_cv_range); - ovlp_cv._ps.add_originator (Originator (cv._curve, cv._xid, t_cv_src)); + ovlp_cv._ps.add_originator(Originator(cv._curve, cv._xid, t_cv_src)); return (true); } - else if (cv._is_in_range (_ps, cache, t_cv_src, is_endpoint) && - cv._is_in_range (_pt, cache, t_cv_trg, is_endpoint)) + else if (cv._is_in_range(_ps, cache, t_cv_src, is_endpoint) && + cv._is_in_range(_pt, cache, t_cv_trg, is_endpoint)) { // Case 8 - *this: s +---------+ t // cv: s' +================+ t' @@ -2620,38 +2391,32 @@ bool _Bezier_x_monotone_2::_intersect // Take *this as the overlapping subcurve, and add originators for its // endpoints referring to cv. ovlp_cv = *this; - ovlp_cv._ps.add_originator (Originator (cv._curve, cv._xid, t_cv_src)); - ovlp_cv._pt.add_originator (Originator (cv._curve, cv._xid, t_cv_trg)); + ovlp_cv._ps.add_originator(Originator(cv._curve, cv._xid, t_cv_src)); + ovlp_cv._pt.add_originator(Originator(cv._curve, cv._xid, t_cv_trg)); - return (true); + return true; } // If we reached here, there are no overlaps: - return (false); + return false; } // Go over the points and report the ones lying in the parameter ranges // of both curves. - Intersect_iter iit; - - for (iit = inter_list.begin(); iit != inter_list.end(); ++iit) - { - if (_is_in_range (iit->s, cache) && - cv._is_in_range (iit->t, cache)) - { + for (auto iit = inter_list.begin(); iit != inter_list.end(); ++iit) { + if (_is_in_range (iit->s, cache) && cv._is_in_range(iit->t, cache)) { // Construct an intersection point with unknown multiplicity. - Point_2 pt (iit->x, iit->y, - true); // Dummy parameter. + Point_2 pt (iit->x, iit->y, true); // Dummy parameter. - pt.add_originator (Originator (_curve, _xid, iit->s)); - pt.add_originator (Originator (cv._curve, cv._xid, iit->t)); + pt.add_originator(Originator(_curve, _xid, iit->s)); + pt.add_originator(Originator(cv._curve, cv._xid, iit->t)); - ipts.push_back (Intersection_point_2 (pt, 0)); + ipts.push_back(Intersection_point(pt, 0)); } } // Mark that there is no overlap: - return (false); + return false; } // --------------------------------------------------------------------------- @@ -2675,23 +2440,22 @@ _exact_vertical_position(const Point_2& p, rat_p = (Rat_point_2) p; // Get a rational approximation of the parameter values at the endpoints. - Nt_traits nt_traits; - Originator_iterator ps_org = _ps.get_originator (_curve, _xid); + Nt_traits nt_traits; + Originator_iterator ps_org = _ps.get_originator(_curve, _xid); CGAL_assertion (ps_org != _ps.originators_end()); - Originator_iterator pt_org = _pt.get_originator (_curve, _xid); - CGAL_assertion (pt_org != _pt.originators_end()); + Originator_iterator pt_org = _pt.get_originator(_curve, _xid); + CGAL_assertion(pt_org != _pt.originators_end()); - Rational my_t_min; - Rational my_t_max; + Rational my_t_min; + Rational my_t_max; - - bool can_refine_s = ! _ps.is_exact(); - bool can_refine_t = ! _pt.is_exact(); + bool can_refine_s = ! _ps.is_exact(); + bool can_refine_t = ! _pt.is_exact(); do { - if (CGAL::compare (ps_org->point_bound().t_max, - pt_org->point_bound().t_min) == SMALLER) + if (CGAL::compare(ps_org->point_bound().t_max, + pt_org->point_bound().t_min) == SMALLER) { // In case the parameter value of the source is smaller than the target's. my_t_min = ps_org->point_bound().t_max; @@ -2718,14 +2482,14 @@ _exact_vertical_position(const Point_2& p, while(can_refine_s || can_refine_t); // Start the subdivision process from the entire supporting curve. - std::list subcurves; - Subcurve init_scv; - Rational x_min, y_min, x_max, y_max; - bool no_x_ovlp; - Comparison_result res_y_min, res_y_max; + std::list subcurves; + Subcurve init_scv; + Rational x_min, y_min, x_max, y_max; + bool no_x_ovlp; + Comparison_result res_y_min, res_y_max; - std::copy (_curve.control_points_begin(), _curve.control_points_end(), - std::back_inserter (init_scv.control_points)); + std::copy(_curve.control_points_begin(), _curve.control_points_end(), + std::back_inserter(init_scv.control_points)); init_scv.t_min = 0; init_scv.t_max = 1; subcurves.push_back (init_scv); @@ -2734,13 +2498,12 @@ _exact_vertical_position(const Point_2& p, { // Go over the list of subcurves and consider only those lying in the // given [t_min, t_max] bound. - typename std::list::iterator iter = subcurves.begin(); - bool is_fully_in_range; + typename std::list::iterator iter = subcurves.begin(); + bool is_fully_in_range; - while (iter != subcurves.end()) - { - if (CGAL::compare (iter->t_max, my_t_min) == SMALLER || - CGAL::compare (iter->t_min, my_t_max) == LARGER) + while (iter != subcurves.end()) { + if (CGAL::compare(iter->t_max, my_t_min) == SMALLER || + CGAL::compare(iter->t_min, my_t_max) == LARGER) { // Subcurve out of bounds of the x-monotone curve we consider - erase // it and continue to next subcurve. @@ -2752,43 +2515,37 @@ _exact_vertical_position(const Point_2& p, // the bounding box of the point. iter->bbox (x_min, y_min, x_max, y_max); - if (p.is_rational()) - { - no_x_ovlp = (CGAL::compare (x_min, rat_p.x()) == LARGER || - CGAL::compare (x_max, rat_p.x()) == SMALLER); + if (p.is_rational()) { + no_x_ovlp = (CGAL::compare(x_min, rat_p.x()) == LARGER || + CGAL::compare(x_max, rat_p.x()) == SMALLER); } - else - { - no_x_ovlp = (CGAL::compare (nt_traits.convert (x_min), - p.x()) == LARGER || - CGAL::compare (nt_traits.convert (x_max), - p.x()) == SMALLER); + else { + no_x_ovlp = (CGAL::compare(nt_traits.convert (x_min), + p.x()) == LARGER || + CGAL::compare(nt_traits.convert (x_max), + p.x()) == SMALLER); } - if (no_x_ovlp) - { + if (no_x_ovlp) { // Subcurve out of x-bounds - erase it and continue to next subcurve. subcurves.erase(iter++); continue; } // In this case, check if there is an overlap in the y-range. - if (p.is_rational()) - { - res_y_min = CGAL::compare (rat_p.y(), y_min); - res_y_max = CGAL::compare (rat_p.y(), y_max); + if (p.is_rational()) { + res_y_min = CGAL::compare(rat_p.y(), y_min); + res_y_max = CGAL::compare(rat_p.y(), y_max); } - else - { - res_y_min = CGAL::compare (p.y(), nt_traits.convert (y_min)); - res_y_max = CGAL::compare (p.y(), nt_traits.convert (y_max)); + else { + res_y_min = CGAL::compare(p.y(), nt_traits.convert (y_min)); + res_y_max = CGAL::compare(p.y(), nt_traits.convert (y_max)); } - is_fully_in_range = (CGAL::compare (iter->t_min, my_t_min) != SMALLER) && - (CGAL::compare (iter->t_max, my_t_max) != LARGER); + is_fully_in_range = (CGAL::compare(iter->t_min, my_t_min) != SMALLER) && + (CGAL::compare(iter->t_max, my_t_max) != LARGER); - if (res_y_min != res_y_max || ! is_fully_in_range) - { + if (res_y_min != res_y_max || ! is_fully_in_range) { // Subdivide the current subcurve and replace iter with the two // resulting subcurves using de Casteljau's algorithm. Subcurve scv_l, scv_r; @@ -2797,21 +2554,20 @@ _exact_vertical_position(const Point_2& p, scv_r.t_max = iter->t_max; scv_l.t_max = scv_r.t_min = (iter->t_min + iter->t_max) / 2; - bisect_control_polygon_2 (iter->control_points.begin(), - iter->control_points.end(), - std::back_inserter(scv_l.control_points), - std::front_inserter(scv_r.control_points)); + bisect_control_polygon_2(iter->control_points.begin(), + iter->control_points.end(), + std::back_inserter(scv_l.control_points), + std::front_inserter(scv_r.control_points)); - subcurves.insert (iter, scv_l); - subcurves.insert (iter, scv_r); + subcurves.insert(iter, scv_l); + subcurves.insert(iter, scv_r); subcurves.erase(iter++); continue; } - if (res_y_min == res_y_max) - { - CGAL_assertion (res_y_min != EQUAL); + if (res_y_min == res_y_max) { + CGAL_assertion(res_y_min != EQUAL); // We reached a separation, as p is either strictly above or strictly // below the bounding box of the current subcurve. @@ -2825,8 +2581,8 @@ _exact_vertical_position(const Point_2& p, } // We can reach here only if we do not force an exact result. - CGAL_assertion (! force_exact); - return (EQUAL); + CGAL_assertion(! force_exact); + return EQUAL; } } //namespace CGAL diff --git a/Arrangement_on_surface_2/include/CGAL/Arr_geometry_traits/Circle_segment_2.h b/Arrangement_on_surface_2/include/CGAL/Arr_geometry_traits/Circle_segment_2.h index f1bdb72d62b..2d94e51f820 100644 --- a/Arrangement_on_surface_2/include/CGAL/Arr_geometry_traits/Circle_segment_2.h +++ b/Arrangement_on_surface_2/include/CGAL/Arr_geometry_traits/Circle_segment_2.h @@ -8,16 +8,16 @@ // SPDX-License-Identifier: GPL-3.0-or-later OR LicenseRef-Commercial // // -// Author(s) : Ron Wein -// Baruch Zukerman -// Waqar Khan +// Author(s): Ron Wein +// Baruch Zukerman +// Waqar Khan +// Efi Fogel #ifndef CGAL_CIRCLE_SEGMENT_2_H #define CGAL_CIRCLE_SEGMENT_2_H #include - /*! \file * Header file for the _Circle_segment_2 class. */ @@ -31,126 +31,103 @@ namespace CGAL { // Forward declaration: -template class _One_root_point_2; +template class _One_root_point_2; /*! \class * Representation of a point whose coordinates are one-root numbers. */ -template -class _One_root_point_2_rep //: public Ref_counted -{ +template +class _One_root_point_2_rep { friend class _One_root_point_2; public: - typedef NumberType_ NT; typedef _One_root_point_2_rep Self; - typedef Sqrt_extension > CoordNT; + typedef Sqrt_extension > CoordNT; private: - - CoordNT _x; // The coordinates. - CoordNT _y; + CoordNT _x; // The coordinates. + CoordNT _y; public: - /*! Default constructor. */ - _One_root_point_2_rep () : - _x (0), - _y (0) + _One_root_point_2_rep() : + _x(0), + _y(0) {} /*! Constructor of a point with one-root coefficients. This constructor of a point can also be used with rational coefficients thanks to convertor of CoordNT. */ - _One_root_point_2_rep (const CoordNT& x, const CoordNT& y) : - _x (x), - _y (y) + _One_root_point_2_rep(const CoordNT& x, const CoordNT& y) : + _x(x), + _y(y) {} }; /*! \class * A handle for a point whose coordinates are one-root numbers. */ -template +template class _One_root_point_2 : public Handle_for<_One_root_point_2_rep > { public: - typedef NumberType_ NT; typedef _One_root_point_2 Self; private: - typedef _One_root_point_2_rep Point_rep; typedef Handle_for Point_handle; public: - typedef typename Point_rep::CoordNT CoordNT; /*! Default constructor. */ - _One_root_point_2 () : - Point_handle (Point_rep()) - {} + _One_root_point_2() : Point_handle(Point_rep()) {} /*! Copy constructor. */ - _One_root_point_2 (const Self& p) : - Point_handle (p) - {} + _One_root_point_2(const Self& p) : Point_handle(p) {} _One_root_point_2& operator=(const _One_root_point_2&)=default; /*! Constructor of a point with one-root coefficients. This constructor of a point can also be used with rational coefficients thanks to convertor of CoordNT. */ - _One_root_point_2 (const CoordNT& x, const CoordNT& y) : - Point_handle (Point_rep (x, y)) + _One_root_point_2(const CoordNT& x, const CoordNT& y) : + Point_handle(Point_rep(x, y)) {} /*! Get the x-coordinate. */ - const CoordNT& x () const - { - return (this->ptr()->_x); - } + const CoordNT& x() const { return (this->ptr()->_x); } /*! Get the y-coordinate. */ - const CoordNT& y () const - { - return (this->ptr()->_y); - } + const CoordNT& y() const { return (this->ptr()->_y); } /*! Check for equality. */ - bool equals (const Self& p) const + bool equals(const Self& p) const { - if (this->identical (p)) - return (true); + if (this->identical(p)) return (true); - return (CGAL::compare (this->ptr()->_x, p.ptr()->_x) == EQUAL && - CGAL::compare (this->ptr()->_y, p.ptr()->_y) == EQUAL); + return (CGAL::compare(this->ptr()->_x, p.ptr()->_x) == EQUAL && + CGAL::compare(this->ptr()->_y, p.ptr()->_y) == EQUAL); } - bool operator != (const Self& p) const - { - return !equals(p); - } + bool operator != (const Self& p) const { return ! equals(p); } + + bool operator == (const Self& p) const { return equals(p); } - bool operator == (const Self& p) const - { - return equals(p); - } /*! Set the point coordinates. */ - void set (const NT& x, const NT& y) + void set(const NT& x, const NT& y) { this->copy_on_write(); - this->ptr()->_x = CoordNT (x); - this->ptr()->_y = CoordNT (y); + this->ptr()->_x = CoordNT(x); + this->ptr()->_y = CoordNT(y); return; } /*! Set the point coordinates. */ - void set (const CoordNT& x, const CoordNT& y) + void set(const CoordNT& x, const CoordNT& y) { this->copy_on_write(); this->ptr()->_x = x; @@ -162,10 +139,9 @@ public: /*! * Exporter for conic arcs. */ -template -std::ostream& -operator<< (std::ostream& os, - const _One_root_point_2& p) +template +std::ostream& operator<<(std::ostream& os, + const _One_root_point_2& p) { os << CGAL::to_double(p.x()) << ' ' << CGAL::to_double(p.y()); return (os); @@ -186,11 +162,9 @@ std::istream & operator >> (std::istream & is, /*! \class * Representation of a circle, a circular arc or a line segment. */ -template -class _Circle_segment_2 -{ +template +class _Circle_segment_2 { public: - typedef Kernel_ Kernel; typedef typename Kernel::FT NT; typedef _One_root_point_2 Point_2; @@ -199,114 +173,101 @@ public: typedef typename Kernel::Line_2 Line_2; protected: - typedef typename Point_2::CoordNT CoordNT; // Data members: - Line_2 _line; // The supporting line (for line segments). - Circle_2 _circ; // The supporting circle (for circular arcs). - bool _is_full; // Whether we have a full circle. - bool _has_radius; // Is the radius (not just the squared radius) + Line_2 m_line; // The supporting line (for line segments). + Circle_2 m_circ; // The supporting circle (for circular arcs). + bool m_is_full; // Whether we have a full circle. + bool m_has_radius; // Is the radius (not just the squared radius) // explicitly specified). - NT _radius; // The radius, in case it is specified. - Point_2 _source; // The source point. - Point_2 _target; // The target point. - Orientation _orient; // The orientation (COLLINEAR for line segments). + NT m_radius; // The radius, in case it is specified. + Point_2 m_source; // The source point. + Point_2 m_target; // The target point. + Orientation m_orient; // The orientation (COLLINEAR for line segments). public: - /*! Default constructor. */ - _Circle_segment_2 () : - _is_full (false), - _has_radius (false), - _orient (COLLINEAR) + _Circle_segment_2() : + m_is_full(false), + m_has_radius(false), + m_orient(COLLINEAR) {} - /*! - * Constructor from a line segment. + /*! Constructor from a line segment. * \param seg The segment. */ - _Circle_segment_2 (const Segment_2& seg) : - _line (seg), - _is_full (false), - _has_radius (false), - _source (seg.source().x(), seg.source().y()), - _target (seg.target().x(), seg.target().y()), - _orient (COLLINEAR) + _Circle_segment_2(const Segment_2& seg) : + m_line(seg), + m_is_full(false), + m_has_radius(false), + m_source(seg.source().x(), seg.source().y()), + m_target(seg.target().x(), seg.target().y()), + m_orient(COLLINEAR) {} - /*! - * Constructor from of a line segment. + /*! Constructor from of a line segment. * \param ps The source point. * \param pt The target point. */ - _Circle_segment_2 (const typename Kernel::Point_2& ps, - const typename Kernel::Point_2& pt) : - _line (ps, pt), - _is_full (false), - _has_radius (false), - _source (ps.x(), ps.y()), - _target (pt.x(), pt.y()), - _orient (COLLINEAR) + _Circle_segment_2(const typename Kernel::Point_2& ps, + const typename Kernel::Point_2& pt) : + m_line(ps, pt), + m_is_full(false), + m_has_radius(false), + m_source(ps.x(), ps.y()), + m_target(pt.x(), pt.y()), + m_orient(COLLINEAR) {} - /*! - * Constructor of a segment, given a supporting line and two endpoints, + /*! Constructor of a segment, given a supporting line and two endpoints, * which need not necessarily have rational coordinates. * \param line The supporting line. * \param source The source point. * \param target The target point. * \pre Both endpoints lie on the supporting line. */ - _Circle_segment_2 (const Line_2& line, - const Point_2& source, const Point_2& target) : - _line (line), - _is_full (false), - _has_radius (false), - _source (source), - _target (target), - _orient (COLLINEAR) + _Circle_segment_2(const Line_2& line, + const Point_2& source, const Point_2& target) : + m_line(line), + m_is_full(false), + m_has_radius(false), + m_source(source), + m_target(target), + m_orient(COLLINEAR) { - CGAL_precondition (CGAL::compare (source.x()*line.a() + line.c(), - -source.y()*line.b()) == EQUAL); + CGAL_precondition(CGAL::compare(source.x() * line.a() + line.c(), + -source.y() * line.b()) == EQUAL); - CGAL_precondition (CGAL::compare (target.x()*line.a() + line.c(), - -target.y()*line.b()) == EQUAL); + CGAL_precondition(CGAL::compare(target.x() * line.a() + line.c(), + -target.y() * line.b()) == EQUAL); } - /*! - * Constructor from a circle. + /*! Constructor from a circle. * \param circ The circle. */ - _Circle_segment_2 (const Circle_2& circ) : - _circ (circ), - _is_full (true), - _has_radius (false), - _orient (circ.orientation()) - { - CGAL_assertion (_orient != COLLINEAR); - } + _Circle_segment_2(const Circle_2& circ) : + m_circ(circ), + m_is_full(true), + m_has_radius(false), + m_orient(circ.orientation()) + { CGAL_assertion(m_orient != COLLINEAR); } - /*! - * Constructor from a circle. + /*! Constructor from a circle. * \param c The circle center. * \param r The radius. * \param orient The orientation of the circle. */ - _Circle_segment_2 (const typename Kernel::Point_2& c, - const NT& r, - Orientation orient = COUNTERCLOCKWISE) : - _circ (c, r*r, orient), - _is_full (true), - _has_radius (true), - _radius (r), - _orient (orient) - { - CGAL_assertion (orient != COLLINEAR); - } + _Circle_segment_2(const typename Kernel::Point_2& c, const NT& r, + Orientation orient = COUNTERCLOCKWISE) : + m_circ(c, r*r, orient), + m_is_full(true), + m_has_radius(true), + m_radius(r), + m_orient(orient) + { CGAL_assertion (orient != COLLINEAR); } - /*! - * Constructor of a circular arc, given a supporting circle and two + /*! Constructor of a circular arc, given a supporting circle and two * endpoints, which need not necessarily have rational coordinates. * The orientation of the circle determines the orientation of the arc. * \param circ The supporting circle. @@ -314,30 +275,29 @@ public: * \param target The target point. * \pre Both endpoints lie on the supporting circle. */ - _Circle_segment_2 (const Circle_2& circ, - const Point_2& source, const Point_2& target) : - _circ (circ), - _is_full (false), - _has_radius (false), - _source (source), - _target (target), - _orient (circ.orientation()) + _Circle_segment_2(const Circle_2& circ, + const Point_2& source, const Point_2& target) : + m_circ(circ), + m_is_full(false), + m_has_radius(false), + m_source(source), + m_target(target), + m_orient(circ.orientation()) { - CGAL_assertion (_orient != COLLINEAR); + CGAL_assertion(m_orient != COLLINEAR); CGAL_precondition - (CGAL::compare (CGAL::square (source.x() - circ.center().x()), - circ.squared_radius() - - CGAL::square (source.y() - circ.center().y())) == EQUAL); + (CGAL::compare(CGAL::square(source.x() - circ.center().x()), + circ.squared_radius() - + CGAL::square(source.y() - circ.center().y())) == EQUAL); CGAL_precondition - (CGAL::compare (CGAL::square (target.x() - circ.center().x()), - circ.squared_radius() - - CGAL::square (target.y() - circ.center().y())) == EQUAL); + (CGAL::compare(CGAL::square(target.x() - circ.center().x()), + circ.squared_radius() - + CGAL::square(target.y() - circ.center().y())) == EQUAL); } - /*! - * Constructor of a circular arc, given a supporting circle and two + /*! Constructor of a circular arc, given a supporting circle and two * endpoints, which need not necessarily have rational coordinates. * \param c The circle center. * \param r The radius. @@ -346,86 +306,83 @@ public: * \param target The target point. * \pre Both endpoints lie on the supporting circle. */ - _Circle_segment_2 (const typename Kernel::Point_2& c, - const NT& r, Orientation orient, - const Point_2& source, const Point_2& target) : - _circ (c, r*r, orient), - _is_full (false), - _has_radius (true), - _radius (r), - _source (source), - _target (target), - _orient (orient) + _Circle_segment_2(const typename Kernel::Point_2& c, + const NT& r, Orientation orient, + const Point_2& source, const Point_2& target) : + m_circ(c, r*r, orient), + m_is_full(false), + m_has_radius(true), + m_radius(r), + m_source(source), + m_target(target), + m_orient(orient) { - CGAL_assertion (orient != COLLINEAR); + CGAL_assertion(orient != COLLINEAR); CGAL_precondition - (CGAL::compare (CGAL::square (source.x() - c.x()), - CGAL::square (r) - - CGAL::square (source.y() - c.y())) == EQUAL); + (CGAL::compare(CGAL::square(source.x() - c.x()), + CGAL::square(r) - + CGAL::square(source.y() - c.y())) == EQUAL); CGAL_precondition - (CGAL::compare (CGAL::square (target.x() - c.x()), - CGAL::square (r) - - CGAL::square (target.y() - c.y())) == EQUAL); + (CGAL::compare(CGAL::square(target.x() - c.x()), + CGAL::square(r) - + CGAL::square(target.y() - c.y())) == EQUAL); } - /*! - * Constructor of a circular arc, from the given three points, in case of + /*! Constructor of a circular arc, from the given three points, in case of * three collinear points, a segment will be constructed. * \param p1 The arc source. * \param p2 A point in the interior of the arc. * \param p3 The arc target. * \pre p1 and p3 are not equal. */ - _Circle_segment_2 (const typename Kernel::Point_2& p1, - const typename Kernel::Point_2& p2, - const typename Kernel::Point_2& p3) : - _is_full(false), - _has_radius(false), - _source(p1.x(), p1.y()), - _target(p3.x(), p3.y()) + _Circle_segment_2(const typename Kernel::Point_2& p1, + const typename Kernel::Point_2& p2, + const typename Kernel::Point_2& p3) : + m_is_full(false), + m_has_radius(false), + m_source(p1.x(), p1.y()), + m_target(p3.x(), p3.y()) { // Set the source and target. - NT x1 = p1.x(); - NT y1 = p1.y(); - NT x2 = p2.x(); - NT y2 = p2.y(); - NT x3 = p3.x(); - NT y3 = p3.y(); - + NT x1 = p1.x(); + NT y1 = p1.y(); + NT x2 = p2.x(); + NT y2 = p2.y(); + NT x3 = p3.x(); + NT y3 = p3.y(); // Make sure that the source and the target are not the same. - CGAL_precondition (Kernel().compare_xy_2_object() (p1, p3) != EQUAL); + CGAL_precondition(Kernel().compare_xy_2_object()(p1, p3) != EQUAL); // Compute the lines: A1*x + B1*y + C1 = 0, // and: A2*x + B2*y + C2 = 0, // where: - const NT _two = 2; + const NT _two = 2; - const NT A1 = _two*(x1 - x2); - const NT B1 = _two*(y1 - y2); - const NT C1 = CGAL::square(y2) - CGAL::square(y1) + - CGAL::square(x2) - CGAL::square(x1); + const NT A1 = _two*(x1 - x2); + const NT B1 = _two*(y1 - y2); + const NT C1 = + CGAL::square(y2) - CGAL::square(y1) + CGAL::square(x2) - CGAL::square(x1); - const NT A2 = _two*(x2 - x3); - const NT B2 = _two*(y2 - y3); - const NT C2 = CGAL::square(y3) - CGAL::square(y2) + - CGAL::square(x3) - CGAL::square(x2); + const NT A2 = _two*(x2 - x3); + const NT B2 = _two*(y2 - y3); + const NT C2 = + CGAL::square(y3) - CGAL::square(y2) + CGAL::square(x3) - CGAL::square(x2); // Compute the coordinates of the intersection point between the // two lines, given by (Nx / D, Ny / D), where: - const NT Nx = B1*C2 - B2*C1; - const NT Ny = A2*C1 - A1*C2; - const NT D = A1*B2 - A2*B1; + const NT Nx = B1*C2 - B2*C1; + const NT Ny = A2*C1 - A1*C2; + const NT D = A1*B2 - A2*B1; // Make sure the three points are not collinear. - const bool points_collinear = (CGAL::sign (D) == ZERO); + const bool points_collinear = (CGAL::sign (D) == ZERO); - if (points_collinear) - { - _line = Line_2(p1, p3); - _orient = COLLINEAR; + if (points_collinear) { + m_line = Line_2(p1, p3); + m_orient = COLLINEAR; return; } @@ -436,145 +393,118 @@ public: typename Kernel::Point_2 circ_center(x_center, y_center); - - - NT sqr_rad = (CGAL::square(D*x2 - Nx) + CGAL::square(D*y2 - Ny)) / - CGAL::square(D); + NT sqr_rad = + (CGAL::square(D*x2 - Nx) + CGAL::square(D*y2 - Ny)) / CGAL::square(D); // Determine the orientation: If the mid-point forms a left-turn with // the source and the target points, the orientation is positive (going // counterclockwise). // Otherwise, it is negative (going clockwise). - Kernel ker; + Kernel ker; typename Kernel::Orientation_2 orient_f = ker.orientation_2_object(); - if (orient_f(p1, p2, p3) == LEFT_TURN) - _orient = COUNTERCLOCKWISE; - else - _orient = CLOCKWISE; - - _circ = Circle_2(circ_center, sqr_rad, _orient); + if (orient_f(p1, p2, p3) == LEFT_TURN) m_orient = COUNTERCLOCKWISE; + else m_orient = CLOCKWISE; + m_circ = Circle_2(circ_center, sqr_rad, m_orient); } - /*! - * Get the orientation of the curve. + /*! Get the orientation of the curve. * \return COLLINEAR in case of a line segment, * CLOCKWISE or COUNTERCLOCKWISE for circular curves. */ - inline Orientation orientation () const - { - return (_orient); - } + inline Orientation orientation() const { return (m_orient); } /*! Check if the arc is linear. */ - inline bool is_linear () const - { - return (_orient == COLLINEAR); - } + inline bool is_linear() const { return (m_orient == COLLINEAR); } /*! Check if the arc is circular. */ - inline bool is_circular () const - { - return (_orient != COLLINEAR); - } + inline bool is_circular() const { return (m_orient != COLLINEAR); } - /*! - * Get the supporting line. + /*! Obtain the supporting line. * \pre The curve orientation is COLLINEAR. */ - const Line_2& supporting_line () const + const Line_2& supporting_line() const { - CGAL_precondition (_orient == COLLINEAR); - return (_line); + CGAL_precondition(m_orient == COLLINEAR); + return m_line; } - /*! - * Get the supporting circle. + /*! Obtain the supporting circle. * \pre The curve orientation is not COLLINEAR. */ - const Circle_2& supporting_circle () const + const Circle_2& supporting_circle() const { - CGAL_precondition (_orient != COLLINEAR); - return (_circ); + CGAL_precondition(m_orient != COLLINEAR); + return m_circ; } /*! Check if the curve is a full circle. */ - bool is_full () const - { - return (_is_full); - } + bool is_full() const { return (m_is_full); } /*! * Get the source point. * \pre The curve is not a full circle. */ - const Point_2& source () const + const Point_2& source() const { - CGAL_precondition (! _is_full); - return (_source); + CGAL_precondition(! m_is_full); + return (m_source); } /*! * Get the target point. * \pre The curve is not a full circle. */ - const Point_2& target () const + const Point_2& target() const { - CGAL_precondition (! _is_full); - return (_target); + CGAL_precondition(! m_is_full); + return (m_target); } - /*! - * Get the vertical tangency points the arc contains. + /*! Get the vertical tangency points the arc contains. * \param vpts Output: The vertical tangency points. * \pre The curve is circular. * \return The number of points (0, 1, or 2). */ - unsigned int vertical_tangency_points (Point_2 *vpts) const + unsigned int vertical_tangency_points(Point_2* vpts) const { - CGAL_precondition (_orient != COLLINEAR); - unsigned int n_vpts = 0; + CGAL_precondition(m_orient != COLLINEAR); + unsigned int n_vpts = 0; - if (_is_full) - { + if (m_is_full) { // In case of a full circle, create both vertical tangency points: - const NT& x0 = _circ.center().x(); - const NT& y0 = _circ.center().y(); - CoordNT xv_left; - CoordNT xv_right; + const NT& x0 = m_circ.center().x(); + const NT& y0 = m_circ.center().y(); + CoordNT xv_left; + CoordNT xv_right; - if (_has_radius) - { + if (m_has_radius) { // In case the radius is explicitly given: - xv_left = CoordNT (x0 - _radius); - xv_right = CoordNT (x0 + _radius); + xv_left = CoordNT(x0 - m_radius); + xv_right = CoordNT(x0 + m_radius); } - else - { + else { // In case only the squared root is given: - xv_left = CoordNT (x0, NT(-1), _circ.squared_radius()); - xv_right = CoordNT (x0, NT(1), _circ.squared_radius()); + xv_left = CoordNT(x0, NT(-1), m_circ.squared_radius()); + xv_right = CoordNT(x0, NT(1), m_circ.squared_radius()); } - vpts[0] = Point_2 (xv_left, y0); - vpts[1] = Point_2 (xv_right, y0); + vpts[0] = Point_2(xv_left, y0); + vpts[1] = Point_2(xv_right, y0); return (2); } - if (_orient == COUNTERCLOCKWISE) - { + if (m_orient == COUNTERCLOCKWISE) { // Compute the vertical tangency points for the arc: - n_vpts = _ccw_vertical_tangency_points (_source, _target, vpts); + n_vpts = _ccw_vertical_tangency_points(m_source, m_target, vpts); } - else - { + else { // Compute the vertical tangency points for the opposite arc: - n_vpts = _ccw_vertical_tangency_points (_target, _source, vpts); + n_vpts = _ccw_vertical_tangency_points(m_target, m_source, vpts); // Swap their order, if necessary. - if (n_vpts == 2) - { - Point_2 temp = vpts[0]; + if (n_vpts == 2) { + Point_2 temp = vpts[0]; vpts[0] = vpts[1]; vpts[1] = temp; } @@ -584,69 +514,62 @@ public: } private: - - /*! - * Get the vertical tangency points the arc contains, assuming it is + /*! Obtain the vertical tangency points the arc contains, assuming it is * counterclockwise oriented. * \param vpts Output: The vertical tangency points. * \return The number of points (0, 1, or 2). */ - unsigned int _ccw_vertical_tangency_points (const Point_2& src, - const Point_2& trg, - Point_2 *vpts) const + unsigned int _ccw_vertical_tangency_points(const Point_2& src, + const Point_2& trg, + Point_2* vpts) const { - unsigned int n_vpts = 0; - const NT& x0 = _circ.center().x(); - const NT& y0 = _circ.center().y(); - int qs = _quart_index (src); - int qt = _quart_index (trg); + unsigned int n_vpts = 0; + const NT& x0 = m_circ.center().x(); + const NT& y0 = m_circ.center().y(); + int qs = _quart_index(src); + int qt = _quart_index(trg); - if (qs == qt) - { - if ((qs == 0 || qs == 1) && CGAL::compare (src.x(), trg.x()) == LARGER) + if (qs == qt) { + if ((qs == 0 || qs == 1) && CGAL::compare(src.x(), trg.x()) == LARGER) // We have an x-monotone arc lying on the upper half of the circle: return (0); - if ((qs == 2 || qs == 3) && CGAL::compare (src.x(), trg.x()) == SMALLER) + if ((qs == 2 || qs == 3) && CGAL::compare(src.x(), trg.x()) == SMALLER) // We have an x-monotone arc lying on the lower half of the circle: return (0); } // Make sure the target quarter is larger than the source quarter, by // adding 4 to its index, if necessary. - if (qt <= qs) - qt += 4; + if (qt <= qs) qt += 4; // Start traversing the quarter-planes and collect the vertical tangency // points we encounter. - while (qs < qt) - { - if ((qs % 4) == 1) - { + while (qs < qt) { + if ((qs % 4) == 1) { // We collect the left tangency point when going from Q[1] to Q[2]: - if (CGAL::compare (x0, trg.x()) != LARGER || - CGAL::compare (y0, trg.y()) != EQUAL) + if (CGAL::compare(x0, trg.x()) != LARGER || + CGAL::compare(y0, trg.y()) != EQUAL) { - if (_has_radius) - vpts[n_vpts] = Point_2 (CoordNT (x0 - _radius), y0); + if (m_has_radius) + vpts[n_vpts] = Point_2(CoordNT(x0 - m_radius), y0); else - vpts[n_vpts] = Point_2 (CoordNT (x0, NT(-1), _circ.squared_radius()), - y0); + vpts[n_vpts] = + Point_2(CoordNT(x0, NT(-1), m_circ.squared_radius()), y0); n_vpts++; } } - else if ((qs % 4) == 3) - { + else if ((qs % 4) == 3) { // We collect the right tangency point when going from Q[3] to Q[0]: - if (CGAL::compare (x0, trg.x()) != SMALLER || - CGAL::compare (y0, trg.y()) != EQUAL) + if (CGAL::compare(x0, trg.x()) != SMALLER || + CGAL::compare(y0, trg.y()) != EQUAL) { - if (_has_radius) - vpts[n_vpts] = Point_2 (CoordNT (x0 + _radius), y0); + if (m_has_radius) + vpts[n_vpts] = Point_2(CoordNT(x0 + m_radius), y0); else - vpts[n_vpts] = Point_2 (CoordNT (x0, NT(1), _circ.squared_radius()), - y0); + vpts[n_vpts] = + Point_2(CoordNT(x0, NT(1), m_circ.squared_radius()), y0); n_vpts++; } } @@ -657,11 +580,10 @@ private: return (n_vpts); } - /*! - * Get the index of the quarter-plane containing the given point, + /*! Obtain the index of the quarter-plane containing the given point, * where the circle center is considered to be the origin. */ - int _quart_index (const Point_2& p) const + int _quart_index(const Point_2& p) const { // The plane looks like: // @@ -673,44 +595,32 @@ private: // x < 0 | x >= 0 // y <= 0 | y < 0 // - const CGAL::Sign sign_x = CGAL::sign (p.x() - _circ.center().x()); - const CGAL::Sign sign_y = CGAL::sign (p.y() - _circ.center().y()); + const CGAL::Sign sign_x = CGAL::sign(p.x() - m_circ.center().x()); + const CGAL::Sign sign_y = CGAL::sign(p.y() - m_circ.center().y()); - if (sign_x == POSITIVE) - { - return ((sign_y == NEGATIVE) ? 3 : 0); - } - else if (sign_x == NEGATIVE) - { - return ((sign_y == POSITIVE) ? 1 : 2); - } + if (sign_x == POSITIVE) return ((sign_y == NEGATIVE) ? 3 : 0); + else if (sign_x == NEGATIVE) return ((sign_y == POSITIVE) ? 1 : 2); CGAL_assertion (sign_y != ZERO); return ((sign_y == POSITIVE) ? 1 : 3); } }; -/*! - * Exporter for line segments and circular arcs. +/*! Exporter for line segments and circular arcs. */ -template +template std::ostream& -operator<< (std::ostream& os, - const _Circle_segment_2& c) +operator<<(std::ostream& os, const _Circle_segment_2& c) { - if (c.orientation() == COLLINEAR) - { + if (c.orientation() == COLLINEAR) { os<< "segment: " << c.source() << " -> " << c.target(); } - else - { - if(!c.is_full()) - { + else { + if (! c.is_full()) { os << "circular arc: " << c.supporting_circle() << ' ' << c.source() << " -> " << c.target(); } - else - { + else { os << "circular arc: " << c.supporting_circle(); } } @@ -721,11 +631,9 @@ operator<< (std::ostream& os, /*! \class * Representation of an x-monotone circular arc. */ -template -class _X_monotone_circle_segment_2 -{ +template +class _X_monotone_circle_segment_2 { public: - typedef Kernel_ Kernel; typedef _X_monotone_circle_segment_2 Self; typedef typename Kernel::FT NT; @@ -735,17 +643,16 @@ public: typedef typename Point_2::CoordNT CoordNT; // Type definition for the intersection points mapping. - typedef std::pair Curve_id_pair; - typedef unsigned int Multiplicity; - typedef std::pair Intersection_point_2; - typedef std::list Intersection_list; + typedef std::pair Curve_id_pair; + typedef unsigned int Multiplicity; + typedef std::pair Intersection_point; + typedef std::list Intersection_list; /*! * \struct Less functor for Curve_id_pair. */ - struct Less_id_pair - { - bool operator() (const Curve_id_pair& ip1, const Curve_id_pair& ip2) const + struct Less_id_pair { + bool operator()(const Curve_id_pair& ip1, const Curve_id_pair& ip2) const { // Compare the pairs of IDs lexicographically. return (ip1.first < ip2.first || @@ -753,25 +660,20 @@ public: } }; - typedef std::map Intersection_map; + typedef std::map + Intersection_map; typedef typename Intersection_map::value_type Intersection_map_entry; typedef typename Intersection_map::iterator Intersection_map_iterator; protected: - - NT _first; // The x-coordinate of the circle center. - // Or: the coefficient of x in the line equation. - - NT _second; // The y-coordinate of the circle center. - // Or: the coefficient of y in the line equation. - - NT _third; // The squared radius of the supporting circle. - // Or: the free coefficient in the line equation. - - Point_2 _source; // The source point. - Point_2 _target; // The target point. + NT m_first; // The x-coordinate of the circle center. + // Or: the coefficient of x in the line equation. + NT m_second; // The y-coordinate of the circle center. + // Or: the coefficient of y in the line equation. + NT m_third; // The squared radius of the supporting circle. + // Or: the free coefficient in the line equation. + Point_2 m_source; // The source point. + Point_2 m_target; // The target point. enum { IS_DIRECTED_RIGHT_MASK = 1, @@ -782,7 +684,7 @@ protected: INDEX_SHIFT_BITS = 4 }; - unsigned int _info; // A bit vector, where: + unsigned int m_info; // A bit vector, where: // Bit 0 (the LSB): marks if the arc is directed // from left to right. // Bit 1: marks if the arc is a vertical segment. @@ -790,408 +692,321 @@ protected: // The rest of the bits represent the curve index. public: - - /*! - * Default constructor. + /*! Default constructor. */ - _X_monotone_circle_segment_2 () : - _first(), - _second(), - _third(), - _source(), - _target(), - _info (0) + _X_monotone_circle_segment_2() : + m_first(), + m_second(), + m_third(), + m_source(), + m_target(), + m_info(0) {} - /*! - * Construct an arc from a line segment. + /*! Construct an arc from a line segment. * \param line The supporting line. * \param source The source point. * \param target The target point. */ - _X_monotone_circle_segment_2 (const Line_2& line, - const Point_2& source, const Point_2& target, - unsigned int index = 0) : - _first (line.a()), - _second (line.b()), - _third (line.c()), - _source (source), - _target(target), - _info (index << INDEX_SHIFT_BITS) + _X_monotone_circle_segment_2(const Line_2& line, + const Point_2& source, const Point_2& target, + unsigned int index = 0) : + m_first(line.a()), + m_second(line.b()), + m_third(line.c()), + m_source(source), + m_target(target), + m_info(index << INDEX_SHIFT_BITS) { // Check if the segment is directed left or right: - Comparison_result res = CGAL::compare (source.x(), target.x()); + Comparison_result res = CGAL::compare(source.x(), target.x()); - if (res == EQUAL) - { - CGAL_precondition (CGAL::sign(_second) == ZERO); + if (res == EQUAL) { + CGAL_precondition(CGAL::sign(m_second) == ZERO); // We have a vertical segment - compare the points by their // y-coordinates: - _info = (_info | IS_VERTICAL_SEGMENT_MASK); - res = CGAL::compare (source.y(), target.y()); + m_info = (m_info | IS_VERTICAL_SEGMENT_MASK); + res = CGAL::compare(source.y(), target.y()); } - CGAL_precondition (res != EQUAL); - if (res == SMALLER) - _info = (_info | IS_DIRECTED_RIGHT_MASK); + CGAL_precondition(res != EQUAL); + if (res == SMALLER) m_info = (m_info | IS_DIRECTED_RIGHT_MASK); } - /*! - * Construct a segment arc from two kernel points + /*! Construct a segment arc from two kernel points * \param source the source point. * \ param target the target point. * \pre source and target are not equal. */ - _X_monotone_circle_segment_2 (const typename Kernel::Point_2& source, - const typename Kernel::Point_2& target) : - _source(source.x(), source.y()), - _target(target.x(), target.y()), - _info (0) + _X_monotone_circle_segment_2(const typename Kernel::Point_2& source, + const typename Kernel::Point_2& target) : + m_source(source.x(), source.y()), + m_target(target.x(), target.y()), + m_info(0) { Line_2 line(source, target); - _first = line.a(); - _second = line.b(); - _third = line.c(); + m_first = line.a(); + m_second = line.b(); + m_third = line.c(); // Check if the segment is directed left or right: - Comparison_result res = CGAL::compare (source.x(), target.x()); + Comparison_result res = CGAL::compare(source.x(), target.x()); - if (res == EQUAL) - { - CGAL_precondition (CGAL::sign(_second) == ZERO); + if (res == EQUAL) { + CGAL_precondition(CGAL::sign(m_second) == ZERO); // We have a vertical segment - compare the points by their // y-coordinates: - _info = (_info | IS_VERTICAL_SEGMENT_MASK); - res = CGAL::compare (source.y(), target.y()); + m_info = (m_info | IS_VERTICAL_SEGMENT_MASK); + res = CGAL::compare(source.y(), target.y()); } - CGAL_precondition (res != EQUAL); - if (res == SMALLER) - _info = (_info | IS_DIRECTED_RIGHT_MASK); + CGAL_precondition(res != EQUAL); + if (res == SMALLER) m_info = (m_info | IS_DIRECTED_RIGHT_MASK); } - /*! - * Construct a circular arc. + /*! Construct a circular arc. * \param line The supporting line. * \param source The source point. * \param target The target point. * \param orient The orientation of the arc. */ - _X_monotone_circle_segment_2 (const Circle_2& circ, - const Point_2& source, const Point_2& target, - Orientation orient, - unsigned int index = 0) : - _first (circ.center().x()), - _second (circ.center().y()), - _third (circ.squared_radius()), - _source (source), - _target(target), - _info (index << INDEX_SHIFT_BITS) + _X_monotone_circle_segment_2(const Circle_2& circ, + const Point_2& source, const Point_2& target, + Orientation orient, + unsigned int index = 0) : + m_first(circ.center().x()), + m_second(circ.center().y()), + m_third(circ.squared_radius()), + m_source(source), + m_target(target), + m_info(index << INDEX_SHIFT_BITS) { // Check if the segment is directed left or right: - Comparison_result res = CGAL::compare (source.x(), target.x()); + Comparison_result res = CGAL::compare (source.x(), target.x()); - CGAL_precondition (res != EQUAL); - if (res == SMALLER) - _info = (_info | IS_DIRECTED_RIGHT_MASK); + CGAL_precondition(res != EQUAL); + if (res == SMALLER) m_info = (m_info | IS_DIRECTED_RIGHT_MASK); // Set the orientation. CGAL_precondition (orient != COLLINEAR); - if (orient == COUNTERCLOCKWISE) - _info = (_info | COUNTERCLOCKWISE_CODE); - else - _info = (_info | CLOCKWISE_CODE); + if (orient == COUNTERCLOCKWISE) m_info = (m_info | COUNTERCLOCKWISE_CODE); + else m_info = (m_info | CLOCKWISE_CODE); } /*! Check if the arc is linear. */ - inline bool is_linear () const - { - return ((_info & ORIENTATION_MASK) == 0); - } + inline bool is_linear () const { return ((m_info & ORIENTATION_MASK) == 0); } /*! Check if the arc is circular. */ inline bool is_circular () const - { - return ((_info & ORIENTATION_MASK) != 0); - } + { return ((m_info & ORIENTATION_MASK) != 0); } - /*! - * Get the supporting line. + /*! Obtain the supporting line. * \pre The arc is linear (a line segment). */ - Line_2 supporting_line () const + Line_2 supporting_line() const { CGAL_precondition (is_linear()); - return (Line_2 (a(), b(), c())); } - /*! - * Get the supporting circle. + /*! Obtain the supporting circle. * \pre The arc is circular. */ - Circle_2 supporting_circle () const + Circle_2 supporting_circle() const { CGAL_precondition (is_circular()); - typename Kernel::Point_2 center (x0(), y0()); - return (Circle_2 (center , sqr_r(), orientation())); + typename Kernel::Point_2 center(x0(), y0()); + return (Circle_2(center , sqr_r(), orientation())); } /*! Get the source point. */ - inline const Point_2& source () const - { - return (_source); - } + inline const Point_2& source() const { return (m_source); } /*! Get the target point. */ - inline const Point_2& target () const - { - return (_target); - } + inline const Point_2& target() const { return (m_target); } /*! True if the arc is directed right, false otherwise. */ - bool is_directed_right () const - { - return ((_info & IS_DIRECTED_RIGHT_MASK) != 0); - } + bool is_directed_right() const + { return ((m_info & IS_DIRECTED_RIGHT_MASK) != 0); } - bool has_left() const - { - return true; - } + bool has_left() const { return true; } - bool has_right() const - { - return true; - } + bool has_right() const { return true; } /*! Get the left endpoint of the arc. */ - inline const Point_2& left () const - { - return (((_info & IS_DIRECTED_RIGHT_MASK) != 0) ? _source : _target); - } + inline const Point_2& left() const + { return (((m_info & IS_DIRECTED_RIGHT_MASK) != 0) ? m_source : m_target); } /*! Get the right endpoint of the arc. */ - inline const Point_2& right () const - { - return (((_info & IS_DIRECTED_RIGHT_MASK) != 0) ? _target : _source); - } + inline const Point_2& right() const + { return (((m_info & IS_DIRECTED_RIGHT_MASK) != 0) ? m_target : m_source); } - /*! - * Check whether the given point is in the x-range of the arc. + /*! Check whether the given point is in the x-range of the arc. */ - bool is_in_x_range (const Point_2& p) const + bool is_in_x_range(const Point_2& p) const { - Comparison_result res = CGAL::compare (p.x(), left().x()); + Comparison_result res = CGAL::compare (p.x(), left().x()); - if (res == SMALLER) - return (false); - else if (res == EQUAL) - return (true); + if (res == SMALLER) return false; + else if (res == EQUAL) return true; return (CGAL::compare (p.x(), right().x()) != LARGER); } /*! Check if the arc is a vertical segment. */ - inline bool is_vertical () const - { - return ((_info & IS_VERTICAL_SEGMENT_MASK) != 0); - } + inline bool is_vertical() const + { return ((m_info & IS_VERTICAL_SEGMENT_MASK) != 0); } /*! Get the orientation of the arc. */ inline Orientation orientation() const { - unsigned int _or = (_info & ORIENTATION_MASK); + unsigned int or_ = (m_info & ORIENTATION_MASK); + if (or_ == COUNTERCLOCKWISE_CODE) return (CGAL::COUNTERCLOCKWISE); + else if (or_ == CLOCKWISE_CODE) return (CGAL::CLOCKWISE); - if (_or == COUNTERCLOCKWISE_CODE) - return (CGAL::COUNTERCLOCKWISE); - else if (_or == CLOCKWISE_CODE) - return (CGAL::CLOCKWISE); - - CGAL_assertion (_or == 0); + CGAL_assertion(or_ == 0); return (CGAL::COLLINEAR); } - /*! - * Check the position of a given point with respect to the arc. + /*! Check the position of a given point with respect to the arc. */ - Comparison_result point_position (const Point_2& p) const + Comparison_result point_position(const Point_2& p) const { - if (is_linear()) - return (_line_point_position (p)); - else - return (_circ_point_position (p)); + if (is_linear()) return (_line_point_position(p)); + else return (_circ_point_position (p)); } - - /*! - * Compare the two arcs to the right of their intersection point. + /*! Compare the two arcs to the right of their intersection point. */ - Comparison_result compare_to_right (const Self& cv, const Point_2& p) const + Comparison_result compare_to_right(const Self& cv, const Point_2& p) const { - if (is_linear()) - { - if (cv.is_linear()) - return (_lines_compare_to_right (cv, p)); - - Comparison_result res = cv._circ_line_compare_to_right (*this, p); - - if (res != EQUAL) - res = (res == SMALLER) ? LARGER : SMALLER; - + if (is_linear()) { + if (cv.is_linear()) return (_lines_compare_to_right (cv, p)); + Comparison_result res = cv._circ_line_compare_to_right (*this, p); + if (res != EQUAL) res = (res == SMALLER) ? LARGER : SMALLER; return (res); } - else - { - if (cv.is_linear()) - return (_circ_line_compare_to_right (cv, p)); - + else { + if (cv.is_linear()) return (_circ_line_compare_to_right (cv, p)); return (_circs_compare_to_right (cv, p)); } } - /*! - * Compare the two arcs to the left of their intersection point. + /*! Compare the two arcs to the left of their intersection point. */ - Comparison_result compare_to_left (const Self& cv, const Point_2& p) const + Comparison_result compare_to_left(const Self& cv, const Point_2& p) const { - if (is_linear()) - { - if (cv.is_linear()) - return (_lines_compare_to_left (cv, p)); - - Comparison_result res = cv._circ_line_compare_to_left (*this, p); - - if (res != EQUAL) - res = (res == SMALLER) ? LARGER : SMALLER; - + if (is_linear()) { + if (cv.is_linear()) return (_lines_compare_to_left (cv, p)); + Comparison_result res = cv._circ_line_compare_to_left(*this, p); + if (res != EQUAL) res = (res == SMALLER) ? LARGER : SMALLER; return (res); } - else - { - if (cv.is_linear()) - return (_circ_line_compare_to_left (cv, p)); - + else { + if (cv.is_linear()) return (_circ_line_compare_to_left(cv, p)); return (_circs_compare_to_left (cv, p)); } } - /*! - * Check whether the two arcs have the same supporting curve. + /*! Check whether the two arcs have the same supporting curve. */ - bool has_same_supporting_curve (const Self& cv) const + bool has_same_supporting_curve(const Self& cv) const { // Check if the curve indices are the same. - if (_index() != 0 && _index() == cv._index()) - return (true); + if (_index() != 0 && _index() == cv._index()) return true; // Make sure that the supporting curves are of the same type. - if (is_linear() && ! cv.is_linear()) - return (false); + if (is_linear() && ! cv.is_linear()) return false; - if (! is_linear() && cv.is_linear()) - return (false); + if (! is_linear() && cv.is_linear()) return false; // Compare the curve coefficients. - if (! is_linear()) - { + if (! is_linear()) { // The two circles must have the same center and the same radius. - return (CGAL::compare (x0(), cv.x0()) == EQUAL && - CGAL::compare (y0(), cv.y0()) == EQUAL && - CGAL::compare (sqr_r(), cv.sqr_r()) == EQUAL); + return (CGAL::compare(x0(), cv.x0()) == EQUAL && + CGAL::compare(y0(), cv.y0()) == EQUAL && + CGAL::compare(sqr_r(), cv.sqr_r()) == EQUAL); } // Compare the line equations: Note that these may be scaled. - NT fact1; - NT fact2; + NT fact1; + NT fact2; - if (is_vertical()) - { - if (! cv.is_vertical()) - return (false); + if (is_vertical()) { + if (! cv.is_vertical()) return false; fact1 = a(); fact2 = cv.a(); } - else - { + else { fact1 = b(); fact2 = cv.b(); } - return (CGAL::compare (fact2*a(), fact1*cv.a()) == EQUAL && - CGAL::compare (fact2*b(), fact1*cv.b()) == EQUAL && - CGAL::compare (fact2*c(), fact1*cv.c()) == EQUAL); + return (CGAL::compare(fact2*a(), fact1*cv.a()) == EQUAL && + CGAL::compare(fact2*b(), fact1*cv.b()) == EQUAL && + CGAL::compare(fact2*c(), fact1*cv.c()) == EQUAL); } - /*! - * Check if the two curves are equal. + /*! Check whether the two curves are equal. */ - bool equals (const Self& cv) const + bool equals(const Self& cv) const { - if (! this->has_same_supporting_curve (cv)) - return (false); + if (! this->has_same_supporting_curve(cv)) return false; - if (is_linear()) - { + if (is_linear()) { // In case of line segments we can swap the source and target: - return ((_source.equals (cv._source) && _target.equals (cv._target)) || - (_source.equals (cv._target) && _target.equals (cv._source))); + return ((m_source.equals(cv.m_source) && m_target.equals(cv.m_target)) || + (m_source.equals(cv.m_target) && m_target.equals(cv.m_source))); } // Once again, opposite circular arcs are considered to be equal: return ((orientation() == cv.orientation() && - _source.equals (cv._source) && _target.equals (cv._target)) || + m_source.equals(cv.m_source) && m_target.equals(cv.m_target)) || (orientation() != cv.orientation() && - _source.equals (cv._target) && _target.equals (cv._source))); + m_source.equals(cv.m_target) && m_target.equals(cv.m_source))); } - /*! - * Split the curve at a given point into two sub-arcs. + /*! Split the curve at a given point into two sub-arcs. */ - void split (const Point_2& p, Self& c1, Self& c2) const + void split(const Point_2& p, Self& c1, Self& c2) const { // Copy the properties of this arc to the sub-arcs. c1 = *this; c2 = *this; // Change the endpoint, such that c1 lies to the right of c2: - if (is_directed_right()) - { - c1._target = p; - c2._source = p; + if (is_directed_right()) { + c1.m_target = p; + c2.m_source = p; } - else - { - c1._source = p; - c2._target = p; + else { + c1.m_source = p; + c2.m_target = p; } - - return; } - /*! - * Compute the intersections between the two arcs or segments. + /*! Compute the intersections between the two arcs or segments. */ - template - OutputIterator intersect (const Self& cv, OutputIterator oi, - Intersection_map *inter_map = nullptr) const + template + OutputIterator intersect(const Self& cv, OutputIterator oi, + Intersection_map* inter_map = nullptr) const { - // First check whether the two arcs have the same supporting curve. - if (has_same_supporting_curve (cv)) - { - // Check for overlaps between the two arcs. - Self overlap; + typedef std::pair Intersection_point; + typedef boost::variant Intersection_result; - if (_compute_overlap (cv, overlap)) - { + // First check whether the two arcs have the same supporting curve. + if (has_same_supporting_curve(cv)) { + // Check for overlaps between the two arcs. + Self overlap; + + if (_compute_overlap(cv, overlap)) { // There can be just a single overlap between two x-monotone arcs: - *oi = CGAL::make_object (overlap); - ++oi; - return (oi); + *oi++ = Intersection_result(overlap); + return oi; } // In case there is not overlap and the supporting curves are the same, @@ -1199,155 +1014,121 @@ public: // a common end point. // Note that in this case we do not define the multiplicity of the // intersection points we report. - unsigned int mult = 0; - if (left().equals (cv.left()) || left().equals(cv.right())) - { - *oi = CGAL::make_object (std::make_pair (left(), mult)); - ++oi; + Multiplicity mult = 0; + if (left().equals(cv.left()) || left().equals(cv.right())) { + *oi++ = Intersection_result(std::make_pair(left(), mult)); } - if (right().equals (cv.right()) || right().equals(cv.left())) - { - *oi = CGAL::make_object (std::make_pair (right(), mult)); - ++oi; + if (right().equals(cv.right()) || right().equals(cv.left())) { + *oi++ = Intersection_result(std::make_pair(right(), mult)); } - return (oi); + return oi; } // Before computing the intersection points between the two supporting // curves, check if their intersection has already been computed and // cached. - Curve_id_pair id_pair; - Intersection_map_iterator map_iter; - Intersection_list inter_list; - bool invalid_ids = false; + Curve_id_pair id_pair; + Intersection_map_iterator map_iter; + Intersection_list inter_list; + bool invalid_ids = false; - if (inter_map != nullptr && _index() != 0 && cv._index() != 0) - { + if (inter_map != nullptr && _index() != 0 && cv._index() != 0) { if (_index() < cv._index()) id_pair = Curve_id_pair (_index(), cv._index()); - else - id_pair = Curve_id_pair (cv._index(), _index()); + else id_pair = Curve_id_pair (cv._index(), _index()); - map_iter = inter_map->find (id_pair); + map_iter = inter_map->find(id_pair); } - else - { + else { // In case one of the IDs is invalid, we do not look in the map neither // we cache the results. - if (inter_map != nullptr) - map_iter = inter_map->end(); + if (inter_map != nullptr) map_iter = inter_map->end(); invalid_ids = true; } - if (inter_map == nullptr || map_iter == inter_map->end()) - { + if ((inter_map == nullptr) || (map_iter == inter_map->end())) { // Compute the intersections points between the two supporting curves. - if (is_linear()) - { - if (cv.is_linear()) - _lines_intersect (cv, inter_list); - else - cv._circ_line_intersect (*this, inter_list); + if (is_linear()) { + if (cv.is_linear()) _lines_intersect(cv, inter_list); + else cv._circ_line_intersect(*this, inter_list); } - else - { - if (cv.is_linear()) - _circ_line_intersect (cv, inter_list); - else - _circs_intersect (cv, inter_list); + else { + if (cv.is_linear()) _circ_line_intersect(cv, inter_list); + else _circs_intersect(cv, inter_list); } // Cache the result. - if (! invalid_ids) - (*inter_map)[id_pair] = inter_list; + if (! invalid_ids) (*inter_map)[id_pair] = inter_list; } - else - { + else { // Obtain the precomputed intersection points from the map. inter_list = (*map_iter).second; } // Report only the intersection points that lie on both arcs. - typename Intersection_list::const_iterator iter; - - for (iter = inter_list.begin(); iter != inter_list.end(); ++iter) - { + for (auto iter = inter_list.begin(); iter != inter_list.end(); ++iter) { if (this->_is_between_endpoints (iter->first) && cv._is_between_endpoints (iter->first)) { - *oi = CGAL::make_object (*iter); - ++oi; + *oi++ = Intersection_result(*iter); } } - return (oi); + return oi; } - /*! - * Check whether it is possible to merge our arc with the given arc. + /*! Check whether it is possible to merge our arc with the given arc. */ - bool can_merge_with (const Self& cv) const + bool can_merge_with(const Self& cv) const { // In order to merge the two arcs, they should have the same supporting // curve. - if (! this->has_same_supporting_curve (cv)) - return (false); + if (! this->has_same_supporting_curve(cv)) return false; // Check if the left endpoint of one curve is the right endpoint of the // other. - return (right().equals (cv.left()) || - left().equals (cv.right())); + return (right().equals(cv.left()) || left().equals(cv.right())); } - /*! - * Merge our arc with the given arc. + /*! Merge our arc with the given arc. * \pre The two arcs are mergeable. */ - void merge (const Self& cv) + void merge(const Self& cv) { - CGAL_precondition (this->can_merge_with (cv)); + CGAL_precondition(this->can_merge_with (cv)); // Check if we should extend the arc to the left or to the right. - if (right().equals (cv.left())) - { + if (right().equals(cv.left())) { // Extend the arc to the right. - if (is_directed_right()) - this->_target = cv.right(); - else - this->_source = cv.right(); + if (is_directed_right()) this->m_target = cv.right(); + else this->m_source = cv.right(); } - else - { - CGAL_precondition (left().equals (cv.right())); + else { + CGAL_precondition(left().equals(cv.right())); // Extend the arc to the left. - if (is_directed_right()) - this->_source = cv.left(); - else - this->_target = cv.left(); + if (is_directed_right()) this->m_source = cv.left(); + else this->m_target = cv.left(); } - - return; } /*! construct an opposite arc. */ Self construct_opposite() const { Self opp_cv; - opp_cv._first = this->_first; - opp_cv._second = this-> _second; - opp_cv._third = this-> _third; - opp_cv._source = this->_target; - opp_cv._target = this->_source; + opp_cv.m_first = this->m_first; + opp_cv.m_second = this->m_second; + opp_cv.m_third = this->m_third; + opp_cv.m_source = this->m_target; + opp_cv.m_target = this->m_source; // Take care of the information bits: We flip the orientation bits and // the bits that marks the direction. - if (is_linear()) - opp_cv._info = (this->_info ^ IS_DIRECTED_RIGHT_MASK); + if (is_linear()) opp_cv.m_info = (this->m_info ^ IS_DIRECTED_RIGHT_MASK); else - opp_cv._info = (this->_info ^ IS_DIRECTED_RIGHT_MASK ^ ORIENTATION_MASK); + opp_cv.m_info = (this->m_info ^ IS_DIRECTED_RIGHT_MASK ^ ORIENTATION_MASK); return (opp_cv); } @@ -1358,65 +1139,47 @@ public: double x_max = to_double(right().x()); double y_min = to_double(left().y()); double y_max = to_double(right().y()); - if(y_min > y_max) - std::swap(y_min, y_max); - if(is_circular()) - { + if (y_min > y_max) std::swap(y_min, y_max); + if (is_circular()) { const Circle_2& circ = this->supporting_circle(); - if(_is_upper()) - { + if (_is_upper()) { y_max = to_double(circ.center().y())+ - std::sqrt(to_double(circ.squared_radius())); + std::sqrt(to_double(circ.squared_radius())); } - else - { + else { y_min = to_double(circ.center().y()) - - std::sqrt(to_double(circ.squared_radius())); + std::sqrt(to_double(circ.squared_radius())); } } - return Bbox_2(x_min, y_min, x_max, y_max); } protected: - /*! Get the curve index. */ - inline unsigned int _index () const - { - return (_info >> INDEX_SHIFT_BITS); - } + inline unsigned int _index() const { return (m_info >> INDEX_SHIFT_BITS); } /// \name Accessors for circular arcs. //@{ /*! Get the x-coordinate of the center of the supporting circle. */ - inline const NT& x0 () const - { - return (_first); - } + inline const NT& x0() const { return (m_first); } /*! Get the y-coordinate of the center of the supporting circle. */ - inline const NT& y0 () const - { - return (_second); - } + inline const NT& y0() const { return (m_second); } /*! Get the squared radius of the supporting circle. */ - inline const NT& sqr_r () const - { - return (_third); - } + inline const NT& sqr_r() const { return (m_third); } /*! * Check if the circular arc lies on the upper half of the supporting circle. */ - inline bool _is_upper () const + inline bool _is_upper() const { - Orientation orient = orientation(); - bool dir_right = ((_info & IS_DIRECTED_RIGHT_MASK) != 0); + Orientation orient = orientation(); + bool dir_right = ((m_info & IS_DIRECTED_RIGHT_MASK) != 0); - CGAL_precondition (orient != COLLINEAR); + CGAL_precondition(orient != COLLINEAR); return ((orient == COUNTERCLOCKWISE && !dir_right) || (orient == CLOCKWISE && dir_right)); @@ -1427,22 +1190,13 @@ protected: //@{ /*! Get the coefficient of x in the equation of the supporting line. */ - inline const NT& a () const - { - return (_first); - } + inline const NT& a() const { return (m_first); } /*! Get the coefficient of y in the equation of the supporting line. */ - inline const NT& b () const - { - return (_second); - } + inline const NT& b() const { return (m_second); } /*! Get the free coefficient in the equation of the supporting line. */ - inline const NT& c () const - { - return (_third); - } + inline const NT& c() const { return (m_third); } //@} /// \name Auxiliary functions for the point_position predicate. @@ -1451,27 +1205,24 @@ protected: /*! * Check the position of a given point with respect to a line segment. */ - Comparison_result _line_point_position (const Point_2& p) const + Comparison_result _line_point_position(const Point_2& p) const { // Check if we have a vertical segment. - CGAL_precondition (is_in_x_range(p)); + CGAL_precondition(is_in_x_range(p)); - Comparison_result res; + Comparison_result res; - if (is_vertical()) - { + if (is_vertical()) { // left() is the lower endpoint: - res = CGAL::compare (p.y(), left().y()); + res = CGAL::compare(p.y(), left().y()); - if (res != LARGER) - return (res); + if (res != LARGER) return (res); // left() is the upper endpoint: res = CGAL::compare (p.y(), right().y()); - if (res != SMALLER) - return (res); + if (res != SMALLER) return (res); // p lies in the interior of the vertical segment: return (EQUAL); @@ -1487,19 +1238,17 @@ protected: /*! * Check the position of a given point with respect to a circular arc. */ - Comparison_result _circ_point_position (const Point_2& p) const + Comparison_result _circ_point_position(const Point_2& p) const { - Comparison_result c_res = CGAL::compare (p.y(), y0()); + Comparison_result c_res = CGAL::compare (p.y(), y0()); - if (_is_upper()) - { + if (_is_upper()) { // Check if p lies below the "equator" (while the arc lies above it): if (c_res == SMALLER) return (SMALLER); } - else - { + else { // Check if p lies above the "equator" (while the arc lies below it): if (c_res == LARGER) return (LARGER); @@ -1507,21 +1256,18 @@ protected: // Check if p lies inside the supporting circle, namely we have to check // whether (p.x() - x0)^2 + (p.y() - y0)^2 < r^2: - Comparison_result res = - CGAL::compare (CGAL::square (p.x() - x0()), - sqr_r() - CGAL::square (p.y() - y0())); + Comparison_result res = + CGAL::compare(CGAL::square (p.x() - x0()), + sqr_r() - CGAL::square (p.y() - y0())); - if (res == EQUAL) - // p lies on the circle: - return (EQUAL); + // p lies on the circle: + if (res == EQUAL) return (EQUAL); - if (_is_upper()) - { + if (_is_upper()) { // If p is inside the circle, it lies below the upper arc: return (res); } - else - { + else { // If p is inside the circle, it lies above the lower arc: return (res == SMALLER ? LARGER : SMALLER); } @@ -1534,25 +1280,18 @@ protected: /*! * Compare two line segments to the right of their intersection point. */ - Comparison_result _lines_compare_to_right (const Self& cv, - const Point_2& /* p */) const + Comparison_result _lines_compare_to_right(const Self& cv, + const Point_2& /* p */) const { - if (_index() != 0 && _index() == cv._index()) - return (EQUAL); + if (_index() != 0 && _index() == cv._index()) return (EQUAL); // Special treatment for vertical segments: a vertical segment is larger // than any other non-vertical segment. - if (is_vertical()) - { - if (cv.is_vertical()) - return (EQUAL); - + if (is_vertical()) { + if (cv.is_vertical()) return (EQUAL); return (LARGER); } - else if (cv.is_vertical()) - { - return (SMALLER); - } + else if (cv.is_vertical()) return (SMALLER); // Compare the slopes: -A1/B1 and -A2/B2. We actually negate the slopes // and swap the result. @@ -1563,12 +1302,11 @@ protected: * Compare a circular arcs (this) and a line segment (cv) to the right of * their intersection point. */ - Comparison_result _circ_line_compare_to_right (const Self& cv, - const Point_2& p) const + Comparison_result _circ_line_compare_to_right(const Self& cv, + const Point_2& p) const { // A vertical segment lies above any other circle to the right of p: - if (cv.is_vertical()) - return (SMALLER); + if (cv.is_vertical()) return (SMALLER); // We have to compare the slopes of the supporting circles and the // supporting line at p: @@ -1580,8 +1318,7 @@ protected: const CGAL::Sign sign_denom1 = CGAL::sign (y0() - p.y()); // Check the case of a vertical tangent. - if (sign_denom1 == ZERO) - { + if (sign_denom1 == ZERO) { // The arc lies above any line segment if it is an upper arc, or below // any segment if it is a lower arc. return (_is_upper() ? LARGER : SMALLER); @@ -1589,16 +1326,13 @@ protected: // Compare (p.x() - x0(1)) and (A(2)/B(2)*(p.y() - y0(1)). // Note that if the denominator is negative, we have to swap the result. - const bool swap_res = (sign_denom1 == NEGATIVE); - Comparison_result slope_res = CGAL::compare (p.x() - x0(), - (p.y() - y0())*cv.a()/cv.b()); - - if (slope_res != EQUAL) - { - if (swap_res) - // Swap the comparison result, if necessary: - slope_res = (slope_res == SMALLER) ? LARGER : SMALLER; + const bool swap_res = (sign_denom1 == NEGATIVE); + Comparison_result slope_res = + CGAL::compare (p.x() - x0(), (p.y() - y0())*cv.a()/cv.b()); + if (slope_res != EQUAL) { + // Swap the comparison result, if necessary: + if (swap_res) slope_res = (slope_res == SMALLER) ? LARGER : SMALLER; return (slope_res); } @@ -1608,23 +1342,18 @@ protected: return (_is_upper() ? SMALLER : LARGER); } - /*! - * Compare two circular arcs to the right of their intersection point. + /*! Compare two circular arcs to the right of their intersection point. */ - Comparison_result _circs_compare_to_right (const Self& cv, - const Point_2& p) const + Comparison_result _circs_compare_to_right(const Self& cv, + const Point_2& p) const { - if (_index() != 0 && _index() == cv._index()) - { + if (_index() != 0 && _index() == cv._index()) { // Check the case of comparing two circular arcs that originate from the // same supporting circle. Their comparison result is not EQUAL only if // one is an upper arc and the other is a lower arc. - if (_is_upper() && ! cv._is_upper()) - return (LARGER); - else if (! _is_upper() && cv._is_upper()) - return (SMALLER); - else - return (EQUAL); + if (_is_upper() && ! cv._is_upper()) return (LARGER); + else if (! _is_upper() && cv._is_upper()) return (SMALLER); + else return (EQUAL); } // We have to compare the slopes of the two supporting circles at p: @@ -1633,39 +1362,31 @@ protected: // --------------- and --------------- // y0(1) - p.y() y0(2) - p.y() // - const CGAL::Sign sign_numer1 = CGAL::sign (p.x() - x0()); - const CGAL::Sign sign_denom1 = CGAL::sign (y0() - p.y()); - const CGAL::Sign sign_numer2 = CGAL::sign (p.x() - cv.x0()); - const CGAL::Sign sign_denom2 = CGAL::sign (cv.y0() - p.y()); + const CGAL::Sign sign_numer1 = CGAL::sign(p.x() - x0()); + const CGAL::Sign sign_denom1 = CGAL::sign(y0() - p.y()); + const CGAL::Sign sign_numer2 = CGAL::sign(p.x() - cv.x0()); + const CGAL::Sign sign_denom2 = CGAL::sign(cv.y0() - p.y()); // Check the case of vertical tangents. - if (sign_denom1 == ZERO) - { - if (sign_denom2 == ZERO) - { - if (_is_upper()) - { - if (cv._is_upper()) - { + if (sign_denom1 == ZERO) { + if (sign_denom2 == ZERO) { + if (_is_upper()) { + if (cv._is_upper()) { // The two circles have a vertical tangent: // The one with a larger radius is above the other. return (CGAL::compare (sqr_r(), cv.sqr_r())); } - else - { + else { // The other curve is directed downwards: return (LARGER); } } - else - { - if (cv._is_upper()) - { + else { + if (cv._is_upper()) { // The other curve is directed upwards: return (SMALLER); } - else - { + else { // The two circles have a vertical tangent: // The one with a smaller radius is above the other. return (CGAL::compare (cv.sqr_r(), sqr_r())); @@ -1676,28 +1397,21 @@ protected: // The other arc does not have a vertical tangent. return (_is_upper() ? LARGER : SMALLER); } - else if (sign_denom2 == ZERO) - { + else if (sign_denom2 == ZERO) { return (cv._is_upper() ? SMALLER : LARGER); } // Try to act according to the slope signs. - CGAL::Sign sign_slope1; - CGAL::Sign sign_slope2; + CGAL::Sign sign_slope1; + CGAL::Sign sign_slope2; - if (sign_numer1 == sign_denom1) - sign_slope1 = POSITIVE; - else if (sign_numer1 == ZERO) - sign_slope1 = ZERO; - else - sign_slope1 = NEGATIVE; + if (sign_numer1 == sign_denom1) sign_slope1 = POSITIVE; + else if (sign_numer1 == ZERO) sign_slope1 = ZERO; + else sign_slope1 = NEGATIVE; - if (sign_numer2 == sign_denom2) - sign_slope2 = POSITIVE; - else if (sign_numer2 == ZERO) - sign_slope2 = ZERO; - else - sign_slope2 = NEGATIVE; + if (sign_numer2 == sign_denom2) sign_slope2 = POSITIVE; + else if (sign_numer2 == ZERO) sign_slope2 = ZERO; + else sign_slope2 = NEGATIVE; if ((sign_slope1 == POSITIVE && sign_slope2 != POSITIVE) || (sign_slope1 == ZERO && sign_slope2 == NEGATIVE)) @@ -1718,46 +1432,38 @@ protected: else { // Actually compare the slopes. - const bool swap_res = (sign_denom1 != sign_denom2); + const bool swap_res = (sign_denom1 != sign_denom2); const CoordNT A = (cv.y0() - y0())*p.x() + (y0()*cv.x0() - cv.y0()*x0()); const CoordNT B = (cv.x0() - x0())*p.y(); slope_res = CGAL::compare (A, B); - if (slope_res != EQUAL && swap_res) - { + if (slope_res != EQUAL && swap_res) { // Swap the comparison result, if necessary: slope_res = (slope_res == SMALLER) ? LARGER : SMALLER; } } // In case the two circles have different tangent slopes at p: - if (slope_res != EQUAL) - return (slope_res); + if (slope_res != EQUAL) return (slope_res); // In this case we have a tangency point at p. - if (_is_upper()) - { - if (cv._is_upper()) - { + if (_is_upper()) { + if (cv._is_upper()) { // The circle with a larger radius is above the other. - return (CGAL::compare (sqr_r(), cv.sqr_r())); + return (CGAL::compare(sqr_r(), cv.sqr_r())); } - else - { + else { // The other curve is above our curve: return (SMALLER); } } - else - { - if (cv._is_upper()) - { + else { + if (cv._is_upper()) { // Out curve is above the other curve: return (LARGER); } - else - { + else { // The circle with a smaller radius is above the other. return (CGAL::compare (cv.sqr_r(), sqr_r())); } @@ -1771,23 +1477,18 @@ protected: /*! * Compare two line segments to the left of their intersection point. */ - Comparison_result _lines_compare_to_left (const Self& cv, - const Point_2& ) const + Comparison_result _lines_compare_to_left(const Self& cv, + const Point_2& ) const { - if (_index() != 0 && _index() == cv._index()) - return (EQUAL); + if (_index() != 0 && _index() == cv._index()) return (EQUAL); // Special treatment for vertical segments: a vertical segment is smaller // than any other non-vertical segment. - if (is_vertical()) - { - if (cv.is_vertical()) - return (EQUAL); - + if (is_vertical()) { + if (cv.is_vertical()) return (EQUAL); return (SMALLER); } - else if (cv.is_vertical()) - { + else if (cv.is_vertical()) { return (LARGER); } @@ -1796,16 +1497,14 @@ protected: return (CGAL::compare (a()/b(), cv.a()/cv.b())); } - /*! - * Compare a circular arcs (this) and a line segment (cv) to the left of + /*! Compare a circular arcs (this) and a line segment (cv) to the left of * their intersection point. */ - Comparison_result _circ_line_compare_to_left (const Self& cv, - const Point_2& p) const + Comparison_result _circ_line_compare_to_left(const Self& cv, + const Point_2& p) const { // A vertical segment lies below any other circle to the left of p: - if (cv.is_vertical()) - return (LARGER); + if (cv.is_vertical()) return (LARGER); // We have to compare the slopes of the supporting circles and the // supporting line at p, and return the swapped result: @@ -1817,8 +1516,7 @@ protected: const CGAL::Sign sign_denom1 = CGAL::sign (y0() - p.y()); // Check the case of a vertical tangent. - if (sign_denom1 == ZERO) - { + if (sign_denom1 == ZERO) { // The arc lies above any line segment if it is an upper arc, or below // any segment if it is a lower arc. return (_is_upper() ? LARGER : SMALLER); @@ -1826,12 +1524,11 @@ protected: // Compare (p.x() - x0(1)) and (A(2)/B(2)*(p.y() - y0(1)). // Note that if the denominator is negative, we have to swap the result. - const bool swap_res = (sign_denom1 == NEGATIVE); - Comparison_result slope_res = CGAL::compare (p.x() - x0(), - (p.y() - y0())*cv.a()/cv.b()); + const bool swap_res = (sign_denom1 == NEGATIVE); + Comparison_result slope_res = + CGAL::compare(p.x() - x0(), (p.y() - y0()) * cv.a() / cv.b()); - if (slope_res != EQUAL) - { + if (slope_res != EQUAL) { if (swap_res) // Swap the comparison result, if necessary: slope_res = (slope_res == SMALLER) ? LARGER : SMALLER; @@ -1849,20 +1546,16 @@ protected: /*! * Compare the two arcs to the left of their intersection point. */ - Comparison_result _circs_compare_to_left (const Self& cv, - const Point_2& p) const + Comparison_result _circs_compare_to_left(const Self& cv, + const Point_2& p) const { - if (_index() != 0 && _index() == cv._index()) - { + if (_index() != 0 && _index() == cv._index()) { // Check the case of comparing two circular arcs that originate from the // same supporting circle. Their comparison result is not EQUAL only if // one is an upper arc and the other is a lower arc. - if (_is_upper() && ! cv._is_upper()) - return (LARGER); - else if (! _is_upper() && cv._is_upper()) - return (SMALLER); - else - return (EQUAL); + if (_is_upper() && ! cv._is_upper()) return (LARGER); + else if (! _is_upper() && cv._is_upper()) return (SMALLER); + else return (EQUAL); } // We have to compare the slopes of the two supporting circles at p: @@ -1872,39 +1565,31 @@ protected: // y0(1) - p.y() y0(2) - p.y() // // Eventually, we should take the opposite result. - const CGAL::Sign sign_numer1 = CGAL::sign (p.x() - x0()); - const CGAL::Sign sign_denom1 = CGAL::sign (y0() - p.y()); - const CGAL::Sign sign_numer2 = CGAL::sign (p.x() - cv.x0()); - const CGAL::Sign sign_denom2 = CGAL::sign (cv.y0() - p.y()); + const CGAL::Sign sign_numer1 = CGAL::sign(p.x() - x0()); + const CGAL::Sign sign_denom1 = CGAL::sign(y0() - p.y()); + const CGAL::Sign sign_numer2 = CGAL::sign(p.x() - cv.x0()); + const CGAL::Sign sign_denom2 = CGAL::sign(cv.y0() - p.y()); // Check the case of vertical tangents. - if (sign_denom1 == ZERO) - { - if (sign_denom2 == ZERO) - { - if (_is_upper()) - { - if (cv._is_upper()) - { + if (sign_denom1 == ZERO) { + if (sign_denom2 == ZERO) { + if (_is_upper()) { + if (cv._is_upper()) { // The two circles have a vertical tangent: // The one with a larger radius is above the other. return (CGAL::compare (sqr_r(), cv.sqr_r())); } - else - { + else { // The other curve is directed downwards: return (LARGER); } } - else - { - if (cv._is_upper()) - { + else { + if (cv._is_upper()) { // The other curve is directed upwards: return (SMALLER); } - else - { + else { // The two circles have a vertical tangent: // The one with a smaller radius is above the other. return (CGAL::compare (cv.sqr_r(), sqr_r())); @@ -1915,28 +1600,21 @@ protected: // The other arc does not have a vertical tangent. return (_is_upper() ? LARGER : SMALLER); } - else if (sign_denom2 == ZERO) - { + else if (sign_denom2 == ZERO) { return (cv._is_upper() ? SMALLER : LARGER); } // Try to act according to the slope signs. - CGAL::Sign sign_slope1; - CGAL::Sign sign_slope2; + CGAL::Sign sign_slope1; + CGAL::Sign sign_slope2; - if (sign_numer1 == sign_denom1) - sign_slope1 = POSITIVE; - else if (sign_numer1 == ZERO) - sign_slope1 = ZERO; - else - sign_slope1 = NEGATIVE; + if (sign_numer1 == sign_denom1) sign_slope1 = POSITIVE; + else if (sign_numer1 == ZERO) sign_slope1 = ZERO; + else sign_slope1 = NEGATIVE; - if (sign_numer2 == sign_denom2) - sign_slope2 = POSITIVE; - else if (sign_numer2 == ZERO) - sign_slope2 = ZERO; - else - sign_slope2 = NEGATIVE; + if (sign_numer2 == sign_denom2) sign_slope2 = POSITIVE; + else if (sign_numer2 == ZERO) sign_slope2 = ZERO; + else sign_slope2 = NEGATIVE; if ((sign_slope1 == POSITIVE && sign_slope2 != POSITIVE) || (sign_slope1 == ZERO && sign_slope2 == NEGATIVE)) @@ -1954,17 +1632,15 @@ protected: // Special case were both circles have a horizontal tangent: slope_res = EQUAL; } - else - { + else { // Actually compare the slopes. - const bool swap_res = (sign_denom1 != sign_denom2); + const bool swap_res = (sign_denom1 != sign_denom2); const CoordNT A = (cv.y0() - y0())*p.x() + (y0()*cv.x0() - cv.y0()*x0()); const CoordNT B = (cv.x0() - x0())*p.y(); - slope_res = CGAL::compare (A, B); + slope_res = CGAL::compare(A, B); - if (slope_res != EQUAL && swap_res) - { + if (slope_res != EQUAL && swap_res) { // Swap the comparison result, if necessary: slope_res = (slope_res == SMALLER) ? LARGER : SMALLER; } @@ -1973,34 +1649,27 @@ protected: // In case the two circles have different tangent slopes at p, return // the opposite of the slope result (since the slope result is the // comparison result to the right of the intersection point): - if (slope_res != EQUAL) - return ((slope_res == SMALLER) ? LARGER : SMALLER); + if (slope_res != EQUAL) return ((slope_res == SMALLER) ? LARGER : SMALLER); // In this case we have a tangency point at p. - if (_is_upper()) - { - if (cv._is_upper()) - { + if (_is_upper()) { + if (cv._is_upper()) { // The circle with a larger radius is above the other. - return (CGAL::compare (sqr_r(), cv.sqr_r())); + return (CGAL::compare(sqr_r(), cv.sqr_r())); } - else - { + else { // The other curve is above our curve: return (SMALLER); } } - else - { - if (cv._is_upper()) - { + else { + if (cv._is_upper()) { // Out curve is above the other curve: return (LARGER); } - else - { + else { // The circle with a smaller radius is above the other. - return (CGAL::compare (cv.sqr_r(), sqr_r())); + return (CGAL::compare(cv.sqr_r(), sqr_r())); } } } @@ -2009,11 +1678,10 @@ protected: /// \name Auxiliary functions for computing intersections. //@{ - /*! - * Compute the intersections between two line segments. + /*! Compute the intersections between two line segments. */ - void _lines_intersect (const Self& cv, - Intersection_list& inter_list) const + void _lines_intersect(const Self& cv, + Intersection_list& inter_list) const { // The intersection of the lines: // a1*x + b1*y + c1 = 0 and a2*x + b2*y + c2 = 0 , @@ -2023,53 +1691,47 @@ protected: // ( --------------- , --------------- ) // a1*b2 - b1*a2 a1*b2 - b1*a2 // - unsigned int mult = 1; - const NT denom = a()*cv.b() - b()*cv.a(); + unsigned int mult = 1; + const NT denom = a()*cv.b() - b()*cv.a(); // Make sure the supporting lines are not parallel. - if (CGAL::sign(denom) == ZERO) - return; + if (CGAL::sign(denom) == ZERO) return; - const NT x = (b()*cv.c() - c()*cv.b()) / denom; - const NT y = (c()*cv.a() - a()*cv.c()) / denom; - Point_2 p (x, y); + const NT x = (b()*cv.c() - c()*cv.b()) / denom; + const NT y = (c()*cv.a() - a()*cv.c()) / denom; + Point_2 p (x, y); - inter_list.push_back (Intersection_point_2 (p, mult)); - return; + inter_list.push_back(Intersection_point(p, mult)); } - /*! - * Compute the intersections between the supporting circle of (*this) and + /*! Compute the intersections between the supporting circle of (*this) and * the supporting line of the segement cv. */ - void _circ_line_intersect (const Self& cv, - Intersection_list& inter_list) const + void _circ_line_intersect(const Self& cv, + Intersection_list& inter_list) const { - Point_2 p; - unsigned int mult; + Point_2 p; + unsigned int mult; // First check the special cases of vertical and horizontal lines. - if (cv.is_vertical()) - { + if (cv.is_vertical()) { // The equation of the vertical line is x = -c / a. // The y-coordinates of the intersection points are: // y = y0 +/- sqrt(r^2 - (x - x0)^2) // - const NT vx = -cv.c() / cv.a(); - const NT vdisc = sqr_r() - CGAL::square (vx - x0()); + const NT vx = -cv.c() / cv.a(); + const NT vdisc = sqr_r() - CGAL::square (vx - x0()); CGAL::Sign sign_vdisc = CGAL::sign (vdisc); - if (sign_vdisc == NEGATIVE) - { + if (sign_vdisc == NEGATIVE) { // The circle and the vertical line do not intersect. return; } - else if (sign_vdisc == ZERO) - { + else if (sign_vdisc == ZERO) { // A single tangency point, given by: mult = 2; p = Point_2 (vx, y0()); - inter_list.push_back (Intersection_point_2 (p, mult)); + inter_list.push_back(Intersection_point(p, mult)); return; } @@ -2077,37 +1739,30 @@ protected: // Compute the two intersection points: mult = 1; - p = Point_2 (CoordNT (vx), - CoordNT (y0(), NT(-1), vdisc)); - inter_list.push_back (Intersection_point_2 (p, mult)); + p = Point_2(CoordNT (vx), CoordNT (y0(), NT(-1), vdisc)); + inter_list.push_back (Intersection_point(p, mult)); - p = Point_2 (CoordNT (vx), - CoordNT (y0(), NT(1), vdisc)); - inter_list.push_back (Intersection_point_2 (p, mult)); + p = Point_2(CoordNT (vx), CoordNT (y0(), NT(1), vdisc)); + inter_list.push_back(Intersection_point(p, mult)); return; } - else if (CGAL::sign (cv.a()) == ZERO) - { + else if (CGAL::sign (cv.a()) == ZERO) { // The equation of the horizontal line is y = -c / b. // The y-coordinates of the intersection points are: // x = x0 +/- sqrt(r^2 - (y - y0)^2) // - const NT hy = -cv.c() / cv.b(); - const NT hdisc = sqr_r() - CGAL::square (hy - y0()); + const NT hy = -cv.c() / cv.b(); + const NT hdisc = sqr_r() - CGAL::square (hy - y0()); CGAL::Sign sign_hdisc = CGAL::sign (hdisc); - if (sign_hdisc == NEGATIVE) - { - // The circle and the vertical line do not intersect. - return; - } - else if (sign_hdisc == ZERO) - { + // The circle and the vertical line do not intersect. + if (sign_hdisc == NEGATIVE) return; + else if (sign_hdisc == ZERO) { // A single tangency point, given by: mult = 2; - p = Point_2 (x0(), hy); - inter_list.push_back (Intersection_point_2 (p, mult)); + p = Point_2(x0(), hy); + inter_list.push_back(Intersection_point (p, mult)); return; } @@ -2115,287 +1770,246 @@ protected: // Compute the two intersection points: mult = 1; - p = Point_2 (CoordNT (x0(), NT(-1), hdisc), - CoordNT (hy)); - inter_list.push_back (Intersection_point_2 (p, mult)); + p = Point_2(CoordNT(x0(), NT(-1), hdisc), CoordNT (hy)); + inter_list.push_back(Intersection_point (p, mult)); - p = Point_2 (CoordNT (x0(), NT(1), hdisc), - CoordNT (hy)); - inter_list.push_back (Intersection_point_2 (p, mult)); + p = Point_2(CoordNT(x0(), NT(1), hdisc), CoordNT(hy)); + inter_list.push_back(Intersection_point (p, mult)); return; } // Compute the squared distance between the line and the circle center, // inducing the discriminant of the quadratic equations we have to solve. - const NT line_factor = CGAL::square(cv.a()) + CGAL::square(cv.b()); - const NT disc = line_factor*sqr_r() - - CGAL::square(cv.a()*x0() + cv.b()*y0() + cv.c()); + const NT line_factor = CGAL::square(cv.a()) + CGAL::square(cv.b()); + const NT disc = + line_factor*sqr_r() - CGAL::square(cv.a()*x0() + cv.b()*y0() + cv.c()); CGAL::Sign sign_disc = CGAL::sign (disc); - if (sign_disc == NEGATIVE) - { - // The circle and the line do not intersect: - return; - } + // The circle and the line do not intersect: + if (sign_disc == NEGATIVE) return; // Compare the square-free part of the solution: - const NT aux = cv.b()*x0() - cv.a()*y0(); - const NT x_base = (aux*cv.b() - cv.a()*cv.c()) / line_factor; - const NT y_base = (-aux*cv.a() - cv.b()*cv.c()) / line_factor; + const NT aux = cv.b()*x0() - cv.a()*y0(); + const NT x_base = (aux*cv.b() - cv.a()*cv.c()) / line_factor; + const NT y_base = (-aux*cv.a() - cv.b()*cv.c()) / line_factor; - if (sign_disc == ZERO) - { + if (sign_disc == ZERO) { // A single tangency point, given by: mult = 2; - p = Point_2 (x_base, y_base); - inter_list.push_back (Intersection_point_2 (p, mult)); + p = Point_2(x_base, y_base); + inter_list.push_back(Intersection_point(p, mult)); return; } // We have two intersection points, whose coordinates are one-root numbers. - bool minus_root_first = (CGAL::sign(cv.b()) == POSITIVE); - const NT x_root_coeff = cv.b() / line_factor; - const NT y_root_coeff = cv.a() / line_factor; + bool minus_root_first = (CGAL::sign(cv.b()) == POSITIVE); + const NT x_root_coeff = cv.b() / line_factor; + const NT y_root_coeff = cv.a() / line_factor; mult = 1; - if (minus_root_first) - { - p = Point_2 (CoordNT (x_base, -x_root_coeff, disc), - CoordNT (y_base, y_root_coeff, disc)); - inter_list.push_back (Intersection_point_2 (p, mult)); + if (minus_root_first) { + p = Point_2(CoordNT(x_base, -x_root_coeff, disc), + CoordNT(y_base, y_root_coeff, disc)); + inter_list.push_back(Intersection_point (p, mult)); - p = Point_2 (CoordNT (x_base, x_root_coeff, disc), - CoordNT (y_base, -y_root_coeff, disc)); - inter_list.push_back (Intersection_point_2 (p, mult)); + p = Point_2(CoordNT(x_base, x_root_coeff, disc), + CoordNT(y_base, -y_root_coeff, disc)); + inter_list.push_back(Intersection_point(p, mult)); } - else - { - p = Point_2 (CoordNT (x_base, x_root_coeff, disc), - CoordNT (y_base, -y_root_coeff, disc)); - inter_list.push_back (Intersection_point_2 (p, mult)); + else { + p = Point_2(CoordNT(x_base, x_root_coeff, disc), + CoordNT(y_base, -y_root_coeff, disc)); + inter_list.push_back(Intersection_point(p, mult)); - p = Point_2 (CoordNT (x_base, -x_root_coeff, disc), - CoordNT (y_base, y_root_coeff, disc)); - inter_list.push_back (Intersection_point_2 (p, mult)); + p = Point_2(CoordNT(x_base, -x_root_coeff, disc), + CoordNT(y_base, y_root_coeff, disc)); + inter_list.push_back(Intersection_point(p, mult)); } - - return; } - /*! - * Compute the intersections between two circles. + /*! Compute the intersections between two circles. */ - void _circs_intersect (const Self& cv, - Intersection_list& inter_list) const + void _circs_intersect(const Self& cv, Intersection_list& inter_list) const { - Point_2 p; - unsigned int mult; + Point_2 p; + unsigned int mult; // Compute the squared distance between the circle centers, inducing the // discriminant of the quadratic equations we have to solve. - const NT diff_x = cv.x0() - x0(); - const NT diff_y = cv.y0() - y0(); - const NT sqr_dist = CGAL::square(diff_x) + CGAL::square(diff_y); - const NT diff_sqr_rad = sqr_r() - cv.sqr_r(); - const NT disc = 2*sqr_dist*(sqr_r() + cv.sqr_r()) - - (CGAL::square(diff_sqr_rad) + CGAL::square(sqr_dist)); + const NT diff_x = cv.x0() - x0(); + const NT diff_y = cv.y0() - y0(); + const NT sqr_dist = CGAL::square(diff_x) + CGAL::square(diff_y); + const NT diff_sqr_rad = sqr_r() - cv.sqr_r(); + const NT disc = 2 * sqr_dist * (sqr_r() + cv.sqr_r()) - + (CGAL::square(diff_sqr_rad) + CGAL::square(sqr_dist)); CGAL::Sign sign_disc = CGAL::sign (disc); - if (sign_disc == NEGATIVE) - { - // The two circles do not intersect. - return; - } + // The two circles do not intersect. + if (sign_disc == NEGATIVE) return; // Compare the square-free part of the solution: - const NT x_base = ((x0() + cv.x0()) + diff_x*diff_sqr_rad/sqr_dist) / 2; - const NT y_base = ((y0() + cv.y0()) + diff_y*diff_sqr_rad/sqr_dist) / 2; + const NT x_base = ((x0() + cv.x0()) + diff_x * diff_sqr_rad / sqr_dist) / 2; + const NT y_base = ((y0() + cv.y0()) + diff_y * diff_sqr_rad / sqr_dist) / 2; - if (sign_disc == ZERO) - { + if (sign_disc == ZERO) { // A single tangency point, given by: mult = 2; - p = Point_2 (x_base, y_base); - inter_list.push_back (Intersection_point_2 (p, mult)); - + p = Point_2(x_base, y_base); + inter_list.push_back(Intersection_point(p, mult)); return; } // We have two intersection points, whose coordinates are one-root numbers. CGAL::Sign sign_diff_y = CGAL::sign (diff_y); - bool minus_root_first; + bool minus_root_first; if (sign_diff_y == ZERO) minus_root_first = (CGAL::sign (diff_x) == NEGATIVE); else minus_root_first = (sign_diff_y == POSITIVE); - const NT x_root_coeff = diff_y / (2 * sqr_dist); - const NT y_root_coeff = diff_x / (2 * sqr_dist); + const NT x_root_coeff = diff_y / (2 * sqr_dist); + const NT y_root_coeff = diff_x / (2 * sqr_dist); mult = 1; - if (minus_root_first) - { - p = Point_2 (CoordNT (x_base, -x_root_coeff, disc), - CoordNT (y_base, y_root_coeff, disc)); - inter_list.push_back (Intersection_point_2 (p, mult)); + if (minus_root_first) { + p = Point_2(CoordNT(x_base, -x_root_coeff, disc), + CoordNT(y_base, y_root_coeff, disc)); + inter_list.push_back(Intersection_point (p, mult)); - p = Point_2 (CoordNT (x_base, x_root_coeff, disc), - CoordNT (y_base, -y_root_coeff, disc)); - inter_list.push_back (Intersection_point_2 (p, mult)); + p = Point_2(CoordNT(x_base, x_root_coeff, disc), + CoordNT(y_base, -y_root_coeff, disc)); + inter_list.push_back(Intersection_point (p, mult)); } - else - { - p = Point_2 (CoordNT (x_base, x_root_coeff, disc), - CoordNT (y_base, -y_root_coeff, disc)); - inter_list.push_back (Intersection_point_2 (p, mult)); + else { + p = Point_2(CoordNT(x_base, x_root_coeff, disc), + CoordNT(y_base, -y_root_coeff, disc)); + inter_list.push_back(Intersection_point (p, mult)); - p = Point_2 (CoordNT (x_base, -x_root_coeff, disc), - CoordNT (y_base, y_root_coeff, disc)); - inter_list.push_back (Intersection_point_2 (p, mult)); + p = Point_2(CoordNT(x_base, -x_root_coeff, disc), + CoordNT(y_base, y_root_coeff, disc)); + inter_list.push_back(Intersection_point(p, mult)); } - - return; } - /*! - * Check if the given point lies on the arc. + /*! Check if the given point lies on the arc. * \pre p lies on the supporting curve. */ - bool _is_between_endpoints (const Point_2& p) const + bool _is_between_endpoints(const Point_2& p) const { - if (is_linear()) - { - if (is_vertical()) - { + if (is_linear()) { + if (is_vertical()) { // Check if the point is in the y-range of the arc. // Note that left() is the lower endpoint and right() is the upper // endpoint of the segment in this case. - Comparison_result res = CGAL::compare (p.y(), left().y()); + Comparison_result res = CGAL::compare(p.y(), left().y()); - if (res == SMALLER) - return (false); - else if (res == EQUAL) - return (true); + if (res == SMALLER) return false; + else if (res == EQUAL) return true; - return (CGAL::compare (p.y(), right().y()) != LARGER); + return (CGAL::compare(p.y(), right().y()) != LARGER); } // For non-vertical segments, it is sufficient to check if the point // is in the x-range of the arc. - return (this->is_in_x_range (p)); + return (this->is_in_x_range(p)); } // The supporting curve is a circle: // Check whether p lies on the upper or on the lower part of the circle. - Comparison_result c_res = CGAL::compare (p.y(), y0()); + Comparison_result c_res = CGAL::compare(p.y(), y0()); - if ((_is_upper() && c_res == SMALLER) || - (! _is_upper() && c_res == LARGER)) + if ((_is_upper() && c_res == SMALLER) || (! _is_upper() && c_res == LARGER)) { // The point lies on the other half of the circle: - return (false); + return false; } // Check if the point is in the x-range of the arc. - return (this->is_in_x_range (p)); + return (this->is_in_x_range(p)); } - /*! - * Check if the given point lies in the interior of the arc. + /*! Check whether the given point lies in the interior of the arc. * \pre p lies on the supporting curve. */ - bool _is_strictly_between_endpoints (const Point_2& p) const + bool _is_strictly_between_endpoints(const Point_2& p) const { - if (p.equals (_source) || p.equals (_target)) - return (false); - - return (_is_between_endpoints (p)); + if (p.equals (m_source) || p.equals (m_target)) return false; + return (_is_between_endpoints(p)); } - /*! - * Compute the overlap with a given arc having the same supporting curve. + /*! Compute the overlap with a given arc having the same supporting curve. * \param cv The given arc. * \param overlap Output: The overlapping arc (if any). * \return Whether we found an overlap. */ - bool _compute_overlap (const Self& cv, Self& overlap) const + bool _compute_overlap(const Self& cv, Self& overlap) const { // Check if the two arcs are identical. - if (is_linear()) - { + if (is_linear()) { // In case of line segments we can swap the source and target: - if (((_source.equals (cv._source) && _target.equals (cv._target)) || - (_source.equals (cv._target) && _target.equals (cv._source)))) + if (((m_source.equals(cv.m_source) && m_target.equals(cv.m_target)) || + (m_source.equals(cv.m_target) && m_target.equals(cv.m_source)))) { overlap = cv; - return (true); + return true; } } - else - { + else { if ((orientation() == cv.orientation() && - _source.equals (cv._source) && _target.equals (cv._target)) || + m_source.equals(cv.m_source) && m_target.equals(cv.m_target)) || (orientation() != cv.orientation() && - _source.equals (cv._target) && _target.equals (cv._source))) + m_source.equals(cv.m_target) && m_target.equals(cv.m_source))) { overlap = cv; - return (true); + return true; } } // Check for other overlaps: - if (_is_strictly_between_endpoints (cv.left())) - { - if (_is_strictly_between_endpoints (cv.right())) - { + if (_is_strictly_between_endpoints(cv.left())) { + if (_is_strictly_between_endpoints(cv.right())) { // Case 1 - *this: +-----------> // cv: +=====> overlap = cv; - return (true); + return true; } - else - { + else { // Case 2 - *this: +-----------> // cv: +=====> overlap = *this; - if (overlap.is_directed_right()) - overlap._source = cv.left(); - else - overlap._target = cv.left(); + if (overlap.is_directed_right()) overlap.m_source = cv.left(); + else overlap.m_target = cv.left(); - return (true); + return true; } } - else if (_is_strictly_between_endpoints (cv.right())) - { + else if (_is_strictly_between_endpoints(cv.right())) { // Case 3 - *this: +-----------> // cv: +=====> overlap = *this; - if (overlap.is_directed_right()) - overlap._target = cv.right(); - else - overlap._source = cv.right(); + if (overlap.is_directed_right()) overlap.m_target = cv.right(); + else overlap.m_source = cv.right(); - return (true); + return true; } - else if (cv._is_between_endpoints (_source) && - cv._is_between_endpoints (_target) && - (cv._is_strictly_between_endpoints (_source) || - cv._is_strictly_between_endpoints (_target))) + else if (cv._is_between_endpoints(m_source) && + cv._is_between_endpoints(m_target) && + (cv._is_strictly_between_endpoints(m_source) || + cv._is_strictly_between_endpoints(m_target))) { // Case 4 - *this: +-----------> // cv: +================> overlap = *this; - return (true); + return true; } // If we reached here, there are no overlaps: - return (false); + return false; } public: @@ -2407,61 +2021,49 @@ protected: const double x_right = CGAL::to_double(this->target().x()); const double y_right = CGAL::to_double(this->target().y()); - if(this->is_linear()) - { - *oi = std::make_pair(x_left, y_left); - ++oi; - - *oi = std::make_pair(x_right, y_right); - ++oi; + if (this->is_linear()) { + *oi++ = std::make_pair(x_left, y_left); + *oi++ = std::make_pair(x_right, y_right); return; } // Otherwise, sample (n - 1) equally-spaced points in between. - const double app_xcenter = CGAL::to_double (this->_first); - const double app_ycenter = CGAL::to_double (this->_second); - const double app_sqr_rad = CGAL::to_double (this->_third); + const double app_xcenter = CGAL::to_double(this->m_first); + const double app_ycenter = CGAL::to_double(this->m_second); + const double app_sqr_rad = CGAL::to_double(this->m_third); - const double x_jump = (x_right - x_left) / n; - double x, y; - double disc; - unsigned int i; + const double x_jump = (x_right - x_left) / n; + double x, y; + double disc; + unsigned int i; const bool is_up = this->_is_upper(); - *oi = std::make_pair (x_left, y_left); // The left point. - ++oi; - for (i = 1; i < n; i++) - { + *oi++ = std::make_pair (x_left, y_left); // The left point. + for (i = 1; i < n; ++i) { x = x_left + x_jump*i; disc = app_sqr_rad - CGAL::square(x - app_xcenter); if (disc < 0) disc = 0; - if(is_up) - y = app_ycenter + std::sqrt(disc); - else - y = app_ycenter - std::sqrt(disc); + if(is_up) y = app_ycenter + std::sqrt(disc); + else y = app_ycenter - std::sqrt(disc); - *oi = std::make_pair(x, y); - ++oi; + *oi++ = std::make_pair(x, y); } - *oi = std::make_pair(x_right, y_right); // The right point. - ++oi; + *oi++ = std::make_pair(x_right, y_right); // The right point. } - /*! - * Trim the arc given its new endpoints. + /*! Trim the arc given its new endpoints. * \param ps The new source point. * \param pt The new target point. * \return The new trimmed arc. * \pre Both ps and pt lies on the arc and must conform with the current * direction of the arc. */ - Self trim (const Point_2& ps, - const Point_2& pt) const + Self trim(const Point_2& ps, const Point_2& pt) const { - Self arc = *this; + Self arc = *this; - arc._source = ps; - arc._target = pt; + arc.m_source = ps; + arc.m_target = pt; return arc; } @@ -2469,13 +2071,12 @@ protected: //@} }; -/*! - * Exporter for circular arcs (or line segments). +/*! Exporter for circular arcs (or line segments). */ template std::ostream& -operator<< (std::ostream& os, - const _X_monotone_circle_segment_2 & arc) +operator<<(std::ostream& os, + const _X_monotone_circle_segment_2 & arc) { if (! arc.is_linear()) os << "(" << arc.supporting_circle() << ") "; diff --git a/Arrangement_on_surface_2/include/CGAL/Arr_geometry_traits/Conic_x_monotone_arc_2.h b/Arrangement_on_surface_2/include/CGAL/Arr_geometry_traits/Conic_x_monotone_arc_2.h index 6fc3ecce08c..b58ff269944 100644 --- a/Arrangement_on_surface_2/include/CGAL/Arr_geometry_traits/Conic_x_monotone_arc_2.h +++ b/Arrangement_on_surface_2/include/CGAL/Arr_geometry_traits/Conic_x_monotone_arc_2.h @@ -7,15 +7,13 @@ // $Id$ // SPDX-License-Identifier: GPL-3.0-or-later OR LicenseRef-Commercial // -// -// Author(s) : Ron Wein +// Author(s): Ron Wein #ifndef CGAL_CONIC_X_MONOTONE_ARC_2_H #define CGAL_CONIC_X_MONOTONE_ARC_2_H #include - /*! \file * Header file for the _Conic_x_monotone_arc_2 class. */ @@ -32,9 +30,8 @@ namespace CGAL { * The class is templated by a representation of a general bounded conic arc. */ -template -class _Conic_x_monotone_arc_2 : private Conic_arc_ -{ +template +class _Conic_x_monotone_arc_2 : private Conic_arc_ { public: typedef Conic_arc_ Conic_arc_2; @@ -49,8 +46,8 @@ public: // Type definition for the intersection points mapping. typedef typename Conic_point_2::Conic_id Conic_id; typedef std::pair Conic_pair; - typedef std::pair Intersection_point_2; - typedef std::list Intersection_list; + typedef std::pair Intersection_point; + typedef std::list Intersection_list; using Conic_arc_2::_sign_of_extra_data; using Conic_arc_2::_is_between_endpoints; @@ -59,13 +56,12 @@ public: /*! * \struct Less functor for Conic_pair. */ - struct Less_conic_pair - { - bool operator() (const Conic_pair& cp1, const Conic_pair& cp2) const + struct Less_conic_pair { + bool operator()(const Conic_pair& cp1, const Conic_pair& cp2) const { // Compare the pairs of IDs lexicographically. - return (cp1.first < cp2.first || - (cp1.first == cp2.first && cp1.second < cp2.second)); + return ((cp1.first < cp2.first) || + ((cp1.first == cp2.first) && (cp1.second < cp2.second))); } }; @@ -85,8 +81,7 @@ protected: // Bit masks for the _info field (the two least significant bits are already // used by the base class). - enum - { + enum { IS_VERTICAL_SEGMENT = 4, IS_DIRECTED_RIGHT = 8, DEGREE_1 = 16, @@ -99,14 +94,14 @@ protected: IS_SPECIAL_SEGMENT = 512 }; - Algebraic alg_r; // The coefficients of the supporting conic curve: - Algebraic alg_s; // - Algebraic alg_t; // r*x^2 + s*y^2 + t*xy + u*x + v*y +w = 0 , - Algebraic alg_u; // - Algebraic alg_v; // converted to algebraic numbers. - Algebraic alg_w; // + Algebraic alg_r; // The coefficients of the supporting conic curve: + Algebraic alg_s; // + Algebraic alg_t; // r*x^2 + s*y^2 + t*xy + u*x + v*y +w = 0 , + Algebraic alg_u; // + Algebraic alg_v; // converted to algebraic numbers. + Algebraic alg_w; // - Conic_id _id; // The ID number of the supporting conic curve. + Conic_id _id; // The ID number of the supporting conic curve. public: @@ -117,68 +112,62 @@ public: * Default constructor. */ _Conic_x_monotone_arc_2 () : - Base (), - _id () + Base(), + _id() {} /*! * Copy constructor. * \param arc The copied arc. */ - _Conic_x_monotone_arc_2 (const Self& arc) : - Base (arc), - alg_r (arc.alg_r), - alg_s (arc.alg_s), - alg_t (arc.alg_t), - alg_u (arc.alg_u), - alg_v (arc.alg_v), - alg_w (arc.alg_w), - _id (arc._id) + _Conic_x_monotone_arc_2(const Self& arc) : + Base(arc), + alg_r(arc.alg_r), + alg_s(arc.alg_s), + alg_t(arc.alg_t), + alg_u(arc.alg_u), + alg_v(arc.alg_v), + alg_w(arc.alg_w), + _id(arc._id) {} - /*! - * Construct an x-monotone arc from a conic arc. + /*! Construct an x-monotone arc from a conic arc. * \param arc The given (base) arc. * \pre The given arc is x-monotone. */ - _Conic_x_monotone_arc_2 (const Base& arc) : - Base (arc), - _id () + _Conic_x_monotone_arc_2(const Base& arc) : + Base(arc), + _id() { - CGAL_precondition (arc.is_valid() && arc.is_x_monotone()); - + CGAL_precondition(arc.is_valid() && arc.is_x_monotone()); _set (); } - /*! - * Construct an x-monotone arc from a conic arc. + /*! Construct an x-monotone arc from a conic arc. * \param arc The given (base) arc. * \param id The ID of the base arc. */ - _Conic_x_monotone_arc_2 (const Base& arc, - const Conic_id& id) : - Base (arc), - _id (id) + _Conic_x_monotone_arc_2(const Base& arc, const Conic_id& id) : + Base(arc), + _id(id) { - CGAL_precondition (arc.is_valid() && id.is_valid()); - + CGAL_precondition(arc.is_valid() && id.is_valid()); _set (); } - /*! - * Construct an x-monotone sub-arc from a conic arc. + /*! Construct an x-monotone sub-arc from a conic arc. * \param arc The given (base) arc. * \param source The source point. * \param target The target point. * \param id The ID of the base arc. */ - _Conic_x_monotone_arc_2 (const Base& arc, - const Point_2& source, const Point_2& target, - const Conic_id& id) : - Base (arc), - _id (id) + _Conic_x_monotone_arc_2(const Base& arc, + const Point_2& source, const Point_2& target, + const Conic_id& id) : + Base(arc), + _id(id) { - CGAL_precondition (arc.is_valid() && id.is_valid()); + CGAL_precondition(arc.is_valid() && id.is_valid()); // Set the two endpoints. this->_source = source; @@ -193,7 +182,7 @@ public: * \param source The source point. * \param target The target point. */ - _Conic_x_monotone_arc_2 (const Point_2& source, const Point_2& target) : + _Conic_x_monotone_arc_2(const Point_2& source, const Point_2& target) : Base() { // Set the basic properties and clear the _info bits. @@ -204,22 +193,21 @@ public: // Check if the arc is directed right (the target is lexicographically // greater than the source point), or to the left. - Alg_kernel ker; - Comparison_result dir_res = ker.compare_xy_2_object() (this->_source, - this->_target); + Alg_kernel ker; + Comparison_result dir_res = + ker.compare_xy_2_object()(this->_source, this->_target); CGAL_precondition (dir_res != EQUAL); - if (dir_res == EQUAL) - // Invalid arc: - return; + // Invalid arc: + if (dir_res == EQUAL) return; this->_info = (Conic_arc_2::IS_VALID | DEGREE_1); if (dir_res == SMALLER) this->_info = (this->_info | IS_DIRECTED_RIGHT); // Compose the equation of the underlying line. - const Algebraic x1 = source.x(), y1 = source.y(); - const Algebraic x2 = target.x(), y2 = target.y(); + const Algebraic x1 = source.x(), y1 = source.y(); + const Algebraic x2 = target.x(), y2 = target.y(); // The supporting line is A*x + B*y + C = 0, where: // @@ -249,18 +237,18 @@ public: * \param source The source point. * \param target The target point. */ - _Conic_x_monotone_arc_2 (const Algebraic& a, - const Algebraic& b, - const Algebraic& c, - const Point_2& source, const Point_2& target) : + _Conic_x_monotone_arc_2(const Algebraic& a, + const Algebraic& b, + const Algebraic& c, + const Point_2& source, const Point_2& target) : Base() { // Make sure the two endpoints lie on the supporting line. - CGAL_precondition (CGAL::sign (a * source.x() + - b * source.y() + c) == CGAL::ZERO); + CGAL_precondition(CGAL::sign(a * source.x() + + b * source.y() + c) == CGAL::ZERO); - CGAL_precondition (CGAL::sign (a * target.x() + - b * target.y() + c) == CGAL::ZERO); + CGAL_precondition(CGAL::sign(a * target.x() + + b * target.y() + c) == CGAL::ZERO); // Set the basic properties and clear the _info bits. this->_source = source; @@ -270,23 +258,20 @@ public: // Check if the arc is directed right (the target is lexicographically // greater than the source point), or to the left. - Alg_kernel ker; - Comparison_result res = ker.compare_x_2_object() (this->_source, - this->_target); + Alg_kernel ker; + Comparison_result res = + ker.compare_x_2_object()(this->_source, this->_target); this->_info = (Conic_arc_2::IS_VALID | DEGREE_1); - if (res == EQUAL) - { + if (res == EQUAL) { // Mark that the segment is vertical. this->_info = (this->_info | IS_VERTICAL_SEGMENT); // Compare the endpoints lexicographically. - res = ker.compare_y_2_object() (this->_source, - this->_target); + res = ker.compare_y_2_object()(this->_source, this->_target); CGAL_precondition (res != EQUAL); - if (res == EQUAL) - { + if (res == EQUAL) { // Invalid arc: this->_info = 0; return; @@ -313,12 +298,11 @@ public: * Assignment operator. * \param arc The copied arc. */ - const Self& operator= (const Self& arc) + const Self& operator=(const Self& arc) { CGAL_precondition (arc.is_valid()); - if (this == &arc) - return (*this); + if (this == &arc) return (*this); // Copy the base arc. Base::operator= (arc); @@ -343,49 +327,35 @@ public: /*! * Get the coefficients of the underlying conic. */ - const Integer& r () const {return (this->_r);} - const Integer& s () const {return (this->_s);} - const Integer& t () const {return (this->_t);} - const Integer& u () const {return (this->_u);} - const Integer& v () const {return (this->_v);} - const Integer& w () const {return (this->_w);} + const Integer& r() const { return (this->_r); } + const Integer& s() const { return (this->_s); } + const Integer& t() const { return (this->_t); } + const Integer& u() const { return (this->_u); } + const Integer& v() const { return (this->_v); } + const Integer& w() const { return (this->_w); } /*! * Get the arc's source. * \return The source point. */ - const Conic_point_2& source () const - { - return (this->_source); - } + const Conic_point_2& source() const { return (this->_source); } - /*! - * Get the arc's target. + /*! Get the arc's target. * \return The target point. */ - const Conic_point_2& target () const - { - return (this->_target); - } + const Conic_point_2& target() const { return (this->_target); } - /*! - * Get the orientation of the arc. + /*! Get the orientation of the arc. * \return The orientation. */ - Orientation orientation () const - { - return (this->_orient); - } + Orientation orientation() const { return (this->_orient); } - /*! - * Get the left endpoint of the arc. + /*! Get the left endpoint of the arc. */ const Conic_point_2& left () const { - if ((this->_info & IS_DIRECTED_RIGHT) != 0) - return (this->_source); - else - return (this->_target); + if ((this->_info & IS_DIRECTED_RIGHT) != 0) return (this->_source); + else return (this->_target); } /*! @@ -393,28 +363,21 @@ public: */ const Conic_point_2& right () const { - if ((this->_info & IS_DIRECTED_RIGHT) != 0) - return (this->_target); - else - return (this->_source); + if ((this->_info & IS_DIRECTED_RIGHT) != 0) return (this->_target); + else return (this->_source); } /*! * Return true iff the conic arc is directed right iexicographically. */ bool is_directed_right() const - { - return ((this->_info & IS_DIRECTED_RIGHT) != 0); - } + { return ((this->_info & IS_DIRECTED_RIGHT) != 0); } /*! * Get a bounding box for the conic arc. * \return The bounding box. */ - Bbox_2 bbox () const - { - return (Base::bbox()); - } + Bbox_2 bbox() const { return (Base::bbox()); } //@} /// \name Predicates. @@ -433,23 +396,20 @@ public: * \param p The qury point. * \param (true) if p lies on the arc; (false) otherwise. */ - bool contains_point (const Conic_point_2& p) const + bool contains_point(const Conic_point_2& p) const { // First check if p lies on the supporting conic. We first check whether // it is one of p's generating conic curves. bool p_on_conic = false; - if (p.is_generating_conic (_id)) - { + if (p.is_generating_conic(_id)) { p_on_conic = true; } - else - { + else { // Check whether p satisfies the supporting conic equation. - p_on_conic = _is_on_supporting_conic (p.x(), p.y()); + p_on_conic = _is_on_supporting_conic(p.x(), p.y()); - if (p_on_conic) - { + if (p_on_conic) { // As p lies on the supporting conic of our arc, add its ID to // the list of generating conics for p. Conic_point_2& p_non_const = const_cast (p); @@ -483,17 +443,16 @@ public: Alg_kernel ker; ); - CGAL_precondition (ker.compare_x_2_object() (p, left()) != SMALLER && - ker.compare_x_2_object() (p, right()) != LARGER); + CGAL_precondition(ker.compare_x_2_object() (p, left()) != SMALLER && + ker.compare_x_2_object() (p, right()) != LARGER); - if (_is_special_segment()) - { + if (_is_special_segment()) { // In case of a special segment, the equation of the supported line // (a*x + b*y + c) = 0 is stored with the extra data field, and we // simply have: - Algebraic _y = -(this->_extra_data_P->a*p.x() + - this->_extra_data_P->c) / - this->_extra_data_P->b; + Algebraic _y = -(this->_extra_data_P->a*p.x() + + this->_extra_data_P->c) / + this->_extra_data_P->b; // Return the computed point. return (Point_2 (p.x(), _y)); @@ -501,18 +460,16 @@ public: // Compute the y-coordinate according to the degree of the supporting // conic curve. - Nt_traits nt_traits; - Algebraic y; + Nt_traits nt_traits; + Algebraic y; - if ((this->_info & DEGREE_MASK) == DEGREE_1) - { + if ((this->_info & DEGREE_MASK) == DEGREE_1) { // In case of a linear curve, the y-coordinate is a simple linear // expression of x(p) (note that v is not 0 as the arc is not vertical): // y = -(u*x(p) + w) / v y = -(alg_u*p.x() + alg_w) / alg_v; } - else if (this->_orient == COLLINEAR) - { + else if (this->_orient == COLLINEAR) { CGAL_assertion (this->_extra_data_P != nullptr); // In this case the equation of the supporting line is given by the @@ -520,26 +477,23 @@ public: y = -(this->_extra_data_P->a * p.x() + this->_extra_data_P->c) / this->_extra_data_P->b; } - else - { - CGAL_assertion ((this->_info & DEGREE_MASK) == DEGREE_2); + else { + CGAL_assertion((this->_info & DEGREE_MASK) == DEGREE_2); // In this case the y-coordinate is one of solutions to the quadratic // equation: // s*y^2 + (t*x(p) + v)*y + (r*x(p)^2 + u*x(p) + w) = 0 - Algebraic A = alg_s; - Algebraic B = alg_t*p.x() + alg_v; - Algebraic C = (alg_r*p.x() + alg_u)*p.x() + alg_w; + Algebraic A = alg_s; + Algebraic B = alg_t*p.x() + alg_v; + Algebraic C = (alg_r*p.x() + alg_u)*p.x() + alg_w; - if (CGAL::sign(this->_s) == ZERO) - { + if (CGAL::sign(this->_s) == ZERO) { // In this case A is 0 and we have a linear equation. CGAL_assertion (CGAL::sign (B) != ZERO); y = -C / B; } - else - { + else { // Solve the quadratic equation. Algebraic disc = B*B - 4*A*C; @@ -547,13 +501,10 @@ public: // We take either the root involving -sqrt(disc) or +sqrt(disc) // based on the information flags. - if ((this->_info & PLUS_SQRT_DISC_ROOT) != 0) - { + if ((this->_info & PLUS_SQRT_DISC_ROOT) != 0) { y = (nt_traits.sqrt (disc) - B) / (2*A); } - else - - { + else { y = -(B + nt_traits.sqrt (disc)) / (2*A); } } @@ -579,169 +530,148 @@ public: { CGAL_precondition (n != 0); - const double x_left = CGAL::to_double (left().x()); - const double y_left = CGAL::to_double (left().y()); - const double x_right = CGAL::to_double (right().x()); - const double y_right = CGAL::to_double (right().y()); + const double x_left = CGAL::to_double (left().x()); + const double y_left = CGAL::to_double (left().y()); + const double x_right = CGAL::to_double (right().x()); + const double y_right = CGAL::to_double (right().y()); - if (this->_orient == COLLINEAR) - { + if (this->_orient == COLLINEAR) { // In case of a line segment, return the two endpoints. - *oi = std::pair (x_left, y_left); - ++oi; - *oi = std::pair (x_right, y_right); - ++oi; - return (oi); + *oi++ = std::pair (x_left, y_left); + *oi++ = std::pair (x_right, y_right); + return oi; } // Otherwise, sample (n - 1) equally-spaced points in between. - const double app_r = CGAL::to_double (this->_r); - const double app_s = CGAL::to_double (this->_s); - const double app_t = CGAL::to_double (this->_t); - const double app_u = CGAL::to_double (this->_u); - const double app_v = CGAL::to_double (this->_v); - const double app_w = CGAL::to_double (this->_w); - const double x_jump = (x_right - x_left) / n; - double x, y; - const bool A_is_zero = (CGAL::sign(this->_s) == ZERO); - double A = app_s, B, C; - double disc; - size_t i; + const double app_r = CGAL::to_double (this->_r); + const double app_s = CGAL::to_double (this->_s); + const double app_t = CGAL::to_double (this->_t); + const double app_u = CGAL::to_double (this->_u); + const double app_v = CGAL::to_double (this->_v); + const double app_w = CGAL::to_double (this->_w); + const double x_jump = (x_right - x_left) / n; + double x, y; + const bool A_is_zero = (CGAL::sign(this->_s) == ZERO); + double A = app_s, B, C; + double disc; + size_t i; - *oi = std::pair (x_left, y_left); // The left point. + *oi = std::pair(x_left, y_left); // The left point. ++oi; - for (i = 1; i < n; i++) - { + for (i = 1; i < n; i++) { x = x_left + x_jump*i; // Solve the quadratic equation: A*x^2 + B*x + C = 0: B = app_t*x + app_v; C = (app_r*x + app_u)*x + app_w; - if (A_is_zero) - { + if (A_is_zero) { y = -C / B; } - else - { + else { disc = B*B - 4*A*C; - if (disc < 0) - disc = 0; + if (disc < 0) disc = 0; // We take either the root involving -sqrt(disc) or +sqrt(disc) // based on the information flags. - if ((this->_info & PLUS_SQRT_DISC_ROOT) != 0) - { + if ((this->_info & PLUS_SQRT_DISC_ROOT) != 0) { y = (std::sqrt(disc) - B) / (2*A); } - else - { + else { y = -(B + std::sqrt (disc)) / (2*A); } } - *oi = std::pair (x, y); - ++oi; + *oi++ = std::pair (x, y); } - *oi = std::pair (x_right, y_right); // The right point. - ++oi; + *oi++ = std::pair (x_right, y_right); // The right point. - return (oi); + return oi; } - /*! - * Compare to arcs immediately to the right of their intersection point. + /*! Compare to arcs immediately to the right of their intersection point. * \param arc The compared arc. * \param p The reference intersection point. * \return The relative position of the arcs to the right of p. * \pre Both arcs we compare are not vertical segments. */ - Comparison_result compare_to_right (const Self& arc, - const Conic_point_2& p) const + Comparison_result compare_to_right(const Self& arc, + const Conic_point_2& p) const { - CGAL_precondition ((this->_info & IS_VERTICAL_SEGMENT) == 0 && - (arc._info & IS_VERTICAL_SEGMENT) == 0); + CGAL_precondition((this->_info & IS_VERTICAL_SEGMENT) == 0 && + (arc._info & IS_VERTICAL_SEGMENT) == 0); // In case one arc is facing upwards and another facing downwards, it is // clear that the one facing upward is above the one facing downwards. - if (_has_same_supporting_conic (arc)) - { + if (_has_same_supporting_conic (arc)) { if ((this->_info & FACING_UP) != 0 && (arc._info & FACING_DOWN) != 0) - return (LARGER); + return LARGER; else if ((this->_info & FACING_DOWN)!= 0 && (arc._info & FACING_UP) != 0) - return (SMALLER); + return SMALLER; // In this case the two arcs overlap. - CGAL_assertion ((this->_info & FACING_MASK) == - (arc._info & FACING_MASK)); + CGAL_assertion((this->_info & FACING_MASK) == (arc._info & FACING_MASK)); - return (EQUAL); + return EQUAL; } // Compare the slopes of the two arcs at p, using their first-order // partial derivatives. - Algebraic slope1_numer, slope1_denom; - Algebraic slope2_numer, slope2_denom; + Algebraic slope1_numer, slope1_denom; + Algebraic slope2_numer, slope2_denom; _derive_by_x_at (p, 1, slope1_numer, slope1_denom); arc._derive_by_x_at (p, 1, slope2_numer, slope2_denom); // Check if any of the slopes is vertical. - const bool is_vertical_slope1 = (CGAL::sign (slope1_denom) == ZERO); - const bool is_vertical_slope2 = (CGAL::sign (slope2_denom) == ZERO); + const bool is_vertical_slope1 = (CGAL::sign(slope1_denom) == ZERO); + const bool is_vertical_slope2 = (CGAL::sign(slope2_denom) == ZERO); - if (!is_vertical_slope1 && !is_vertical_slope2) - { + if (!is_vertical_slope1 && !is_vertical_slope2) { // The two derivatives at p are well-defined: use them to determine // which arc is above the other (the one with a larger slope is below). - Comparison_result slope_res = CGAL::compare (slope1_numer*slope2_denom, - slope2_numer*slope1_denom); + Comparison_result slope_res = + CGAL::compare(slope1_numer*slope2_denom, slope2_numer*slope1_denom); - if (slope_res != EQUAL) - return (slope_res); + if (slope_res != EQUAL) return (slope_res); // Use the second-order derivative. - _derive_by_x_at (p, 2, slope1_numer, slope1_denom); - arc._derive_by_x_at (p, 2, slope2_numer, slope2_denom); + _derive_by_x_at(p, 2, slope1_numer, slope1_denom); + arc._derive_by_x_at(p, 2, slope2_numer, slope2_denom); - slope_res = CGAL::compare (slope1_numer*slope2_denom, - slope2_numer*slope1_denom); + slope_res = + CGAL::compare(slope1_numer*slope2_denom, slope2_numer*slope1_denom); - if (slope_res != EQUAL) - return (slope_res); + if (slope_res != EQUAL) return (slope_res); // Use the third-order derivative. - _derive_by_x_at (p, 3, slope1_numer, slope1_denom); - arc._derive_by_x_at (p, 3, slope2_numer, slope2_denom); + _derive_by_x_at(p, 3, slope1_numer, slope1_denom); + arc._derive_by_x_at(p, 3, slope2_numer, slope2_denom); - slope_res = CGAL::compare (slope1_numer*slope2_denom, - slope2_numer*slope1_denom); + slope_res = + CGAL::compare(slope1_numer*slope2_denom, slope2_numer*slope1_denom); // \todo Handle higher-order derivatives: CGAL_assertion (slope_res != EQUAL); return (slope_res); } - else if (!is_vertical_slope2) - { + else if (!is_vertical_slope2) { // The first arc has a vertical slope at p: check whether it is // facing upwards or downwards and decide accordingly. CGAL_assertion ((this->_info & FACING_MASK) != 0); - if ((this->_info & FACING_UP) != 0) - return (LARGER); - return (SMALLER); + if ((this->_info & FACING_UP) != 0) return (LARGER); + return SMALLER; } - else if (!is_vertical_slope1) - { + else if (!is_vertical_slope1) { // The second arc has a vertical slope at p_int: check whether it is // facing upwards or downwards and decide accordingly. CGAL_assertion ((arc._info & FACING_MASK) != 0); - if ((arc._info & FACING_UP) != 0) - return (SMALLER); - return (LARGER); + if ((arc._info & FACING_UP) != 0) return (SMALLER); + return LARGER; } // The two arcs have vertical slopes at p_int: @@ -750,31 +680,29 @@ public: if ((this->_info & FACING_UP) != 0 && (arc._info & FACING_DOWN) != 0) return (LARGER); else if ((this->_info & FACING_DOWN)!= 0 && (arc._info & FACING_UP)!= 0) - return (SMALLER); + return SMALLER; // Compute the second-order derivative by y and act according to it. _derive_by_y_at (p, 2, slope1_numer, slope1_denom); arc._derive_by_y_at (p, 2, slope2_numer, slope2_denom); - Comparison_result slope_res = CGAL::compare (slope1_numer*slope2_denom, - slope2_numer*slope1_denom); + Comparison_result slope_res = + CGAL::compare(slope1_numer*slope2_denom, slope2_numer*slope1_denom); // If necessary, use the third-order derivative by y. - if (slope_res == EQUAL) - { + if (slope_res == EQUAL) { // \todo Check this! - _derive_by_y_at (p, 3, slope1_numer, slope1_denom); - arc._derive_by_y_at (p, 3, slope2_numer, slope2_denom); + _derive_by_y_at(p, 3, slope1_numer, slope1_denom); + arc._derive_by_y_at(p, 3, slope2_numer, slope2_denom); - slope_res = CGAL::compare (slope2_numer*slope1_denom, - slope1_numer*slope2_denom); + slope_res = + CGAL::compare(slope2_numer*slope1_denom, slope1_numer*slope2_denom); } // \todo Handle higher-order derivatives: CGAL_assertion(slope_res != EQUAL); - if ((this->_info & FACING_UP) != 0 && (arc._info & FACING_UP) != 0) - { + if ((this->_info & FACING_UP) != 0 && (arc._info & FACING_UP) != 0) { // Both are facing up. return ((slope_res == LARGER) ? SMALLER : LARGER); } @@ -789,50 +717,45 @@ public: * \return The relative position of the arcs to the left of p. * \pre Both arcs we compare are not vertical segments. */ - Comparison_result compare_to_left (const Self& arc, - const Conic_point_2& p) const + Comparison_result compare_to_left(const Self& arc, + const Conic_point_2& p) const { - CGAL_precondition ((this->_info & IS_VERTICAL_SEGMENT) == 0 && - (arc._info & IS_VERTICAL_SEGMENT) == 0); + CGAL_precondition((this->_info & IS_VERTICAL_SEGMENT) == 0 && + (arc._info & IS_VERTICAL_SEGMENT) == 0); // In case one arc is facing upwards and another facing downwards, it is // clear that the one facing upward is above the one facing downwards. - if (_has_same_supporting_conic (arc)) - { + if (_has_same_supporting_conic (arc)) { if ((this->_info & FACING_UP) != 0 && (arc._info & FACING_DOWN) != 0) - return (LARGER); + return LARGER; else if ((this->_info & FACING_DOWN)!= 0 && (arc._info & FACING_UP)!= 0) - return (SMALLER); + return SMALLER; // In this case the two arcs overlap. - CGAL_assertion ((this->_info & FACING_MASK) == - (arc._info & FACING_MASK)); + CGAL_assertion((this->_info & FACING_MASK) == (arc._info & FACING_MASK)); - return (EQUAL); + return EQUAL; } // Compare the slopes of the two arcs at p, using their first-order // partial derivatives. - Algebraic slope1_numer, slope1_denom; - Algebraic slope2_numer, slope2_denom; + Algebraic slope1_numer, slope1_denom; + Algebraic slope2_numer, slope2_denom; - _derive_by_x_at (p, 1, slope1_numer, slope1_denom); - arc._derive_by_x_at (p, 1, slope2_numer, slope2_denom); + _derive_by_x_at(p, 1, slope1_numer, slope1_denom); + arc._derive_by_x_at(p, 1, slope2_numer, slope2_denom); // Check if any of the slopes is vertical. - const bool is_vertical_slope1 = (CGAL::sign (slope1_denom) == ZERO); + const bool is_vertical_slope1 = (CGAL::sign (slope1_denom) == ZERO); + const bool is_vertical_slope2 = (CGAL::sign (slope2_denom) == ZERO); - const bool is_vertical_slope2 = (CGAL::sign (slope2_denom) == ZERO); - - if (!is_vertical_slope1 && !is_vertical_slope2) - { + if (!is_vertical_slope1 && !is_vertical_slope2) { // The two derivatives at p are well-defined: use them to determine // which arc is above the other (the one with a larger slope is below). Comparison_result slope_res = CGAL::compare(slope2_numer*slope1_denom, slope1_numer*slope2_denom); - if (slope_res != EQUAL) - return (slope_res); + if (slope_res != EQUAL) return (slope_res); // Use the second-order derivative. _derive_by_x_at (p, 2, slope1_numer, slope1_denom); @@ -841,73 +764,66 @@ public: slope_res = CGAL::compare (slope1_numer*slope2_denom, slope2_numer*slope1_denom); - if (slope_res != EQUAL) - return (slope_res); + if (slope_res != EQUAL) return (slope_res); // Use the third-order derivative. - _derive_by_x_at (p, 3, slope1_numer, slope1_denom); - arc._derive_by_x_at (p, 3, slope2_numer, slope2_denom); + _derive_by_x_at(p, 3, slope1_numer, slope1_denom); + arc._derive_by_x_at(p, 3, slope2_numer, slope2_denom); - slope_res = CGAL::compare (slope2_numer*slope1_denom, - slope1_numer*slope2_denom); + slope_res = CGAL::compare(slope2_numer*slope1_denom, + slope1_numer*slope2_denom); // \todo Handle higher-order derivatives: CGAL_assertion (slope_res != EQUAL); return (slope_res); } - else if (!is_vertical_slope2) - { + else if (!is_vertical_slope2) { // The first arc has a vertical slope at p: check whether it is // facing upwards or downwards and decide accordingly. CGAL_assertion ((this->_info & FACING_MASK) != 0); - if ((this->_info & FACING_UP) != 0) - return (LARGER); - return (SMALLER); + if ((this->_info & FACING_UP) != 0) return (LARGER); + return SMALLER; } - else if (!is_vertical_slope1) - { + else if (!is_vertical_slope1) { // The second arc has a vertical slope at p_int: check whether it is // facing upwards or downwards and decide accordingly. CGAL_assertion ((arc._info & FACING_MASK) != 0); - if ((arc._info & FACING_UP) != 0) - return (SMALLER); - return (LARGER); + if ((arc._info & FACING_UP) != 0) return (SMALLER); + return LARGER; } // The two arcs have vertical slopes at p_int: // First check whether one is facing up and one down. In this case the // comparison result is trivial. if ((this->_info & FACING_UP) != 0 && (arc._info & FACING_DOWN) != 0) - return (LARGER); + return LARGER; else if ((this->_info & FACING_DOWN)!= 0 && (arc._info & FACING_UP)!= 0) - return (SMALLER); + return SMALLER; // Compute the second-order derivative by y and act according to it. - _derive_by_y_at (p, 2, slope1_numer, slope1_denom); - arc._derive_by_y_at (p, 2, slope2_numer, slope2_denom); + _derive_by_y_at(p, 2, slope1_numer, slope1_denom); + arc._derive_by_y_at(p, 2, slope2_numer, slope2_denom); - Comparison_result slope_res = CGAL::compare(slope2_numer*slope1_denom, - slope1_numer*slope2_denom); + Comparison_result slope_res = + CGAL::compare(slope2_numer*slope1_denom, slope1_numer*slope2_denom); // If necessary, use the third-order derivative by y. - if (slope_res == EQUAL) - { + if (slope_res == EQUAL) { // \todo Check this! - _derive_by_y_at (p, 3, slope1_numer, slope1_denom); - arc._derive_by_y_at (p, 3, slope2_numer, slope2_denom); + _derive_by_y_at(p, 3, slope1_numer, slope1_denom); + arc._derive_by_y_at(p, 3, slope2_numer, slope2_denom); - slope_res = CGAL::compare (slope2_numer*slope1_denom, - slope1_numer*slope2_denom); + slope_res = + CGAL::compare(slope2_numer*slope1_denom, slope1_numer*slope2_denom); } // \todo Handle higher-order derivatives: CGAL_assertion(slope_res != EQUAL); - if ((this->_info & FACING_UP) != 0 && (arc._info & FACING_UP) != 0) - { + if ((this->_info & FACING_UP) != 0 && (arc._info & FACING_UP) != 0) { // Both are facing up. return ((slope_res == LARGER) ? SMALLER : LARGER); } @@ -922,22 +838,22 @@ public: * \param oi The output iterator. * \return The past-the-end iterator. */ - template - OutputIterator intersect (const Self& arc, - Intersection_map& inter_map, - OutputIterator oi) const + template + OutputIterator intersect(const Self& arc, + Intersection_map& inter_map, + OutputIterator oi) const { - if (_has_same_supporting_conic (arc)) - { - // Check for overlaps between the two arcs. - Self overlap; + typedef unsigned int Multiplicity; + typedef boost::variant Intersection_result; - if (_compute_overlap (arc, overlap)) - { + if (_has_same_supporting_conic(arc)) { + // Check for overlaps between the two arcs. + Self overlap; + + if (_compute_overlap(arc, overlap)) { // There can be just a single overlap between two x-monotone arcs: - *oi = make_object (overlap); - oi++; - return (oi); + *oi++ = Intersection_result(overlap); + return oi; } // In case there is not overlap and the supporting conics are the same, @@ -947,80 +863,62 @@ public: // intersection points we report. Alg_kernel ker; - if (ker.equal_2_object() (left(), arc.left())) - { - Intersection_point_2 ip (left(), 0); - - *oi = make_object (ip); - oi++; + if (ker.equal_2_object()(left(), arc.left())) { + Intersection_point ip(left(), 0); + *oi++ = Intersection_result(ip); } - if (ker.equal_2_object() (right(), arc.right())) - { - Intersection_point_2 ip (right(), 0); - - *oi = make_object (ip); - oi++; + if (ker.equal_2_object()(right(), arc.right())) { + Intersection_point ip(right(), 0); + *oi++ = Intersection_result(ip); } - return (oi); + return oi; } // Search for the pair of supporting conics in the map (the first conic // ID in the pair should be smaller than the second one, to guarantee // uniqueness). - Conic_pair conic_pair; - Intersection_map_iterator map_iter; - Intersection_list inter_list; - bool invalid_ids = false; - - if (_id.is_valid() && arc._id.is_valid()) - { - if (_id < arc._id) - conic_pair = Conic_pair (_id, arc._id); - else - conic_pair = Conic_pair (arc._id, _id); + Conic_pair conic_pair; + Intersection_map_iterator map_iter; + Intersection_list inter_list; + bool invalid_ids = false; + if (_id.is_valid() && arc._id.is_valid()) { + if (_id < arc._id) conic_pair = Conic_pair (_id, arc._id); + else conic_pair = Conic_pair (arc._id, _id); map_iter = inter_map.find (conic_pair); } - else - { + else { // In case one of the IDs is invalid, we do not look in the map neither // we cache the results. map_iter = inter_map.end(); invalid_ids = true; } - if (map_iter == inter_map.end()) - { + if (map_iter == inter_map.end()) { // In case the intersection points between the supporting conics have // not been computed before, compute them now and store them in the map. - _intersect_supporting_conics (arc, inter_list); + _intersect_supporting_conics(arc, inter_list); - if (! invalid_ids) - inter_map[conic_pair] = inter_list; + if (! invalid_ids) inter_map[conic_pair] = inter_list; } - else - { + else { // Obtain the precomputed intersection points from the map. inter_list = (*map_iter).second; } // Go over the list of intersection points and report those that lie on // both x-monotone arcs. - typename Intersection_list::const_iterator iter; - - for (iter = inter_list.begin(); iter != inter_list.end(); ++iter) - { - if (_is_between_endpoints ((*iter).first) && - arc._is_between_endpoints ((*iter).first)) + for (auto iter = inter_list.begin(); iter != inter_list.end(); ++iter) { + if (_is_between_endpoints((*iter).first) && + arc._is_between_endpoints((*iter).first)) { - *oi = make_object (*iter); - ++oi; + *oi++ = Intersection_result(*iter); } } - return (oi); + return oi; } //@} @@ -1034,13 +932,10 @@ public: * \param c2 Output: The first resulting arc, lying to the right of p. * \pre p lies in the interior of the arc (not one of its endpoints). */ - void split (const Conic_point_2& p, - Self& c1, Self& c2) const + void split(const Conic_point_2& p, Self& c1, Self& c2) const { // Make sure that p lies on the interior of the arc. - CGAL_precondition_code ( - Alg_kernel ker; - ); + CGAL_precondition_code(Alg_kernel ker); CGAL_precondition (this->contains_point (p) && ! ker.equal_2_object() (p, this->_source) && @@ -1058,8 +953,7 @@ public: c1._target = p; c2._source = p; - if (! p.is_generating_conic (_id)) - { + if (! p.is_generating_conic (_id)) { c1._target.set_generating_conic (_id); c2._source.set_generating_conic (_id); } @@ -1071,8 +965,7 @@ public: c1._source = p; c2._target = p; - if (! p.is_generating_conic (_id)) - { + if (! p.is_generating_conic (_id)) { c1._source.set_generating_conic (_id); c2._target.set_generating_conic (_id); } @@ -1085,16 +978,14 @@ public: * Flip the arc. * \return An arc with swapped source and target and a reverse orienation. */ - Self flip () const + Self flip() const { // Make a copy of the current arc. - Self arc = *this; + Self arc = *this; // Reverse the orientation. - if (this->_orient == CLOCKWISE) - arc._orient = COUNTERCLOCKWISE; - else if (this->_orient == COUNTERCLOCKWISE) - arc._orient = CLOCKWISE; + if (this->_orient == CLOCKWISE) arc._orient = COUNTERCLOCKWISE; + else if (this->_orient == COUNTERCLOCKWISE) arc._orient = CLOCKWISE; // Swap the source and the target. arc._source = this->_target; @@ -1103,7 +994,7 @@ public: // Change the direction bit among the information flags. arc._info = (this->_info ^ IS_DIRECTED_RIGHT); - return (arc); + return arc; } /*! @@ -1114,12 +1005,11 @@ public: * \pre Both ps and pt lies on the arc and must conform with the current * direction of the arc. */ - Self trim (const Conic_point_2& ps, - const Conic_point_2& pt) const + Self trim(const Conic_point_2& ps, const Conic_point_2& pt) const { // Make sure that both ps and pt lie on the arc. - CGAL_precondition (this->contains_point (ps) && - this->contains_point (pt)); + CGAL_precondition(this->contains_point (ps) && + this->contains_point (pt)); // Make sure that the endpoints conform with the direction of the arc. Self arc = *this; @@ -1136,8 +1026,7 @@ public: } // Make a copy of the current arc and assign its endpoints. - if (! ker.equal_2_object() (ps, this->_source)) - { + if (! ker.equal_2_object() (ps, this->_source)) { arc._source = ps; if (! ps.is_generating_conic (_id)) @@ -1164,46 +1053,41 @@ public: { // The two arc must have the same supporting conic curves. if (! _has_same_supporting_conic (arc)) - return (false); + return false; // Check that the arc endpoints are the same. - Alg_kernel ker; + Alg_kernel ker; - if(this->_orient == COLLINEAR) - { + if (this->_orient == COLLINEAR) { CGAL_assertion(arc._orient == COLLINEAR); - return((ker.equal_2_object() (this->_source, arc._source) && - ker.equal_2_object() (this->_target, arc._target)) || - (ker.equal_2_object() (this->_source, arc._target) && - ker.equal_2_object() (this->_target, arc._source))); + return((ker.equal_2_object()(this->_source, arc._source) && + ker.equal_2_object()(this->_target, arc._target)) || + (ker.equal_2_object()(this->_source, arc._target) && + ker.equal_2_object()(this->_target, arc._source))); } - if (this->_orient == arc._orient) - { + if (this->_orient == arc._orient) { // Same orientation - the source and target points must be the same. - return (ker.equal_2_object() (this->_source, arc._source) && - ker.equal_2_object() (this->_target, arc._target)); + return (ker.equal_2_object()(this->_source, arc._source) && + ker.equal_2_object()(this->_target, arc._target)); } - else - { + else { // Reverse orientation - the source and target points must be swapped. - return (ker.equal_2_object() (this->_source, arc._target) && - ker.equal_2_object() (this->_target, arc._source)); + return (ker.equal_2_object()(this->_source, arc._target) && + ker.equal_2_object()(this->_target, arc._source)); } } - /*! - * Check whether it is possible to merge the arc with the given arc. + /*! Check whether it is possible to merge the arc with the given arc. * \param arc The query arc. * \return (true) if it is possible to merge the two arcs; * (false) otherwise. */ - bool can_merge_with (const Self& arc) const + bool can_merge_with(const Self& arc) const { // In order to merge the two arcs, they should have the same supporting // conic. - if (! _has_same_supporting_conic (arc)) - return (false); + if (! _has_same_supporting_conic(arc)) return false; // Check if the left endpoint of one curve is the right endpoint of the // other. @@ -1213,28 +1097,23 @@ public: ker.equal_2_object() (left(), arc.right())); } - /*! - * Merge the current arc with the given arc. + /*! Merge the current arc with the given arc. * \param arc The arc to merge with. * \pre The two arcs are mergeable. */ - void merge (const Self& arc) + void merge(const Self& arc) { CGAL_precondition (this->can_merge_with (arc)); // Check if we should extend the arc to the left or to the right. Alg_kernel ker; - if (ker.equal_2_object() (right(), arc.left())) - { + if (ker.equal_2_object() (right(), arc.left())) { // Extend the arc to the right. - if ((this->_info & IS_DIRECTED_RIGHT) != 0) - this->_target = arc.right(); - else - this->_source = arc.right(); + if ((this->_info & IS_DIRECTED_RIGHT) != 0) this->_target = arc.right(); + else this->_source = arc.right(); } - else - { + else { CGAL_precondition (ker.equal_2_object() (left(), arc.right())); // Extend the arc to the left. @@ -1835,36 +1714,32 @@ private: * \param arc The arc to intersect with. * \param inter_list The list of intersection points. */ - void _intersect_supporting_conics (const Self& arc, - Intersection_list& inter_list) const + void _intersect_supporting_conics(const Self& arc, + Intersection_list& inter_list) const { - if (_is_special_segment() && ! arc._is_special_segment()) - { + if (_is_special_segment() && ! arc._is_special_segment()) { // If one of the arcs is a special segment, make sure it is (arc). - arc._intersect_supporting_conics (*this, inter_list); + arc._intersect_supporting_conics(*this, inter_list); return; } - const int deg1 = ((this->_info & DEGREE_MASK) == DEGREE_1) ? 1 : 2; - const int deg2 = ((arc._info & DEGREE_MASK) == DEGREE_1) ? 1 : 2; - Nt_traits nt_traits; - Algebraic xs[4]; - int n_xs = 0; - Algebraic ys[4]; - int n_ys = 0; + const int deg1 = ((this->_info & DEGREE_MASK) == DEGREE_1) ? 1 : 2; + const int deg2 = ((arc._info & DEGREE_MASK) == DEGREE_1) ? 1 : 2; + Nt_traits nt_traits; + Algebraic xs[4]; + int n_xs = 0; + Algebraic ys[4]; + int n_ys = 0; - if (arc._is_special_segment()) - { + if (arc._is_special_segment()) { // The second arc is a special segment (a*x + b*y + c = 0). - if (_is_special_segment()) - { + if (_is_special_segment()) { // Both arc are sepcial segment, so they have at most one intersection // point. - Algebraic denom = this->_extra_data_P->a * arc._extra_data_P->b - - this->_extra_data_P->b * arc._extra_data_P->a; + Algebraic denom = this->_extra_data_P->a * arc._extra_data_P->b - + this->_extra_data_P->b * arc._extra_data_P->a; - if (CGAL::sign (denom) != CGAL::ZERO) - { + if (CGAL::sign (denom) != CGAL::ZERO) { xs[0] = (this->_extra_data_P->b * arc._extra_data_P->c - this->_extra_data_P->c * arc._extra_data_P->b) / denom; n_xs = 1; @@ -1874,8 +1749,7 @@ private: n_ys = 1; } } - else - { + else { // Compute the x-coordinates of the intersection points. n_xs = _compute_resultant_roots (nt_traits, alg_r, alg_s, alg_t, @@ -1899,8 +1773,7 @@ private: CGAL_assertion (n_ys <= 2); } } - else - { + else { // Compute the x-coordinates of the intersection points. n_xs = _compute_resultant_roots (nt_traits, this->_r, this->_s, this->_t, @@ -1921,7 +1794,7 @@ private: arc._v, arc._u, arc._w, deg2, ys); - CGAL_assertion (n_ys <= 4); + CGAL_assertion(n_ys <= 4); } // Pair the coordinates of the intersection points. As the vectors of @@ -1938,14 +1811,14 @@ private: if (n_xs == 1 && n_ys == 1) { // Single intersection. - Conic_point_2 ip (xs[0], ys[0]); + Conic_point_2 ip (xs[0], ys[0]); ip.set_generating_conic (_id); ip.set_generating_conic (arc._id); // In case the other curve is of degree 2, this is a tangency point. mult = (deg1 == 1 || _is_special_segment()) ? 1 : 2; - inter_list.push_back (Intersection_point_2 (ip, mult)); + inter_list.push_back(Intersection_point (ip, mult)); } else if (n_xs == 1 && n_ys == 2) { @@ -1954,14 +1827,14 @@ private: ip1.set_generating_conic (_id); ip1.set_generating_conic (arc._id); - inter_list.push_back (Intersection_point_2 (ip1, 1)); + inter_list.push_back(Intersection_point (ip1, 1)); Conic_point_2 ip2 (xs[0], ys[1]); ip2.set_generating_conic (_id); ip2.set_generating_conic (arc._id); - inter_list.push_back (Intersection_point_2 (ip2, 1)); + inter_list.push_back(Intersection_point (ip2, 1)); } else if (n_xs == 2 && n_ys == 1) { @@ -1970,24 +1843,23 @@ private: ip1.set_generating_conic (_id); ip1.set_generating_conic (arc._id); - inter_list.push_back (Intersection_point_2 (ip1, 1)); + inter_list.push_back(Intersection_point (ip1, 1)); Conic_point_2 ip2 (xs[1], ys[0]); ip2.set_generating_conic (_id); ip2.set_generating_conic (arc._id); - inter_list.push_back (Intersection_point_2 (ip2, 1)); + inter_list.push_back(Intersection_point (ip2, 1)); } - else - { + else { CGAL_assertion (n_xs == 2 && n_ys == 2); // The x-coordinates and the y-coordinates are given in ascending // order. If the slope of the segment is positive, we pair the // coordinates as is - otherwise, we swap the pairs. - int ind_first_y = 0, ind_second_y = 1; + int ind_first_y = 0, ind_second_y = 1; if (CGAL::sign (arc._extra_data_P->b) == CGAL::sign(arc._extra_data_P->a)) @@ -1996,45 +1868,41 @@ private: ind_second_y = 0; } - Conic_point_2 ip1 (xs[0], ys[ind_first_y]); + Conic_point_2 ip1(xs[0], ys[ind_first_y]); - ip1.set_generating_conic (_id); - ip1.set_generating_conic (arc._id); + ip1.set_generating_conic(_id); + ip1.set_generating_conic(arc._id); - inter_list.push_back (Intersection_point_2 (ip1, 1)); + inter_list.push_back(Intersection_point (ip1, 1)); - Conic_point_2 ip2 (xs[1], ys[ind_second_y]); + Conic_point_2 ip2(xs[1], ys[ind_second_y]); ip2.set_generating_conic (_id); ip2.set_generating_conic (arc._id); - inter_list.push_back (Intersection_point_2 (ip2, 1)); + inter_list.push_back(Intersection_point(ip2, 1)); } return; } - for (i = 0; i < n_xs; i++) - { - for (j = 0; j < n_ys; j++) - { + for (i = 0; i < n_xs; i++) { + for (j = 0; j < n_ys; j++) { if (_is_on_supporting_conic (xs[i], ys[j]) && arc._is_on_supporting_conic (xs[i], ys[j])) { // Create the intersection point and set its generating conics. - Conic_point_2 ip (xs[i], ys[j]); + Conic_point_2 ip(xs[i], ys[j]); ip.set_generating_conic (_id); ip.set_generating_conic (arc._id); // Compute the multiplicity of the intersection point. - if (deg1 == 1 && deg2 == 1) - mult = 1; - else - mult = _multiplicity_of_intersection_point (arc, ip); + if (deg1 == 1 && deg2 == 1) mult = 1; + else mult = _multiplicity_of_intersection_point(arc, ip); // Insert the intersection point to the output list. - inter_list.push_back (Intersection_point_2 (ip, mult)); + inter_list.push_back(Intersection_point(ip, mult)); } } } diff --git a/Arrangement_on_surface_2/include/CGAL/Arr_geometry_traits/Rational_arc_2.h b/Arrangement_on_surface_2/include/CGAL/Arr_geometry_traits/Rational_arc_2.h index f5db0ebbad7..b6c246eb583 100644 --- a/Arrangement_on_surface_2/include/CGAL/Arr_geometry_traits/Rational_arc_2.h +++ b/Arrangement_on_surface_2/include/CGAL/Arr_geometry_traits/Rational_arc_2.h @@ -1830,7 +1830,7 @@ public: typedef typename Base::Rat_vector Rat_vector; typedef typename Base::Polynomial Polynomial; - typedef std::pair Intersection_point_2; + typedef std::pair Intersection_point; /// \name Constrcution methods. @@ -1967,138 +1967,118 @@ public: CGAL_precondition (this->is_valid() && this->is_continuous()); CGAL_precondition (arc.is_valid() && arc.is_continuous()); - if (this->_has_same_base (arc)) - { - Alg_kernel ker; + if (this->_has_same_base (arc)) { + Alg_kernel ker; // Get the left and right endpoints of (*this) and their information // bits. - const Point_2& left1 = (this->is_directed_right() ? - this->_ps : this->_pt); - const Point_2& right1 = (this->is_directed_right() ? - this->_pt : this->_ps); - int info_left1, info_right1; + const Point_2& left1 = + (this->is_directed_right() ? this->_ps : this->_pt); + const Point_2& right1 = + (this->is_directed_right() ? this->_pt : this->_ps); + int info_left1, info_right1; - if (this->is_directed_right()) - { + if (this->is_directed_right()) { info_left1 = (this->_info & this->SRC_INFO_BITS); info_right1 = ((this->_info & this->TRG_INFO_BITS) >> 4); } - else - { + else { info_right1 = (this->_info & this->SRC_INFO_BITS); info_left1 = ((this->_info & this->TRG_INFO_BITS) >> 4); } // Get the left and right endpoints of the other arc and their // information bits. - const Point_2& left2 = (arc.is_directed_right() ? arc._ps : arc._pt); - const Point_2& right2 = (arc.is_directed_right() ? arc._pt : arc._ps); - int info_left2, info_right2; + const Point_2& left2 = (arc.is_directed_right() ? arc._ps : arc._pt); + const Point_2& right2 = (arc.is_directed_right() ? arc._pt : arc._ps); + int info_left2, info_right2; - if (arc.is_directed_right()) - { + if (arc.is_directed_right()) { info_left2 = (arc._info & this->SRC_INFO_BITS); info_right2 = ((arc._info & this->TRG_INFO_BITS) >> 4); } - else - { + else { info_right2 = (arc._info & this->SRC_INFO_BITS); info_left2 = ((arc._info & this->TRG_INFO_BITS) >> 4); } // Locate the left curve-end with larger x-coordinate. - bool at_minus_infinity = false; - Arr_parameter_space inf_l1 = this->left_infinite_in_x(); - Arr_parameter_space inf_l2 = arc.left_infinite_in_x(); - Point_2 p_left; - int info_left; + bool at_minus_infinity = false; + Arr_parameter_space inf_l1 = this->left_infinite_in_x(); + Arr_parameter_space inf_l2 = arc.left_infinite_in_x(); + Point_2 p_left; + int info_left; - if (inf_l1 == ARR_INTERIOR && inf_l2 == ARR_INTERIOR) - { + if (inf_l1 == ARR_INTERIOR && inf_l2 == ARR_INTERIOR) { // Let p_left be the rightmost of the two left endpoints. - if (ker.compare_x_2_object() (left1, left2) == LARGER) - { + if (ker.compare_x_2_object() (left1, left2) == LARGER) { p_left = left1; info_left = info_left1; } - else - { + else { p_left = left2; info_left = info_left2; } } - else if (inf_l1 == ARR_INTERIOR) - { + else if (inf_l1 == ARR_INTERIOR) { // Let p_left be the left endpoint of (*this). p_left = left1; info_left = info_left1; } - else if (inf_l2 == ARR_INTERIOR) - { + else if (inf_l2 == ARR_INTERIOR) { // Let p_left be the left endpoint of the other arc. p_left = left2; info_left = info_left2; } - else - { + else { // Both arcs are defined at x = -oo. at_minus_infinity = true; info_left = info_left1; } // Locate the right curve-end with smaller x-coordinate. - bool at_plus_infinity = false; - Arr_parameter_space inf_r1 = this->right_infinite_in_x(); - Arr_parameter_space inf_r2 = arc.right_infinite_in_x(); - Point_2 p_right; - int info_right; + bool at_plus_infinity = false; + Arr_parameter_space inf_r1 = this->right_infinite_in_x(); + Arr_parameter_space inf_r2 = arc.right_infinite_in_x(); + Point_2 p_right; + int info_right; - if (inf_r1 == ARR_INTERIOR && inf_r2 == ARR_INTERIOR) - { + if (inf_r1 == ARR_INTERIOR && inf_r2 == ARR_INTERIOR) { // Let p_right be the rightmost of the two right endpoints. - if (ker.compare_x_2_object() (right1, right2) == SMALLER) - { + if (ker.compare_x_2_object() (right1, right2) == SMALLER) { p_right = right1; info_right = info_right1; } - else - { + else { p_right = right2; info_right = info_right2; } } - else if (inf_r1 == ARR_INTERIOR) - { + else if (inf_r1 == ARR_INTERIOR) { // Let p_right be the right endpoint of (*this). p_right = right1; info_right = info_right1; } - else if (inf_r2 == ARR_INTERIOR) - { + else if (inf_r2 == ARR_INTERIOR) { // Let p_right be the right endpoint of the other arc. p_right = right2; info_right = info_right2; } - else - { + else { // Both arcs are defined at x = +oo. at_plus_infinity = true; info_right = info_right2; } // Check the case of two bounded (in x) ends. - if (! at_minus_infinity && ! at_plus_infinity) - { + if (! at_minus_infinity && ! at_plus_infinity) { Comparison_result res = ker.compare_x_2_object() (p_left, p_right); - if (res == LARGER) - { + if (res == LARGER) { // The x-range of the overlap is empty, so there is no overlap. - return (oi); + return oi; } - else if (res == EQUAL) - { + if (res == EQUAL) { // We have a single overlapping point. Just make sure this point // is not at y = -/+ oo. if (info_left && @@ -2106,20 +2086,19 @@ public: info_right && (this->SRC_AT_Y_MINUS_INFTY | this->SRC_AT_Y_PLUS_INFTY) == 0) { - Intersection_point_2 ip (p_left, 0); + Intersection_point ip (p_left, 0); - *oi = make_object (ip); - ++oi; + *oi++ = make_object (ip); } - return (oi); + return oi; } } // Create the overlapping portion of the rational arc by properly setting // the source (left) and target (right) endpoints and their information // bits. - Self overlap_arc (*this); + Self overlap_arc(*this); overlap_arc._ps = p_left; overlap_arc._pt = p_right; @@ -2128,10 +2107,9 @@ public: this->IS_DIRECTED_RIGHT | this->IS_CONTINUOUS | this->IS_VALID); - *oi = make_object (overlap_arc); - ++oi; + *oi++ = make_object(overlap_arc); - return (oi); + return oi; } // We wish to find the intersection points between: @@ -2140,39 +2118,34 @@ public: // // It is clear that the x-coordinates of the intersection points are // the roots of the polynomial: ip(x) = p1(x)*q2(x) - p2(x)*q1(x). - Nt_traits nt_traits; - Polynomial ipoly = this->_numer * arc._denom - - arc._numer * this->_denom; - std::list xs; + Nt_traits nt_traits; + Polynomial ipoly = this->_numer * arc._denom - arc._numer* this->_denom; + std::list xs; typename std::list::const_iterator x_iter; - nt_traits.compute_polynomial_roots (ipoly, - std::back_inserter(xs)); + nt_traits.compute_polynomial_roots(ipoly, std::back_inserter(xs)); // Go over the x-values we obtained. For each value produce an // intersection point if it is contained in the x-range of both curves. - unsigned int mult; + unsigned int mult; - for (x_iter = xs.begin(); x_iter != xs.end(); ++x_iter) - { + for (x_iter = xs.begin(); x_iter != xs.end(); ++x_iter) { if (this->_is_in_true_x_range (*x_iter) && arc._is_in_true_x_range (*x_iter)) { // Compute the intersection point and obtain its multiplicity. - Point_2 p (*x_iter, nt_traits.evaluate_at (this->_numer, *x_iter) / - nt_traits.evaluate_at (this->_denom, *x_iter)); + Point_2 p(*x_iter, nt_traits.evaluate_at (this->_numer, *x_iter) / + nt_traits.evaluate_at (this->_denom, *x_iter)); - this->compare_slopes (arc, p, mult); + this->compare_slopes(arc, p, mult); // Output the intersection point: - Intersection_point_2 ip (p, mult); - - *oi = make_object (ip); - ++oi; + Intersection_point ip(p, mult); + *oi++ = make_object(ip); } } - return (oi); + return oi; } /*! diff --git a/Arrangement_on_surface_2/include/CGAL/Arr_linear_traits_2.h b/Arrangement_on_surface_2/include/CGAL/Arr_linear_traits_2.h index 2038cf0ad79..7f8d4a6a570 100644 --- a/Arrangement_on_surface_2/include/CGAL/Arr_linear_traits_2.h +++ b/Arrangement_on_surface_2/include/CGAL/Arr_linear_traits_2.h @@ -8,8 +8,9 @@ // SPDX-License-Identifier: GPL-3.0-or-later OR LicenseRef-Commercial // // -// Author(s) : Ron Wein -// : Waqar Khan +// Author(s): Ron Wein +// Waqar Khan +// Efi fogel #ifndef CGAL_ARR_LINEAR_TRAITS_2_H #define CGAL_ARR_LINEAR_TRAITS_2_H @@ -32,18 +33,17 @@ namespace CGAL { -template class Arr_linear_object_2; +template class Arr_linear_object_2; /*! \class * A traits class for maintaining an arrangement of linear objects (lines, * rays and segments), aoviding cascading of computations as much as possible. */ -template +template class Arr_linear_traits_2 : public Kernel_ { friend class Arr_linear_object_2; public: - typedef Kernel_ Kernel; typedef typename Kernel::FT FT; @@ -70,17 +70,14 @@ public: /*! * \class Representation of a linear with cached data. */ - class _Linear_object_cached_2 - { + class _Linear_object_cached_2 { public: - typedef typename Kernel::Line_2 Line_2; typedef typename Kernel::Ray_2 Ray_2; typedef typename Kernel::Segment_2 Segment_2; typedef typename Kernel::Point_2 Point_2; protected: - Line_2 l; // The supporting line. Point_2 ps; // The source point (if exists). Point_2 pt; // The target point (if exists). @@ -99,39 +96,36 @@ public: bool is_degen; // Is the object degenerate (a single point). public: - - /*! - * Default constructor. + /*! Default constructor. */ - _Linear_object_cached_2 () : - has_source (true), - has_target (true), - is_vert (false), - is_horiz (false), - has_pos_slope (false), - is_degen (true) + _Linear_object_cached_2() : + has_source(true), + has_target(true), + is_vert(false), + is_horiz(false), + has_pos_slope(false), + is_degen(true) {} - /*! - * Constructor for segment from two points. + /*! Constructor for segment from two points. * \param p1 source point. * \param p2 target point. * \pre The two points must not be equal. */ _Linear_object_cached_2(const Point_2& source, const Point_2& target) : - ps (source), - pt (target), - has_source (true), - has_target (true) + ps(source), + pt(target), + has_source(true), + has_target(true) { - Kernel kernel; + Kernel kernel; - Comparison_result res = kernel.compare_xy_2_object()(source, target); + Comparison_result res = kernel.compare_xy_2_object()(source, target); is_degen = (res == EQUAL); is_right = (res == SMALLER); - CGAL_precondition_msg (! is_degen, - "Cannot construct a degenerate segment."); + CGAL_precondition_msg(! is_degen, + "Cannot construct a degenerate segment."); l = kernel.construct_line_2_object()(source, target); is_vert = kernel.is_vertical_2_object()(l); @@ -139,17 +133,16 @@ public: has_pos_slope = _has_positive_slope(); } - /*! - * Constructor from a segment. + /*! Constructor from a segment. * \param seg The segment. * \pre The segment is not degenerate. */ - _Linear_object_cached_2 (const Segment_2& seg) + _Linear_object_cached_2(const Segment_2& seg) { - Kernel kernel; + Kernel kernel; - CGAL_assertion_msg (! kernel.is_degenerate_2_object() (seg), - "Cannot construct a degenerate segment."); + CGAL_assertion_msg(! kernel.is_degenerate_2_object()(seg), + "Cannot construct a degenerate segment."); typename Kernel_::Construct_vertex_2 construct_vertex = kernel.construct_vertex_2_object(); @@ -159,9 +152,9 @@ public: pt = construct_vertex(seg, 1); has_target = true; - Comparison_result res = kernel.compare_xy_2_object()(ps, pt); + Comparison_result res = kernel.compare_xy_2_object()(ps, pt); - CGAL_assertion (res != EQUAL); + CGAL_assertion(res != EQUAL); is_degen = false; is_right = (res == SMALLER); @@ -171,17 +164,16 @@ public: has_pos_slope = _has_positive_slope(); } - /*! - * Constructor from a ray. + /*! Constructor from a ray. * \param ray The ray. * \pre The ray is not degenerate. */ - _Linear_object_cached_2 (const Ray_2& ray) + _Linear_object_cached_2(const Ray_2& ray) { - Kernel kernel; + Kernel kernel; - CGAL_assertion_msg (! kernel.is_degenerate_2_object() (ray), - "Cannot construct a degenerate ray."); + CGAL_assertion_msg(! kernel.is_degenerate_2_object()(ray), + "Cannot construct a degenerate ray."); typename Kernel_::Construct_point_on_2 construct_vertex = kernel.construct_point_on_2_object(); @@ -192,7 +184,7 @@ public: has_target = false; Comparison_result res = kernel.compare_xy_2_object()(ps, pt); - CGAL_assertion (res != EQUAL); + CGAL_assertion(res != EQUAL); is_degen = false; is_right = (res == SMALLER); @@ -202,20 +194,19 @@ public: has_pos_slope = _has_positive_slope(); } - /*! - * Constructor from a line. + /*! Constructor from a line. * \param ln The line. * \pre The line is not degenerate. */ - _Linear_object_cached_2 (const Line_2& ln) : - l (ln), - has_source (false), - has_target (false) + _Linear_object_cached_2(const Line_2& ln) : + l(ln), + has_source(false), + has_target(false) { - Kernel kernel; + Kernel kernel; - CGAL_assertion_msg (! kernel.is_degenerate_2_object() (ln), - "Cannot construct a degenerate line."); + CGAL_assertion_msg(! kernel.is_degenerate_2_object()(ln), + "Cannot construct a degenerate line."); typename Kernel_::Construct_point_on_2 construct_vertex = kernel.construct_point_on_2_object(); @@ -225,8 +216,8 @@ public: pt = construct_vertex(ln, 1); // Some point further on the line. has_target = false; - Comparison_result res = kernel.compare_xy_2_object()(ps, pt); - CGAL_assertion (res != EQUAL); + Comparison_result res = kernel.compare_xy_2_object()(ps, pt); + CGAL_assertion(res != EQUAL); is_degen = false; is_right = (res == SMALLER); @@ -235,31 +226,27 @@ public: has_pos_slope = _has_positive_slope(); } - /*! - * Check whether the x-coordinate of the left point is infinite. + /*! Check whether the x-coordinate of the left point is infinite. * \return ARR_LEFT_BOUNDARY if the left point is near the boundary; * ARR_INTERIOR if the x-coordinate is finite. */ - Arr_parameter_space left_infinite_in_x () const + Arr_parameter_space left_infinite_in_x() const { - if (is_vert || is_degen) - return (ARR_INTERIOR); + if (is_vert || is_degen) return (ARR_INTERIOR); return (is_right) ? (has_source ? ARR_INTERIOR : ARR_LEFT_BOUNDARY) : (has_target ? ARR_INTERIOR : ARR_LEFT_BOUNDARY); } - /*! - * Check whether the y-coordinate of the left point is infinite. + /*! Check whether the y-coordinate of the left point is infinite. * \return ARR_BOTTOM_BOUNDARY if the left point is at y = -oo; * ARR_INTERIOR if the y-coordinate is finite. * ARR_TOP_BOUNDARY if the left point is at y = +oo; */ - Arr_parameter_space left_infinite_in_y () const + Arr_parameter_space left_infinite_in_y() const { - if (is_horiz || is_degen) - return ARR_INTERIOR; + if (is_horiz || is_degen) return ARR_INTERIOR; if (is_vert) { return (is_right) ? @@ -268,100 +255,80 @@ public: } if ((is_right && has_source) || (! is_right && has_target)) - return ARR_INTERIOR; + return ARR_INTERIOR; return (has_pos_slope ? ARR_BOTTOM_BOUNDARY : ARR_TOP_BOUNDARY); } - /*! - * Check whether the left point is finite. + /*! Check whether the left point is finite. */ - bool has_left () const - { - if (is_right) - return (has_source); - else - return (has_target); - } + bool has_left() const { return (is_right ? has_source : has_target); } - /*! - * Obtain the (lexicographically) left endpoint. + /*! Obtain the (lexicographically) left endpoint. * \pre The left point is finite. */ - const Point_2& left () const + const Point_2& left() const { - CGAL_precondition (has_left()); + CGAL_precondition(has_left()); return (is_right ? ps : pt); } - /*! - * Set the (lexicographically) left endpoint. + /*! Set the (lexicographically) left endpoint. * \param p The point to set. * \pre p lies on the supporting line to the left of the right endpoint. */ - void set_left (const Point_2& p, bool CGAL_assertion_code(check_validity) = true) + void set_left(const Point_2& p, + bool CGAL_assertion_code(check_validity) = true) { - CGAL_precondition (! is_degen); + CGAL_precondition(! is_degen); - CGAL_precondition_code ( - Kernel kernel; - ); + CGAL_precondition_code(Kernel kernel); CGAL_precondition - (Segment_assertions::_assert_is_point_on (p, l, - Has_exact_division()) && + (Segment_assertions::_assert_is_point_on(p, l, Has_exact_division()) && (! check_validity || ! has_right() || - kernel.compare_xy_2_object() (p, right()) == SMALLER)); + kernel.compare_xy_2_object()(p, right()) == SMALLER)); - if (is_right) - { + if (is_right) { ps = p; has_source = true; } - else - { + else { pt = p; has_target = true; } } - /*! - * Set the (lexicographically) left endpoint as infinite. + /*! Set the (lexicographically) left endpoint as infinite. */ - void set_left () + void set_left() { - CGAL_precondition (! is_degen); + CGAL_precondition(! is_degen); - if (is_right) - has_source = false; - else - has_target = false; + if (is_right) has_source = false; + else has_target = false; } - /*! - * Check whether the x-coordinate of the right point is infinite. + /*! Check whether the x-coordinate of the right point is infinite. * \return ARR_RIGHT_BOUNDARY if the right point is near the boundary; * ARR_INTERIOR if the x-coordinate is finite. */ - Arr_parameter_space right_infinite_in_x () const + Arr_parameter_space right_infinite_in_x() const { - if (is_vert || is_degen) - return ARR_INTERIOR; + if (is_vert || is_degen) return ARR_INTERIOR; return (is_right) ? (has_target ? ARR_INTERIOR : ARR_RIGHT_BOUNDARY) : (has_source ? ARR_INTERIOR : ARR_RIGHT_BOUNDARY); } - /*! - * Check whether the y-coordinate of the right point is infinite. + /*! Check whether the y-coordinate of the right point is infinite. * \return ARR_BOTTOM_BOUNDARY if the right point is at y = -oo; * ARR_INTERIOR if the y-coordinate is finite. * ARR_TOP_BOUNDARY if the right point is at y = +oo; */ - Arr_parameter_space right_infinite_in_y () const + Arr_parameter_space right_infinite_in_y() const { - if (is_horiz || is_degen) - return ARR_INTERIOR; + if (is_horiz || is_degen) return ARR_INTERIOR; if (is_vert) { return (is_right) ? @@ -375,145 +342,108 @@ public: return (has_pos_slope ? ARR_TOP_BOUNDARY : ARR_BOTTOM_BOUNDARY); } - /*! - * Check whether the right point is finite. + /*! Check whether the right point is finite. */ - bool has_right () const - { - if (is_right) - return (has_target); - else - return (has_source); - } + bool has_right() const { return (is_right ? has_target : has_source); } - /*! - * Obtain the (lexicographically) right endpoint. + /*! Obtain the (lexicographically) right endpoint. * \pre The right endpoint is finite. */ - const Point_2& right () const + const Point_2& right() const { - CGAL_precondition (has_right()); + CGAL_precondition(has_right()); return (is_right ? pt : ps); } - /*! - * Set the (lexicographically) right endpoint. + /*! Set the (lexicographically) right endpoint. * \param p The point to set. * \pre p lies on the supporting line to the right of the left endpoint. */ - void set_right (const Point_2& p, bool CGAL_assertion_code(check_validity) = true) + void set_right(const Point_2& p, + bool CGAL_assertion_code(check_validity) = true) { - CGAL_precondition (! is_degen); - CGAL_precondition_code ( - Kernel kernel; - ); + CGAL_precondition(! is_degen); + CGAL_precondition_code(Kernel kernel); CGAL_precondition - (Segment_assertions::_assert_is_point_on (p, l, - Has_exact_division()) && + (Segment_assertions::_assert_is_point_on(p, l, Has_exact_division()) && (! check_validity || ! has_left() || - kernel.compare_xy_2_object() (p, left()) == LARGER)); + kernel.compare_xy_2_object()(p, left()) == LARGER)); - if (is_right) - { + if (is_right) { pt = p; has_target = true; } - else - { + else { ps = p; has_source = true; } } - /*! - * Set the (lexicographically) right endpoint as infinite. + /*! Set the (lexicographically) right endpoint as infinite. */ - void set_right () + void set_right() { CGAL_precondition (! is_degen); - if (is_right) - has_target = false; - else - has_source = false; + if (is_right) has_target = false; + else has_source = false; } - /*! - * Obtain the supporting line. + /*! Obtain the supporting line. */ - const Line_2& supp_line () const + const Line_2& supp_line() const { - CGAL_precondition (! is_degen); + CGAL_precondition(! is_degen); return (l); } - /*! - * Check whether the curve is vertical. + /*! Check whether the curve is vertical. */ - bool is_vertical () const + bool is_vertical() const { - CGAL_precondition (! is_degen); + CGAL_precondition(! is_degen); return (is_vert); } - /*! - * Check whether the curve is degenerate. + /*! Check whether the curve is degenerate. */ - bool is_degenerate () const - { - return (is_degen); - } + bool is_degenerate() const { return (is_degen); } - /*! - * Check whether the curve is directed lexicographic from left to right + /*! Check whether the curve is directed lexicographic from left to right */ - bool is_directed_right () const - { - return (is_right); - } + bool is_directed_right() const { return (is_right); } - /*! - * Check whether the given point is in the x-range of the object. + /*! Check whether the given point is in the x-range of the object. * \param p The query point. * \return (true) is in the x-range of the segment; (false) if it is not. */ - bool is_in_x_range (const Point_2& p) const + bool is_in_x_range(const Point_2& p) const { - Kernel kernel; - typename Kernel_::Compare_x_2 compare_x = kernel.compare_x_2_object(); - Comparison_result res1; + Kernel kernel; + typename Kernel_::Compare_x_2 compare_x = kernel.compare_x_2_object(); + Comparison_result res1; - if (left_infinite_in_x() == ARR_INTERIOR) - { - if (left_infinite_in_y() != ARR_INTERIOR) - // Compare with some point on the curve. - res1 = compare_x (p, ps); - else - res1 = compare_x (p, left()); + if (left_infinite_in_x() == ARR_INTERIOR) { + // Compare with some point on the curve. + if (left_infinite_in_y() != ARR_INTERIOR) res1 = compare_x(p, ps); + else res1 = compare_x(p, left()); } - else - { + else { // p is obviously to the right. res1 = LARGER; } - if (res1 == SMALLER) - return (false); - else if (res1 == EQUAL) - return (true); + if (res1 == SMALLER) return false; + else if (res1 == EQUAL) return true; - Comparison_result res2; + Comparison_result res2; - if (right_infinite_in_x() == ARR_INTERIOR) - { - if (right_infinite_in_y() != ARR_INTERIOR) - // Compare with some point on the curve. - res2 = compare_x (p, ps); - else - res2 = compare_x (p, right()); + if (right_infinite_in_x() == ARR_INTERIOR) { + // Compare with some point on the curve. + if (right_infinite_in_y() != ARR_INTERIOR) res2 = compare_x(p, ps); + else res2 = compare_x(p, right()); } - else - { + else { // p is obviously to the right. res2 = SMALLER; } @@ -521,68 +451,54 @@ public: return (res2 != LARGER); } - /*! - * Check whether the given point is in the y-range of the object. + /*! Check whether the given point is in the y-range of the object. * \param p The query point. * \pre The object is vertical. * \return (true) is in the y-range of the segment; (false) if it is not. */ - bool is_in_y_range (const Point_2& p) const + bool is_in_y_range(const Point_2& p) const { - CGAL_precondition (is_vertical()); + CGAL_precondition(is_vertical()); - Kernel kernel; - typename Kernel_::Compare_y_2 compare_y = kernel.compare_y_2_object(); - Arr_parameter_space inf = left_infinite_in_y(); - Comparison_result res1; + Kernel kernel; + typename Kernel_::Compare_y_2 compare_y = kernel.compare_y_2_object(); + Arr_parameter_space inf = left_infinite_in_y(); + Comparison_result res1; - CGAL_assertion (inf != ARR_TOP_BOUNDARY); - if (inf == ARR_INTERIOR) - res1 = compare_y (p, left()); - else - res1 = LARGER; // p is obviously above. + CGAL_assertion(inf != ARR_TOP_BOUNDARY); + if (inf == ARR_INTERIOR) res1 = compare_y (p, left()); + else res1 = LARGER; // p is obviously above. - if (res1 == SMALLER) - return (false); - else if (res1 == EQUAL) - return (true); + if (res1 == SMALLER) return false; + else if (res1 == EQUAL) return true; - Comparison_result res2; + Comparison_result res2; inf = right_infinite_in_y(); - CGAL_assertion (inf != ARR_BOTTOM_BOUNDARY); - if (inf == ARR_INTERIOR) - res2 = compare_y (p, right()); - else - res2 = SMALLER; // p is obviously below. + CGAL_assertion(inf != ARR_BOTTOM_BOUNDARY); + if (inf == ARR_INTERIOR) res2 = compare_y(p, right()); + else res2 = SMALLER; // p is obviously below. return (res2 != LARGER); } private: - - /*! - * Determine if the supporting line has a positive slope. + /*! Determine if the supporting line has a positive slope. */ - bool _has_positive_slope () const + bool _has_positive_slope() const { - if (is_vert) - return (true); - - if (is_horiz) - return (false); + if (is_vert) return true; + if (is_horiz) return false; // Construct a horizontal line and compare its slope the that of l. - Kernel kernel; - Line_2 l_horiz = kernel.construct_line_2_object() (Point_2 (0, 0), - Point_2 (1, 0)); - - return (kernel.compare_slope_2_object() (l, l_horiz) == LARGER); + Kernel kernel; + Line_2 l_horiz = + kernel.construct_line_2_object()(Point_2(0, 0), Point_2(1, 0)); + return (kernel.compare_slope_2_object()(l, l_horiz) == LARGER); } }; public: - // Traits objects typedef typename Kernel::Point_2 Point_2; typedef Arr_linear_object_2 X_monotone_curve_2; @@ -590,12 +506,9 @@ public: typedef unsigned int Multiplicity; public: - - /*! - * Default constructor. + /*! Default constructor. */ - Arr_linear_traits_2 () - {} + Arr_linear_traits_2() {} /// \name Basic functor definitions. //@{ @@ -606,7 +519,7 @@ public: typedef Arr_linear_traits_2 Traits; /*! The traits (in case it has state) */ - const Traits * m_traits; + const Traits& m_traits; /*! Constructor * \param traits the traits (in case it has state) @@ -614,32 +527,28 @@ public: * obtaining function, which is a member of the nesting class, * constructing it. */ - Compare_x_2(const Traits * traits) : m_traits(traits) {} + Compare_x_2(const Traits& traits) : m_traits(traits) {} //! Allow its functor obtaining function calling the private constructor. friend class Arr_linear_traits_2; public: - /*! - * Compare the x-coordinates of two points. + /*! Compare the x-coordinates of two points. * \param p1 The first point. * \param p2 The second point. * \return LARGER if x(p1) > x(p2); * SMALLER if x(p1) < x(p2); * EQUAL if x(p1) = x(p2). */ - Comparison_result operator() (const Point_2& p1, const Point_2& p2) const + Comparison_result operator()(const Point_2& p1, const Point_2& p2) const { - const Kernel * kernel = m_traits; - return (kernel->compare_x_2_object()(p1, p2)); + const Kernel& kernel = m_traits; + return (kernel.compare_x_2_object()(p1, p2)); } }; /*! Obtain a Compare_x_2 functor. */ - Compare_x_2 compare_x_2_object () const - { - return Compare_x_2(this); - } + Compare_x_2 compare_x_2_object() const { return Compare_x_2(*this); } /*! A functor that compares the he endpoints of an $x$-monotone curve. */ class Compare_endpoints_xy_2{ @@ -650,21 +559,19 @@ public: * \return SMALLER if the curve is directed right; * LARGER if the curve is directed left. */ - Comparison_result operator() (const X_monotone_curve_2& xcv) const + Comparison_result operator()(const X_monotone_curve_2& xcv) const { return (xcv.is_directed_right()) ? (SMALLER) : (LARGER); } }; Compare_endpoints_xy_2 compare_endpoints_xy_2_object() const - { - return Compare_endpoints_xy_2(); - } + { return Compare_endpoints_xy_2(); } - class Trim_2{ + class Trim_2 { protected: typedef Arr_linear_traits_2 Traits; /*! The traits (in case it has state) */ - const Traits* m_traits; + const Traits& m_traits; /*! Constructor * \param traits the traits (in case it has state) @@ -672,25 +579,25 @@ public: * obtaining function, which is a member of the nesting class, * constructing it. */ - Trim_2(const Traits * traits) : m_traits(traits) {} + Trim_2(const Traits& traits) : m_traits(traits) {} //! Allow its functor obtaining function calling the private constructor. friend class Arr_linear_traits_2; public: - X_monotone_curve_2 operator()( const X_monotone_curve_2 xcv, - const Point_2 src, - const Point_2 tgt ) + X_monotone_curve_2 operator()(const X_monotone_curve_2 xcv, + const Point_2 src, + const Point_2 tgt) { /* * "Line_segment, line, and ray" will become line segments * when trimmed. - */ + */ Equal_2 equal = Equal_2(); - Compare_y_at_x_2 compare_y_at_x = m_traits->compare_y_at_x_2_object(); + Compare_y_at_x_2 compare_y_at_x = m_traits.compare_y_at_x_2_object(); //preconditions - //check if source and taget are two distinct points and they lie on the line. + //check if source and taget are distinct points and they lie on the line. CGAL_precondition(!equal(src, tgt)); CGAL_precondition(compare_y_at_x(src, xcv) == EQUAL); CGAL_precondition(compare_y_at_x(tgt, xcv) == EQUAL); @@ -698,33 +605,24 @@ public: //create trimmed line_segment X_monotone_curve_2 trimmed_segment; - if( xcv.is_directed_right() && tgt.x() < src.x() ) + if (xcv.is_directed_right() && (tgt.x() < src.x())) trimmed_segment = Segment_2(tgt, src); - - - else if( !xcv.is_directed_right() && tgt.x() > src.x()) + else if (! xcv.is_directed_right() && (tgt.x() > src.x())) trimmed_segment = Segment_2(tgt, src); - - else - trimmed_segment = Segment_2(src, tgt); + else trimmed_segment = Segment_2(src, tgt); return trimmed_segment; } - }; - Trim_2 trim_2_object() const - { - return Trim_2(this); - } - + Trim_2 trim_2_object() const { return Trim_2(*this); } class Construct_opposite_2{ protected: typedef Arr_linear_traits_2 Traits; /*! The traits (in case it has state) */ - const Traits* m_traits; + const Traits& m_traits; /*! Constructor * \param traits the traits (in case it has state) @@ -732,142 +630,111 @@ public: * obtaining function, which is a member of the nesting class, * constructing it. */ - Construct_opposite_2(const Traits * traits) : m_traits(traits) {} + Construct_opposite_2(const Traits& traits) : m_traits(traits) {} //! Allow its functor obtaining function calling the private constructor. friend class Arr_linear_traits_2; public: - - X_monotone_curve_2 operator()(const X_monotone_curve_2& xcv)const + X_monotone_curve_2 operator()(const X_monotone_curve_2& xcv) const { - CGAL_precondition (! xcv.is_degenerate()); + CGAL_precondition(! xcv.is_degenerate()); X_monotone_curve_2 opp_xcv; - if( xcv.is_segment() ) - { - opp_xcv = Segment_2(xcv.target(), xcv.source()); - } - - if( xcv.is_line() ) - { - opp_xcv = Line_2(xcv.get_pt(), xcv.get_ps()); - } - - if( xcv.is_ray() ) - { + if (xcv.is_segment()) opp_xcv = Segment_2(xcv.target(), xcv.source()); + if (xcv.is_line()) opp_xcv = Line_2(xcv.get_pt(), xcv.get_ps()); + if (xcv.is_ray()) { Point_2 opp_tgt = Point_2( -(xcv.get_pt().x()), -(xcv.get_pt().y())); opp_xcv = Ray_2( xcv.source(), opp_tgt); } return opp_xcv; - } - }; /*! Get a Construct_opposite_2 functor object. */ Construct_opposite_2 construct_opposite_2_object() const - { - return Construct_opposite_2(this); - } + { return Construct_opposite_2(*this); } /*! A functor that compares the x-coordinates of two points */ class Compare_xy_2 { public: - /*! - * Compare two points lexigoraphically: by x, then by y. + /*! Compare two points lexigoraphically: by x, then by y. * \param p1 The first point. * \param p2 The second point. * \return LARGER if x(p1) > x(p2), or if x(p1) = x(p2) and y(p1) > y(p2); * SMALLER if x(p1) < x(p2), or if x(p1) = x(p2) and y(p1) < y(p2); * EQUAL if the two points are equal. */ - Comparison_result operator() (const Point_2& p1, const Point_2& p2) const + Comparison_result operator()(const Point_2& p1, const Point_2& p2) const { - Kernel kernel; + Kernel kernel; return (kernel.compare_xy_2_object()(p1, p2)); } }; /*! Obtain a Compare_xy_2 functor object. */ - Compare_xy_2 compare_xy_2_object () const - { - return Compare_xy_2(); - } + Compare_xy_2 compare_xy_2_object() const { return Compare_xy_2(); } /*! A functor that obtains the left endpoint of a segment or a ray. */ - class Construct_min_vertex_2 - { + class Construct_min_vertex_2 { public: - /*! - * Get the left endpoint of the x-monotone curve (segment). + /*! Obtain the left endpoint of the x-monotone curve (segment). * \param cv The curve. * \pre The left end of cv is a valid (bounded) point. * \return The left endpoint. */ - const Point_2& operator() (const X_monotone_curve_2& cv) const + const Point_2& operator()(const X_monotone_curve_2& cv) const { - CGAL_precondition (! cv.is_degenerate()); - CGAL_precondition (cv.has_left()); + CGAL_precondition(! cv.is_degenerate()); + CGAL_precondition(cv.has_left()); return (cv.left()); } }; /*! Obtain a Construct_min_vertex_2 functor object. */ - Construct_min_vertex_2 construct_min_vertex_2_object () const - { - return Construct_min_vertex_2(); - } + Construct_min_vertex_2 construct_min_vertex_2_object() const + { return Construct_min_vertex_2(); } /*! A functor that obtains the right endpoint of a segment or a ray. */ - class Construct_max_vertex_2 - { + class Construct_max_vertex_2 { public: - /*! - * Get the right endpoint of the x-monotone curve (segment). + /*! Obtain the right endpoint of the x-monotone curve (segment). * \param cv The curve. * \pre The right end of cv is a valid (bounded) point. * \return The right endpoint. */ - const Point_2& operator() (const X_monotone_curve_2& cv) const + const Point_2& operator()(const X_monotone_curve_2& cv) const { - CGAL_precondition (! cv.is_degenerate()); - CGAL_precondition (cv.has_right()); + CGAL_precondition(! cv.is_degenerate()); + CGAL_precondition(cv.has_right()); return (cv.right()); } }; /*! Obtain a Construct_max_vertex_2 functor object. */ - Construct_max_vertex_2 construct_max_vertex_2_object () const - { - return Construct_max_vertex_2(); - } + Construct_max_vertex_2 construct_max_vertex_2_object() const + { return Construct_max_vertex_2(); } /*! A functor that checks whether a given linear curve is vertical. */ - class Is_vertical_2 - { + class Is_vertical_2 { public: - /*! - * Check whether the given x-monotone curve is a vertical segment. + /*! Check whether the given x-monotone curve is a vertical segment. * \param cv The curve. * \return (true) if the curve is a vertical segment; (false) otherwise. */ - bool operator() (const X_monotone_curve_2& cv) const + bool operator()(const X_monotone_curve_2& cv) const { - CGAL_precondition (! cv.is_degenerate()); + CGAL_precondition(! cv.is_degenerate()); return (cv.is_vertical()); } }; /*! Obtain an Is_vertical_2 functor object. */ - Is_vertical_2 is_vertical_2_object () const - { - return Is_vertical_2(); - } + Is_vertical_2 is_vertical_2_object() const { return Is_vertical_2(); } /*! A functor that compares the y-coordinates of a point and a line at * the point x-coordinate @@ -877,7 +744,7 @@ public: typedef Arr_linear_traits_2 Traits; /*! The traits (in case it has state) */ - const Traits* m_traits; + const Traits& m_traits; /*! Constructor * \param traits the traits (in case it has state) @@ -885,14 +752,13 @@ public: * obtaining function, which is a member of the nesting class, * constructing it. */ - Compare_y_at_x_2(const Traits * traits) : m_traits(traits) {} + Compare_y_at_x_2(const Traits& traits) : m_traits(traits) {} //! Allow its functor obtaining function calling the private constructor. friend class Arr_linear_traits_2; public: - /*! - * Return the location of the given point with respect to the input curve. + /*! Obtain the location of the given point with respect to the input curve. * \param cv The curve. * \param p The point. * \pre p is in the x-range of cv. @@ -900,42 +766,38 @@ public: * LARGER if y(p) > cv(x(p)), i.e. the point is above the curve; * EQUAL if p lies on the curve. */ - Comparison_result operator() (const Point_2& p, - const X_monotone_curve_2& cv) const + Comparison_result operator()(const Point_2& p, + const X_monotone_curve_2& cv) const { - CGAL_precondition (! cv.is_degenerate()); - CGAL_precondition (cv.is_in_x_range (p)); + CGAL_precondition(! cv.is_degenerate()); + CGAL_precondition(cv.is_in_x_range(p)); - const Kernel * kernel = m_traits; + const Kernel& kernel = m_traits; if (! cv.is_vertical()) // Compare p with the segment's supporting line. - return (kernel->compare_y_at_x_2_object()(p, cv.supp_line())); + return (kernel.compare_y_at_x_2_object()(p, cv.supp_line())); // Compare with the vertical segment's end-points. - typename Kernel::Compare_y_2 compare_y = kernel->compare_y_2_object(); + typename Kernel::Compare_y_2 compare_y = kernel.compare_y_2_object(); const Comparison_result res1 = - cv.has_left() ? compare_y (p, cv.left()) : LARGER; + cv.has_left() ? compare_y(p, cv.left()) : LARGER; const Comparison_result res2 = - cv.has_right() ? compare_y (p, cv.right()) : SMALLER; + cv.has_right() ? compare_y(p, cv.right()) : SMALLER; return (res1 == res2) ? res1 : EQUAL; } }; /*! Obtain a Compare_y_at_x_2 functor object. */ - Compare_y_at_x_2 compare_y_at_x_2_object () const - { - return Compare_y_at_x_2(this); - } + Compare_y_at_x_2 compare_y_at_x_2_object() const + { return Compare_y_at_x_2(*this); } /*! A functor that compares compares the y-coordinates of two linear * curves immediately to the left of their intersection point. */ - class Compare_y_at_x_left_2 - { + class Compare_y_at_x_left_2 { public: - /*! - * Compare the y value of two x-monotone curves immediately to the left + /*! Compare the y value of two x-monotone curves immediately to the left * of their intersection point. * \param cv1 The first curve. * \param cv2 The second curve. @@ -945,31 +807,28 @@ public: * \return The relative position of cv1 with respect to cv2 immdiately to * the left of p: SMALLER, LARGER or EQUAL. */ - Comparison_result operator() (const X_monotone_curve_2& cv1, - const X_monotone_curve_2& cv2, - const Point_2& CGAL_precondition_code(p)) const + Comparison_result operator()(const X_monotone_curve_2& cv1, + const X_monotone_curve_2& cv2, + const Point_2& CGAL_precondition_code(p)) const { - CGAL_precondition (! cv1.is_degenerate()); - CGAL_precondition (! cv2.is_degenerate()); + CGAL_precondition(! cv1.is_degenerate()); + CGAL_precondition(! cv2.is_degenerate()); Kernel kernel; // Make sure that p lies on both curves, and that both are defined to its // left (so their left endpoint is lexicographically smaller than p). - CGAL_precondition_code ( - typename Kernel::Compare_xy_2 compare_xy = kernel.compare_xy_2_object(); - ); + CGAL_precondition_code(auto compare_xy = kernel.compare_xy_2_object()); CGAL_precondition - (Segment_assertions::_assert_is_point_on (p, cv1, - Has_exact_division()) && - Segment_assertions::_assert_is_point_on (p, cv2, - Has_exact_division())); + (Segment_assertions::_assert_is_point_on(p, cv1, + Has_exact_division()) && + Segment_assertions::_assert_is_point_on(p, cv2, Has_exact_division())); - CGAL_precondition ((! cv1.has_left() || - compare_xy(cv1.left(), p) == SMALLER) && - (! cv2.has_left() || - compare_xy(cv2.left(), p) == SMALLER)); + CGAL_precondition((! cv1.has_left() || + compare_xy(cv1.left(), p) == SMALLER) && + (! cv2.has_left() || + compare_xy(cv2.left(), p) == SMALLER)); // Compare the slopes of the two segments to determine thir relative // position immediately to the left of q. @@ -981,19 +840,15 @@ public: }; /*! Obtain a Compare_y_at_x_left_2 functor object. */ - Compare_y_at_x_left_2 compare_y_at_x_left_2_object () const - { - return Compare_y_at_x_left_2(); - } + Compare_y_at_x_left_2 compare_y_at_x_left_2_object() const + { return Compare_y_at_x_left_2(); } /*! A functor that compares compares the y-coordinates of two linear * curves immediately to the right of their intersection point. */ - class Compare_y_at_x_right_2 - { + class Compare_y_at_x_right_2 { public: - /*! - * Compare the y value of two x-monotone curves immediately to the right + /*! Compare the y value of two x-monotone curves immediately to the right * of their intersection point. * \param cv1 The first curve. * \param cv2 The second curve. @@ -1003,31 +858,28 @@ public: * \return The relative position of cv1 with respect to cv2 immdiately to * the right of p: SMALLER, LARGER or EQUAL. */ - Comparison_result operator() (const X_monotone_curve_2& cv1, - const X_monotone_curve_2& cv2, - const Point_2& CGAL_precondition_code(p)) const + Comparison_result operator()(const X_monotone_curve_2& cv1, + const X_monotone_curve_2& cv2, + const Point_2& CGAL_precondition_code(p)) const { - CGAL_precondition (! cv1.is_degenerate()); - CGAL_precondition (! cv2.is_degenerate()); + CGAL_precondition(! cv1.is_degenerate()); + CGAL_precondition(! cv2.is_degenerate()); - Kernel kernel; + Kernel kernel; // Make sure that p lies on both curves, and that both are defined to its // right (so their right endpoint is lexicographically larger than p). - CGAL_precondition_code ( - typename Kernel::Compare_xy_2 compare_xy = kernel.compare_xy_2_object(); - ); + CGAL_precondition_code(auto compare_xy = kernel.compare_xy_2_object()); CGAL_precondition - (Segment_assertions::_assert_is_point_on (p, cv1, - Has_exact_division()) && - Segment_assertions::_assert_is_point_on (p, cv2, - Has_exact_division())); + (Segment_assertions::_assert_is_point_on(p, cv1, + Has_exact_division()) && + Segment_assertions::_assert_is_point_on(p, cv2, Has_exact_division())); - CGAL_precondition ((! cv1.has_right() || - compare_xy(cv1.right(), p) == LARGER) && - (! cv2.has_right() || - compare_xy(cv2.right(), p) == LARGER)); + CGAL_precondition((! cv1.has_right() || + compare_xy(cv1.right(), p) == LARGER) && + (! cv2.has_right() || + compare_xy(cv2.right(), p) == LARGER)); // Compare the slopes of the two segments to determine thir relative // position immediately to the left of q. @@ -1038,47 +890,43 @@ public: }; /*! Obtain a Compare_y_at_x_right_2 functor object. */ - Compare_y_at_x_right_2 compare_y_at_x_right_2_object () const - { - return Compare_y_at_x_right_2(); - } + Compare_y_at_x_right_2 compare_y_at_x_right_2_object() const + { return Compare_y_at_x_right_2(); } /*! A functor that checks whether two points and two linear curves are * identical. */ - class Equal_2 - { + class Equal_2 { public: - /*! - * Check whether the two x-monotone curves are the same (have the same + /*! Check whether the two x-monotone curves are the same (have the same * graph). * \param cv1 The first curve. * \param cv2 The second curve. * \return (true) if the two curves are the same; (false) otherwise. */ - bool operator() (const X_monotone_curve_2& cv1, - const X_monotone_curve_2& cv2) const + bool operator()(const X_monotone_curve_2& cv1, + const X_monotone_curve_2& cv2) const { - CGAL_precondition (! cv1.is_degenerate()); - CGAL_precondition (! cv2.is_degenerate()); + CGAL_precondition(! cv1.is_degenerate()); + CGAL_precondition(! cv2.is_degenerate()); - Kernel kernel; - typename Kernel::Equal_2 equal = kernel.equal_2_object(); + Kernel kernel; + typename Kernel::Equal_2 equal = kernel.equal_2_object(); // Check that the two supporting lines are the same. - if (! equal (cv1.supp_line(), cv2.supp_line()) && - ! equal (cv1.supp_line(), - kernel.construct_opposite_line_2_object()(cv2.supp_line()))) + if (! equal(cv1.supp_line(), cv2.supp_line()) && + ! equal(cv1.supp_line(), + kernel.construct_opposite_line_2_object()(cv2.supp_line()))) { - return (false); + return false; } // Check that either the two left endpoints are at infinity, or they // are bounded and equal. if ((cv1.has_left() != cv2.has_left()) || - (cv1.has_left() && ! equal (cv1.left(), cv2.left()))) + (cv1.has_left() && ! equal(cv1.left(), cv2.left()))) { - return (false); + return false; } // Check that either the two right endpoints are at infinity, or they @@ -1087,24 +935,20 @@ public: (! cv1.has_right() || equal (cv1.right(), cv2.right()))); } - /*! - * Check whether the two points are the same. + /*! Check whether the two points are the same. * \param p1 The first point. * \param p2 The second point. * \return (true) if the two point are the same; (false) otherwise. */ - bool operator() (const Point_2& p1, const Point_2& p2) const + bool operator()(const Point_2& p1, const Point_2& p2) const { - Kernel kernel; + Kernel kernel; return (kernel.equal_2_object()(p1, p2)); } }; /*! Obtain an Equal_2 functor object. */ - Equal_2 equal_2_object () const - { - return Equal_2(); - } + Equal_2 equal_2_object() const { return Equal_2(); } //@} /// \name Functor definitions to handle boundaries @@ -1130,7 +974,7 @@ public: Arr_parameter_space operator()(const X_monotone_curve_2 & xcv, Arr_curve_end ce) const { - CGAL_precondition (! xcv.is_degenerate()); + CGAL_precondition(! xcv.is_degenerate()); return (ce == ARR_MIN_END) ? xcv.left_infinite_in_x() : xcv.right_infinite_in_x(); } @@ -1140,9 +984,7 @@ public: * \return the parameter space at p. */ Arr_parameter_space operator()(const Point_2 ) const - { - return ARR_INTERIOR; - } + { return ARR_INTERIOR; } }; /*! Obtain a Parameter_space_in_x_2 function object */ @@ -1185,9 +1027,7 @@ public: * \return the parameter space at p. */ Arr_parameter_space operator()(const Point_2 ) const - { - return ARR_INTERIOR; - } + { return ARR_INTERIOR; } }; /*! Obtain a Parameter_space_in_y_2 function object */ @@ -1202,7 +1042,7 @@ public: typedef Arr_linear_traits_2 Traits; /*! The traits (in case it has state) */ - const Traits* m_traits; + const Traits& m_traits; /*! Constructor * \param traits the traits (in case it has state) @@ -1210,7 +1050,7 @@ public: * obtaining function, which is a member of the nesting class, * constructing it. */ - Compare_x_at_limit_2(const Traits* traits) : m_traits(traits) {} + Compare_x_at_limit_2(const Traits& traits) : m_traits(traits) {} //! Allow its functor obtaining function calling the private constructor. friend class Arr_linear_traits_2; @@ -1238,8 +1078,8 @@ public: CGAL_precondition(! xcv.is_degenerate()); CGAL_precondition(xcv.is_vertical()); - const Kernel* kernel = m_traits; - return (kernel->compare_x_at_y_2_object()(p, xcv.supp_line())); + const Kernel& kernel = m_traits; + return (kernel.compare_x_at_y_2_object()(p, xcv.supp_line())); } /*! Compare the x-limits of 2 arcs ends on the boundary of the @@ -1271,23 +1111,22 @@ public: CGAL_precondition(xcv1.is_vertical()); CGAL_precondition(xcv2.is_vertical()); - const Kernel* kernel = m_traits; - const Point_2 p = kernel->construct_point_2_object()(ORIGIN); - return (kernel->compare_x_at_y_2_object()(p, xcv1.supp_line(), - xcv2.supp_line())); + const Kernel& kernel = m_traits; + const Point_2 p = kernel.construct_point_2_object()(ORIGIN); + return (kernel.compare_x_at_y_2_object()(p, xcv1.supp_line(), + xcv2.supp_line())); } }; /*! Obtain a Compare_x_at_limit_2 function object */ Compare_x_at_limit_2 compare_x_at_limit_2_object() const - { return Compare_x_at_limit_2(this); } + { return Compare_x_at_limit_2(*this); } /*! A function object that compares the x-coordinates of arc ends near the * boundary of the parameter space */ class Compare_x_near_limit_2 { public: - /*! Compare the x-coordinates of 2 arcs ends near the boundary of the * parameter space at y = +/- oo. * \param xcv1 the first arc. @@ -1335,7 +1174,7 @@ public: typedef Arr_linear_traits_2 Traits; /*! The traits (in case it has state) */ - const Traits* m_traits; + const Traits& m_traits; /*! Constructor * \param traits the traits (in case it has state) @@ -1343,7 +1182,7 @@ public: * obtaining function, which is a member of the nesting class, * constructing it. */ - Compare_y_near_boundary_2(const Traits* traits) : m_traits(traits) {} + Compare_y_near_boundary_2(const Traits& traits) : m_traits(traits) {} //! Allow its functor obtaining function calling the private constructor. friend class Arr_linear_traits_2; @@ -1373,17 +1212,17 @@ public: xcv2.right_infinite_in_x() == ARR_RIGHT_BOUNDARY)); // Compare the slopes of the two supporting lines. - const Kernel* kernel = m_traits; + const Kernel& kernel = m_traits; const Comparison_result res_slopes = - kernel->compare_slope_2_object()(xcv1.supp_line(), xcv2.supp_line()); + kernel.compare_slope_2_object()(xcv1.supp_line(), xcv2.supp_line()); if (res_slopes == EQUAL) { // In case the two supporting line are parallel, compare their // relative position at x = 0, which is the same as their position // at infinity. - const Point_2 p = kernel->construct_point_2_object()(ORIGIN); - return (kernel->compare_y_at_x_2_object()(p, xcv1.supp_line(), - xcv2.supp_line())); + const Point_2 p = kernel.construct_point_2_object()(ORIGIN); + return (kernel.compare_y_at_x_2_object()(p, xcv1.supp_line(), + xcv2.supp_line())); } // Flip the slope result if we compare at x = -oo: @@ -1391,21 +1230,18 @@ public: } }; - /*! Obtain a Compare_y_limit_on_boundary_2 function object */ Compare_y_near_boundary_2 compare_y_near_boundary_2_object() const - { return Compare_y_near_boundary_2(this); } + { return Compare_y_near_boundary_2(*this); } //@} /// \name Functor definitions for supporting intersections. //@{ - class Make_x_monotone_2 - { + class Make_x_monotone_2 { public: - /*! - * Cut the given curve into x-monotone subcurves and insert them into the + /*! Cut the given curve into x-monotone subcurves and insert them into the * given output iterator. As segments are always x_monotone, only one * object will be contained in the iterator. * \param cv The curve. @@ -1414,73 +1250,72 @@ public: * essentially the same as the input curve. * \return The past-the-end iterator. */ - template - OutputIterator operator() (const Curve_2& cv, OutputIterator oi) const + template + OutputIterator operator()(const Curve_2& cv, OutputIterator oi) const { // Wrap the curve with an object. - *oi = make_object (cv); - ++oi; - - return (oi); + *oi++ = make_object(cv); + return oi; } }; /*! Obtain a Make_x_monotone_2 functor object. */ - Make_x_monotone_2 make_x_monotone_2_object () const - { - return Make_x_monotone_2(); - } + Make_x_monotone_2 make_x_monotone_2_object() const + { return Make_x_monotone_2(); } - class Split_2 - { + class Split_2 { public: - /*! - * Split a given x-monotone curve at a given point into two sub-curves. + /*! Split a given x-monotone curve at a given point into two sub-curves. * \param cv The curve to split * \param p The split point. * \param c1 Output: The left resulting subcurve (p is its right endpoint). * \param c2 Output: The right resulting subcurve (p is its left endpoint). * \pre p lies on cv but is not one of its end-points. */ - void operator() (const X_monotone_curve_2& cv, const Point_2& p, - X_monotone_curve_2& c1, X_monotone_curve_2& c2) const + void operator()(const X_monotone_curve_2& cv, const Point_2& p, + X_monotone_curve_2& c1, X_monotone_curve_2& c2) const { CGAL_precondition (! cv.is_degenerate()); // Make sure that p lies on the interior of the curve. CGAL_precondition_code ( - Kernel kernel; + Kernel kernel; typename Kernel::Compare_xy_2 compare_xy = kernel.compare_xy_2_object(); ); CGAL_precondition - (Segment_assertions::_assert_is_point_on (p, cv, - Has_exact_division()) && + (Segment_assertions::_assert_is_point_on(p, cv, Has_exact_division()) && (! cv.has_left() || compare_xy(cv.left(), p) == SMALLER) && (! cv.has_right() || compare_xy(cv.right(), p) == LARGER)); // Perform the split. c1 = cv; - c1.set_right (p); + c1.set_right(p); c2 = cv; - c2.set_left (p); - - return; + c2.set_left(p); } }; /*! Obtain a Split_2 functor object. */ - Split_2 split_2_object () const - { - return Split_2(); - } + Split_2 split_2_object() const { return Split_2(); } + + class Intersect_2 { + protected: + typedef Arr_linear_traits_2 Traits; + + /*! The traits (in case it has state) */ + const Traits& m_traits; + + /*! Constructor + * \param traits the traits (in case it has state) + */ + Intersect_2(const Traits& traits) : m_traits(traits) {} + + friend class Arr_linear_traits_2; - class Intersect_2 - { public: - /*! - * Find the intersections of the two given curves and insert them into the + /*! Find the intersections of the two given curves and insert them into the * given output iterator. As two segments may itersect only once, only a * single intersection will be contained in the iterator. * \param cv1 The first curve. @@ -1488,195 +1323,170 @@ public: * \param oi The output iterator. * \return The past-the-end iterator. */ - template - OutputIterator operator() (const X_monotone_curve_2& cv1, - const X_monotone_curve_2& cv2, - OutputIterator oi) const + template + OutputIterator operator()(const X_monotone_curve_2& cv1, + const X_monotone_curve_2& cv2, + OutputIterator oi) const { - CGAL_precondition (! cv1.is_degenerate()); - CGAL_precondition (! cv2.is_degenerate()); + typedef std::pair Intersection_point; + typedef boost::variant + Intersection_result; + + CGAL_precondition(! cv1.is_degenerate()); + CGAL_precondition(! cv2.is_degenerate()); // Intersect the two supporting lines. - Kernel kernel; - CGAL::Object obj = kernel.intersect_2_object()(cv1.supp_line(), - cv2.supp_line()); + const Kernel& kernel = m_traits; + auto res = kernel.intersect_2_object()(cv1.supp_line(), cv2.supp_line()); - if (obj.is_empty()) - { - // The supporting line are parallel lines and do not intersect: - return (oi); - } + // The supporting line are parallel lines and do not intersect: + if (! res) return oi; // Check whether we have a single intersection point. - const Point_2 *ip = object_cast (&obj); - - if (ip != nullptr) - { + const Point_2* ip = boost::get(&*res); + if (ip != nullptr) { // Check whether the intersection point ip lies on both segments. - const bool ip_on_cv1 = cv1.is_vertical() ? cv1.is_in_y_range(*ip) : - cv1.is_in_x_range(*ip); + const bool ip_on_cv1 = cv1.is_vertical() ? + cv1.is_in_y_range(*ip) : cv1.is_in_x_range(*ip); - if (ip_on_cv1) - { - const bool ip_on_cv2 = cv2.is_vertical() ? cv2.is_in_y_range(*ip) : - cv2.is_in_x_range(*ip); + if (ip_on_cv1) { + const bool ip_on_cv2 = cv2.is_vertical() ? + cv2.is_in_y_range(*ip) : cv2.is_in_x_range(*ip); - if (ip_on_cv2) - { + if (ip_on_cv2) { // Create a pair representing the point with its multiplicity, // which is always 1 for line segments. - std::pair ip_mult (*ip, 1); - *oi = make_object (ip_mult); - oi++; + Intersection_point ip_mult(*ip, 1); + *oi++ = Intersection_result(ip_mult); } } - return (oi); + return oi; } // In this case, the two supporting lines overlap. // We start with the entire cv1 curve as the overlapping subcurve, // then clip it to form the true overlapping curve. - typename Kernel::Compare_xy_2 compare_xy = kernel.compare_xy_2_object(); - X_monotone_curve_2 ovlp = cv1; + auto compare_xy = kernel.compare_xy_2_object(); + X_monotone_curve_2 ovlp = cv1; - if (cv2.has_left()) - { + if (cv2.has_left()) { // If the left endpoint of cv2 is to the right of cv1's left endpoint, // clip the overlapping subcurve. - if (! cv1.has_left()) - { + if (! cv1.has_left()) { ovlp.set_left (cv2.left(), false); } - else - { - if (compare_xy (cv1.left(), cv2.left()) == SMALLER) - ovlp.set_left (cv2.left(), false); + else { + if (compare_xy(cv1.left(), cv2.left()) == SMALLER) + ovlp.set_left(cv2.left(), false); } } - if (cv2.has_right()) - { + if (cv2.has_right()) { // If the right endpoint of cv2 is to the left of cv1's right endpoint, // clip the overlapping subcurve. - if (! cv1.has_right()) - { - ovlp.set_right (cv2.right(), false); + if (! cv1.has_right()) { + ovlp.set_right(cv2.right(), false); } - else - { - if (compare_xy (cv1.right(), cv2.right()) == LARGER) - ovlp.set_right (cv2.right(), false); + else { + if (compare_xy(cv1.right(), cv2.right()) == LARGER) + ovlp.set_right(cv2.right(), false); } } // Examine the resulting subcurve. - Comparison_result res = SMALLER; + Comparison_result cmp_res = SMALLER; if (ovlp.has_left() && ovlp.has_right()) - res = compare_xy (ovlp.left(), ovlp.right()); + cmp_res = compare_xy(ovlp.left(), ovlp.right()); - if (res == SMALLER) - { + if (cmp_res == SMALLER) { // We have discovered a true overlapping subcurve: - *oi = make_object (ovlp); - oi++; + *oi++ = Intersection_result(ovlp); } - else if (res == EQUAL) - { + else if (cmp_res == EQUAL) { // The two objects have the same supporting line, but they just share // a common endpoint. Thus we have an intersection point, but we leave // the multiplicity of this point undefined. - std::pair ip_mult (ovlp.left(), 0); - *oi = make_object (ip_mult); - oi++; + Intersection_point ip_mult(ovlp.left(), 0); + *oi++ = Intersection_result(ip_mult); } - return (oi); + return oi; } }; /*! Obtain an Intersect_2 functor object. */ - Intersect_2 intersect_2_object () const - { - return Intersect_2(); - } + Intersect_2 intersect_2_object () const { return Intersect_2(*this); } - class Are_mergeable_2 - { + class Are_mergeable_2 { public: - /*! - * Check whether it is possible to merge two given x-monotone curves. + /*! Check whether it is possible to merge two given x-monotone curves. * \param cv1 The first curve. * \param cv2 The second curve. * \return (true) if the two curves are mergeable - if they are supported * by the same line and share a common endpoint; (false) otherwise. */ - bool operator() (const X_monotone_curve_2& cv1, + bool operator()(const X_monotone_curve_2& cv1, const X_monotone_curve_2& cv2) const { - CGAL_precondition (! cv1.is_degenerate()); - CGAL_precondition (! cv2.is_degenerate()); + CGAL_precondition(! cv1.is_degenerate()); + CGAL_precondition(! cv2.is_degenerate()); - Kernel kernel; - typename Kernel::Equal_2 equal = kernel.equal_2_object(); + Kernel kernel; + typename Kernel::Equal_2 equal = kernel.equal_2_object(); // Check whether the two curves have the same supporting line. - if (! equal (cv1.supp_line(), cv2.supp_line()) && - ! equal (cv1.supp_line(), - kernel.construct_opposite_line_2_object()(cv2.supp_line()))) - return (false); + if (! equal(cv1.supp_line(), cv2.supp_line()) && + ! equal(cv1.supp_line(), + kernel.construct_opposite_line_2_object()(cv2.supp_line()))) + return false; // Check whether the left endpoint of one curve is the right endpoint of the // other. return ((cv1.has_right() && cv2.has_left() && - equal (cv1.right(), cv2.left())) || + equal(cv1.right(), cv2.left())) || (cv2.has_right() && cv1.has_left() && - equal (cv2.right(), cv1.left()))); + equal(cv2.right(), cv1.left()))); } }; /*! Obtain an Are_mergeable_2 functor object. */ - Are_mergeable_2 are_mergeable_2_object () const - { - return Are_mergeable_2(); - } + Are_mergeable_2 are_mergeable_2_object () const { return Are_mergeable_2(); } /*! \class Merge_2 * A functor that merges two x-monotone arcs into one. */ - class Merge_2 - { + class Merge_2 { protected: typedef Arr_linear_traits_2 Traits; /*! The traits (in case it has state) */ - const Traits* m_traits; + const Traits& m_traits; /*! Constructor * \param traits the traits (in case it has state) */ - Merge_2(const Traits* traits) : m_traits(traits) {} + Merge_2(const Traits& traits) : m_traits(traits) {} friend class Arr_linear_traits_2; public: - /*! - * Merge two given x-monotone curves into a single curve (segment). + /*! Merge two given x-monotone curves into a single curve (segment). * \param cv1 The first curve. * \param cv2 The second curve. * \param c Output: The merged curve. * \pre The two curves are mergeable. */ - void operator() (const X_monotone_curve_2& cv1, - const X_monotone_curve_2& cv2, - X_monotone_curve_2& c) const + void operator()(const X_monotone_curve_2& cv1, + const X_monotone_curve_2& cv2, + X_monotone_curve_2& c) const { - CGAL_precondition(m_traits->are_mergeable_2_object()(cv2, cv1)); + CGAL_precondition(m_traits.are_mergeable_2_object()(cv2, cv1)); CGAL_precondition(!cv1.is_degenerate()); CGAL_precondition(!cv2.is_degenerate()); - Equal_2 equal = m_traits->equal_2_object(); + Equal_2 equal = m_traits.equal_2_object(); // Check which curve extends to the right of the other. if (cv1.has_right() && cv2.has_left() && @@ -1685,10 +1495,8 @@ public: // cv2 extends cv1 to the right. c = cv1; - if (cv2.has_right()) - c.set_right(cv2.right()); - else - c.set_right(); // Unbounded endpoint. + if (cv2.has_right()) c.set_right(cv2.right()); + else c.set_right(); // Unbounded endpoint. } else { CGAL_precondition(cv2.has_right() && cv1.has_left() && @@ -1697,87 +1505,67 @@ public: // cv1 extends cv2 to the right. c = cv2; - if (cv1.has_right()) - c.set_right(cv1.right()); - else - c.set_right(); // Unbounded endpoint. + if (cv1.has_right()) c.set_right(cv1.right()); + else c.set_right(); // Unbounded endpoint. } } }; /*! Obtain a Merge_2 functor object. */ - Merge_2 merge_2_object () const { return Merge_2(this); } + Merge_2 merge_2_object() const { return Merge_2(*this); } //@} /// \name Functor definitions for the landmarks point-location strategy. //@{ typedef double Approximate_number_type; - class Approximate_2 - { + class Approximate_2 { public: - - /*! - * Return an approximation of a point coordinate. + /*! Obtain an approximation of a point coordinate. * \param p The exact point. * \param i The coordinate index (either 0 or 1). * \pre i is either 0 or 1. * \return An approximation of p's x-coordinate (if i == 0), or an * approximation of p's y-coordinate (if i == 1). */ - Approximate_number_type operator() (const Point_2& p, - int i) const + Approximate_number_type operator()(const Point_2& p, int i) const { - CGAL_precondition (i == 0 || i == 1); - - if (i == 0) - return (CGAL::to_double(p.x())); - else - return (CGAL::to_double(p.y())); + CGAL_precondition((i == 0) || (i == 1)); + return (i == 0) ? CGAL::to_double(p.x()) : CGAL::to_double(p.y()); } }; /*! Obtain an Approximate_2 functor object. */ - Approximate_2 approximate_2_object () const - { - return Approximate_2(); - } + Approximate_2 approximate_2_object() const { return Approximate_2(); } - class Construct_x_monotone_curve_2 - { + class Construct_x_monotone_curve_2 { public: - - /*! - * Return an x-monotone curve connecting the two given endpoints. + /*! Obtain an x-monotone curve connecting the two given endpoints. * \param p The first point. * \param q The second point. * \pre p and q must not be the same. * \return A segment connecting p and q. */ - X_monotone_curve_2 operator() (const Point_2& p, - const Point_2& q) const + X_monotone_curve_2 operator()(const Point_2& p, const Point_2& q) const { - Kernel kernel; - Segment_2 seg = kernel.construct_segment_2_object() (p, q); + Kernel kernel; + Segment_2 seg = kernel.construct_segment_2_object()(p, q); - return (X_monotone_curve_2 (seg)); + return (X_monotone_curve_2(seg)); } }; /*! Obtain a Construct_x_monotone_curve_2 functor object. */ - Construct_x_monotone_curve_2 construct_x_monotone_curve_2_object () const - { - return Construct_x_monotone_curve_2(); - } + Construct_x_monotone_curve_2 construct_x_monotone_curve_2_object() const + { return Construct_x_monotone_curve_2(); } //@} - }; /*! * \class A representation of a segment, as used by the Arr_segment_traits_2 * traits-class. */ -template +template class Arr_linear_object_2 : public Arr_linear_traits_2::_Linear_object_cached_2 { @@ -1785,7 +1573,6 @@ class Arr_linear_object_2 : Base; public: - typedef Kernel_ Kernel; typedef typename Kernel::Point_2 Point_2; @@ -1794,121 +1581,92 @@ public: typedef typename Kernel::Line_2 Line_2; public: - - /*! - * Default constructor. + /*! Default constructor. */ - Arr_linear_object_2 () : - Base() - {} + Arr_linear_object_2() : Base() {} - /*! - * Constructor from two points. + /*! Constructor from two points. * \param s The source point. * \param t The target point. * \pre The two points must not be the same. */ - Arr_linear_object_2(const Point_2& s, const Point_2& t): - Base(s, t) - {} + Arr_linear_object_2(const Point_2& s, const Point_2& t) : Base(s, t) {} - /*! - * Constructor from a segment. + /*! Constructor from a segment. * \param seg The segment. * \pre The segment is not degenerate. */ - Arr_linear_object_2 (const Segment_2& seg) : - Base (seg) - {} + Arr_linear_object_2(const Segment_2& seg) : Base(seg) {} - /*! - * Constructor from a ray. + /*! Constructor from a ray. * \param ray The segment. * \pre The ray is not degenerate. */ - Arr_linear_object_2 (const Ray_2& ray) : - Base (ray) - {} + Arr_linear_object_2(const Ray_2& ray) : Base(ray) {} - /*! - * Constructor from a line. + /*! Constructor from a line. * \param line The line. * \pre The line is not degenerate. */ - Arr_linear_object_2 (const Line_2& line) : - Base (line) - {} + Arr_linear_object_2(const Line_2& line) : Base(line) {} - /*! - * Check whether the object is actually a segment. + /*! Check whether the object is actually a segment. */ - bool is_segment () const - { - return (! this->is_degen && this->has_source && this->has_target); - } + bool is_segment() const + { return (! this->is_degen && this->has_source && this->has_target); } - /*! - * Cast to a segment. + /*! Cast to a segment. * \pre The linear object is really a segment. */ - Segment_2 segment () const + Segment_2 segment() const { - CGAL_precondition (is_segment()); + CGAL_precondition(is_segment()); - Kernel kernel; - Segment_2 seg = kernel.construct_segment_2_object() (this->ps, this->pt); + Kernel kernel; + Segment_2 seg = kernel.construct_segment_2_object()(this->ps, this->pt); return seg; } - /*! - * Check whether the object is actually a ray. + /*! Check whether the object is actually a ray. */ - bool is_ray () const - { - return (! this->is_degen && (this->has_source != this->has_target)); - } + bool is_ray() const + { return (! this->is_degen && (this->has_source != this->has_target)); } - /*! - * Cast to a ray. + /*! Cast to a ray. * \pre The linear object is really a ray. */ - Ray_2 ray () const + Ray_2 ray() const { - CGAL_precondition (is_ray()); + CGAL_precondition(is_ray()); - Kernel kernel; - Ray_2 ray = (this->has_source) ? - kernel.construct_ray_2_object() (this->ps, this->l) : + Kernel kernel; + Ray_2 ray = (this->has_source) ? + kernel.construct_ray_2_object()(this->ps, this->l) : kernel.construct_ray_2_object() (this->pt, kernel.construct_opposite_line_2_object()(this->l)); return ray; } - /*! - * Check whether the object is actually a line. + /*! Check whether the object is actually a line. */ - bool is_line () const - { - return (! this->is_degen && ! this->has_source && ! this->has_target); - } + bool is_line() const + { return (! this->is_degen && ! this->has_source && ! this->has_target); } - /*! - * Cast to a line. + /*! Cast to a line. * \pre The linear object is really a line. */ - Line_2 line () const + Line_2 line() const { - CGAL_precondition (is_line()); + CGAL_precondition(is_line()); return (this->l); } - /*! - * Get the supporting line. + /*! Get the supporting line. * \pre The object is not a point. */ - const Line_2& supporting_line () const + const Line_2& supporting_line() const { - CGAL_precondition (! this->is_degen); + CGAL_precondition(! this->is_degen); return (this->l); } @@ -1918,37 +1676,30 @@ public: */ const Point_2& source() const { - CGAL_precondition (! is_line()); + CGAL_precondition(! is_line()); - if (this->is_degen) - return (this->ps); // For a point. - - if (this->has_source) - return (this->ps); // For a segment or a ray. - else - return (this->pt); // For a "flipped" ray. + if (this->is_degen) return (this->ps); // For a point. + if (this->has_source) return (this->ps); // For a segment or a ray. + else return (this->pt); // For a "flipped" ray. } - /*! - * Get the target point. + /*! Get the target point. * \pre The object is a point or a segment. */ const Point_2& target() const { - CGAL_precondition (! is_line() && ! is_ray()); - + CGAL_precondition(! is_line() && ! is_ray()); return (this->pt); } - /*! - * Create a bounding box for the linear object. + /*! Create a bounding box for the linear object. */ Bbox_2 bbox() const { CGAL_precondition(this->is_segment()); - Kernel kernel; - Segment_2 seg = kernel.construct_segment_2_object() (this->ps, this->pt); - return (kernel.construct_bbox_2_object() (seg)); + Kernel kernel; + Segment_2 seg = kernel.construct_segment_2_object()(this->ps, this->pt); + return (kernel.construct_bbox_2_object()(seg)); } // Introducing casting operators instead from a curve to @@ -1962,58 +1713,49 @@ public: /*! * Exporter for the segment class used by the traits-class. */ -template -OutputStream& operator<< (OutputStream& os, - const Arr_linear_object_2& lobj) +template +OutputStream& operator<<(OutputStream& os, + const Arr_linear_object_2& lobj) { // Print a letter identifying the object type, then the object itself. - if (lobj.is_segment()) - os << " S " << lobj.segment(); - else if (lobj.is_ray()) - os << " R " << lobj.ray(); - else - os << " L " << lobj.line(); - - return (os); + if (lobj.is_segment()) os << " S " << lobj.segment(); + else if (lobj.is_ray()) os << " R " << lobj.ray(); + else os << " L " << lobj.line(); + return os; } -/*! - * Importer for the segment class used by the traits-class. +/*! Importer for the segment class used by the traits-class. */ -template -InputStream& operator>> (InputStream& is, Arr_linear_object_2& lobj) +template +InputStream& operator>>(InputStream& is, Arr_linear_object_2& lobj) { // Read the object type. - char c; + char c; - do - { + do { is >> c; } while ((c != 'S' && c != 's') && (c != 'R' && c != 'r') && (c != 'L' && c != 'l')); // Read the object accordingly. - if (c == 'S' || c == 's') - { + if (c == 'S' || c == 's') { typename Kernel::Segment_2 seg; is >> seg; lobj = seg; } - else if (c == 'R' || c == 'r') - { - typename Kernel::Ray_2 ray; + else if (c == 'R' || c == 'r') { + typename Kernel::Ray_2 ray; is >> ray; lobj = ray; } - else - { - typename Kernel::Line_2 line; + else { + typename Kernel::Line_2 line; is >> line; lobj = line; } - return (is); + return is; } } //namespace CGAL diff --git a/Arrangement_on_surface_2/include/CGAL/Arr_non_caching_segment_traits_2.h b/Arrangement_on_surface_2/include/CGAL/Arr_non_caching_segment_traits_2.h index aa3483255de..3df642ba1e7 100644 --- a/Arrangement_on_surface_2/include/CGAL/Arr_non_caching_segment_traits_2.h +++ b/Arrangement_on_surface_2/include/CGAL/Arr_non_caching_segment_traits_2.h @@ -27,7 +27,6 @@ * functors required by the concept it models. */ -#include #include #include @@ -223,8 +222,7 @@ public: { typedef std::pair Intersection_point; typedef boost::variant - Intersection_variant; - typedef boost::optional Intersection_result; + Intersection_result; const Kernel& kernel = m_traits; auto res = kernel.intersect_2_object()(cv1, cv2); @@ -233,21 +231,20 @@ public: if (! res) return oi; // Chack if the intersection is a point: - const Point_2* ip = boost::get(&*res); - if (ip != nullptr) { + const Point_2* p_p = boost::get(&*res); + if (p_p != nullptr) { // Create a pair representing the point with its multiplicity, // which is always 1 for line segments for all practical purposes. // If the two segments intersect at their endpoints, then the // multiplicity is undefined, but we deliberately ignore it for // efficieny reasons. - Intersection_point ip_mult(*ip, 1); - *oi++ = Intersection_result(ip_mult); + *oi++ = Intersection_result(Intersection_point(*p_p, 1)); return oi; } // The intersection is a segment. - const X_monotone_curve_2* ov = boost::get(&*res); - CGAL_assertion(ov != nullptr); + const X_monotone_curve_2* cv_p = boost::get(&*res); + CGAL_assertion(cv_p != nullptr); Comparison_result cmp1 = m_traits.compare_endpoints_xy_2_object()(cv1); Comparison_result cmp2 = m_traits.compare_endpoints_xy_2_object()(cv2); @@ -255,13 +252,13 @@ public: if (cmp1 == cmp2) { // cv1 and cv2 have the same directions, maintain this direction // in the overlap segment - if (m_traits.compare_endpoints_xy_2_object()(*ov) != cmp1) { + if (m_traits.compare_endpoints_xy_2_object()(*cv_p) != cmp1) { auto ctr_opposite = kernel.construct_opposite_segment_2_object(); - res = Intersection_result(ctr_opposite(*ov)); + *oi++ = Intersection_result(ctr_opposite(*cv_p)); + return oi; } } - - *oi++ = res; + *oi++ = Intersection_result(*cv_p); return oi; } }; diff --git a/Arrangement_on_surface_2/include/CGAL/Arr_polycurve_traits_2.h b/Arrangement_on_surface_2/include/CGAL/Arr_polycurve_traits_2.h index e99c306a1e0..59a6be2c319 100644 --- a/Arrangement_on_surface_2/include/CGAL/Arr_polycurve_traits_2.h +++ b/Arrangement_on_surface_2/include/CGAL/Arr_polycurve_traits_2.h @@ -193,13 +193,12 @@ public: // If the polycurve is empty, return. if (cv.number_of_subcurves() == 0) return oi; - Construct_x_monotone_curve_2 ctr_x_curve = - m_poly_traits.construct_x_monotone_curve_2_object(); + auto ctr_x_curve = m_poly_traits.construct_x_monotone_curve_2_object(); - typename Subcurve_traits_2::Make_x_monotone_2 make_seg_x_monotone = + auto make_seg_x_monotone = m_poly_traits.subcurve_traits_2()->make_x_monotone_2_object(); - typename Subcurve_traits_2::Compare_endpoints_xy_2 cmp_seg_endpts = + auto cmp_seg_endpts = m_poly_traits.subcurve_traits_2()->compare_endpoints_xy_2_object(); #ifdef CGAL_ALWAYS_LEFT_TO_RIGHT @@ -238,12 +237,11 @@ public: ( // To be used in order to verify continuity and well-orientedness // of the input curve cv. - typename Subcurve_traits_2::Construct_min_vertex_2 min_seg_v = + auto min_seg_v = m_poly_traits.subcurve_traits_2()->construct_min_vertex_2_object(); - typename Subcurve_traits_2::Construct_max_vertex_2 max_seg_v = + auto max_seg_v = m_poly_traits.subcurve_traits_2()->construct_max_vertex_2_object(); - typename Subcurve_traits_2::Equal_2 equal = - m_poly_traits.subcurve_traits_2()->equal_2_object(); + auto equal = m_poly_traits.subcurve_traits_2()->equal_2_object(); Point_2 last_target = (cmp_seg_endpts(x_seg) == SMALLER) ? max_seg_v(x_seg) : min_seg_v(x_seg); Point_2 next_src; @@ -329,19 +327,18 @@ public: // If the polycurve is empty, return. if (cv.number_of_subcurves() == 0) return oi; - Construct_x_monotone_curve_2 ctr_x_curve = - m_poly_traits.construct_x_monotone_curve_2_object(); + auto ctr_x_curve = m_poly_traits.construct_x_monotone_curve_2_object(); - typename Subcurve_traits_2::Make_x_monotone_2 make_seg_x_monotone = + auto make_seg_x_monotone = m_poly_traits.subcurve_traits_2()->make_x_monotone_2_object(); - typename Subcurve_traits_2::Compare_endpoints_xy_2 cmp_seg_endpts = + auto cmp_seg_endpts = m_poly_traits.subcurve_traits_2()->compare_endpoints_xy_2_object(); - typename Subcurve_traits_2::Parameter_space_in_x_2 ps_x = - m_poly_traits.subcurve_traits_2()->parameter_space_in_x_2_object(); - typename Subcurve_traits_2::Parameter_space_in_y_2 ps_y = - m_poly_traits.subcurve_traits_2()->parameter_space_in_y_2_object(); + auto ps_x = + m_poly_traits.subcurve_traits_2()->parameter_space_in_x_2_object(); + auto ps_y = + m_poly_traits.subcurve_traits_2()->parameter_space_in_y_2_object(); #ifdef CGAL_ALWAYS_LEFT_TO_RIGHT typename Subcurve_traits_2::Construct_opposite_2 ctr_seg_opposite = @@ -379,12 +376,11 @@ public: ( // To be used in order to verify continuity and well-orientedness // of the input curve cv. - typename Subcurve_traits_2::Construct_min_vertex_2 min_seg_v = + auto min_seg_v = m_poly_traits.subcurve_traits_2()->construct_min_vertex_2_object(); - typename Subcurve_traits_2::Construct_max_vertex_2 max_seg_v = + auto max_seg_v = m_poly_traits.subcurve_traits_2()->construct_max_vertex_2_object(); - typename Subcurve_traits_2::Equal_2 equal = - m_poly_traits.subcurve_traits_2()->equal_2_object(); + auto equal = m_poly_traits.subcurve_traits_2()->equal_2_object(); Point_2 last_target = (cmp_seg_endpts(x_seg) == SMALLER) ? max_seg_v(x_seg) : min_seg_v(x_seg); Point_2 next_src; @@ -498,9 +494,7 @@ public: public: /*! Constructor. */ - Push_back_2(const Polycurve_traits_2& traits) : - Base::Push_back_2(traits) - {} + Push_back_2(const Polycurve_traits_2& traits) : Base::Push_back_2(traits) {} // Normally, the moment the compiler finds a name, it stops looking. In // other words, the compiler first finds the operator() in the current @@ -584,20 +578,16 @@ public: X_monotone_curve_2& xcv1, X_monotone_curve_2& xcv2) const { const Subcurve_traits_2* geom_traits = m_poly_traits.subcurve_traits_2(); - typename Subcurve_traits_2::Construct_min_vertex_2 min_vertex = - geom_traits->construct_min_vertex_2_object(); - typename Subcurve_traits_2::Construct_max_vertex_2 max_vertex = - geom_traits->construct_max_vertex_2_object(); - typename Subcurve_traits_2::Equal_2 equal = - geom_traits->equal_2_object(); - typename Subcurve_traits_2::Compare_endpoints_xy_2 cmp_seg_endpts = - geom_traits->compare_endpoints_xy_2_object(); + auto min_vertex = geom_traits->construct_min_vertex_2_object(); + auto max_vertex = geom_traits->construct_max_vertex_2_object(); + auto equal = geom_traits->equal_2_object(); + auto cmp_seg_endpts = geom_traits->compare_endpoints_xy_2_object(); // Make sure the split point is not one of the curve endpoints. - CGAL_precondition((!equal(m_poly_traits. - construct_min_vertex_2_object()(xcv), p))); - CGAL_precondition((!equal(m_poly_traits. - construct_max_vertex_2_object()(xcv), p))); + CGAL_precondition((! equal(m_poly_traits. + construct_min_vertex_2_object()(xcv), p))); + CGAL_precondition((! equal(m_poly_traits. + construct_max_vertex_2_object()(xcv), p))); CGAL_precondition_msg(xcv.number_of_subcurves() > 0, "Cannot split a polycurve of length zero."); @@ -709,22 +699,20 @@ public: const X_monotone_curve_2& cv2, OutputIterator oi) const { - const Subcurve_traits_2* geom_traits = m_poly_traits.subcurve_traits_2(); - Compare_y_at_x_2 cmp_y_at_x = m_poly_traits.compare_y_at_x_2_object(); - typename Subcurve_traits_2::Equal_2 equal = - geom_traits->equal_2_object(); - typename Subcurve_traits_2::Construct_min_vertex_2 min_vertex = - geom_traits->construct_min_vertex_2_object(); - typename Subcurve_traits_2::Construct_max_vertex_2 max_vertex = - geom_traits->construct_max_vertex_2_object(); - typename Subcurve_traits_2::Intersect_2 intersect = - geom_traits->intersect_2_object(); - typename Subcurve_traits_2::Compare_endpoints_xy_2 cmp_seg_endpts = - geom_traits->compare_endpoints_xy_2_object(); - typename Subcurve_traits_2::Construct_opposite_2 construct_opposite = - geom_traits->construct_opposite_2_object(); + typedef std::pair Intersection_point; + typedef boost::variant + Intersection_base_result; + typedef boost::variant + Intersection_result; - typedef std::pair Point_2_pair; + const Subcurve_traits_2* geom_traits = m_poly_traits.subcurve_traits_2(); + auto cmp_y_at_x = m_poly_traits.compare_y_at_x_2_object(); + auto equal = geom_traits->equal_2_object(); + auto min_vertex = geom_traits->construct_min_vertex_2_object(); + auto max_vertex = geom_traits->construct_max_vertex_2_object(); + auto intersect = geom_traits->intersect_2_object(); + auto cmp_seg_endpts = geom_traits->compare_endpoints_xy_2_object(); + auto construct_opposite = geom_traits->construct_opposite_2_object(); Comparison_result dir1 = cmp_seg_endpts(cv1[0]); Comparison_result dir2 = cmp_seg_endpts(cv2[0]); @@ -737,7 +725,7 @@ public: X_monotone_curve_2 ocv; // Used to represent overlaps. - Compare_xy_2 compare_xy = m_poly_traits.compare_xy_2_object(); + auto compare_xy = m_poly_traits.compare_xy_2_object(); Comparison_result left_res = compare_xy(cv1[i1], ARR_MIN_END, cv2[i2], ARR_MIN_END); @@ -754,12 +742,13 @@ public: ((dir1 == LARGER) && (i1 == 0))){ // cv1's right endpoint equals cv2's left endpoint // Thus we can return this single(!) intersection point - std::pair p(max_vertex(cv1[i1]), 0); - *oi++ = make_object(p); + Intersection_point p(max_vertex(cv1[i1]), 0); + *oi++ = Intersection_result(p); return oi; } dir1 == SMALLER ? - ++i1 : (i1 != 0) ? --i1 : (std::size_t) Polycurve_traits_2::INVALID_INDEX; + ++i1 : + (i1 != 0) ? --i1 : (std::size_t) Polycurve_traits_2::INVALID_INDEX; left_res = EQUAL; } } @@ -776,13 +765,14 @@ public: ((dir2 == LARGER) && (i2 == 0))){ // cv2's right endpoint equals cv1's left endpoint // Thus we can return this single(!) intersection point - std::pair p(max_vertex(cv2[i2]), 0); - *oi++ = make_object(p); + Intersection_point p(max_vertex(cv2[i2]), 0); + *oi++ = Intersection_result(p); return oi; } dir2 == SMALLER ? - ++i2 : (i2 != 0) ? --i2 : (std::size_t) Polycurve_traits_2::INVALID_INDEX; + ++i2 : + (i2 != 0) ? --i2 : (std::size_t) Polycurve_traits_2::INVALID_INDEX; left_res = EQUAL; } } @@ -823,48 +813,64 @@ public: right_overlap = false; - if (!right_coincides && !left_coincides) { + //! EF: the following code is abit suspicious. It may erroneously + // assume that the subcurves cannot overlap more than once. + if (! right_coincides && ! left_coincides) { // Non of the endpoints of the current subcurve of one polycurve // coincides with the curent subcurve of the other polycurve: // Output the intersection if exists. - oi = intersect(cv1[i1], cv2[i2], oi); + std::vector xections; + intersect(cv1[i1], cv2[i2], std::back_inserter(xections)); + for (const auto& xection : xections) { + const X_monotone_subcurve_2* subcv_p = + boost::get(&xection); + if (subcv_p != nullptr) { + ocv.push_back(*subcv_p); + *oi++ = Intersection_result(ocv); + ocv.clear(); + continue; + } + + const Intersection_point* p_p = + boost::get(&xection); + if (p_p != nullptr) *oi++ = Intersection_result(*p_p); + } } else if (right_coincides && left_coincides) { // An overlap exists between the current subcurves of the // polycurves: Output the overlapping subcurve. right_overlap = true; - std::vector int_seg; - intersect(cv1[i1], cv2[i2], std::back_inserter(int_seg)); + std::vector sub_xections; + intersect(cv1[i1], cv2[i2], std::back_inserter(sub_xections)); - for (size_t i = 0; i < int_seg.size(); ++i) { + for (const auto& item : sub_xections) { const X_monotone_subcurve_2* x_seg = - CGAL::object_cast (&(int_seg[i])); + boost::get(&item); if (x_seg != nullptr) { X_monotone_subcurve_2 seg = *x_seg; // If for some reason the subcurve intersection // results in left oriented curve. - if ( cmp_seg_endpts(seg) == LARGER) - seg = construct_opposite(seg); + if (cmp_seg_endpts(seg) == LARGER) seg = construct_opposite(seg); ocv.push_back(seg); } - const Point_2_pair* p_ptr = - CGAL::object_cast(&(int_seg[i])); + const Intersection_point* p_ptr = + boost::get(&item); if (p_ptr != nullptr) { // Any point that is not equal to the max_vertex of the // subcurve should be inserted into oi. // The max_vertex of the current subcurve (if intersecting) // will be taken care of as the min_vertex of in the next // iteration. - if (!equal(p_ptr->first, max_vertex(cv1[i1]))) - *oi++ = make_object(*p_ptr); + if (! equal(p_ptr->first, max_vertex(cv1[i1]))) + *oi++ = Intersection_result(*p_ptr); } } } - else if (left_coincides && !right_coincides) { + else if (left_coincides && ! right_coincides) { // std::cout << "Left is coinciding but right is not." << std::endl; // The left point of the current subcurve of one polycurve // coincides with the current subcurve of the other polycurve. @@ -872,7 +878,7 @@ public: // An overlap occurred at the previous iteration: // Output the overlapping polycurve. CGAL_assertion(ocv.number_of_subcurves() > 0); - *oi++ = make_object(ocv); + *oi++ = Intersection_result(ocv); ocv.clear(); } else { @@ -884,12 +890,12 @@ public: // polycurves is not defined at this point, so we give // it multiplicity 0. if (left_res == SMALLER) { - std::pair p(min_vertex(cv2[i2]), 0); - *oi++ = make_object(p); + Intersection_point p(min_vertex(cv2[i2]), 0); + *oi++ = Intersection_result(p); } else { - std::pair p(min_vertex(cv1[i1]), 0); - *oi++ = make_object(p); + Intersection_point p(min_vertex(cv1[i1]), 0); + *oi++ = Intersection_result(p); } } } @@ -919,7 +925,7 @@ public: // Output the remaining overlapping polycurve, if necessary. if (ocv.number_of_subcurves() > 0) { - *oi++ = make_object(ocv); + *oi++ = Intersection_result(ocv); } else if (right_coincides) { typedef std::pair return_point; @@ -930,7 +936,7 @@ public: (i1 != Polycurve_traits_2::INVALID_INDEX) ? return_point(max_vertex(cv1[i1+1]), 0) : return_point(max_vertex(cv1[0]), 0); - *oi++ = make_object(ip); + *oi++ = Intersection_result(ip); } else if (right_res == LARGER) { ip = (dir2 == SMALLER) ? @@ -938,7 +944,7 @@ public: (i2 != Polycurve_traits_2::INVALID_INDEX) ? return_point(max_vertex(cv2[i2+1]), 0) : return_point(max_vertex(cv2[0]), 0); - *oi++ = make_object(ip); + *oi++ = Intersection_result(ip); } else if (((i1 > 0) && (dir1 == SMALLER)) || ((i1 < n1) && (dir1 != SMALLER)) || @@ -950,7 +956,7 @@ public: (i1 != Polycurve_traits_2::INVALID_INDEX) ? return_point(max_vertex(cv1[i1+1]), 0) : return_point(max_vertex(cv1[0]), 0); - *oi++ = make_object(ip); + *oi++ = Intersection_result(ip); } else { CGAL_assertion_msg((dir2 == SMALLER && i2 > 0) || @@ -965,7 +971,7 @@ public: (i2 != Polycurve_traits_2::INVALID_INDEX) ? return_point(max_vertex(cv2[i2+1]), 0) : return_point(max_vertex(cv2[0]), 0); - *oi++ = make_object(ip); + *oi++ = Intersection_result(ip); } } diff --git a/Arrangement_on_surface_2/include/CGAL/Arr_rat_arc/Rational_arc_d_1.h b/Arrangement_on_surface_2/include/CGAL/Arr_rat_arc/Rational_arc_d_1.h index e2010a578ec..7d253018be3 100644 --- a/Arrangement_on_surface_2/include/CGAL/Arr_rat_arc/Rational_arc_d_1.h +++ b/Arrangement_on_surface_2/include/CGAL/Arr_rat_arc/Rational_arc_d_1.h @@ -1848,8 +1848,8 @@ public: typedef typename Base::Cache Cache; - typedef std::pair Intersection_point_2; - //typedef std::pair Intersection_point_2; + typedef std::pair Intersection_point; + //typedef std::pair Intersection_point; /// \name Constrcution methods. @@ -2029,8 +2029,7 @@ public: /// \name Constructions of points and curves. //@{ - /*! - * Compute the intersections with the given arc. + /*! Compute the intersections with the given arc. * \param arc The given intersecting arc. * \param oi The output iterator. * \return The past-the-end iterator. @@ -2039,33 +2038,31 @@ public: OutputIterator intersect(const Self& arc, OutputIterator oi, const Cache& cache) const { + typedef boost::variant Intersection_result; + CGAL_precondition(this->is_valid() && this->is_continuous()); CGAL_precondition(arc.is_valid() && arc.is_continuous()); - if (this->equals(arc)) - { - Self overlap_arc(*this); - *oi++ = make_object(overlap_arc); - return (oi); + if (this->equals(arc)) { + Self overlap_arc(*this); + *oi++ = Intersection_result(overlap_arc); + return oi; } - if (this->_has_same_base(arc)) - { + if (this->_has_same_base(arc)) { // Get the left and right endpoints of (*this) and their information // bits. - const Algebraic_point_2& left1 = (this->is_directed_right() ? - this->_ps : this->_pt); - const Algebraic_point_2& right1 = (this->is_directed_right() ? - this->_pt : this->_ps); - int info_left1, info_right1; + const Algebraic_point_2& left1 = + (this->is_directed_right() ? this->_ps : this->_pt); + const Algebraic_point_2& right1 = + (this->is_directed_right() ? this->_pt : this->_ps); + int info_left1, info_right1; - if (this->is_directed_right()) - { + if (this->is_directed_right()) { info_left1 = (this->_info & this->SRC_INFO_BITS); info_right1 = ((this->_info & this->TRG_INFO_BITS) >> 4); } - else - { + else { info_right1 = (this->_info & this->SRC_INFO_BITS); info_left1 = ((this->_info & this->TRG_INFO_BITS) >> 4); } @@ -2076,110 +2073,93 @@ public: (arc.is_directed_right() ? arc._ps : arc._pt); const Algebraic_point_2& right2 = (arc.is_directed_right() ? arc._pt : arc._ps); - int info_left2, info_right2; + int info_left2, info_right2; - if (arc.is_directed_right()) - { + if (arc.is_directed_right()) { info_left2 = (arc._info & this->SRC_INFO_BITS); info_right2 = ((arc._info & this->TRG_INFO_BITS) >> 4); } - else - { + else { info_right2 = (arc._info & this->SRC_INFO_BITS); info_left2 = ((arc._info & this->TRG_INFO_BITS) >> 4); } // Locate the left curve-end with larger x-coordinate. - bool at_minus_infinity = false; - Arr_parameter_space inf_l1 = this->left_parameter_space_in_x(); - Arr_parameter_space inf_l2 = arc.left_parameter_space_in_x(); - Algebraic_point_2 p_left; - int info_left; + bool at_minus_infinity = false; + Arr_parameter_space inf_l1 = this->left_parameter_space_in_x(); + Arr_parameter_space inf_l2 = arc.left_parameter_space_in_x(); + Algebraic_point_2 p_left; + int info_left; - if (inf_l1 == ARR_INTERIOR && inf_l2 == ARR_INTERIOR) - { + if (inf_l1 == ARR_INTERIOR && inf_l2 == ARR_INTERIOR) { // Let p_left be the rightmost of the two left endpoints. - if (left1.x() > left2.x()) - { + if (left1.x() > left2.x()) { p_left = left1; info_left = info_left1; } - else - { + else { p_left = left2; info_left = info_left2; } } - else if (inf_l1 == ARR_INTERIOR) - { + else if (inf_l1 == ARR_INTERIOR) { // Let p_left be the left endpoint of (*this). p_left = left1; info_left = info_left1; } - else if (inf_l2 == ARR_INTERIOR) - { + else if (inf_l2 == ARR_INTERIOR) { // Let p_left be the left endpoint of the other arc. p_left = left2; info_left = info_left2; } - else - { + else { // Both arcs are defined at x = -oo. at_minus_infinity = true; info_left = info_left1; } // Locate the right curve-end with smaller x-coordinate. - bool at_plus_infinity = false; - Arr_parameter_space inf_r1 = this->right_parameter_space_in_x(); - Arr_parameter_space inf_r2 = arc.right_parameter_space_in_x(); - Algebraic_point_2 p_right; - int info_right; + bool at_plus_infinity = false; + Arr_parameter_space inf_r1 = this->right_parameter_space_in_x(); + Arr_parameter_space inf_r2 = arc.right_parameter_space_in_x(); + Algebraic_point_2 p_right; + int info_right; - if (inf_r1 == ARR_INTERIOR && inf_r2 == ARR_INTERIOR) - { + if (inf_r1 == ARR_INTERIOR && inf_r2 == ARR_INTERIOR) { // Let p_right be the rightmost of the two right endpoints. - if (right1.x() < right2.x()) - { + if (right1.x() < right2.x()) { p_right = right1; info_right = info_right1; } - else - { + else { p_right = right2; info_right = info_right2; } } - else if (inf_r1 == ARR_INTERIOR) - { + else if (inf_r1 == ARR_INTERIOR) { // Let p_right be the right endpoint of (*this). p_right = right1; info_right = info_right1; } - else if (inf_r2 == ARR_INTERIOR) - { + else if (inf_r2 == ARR_INTERIOR) { // Let p_right be the right endpoint of the other arc. p_right = right2; info_right = info_right2; } - else - { + else { // Both arcs are defined at x = +oo. at_plus_infinity = true; info_right = info_right2; } // Check the case of two bounded (in x) ends. - if (! at_minus_infinity && ! at_plus_infinity) - { + if (! at_minus_infinity && ! at_plus_infinity) { Comparison_result res = CGAL::compare(p_left.x(), p_right.x()); - if (res == LARGER) - { - // The x-range of the overlap is empty, so there is no overlap. - return (oi); - } - else if (res == EQUAL) - { + + // The x-range of the overlap is empty, so there is no overlap. + if (res == LARGER) return oi; + + if (res == EQUAL) { // We have a single overlapping point. Just make sure this point // is not at y = -/+ oo. if (info_left && @@ -2187,19 +2167,18 @@ public: info_right && (this->SRC_AT_Y_MINUS_INFTY | this->SRC_AT_Y_PLUS_INFTY) == 0) { - Intersection_point_2 ip(p_left, 0); - - *oi++ = make_object(ip); + Intersection_point ip(p_left, 0); + *oi++ = Intersection_result(ip); } - return (oi); + return oi; } } // Create the overlapping portion of the rational arc by properly setting // the source (left) and target (right) endpoints and their information // bits. - Self overlap_arc(*this); + Self overlap_arc(*this); overlap_arc._ps = p_left; overlap_arc._pt = p_right; @@ -2208,8 +2187,8 @@ public: this->IS_DIRECTED_RIGHT | this->IS_CONTINUOUS | this->IS_VALID); - *oi++ = make_object(overlap_arc); - return (oi); + *oi++ = Intersection_result(overlap_arc); + return oi; } // We wish to find the intersection points between: @@ -2237,15 +2216,14 @@ public: if (this->_is_in_true_x_range(*x_iter) && arc._is_in_true_x_range(*x_iter)) { // Compute the intersection point and obtain its multiplicity. - Algebraic_point_2 p(this->_f, *x_iter); + Algebraic_point_2 p(this->_f, *x_iter); // Output the intersection point: - Intersection_point_2 ip(p, *m_iter); - - *oi++ = make_object(ip); + Intersection_point ip(p, *m_iter); + *oi++ = Intersection_result(ip); } } - return (oi); + return oi; } /*! @@ -2255,7 +2233,8 @@ public: * \param c2 Output: The first resulting arc, lying to the right of p. * \pre p lies in the interior of the arc (not one of its endpoints). */ - void split(const Algebraic_point_2& p, Self& c1, Self& c2, const Cache& CGAL_assertion_code(cache)) const + void split(const Algebraic_point_2& p, Self& c1, Self& c2, + const Cache& CGAL_assertion_code(cache)) const { CGAL_precondition(this->is_valid() && this->is_continuous()); @@ -2598,4 +2577,3 @@ public: } //namespace CGAL { #endif //CGAL_RATIONAL_ARC_D_1_H - diff --git a/Arrangement_on_surface_2/include/CGAL/Arr_segment_traits_2.h b/Arrangement_on_surface_2/include/CGAL/Arr_segment_traits_2.h index 955d67ae84f..a671a741f80 100644 --- a/Arrangement_on_surface_2/include/CGAL/Arr_segment_traits_2.h +++ b/Arrangement_on_surface_2/include/CGAL/Arr_segment_traits_2.h @@ -24,7 +24,6 @@ #include -#include #include #include @@ -619,7 +618,7 @@ public: * given output iterator. As segments are always x_monotone, only one * object will be contained in the iterator. * \param cv The curve. - * \param oi The output iterator, whose value-type is optional @@ -710,8 +709,7 @@ public: { typedef std::pair Intersection_point; typedef boost::variant - Intersection_variant; - typedef boost::optional Intersection_result; + Intersection_result; // Intersect the two supporting lines. const Kernel& kernel = m_traits; diff --git a/Arrangement_on_surface_2/include/CGAL/Arr_tracing_traits_2.h b/Arrangement_on_surface_2/include/CGAL/Arr_tracing_traits_2.h index 532b2bf4dbd..9197b38149f 100644 --- a/Arrangement_on_surface_2/include/CGAL/Arr_tracing_traits_2.h +++ b/Arrangement_on_surface_2/include/CGAL/Arr_tracing_traits_2.h @@ -7,7 +7,7 @@ // $Id$ // SPDX-License-Identifier: GPL-3.0-or-later OR LicenseRef-Commercial // -// Author(s) : Efi Fogel +// Author(s): Efi Fogel #ifndef CGAL_ARR_TRACING_TRAITS_H #define CGAL_ARR_TRACING_TRAITS_H @@ -592,7 +592,7 @@ public: public: /*! Construct */ - Intersect_2(const Base * base, bool enabled = true) : + Intersect_2(const Base* base, bool enabled = true) : m_object(base->intersect_2_object()), m_enabled(enabled) {} /*! Operate @@ -604,37 +604,41 @@ public: * multiplicity * \return the output iterator */ - template + template OutputIterator operator()(const X_monotone_curve_2 & xcv1, const X_monotone_curve_2 & xcv2, OutputIterator oi) const { - if (!m_enabled) return m_object(xcv1, xcv2, oi); + typedef std::pair Intersection_point; + typedef boost::variant + Intersection_result; + + if (! m_enabled) return m_object(xcv1, xcv2, oi); + std::cout << "intersect" << std::endl << " xcv1: " << xcv1 << std::endl << " xcv2: " << xcv2 << std::endl; - std::list container; + std::list container; m_object(xcv1, xcv2, std::back_inserter(container)); if (container.empty()) return oi; - std::list::iterator it; unsigned int i = 0; - for (it = container.begin(); it != container.end(); ++it) { - X_monotone_curve_2 xcv; - if (assign (xcv, *it)) { - std::cout << " result[" << i++ << "]: xcv: " << xcv << std::endl; + for (const auto& item : container) { + const X_monotone_curve_2* xcv = boost::get(&item); + if (xcv != nullptr) { + std::cout << " result[" << i++ << "]: xcv: " << *xcv << std::endl; continue; } - std::pair point_pair; - if (assign (point_pair, *it)) { - std::cout << " result[" << i++ << "]: p: " << point_pair.first - << ", multiplicity: " << point_pair.second << std::endl; + const Intersection_point* ip = boost::get(&item); + if (ip != nullptr) { + std::cout << " result[" << i++ << "]: p: " << ip->first + << ", multiplicity: " << ip->second << std::endl; continue; } } - for (it = container.begin(); it != container.end(); ++it) *oi++ = *it; + for (auto it = container.begin(); it != container.end(); ++it) *oi++ = *it; container.clear(); return oi; } diff --git a/Arrangement_on_surface_2/include/CGAL/Arrangement_2/Arrangement_zone_2_impl.h b/Arrangement_on_surface_2/include/CGAL/Arrangement_2/Arrangement_zone_2_impl.h index aa0532cde12..b3d8c63f5b2 100644 --- a/Arrangement_on_surface_2/include/CGAL/Arrangement_2/Arrangement_zone_2_impl.h +++ b/Arrangement_on_surface_2/include/CGAL/Arrangement_2/Arrangement_zone_2_impl.h @@ -132,8 +132,8 @@ void Arrangement_zone_2::compute_zone() // In this case m_cv overlaps the curve associated with m_intersect_he. // Compute the overlapping subcurve. bool dummy; - m_obj = _compute_next_intersection(m_intersect_he, false, dummy); - m_overlap_cv = object_cast(m_obj); + auto obj = _compute_next_intersection(m_intersect_he, false, dummy); + m_overlap_cv = boost::get(*obj); // Remove the overlap from the map. _remove_next_intersection(m_intersect_he); @@ -148,8 +148,8 @@ void Arrangement_zone_2::compute_zone() m_intersect_he = m_arr.non_const_handle(*hh); bool dummy; - m_obj = _compute_next_intersection(m_intersect_he, false, dummy); - m_overlap_cv = object_cast(m_obj); + auto obj = _compute_next_intersection(m_intersect_he, false, dummy); + m_overlap_cv = boost::get(*obj); // Remove the overlap from the map. _remove_next_intersection(m_intersect_he); @@ -207,8 +207,8 @@ void Arrangement_zone_2::compute_zone() // In this case m_cv overlaps the curve associated with m_intersect_he. // Compute the overlapping subcurve to the right of curr_v. bool dummy; - m_obj = _compute_next_intersection(m_intersect_he, false, dummy); - m_overlap_cv = object_cast(m_obj); + auto obj = _compute_next_intersection(m_intersect_he, false, dummy); + m_overlap_cv = boost::get(*obj); // Remove the overlap from the map. _remove_next_intersection(m_intersect_he); @@ -800,7 +800,7 @@ _direct_intersecting_edge_to_left(const X_monotone_curve_2& cv_ins, // Get the next intersection of cv with the given halfedge. // template -CGAL::Object +typename Arrangement_zone_2::Optional_intersection Arrangement_zone_2:: _compute_next_intersection(Halfedge_handle he, bool skip_first_point, @@ -811,7 +811,7 @@ _compute_next_intersection(Halfedge_handle he, // Try to locate the intersections with this curve in the intersections map. Intersect_map_iterator iter = m_inter_map.find(p_curve); - const Intersect_point_2* ip; + const Intersection_point* ip; const X_monotone_curve_2* icv; bool valid_intersection; @@ -821,13 +821,13 @@ _compute_next_intersection(Halfedge_handle he, // Retrieve the intersections list from the map. Intersect_list& inter_list = iter->second; - if (inter_list.empty()) return CGAL::Object(); + if (inter_list.empty()) return Optional_intersection(); // Locate the first intersection that lies to the right of m_left_pt // (if the left point exists). while (! inter_list.empty()) { // Compare that current object with m_left_pt (if exists). - ip = object_cast(&(inter_list.front())); + ip = boost::get(&(inter_list.front())); if (m_left_on_boundary) { // The left end lie on the left boundary, so all intersections are @@ -851,7 +851,7 @@ _compute_next_intersection(Halfedge_handle he, } else { // We have an overlapping subcurve. - icv = object_cast(&(inter_list.front())); + icv = boost::get(&(inter_list.front())); CGAL_assertion(icv != nullptr); if (m_geom_traits->is_closed_2_object()(*icv, ARR_MIN_END)) { @@ -869,14 +869,14 @@ _compute_next_intersection(Halfedge_handle he, } // Found an intersection to m_left_pt's right. - if (valid_intersection) return (inter_list.front()); + if (valid_intersection) return Optional_intersection(inter_list.front()); // Discard the current intersection, which lies to m_left_pt's left. inter_list.pop_front(); } // If we reached here, the list of intersections is empty: - return CGAL::Object(); + return Optional_intersection(); } // The intersections with the curve have not been computed yet, so we @@ -894,7 +894,7 @@ _compute_next_intersection(Halfedge_handle he, // Discard all intersection lying to the left of m_left_pt (if exists). while (! inter_list.empty()) { // Compare that current object with m_left_pt (if exists). - ip = object_cast(&(inter_list.front())); + ip = boost::get(&(inter_list.front())); if (ip != nullptr) { // We have a simple intersection point - if we don't have to skip it, @@ -920,7 +920,7 @@ _compute_next_intersection(Halfedge_handle he, } else { // We have an overlapping subcurve. - icv = object_cast(&(inter_list.front())); + icv = boost::get(&(inter_list.front())); CGAL_assertion(icv != nullptr); if (m_geom_traits->is_closed_2_object()(*icv, ARR_MIN_END)) { @@ -947,8 +947,8 @@ _compute_next_intersection(Halfedge_handle he, m_inter_map[p_curve] = inter_list; // Return the first intersection object computed (may be empty). - if (inter_list.empty()) return CGAL::Object(); - else return (inter_list.front()); + if (inter_list.empty()) return Optional_intersection(); + else return Optional_intersection(inter_list.front()); } //----------------------------------------------------------------------------- @@ -1105,14 +1105,14 @@ _leftmost_intersection(Ccb_halfedge_circulator he_curr, bool on_boundary, // Compute the next intersection of m_cv and the current halfedge. bool intersection_on_right_boundary; - CGAL::Object iobj = + Optional_intersection iobj = _compute_next_intersection(he_curr, left_equals_curr_endpoint, intersection_on_right_boundary); - if (! iobj.is_empty()) { + if (iobj) { // We have found an intersection (either a simple point or an // overlapping x-monotone curve). - const Intersect_point_2* int_p = object_cast(&iobj); + const Intersection_point* int_p = boost::get(&*iobj); if (int_p != nullptr) { Point_2 ip = int_p->first; @@ -1134,7 +1134,7 @@ _leftmost_intersection(Ccb_halfedge_circulator he_curr, bool on_boundary, else { // We have located an overlapping curve. Assign ip as its left // endpoint. - const X_monotone_curve_2* icv = object_cast(&iobj); + const X_monotone_curve_2* icv = boost::get(&*iobj); CGAL_assertion(icv != nullptr); Point_2 ip = min_vertex(*icv); diff --git a/Arrangement_on_surface_2/include/CGAL/Arrangement_zone_2.h b/Arrangement_on_surface_2/include/CGAL/Arrangement_zone_2.h index b3d39acaf46..55616307cd0 100644 --- a/Arrangement_on_surface_2/include/CGAL/Arrangement_zone_2.h +++ b/Arrangement_on_surface_2/include/CGAL/Arrangement_zone_2.h @@ -93,22 +93,25 @@ protected: Right_side_category>::result Are_all_sides_oblivious_category; - typedef typename Arrangement_2::Vertex_const_handle Vertex_const_handle; - typedef typename Arrangement_2::Halfedge_const_handle Halfedge_const_handle; - typedef typename Arrangement_2::Face_const_handle Face_const_handle; + typedef typename Arrangement_2::Vertex_const_handle Vertex_const_handle; + typedef typename Arrangement_2::Halfedge_const_handle Halfedge_const_handle; + typedef typename Arrangement_2::Face_const_handle Face_const_handle; typedef typename Arrangement_2::Ccb_halfedge_circulator Ccb_halfedge_circulator; // Types used for caching intersection points: - typedef std::pair Intersect_point_2; - typedef std::list Intersect_list; + typedef std::pair Intersection_point; + typedef boost::variant + Intersection_result; + typedef boost::optional Optional_intersection; + typedef std::list Intersect_list; typedef std::map - Intersect_map; - typedef typename Intersect_map::iterator Intersect_map_iterator; + Intersect_map; + typedef typename Intersect_map::iterator Intersect_map_iterator; - typedef std::set Curves_set; - typedef typename Curves_set::iterator Curves_set_iterator; + typedef std::set Curves_set; + typedef typename Curves_set::iterator Curves_set_iterator; // Data members: Arrangement_2& m_arr; // The associated arrangement. @@ -378,14 +381,15 @@ private: * point coincides with the right * curve-end, which lies on the * surface boundary. - * \return An object representing the next intersection: Intersect_point_2 + * \return An object representing the next intersection: Intersection_point * in case of a simple intersection point, X_monotone_curve_2 in * case of an overlap, and an empty object if there is no * intersection. */ - CGAL::Object _compute_next_intersection(Halfedge_handle he, - bool skip_first_point, - bool& intersect_on_right_boundary); + Optional_intersection + _compute_next_intersection(Halfedge_handle he, + bool skip_first_point, + bool& intersect_on_right_boundary); /*! Remove the next intersection of m_cv with the given halfedge from the map. * \param he A handle to the halfedge. diff --git a/Arrangement_on_surface_2/include/CGAL/Curved_kernel_via_analysis_2/Curved_kernel_via_analysis_2_functors.h b/Arrangement_on_surface_2/include/CGAL/Curved_kernel_via_analysis_2/Curved_kernel_via_analysis_2_functors.h index adb833f663a..de6f2e14529 100644 --- a/Arrangement_on_surface_2/include/CGAL/Curved_kernel_via_analysis_2/Curved_kernel_via_analysis_2_functors.h +++ b/Arrangement_on_surface_2/include/CGAL/Curved_kernel_via_analysis_2/Curved_kernel_via_analysis_2_functors.h @@ -1459,29 +1459,24 @@ public: OutputIterator operator()(const Arc_2& cv1, const Arc_2& cv2, OutputIterator oi) const { + typedef unsigned int Multiplicity; + typedef std::pair Intersection_point; + typedef boost::variant Intersection_result; + CERR("\nintersect; cv1: " << cv1 << ";\n cv2:" << cv2 << ""); // if arcs overlap, just store their common part, otherwise compute // point-wise intersections - std::vector< Arc_2 > common_arcs; - if (cv1._trim_if_overlapped(cv2, std::back_inserter(common_arcs))) { - typename std::vector< Arc_2 >::const_iterator it; - for(it = common_arcs.begin(); it < common_arcs.end(); it++) { - *oi++ = CGAL::make_object(*it); - } + std::vector arcs; + if (cv1._trim_if_overlapped(cv2, std::back_inserter(arcs))) { + for (const auto& item : arcs) *oi++ = Intersection_result(item); return oi; } // process non-ov erlapping case - typedef std::pair< Point_2, unsigned int > Point_and_mult; - typedef std::vector< Point_and_mult > Point_vector; - Point_vector vec; - typename Point_vector::const_iterator it; + std::vector vec; Arc_2::_intersection_points(cv1, cv2, std::back_inserter(vec)); - - for (it = vec.begin(); it != vec.end(); it++) { - *oi++ = CGAL::make_object(*it); - } + for (const auto& item : vec) *oi++ = Intersection_result(item); return oi; } diff --git a/Arrangement_on_surface_2/test/Arrangement_on_surface_2/Traits_test.h b/Arrangement_on_surface_2/test/Arrangement_on_surface_2/Traits_test.h index b69443c205d..a519c90b1e1 100644 --- a/Arrangement_on_surface_2/test/Arrangement_on_surface_2/Traits_test.h +++ b/Arrangement_on_surface_2/test/Arrangement_on_surface_2/Traits_test.h @@ -17,6 +17,7 @@ #include #include #include + #include "Traits_base_test.h" /*! Traits test */ @@ -989,18 +990,22 @@ intersect_wrapper(std::istringstream& str_stream) typedef typename Traits::X_monotone_curve_2 X_monotone_curve_2; typedef typename Traits::Multiplicity Multiplicity; + typedef std::pair Intersection_point; + typedef boost::variant + Intersection_result; + unsigned int id1, id2; str_stream >> id1 >> id2; - std::vector object_vec; + std::vector xections; this->m_geom_traits.intersect_2_object()(this->m_xcurves[id1], this->m_xcurves[id2], - std::back_inserter(object_vec)); + std::back_inserter(xections)); std::cout << "Test: intersect( " << this->m_xcurves[id1] << "," << this->m_xcurves[id2] << " ) ? "; size_t num; str_stream >> num; - if (!this->compare(num, object_vec.size(), "size")) return false; + if (! this->compare(num, xections.size(), "size")) return false; for (size_t i = 0; i < num; ++i) { unsigned int type; // 0 - point, 1 - x-monotone curve @@ -1011,30 +1016,25 @@ intersect_wrapper(std::istringstream& str_stream) if (type == 0) str_stream >> multiplicity; unsigned int exp_type = 1; - const X_monotone_curve_2 * xcv_ptr = - CGAL::object_cast (&(object_vec[i])); + const X_monotone_curve_2* cv_p = + boost::get(&(xections[i])); - if (xcv_ptr != NULL) { - if (!this->compare(type, exp_type, "type")) return false; - - if (!this->compare_curves(this->m_xcurves[id], *xcv_ptr)) return false; + if (cv_p != nullptr) { + if (! this->compare(type, exp_type, "type")) return false; + if (! this->compare_curves(this->m_xcurves[id], *cv_p)) return false; continue; } exp_type = 0; - typedef std::pair Point_2_pair; - const Point_2_pair * pt_pair_ptr = - CGAL::object_cast (&(object_vec[i])); - assert(pt_pair_ptr != NULL); - if (!this->compare(type, exp_type, "type")) return false; - if (!this->compare_points(this->m_points[id], (*pt_pair_ptr).first)) - return false; - if (!this->compare(multiplicity, (*pt_pair_ptr).second, "multiplicity")) - return false; - } //forloop - - object_vec.clear(); + const Intersection_point* p_p = + boost::get(&(xections[i])); + assert(p_p != nullptr); + if (! this->compare(type, exp_type, "type")) return false; + if (! this->compare_points(this->m_points[id], p_p->first)) return false; + if (! this->compare(multiplicity, p_p->second, "multiplicity")) return false; + } + xections.clear(); return true; } From b70b47fdd6f1910b459d0b1806ba6dfe0b4ce425 Mon Sep 17 00:00:00 2001 From: Jane Tournois Date: Wed, 1 Apr 2020 07:17:08 +0200 Subject: [PATCH 199/568] derecursify computation of facets normals it was causing stack overflow on some models --- .../internal/smooth_vertices.h | 88 +++++++++++-------- 1 file changed, 50 insertions(+), 38 deletions(-) diff --git a/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/smooth_vertices.h b/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/smooth_vertices.h index 457cb7f5d15..d7664542b8c 100644 --- a/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/smooth_vertices.h +++ b/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/smooth_vertices.h @@ -15,6 +15,7 @@ #include #include +#include namespace CGAL { @@ -105,43 +106,24 @@ namespace CGAL return {}; } - template - void compute_neighbors_normals(const Facet& f, - const typename Vector_3& reference_normal, - FacetNormalsMap& fnormals, - const C3t3& c3t3, - const CellSelector& cell_selector) + template + Vector_3 compute_normal(const Facet& f, + const Vector_3& reference_normal, + const C3t3& c3t3, + const CellSelector& cell_selector) { + CGAL_assertion(is_boundary(c3t3, f, cell_selector)); + typename Tr::Geom_traits::Construct_opposite_vector_3 opp = c3t3.triangulation().geom_traits().construct_opposite_vector_3_object(); typename Tr::Geom_traits::Compute_scalar_product_3 scalar_product = c3t3.triangulation().geom_traits().compute_scalar_product_3_object(); - CGAL_assertion(is_boundary(c3t3, f, cell_selector)); - - if (fnormals[f] != CGAL::NULL_VECTOR) - return; - Vector_3 n = CGAL::Tetrahedral_remeshing::normal(f, c3t3.triangulation().geom_traits()); if (scalar_product(n, reference_normal) < 0.) n = opp(n); - fnormals[f] = n; - // update complex edges - const typename C3t3::Cell_handle ch = f.first; - const std::array, 3> edges - = { (f.second + 1) % 4, (f.second + 2) % 4, //edge 1-2 - (f.second + 2) % 4, (f.second + 3) % 4, //edge 2-3 - (f.second + 3) % 4, (f.second + 1) % 4 //edge 3-1 - }; //vertex indices in cells - - for (const std::array& ei : edges) - { - Edge edge(ch, ei[0], ei[1]); - if (boost::optional neighbor - = find_adjacent_facet_on_surface(f, edge, c3t3, cell_selector)) - compute_neighbors_normals(*neighbor, n, fnormals, c3t3, cell_selector); - } + return n; } template @@ -167,22 +149,51 @@ namespace CGAL } } - for (const auto& fn : fnormals) + for (const std::pair& fn : fnormals) { - const Vector_3& n = fn.second; - if (n != CGAL::NULL_VECTOR) - continue; //already computed + if(fn.second != CGAL::NULL_VECTOR) + continue; const Facet& f = fn.first; const Facet& mf = tr.mirror_facet(f); CGAL_assertion(is_boundary(c3t3, f, cell_selector)); - Vector_3 ref = CGAL::Tetrahedral_remeshing::normal(f, tr.geom_traits()); - if (c3t3.triangulation().is_infinite(f.first) - || c3t3.subdomain_index(f.first) < c3t3.subdomain_index(mf.first)) - ref = opp(ref); + Vector_3 start_ref = CGAL::Tetrahedral_remeshing::normal(f, tr.geom_traits()); + if (c3t3.triangulation().is_infinite(mf.first) + || c3t3.subdomain_index(mf.first) < c3t3.subdomain_index(f.first)) + start_ref = opp(start_ref); + fnormals[f] = start_ref; - compute_neighbors_normals(f, ref, fnormals, c3t3, cell_selector); + std::list facets; + facets.push_back(f); + while (!facets.empty()) + { + const Facet f = facets.front(); + facets.pop_front(); + + const typename C3t3::Cell_handle ch = f.first; + const std::array, 3> edges + = { (f.second + 1) % 4, (f.second + 2) % 4, //edge 1-2 + (f.second + 2) % 4, (f.second + 3) % 4, //edge 2-3 + (f.second + 3) % 4, (f.second + 1) % 4 //edge 3-1 + }; //vertex indices in cells + + const Vector_3& ref = fnormals[f]; + for (const std::array& ei : edges) + { + Edge edge(ch, ei[0], ei[1]); + if (boost::optional neighbor + = find_adjacent_facet_on_surface(f, edge, c3t3, cell_selector)) + { + const Facet neigh = *neighbor; //already a canonical_facet + if (fnormals[neigh] == CGAL::NULL_VECTOR) //check it's not already computed + { + fnormals[neigh] = compute_normal(neigh, ref, c3t3, cell_selector); + facets.push_back(neigh); + } + } + } + } } #ifdef CGAL_TETRAHEDRAL_REMESHING_DEBUG @@ -291,8 +302,9 @@ namespace CGAL fmls.fastProjectionCPU(point, result, res_normal); if (std::isnan(result[0]) || std::isnan(result[1]) || std::isnan(result[2])) { - std::cout << "MLS error detected si size " << si - << " : " << fmls.getPNSize() << std::endl; + std::cout << "MLS error detected si " << si + << "\t(size : " << fmls.getPNSize() << ")" + << "\t(point = " << point << " )" << std::endl; return {}; } } while ((result - point).getSquaredLength() > sq_eps&& ++it_nb < max_it_nb); From 6d71f78b60580783ad1ac26dc7a549626e1321ac Mon Sep 17 00:00:00 2001 From: Jane Tournois Date: Wed, 1 Apr 2020 07:39:04 +0200 Subject: [PATCH 200/568] comment debug macros --- .../Tetrahedral_remeshing/Tetrahedral_remeshing_plugin.cpp | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/Polyhedron/demo/Polyhedron/Plugins/Tetrahedral_remeshing/Tetrahedral_remeshing_plugin.cpp b/Polyhedron/demo/Polyhedron/Plugins/Tetrahedral_remeshing/Tetrahedral_remeshing_plugin.cpp index bfc70f4bf7c..be25867c10e 100644 --- a/Polyhedron/demo/Polyhedron/Plugins/Tetrahedral_remeshing/Tetrahedral_remeshing_plugin.cpp +++ b/Polyhedron/demo/Polyhedron/Plugins/Tetrahedral_remeshing/Tetrahedral_remeshing_plugin.cpp @@ -1,7 +1,8 @@ #define CGAL_TETRAHEDRAL_REMESHING_VERBOSE -#define CGAL_DUMP_REMESHING_STEPS -#define CGAL_TETRAHEDRAL_REMESHING_DEBUG -#define CGAL_TETRAHEDRAL_REMESHING_VERBOSE_PROGRESS +//#define CGAL_DUMP_REMESHING_STEPS +//#define CGAL_TETRAHEDRAL_REMESHING_DEBUG +//#define CGAL_TETRAHEDRAL_REMESHING_VERBOSE_PROGRESS +//#define CGAL_TETRAHEDRAL_REMESHING_PROFILE #include From 53843de366ca31aa2d06a5f41afff0c09f96d106 Mon Sep 17 00:00:00 2001 From: Jane Tournois Date: Wed, 1 Apr 2020 07:59:27 +0200 Subject: [PATCH 201/568] protect smoothing of sharp edges with a macro --- .../Tetrahedral_remeshing_plugin.cpp | 1 + .../internal/smooth_vertices.h | 223 +++++++++--------- 2 files changed, 114 insertions(+), 110 deletions(-) diff --git a/Polyhedron/demo/Polyhedron/Plugins/Tetrahedral_remeshing/Tetrahedral_remeshing_plugin.cpp b/Polyhedron/demo/Polyhedron/Plugins/Tetrahedral_remeshing/Tetrahedral_remeshing_plugin.cpp index be25867c10e..25219b9b7a0 100644 --- a/Polyhedron/demo/Polyhedron/Plugins/Tetrahedral_remeshing/Tetrahedral_remeshing_plugin.cpp +++ b/Polyhedron/demo/Polyhedron/Plugins/Tetrahedral_remeshing/Tetrahedral_remeshing_plugin.cpp @@ -3,6 +3,7 @@ //#define CGAL_TETRAHEDRAL_REMESHING_DEBUG //#define CGAL_TETRAHEDRAL_REMESHING_VERBOSE_PROGRESS //#define CGAL_TETRAHEDRAL_REMESHING_PROFILE +//#define CGAL_TETRAHEDRAL_REMESHING_SMOOTH_SHARP_EDGES #include diff --git a/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/smooth_vertices.h b/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/smooth_vertices.h index d7664542b8c..a1088ec2320 100644 --- a/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/smooth_vertices.h +++ b/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/smooth_vertices.h @@ -356,10 +356,11 @@ namespace CGAL Tr& tr = c3t3.triangulation(); +#ifdef CGAL_TETRAHEDRAL_REMESHING_SMOOTH_SHARP_EDGES //collect a map of vertices surface indices boost::unordered_map > vertices_surface_indices; collect_vertices_surface_indices(c3t3, vertices_surface_indices); - +#endif //collect a map of normals at surface vertices boost::unordered_map > vertices_normals; @@ -380,115 +381,117 @@ namespace CGAL if (!protect_boundaries) { -// /////////////// EDGES IN COMPLEX ////////////////// -// //collect neighbors -// for (const Edge& e : tr.finite_edges()) -// { -// if (c3t3.is_in_complex(e)) -// { -// const Vertex_handle vh0 = e.first->vertex(e.second); -// const Vertex_handle vh1 = e.first->vertex(e.third); -// -// const std::size_t& i0 = vertex_id.at(vh0); -// const std::size_t& i1 = vertex_id.at(vh1); -// -// const bool on_feature_v0 = is_on_feature(vh0); -// const bool on_feature_v1 = is_on_feature(vh1); -// -// if (!c3t3.is_in_complex(vh0)) -// neighbors[i0] = (std::max)(0, neighbors[i0]); -// if (!c3t3.is_in_complex(vh1)) -// neighbors[i1] = (std::max)(0, neighbors[i1]); -// -// if (!c3t3.is_in_complex(vh0) && on_feature_v1) -// { -// const Point_3& p1 = point(vh1->point()); -// smoothed_positions[i0] = smoothed_positions[i0] + Vector_3(p1.x(), p1.y(), p1.z()); -// neighbors[i0]++; -// } -// if (!c3t3.is_in_complex(vh1) && on_feature_v0) -// { -// const Point_3& p0 = point(vh0->point()); -// smoothed_positions[i1] = smoothed_positions[i1] + Vector_3(p0.x(), p0.y(), p0.z()); -// neighbors[i1]++; -// } -// } -// } -// -// // Smooth -// for (Vertex_handle v : tr.finite_vertex_handles()) -// { -// const std::size_t& vid = vertex_id.at(v); -// if (neighbors[vid] > 1) -// { -// Vector_3 smoothed_position = smoothed_positions[vid] / neighbors[vid]; -// Vector_3 final_position = CGAL::NULL_VECTOR; -// -// std::size_t count = 0; -// const Vector_3 current_pos(CGAL::ORIGIN, point(v->point())); -// -// const std::vector& v_surface_indices = vertices_surface_indices[v]; -// for (const Surface_patch_index& si : v_surface_indices) -// { -// Vector_3 normal_projection -// = project_on_tangent_plane(smoothed_position, current_pos, vertices_normals[v][si]); -// -// //Check if the mls surface exists to avoid degenerated cases -// if (boost::optional mls_projection = project(si, normal_projection)) { -// final_position = final_position + *mls_projection; -// } -// else { -// final_position = final_position + normal_projection; -// } -// count++; -// } -// -// if (count > 0) -// final_position = final_position / static_cast(count); -// else -// final_position = smoothed_position; -// -//#ifdef CGAL_TETRAHEDRAL_REMESHING_DEBUG -// os_surf << "2 " << current_pos << " " << final_position << std::endl, -//#endif -// // move vertex -// v->set_point(typename Tr::Point( -// final_position.x(), final_position.y(), final_position.z())); -// } -// else if (neighbors[vid] > 0) -// { -// Vector_3 final_position = CGAL::NULL_VECTOR; -// -// int count = 0; -// const Vector_3 current_pos(CGAL::ORIGIN, point(v->point())); -// -// const std::vector& v_surface_indices = vertices_surface_indices[v]; -// for (const Surface_patch_index si : v_surface_indices) -// { -// //Check if the mls surface exists to avoid degenerated cases -// -// if (boost::optional mls_projection = project(si, current_pos)) { -// final_position = final_position + *mls_projection; -// } -// else { -// final_position = final_position + current_pos; -// } -// count++; -// } -// -// if (count > 0) -// final_position = final_position / static_cast(count); -// else -// final_position = current_pos; -// -//#ifdef CGAL_TETRAHEDRAL_REMESHING_DEBUG -// os_surf << "2 " << current_pos << " " << final_position << std::endl, -//#endif -// // move vertex -// v->set_point( -// typename Tr::Point(final_position.x(), final_position.y(), final_position.z())); -// } -// } +#ifdef CGAL_TETRAHEDRAL_REMESHING_SMOOTH_SHARP_EDGES + /////////////// EDGES IN COMPLEX ////////////////// + //collect neighbors + for (const Edge& e : tr.finite_edges()) + { + if (c3t3.is_in_complex(e)) + { + const Vertex_handle vh0 = e.first->vertex(e.second); + const Vertex_handle vh1 = e.first->vertex(e.third); + + const std::size_t& i0 = vertex_id.at(vh0); + const std::size_t& i1 = vertex_id.at(vh1); + + const bool on_feature_v0 = is_on_feature(vh0); + const bool on_feature_v1 = is_on_feature(vh1); + + if (!c3t3.is_in_complex(vh0)) + neighbors[i0] = (std::max)(0, neighbors[i0]); + if (!c3t3.is_in_complex(vh1)) + neighbors[i1] = (std::max)(0, neighbors[i1]); + + if (!c3t3.is_in_complex(vh0) && on_feature_v1) + { + const Point_3& p1 = point(vh1->point()); + smoothed_positions[i0] = smoothed_positions[i0] + Vector_3(p1.x(), p1.y(), p1.z()); + neighbors[i0]++; + } + if (!c3t3.is_in_complex(vh1) && on_feature_v0) + { + const Point_3& p0 = point(vh0->point()); + smoothed_positions[i1] = smoothed_positions[i1] + Vector_3(p0.x(), p0.y(), p0.z()); + neighbors[i1]++; + } + } + } + + // Smooth + for (Vertex_handle v : tr.finite_vertex_handles()) + { + const std::size_t& vid = vertex_id.at(v); + if (neighbors[vid] > 1) + { + Vector_3 smoothed_position = smoothed_positions[vid] / neighbors[vid]; + Vector_3 final_position = CGAL::NULL_VECTOR; + + std::size_t count = 0; + const Vector_3 current_pos(CGAL::ORIGIN, point(v->point())); + + const std::vector& v_surface_indices = vertices_surface_indices[v]; + for (const Surface_patch_index& si : v_surface_indices) + { + Vector_3 normal_projection + = project_on_tangent_plane(smoothed_position, current_pos, vertices_normals[v][si]); + + //Check if the mls surface exists to avoid degenerated cases + if (boost::optional mls_projection = project(si, normal_projection)) { + final_position = final_position + *mls_projection; + } + else { + final_position = final_position + normal_projection; + } + count++; + } + + if (count > 0) + final_position = final_position / static_cast(count); + else + final_position = smoothed_position; + +#ifdef CGAL_TETRAHEDRAL_REMESHING_DEBUG + os_surf << "2 " << current_pos << " " << final_position << std::endl, +#endif + // move vertex + v->set_point(typename Tr::Point( + final_position.x(), final_position.y(), final_position.z())); + } + else if (neighbors[vid] > 0) + { + Vector_3 final_position = CGAL::NULL_VECTOR; + + int count = 0; + const Vector_3 current_pos(CGAL::ORIGIN, point(v->point())); + + const std::vector& v_surface_indices = vertices_surface_indices[v]; + for (const Surface_patch_index si : v_surface_indices) + { + //Check if the mls surface exists to avoid degenerated cases + + if (boost::optional mls_projection = project(si, current_pos)) { + final_position = final_position + *mls_projection; + } + else { + final_position = final_position + current_pos; + } + count++; + } + + if (count > 0) + final_position = final_position / static_cast(count); + else + final_position = current_pos; + +#ifdef CGAL_TETRAHEDRAL_REMESHING_DEBUG + os_surf << "2 " << current_pos << " " << final_position << std::endl, +#endif + // move vertex + v->set_point( + typename Tr::Point(final_position.x(), final_position.y(), final_position.z())); + } + } +#endif //CGAL_TETRAHEDRAL_REMESHING_SMOOTH_SHARP_EDGES smoothed_positions.assign(nbv, CGAL::NULL_VECTOR); neighbors.assign(nbv, -1); From 4158542c8657fb4f9396980f3de25c3d9fb1e995 Mon Sep 17 00:00:00 2001 From: Efi Fogel Date: Wed, 1 Apr 2020 12:31:51 +0300 Subject: [PATCH 202/568] Fixed intersection result --- .../Surface_sweep_2/Arr_insertion_traits_2.h | 64 +++-- .../Surface_sweep_2/Arr_overlay_traits_2.h | 96 +++---- .../include/CGAL/Surface_sweep_2.h | 14 +- .../Surface_sweep_2/Surface_sweep_2_impl.h | 248 ++++++++---------- 4 files changed, 207 insertions(+), 215 deletions(-) diff --git a/Arrangement_on_surface_2/include/CGAL/Surface_sweep_2/Arr_insertion_traits_2.h b/Arrangement_on_surface_2/include/CGAL/Surface_sweep_2/Arr_insertion_traits_2.h index ba2e709c6cf..73d7f3b0326 100644 --- a/Arrangement_on_surface_2/include/CGAL/Surface_sweep_2/Arr_insertion_traits_2.h +++ b/Arrangement_on_surface_2/include/CGAL/Surface_sweep_2/Arr_insertion_traits_2.h @@ -80,17 +80,13 @@ public: protected: //! The base operators. Base_intersect_2 m_base_intersect; - Halfedge_handle invalid_he; /*! Constructor. * The constructor is declared private to allow only the functor * obtaining function, which is a member of the nesting class, * constructing it. */ - Intersect_2(const Base_intersect_2& base) : - m_base_intersect (base), - invalid_he() - {} + Intersect_2(const Base_intersect_2& base) : m_base_intersect (base) {} //! Allow its functor obtaining function calling the private constructor. friend class Arr_insertion_traits_2; @@ -101,6 +97,14 @@ public: const X_monotone_curve_2& cv2, OutputIterator oi) { + typedef std::pair Intersection_point; + typedef boost::variant + Intersection_result; + typedef boost::variant + Intersection_base_result; + + Halfedge_handle invalid_he; + if ((cv1.halfedge_handle() != invalid_he) && (cv2.halfedge_handle() != invalid_he) && (cv1.halfedge_handle() != cv2.halfedge_handle())) @@ -110,40 +114,32 @@ public: return oi; } - OutputIterator oi_end = m_base_intersect(cv1.base(), cv2.base(), oi); - const Base_x_monotone_curve_2* base_overlap_cv; - const std::pair* intersect_p; - + std::vector xections; + m_base_intersect(cv1.base(), cv2.base(), std::back_inserter(xections)); // convert objects that are associated with Base_x_monotone_curve_2 to // X_monotone_curve_2 - for(; oi != oi_end; ++oi) { - base_overlap_cv = object_cast(&(*oi)); - if (base_overlap_cv != nullptr) { - // Add halfedge handles to the resulting curve. - Halfedge_handle he; - - if (cv1.halfedge_handle() != invalid_he) he = cv1.halfedge_handle(); - else if (cv2.halfedge_handle() != invalid_he) - he = cv2.halfedge_handle(); - - X_monotone_curve_2 overlap_cv (*base_overlap_cv, he); - - overlap_cv.set_overlapping(); - *oi = make_object (overlap_cv); + for (const auto& xection : xections) { + const Intersection_point* + p_p = boost::get(&xection); + if (p_p != nullptr) { + *oi++ = Intersection_result(xection); + continue; } - else { - intersect_p = - object_cast >(&(*oi)); + const Base_x_monotone_curve_2* base_cv_p = + boost::get(&xection); + CGAL_assertion(base_cv_p); - CGAL_assertion (intersect_p != nullptr); - - *oi = make_object(std::make_pair(Point_2(intersect_p->first), - intersect_p->second)); - } + // Add halfedge handles to the resulting curve. + Halfedge_handle he; + if (cv1.halfedge_handle() != invalid_he) he = cv1.halfedge_handle(); + else if (cv2.halfedge_handle() != invalid_he) + he = cv2.halfedge_handle(); + X_monotone_curve_2 cv(*base_cv_p, he); + cv.set_overlapping(); + *oi++ = Intersection_result(cv); } - - // Return a past-the-end iterator. - return oi_end; + xections.clear(); + return oi; } }; diff --git a/Arrangement_on_surface_2/include/CGAL/Surface_sweep_2/Arr_overlay_traits_2.h b/Arrangement_on_surface_2/include/CGAL/Surface_sweep_2/Arr_overlay_traits_2.h index 8f6275e441d..c94ecf40913 100644 --- a/Arrangement_on_surface_2/include/CGAL/Surface_sweep_2/Arr_overlay_traits_2.h +++ b/Arrangement_on_surface_2/include/CGAL/Surface_sweep_2/Arr_overlay_traits_2.h @@ -345,24 +345,31 @@ public: class Intersect_2 { protected: //! The base traits. - const Arr_overlay_traits_2* m_traits; + const Arr_overlay_traits_2& m_traits; /*! Constructor. * The constructor is declared protected to allow only the functor * obtaining function, which is a member of the nesting class, * constructing it. */ - Intersect_2(const Arr_overlay_traits_2* traits) : m_traits(traits) {} + Intersect_2(const Arr_overlay_traits_2& traits) : m_traits(traits) {} //! Allow its functor obtaining function calling the protected constructor. friend class Arr_overlay_traits_2; public: - template + template OutputIterator operator()(const X_monotone_curve_2& xcv1, const X_monotone_curve_2& xcv2, OutputIterator oi) { + typedef std::pair Intersection_point; + typedef boost::variant + Intersection_result; + typedef std::pair Intersection_base_point; + typedef boost::variant + Intersection_base_result; + // In case the curves originate from the same arrangement, they are // obviously interior-disjoint. if (xcv1.color() == xcv2.color()) return oi; @@ -396,19 +403,16 @@ public: // Note that we do not bother with curves whose left ends are open, // since such curved did not intersect before. - const std::pair* base_ipt; - const Base_x_monotone_curve_2* overlap_xcv; bool send_xcv1_first = true; - OutputIterator oi_end; - Parameter_space_in_x_2 ps_x_op = m_traits->parameter_space_in_x_2_object(); - Parameter_space_in_y_2 ps_y_op = m_traits->parameter_space_in_y_2_object(); - const Arr_parameter_space bx1 = ps_x_op(xcv1, ARR_MIN_END); - const Arr_parameter_space by1 = ps_y_op(xcv1, ARR_MIN_END); - const Arr_parameter_space bx2 = ps_x_op(xcv2, ARR_MIN_END); - const Arr_parameter_space by2 = ps_y_op(xcv2, ARR_MIN_END); + auto ps_x_op = m_traits.parameter_space_in_x_2_object(); + auto ps_y_op = m_traits.parameter_space_in_y_2_object(); + Arr_parameter_space bx1 = ps_x_op(xcv1, ARR_MIN_END); + Arr_parameter_space by1 = ps_y_op(xcv1, ARR_MIN_END); + Arr_parameter_space bx2 = ps_x_op(xcv2, ARR_MIN_END); + Arr_parameter_space by2 = ps_y_op(xcv2, ARR_MIN_END); - const Gt2* m_base_tr = m_traits->base_traits(); + const Gt2* m_base_tr = m_traits.base_traits(); if ((bx1 == ARR_INTERIOR) && (by1 == ARR_INTERIOR) && (bx2 == ARR_INTERIOR) && (by2 == ARR_INTERIOR)) @@ -419,15 +423,17 @@ public: m_base_tr->construct_min_vertex_2_object()(xcv2.base())) == LARGER); } - oi_end = (send_xcv1_first) ? - m_base_tr->intersect_2_object()(xcv1.base(), xcv2.base(), oi) : - m_base_tr->intersect_2_object()(xcv2.base(), xcv1.base(), oi); + auto intersector = m_base_tr->intersect_2_object(); + std::vector xections; + (send_xcv1_first) ? + intersector(xcv1.base(), xcv2.base(), std::back_inserter(xections)) : + intersector(xcv2.base(), xcv1.base(), std::back_inserter(xections)); // Convert objects that are associated with Base_x_monotone_curve_2 to // the exteneded X_monotone_curve_2. - while (oi != oi_end) { - base_ipt = object_cast >(&(*oi)); - + for (const auto& xection : xections) { + const Intersection_base_point* base_ipt = + boost::get(&xection); if (base_ipt != nullptr) { // We have a red-blue intersection point, so we attach the // intersecting red and blue halfedges to it. @@ -451,42 +457,44 @@ public: // Create the extended point and add the multiplicity. Point_2 ex_point(base_ipt->first, red_cell, blue_cell); - *oi++ = CGAL::make_object(std::make_pair(ex_point, base_ipt->second)); + *oi++ = + Intersection_result(std::make_pair(ex_point, base_ipt->second)); + continue; + } + + const Base_x_monotone_curve_2* overlap_xcv = + boost::get(&xection); + CGAL_assertion(overlap_xcv != nullptr); + + // We have a red-blue overlap, so we mark the curve accordingly. + Halfedge_handle_red red_he; + Halfedge_handle_blue blue_he; + + if (xcv1.color() == RED) { + red_he = xcv1.red_halfedge_handle(); + + // Overlap can occur only between curves from a different color. + CGAL_assertion(xcv2.color() == BLUE); + blue_he = xcv2.blue_halfedge_handle(); } else { - overlap_xcv = object_cast(&(*oi)); - CGAL_assertion(overlap_xcv != nullptr); + CGAL_assertion((xcv1.color() == BLUE) && (xcv2.color() == RED)); - // We have a red-blue overlap, so we mark the curve accordingly. - Halfedge_handle_red red_he; - Halfedge_handle_blue blue_he; - - if (xcv1.color() == RED) { - red_he = xcv1.red_halfedge_handle(); - - // Overlap can occur only between curves from a different color. - CGAL_assertion(xcv2.color() == BLUE); - blue_he = xcv2.blue_halfedge_handle(); - } - else { - CGAL_assertion((xcv1.color() == BLUE) && (xcv2.color() == RED)); - - red_he = xcv2.red_halfedge_handle(); - blue_he = xcv1.blue_halfedge_handle(); - } - - *oi++ = CGAL::make_object(X_monotone_curve_2(*overlap_xcv, - red_he, blue_he)); + red_he = xcv2.red_halfedge_handle(); + blue_he = xcv1.blue_halfedge_handle(); } + + X_monotone_curve_2 cv(*overlap_xcv, red_he, blue_he); + *oi++ = Intersection_result(cv); } // Return the past-the-end iterator. - return oi_end; + return oi; } }; /*! Obtain an Intersect_2 functor object. */ - Intersect_2 intersect_2_object() const { return Intersect_2(this); } + Intersect_2 intersect_2_object() const { return Intersect_2(*this); } /*! A functor that splits an arc at a point. */ class Split_2 { diff --git a/Surface_sweep_2/include/CGAL/Surface_sweep_2.h b/Surface_sweep_2/include/CGAL/Surface_sweep_2.h index e8b8a1abea8..550e83fb0e0 100644 --- a/Surface_sweep_2/include/CGAL/Surface_sweep_2.h +++ b/Surface_sweep_2/include/CGAL/Surface_sweep_2.h @@ -90,6 +90,7 @@ public: typedef typename Base::Traits_adaptor_2 Traits_adaptor_2; typedef typename Traits_adaptor_2::Point_2 Point_2; typedef typename Traits_adaptor_2::X_monotone_curve_2 X_monotone_curve_2; + typedef typename Traits_adaptor_2::Multiplicity Multiplicity; typedef typename Base::Event_queue_iterator Event_queue_iterator; typedef typename Event::Subcurve_iterator Event_subcurve_iterator; @@ -106,11 +107,14 @@ public: typedef CGAL::Surface_sweep_2::Equal_curve_pair Equal_curve_pair; typedef boost::unordered_set - Curve_pair_set; - - typedef std::vector Object_vector; - typedef random_access_input_iterator vector_inserter; + Curve_pair_set; + typedef std::pair Intersection_point; + typedef boost::variant + Intersection_result; + typedef std::vector Intersection_vector; + typedef random_access_input_iterator + vector_inserter; typedef typename Base::Subcurve_alloc Subcurve_alloc; protected: // Data members: @@ -121,7 +125,7 @@ protected: Curve_pair_set m_curves_pair_set; // A lookup table of pairs of Subcurves // that have been intersected. - std::vector m_x_objects; // Auxiliary vector for storing the + Intersection_vector m_x_objects; // Auxiliary vector for storing the // intersection objects. X_monotone_curve_2 sub_cv1; // Auxiliary varibales diff --git a/Surface_sweep_2/include/CGAL/Surface_sweep_2/Surface_sweep_2_impl.h b/Surface_sweep_2/include/CGAL/Surface_sweep_2/Surface_sweep_2_impl.h index 79c4930a4e2..a0d01f0329e 100644 --- a/Surface_sweep_2/include/CGAL/Surface_sweep_2/Surface_sweep_2_impl.h +++ b/Surface_sweep_2/include/CGAL/Surface_sweep_2/Surface_sweep_2_impl.h @@ -514,9 +514,10 @@ template CGAL_SS_PRINT_CURVE(c2); CGAL_SS_PRINT_EOL(); - CGAL_assertion(event_for_overlap==NULL || event_for_overlap==this->m_currentEvent); + CGAL_assertion((event_for_overlap == nullptr) || + (event_for_overlap == this->m_currentEvent)); - typedef typename Geometry_traits_2::Multiplicity Multiplicity; + auto ctr_min = this->m_traits->construct_min_vertex_2_object();; CGAL_assertion(c1 != c2); @@ -529,12 +530,13 @@ template // handle overlapping curves with common ancesters Subcurve_vector all_leaves_diff; - Subcurve* first_parent=nullptr; - if (c1->originating_subcurve1()!=nullptr || c2->originating_subcurve2()!=nullptr) + Subcurve* first_parent = nullptr; + if ((c1->originating_subcurve1() != nullptr) || + (c2->originating_subcurve2() != nullptr)) { - // get the subcurve leaves of c1 and of c2. Then extract from the smallest set - // the subcurves leaves that are not in the other one. If empty, it means that - // a subcurves is completely contained in another one. + // get the subcurve leaves of c1 and of c2. Then extract from the smallest + // set the subcurves leaves that are not in the other one. If empty, it + // means that a subcurves is completely contained in another one. first_parent = c1; Subcurve* second_parent = c2; @@ -542,8 +544,7 @@ template Subcurve_vector all_leaves_second; first_parent->all_leaves(std::back_inserter(all_leaves_first)); second_parent->all_leaves(std::back_inserter(all_leaves_second)); - if (all_leaves_second.size() > all_leaves_first.size()) - { + if (all_leaves_second.size() > all_leaves_first.size()) { std::swap(first_parent,second_parent); std::swap(all_leaves_first,all_leaves_second); } @@ -553,105 +554,108 @@ template std::sort(all_leaves_first.begin(), all_leaves_first.end()); std::sort(all_leaves_second.begin(), all_leaves_second.end()); + // copies elements from all_leaves_second that are not in all_leaves_first std::set_difference(all_leaves_second.begin(), all_leaves_second.end(), all_leaves_first.begin(), all_leaves_first.end(), - std::back_inserter(all_leaves_diff)); // copies elements from all_leaves_second that are not in all_leaves_first + std::back_inserter(all_leaves_diff)); - if (all_leaves_second.size()==all_leaves_diff.size()) - { + if (all_leaves_second.size() == all_leaves_diff.size()) { // first_parent has no common parent with second_parent - all_leaves_diff.clear(); // clear so that it is not used by _create_overlapping_curve() + // clear so that it is not used by _create_overlapping_curve() + all_leaves_diff.clear(); } - else - if (all_leaves_diff.empty()) + else if (all_leaves_diff.empty()) { + // first_parent entirely contains second_parent + CGAL_SS_PRINT_TEXT("One overlapping curve entirely contains the other one"); + CGAL_SS_PRINT_EOL(); + + Event* left_event = (Event*) first_parent->left_event(); + Event* right_event = (Event*) first_parent->right_event(); + + if (! second_parent->is_start_point(left_event)) + left_event->add_curve_to_left(second_parent); + else + left_event->remove_curve_from_right(second_parent); + + CGAL_SS_PRINT_CURVE(c1); + CGAL_SS_PRINT_TEXT(" + "); + CGAL_SS_PRINT_CURVE(c2); + CGAL_SS_PRINT_TEXT(" => "); + CGAL_SS_PRINT_EOL(); + CGAL_SS_PRINT_TEXT(" "); + CGAL_SS_PRINT_CURVE(first_parent); + CGAL_SS_PRINT_EOL(); + + // Remove second_parent from the left curves of the right end + // and add it on the right otherwise + if (second_parent->is_end_point(right_event)) + right_event->remove_curve_from_left(second_parent); + else + _add_curve_to_right(right_event, second_parent); + + // add the overlapping curve kept of the right of the left end + right_event->add_curve_to_left(first_parent); + _add_curve_to_right(left_event, first_parent); + + this->m_visitor->found_overlap(c1, c2, first_parent); + + CGAL_SS_PRINT_END_EOL("computing intersection"); + return; + } + else { + CGAL_SS_PRINT_TEXT("Overlap with common ancestors (all_leaves_diff.size() = "); + CGAL_SS_PRINT_TEXT(std::to_string(all_leaves_diff.size()).c_str()); + CGAL_SS_PRINT_TEXT(")"); + CGAL_SS_PRINT_EOL(); + + // iteratively create the final overlapping (geometric) curve. + // This is needed rather than simply computing the intersection of + // the last curves of first_parent and second_parent as some traits + // classes (such as Arr_curve_data_traits_2) override the Intersect_2 + // functor and expects the curve to have no common ancesters + // (Arr_curve_data_traits_2 is used in the testsuite to sum up + // the overlapping degree of a curve) + CGAL_SS_PRINT_TEXT("First parent is: "); + CGAL_SS_PRINT_CURVE(first_parent); + CGAL_SS_PRINT_EOL(); + X_monotone_curve_2 xc = first_parent->last_curve(); + for (auto sc_it = all_leaves_diff.begin(); + sc_it != all_leaves_diff.end(); ++sc_it) { - // first_parent entirely contains second_parent - CGAL_SS_PRINT_TEXT("One overlapping curve entirely contains the other one"); + CGAL_SS_PRINT_TEXT("Inter with curve: "); + CGAL_SS_PRINT_CURVE((*sc_it)); CGAL_SS_PRINT_EOL(); - Event* left_event = (Event*) first_parent->left_event(); - Event* right_event = (Event*) first_parent->right_event(); - - if (!second_parent->is_start_point(left_event)) - left_event->add_curve_to_left(second_parent); - else - left_event->remove_curve_from_right(second_parent); - - CGAL_SS_PRINT_CURVE(c1); - CGAL_SS_PRINT_TEXT(" + "); - CGAL_SS_PRINT_CURVE(c2); - CGAL_SS_PRINT_TEXT(" => "); - CGAL_SS_PRINT_EOL(); - CGAL_SS_PRINT_TEXT(" "); - CGAL_SS_PRINT_CURVE(first_parent); - CGAL_SS_PRINT_EOL(); - - // Remove second_parent from the left curves of the right end - // and add it on the right otherwise - if (second_parent->is_end_point(right_event)) - right_event->remove_curve_from_left(second_parent); - else - _add_curve_to_right(right_event, second_parent); - - // add the overlapping curve kept of the right of the left end - right_event->add_curve_to_left(first_parent); - _add_curve_to_right(left_event, first_parent); - - this->m_visitor->found_overlap(c1, c2, first_parent); - - CGAL_SS_PRINT_END_EOL("computing intersection"); - return; + Intersection_vector xections; + auto intersector = this->m_traits->intersect_2_object(); + intersector(xc, (*sc_it)->last_curve(), vector_inserter(xections)); + CGAL_assertion(xections.size() == 1); + auto& item = xections.front(); + xc = *boost::get(&item); } - else{ - CGAL_SS_PRINT_TEXT("Overlap with common ancestors (all_leaves_diff.size() = "); - CGAL_SS_PRINT_TEXT(std::to_string(all_leaves_diff.size()).c_str()); - CGAL_SS_PRINT_TEXT(")"); - CGAL_SS_PRINT_EOL(); - // iteratively create the final overlapping (geometric) curve. - // This is needed rather than simply computing the intersection of - // the last curves of first_parent and second_parent as some traits - // classes (such as Arr_curve_data_traits_2) override the Intersect_2 - // functor and expects the curve to have no common ancesters - // (Arr_curve_data_traits_2 is used in the testsuite to sum up - // the overlapping degree of a curve) - CGAL_SS_PRINT_TEXT("First parent is: "); - CGAL_SS_PRINT_CURVE(first_parent); - CGAL_SS_PRINT_EOL(); - X_monotone_curve_2 xc = first_parent->last_curve(); - for (typename Subcurve_vector::iterator sc_it=all_leaves_diff.begin(); - sc_it!=all_leaves_diff.end(); ++sc_it) - { - CGAL_SS_PRINT_TEXT("Inter with curve: "); - CGAL_SS_PRINT_CURVE((*sc_it)); - CGAL_SS_PRINT_EOL(); + CGAL_assertion + (this->m_queueEventLess(ctr_min(xc), + event_for_overlap == nullptr ? + this->m_currentEvent : event_for_overlap) == + EQUAL); - std::vector inter_res; - - this->m_traits->intersect_2_object()(xc, - (*sc_it)->last_curve(), - vector_inserter(inter_res)); - CGAL_assertion(inter_res.size()==1); - CGAL_assertion( CGAL::object_cast< X_monotone_curve_2 >(&inter_res.front())!=nullptr ); - xc = *CGAL::object_cast< X_monotone_curve_2 >(&inter_res.front()); - } - - CGAL_assertion( this->m_queueEventLess(this->m_traits->construct_min_vertex_2_object()(xc), - event_for_overlap==NULL ? this->m_currentEvent : event_for_overlap) - == EQUAL); - - _create_overlapping_curve(xc, c1 , c2, all_leaves_diff, first_parent, event_for_overlap); - CGAL_SS_PRINT_END_EOL("computing intersection (overlap with common ancestors)"); - return; - } + _create_overlapping_curve(xc, c1 , c2, all_leaves_diff, first_parent, + event_for_overlap); + CGAL_SS_PRINT_END_EOL("computing intersection (overlap with common ancestors)"); + return; + } } + auto ps_x_fnc = this->m_traits->parameter_space_in_x_2_object(); + auto ps_y_fnc = this->m_traits->parameter_space_in_y_2_object(); + // do compute the intersection of the two curves vector_inserter vi(m_x_objects) ; vector_inserter vi_end(m_x_objects); - vi_end = - this->m_traits->intersect_2_object()(c1->last_curve(), c2->last_curve(), vi); + auto intersector = this->m_traits->intersect_2_object(); + vi_end = intersector(c1->last_curve(), c2->last_curve(), vi); if (vi == vi_end) { CGAL_SS_PRINT_END_EOL("Computing intersection (no intersection)"); @@ -660,29 +664,19 @@ template // The two subCurves may start at the same point, in that case we ignore the // first intersection point. - - const Arr_parameter_space ps_x1 = - this->m_traits->parameter_space_in_x_2_object()(c1->last_curve(), - ARR_MIN_END); - const Arr_parameter_space ps_y1 = - this->m_traits->parameter_space_in_y_2_object()(c1->last_curve(), - ARR_MIN_END); - const Arr_parameter_space ps_x2 = - this->m_traits->parameter_space_in_x_2_object()(c2->last_curve(), - ARR_MIN_END); - const Arr_parameter_space ps_y2 = - this->m_traits->parameter_space_in_y_2_object()(c2->last_curve(), - ARR_MIN_END); + Arr_parameter_space ps_x1 = ps_x_fnc(c1->last_curve(), ARR_MIN_END); + Arr_parameter_space ps_y1 = ps_y_fnc(c1->last_curve(), ARR_MIN_END); + Arr_parameter_space ps_x2 = ps_x_fnc(c2->last_curve(), ARR_MIN_END); + Arr_parameter_space ps_y2 = ps_y_fnc(c2->last_curve(), ARR_MIN_END); if ((ps_x1 == ps_x2) && (ps_y1 == ps_y2) && ((ps_x1 != ARR_INTERIOR) || (ps_y1 != ARR_INTERIOR)) && this->m_traits->is_closed_2_object()(c1->last_curve(), ARR_MIN_END) && this->m_traits->is_closed_2_object()(c2->last_curve(), ARR_MIN_END)) { - if ( object_cast >(&(*vi)) != nullptr - && this->m_traits->equal_2_object() - (this->m_traits->construct_min_vertex_2_object()(c1->last_curve()), - this->m_traits->construct_min_vertex_2_object()(c2->last_curve()))) + if ((boost::get(&(*vi)) != nullptr) && + this->m_traits->equal_2_object()(ctr_min(c1->last_curve()), + ctr_min(c2->last_curve()))) { CGAL_SS_PRINT_TEXT("Skipping common left endpoint on boundary ..."); CGAL_SS_PRINT_EOL(); @@ -698,7 +692,7 @@ template vector_inserter vi_last = vi_end; --vi_last; - if (object_cast >(&(*vi_last)) != nullptr) { + if (boost::get(&(*vi_last)) != nullptr) { CGAL_SS_PRINT_TEXT("Skipping common right endpoint..."); CGAL_SS_PRINT_EOL(); --vi_end; @@ -708,18 +702,10 @@ template // In case both right curve-ends have boundary conditions and are not // open, check whether the right endpoints are the same. If they are, // skip the last intersection point. - const Arr_parameter_space ps_x1 = - this->m_traits->parameter_space_in_x_2_object()(c1->last_curve(), - ARR_MAX_END); - const Arr_parameter_space ps_y1 = - this->m_traits->parameter_space_in_y_2_object()(c1->last_curve(), - ARR_MAX_END); - const Arr_parameter_space ps_x2 = - this->m_traits->parameter_space_in_x_2_object()(c2->last_curve(), - ARR_MAX_END); - const Arr_parameter_space ps_y2 = - this->m_traits->parameter_space_in_y_2_object()(c2->last_curve(), - ARR_MAX_END); + Arr_parameter_space ps_x1 = ps_x_fnc(c1->last_curve(), ARR_MAX_END); + Arr_parameter_space ps_y1 = ps_y_fnc(c1->last_curve(), ARR_MAX_END); + Arr_parameter_space ps_x2 = ps_x_fnc(c2->last_curve(), ARR_MAX_END); + Arr_parameter_space ps_y2 = ps_y_fnc(c2->last_curve(), ARR_MAX_END); if ((ps_x1 == ps_x2) && (ps_y1 == ps_y2) && ((ps_x1 != ARR_INTERIOR) || (ps_y2 != ARR_INTERIOR)) && @@ -733,8 +719,7 @@ template vector_inserter vi_last = vi_end; --vi_last; - if (object_cast >(&(*vi_last)) != nullptr) - { + if (boost::get(&(*vi_last)) != nullptr) { CGAL_SS_PRINT_TEXT("Skipping common right endpoint on boundary..."); CGAL_SS_PRINT_EOL(); --vi_end; @@ -743,12 +728,11 @@ template } } - const std::pair* xp_point; - // Efi: why not skipping in a loop?check only one (that is, why not in a loop)? - // SL: curves are split and no event strictly before the current event should be reported + // SL: curves are split and no event strictly before the current event should + // be reported if (vi != vi_end) { - xp_point = object_cast >(&(*vi)); + const Intersection_point* xp_point = boost::get(&(*vi)); if (xp_point != nullptr) { // Skip the intersection point if it is not larger than the current // event. @@ -762,9 +746,8 @@ template bool first_i = true; for (; vi != vi_end; ++vi) { - unsigned int multiplicity = 0; - - xp_point = object_cast >(&(*vi)); + Multiplicity multiplicity = 0; + const Intersection_point* xp_point = boost::get(&(*vi)); if (xp_point != nullptr) { Point_2 xp = xp_point->first; multiplicity = xp_point->second; @@ -773,13 +756,14 @@ template _create_intersection_point(xp, multiplicity, c1, c2); } else { - X_monotone_curve_2 icv = *object_cast(&(*vi)); + const X_monotone_curve_2 icv = *boost::get(&(*vi)); // CGAL_assertion(icv != nullptr); CGAL_SS_PRINT_TEXT("Found an overlap"); CGAL_SS_PRINT_EOL(); + // event_for_overlap is only valid for the first intersection _create_overlapping_curve(icv, c1 , c2, all_leaves_diff, first_parent, - first_i ? event_for_overlap:NULL); // event_for_overlap is only valid for the first intersection + first_i ? event_for_overlap : NULL); } first_i = false; } From feefdde5a1a76d25e95442696253cb48ea7b722c Mon Sep 17 00:00:00 2001 From: Jane Tournois Date: Wed, 1 Apr 2020 14:15:21 +0200 Subject: [PATCH 203/568] use latest API of named parameters (after merging master) --- .../include/CGAL/tetrahedral_remeshing.h | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/Tetrahedral_remeshing/include/CGAL/tetrahedral_remeshing.h b/Tetrahedral_remeshing/include/CGAL/tetrahedral_remeshing.h index d467862b6da..be425ac7296 100644 --- a/Tetrahedral_remeshing/include/CGAL/tetrahedral_remeshing.h +++ b/Tetrahedral_remeshing/include/CGAL/tetrahedral_remeshing.h @@ -315,7 +315,7 @@ namespace CGAL bool protect = !remesh_surfaces; std::size_t max_it = choose_parameter(get_parameter(np, internal_np::number_of_iterations), 1); - typedef typename boost::lookup_named_param_def < + typedef typename internal_np::Lookup_named_param_def < internal_np::cell_selector_t, NamedParameters, Tetrahedral_remeshing::internal::All_cells_selected//default @@ -326,7 +326,7 @@ namespace CGAL typedef std::pair Edge_vv; typedef Tetrahedral_remeshing::internal::No_constraint_pmap No_edge; - typedef typename boost::lookup_named_param_def < + typedef typename internal_np::Lookup_named_param_def < internal_np::edge_is_constrained_t, NamedParameters, No_edge//default @@ -336,7 +336,7 @@ namespace CGAL typedef typename Tr::Facet Facet; typedef Tetrahedral_remeshing::internal::No_constraint_pmap No_facet; - typedef typename boost::lookup_named_param_def < + typedef typename internal_np::Lookup_named_param_def < internal_np::facet_is_constrained_t, NamedParameters, No_facet//default @@ -344,7 +344,7 @@ namespace CGAL FCMap fcmap = choose_parameter(get_parameter(np, internal_np::facet_is_constrained), No_facet()); - typedef typename boost::lookup_named_param_def < + typedef typename internal_np::Lookup_named_param_def < internal_np::remeshing_visitor_t, NamedParameters, Tetrahedral_remeshing::internal::Default_remeshing_visitor From 82ca7db4c2f896e7ae07b432934cd3b2dbe355f9 Mon Sep 17 00:00:00 2001 From: Jane Tournois Date: Wed, 1 Apr 2020 14:49:19 +0200 Subject: [PATCH 204/568] add const ref --- .../CGAL/Tetrahedral_remeshing/internal/smooth_vertices.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/smooth_vertices.h b/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/smooth_vertices.h index a1088ec2320..abe02f66778 100644 --- a/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/smooth_vertices.h +++ b/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/smooth_vertices.h @@ -337,7 +337,7 @@ namespace CGAL template void smooth_vertices(C3T3& c3t3, const bool protect_boundaries, - CellSelector cell_selector) + const CellSelector& cell_selector) { typedef typename C3T3::Cell_handle Cell_handle; typedef typename Gt::FT FT; From dbbee667af247a941fc0be6319f639e9c7928276 Mon Sep 17 00:00:00 2001 From: rathod-sahaab Date: Thu, 2 Apr 2020 18:31:00 +0530 Subject: [PATCH 205/568] replaced throw() with noexcept --- STL_Extension/include/CGAL/Object.h | 2 +- STL_Extension/include/CGAL/Uncertain.h | 2 +- STL_Extension/include/CGAL/exceptions.h | 2 +- ...gular_triangulation_cell_base_with_weighted_circumcenter_3.h | 2 +- ...gular_triangulation_cell_base_with_weighted_circumcenter_3.h | 2 +- 5 files changed, 5 insertions(+), 5 deletions(-) diff --git a/STL_Extension/include/CGAL/Object.h b/STL_Extension/include/CGAL/Object.h index 5a901eb3110..b6efd83c3f0 100644 --- a/STL_Extension/include/CGAL/Object.h +++ b/STL_Extension/include/CGAL/Object.h @@ -161,7 +161,7 @@ assign(T& t, const Object& o) struct Bad_object_cast : public std::bad_cast { - virtual const char * what() const throw() + virtual const char * what() const noexcept { return "CGAL::bad_object_cast: " "failed conversion using CGAL::object_cast"; diff --git a/STL_Extension/include/CGAL/Uncertain.h b/STL_Extension/include/CGAL/Uncertain.h index a4290beb337..01a27cc696c 100644 --- a/STL_Extension/include/CGAL/Uncertain.h +++ b/STL_Extension/include/CGAL/Uncertain.h @@ -67,7 +67,7 @@ public: Uncertain_conversion_exception(const std::string &s) : std::range_error(s) {} - ~Uncertain_conversion_exception() throw() {} + ~Uncertain_conversion_exception() noexcept {} }; diff --git a/STL_Extension/include/CGAL/exceptions.h b/STL_Extension/include/CGAL/exceptions.h index a828503e7b3..92567623563 100644 --- a/STL_Extension/include/CGAL/exceptions.h +++ b/STL_Extension/include/CGAL/exceptions.h @@ -97,7 +97,7 @@ public: m_msg( msg) {} - ~Failure_exception() throw() {} + ~Failure_exception() noexcept {} //! the name of the library that issues this message. std::string library() const { return m_lib; } diff --git a/Triangulation_3/doc/Triangulation_3/CGAL/Regular_triangulation_cell_base_with_weighted_circumcenter_3.h b/Triangulation_3/doc/Triangulation_3/CGAL/Regular_triangulation_cell_base_with_weighted_circumcenter_3.h index caac4df2c52..24d0f9ed64e 100644 --- a/Triangulation_3/doc/Triangulation_3/CGAL/Regular_triangulation_cell_base_with_weighted_circumcenter_3.h +++ b/Triangulation_3/doc/Triangulation_3/CGAL/Regular_triangulation_cell_base_with_weighted_circumcenter_3.h @@ -68,7 +68,7 @@ Swaps the Regular_triangulation_cell_base_with_weighted_circumcenter_3 and `othe This function should be preferred to an assignment or the copy constructor if `other` is deleted thereafter. */ -void swap (Regular_triangulation_cell_base_with_weighted_circumcenter_3& other) throw(); +void swap (Regular_triangulation_cell_base_with_weighted_circumcenter_3& other) noexcept; /// @} diff --git a/Triangulation_3/include/CGAL/Regular_triangulation_cell_base_with_weighted_circumcenter_3.h b/Triangulation_3/include/CGAL/Regular_triangulation_cell_base_with_weighted_circumcenter_3.h index 54dbdc91e4f..b79b2111a05 100644 --- a/Triangulation_3/include/CGAL/Regular_triangulation_cell_base_with_weighted_circumcenter_3.h +++ b/Triangulation_3/include/CGAL/Regular_triangulation_cell_base_with_weighted_circumcenter_3.h @@ -132,7 +132,7 @@ public: return *weighted_circumcenter_; } - void swap (Regular_triangulation_cell_base_with_weighted_circumcenter_3& other) throw() + void swap (Regular_triangulation_cell_base_with_weighted_circumcenter_3& other) noexcept { std::swap(static_cast(*this), static_cast(other)); std::swap(weighted_circumcenter_, other.weighted_circumcenter_); From 7436c149e1be42abb984c7f7069ee97334823bdf Mon Sep 17 00:00:00 2001 From: Efi Fogel Date: Mon, 6 Apr 2020 01:23:45 +0300 Subject: [PATCH 206/568] Fixed intersection return type --- .../Gps_agg_meta_traits.h | 154 +++--- .../Gps_insertion_meta_traits.h | 6 +- .../Gps_simplifier_traits.h | 456 +++++++----------- .../Gps_traits_decorator.h | 42 +- .../include/CGAL/Gps_traits_2.h | 2 + 5 files changed, 273 insertions(+), 387 deletions(-) diff --git a/Boolean_set_operations_2/include/CGAL/Boolean_set_operations_2/Gps_agg_meta_traits.h b/Boolean_set_operations_2/include/CGAL/Boolean_set_operations_2/Gps_agg_meta_traits.h index 854f90f70c3..5d062639df6 100644 --- a/Boolean_set_operations_2/include/CGAL/Boolean_set_operations_2/Gps_agg_meta_traits.h +++ b/Boolean_set_operations_2/include/CGAL/Boolean_set_operations_2/Gps_agg_meta_traits.h @@ -8,7 +8,8 @@ // SPDX-License-Identifier: GPL-3.0-or-later OR LicenseRef-Commercial // // -// Author(s) : Baruch Zukerman +// Author(s): Baruch Zukerman +// Efi Fogel #ifndef CGAL_BSO_2_GPS_AGG_META_TRAITS_H #define CGAL_BSO_2_GPS_AGG_META_TRAITS_H @@ -81,8 +82,8 @@ class Gps_agg_meta_traits : typedef typename Arr::Traits_adaptor_2 Traits; typedef Traits Gt2; - typedef typename Gt2::X_monotone_curve_2 Base_X_monotone_curve_2; - typedef typename Gt2::Point_2 Base_Point_2; + typedef typename Gt2::X_monotone_curve_2 Base_x_monotone_curve_2; + typedef typename Gt2::Point_2 Base_point_2; typedef typename Gt2::Construct_min_vertex_2 Base_Construct_min_vertex_2; typedef typename Gt2::Construct_max_vertex_2 Base_Construct_max_vertex_2; typedef typename Gt2::Compare_endpoints_xy_2 Base_Compare_endpoints_xy_2; @@ -106,8 +107,8 @@ public: typedef Point_with_vertex Point_data; private: - typedef Gps_traits_decorator - Base; + typedef Gps_agg_meta_traits Self; + typedef Gps_traits_decorator Base; public: typedef typename Base::X_monotone_curve_2 X_monotone_curve_2; @@ -145,93 +146,88 @@ public: class Intersect_2 { private: - Base_Intersect_2 m_base; - Base_Compare_endpoints_xy_2 m_base_cmp_endpoints; - Base_Compare_xy_2 m_base_cmp_xy; - Base_Construct_min_vertex_2 m_base_ctr_min_v; + const Self& m_traits; + + /*! Constructor. */ + Intersect_2(const Self& traits) : m_traits(traits) {} + + friend Self; public: - /*! Construct. */ - Intersect_2(const Base_Intersect_2& base, - const Base_Compare_endpoints_xy_2& base_cmp_endpoints, - const Base_Compare_xy_2& base_cmp_xy, - const Base_Construct_min_vertex_2& base_ctr_min_v) : - m_base(base), - m_base_cmp_endpoints(base_cmp_endpoints), - m_base_cmp_xy(base_cmp_xy), - m_base_ctr_min_v(base_ctr_min_v) - {} - template OutputIterator operator()(const X_monotone_curve_2& cv1, const X_monotone_curve_2& cv2, OutputIterator oi) const { - if (cv1.data().arr() == cv2.data().arr()) { - return oi; // the curves are disjoint-interior because they - // are already at the same arrangement. - } + // Check whether the curves are already in the same arrangement, and thus + // must be interior-disjoint + if (cv1.data().arr() == cv2.data().arr()) return oi; - const std::pair* base_pt; - const Base_X_monotone_curve_2* overlap_cv; - OutputIterator oi_end; - if(m_base_cmp_xy(m_base_ctr_min_v(cv1.base()), - m_base_ctr_min_v(cv2.base())) == LARGER) - oi_end = m_base(cv1.base(), cv2.base(), oi); + typedef const std::pair + Intersection_base_point; + typedef boost::variant + Intersection_base_result; + typedef const std::pair Intersection_point; + typedef boost::variant + Intersection_result; + + const auto* base_traits = m_traits.m_base_traits; + auto base_cmp_xy = base_traits->compare_xy_2_object(); + auto base_cmp_endpoints = base_traits->compare_endpoints_xy_2_object(); + auto base_ctr_min_vertex = base_traits->construct_min_vertex_2_object(); + auto base_intersect = base_traits->intersect_2_object(); + + std::vector xections; + if (base_cmp_xy(base_ctr_min_vertex(cv1.base()), + base_ctr_min_vertex(cv2.base())) == LARGER) + base_intersect(cv1.base(), cv2.base(), back_inserter(xections)); else - oi_end = m_base(cv2.base(), cv1.base(), oi); + base_intersect(cv2.base(), cv1.base(), back_inserter(xections)); - // convert objects that are associated with Base_X_monotone_curve_2 to + // convert objects that are associated with Base_x_monotone_curve_2 to // the extenede X_monotone_curve_2 - for (; oi != oi_end; ++oi) { - base_pt = object_cast >(&(*oi)); - + for (const auto& xection : xections) { + const Intersection_base_point* base_pt = + boost::get(&xection); if (base_pt != nullptr) { Point_2 point_plus(base_pt->first); // the extended point - *oi = CGAL::make_object(std::make_pair(point_plus, - base_pt->second)); + *oi++ = + Intersection_result(std::make_pair(point_plus, base_pt->second)); + continue; + } + + const Base_x_monotone_curve_2* overlap_cv = + boost::get(&xection); + CGAL_assertion(overlap_cv != nullptr); + unsigned int ov_bc; + unsigned int ov_twin_bc; + if (base_cmp_endpoints(cv1) == base_cmp_endpoints(cv2)) { + // cv1 and cv2 have the same directions + ov_bc = cv1.data().bc() + cv2.data().bc(); + ov_twin_bc = cv1.data().twin_bc() + cv2.data().twin_bc(); } else { - overlap_cv = object_cast(&(*oi)); - - if (overlap_cv != nullptr) { - unsigned int ov_bc; - unsigned int ov_twin_bc; - if (m_base_cmp_endpoints(cv1) == m_base_cmp_endpoints(cv2)) { - // cv1 and cv2 have the same directions - ov_bc = cv1.data().bc() + cv2.data().bc(); - ov_twin_bc = cv1.data().twin_bc() + cv2.data().twin_bc(); - } - else { - // cv1 and cv2 have opposite directions - ov_bc = cv1.data().bc() + cv2.data().twin_bc(); - ov_twin_bc = cv1.data().twin_bc() + cv2.data().bc(); - } - - if(m_base_cmp_endpoints(*overlap_cv) != m_base_cmp_endpoints(cv1)) { - // overlap_cv, cv1 have opposite directions - std::swap(ov_bc, ov_twin_bc); - } - - Curve_data cv_data(cv1.data().arr(), Halfedge_handle(), - ov_bc, ov_twin_bc); - *oi = CGAL::make_object(X_monotone_curve_2(*overlap_cv, cv_data)); - } + // cv1 and cv2 have opposite directions + ov_bc = cv1.data().bc() + cv2.data().twin_bc(); + ov_twin_bc = cv1.data().twin_bc() + cv2.data().bc(); } + + if (base_cmp_endpoints(*overlap_cv) != base_cmp_endpoints(cv1)) { + // overlap_cv, cv1 have opposite directions + std::swap(ov_bc, ov_twin_bc); + } + + Curve_data cv_data(cv1.data().arr(), Halfedge_handle(), + ov_bc, ov_twin_bc); + *oi++ = Intersection_result(X_monotone_curve_2(*overlap_cv, cv_data)); } - //return past-end iterator - return oi_end; + + return oi; } }; /*! Obtain an Intersect_2 functor object. */ - Intersect_2 intersect_2_object() const - { - return Intersect_2(this->m_base_tr->intersect_2_object(), - this->m_base_tr->compare_endpoints_xy_2_object(), - this->m_base_tr->compare_xy_2_object(), - this->m_base_tr->construct_min_vertex_2_object()); - } + Intersect_2 intersect_2_object() const { return Intersect_2(*this); } class Split_2 { private: @@ -256,7 +252,7 @@ public: /*! Obtain a Split_2 functor object. */ Split_2 split_2_object() const - { return Split_2(this->m_base_tr->split_2_object()); } + { return Split_2(this->m_base_traits->split_2_object()); } class Construct_min_vertex_2 { private: @@ -286,7 +282,7 @@ public: /*! Get a Construct_min_vertex_2 functor object. */ Construct_min_vertex_2 construct_min_vertex_2_object() const { - return Construct_min_vertex_2(this->m_base_tr-> + return Construct_min_vertex_2(this->m_base_traits-> construct_min_vertex_2_object()); } @@ -318,7 +314,7 @@ public: /*! Get a Construct_min_vertex_2 functor object. */ Construct_max_vertex_2 construct_max_vertex_2_object() const { - return Construct_max_vertex_2(this->m_base_tr-> + return Construct_max_vertex_2(this->m_base_traits-> construct_max_vertex_2_object()); } @@ -348,7 +344,7 @@ public: /*! Obtain a Construct_min_vertex_2 functor object. */ Compare_xy_2 compare_xy_2_object() const - { return Compare_xy_2(this->m_base_tr->compare_xy_2_object()); } + { return Compare_xy_2(this->m_base_traits->compare_xy_2_object()); } // left-right class Parameter_space_in_x_2 { @@ -380,7 +376,7 @@ public: /*! Obtain a Construct_min_vertex_2 functor object. */ Parameter_space_in_x_2 parameter_space_in_x_2_object() const { - return Parameter_space_in_x_2(this->m_base_tr-> + return Parameter_space_in_x_2(this->m_base_traits-> parameter_space_in_x_2_object()); } @@ -404,7 +400,7 @@ public: /*! Obtain a Construct_min_vertex_2 functor object. */ Compare_y_near_boundary_2 compare_y_near_boundary_2_object() const { - return Compare_y_near_boundary_2(this->m_base_tr-> + return Compare_y_near_boundary_2(this->m_base_traits-> compare_y_near_boundary_2_object() ); } @@ -443,7 +439,7 @@ public: /*! Obtain a Construct_min_vertex_2 functor object. */ Parameter_space_in_y_2 parameter_space_in_y_2_object() const { - return Parameter_space_in_y_2(this->m_base_tr-> + return Parameter_space_in_y_2(this->m_base_traits-> parameter_space_in_y_2_object()); } @@ -476,7 +472,7 @@ public: /*! Obtain a Construct_min_vertex_2 functor object. */ Compare_x_near_boundary_2 compare_x_near_boundary_2_object() const { - return Compare_x_near_boundary_2(this->m_base_tr-> + return Compare_x_near_boundary_2(this->m_base_traits-> compare_x_near_boundary_2_object()); } diff --git a/Boolean_set_operations_2/include/CGAL/Boolean_set_operations_2/Gps_insertion_meta_traits.h b/Boolean_set_operations_2/include/CGAL/Boolean_set_operations_2/Gps_insertion_meta_traits.h index 2c1557a2619..bbf2835fb68 100644 --- a/Boolean_set_operations_2/include/CGAL/Boolean_set_operations_2/Gps_insertion_meta_traits.h +++ b/Boolean_set_operations_2/include/CGAL/Boolean_set_operations_2/Gps_insertion_meta_traits.h @@ -75,7 +75,7 @@ public: Construct_min_vertex_2 construct_min_vertex_2_object () const { return Construct_min_vertex_2 - (this->m_base_tr->construct_min_vertex_2_object()); + (this->m_base_traits->construct_min_vertex_2_object()); } @@ -100,7 +100,7 @@ public: Construct_max_vertex_2 construct_max_vertex_2_object () const { return Construct_max_vertex_2 - (this->m_base_tr->construct_max_vertex_2_object()); + (this->m_base_traits->construct_max_vertex_2_object()); } class Compare_xy_2 @@ -123,7 +123,7 @@ public: /*! Get a Compare_xy_2 functor object. */ Compare_xy_2 compare_xy_2_object () const { - return Compare_xy_2(m_base_tr->compare_xy_2_object()); + return Compare_xy_2(m_base_traits->compare_xy_2_object()); } }; diff --git a/Boolean_set_operations_2/include/CGAL/Boolean_set_operations_2/Gps_simplifier_traits.h b/Boolean_set_operations_2/include/CGAL/Boolean_set_operations_2/Gps_simplifier_traits.h index 48b969adea8..1238537aba2 100644 --- a/Boolean_set_operations_2/include/CGAL/Boolean_set_operations_2/Gps_simplifier_traits.h +++ b/Boolean_set_operations_2/include/CGAL/Boolean_set_operations_2/Gps_simplifier_traits.h @@ -8,7 +8,8 @@ // SPDX-License-Identifier: GPL-3.0-or-later OR LicenseRef-Commercial // // -// Author(s) : Baruch Zukerman +// Author(s): Baruch Zukerman +// Efi Fogel #ifndef CGAL_GPS_SIMPLIFIER_TRAITS_H #define CGAL_GPS_SIMPLIFIER_TRAITS_H @@ -20,103 +21,67 @@ namespace CGAL { -class Gps_simplifier_curve_data -{ +class Gps_simplifier_curve_data { protected: unsigned int m_bc; unsigned int m_twin_bc; unsigned int m_index; public: - Gps_simplifier_curve_data() - {} + Gps_simplifier_curve_data() {} - Gps_simplifier_curve_data(unsigned int bc, - unsigned int twin_bc, + Gps_simplifier_curve_data(unsigned int bc, unsigned int twin_bc, unsigned int index): m_bc(bc), m_twin_bc(twin_bc), m_index(index) {} - unsigned int bc() const - { - return m_bc; - } + unsigned int bc() const { return m_bc; } - unsigned int twin_bc() const - { - return m_twin_bc; - } + unsigned int twin_bc() const { return m_twin_bc; } - unsigned int index() const - { - return m_index; - } + unsigned int index() const { return m_index; } - unsigned int& index() - { - return m_index; - } + unsigned int& index() { return m_index; } - unsigned int& twin_bc() - { - return m_twin_bc; - } + unsigned int& twin_bc() { return m_twin_bc; } - void set_bc(unsigned int bc) - { - m_bc = bc; - } + void set_bc(unsigned int bc) { m_bc = bc; } - void set_twin_bc(unsigned int twin_bc) - { - m_twin_bc = twin_bc; - } + void set_twin_bc(unsigned int twin_bc) { m_twin_bc = twin_bc; } - void set_index(unsigned int index) - { - m_index = index; - } + void set_index(unsigned int index) { m_index = index; } }; -struct Gps_simplifier_point_data -{ +struct Gps_simplifier_point_data { protected: unsigned int m_index; public: - Gps_simplifier_point_data() - {} + Gps_simplifier_point_data() {} - Gps_simplifier_point_data(unsigned int index) : m_index(index) - {} + Gps_simplifier_point_data(unsigned int index) : m_index(index) {} - unsigned int index() const - { - return m_index; - } + unsigned int index() const { return m_index; } - void set_index(unsigned int index) - { - m_index = index; - } + void set_index(unsigned int index) { m_index = index; } }; -template +template class Gps_simplifier_traits : public Gps_traits_decorator { public: - typedef Traits_ Traits; + typedef Traits_ Traits; typedef Gps_traits_decorator Base; - typedef Gps_simplifier_traits Self; - typedef typename Traits::X_monotone_curve_2 Base_X_monotone_curve_2; - typedef typename Traits::Point_2 Base_Point_2; + Gps_simplifier_point_data> Base; + typedef Gps_simplifier_traits Self; + typedef typename Traits::X_monotone_curve_2 Base_x_monotone_curve_2; + typedef typename Traits::Point_2 Base_point_2; typedef typename Traits::Construct_min_vertex_2 Base_Construct_min_vertex_2; typedef typename Traits::Construct_max_vertex_2 Base_Construct_max_vertex_2; typedef typename Traits::Compare_endpoints_xy_2 Base_Compare_endpoints_xy_2; @@ -129,9 +94,7 @@ public: protected: mutable unsigned int m_pgn_size; - public: - typedef typename Base::X_monotone_curve_2 X_monotone_curve_2; typedef typename Base::Point_2 Point_2; typedef typename Base::Multiplicity Multiplicity; @@ -139,333 +102,256 @@ public: typedef typename Base::Curve_data Curve_data; typedef typename Base::Point_data Point_data; - Gps_simplifier_traits() - {} + Gps_simplifier_traits() {} - Gps_simplifier_traits(const Traits & tr) : Base(tr) - {} + Gps_simplifier_traits(const Traits& tr) : Base(tr) {} - unsigned int polygon_size() const - { - return m_pgn_size; - } + unsigned int polygon_size() const { return m_pgn_size; } - void set_polygon_size(unsigned int pgn_size) const - { - m_pgn_size = pgn_size; - } + void set_polygon_size(unsigned int pgn_size) const { m_pgn_size = pgn_size; } bool is_valid_index(unsigned int index) const - { - return (index < m_pgn_size); - } + { return (index < m_pgn_size); } - unsigned int invalid_index() const - { - return (m_pgn_size); - } + unsigned int invalid_index() const { return (m_pgn_size); } - - class Intersect_2 - { + class Intersect_2 { private: - - Base_Intersect_2 m_base; - Base_Compare_endpoints_xy_2 m_base_cmp_endpoints; - Base_Compare_xy_2 m_base_cmp_xy; - Base_Construct_min_vertex_2 m_ctr_min_v; - const Self * m_self_tr; - - public: + /*! The traits (in case it has state) */ + const Self& m_traits; /*! Constructor. */ - Intersect_2 (const Base_Intersect_2& base, - const Base_Compare_endpoints_xy_2& base_cmp_endpoints, - const Base_Compare_xy_2& base_cmp_xy, - const Base_Construct_min_vertex_2& , - const Self* tr) : - m_base(base), - m_base_cmp_endpoints(base_cmp_endpoints), - m_base_cmp_xy(base_cmp_xy), - m_self_tr(tr) - {} + Intersect_2(const Self& tr) : m_traits(tr) {} - template - OutputIterator operator() (const X_monotone_curve_2& cv1, - const X_monotone_curve_2& cv2, - OutputIterator oi) const + friend Self; + + public: + template + OutputIterator operator()(const X_monotone_curve_2& cv1, + const X_monotone_curve_2& cv2, + OutputIterator oi) const { + typedef const std::pair + Intersection_base_point; + typedef boost::variant + Intersection_base_result; + typedef const std::pair Intersection_point; + typedef boost::variant + Intersection_result; + + const auto* base_traits = m_traits.m_base_traits; + auto base_cmp_xy = base_traits->compare_xy_2_object(); + auto base_cmp_endpoints = base_traits->compare_endpoints_xy_2_object(); + auto base_ctr_min_vertex = base_traits->construct_min_vertex_2_object(); + auto base_intersect = base_traits->intersect_2_object(); + //// if the two curves are incident, do not intersect them - //if(m_self_tr->is_valid_index(cv1.data().index()) && - // m_self_tr->is_valid_index(cv2.data().index())) + //if (m_traits.is_valid_index(cv1.data().index()) && + // m_traits.is_valid_index(cv2.data().index())) //{ // unsigned int index_diff = // (cv1.data().index() > cv2.data().index()) ? // (cv1.data().index() - cv2.data().index()): // (cv2.data().index() - cv1.data().index()); - // if(index_diff == 1 ||index_diff == m_self_tr->polygon_size() -1) + // if(index_diff == 1 ||index_diff == m_traits.polygon_size() -1) // { // return (oi); // } //} - const std::pair *base_pt; - const Base_X_monotone_curve_2 *overlap_cv; - OutputIterator oi_end; - if(m_base_cmp_xy(m_ctr_min_v(cv1.base()), - m_ctr_min_v(cv2.base())) == LARGER) - oi_end = m_base(cv1.base(), cv2.base(), oi); + std::vector xections; + if (base_cmp_xy(base_ctr_min_vertex(cv1.base()), + base_ctr_min_vertex(cv2.base())) == LARGER) + base_intersect(cv1.base(), cv2.base(), back_inserter(xections)); else - oi_end = m_base(cv2.base(), cv1.base(), oi); + base_intersect(cv2.base(), cv1.base(), back_inserter(xections)); - // convert objects that are associated with Base_X_monotone_curve_2 to + // convert objects that are associated with Base_x_monotone_curve_2 to // the extenede X_monotone_curve_2 - for(; oi != oi_end; ++oi) - { - base_pt = object_cast >(&(*oi)); - - if (base_pt != nullptr) - { - Point_data pt_data(m_self_tr->invalid_index()); - Point_2 point_plus (base_pt->first, pt_data); // the extended point - *oi = CGAL::make_object(std::make_pair(point_plus, - base_pt->second)); + for (const auto& xection : xections) { + const Intersection_base_point* base_pt = + boost::get(&xection); + if (base_pt != nullptr) { + Point_data pt_data(m_traits.invalid_index()); + Point_2 point_plus(base_pt->first, pt_data); // the extended point + *oi++ = + Intersection_result(std::make_pair(point_plus, base_pt->second)); + continue; } - else - { - overlap_cv = object_cast (&(*oi)); - if (overlap_cv != nullptr) - { - unsigned int ov_bc; - unsigned int ov_twin_bc; - if(m_base_cmp_endpoints(cv1) == m_base_cmp_endpoints(cv2)) - { - // cv1 and cv2 have the same directions - ov_bc = cv1.data().bc() + cv2.data().bc(); - ov_twin_bc = cv1.data().twin_bc() + cv2.data().twin_bc(); - } - else - { - // cv1 and cv2 have opposite directions - ov_bc = cv1.data().bc() + cv2.data().twin_bc(); - ov_twin_bc = cv1.data().twin_bc() + cv2.data().bc(); - } + const Base_x_monotone_curve_2* overlap_cv = + boost::get(&xection); - if(m_base_cmp_endpoints(*overlap_cv) != m_base_cmp_endpoints(cv1)) - { - // overlap_cv, cv1 have opposite directions - std::swap(ov_bc, ov_twin_bc); - } - - Curve_data cv_data(ov_bc, ov_twin_bc, m_self_tr->invalid_index()); - *oi = CGAL::make_object (X_monotone_curve_2 (*overlap_cv, cv_data)); - } + CGAL_assertion_code(overlap_cv != nullptr); + unsigned int ov_bc; + unsigned int ov_twin_bc; + if (base_cmp_endpoints(cv1) == base_cmp_endpoints(cv2)) { + // cv1 and cv2 have the same directions + ov_bc = cv1.data().bc() + cv2.data().bc(); + ov_twin_bc = cv1.data().twin_bc() + cv2.data().twin_bc(); } + else { + // cv1 and cv2 have opposite directions + ov_bc = cv1.data().bc() + cv2.data().twin_bc(); + ov_twin_bc = cv1.data().twin_bc() + cv2.data().bc(); + } + + if (base_cmp_endpoints(*overlap_cv) != base_cmp_endpoints(cv1)) { + // overlap_cv, cv1 have opposite directions + std::swap(ov_bc, ov_twin_bc); + } + + Curve_data cv_data(ov_bc, ov_twin_bc, m_traits.invalid_index()); + *oi++ = Intersection_result(X_monotone_curve_2(*overlap_cv, cv_data)); } - //return past-end iterator - return oi_end; + + return oi; } }; - /*! Get an Intersect_2 functor object. */ - Intersect_2 intersect_2_object () const - { - return Intersect_2(this->m_base_tr->intersect_2_object(), - this->m_base_tr->compare_endpoints_xy_2_object(), - this->m_base_tr->compare_xy_2_object(), - this->m_base_tr->construct_min_vertex_2_object(), - this); - } + /*! Obtain an Intersect_2 functor object. */ + Intersect_2 intersect_2_object () const { return Intersect_2(*this); } - class Split_2 - { + class Split_2 { private: - Base_Split_2 m_base_split; - const Self * m_self_tr; - - public: + const Self& m_traits; /*! Constructor. */ - Split_2 (const Base_Split_2& base, const Self* tr) : - m_base_split(base), - m_self_tr(tr) - {} + Split_2(const Self& tr) : m_traits(tr) {} - void operator() (const X_monotone_curve_2& cv, const Point_2 & p, - X_monotone_curve_2& c1, X_monotone_curve_2& c2) const + friend Self; + + public: + void operator()(const X_monotone_curve_2& cv, const Point_2 & p, + X_monotone_curve_2& c1, X_monotone_curve_2& c2) const { - m_base_split(cv.base(), - p.base(), - c1.base(), - c2.base()); + const auto* base_traits = m_traits.m_base_traits; + auto base_split = base_traits->split_2_object(); + base_split(cv.base(), p.base(), c1.base(), c2.base()); const Curve_data& cv_data = cv.data(); - c1.set_data(Curve_data(cv_data.bc(), - cv_data.twin_bc(), - m_self_tr->invalid_index())); + c1.set_data(Curve_data(cv_data.bc(), cv_data.twin_bc(), + m_traits.invalid_index())); - c2.set_data(Curve_data(cv_data.bc(), - cv_data.twin_bc(), - m_self_tr->invalid_index())); + c2.set_data(Curve_data(cv_data.bc(), cv_data.twin_bc(), + m_traits.invalid_index())); } }; /*! Get a Split_2 functor object. */ - Split_2 split_2_object () const - { - return Split_2(this->m_base_tr->split_2_object(), this); - } + Split_2 split_2_object () const { return Split_2(*this); } - class Construct_min_vertex_2 - { + class Construct_min_vertex_2 { private: - Base_Construct_min_vertex_2 m_base; - Base_Compare_endpoints_xy_2 m_base_cmp_endpoints; - const Self * m_self_tr; + const Self& m_traits; + + Construct_min_vertex_2(const Self& tr) : m_traits(tr) {} + + friend Self; public: - - Construct_min_vertex_2(const Base_Construct_min_vertex_2& base, - const Base_Compare_endpoints_xy_2& base_cmp_endpoints, - const Self * tr): - m_base(base), - m_base_cmp_endpoints(base_cmp_endpoints), - m_self_tr(tr) - {} - - /*! - * Get the left endpoint of the x-monotone curve (segment). + /*! Obtain the left endpoint of the x-monotone curve (segment). * \param cv The curve. * \return The left endpoint. */ - Point_2 operator() (const X_monotone_curve_2 & cv) const + Point_2 operator()(const X_monotone_curve_2 & cv) const { - if(!m_self_tr->is_valid_index(cv.data().index())) - { - return Point_2 (m_base(cv.base()), m_self_tr->invalid_index()); - } + const auto* base_traits = m_traits.m_base_traits; + auto base_ctr_min_vertex = base_traits->construct_min_vertex_2_object(); - Comparison_result res = m_base_cmp_endpoints(cv); + if (! m_traits.is_valid_index(cv.data().index())) + return Point_2(base_ctr_min_vertex(cv.base()), m_traits.invalid_index()); + + auto base_cmp_endpoints = base_traits->compare_endpoints_xy_2_object(); + Comparison_result res = base_cmp_endpoints(cv); Point_data pt_data; - if(res == SMALLER) - { + if (res == SMALLER) { // min vertex is the source pt_data.set_index(cv.data().index()); } - else - { + else { // min vertex is the target - pt_data.set_index((cv.data().index() + 1) % m_self_tr->polygon_size()); + pt_data.set_index((cv.data().index() + 1) % m_traits.polygon_size()); } - return Point_2 (m_base(cv.base()), pt_data); + return Point_2(base_ctr_min_vertex(cv.base()), pt_data); } }; /*! Get a Construct_min_vertex_2 functor object. */ Construct_min_vertex_2 construct_min_vertex_2_object () const - { - return Construct_min_vertex_2 - (this->m_base_tr->construct_min_vertex_2_object(), - this->m_base_tr->compare_endpoints_xy_2_object(), - this); - } + { return Construct_min_vertex_2(*this); } - - class Construct_max_vertex_2 - { + class Construct_max_vertex_2 { private: - Base_Construct_max_vertex_2 m_base; - Base_Compare_endpoints_xy_2 m_base_cmp_endpoints; - const Self * m_self_tr; + const Self& m_traits; + + Construct_max_vertex_2(const Self& tr) : m_traits(tr) {} + + friend Self; public: - - Construct_max_vertex_2(const Base_Construct_max_vertex_2& base, - const Base_Compare_endpoints_xy_2& base_cmp_endpoints, - const Self * tr): - m_base(base), - m_base_cmp_endpoints(base_cmp_endpoints), - m_self_tr(tr) - {} - - /*! - * Get the right endpoint of the x-monotone curve (segment). + /*! Obtain the right endpoint of the x-monotone curve (segment). * \param cv The curve. * \return The left endpoint. */ Point_2 operator() (const X_monotone_curve_2 & cv) const { - if(!m_self_tr->is_valid_index(cv.data().index())) - { - return Point_2 (m_base(cv.base()), m_self_tr->invalid_index()); - } - Comparison_result res = m_base_cmp_endpoints(cv); + const auto* base_traits = m_traits.m_base_traits; + auto base_ctr_max_vertex = base_traits->construct_max_vertex_2_object(); + if (! m_traits.is_valid_index(cv.data().index())) + return Point_2(base_ctr_max_vertex(cv.base()), m_traits.invalid_index()); + + auto base_cmp_endpoints = base_traits->compare_endpoints_xy_2_object(); + Comparison_result res = base_cmp_endpoints(cv); Point_data pt_data; - if(res == SMALLER) - { + if (res == SMALLER) { // min vertex is the target - pt_data.set_index((cv.data().index() + 1) % m_self_tr->polygon_size()); + pt_data.set_index((cv.data().index() + 1) % m_traits.polygon_size()); } - else - { + else { // min vertex is the source pt_data.set_index(cv.data().index()); } - return Point_2 (m_base(cv.base()), pt_data); + return Point_2(base_ctr_max_vertex(cv.base()), pt_data); } }; /*! Get a Construct_min_vertex_2 functor object. */ Construct_max_vertex_2 construct_max_vertex_2_object () const - { - return Construct_max_vertex_2 - (this->m_base_tr->construct_max_vertex_2_object(), - this->m_base_tr->compare_endpoints_xy_2_object(), - this); - } + { return Construct_max_vertex_2(*this); } - class Compare_xy_2 - { + class Compare_xy_2 { private: - Base_Compare_xy_2 m_base; - const Self * m_self_tr; + const Self& m_traits; + + Compare_xy_2(const Self& tr) : m_traits(tr) {} + + friend Self; public: - Compare_xy_2(const Base_Compare_xy_2& base, - const Self * tr): - m_base(base), - m_self_tr(tr) - {} - - - /*! - * Get the left endpoint of the x-monotone curve (segment). + /*! Obtain the left endpoint of the x-monotone curve (segment). * \param cv The curve. * \return The left endpoint. */ - Comparison_result operator() (const Point_2& p1, const Point_2& p2) const + Comparison_result operator()(const Point_2& p1, const Point_2& p2) const { + const auto* base_traits = m_traits.m_base_traits; + auto base_cmp_xy = base_traits->compare_xy_2_object(); + //if one of the indexes is invalid, compare p1 and p2 - if(! m_self_tr->is_valid_index(p1.data().index()) || - ! m_self_tr->is_valid_index(p2.data().index())) - return (m_base(p1.base(), p2.base())); + if (! m_traits.is_valid_index(p1.data().index()) || + ! m_traits.is_valid_index(p2.data().index())) + return (base_cmp_xy(p1.base(), p2.base())); // if the two point has the same index, return EQUAL - if(p1.data().index() == p2.data().index()) - { - return EQUAL; - } + if (p1.data().index() == p2.data().index()) return EQUAL; - return (m_base(p1.base(), p2.base())); + return (base_cmp_xy(p1.base(), p2.base())); } }; /*! Get a Construct_min_vertex_2 functor object. */ - Compare_xy_2 compare_xy_2_object () const - { - return Compare_xy_2(this->m_base_tr->compare_xy_2_object(), this); - } + Compare_xy_2 compare_xy_2_object () const { return Compare_xy_2(*this); } }; } //namespace CGAL diff --git a/Boolean_set_operations_2/include/CGAL/Boolean_set_operations_2/Gps_traits_decorator.h b/Boolean_set_operations_2/include/CGAL/Boolean_set_operations_2/Gps_traits_decorator.h index 74b62b9d5f5..74664d72795 100644 --- a/Boolean_set_operations_2/include/CGAL/Boolean_set_operations_2/Gps_traits_decorator.h +++ b/Boolean_set_operations_2/include/CGAL/Boolean_set_operations_2/Gps_traits_decorator.h @@ -202,25 +202,27 @@ public: protected: //Data members - const Base * m_base_tr; + const Base* m_base_traits; bool m_traits_owner; public: Gps_traits_decorator() : - m_base_tr(new Base()), + m_base_traits(new Base()), m_traits_owner(true) {} - Gps_traits_decorator(const Base & base_traits) : - m_base_tr(&base_traits), + Gps_traits_decorator(const Base& base_traits) : + m_base_traits(&base_traits), m_traits_owner(false) {} ~Gps_traits_decorator() { - if (m_traits_owner) - delete m_base_tr; + if (m_traits_owner) { + delete m_base_traits; + m_base_traits = nullptr; + } } class Compare_x_2 @@ -242,7 +244,7 @@ public: /*! Get a Compare_x_2 functor object. */ Compare_x_2 compare_x_2_object () const { - return Compare_x_2(m_base_tr->compare_x_2_object()); + return Compare_x_2(m_base_traits->compare_x_2_object()); } @@ -265,7 +267,7 @@ public: /*! Get a Compare_xy_2 functor object. */ Compare_xy_2 compare_xy_2_object () const { - return Compare_xy_2(m_base_tr->compare_xy_2_object()); + return Compare_xy_2(m_base_traits->compare_xy_2_object()); } class Construct_min_vertex_2 @@ -288,7 +290,7 @@ public: /*! Get a Construct_min_vertex_2 functor object. */ Construct_min_vertex_2 construct_min_vertex_2_object () const { - return Construct_min_vertex_2(m_base_tr->construct_min_vertex_2_object()); + return Construct_min_vertex_2(m_base_traits->construct_min_vertex_2_object()); } class Construct_max_vertex_2 @@ -311,7 +313,7 @@ public: /*! Get a Construct_max_vertex_2 functor object. */ Construct_max_vertex_2 construct_max_vertex_2_object () const { - return Construct_max_vertex_2(m_base_tr->construct_max_vertex_2_object()); + return Construct_max_vertex_2(m_base_traits->construct_max_vertex_2_object()); } @@ -334,7 +336,7 @@ public: /*! Get a Is_vertical_2 functor object. */ Is_vertical_2 is_vertical_2_object() const { - return Is_vertical_2(m_base_tr->is_vertical_2_object()); + return Is_vertical_2(m_base_traits->is_vertical_2_object()); } @@ -358,7 +360,7 @@ public: /*! Get a compare_y_at_x_2_object functor object. */ Compare_y_at_x_2 compare_y_at_x_2_object() const { - return Compare_y_at_x_2(m_base_tr->compare_y_at_x_2_object()); + return Compare_y_at_x_2(m_base_traits->compare_y_at_x_2_object()); } @@ -384,7 +386,7 @@ public: /*! Get a Compare_y_at_x_right_2 functor object. */ Compare_y_at_x_right_2 compare_y_at_x_right_2_object() const { - return Compare_y_at_x_right_2(m_base_tr->compare_y_at_x_right_2_object()); + return Compare_y_at_x_right_2(m_base_traits->compare_y_at_x_right_2_object()); } @@ -407,7 +409,7 @@ public: /*! Get a Equal_2 functor object. */ Equal_2 equal_2_object() const { - return Equal_2(m_base_tr->equal_2_object()); + return Equal_2(m_base_traits->equal_2_object()); } @@ -432,7 +434,7 @@ public: /*! Get a Split_2 functor object. */ Split_2 split_2_object() const { - return Split_2(m_base_tr->split_2_object()); + return Split_2(m_base_traits->split_2_object()); } @@ -495,9 +497,9 @@ public: /*! Get a Intersect_2 functor object. */ Intersect_2 intersect_2_object() const { - return Intersect_2(m_base_tr->intersect_2_object(), - m_base_tr->compare_xy_2_object(), - m_base_tr->construct_min_vertex_2_object()); + return Intersect_2(m_base_traits->intersect_2_object(), + m_base_traits->compare_xy_2_object(), + m_base_traits->construct_min_vertex_2_object()); } @@ -522,7 +524,7 @@ public: /*! Get a Compare_endpoints_xy_2 functor object. */ Compare_endpoints_xy_2 compare_endpoints_xy_2_object() const { - return Compare_endpoints_xy_2(m_base_tr->compare_endpoints_xy_2_object()); + return Compare_endpoints_xy_2(m_base_traits->compare_endpoints_xy_2_object()); } @@ -545,7 +547,7 @@ public: /*! Get a Construct_opposite_2 functor object. */ Construct_opposite_2 construct_opposite_2_object() const { - return Construct_opposite_2(m_base_tr->construct_opposite_2_object()); + return Construct_opposite_2(m_base_traits->construct_opposite_2_object()); } }; diff --git a/Boolean_set_operations_2/include/CGAL/Gps_traits_2.h b/Boolean_set_operations_2/include/CGAL/Gps_traits_2.h index 068e95c2169..3f916b7e71d 100644 --- a/Boolean_set_operations_2/include/CGAL/Gps_traits_2.h +++ b/Boolean_set_operations_2/include/CGAL/Gps_traits_2.h @@ -35,6 +35,8 @@ public: typedef typename Base::Point_2 Point_2; typedef typename Base::X_monotone_curve_2 X_monotone_curve_2; + typedef typename Base::Multiplicity Multiplicity; + //Polygon_2 type is required by GeneralPolygonSetTraits Concept typedef General_polygon_t Polygon_2; //Polygon_2 is a model of the GeneralPolygon2 concept From 3863b969e5fb66a11af6905beccb286f3434dfcd Mon Sep 17 00:00:00 2001 From: Efi Fogel Date: Mon, 6 Apr 2020 02:01:25 +0300 Subject: [PATCH 207/568] Fixed intersection return type and cleaned up --- .../Minkowski_sum_2/Arr_labeled_traits_2.h | 363 +++++++----------- 1 file changed, 149 insertions(+), 214 deletions(-) diff --git a/Minkowski_sum_2/include/CGAL/Minkowski_sum_2/Arr_labeled_traits_2.h b/Minkowski_sum_2/include/CGAL/Minkowski_sum_2/Arr_labeled_traits_2.h index 256769ff2bf..f8e614a3142 100644 --- a/Minkowski_sum_2/include/CGAL/Minkowski_sum_2/Arr_labeled_traits_2.h +++ b/Minkowski_sum_2/include/CGAL/Minkowski_sum_2/Arr_labeled_traits_2.h @@ -7,7 +7,7 @@ // $Id$ // SPDX-License-Identifier: GPL-3.0-or-later OR LicenseRef-Commercial // -// Author(s) : Ron Wein +// Author(s): Ron Wein #ifndef CGAL_ARR_LABELED_TRAITS_2_H #define CGAL_ARR_LABELED_TRAITS_2_H @@ -25,95 +25,79 @@ namespace CGAL { * such that the comparison of two points, as well as the computation of the * intersections between two segments can be easily filtered. */ -template -class Arr_labeled_traits_2 : public Traits_ -{ +template +class Arr_labeled_traits_2 : public Traits_ { private: + typedef Traits_ Base_traits_2; + typedef Arr_labeled_traits_2 Traits; - typedef Traits_ Base_traits_2; - typedef typename Base_traits_2::Point_2 Base_point_2; - typedef typename Base_traits_2::X_monotone_curve_2 Base_x_monotone_curve_2; + typedef typename Base_traits_2::Point_2 Base_point_2; + typedef typename Base_traits_2::X_monotone_curve_2 Base_x_monotone_curve_2; public: + typedef typename Base_traits_2::Multiplicity Multiplicity; /*! \class * A point extended by a label. */ - class Point_2 : public Base_point_2 - { + class Point_2 : public Base_point_2 { private: - - Point_label _label; + Point_label m_label; public: - /*! Default constructor. */ - Point_2 () - {} + Point_2() {} /*! Constructor from a base point. */ - Point_2 (const Base_point_2& p) : - Base_point_2 (p), - _label() + Point_2(const Base_point_2& p) : + Base_point_2(p), + m_label() {} /*! Constructor from a point an a label. */ - Point_2 (const Base_point_2& p, const Point_label& label) : - Base_point_2 (p), - _label (label) + Point_2(const Base_point_2& p, const Point_label& label) : + Base_point_2(p), + m_label(label) {} /*! Get the label. */ - const Point_label& label () const - { - return (_label); - } + const Point_label& label() const { return (m_label); } }; /*! \class * An x-monotone curve extended by a label. */ - class X_monotone_curve_2 : public Base_x_monotone_curve_2 - { + class X_monotone_curve_2 : public Base_x_monotone_curve_2 { private: - - X_curve_label _label; + X_curve_label m_label; public: - /*! Default constructor. */ - X_monotone_curve_2 () - {} + X_monotone_curve_2() {} /*! Constructor from a base x-monotone curve. */ - X_monotone_curve_2 (const Base_x_monotone_curve_2& p) : - Base_x_monotone_curve_2 (p), - _label() + X_monotone_curve_2(const Base_x_monotone_curve_2& p) : + Base_x_monotone_curve_2(p), + m_label() {} /*! Constructor from an x-monotone curve an a label. */ - X_monotone_curve_2 (const Base_x_monotone_curve_2& p, - const X_curve_label& label) : - Base_x_monotone_curve_2 (p), - _label (label) + X_monotone_curve_2(const Base_x_monotone_curve_2& p, + const X_curve_label& label) : + Base_x_monotone_curve_2(p), + m_label(label) {} /*! Get the label (const version). */ - const X_curve_label& label () const - { - return (_label); - } + const X_curve_label& label() const { return m_label; } /*! Get the label (non-const version). */ - X_curve_label& label () - { - return (_label); - } + X_curve_label& label() { return m_label; } /*! Set the label. */ - void set_label (const X_curve_label& label) + void set_label(const X_curve_label& label) { - _label = label; + m_label = label; return; } }; @@ -122,8 +106,7 @@ public: typedef Tag_false Has_merge_category; /*! Default constructor. */ - Arr_labeled_traits_2 () - {} + Arr_labeled_traits_2() {} // Inherited functors: typedef typename Base_traits_2::Is_vertical_2 Is_vertical_2; @@ -134,280 +117,232 @@ public: /// \name Overriden functors. //@{ - class Compare_x_2 - { + class Compare_x_2 { private: - - const Base_traits_2 * base; - - public: + const Base_traits_2& m_base_traits; /*! Constructor. */ - Compare_x_2 (const Base_traits_2 * _base) : - base (_base) - {} + Compare_x_2(const Base_traits_2& base_tr) : m_base_traits(base_tr) {} - /*! - * Compare the x-coordinates of two points. + friend Traits; + + public: + /*! Compare the x-coordinates of two points. */ - Comparison_result operator() (const Point_2& p1, const Point_2& p2) const + Comparison_result operator()(const Point_2& p1, const Point_2& p2) const { // If two points have the same label, they are equal. - if (p1.label() == p2.label()) - return (EQUAL); + if (p1.label() == p2.label()) return (EQUAL); - return (base->compare_x_2_object()(p1, p2)); + return (m_base_traits.compare_x_2_object()(p1, p2)); } }; /*! Get a Compare_x_2 functor object. */ - Compare_x_2 compare_x_2_object () const - { - return (Compare_x_2 (this)); - } + Compare_x_2 compare_x_2_object() const { return (Compare_x_2(*this)); } - - class Compare_xy_2 - { + class Compare_xy_2 { private: - - const Base_traits_2 * base; - - public: + const Base_traits_2& m_base_traits; /*! Constructor. */ - Compare_xy_2 (const Base_traits_2 *_base) : - base (_base) - {} + Compare_xy_2(const Base_traits_2& base_tr) : m_base_traits(base_tr) {} - /*! - * Compare two points lexigoraphically: by x, then by y. + friend Traits; + + public: + /*! Compare two points lexigoraphically: by x, then by y. */ - Comparison_result operator() (const Point_2& p1, const Point_2& p2) const + Comparison_result operator()(const Point_2& p1, const Point_2& p2) const { // If two points have the same label, they are equal. - if (p1.label() == p2.label()) - return (EQUAL); + if (p1.label() == p2.label()) return (EQUAL); - return (base->compare_xy_2_object()(p1, p2)); + return (m_base_traits.compare_xy_2_object()(p1, p2)); } }; - /*! Get a Compare_xy_2 functor object. */ - Compare_xy_2 compare_xy_2_object () const - { - return (Compare_xy_2 (this)); - } + /*! Obtain a Compare_xy_2 functor object. */ + Compare_xy_2 compare_xy_2_object() const { return Compare_xy_2(*this); } - - class Construct_min_vertex_2 - { + class Construct_min_vertex_2 { private: - - const Base_traits_2 * base; - - public: + const Base_traits_2& m_base_traits; /*! Constructor. */ - Construct_min_vertex_2 (const Base_traits_2 *_base) : - base (_base) + Construct_min_vertex_2(const Base_traits_2& base_tr) : + m_base_traits(base_tr) {} - /*! - * Get the left endpoint of the x-monotone curve. - */ - Point_2 operator() (const X_monotone_curve_2& cv) const - { - const Base_point_2& pt = base->construct_min_vertex_2_object() (cv); + friend Traits; - if (cv.label().right_count() == 1 && cv.label().left_count() == 0) - { + public: + /*! Obtain the left endpoint of the x-monotone curve. + */ + Point_2 operator()(const X_monotone_curve_2& cv) const + { + auto base_ctr_min_vertex = m_base_traits.construct_min_vertex_2_object(); + const Base_point_2& pt = base_ctr_min_vertex(cv); + + if ((cv.label().right_count() == 1) && (cv.label().left_count() == 0)) { // A curve directed from left to right: - Point_label label (cv.label().component(), cv.label().index()); + Point_label label(cv.label().component(), cv.label().index()); return (Point_2 (pt, label)); } - else if (cv.label().right_count() == 0 && cv.label().left_count() == 1) + else if ((cv.label().right_count() == 0) && + (cv.label().left_count() == 1)) { // A curve directed from right to left: - Point_label label (cv.label().component(), - cv.label().is_last() ? 0 : cv.label().index()+1); + Point_label label(cv.label().component(), + cv.label().is_last() ? 0 : cv.label().index()+1); - return (Point_2 (pt, label)); + return (Point_2(pt, label)); } // Assign an invalid label to the point. - return (Point_2 (pt)); + return Point_2(pt); } }; /*! Get a Construct_min_vertex_2 functor object. */ Construct_min_vertex_2 construct_min_vertex_2_object () const - { - return (Construct_min_vertex_2 (this)); - } + { return Construct_min_vertex_2(*this); } - - class Construct_max_vertex_2 - { + class Construct_max_vertex_2 { private: - - const Base_traits_2 * base; - - public: + const Base_traits_2& m_base_traits; /*! Constructor. */ - Construct_max_vertex_2 (const Base_traits_2 *_base) : - base (_base) + Construct_max_vertex_2(const Base_traits_2& base_tr) : + m_base_traits(base_tr) {} - /*! - * Get the right endpoint of the x-monotone curve. + friend Traits; + + public: + /*! Obtain the right endpoint of the x-monotone curve. */ - Point_2 operator() (const X_monotone_curve_2& cv) const + Point_2 operator()(const X_monotone_curve_2& cv) const { - const Base_point_2& pt = base->construct_max_vertex_2_object() (cv); + auto base_ctr_max_vertex = m_base_traits.construct_max_vertex_2_object(); + const Base_point_2& pt = base_ctr_max_vertex(cv); - if (cv.label().right_count() == 1 && cv.label().left_count() == 0) - { + if ((cv.label().right_count() == 1) && (cv.label().left_count() == 0)) { // A curve directed from left to right: - Point_label label (cv.label().component(), - cv.label().is_last() ? 0 : cv.label().index()+1); + Point_label label(cv.label().component(), + cv.label().is_last() ? 0 : cv.label().index()+1); - return (Point_2 (pt, label)); + return Point_2(pt, label); } - else if (cv.label().right_count() == 0 && cv.label().left_count() == 1) + else if ((cv.label().right_count() == 0) && + (cv.label().left_count() == 1)) { // A curve directed from right to left: - Point_label label (cv.label().component(), cv.label().index()); + Point_label label(cv.label().component(), cv.label().index()); - return (Point_2 (pt, label)); + return Point_2(pt, label); } // Assign an invalid label to the point. - return (Point_2 (pt)); + return Point_2(pt); } }; /*! Get a Construct_max_vertex_2 functor object. */ Construct_max_vertex_2 construct_max_vertex_2_object () const - { - return (Construct_max_vertex_2 (this)); - } + { return Construct_max_vertex_2(*this); } - - class Split_2 - { + class Split_2 { private: - - const Base_traits_2 * base; - - public: + const Base_traits_2& m_base_traits; /*! Constructor. */ - Split_2 (const Base_traits_2 * _base) : - base (_base) - {} + Split_2(const Base_traits_2& base_tr) : m_base_traits(base_tr) {} - /*! - * Split a given x-monotone curve at a given point into two sub-curves. + friend Traits; + + public: + /*! Split a given x-monotone curve at a given point into two sub-curves. */ - void operator() (const X_monotone_curve_2& cv, const Point_2& p, - X_monotone_curve_2& c1, X_monotone_curve_2& c2) const + void operator()(const X_monotone_curve_2& cv, const Point_2& p, + X_monotone_curve_2& c1, X_monotone_curve_2& c2) const { // Split the base curve into two. - base->split_2_object() (cv, p, c1, c2); + m_base_traits.split_2_object()(cv, p, c1, c2); // Duplicate the label to both subcurves. - c1.set_label (cv.label()); - c2.set_label (cv.label()); - - return; + c1.set_label(cv.label()); + c2.set_label(cv.label()); } }; /*! Get a Split_2 functor object. */ - Split_2 split_2_object () const - { - return (Split_2 (this)); - } + Split_2 split_2_object() const { return Split_2(*this); } - - class Intersect_2 - { + class Intersect_2 { private: - - const Base_traits_2 * base; + const Base_traits_2& m_base_traits; public: - /*! Constructor. */ - Intersect_2 (const Base_traits_2 * _base) : - base (_base) - {} + Intersect_2(const Base_traits_2& traits) : m_base_traits(traits) {} - /*! - * Find the intersections of the two given curves and insert them to the + /*! Find the intersections of the two given curves and insert them to the * given output iterator. */ - template - OutputIterator operator() (const X_monotone_curve_2& cv1, - const X_monotone_curve_2& cv2, - OutputIterator oi) const + template + OutputIterator operator()(const X_monotone_curve_2& cv1, + const X_monotone_curve_2& cv2, + OutputIterator oi) const { + typedef std::pair Intersection_base_point; + typedef boost::variant + Intersection_base_result; + typedef std::pair Intersection_point; + typedef boost::variant + Intersection_result; + // In case the curves are adjacent in their curve sequence, we do // not have to compute their intersection (we already know that they // have just one common endpoint). - if (cv1.label().is_adjacent (cv2.label())) - return (oi); + if (cv1.label().is_adjacent(cv2.label())) return oi; // Compute the intersection. - std::list base_objs; + std::list xections; + m_base_traits.intersect_2_object()(cv1, cv2, std::back_inserter(xections)); - base->intersect_2_object() (cv1, cv2, std::back_inserter (base_objs)); - - if (base_objs.empty()) - return (oi); + if (xections.empty()) return oi; // Attach labels to the intersection objects. - std::list::iterator obj_it; - const std::pair *base_pt; - const Base_x_monotone_curve_2 *base_xcv; + for (const auto& xection : xections) { + const Intersection_base_point* base_pt = + boost::get(&xection); - for (obj_it = base_objs.begin(); obj_it != base_objs.end(); ++obj_it) - { - base_pt = - object_cast > (&(*obj_it)); - - if (base_pt != nullptr) - { + if (base_pt != nullptr) { // Attach an invalid label to an itersection point. - *oi = CGAL::make_object - (std::make_pair (Point_2 (base_pt->first), base_pt->second)); - ++oi; + *oi++ = Intersection_result(std::make_pair(Point_2(base_pt->first), + base_pt->second)); + continue; } - else - { - base_xcv = object_cast (&(*obj_it)); - CGAL_assertion (base_xcv != nullptr); - // Attach a merged label to the overlapping curve. - *oi = CGAL::make_object - (X_monotone_curve_2 (*base_xcv, - X_curve_label (cv1.label(), cv2.label()))); - ++oi; - } + const Base_x_monotone_curve_2* base_xcv = + boost::get(&xection); + CGAL_assertion(base_xcv != nullptr); + + // Attach a merged label to the overlapping curve. + *oi++ = + Intersection_result(X_monotone_curve_2(*base_xcv, + X_curve_label(cv1.label(), + cv2.label()))); } - return (oi); + return oi; } }; /*! Get an Intersect_2 functor object. */ - Intersect_2 intersect_2_object () const - { - return (Intersect_2 (this)); - } + Intersect_2 intersect_2_object() const { return Intersect_2(*this); } //@} }; From 6eefda4e6de0d1116009c68fe4739c96f95dd698 Mon Sep 17 00:00:00 2001 From: Efi Fogel Date: Mon, 6 Apr 2020 15:34:28 +0300 Subject: [PATCH 208/568] Added missing include --- .../include/CGAL/Arr_circular_line_arc_traits_2.h | 10 +++++----- .../include/CGAL/Arr_curve_data_traits_2.h | 2 ++ .../include/CGAL/Arr_geodesic_arc_on_sphere_traits_2.h | 2 ++ .../CGAL/Arr_geometry_traits/Conic_x_monotone_arc_2.h | 9 +++++---- .../include/CGAL/Arr_linear_traits_2.h | 5 ++++- .../include/CGAL/Arr_polycurve_traits_2.h | 2 ++ .../include/CGAL/Arr_tracing_traits_2.h | 2 ++ 7 files changed, 22 insertions(+), 10 deletions(-) diff --git a/Arrangement_on_surface_2/include/CGAL/Arr_circular_line_arc_traits_2.h b/Arrangement_on_surface_2/include/CGAL/Arr_circular_line_arc_traits_2.h index f64bcbfc867..9e8f8085807 100644 --- a/Arrangement_on_surface_2/include/CGAL/Arr_circular_line_arc_traits_2.h +++ b/Arrangement_on_surface_2/include/CGAL/Arr_circular_line_arc_traits_2.h @@ -22,7 +22,6 @@ #include - /*! \file * This file was developed at Inria, France, and copied over to the * Arrangement_2 package, which it is now part of. It contains a traits @@ -30,12 +29,13 @@ * It is based on the circular kernel. */ -#include -#include -#include - #include +#include + +#include +#include + namespace CGAL { namespace VariantFunctors{ diff --git a/Arrangement_on_surface_2/include/CGAL/Arr_curve_data_traits_2.h b/Arrangement_on_surface_2/include/CGAL/Arr_curve_data_traits_2.h index 5be881f3601..7ed8e459334 100644 --- a/Arrangement_on_surface_2/include/CGAL/Arr_curve_data_traits_2.h +++ b/Arrangement_on_surface_2/include/CGAL/Arr_curve_data_traits_2.h @@ -22,6 +22,8 @@ */ #include + +#include #include #include diff --git a/Arrangement_on_surface_2/include/CGAL/Arr_geodesic_arc_on_sphere_traits_2.h b/Arrangement_on_surface_2/include/CGAL/Arr_geodesic_arc_on_sphere_traits_2.h index 9b511d4b7b4..c366df483e5 100644 --- a/Arrangement_on_surface_2/include/CGAL/Arr_geodesic_arc_on_sphere_traits_2.h +++ b/Arrangement_on_surface_2/include/CGAL/Arr_geodesic_arc_on_sphere_traits_2.h @@ -25,6 +25,8 @@ #include +#include + #include #include #include diff --git a/Arrangement_on_surface_2/include/CGAL/Arr_geometry_traits/Conic_x_monotone_arc_2.h b/Arrangement_on_surface_2/include/CGAL/Arr_geometry_traits/Conic_x_monotone_arc_2.h index b58ff269944..a2e2d7790d4 100644 --- a/Arrangement_on_surface_2/include/CGAL/Arr_geometry_traits/Conic_x_monotone_arc_2.h +++ b/Arrangement_on_surface_2/include/CGAL/Arr_geometry_traits/Conic_x_monotone_arc_2.h @@ -18,15 +18,16 @@ * Header file for the _Conic_x_monotone_arc_2 class. */ -#include - #include #include +#include + +#include + namespace CGAL { -/*! - * Representation of an x-monotone conic arc. +/*! Representation of an x-monotone conic arc. * The class is templated by a representation of a general bounded conic arc. */ diff --git a/Arrangement_on_surface_2/include/CGAL/Arr_linear_traits_2.h b/Arrangement_on_surface_2/include/CGAL/Arr_linear_traits_2.h index 7f8d4a6a570..4c73bcb4880 100644 --- a/Arrangement_on_surface_2/include/CGAL/Arr_linear_traits_2.h +++ b/Arrangement_on_surface_2/include/CGAL/Arr_linear_traits_2.h @@ -24,12 +24,15 @@ * in the arrangement package. */ +#include + +#include + #include #include #include #include #include -#include namespace CGAL { diff --git a/Arrangement_on_surface_2/include/CGAL/Arr_polycurve_traits_2.h b/Arrangement_on_surface_2/include/CGAL/Arr_polycurve_traits_2.h index 59a6be2c319..6d61db9e61e 100644 --- a/Arrangement_on_surface_2/include/CGAL/Arr_polycurve_traits_2.h +++ b/Arrangement_on_surface_2/include/CGAL/Arr_polycurve_traits_2.h @@ -25,6 +25,8 @@ */ #include + +#include #include #include diff --git a/Arrangement_on_surface_2/include/CGAL/Arr_tracing_traits_2.h b/Arrangement_on_surface_2/include/CGAL/Arr_tracing_traits_2.h index 9197b38149f..5847dd43e02 100644 --- a/Arrangement_on_surface_2/include/CGAL/Arr_tracing_traits_2.h +++ b/Arrangement_on_surface_2/include/CGAL/Arr_tracing_traits_2.h @@ -26,6 +26,8 @@ #include #include +#include + #include #include #include From 3d42c79d851bdbbdbea335ca07d61b9ebdafcb32 Mon Sep 17 00:00:00 2001 From: Efi Fogel Date: Mon, 6 Apr 2020 15:59:03 +0300 Subject: [PATCH 209/568] Announced the Change of intersection return type from legacy CGAL::Object to modern boost::variant --- Installation/CHANGES.md | 71 +++++++++++++++++++++++++---------------- 1 file changed, 43 insertions(+), 28 deletions(-) diff --git a/Installation/CHANGES.md b/Installation/CHANGES.md index fcd93c9ac8d..b823b61e230 100644 --- a/Installation/CHANGES.md +++ b/Installation/CHANGES.md @@ -6,19 +6,34 @@ Release History Release date: June 2020 +### 2D Arrangement on Suurface + - Changed intersection return type from legacy CGAL::Object to modern + boost::variant. + As there is an implicit conversion from boost::variant to CGAL::Object, the + new code is backward compatible. However, it is recomnded that all calls + to the intersection functions are fixed to use the new return type. + +### 2D Regularized Boolean Operations + - Changed intersection return type from legacy CGAL::Object to modern + boost::variant. + +### 2D Minkowski sums + - Changed intersection return type from legacy CGAL::Object to modern + boost::variant. + ### Surface Mesh Topology (new package) - This package allows to compute some topological invariants of surfaces. For now, it is possible to test if two (closed) curves on a combinatorial surface are homotopic. The user can choose - between free homotopy and homotopy with fixed endpoints. + between free homotopy and homotopy with fixed endpoints. A contractibility test is also provided. ### 3D Fast Intersection and Distance Computation - **Breaking change**: the internal search tree is now lazily constructed. To disable it, one must call the new function `do_not_accelerate_distance_queries()` before the first distance query. -### Intersecting Sequences of dD Iso-oriented Boxes +### Intersecting Sequences of dD Iso-oriented Boxes - Added parallel versions of the functions `CGAL::box_intersection_d()` and `CGAL::box_self_intersection_d()`. ### CGAL and the Boost Graph Library (BGL) @@ -27,7 +42,7 @@ Release date: June 2020 ### Polygon Mesh Processing -- Introduced a new function, `CGAL::Polygon_mesh_processing::remove_connected_components_of_negligible_size()`, +- Introduced a new function, `CGAL::Polygon_mesh_processing::remove_connected_components_of_negligible_size()`, which can be used to remove connected components whose area or volume is under a certain threshold. Area and volume thresholds are either specified by the user or deduced from the bounding box of the mesh. - Added the function `CGAL::Polygon_mesh_processing::volume_connected_component()` that can be used to @@ -39,10 +54,10 @@ Release date: June 2020 - The function `CGAL::Polygon_mesh_processing::stitch_borders()` now returns the number of halfedge pairs that were stitched. - New function to split meshes along a mesh or a plane: - `CGAL::Polygon_mesh_processing::split()` + `CGAL::Polygon_mesh_processing::split()` - New function to split a single mesh containing several connected components into several meshes containing one connected component: `CGAL::Polygon_mesh_processing::split_connected_components()` - - Added parallel versions of the functions `CGAL::Polygon_mesh_processing::does_self_intersect()` + - Added parallel versions of the functions `CGAL::Polygon_mesh_processing::does_self_intersect()` and `CGAL::Polygon_mesh_processing::self_intersections()`. - The function `CGAL::Polygon_mesh_processing::polygon_soup_to_polygon_mesh` now allows passing a point map (for the point range) and a vertex point map (for the polygon mesh) via named parameters. @@ -52,14 +67,14 @@ Release date: June 2020 - Added wrapper functions for registration: - `CGAL::OpenGR::compute_registration_transformation()` computes the registration transformation for two point sets using Super4PCS algorithm implemented in the third party library OpenGR. - - `CGAL::OpenGR::register_point_sets()` computes the registration transformation for two point + - `CGAL::OpenGR::register_point_sets()` computes the registration transformation for two point sets using Super4PCS algorithm implemented in the third party library OpenGR, and registers the points sets by transforming the data point set using the computed transformation. - `CGAL::pointmatcher::compute_registration_transformation()` computes the registration transformation for two point sets using ICP algorithm implemented in the third party library libpointmatcher. - `CGAL::pointmatcher::register_point_sets()` computes the registration transformation for two point - sets using ICP algorithm implemented in the third party library libpointmatcher, and registers + sets using ICP algorithm implemented in the third party library libpointmatcher, and registers the points sets by transforming the data point set using the computed transformation. ### 2D Triangulations @@ -115,7 +130,7 @@ Release date: June 2020 ### STL Extensions for CGAL - Added a new concurrency tag: `CGAL::Parallel_if_available_tag`. This tag is a convenience typedef to `CGAL::Parallel_tag` if the third party library TBB has been found and linked with, and to `CGAL::Sequential_tag` otherwise. - + ### Convex_hull_3 - A new overload for `convex_hull_3()` that takes a model of `VertexListGraph` has been added. @@ -145,13 +160,13 @@ Release date: November 2019 ### [Polygonal Surface Reconstruction](https://doc.cgal.org/5.0/Manual/packages.html#PkgPolygonalSurfaceReconstruction) (new package) - - This package provides a method for piecewise planar object reconstruction from point clouds. - The method takes as input an unordered point set sampled from a piecewise planar object - and outputs a compact and watertight surface mesh interpolating the input point set. - The method assumes that all necessary major planes are provided (or can be extracted from - the input point set using the shape detection method described in Point Set Shape Detection, - or any other alternative methods).The method can handle arbitrary piecewise planar objects - and is capable of recovering sharp features and is robust to noise and outliers. See also + - This package provides a method for piecewise planar object reconstruction from point clouds. + The method takes as input an unordered point set sampled from a piecewise planar object + and outputs a compact and watertight surface mesh interpolating the input point set. + The method assumes that all necessary major planes are provided (or can be extracted from + the input point set using the shape detection method described in Point Set Shape Detection, + or any other alternative methods).The method can handle arbitrary piecewise planar objects + and is capable of recovering sharp features and is robust to noise and outliers. See also the associated [blog entry](https://www.cgal.org/2019/08/05/Polygonal_surface_reconstruction/). ### [Shape Detection](https://doc.cgal.org/5.0/Manual/packages.html#PkgShapeDetection) (major changes) @@ -166,11 +181,11 @@ Release date: November 2019 ### [2D and 3D Linear Geometry Kernel](https://doc.cgal.org/5.0/Manual/packages.html#PkgKernel23) - Added a new concept, [`ComputeApproximateAngle_3`](https://doc.cgal.org/5.0/Kernel_23/classKernel_1_1ComputeApproximateAngle__3.html), to the 3D Kernel concepts to compute the approximate angle between two 3D vectors. Corresponding functors - in the model ([`Compute_approximate_angle_3`](https://doc.cgal.org/5.0/Kernel_23/classKernel.html#a183c9ac358a4ccddc04e680f8ed16c0b)) + in the model ([`Compute_approximate_angle_3`](https://doc.cgal.org/5.0/Kernel_23/classKernel.html#a183c9ac358a4ccddc04e680f8ed16c0b)) and free function ([`approximate_angle`](https://doc.cgal.org/5.0/Kernel_23/group__approximate__angle__grp.html)) have also been added. - - The following objects are now hashable and thus trivially usable - with [`std::unordered_set`](https://en.cppreference.com/w/cpp/container/unordered_set) + - The following objects are now hashable and thus trivially usable + with [`std::unordered_set`](https://en.cppreference.com/w/cpp/container/unordered_set) and [`std::unordered_map`](https://en.cppreference.com/w/cpp/header/unordered_map): `CGAL::Aff_transformation_2`, `CGAL::Aff_transformation_3`, `CGAL::Bbox_2`, `CGAL::Bbox_3`, `CGAL::Circle_2`, @@ -180,11 +195,11 @@ Release date: November 2019 `CGAL::Weighted_point_2` and `CGAL::Weighted_point_3`. ### [Polygon Mesh Processing](https://doc.cgal.org/latest/Manual/packages.html#PkgPolygonMeshProcessing) - - Introduced a [wide range of new functions](https://doc.cgal.org/5.0/Polygon_mesh_processing/index.html#title36) + - Introduced a [wide range of new functions](https://doc.cgal.org/5.0/Polygon_mesh_processing/index.html#title36) related to location of queries on a triangle mesh, such as [`CGAL::Polygon_mesh_processing::locate(Point, Mesh)`](https://doc.cgal.org/5.0/Polygon_mesh_processing/group__PMP__locate__grp.html#gada09bd8740ba69ead9deca597d53cf15). The location of a point on a triangle mesh is expressed as the pair of a face and the barycentric - coordinates of the point in this face, enabling robust manipulation of locations + coordinates of the point in this face, enabling robust manipulation of locations (for example, intersections of two 3D segments living within the same face). - Added the mesh smoothing function [`smooth_mesh()`](https://doc.cgal.org/5.0/Polygon_mesh_processing/group__PMP__meshing__grp.html#gaa0551d546f6ab2cd9402bea12d8332a3), which can be used to improve the quality of triangle elements based on various geometric characteristics. @@ -207,14 +222,14 @@ Release date: November 2019 or vertices appearing in multiple umbrellas) of a mesh. ### [3D Point Set](https://doc.cgal.org/5.0/Manual/packages.html#PkgPointSet3) - - The [PLY IO functions](https://doc.cgal.org/5.0/Point_set_3/group__PkgPointSet3IO.html) now take an additional optional parameter to + - The [PLY IO functions](https://doc.cgal.org/5.0/Point_set_3/group__PkgPointSet3IO.html) now take an additional optional parameter to read/write comments from/in the PLY header. ### [Point Set Processing](https://doc.cgal.org/latest/Manual/packages.html#PkgPointSetProcessing3) - **Breaking change**: the API using iterators and overloads for optional parameters (deprecated since CGAL 4.12) has been removed. The current (and now only) API uses ranges and Named Parameters. - Added the possibility to use the named parameter - [`neighbor_radius`](https://doc.cgal.org/5.0/Point_set_processing_3/group__psp__namedparameters.html#PSP_neighbor_radius) + [`neighbor_radius`](https://doc.cgal.org/5.0/Point_set_processing_3/group__psp__namedparameters.html#PSP_neighbor_radius) to use spherical neighbor queries instead of K-nearest neighbors queries for the following functions: [`CGAL::bilateral_smooth_point_set()`](https://doc.cgal.org/5.0/Point_set_processing_3/group__PkgPointSetProcessing3Algorithms.html#ga4f82723e2f0bb33f3677e29e0208a256), [`CGAL::jet_estimate_normals()`](https://doc.cgal.org/5.0/Point_set_processing_3/group__PkgPointSetProcessing3Algorithms.html#ga0cd0f87de690d4edf82740e856efa491), @@ -257,7 +272,7 @@ Release date: November 2019 ### [3D Triangulations](https://doc.cgal.org/5.0/Manual/packages.html#PkgTriangulation3) - **Breaking change**: The [constructor](https://doc.cgal.org/5.0/Triangulation_3/classCGAL_1_1Triangulation__3.html#a63f67cf6aaadcee14318cf56a36d247a) and the [`insert()`](https://doc.cgal.org/5.0/Triangulation_3/classCGAL_1_1Triangulation__3.html#ad3353128386bbb51f79d0263e7f67337) - function of [`CGAL::Triangulation_3`](https://doc.cgal.org/5.0/Triangulation_3/classCGAL_1_1Triangulation__3.html) + function of [`CGAL::Triangulation_3`](https://doc.cgal.org/5.0/Triangulation_3/classCGAL_1_1Triangulation__3.html) which take a range of points as argument are now guaranteed to insert the points following the order of `InputIterator`. Note that this change only affects the base class `Triangulation_3` @@ -269,14 +284,14 @@ Release date: November 2019 ### [Surface Mesh](https://doc.cgal.org/5.0/Manual/packages.html#PkgSurfaceMesh) - Introduced new functions to read and write using the PLY format, - [`CGAL::read_ply()`](https://doc.cgal.org/5.0/Surface_mesh/group__PkgSurface__mesh.html#ga42f6ad486ddab74e13d3dc53f511c343) - and [`CGAL::write_ply()`](https://doc.cgal.org/5.0/Surface_mesh/group__PkgSurface__mesh.html#ga77bbb79d449c981895eedb6c3c23bd14), + [`CGAL::read_ply()`](https://doc.cgal.org/5.0/Surface_mesh/group__PkgSurface__mesh.html#ga42f6ad486ddab74e13d3dc53f511c343) + and [`CGAL::write_ply()`](https://doc.cgal.org/5.0/Surface_mesh/group__PkgSurface__mesh.html#ga77bbb79d449c981895eedb6c3c23bd14), enabling users to save and load additional property maps of the surface mesh. ### [CGAL and Solvers](https://doc.cgal.org/5.0/Manual/packages.html#PkgSolverInterface) - Added [concepts](https://doc.cgal.org/5.0/Solver_interface/group__PkgSolverInterfaceConcepts.html) - and [models](https://doc.cgal.org/5.0/Solver_interface/group__PkgSolverInterfaceRef.html) - for solving Mixed Integer Programming (MIP) problems with or without constraints. + and [models](https://doc.cgal.org/5.0/Solver_interface/group__PkgSolverInterfaceRef.html) + for solving Mixed Integer Programming (MIP) problems with or without constraints. ### [3D Boolean Operations on Nef Polyhedra](https://doc.cgal.org/5.0/Manual/packages.html#PkgNef3) - Added a function to convert a Nef_polyhedron_3 to a polygon soup: [`CGAL::convert_nef_polyhedron_to_polygon_soup()`](https://doc.cgal.org/5.0/Nef_3/group__PkgNef3IOFunctions.html#ga28a9eb4da0cd6153f0c16f7f9eaf6665) @@ -305,7 +320,7 @@ Release 4.14 Release date: March 2019 ### 2D Periodic Hyperbolic Triangulations (new package) - + - This package allows the computation of Delaunay triangulations of the Bolza surface. The Bolza surface is the most symmetric hyperbolic surface of genus 2. Its fundamental domain is the From 50fd3f8fd7b6e189859fdc2e4c3e492dcf673d35 Mon Sep 17 00:00:00 2001 From: Efi Fogel Date: Mon, 6 Apr 2020 16:24:48 +0300 Subject: [PATCH 210/568] Fixed documentation of intersection return types --- .../Concepts/ArrTraits--Intersect_2.h | 28 +++++++++---------- 1 file changed, 13 insertions(+), 15 deletions(-) diff --git a/Arrangement_on_surface_2/doc/Arrangement_on_surface_2/Concepts/ArrTraits--Intersect_2.h b/Arrangement_on_surface_2/doc/Arrangement_on_surface_2/Concepts/ArrTraits--Intersect_2.h index 3af9a106877..9d65d678de0 100644 --- a/Arrangement_on_surface_2/doc/Arrangement_on_surface_2/Concepts/ArrTraits--Intersect_2.h +++ b/Arrangement_on_surface_2/doc/Arrangement_on_surface_2/Concepts/ArrTraits--Intersect_2.h @@ -16,21 +16,19 @@ public: /// A model of this concept must provide: /// @{ -/*! -computes the intersections of `xc1` and `xc2` and -inserts them in an ascending lexicographic \f$ xy\f$-order into the -output iterator `oi`. The value-type of `Output_iterator` is -`CGAL::Object`, where each `Object` wraps either a -`pair` object, which -represents an intersection point with its multiplicity (in case the -multiplicity is undefined or unknown, it should be set to \f$ 0\f$) or an -`ArrTraits::X_monotone_curve_2` object, representing an -overlapping subcurve of `xc1` and `xc2`. The operator -returns a past-the-end iterator for the output sequence. -*/ -Output_iterator operator()(ArrTraits::X_monotone_curve_2 xc1, -ArrTraits::X_monotone_curve_2 xc2, -Output_iterator& oi); +/*! computes the intersections of `xc1` and `xc2` and inserts them in an + * ascending lexicographic \f$ xy\f$-order into a range begining at + * `oi`. The value-type of `OutputIterator` is `boost::variant` of either the + * type `pair` or the type + * `ArrTraits::X_monotone_curve_2`. An object of the former type represents an + * intersection point with its multiplicity (in case the multiplicity is + * undefined or unknown, it should be set to \f$ 0\f$). An object of the latter + * type representing an overlapping subcurve of `xc1` and `xc2`. The operator + * returns a past-the-end iterator of the destination range. + */ +OutputIterator operator()(ArrTraits::X_monotone_curve_2 xc1, + ArrTraits::X_monotone_curve_2 xc2, + Output_iterator& oi); /// @} From 61d51502c02c0096d5e5cfa75b8aad12b53c88dd Mon Sep 17 00:00:00 2001 From: Efi Fogel Date: Mon, 6 Apr 2020 16:37:46 +0300 Subject: [PATCH 211/568] Fixed documentation of intersection return types --- .../Concepts/ArrTraits--Intersect_2.h | 2 +- .../ArrDirectionalTraits--Intersect_2.h | 35 +++++++++---------- 2 files changed, 18 insertions(+), 19 deletions(-) diff --git a/Arrangement_on_surface_2/doc/Arrangement_on_surface_2/Concepts/ArrTraits--Intersect_2.h b/Arrangement_on_surface_2/doc/Arrangement_on_surface_2/Concepts/ArrTraits--Intersect_2.h index 9d65d678de0..146eb151548 100644 --- a/Arrangement_on_surface_2/doc/Arrangement_on_surface_2/Concepts/ArrTraits--Intersect_2.h +++ b/Arrangement_on_surface_2/doc/Arrangement_on_surface_2/Concepts/ArrTraits--Intersect_2.h @@ -18,7 +18,7 @@ public: /*! computes the intersections of `xc1` and `xc2` and inserts them in an * ascending lexicographic \f$ xy\f$-order into a range begining at - * `oi`. The value-type of `OutputIterator` is `boost::variant` of either the + * `oi`. The type `OutputIterator` dereferences a `boost::variant` of either the * type `pair` or the type * `ArrTraits::X_monotone_curve_2`. An object of the former type represents an * intersection point with its multiplicity (in case the multiplicity is diff --git a/Boolean_set_operations_2/doc/Boolean_set_operations_2/Concepts/ArrDirectionalTraits--Intersect_2.h b/Boolean_set_operations_2/doc/Boolean_set_operations_2/Concepts/ArrDirectionalTraits--Intersect_2.h index 4d09d1f41e3..76efa0e5073 100644 --- a/Boolean_set_operations_2/doc/Boolean_set_operations_2/Concepts/ArrDirectionalTraits--Intersect_2.h +++ b/Boolean_set_operations_2/doc/Boolean_set_operations_2/Concepts/ArrDirectionalTraits--Intersect_2.h @@ -16,24 +16,23 @@ public: /// A model of this concept must provide: /// @{ -/*! -computes the intersections of `xc1` and `xc2` and -inserts them in an ascending lexicographic \f$ xy\f$-order into the -output iterator `oi`. The value-type of `Output_iterator` is -`CGAL::Object`, where each `Object` wraps either a -`pair` object, which -represents an intersection point with its multiplicity (in case the -multiplicity is undefined or unknown, it is set to \f$ 0\f$) or an -`ArrDirectionalTraits::X_monotone_curve_2` object, representing an -overlapping subcurve of `xc1` and `xc2`. In the latter case, -the overlapping subcurves are given the direction of `xc1` and -`xc2` if their directions are identical. Otherwise, the overlapping -subcurves are given an arbitrary direction. The operator returns a -past-the-end iterator for the output sequence. -*/ -Output_iterator operator()(ArrDirectionalTraits::X_monotone_curve_2 xc1, -ArrDirectionalTraits::X_monotone_curve_2 xc2, -Output_iterator& oi); +/*! computes the intersections of `xc1` and `xc2` and inserts them in an + * ascending lexicographic \f$ xy\f$-order into a range begining at + * `oi`. The type `OutputIterator` dereferences a `boost::variant` of either the + * type `pair` or the type + * `ArrDirectionalTraits::X_monotone_curve_2`. An object of the former type + * represents an intersection point with its multiplicity (in case the + * multiplicity is undefined or unknown, it is set to \f$ 0\f$). An object of + * the latter type representing an overlapping subcurve of `xc1` and `xc2`. The + * overlapping subcurves are given the direction of `xc1` and `xc2` if their + * directions are identical. Otherwise, the overlapping subcurves are given an + * arbitrary direction. The operator returns a past-the-end iterator of the + * destination range. + */ +OutputIterator operator()(ArrDirectionalTraits::X_monotone_curve_2 xc1, + ArrDirectionalTraits::X_monotone_curve_2 xc2, + Output_iterator& oi); /// @} From 52caec6d82c5ad58536d7e05be18cdd229e6d0ad Mon Sep 17 00:00:00 2001 From: Efi Fogel Date: Mon, 6 Apr 2020 16:42:27 +0300 Subject: [PATCH 212/568] Fixed typo; Improved format --- Installation/CHANGES.md | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/Installation/CHANGES.md b/Installation/CHANGES.md index b823b61e230..2e59c1f8d42 100644 --- a/Installation/CHANGES.md +++ b/Installation/CHANGES.md @@ -6,20 +6,20 @@ Release History Release date: June 2020 -### 2D Arrangement on Suurface - - Changed intersection return type from legacy CGAL::Object to modern - boost::variant. +### 2D Arrangement on Surface + - Changed intersection return type from legacy `CGAL::Object` to modern + `boost::variant`. As there is an implicit conversion from boost::variant to CGAL::Object, the - new code is backward compatible. However, it is recomnded that all calls + new code is backward compatible. However, it is recommended that all calls to the intersection functions are fixed to use the new return type. ### 2D Regularized Boolean Operations - - Changed intersection return type from legacy CGAL::Object to modern - boost::variant. + - Changed intersection return type from legacy `CGAL::Object` to modern + `boost::variant`. ### 2D Minkowski sums - - Changed intersection return type from legacy CGAL::Object to modern - boost::variant. + - Changed intersection return type from legacy `CGAL::Object` to modern + `boost::variant`. ### Surface Mesh Topology (new package) From f05f53a74f409f8e450b6a8829c3e5721e54e480 Mon Sep 17 00:00:00 2001 From: Efi Fogel Date: Mon, 6 Apr 2020 16:49:51 +0300 Subject: [PATCH 213/568] Refined description of the change in the intersection return type of 2d arrangements --- Installation/CHANGES.md | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/Installation/CHANGES.md b/Installation/CHANGES.md index 2e59c1f8d42..1b8181660e5 100644 --- a/Installation/CHANGES.md +++ b/Installation/CHANGES.md @@ -8,18 +8,19 @@ Release date: June 2020 ### 2D Arrangement on Surface - Changed intersection return type from legacy `CGAL::Object` to modern - `boost::variant`. + `boost::variant` in all traits concepts and models. As there is an implicit conversion from boost::variant to CGAL::Object, the new code is backward compatible. However, it is recommended that all calls to the intersection functions are fixed to use the new return type. ### 2D Regularized Boolean Operations - Changed intersection return type from legacy `CGAL::Object` to modern - `boost::variant`. + `boost::variant` in the concept `ArrDirectionalTraits::Intersect_2` and + its models.. ### 2D Minkowski sums - Changed intersection return type from legacy `CGAL::Object` to modern - `boost::variant`. + `boost::variant` in the (internally used) model `Arr_labeled_traits_2`. ### Surface Mesh Topology (new package) From 819aeded4494ef57097e45a81f141572f29f8f6b Mon Sep 17 00:00:00 2001 From: Jane Tournois Date: Tue, 7 Apr 2020 13:34:28 +0200 Subject: [PATCH 214/568] fix file name --- .../include/CGAL/Tetrahedral_remeshing/internal/FMLS.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/FMLS.h b/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/FMLS.h index 58e30f055ee..dbecf6a79b1 100644 --- a/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/FMLS.h +++ b/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/FMLS.h @@ -27,7 +27,7 @@ #include #include -#include +#include #include #include From 42edead686b8699b7bd1705339da784d2c924aed Mon Sep 17 00:00:00 2001 From: Simon Giraudot Date: Wed, 8 Apr 2020 10:28:22 +0200 Subject: [PATCH 215/568] Fix text and trailing whitespaces --- .../Point_set_processing_3.txt | 8 ++++---- .../include/CGAL/cluster_point_set.h | 14 +++++++------- 2 files changed, 11 insertions(+), 11 deletions(-) diff --git a/Point_set_processing_3/doc/Point_set_processing_3/Point_set_processing_3.txt b/Point_set_processing_3/doc/Point_set_processing_3/Point_set_processing_3.txt index 2de6c16e556..5d9c75a112b 100644 --- a/Point_set_processing_3/doc/Point_set_processing_3/Point_set_processing_3.txt +++ b/Point_set_processing_3/doc/Point_set_processing_3/Point_set_processing_3.txt @@ -318,15 +318,15 @@ points in the domain. If an input point set represents several objects which are spatially separated, a clustering algorithm can be applied to identify connected -components on a nearest neighbors graph built using a query sphere of +components on a nearest neighbor graph built using a query sphere of fixed radius centered on each point. The clustering is stored in a cluster map which associates each input point with the index of the cluster it belongs to: users can then use this map however they find it relevant to their use case, for example -segmenting the input point set into several (one per -cluster). \cgalFigureRef{Point_set_processing_3figclustering} shows different clustering -outputs. +segmenting the input point set into one point set per +cluster. \cgalFigureRef{Point_set_processing_3figclustering} shows +different clustering outputs. \cgalFigureBegin{Point_set_processing_3figclustering,clustering.png} Point Set Clustering outputs (one color per cluster). Top: input point diff --git a/Point_set_processing_3/include/CGAL/cluster_point_set.h b/Point_set_processing_3/include/CGAL/cluster_point_set.h index c06979fe106..16b394c482f 100644 --- a/Point_set_processing_3/include/CGAL/cluster_point_set.h +++ b/Point_set_processing_3/include/CGAL/cluster_point_set.h @@ -63,7 +63,7 @@ CGAL::Emptyset_iterator get_adjacencies (const NamedParameters&, CGAL::Emptyset_ /** \ingroup PkgPointSetProcessing3Algorithms - Identifies connected components on a nearest neighbors graph built + Identifies connected components on a nearest neighbor graph built using a query sphere of fixed radius centered on each point. \tparam PointRange is a model of `Range`. The value type of its @@ -110,7 +110,7 @@ std::size_t cluster_point_set (PointRange& points, { using parameters::choose_parameter; using parameters::get_parameter; - + // basic geometric types typedef typename PointRange::iterator iterator; typedef typename iterator::value_type value_type; @@ -161,11 +161,11 @@ std::size_t cluster_point_set (PointRange& points, // Flooding algorithm from each point std::size_t done = 0; std::size_t size = points.size(); - + for (iterator it = points.begin(); it != points.end(); ++ it) { const value_type& p = *it; - + if (get (cluster_map, p) != -1) continue; @@ -181,7 +181,7 @@ std::size_t cluster_point_set (PointRange& points, put (cluster_map, *current, nb_clusters); ++ done; - + if (callback && !callback (callback_factor * (done + 1) / double(size))) return (nb_clusters + 1); @@ -207,7 +207,7 @@ std::size_t cluster_point_set (PointRange& points, for (const value_type& p : points) { std::size_t c0 = get (cluster_map, p); - + neighbors.clear(); neighbor_query.get_iterators (get (point_map, p), 0, neighbor_radius, std::back_inserter (neighbors), false); @@ -230,7 +230,7 @@ std::size_t cluster_point_set (PointRange& points, auto last = std::unique (adj.begin(), adj.end()); std::copy (adj.begin(), last, adjacencies); } - + return nb_clusters; } From 7929c7d872c892dbfadc957a5325a664a5690c4d Mon Sep 17 00:00:00 2001 From: Marc Glisse Date: Wed, 8 Apr 2020 14:42:47 +0200 Subject: [PATCH 216/568] Remove outdated comment. --- NewKernel_d/include/CGAL/Epick_d.h | 2 -- 1 file changed, 2 deletions(-) diff --git a/NewKernel_d/include/CGAL/Epick_d.h b/NewKernel_d/include/CGAL/Epick_d.h index 075c12b42ed..39575dd034a 100644 --- a/NewKernel_d/include/CGAL/Epick_d.h +++ b/NewKernel_d/include/CGAL/Epick_d.h @@ -39,8 +39,6 @@ struct Epick_d_help1 constexpr Epick_d_help1(int d):CGAL_BASE(d){} }; #undef CGAL_BASE -// determinant is only safe for use with integers with this condition, see LA_eigen/LA.h - #define CGAL_BASE \ Cartesian_filter_K< \ Epick_d_help1, \ From a03eff675b33e83c4013afc5f80e88eb073b1749 Mon Sep 17 00:00:00 2001 From: Marc Glisse Date: Wed, 8 Apr 2020 16:03:18 +0200 Subject: [PATCH 217/568] Switch to std::is_empty --- NewKernel_d/include/CGAL/NewKernel_d/store_kernel.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/NewKernel_d/include/CGAL/NewKernel_d/store_kernel.h b/NewKernel_d/include/CGAL/NewKernel_d/store_kernel.h index b9bfe61749f..5249dff2fcb 100644 --- a/NewKernel_d/include/CGAL/NewKernel_d/store_kernel.h +++ b/NewKernel_d/include/CGAL/NewKernel_d/store_kernel.h @@ -13,12 +13,12 @@ #define CGAL_STORE_KERNEL_H #include -#include +#include namespace CGAL { namespace internal { BOOST_MPL_HAS_XXX_TRAIT_DEF(Do_not_store_kernel) -template::value,bool=has_Do_not_store_kernel::value> struct Do_not_store_kernel { +template::value,bool=has_Do_not_store_kernel::value> struct Do_not_store_kernel { enum { value=false }; typedef Tag_false type; }; From 38f249b7a1930b77a55904ab7d9fa5088dcbd733 Mon Sep 17 00:00:00 2001 From: Marc Glisse Date: Wed, 8 Apr 2020 18:43:28 +0200 Subject: [PATCH 218/568] Use members rather than private bases --- .../CGAL/NewKernel_d/Cartesian_filter_K.h | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/NewKernel_d/include/CGAL/NewKernel_d/Cartesian_filter_K.h b/NewKernel_d/include/CGAL/NewKernel_d/Cartesian_filter_K.h index ad57f2e541e..b5b17fc2c23 100644 --- a/NewKernel_d/include/CGAL/NewKernel_d/Cartesian_filter_K.h +++ b/NewKernel_d/include/CGAL/NewKernel_d/Cartesian_filter_K.h @@ -42,26 +42,28 @@ template<> struct Functors_without_division > { }; template < typename Base_, typename AK_, typename EK_, typename Pred_list = typeset_all > -struct Cartesian_filter_K : public Base_, - private Store_kernel +struct Cartesian_filter_K : public Base_ { + CGAL_NO_UNIQUE_ADDRESS Store_kernel sak; + CGAL_NO_UNIQUE_ADDRESS Store_kernel sek; constexpr Cartesian_filter_K(){} constexpr Cartesian_filter_K(int d):Base_(d){} //FIXME: or do we want an instance of AK and EK belonging to this kernel, //instead of a reference to external ones? - constexpr Cartesian_filter_K(AK_ const&,EK_ const&b):Base_(),Store_kernel(b){} - constexpr Cartesian_filter_K(int d,AK_ const&,EK_ const&b):Base_(d),Store_kernel(b){} + constexpr Cartesian_filter_K(AK_ const&a,EK_ const&b):Base_(),sak(a),sek(b){} + constexpr Cartesian_filter_K(int d,AK_ const&a,EK_ const&b):Base_(d),sak(a),sek(b){} typedef Base_ Kernel_base; typedef AK_ AK; typedef EK_ EK; - CGAL_static_assertion_msg(internal::Do_not_store_kernel::value, "Only handle stateless kernels as AK"); - AK approximate_kernel()const{return {};} + typedef typename Store_kernel::reference_type AK_rt; + AK_rt approximate_kernel()const{return sak.kernel();} typedef typename Store_kernel::reference_type EK_rt; - EK_rt exact_kernel()const{return this->Store_kernel::kernel();} + EK_rt exact_kernel()const{return sek.kernel();} // MSVC is too dumb to perform the empty base optimization. typedef boost::mpl::and_< internal::Do_not_store_kernel, + internal::Do_not_store_kernel, internal::Do_not_store_kernel > Do_not_store_kernel; //TODO: C2A/C2E could be able to convert *this into this->kernel() or this->kernel2(). From 0a16ab839554632473345026eda8115d0dc3e9d3 Mon Sep 17 00:00:00 2001 From: Marc Glisse Date: Wed, 8 Apr 2020 22:05:20 +0200 Subject: [PATCH 219/568] Move constructor for Mpzf --- Number_types/include/CGAL/Mpzf.h | 26 +++++++++++++++++++++++--- 1 file changed, 23 insertions(+), 3 deletions(-) diff --git a/Number_types/include/CGAL/Mpzf.h b/Number_types/include/CGAL/Mpzf.h index d775431ebcf..117b5dac71a 100644 --- a/Number_types/include/CGAL/Mpzf.h +++ b/Number_types/include/CGAL/Mpzf.h @@ -340,18 +340,38 @@ struct Mpzf { exp=x.exp; if(size!=0) mpn_copyi(data(),x.data(),asize); } -#if !defined(CGAL_MPZF_USE_CACHE) +#if defined(CGAL_MPZF_USE_CACHE) + Mpzf(Mpzf&& x)noexcept:size(x.size),exp(x.exp){ + auto xd = x.data(); + while(*--xd==0); + if (xd != x.cache) { + data() = x.data(); + x.init(); + } else { + init(); + if(size!=0) mpn_copyi(data(),x.data(),std::abs(size)); + } + x.size = 0; + } +#else Mpzf(Mpzf&& x):data_(x.data()),size(x.size),exp(x.exp){ x.init(); // yes, that's a shame... x.size = 0; x.exp = 0; } - Mpzf& operator=(Mpzf&& x){ - std::swap(size,x.size); + Mpzf& operator=(Mpzf&& x)noexcept{ + size = x.size; + // In case something tries to read it, size needs to be smaller than data + x.size = 0; exp = x.exp; std::swap(data(),x.data()); return *this; } + friend void swap(Mpzf&a, Mpzf&b)noexcept{ + std::swap(a.size, b.size); + std::swap(a.exp, b.exp); + std::swap(a.data(), b.data()); + } friend Mpzf operator-(Mpzf&& x){ Mpzf ret = std::move(x); ret.size = -ret.size; From 6aec7dc3bedb559274440e787d284d46a49e6535 Mon Sep 17 00:00:00 2001 From: Marc Glisse Date: Thu, 9 Apr 2020 23:50:26 +0200 Subject: [PATCH 220/568] Add comments --- NewKernel_d/include/CGAL/NewKernel_d/Cartesian_filter_K.h | 4 ++++ NewKernel_d/include/CGAL/NewKernel_d/LA_eigen/LA.h | 3 +++ 2 files changed, 7 insertions(+) diff --git a/NewKernel_d/include/CGAL/NewKernel_d/Cartesian_filter_K.h b/NewKernel_d/include/CGAL/NewKernel_d/Cartesian_filter_K.h index b5b17fc2c23..ed164e844da 100644 --- a/NewKernel_d/include/CGAL/NewKernel_d/Cartesian_filter_K.h +++ b/NewKernel_d/include/CGAL/NewKernel_d/Cartesian_filter_K.h @@ -41,6 +41,10 @@ template<> struct Functors_without_division > { typedef typeset type; }; +// FIXME: +// - Is_exact (which should be renamed to Uses_no_arithmetic) predicates should not be filtered +// - Functors_without_division should be defined near/in the actual functors + template < typename Base_, typename AK_, typename EK_, typename Pred_list = typeset_all > struct Cartesian_filter_K : public Base_ { diff --git a/NewKernel_d/include/CGAL/NewKernel_d/LA_eigen/LA.h b/NewKernel_d/include/CGAL/NewKernel_d/LA_eigen/LA.h index 4bff70e2f5c..6d92765a34a 100644 --- a/NewKernel_d/include/CGAL/NewKernel_d/LA_eigen/LA.h +++ b/NewKernel_d/include/CGAL/NewKernel_d/LA_eigen/LA.h @@ -109,6 +109,9 @@ template struct LA_eigen { return m.determinant(); } + // TODO: https://gitlab.com/libeigen/eigen/-/issues/1782 + // Implement a version of (sign_of_)determinant that works + // without (inexact) division in any dimension template static NT determinant(Mat_ const&m,bool=false){ switch(m.rows()){ //case 0: From 5e4de872a1608f6df7a850c9fe341fe189c29416 Mon Sep 17 00:00:00 2001 From: Jane Tournois Date: Tue, 7 Apr 2020 14:02:36 +0200 Subject: [PATCH 221/568] fix copyright headers --- .../Remeshing_cell_base.h | 17 +++---------- .../Remeshing_triangulation_3.h | 17 +++---------- .../Remeshing_vertex_base.h | 18 +++---------- .../CGAL/Tetrahedral_remeshing/Sizing_field.h | 17 +++---------- .../Uniform_sizing_field.h | 17 +++---------- .../Tetrahedral_remeshing/internal/FMLS.h | 25 ++++++++++--------- .../Tetrahedral_remeshing/internal/Vec3D.h | 24 ++++++------------ .../internal/add_imaginary_layer.h | 2 +- .../internal/collapse_short_edges.h | 17 +++---------- .../internal/compute_c3t3_statistics.h | 19 +++----------- .../internal/flip_edges.h | 18 ++++--------- .../internal/smooth_vertices.h | 11 +++++++- .../internal/split_long_edges.h | 17 +++---------- .../tetrahedral_adaptive_remeshing_impl.h | 17 +++---------- .../internal/tetrahedral_remeshing_helpers.h | 17 +++---------- .../include/CGAL/tetrahedral_remeshing.h | 17 +++---------- 16 files changed, 80 insertions(+), 190 deletions(-) diff --git a/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/Remeshing_cell_base.h b/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/Remeshing_cell_base.h index d9998b6e2a3..eff663b51dd 100644 --- a/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/Remeshing_cell_base.h +++ b/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/Remeshing_cell_base.h @@ -1,23 +1,14 @@ -// Copyright (c) 2019 GeometryFactory (France). +// Copyright (c) 2020 GeometryFactory (France) and Telecom Paris (France). // All rights reserved. // -// This file is part of CGAL (www.cgal.org). -// You can redistribute it and/or modify it under the terms of the GNU -// General Public License as published by the Free Software Foundation, -// either version 3 of the License, or (at your option) any later version. -// -// Licensees holding a valid commercial license may use this file in -// accordance with the commercial license agreement provided with the software. -// -// This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE -// WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. +// This file is part of CGAL (www.cgal.org) // // $URL$ // $Id$ -// SPDX-License-Identifier: GPL-3.0+ +// SPDX-License-Identifier: GPL-3.0-or-later OR LicenseRef-Commercial // // -// Author(s) : Jane Tournois +// Author(s) : Jane Tournois, Noura Faraj #ifndef CGAL_TET_ADAPTIVE_REMESHING_CELL_BASE_H #define CGAL_TET_ADAPTIVE_REMESHING_CELL_BASE_H diff --git a/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/Remeshing_triangulation_3.h b/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/Remeshing_triangulation_3.h index 9cc108b7462..f009f25738b 100644 --- a/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/Remeshing_triangulation_3.h +++ b/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/Remeshing_triangulation_3.h @@ -1,23 +1,14 @@ -// Copyright (c) 2019 GeometryFactory (France). +// Copyright (c) 2020 GeometryFactory (France) and Telecom Paris (France). // All rights reserved. // -// This file is part of CGAL (www.cgal.org). -// You can redistribute it and/or modify it under the terms of the GNU -// General Public License as published by the Free Software Foundation, -// either version 3 of the License, or (at your option) any later version. -// -// Licensees holding a valid commercial license may use this file in -// accordance with the commercial license agreement provided with the software. -// -// This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE -// WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. +// This file is part of CGAL (www.cgal.org) // // $URL$ // $Id$ -// SPDX-License-Identifier: GPL-3.0+ +// SPDX-License-Identifier: GPL-3.0-or-later OR LicenseRef-Commercial // // -// Author(s) : Jane Tournois +// Author(s) : Jane Tournois, Noura Faraj #ifndef CGAL_TETRAHEDRAL_REMESHING_TRIANGULATION_H diff --git a/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/Remeshing_vertex_base.h b/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/Remeshing_vertex_base.h index eb1d10bf802..a44f9ad7a0b 100644 --- a/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/Remeshing_vertex_base.h +++ b/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/Remeshing_vertex_base.h @@ -1,24 +1,14 @@ -// Copyright (c) 2019 GeometryFactory (France). +// Copyright (c) 2020 GeometryFactory (France) and Telecom Paris (France). // All rights reserved. // -// This file is part of CGAL (www.cgal.org). -// You can redistribute it and/or modify it under the terms of the GNU -// General Public License as published by the Free Software Foundation, -// either version 3 of the License, or (at your option) any later version. -// -// Licensees holding a valid commercial license may use this file in -// accordance with the commercial license agreement provided with the software. -// -// This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE -// WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. +// This file is part of CGAL (www.cgal.org) // // $URL$ // $Id$ -// SPDX-License-Identifier: GPL-3.0+ +// SPDX-License-Identifier: GPL-3.0-or-later OR LicenseRef-Commercial // // -// Author(s) : Jane Tournois - +// Author(s) : Jane Tournois, Noura Faraj #ifndef CGAL_TET_ADAPTIVE_REMESHING_VERTEX_BASE_H #define CGAL_TET_ADAPTIVE_REMESHING_VERTEX_BASE_H diff --git a/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/Sizing_field.h b/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/Sizing_field.h index 4d6cb39c01d..8d086ecf120 100644 --- a/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/Sizing_field.h +++ b/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/Sizing_field.h @@ -1,23 +1,14 @@ -// Copyright (c) 2019 GeometryFactory (France). +// Copyright (c) 2020 GeometryFactory (France) and Telecom Paris (France). // All rights reserved. // -// This file is part of CGAL (www.cgal.org). -// You can redistribute it and/or modify it under the terms of the GNU -// General Public License as published by the Free Software Foundation, -// either version 3 of the License, or (at your option) any later version. -// -// Licensees holding a valid commercial license may use this file in -// accordance with the commercial license agreement provided with the software. -// -// This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE -// WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. +// This file is part of CGAL (www.cgal.org) // // $URL$ // $Id$ -// SPDX-License-Identifier: GPL-3.0+ +// SPDX-License-Identifier: GPL-3.0-or-later OR LicenseRef-Commercial // // -// Author(s) : Jane Tournois +// Author(s) : Jane Tournois, Noura Faraj #ifndef CGAL_SIZING_FIELD_H #define CGAL_SIZING_FIELD_H diff --git a/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/Uniform_sizing_field.h b/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/Uniform_sizing_field.h index 60e71b5783e..2f69d13b081 100644 --- a/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/Uniform_sizing_field.h +++ b/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/Uniform_sizing_field.h @@ -1,23 +1,14 @@ -// Copyright (c) 2019 GeometryFactory (France). +// Copyright (c) 2020 GeometryFactory (France) and Telecom Paris (France). // All rights reserved. // -// This file is part of CGAL (www.cgal.org). -// You can redistribute it and/or modify it under the terms of the GNU -// General Public License as published by the Free Software Foundation, -// either version 3 of the License, or (at your option) any later version. -// -// Licensees holding a valid commercial license may use this file in -// accordance with the commercial license agreement provided with the software. -// -// This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE -// WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. +// This file is part of CGAL (www.cgal.org) // // $URL$ // $Id$ -// SPDX-License-Identifier: GPL-3.0+ +// SPDX-License-Identifier: GPL-3.0-or-later OR LicenseRef-Commercial // // -// Author(s) : Jane Tournois +// Author(s) : Jane Tournois, Noura Faraj #ifndef CGAL_UNIFORM_SIZING_FIELD_H #define CGAL_UNIFORM_SIZING_FIELD_H diff --git a/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/FMLS.h b/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/FMLS.h index dbecf6a79b1..249df7a2a50 100644 --- a/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/FMLS.h +++ b/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/FMLS.h @@ -1,3 +1,16 @@ +// Copyright (c) 2020 GeometryFactory (France) and Telecom Paris (France). +// All rights reserved. +// +// This file is part of CGAL (www.cgal.org) +// +// $URL$ +// $Id$ +// SPDX-License-Identifier: GPL-3.0-or-later OR LicenseRef-Commercial +// +// +// Author(s) : Jane Tournois, Noura Faraj + + #ifndef CGAL_TETRAHEDRAL_REMESHING_FMLS_H #define CGAL_TETRAHEDRAL_REMESHING_FMLS_H @@ -5,18 +18,6 @@ // FMLS // A Fast Moving Least Square operator for 3D // points sets. -// -// Copyright (C) 2006-2011 Tamy Boubekeur -// All rights reserved. -// ------------------------------------------- - -// ------------------------------------------- -// Disclaimer: this code is dirty in the -// meaning that there is no attention paid to -// proper class attribute access, memory -// management or optimisation of any kind. It -// is designed for quick-and-dirty testing -// purpose. // ------------------------------------------- #include diff --git a/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/Vec3D.h b/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/Vec3D.h index 00a42c8b527..29bd20e9fa9 100644 --- a/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/Vec3D.h +++ b/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/Vec3D.h @@ -1,24 +1,14 @@ -// -------------------------------------------------------------------------- -// gMini, -// a minimal Glut/OpenGL app to extend -// -// Copyright(C) 2007-2009 -// Tamy Boubekeur -// +// Copyright (c) 2020 GeometryFactory (France) and Telecom Paris (France). // All rights reserved. // -// This program is free software; you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation; either version 2 of the License, or -// (at your option) any later version. +// This file is part of CGAL (www.cgal.org) // -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License (http://www.gnu.org/licenses/gpl.txt) -// for more details. +// $URL$ +// $Id$ +// SPDX-License-Identifier: GPL-3.0-or-later OR LicenseRef-Commercial // -// -------------------------------------------------------------------------- +// +// Author(s) : Jane Tournois, Noura Faraj #pragma once diff --git a/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/add_imaginary_layer.h b/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/add_imaginary_layer.h index 7c28e36b60a..648c2898a9d 100644 --- a/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/add_imaginary_layer.h +++ b/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/add_imaginary_layer.h @@ -14,7 +14,7 @@ // // $URL$ // $Id$ -// SPDX-License-Identifier: GPL-3.0+ +// SPDX-License-Identifier: GPL-3.0-or-later OR LicenseRef-Commercial // // // Author(s) : Jane Tournois diff --git a/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/collapse_short_edges.h b/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/collapse_short_edges.h index 469e45c5dcf..13aad9b8b37 100644 --- a/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/collapse_short_edges.h +++ b/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/collapse_short_edges.h @@ -1,23 +1,14 @@ -// Copyright (c) 2019 GeometryFactory (France). +// Copyright (c) 2020 GeometryFactory (France) and Telecom Paris (France). // All rights reserved. // -// This file is part of CGAL (www.cgal.org). -// You can redistribute it and/or modify it under the terms of the GNU -// General Public License as published by the Free Software Foundation, -// either version 3 of the License, or (at your option) any later version. -// -// Licensees holding a valid commercial license may use this file in -// accordance with the commercial license agreement provided with the software. -// -// This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE -// WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. +// This file is part of CGAL (www.cgal.org) // // $URL$ // $Id$ -// SPDX-License-Identifier: GPL-3.0+ +// SPDX-License-Identifier: GPL-3.0-or-later OR LicenseRef-Commercial // // -// Author(s) : Jane Tournois +// Author(s) : Jane Tournois, Noura Faraj #ifndef CGAL_INTERNAL_COLLAPSE_SHORT_EDGES_H #define CGAL_INTERNAL_COLLAPSE_SHORT_EDGES_H diff --git a/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/compute_c3t3_statistics.h b/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/compute_c3t3_statistics.h index 4d6a92c438d..7799ccce312 100644 --- a/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/compute_c3t3_statistics.h +++ b/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/compute_c3t3_statistics.h @@ -1,25 +1,14 @@ -// Copyright (c) 2018 GeometryFactory (France). +// Copyright (c) 2020 GeometryFactory (France) and Telecom Paris (France). // All rights reserved. // -// This file is part of CGAL (www.cgal.org). -// You can redistribute it and/or modify it under the terms of the GNU -// General Public License as published by the Free Software Foundation, -// either version 3 of the License, or (at your option) any later version. -// -// Licensees holding a valid commercial license may use this file in -// accordance with the commercial license agreement provided with the software. -// -// This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE -// WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. +// This file is part of CGAL (www.cgal.org) // // $URL$ // $Id$ +// SPDX-License-Identifier: GPL-3.0-or-later OR LicenseRef-Commercial // // -// -//****************************************************************************** -// -//****************************************************************************** +// Author(s) : Jane Tournois, Noura Faraj #include #include diff --git a/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/flip_edges.h b/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/flip_edges.h index 5163c5f90ce..15dd8a3b113 100644 --- a/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/flip_edges.h +++ b/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/flip_edges.h @@ -1,23 +1,15 @@ -// Copyright (c) 2019 GeometryFactory (France). +// Copyright (c) 2020 GeometryFactory (France) and Telecom Paris (France). // All rights reserved. // -// This file is part of CGAL (www.cgal.org). -// You can redistribute it and/or modify it under the terms of the GNU -// General Public License as published by the Free Software Foundation, -// either version 3 of the License, or (at your option) any later version. -// -// Licensees holding a valid commercial license may use this file in -// accordance with the commercial license agreement provided with the software. -// -// This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE -// WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. +// This file is part of CGAL (www.cgal.org) // // $URL$ // $Id$ -// SPDX-License-Identifier: GPL-3.0+ +// SPDX-License-Identifier: GPL-3.0-or-later OR LicenseRef-Commercial // // -// Author(s) : Jane Tournois +// Author(s) : Jane Tournois, Noura Faraj + #ifndef CGAL_INTERNAL_FLIP_EDGES_H #define CGAL_INTERNAL_FLIP_EDGES_H diff --git a/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/smooth_vertices.h b/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/smooth_vertices.h index abe02f66778..0371128da30 100644 --- a/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/smooth_vertices.h +++ b/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/smooth_vertices.h @@ -1,5 +1,14 @@ -// Copyright (c) 2017 GeometryFactory (France). +// Copyright (c) 2020 GeometryFactory (France) and Telecom Paris (France). // All rights reserved. +// +// This file is part of CGAL (www.cgal.org) +// +// $URL$ +// $Id$ +// SPDX-License-Identifier: GPL-3.0-or-later OR LicenseRef-Commercial +// +// +// Author(s) : Jane Tournois, Noura Faraj #ifndef CGAL_INTERNAL_SMOOTH_VERTICES_H #define CGAL_INTERNAL_SMOOTH_VERTICES_H diff --git a/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/split_long_edges.h b/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/split_long_edges.h index 6d7615f80e7..5e68780b311 100644 --- a/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/split_long_edges.h +++ b/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/split_long_edges.h @@ -1,23 +1,14 @@ -// Copyright (c) 2019 GeometryFactory (France). +// Copyright (c) 2020 GeometryFactory (France) and Telecom Paris (France). // All rights reserved. // -// This file is part of CGAL (www.cgal.org). -// You can redistribute it and/or modify it under the terms of the GNU -// General Public License as published by the Free Software Foundation, -// either version 3 of the License, or (at your option) any later version. -// -// Licensees holding a valid commercial license may use this file in -// accordance with the commercial license agreement provided with the software. -// -// This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE -// WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. +// This file is part of CGAL (www.cgal.org) // // $URL$ // $Id$ -// SPDX-License-Identifier: GPL-3.0+ +// SPDX-License-Identifier: GPL-3.0-or-later OR LicenseRef-Commercial // // -// Author(s) : Jane Tournois +// Author(s) : Jane Tournois, Noura Faraj #ifndef CGAL_INTERNAL_SPLIT_LONG_EDGES_H #define CGAL_INTERNAL_SPLIT_LONG_EDGES_H diff --git a/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/tetrahedral_adaptive_remeshing_impl.h b/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/tetrahedral_adaptive_remeshing_impl.h index 1a2a5b4a317..65e3d361df5 100644 --- a/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/tetrahedral_adaptive_remeshing_impl.h +++ b/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/tetrahedral_adaptive_remeshing_impl.h @@ -1,23 +1,14 @@ -// Copyright (c) 2019 GeometryFactory (France). +// Copyright (c) 2020 GeometryFactory (France) and Telecom Paris (France). // All rights reserved. // -// This file is part of CGAL (www.cgal.org). -// You can redistribute it and/or modify it under the terms of the GNU -// General Public License as published by the Free Software Foundation, -// either version 3 of the License, or (at your option) any later version. -// -// Licensees holding a valid commercial license may use this file in -// accordance with the commercial license agreement provided with the software. -// -// This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE -// WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. +// This file is part of CGAL (www.cgal.org) // // $URL$ // $Id$ -// SPDX-License-Identifier: GPL-3.0+ +// SPDX-License-Identifier: GPL-3.0-or-later OR LicenseRef-Commercial // // -// Author(s) : Jane Tournois +// Author(s) : Jane Tournois, Noura Faraj #ifndef TETRAHEDRAL_REMESHING_IMPL_H #define TETRAHEDRAL_REMESHING_IMPL_H diff --git a/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/tetrahedral_remeshing_helpers.h b/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/tetrahedral_remeshing_helpers.h index 601577824cb..e800facc17b 100644 --- a/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/tetrahedral_remeshing_helpers.h +++ b/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/tetrahedral_remeshing_helpers.h @@ -1,23 +1,14 @@ -// Copyright (c) 2019 GeometryFactory (France). +// Copyright (c) 2020 GeometryFactory (France) and Telecom Paris (France). // All rights reserved. // -// This file is part of CGAL (www.cgal.org). -// You can redistribute it and/or modify it under the terms of the GNU -// General Public License as published by the Free Software Foundation, -// either version 3 of the License, or (at your option) any later version. -// -// Licensees holding a valid commercial license may use this file in -// accordance with the commercial license agreement provided with the software. -// -// This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE -// WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. +// This file is part of CGAL (www.cgal.org) // // $URL$ // $Id$ -// SPDX-License-Identifier: GPL-3.0+ +// SPDX-License-Identifier: GPL-3.0-or-later OR LicenseRef-Commercial // // -// Author(s) : Jane Tournois +// Author(s) : Jane Tournois, Noura Faraj #ifndef CGAL_INTERNAL_TET_REMESHING_HELPERS_H #define CGAL_INTERNAL_TET_REMESHING_HELPERS_H diff --git a/Tetrahedral_remeshing/include/CGAL/tetrahedral_remeshing.h b/Tetrahedral_remeshing/include/CGAL/tetrahedral_remeshing.h index be425ac7296..cc772a02bb5 100644 --- a/Tetrahedral_remeshing/include/CGAL/tetrahedral_remeshing.h +++ b/Tetrahedral_remeshing/include/CGAL/tetrahedral_remeshing.h @@ -1,23 +1,14 @@ -// Copyright (c) 2019 GeometryFactory (France). +// Copyright (c) 2020 GeometryFactory (France) and Telecom Paris (France). // All rights reserved. // -// This file is part of CGAL (www.cgal.org). -// You can redistribute it and/or modify it under the terms of the GNU -// General Public License as published by the Free Software Foundation, -// either version 3 of the License, or (at your option) any later version. -// -// Licensees holding a valid commercial license may use this file in -// accordance with the commercial license agreement provided with the software. -// -// This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE -// WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. +// This file is part of CGAL (www.cgal.org) // // $URL$ // $Id$ -// SPDX-License-Identifier: GPL-3.0+ +// SPDX-License-Identifier: GPL-3.0-or-later OR LicenseRef-Commercial // // -// Author(s) : Jane Tournois +// Author(s) : Jane Tournois, Noura Faraj #ifndef TETRAHEDRAL_REMESHING_H #define TETRAHEDRAL_REMESHING_H From 933a5bc776282dbd013194ef896db1d850b85de3 Mon Sep 17 00:00:00 2001 From: Jane Tournois Date: Tue, 7 Apr 2020 14:04:32 +0200 Subject: [PATCH 222/568] remove useless file --- .../internal/add_imaginary_layer.h | 251 ------------------ 1 file changed, 251 deletions(-) delete mode 100644 Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/add_imaginary_layer.h diff --git a/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/add_imaginary_layer.h b/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/add_imaginary_layer.h deleted file mode 100644 index 648c2898a9d..00000000000 --- a/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/add_imaginary_layer.h +++ /dev/null @@ -1,251 +0,0 @@ -// Copyright (c) 2019 GeometryFactory (France). -// All rights reserved. -// -// This file is part of CGAL (www.cgal.org). -// You can redistribute it and/or modify it under the terms of the GNU -// General Public License as published by the Free Software Foundation, -// either version 3 of the License, or (at your option) any later version. -// -// Licensees holding a valid commercial license may use this file in -// accordance with the commercial license agreement provided with the software. -// -// This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE -// WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. -// -// $URL$ -// $Id$ -// SPDX-License-Identifier: GPL-3.0-or-later OR LicenseRef-Commercial -// -// -// Author(s) : Jane Tournois - -#ifndef CGAL_INTERNAL_ADD_IMAGINARY_LAYER_H -#define CGAL_INTERNAL_ADD_IMAGINARY_LAYER_H - -#include -#include - -#include -#include -#include - -namespace CGAL -{ -namespace Tetrahedral_remeshing -{ -namespace internal -{ - template - void set_labels_of_incident_cells(VertexIterator begin, - VertexIterator end, - const Tr& tr, - const int& label) - { - typedef typename Tr::Cell_handle Cell_handle; - for (VertexIterator vit = begin; vit != end; ++vit) - { - std::vector cells; - tr.finite_incident_cells(*vit, std::back_inserter(cells)); - - for (std::size_t i = 0; i < cells.size(); ++i) - cells[i]->set_subdomain_index(label); - } - } - - template - void set_dimension(VertexIterator begin, - VertexIterator end, - const short& dimension) - { - for (VertexIterator vit = begin; vit != end; ++vit) - (*vit)->set_dimension(dimension); - } - - template - OutputIterator insert_points(PointIterator begin, - PointIterator end, - Tr& tr, - OutputIterator oit) - { - typedef typename Tr::Point Point; - - CGAL_assertion(tr.is_valid()); - int i = 1; - for (PointIterator pit = begin; pit != end; ++pit, ++i) - { - *oit++ = tr.insert(Point(*pit)); - } - CGAL_assertion(tr.is_valid()); - -#ifdef CGAL_TETRAHEDRAL_REMESHING_VERBOSE - std::cout << "(" << i << " points inserted successfully)" << std::endl; -#endif - - return oit; - } - - template - OutputIterator compute_offset_points(const VertexNormalsMap& normals, - const double& offset, - OutputIterator oit, - const Gt& gt) - { -#ifdef CGAL_TETRAHEDRAL_REMESHING_DEBUG - std::ofstream ofs("imaginary_points.off"); - ofs << "OFF" << std::endl; - ofs << normals.size() << " 0 0" << std::endl; -#endif - - typename Gt::Construct_translated_point_3 translate - = gt.construct_translated_point_3_object(); - - for (typename VertexNormalsMap::const_iterator nit = normals.begin(); - nit != normals.end(); ++nit) - { - *oit++ = translate(point((*nit).first->point()), offset * (*nit).second); - -#ifdef CGAL_TETRAHEDRAL_REMESHING_DEBUG - ofs << translate(point((*nit).first->point()), offset * (*nit).second) << std::endl; -#endif - } - -#ifdef CGAL_TETRAHEDRAL_REMESHING_DEBUG - ofs.close(); -#endif - return oit; - } - - template - void compute_normals_on_convex_hull(const T3& tr, - VertexNormalsMap& normals) - { -#ifdef CGAL_TETRAHEDRAL_REMESHING_DEBUG - std::ofstream ofs("imaginary_normals.xyz"); -#endif - namespace PMP = CGAL::Polygon_mesh_processing; - - typedef typename T3::Geom_traits Gt; - typedef typename Gt::Vector_3 Vector_3; - const Gt& gt = tr.geom_traits(); - - typedef typename T3::Vertex_handle Vertex_handle; - typedef typename T3::Facet Facet; - typedef typename T3::Finite_facets_iterator Finite_facets_iterator; - - boost::unordered_map fnormals; - for (Finite_facets_iterator fit = tr.finite_facets_begin(); - fit != tr.finite_facets_end(); - ++fit) - { - Facet f = *fit; - if (tr.is_infinite(f.first)) - { - f = tr.mirror_facet(f); - fnormals.insert(std::make_pair(f, normal(f, gt))); - } - else if (tr.is_infinite(f.first->neighbor(f.second))) - fnormals.insert(std::make_pair(f, normal(f, gt))); - } - - std::vector vertices; - tr.finite_adjacent_vertices(tr.infinite_vertex(), - std::back_inserter(vertices)); - for (std::size_t i = 0; i < vertices.size(); ++i) - { - Vertex_handle vi = vertices[i]; - std::vector inc_facets; - tr.finite_incident_facets(vi, std::back_inserter(inc_facets)); - - Vector_3 ni = gt.construct_vector_3_object()(CGAL::NULL_VECTOR); - for (std::size_t j = 0; j < inc_facets.size(); ++j) - { - typename boost::unordered_map::iterator - fnit = fnormals.find(inc_facets[j]); - if (fnit != fnormals.end()) - ni = gt.construct_sum_of_vectors_3_object()(ni, fnit->second); - else - { - //check for mirror_facet - fnit = fnormals.find(tr.mirror_facet(inc_facets[j])); - if (fnit != fnormals.end()) - ni = gt.construct_sum_of_vectors_3_object()(ni, fnit->second); - } - } - - if (!typename Gt::Equal_3()(ni, CGAL::NULL_VECTOR)) - { - ni = gt.construct_opposite_vector_3_object()(ni); - PMP::internal::normalize(ni, gt); - normals.insert(std::make_pair(vi, ni)); -#ifdef CGAL_TETRAHEDRAL_REMESHING_DEBUG - ofs << vi->point() << " " << ni << std::endl; -#endif - } - } -#ifdef CGAL_TETRAHEDRAL_REMESHING_DEBUG - ofs.close(); -#endif - } - - template - double compute_bbox_max_size(const Tr& tr) - { - typename Tr::Finite_vertices_iterator vit = tr.finite_vertices_begin(); - const typename Tr::Point& p = vit->point(); - CGAL::Bbox_3 bbox = p.bbox(); - ++vit; - for ( ; vit != tr.finite_vertices_end(); ++vit) - { - bbox = bbox + vit->point().bbox(); - } - - return (std::max)((std::max)(bbox.xmax() - bbox.xmin(), - bbox.ymax() - bbox.ymin()), - bbox.zmax() - bbox.zmin()); - - } - - template - void add_layer_of_imaginary_tets(T3& tr, const Index& imaginary_index) - { - typedef typename T3::Vertex_handle Vertex_handle; - typedef typename T3::Geom_traits::Point_3 Point_3; - typedef typename T3::Geom_traits::Vector_3 Vector_3; - - //compute normals - boost::unordered_map normals; - compute_normals_on_convex_hull(tr, normals); - - //compute bbox max size - const double offset = 0.04 * compute_bbox_max_size(tr); - - //compute points to be inserted - std::vector offset_points; - compute_offset_points(normals, - offset, - std::back_inserter(offset_points), - tr.geom_traits()); - - //insert vertices on offset - //note we only need to insert them in the T3, because they - //are all outside convex hull. The rest of the T3 will not be modified - std::vector offset_vertices; - insert_points(offset_points.begin(), offset_points.end(), - tr, std::back_inserter(offset_vertices)); - - CGAL_assertion(tr.is_valid()); - - //set labels - set_labels_of_incident_cells(offset_vertices.begin(), - offset_vertices.end(), - tr, - imaginary_index); - - set_dimension(offset_vertices.begin(), offset_vertices.end(), 3); - } - -}//end namespace internal -}//end namespace Tetrahedral_remeshing -}//end namesapce CGAL - -#endif From dd755c82e357e42a40df5c519cf274c5ab5a332c Mon Sep 17 00:00:00 2001 From: Jane Tournois Date: Wed, 8 Apr 2020 09:54:43 +0200 Subject: [PATCH 223/568] move package info to package_info/Tetrahedral_remeshing directory --- .../package_info/Tetrahedral_remeshing/copyright | 2 ++ .../package_info/{ => Tetrahedral_remeshing}/dependencies | 1 + .../package_info/{ => Tetrahedral_remeshing}/license.txt | 0 .../package_info/{ => Tetrahedral_remeshing}/maintainer | 0 Tetrahedral_remeshing/package_info/copyright | 1 - 5 files changed, 3 insertions(+), 1 deletion(-) create mode 100644 Tetrahedral_remeshing/package_info/Tetrahedral_remeshing/copyright rename Tetrahedral_remeshing/package_info/{ => Tetrahedral_remeshing}/dependencies (98%) rename Tetrahedral_remeshing/package_info/{ => Tetrahedral_remeshing}/license.txt (100%) rename Tetrahedral_remeshing/package_info/{ => Tetrahedral_remeshing}/maintainer (100%) delete mode 100644 Tetrahedral_remeshing/package_info/copyright diff --git a/Tetrahedral_remeshing/package_info/Tetrahedral_remeshing/copyright b/Tetrahedral_remeshing/package_info/Tetrahedral_remeshing/copyright new file mode 100644 index 00000000000..a49b9cc8d1a --- /dev/null +++ b/Tetrahedral_remeshing/package_info/Tetrahedral_remeshing/copyright @@ -0,0 +1,2 @@ +GeometryFactory (France) +Telecom Paris (France) diff --git a/Tetrahedral_remeshing/package_info/dependencies b/Tetrahedral_remeshing/package_info/Tetrahedral_remeshing/dependencies similarity index 98% rename from Tetrahedral_remeshing/package_info/dependencies rename to Tetrahedral_remeshing/package_info/Tetrahedral_remeshing/dependencies index ac9cf1d15bf..15622284ce4 100644 --- a/Tetrahedral_remeshing/package_info/dependencies +++ b/Tetrahedral_remeshing/package_info/Tetrahedral_remeshing/dependencies @@ -11,6 +11,7 @@ Homogeneous_kernel Installation Interval_support Kernel_23 +Mesh_3 Modular_arithmetic Number_types Polygon_mesh_processing diff --git a/Tetrahedral_remeshing/package_info/license.txt b/Tetrahedral_remeshing/package_info/Tetrahedral_remeshing/license.txt similarity index 100% rename from Tetrahedral_remeshing/package_info/license.txt rename to Tetrahedral_remeshing/package_info/Tetrahedral_remeshing/license.txt diff --git a/Tetrahedral_remeshing/package_info/maintainer b/Tetrahedral_remeshing/package_info/Tetrahedral_remeshing/maintainer similarity index 100% rename from Tetrahedral_remeshing/package_info/maintainer rename to Tetrahedral_remeshing/package_info/Tetrahedral_remeshing/maintainer diff --git a/Tetrahedral_remeshing/package_info/copyright b/Tetrahedral_remeshing/package_info/copyright deleted file mode 100644 index d76cdbe60d6..00000000000 --- a/Tetrahedral_remeshing/package_info/copyright +++ /dev/null @@ -1 +0,0 @@ -GeometryFactory (France) \ No newline at end of file From 9a40e58877d98e4608340ee59b10a509715f4152 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9bastien=20Loriot?= Date: Wed, 8 Apr 2020 18:48:46 +0200 Subject: [PATCH 224/568] fix warnings and compilation errors --- .../tetrahedral_remeshing_example.cpp | 2 +- .../tetrahedral_remeshing_io.h | 13 ++++++------- .../tetrahedral_remeshing_of_one_subdomain.cpp | 2 +- .../tetrahedral_remeshing_with_features.cpp | 2 +- .../Remeshing_triangulation_3.h | 5 +++-- .../CGAL/Tetrahedral_remeshing/internal/FMLS.h | 4 ++++ .../internal/collapse_short_edges.h | 8 ++++---- .../internal/compute_c3t3_statistics.h | 5 +++++ .../Tetrahedral_remeshing/internal/flip_edges.h | 6 +++--- .../internal/smooth_vertices.h | 6 +++--- .../tetrahedral_adaptive_remeshing_impl.h | 16 +++++++++------- .../include/CGAL/tetrahedral_remeshing.h | 4 ++-- 12 files changed, 42 insertions(+), 31 deletions(-) diff --git a/Tetrahedral_remeshing/examples/Tetrahedral_remeshing/tetrahedral_remeshing_example.cpp b/Tetrahedral_remeshing/examples/Tetrahedral_remeshing/tetrahedral_remeshing_example.cpp index a9f6922d80a..06127342f8c 100644 --- a/Tetrahedral_remeshing/examples/Tetrahedral_remeshing/tetrahedral_remeshing_example.cpp +++ b/Tetrahedral_remeshing/examples/Tetrahedral_remeshing/tetrahedral_remeshing_example.cpp @@ -32,7 +32,7 @@ bool load_binary_triangulation(std::istream& is, T3& t3) bool save_binary_triangulation(std::ostream& os, const T3& t3) { - typedef T3::Geom_traits::FT FT; +// typedef T3::Geom_traits::FT FT; os << "binary CGAL c3t3\n"; CGAL::set_binary_mode(os); return !!(os << t3); diff --git a/Tetrahedral_remeshing/examples/Tetrahedral_remeshing/tetrahedral_remeshing_io.h b/Tetrahedral_remeshing/examples/Tetrahedral_remeshing/tetrahedral_remeshing_io.h index e42f07740ff..b457318990b 100644 --- a/Tetrahedral_remeshing/examples/Tetrahedral_remeshing/tetrahedral_remeshing_io.h +++ b/Tetrahedral_remeshing/examples/Tetrahedral_remeshing/tetrahedral_remeshing_io.h @@ -27,7 +27,6 @@ bool load_binary_triangulation(std::istream& is, T3& t3) template bool save_binary_triangulation(std::ostream& os, const T3& t3) { - typedef T3::Geom_traits::FT FT; os << "binary CGAL c3t3\n"; CGAL::set_binary_mode(os); return !!(os << t3); @@ -46,7 +45,7 @@ void save_ascii_triangulation(const char* filename, const T3& t3) template int generate_input(int input_id, std::size_t nbv, T3& tr) { - char* filename; + std::string filename; CGAL::Random rng; if (input_id == 1) //sphere and only one subdomain @@ -54,9 +53,9 @@ int generate_input(int input_id, std::size_t nbv, T3& tr) filename = "data/triangulation_one_subdomain.binary.cgal"; while (tr.number_of_vertices() < nbv) - tr.insert(T3::Point(rng.get_double(-1., 1.), rng.get_double(-1., 1.), rng.get_double(-1., 1.))); + tr.insert(typename T3::Point(rng.get_double(-1., 1.), rng.get_double(-1., 1.), rng.get_double(-1., 1.))); - for (T3::Finite_cells_iterator cit = tr.finite_cells_begin(); + for (typename T3::Finite_cells_iterator cit = tr.finite_cells_begin(); cit != tr.finite_cells_end(); ++cit) { cit->set_subdomain_index(1); @@ -68,11 +67,11 @@ int generate_input(int input_id, std::size_t nbv, T3& tr) while (tr.number_of_vertices() < nbv) tr.insert( - T3::Point(rng.get_double(-1., 1.), rng.get_double(-1., 1.), rng.get_double(-1., 1.))); + typename T3::Point(rng.get_double(-1., 1.), rng.get_double(-1., 1.), rng.get_double(-1., 1.))); - const K::Plane_3 plane(K::Point_3(0,0,0), K::Point_3(0,1,0), K::Point_3(0,0,1)); + const typename T3::Plane_3 plane(typename T3::Point(0,0,0), typename T3::Point(0,1,0), typename T3::Point(0,0,1)); - for (T3::Finite_cells_iterator cit = tr.finite_cells_begin(); + for (typename T3::Finite_cells_iterator cit = tr.finite_cells_begin(); cit != tr.finite_cells_end(); ++cit) { if(plane.has_on_positive_side( diff --git a/Tetrahedral_remeshing/examples/Tetrahedral_remeshing/tetrahedral_remeshing_of_one_subdomain.cpp b/Tetrahedral_remeshing/examples/Tetrahedral_remeshing/tetrahedral_remeshing_of_one_subdomain.cpp index c17a444cbb2..416adbefe44 100644 --- a/Tetrahedral_remeshing/examples/Tetrahedral_remeshing/tetrahedral_remeshing_of_one_subdomain.cpp +++ b/Tetrahedral_remeshing/examples/Tetrahedral_remeshing/tetrahedral_remeshing_of_one_subdomain.cpp @@ -26,7 +26,7 @@ public: : m_subdomain(subdomain) {} - const bool operator()(Remeshing_triangulation::Cell_handle c) const + bool operator()(Remeshing_triangulation::Cell_handle c) const { return m_subdomain == c->subdomain_index(); } diff --git a/Tetrahedral_remeshing/examples/Tetrahedral_remeshing/tetrahedral_remeshing_with_features.cpp b/Tetrahedral_remeshing/examples/Tetrahedral_remeshing/tetrahedral_remeshing_with_features.cpp index a1947b7e2cc..c65bc72e6d4 100644 --- a/Tetrahedral_remeshing/examples/Tetrahedral_remeshing/tetrahedral_remeshing_with_features.cpp +++ b/Tetrahedral_remeshing/examples/Tetrahedral_remeshing/tetrahedral_remeshing_with_features.cpp @@ -56,7 +56,7 @@ public: else map.m_set_ptr->erase(k); } - friend const value_type get(const Constrained_edges_property_map& map, + friend value_type get(const Constrained_edges_property_map& map, const key_type& k) { CGAL_assertion(map.m_set_ptr != NULL); diff --git a/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/Remeshing_triangulation_3.h b/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/Remeshing_triangulation_3.h index f009f25738b..4c652798659 100644 --- a/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/Remeshing_triangulation_3.h +++ b/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/Remeshing_triangulation_3.h @@ -77,6 +77,7 @@ namespace Tetrahedral_remeshing typedef CGAL::Triangulation_data_structure_3< Remeshing_Vb, Remeshing_Cb, Concurrency_tag> Tds; typedef CGAL::Triangulation_3 Self; + typedef typename Gt::Plane_3 Plane_3; }; namespace internal @@ -147,7 +148,7 @@ namespace Tetrahedral_remeshing Remeshing_triangulation_3& remeshing_tr) { typedef typename T3::Triangulation_data_structure Tds; - typedef Remeshing_triangulation_3::Tds RTds; + typedef typename Remeshing_triangulation_3::Tds RTds; remeshing_tr.clear(); @@ -165,7 +166,7 @@ namespace Tetrahedral_remeshing T3& tr) { typedef typename T3::Triangulation_data_structure Tds; - typedef Remeshing_triangulation_3::Tds RTds; + typedef typename Remeshing_triangulation_3::Tds RTds; tr.clear(); diff --git a/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/FMLS.h b/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/FMLS.h index 249df7a2a50..aee9be085f2 100644 --- a/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/FMLS.h +++ b/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/FMLS.h @@ -251,7 +251,9 @@ namespace CGAL void fastProjectionCPU(const float* pv, unsigned int pvSize, float* qv, unsigned int stride = 3) const { +#ifdef _OPENMP #pragma omp parallel for +#endif for (int i = 0; i < int(pvSize); i++) { Vec3Df p(pv[stride * i], pv[stride * i + 1], pv[stride * i + 2]); Vec3Df q, n; @@ -292,7 +294,9 @@ namespace CGAL void projectionCPU(const float* pv, unsigned int pvSize, float* qv, unsigned int stride = 3) { +#ifdef _OPENMP #pragma omp parallel for +#endif for (int i = 0; i < int(pvSize); i++) { Vec3Df p(pv[stride * i], pv[stride * i + 1], pv[stride * i + 2]); Vec3Df q, n; diff --git a/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/collapse_short_edges.h b/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/collapse_short_edges.h index 13aad9b8b37..772632cc1df 100644 --- a/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/collapse_short_edges.h +++ b/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/collapse_short_edges.h @@ -597,8 +597,8 @@ namespace internal } template - void merge_surface_patch_indices(typename C3t3::Facet& f1, - typename C3t3::Facet& f2, + void merge_surface_patch_indices(const typename C3t3::Facet& f1, + const typename C3t3::Facet& f2, C3t3& c3t3) { const bool in_cx_f1 = c3t3.is_in_complex(f1); @@ -856,7 +856,7 @@ namespace internal typename C3t3::Vertex_handle collapse_edge(typename C3t3::Edge& edge, C3t3& c3t3, const typename C3t3::Triangulation::Geom_traits::FT& sqhigh, - const bool protect_boundaries, + const bool /* protect_boundaries */, CellSelector cell_selector, Visitor& visitor) { @@ -1044,10 +1044,10 @@ namespace internal //the edge with shortest length typename Boost_bimap::right_map::iterator eit = short_edges.right.begin(); Edge_vv e = eit->second; - FT sqlen = eit->first; short_edges.right.erase(eit); #ifdef CGAL_TETRAHEDRAL_REMESHING_VERBOSE_PROGRESS + FT sqlen = eit->first; std::cout << "\rCollapse... (" << short_edges.left.size() << " short edges, "; std::cout << std::sqrt(sqlen) << ", "; std::cout << nb_collapses << " collapses)"; diff --git a/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/compute_c3t3_statistics.h b/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/compute_c3t3_statistics.h index 7799ccce312..3af1fdae96d 100644 --- a/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/compute_c3t3_statistics.h +++ b/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/compute_c3t3_statistics.h @@ -19,6 +19,9 @@ #include +#ifndef CGAL_TR_INTERNAL_COMPUTE_C3T3_STATISTICS_H +#define CGAL_TR_INTERNAL_COMPUTE_C3T3_STATISTICS_H + namespace CGAL { namespace Tetrahedral_remeshing @@ -205,3 +208,5 @@ namespace internal }//end namespace internal }//end namespace Tetrahedral_remeshing }//end namespace CGAL + +#endif // CGAL_TR_INTERNAL_COMPUTE_C3T3_STATISTICS_H diff --git a/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/flip_edges.h b/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/flip_edges.h index 15dd8a3b113..9edc8827182 100644 --- a/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/flip_edges.h +++ b/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/flip_edges.h @@ -1008,8 +1008,8 @@ namespace internal { typedef typename C3t3::Triangulation Tr; typedef typename C3t3::Vertex_handle Vertex_handle; - typedef typename C3t3::Facet Facet; - typedef typename C3t3::Surface_patch_index Surface_patch_index; +// typedef typename C3t3::Facet Facet; +// typedef typename C3t3::Surface_patch_index Surface_patch_index; typedef typename Tr::Facet_circulator Facet_circulator; Tr& tr = c3t3.triangulation(); @@ -1097,7 +1097,7 @@ namespace internal Visitor& visitor) { typedef typename C3t3::Triangulation Tr; - typedef typename Tr::Vertex_handle Vertex_handle; +// typedef typename Tr::Vertex_handle Vertex_handle; typedef typename Tr::Cell_handle Cell_handle; typedef typename Tr::Edge Edge; diff --git a/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/smooth_vertices.h b/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/smooth_vertices.h index 0371128da30..0ec9e7e643b 100644 --- a/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/smooth_vertices.h +++ b/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/smooth_vertices.h @@ -142,8 +142,8 @@ namespace CGAL { typename Tr::Geom_traits::Construct_opposite_vector_3 opp = c3t3.triangulation().geom_traits().construct_opposite_vector_3_object(); - typename Tr::Geom_traits::Construct_scaled_vector_3 - scale = c3t3.triangulation().geom_traits().construct_scaled_vector_3_object(); +// typename Tr::Geom_traits::Construct_scaled_vector_3 +// scale = c3t3.triangulation().geom_traits().construct_scaled_vector_3_object(); const Tr& tr = c3t3.triangulation(); @@ -348,7 +348,7 @@ namespace CGAL const bool protect_boundaries, const CellSelector& cell_selector) { - typedef typename C3T3::Cell_handle Cell_handle; +// typedef typename C3T3::Cell_handle Cell_handle; typedef typename Gt::FT FT; #ifdef CGAL_TETRAHEDRAL_REMESHING_DEBUG diff --git a/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/tetrahedral_adaptive_remeshing_impl.h b/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/tetrahedral_adaptive_remeshing_impl.h index 65e3d361df5..4df37371be6 100644 --- a/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/tetrahedral_adaptive_remeshing_impl.h +++ b/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/tetrahedral_adaptive_remeshing_impl.h @@ -26,6 +26,8 @@ #include #include +#include + namespace CGAL { @@ -37,17 +39,17 @@ namespace internal { public: template - void before_split(const Tr& tr, const typename Tr::Edge& e) {} + void before_split(const Tr& /* tr */, const typename Tr::Edge& /* e */) {} template - void after_split(const Tr& tr, const typename Tr::Vertex_handle new_v) {} + void after_split(const Tr& /* tr */, const typename Tr::Vertex_handle /* new_v */) {} template - void after_add_cell(CellHandleOld co, CellHandleNew cn) const {} + void after_add_cell(CellHandleOld /* co */, CellHandleNew /* cn */) const {} template - void before_flip(const CellHandle c) {} + void before_flip(const CellHandle /* c */) {} template - void after_flip(CellHandle c) {} + void after_flip(CellHandle /* c */) {} }; template @@ -100,7 +102,7 @@ namespace internal typedef typename C3t3::Subdomain_index Subdomain_index; typedef typename C3t3::Surface_patch_index Surface_patch_index; - typedef typename Tetrahedral_remeshing_smoother Smoother; + typedef Tetrahedral_remeshing_smoother Smoother; private: C3t3 m_c3t3; @@ -110,8 +112,8 @@ namespace internal Visitor& m_visitor; Smoother m_vertex_smoother;//initialized with initial surface - Triangulation* m_tr_pbackup; //backup to re-swap triangulations when done C3t3* m_c3t3_pbackup; + Triangulation* m_tr_pbackup; //backup to re-swap triangulations when done public: Adaptive_remesher(Triangulation& tr diff --git a/Tetrahedral_remeshing/include/CGAL/tetrahedral_remeshing.h b/Tetrahedral_remeshing/include/CGAL/tetrahedral_remeshing.h index cc772a02bb5..bb598fd28a1 100644 --- a/Tetrahedral_remeshing/include/CGAL/tetrahedral_remeshing.h +++ b/Tetrahedral_remeshing/include/CGAL/tetrahedral_remeshing.h @@ -114,7 +114,7 @@ namespace CGAL typedef CGAL::Triangulation_3 Triangulation; tetrahedral_adaptive_remeshing( tr, - [target_edge_length](const Triangulation::Point& p) + [target_edge_length](const typename Triangulation::Point& /* p */) {return target_edge_length;}, np); } @@ -129,7 +129,7 @@ namespace CGAL typedef CGAL::Triangulation_3 Triangulation; tetrahedral_adaptive_remeshing( tr, - [target_edge_length](const Triangulation::Point& p) + [target_edge_length](const typename Triangulation::Point& /* p */) {return target_edge_length; }, np); } From d42b2299d8dfedfa50e79a9cefe66ab20c23bf98 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9bastien=20Loriot?= Date: Wed, 8 Apr 2020 19:22:36 +0200 Subject: [PATCH 225/568] update travis --- .travis.yml | 7 ++++--- .travis/packages.txt | 1 + 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/.travis.yml b/.travis.yml index 1fbffbcaa3e..1c040f94c27 100644 --- a/.travis.yml +++ b/.travis.yml @@ -49,9 +49,10 @@ env: - PACKAGE='Surface_mesh_segmentation Surface_mesh_shortest_path Surface_mesh_simplification ' - PACKAGE='Surface_mesh_skeletonization Surface_mesh_topology Surface_mesher ' - PACKAGE='Surface_sweep_2 TDS_2 TDS_3 ' - - PACKAGE='Testsuite Three Triangulation ' - - PACKAGE='Triangulation_2 Triangulation_3 Union_find ' - - PACKAGE='Visibility_2 Voronoi_diagram_2 wininst ' + - PACKAGE='Testsuite Tetrahedral_remeshing Three ' + - PACKAGE='Triangulation Triangulation_2 Triangulation_3 ' + - PACKAGE='Union_find Visibility_2 Voronoi_diagram_2 ' + - PACKAGE='wininst ' compiler: clang install: - echo "$PWD" diff --git a/.travis/packages.txt b/.travis/packages.txt index b6c8ea4b1f6..86c4a18a5b6 100644 --- a/.travis/packages.txt +++ b/.travis/packages.txt @@ -128,6 +128,7 @@ Surface_sweep_2 TDS_2 TDS_3 Testsuite +Tetrahedral_remeshing Three Triangulation Triangulation_2 From 022c261b93b032ae2941dc398688d5b20c1a4a5e Mon Sep 17 00:00:00 2001 From: Jane Tournois Date: Thu, 9 Apr 2020 06:34:16 +0200 Subject: [PATCH 226/568] make sure no cell has its volume negative after smoothing if so, we shorten the move by 10% - several times is necessary - while making sure every cell still has a positive volume --- .../internal/smooth_vertices.h | 69 +++++++++++++++++-- .../tetrahedral_adaptive_remeshing_impl.h | 5 ++ .../internal/tetrahedral_remeshing_helpers.h | 37 +++++++++- 3 files changed, 102 insertions(+), 9 deletions(-) diff --git a/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/smooth_vertices.h b/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/smooth_vertices.h index 0ec9e7e643b..dc1e029b268 100644 --- a/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/smooth_vertices.h +++ b/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/smooth_vertices.h @@ -21,6 +21,7 @@ #include #include +#include #include #include @@ -321,6 +322,46 @@ namespace CGAL return Vector_3(result[0], result[1], result[2]); } + template + void check_inversion_and_move(const typename Tr::Vertex_handle v, + const typename Tr::Point& final_pos, + const CellRange& inc_cells, + const Tr& tr) + { + const typename Tr::Point backup = v->point(); //backup v's position + const typename Tr::Geom_traits::Point_3 pv = point(backup); + + bool valid_orientation = false; + double frac = 1.0; + typename Tr::Geom_traits::Vector_3 move(pv, point(final_pos)); + do + { + v->set_point(typename Tr::Point(pv + frac * move)); + + bool valid_try = true; + for (const typename Tr::Cell_handle ci : inc_cells) + { + if (CGAL::POSITIVE != CGAL::orientation(point(ci->vertex(0)->point()), + point(ci->vertex(1)->point()), + point(ci->vertex(2)->point()), + point(ci->vertex(3)->point()))) + { + frac = 0.9 * frac; + valid_try = false; + break; + } + } + valid_orientation = valid_try; + +// std::cout << std::boolalpha << "valid orientation = " << valid_orientation +// << "\tfrac = " << frac << std::endl; + } + while(!valid_orientation && frac > 0.1); + + if (!valid_orientation) //move failed + v->set_point(backup); + } + void collect_vertices_surface_indices( const C3t3& c3t3, boost::unordered_map > + inc_cells(nbv, boost::container::small_vector()); + for (const Cell_handle c : tr.finite_cell_handles()) + { + for (int i = 0; i < 4; ++i) + { + const std::size_t id = vertex_id[c->vertex(i)]; + inc_cells[id].push_back(c); + } + } + if (!protect_boundaries) { #ifdef CGAL_TETRAHEDRAL_REMESHING_SMOOTH_SHARP_EDGES @@ -566,8 +619,10 @@ namespace CGAL #ifdef CGAL_TETRAHEDRAL_REMESHING_DEBUG os_surf << "2 " << current_pos << " " << final_position << std::endl, #endif - v->set_point(typename Tr::Point( - final_position.x(), final_position.y(), final_position.z())); + check_inversion_and_move(v, typename Tr::Point( + final_position.x(), final_position.y(), final_position.z()), + inc_cells[vid], + tr); } else if (neighbors[vid] > 0) { @@ -579,15 +634,16 @@ namespace CGAL if (boost::optional mls_projection = project(si, current_pos)) { const typename Tr::Point new_pos(CGAL::ORIGIN + *mls_projection); - v->set_point(new_pos); + check_inversion_and_move(v, new_pos, inc_cells[vid], tr); #ifdef CGAL_TETRAHEDRAL_REMESHING_DEBUG - os_surf0 << "2 " << current_pos << " " << current_pos << std::endl; + os_surf0 << "2 " << current_pos << " " << new_pos << std::endl; #endif } } } } + CGAL_assertion(CGAL::Tetrahedral_remeshing::debug::debug_negative_volumes(tr)); //// end if(!protect_boundaries) smoothed_positions.assign(nbv, CGAL::NULL_VECTOR); @@ -631,13 +687,14 @@ namespace CGAL os_vol << "2 " << point(v->point()); #endif const Vector_3 p = smoothed_positions[vid] / static_cast(neighbors[vid]); - v->set_point(typename Tr::Point(p.x(), p.y(), p.z())); + check_inversion_and_move(v, typename Tr::Point(p.x(), p.y(), p.z()), inc_cells[vid], tr); #ifdef CGAL_TETRAHEDRAL_REMESHING_DEBUG os_vol << " " << point(v->point()) << std::endl; #endif } } + CGAL_assertion(CGAL::Tetrahedral_remeshing::debug::debug_negative_volumes(tr)); #ifdef CGAL_TETRAHEDRAL_REMESHING_VERBOSE std::cout << " done (" << nb_done << " vertices smoothed)." << std::endl; diff --git a/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/tetrahedral_adaptive_remeshing_impl.h b/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/tetrahedral_adaptive_remeshing_impl.h index 4df37371be6..4f4e1460cc0 100644 --- a/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/tetrahedral_adaptive_remeshing_impl.h +++ b/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/tetrahedral_adaptive_remeshing_impl.h @@ -183,6 +183,7 @@ namespace internal m_cell_selector, m_visitor); CGAL_assertion(tr().tds().is_valid(true)); + CGAL_assertion(debug::debug_negative_volumes(tr())); #ifdef CGAL_DUMP_REMESHING_STEPS CGAL::Tetrahedral_remeshing::debug::dump_triangulation_cells(tr(), "1-split.mesh"); CGAL::Tetrahedral_remeshing::debug::dump_binary(m_c3t3, "1-split.binary.cgal"); @@ -200,6 +201,7 @@ namespace internal m_cell_selector, m_visitor); CGAL_assertion(tr().tds().is_valid(true)); + CGAL_assertion(debug::debug_negative_volumes(tr())); #ifdef CGAL_DUMP_REMESHING_STEPS CGAL::Tetrahedral_remeshing::debug::dump_triangulation_cells(tr(), "2-collapse.mesh"); @@ -213,6 +215,7 @@ namespace internal m_cell_selector, m_visitor); CGAL_assertion(tr().tds().is_valid(true)); + CGAL_assertion(debug::debug_negative_volumes(tr())); #ifdef CGAL_DUMP_REMESHING_STEPS CGAL::Tetrahedral_remeshing::debug::dump_triangulation_cells(tr(), "3-flip.mesh"); CGAL::Tetrahedral_remeshing::debug::dump_binary(m_c3t3, "3-flip.binary.cgal"); @@ -224,6 +227,7 @@ namespace internal m_vertex_smoother.smooth_vertices(m_c3t3, m_protect_boundaries, m_cell_selector); CGAL_assertion(tr().tds().is_valid(true)); + CGAL_assertion(debug::debug_negative_volumes(tr())); #ifdef CGAL_DUMP_REMESHING_STEPS CGAL::Tetrahedral_remeshing::debug::dump_triangulation_cells(tr(), "4-smooth.mesh"); @@ -293,6 +297,7 @@ namespace internal } CGAL_assertion(tr().tds().is_valid(true)); + CGAL_assertion(CGAL::Tetrahedral_remeshing::debug::debug_negative_volumes(tr())); #ifdef CGAL_DUMP_REMESHING_STEPS CGAL::Tetrahedral_remeshing::debug::dump_triangulation_cells(tr(), "99-postprocess.mesh"); diff --git a/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/tetrahedral_remeshing_helpers.h b/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/tetrahedral_remeshing_helpers.h index e800facc17b..16d35b91966 100644 --- a/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/tetrahedral_remeshing_helpers.h +++ b/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/tetrahedral_remeshing_helpers.h @@ -853,6 +853,38 @@ namespace Tetrahedral_remeshing template void dump_cells(const CellRange& cells, const char* filename); + template + bool debug_negative_volumes(const Tr& tr) + { + typedef typename Tr::Geom_traits::Point_3 Point_3; + typedef typename Tr::Facet Facet; + + std::set facets; + for (const typename Tr::Cell_handle ch : tr.finite_cell_handles()) + { + const Point_3& p0 = point(ch->vertex(0)->point()); + const Point_3& p1 = point(ch->vertex(1)->point()); + const Point_3& p2 = point(ch->vertex(2)->point()); + const Point_3& p3 = point(ch->vertex(3)->point()); + + const double vol = CGAL::volume(p0, p1, p2, p3); + if (vol < 0.) + { + facets.insert(canonical_facet(Facet(ch, 0))); + facets.insert(canonical_facet(Facet(ch, 1))); + facets.insert(canonical_facet(Facet(ch, 2))); + facets.insert(canonical_facet(Facet(ch, 3))); + } + } + if (!facets.empty()) + { + std::cerr << "Warning : there are inverted cells!\n" + << "\tSee cells_with_negative_volume.polylines.txt" << std::endl; + dump_facets(facets, "cells_with_negative_volume.polylines.txt"); + } + return facets.empty(); + } + template void dump_edges(const Bimap& edges, const char* filename) { @@ -882,12 +914,11 @@ namespace Tetrahedral_remeshing void dump_facets(const FacetRange& facets, const char* filename) { std::ofstream os(filename); - for (typename FacetRange::const_iterator fit = facets.begin(); - fit != facets.end(); ++fit) + for (typename FacetRange::value_type f : facets) { - typename FacetRange::value_type f = *fit; dump_facet(f, os); } + os.close(); } template From 0446f85873984d523c33d1b3c32d6e31501b6a79 Mon Sep 17 00:00:00 2001 From: Jane Tournois Date: Thu, 9 Apr 2020 14:23:01 +0200 Subject: [PATCH 227/568] replace test on volume by test on orientation CGAL::orientation is filtered, and CGAL::volume is not, so there results can be different in nearly degenerate cases --- .../Tetrahedral_remeshing/internal/smooth_vertices.h | 4 ++-- .../internal/tetrahedral_adaptive_remeshing_impl.h | 10 +++++----- .../internal/tetrahedral_remeshing_helpers.h | 6 +++--- 3 files changed, 10 insertions(+), 10 deletions(-) diff --git a/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/smooth_vertices.h b/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/smooth_vertices.h index dc1e029b268..070abfdb7a4 100644 --- a/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/smooth_vertices.h +++ b/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/smooth_vertices.h @@ -643,7 +643,7 @@ namespace CGAL } } } - CGAL_assertion(CGAL::Tetrahedral_remeshing::debug::debug_negative_volumes(tr)); + CGAL_assertion(CGAL::Tetrahedral_remeshing::debug::debug_orientation(tr)); //// end if(!protect_boundaries) smoothed_positions.assign(nbv, CGAL::NULL_VECTOR); @@ -694,7 +694,7 @@ namespace CGAL #endif } } - CGAL_assertion(CGAL::Tetrahedral_remeshing::debug::debug_negative_volumes(tr)); + CGAL_assertion(CGAL::Tetrahedral_remeshing::debug::debug_orientation(tr)); #ifdef CGAL_TETRAHEDRAL_REMESHING_VERBOSE std::cout << " done (" << nb_done << " vertices smoothed)." << std::endl; diff --git a/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/tetrahedral_adaptive_remeshing_impl.h b/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/tetrahedral_adaptive_remeshing_impl.h index 4f4e1460cc0..4696cdd6008 100644 --- a/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/tetrahedral_adaptive_remeshing_impl.h +++ b/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/tetrahedral_adaptive_remeshing_impl.h @@ -183,7 +183,7 @@ namespace internal m_cell_selector, m_visitor); CGAL_assertion(tr().tds().is_valid(true)); - CGAL_assertion(debug::debug_negative_volumes(tr())); + CGAL_assertion(debug::debug_orientation(tr())); #ifdef CGAL_DUMP_REMESHING_STEPS CGAL::Tetrahedral_remeshing::debug::dump_triangulation_cells(tr(), "1-split.mesh"); CGAL::Tetrahedral_remeshing::debug::dump_binary(m_c3t3, "1-split.binary.cgal"); @@ -201,7 +201,7 @@ namespace internal m_cell_selector, m_visitor); CGAL_assertion(tr().tds().is_valid(true)); - CGAL_assertion(debug::debug_negative_volumes(tr())); + CGAL_assertion(debug::debug_orientation(tr())); #ifdef CGAL_DUMP_REMESHING_STEPS CGAL::Tetrahedral_remeshing::debug::dump_triangulation_cells(tr(), "2-collapse.mesh"); @@ -215,7 +215,7 @@ namespace internal m_cell_selector, m_visitor); CGAL_assertion(tr().tds().is_valid(true)); - CGAL_assertion(debug::debug_negative_volumes(tr())); + CGAL_assertion(debug::debug_orientation(tr())); #ifdef CGAL_DUMP_REMESHING_STEPS CGAL::Tetrahedral_remeshing::debug::dump_triangulation_cells(tr(), "3-flip.mesh"); CGAL::Tetrahedral_remeshing::debug::dump_binary(m_c3t3, "3-flip.binary.cgal"); @@ -227,7 +227,7 @@ namespace internal m_vertex_smoother.smooth_vertices(m_c3t3, m_protect_boundaries, m_cell_selector); CGAL_assertion(tr().tds().is_valid(true)); - CGAL_assertion(debug::debug_negative_volumes(tr())); + CGAL_assertion(debug::debug_orientation(tr())); #ifdef CGAL_DUMP_REMESHING_STEPS CGAL::Tetrahedral_remeshing::debug::dump_triangulation_cells(tr(), "4-smooth.mesh"); @@ -297,7 +297,7 @@ namespace internal } CGAL_assertion(tr().tds().is_valid(true)); - CGAL_assertion(CGAL::Tetrahedral_remeshing::debug::debug_negative_volumes(tr())); + CGAL_assertion(debug::debug_orientation(tr())); #ifdef CGAL_DUMP_REMESHING_STEPS CGAL::Tetrahedral_remeshing::debug::dump_triangulation_cells(tr(), "99-postprocess.mesh"); diff --git a/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/tetrahedral_remeshing_helpers.h b/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/tetrahedral_remeshing_helpers.h index 16d35b91966..84fedbc6be4 100644 --- a/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/tetrahedral_remeshing_helpers.h +++ b/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/tetrahedral_remeshing_helpers.h @@ -854,7 +854,7 @@ namespace Tetrahedral_remeshing void dump_cells(const CellRange& cells, const char* filename); template - bool debug_negative_volumes(const Tr& tr) + bool debug_orientation(const Tr& tr) { typedef typename Tr::Geom_traits::Point_3 Point_3; typedef typename Tr::Facet Facet; @@ -867,8 +867,8 @@ namespace Tetrahedral_remeshing const Point_3& p2 = point(ch->vertex(2)->point()); const Point_3& p3 = point(ch->vertex(3)->point()); - const double vol = CGAL::volume(p0, p1, p2, p3); - if (vol < 0.) + const CGAL::Orientation o = CGAL::orientation(p0, p1, p2, p3); + if (o != CGAL::POSITIVE) { facets.insert(canonical_facet(Facet(ch, 0))); facets.insert(canonical_facet(Facet(ch, 1))); From a70473f361f95af597885a1202ccd72056cd588f Mon Sep 17 00:00:00 2001 From: Jane Tournois Date: Thu, 9 Apr 2020 15:17:20 +0200 Subject: [PATCH 228/568] rename debugging function --- .../Tetrahedral_remeshing/internal/smooth_vertices.h | 4 ++-- .../internal/tetrahedral_adaptive_remeshing_impl.h | 10 +++++----- .../internal/tetrahedral_remeshing_helpers.h | 2 +- 3 files changed, 8 insertions(+), 8 deletions(-) diff --git a/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/smooth_vertices.h b/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/smooth_vertices.h index 070abfdb7a4..ee2bde814c2 100644 --- a/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/smooth_vertices.h +++ b/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/smooth_vertices.h @@ -643,7 +643,7 @@ namespace CGAL } } } - CGAL_assertion(CGAL::Tetrahedral_remeshing::debug::debug_orientation(tr)); + CGAL_assertion(CGAL::Tetrahedral_remeshing::debug::are_cell_orientations_valid(tr)); //// end if(!protect_boundaries) smoothed_positions.assign(nbv, CGAL::NULL_VECTOR); @@ -694,7 +694,7 @@ namespace CGAL #endif } } - CGAL_assertion(CGAL::Tetrahedral_remeshing::debug::debug_orientation(tr)); + CGAL_assertion(CGAL::Tetrahedral_remeshing::debug::are_cell_orientations_valid(tr)); #ifdef CGAL_TETRAHEDRAL_REMESHING_VERBOSE std::cout << " done (" << nb_done << " vertices smoothed)." << std::endl; diff --git a/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/tetrahedral_adaptive_remeshing_impl.h b/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/tetrahedral_adaptive_remeshing_impl.h index 4696cdd6008..639c68f2c44 100644 --- a/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/tetrahedral_adaptive_remeshing_impl.h +++ b/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/tetrahedral_adaptive_remeshing_impl.h @@ -183,7 +183,7 @@ namespace internal m_cell_selector, m_visitor); CGAL_assertion(tr().tds().is_valid(true)); - CGAL_assertion(debug::debug_orientation(tr())); + CGAL_assertion(debug::are_cell_orientations_valid(tr())); #ifdef CGAL_DUMP_REMESHING_STEPS CGAL::Tetrahedral_remeshing::debug::dump_triangulation_cells(tr(), "1-split.mesh"); CGAL::Tetrahedral_remeshing::debug::dump_binary(m_c3t3, "1-split.binary.cgal"); @@ -201,7 +201,7 @@ namespace internal m_cell_selector, m_visitor); CGAL_assertion(tr().tds().is_valid(true)); - CGAL_assertion(debug::debug_orientation(tr())); + CGAL_assertion(debug::are_cell_orientations_valid(tr())); #ifdef CGAL_DUMP_REMESHING_STEPS CGAL::Tetrahedral_remeshing::debug::dump_triangulation_cells(tr(), "2-collapse.mesh"); @@ -215,7 +215,7 @@ namespace internal m_cell_selector, m_visitor); CGAL_assertion(tr().tds().is_valid(true)); - CGAL_assertion(debug::debug_orientation(tr())); + CGAL_assertion(debug::are_cell_orientations_valid(tr())); #ifdef CGAL_DUMP_REMESHING_STEPS CGAL::Tetrahedral_remeshing::debug::dump_triangulation_cells(tr(), "3-flip.mesh"); CGAL::Tetrahedral_remeshing::debug::dump_binary(m_c3t3, "3-flip.binary.cgal"); @@ -227,7 +227,7 @@ namespace internal m_vertex_smoother.smooth_vertices(m_c3t3, m_protect_boundaries, m_cell_selector); CGAL_assertion(tr().tds().is_valid(true)); - CGAL_assertion(debug::debug_orientation(tr())); + CGAL_assertion(debug::are_cell_orientations_valid(tr())); #ifdef CGAL_DUMP_REMESHING_STEPS CGAL::Tetrahedral_remeshing::debug::dump_triangulation_cells(tr(), "4-smooth.mesh"); @@ -297,7 +297,7 @@ namespace internal } CGAL_assertion(tr().tds().is_valid(true)); - CGAL_assertion(debug::debug_orientation(tr())); + CGAL_assertion(debug::are_cell_orientations_valid(tr())); #ifdef CGAL_DUMP_REMESHING_STEPS CGAL::Tetrahedral_remeshing::debug::dump_triangulation_cells(tr(), "99-postprocess.mesh"); diff --git a/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/tetrahedral_remeshing_helpers.h b/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/tetrahedral_remeshing_helpers.h index 84fedbc6be4..fba2a3a8747 100644 --- a/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/tetrahedral_remeshing_helpers.h +++ b/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/tetrahedral_remeshing_helpers.h @@ -854,7 +854,7 @@ namespace Tetrahedral_remeshing void dump_cells(const CellRange& cells, const char* filename); template - bool debug_orientation(const Tr& tr) + bool are_cell_orientations_valid(const Tr& tr) { typedef typename Tr::Geom_traits::Point_3 Point_3; typedef typename Tr::Facet Facet; From 76cf92daaa123bcd7794a64673a3854c2c140a1b Mon Sep 17 00:00:00 2001 From: Jane Tournois Date: Thu, 9 Apr 2020 16:36:07 +0200 Subject: [PATCH 229/568] replace Vec3D.h with CGAL::Vector_3 --- .../Tetrahedral_remeshing/internal/FMLS.h | 137 ++++--- .../Tetrahedral_remeshing/internal/Vec3D.h | 366 ------------------ .../internal/smooth_vertices.h | 15 +- 3 files changed, 95 insertions(+), 423 deletions(-) delete mode 100644 Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/Vec3D.h diff --git a/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/FMLS.h b/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/FMLS.h index aee9be085f2..54d3445d7ca 100644 --- a/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/FMLS.h +++ b/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/FMLS.h @@ -22,6 +22,7 @@ #include #include +#include #include #include @@ -29,7 +30,6 @@ #include #include -#include #include @@ -77,24 +77,59 @@ namespace CGAL p[6 * i + 5] = nz; } - inline void weightedPointCombination(const Vec3Df& x, const Vec3Df& pi, const Vec3Df& ni, + template + inline CGAL::Vector_3 projectOn(const CGAL::Vector_3& x, + const CGAL::Vector_3& N, + const CGAL::Vector_3& P) + { + typename Gt::Compute_scalar_product_3 scalar_product + = Gt().compute_scalar_product_3_object(); + + typename Gt::FT w = scalar_product((x - P), N); + return x - (N * w); + } + + template + inline typename Gt::FT length(const CGAL::Vector_3& v) + { + return CGAL::approximate_sqrt(v.squared_length()); + } + + template + inline typename Gt::FT distance(const CGAL::Vector_3& v1, + const CGAL::Vector_3& v2) + { + CGAL::Vector_3 diff(v1.x() - v2.x(), + v1.y() - v2.y(), + v1.z() - v2.z()); + return length(diff); + } + + template + inline void weightedPointCombination(const CGAL::Vector_3& x, + const CGAL::Vector_3& pi, + const CGAL::Vector_3& ni, float sigma_s, bool bilateral, float sigma_r, bool hermite, - Vec3Df& c, Vec3Df& nc, float& sumW) + CGAL::Vector_3& c, CGAL::Vector_3& nc, float& sumW) { - float w = wendland(Vec3Df::distance(x, pi), sigma_s); + float w = wendland(distance(x, pi), sigma_s); if (bilateral) - w *= wendland((x - x.projectOn(ni, pi)).getLength(), sigma_r); + w *= wendland(length(x - projectOn(x, ni, pi)), sigma_r); if (hermite) - c += w * x.projectOn(ni, pi); + c += w * projectOn(x, ni, pi); else c += w * pi; nc += w * ni; sumW += w; } + template class FMLS { + typedef typename Gt::Vector_3 Vector_3; + typedef typename Gt::FT FT; + public: // FMLS provide MLS projection and filtering from a point set. // The underlying data structure is a simple list of float in the PN format @@ -192,30 +227,33 @@ namespace CGAL // Compute, according to the current point sampling stored in FMLS, the MLS projection // of p and store the resulting position in q and normal in n. - void fastProjectionCPU(const Vec3Df& p, Vec3Df& q, Vec3Df& n) const + void fastProjectionCPU(const Vector_3& p, Vector_3& q, Vector_3& n) const { float sigma_s = PNScale * MLSRadius; float sigma_r = bilateralRange; - Vec3Df g = (p - Vec3Df(grid.getMinMax()[0], grid.getMinMax()[1], grid.getMinMax()[2])) / sigma_s; + + Vector_3 g = (p - Vector_3(grid.getMinMax()[0], grid.getMinMax()[1], grid.getMinMax()[2])) / sigma_s; + std::array gxyz = { g.x(), g.y(), g.z() }; + for (unsigned int j = 0; j < 3; j++) { - g[j] = floor(g[j]); - if (g[j] < 0.f) - g[j] = 0.f; - if (g[j] >= grid.getRes()[j]) - g[j] = grid.getRes()[j] - 1; + gxyz[j] = floor(gxyz[j]); + if (gxyz[j] < 0.f) + gxyz[j] = 0.f; + if (gxyz[j] >= grid.getRes()[j]) + gxyz[j] = grid.getRes()[j] - 1; } unsigned int minIt[3], maxIt[3]; for (unsigned int j = 0; j < 3; j++) { - if (((unsigned int)g[j]) == 0) + if (((unsigned int)gxyz[j]) == 0) minIt[j] = 0; else - minIt[j] = ((unsigned int)g[j]) - 1; - if (((unsigned int)g[j]) == (grid.getRes()[j] - 1)) + minIt[j] = ((unsigned int)gxyz[j]) - 1; + if (((unsigned int)gxyz[j]) == (grid.getRes()[j] - 1)) maxIt[j] = (grid.getRes()[j] - 1); else - maxIt[j] = ((unsigned int)g[j]) + 1; + maxIt[j] = ((unsigned int)gxyz[j]) + 1; } - Vec3Df c; + Vector_3 c; float sumW = 0.f; unsigned int it[3]; for (it[0] = minIt[0]; it[0] <= maxIt[0]; it[0]++) @@ -227,19 +265,19 @@ namespace CGAL unsigned int neigh = grid.getCellIndicesSize(it[0], it[1], it[2]); for (unsigned int j = 0; j < neigh; j++) { unsigned int k = grid.getIndicesElement(it[0], it[1], it[2], j); - Vec3Df pk(PN[6 * k], PN[6 * k + 1], PN[6 * k + 2]); - Vec3Df nk(PN[6 * k + 3], PN[6 * k + 4], PN[6 * k + 5]); + Vector_3 pk(PN[6 * k], PN[6 * k + 1], PN[6 * k + 2]); + Vector_3 nk(PN[6 * k + 3], PN[6 * k + 4], PN[6 * k + 5]); weightedPointCombination(p, pk, nk, sigma_s, bilateral, sigma_r, hermite, c, n, sumW); } } if (sumW == 0.f) { - n = Vec3Df(1.f, 0.f, 0.f); + n = Vector_3(1.f, 0.f, 0.f); q = p; } else { c /= sumW; - n.normalize(); - q = p.projectOn(n, c); + normalize(n, Gt()); + q = projectOn(p, n, c); } } @@ -255,11 +293,11 @@ namespace CGAL #pragma omp parallel for #endif for (int i = 0; i < int(pvSize); i++) { - Vec3Df p(pv[stride * i], pv[stride * i + 1], pv[stride * i + 2]); - Vec3Df q, n; + Vector_3 p(pv[stride * i], pv[stride * i + 1], pv[stride * i + 2]); + Vector_3 q, n; for (unsigned int j = 0; j < numIter; j++) { - q = Vec3Df(); - n = Vec3Df(); + q = Vector_3(); + n = Vector_3(); fastProjectionCPU(p, q, n); p = q; } @@ -269,23 +307,23 @@ namespace CGAL } // Brute force version. O(PNSize) complexity. For comparison only. - void projectionCPU(const Vec3Df& x, Vec3Df& q, Vec3Df& n) + void projectionCPU(const Vector_3& x, Vector_3& q, Vector_3& n) { float sigma_s = MLSRadius * PNScale; float sigma_r = bilateralRange; - Vec3Df p(x); + Vector_3 p(x); for (unsigned int k = 0; k < numIter; k++) { - Vec3Df c; - n = Vec3Df();; + Vector_3 c; + n = Vector_3();; float sumW = 0.f; for (unsigned int j = 0; j < PNSize; j++) { - Vec3Df pj(PN[6 * j], PN[6 * j + 1], PN[6 * j + 2]); - Vec3Df nj(PN[6 * j + 3], PN[6 * j + 4], PN[6 * j + 5]); + Vector_3 pj(PN[6 * j], PN[6 * j + 1], PN[6 * j + 2]); + Vector_3 nj(PN[6 * j + 3], PN[6 * j + 4], PN[6 * j + 5]); weightedPointCombination(p, pj, nj, sigma_s, bilateral, sigma_r, hermite, c, n, sumW); } c /= sumW; n.normalize(); - q = p.projectOn(n, c); + q = projectOn(p, n, c); p = q; } @@ -298,11 +336,11 @@ namespace CGAL #pragma omp parallel for #endif for (int i = 0; i < int(pvSize); i++) { - Vec3Df p(pv[stride * i], pv[stride * i + 1], pv[stride * i + 2]); - Vec3Df q, n; + Vector_3 p(pv[stride * i], pv[stride * i + 1], pv[stride * i + 2]); + Vector_3 q, n; for (unsigned int j = 0; j < numIter; j++) { - q = Vec3Df(); - n = Vec3Df(); + q = Vector_3(); + n = Vector_3(); projectionCPU(p, q, n); p = q; } @@ -376,13 +414,13 @@ namespace CGAL void computePNScale() { - Vec3Df c; + Vector_3 c; for (unsigned int i = 0; i < PNSize; i++) - c += Vec3Df(PN[6 * i], PN[6 * i + 1], PN[6 * i + 2]); + c += Vector_3(PN[6 * i], PN[6 * i + 1], PN[6 * i + 2]); c /= PNSize; PNScale = 0.f; for (unsigned int i = 0; i < PNSize; i++) { - float r = Vec3Df::distance(c, Vec3Df(PN[6 * i], PN[6 * i + 1], PN[6 * i + 2])); + float r = distance(c, Vector_3(PN[6 * i], PN[6 * i + 1], PN[6 * i + 2])); if (r > PNScale) PNScale = r; } @@ -436,10 +474,10 @@ namespace CGAL LUT = (unsigned int*)malloc(gridLUTNumOfByte); memset(LUT, 0, gridLUTNumOfByte); unsigned int nonEmptyCells = 0; - Vec3Df gMin(minMax[0], minMax[1], minMax[2]); - Vec3Df gMax(minMax[3], minMax[4], minMax[5]); + Vector_3 gMin(minMax[0], minMax[1], minMax[2]); + Vector_3 gMax(minMax[3], minMax[4], minMax[5]); for (unsigned int i = 0; i < PNSize; i++) { - unsigned int index = getLUTIndex(Vec3Df(PN[6 * i], PN[6 * i + 1], PN[6 * i + 2])); + unsigned int index = getLUTIndex(Vector_3(PN[6 * i], PN[6 * i + 1], PN[6 * i + 2])); if (LUT[index] == 0) nonEmptyCells++; LUT[index]++; @@ -461,7 +499,7 @@ namespace CGAL LUT[index] = 2 * PNSize; } for (unsigned int i = 0; i < PNSize; i++) { - Vec3Df p = Vec3Df(PN[6 * i], PN[6 * i + 1], PN[6 * i + 2]); + Vector_3 p = Vector_3(PN[6 * i], PN[6 * i + 1], PN[6 * i + 2]); unsigned int indicesIndex = getLUTElement(p); unsigned int totalCount = indices[indicesIndex]; unsigned int countIndex = indicesIndex + totalCount; @@ -506,9 +544,10 @@ namespace CGAL { return LUT[getLUTIndex(i, j, k)]; } - unsigned int getLUTIndex(const Vec3Df& x) const + unsigned int getLUTIndex(const Vector_3& x) const { - Vec3Df p = (x - Vec3Df(minMax[0], minMax[1], minMax[2])) / cellSize; + Vector_3 vp = (x - Vector_3(minMax[0], minMax[1], minMax[2])) / cellSize; + std::array p = { vp.x(), vp.y(), vp.z() }; for (unsigned int j = 0; j < 3; j++) { p[j] = floor(p[j]); if (p[j] < 0) @@ -521,7 +560,7 @@ namespace CGAL + ((unsigned int)floor(p[0])); return index; } - inline unsigned int getLUTElement(const Vec3Df& x) const { + inline unsigned int getLUTElement(const Vector_3& x) const { return LUT[getLUTIndex(x)]; } inline unsigned int* getIndices() { return indices; } @@ -830,7 +869,7 @@ namespace CGAL average_point_spacing = average_point_spacing / nb_of_mls_to_create; - subdomain_FMLS.resize(nb_of_mls_to_create, FMLS()); + subdomain_FMLS.resize(nb_of_mls_to_create, FMLS()); count = 0; //Creating the actual MLS surfaces diff --git a/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/Vec3D.h b/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/Vec3D.h deleted file mode 100644 index 29bd20e9fa9..00000000000 --- a/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/Vec3D.h +++ /dev/null @@ -1,366 +0,0 @@ -// Copyright (c) 2020 GeometryFactory (France) and Telecom Paris (France). -// All rights reserved. -// -// This file is part of CGAL (www.cgal.org) -// -// $URL$ -// $Id$ -// SPDX-License-Identifier: GPL-3.0-or-later OR LicenseRef-Commercial -// -// -// Author(s) : Jane Tournois, Noura Faraj - -#pragma once - -#include -#include - -template class Vec3D; - -template bool operator!= (const Vec3D & p1, const Vec3D & p2) { - return (p1[0] != p2[0] || p1[1] != p2[1] || p1[2] != p2[2]); -} - -template const Vec3D operator* (const Vec3D & p, double factor) { - return Vec3D (p[0] * factor, p[1] * factor, p[2] * factor); -} - -template const Vec3D operator* (double factor, const Vec3D & p) { - return Vec3D (p[0] * factor, p[1] * factor, p[2] * factor); -} - -template const Vec3D operator* (const Vec3D & p1, const Vec3D & p2) { - return Vec3D (p1[0] * p2[0], p1[1] * p2[1], p1[2] * p2[2]); -} - -template const Vec3D operator+ (const Vec3D & p1, const Vec3D & p2) { - return Vec3D (p1[0] + p2[0], p1[1] + p2[1], p1[2] + p2[2]); -} - -template const Vec3D operator- (const Vec3D & p1, const Vec3D & p2) { - return Vec3D (p1[0] - p2[0], p1[1] - p2[1], p1[2] - p2[2]); -} - -template const Vec3D operator- (const Vec3D & p) { - return Vec3D (-p[0], -p[1], -p[2]); -} - -template const Vec3D operator/ (const Vec3D & p, double divisor) { - return Vec3D (p[0]/divisor, p[1]/divisor, p[2]/divisor); -} - -template bool operator== (const Vec3D & p1, const Vec3D & p2) { - return (p1[0] == p2[0] && p1[1] == p2[1] && p1[2] == p2[2]); -} - -template bool operator< (const Vec3D & a, const Vec3D & b) { - return (a[0] < b[0] && a[1] < b[1] && a[2] < b[2]); -} - -template bool operator>= (const Vec3D & a, const Vec3D & b) { - return (a[0] >= b[0] || a[1] >= b[1] || a[2] >= b[2]); -} - -/** - * Vector in 3 dimensions, with basics operators overloaded. - */ -template -class Vec3D{ - public: - inline Vec3D (void) { - p[0] = p[1] = p[2] = T (); - } - inline Vec3D (T p0, T p1, T p2) { - p[0] = p0; - p[1] = p1; - p[2] = p2; - }; - inline Vec3D (const Vec3D & v) { - init (v[0], v[1], v[2]); - } - inline Vec3D (T* pp) { - p[0] = pp[0]; - p[1] = pp[1]; - p[2] = pp[2]; - }; - // --------- - // Operators - // --------- - // typedef Eigen::Matrix Vector3; - // - // inline operator Vector3() { // FIXME - // return Vector3(p[0], p[1], p[2]); - // } - inline operator T*() { - return p; - } - inline operator const T*() const { - return p; - } - inline T& operator[] (int Index) { - return (p[Index]); - }; - inline const T& operator[] (int Index) const { - return (p[Index]); - }; - inline Vec3D& operator= (const Vec3D & P) { - p[0] = P[0]; - p[1] = P[1]; - p[2] = P[2]; - return (*this); - }; - inline Vec3D& operator+= (const Vec3D & P) { - p[0] += P[0]; - p[1] += P[1]; - p[2] += P[2]; - return (*this); - }; - inline Vec3D& operator-= (const Vec3D & P) { - p[0] -= P[0]; - p[1] -= P[1]; - p[2] -= P[2]; - return (*this); - }; - inline Vec3D& operator*= (const Vec3D & P) { - p[0] *= P[0]; - p[1] *= P[1]; - p[2] *= P[2]; - return (*this); - }; - inline Vec3D& operator*= (T s) { - p[0] *= s; - p[1] *= s; - p[2] *= s; - return (*this); - }; - inline Vec3D& operator/= (const Vec3D & P) { - p[0] /= P[0]; - p[1] /= P[1]; - p[2] /= P[2]; - return (*this); - }; - inline Vec3D& operator/= (T s) { - p[0] /= s; - p[1] /= s; - p[2] /= s; - return (*this); - }; - - //--------------------------------------------------------------- - - inline Vec3D & init (T x, T y, T z) { - p[0] = x; - p[1] = y; - p[2] = z; - return (*this); - }; - inline T getSquaredLength() const { - return (dotProduct (*this, *this)); - }; - inline T getLength() const { - return (T)sqrt (getSquaredLength()); - }; - /// Return length after normalization - inline T normalize (void) { - T length = getLength(); - if (length == 0.0f) - return 0; - T rezLength = 1.0f / length; - p[0] *= rezLength; - p[1] *= rezLength; - p[2] *= rezLength; - return length; - }; - inline void fromTo (const Vec3D & P1, const Vec3D & P2) { - p[0] = P2[0] - P1[0]; - p[1] = P2[1] - P1[1]; - p[2] = P2[2] - P1[2]; - }; - inline double transProduct (const Vec3D & v) const { - return (p[0]*v[0] + p[1]*v[1] + p[2]*v[2]); - } - inline void getTwoOrthogonals (Vec3D & u, Vec3D & v) const { - if (fabs(p[0]) < fabs(p[1])) { - if (fabs(p[0]) < fabs(p[2])) - u = Vec3D (0, -p[2], p[1]); - else - u = Vec3D (-p[1], p[0], 0); - } else { - if (fabs(p[1]) < fabs(p[2])) - u = Vec3D (p[2], 0, -p[0]); - else - u = Vec3D(-p[1], p[0], 0); - } - v = crossProduct (*this, u); - } - inline Vec3D projectOn (const Vec3D & N, const Vec3D & P) const { - T w = dotProduct (((*this) - P), N); - return (*this) - (N * w); - } - static inline Vec3D segment (const Vec3D & a, const Vec3D & b) { - Vec3D r; - r[0] = b[0] - a[0]; - r[1] = b[1] - a[1]; - r[2] = b[2] - a[2]; - return r; - }; - static inline Vec3D crossProduct(const Vec3D & a, const Vec3D & b) { - Vec3D result; - result[0] = a[1] * b[2] - a[2] * b[1]; - result[1] = a[2] * b[0] - a[0] * b[2]; - result[2] = a[0] * b[1] - a[1] * b[0]; - return(result); - } - static inline void computeRepere(const Vec3D & n, const T& theta, Vec3D& x, Vec3D& y, Vec3D& z) - { - z = n; - x = z; - if(x[2] == 0) - { - x = Vec3D(0,0,1); - } - else if(x[1]==0) - { - x = Vec3D(1,0,0); - } - else - { - x[2] = -(x[0] + x[1])/x[2]; - x[0] = x[1] = 1; - } - y = Vec3D::crossProduct(z,x); - y.normalize(); - x = Vec3D::crossProduct(y,z); - x.normalize(); - - Vec3D xp = cos(theta)*x + sin(theta)*y, yp = cos(theta)*y - sin(theta)*x; - x = xp; - y = yp; - x.normalize(); - y.normalize(); - } - static inline T dotProduct(const Vec3D & a, const Vec3D & b) { - return (a[0] * b[0] + a[1] * b[1] + a[2] * b[2]); - } - static inline T squaredDistance (const Vec3D &v1, const Vec3D &v2) { - Vec3D tmp = v1 - v2; - return (tmp.getSquaredLength()); - } - static inline T distance (const Vec3D &v1, const Vec3D &v2) { - Vec3D tmp = v1 - v2; - return (tmp.getLength()); - } - static inline Vec3D interpolate (const Vec3D & u, const Vec3D & v, T alpha) { - return (u * (1.0f - alpha) + v * alpha); - } - static inline Vec3D rotate(const Vec3D & v, const Vec3D & axes, double theta = 0.0) { - double c = cos(theta), s = sin(theta); - const double &x = axes[0], &y = axes[1], &z = axes[2]; - double x2 = x*x, y2 = y*y, z2 = z*z; - return Vec3D((x2+(1-x2)*c)*v[0] + (x*y*(1-c)-z*s)*v[1] + (x*z*(1-c)+y*s)*v[2], - (x*y*(1-c)+z*s)*v[0] + (y2+(1-y2)*c)*v[1] + (y*z*(1-c)-x*s)*v[2], - (x*z*(1-c)-y*s)*v[0] + (y*z*(1-c)+x*s)*v[1] + (z2+(1-z2)*c)*v[2]); - } - static inline Vec3D changeReference(const Vec3D & v, const Vec3D & x, const Vec3D & y, const Vec3D & z) { - return Vec3D(dotProduct(v,x),dotProduct(v,y),dotProduct(v,z)); - } - static inline Vec3D changeReference(const Vec3D & v, const Vec3D & c, const Vec3D & x, const Vec3D & y, const Vec3D & z) { - Vec3D vn = v-c; - return Vec3D(dotProduct(vn,x),dotProduct(vn,y),dotProduct(vn,z)); - } - - - // cartesion to polar coordinates - // result: - // [0] = length - // [1] = angle with z-axis - // [2] = angle of projection into x,y, plane with x-axis - static inline Vec3D cartesianToPolar (const Vec3D &v) { - Vec3D polar; - polar[0] = v.getLength(); - if (v[2] > 0.0f) - polar[1] = (T) atan (sqrt (v[0] * v[0] + v[1] * v[1]) / v[2]); - else if (v[2] < 0.0f) - polar[1] = (T) atan (sqrt (v[0] * v[0] + v[1] * v[1]) / v[2]) + M_PI; - else - polar[1] = M_PI * 0.5f; - if (v[0] > 0.0f) - polar[2] = (T) atan (v[1] / v[0]); - else if (v[0] < 0.0f) - polar[2] = (T) atan (v[1] / v[0]) + M_PI; - else if (v[1] > 0) - polar[2] = M_PI * 0.5f; - else - polar[2] = -M_PI * 0.5; - return polar; - } - - // polar to cartesion coordinates - // input: - // [0] = length - // [1] = angle with z-axis - // [2] = angle of projection into x,y, plane with x-axis - static inline Vec3D polarToCartesian (const Vec3D & v) { - Vec3D cart; - cart[0] = v[0] * (T) sin (v[1]) * (T) cos (v[2]); - cart[1] = v[0] * (T) sin (v[1]) * (T) sin (v[2]); - cart[2] = v[0] * (T) cos (v[1]); - return cart; - } - static inline Vec3D projectOntoVector (const Vec3D & v1, const Vec3D & v2) { - return v2 * dotProduct (v1, v2); - } - inline Vec3D transformIn (const Vec3D & pos, const Vec3D & n, const Vec3D & u, const Vec3D & v) const { - Vec3D q = (*this) - pos; - return Vec3D (u[0]*q[0] + u[1]*q[1] + u[2]*q[2], - v[0]*q[0] + v[1]*q[1] + v[2]*q[2], - n[0]*q[0] + n[1]*q[1] + n[2]*q[2]); - } - - protected: - T p[3]; -}; - -template inline void swap (Vec3D & P, Vec3D & Q) { - Vec3D tmp = P; - P = Q; - Q = tmp; -} - -template std::ostream & operator<< (std::ostream & output, const Vec3D & v) { - output << v[0] << " " << v[1] << " " << v[2]; - return output; -} - -template void read (std::istream & input, Vec3D & v) { - float val[3]; - input.read((char*)val, 3*sizeof(float)); - v[0] = val[0]; - v[1] = val[1]; - v[2] = val[2]; -} - -template void write (std::ostream & output, const Vec3D & v) { - float val = v[0]; - output.write((char*)(&val), sizeof(float)); - val = v[1]; - output.write((char*)(&val), sizeof(float)); - val = v[2]; - output.write((char*)(&val), sizeof(float)); -} - -template std::istream & operator>> (std::istream & input, Vec3D & v) { - input >> v[0] >> v[1] >> v[2]; - return input; -} - -typedef Vec3D Vec3Dd; -typedef Vec3D Vec3Df; -typedef Vec3D Vec3Di; - -// Some Emacs-Hints -- please don't remove: -// -// Local Variables: -// mode:C++ -// tab-width:4 -// End: diff --git a/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/smooth_vertices.h b/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/smooth_vertices.h index ee2bde814c2..b8bd1ac4a01 100644 --- a/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/smooth_vertices.h +++ b/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/smooth_vertices.h @@ -17,7 +17,6 @@ #include #include -#include #include #include @@ -47,7 +46,8 @@ namespace CGAL typedef typename Gt::Point_3 Point_3; private: - std::vector < CGAL::Tetrahedral_remeshing::internal::FMLS > subdomain_FMLS; + typedef CGAL::Tetrahedral_remeshing::internal::FMLS FMLS; + std::vector subdomain_FMLS; boost::unordered_map subdomain_FMLS_indices; public: @@ -293,12 +293,11 @@ namespace CGAL CGAL_assertion(subdomain_FMLS_indices.find(si) != subdomain_FMLS_indices.end()); CGAL_assertion(!std::isnan(gi.x()) && !std::isnan(gi.y()) && !std::isnan(gi.z())); - Vec3Df point(gi.x(), gi.y(), gi.z()); - Vec3Df res_normal; - Vec3Df result(point); + Vector_3 point(gi.x(), gi.y(), gi.z()); + Vector_3 res_normal; + Vector_3 result(point); - const CGAL::Tetrahedral_remeshing::internal::FMLS& - fmls = subdomain_FMLS[subdomain_FMLS_indices.at(si)]; + const FMLS& fmls = subdomain_FMLS[subdomain_FMLS_indices.at(si)]; int it_nb = 0; const int max_it_nb = 5; @@ -317,7 +316,7 @@ namespace CGAL << "\t(point = " << point << " )" << std::endl; return {}; } - } while ((result - point).getSquaredLength() > sq_eps&& ++it_nb < max_it_nb); + } while ((result - point).squared_length() > sq_eps && ++it_nb < max_it_nb); return Vector_3(result[0], result[1], result[2]); } From acd6d9d8de59901235b759b9e2059d5bf032a981 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9bastien=20Loriot?= Date: Fri, 10 Apr 2020 07:50:42 +0200 Subject: [PATCH 230/568] removing tabs and trailing whitespaces --- Mesh_3/include/CGAL/IO/File_medit.h | 180 +++++++++--------- .../Plugins/Mesh_3/C3t3_io_plugin.cpp | 14 +- .../demo/Polyhedron/Scene_c3t3_item.cpp | 86 ++++----- .../Concepts/RemeshingTriangulationTraits_3.h | 2 +- .../Tetrahedral_remeshing/CMakeLists.txt | 4 +- .../tetrahedral_remeshing_with_features.cpp | 2 +- .../Remeshing_triangulation_3.h | 8 +- .../Remeshing_vertex_base.h | 6 +- .../Tetrahedral_remeshing/internal/FMLS.h | 8 +- .../internal/collapse_short_edges.h | 2 +- .../internal/compute_c3t3_statistics.h | 4 +- .../internal/flip_edges.h | 2 +- .../internal/split_long_edges.h | 2 +- .../tetrahedral_adaptive_remeshing_impl.h | 2 +- .../internal/tetrahedral_remeshing_helpers.h | 4 +- .../include/CGAL/tetrahedral_remeshing.h | 4 +- 16 files changed, 165 insertions(+), 165 deletions(-) diff --git a/Mesh_3/include/CGAL/IO/File_medit.h b/Mesh_3/include/CGAL/IO/File_medit.h index 6c3f2ced314..a0005e98894 100644 --- a/Mesh_3/include/CGAL/IO/File_medit.h +++ b/Mesh_3/include/CGAL/IO/File_medit.h @@ -126,13 +126,13 @@ private: else return -1; } - + private: const C3T3& r_c3t3_; Subdomain_map subdomain_map_; }; - -// Accessor + +// Accessor template int get(const Rebind_cell_pmap& cmap, @@ -146,7 +146,7 @@ unsigned int get_size(const Rebind_cell_pmap& cmap) { return cmap.subdomain_number(); } - + // ----------------------------------- // No_rebind_cell_pmap @@ -157,21 +157,21 @@ class No_rebind_cell_pmap typedef typename C3T3::Subdomain_index Subdomain_index; typedef typename C3T3::Cell_handle Cell_handle; typedef unsigned int size_type; - + public: No_rebind_cell_pmap(const C3T3& c3t3) : r_c3t3_(c3t3) {} - + int subdomain_index(const Cell_handle& ch) const { return static_cast(r_c3t3_.subdomain_index(ch)); } - + size_type subdomain_number() const { typedef typename C3T3::Cells_in_complex_iterator Cell_iterator; std::set subdomain_set; - + for( Cell_iterator cell_it = r_c3t3_.cells_in_complex_begin(); cell_it != r_c3t3_.cells_in_complex_end(); ++cell_it) @@ -179,15 +179,15 @@ public: // Add subdomain index in set subdomain_set.insert(subdomain_index(cell_it)); } - + return subdomain_set.size(); } - + private: const C3T3& r_c3t3_; }; - -// Accessor + +// Accessor template int get(const No_rebind_cell_pmap& cmap, @@ -195,8 +195,8 @@ get(const No_rebind_cell_pmap& cmap, { return cmap.subdomain_index(ch); } - - + + // ----------------------------------- // Rebind_facet_pmap // ----------------------------------- @@ -207,17 +207,17 @@ class Rebind_facet_pmap typedef std::map Surface_map; typedef typename C3T3::Facet Facet; typedef unsigned int size_type; - + public: Rebind_facet_pmap(const C3T3& c3t3, const Cell_pmap& cell_pmap) : r_c3t3_(c3t3) , cell_pmap_(cell_pmap) { typedef typename C3T3::Facets_in_complex_iterator Facet_iterator; - + int first_index = 1; int index_counter = first_index; - + for( Facet_iterator facet_it = r_c3t3_.facets_in_complex_begin(); facet_it != r_c3t3_.facets_in_complex_end(); ++facet_it) @@ -229,11 +229,11 @@ public: if(is_insert_successful.second) ++index_counter; } - + // Find cell_pmap_ unused indices typedef typename C3T3::Cells_in_complex_iterator Cell_iterator; std::set cell_label_set; - + for( Cell_iterator cell_it = r_c3t3_.cells_in_complex_begin(); cell_it != r_c3t3_.cells_in_complex_end(); ++cell_it) @@ -241,7 +241,7 @@ public: // Add subdomain index in set cell_label_set.insert(get(cell_pmap_, cell_it)); } - + // Rebind indices index_counter = get_first_unused_label(cell_label_set,first_index); for ( typename Surface_map::iterator mit = surface_map_.begin() ; @@ -251,11 +251,11 @@ public: mit->second = index_counter++; index_counter = get_first_unused_label(cell_label_set,index_counter); } - + #ifdef CGAL_MESH_3_IO_VERBOSE std::cerr << "Nb of surface patches: " << surface_map_.size() << "\n"; std::cerr << "Surface mapping:\n\t" ; - + typedef typename Surface_map::iterator Surface_map_iterator; for ( Surface_map_iterator surf_it = surface_map_.begin() ; surf_it != surface_map_.end() ; @@ -267,17 +267,17 @@ public: std::cerr << "\n"; #endif } - + int surface_index(const Facet& f) const { return surface_index(r_c3t3_.surface_patch_index(f)); } - + size_type surface_number() const { return surface_map_.size(); } - + private: int surface_index(const Surface_patch_index& index) const { @@ -288,23 +288,23 @@ private: else return -1; } - + int get_first_unused_label(const std::set& label_set, int search_start) const { while ( label_set.end() != label_set.find(search_start) ) ++search_start; - + return search_start; } - + private: const C3T3& r_c3t3_; const Cell_pmap& cell_pmap_; Surface_map surface_map_; }; - + // Accessors template int @@ -313,7 +313,7 @@ get(const Rebind_facet_pmap& fmap, { return fmap.surface_index(f); } - + template unsigned int get_size(const Rebind_facet_pmap& fmap, @@ -322,7 +322,7 @@ get_size(const Rebind_facet_pmap& fmap, return fmap.surface_number(f); } - + // ----------------------------------- // No_rebind_facet_pmap // ----------------------------------- @@ -332,7 +332,7 @@ class No_rebind_facet_pmap typedef typename C3T3::Surface_patch_index Surface_patch_index; typedef typename C3T3::Facet Facet; typedef unsigned int size_type; - + public: No_rebind_facet_pmap(const C3T3& c3t3, const Cell_pmap& /*cell_pmap*/) : r_c3t3_(c3t3) {} @@ -341,7 +341,7 @@ public: { return static_cast(r_c3t3_.surface_patch_index(f)); } - + private: const C3T3& r_c3t3_; }; @@ -365,16 +365,16 @@ class No_rebind_facet_pmap_first typedef typename C3T3::Surface_patch_index Surface_patch_index; typedef typename C3T3::Facet Facet; typedef unsigned int size_type; - + public: No_rebind_facet_pmap_first(const C3T3& c3t3, const Cell_pmap& /*cell_pmap*/) : r_c3t3_(c3t3) {} - + int surface_index(const Facet& f) const { return static_cast(r_c3t3_.surface_patch_index(f).first); } - + private: const C3T3& r_c3t3_; }; @@ -388,8 +388,8 @@ get(const No_rebind_facet_pmap_first& fmap, { return fmap.surface_index(f); } - - + + // ----------------------------------- // No_rebind_facet_pmap_second // ----------------------------------- @@ -399,16 +399,16 @@ class No_rebind_facet_pmap_second typedef typename C3T3::Surface_patch_index Surface_patch_index; typedef typename C3T3::Facet Facet; typedef unsigned int size_type; - + public: No_rebind_facet_pmap_second(const C3T3& c3t3, const Cell_pmap& /*cell_pmap*/) : r_c3t3_(c3t3) {} - + int surface_index(const Facet& f) const { return static_cast(r_c3t3_.surface_patch_index(f).second); } - + private: const C3T3& r_c3t3_; }; @@ -422,9 +422,9 @@ get(const No_rebind_facet_pmap_second& fmap, { return fmap.surface_index(f); } - - - + + + // ----------------------------------- // No_patch_facet_pmap_first // ----------------------------------- @@ -434,32 +434,32 @@ class No_patch_facet_pmap_first typedef typename C3T3::Surface_patch_index Surface_patch_index; typedef typename C3T3::Facet Facet; typedef typename C3T3::Cell_handle Cell_handle; - + public: No_patch_facet_pmap_first(const C3T3&, const Cell_pmap& cell_pmap) : cell_pmap_(cell_pmap) { } - + int surface_index(const Facet& f) const { Cell_handle c1 = f.first; Cell_handle c2 = c1->neighbor(f.second); - + int label1 = get(cell_pmap_,c1); int label2 = get(cell_pmap_,c2); - + if ( 0 == label1 || -1 == label1 ) label1 = label2; if ( 0 == label2 || -1 == label2 ) label2 = label1; - + return (std::min)(label1,label2); } - + private: const Cell_pmap& cell_pmap_; }; -// Accessors +// Accessors template int get(const No_patch_facet_pmap_first& fmap, @@ -477,32 +477,32 @@ class No_patch_facet_pmap_second typedef typename C3T3::Surface_patch_index Surface_patch_index; typedef typename C3T3::Facet Facet; typedef typename C3T3::Cell_handle Cell_handle; - + public: No_patch_facet_pmap_second(const C3T3&, const Cell_pmap& cell_pmap) : cell_pmap_(cell_pmap) { } - + int surface_index(const Facet& f) const { Cell_handle c1 = f.first; Cell_handle c2 = c1->neighbor(f.second); - + int label1 = get(cell_pmap_,c1); int label2 = get(cell_pmap_,c2); - + if ( 0 == label1 || -1 == label1 ) label1 = label2; if ( 0 == label2 || -1 == label2 ) label2 = label1; - + return (std::max)(label1,label2); } - + private: const Cell_pmap& cell_pmap_; }; -// Accessors +// Accessors template int get(const No_patch_facet_pmap_second& fmap, @@ -510,11 +510,11 @@ get(const No_patch_facet_pmap_second& fmap, { return fmap.surface_index(f); } - - + + // ----------------------------------- // Default_vertex_index_pmap -// ----------------------------------- +// ----------------------------------- template class Default_vertex_pmap { @@ -611,26 +611,26 @@ get(const Default_vertex_pmap& vmap, // ----------------------------------- // Null pmap -// ----------------------------------- +// ----------------------------------- template struct Null_facet_pmap { Null_facet_pmap(const C3T3&, const Cell_pmap&) {} }; - + template int get(const Null_facet_pmap&, const typename C3T3::Facet&) { return 0; } - + template struct Null_vertex_pmap { Null_vertex_pmap(const C3T3&, const Cell_pmap&, const Facet_pmap&) {} }; - + template int get(const Null_vertex_pmap&, const typename C3T3::Vertex_handle&) @@ -645,7 +645,7 @@ int get(const Null_vertex_pmap&, template struct Medit_pmap_generator{}; - + template struct Medit_pmap_generator { @@ -653,11 +653,11 @@ struct Medit_pmap_generator typedef Rebind_facet_pmap Facet_pmap; typedef Null_facet_pmap Facet_pmap_twice; typedef Default_vertex_pmap Vertex_pmap; - + bool print_twice() { return false; } }; - - + + template struct Medit_pmap_generator { @@ -665,7 +665,7 @@ struct Medit_pmap_generator typedef No_patch_facet_pmap_first Facet_pmap; typedef No_patch_facet_pmap_second Facet_pmap_twice; typedef Default_vertex_pmap Vertex_pmap; - + bool print_twice() { return true; } }; @@ -677,10 +677,10 @@ struct Medit_pmap_generator typedef No_patch_facet_pmap_first Facet_pmap; typedef No_patch_facet_pmap_second Facet_pmap_twice; typedef Default_vertex_pmap Vertex_pmap; - + bool print_twice() { return true; } }; - + template struct Medit_pmap_generator { @@ -688,17 +688,17 @@ struct Medit_pmap_generator typedef Rebind_facet_pmap Facet_pmap; typedef Null_facet_pmap Facet_pmap_twice; typedef Null_vertex_pmap Vertex_pmap; - + bool print_twice() { return false; } }; - + //------------------------------------------------------- // IO functions //------------------------------------------------------- - + template void output_to_medit(std::ostream& os, @@ -707,18 +707,18 @@ output_to_medit(std::ostream& os, #ifdef CGAL_MESH_3_IO_VERBOSE std::cerr << "Output to medit:\n"; #endif - + typedef Medit_pmap_generator Generator; typedef typename Generator::Cell_pmap Cell_pmap; typedef typename Generator::Facet_pmap Facet_pmap; typedef typename Generator::Facet_pmap_twice Facet_pmap_twice; typedef typename Generator::Vertex_pmap Vertex_pmap; - + Cell_pmap cell_pmap(c3t3); Facet_pmap facet_pmap(c3t3,cell_pmap); Facet_pmap_twice facet_pmap_twice(c3t3,cell_pmap); Vertex_pmap vertex_pmap(c3t3,cell_pmap,facet_pmap); - + output_to_medit(os, c3t3, vertex_pmap, @@ -726,14 +726,14 @@ output_to_medit(std::ostream& os, cell_pmap, facet_pmap_twice, Generator().print_twice()); - + #ifdef CGAL_MESH_3_IO_VERBOSE std::cerr << "done.\n"; #endif } - + template subdomain_index() > f.first->neighbor(f.second)->subdomain_index()) f = tr.mirror_facet(f); } - + // Get facet vertices in CCW order. Vertex_handle vh1 = f.first->vertex((f.second + 1) % 4); Vertex_handle vh2 = f.first->vertex((f.second + 2) % 4); Vertex_handle vh3 = f.first->vertex((f.second + 3) % 4); - + // Facet orientation also depends on parity. if (f.second % 2 != 0) std::swap(vh2, vh3); - - os << V[vh1] << ' ' << V[vh2] << ' ' << V[vh3] << ' '; + + os << V[vh1] << ' ' << V[vh2] << ' ' << V[vh3] << ' '; os << get(facet_pmap, *fit) << '\n'; - + // Print triangle again if needed, with opposite orientation if ( print_each_facet_twice ) { - os << V[vh3] << ' ' << V[vh2] << ' ' << V[vh1] << ' '; + os << V[vh3] << ' ' << V[vh2] << ' ' << V[vh1] << ' '; os << get(facet_twice_pmap, *fit) << '\n'; } } diff --git a/Polyhedron/demo/Polyhedron/Plugins/Mesh_3/C3t3_io_plugin.cpp b/Polyhedron/demo/Polyhedron/Plugins/Mesh_3/C3t3_io_plugin.cpp index 69b626f5397..b78a17c731b 100644 --- a/Polyhedron/demo/Polyhedron/Plugins/Mesh_3/C3t3_io_plugin.cpp +++ b/Polyhedron/demo/Polyhedron/Plugins/Mesh_3/C3t3_io_plugin.cpp @@ -75,7 +75,7 @@ Polyhedron_demo_c3t3_binary_io_plugin::load( return QList(); } Scene_c3t3_item* item = new Scene_c3t3_item(); - + if(fileinfo.size() == 0) { CGAL::Three::Three::warning( tr("The file you are trying to load is empty.")); @@ -322,10 +322,10 @@ operator>>( std::istream& is, Fake_CDT_3_vertex_base& v) } else { // if(s != '.') { - // std::cerr << "v.point()=" << v.point() << std::endl; - // std::cerr << "s=" << s << " (" << (int)s - // << "), just before position " - // << is.tellg() << " !\n"; + // std::cerr << "v.point()=" << v.point() << std::endl; + // std::cerr << "s=" << s << " (" << (int)s + // << "), just before position " + // << is.tellg() << " !\n"; // } CGAL_assertion(s == '.' || s== 'F'); v.steiner = false; @@ -385,7 +385,7 @@ operator>>( std::istream& is, Fake_CDT_3_cell_base& c) { std::cerr << "\n"; std::cerr << "s=" << s << " (" << (int)s << "), just before position " - << is.tellg() << " !\n"; } + << is.tellg() << " !\n"; } CGAL_assertion(s == '.'); c._restoring[c.to_edge_index(li, lj)] = false; } @@ -487,7 +487,7 @@ try_load_a_cdt_3(std::istream& is, C3t3& c3t3) } if (s != "CGAL" || !(is >> s) || - s != "c3t3") + s != "c3t3") { return false; } diff --git a/Polyhedron/demo/Polyhedron/Scene_c3t3_item.cpp b/Polyhedron/demo/Polyhedron/Scene_c3t3_item.cpp index 39745ddeb8b..8d86cd539ef 100644 --- a/Polyhedron/demo/Polyhedron/Scene_c3t3_item.cpp +++ b/Polyhedron/demo/Polyhedron/Scene_c3t3_item.cpp @@ -79,7 +79,7 @@ public : delete alphaSlider; } void compute_bbox() const Q_DECL_OVERRIDE{} - + void gl_initialization(Vi* viewer) { if(!isInit(viewer)) @@ -113,7 +113,7 @@ public : { getTriangleContainer(0)->reset_vbos(ALL); getEdgeContainer(0)->reset_vbos(ALL); - + getTriangleContainer(0)->allocate(Tc::Flat_vertices, vertices->data(), static_cast(vertices->size()*sizeof(float))); getTriangleContainer(0)->allocate(Tc::Flat_normals, normals->data(), @@ -139,7 +139,7 @@ public : getEdgeContainer(0)->setFlatDataSize(edges->size()); } } - + //Displays the item void draw(CGAL::Three::Viewer_interface* viewer) const Q_DECL_OVERRIDE { @@ -173,7 +173,7 @@ public : getEdgeContainer(0)->setPlane(cp); getEdgeContainer(0)->setColor(QColor(Qt::black)); getEdgeContainer(0)->draw(viewer, true); - + } void setFast(bool b) @@ -238,10 +238,10 @@ public : QMenu* contextMenu() Q_DECL_OVERRIDE { QMenu* menu = Scene_item::contextMenu(); - + const char* prop_name = "Menu modified by Scene_surface_mesh_item."; bool menuChanged = menu->property(prop_name).toBool(); - + if(!menuChanged) { menu->addSeparator(); QMenu *container = new QMenu(tr("Alpha value")); @@ -253,7 +253,7 @@ public : setAlpha(alphaSlider->value()); redraw(); }); - + container->addAction(sliderAction); menu->addMenu(container); setProperty("menu_changed", true); @@ -265,10 +265,10 @@ public : { return m_alpha ; } - + void setAlpha(int a) Q_DECL_OVERRIDE { - m_alpha = a / 255.0f; + m_alpha = a / 255.0f; redraw(); } private: @@ -541,14 +541,14 @@ void Scene_c3t3_item::common_constructor(bool is_surface) c3t3_changed(); setRenderingMode(FlatPlusEdges); create_flat_and_wire_sphere(1.0f,d->s_vertex,d->s_normals, d->ws_vertex); - + d->is_surface = is_surface; d->is_grid_shown = !is_surface; d->show_tetrahedra = !is_surface; d->last_intersection = !d->show_tetrahedra; - + setTriangleContainer(C3t3_faces, new Tc(Vi::PROGRAM_C3T3, false)); - + setEdgeContainer(CNC, new Ec(Vi::PROGRAM_NO_SELECTION, false)); setEdgeContainer(Grid_edges, new Ec(Vi::PROGRAM_NO_SELECTION, false)); setEdgeContainer(C3t3_edges, new Ec(Vi::PROGRAM_C3T3_EDGES, false)); @@ -569,7 +569,7 @@ Scene_c3t3_item::Scene_c3t3_item(const C3t3& c3t3, bool is_surface) : Scene_group_item("unnamed") , d(new Scene_c3t3_item_priv(c3t3, this)) { - d->reset_cut_plane(); + d->reset_cut_plane(); common_constructor(is_surface); } @@ -968,7 +968,7 @@ void Scene_c3t3_item::draw(CGAL::Three::Viewer_interface* viewer) const { d->intersection->setFast(false); else d->intersection->setFast(true); - + if(!d->frame->isManipulated() && !d->areInterBufFilled(viewer)) { //initGL @@ -984,7 +984,7 @@ void Scene_c3t3_item::draw(CGAL::Three::Viewer_interface* viewer) const { } if(d->is_grid_shown) { - //viewer->makeCurrent(); //messes with the depthPeeling + //viewer->makeCurrent(); //messes with the depthPeeling getEdgeContainer(Grid_edges)->setColor(QColor(Qt::black)); QMatrix4x4 f_mat; for (int i = 0; i<16; i++) @@ -1029,13 +1029,13 @@ void Scene_c3t3_item::drawEdges(CGAL::Three::Viewer_interface* viewer) const { getEdgeContainer(Grid_edges)->setFrameMatrix(f_mat); getEdgeContainer(Grid_edges)->draw(viewer, true); } - + QVector4D cp = cgal_plane_to_vector4d(this->plane()); getEdgeContainer(C3t3_edges)->setPlane(cp); getEdgeContainer(C3t3_edges)->setIsSurface(d->is_surface); getEdgeContainer(C3t3_edges)->setColor(QColor(Qt::black)); getEdgeContainer(C3t3_edges)->draw(viewer, true); - + if(d->show_tetrahedra){ if(!d->frame->isManipulated()) d->intersection->setFast(false); @@ -1078,14 +1078,14 @@ void Scene_c3t3_item::drawPoints(CGAL::Three::Viewer_interface * viewer) const computeElements(); initializeBuffers(viewer); } - - + + QVector4D cp = cgal_plane_to_vector4d(this->plane()); getPointContainer(C3t3_points)->setPlane(cp); getPointContainer(C3t3_points)->setIsSurface(d->is_surface); getPointContainer(C3t3_points)->setColor(this->color()); getPointContainer(C3t3_points)->draw(viewer, true); - + if(d->is_grid_shown) { getEdgeContainer(Grid_edges)->setColor(QColor(Qt::black)); @@ -1175,7 +1175,7 @@ QMenu* Scene_c3t3_item::contextMenu() bool menuChanged = menu->property(prop_name).toBool(); if (!menuChanged) { - + QMenu *container = new QMenu(tr("Alpha value")); container->menuAction()->setProperty("is_groupable", true); QWidgetAction *sliderAction = new QWidgetAction(0); @@ -1190,7 +1190,7 @@ QMenu* Scene_c3t3_item::contextMenu() ); container->addAction(sliderAction); menu->addMenu(container); - + container = new QMenu(tr("Tetrahedra's Shrink Factor")); sliderAction = new QWidgetAction(0); connect(d->tet_Slider, &QSlider::valueChanged, this, &Scene_c3t3_item::itemChanged); @@ -1234,7 +1234,7 @@ QMenu* Scene_c3t3_item::contextMenu() connect(actionShowGrid, SIGNAL(toggled(bool)), this, SLOT(show_grid(bool))); - + menu->setProperty(prop_name, true); } return menu; @@ -1248,8 +1248,8 @@ void Scene_c3t3_item_priv::initializeBuffers(CGAL::Three::Viewer_interface *view item->getTriangleContainer(Scene_c3t3_item::C3t3_faces)->initializeBuffers(viewer); item->getTriangleContainer(Scene_c3t3_item::C3t3_faces)->setFlatDataSize( positions_poly_size); - - + + positions_poly.clear(); positions_poly.shrink_to_fit(); normals.clear(); @@ -1271,7 +1271,7 @@ void Scene_c3t3_item_priv::initializeBuffers(CGAL::Three::Viewer_interface *view item->getPointContainer(Scene_c3t3_item::C3t3_points)->initializeBuffers(viewer); item->getPointContainer(Scene_c3t3_item::C3t3_points)->setFlatDataSize( positions_lines_size); - + positions_lines.clear(); positions_lines.shrink_to_fit(); } @@ -1341,7 +1341,7 @@ void Scene_c3t3_item_priv::computeIntersections(CGAL::Three::Viewer_interface* v positions_barycenter.clear(); const Geom_traits::Plane_3& plane = item->plane(offset); tree.all_intersected_primitives(plane, - boost::make_function_output_iterator(ComputeIntersection(*this))); + boost::make_function_output_iterator(ComputeIntersection(*this))); intersection->gl_initialization(viewer); } @@ -1401,13 +1401,13 @@ void Scene_c3t3_item_priv::computeSpheres() tr_vertices.push_back(*vit); spheres->add_sphere(Geom_traits::Sphere_3(center, radius),s_id++, CGAL::Color(UC(c.red()), UC(c.green()), UC(c.blue()))); - + } spheres->invalidateOpenGLBuffers(); } void Scene_c3t3_item_priv::computeElements() -{ +{ if(!alphaSlider) { alphaSlider = new QSlider(::Qt::Horizontal); @@ -1577,7 +1577,7 @@ void Scene_c3t3_item::show_spheres(bool b) QString msg = QString("Vertex's index : %1; Vertex's in dimension: %2.").arg(d->tr_vertices[id].index()).arg(d->tr_vertices[id].in_dimension()); CGAL::Three::Three::information(msg); CGAL::Three::Three::mainViewer()->displayMessage(msg, 5000); - + }); d->spheres->setName("Protecting spheres"); d->spheres->setRenderingMode(Gouraud); @@ -1959,7 +1959,7 @@ void Scene_c3t3_item::invalidateOpenGLBuffers() getEdgeContainer(CNC)->reset_vbos(ALL); getEdgeContainer(Grid_edges)->reset_vbos(ALL); getPointContainer(C3t3_points)->reset_vbos(ALL); - + Q_FOREACH(CGAL::QGLViewer* v, CGAL::QGLViewer::QGLViewerPool()) { CGAL::Three::Viewer_interface* viewer = static_cast(v); @@ -2038,52 +2038,52 @@ void Scene_c3t3_item::computeElements()const { QApplication::setOverrideCursor(Qt::WaitCursor); const_cast(this)->d->computeElements(); - + getTriangleContainer(C3t3_faces)->allocate( Tc::Flat_vertices, d->positions_poly.data(), static_cast(d->positions_poly.size()*sizeof(float))); - + getTriangleContainer(C3t3_faces)->allocate( Tc::Flat_normals, d->normals.data(), static_cast(d->normals.size()*sizeof(float))); - - + + getTriangleContainer(C3t3_faces)->allocate( Tc::FColors, d->f_colors.data(), static_cast(d->f_colors.size()*sizeof(float))); - + getTriangleContainer(C3t3_faces)->allocate( Tc::Facet_centers, d->positions_barycenter.data(), static_cast(d->positions_barycenter.size()*sizeof(float))); - + d->positions_poly_size = d->positions_poly.size(); - + getEdgeContainer(C3t3_edges)->allocate( Ec::Vertices, d->positions_lines.data(), static_cast(d->positions_lines.size()*sizeof(float))); d->positions_lines_size = d->positions_lines.size(); - + getEdgeContainer(CNC)->allocate( Ec::Vertices, d->positions_lines_not_in_complex.data(), static_cast(d->positions_lines_not_in_complex.size()*sizeof(float))); - + d->positions_lines_not_in_complex_size = d->positions_lines_not_in_complex.size(); - + getEdgeContainer(Grid_edges)->allocate( Ec::Vertices, d->positions_grid.data(), static_cast(d->positions_grid.size()*sizeof(float))); - + getPointContainer(C3t3_points)->allocate( Pc::Vertices, d->positions_lines.data(), static_cast(d->positions_lines.size()*sizeof(float))); - + setBuffersFilled(true); QApplication::restoreOverrideCursor(); } diff --git a/Tetrahedral_remeshing/doc/Tetrahedral_remeshing/Concepts/RemeshingTriangulationTraits_3.h b/Tetrahedral_remeshing/doc/Tetrahedral_remeshing/Concepts/RemeshingTriangulationTraits_3.h index 26667f9b3a4..48cfd4c4db2 100644 --- a/Tetrahedral_remeshing/doc/Tetrahedral_remeshing/Concepts/RemeshingTriangulationTraits_3.h +++ b/Tetrahedral_remeshing/doc/Tetrahedral_remeshing/Concepts/RemeshingTriangulationTraits_3.h @@ -123,7 +123,7 @@ Construct_translated_point_3 construct_translated_point_3_object(); /*! */ -Construct_midpoint_3 construct_midpoint_3_object(); +Construct_midpoint_3 construct_midpoint_3_object(); /*! */ diff --git a/Tetrahedral_remeshing/examples/Tetrahedral_remeshing/CMakeLists.txt b/Tetrahedral_remeshing/examples/Tetrahedral_remeshing/CMakeLists.txt index 855e5acbde1..fa76c657294 100644 --- a/Tetrahedral_remeshing/examples/Tetrahedral_remeshing/CMakeLists.txt +++ b/Tetrahedral_remeshing/examples/Tetrahedral_remeshing/CMakeLists.txt @@ -9,14 +9,14 @@ project( Tetrahedral_remeshing_Examples ) find_package( CGAL REQUIRED ) if ( NOT CGAL_FOUND ) message(STATUS "This project requires the CGAL library, and will not be compiled.") - return() + return() endif() # Boost and its components find_package( Boost REQUIRED ) if ( NOT Boost_FOUND ) message(STATUS "This project requires the Boost library, and will not be compiled.") - return() + return() endif() diff --git a/Tetrahedral_remeshing/examples/Tetrahedral_remeshing/tetrahedral_remeshing_with_features.cpp b/Tetrahedral_remeshing/examples/Tetrahedral_remeshing/tetrahedral_remeshing_with_features.cpp index c65bc72e6d4..2d8a4fe4a44 100644 --- a/Tetrahedral_remeshing/examples/Tetrahedral_remeshing/tetrahedral_remeshing_with_features.cpp +++ b/Tetrahedral_remeshing/examples/Tetrahedral_remeshing/tetrahedral_remeshing_with_features.cpp @@ -92,7 +92,7 @@ void generate_input(const std::size_t& n, Vertex_handle v2 = tr.insert(Point( 2., -2., -2.)); Vertex_handle v3 = tr.insert(Point( 2., -2., 2.)); - + Vertex_handle v4 = tr.insert(Point(-2., 2., -2.)); Vertex_handle v5 = tr.insert(Point(-2., 2., 2.)); diff --git a/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/Remeshing_triangulation_3.h b/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/Remeshing_triangulation_3.h index 4c652798659..83cbbd8880f 100644 --- a/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/Remeshing_triangulation_3.h +++ b/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/Remeshing_triangulation_3.h @@ -33,12 +33,12 @@ namespace Tetrahedral_remeshing { /*! \ingroup PkgTetrahedralRemeshingClasses - + The class `Remeshing_triangulation_3` is a class template which provides a valid triangulation type that can be used as the 3D triangulation input for the tetrahedral remeshing process. - + \tparam Gt is the geometric traits class. It has to be a model of the concept `RemeshingTriangulationTraits_3`. @@ -55,7 +55,7 @@ namespace Tetrahedral_remeshing It has the default value `Triangulation_vertex_base_3`. \cgalRefines `Triangulation_3` - + */ template void build_remeshing_triangulation(const T3& tr, diff --git a/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/Remeshing_vertex_base.h b/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/Remeshing_vertex_base.h index a44f9ad7a0b..aa5dc250979 100644 --- a/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/Remeshing_vertex_base.h +++ b/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/Remeshing_vertex_base.h @@ -31,7 +31,7 @@ namespace Tetrahedral_remeshing /*! \ingroup PkgTetrahedralRemeshingClasses - + The class `Remeshing_vertex_base` is a model of the concept `MeshVertexBase_3`. It is designed to serve as vertex base class for the 3D triangulation used in the tetrahedral remeshing process. @@ -42,9 +42,9 @@ namespace Tetrahedral_remeshing \tparam Vb is a vertex base class from which `Remeshing_vertex_base` derives. It must be a model of the `TriangulationVertexBase_3` concept. It has the default value `Triangulation_vertex_base_3`. - + \cgalModels `MeshVertexBase_3` - \cgalRefines `Triangulation_vertex_base_3` + \cgalRefines `Triangulation_vertex_base_3` */ template 0) { std::cout << "Up sampling MLS " << upsample << std::endl; diff --git a/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/collapse_short_edges.h b/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/collapse_short_edges.h index 772632cc1df..4742352dcac 100644 --- a/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/collapse_short_edges.h +++ b/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/collapse_short_edges.h @@ -1076,7 +1076,7 @@ namespace internal } Vertex_handle vh = collapse_edge(edge, c3t3, sq_high, - protect_boundaries, cell_selector, + protect_boundaries, cell_selector, visitor); if (vh != Vertex_handle()) { diff --git a/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/compute_c3t3_statistics.h b/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/compute_c3t3_statistics.h index 3af1fdae96d..70724a49097 100644 --- a/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/compute_c3t3_statistics.h +++ b/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/compute_c3t3_statistics.h @@ -49,7 +49,7 @@ namespace internal double min_edges_length = (std::numeric_limits::max)(); double max_edges_length = 0.; - + double smallest_edge_radius = (std::numeric_limits::max)(); double smallest_radius_radius = (std::numeric_limits::max)(); double biggest_v_sma_cube = 0.; @@ -197,7 +197,7 @@ namespace internal ofs << std::endl; ofs << "Min dihedral angle : " << min_dihedral_angle << std::endl; ofs << "Max dihedral angle : " << max_dihedral_angle << std::endl; - ofs << std::endl; + ofs << std::endl; ofs << "Shortest edge : " << min_edges_length << std::endl; ofs << "Longest edge : " << max_edges_length << std::endl; ofs << "Average edge length : " << mean_edges_length << std::endl; diff --git a/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/flip_edges.h b/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/flip_edges.h index 9edc8827182..05d52dbb768 100644 --- a/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/flip_edges.h +++ b/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/flip_edges.h @@ -384,7 +384,7 @@ namespace internal // std::cout << "find_best_flip_to_improve_dh boundary " << std::endl; Tr& tr = c3t3.triangulation(); - + Vertex_handle vh0 = edge.first->vertex(edge.second); Vertex_handle vh1 = edge.first->vertex(edge.third); diff --git a/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/split_long_edges.h b/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/split_long_edges.h index 5e68780b311..6eea09b01f9 100644 --- a/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/split_long_edges.h +++ b/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/split_long_edges.h @@ -121,7 +121,7 @@ namespace internal // facet opposite to new_v (status wrt c3t3 is unchanged) new_cell->set_surface_patch_index(new_cell->index(new_v), mfi.first->surface_patch_index(mfi.second)); - + // new half-facet (added or not to c3t3 depending on the stored surface patch index) if (Surface_patch_index() == v_and_opp_patch.second) new_cell->set_surface_patch_index(new_cell->index(v_and_opp_patch.first), diff --git a/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/tetrahedral_adaptive_remeshing_impl.h b/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/tetrahedral_adaptive_remeshing_impl.h index 639c68f2c44..a73901b8a8b 100644 --- a/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/tetrahedral_adaptive_remeshing_impl.h +++ b/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/tetrahedral_adaptive_remeshing_impl.h @@ -483,7 +483,7 @@ private: return true; } - + public: Tr& tr() { diff --git a/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/tetrahedral_remeshing_helpers.h b/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/tetrahedral_remeshing_helpers.h index fba2a3a8747..a562f1f96d0 100644 --- a/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/tetrahedral_remeshing_helpers.h +++ b/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/tetrahedral_remeshing_helpers.h @@ -53,7 +53,7 @@ namespace Tetrahedral_remeshing return vec(point(wp)); } - + const int indices_table[4][3] = { { 3, 1, 2 }, { 3, 2, 0 }, { 3, 0, 1 }, @@ -355,7 +355,7 @@ namespace Tetrahedral_remeshing *oit++ = c3t3.surface_patch_index(f); } while (++circ != end); - + return oit; } diff --git a/Tetrahedral_remeshing/include/CGAL/tetrahedral_remeshing.h b/Tetrahedral_remeshing/include/CGAL/tetrahedral_remeshing.h index bb598fd28a1..cd5324823f5 100644 --- a/Tetrahedral_remeshing/include/CGAL/tetrahedral_remeshing.h +++ b/Tetrahedral_remeshing/include/CGAL/tetrahedral_remeshing.h @@ -118,7 +118,7 @@ namespace CGAL {return target_edge_length;}, np); } - + template void tetrahedral_adaptive_remeshing( @@ -246,7 +246,7 @@ namespace CGAL /////// MESH_COMPLEX_3_IN_TRIANGULATION_3 ///////// /////////////////////////////////////////////////// - template void tetrahedral_adaptive_remeshing( From b3c44b837accddaa68542901f4dc48b0343b53ed Mon Sep 17 00:00:00 2001 From: Jane Tournois Date: Fri, 10 Apr 2020 09:03:47 +0200 Subject: [PATCH 231/568] replace all malloc/free code with std::vector's and remove unused code --- .../Tetrahedral_remeshing/internal/FMLS.h | 168 ++++-------------- 1 file changed, 35 insertions(+), 133 deletions(-) diff --git a/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/FMLS.h b/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/FMLS.h index 9b5fd39a323..0f8d0346280 100644 --- a/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/FMLS.h +++ b/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/FMLS.h @@ -25,7 +25,6 @@ #include #include -#include #include #include @@ -40,18 +39,6 @@ namespace CGAL { namespace internal { - // -------------------------------------------------------------- - // CPU Memory Code - // -------------------------------------------------------------- - - template - void freeCPUResource(T** res) { - if (*res != NULL) { - free(*res); - *res = NULL; - } - } - // -------------------------------------------------------------- // MLS Projection // -------------------------------------------------------------- @@ -65,7 +52,7 @@ namespace CGAL return 0.0; } - inline void setPNSample(float* p, unsigned int i, + inline void setPNSample(std::vector& p, unsigned int i, float x, float y, float z, float nx, float ny, float nz) { @@ -146,7 +133,6 @@ namespace CGAL // be copied if modified outside the class. FMLS() { - PN = NULL; PNSize = 0; PNScale = 1.0f; MLSRadius = 0.1f; @@ -155,57 +141,19 @@ namespace CGAL hermite = false; numIter = 1; } - ~FMLS() - { - freeCPUMemory(); - } // -------------------------------------------------------------- // Main Interface // -------------------------------------------------------------- - float* createPN(unsigned int size) + std::vector createPN(unsigned int size) { - return (float*)malloc(size * SURFEL_SIZE); + return std::vector(size * SURFEL_SIZE); } - float* clonePN() - { - float* clone = createPN(PNSize); - memcpy(clone, PN, PNSize * SURFEL_SIZE); - return clone; - } - - void loadPN(const char* filename) - { - freeCPUMemory(); - FILE* file = fopen(filename, "r"); - if (!file) - throw Exception("Cannot read file" + std::string(filename)); - fseek(file, 0, SEEK_END); - unsigned int numOfByte = ftell(file); - fseek(file, 0, SEEK_SET); - PNSize = numOfByte / SURFEL_SIZE; - PN = createPN(PNSize); - fread(PN, SURFEL_SIZE, PNSize, file); - fclose(file); - - computePNScale(); - grid.clear(); - grid.init(PN, PNSize, MLSRadius * PNScale); - } - - void setPN(float* newPN, unsigned int newPNSize) - { - freeCPUMemory(); - PN = newPN; - PNSize = newPNSize; - computePNScale(); - grid.clear(); - grid.init(PN, PNSize, MLSRadius * PNScale); - } - - void setPN(float* newPN, unsigned int newPNSize, float pointSpacing) + void setPN(const std::vector& newPN, + const unsigned int newPNSize, + const float pointSpacing) { freeCPUMemory(); PN = newPN; @@ -216,15 +164,6 @@ namespace CGAL grid.init(PN, PNSize, MLSRadius * PNScale); } - static void savePN(float* pn, unsigned int size, const char* filename) - { - FILE* file = fopen(filename, "w"); - if (!file) - throw Exception("Cannot write to file" + std::string(filename)); - fwrite(pn, SURFEL_SIZE, size, file); - fclose(file); - } - // Compute, according to the current point sampling stored in FMLS, the MLS projection // of p and store the resulting position in q and normal in n. void fastProjectionCPU(const Vector_3& p, Vector_3& q, Vector_3& n) const @@ -286,12 +225,9 @@ namespace CGAL // The strid indicates the offsets in qv (the defautl value of 3 means that the qv // is compact: pv={x0,y0,z0,x1,y1,z1...}. If pv contains also normals for instance, // the stride should be set to 6. - void fastProjectionCPU(const float* pv, unsigned int pvSize, - float* qv, unsigned int stride = 3) const + void fastProjectionCPU(const std::vector& pv, unsigned int pvSize, + std::vector& qv, unsigned int stride = 3) const { -#ifdef _OPENMP -#pragma omp parallel for -#endif for (int i = 0; i < int(pvSize); i++) { Vector_3 p(pv[stride * i], pv[stride * i + 1], pv[stride * i + 2]); Vector_3 q, n; @@ -329,12 +265,11 @@ namespace CGAL } // Brute force version. O(pvSize*PNSize) complexity. For comparison only. - void projectionCPU(const float* pv, unsigned int pvSize, - float* qv, unsigned int stride = 3) + void projectionCPU(const std::vector& pv, + unsigned int pvSize, + std::vector& qv, + unsigned int stride = 3) { -#ifdef _OPENMP -#pragma omp parallel for -#endif for (int i = 0; i < int(pvSize); i++) { Vector_3 p(pv[stride * i], pv[stride * i + 1], pv[stride * i + 2]); Vector_3 q, n; @@ -348,31 +283,14 @@ namespace CGAL } } - - // -------------------------------------------------------------------- - // Filtering by applying MLS projection on the input point set itself. - // -------------------------------------------------------------------- - // The 'filter*_*' methods apply the MLS projection to the PN samples themselves, - // providing a low pass (or feature preserving, dependeing on the options) - // version which can be gathered using 'getFilteredPN ()' afterwards. - void fastFilterCPU(float* fPN) - { - fastProjectionCPU(PN, PNSize, fPN, 6); - } - - void filterCPU(float* fPN) // Brute force method. O(PNSize^2) complexity. For comparison only. - { - projectionCPU(PN, PNSize, fPN, 6); - } - // -------------------------------------------------------------- // Accessors // -------------------------------------------------------------- // Number of elements of the PN. One elemnt is a 6-float32 chunk. inline unsigned int getPNSize() const { return PNSize; } - inline float* getPN() { return PN; } - inline const float* getPN() const { return PN; } + inline std::vector& getPN() { return PN; } + inline const std::vector& getPN() const { return PN; } // Min/Max corners of PN's bounding volume inline const float* getMinMax() const { return grid.getMinMax(); } @@ -401,15 +319,6 @@ namespace CGAL // Size of a point sample in bytes (6xfloat32: 3 for position and normal static const unsigned int SURFEL_SIZE = 24; - class Exception { - private: - std::string msg; - public: - inline Exception(const std::string& msg) : msg(msg) {} - virtual ~Exception() {} - inline const std::string getMessage() const { return std::string("[FMLS][Error]: ") + msg; } - }; - private: void computePNScale() @@ -440,16 +349,14 @@ namespace CGAL { cellSize = 1.f; LUTSize = 0; - LUT = NULL; indicesSize = 0; - indices = NULL; } ~Grid() { clear(); } - void init(float* PN, unsigned int PNSize, float sigma_s) + void init(const std::vector& PN, unsigned int PNSize, float sigma_s) { cellSize = sigma_s; for (unsigned int i = 0; i < 3; i++) { @@ -470,9 +377,9 @@ namespace CGAL for (unsigned int i = 0; i < 3; i++) res[i] = (unsigned int)ceil((minMax[3 + i] - minMax[i]) / cellSize); LUTSize = res[0] * res[1] * res[2]; - unsigned int gridLUTNumOfByte = LUTSize * sizeof(unsigned int); - LUT = (unsigned int*)malloc(gridLUTNumOfByte); - memset(LUT, 0, gridLUTNumOfByte); + LUT.resize(LUTSize); + LUT.assign(LUTSize, 0); + unsigned int nonEmptyCells = 0; Vector_3 gMin(minMax[0], minMax[1], minMax[2]); Vector_3 gMax(minMax[3], minMax[4], minMax[5]); @@ -483,7 +390,9 @@ namespace CGAL LUT[index]++; } indicesSize = PNSize + nonEmptyCells; - indices = (unsigned int*)malloc(indicesSize * sizeof(unsigned int)); + indices.reserve(indicesSize); + indices.assign(indicesSize, 0); + unsigned int cpt = 0; for (unsigned int i = 0; i < res[0]; i++) for (unsigned int j = 0; j < res[1]; j++) @@ -513,24 +422,18 @@ namespace CGAL void clear() { - if (LUT != NULL) - free(LUT); - if (indices != NULL) - free(indices); cellSize = 1.f; LUTSize = 0; - LUT = NULL; indicesSize = 0; - indices = NULL; } // Accessors - inline const float* getMinMax() const { return minMax; } - inline const unsigned int* getRes() const { return res; } + inline const std::array getMinMax() const { return minMax; } + inline const std::array getRes() const { return res; } inline float getCellSize() const { return cellSize; } - inline unsigned int* getLUT() { return LUT; } - inline const unsigned int* getLUT() const { return LUT; } + inline std::vector& getLUT() { return LUT; } + inline const std::vector& getLUT() const { return LUT; } inline unsigned int getLUTSize() const { return LUTSize; } inline unsigned int getLUTIndex(unsigned int i, unsigned int j, @@ -563,8 +466,8 @@ namespace CGAL inline unsigned int getLUTElement(const Vector_3& x) const { return LUT[getLUTIndex(x)]; } - inline unsigned int* getIndices() { return indices; } - inline const unsigned int* getIndices() const { return indices; } + inline std::vector& getIndices() { return indices; } + inline const std::vector& getIndices() const { return indices; } inline unsigned int getIndicesSize() const { return indicesSize; } inline unsigned int getCellIndicesSize(unsigned int i, unsigned int j, @@ -579,13 +482,13 @@ namespace CGAL } private: - float minMax[6]; + std::array minMax; float cellSize; - unsigned int res[3]; + std::array res; unsigned int LUTSize; - unsigned int* LUT; // 3D Index Look-Up Table + std::vector LUT; // 3D Index Look-Up Table unsigned int indicesSize; - unsigned int* indices; // 3D Grid data + std::vector indices; // 3D Grid data }; @@ -595,8 +498,7 @@ namespace CGAL void freeCPUMemory() { - if (PN != NULL) - freeCPUResource(&PN); + PN.clear(); PNSize = 0; } @@ -604,7 +506,7 @@ namespace CGAL // CPU Data // -------------------------------------------------------------- - float* PN; + std::vector PN; unsigned int PNSize; float PNScale; // size of the bounding sphere radius float MLSRadius; @@ -681,7 +583,7 @@ namespace CGAL } } - std::vector< float* > pns; + std::vector< std::vector > pns; int count = 0; //Memory allocation for the point plus normals of the point samples @@ -689,7 +591,7 @@ namespace CGAL it != subdomain_sample_numbers.end(); ++it) { current_subdomain_FMLS_indices[it->first] = count; - pns.push_back(new float[it->second * 6]); + pns.push_back(std::vector(it->second * 6, 0)); count++; } From 81541b29814d19232c82deb5586ebf41575c0b50 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9bastien=20Loriot?= Date: Fri, 10 Apr 2020 09:37:58 +0200 Subject: [PATCH 232/568] fix warnings + compilation error --- .../Tetrahedral_remeshing/CMakeLists.txt | 6 +- .../internal/smooth_vertices.h | 2 +- .../internal/tetrahedral_remeshing_helpers.h | 64 +++++++++---------- 3 files changed, 36 insertions(+), 36 deletions(-) diff --git a/Tetrahedral_remeshing/examples/Tetrahedral_remeshing/CMakeLists.txt b/Tetrahedral_remeshing/examples/Tetrahedral_remeshing/CMakeLists.txt index fa76c657294..ecc37356c72 100644 --- a/Tetrahedral_remeshing/examples/Tetrahedral_remeshing/CMakeLists.txt +++ b/Tetrahedral_remeshing/examples/Tetrahedral_remeshing/CMakeLists.txt @@ -22,6 +22,6 @@ endif() # Creating entries for all C++ files with "main" routine # ########################################################## - create_single_source_cgal_program( "tetrahedral_remeshing_example.cpp" ) - create_single_source_cgal_program( "tetrahedral_remeshing_with_features.cpp") - create_single_source_cgal_program( "tetrahedral_remeshing_of_one_subdomain.cpp") +create_single_source_cgal_program( "tetrahedral_remeshing_example.cpp" ) +create_single_source_cgal_program( "tetrahedral_remeshing_with_features.cpp") +create_single_source_cgal_program( "tetrahedral_remeshing_of_one_subdomain.cpp") diff --git a/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/smooth_vertices.h b/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/smooth_vertices.h index b8bd1ac4a01..5b0f6b4c90b 100644 --- a/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/smooth_vertices.h +++ b/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/smooth_vertices.h @@ -325,7 +325,7 @@ namespace CGAL void check_inversion_and_move(const typename Tr::Vertex_handle v, const typename Tr::Point& final_pos, const CellRange& inc_cells, - const Tr& tr) + const Tr& /* tr */) { const typename Tr::Point backup = v->point(); //backup v's position const typename Tr::Geom_traits::Point_3 pv = point(backup); diff --git a/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/tetrahedral_remeshing_helpers.h b/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/tetrahedral_remeshing_helpers.h index a562f1f96d0..0261ea88d10 100644 --- a/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/tetrahedral_remeshing_helpers.h +++ b/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/tetrahedral_remeshing_helpers.h @@ -853,38 +853,6 @@ namespace Tetrahedral_remeshing template void dump_cells(const CellRange& cells, const char* filename); - template - bool are_cell_orientations_valid(const Tr& tr) - { - typedef typename Tr::Geom_traits::Point_3 Point_3; - typedef typename Tr::Facet Facet; - - std::set facets; - for (const typename Tr::Cell_handle ch : tr.finite_cell_handles()) - { - const Point_3& p0 = point(ch->vertex(0)->point()); - const Point_3& p1 = point(ch->vertex(1)->point()); - const Point_3& p2 = point(ch->vertex(2)->point()); - const Point_3& p3 = point(ch->vertex(3)->point()); - - const CGAL::Orientation o = CGAL::orientation(p0, p1, p2, p3); - if (o != CGAL::POSITIVE) - { - facets.insert(canonical_facet(Facet(ch, 0))); - facets.insert(canonical_facet(Facet(ch, 1))); - facets.insert(canonical_facet(Facet(ch, 2))); - facets.insert(canonical_facet(Facet(ch, 3))); - } - } - if (!facets.empty()) - { - std::cerr << "Warning : there are inverted cells!\n" - << "\tSee cells_with_negative_volume.polylines.txt" << std::endl; - dump_facets(facets, "cells_with_negative_volume.polylines.txt"); - } - return facets.empty(); - } - template void dump_edges(const Bimap& edges, const char* filename) { @@ -936,6 +904,38 @@ namespace Tetrahedral_remeshing ofs.close(); } + template + bool are_cell_orientations_valid(const Tr& tr) + { + typedef typename Tr::Geom_traits::Point_3 Point_3; + typedef typename Tr::Facet Facet; + + std::set facets; + for (const typename Tr::Cell_handle ch : tr.finite_cell_handles()) + { + const Point_3& p0 = point(ch->vertex(0)->point()); + const Point_3& p1 = point(ch->vertex(1)->point()); + const Point_3& p2 = point(ch->vertex(2)->point()); + const Point_3& p3 = point(ch->vertex(3)->point()); + + const CGAL::Orientation o = CGAL::orientation(p0, p1, p2, p3); + if (o != CGAL::POSITIVE) + { + facets.insert(canonical_facet(Facet(ch, 0))); + facets.insert(canonical_facet(Facet(ch, 1))); + facets.insert(canonical_facet(Facet(ch, 2))); + facets.insert(canonical_facet(Facet(ch, 3))); + } + } + if (!facets.empty()) + { + std::cerr << "Warning : there are inverted cells!\n" + << "\tSee cells_with_negative_volume.polylines.txt" << std::endl; + dump_facets(facets, "cells_with_negative_volume.polylines.txt"); + } + return facets.empty(); + } + template void dump_surface_off(const Tr& tr, const char* filename) { From 9b4a53326c78e20045b73b1952396e935a388fe2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9bastien=20Loriot?= Date: Fri, 10 Apr 2020 10:01:12 +0200 Subject: [PATCH 233/568] remove extra indentation --- .../Remeshing_cell_base.h | 124 +- .../Remeshing_triangulation_3.h | 246 +- .../Remeshing_vertex_base.h | 74 +- .../CGAL/Tetrahedral_remeshing/Sizing_field.h | 26 +- .../Uniform_sizing_field.h | 38 +- .../Tetrahedral_remeshing/internal/FMLS.h | 1459 +++++----- .../internal/collapse_short_edges.h | 1774 ++++++------ .../internal/compute_c3t3_statistics.h | 340 +-- .../internal/flip_edges.h | 1978 +++++++------- .../internal/smooth_vertices.h | 1212 ++++---- .../internal/split_long_edges.h | 423 +-- .../tetrahedral_adaptive_remeshing_impl.h | 987 +++---- .../internal/tetrahedral_remeshing_helpers.h | 2428 +++++++++-------- 13 files changed, 5558 insertions(+), 5551 deletions(-) diff --git a/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/Remeshing_cell_base.h b/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/Remeshing_cell_base.h index eff663b51dd..7f67a4cb3b2 100644 --- a/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/Remeshing_cell_base.h +++ b/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/Remeshing_cell_base.h @@ -19,15 +19,15 @@ namespace CGAL { namespace Tetrahedral_remeshing { - namespace internal +namespace internal +{ + struct Fake_MD_C { - struct Fake_MD_C - { - typedef int Subdomain_index; - typedef int Surface_patch_index; - typedef int Index; - }; - } + typedef int Subdomain_index; + typedef int Surface_patch_index; + typedef int Index; + }; +} /*! \ingroup PkgTetrahedralRemeshingClasses @@ -46,52 +46,52 @@ It has the default value `Triangulation_cell_base_3`. \cgalModels `MeshCellBase_3` */ - template > - class Remeshing_cell_base +template > +class Remeshing_cell_base #ifndef DOXYGEN_RUNNING - : public CGAL::Mesh_cell_base_3 + : public CGAL::Mesh_cell_base_3 #endif +{ + typedef CGAL::Mesh_cell_base_3 Base; + typedef typename Base::Vertex_handle Vertex_handle; + typedef typename Base::Cell_handle Cell_handle; + +public: + // To get correct cell type in TDS + template < class TDS2 > + struct Rebind_TDS { - typedef CGAL::Mesh_cell_base_3 Base; - typedef typename Base::Vertex_handle Vertex_handle; - typedef typename Base::Cell_handle Cell_handle; + typedef typename Cb::template Rebind_TDS::Other Cb2; + typedef Remeshing_cell_base Other; + }; - public: - // To get correct cell type in TDS - template < class TDS2 > - struct Rebind_TDS - { - typedef typename Cb::template Rebind_TDS::Other Cb2; - typedef Remeshing_cell_base Other; - }; - - using Base::Base; + using Base::Base; #ifndef DOXYGEN_RUNNING - /// TODO : remove this function from here - /// Returns `true` if facet lies on a surface patch - bool is_facet_on_surface(const int facet) const - { - CGAL_precondition(facet >= 0 && facet<4); - return this->subdomain_index() != this->neighbor(facet)->subdomain_index(); - } + /// TODO : remove this function from here + /// Returns `true` if facet lies on a surface patch + bool is_facet_on_surface(const int facet) const + { + CGAL_precondition(facet >= 0 && facet<4); + return this->subdomain_index() != this->neighbor(facet)->subdomain_index(); + } #endif }; - template < class Gt, class Cb > - std::istream& - operator>>(std::istream &is, Remeshing_cell_base &c) - { - typename Remeshing_cell_base::Subdomain_index index; - if (is_ascii(is)) - is >> index; - else - read(is, index); - if (is) { - c.set_subdomain_index(index); +template < class Gt, class Cb > +std::istream& + operator>>(std::istream &is, Remeshing_cell_base &c) +{ + typename Remeshing_cell_base::Subdomain_index index; + if (is_ascii(is)) + is >> index; + else + read(is, index); + if (is) { + c.set_subdomain_index(index); // for (int i = 0; i < 4; ++i) // { // typename Compact_mesh_cell_base_3::Surface_patch_index i2; @@ -103,27 +103,27 @@ It has the default value `Triangulation_cell_base_3`. // } // c.set_surface_patch_index(i, i2); // } - } - return is; } + return is; +} - template < class Gt, class Cb > - std::ostream& - operator<<(std::ostream &os, const Remeshing_cell_base &c) - { - if (is_ascii(os)) - os << c.subdomain_index(); - else - write(os, c.subdomain_index()); - //for (int i = 0; i < 4; ++i) - //{ - // if (is_ascii(os)) - // os << ' ' << oformat(c.surface_patch_index(i)); - // else - // write(os, c.surface_patch_index(i)); - //} - return os; - } +template < class Gt, class Cb > +std::ostream& + operator<<(std::ostream &os, const Remeshing_cell_base &c) +{ + if (is_ascii(os)) + os << c.subdomain_index(); + else + write(os, c.subdomain_index()); + //for (int i = 0; i < 4; ++i) + //{ + // if (is_ascii(os)) + // os << ' ' << oformat(c.surface_patch_index(i)); + // else + // write(os, c.surface_patch_index(i)); + //} + return os; +} }//end namespace Tetrahedral_remeshing diff --git a/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/Remeshing_triangulation_3.h b/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/Remeshing_triangulation_3.h index 83cbbd8880f..2c886cdafbc 100644 --- a/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/Remeshing_triangulation_3.h +++ b/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/Remeshing_triangulation_3.h @@ -31,152 +31,152 @@ namespace CGAL { namespace Tetrahedral_remeshing { - /*! - \ingroup PkgTetrahedralRemeshingClasses +/*! +\ingroup PkgTetrahedralRemeshingClasses - The class `Remeshing_triangulation_3` - is a class template which provides a valid triangulation type - that can be used as the 3D triangulation input for - the tetrahedral remeshing process. +The class `Remeshing_triangulation_3` +is a class template which provides a valid triangulation type +that can be used as the 3D triangulation input for +the tetrahedral remeshing process. - \tparam Gt is the geometric traits class. - It has to be a model of the concept `RemeshingTriangulationTraits_3`. +\tparam Gt is the geometric traits class. +It has to be a model of the concept `RemeshingTriangulationTraits_3`. - \tparam Concurrency_tag enables sequential versus parallel implementation of the - triangulation data structure. - Possible values are `Sequential_tag` (the default) and `Parallel_tag`. +\tparam Concurrency_tag enables sequential versus parallel implementation of the +triangulation data structure. +Possible values are `Sequential_tag` (the default) and `Parallel_tag`. - \tparam Cb is a cell base class from which `Remeshing_cell_base` derives. - It must be a model of the `TriangulationCellBase_3` concept. - It has the default value `Triangulation_cell_base_3`. +\tparam Cb is a cell base class from which `Remeshing_cell_base` derives. +It must be a model of the `TriangulationCellBase_3` concept. +It has the default value `Triangulation_cell_base_3`. - \tparam Vb is a vertex base class from which `Remeshing_vertex_base` derives. - It must be a model of the `TriangulationVertexBase_3` concept. - It has the default value `Triangulation_vertex_base_3`. +\tparam Vb is a vertex base class from which `Remeshing_vertex_base` derives. +It must be a model of the `TriangulationVertexBase_3` concept. +It has the default value `Triangulation_vertex_base_3`. - \cgalRefines `Triangulation_3` +\cgalRefines `Triangulation_3` - */ - template, - typename Vb = CGAL::Triangulation_vertex_base_3 - > - class Remeshing_triangulation_3 - : public CGAL::Triangulation_3, - Remeshing_cell_base - > +*/ +template, + typename Vb = CGAL::Triangulation_vertex_base_3 +> +class Remeshing_triangulation_3 + : public CGAL::Triangulation_3, + Remeshing_cell_base > - { - public: - typedef Remeshing_vertex_base Remeshing_Vb; - typedef Remeshing_cell_base Remeshing_Cb; + > +{ +public: + typedef Remeshing_vertex_base Remeshing_Vb; + typedef Remeshing_cell_base Remeshing_Cb; - typedef CGAL::Triangulation_data_structure_3< - Remeshing_Vb, Remeshing_Cb, Concurrency_tag> Tds; - typedef CGAL::Triangulation_3 Self; - typedef typename Gt::Plane_3 Plane_3; + typedef CGAL::Triangulation_data_structure_3< + Remeshing_Vb, Remeshing_Cb, Concurrency_tag> Tds; + typedef CGAL::Triangulation_3 Self; + typedef typename Gt::Plane_3 Plane_3; +}; + +namespace internal +{ + template + struct Vertex_converter + { + //This operator is used to create the vertex from v_src. + typename TDS_tgt::Vertex operator()(const typename TDS_src::Vertex& v_src) const + { + typedef typename CGAL::Kernel_traits< + typename TDS_src::Vertex::Point>::Kernel GT_src; + typedef typename CGAL::Kernel_traits< + typename TDS_tgt::Vertex::Point>::Kernel GT_tgt; + CGAL::Cartesian_converter conv; + + typedef typename TDS_tgt::Vertex::Point Tgt_point; + + typename TDS_tgt::Vertex v_tgt; + v_tgt.set_point(Tgt_point(conv(point(v_src.point())))); + v_tgt.set_time_stamp(-1); + v_tgt.set_dimension(3);//-1 if unset, 0,1,2, or 3 if set + return v_tgt; + } + //This operator is meant to be used in case heavy data should transferred to v_tgt. + void operator()(const typename TDS_src::Vertex& v_src, + typename TDS_tgt::Vertex& v_tgt) const + { + typedef typename CGAL::Kernel_traits< + typename TDS_src::Vertex::Point>::Kernel GT_src; + typedef typename CGAL::Kernel_traits< + typename TDS_tgt::Vertex::Point>::Kernel GT_tgt; + CGAL::Cartesian_converter conv; + + typedef typename TDS_tgt::Vertex::Point Tgt_point; + + v_tgt.set_point(Tgt_point(conv(point(v_src.point())))); + v_tgt.set_dimension(3);//v_src.info()); + } }; - namespace internal + template + struct Cell_converter { - template - struct Vertex_converter + //This operator is used to create the cell from c_src. + typename TDS_tgt::Cell operator()(const typename TDS_src::Cell& c_src) const { - //This operator is used to create the vertex from v_src. - typename TDS_tgt::Vertex operator()(const typename TDS_src::Vertex& v_src) const - { - typedef typename CGAL::Kernel_traits< - typename TDS_src::Vertex::Point>::Kernel GT_src; - typedef typename CGAL::Kernel_traits< - typename TDS_tgt::Vertex::Point>::Kernel GT_tgt; - CGAL::Cartesian_converter conv; - - typedef typename TDS_tgt::Vertex::Point Tgt_point; - - typename TDS_tgt::Vertex v_tgt; - v_tgt.set_point(Tgt_point(conv(point(v_src.point())))); - v_tgt.set_time_stamp(-1); - v_tgt.set_dimension(3);//-1 if unset, 0,1,2, or 3 if set - return v_tgt; - } - //This operator is meant to be used in case heavy data should transferred to v_tgt. - void operator()(const typename TDS_src::Vertex& v_src, - typename TDS_tgt::Vertex& v_tgt) const - { - typedef typename CGAL::Kernel_traits< - typename TDS_src::Vertex::Point>::Kernel GT_src; - typedef typename CGAL::Kernel_traits< - typename TDS_tgt::Vertex::Point>::Kernel GT_tgt; - CGAL::Cartesian_converter conv; - - typedef typename TDS_tgt::Vertex::Point Tgt_point; - - v_tgt.set_point(Tgt_point(conv(point(v_src.point())))); - v_tgt.set_dimension(3);//v_src.info()); - } - }; - - template - struct Cell_converter - { - //This operator is used to create the cell from c_src. - typename TDS_tgt::Cell operator()(const typename TDS_src::Cell& c_src) const - { - typename TDS_tgt::Cell c_tgt; - c_tgt.set_subdomain_index(1);//c_src.subdomain_index()); + typename TDS_tgt::Cell c_tgt; + c_tgt.set_subdomain_index(1);//c_src.subdomain_index()); // c_tgt.info() = c_src.info(); - c_tgt.set_time_stamp(-1); - return c_tgt; - } - //This operator is meant to be used in case heavy data should transferred to c_tgt. - void operator()(const typename TDS_src::Cell& c_src, - typename TDS_tgt::Cell& c_tgt) const - { + c_tgt.set_time_stamp(-1); + return c_tgt; + } + //This operator is meant to be used in case heavy data should transferred to c_tgt. + void operator()(const typename TDS_src::Cell& c_src, + typename TDS_tgt::Cell& c_tgt) const + { // c_tgt.set_subdomain_index(c_src.subdomain_index()); - // c_tgt.info() = c_src.info(); - } - }; + // c_tgt.info() = c_src.info(); + } + }; - } +} - template - void build_remeshing_triangulation(const T3& tr, - Remeshing_triangulation_3& remeshing_tr) - { - typedef typename T3::Triangulation_data_structure Tds; - typedef typename Remeshing_triangulation_3::Tds RTds; +template +void build_remeshing_triangulation(const T3& tr, + Remeshing_triangulation_3& remeshing_tr) +{ + typedef typename T3::Triangulation_data_structure Tds; + typedef typename Remeshing_triangulation_3::Tds RTds; - remeshing_tr.clear(); + remeshing_tr.clear(); - remeshing_tr.set_infinite_vertex( - remeshing_tr.tds().copy_tds( - tr.tds(), - tr.infinite_vertex(), - internal::Vertex_converter(), - internal::Cell_converter())); - } + remeshing_tr.set_infinite_vertex( + remeshing_tr.tds().copy_tds( + tr.tds(), + tr.infinite_vertex(), + internal::Vertex_converter(), + internal::Cell_converter())); +} - template - void build_from_remeshing_triangulation( - const Remeshing_triangulation_3& remeshing_tr, - T3& tr) - { - typedef typename T3::Triangulation_data_structure Tds; - typedef typename Remeshing_triangulation_3::Tds RTds; +template +void build_from_remeshing_triangulation( + const Remeshing_triangulation_3& remeshing_tr, + T3& tr) +{ + typedef typename T3::Triangulation_data_structure Tds; + typedef typename Remeshing_triangulation_3::Tds RTds; - tr.clear(); + tr.clear(); - tr.set_infinite_vertex( - tr.tds().copy_tds( - remeshing_tr.tds(), - remeshing_tr.infinite_vertex(), - internal::Vertex_converter(), - internal::Cell_converter())); - } + tr.set_infinite_vertex( + tr.tds().copy_tds( + remeshing_tr.tds(), + remeshing_tr.infinite_vertex(), + internal::Vertex_converter(), + internal::Cell_converter())); +} }//end namespace Tetrahedral_remeshing }//end namespace CGAL diff --git a/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/Remeshing_vertex_base.h b/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/Remeshing_vertex_base.h index aa5dc250979..e55f14ba3b4 100644 --- a/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/Remeshing_vertex_base.h +++ b/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/Remeshing_vertex_base.h @@ -19,53 +19,55 @@ namespace CGAL { namespace Tetrahedral_remeshing { - namespace internal - { - struct Fake_MD_V - { - typedef int Subdomain_index; - typedef int Surface_patch_index; - typedef int Index; - }; - } +namespace internal +{ - /*! - \ingroup PkgTetrahedralRemeshingClasses +struct Fake_MD_V +{ + typedef int Subdomain_index; + typedef int Surface_patch_index; + typedef int Index; +}; - The class `Remeshing_vertex_base` is a model of the concept `MeshVertexBase_3`. - It is designed to serve as vertex base class for the 3D triangulation - used in the tetrahedral remeshing process. +} // internal - \tparam Gt is the geometric traits class. - It has to be a model of the concept `RemeshingTriangulationTraits_3`. +/*! +\ingroup PkgTetrahedralRemeshingClasses - \tparam Vb is a vertex base class from which `Remeshing_vertex_base` derives. - It must be a model of the `TriangulationVertexBase_3` concept. - It has the default value `Triangulation_vertex_base_3`. +The class `Remeshing_vertex_base` is a model of the concept `MeshVertexBase_3`. +It is designed to serve as vertex base class for the 3D triangulation +used in the tetrahedral remeshing process. - \cgalModels `MeshVertexBase_3` - \cgalRefines `Triangulation_vertex_base_3` - */ +\tparam Gt is the geometric traits class. +It has to be a model of the concept `RemeshingTriangulationTraits_3`. - template > - class Remeshing_vertex_base +\tparam Vb is a vertex base class from which `Remeshing_vertex_base` derives. +It must be a model of the `TriangulationVertexBase_3` concept. +It has the default value `Triangulation_vertex_base_3`. + +\cgalModels `MeshVertexBase_3` +\cgalRefines `Triangulation_vertex_base_3` +*/ + +template > +class Remeshing_vertex_base #ifndef DOXYGEN_RUNNING - : public CGAL::Mesh_vertex_base_3 + : public CGAL::Mesh_vertex_base_3 #endif - { - typedef CGAL::Mesh_vertex_base_3 Base; - - public: - // To get correct vertex type in TDS - template < class TDS3 > - struct Rebind_TDS { - typedef typename Vb::template Rebind_TDS::Other Vb3; - typedef Remeshing_vertex_base Other; - }; +{ + typedef CGAL::Mesh_vertex_base_3 Base; +public: + // To get correct vertex type in TDS + template < class TDS3 > + struct Rebind_TDS { + typedef typename Vb::template Rebind_TDS::Other Vb3; + typedef Remeshing_vertex_base Other; }; +}; + }//end namespace Tetrahedral_remeshing }//end namespace CGAL diff --git a/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/Sizing_field.h b/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/Sizing_field.h index 8d086ecf120..446992acb3b 100644 --- a/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/Sizing_field.h +++ b/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/Sizing_field.h @@ -15,20 +15,20 @@ namespace CGAL { - /*! - * Sizing field virtual class - */ - template - class Sizing_field - { - public: - typedef Kernel K; - typedef typename Kernel::FT FT; - typedef typename Kernel::Point_3 Point_3; +/*! +* Sizing field virtual class +*/ +template +class Sizing_field +{ +public: + typedef Kernel K; + typedef typename Kernel::FT FT; + typedef typename Kernel::Point_3 Point_3; - public: - virtual FT operator()(const Point_3& p) const = 0; - }; +public: + virtual FT operator()(const Point_3& p) const = 0; +}; }//end namespace CGAL diff --git a/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/Uniform_sizing_field.h b/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/Uniform_sizing_field.h index 2f69d13b081..6c3ae7126b4 100644 --- a/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/Uniform_sizing_field.h +++ b/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/Uniform_sizing_field.h @@ -17,26 +17,26 @@ namespace CGAL { - template - class Uniform_sizing_field : Sizing_field +template +class Uniform_sizing_field : Sizing_field +{ +private: + typedef Sizing_field Base; +public: + typedef typename Base::FT FT; + typedef typename Base::Point_3 Point_3; + + Uniform_sizing_field(const FT& size) + : m_size(size) + {} + + FT operator()(const Point_3&) const { - private: - typedef Sizing_field Base; - public: - typedef typename Base::FT FT; - typedef typename Base::Point_3 Point_3; - - Uniform_sizing_field(const FT& size) - : m_size(size) - {} - - FT operator()(const Point_3&) const - { - return m_size; - } - private: - FT m_size; - }; + return m_size; + } +private: + FT m_size; +}; }//end namespace CGAL diff --git a/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/FMLS.h b/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/FMLS.h index 0f8d0346280..f5c75f3ca00 100644 --- a/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/FMLS.h +++ b/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/FMLS.h @@ -35,767 +35,768 @@ namespace CGAL { - namespace Tetrahedral_remeshing +namespace Tetrahedral_remeshing +{ +namespace internal +{ +// -------------------------------------------------------------- +// MLS Projection +// -------------------------------------------------------------- + +inline float wendland(float x, float h) +{ + x = CGAL::abs(x); + if (x < h) + return CGAL::square(CGAL::square(1 - x / h)) * (4 * x / h + 1); + else + return 0.0; +} + +inline void setPNSample(std::vector& p, unsigned int i, + float x, float y, float z, + float nx, float ny, float nz) +{ + p[6 * i] = x; + p[6 * i + 1] = y; + p[6 * i + 2] = z; + p[6 * i + 3] = nx; + p[6 * i + 4] = ny; + p[6 * i + 5] = nz; +} + +template +inline CGAL::Vector_3 projectOn(const CGAL::Vector_3& x, + const CGAL::Vector_3& N, + const CGAL::Vector_3& P) +{ + typename Gt::Compute_scalar_product_3 scalar_product + = Gt().compute_scalar_product_3_object(); + + typename Gt::FT w = scalar_product((x - P), N); + return x - (N * w); +} + +template +inline typename Gt::FT length(const CGAL::Vector_3& v) +{ + return CGAL::approximate_sqrt(v.squared_length()); +} + +template +inline typename Gt::FT distance(const CGAL::Vector_3& v1, + const CGAL::Vector_3& v2) +{ + CGAL::Vector_3 diff(v1.x() - v2.x(), + v1.y() - v2.y(), + v1.z() - v2.z()); + return length(diff); +} + +template +inline void weightedPointCombination(const CGAL::Vector_3& x, + const CGAL::Vector_3& pi, + const CGAL::Vector_3& ni, + float sigma_s, bool bilateral, float sigma_r, + bool hermite, + CGAL::Vector_3& c, CGAL::Vector_3& nc, float& sumW) +{ + float w = wendland(distance(x, pi), sigma_s); + if (bilateral) + w *= wendland(length(x - projectOn(x, ni, pi)), sigma_r); + if (hermite) + c += w * projectOn(x, ni, pi); + else + c += w * pi; + nc += w * ni; + sumW += w; +} + +template +class FMLS +{ + typedef typename Gt::Vector_3 Vector_3; + typedef typename Gt::FT FT; + +public: + // FMLS provide MLS projection and filtering from a point set. + // The underlying data structure is a simple list of float in the PN format + // A PN object is a list of 6xfloat32 chunk : + // x0,y0,z0,nx0,ny0,nz0,x1,y1,z1,nx1,ny1,nz1,... + // with {xi,yi,zi} the position and {nxi,nyi,nzi} the normal vector of the + // i-th point sample. A PN can be read from and write to file directly + // (identity serialization) and is handled as a simple float32 pointer. + // + // Use the 'fast*' methods. Brute force methods are inserted only for comparison. + // + // Memory policy: a FMLS class manages itself al its belonging objects. + // Therefore, PN and filtered PN lists are the property of this class, and should + // be copied if modified outside the class. + FMLS() { - namespace internal + PNSize = 0; + PNScale = 1.0f; + MLSRadius = 0.1f; + bilateralRange = 0.05f; + bilateral = false; + hermite = false; + numIter = 1; + } + + // -------------------------------------------------------------- + // Main Interface + // -------------------------------------------------------------- + + std::vector createPN(unsigned int size) + { + return std::vector(size * SURFEL_SIZE); + } + + void setPN(const std::vector& newPN, + const unsigned int newPNSize, + const float pointSpacing) + { + freeCPUMemory(); + PN = newPN; + PNSize = newPNSize; + computePNScale(); + MLSRadius = 3 * pointSpacing / PNScale; + grid.clear(); + grid.init(PN, PNSize, MLSRadius * PNScale); + } + + // Compute, according to the current point sampling stored in FMLS, the MLS projection + // of p and store the resulting position in q and normal in n. + void fastProjectionCPU(const Vector_3& p, Vector_3& q, Vector_3& n) const + { + float sigma_s = PNScale * MLSRadius; + float sigma_r = bilateralRange; + + Vector_3 g = (p - Vector_3(grid.getMinMax()[0], grid.getMinMax()[1], grid.getMinMax()[2])) / sigma_s; + std::array gxyz = { g.x(), g.y(), g.z() }; + + for (unsigned int j = 0; j < 3; j++) { + gxyz[j] = floor(gxyz[j]); + if (gxyz[j] < 0.f) + gxyz[j] = 0.f; + if (gxyz[j] >= grid.getRes()[j]) + gxyz[j] = grid.getRes()[j] - 1; + } + unsigned int minIt[3], maxIt[3]; + for (unsigned int j = 0; j < 3; j++) { + if (((unsigned int)gxyz[j]) == 0) + minIt[j] = 0; + else + minIt[j] = ((unsigned int)gxyz[j]) - 1; + if (((unsigned int)gxyz[j]) == (grid.getRes()[j] - 1)) + maxIt[j] = (grid.getRes()[j] - 1); + else + maxIt[j] = ((unsigned int)gxyz[j]) + 1; + } + Vector_3 c; + float sumW = 0.f; + unsigned int it[3]; + for (it[0] = minIt[0]; it[0] <= maxIt[0]; it[0]++) + for (it[1] = minIt[1]; it[1] <= maxIt[1]; it[1]++) + for (it[2] = minIt[2]; it[2] <= maxIt[2]; it[2]++) { + unsigned int gridIndex = grid.getLUTElement(it[0], it[1], it[2]); + if (gridIndex == 2 * PNSize) + continue; + unsigned int neigh = grid.getCellIndicesSize(it[0], it[1], it[2]); + for (unsigned int j = 0; j < neigh; j++) { + unsigned int k = grid.getIndicesElement(it[0], it[1], it[2], j); + Vector_3 pk(PN[6 * k], PN[6 * k + 1], PN[6 * k + 2]); + Vector_3 nk(PN[6 * k + 3], PN[6 * k + 4], PN[6 * k + 5]); + weightedPointCombination(p, pk, nk, sigma_s, bilateral, sigma_r, hermite, c, n, sumW); + } + } + if (sumW == 0.f) { + n = Vector_3(1.f, 0.f, 0.f); + q = p; + } + else { + c /= sumW; + normalize(n, Gt()); + q = projectOn(p, n, c); + } + } + + // Compute the MLS projection of the list of point stored in pv and store the resulting + // positions and normal in qv. qv must be preallocated to stroe 6*pvSize float32. + // The strid indicates the offsets in qv (the defautl value of 3 means that the qv + // is compact: pv={x0,y0,z0,x1,y1,z1...}. If pv contains also normals for instance, + // the stride should be set to 6. + void fastProjectionCPU(const std::vector& pv, unsigned int pvSize, + std::vector& qv, unsigned int stride = 3) const + { + for (int i = 0; i < int(pvSize); i++) { + Vector_3 p(pv[stride * i], pv[stride * i + 1], pv[stride * i + 2]); + Vector_3 q, n; + for (unsigned int j = 0; j < numIter; j++) { + q = Vector_3(); + n = Vector_3(); + fastProjectionCPU(p, q, n); + p = q; + } + setPNSample(qv, i, q[0], q[1], q[2], n[0], n[1], n[2]); + } + + } + + // Brute force version. O(PNSize) complexity. For comparison only. + void projectionCPU(const Vector_3& x, Vector_3& q, Vector_3& n) + { + float sigma_s = MLSRadius * PNScale; + float sigma_r = bilateralRange; + Vector_3 p(x); + for (unsigned int k = 0; k < numIter; k++) { + Vector_3 c; + n = Vector_3();; + float sumW = 0.f; + for (unsigned int j = 0; j < PNSize; j++) { + Vector_3 pj(PN[6 * j], PN[6 * j + 1], PN[6 * j + 2]); + Vector_3 nj(PN[6 * j + 3], PN[6 * j + 4], PN[6 * j + 5]); + weightedPointCombination(p, pj, nj, sigma_s, bilateral, sigma_r, hermite, c, n, sumW); + } + c /= sumW; + n.normalize(); + q = projectOn(p, n, c); + p = q; + } + + } + // Brute force version. O(pvSize*PNSize) complexity. For comparison only. + void projectionCPU(const std::vector& pv, + unsigned int pvSize, + std::vector& qv, + unsigned int stride = 3) + { + for (int i = 0; i < int(pvSize); i++) { + Vector_3 p(pv[stride * i], pv[stride * i + 1], pv[stride * i + 2]); + Vector_3 q, n; + for (unsigned int j = 0; j < numIter; j++) { + q = Vector_3(); + n = Vector_3(); + projectionCPU(p, q, n); + p = q; + } + setPNSample(qv, i, q[0], q[1], q[2], n[0], n[1], n[2]); + } + } + + // -------------------------------------------------------------- + // Accessors + // -------------------------------------------------------------- + + // Number of elements of the PN. One elemnt is a 6-float32 chunk. + inline unsigned int getPNSize() const { return PNSize; } + inline std::vector& getPN() { return PN; } + inline const std::vector& getPN() const { return PN; } + + // Min/Max corners of PN's bounding volume + inline const float* getMinMax() const { return grid.getMinMax(); } + // Radius of the bounding sphere of the PN + inline float getPNScale() const { return PNScale; } + // Normalized MLS support size + inline float getMLSRadius() const { return MLSRadius; } + inline void setMLSRadius(float s) { MLSRadius = s; grid.clear(); grid.init(PN, PNSize, MLSRadius * PNScale); } + // Bilateral weighting for feature preservation (inspired by [Jones 2003]). + inline bool isBilateral() const { return bilateral; } + inline void toggleBilateral(bool b) { bilateral = b; } + // Bilateral support size for the range weight + inline float getBilateralRange() const { return bilateralRange; } + inline void setBilateralRange(float r) { bilateralRange = r; } + // Hermite interpolation [Alexa 2009] + inline bool isHermite() const { return hermite; } + inline void toggleHermite(bool b) { hermite = b; } + // Fix number of iterations of the MLS projection + inline unsigned int getNumOfIter() const { return numIter; } + inline void setNumOfIter(unsigned int i) { numIter = i; } + + // -------------------------------------------------------------- + // Misc. + // -------------------------------------------------------------- + + // Size of a point sample in bytes (6xfloat32: 3 for position and normal + static const unsigned int SURFEL_SIZE = 24; + +private: + + void computePNScale() + { + Vector_3 c; + for (unsigned int i = 0; i < PNSize; i++) + c += Vector_3(PN[6 * i], PN[6 * i + 1], PN[6 * i + 2]); + c /= PNSize; + PNScale = 0.f; + for (unsigned int i = 0; i < PNSize; i++) { + float r = distance(c, Vector_3(PN[6 * i], PN[6 * i + 1], PN[6 * i + 2])); + if (r > PNScale) + PNScale = r; + } + } + + // -------------------------------------------------------------- + // 3D Grid Structure + // -------------------------------------------------------------- + // -------------------------------------------------------------- + // Grid data structure for fast r-ball neighborhood query + // -------------------------------------------------------------- + + class Grid + { + public: + Grid() { - // -------------------------------------------------------------- - // MLS Projection - // -------------------------------------------------------------- + cellSize = 1.f; + LUTSize = 0; + indicesSize = 0; + } + ~Grid() + { + clear(); + } - inline float wendland(float x, float h) - { - x = CGAL::abs(x); - if (x < h) - return CGAL::square(CGAL::square(1 - x / h)) * (4 * x / h + 1); - else - return 0.0; + void init(const std::vector& PN, unsigned int PNSize, float sigma_s) + { + cellSize = sigma_s; + for (unsigned int i = 0; i < 3; i++) { + minMax[i] = PN[i]; + minMax[3 + i] = PN[i]; } - - inline void setPNSample(std::vector& p, unsigned int i, - float x, float y, float z, - float nx, float ny, float nz) - { - p[6 * i] = x; - p[6 * i + 1] = y; - p[6 * i + 2] = z; - p[6 * i + 3] = nx; - p[6 * i + 4] = ny; - p[6 * i + 5] = nz; - } - - template - inline CGAL::Vector_3 projectOn(const CGAL::Vector_3& x, - const CGAL::Vector_3& N, - const CGAL::Vector_3& P) - { - typename Gt::Compute_scalar_product_3 scalar_product - = Gt().compute_scalar_product_3_object(); - - typename Gt::FT w = scalar_product((x - P), N); - return x - (N * w); - } - - template - inline typename Gt::FT length(const CGAL::Vector_3& v) - { - return CGAL::approximate_sqrt(v.squared_length()); - } - - template - inline typename Gt::FT distance(const CGAL::Vector_3& v1, - const CGAL::Vector_3& v2) - { - CGAL::Vector_3 diff(v1.x() - v2.x(), - v1.y() - v2.y(), - v1.z() - v2.z()); - return length(diff); - } - - template - inline void weightedPointCombination(const CGAL::Vector_3& x, - const CGAL::Vector_3& pi, - const CGAL::Vector_3& ni, - float sigma_s, bool bilateral, float sigma_r, - bool hermite, - CGAL::Vector_3& c, CGAL::Vector_3& nc, float& sumW) - { - float w = wendland(distance(x, pi), sigma_s); - if (bilateral) - w *= wendland(length(x - projectOn(x, ni, pi)), sigma_r); - if (hermite) - c += w * projectOn(x, ni, pi); - else - c += w * pi; - nc += w * ni; - sumW += w; - } - - template - class FMLS - { - typedef typename Gt::Vector_3 Vector_3; - typedef typename Gt::FT FT; - - public: - // FMLS provide MLS projection and filtering from a point set. - // The underlying data structure is a simple list of float in the PN format - // A PN object is a list of 6xfloat32 chunk : - // x0,y0,z0,nx0,ny0,nz0,x1,y1,z1,nx1,ny1,nz1,... - // with {xi,yi,zi} the position and {nxi,nyi,nzi} the normal vector of the - // i-th point sample. A PN can be read from and write to file directly - // (identity serialization) and is handled as a simple float32 pointer. - // - // Use the 'fast*' methods. Brute force methods are inserted only for comparison. - // - // Memory policy: a FMLS class manages itself al its belonging objects. - // Therefore, PN and filtered PN lists are the property of this class, and should - // be copied if modified outside the class. - FMLS() - { - PNSize = 0; - PNScale = 1.0f; - MLSRadius = 0.1f; - bilateralRange = 0.05f; - bilateral = false; - hermite = false; - numIter = 1; + for (unsigned int i = 0; i < PNSize; i++) + for (unsigned int j = 0; j < 3; j++) { + if (PN[6 * i + j] < minMax[j]) + minMax[j] = PN[6 * i + j]; + if (PN[6 * i + j] > minMax[3 + j]) + minMax[3 + j] = PN[6 * i + j]; } + for (unsigned int i = 0; i < 3; i++) { + minMax[i] -= 0.001f; + minMax[3 + i] += 0.001f; + } + for (unsigned int i = 0; i < 3; i++) + res[i] = (unsigned int)ceil((minMax[3 + i] - minMax[i]) / cellSize); + LUTSize = res[0] * res[1] * res[2]; + LUT.resize(LUTSize); + LUT.assign(LUTSize, 0); - // -------------------------------------------------------------- - // Main Interface - // -------------------------------------------------------------- + unsigned int nonEmptyCells = 0; + Vector_3 gMin(minMax[0], minMax[1], minMax[2]); + Vector_3 gMax(minMax[3], minMax[4], minMax[5]); + for (unsigned int i = 0; i < PNSize; i++) { + unsigned int index = getLUTIndex(Vector_3(PN[6 * i], PN[6 * i + 1], PN[6 * i + 2])); + if (LUT[index] == 0) + nonEmptyCells++; + LUT[index]++; + } + indicesSize = PNSize + nonEmptyCells; + indices.reserve(indicesSize); + indices.assign(indicesSize, 0); - std::vector createPN(unsigned int size) - { - return std::vector(size * SURFEL_SIZE); - } - - void setPN(const std::vector& newPN, - const unsigned int newPNSize, - const float pointSpacing) - { - freeCPUMemory(); - PN = newPN; - PNSize = newPNSize; - computePNScale(); - MLSRadius = 3 * pointSpacing / PNScale; - grid.clear(); - grid.init(PN, PNSize, MLSRadius * PNScale); - } - - // Compute, according to the current point sampling stored in FMLS, the MLS projection - // of p and store the resulting position in q and normal in n. - void fastProjectionCPU(const Vector_3& p, Vector_3& q, Vector_3& n) const - { - float sigma_s = PNScale * MLSRadius; - float sigma_r = bilateralRange; - - Vector_3 g = (p - Vector_3(grid.getMinMax()[0], grid.getMinMax()[1], grid.getMinMax()[2])) / sigma_s; - std::array gxyz = { g.x(), g.y(), g.z() }; - - for (unsigned int j = 0; j < 3; j++) { - gxyz[j] = floor(gxyz[j]); - if (gxyz[j] < 0.f) - gxyz[j] = 0.f; - if (gxyz[j] >= grid.getRes()[j]) - gxyz[j] = grid.getRes()[j] - 1; - } - unsigned int minIt[3], maxIt[3]; - for (unsigned int j = 0; j < 3; j++) { - if (((unsigned int)gxyz[j]) == 0) - minIt[j] = 0; + unsigned int cpt = 0; + for (unsigned int i = 0; i < res[0]; i++) + for (unsigned int j = 0; j < res[1]; j++) + for (unsigned int k = 0; k < res[2]; k++) { + unsigned int index = getLUTIndex(i, j, k); + if (LUT[index] != 0) { + indices[cpt] = LUT[index]; + LUT[index] = cpt; + cpt += indices[cpt] + 1; + indices[cpt - 1] = 0; // local iterator for subsequent filling + } else - minIt[j] = ((unsigned int)gxyz[j]) - 1; - if (((unsigned int)gxyz[j]) == (grid.getRes()[j] - 1)) - maxIt[j] = (grid.getRes()[j] - 1); - else - maxIt[j] = ((unsigned int)gxyz[j]) + 1; + LUT[index] = 2 * PNSize; } - Vector_3 c; - float sumW = 0.f; - unsigned int it[3]; - for (it[0] = minIt[0]; it[0] <= maxIt[0]; it[0]++) - for (it[1] = minIt[1]; it[1] <= maxIt[1]; it[1]++) - for (it[2] = minIt[2]; it[2] <= maxIt[2]; it[2]++) { - unsigned int gridIndex = grid.getLUTElement(it[0], it[1], it[2]); - if (gridIndex == 2 * PNSize) - continue; - unsigned int neigh = grid.getCellIndicesSize(it[0], it[1], it[2]); - for (unsigned int j = 0; j < neigh; j++) { - unsigned int k = grid.getIndicesElement(it[0], it[1], it[2], j); - Vector_3 pk(PN[6 * k], PN[6 * k + 1], PN[6 * k + 2]); - Vector_3 nk(PN[6 * k + 3], PN[6 * k + 4], PN[6 * k + 5]); - weightedPointCombination(p, pk, nk, sigma_s, bilateral, sigma_r, hermite, c, n, sumW); - } - } - if (sumW == 0.f) { - n = Vector_3(1.f, 0.f, 0.f); - q = p; - } - else { - c /= sumW; - normalize(n, Gt()); - q = projectOn(p, n, c); - } - } + for (unsigned int i = 0; i < PNSize; i++) { + Vector_3 p = Vector_3(PN[6 * i], PN[6 * i + 1], PN[6 * i + 2]); + unsigned int indicesIndex = getLUTElement(p); + unsigned int totalCount = indices[indicesIndex]; + unsigned int countIndex = indicesIndex + totalCount; + unsigned int currentCount = indices[countIndex]; + if (currentCount < indices[indicesIndex]) + indices[countIndex]++; + unsigned int pIndex = indicesIndex + 1 + currentCount; + indices[pIndex] = i; + } + } - // Compute the MLS projection of the list of point stored in pv and store the resulting - // positions and normal in qv. qv must be preallocated to stroe 6*pvSize float32. - // The strid indicates the offsets in qv (the defautl value of 3 means that the qv - // is compact: pv={x0,y0,z0,x1,y1,z1...}. If pv contains also normals for instance, - // the stride should be set to 6. - void fastProjectionCPU(const std::vector& pv, unsigned int pvSize, - std::vector& qv, unsigned int stride = 3) const - { - for (int i = 0; i < int(pvSize); i++) { - Vector_3 p(pv[stride * i], pv[stride * i + 1], pv[stride * i + 2]); - Vector_3 q, n; - for (unsigned int j = 0; j < numIter; j++) { - q = Vector_3(); - n = Vector_3(); - fastProjectionCPU(p, q, n); - p = q; - } - setPNSample(qv, i, q[0], q[1], q[2], n[0], n[1], n[2]); - } + void clear() + { + cellSize = 1.f; + LUTSize = 0; + indicesSize = 0; + } - } + // Accessors - // Brute force version. O(PNSize) complexity. For comparison only. - void projectionCPU(const Vector_3& x, Vector_3& q, Vector_3& n) - { - float sigma_s = MLSRadius * PNScale; - float sigma_r = bilateralRange; - Vector_3 p(x); - for (unsigned int k = 0; k < numIter; k++) { - Vector_3 c; - n = Vector_3();; - float sumW = 0.f; - for (unsigned int j = 0; j < PNSize; j++) { - Vector_3 pj(PN[6 * j], PN[6 * j + 1], PN[6 * j + 2]); - Vector_3 nj(PN[6 * j + 3], PN[6 * j + 4], PN[6 * j + 5]); - weightedPointCombination(p, pj, nj, sigma_s, bilateral, sigma_r, hermite, c, n, sumW); - } - c /= sumW; - n.normalize(); - q = projectOn(p, n, c); - p = q; - } + inline const std::array getMinMax() const { return minMax; } + inline const std::array getRes() const { return res; } + inline float getCellSize() const { return cellSize; } + inline std::vector& getLUT() { return LUT; } + inline const std::vector& getLUT() const { return LUT; } + inline unsigned int getLUTSize() const { return LUTSize; } + inline unsigned int getLUTIndex(unsigned int i, + unsigned int j, + unsigned int k) const + { + return k * res[0] * res[1] + j * res[0] + i; + } + inline unsigned int getLUTElement(unsigned int i, + unsigned int j, + unsigned int k) const + { + return LUT[getLUTIndex(i, j, k)]; + } + unsigned int getLUTIndex(const Vector_3& x) const + { + Vector_3 vp = (x - Vector_3(minMax[0], minMax[1], minMax[2])) / cellSize; + std::array p = { vp.x(), vp.y(), vp.z() }; + for (unsigned int j = 0; j < 3; j++) { + p[j] = floor(p[j]); + if (p[j] < 0) + p[j] = 0.f; + if (p[j] >= res[j]) + p[j] = res[j] - 1; + } + unsigned index = ((unsigned int)floor(p[2])) * res[0] * res[1] + + ((unsigned int)floor(p[1])) * res[0] + + ((unsigned int)floor(p[0])); + return index; + } + inline unsigned int getLUTElement(const Vector_3& x) const { + return LUT[getLUTIndex(x)]; + } + inline std::vector& getIndices() { return indices; } + inline const std::vector& getIndices() const { return indices; } + inline unsigned int getIndicesSize() const { return indicesSize; } + inline unsigned int getCellIndicesSize(unsigned int i, + unsigned int j, + unsigned int k) const { + return indices[getLUTElement(i, j, k)]; + } + inline unsigned int getIndicesElement(unsigned int i, + unsigned int j, + unsigned int k, + unsigned int e) const { + return indices[getLUTElement(i, j, k) + 1 + e]; + } - } - // Brute force version. O(pvSize*PNSize) complexity. For comparison only. - void projectionCPU(const std::vector& pv, - unsigned int pvSize, - std::vector& qv, - unsigned int stride = 3) - { - for (int i = 0; i < int(pvSize); i++) { - Vector_3 p(pv[stride * i], pv[stride * i + 1], pv[stride * i + 2]); - Vector_3 q, n; - for (unsigned int j = 0; j < numIter; j++) { - q = Vector_3(); - n = Vector_3(); - projectionCPU(p, q, n); - p = q; - } - setPNSample(qv, i, q[0], q[1], q[2], n[0], n[1], n[2]); - } - } - - // -------------------------------------------------------------- - // Accessors - // -------------------------------------------------------------- - - // Number of elements of the PN. One elemnt is a 6-float32 chunk. - inline unsigned int getPNSize() const { return PNSize; } - inline std::vector& getPN() { return PN; } - inline const std::vector& getPN() const { return PN; } - - // Min/Max corners of PN's bounding volume - inline const float* getMinMax() const { return grid.getMinMax(); } - // Radius of the bounding sphere of the PN - inline float getPNScale() const { return PNScale; } - // Normalized MLS support size - inline float getMLSRadius() const { return MLSRadius; } - inline void setMLSRadius(float s) { MLSRadius = s; grid.clear(); grid.init(PN, PNSize, MLSRadius * PNScale); } - // Bilateral weighting for feature preservation (inspired by [Jones 2003]). - inline bool isBilateral() const { return bilateral; } - inline void toggleBilateral(bool b) { bilateral = b; } - // Bilateral support size for the range weight - inline float getBilateralRange() const { return bilateralRange; } - inline void setBilateralRange(float r) { bilateralRange = r; } - // Hermite interpolation [Alexa 2009] - inline bool isHermite() const { return hermite; } - inline void toggleHermite(bool b) { hermite = b; } - // Fix number of iterations of the MLS projection - inline unsigned int getNumOfIter() const { return numIter; } - inline void setNumOfIter(unsigned int i) { numIter = i; } - - // -------------------------------------------------------------- - // Misc. - // -------------------------------------------------------------- - - // Size of a point sample in bytes (6xfloat32: 3 for position and normal - static const unsigned int SURFEL_SIZE = 24; - - private: - - void computePNScale() - { - Vector_3 c; - for (unsigned int i = 0; i < PNSize; i++) - c += Vector_3(PN[6 * i], PN[6 * i + 1], PN[6 * i + 2]); - c /= PNSize; - PNScale = 0.f; - for (unsigned int i = 0; i < PNSize; i++) { - float r = distance(c, Vector_3(PN[6 * i], PN[6 * i + 1], PN[6 * i + 2])); - if (r > PNScale) - PNScale = r; - } - } - - // -------------------------------------------------------------- - // 3D Grid Structure - // -------------------------------------------------------------- - // -------------------------------------------------------------- - // Grid data structure for fast r-ball neighborhood query - // -------------------------------------------------------------- - - class Grid - { - public: - Grid() - { - cellSize = 1.f; - LUTSize = 0; - indicesSize = 0; - } - ~Grid() - { - clear(); - } - - void init(const std::vector& PN, unsigned int PNSize, float sigma_s) - { - cellSize = sigma_s; - for (unsigned int i = 0; i < 3; i++) { - minMax[i] = PN[i]; - minMax[3 + i] = PN[i]; - } - for (unsigned int i = 0; i < PNSize; i++) - for (unsigned int j = 0; j < 3; j++) { - if (PN[6 * i + j] < minMax[j]) - minMax[j] = PN[6 * i + j]; - if (PN[6 * i + j] > minMax[3 + j]) - minMax[3 + j] = PN[6 * i + j]; - } - for (unsigned int i = 0; i < 3; i++) { - minMax[i] -= 0.001f; - minMax[3 + i] += 0.001f; - } - for (unsigned int i = 0; i < 3; i++) - res[i] = (unsigned int)ceil((minMax[3 + i] - minMax[i]) / cellSize); - LUTSize = res[0] * res[1] * res[2]; - LUT.resize(LUTSize); - LUT.assign(LUTSize, 0); - - unsigned int nonEmptyCells = 0; - Vector_3 gMin(minMax[0], minMax[1], minMax[2]); - Vector_3 gMax(minMax[3], minMax[4], minMax[5]); - for (unsigned int i = 0; i < PNSize; i++) { - unsigned int index = getLUTIndex(Vector_3(PN[6 * i], PN[6 * i + 1], PN[6 * i + 2])); - if (LUT[index] == 0) - nonEmptyCells++; - LUT[index]++; - } - indicesSize = PNSize + nonEmptyCells; - indices.reserve(indicesSize); - indices.assign(indicesSize, 0); - - unsigned int cpt = 0; - for (unsigned int i = 0; i < res[0]; i++) - for (unsigned int j = 0; j < res[1]; j++) - for (unsigned int k = 0; k < res[2]; k++) { - unsigned int index = getLUTIndex(i, j, k); - if (LUT[index] != 0) { - indices[cpt] = LUT[index]; - LUT[index] = cpt; - cpt += indices[cpt] + 1; - indices[cpt - 1] = 0; // local iterator for subsequent filling - } - else - LUT[index] = 2 * PNSize; - } - for (unsigned int i = 0; i < PNSize; i++) { - Vector_3 p = Vector_3(PN[6 * i], PN[6 * i + 1], PN[6 * i + 2]); - unsigned int indicesIndex = getLUTElement(p); - unsigned int totalCount = indices[indicesIndex]; - unsigned int countIndex = indicesIndex + totalCount; - unsigned int currentCount = indices[countIndex]; - if (currentCount < indices[indicesIndex]) - indices[countIndex]++; - unsigned int pIndex = indicesIndex + 1 + currentCount; - indices[pIndex] = i; - } - } - - void clear() - { - cellSize = 1.f; - LUTSize = 0; - indicesSize = 0; - } - - // Accessors - - inline const std::array getMinMax() const { return minMax; } - inline const std::array getRes() const { return res; } - inline float getCellSize() const { return cellSize; } - inline std::vector& getLUT() { return LUT; } - inline const std::vector& getLUT() const { return LUT; } - inline unsigned int getLUTSize() const { return LUTSize; } - inline unsigned int getLUTIndex(unsigned int i, - unsigned int j, - unsigned int k) const - { - return k * res[0] * res[1] + j * res[0] + i; - } - inline unsigned int getLUTElement(unsigned int i, - unsigned int j, - unsigned int k) const - { - return LUT[getLUTIndex(i, j, k)]; - } - unsigned int getLUTIndex(const Vector_3& x) const - { - Vector_3 vp = (x - Vector_3(minMax[0], minMax[1], minMax[2])) / cellSize; - std::array p = { vp.x(), vp.y(), vp.z() }; - for (unsigned int j = 0; j < 3; j++) { - p[j] = floor(p[j]); - if (p[j] < 0) - p[j] = 0.f; - if (p[j] >= res[j]) - p[j] = res[j] - 1; - } - unsigned index = ((unsigned int)floor(p[2])) * res[0] * res[1] - + ((unsigned int)floor(p[1])) * res[0] - + ((unsigned int)floor(p[0])); - return index; - } - inline unsigned int getLUTElement(const Vector_3& x) const { - return LUT[getLUTIndex(x)]; - } - inline std::vector& getIndices() { return indices; } - inline const std::vector& getIndices() const { return indices; } - inline unsigned int getIndicesSize() const { return indicesSize; } - inline unsigned int getCellIndicesSize(unsigned int i, - unsigned int j, - unsigned int k) const { - return indices[getLUTElement(i, j, k)]; - } - inline unsigned int getIndicesElement(unsigned int i, - unsigned int j, - unsigned int k, - unsigned int e) const { - return indices[getLUTElement(i, j, k) + 1 + e]; - } - - private: - std::array minMax; - float cellSize; - std::array res; - unsigned int LUTSize; - std::vector LUT; // 3D Index Look-Up Table - unsigned int indicesSize; - std::vector indices; // 3D Grid data - }; + private: + std::array minMax; + float cellSize; + std::array res; + unsigned int LUTSize; + std::vector LUT; // 3D Index Look-Up Table + unsigned int indicesSize; + std::vector indices; // 3D Grid data + }; - // -------------------------------------------------------------- - // Memory Managment - // -------------------------------------------------------------- + // -------------------------------------------------------------- + // Memory Managment + // -------------------------------------------------------------- - void freeCPUMemory() - { - PN.clear(); - PNSize = 0; - } + void freeCPUMemory() + { + PN.clear(); + PNSize = 0; + } - // -------------------------------------------------------------- - // CPU Data - // -------------------------------------------------------------- + // -------------------------------------------------------------- + // CPU Data + // -------------------------------------------------------------- - std::vector PN; - unsigned int PNSize; - float PNScale; // size of the bounding sphere radius - float MLSRadius; - float bilateralRange; - bool bilateral; - bool hermite; - unsigned int numIter; - Grid grid; - }; + std::vector PN; + unsigned int PNSize; + float PNScale; // size of the bounding sphere radius + float MLSRadius; + float bilateralRange; + bool bilateral; + bool hermite; + unsigned int numIter; + Grid grid; +}; - template - void createMLSSurfaces(Subdomain__FMLS& subdomain_FMLS, - Subdomain__FMLS_indices& subdomain_FMLS_indices, - const VerticesNormalsMap& vertices_normals, - const VerticesSurfaceIndices& vertices_surface_indices, - const C3t3& c3t3) +template +void createMLSSurfaces(Subdomain__FMLS& subdomain_FMLS, + Subdomain__FMLS_indices& subdomain_FMLS_indices, + const VerticesNormalsMap& vertices_normals, + const VerticesSurfaceIndices& vertices_surface_indices, + const C3t3& c3t3) +{ + const int upsample = 2; // can be 0, 1 or 2 + + typedef typename C3t3::Surface_patch_index Surface_index; + typedef typename C3t3::Triangulation Tr; + typedef typename Tr::Edge Edge; + typedef typename Tr::Vertex_handle Vertex_handle; + typedef typename Tr::Geom_traits Gt; + typedef typename Gt::Point_3 Point_3; + typedef typename Gt::Vector_3 Vector_3; + + typedef typename VerticesSurfaceIndices::mapped_type VertexSurfaces; + typedef typename VerticesSurfaceIndices::const_iterator VerticesSurfaceIterator; + + const Tr& tr = c3t3.triangulation(); + + //createAreaWeightedUpSampledMLSSurfaces(0); + //return ; + subdomain_FMLS.clear(); + subdomain_FMLS_indices.clear(); + + typedef boost::unordered_map SurfaceIndexMap; + + SurfaceIndexMap current_subdomain_FMLS_indices; + SurfaceIndexMap subdomain_sample_numbers; + + //Count the number of vertices for each boundary surface (i.e. one per label) + for (const Vertex_handle vit : tr.finite_vertex_handles()) + { + VerticesSurfaceIterator sit = vertices_surface_indices.find(vit); + if (sit == vertices_surface_indices.end()) + continue; + + const VertexSurfaces& v_surface_indices = vertices_surface_indices.at(vit); + CGAL_assertion(vit->in_dimension() <= 2); + + for(const Surface_index& si : v_surface_indices) + { + subdomain_sample_numbers[si]++; + } + } + + if (upsample > 0) + { + std::cout << "Up sampling MLS " << upsample << std::endl; + for (typename C3t3::Facet_iterator fit = c3t3.facets_begin(); + fit != c3t3.facets_end(); ++fit) + { + const Surface_index surf_i = c3t3.surface_patch_index(*fit); + if (upsample == 1) + subdomain_sample_numbers[surf_i] ++; + else if (upsample == 2) + subdomain_sample_numbers[surf_i] += 4; + } + } + + std::vector< std::vector > pns; + + int count = 0; + //Memory allocation for the point plus normals of the point samples + for (typename SurfaceIndexMap::iterator it = subdomain_sample_numbers.begin(); + it != subdomain_sample_numbers.end(); ++it) + { + current_subdomain_FMLS_indices[it->first] = count; + pns.push_back(std::vector(it->second * 6, 0)); + count++; + } + + std::vector current_v_count(count, 0); + std::vector point_spacing(count, 0); + std::vector point_spacing_count(count, 0); + + //Allocation of the PN + for (Vertex_handle vit : tr.finite_vertex_handles()) + { + VerticesSurfaceIterator sit = vertices_surface_indices.find(vit); + if (sit == vertices_surface_indices.end()) + continue; + + const VertexSurfaces& v_surface_indices = vertices_surface_indices.at(vit); + CGAL_assertion(vit->in_dimension() <= 2); + + for (const Surface_index& surf_i : v_surface_indices) + { + const int fmls_id = current_subdomain_FMLS_indices[surf_i]; + + const Point_3& p = point(vit->point()); + + pns[fmls_id][6 * current_v_count[fmls_id]] = p.x(); + pns[fmls_id][6 * current_v_count[fmls_id] + 1] = p.y(); + pns[fmls_id][6 * current_v_count[fmls_id] + 2] = p.z(); + + const Vector_3& normal = vertices_normals.at(vit).at(surf_i); + + pns[fmls_id][6 * current_v_count[fmls_id] + 3] = normal.x(); + pns[fmls_id][6 * current_v_count[fmls_id] + 4] = normal.y(); + pns[fmls_id][6 * current_v_count[fmls_id] + 5] = normal.z(); + + current_v_count[fmls_id]++; + } + } + + typedef std::pair Edge_vv; + if (upsample == 0) + { + std::unordered_set > edgeMap; + + for (typename C3t3::Facet_iterator fit = c3t3.facets_begin(); + fit != c3t3.facets_end(); ++fit) + { + for (int i = 0; i < 2; i++) { - const int upsample = 2; // can be 0, 1 or 2 - - typedef typename C3t3::Surface_patch_index Surface_index; - typedef typename C3t3::Triangulation Tr; - typedef typename Tr::Edge Edge; - typedef typename Tr::Vertex_handle Vertex_handle; - typedef typename Tr::Geom_traits Gt; - typedef typename Gt::Point_3 Point_3; - typedef typename Gt::Vector_3 Vector_3; - - typedef typename VerticesSurfaceIndices::mapped_type VertexSurfaces; - typedef typename VerticesSurfaceIndices::const_iterator VerticesSurfaceIterator; - - const Tr& tr = c3t3.triangulation(); - - //createAreaWeightedUpSampledMLSSurfaces(0); - //return ; - subdomain_FMLS.clear(); - subdomain_FMLS_indices.clear(); - - typedef boost::unordered_map SurfaceIndexMap; - - SurfaceIndexMap current_subdomain_FMLS_indices; - SurfaceIndexMap subdomain_sample_numbers; - - //Count the number of vertices for each boundary surface (i.e. one per label) - for (const Vertex_handle vit : tr.finite_vertex_handles()) + for (int j = i + 1; j < 3; j++) { - VerticesSurfaceIterator sit = vertices_surface_indices.find(vit); - if (sit == vertices_surface_indices.end()) - continue; + Edge edge(fit->first, indices(fit->second,i), indices(fit->second,j)); - const VertexSurfaces& v_surface_indices = vertices_surface_indices.at(vit); - CGAL_assertion(vit->in_dimension() <= 2); - - for(const Surface_index& si : v_surface_indices) + Vertex_handle vh0 = edge.first->vertex(edge.second); + Vertex_handle vh1 = edge.first->vertex(edge.third); + Edge_vv e = make_vertex_pair(vh0, vh1); + if ( vertices_surface_indices.find(vh0) != vertices_surface_indices.end() + && vertices_surface_indices.find(vh1) != vertices_surface_indices.end() + && edgeMap.find(e) == edgeMap.end()) { - subdomain_sample_numbers[si]++; - } - } + edgeMap.insert(e); - if (upsample > 0) - { - std::cout << "Up sampling MLS " << upsample << std::endl; - for (typename C3t3::Facet_iterator fit = c3t3.facets_begin(); - fit != c3t3.facets_end(); ++fit) - { const Surface_index surf_i = c3t3.surface_patch_index(*fit); - if (upsample == 1) - subdomain_sample_numbers[surf_i] ++; - else if (upsample == 2) - subdomain_sample_numbers[surf_i] += 4; - } - } - - std::vector< std::vector > pns; - - int count = 0; - //Memory allocation for the point plus normals of the point samples - for (typename SurfaceIndexMap::iterator it = subdomain_sample_numbers.begin(); - it != subdomain_sample_numbers.end(); ++it) - { - current_subdomain_FMLS_indices[it->first] = count; - pns.push_back(std::vector(it->second * 6, 0)); - count++; - } - - std::vector current_v_count(count, 0); - std::vector point_spacing(count, 0); - std::vector point_spacing_count(count, 0); - - //Allocation of the PN - for (Vertex_handle vit : tr.finite_vertex_handles()) - { - VerticesSurfaceIterator sit = vertices_surface_indices.find(vit); - if (sit == vertices_surface_indices.end()) - continue; - - const VertexSurfaces& v_surface_indices = vertices_surface_indices.at(vit); - CGAL_assertion(vit->in_dimension() <= 2); - - for (const Surface_index& surf_i : v_surface_indices) - { const int fmls_id = current_subdomain_FMLS_indices[surf_i]; - const Point_3& p = point(vit->point()); - - pns[fmls_id][6 * current_v_count[fmls_id]] = p.x(); - pns[fmls_id][6 * current_v_count[fmls_id] + 1] = p.y(); - pns[fmls_id][6 * current_v_count[fmls_id] + 2] = p.z(); - - const Vector_3& normal = vertices_normals.at(vit).at(surf_i); - - pns[fmls_id][6 * current_v_count[fmls_id] + 3] = normal.x(); - pns[fmls_id][6 * current_v_count[fmls_id] + 4] = normal.y(); - pns[fmls_id][6 * current_v_count[fmls_id] + 5] = normal.z(); - - current_v_count[fmls_id]++; - } - } - - typedef std::pair Edge_vv; - if (upsample == 0) - { - std::unordered_set > edgeMap; - - for (typename C3t3::Facet_iterator fit = c3t3.facets_begin(); - fit != c3t3.facets_end(); ++fit) - { - for (int i = 0; i < 2; i++) - { - for (int j = i + 1; j < 3; j++) - { - Edge edge(fit->first, indices(fit->second,i), indices(fit->second,j)); - - Vertex_handle vh0 = edge.first->vertex(edge.second); - Vertex_handle vh1 = edge.first->vertex(edge.third); - Edge_vv e = make_vertex_pair(vh0, vh1); - if ( vertices_surface_indices.find(vh0) != vertices_surface_indices.end() - && vertices_surface_indices.find(vh1) != vertices_surface_indices.end() - && edgeMap.find(e) == edgeMap.end()) - { - edgeMap.insert(e); - - const Surface_index surf_i = c3t3.surface_patch_index(*fit); - const int fmls_id = current_subdomain_FMLS_indices[surf_i]; - - point_spacing[fmls_id] += CGAL::approximate_sqrt( - CGAL::squared_distance(point(vh0->point()), point(vh1->point()))); - point_spacing_count[fmls_id] ++; - } - } - } - } - } - - if (upsample > 0) - { - for (typename C3t3::Facet_iterator fit = c3t3.facets_begin(); - fit != c3t3.facets_end(); ++fit) - { - const Surface_index surf_i = c3t3.surface_patch_index(*fit); - - const int fmls_id = current_subdomain_FMLS_indices[surf_i]; - - Vertex_handle vhs[3] = { fit->first->vertex(indices(fit->second, 0)), - fit->first->vertex(indices(fit->second, 1)), - fit->first->vertex(indices(fit->second, 2)) }; - Vector_3 points[3] = { Vector_3(CGAL::ORIGIN, point(vhs[0]->point())), - Vector_3(CGAL::ORIGIN, point(vhs[1]->point())), - Vector_3(CGAL::ORIGIN, point(vhs[2]->point())) }; - Vector_3 normals[3] = { vertices_normals.at(vhs[0]).at(surf_i), - vertices_normals.at(vhs[1]).at(surf_i), - vertices_normals.at(vhs[2]).at(surf_i) }; - - std::vector points_to_add; - std::vector n_points_to_add; - - //Add the barycenter of the facet - Vector_3 barycenter = (points[0] + points[1] + points[2]) / 3.; - Vector_3 n_barycenter = (normals[0] + normals[1] + normals[2]); - - n_barycenter = n_barycenter / CGAL::sqrt((n_barycenter * n_barycenter)); - - points_to_add.push_back(barycenter); - n_points_to_add.push_back(n_barycenter); - - if (upsample == 1) - { - for (int i = 0; i < 3; i++) - { - Vector_3 space_1 = barycenter - points[i]; - - point_spacing[fmls_id] += CGAL::to_double(CGAL::sqrt(space_1 * space_1)); - point_spacing_count[fmls_id] ++; - } - } - else if (upsample == 2) - { - for (int i = 0; i < 3; i++) - { - int i1 = (i + 1) % 3; - int i2 = (i + 2) % 3; - - Vector_3 p = (barycenter + points[i1] + points[i2]) / 3.; - Vector_3 n = (n_barycenter + normals[i1] + normals[i2]); - - n = n / CGAL::sqrt(n * n); - - points_to_add.push_back(p); - n_points_to_add.push_back(n); - - Vector_3 space_1 = p - barycenter; - Vector_3 space_2 = p - points[i1]; - Vector_3 space_3 = p - points[i2]; - - point_spacing[fmls_id] += CGAL::to_double(CGAL::sqrt(space_1 * space_1)); - point_spacing[fmls_id] += CGAL::to_double(CGAL::sqrt(space_2 * space_2)); - point_spacing[fmls_id] += CGAL::to_double(CGAL::sqrt(space_3 * space_3)); - - point_spacing_count[fmls_id] += 3; - } - } - for (unsigned int i = 0; i < points_to_add.size(); i++) - { - Vector_3& point = points_to_add[i]; - - pns[fmls_id][6 * current_v_count[fmls_id]] = point.x(); - pns[fmls_id][6 * current_v_count[fmls_id] + 1] = point.y(); - pns[fmls_id][6 * current_v_count[fmls_id] + 2] = point.z(); - - Vector_3& normal = n_points_to_add[i]; - - pns[fmls_id][6 * current_v_count[fmls_id] + 3] = normal.x(); - pns[fmls_id][6 * current_v_count[fmls_id] + 4] = normal.y(); - pns[fmls_id][6 * current_v_count[fmls_id] + 5] = normal.z(); - - current_v_count[fmls_id]++; - } - } - } - - - int nb_of_mls_to_create = 0; - double average_point_spacing = 0; - - //Cretaing the actual MLS surfaces - for (typename SurfaceIndexMap::iterator it = current_subdomain_FMLS_indices.begin(); - it != current_subdomain_FMLS_indices.end(); ++it) - { - if (current_v_count[it->second] > 3) - { - nb_of_mls_to_create++; - - double current_point_spacing = point_spacing[it->second] / point_spacing_count[it->second]; - point_spacing[it->second] = current_point_spacing; - - average_point_spacing += current_point_spacing; - } - } - - average_point_spacing = average_point_spacing / nb_of_mls_to_create; - - subdomain_FMLS.resize(nb_of_mls_to_create, FMLS()); - - count = 0; - //Creating the actual MLS surfaces - for (typename SurfaceIndexMap::iterator it = current_subdomain_FMLS_indices.begin(); - it != current_subdomain_FMLS_indices.end(); ++it) - { - if (current_v_count[it->second] > 3) - { - double current_point_spacing = point_spacing[it->second]; - - //subdomain_FMLS[count].toggleHermite(true); - subdomain_FMLS[count].setPN(pns[it->second], current_v_count[it->second], current_point_spacing); - // subdomain_FMLS[count].toggleHermite(true); - subdomain_FMLS_indices[it->first] = count; - - count++; - } - else { - std::cout << "Problem of number for MLS : " << current_v_count[it->second] << std::endl; + point_spacing[fmls_id] += CGAL::approximate_sqrt( + CGAL::squared_distance(point(vh0->point()), point(vh1->point()))); + point_spacing_count[fmls_id] ++; } } } } } + + if (upsample > 0) + { + for (typename C3t3::Facet_iterator fit = c3t3.facets_begin(); + fit != c3t3.facets_end(); ++fit) + { + const Surface_index surf_i = c3t3.surface_patch_index(*fit); + + const int fmls_id = current_subdomain_FMLS_indices[surf_i]; + + Vertex_handle vhs[3] = { fit->first->vertex(indices(fit->second, 0)), + fit->first->vertex(indices(fit->second, 1)), + fit->first->vertex(indices(fit->second, 2)) }; + Vector_3 points[3] = { Vector_3(CGAL::ORIGIN, point(vhs[0]->point())), + Vector_3(CGAL::ORIGIN, point(vhs[1]->point())), + Vector_3(CGAL::ORIGIN, point(vhs[2]->point())) }; + Vector_3 normals[3] = { vertices_normals.at(vhs[0]).at(surf_i), + vertices_normals.at(vhs[1]).at(surf_i), + vertices_normals.at(vhs[2]).at(surf_i) }; + + std::vector points_to_add; + std::vector n_points_to_add; + + //Add the barycenter of the facet + Vector_3 barycenter = (points[0] + points[1] + points[2]) / 3.; + Vector_3 n_barycenter = (normals[0] + normals[1] + normals[2]); + + n_barycenter = n_barycenter / CGAL::sqrt((n_barycenter * n_barycenter)); + + points_to_add.push_back(barycenter); + n_points_to_add.push_back(n_barycenter); + + if (upsample == 1) + { + for (int i = 0; i < 3; i++) + { + Vector_3 space_1 = barycenter - points[i]; + + point_spacing[fmls_id] += CGAL::to_double(CGAL::sqrt(space_1 * space_1)); + point_spacing_count[fmls_id] ++; + } + } + else if (upsample == 2) + { + for (int i = 0; i < 3; i++) + { + int i1 = (i + 1) % 3; + int i2 = (i + 2) % 3; + + Vector_3 p = (barycenter + points[i1] + points[i2]) / 3.; + Vector_3 n = (n_barycenter + normals[i1] + normals[i2]); + + n = n / CGAL::sqrt(n * n); + + points_to_add.push_back(p); + n_points_to_add.push_back(n); + + Vector_3 space_1 = p - barycenter; + Vector_3 space_2 = p - points[i1]; + Vector_3 space_3 = p - points[i2]; + + point_spacing[fmls_id] += CGAL::to_double(CGAL::sqrt(space_1 * space_1)); + point_spacing[fmls_id] += CGAL::to_double(CGAL::sqrt(space_2 * space_2)); + point_spacing[fmls_id] += CGAL::to_double(CGAL::sqrt(space_3 * space_3)); + + point_spacing_count[fmls_id] += 3; + } + } + for (unsigned int i = 0; i < points_to_add.size(); i++) + { + Vector_3& point = points_to_add[i]; + + pns[fmls_id][6 * current_v_count[fmls_id]] = point.x(); + pns[fmls_id][6 * current_v_count[fmls_id] + 1] = point.y(); + pns[fmls_id][6 * current_v_count[fmls_id] + 2] = point.z(); + + Vector_3& normal = n_points_to_add[i]; + + pns[fmls_id][6 * current_v_count[fmls_id] + 3] = normal.x(); + pns[fmls_id][6 * current_v_count[fmls_id] + 4] = normal.y(); + pns[fmls_id][6 * current_v_count[fmls_id] + 5] = normal.z(); + + current_v_count[fmls_id]++; + } + } + } + + + int nb_of_mls_to_create = 0; + double average_point_spacing = 0; + + //Cretaing the actual MLS surfaces + for (typename SurfaceIndexMap::iterator it = current_subdomain_FMLS_indices.begin(); + it != current_subdomain_FMLS_indices.end(); ++it) + { + if (current_v_count[it->second] > 3) + { + nb_of_mls_to_create++; + + double current_point_spacing = point_spacing[it->second] / point_spacing_count[it->second]; + point_spacing[it->second] = current_point_spacing; + + average_point_spacing += current_point_spacing; + } + } + + average_point_spacing = average_point_spacing / nb_of_mls_to_create; + + subdomain_FMLS.resize(nb_of_mls_to_create, FMLS()); + + count = 0; + //Creating the actual MLS surfaces + for (typename SurfaceIndexMap::iterator it = current_subdomain_FMLS_indices.begin(); + it != current_subdomain_FMLS_indices.end(); ++it) + { + if (current_v_count[it->second] > 3) + { + double current_point_spacing = point_spacing[it->second]; + + //subdomain_FMLS[count].toggleHermite(true); + subdomain_FMLS[count].setPN(pns[it->second], current_v_count[it->second], current_point_spacing); + // subdomain_FMLS[count].toggleHermite(true); + subdomain_FMLS_indices[it->first] = count; + + count++; + } + else { + std::cout << "Problem of number for MLS : " << current_v_count[it->second] << std::endl; + } + } } +} // internal +} // Tetrahedral_remeshing +} // CGAL + #endif //CGAL_TETRAHEDRAL_REMESHING_FMLS_H diff --git a/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/collapse_short_edges.h b/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/collapse_short_edges.h index 4742352dcac..7718c7b2962 100644 --- a/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/collapse_short_edges.h +++ b/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/collapse_short_edges.h @@ -34,889 +34,879 @@ namespace Tetrahedral_remeshing { namespace internal { - enum Edge_type { FEATURE, BOUNDARY, INSIDE, MIXTE, - NO_COLLAPSE, INVALID, IMAGINARY, MIXTE_IMAGINARY, HULL_EDGE }; - enum Collapse_type { TO_MIDPOINT, TO_V0, TO_V1, IMPOSSIBLE }; - enum Result_type { VALID, - V_PROBLEM, C_PROBLEM, E_PROBLEM, - TOPOLOGICAL_PROBLEM, ORIENTATION_PROBLEM, SHARED_NEIGHBOR_PROBLEM }; +enum Edge_type { FEATURE, BOUNDARY, INSIDE, MIXTE, + NO_COLLAPSE, INVALID, IMAGINARY, MIXTE_IMAGINARY, HULL_EDGE }; +enum Collapse_type { TO_MIDPOINT, TO_V0, TO_V1, IMPOSSIBLE }; +enum Result_type { VALID, + V_PROBLEM, C_PROBLEM, E_PROBLEM, + TOPOLOGICAL_PROBLEM, ORIENTATION_PROBLEM, SHARED_NEIGHBOR_PROBLEM }; - template - class CollapseTriangulation +template +class CollapseTriangulation +{ + typedef typename C3t3::Triangulation Tr; + typedef typename C3t3::Edge Edge; + typedef typename C3t3::Cell_handle Cell_handle; + typedef typename C3t3::Vertex_handle Vertex_handle; + typedef typename C3t3::Subdomain_index Subdomain_index; + typedef typename C3t3::Triangulation::Point Point_3; + typedef typename C3t3::Triangulation::Geom_traits::Vector_3 Vector_3; + + typedef CGAL::Triangulation_incremental_builder_3 Builder; + +public: + CollapseTriangulation(C3t3& c3t3, + const Edge& edge, + Collapse_type _collapse_type, + Visitor& visitor) { - typedef typename C3t3::Triangulation Tr; - typedef typename C3t3::Edge Edge; - typedef typename C3t3::Cell_handle Cell_handle; - typedef typename C3t3::Vertex_handle Vertex_handle; - typedef typename C3t3::Subdomain_index Subdomain_index; - typedef typename C3t3::Triangulation::Point Point_3; - typedef typename C3t3::Triangulation::Geom_traits::Vector_3 Vector_3; + v0_init = edge.first->vertex(edge.second); + v1_init = edge.first->vertex(edge.third); - typedef CGAL::Triangulation_incremental_builder_3 Builder; + std::vector vertices_to_insert; + c3t3.triangulation().finite_incident_vertices(v0_init, + std::back_inserter(vertices_to_insert)); + vertices_to_insert.push_back(v0_init); + c3t3.triangulation().finite_incident_vertices(v1_init, + std::back_inserter(vertices_to_insert)); - public: - CollapseTriangulation(C3t3& c3t3, - const Edge& edge, - Collapse_type _collapse_type, - Visitor& visitor) + // create incremental builder + Builder builder(triangulation, true); + builder.begin_triangulation(3); + + collapse_type = _collapse_type; + + //To add the vertices only once + for (Vertex_handle vh : vertices_to_insert) { - v0_init = edge.first->vertex(edge.second); - v1_init = edge.first->vertex(edge.third); - - std::vector vertices_to_insert; - c3t3.triangulation().finite_incident_vertices(v0_init, - std::back_inserter(vertices_to_insert)); - vertices_to_insert.push_back(v0_init); - c3t3.triangulation().finite_incident_vertices(v1_init, - std::back_inserter(vertices_to_insert)); - - // create incremental builder - Builder builder(triangulation, true); - builder.begin_triangulation(3); - - collapse_type = _collapse_type; - - //To add the vertices only once - for (Vertex_handle vh : vertices_to_insert) + if (v2v.left.find(vh) == v2v.left.end()) { - if (v2v.left.find(vh) == v2v.left.end()) - { - Vertex_handle new_vh = builder.add_vertex(); - new_vh->set_point(vh->point()); - new_vh->set_dimension(vh->in_dimension()); + Vertex_handle new_vh = builder.add_vertex(); + new_vh->set_point(vh->point()); + new_vh->set_dimension(vh->in_dimension()); - v2v.left.insert(std::make_pair(vh, new_vh)); - } + v2v.left.insert(std::make_pair(vh, new_vh)); } - - std::vector cells_to_insert; - c3t3.triangulation().finite_incident_cells(v0_init, std::back_inserter(cells_to_insert)); - c3t3.triangulation().finite_incident_cells(v1_init, std::back_inserter(cells_to_insert)); - - //To add the cells only once - for (Cell_handle ch : cells_to_insert) - { - if (c2c.left.find(ch) == c2c.left.end()) - { - Cell_handle new_ch = builder.add_cell(v2v.left.at(ch->vertex(0)), v2v.left.at(ch->vertex(1)), - v2v.left.at(ch->vertex(2)), v2v.left.at(ch->vertex(3))); - new_ch->set_subdomain_index(ch->subdomain_index()); - visitor.after_add_cell(ch, new_ch); - - c2c.left.insert(std::make_pair(ch, new_ch)); - } - } - - // finished - builder.end_triangulation(); } - void update() - { - vh0 = v2v.left.at(v0_init); - vh1 = v2v.left.at(v1_init); + std::vector cells_to_insert; + c3t3.triangulation().finite_incident_cells(v0_init, std::back_inserter(cells_to_insert)); + c3t3.triangulation().finite_incident_cells(v1_init, std::back_inserter(cells_to_insert)); - Cell_handle ch; - int i0, i1; - not_an_edge = true; - if (triangulation.is_edge(vh0, vh1, ch, i0, i1)) + //To add the cells only once + for (Cell_handle ch : cells_to_insert) + { + if (c2c.left.find(ch) == c2c.left.end()) { - edge = Edge(ch, i0, i1); - not_an_edge = false; + Cell_handle new_ch = builder.add_cell(v2v.left.at(ch->vertex(0)), v2v.left.at(ch->vertex(1)), + v2v.left.at(ch->vertex(2)), v2v.left.at(ch->vertex(3))); + new_ch->set_subdomain_index(ch->subdomain_index()); + visitor.after_add_cell(ch, new_ch); + + c2c.left.insert(std::make_pair(ch, new_ch)); + } + } + + // finished + builder.end_triangulation(); + } + + void update() + { + vh0 = v2v.left.at(v0_init); + vh1 = v2v.left.at(v1_init); + + Cell_handle ch; + int i0, i1; + not_an_edge = true; + if (triangulation.is_edge(vh0, vh1, ch, i0, i1)) + { + edge = Edge(ch, i0, i1); + not_an_edge = false; + } + + to_remove.clear(); + sharing_neighbor.clear(); + + typedef typename Tr::Cell_circulator Cell_circulator; + Cell_circulator circ = triangulation.incident_cells(edge); + Cell_circulator done = circ; + do + { + to_remove[circ] = true; + if (circ->neighbor(circ->index(vh0))->has_neighbor(circ->neighbor(circ->index(vh1)))) + { + sharing_neighbor[circ->neighbor(circ->index(vh0))] = true; + sharing_neighbor[circ->neighbor(circ->index(vh1))] = true; + } + } while (++circ != done); + + collapsed = false; + } + + Result_type collapse() + { + if (not_an_edge) + { + std::cout << "LocalTriangulation::Not an edge..." << std::endl; + return E_PROBLEM; + } + else + { + Vector_3 v0_new_pos = vec(vh0->point()); + + if (collapse_type == TO_MIDPOINT){ + v0_new_pos = v0_new_pos + 0.5 * Vector_3(point(vh0->point()), point(vh1->point())); + } + else if (collapse_type == TO_V1){ + v0_new_pos = vec(point(vh1->point())); } - to_remove.clear(); - sharing_neighbor.clear(); + boost::unordered_set invalid_cells; typedef typename Tr::Cell_circulator Cell_circulator; Cell_circulator circ = triangulation.incident_cells(edge); Cell_circulator done = circ; - do - { - to_remove[circ] = true; - if (circ->neighbor(circ->index(vh0))->has_neighbor(circ->neighbor(circ->index(vh1)))) - { - sharing_neighbor[circ->neighbor(circ->index(vh0))] = true; - sharing_neighbor[circ->neighbor(circ->index(vh1))] = true; - } - } while (++circ != done); - collapsed = false; - } + std::vector cells_to_remove; - Result_type collapse() - { - if (not_an_edge) - { - std::cout << "LocalTriangulation::Not an edge..." << std::endl; - return E_PROBLEM; - } - else - { - Vector_3 v0_new_pos = vec(vh0->point()); + //Update the vertex before removing it + std::vector find_incident; + triangulation.incident_cells(vh0, std::back_inserter(find_incident)); - if (collapse_type == TO_MIDPOINT){ - v0_new_pos = v0_new_pos + 0.5 * Vector_3(point(vh0->point()), point(vh1->point())); - } - else if (collapse_type == TO_V1){ - v0_new_pos = vec(point(vh1->point())); - } - - boost::unordered_set invalid_cells; - - typedef typename Tr::Cell_circulator Cell_circulator; - Cell_circulator circ = triangulation.incident_cells(edge); - Cell_circulator done = circ; - - std::vector cells_to_remove; - - //Update the vertex before removing it - std::vector find_incident; - triangulation.incident_cells(vh0, std::back_inserter(find_incident)); - - std::vector cells_to_update; - triangulation.incident_cells(vh1, std::back_inserter(cells_to_update)); + std::vector cells_to_update; + triangulation.incident_cells(vh1, std::back_inserter(cells_to_update)); // Result_type r = VALID; - do - { - int v0_id = circ->index(vh0); - int v1_id = circ->index(vh1); + do + { + int v0_id = circ->index(vh0); + int v1_id = circ->index(vh1); - Cell_handle n0_ch = circ->neighbor(v0_id); - Cell_handle n1_ch = circ->neighbor(v1_id); + Cell_handle n0_ch = circ->neighbor(v0_id); + Cell_handle n1_ch = circ->neighbor(v1_id); - int ch_id_in_n0 = n0_ch->index(circ); - int ch_id_in_n1 = n1_ch->index(circ); + int ch_id_in_n0 = n0_ch->index(circ); + int ch_id_in_n1 = n1_ch->index(circ); // if (n0_ch->has_neighbor(n1_ch)) // r = SHARED_NEIGHBOR_PROBLEM; - //Update neighbors before removing cell - n0_ch->set_neighbor(ch_id_in_n0, n1_ch); - n1_ch->set_neighbor(ch_id_in_n1, n0_ch); + //Update neighbors before removing cell + n0_ch->set_neighbor(ch_id_in_n0, n1_ch); + n1_ch->set_neighbor(ch_id_in_n1, n0_ch); - Subdomain_index si_n0 = n0_ch->subdomain_index(); - Subdomain_index si_n1 = n1_ch->subdomain_index(); - Subdomain_index si = circ->subdomain_index(); + Subdomain_index si_n0 = n0_ch->subdomain_index(); + Subdomain_index si_n1 = n1_ch->subdomain_index(); + Subdomain_index si = circ->subdomain_index(); - if (si_n0 != si && si_n1 != si) - return TOPOLOGICAL_PROBLEM; + if (si_n0 != si && si_n1 != si) + return TOPOLOGICAL_PROBLEM; - if ( triangulation.is_infinite(n0_ch->vertex(ch_id_in_n0)) - && triangulation.is_infinite(n1_ch->vertex(ch_id_in_n1))) - return TOPOLOGICAL_PROBLEM; + if ( triangulation.is_infinite(n0_ch->vertex(ch_id_in_n0)) + && triangulation.is_infinite(n1_ch->vertex(ch_id_in_n1))) + return TOPOLOGICAL_PROBLEM; - if ( triangulation.is_infinite(n0_ch) - && triangulation.is_infinite(n1_ch) - && !triangulation.is_infinite(circ)) - return TOPOLOGICAL_PROBLEM; + if ( triangulation.is_infinite(n0_ch) + && triangulation.is_infinite(n1_ch) + && !triangulation.is_infinite(circ)) + return TOPOLOGICAL_PROBLEM; - cells_to_remove.push_back(circ); + cells_to_remove.push_back(circ); - invalid_cells.insert(circ); + invalid_cells.insert(circ); - } while (++circ != done); + } while (++circ != done); - vh0->set_point(Point_3(v0_new_pos.x(), v0_new_pos.y(), v0_new_pos.z())); - vh1->set_point(Point_3(v0_new_pos.x(), v0_new_pos.y(), v0_new_pos.z())); + vh0->set_point(Point_3(v0_new_pos.x(), v0_new_pos.y(), v0_new_pos.z())); + vh1->set_point(Point_3(v0_new_pos.x(), v0_new_pos.y(), v0_new_pos.z())); - Vertex_handle infinite_vertex = triangulation.infinite_vertex(); + Vertex_handle infinite_vertex = triangulation.infinite_vertex(); - bool v0_updated = false; - for (unsigned int i = 0; i < find_incident.size(); i++) + bool v0_updated = false; + for (unsigned int i = 0; i < find_incident.size(); i++) + { + const Cell_handle ch = find_incident[i]; + if (invalid_cells.find(ch) == invalid_cells.end()) //valid cell { - const Cell_handle ch = find_incident[i]; - if (invalid_cells.find(ch) == invalid_cells.end()) //valid cell - { - if (triangulation.is_infinite(ch)) - infinite_vertex->set_cell(ch); - else { + if (triangulation.is_infinite(ch)) + infinite_vertex->set_cell(ch); + else { + vh0->set_cell(ch); + v0_updated = true; + } + } + } + + //Update the vertex before removing it + for (unsigned int i = 0; i < cells_to_update.size(); i++) + { + Cell_handle & ch = cells_to_update[i]; + + if (invalid_cells.find(ch) == invalid_cells.end()) //valid cell + { + ch->set_vertex(ch->index(vh1), vh0); + + if (triangulation.is_infinite(ch)) + infinite_vertex->set_cell(ch); + else { + if (!v0_updated) { vh0->set_cell(ch); v0_updated = true; } } } + } - //Update the vertex before removing it - for (unsigned int i = 0; i < cells_to_update.size(); i++) - { - Cell_handle & ch = cells_to_update[i]; + if (!v0_updated){ + std::cout << "CollapseTriangulation::PB i cell not valid!!!" << std::endl; + return V_PROBLEM; + } + triangulation.tds().delete_vertex(vh1); - if (invalid_cells.find(ch) == invalid_cells.end()) //valid cell - { - ch->set_vertex(ch->index(vh1), vh0); + //Removing cells + for (unsigned int i = 0; i < cells_to_remove.size(); i++){ + triangulation.tds().delete_cell(cells_to_remove[i]); + } - if (triangulation.is_infinite(ch)) - infinite_vertex->set_cell(ch); - else { - if (!v0_updated) { - vh0->set_cell(ch); - v0_updated = true; - } - } - } - } + typedef typename Tr::Finite_cells_iterator Finite_cells_iterator; + for (Finite_cells_iterator cit = triangulation.finite_cells_begin(); + cit != triangulation.finite_cells_end(); ++cit) + { + if (!is_well_oriented(triangulation, cit)) + return ORIENTATION_PROBLEM; + } - if (!v0_updated){ - std::cout << "CollapseTriangulation::PB i cell not valid!!!" << std::endl; + typedef typename Tr::Cell_iterator Cell_iterator; + for (Cell_iterator cit = triangulation.cells_begin(); + cit != triangulation.cells_end(); ++cit) + { + if (!triangulation.tds().is_valid(cit, true)) + return C_PROBLEM; + } + + typedef typename Tr::Vertex_iterator Vertex_iterator; + for (Vertex_iterator vit = triangulation.vertices_begin(); + vit != triangulation.vertices_end(); ++vit) + { + if (!triangulation.tds().is_valid(vit, true)) return V_PROBLEM; - } - triangulation.tds().delete_vertex(vh1); - - //Removing cells - for (unsigned int i = 0; i < cells_to_remove.size(); i++){ - triangulation.tds().delete_cell(cells_to_remove[i]); - } - - typedef typename Tr::Finite_cells_iterator Finite_cells_iterator; - for (Finite_cells_iterator cit = triangulation.finite_cells_begin(); - cit != triangulation.finite_cells_end(); ++cit) - { - if (!is_well_oriented(triangulation, cit)) - return ORIENTATION_PROBLEM; - } - - typedef typename Tr::Cell_iterator Cell_iterator; - for (Cell_iterator cit = triangulation.cells_begin(); - cit != triangulation.cells_end(); ++cit) - { - if (!triangulation.tds().is_valid(cit, true)) - return C_PROBLEM; - } - - typedef typename Tr::Vertex_iterator Vertex_iterator; - for (Vertex_iterator vit = triangulation.vertices_begin(); - vit != triangulation.vertices_end(); ++vit) - { - if (!triangulation.tds().is_valid(vit, true)) - return V_PROBLEM; - } - - //int si_nb_vh0 = nb_incident_subdomains(vh0, c3t3); - //int si_nb_vh1 = nb_incident_subdomains(vh1, c3t3); - //int vertices_subdomain_nb_vh0 = std::max(si_nb_vh0, si_nb_vh1); - //bool is_on_hull_vh0 = is_on_convex_hull(vh0, c3t3) || is_on_convex_hull(vh1, c3t3); - - //if( is_valid_for_domains() ) - return VALID; - - // return TOPOLOGICAL_PROBLEM; } + + //int si_nb_vh0 = nb_incident_subdomains(vh0, c3t3); + //int si_nb_vh1 = nb_incident_subdomains(vh1, c3t3); + //int vertices_subdomain_nb_vh0 = std::max(si_nb_vh0, si_nb_vh1); + //bool is_on_hull_vh0 = is_on_convex_hull(vh0, c3t3) || is_on_convex_hull(vh1, c3t3); + + //if( is_valid_for_domains() ) + return VALID; + + // return TOPOLOGICAL_PROBLEM; } - - protected: - Tr triangulation; - boost::bimap v2v;/*vertex of main tr - vertex of collapse tr*/ - boost::bimap c2c;/*cell of main tr - cell of collapse tr*/ - - boost::unordered_map to_remove; //default is false - boost::unordered_map sharing_neighbor;//default is false - - Collapse_type collapse_type; - - Vertex_handle v0_init; - Vertex_handle v1_init; - - Vertex_handle vh0; - Vertex_handle vh1; - - Edge edge; - - bool collapsed; - bool not_an_edge; - }; - - - - template - Collapse_type get_collapse_type(const typename C3t3::Edge& edge, - const C3t3& c3t3, - CellSelector cell_selector) - { - bool update_v0 = false; - bool update_v1 = false; - get_edge_info(edge, update_v0, update_v1, c3t3, cell_selector); - - if (update_v0 && update_v1) return TO_MIDPOINT; - else if (update_v0) return TO_V1; - else if (update_v1) return TO_V0; - else return IMPOSSIBLE; } - //template - //Edge_type get_edge_type(const typename C3t3::Edge& edge, - // const C3t3& c3t3) - //{ - // typedef typename C3t3::Vertex_handle Vertex_handle; - // typedef typename C3t3::Triangulation::Cell_circulator Cell_circulator; - // typedef typename C3t3::Subdomain_index Subdomain_index; +protected: + Tr triangulation; + boost::bimap v2v;/*vertex of main tr - vertex of collapse tr*/ + boost::bimap c2c;/*cell of main tr - cell of collapse tr*/ - // const Vertex_handle & v0 = edge.first->vertex(edge.second); - // const Vertex_handle & v1 = edge.first->vertex(edge.third); + boost::unordered_map to_remove; //default is false + boost::unordered_map sharing_neighbor;//default is false - // const int dim0 = c3t3.in_dimension(v0); - // const int dim1 = c3t3.in_dimension(v1); + Collapse_type collapse_type; - // const bool is_v0_on_hull = is_on_convex_hull(v0, c3t3); - // const bool is_v1_on_hull = is_on_convex_hull(v1, c3t3); + Vertex_handle v0_init; + Vertex_handle v1_init; - // if (c3t3.is_in_complex(edge)) - // return FEATURE; + Vertex_handle vh0; + Vertex_handle vh1; - // else if (dim0 == 3 && dim1 == 3) - // return INSIDE; + Edge edge; - // else if (dim0 == 2 && dim1 == 2) - // { - // Cell_circulator circ = c3t3.triangulation().incident_cells(edge); - // Cell_circulator done = circ; + bool collapsed; + bool not_an_edge; +}; - // std::vector indices; - // do - // { - // Subdomain_index current_si = circ->subdomain_index(); - // if (std::find(indices.begin(), indices.end(), current_si) == indices.end()) { - // indices.push_back(current_si); - // } - // Subdomain_index si_n0 = circ->neighbor(circ->index(v0))->subdomain_index(); - // Subdomain_index si_n1 = circ->neighbor(circ->index(v1))->subdomain_index(); - // if (si_n0 == si_n1 && si_n0 != current_si) - // return NO_COLLAPSE; +template +Collapse_type get_collapse_type(const typename C3t3::Edge& edge, + const C3t3& c3t3, + CellSelector cell_selector) +{ + bool update_v0 = false; + bool update_v1 = false; + get_edge_info(edge, update_v0, update_v1, c3t3, cell_selector); - // } while (++circ != done); + if (update_v0 && update_v1) return TO_MIDPOINT; + else if (update_v0) return TO_V1; + else if (update_v1) return TO_V0; + else return IMPOSSIBLE; +} - // const std::size_t nb_si_v0 = nb_incident_subdomains(v0, c3t3); - // const std::size_t nb_si_v1 = nb_incident_subdomains(v1, c3t3); +//template +//Edge_type get_edge_type(const typename C3t3::Edge& edge, +// const C3t3& c3t3) +//{ +// typedef typename C3t3::Vertex_handle Vertex_handle; +// typedef typename C3t3::Triangulation::Cell_circulator Cell_circulator; +// typedef typename C3t3::Subdomain_index Subdomain_index; - // if (indices.size() >= (std::min)(nb_si_v0, nb_si_v1)) { - // return BOUNDARY; - // } - // } +// const Vertex_handle & v0 = edge.first->vertex(edge.second); +// const Vertex_handle & v1 = edge.first->vertex(edge.third); - // //std::cerr << "ERROR : get_edge_type did not return anything valid!" << std::endl; - // return NO_COLLAPSE; - //} +// const int dim0 = c3t3.in_dimension(v0); +// const int dim1 = c3t3.in_dimension(v1); - template - bool is_valid_collapse(const typename C3t3::Edge& edge, - const C3t3& c3t3) +// const bool is_v0_on_hull = is_on_convex_hull(v0, c3t3); +// const bool is_v1_on_hull = is_on_convex_hull(v1, c3t3); + +// if (c3t3.is_in_complex(edge)) +// return FEATURE; + +// else if (dim0 == 3 && dim1 == 3) +// return INSIDE; + +// else if (dim0 == 2 && dim1 == 2) +// { +// Cell_circulator circ = c3t3.triangulation().incident_cells(edge); +// Cell_circulator done = circ; + +// std::vector indices; +// do +// { +// Subdomain_index current_si = circ->subdomain_index(); + +// if (std::find(indices.begin(), indices.end(), current_si) == indices.end()) { +// indices.push_back(current_si); +// } + +// Subdomain_index si_n0 = circ->neighbor(circ->index(v0))->subdomain_index(); +// Subdomain_index si_n1 = circ->neighbor(circ->index(v1))->subdomain_index(); +// if (si_n0 == si_n1 && si_n0 != current_si) +// return NO_COLLAPSE; + +// } while (++circ != done); + +// const std::size_t nb_si_v0 = nb_incident_subdomains(v0, c3t3); +// const std::size_t nb_si_v1 = nb_incident_subdomains(v1, c3t3); + +// if (indices.size() >= (std::min)(nb_si_v0, nb_si_v1)) { +// return BOUNDARY; +// } +// } + +// //std::cerr << "ERROR : get_edge_type did not return anything valid!" << std::endl; +// return NO_COLLAPSE; +//} + +template +bool is_valid_collapse(const typename C3t3::Edge& edge, + const C3t3& c3t3) +{ + typedef typename C3t3::Vertex_handle Vertex_handle; + typedef typename C3t3::Cell_handle Cell_handle; + typedef typename C3t3::Triangulation::Cell_circulator Cell_circulator; + + const Vertex_handle v0 = edge.first->vertex(edge.second); + const Vertex_handle v1 = edge.first->vertex(edge.third); + + Cell_circulator circ = c3t3.triangulation().incident_cells(edge); + Cell_circulator done = circ; + do { - typedef typename C3t3::Vertex_handle Vertex_handle; - typedef typename C3t3::Cell_handle Cell_handle; - typedef typename C3t3::Triangulation::Cell_circulator Cell_circulator; + int v0_id = circ->index(v0); + int v1_id = circ->index(v1); - const Vertex_handle v0 = edge.first->vertex(edge.second); - const Vertex_handle v1 = edge.first->vertex(edge.third); + Cell_handle n0_ch = circ->neighbor(v0_id); + Cell_handle n1_ch = circ->neighbor(v1_id); - Cell_circulator circ = c3t3.triangulation().incident_cells(edge); - Cell_circulator done = circ; - do + if (n0_ch->has_vertex(v0) + || n1_ch->has_vertex(v1) + || n0_ch->has_neighbor(n1_ch)) { - int v0_id = circ->index(v0); - int v1_id = circ->index(v1); - - Cell_handle n0_ch = circ->neighbor(v0_id); - Cell_handle n1_ch = circ->neighbor(v1_id); - - if (n0_ch->has_vertex(v0) - || n1_ch->has_vertex(v1) - || n0_ch->has_neighbor(n1_ch)) - { #ifdef CGAL_DEBUG_TET_REMESHING_IN_PLUGIN - if (c3t3.is_in_complex(edge)) - ++nb_invalid_collapse_short; + if (c3t3.is_in_complex(edge)) + ++nb_invalid_collapse_short; #endif - return false; - } + return false; } - while (++circ != done); - - return true; } + while (++circ != done); - template - bool is_valid_collapse(const typename C3t3::Edge& edge, - const Collapse_type& collapse_type, - const typename C3t3::Triangulation::Point& new_pos, - const C3t3& c3t3) - { - typedef typename C3t3::Vertex_handle Vertex_handle; - typedef typename C3t3::Cell_handle Cell_handle; - typedef typename C3t3::Triangulation::Point Point; + return true; +} - const Vertex_handle v0 = edge.first->vertex(edge.second); - const Vertex_handle v1 = edge.first->vertex(edge.third); +template +bool is_valid_collapse(const typename C3t3::Edge& edge, + const Collapse_type& collapse_type, + const typename C3t3::Triangulation::Point& new_pos, + const C3t3& c3t3) +{ + typedef typename C3t3::Vertex_handle Vertex_handle; + typedef typename C3t3::Cell_handle Cell_handle; + typedef typename C3t3::Triangulation::Point Point; + + const Vertex_handle v0 = edge.first->vertex(edge.second); + const Vertex_handle v1 = edge.first->vertex(edge.third); #ifdef CGAL_DEBUG_TET_REMESHING_IN_PLUGIN - const bool in_cx = c3t3.is_in_complex(edge); - if (in_cx) - { - if (collapse_type == TO_MIDPOINT) - nb_test_midpoint++; - else if (collapse_type == TO_V1) - nb_test_v1++; - else - nb_test_v0++; - } + const bool in_cx = c3t3.is_in_complex(edge); + if (in_cx) + { + if (collapse_type == TO_MIDPOINT) + nb_test_midpoint++; + else if (collapse_type == TO_V1) + nb_test_v1++; + else + nb_test_v0++; + } #endif - if (collapse_type == TO_V1 || collapse_type == TO_MIDPOINT) - { - std::vector cells_to_check; - c3t3.triangulation().finite_incident_cells(v0, - std::back_inserter(cells_to_check)); + if (collapse_type == TO_V1 || collapse_type == TO_MIDPOINT) + { + std::vector cells_to_check; + c3t3.triangulation().finite_incident_cells(v0, + std::back_inserter(cells_to_check)); - for (const Cell_handle ch : cells_to_check) + for (const Cell_handle ch : cells_to_check) + { + if (!ch->has_vertex(v1)) { - if (!ch->has_vertex(v1)) + //check orientation + boost::array pts = { ch->vertex(0)->point(), + ch->vertex(1)->point(), + ch->vertex(2)->point(), + ch->vertex(3)->point()}; + pts[ch->index(v0)] = new_pos; + if (CGAL::orientation(point(pts[0]), point(pts[1]), point(pts[2]), point(pts[3])) + != CGAL::POSITIVE) { - //check orientation - boost::array pts = { ch->vertex(0)->point(), - ch->vertex(1)->point(), - ch->vertex(2)->point(), - ch->vertex(3)->point()}; - pts[ch->index(v0)] = new_pos; - if (CGAL::orientation(point(pts[0]), point(pts[1]), point(pts[2]), point(pts[3])) - != CGAL::POSITIVE) +#ifdef CGAL_DEBUG_TET_REMESHING_IN_PLUGIN + if (in_cx) { -#ifdef CGAL_DEBUG_TET_REMESHING_IN_PLUGIN - if (in_cx) - { - if (collapse_type == TO_MIDPOINT) - nb_orientation_midpoint++; - else - nb_orientation_v1++; - } -#endif - return false; + if (collapse_type == TO_MIDPOINT) + nb_orientation_midpoint++; + else + nb_orientation_v1++; } - } - } - } - if (collapse_type == TO_V0 || collapse_type == TO_MIDPOINT) - { - std::vector cells_to_check; - c3t3.triangulation().finite_incident_cells(v1, - std::back_inserter(cells_to_check)); - - for (const Cell_handle ch : cells_to_check) - { - if (!ch->has_vertex(v0)) - { - //check orientation - boost::array pts = { ch->vertex(0)->point(), - ch->vertex(1)->point(), - ch->vertex(2)->point(), - ch->vertex(3)->point() }; - pts[ch->index(v1)] = new_pos; - if (CGAL::orientation(point(pts[0]), point(pts[1]), point(pts[2]), point(pts[3])) - != CGAL::POSITIVE) - { -#ifdef CGAL_DEBUG_TET_REMESHING_IN_PLUGIN - if (in_cx) - { - if (collapse_type == TO_MIDPOINT) - nb_orientation_midpoint++; - else - nb_orientation_v0++; - } #endif - return false; - } - } - } - } - - return is_valid_collapse(edge, c3t3); - } - - template - bool are_edge_lengths_valid(const typename C3t3::Edge& edge, - const C3t3& c3t3, - const typename C3t3::Triangulation::Point& new_pos, - const typename C3t3::Triangulation::Geom_traits::FT& sqhigh, - const CellSelector& cell_selector, - const bool /* adaptive */ = false) - { - //SqLengthMap::key_type is Vertex_handle - //SqLengthMap::value_type is double - typedef typename C3t3::Triangulation::Geom_traits::FT FT; - typedef typename C3t3::Edge Edge; - typedef typename C3t3::Vertex_handle Vertex_handle; - - const Vertex_handle v1 = edge.first->vertex(edge.second); - const Vertex_handle v2 = edge.first->vertex(edge.third); - - boost::unordered_map edges_sqlength_after_collapse; - - std::vector inc_edges; - c3t3.triangulation().finite_incident_edges(v1, - std::back_inserter(inc_edges)); - c3t3.triangulation().finite_incident_edges(v2, - std::back_inserter(inc_edges)); - - for (const Edge& ei : inc_edges) - { - if (is_outside(ei, c3t3, cell_selector)) - continue; - - Vertex_handle vh = ei.first->vertex(ei.second); - if (vh == v1 || vh == v2) - vh = ei.first->vertex(ei.third); - if (vh == v1 || vh == v2) - continue; - - if (edges_sqlength_after_collapse.find(vh) == edges_sqlength_after_collapse.end()) - { - const FT sqlen = CGAL::squared_distance(new_pos, point(vh->point())); - - //if (adaptive){ - // if (is_boundary_edge(ei) || is_hull_edge(ei)){ - // if (sqlen_i > split_length) - // return false; - // } - // else if (sqlen_i > 4.*getAimedLength(ei, aimed_length) / 3.){// && is_in_complex(ei) ){ - // return false; - // } - //} - //else { - - if (sqlen > sqhigh) { return false; } - //} - edges_sqlength_after_collapse[vh] = sqlen; } } - - return true; } - - template - void merge_surface_patch_indices(const typename C3t3::Facet& f1, - const typename C3t3::Facet& f2, - C3t3& c3t3) + if (collapse_type == TO_V0 || collapse_type == TO_MIDPOINT) { - const bool in_cx_f1 = c3t3.is_in_complex(f1); - const bool in_cx_f2 = c3t3.is_in_complex(f2); + std::vector cells_to_check; + c3t3.triangulation().finite_incident_cells(v1, + std::back_inserter(cells_to_check)); - if (in_cx_f1 && !in_cx_f2) + for (const Cell_handle ch : cells_to_check) { - typename C3t3::Surface_patch_index patch = c3t3.surface_patch_index(f1); - c3t3.remove_from_complex(f1); - c3t3.add_to_complex(f1, patch); - c3t3.add_to_complex(f2, patch); - } - else if (in_cx_f2 && !in_cx_f1) - { - typename C3t3::Surface_patch_index patch = c3t3.surface_patch_index(f2); - c3t3.remove_from_complex(f2); - c3t3.add_to_complex(f1, patch); - c3t3.add_to_complex(f2, patch); - } - else - { - CGAL_assertion( - //f1 and f2 are not both in complex - !(in_cx_f1 && in_cx_f2) - // unless they are on the same surface - || c3t3.surface_patch_index(f1) == c3t3.surface_patch_index(f2)); + if (!ch->has_vertex(v0)) + { + //check orientation + boost::array pts = { ch->vertex(0)->point(), + ch->vertex(1)->point(), + ch->vertex(2)->point(), + ch->vertex(3)->point() }; + pts[ch->index(v1)] = new_pos; + if (CGAL::orientation(point(pts[0]), point(pts[1]), point(pts[2]), point(pts[3])) + != CGAL::POSITIVE) + { +#ifdef CGAL_DEBUG_TET_REMESHING_IN_PLUGIN + if (in_cx) + { + if (collapse_type == TO_MIDPOINT) + nb_orientation_midpoint++; + else + nb_orientation_v0++; + } +#endif + return false; + } + } } } - template - typename C3t3::Vertex_handle - collapse(const typename C3t3::Cell_handle ch, - const int to, const int from, - C3t3& c3t3) + return is_valid_collapse(edge, c3t3); +} + +template +bool are_edge_lengths_valid(const typename C3t3::Edge& edge, + const C3t3& c3t3, + const typename C3t3::Triangulation::Point& new_pos, + const typename C3t3::Triangulation::Geom_traits::FT& sqhigh, + const CellSelector& cell_selector, + const bool /* adaptive */ = false) +{ + //SqLengthMap::key_type is Vertex_handle + //SqLengthMap::value_type is double + typedef typename C3t3::Triangulation::Geom_traits::FT FT; + typedef typename C3t3::Edge Edge; + typedef typename C3t3::Vertex_handle Vertex_handle; + + const Vertex_handle v1 = edge.first->vertex(edge.second); + const Vertex_handle v2 = edge.first->vertex(edge.third); + + boost::unordered_map edges_sqlength_after_collapse; + + std::vector inc_edges; + c3t3.triangulation().finite_incident_edges(v1, + std::back_inserter(inc_edges)); + c3t3.triangulation().finite_incident_edges(v2, + std::back_inserter(inc_edges)); + + for (const Edge& ei : inc_edges) { - typedef typename C3t3::Triangulation Tr; - typedef typename C3t3::Vertex_handle Vertex_handle; - typedef typename C3t3::Cell_handle Cell_handle; - typedef typename C3t3::Facet Facet; - typedef typename Tr::Cell_circulator Cell_circulator; + if (is_outside(ei, c3t3, cell_selector)) + continue; - Tr& tr = c3t3.triangulation(); + Vertex_handle vh = ei.first->vertex(ei.second); + if (vh == v1 || vh == v2) + vh = ei.first->vertex(ei.third); + if (vh == v1 || vh == v2) + continue; - Vertex_handle vh0 = ch->vertex(to); - Vertex_handle vh1 = ch->vertex(from); + if (edges_sqlength_after_collapse.find(vh) == edges_sqlength_after_collapse.end()) + { + const FT sqlen = CGAL::squared_distance(new_pos, point(vh->point())); - std::vector cells_to_remove; + //if (adaptive){ + // if (is_boundary_edge(ei) || is_hull_edge(ei)){ + // if (sqlen_i > split_length) + // return false; + // } + // else if (sqlen_i > 4.*getAimedLength(ei, aimed_length) / 3.){// && is_in_complex(ei) ){ + // return false; + // } + //} + //else { - //Update the vertex before removing it - std::vector find_incident; - tr.incident_cells(vh0, std::back_inserter(find_incident)); + if (sqlen > sqhigh) { + return false; + } + //} + edges_sqlength_after_collapse[vh] = sqlen; + } + } - std::vector cells_to_update; - tr.incident_cells(vh1, std::back_inserter(cells_to_update)); + return true; +} + +template +void merge_surface_patch_indices(const typename C3t3::Facet& f1, + const typename C3t3::Facet& f2, + C3t3& c3t3) +{ + const bool in_cx_f1 = c3t3.is_in_complex(f1); + const bool in_cx_f2 = c3t3.is_in_complex(f2); + + if (in_cx_f1 && !in_cx_f2) + { + typename C3t3::Surface_patch_index patch = c3t3.surface_patch_index(f1); + c3t3.remove_from_complex(f1); + c3t3.add_to_complex(f1, patch); + c3t3.add_to_complex(f2, patch); + } + else if (in_cx_f2 && !in_cx_f1) + { + typename C3t3::Surface_patch_index patch = c3t3.surface_patch_index(f2); + c3t3.remove_from_complex(f2); + c3t3.add_to_complex(f1, patch); + c3t3.add_to_complex(f2, patch); + } + else + { + CGAL_assertion( + //f1 and f2 are not both in complex + !(in_cx_f1 && in_cx_f2) + // unless they are on the same surface + || c3t3.surface_patch_index(f1) == c3t3.surface_patch_index(f2)); + } +} + +template +typename C3t3::Vertex_handle +collapse(const typename C3t3::Cell_handle ch, + const int to, const int from, + C3t3& c3t3) +{ + typedef typename C3t3::Triangulation Tr; + typedef typename C3t3::Vertex_handle Vertex_handle; + typedef typename C3t3::Cell_handle Cell_handle; + typedef typename C3t3::Facet Facet; + typedef typename Tr::Cell_circulator Cell_circulator; + + Tr& tr = c3t3.triangulation(); + + Vertex_handle vh0 = ch->vertex(to); + Vertex_handle vh1 = ch->vertex(from); + + std::vector cells_to_remove; + + //Update the vertex before removing it + std::vector find_incident; + tr.incident_cells(vh0, std::back_inserter(find_incident)); + + std::vector cells_to_update; + tr.incident_cells(vh1, std::back_inserter(cells_to_update)); // if (vh1->in_dimension() == 2 && c3t3.is_in_complex(vh1)) // std::cout << "Collapsing a feature vertex!!!!!!" << std::endl; - boost::unordered_set invalid_cells; - bool valid = true; - Cell_circulator circ = tr.incident_cells(ch, to, from); - Cell_circulator done = circ; - do + boost::unordered_set invalid_cells; + bool valid = true; + Cell_circulator circ = tr.incident_cells(ch, to, from); + Cell_circulator done = circ; + do + { + const int v0_id = circ->index(vh0); + const int v1_id = circ->index(vh1); + + Cell_handle n0_ch = circ->neighbor(v0_id); + Cell_handle n1_ch = circ->neighbor(v1_id); + + const int ch_id_in_n0 = n0_ch->index(circ); + const int ch_id_in_n1 = n1_ch->index(circ); + + //Merge surface patch indices + merge_surface_patch_indices(Facet(n0_ch, ch_id_in_n0), + Facet(n1_ch, ch_id_in_n1), + c3t3); + + //Update neighbors before removing cell + n0_ch->set_neighbor(ch_id_in_n0, n1_ch); + n1_ch->set_neighbor(ch_id_in_n1, n0_ch); + + //Update vertices cell pointer + //if( !triangulation.is_infinite( n0_ch ) ) + int nb_on_boundary_n0 = 0; + for (int i = 0; i < 3; i++) { - const int v0_id = circ->index(vh0); - const int v1_id = circ->index(vh1); - - Cell_handle n0_ch = circ->neighbor(v0_id); - Cell_handle n1_ch = circ->neighbor(v1_id); - - const int ch_id_in_n0 = n0_ch->index(circ); - const int ch_id_in_n1 = n1_ch->index(circ); - - //Merge surface patch indices - merge_surface_patch_indices(Facet(n0_ch, ch_id_in_n0), - Facet(n1_ch, ch_id_in_n1), - c3t3); - - //Update neighbors before removing cell - n0_ch->set_neighbor(ch_id_in_n0, n1_ch); - n1_ch->set_neighbor(ch_id_in_n1, n0_ch); - - //Update vertices cell pointer - //if( !triangulation.is_infinite( n0_ch ) ) - int nb_on_boundary_n0 = 0; - for (int i = 0; i < 3; i++) - { - int vid = Tr::vertex_triple_index(ch_id_in_n0, i); - n0_ch->vertex(vid)->set_cell(n0_ch); - if (c3t3.in_dimension(n0_ch->vertex(vid))) - nb_on_boundary_n0++; - } - //else - int nb_on_boundary_n1 = 0; - for (int i = 0; i < 3; i++) - { - int vid = Tr::vertex_triple_index(ch_id_in_n1, i); - n1_ch->vertex(vid)->set_cell(n1_ch); - if (c3t3.in_dimension(n1_ch->vertex(vid))) - nb_on_boundary_n1++; - } - - if ( tr.is_infinite(n0_ch->vertex(ch_id_in_n0)) - && tr.is_infinite(n1_ch->vertex(ch_id_in_n1))) - return Vertex_handle(); - - cells_to_remove.push_back(circ); - - invalid_cells.insert(circ); - - } while (++circ != done); - - const Vertex_handle infinite_vertex = tr.infinite_vertex(); - - bool v0_updated = false; - for (const Cell_handle ch : find_incident) + int vid = Tr::vertex_triple_index(ch_id_in_n0, i); + n0_ch->vertex(vid)->set_cell(n0_ch); + if (c3t3.in_dimension(n0_ch->vertex(vid))) + nb_on_boundary_n0++; + } + //else + int nb_on_boundary_n1 = 0; + for (int i = 0; i < 3; i++) { - if (invalid_cells.find(ch) == invalid_cells.end())//valid cell + int vid = Tr::vertex_triple_index(ch_id_in_n1, i); + n1_ch->vertex(vid)->set_cell(n1_ch); + if (c3t3.in_dimension(n1_ch->vertex(vid))) + nb_on_boundary_n1++; + } + + if ( tr.is_infinite(n0_ch->vertex(ch_id_in_n0)) + && tr.is_infinite(n1_ch->vertex(ch_id_in_n1))) + return Vertex_handle(); + + cells_to_remove.push_back(circ); + + invalid_cells.insert(circ); + + } while (++circ != done); + + const Vertex_handle infinite_vertex = tr.infinite_vertex(); + + bool v0_updated = false; + for (const Cell_handle ch : find_incident) + { + if (invalid_cells.find(ch) == invalid_cells.end())//valid cell + { + if (tr.is_infinite(ch)) + infinite_vertex->set_cell(ch); + //else { + vh0->set_cell(ch); + v0_updated = true; + //} + } + } + + // update complex edges + const std::array, 6> edges + = { 0,1, 0,2, 0,3, 1,2, 1,3, 2,3 }; //vertex indices in cells + const Vertex_handle vkept = vh0; + const Vertex_handle vdeleted = vh1; + for (const Cell_handle ch : cells_to_update) + { + for (const std::array& ei : edges) + { + Vertex_handle eiv0 = ch->vertex(ei[0]); + Vertex_handle eiv1 = ch->vertex(ei[1]); + if (eiv1 == vdeleted && eiv0 != vkept) //replace eiv1 by vkept { - if (tr.is_infinite(ch)) - infinite_vertex->set_cell(ch); - //else { + if (c3t3.is_in_complex(eiv0, eiv1)) + { + c3t3.add_to_complex(eiv0, vkept, c3t3.curve_index(eiv0, eiv1)); + c3t3.remove_from_complex(eiv0, eiv1); + } + } + else if (eiv0 == vdeleted && eiv1 != vkept) //replace eiv0 by vkept + { + if (c3t3.is_in_complex(eiv0, eiv1)) + { + c3t3.add_to_complex(vkept, eiv1, c3t3.curve_index(eiv0, eiv1)); + c3t3.remove_from_complex(eiv0, eiv1); + } + } + } + } + + //Update the vertex before removing it + for (const Cell_handle ch : cells_to_update) + { + if (invalid_cells.find(ch) == invalid_cells.end()) //valid cell + { + ch->set_vertex(ch->index(vh1), vh0); + + if (tr.is_infinite(ch)) + infinite_vertex->set_cell(ch); + //else { + if (!v0_updated) { vh0->set_cell(ch); v0_updated = true; - //} } + //} } - - // update complex edges - const std::array, 6> edges - = { 0,1, 0,2, 0,3, 1,2, 1,3, 2,3 }; //vertex indices in cells - const Vertex_handle vkept = vh0; - const Vertex_handle vdeleted = vh1; - for (const Cell_handle ch : cells_to_update) - { - for (const std::array& ei : edges) - { - Vertex_handle eiv0 = ch->vertex(ei[0]); - Vertex_handle eiv1 = ch->vertex(ei[1]); - if (eiv1 == vdeleted && eiv0 != vkept) //replace eiv1 by vkept - { - if (c3t3.is_in_complex(eiv0, eiv1)) - { - c3t3.add_to_complex(eiv0, vkept, c3t3.curve_index(eiv0, eiv1)); - c3t3.remove_from_complex(eiv0, eiv1); - } - } - else if (eiv0 == vdeleted && eiv1 != vkept) //replace eiv0 by vkept - { - if (c3t3.is_in_complex(eiv0, eiv1)) - { - c3t3.add_to_complex(vkept, eiv1, c3t3.curve_index(eiv0, eiv1)); - c3t3.remove_from_complex(eiv0, eiv1); - } - } - } - } - - //Update the vertex before removing it - for (const Cell_handle ch : cells_to_update) - { - if (invalid_cells.find(ch) == invalid_cells.end()) //valid cell - { - ch->set_vertex(ch->index(vh1), vh0); - - if (tr.is_infinite(ch)) - infinite_vertex->set_cell(ch); - //else { - if (!v0_updated) { - vh0->set_cell(ch); - v0_updated = true; - } - //} - } - } - - if (!v0_updated) - std::cout << "PB i cell not valid!!!" << std::endl; - - // Delete vertex - c3t3.triangulation().tds().delete_vertex(vh1); - - // Delete cells - for (Cell_handle cell_to_remove : cells_to_remove) - { - // remove cell - if (cell_to_remove->subdomain_index() > 0) - c3t3.remove_from_complex(cell_to_remove); - - c3t3.triangulation().tds().delete_cell(cell_to_remove); - } - - if (!valid){ - std::cout << "Global triangulation collapse bug!!" << std::endl; - return Vertex_handle(); - } - - return vh0; } + if (!v0_updated) + std::cout << "PB i cell not valid!!!" << std::endl; - template - typename C3t3::Vertex_handle collapse(typename C3t3::Edge& edge, - const Collapse_type& collapse_type, - C3t3& c3t3) + // Delete vertex + c3t3.triangulation().tds().delete_vertex(vh1); + + // Delete cells + for (Cell_handle cell_to_remove : cells_to_remove) { - typedef typename C3t3::Vertex_handle Vertex_handle; - typedef typename C3t3::Triangulation::Point Point_3; + // remove cell + if (cell_to_remove->subdomain_index() > 0) + c3t3.remove_from_complex(cell_to_remove); - Vertex_handle vh0 = edge.first->vertex(edge.second); - Vertex_handle vh1 = edge.first->vertex(edge.third); + c3t3.triangulation().tds().delete_cell(cell_to_remove); + } - const int dim_vh0 = c3t3.in_dimension(vh0); - const int dim_vh1 = c3t3.in_dimension(vh1); + if (!valid){ + std::cout << "Global triangulation collapse bug!!" << std::endl; + return Vertex_handle(); + } - Vertex_handle vh = Vertex_handle(); + return vh0; +} - const Point_3 p0 = vh0->point(); - const Point_3 p1 = vh1->point(); - //Collapse at mid point - if (collapse_type == TO_MIDPOINT) +template +typename C3t3::Vertex_handle collapse(typename C3t3::Edge& edge, + const Collapse_type& collapse_type, + C3t3& c3t3) +{ + typedef typename C3t3::Vertex_handle Vertex_handle; + typedef typename C3t3::Triangulation::Point Point_3; + + Vertex_handle vh0 = edge.first->vertex(edge.second); + Vertex_handle vh1 = edge.first->vertex(edge.third); + + const int dim_vh0 = c3t3.in_dimension(vh0); + const int dim_vh1 = c3t3.in_dimension(vh1); + + Vertex_handle vh = Vertex_handle(); + + const Point_3 p0 = vh0->point(); + const Point_3 p1 = vh1->point(); + + //Collapse at mid point + if (collapse_type == TO_MIDPOINT) + { + Point_3 new_position(CGAL::midpoint(point(vh0->point()), point(vh1->point()))); + vh0->set_point(new_position); + vh1->set_point(new_position); + + vh = collapse(edge.first, edge.second, edge.third, c3t3); + c3t3.set_dimension(vh, (std::min)(dim_vh0, dim_vh1)); + } + else //Collapse at vertex + { + if (collapse_type == TO_V1) { - Point_3 new_position(CGAL::midpoint(point(vh0->point()), point(vh1->point()))); - vh0->set_point(new_position); - vh1->set_point(new_position); - - vh = collapse(edge.first, edge.second, edge.third, c3t3); + vh0->set_point(p1); + vh = collapse(edge.first, edge.third, edge.second, c3t3); c3t3.set_dimension(vh, (std::min)(dim_vh0, dim_vh1)); } - else //Collapse at vertex + else //Collapse at v0 { - if (collapse_type == TO_V1) + if (collapse_type == TO_V0) { - vh0->set_point(p1); - vh = collapse(edge.first, edge.third, edge.second, c3t3); + vh1->set_point(p0); + vh = collapse(edge.first, edge.second, edge.third, c3t3); c3t3.set_dimension(vh, (std::min)(dim_vh0, dim_vh1)); } - else //Collapse at v0 - { - if (collapse_type == TO_V0) - { - vh1->set_point(p0); - vh = collapse(edge.first, edge.second, edge.third, c3t3); - c3t3.set_dimension(vh, (std::min)(dim_vh0, dim_vh1)); - } - else - CGAL_assertion(false); - } + else + CGAL_assertion(false); } - return vh; + } + return vh; +} + +template +typename C3t3::Vertex_handle collapse_edge(typename C3t3::Edge& edge, + C3t3& c3t3, + const typename C3t3::Triangulation::Geom_traits::FT& sqhigh, + const bool /* protect_boundaries */, + CellSelector cell_selector, + Visitor& visitor) +{ + typedef typename C3t3::Triangulation Tr; + typedef typename Tr::Point Point; + typedef typename Tr::Vertex_handle Vertex_handle; + + const Vertex_handle v0 = edge.first->vertex(edge.second); + const Vertex_handle v1 = edge.first->vertex(edge.third); + + Collapse_type collapse_type = get_collapse_type(edge, c3t3, cell_selector); + +#ifdef CGAL_DEBUG_TET_REMESHING_IN_PLUGIN + const bool in_cx = c3t3.is_in_complex(edge); + if (in_cx && collapse_type == IMPOSSIBLE) + nb_impossible++; +#endif + + if (collapse_type == IMPOSSIBLE) + return Vertex_handle(); + + Point new_pos; + switch(collapse_type) + { + case TO_V0: + new_pos = v0->point(); break; + case TO_V1: + new_pos = v1->point(); break; + default: + CGAL_assertion(collapse_type == TO_MIDPOINT); + new_pos = Point(CGAL::midpoint(point(v0->point()), point(v1->point()))); } - template - typename C3t3::Vertex_handle collapse_edge(typename C3t3::Edge& edge, - C3t3& c3t3, - const typename C3t3::Triangulation::Geom_traits::FT& sqhigh, - const bool /* protect_boundaries */, - CellSelector cell_selector, - Visitor& visitor) + if (!is_valid_collapse(edge, collapse_type, new_pos, c3t3)) { - typedef typename C3t3::Triangulation Tr; - typedef typename Tr::Point Point; - typedef typename Tr::Vertex_handle Vertex_handle; - - const Vertex_handle v0 = edge.first->vertex(edge.second); - const Vertex_handle v1 = edge.first->vertex(edge.third); - - Collapse_type collapse_type = get_collapse_type(edge, c3t3, cell_selector); - -#ifdef CGAL_DEBUG_TET_REMESHING_IN_PLUGIN - const bool in_cx = c3t3.is_in_complex(edge); - if (in_cx && collapse_type == IMPOSSIBLE) - nb_impossible++; -#endif - - if (collapse_type == IMPOSSIBLE) - return Vertex_handle(); - - Point new_pos; - switch(collapse_type) - { - case TO_V0: - new_pos = v0->point(); break; - case TO_V1: - new_pos = v1->point(); break; - default: - CGAL_assertion(collapse_type == TO_MIDPOINT); - new_pos = Point(CGAL::midpoint(point(v0->point()), point(v1->point()))); - } - - if (!is_valid_collapse(edge, collapse_type, new_pos, c3t3)) - { #ifdef TET_REMESHING_COLLAPSE_FALLBACK_EXPERIMENTS - if (collapse_type == TO_MIDPOINT) + if (collapse_type == TO_MIDPOINT) + { + // with TO_MIDPOINT, we are authorized to test TO_V0 and TO_V1 + if (is_valid_collapse(edge, TO_V0, v0->point(), c3t3)) { - // with TO_MIDPOINT, we are authorized to test TO_V0 and TO_V1 - if (is_valid_collapse(edge, TO_V0, v0->point(), c3t3)) - { - collapse_type = TO_V0; - new_pos = v0->point(); - } - else if (is_valid_collapse(edge, TO_V1, v1->point(), c3t3)) - { - collapse_type = TO_V1; - new_pos = v1->point(); - } - else - { -#ifdef CGAL_DEBUG_TET_REMESHING_IN_PLUGIN - if (in_cx) - nb_invalid_collapse++; -#endif - return Vertex_handle(); - } + collapse_type = TO_V0; + new_pos = v0->point(); + } + else if (is_valid_collapse(edge, TO_V1, v1->point(), c3t3)) + { + collapse_type = TO_V1; + new_pos = v1->point(); } else -#endif //TET_REMESHING_COLLAPSE_FALLBACK_EXPERIMENTS { #ifdef CGAL_DEBUG_TET_REMESHING_IN_PLUGIN if (in_cx) @@ -925,195 +915,205 @@ namespace internal return Vertex_handle(); } } - - if (are_edge_lengths_valid(edge, c3t3, new_pos, sqhigh, cell_selector/*, adaptive = false*/)) + else +#endif //TET_REMESHING_COLLAPSE_FALLBACK_EXPERIMENTS { - CollapseTriangulation local_tri(c3t3, edge, collapse_type, visitor); - local_tri.update(); - - Result_type res = local_tri.collapse(); - if (res == VALID) - { #ifdef CGAL_DEBUG_TET_REMESHING_IN_PLUGIN - if (in_cx) - nb_valid_collapse++; + if (in_cx) + nb_invalid_collapse++; #endif - return collapse(edge, collapse_type, c3t3); - } + return Vertex_handle(); } -#ifdef CGAL_DEBUG_TET_REMESHING_IN_PLUGIN - else if (in_cx) - nb_invalid_lengths++; -#endif - return Vertex_handle(); } - template - bool can_be_collapsed(const typename C3T3::Edge& e, - const C3T3& c3t3, - const bool protect_boundaries, - CellSelector cell_selector) + if (are_edge_lengths_valid(edge, c3t3, new_pos, sqhigh, cell_selector/*, adaptive = false*/)) { - if (is_outside(e, c3t3, cell_selector)) + CollapseTriangulation local_tri(c3t3, edge, collapse_type, visitor); + local_tri.update(); + + Result_type res = local_tri.collapse(); + if (res == VALID) + { +#ifdef CGAL_DEBUG_TET_REMESHING_IN_PLUGIN + if (in_cx) + nb_valid_collapse++; +#endif + return collapse(edge, collapse_type, c3t3); + } + } +#ifdef CGAL_DEBUG_TET_REMESHING_IN_PLUGIN + else if (in_cx) + nb_invalid_lengths++; +#endif + return Vertex_handle(); +} + +template +bool can_be_collapsed(const typename C3T3::Edge& e, + const C3T3& c3t3, + const bool protect_boundaries, + CellSelector cell_selector) +{ + if (is_outside(e, c3t3, cell_selector)) + return false; + + if (protect_boundaries) + { + if (c3t3.is_in_complex(e)) + return false; + else if (is_boundary(c3t3, e, cell_selector)) return false; - if (protect_boundaries) - { - if (c3t3.is_in_complex(e)) - return false; - else if (is_boundary(c3t3, e, cell_selector)) - return false; - #ifdef CGAL_TETRAHEDRAL_REMESHING_DEBUG - if (!is_internal(e, c3t3, cell_selector)) - { - std::cerr << "e is not inside!?" << std::endl; - typename C3T3::Vertex_handle v1 = e.first->vertex(e.second); - typename C3T3::Vertex_handle v2 = e.first->vertex(e.third); - std::cerr << v1->point() << " " << v2->point() << std::endl; - } + if (!is_internal(e, c3t3, cell_selector)) + { + std::cerr << "e is not inside!?" << std::endl; + typename C3T3::Vertex_handle v1 = e.first->vertex(e.second); + typename C3T3::Vertex_handle v2 = e.first->vertex(e.third); + std::cerr << v1->point() << " " << v2->point() << std::endl; + } #endif - CGAL_assertion(is_internal(e, c3t3, cell_selector)); - return true; - } - else - { - return true; - } + CGAL_assertion(is_internal(e, c3t3, cell_selector)); + return true; } - - template - void collapse_short_edges(C3T3& c3t3, - const typename C3T3::Triangulation::Geom_traits::FT& low, - const typename C3T3::Triangulation::Geom_traits::FT& high, - const bool protect_boundaries, - CellSelector cell_selector, - Visitor& visitor) + else { - typedef typename C3T3::Triangulation T3; - typedef typename T3::Cell_handle Cell_handle; - typedef typename T3::Edge Edge; - typedef typename T3::Finite_edges_iterator Finite_edges_iterator; - typedef typename T3::Vertex_handle Vertex_handle; - typedef typename std::pair Edge_vv; + return true; + } +} - typedef typename T3::Geom_traits Gt; - typedef typename T3::Geom_traits::FT FT; - typedef boost::bimap< - boost::bimaps::set_of, - boost::bimaps::multiset_of > > Boost_bimap; - typedef typename Boost_bimap::value_type short_edge; +template +void collapse_short_edges(C3T3& c3t3, + const typename C3T3::Triangulation::Geom_traits::FT& low, + const typename C3T3::Triangulation::Geom_traits::FT& high, + const bool protect_boundaries, + CellSelector cell_selector, + Visitor& visitor) +{ + typedef typename C3T3::Triangulation T3; + typedef typename T3::Cell_handle Cell_handle; + typedef typename T3::Edge Edge; + typedef typename T3::Finite_edges_iterator Finite_edges_iterator; + typedef typename T3::Vertex_handle Vertex_handle; + typedef typename std::pair Edge_vv; - T3& tr = c3t3.triangulation(); - typename Gt::Compute_squared_length_3 sql - = tr.geom_traits().compute_squared_length_3_object(); + typedef typename T3::Geom_traits Gt; + typedef typename T3::Geom_traits::FT FT; + typedef boost::bimap< + boost::bimaps::set_of, + boost::bimaps::multiset_of > > Boost_bimap; + typedef typename Boost_bimap::value_type short_edge; + + T3& tr = c3t3.triangulation(); + typename Gt::Compute_squared_length_3 sql + = tr.geom_traits().compute_squared_length_3_object(); #ifdef CGAL_TETRAHEDRAL_REMESHING_VERBOSE - std::cout << "Collapse short edges (" << low << ", " << high << ")..."; - std::cout.flush(); - std::size_t nb_collapses = 0; + std::cout << "Collapse short edges (" << low << ", " << high << ")..."; + std::cout.flush(); + std::size_t nb_collapses = 0; #endif - const FT sq_low = low*low; - const FT sq_high = high*high; + const FT sq_low = low*low; + const FT sq_high = high*high; - //collect long edges - Boost_bimap short_edges; - for (Finite_edges_iterator eit = tr.finite_edges_begin(); - eit != tr.finite_edges_end(); ++eit) - { - const Edge& e = *eit; - if (!can_be_collapsed(e, c3t3, protect_boundaries, cell_selector)) - continue; + //collect long edges + Boost_bimap short_edges; + for (Finite_edges_iterator eit = tr.finite_edges_begin(); + eit != tr.finite_edges_end(); ++eit) + { + const Edge& e = *eit; + if (!can_be_collapsed(e, c3t3, protect_boundaries, cell_selector)) + continue; - FT sqlen = sql(tr.segment(e)); - if (sqlen < sq_low) - short_edges.insert(short_edge(make_vertex_pair(e), sqlen)); - } + FT sqlen = sql(tr.segment(e)); + if (sqlen < sq_low) + short_edges.insert(short_edge(make_vertex_pair(e), sqlen)); + } #ifdef CGAL_TETRAHEDRAL_REMESHING_DEBUG - debug::dump_edges(short_edges, "short_edges.polylines.txt"); + debug::dump_edges(short_edges, "short_edges.polylines.txt"); - std::ofstream short_success("short_collapse_success.polylines.txt"); - std::ofstream short_fail("short_collapse_fail.polylines.txt"); - std::ofstream short_cancel("short_collapse_canceled.polylines.txt"); + std::ofstream short_success("short_collapse_success.polylines.txt"); + std::ofstream short_fail("short_collapse_fail.polylines.txt"); + std::ofstream short_cancel("short_collapse_canceled.polylines.txt"); #endif - while(!short_edges.empty()) - { - //the edge with shortest length - typename Boost_bimap::right_map::iterator eit = short_edges.right.begin(); - Edge_vv e = eit->second; - short_edges.right.erase(eit); + while(!short_edges.empty()) + { + //the edge with shortest length + typename Boost_bimap::right_map::iterator eit = short_edges.right.begin(); + Edge_vv e = eit->second; + short_edges.right.erase(eit); #ifdef CGAL_TETRAHEDRAL_REMESHING_VERBOSE_PROGRESS - FT sqlen = eit->first; - std::cout << "\rCollapse... (" << short_edges.left.size() << " short edges, "; - std::cout << std::sqrt(sqlen) << ", "; - std::cout << nb_collapses << " collapses)"; - std::cout.flush(); + FT sqlen = eit->first; + std::cout << "\rCollapse... (" << short_edges.left.size() << " short edges, "; + std::cout << std::sqrt(sqlen) << ", "; + std::cout << nb_collapses << " collapses)"; + std::cout.flush(); #endif - Cell_handle cell; - int i1, i2; - if ( tr.tds().is_vertex(e.first) - && tr.tds().is_vertex(e.second) - && tr.tds().is_edge(e.first, e.second, cell, i1, i2) - && tr.segment(Edge(cell, i1, i2)).squared_length() < sq_low) + Cell_handle cell; + int i1, i2; + if ( tr.tds().is_vertex(e.first) + && tr.tds().is_vertex(e.second) + && tr.tds().is_edge(e.first, e.second, cell, i1, i2) + && tr.segment(Edge(cell, i1, i2)).squared_length() < sq_low) + { +#ifdef CGAL_TETRAHEDRAL_REMESHING_DEBUG + const typename T3::Point p1 = e.first->point(); + const typename T3::Point p2 = e.second->point(); +#endif + + Edge edge(cell, i1, i2); + + if (!can_be_collapsed(edge, c3t3, protect_boundaries, cell_selector)) { #ifdef CGAL_TETRAHEDRAL_REMESHING_DEBUG - const typename T3::Point p1 = e.first->point(); - const typename T3::Point p2 = e.second->point(); + short_cancel << "2 " << point(p1) << " " << point(p2) << std::endl; #endif + continue; + } - Edge edge(cell, i1, i2); - - if (!can_be_collapsed(edge, c3t3, protect_boundaries, cell_selector)) + Vertex_handle vh = collapse_edge(edge, c3t3, sq_high, + protect_boundaries, cell_selector, + visitor); + if (vh != Vertex_handle()) + { + std::vector incident_short; + c3t3.triangulation().finite_incident_edges(vh, + std::back_inserter(incident_short)); + for (const Edge& eshort : incident_short) { -#ifdef CGAL_TETRAHEDRAL_REMESHING_DEBUG - short_cancel << "2 " << point(p1) << " " << point(p2) << std::endl; -#endif - continue; + if (!can_be_collapsed(eshort, c3t3, protect_boundaries, cell_selector)) + continue; + + const FT sqlen = sql(tr.segment(eshort)); + if (sqlen < sq_low) + short_edges.insert(short_edge(make_vertex_pair(eshort), sqlen)); } - Vertex_handle vh = collapse_edge(edge, c3t3, sq_high, - protect_boundaries, cell_selector, - visitor); - if (vh != Vertex_handle()) - { - std::vector incident_short; - c3t3.triangulation().finite_incident_edges(vh, - std::back_inserter(incident_short)); - for (const Edge& eshort : incident_short) - { - if (!can_be_collapsed(eshort, c3t3, protect_boundaries, cell_selector)) - continue; - - const FT sqlen = sql(tr.segment(eshort)); - if (sqlen < sq_low) - short_edges.insert(short_edge(make_vertex_pair(eshort), sqlen)); - } - #ifdef CGAL_TETRAHEDRAL_REMESHING_VERBOSE - ++nb_collapses; -#endif - } -#ifdef CGAL_TETRAHEDRAL_REMESHING_DEBUG - if (vh != Vertex_handle()) - short_success << "2 " << point(p1) << " " << point(p2) << std::endl; - else - short_fail << "2 " << point(p1) << " " << point(p2) << std::endl; + ++nb_collapses; #endif } - }//end loop on short_edges #ifdef CGAL_TETRAHEDRAL_REMESHING_DEBUG - short_success.close(); - short_fail.close(); + if (vh != Vertex_handle()) + short_success << "2 " << point(p1) << " " << point(p2) << std::endl; + else + short_fail << "2 " << point(p1) << " " << point(p2) << std::endl; +#endif + } + }//end loop on short_edges +#ifdef CGAL_TETRAHEDRAL_REMESHING_DEBUG + short_success.close(); + short_fail.close(); #endif #ifdef CGAL_TETRAHEDRAL_REMESHING_VERBOSE - std::cout << " done (" << nb_collapses << " collapses)." << std::endl; + std::cout << " done (" << nb_collapses << " collapses)." << std::endl; #endif - } +} } } } diff --git a/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/compute_c3t3_statistics.h b/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/compute_c3t3_statistics.h index 70724a49097..20d676f7117 100644 --- a/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/compute_c3t3_statistics.h +++ b/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/compute_c3t3_statistics.h @@ -28,183 +28,183 @@ namespace Tetrahedral_remeshing { namespace internal { - template - void compute_statistics(const Triangulation& tr, - CellSelector cell_selector, - const char* filename = "statistics_c3t3.txt") +template +void compute_statistics(const Triangulation& tr, + CellSelector cell_selector, + const char* filename = "statistics_c3t3.txt") +{ + typedef Triangulation Tr; + typedef typename Tr::Geom_traits Gt; + typedef typename Tr::Cell_handle Cell_handle; + typedef typename Tr::Vertex_handle Vertex_handle; + typedef typename Gt::Point_3 Point; + typedef typename Tr::Finite_facets_iterator Finite_facets_iterator; + typedef typename Tr::Finite_cells_iterator Finite_cells_iterator; + typedef typename Tr::Cell::Subdomain_index Subdomain_index; + + std::size_t nb_edges = 0; + double total_edges = 0; + std::size_t nb_angle = 0; + double total_angle = 0; + + double min_edges_length = (std::numeric_limits::max)(); + double max_edges_length = 0.; + + double smallest_edge_radius = (std::numeric_limits::max)(); + double smallest_radius_radius = (std::numeric_limits::max)(); + double biggest_v_sma_cube = 0.; + double max_dihedral_angle = 0.; + double min_dihedral_angle = 180.; + + for (Finite_facets_iterator fit = tr.finite_facets_begin(); + fit != tr.finite_facets_end(); ++fit) { - typedef Triangulation Tr; - typedef typename Tr::Geom_traits Gt; - typedef typename Tr::Cell_handle Cell_handle; - typedef typename Tr::Vertex_handle Vertex_handle; - typedef typename Gt::Point_3 Point; - typedef typename Tr::Finite_facets_iterator Finite_facets_iterator; - typedef typename Tr::Finite_cells_iterator Finite_cells_iterator; - typedef typename Tr::Cell::Subdomain_index Subdomain_index; + const Cell_handle cell = fit->first; + const int& index = fit->second; + if (!cell_selector(cell) || !cell_selector(cell->neighbor(index))) + continue; - std::size_t nb_edges = 0; - double total_edges = 0; - std::size_t nb_angle = 0; - double total_angle = 0; + const Point& pa = point(cell->vertex((index + 1) & 3)->point()); + const Point& pb = point(cell->vertex((index + 2) & 3)->point()); + const Point& pc = point(cell->vertex((index + 3) & 3)->point()); - double min_edges_length = (std::numeric_limits::max)(); - double max_edges_length = 0.; - - double smallest_edge_radius = (std::numeric_limits::max)(); - double smallest_radius_radius = (std::numeric_limits::max)(); - double biggest_v_sma_cube = 0.; - double max_dihedral_angle = 0.; - double min_dihedral_angle = 180.; - - for (Finite_facets_iterator fit = tr.finite_facets_begin(); - fit != tr.finite_facets_end(); ++fit) + double edges[3]; + edges[0] = (CGAL::sqrt(CGAL::squared_distance(pa, pb))); + edges[1] = (CGAL::sqrt(CGAL::squared_distance(pa, pc))); + edges[2] = (CGAL::sqrt(CGAL::squared_distance(pb, pc))); + for (int i = 0; i < 3; ++i) { - const Cell_handle cell = fit->first; - const int& index = fit->second; - if (!cell_selector(cell) || !cell_selector(cell->neighbor(index))) - continue; - - const Point& pa = point(cell->vertex((index + 1) & 3)->point()); - const Point& pb = point(cell->vertex((index + 2) & 3)->point()); - const Point& pc = point(cell->vertex((index + 3) & 3)->point()); - - double edges[3]; - edges[0] = (CGAL::sqrt(CGAL::squared_distance(pa, pb))); - edges[1] = (CGAL::sqrt(CGAL::squared_distance(pa, pc))); - edges[2] = (CGAL::sqrt(CGAL::squared_distance(pb, pc))); - for (int i = 0; i < 3; ++i) - { - if (edges[i] < min_edges_length){ min_edges_length = edges[i]; } - if (edges[i] > max_edges_length){ max_edges_length = edges[i]; } - total_edges += edges[i]; - ++nb_edges; - } + if (edges[i] < min_edges_length){ min_edges_length = edges[i]; } + if (edges[i] > max_edges_length){ max_edges_length = edges[i]; } + total_edges += edges[i]; + ++nb_edges; } - - double mean_edges_length = total_edges / (double)nb_edges; - - typename Gt::Compute_approximate_dihedral_angle_3 approx_dihedral_angle - = tr.geom_traits().compute_approximate_dihedral_angle_3_object(); - - std::size_t nb_tets = 0; - boost::unordered_set selected_vertices; - std::vector sub_ids; - for (Finite_cells_iterator cit = tr.finite_cells_begin(); - cit != tr.finite_cells_end(); - ++cit) - { - const Subdomain_index& si = cit->subdomain_index(); - if (si == Subdomain_index() || !cell_selector(cit)) - continue; - - ++nb_tets; - if (std::find(sub_ids.begin(), sub_ids.end(), si) == sub_ids.end()) - sub_ids.push_back(cit->subdomain_index()); - for (int i = 0; i < 4; ++i) - selected_vertices.insert(cit->vertex(i)); - - const Point& p0 = point(cit->vertex(0)->point()); - const Point& p1 = point(cit->vertex(1)->point()); - const Point& p2 = point(cit->vertex(2)->point()); - const Point& p3 = point(cit->vertex(3)->point()); - double v = CGAL::abs(tr.tetrahedron(cit).volume()); - if (v == 0.) - { - std::cout << "degenerate cell :\n\t"; - std::cout << p0 << "\n\t" << p1 << "\n\t" << p2 << "\n\t" << p3 << std::endl; - } - double circumradius = (v == 0.) - ? CGAL::sqrt(CGAL::squared_radius(p0, p1, p2)) - : CGAL::sqrt(CGAL::squared_radius(p0, p1, p2, p3)); - - //find shortest edge - double edges[6]; - edges[0] = CGAL::sqrt(CGAL::squared_distance(p0, p1)); - edges[1] = CGAL::sqrt(CGAL::squared_distance(p0, p2)); - edges[2] = CGAL::sqrt(CGAL::squared_distance(p0, p3)); - edges[3] = CGAL::sqrt(CGAL::squared_distance(p2, p1)); - edges[4] = CGAL::sqrt(CGAL::squared_distance(p2, p3)); - edges[5] = CGAL::sqrt(CGAL::squared_distance(p1, p3)); - - double min_edge = edges[0]; - for (int i = 1; i < 6; ++i) - { - if (edges[i] < min_edge) - min_edge = edges[i]; - } - - double sumar = CGAL::sqrt(CGAL::squared_area(p0, p1, p2)) - + CGAL::sqrt(CGAL::squared_area(p1, p2, p3)) - + CGAL::sqrt(CGAL::squared_area(p2, p3, p0)) - + CGAL::sqrt(CGAL::squared_area(p3, p1, p0)); - double inradius = 3. * v / sumar; - double smallest_edge_radius_ = min_edge / circumradius*CGAL::sqrt(6.) / 4.;//*sqrt(6)/4 so that the perfect tet ratio is 1 - double smallest_radius_radius_ = inradius / circumradius * 3.; //*3 so that the perfect tet ratio is 1 instead of 1/3 - double biggest_v_sma_cube_ = v / std::pow(min_edge, 3) * 6. * CGAL::sqrt(2.);//*6*sqrt(2) so that the perfect tet ratio is 1 instead - - if (smallest_edge_radius_ < smallest_edge_radius) - smallest_edge_radius = smallest_edge_radius_; - - if (smallest_radius_radius_ < smallest_radius_radius) - smallest_radius_radius = smallest_radius_radius_; - - if (biggest_v_sma_cube_ > biggest_v_sma_cube) - biggest_v_sma_cube = biggest_v_sma_cube_; - - double a = CGAL::to_double(CGAL::abs(approx_dihedral_angle(p0, p1, p2, p3))); - if (a < min_dihedral_angle) { min_dihedral_angle = a; } - if (a > max_dihedral_angle) { max_dihedral_angle = a; } - total_angle += a; - ++nb_angle; - a = CGAL::to_double(CGAL::abs(approx_dihedral_angle(p0, p2, p1, p3))); - if (a < min_dihedral_angle) { min_dihedral_angle = a; } - if (a > max_dihedral_angle) { max_dihedral_angle = a; } - total_angle += a; - ++nb_angle; - a = CGAL::to_double(CGAL::abs(approx_dihedral_angle(p0, p3, p1, p2))); - if (a < min_dihedral_angle) { min_dihedral_angle = a; } - if (a > max_dihedral_angle) { max_dihedral_angle = a; } - total_angle += a; - ++nb_angle; - a = CGAL::to_double(CGAL::abs(approx_dihedral_angle(p1, p2, p0, p3))); - if (a < min_dihedral_angle) { min_dihedral_angle = a; } - if (a > max_dihedral_angle) { max_dihedral_angle = a; } - total_angle += a; - ++nb_angle; - a = CGAL::to_double(CGAL::abs(approx_dihedral_angle(p1, p3, p0, p2))); - if (a < min_dihedral_angle) { min_dihedral_angle = a; } - if (a > max_dihedral_angle) { max_dihedral_angle = a; } - total_angle += a; - ++nb_angle; - a = CGAL::to_double(CGAL::abs(approx_dihedral_angle(p2, p3, p0, p1))); - if (a < min_dihedral_angle) { min_dihedral_angle = a; } - if (a > max_dihedral_angle) { max_dihedral_angle = a; } - total_angle += a; - ++nb_angle; - } - - std::size_t nb_subdomains = sub_ids.size(); - //std::size_t nb_vertices = d->c3t3.number_of_vertices_in_complex(); - - std::ofstream ofs(filename); - if (!ofs) - return; - - ofs << "Nb subdomains : " << nb_subdomains << std::endl; - ofs << "Total number of vertices : " << tr.number_of_vertices() << std::endl; - ofs << "Number of selected cells : " << nb_tets << std::endl; - ofs << "Number of selected vertices : " << selected_vertices.size() << std::endl; - ofs << std::endl; - ofs << "Min dihedral angle : " << min_dihedral_angle << std::endl; - ofs << "Max dihedral angle : " << max_dihedral_angle << std::endl; - ofs << std::endl; - ofs << "Shortest edge : " << min_edges_length << std::endl; - ofs << "Longest edge : " << max_edges_length << std::endl; - ofs << "Average edge length : " << mean_edges_length << std::endl; - - ofs.close(); } + double mean_edges_length = total_edges / (double)nb_edges; + + typename Gt::Compute_approximate_dihedral_angle_3 approx_dihedral_angle + = tr.geom_traits().compute_approximate_dihedral_angle_3_object(); + + std::size_t nb_tets = 0; + boost::unordered_set selected_vertices; + std::vector sub_ids; + for (Finite_cells_iterator cit = tr.finite_cells_begin(); + cit != tr.finite_cells_end(); + ++cit) + { + const Subdomain_index& si = cit->subdomain_index(); + if (si == Subdomain_index() || !cell_selector(cit)) + continue; + + ++nb_tets; + if (std::find(sub_ids.begin(), sub_ids.end(), si) == sub_ids.end()) + sub_ids.push_back(cit->subdomain_index()); + for (int i = 0; i < 4; ++i) + selected_vertices.insert(cit->vertex(i)); + + const Point& p0 = point(cit->vertex(0)->point()); + const Point& p1 = point(cit->vertex(1)->point()); + const Point& p2 = point(cit->vertex(2)->point()); + const Point& p3 = point(cit->vertex(3)->point()); + double v = CGAL::abs(tr.tetrahedron(cit).volume()); + if (v == 0.) + { + std::cout << "degenerate cell :\n\t"; + std::cout << p0 << "\n\t" << p1 << "\n\t" << p2 << "\n\t" << p3 << std::endl; + } + double circumradius = (v == 0.) + ? CGAL::sqrt(CGAL::squared_radius(p0, p1, p2)) + : CGAL::sqrt(CGAL::squared_radius(p0, p1, p2, p3)); + + //find shortest edge + double edges[6]; + edges[0] = CGAL::sqrt(CGAL::squared_distance(p0, p1)); + edges[1] = CGAL::sqrt(CGAL::squared_distance(p0, p2)); + edges[2] = CGAL::sqrt(CGAL::squared_distance(p0, p3)); + edges[3] = CGAL::sqrt(CGAL::squared_distance(p2, p1)); + edges[4] = CGAL::sqrt(CGAL::squared_distance(p2, p3)); + edges[5] = CGAL::sqrt(CGAL::squared_distance(p1, p3)); + + double min_edge = edges[0]; + for (int i = 1; i < 6; ++i) + { + if (edges[i] < min_edge) + min_edge = edges[i]; + } + + double sumar = CGAL::sqrt(CGAL::squared_area(p0, p1, p2)) + + CGAL::sqrt(CGAL::squared_area(p1, p2, p3)) + + CGAL::sqrt(CGAL::squared_area(p2, p3, p0)) + + CGAL::sqrt(CGAL::squared_area(p3, p1, p0)); + double inradius = 3. * v / sumar; + double smallest_edge_radius_ = min_edge / circumradius*CGAL::sqrt(6.) / 4.;//*sqrt(6)/4 so that the perfect tet ratio is 1 + double smallest_radius_radius_ = inradius / circumradius * 3.; //*3 so that the perfect tet ratio is 1 instead of 1/3 + double biggest_v_sma_cube_ = v / std::pow(min_edge, 3) * 6. * CGAL::sqrt(2.);//*6*sqrt(2) so that the perfect tet ratio is 1 instead + + if (smallest_edge_radius_ < smallest_edge_radius) + smallest_edge_radius = smallest_edge_radius_; + + if (smallest_radius_radius_ < smallest_radius_radius) + smallest_radius_radius = smallest_radius_radius_; + + if (biggest_v_sma_cube_ > biggest_v_sma_cube) + biggest_v_sma_cube = biggest_v_sma_cube_; + + double a = CGAL::to_double(CGAL::abs(approx_dihedral_angle(p0, p1, p2, p3))); + if (a < min_dihedral_angle) { min_dihedral_angle = a; } + if (a > max_dihedral_angle) { max_dihedral_angle = a; } + total_angle += a; + ++nb_angle; + a = CGAL::to_double(CGAL::abs(approx_dihedral_angle(p0, p2, p1, p3))); + if (a < min_dihedral_angle) { min_dihedral_angle = a; } + if (a > max_dihedral_angle) { max_dihedral_angle = a; } + total_angle += a; + ++nb_angle; + a = CGAL::to_double(CGAL::abs(approx_dihedral_angle(p0, p3, p1, p2))); + if (a < min_dihedral_angle) { min_dihedral_angle = a; } + if (a > max_dihedral_angle) { max_dihedral_angle = a; } + total_angle += a; + ++nb_angle; + a = CGAL::to_double(CGAL::abs(approx_dihedral_angle(p1, p2, p0, p3))); + if (a < min_dihedral_angle) { min_dihedral_angle = a; } + if (a > max_dihedral_angle) { max_dihedral_angle = a; } + total_angle += a; + ++nb_angle; + a = CGAL::to_double(CGAL::abs(approx_dihedral_angle(p1, p3, p0, p2))); + if (a < min_dihedral_angle) { min_dihedral_angle = a; } + if (a > max_dihedral_angle) { max_dihedral_angle = a; } + total_angle += a; + ++nb_angle; + a = CGAL::to_double(CGAL::abs(approx_dihedral_angle(p2, p3, p0, p1))); + if (a < min_dihedral_angle) { min_dihedral_angle = a; } + if (a > max_dihedral_angle) { max_dihedral_angle = a; } + total_angle += a; + ++nb_angle; + } + + std::size_t nb_subdomains = sub_ids.size(); + //std::size_t nb_vertices = d->c3t3.number_of_vertices_in_complex(); + + std::ofstream ofs(filename); + if (!ofs) + return; + + ofs << "Nb subdomains : " << nb_subdomains << std::endl; + ofs << "Total number of vertices : " << tr.number_of_vertices() << std::endl; + ofs << "Number of selected cells : " << nb_tets << std::endl; + ofs << "Number of selected vertices : " << selected_vertices.size() << std::endl; + ofs << std::endl; + ofs << "Min dihedral angle : " << min_dihedral_angle << std::endl; + ofs << "Max dihedral angle : " << max_dihedral_angle << std::endl; + ofs << std::endl; + ofs << "Shortest edge : " << min_edges_length << std::endl; + ofs << "Longest edge : " << max_edges_length << std::endl; + ofs << "Average edge length : " << mean_edges_length << std::endl; + + ofs.close(); +} + }//end namespace internal }//end namespace Tetrahedral_remeshing }//end namespace CGAL diff --git a/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/flip_edges.h b/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/flip_edges.h index 05d52dbb768..4ae9e2afe25 100644 --- a/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/flip_edges.h +++ b/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/flip_edges.h @@ -31,668 +31,527 @@ namespace Tetrahedral_remeshing { namespace internal { - enum Flip_Criterion{ MIN_ANGLE_BASED, AVERAGE_ANGLE_BASED, - VALENCE_BASED, VALENCE_MIN_DH_BASED }; +enum Flip_Criterion{ MIN_ANGLE_BASED, AVERAGE_ANGLE_BASED, + VALENCE_BASED, VALENCE_MIN_DH_BASED }; - //template - //void flip_inside_edges(std::vector&) - //{ - // //TODO +//template +//void flip_inside_edges(std::vector&) +//{ +// //TODO +//} + +//outer_mirror_facets contains the set of facets of the outer hull +//of the set of cells modified by the flip operation, +//"seen from" outside +//i.e. for each facet f among those, f.first has not been modified by flip +template +void update_c3t3_facets(C3t3& c3t3, + const CellSet& cells_to_update, + const FacetSet& outer_mirror_facets) +{ + typedef typename C3t3::Facet Facet; + typedef typename C3t3::Cell_handle Cell_handle; + + for (Cell_handle c : cells_to_update) + { + //their subdomain indices have not been modified because we kept the same cells + //surface patch indices need to be fixed though + for (int i = 0; i < 4; ++i) + { + const Facet f(c, i); + const Facet mf = c3t3.triangulation().mirror_facet(f); + if (outer_mirror_facets.find(mf) == outer_mirror_facets.end()) + { + //we are inside the modified zone, c3t3 info is not valid anymore + if (c3t3.is_in_complex(f)) + c3t3.remove_from_complex(f); + if (c3t3.is_in_complex(mf)) + c3t3.remove_from_complex(mf); + } + else + { + //we are on the border of the modified zone, c3t3 info is valid outside, + //on mirror facet + const typename C3t3::Surface_patch_index patch = c3t3.surface_patch_index(mf); + if (c3t3.is_in_complex(mf)) + { + c3t3.remove_from_complex(mf); + c3t3.add_to_complex(mf, patch); + } + } + } + } +} + +template +Sliver_removal_result flip_3_to_2(typename C3t3::Edge& edge, + C3t3& c3t3, + const std::vector& vertices_around_edge, + const Flip_Criterion& criterion) +{ + typedef typename C3t3::Triangulation Tr; + typedef typename C3t3::Facet Facet; + typedef typename C3t3::Vertex_handle Vertex_handle; + typedef typename C3t3::Cell_handle Cell_handle; + typedef typename Tr::Cell_circulator Cell_circulator; + typedef typename Tr::Geom_traits Gt; + typedef typename Gt::FT FT; + + //Edge to face flip + Tr& tr = c3t3.triangulation(); + + Cell_circulator circ = tr.incident_cells(edge); + Cell_circulator done = circ; + + Vertex_handle vh0 = edge.first->vertex(edge.second); + Vertex_handle vh1 = edge.first->vertex(edge.third); + + //Select 2 cells to keep and update and one to remove + Cell_handle ch0 = Cell_handle(circ++); + Cell_handle ch1 = Cell_handle(circ++); + Cell_handle cell_to_remove = Cell_handle(circ++); + if (circ != done) + { + std::cout << "Wrong flip function" << std::endl; + return NOT_FLIPPABLE; + } + + //Check structural validity + Cell_handle c; + int i0, i1, i3; + if (tr.is_facet(vertices_around_edge[0], vertices_around_edge[1], vertices_around_edge[2], + c, i0, i1, i3)) + return NOT_FLIPPABLE; + + //Check topological validity + const typename C3t3::Subdomain_index subdomain = ch0->subdomain_index(); + if ( subdomain != ch1->subdomain_index() + || subdomain != cell_to_remove->subdomain_index() + || ch1->subdomain_index() != cell_to_remove->subdomain_index()) + return NOT_FLIPPABLE; + + Vertex_handle vh2; + Vertex_handle vh3; + + for (int i = 0; i < 3; ++i){ + if (!ch0->has_vertex(vertices_around_edge[i])) + vh2 = vertices_around_edge[i]; + else if (!ch1->has_vertex(vertices_around_edge[i])) + vh3 = vertices_around_edge[i]; + } + + int vh0_id = ch0->index(vh0); + int vh1_id = ch1->index(vh1); + + //Check if flip valid + if (!is_well_oriented(tr, vh2, + ch0->vertex(indices(vh0_id, 0)), + ch0->vertex(indices(vh0_id, 1)), + ch0->vertex(indices(vh0_id, 2))) + || !is_well_oriented(tr, vh3, + ch1->vertex(indices(vh1_id, 0)), + ch1->vertex(indices(vh1_id, 1)), + ch1->vertex(indices(vh1_id, 2)))) + return NOT_FLIPPABLE; + + ///********************VALIDITY CHECK***************************/ + //double curr_min_dh; + //bool check_validity = false; + //std::vector pre_sliver_Removal_cells; + //if (check_validity){ + // pre_sliver_Removal_cells.clear(); + // pre_sliver_Removal_cells.push_back(K::Tetrahedron_3(ch0->vertex(0)->point(), ch0->vertex(1)->point(), ch0->vertex(2)->point(), ch0->vertex(3)->point())); + // pre_sliver_Removal_cells.push_back(K::Tetrahedron_3(ch1->vertex(0)->point(), ch1->vertex(1)->point(), ch1->vertex(2)->point(), ch1->vertex(3)->point())); + // pre_sliver_Removal_cells.push_back(K::Tetrahedron_3(cell_to_remove->vertex(0)->point(), cell_to_remove->vertex(1)->point(), + // cell_to_remove->vertex(2)->point(), cell_to_remove->vertex(3)->point())); + + // curr_min_dh = min_dihedral_angle(ch0); + // curr_min_dh = std::min(curr_min_dh, min_dihedral_angle(ch1)); + // curr_min_dh = std::min(curr_min_dh, min_dihedral_angle(cell_to_remove)); + + // pre_sliver_Removal_vertices.clear(); + // for (int i = 0; i < vertices_around_edge.size(); ++i){ + // pre_sliver_Removal_vertices.push_back(Point_3(vertices_around_edge[i]->point())); + // } + + // previous_edges.clear(); + // previous_edges.push_back(std::make_pair(vh0->point(), vh1->point())); //} + /*************************************************************/ - //outer_mirror_facets contains the set of facets of the outer hull - //of the set of cells modified by the flip operation, - //"seen from" outside - //i.e. for each facet f among those, f.first has not been modified by flip - template - void update_c3t3_facets(C3t3& c3t3, - const CellSet& cells_to_update, - const FacetSet& outer_mirror_facets) + + if (criterion == MIN_ANGLE_BASED) { - typedef typename C3t3::Facet Facet; - typedef typename C3t3::Cell_handle Cell_handle; + //Current worst dihedral angle + FT curr_min_dh = min_dihedral_angle(tr, ch0); + curr_min_dh = (std::min)(curr_min_dh, min_dihedral_angle(tr, ch1)); + curr_min_dh = (std::min)(curr_min_dh, min_dihedral_angle(tr, cell_to_remove)); - for (Cell_handle c : cells_to_update) + //Result worst dihedral angle + if (curr_min_dh > min_dihedral_angle(tr, vh2, + ch0->vertex(indices(vh0_id, 0)), + ch0->vertex(indices(vh0_id, 1)), + ch0->vertex(indices(vh0_id, 2))) + || curr_min_dh > min_dihedral_angle(tr, vh3, + ch1->vertex(indices(vh1_id, 0)), + ch1->vertex(indices(vh1_id, 1)), + ch1->vertex(indices(vh1_id, 2)))) + return NO_BEST_CONFIGURATION; + } + else if (criterion == AVERAGE_ANGLE_BASED) + { + //Current worst dihedral angle + double average_min_dh = min_dihedral_angle(tr, ch0); + average_min_dh += min_dihedral_angle(tr, ch1); + average_min_dh += min_dihedral_angle(tr, cell_to_remove); + + average_min_dh /= 3.; + + FT new_average_min_dh = 0.5 * + (min_dihedral_angle(tr, vh2, ch0->vertex(indices(vh0_id, 0)), + ch0->vertex(indices(vh0_id, 1)), + ch0->vertex(indices(vh0_id, 2))) + + min_dihedral_angle(tr, vh3, ch1->vertex(indices(vh1_id, 0)), + ch1->vertex(indices(vh1_id, 1)), + ch1->vertex(indices(vh1_id, 2)))); + //Result worst dihedral angle + if (average_min_dh > new_average_min_dh) + return NO_BEST_CONFIGURATION; + } + + //Keep the facets + typedef CGAL::Triple Facet_vvv; + typedef boost::unordered_map FaceMapIndex; + boost::unordered_set outer_mirror_facets; + + FaceMapIndex facet_map_indices; + std::vector mirror_facets; + circ = Cell_circulator(done); + do + { + // facet opposite to vh0 + int curr_vh0_id = circ->index(vh0); + Facet n_vh0_facet = tr.mirror_facet(Facet(circ, curr_vh0_id)); + + outer_mirror_facets.insert(n_vh0_facet); + + Facet_vvv face0 = make_vertex_triple(circ->vertex(indices(curr_vh0_id, 0)), + circ->vertex(indices(curr_vh0_id, 1)), + circ->vertex(indices(curr_vh0_id, 2))); + + typename FaceMapIndex::iterator it = facet_map_indices.find(face0); + if (it == facet_map_indices.end()) { - //their subdomain indices have not been modified because we kept the same cells - //surface patch indices need to be fixed though - for (int i = 0; i < 4; ++i) + facet_map_indices[face0] = mirror_facets.size(); + mirror_facets.push_back(n_vh0_facet); + } + + // facet opposite to vh1 + int curr_vh1_id = circ->index(vh1); + Facet n_vh1_facet = tr.mirror_facet(Facet(circ, curr_vh1_id)); + + outer_mirror_facets.insert(n_vh1_facet); + + Facet_vvv face1 = make_vertex_triple(circ->vertex(indices(curr_vh1_id, 0)), + circ->vertex(indices(curr_vh1_id, 1)), + circ->vertex(indices(curr_vh1_id, 2))); + it = facet_map_indices.find(face1); + if (it == facet_map_indices.end()) + { + facet_map_indices[face1] = mirror_facets.size(); + mirror_facets.push_back(n_vh1_facet); + } + } + while (++circ != done); + + /* + c3t3.remove_from_complex( ch0 ); + c3t3.remove_from_complex( ch1 ); + c3t3.remove_from_complex( cell_to_remove ); + + tr.flip(edge); + + for( int i = 0 ; i < facets.size() ; i ++ ){ + Cell_handle new_cell = facets[i].first->neighbor( facets[i].second ); + c3t3.add_to_complex( new_cell, si ); + } + */ + + //Update cells + ch0->set_vertex(vh0_id, vh2); + ch1->set_vertex(vh1_id, vh3); + + // "New" cells are not created, only modified/updated + std::vector cells_to_update; + cells_to_update.push_back(ch0); + cells_to_update.push_back(ch1); + + //Update adjacencies and vertices' cells + for (Cell_handle ch : cells_to_update) + { + for (int v = 0; v < 4; ++v) + { + Facet_vvv face = make_vertex_triple(ch->vertex(indices(v, 0)), + ch->vertex(indices(v, 1)), + ch->vertex(indices(v, 2))); + typename FaceMapIndex::iterator it = facet_map_indices.find(face); + if (it == facet_map_indices.end()) { - const Facet f(c, i); - const Facet mf = c3t3.triangulation().mirror_facet(f); - if (outer_mirror_facets.find(mf) == outer_mirror_facets.end()) - { - //we are inside the modified zone, c3t3 info is not valid anymore - if (c3t3.is_in_complex(f)) - c3t3.remove_from_complex(f); - if (c3t3.is_in_complex(mf)) - c3t3.remove_from_complex(mf); - } - else - { - //we are on the border of the modified zone, c3t3 info is valid outside, - //on mirror facet - const typename C3t3::Surface_patch_index patch = c3t3.surface_patch_index(mf); - if (c3t3.is_in_complex(mf)) - { - c3t3.remove_from_complex(mf); - c3t3.add_to_complex(mf, patch); - } - } + facet_map_indices[face] = mirror_facets.size(); + mirror_facets.push_back(Facet(ch, v)); } + else + { + Facet mirror_facet = mirror_facets[it->second]; + + //Update neighbor + mirror_facet.first->set_neighbor(mirror_facet.second, ch); + ch->set_neighbor(v, mirror_facet.first); + } + ch->vertex(v)->set_cell(ch); } } - template - Sliver_removal_result flip_3_to_2(typename C3t3::Edge& edge, - C3t3& c3t3, - const std::vector& vertices_around_edge, - const Flip_Criterion& criterion) + // Update c3t3 + c3t3.remove_from_complex(cell_to_remove); + tr.tds().delete_cell(cell_to_remove); + + update_c3t3_facets(c3t3, cells_to_update, outer_mirror_facets); + + /********************VALIDITY CHECK***************************/ + //if (check_validity) + //{ + // post_sliver_Removal_cells.clear(); + // post_sliver_Removal_cells.push_back(ch0); + // post_sliver_Removal_cells.push_back(ch1); + + // double new_min_dh = min_dihedral_angle(ch0); + // new_min_dh = std::min(new_min_dh, min_dihedral_angle(ch1)); + + // post_sliver_Removal_vertices.clear(); + // post_sliver_Removal_vertices.push_back(vh2); + // post_sliver_Removal_vertices.push_back(vh3); + + // if (!is_well_oriented(ch0)) + // return INVALID_ORIENTATION; + // if (!is_well_oriented(ch1)) + // return INVALID_ORIENTATION; + // if (!tr.is_valid(ch0)) + // return INVALID_CELL; + // if (!tr.is_valid(ch1)) + // return INVALID_CELL; + + // for (int i = 0; i < 4; ++i){ + // if (!tr.is_valid(ch0->neighbor(i))) + // return INVALID_CELL; + // if (!tr.is_valid(ch1->neighbor(i))) + // return INVALID_CELL; + // if (!tr.tds().is_valid(ch0->vertex(i))) + // return INVALID_VERTEX; + // if (!tr.tds().is_valid(ch1->vertex(i))){ + // return INVALID_VERTEX; + // } + // } + + // if ((curr_min_dh - new_min_dh) > 0.01){ + // std::cout << "Three_to_two_flip::Flip not improving the quality: " << curr_min_dh << " to " << new_min_dh << std::endl; + // return INVALID_CELL; + // } + //} + /***********************************************************/ + + return VALID_FLIP; +} + +template +void find_best_flip_to_improve_dh(C3t3& c3t3, + typename C3t3::Edge& edge, + typename C3t3::Vertex_handle vh2, + typename C3t3::Vertex_handle vh3, + CandidatesQueue& candidates, + double curr_min_dh, + bool is_sliver_well_oriented = true, + int e_id = 0) +{ + typedef typename C3t3::Triangulation Tr; + typedef typename C3t3::Vertex_handle Vertex_handle; + typedef typename C3t3::Cell_handle Cell_handle; + typedef typename C3t3::Facet Facet; + typedef typename Tr::Facet_circulator Facet_circulator; + typedef typename Tr::Cell_circulator Cell_circulator; + typedef typename Tr::Geom_traits Gt; + typedef typename Gt::FT FT; + + // std::cout << "find_best_flip_to_improve_dh boundary " << std::endl; + Tr& tr = c3t3.triangulation(); + + Vertex_handle vh0 = edge.first->vertex(edge.second); + Vertex_handle vh1 = edge.first->vertex(edge.third); + + Facet_circulator curr_fcirc = tr.incident_facets(edge); + Facet_circulator curr_fdone = curr_fcirc; + + //Only keep the possible flips + std::vector opposite_vertices; + int nb_cells_around_edge = 0; + do { - typedef typename C3t3::Triangulation Tr; - typedef typename C3t3::Facet Facet; - typedef typename C3t3::Vertex_handle Vertex_handle; - typedef typename C3t3::Cell_handle Cell_handle; - typedef typename Tr::Cell_circulator Cell_circulator; - typedef typename Tr::Geom_traits Gt; - typedef typename Gt::FT FT; - - //Edge to face flip - Tr& tr = c3t3.triangulation(); - - Cell_circulator circ = tr.incident_cells(edge); - Cell_circulator done = circ; - - Vertex_handle vh0 = edge.first->vertex(edge.second); - Vertex_handle vh1 = edge.first->vertex(edge.third); - - //Select 2 cells to keep and update and one to remove - Cell_handle ch0 = Cell_handle(circ++); - Cell_handle ch1 = Cell_handle(circ++); - Cell_handle cell_to_remove = Cell_handle(circ++); - if (circ != done) + Vertex_handle vh; + //Get the ids of the opposite vertices + for (int i = 0; i < 3; ++i) { - std::cout << "Wrong flip function" << std::endl; - return NOT_FLIPPABLE; - } - - //Check structural validity - Cell_handle c; - int i0, i1, i3; - if (tr.is_facet(vertices_around_edge[0], vertices_around_edge[1], vertices_around_edge[2], - c, i0, i1, i3)) - return NOT_FLIPPABLE; - - //Check topological validity - const typename C3t3::Subdomain_index subdomain = ch0->subdomain_index(); - if ( subdomain != ch1->subdomain_index() - || subdomain != cell_to_remove->subdomain_index() - || ch1->subdomain_index() != cell_to_remove->subdomain_index()) - return NOT_FLIPPABLE; - - Vertex_handle vh2; - Vertex_handle vh3; - - for (int i = 0; i < 3; ++i){ - if (!ch0->has_vertex(vertices_around_edge[i])) - vh2 = vertices_around_edge[i]; - else if (!ch1->has_vertex(vertices_around_edge[i])) - vh3 = vertices_around_edge[i]; - } - - int vh0_id = ch0->index(vh0); - int vh1_id = ch1->index(vh1); - - //Check if flip valid - if (!is_well_oriented(tr, vh2, - ch0->vertex(indices(vh0_id, 0)), - ch0->vertex(indices(vh0_id, 1)), - ch0->vertex(indices(vh0_id, 2))) - || !is_well_oriented(tr, vh3, - ch1->vertex(indices(vh1_id, 0)), - ch1->vertex(indices(vh1_id, 1)), - ch1->vertex(indices(vh1_id, 2)))) - return NOT_FLIPPABLE; - - ///********************VALIDITY CHECK***************************/ - //double curr_min_dh; - //bool check_validity = false; - //std::vector pre_sliver_Removal_cells; - //if (check_validity){ - // pre_sliver_Removal_cells.clear(); - // pre_sliver_Removal_cells.push_back(K::Tetrahedron_3(ch0->vertex(0)->point(), ch0->vertex(1)->point(), ch0->vertex(2)->point(), ch0->vertex(3)->point())); - // pre_sliver_Removal_cells.push_back(K::Tetrahedron_3(ch1->vertex(0)->point(), ch1->vertex(1)->point(), ch1->vertex(2)->point(), ch1->vertex(3)->point())); - // pre_sliver_Removal_cells.push_back(K::Tetrahedron_3(cell_to_remove->vertex(0)->point(), cell_to_remove->vertex(1)->point(), - // cell_to_remove->vertex(2)->point(), cell_to_remove->vertex(3)->point())); - - // curr_min_dh = min_dihedral_angle(ch0); - // curr_min_dh = std::min(curr_min_dh, min_dihedral_angle(ch1)); - // curr_min_dh = std::min(curr_min_dh, min_dihedral_angle(cell_to_remove)); - - // pre_sliver_Removal_vertices.clear(); - // for (int i = 0; i < vertices_around_edge.size(); ++i){ - // pre_sliver_Removal_vertices.push_back(Point_3(vertices_around_edge[i]->point())); - // } - - // previous_edges.clear(); - // previous_edges.push_back(std::make_pair(vh0->point(), vh1->point())); - //} - /*************************************************************/ - - - if (criterion == MIN_ANGLE_BASED) - { - //Current worst dihedral angle - FT curr_min_dh = min_dihedral_angle(tr, ch0); - curr_min_dh = (std::min)(curr_min_dh, min_dihedral_angle(tr, ch1)); - curr_min_dh = (std::min)(curr_min_dh, min_dihedral_angle(tr, cell_to_remove)); - - //Result worst dihedral angle - if (curr_min_dh > min_dihedral_angle(tr, vh2, - ch0->vertex(indices(vh0_id, 0)), - ch0->vertex(indices(vh0_id, 1)), - ch0->vertex(indices(vh0_id, 2))) - || curr_min_dh > min_dihedral_angle(tr, vh3, - ch1->vertex(indices(vh1_id, 0)), - ch1->vertex(indices(vh1_id, 1)), - ch1->vertex(indices(vh1_id, 2)))) - return NO_BEST_CONFIGURATION; - } - else if (criterion == AVERAGE_ANGLE_BASED) - { - //Current worst dihedral angle - double average_min_dh = min_dihedral_angle(tr, ch0); - average_min_dh += min_dihedral_angle(tr, ch1); - average_min_dh += min_dihedral_angle(tr, cell_to_remove); - - average_min_dh /= 3.; - - FT new_average_min_dh = 0.5 * - (min_dihedral_angle(tr, vh2, ch0->vertex(indices(vh0_id, 0)), - ch0->vertex(indices(vh0_id, 1)), - ch0->vertex(indices(vh0_id, 2))) - + min_dihedral_angle(tr, vh3, ch1->vertex(indices(vh1_id, 0)), - ch1->vertex(indices(vh1_id, 1)), - ch1->vertex(indices(vh1_id, 2)))); - //Result worst dihedral angle - if (average_min_dh > new_average_min_dh) - return NO_BEST_CONFIGURATION; - } - - //Keep the facets - typedef CGAL::Triple Facet_vvv; - typedef boost::unordered_map FaceMapIndex; - boost::unordered_set outer_mirror_facets; - - FaceMapIndex facet_map_indices; - std::vector mirror_facets; - circ = Cell_circulator(done); - do - { - // facet opposite to vh0 - int curr_vh0_id = circ->index(vh0); - Facet n_vh0_facet = tr.mirror_facet(Facet(circ, curr_vh0_id)); - - outer_mirror_facets.insert(n_vh0_facet); - - Facet_vvv face0 = make_vertex_triple(circ->vertex(indices(curr_vh0_id, 0)), - circ->vertex(indices(curr_vh0_id, 1)), - circ->vertex(indices(curr_vh0_id, 2))); - - typename FaceMapIndex::iterator it = facet_map_indices.find(face0); - if (it == facet_map_indices.end()) + Vertex_handle curr_vertex = curr_fcirc->first->vertex(indices(curr_fcirc->second, i)); + if ( curr_vertex != vh0 + && curr_vertex != vh1 + && (curr_vertex == vh2 || curr_vertex == vh3)) { - facet_map_indices[face0] = mirror_facets.size(); - mirror_facets.push_back(n_vh0_facet); - } + vh = curr_vertex; + Facet_circulator facet_circulator(curr_fcirc); + Facet_circulator facet_done(curr_fcirc); - // facet opposite to vh1 - int curr_vh1_id = circ->index(vh1); - Facet n_vh1_facet = tr.mirror_facet(Facet(circ, curr_vh1_id)); + facet_done--; + facet_circulator++; + facet_circulator++; - outer_mirror_facets.insert(n_vh1_facet); - - Facet_vvv face1 = make_vertex_triple(circ->vertex(indices(curr_vh1_id, 0)), - circ->vertex(indices(curr_vh1_id, 1)), - circ->vertex(indices(curr_vh1_id, 2))); - it = facet_map_indices.find(face1); - if (it == facet_map_indices.end()) - { - facet_map_indices[face1] = mirror_facets.size(); - mirror_facets.push_back(n_vh1_facet); - } - } - while (++circ != done); - - /* - c3t3.remove_from_complex( ch0 ); - c3t3.remove_from_complex( ch1 ); - c3t3.remove_from_complex( cell_to_remove ); - - tr.flip(edge); - - for( int i = 0 ; i < facets.size() ; i ++ ){ - Cell_handle new_cell = facets[i].first->neighbor( facets[i].second ); - c3t3.add_to_complex( new_cell, si ); - } - */ - - //Update cells - ch0->set_vertex(vh0_id, vh2); - ch1->set_vertex(vh1_id, vh3); - - // "New" cells are not created, only modified/updated - std::vector cells_to_update; - cells_to_update.push_back(ch0); - cells_to_update.push_back(ch1); - - //Update adjacencies and vertices' cells - for (Cell_handle ch : cells_to_update) - { - for (int v = 0; v < 4; ++v) - { - Facet_vvv face = make_vertex_triple(ch->vertex(indices(v, 0)), - ch->vertex(indices(v, 1)), - ch->vertex(indices(v, 2))); - typename FaceMapIndex::iterator it = facet_map_indices.find(face); - if (it == facet_map_indices.end()) + bool is_edge = false; + do { - facet_map_indices[face] = mirror_facets.size(); - mirror_facets.push_back(Facet(ch, v)); - } - else - { - Facet mirror_facet = mirror_facets[it->second]; - - //Update neighbor - mirror_facet.first->set_neighbor(mirror_facet.second, ch); - ch->set_neighbor(v, mirror_facet.first); - } - ch->vertex(v)->set_cell(ch); - } - } - - // Update c3t3 - c3t3.remove_from_complex(cell_to_remove); - tr.tds().delete_cell(cell_to_remove); - - update_c3t3_facets(c3t3, cells_to_update, outer_mirror_facets); - - /********************VALIDITY CHECK***************************/ - //if (check_validity) - //{ - // post_sliver_Removal_cells.clear(); - // post_sliver_Removal_cells.push_back(ch0); - // post_sliver_Removal_cells.push_back(ch1); - - // double new_min_dh = min_dihedral_angle(ch0); - // new_min_dh = std::min(new_min_dh, min_dihedral_angle(ch1)); - - // post_sliver_Removal_vertices.clear(); - // post_sliver_Removal_vertices.push_back(vh2); - // post_sliver_Removal_vertices.push_back(vh3); - - // if (!is_well_oriented(ch0)) - // return INVALID_ORIENTATION; - // if (!is_well_oriented(ch1)) - // return INVALID_ORIENTATION; - // if (!tr.is_valid(ch0)) - // return INVALID_CELL; - // if (!tr.is_valid(ch1)) - // return INVALID_CELL; - - // for (int i = 0; i < 4; ++i){ - // if (!tr.is_valid(ch0->neighbor(i))) - // return INVALID_CELL; - // if (!tr.is_valid(ch1->neighbor(i))) - // return INVALID_CELL; - // if (!tr.tds().is_valid(ch0->vertex(i))) - // return INVALID_VERTEX; - // if (!tr.tds().is_valid(ch1->vertex(i))){ - // return INVALID_VERTEX; - // } - // } - - // if ((curr_min_dh - new_min_dh) > 0.01){ - // std::cout << "Three_to_two_flip::Flip not improving the quality: " << curr_min_dh << " to " << new_min_dh << std::endl; - // return INVALID_CELL; - // } - //} - /***********************************************************/ - - return VALID_FLIP; - } - - template - void find_best_flip_to_improve_dh(C3t3& c3t3, - typename C3t3::Edge& edge, - typename C3t3::Vertex_handle vh2, - typename C3t3::Vertex_handle vh3, - CandidatesQueue& candidates, - double curr_min_dh, - bool is_sliver_well_oriented = true, - int e_id = 0) - { - typedef typename C3t3::Triangulation Tr; - typedef typename C3t3::Vertex_handle Vertex_handle; - typedef typename C3t3::Cell_handle Cell_handle; - typedef typename C3t3::Facet Facet; - typedef typename Tr::Facet_circulator Facet_circulator; - typedef typename Tr::Cell_circulator Cell_circulator; - typedef typename Tr::Geom_traits Gt; - typedef typename Gt::FT FT; - - // std::cout << "find_best_flip_to_improve_dh boundary " << std::endl; - Tr& tr = c3t3.triangulation(); - - Vertex_handle vh0 = edge.first->vertex(edge.second); - Vertex_handle vh1 = edge.first->vertex(edge.third); - - Facet_circulator curr_fcirc = tr.incident_facets(edge); - Facet_circulator curr_fdone = curr_fcirc; - - //Only keep the possible flips - std::vector opposite_vertices; - int nb_cells_around_edge = 0; - do - { - Vertex_handle vh; - //Get the ids of the opposite vertices - for (int i = 0; i < 3; ++i) - { - Vertex_handle curr_vertex = curr_fcirc->first->vertex(indices(curr_fcirc->second, i)); - if ( curr_vertex != vh0 - && curr_vertex != vh1 - && (curr_vertex == vh2 || curr_vertex == vh3)) - { - vh = curr_vertex; - Facet_circulator facet_circulator(curr_fcirc); - Facet_circulator facet_done(curr_fcirc); - - facet_done--; - facet_circulator++; - facet_circulator++; - - bool is_edge = false; - do + //Get the ids of the opposite vertices + for (int i = 0; i < 3; ++i) { - //Get the ids of the opposite vertices - for (int i = 0; i < 3; ++i) + Vertex_handle curr_vertex = facet_circulator->first->vertex( + indices(facet_circulator->second, i)); + if (curr_vertex != vh0 && curr_vertex != vh1) { - Vertex_handle curr_vertex = facet_circulator->first->vertex( - indices(facet_circulator->second, i)); - if (curr_vertex != vh0 && curr_vertex != vh1) - { - Cell_handle ch; - int i0, i1; - if (tr.is_edge(curr_vertex, vh, ch, i0, i1)) - is_edge = true; - } + Cell_handle ch; + int i0, i1; + if (tr.is_edge(curr_vertex, vh, ch, i0, i1)) + is_edge = true; } - } while (++facet_circulator != facet_done); - - if (!is_edge && !tr.is_infinite(vh)) - opposite_vertices.push_back(vh); - } - } - nb_cells_around_edge++; - } - while (++curr_fcirc != curr_fdone); - - if (nb_cells_around_edge < 4) - return; - - //Facets that will be used to create new cells i.e. all the facets opposite to vh1 and don't have vh - //Facets that will be used to update cells i.e. all the facets opposite to vh0 will be set to vh: facet.first->set_vertex( facet.second, vh ) - - Cell_circulator cell_circulator = tr.incident_cells(edge); - Cell_circulator done = cell_circulator; - - for (std::size_t i = 0; i < opposite_vertices.size(); ++i) - { - Vertex_handle vh = opposite_vertices[i]; - bool keep = true; - - std::vector facets; - do - { - //Store it if it do not have vh - if (!cell_circulator->has_vertex(vh)) - { - //Facets opposite to vh0 - Facet facet_vh0(cell_circulator, cell_circulator->index(vh0)); - - //Facets opposite to vh1 - Facet facet_vh1(cell_circulator, cell_circulator->index(vh1)); - - facets.push_back(facet_vh1); - facets.push_back(facet_vh0); - } - } while (++cell_circulator != done); - - - FT min_flip_dihedral_angle = (std::numeric_limits::max)(); - for (std::size_t i = 0; i < facets.size(); ++i) - { - const Facet& fi = facets[i]; - if (!tr.is_infinite(fi.first)) - { - if (is_well_oriented(tr, vh, fi.first->vertex(indices(fi.second, 0)), - fi.first->vertex(indices(fi.second, 1)), - fi.first->vertex(indices(fi.second, 2)))) - { - min_flip_dihedral_angle = (std::min)(min_flip_dihedral_angle, - min_dihedral_angle(tr, vh, fi.first->vertex(indices(fi.second, 0)), - fi.first->vertex(indices(fi.second, 1)), - fi.first->vertex(indices(fi.second, 2)))); } - else - { - keep = false; - break; - } - } - } + } while (++facet_circulator != facet_done); - if (keep && (curr_min_dh < min_flip_dihedral_angle || !is_sliver_well_oriented)) - { - //std::cout << "vh " << vh->info() <<" old " << curr_min_dh << " min " << min_flip_dihedral_angle << std::endl; - candidates.push(std::make_pair(min_flip_dihedral_angle, std::make_pair(vh, e_id))); + if (!is_edge && !tr.is_infinite(vh)) + opposite_vertices.push_back(vh); } } + nb_cells_around_edge++; } + while (++curr_fcirc != curr_fdone); - template - void find_best_flip_to_improve_dh(C3t3& c3t3, - typename C3t3::Edge& edge, - CandidatesQueue& candidates, - double curr_min_dh, - bool is_sliver_well_oriented = true, - int e_id = 0) + if (nb_cells_around_edge < 4) + return; + + //Facets that will be used to create new cells i.e. all the facets opposite to vh1 and don't have vh + //Facets that will be used to update cells i.e. all the facets opposite to vh0 will be set to vh: facet.first->set_vertex( facet.second, vh ) + + Cell_circulator cell_circulator = tr.incident_cells(edge); + Cell_circulator done = cell_circulator; + + for (std::size_t i = 0; i < opposite_vertices.size(); ++i) { - typedef typename C3t3::Triangulation Tr; - typedef typename C3t3::Vertex_handle Vertex_handle; - typedef typename C3t3::Cell_handle Cell_handle; - typedef typename C3t3::Facet Facet; - typedef typename Tr::Facet_circulator Facet_circulator; - typedef typename Tr::Cell_circulator Cell_circulator; - typedef typename Tr::Geom_traits Gt; - typedef typename Gt::FT FT; + Vertex_handle vh = opposite_vertices[i]; + bool keep = true; - Tr& tr = c3t3.triangulation(); - - Vertex_handle vh0 = edge.first->vertex(edge.second); - Vertex_handle vh1 = edge.first->vertex(edge.third); - - Facet_circulator curr_fcirc = tr.incident_facets(edge); - Facet_circulator curr_fdone = curr_fcirc; - - //Only keep the possible flips - std::vector opposite_vertices; - int nb_cells_around_edge = 0; + std::vector facets; do { - Vertex_handle vh; - //Get the ids of the opposite vertices - for (int i = 0; i < 3; ++i) + //Store it if it do not have vh + if (!cell_circulator->has_vertex(vh)) { - Vertex_handle curr_vertex = curr_fcirc->first->vertex( - indices(curr_fcirc->second, i)); - if (curr_vertex != vh0 && curr_vertex != vh1) + //Facets opposite to vh0 + Facet facet_vh0(cell_circulator, cell_circulator->index(vh0)); + + //Facets opposite to vh1 + Facet facet_vh1(cell_circulator, cell_circulator->index(vh1)); + + facets.push_back(facet_vh1); + facets.push_back(facet_vh0); + } + } while (++cell_circulator != done); + + + FT min_flip_dihedral_angle = (std::numeric_limits::max)(); + for (std::size_t i = 0; i < facets.size(); ++i) + { + const Facet& fi = facets[i]; + if (!tr.is_infinite(fi.first)) + { + if (is_well_oriented(tr, vh, fi.first->vertex(indices(fi.second, 0)), + fi.first->vertex(indices(fi.second, 1)), + fi.first->vertex(indices(fi.second, 2)))) { - vh = curr_vertex; + min_flip_dihedral_angle = (std::min)(min_flip_dihedral_angle, + min_dihedral_angle(tr, vh, fi.first->vertex(indices(fi.second, 0)), + fi.first->vertex(indices(fi.second, 1)), + fi.first->vertex(indices(fi.second, 2)))); + } + else + { + keep = false; break; } } - - Facet_circulator facet_circulator = curr_fcirc; - Facet_circulator facet_done = curr_fcirc; - - facet_done--; - facet_circulator++; - facet_circulator++; - bool is_edge = false; - do - { - //Get the ids of the opposite vertices - for (int i = 0; i < 3; ++i) - { - Vertex_handle curr_vertex = facet_circulator->first->vertex( - indices(facet_circulator->second, i)); - if (curr_vertex != vh0 && curr_vertex != vh1) - { - Cell_handle ch; - int i0, i1; - if (tr.is_edge(curr_vertex, vh, ch, i0, i1)) - is_edge = true; - } - } - } while (++facet_circulator != facet_done); - - if (!is_edge && !tr.is_infinite(vh)) - opposite_vertices.push_back(vh); - - nb_cells_around_edge++; } - while (++curr_fcirc != curr_fdone); - if (nb_cells_around_edge < 4) - return; - //Facets that will be used to create new cells - // i.e. all the facets opposite to vh1 and don't have vh - //Facets that will be used to update cells - // i.e. all the facets opposite to vh0 will be set to vh: - // facet.first->set_vertex( facet.second, vh ) - - Cell_circulator cell_circulator = tr.incident_cells(edge); - Cell_circulator done = cell_circulator; - - for (std::size_t i = 0; i < opposite_vertices.size(); ++i) + if (keep && (curr_min_dh < min_flip_dihedral_angle || !is_sliver_well_oriented)) { - Vertex_handle vh = opposite_vertices[i]; - bool keep = true; - - std::vector facets; - do - { - //Store it if it do not have vh - if (!cell_circulator->has_vertex(vh)) - { - //Facets opposite to vh0 - Facet facet_vh0(cell_circulator, cell_circulator->index(vh0)); - - //Facets opposite to vh1 - Facet facet_vh1(cell_circulator, cell_circulator->index(vh1)); - - facets.push_back(facet_vh1); - facets.push_back(facet_vh0); - } - } - while (++cell_circulator != done); - - FT min_flip_dihedral_angle = (std::numeric_limits::max)(); - for (std::size_t i = 0; i < facets.size(); ++i) - { - const Facet& fi = facets[i]; - if (!tr.is_infinite(fi.first)) - { - if (is_well_oriented(tr, vh, fi.first->vertex(indices(fi.second, 0)), - fi.first->vertex(indices(fi.second, 1)), - fi.first->vertex(indices(fi.second, 2)))) - { - min_flip_dihedral_angle = (std::min)(min_flip_dihedral_angle, - min_dihedral_angle(tr, vh, fi.first->vertex(indices(fi.second, 0)), - fi.first->vertex(indices(fi.second, 1)), - fi.first->vertex(indices(fi.second, 2)))); - } - else - { - keep = false; - break; - } - } - } - - if (keep && (curr_min_dh < min_flip_dihedral_angle || !is_sliver_well_oriented)) - { - //std::cout << "vh " << vh->info() <<" old " << curr_min_dh << " min " << min_flip_dihedral_angle << std::endl; - candidates.push(std::make_pair(min_flip_dihedral_angle, std::make_pair(vh, e_id))); - } + //std::cout << "vh " << vh->info() <<" old " << curr_min_dh << " min " << min_flip_dihedral_angle << std::endl; + candidates.push(std::make_pair(min_flip_dihedral_angle, std::make_pair(vh, e_id))); } } +} - template - Sliver_removal_result flip_n_to_m(C3t3& c3t3, - typename C3t3::Edge& edge, - typename C3t3::Vertex_handle vh, - Visitor& visitor, - bool check_validity = false) +template +void find_best_flip_to_improve_dh(C3t3& c3t3, + typename C3t3::Edge& edge, + CandidatesQueue& candidates, + double curr_min_dh, + bool is_sliver_well_oriented = true, + int e_id = 0) +{ + typedef typename C3t3::Triangulation Tr; + typedef typename C3t3::Vertex_handle Vertex_handle; + typedef typename C3t3::Cell_handle Cell_handle; + typedef typename C3t3::Facet Facet; + typedef typename Tr::Facet_circulator Facet_circulator; + typedef typename Tr::Cell_circulator Cell_circulator; + typedef typename Tr::Geom_traits Gt; + typedef typename Gt::FT FT; + + Tr& tr = c3t3.triangulation(); + + Vertex_handle vh0 = edge.first->vertex(edge.second); + Vertex_handle vh1 = edge.first->vertex(edge.third); + + Facet_circulator curr_fcirc = tr.incident_facets(edge); + Facet_circulator curr_fdone = curr_fcirc; + + //Only keep the possible flips + std::vector opposite_vertices; + int nb_cells_around_edge = 0; + do { - CGAL_USE(check_validity); - // std::cout << "n_to_m_flip::start" << std::endl; - typedef typename C3t3::Triangulation Tr; - typedef typename C3t3::Vertex_handle Vertex_handle; - typedef typename C3t3::Cell_handle Cell_handle; - typedef typename C3t3::Facet Facet; - typedef typename Tr::Facet_circulator Facet_circulator; - typedef typename Tr::Cell_circulator Cell_circulator; - - Tr& tr = c3t3.triangulation(); - - Vertex_handle vh0 = edge.first->vertex(edge.second); - Vertex_handle vh1 = edge.first->vertex(edge.third); - - //This vertex will have its valence augmenting a lot, - //TODO take the best one - - //TODO!!!! Check that the created edges do not exist!!! - - Facet_circulator facet_circulator = tr.incident_facets(edge); - Facet_circulator done_facet_circulator = facet_circulator; - bool look_for_vh_iterator = true; - do + Vertex_handle vh; + //Get the ids of the opposite vertices + for (int i = 0; i < 3; ++i) { - facet_circulator++; - - //Get the ids of the opposite vertices - for (int i = 0; i < 3; ++i) + Vertex_handle curr_vertex = curr_fcirc->first->vertex( + indices(curr_fcirc->second, i)); + if (curr_vertex != vh0 && curr_vertex != vh1) { - if (facet_circulator->first->vertex(indices(facet_circulator->second, i)) == vh) - look_for_vh_iterator = false; + vh = curr_vertex; + break; } - } while (facet_circulator != done_facet_circulator && look_for_vh_iterator); - - if (look_for_vh_iterator){ - std::cout << "Vertex not an opposite of the edge!!" << std::endl; - return NOT_FLIPPABLE; } - Facet_circulator facet_done(facet_circulator); + Facet_circulator facet_circulator = curr_fcirc; + Facet_circulator facet_done = curr_fcirc; + facet_done--; facet_circulator++; facet_circulator++; - - std::vector vertices_around_edge; + bool is_edge = false; do { //Get the ids of the opposite vertices @@ -705,143 +564,300 @@ namespace internal Cell_handle ch; int i0, i1; if (tr.is_edge(curr_vertex, vh, ch, i0, i1)) - return NOT_FLIPPABLE; - - vertices_around_edge.push_back(curr_vertex); + is_edge = true; } } } while (++facet_circulator != facet_done); + if (!is_edge && !tr.is_infinite(vh)) + opposite_vertices.push_back(vh); - std::vector cells_around_edge; - std::vector to_remove; + nb_cells_around_edge++; + } + while (++curr_fcirc != curr_fdone); + if (nb_cells_around_edge < 4) + return; - //Neighbors that will need to be updated after flip - boost::unordered_set neighbor_facets; + //Facets that will be used to create new cells + // i.e. all the facets opposite to vh1 and don't have vh + //Facets that will be used to update cells + // i.e. all the facets opposite to vh0 will be set to vh: + // facet.first->set_vertex( facet.second, vh ) - //Facets that will be used to create new cells - // i.e. all the facets opposite to vh1 and don't have vh - std::vector facets_for_new_cells; + Cell_circulator cell_circulator = tr.incident_cells(edge); + Cell_circulator done = cell_circulator; - //Facets that will be used to update cells - // i.e. all the facets opposite to vh0 will be set to vh : - // facet.first->set_vertex( facet.second, vh ) - std::vector facets_for_updated_cells; + for (std::size_t i = 0; i < opposite_vertices.size(); ++i) + { + Vertex_handle vh = opposite_vertices[i]; + bool keep = true; - Cell_circulator cell_circulator = tr.incident_cells(edge); - Cell_circulator done = cell_circulator; + std::vector facets; do { - cells_around_edge.push_back(cell_circulator); - - //Facets opposite to vh0 - Facet facet_vh0(cell_circulator, cell_circulator->index(vh0)); - neighbor_facets.insert(tr.mirror_facet(facet_vh0)); - - //Facets opposite to vh1 - Facet facet_vh1(cell_circulator, cell_circulator->index(vh1)); - neighbor_facets.insert(tr.mirror_facet(facet_vh1)); - //Store it if it do not have vh - if (cell_circulator->has_vertex(vh)){ - to_remove.push_back(cell_circulator); - } - else + if (!cell_circulator->has_vertex(vh)) { - facets_for_new_cells.push_back(facet_vh1); - facets_for_updated_cells.push_back(facet_vh0); + //Facets opposite to vh0 + Facet facet_vh0(cell_circulator, cell_circulator->index(vh0)); + + //Facets opposite to vh1 + Facet facet_vh1(cell_circulator, cell_circulator->index(vh1)); + + facets.push_back(facet_vh1); + facets.push_back(facet_vh0); } - // - // if( ! is_well_oriented( cell_circulator ) ) - // return WRONG; } while (++cell_circulator != done); - //Check that the result will be valid - for (const Facet& fi : facets_for_new_cells) + FT min_flip_dihedral_angle = (std::numeric_limits::max)(); + for (std::size_t i = 0; i < facets.size(); ++i) { - if ( !tr.is_infinite(fi.first) - && !is_well_oriented(tr, vh, fi.first->vertex(indices(fi.second, 0)), + const Facet& fi = facets[i]; + if (!tr.is_infinite(fi.first)) + { + if (is_well_oriented(tr, vh, fi.first->vertex(indices(fi.second, 0)), fi.first->vertex(indices(fi.second, 1)), fi.first->vertex(indices(fi.second, 2)))) - return NOT_FLIPPABLE; + { + min_flip_dihedral_angle = (std::min)(min_flip_dihedral_angle, + min_dihedral_angle(tr, vh, fi.first->vertex(indices(fi.second, 0)), + fi.first->vertex(indices(fi.second, 1)), + fi.first->vertex(indices(fi.second, 2)))); + } + else + { + keep = false; + break; + } + } } - for (const Facet& fi : facets_for_updated_cells) + + if (keep && (curr_min_dh < min_flip_dihedral_angle || !is_sliver_well_oriented)) { - if ( !tr.is_infinite(fi.first) - && !is_well_oriented(tr, vh, fi.first->vertex(indices(fi.second, 0)), - fi.first->vertex(indices(fi.second, 1)), - fi.first->vertex(indices(fi.second, 2)))) - return NOT_FLIPPABLE; + //std::cout << "vh " << vh->info() <<" old " << curr_min_dh << " min " << min_flip_dihedral_angle << std::endl; + candidates.push(std::make_pair(min_flip_dihedral_angle, std::make_pair(vh, e_id))); } + } +} - ///********************VALIDITY CHECK***************************/ - //double current_min_dh = DBL_MAX; +template +Sliver_removal_result flip_n_to_m(C3t3& c3t3, + typename C3t3::Edge& edge, + typename C3t3::Vertex_handle vh, + Visitor& visitor, + bool check_validity = false) +{ + CGAL_USE(check_validity); + // std::cout << "n_to_m_flip::start" << std::endl; + typedef typename C3t3::Triangulation Tr; + typedef typename C3t3::Vertex_handle Vertex_handle; + typedef typename C3t3::Cell_handle Cell_handle; + typedef typename C3t3::Facet Facet; + typedef typename Tr::Facet_circulator Facet_circulator; + typedef typename Tr::Cell_circulator Cell_circulator; - //if (check_validity){ + Tr& tr = c3t3.triangulation(); - // pre_sliver_Removal_cells.clear(); - // do{ - // pre_sliver_Removal_cells.push_back(K::Tetrahedron_3(cell_circulator->vertex(0)->point(), cell_circulator->vertex(1)->point(), - // cell_circulator->vertex(2)->point(), cell_circulator->vertex(3)->point())); + Vertex_handle vh0 = edge.first->vertex(edge.second); + Vertex_handle vh1 = edge.first->vertex(edge.third); - // if (!tr.is_infinite(cell_circulator)) - // current_min_dh = std::min(current_min_dh, min_dihedral_angle(cell_circulator)); - // } while (++cell_circulator != done); + //This vertex will have its valence augmenting a lot, + //TODO take the best one - // pre_sliver_Removal_vertices.clear(); - // pre_sliver_Removal_vertices.push_back(vh->point()); + //TODO!!!! Check that the created edges do not exist!!! - // previous_edges.clear(); - // previous_edges.push_back(std::make_pair(vh0->point(), vh1->point())); - //} - ///*************************************************************/ + Facet_circulator facet_circulator = tr.incident_facets(edge); + Facet_circulator done_facet_circulator = facet_circulator; + bool look_for_vh_iterator = true; + do + { + facet_circulator++; - //Subdomain index? - typename C3t3::Subdomain_index subdomain = to_remove[0]->subdomain_index(); - visitor.before_flip(to_remove[0]); + //Get the ids of the opposite vertices + for (int i = 0; i < 3; ++i) + { + if (facet_circulator->first->vertex(indices(facet_circulator->second, i)) == vh) + look_for_vh_iterator = false; + } + } while (facet_circulator != done_facet_circulator && look_for_vh_iterator); + + if (look_for_vh_iterator){ + std::cout << "Vertex not an opposite of the edge!!" << std::endl; + return NOT_FLIPPABLE; + } + + Facet_circulator facet_done(facet_circulator); + facet_done--; + facet_circulator++; + facet_circulator++; + + std::vector vertices_around_edge; + do + { + //Get the ids of the opposite vertices + for (int i = 0; i < 3; ++i) + { + Vertex_handle curr_vertex = facet_circulator->first->vertex( + indices(facet_circulator->second, i)); + if (curr_vertex != vh0 && curr_vertex != vh1) + { + Cell_handle ch; + int i0, i1; + if (tr.is_edge(curr_vertex, vh, ch, i0, i1)) + return NOT_FLIPPABLE; + + vertices_around_edge.push_back(curr_vertex); + } + } + } while (++facet_circulator != facet_done); + + + std::vector cells_around_edge; + std::vector to_remove; + + //Neighbors that will need to be updated after flip + boost::unordered_set neighbor_facets; + + //Facets that will be used to create new cells + // i.e. all the facets opposite to vh1 and don't have vh + std::vector facets_for_new_cells; + + //Facets that will be used to update cells + // i.e. all the facets opposite to vh0 will be set to vh : + // facet.first->set_vertex( facet.second, vh ) + std::vector facets_for_updated_cells; + + Cell_circulator cell_circulator = tr.incident_cells(edge); + Cell_circulator done = cell_circulator; + do + { + cells_around_edge.push_back(cell_circulator); + + //Facets opposite to vh0 + Facet facet_vh0(cell_circulator, cell_circulator->index(vh0)); + neighbor_facets.insert(tr.mirror_facet(facet_vh0)); + + //Facets opposite to vh1 + Facet facet_vh1(cell_circulator, cell_circulator->index(vh1)); + neighbor_facets.insert(tr.mirror_facet(facet_vh1)); + + //Store it if it do not have vh + if (cell_circulator->has_vertex(vh)){ + to_remove.push_back(cell_circulator); + } + else + { + facets_for_new_cells.push_back(facet_vh1); + facets_for_updated_cells.push_back(facet_vh0); + } + // + // if( ! is_well_oriented( cell_circulator ) ) + // return WRONG; + } + while (++cell_circulator != done); + + //Check that the result will be valid + for (const Facet& fi : facets_for_new_cells) + { + if ( !tr.is_infinite(fi.first) + && !is_well_oriented(tr, vh, fi.first->vertex(indices(fi.second, 0)), + fi.first->vertex(indices(fi.second, 1)), + fi.first->vertex(indices(fi.second, 2)))) + return NOT_FLIPPABLE; + } + for (const Facet& fi : facets_for_updated_cells) + { + if ( !tr.is_infinite(fi.first) + && !is_well_oriented(tr, vh, fi.first->vertex(indices(fi.second, 0)), + fi.first->vertex(indices(fi.second, 1)), + fi.first->vertex(indices(fi.second, 2)))) + return NOT_FLIPPABLE; + } + + ///********************VALIDITY CHECK***************************/ + //double current_min_dh = DBL_MAX; + + //if (check_validity){ + + // pre_sliver_Removal_cells.clear(); + // do{ + // pre_sliver_Removal_cells.push_back(K::Tetrahedron_3(cell_circulator->vertex(0)->point(), cell_circulator->vertex(1)->point(), + // cell_circulator->vertex(2)->point(), cell_circulator->vertex(3)->point())); + + // if (!tr.is_infinite(cell_circulator)) + // current_min_dh = std::min(current_min_dh, min_dihedral_angle(cell_circulator)); + // } while (++cell_circulator != done); + + // pre_sliver_Removal_vertices.clear(); + // pre_sliver_Removal_vertices.push_back(vh->point()); + + // previous_edges.clear(); + // previous_edges.push_back(std::make_pair(vh0->point(), vh1->point())); + //} + ///*************************************************************/ + + //Subdomain index? + typename C3t3::Subdomain_index subdomain = to_remove[0]->subdomain_index(); + visitor.before_flip(to_remove[0]); #ifdef CGAL_TETRAHEDRAL_REMESHING_DEBUG - for (std::size_t i = 1; i < to_remove.size(); ++i) - CGAL_assertion(subdomain == to_remove[i]->subdomain_index()); + for (std::size_t i = 1; i < to_remove.size(); ++i) + CGAL_assertion(subdomain == to_remove[i]->subdomain_index()); #endif - std::vector cells_to_update; + std::vector cells_to_update; - //Create new cells - for (const Facet& fi : facets_for_new_cells) - { - Cell_handle new_cell = tr.tds().create_cell(); + //Create new cells + for (const Facet& fi : facets_for_new_cells) + { + Cell_handle new_cell = tr.tds().create_cell(); - for (int v = 0; v < 4; v++){ - new_cell->set_vertex(v, fi.first->vertex(v)); - } - - new_cell->set_vertex(fi.second, vh); - - c3t3.add_to_complex(new_cell, subdomain); - visitor.after_flip(new_cell); - cells_to_update.push_back(new_cell); + for (int v = 0; v < 4; v++){ + new_cell->set_vertex(v, fi.first->vertex(v)); } - //Update_existing cells - for (const Facet& fi : facets_for_updated_cells) + new_cell->set_vertex(fi.second, vh); + + c3t3.add_to_complex(new_cell, subdomain); + visitor.after_flip(new_cell); + cells_to_update.push_back(new_cell); + } + + //Update_existing cells + for (const Facet& fi : facets_for_updated_cells) + { + fi.first->set_vertex(fi.second, vh); + cells_to_update.push_back(fi.first); + } + + typedef CGAL::Triple Facet_vvv; + typedef boost::unordered_map FaceMapIndex; + + FaceMapIndex facet_map_indices; + std::vector facets; + + for (const Facet& f : neighbor_facets) + { + Cell_handle ch = f.first; + int v = f.second; + + Facet_vvv face = make_vertex_triple(ch->vertex(indices(v,0)), + ch->vertex(indices(v,1)), + ch->vertex(indices(v,2))); + typename FaceMapIndex::iterator it = facet_map_indices.find(face); + if (it == facet_map_indices.end()) { - fi.first->set_vertex(fi.second, vh); - cells_to_update.push_back(fi.first); + facet_map_indices[face] = facets.size(); + facets.push_back(Facet(ch, v)); } + } - typedef CGAL::Triple Facet_vvv; - typedef boost::unordered_map FaceMapIndex; - - FaceMapIndex facet_map_indices; - std::vector facets; - - for (const Facet& f : neighbor_facets) + //Update adjacencies and vertices cells + for (Cell_handle ch : cells_to_update) + { + for (int v = 0; v < 4; v++) { - Cell_handle ch = f.first; - int v = f.second; - Facet_vvv face = make_vertex_triple(ch->vertex(indices(v,0)), ch->vertex(indices(v,1)), ch->vertex(indices(v,2))); @@ -851,348 +867,332 @@ namespace internal facet_map_indices[face] = facets.size(); facets.push_back(Facet(ch, v)); } - } - - //Update adjacencies and vertices cells - for (Cell_handle ch : cells_to_update) - { - for (int v = 0; v < 4; v++) - { - Facet_vvv face = make_vertex_triple(ch->vertex(indices(v,0)), - ch->vertex(indices(v,1)), - ch->vertex(indices(v,2))); - typename FaceMapIndex::iterator it = facet_map_indices.find(face); - if (it == facet_map_indices.end()) - { - facet_map_indices[face] = facets.size(); - facets.push_back(Facet(ch, v)); - } - else - { - Facet facet = facets[it->second]; - - //Update neighbor - facet.first->set_neighbor(facet.second, ch); - ch->set_neighbor(v, facet.first); - } - ch->vertex(v)->set_cell(ch); - } - } - - //Remove cells - for (Cell_handle ch : to_remove) - { - c3t3.remove_from_complex(ch); - tr.tds().delete_cell(ch); - } - - // Update c3t3 - update_c3t3_facets(c3t3, cells_to_update, neighbor_facets); - - - ///********************VALIDITY CHECK***************************/ - //if (check_validity){ - - // double new_min_dh = DBL_MAX; - - // post_sliver_Removal_cells.clear(); - // for (unsigned int i = 0; i < cells_to_update.size(); ++i){ - // post_sliver_Removal_cells.push_back(cells_to_update[i]); - - // if (!tr.is_infinite(cells_to_update[i])) - // new_min_dh = std::min(new_min_dh, min_dihedral_angle(cells_to_update[i])); - // } - - // post_sliver_Removal_vertices.clear(); - // for (unsigned int i = 0; i < vertices_around_edge.size(); ++i){ - // post_sliver_Removal_vertices.push_back(vertices_around_edge[i]); - // } - - // current_edges.clear(); - // for (unsigned int i = 0; i < vertices_around_edge.size(); ++i){ - // current_edges.push_back(std::make_pair(vertices_around_edge[i]->point(), vh->point())); - // } - - - // for (unsigned int i = 0; i < cells_to_update.size(); ++i){ - // if (!tr.is_valid(cells_to_update[i])) - // return INVALID_CELL; - - // for (int v = 0; v < 4; v++){ - // if (!tr.is_valid(cells_to_update[i]->neighbor(v))) - // return INVALID_CELL; - - // if (!tr.tds().is_valid(cells_to_update[i]->vertex(v))) - // return INVALID_VERTEX; - - // } - // } - - // if ((current_min_dh - new_min_dh) > 0.01){ - // std::cout << pre_sliver_Removal_cells.size() << " to " << post_sliver_Removal_cells.size() << " flip not improving the quality: " << - // current_min_dh << " to " << new_min_dh << std::endl; - // return INVALID_CELL; - // } - - //} - ///***********************************************************/ - - // std::cout << "n_to_m_flip::end with success" << std::endl; - - return VALID_FLIP; - } - - - template - Sliver_removal_result flip_n_to_m(typename C3t3::Edge& edge, - C3t3& c3t3, - std::vector& boundary_vertices, - const Flip_Criterion& criterion, - Visitor& visitor) - { - typedef typename C3t3::Vertex_handle Vertex_handle; - typedef typename C3t3::Triangulation::Cell_circulator Cell_circulator; - typedef typename C3t3::Triangulation::Geom_traits Gt; - typedef typename Gt::FT FT; - typename C3t3::Triangulation& tr = c3t3.triangulation(); - - Sliver_removal_result result = NOT_FLIPPABLE; - - typedef std::pair > Angle_and_vertex; - - //std::cout << "n_to_m_flip " << boundary_vertices.size() << std::endl; - if (criterion == MIN_ANGLE_BASED) - { - std::priority_queue candidates; - - Cell_circulator circ = c3t3.triangulation().incident_cells(edge); - Cell_circulator done = circ; - - FT curr_min_dh = min_dihedral_angle(tr, circ++); - while (circ != done) - { - curr_min_dh = (std::min)(curr_min_dh, min_dihedral_angle(tr, circ++)); - } - if (boundary_vertices.size() == 2) - find_best_flip_to_improve_dh(c3t3, edge, boundary_vertices[0], boundary_vertices[1], - candidates, curr_min_dh); else - find_best_flip_to_improve_dh(c3t3, edge, candidates, curr_min_dh); - - bool flip_performed = false; - while (!candidates.empty() && !flip_performed) { - Angle_and_vertex curr_cost_vpair = candidates.top(); - candidates.pop(); + Facet facet = facets[it->second]; - //std::cout << curr_min_dh << " old, current " << curr_cost_vpair.second.first->info() <<" and angle " << curr_cost_vpair.first << std::endl; - - if (curr_min_dh >= curr_cost_vpair.first) - return NO_BEST_CONFIGURATION; - - result = flip_n_to_m(c3t3, edge, curr_cost_vpair.second.first, visitor); - - if (result != NOT_FLIPPABLE) - flip_performed = true; + //Update neighbor + facet.first->set_neighbor(facet.second, ch); + ch->set_neighbor(v, facet.first); } + ch->vertex(v)->set_cell(ch); } - - return result; } - template - Sliver_removal_result find_best_flip(typename C3t3::Edge& edge, - C3t3& c3t3, - const Flip_Criterion& criterion, - Visitor& visitor) + //Remove cells + for (Cell_handle ch : to_remove) { - typedef typename C3t3::Triangulation Tr; - typedef typename C3t3::Vertex_handle Vertex_handle; + c3t3.remove_from_complex(ch); + tr.tds().delete_cell(ch); + } + + // Update c3t3 + update_c3t3_facets(c3t3, cells_to_update, neighbor_facets); + + + ///********************VALIDITY CHECK***************************/ + //if (check_validity){ + + // double new_min_dh = DBL_MAX; + + // post_sliver_Removal_cells.clear(); + // for (unsigned int i = 0; i < cells_to_update.size(); ++i){ + // post_sliver_Removal_cells.push_back(cells_to_update[i]); + + // if (!tr.is_infinite(cells_to_update[i])) + // new_min_dh = std::min(new_min_dh, min_dihedral_angle(cells_to_update[i])); + // } + + // post_sliver_Removal_vertices.clear(); + // for (unsigned int i = 0; i < vertices_around_edge.size(); ++i){ + // post_sliver_Removal_vertices.push_back(vertices_around_edge[i]); + // } + + // current_edges.clear(); + // for (unsigned int i = 0; i < vertices_around_edge.size(); ++i){ + // current_edges.push_back(std::make_pair(vertices_around_edge[i]->point(), vh->point())); + // } + + + // for (unsigned int i = 0; i < cells_to_update.size(); ++i){ + // if (!tr.is_valid(cells_to_update[i])) + // return INVALID_CELL; + + // for (int v = 0; v < 4; v++){ + // if (!tr.is_valid(cells_to_update[i]->neighbor(v))) + // return INVALID_CELL; + + // if (!tr.tds().is_valid(cells_to_update[i]->vertex(v))) + // return INVALID_VERTEX; + + // } + // } + + // if ((current_min_dh - new_min_dh) > 0.01){ + // std::cout << pre_sliver_Removal_cells.size() << " to " << post_sliver_Removal_cells.size() << " flip not improving the quality: " << + // current_min_dh << " to " << new_min_dh << std::endl; + // return INVALID_CELL; + // } + + //} + ///***********************************************************/ + + // std::cout << "n_to_m_flip::end with success" << std::endl; + + return VALID_FLIP; +} + + +template +Sliver_removal_result flip_n_to_m(typename C3t3::Edge& edge, + C3t3& c3t3, + std::vector& boundary_vertices, + const Flip_Criterion& criterion, + Visitor& visitor) +{ + typedef typename C3t3::Vertex_handle Vertex_handle; + typedef typename C3t3::Triangulation::Cell_circulator Cell_circulator; + typedef typename C3t3::Triangulation::Geom_traits Gt; + typedef typename Gt::FT FT; + typename C3t3::Triangulation& tr = c3t3.triangulation(); + + Sliver_removal_result result = NOT_FLIPPABLE; + + typedef std::pair > Angle_and_vertex; + + //std::cout << "n_to_m_flip " << boundary_vertices.size() << std::endl; + if (criterion == MIN_ANGLE_BASED) + { + std::priority_queue candidates; + + Cell_circulator circ = c3t3.triangulation().incident_cells(edge); + Cell_circulator done = circ; + + FT curr_min_dh = min_dihedral_angle(tr, circ++); + while (circ != done) + { + curr_min_dh = (std::min)(curr_min_dh, min_dihedral_angle(tr, circ++)); + } + if (boundary_vertices.size() == 2) + find_best_flip_to_improve_dh(c3t3, edge, boundary_vertices[0], boundary_vertices[1], + candidates, curr_min_dh); + else + find_best_flip_to_improve_dh(c3t3, edge, candidates, curr_min_dh); + + bool flip_performed = false; + while (!candidates.empty() && !flip_performed) + { + Angle_and_vertex curr_cost_vpair = candidates.top(); + candidates.pop(); + + //std::cout << curr_min_dh << " old, current " << curr_cost_vpair.second.first->info() <<" and angle " << curr_cost_vpair.first << std::endl; + + if (curr_min_dh >= curr_cost_vpair.first) + return NO_BEST_CONFIGURATION; + + result = flip_n_to_m(c3t3, edge, curr_cost_vpair.second.first, visitor); + + if (result != NOT_FLIPPABLE) + flip_performed = true; + } + } + + return result; +} + +template +Sliver_removal_result find_best_flip(typename C3t3::Edge& edge, + C3t3& c3t3, + const Flip_Criterion& criterion, + Visitor& visitor) +{ + typedef typename C3t3::Triangulation Tr; + typedef typename C3t3::Vertex_handle Vertex_handle; // typedef typename C3t3::Facet Facet; // typedef typename C3t3::Surface_patch_index Surface_patch_index; - typedef typename Tr::Facet_circulator Facet_circulator; + typedef typename Tr::Facet_circulator Facet_circulator; - Tr& tr = c3t3.triangulation(); + Tr& tr = c3t3.triangulation(); - const Vertex_handle v0 = edge.first->vertex(edge.second); - const Vertex_handle v1 = edge.first->vertex(edge.third); + const Vertex_handle v0 = edge.first->vertex(edge.second); + const Vertex_handle v1 = edge.first->vertex(edge.third); - Facet_circulator circ = tr.incident_facets(edge); - Facet_circulator done = circ; + Facet_circulator circ = tr.incident_facets(edge); + Facet_circulator done = circ; - //Identify the vertices around this edge - boost::unordered_set vertices_around_edge; - bool boundary_edge = false; - bool hull_edge = false; + //Identify the vertices around this edge + boost::unordered_set vertices_around_edge; + bool boundary_edge = false; + bool hull_edge = false; - boost::unordered_set boundary_vertices; - boost::unordered_set hull_vertices; - do + boost::unordered_set boundary_vertices; + boost::unordered_set hull_vertices; + do + { + //Get the ids of the opposite vertices + for (int i = 0; i < 3; ++i) { - //Get the ids of the opposite vertices - for (int i = 0; i < 3; ++i) + Vertex_handle vi = circ->first->vertex(indices(circ->second, i)); + if (vi != v0 && vi != v1) { - Vertex_handle vi = circ->first->vertex(indices(circ->second, i)); - if (vi != v0 && vi != v1) + vertices_around_edge.insert(vi); + + if ( circ->first->subdomain_index() + != circ->first->neighbor(circ->second)->subdomain_index()) { - vertices_around_edge.insert(vi); + boundary_edge = true; + boundary_vertices.insert(vi); + } - if ( circ->first->subdomain_index() - != circ->first->neighbor(circ->second)->subdomain_index()) - { - boundary_edge = true; - boundary_vertices.insert(vi); - } - - if ( tr.is_infinite(circ->first) - != tr.is_infinite(circ->first->neighbor(circ->second))) - { - hull_edge = true; - hull_vertices.insert(vi); - } + if ( tr.is_infinite(circ->first) + != tr.is_infinite(circ->first->neighbor(circ->second))) + { + hull_edge = true; + hull_vertices.insert(vi); } } } - while (++circ != done); + } + while (++circ != done); - //Check if not feature edge - if (boundary_vertices.size() > 2) - return NOT_FLIPPABLE; + //Check if not feature edge + if (boundary_vertices.size() > 2) + return NOT_FLIPPABLE; - // perform flip when possible - Sliver_removal_result res = NOT_FLIPPABLE; - if (vertices_around_edge.size() == 3) + // perform flip when possible + Sliver_removal_result res = NOT_FLIPPABLE; + if (vertices_around_edge.size() == 3) + { + if (!boundary_edge && !hull_edge) { - if (!boundary_edge && !hull_edge) - { - std::vector vertices; - vertices.insert(vertices.end(), vertices_around_edge.begin(), vertices_around_edge.end()); - res = flip_3_to_2(edge, c3t3, vertices, criterion); - } + std::vector vertices; + vertices.insert(vertices.end(), vertices_around_edge.begin(), vertices_around_edge.end()); + res = flip_3_to_2(edge, c3t3, vertices, criterion); } - else + } + else + { + //TODO fix for hull edges + // if( hull_edge ) + // return n_to_m_flip( edge, hull_vertices, flip_criterion, check_validity ); + if (!hull_edge) { - //TODO fix for hull edges - // if( hull_edge ) - // return n_to_m_flip( edge, hull_vertices, flip_criterion, check_validity ); - if (!hull_edge) - { - std::vector vertices; - vertices.insert(vertices.end(), boundary_vertices.begin(), boundary_vertices.end()); - res = flip_n_to_m(edge, c3t3, vertices, criterion, visitor); - //return n_to_m_flip(edge, boundary_vertices, flip_criterion); - } + std::vector vertices; + vertices.insert(vertices.end(), boundary_vertices.begin(), boundary_vertices.end()); + res = flip_n_to_m(edge, c3t3, vertices, criterion, visitor); + //return n_to_m_flip(edge, boundary_vertices, flip_criterion); } - - - return res; } - template - std::size_t flip_all_edges(std::vector& edges, - C3t3& c3t3, - const Flip_Criterion& criterion, - Visitor& visitor) - { - typedef typename C3t3::Triangulation Tr; + return res; +} + + +template +std::size_t flip_all_edges(std::vector& edges, + C3t3& c3t3, + const Flip_Criterion& criterion, + Visitor& visitor) +{ + typedef typename C3t3::Triangulation Tr; // typedef typename Tr::Vertex_handle Vertex_handle; - typedef typename Tr::Cell_handle Cell_handle; - typedef typename Tr::Edge Edge; + typedef typename Tr::Cell_handle Cell_handle; + typedef typename Tr::Edge Edge; - Tr& tr = c3t3.triangulation(); + Tr& tr = c3t3.triangulation(); - std::size_t count = 0; - for (const VertexPair vp : edges) + std::size_t count = 0; + for (const VertexPair vp : edges) + { + Cell_handle ch; + int i0, i1; + if (tr.is_edge(vp.first, vp.second, ch, i0, i1)) { - Cell_handle ch; - int i0, i1; - if (tr.is_edge(vp.first, vp.second, ch, i0, i1)) - { - Edge edge(ch, i0, i1); + Edge edge(ch, i0, i1); - Sliver_removal_result res = find_best_flip(edge, c3t3, criterion, visitor); - if (res == INVALID_CELL || res == INVALID_VERTEX || res == INVALID_ORIENTATION) - { - std::cout << "FLIP PROBLEM!!!!" << std::endl; - return count; - } - if (res == VALID_FLIP) - { - ++count; + Sliver_removal_result res = find_best_flip(edge, c3t3, criterion, visitor); + if (res == INVALID_CELL || res == INVALID_VERTEX || res == INVALID_ORIENTATION) + { + std::cout << "FLIP PROBLEM!!!!" << std::endl; + return count; + } + if (res == VALID_FLIP) + { + ++count; #ifdef CGAL_TETRAHEDRAL_REMESHING_VERBOSE_PROGRESS - std::cout << "\rFlip... ("; - std::cout << count << " flips)"; - std::cout.flush(); + std::cout << "\rFlip... ("; + std::cout << count << " flips)"; + std::cout.flush(); #endif - } } } - return count; } + return count; +} - template - void flip_edges(C3T3& c3t3, - const bool protect_boundaries, - CellSelector cell_selector, - Visitor& visitor) - { - CGAL_USE(protect_boundaries); - typedef typename C3T3::Triangulation T3; - typedef typename T3::Vertex_handle Vertex_handle; - typedef typename std::pair Edge_vv; +template +void flip_edges(C3T3& c3t3, + const bool protect_boundaries, + CellSelector cell_selector, + Visitor& visitor) +{ + CGAL_USE(protect_boundaries); + typedef typename C3T3::Triangulation T3; + typedef typename T3::Vertex_handle Vertex_handle; + typedef typename std::pair Edge_vv; #ifdef CGAL_TETRAHEDRAL_REMESHING_VERBOSE - std::cout << "Flip edges..."; - std::cout.flush(); - std::size_t nb_flips = 0; + std::cout << "Flip edges..."; + std::cout.flush(); + std::size_t nb_flips = 0; #endif - //const Flip_Criterion criterion = VALENCE_MIN_DH_BASED; + //const Flip_Criterion criterion = VALENCE_MIN_DH_BASED; - //collect long edges + //collect long edges - //compute vertices normals map? + //compute vertices normals map? - // typedef typename C3T3::Surface_patch_index Surface_patch_index; - // typedef boost::unordered_map Spi_map; - //if (!protect_boundaries) - //{ - // std::cout << "\tBoundary flips" << std::endl; - // //Boundary flip - // std::vector boundary_vertices_valences; - // std::vector boundary_edges; + // typedef typename C3T3::Surface_patch_index Surface_patch_index; + // typedef boost::unordered_map Spi_map; + //if (!protect_boundaries) + //{ + // std::cout << "\tBoundary flips" << std::endl; + // //Boundary flip + // std::vector boundary_vertices_valences; + // std::vector boundary_edges; - // collectBoundaryEdges(boundary_edges); + // collectBoundaryEdges(boundary_edges); - // computeVerticesValences(boundary_vertices_valences); + // computeVerticesValences(boundary_vertices_valences); - // if (criterion == VALENCE_BASED) - // flipBoundaryEdges(boundary_edges, boundary_vertices_valences, VALENCE_BASED); - // else - // flipBoundaryEdges(boundary_edges, boundary_vertices_valences, MIN_ANGLE_BASED); - //} + // if (criterion == VALENCE_BASED) + // flipBoundaryEdges(boundary_edges, boundary_vertices_valences, VALENCE_BASED); + // else + // flipBoundaryEdges(boundary_edges, boundary_vertices_valences, MIN_ANGLE_BASED); + //} - std::vector inside_edges; - get_internal_edges(c3t3, - cell_selector, - std::back_inserter(inside_edges)); + std::vector inside_edges; + get_internal_edges(c3t3, + cell_selector, + std::back_inserter(inside_edges)); - //if (criterion == VALENCE_BASED) - // flip_inside_edges(inside_edges); - //else - //{ + //if (criterion == VALENCE_BASED) + // flip_inside_edges(inside_edges); + //else + //{ #ifdef CGAL_TETRAHEDRAL_REMESHING_VERBOSE - nb_flips = + nb_flips = #endif - flip_all_edges(inside_edges, c3t3, MIN_ANGLE_BASED, visitor); - //} + flip_all_edges(inside_edges, c3t3, MIN_ANGLE_BASED, visitor); + //} #ifdef CGAL_TETRAHEDRAL_REMESHING_VERBOSE - std::cout << " done (" << nb_flips << " flips)." << std::endl; + std::cout << " done (" << nb_flips << " flips)." << std::endl; #endif - } +} }//namespace internal }//namespace Tetrahedral_remeshing diff --git a/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/smooth_vertices.h b/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/smooth_vertices.h index 5b0f6b4c90b..f8f430b8b9b 100644 --- a/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/smooth_vertices.h +++ b/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/smooth_vertices.h @@ -28,687 +28,687 @@ namespace CGAL { - namespace Tetrahedral_remeshing +namespace Tetrahedral_remeshing +{ +namespace internal +{ +template +class Tetrahedral_remeshing_smoother +{ + typedef typename C3t3::Triangulation Tr; + typedef typename C3t3::Surface_patch_index Surface_patch_index; + typedef typename Tr::Vertex_handle Vertex_handle; + typedef typename Tr::Edge Edge; + typedef typename Tr::Facet Facet; + + typedef typename Tr::Geom_traits Gt; + typedef typename Gt::Vector_3 Vector_3; + typedef typename Gt::Point_3 Point_3; + +private: + typedef CGAL::Tetrahedral_remeshing::internal::FMLS FMLS; + std::vector subdomain_FMLS; + boost::unordered_map subdomain_FMLS_indices; + +public: + template + void init(const C3t3& c3t3, const CellSelector& cell_selector) { - namespace internal + //collect a map of vertices surface indices + boost::unordered_map > vertices_surface_indices; + collect_vertices_surface_indices(c3t3, vertices_surface_indices); + + //collect a map of normals at surface vertices + boost::unordered_map > vertices_normals; + compute_vertices_normals(c3t3, vertices_normals, cell_selector); + + // Build MLS Surfaces + createMLSSurfaces(subdomain_FMLS, + subdomain_FMLS_indices, + vertices_normals, + vertices_surface_indices, + c3t3); + } + +private: + +Vector_3 project_on_tangent_plane(const Vector_3& gi, + const Vector_3& pi, + const Vector_3& normal) +{ + Vector_3 diff = pi - gi; + return gi + (normal * diff) * normal; +} + +template +boost::optional + find_adjacent_facet_on_surface(const Facet& f, + const Edge& edge, + const C3t3& c3t3, + const CellSelector& cell_selector) +{ + CGAL_assertion(is_boundary(c3t3, f, cell_selector)); + + typedef typename Tr::Facet_circulator Facet_circulator; + + if (c3t3.is_in_complex(edge)) + return {}; //do not "cross" complex edges + //they are likely to be sharp and not to follow the > 0 dot product criterion + + const Surface_patch_index& patch = c3t3.surface_patch_index(f); + const Facet& mf = c3t3.triangulation().mirror_facet(f); + + Facet_circulator fcirc = c3t3.triangulation().incident_facets(edge); + Facet_circulator fend = fcirc; + do + { + const Facet fi = *fcirc; + if (f != fi + && mf != fi + && is_boundary(c3t3, fi, cell_selector) + && patch == c3t3.surface_patch_index(fi)) { - template - class Tetrahedral_remeshing_smoother - { - typedef typename C3t3::Triangulation Tr; - typedef typename C3t3::Surface_patch_index Surface_patch_index; - typedef typename Tr::Vertex_handle Vertex_handle; - typedef typename Tr::Edge Edge; - typedef typename Tr::Facet Facet; + return canonical_facet(fi); //"canonical" is important + } + } while (++fcirc != fend); - typedef typename Tr::Geom_traits Gt; - typedef typename Gt::Vector_3 Vector_3; - typedef typename Gt::Point_3 Point_3; + return {}; +} - private: - typedef CGAL::Tetrahedral_remeshing::internal::FMLS FMLS; - std::vector subdomain_FMLS; - boost::unordered_map subdomain_FMLS_indices; +template +Vector_3 compute_normal(const Facet& f, + const Vector_3& reference_normal, + const C3t3& c3t3, + const CellSelector& cell_selector) +{ + CGAL_assertion(is_boundary(c3t3, f, cell_selector)); - public: - template - void init(const C3t3& c3t3, const CellSelector& cell_selector) - { - //collect a map of vertices surface indices - boost::unordered_map > vertices_surface_indices; - collect_vertices_surface_indices(c3t3, vertices_surface_indices); + typename Tr::Geom_traits::Construct_opposite_vector_3 + opp = c3t3.triangulation().geom_traits().construct_opposite_vector_3_object(); + typename Tr::Geom_traits::Compute_scalar_product_3 + scalar_product = c3t3.triangulation().geom_traits().compute_scalar_product_3_object(); - //collect a map of normals at surface vertices - boost::unordered_map > vertices_normals; - compute_vertices_normals(c3t3, vertices_normals, cell_selector); + Vector_3 n = CGAL::Tetrahedral_remeshing::normal(f, c3t3.triangulation().geom_traits()); + if (scalar_product(n, reference_normal) < 0.) + n = opp(n); - // Build MLS Surfaces - createMLSSurfaces(subdomain_FMLS, - subdomain_FMLS_indices, - vertices_normals, - vertices_surface_indices, - c3t3); - } + return n; +} - private: - - Vector_3 project_on_tangent_plane(const Vector_3& gi, - const Vector_3& pi, - const Vector_3& normal) - { - Vector_3 diff = pi - gi; - return gi + (normal * diff) * normal; - } - - template - boost::optional - find_adjacent_facet_on_surface(const Facet& f, - const Edge& edge, - const C3t3& c3t3, - const CellSelector& cell_selector) - { - CGAL_assertion(is_boundary(c3t3, f, cell_selector)); - - typedef typename Tr::Facet_circulator Facet_circulator; - - if (c3t3.is_in_complex(edge)) - return {}; //do not "cross" complex edges - //they are likely to be sharp and not to follow the > 0 dot product criterion - - const Surface_patch_index& patch = c3t3.surface_patch_index(f); - const Facet& mf = c3t3.triangulation().mirror_facet(f); - - Facet_circulator fcirc = c3t3.triangulation().incident_facets(edge); - Facet_circulator fend = fcirc; - do - { - const Facet fi = *fcirc; - if (f != fi - && mf != fi - && is_boundary(c3t3, fi, cell_selector) - && patch == c3t3.surface_patch_index(fi)) - { - return canonical_facet(fi); //"canonical" is important - } - } while (++fcirc != fend); - - return {}; - } - - template - Vector_3 compute_normal(const Facet& f, - const Vector_3& reference_normal, - const C3t3& c3t3, +template +void compute_vertices_normals(const C3t3& c3t3, + VertexNormalsMap& normals_map, const CellSelector& cell_selector) - { - CGAL_assertion(is_boundary(c3t3, f, cell_selector)); - - typename Tr::Geom_traits::Construct_opposite_vector_3 - opp = c3t3.triangulation().geom_traits().construct_opposite_vector_3_object(); - typename Tr::Geom_traits::Compute_scalar_product_3 - scalar_product = c3t3.triangulation().geom_traits().compute_scalar_product_3_object(); - - Vector_3 n = CGAL::Tetrahedral_remeshing::normal(f, c3t3.triangulation().geom_traits()); - if (scalar_product(n, reference_normal) < 0.) - n = opp(n); - - return n; - } - - template - void compute_vertices_normals(const C3t3& c3t3, - VertexNormalsMap& normals_map, - const CellSelector& cell_selector) - { - typename Tr::Geom_traits::Construct_opposite_vector_3 - opp = c3t3.triangulation().geom_traits().construct_opposite_vector_3_object(); +{ + typename Tr::Geom_traits::Construct_opposite_vector_3 + opp = c3t3.triangulation().geom_traits().construct_opposite_vector_3_object(); // typename Tr::Geom_traits::Construct_scaled_vector_3 // scale = c3t3.triangulation().geom_traits().construct_scaled_vector_3_object(); - const Tr& tr = c3t3.triangulation(); + const Tr& tr = c3t3.triangulation(); - //collect all facet normals - boost::unordered_map fnormals; - for (const Facet& f : tr.finite_facets()) - { - if (is_boundary(c3t3, f, cell_selector)) - { - const Facet cf = canonical_facet(f); - fnormals[cf] = CGAL::NULL_VECTOR; - } - } + //collect all facet normals + boost::unordered_map fnormals; + for (const Facet& f : tr.finite_facets()) + { + if (is_boundary(c3t3, f, cell_selector)) + { + const Facet cf = canonical_facet(f); + fnormals[cf] = CGAL::NULL_VECTOR; + } + } - for (const std::pair& fn : fnormals) - { - if(fn.second != CGAL::NULL_VECTOR) - continue; + for (const std::pair& fn : fnormals) + { + if(fn.second != CGAL::NULL_VECTOR) + continue; - const Facet& f = fn.first; - const Facet& mf = tr.mirror_facet(f); - CGAL_assertion(is_boundary(c3t3, f, cell_selector)); + const Facet& f = fn.first; + const Facet& mf = tr.mirror_facet(f); + CGAL_assertion(is_boundary(c3t3, f, cell_selector)); - Vector_3 start_ref = CGAL::Tetrahedral_remeshing::normal(f, tr.geom_traits()); - if (c3t3.triangulation().is_infinite(mf.first) - || c3t3.subdomain_index(mf.first) < c3t3.subdomain_index(f.first)) - start_ref = opp(start_ref); - fnormals[f] = start_ref; + Vector_3 start_ref = CGAL::Tetrahedral_remeshing::normal(f, tr.geom_traits()); + if (c3t3.triangulation().is_infinite(mf.first) + || c3t3.subdomain_index(mf.first) < c3t3.subdomain_index(f.first)) + start_ref = opp(start_ref); + fnormals[f] = start_ref; - std::list facets; - facets.push_back(f); - while (!facets.empty()) - { - const Facet f = facets.front(); - facets.pop_front(); + std::list facets; + facets.push_back(f); + while (!facets.empty()) + { + const Facet f = facets.front(); + facets.pop_front(); - const typename C3t3::Cell_handle ch = f.first; - const std::array, 3> edges - = { (f.second + 1) % 4, (f.second + 2) % 4, //edge 1-2 - (f.second + 2) % 4, (f.second + 3) % 4, //edge 2-3 - (f.second + 3) % 4, (f.second + 1) % 4 //edge 3-1 - }; //vertex indices in cells + const typename C3t3::Cell_handle ch = f.first; + const std::array, 3> edges + = { (f.second + 1) % 4, (f.second + 2) % 4, //edge 1-2 + (f.second + 2) % 4, (f.second + 3) % 4, //edge 2-3 + (f.second + 3) % 4, (f.second + 1) % 4 //edge 3-1 + }; //vertex indices in cells - const Vector_3& ref = fnormals[f]; - for (const std::array& ei : edges) - { - Edge edge(ch, ei[0], ei[1]); - if (boost::optional neighbor - = find_adjacent_facet_on_surface(f, edge, c3t3, cell_selector)) - { - const Facet neigh = *neighbor; //already a canonical_facet - if (fnormals[neigh] == CGAL::NULL_VECTOR) //check it's not already computed - { - fnormals[neigh] = compute_normal(neigh, ref, c3t3, cell_selector); - facets.push_back(neigh); - } - } - } - } - } - -#ifdef CGAL_TETRAHEDRAL_REMESHING_DEBUG - std::ofstream osf("dump_facet_normals.polylines.txt"); -#endif - for (const auto& fn : fnormals) - { - const Facet& f = fn.first; - const Vector_3& n = fn.second; - -#ifdef CGAL_TETRAHEDRAL_REMESHING_DEBUG - typename Tr::Geom_traits::Point_3 fc - = CGAL::centroid(point(f.first->vertex(indices(f.second, 0))->point()), - point(f.first->vertex(indices(f.second, 1))->point()), - point(f.first->vertex(indices(f.second, 2))->point())); - osf << "2 " << fc << " " << (fc + n) << std::endl; -#endif - const Surface_patch_index& surf_i = c3t3.surface_patch_index(f); - - for (int i = 0; i < 3; ++i) - { - const Vertex_handle vi = f.first->vertex(indices(f.second, i)); - typename VertexNormalsMap::iterator patch_vector_it = normals_map.find(vi); - - if (patch_vector_it == normals_map.end() - || patch_vector_it->second.find(surf_i) == patch_vector_it->second.end()) - { - normals_map[vi][surf_i] = n; - } - else - { - normals_map[vi][surf_i] += n; - } - } - } - -#ifdef CGAL_TETRAHEDRAL_REMESHING_DEBUG - osf.close(); - std::ofstream os("dump_normals.polylines.txt"); - boost::unordered_map > ons_map; -#endif - - //normalize the computed normals - for (typename VertexNormalsMap::iterator vnm_it = normals_map.begin(); - vnm_it != normals_map.end(); ++vnm_it) - { - //value type is map - for (typename VertexNormalsMap::mapped_type::iterator it = vnm_it->second.begin(); - it != vnm_it->second.end(); ++it) - { - Vector_3& n = it->second; - -#ifdef CGAL_TETRAHEDRAL_REMESHING_DEBUG - auto p = point(vnm_it->first->point()); - os << "2 " << p << " " << (p + n) << std::endl; -#endif - - CGAL::Tetrahedral_remeshing::normalize(n, c3t3.triangulation().geom_traits()); - -#ifdef CGAL_TETRAHEDRAL_REMESHING_DEBUG - const Surface_patch_index si = it->first; - if (ons_map.find(si) == ons_map.end()) - ons_map[si] = std::vector(); - ons_map[si].push_back(typename Tr::Geom_traits::Segment_3(p, p + n)); -#endif - } - } - -#ifdef CGAL_TETRAHEDRAL_REMESHING_DEBUG - os.close(); - for (auto& kv : ons_map) - { - std::ostringstream oss; - oss << "dump_normals_normalized_" << kv.first << ".polylines.txt"; - std::ofstream ons(oss.str()); - for (auto s : kv.second) - ons << "2 " << s.source() << " " << s.target() << std::endl; - ons.close(); - } -#endif - } - - boost::optional project(const Surface_patch_index& si, - const Vector_3& gi) + const Vector_3& ref = fnormals[f]; + for (const std::array& ei : edges) { - CGAL_assertion(subdomain_FMLS_indices.find(si) != subdomain_FMLS_indices.end()); - CGAL_assertion(!std::isnan(gi.x()) && !std::isnan(gi.y()) && !std::isnan(gi.z())); - - Vector_3 point(gi.x(), gi.y(), gi.z()); - Vector_3 res_normal; - Vector_3 result(point); - - const FMLS& fmls = subdomain_FMLS[subdomain_FMLS_indices.at(si)]; - - int it_nb = 0; - const int max_it_nb = 5; - const float epsilon = fmls.getPNScale() / 1000.; - const float sq_eps = CGAL::square(epsilon); - - do + Edge edge(ch, ei[0], ei[1]); + if (boost::optional neighbor + = find_adjacent_facet_on_surface(f, edge, c3t3, cell_selector)) { - point = result; - - fmls.fastProjectionCPU(point, result, res_normal); - - if (std::isnan(result[0]) || std::isnan(result[1]) || std::isnan(result[2])) { - std::cout << "MLS error detected si " << si - << "\t(size : " << fmls.getPNSize() << ")" - << "\t(point = " << point << " )" << std::endl; - return {}; - } - } while ((result - point).squared_length() > sq_eps && ++it_nb < max_it_nb); - - return Vector_3(result[0], result[1], result[2]); - } - - template - void check_inversion_and_move(const typename Tr::Vertex_handle v, - const typename Tr::Point& final_pos, - const CellRange& inc_cells, - const Tr& /* tr */) - { - const typename Tr::Point backup = v->point(); //backup v's position - const typename Tr::Geom_traits::Point_3 pv = point(backup); - - bool valid_orientation = false; - double frac = 1.0; - typename Tr::Geom_traits::Vector_3 move(pv, point(final_pos)); - do - { - v->set_point(typename Tr::Point(pv + frac * move)); - - bool valid_try = true; - for (const typename Tr::Cell_handle ci : inc_cells) + const Facet neigh = *neighbor; //already a canonical_facet + if (fnormals[neigh] == CGAL::NULL_VECTOR) //check it's not already computed { - if (CGAL::POSITIVE != CGAL::orientation(point(ci->vertex(0)->point()), - point(ci->vertex(1)->point()), - point(ci->vertex(2)->point()), - point(ci->vertex(3)->point()))) - { - frac = 0.9 * frac; - valid_try = false; - break; - } + fnormals[neigh] = compute_normal(neigh, ref, c3t3, cell_selector); + facets.push_back(neigh); } - valid_orientation = valid_try; + } + } + } + } + +#ifdef CGAL_TETRAHEDRAL_REMESHING_DEBUG + std::ofstream osf("dump_facet_normals.polylines.txt"); +#endif + for (const auto& fn : fnormals) + { + const Facet& f = fn.first; + const Vector_3& n = fn.second; + +#ifdef CGAL_TETRAHEDRAL_REMESHING_DEBUG + typename Tr::Geom_traits::Point_3 fc + = CGAL::centroid(point(f.first->vertex(indices(f.second, 0))->point()), + point(f.first->vertex(indices(f.second, 1))->point()), + point(f.first->vertex(indices(f.second, 2))->point())); + osf << "2 " << fc << " " << (fc + n) << std::endl; +#endif + const Surface_patch_index& surf_i = c3t3.surface_patch_index(f); + + for (int i = 0; i < 3; ++i) + { + const Vertex_handle vi = f.first->vertex(indices(f.second, i)); + typename VertexNormalsMap::iterator patch_vector_it = normals_map.find(vi); + + if (patch_vector_it == normals_map.end() + || patch_vector_it->second.find(surf_i) == patch_vector_it->second.end()) + { + normals_map[vi][surf_i] = n; + } + else + { + normals_map[vi][surf_i] += n; + } + } + } + +#ifdef CGAL_TETRAHEDRAL_REMESHING_DEBUG + osf.close(); + std::ofstream os("dump_normals.polylines.txt"); + boost::unordered_map > ons_map; +#endif + + //normalize the computed normals + for (typename VertexNormalsMap::iterator vnm_it = normals_map.begin(); + vnm_it != normals_map.end(); ++vnm_it) + { + //value type is map + for (typename VertexNormalsMap::mapped_type::iterator it = vnm_it->second.begin(); + it != vnm_it->second.end(); ++it) + { + Vector_3& n = it->second; + +#ifdef CGAL_TETRAHEDRAL_REMESHING_DEBUG + auto p = point(vnm_it->first->point()); + os << "2 " << p << " " << (p + n) << std::endl; +#endif + + CGAL::Tetrahedral_remeshing::normalize(n, c3t3.triangulation().geom_traits()); + +#ifdef CGAL_TETRAHEDRAL_REMESHING_DEBUG + const Surface_patch_index si = it->first; + if (ons_map.find(si) == ons_map.end()) + ons_map[si] = std::vector(); + ons_map[si].push_back(typename Tr::Geom_traits::Segment_3(p, p + n)); +#endif + } + } + +#ifdef CGAL_TETRAHEDRAL_REMESHING_DEBUG + os.close(); + for (auto& kv : ons_map) + { + std::ostringstream oss; + oss << "dump_normals_normalized_" << kv.first << ".polylines.txt"; + std::ofstream ons(oss.str()); + for (auto s : kv.second) + ons << "2 " << s.source() << " " << s.target() << std::endl; + ons.close(); + } +#endif +} + +boost::optional project(const Surface_patch_index& si, + const Vector_3& gi) +{ + CGAL_assertion(subdomain_FMLS_indices.find(si) != subdomain_FMLS_indices.end()); + CGAL_assertion(!std::isnan(gi.x()) && !std::isnan(gi.y()) && !std::isnan(gi.z())); + + Vector_3 point(gi.x(), gi.y(), gi.z()); + Vector_3 res_normal; + Vector_3 result(point); + + const FMLS& fmls = subdomain_FMLS[subdomain_FMLS_indices.at(si)]; + + int it_nb = 0; + const int max_it_nb = 5; + const float epsilon = fmls.getPNScale() / 1000.; + const float sq_eps = CGAL::square(epsilon); + + do + { + point = result; + + fmls.fastProjectionCPU(point, result, res_normal); + + if (std::isnan(result[0]) || std::isnan(result[1]) || std::isnan(result[2])) { + std::cout << "MLS error detected si " << si + << "\t(size : " << fmls.getPNSize() << ")" + << "\t(point = " << point << " )" << std::endl; + return {}; + } + } while ((result - point).squared_length() > sq_eps && ++it_nb < max_it_nb); + + return Vector_3(result[0], result[1], result[2]); +} + +template +void check_inversion_and_move(const typename Tr::Vertex_handle v, + const typename Tr::Point& final_pos, + const CellRange& inc_cells, + const Tr& /* tr */) +{ + const typename Tr::Point backup = v->point(); //backup v's position + const typename Tr::Geom_traits::Point_3 pv = point(backup); + + bool valid_orientation = false; + double frac = 1.0; + typename Tr::Geom_traits::Vector_3 move(pv, point(final_pos)); + do + { + v->set_point(typename Tr::Point(pv + frac * move)); + + bool valid_try = true; + for (const typename Tr::Cell_handle ci : inc_cells) + { + if (CGAL::POSITIVE != CGAL::orientation(point(ci->vertex(0)->point()), + point(ci->vertex(1)->point()), + point(ci->vertex(2)->point()), + point(ci->vertex(3)->point()))) + { + frac = 0.9 * frac; + valid_try = false; + break; + } + } + valid_orientation = valid_try; // std::cout << std::boolalpha << "valid orientation = " << valid_orientation // << "\tfrac = " << frac << std::endl; - } - while(!valid_orientation && frac > 0.1); + } + while(!valid_orientation && frac > 0.1); - if (!valid_orientation) //move failed - v->set_point(backup); - } + if (!valid_orientation) //move failed + v->set_point(backup); +} - void collect_vertices_surface_indices( - const C3t3& c3t3, - boost::unordered_map >& vertices_surface_indices) - { - for (typename C3t3::Facet_iterator fit = c3t3.facets_begin(); - fit != c3t3.facets_end(); ++fit) - { - const Surface_patch_index& surface_index = c3t3.surface_patch_index(*fit); +void collect_vertices_surface_indices( + const C3t3& c3t3, + boost::unordered_map >& vertices_surface_indices) +{ + for (typename C3t3::Facet_iterator fit = c3t3.facets_begin(); + fit != c3t3.facets_end(); ++fit) + { + const Surface_patch_index& surface_index = c3t3.surface_patch_index(*fit); - for (int i = 0; i < 3; i++) - { - const Vertex_handle vi = fit->first->vertex(indices(fit->second, i)); + for (int i = 0; i < 3; i++) + { + const Vertex_handle vi = fit->first->vertex(indices(fit->second, i)); - std::vector& v_surface_indices = vertices_surface_indices[vi]; - if (std::find(v_surface_indices.begin(), v_surface_indices.end(), surface_index) == v_surface_indices.end()) - v_surface_indices.push_back(surface_index); - } - } - } + std::vector& v_surface_indices = vertices_surface_indices[vi]; + if (std::find(v_surface_indices.begin(), v_surface_indices.end(), surface_index) == v_surface_indices.end()) + v_surface_indices.push_back(surface_index); + } + } +} - public: - template - void smooth_vertices(C3T3& c3t3, - const bool protect_boundaries, - const CellSelector& cell_selector) - { - typedef typename C3T3::Cell_handle Cell_handle; - typedef typename Gt::FT FT; +public: +template +void smooth_vertices(C3T3& c3t3, + const bool protect_boundaries, + const CellSelector& cell_selector) +{ + typedef typename C3T3::Cell_handle Cell_handle; + typedef typename Gt::FT FT; #ifdef CGAL_TETRAHEDRAL_REMESHING_DEBUG - std::ofstream os_surf("smooth_surfaces.polylines.txt"); - std::ofstream os_surf0("smooth_surfaces0.polylines.txt"); - std::ofstream os_vol("smooth_volume.polylines.txt"); + std::ofstream os_surf("smooth_surfaces.polylines.txt"); + std::ofstream os_surf0("smooth_surfaces0.polylines.txt"); + std::ofstream os_vol("smooth_volume.polylines.txt"); #endif #ifdef CGAL_TETRAHEDRAL_REMESHING_VERBOSE - std::cout << "Smooth vertices..."; - std::cout.flush(); - std::size_t nb_done = 0; + std::cout << "Smooth vertices..."; + std::cout.flush(); + std::size_t nb_done = 0; #endif - Tr& tr = c3t3.triangulation(); + Tr& tr = c3t3.triangulation(); #ifdef CGAL_TETRAHEDRAL_REMESHING_SMOOTH_SHARP_EDGES - //collect a map of vertices surface indices - boost::unordered_map > vertices_surface_indices; - collect_vertices_surface_indices(c3t3, vertices_surface_indices); + //collect a map of vertices surface indices + boost::unordered_map > vertices_surface_indices; + collect_vertices_surface_indices(c3t3, vertices_surface_indices); #endif - //collect a map of normals at surface vertices - boost::unordered_map > vertices_normals; - compute_vertices_normals(c3t3, vertices_normals, cell_selector); + //collect a map of normals at surface vertices + boost::unordered_map > vertices_normals; + compute_vertices_normals(c3t3, vertices_normals, cell_selector); - //smooth() - const std::size_t nbv = tr.number_of_vertices(); - boost::unordered_map vertex_id; - std::vector smoothed_positions(nbv, CGAL::NULL_VECTOR); - std::vector neighbors(nbv, -1); + //smooth() + const std::size_t nbv = tr.number_of_vertices(); + boost::unordered_map vertex_id; + std::vector smoothed_positions(nbv, CGAL::NULL_VECTOR); + std::vector neighbors(nbv, -1); - //collect ids - std::size_t id = 0; - for (const Vertex_handle v : tr.finite_vertex_handles()) - { - vertex_id[v] = id++; - } + //collect ids + std::size_t id = 0; + for (const Vertex_handle v : tr.finite_vertex_handles()) + { + vertex_id[v] = id++; + } - //collect incident cells - std::vector > - inc_cells(nbv, boost::container::small_vector()); - for (const Cell_handle c : tr.finite_cell_handles()) - { - for (int i = 0; i < 4; ++i) - { - const std::size_t id = vertex_id[c->vertex(i)]; - inc_cells[id].push_back(c); - } - } + //collect incident cells + std::vector > + inc_cells(nbv, boost::container::small_vector()); + for (const Cell_handle c : tr.finite_cell_handles()) + { + for (int i = 0; i < 4; ++i) + { + const std::size_t id = vertex_id[c->vertex(i)]; + inc_cells[id].push_back(c); + } + } - if (!protect_boundaries) - { + if (!protect_boundaries) + { #ifdef CGAL_TETRAHEDRAL_REMESHING_SMOOTH_SHARP_EDGES - /////////////// EDGES IN COMPLEX ////////////////// - //collect neighbors - for (const Edge& e : tr.finite_edges()) - { - if (c3t3.is_in_complex(e)) - { - const Vertex_handle vh0 = e.first->vertex(e.second); - const Vertex_handle vh1 = e.first->vertex(e.third); + /////////////// EDGES IN COMPLEX ////////////////// + //collect neighbors + for (const Edge& e : tr.finite_edges()) + { + if (c3t3.is_in_complex(e)) + { + const Vertex_handle vh0 = e.first->vertex(e.second); + const Vertex_handle vh1 = e.first->vertex(e.third); - const std::size_t& i0 = vertex_id.at(vh0); - const std::size_t& i1 = vertex_id.at(vh1); + const std::size_t& i0 = vertex_id.at(vh0); + const std::size_t& i1 = vertex_id.at(vh1); - const bool on_feature_v0 = is_on_feature(vh0); - const bool on_feature_v1 = is_on_feature(vh1); + const bool on_feature_v0 = is_on_feature(vh0); + const bool on_feature_v1 = is_on_feature(vh1); - if (!c3t3.is_in_complex(vh0)) - neighbors[i0] = (std::max)(0, neighbors[i0]); - if (!c3t3.is_in_complex(vh1)) - neighbors[i1] = (std::max)(0, neighbors[i1]); + if (!c3t3.is_in_complex(vh0)) + neighbors[i0] = (std::max)(0, neighbors[i0]); + if (!c3t3.is_in_complex(vh1)) + neighbors[i1] = (std::max)(0, neighbors[i1]); - if (!c3t3.is_in_complex(vh0) && on_feature_v1) - { - const Point_3& p1 = point(vh1->point()); - smoothed_positions[i0] = smoothed_positions[i0] + Vector_3(p1.x(), p1.y(), p1.z()); - neighbors[i0]++; - } - if (!c3t3.is_in_complex(vh1) && on_feature_v0) - { - const Point_3& p0 = point(vh0->point()); - smoothed_positions[i1] = smoothed_positions[i1] + Vector_3(p0.x(), p0.y(), p0.z()); - neighbors[i1]++; - } - } + if (!c3t3.is_in_complex(vh0) && on_feature_v1) + { + const Point_3& p1 = point(vh1->point()); + smoothed_positions[i0] = smoothed_positions[i0] + Vector_3(p1.x(), p1.y(), p1.z()); + neighbors[i0]++; + } + if (!c3t3.is_in_complex(vh1) && on_feature_v0) + { + const Point_3& p0 = point(vh0->point()); + smoothed_positions[i1] = smoothed_positions[i1] + Vector_3(p0.x(), p0.y(), p0.z()); + neighbors[i1]++; + } + } + } + + // Smooth + for (Vertex_handle v : tr.finite_vertex_handles()) + { + const std::size_t& vid = vertex_id.at(v); + if (neighbors[vid] > 1) + { + Vector_3 smoothed_position = smoothed_positions[vid] / neighbors[vid]; + Vector_3 final_position = CGAL::NULL_VECTOR; + + std::size_t count = 0; + const Vector_3 current_pos(CGAL::ORIGIN, point(v->point())); + + const std::vector& v_surface_indices = vertices_surface_indices[v]; + for (const Surface_patch_index& si : v_surface_indices) + { + Vector_3 normal_projection + = project_on_tangent_plane(smoothed_position, current_pos, vertices_normals[v][si]); + + //Check if the mls surface exists to avoid degenerated cases + if (boost::optional mls_projection = project(si, normal_projection)) { + final_position = final_position + *mls_projection; } + else { + final_position = final_position + normal_projection; + } + count++; + } - // Smooth - for (Vertex_handle v : tr.finite_vertex_handles()) - { - const std::size_t& vid = vertex_id.at(v); - if (neighbors[vid] > 1) - { - Vector_3 smoothed_position = smoothed_positions[vid] / neighbors[vid]; - Vector_3 final_position = CGAL::NULL_VECTOR; - - std::size_t count = 0; - const Vector_3 current_pos(CGAL::ORIGIN, point(v->point())); - - const std::vector& v_surface_indices = vertices_surface_indices[v]; - for (const Surface_patch_index& si : v_surface_indices) - { - Vector_3 normal_projection - = project_on_tangent_plane(smoothed_position, current_pos, vertices_normals[v][si]); - - //Check if the mls surface exists to avoid degenerated cases - if (boost::optional mls_projection = project(si, normal_projection)) { - final_position = final_position + *mls_projection; - } - else { - final_position = final_position + normal_projection; - } - count++; - } - - if (count > 0) - final_position = final_position / static_cast(count); - else - final_position = smoothed_position; + if (count > 0) + final_position = final_position / static_cast(count); + else + final_position = smoothed_position; #ifdef CGAL_TETRAHEDRAL_REMESHING_DEBUG - os_surf << "2 " << current_pos << " " << final_position << std::endl, + os_surf << "2 " << current_pos << " " << final_position << std::endl, #endif - // move vertex - v->set_point(typename Tr::Point( - final_position.x(), final_position.y(), final_position.z())); - } - else if (neighbors[vid] > 0) - { - Vector_3 final_position = CGAL::NULL_VECTOR; + // move vertex + v->set_point(typename Tr::Point( + final_position.x(), final_position.y(), final_position.z())); + } + else if (neighbors[vid] > 0) + { + Vector_3 final_position = CGAL::NULL_VECTOR; - int count = 0; - const Vector_3 current_pos(CGAL::ORIGIN, point(v->point())); + int count = 0; + const Vector_3 current_pos(CGAL::ORIGIN, point(v->point())); - const std::vector& v_surface_indices = vertices_surface_indices[v]; - for (const Surface_patch_index si : v_surface_indices) - { - //Check if the mls surface exists to avoid degenerated cases + const std::vector& v_surface_indices = vertices_surface_indices[v]; + for (const Surface_patch_index si : v_surface_indices) + { + //Check if the mls surface exists to avoid degenerated cases - if (boost::optional mls_projection = project(si, current_pos)) { - final_position = final_position + *mls_projection; - } - else { - final_position = final_position + current_pos; - } - count++; - } + if (boost::optional mls_projection = project(si, current_pos)) { + final_position = final_position + *mls_projection; + } + else { + final_position = final_position + current_pos; + } + count++; + } - if (count > 0) - final_position = final_position / static_cast(count); - else - final_position = current_pos; + if (count > 0) + final_position = final_position / static_cast(count); + else + final_position = current_pos; #ifdef CGAL_TETRAHEDRAL_REMESHING_DEBUG - os_surf << "2 " << current_pos << " " << final_position << std::endl, + os_surf << "2 " << current_pos << " " << final_position << std::endl, #endif - // move vertex - v->set_point( - typename Tr::Point(final_position.x(), final_position.y(), final_position.z())); - } - } + // move vertex + v->set_point( + typename Tr::Point(final_position.x(), final_position.y(), final_position.z())); + } + } #endif //CGAL_TETRAHEDRAL_REMESHING_SMOOTH_SHARP_EDGES - smoothed_positions.assign(nbv, CGAL::NULL_VECTOR); - neighbors.assign(nbv, -1); + smoothed_positions.assign(nbv, CGAL::NULL_VECTOR); + neighbors.assign(nbv, -1); - /////////////// EDGES ON SURFACE, BUT NOT IN COMPLEX ////////////////// - for (const Edge& e : tr.finite_edges()) - { - if (is_boundary(c3t3, e, cell_selector) && !c3t3.is_in_complex(e)) - { - const Vertex_handle vh0 = e.first->vertex(e.second); - const Vertex_handle vh1 = e.first->vertex(e.third); + /////////////// EDGES ON SURFACE, BUT NOT IN COMPLEX ////////////////// + for (const Edge& e : tr.finite_edges()) + { + if (is_boundary(c3t3, e, cell_selector) && !c3t3.is_in_complex(e)) + { + const Vertex_handle vh0 = e.first->vertex(e.second); + const Vertex_handle vh1 = e.first->vertex(e.third); - const std::size_t& i0 = vertex_id.at(vh0); - const std::size_t& i1 = vertex_id.at(vh1); + const std::size_t& i0 = vertex_id.at(vh0); + const std::size_t& i1 = vertex_id.at(vh1); - const bool on_feature_v0 = is_on_feature(vh0); - const bool on_feature_v1 = is_on_feature(vh1); + const bool on_feature_v0 = is_on_feature(vh0); + const bool on_feature_v1 = is_on_feature(vh1); - if (!on_feature_v0) - neighbors[i0] = (std::max)(0, neighbors[i0]); - if (!on_feature_v1) - neighbors[i1] = (std::max)(0, neighbors[i1]); + if (!on_feature_v0) + neighbors[i0] = (std::max)(0, neighbors[i0]); + if (!on_feature_v1) + neighbors[i1] = (std::max)(0, neighbors[i1]); - if (!on_feature_v0) - { - const Point_3& p1 = point(vh1->point()); - smoothed_positions[i0] = smoothed_positions[i0] + Vector_3(p1.x(), p1.y(), p1.z()); - neighbors[i0]++; - } - if (!on_feature_v1) - { - const Point_3& p0 = point(vh0->point()); - smoothed_positions[i1] = smoothed_positions[i1] + Vector_3(p0.x(), p0.y(), p0.z()); - neighbors[i1]++; - } - } - } - - for (Vertex_handle v : tr.finite_vertex_handles()) - { - if (v->in_dimension() != 2) - continue; - - const std::size_t& vid = vertex_id.at(v); - if (neighbors[vid] > 1) - { - Vector_3 smoothed_position = smoothed_positions[vid] / static_cast(neighbors[vid]); - const Vector_3 current_pos(CGAL::ORIGIN, point(v->point())); - Vector_3 final_position = CGAL::NULL_VECTOR; - - const Surface_patch_index si = surface_patch_index(v, c3t3); - CGAL_assertion(si != Surface_patch_index()); - - Vector_3 normal_projection = project_on_tangent_plane(smoothed_position, - current_pos, - vertices_normals[v][si]); - - if (boost::optional mls_projection = project(si, normal_projection)) - final_position = final_position + *mls_projection; - else - final_position = smoothed_position; - -#ifdef CGAL_TETRAHEDRAL_REMESHING_DEBUG - os_surf << "2 " << current_pos << " " << final_position << std::endl, -#endif - check_inversion_and_move(v, typename Tr::Point( - final_position.x(), final_position.y(), final_position.z()), - inc_cells[vid], - tr); - } - else if (neighbors[vid] > 0) - { - const Surface_patch_index si = surface_patch_index(v, c3t3); - CGAL_assertion(si != Surface_patch_index()); - - const Vector_3 current_pos(CGAL::ORIGIN, point(v->point())); - - if (boost::optional mls_projection = project(si, current_pos)) - { - const typename Tr::Point new_pos(CGAL::ORIGIN + *mls_projection); - check_inversion_and_move(v, new_pos, inc_cells[vid], tr); - -#ifdef CGAL_TETRAHEDRAL_REMESHING_DEBUG - os_surf0 << "2 " << current_pos << " " << new_pos << std::endl; -#endif - } - } - } - } - CGAL_assertion(CGAL::Tetrahedral_remeshing::debug::are_cell_orientations_valid(tr)); - //// end if(!protect_boundaries) - - smoothed_positions.assign(nbv, CGAL::NULL_VECTOR); - neighbors.assign(nbv, 0/*for dim 3 vertices, start counting directly from 0*/); - - ////////////// INTERNAL VERTICES /////////////////////// - for (const Edge& e : tr.finite_edges()) + if (!on_feature_v0) { - if (!is_outside(e, c3t3, cell_selector)) - { - const Vertex_handle vh0 = e.first->vertex(e.second); - const Vertex_handle vh1 = e.first->vertex(e.third); - - const std::size_t& i0 = vertex_id.at(vh0); - const std::size_t& i1 = vertex_id.at(vh1); - - if (c3t3.in_dimension(vh0) == 3) - { - const Point_3& p1 = point(vh1->point()); - smoothed_positions[i0] = smoothed_positions[i0] + Vector_3(CGAL::ORIGIN, p1); - neighbors[i0]++; - } - if (c3t3.in_dimension(vh1) == 3) - { - const Point_3& p0 = point(vh0->point()); - smoothed_positions[i1] = smoothed_positions[i1] + Vector_3(CGAL::ORIGIN, p0); - neighbors[i1]++; - } - } + const Point_3& p1 = point(vh1->point()); + smoothed_positions[i0] = smoothed_positions[i0] + Vector_3(p1.x(), p1.y(), p1.z()); + neighbors[i0]++; } - - for (Vertex_handle v : tr.finite_vertex_handles()) + if (!on_feature_v1) { - const std::size_t& vid = vertex_id.at(v); - if (c3t3.in_dimension(v) == 3 && neighbors[vid] > 1) - { -#ifdef CGAL_TETRAHEDRAL_REMESHING_VERBOSE - ++nb_done; -#endif -#ifdef CGAL_TETRAHEDRAL_REMESHING_DEBUG - os_vol << "2 " << point(v->point()); -#endif - const Vector_3 p = smoothed_positions[vid] / static_cast(neighbors[vid]); - check_inversion_and_move(v, typename Tr::Point(p.x(), p.y(), p.z()), inc_cells[vid], tr); - -#ifdef CGAL_TETRAHEDRAL_REMESHING_DEBUG - os_vol << " " << point(v->point()) << std::endl; -#endif - } + const Point_3& p0 = point(vh0->point()); + smoothed_positions[i1] = smoothed_positions[i1] + Vector_3(p0.x(), p0.y(), p0.z()); + neighbors[i1]++; } - CGAL_assertion(CGAL::Tetrahedral_remeshing::debug::are_cell_orientations_valid(tr)); - -#ifdef CGAL_TETRAHEDRAL_REMESHING_VERBOSE - std::cout << " done (" << nb_done << " vertices smoothed)." << std::endl; -#endif -#ifdef CGAL_TETRAHEDRAL_REMESHING_DEBUG - CGAL::Tetrahedral_remeshing::debug::dump_vertices_by_dimension( - c3t3.triangulation(), "c3t3_vertices_after_smoothing"); - os_surf.close(); - os_vol.close(); -#endif } + } - };//end class Tetrahedral_remeshing_smoother - }//namespace internal - }//namespace Tetrahedral_adaptive_remeshing + for (Vertex_handle v : tr.finite_vertex_handles()) + { + if (v->in_dimension() != 2) + continue; + + const std::size_t& vid = vertex_id.at(v); + if (neighbors[vid] > 1) + { + Vector_3 smoothed_position = smoothed_positions[vid] / static_cast(neighbors[vid]); + const Vector_3 current_pos(CGAL::ORIGIN, point(v->point())); + Vector_3 final_position = CGAL::NULL_VECTOR; + + const Surface_patch_index si = surface_patch_index(v, c3t3); + CGAL_assertion(si != Surface_patch_index()); + + Vector_3 normal_projection = project_on_tangent_plane(smoothed_position, + current_pos, + vertices_normals[v][si]); + + if (boost::optional mls_projection = project(si, normal_projection)) + final_position = final_position + *mls_projection; + else + final_position = smoothed_position; + +#ifdef CGAL_TETRAHEDRAL_REMESHING_DEBUG + os_surf << "2 " << current_pos << " " << final_position << std::endl, +#endif + check_inversion_and_move(v, typename Tr::Point( + final_position.x(), final_position.y(), final_position.z()), + inc_cells[vid], + tr); + } + else if (neighbors[vid] > 0) + { + const Surface_patch_index si = surface_patch_index(v, c3t3); + CGAL_assertion(si != Surface_patch_index()); + + const Vector_3 current_pos(CGAL::ORIGIN, point(v->point())); + + if (boost::optional mls_projection = project(si, current_pos)) + { + const typename Tr::Point new_pos(CGAL::ORIGIN + *mls_projection); + check_inversion_and_move(v, new_pos, inc_cells[vid], tr); + +#ifdef CGAL_TETRAHEDRAL_REMESHING_DEBUG + os_surf0 << "2 " << current_pos << " " << new_pos << std::endl; +#endif + } + } + } + } + CGAL_assertion(CGAL::Tetrahedral_remeshing::debug::are_cell_orientations_valid(tr)); + //// end if(!protect_boundaries) + + smoothed_positions.assign(nbv, CGAL::NULL_VECTOR); + neighbors.assign(nbv, 0/*for dim 3 vertices, start counting directly from 0*/); + + ////////////// INTERNAL VERTICES /////////////////////// + for (const Edge& e : tr.finite_edges()) + { + if (!is_outside(e, c3t3, cell_selector)) + { + const Vertex_handle vh0 = e.first->vertex(e.second); + const Vertex_handle vh1 = e.first->vertex(e.third); + + const std::size_t& i0 = vertex_id.at(vh0); + const std::size_t& i1 = vertex_id.at(vh1); + + if (c3t3.in_dimension(vh0) == 3) + { + const Point_3& p1 = point(vh1->point()); + smoothed_positions[i0] = smoothed_positions[i0] + Vector_3(CGAL::ORIGIN, p1); + neighbors[i0]++; + } + if (c3t3.in_dimension(vh1) == 3) + { + const Point_3& p0 = point(vh0->point()); + smoothed_positions[i1] = smoothed_positions[i1] + Vector_3(CGAL::ORIGIN, p0); + neighbors[i1]++; + } + } + } + + for (Vertex_handle v : tr.finite_vertex_handles()) + { + const std::size_t& vid = vertex_id.at(v); + if (c3t3.in_dimension(v) == 3 && neighbors[vid] > 1) + { +#ifdef CGAL_TETRAHEDRAL_REMESHING_VERBOSE + ++nb_done; +#endif +#ifdef CGAL_TETRAHEDRAL_REMESHING_DEBUG + os_vol << "2 " << point(v->point()); +#endif + const Vector_3 p = smoothed_positions[vid] / static_cast(neighbors[vid]); + check_inversion_and_move(v, typename Tr::Point(p.x(), p.y(), p.z()), inc_cells[vid], tr); + +#ifdef CGAL_TETRAHEDRAL_REMESHING_DEBUG + os_vol << " " << point(v->point()) << std::endl; +#endif + } + } + CGAL_assertion(CGAL::Tetrahedral_remeshing::debug::are_cell_orientations_valid(tr)); + +#ifdef CGAL_TETRAHEDRAL_REMESHING_VERBOSE + std::cout << " done (" << nb_done << " vertices smoothed)." << std::endl; +#endif +#ifdef CGAL_TETRAHEDRAL_REMESHING_DEBUG + CGAL::Tetrahedral_remeshing::debug::dump_vertices_by_dimension( + c3t3.triangulation(), "c3t3_vertices_after_smoothing"); + os_surf.close(); + os_vol.close(); +#endif +} + +};//end class Tetrahedral_remeshing_smoother +}//namespace internal +}//namespace Tetrahedral_adaptive_remeshing }//namespace CGAL #endif //CGAL_INTERNAL_SMOOTH_VERTICES_H diff --git a/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/split_long_edges.h b/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/split_long_edges.h index 6eea09b01f9..d0f32b774cb 100644 --- a/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/split_long_edges.h +++ b/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/split_long_edges.h @@ -29,268 +29,269 @@ namespace Tetrahedral_remeshing { namespace internal { - template - typename C3t3::Vertex_handle split_edge(const typename C3t3::Edge& e, - C3t3& c3t3) +template +typename C3t3::Vertex_handle split_edge(const typename C3t3::Edge& e, + C3t3& c3t3) +{ + typedef typename C3t3::Triangulation Tr; + typedef typename C3t3::Subdomain_index Subdomain_index; + typedef typename C3t3::Surface_patch_index Surface_patch_index; + typedef typename Tr::Geom_traits::Point_3 Point; + typedef typename Tr::Facet Facet; + typedef typename Tr::Vertex_handle Vertex_handle; + typedef typename Tr::Cell_handle Cell_handle; + typedef typename Tr::Cell_circulator Cell_circulator; + + Tr& tr = c3t3.triangulation(); + const Vertex_handle v1 = e.first->vertex(e.second); + const Vertex_handle v2 = e.first->vertex(e.third); + + //backup subdomain info of incident cells before making changes + short dimension = (c3t3.is_in_complex(e)) ? 1 : 3; + boost::unordered_map cells_info; + boost::unordered_map > facets_info; + + Cell_circulator circ = tr.incident_cells(e); + Cell_circulator end = circ; + do { - typedef typename C3t3::Triangulation Tr; - typedef typename C3t3::Subdomain_index Subdomain_index; - typedef typename C3t3::Surface_patch_index Surface_patch_index; - typedef typename Tr::Geom_traits::Point_3 Point; - typedef typename Tr::Facet Facet; - typedef typename Tr::Vertex_handle Vertex_handle; - typedef typename Tr::Cell_handle Cell_handle; - typedef typename Tr::Cell_circulator Cell_circulator; + const int index_v1 = circ->index(v1); + const int index_v2 = circ->index(v2); - Tr& tr = c3t3.triangulation(); - const Vertex_handle v1 = e.first->vertex(e.second); - const Vertex_handle v2 = e.first->vertex(e.third); + //keys are the opposite facets to the ones not containing e, + //because they will not be modified + const Subdomain_index subdomain = c3t3.subdomain_index(circ); + const Facet opp_facet1 = tr.mirror_facet(Facet(circ, index_v1)); + const Facet opp_facet2 = tr.mirror_facet(Facet(circ, index_v2)); - //backup subdomain info of incident cells before making changes - short dimension = (c3t3.is_in_complex(e)) ? 1 : 3; - boost::unordered_map cells_info; - boost::unordered_map > facets_info; + // volume data + cells_info.insert(std::make_pair(opp_facet1, subdomain)); + cells_info.insert(std::make_pair(opp_facet2, subdomain)); + if (c3t3.is_in_complex(circ)) + c3t3.remove_from_complex(circ); - Cell_circulator circ = tr.incident_cells(e); - Cell_circulator end = circ; - do + // surface data for facets of the cells to be split + const int findex = CGAL::Triangulation_utils_3::next_around_edge(index_v1, index_v2); + if (c3t3.is_in_complex(circ, findex)) { - const int index_v1 = circ->index(v1); - const int index_v2 = circ->index(v2); + if (dimension == 3) + dimension = 2; + } + Surface_patch_index patch = c3t3.surface_patch_index(circ, findex); + Vertex_handle opp_vertex = circ->vertex(findex); + facets_info.insert(std::make_pair(opp_facet1, + std::make_pair(opp_vertex, patch))); + facets_info.insert(std::make_pair(opp_facet2, + std::make_pair(opp_vertex, patch))); - //keys are the opposite facets to the ones not containing e, - //because they will not be modified - const Subdomain_index subdomain = c3t3.subdomain_index(circ); - const Facet opp_facet1 = tr.mirror_facet(Facet(circ, index_v1)); - const Facet opp_facet2 = tr.mirror_facet(Facet(circ, index_v2)); + if(c3t3.is_in_complex(circ, findex)) + c3t3.remove_from_complex(circ, findex); - // volume data - cells_info.insert(std::make_pair(opp_facet1, subdomain)); - cells_info.insert(std::make_pair(opp_facet2, subdomain)); - if (c3t3.is_in_complex(circ)) - c3t3.remove_from_complex(circ); + ++circ; - // surface data for facets of the cells to be split - const int findex = CGAL::Triangulation_utils_3::next_around_edge(index_v1, index_v2); - if (c3t3.is_in_complex(circ, findex)) - { - if (dimension == 3) - dimension = 2; - } - Surface_patch_index patch = c3t3.surface_patch_index(circ, findex); - Vertex_handle opp_vertex = circ->vertex(findex); - facets_info.insert(std::make_pair(opp_facet1, - std::make_pair(opp_vertex, patch))); - facets_info.insert(std::make_pair(opp_facet2, - std::make_pair(opp_vertex, patch))); + } while (circ != end); - if(c3t3.is_in_complex(circ, findex)) - c3t3.remove_from_complex(circ, findex); + // insert midpoint + Vertex_handle new_v = tr.tds().insert_in_edge(e); + const Point m = tr.geom_traits().construct_midpoint_3_object() + (point(v1->point()), point(v2->point())); + new_v->set_point(typename Tr::Point(m)); + new_v->set_dimension(dimension); - ++circ; + // update c3t3 with subdomain and surface patch indices + std::vector new_cells; + tr.incident_cells(new_v, std::back_inserter(new_cells)); + for (Cell_handle new_cell : new_cells) + { + const Facet fi(new_cell, new_cell->index(new_v)); + const Facet mfi = tr.mirror_facet(fi); - } while (circ != end); + //get subdomain info back + CGAL_assertion(cells_info.find(mfi) != cells_info.end()); + Subdomain_index n_index = cells_info.at(mfi); + if (Subdomain_index() != n_index) + c3t3.add_to_complex(new_cell, n_index); + else + new_cell->set_subdomain_index(Subdomain_index()); - // insert midpoint - Vertex_handle new_v = tr.tds().insert_in_edge(e); - const Point m = tr.geom_traits().construct_midpoint_3_object() - (point(v1->point()), point(v2->point())); - new_v->set_point(typename Tr::Point(m)); - new_v->set_dimension(dimension); + // get surface info back + CGAL_assertion(facets_info.find(mfi) != facets_info.end()); + const std::pair v_and_opp_patch = facets_info.at(mfi); - // update c3t3 with subdomain and surface patch indices - std::vector new_cells; - tr.incident_cells(new_v, std::back_inserter(new_cells)); - for (Cell_handle new_cell : new_cells) + // facet opposite to new_v (status wrt c3t3 is unchanged) + new_cell->set_surface_patch_index(new_cell->index(new_v), + mfi.first->surface_patch_index(mfi.second)); + + // new half-facet (added or not to c3t3 depending on the stored surface patch index) + if (Surface_patch_index() == v_and_opp_patch.second) + new_cell->set_surface_patch_index(new_cell->index(v_and_opp_patch.first), + Surface_patch_index()); + else + c3t3.add_to_complex(new_cell, + new_cell->index(v_and_opp_patch.first), + v_and_opp_patch.second); + + // newly created internal facet + for (int i = 0; i < 4; ++i) { - const Facet fi(new_cell, new_cell->index(new_v)); - const Facet mfi = tr.mirror_facet(fi); - - //get subdomain info back - CGAL_assertion(cells_info.find(mfi) != cells_info.end()); - Subdomain_index n_index = cells_info.at(mfi); - if (Subdomain_index() != n_index) - c3t3.add_to_complex(new_cell, n_index); - else - new_cell->set_subdomain_index(Subdomain_index()); - - // get surface info back - CGAL_assertion(facets_info.find(mfi) != facets_info.end()); - const std::pair v_and_opp_patch = facets_info.at(mfi); - - // facet opposite to new_v (status wrt c3t3 is unchanged) - new_cell->set_surface_patch_index(new_cell->index(new_v), - mfi.first->surface_patch_index(mfi.second)); - - // new half-facet (added or not to c3t3 depending on the stored surface patch index) - if (Surface_patch_index() == v_and_opp_patch.second) - new_cell->set_surface_patch_index(new_cell->index(v_and_opp_patch.first), - Surface_patch_index()); - else - c3t3.add_to_complex(new_cell, - new_cell->index(v_and_opp_patch.first), - v_and_opp_patch.second); - - // newly created internal facet - for (int i = 0; i < 4; ++i) + const Vertex_handle vi = new_cell->vertex(i); + if (vi == v1 || vi == v2) { - const Vertex_handle vi = new_cell->vertex(i); - if (vi == v1 || vi == v2) - { - new_cell->set_surface_patch_index(i, Surface_patch_index()); - break; - } + new_cell->set_surface_patch_index(i, Surface_patch_index()); + break; } - - //the 4th facet (new_v, v_and_opp_patch.first, v1 or v2) - // will have its patch tagged from the other side, if needed } - return new_v; + //the 4th facet (new_v, v_and_opp_patch.first, v1 or v2) + // will have its patch tagged from the other side, if needed } - template - bool can_be_split(const typename C3T3::Edge& e, - const C3T3& c3t3, - const bool protect_boundaries, - CellSelector cell_selector) + return new_v; +} + +template +bool can_be_split(const typename C3T3::Edge& e, + const C3T3& c3t3, + const bool protect_boundaries, + CellSelector cell_selector) +{ + if (is_outside(e, c3t3, cell_selector)) + return false; + + if (protect_boundaries) { - if (is_outside(e, c3t3, cell_selector)) + if (c3t3.is_in_complex(e)) + return false; + else if (is_boundary(c3t3, e, cell_selector)) return false; - if (protect_boundaries) - { - if (c3t3.is_in_complex(e)) - return false; - else if (is_boundary(c3t3, e, cell_selector)) - return false; - #ifdef CGAL_TETRAHEDRAL_REMESHING_DEBUG - if (!is_internal(e, c3t3, cell_selector)) - { - std::cerr << "e is not inside!?" << std::endl; - typename C3T3::Vertex_handle v1 = e.first->vertex(e.second); - typename C3T3::Vertex_handle v2 = e.first->vertex(e.third); - std::cerr << v1->point() << " " << v2->point() << std::endl; - } + if (!is_internal(e, c3t3, cell_selector)) + { + std::cerr << "e is not inside!?" << std::endl; + typename C3T3::Vertex_handle v1 = e.first->vertex(e.second); + typename C3T3::Vertex_handle v2 = e.first->vertex(e.third); + std::cerr << v1->point() << " " << v2->point() << std::endl; + } #endif - CGAL_assertion(is_internal(e, c3t3, cell_selector)); - return true; - } - else - { - return true; - } + CGAL_assertion(is_internal(e, c3t3, cell_selector)); + return true; } - - template - void split_long_edges(C3T3& c3t3, - const typename C3T3::Triangulation::Geom_traits::FT& high, - const bool protect_boundaries, - CellSelector cell_selector, - Visitor& visitor) + else { - typedef typename C3T3::Triangulation T3; - typedef typename T3::Cell_handle Cell_handle; - typedef typename T3::Edge Edge; - typedef typename T3::Finite_edges_iterator Finite_edges_iterator; - typedef typename T3::Vertex_handle Vertex_handle; - typedef typename std::pair Edge_vv; + return true; + } +} - typedef typename T3::Geom_traits Gt; - typedef typename T3::Geom_traits::FT FT; - typedef boost::bimap< - boost::bimaps::set_of, - boost::bimaps::multiset_of > > Boost_bimap; - typedef typename Boost_bimap::value_type long_edge; +template +void split_long_edges(C3T3& c3t3, + const typename C3T3::Triangulation::Geom_traits::FT& high, + const bool protect_boundaries, + CellSelector cell_selector, + Visitor& visitor) +{ + typedef typename C3T3::Triangulation T3; + typedef typename T3::Cell_handle Cell_handle; + typedef typename T3::Edge Edge; + typedef typename T3::Finite_edges_iterator Finite_edges_iterator; + typedef typename T3::Vertex_handle Vertex_handle; + typedef typename std::pair Edge_vv; + + typedef typename T3::Geom_traits Gt; + typedef typename T3::Geom_traits::FT FT; + typedef boost::bimap< + boost::bimaps::set_of, + boost::bimaps::multiset_of > > Boost_bimap; + typedef typename Boost_bimap::value_type long_edge; #ifdef CGAL_TETRAHEDRAL_REMESHING_VERBOSE - std::cout << "Split long edges (" << high << ")..."; - std::cout.flush(); - std::size_t nb_splits = 0; + std::cout << "Split long edges (" << high << ")..."; + std::cout.flush(); + std::size_t nb_splits = 0; #endif - const FT sq_high = high*high; + const FT sq_high = high*high; - //collect long edges - T3& tr = c3t3.triangulation(); - Boost_bimap long_edges; - for (Finite_edges_iterator eit = tr.finite_edges_begin(); - eit != tr.finite_edges_end(); ++eit) + //collect long edges + T3& tr = c3t3.triangulation(); + Boost_bimap long_edges; + for (Finite_edges_iterator eit = tr.finite_edges_begin(); + eit != tr.finite_edges_end(); ++eit) + { + Edge e = *eit; + if (!can_be_split(e, c3t3, protect_boundaries, cell_selector)) + continue; + + typename Gt::Compute_squared_length_3 sql + = tr.geom_traits().compute_squared_length_3_object(); + FT sqlen = sql(tr.segment(e)); + if (sqlen > sq_high) + long_edges.insert(long_edge(make_vertex_pair(e), sqlen)); + } + +#ifdef CGAL_TETRAHEDRAL_REMESHING_DEBUG + debug::dump_edges(long_edges, "long_edges.polylines.txt"); + + std::ofstream ofs("midpoints.off"); + ofs << "OFF" << std::endl; + ofs << long_edges.size() << " 0 0" << std::endl; +#endif + while(!long_edges.empty()) + { + //the edge with longest length + typename Boost_bimap::right_map::iterator eit = long_edges.right.begin(); + Edge_vv e = eit->second; +#ifdef CGAL_TETRAHEDRAL_REMESHING_VERBOSE_PROGRESS + const double sqlen = eit->first; +#endif + long_edges.right.erase(eit); + + Cell_handle cell; + int i1, i2; + if ( tr.tds().is_edge(e.first, e.second, cell, i1, i2)) { - Edge e = *eit; - if (!can_be_split(e, c3t3, protect_boundaries, cell_selector)) + Edge edge(cell, i1, i2); + + //check that splittability has not changed + if (!can_be_split(edge, c3t3, protect_boundaries, cell_selector)) continue; - typename Gt::Compute_squared_length_3 sql - = tr.geom_traits().compute_squared_length_3_object(); - FT sqlen = sql(tr.segment(e)); - if (sqlen > sq_high) - long_edges.insert(long_edge(make_vertex_pair(e), sqlen)); - } + visitor.before_split(tr, edge); + Vertex_handle vh = split_edge(edge, c3t3); + visitor.after_split(tr, vh); #ifdef CGAL_TETRAHEDRAL_REMESHING_DEBUG - debug::dump_edges(long_edges, "long_edges.polylines.txt"); - - std::ofstream ofs("midpoints.off"); - ofs << "OFF" << std::endl; - ofs << long_edges.size() << " 0 0" << std::endl; -#endif - while(!long_edges.empty()) - { - //the edge with longest length - typename Boost_bimap::right_map::iterator eit = long_edges.right.begin(); - Edge_vv e = eit->second; -#ifdef CGAL_TETRAHEDRAL_REMESHING_VERBOSE_PROGRESS - const double sqlen = eit->first; -#endif - long_edges.right.erase(eit); - - Cell_handle cell; - int i1, i2; - if ( tr.tds().is_edge(e.first, e.second, cell, i1, i2)) - { - Edge edge(cell, i1, i2); - - //check that splittability has not changed - if (!can_be_split(edge, c3t3, protect_boundaries, cell_selector)) - continue; - - visitor.before_split(tr, edge); - Vertex_handle vh = split_edge(edge, c3t3); - visitor.after_split(tr, vh); - -#ifdef CGAL_TETRAHEDRAL_REMESHING_DEBUG - ofs << vh->point() << std::endl; + ofs << vh->point() << std::endl; #endif #if defined(CGAL_TETRAHEDRAL_REMESHING_VERBOSE_PROGRESS) \ - || defined(CGAL_TETRAHEDRAL_REMESHING_VERBOSE) - if (vh != Vertex_handle()) - ++nb_splits; +|| defined(CGAL_TETRAHEDRAL_REMESHING_VERBOSE) + if (vh != Vertex_handle()) + ++nb_splits; #endif #ifdef CGAL_TETRAHEDRAL_REMESHING_VERBOSE_PROGRESS - std::cout << "\rSplit (" << high << ")... (" - << long_edges.left.size() << " long edges, " - << "length = " << std::sqrt(sqlen) << ", " - << nb_splits << " splits)"; - std::cout.flush(); + std::cout << "\rSplit (" << high << ")... (" + << long_edges.left.size() << " long edges, " + << "length = " << std::sqrt(sqlen) << ", " + << nb_splits << " splits)"; + std::cout.flush(); #endif - } - }//end loop on long_edges + } + }//end loop on long_edges #ifdef CGAL_TETRAHEDRAL_REMESHING_DEBUG - if(ofs.is_open()) - ofs.close(); + if(ofs.is_open()) + ofs.close(); #endif #ifdef CGAL_TETRAHEDRAL_REMESHING_VERBOSE - std::cout << " done (" << nb_splits << " splits)." << std::endl; + std::cout << " done (" << nb_splits << " splits)." << std::endl; #endif - } -} -} } +} // internal +} // Tetrahedral_remeshing +} // CGAL + #endif // CGAL_INTERNAL_SPLIT_LONG_EDGES_H diff --git a/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/tetrahedral_adaptive_remeshing_impl.h b/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/tetrahedral_adaptive_remeshing_impl.h index a73901b8a8b..e330d8f68ec 100644 --- a/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/tetrahedral_adaptive_remeshing_impl.h +++ b/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/tetrahedral_adaptive_remeshing_impl.h @@ -35,523 +35,524 @@ namespace Tetrahedral_remeshing { namespace internal { - class Default_remeshing_visitor - { - public: - template - void before_split(const Tr& /* tr */, const typename Tr::Edge& /* e */) {} - template - void after_split(const Tr& /* tr */, const typename Tr::Vertex_handle /* new_v */) {} - - template - void after_add_cell(CellHandleOld /* co */, CellHandleNew /* cn */) const {} - - template - void before_flip(const CellHandle /* c */) {} - template - void after_flip(CellHandle /* c */) {} - }; - +class Default_remeshing_visitor +{ +public: template - struct All_cells_selected + void before_split(const Tr& /* tr */, const typename Tr::Edge& /* e */) {} + template + void after_split(const Tr& /* tr */, const typename Tr::Vertex_handle /* new_v */) {} + + template + void after_add_cell(CellHandleOld /* co */, CellHandleNew /* cn */) const {} + + template + void before_flip(const CellHandle /* c */) {} + template + void after_flip(CellHandle /* c */) {} +}; + +template +struct All_cells_selected +{ + typedef typename Tr::Cell_handle argument_type; + typedef typename Tr::Cell::Subdomain_index Subdomain_index; + + typedef bool result_type; + + result_type operator()(const argument_type c) const { - typedef typename Tr::Cell_handle argument_type; - typedef typename Tr::Cell::Subdomain_index Subdomain_index; + return c->subdomain_index() != Subdomain_index(); + } +}; - typedef bool result_type; +template +struct No_constraint_pmap +{ +public: + typedef Primitive key_type; + typedef bool value_type; + typedef value_type& reference; + typedef boost::read_write_property_map_tag category; - result_type operator()(const argument_type c) const - { - return c->subdomain_index() != Subdomain_index(); - } - }; + friend bool get(const No_constraint_pmap&, const key_type&) { + return false; + } + friend void put(No_constraint_pmap&, const key_type&, const bool) {} +}; - template - struct No_constraint_pmap - { - public: - typedef Primitive key_type; - typedef bool value_type; - typedef value_type& reference; - typedef boost::read_write_property_map_tag category; +template +class Adaptive_remesher +{ + typedef Triangulation Tr; + typedef typename Tr::Geom_traits::FT FT; - friend bool get(const No_constraint_pmap&, const key_type&) { - return false; - } - friend void put(No_constraint_pmap&, const key_type&, const bool) {} - }; + typedef CGAL::Mesh_complex_3_in_triangulation_3 C3t3; - template - class Adaptive_remesher - { - typedef Triangulation Tr; - typedef typename Tr::Geom_traits::FT FT; + typedef typename C3t3::Cell_handle Cell_handle; + typedef typename C3t3::Vertex_handle Vertex_handle; + typedef typename C3t3::Subdomain_index Subdomain_index; + typedef typename C3t3::Surface_patch_index Surface_patch_index; - typedef CGAL::Mesh_complex_3_in_triangulation_3 C3t3; - - typedef typename C3t3::Cell_handle Cell_handle; - typedef typename C3t3::Vertex_handle Vertex_handle; - typedef typename C3t3::Subdomain_index Subdomain_index; - typedef typename C3t3::Surface_patch_index Surface_patch_index; - - typedef Tetrahedral_remeshing_smoother Smoother; - - private: - C3t3 m_c3t3; - const SizingFunction& m_sizing; - const bool m_protect_boundaries; - CellSelector m_cell_selector; - Visitor& m_visitor; - Smoother m_vertex_smoother;//initialized with initial surface - - C3t3* m_c3t3_pbackup; - Triangulation* m_tr_pbackup; //backup to re-swap triangulations when done - - public: - Adaptive_remesher(Triangulation& tr - , const SizingFunction& sizing - , const bool protect_boundaries - , EdgeIsConstrainedMap ecmap - , FacetIsConstrainedMap fcmap - , CellSelector cell_selector - , Visitor& visitor - ) - : m_c3t3() - , m_sizing(sizing) - , m_protect_boundaries(protect_boundaries) - , m_cell_selector(cell_selector) - , m_visitor(visitor) - , m_c3t3_pbackup(NULL) - , m_tr_pbackup(&tr) - { - m_c3t3.triangulation().swap(tr); - - init_c3t3(ecmap, fcmap); - m_vertex_smoother.init(m_c3t3, m_cell_selector); - -#ifdef CGAL_DUMP_REMESHING_STEPS - CGAL::Tetrahedral_remeshing::debug::dump_binary(m_c3t3, "00-init.binary.cgal"); -#endif - } - - Adaptive_remesher(C3t3& c3t3 - , const SizingFunction& sizing - , const bool protect_boundaries - , EdgeIsConstrainedMap ecmap - , FacetIsConstrainedMap fcmap - , CellSelector cell_selector - , Visitor& visitor - ) - : m_c3t3() - , m_sizing(sizing) - , m_protect_boundaries(protect_boundaries) - , m_cell_selector(cell_selector) - , m_visitor(visitor) - , m_c3t3_pbackup(&c3t3) - , m_tr_pbackup(NULL) - { - m_c3t3.swap(c3t3); - - init_c3t3(ecmap, fcmap); - m_vertex_smoother.init(m_c3t3, m_cell_selector); - -#ifdef CGAL_DUMP_REMESHING_STEPS - CGAL::Tetrahedral_remeshing::debug::dump_binary(m_c3t3, "00-init.binary.cgal"); -#endif - } - - bool input_is_c3t3() const - { - return m_c3t3_pbackup != NULL; - } - - void split() - { - CGAL_assertion(check_vertex_dimensions()); - - const FT target_edge_length = m_sizing(CGAL::ORIGIN); - const FT emax = FT(4)/FT(3) * target_edge_length; - split_long_edges(m_c3t3, emax, m_protect_boundaries, - m_cell_selector, m_visitor); - - CGAL_assertion(tr().tds().is_valid(true)); - CGAL_assertion(debug::are_cell_orientations_valid(tr())); -#ifdef CGAL_DUMP_REMESHING_STEPS - CGAL::Tetrahedral_remeshing::debug::dump_triangulation_cells(tr(), "1-split.mesh"); - CGAL::Tetrahedral_remeshing::debug::dump_binary(m_c3t3, "1-split.binary.cgal"); -#endif - } - - void collapse() - { - CGAL_assertion(check_vertex_dimensions()); - - const FT target_edge_length = m_sizing(CGAL::ORIGIN); - FT emin = FT(4)/FT(5) * target_edge_length; - FT emax = FT(4)/FT(3) * target_edge_length; - collapse_short_edges(m_c3t3, emin, emax, m_protect_boundaries, - m_cell_selector, m_visitor); - - CGAL_assertion(tr().tds().is_valid(true)); - CGAL_assertion(debug::are_cell_orientations_valid(tr())); -#ifdef CGAL_DUMP_REMESHING_STEPS - CGAL::Tetrahedral_remeshing::debug::dump_triangulation_cells(tr(), - "2-collapse.mesh"); - CGAL::Tetrahedral_remeshing::debug::dump_binary(m_c3t3, "2-collapse.binary.cgal"); -#endif - } - - void flip() - { - flip_edges(m_c3t3, m_protect_boundaries, - m_cell_selector, m_visitor); - - CGAL_assertion(tr().tds().is_valid(true)); - CGAL_assertion(debug::are_cell_orientations_valid(tr())); -#ifdef CGAL_DUMP_REMESHING_STEPS - CGAL::Tetrahedral_remeshing::debug::dump_triangulation_cells(tr(), "3-flip.mesh"); - CGAL::Tetrahedral_remeshing::debug::dump_binary(m_c3t3, "3-flip.binary.cgal"); -#endif - } - - void smooth() - { - m_vertex_smoother.smooth_vertices(m_c3t3, m_protect_boundaries, m_cell_selector); - - CGAL_assertion(tr().tds().is_valid(true)); - CGAL_assertion(debug::are_cell_orientations_valid(tr())); -#ifdef CGAL_DUMP_REMESHING_STEPS - CGAL::Tetrahedral_remeshing::debug::dump_triangulation_cells(tr(), - "4-smooth.mesh"); - CGAL::Tetrahedral_remeshing::debug::dump_binary(m_c3t3, "4-smooth.binary.cgal"); -#endif - } - - bool resolution_reached() - { - const FT target_edge_length = m_sizing(CGAL::ORIGIN); - - FT emax = FT(4) / FT(3) * target_edge_length; - FT emin = FT(4) / FT(5) * target_edge_length; - - FT sqmax = emax * emax; - FT sqmin = emin * emin; - - typedef typename Tr::Finite_edges_iterator Finite_edges_iterator; - for (Finite_edges_iterator eit = tr().finite_edges_begin(); - eit != tr().finite_edges_end(); - ++eit) - { - typename Tr::Edge e = *eit; - // skip protected edges - if (m_protect_boundaries) - { - if( m_c3t3.is_in_complex(e) - || is_boundary(m_c3t3, e, m_cell_selector)) - continue; - } - - FT sqlen = tr().segment(e).squared_length(); - if (sqlen < sqmin || sqlen > sqmax) - return false; - } - std::cout << "Resolution reached" << std::endl; - return true; - } - - //peel off slivers - std::size_t postprocess(const double sliver_angle = 0.1) - { - if (m_protect_boundaries) - return 0; - -#ifdef CGAL_TETRAHEDRAL_REMESHING_VERBOSE - std::cout << "Postprocess..."; - std::cout.flush(); -#endif - - std::size_t nb_slivers_peel = 0; - typedef typename Tr::Finite_cells_iterator Finite_cells_iterator; - for (Finite_cells_iterator cit = tr().finite_cells_begin(); - cit != tr().finite_cells_end(); ++cit) - { - if(m_c3t3.is_in_complex(cit) && min_dihedral_angle(tr(), cit) < sliver_angle) - { - for (int i = 0; i < 4; ++i) - { - if (!m_c3t3.is_in_complex(cit->neighbor(i))) - { - m_c3t3.remove_from_complex(cit); - ++nb_slivers_peel; - } - } - } - } - - CGAL_assertion(tr().tds().is_valid(true)); - CGAL_assertion(debug::are_cell_orientations_valid(tr())); - -#ifdef CGAL_DUMP_REMESHING_STEPS - CGAL::Tetrahedral_remeshing::debug::dump_triangulation_cells(tr(), "99-postprocess.mesh"); - CGAL::Tetrahedral_remeshing::debug::dump_binary(m_c3t3, "99-postprocess.binary.cgal"); -#endif -#ifdef CGAL_TETRAHEDRAL_REMESHING_VERBOSE - std::cout << "(peeling removed " << nb_slivers_peel << " slivers)" << std::endl; - std::cout << "done." << std::endl; -#endif - return nb_slivers_peel; - } - - void finalize() - { - if (m_c3t3_pbackup != NULL) - m_c3t3_pbackup->swap(m_c3t3); - else - m_tr_pbackup->swap(m_c3t3.triangulation()); - } + typedef Tetrahedral_remeshing_smoother Smoother; private: - void init_c3t3(const EdgeIsConstrainedMap& ecmap, - const FacetIsConstrainedMap& fcmap) + C3t3 m_c3t3; + const SizingFunction& m_sizing; + const bool m_protect_boundaries; + CellSelector m_cell_selector; + Visitor& m_visitor; + Smoother m_vertex_smoother;//initialized with initial surface + + C3t3* m_c3t3_pbackup; + Triangulation* m_tr_pbackup; //backup to re-swap triangulations when done + +public: + Adaptive_remesher(Triangulation& tr + , const SizingFunction& sizing + , const bool protect_boundaries + , EdgeIsConstrainedMap ecmap + , FacetIsConstrainedMap fcmap + , CellSelector cell_selector + , Visitor& visitor + ) + : m_c3t3() + , m_sizing(sizing) + , m_protect_boundaries(protect_boundaries) + , m_cell_selector(cell_selector) + , m_visitor(visitor) + , m_c3t3_pbackup(NULL) + , m_tr_pbackup(&tr) + { + m_c3t3.triangulation().swap(tr); + + init_c3t3(ecmap, fcmap); + m_vertex_smoother.init(m_c3t3, m_cell_selector); + +#ifdef CGAL_DUMP_REMESHING_STEPS + CGAL::Tetrahedral_remeshing::debug::dump_binary(m_c3t3, "00-init.binary.cgal"); +#endif + } + + Adaptive_remesher(C3t3& c3t3 + , const SizingFunction& sizing + , const bool protect_boundaries + , EdgeIsConstrainedMap ecmap + , FacetIsConstrainedMap fcmap + , CellSelector cell_selector + , Visitor& visitor + ) + : m_c3t3() + , m_sizing(sizing) + , m_protect_boundaries(protect_boundaries) + , m_cell_selector(cell_selector) + , m_visitor(visitor) + , m_c3t3_pbackup(&c3t3) + , m_tr_pbackup(NULL) + { + m_c3t3.swap(c3t3); + + init_c3t3(ecmap, fcmap); + m_vertex_smoother.init(m_c3t3, m_cell_selector); + +#ifdef CGAL_DUMP_REMESHING_STEPS + CGAL::Tetrahedral_remeshing::debug::dump_binary(m_c3t3, "00-init.binary.cgal"); +#endif + } + + bool input_is_c3t3() const + { + return m_c3t3_pbackup != NULL; + } + + void split() + { + CGAL_assertion(check_vertex_dimensions()); + + const FT target_edge_length = m_sizing(CGAL::ORIGIN); + const FT emax = FT(4)/FT(3) * target_edge_length; + split_long_edges(m_c3t3, emax, m_protect_boundaries, + m_cell_selector, m_visitor); + + CGAL_assertion(tr().tds().is_valid(true)); + CGAL_assertion(debug::are_cell_orientations_valid(tr())); +#ifdef CGAL_DUMP_REMESHING_STEPS + CGAL::Tetrahedral_remeshing::debug::dump_triangulation_cells(tr(), "1-split.mesh"); + CGAL::Tetrahedral_remeshing::debug::dump_binary(m_c3t3, "1-split.binary.cgal"); +#endif + } + + void collapse() + { + CGAL_assertion(check_vertex_dimensions()); + + const FT target_edge_length = m_sizing(CGAL::ORIGIN); + FT emin = FT(4)/FT(5) * target_edge_length; + FT emax = FT(4)/FT(3) * target_edge_length; + collapse_short_edges(m_c3t3, emin, emax, m_protect_boundaries, + m_cell_selector, m_visitor); + + CGAL_assertion(tr().tds().is_valid(true)); + CGAL_assertion(debug::are_cell_orientations_valid(tr())); +#ifdef CGAL_DUMP_REMESHING_STEPS + CGAL::Tetrahedral_remeshing::debug::dump_triangulation_cells(tr(), + "2-collapse.mesh"); + CGAL::Tetrahedral_remeshing::debug::dump_binary(m_c3t3, "2-collapse.binary.cgal"); +#endif + } + + void flip() + { + flip_edges(m_c3t3, m_protect_boundaries, + m_cell_selector, m_visitor); + + CGAL_assertion(tr().tds().is_valid(true)); + CGAL_assertion(debug::are_cell_orientations_valid(tr())); +#ifdef CGAL_DUMP_REMESHING_STEPS + CGAL::Tetrahedral_remeshing::debug::dump_triangulation_cells(tr(), "3-flip.mesh"); + CGAL::Tetrahedral_remeshing::debug::dump_binary(m_c3t3, "3-flip.binary.cgal"); +#endif + } + + void smooth() + { + m_vertex_smoother.smooth_vertices(m_c3t3, m_protect_boundaries, m_cell_selector); + + CGAL_assertion(tr().tds().is_valid(true)); + CGAL_assertion(debug::are_cell_orientations_valid(tr())); +#ifdef CGAL_DUMP_REMESHING_STEPS + CGAL::Tetrahedral_remeshing::debug::dump_triangulation_cells(tr(), + "4-smooth.mesh"); + CGAL::Tetrahedral_remeshing::debug::dump_binary(m_c3t3, "4-smooth.binary.cgal"); +#endif + } + + bool resolution_reached() + { + const FT target_edge_length = m_sizing(CGAL::ORIGIN); + + FT emax = FT(4) / FT(3) * target_edge_length; + FT emin = FT(4) / FT(5) * target_edge_length; + + FT sqmax = emax * emax; + FT sqmin = emin * emin; + + typedef typename Tr::Finite_edges_iterator Finite_edges_iterator; + for (Finite_edges_iterator eit = tr().finite_edges_begin(); + eit != tr().finite_edges_end(); + ++eit) { -#ifdef CGAL_TETRAHEDRAL_REMESHING_DEBUG - std::size_t nbc = 0; - std::size_t nbf = 0; - std::size_t nbe = 0; - std::size_t nbv = 0; -#endif - - //tag cells - typedef typename Tr::Finite_cells_iterator Finite_cells_iterator; - for (Finite_cells_iterator cit = tr().finite_cells_begin(); - cit != tr().finite_cells_end(); - ++cit) + typename Tr::Edge e = *eit; + // skip protected edges + if (m_protect_boundaries) { - if (m_cell_selector(cit)) - { - m_c3t3.add_to_complex(cit, cit->subdomain_index()); - -#ifdef CGAL_TETRAHEDRAL_REMESHING_DEBUG - ++nbc; -#endif - } - if (!input_is_c3t3()) - { - for (int i = 0; i < 4; ++i) - { - if (cit->vertex(i)->in_dimension() == -1) - cit->vertex(i)->set_dimension(3); - } - } -#ifdef CGAL_TETRAHEDRAL_REMESHING_DEBUG - else if (input_is_c3t3() && m_c3t3.is_in_complex(cit)) - ++nbc; -#endif - } - - //tag facets - typedef typename Tr::Facet Facet; - typedef typename Tr::Finite_facets_iterator Finite_facets_iterator; - for (Finite_facets_iterator fit = tr().finite_facets_begin(); - fit != tr().finite_facets_end(); - ++fit) - { - const Facet f = *fit; - const Facet mf = tr().mirror_facet(f); - const Subdomain_index s1 = f.first->subdomain_index(); - const Subdomain_index s2 = mf.first->subdomain_index(); - if (s1 != s2 - || get(fcmap, f) - || get(fcmap, mf) - || (m_c3t3_pbackup == NULL && f.first->is_facet_on_surface(f.second))) - { - m_c3t3.add_to_complex(f, 1); - - const int i = f.second; - for (int j = 0; j < 3; ++j) - { - Vertex_handle vij = f.first->vertex(Tr::vertex_triple_index(i, j)); - if (vij->in_dimension() == -1 || vij->in_dimension() > 2) - vij->set_dimension(2); - } -#ifdef CGAL_TETRAHEDRAL_REMESHING_DEBUG - ++nbf; -#endif - } - } -#ifdef CGAL_TETRAHEDRAL_REMESHING_DEBUG - CGAL::Tetrahedral_remeshing::debug::dump_facets_in_complex(m_c3t3, "facets_in_complex.off"); -#endif - - //tag edges - typedef typename Tr::Edge Edge; - typedef typename Tr::Finite_edges_iterator Finite_edges_iterator; - for (Finite_edges_iterator eit = tr().finite_edges_begin(); - eit != tr().finite_edges_end(); - ++eit) - { - const Edge& e = *eit; - - if (m_c3t3.is_in_complex(e)) - { - CGAL_assertion(m_c3t3.in_dimension(e.first->vertex(e.second)) <= 1); - CGAL_assertion(m_c3t3.in_dimension(e.first->vertex(e.third)) <= 1); -#ifdef CGAL_TETRAHEDRAL_REMESHING_DEBUG - ++nbe; -#endif + if( m_c3t3.is_in_complex(e) + || is_boundary(m_c3t3, e, m_cell_selector)) continue; - } - - if (get(ecmap, CGAL::Tetrahedral_remeshing::make_vertex_pair(e)) - || nb_incident_subdomains(e, m_c3t3) > 2 - || nb_incident_surface_patches(e, m_c3t3) > 1) - { - m_c3t3.add_to_complex(e, 1); - - Vertex_handle v = e.first->vertex(e.second); - if (v->in_dimension() == -1 || v->in_dimension() > 1) - v->set_dimension(1); - - v = e.first->vertex(e.third); - if (v->in_dimension() == -1 || v->in_dimension() > 1) - v->set_dimension(1); - -#ifdef CGAL_TETRAHEDRAL_REMESHING_DEBUG - ++nbe; -#endif - } - } -#ifdef CGAL_TETRAHEDRAL_REMESHING_DEBUG - CGAL::Tetrahedral_remeshing::debug::dump_edges_in_complex(m_c3t3, "edges_in_complex.polylines.txt"); -#endif - - //tag vertices - typedef typename Tr::Finite_vertices_iterator Finite_vertices_iterator; - unsigned int corner_id = 0; - for (Finite_vertices_iterator vit = tr().finite_vertices_begin(); - vit != tr().finite_vertices_end(); - ++vit) - { - if ( vit->in_dimension() == 0 - || nb_incident_complex_edges(vit, m_c3t3) > 2) - { - if(!m_c3t3.is_in_complex(vit)) - m_c3t3.add_to_complex(vit, ++corner_id); - - if (vit->in_dimension() == -1 || vit->in_dimension() > 0) - vit->set_dimension(0); - -#ifdef CGAL_TETRAHEDRAL_REMESHING_DEBUG - ++nbv; -#endif - } } -#ifdef CGAL_TETRAHEDRAL_REMESHING_DEBUG - std::cout << "C3t3 ready :" << std::endl; - std::cout << "\t cells = " << nbc << std::endl; - std::cout << "\t facets = " << nbf << std::endl; - std::cout << "\t edges = " << nbe << std::endl; - std::cout << "\t vertices = " << nbv << std::endl; - - CGAL::Tetrahedral_remeshing::debug::dump_vertices_by_dimension( - m_c3t3.triangulation(), "c3t3_vertices_"); -#endif + FT sqlen = tr().segment(e).squared_length(); + if (sqlen < sqmin || sqlen > sqmax) + return false; } + std::cout << "Resolution reached" << std::endl; + return true; + } - private: - - bool check_vertex_dimensions() - { - typename Tr::Finite_vertices_iterator vit; - for (vit = tr().finite_vertices_begin(); - vit != tr().finite_vertices_end(); ++vit) - { - // dimension is -1 for Mesh_3 "far points" - // for other vertices, it is in [0; 3] - if (vit->in_dimension() < -1 || vit->in_dimension() > 3) - return false; - } - return true; - } - - - public: - Tr& tr() - { - return m_c3t3.triangulation(); - } - const Tr& tr() const - { - return m_c3t3.triangulation(); - } - - void remesh(const std::size_t& max_it, - const std::size_t& nb_extra_iterations) - { - std::size_t it_nb = 0; - while (it_nb < max_it) - { - ++it_nb; -#ifdef CGAL_TETRAHEDRAL_REMESHING_VERBOSE - std::cout << "# Iteration " << it_nb << " #" << std::endl; -#endif - if (!resolution_reached()) - { - split(); - collapse(); - } - flip(); - smooth(); + //peel off slivers + std::size_t postprocess(const double sliver_angle = 0.1) + { + if (m_protect_boundaries) + return 0; #ifdef CGAL_TETRAHEDRAL_REMESHING_VERBOSE - std::cout << "# Iteration " << it_nb << " done : " - << tr().number_of_vertices() - << " vertices #" << std::endl; + std::cout << "Postprocess..."; + std::cout.flush(); +#endif + + std::size_t nb_slivers_peel = 0; + typedef typename Tr::Finite_cells_iterator Finite_cells_iterator; + for (Finite_cells_iterator cit = tr().finite_cells_begin(); + cit != tr().finite_cells_end(); ++cit) + { + if(m_c3t3.is_in_complex(cit) && min_dihedral_angle(tr(), cit) < sliver_angle) + { + for (int i = 0; i < 4; ++i) + { + if (!m_c3t3.is_in_complex(cit->neighbor(i))) + { + m_c3t3.remove_from_complex(cit); + ++nb_slivers_peel; + } + } + } + } + + CGAL_assertion(tr().tds().is_valid(true)); + CGAL_assertion(debug::are_cell_orientations_valid(tr())); + +#ifdef CGAL_DUMP_REMESHING_STEPS + CGAL::Tetrahedral_remeshing::debug::dump_triangulation_cells(tr(), "99-postprocess.mesh"); + CGAL::Tetrahedral_remeshing::debug::dump_binary(m_c3t3, "99-postprocess.binary.cgal"); +#endif +#ifdef CGAL_TETRAHEDRAL_REMESHING_VERBOSE + std::cout << "(peeling removed " << nb_slivers_peel << " slivers)" << std::endl; + std::cout << "done." << std::endl; +#endif + return nb_slivers_peel; + } + + void finalize() + { + if (m_c3t3_pbackup != NULL) + m_c3t3_pbackup->swap(m_c3t3); + else + m_tr_pbackup->swap(m_c3t3.triangulation()); + } + +private: + void init_c3t3(const EdgeIsConstrainedMap& ecmap, + const FacetIsConstrainedMap& fcmap) + { +#ifdef CGAL_TETRAHEDRAL_REMESHING_DEBUG + std::size_t nbc = 0; + std::size_t nbf = 0; + std::size_t nbe = 0; + std::size_t nbv = 0; +#endif + + //tag cells + typedef typename Tr::Finite_cells_iterator Finite_cells_iterator; + for (Finite_cells_iterator cit = tr().finite_cells_begin(); + cit != tr().finite_cells_end(); + ++cit) + { + if (m_cell_selector(cit)) + { + m_c3t3.add_to_complex(cit, cit->subdomain_index()); + +#ifdef CGAL_TETRAHEDRAL_REMESHING_DEBUG + ++nbc; +#endif + } + if (!input_is_c3t3()) + { + for (int i = 0; i < 4; ++i) + { + if (cit->vertex(i)->in_dimension() == -1) + cit->vertex(i)->set_dimension(3); + } + } +#ifdef CGAL_TETRAHEDRAL_REMESHING_DEBUG + else if (input_is_c3t3() && m_c3t3.is_in_complex(cit)) + ++nbc; +#endif + } + + //tag facets + typedef typename Tr::Facet Facet; + typedef typename Tr::Finite_facets_iterator Finite_facets_iterator; + for (Finite_facets_iterator fit = tr().finite_facets_begin(); + fit != tr().finite_facets_end(); + ++fit) + { + const Facet f = *fit; + const Facet mf = tr().mirror_facet(f); + const Subdomain_index s1 = f.first->subdomain_index(); + const Subdomain_index s2 = mf.first->subdomain_index(); + if (s1 != s2 + || get(fcmap, f) + || get(fcmap, mf) + || (m_c3t3_pbackup == NULL && f.first->is_facet_on_surface(f.second))) + { + m_c3t3.add_to_complex(f, 1); + + const int i = f.second; + for (int j = 0; j < 3; ++j) + { + Vertex_handle vij = f.first->vertex(Tr::vertex_triple_index(i, j)); + if (vij->in_dimension() == -1 || vij->in_dimension() > 2) + vij->set_dimension(2); + } +#ifdef CGAL_TETRAHEDRAL_REMESHING_DEBUG + ++nbf; +#endif + } + } +#ifdef CGAL_TETRAHEDRAL_REMESHING_DEBUG + CGAL::Tetrahedral_remeshing::debug::dump_facets_in_complex(m_c3t3, "facets_in_complex.off"); +#endif + + //tag edges + typedef typename Tr::Edge Edge; + typedef typename Tr::Finite_edges_iterator Finite_edges_iterator; + for (Finite_edges_iterator eit = tr().finite_edges_begin(); + eit != tr().finite_edges_end(); + ++eit) + { + const Edge& e = *eit; + + if (m_c3t3.is_in_complex(e)) + { + CGAL_assertion(m_c3t3.in_dimension(e.first->vertex(e.second)) <= 1); + CGAL_assertion(m_c3t3.in_dimension(e.first->vertex(e.third)) <= 1); +#ifdef CGAL_TETRAHEDRAL_REMESHING_DEBUG + ++nbe; +#endif + continue; + } + + if (get(ecmap, CGAL::Tetrahedral_remeshing::make_vertex_pair(e)) + || nb_incident_subdomains(e, m_c3t3) > 2 + || nb_incident_surface_patches(e, m_c3t3) > 1) + { + m_c3t3.add_to_complex(e, 1); + + Vertex_handle v = e.first->vertex(e.second); + if (v->in_dimension() == -1 || v->in_dimension() > 1) + v->set_dimension(1); + + v = e.first->vertex(e.third); + if (v->in_dimension() == -1 || v->in_dimension() > 1) + v->set_dimension(1); + +#ifdef CGAL_TETRAHEDRAL_REMESHING_DEBUG + ++nbe; +#endif + } + } +#ifdef CGAL_TETRAHEDRAL_REMESHING_DEBUG + CGAL::Tetrahedral_remeshing::debug::dump_edges_in_complex(m_c3t3, "edges_in_complex.polylines.txt"); +#endif + + //tag vertices + typedef typename Tr::Finite_vertices_iterator Finite_vertices_iterator; + unsigned int corner_id = 0; + for (Finite_vertices_iterator vit = tr().finite_vertices_begin(); + vit != tr().finite_vertices_end(); + ++vit) + { + if ( vit->in_dimension() == 0 + || nb_incident_complex_edges(vit, m_c3t3) > 2) + { + if(!m_c3t3.is_in_complex(vit)) + m_c3t3.add_to_complex(vit, ++corner_id); + + if (vit->in_dimension() == -1 || vit->in_dimension() > 0) + vit->set_dimension(0); + +#ifdef CGAL_TETRAHEDRAL_REMESHING_DEBUG + ++nbv; +#endif + } + } + +#ifdef CGAL_TETRAHEDRAL_REMESHING_DEBUG + std::cout << "C3t3 ready :" << std::endl; + std::cout << "\t cells = " << nbc << std::endl; + std::cout << "\t facets = " << nbf << std::endl; + std::cout << "\t edges = " << nbe << std::endl; + std::cout << "\t vertices = " << nbv << std::endl; + + CGAL::Tetrahedral_remeshing::debug::dump_vertices_by_dimension( + m_c3t3.triangulation(), "c3t3_vertices_"); +#endif + } + +private: + + bool check_vertex_dimensions() + { + typename Tr::Finite_vertices_iterator vit; + for (vit = tr().finite_vertices_begin(); + vit != tr().finite_vertices_end(); ++vit) + { + // dimension is -1 for Mesh_3 "far points" + // for other vertices, it is in [0; 3] + if (vit->in_dimension() < -1 || vit->in_dimension() > 3) + return false; + } + return true; + } + + +public: + Tr& tr() + { + return m_c3t3.triangulation(); + } + const Tr& tr() const + { + return m_c3t3.triangulation(); + } + + void remesh(const std::size_t& max_it, + const std::size_t& nb_extra_iterations) + { + std::size_t it_nb = 0; + while (it_nb < max_it) + { + ++it_nb; +#ifdef CGAL_TETRAHEDRAL_REMESHING_VERBOSE + std::cout << "# Iteration " << it_nb << " #" << std::endl; +#endif + if (!resolution_reached()) + { + split(); + collapse(); + } + flip(); + smooth(); + +#ifdef CGAL_TETRAHEDRAL_REMESHING_VERBOSE + std::cout << "# Iteration " << it_nb << " done : " + << tr().number_of_vertices() + << " vertices #" << std::endl; #endif #ifdef CGAL_DUMP_REMESHING_STEPS - std::ostringstream ossi; - ossi << "statistics_" << it_nb << ".txt"; - Tetrahedral_remeshing::internal::compute_statistics( - tr(), m_cell_selector, ossi.str().c_str()); + std::ostringstream ossi; + ossi << "statistics_" << it_nb << ".txt"; + Tetrahedral_remeshing::internal::compute_statistics( + tr(), m_cell_selector, ossi.str().c_str()); #endif - } - - while (it_nb < max_it + nb_extra_iterations) - { - ++it_nb; - - flip(); - smooth(); - -#ifdef CGAL_TETRAHEDRAL_REMESHING_VERBOSE - std::cout << "# Iteration " << it_nb << " (flip and smooth only) done : " - << tr().number_of_vertices() - << " vertices #" << std::endl; -#endif -#ifdef CGAL_DUMP_REMESHING_STEPS - std::ostringstream ossi; - ossi << "statistics_" << it_nb << ".txt"; - Tetrahedral_remeshing::internal::compute_statistics( - tr(), m_cell_selector, ossi.str().c_str()); -#endif - } - - postprocess(); //peel off boundary slivers - - finalize(); - //Warning : triangulation() is now empty } - };//end class Adaptive_remesher + while (it_nb < max_it + nb_extra_iterations) + { + ++it_nb; + + flip(); + smooth(); + +#ifdef CGAL_TETRAHEDRAL_REMESHING_VERBOSE + std::cout << "# Iteration " << it_nb << " (flip and smooth only) done : " + << tr().number_of_vertices() + << " vertices #" << std::endl; +#endif +#ifdef CGAL_DUMP_REMESHING_STEPS + std::ostringstream ossi; + ossi << "statistics_" << it_nb << ".txt"; + Tetrahedral_remeshing::internal::compute_statistics( + tr(), m_cell_selector, ossi.str().c_str()); +#endif + } + + postprocess(); //peel off boundary slivers + + finalize(); + //Warning : triangulation() is now empty + } + +};//end class Adaptive_remesher + }//end namespace internal }//end namespace Tetrahedral_remeshing }//end namespace CGAL diff --git a/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/tetrahedral_remeshing_helpers.h b/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/tetrahedral_remeshing_helpers.h index 0261ea88d10..cc971d0c873 100644 --- a/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/tetrahedral_remeshing_helpers.h +++ b/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/tetrahedral_remeshing_helpers.h @@ -25,1292 +25,1294 @@ namespace CGAL { namespace Tetrahedral_remeshing { - enum Subdomain_relation { EQUAL, DIFFERENT, INCLUDED, INCLUDES }; - enum Sliver_removal_result { INVALID_ORIENTATION, INVALID_CELL, INVALID_VERTEX, - NOT_FLIPPABLE, EDGE_PROBLEM, VALID_FLIP, NO_BEST_CONFIGURATION, EXISTING_EDGE }; - template - CGAL::Point_3 point(const CGAL::Point_3& p) +enum Subdomain_relation { EQUAL, DIFFERENT, INCLUDED, INCLUDES }; +enum Sliver_removal_result { INVALID_ORIENTATION, INVALID_CELL, INVALID_VERTEX, + NOT_FLIPPABLE, EDGE_PROBLEM, VALID_FLIP, NO_BEST_CONFIGURATION, EXISTING_EDGE }; + +template +CGAL::Point_3 point(const CGAL::Point_3& p) +{ + return p; +} +template +CGAL::Point_3 point(const CGAL::Weighted_point_3& wp) +{ + typename K::Construct_point_3 pt = K().construct_point_3_object(); + return pt(wp); +} + +template +CGAL::Vector_3 vec(const CGAL::Point_3& p) +{ + typename K::Construct_vector_3 v = K().construct_vector_3_object(); + return v(CGAL::ORIGIN, p); +} +template +CGAL::Vector_3 vec(const CGAL::Weighted_point_3& wp) +{ + return vec(point(wp)); +} + + +const int indices_table[4][3] = { { 3, 1, 2 }, + { 3, 2, 0 }, + { 3, 0, 1 }, + { 2, 1, 0 } }; + +int indices(const int& i, const int& j) +{ + CGAL_assertion(i >= 0 && i < 4); + CGAL_assertion(j >= 0 && j < 3); + return indices_table[i][j]; +} + +template +typename Gt::FT dihedral_angle(const Point& p, + const Point& q, + const Point& r, + const Point& s, + const Gt& gt) +{ + return gt.compute_approximate_dihedral_angle_3_object()(p, q, r, s); +} + +template +typename Geom_traits::FT min_dihedral_angle(const Point& p, + const Point& q, + const Point& r, + const Point& s, + const Geom_traits& gt) +{ + typedef typename Geom_traits::FT FT; + FT a = CGAL::abs(dihedral_angle(p, q, r, s, gt)); + FT min_dh = a; + + a = CGAL::abs(dihedral_angle(p, r, q, s, gt)); + min_dh = (std::min)(a, min_dh); + + a = CGAL::abs(dihedral_angle(p, s, q, r, gt)); + min_dh = (std::min)(a, min_dh); + + a = CGAL::abs(dihedral_angle(q, r, p, s, gt)); + min_dh = (std::min)(a, min_dh); + + a = CGAL::abs(dihedral_angle(q, s, p, r, gt)); + min_dh = (std::min)(a, min_dh); + + a = CGAL::abs(dihedral_angle(r, s, p, q, gt)); + min_dh = (std::min)(a, min_dh); + + return min_dh; +} + +template +typename Tr::Geom_traits::FT min_dihedral_angle(const Tr& tr, + const typename Tr::Vertex_handle v0, + const typename Tr::Vertex_handle v1, + const typename Tr::Vertex_handle v2, + const typename Tr::Vertex_handle v3) +{ + return min_dihedral_angle(point(v0->point()), + point(v1->point()), + point(v2->point()), + point(v3->point()), + tr.geom_traits()); +} + +template +typename Tr::Geom_traits::FT min_dihedral_angle(const Tr& tr, + const typename Tr::Cell_handle c) +{ + return min_dihedral_angle(tr, + c->vertex(0), + c->vertex(1), + c->vertex(2), + c->vertex(3)); +} + +template +typename Tr::Geom_traits::Vector_3 facet_normal(const Tr& tr, + const typename Tr::Facet& f) +{ + const typename Tr::Geom_traits gt = tr.geom_traits(); + typename Tr::Geom_traits::Construct_normal_3 cn + = gt.construct_normal_3_object(); + return cn(point(f.first->vertex((f.second + 1) % 4)->point()), + point(f.first->vertex((f.second + 2) % 4)->point()), + point(f.first->vertex((f.second + 3) % 4)->point())); +} + +template +std::pair make_vertex_pair(const Vh v1, const Vh v2) +{ + if (v2 < v1) return std::make_pair(v2, v1); + else return std::make_pair(v1, v2); +} + +template +std::pair + make_vertex_pair(const typename Tr::Edge& e) +{ + typedef typename Tr::Vertex_handle Vertex_handle; + Vertex_handle v1 = e.first->vertex(e.second); + Vertex_handle v2 = e.first->vertex(e.third); + return make_vertex_pair(v1, v2); +} + +template +CGAL::Triple make_vertex_triple(const Vh vh0, const Vh vh1, const Vh vh2) +{ + CGAL::Triple ft(vh0, vh1, vh2); + if (ft.template get<1>() < ft.template get<0>()) std::swap(ft.template get<0>(), ft.template get<1>()); + if (ft.template get<2>() < ft.template get<1>()) std::swap(ft.template get<1>(), ft.template get<2>()); + if (ft.template get<1>() < ft.template get<0>()) std::swap(ft.template get<0>(), ft.template get<1>()); + return ft; +} + +template +Facet canonical_facet(const Facet& f) +{ + const typename Facet::first_type c = f.first; + const int i = f.second; + const typename Facet::first_type c2 = c->neighbor(i); + return (c2 < c) ? std::make_pair(c2, c2->index(c)) : std::make_pair(c, i); +} + +template +bool is_on_feature(const VertexHandle v) +{ + return (v->in_dimension() == 1 || v->in_dimension() == 0); +} + +template +bool is_well_oriented(const Tr& tr, const typename Tr::Cell_handle ch) +{ + return is_well_oriented(tr, ch->vertex(0), ch->vertex(1), + ch->vertex(2), ch->vertex(3)); +} + +template +bool is_well_oriented(const Tr& tr, + const typename Tr::Vertex_handle v0, + const typename Tr::Vertex_handle v1, + const typename Tr::Vertex_handle v2, + const typename Tr::Vertex_handle v3) +{ + return CGAL::POSITIVE == tr.geom_traits().orientation_3_object()( + point(v0->point()), + point(v1->point()), + point(v2->point()), + point(v3->point())); +} + +template +bool is_boundary(const C3T3& c3t3, + const typename C3T3::Facet& f, + const CellSelector& cell_selector) +{ + return c3t3.is_in_complex(f) + || cell_selector(f.first) != cell_selector(f.first->neighbor(f.second)); +} + +template +bool is_boundary(const C3T3& c3t3, + const typename C3T3::Triangulation::Edge& e, + CellSelector cell_selector) +{ + typedef typename C3T3::Triangulation Tr; + typedef typename Tr::Facet_circulator Facet_circulator; + typedef typename Tr::Facet Facet; + + Facet_circulator fcirc = c3t3.triangulation().incident_facets(e); + Facet_circulator fend = fcirc; + + do { - return p; - } - template - CGAL::Point_3 point(const CGAL::Weighted_point_3& wp) - { - typename K::Construct_point_3 pt = K().construct_point_3_object(); - return pt(wp); - } - - template - CGAL::Vector_3 vec(const CGAL::Point_3& p) - { - typename K::Construct_vector_3 v = K().construct_vector_3_object(); - return v(CGAL::ORIGIN, p); - } - template - CGAL::Vector_3 vec(const CGAL::Weighted_point_3& wp) - { - return vec(point(wp)); - } - - - const int indices_table[4][3] = { { 3, 1, 2 }, - { 3, 2, 0 }, - { 3, 0, 1 }, - { 2, 1, 0 } }; - - int indices(const int& i, const int& j) - { - CGAL_assertion(i >= 0 && i < 4); - CGAL_assertion(j >= 0 && j < 3); - return indices_table[i][j]; - } - - template - typename Gt::FT dihedral_angle(const Point& p, - const Point& q, - const Point& r, - const Point& s, - const Gt& gt) - { - return gt.compute_approximate_dihedral_angle_3_object()(p, q, r, s); - } - - template - typename Geom_traits::FT min_dihedral_angle(const Point& p, - const Point& q, - const Point& r, - const Point& s, - const Geom_traits& gt) - { - typedef typename Geom_traits::FT FT; - FT a = CGAL::abs(dihedral_angle(p, q, r, s, gt)); - FT min_dh = a; - - a = CGAL::abs(dihedral_angle(p, r, q, s, gt)); - min_dh = (std::min)(a, min_dh); - - a = CGAL::abs(dihedral_angle(p, s, q, r, gt)); - min_dh = (std::min)(a, min_dh); - - a = CGAL::abs(dihedral_angle(q, r, p, s, gt)); - min_dh = (std::min)(a, min_dh); - - a = CGAL::abs(dihedral_angle(q, s, p, r, gt)); - min_dh = (std::min)(a, min_dh); - - a = CGAL::abs(dihedral_angle(r, s, p, q, gt)); - min_dh = (std::min)(a, min_dh); - - return min_dh; - } - - template - typename Tr::Geom_traits::FT min_dihedral_angle(const Tr& tr, - const typename Tr::Vertex_handle v0, - const typename Tr::Vertex_handle v1, - const typename Tr::Vertex_handle v2, - const typename Tr::Vertex_handle v3) - { - return min_dihedral_angle(point(v0->point()), - point(v1->point()), - point(v2->point()), - point(v3->point()), - tr.geom_traits()); - } - - template - typename Tr::Geom_traits::FT min_dihedral_angle(const Tr& tr, - const typename Tr::Cell_handle c) - { - return min_dihedral_angle(tr, - c->vertex(0), - c->vertex(1), - c->vertex(2), - c->vertex(3)); - } - - template - typename Tr::Geom_traits::Vector_3 facet_normal(const Tr& tr, - const typename Tr::Facet& f) - { - const typename Tr::Geom_traits gt = tr.geom_traits(); - typename Tr::Geom_traits::Construct_normal_3 cn - = gt.construct_normal_3_object(); - return cn(point(f.first->vertex((f.second + 1) % 4)->point()), - point(f.first->vertex((f.second + 2) % 4)->point()), - point(f.first->vertex((f.second + 3) % 4)->point())); - } - - template - std::pair make_vertex_pair(const Vh v1, const Vh v2) - { - if (v2 < v1) return std::make_pair(v2, v1); - else return std::make_pair(v1, v2); - } - - template - std::pair - make_vertex_pair(const typename Tr::Edge& e) - { - typedef typename Tr::Vertex_handle Vertex_handle; - Vertex_handle v1 = e.first->vertex(e.second); - Vertex_handle v2 = e.first->vertex(e.third); - return make_vertex_pair(v1, v2); - } - - template - CGAL::Triple make_vertex_triple(const Vh vh0, const Vh vh1, const Vh vh2) - { - CGAL::Triple ft(vh0, vh1, vh2); - if (ft.template get<1>() < ft.template get<0>()) std::swap(ft.template get<0>(), ft.template get<1>()); - if (ft.template get<2>() < ft.template get<1>()) std::swap(ft.template get<1>(), ft.template get<2>()); - if (ft.template get<1>() < ft.template get<0>()) std::swap(ft.template get<0>(), ft.template get<1>()); - return ft; - } - - template - Facet canonical_facet(const Facet& f) - { - const typename Facet::first_type c = f.first; - const int i = f.second; - const typename Facet::first_type c2 = c->neighbor(i); - return (c2 < c) ? std::make_pair(c2, c2->index(c)) : std::make_pair(c, i); - } - - template - bool is_on_feature(const VertexHandle v) - { - return (v->in_dimension() == 1 || v->in_dimension() == 0); - } - - template - bool is_well_oriented(const Tr& tr, const typename Tr::Cell_handle ch) - { - return is_well_oriented(tr, ch->vertex(0), ch->vertex(1), - ch->vertex(2), ch->vertex(3)); - } - - template - bool is_well_oriented(const Tr& tr, - const typename Tr::Vertex_handle v0, - const typename Tr::Vertex_handle v1, - const typename Tr::Vertex_handle v2, - const typename Tr::Vertex_handle v3) - { - return CGAL::POSITIVE == tr.geom_traits().orientation_3_object()( - point(v0->point()), - point(v1->point()), - point(v2->point()), - point(v3->point())); - } - - template - bool is_boundary(const C3T3& c3t3, - const typename C3T3::Facet& f, - const CellSelector& cell_selector) - { - return c3t3.is_in_complex(f) - || cell_selector(f.first) != cell_selector(f.first->neighbor(f.second)); - } - - template - bool is_boundary(const C3T3& c3t3, - const typename C3T3::Triangulation::Edge& e, - CellSelector cell_selector) - { - typedef typename C3T3::Triangulation Tr; - typedef typename Tr::Facet_circulator Facet_circulator; - typedef typename Tr::Facet Facet; - - Facet_circulator fcirc = c3t3.triangulation().incident_facets(e); - Facet_circulator fend = fcirc; - - do - { - const Facet& f = *fcirc; - if (is_boundary(c3t3, f, cell_selector)) - return true; - } - while (++fcirc != fend); - - return false; - } - - template - bool is_boundary_edge(const typename C3t3::Vertex_handle& v0, - const typename C3t3::Vertex_handle& v1, - const C3t3& c3t3, - const CellSelector& cell_selector) - { - typedef typename C3t3::Edge Edge; - typedef typename C3t3::Cell_handle Cell_handle; - - Cell_handle cell; - int i0, i1; - if (c3t3.triangulation().tds().is_edge(v0, v1, cell, i0, i1)) - return is_boundary(c3t3, Edge(cell, i0, i1), cell_selector); - else - return false; - } - - template - bool is_boundary_vertex(const typename C3t3::Vertex_handle& v, - const C3t3& c3t3, - CellSelector cell_selector) - { - typedef typename C3t3::Facet Facet; - std::vector facets; - c3t3.triangulation().incident_facets(v, std::back_inserter(facets)); - - for(const Facet& f : facets) - { - if (c3t3.is_in_complex(f)) - return true; - if (cell_selector(f.first) ^ cell_selector(f.first->neighbor(f.second))) - return true; - } - return false; - } - - template - typename C3t3::Surface_patch_index surface_patch_index(const typename C3t3::Vertex_handle v, - const C3t3& c3t3) - { - typedef typename C3t3::Surface_patch_index Surface_patch_index; - typedef typename C3t3::Facet Facet; - std::vector facets; - c3t3.triangulation().incident_facets(v, std::back_inserter(facets)); - - for(const Facet& f : facets) - { - if (c3t3.is_in_complex(f)) - return c3t3.surface_patch_index(f); - } - return Surface_patch_index(); - } - - template - bool is_edge_in_complex(const typename C3t3::Vertex_handle& v0, - const typename C3t3::Vertex_handle& v1, - const C3t3& c3t3) - { - typedef typename C3t3::Edge Edge; - typedef typename C3t3::Cell_handle Cell_handle; - - Cell_handle cell; - int i0, i1; - if (c3t3.triangulation().tds().is_edge(v0, v1, cell, i0, i1)) - return c3t3.is_in_complex(Edge(cell, i0, i1)); - else - return false; - } - - template - OutputIterator incident_subdomains(const typename C3t3::Vertex_handle v, - const C3t3& c3t3, - OutputIterator oit) - { - typedef typename C3t3::Triangulation::Cell_handle Cell_handle; - std::vector cells; - c3t3.triangulation().incident_cells(v, std::back_inserter(cells)); - - for (std::size_t i = 0; i < cells.size(); ++i) - *oit++ = cells[i]->subdomain_index(); - - return oit; - } - - template - OutputIterator incident_subdomains(const typename C3t3::Edge& e, - const C3t3& c3t3, - OutputIterator oit) - { - typedef typename C3t3::Triangulation::Cell_circulator Cell_circulator; - - Cell_circulator circ = c3t3.triangulation().incident_cells(e); - Cell_circulator end = circ; - do - { - *oit++ = circ->subdomain_index(); - } while (++circ != end); - - return oit; - } - - template - OutputIterator incident_surface_patches(const typename C3t3::Edge& e, - const C3t3& c3t3, - OutputIterator oit) - { - typedef typename C3t3::Triangulation::Facet_circulator Facet_circulator; - typedef typename C3t3::Triangulation::Facet Facet; - - Facet_circulator circ = c3t3.triangulation().incident_facets(e); - Facet_circulator end = circ; - do - { - const Facet& f = *circ; - if(c3t3.is_in_complex(f)) - *oit++ = c3t3.surface_patch_index(f); - } - while (++circ != end); - - return oit; - } - - template - std::size_t nb_incident_subdomains(const typename C3t3::Vertex_handle v, - const C3t3& c3t3) - { - typedef typename C3t3::Subdomain_index Subdomain_index; - - boost::unordered_set indices; - incident_subdomains(v, c3t3, std::inserter(indices, indices.begin())); - - return indices.size(); - } - - template - std::size_t nb_incident_subdomains(const typename C3t3::Edge& e, - const C3t3& c3t3) - { - typedef typename C3t3::Subdomain_index Subdomain_index; - - boost::unordered_set indices; - incident_subdomains(e, c3t3, std::inserter(indices, indices.begin())); - - return indices.size(); - } - - template - std::size_t nb_incident_surface_patches(const typename C3t3::Edge& e, - const C3t3& c3t3) - { - typedef typename C3t3::Surface_patch_index Surface_patch_index; - - boost::unordered_set indices; - incident_surface_patches(e, c3t3, std::inserter(indices, indices.begin())); - - return indices.size(); - } - - template - std::size_t nb_incident_complex_edges(const typename C3t3::Vertex_handle v, - const C3t3& c3t3) - { - typedef typename C3t3::Edge Edge; - boost::unordered_set edges; - c3t3.triangulation().finite_incident_edges(v, std::inserter(edges, edges.begin())); - - std::size_t count = 0; - for (const Edge& e : edges) - { - if (c3t3.is_in_complex(e)) - ++count; - } - return count; - } - - - template - bool is_feature(const typename C3t3::Vertex_handle v, - const typename C3t3::Vertex_handle neighbor, - const C3t3& c3t3) - { - typename C3t3::Cell_handle ch; - int i0, i1; - if (c3t3.triangulation().is_edge(v, neighbor, ch, i0, i1)) - { - typename C3t3::Edge edge(ch, i0, i1); - return c3t3.is_in_complex(edge); - } - return false; - } - - template - bool is_feature(const typename C3t3::Vertex_handle v, const C3t3& c3t3) - { - typedef typename C3t3::Edge Edge; - - if (c3t3.number_of_corners() > 0) - { - return c3t3.is_in_complex(v); - } - else if (nb_incident_subdomains(v, c3t3) > 3) - { - std::vector edges; - c3t3.triangulation().finite_incident_edges(v, std::back_inserter(edges)); - - int feature_count = 0; - for(const Edge& ei : edges) - { - if (c3t3.is_in_complex(ei)) - { - feature_count++; - if (feature_count >= 3) - return true; - } - } - } - return false; - } - - /** - * returns true iff `v` is on the outer hull of c3t3.triangulation() - * i.e. finite and incident to at least one infinite cell - */ - template - bool is_on_convex_hull(const typename C3t3::Vertex_handle v, - const C3t3& c3t3) - { - if (v == c3t3.triangulation().infinite_vertex()) + const Facet& f = *fcirc; + if (is_boundary(c3t3, f, cell_selector)) return true; + } + while (++fcirc != fend); - //on hull == incident to infinite cell - typedef typename C3t3::Triangulation::Cell_handle Cell_handle; + return false; +} - std::vector cells; - c3t3.triangulation().incident_cells(v, std::back_inserter(cells)); - for (Cell_handle ci : cells) - { - if (c3t3.triangulation().is_infinite(ci)) - return true; - } +template +bool is_boundary_edge(const typename C3t3::Vertex_handle& v0, + const typename C3t3::Vertex_handle& v1, + const C3t3& c3t3, + const CellSelector& cell_selector) +{ + typedef typename C3t3::Edge Edge; + typedef typename C3t3::Cell_handle Cell_handle; + + Cell_handle cell; + int i0, i1; + if (c3t3.triangulation().tds().is_edge(v0, v1, cell, i0, i1)) + return is_boundary(c3t3, Edge(cell, i0, i1), cell_selector); + else return false; - } +} - /** - * returns true iff `edge` is on the outer hull - * of c3t3.triangulation() - * i.e. finite and incident to at least one infinite cell - */ - template - bool is_on_convex_hull(const typename C3t3::Edge & edge, - const C3t3& c3t3) +template +bool is_boundary_vertex(const typename C3t3::Vertex_handle& v, + const C3t3& c3t3, + CellSelector cell_selector) +{ + typedef typename C3t3::Facet Facet; + std::vector facets; + c3t3.triangulation().incident_facets(v, std::back_inserter(facets)); + + for(const Facet& f : facets) { - typedef typename C3t3::Triangulation::Cell_circulator Cell_circulator; - Cell_circulator circ = c3t3.triangulation().incident_cells(edge); - Cell_circulator done = circ; - do - { - if (c3t3.triangulation().is_infinite(circ)) - return true; - } while (++circ != done); + if (c3t3.is_in_complex(f)) + return true; + if (cell_selector(f.first) ^ cell_selector(f.first->neighbor(f.second))) + return true; + } + return false; +} +template +typename C3t3::Surface_patch_index surface_patch_index(const typename C3t3::Vertex_handle v, + const C3t3& c3t3) +{ + typedef typename C3t3::Surface_patch_index Surface_patch_index; + typedef typename C3t3::Facet Facet; + std::vector facets; + c3t3.triangulation().incident_facets(v, std::back_inserter(facets)); + + for(const Facet& f : facets) + { + if (c3t3.is_in_complex(f)) + return c3t3.surface_patch_index(f); + } + return Surface_patch_index(); +} + +template +bool is_edge_in_complex(const typename C3t3::Vertex_handle& v0, + const typename C3t3::Vertex_handle& v1, + const C3t3& c3t3) +{ + typedef typename C3t3::Edge Edge; + typedef typename C3t3::Cell_handle Cell_handle; + + Cell_handle cell; + int i0, i1; + if (c3t3.triangulation().tds().is_edge(v0, v1, cell, i0, i1)) + return c3t3.is_in_complex(Edge(cell, i0, i1)); + else return false; - } +} - template - bool is_outside(const typename C3t3::Edge & edge, - const C3t3& c3t3, - CellSelector cell_selector) +template +OutputIterator incident_subdomains(const typename C3t3::Vertex_handle v, + const C3t3& c3t3, + OutputIterator oit) +{ + typedef typename C3t3::Triangulation::Cell_handle Cell_handle; + std::vector cells; + c3t3.triangulation().incident_cells(v, std::back_inserter(cells)); + + for (std::size_t i = 0; i < cells.size(); ++i) + *oit++ = cells[i]->subdomain_index(); + + return oit; +} + +template +OutputIterator incident_subdomains(const typename C3t3::Edge& e, + const C3t3& c3t3, + OutputIterator oit) +{ + typedef typename C3t3::Triangulation::Cell_circulator Cell_circulator; + + Cell_circulator circ = c3t3.triangulation().incident_cells(e); + Cell_circulator end = circ; + do { - typedef typename C3t3::Triangulation::Cell_circulator Cell_circulator; - Cell_circulator circ = c3t3.triangulation().incident_cells(edge); - Cell_circulator done = circ; - do + *oit++ = circ->subdomain_index(); + } while (++circ != end); + + return oit; +} + +template +OutputIterator incident_surface_patches(const typename C3t3::Edge& e, + const C3t3& c3t3, + OutputIterator oit) +{ + typedef typename C3t3::Triangulation::Facet_circulator Facet_circulator; + typedef typename C3t3::Triangulation::Facet Facet; + + Facet_circulator circ = c3t3.triangulation().incident_facets(e); + Facet_circulator end = circ; + do + { + const Facet& f = *circ; + if(c3t3.is_in_complex(f)) + *oit++ = c3t3.surface_patch_index(f); + } + while (++circ != end); + + return oit; +} + +template +std::size_t nb_incident_subdomains(const typename C3t3::Vertex_handle v, + const C3t3& c3t3) +{ + typedef typename C3t3::Subdomain_index Subdomain_index; + + boost::unordered_set indices; + incident_subdomains(v, c3t3, std::inserter(indices, indices.begin())); + + return indices.size(); +} + +template +std::size_t nb_incident_subdomains(const typename C3t3::Edge& e, + const C3t3& c3t3) +{ + typedef typename C3t3::Subdomain_index Subdomain_index; + + boost::unordered_set indices; + incident_subdomains(e, c3t3, std::inserter(indices, indices.begin())); + + return indices.size(); +} + +template +std::size_t nb_incident_surface_patches(const typename C3t3::Edge& e, + const C3t3& c3t3) +{ + typedef typename C3t3::Surface_patch_index Surface_patch_index; + + boost::unordered_set indices; + incident_surface_patches(e, c3t3, std::inserter(indices, indices.begin())); + + return indices.size(); +} + +template +std::size_t nb_incident_complex_edges(const typename C3t3::Vertex_handle v, + const C3t3& c3t3) +{ + typedef typename C3t3::Edge Edge; + boost::unordered_set edges; + c3t3.triangulation().finite_incident_edges(v, std::inserter(edges, edges.begin())); + + std::size_t count = 0; + for (const Edge& e : edges) + { + if (c3t3.is_in_complex(e)) + ++count; + } + return count; +} + + +template +bool is_feature(const typename C3t3::Vertex_handle v, + const typename C3t3::Vertex_handle neighbor, + const C3t3& c3t3) +{ + typename C3t3::Cell_handle ch; + int i0, i1; + if (c3t3.triangulation().is_edge(v, neighbor, ch, i0, i1)) + { + typename C3t3::Edge edge(ch, i0, i1); + return c3t3.is_in_complex(edge); + } + return false; +} + +template +bool is_feature(const typename C3t3::Vertex_handle v, const C3t3& c3t3) +{ + typedef typename C3t3::Edge Edge; + + if (c3t3.number_of_corners() > 0) + { + return c3t3.is_in_complex(v); + } + else if (nb_incident_subdomains(v, c3t3) > 3) + { + std::vector edges; + c3t3.triangulation().finite_incident_edges(v, std::back_inserter(edges)); + + int feature_count = 0; + for(const Edge& ei : edges) { - // is cell in complex? - if (c3t3.is_in_complex(circ)) - return false; - // does circ belong to the selection? - if (cell_selector(circ)) - return false; - - ++circ; - } while (circ != done); - - return true; //all incident cells are outside or infinite - } - - template - bool is_selected(const typename C3t3::Vertex_handle v, - const C3t3& c3t3, - CellSelector cell_selector) - { - typedef typename C3t3::Triangulation::Cell_handle Cell_handle; - - std::vector cells; - c3t3.triangulation().incident_cells(v, std::back_inserter(cells)); - - for(Cell_handle c : cells) - { - if (cell_selector(c)) - return true; - } - return false; - } - - template - bool is_internal(const typename C3t3::Edge& edge, - const C3t3& c3t3, - CellSelector cell_selector) - { - const typename C3t3::Vertex_handle vs = edge.first->vertex(edge.second); - const typename C3t3::Vertex_handle vt = edge.first->vertex(edge.third); - - typedef typename C3t3::Triangulation::Cell_circulator Cell_circulator; - Cell_circulator circ = c3t3.triangulation().incident_cells(edge); - Cell_circulator done = circ; - - const typename C3t3::Subdomain_index si = circ->subdomain_index(); - do - { - if (c3t3.triangulation().is_infinite(circ)) - return false; - if (si != circ->subdomain_index()) - return false; - if (!cell_selector(circ)) - return false; - if (c3t3.is_in_complex( - circ, - CGAL::Triangulation_utils_3::next_around_edge(circ->index(vs), circ->index(vt)))) - return false; - } while (++circ != done); - - return true; - } - - template - void normalize(typename Gt::Vector_3& v, const Gt& gt) - { - typedef typename Gt::FT FT; - - const FT norm = CGAL::approximate_sqrt(gt.compute_squared_length_3_object()(v)); - if (norm != FT(0)) - v = gt.construct_divided_vector_3_object()(v, norm); - } - - template - typename Gt::Vector_3 normal(const Facet& f, const Gt& gt) - { - typedef typename Gt::Vector_3 Vector_3; - typedef typename Gt::Point_3 Point; - typedef typename Gt::FT FT; - - Point p0 = point(f.first->vertex((f.second + 1) % 4)->point()); - Point p1 = point(f.first->vertex((f.second + 2) % 4)->point()); - const Point& p2 = point(f.first->vertex((f.second + 3) % 4)->point()); - - if (f.second % 2 == 0)//equivalent to the commented orientation test - std::swap(p0, p1); - - Vector_3 n = gt.construct_cross_product_vector_3_object()( - gt.construct_vector_3_object()(p1, p2), - gt.construct_vector_3_object()(p1, p0)); - - //cross-product(AB, AC)'s norm is the area of the parallelogram - //formed by these 2 vectors. - //the triangle's area is half of it - return gt.construct_scaled_vector_3_object()(n, FT(1) / FT(2)); - } - - template - OutputIterator get_internal_edges(const C3t3& c3t3, - CellSelector cell_selector, - OutputIterator oit)/*holds Edges*/ - { - for (typename C3t3::Triangulation::Finite_edges_iterator - eit = c3t3.triangulation().finite_edges_begin(); - eit != c3t3.triangulation().finite_edges_end(); - ++eit) - { - const typename C3t3::Edge& e = *eit; - if (is_internal(e, c3t3, cell_selector)) + if (c3t3.is_in_complex(ei)) { - *oit++ = make_vertex_pair(e); + feature_count++; + if (feature_count >= 3) + return true; } } - return oit; } + return false; +} - template - bool topology_test(const typename C3t3::Edge& edge, - const C3t3& c3t3, - const CellSelector& cell_selector) +/** +* returns true iff `v` is on the outer hull of c3t3.triangulation() +* i.e. finite and incident to at least one infinite cell +*/ +template +bool is_on_convex_hull(const typename C3t3::Vertex_handle v, + const C3t3& c3t3) +{ + if (v == c3t3.triangulation().infinite_vertex()) + return true; + + //on hull == incident to infinite cell + typedef typename C3t3::Triangulation::Cell_handle Cell_handle; + + std::vector cells; + c3t3.triangulation().incident_cells(v, std::back_inserter(cells)); + for (Cell_handle ci : cells) { - typedef typename C3t3::Vertex_handle Vertex_handle; - typedef typename C3t3::Cell_handle Cell_handle; - typedef typename C3t3::Edge Edge; - typedef typename C3t3::Facet Facet; - typedef typename C3t3::Triangulation::Facet_circulator Facet_circulator; + if (c3t3.triangulation().is_infinite(ci)) + return true; + } + return false; +} - const Vertex_handle v0 = edge.first->vertex(edge.second); - const Vertex_handle v1 = edge.first->vertex(edge.third); +/** +* returns true iff `edge` is on the outer hull +* of c3t3.triangulation() +* i.e. finite and incident to at least one infinite cell +*/ +template +bool is_on_convex_hull(const typename C3t3::Edge & edge, + const C3t3& c3t3) +{ + typedef typename C3t3::Triangulation::Cell_circulator Cell_circulator; + Cell_circulator circ = c3t3.triangulation().incident_cells(edge); + Cell_circulator done = circ; + do + { + if (c3t3.triangulation().is_infinite(circ)) + return true; + } while (++circ != done); - // the "topology test" checks that : - // no incident non-boundary facet has 3 boundary edges - // no incident boundary facet has 3 feature edges + return false; +} - Facet_circulator fcirc = c3t3.triangulation().incident_facets(edge); - Facet_circulator fdone = fcirc; - do +template +bool is_outside(const typename C3t3::Edge & edge, + const C3t3& c3t3, + CellSelector cell_selector) +{ + typedef typename C3t3::Triangulation::Cell_circulator Cell_circulator; + Cell_circulator circ = c3t3.triangulation().incident_cells(edge); + Cell_circulator done = circ; + do + { + // is cell in complex? + if (c3t3.is_in_complex(circ)) + return false; + // does circ belong to the selection? + if (cell_selector(circ)) + return false; + + ++circ; + } while (circ != done); + + return true; //all incident cells are outside or infinite +} + +template +bool is_selected(const typename C3t3::Vertex_handle v, + const C3t3& c3t3, + CellSelector cell_selector) +{ + typedef typename C3t3::Triangulation::Cell_handle Cell_handle; + + std::vector cells; + c3t3.triangulation().incident_cells(v, std::back_inserter(cells)); + + for(Cell_handle c : cells) + { + if (cell_selector(c)) + return true; + } + return false; +} + +template +bool is_internal(const typename C3t3::Edge& edge, + const C3t3& c3t3, + CellSelector cell_selector) +{ + const typename C3t3::Vertex_handle vs = edge.first->vertex(edge.second); + const typename C3t3::Vertex_handle vt = edge.first->vertex(edge.third); + + typedef typename C3t3::Triangulation::Cell_circulator Cell_circulator; + Cell_circulator circ = c3t3.triangulation().incident_cells(edge); + Cell_circulator done = circ; + + const typename C3t3::Subdomain_index si = circ->subdomain_index(); + do + { + if (c3t3.triangulation().is_infinite(circ)) + return false; + if (si != circ->subdomain_index()) + return false; + if (!cell_selector(circ)) + return false; + if (c3t3.is_in_complex( + circ, + CGAL::Triangulation_utils_3::next_around_edge(circ->index(vs), circ->index(vt)))) + return false; + } while (++circ != done); + + return true; +} + +template +void normalize(typename Gt::Vector_3& v, const Gt& gt) +{ + typedef typename Gt::FT FT; + + const FT norm = CGAL::approximate_sqrt(gt.compute_squared_length_3_object()(v)); + if (norm != FT(0)) + v = gt.construct_divided_vector_3_object()(v, norm); +} + +template +typename Gt::Vector_3 normal(const Facet& f, const Gt& gt) +{ + typedef typename Gt::Vector_3 Vector_3; + typedef typename Gt::Point_3 Point; + typedef typename Gt::FT FT; + + Point p0 = point(f.first->vertex((f.second + 1) % 4)->point()); + Point p1 = point(f.first->vertex((f.second + 2) % 4)->point()); + const Point& p2 = point(f.first->vertex((f.second + 3) % 4)->point()); + + if (f.second % 2 == 0)//equivalent to the commented orientation test + std::swap(p0, p1); + + Vector_3 n = gt.construct_cross_product_vector_3_object()( + gt.construct_vector_3_object()(p1, p2), + gt.construct_vector_3_object()(p1, p0)); + + //cross-product(AB, AC)'s norm is the area of the parallelogram + //formed by these 2 vectors. + //the triangle's area is half of it + return gt.construct_scaled_vector_3_object()(n, FT(1) / FT(2)); +} + +template +OutputIterator get_internal_edges(const C3t3& c3t3, + CellSelector cell_selector, + OutputIterator oit)/*holds Edges*/ +{ + for (typename C3t3::Triangulation::Finite_edges_iterator + eit = c3t3.triangulation().finite_edges_begin(); + eit != c3t3.triangulation().finite_edges_end(); + ++eit) + { + const typename C3t3::Edge& e = *eit; + if (is_internal(e, c3t3, cell_selector)) { - if (c3t3.triangulation().is_infinite(fcirc->first)) - continue; + *oit++ = make_vertex_pair(e); + } + } + return oit; +} - const Facet& f = *fcirc; - if (is_boundary(c3t3, f, cell_selector)) - //boundary : check that facet does not have 3 feature edges +template +bool topology_test(const typename C3t3::Edge& edge, + const C3t3& c3t3, + const CellSelector& cell_selector) +{ + typedef typename C3t3::Vertex_handle Vertex_handle; + typedef typename C3t3::Cell_handle Cell_handle; + typedef typename C3t3::Edge Edge; + typedef typename C3t3::Facet Facet; + typedef typename C3t3::Triangulation::Facet_circulator Facet_circulator; + + const Vertex_handle v0 = edge.first->vertex(edge.second); + const Vertex_handle v1 = edge.first->vertex(edge.third); + + // the "topology test" checks that : + // no incident non-boundary facet has 3 boundary edges + // no incident boundary facet has 3 feature edges + + Facet_circulator fcirc = c3t3.triangulation().incident_facets(edge); + Facet_circulator fdone = fcirc; + do + { + if (c3t3.triangulation().is_infinite(fcirc->first)) + continue; + + const Facet& f = *fcirc; + if (is_boundary(c3t3, f, cell_selector)) + //boundary : check that facet does not have 3 feature edges + { + //Get the ids of the opposite vertices + for (int i = 1; i < 4; i++) { - //Get the ids of the opposite vertices - for (int i = 1; i < 4; i++) + Vertex_handle vi = f.first->vertex((f.second + i) % 4); + if (vi != v0 && vi != v1 && nb_incident_subdomains(vi, c3t3) > 1) { - Vertex_handle vi = f.first->vertex((f.second + i) % 4); - if (vi != v0 && vi != v1 && nb_incident_subdomains(vi, c3t3) > 1) - { - if (is_edge_in_complex(v0, vi, c3t3) - && is_edge_in_complex(v1, vi, c3t3)) - return false; - } + if (is_edge_in_complex(v0, vi, c3t3) + && is_edge_in_complex(v1, vi, c3t3)) + return false; } } - else //non-boundary : check that facet does not have 3 boundary edges - { - const Cell_handle circ = f.first; - const int i = f.second; - if (is_boundary(c3t3, Edge(circ, (i + 1) % 4, (i + 2) % 4), cell_selector) - && is_boundary(c3t3, Edge(circ, (i + 2) % 4, (i + 3) % 4), cell_selector) - && is_boundary(c3t3, Edge(circ, (i + 3) % 4, (i + 1) % 4), cell_selector)) - return false; - } - } while (++fcirc != fdone); - - return true; - } - - template - void get_edge_info(const typename C3t3::Edge& edge, - bool& update_v0, - bool& update_v1, - const C3t3& c3t3, - const CellSelector& cell_selector) - { - typedef typename C3t3::Vertex_handle Vertex_handle; - - update_v0 = false; - update_v1 = false; - - const Vertex_handle v0 = edge.first->vertex(edge.second); - const Vertex_handle v1 = edge.first->vertex(edge.third); - - const int dim0 = c3t3.in_dimension(v0); - const int dim1 = c3t3.in_dimension(v1); - - if (dim0 == 3) - { - CGAL_assertion(!is_on_convex_hull(v0, c3t3)); - update_v0 = true; - if (dim1 == 3) - { - CGAL_assertion(!is_on_convex_hull(v1, c3t3)); - update_v1 = true; - return; - } - else // dim1 is 2, 1, or 0 - return; } - else if (dim1 == 3) + else //non-boundary : check that facet does not have 3 boundary edges { + const Cell_handle circ = f.first; + const int i = f.second; + if (is_boundary(c3t3, Edge(circ, (i + 1) % 4, (i + 2) % 4), cell_selector) + && is_boundary(c3t3, Edge(circ, (i + 2) % 4, (i + 3) % 4), cell_selector) + && is_boundary(c3t3, Edge(circ, (i + 3) % 4, (i + 1) % 4), cell_selector)) + return false; + } + } while (++fcirc != fdone); + + return true; +} + +template +void get_edge_info(const typename C3t3::Edge& edge, + bool& update_v0, + bool& update_v1, + const C3t3& c3t3, + const CellSelector& cell_selector) +{ + typedef typename C3t3::Vertex_handle Vertex_handle; + + update_v0 = false; + update_v1 = false; + + const Vertex_handle v0 = edge.first->vertex(edge.second); + const Vertex_handle v1 = edge.first->vertex(edge.third); + + const int dim0 = c3t3.in_dimension(v0); + const int dim1 = c3t3.in_dimension(v1); + + if (dim0 == 3) + { + CGAL_assertion(!is_on_convex_hull(v0, c3t3)); + update_v0 = true; + if (dim1 == 3) + { + CGAL_assertion(!is_on_convex_hull(v1, c3t3)); update_v1 = true; return; } - - // from now on, all cases lie on surfaces, or between surfaces - CGAL_assertion(dim0 != 3 && dim1 != 3); - - //feature edges and feature vertices - if (dim0 < 2 || dim1 < 2) - { - if (c3t3.is_in_complex(edge)) - { - if (!topology_test(edge, c3t3, cell_selector)) - { -#ifdef CGAL_DEBUG_TET_REMESHING_IN_PLUGIN - nb_topology_test++; -#endif - return; - } - const std::size_t nb_si_v0 = nb_incident_subdomains(v0, c3t3); - const std::size_t nb_si_v1 = nb_incident_subdomains(v1, c3t3); - - if (nb_si_v0 > nb_si_v1) { - if (!c3t3.is_in_complex(v1)) - update_v1 = true; - } - else if (nb_si_v1 > nb_si_v0) { - if (!c3t3.is_in_complex(v0)) - update_v0 = true; - } - else { - if (!c3t3.is_in_complex(v0)) - update_v0 = true; - if (!c3t3.is_in_complex(v1)) - update_v1 = true; - } - } + else // dim1 is 2, 1, or 0 return; - } + } + else if (dim1 == 3) + { + update_v1 = true; + return; + } - if (dim0 == 2 && dim1 == 2) + // from now on, all cases lie on surfaces, or between surfaces + CGAL_assertion(dim0 != 3 && dim1 != 3); + + //feature edges and feature vertices + if (dim0 < 2 || dim1 < 2) + { + if (c3t3.is_in_complex(edge)) { - if (is_boundary(c3t3, edge, cell_selector)) + if (!topology_test(edge, c3t3, cell_selector)) { - if (!topology_test(edge, c3t3, cell_selector)) - return; - Subdomain_relation subdomain_rel = compare_subdomains(v0, v1, c3t3); +#ifdef CGAL_DEBUG_TET_REMESHING_IN_PLUGIN + nb_topology_test++; +#endif + return; + } + const std::size_t nb_si_v0 = nb_incident_subdomains(v0, c3t3); + const std::size_t nb_si_v1 = nb_incident_subdomains(v1, c3t3); - //Vertices on the same surface - if (subdomain_rel == INCLUDES) { + if (nb_si_v0 > nb_si_v1) { + if (!c3t3.is_in_complex(v1)) + update_v1 = true; + } + else if (nb_si_v1 > nb_si_v0) { + if (!c3t3.is_in_complex(v0)) + update_v0 = true; + } + else { + if (!c3t3.is_in_complex(v0)) + update_v0 = true; + if (!c3t3.is_in_complex(v1)) + update_v1 = true; + } + } + return; + } + + if (dim0 == 2 && dim1 == 2) + { + if (is_boundary(c3t3, edge, cell_selector)) + { + if (!topology_test(edge, c3t3, cell_selector)) + return; + Subdomain_relation subdomain_rel = compare_subdomains(v0, v1, c3t3); + + //Vertices on the same surface + if (subdomain_rel == INCLUDES) { + update_v1 = true; + } + else if (subdomain_rel == INCLUDED) { + update_v0 = true; + } + else if (subdomain_rel == EQUAL) + { + if (c3t3.number_of_edges() == 0) + { + update_v0 = true; update_v1 = true; } - else if (subdomain_rel == INCLUDED) { - update_v0 = true; - } - else if (subdomain_rel == EQUAL) - { - if (c3t3.number_of_edges() == 0) - { - update_v0 = true; - update_v1 = true; - } - else - { - const bool v0_on_feature = is_on_feature(v0); - const bool v1_on_feature = is_on_feature(v1); - - if (v0_on_feature && v1_on_feature) { - if (c3t3.is_in_complex(edge)) { - if (!c3t3.is_in_complex(v0)) - update_v0 = true; - if (!c3t3.is_in_complex(v1)) - update_v1 = true; - } - } - else { - if (!v0_on_feature) { - update_v0 = true; - } - if (!v1_on_feature) { - update_v1 = true; - } - } - } - } - } - } - } - - template - Subdomain_relation compare_subdomains(const typename C3t3::Vertex_handle v0, - const typename C3t3::Vertex_handle v1, - const C3t3& c3t3) - { - typedef typename C3t3::Subdomain_index Subdomain_index; - - std::vector subdomains_v0; - incident_subdomains(v0, c3t3, std::back_inserter(subdomains_v0)); - std::sort(subdomains_v0.begin(), subdomains_v0.end()); - - std::vector subdomains_v1; - incident_subdomains(v1, c3t3, std::back_inserter(subdomains_v1)); - std::sort(subdomains_v1.begin(), subdomains_v1.end()); - - if (subdomains_v0.size() == subdomains_v1.size()) - { - for (unsigned int i = 0; i < subdomains_v0.size(); i++) - if (subdomains_v0[i] != subdomains_v1[i]) - return DIFFERENT; - return EQUAL; - } - else - { - std::vector - intersection((std::min)(subdomains_v0.size(), subdomains_v1.size()), -1); - typename std::vector::iterator - end_it = std::set_intersection(subdomains_v0.begin(), subdomains_v0.end(), - subdomains_v1.begin(), subdomains_v1.end(), - intersection.begin()); - std::ptrdiff_t intersection_size = (end_it - intersection.begin()); - - if (subdomains_v0.size() > subdomains_v1.size() - && intersection_size == std::ptrdiff_t(subdomains_v1.size())) - { - return INCLUDES; - } - else if (intersection_size == std::ptrdiff_t(subdomains_v0.size())) { - return INCLUDED; - } - } - return DIFFERENT; - } - - - namespace debug - { - // forward-declaration - template - void dump_cells(const CellRange& cells, const char* filename); - - template - void dump_edges(const Bimap& edges, const char* filename) - { - std::ofstream ofs(filename); - ofs.precision(17); - - BOOST_FOREACH(typename Bimap::left_const_reference it, edges.left) - { - ofs << "2 " << point(it.first.first->point()) - << " " << point(it.first.second->point()) << std::endl; - } - ofs.close(); - } - - template - void dump_facet(const Facet& f, OutputStream& os) - { - os << "4 "; - os << point(f.first->vertex((f.second + 1) % 4)->point()) << " " - << point(f.first->vertex((f.second + 2) % 4)->point()) << " " - << point(f.first->vertex((f.second + 3) % 4)->point()) << " " - << point(f.first->vertex((f.second + 1) % 4)->point()); - os << std::endl; - } - - template - void dump_facets(const FacetRange& facets, const char* filename) - { - std::ofstream os(filename); - for (typename FacetRange::value_type f : facets) - { - dump_facet(f, os); - } - os.close(); - } - - template - void dump_polylines(const CellRange& cells, const char* filename) - { - std::ofstream ofs(filename); - if (!ofs) return; - - for (typename CellRange::const_iterator it = cells.begin(); - it != cells.end(); ++it) - { - for (int i = 0; i < 4; ++i) - dump_facet(std::make_pair(*it, i), ofs); - } - ofs.close(); - } - - template - bool are_cell_orientations_valid(const Tr& tr) - { - typedef typename Tr::Geom_traits::Point_3 Point_3; - typedef typename Tr::Facet Facet; - - std::set facets; - for (const typename Tr::Cell_handle ch : tr.finite_cell_handles()) - { - const Point_3& p0 = point(ch->vertex(0)->point()); - const Point_3& p1 = point(ch->vertex(1)->point()); - const Point_3& p2 = point(ch->vertex(2)->point()); - const Point_3& p3 = point(ch->vertex(3)->point()); - - const CGAL::Orientation o = CGAL::orientation(p0, p1, p2, p3); - if (o != CGAL::POSITIVE) - { - facets.insert(canonical_facet(Facet(ch, 0))); - facets.insert(canonical_facet(Facet(ch, 1))); - facets.insert(canonical_facet(Facet(ch, 2))); - facets.insert(canonical_facet(Facet(ch, 3))); - } - } - if (!facets.empty()) - { - std::cerr << "Warning : there are inverted cells!\n" - << "\tSee cells_with_negative_volume.polylines.txt" << std::endl; - dump_facets(facets, "cells_with_negative_volume.polylines.txt"); - } - return facets.empty(); - } - - template - void dump_surface_off(const Tr& tr, const char* filename) - { - typedef typename Tr::Vertex_handle Vertex_handle; - typedef typename Tr::Cell_handle Cell_handle; - typedef typename Tr::Finite_facets_iterator Finite_facets_iterator; - typedef boost::bimap Bimap_t; - typedef typename Bimap_t::left_map::value_type value_type; - - //collect vertices - Bimap_t vertices; - std::size_t nbf = 0; - int index = 0; - for (Finite_facets_iterator fit = tr.finite_facets_begin(); - fit != tr.finite_facets_end(); ++fit) - { - Cell_handle c = fit->first; - int i = fit->second; - if (tr.is_infinite(c) || tr.is_infinite(c->neighbor(i))) - { - nbf++; - for (int j = 1; j < 4; ++j) - { - Vertex_handle vij = c->vertex((i + j) % 4); - if (vertices.left.find(vij) == vertices.left.end()) - vertices.left.insert(value_type(vij, index++)); - } - } - } - - //write header - std::ofstream ofs(filename); - ofs.precision(17); - ofs << "OFF" << std::endl; - ofs << vertices.left.size() << " " << nbf << " 0" << std::endl << std::endl; - - // write vertices - for (typename Bimap_t::right_iterator vit = vertices.right.begin(); - vit != vertices.right.end(); ++vit) - { - ofs << point(vit->second->point()) << std::endl; - } - - //write facets - std::size_t nbf_print = 0; - for (Finite_facets_iterator fit = tr.finite_facets_begin(); - fit != tr.finite_facets_end(); ++fit) - { - Cell_handle c = fit->first; - int i = fit->second; - if (tr.is_infinite(c) || tr.is_infinite(c->neighbor(i))) - { - ofs << "3 " << vertices.left.at(c->vertex((i + 1) % 4)) << " " - << vertices.left.at(c->vertex((i + 2) % 4)) << " " - << vertices.left.at(c->vertex((i + 3) % 4)) << std::endl; - ++nbf_print; - } - } - CGAL_assertion(nbf == nbf_print); - - ofs.close(); - } - - template - void dump_cells_off(const Tr& tr, const char* filename) - { - typedef typename Tr::Vertex_handle Vertex_handle; - typedef typename Tr::Cell_handle Cell_handle; - typedef typename Tr::Finite_facets_iterator Finite_facets_iterator; - typedef typename Tr::Finite_vertices_iterator Finite_vertices_iterator; - typedef boost::bimap Bimap_t; - typedef typename Bimap_t::left_map::value_type value_type; - - //write header - std::ofstream ofs(filename); - ofs.precision(17); - ofs << "OFF" << std::endl; - ofs << tr.number_of_vertices() - << " " << tr.number_of_finite_facets() << " 0" << std::endl << std::endl; - - //collect and write vertices - Bimap_t vertices; - int index = 0; - for (Finite_vertices_iterator vit = tr.finite_vertices_begin(); - vit != tr.finite_vertices_end(); ++vit) - { - vertices.left.insert(value_type(vit, index++)); - ofs << vit->point().x() << " " - << vit->point().y() << " " - << vit->point().z() << std::endl; - } - - //write facets - for (Finite_facets_iterator fit = tr.finite_facets_begin(); - fit != tr.finite_facets_end(); ++fit) - { - Cell_handle c = fit->first; - int i = fit->second; - ofs << "3 " << vertices.left.at(c->vertex((i + 1) % 4)) << " " - << vertices.left.at(c->vertex((i + 2) % 4)) << " " - << vertices.left.at(c->vertex((i + 3) % 4)) << std::endl; - } - ofs.close(); - } - - template - void dump_cells(const CellRange& cells, - const IndexRange& indices, - const char* filename) - { - typedef typename Tr::Vertex_handle Vertex_handle; - typedef typename Tr::Point Point; - typedef boost::bimap Bimap_t; - typedef typename Bimap_t::left_map::value_type value_type; - - CGAL_assertion(indices.empty() || cells.size() == indices.size()); - - //collect vertices - Bimap_t vertices; - int index = 1; - for (typename CellRange::const_iterator cit = cells.begin(); - cit != cells.end(); - ++cit) - { - for (int i = 0; i < 4; ++i) - { - Vertex_handle vi = (*cit)->vertex(i); - if (vertices.left.find(vi) == vertices.left.end()) - vertices.left.insert(value_type(vi, index++)); - } - } - - //write cells - std::ofstream ofs(filename); - ofs.precision(17); - ofs << "MeshVersionFormatted 1" << std::endl; - ofs << "Dimension 3" << std::endl; - ofs << "Vertices" << std::endl << vertices.size() << std::endl; - for (typename Bimap_t::right_const_iterator vit = vertices.right.begin(); - vit != vertices.right.end(); - ++vit) - { - const Point& p = vit->second->point(); - ofs << p.x() << " " << p.y() << " " << p.z() << " 2" << std::endl; - } - ofs << "Tetrahedra " << std::endl << cells.size() << std::endl; - typename IndexRange::const_iterator iit = indices.begin(); - for (typename CellRange::const_iterator cit = cells.begin(); - cit != cells.end(); - ++cit) - { - ofs << vertices.left.at((*cit)->vertex(0)) - << " " << vertices.left.at((*cit)->vertex(1)) - << " " << vertices.left.at((*cit)->vertex(2)) - << " " << vertices.left.at((*cit)->vertex(3)); - - if (iit == indices.end()) - ofs << " 1" << std::endl; else { - ofs << " " << (*iit) << std::endl; - ++iit; + const bool v0_on_feature = is_on_feature(v0); + const bool v1_on_feature = is_on_feature(v1); + + if (v0_on_feature && v1_on_feature) { + if (c3t3.is_in_complex(edge)) { + if (!c3t3.is_in_complex(v0)) + update_v0 = true; + if (!c3t3.is_in_complex(v1)) + update_v1 = true; + } + } + else { + if (!v0_on_feature) { + update_v0 = true; + } + if (!v1_on_feature) { + update_v1 = true; + } + } } } - ofs << "End" << std::endl; - ofs.close(); } + } +} - template - void dump_cells(const CellRange& cells, const char* filename) +template +Subdomain_relation compare_subdomains(const typename C3t3::Vertex_handle v0, + const typename C3t3::Vertex_handle v1, + const C3t3& c3t3) +{ + typedef typename C3t3::Subdomain_index Subdomain_index; + + std::vector subdomains_v0; + incident_subdomains(v0, c3t3, std::back_inserter(subdomains_v0)); + std::sort(subdomains_v0.begin(), subdomains_v0.end()); + + std::vector subdomains_v1; + incident_subdomains(v1, c3t3, std::back_inserter(subdomains_v1)); + std::sort(subdomains_v1.begin(), subdomains_v1.end()); + + if (subdomains_v0.size() == subdomains_v1.size()) + { + for (unsigned int i = 0; i < subdomains_v0.size(); i++) + if (subdomains_v0[i] != subdomains_v1[i]) + return DIFFERENT; + return EQUAL; + } + else + { + std::vector + intersection((std::min)(subdomains_v0.size(), subdomains_v1.size()), -1); + typename std::vector::iterator + end_it = std::set_intersection(subdomains_v0.begin(), subdomains_v0.end(), + subdomains_v1.begin(), subdomains_v1.end(), + intersection.begin()); + std::ptrdiff_t intersection_size = (end_it - intersection.begin()); + + if (subdomains_v0.size() > subdomains_v1.size() + && intersection_size == std::ptrdiff_t(subdomains_v1.size())) { - std::vector indices; - dump_cells(cells, indices, filename); + return INCLUDES; } + else if (intersection_size == std::ptrdiff_t(subdomains_v0.size())) { + return INCLUDED; + } + } + return DIFFERENT; +} - template - void dump_cells_in_complex(const Tr& tr, const char* filename) + +namespace debug +{ + +// forward-declaration +template +void dump_cells(const CellRange& cells, const char* filename); + +template +void dump_edges(const Bimap& edges, const char* filename) +{ + std::ofstream ofs(filename); + ofs.precision(17); + + BOOST_FOREACH(typename Bimap::left_const_reference it, edges.left) + { + ofs << "2 " << point(it.first.first->point()) + << " " << point(it.first.second->point()) << std::endl; + } + ofs.close(); +} + +template +void dump_facet(const Facet& f, OutputStream& os) +{ + os << "4 "; + os << point(f.first->vertex((f.second + 1) % 4)->point()) << " " + << point(f.first->vertex((f.second + 2) % 4)->point()) << " " + << point(f.first->vertex((f.second + 3) % 4)->point()) << " " + << point(f.first->vertex((f.second + 1) % 4)->point()); + os << std::endl; +} + +template +void dump_facets(const FacetRange& facets, const char* filename) +{ + std::ofstream os(filename); + for (typename FacetRange::value_type f : facets) + { + dump_facet(f, os); + } + os.close(); +} + +template +void dump_polylines(const CellRange& cells, const char* filename) +{ + std::ofstream ofs(filename); + if (!ofs) return; + + for (typename CellRange::const_iterator it = cells.begin(); + it != cells.end(); ++it) + { + for (int i = 0; i < 4; ++i) + dump_facet(std::make_pair(*it, i), ofs); + } + ofs.close(); +} + +template +bool are_cell_orientations_valid(const Tr& tr) +{ + typedef typename Tr::Geom_traits::Point_3 Point_3; + typedef typename Tr::Facet Facet; + + std::set facets; + for (const typename Tr::Cell_handle ch : tr.finite_cell_handles()) + { + const Point_3& p0 = point(ch->vertex(0)->point()); + const Point_3& p1 = point(ch->vertex(1)->point()); + const Point_3& p2 = point(ch->vertex(2)->point()); + const Point_3& p3 = point(ch->vertex(3)->point()); + + const CGAL::Orientation o = CGAL::orientation(p0, p1, p2, p3); + if (o != CGAL::POSITIVE) { - std::vector cells; - std::vector indices; - - for (typename Tr::Finite_cells_iterator cit = tr.finite_cells_begin(); - cit != tr.finite_cells_end(); ++cit) - { - if (cit->subdomain_index() > 0) - { - cells.push_back(cit); - indices.push_back(cit->subdomain_index()); - } - } - dump_cells(cells, indices, filename); + facets.insert(canonical_facet(Facet(ch, 0))); + facets.insert(canonical_facet(Facet(ch, 1))); + facets.insert(canonical_facet(Facet(ch, 2))); + facets.insert(canonical_facet(Facet(ch, 3))); } + } + if (!facets.empty()) + { + std::cerr << "Warning : there are inverted cells!\n" + << "\tSee cells_with_negative_volume.polylines.txt" << std::endl; + dump_facets(facets, "cells_with_negative_volume.polylines.txt"); + } + return facets.empty(); +} - template - void dump_facets_in_complex(const C3t3& c3t3, const char* filename) +template +void dump_surface_off(const Tr& tr, const char* filename) +{ + typedef typename Tr::Vertex_handle Vertex_handle; + typedef typename Tr::Cell_handle Cell_handle; + typedef typename Tr::Finite_facets_iterator Finite_facets_iterator; + typedef boost::bimap Bimap_t; + typedef typename Bimap_t::left_map::value_type value_type; + + //collect vertices + Bimap_t vertices; + std::size_t nbf = 0; + int index = 0; + for (Finite_facets_iterator fit = tr.finite_facets_begin(); + fit != tr.finite_facets_end(); ++fit) + { + Cell_handle c = fit->first; + int i = fit->second; + if (tr.is_infinite(c) || tr.is_infinite(c->neighbor(i))) { - typedef typename C3t3::Triangulation Tr; - typedef typename Tr::Vertex_handle Vertex_handle; - typedef typename Tr::Cell_handle Cell_handle; - typedef typename C3t3::Facets_in_complex_iterator Facets_in_complex_iterator; - typedef boost::bimap Bimap_t; - typedef typename Bimap_t::left_map::value_type value_type; - - //collect vertices - Bimap_t vertices; - std::size_t nbf = 0; - int index = 0; - for (Facets_in_complex_iterator fit = c3t3.facets_in_complex_begin(); - fit != c3t3.facets_in_complex_end(); ++fit) + nbf++; + for (int j = 1; j < 4; ++j) { - Cell_handle c = fit->first; - int i = fit->second; - - nbf++; - for (int j = 1; j < 4; ++j) - { - Vertex_handle vij = c->vertex((i + j) % 4); - if (vertices.left.find(vij) == vertices.left.end()) - vertices.left.insert(value_type(vij, index++)); - } + Vertex_handle vij = c->vertex((i + j) % 4); + if (vertices.left.find(vij) == vertices.left.end()) + vertices.left.insert(value_type(vij, index++)); } - - //write header - std::ofstream ofs(filename); - ofs.precision(17); - ofs << "OFF" << std::endl; - ofs << vertices.left.size() << " " << nbf << " 0" << std::endl << std::endl; - - // write vertices - for (typename Bimap_t::right_iterator vit = vertices.right.begin(); - vit != vertices.right.end(); ++vit) - { - ofs << point(vit->second->point()) << std::endl; - } - - //write facets - std::size_t nbf_print = 0; - for (Facets_in_complex_iterator fit = c3t3.facets_in_complex_begin(); - fit != c3t3.facets_in_complex_end(); ++fit) - { - Cell_handle c = fit->first; - int i = fit->second; - ofs << "3 " << vertices.left.at(c->vertex((i + 1) % 4)) << " " - << vertices.left.at(c->vertex((i + 2) % 4)) << " " - << vertices.left.at(c->vertex((i + 3) % 4)) << std::endl; - ++nbf_print; - } - CGAL_assertion(nbf == nbf_print); - - ofs.close(); } + } - template - void dump_edges_in_complex(const C3T3& c3t3, const char* filename) + //write header + std::ofstream ofs(filename); + ofs.precision(17); + ofs << "OFF" << std::endl; + ofs << vertices.left.size() << " " << nbf << " 0" << std::endl << std::endl; + + // write vertices + for (typename Bimap_t::right_iterator vit = vertices.right.begin(); + vit != vertices.right.end(); ++vit) + { + ofs << point(vit->second->point()) << std::endl; + } + + //write facets + std::size_t nbf_print = 0; + for (Finite_facets_iterator fit = tr.finite_facets_begin(); + fit != tr.finite_facets_end(); ++fit) + { + Cell_handle c = fit->first; + int i = fit->second; + if (tr.is_infinite(c) || tr.is_infinite(c->neighbor(i))) { - std::ofstream ofs(filename); - ofs.precision(17); - for (typename C3T3::Edges_in_complex_iterator eit = c3t3.edges_in_complex_begin(); - eit != c3t3.edges_in_complex_end(); ++eit) - { - const typename C3T3::Edge& e = *eit; - ofs << "2 " - << point(e.first->vertex(e.second)->point()) << " " - << point(e.first->vertex(e.third)->point()) << "\n"; - } - ofs.close(); + ofs << "3 " << vertices.left.at(c->vertex((i + 1) % 4)) << " " + << vertices.left.at(c->vertex((i + 2) % 4)) << " " + << vertices.left.at(c->vertex((i + 3) % 4)) << std::endl; + ++nbf_print; } + } + CGAL_assertion(nbf == nbf_print); - template - void dump_cells_with_small_dihedral_angle(const Tr& tr, - const double angle_bound, - CellSelector cell_select, - const char* filename) + ofs.close(); +} + +template +void dump_cells_off(const Tr& tr, const char* filename) +{ + typedef typename Tr::Vertex_handle Vertex_handle; + typedef typename Tr::Cell_handle Cell_handle; + typedef typename Tr::Finite_facets_iterator Finite_facets_iterator; + typedef typename Tr::Finite_vertices_iterator Finite_vertices_iterator; + typedef boost::bimap Bimap_t; + typedef typename Bimap_t::left_map::value_type value_type; + + //write header + std::ofstream ofs(filename); + ofs.precision(17); + ofs << "OFF" << std::endl; + ofs << tr.number_of_vertices() + << " " << tr.number_of_finite_facets() << " 0" << std::endl << std::endl; + + //collect and write vertices + Bimap_t vertices; + int index = 0; + for (Finite_vertices_iterator vit = tr.finite_vertices_begin(); + vit != tr.finite_vertices_end(); ++vit) + { + vertices.left.insert(value_type(vit, index++)); + ofs << vit->point().x() << " " + << vit->point().y() << " " + << vit->point().z() << std::endl; + } + + //write facets + for (Finite_facets_iterator fit = tr.finite_facets_begin(); + fit != tr.finite_facets_end(); ++fit) + { + Cell_handle c = fit->first; + int i = fit->second; + ofs << "3 " << vertices.left.at(c->vertex((i + 1) % 4)) << " " + << vertices.left.at(c->vertex((i + 2) % 4)) << " " + << vertices.left.at(c->vertex((i + 3) % 4)) << std::endl; + } + ofs.close(); +} + +template +void dump_cells(const CellRange& cells, + const IndexRange& indices, + const char* filename) +{ + typedef typename Tr::Vertex_handle Vertex_handle; + typedef typename Tr::Point Point; + typedef boost::bimap Bimap_t; + typedef typename Bimap_t::left_map::value_type value_type; + + CGAL_assertion(indices.empty() || cells.size() == indices.size()); + + //collect vertices + Bimap_t vertices; + int index = 1; + for (typename CellRange::const_iterator cit = cells.begin(); + cit != cells.end(); + ++cit) + { + for (int i = 0; i < 4; ++i) { - typedef typename Tr::Cell_handle Cell_handle; - typedef typename Tr::Cell::Subdomain_index Subdomain_index; - std::vector cells; - std::vector indices; - - for (typename Tr::Finite_cells_iterator cit = tr.finite_cells_begin(); - cit != tr.finite_cells_end(); ++cit) - { - Cell_handle c = cit; - if ( c->subdomain_index() != Subdomain_index() - && cell_select(c) - && min_dihedral_angle(tr, c) < angle_bound) - { - - cells.push_back(c); - indices.push_back(c->subdomain_index()); - } - } - std::cout << "bad cells : " << cells.size() << std::endl; - dump_cells(cells, indices, filename); + Vertex_handle vi = (*cit)->vertex(i); + if (vertices.left.find(vi) == vertices.left.end()) + vertices.left.insert(value_type(vi, index++)); } + } - template - void dump_vertices_by_dimension(const Tr& tr, const char* prefix) + //write cells + std::ofstream ofs(filename); + ofs.precision(17); + ofs << "MeshVersionFormatted 1" << std::endl; + ofs << "Dimension 3" << std::endl; + ofs << "Vertices" << std::endl << vertices.size() << std::endl; + for (typename Bimap_t::right_const_iterator vit = vertices.right.begin(); + vit != vertices.right.end(); + ++vit) + { + const Point& p = vit->second->point(); + ofs << p.x() << " " << p.y() << " " << p.z() << " 2" << std::endl; + } + ofs << "Tetrahedra " << std::endl << cells.size() << std::endl; + typename IndexRange::const_iterator iit = indices.begin(); + for (typename CellRange::const_iterator cit = cells.begin(); + cit != cells.end(); + ++cit) + { + ofs << vertices.left.at((*cit)->vertex(0)) + << " " << vertices.left.at((*cit)->vertex(1)) + << " " << vertices.left.at((*cit)->vertex(2)) + << " " << vertices.left.at((*cit)->vertex(3)); + + if (iit == indices.end()) + ofs << " 1" << std::endl; + else { - typedef typename Tr::Vertex_handle Vertex_handle; - std::vector< std::vector > vertices_per_dimension(4); - - for (typename Tr::Finite_vertices_iterator - vit = tr.finite_vertices_begin(); - vit != tr.finite_vertices_end(); - ++vit) - { - if (vit->in_dimension() == -1) - continue;//far point - CGAL_assertion(vit->in_dimension() >= 0 && vit->in_dimension() < 4); - - vertices_per_dimension[vit->in_dimension()].push_back(vit); - } - - for (int i = 0; i < 4; ++i) - { - //dimension is i - const std::vector& vertices_di = vertices_per_dimension[i]; - - std::cout << "Dimension " << i << " : " << vertices_di.size() << std::endl; - - std::ostringstream oss; - oss << prefix << "_dimension_" << i << ".off"; - - std::ofstream ofs(oss.str()); - ofs.precision(17); - ofs << "OFF" << std::endl; - ofs << vertices_di.size() << " 0 0" << std::endl << std::endl; - - for (Vertex_handle vj : vertices_di) - { - ofs << point(vj->point()) << std::endl; - } - - ofs.close(); - } + ofs << " " << (*iit) << std::endl; + ++iit; } + } + ofs << "End" << std::endl; + ofs.close(); +} - template - void dump_triangulation_cells(const Tr& tr, const char* filename) +template +void dump_cells(const CellRange& cells, const char* filename) +{ + std::vector indices; + dump_cells(cells, indices, filename); +} + +template +void dump_cells_in_complex(const Tr& tr, const char* filename) +{ + std::vector cells; + std::vector indices; + + for (typename Tr::Finite_cells_iterator cit = tr.finite_cells_begin(); + cit != tr.finite_cells_end(); ++cit) + { + if (cit->subdomain_index() > 0) { - std::vector cells(tr.number_of_finite_cells()); - std::vector indices(tr.number_of_finite_cells()); - int i = 0; - for (typename Tr::Finite_cells_iterator cit = tr.finite_cells_begin(); - cit != tr.finite_cells_end(); ++cit) - { - cells[i] = cit; - indices[i++] = cit->subdomain_index(); - } - dump_cells(cells, indices, filename); + cells.push_back(cit); + indices.push_back(cit->subdomain_index()); } + } + dump_cells(cells, indices, filename); +} - template - void dump_binary(const C3t3& c3t3, const char* filename) +template +void dump_facets_in_complex(const C3t3& c3t3, const char* filename) +{ + typedef typename C3t3::Triangulation Tr; + typedef typename Tr::Vertex_handle Vertex_handle; + typedef typename Tr::Cell_handle Cell_handle; + typedef typename C3t3::Facets_in_complex_iterator Facets_in_complex_iterator; + typedef boost::bimap Bimap_t; + typedef typename Bimap_t::left_map::value_type value_type; + + //collect vertices + Bimap_t vertices; + std::size_t nbf = 0; + int index = 0; + for (Facets_in_complex_iterator fit = c3t3.facets_in_complex_begin(); + fit != c3t3.facets_in_complex_end(); ++fit) + { + Cell_handle c = fit->first; + int i = fit->second; + + nbf++; + for (int j = 1; j < 4; ++j) { - std::ofstream os(filename, std::ios::binary | std::ios::out); - CGAL::Mesh_3::save_binary_file(os, c3t3); - os.close(); + Vertex_handle vij = c->vertex((i + j) % 4); + if (vertices.left.find(vij) == vertices.left.end()) + vertices.left.insert(value_type(vij, index++)); + } + } + + //write header + std::ofstream ofs(filename); + ofs.precision(17); + ofs << "OFF" << std::endl; + ofs << vertices.left.size() << " " << nbf << " 0" << std::endl << std::endl; + + // write vertices + for (typename Bimap_t::right_iterator vit = vertices.right.begin(); + vit != vertices.right.end(); ++vit) + { + ofs << point(vit->second->point()) << std::endl; + } + + //write facets + std::size_t nbf_print = 0; + for (Facets_in_complex_iterator fit = c3t3.facets_in_complex_begin(); + fit != c3t3.facets_in_complex_end(); ++fit) + { + Cell_handle c = fit->first; + int i = fit->second; + ofs << "3 " << vertices.left.at(c->vertex((i + 1) % 4)) << " " + << vertices.left.at(c->vertex((i + 2) % 4)) << " " + << vertices.left.at(c->vertex((i + 3) % 4)) << std::endl; + ++nbf_print; + } + CGAL_assertion(nbf == nbf_print); + + ofs.close(); +} + +template +void dump_edges_in_complex(const C3T3& c3t3, const char* filename) +{ + std::ofstream ofs(filename); + ofs.precision(17); + for (typename C3T3::Edges_in_complex_iterator eit = c3t3.edges_in_complex_begin(); + eit != c3t3.edges_in_complex_end(); ++eit) + { + const typename C3T3::Edge& e = *eit; + ofs << "2 " + << point(e.first->vertex(e.second)->point()) << " " + << point(e.first->vertex(e.third)->point()) << "\n"; + } + ofs.close(); +} + +template +void dump_cells_with_small_dihedral_angle(const Tr& tr, + const double angle_bound, + CellSelector cell_select, + const char* filename) +{ + typedef typename Tr::Cell_handle Cell_handle; + typedef typename Tr::Cell::Subdomain_index Subdomain_index; + std::vector cells; + std::vector indices; + + for (typename Tr::Finite_cells_iterator cit = tr.finite_cells_begin(); + cit != tr.finite_cells_end(); ++cit) + { + Cell_handle c = cit; + if ( c->subdomain_index() != Subdomain_index() + && cell_select(c) + && min_dihedral_angle(tr, c) < angle_bound) + { + + cells.push_back(c); + indices.push_back(c->subdomain_index()); + } + } + std::cout << "bad cells : " << cells.size() << std::endl; + dump_cells(cells, indices, filename); +} + +template +void dump_vertices_by_dimension(const Tr& tr, const char* prefix) +{ + typedef typename Tr::Vertex_handle Vertex_handle; + std::vector< std::vector > vertices_per_dimension(4); + + for (typename Tr::Finite_vertices_iterator + vit = tr.finite_vertices_begin(); + vit != tr.finite_vertices_end(); + ++vit) + { + if (vit->in_dimension() == -1) + continue;//far point + CGAL_assertion(vit->in_dimension() >= 0 && vit->in_dimension() < 4); + + vertices_per_dimension[vit->in_dimension()].push_back(vit); + } + + for (int i = 0; i < 4; ++i) + { + //dimension is i + const std::vector& vertices_di = vertices_per_dimension[i]; + + std::cout << "Dimension " << i << " : " << vertices_di.size() << std::endl; + + std::ostringstream oss; + oss << prefix << "_dimension_" << i << ".off"; + + std::ofstream ofs(oss.str()); + ofs.precision(17); + ofs << "OFF" << std::endl; + ofs << vertices_di.size() << " 0 0" << std::endl << std::endl; + + for (Vertex_handle vj : vertices_di) + { + ofs << point(vj->point()) << std::endl; } - //template - //void dump_edges(const VertexPairsSet& edges, const char* filename) - //{ - // std::ofstream ofs(filename); - // BOOST_FOREACH(typename VertexPairsSet::key_type vp, edges) - // { - // ofs << "2 " << vp.first->point() - // << " " << vp.second->point() << std::endl; - // } - // ofs.close(); - //} + ofs.close(); + } +} - } //namespace debug - } //namespace Tetrahedral_remeshing +template +void dump_triangulation_cells(const Tr& tr, const char* filename) +{ + std::vector cells(tr.number_of_finite_cells()); + std::vector indices(tr.number_of_finite_cells()); + int i = 0; + for (typename Tr::Finite_cells_iterator cit = tr.finite_cells_begin(); + cit != tr.finite_cells_end(); ++cit) + { + cells[i] = cit; + indices[i++] = cit->subdomain_index(); + } + dump_cells(cells, indices, filename); +} + +template +void dump_binary(const C3t3& c3t3, const char* filename) +{ + std::ofstream os(filename, std::ios::binary | std::ios::out); + CGAL::Mesh_3::save_binary_file(os, c3t3); + os.close(); +} + +//template +//void dump_edges(const VertexPairsSet& edges, const char* filename) +//{ +// std::ofstream ofs(filename); +// BOOST_FOREACH(typename VertexPairsSet::key_type vp, edges) +// { +// ofs << "2 " << vp.first->point() +// << " " << vp.second->point() << std::endl; +// } +// ofs.close(); +//} + +} //namespace debug +} //namespace Tetrahedral_remeshing } //namespace CGAL #endif //CGAL_INTERNAL_TET_REMESHING_HELPERS_H From e8295bee192982f867a47596fccdec86c1a5b414 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9bastien=20Loriot?= Date: Fri, 10 Apr 2020 10:12:12 +0200 Subject: [PATCH 234/568] more identation --- .../include/CGAL/tetrahedral_remeshing.h | 657 +++++++++--------- 1 file changed, 328 insertions(+), 329 deletions(-) diff --git a/Tetrahedral_remeshing/include/CGAL/tetrahedral_remeshing.h b/Tetrahedral_remeshing/include/CGAL/tetrahedral_remeshing.h index cd5324823f5..ccaeb8efc88 100644 --- a/Tetrahedral_remeshing/include/CGAL/tetrahedral_remeshing.h +++ b/Tetrahedral_remeshing/include/CGAL/tetrahedral_remeshing.h @@ -30,364 +30,363 @@ namespace CGAL { - /////////////////////////////////////////////////// - ///////////////// TRIANGULATION_3 ///////////////// - /////////////////////////////////////////////////// - /*! - * \ingroup PkgTetrahedralRemeshingRef - * remeshes a tetrahedral mesh. - * - * This function takes as input a 3-dimensional triangulation - * and performs a sequence of atomic operations - * in order to generate as output a high quality mesh with a prescribed density. - * These atomic operations are performed as follows : - * - edge splits, until all edges satisfy a prescribed length criterion, - * - edge collapses, until all edges satisfy a prescribed length criterion, - * - edge flips, to locally improve dihedral angles, until they can't be improved by flipping, - * - global smoothing by vertex relocations, - * - re-projection of boundary vertices to the initial surface. - * - * This remeshing function can deal with multi-domains, multi-material boundaries and features. - * It preserves the geometry of - * subdomains throughout the remeshing process. - * - * Subdomains are defined by indices that - * are stored in the cells of the input triangulation, following the `MeshCellBase_3` - * concept. - * The surfacic interfaces between subdomains are formed by facets which two incident cells - * have different subdomain indices. - * The edges where three or more subdomains meet form feature polylines, - * and are considered as constrained edges. - * - * - * @tparam Traits is the geometric traits, model of `RemeshingTriangulationTraits_3` - * @tparam TDS is the triangulation data structure for `Triangulation_3`, - * model of ` TriangulationDataStructure_3`, - * with cell base model of `MeshCellBase_3` - * and vertex base model of `MeshVertexBase_3`. - * @tparam SLDS is an optional parameter for `Triangulation_3`, that - * specifies the type of the spatial lock data structure. - * @tparam NamedParameters a sequence of \ref Remeshing_namedparameters "Named Parameters" - * - * @param tr the triangulation to the remeshed, of type `Triangulation_3`. - * `Remeshing_triangulation` is a helper class that satisfies all the requirements - * of its template parameters. - * @param target_edge_length the uniform target edge length. This parameter provides a - * mesh density target for the remeshing algorithm. - * @param np optional sequence of \ref Remeshing_namedparameters "Named Parameters" - * among the ones listed below - * \cgalNamedParamsBegin - * \cgalParamBegin{number_of_iterations} the number of iterations for the full - * sequence of atomic operations - * performed (listed in the above description) - * \cgalParamEnd - * \cgalParamBegin{remesh_boundaries} If `false`, none of the volume boundaries can be modified. - * Otherwise, the topology is preserved, but atomic operations can be performed on the - * surfaces, and along feature polylines, such that boundaries are remeshed. - * \cgalParamEnd - * \cgalParamBegin{edge_is_constrained_map} a property map containing the - * constrained - or - not status of each edge of `tr`. A constrained edge can be split - * or collapsed, but not flipped. - * \cgalParamEnd - * \cgalParamBegin{facet_is_constrained_map} a property map containing the - * constrained - or - not status of each facet of `tr`. A constrained facet can be split - * or collapsed, but not flipped. - * \cgalParamEnd - * \cgalParamBegin{cell_is_selected_map} a property map containing the - * selected - or - not status for each cell of `tr` for remeshing. - * Only selected cells are modified (and possibly their neighbors if surfaces are - * modified) by remeshing. - * By default, all cells with a non-zero `Subdomain_index` are selected. - * \cgalParamEnd - * \cgalNamedParamsEnd +/////////////////////////////////////////////////// +///////////////// TRIANGULATION_3 ///////////////// +/////////////////////////////////////////////////// +/*! +* \ingroup PkgTetrahedralRemeshingRef +* remeshes a tetrahedral mesh. +* +* This function takes as input a 3-dimensional triangulation +* and performs a sequence of atomic operations +* in order to generate as output a high quality mesh with a prescribed density. +* These atomic operations are performed as follows : +* - edge splits, until all edges satisfy a prescribed length criterion, +* - edge collapses, until all edges satisfy a prescribed length criterion, +* - edge flips, to locally improve dihedral angles, until they can't be improved by flipping, +* - global smoothing by vertex relocations, +* - re-projection of boundary vertices to the initial surface. +* +* This remeshing function can deal with multi-domains, multi-material boundaries and features. +* It preserves the geometry of +* subdomains throughout the remeshing process. +* +* Subdomains are defined by indices that +* are stored in the cells of the input triangulation, following the `MeshCellBase_3` +* concept. +* The surfacic interfaces between subdomains are formed by facets which two incident cells +* have different subdomain indices. +* The edges where three or more subdomains meet form feature polylines, +* and are considered as constrained edges. +* +* +* @tparam Traits is the geometric traits, model of `RemeshingTriangulationTraits_3` +* @tparam TDS is the triangulation data structure for `Triangulation_3`, +* model of ` TriangulationDataStructure_3`, +* with cell base model of `MeshCellBase_3` +* and vertex base model of `MeshVertexBase_3`. +* @tparam SLDS is an optional parameter for `Triangulation_3`, that +* specifies the type of the spatial lock data structure. +* @tparam NamedParameters a sequence of \ref Remeshing_namedparameters "Named Parameters" +* +* @param tr the triangulation to the remeshed, of type `Triangulation_3`. +* `Remeshing_triangulation` is a helper class that satisfies all the requirements +* of its template parameters. +* @param target_edge_length the uniform target edge length. This parameter provides a +* mesh density target for the remeshing algorithm. +* @param np optional sequence of \ref Remeshing_namedparameters "Named Parameters" +* among the ones listed below +* \cgalNamedParamsBegin +* \cgalParamBegin{number_of_iterations} the number of iterations for the full +* sequence of atomic operations +* performed (listed in the above description) +* \cgalParamEnd +* \cgalParamBegin{remesh_boundaries} If `false`, none of the volume boundaries can be modified. +* Otherwise, the topology is preserved, but atomic operations can be performed on the +* surfaces, and along feature polylines, such that boundaries are remeshed. +* \cgalParamEnd +* \cgalParamBegin{edge_is_constrained_map} a property map containing the +* constrained - or - not status of each edge of `tr`. A constrained edge can be split +* or collapsed, but not flipped. +* \cgalParamEnd +* \cgalParamBegin{facet_is_constrained_map} a property map containing the +* constrained - or - not status of each facet of `tr`. A constrained facet can be split +* or collapsed, but not flipped. +* \cgalParamEnd +* \cgalParamBegin{cell_is_selected_map} a property map containing the +* selected - or - not status for each cell of `tr` for remeshing. +* Only selected cells are modified (and possibly their neighbors if surfaces are +* modified) by remeshing. +* By default, all cells with a non-zero `Subdomain_index` are selected. +* \cgalParamEnd +* \cgalNamedParamsEnd - * @todo implement 1D smoothing for constrained edges - * @todo implement sizing field instead of uniform target edge length - */ - template - void tetrahedral_adaptive_remeshing( - CGAL::Triangulation_3& tr, +* @todo implement 1D smoothing for constrained edges +* @todo implement sizing field instead of uniform target edge length +*/ +template +void tetrahedral_adaptive_remeshing( + CGAL::Triangulation_3& tr, + const double& target_edge_length, + const NamedParameters& np) +{ + typedef CGAL::Triangulation_3 Triangulation; + tetrahedral_adaptive_remeshing( + tr, + [target_edge_length](const typename Triangulation::Point& /* p */) + {return target_edge_length;}, + np); +} + +template +void tetrahedral_adaptive_remeshing( + CGAL::Triangulation_3& tr, + const float& target_edge_length, + const NamedParameters& np) +{ + typedef CGAL::Triangulation_3 Triangulation; + tetrahedral_adaptive_remeshing( + tr, + [target_edge_length](const typename Triangulation::Point& /* p */) + {return target_edge_length; }, + np); +} + +template +void tetrahedral_adaptive_remeshing( + CGAL::Triangulation_3& tr, + const SizingFunction& sizing, + const NamedParameters& np) +{ + CGAL_assertion(tr.is_valid(true)); + + typedef CGAL::Triangulation_3 Tr; + + using parameters::choose_parameter; + using parameters::get_parameter; + + bool remesh_surfaces = choose_parameter(get_parameter(np, internal_np::remesh_boundaries), + true); + bool protect = !remesh_surfaces; + // bool adaptive = choose_parameter(get_parameter(np, internal_np::adaptive_size), + // false); + std::size_t max_it = choose_parameter(get_parameter(np, internal_np::number_of_iterations), + 1); + + typedef typename internal_np::Lookup_named_param_def < + internal_np::cell_selector_t, + NamedParameters, + Tetrahedral_remeshing::internal::All_cells_selected//default + > ::type SelectionFunctor; + SelectionFunctor cell_select + = choose_parameter(get_parameter(np, internal_np::cell_selector), + Tetrahedral_remeshing::internal::All_cells_selected()); + + typedef std::pair Edge_vv; + typedef Tetrahedral_remeshing::internal::No_constraint_pmap No_edge; + typedef typename internal_np::Lookup_named_param_def < + internal_np::edge_is_constrained_t, + NamedParameters, + No_edge//default + > ::type ECMap; + ECMap ecmap = choose_parameter(get_parameter(np, internal_np::edge_is_constrained), + No_edge()); + + typedef typename Tr::Facet Facet; + typedef Tetrahedral_remeshing::internal::No_constraint_pmap No_facet; + typedef typename internal_np::Lookup_named_param_def < + internal_np::facet_is_constrained_t, + NamedParameters, + No_facet//default + > ::type FCMap; + FCMap fcmap = choose_parameter(get_parameter(np, internal_np::facet_is_constrained), + No_facet()); + + typedef typename internal_np::Lookup_named_param_def < + internal_np::remeshing_visitor_t, + NamedParameters, + Tetrahedral_remeshing::internal::Default_remeshing_visitor + > ::type Visitor; + Visitor visitor + = choose_parameter(get_parameter(np, internal_np::remeshing_visitor), + Tetrahedral_remeshing::internal::Default_remeshing_visitor()); + +#ifdef CGAL_TETRAHEDRAL_REMESHING_VERBOSE + std::cout << "Tetrahedral remeshing (" + << "nb_iter = " << max_it << ", " + << "protect = " << std::boolalpha << protect + << ")" << std::endl; + + std::cout << "Init tetrahedral remeshing..."; + std::cout.flush(); +#endif + + typedef Tetrahedral_remeshing::internal::Adaptive_remesher< + Tr, SizingFunction, ECMap, FCMap, SelectionFunctor, Visitor> Remesher; + Remesher remesher(tr, sizing, protect + , ecmap, fcmap + , cell_select + , visitor); + +#ifdef CGAL_TETRAHEDRAL_REMESHING_VERBOSE + std::cout << "done." << std::endl; + Tetrahedral_remeshing::internal::compute_statistics( + remesher.tr(), cell_select, "statistics_begin.txt"); +#endif + + // perform remeshing + std::size_t nb_extra_iterations = 3; + remesher.remesh(max_it, nb_extra_iterations); + +#ifdef CGAL_TETRAHEDRAL_REMESHING_DEBUG + const double angle_bound = 5.0; + Tetrahedral_remeshing::debug::dump_cells_with_small_dihedral_angle(tr, + angle_bound, cell_select, "bad_cells.mesh"); +#endif +#ifdef CGAL_TETRAHEDRAL_REMESHING_VERBOSE + Tetrahedral_remeshing::internal::compute_statistics(tr, + cell_select, "statistics_end.txt"); +#endif +} + +template +void tetrahedral_adaptive_remeshing( + CGAL::Triangulation_3& tr, + const double& target_edge_length) +{ + tetrahedral_adaptive_remeshing(tr, target_edge_length, + CGAL::parameters::all_default()); +} + +/////////////////////////////////////////////////// +/////// MESH_COMPLEX_3_IN_TRIANGULATION_3 ///////// +/////////////////////////////////////////////////// + +template +void tetrahedral_adaptive_remeshing( + CGAL::Mesh_complex_3_in_triangulation_3& c3t3, const double& target_edge_length, const NamedParameters& np) - { - typedef CGAL::Triangulation_3 Triangulation; - tetrahedral_adaptive_remeshing( - tr, - [target_edge_length](const typename Triangulation::Point& /* p */) - {return target_edge_length;}, - np); - } +{ + tetrahedral_adaptive_remeshing( + c3t3, + [target_edge_length](const typename Tr::Point& p) + {return target_edge_length; }, + np); +} - template - void tetrahedral_adaptive_remeshing( - CGAL::Triangulation_3& tr, +template +void tetrahedral_adaptive_remeshing( + CGAL::Mesh_complex_3_in_triangulation_3& c3t3, const float& target_edge_length, const NamedParameters& np) - { - typedef CGAL::Triangulation_3 Triangulation; - tetrahedral_adaptive_remeshing( - tr, - [target_edge_length](const typename Triangulation::Point& /* p */) - {return target_edge_length; }, - np); - } +{ + tetrahedral_adaptive_remeshing( + c3t3, + [target_edge_length](const typename Tr::Point& p) + {return target_edge_length; }, + np); +} - template - void tetrahedral_adaptive_remeshing( - CGAL::Triangulation_3& tr, +template +void tetrahedral_adaptive_remeshing( + CGAL::Mesh_complex_3_in_triangulation_3& c3t3, + const double& target_edge_length) +{ + return tetrahedral_adaptive_remeshing(c3t3, target_edge_length, + CGAL::parameters::all_default()); +} + +template +void tetrahedral_adaptive_remeshing( + CGAL::Mesh_complex_3_in_triangulation_3& c3t3, const SizingFunction& sizing, const NamedParameters& np) - { - CGAL_assertion(tr.is_valid(true)); +{ + CGAL_assertion(c3t3.triangulation().tds().is_valid(true)); - typedef CGAL::Triangulation_3 Tr; + using parameters::get_parameter; + using parameters::choose_parameter; - using parameters::choose_parameter; - using parameters::get_parameter; + bool remesh_surfaces = choose_parameter(get_parameter(np, internal_np::remesh_boundaries), + true); + bool protect = !remesh_surfaces; + std::size_t max_it = choose_parameter(get_parameter(np, internal_np::number_of_iterations), 1); - bool remesh_surfaces = choose_parameter(get_parameter(np, internal_np::remesh_boundaries), - true); - bool protect = !remesh_surfaces; - // bool adaptive = choose_parameter(get_parameter(np, internal_np::adaptive_size), - // false); - std::size_t max_it = choose_parameter(get_parameter(np, internal_np::number_of_iterations), - 1); + typedef typename internal_np::Lookup_named_param_def < + internal_np::cell_selector_t, + NamedParameters, + Tetrahedral_remeshing::internal::All_cells_selected//default + > ::type SelectionFunctor; + SelectionFunctor cell_select + = choose_parameter(get_parameter(np, internal_np::cell_selector), + Tetrahedral_remeshing::internal::All_cells_selected()); - typedef typename internal_np::Lookup_named_param_def < - internal_np::cell_selector_t, - NamedParameters, - Tetrahedral_remeshing::internal::All_cells_selected//default - > ::type SelectionFunctor; - SelectionFunctor cell_select - = choose_parameter(get_parameter(np, internal_np::cell_selector), - Tetrahedral_remeshing::internal::All_cells_selected()); + typedef std::pair Edge_vv; + typedef Tetrahedral_remeshing::internal::No_constraint_pmap No_edge; + typedef typename internal_np::Lookup_named_param_def < + internal_np::edge_is_constrained_t, + NamedParameters, + No_edge//default + > ::type ECMap; + ECMap ecmap = choose_parameter(get_parameter(np, internal_np::edge_is_constrained), + No_edge()); - typedef std::pair Edge_vv; - typedef Tetrahedral_remeshing::internal::No_constraint_pmap No_edge; - typedef typename internal_np::Lookup_named_param_def < - internal_np::edge_is_constrained_t, - NamedParameters, - No_edge//default - > ::type ECMap; - ECMap ecmap = choose_parameter(get_parameter(np, internal_np::edge_is_constrained), - No_edge()); + typedef typename Tr::Facet Facet; + typedef Tetrahedral_remeshing::internal::No_constraint_pmap No_facet; + typedef typename internal_np::Lookup_named_param_def < + internal_np::facet_is_constrained_t, + NamedParameters, + No_facet//default + > ::type FCMap; + FCMap fcmap = choose_parameter(get_parameter(np, internal_np::facet_is_constrained), + No_facet()); - typedef typename Tr::Facet Facet; - typedef Tetrahedral_remeshing::internal::No_constraint_pmap No_facet; - typedef typename internal_np::Lookup_named_param_def < - internal_np::facet_is_constrained_t, - NamedParameters, - No_facet//default - > ::type FCMap; - FCMap fcmap = choose_parameter(get_parameter(np, internal_np::facet_is_constrained), - No_facet()); - - typedef typename internal_np::Lookup_named_param_def < - internal_np::remeshing_visitor_t, - NamedParameters, - Tetrahedral_remeshing::internal::Default_remeshing_visitor - > ::type Visitor; - Visitor visitor - = choose_parameter(get_parameter(np, internal_np::remeshing_visitor), - Tetrahedral_remeshing::internal::Default_remeshing_visitor()); + typedef typename internal_np::Lookup_named_param_def < + internal_np::remeshing_visitor_t, + NamedParameters, + Tetrahedral_remeshing::internal::Default_remeshing_visitor + > ::type Visitor; + Visitor visitor + = choose_parameter(get_parameter(np, internal_np::remeshing_visitor), + Tetrahedral_remeshing::internal::Default_remeshing_visitor()); #ifdef CGAL_TETRAHEDRAL_REMESHING_VERBOSE - std::cout << "Tetrahedral remeshing (" - << "nb_iter = " << max_it << ", " - << "protect = " << std::boolalpha << protect - << ")" << std::endl; + std::cout << "Tetrahedral remeshing (" + << "nb_iter = " << max_it << ", " + << "protect = " << std::boolalpha << protect + << ")" << std::endl; - std::cout << "Init tetrahedral remeshing..."; - std::cout.flush(); + std::cout << "Init tetrahedral remeshing..."; + std::cout.flush(); #endif - typedef Tetrahedral_remeshing::internal::Adaptive_remesher< - Tr, SizingFunction, ECMap, FCMap, SelectionFunctor, Visitor> Remesher; - Remesher remesher(tr, sizing, protect - , ecmap, fcmap - , cell_select - , visitor); + typedef Tetrahedral_remeshing::internal::Adaptive_remesher< + Tr, SizingFunction, ECMap, FCMap, SelectionFunctor, + Visitor, + CornerIndex, CurveIndex + > Remesher; + Remesher remesher(c3t3, sizing, protect + , ecmap, fcmap + , cell_select + , visitor); #ifdef CGAL_TETRAHEDRAL_REMESHING_VERBOSE - std::cout << "done." << std::endl; - Tetrahedral_remeshing::internal::compute_statistics( - remesher.tr(), cell_select, "statistics_begin.txt"); + std::cout << "done." << std::endl; + Tetrahedral_remeshing::internal::compute_statistics( + remesher.tr(), + cell_select, "statistics_begin.txt"); #endif - // perform remeshing - std::size_t nb_extra_iterations = 3; - remesher.remesh(max_it, nb_extra_iterations); + // perform remeshing + std::size_t nb_extra_iterations = 3; + remesher.remesh(max_it, nb_extra_iterations); #ifdef CGAL_TETRAHEDRAL_REMESHING_DEBUG - const double angle_bound = 5.0; - Tetrahedral_remeshing::debug::dump_cells_with_small_dihedral_angle(tr, - angle_bound, cell_select, "bad_cells.mesh"); + const double angle_bound = 5.0; + Tetrahedral_remeshing::debug::dump_cells_with_small_dihedral_angle( + c3t3.triangulation(), + angle_bound, cell_select, "bad_cells.mesh"); #endif #ifdef CGAL_TETRAHEDRAL_REMESHING_VERBOSE - Tetrahedral_remeshing::internal::compute_statistics(tr, - cell_select, "statistics_end.txt"); + Tetrahedral_remeshing::internal::compute_statistics( + c3t3.triangulation(), + cell_select, "statistics_end.txt"); #endif - } - - template - void tetrahedral_adaptive_remeshing( - CGAL::Triangulation_3& tr, - const double& target_edge_length) - { - tetrahedral_adaptive_remeshing(tr, target_edge_length, - CGAL::parameters::all_default()); - } - - /////////////////////////////////////////////////// - /////// MESH_COMPLEX_3_IN_TRIANGULATION_3 ///////// - /////////////////////////////////////////////////// - - template - void tetrahedral_adaptive_remeshing( - CGAL::Mesh_complex_3_in_triangulation_3& c3t3, - const double& target_edge_length, - const NamedParameters& np) - { - tetrahedral_adaptive_remeshing( - c3t3, - [target_edge_length](const typename Tr::Point& p) - {return target_edge_length; }, - np); - } - - template - void tetrahedral_adaptive_remeshing( - CGAL::Mesh_complex_3_in_triangulation_3& c3t3, - const float& target_edge_length, - const NamedParameters& np) - { - tetrahedral_adaptive_remeshing( - c3t3, - [target_edge_length](const typename Tr::Point& p) - {return target_edge_length; }, - np); - } - - template - void tetrahedral_adaptive_remeshing( - CGAL::Mesh_complex_3_in_triangulation_3& c3t3, - const double& target_edge_length) - { - return tetrahedral_adaptive_remeshing(c3t3, target_edge_length, - CGAL::parameters::all_default()); - } - - template - void tetrahedral_adaptive_remeshing( - CGAL::Mesh_complex_3_in_triangulation_3& c3t3, - const SizingFunction& sizing, - const NamedParameters& np) - { - CGAL_assertion(c3t3.triangulation().tds().is_valid(true)); - - using parameters::get_parameter; - using parameters::choose_parameter; - - bool remesh_surfaces = choose_parameter(get_parameter(np, internal_np::remesh_boundaries), - true); - bool protect = !remesh_surfaces; - std::size_t max_it = choose_parameter(get_parameter(np, internal_np::number_of_iterations), 1); - - typedef typename internal_np::Lookup_named_param_def < - internal_np::cell_selector_t, - NamedParameters, - Tetrahedral_remeshing::internal::All_cells_selected//default - > ::type SelectionFunctor; - SelectionFunctor cell_select - = choose_parameter(get_parameter(np, internal_np::cell_selector), - Tetrahedral_remeshing::internal::All_cells_selected()); - - typedef std::pair Edge_vv; - typedef Tetrahedral_remeshing::internal::No_constraint_pmap No_edge; - typedef typename internal_np::Lookup_named_param_def < - internal_np::edge_is_constrained_t, - NamedParameters, - No_edge//default - > ::type ECMap; - ECMap ecmap = choose_parameter(get_parameter(np, internal_np::edge_is_constrained), - No_edge()); - - typedef typename Tr::Facet Facet; - typedef Tetrahedral_remeshing::internal::No_constraint_pmap No_facet; - typedef typename internal_np::Lookup_named_param_def < - internal_np::facet_is_constrained_t, - NamedParameters, - No_facet//default - > ::type FCMap; - FCMap fcmap = choose_parameter(get_parameter(np, internal_np::facet_is_constrained), - No_facet()); - - typedef typename internal_np::Lookup_named_param_def < - internal_np::remeshing_visitor_t, - NamedParameters, - Tetrahedral_remeshing::internal::Default_remeshing_visitor - > ::type Visitor; - Visitor visitor - = choose_parameter(get_parameter(np, internal_np::remeshing_visitor), - Tetrahedral_remeshing::internal::Default_remeshing_visitor()); - -#ifdef CGAL_TETRAHEDRAL_REMESHING_VERBOSE - std::cout << "Tetrahedral remeshing (" - << "nb_iter = " << max_it << ", " - << "protect = " << std::boolalpha << protect - << ")" << std::endl; - - std::cout << "Init tetrahedral remeshing..."; - std::cout.flush(); -#endif - - typedef Tetrahedral_remeshing::internal::Adaptive_remesher< - Tr, SizingFunction, ECMap, FCMap, SelectionFunctor, - Visitor, - CornerIndex, CurveIndex - > Remesher; - Remesher remesher(c3t3, sizing, protect - , ecmap, fcmap - , cell_select - , visitor); - -#ifdef CGAL_TETRAHEDRAL_REMESHING_VERBOSE - std::cout << "done." << std::endl; - Tetrahedral_remeshing::internal::compute_statistics( - remesher.tr(), - cell_select, "statistics_begin.txt"); -#endif - - // perform remeshing - std::size_t nb_extra_iterations = 3; - remesher.remesh(max_it, nb_extra_iterations); - -#ifdef CGAL_TETRAHEDRAL_REMESHING_DEBUG - const double angle_bound = 5.0; - Tetrahedral_remeshing::debug::dump_cells_with_small_dihedral_angle( - c3t3.triangulation(), - angle_bound, cell_select, "bad_cells.mesh"); -#endif -#ifdef CGAL_TETRAHEDRAL_REMESHING_VERBOSE - Tetrahedral_remeshing::internal::compute_statistics( - c3t3.triangulation(), - cell_select, "statistics_end.txt"); -#endif - } - +} }//end namespace CGAL From c929edcfd6530e55c35727af74cea55ba5ad6e5b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9bastien=20Loriot?= Date: Fri, 10 Apr 2020 10:24:40 +0200 Subject: [PATCH 235/568] more identation using astyle -s2 --- .../Remeshing_cell_base.h | 18 +- .../Remeshing_triangulation_3.h | 102 +- .../Tetrahedral_remeshing/internal/FMLS.h | 28 +- .../internal/collapse_short_edges.h | 60 +- .../internal/compute_c3t3_statistics.h | 14 +- .../internal/flip_edges.h | 116 +-- .../internal/smooth_vertices.h | 986 +++++++++--------- .../internal/split_long_edges.h | 24 +- .../tetrahedral_adaptive_remeshing_impl.h | 70 +- .../internal/tetrahedral_remeshing_helpers.h | 180 ++-- .../include/CGAL/tetrahedral_remeshing.h | 102 +- 11 files changed, 850 insertions(+), 850 deletions(-) diff --git a/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/Remeshing_cell_base.h b/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/Remeshing_cell_base.h index 7f67a4cb3b2..5e2b2b88a77 100644 --- a/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/Remeshing_cell_base.h +++ b/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/Remeshing_cell_base.h @@ -21,12 +21,12 @@ namespace Tetrahedral_remeshing { namespace internal { - struct Fake_MD_C - { - typedef int Subdomain_index; - typedef int Surface_patch_index; - typedef int Index; - }; +struct Fake_MD_C +{ + typedef int Subdomain_index; + typedef int Surface_patch_index; + typedef int Index; +}; } /*! @@ -77,13 +77,13 @@ public: return this->subdomain_index() != this->neighbor(facet)->subdomain_index(); } #endif - }; +}; template < class Gt, class Cb > std::istream& - operator>>(std::istream &is, Remeshing_cell_base &c) +operator>>(std::istream &is, Remeshing_cell_base &c) { typename Remeshing_cell_base::Subdomain_index index; if (is_ascii(is)) @@ -109,7 +109,7 @@ std::istream& template < class Gt, class Cb > std::ostream& - operator<<(std::ostream &os, const Remeshing_cell_base &c) +operator<<(std::ostream &os, const Remeshing_cell_base &c) { if (is_ascii(os)) os << c.subdomain_index(); diff --git a/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/Remeshing_triangulation_3.h b/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/Remeshing_triangulation_3.h index 2c886cdafbc..8cccebf078f 100644 --- a/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/Remeshing_triangulation_3.h +++ b/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/Remeshing_triangulation_3.h @@ -82,63 +82,63 @@ public: namespace internal { - template - struct Vertex_converter +template +struct Vertex_converter +{ + //This operator is used to create the vertex from v_src. + typename TDS_tgt::Vertex operator()(const typename TDS_src::Vertex& v_src) const { - //This operator is used to create the vertex from v_src. - typename TDS_tgt::Vertex operator()(const typename TDS_src::Vertex& v_src) const - { - typedef typename CGAL::Kernel_traits< - typename TDS_src::Vertex::Point>::Kernel GT_src; - typedef typename CGAL::Kernel_traits< - typename TDS_tgt::Vertex::Point>::Kernel GT_tgt; - CGAL::Cartesian_converter conv; + typedef typename CGAL::Kernel_traits< + typename TDS_src::Vertex::Point>::Kernel GT_src; + typedef typename CGAL::Kernel_traits< + typename TDS_tgt::Vertex::Point>::Kernel GT_tgt; + CGAL::Cartesian_converter conv; - typedef typename TDS_tgt::Vertex::Point Tgt_point; + typedef typename TDS_tgt::Vertex::Point Tgt_point; - typename TDS_tgt::Vertex v_tgt; - v_tgt.set_point(Tgt_point(conv(point(v_src.point())))); - v_tgt.set_time_stamp(-1); - v_tgt.set_dimension(3);//-1 if unset, 0,1,2, or 3 if set - return v_tgt; - } - //This operator is meant to be used in case heavy data should transferred to v_tgt. - void operator()(const typename TDS_src::Vertex& v_src, - typename TDS_tgt::Vertex& v_tgt) const - { - typedef typename CGAL::Kernel_traits< - typename TDS_src::Vertex::Point>::Kernel GT_src; - typedef typename CGAL::Kernel_traits< - typename TDS_tgt::Vertex::Point>::Kernel GT_tgt; - CGAL::Cartesian_converter conv; - - typedef typename TDS_tgt::Vertex::Point Tgt_point; - - v_tgt.set_point(Tgt_point(conv(point(v_src.point())))); - v_tgt.set_dimension(3);//v_src.info()); - } - }; - - template - struct Cell_converter + typename TDS_tgt::Vertex v_tgt; + v_tgt.set_point(Tgt_point(conv(point(v_src.point())))); + v_tgt.set_time_stamp(-1); + v_tgt.set_dimension(3);//-1 if unset, 0,1,2, or 3 if set + return v_tgt; + } + //This operator is meant to be used in case heavy data should transferred to v_tgt. + void operator()(const typename TDS_src::Vertex& v_src, + typename TDS_tgt::Vertex& v_tgt) const { - //This operator is used to create the cell from c_src. - typename TDS_tgt::Cell operator()(const typename TDS_src::Cell& c_src) const - { - typename TDS_tgt::Cell c_tgt; - c_tgt.set_subdomain_index(1);//c_src.subdomain_index()); + typedef typename CGAL::Kernel_traits< + typename TDS_src::Vertex::Point>::Kernel GT_src; + typedef typename CGAL::Kernel_traits< + typename TDS_tgt::Vertex::Point>::Kernel GT_tgt; + CGAL::Cartesian_converter conv; + + typedef typename TDS_tgt::Vertex::Point Tgt_point; + + v_tgt.set_point(Tgt_point(conv(point(v_src.point())))); + v_tgt.set_dimension(3);//v_src.info()); + } +}; + +template +struct Cell_converter +{ + //This operator is used to create the cell from c_src. + typename TDS_tgt::Cell operator()(const typename TDS_src::Cell& c_src) const + { + typename TDS_tgt::Cell c_tgt; + c_tgt.set_subdomain_index(1);//c_src.subdomain_index()); // c_tgt.info() = c_src.info(); - c_tgt.set_time_stamp(-1); - return c_tgt; - } - //This operator is meant to be used in case heavy data should transferred to c_tgt. - void operator()(const typename TDS_src::Cell& c_src, - typename TDS_tgt::Cell& c_tgt) const - { + c_tgt.set_time_stamp(-1); + return c_tgt; + } + //This operator is meant to be used in case heavy data should transferred to c_tgt. + void operator()(const typename TDS_src::Cell& c_src, + typename TDS_tgt::Cell& c_tgt) const + { // c_tgt.set_subdomain_index(c_src.subdomain_index()); - // c_tgt.info() = c_src.info(); - } - }; + // c_tgt.info() = c_src.info(); + } +}; } diff --git a/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/FMLS.h b/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/FMLS.h index f5c75f3ca00..4d7152877fa 100644 --- a/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/FMLS.h +++ b/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/FMLS.h @@ -226,7 +226,7 @@ public: // is compact: pv={x0,y0,z0,x1,y1,z1...}. If pv contains also normals for instance, // the stride should be set to 6. void fastProjectionCPU(const std::vector& pv, unsigned int pvSize, - std::vector& qv, unsigned int stride = 3) const + std::vector& qv, unsigned int stride = 3) const { for (int i = 0; i < int(pvSize); i++) { Vector_3 p(pv[stride * i], pv[stride * i + 1], pv[stride * i + 2]); @@ -266,9 +266,9 @@ public: } // Brute force version. O(pvSize*PNSize) complexity. For comparison only. void projectionCPU(const std::vector& pv, - unsigned int pvSize, - std::vector& qv, - unsigned int stride = 3) + unsigned int pvSize, + std::vector& qv, + unsigned int stride = 3) { for (int i = 0; i < int(pvSize); i++) { Vector_3 p(pv[stride * i], pv[stride * i + 1], pv[stride * i + 2]); @@ -459,8 +459,8 @@ private: p[j] = res[j] - 1; } unsigned index = ((unsigned int)floor(p[2])) * res[0] * res[1] - + ((unsigned int)floor(p[1])) * res[0] - + ((unsigned int)floor(p[0])); + + ((unsigned int)floor(p[1])) * res[0] + + ((unsigned int)floor(p[0])); return index; } inline unsigned int getLUTElement(const Vector_3& x) const { @@ -470,14 +470,14 @@ private: inline const std::vector& getIndices() const { return indices; } inline unsigned int getIndicesSize() const { return indicesSize; } inline unsigned int getCellIndicesSize(unsigned int i, - unsigned int j, - unsigned int k) const { + unsigned int j, + unsigned int k) const { return indices[getLUTElement(i, j, k)]; } inline unsigned int getIndicesElement(unsigned int i, - unsigned int j, - unsigned int k, - unsigned int e) const { + unsigned int j, + unsigned int k, + unsigned int e) const { return indices[getLUTElement(i, j, k) + 1 + e]; } @@ -647,8 +647,8 @@ void createMLSSurfaces(Subdomain__FMLS& subdomain_FMLS, Vertex_handle vh1 = edge.first->vertex(edge.third); Edge_vv e = make_vertex_pair(vh0, vh1); if ( vertices_surface_indices.find(vh0) != vertices_surface_indices.end() - && vertices_surface_indices.find(vh1) != vertices_surface_indices.end() - && edgeMap.find(e) == edgeMap.end()) + && vertices_surface_indices.find(vh1) != vertices_surface_indices.end() + && edgeMap.find(e) == edgeMap.end()) { edgeMap.insert(e); @@ -656,7 +656,7 @@ void createMLSSurfaces(Subdomain__FMLS& subdomain_FMLS, const int fmls_id = current_subdomain_FMLS_indices[surf_i]; point_spacing[fmls_id] += CGAL::approximate_sqrt( - CGAL::squared_distance(point(vh0->point()), point(vh1->point()))); + CGAL::squared_distance(point(vh0->point()), point(vh1->point()))); point_spacing_count[fmls_id] ++; } } diff --git a/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/collapse_short_edges.h b/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/collapse_short_edges.h index 7718c7b2962..4732d6759a1 100644 --- a/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/collapse_short_edges.h +++ b/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/collapse_short_edges.h @@ -65,10 +65,10 @@ public: std::vector vertices_to_insert; c3t3.triangulation().finite_incident_vertices(v0_init, - std::back_inserter(vertices_to_insert)); + std::back_inserter(vertices_to_insert)); vertices_to_insert.push_back(v0_init); c3t3.triangulation().finite_incident_vertices(v1_init, - std::back_inserter(vertices_to_insert)); + std::back_inserter(vertices_to_insert)); // create incremental builder Builder builder(triangulation, true); @@ -204,12 +204,12 @@ public: return TOPOLOGICAL_PROBLEM; if ( triangulation.is_infinite(n0_ch->vertex(ch_id_in_n0)) - && triangulation.is_infinite(n1_ch->vertex(ch_id_in_n1))) + && triangulation.is_infinite(n1_ch->vertex(ch_id_in_n1))) return TOPOLOGICAL_PROBLEM; if ( triangulation.is_infinite(n0_ch) - && triangulation.is_infinite(n1_ch) - && !triangulation.is_infinite(circ)) + && triangulation.is_infinite(n1_ch) + && !triangulation.is_infinite(circ)) return TOPOLOGICAL_PROBLEM; cells_to_remove.push_back(circ); @@ -302,7 +302,7 @@ public: //if( is_valid_for_domains() ) return VALID; - // return TOPOLOGICAL_PROBLEM; + // return TOPOLOGICAL_PROBLEM; } } @@ -423,8 +423,8 @@ bool is_valid_collapse(const typename C3t3::Edge& edge, Cell_handle n1_ch = circ->neighbor(v1_id); if (n0_ch->has_vertex(v0) - || n1_ch->has_vertex(v1) - || n0_ch->has_neighbor(n1_ch)) + || n1_ch->has_vertex(v1) + || n0_ch->has_neighbor(n1_ch)) { #ifdef CGAL_DEBUG_TET_REMESHING_IN_PLUGIN if (c3t3.is_in_complex(edge)) @@ -468,7 +468,7 @@ bool is_valid_collapse(const typename C3t3::Edge& edge, { std::vector cells_to_check; c3t3.triangulation().finite_incident_cells(v0, - std::back_inserter(cells_to_check)); + std::back_inserter(cells_to_check)); for (const Cell_handle ch : cells_to_check) { @@ -501,7 +501,7 @@ bool is_valid_collapse(const typename C3t3::Edge& edge, { std::vector cells_to_check; c3t3.triangulation().finite_incident_cells(v1, - std::back_inserter(cells_to_check)); + std::back_inserter(cells_to_check)); for (const Cell_handle ch : cells_to_check) { @@ -555,9 +555,9 @@ bool are_edge_lengths_valid(const typename C3t3::Edge& edge, std::vector inc_edges; c3t3.triangulation().finite_incident_edges(v1, - std::back_inserter(inc_edges)); + std::back_inserter(inc_edges)); c3t3.triangulation().finite_incident_edges(v2, - std::back_inserter(inc_edges)); + std::back_inserter(inc_edges)); for (const Edge& ei : inc_edges) { @@ -702,7 +702,7 @@ collapse(const typename C3t3::Cell_handle ch, } if ( tr.is_infinite(n0_ch->vertex(ch_id_in_n0)) - && tr.is_infinite(n1_ch->vertex(ch_id_in_n1))) + && tr.is_infinite(n1_ch->vertex(ch_id_in_n1))) return Vertex_handle(); cells_to_remove.push_back(circ); @@ -854,11 +854,11 @@ typename C3t3::Vertex_handle collapse(typename C3t3::Edge& edge, template typename C3t3::Vertex_handle collapse_edge(typename C3t3::Edge& edge, - C3t3& c3t3, - const typename C3t3::Triangulation::Geom_traits::FT& sqhigh, - const bool /* protect_boundaries */, - CellSelector cell_selector, - Visitor& visitor) + C3t3& c3t3, + const typename C3t3::Triangulation::Geom_traits::FT& sqhigh, + const bool /* protect_boundaries */, + CellSelector cell_selector, + Visitor& visitor) { typedef typename C3t3::Triangulation Tr; typedef typename Tr::Point Point; @@ -985,11 +985,11 @@ bool can_be_collapsed(const typename C3T3::Edge& e, template void collapse_short_edges(C3T3& c3t3, - const typename C3T3::Triangulation::Geom_traits::FT& low, - const typename C3T3::Triangulation::Geom_traits::FT& high, - const bool protect_boundaries, - CellSelector cell_selector, - Visitor& visitor) + const typename C3T3::Triangulation::Geom_traits::FT& low, + const typename C3T3::Triangulation::Geom_traits::FT& high, + const bool protect_boundaries, + CellSelector cell_selector, + Visitor& visitor) { typedef typename C3T3::Triangulation T3; typedef typename T3::Cell_handle Cell_handle; @@ -1001,8 +1001,8 @@ void collapse_short_edges(C3T3& c3t3, typedef typename T3::Geom_traits Gt; typedef typename T3::Geom_traits::FT FT; typedef boost::bimap< - boost::bimaps::set_of, - boost::bimaps::multiset_of > > Boost_bimap; + boost::bimaps::set_of, + boost::bimaps::multiset_of > > Boost_bimap; typedef typename Boost_bimap::value_type short_edge; T3& tr = c3t3.triangulation(); @@ -1056,9 +1056,9 @@ void collapse_short_edges(C3T3& c3t3, Cell_handle cell; int i1, i2; if ( tr.tds().is_vertex(e.first) - && tr.tds().is_vertex(e.second) - && tr.tds().is_edge(e.first, e.second, cell, i1, i2) - && tr.segment(Edge(cell, i1, i2)).squared_length() < sq_low) + && tr.tds().is_vertex(e.second) + && tr.tds().is_edge(e.first, e.second, cell, i1, i2) + && tr.segment(Edge(cell, i1, i2)).squared_length() < sq_low) { #ifdef CGAL_TETRAHEDRAL_REMESHING_DEBUG const typename T3::Point p1 = e.first->point(); @@ -1070,7 +1070,7 @@ void collapse_short_edges(C3T3& c3t3, if (!can_be_collapsed(edge, c3t3, protect_boundaries, cell_selector)) { #ifdef CGAL_TETRAHEDRAL_REMESHING_DEBUG - short_cancel << "2 " << point(p1) << " " << point(p2) << std::endl; + short_cancel << "2 " << point(p1) << " " << point(p2) << std::endl; #endif continue; } @@ -1082,7 +1082,7 @@ void collapse_short_edges(C3T3& c3t3, { std::vector incident_short; c3t3.triangulation().finite_incident_edges(vh, - std::back_inserter(incident_short)); + std::back_inserter(incident_short)); for (const Edge& eshort : incident_short) { if (!can_be_collapsed(eshort, c3t3, protect_boundaries, cell_selector)) diff --git a/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/compute_c3t3_statistics.h b/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/compute_c3t3_statistics.h index 20d676f7117..13cdf08d36f 100644 --- a/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/compute_c3t3_statistics.h +++ b/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/compute_c3t3_statistics.h @@ -30,8 +30,8 @@ namespace internal { template void compute_statistics(const Triangulation& tr, - CellSelector cell_selector, - const char* filename = "statistics_c3t3.txt") + CellSelector cell_selector, + const char* filename = "statistics_c3t3.txt") { typedef Triangulation Tr; typedef typename Tr::Geom_traits Gt; @@ -114,8 +114,8 @@ void compute_statistics(const Triangulation& tr, std::cout << p0 << "\n\t" << p1 << "\n\t" << p2 << "\n\t" << p3 << std::endl; } double circumradius = (v == 0.) - ? CGAL::sqrt(CGAL::squared_radius(p0, p1, p2)) - : CGAL::sqrt(CGAL::squared_radius(p0, p1, p2, p3)); + ? CGAL::sqrt(CGAL::squared_radius(p0, p1, p2)) + : CGAL::sqrt(CGAL::squared_radius(p0, p1, p2, p3)); //find shortest edge double edges[6]; @@ -134,9 +134,9 @@ void compute_statistics(const Triangulation& tr, } double sumar = CGAL::sqrt(CGAL::squared_area(p0, p1, p2)) - + CGAL::sqrt(CGAL::squared_area(p1, p2, p3)) - + CGAL::sqrt(CGAL::squared_area(p2, p3, p0)) - + CGAL::sqrt(CGAL::squared_area(p3, p1, p0)); + + CGAL::sqrt(CGAL::squared_area(p1, p2, p3)) + + CGAL::sqrt(CGAL::squared_area(p2, p3, p0)) + + CGAL::sqrt(CGAL::squared_area(p3, p1, p0)); double inradius = 3. * v / sumar; double smallest_edge_radius_ = min_edge / circumradius*CGAL::sqrt(6.) / 4.;//*sqrt(6)/4 so that the perfect tet ratio is 1 double smallest_radius_radius_ = inradius / circumradius * 3.; //*3 so that the perfect tet ratio is 1 instead of 1/3 diff --git a/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/flip_edges.h b/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/flip_edges.h index 4ae9e2afe25..8f9dbf2c181 100644 --- a/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/flip_edges.h +++ b/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/flip_edges.h @@ -85,9 +85,9 @@ void update_c3t3_facets(C3t3& c3t3, template Sliver_removal_result flip_3_to_2(typename C3t3::Edge& edge, - C3t3& c3t3, - const std::vector& vertices_around_edge, - const Flip_Criterion& criterion) + C3t3& c3t3, + const std::vector& vertices_around_edge, + const Flip_Criterion& criterion) { typedef typename C3t3::Triangulation Tr; typedef typename C3t3::Facet Facet; @@ -126,8 +126,8 @@ Sliver_removal_result flip_3_to_2(typename C3t3::Edge& edge, //Check topological validity const typename C3t3::Subdomain_index subdomain = ch0->subdomain_index(); if ( subdomain != ch1->subdomain_index() - || subdomain != cell_to_remove->subdomain_index() - || ch1->subdomain_index() != cell_to_remove->subdomain_index()) + || subdomain != cell_to_remove->subdomain_index() + || ch1->subdomain_index() != cell_to_remove->subdomain_index()) return NOT_FLIPPABLE; Vertex_handle vh2; @@ -148,10 +148,10 @@ Sliver_removal_result flip_3_to_2(typename C3t3::Edge& edge, ch0->vertex(indices(vh0_id, 0)), ch0->vertex(indices(vh0_id, 1)), ch0->vertex(indices(vh0_id, 2))) - || !is_well_oriented(tr, vh3, - ch1->vertex(indices(vh1_id, 0)), - ch1->vertex(indices(vh1_id, 1)), - ch1->vertex(indices(vh1_id, 2)))) + || !is_well_oriented(tr, vh3, + ch1->vertex(indices(vh1_id, 0)), + ch1->vertex(indices(vh1_id, 1)), + ch1->vertex(indices(vh1_id, 2)))) return NOT_FLIPPABLE; ///********************VALIDITY CHECK***************************/ @@ -189,13 +189,13 @@ Sliver_removal_result flip_3_to_2(typename C3t3::Edge& edge, //Result worst dihedral angle if (curr_min_dh > min_dihedral_angle(tr, vh2, - ch0->vertex(indices(vh0_id, 0)), - ch0->vertex(indices(vh0_id, 1)), - ch0->vertex(indices(vh0_id, 2))) - || curr_min_dh > min_dihedral_angle(tr, vh3, - ch1->vertex(indices(vh1_id, 0)), - ch1->vertex(indices(vh1_id, 1)), - ch1->vertex(indices(vh1_id, 2)))) + ch0->vertex(indices(vh0_id, 0)), + ch0->vertex(indices(vh0_id, 1)), + ch0->vertex(indices(vh0_id, 2))) + || curr_min_dh > min_dihedral_angle(tr, vh3, + ch1->vertex(indices(vh1_id, 0)), + ch1->vertex(indices(vh1_id, 1)), + ch1->vertex(indices(vh1_id, 2)))) return NO_BEST_CONFIGURATION; } else if (criterion == AVERAGE_ANGLE_BASED) @@ -208,12 +208,12 @@ Sliver_removal_result flip_3_to_2(typename C3t3::Edge& edge, average_min_dh /= 3.; FT new_average_min_dh = 0.5 * - (min_dihedral_angle(tr, vh2, ch0->vertex(indices(vh0_id, 0)), - ch0->vertex(indices(vh0_id, 1)), - ch0->vertex(indices(vh0_id, 2))) - + min_dihedral_angle(tr, vh3, ch1->vertex(indices(vh1_id, 0)), - ch1->vertex(indices(vh1_id, 1)), - ch1->vertex(indices(vh1_id, 2)))); + (min_dihedral_angle(tr, vh2, ch0->vertex(indices(vh0_id, 0)), + ch0->vertex(indices(vh0_id, 1)), + ch0->vertex(indices(vh0_id, 2))) + + min_dihedral_angle(tr, vh3, ch1->vertex(indices(vh1_id, 0)), + ch1->vertex(indices(vh1_id, 1)), + ch1->vertex(indices(vh1_id, 2)))); //Result worst dihedral angle if (average_min_dh > new_average_min_dh) return NO_BEST_CONFIGURATION; @@ -402,8 +402,8 @@ void find_best_flip_to_improve_dh(C3t3& c3t3, { Vertex_handle curr_vertex = curr_fcirc->first->vertex(indices(curr_fcirc->second, i)); if ( curr_vertex != vh0 - && curr_vertex != vh1 - && (curr_vertex == vh2 || curr_vertex == vh3)) + && curr_vertex != vh1 + && (curr_vertex == vh2 || curr_vertex == vh3)) { vh = curr_vertex; Facet_circulator facet_circulator(curr_fcirc); @@ -420,7 +420,7 @@ void find_best_flip_to_improve_dh(C3t3& c3t3, for (int i = 0; i < 3; ++i) { Vertex_handle curr_vertex = facet_circulator->first->vertex( - indices(facet_circulator->second, i)); + indices(facet_circulator->second, i)); if (curr_vertex != vh0 && curr_vertex != vh1) { Cell_handle ch; @@ -478,13 +478,13 @@ void find_best_flip_to_improve_dh(C3t3& c3t3, if (!tr.is_infinite(fi.first)) { if (is_well_oriented(tr, vh, fi.first->vertex(indices(fi.second, 0)), - fi.first->vertex(indices(fi.second, 1)), - fi.first->vertex(indices(fi.second, 2)))) + fi.first->vertex(indices(fi.second, 1)), + fi.first->vertex(indices(fi.second, 2)))) { min_flip_dihedral_angle = (std::min)(min_flip_dihedral_angle, - min_dihedral_angle(tr, vh, fi.first->vertex(indices(fi.second, 0)), - fi.first->vertex(indices(fi.second, 1)), - fi.first->vertex(indices(fi.second, 2)))); + min_dihedral_angle(tr, vh, fi.first->vertex(indices(fi.second, 0)), + fi.first->vertex(indices(fi.second, 1)), + fi.first->vertex(indices(fi.second, 2)))); } else { @@ -537,7 +537,7 @@ void find_best_flip_to_improve_dh(C3t3& c3t3, for (int i = 0; i < 3; ++i) { Vertex_handle curr_vertex = curr_fcirc->first->vertex( - indices(curr_fcirc->second, i)); + indices(curr_fcirc->second, i)); if (curr_vertex != vh0 && curr_vertex != vh1) { vh = curr_vertex; @@ -558,7 +558,7 @@ void find_best_flip_to_improve_dh(C3t3& c3t3, for (int i = 0; i < 3; ++i) { Vertex_handle curr_vertex = facet_circulator->first->vertex( - indices(facet_circulator->second, i)); + indices(facet_circulator->second, i)); if (curr_vertex != vh0 && curr_vertex != vh1) { Cell_handle ch; @@ -617,13 +617,13 @@ void find_best_flip_to_improve_dh(C3t3& c3t3, if (!tr.is_infinite(fi.first)) { if (is_well_oriented(tr, vh, fi.first->vertex(indices(fi.second, 0)), - fi.first->vertex(indices(fi.second, 1)), - fi.first->vertex(indices(fi.second, 2)))) + fi.first->vertex(indices(fi.second, 1)), + fi.first->vertex(indices(fi.second, 2)))) { min_flip_dihedral_angle = (std::min)(min_flip_dihedral_angle, - min_dihedral_angle(tr, vh, fi.first->vertex(indices(fi.second, 0)), - fi.first->vertex(indices(fi.second, 1)), - fi.first->vertex(indices(fi.second, 2)))); + min_dihedral_angle(tr, vh, fi.first->vertex(indices(fi.second, 0)), + fi.first->vertex(indices(fi.second, 1)), + fi.first->vertex(indices(fi.second, 2)))); } else { @@ -682,7 +682,7 @@ Sliver_removal_result flip_n_to_m(C3t3& c3t3, } } while (facet_circulator != done_facet_circulator && look_for_vh_iterator); - if (look_for_vh_iterator){ + if (look_for_vh_iterator) { std::cout << "Vertex not an opposite of the edge!!" << std::endl; return NOT_FLIPPABLE; } @@ -699,7 +699,7 @@ Sliver_removal_result flip_n_to_m(C3t3& c3t3, for (int i = 0; i < 3; ++i) { Vertex_handle curr_vertex = facet_circulator->first->vertex( - indices(facet_circulator->second, i)); + indices(facet_circulator->second, i)); if (curr_vertex != vh0 && curr_vertex != vh1) { Cell_handle ch; @@ -743,7 +743,7 @@ Sliver_removal_result flip_n_to_m(C3t3& c3t3, neighbor_facets.insert(tr.mirror_facet(facet_vh1)); //Store it if it do not have vh - if (cell_circulator->has_vertex(vh)){ + if (cell_circulator->has_vertex(vh)) { to_remove.push_back(cell_circulator); } else @@ -761,17 +761,17 @@ Sliver_removal_result flip_n_to_m(C3t3& c3t3, for (const Facet& fi : facets_for_new_cells) { if ( !tr.is_infinite(fi.first) - && !is_well_oriented(tr, vh, fi.first->vertex(indices(fi.second, 0)), - fi.first->vertex(indices(fi.second, 1)), - fi.first->vertex(indices(fi.second, 2)))) + && !is_well_oriented(tr, vh, fi.first->vertex(indices(fi.second, 0)), + fi.first->vertex(indices(fi.second, 1)), + fi.first->vertex(indices(fi.second, 2)))) return NOT_FLIPPABLE; } for (const Facet& fi : facets_for_updated_cells) { if ( !tr.is_infinite(fi.first) - && !is_well_oriented(tr, vh, fi.first->vertex(indices(fi.second, 0)), - fi.first->vertex(indices(fi.second, 1)), - fi.first->vertex(indices(fi.second, 2)))) + && !is_well_oriented(tr, vh, fi.first->vertex(indices(fi.second, 0)), + fi.first->vertex(indices(fi.second, 1)), + fi.first->vertex(indices(fi.second, 2)))) return NOT_FLIPPABLE; } @@ -945,10 +945,10 @@ Sliver_removal_result flip_n_to_m(C3t3& c3t3, template Sliver_removal_result flip_n_to_m(typename C3t3::Edge& edge, - C3t3& c3t3, - std::vector& boundary_vertices, - const Flip_Criterion& criterion, - Visitor& visitor) + C3t3& c3t3, + std::vector& boundary_vertices, + const Flip_Criterion& criterion, + Visitor& visitor) { typedef typename C3t3::Vertex_handle Vertex_handle; typedef typename C3t3::Triangulation::Cell_circulator Cell_circulator; @@ -1038,14 +1038,14 @@ Sliver_removal_result find_best_flip(typename C3t3::Edge& edge, vertices_around_edge.insert(vi); if ( circ->first->subdomain_index() - != circ->first->neighbor(circ->second)->subdomain_index()) + != circ->first->neighbor(circ->second)->subdomain_index()) { boundary_edge = true; boundary_vertices.insert(vi); } if ( tr.is_infinite(circ->first) - != tr.is_infinite(circ->first->neighbor(circ->second))) + != tr.is_infinite(circ->first->neighbor(circ->second))) { hull_edge = true; hull_vertices.insert(vi); @@ -1134,9 +1134,9 @@ std::size_t flip_all_edges(std::vector& edges, template void flip_edges(C3T3& c3t3, - const bool protect_boundaries, - CellSelector cell_selector, - Visitor& visitor) + const bool protect_boundaries, + CellSelector cell_selector, + Visitor& visitor) { CGAL_USE(protect_boundaries); typedef typename C3T3::Triangulation T3; @@ -1176,15 +1176,15 @@ void flip_edges(C3T3& c3t3, std::vector inside_edges; get_internal_edges(c3t3, - cell_selector, - std::back_inserter(inside_edges)); + cell_selector, + std::back_inserter(inside_edges)); //if (criterion == VALENCE_BASED) // flip_inside_edges(inside_edges); //else //{ #ifdef CGAL_TETRAHEDRAL_REMESHING_VERBOSE - nb_flips = + nb_flips = #endif flip_all_edges(inside_edges, c3t3, MIN_ANGLE_BASED, visitor); //} diff --git a/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/smooth_vertices.h b/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/smooth_vertices.h index f8f430b8b9b..ed4e0a8785a 100644 --- a/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/smooth_vertices.h +++ b/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/smooth_vertices.h @@ -60,7 +60,7 @@ public: //collect a map of normals at surface vertices boost::unordered_map > vertices_normals; + boost::unordered_map > vertices_normals; compute_vertices_normals(c3t3, vertices_normals, cell_selector); // Build MLS Surfaces @@ -73,494 +73,585 @@ public: private: -Vector_3 project_on_tangent_plane(const Vector_3& gi, - const Vector_3& pi, - const Vector_3& normal) -{ - Vector_3 diff = pi - gi; - return gi + (normal * diff) * normal; -} + Vector_3 project_on_tangent_plane(const Vector_3& gi, + const Vector_3& pi, + const Vector_3& normal) + { + Vector_3 diff = pi - gi; + return gi + (normal * diff) * normal; + } -template -boost::optional + template + boost::optional find_adjacent_facet_on_surface(const Facet& f, const Edge& edge, const C3t3& c3t3, const CellSelector& cell_selector) -{ - CGAL_assertion(is_boundary(c3t3, f, cell_selector)); - - typedef typename Tr::Facet_circulator Facet_circulator; - - if (c3t3.is_in_complex(edge)) - return {}; //do not "cross" complex edges - //they are likely to be sharp and not to follow the > 0 dot product criterion - - const Surface_patch_index& patch = c3t3.surface_patch_index(f); - const Facet& mf = c3t3.triangulation().mirror_facet(f); - - Facet_circulator fcirc = c3t3.triangulation().incident_facets(edge); - Facet_circulator fend = fcirc; - do { - const Facet fi = *fcirc; - if (f != fi - && mf != fi - && is_boundary(c3t3, fi, cell_selector) - && patch == c3t3.surface_patch_index(fi)) + CGAL_assertion(is_boundary(c3t3, f, cell_selector)); + + typedef typename Tr::Facet_circulator Facet_circulator; + + if (c3t3.is_in_complex(edge)) + return {}; //do not "cross" complex edges + //they are likely to be sharp and not to follow the > 0 dot product criterion + + const Surface_patch_index& patch = c3t3.surface_patch_index(f); + const Facet& mf = c3t3.triangulation().mirror_facet(f); + + Facet_circulator fcirc = c3t3.triangulation().incident_facets(edge); + Facet_circulator fend = fcirc; + do { - return canonical_facet(fi); //"canonical" is important - } - } while (++fcirc != fend); + const Facet fi = *fcirc; + if (f != fi + && mf != fi + && is_boundary(c3t3, fi, cell_selector) + && patch == c3t3.surface_patch_index(fi)) + { + return canonical_facet(fi); //"canonical" is important + } + } while (++fcirc != fend); - return {}; -} + return {}; + } -template -Vector_3 compute_normal(const Facet& f, - const Vector_3& reference_normal, - const C3t3& c3t3, - const CellSelector& cell_selector) -{ - CGAL_assertion(is_boundary(c3t3, f, cell_selector)); + template + Vector_3 compute_normal(const Facet& f, + const Vector_3& reference_normal, + const C3t3& c3t3, + const CellSelector& cell_selector) + { + CGAL_assertion(is_boundary(c3t3, f, cell_selector)); - typename Tr::Geom_traits::Construct_opposite_vector_3 + typename Tr::Geom_traits::Construct_opposite_vector_3 opp = c3t3.triangulation().geom_traits().construct_opposite_vector_3_object(); - typename Tr::Geom_traits::Compute_scalar_product_3 + typename Tr::Geom_traits::Compute_scalar_product_3 scalar_product = c3t3.triangulation().geom_traits().compute_scalar_product_3_object(); - Vector_3 n = CGAL::Tetrahedral_remeshing::normal(f, c3t3.triangulation().geom_traits()); - if (scalar_product(n, reference_normal) < 0.) - n = opp(n); + Vector_3 n = CGAL::Tetrahedral_remeshing::normal(f, c3t3.triangulation().geom_traits()); + if (scalar_product(n, reference_normal) < 0.) + n = opp(n); - return n; -} + return n; + } -template -void compute_vertices_normals(const C3t3& c3t3, - VertexNormalsMap& normals_map, - const CellSelector& cell_selector) -{ - typename Tr::Geom_traits::Construct_opposite_vector_3 + template + void compute_vertices_normals(const C3t3& c3t3, + VertexNormalsMap& normals_map, + const CellSelector& cell_selector) + { + typename Tr::Geom_traits::Construct_opposite_vector_3 opp = c3t3.triangulation().geom_traits().construct_opposite_vector_3_object(); // typename Tr::Geom_traits::Construct_scaled_vector_3 // scale = c3t3.triangulation().geom_traits().construct_scaled_vector_3_object(); - const Tr& tr = c3t3.triangulation(); + const Tr& tr = c3t3.triangulation(); - //collect all facet normals - boost::unordered_map fnormals; - for (const Facet& f : tr.finite_facets()) - { - if (is_boundary(c3t3, f, cell_selector)) + //collect all facet normals + boost::unordered_map fnormals; + for (const Facet& f : tr.finite_facets()) { - const Facet cf = canonical_facet(f); - fnormals[cf] = CGAL::NULL_VECTOR; + if (is_boundary(c3t3, f, cell_selector)) + { + const Facet cf = canonical_facet(f); + fnormals[cf] = CGAL::NULL_VECTOR; + } } - } - for (const std::pair& fn : fnormals) - { - if(fn.second != CGAL::NULL_VECTOR) - continue; - - const Facet& f = fn.first; - const Facet& mf = tr.mirror_facet(f); - CGAL_assertion(is_boundary(c3t3, f, cell_selector)); - - Vector_3 start_ref = CGAL::Tetrahedral_remeshing::normal(f, tr.geom_traits()); - if (c3t3.triangulation().is_infinite(mf.first) - || c3t3.subdomain_index(mf.first) < c3t3.subdomain_index(f.first)) - start_ref = opp(start_ref); - fnormals[f] = start_ref; - - std::list facets; - facets.push_back(f); - while (!facets.empty()) + for (const std::pair& fn : fnormals) { - const Facet f = facets.front(); - facets.pop_front(); + if(fn.second != CGAL::NULL_VECTOR) + continue; - const typename C3t3::Cell_handle ch = f.first; - const std::array, 3> edges + const Facet& f = fn.first; + const Facet& mf = tr.mirror_facet(f); + CGAL_assertion(is_boundary(c3t3, f, cell_selector)); + + Vector_3 start_ref = CGAL::Tetrahedral_remeshing::normal(f, tr.geom_traits()); + if (c3t3.triangulation().is_infinite(mf.first) + || c3t3.subdomain_index(mf.first) < c3t3.subdomain_index(f.first)) + start_ref = opp(start_ref); + fnormals[f] = start_ref; + + std::list facets; + facets.push_back(f); + while (!facets.empty()) + { + const Facet f = facets.front(); + facets.pop_front(); + + const typename C3t3::Cell_handle ch = f.first; + const std::array, 3> edges = { (f.second + 1) % 4, (f.second + 2) % 4, //edge 1-2 (f.second + 2) % 4, (f.second + 3) % 4, //edge 2-3 (f.second + 3) % 4, (f.second + 1) % 4 //edge 3-1 - }; //vertex indices in cells + }; //vertex indices in cells - const Vector_3& ref = fnormals[f]; - for (const std::array& ei : edges) - { - Edge edge(ch, ei[0], ei[1]); - if (boost::optional neighbor - = find_adjacent_facet_on_surface(f, edge, c3t3, cell_selector)) + const Vector_3& ref = fnormals[f]; + for (const std::array& ei : edges) { - const Facet neigh = *neighbor; //already a canonical_facet - if (fnormals[neigh] == CGAL::NULL_VECTOR) //check it's not already computed + Edge edge(ch, ei[0], ei[1]); + if (boost::optional neighbor + = find_adjacent_facet_on_surface(f, edge, c3t3, cell_selector)) { - fnormals[neigh] = compute_normal(neigh, ref, c3t3, cell_selector); - facets.push_back(neigh); + const Facet neigh = *neighbor; //already a canonical_facet + if (fnormals[neigh] == CGAL::NULL_VECTOR) //check it's not already computed + { + fnormals[neigh] = compute_normal(neigh, ref, c3t3, cell_selector); + facets.push_back(neigh); + } } } } } - } #ifdef CGAL_TETRAHEDRAL_REMESHING_DEBUG - std::ofstream osf("dump_facet_normals.polylines.txt"); + std::ofstream osf("dump_facet_normals.polylines.txt"); #endif - for (const auto& fn : fnormals) - { - const Facet& f = fn.first; - const Vector_3& n = fn.second; - -#ifdef CGAL_TETRAHEDRAL_REMESHING_DEBUG - typename Tr::Geom_traits::Point_3 fc - = CGAL::centroid(point(f.first->vertex(indices(f.second, 0))->point()), - point(f.first->vertex(indices(f.second, 1))->point()), - point(f.first->vertex(indices(f.second, 2))->point())); - osf << "2 " << fc << " " << (fc + n) << std::endl; -#endif - const Surface_patch_index& surf_i = c3t3.surface_patch_index(f); - - for (int i = 0; i < 3; ++i) + for (const auto& fn : fnormals) { - const Vertex_handle vi = f.first->vertex(indices(f.second, i)); - typename VertexNormalsMap::iterator patch_vector_it = normals_map.find(vi); + const Facet& f = fn.first; + const Vector_3& n = fn.second; - if (patch_vector_it == normals_map.end() - || patch_vector_it->second.find(surf_i) == patch_vector_it->second.end()) +#ifdef CGAL_TETRAHEDRAL_REMESHING_DEBUG + typename Tr::Geom_traits::Point_3 fc + = CGAL::centroid(point(f.first->vertex(indices(f.second, 0))->point()), + point(f.first->vertex(indices(f.second, 1))->point()), + point(f.first->vertex(indices(f.second, 2))->point())); + osf << "2 " << fc << " " << (fc + n) << std::endl; +#endif + const Surface_patch_index& surf_i = c3t3.surface_patch_index(f); + + for (int i = 0; i < 3; ++i) { - normals_map[vi][surf_i] = n; - } - else - { - normals_map[vi][surf_i] += n; + const Vertex_handle vi = f.first->vertex(indices(f.second, i)); + typename VertexNormalsMap::iterator patch_vector_it = normals_map.find(vi); + + if (patch_vector_it == normals_map.end() + || patch_vector_it->second.find(surf_i) == patch_vector_it->second.end()) + { + normals_map[vi][surf_i] = n; + } + else + { + normals_map[vi][surf_i] += n; + } } } - } #ifdef CGAL_TETRAHEDRAL_REMESHING_DEBUG - osf.close(); - std::ofstream os("dump_normals.polylines.txt"); - boost::unordered_map > ons_map; + osf.close(); + std::ofstream os("dump_normals.polylines.txt"); + boost::unordered_map > ons_map; #endif - //normalize the computed normals - for (typename VertexNormalsMap::iterator vnm_it = normals_map.begin(); - vnm_it != normals_map.end(); ++vnm_it) - { - //value type is map - for (typename VertexNormalsMap::mapped_type::iterator it = vnm_it->second.begin(); - it != vnm_it->second.end(); ++it) + //normalize the computed normals + for (typename VertexNormalsMap::iterator vnm_it = normals_map.begin(); + vnm_it != normals_map.end(); ++vnm_it) { - Vector_3& n = it->second; - -#ifdef CGAL_TETRAHEDRAL_REMESHING_DEBUG - auto p = point(vnm_it->first->point()); - os << "2 " << p << " " << (p + n) << std::endl; -#endif - - CGAL::Tetrahedral_remeshing::normalize(n, c3t3.triangulation().geom_traits()); - -#ifdef CGAL_TETRAHEDRAL_REMESHING_DEBUG - const Surface_patch_index si = it->first; - if (ons_map.find(si) == ons_map.end()) - ons_map[si] = std::vector(); - ons_map[si].push_back(typename Tr::Geom_traits::Segment_3(p, p + n)); -#endif - } - } - -#ifdef CGAL_TETRAHEDRAL_REMESHING_DEBUG - os.close(); - for (auto& kv : ons_map) - { - std::ostringstream oss; - oss << "dump_normals_normalized_" << kv.first << ".polylines.txt"; - std::ofstream ons(oss.str()); - for (auto s : kv.second) - ons << "2 " << s.source() << " " << s.target() << std::endl; - ons.close(); - } -#endif -} - -boost::optional project(const Surface_patch_index& si, - const Vector_3& gi) -{ - CGAL_assertion(subdomain_FMLS_indices.find(si) != subdomain_FMLS_indices.end()); - CGAL_assertion(!std::isnan(gi.x()) && !std::isnan(gi.y()) && !std::isnan(gi.z())); - - Vector_3 point(gi.x(), gi.y(), gi.z()); - Vector_3 res_normal; - Vector_3 result(point); - - const FMLS& fmls = subdomain_FMLS[subdomain_FMLS_indices.at(si)]; - - int it_nb = 0; - const int max_it_nb = 5; - const float epsilon = fmls.getPNScale() / 1000.; - const float sq_eps = CGAL::square(epsilon); - - do - { - point = result; - - fmls.fastProjectionCPU(point, result, res_normal); - - if (std::isnan(result[0]) || std::isnan(result[1]) || std::isnan(result[2])) { - std::cout << "MLS error detected si " << si - << "\t(size : " << fmls.getPNSize() << ")" - << "\t(point = " << point << " )" << std::endl; - return {}; - } - } while ((result - point).squared_length() > sq_eps && ++it_nb < max_it_nb); - - return Vector_3(result[0], result[1], result[2]); -} - -template -void check_inversion_and_move(const typename Tr::Vertex_handle v, - const typename Tr::Point& final_pos, - const CellRange& inc_cells, - const Tr& /* tr */) -{ - const typename Tr::Point backup = v->point(); //backup v's position - const typename Tr::Geom_traits::Point_3 pv = point(backup); - - bool valid_orientation = false; - double frac = 1.0; - typename Tr::Geom_traits::Vector_3 move(pv, point(final_pos)); - do - { - v->set_point(typename Tr::Point(pv + frac * move)); - - bool valid_try = true; - for (const typename Tr::Cell_handle ci : inc_cells) - { - if (CGAL::POSITIVE != CGAL::orientation(point(ci->vertex(0)->point()), - point(ci->vertex(1)->point()), - point(ci->vertex(2)->point()), - point(ci->vertex(3)->point()))) + //value type is map + for (typename VertexNormalsMap::mapped_type::iterator it = vnm_it->second.begin(); + it != vnm_it->second.end(); ++it) { - frac = 0.9 * frac; - valid_try = false; - break; + Vector_3& n = it->second; + +#ifdef CGAL_TETRAHEDRAL_REMESHING_DEBUG + auto p = point(vnm_it->first->point()); + os << "2 " << p << " " << (p + n) << std::endl; +#endif + + CGAL::Tetrahedral_remeshing::normalize(n, c3t3.triangulation().geom_traits()); + +#ifdef CGAL_TETRAHEDRAL_REMESHING_DEBUG + const Surface_patch_index si = it->first; + if (ons_map.find(si) == ons_map.end()) + ons_map[si] = std::vector(); + ons_map[si].push_back(typename Tr::Geom_traits::Segment_3(p, p + n)); +#endif } } - valid_orientation = valid_try; + +#ifdef CGAL_TETRAHEDRAL_REMESHING_DEBUG + os.close(); + for (auto& kv : ons_map) + { + std::ostringstream oss; + oss << "dump_normals_normalized_" << kv.first << ".polylines.txt"; + std::ofstream ons(oss.str()); + for (auto s : kv.second) + ons << "2 " << s.source() << " " << s.target() << std::endl; + ons.close(); + } +#endif + } + + boost::optional project(const Surface_patch_index& si, + const Vector_3& gi) + { + CGAL_assertion(subdomain_FMLS_indices.find(si) != subdomain_FMLS_indices.end()); + CGAL_assertion(!std::isnan(gi.x()) && !std::isnan(gi.y()) && !std::isnan(gi.z())); + + Vector_3 point(gi.x(), gi.y(), gi.z()); + Vector_3 res_normal; + Vector_3 result(point); + + const FMLS& fmls = subdomain_FMLS[subdomain_FMLS_indices.at(si)]; + + int it_nb = 0; + const int max_it_nb = 5; + const float epsilon = fmls.getPNScale() / 1000.; + const float sq_eps = CGAL::square(epsilon); + + do + { + point = result; + + fmls.fastProjectionCPU(point, result, res_normal); + + if (std::isnan(result[0]) || std::isnan(result[1]) || std::isnan(result[2])) { + std::cout << "MLS error detected si " << si + << "\t(size : " << fmls.getPNSize() << ")" + << "\t(point = " << point << " )" << std::endl; + return {}; + } + } while ((result - point).squared_length() > sq_eps && ++it_nb < max_it_nb); + + return Vector_3(result[0], result[1], result[2]); + } + + template + void check_inversion_and_move(const typename Tr::Vertex_handle v, + const typename Tr::Point& final_pos, + const CellRange& inc_cells, + const Tr& /* tr */) + { + const typename Tr::Point backup = v->point(); //backup v's position + const typename Tr::Geom_traits::Point_3 pv = point(backup); + + bool valid_orientation = false; + double frac = 1.0; + typename Tr::Geom_traits::Vector_3 move(pv, point(final_pos)); + do + { + v->set_point(typename Tr::Point(pv + frac * move)); + + bool valid_try = true; + for (const typename Tr::Cell_handle ci : inc_cells) + { + if (CGAL::POSITIVE != CGAL::orientation(point(ci->vertex(0)->point()), + point(ci->vertex(1)->point()), + point(ci->vertex(2)->point()), + point(ci->vertex(3)->point()))) + { + frac = 0.9 * frac; + valid_try = false; + break; + } + } + valid_orientation = valid_try; // std::cout << std::boolalpha << "valid orientation = " << valid_orientation // << "\tfrac = " << frac << std::endl; + } + while(!valid_orientation && frac > 0.1); + + if (!valid_orientation) //move failed + v->set_point(backup); } - while(!valid_orientation && frac > 0.1); - if (!valid_orientation) //move failed - v->set_point(backup); -} - -void collect_vertices_surface_indices( - const C3t3& c3t3, - boost::unordered_map >& vertices_surface_indices) -{ - for (typename C3t3::Facet_iterator fit = c3t3.facets_begin(); - fit != c3t3.facets_end(); ++fit) { - const Surface_patch_index& surface_index = c3t3.surface_patch_index(*fit); - - for (int i = 0; i < 3; i++) + for (typename C3t3::Facet_iterator fit = c3t3.facets_begin(); + fit != c3t3.facets_end(); ++fit) { - const Vertex_handle vi = fit->first->vertex(indices(fit->second, i)); + const Surface_patch_index& surface_index = c3t3.surface_patch_index(*fit); - std::vector& v_surface_indices = vertices_surface_indices[vi]; - if (std::find(v_surface_indices.begin(), v_surface_indices.end(), surface_index) == v_surface_indices.end()) - v_surface_indices.push_back(surface_index); + for (int i = 0; i < 3; i++) + { + const Vertex_handle vi = fit->first->vertex(indices(fit->second, i)); + + std::vector& v_surface_indices = vertices_surface_indices[vi]; + if (std::find(v_surface_indices.begin(), v_surface_indices.end(), surface_index) == v_surface_indices.end()) + v_surface_indices.push_back(surface_index); + } } } -} public: -template -void smooth_vertices(C3T3& c3t3, - const bool protect_boundaries, - const CellSelector& cell_selector) -{ - typedef typename C3T3::Cell_handle Cell_handle; - typedef typename Gt::FT FT; + template + void smooth_vertices(C3T3& c3t3, + const bool protect_boundaries, + const CellSelector& cell_selector) + { + typedef typename C3T3::Cell_handle Cell_handle; + typedef typename Gt::FT FT; #ifdef CGAL_TETRAHEDRAL_REMESHING_DEBUG - std::ofstream os_surf("smooth_surfaces.polylines.txt"); - std::ofstream os_surf0("smooth_surfaces0.polylines.txt"); - std::ofstream os_vol("smooth_volume.polylines.txt"); + std::ofstream os_surf("smooth_surfaces.polylines.txt"); + std::ofstream os_surf0("smooth_surfaces0.polylines.txt"); + std::ofstream os_vol("smooth_volume.polylines.txt"); #endif #ifdef CGAL_TETRAHEDRAL_REMESHING_VERBOSE - std::cout << "Smooth vertices..."; - std::cout.flush(); - std::size_t nb_done = 0; + std::cout << "Smooth vertices..."; + std::cout.flush(); + std::size_t nb_done = 0; #endif - Tr& tr = c3t3.triangulation(); + Tr& tr = c3t3.triangulation(); #ifdef CGAL_TETRAHEDRAL_REMESHING_SMOOTH_SHARP_EDGES - //collect a map of vertices surface indices - boost::unordered_map > vertices_surface_indices; - collect_vertices_surface_indices(c3t3, vertices_surface_indices); + //collect a map of vertices surface indices + boost::unordered_map > vertices_surface_indices; + collect_vertices_surface_indices(c3t3, vertices_surface_indices); #endif - //collect a map of normals at surface vertices - boost::unordered_map > vertices_normals; - compute_vertices_normals(c3t3, vertices_normals, cell_selector); + //collect a map of normals at surface vertices + boost::unordered_map > vertices_normals; + compute_vertices_normals(c3t3, vertices_normals, cell_selector); - //smooth() - const std::size_t nbv = tr.number_of_vertices(); - boost::unordered_map vertex_id; - std::vector smoothed_positions(nbv, CGAL::NULL_VECTOR); - std::vector neighbors(nbv, -1); + //smooth() + const std::size_t nbv = tr.number_of_vertices(); + boost::unordered_map vertex_id; + std::vector smoothed_positions(nbv, CGAL::NULL_VECTOR); + std::vector neighbors(nbv, -1); - //collect ids - std::size_t id = 0; - for (const Vertex_handle v : tr.finite_vertex_handles()) - { - vertex_id[v] = id++; - } + //collect ids + std::size_t id = 0; + for (const Vertex_handle v : tr.finite_vertex_handles()) + { + vertex_id[v] = id++; + } - //collect incident cells - std::vector > + //collect incident cells + std::vector > inc_cells(nbv, boost::container::small_vector()); - for (const Cell_handle c : tr.finite_cell_handles()) - { - for (int i = 0; i < 4; ++i) + for (const Cell_handle c : tr.finite_cell_handles()) { - const std::size_t id = vertex_id[c->vertex(i)]; - inc_cells[id].push_back(c); + for (int i = 0; i < 4; ++i) + { + const std::size_t id = vertex_id[c->vertex(i)]; + inc_cells[id].push_back(c); + } } - } - if (!protect_boundaries) - { + if (!protect_boundaries) + { #ifdef CGAL_TETRAHEDRAL_REMESHING_SMOOTH_SHARP_EDGES - /////////////// EDGES IN COMPLEX ////////////////// - //collect neighbors - for (const Edge& e : tr.finite_edges()) - { - if (c3t3.is_in_complex(e)) + /////////////// EDGES IN COMPLEX ////////////////// + //collect neighbors + for (const Edge& e : tr.finite_edges()) { - const Vertex_handle vh0 = e.first->vertex(e.second); - const Vertex_handle vh1 = e.first->vertex(e.third); - - const std::size_t& i0 = vertex_id.at(vh0); - const std::size_t& i1 = vertex_id.at(vh1); - - const bool on_feature_v0 = is_on_feature(vh0); - const bool on_feature_v1 = is_on_feature(vh1); - - if (!c3t3.is_in_complex(vh0)) - neighbors[i0] = (std::max)(0, neighbors[i0]); - if (!c3t3.is_in_complex(vh1)) - neighbors[i1] = (std::max)(0, neighbors[i1]); - - if (!c3t3.is_in_complex(vh0) && on_feature_v1) + if (c3t3.is_in_complex(e)) { - const Point_3& p1 = point(vh1->point()); - smoothed_positions[i0] = smoothed_positions[i0] + Vector_3(p1.x(), p1.y(), p1.z()); - neighbors[i0]++; - } - if (!c3t3.is_in_complex(vh1) && on_feature_v0) - { - const Point_3& p0 = point(vh0->point()); - smoothed_positions[i1] = smoothed_positions[i1] + Vector_3(p0.x(), p0.y(), p0.z()); - neighbors[i1]++; + const Vertex_handle vh0 = e.first->vertex(e.second); + const Vertex_handle vh1 = e.first->vertex(e.third); + + const std::size_t& i0 = vertex_id.at(vh0); + const std::size_t& i1 = vertex_id.at(vh1); + + const bool on_feature_v0 = is_on_feature(vh0); + const bool on_feature_v1 = is_on_feature(vh1); + + if (!c3t3.is_in_complex(vh0)) + neighbors[i0] = (std::max)(0, neighbors[i0]); + if (!c3t3.is_in_complex(vh1)) + neighbors[i1] = (std::max)(0, neighbors[i1]); + + if (!c3t3.is_in_complex(vh0) && on_feature_v1) + { + const Point_3& p1 = point(vh1->point()); + smoothed_positions[i0] = smoothed_positions[i0] + Vector_3(p1.x(), p1.y(), p1.z()); + neighbors[i0]++; + } + if (!c3t3.is_in_complex(vh1) && on_feature_v0) + { + const Point_3& p0 = point(vh0->point()); + smoothed_positions[i1] = smoothed_positions[i1] + Vector_3(p0.x(), p0.y(), p0.z()); + neighbors[i1]++; + } } } - } - // Smooth - for (Vertex_handle v : tr.finite_vertex_handles()) - { - const std::size_t& vid = vertex_id.at(v); - if (neighbors[vid] > 1) + // Smooth + for (Vertex_handle v : tr.finite_vertex_handles()) { - Vector_3 smoothed_position = smoothed_positions[vid] / neighbors[vid]; - Vector_3 final_position = CGAL::NULL_VECTOR; - - std::size_t count = 0; - const Vector_3 current_pos(CGAL::ORIGIN, point(v->point())); - - const std::vector& v_surface_indices = vertices_surface_indices[v]; - for (const Surface_patch_index& si : v_surface_indices) + const std::size_t& vid = vertex_id.at(v); + if (neighbors[vid] > 1) { - Vector_3 normal_projection - = project_on_tangent_plane(smoothed_position, current_pos, vertices_normals[v][si]); + Vector_3 smoothed_position = smoothed_positions[vid] / neighbors[vid]; + Vector_3 final_position = CGAL::NULL_VECTOR; - //Check if the mls surface exists to avoid degenerated cases - if (boost::optional mls_projection = project(si, normal_projection)) { - final_position = final_position + *mls_projection; - } - else { - final_position = final_position + normal_projection; - } - count++; - } + std::size_t count = 0; + const Vector_3 current_pos(CGAL::ORIGIN, point(v->point())); - if (count > 0) - final_position = final_position / static_cast(count); - else - final_position = smoothed_position; + const std::vector& v_surface_indices = vertices_surface_indices[v]; + for (const Surface_patch_index& si : v_surface_indices) + { + Vector_3 normal_projection + = project_on_tangent_plane(smoothed_position, current_pos, vertices_normals[v][si]); + + //Check if the mls surface exists to avoid degenerated cases + if (boost::optional mls_projection = project(si, normal_projection)) { + final_position = final_position + *mls_projection; + } + else { + final_position = final_position + normal_projection; + } + count++; + } + + if (count > 0) + final_position = final_position / static_cast(count); + else + final_position = smoothed_position; #ifdef CGAL_TETRAHEDRAL_REMESHING_DEBUG - os_surf << "2 " << current_pos << " " << final_position << std::endl, + os_surf << "2 " << current_pos << " " << final_position << std::endl, #endif - // move vertex - v->set_point(typename Tr::Point( - final_position.x(), final_position.y(), final_position.z())); - } - else if (neighbors[vid] > 0) - { - Vector_3 final_position = CGAL::NULL_VECTOR; - - int count = 0; - const Vector_3 current_pos(CGAL::ORIGIN, point(v->point())); - - const std::vector& v_surface_indices = vertices_surface_indices[v]; - for (const Surface_patch_index si : v_surface_indices) - { - //Check if the mls surface exists to avoid degenerated cases - - if (boost::optional mls_projection = project(si, current_pos)) { - final_position = final_position + *mls_projection; - } - else { - final_position = final_position + current_pos; - } - count++; + // move vertex + v->set_point(typename Tr::Point( + final_position.x(), final_position.y(), final_position.z())); } + else if (neighbors[vid] > 0) + { + Vector_3 final_position = CGAL::NULL_VECTOR; - if (count > 0) - final_position = final_position / static_cast(count); - else - final_position = current_pos; + int count = 0; + const Vector_3 current_pos(CGAL::ORIGIN, point(v->point())); + + const std::vector& v_surface_indices = vertices_surface_indices[v]; + for (const Surface_patch_index si : v_surface_indices) + { + //Check if the mls surface exists to avoid degenerated cases + + if (boost::optional mls_projection = project(si, current_pos)) { + final_position = final_position + *mls_projection; + } + else { + final_position = final_position + current_pos; + } + count++; + } + + if (count > 0) + final_position = final_position / static_cast(count); + else + final_position = current_pos; #ifdef CGAL_TETRAHEDRAL_REMESHING_DEBUG - os_surf << "2 " << current_pos << " " << final_position << std::endl, + os_surf << "2 " << current_pos << " " << final_position << std::endl, #endif - // move vertex - v->set_point( - typename Tr::Point(final_position.x(), final_position.y(), final_position.z())); + // move vertex + v->set_point( + typename Tr::Point(final_position.x(), final_position.y(), final_position.z())); + } } - } #endif //CGAL_TETRAHEDRAL_REMESHING_SMOOTH_SHARP_EDGES - smoothed_positions.assign(nbv, CGAL::NULL_VECTOR); - neighbors.assign(nbv, -1); + smoothed_positions.assign(nbv, CGAL::NULL_VECTOR); + neighbors.assign(nbv, -1); - /////////////// EDGES ON SURFACE, BUT NOT IN COMPLEX ////////////////// + /////////////// EDGES ON SURFACE, BUT NOT IN COMPLEX ////////////////// + for (const Edge& e : tr.finite_edges()) + { + if (is_boundary(c3t3, e, cell_selector) && !c3t3.is_in_complex(e)) + { + const Vertex_handle vh0 = e.first->vertex(e.second); + const Vertex_handle vh1 = e.first->vertex(e.third); + + const std::size_t& i0 = vertex_id.at(vh0); + const std::size_t& i1 = vertex_id.at(vh1); + + const bool on_feature_v0 = is_on_feature(vh0); + const bool on_feature_v1 = is_on_feature(vh1); + + if (!on_feature_v0) + neighbors[i0] = (std::max)(0, neighbors[i0]); + if (!on_feature_v1) + neighbors[i1] = (std::max)(0, neighbors[i1]); + + if (!on_feature_v0) + { + const Point_3& p1 = point(vh1->point()); + smoothed_positions[i0] = smoothed_positions[i0] + Vector_3(p1.x(), p1.y(), p1.z()); + neighbors[i0]++; + } + if (!on_feature_v1) + { + const Point_3& p0 = point(vh0->point()); + smoothed_positions[i1] = smoothed_positions[i1] + Vector_3(p0.x(), p0.y(), p0.z()); + neighbors[i1]++; + } + } + } + + for (Vertex_handle v : tr.finite_vertex_handles()) + { + if (v->in_dimension() != 2) + continue; + + const std::size_t& vid = vertex_id.at(v); + if (neighbors[vid] > 1) + { + Vector_3 smoothed_position = smoothed_positions[vid] / static_cast(neighbors[vid]); + const Vector_3 current_pos(CGAL::ORIGIN, point(v->point())); + Vector_3 final_position = CGAL::NULL_VECTOR; + + const Surface_patch_index si = surface_patch_index(v, c3t3); + CGAL_assertion(si != Surface_patch_index()); + + Vector_3 normal_projection = project_on_tangent_plane(smoothed_position, + current_pos, + vertices_normals[v][si]); + + if (boost::optional mls_projection = project(si, normal_projection)) + final_position = final_position + *mls_projection; + else + final_position = smoothed_position; + +#ifdef CGAL_TETRAHEDRAL_REMESHING_DEBUG + os_surf << "2 " << current_pos << " " << final_position << std::endl, +#endif + check_inversion_and_move(v, typename Tr::Point( + final_position.x(), final_position.y(), final_position.z()), + inc_cells[vid], + tr); + } + else if (neighbors[vid] > 0) + { + const Surface_patch_index si = surface_patch_index(v, c3t3); + CGAL_assertion(si != Surface_patch_index()); + + const Vector_3 current_pos(CGAL::ORIGIN, point(v->point())); + + if (boost::optional mls_projection = project(si, current_pos)) + { + const typename Tr::Point new_pos(CGAL::ORIGIN + *mls_projection); + check_inversion_and_move(v, new_pos, inc_cells[vid], tr); + +#ifdef CGAL_TETRAHEDRAL_REMESHING_DEBUG + os_surf0 << "2 " << current_pos << " " << new_pos << std::endl; +#endif + } + } + } + } + CGAL_assertion(CGAL::Tetrahedral_remeshing::debug::are_cell_orientations_valid(tr)); + //// end if(!protect_boundaries) + + smoothed_positions.assign(nbv, CGAL::NULL_VECTOR); + neighbors.assign(nbv, 0/*for dim 3 vertices, start counting directly from 0*/); + + ////////////// INTERNAL VERTICES /////////////////////// for (const Edge& e : tr.finite_edges()) { - if (is_boundary(c3t3, e, cell_selector) && !c3t3.is_in_complex(e)) + if (!is_outside(e, c3t3, cell_selector)) { const Vertex_handle vh0 = e.first->vertex(e.second); const Vertex_handle vh1 = e.first->vertex(e.third); @@ -568,24 +659,16 @@ void smooth_vertices(C3T3& c3t3, const std::size_t& i0 = vertex_id.at(vh0); const std::size_t& i1 = vertex_id.at(vh1); - const bool on_feature_v0 = is_on_feature(vh0); - const bool on_feature_v1 = is_on_feature(vh1); - - if (!on_feature_v0) - neighbors[i0] = (std::max)(0, neighbors[i0]); - if (!on_feature_v1) - neighbors[i1] = (std::max)(0, neighbors[i1]); - - if (!on_feature_v0) + if (c3t3.in_dimension(vh0) == 3) { const Point_3& p1 = point(vh1->point()); - smoothed_positions[i0] = smoothed_positions[i0] + Vector_3(p1.x(), p1.y(), p1.z()); + smoothed_positions[i0] = smoothed_positions[i0] + Vector_3(CGAL::ORIGIN, p1); neighbors[i0]++; } - if (!on_feature_v1) + if (c3t3.in_dimension(vh1) == 3) { const Point_3& p0 = point(vh0->point()); - smoothed_positions[i1] = smoothed_positions[i1] + Vector_3(p0.x(), p0.y(), p0.z()); + smoothed_positions[i1] = smoothed_positions[i1] + Vector_3(CGAL::ORIGIN, p0); neighbors[i1]++; } } @@ -593,118 +676,35 @@ void smooth_vertices(C3T3& c3t3, for (Vertex_handle v : tr.finite_vertex_handles()) { - if (v->in_dimension() != 2) - continue; - const std::size_t& vid = vertex_id.at(v); - if (neighbors[vid] > 1) + if (c3t3.in_dimension(v) == 3 && neighbors[vid] > 1) { - Vector_3 smoothed_position = smoothed_positions[vid] / static_cast(neighbors[vid]); - const Vector_3 current_pos(CGAL::ORIGIN, point(v->point())); - Vector_3 final_position = CGAL::NULL_VECTOR; - - const Surface_patch_index si = surface_patch_index(v, c3t3); - CGAL_assertion(si != Surface_patch_index()); - - Vector_3 normal_projection = project_on_tangent_plane(smoothed_position, - current_pos, - vertices_normals[v][si]); - - if (boost::optional mls_projection = project(si, normal_projection)) - final_position = final_position + *mls_projection; - else - final_position = smoothed_position; - -#ifdef CGAL_TETRAHEDRAL_REMESHING_DEBUG - os_surf << "2 " << current_pos << " " << final_position << std::endl, -#endif - check_inversion_and_move(v, typename Tr::Point( - final_position.x(), final_position.y(), final_position.z()), - inc_cells[vid], - tr); - } - else if (neighbors[vid] > 0) - { - const Surface_patch_index si = surface_patch_index(v, c3t3); - CGAL_assertion(si != Surface_patch_index()); - - const Vector_3 current_pos(CGAL::ORIGIN, point(v->point())); - - if (boost::optional mls_projection = project(si, current_pos)) - { - const typename Tr::Point new_pos(CGAL::ORIGIN + *mls_projection); - check_inversion_and_move(v, new_pos, inc_cells[vid], tr); - -#ifdef CGAL_TETRAHEDRAL_REMESHING_DEBUG - os_surf0 << "2 " << current_pos << " " << new_pos << std::endl; -#endif - } - } - } - } - CGAL_assertion(CGAL::Tetrahedral_remeshing::debug::are_cell_orientations_valid(tr)); - //// end if(!protect_boundaries) - - smoothed_positions.assign(nbv, CGAL::NULL_VECTOR); - neighbors.assign(nbv, 0/*for dim 3 vertices, start counting directly from 0*/); - - ////////////// INTERNAL VERTICES /////////////////////// - for (const Edge& e : tr.finite_edges()) - { - if (!is_outside(e, c3t3, cell_selector)) - { - const Vertex_handle vh0 = e.first->vertex(e.second); - const Vertex_handle vh1 = e.first->vertex(e.third); - - const std::size_t& i0 = vertex_id.at(vh0); - const std::size_t& i1 = vertex_id.at(vh1); - - if (c3t3.in_dimension(vh0) == 3) - { - const Point_3& p1 = point(vh1->point()); - smoothed_positions[i0] = smoothed_positions[i0] + Vector_3(CGAL::ORIGIN, p1); - neighbors[i0]++; - } - if (c3t3.in_dimension(vh1) == 3) - { - const Point_3& p0 = point(vh0->point()); - smoothed_positions[i1] = smoothed_positions[i1] + Vector_3(CGAL::ORIGIN, p0); - neighbors[i1]++; - } - } - } - - for (Vertex_handle v : tr.finite_vertex_handles()) - { - const std::size_t& vid = vertex_id.at(v); - if (c3t3.in_dimension(v) == 3 && neighbors[vid] > 1) - { #ifdef CGAL_TETRAHEDRAL_REMESHING_VERBOSE - ++nb_done; + ++nb_done; #endif #ifdef CGAL_TETRAHEDRAL_REMESHING_DEBUG - os_vol << "2 " << point(v->point()); + os_vol << "2 " << point(v->point()); #endif - const Vector_3 p = smoothed_positions[vid] / static_cast(neighbors[vid]); - check_inversion_and_move(v, typename Tr::Point(p.x(), p.y(), p.z()), inc_cells[vid], tr); + const Vector_3 p = smoothed_positions[vid] / static_cast(neighbors[vid]); + check_inversion_and_move(v, typename Tr::Point(p.x(), p.y(), p.z()), inc_cells[vid], tr); #ifdef CGAL_TETRAHEDRAL_REMESHING_DEBUG - os_vol << " " << point(v->point()) << std::endl; + os_vol << " " << point(v->point()) << std::endl; #endif + } } - } - CGAL_assertion(CGAL::Tetrahedral_remeshing::debug::are_cell_orientations_valid(tr)); + CGAL_assertion(CGAL::Tetrahedral_remeshing::debug::are_cell_orientations_valid(tr)); #ifdef CGAL_TETRAHEDRAL_REMESHING_VERBOSE - std::cout << " done (" << nb_done << " vertices smoothed)." << std::endl; + std::cout << " done (" << nb_done << " vertices smoothed)." << std::endl; #endif #ifdef CGAL_TETRAHEDRAL_REMESHING_DEBUG - CGAL::Tetrahedral_remeshing::debug::dump_vertices_by_dimension( - c3t3.triangulation(), "c3t3_vertices_after_smoothing"); - os_surf.close(); - os_vol.close(); + CGAL::Tetrahedral_remeshing::debug::dump_vertices_by_dimension( + c3t3.triangulation(), "c3t3_vertices_after_smoothing"); + os_surf.close(); + os_vol.close(); #endif -} + } };//end class Tetrahedral_remeshing_smoother }//namespace internal diff --git a/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/split_long_edges.h b/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/split_long_edges.h index d0f32b774cb..0c3eb81ebe7 100644 --- a/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/split_long_edges.h +++ b/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/split_long_edges.h @@ -80,9 +80,9 @@ typename C3t3::Vertex_handle split_edge(const typename C3t3::Edge& e, Surface_patch_index patch = c3t3.surface_patch_index(circ, findex); Vertex_handle opp_vertex = circ->vertex(findex); facets_info.insert(std::make_pair(opp_facet1, - std::make_pair(opp_vertex, patch))); + std::make_pair(opp_vertex, patch))); facets_info.insert(std::make_pair(opp_facet2, - std::make_pair(opp_vertex, patch))); + std::make_pair(opp_vertex, patch))); if(c3t3.is_in_complex(circ, findex)) c3t3.remove_from_complex(circ, findex); @@ -94,7 +94,7 @@ typename C3t3::Vertex_handle split_edge(const typename C3t3::Edge& e, // insert midpoint Vertex_handle new_v = tr.tds().insert_in_edge(e); const Point m = tr.geom_traits().construct_midpoint_3_object() - (point(v1->point()), point(v2->point())); + (point(v1->point()), point(v2->point())); new_v->set_point(typename Tr::Point(m)); new_v->set_dimension(dimension); @@ -186,10 +186,10 @@ bool can_be_split(const typename C3T3::Edge& e, template void split_long_edges(C3T3& c3t3, - const typename C3T3::Triangulation::Geom_traits::FT& high, - const bool protect_boundaries, - CellSelector cell_selector, - Visitor& visitor) + const typename C3T3::Triangulation::Geom_traits::FT& high, + const bool protect_boundaries, + CellSelector cell_selector, + Visitor& visitor) { typedef typename C3T3::Triangulation T3; typedef typename T3::Cell_handle Cell_handle; @@ -201,8 +201,8 @@ void split_long_edges(C3T3& c3t3, typedef typename T3::Geom_traits Gt; typedef typename T3::Geom_traits::FT FT; typedef boost::bimap< - boost::bimaps::set_of, - boost::bimaps::multiset_of > > Boost_bimap; + boost::bimaps::set_of, + boost::bimaps::multiset_of > > Boost_bimap; typedef typename Boost_bimap::value_type long_edge; #ifdef CGAL_TETRAHEDRAL_REMESHING_VERBOSE @@ -272,9 +272,9 @@ void split_long_edges(C3T3& c3t3, #ifdef CGAL_TETRAHEDRAL_REMESHING_VERBOSE_PROGRESS std::cout << "\rSplit (" << high << ")... (" - << long_edges.left.size() << " long edges, " - << "length = " << std::sqrt(sqlen) << ", " - << nb_splits << " splits)"; + << long_edges.left.size() << " long edges, " + << "length = " << std::sqrt(sqlen) << ", " + << nb_splits << " splits)"; std::cout.flush(); #endif } diff --git a/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/tetrahedral_adaptive_remeshing_impl.h b/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/tetrahedral_adaptive_remeshing_impl.h index e330d8f68ec..5969470a1a9 100644 --- a/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/tetrahedral_adaptive_remeshing_impl.h +++ b/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/tetrahedral_adaptive_remeshing_impl.h @@ -82,14 +82,14 @@ public: }; template + , typename SizingFunction + , typename EdgeIsConstrainedMap + , typename FacetIsConstrainedMap + , typename CellSelector + , typename Visitor + , typename CornerIndex = int + , typename CurveIndex = int + > class Adaptive_remesher { typedef Triangulation Tr; @@ -117,13 +117,13 @@ private: public: Adaptive_remesher(Triangulation& tr - , const SizingFunction& sizing - , const bool protect_boundaries - , EdgeIsConstrainedMap ecmap - , FacetIsConstrainedMap fcmap - , CellSelector cell_selector - , Visitor& visitor - ) + , const SizingFunction& sizing + , const bool protect_boundaries + , EdgeIsConstrainedMap ecmap + , FacetIsConstrainedMap fcmap + , CellSelector cell_selector + , Visitor& visitor + ) : m_c3t3() , m_sizing(sizing) , m_protect_boundaries(protect_boundaries) @@ -143,13 +143,13 @@ public: } Adaptive_remesher(C3t3& c3t3 - , const SizingFunction& sizing - , const bool protect_boundaries - , EdgeIsConstrainedMap ecmap - , FacetIsConstrainedMap fcmap - , CellSelector cell_selector - , Visitor& visitor - ) + , const SizingFunction& sizing + , const bool protect_boundaries + , EdgeIsConstrainedMap ecmap + , FacetIsConstrainedMap fcmap + , CellSelector cell_selector + , Visitor& visitor + ) : m_c3t3() , m_sizing(sizing) , m_protect_boundaries(protect_boundaries) @@ -204,7 +204,7 @@ public: CGAL_assertion(debug::are_cell_orientations_valid(tr())); #ifdef CGAL_DUMP_REMESHING_STEPS CGAL::Tetrahedral_remeshing::debug::dump_triangulation_cells(tr(), - "2-collapse.mesh"); + "2-collapse.mesh"); CGAL::Tetrahedral_remeshing::debug::dump_binary(m_c3t3, "2-collapse.binary.cgal"); #endif } @@ -230,7 +230,7 @@ public: CGAL_assertion(debug::are_cell_orientations_valid(tr())); #ifdef CGAL_DUMP_REMESHING_STEPS CGAL::Tetrahedral_remeshing::debug::dump_triangulation_cells(tr(), - "4-smooth.mesh"); + "4-smooth.mesh"); CGAL::Tetrahedral_remeshing::debug::dump_binary(m_c3t3, "4-smooth.binary.cgal"); #endif } @@ -255,7 +255,7 @@ public: if (m_protect_boundaries) { if( m_c3t3.is_in_complex(e) - || is_boundary(m_c3t3, e, m_cell_selector)) + || is_boundary(m_c3t3, e, m_cell_selector)) continue; } @@ -369,9 +369,9 @@ private: const Subdomain_index s1 = f.first->subdomain_index(); const Subdomain_index s2 = mf.first->subdomain_index(); if (s1 != s2 - || get(fcmap, f) - || get(fcmap, mf) - || (m_c3t3_pbackup == NULL && f.first->is_facet_on_surface(f.second))) + || get(fcmap, f) + || get(fcmap, mf) + || (m_c3t3_pbackup == NULL && f.first->is_facet_on_surface(f.second))) { m_c3t3.add_to_complex(f, 1); @@ -411,8 +411,8 @@ private: } if (get(ecmap, CGAL::Tetrahedral_remeshing::make_vertex_pair(e)) - || nb_incident_subdomains(e, m_c3t3) > 2 - || nb_incident_surface_patches(e, m_c3t3) > 1) + || nb_incident_subdomains(e, m_c3t3) > 2 + || nb_incident_surface_patches(e, m_c3t3) > 1) { m_c3t3.add_to_complex(e, 1); @@ -441,7 +441,7 @@ private: ++vit) { if ( vit->in_dimension() == 0 - || nb_incident_complex_edges(vit, m_c3t3) > 2) + || nb_incident_complex_edges(vit, m_c3t3) > 2) { if(!m_c3t3.is_in_complex(vit)) m_c3t3.add_to_complex(vit, ++corner_id); @@ -514,8 +514,8 @@ public: #ifdef CGAL_TETRAHEDRAL_REMESHING_VERBOSE std::cout << "# Iteration " << it_nb << " done : " - << tr().number_of_vertices() - << " vertices #" << std::endl; + << tr().number_of_vertices() + << " vertices #" << std::endl; #endif #ifdef CGAL_DUMP_REMESHING_STEPS std::ostringstream ossi; @@ -534,8 +534,8 @@ public: #ifdef CGAL_TETRAHEDRAL_REMESHING_VERBOSE std::cout << "# Iteration " << it_nb << " (flip and smooth only) done : " - << tr().number_of_vertices() - << " vertices #" << std::endl; + << tr().number_of_vertices() + << " vertices #" << std::endl; #endif #ifdef CGAL_DUMP_REMESHING_STEPS std::ostringstream ossi; diff --git a/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/tetrahedral_remeshing_helpers.h b/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/tetrahedral_remeshing_helpers.h index cc971d0c873..670034edbc2 100644 --- a/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/tetrahedral_remeshing_helpers.h +++ b/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/tetrahedral_remeshing_helpers.h @@ -152,7 +152,7 @@ std::pair make_vertex_pair(const Vh v1, const Vh v2) template std::pair - make_vertex_pair(const typename Tr::Edge& e) +make_vertex_pair(const typename Tr::Edge& e) { typedef typename Tr::Vertex_handle Vertex_handle; Vertex_handle v1 = e.first->vertex(e.second); @@ -200,10 +200,10 @@ bool is_well_oriented(const Tr& tr, const typename Tr::Vertex_handle v3) { return CGAL::POSITIVE == tr.geom_traits().orientation_3_object()( - point(v0->point()), - point(v1->point()), - point(v2->point()), - point(v3->point())); + point(v0->point()), + point(v1->point()), + point(v2->point()), + point(v3->point())); } template @@ -212,13 +212,13 @@ bool is_boundary(const C3T3& c3t3, const CellSelector& cell_selector) { return c3t3.is_in_complex(f) - || cell_selector(f.first) != cell_selector(f.first->neighbor(f.second)); + || cell_selector(f.first) != cell_selector(f.first->neighbor(f.second)); } template bool is_boundary(const C3T3& c3t3, - const typename C3T3::Triangulation::Edge& e, - CellSelector cell_selector) + const typename C3T3::Triangulation::Edge& e, + CellSelector cell_selector) { typedef typename C3T3::Triangulation Tr; typedef typename Tr::Facet_circulator Facet_circulator; @@ -240,9 +240,9 @@ bool is_boundary(const C3T3& c3t3, template bool is_boundary_edge(const typename C3t3::Vertex_handle& v0, - const typename C3t3::Vertex_handle& v1, - const C3t3& c3t3, - const CellSelector& cell_selector) + const typename C3t3::Vertex_handle& v1, + const C3t3& c3t3, + const CellSelector& cell_selector) { typedef typename C3t3::Edge Edge; typedef typename C3t3::Cell_handle Cell_handle; @@ -257,8 +257,8 @@ bool is_boundary_edge(const typename C3t3::Vertex_handle& v0, template bool is_boundary_vertex(const typename C3t3::Vertex_handle& v, - const C3t3& c3t3, - CellSelector cell_selector) + const C3t3& c3t3, + CellSelector cell_selector) { typedef typename C3t3::Facet Facet; std::vector facets; @@ -276,7 +276,7 @@ bool is_boundary_vertex(const typename C3t3::Vertex_handle& v, template typename C3t3::Surface_patch_index surface_patch_index(const typename C3t3::Vertex_handle v, - const C3t3& c3t3) + const C3t3& c3t3) { typedef typename C3t3::Surface_patch_index Surface_patch_index; typedef typename C3t3::Facet Facet; @@ -309,8 +309,8 @@ bool is_edge_in_complex(const typename C3t3::Vertex_handle& v0, template OutputIterator incident_subdomains(const typename C3t3::Vertex_handle v, - const C3t3& c3t3, - OutputIterator oit) + const C3t3& c3t3, + OutputIterator oit) { typedef typename C3t3::Triangulation::Cell_handle Cell_handle; std::vector cells; @@ -324,8 +324,8 @@ OutputIterator incident_subdomains(const typename C3t3::Vertex_handle v, template OutputIterator incident_subdomains(const typename C3t3::Edge& e, - const C3t3& c3t3, - OutputIterator oit) + const C3t3& c3t3, + OutputIterator oit) { typedef typename C3t3::Triangulation::Cell_circulator Cell_circulator; @@ -362,7 +362,7 @@ OutputIterator incident_surface_patches(const typename C3t3::Edge& e, template std::size_t nb_incident_subdomains(const typename C3t3::Vertex_handle v, - const C3t3& c3t3) + const C3t3& c3t3) { typedef typename C3t3::Subdomain_index Subdomain_index; @@ -374,7 +374,7 @@ std::size_t nb_incident_subdomains(const typename C3t3::Vertex_handle v, template std::size_t nb_incident_subdomains(const typename C3t3::Edge& e, - const C3t3& c3t3) + const C3t3& c3t3) { typedef typename C3t3::Subdomain_index Subdomain_index; @@ -398,7 +398,7 @@ std::size_t nb_incident_surface_patches(const typename C3t3::Edge& e, template std::size_t nb_incident_complex_edges(const typename C3t3::Vertex_handle v, - const C3t3& c3t3) + const C3t3& c3t3) { typedef typename C3t3::Edge Edge; boost::unordered_set edges; @@ -416,8 +416,8 @@ std::size_t nb_incident_complex_edges(const typename C3t3::Vertex_handle v, template bool is_feature(const typename C3t3::Vertex_handle v, - const typename C3t3::Vertex_handle neighbor, - const C3t3& c3t3) + const typename C3t3::Vertex_handle neighbor, + const C3t3& c3t3) { typename C3t3::Cell_handle ch; int i0, i1; @@ -463,7 +463,7 @@ bool is_feature(const typename C3t3::Vertex_handle v, const C3t3& c3t3) */ template bool is_on_convex_hull(const typename C3t3::Vertex_handle v, - const C3t3& c3t3) + const C3t3& c3t3) { if (v == c3t3.triangulation().infinite_vertex()) return true; @@ -488,7 +488,7 @@ bool is_on_convex_hull(const typename C3t3::Vertex_handle v, */ template bool is_on_convex_hull(const typename C3t3::Edge & edge, - const C3t3& c3t3) + const C3t3& c3t3) { typedef typename C3t3::Triangulation::Cell_circulator Cell_circulator; Cell_circulator circ = c3t3.triangulation().incident_cells(edge); @@ -527,8 +527,8 @@ bool is_outside(const typename C3t3::Edge & edge, template bool is_selected(const typename C3t3::Vertex_handle v, - const C3t3& c3t3, - CellSelector cell_selector) + const C3t3& c3t3, + CellSelector cell_selector) { typedef typename C3t3::Triangulation::Cell_handle Cell_handle; @@ -545,8 +545,8 @@ bool is_selected(const typename C3t3::Vertex_handle v, template bool is_internal(const typename C3t3::Edge& edge, - const C3t3& c3t3, - CellSelector cell_selector) + const C3t3& c3t3, + CellSelector cell_selector) { const typename C3t3::Vertex_handle vs = edge.first->vertex(edge.second); const typename C3t3::Vertex_handle vt = edge.first->vertex(edge.third); @@ -565,8 +565,8 @@ bool is_internal(const typename C3t3::Edge& edge, if (!cell_selector(circ)) return false; if (c3t3.is_in_complex( - circ, - CGAL::Triangulation_utils_3::next_around_edge(circ->index(vs), circ->index(vt)))) + circ, + CGAL::Triangulation_utils_3::next_around_edge(circ->index(vs), circ->index(vt)))) return false; } while (++circ != done); @@ -598,8 +598,8 @@ typename Gt::Vector_3 normal(const Facet& f, const Gt& gt) std::swap(p0, p1); Vector_3 n = gt.construct_cross_product_vector_3_object()( - gt.construct_vector_3_object()(p1, p2), - gt.construct_vector_3_object()(p1, p0)); + gt.construct_vector_3_object()(p1, p2), + gt.construct_vector_3_object()(p1, p0)); //cross-product(AB, AC)'s norm is the area of the parallelogram //formed by these 2 vectors. @@ -609,13 +609,13 @@ typename Gt::Vector_3 normal(const Facet& f, const Gt& gt) template OutputIterator get_internal_edges(const C3t3& c3t3, - CellSelector cell_selector, - OutputIterator oit)/*holds Edges*/ + CellSelector cell_selector, + OutputIterator oit)/*holds Edges*/ { for (typename C3t3::Triangulation::Finite_edges_iterator - eit = c3t3.triangulation().finite_edges_begin(); - eit != c3t3.triangulation().finite_edges_end(); - ++eit) + eit = c3t3.triangulation().finite_edges_begin(); + eit != c3t3.triangulation().finite_edges_end(); + ++eit) { const typename C3t3::Edge& e = *eit; if (is_internal(e, c3t3, cell_selector)) @@ -662,7 +662,7 @@ bool topology_test(const typename C3t3::Edge& edge, if (vi != v0 && vi != v1 && nb_incident_subdomains(vi, c3t3) > 1) { if (is_edge_in_complex(v0, vi, c3t3) - && is_edge_in_complex(v1, vi, c3t3)) + && is_edge_in_complex(v1, vi, c3t3)) return false; } } @@ -672,8 +672,8 @@ bool topology_test(const typename C3t3::Edge& edge, const Cell_handle circ = f.first; const int i = f.second; if (is_boundary(c3t3, Edge(circ, (i + 1) % 4, (i + 2) % 4), cell_selector) - && is_boundary(c3t3, Edge(circ, (i + 2) % 4, (i + 3) % 4), cell_selector) - && is_boundary(c3t3, Edge(circ, (i + 3) % 4, (i + 1) % 4), cell_selector)) + && is_boundary(c3t3, Edge(circ, (i + 2) % 4, (i + 3) % 4), cell_selector) + && is_boundary(c3t3, Edge(circ, (i + 3) % 4, (i + 1) % 4), cell_selector)) return false; } } while (++fcirc != fdone); @@ -738,7 +738,7 @@ void get_edge_info(const typename C3t3::Edge& edge, if (nb_si_v0 > nb_si_v1) { if (!c3t3.is_in_complex(v1)) - update_v1 = true; + update_v1 = true; } else if (nb_si_v1 > nb_si_v0) { if (!c3t3.is_in_complex(v0)) @@ -828,15 +828,15 @@ Subdomain_relation compare_subdomains(const typename C3t3::Vertex_handle v0, else { std::vector - intersection((std::min)(subdomains_v0.size(), subdomains_v1.size()), -1); + intersection((std::min)(subdomains_v0.size(), subdomains_v1.size()), -1); typename std::vector::iterator - end_it = std::set_intersection(subdomains_v0.begin(), subdomains_v0.end(), - subdomains_v1.begin(), subdomains_v1.end(), - intersection.begin()); + end_it = std::set_intersection(subdomains_v0.begin(), subdomains_v0.end(), + subdomains_v1.begin(), subdomains_v1.end(), + intersection.begin()); std::ptrdiff_t intersection_size = (end_it - intersection.begin()); if (subdomains_v0.size() > subdomains_v1.size() - && intersection_size == std::ptrdiff_t(subdomains_v1.size())) + && intersection_size == std::ptrdiff_t(subdomains_v1.size())) { return INCLUDES; } @@ -898,7 +898,7 @@ void dump_polylines(const CellRange& cells, const char* filename) if (!ofs) return; for (typename CellRange::const_iterator it = cells.begin(); - it != cells.end(); ++it) + it != cells.end(); ++it) { for (int i = 0; i < 4; ++i) dump_facet(std::make_pair(*it, i), ofs); @@ -932,7 +932,7 @@ bool are_cell_orientations_valid(const Tr& tr) if (!facets.empty()) { std::cerr << "Warning : there are inverted cells!\n" - << "\tSee cells_with_negative_volume.polylines.txt" << std::endl; + << "\tSee cells_with_negative_volume.polylines.txt" << std::endl; dump_facets(facets, "cells_with_negative_volume.polylines.txt"); } return facets.empty(); @@ -952,7 +952,7 @@ void dump_surface_off(const Tr& tr, const char* filename) std::size_t nbf = 0; int index = 0; for (Finite_facets_iterator fit = tr.finite_facets_begin(); - fit != tr.finite_facets_end(); ++fit) + fit != tr.finite_facets_end(); ++fit) { Cell_handle c = fit->first; int i = fit->second; @@ -976,7 +976,7 @@ void dump_surface_off(const Tr& tr, const char* filename) // write vertices for (typename Bimap_t::right_iterator vit = vertices.right.begin(); - vit != vertices.right.end(); ++vit) + vit != vertices.right.end(); ++vit) { ofs << point(vit->second->point()) << std::endl; } @@ -984,15 +984,15 @@ void dump_surface_off(const Tr& tr, const char* filename) //write facets std::size_t nbf_print = 0; for (Finite_facets_iterator fit = tr.finite_facets_begin(); - fit != tr.finite_facets_end(); ++fit) + fit != tr.finite_facets_end(); ++fit) { Cell_handle c = fit->first; int i = fit->second; if (tr.is_infinite(c) || tr.is_infinite(c->neighbor(i))) { ofs << "3 " << vertices.left.at(c->vertex((i + 1) % 4)) << " " - << vertices.left.at(c->vertex((i + 2) % 4)) << " " - << vertices.left.at(c->vertex((i + 3) % 4)) << std::endl; + << vertices.left.at(c->vertex((i + 2) % 4)) << " " + << vertices.left.at(c->vertex((i + 3) % 4)) << std::endl; ++nbf_print; } } @@ -1016,37 +1016,37 @@ void dump_cells_off(const Tr& tr, const char* filename) ofs.precision(17); ofs << "OFF" << std::endl; ofs << tr.number_of_vertices() - << " " << tr.number_of_finite_facets() << " 0" << std::endl << std::endl; + << " " << tr.number_of_finite_facets() << " 0" << std::endl << std::endl; //collect and write vertices Bimap_t vertices; int index = 0; for (Finite_vertices_iterator vit = tr.finite_vertices_begin(); - vit != tr.finite_vertices_end(); ++vit) + vit != tr.finite_vertices_end(); ++vit) { vertices.left.insert(value_type(vit, index++)); ofs << vit->point().x() << " " - << vit->point().y() << " " - << vit->point().z() << std::endl; + << vit->point().y() << " " + << vit->point().z() << std::endl; } //write facets for (Finite_facets_iterator fit = tr.finite_facets_begin(); - fit != tr.finite_facets_end(); ++fit) + fit != tr.finite_facets_end(); ++fit) { Cell_handle c = fit->first; int i = fit->second; ofs << "3 " << vertices.left.at(c->vertex((i + 1) % 4)) << " " - << vertices.left.at(c->vertex((i + 2) % 4)) << " " - << vertices.left.at(c->vertex((i + 3) % 4)) << std::endl; + << vertices.left.at(c->vertex((i + 2) % 4)) << " " + << vertices.left.at(c->vertex((i + 3) % 4)) << std::endl; } ofs.close(); } template void dump_cells(const CellRange& cells, - const IndexRange& indices, - const char* filename) + const IndexRange& indices, + const char* filename) { typedef typename Tr::Vertex_handle Vertex_handle; typedef typename Tr::Point Point; @@ -1059,8 +1059,8 @@ void dump_cells(const CellRange& cells, Bimap_t vertices; int index = 1; for (typename CellRange::const_iterator cit = cells.begin(); - cit != cells.end(); - ++cit) + cit != cells.end(); + ++cit) { for (int i = 0; i < 4; ++i) { @@ -1077,8 +1077,8 @@ void dump_cells(const CellRange& cells, ofs << "Dimension 3" << std::endl; ofs << "Vertices" << std::endl << vertices.size() << std::endl; for (typename Bimap_t::right_const_iterator vit = vertices.right.begin(); - vit != vertices.right.end(); - ++vit) + vit != vertices.right.end(); + ++vit) { const Point& p = vit->second->point(); ofs << p.x() << " " << p.y() << " " << p.z() << " 2" << std::endl; @@ -1086,13 +1086,13 @@ void dump_cells(const CellRange& cells, ofs << "Tetrahedra " << std::endl << cells.size() << std::endl; typename IndexRange::const_iterator iit = indices.begin(); for (typename CellRange::const_iterator cit = cells.begin(); - cit != cells.end(); - ++cit) + cit != cells.end(); + ++cit) { ofs << vertices.left.at((*cit)->vertex(0)) - << " " << vertices.left.at((*cit)->vertex(1)) - << " " << vertices.left.at((*cit)->vertex(2)) - << " " << vertices.left.at((*cit)->vertex(3)); + << " " << vertices.left.at((*cit)->vertex(1)) + << " " << vertices.left.at((*cit)->vertex(2)) + << " " << vertices.left.at((*cit)->vertex(3)); if (iit == indices.end()) ofs << " 1" << std::endl; @@ -1120,7 +1120,7 @@ void dump_cells_in_complex(const Tr& tr, const char* filename) std::vector indices; for (typename Tr::Finite_cells_iterator cit = tr.finite_cells_begin(); - cit != tr.finite_cells_end(); ++cit) + cit != tr.finite_cells_end(); ++cit) { if (cit->subdomain_index() > 0) { @@ -1146,7 +1146,7 @@ void dump_facets_in_complex(const C3t3& c3t3, const char* filename) std::size_t nbf = 0; int index = 0; for (Facets_in_complex_iterator fit = c3t3.facets_in_complex_begin(); - fit != c3t3.facets_in_complex_end(); ++fit) + fit != c3t3.facets_in_complex_end(); ++fit) { Cell_handle c = fit->first; int i = fit->second; @@ -1168,7 +1168,7 @@ void dump_facets_in_complex(const C3t3& c3t3, const char* filename) // write vertices for (typename Bimap_t::right_iterator vit = vertices.right.begin(); - vit != vertices.right.end(); ++vit) + vit != vertices.right.end(); ++vit) { ofs << point(vit->second->point()) << std::endl; } @@ -1176,13 +1176,13 @@ void dump_facets_in_complex(const C3t3& c3t3, const char* filename) //write facets std::size_t nbf_print = 0; for (Facets_in_complex_iterator fit = c3t3.facets_in_complex_begin(); - fit != c3t3.facets_in_complex_end(); ++fit) + fit != c3t3.facets_in_complex_end(); ++fit) { Cell_handle c = fit->first; int i = fit->second; ofs << "3 " << vertices.left.at(c->vertex((i + 1) % 4)) << " " - << vertices.left.at(c->vertex((i + 2) % 4)) << " " - << vertices.left.at(c->vertex((i + 3) % 4)) << std::endl; + << vertices.left.at(c->vertex((i + 2) % 4)) << " " + << vertices.left.at(c->vertex((i + 3) % 4)) << std::endl; ++nbf_print; } CGAL_assertion(nbf == nbf_print); @@ -1196,21 +1196,21 @@ void dump_edges_in_complex(const C3T3& c3t3, const char* filename) std::ofstream ofs(filename); ofs.precision(17); for (typename C3T3::Edges_in_complex_iterator eit = c3t3.edges_in_complex_begin(); - eit != c3t3.edges_in_complex_end(); ++eit) + eit != c3t3.edges_in_complex_end(); ++eit) { const typename C3T3::Edge& e = *eit; ofs << "2 " - << point(e.first->vertex(e.second)->point()) << " " - << point(e.first->vertex(e.third)->point()) << "\n"; + << point(e.first->vertex(e.second)->point()) << " " + << point(e.first->vertex(e.third)->point()) << "\n"; } ofs.close(); } template void dump_cells_with_small_dihedral_angle(const Tr& tr, - const double angle_bound, - CellSelector cell_select, - const char* filename) + const double angle_bound, + CellSelector cell_select, + const char* filename) { typedef typename Tr::Cell_handle Cell_handle; typedef typename Tr::Cell::Subdomain_index Subdomain_index; @@ -1222,8 +1222,8 @@ void dump_cells_with_small_dihedral_angle(const Tr& tr, { Cell_handle c = cit; if ( c->subdomain_index() != Subdomain_index() - && cell_select(c) - && min_dihedral_angle(tr, c) < angle_bound) + && cell_select(c) + && min_dihedral_angle(tr, c) < angle_bound) { cells.push_back(c); @@ -1241,9 +1241,9 @@ void dump_vertices_by_dimension(const Tr& tr, const char* prefix) std::vector< std::vector > vertices_per_dimension(4); for (typename Tr::Finite_vertices_iterator - vit = tr.finite_vertices_begin(); - vit != tr.finite_vertices_end(); - ++vit) + vit = tr.finite_vertices_begin(); + vit != tr.finite_vertices_end(); + ++vit) { if (vit->in_dimension() == -1) continue;//far point @@ -1283,7 +1283,7 @@ void dump_triangulation_cells(const Tr& tr, const char* filename) std::vector indices(tr.number_of_finite_cells()); int i = 0; for (typename Tr::Finite_cells_iterator cit = tr.finite_cells_begin(); - cit != tr.finite_cells_end(); ++cit) + cit != tr.finite_cells_end(); ++cit) { cells[i] = cit; indices[i++] = cit->subdomain_index(); diff --git a/Tetrahedral_remeshing/include/CGAL/tetrahedral_remeshing.h b/Tetrahedral_remeshing/include/CGAL/tetrahedral_remeshing.h index ccaeb8efc88..205a4fa69a1 100644 --- a/Tetrahedral_remeshing/include/CGAL/tetrahedral_remeshing.h +++ b/Tetrahedral_remeshing/include/CGAL/tetrahedral_remeshing.h @@ -150,12 +150,12 @@ void tetrahedral_adaptive_remeshing( using parameters::get_parameter; bool remesh_surfaces = choose_parameter(get_parameter(np, internal_np::remesh_boundaries), - true); + true); bool protect = !remesh_surfaces; // bool adaptive = choose_parameter(get_parameter(np, internal_np::adaptive_size), // false); std::size_t max_it = choose_parameter(get_parameter(np, internal_np::number_of_iterations), - 1); + 1); typedef typename internal_np::Lookup_named_param_def < internal_np::cell_selector_t, @@ -164,7 +164,7 @@ void tetrahedral_adaptive_remeshing( > ::type SelectionFunctor; SelectionFunctor cell_select = choose_parameter(get_parameter(np, internal_np::cell_selector), - Tetrahedral_remeshing::internal::All_cells_selected()); + Tetrahedral_remeshing::internal::All_cells_selected()); typedef std::pair Edge_vv; typedef Tetrahedral_remeshing::internal::No_constraint_pmap No_edge; @@ -174,7 +174,7 @@ void tetrahedral_adaptive_remeshing( No_edge//default > ::type ECMap; ECMap ecmap = choose_parameter(get_parameter(np, internal_np::edge_is_constrained), - No_edge()); + No_edge()); typedef typename Tr::Facet Facet; typedef Tetrahedral_remeshing::internal::No_constraint_pmap No_facet; @@ -184,7 +184,7 @@ void tetrahedral_adaptive_remeshing( No_facet//default > ::type FCMap; FCMap fcmap = choose_parameter(get_parameter(np, internal_np::facet_is_constrained), - No_facet()); + No_facet()); typedef typename internal_np::Lookup_named_param_def < internal_np::remeshing_visitor_t, @@ -193,13 +193,13 @@ void tetrahedral_adaptive_remeshing( > ::type Visitor; Visitor visitor = choose_parameter(get_parameter(np, internal_np::remeshing_visitor), - Tetrahedral_remeshing::internal::Default_remeshing_visitor()); + Tetrahedral_remeshing::internal::Default_remeshing_visitor()); #ifdef CGAL_TETRAHEDRAL_REMESHING_VERBOSE std::cout << "Tetrahedral remeshing (" - << "nb_iter = " << max_it << ", " - << "protect = " << std::boolalpha << protect - << ")" << std::endl; + << "nb_iter = " << max_it << ", " + << "protect = " << std::boolalpha << protect + << ")" << std::endl; std::cout << "Init tetrahedral remeshing..."; std::cout.flush(); @@ -239,7 +239,7 @@ void tetrahedral_adaptive_remeshing( const double& target_edge_length) { tetrahedral_adaptive_remeshing(tr, target_edge_length, - CGAL::parameters::all_default()); + CGAL::parameters::all_default()); } /////////////////////////////////////////////////// @@ -250,9 +250,9 @@ template void tetrahedral_adaptive_remeshing( - CGAL::Mesh_complex_3_in_triangulation_3& c3t3, - const double& target_edge_length, - const NamedParameters& np) + CGAL::Mesh_complex_3_in_triangulation_3& c3t3, + const double& target_edge_length, + const NamedParameters& np) { tetrahedral_adaptive_remeshing( c3t3, @@ -265,9 +265,9 @@ template void tetrahedral_adaptive_remeshing( - CGAL::Mesh_complex_3_in_triangulation_3& c3t3, - const float& target_edge_length, - const NamedParameters& np) + CGAL::Mesh_complex_3_in_triangulation_3& c3t3, + const float& target_edge_length, + const NamedParameters& np) { tetrahedral_adaptive_remeshing( c3t3, @@ -280,8 +280,8 @@ template void tetrahedral_adaptive_remeshing( - CGAL::Mesh_complex_3_in_triangulation_3& c3t3, - const double& target_edge_length) + CGAL::Mesh_complex_3_in_triangulation_3& c3t3, + const double& target_edge_length) { return tetrahedral_adaptive_remeshing(c3t3, target_edge_length, CGAL::parameters::all_default()); @@ -292,9 +292,9 @@ template void tetrahedral_adaptive_remeshing( - CGAL::Mesh_complex_3_in_triangulation_3& c3t3, - const SizingFunction& sizing, - const NamedParameters& np) + CGAL::Mesh_complex_3_in_triangulation_3& c3t3, + const SizingFunction& sizing, + const NamedParameters& np) { CGAL_assertion(c3t3.triangulation().tds().is_valid(true)); @@ -302,67 +302,67 @@ void tetrahedral_adaptive_remeshing( using parameters::choose_parameter; bool remesh_surfaces = choose_parameter(get_parameter(np, internal_np::remesh_boundaries), - true); + true); bool protect = !remesh_surfaces; std::size_t max_it = choose_parameter(get_parameter(np, internal_np::number_of_iterations), 1); typedef typename internal_np::Lookup_named_param_def < - internal_np::cell_selector_t, - NamedParameters, - Tetrahedral_remeshing::internal::All_cells_selected//default - > ::type SelectionFunctor; + internal_np::cell_selector_t, + NamedParameters, + Tetrahedral_remeshing::internal::All_cells_selected//default + > ::type SelectionFunctor; SelectionFunctor cell_select = choose_parameter(get_parameter(np, internal_np::cell_selector), - Tetrahedral_remeshing::internal::All_cells_selected()); + Tetrahedral_remeshing::internal::All_cells_selected()); typedef std::pair Edge_vv; typedef Tetrahedral_remeshing::internal::No_constraint_pmap No_edge; typedef typename internal_np::Lookup_named_param_def < - internal_np::edge_is_constrained_t, - NamedParameters, - No_edge//default - > ::type ECMap; + internal_np::edge_is_constrained_t, + NamedParameters, + No_edge//default + > ::type ECMap; ECMap ecmap = choose_parameter(get_parameter(np, internal_np::edge_is_constrained), - No_edge()); + No_edge()); typedef typename Tr::Facet Facet; typedef Tetrahedral_remeshing::internal::No_constraint_pmap No_facet; typedef typename internal_np::Lookup_named_param_def < - internal_np::facet_is_constrained_t, - NamedParameters, - No_facet//default - > ::type FCMap; + internal_np::facet_is_constrained_t, + NamedParameters, + No_facet//default + > ::type FCMap; FCMap fcmap = choose_parameter(get_parameter(np, internal_np::facet_is_constrained), - No_facet()); + No_facet()); typedef typename internal_np::Lookup_named_param_def < - internal_np::remeshing_visitor_t, - NamedParameters, - Tetrahedral_remeshing::internal::Default_remeshing_visitor - > ::type Visitor; + internal_np::remeshing_visitor_t, + NamedParameters, + Tetrahedral_remeshing::internal::Default_remeshing_visitor + > ::type Visitor; Visitor visitor = choose_parameter(get_parameter(np, internal_np::remeshing_visitor), - Tetrahedral_remeshing::internal::Default_remeshing_visitor()); + Tetrahedral_remeshing::internal::Default_remeshing_visitor()); #ifdef CGAL_TETRAHEDRAL_REMESHING_VERBOSE std::cout << "Tetrahedral remeshing (" - << "nb_iter = " << max_it << ", " - << "protect = " << std::boolalpha << protect - << ")" << std::endl; + << "nb_iter = " << max_it << ", " + << "protect = " << std::boolalpha << protect + << ")" << std::endl; std::cout << "Init tetrahedral remeshing..."; std::cout.flush(); #endif typedef Tetrahedral_remeshing::internal::Adaptive_remesher< - Tr, SizingFunction, ECMap, FCMap, SelectionFunctor, - Visitor, - CornerIndex, CurveIndex + Tr, SizingFunction, ECMap, FCMap, SelectionFunctor, + Visitor, + CornerIndex, CurveIndex > Remesher; Remesher remesher(c3t3, sizing, protect - , ecmap, fcmap - , cell_select - , visitor); + , ecmap, fcmap + , cell_select + , visitor); #ifdef CGAL_TETRAHEDRAL_REMESHING_VERBOSE std::cout << "done." << std::endl; From 825f77baaa39e3d8a7d0249530762792acf098e4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9bastien=20Loriot?= Date: Fri, 10 Apr 2020 14:14:30 +0200 Subject: [PATCH 236/568] add license include directives --- .../CGAL/license/Tetrahedral_remeshing.h | 54 +++++++++++++++++++ .../include/CGAL/license/gpl_package_list.txt | 1 + .../Remeshing_cell_base.h | 2 + .../Remeshing_triangulation_3.h | 3 +- .../Remeshing_vertex_base.h | 2 + .../CGAL/Tetrahedral_remeshing/Sizing_field.h | 2 + .../Uniform_sizing_field.h | 2 + .../Tetrahedral_remeshing/internal/FMLS.h | 3 +- .../internal/collapse_short_edges.h | 2 + .../internal/compute_c3t3_statistics.h | 8 +-- .../internal/flip_edges.h | 3 +- .../internal/smooth_vertices.h | 2 + .../internal/split_long_edges.h | 2 + .../tetrahedral_adaptive_remeshing_impl.h | 2 + .../internal/tetrahedral_remeshing_helpers.h | 2 + .../include/CGAL/tetrahedral_remeshing.h | 2 + 16 files changed, 86 insertions(+), 6 deletions(-) create mode 100644 Installation/include/CGAL/license/Tetrahedral_remeshing.h diff --git a/Installation/include/CGAL/license/Tetrahedral_remeshing.h b/Installation/include/CGAL/license/Tetrahedral_remeshing.h new file mode 100644 index 00000000000..10c8d9e138d --- /dev/null +++ b/Installation/include/CGAL/license/Tetrahedral_remeshing.h @@ -0,0 +1,54 @@ +// Copyright (c) 2016 GeometryFactory SARL (France). +// All rights reserved. +// +// This file is part of CGAL (www.cgal.org) +// +// $URL$ +// $Id$ +// SPDX-License-Identifier: LGPL-3.0-or-later OR LicenseRef-Commercial +// +// Author(s) : Andreas Fabri +// +// Warning: this file is generated, see include/CGAL/licence/README.md + +#ifndef CGAL_LICENSE_TETRAHEDRAL_REMESHING_H +#define CGAL_LICENSE_TETRAHEDRAL_REMESHING_H + +#include +#include + +#ifdef CGAL_TETRAHEDRAL_REMESHING_COMMERCIAL_LICENSE + +# if CGAL_TETRAHEDRAL_REMESHING_COMMERCIAL_LICENSE < CGAL_RELEASE_DATE + +# if defined(CGAL_LICENSE_WARNING) + + CGAL_pragma_warning("Your commercial license for CGAL does not cover " + "this release of the Tetrahedral Remeshing package.") +# endif + +# ifdef CGAL_LICENSE_ERROR +# error "Your commercial license for CGAL does not cover this release \ + of the Tetrahedral Remeshing package. \ + You get this error, as you defined CGAL_LICENSE_ERROR." +# endif // CGAL_LICENSE_ERROR + +# endif // CGAL_TETRAHEDRAL_REMESHING_COMMERCIAL_LICENSE < CGAL_RELEASE_DATE + +#else // no CGAL_TETRAHEDRAL_REMESHING_COMMERCIAL_LICENSE + +# if defined(CGAL_LICENSE_WARNING) + CGAL_pragma_warning("\nThe macro CGAL_TETRAHEDRAL_REMESHING_COMMERCIAL_LICENSE is not defined." + "\nYou use the CGAL Tetrahedral Remeshing package under " + "the terms of the GPLv3+.") +# endif // CGAL_LICENSE_WARNING + +# ifdef CGAL_LICENSE_ERROR +# error "The macro CGAL_TETRAHEDRAL_REMESHING_COMMERCIAL_LICENSE is not defined.\ + You use the CGAL Tetrahedral Remeshing package under the terms of \ + the GPLv3+. You get this error, as you defined CGAL_LICENSE_ERROR." +# endif // CGAL_LICENSE_ERROR + +#endif // no CGAL_TETRAHEDRAL_REMESHING_COMMERCIAL_LICENSE + +#endif // CGAL_LICENSE_TETRAHEDRAL_REMESHING_H diff --git a/Installation/include/CGAL/license/gpl_package_list.txt b/Installation/include/CGAL/license/gpl_package_list.txt index c82b04d0784..0eea39a8779 100644 --- a/Installation/include/CGAL/license/gpl_package_list.txt +++ b/Installation/include/CGAL/license/gpl_package_list.txt @@ -92,3 +92,4 @@ Triangulation_3 3D Triangulations Triangulation dD Triangulations Visibility_2 2D Visibility Computation Voronoi_diagram_2 2D Voronoi Diagram Adaptor +Tetrahedral_remeshing Tetrahedral Remeshing diff --git a/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/Remeshing_cell_base.h b/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/Remeshing_cell_base.h index 5e2b2b88a77..db4324736f2 100644 --- a/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/Remeshing_cell_base.h +++ b/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/Remeshing_cell_base.h @@ -13,6 +13,8 @@ #ifndef CGAL_TET_ADAPTIVE_REMESHING_CELL_BASE_H #define CGAL_TET_ADAPTIVE_REMESHING_CELL_BASE_H +#include + #include namespace CGAL diff --git a/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/Remeshing_triangulation_3.h b/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/Remeshing_triangulation_3.h index 8cccebf078f..4252508dd1b 100644 --- a/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/Remeshing_triangulation_3.h +++ b/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/Remeshing_triangulation_3.h @@ -10,10 +10,11 @@ // // Author(s) : Jane Tournois, Noura Faraj - #ifndef CGAL_TETRAHEDRAL_REMESHING_TRIANGULATION_H #define CGAL_TETRAHEDRAL_REMESHING_TRIANGULATION_H +#include + #include #include diff --git a/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/Remeshing_vertex_base.h b/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/Remeshing_vertex_base.h index e55f14ba3b4..f03cbcc7ffc 100644 --- a/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/Remeshing_vertex_base.h +++ b/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/Remeshing_vertex_base.h @@ -13,6 +13,8 @@ #ifndef CGAL_TET_ADAPTIVE_REMESHING_VERTEX_BASE_H #define CGAL_TET_ADAPTIVE_REMESHING_VERTEX_BASE_H +#include + #include namespace CGAL diff --git a/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/Sizing_field.h b/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/Sizing_field.h index 446992acb3b..53448be56a8 100644 --- a/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/Sizing_field.h +++ b/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/Sizing_field.h @@ -13,6 +13,8 @@ #ifndef CGAL_SIZING_FIELD_H #define CGAL_SIZING_FIELD_H +#include + namespace CGAL { /*! diff --git a/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/Uniform_sizing_field.h b/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/Uniform_sizing_field.h index 6c3ae7126b4..59c7264f502 100644 --- a/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/Uniform_sizing_field.h +++ b/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/Uniform_sizing_field.h @@ -13,6 +13,8 @@ #ifndef CGAL_UNIFORM_SIZING_FIELD_H #define CGAL_UNIFORM_SIZING_FIELD_H +#include + #include namespace CGAL diff --git a/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/FMLS.h b/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/FMLS.h index 4d7152877fa..e635efde797 100644 --- a/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/FMLS.h +++ b/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/FMLS.h @@ -10,10 +10,11 @@ // // Author(s) : Jane Tournois, Noura Faraj - #ifndef CGAL_TETRAHEDRAL_REMESHING_FMLS_H #define CGAL_TETRAHEDRAL_REMESHING_FMLS_H +#include + // ------------------------------------------- // FMLS // A Fast Moving Least Square operator for 3D diff --git a/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/collapse_short_edges.h b/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/collapse_short_edges.h index 4732d6759a1..d60935b19a1 100644 --- a/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/collapse_short_edges.h +++ b/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/collapse_short_edges.h @@ -13,6 +13,8 @@ #ifndef CGAL_INTERNAL_COLLAPSE_SHORT_EDGES_H #define CGAL_INTERNAL_COLLAPSE_SHORT_EDGES_H +#include + #include #include #include diff --git a/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/compute_c3t3_statistics.h b/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/compute_c3t3_statistics.h index 13cdf08d36f..15474f84825 100644 --- a/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/compute_c3t3_statistics.h +++ b/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/compute_c3t3_statistics.h @@ -10,6 +10,11 @@ // // Author(s) : Jane Tournois, Noura Faraj +#ifndef CGAL_TR_INTERNAL_COMPUTE_C3T3_STATISTICS_H +#define CGAL_TR_INTERNAL_COMPUTE_C3T3_STATISTICS_H + +#include + #include #include #include @@ -19,9 +24,6 @@ #include -#ifndef CGAL_TR_INTERNAL_COMPUTE_C3T3_STATISTICS_H -#define CGAL_TR_INTERNAL_COMPUTE_C3T3_STATISTICS_H - namespace CGAL { namespace Tetrahedral_remeshing diff --git a/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/flip_edges.h b/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/flip_edges.h index 8f9dbf2c181..d441f452a0f 100644 --- a/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/flip_edges.h +++ b/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/flip_edges.h @@ -10,10 +10,11 @@ // // Author(s) : Jane Tournois, Noura Faraj - #ifndef CGAL_INTERNAL_FLIP_EDGES_H #define CGAL_INTERNAL_FLIP_EDGES_H +#include + #include #include diff --git a/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/smooth_vertices.h b/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/smooth_vertices.h index ed4e0a8785a..dceef9cb515 100644 --- a/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/smooth_vertices.h +++ b/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/smooth_vertices.h @@ -13,6 +13,8 @@ #ifndef CGAL_INTERNAL_SMOOTH_VERTICES_H #define CGAL_INTERNAL_SMOOTH_VERTICES_H +#include + #include #include diff --git a/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/split_long_edges.h b/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/split_long_edges.h index 0c3eb81ebe7..0a0c96e46ca 100644 --- a/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/split_long_edges.h +++ b/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/split_long_edges.h @@ -13,6 +13,8 @@ #ifndef CGAL_INTERNAL_SPLIT_LONG_EDGES_H #define CGAL_INTERNAL_SPLIT_LONG_EDGES_H +#include + #include #include #include diff --git a/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/tetrahedral_adaptive_remeshing_impl.h b/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/tetrahedral_adaptive_remeshing_impl.h index 5969470a1a9..1725c5ebf1e 100644 --- a/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/tetrahedral_adaptive_remeshing_impl.h +++ b/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/tetrahedral_adaptive_remeshing_impl.h @@ -13,6 +13,8 @@ #ifndef TETRAHEDRAL_REMESHING_IMPL_H #define TETRAHEDRAL_REMESHING_IMPL_H +#include + #ifdef CGAL_TETRAHEDRAL_REMESHING_VERBOSE_PROGRESS #define CGAL_TETRAHEDRAL_REMESHING_VERBOSE #endif diff --git a/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/tetrahedral_remeshing_helpers.h b/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/tetrahedral_remeshing_helpers.h index 670034edbc2..524120bf424 100644 --- a/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/tetrahedral_remeshing_helpers.h +++ b/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/tetrahedral_remeshing_helpers.h @@ -13,6 +13,8 @@ #ifndef CGAL_INTERNAL_TET_REMESHING_HELPERS_H #define CGAL_INTERNAL_TET_REMESHING_HELPERS_H +#include + #include #include diff --git a/Tetrahedral_remeshing/include/CGAL/tetrahedral_remeshing.h b/Tetrahedral_remeshing/include/CGAL/tetrahedral_remeshing.h index 205a4fa69a1..3db4021a856 100644 --- a/Tetrahedral_remeshing/include/CGAL/tetrahedral_remeshing.h +++ b/Tetrahedral_remeshing/include/CGAL/tetrahedral_remeshing.h @@ -13,6 +13,8 @@ #ifndef TETRAHEDRAL_REMESHING_H #define TETRAHEDRAL_REMESHING_H +#include + #include #include From 139ef738c46eec786f2bd2db0928841367fd7e69 Mon Sep 17 00:00:00 2001 From: Jane Tournois Date: Fri, 10 Apr 2020 14:56:36 +0200 Subject: [PATCH 237/568] remove member variables that are used only once --- .../CGAL/Tetrahedral_remeshing/internal/FMLS.h | 17 ++++------------- 1 file changed, 4 insertions(+), 13 deletions(-) diff --git a/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/FMLS.h b/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/FMLS.h index e635efde797..4f6712a1e9f 100644 --- a/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/FMLS.h +++ b/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/FMLS.h @@ -347,11 +347,8 @@ private: { public: Grid() - { - cellSize = 1.f; - LUTSize = 0; - indicesSize = 0; - } + : cellSize(1.f) + {} ~Grid() { clear(); @@ -377,7 +374,7 @@ private: } for (unsigned int i = 0; i < 3; i++) res[i] = (unsigned int)ceil((minMax[3 + i] - minMax[i]) / cellSize); - LUTSize = res[0] * res[1] * res[2]; + unsigned int LUTSize = res[0] * res[1] * res[2]; LUT.resize(LUTSize); LUT.assign(LUTSize, 0); @@ -390,7 +387,7 @@ private: nonEmptyCells++; LUT[index]++; } - indicesSize = PNSize + nonEmptyCells; + unsigned int indicesSize = PNSize + nonEmptyCells; indices.reserve(indicesSize); indices.assign(indicesSize, 0); @@ -424,8 +421,6 @@ private: void clear() { cellSize = 1.f; - LUTSize = 0; - indicesSize = 0; } // Accessors @@ -435,7 +430,6 @@ private: inline float getCellSize() const { return cellSize; } inline std::vector& getLUT() { return LUT; } inline const std::vector& getLUT() const { return LUT; } - inline unsigned int getLUTSize() const { return LUTSize; } inline unsigned int getLUTIndex(unsigned int i, unsigned int j, unsigned int k) const @@ -469,7 +463,6 @@ private: } inline std::vector& getIndices() { return indices; } inline const std::vector& getIndices() const { return indices; } - inline unsigned int getIndicesSize() const { return indicesSize; } inline unsigned int getCellIndicesSize(unsigned int i, unsigned int j, unsigned int k) const { @@ -486,9 +479,7 @@ private: std::array minMax; float cellSize; std::array res; - unsigned int LUTSize; std::vector LUT; // 3D Index Look-Up Table - unsigned int indicesSize; std::vector indices; // 3D Grid data }; From de568c718bc804caa9f4749a7405b494492fb9bf Mon Sep 17 00:00:00 2001 From: Jane Tournois Date: Fri, 10 Apr 2020 16:14:41 +0200 Subject: [PATCH 238/568] use range iterators --- .../tetrahedral_adaptive_remeshing_impl.h | 28 +++++-------------- 1 file changed, 7 insertions(+), 21 deletions(-) diff --git a/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/tetrahedral_adaptive_remeshing_impl.h b/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/tetrahedral_adaptive_remeshing_impl.h index 1725c5ebf1e..48796886503 100644 --- a/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/tetrahedral_adaptive_remeshing_impl.h +++ b/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/tetrahedral_adaptive_remeshing_impl.h @@ -332,10 +332,8 @@ private: #endif //tag cells - typedef typename Tr::Finite_cells_iterator Finite_cells_iterator; - for (Finite_cells_iterator cit = tr().finite_cells_begin(); - cit != tr().finite_cells_end(); - ++cit) + typedef typename Tr::Cell_handle Cell_handle; + for (Cell_handle cit : tr().finite_cell_handles()) { if (m_cell_selector(cit)) { @@ -360,13 +358,9 @@ private: } //tag facets - typedef typename Tr::Facet Facet; - typedef typename Tr::Finite_facets_iterator Finite_facets_iterator; - for (Finite_facets_iterator fit = tr().finite_facets_begin(); - fit != tr().finite_facets_end(); - ++fit) + typedef typename Tr::Facet Facet; + for (const Facet& f : tr().finite_facets()) { - const Facet f = *fit; const Facet mf = tr().mirror_facet(f); const Subdomain_index s1 = f.first->subdomain_index(); const Subdomain_index s2 = mf.first->subdomain_index(); @@ -394,14 +388,9 @@ private: #endif //tag edges - typedef typename Tr::Edge Edge; - typedef typename Tr::Finite_edges_iterator Finite_edges_iterator; - for (Finite_edges_iterator eit = tr().finite_edges_begin(); - eit != tr().finite_edges_end(); - ++eit) + typedef typename Tr::Edge Edge; + for (const Edge& e : tr().finite_edges()) { - const Edge& e = *eit; - if (m_c3t3.is_in_complex(e)) { CGAL_assertion(m_c3t3.in_dimension(e.first->vertex(e.second)) <= 1); @@ -436,11 +425,8 @@ private: #endif //tag vertices - typedef typename Tr::Finite_vertices_iterator Finite_vertices_iterator; unsigned int corner_id = 0; - for (Finite_vertices_iterator vit = tr().finite_vertices_begin(); - vit != tr().finite_vertices_end(); - ++vit) + for (Vertex_handle vit : tr().finite_vertex_handles()) { if ( vit->in_dimension() == 0 || nb_incident_complex_edges(vit, m_c3t3) > 2) From e3547c1962bae64a65a3f3628ed287e72edd1eda Mon Sep 17 00:00:00 2001 From: Jane Tournois Date: Fri, 10 Apr 2020 16:15:33 +0200 Subject: [PATCH 239/568] reorganize examples and keep only IO in the tetrahedral_remeshing_io.h file --- .../tetrahedral_remeshing_example.cpp | 44 ++++++++-------- .../tetrahedral_remeshing_io.h | 52 ------------------- ...tetrahedral_remeshing_of_one_subdomain.cpp | 44 +++++++++++++--- .../tetrahedral_remeshing_with_features.cpp | 11 ++-- 4 files changed, 68 insertions(+), 83 deletions(-) diff --git a/Tetrahedral_remeshing/examples/Tetrahedral_remeshing/tetrahedral_remeshing_example.cpp b/Tetrahedral_remeshing/examples/Tetrahedral_remeshing/tetrahedral_remeshing_example.cpp index 06127342f8c..95dfbfdf3e3 100644 --- a/Tetrahedral_remeshing/examples/Tetrahedral_remeshing/tetrahedral_remeshing_example.cpp +++ b/Tetrahedral_remeshing/examples/Tetrahedral_remeshing/tetrahedral_remeshing_example.cpp @@ -5,47 +5,47 @@ #include #include +#include "tetrahedral_remeshing_io.h" + #include #include #include typedef CGAL::Exact_predicates_inexact_constructions_kernel K; -typedef CGAL::Tetrahedral_remeshing::Remeshing_triangulation_3 T3; +typedef CGAL::Tetrahedral_remeshing::Remeshing_triangulation_3 Remeshing_triangulation; -bool load_binary_triangulation(std::istream& is, T3& t3) +template +bool generate_input_one_subdomain(const std::size_t nbv, T3& tr) { - std::string s; - if (!(is >> s)) return false; - bool binary = (s == "binary"); - if (binary) { - if (!(is >> s)) return false; - } - if (s != "CGAL" || !(is >> s) || s != "c3t3") - return false; + CGAL::Random rng; + std::cout << "CGAL Random seed = " << CGAL::get_default_random().get_seed() << std::endl; - std::getline(is, s); - if (binary) CGAL::set_binary_mode(is); - is >> t3; - return bool(is); -} + typedef typename T3::Point Point; + while (tr.number_of_vertices() < nbv) + tr.insert(Point(rng.get_double(-1., 1.), rng.get_double(-1., 1.), rng.get_double(-1., 1.))); -bool save_binary_triangulation(std::ostream& os, const T3& t3) -{ -// typedef T3::Geom_traits::FT FT; - os << "binary CGAL c3t3\n"; - CGAL::set_binary_mode(os); - return !!(os << t3); + for (typename T3::Cell_handle c : tr.finite_cell_handles()) + c->set_subdomain_index(1); + + std::string filename("data/triangulation_one_subdomain.binary.cgal"); + std::ofstream out(filename, std::ios_base::out | std::ios_base::binary); + save_binary_triangulation(out, tr); + + return (!out.bad()); } int main(int argc, char* argv[]) { + Remeshing_triangulation tmp; + generate_input_one_subdomain(1000, tmp); + const char* filename = (argc > 1) ? argv[1] : "data/triangulation_one_subdomain.binary.cgal"; float target_edge_length = (argc > 2) ? atof(argv[2]) : 0.1f; std::ifstream input(filename, std::ios::in | std::ios::binary); - T3 t3; + Remeshing_triangulation t3; if (!input) return EXIT_FAILURE; diff --git a/Tetrahedral_remeshing/examples/Tetrahedral_remeshing/tetrahedral_remeshing_io.h b/Tetrahedral_remeshing/examples/Tetrahedral_remeshing/tetrahedral_remeshing_io.h index b457318990b..212587bbc28 100644 --- a/Tetrahedral_remeshing/examples/Tetrahedral_remeshing/tetrahedral_remeshing_io.h +++ b/Tetrahedral_remeshing/examples/Tetrahedral_remeshing/tetrahedral_remeshing_io.h @@ -42,55 +42,3 @@ void save_ascii_triangulation(const char* filename, const T3& t3) t3, filename); } -template -int generate_input(int input_id, std::size_t nbv, T3& tr) -{ - std::string filename; - CGAL::Random rng; - - if (input_id == 1) //sphere and only one subdomain - { - filename = "data/triangulation_one_subdomain.binary.cgal"; - - while (tr.number_of_vertices() < nbv) - tr.insert(typename T3::Point(rng.get_double(-1., 1.), rng.get_double(-1., 1.), rng.get_double(-1., 1.))); - - for (typename T3::Finite_cells_iterator cit = tr.finite_cells_begin(); - cit != tr.finite_cells_end(); ++cit) - { - cit->set_subdomain_index(1); - } - } - else if (input_id == 2) //sphere separated in 2 subdomains by a plane - { - filename = "data/triangulation_two_subdomains.binary.cgal"; - - while (tr.number_of_vertices() < nbv) - tr.insert( - typename T3::Point(rng.get_double(-1., 1.), rng.get_double(-1., 1.), rng.get_double(-1., 1.))); - - const typename T3::Plane_3 plane(typename T3::Point(0,0,0), typename T3::Point(0,1,0), typename T3::Point(0,0,1)); - - for (typename T3::Finite_cells_iterator cit = tr.finite_cells_begin(); - cit != tr.finite_cells_end(); ++cit) - { - if(plane.has_on_positive_side( - CGAL::centroid(cit->vertex(0)->point(), cit->vertex(1)->point(), - cit->vertex(2)->point(), cit->vertex(3)->point()))) - cit->set_subdomain_index(1); - else - cit->set_subdomain_index(2); - } - } - - std::ofstream out(filename, std::ios_base::out | std::ios_base::binary); - save_binary_triangulation(out, tr); - -// std::string file_in(filename); -// std::string file_out = file_in.substr(0, file_in.find_first_of(".")); -// file_out.append(".mesh"); -// std::ofstream medit_out(file_out.c_str(), std::ios_base::out); -// c3t3.output_to_medit(medit_out); - - return (!out.bad()); -} diff --git a/Tetrahedral_remeshing/examples/Tetrahedral_remeshing/tetrahedral_remeshing_of_one_subdomain.cpp b/Tetrahedral_remeshing/examples/Tetrahedral_remeshing/tetrahedral_remeshing_of_one_subdomain.cpp index 416adbefe44..59cce672941 100644 --- a/Tetrahedral_remeshing/examples/Tetrahedral_remeshing/tetrahedral_remeshing_of_one_subdomain.cpp +++ b/Tetrahedral_remeshing/examples/Tetrahedral_remeshing/tetrahedral_remeshing_of_one_subdomain.cpp @@ -16,6 +16,37 @@ typedef CGAL::Exact_predicates_inexact_constructions_kernel K; typedef CGAL::Tetrahedral_remeshing::Remeshing_triangulation_3 Remeshing_triangulation; +template +bool generate_input_two_subdomains(const std::size_t nbv, T3& tr) +{ + CGAL::Random rng; + std::cout << "CGAL Random seed = " << CGAL::get_default_random().get_seed() << std::endl; + + typedef typename T3::Point Point; + while (tr.number_of_vertices() < nbv) + tr.insert(Point(rng.get_double(-1., 1.), rng.get_double(-1., 1.), rng.get_double(-1., 1.))); + + const typename T3::Geom_traits::Plane_3 + plane(Point(0, 0, 0), Point(0, 1, 0), Point(0, 0, 1)); + + for (typename T3::Cell_handle c : tr.finite_cell_handles()) + { + if (plane.has_on_positive_side( + CGAL::centroid(c->vertex(0)->point(), c->vertex(1)->point(), + c->vertex(2)->point(), c->vertex(3)->point()))) + c->set_subdomain_index(1); + else + c->set_subdomain_index(2); + } + CGAL_assertion(tr.is_valid(true)); + + std::string filename("data/triangulation_two_subdomains.binary.cgal"); + std::ofstream out(filename, std::ios_base::out | std::ios_base::binary); + save_binary_triangulation(out, tr); + + return (!out.bad()); +} + struct Cells_of_subdomain { private: @@ -34,18 +65,19 @@ public: int main(int argc, char* argv[]) { - float target_edge_length = (argc > 1) ? atof(argv[1]) : 0.1f; + CGAL::get_default_random() = CGAL::Random(1586522498); + + const float target_edge_length = (argc > 1) ? atof(argv[1]) : 0.1f; Remeshing_triangulation tr; - generate_input(2, 1000, tr); + generate_input_two_subdomains(1000, tr); CGAL::tetrahedral_adaptive_remeshing(tr, target_edge_length, - CGAL::parameters::cell_selector(Cells_of_subdomain(2))); + CGAL::parameters::cell_selector(Cells_of_subdomain(2))); - std::ofstream oFileT("output.binary.cgal", std::ios::out); - save_binary_triangulation(oFileT, tr); + std::ofstream ofile("output.binary.cgal", std::ios::out); + save_binary_triangulation(ofile, tr); - std::cout << "done" << std::endl; return EXIT_SUCCESS; } diff --git a/Tetrahedral_remeshing/examples/Tetrahedral_remeshing/tetrahedral_remeshing_with_features.cpp b/Tetrahedral_remeshing/examples/Tetrahedral_remeshing/tetrahedral_remeshing_with_features.cpp index 2d8a4fe4a44..63f5a574bf9 100644 --- a/Tetrahedral_remeshing/examples/Tetrahedral_remeshing/tetrahedral_remeshing_with_features.cpp +++ b/Tetrahedral_remeshing/examples/Tetrahedral_remeshing/tetrahedral_remeshing_with_features.cpp @@ -76,16 +76,19 @@ void add_edge(Vertex_handle v1, constraints.insert(std::make_pair(v1, v2)); } -void generate_input(const std::size_t& n, +void generate_input_cube(const std::size_t& n, const char* filename, boost::unordered_set >& constraints) { - Remeshing_triangulation tr; CGAL::Random rng; + std::cout << "CGAL Random seed = " << CGAL::get_default_random().get_seed() << std::endl; + + Remeshing_triangulation tr; // points in a sphere while (tr.number_of_vertices() < n) tr.insert(Point(rng.get_double(-1., 1.), rng.get_double(-1., 1.), rng.get_double(-1., 1.))); + // vertices of a larger cube Vertex_handle v0 = tr.insert(Point(-2., -2., -2.)); Vertex_handle v1 = tr.insert(Point(-2., -2., 2.)); @@ -119,6 +122,8 @@ void generate_input(const std::size_t& n, add_edge(v1, v5, tr, constraints); add_edge(v2, v6, tr, constraints); add_edge(v3, v7, tr, constraints); + + CGAL_assertion(tr.is_valid(true)); } void set_subdomain(Remeshing_triangulation& tr, const int index) @@ -133,7 +138,7 @@ void set_subdomain(Remeshing_triangulation& tr, const int index) int main(int argc, char* argv[]) { boost::unordered_set > constraints; - generate_input(1000, "data/sphere_in_cube.tr.cgal", constraints); + generate_input_cube(1000, "data/sphere_in_cube.tr.cgal", constraints); const char* filename = (argc > 1) ? argv[1] : "data/sphere_in_cube.tr.cgal"; double target_edge_length = (argc > 2) ? atof(argv[2]) : 0.02; From 0c6ce981a3dfd72aac363d8a7e5c621bbb3d5681 Mon Sep 17 00:00:00 2001 From: Marc Glisse Date: Fri, 10 Apr 2020 20:09:43 +0200 Subject: [PATCH 240/568] Missing functions in Mpzf and new test --- Number_types/include/CGAL/Mpzf.h | 33 +++++++++++++++++ Number_types/test/Number_types/Mpzf_new.cpp | 40 +++++++++++++++++++++ 2 files changed, 73 insertions(+) create mode 100644 Number_types/test/Number_types/Mpzf_new.cpp diff --git a/Number_types/include/CGAL/Mpzf.h b/Number_types/include/CGAL/Mpzf.h index 117b5dac71a..46ee60a70bf 100644 --- a/Number_types/include/CGAL/Mpzf.h +++ b/Number_types/include/CGAL/Mpzf.h @@ -353,6 +353,30 @@ struct Mpzf { } x.size = 0; } + Mpzf& operator=(Mpzf&& x)noexcept{ + if (this == &x) return *this; // is this needed? + size = x.size; + exp = x.exp; + auto xd = x.data(); + auto td = data(); + while(*--xd==0); + while(*--td==0); + if (xd != x.cache) { + data() = x.data(); + if (td != cache) { + pool::push(td+1); + // should we instead give it to x in case x is reused? + // x.data() = td + 1; + } + x.init(); + } else { + // In some cases data points in the middle of the buffer, reset it + data() = td + 1; + if(size!=0) mpn_copyi(data(),x.data(),std::abs(size)); + } + x.size = 0; + return *this; + } #else Mpzf(Mpzf&& x):data_(x.data()),size(x.size),exp(x.exp){ x.init(); // yes, that's a shame... @@ -554,6 +578,12 @@ struct Mpzf { friend bool operator!=(Mpzf const&a, Mpzf const&b){ return !(a==b); } + friend Mpzf const&min(Mpzf const&a, Mpzf const&b){ + return (b + +#ifdef CGAL_USE_GMP +# include +#endif +#ifdef CGAL_HAS_MPZF + +#include +#include +#include +#include + +int main() { + { + typedef CGAL::Mpzf NT; + typedef CGAL::Integral_domain_without_division_tag Tag; + typedef CGAL::Tag_true Is_exact; + + CGAL::test_algebraic_structure(); + CGAL::test_algebraic_structure(NT(4),NT(6),NT(15)); + CGAL::test_algebraic_structure(NT(-4),NT(6),NT(15)); + CGAL::test_algebraic_structure(NT(4),NT(-6),NT(15)); + CGAL::test_algebraic_structure(NT(-4),NT(-6),NT(15)); + CGAL::test_algebraic_structure(NT(4),NT(6),NT(-15)); + CGAL::test_algebraic_structure(NT(-4),NT(6), NT(15)); + CGAL::test_algebraic_structure(NT(4),NT(-6),NT(-15)); + CGAL::test_algebraic_structure(NT(-4),NT(-6),NT(-15)); + + CGAL::test_real_embeddable(); + } + + return 0; +} + +#else +int main() +{ + return 0; +} +#endif //CGAL_HAS_MPZF From 58e37209623faa157f6f147de117abe9b4d489f4 Mon Sep 17 00:00:00 2001 From: Marc Glisse Date: Sat, 11 Apr 2020 11:24:26 +0200 Subject: [PATCH 241/568] Replace boost::totally_ordered* with <=> for Gmpq --- Number_types/include/CGAL/GMP/Gmpq_type.h | 46 ++++++++++++++++++++++- 1 file changed, 44 insertions(+), 2 deletions(-) diff --git a/Number_types/include/CGAL/GMP/Gmpq_type.h b/Number_types/include/CGAL/GMP/Gmpq_type.h index 54776eb5b78..156e24c02ba 100644 --- a/Number_types/include/CGAL/GMP/Gmpq_type.h +++ b/Number_types/include/CGAL/GMP/Gmpq_type.h @@ -35,6 +35,10 @@ #include #include +#if __cpp_impl_three_way_comparison >= 201907L +# include +#endif + #if defined(BOOST_MSVC) # pragma warning(push) # pragma warning(disable:4146) @@ -61,8 +65,17 @@ private: class Gmpq - : Handle_for, - boost::totally_ordered1< Gmpq + : Handle_for +#if __cpp_impl_three_way_comparison >= 201907L + , boost::field_operators2< Gmpq, int + , boost::field_operators2< Gmpq, long + , boost::field_operators2< Gmpq, long long + , boost::field_operators2< Gmpq, double + , boost::field_operators2< Gmpq, Gmpz + , boost::field_operators2< Gmpq, Gmpfr + > > > > > > +#else + , boost::totally_ordered1< Gmpq , boost::ordered_field_operators2< Gmpq, int , boost::ordered_field_operators2< Gmpq, long , boost::ordered_field_operators2< Gmpq, long long @@ -70,6 +83,7 @@ class Gmpq , boost::ordered_field_operators2< Gmpq, Gmpz , boost::ordered_field_operators2< Gmpq, Gmpfr > > > > > > > +#endif { typedef Handle_for Base; public: @@ -223,7 +237,11 @@ public: Gmpq& operator/=(const Gmpq &q); bool operator==(const Gmpq &q) const noexcept { return mpq_equal(this->mpq(), q.mpq()) != 0;} +#if __cpp_impl_three_way_comparison >= 201907L + std::strong_ordering operator<=>(const Gmpq&q) const noexcept { return mpq_cmp(this->mpq(), q.mpq()) <=> 0; } +#else bool operator< (const Gmpq &q) const noexcept { return mpq_cmp(this->mpq(), q.mpq()) < 0; } +#endif double to_double() const noexcept; Sign sign() const noexcept; @@ -245,54 +263,78 @@ public: Gmpq& operator-=(int z){return (*this)-= Gmpq(z);} Gmpq& operator*=(int z){return (*this)*= Gmpq(z);} Gmpq& operator/=(int z){return (*this)/= Gmpq(z);} +#if __cpp_impl_three_way_comparison >= 201907L + std::strong_ordering operator<=>(int z) const noexcept { return mpq_cmp_si(mpq(),z,1) <=> 0; } +#else bool operator==(int z) const {return mpq_cmp_si(mpq(),z,1)==0;} bool operator< (int z) const {return mpq_cmp_si(mpq(),z,1)<0;} bool operator> (int z) const {return mpq_cmp_si(mpq(),z,1)>0;} +#endif // Interoperability with long Gmpq& operator+=(long z){return (*this)+= Gmpq(z);} Gmpq& operator-=(long z){return (*this)-= Gmpq(z);} Gmpq& operator*=(long z){return (*this)*= Gmpq(z);} Gmpq& operator/=(long z){return (*this)/= Gmpq(z);} +#if __cpp_impl_three_way_comparison >= 201907L + std::strong_ordering operator<=>(long z) const noexcept { return mpq_cmp_si(mpq(),z,1) <=> 0; } +#else bool operator==(long z) const {return mpq_cmp_si(mpq(),z,1)==0;} bool operator< (long z) const {return mpq_cmp_si(mpq(),z,1)<0;} bool operator> (long z) const {return mpq_cmp_si(mpq(),z,1)>0;} +#endif // Interoperability with long long Gmpq& operator+=(long long z){return (*this)+= Gmpq(z);} Gmpq& operator-=(long long z){return (*this)-= Gmpq(z);} Gmpq& operator*=(long long z){return (*this)*= Gmpq(z);} Gmpq& operator/=(long long z){return (*this)/= Gmpq(z);} +#if __cpp_impl_three_way_comparison >= 201907L + std::strong_ordering operator<=>(long long z) const noexcept { return *this <=> Gmpq(z); } +#else bool operator==(long long z) const {return (*this)== Gmpq(z);} bool operator< (long long z) const {return (*this)< Gmpq(z);} bool operator> (long long z) const {return (*this)> Gmpq(z);} +#endif // Interoperability with double Gmpq& operator+=(double d){return (*this)+= Gmpq(d);} Gmpq& operator-=(double d){return (*this)-= Gmpq(d);} Gmpq& operator*=(double d){return (*this)*= Gmpq(d);} Gmpq& operator/=(double d){return (*this)/= Gmpq(d);} +#if __cpp_impl_three_way_comparison >= 201907L + std::strong_ordering operator<=>(double d) const noexcept { return *this <=> Gmpq(d); } +#else bool operator==(double d) const {return (*this)== Gmpq(d);} bool operator< (double d) const {return (*this)< Gmpq(d);} bool operator> (double d) const {return (*this)> Gmpq(d);} +#endif // Interoperability with Gmpz Gmpq& operator+=(const Gmpz&); Gmpq& operator-=(const Gmpz&); Gmpq& operator*=(const Gmpz&); Gmpq& operator/=(const Gmpz&); +#if __cpp_impl_three_way_comparison >= 201907L + std::strong_ordering operator<=>(const Gmpz& z) const noexcept { return *this <=> Gmpq(z); } +#else bool operator==(const Gmpz &z) const {return (*this)== Gmpq(z);} bool operator< (const Gmpz &z) const {return (*this)< Gmpq(z);} bool operator> (const Gmpz &z) const {return (*this)> Gmpq(z);} +#endif // Interoperability with Gmpfr Gmpq& operator+=(const Gmpfr &f){return (*this)+= Gmpq(f);} Gmpq& operator-=(const Gmpfr &f){return (*this)-= Gmpq(f);} Gmpq& operator*=(const Gmpfr &f){return (*this)*= Gmpq(f);} Gmpq& operator/=(const Gmpfr &f){return (*this)/= Gmpq(f);} +#if __cpp_impl_three_way_comparison >= 201907L + std::strong_ordering operator<=>(const Gmpfr& f) const noexcept { return 0 <=> mpfr_cmp_q(f.fr(),mpq()); } +#else bool operator==(const Gmpfr &f) const {return mpfr_cmp_q(f.fr(),mpq())==0;} bool operator< (const Gmpfr &f) const {return mpfr_cmp_q(f.fr(),mpq())>0;} bool operator> (const Gmpfr &f) const {return mpfr_cmp_q(f.fr(),mpq())<0;} +#endif }; From c1f2fdecbafe5ff7ae2a95bb98ef0c6f107ab58b Mon Sep 17 00:00:00 2001 From: Marc Glisse Date: Sat, 11 Apr 2020 12:12:27 +0200 Subject: [PATCH 242/568] Make mixed comparisons friends for Lazy_exact_nt --- Number_types/include/CGAL/Lazy_exact_nt.h | 141 ++++++++++------------ 1 file changed, 63 insertions(+), 78 deletions(-) diff --git a/Number_types/include/CGAL/Lazy_exact_nt.h b/Number_types/include/CGAL/Lazy_exact_nt.h index b0c401a3797..1a511325de9 100644 --- a/Number_types/include/CGAL/Lazy_exact_nt.h +++ b/Number_types/include/CGAL/Lazy_exact_nt.h @@ -438,6 +438,69 @@ public : return *this = new Lazy_exact_Div(*this, b); } + // Mixed comparisons with int. + friend bool operator<(const Lazy_exact_nt& a, int b) + { + CGAL_BRANCH_PROFILER(std::string(" failures/calls to : ") + std::string(CGAL_PRETTY_FUNCTION), tmp); + Uncertain res = a.approx() < b; + if (is_certain(res)) + return res; + CGAL_BRANCH_PROFILER_BRANCH(tmp); + return a.exact() < b; + } + + friend bool operator>(const Lazy_exact_nt& a, int b) + { + CGAL_BRANCH_PROFILER(std::string(" failures/calls to : ") + std::string(CGAL_PRETTY_FUNCTION), tmp); + Uncertain res = b < a.approx(); + if (is_certain(res)) + return get_certain(res); + CGAL_BRANCH_PROFILER_BRANCH(tmp); + return b < a.exact(); + } + + friend bool operator==(const Lazy_exact_nt& a, int b) + { + CGAL_BRANCH_PROFILER(std::string(" failures/calls to : ") + std::string(CGAL_PRETTY_FUNCTION), tmp); + Uncertain res = b == a.approx(); + if (is_certain(res)) + return get_certain(res); + CGAL_BRANCH_PROFILER_BRANCH(tmp); + return b == a.exact(); + } + + + // Mixed comparisons with double. + friend bool operator<(const Lazy_exact_nt& a, double b) + { + CGAL_BRANCH_PROFILER(std::string(" failures/calls to : ") + std::string(CGAL_PRETTY_FUNCTION), tmp); + Uncertain res = a.approx() < b; + if (is_certain(res)) + return res; + CGAL_BRANCH_PROFILER_BRANCH(tmp); + return a.exact() < b; + } + + friend bool operator>(const Lazy_exact_nt& a, double b) + { + CGAL_BRANCH_PROFILER(std::string(" failures/calls to : ") + std::string(CGAL_PRETTY_FUNCTION), tmp); + Uncertain res = b < a.approx(); + if (is_certain(res)) + return res; + CGAL_BRANCH_PROFILER_BRANCH(tmp); + return b < a.exact(); + } + + friend bool operator==(const Lazy_exact_nt& a, double b) + { + CGAL_BRANCH_PROFILER(std::string(" failures/calls to : ") + std::string(CGAL_PRETTY_FUNCTION), tmp); + Uncertain res = b == a.approx(); + if (is_certain(res)) + return res; + CGAL_BRANCH_PROFILER_BRANCH(tmp); + return b == a.exact(); + } + // % kills filtering Self & operator%=(const Self& b) { @@ -562,84 +625,6 @@ operator%(const Lazy_exact_nt& a, const Lazy_exact_nt& b) } - -// Mixed operators with int. -template -bool -operator<(const Lazy_exact_nt& a, int b) -{ - CGAL_BRANCH_PROFILER(std::string(" failures/calls to : ") + std::string(CGAL_PRETTY_FUNCTION), tmp); - Uncertain res = a.approx() < b; - if (is_certain(res)) - return res; - CGAL_BRANCH_PROFILER_BRANCH(tmp); - return a.exact() < b; -} - -template -bool -operator>(const Lazy_exact_nt& a, int b) -{ - CGAL_BRANCH_PROFILER(std::string(" failures/calls to : ") + std::string(CGAL_PRETTY_FUNCTION), tmp); - Uncertain res = b < a.approx(); - if (is_certain(res)) - return get_certain(res); - CGAL_BRANCH_PROFILER_BRANCH(tmp); - return b < a.exact(); -} - -template -bool -operator==(const Lazy_exact_nt& a, int b) -{ - CGAL_BRANCH_PROFILER(std::string(" failures/calls to : ") + std::string(CGAL_PRETTY_FUNCTION), tmp); - Uncertain res = b == a.approx(); - if (is_certain(res)) - return get_certain(res); - CGAL_BRANCH_PROFILER_BRANCH(tmp); - return b == a.exact(); -} - - -// Mixed operators with double. -template -bool -operator<(const Lazy_exact_nt& a, double b) -{ - CGAL_BRANCH_PROFILER(std::string(" failures/calls to : ") + std::string(CGAL_PRETTY_FUNCTION), tmp); - Uncertain res = a.approx() < b; - if (is_certain(res)) - return res; - CGAL_BRANCH_PROFILER_BRANCH(tmp); - return a.exact() < b; -} - -template -bool -operator>(const Lazy_exact_nt& a, double b) -{ - CGAL_BRANCH_PROFILER(std::string(" failures/calls to : ") + std::string(CGAL_PRETTY_FUNCTION), tmp); - Uncertain res = b < a.approx(); - if (is_certain(res)) - return res; - CGAL_BRANCH_PROFILER_BRANCH(tmp); - return b < a.exact(); -} - -template -bool -operator==(const Lazy_exact_nt& a, double b) -{ - CGAL_BRANCH_PROFILER(std::string(" failures/calls to : ") + std::string(CGAL_PRETTY_FUNCTION), tmp); - Uncertain res = b == a.approx(); - if (is_certain(res)) - return res; - CGAL_BRANCH_PROFILER_BRANCH(tmp); - return b == a.exact(); -} - - - template Lazy_exact_nt< typename Coercion_traits::Type > operator+(const Lazy_exact_nt& a, const Lazy_exact_nt& b) From 84d2f1de5dbd1a8858e5b9a03116e4a6d702ce96 Mon Sep 17 00:00:00 2001 From: Marc Glisse Date: Sat, 11 Apr 2020 12:26:55 +0200 Subject: [PATCH 243/568] Remove wrong noexcept I copy-pasted them a bit too fast... --- Number_types/include/CGAL/GMP/Gmpq_type.h | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/Number_types/include/CGAL/GMP/Gmpq_type.h b/Number_types/include/CGAL/GMP/Gmpq_type.h index 156e24c02ba..634d5adfc2b 100644 --- a/Number_types/include/CGAL/GMP/Gmpq_type.h +++ b/Number_types/include/CGAL/GMP/Gmpq_type.h @@ -238,9 +238,9 @@ public: bool operator==(const Gmpq &q) const noexcept { return mpq_equal(this->mpq(), q.mpq()) != 0;} #if __cpp_impl_three_way_comparison >= 201907L - std::strong_ordering operator<=>(const Gmpq&q) const noexcept { return mpq_cmp(this->mpq(), q.mpq()) <=> 0; } + std::strong_ordering operator<=>(const Gmpq&q) const { return mpq_cmp(this->mpq(), q.mpq()) <=> 0; } #else - bool operator< (const Gmpq &q) const noexcept { return mpq_cmp(this->mpq(), q.mpq()) < 0; } + bool operator< (const Gmpq &q) const { return mpq_cmp(this->mpq(), q.mpq()) < 0; } #endif double to_double() const noexcept; @@ -264,7 +264,7 @@ public: Gmpq& operator*=(int z){return (*this)*= Gmpq(z);} Gmpq& operator/=(int z){return (*this)/= Gmpq(z);} #if __cpp_impl_three_way_comparison >= 201907L - std::strong_ordering operator<=>(int z) const noexcept { return mpq_cmp_si(mpq(),z,1) <=> 0; } + std::strong_ordering operator<=>(int z) const { return mpq_cmp_si(mpq(),z,1) <=> 0; } #else bool operator==(int z) const {return mpq_cmp_si(mpq(),z,1)==0;} bool operator< (int z) const {return mpq_cmp_si(mpq(),z,1)<0;} @@ -277,7 +277,7 @@ public: Gmpq& operator*=(long z){return (*this)*= Gmpq(z);} Gmpq& operator/=(long z){return (*this)/= Gmpq(z);} #if __cpp_impl_three_way_comparison >= 201907L - std::strong_ordering operator<=>(long z) const noexcept { return mpq_cmp_si(mpq(),z,1) <=> 0; } + std::strong_ordering operator<=>(long z) const { return mpq_cmp_si(mpq(),z,1) <=> 0; } #else bool operator==(long z) const {return mpq_cmp_si(mpq(),z,1)==0;} bool operator< (long z) const {return mpq_cmp_si(mpq(),z,1)<0;} @@ -290,7 +290,7 @@ public: Gmpq& operator*=(long long z){return (*this)*= Gmpq(z);} Gmpq& operator/=(long long z){return (*this)/= Gmpq(z);} #if __cpp_impl_three_way_comparison >= 201907L - std::strong_ordering operator<=>(long long z) const noexcept { return *this <=> Gmpq(z); } + std::strong_ordering operator<=>(long long z) const { return *this <=> Gmpq(z); } #else bool operator==(long long z) const {return (*this)== Gmpq(z);} bool operator< (long long z) const {return (*this)< Gmpq(z);} @@ -303,7 +303,7 @@ public: Gmpq& operator*=(double d){return (*this)*= Gmpq(d);} Gmpq& operator/=(double d){return (*this)/= Gmpq(d);} #if __cpp_impl_three_way_comparison >= 201907L - std::strong_ordering operator<=>(double d) const noexcept { return *this <=> Gmpq(d); } + std::strong_ordering operator<=>(double d) const { return *this <=> Gmpq(d); } #else bool operator==(double d) const {return (*this)== Gmpq(d);} bool operator< (double d) const {return (*this)< Gmpq(d);} @@ -316,7 +316,7 @@ public: Gmpq& operator*=(const Gmpz&); Gmpq& operator/=(const Gmpz&); #if __cpp_impl_three_way_comparison >= 201907L - std::strong_ordering operator<=>(const Gmpz& z) const noexcept { return *this <=> Gmpq(z); } + std::strong_ordering operator<=>(const Gmpz& z) const { return *this <=> Gmpq(z); } #else bool operator==(const Gmpz &z) const {return (*this)== Gmpq(z);} bool operator< (const Gmpz &z) const {return (*this)< Gmpq(z);} @@ -329,7 +329,7 @@ public: Gmpq& operator*=(const Gmpfr &f){return (*this)*= Gmpq(f);} Gmpq& operator/=(const Gmpfr &f){return (*this)/= Gmpq(f);} #if __cpp_impl_three_way_comparison >= 201907L - std::strong_ordering operator<=>(const Gmpfr& f) const noexcept { return 0 <=> mpfr_cmp_q(f.fr(),mpq()); } + std::strong_ordering operator<=>(const Gmpfr& f) const { return 0 <=> mpfr_cmp_q(f.fr(),mpq()); } #else bool operator==(const Gmpfr &f) const {return mpfr_cmp_q(f.fr(),mpq())==0;} bool operator< (const Gmpfr &f) const {return mpfr_cmp_q(f.fr(),mpq())>0;} From 8b79068a12fc784807599b1790cbcf9104428a96 Mon Sep 17 00:00:00 2001 From: Marc Glisse Date: Sat, 11 Apr 2020 13:19:06 +0200 Subject: [PATCH 244/568] friend operator== for Quotient --- Number_types/include/CGAL/Quotient.h | 34 ++++++++-------------------- 1 file changed, 9 insertions(+), 25 deletions(-) diff --git a/Number_types/include/CGAL/Quotient.h b/Number_types/include/CGAL/Quotient.h index 5c91f07d2cf..41e9423d9b7 100644 --- a/Number_types/include/CGAL/Quotient.h +++ b/Number_types/include/CGAL/Quotient.h @@ -129,6 +129,15 @@ class Quotient Quotient& operator*= (const CGAL_double(NT)& r); Quotient& operator/= (const CGAL_double(NT)& r); + friend bool operator==(const Quotient& x, const Quotient& y) + { return x.num * y.den == x.den * y.num; } + friend bool operator==(const Quotient& x, const NT& y) + { return x.den * y == x.num; } + friend inline bool operator==(const Quotient& x, const CGAL_int(NT) & y) + { return x.den * y == x.num; } + friend inline bool operator==(const Quotient& x, const CGAL_double(NT) & y) + { return x.den * y == x.num; } // Uh? + Quotient& normalize(); const NT& numerator() const { return num; } @@ -438,31 +447,6 @@ quotient_truncation(const Quotient& r) -template -CGAL_MEDIUM_INLINE -bool -operator==(const Quotient& x, const Quotient& y) -{ return x.num * y.den == x.den * y.num; } - -template -CGAL_MEDIUM_INLINE -bool -operator==(const Quotient& x, const NT& y) -{ return x.den * y == x.num; } - -template -inline -bool -operator==(const Quotient& x, const CGAL_int(NT) & y) -{ return x.den * y == x.num; } - -template -inline -bool -operator==(const Quotient& x, const CGAL_double(NT) & y) -{ return x.den * y == x.num; } - - template CGAL_MEDIUM_INLINE From 2aac945e2f9e8854a0c5130660a5fb7028b93fe5 Mon Sep 17 00:00:00 2001 From: Jane Tournois Date: Sat, 11 Apr 2020 15:44:36 +0200 Subject: [PATCH 245/568] dump c3t3 using output_to_medit() --- .../tetrahedral_adaptive_remeshing_impl.h | 14 +++++++------- .../internal/tetrahedral_remeshing_helpers.h | 18 +++++++----------- 2 files changed, 14 insertions(+), 18 deletions(-) diff --git a/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/tetrahedral_adaptive_remeshing_impl.h b/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/tetrahedral_adaptive_remeshing_impl.h index 48796886503..674ec69ab3f 100644 --- a/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/tetrahedral_adaptive_remeshing_impl.h +++ b/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/tetrahedral_adaptive_remeshing_impl.h @@ -140,6 +140,7 @@ public: m_vertex_smoother.init(m_c3t3, m_cell_selector); #ifdef CGAL_DUMP_REMESHING_STEPS + CGAL::Tetrahedral_remeshing::debug::dump_medit(m_c3t3, "00-init.mesh"); CGAL::Tetrahedral_remeshing::debug::dump_binary(m_c3t3, "00-init.binary.cgal"); #endif } @@ -166,6 +167,7 @@ public: m_vertex_smoother.init(m_c3t3, m_cell_selector); #ifdef CGAL_DUMP_REMESHING_STEPS + CGAL::Tetrahedral_remeshing::debug::dump_medit(m_c3t3, "00-init.mesh"); CGAL::Tetrahedral_remeshing::debug::dump_binary(m_c3t3, "00-init.binary.cgal"); #endif } @@ -187,7 +189,7 @@ public: CGAL_assertion(tr().tds().is_valid(true)); CGAL_assertion(debug::are_cell_orientations_valid(tr())); #ifdef CGAL_DUMP_REMESHING_STEPS - CGAL::Tetrahedral_remeshing::debug::dump_triangulation_cells(tr(), "1-split.mesh"); + CGAL::Tetrahedral_remeshing::debug::dump_medit(m_c3t3, "1-split.mesh"); CGAL::Tetrahedral_remeshing::debug::dump_binary(m_c3t3, "1-split.binary.cgal"); #endif } @@ -205,8 +207,7 @@ public: CGAL_assertion(tr().tds().is_valid(true)); CGAL_assertion(debug::are_cell_orientations_valid(tr())); #ifdef CGAL_DUMP_REMESHING_STEPS - CGAL::Tetrahedral_remeshing::debug::dump_triangulation_cells(tr(), - "2-collapse.mesh"); + CGAL::Tetrahedral_remeshing::debug::dump_medit(m_c3t3, "2-collapse.mesh"); CGAL::Tetrahedral_remeshing::debug::dump_binary(m_c3t3, "2-collapse.binary.cgal"); #endif } @@ -219,7 +220,7 @@ public: CGAL_assertion(tr().tds().is_valid(true)); CGAL_assertion(debug::are_cell_orientations_valid(tr())); #ifdef CGAL_DUMP_REMESHING_STEPS - CGAL::Tetrahedral_remeshing::debug::dump_triangulation_cells(tr(), "3-flip.mesh"); + CGAL::Tetrahedral_remeshing::debug::dump_medit(m_c3t3, "3-flip.mesh"); CGAL::Tetrahedral_remeshing::debug::dump_binary(m_c3t3, "3-flip.binary.cgal"); #endif } @@ -231,8 +232,7 @@ public: CGAL_assertion(tr().tds().is_valid(true)); CGAL_assertion(debug::are_cell_orientations_valid(tr())); #ifdef CGAL_DUMP_REMESHING_STEPS - CGAL::Tetrahedral_remeshing::debug::dump_triangulation_cells(tr(), - "4-smooth.mesh"); + CGAL::Tetrahedral_remeshing::debug::dump_medit(m_c3t3, "4-smooth.mesh"); CGAL::Tetrahedral_remeshing::debug::dump_binary(m_c3t3, "4-smooth.binary.cgal"); #endif } @@ -302,7 +302,7 @@ public: CGAL_assertion(debug::are_cell_orientations_valid(tr())); #ifdef CGAL_DUMP_REMESHING_STEPS - CGAL::Tetrahedral_remeshing::debug::dump_triangulation_cells(tr(), "99-postprocess.mesh"); + CGAL::Tetrahedral_remeshing::debug::dump_medit(m_c3t3, "99-postprocess.mesh"); CGAL::Tetrahedral_remeshing::debug::dump_binary(m_c3t3, "99-postprocess.binary.cgal"); #endif #ifdef CGAL_TETRAHEDRAL_REMESHING_VERBOSE diff --git a/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/tetrahedral_remeshing_helpers.h b/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/tetrahedral_remeshing_helpers.h index 524120bf424..7404293ecec 100644 --- a/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/tetrahedral_remeshing_helpers.h +++ b/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/tetrahedral_remeshing_helpers.h @@ -1301,17 +1301,13 @@ void dump_binary(const C3t3& c3t3, const char* filename) os.close(); } -//template -//void dump_edges(const VertexPairsSet& edges, const char* filename) -//{ -// std::ofstream ofs(filename); -// BOOST_FOREACH(typename VertexPairsSet::key_type vp, edges) -// { -// ofs << "2 " << vp.first->point() -// << " " << vp.second->point() << std::endl; -// } -// ofs.close(); -//} +template +void dump_medit(const C3t3& c3t3, const char* filename) +{ + std::ofstream os(filename, std::ios::out); + c3t3.output_to_medit(os, true, true); + os.close(); +} } //namespace debug } //namespace Tetrahedral_remeshing From 608272d2a509c5d427bf34c8725a70bac165b31a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9bastien=20Loriot?= Date: Mon, 13 Apr 2020 10:45:28 +0200 Subject: [PATCH 246/568] fix compilation errors and a warning --- .../internal/tetrahedral_remeshing_helpers.h | 103 +++++++++--------- .../include/CGAL/tetrahedral_remeshing.h | 2 +- 2 files changed, 52 insertions(+), 53 deletions(-) diff --git a/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/tetrahedral_remeshing_helpers.h b/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/tetrahedral_remeshing_helpers.h index 7404293ecec..082b9697a5f 100644 --- a/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/tetrahedral_remeshing_helpers.h +++ b/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/tetrahedral_remeshing_helpers.h @@ -187,13 +187,6 @@ bool is_on_feature(const VertexHandle v) return (v->in_dimension() == 1 || v->in_dimension() == 0); } -template -bool is_well_oriented(const Tr& tr, const typename Tr::Cell_handle ch) -{ - return is_well_oriented(tr, ch->vertex(0), ch->vertex(1), - ch->vertex(2), ch->vertex(3)); -} - template bool is_well_oriented(const Tr& tr, const typename Tr::Vertex_handle v0, @@ -208,6 +201,13 @@ bool is_well_oriented(const Tr& tr, point(v3->point())); } +template +bool is_well_oriented(const Tr& tr, const typename Tr::Cell_handle ch) +{ + return is_well_oriented(tr, ch->vertex(0), ch->vertex(1), + ch->vertex(2), ch->vertex(3)); +} + template bool is_boundary(const C3T3& c3t3, const typename C3T3::Facet& f, @@ -683,6 +683,50 @@ bool topology_test(const typename C3t3::Edge& edge, return true; } +template +Subdomain_relation compare_subdomains(const typename C3t3::Vertex_handle v0, + const typename C3t3::Vertex_handle v1, + const C3t3& c3t3) +{ + typedef typename C3t3::Subdomain_index Subdomain_index; + + std::vector subdomains_v0; + incident_subdomains(v0, c3t3, std::back_inserter(subdomains_v0)); + std::sort(subdomains_v0.begin(), subdomains_v0.end()); + + std::vector subdomains_v1; + incident_subdomains(v1, c3t3, std::back_inserter(subdomains_v1)); + std::sort(subdomains_v1.begin(), subdomains_v1.end()); + + if (subdomains_v0.size() == subdomains_v1.size()) + { + for (unsigned int i = 0; i < subdomains_v0.size(); i++) + if (subdomains_v0[i] != subdomains_v1[i]) + return DIFFERENT; + return EQUAL; + } + else + { + std::vector + intersection((std::min)(subdomains_v0.size(), subdomains_v1.size()), -1); + typename std::vector::iterator + end_it = std::set_intersection(subdomains_v0.begin(), subdomains_v0.end(), + subdomains_v1.begin(), subdomains_v1.end(), + intersection.begin()); + std::ptrdiff_t intersection_size = (end_it - intersection.begin()); + + if (subdomains_v0.size() > subdomains_v1.size() + && intersection_size == std::ptrdiff_t(subdomains_v1.size())) + { + return INCLUDES; + } + else if (intersection_size == std::ptrdiff_t(subdomains_v0.size())) { + return INCLUDED; + } + } + return DIFFERENT; +} + template void get_edge_info(const typename C3t3::Edge& edge, bool& update_v0, @@ -805,51 +849,6 @@ void get_edge_info(const typename C3t3::Edge& edge, } } -template -Subdomain_relation compare_subdomains(const typename C3t3::Vertex_handle v0, - const typename C3t3::Vertex_handle v1, - const C3t3& c3t3) -{ - typedef typename C3t3::Subdomain_index Subdomain_index; - - std::vector subdomains_v0; - incident_subdomains(v0, c3t3, std::back_inserter(subdomains_v0)); - std::sort(subdomains_v0.begin(), subdomains_v0.end()); - - std::vector subdomains_v1; - incident_subdomains(v1, c3t3, std::back_inserter(subdomains_v1)); - std::sort(subdomains_v1.begin(), subdomains_v1.end()); - - if (subdomains_v0.size() == subdomains_v1.size()) - { - for (unsigned int i = 0; i < subdomains_v0.size(); i++) - if (subdomains_v0[i] != subdomains_v1[i]) - return DIFFERENT; - return EQUAL; - } - else - { - std::vector - intersection((std::min)(subdomains_v0.size(), subdomains_v1.size()), -1); - typename std::vector::iterator - end_it = std::set_intersection(subdomains_v0.begin(), subdomains_v0.end(), - subdomains_v1.begin(), subdomains_v1.end(), - intersection.begin()); - std::ptrdiff_t intersection_size = (end_it - intersection.begin()); - - if (subdomains_v0.size() > subdomains_v1.size() - && intersection_size == std::ptrdiff_t(subdomains_v1.size())) - { - return INCLUDES; - } - else if (intersection_size == std::ptrdiff_t(subdomains_v0.size())) { - return INCLUDED; - } - } - return DIFFERENT; -} - - namespace debug { diff --git a/Tetrahedral_remeshing/include/CGAL/tetrahedral_remeshing.h b/Tetrahedral_remeshing/include/CGAL/tetrahedral_remeshing.h index 3db4021a856..25421889142 100644 --- a/Tetrahedral_remeshing/include/CGAL/tetrahedral_remeshing.h +++ b/Tetrahedral_remeshing/include/CGAL/tetrahedral_remeshing.h @@ -258,7 +258,7 @@ void tetrahedral_adaptive_remeshing( { tetrahedral_adaptive_remeshing( c3t3, - [target_edge_length](const typename Tr::Point& p) + [target_edge_length](const typename Tr::Point& /* p */) {return target_edge_length; }, np); } From d5a061a326b6bac1a013fd104d9124aa3dc9a8d4 Mon Sep 17 00:00:00 2001 From: Jane Tournois Date: Tue, 14 Apr 2020 06:38:13 +0200 Subject: [PATCH 247/568] create single function for both dumps too ascii and medit --- .../tetrahedral_adaptive_remeshing_impl.h | 29 +++++++------------ .../internal/tetrahedral_remeshing_helpers.h | 13 +++++++++ 2 files changed, 24 insertions(+), 18 deletions(-) diff --git a/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/tetrahedral_adaptive_remeshing_impl.h b/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/tetrahedral_adaptive_remeshing_impl.h index 674ec69ab3f..2971320a6cf 100644 --- a/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/tetrahedral_adaptive_remeshing_impl.h +++ b/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/tetrahedral_adaptive_remeshing_impl.h @@ -140,8 +140,7 @@ public: m_vertex_smoother.init(m_c3t3, m_cell_selector); #ifdef CGAL_DUMP_REMESHING_STEPS - CGAL::Tetrahedral_remeshing::debug::dump_medit(m_c3t3, "00-init.mesh"); - CGAL::Tetrahedral_remeshing::debug::dump_binary(m_c3t3, "00-init.binary.cgal"); + CGAL::Tetrahedral_remeshing::debug::dump_c3t3(m_c3t3, "00-init"); #endif } @@ -167,8 +166,7 @@ public: m_vertex_smoother.init(m_c3t3, m_cell_selector); #ifdef CGAL_DUMP_REMESHING_STEPS - CGAL::Tetrahedral_remeshing::debug::dump_medit(m_c3t3, "00-init.mesh"); - CGAL::Tetrahedral_remeshing::debug::dump_binary(m_c3t3, "00-init.binary.cgal"); + CGAL::Tetrahedral_remeshing::debug::dump_c3t3(m_c3t3, "00-init"); #endif } @@ -189,8 +187,7 @@ public: CGAL_assertion(tr().tds().is_valid(true)); CGAL_assertion(debug::are_cell_orientations_valid(tr())); #ifdef CGAL_DUMP_REMESHING_STEPS - CGAL::Tetrahedral_remeshing::debug::dump_medit(m_c3t3, "1-split.mesh"); - CGAL::Tetrahedral_remeshing::debug::dump_binary(m_c3t3, "1-split.binary.cgal"); + CGAL::Tetrahedral_remeshing::debug::dump_c3t3(m_c3t3, "1-split"); #endif } @@ -207,8 +204,7 @@ public: CGAL_assertion(tr().tds().is_valid(true)); CGAL_assertion(debug::are_cell_orientations_valid(tr())); #ifdef CGAL_DUMP_REMESHING_STEPS - CGAL::Tetrahedral_remeshing::debug::dump_medit(m_c3t3, "2-collapse.mesh"); - CGAL::Tetrahedral_remeshing::debug::dump_binary(m_c3t3, "2-collapse.binary.cgal"); + CGAL::Tetrahedral_remeshing::debug::dump_c3t3(m_c3t3, "2-collapse"); #endif } @@ -220,8 +216,7 @@ public: CGAL_assertion(tr().tds().is_valid(true)); CGAL_assertion(debug::are_cell_orientations_valid(tr())); #ifdef CGAL_DUMP_REMESHING_STEPS - CGAL::Tetrahedral_remeshing::debug::dump_medit(m_c3t3, "3-flip.mesh"); - CGAL::Tetrahedral_remeshing::debug::dump_binary(m_c3t3, "3-flip.binary.cgal"); + CGAL::Tetrahedral_remeshing::debug::dump_c3t3(m_c3t3, "3-flip"); #endif } @@ -232,8 +227,7 @@ public: CGAL_assertion(tr().tds().is_valid(true)); CGAL_assertion(debug::are_cell_orientations_valid(tr())); #ifdef CGAL_DUMP_REMESHING_STEPS - CGAL::Tetrahedral_remeshing::debug::dump_medit(m_c3t3, "4-smooth.mesh"); - CGAL::Tetrahedral_remeshing::debug::dump_binary(m_c3t3, "4-smooth.binary.cgal"); + CGAL::Tetrahedral_remeshing::debug::dump_c3t3(m_c3t3, "4-smooth"); #endif } @@ -302,8 +296,7 @@ public: CGAL_assertion(debug::are_cell_orientations_valid(tr())); #ifdef CGAL_DUMP_REMESHING_STEPS - CGAL::Tetrahedral_remeshing::debug::dump_medit(m_c3t3, "99-postprocess.mesh"); - CGAL::Tetrahedral_remeshing::debug::dump_binary(m_c3t3, "99-postprocess.binary.cgal"); + CGAL::Tetrahedral_remeshing::debug::dump_c3t3(m_c3t3, "99-postprocess"); #endif #ifdef CGAL_TETRAHEDRAL_REMESHING_VERBOSE std::cout << "(peeling removed " << nb_slivers_peel << " slivers)" << std::endl; @@ -330,7 +323,7 @@ private: std::size_t nbe = 0; std::size_t nbv = 0; #endif - + //tag cells typedef typename Tr::Cell_handle Cell_handle; for (Cell_handle cit : tr().finite_cell_handles()) @@ -495,10 +488,10 @@ public: if (!resolution_reached()) { split(); - collapse(); +// collapse(); } - flip(); - smooth(); +// flip(); +// smooth(); #ifdef CGAL_TETRAHEDRAL_REMESHING_VERBOSE std::cout << "# Iteration " << it_nb << " done : " diff --git a/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/tetrahedral_remeshing_helpers.h b/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/tetrahedral_remeshing_helpers.h index 7404293ecec..446f551f034 100644 --- a/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/tetrahedral_remeshing_helpers.h +++ b/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/tetrahedral_remeshing_helpers.h @@ -1309,6 +1309,19 @@ void dump_medit(const C3t3& c3t3, const char* filename) os.close(); } +template +void dump_c3t3(const C3t3& c3t3, const char* filename_no_extension) +{ + std::string filename_medit(filename_no_extension); + filename_medit.append(".mesh"); + dump_medit(c3t3, filename_medit.c_str()); + + std::string filename_binary(filename_no_extension); + filename_binary.append(".binary.cgal"); + dump_binary(c3t3, filename_binary.c_str()); +} + + } //namespace debug } //namespace Tetrahedral_remeshing } //namespace CGAL From 6220e11b59ec9e5b6220ae960ebd4b3c5e923d60 Mon Sep 17 00:00:00 2001 From: Jane Tournois Date: Tue, 14 Apr 2020 08:16:18 +0200 Subject: [PATCH 248/568] avoid creation of degenerate cells with split() --- .../internal/split_long_edges.h | 52 ++++++++++++++++--- 1 file changed, 44 insertions(+), 8 deletions(-) diff --git a/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/split_long_edges.h b/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/split_long_edges.h index 0a0c96e46ca..b5b4e21f7de 100644 --- a/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/split_long_edges.h +++ b/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/split_long_edges.h @@ -19,6 +19,7 @@ #include #include #include +#include #include @@ -48,14 +49,49 @@ typename C3t3::Vertex_handle split_edge(const typename C3t3::Edge& e, const Vertex_handle v1 = e.first->vertex(e.second); const Vertex_handle v2 = e.first->vertex(e.third); + const Point m = tr.geom_traits().construct_midpoint_3_object() + (point(v1->point()), point(v2->point())); + //backup subdomain info of incident cells before making changes short dimension = (c3t3.is_in_complex(e)) ? 1 : 3; boost::unordered_map cells_info; boost::unordered_map > facets_info; + // check orientation and collect incident cells to avoid circulating twice + boost::container::small_vector inc_cells; Cell_circulator circ = tr.incident_cells(e); Cell_circulator end = circ; do + { + inc_cells.push_back(circ); + if (tr.is_infinite(circ)) + { + ++circ; + continue; + } + + //1st half-cell + std::array pts = { point(circ->vertex(0)->point()), + point(circ->vertex(1)->point()), + point(circ->vertex(2)->point()), + point(circ->vertex(3)->point()) }; + const int i1 = circ->index(v1); + const Point p1 = pts[i1]; + pts[i1] = m; + if(CGAL::orientation(pts[0], pts[1], pts[2], pts[3]) != CGAL::POSITIVE) + return Vertex_handle(); + + //2nd half-cell + pts[i1] = p1; + pts[circ->index(v2)] = m; + if (CGAL::orientation(pts[0], pts[1], pts[2], pts[3]) != CGAL::POSITIVE) + return Vertex_handle(); + + ++circ; + } + while (circ != end); + + for(Cell_handle circ : inc_cells) { const int index_v1 = circ->index(v1); const int index_v2 = circ->index(v2); @@ -88,15 +124,10 @@ typename C3t3::Vertex_handle split_edge(const typename C3t3::Edge& e, if(c3t3.is_in_complex(circ, findex)) c3t3.remove_from_complex(circ, findex); - - ++circ; - - } while (circ != end); + } // insert midpoint Vertex_handle new_v = tr.tds().insert_in_edge(e); - const Point m = tr.geom_traits().construct_midpoint_3_object() - (point(v1->point()), point(v2->point())); new_v->set_point(typename Tr::Point(m)); new_v->set_dimension(dimension); @@ -260,10 +291,15 @@ void split_long_edges(C3T3& c3t3, visitor.before_split(tr, edge); Vertex_handle vh = split_edge(edge, c3t3); - visitor.after_split(tr, vh); + + if(vh != Vertex_handle()) + visitor.after_split(tr, vh); + + CGAL_assertion(debug::are_cell_orientations_valid(tr)); #ifdef CGAL_TETRAHEDRAL_REMESHING_DEBUG - ofs << vh->point() << std::endl; + if (vh != Vertex_handle()) + ofs << vh->point() << std::endl; #endif #if defined(CGAL_TETRAHEDRAL_REMESHING_VERBOSE_PROGRESS) \ From 32dfc3380af19a597795e0ba707a9fd7fbfef52a Mon Sep 17 00:00:00 2001 From: Jane Tournois Date: Tue, 14 Apr 2020 08:22:05 +0200 Subject: [PATCH 249/568] keep c3t3 number of facets valid during collapse using add_to_complex(facet) and remove_from_complex(facet) increment and decrement the number this commit removes before collapse facets that will disappear from triangulation --- .../internal/collapse_short_edges.h | 73 ++++++++++--------- 1 file changed, 39 insertions(+), 34 deletions(-) diff --git a/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/collapse_short_edges.h b/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/collapse_short_edges.h index d60935b19a1..122ac9bab8a 100644 --- a/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/collapse_short_edges.h +++ b/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/collapse_short_edges.h @@ -18,9 +18,9 @@ #include #include #include -#include #include #include +#include #include @@ -609,24 +609,20 @@ void merge_surface_patch_indices(const typename C3t3::Facet& f1, if (in_cx_f1 && !in_cx_f2) { typename C3t3::Surface_patch_index patch = c3t3.surface_patch_index(f1); - c3t3.remove_from_complex(f1); - c3t3.add_to_complex(f1, patch); - c3t3.add_to_complex(f2, patch); + f2.first->set_surface_patch_index(f2.second, patch); } else if (in_cx_f2 && !in_cx_f1) { typename C3t3::Surface_patch_index patch = c3t3.surface_patch_index(f2); - c3t3.remove_from_complex(f2); - c3t3.add_to_complex(f1, patch); - c3t3.add_to_complex(f2, patch); + f1.first->set_surface_patch_index(f1.second, patch); } - else + else if(in_cx_f1 && in_cx_f2) { - CGAL_assertion( - //f1 and f2 are not both in complex - !(in_cx_f1 && in_cx_f2) - // unless they are on the same surface - || c3t3.surface_patch_index(f1) == c3t3.surface_patch_index(f2)); + CGAL_assertion(c3t3.surface_patch_index(f1) == c3t3.surface_patch_index(f2)); + + typename C3t3::Surface_patch_index patch = c3t3.surface_patch_index(f2); + c3t3.remove_from_complex(f2); + f2.first->set_surface_patch_index(f2.second, patch); } } @@ -647,7 +643,6 @@ collapse(const typename C3t3::Cell_handle ch, Vertex_handle vh0 = ch->vertex(to); Vertex_handle vh1 = ch->vertex(from); - std::vector cells_to_remove; //Update the vertex before removing it std::vector find_incident; @@ -656,14 +651,30 @@ collapse(const typename C3t3::Cell_handle ch, std::vector cells_to_update; tr.incident_cells(vh1, std::back_inserter(cells_to_update)); -// if (vh1->in_dimension() == 2 && c3t3.is_in_complex(vh1)) -// std::cout << "Collapsing a feature vertex!!!!!!" << std::endl; - - boost::unordered_set invalid_cells; - bool valid = true; + boost::container::small_vector inc_cells; Cell_circulator circ = tr.incident_cells(ch, to, from); Cell_circulator done = circ; do + { + for (int i = 0; i < 4; ++i) + { + const Vertex_handle vi = circ->vertex(i); + if (vi != vh0 && vi != vh1) + { + const Facet fi(circ, i); + if (c3t3.is_in_complex(fi)) + c3t3.remove_from_complex(fi); + } + } + inc_cells.push_back(circ); + } + while (++circ != done); + + bool valid = true; + std::vector cells_to_remove; + boost::unordered_set invalid_cells; + + for(const Cell_handle circ : inc_cells) { const int v0_id = circ->index(vh0); const int v1_id = circ->index(vh1); @@ -684,34 +695,27 @@ collapse(const typename C3t3::Cell_handle ch, n1_ch->set_neighbor(ch_id_in_n1, n0_ch); //Update vertices cell pointer - //if( !triangulation.is_infinite( n0_ch ) ) - int nb_on_boundary_n0 = 0; for (int i = 0; i < 3; i++) { int vid = Tr::vertex_triple_index(ch_id_in_n0, i); n0_ch->vertex(vid)->set_cell(n0_ch); - if (c3t3.in_dimension(n0_ch->vertex(vid))) - nb_on_boundary_n0++; } - //else - int nb_on_boundary_n1 = 0; for (int i = 0; i < 3; i++) { int vid = Tr::vertex_triple_index(ch_id_in_n1, i); n1_ch->vertex(vid)->set_cell(n1_ch); - if (c3t3.in_dimension(n1_ch->vertex(vid))) - nb_on_boundary_n1++; } - if ( tr.is_infinite(n0_ch->vertex(ch_id_in_n0)) - && tr.is_infinite(n1_ch->vertex(ch_id_in_n1))) + if (tr.is_infinite(n0_ch->vertex(ch_id_in_n0)) + && tr.is_infinite(n1_ch->vertex(ch_id_in_n1))) + { + std::cout << "Collapse infinite issue!" << std::endl; return Vertex_handle(); - + } cells_to_remove.push_back(circ); invalid_cells.insert(circ); - - } while (++circ != done); + } const Vertex_handle infinite_vertex = tr.infinite_vertex(); @@ -759,6 +763,8 @@ collapse(const typename C3t3::Cell_handle ch, } } + // update complex facets + //Update the vertex before removing it for (const Cell_handle ch : cells_to_update) { @@ -787,9 +793,8 @@ collapse(const typename C3t3::Cell_handle ch, for (Cell_handle cell_to_remove : cells_to_remove) { // remove cell - if (cell_to_remove->subdomain_index() > 0) + if (c3t3.is_in_complex(cell_to_remove)) c3t3.remove_from_complex(cell_to_remove); - c3t3.triangulation().tds().delete_cell(cell_to_remove); } From 9660846c032d8030a0f26e62170ca74f32258f61 Mon Sep 17 00:00:00 2001 From: Jane Tournois Date: Tue, 14 Apr 2020 08:23:02 +0200 Subject: [PATCH 250/568] reintroduce collapse/flip/smooth --- .../internal/tetrahedral_adaptive_remeshing_impl.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/tetrahedral_adaptive_remeshing_impl.h b/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/tetrahedral_adaptive_remeshing_impl.h index 2971320a6cf..91c688a34b4 100644 --- a/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/tetrahedral_adaptive_remeshing_impl.h +++ b/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/tetrahedral_adaptive_remeshing_impl.h @@ -488,10 +488,10 @@ public: if (!resolution_reached()) { split(); -// collapse(); + collapse(); } -// flip(); -// smooth(); + flip(); + smooth(); #ifdef CGAL_TETRAHEDRAL_REMESHING_VERBOSE std::cout << "# Iteration " << it_nb << " done : " From 54d72e9533d89750fd141ec3f85e32abc52ef208 Mon Sep 17 00:00:00 2001 From: Jane Tournois Date: Tue, 14 Apr 2020 08:30:24 +0200 Subject: [PATCH 251/568] remove (too) expensive assertion --- .../CGAL/Tetrahedral_remeshing/internal/split_long_edges.h | 2 -- 1 file changed, 2 deletions(-) diff --git a/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/split_long_edges.h b/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/split_long_edges.h index b5b4e21f7de..1b42de85416 100644 --- a/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/split_long_edges.h +++ b/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/split_long_edges.h @@ -295,8 +295,6 @@ void split_long_edges(C3T3& c3t3, if(vh != Vertex_handle()) visitor.after_split(tr, vh); - CGAL_assertion(debug::are_cell_orientations_valid(tr)); - #ifdef CGAL_TETRAHEDRAL_REMESHING_DEBUG if (vh != Vertex_handle()) ofs << vh->point() << std::endl; From 29350cb260ddabf54d6a465d313609a74cc4536c Mon Sep 17 00:00:00 2001 From: Jane Tournois Date: Tue, 14 Apr 2020 15:09:59 +0200 Subject: [PATCH 252/568] fix the update of c3t3 facets in the flip step --- .../Tetrahedral_remeshing_plugin.cpp | 2 +- .../internal/flip_edges.h | 45 +++++++++---------- 2 files changed, 23 insertions(+), 24 deletions(-) diff --git a/Polyhedron/demo/Polyhedron/Plugins/Tetrahedral_remeshing/Tetrahedral_remeshing_plugin.cpp b/Polyhedron/demo/Polyhedron/Plugins/Tetrahedral_remeshing/Tetrahedral_remeshing_plugin.cpp index 25219b9b7a0..d272fe1c232 100644 --- a/Polyhedron/demo/Polyhedron/Plugins/Tetrahedral_remeshing/Tetrahedral_remeshing_plugin.cpp +++ b/Polyhedron/demo/Polyhedron/Plugins/Tetrahedral_remeshing/Tetrahedral_remeshing_plugin.cpp @@ -1,5 +1,5 @@ #define CGAL_TETRAHEDRAL_REMESHING_VERBOSE -//#define CGAL_DUMP_REMESHING_STEPS +#define CGAL_DUMP_REMESHING_STEPS //#define CGAL_TETRAHEDRAL_REMESHING_DEBUG //#define CGAL_TETRAHEDRAL_REMESHING_VERBOSE_PROGRESS //#define CGAL_TETRAHEDRAL_REMESHING_PROFILE diff --git a/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/flip_edges.h b/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/flip_edges.h index d441f452a0f..a306580ed8f 100644 --- a/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/flip_edges.h +++ b/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/flip_edges.h @@ -22,6 +22,7 @@ #include #include +#include #include #include @@ -52,6 +53,7 @@ void update_c3t3_facets(C3t3& c3t3, { typedef typename C3t3::Facet Facet; typedef typename C3t3::Cell_handle Cell_handle; + typedef typename C3t3::Surface_patch_index Surface_patch_index; for (Cell_handle c : cells_to_update) { @@ -61,23 +63,23 @@ void update_c3t3_facets(C3t3& c3t3, { const Facet f(c, i); const Facet mf = c3t3.triangulation().mirror_facet(f); - if (outer_mirror_facets.find(mf) == outer_mirror_facets.end()) - { - //we are inside the modified zone, c3t3 info is not valid anymore - if (c3t3.is_in_complex(f)) - c3t3.remove_from_complex(f); - if (c3t3.is_in_complex(mf)) - c3t3.remove_from_complex(mf); - } - else + if (outer_mirror_facets.find(mf) != outer_mirror_facets.end()) { //we are on the border of the modified zone, c3t3 info is valid outside, //on mirror facet const typename C3t3::Surface_patch_index patch = c3t3.surface_patch_index(mf); if (c3t3.is_in_complex(mf)) + f.first->set_surface_patch_index(f.second, patch); + else + f.first->set_surface_patch_index(f.second, Surface_patch_index()); + } + else + { + //we are inside the modified zone, c3t3 info is not valid anymore + if (c3t3.is_in_complex(f) || c3t3.is_in_complex(mf)) { - c3t3.remove_from_complex(mf); - c3t3.add_to_complex(mf, patch); + f.first->set_surface_patch_index(f.second, Surface_patch_index()); + mf.first->set_surface_patch_index(mf.second, Surface_patch_index()); } } } @@ -314,11 +316,11 @@ Sliver_removal_result flip_3_to_2(typename C3t3::Edge& edge, } // Update c3t3 + update_c3t3_facets(c3t3, cells_to_update, outer_mirror_facets); + c3t3.remove_from_complex(cell_to_remove); tr.tds().delete_cell(cell_to_remove); - update_c3t3_facets(c3t3, cells_to_update, outer_mirror_facets); - /********************VALIDITY CHECK***************************/ //if (check_validity) //{ @@ -715,7 +717,7 @@ Sliver_removal_result flip_n_to_m(C3t3& c3t3, std::vector cells_around_edge; - std::vector to_remove; + boost::container::small_vector to_remove; //Neighbors that will need to be updated after flip boost::unordered_set neighbor_facets; @@ -880,6 +882,9 @@ Sliver_removal_result flip_n_to_m(C3t3& c3t3, } } + // Update c3t3 + update_c3t3_facets(c3t3, cells_to_update, neighbor_facets); + //Remove cells for (Cell_handle ch : to_remove) { @@ -887,10 +892,6 @@ Sliver_removal_result flip_n_to_m(C3t3& c3t3, tr.tds().delete_cell(ch); } - // Update c3t3 - update_c3t3_facets(c3t3, cells_to_update, neighbor_facets); - - ///********************VALIDITY CHECK***************************/ //if (check_validity){ @@ -1009,8 +1010,6 @@ Sliver_removal_result find_best_flip(typename C3t3::Edge& edge, { typedef typename C3t3::Triangulation Tr; typedef typename C3t3::Vertex_handle Vertex_handle; -// typedef typename C3t3::Facet Facet; -// typedef typename C3t3::Surface_patch_index Surface_patch_index; typedef typename Tr::Facet_circulator Facet_circulator; Tr& tr = c3t3.triangulation(); @@ -1027,7 +1026,7 @@ Sliver_removal_result find_best_flip(typename C3t3::Edge& edge, bool hull_edge = false; boost::unordered_set boundary_vertices; - boost::unordered_set hull_vertices; +// boost::unordered_set hull_vertices; do { //Get the ids of the opposite vertices @@ -1049,7 +1048,7 @@ Sliver_removal_result find_best_flip(typename C3t3::Edge& edge, != tr.is_infinite(circ->first->neighbor(circ->second))) { hull_edge = true; - hull_vertices.insert(vi); + //hull_vertices.insert(vi); } } } @@ -1092,7 +1091,7 @@ Sliver_removal_result find_best_flip(typename C3t3::Edge& edge, template -std::size_t flip_all_edges(std::vector& edges, +std::size_t flip_all_edges(const std::vector& edges, C3t3& c3t3, const Flip_Criterion& criterion, Visitor& visitor) From 807eac022daa7090aef3a4da26bfb5bad0d57f55 Mon Sep 17 00:00:00 2001 From: Jane Tournois Date: Tue, 14 Apr 2020 15:25:57 +0200 Subject: [PATCH 253/568] fix maybe uninitialized warning - important if default constructed is not 0,0,0 --- .../include/CGAL/Tetrahedral_remeshing/internal/FMLS.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/FMLS.h b/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/FMLS.h index 4f6712a1e9f..b206bc00751 100644 --- a/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/FMLS.h +++ b/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/FMLS.h @@ -193,7 +193,7 @@ public: else maxIt[j] = ((unsigned int)gxyz[j]) + 1; } - Vector_3 c; + Vector_3 c = CGAL::NULL_VECTOR; float sumW = 0.f; unsigned int it[3]; for (it[0] = minIt[0]; it[0] <= maxIt[0]; it[0]++) From 15cb9cb62d0ebf8d8edf4b786cb29398b06c079b Mon Sep 17 00:00:00 2001 From: Jane Tournois Date: Wed, 15 Apr 2020 07:54:26 +0200 Subject: [PATCH 254/568] simplify examples for the user manual more complicated code will move to the tests --- .../tetrahedral_remeshing_example.cpp | 22 -------- ...tetrahedral_remeshing_of_one_subdomain.cpp | 33 ----------- .../tetrahedral_remeshing_with_features.cpp | 56 ++++++++----------- 3 files changed, 24 insertions(+), 87 deletions(-) diff --git a/Tetrahedral_remeshing/examples/Tetrahedral_remeshing/tetrahedral_remeshing_example.cpp b/Tetrahedral_remeshing/examples/Tetrahedral_remeshing/tetrahedral_remeshing_example.cpp index 95dfbfdf3e3..0435c077b6e 100644 --- a/Tetrahedral_remeshing/examples/Tetrahedral_remeshing/tetrahedral_remeshing_example.cpp +++ b/Tetrahedral_remeshing/examples/Tetrahedral_remeshing/tetrahedral_remeshing_example.cpp @@ -15,31 +15,9 @@ typedef CGAL::Exact_predicates_inexact_constructions_kernel K; typedef CGAL::Tetrahedral_remeshing::Remeshing_triangulation_3 Remeshing_triangulation; -template -bool generate_input_one_subdomain(const std::size_t nbv, T3& tr) -{ - CGAL::Random rng; - std::cout << "CGAL Random seed = " << CGAL::get_default_random().get_seed() << std::endl; - - typedef typename T3::Point Point; - while (tr.number_of_vertices() < nbv) - tr.insert(Point(rng.get_double(-1., 1.), rng.get_double(-1., 1.), rng.get_double(-1., 1.))); - - for (typename T3::Cell_handle c : tr.finite_cell_handles()) - c->set_subdomain_index(1); - - std::string filename("data/triangulation_one_subdomain.binary.cgal"); - std::ofstream out(filename, std::ios_base::out | std::ios_base::binary); - save_binary_triangulation(out, tr); - - return (!out.bad()); -} int main(int argc, char* argv[]) { - Remeshing_triangulation tmp; - generate_input_one_subdomain(1000, tmp); - const char* filename = (argc > 1) ? argv[1] : "data/triangulation_one_subdomain.binary.cgal"; float target_edge_length = (argc > 2) ? atof(argv[2]) : 0.1f; diff --git a/Tetrahedral_remeshing/examples/Tetrahedral_remeshing/tetrahedral_remeshing_of_one_subdomain.cpp b/Tetrahedral_remeshing/examples/Tetrahedral_remeshing/tetrahedral_remeshing_of_one_subdomain.cpp index 59cce672941..ee6df98925f 100644 --- a/Tetrahedral_remeshing/examples/Tetrahedral_remeshing/tetrahedral_remeshing_of_one_subdomain.cpp +++ b/Tetrahedral_remeshing/examples/Tetrahedral_remeshing/tetrahedral_remeshing_of_one_subdomain.cpp @@ -16,36 +16,6 @@ typedef CGAL::Exact_predicates_inexact_constructions_kernel K; typedef CGAL::Tetrahedral_remeshing::Remeshing_triangulation_3 Remeshing_triangulation; -template -bool generate_input_two_subdomains(const std::size_t nbv, T3& tr) -{ - CGAL::Random rng; - std::cout << "CGAL Random seed = " << CGAL::get_default_random().get_seed() << std::endl; - - typedef typename T3::Point Point; - while (tr.number_of_vertices() < nbv) - tr.insert(Point(rng.get_double(-1., 1.), rng.get_double(-1., 1.), rng.get_double(-1., 1.))); - - const typename T3::Geom_traits::Plane_3 - plane(Point(0, 0, 0), Point(0, 1, 0), Point(0, 0, 1)); - - for (typename T3::Cell_handle c : tr.finite_cell_handles()) - { - if (plane.has_on_positive_side( - CGAL::centroid(c->vertex(0)->point(), c->vertex(1)->point(), - c->vertex(2)->point(), c->vertex(3)->point()))) - c->set_subdomain_index(1); - else - c->set_subdomain_index(2); - } - CGAL_assertion(tr.is_valid(true)); - - std::string filename("data/triangulation_two_subdomains.binary.cgal"); - std::ofstream out(filename, std::ios_base::out | std::ios_base::binary); - save_binary_triangulation(out, tr); - - return (!out.bad()); -} struct Cells_of_subdomain { @@ -65,12 +35,9 @@ public: int main(int argc, char* argv[]) { - CGAL::get_default_random() = CGAL::Random(1586522498); - const float target_edge_length = (argc > 1) ? atof(argv[1]) : 0.1f; Remeshing_triangulation tr; - generate_input_two_subdomains(1000, tr); CGAL::tetrahedral_adaptive_remeshing(tr, target_edge_length, CGAL::parameters::cell_selector(Cells_of_subdomain(2))); diff --git a/Tetrahedral_remeshing/examples/Tetrahedral_remeshing/tetrahedral_remeshing_with_features.cpp b/Tetrahedral_remeshing/examples/Tetrahedral_remeshing/tetrahedral_remeshing_with_features.cpp index 63f5a574bf9..e0793840e8b 100644 --- a/Tetrahedral_remeshing/examples/Tetrahedral_remeshing/tetrahedral_remeshing_with_features.cpp +++ b/Tetrahedral_remeshing/examples/Tetrahedral_remeshing/tetrahedral_remeshing_with_features.cpp @@ -76,36 +76,32 @@ void add_edge(Vertex_handle v1, constraints.insert(std::make_pair(v1, v2)); } -void generate_input_cube(const std::size_t& n, - const char* filename, - boost::unordered_set >& constraints) +void make_constraints_from_cube_edges( + Remeshing_triangulation& tr, + boost::unordered_set >& constraints) { - CGAL::Random rng; - std::cout << "CGAL Random seed = " << CGAL::get_default_random().get_seed() << std::endl; + Remeshing_triangulation::Locate_type lt; + int li, lj; - Remeshing_triangulation tr; + Cell_handle c = tr.locate(Point(-2., -2., -2.), lt, li, lj); + Vertex_handle v0 = c->vertex(li); + c = tr.locate(Point(-2., -2., 2.)); + Vertex_handle v1 = c->vertex(li); - // points in a sphere - while (tr.number_of_vertices() < n) - tr.insert(Point(rng.get_double(-1., 1.), rng.get_double(-1., 1.), rng.get_double(-1., 1.))); + c = tr.locate(Point( 2., -2., -2.)); + Vertex_handle v2 = c->vertex(li); + c = tr.locate(Point( 2., -2., 2.)); + Vertex_handle v3 = c->vertex(li); - // vertices of a larger cube - Vertex_handle v0 = tr.insert(Point(-2., -2., -2.)); - Vertex_handle v1 = tr.insert(Point(-2., -2., 2.)); + c = tr.locate(Point(-2., 2., -2.)); + Vertex_handle v4 = c->vertex(li); + c = tr.locate(Point(-2., 2., 2.)); + Vertex_handle v5 = c->vertex(li); - Vertex_handle v2 = tr.insert(Point( 2., -2., -2.)); - Vertex_handle v3 = tr.insert(Point( 2., -2., 2.)); - - Vertex_handle v4 = tr.insert(Point(-2., 2., -2.)); - Vertex_handle v5 = tr.insert(Point(-2., 2., 2.)); - - Vertex_handle v6 = tr.insert(Point( 2., 2., -2.)); - Vertex_handle v7 = tr.insert(Point( 2., 2., 2.)); - - // writing file output - std::ofstream oFileT(filename, std::ios::out); - oFileT << tr; - oFileT.close(); + c = tr.locate(Point( 2., 2., -2.)); + Vertex_handle v6 = c->vertex(li); + c = tr.locate(Point( 2., 2., 2.)); + Vertex_handle v7 = c->vertex(li); // constrain cube edges add_edge(v0, v1, tr, constraints); @@ -122,8 +118,6 @@ void generate_input_cube(const std::size_t& n, add_edge(v1, v5, tr, constraints); add_edge(v2, v6, tr, constraints); add_edge(v3, v7, tr, constraints); - - CGAL_assertion(tr.is_valid(true)); } void set_subdomain(Remeshing_triangulation& tr, const int index) @@ -137,9 +131,6 @@ void set_subdomain(Remeshing_triangulation& tr, const int index) int main(int argc, char* argv[]) { - boost::unordered_set > constraints; - generate_input_cube(1000, "data/sphere_in_cube.tr.cgal", constraints); - const char* filename = (argc > 1) ? argv[1] : "data/sphere_in_cube.tr.cgal"; double target_edge_length = (argc > 2) ? atof(argv[2]) : 0.02; int nb_iter = (argc > 3) ? atoi(argv[3]) : 1; @@ -154,9 +145,10 @@ int main(int argc, char* argv[]) Remeshing_triangulation t3; input >> t3; set_subdomain(t3, 1); - CGAL_assertion(t3.is_valid()); + boost::unordered_set > constraints; + make_constraints_from_cube_edges(t3, constraints); - save_ascii_triangulation("tet_remeshing_with_features_before.mesh", t3); + CGAL_assertion(t3.is_valid()); CGAL::tetrahedral_adaptive_remeshing(t3, target_edge_length, CGAL::parameters::edge_is_constrained_map( From 0a0f8a631a149f65c150debc50f8f69da4f6a4d0 Mon Sep 17 00:00:00 2001 From: Jane Tournois Date: Wed, 15 Apr 2020 11:33:54 +0200 Subject: [PATCH 255/568] add missing initialization --- .../include/CGAL/Tetrahedral_remeshing/internal/FMLS.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/FMLS.h b/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/FMLS.h index b206bc00751..7800f98d7dd 100644 --- a/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/FMLS.h +++ b/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/FMLS.h @@ -324,7 +324,7 @@ private: void computePNScale() { - Vector_3 c; + Vector_3 c = CGAL::NULL_VECTOR; for (unsigned int i = 0; i < PNSize; i++) c += Vector_3(PN[6 * i], PN[6 * i + 1], PN[6 * i + 2]); c /= PNSize; From 0fae00577d92888384350570e12f44720d357b00 Mon Sep 17 00:00:00 2001 From: Jane Tournois Date: Wed, 15 Apr 2020 11:42:21 +0200 Subject: [PATCH 256/568] explicitely use CGAL::NULL_VECTOR instead of Vector_3() --- .../CGAL/Tetrahedral_remeshing/internal/FMLS.h | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/FMLS.h b/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/FMLS.h index 7800f98d7dd..71e0115a76b 100644 --- a/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/FMLS.h +++ b/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/FMLS.h @@ -233,8 +233,8 @@ public: Vector_3 p(pv[stride * i], pv[stride * i + 1], pv[stride * i + 2]); Vector_3 q, n; for (unsigned int j = 0; j < numIter; j++) { - q = Vector_3(); - n = Vector_3(); + q = CGAL::NULL_VECTOR; + n = CGAL::NULL_VECTOR; fastProjectionCPU(p, q, n); p = q; } @@ -250,8 +250,8 @@ public: float sigma_r = bilateralRange; Vector_3 p(x); for (unsigned int k = 0; k < numIter; k++) { - Vector_3 c; - n = Vector_3();; + Vector_3 c = CGAL::NULL_VECTOR; + n = CGAL::NULL_VECTOR; float sumW = 0.f; for (unsigned int j = 0; j < PNSize; j++) { Vector_3 pj(PN[6 * j], PN[6 * j + 1], PN[6 * j + 2]); @@ -275,8 +275,8 @@ public: Vector_3 p(pv[stride * i], pv[stride * i + 1], pv[stride * i + 2]); Vector_3 q, n; for (unsigned int j = 0; j < numIter; j++) { - q = Vector_3(); - n = Vector_3(); + q = CGAL::NULL_VECTOR; + n = CGAL::NULL_VECTOR; projectionCPU(p, q, n); p = q; } From 3604e800a8453d684161d1503bfa1a19286cca67 Mon Sep 17 00:00:00 2001 From: Jane Tournois Date: Wed, 15 Apr 2020 12:35:10 +0200 Subject: [PATCH 257/568] user manual --- .../doc/Tetrahedral_remeshing/Tetrahedral_remeshing.txt | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/Tetrahedral_remeshing/doc/Tetrahedral_remeshing/Tetrahedral_remeshing.txt b/Tetrahedral_remeshing/doc/Tetrahedral_remeshing/Tetrahedral_remeshing.txt index 995b3270785..f601166d063 100644 --- a/Tetrahedral_remeshing/doc/Tetrahedral_remeshing/Tetrahedral_remeshing.txt +++ b/Tetrahedral_remeshing/doc/Tetrahedral_remeshing/Tetrahedral_remeshing.txt @@ -13,7 +13,7 @@ This package implements an algorithm for quality tetrahedral remeshing, introduced by N.Faraj et al in \cgalCite{faraj2016mvr}. This practical iterative remeshing algorithm is designed to remesh multi-material tetrahedral meshes, by iteratively performing a sequence of simple -elementary operations such as edge collapses, edge splits, edge flips, +elementary operations such as edge splits, edge collapses, edge flips, and vertex relocations following a Laplacian smoothing. The algorithm results in high quality isotropic meshes, with the desired mesh density, while preserving the input geometric linear and surfacic features. @@ -34,10 +34,10 @@ while targetting the user-defined uniform sizing field and preserving the topology of the feature complex, as highlighted by Figure \cgalFigureRef{Remesh_liver}. \cgalFigureBegin{Remesh_liver, tetrahedral_remeshing_before_after.png} -Tetrahedral mesh, modified by our uniform tetrahedral remeshing method. -(Left) Before remeshing, dihedral angles were in the interval [1.3; 177.8]. +Tetrahedral mesh, modified by the uniform tetrahedral remeshing algorithm. +(Left) Before remeshing, dihedral angles were in the interval [0.7; 178.9]. (Right) After remeshing and keeping the same density, -dihedral angles were are the interval [9.5; 161.9]. +dihedral angles are the interval [12,7; 157.7]. \cgalFigureEnd Experimental evidence show that a higher number of remeshing iterations From 41519e30104fd6fbfbc178f18230a9fa7fd59076 Mon Sep 17 00:00:00 2001 From: Simon Giraudot Date: Thu, 9 Apr 2020 13:40:19 +0200 Subject: [PATCH 258/568] Proposal for imported targets --- .../cmake/modules/CGAL_Eigen_support.cmake | 9 ++ .../cmake/modules/CGAL_LASLIB_support.cmake | 7 + .../cmake/modules/CGAL_OpenGR_support.cmake | 6 + .../cmake/modules/CGAL_TBB_support.cmake | 10 ++ .../modules/CGAL_pointmatcher_support.cmake | 7 + .../Point_set_processing_3/CMakeLists.txt | 129 ++++++++---------- 6 files changed, 97 insertions(+), 71 deletions(-) create mode 100644 Installation/cmake/modules/CGAL_Eigen_support.cmake create mode 100644 Installation/cmake/modules/CGAL_LASLIB_support.cmake create mode 100644 Installation/cmake/modules/CGAL_OpenGR_support.cmake create mode 100644 Installation/cmake/modules/CGAL_TBB_support.cmake create mode 100644 Installation/cmake/modules/CGAL_pointmatcher_support.cmake diff --git a/Installation/cmake/modules/CGAL_Eigen_support.cmake b/Installation/cmake/modules/CGAL_Eigen_support.cmake new file mode 100644 index 00000000000..31e5f22abf5 --- /dev/null +++ b/Installation/cmake/modules/CGAL_Eigen_support.cmake @@ -0,0 +1,9 @@ +if(Eigen_FOUND AND NOT TARGET CGAL::Eigen_support) + if(NOT TARGET Threads::Threads) + find_package(Threads REQUIRED) + endif() + add_library(CGAL::Eigen_support INTERFACE IMPORTED) + set_target_properties(CGAL::Eigen_support PROPERTIES + INTERFACE_COMPILE_DEFINITIONS "CGAL_EIGEN3_ENABLED" + INTERFACE_INCLUDE_DIRECTORIES "${EIGEN3_INCLUDE_DIR}") +endif() diff --git a/Installation/cmake/modules/CGAL_LASLIB_support.cmake b/Installation/cmake/modules/CGAL_LASLIB_support.cmake new file mode 100644 index 00000000000..6b1f6cbb58a --- /dev/null +++ b/Installation/cmake/modules/CGAL_LASLIB_support.cmake @@ -0,0 +1,7 @@ +if(LASLIB_FOUND AND NOT TARGET CGAL::LASLIB_support) + add_library(CGAL::LASLIB_support INTERFACE IMPORTED) + set_target_properties(CGAL::LASLIB_support PROPERTIES + INTERFACE_COMPILE_DEFINITIONS "CGAL_LINKED_WITH_LASLIB" + INTERFACE_INCLUDE_DIRECTORIES "${LASLIB_INCLUDE_DIR};${LASZIP_INCLUDE_DIR}" + INTERFACE_LINK_LIBRARIES "${LASLIB_LIBRARIES}") +endif() diff --git a/Installation/cmake/modules/CGAL_OpenGR_support.cmake b/Installation/cmake/modules/CGAL_OpenGR_support.cmake new file mode 100644 index 00000000000..227dda5ec57 --- /dev/null +++ b/Installation/cmake/modules/CGAL_OpenGR_support.cmake @@ -0,0 +1,6 @@ +if(OpenGR_FOUND AND NOT TARGET CGAL::OpenGR_support) + add_library(CGAL::OpenGR_support INTERFACE IMPORTED) + set_target_properties(CGAL::OpenGR_support PROPERTIES + INTERFACE_COMPILE_DEFINITIONS "CGAL_LINKED_WITH_OPENGR" + INTERFACE_INCLUDE_DIRECTORIES "${OpenGR_INCLUDE_DIR}") +endif() diff --git a/Installation/cmake/modules/CGAL_TBB_support.cmake b/Installation/cmake/modules/CGAL_TBB_support.cmake new file mode 100644 index 00000000000..e34882e949c --- /dev/null +++ b/Installation/cmake/modules/CGAL_TBB_support.cmake @@ -0,0 +1,10 @@ +if(TBB_FOUND AND NOT TARGET CGAL::TBB_support) + if(NOT TARGET Threads::Threads) + find_package(Threads REQUIRED) + endif() + add_library(CGAL::TBB_support INTERFACE IMPORTED) + set_target_properties(CGAL::TBB_support PROPERTIES + INTERFACE_COMPILE_DEFINITIONS "CGAL_LINKED_WITH_TBB;NOMINMAX" + INTERFACE_INCLUDE_DIRECTORIES "${TBB_INCLUDE_DIRS}" + INTERFACE_LINK_LIBRARIES "TBB:tbb;TBB:tbbmalloc;Threads::Threads") +endif() diff --git a/Installation/cmake/modules/CGAL_pointmatcher_support.cmake b/Installation/cmake/modules/CGAL_pointmatcher_support.cmake new file mode 100644 index 00000000000..c023102661f --- /dev/null +++ b/Installation/cmake/modules/CGAL_pointmatcher_support.cmake @@ -0,0 +1,7 @@ +if(libpointmatcher_FOUND AND NOT TARGET CGAL::pointmatcher_support) + add_library(CGAL::pointmatcher_support INTERFACE IMPORTED) + set_target_properties(CGAL::pointmatcher_support PROPERTIES + INTERFACE_COMPILE_DEFINITIONS "CGAL_LINKED_WITH_POINTMATCHER" + INTERFACE_INCLUDE_DIRECTORIES "${libpointmatcher_INCLUDE_DIR}" + INTERFACE_LINK_LIBRARIES "${libpointmatcher_LIBRARIES}") +endif() diff --git a/Point_set_processing_3/examples/Point_set_processing_3/CMakeLists.txt b/Point_set_processing_3/examples/Point_set_processing_3/CMakeLists.txt index 36412ac7b68..318f6a91e0c 100644 --- a/Point_set_processing_3/examples/Point_set_processing_3/CMakeLists.txt +++ b/Point_set_processing_3/examples/Point_set_processing_3/CMakeLists.txt @@ -31,114 +31,101 @@ if ( CGAL_FOUND ) "Enable concurrency" OFF) + set(CGAL_libs CGAL::CGAL) if( CGAL_ACTIVATE_CONCURRENT_PSP3 OR ENV{CGAL_ACTIVATE_CONCURRENT_PSP3} ) find_package( TBB REQUIRED ) + include(CGAL_TBB_support) + if (TARGET CGAL::TBB_support) + set(CGAL_TBB_target ${CGAL_libs} CGAL::TBB_support) + endif() endif() # Executables that do *not* require EIGEN - create_single_source_cgal_program( "average_spacing_example.cpp" ) - create_single_source_cgal_program( "bilateral_smooth_point_set_example.cpp" ) - create_single_source_cgal_program( "grid_simplification_example.cpp" ) - create_single_source_cgal_program( "grid_simplify_indices.cpp" ) - create_single_source_cgal_program( "property_map.cpp" ) - create_single_source_cgal_program( "random_simplification_example.cpp" ) - create_single_source_cgal_program( "read_write_xyz_point_set_example.cpp" ) - create_single_source_cgal_program( "remove_outliers_example.cpp" ) - create_single_source_cgal_program( "wlop_simplify_and_regularize_point_set_example.cpp" ) - create_single_source_cgal_program( "edge_aware_upsample_point_set_example.cpp" ) - create_single_source_cgal_program( "structuring_example.cpp" ) - - create_single_source_cgal_program( "read_ply_points_with_colors_example.cpp" ) - create_single_source_cgal_program( "write_ply_points_example.cpp" ) + foreach(target + average_spacing_example + bilateral_smooth_point_set_example + grid_simplification_example + grid_simplify_indices + property_map + random_simplification_example + read_write_xyz_point_set_example + remove_outliers_example + wlop_simplify_and_regularize_point_set_example + edge_aware_upsample_point_set_example + structuring_example + read_ply_points_with_colors_example + write_ply_points_example) + add_executable(${target} "${target}.cpp") + target_link_libraries(${target} ${CGAL_libs}) + endforeach() find_package(LASLIB) - if (LASLIB_FOUND) - create_single_source_cgal_program( "read_las_example.cpp" ) - CGAL_target_use_LASLIB(read_las_example) + include(CGAL_LASLIB_support) + if (TARGET CGAL::LASLIB_support) + add_executable( read_las_example "read_las_example.cpp" ) + target_link_libraries(read_las_example ${CGAL_libs} CGAL::LASLIB_support) else() message(STATUS "NOTICE : the LAS reader test requires LASlib and will not be compiled.") endif() # Use Eigen find_package(Eigen3 3.1.0) #(requires 3.1.0 or greater) - if (EIGEN3_FOUND) + include(CGAL_Eigen_support) + if (TARGET CGAL::Eigen_support) + set(CGAL_libs ${CGAL_libs} CGAL::Eigen_support) + # Executables that require Eigen - create_single_source_cgal_program( "jet_smoothing_example.cpp" ) - CGAL_target_use_Eigen(jet_smoothing_example) + foreach(target + jet_smoothing_example + normal_estimation + edges_example - create_single_source_cgal_program( "normal_estimation.cpp" ) - CGAL_target_use_Eigen(normal_estimation) - - create_single_source_cgal_program( "edges_example.cpp" ) + callback_example + scale_estimation_example + scale_estimation_2d_example + hierarchy_simplification_example + normals_example) + add_executable(${target} "${target}.cpp") + target_link_libraries(${target} ${CGAL_libs}) + endforeach() # Executables that require libpointmatcher find_package(libpointmatcher QUIET) - if (libpointmatcher_FOUND) - create_single_source_cgal_program( "registration_with_pointmatcher.cpp" ) - CGAL_target_use_pointmatcher(registration_with_pointmatcher) - CGAL_target_use_Eigen(registration_with_pointmatcher) + include(CGAL_pointmatcher_support) + if (TARGET CGAL::pointmatcher_support) + add_executable(registration_with_pointmatcher "registration_with_pointmatcher.cpp") + target_link_libraries(registration_with_pointmatcher + ${CGAL_libs} CGAL::pointmatcher_support) else() message(STATUS "NOTICE : the registration_with_pointmatcher test requires libpointmatcher and will not be compiled.") endif() # Executables that require OpenGR find_package(OpenGR QUIET) - if (OpenGR_FOUND) - create_single_source_cgal_program( "registration_with_OpenGR.cpp" ) - CGAL_target_use_OpenGR(registration_with_OpenGR) - CGAL_target_use_Eigen(registration_with_OpenGR) + include(CGAL_OpenGR_support) + if (TARGET CGAL::OpenGR_support) + add_executable(registration_with_OpenGR "registration_with_OpenGR.cpp" ) + target_link_libraries(registration_with_OpenGR + ${CGAL_libs} CGAL::OpenGR_support) else() message(STATUS "NOTICE : registration_with_OpenGR requires OpenGR, and will not be compiled.") endif() # Executables that require both libpointmatcher and OpenGR - if (libpointmatcher_FOUND AND OpenGR_FOUND) - create_single_source_cgal_program( "registration_with_opengr_pointmatcher_pipeline.cpp" ) - CGAL_target_use_OpenGR(registration_with_opengr_pointmatcher_pipeline) - CGAL_target_use_pointmatcher(registration_with_opengr_pointmatcher_pipeline) - CGAL_target_use_Eigen(registration_with_opengr_pointmatcher_pipeline) + if (TARGET CGAL::pointmatcher_support AND + TARGET CGAL::OpenGR_support) + add_executable(registration_with_opengr_pointmatcher_pipeline + "registration_with_opengr_pointmatcher_pipeline.cpp" ) + target_link_libraries(registration_with_opengr_pointmatcher_pipeline + ${CGAL_libs} CGAL::pointmatcher_support CGAL::OpenGR_support) else() message(STATUS "NOTICE : registration_with_opengr_pointmatcher_pipeline requires libpointmatcher and OpenGR, and will not be compiled.") endif() - CGAL_target_use_Eigen(edges_example) - - create_single_source_cgal_program( "callback_example.cpp" ) - CGAL_target_use_Eigen(callback_example) - - create_single_source_cgal_program( "scale_estimation_example.cpp" ) - CGAL_target_use_Eigen(scale_estimation_example) - - create_single_source_cgal_program( "scale_estimation_2d_example.cpp" ) - CGAL_target_use_Eigen(scale_estimation_2d_example) - - create_single_source_cgal_program( "hierarchy_simplification_example.cpp" ) - CGAL_target_use_Eigen(hierarchy_simplification_example) - - create_single_source_cgal_program( "normals_example.cpp" ) - CGAL_target_use_Eigen(normals_example) - else() message(STATUS "NOTICE: Some of the executables in this directory need Eigen 3.1 (or greater) and will not be compiled.") endif() - if (TBB_FOUND) - foreach(target - scale_estimation_example - wlop_simplify_and_regularize_point_set_example - bilateral_smooth_point_set_example - edge_aware_upsample_point_set_example - average_spacing_example - normals_example - jet_smoothing_example - normal_estimation - callback_example) - if(TARGET ${target}) - CGAL_target_use_TBB(${target}) - endif() - endforeach() - endif() - else() message(STATUS "NOTICE: This program requires the CGAL library, and will not be compiled.") endif() From 421096fd7f52ec7bb1e544860c22ff85d080a81c Mon Sep 17 00:00:00 2001 From: Simon Giraudot Date: Wed, 15 Apr 2020 12:28:48 +0200 Subject: [PATCH 259/568] Use imported targets everywhere --- .../CMakeLists.txt | 14 +-- .../test/Bounding_volumes/CMakeLists.txt | 14 +-- .../test/Box_intersection_d/CMakeLists.txt | 6 +- CGAL_ipelets/demo/CGAL_ipelets/CMakeLists.txt | 12 +-- .../examples/Classification/CMakeLists.txt | 37 +++++--- .../test/Classification/CMakeLists.txt | 22 +++-- Generator/examples/Generator/CMakeLists.txt | 8 +- Generator/test/Generator/CMakeLists.txt | 8 +- GraphicsView/demo/Polygon/CMakeLists.txt | 6 +- .../examples/Heat_method_3/CMakeLists.txt | 11 ++- .../test/Heat_method_3/CMakeLists.txt | 9 +- ...ake => CGAL_Boost_iostreams_support.cmake} | 41 ++++---- .../CGAL_Boost_serialization_support.cmake | 12 +++ Installation/cmake/modules/CGAL_Common.cmake | 15 +-- .../cmake/modules/CGAL_Eigen_support.cmake | 2 +- .../cmake/modules/CGAL_GLPK_support.cmake | 7 ++ .../cmake/modules/CGAL_OpenCV_support.cmake | 7 ++ .../cmake/modules/CGAL_SCIP_support.cmake | 7 ++ .../cmake/modules/CGAL_TBB_support.cmake | 2 +- .../modules/CGAL_TensorFlow_support.cmake | 7 ++ .../CGAL_target_use_Boost_Serialization.cmake | 14 --- .../cmake/modules/CGAL_target_use_Eigen.cmake | 13 --- .../cmake/modules/CGAL_target_use_GLPK.cmake | 11 --- .../modules/CGAL_target_use_LASLIB.cmake | 11 --- .../modules/CGAL_target_use_OpenCV.cmake | 10 -- .../modules/CGAL_target_use_OpenGR.cmake | 9 -- .../cmake/modules/CGAL_target_use_SCIP.cmake | 11 --- .../cmake/modules/CGAL_target_use_TBB.cmake | 4 +- .../modules/CGAL_target_use_TensorFlow.cmake | 10 -- .../CGAL_target_use_pointmatcher.cmake | 10 -- Installation/cmake/modules/UseTBB.cmake | 2 +- Installation/test/Installation/CMakeLists.txt | 5 +- .../examples/Jet_fitting_3/CMakeLists.txt | 8 +- .../test/Jet_fitting_3/CMakeLists.txt | 6 +- Mesh_3/benchmark/Mesh_3/CMakeLists.txt | 9 +- Mesh_3/examples/Mesh_3/CMakeLists.txt | 95 ++++++++++--------- Mesh_3/test/Mesh_3/CMakeLists.txt | 45 +++++---- NewKernel_d/test/NewKernel_d/CMakeLists.txt | 6 +- Number_types/test/Number_types/CMakeLists.txt | 5 +- .../examples/Periodic_3_mesh_3/CMakeLists.txt | 5 +- .../test/Periodic_3_mesh_3/CMakeLists.txt | 10 +- .../examples/Point_set_3/CMakeLists.txt | 3 +- .../Point_set_processing_3/CMakeLists.txt | 19 ++-- .../CMakeLists.txt | 12 +-- .../CMakeLists.txt | 6 +- .../Polygon_mesh_processing/CMakeLists.txt | 8 +- .../Polygon_mesh_processing/CMakeLists.txt | 27 +++--- .../Polygon_mesh_processing/CMakeLists.txt | 23 ++--- .../CMakeLists.txt | 17 ++-- .../CMakeLists.txt | 19 ++-- Polyhedron/demo/Polyhedron/CMakeLists.txt | 36 +++---- .../Plugins/AABB_tree/CMakeLists.txt | 4 +- .../Plugins/Classification/CMakeLists.txt | 39 ++++---- .../Polyhedron/Plugins/Display/CMakeLists.txt | 7 +- .../demo/Polyhedron/Plugins/IO/CMakeLists.txt | 5 +- .../Polyhedron/Plugins/Mesh_3/CMakeLists.txt | 13 +-- .../Polyhedron/Plugins/PMP/CMakeLists.txt | 39 ++++---- .../Plugins/Point_set/CMakeLists.txt | 51 +++++----- .../Plugins/Surface_mesh/CMakeLists.txt | 17 ++-- .../CMakeLists.txt | 6 +- .../CMakeLists.txt | 6 +- .../CMakeLists.txt | 6 +- .../examples/Property_map/CMakeLists.txt | 7 +- Ridges_3/examples/Ridges_3/CMakeLists.txt | 9 +- Ridges_3/test/Ridges_3/CMakeLists.txt | 6 +- .../CMakeLists.txt | 5 +- .../test/STL_Extension/CMakeLists.txt | 10 +- .../CMakeLists.txt | 24 ++--- .../benchmark/Shape_detection/CMakeLists.txt | 7 +- .../examples/Shape_detection/CMakeLists.txt | 5 +- .../test/Shape_detection/CMakeLists.txt | 3 +- .../examples/Solver_interface/CMakeLists.txt | 22 +++-- .../Spatial_searching/CMakeLists.txt | 4 +- .../examples/Spatial_searching/CMakeLists.txt | 7 +- .../examples/Spatial_sorting/CMakeLists.txt | 7 +- .../test/Spatial_sorting/CMakeLists.txt | 9 +- .../Surface_mesh_approximation/CMakeLists.txt | 16 ++-- .../Surface_mesh_approximation/CMakeLists.txt | 23 +++-- .../Surface_mesh_deformation/CMakeLists.txt | 6 +- .../Surface_mesh_deformation/CMakeLists.txt | 9 +- .../Surface_mesh_deformation/CMakeLists.txt | 13 ++- .../CMakeLists.txt | 20 ++-- .../CMakeLists.txt | 10 +- .../CMakeLists.txt | 5 +- .../CMakeLists.txt | 10 +- .../CMakeLists.txt | 6 +- .../CMakeLists.txt | 8 +- TDS_3/test/TDS_3/CMakeLists.txt | 5 +- .../applications/Triangulation/CMakeLists.txt | 7 +- .../benchmark/Triangulation/CMakeLists.txt | 8 +- .../examples/Triangulation/CMakeLists.txt | 6 +- .../test/Triangulation/CMakeLists.txt | 6 +- .../benchmark/Triangulation_3/CMakeLists.txt | 8 +- .../demo/Triangulation_3/CMakeLists.txt | 6 +- .../examples/Triangulation_3/CMakeLists.txt | 12 +-- .../test/Triangulation_3/CMakeLists.txt | 6 +- 96 files changed, 596 insertions(+), 628 deletions(-) rename Installation/cmake/modules/{CGAL_target_use_Boost_IOStreams.cmake => CGAL_Boost_iostreams_support.cmake} (54%) create mode 100644 Installation/cmake/modules/CGAL_Boost_serialization_support.cmake create mode 100644 Installation/cmake/modules/CGAL_GLPK_support.cmake create mode 100644 Installation/cmake/modules/CGAL_OpenCV_support.cmake create mode 100644 Installation/cmake/modules/CGAL_SCIP_support.cmake create mode 100644 Installation/cmake/modules/CGAL_TensorFlow_support.cmake delete mode 100644 Installation/cmake/modules/CGAL_target_use_Boost_Serialization.cmake delete mode 100644 Installation/cmake/modules/CGAL_target_use_Eigen.cmake delete mode 100644 Installation/cmake/modules/CGAL_target_use_GLPK.cmake delete mode 100644 Installation/cmake/modules/CGAL_target_use_LASLIB.cmake delete mode 100644 Installation/cmake/modules/CGAL_target_use_OpenCV.cmake delete mode 100644 Installation/cmake/modules/CGAL_target_use_OpenGR.cmake delete mode 100644 Installation/cmake/modules/CGAL_target_use_SCIP.cmake delete mode 100644 Installation/cmake/modules/CGAL_target_use_TensorFlow.cmake delete mode 100644 Installation/cmake/modules/CGAL_target_use_pointmatcher.cmake diff --git a/Bounding_volumes/examples/Approximate_min_ellipsoid_d/CMakeLists.txt b/Bounding_volumes/examples/Approximate_min_ellipsoid_d/CMakeLists.txt index 5ea12f55be3..9c066bd6cf4 100644 --- a/Bounding_volumes/examples/Approximate_min_ellipsoid_d/CMakeLists.txt +++ b/Bounding_volumes/examples/Approximate_min_ellipsoid_d/CMakeLists.txt @@ -8,15 +8,18 @@ if ( CGAL_FOUND ) # Use Eigen find_package(Eigen3 3.1.0 QUIET) #(3.1.0 or greater) + include(CGAL_Eigen_support) # create a target per cppfile file(GLOB cppfiles RELATIVE ${CMAKE_CURRENT_SOURCE_DIR} ${CMAKE_CURRENT_SOURCE_DIR}/*.cpp) foreach(cppfile ${cppfiles}) - if(NOT (${cppfile} STREQUAL "ellipsoid.cpp") OR EIGEN3_FOUND) - create_single_source_cgal_program( "${cppfile}" ) - if (EIGEN3_FOUND) - get_filename_component(target ${cppfile} NAME_WE) - CGAL_target_use_Eigen(${target}) + if(NOT (${cppfile} STREQUAL "ellipsoid.cpp") OR TARGET CGAL::Eigen_support) + get_filename_component(target ${cppfile} NAME_WE) + add_executable(${target} ${cppfile}) + if (TARGET CGAL::Eigen_support) + target_link_libraries(${target} CGAL::CGAL CGAL::Eigen_support) + else() + target_link_libraries(${target} CGAL::CGAL) endif() endif() endforeach() @@ -26,4 +29,3 @@ else() message(STATUS "This program requires the CGAL library, and will not be compiled.") endif() - diff --git a/Bounding_volumes/test/Bounding_volumes/CMakeLists.txt b/Bounding_volumes/test/Bounding_volumes/CMakeLists.txt index 804517aea26..5a29e19f887 100644 --- a/Bounding_volumes/test/Bounding_volumes/CMakeLists.txt +++ b/Bounding_volumes/test/Bounding_volumes/CMakeLists.txt @@ -14,15 +14,18 @@ if ( CGAL_FOUND ) # Use Eigen find_package(Eigen3 3.1.0 QUIET) #(3.1.0 or greater) + include(CGAL_Eigen_support) # create a target per cppfile file(GLOB cppfiles RELATIVE ${CMAKE_CURRENT_SOURCE_DIR} ${CMAKE_CURRENT_SOURCE_DIR}/*.cpp) foreach(cppfile ${cppfiles}) - if(NOT (${cppfile} STREQUAL "Approximate_min_ellipsoid_d.cpp") OR EIGEN3_FOUND) - create_single_source_cgal_program( "${cppfile}" ) - if (EIGEN3_FOUND) - get_filename_component(target ${cppfile} NAME_WE) - CGAL_target_use_Eigen(${target}) + if(NOT (${cppfile} STREQUAL "Approximate_min_ellipsoid_d.cpp") OR TARGET CGAL::Eigen_support) + get_filename_component(target ${cppfile} NAME_WE) + add_executable(${target} ${cppfile}) + if (TARGET CGAL::Eigen_support) + target_link_libraries(${target} CGAL::CGAL CGAL::Eigen_support) + else() + target_link_libraries(${target} CGAL::CGAL) endif() endif() endforeach() @@ -32,4 +35,3 @@ else() message(STATUS "This program requires the CGAL library, and will not be compiled.") endif() - diff --git a/Box_intersection_d/test/Box_intersection_d/CMakeLists.txt b/Box_intersection_d/test/Box_intersection_d/CMakeLists.txt index 6f4ec1704ce..de7955c4208 100644 --- a/Box_intersection_d/test/Box_intersection_d/CMakeLists.txt +++ b/Box_intersection_d/test/Box_intersection_d/CMakeLists.txt @@ -8,6 +8,7 @@ project( Box_intersection_d_Tests ) find_package( CGAL QUIET ) find_package( TBB ) +include(CGAL_TBB_support) if ( CGAL_FOUND ) @@ -16,12 +17,11 @@ if ( CGAL_FOUND ) create_single_source_cgal_program( "random_set_test.cpp" ) create_single_source_cgal_program( "test_box_grid.cpp" ) - if( TBB_FOUND ) - CGAL_target_use_TBB( test_box_grid ) + if(TARGET CGAL::TBB_support) + target_link_libraries(test_box_grid PUBLIC CGAL::TBB_support) else() message( STATUS "NOTICE: Intel TBB was not found. Sequential code will be used." ) endif() else() message(STATUS "This program requires the CGAL library, and will not be compiled.") endif() - diff --git a/CGAL_ipelets/demo/CGAL_ipelets/CMakeLists.txt b/CGAL_ipelets/demo/CGAL_ipelets/CMakeLists.txt index 18e2f342352..6e6749d8619 100644 --- a/CGAL_ipelets/demo/CGAL_ipelets/CMakeLists.txt +++ b/CGAL_ipelets/demo/CGAL_ipelets/CMakeLists.txt @@ -27,7 +27,8 @@ if ( CGAL_FOUND ) include(${CGAL_USE_FILE}) find_package(Eigen3 3.1.0) #(requires 3.1.0 or greater) - if (NOT EIGEN3_FOUND) + include(CGAL_Eigen_support) + if (NOT TARGET CGAL::Eigen_support) message(STATUS "NOTICE: This project requires the Eigen library, and will not be compiled.") return() endif() @@ -140,8 +141,7 @@ if ( CGAL_FOUND ) foreach(IPELET ${CGAL_IPELETS}) add_library(CGAL_${IPELET} MODULE ${IPELET}.cpp) add_to_cached_list(CGAL_EXECUTABLE_TARGETS CGAL_${IPELET}) - target_link_libraries(CGAL_${IPELET} PRIVATE CGAL::CGAL ${IPE_LIBRARIES}) - CGAL_target_use_Eigen(CGAL_${IPELET}) + target_link_libraries(CGAL_${IPELET} PRIVATE CGAL::CGAL CGAL::Eigen_support ${IPE_LIBRARIES}) if ( IPELET_INSTALL_DIR ) install(TARGETS CGAL_${IPELET} DESTINATION ${IPELET_INSTALL_DIR}) if (WITH_IPE_7) @@ -151,14 +151,12 @@ if ( CGAL_FOUND ) cgal_add_compilation_test(CGAL_${IPELET}) endforeach(IPELET) if(CGAL_Core_FOUND) - target_link_libraries(CGAL_cone_spanners PRIVATE CGAL::CGAL_Core) - CGAL_target_use_Eigen(CGAL_cone_spanners) + target_link_libraries(CGAL_cone_spanners PRIVATE CGAL::CGAL_Core CGAL::Eigen_support) endif() #example in doc not installed add_library(simple_triangulation MODULE simple_triangulation.cpp) add_to_cached_list(CGAL_EXECUTABLE_TARGETS simple_triangulation) - target_link_libraries(simple_triangulation ${IPE_LIBRARIES}) - CGAL_target_use_Eigen(simple_triangulation) + target_link_libraries(simple_triangulation CGAL::Eigen_support ${IPE_LIBRARIES}) cgal_add_compilation_test(simple_triangulation) else() diff --git a/Classification/examples/Classification/CMakeLists.txt b/Classification/examples/Classification/CMakeLists.txt index f2e1cf3ec61..4aea4f3ebc4 100644 --- a/Classification/examples/Classification/CMakeLists.txt +++ b/Classification/examples/Classification/CMakeLists.txt @@ -24,32 +24,39 @@ endif() set(Classification_dependencies_met TRUE) find_package( Boost OPTIONAL_COMPONENTS serialization iostreams ) -if (NOT Boost_SERIALIZATION_FOUND) +include(CGAL_Boost_serialization_support) +include(CGAL_Boost_iostreams_support) + +if (NOT TARGET CGAL::Boost_serialization_support) message(STATUS "NOTICE: This project requires Boost Serialization, and will not be compiled.") set(Classification_dependencies_met FALSE) endif() -if (NOT Boost_IOSTREAMS_FOUND) +if (NOT TARGET CGAL::Boost_iostreams_support) message(STATUS "NOTICE: This project requires Boost IO Streams, and will not be compiled.") set(Classification_dependencies_met FALSE) endif() find_package(OpenCV QUIET COMPONENTS core ml) # Need core + machine learning -if (NOT OpenCV_FOUND) +include(CGAL_OpenCV_support) +if (NOT TARGET CGAL::OpenCV_support) message(STATUS "NOTICE: OpenCV was not found. OpenCV random forest predicate for classification won't be available.") endif() find_package(TensorFlow QUIET) -if (NOT TensorFlow_FOUND) +include(CGAL_TensorFlow_support) +if (NOT TARGET CGAL::TensorFlow_support) message(STATUS "NOTICE: TensorFlow was not found. TensorFlow neural network predicate for classification won't be available.") endif() find_package(Eigen3 3.1.0 REQUIRED) #(3.1.0 or greater) -if (NOT EIGEN3_FOUND) +include(CGAL_Eigen_support) +if (NOT TARGET CGAL::Eigen_support) message(STATUS "This project requires the Eigen library, and will not be compiled.") set(Classification_dependencies_met FALSE) endif() find_package(TBB QUIET) +include(CGAL_TBB_support) if (NOT Classification_dependencies_met) return() @@ -62,14 +69,14 @@ create_single_source_cgal_program( "example_generation_and_training.cpp" ) create_single_source_cgal_program( "example_mesh_classification.cpp" ) create_single_source_cgal_program( "example_cluster_classification.cpp" ) -if (OpenCV_FOUND) +if (TARGET CGAL::OpenCV_support) create_single_source_cgal_program( "example_opencv_random_forest.cpp" ) - CGAL_target_use_OpenCV(example_opencv_random_forest) + target_link_libraries(example_opencv_random_forest PUBLIC CGAL::OpenCV_support) endif() -if (TensorFlow_FOUND) +if (TARGET CGAL::TensorFlow_support) create_single_source_cgal_program( "example_tensorflow_neural_network.cpp" ) - CGAL_target_use_TensorFlow(example_tensorflow_neural_network) + target_link_libraries(example_opencv_random_forest PUBLIC CGAL::TensorFlow_support) endif() foreach(target @@ -82,12 +89,12 @@ foreach(target example_opencv_random_forest example_tensorflow_neural_network) if(TARGET ${target}) - CGAL_target_use_Eigen(${target}) - CGAL_target_use_Boost_IOStreams(${target}) - CGAL_target_use_Boost_Serialization(${target}) - if(TBB_FOUND) - CGAL_target_use_TBB(${target}) + target_link_libraries(${target} PUBLIC + CGAL::Eigen_support + CGAL::Boost_iostreams_support + CGAL::Boost_serialization_support) + if(TARGET CGAL::TBB_support) + target_link_libraries(${target} PUBLIC CGAL::TBB_support) endif() endif() endforeach() - diff --git a/Classification/test/Classification/CMakeLists.txt b/Classification/test/Classification/CMakeLists.txt index 9dc6193801a..a93e0277355 100644 --- a/Classification/test/Classification/CMakeLists.txt +++ b/Classification/test/Classification/CMakeLists.txt @@ -24,17 +24,21 @@ endif() set(Classification_dependencies_met TRUE) find_package( Boost OPTIONAL_COMPONENTS serialization iostreams ) -if (NOT Boost_SERIALIZATION_FOUND) +include(CGAL_Boost_serialization_support) +include(CGAL_Boost_iostreams_support) + +if (NOT TARGET CGAL::Boost_serialization_support) message(STATUS "NOTICE: This project requires Boost Serialization, and will not be compiled.") set(Classification_dependencies_met FALSE) endif() -if (NOT Boost_IOSTREAMS_FOUND) +if (NOT TARGET CGAL::Boost_iostreams_support) message(STATUS "NOTICE: This project requires Boost IO Streams, and will not be compiled.") set(Classification_dependencies_met FALSE) endif() find_package(Eigen3 3.1.0 REQUIRED) #(3.1.0 or greater) -if (NOT EIGEN3_FOUND) +include(CGAL_Eigen_support) +if (NOT TARGET CGAL::Eigen_support) message(STATUS "This project requires the Eigen library, and will not be compiled.") set(Classification_dependencies_met FALSE) endif() @@ -49,11 +53,11 @@ create_single_source_cgal_program( "test_classification_point_set.cpp" ) create_single_source_cgal_program( "test_classification_io.cpp" ) foreach(target test_classification_point_set test_classification_io) - CGAL_target_use_Eigen(${target}) - CGAL_target_use_Boost_IOStreams(${target}) - CGAL_target_use_Boost_Serialization(${target}) - if(TBB_FOUND) - CGAL_target_use_TBB(${target}) + target_link_libraries(${target} PUBLIC + CGAL::Eigen_support + CGAL::Boost_iostreams_support + CGAL::Boost_serialization_support) + if(TARGET CGAL::TBB_support) + target_link_libraries(${target} PUBLIC CGAL::TBB_support) endif() endforeach() - diff --git a/Generator/examples/Generator/CMakeLists.txt b/Generator/examples/Generator/CMakeLists.txt index c5ac751d26c..fa8efe5d09a 100644 --- a/Generator/examples/Generator/CMakeLists.txt +++ b/Generator/examples/Generator/CMakeLists.txt @@ -12,17 +12,18 @@ if ( CGAL_FOUND ) # Use Eigen find_package(Eigen3 3.1.0 QUIET) #(3.1.0 or greater) + include(CGAL_Eigen_support) # create a target per cppfile file(GLOB cppfiles RELATIVE ${CMAKE_CURRENT_SOURCE_DIR} ${CMAKE_CURRENT_SOURCE_DIR}/*.cpp) foreach(cppfile ${cppfiles}) if(NOT (${cppfile} STREQUAL "random_points_in_tetrahedral_mesh_3.cpp") OR NOT (${cppfile} STREQUAL "random_points_on_tetrahedral_mesh_3.cpp") - OR EIGEN3_FOUND) + OR TARGET CGAL::Eigen_support) create_single_source_cgal_program( "${cppfile}" ) - if (EIGEN3_FOUND) + if (TARGET CGAL::Eigen_support) get_filename_component(target ${cppfile} NAME_WE) - CGAL_target_use_Eigen(${target}) + target_link_libraries(${target} PUBLIC CGAL::Eigen_support) endif() endif() endforeach() @@ -32,4 +33,3 @@ else() message(STATUS "This program requires the CGAL library, and will not be compiled.") endif() - diff --git a/Generator/test/Generator/CMakeLists.txt b/Generator/test/Generator/CMakeLists.txt index 3f24895ab6a..a757803d15c 100644 --- a/Generator/test/Generator/CMakeLists.txt +++ b/Generator/test/Generator/CMakeLists.txt @@ -12,15 +12,16 @@ if ( CGAL_FOUND ) # Use Eigen find_package(Eigen3 3.1.0 QUIET) #(3.1.0 or greater) + include(CGAL_Eigen_support) # create a target per cppfile file(GLOB cppfiles RELATIVE ${CMAKE_CURRENT_SOURCE_DIR} ${CMAKE_CURRENT_SOURCE_DIR}/*.cpp) foreach(cppfile ${cppfiles}) - if(NOT (${cppfile} STREQUAL "generic_random_test.cpp") OR EIGEN3_FOUND) + if(NOT (${cppfile} STREQUAL "generic_random_test.cpp") OR TARGET CGAL::Eigen_support) create_single_source_cgal_program( "${cppfile}" ) - if (EIGEN3_FOUND) + if (TARGET CGAL::Eigen_support) get_filename_component(target ${cppfile} NAME_WE) - CGAL_target_use_Eigen(${target}) + target_link_libraries(${target} PUBLIC CGAL::Eigen_support) endif() endif() endforeach() @@ -30,4 +31,3 @@ else() message(STATUS "This program requires the CGAL library, and will not be compiled.") endif() - diff --git a/GraphicsView/demo/Polygon/CMakeLists.txt b/GraphicsView/demo/Polygon/CMakeLists.txt index 4ef96ffcf74..a38afceeedd 100644 --- a/GraphicsView/demo/Polygon/CMakeLists.txt +++ b/GraphicsView/demo/Polygon/CMakeLists.txt @@ -16,7 +16,8 @@ endif() find_package(CGAL COMPONENTS Qt5 Core) find_package(Eigen3 3.1.0) #(requires 3.1.0 or greater) -if (NOT EIGEN3_FOUND) +include(CGAL_Eigen_support) +if (NOT TARGET CGAL::Eigen_support) message(STATUS "NOTICE: This project requires the Eigen library, and will not be compiled.") return() endif() @@ -46,12 +47,11 @@ if ( CGAL_FOUND AND CGAL_Qt5_FOUND AND Qt5_FOUND ) # The executable itself. add_executable ( Polygon_2 Polygon_2.cpp ${DT_UI_FILES} ${DT_RESOURCE_FILES} ${CGAL_Qt5_RESOURCE_FILES} ${CGAL_Qt5_MOC_FILES} ) - CGAL_target_use_Eigen(Polygon_2) add_to_cached_list( CGAL_EXECUTABLE_TARGETS Polygon_2 ) target_link_libraries( Polygon_2 PRIVATE - CGAL::CGAL CGAL::CGAL_Qt5 Qt5::Gui ) + CGAL::CGAL CGAL::CGAL_Qt5 CGAL::Eigen_support Qt5::Gui ) include(${CGAL_MODULES_DIR}/CGAL_add_test.cmake) cgal_add_compilation_test(Polygon_2) diff --git a/Heat_method_3/examples/Heat_method_3/CMakeLists.txt b/Heat_method_3/examples/Heat_method_3/CMakeLists.txt index f9703071b81..0a29731a259 100644 --- a/Heat_method_3/examples/Heat_method_3/CMakeLists.txt +++ b/Heat_method_3/examples/Heat_method_3/CMakeLists.txt @@ -33,8 +33,9 @@ endif() find_package(Eigen3 3.3.0) +include(CGAL_Eigen_support) -if (NOT EIGEN3_FOUND) +if (NOT TARGET CGAL::Eigen_support) message(STATUS "This project requires the Eigen library (3.3 or greater), and will not be compiled.") return() endif() @@ -51,10 +52,10 @@ include_directories( BEFORE include ) include( CGAL_CreateSingleSourceCGALProgram ) create_single_source_cgal_program( "heat_method.cpp" ) -CGAL_target_use_Eigen(heat_method) +target_link_libraries(heat_method PUBLIC CGAL::Eigen_support) create_single_source_cgal_program( "heat_method_polyhedron.cpp" ) -CGAL_target_use_Eigen(heat_method_polyhedron) +target_link_libraries(heat_method_polyhedron PUBLIC CGAL::Eigen_support) create_single_source_cgal_program( "heat_method_surface_mesh.cpp" ) -CGAL_target_use_Eigen(heat_method_surface_mesh) +target_link_libraries(heat_method_surface_mesh PUBLIC CGAL::Eigen_support) create_single_source_cgal_program( "heat_method_surface_mesh_direct.cpp" ) -CGAL_target_use_Eigen(heat_method_surface_mesh_direct) +target_link_libraries(heat_method_surface_mesh_direct PUBLIC CGAL::Eigen_support) diff --git a/Heat_method_3/test/Heat_method_3/CMakeLists.txt b/Heat_method_3/test/Heat_method_3/CMakeLists.txt index 7876d80a53b..9a86ed7236c 100644 --- a/Heat_method_3/test/Heat_method_3/CMakeLists.txt +++ b/Heat_method_3/test/Heat_method_3/CMakeLists.txt @@ -33,8 +33,9 @@ endif() find_package(Eigen3 3.3.0) +include(CGAL_Eigen_support) -if (NOT EIGEN3_FOUND) +if (NOT TARGET CGAL::Eigen_support) message(STATUS "This project requires the Eigen library (3.3 or greater), and will not be compiled.") return() endif() @@ -49,8 +50,8 @@ include_directories( BEFORE include ) include( CGAL_CreateSingleSourceCGALProgram ) create_single_source_cgal_program( "heat_method_concept.cpp" ) -CGAL_target_use_Eigen(heat_method_concept) +target_link_libraries(heat_method_concept PUBLIC CGAL::Eigen_support) create_single_source_cgal_program( "heat_method_surface_mesh_test.cpp" ) -CGAL_target_use_Eigen(heat_method_surface_mesh_test) +target_link_libraries(heat_method_surface_mesh_test PUBLIC CGAL::Eigen_support) create_single_source_cgal_program( "heat_method_surface_mesh_direct_test.cpp" ) -CGAL_target_use_Eigen(heat_method_surface_mesh_direct_test) +target_link_libraries(heat_method_surface_mesh_direct_test PUBLIC CGAL::Eigen_support) diff --git a/Installation/cmake/modules/CGAL_target_use_Boost_IOStreams.cmake b/Installation/cmake/modules/CGAL_Boost_iostreams_support.cmake similarity index 54% rename from Installation/cmake/modules/CGAL_target_use_Boost_IOStreams.cmake rename to Installation/cmake/modules/CGAL_Boost_iostreams_support.cmake index d57f785d54f..49e5965662b 100644 --- a/Installation/cmake/modules/CGAL_target_use_Boost_IOStreams.cmake +++ b/Installation/cmake/modules/CGAL_Boost_iostreams_support.cmake @@ -1,39 +1,38 @@ -if (CGAL_target_use_Boost_IOStreams_included) - return() -endif() -set(CGAL_target_use_Boost_IOStreams_included TRUE) - -function(CGAL_target_use_Boost_IOStreams target) +if(Boost_IOSTREAMS_FOUND AND NOT TARGET CGAL::Boost_iostreams_support) if( WIN32 ) - # to avoid a warning with old cmake + + # to avoid a warning with old cmake set(_Boost_BZIP2_HEADERS "boost/iostreams/filter/bzip2.hpp") set(_Boost_ZLIB_HEADERS "boost/iostreams/filter/zlib.hpp") find_package( Boost OPTIONAL_COMPONENTS bzip2 zlib) - else() - find_package(ZLIB QUIET) - endif() - - if(TARGET Boost::iostreams) - target_link_libraries(${target} PUBLIC Boost::iostreams) - else() - target_link_libraries(${target} PUBLIC ${Boost_IOSTREAMS_LIBRARY}) - endif() - - if( WIN32 ) if (Boost_ZLIB_FOUND AND Boost_BZIP2_FOUND) - target_link_libraries(${target} PUBLIC ${Boost_ZLIB_LIBRARY} ${Boost_BZIP2_LIBRARY}) + set(ZLIB_LIBS ${Boost_ZLIB_LIBRARY} ${Boost_BZIP2_LIBRARY}) else() message(STATUS "NOTICE: This project requires Boost ZLIB and Boost BZIP2, and will not be compiled.") return() endif() + else() + + find_package(ZLIB QUIET) if(ZLIB_FOUND) - target_link_libraries(${target} PUBLIC ZLIB::ZLIB) + set(ZLIB_LIBS ZLIB::ZLIB) else() message(STATUS "NOTICE: This project requires ZLIB, and will not be compiled.") return() endif() + endif() -endfunction() + if(TARGET Boost::iostreams) + set(Boost_LIB Boost::iostreams) + else() + set(Boost_LIB ${Boost_IOSTREAMS_LIBRARY}) + endif() + + add_library(CGAL::Boost_iostreams_support INTERFACE IMPORTED) + set_target_properties(CGAL::Boost_iostreams_support PROPERTIES + INTERFACE_COMPILE_DEFINITIONS "CGAL_LINKED_WITH_BOOST_IOSTREAMS" + INTERFACE_LINK_LIBRARIES "${Boost_LIB};${ZLIB_LIBS}") +endif() diff --git a/Installation/cmake/modules/CGAL_Boost_serialization_support.cmake b/Installation/cmake/modules/CGAL_Boost_serialization_support.cmake new file mode 100644 index 00000000000..236fbb4bf0c --- /dev/null +++ b/Installation/cmake/modules/CGAL_Boost_serialization_support.cmake @@ -0,0 +1,12 @@ +if(Boost_SERIALIZATION_FOUND AND NOT TARGET CGAL::Boost_serialization_support) + if(TARGET Boost::serialization) + set(Boost_LIB Boost::serialization) + else() + set(Boost_LIB ${Boost_SERIALIZATION_LIBRARY}) + endif() + + add_library(CGAL::Boost_serialization_support INTERFACE IMPORTED) + set_target_properties(CGAL::Boost_serialization_support PROPERTIES + INTERFACE_COMPILE_DEFINITIONS "CGAL_LINKED_WITH_BOOST_SERIALIZATION" + INTERFACE_LINK_LIBRARIES "${Boost_LIB}") +endif() diff --git a/Installation/cmake/modules/CGAL_Common.cmake b/Installation/cmake/modules/CGAL_Common.cmake index 786763eb01f..ed1fe54ad0c 100644 --- a/Installation/cmake/modules/CGAL_Common.cmake +++ b/Installation/cmake/modules/CGAL_Common.cmake @@ -23,7 +23,7 @@ if( NOT CGAL_COMMON_FILE_INCLUDED ) else() set( CMAKE_2_6_3_OR_ABOVE FALSE ) endif() - + if ( CGAL_BUILDING_LIBS ) option(BUILD_SHARED_LIBS "Build shared libraries" ON) set(CGAL_BUILD_SHARED_LIBS ${BUILD_SHARED_LIBS}) @@ -34,7 +34,7 @@ if( NOT CGAL_COMMON_FILE_INCLUDED ) message( STATUS "Building static libraries" ) endif() endif() - + if ( WIN32 ) find_program(CMAKE_UNAME uname /bin /usr/bin /usr/local/bin ) if(CMAKE_UNAME) @@ -61,15 +61,4 @@ if( NOT CGAL_COMMON_FILE_INCLUDED ) # set use-file for Eigen3 (needed to have default solvers) set(EIGEN3_USE_FILE "UseEigen3") - include(${CMAKE_CURRENT_LIST_DIR}/CGAL_target_use_Boost_IOStreams.cmake) - include(${CMAKE_CURRENT_LIST_DIR}/CGAL_target_use_Boost_Serialization.cmake) - include(${CMAKE_CURRENT_LIST_DIR}/CGAL_target_use_Eigen.cmake) - include(${CMAKE_CURRENT_LIST_DIR}/CGAL_target_use_GLPK.cmake) - include(${CMAKE_CURRENT_LIST_DIR}/CGAL_target_use_LASLIB.cmake) - include(${CMAKE_CURRENT_LIST_DIR}/CGAL_target_use_OpenCV.cmake) - include(${CMAKE_CURRENT_LIST_DIR}/CGAL_target_use_OpenGR.cmake) - include(${CMAKE_CURRENT_LIST_DIR}/CGAL_target_use_pointmatcher.cmake) - include(${CMAKE_CURRENT_LIST_DIR}/CGAL_target_use_SCIP.cmake) - include(${CMAKE_CURRENT_LIST_DIR}/CGAL_target_use_TBB.cmake) - include(${CMAKE_CURRENT_LIST_DIR}/CGAL_target_use_TensorFlow.cmake) endif() diff --git a/Installation/cmake/modules/CGAL_Eigen_support.cmake b/Installation/cmake/modules/CGAL_Eigen_support.cmake index 31e5f22abf5..5039bd5871a 100644 --- a/Installation/cmake/modules/CGAL_Eigen_support.cmake +++ b/Installation/cmake/modules/CGAL_Eigen_support.cmake @@ -1,4 +1,4 @@ -if(Eigen_FOUND AND NOT TARGET CGAL::Eigen_support) +if(EIGEN3_FOUND AND NOT TARGET CGAL::Eigen_support) if(NOT TARGET Threads::Threads) find_package(Threads REQUIRED) endif() diff --git a/Installation/cmake/modules/CGAL_GLPK_support.cmake b/Installation/cmake/modules/CGAL_GLPK_support.cmake new file mode 100644 index 00000000000..391fdf6263f --- /dev/null +++ b/Installation/cmake/modules/CGAL_GLPK_support.cmake @@ -0,0 +1,7 @@ +if(GLPK_FOUND AND NOT TARGET CGAL::GLPK_support) + add_library(CGAL::GLPK_support INTERFACE IMPORTED) + set_target_properties(CGAL::GLPK_support PROPERTIES + INTERFACE_COMPILE_DEFINITIONS "CGAL_USE_GLPK" + INTERFACE_INCLUDE_DIRECTORIES "${GLPK_INCLUDE_DIR}" + INTERFACE_LINK_LIBRARIES "${GLPK_LIBRARIES}") +endif() diff --git a/Installation/cmake/modules/CGAL_OpenCV_support.cmake b/Installation/cmake/modules/CGAL_OpenCV_support.cmake new file mode 100644 index 00000000000..84b4e9dd34d --- /dev/null +++ b/Installation/cmake/modules/CGAL_OpenCV_support.cmake @@ -0,0 +1,7 @@ +if(OpenCV_FOUND AND NOT TARGET CGAL::OpenCV_support) + add_library(CGAL::OpenCV_support INTERFACE IMPORTED) + set_target_properties(CGAL::OpenCV_support PROPERTIES + INTERFACE_COMPILE_DEFINITIONS "CGAL_LINKED_WITH_OPENCV" + INTERFACE_INCLUDE_DIRECTORIES "${OpenCV_INCLUDE_DIRS}" + INTERFACE_LINK_LIBRARIES "${OpenCV_LIBS}") +endif() diff --git a/Installation/cmake/modules/CGAL_SCIP_support.cmake b/Installation/cmake/modules/CGAL_SCIP_support.cmake new file mode 100644 index 00000000000..6035b6d64cd --- /dev/null +++ b/Installation/cmake/modules/CGAL_SCIP_support.cmake @@ -0,0 +1,7 @@ +if(SCIP_FOUND AND NOT TARGET CGAL::SCIP_support) + add_library(CGAL::SCIP_support INTERFACE IMPORTED) + set_target_properties(CGAL::SCIP_support PROPERTIES + INTERFACE_COMPILE_DEFINITIONS "CGAL_USE_SCIP" + INTERFACE_INCLUDE_DIRECTORIES "${SCIP_INCLUDE_DIRS}" + INTERFACE_LINK_LIBRARIES "${SCIP_LIBRARIES}") +endif() diff --git a/Installation/cmake/modules/CGAL_TBB_support.cmake b/Installation/cmake/modules/CGAL_TBB_support.cmake index e34882e949c..372f3208578 100644 --- a/Installation/cmake/modules/CGAL_TBB_support.cmake +++ b/Installation/cmake/modules/CGAL_TBB_support.cmake @@ -6,5 +6,5 @@ if(TBB_FOUND AND NOT TARGET CGAL::TBB_support) set_target_properties(CGAL::TBB_support PROPERTIES INTERFACE_COMPILE_DEFINITIONS "CGAL_LINKED_WITH_TBB;NOMINMAX" INTERFACE_INCLUDE_DIRECTORIES "${TBB_INCLUDE_DIRS}" - INTERFACE_LINK_LIBRARIES "TBB:tbb;TBB:tbbmalloc;Threads::Threads") + INTERFACE_LINK_LIBRARIES "TBB::tbb;TBB::tbbmalloc;Threads::Threads") endif() diff --git a/Installation/cmake/modules/CGAL_TensorFlow_support.cmake b/Installation/cmake/modules/CGAL_TensorFlow_support.cmake new file mode 100644 index 00000000000..2a910c1257e --- /dev/null +++ b/Installation/cmake/modules/CGAL_TensorFlow_support.cmake @@ -0,0 +1,7 @@ +if(TensorFlow_FOUND AND NOT TARGET CGAL::TensorFlow_support) + add_library(CGAL::TensorFlow_support INTERFACE IMPORTED) + set_target_properties(CGAL::TensorFlow_support PROPERTIES + INTERFACE_COMPILE_DEFINITIONS "CGAL_LINKED_WITH_TENSORFLOW" + INTERFACE_INCLUDE_DIRECTORIES "${TensorFlow_INCLUDE_DIR}" + INTERFACE_LINK_LIBRARIES "${TensorFlow_LIBRARY}") +endif() diff --git a/Installation/cmake/modules/CGAL_target_use_Boost_Serialization.cmake b/Installation/cmake/modules/CGAL_target_use_Boost_Serialization.cmake deleted file mode 100644 index d6ae805efd8..00000000000 --- a/Installation/cmake/modules/CGAL_target_use_Boost_Serialization.cmake +++ /dev/null @@ -1,14 +0,0 @@ -if (CGAL_target_use_Boost_Serialization_included) - return() -endif() -set(CGAL_target_use_Boost_Serialization_included TRUE) - -function(CGAL_target_use_Boost_Serialization target) - - if(TARGET Boost::serialization) - target_link_libraries(${target} PUBLIC Boost::serialization) - else() - target_link_libraries(${target} PUBLIC ${Boost_SERIALIZATION_LIBRARY}) - endif() - -endfunction() diff --git a/Installation/cmake/modules/CGAL_target_use_Eigen.cmake b/Installation/cmake/modules/CGAL_target_use_Eigen.cmake deleted file mode 100644 index 84f9f3be721..00000000000 --- a/Installation/cmake/modules/CGAL_target_use_Eigen.cmake +++ /dev/null @@ -1,13 +0,0 @@ -if (CGAL_target_use_Eigen_included) - return() -endif() -set(CGAL_target_use_Eigen_included TRUE) - -set( Eigen3_FIND_VERSION "3.1.0") -set(EIGEN3_USE_FILE "UseEigen3") - -function(CGAL_target_use_Eigen target) - target_include_directories(${target} PUBLIC ${EIGEN3_INCLUDE_DIR}) - target_compile_options( ${target} PUBLIC -DCGAL_EIGEN3_ENABLED) -endfunction() - diff --git a/Installation/cmake/modules/CGAL_target_use_GLPK.cmake b/Installation/cmake/modules/CGAL_target_use_GLPK.cmake deleted file mode 100644 index f19bd315b16..00000000000 --- a/Installation/cmake/modules/CGAL_target_use_GLPK.cmake +++ /dev/null @@ -1,11 +0,0 @@ -if (CGAL_target_use_GLPK_included) - return() -endif() -set(CGAL_target_use_GLPK_included TRUE) - -function(CGAL_target_use_GLPK target) - target_include_directories(${target} PUBLIC ${GLPK_INCLUDE_DIR}) - target_compile_options(${target} PUBLIC -DCGAL_USE_GLPK) - target_link_libraries(${target} PUBLIC ${GLPK_LIBRARIES}) -endfunction() - diff --git a/Installation/cmake/modules/CGAL_target_use_LASLIB.cmake b/Installation/cmake/modules/CGAL_target_use_LASLIB.cmake deleted file mode 100644 index 65ad9084e5a..00000000000 --- a/Installation/cmake/modules/CGAL_target_use_LASLIB.cmake +++ /dev/null @@ -1,11 +0,0 @@ -if (CGAL_target_use_LASLIB_included) - return() -endif() -set(CGAL_target_use_LASLIB_included TRUE) - -function(CGAL_target_use_LASLIB target) - target_include_directories(${target} PUBLIC ${LASLIB_INCLUDE_DIR}) - target_include_directories(${target} PUBLIC ${LASZIP_INCLUDE_DIR}) - target_compile_options( ${target} PUBLIC -DCGAL_LINKED_WITH_LASLIB) - target_link_libraries(${target} PUBLIC ${LASLIB_LIBRARIES}) -endfunction() diff --git a/Installation/cmake/modules/CGAL_target_use_OpenCV.cmake b/Installation/cmake/modules/CGAL_target_use_OpenCV.cmake deleted file mode 100644 index d378d50aead..00000000000 --- a/Installation/cmake/modules/CGAL_target_use_OpenCV.cmake +++ /dev/null @@ -1,10 +0,0 @@ -if (CGAL_target_use_OpenCV_included) - return() -endif() -set(CGAL_target_use_OpenCV_included TRUE) - -function(CGAL_target_use_OpenCV target) - target_include_directories(${target} PUBLIC ${OpenCV_INCLUDE_DIRS}) - target_compile_options( ${target} PUBLIC -DCGAL_LINKED_WITH_OPENCV) - target_link_libraries(${target} PUBLIC ${OpenCV_LIBS}) -endfunction() diff --git a/Installation/cmake/modules/CGAL_target_use_OpenGR.cmake b/Installation/cmake/modules/CGAL_target_use_OpenGR.cmake deleted file mode 100644 index dc6044f8926..00000000000 --- a/Installation/cmake/modules/CGAL_target_use_OpenGR.cmake +++ /dev/null @@ -1,9 +0,0 @@ -if (CGAL_target_use_OpenGR_included) - return() -endif() -set(CGAL_target_use_OpenGR_included TRUE) - -function(CGAL_target_use_OpenGR target) - target_include_directories(${target} PUBLIC ${OpenGR_INCLUDE_DIR}) - target_compile_options( ${target} PUBLIC -DCGAL_LINKED_WITH_OPENGR) -endfunction() diff --git a/Installation/cmake/modules/CGAL_target_use_SCIP.cmake b/Installation/cmake/modules/CGAL_target_use_SCIP.cmake deleted file mode 100644 index 354216bb1f7..00000000000 --- a/Installation/cmake/modules/CGAL_target_use_SCIP.cmake +++ /dev/null @@ -1,11 +0,0 @@ -if (CGAL_target_use_SCIP_included) - return() -endif() -set(CGAL_target_use_SCIP_included TRUE) - -function(CGAL_target_use_SCIP target) - target_include_directories(${target} PUBLIC ${SCIP_INCLUDE_DIRS}) - target_compile_options(${target} PUBLIC -DCGAL_USE_SCIP) - target_link_libraries(${target} PUBLIC ${SCIP_LIBRARIES}) -endfunction() - diff --git a/Installation/cmake/modules/CGAL_target_use_TBB.cmake b/Installation/cmake/modules/CGAL_target_use_TBB.cmake index 76c41c4ec25..5f68060eea5 100644 --- a/Installation/cmake/modules/CGAL_target_use_TBB.cmake +++ b/Installation/cmake/modules/CGAL_target_use_TBB.cmake @@ -6,7 +6,9 @@ set(CGAL_target_use_TBB_included TRUE) set(TBB_USE_FILE "UseTBB") function(CGAL_target_use_TBB target) - if(NOT TARGET Threads::Threads) + message(DEPRECATION "This file CGAL_target_use_TBB.cmake is deprecated, and the imported target `CGAL::TBB_support` from CGAL_TBB_support.cmake should be used instead.") + if(NOT TARGET + Threads::Threads) find_package(Threads REQUIRED) endif() target_link_libraries( ${target} PUBLIC TBB::tbb TBB::tbbmalloc Threads::Threads) diff --git a/Installation/cmake/modules/CGAL_target_use_TensorFlow.cmake b/Installation/cmake/modules/CGAL_target_use_TensorFlow.cmake deleted file mode 100644 index 80bda689dab..00000000000 --- a/Installation/cmake/modules/CGAL_target_use_TensorFlow.cmake +++ /dev/null @@ -1,10 +0,0 @@ -if (CGAL_target_use_TensorFlow_included) - return() -endif() -set(CGAL_target_use_TensorFlow_included TRUE) - -function(CGAL_target_use_TensorFlow target) - target_include_directories(${target} PUBLIC ${TensorFlow_INCLUDE_DIR}) - target_compile_options( ${target} PUBLIC -DCGAL_LINKED_WITH_TENSORFLOW) - target_link_libraries(${target} PUBLIC ${TensorFlow_LIBRARU}) -endfunction() diff --git a/Installation/cmake/modules/CGAL_target_use_pointmatcher.cmake b/Installation/cmake/modules/CGAL_target_use_pointmatcher.cmake deleted file mode 100644 index 5047815a336..00000000000 --- a/Installation/cmake/modules/CGAL_target_use_pointmatcher.cmake +++ /dev/null @@ -1,10 +0,0 @@ -if (CGAL_target_use_pointmatcher_included) - return() -endif() -set(CGAL_target_use_pointmatcher_included TRUE) - -function(CGAL_target_use_pointmatcher target) - target_include_directories(${target} PUBLIC ${libpointmatcher_INCLUDE_DIR}) - target_compile_options( ${target} PUBLIC -DCGAL_LINKED_WITH_POINTMATCHER) - target_link_libraries(${target} PUBLIC ${libpointmatcher_LIBRARIES}) -endfunction() diff --git a/Installation/cmake/modules/UseTBB.cmake b/Installation/cmake/modules/UseTBB.cmake index 5a22f6f079a..a1322a2f3a6 100644 --- a/Installation/cmake/modules/UseTBB.cmake +++ b/Installation/cmake/modules/UseTBB.cmake @@ -5,4 +5,4 @@ include_directories ( ${TBB_INCLUDE_DIRS} ) link_directories( ${TBB_LIBRARY_DIRS} ) add_definitions( -DNOMINMAX -DCGAL_LINKED_WITH_TBB ) -message(DEPRECATION "This file UseTBB.cmake is deprecated, and the function `CGAL_target_use_TBB` from CGAL_target_use_TBB.cmake should be used instead.") +message(DEPRECATION "This file UseTBB.cmake is deprecated, and the imported target `CGAL::TBB_support` from CGAL_TBB_support.cmake should be used instead.") diff --git a/Installation/test/Installation/CMakeLists.txt b/Installation/test/Installation/CMakeLists.txt index cba75d0bb15..7dd169ead9f 100644 --- a/Installation/test/Installation/CMakeLists.txt +++ b/Installation/test/Installation/CMakeLists.txt @@ -48,9 +48,10 @@ if ( CGAL_FOUND ) endif() find_package( TBB QUIET ) + include(CGAL_TBB_support) create_single_source_cgal_program( "test_TBB.cpp" ) - if(TBB_FOUND) - CGAL_target_use_TBB(test_TBB) + if(TARGET CGAl::TBB_support) + target_link_libraries(test_TBB PUBLIC CGAL::TBB_support) endif() create_link_to_program(CGAL) diff --git a/Jet_fitting_3/examples/Jet_fitting_3/CMakeLists.txt b/Jet_fitting_3/examples/Jet_fitting_3/CMakeLists.txt index b52c55f79a3..74595d7724f 100644 --- a/Jet_fitting_3/examples/Jet_fitting_3/CMakeLists.txt +++ b/Jet_fitting_3/examples/Jet_fitting_3/CMakeLists.txt @@ -13,7 +13,8 @@ if ( CGAL_FOUND ) # use Eigen find_package(Eigen3 3.1.0) #(requires 3.1.0 or greater) - if (EIGEN3_FOUND) + include(CGAL_Eigen_support) + if (TARGET CGAL::Eigen_support) # Link with Boost.ProgramOptions (optional) find_package(Boost QUIET COMPONENTS program_options) if(Boost_PROGRAM_OPTIONS_FOUND) @@ -30,9 +31,9 @@ if ( CGAL_FOUND ) endif() create_single_source_cgal_program( "Mesh_estimation.cpp" ) - CGAL_target_use_Eigen(Mesh_estimation) + target_link_libraries(Mesh_estimation PUBLIC CGAL::Eigen_support) create_single_source_cgal_program( "Single_estimation.cpp" ) - CGAL_target_use_Eigen(Single_estimation) + target_link_libraries(Single_estimation PUBLIC CGAL::Eigen_support) else() message(STATUS "NOTICE: This program requires Eigen 3.1 (or greater) and will not be compiled.") @@ -43,4 +44,3 @@ else() message(STATUS "NOTICE: This program requires the CGAL library, and will not be compiled.") endif() - diff --git a/Jet_fitting_3/test/Jet_fitting_3/CMakeLists.txt b/Jet_fitting_3/test/Jet_fitting_3/CMakeLists.txt index feff5e7bb7a..2ff8f62b541 100644 --- a/Jet_fitting_3/test/Jet_fitting_3/CMakeLists.txt +++ b/Jet_fitting_3/test/Jet_fitting_3/CMakeLists.txt @@ -13,9 +13,10 @@ if ( CGAL_FOUND ) # use Eigen find_package(Eigen3 3.1.0) #(requires 3.1.0 or greater) - if (EIGEN3_FOUND) + include(CGAL_Eigen_support) + if (TARGET CGAL::Eigen_support) create_single_source_cgal_program( "blind_1pt.cpp" ) - CGAL_target_use_Eigen(blind_1pt) + target_link_libraries(blind_1pt PUBLIC CGAL::Eigen_support) else() message(STATUS "NOTICE: This program requires Eigen 3.1 (or greater) and will not be compiled.") endif() @@ -25,4 +26,3 @@ else() message(STATUS "NOTICE: This program requires the CGAL library, and will not be compiled.") endif() - diff --git a/Mesh_3/benchmark/Mesh_3/CMakeLists.txt b/Mesh_3/benchmark/Mesh_3/CMakeLists.txt index aa4ede4ecf7..1987d458724 100644 --- a/Mesh_3/benchmark/Mesh_3/CMakeLists.txt +++ b/Mesh_3/benchmark/Mesh_3/CMakeLists.txt @@ -57,12 +57,14 @@ if ( CGAL_FOUND ) if( CGAL_ACTIVATE_CONCURRENT_MESH_3 ) add_definitions( -DCGAL_CONCURRENT_MESH_3 ) find_package( TBB REQUIRED ) + include(CGAL_TBB_support) else() option( LINK_WITH_TBB "Link with TBB anyway so we can use TBB timers for profiling" ON) if( LINK_WITH_TBB ) find_package( TBB ) + include(CGAL_TBB_support) endif( LINK_WITH_TBB ) endif() @@ -81,11 +83,11 @@ if ( CGAL_FOUND ) if ( Boost_FOUND AND Boost_VERSION GREATER 103400 ) # Compilable benchmark set (BENCHMARK_SOURCE_FILES "concurrency.cpp") - if(TBB_FOUND) - CGAL_target_use_TBB(concurrency) - endif() ADD_MSVC_PRECOMPILED_HEADER("StdAfx.h" "StdAfx.cpp" BENCHMARK_SOURCE_FILES) create_single_source_cgal_program( ${BENCHMARK_SOURCE_FILES} ) + if(TARGET CGAL::TBB_support) + target_link_libraries(concurrency PUBLIC CGAL::TBB_support) + endif() else() message(STATUS "NOTICE: This program requires Boost >= 1.34.1, and will not be compiled.") @@ -94,4 +96,3 @@ if ( CGAL_FOUND ) else() message(STATUS "This program requires the CGAL library, and will not be compiled.") endif() - diff --git a/Mesh_3/examples/Mesh_3/CMakeLists.txt b/Mesh_3/examples/Mesh_3/CMakeLists.txt index 7a259ab4037..851ce574dec 100644 --- a/Mesh_3/examples/Mesh_3/CMakeLists.txt +++ b/Mesh_3/examples/Mesh_3/CMakeLists.txt @@ -34,18 +34,21 @@ if ( CGAL_FOUND ) if( CGAL_ACTIVATE_CONCURRENT_MESH_3 OR ENV{CGAL_ACTIVATE_CONCURRENT_MESH_3} ) add_definitions( -DCGAL_CONCURRENT_MESH_3 ) find_package( TBB REQUIRED ) + include(CGAL_TBB_support) else( CGAL_ACTIVATE_CONCURRENT_MESH_3 OR ENV{CGAL_ACTIVATE_CONCURRENT_MESH_3} ) option( LINK_WITH_TBB "Link with TBB anyway so we can use TBB timers for profiling" ON) if( LINK_WITH_TBB ) find_package( TBB ) + include(CGAL_TBB_support) endif( LINK_WITH_TBB ) endif() # Use Eigen find_package(Eigen3 3.1.0 REQUIRED) #(3.1.0 or greater) - if (NOT EIGEN3_FOUND) + include(CGAL_Eigen_support) + if (NOT TARGET CGAL::Eigen_support) message(STATUS "This project requires the Eigen library, and will not be compiled.") return() endif() @@ -70,92 +73,91 @@ if ( CGAL_FOUND ) # Compilable examples create_single_source_cgal_program( "mesh_hybrid_mesh_domain.cpp" ) - CGAL_target_use_Eigen(mesh_hybrid_mesh_domain) + target_link_libraries(mesh_hybrid_mesh_domain PUBLIC CGAL::Eigen_support) create_single_source_cgal_program( "mesh_implicit_sphere.cpp" ) - CGAL_target_use_Eigen(mesh_implicit_sphere) + target_link_libraries(mesh_implicit_sphere PUBLIC CGAL::Eigen_support) create_single_source_cgal_program( "mesh_implicit_sphere_variable_size.cpp" ) - CGAL_target_use_Eigen(mesh_implicit_sphere_variable_size) + target_link_libraries(mesh_implicit_sphere_variable_size PUBLIC CGAL::Eigen_support) create_single_source_cgal_program( "mesh_two_implicit_spheres_with_balls.cpp" ) - CGAL_target_use_Eigen(mesh_two_implicit_spheres_with_balls) + target_link_libraries(mesh_two_implicit_spheres_with_balls PUBLIC CGAL::Eigen_support) create_single_source_cgal_program( "mesh_implicit_domains_2.cpp" "implicit_functions.cpp" ) - CGAL_target_use_Eigen(mesh_implicit_domains_2) + target_link_libraries(mesh_implicit_domains_2 PUBLIC CGAL::Eigen_support) create_single_source_cgal_program( "mesh_cubes_intersection.cpp" ) - CGAL_target_use_Eigen(mesh_cubes_intersection) + target_link_libraries(mesh_cubes_intersection PUBLIC CGAL::Eigen_support) create_single_source_cgal_program( "mesh_cubes_intersection_with_features.cpp" ) - CGAL_target_use_Eigen(mesh_cubes_intersection_with_features) + target_link_libraries(mesh_cubes_intersection_with_features PUBLIC CGAL::Eigen_support) create_single_source_cgal_program( "mesh_implicit_domains.cpp" "implicit_functions.cpp" ) - CGAL_target_use_Eigen(mesh_implicit_domains) + target_link_libraries(mesh_implicit_domains PUBLIC CGAL::Eigen_support) create_single_source_cgal_program( "mesh_polyhedral_domain.cpp" ) - CGAL_target_use_Eigen(mesh_polyhedral_domain) + target_link_libraries(mesh_polyhedral_domain PUBLIC CGAL::Eigen_support) create_single_source_cgal_program( "mesh_polyhedral_domain_sm.cpp" ) - CGAL_target_use_Eigen(mesh_polyhedral_domain_sm) + target_link_libraries(mesh_polyhedral_domain_sm PUBLIC CGAL::Eigen_support) create_single_source_cgal_program( "mesh_polyhedral_domain_with_surface_inside.cpp" ) - CGAL_target_use_Eigen(mesh_polyhedral_domain_with_surface_inside) + target_link_libraries(mesh_polyhedral_domain_with_surface_inside PUBLIC CGAL::Eigen_support) create_single_source_cgal_program( "remesh_polyhedral_surface.cpp" ) - CGAL_target_use_Eigen(remesh_polyhedral_surface) + target_link_libraries(remesh_polyhedral_surface PUBLIC CGAL::Eigen_support) create_single_source_cgal_program( "remesh_polyhedral_surface_sm.cpp" ) - CGAL_target_use_Eigen(remesh_polyhedral_surface_sm) + target_link_libraries(remesh_polyhedral_surface_sm PUBLIC CGAL::Eigen_support) create_single_source_cgal_program( "mesh_polyhedral_domain_with_features.cpp" ) - CGAL_target_use_Eigen(mesh_polyhedral_domain_with_features) + target_link_libraries(mesh_polyhedral_domain_with_features PUBLIC CGAL::Eigen_support) create_single_source_cgal_program( "mesh_polyhedral_domain_with_features_sm.cpp" ) - CGAL_target_use_Eigen(mesh_polyhedral_domain_with_features_sm) + target_link_libraries(mesh_polyhedral_domain_with_features_sm PUBLIC CGAL::Eigen_support) create_single_source_cgal_program( "mesh_polyhedral_domain_with_lipschitz_sizing.cpp" ) - CGAL_target_use_Eigen(mesh_polyhedral_domain_with_lipschitz_sizing) + target_link_libraries(mesh_polyhedral_domain_with_lipschitz_sizing PUBLIC CGAL::Eigen_support) create_single_source_cgal_program( "mesh_polyhedral_complex.cpp" ) - CGAL_target_use_Eigen(mesh_polyhedral_complex) + target_link_libraries(mesh_polyhedral_complex PUBLIC CGAL::Eigen_support) create_single_source_cgal_program( "mesh_polyhedral_complex_sm.cpp" ) - CGAL_target_use_Eigen(mesh_polyhedral_complex_sm) + target_link_libraries(mesh_polyhedral_complex_sm PUBLIC CGAL::Eigen_support) if( WITH_CGAL_ImageIO ) if( VTK_FOUND AND ("${VTK_VERSION_MAJOR}" GREATER "5" OR VTK_VERSION VERSION_GREATER 5) ) add_executable ( mesh_3D_gray_vtk_image mesh_3D_gray_vtk_image.cpp ) - CGAL_target_use_Eigen(mesh_3D_gray_vtk_image) - target_link_libraries( mesh_3D_gray_vtk_image ${CGAL_LIBRARIES} ${CGAL_3RD_PARTY_LIBRARIES} ${VTK_LIBRARIES}) + target_link_libraries( mesh_3D_gray_vtk_image PUBLIC CGAL::Eigen_support ${CGAL_LIBRARIES} ${CGAL_3RD_PARTY_LIBRARIES} ${VTK_LIBRARIES}) cgal_add_test( mesh_3D_gray_vtk_image ) add_to_cached_list( CGAL_EXECUTABLE_TARGETS mesh_3D_gray_vtk_image ) endif() create_single_source_cgal_program( "mesh_3D_gray_image.cpp" ) - CGAL_target_use_Eigen(mesh_3D_gray_image) + target_link_libraries(mesh_3D_gray_image PUBLIC CGAL::Eigen_support) create_single_source_cgal_program( "mesh_3D_gray_image_multiple_values.cpp" ) - CGAL_target_use_Eigen(mesh_3D_gray_image_multiple_values) + target_link_libraries(mesh_3D_gray_image_multiple_values PUBLIC CGAL::Eigen_support) create_single_source_cgal_program( "mesh_3D_image_with_features.cpp" ) - CGAL_target_use_Eigen(mesh_3D_image_with_features) + target_link_libraries(mesh_3D_image_with_features PUBLIC CGAL::Eigen_support) if( CGAL_ImageIO_USE_ZLIB ) create_single_source_cgal_program( "mesh_optimization_example.cpp" ) - CGAL_target_use_Eigen(mesh_optimization_example) + target_link_libraries(mesh_optimization_example PUBLIC CGAL::Eigen_support) create_single_source_cgal_program( "mesh_optimization_lloyd_example.cpp" ) - CGAL_target_use_Eigen(mesh_optimization_lloyd_example) + target_link_libraries(mesh_optimization_lloyd_example PUBLIC CGAL::Eigen_support) create_single_source_cgal_program( "mesh_3D_image.cpp" ) - CGAL_target_use_Eigen(mesh_3D_image) + target_link_libraries(mesh_3D_image PUBLIC CGAL::Eigen_support) create_single_source_cgal_program( "mesh_3D_image_with_custom_initialization.cpp" ) - CGAL_target_use_Eigen(mesh_3D_image_with_custom_initialization) + target_link_libraries(mesh_3D_image_with_custom_initialization PUBLIC CGAL::Eigen_support) create_single_source_cgal_program( "mesh_3D_image_variable_size.cpp" ) - CGAL_target_use_Eigen(mesh_3D_image_variable_size) + target_link_libraries(mesh_3D_image_variable_size PUBLIC CGAL::Eigen_support) else() message( STATUS "NOTICE: The examples mesh_3D_image.cpp, mesh_3D_image_variable_size.cpp, mesh_optimization_example.cpp and mesh_optimization_lloyd_example.cpp need CGAL_ImageIO to be configured with ZLIB support, and will not be compiled." ) endif() @@ -167,28 +169,27 @@ if ( CGAL_FOUND ) # create_single_source_cgal_program( "mesh_polyhedral_surface_tolerance_region.cpp" ) # create_single_source_cgal_program( "mesh_polyhedral_edge_tolerance_region.cpp" ) - if(CGAL_ACTIVATE_CONCURRENT_MESH_3 AND TBB_FOUND AND TARGET ${target}) + if(CGAL_ACTIVATE_CONCURRENT_MESH_3 AND TARGET CGAL::TBB_support AND TARGET ${target}) foreach(target - mesh_3D_image_with_features - mesh_3D_image - mesh_polyhedral_domain - mesh_3D_image_with_custom_initialization - mesh_two_implicit_spheres_with_balls - mesh_optimization_lloyd_example - mesh_optimization_example - mesh_implicit_sphere - mesh_polyhedral_complex_sm - mesh_implicit_sphere_variable_size - mesh_polyhedral_domain_sm - mesh_polyhedral_domain_with_lipschitz_sizing - mesh_polyhedral_complex - mesh_polyhedral_domain_with_features - mesh_3D_image_variable_size) - CGAL_target_use_TBB(${target}) + mesh_3D_image_with_features + mesh_3D_image + mesh_polyhedral_domain + mesh_3D_image_with_custom_initialization + mesh_two_implicit_spheres_with_balls + mesh_optimization_lloyd_example + mesh_optimization_example + mesh_implicit_sphere + mesh_polyhedral_complex_sm + mesh_implicit_sphere_variable_size + mesh_polyhedral_domain_sm + mesh_polyhedral_domain_with_lipschitz_sizing + mesh_polyhedral_complex + mesh_polyhedral_domain_with_features + mesh_3D_image_variable_size) + target_link_libraries(${target} PUBLIC CGAL::TBB_support) endforeach() endif() else() message(STATUS "This program requires the CGAL library, and will not be compiled.") endif() - diff --git a/Mesh_3/test/Mesh_3/CMakeLists.txt b/Mesh_3/test/Mesh_3/CMakeLists.txt index ee17ea5e154..d731e12d4e4 100644 --- a/Mesh_3/test/Mesh_3/CMakeLists.txt +++ b/Mesh_3/test/Mesh_3/CMakeLists.txt @@ -16,10 +16,12 @@ if ( CGAL_FOUND ) include( ${CGAL_USE_FILE} ) find_package( TBB QUIET ) + include(CGAL_TBB_support) # Use Eigen find_package(Eigen3 3.1.0 REQUIRED) #(3.1.0 or greater) - if (NOT EIGEN3_FOUND) + include(CGAL_Eigen_support) + if (NOT TARGET CGAL::Eigen_support) message(STATUS "This project requires the Eigen library, and will not be compiled.") return() endif() @@ -91,32 +93,33 @@ if ( CGAL_FOUND ) test_mesh_polyhedral_domain_with_features_deprecated test_meshing_with_one_step.cpp) if(TARGET ${target}) - CGAL_target_use_Eigen(${target}) + target_link_libraries(${target} PUBLIC CGAL::Eigen_support) endif() endforeach() - foreach(target - test_meshing_verbose - test_meshing_polyhedron_with_features - test_meshing_utilities.h - test_meshing_implicit_function - test_meshing_3D_image - test_meshing_3D_gray_image - test_meshing_unit_tetrahedron - test_meshing_polyhedron - test_meshing_polyhedral_complex - test_mesh_capsule_var_distance_bound - test_mesh_3_issue_1554 - test_mesh_polyhedral_domain_with_features_deprecated - ) - if(TBB_FOUND AND TARGET ${target}) - CGAL_target_use_TBB(${target}) - endif() - endforeach() + if(TARGET CGAL::TBB_support) + foreach(target + test_meshing_verbose + test_meshing_polyhedron_with_features + test_meshing_utilities.h + test_meshing_implicit_function + test_meshing_3D_image + test_meshing_3D_gray_image + test_meshing_unit_tetrahedron + test_meshing_polyhedron + test_meshing_polyhedral_complex + test_mesh_capsule_var_distance_bound + test_mesh_3_issue_1554 + test_mesh_polyhedral_domain_with_features_deprecated + ) + if(TARGET ${target}) + target_link_libraries(${target} PUBLIC CGAL::TBB_support) + endif() + endforeach() + endif() else() message(STATUS "This program requires the CGAL library, and will not be compiled.") endif() - diff --git a/NewKernel_d/test/NewKernel_d/CMakeLists.txt b/NewKernel_d/test/NewKernel_d/CMakeLists.txt index e315981083a..ba586fee06d 100644 --- a/NewKernel_d/test/NewKernel_d/CMakeLists.txt +++ b/NewKernel_d/test/NewKernel_d/CMakeLists.txt @@ -17,9 +17,10 @@ find_package(CGAL QUIET) if ( CGAL_FOUND ) find_package(Eigen3) - if (EIGEN3_FOUND) + include(CGAL_Eigen_support) + if (TARGET CGAL::Eigen_support) create_single_source_cgal_program( "Epick_d.cpp" ) - CGAL_target_use_Eigen(Epick_d) + target_link_libraries(Epick_d PUBLIC CGAL::Eigen_support) else() message(STATUS "NOTICE: This program requires the Eigen3 library, and will not be compiled.") @@ -31,4 +32,3 @@ else() message(STATUS "NOTICE: This program requires the CGAL library, and will not be compiled.") endif() - diff --git a/Number_types/test/Number_types/CMakeLists.txt b/Number_types/test/Number_types/CMakeLists.txt index a10e4a8ee8b..52dd912d2f4 100644 --- a/Number_types/test/Number_types/CMakeLists.txt +++ b/Number_types/test/Number_types/CMakeLists.txt @@ -82,8 +82,9 @@ if ( CGAL_FOUND ) create_single_source_cgal_program( "eigen.cpp" ) find_package(Eigen3 3.2.0) #(requires 3.2.0 or greater) - if (EIGEN3_FOUND) - cgal_target_use_Eigen(eigen) + include(CGAL_Eigen_support) + if (TARGET CGAL::Eigen_support) + target_link_libraries(eigen PUBLIC CGAL::Eigen_support) endif() else( CGAL_FOUND ) diff --git a/Periodic_3_mesh_3/examples/Periodic_3_mesh_3/CMakeLists.txt b/Periodic_3_mesh_3/examples/Periodic_3_mesh_3/CMakeLists.txt index bcb9a3247c0..0b936e2c370 100644 --- a/Periodic_3_mesh_3/examples/Periodic_3_mesh_3/CMakeLists.txt +++ b/Periodic_3_mesh_3/examples/Periodic_3_mesh_3/CMakeLists.txt @@ -23,7 +23,8 @@ endif() # Use Eigen find_package(Eigen3 3.1.0 REQUIRED) #(3.1.0 or greater) -if (NOT EIGEN3_FOUND) +include(CGAL_Eigen_support) +if (NOT TARGET CGAL::Eigen_support) message(STATUS "This project requires the Eigen library, and will not be compiled.") return() endif() @@ -52,5 +53,5 @@ foreach(target mesh_implicit_shape_with_subdomains mesh_implicit_shape_with_optimizers mesh_implicit_shape_with_features) - CGAL_target_use_Eigen(${target}) + target_link_libraries(${target} PUBLIC CGAL::Eigen_support) endforeach() diff --git a/Periodic_3_mesh_3/test/Periodic_3_mesh_3/CMakeLists.txt b/Periodic_3_mesh_3/test/Periodic_3_mesh_3/CMakeLists.txt index 3a3f69e79d7..ceba5546a54 100644 --- a/Periodic_3_mesh_3/test/Periodic_3_mesh_3/CMakeLists.txt +++ b/Periodic_3_mesh_3/test/Periodic_3_mesh_3/CMakeLists.txt @@ -16,21 +16,21 @@ if ( CGAL_FOUND ) # Use Eigen find_package(Eigen3 3.1.0 REQUIRED) #(3.1.0 or greater) - if (NOT EIGEN3_FOUND) + include(CGAL_Eigen_support) + if (NOT TARGET CGAL::Eigen_support) message(STATUS "This project requires the Eigen library, and will not be compiled.") return() endif() create_single_source_cgal_program( "test_implicit_shapes_bunch.cpp" ) - CGAL_target_use_Eigen(test_implicit_shapes_bunch) + target_link_libraries(test_implicit_shapes_bunch PUBLIC CGAL::Eigen_support) create_single_source_cgal_program( "test_implicit_shapes_with_features.cpp" ) - CGAL_target_use_Eigen(test_implicit_shapes_with_features) + target_link_libraries(test_implicit_shapes_with_features PUBLIC CGAL::Eigen_support) create_single_source_cgal_program( "test_triply_periodic_minimal_surfaces.cpp" ) - CGAL_target_use_Eigen(test_triply_periodic_minimal_surfaces) + target_link_libraries(test_triply_periodic_minimal_surfaces PUBLIC CGAL::Eigen_support) else() message(STATUS "This program requires the CGAL library, and will not be compiled.") endif() - diff --git a/Point_set_3/examples/Point_set_3/CMakeLists.txt b/Point_set_3/examples/Point_set_3/CMakeLists.txt index 172e045e4d2..cc8a77fb8b6 100644 --- a/Point_set_3/examples/Point_set_3/CMakeLists.txt +++ b/Point_set_3/examples/Point_set_3/CMakeLists.txt @@ -44,9 +44,10 @@ set(needed_cxx_features cxx_rvalue_references cxx_variadic_templates) create_single_source_cgal_program( "point_set_read_ply.cpp" CXX_FEATURES ${needed_cxx_features} ) find_package(Eigen3 3.1.0) #(requires 3.1.0 or greater) +include(CGAL_Eigen_support) if (EIGEN3_FOUND) create_single_source_cgal_program( "point_set_algo.cpp" ) - CGAL_target_use_Eigen(point_set_algo) + target_link_libraries(point_set_algo PUBLIC CGAL::Eigen_support) endif() create_single_source_cgal_program("draw_point_set_3.cpp" ) diff --git a/Point_set_processing_3/test/Point_set_processing_3/CMakeLists.txt b/Point_set_processing_3/test/Point_set_processing_3/CMakeLists.txt index f057bb7332b..33f229e2fe9 100644 --- a/Point_set_processing_3/test/Point_set_processing_3/CMakeLists.txt +++ b/Point_set_processing_3/test/Point_set_processing_3/CMakeLists.txt @@ -27,6 +27,7 @@ if ( CGAL_FOUND ) ADD_DEFINITIONS( "-DDEBUG_TRACE" ) find_package( TBB QUIET ) + include(CGAL_TBB_support) # Executables that do *not* require Eigen create_single_source_cgal_program( "read_test.cpp" ) @@ -40,30 +41,31 @@ if ( CGAL_FOUND ) # Use Eigen find_package(Eigen3 3.1.0) #(requires 3.1.0 or greater) + include(CGAL_Eigen_support) if (EIGEN3_FOUND) # Executables that require Eigen create_single_source_cgal_program( "normal_estimation_test.cpp" ) - CGAL_target_use_Eigen(normal_estimation_test) + target_link_libraries(normal_estimation_test PUBLIC CGAL::Eigen_support) create_single_source_cgal_program( "hierarchy_simplification_test.cpp" ) - CGAL_target_use_Eigen(hierarchy_simplification_test) + target_link_libraries(hierarchy_simplification_test PUBLIC CGAL::Eigen_support) create_single_source_cgal_program( "smoothing_test.cpp" ) - CGAL_target_use_Eigen(smoothing_test) + target_link_libraries(smoothing_test PUBLIC CGAL::Eigen_support) create_single_source_cgal_program( "vcm_plane_test.cpp" ) - CGAL_target_use_Eigen(vcm_plane_test) + target_link_libraries(vcm_plane_test PUBLIC CGAL::Eigen_support) create_single_source_cgal_program( "vcm_all_test.cpp" ) - CGAL_target_use_Eigen(vcm_all_test) + target_link_libraries(vcm_all_test PUBLIC CGAL::Eigen_support) create_single_source_cgal_program( "jet_pointer_as_property_map.cpp" ) - CGAL_target_use_Eigen(jet_pointer_as_property_map) + target_link_libraries(jet_pointer_as_property_map PUBLIC CGAL::Eigen_support) else() message(STATUS "NOTICE: This program requires Eigen 3.1 (or greater) and will not be compiled.") endif() - if (TBB_FOUND) + if (TARGET CGAL::TBB_support) foreach(target analysis_test smoothing_test @@ -72,7 +74,7 @@ if ( CGAL_FOUND ) edge_aware_upsample_test normal_estimation_test) if(TARGET ${target}) - CGAL_target_use_TBB(${target}) + target_link_libraries(${target} PUBLIC CGAL::TBB_support) endif() endforeach() endif() @@ -82,4 +84,3 @@ else() message(STATUS "NOTICE: This program requires the CGAL library, and will not be compiled.") endif() - diff --git a/Poisson_surface_reconstruction_3/examples/Poisson_surface_reconstruction_3/CMakeLists.txt b/Poisson_surface_reconstruction_3/examples/Poisson_surface_reconstruction_3/CMakeLists.txt index a7eb729ec77..b67981f06b6 100644 --- a/Poisson_surface_reconstruction_3/examples/Poisson_surface_reconstruction_3/CMakeLists.txt +++ b/Poisson_surface_reconstruction_3/examples/Poisson_surface_reconstruction_3/CMakeLists.txt @@ -23,16 +23,17 @@ if ( CGAL_FOUND ) # Find Eigen3 (requires 3.1.0 or greater) find_package(Eigen3 3.1.0) - if (EIGEN3_FOUND) + include(CGAL_Eigen_support) + if (TARGET CGAL::Eigen_support) # Executables that require Eigen 3 create_single_source_cgal_program( "poisson_reconstruction_example.cpp" ) - CGAL_target_use_Eigen(poisson_reconstruction_example) + target_link_libraries(poisson_reconstruction_example PUBLIC CGAL::Eigen_support) create_single_source_cgal_program( "poisson_reconstruction.cpp" ) - CGAL_target_use_Eigen(poisson_reconstruction) + target_link_libraries(poisson_reconstruction PUBLIC CGAL::Eigen_support) create_single_source_cgal_program( "poisson_reconstruction_function.cpp" ) - CGAL_target_use_Eigen(poisson_reconstruction_function) + target_link_libraries(poisson_reconstruction_function PUBLIC CGAL::Eigen_support) create_single_source_cgal_program( "tutorial_example.cpp" ) - CGAL_target_use_Eigen(tutorial_example) + target_link_libraries(tutorial_example PUBLIC CGAL::Eigen_support) else() message(STATUS "NOTICE: The examples need Eigen 3.1 (or greater) will not be compiled.") endif() @@ -43,4 +44,3 @@ else() message(STATUS "NOTICE: This program requires the CGAL library, and will not be compiled.") endif() - diff --git a/Poisson_surface_reconstruction_3/test/Poisson_surface_reconstruction_3/CMakeLists.txt b/Poisson_surface_reconstruction_3/test/Poisson_surface_reconstruction_3/CMakeLists.txt index 1c518a1267b..b8cb454be73 100644 --- a/Poisson_surface_reconstruction_3/test/Poisson_surface_reconstruction_3/CMakeLists.txt +++ b/Poisson_surface_reconstruction_3/test/Poisson_surface_reconstruction_3/CMakeLists.txt @@ -24,10 +24,11 @@ if ( CGAL_FOUND ) # Temporary debugging stuff find_package(Eigen3 3.1.0) #(requires 3.1.0 or greater) - if(EIGEN3_FOUND) + include(CGAL_Eigen_support) + if(TARGET CGAL::Eigen_support) # Executables that require Eigen 3.1 create_single_source_cgal_program( "poisson_reconstruction_test.cpp" ) - CGAL_target_use_Eigen(poisson_reconstruction_test) + target_link_libraries(poisson_reconstruction_test PUBLIC CGAL::Eigen_support) else() message(STATUS "NOTICE: Some of the executables in this directory need Eigen 3.1 (or greater) and will not be compiled.") @@ -39,4 +40,3 @@ else() message(STATUS "NOTICE: This program requires the CGAL library, and will not be compiled.") endif() - diff --git a/Polygon_mesh_processing/benchmark/Polygon_mesh_processing/CMakeLists.txt b/Polygon_mesh_processing/benchmark/Polygon_mesh_processing/CMakeLists.txt index 33c8b074104..008b892cd43 100644 --- a/Polygon_mesh_processing/benchmark/Polygon_mesh_processing/CMakeLists.txt +++ b/Polygon_mesh_processing/benchmark/Polygon_mesh_processing/CMakeLists.txt @@ -29,6 +29,7 @@ endif() # include for local package find_package(Eigen3 3.2.0) #(requires 3.2.0 or greater) +include(CGAL_Eigen_support) # Creating entries for all .cpp/.C files with "main" routine # ########################################################## @@ -37,8 +38,7 @@ create_single_source_cgal_program( "polygon_mesh_slicer.cpp" ) create_single_source_cgal_program( "hole_filling.cpp" ) -if (EIGEN3_FOUND) - CGAL_target_use_Eigen(polygon_mesh_slicer) - CGAL_target_use_Eigen(hole_filling) +if (TARGET CGAL::Eigen_support) + target_link_libraries(polygon_mesh_slicer PUBLIC CGAL::Eigen_support) + target_link_libraries(hole_filling PUBLIC CGAL::Eigen_support) endif() - diff --git a/Polygon_mesh_processing/examples/Polygon_mesh_processing/CMakeLists.txt b/Polygon_mesh_processing/examples/Polygon_mesh_processing/CMakeLists.txt index 151f4fe333c..46a7f04d886 100644 --- a/Polygon_mesh_processing/examples/Polygon_mesh_processing/CMakeLists.txt +++ b/Polygon_mesh_processing/examples/Polygon_mesh_processing/CMakeLists.txt @@ -38,6 +38,7 @@ endif() # include for local package find_package(Eigen3 3.2.0) #(requires 3.2.0 or greater) +include(CGAL_Eigen_support) # Creating entries for all .cpp/.C files with "main" routine @@ -45,18 +46,18 @@ find_package(Eigen3 3.2.0) #(requires 3.2.0 or greater) create_single_source_cgal_program( "hausdorff_distance_remeshing_example.cpp") -if (EIGEN3_FOUND) +if (TARGET CGAL::Eigen_support) create_single_source_cgal_program( "hole_filling_example.cpp" ) - CGAL_target_use_Eigen(hole_filling_example) + target_link_libraries(hole_filling_example PUBLIC CGAL::Eigen_support) create_single_source_cgal_program( "hole_filling_example_SM.cpp" ) - CGAL_target_use_Eigen(hole_filling_example_SM) + target_link_libraries(hole_filling_example_SM PUBLIC CGAL::Eigen_support) create_single_source_cgal_program( "refine_fair_example.cpp") - CGAL_target_use_Eigen(refine_fair_example) + target_link_libraries(refine_fair_example PUBLIC CGAL::Eigen_support) create_single_source_cgal_program( "shape_smoothing_example.cpp") - CGAL_target_use_Eigen(shape_smoothing_example) + target_link_libraries(shape_smoothing_example PUBLIC CGAL::Eigen_support) create_single_source_cgal_program( "hole_filling_example_LCC.cpp" ) - CGAL_target_use_Eigen(hole_filling_example_LCC) -endif(EIGEN3_FOUND) + target_link_libraries(hole_filling_example_LCC PUBLIC CGAL::Eigen_support) +endif() create_single_source_cgal_program( "self_intersections_example.cpp" ) create_single_source_cgal_program( "stitch_borders_example.cpp" ) @@ -98,10 +99,9 @@ if(OpenMesh_FOUND) create_single_source_cgal_program( "compute_normals_example_OM.cpp" ) target_link_libraries( compute_normals_example_OM PRIVATE ${OPENMESH_LIBRARIES} ) -if (EIGEN3_FOUND) +if (TARGET CGAL::Eigen_support) create_single_source_cgal_program( "hole_filling_example_OM.cpp" ) - target_link_libraries( hole_filling_example_OM PRIVATE ${OPENMESH_LIBRARIES} ) - CGAL_target_use_Eigen( hole_filling_example_OM ) + target_link_libraries( hole_filling_example_OM PRIVATE CGAL::Eigen_support ${OPENMESH_LIBRARIES} ) endif() create_single_source_cgal_program( "point_inside_example_OM.cpp") @@ -118,9 +118,10 @@ target_link_libraries( triangulate_faces_example_OM PRIVATE ${OPENMESH_LIBRARIES endif(OpenMesh_FOUND) find_package( TBB ) -if( TBB_FOUND ) - CGAL_target_use_TBB(self_intersections_example) - CGAL_target_use_TBB(hausdorff_distance_remeshing_example) +include(CGAL_TBB_support) +if( TARGET CGAL::TBB_support ) + target_link_libraries(self_intersections_example PUBLIC CGAL::TBB_support) + target_link_libraries(hausdorff_distance_remeshing_example PUBLIC CGAL::TBB_support) else() message( STATUS "NOTICE: Intel TBB was not found. Sequential code will be used." ) endif() diff --git a/Polygon_mesh_processing/test/Polygon_mesh_processing/CMakeLists.txt b/Polygon_mesh_processing/test/Polygon_mesh_processing/CMakeLists.txt index f18ccb8bd61..214d55114f2 100644 --- a/Polygon_mesh_processing/test/Polygon_mesh_processing/CMakeLists.txt +++ b/Polygon_mesh_processing/test/Polygon_mesh_processing/CMakeLists.txt @@ -31,22 +31,24 @@ endif() # include for local package find_package(Eigen3 3.2.0) #(requires 3.2.0 or greater) +include(CGAL_Eigen_support) find_package( TBB ) +include(CGAL_TBB_support) -if (EIGEN3_FOUND) +if (TARGET CGAL::Eigen_support) # Creating entries for all .cpp/.C files with "main" routine # ########################################################## create_single_source_cgal_program("fairing_test.cpp") - CGAL_target_use_Eigen(fairing_test) + target_link_libraries(fairing_test PUBLIC CGAL::Eigen_support) create_single_source_cgal_program("triangulate_hole_Polyhedron_3_no_delaunay_test.cpp" ) - CGAL_target_use_Eigen(triangulate_hole_Polyhedron_3_no_delaunay_test) + target_link_libraries(triangulate_hole_Polyhedron_3_no_delaunay_test PUBLIC CGAL::Eigen_support) create_single_source_cgal_program("triangulate_hole_Polyhedron_3_test.cpp") - CGAL_target_use_Eigen(triangulate_hole_Polyhedron_3_test) + target_link_libraries(triangulate_hole_Polyhedron_3_test PUBLIC CGAL::Eigen_support) create_single_source_cgal_program("test_shape_smoothing.cpp") - CGAL_target_use_Eigen(test_shape_smoothing) + target_link_libraries(test_shape_smoothing PUBLIC CGAL::Eigen_support) -endif(EIGEN3_FOUND) +endif() find_package( OpenMesh QUIET ) if ( OpenMesh_FOUND ) @@ -103,11 +105,10 @@ endif() create_single_source_cgal_program("test_remove_caps_needles.cpp") # create_single_source_cgal_program("test_pmp_repair_self_intersections.cpp") - if( TBB_FOUND ) - include(CGAL_target_use_TBB) - CGAL_target_use_TBB(test_pmp_distance) - CGAL_target_use_TBB(orient_polygon_soup_test) - CGAL_target_use_TBB(self_intersection_surface_mesh_test) + if( TARGET CGAL::TBB_support ) + target_link_libraries(test_pmp_distance PUBLIC CGAL::TBB_support) + target_link_libraries(orient_polygon_soup_test PUBLIC CGAL::TBB_support) + target_link_libraries(self_intersection_surface_mesh_test PUBLIC CGAL::TBB_support) else() message( STATUS "NOTICE: Intel TBB was not found. test_pmp_distance will use sequential code." ) endif() diff --git a/Polygonal_surface_reconstruction/examples/Polygonal_surface_reconstruction/CMakeLists.txt b/Polygonal_surface_reconstruction/examples/Polygonal_surface_reconstruction/CMakeLists.txt index 5fd39e6bcc1..68eec9daba7 100644 --- a/Polygonal_surface_reconstruction/examples/Polygonal_surface_reconstruction/CMakeLists.txt +++ b/Polygonal_surface_reconstruction/examples/Polygonal_surface_reconstruction/CMakeLists.txt @@ -37,15 +37,18 @@ endif() include( CGAL_CreateSingleSourceCGALProgram ) find_package(Eigen3 3.1.0) #(requires 3.1.0 or greater) -if(NOT EIGEN3_FOUND) +include(CGAL_Eigen_support) +if(NOT TARGET CGAL::Eigen_support) message(STATUS "NOTICE: This project requires Eigen 3.1 (or greater) and will not be compiled.") return() endif() find_package(SCIP QUIET) -if (NOT SCIP_FOUND ) +include(CGAL_SCIP_support) +if (NOT TARGET CGAL::SCIP_support ) find_package( GLPK QUIET) - if ( NOT GLPK_FOUND ) + include(CGAL_GLPK_support) + if (NOT TARGET CGAL::GLPK_support ) message( STATUS "NOTICE: This project requires either SCIP or GLPK, and will not be compiled.") return() endif() @@ -61,10 +64,10 @@ foreach(target polyfit_example_user_provided_planes polyfit_example_model_complexty_control polyfit_example_with_region_growing) - CGAL_target_use_Eigen(${target}) - if (SCIP_FOUND) - CGAL_target_use_SCIP(${target}) + target_link_libraries(${target} PUBLIC CGAL::Eigen_support) + if (TARGET CGAL::SCIP_support) + target_link_libraries(${target} PUBLIC CGAL::SCIP_support) else() - CGAL_target_use_GLPK(${target}) + target_link_libraries(${target} PUBLIC CGAL::GLPK_support) endif() endforeach() diff --git a/Polygonal_surface_reconstruction/test/Polygonal_surface_reconstruction/CMakeLists.txt b/Polygonal_surface_reconstruction/test/Polygonal_surface_reconstruction/CMakeLists.txt index fb12c54a420..7ce3ba34320 100644 --- a/Polygonal_surface_reconstruction/test/Polygonal_surface_reconstruction/CMakeLists.txt +++ b/Polygonal_surface_reconstruction/test/Polygonal_surface_reconstruction/CMakeLists.txt @@ -38,24 +38,27 @@ include( CGAL_CreateSingleSourceCGALProgram ) find_package(Eigen3 3.1.0) #(requires 3.1.0 or greater) -if(NOT EIGEN3_FOUND) +include(CGAL_Eigen_support) +if(NOT TARGET CGAL::Eigen_support) message(STATUS "NOTICE: This project requires Eigen 3.1 (or greater) and will not be compiled.") return() endif() find_package(SCIP QUIET) -if (NOT SCIP_FOUND ) +include(CGAL_SCIP_support) +if (NOT TARGET CGAL::SCIP_support ) find_package( GLPK QUIET) - if ( NOT GLPK_FOUND ) - message( STATUS "NOTICE : This project requires either SCIP or GLPK, and will not be compiled.") + include(CGAL_GLPK_support) + if (NOT TARGET CGAL::GLPK_support ) + message( STATUS "NOTICE: This project requires either SCIP or GLPK, and will not be compiled.") return() endif() endif() create_single_source_cgal_program( "polygonal_surface_reconstruction_test.cpp") -CGAL_target_use_Eigen(polygonal_surface_reconstruction_test) -if (SCIP_FOUND) - CGAL_target_use_SCIP(polygonal_surface_reconstruction_test) +target_link_libraries(polygonal_surface_reconstruction_test PUBLIC CGAL::Eigen_support) +if (TARGET CGAL::SCIP_support) + target_link_libraries(polygonal_surface_reconstruction_test PUBLIC CGAL::SCIP_support) else() - CGAL_target_use_GLPK(polygonal_surface_reconstruction_test) + target_link_libraries(polygonal_surface_reconstruction_test PUBLIC CGAL::GLPK_support) endif() diff --git a/Polyhedron/demo/Polyhedron/CMakeLists.txt b/Polyhedron/demo/Polyhedron/CMakeLists.txt index 9e00808a516..d6914d1aa07 100644 --- a/Polyhedron/demo/Polyhedron/CMakeLists.txt +++ b/Polyhedron/demo/Polyhedron/CMakeLists.txt @@ -73,6 +73,7 @@ if(Qt5_FOUND) endif(Qt5_FOUND) find_package(Eigen3 3.2.0) #(requires 3.2.0 or greater) +include(CGAL_Eigen_support) find_package( METIS ) @@ -87,7 +88,8 @@ option(POLYHEDRON_DEMO_ACTIVATE_CONCURRENCY if( POLYHEDRON_DEMO_ACTIVATE_CONCURRENCY ) find_package( TBB ) - if( NOT TBB_FOUND ) + include(CGAL_TBB_support) + if( NOT TARGET CGAL::TBB_support ) message( STATUS "NOTICE: Intel TBB was not found. Bilateral smoothing and WLOP plugins are faster if TBB is linked." ) endif() endif() @@ -108,7 +110,8 @@ if( CGAL_ACTIVATE_CONCURRENT_MESH_3 OR ENV{CGAL_ACTIVATE_CONCURRENT_MESH_3} ) add_definitions( -DCGAL_CONCURRENT_MESH_3 ) if(NOT TBB_FOUND) find_package( TBB REQUIRED ) - if( NOT TBB_FOUND ) + include( CGAL_TBB_support) + if( NOT TARGET CGAL::TBB_support ) message(STATUS "NOTICE: Intel TBB was not found. Mesh_3 is faster if TBB is linked.") endif() endif() @@ -119,6 +122,7 @@ else( CGAL_ACTIVATE_CONCURRENT_MESH_3 OR ENV{CGAL_ACTIVATE_CONCURRENT_MESH_3} ) ON) if( LINK_WITH_TBB ) find_package( TBB ) + include( CGAL_TBB_support) endif( LINK_WITH_TBB ) endif() @@ -248,8 +252,8 @@ if(CGAL_Qt5_FOUND AND Qt5_FOUND) add_item(scene_c3t3_item Scene_c3t3_item.cpp) target_link_libraries(scene_c3t3_item PUBLIC scene_surface_mesh_item scene_polygon_soup_item scene_basic_objects ${TBB_LIBRARIES}) - if(TBB_FOUND) - CGAL_target_use_TBB(scene_c3t3_item) + if(TARGET CGAL::TBB_support) + target_link_libraries(scene_c3t3_item PUBLIC CGAL::TBB_support) endif() if(COMMAND target_precompile_headers) # Support for precompiled headers, for Mesh_3 (since CMake 3.16) @@ -261,7 +265,7 @@ if(CGAL_Qt5_FOUND AND Qt5_FOUND) add_item(scene_surface_mesh_item Scene_surface_mesh_item.cpp) if(TBB_FOUND) - CGAL_target_use_TBB(scene_surface_mesh_item) + target_link_libraries(scene_surface_mesh_item PUBLIC CGAL::TBB_support) endif() # special @@ -274,7 +278,7 @@ if(CGAL_Qt5_FOUND AND Qt5_FOUND) add_item(scene_selection_item Scene_polyhedron_selection_item.cpp) target_link_libraries(scene_selection_item PUBLIC scene_item_decorator scene_k_ring_selection) if(TBB_FOUND) - CGAL_target_use_TBB(scene_selection_item) + target_link_libraries(scene_selection_item PUBLIC CGAL::TBB_support) endif() add_item(scene_shortest_path_item Plugins/Surface_mesh/Scene_polyhedron_shortest_path_item.cpp) @@ -282,17 +286,16 @@ if(CGAL_Qt5_FOUND AND Qt5_FOUND) add_item(scene_movable_sm_item Plugins/AABB_tree/Scene_movable_sm_item.cpp) - if(EIGEN3_FOUND ) + if(TARGET CGAL::Eigen_support ) add_item(scene_textured_item Scene_textured_surface_mesh_item.cpp texture.cpp) - CGAL_target_use_Eigen(scene_textured_item) + target_link_libraries(scene_textured_item PUBLIC CGAL::Eigen_support) qt5_wrap_ui( editionUI_FILES Plugins/Surface_mesh_deformation/Deform_mesh.ui ) add_item(scene_edit_item Plugins/Surface_mesh_deformation/Scene_edit_polyhedron_item.cpp ${editionUI_FILES}) - CGAL_target_use_Eigen(scene_edit_item) - target_link_libraries(scene_edit_item PUBLIC scene_surface_mesh_item scene_k_ring_selection + target_link_libraries(scene_edit_item PUBLIC CGAL::Eigen_support scene_surface_mesh_item scene_k_ring_selection scene_basic_objects) add_item(scene_mcf_item Plugins/PMP/Scene_mcf_item.cpp) - CGAL_target_use_Eigen(scene_mcf_item) + target_link_libraries(scene_mcf_item PUBLIC CGAL::Eigen_support) endif() add_item(scene_implicit_function_item Scene_implicit_function_item.cpp ) @@ -305,20 +308,21 @@ if(CGAL_Qt5_FOUND AND Qt5_FOUND) target_link_libraries(scene_nef_polyhedron_item PUBLIC scene_surface_mesh_item) add_item(scene_points_with_normal_item Scene_points_with_normal_item.cpp) - if (EIGEN3_FOUND) - CGAL_target_use_Eigen(scene_points_with_normal_item) + if (TARGET CGAL::Eigen_support) + target_link_libraries(scene_points_with_normal_item PUBLIC CGAL::Eigen_support) endif() find_package(LASLIB) - if (LASLIB_FOUND) - CGAL_target_use_LASLIB(scene_points_with_normal_item) + include(CGAL_LASLIB_support) + if (TARGET CGAL::LASLIB_support) + target_link_libraries(scene_points_with_normal_item PUBLIC CGAL::LASLIB_support) if (MSVC) target_compile_definitions( scene_points_with_normal_item PUBLIC "-D_CRT_SECURE_NO_DEPRECATE -D_CRT_SECURE_NO_WARNINGS") endif() endif() if(TBB_FOUND) - CGAL_target_use_TBB(scene_points_with_normal_item) + target_link_libraries(scene_points_with_normal_item PUBLIC CGAL::TBB_support) endif() add_item(scene_polylines_item Scene_polylines_item.cpp) diff --git a/Polyhedron/demo/Polyhedron/Plugins/AABB_tree/CMakeLists.txt b/Polyhedron/demo/Polyhedron/Plugins/AABB_tree/CMakeLists.txt index bff0df4c9a1..1336c086cd7 100644 --- a/Polyhedron/demo/Polyhedron/Plugins/AABB_tree/CMakeLists.txt +++ b/Polyhedron/demo/Polyhedron/Plugins/AABB_tree/CMakeLists.txt @@ -5,6 +5,6 @@ target_link_libraries(do_trees_intersect_plugin PUBLIC scene_surface_mesh_item s polyhedron_demo_plugin(cut_plugin Cut_plugin ) target_link_libraries(cut_plugin PUBLIC scene_surface_mesh_item scene_basic_objects scene_color_ramp) -if(TBB_FOUND) - CGAL_target_use_TBB(cut_plugin) +if(TARGET CGAL::TBB_support) + target_link_libraries(cut_plugin PUBLIC CGAL::TBB_support) endif() diff --git a/Polyhedron/demo/Polyhedron/Plugins/Classification/CMakeLists.txt b/Polyhedron/demo/Polyhedron/Plugins/Classification/CMakeLists.txt index b4a49753ce2..288c22109ff 100644 --- a/Polyhedron/demo/Polyhedron/Plugins/Classification/CMakeLists.txt +++ b/Polyhedron/demo/Polyhedron/Plugins/Classification/CMakeLists.txt @@ -1,54 +1,61 @@ include( polyhedron_demo_macros ) -if(EIGEN3_FOUND) +if(TARGET CGAL::Eigen_support) set(Classification_dependencies_met TRUE) find_package( Boost OPTIONAL_COMPONENTS serialization iostreams ) - if (NOT Boost_SERIALIZATION_FOUND) + include(CGAL_Boost_serialization_support) + include(CGAL_Boost_iostreams_support) + if (NOT TARGET CGAL::Boost_serialization_support) message(STATUS "NOTICE: Boost Serialization not found. Classification plugin won't be available.") set(Classification_dependencies_met FALSE) endif() - if (NOT Boost_IOSTREAMS_FOUND) + if (NOT TARGET CGAL::Boost_iostreams_support) message(STATUS "NOTICE: Boost IOStreams not found. Classification plugin won't be available.") set(Classification_dependencies_met FALSE) endif() find_package(OpenCV QUIET COMPONENTS core ml) # Need core + machine learning - if (NOT OpenCV_FOUND) + include(CGAL_OpenCV_support) + if (NOT TARGET CGAL::OpenCV_support) message(STATUS "NOTICE: OpenCV was not found. OpenCV random forest predicate for classification won't be available.") endif() find_package(TensorFlow QUIET) - if (NOT TensorFlow_FOUND) + include(CGAL_TensorFlow_support) + if (NOT TARGET CGAL::TensorFlow_support) message(STATUS "NOTICE: TensorFlow not found, Neural Network predicate for classification won't be available.") endif() if (Classification_dependencies_met) qt5_wrap_ui( classificationUI_FILES Classification_widget.ui Classification_advanced_widget.ui ) polyhedron_demo_plugin(classification_plugin Classification_plugin Point_set_item_classification Cluster_classification Surface_mesh_item_classification ${classificationUI_FILES} KEYWORDS Classification) - target_link_libraries(classification_plugin PUBLIC scene_points_with_normal_item - scene_polylines_item scene_polygon_soup_item scene_surface_mesh_item scene_selection_item scene_color_ramp) + target_link_libraries(classification_plugin PUBLIC + scene_points_with_normal_item + scene_polylines_item + scene_polygon_soup_item + scene_surface_mesh_item + scene_selection_item + scene_color_ramp + CGAL::Eigen_support + CGAL::Boost_serialization_support + CGAL::Boost_iostreams_support) - CGAL_target_use_Eigen(classification_plugin) - CGAL_target_use_Boost_IOStreams(classification_plugin) - CGAL_target_use_Boost_Serialization(classification_plugin) if(OpenCV_FOUND) - CGAL_target_use_OpenCV(classification_plugin) + target_link_libraries(classification_plugin PUBLIC CGAL::OpenCV_support) endif() if(TensorFlow_FOUND) - CGAL_target_use_TensorFlow(classification_plugin) + target_link_libraries(classification_plugin PUBLIC CGAL::TensorFlow_support) endif() if(TBB_FOUND) - CGAL_target_use_TBB(classification_plugin) + target_link_libraries(classification_plugin PUBLIC CGAL::TBB_support) endif() add_dependencies(classification_plugin point_set_selection_plugin selection_plugin) endif() -else(EIGEN3_FOUND) +else() message(STATUS "NOTICE: Eigen 3.1 (or greater) was not found. Classification plugin will not be available.") endif() - - diff --git a/Polyhedron/demo/Polyhedron/Plugins/Display/CMakeLists.txt b/Polyhedron/demo/Polyhedron/Plugins/Display/CMakeLists.txt index c783cd751ac..0f03d24021e 100644 --- a/Polyhedron/demo/Polyhedron/Plugins/Display/CMakeLists.txt +++ b/Polyhedron/demo/Polyhedron/Plugins/Display/CMakeLists.txt @@ -1,7 +1,6 @@ include( polyhedron_demo_macros ) -if(EIGEN3_FOUND) +if(TARGET CGAL::Eigen_support) qt5_wrap_ui( display_propertyUI_FILES Display_property.ui ) polyhedron_demo_plugin(display_property_plugin Display_property_plugin ${display_propertyUI_FILES}) - target_link_libraries(display_property_plugin PUBLIC scene_surface_mesh_item scene_points_with_normal_item scene_color_ramp) - CGAL_target_use_Eigen(display_property_plugin) -endif(EIGEN3_FOUND) + target_link_libraries(display_property_plugin PUBLIC scene_surface_mesh_item scene_points_with_normal_item scene_color_ramp CGAL::Eigen_support) +endif() diff --git a/Polyhedron/demo/Polyhedron/Plugins/IO/CMakeLists.txt b/Polyhedron/demo/Polyhedron/Plugins/IO/CMakeLists.txt index c5c5f52ccd8..753eb232b22 100644 --- a/Polyhedron/demo/Polyhedron/Plugins/IO/CMakeLists.txt +++ b/Polyhedron/demo/Polyhedron/Plugins/IO/CMakeLists.txt @@ -69,11 +69,10 @@ else() target_link_libraries(ply_plugin PUBLIC scene_points_with_normal_item scene_polygon_soup_item scene_surface_mesh_item scene_textured_item) target_compile_features(ply_plugin PRIVATE ${needed_cxx_features}) - if (LASLIB_FOUND) + if (TARGET CGAL::LASLIB_support) polyhedron_demo_plugin(las_plugin LAS_io_plugin KEYWORDS IO PointSetProcessing Classification) - target_link_libraries(las_plugin PUBLIC scene_points_with_normal_item) + target_link_libraries(las_plugin PUBLIC scene_points_with_normal_item CGAL::LASLIB_support) target_compile_features(las_plugin PRIVATE ${needed_cxx_features}) - CGAL_target_use_LASLIB(las_plugin) else() message(STATUS "NOTICE : the LAS IO plugin needs LAS libraries and will not be compiled.") endif() diff --git a/Polyhedron/demo/Polyhedron/Plugins/Mesh_3/CMakeLists.txt b/Polyhedron/demo/Polyhedron/Plugins/Mesh_3/CMakeLists.txt index 8f1468406ac..a4e6ac600e2 100644 --- a/Polyhedron/demo/Polyhedron/Plugins/Mesh_3/CMakeLists.txt +++ b/Polyhedron/demo/Polyhedron/Plugins/Mesh_3/CMakeLists.txt @@ -54,9 +54,10 @@ target_link_libraries(mesh_3_optimization_plugin PUBLIC scene_c3t3_item scene_su # Use Eigen find_package(Eigen3 3.1.0 REQUIRED) #(3.1.0 or greater) + include(CGAL_Eigen_support) - if (EIGEN3_FOUND) - CGAL_target_use_Eigen(mesh_3_optimization_plugin) + if (TARGET CGAL::Eigen_support) + target_link_libraries(mesh_3_optimization_plugin PUBLIC CGAL::Eigen_support) else() #eigen message(STATUS "The Mesh_3_optimization_plugin requires Eigen, which was not found, and will use a deprecated class to replace it. Warnings are to be expected.") endif()#eigen @@ -69,8 +70,8 @@ polyhedron_demo_plugin(c3t3_rib_exporter_plugin C3t3_rib_exporter_plugin ${ribUI target_link_libraries(c3t3_rib_exporter_plugin PUBLIC scene_c3t3_item) if(TBB_FOUND) - CGAL_target_use_TBB(mesh_3_plugin) - CGAL_target_use_TBB(mesh_3_optimization_plugin) - CGAL_target_use_TBB(c3t3_io_plugin) - CGAL_target_use_TBB(c3t3_rib_exporter_plugin) + target_link_libraries(mesh_3_plugin PUBLIC CGAL::TBB_support) + target_link_libraries(mesh_3_optimization_plugin PUBLIC CGAL::TBB_support) + target_link_libraries(c3t3_io_plugin PUBLIC CGAL::TBB_support) + target_link_libraries(c3t3_rib_exporter_plugin PUBLIC CGAL::TBB_support) endif() diff --git a/Polyhedron/demo/Polyhedron/Plugins/PMP/CMakeLists.txt b/Polyhedron/demo/Polyhedron/Plugins/PMP/CMakeLists.txt index f5380d67133..56d43cccef3 100644 --- a/Polyhedron/demo/Polyhedron/Plugins/PMP/CMakeLists.txt +++ b/Polyhedron/demo/Polyhedron/Plugins/PMP/CMakeLists.txt @@ -1,33 +1,29 @@ include( polyhedron_demo_macros ) -if(EIGEN3_FOUND) +if(TARGET CGAL::Eigen_support) polyhedron_demo_plugin(jet_fitting_plugin Jet_fitting_plugin) - target_link_libraries(jet_fitting_plugin PUBLIC scene_surface_mesh_item scene_polylines_item) - CGAL_target_use_Eigen(jet_fitting_plugin) + target_link_libraries(jet_fitting_plugin PUBLIC scene_surface_mesh_item scene_polylines_item CGAL::Eigen_support) -else(EIGEN3_FOUND) +else() message(STATUS "NOTICE: Eigen 3.1 (or greater) was not found. Jet fitting plugin will not be available.") -endif(EIGEN3_FOUND) +endif() polyhedron_demo_plugin(extrude_plugin Extrude_plugin KEYWORDS PMP) target_link_libraries(extrude_plugin PUBLIC scene_surface_mesh_item scene_selection_item) -if(EIGEN3_FOUND) +if(TARGET CGAL::Eigen_support) if("${EIGEN3_VERSION}" VERSION_GREATER "3.1.90") qt5_wrap_ui( hole_fillingUI_FILES Hole_filling_widget.ui) polyhedron_demo_plugin(hole_filling_plugin Hole_filling_plugin ${hole_fillingUI_FILES} KEYWORDS PMP) - target_link_libraries(hole_filling_plugin PUBLIC scene_surface_mesh_item scene_polylines_item scene_selection_item) - CGAL_target_use_Eigen(hole_filling_plugin) + target_link_libraries(hole_filling_plugin PUBLIC scene_surface_mesh_item scene_polylines_item scene_selection_item CGAL::Eigen_support) qt5_wrap_ui( fairingUI_FILES Fairing_widget.ui) polyhedron_demo_plugin(fairing_plugin Fairing_plugin ${fairingUI_FILES} KEYWORDS PMP) - target_link_libraries(fairing_plugin PUBLIC scene_selection_item) - CGAL_target_use_Eigen(fairing_plugin) + target_link_libraries(fairing_plugin PUBLIC scene_selection_item CGAL::Eigen_support) polyhedron_demo_plugin(hole_filling_polyline_plugin Hole_filling_polyline_plugin ) - target_link_libraries(hole_filling_polyline_plugin PUBLIC scene_surface_mesh_item scene_polylines_item) - CGAL_target_use_Eigen(hole_filling_polyline_plugin) + target_link_libraries(hole_filling_polyline_plugin PUBLIC scene_surface_mesh_item scene_polylines_item CGAL::Eigen_support) qt5_wrap_ui( Mean_curvature_flow_skeleton_pluginUI_FILES Mean_curvature_flow_skeleton_plugin.ui) polyhedron_demo_plugin(mean_curvature_flow_skeleton_plugin Mean_curvature_flow_skeleton_plugin ${Mean_curvature_flow_skeleton_pluginUI_FILES}) @@ -37,20 +33,19 @@ if(EIGEN3_FOUND) scene_points_with_normal_item scene_polylines_item scene_mcf_item - demo_framework) - CGAL_target_use_Eigen(mean_curvature_flow_skeleton_plugin) + demo_framework + CGAL::Eigen_support) # The smoothing plugin can still do some things, even if Ceres is not found qt5_wrap_ui( smoothingUI_FILES Smoothing_plugin.ui) polyhedron_demo_plugin(smoothing_plugin Smoothing_plugin ${smoothingUI_FILES}) - target_link_libraries(smoothing_plugin PUBLIC scene_surface_mesh_item scene_selection_item) - CGAL_target_use_Eigen(smoothing_plugin) + target_link_libraries(smoothing_plugin PUBLIC scene_surface_mesh_item scene_selection_item CGAL::Eigen_support) find_package(Ceres QUIET) if(TARGET ceres) target_compile_definitions( smoothing_plugin PRIVATE CGAL_PMP_USE_CERES_SOLVER ) target_link_libraries(smoothing_plugin PUBLIC ceres) endif() - CGAL_target_use_Eigen(extrude_plugin) + target_link_libraries(extrude_plugin PUBLIC CGAL::Eigen_support) else() message(STATUS "NOTICE: The hole filling and fairing plugins require Eigen 3.2 (or higher) and will not be available.") endif() @@ -106,17 +101,16 @@ qt5_wrap_ui( isotropicRemeshingUI_FILES Isotropic_remeshing_dialog.ui) polyhedron_demo_plugin(isotropic_remeshing_plugin Isotropic_remeshing_plugin ${isotropicRemeshingUI_FILES} KEYWORDS PMP) target_link_libraries(isotropic_remeshing_plugin PUBLIC scene_surface_mesh_item scene_selection_item) -if(TBB_FOUND) - CGAL_target_use_TBB(isotropic_remeshing_plugin) +if(TARGET CGAL::TBB_support) + target_link_libraries(isotropic_remeshing_plugin PUBLIC CGAL::TBB_support) endif() polyhedron_demo_plugin(distance_plugin Distance_plugin KEYWORDS PMP) target_link_libraries(distance_plugin PUBLIC scene_surface_mesh_item scene_color_ramp) -if(TBB_FOUND) - CGAL_target_use_TBB(distance_plugin) +if(TARGET CGAL::TBB_support) + target_link_libraries(distance_plugin PUBLIC CGAL::TBB_support) endif() - polyhedron_demo_plugin(detect_sharp_edges_plugin Detect_sharp_edges_plugin KEYWORDS IO Mesh_3 PMP) target_link_libraries(detect_sharp_edges_plugin PUBLIC scene_surface_mesh_item) @@ -130,4 +124,3 @@ target_link_libraries(degenerated_faces_plugin PUBLIC scene_surface_mesh_item sc qt5_wrap_ui( engravUI_FILES Engrave_dock_widget.ui ) polyhedron_demo_plugin(engrave_text_plugin Engrave_text_plugin ${engravUI_FILES}) target_link_libraries(engrave_text_plugin PUBLIC scene_surface_mesh_item scene_selection_item scene_polylines_item) - diff --git a/Polyhedron/demo/Polyhedron/Plugins/Point_set/CMakeLists.txt b/Polyhedron/demo/Polyhedron/Plugins/Point_set/CMakeLists.txt index eaf6ddfaf9f..63dd314cd54 100644 --- a/Polyhedron/demo/Polyhedron/Plugins/Point_set/CMakeLists.txt +++ b/Polyhedron/demo/Polyhedron/Plugins/Point_set/CMakeLists.txt @@ -1,60 +1,59 @@ include( polyhedron_demo_macros ) -if(EIGEN3_FOUND) +if(TARGET CGAL::Eigen_support) find_package(SCIP QUIET) - if(NOT SCIP_FOUND) + include(CGAL_SCIP_support) + if(NOT TARGET CGAL::SCIP_support) find_package(GLPK QUIET) + include(CGAL_GLPK_support) endif() - if(NOT SCIP_FOUND AND NOT GLPK_FOUND) + if(NOT TARGET CGAL::SCIP_support AND NOT TARGET CGAL::GLPK_support) message(STATUS "NOTICE: SCIP and GLPK were not found. Polygonal surface reconstruction will not be available.") endif() qt5_wrap_ui( surface_reconstructionUI_FILES Surface_reconstruction_plugin.ui) polyhedron_demo_plugin(surface_reconstruction_plugin Surface_reconstruction_plugin Surface_reconstruction_poisson_impl Surface_reconstruction_advancing_front_impl Surface_reconstruction_scale_space_impl Surface_reconstruction_polygonal_impl ${surface_reconstructionUI_FILES} KEYWORDS PointSetProcessing) - target_link_libraries(surface_reconstruction_plugin PUBLIC scene_polygon_soup_item scene_surface_mesh_item scene_points_with_normal_item) - CGAL_target_use_Eigen(surface_reconstruction_plugin) + target_link_libraries(surface_reconstruction_plugin PUBLIC scene_polygon_soup_item scene_surface_mesh_item scene_points_with_normal_item CGAL::Eigen_support) - if (SCIP_FOUND) - CGAL_target_use_SCIP(surface_reconstruction_plugin) - elseif(GLPK_FOUND) - CGAL_target_use_GLPK(surface_reconstruction_plugin) + if (TARGET CGAL::SCIP_support) + target_link_libraries(surface_reconstruction_plugin PUBLIC CGAL::SCIP_support) + elseif(TARGET CGAL::GLPK_support) + target_link_libraries(surface_reconstruction_plugin PUBLIC CGAL::GLPK_support) endif() qt5_wrap_ui( point_set_normal_estimationUI_FILES Point_set_normal_estimation_plugin.ui) polyhedron_demo_plugin(point_set_normal_estimation_plugin Point_set_normal_estimation_plugin ${point_set_normal_estimationUI_FILES} KEYWORDS PointSetProcessing Classification) - target_link_libraries(point_set_normal_estimation_plugin PUBLIC scene_points_with_normal_item scene_callback_signaler) - CGAL_target_use_Eigen(point_set_normal_estimation_plugin) + target_link_libraries(point_set_normal_estimation_plugin PUBLIC scene_points_with_normal_item scene_callback_signaler CGAL::Eigen_support) qt5_wrap_ui( features_detection_pluginUI_FILES Features_detection_plugin.ui) polyhedron_demo_plugin(features_detection_plugin Features_detection_plugin ${features_detection_pluginUI_FILES} KEYWORDS PointSetProcessing) - target_link_libraries(features_detection_plugin PUBLIC scene_points_with_normal_item) - CGAL_target_use_Eigen(features_detection_plugin) + target_link_libraries(features_detection_plugin PUBLIC scene_points_with_normal_item CGAL::Eigen_support) polyhedron_demo_plugin(point_set_smoothing_plugin Point_set_smoothing_plugin KEYWORDS PointSetProcessing) - target_link_libraries(point_set_smoothing_plugin PUBLIC scene_points_with_normal_item scene_callback_signaler) - CGAL_target_use_Eigen(point_set_smoothing_plugin) + target_link_libraries(point_set_smoothing_plugin PUBLIC scene_points_with_normal_item scene_callback_signaler CGAL::Eigen_support) polyhedron_demo_plugin(point_set_average_spacing_plugin Point_set_average_spacing_plugin KEYWORDS PointSetProcessing Classification) - target_link_libraries(point_set_average_spacing_plugin PUBLIC scene_points_with_normal_item scene_callback_signaler) - CGAL_target_use_Eigen(point_set_average_spacing_plugin) + target_link_libraries(point_set_average_spacing_plugin PUBLIC scene_points_with_normal_item scene_callback_signaler CGAL::Eigen_support) qt5_wrap_ui(point_set_shape_detectionUI_FILES Point_set_shape_detection_plugin.ui) polyhedron_demo_plugin(point_set_shape_detection_plugin Point_set_shape_detection_plugin ${point_set_shape_detectionUI_FILES} KEYWORDS PointSetProcessing Classification) - target_link_libraries(point_set_shape_detection_plugin PUBLIC scene_surface_mesh_item scene_points_with_normal_item scene_polygon_soup_item scene_callback_signaler) - CGAL_target_use_Eigen(point_set_shape_detection_plugin) + target_link_libraries(point_set_shape_detection_plugin PUBLIC scene_surface_mesh_item scene_points_with_normal_item scene_polygon_soup_item scene_callback_signaler CGAL::Eigen_support) find_package(OpenGR QUIET) + include(CGAL_OpenGR_support) find_package(libpointmatcher QUIET) + include(CGAL_pointmatcher_support) - if (OpenGR_FOUND OR libpointmatcher_FOUND) + if (TARGET CGAL::OpenGR_support OR CGAL::pointmatcher_support) qt5_wrap_ui(register_point_setsUI_FILES Register_point_sets_plugin.ui) polyhedron_demo_plugin(register_point_sets_plugin Register_point_sets_plugin ${register_point_setsUI_FILES} KEYWORDS PointSetProcessing) - if (OpenGR_FOUND) - CGAL_target_use_OpenGR(register_point_sets_plugin) + target_link_libraries(register_point_sets_plugin PUBLIC CGAL::Eigen_support) + if (TARGET CGAL::OpenGR_support) + target_link_libraries(register_point_sets_plugin PUBLIC CGAL::OpenGR_support) endif() - if (libpointmatcher_FOUND) - CGAL_target_use_pointmatcher(register_point_sets_plugin) + if (TARGET CGAL::pointmatcher_support) + target_link_libraries(register_point_sets_plugin PUBLIC CGAL::pointmatcher_support) endif() else() message(STATUS "NOTICE: OpenGR and libpointmatcher were not found. Registrationp plugin will not be available.") @@ -106,7 +105,7 @@ endif() polyhedron_demo_plugin(point_set_to_mesh_distance_plugin Point_set_to_mesh_distance_plugin ${distanceUI_FILES} KEYWORDS PointSetProcessing) target_link_libraries(point_set_to_mesh_distance_plugin PUBLIC scene_points_with_normal_item scene_surface_mesh_item scene_color_ramp) - if(TBB_FOUND) + if(TARGET CGAL::TBB_support) foreach(plugin surface_reconstruction_plugin point_set_normal_estimation_plugin @@ -125,7 +124,7 @@ endif() alpha_shape_plugin point_set_to_mesh_distance_plugin) if(TARGET ${plugin}) - CGAL_target_use_TBB(${plugin}) + target_link_libraries(${plugin} PUBLIC CGAL::TBB_support) endif() endforeach() endif() diff --git a/Polyhedron/demo/Polyhedron/Plugins/Surface_mesh/CMakeLists.txt b/Polyhedron/demo/Polyhedron/Plugins/Surface_mesh/CMakeLists.txt index d56331772af..45c1eccb50e 100644 --- a/Polyhedron/demo/Polyhedron/Plugins/Surface_mesh/CMakeLists.txt +++ b/Polyhedron/demo/Polyhedron/Plugins/Surface_mesh/CMakeLists.txt @@ -4,18 +4,17 @@ if(POLICY CMP0074) cmake_policy(SET CMP0074 NEW) endif() -if(EIGEN3_FOUND) +if(TARGET CGAL::Eigen_support) find_package(CGAL COMPONENTS Core) include(${CGAL_USE_FILE}) qt5_wrap_ui(parameterizationUI_FILES Parameterization_widget.ui OTE_dialog.ui) polyhedron_demo_plugin(parameterization_plugin Parameterization_plugin ${parameterizationUI_FILES}) - target_link_libraries(parameterization_plugin PUBLIC scene_surface_mesh_item scene_textured_item scene_selection_item) - CGAL_target_use_Eigen(parameterization_plugin) -else(EIGEN3_FOUND) + target_link_libraries(parameterization_plugin PUBLIC scene_surface_mesh_item scene_textured_item scene_selection_item CGAL::Eigen_support) +else() message(STATUS "NOTICE: Eigen 3.1 (or greater) was not found. The Parameterization plugin will not be available.") -endif(EIGEN3_FOUND) +endif() qt5_wrap_ui( segmentationUI_FILES Mesh_segmentation_widget.ui) polyhedron_demo_plugin(mesh_segmentation_plugin Mesh_segmentation_plugin ${segmentationUI_FILES}) @@ -32,11 +31,11 @@ target_link_libraries(mesh_simplification_plugin PUBLIC scene_surface_mesh_item qt5_wrap_ui( remeshingUI_FILES Remeshing_dialog.ui) polyhedron_demo_plugin(offset_meshing_plugin Offset_meshing_plugin ${remeshingUI_FILES}) target_link_libraries(offset_meshing_plugin PUBLIC scene_surface_mesh_item scene_polygon_soup_item) -if(EIGEN3_FOUND) - CGAL_target_use_Eigen(offset_meshing_plugin) +if(TARGET CGAL::Eigen_support) + target_link_libraries(offset_meshing_plugin PUBLIC CGAL::Eigen_support) endif() -if(TBB_FOUND) - CGAL_target_use_TBB(offset_meshing_plugin) +if(TARGET CGAL::TBB_support) + target_link_libraries(offset_meshing_plugin PUBLIC CGAL::TBB_support) endif() qt5_wrap_ui( shortestPathUI_FILES Shortest_path_widget.ui ) diff --git a/Principal_component_analysis/demo/Principal_component_analysis/CMakeLists.txt b/Principal_component_analysis/demo/Principal_component_analysis/CMakeLists.txt index d8e2d1c3387..fa25ad50bf6 100644 --- a/Principal_component_analysis/demo/Principal_component_analysis/CMakeLists.txt +++ b/Principal_component_analysis/demo/Principal_component_analysis/CMakeLists.txt @@ -19,7 +19,8 @@ include_directories( ./ ) find_package(CGAL COMPONENTS Qt5) find_package(Eigen3 3.1.0) #(requires 3.1.0 or greater) -if (NOT EIGEN3_FOUND) +include(CGAL_Eigen_support) +if (NOT TARGET CGAL::Eigen_support) message(STATUS "NOTICE: This project requires the Eigen library, and will not be compiled.") return() endif() @@ -45,10 +46,9 @@ if(CGAL_Qt5_FOUND AND Qt5_FOUND ) add_file_dependencies( PCA_demo.cpp "${CMAKE_CURRENT_BINARY_DIR}/MainWindow_moc.cpp" "${CMAKE_CURRENT_BINARY_DIR}/Viewer_moc.cpp" ) add_executable ( PCA_demo PCA_demo.cpp ${UI_FILES} ${CGAL_Qt5_RESOURCE_FILES} ${CGAL_Qt5_MOC_FILES}) - CGAL_target_use_Eigen(PCA_demo) target_link_libraries( PCA_demo PRIVATE - CGAL::CGAL CGAL::CGAL_Qt5 Qt5::Gui) + CGAL::CGAL CGAL::CGAL_Qt5 CGAL::Eigen_support Qt5::Gui) add_to_cached_list( CGAL_EXECUTABLE_TARGETS PCA_demo ) diff --git a/Principal_component_analysis/examples/Principal_component_analysis/CMakeLists.txt b/Principal_component_analysis/examples/Principal_component_analysis/CMakeLists.txt index acdc5826865..c5955afe2b4 100644 --- a/Principal_component_analysis/examples/Principal_component_analysis/CMakeLists.txt +++ b/Principal_component_analysis/examples/Principal_component_analysis/CMakeLists.txt @@ -12,14 +12,15 @@ if ( CGAL_FOUND ) # Use Eigen find_package(Eigen3 3.1.0) #(requires 3.1.0 or greater) + include(CGAL_Eigen_support) # create a target per cppfile file(GLOB cppfiles RELATIVE ${CMAKE_CURRENT_SOURCE_DIR} ${CMAKE_CURRENT_SOURCE_DIR}/*.cpp) foreach(cppfile ${cppfiles}) create_single_source_cgal_program( "${cppfile}" ) - if (EIGEN3_FOUND) + if (TARGET CGAL::Eigen_support) get_filename_component(target ${cppfile} NAME_WE) - CGAL_target_use_Eigen(${target}) + target_link_libraries(${target} PUBLIC CGAL::Eigen_support) endif() endforeach() @@ -28,4 +29,3 @@ else() message(STATUS "This program requires the CGAL library, and will not be compiled.") endif() - diff --git a/Principal_component_analysis/test/Principal_component_analysis/CMakeLists.txt b/Principal_component_analysis/test/Principal_component_analysis/CMakeLists.txt index 02d5f28a0ac..236ac02b1be 100644 --- a/Principal_component_analysis/test/Principal_component_analysis/CMakeLists.txt +++ b/Principal_component_analysis/test/Principal_component_analysis/CMakeLists.txt @@ -12,14 +12,15 @@ if ( CGAL_FOUND ) # Use Eigen find_package(Eigen3 3.1.0) #(requires 3.1.0 or greater) + include(CGAL_Eigen_support) # create a target per cppfile file(GLOB cppfiles RELATIVE ${CMAKE_CURRENT_SOURCE_DIR} ${CMAKE_CURRENT_SOURCE_DIR}/*.cpp) foreach(cppfile ${cppfiles}) create_single_source_cgal_program( "${cppfile}" ) - if (EIGEN3_FOUND) + if (TARGET CGAL::Eigen_support) get_filename_component(target ${cppfile} NAME_WE) - CGAL_target_use_Eigen(${target}) + target_link_libraries(${target} PUBLIC CGAL::Eigen_support) endif() endforeach() @@ -28,4 +29,3 @@ else() message(STATUS "This program requires the CGAL library, and will not be compiled.") endif() - diff --git a/Property_map/examples/Property_map/CMakeLists.txt b/Property_map/examples/Property_map/CMakeLists.txt index d5717d3f5d2..5d251def5cf 100644 --- a/Property_map/examples/Property_map/CMakeLists.txt +++ b/Property_map/examples/Property_map/CMakeLists.txt @@ -33,9 +33,8 @@ endif() create_single_source_cgal_program( "dynamic_properties.cpp" ) find_package(Eigen3 3.1.0) #(requires 3.1.0 or greater) -if (EIGEN3_FOUND) +include(CGAL_Eigen_support) +if (TARGET CGAL::Eigen_support) create_single_source_cgal_program( "custom_property_map.cpp" ) - CGAL_target_use_Eigen(custom_property_map) + target_link_libraries(custom_property_map PUBLIC CGAL::Eigen_support) endif() - - diff --git a/Ridges_3/examples/Ridges_3/CMakeLists.txt b/Ridges_3/examples/Ridges_3/CMakeLists.txt index 9392ccb1b48..3fe086671df 100644 --- a/Ridges_3/examples/Ridges_3/CMakeLists.txt +++ b/Ridges_3/examples/Ridges_3/CMakeLists.txt @@ -10,7 +10,8 @@ if ( CGAL_FOUND ) # use either Eigen find_package(Eigen3 3.1.0) #(requires 3.1.0 or greater) - if (EIGEN3_FOUND) + include(CGAL_Eigen_support) + if (TARGET CGAL::Eigen_support) # Link with Boost.ProgramOptions (optional) find_package(Boost QUIET COMPONENTS program_options) @@ -28,11 +29,11 @@ if ( CGAL_FOUND ) endif() create_single_source_cgal_program( Compute_Ridges_Umbilics.cpp) - CGAL_target_use_Eigen(Compute_Ridges_Umbilics) + target_link_libraries(Compute_Ridges_Umbilics PUBLIC CGAL::Eigen_support) create_single_source_cgal_program( Ridges_Umbilics_SM.cpp) - CGAL_target_use_Eigen(Ridges_Umbilics_SM) + target_link_libraries(Ridges_Umbilics_SM PUBLIC CGAL::Eigen_support) create_single_source_cgal_program( Ridges_Umbilics_LCC.cpp) - CGAL_target_use_Eigen(Ridges_Umbilics_LCC) + target_link_libraries(Ridges_Umbilics_LCC PUBLIC CGAL::Eigen_support) else() diff --git a/Ridges_3/test/Ridges_3/CMakeLists.txt b/Ridges_3/test/Ridges_3/CMakeLists.txt index 139ca8dfb10..95025861c1c 100644 --- a/Ridges_3/test/Ridges_3/CMakeLists.txt +++ b/Ridges_3/test/Ridges_3/CMakeLists.txt @@ -13,9 +13,10 @@ if ( CGAL_FOUND ) # use either Eigen find_package(Eigen3 3.1.0) #(requires 3.1.0 or greater) - if (EIGEN3_FOUND) + include(CGAL_Eigen_support) + if (TARGET CGAL::Eigen_support) create_single_source_cgal_program( "ridge_test.cpp" ) - CGAL_target_use_Eigen(ridge_test) + target_link_libraries(ridge_test PUBLIC CGAL::Eigen_support) else() message(STATUS "NOTICE: This program requires Eigen 3.1 (or greater) and will not be compiled.") @@ -27,4 +28,3 @@ else() message(STATUS "NOTICE: This program requires the CGAL library, and will not be compiled.") endif() - diff --git a/STL_Extension/benchmark/compact_container_benchmark/CMakeLists.txt b/STL_Extension/benchmark/compact_container_benchmark/CMakeLists.txt index 4bfa4327eb0..de657c74d8f 100644 --- a/STL_Extension/benchmark/compact_container_benchmark/CMakeLists.txt +++ b/STL_Extension/benchmark/compact_container_benchmark/CMakeLists.txt @@ -6,9 +6,10 @@ find_package(CGAL QUIET) if ( CGAL_FOUND ) find_package( TBB ) + include(CGAL_TBB_support) create_single_source_cgal_program( "cc_benchmark.cpp" ) - if(TBB_FOUND) - CGAL_target_use_TBB(cc_benchmark) + if(TARGET CGAL::TBB_support) + target_link_libraries(cc_benchmark PUBLIC CGAL::TBB_support) endif() else() message(STATUS "This program requires the CGAL library, and will not be compiled.") diff --git a/STL_Extension/test/STL_Extension/CMakeLists.txt b/STL_Extension/test/STL_Extension/CMakeLists.txt index 80563069300..4a427003e02 100644 --- a/STL_Extension/test/STL_Extension/CMakeLists.txt +++ b/STL_Extension/test/STL_Extension/CMakeLists.txt @@ -12,6 +12,7 @@ find_package(CGAL QUIET) if ( CGAL_FOUND ) find_package( TBB QUIET ) + include(CGAL_TBB_support) create_single_source_cgal_program( "test_Boolean_tag.cpp" ) create_single_source_cgal_program( "test_Cache.cpp" ) @@ -21,8 +22,8 @@ if ( CGAL_FOUND ) create_single_source_cgal_program( "test_composition.cpp" ) create_single_source_cgal_program( "test_Concatenate_iterator.cpp" ) create_single_source_cgal_program( "test_Concurrent_compact_container.cpp" ) - if(TBB_FOUND) - CGAL_target_use_TBB(test_Concurrent_compact_container) + if(TARGET CGAL::TBB_support) + target_link_libraries(test_Concurrent_compact_container PUBLIC CGAL::TBB_support) endif() create_single_source_cgal_program( "test_dispatch_output.cpp" ) create_single_source_cgal_program( "test_Flattening_iterator.cpp" ) @@ -43,12 +44,11 @@ if ( CGAL_FOUND ) create_single_source_cgal_program( "test_vector.cpp" ) create_single_source_cgal_program( "test_join_iterators.cpp" ) create_single_source_cgal_program( "test_for_each.cpp" ) - if(TBB_FOUND) - CGAL_target_use_TBB(test_for_each) + if(TARGET CGAL::TBB_support) + target_link_libraries(test_for_each PUBLIC CGAL::TBB_support) endif() else() message(STATUS "This program requires the CGAL library, and will not be compiled.") endif() - diff --git a/Scale_space_reconstruction_3/examples/Scale_space_reconstruction_3/CMakeLists.txt b/Scale_space_reconstruction_3/examples/Scale_space_reconstruction_3/CMakeLists.txt index e1bfb24bc41..b6b1e1a3ba1 100644 --- a/Scale_space_reconstruction_3/examples/Scale_space_reconstruction_3/CMakeLists.txt +++ b/Scale_space_reconstruction_3/examples/Scale_space_reconstruction_3/CMakeLists.txt @@ -13,26 +13,28 @@ if ( CGAL_FOUND ) if( ACTIVATE_CONCURRENCY ) find_package( TBB ) - if( NOT TBB_FOUND ) + include(CGAL_TBB_support) + if( NOT TARGET CGAL::TBB_support ) message( STATUS "NOTICE: Intel TBB NOT found! The example is faster if TBB is linked." ) endif() endif() find_package( Eigen3 3.1.0 ) - if( EIGEN3_FOUND ) + include(CGAL_Eigen_support) + if( TARGET CGAL::Eigen_support ) create_single_source_cgal_program( "scale_space.cpp" ) - CGAL_target_use_Eigen(scale_space) + target_link_libraries(scale_space PUBLIC CGAL::Eigen_support) create_single_source_cgal_program( "scale_space_incremental.cpp" ) - CGAL_target_use_Eigen(scale_space_incremental) + target_link_libraries(scale_space_incremental PUBLIC CGAL::Eigen_support) create_single_source_cgal_program( "scale_space_manifold.cpp" ) - CGAL_target_use_Eigen(scale_space_manifold) + target_link_libraries(scale_space_manifold PUBLIC CGAL::Eigen_support) create_single_source_cgal_program( "scale_space_advancing_front.cpp" ) - CGAL_target_use_Eigen(scale_space_advancing_front) - if(ACTIVATE_CONCURRENCY AND TBB_FOUND) - CGAL_target_use_TBB(scale_space) - CGAL_target_use_TBB(scale_space_incremental) - CGAL_target_use_TBB(scale_space_manifold) - CGAL_target_use_TBB(scale_space_advancing_front) + target_link_libraries(scale_space_advancing_front PUBLIC CGAL::Eigen_support) + if(ACTIVATE_CONCURRENCY AND TARGET CGAL::TBB_support) + target_link_libraries(scale_space PUBLIC CGAL::TBB_support) + target_link_libraries(scale_space_incremental PUBLIC CGAL::TBB_support) + target_link_libraries(scale_space_manifold PUBLIC CGAL::TBB_support) + target_link_libraries(scale_space_advancing_front PUBLIC CGAL::TBB_support) endif() else() message( STATUS "NOTICE: The example needs Eigen 3.1 (or greater) and will not be compiled." ) diff --git a/Shape_detection/benchmark/Shape_detection/CMakeLists.txt b/Shape_detection/benchmark/Shape_detection/CMakeLists.txt index e89abfcbdf8..0e8d4b74cf0 100644 --- a/Shape_detection/benchmark/Shape_detection/CMakeLists.txt +++ b/Shape_detection/benchmark/Shape_detection/CMakeLists.txt @@ -14,13 +14,14 @@ if(CGAL_FOUND) # Use Eigen. find_package(Eigen3 3.1.0 QUIET) # (3.1.0 or greater) - if(EIGEN3_FOUND) + include(CGAL_Eigen_support) + if(TARGET CGAL::Eigen_support) create_single_source_cgal_program( "benchmark_region_growing_on_point_set_2.cpp") - CGAL_target_use_Eigen(benchmark_region_growing_on_point_set_2) + target_link_libraries(benchmark_region_growing_on_point_set_2 PUBLIC CGAL::Eigen_support) create_single_source_cgal_program( "benchmark_region_growing_on_point_set_3.cpp") - CGAL_target_use_Eigen(benchmark_region_growing_on_point_set_3) + target_link_libraries(benchmark_region_growing_on_point_set_3 PUBLIC CGAL::Eigen_support) endif() else() diff --git a/Shape_detection/examples/Shape_detection/CMakeLists.txt b/Shape_detection/examples/Shape_detection/CMakeLists.txt index be7c4667d6d..b012e3a0256 100644 --- a/Shape_detection/examples/Shape_detection/CMakeLists.txt +++ b/Shape_detection/examples/Shape_detection/CMakeLists.txt @@ -14,7 +14,8 @@ if(CGAL_FOUND) # Use Eigen. find_package(Eigen3 3.1.0 QUIET) # (3.1.0 or greater) - if(EIGEN3_FOUND) + include(CGAL_Eigen_support) + if(TARGET CGAL::Eigen_support) create_single_source_cgal_program( "efficient_RANSAC_basic.cpp") create_single_source_cgal_program( @@ -43,7 +44,7 @@ if(CGAL_FOUND) region_growing_on_polygon_mesh region_growing_with_custom_classes shape_detection_basic_deprecated) - CGAL_target_use_Eigen(${target}) + target_link_libraries(${target} PUBLIC CGAL::Eigen_support) endforeach() endif() diff --git a/Shape_detection/test/Shape_detection/CMakeLists.txt b/Shape_detection/test/Shape_detection/CMakeLists.txt index 2effc7dd265..b804d1014f2 100644 --- a/Shape_detection/test/Shape_detection/CMakeLists.txt +++ b/Shape_detection/test/Shape_detection/CMakeLists.txt @@ -14,6 +14,7 @@ if(CGAL_FOUND) # Use Eigen. find_package(Eigen3 3.1.0 QUIET) # (3.1.0 or greater) + include(CGAL_Eigen_support) if(EIGEN3_FOUND) create_single_source_cgal_program( "test_region_growing_basic.cpp") @@ -43,7 +44,7 @@ if(CGAL_FOUND) test_region_growing_on_point_set_3_with_sorting test_region_growing_on_polygon_mesh_with_sorting test_region_growing_on_degenerated_mesh) - CGAL_target_use_Eigen(${target}) + target_link_libraries(${target} PUBLIC CGAL::Eigen_support) endforeach() endif() diff --git a/Solver_interface/examples/Solver_interface/CMakeLists.txt b/Solver_interface/examples/Solver_interface/CMakeLists.txt index fbbea89f568..d6f2c10833a 100644 --- a/Solver_interface/examples/Solver_interface/CMakeLists.txt +++ b/Solver_interface/examples/Solver_interface/CMakeLists.txt @@ -12,32 +12,35 @@ if ( CGAL_FOUND ) # Use Eigen find_package(Eigen3 3.1.0) #(requires 3.1.0 or greater) + include(CGAL_Eigen_support) - if (EIGEN3_FOUND) + if (TARGET CGAL::Eigen_support) create_single_source_cgal_program( "singular_value_decomposition.cpp" ) - CGAL_target_use_Eigen(singular_value_decomposition) + target_link_libraries(singular_value_decomposition PUBLIC CGAL::Eigen_support) create_single_source_cgal_program( "sparse_solvers.cpp" ) - CGAL_target_use_Eigen(sparse_solvers) + target_link_libraries(sparse_solvers PUBLIC CGAL::Eigen_support) create_single_source_cgal_program( "diagonalize_matrix.cpp" ) - CGAL_target_use_Eigen(diagonalize_matrix) + target_link_libraries(diagonalize_matrix PUBLIC CGAL::Eigen_support) endif() create_single_source_cgal_program( "mixed_integer_program.cpp" ) find_package( SCIP QUIET) + include(CGAL_SCIP_support) - if (SCIP_FOUND) + if (TARGET CGAL::SCIP_support) - CGAL_target_use_SCIP(mixed_integer_program) + target_link_libraries(mixed_integer_program PUBLIC CGAL::SCIP_support) message("SCIP found and used") else() - find_package( GLPK QUIET) + find_package( GLPK QUIET) + include(CGAL_GLPK_support) - if (GLPK_FOUND) + if (TARGET CGAL::GLPK_support) - CGAL_target_use_GLPK(mixed_integer_program) + target_link_libraries(mixed_integer_program PUBLIC CGAL::GLPK_support) message("GLPK found and used") else() @@ -54,4 +57,3 @@ else() message(STATUS "NOTICE: This program requires the CGAL library, and will not be compiled.") endif() - diff --git a/Spatial_searching/benchmark/Spatial_searching/CMakeLists.txt b/Spatial_searching/benchmark/Spatial_searching/CMakeLists.txt index 010a9bc992f..e2bb99bb3f6 100644 --- a/Spatial_searching/benchmark/Spatial_searching/CMakeLists.txt +++ b/Spatial_searching/benchmark/Spatial_searching/CMakeLists.txt @@ -13,6 +13,7 @@ if ( CGAL_FOUND ) include(${CGAL_USE_FILE}) find_package(Eigen3 3.1.91) #(requires 3.2.0 or greater) +include(CGAL_Eigen_support) include_directories (BEFORE "include") @@ -45,7 +46,7 @@ find_package(Eigen3 3.1.91) #(requires 3.2.0 or greater) nn3nanoflan sizeof deque) - CGAL_target_use_Eigen(${target}) + target_link_libraries(${target} PUBLIC CGAL::Eigen_support) endforeach() else() @@ -53,4 +54,3 @@ else() message(STATUS "This program requires the CGAL library, and will not be compiled.") endif() - diff --git a/Spatial_searching/examples/Spatial_searching/CMakeLists.txt b/Spatial_searching/examples/Spatial_searching/CMakeLists.txt index a7e3bdd7983..37737a91826 100644 --- a/Spatial_searching/examples/Spatial_searching/CMakeLists.txt +++ b/Spatial_searching/examples/Spatial_searching/CMakeLists.txt @@ -18,6 +18,7 @@ if ( NOT CGAL_FOUND ) endif() find_package(Eigen3 3.1.91) #(requires 3.2.0 or greater) +include(CGAL_Eigen_support) if (MSVC) # Turn off VC++ warning @@ -62,13 +63,13 @@ create_single_source_cgal_program( "weighted_Minkowski_distance.cpp" ) -if (EIGEN3_FOUND) +if (TARGET CGAL::Eigen_support) create_single_source_cgal_program( "fuzzy_range_query.cpp" ) - CGAL_target_use_Eigen(fuzzy_range_query) + target_link_libraries(fuzzy_range_query PUBLIC CGAL::Eigen_support) create_single_source_cgal_program( "general_neighbor_searching.cpp" ) - CGAL_target_use_Eigen(general_neighbor_searching) + target_link_libraries(general_neighbor_searching PUBLIC CGAL::Eigen_support) else() diff --git a/Spatial_sorting/examples/Spatial_sorting/CMakeLists.txt b/Spatial_sorting/examples/Spatial_sorting/CMakeLists.txt index f865c8028c2..25197170b29 100644 --- a/Spatial_sorting/examples/Spatial_sorting/CMakeLists.txt +++ b/Spatial_sorting/examples/Spatial_sorting/CMakeLists.txt @@ -16,13 +16,12 @@ if ( CGAL_FOUND ) endforeach() find_package( TBB QUIET ) - if( TBB_FOUND ) - include( CGAL_target_use_TBB ) - CGAL_target_use_TBB( parallel_spatial_sort_3 ) + include(CGAL_TBB_support) + if( TARGET CGAL::TBB_support ) + target_link_libraries( parallel_spatial_sort_3 PUBLIC CGAL::TBB_support) endif() else() message(STATUS "This program requires the CGAL library, and will not be compiled.") endif() - diff --git a/Spatial_sorting/test/Spatial_sorting/CMakeLists.txt b/Spatial_sorting/test/Spatial_sorting/CMakeLists.txt index 8213186a4b0..437508bf629 100644 --- a/Spatial_sorting/test/Spatial_sorting/CMakeLists.txt +++ b/Spatial_sorting/test/Spatial_sorting/CMakeLists.txt @@ -13,14 +13,13 @@ if ( CGAL_FOUND ) create_single_source_cgal_program( "test_multiscale.cpp" ) find_package (TBB QUIET) - if( TBB_FOUND ) - include( CGAL_target_use_TBB ) - CGAL_target_use_TBB( test_hilbert ) - endif( TBB_FOUND ) + include(CGAL_TBB_support) + if( TARGET CGAL::TBB_support ) + target_link_libraries( test_hilbert PUBLIC CGAL::TBB_support ) + endif() else() message(STATUS "This program requires the CGAL library, and will not be compiled.") endif() - diff --git a/Surface_mesh_approximation/examples/Surface_mesh_approximation/CMakeLists.txt b/Surface_mesh_approximation/examples/Surface_mesh_approximation/CMakeLists.txt index aa73bcd3807..c73ab50c135 100644 --- a/Surface_mesh_approximation/examples/Surface_mesh_approximation/CMakeLists.txt +++ b/Surface_mesh_approximation/examples/Surface_mesh_approximation/CMakeLists.txt @@ -28,7 +28,8 @@ endif() # Use Eigen (for PCA) find_package(Eigen3 3.1.0 REQUIRED) #(3.1.0 or greater) -if (NOT EIGEN3_FOUND) +include(CGAL_Eigen_support) +if (NOT TARGET CGAL::Eigen_support) message(STATUS "This project requires the Eigen library, and will not be compiled.") return() endif() @@ -39,20 +40,19 @@ endif() include( CGAL_CreateSingleSourceCGALProgram ) create_single_source_cgal_program( "vsa_approximation_2_example.cpp" ) -CGAL_target_use_Eigen(vsa_approximation_2_example) +target_link_libraries(vsa_approximation_2_example PUBLIC CGAL::Eigen_support) create_single_source_cgal_program( "vsa_approximation_example.cpp" ) -CGAL_target_use_Eigen(vsa_approximation_example) +target_link_libraries(vsa_approximation_example PUBLIC CGAL::Eigen_support) create_single_source_cgal_program( "vsa_class_interface_example.cpp" ) -CGAL_target_use_Eigen(vsa_class_interface_example) +target_link_libraries(vsa_class_interface_example PUBLIC CGAL::Eigen_support) create_single_source_cgal_program( "vsa_isotropic_metric_example.cpp" ) -CGAL_target_use_Eigen(vsa_isotropic_metric_example) +target_link_libraries(vsa_isotropic_metric_example PUBLIC CGAL::Eigen_support) create_single_source_cgal_program( "vsa_segmentation_example.cpp" ) -CGAL_target_use_Eigen(vsa_segmentation_example) +target_link_libraries(vsa_segmentation_example PUBLIC CGAL::Eigen_support) create_single_source_cgal_program( "vsa_simple_approximation_example.cpp" ) -CGAL_target_use_Eigen(vsa_simple_approximation_example) - +target_link_libraries(vsa_simple_approximation_example PUBLIC CGAL::Eigen_support) diff --git a/Surface_mesh_approximation/test/Surface_mesh_approximation/CMakeLists.txt b/Surface_mesh_approximation/test/Surface_mesh_approximation/CMakeLists.txt index a41a41f1996..9548e5ac986 100644 --- a/Surface_mesh_approximation/test/Surface_mesh_approximation/CMakeLists.txt +++ b/Surface_mesh_approximation/test/Surface_mesh_approximation/CMakeLists.txt @@ -29,7 +29,8 @@ endif() # Use Eigen (for PCA) find_package(Eigen3 3.1.0 REQUIRED) #(3.1.0 or greater) -if (NOT EIGEN3_FOUND) +include(CGAL_Eigen_support) +if (NOT TARGET CGAL::Eigen_support) message(STATUS "This project requires the Eigen library, and will not be compiled.") return() endif() @@ -41,30 +42,28 @@ endif() include( CGAL_CreateSingleSourceCGALProgram ) create_single_source_cgal_program( "vsa_class_interface_test.cpp" ) -CGAL_target_use_Eigen(vsa_class_interface_test) +target_link_libraries(vsa_class_interface_test PUBLIC CGAL::Eigen_support) create_single_source_cgal_program( "vsa_correctness_test.cpp" ) -CGAL_target_use_Eigen(vsa_correctness_test) +target_link_libraries(vsa_correctness_test PUBLIC CGAL::Eigen_support) create_single_source_cgal_program( "vsa_error_decrease_test.cpp" ) -CGAL_target_use_Eigen(vsa_error_decrease_test) +target_link_libraries(vsa_error_decrease_test PUBLIC CGAL::Eigen_support) create_single_source_cgal_program( "vsa_kernel_test.cpp" ) -CGAL_target_use_Eigen(vsa_kernel_test) +target_link_libraries(vsa_kernel_test PUBLIC CGAL::Eigen_support) create_single_source_cgal_program( "vsa_approximation_test.cpp" ) -CGAL_target_use_Eigen(vsa_approximation_test) +target_link_libraries(vsa_approximation_test PUBLIC CGAL::Eigen_support) create_single_source_cgal_program( "vsa_segmentation_test.cpp" ) -CGAL_target_use_Eigen(vsa_segmentation_test) +target_link_libraries(vsa_segmentation_test PUBLIC CGAL::Eigen_support) create_single_source_cgal_program( "vsa_meshing_manifold_test.cpp" ) -CGAL_target_use_Eigen(vsa_meshing_manifold_test) +target_link_libraries(vsa_meshing_manifold_test PUBLIC CGAL::Eigen_support) create_single_source_cgal_program( "vsa_metric_test.cpp" ) -CGAL_target_use_Eigen(vsa_metric_test) +target_link_libraries(vsa_metric_test PUBLIC CGAL::Eigen_support) create_single_source_cgal_program( "vsa_teleportation_test.cpp" ) -CGAL_target_use_Eigen(vsa_teleportation_test) - - +target_link_libraries(vsa_teleportation_test PUBLIC CGAL::Eigen_support) diff --git a/Surface_mesh_deformation/demo/Surface_mesh_deformation/CMakeLists.txt b/Surface_mesh_deformation/demo/Surface_mesh_deformation/CMakeLists.txt index b17f5995d32..daabda6ac44 100644 --- a/Surface_mesh_deformation/demo/Surface_mesh_deformation/CMakeLists.txt +++ b/Surface_mesh_deformation/demo/Surface_mesh_deformation/CMakeLists.txt @@ -17,9 +17,10 @@ find_package(CGAL QUIET) if ( CGAL_FOUND ) find_package(Eigen3 3.1.91) #(requires 3.2.0 or greater) - if (EIGEN3_FOUND) + include(CGAL_Eigen_support) + if (TARGET CGAL::Eigen_support) create_single_source_cgal_program( "deform_mesh_for_botsch08_format.cpp" ) - CGAL_target_use_Eigen(deform_mesh_for_botsch08_format) + target_link_libraries(deform_mesh_for_botsch08_format PUBLIC CGAL::Eigen_support) else() message(STATUS "NOTICE: This program requires the Eigen library, version 3.2 or later and will not be compiled.") endif() @@ -28,4 +29,3 @@ else() message(STATUS "NOTICE: This program requires the CGAL library, and will not be compiled.") endif() - diff --git a/Surface_mesh_deformation/examples/Surface_mesh_deformation/CMakeLists.txt b/Surface_mesh_deformation/examples/Surface_mesh_deformation/CMakeLists.txt index ca146f90433..f60163d11be 100644 --- a/Surface_mesh_deformation/examples/Surface_mesh_deformation/CMakeLists.txt +++ b/Surface_mesh_deformation/examples/Surface_mesh_deformation/CMakeLists.txt @@ -12,7 +12,8 @@ find_package(CGAL QUIET) if ( CGAL_FOUND ) find_package(Eigen3 3.1.91) #(requires 3.2.0 or greater) - if (EIGEN3_FOUND) + include(CGAL_Eigen_support) + if (TARGET CGAL::Eigen_support) create_single_source_cgal_program( "all_roi_assign_example.cpp" ) create_single_source_cgal_program( "all_roi_assign_example_custom_polyhedron.cpp" ) create_single_source_cgal_program( "all_roi_assign_example_Surface_mesh.cpp" ) @@ -31,15 +32,14 @@ if ( CGAL_FOUND ) k_ring_roi_translate_rotate_example k_ring_roi_translate_rotate_Surface_mesh deform_mesh_for_botsch08_format_sre_arap) - CGAL_target_use_Eigen(${target}) + target_link_libraries(${target} PUBLIC CGAL::Eigen_support) endforeach() find_package( OpenMesh QUIET ) if ( OpenMesh_FOUND ) include( UseOpenMesh ) create_single_source_cgal_program( "all_roi_assign_example_with_OpenMesh.cpp" ) - target_link_libraries( all_roi_assign_example_with_OpenMesh PRIVATE ${OPENMESH_LIBRARIES} ) - CGAL_target_use_Eigen(all_roi_assign_example_with_OpenMesh) + target_link_libraries( all_roi_assign_example_with_OpenMesh PRIVATE ${OPENMESH_LIBRARIES} CGAL::Eigen_support) else() message(STATUS "Example that use OpenMesh will not be compiled.") endif() @@ -52,4 +52,3 @@ else() message(STATUS "NOTICE: These exmaples require the CGAL library, and will not be compiled.") endif() - diff --git a/Surface_mesh_deformation/test/Surface_mesh_deformation/CMakeLists.txt b/Surface_mesh_deformation/test/Surface_mesh_deformation/CMakeLists.txt index 05da9a51cf7..624cef733bb 100644 --- a/Surface_mesh_deformation/test/Surface_mesh_deformation/CMakeLists.txt +++ b/Surface_mesh_deformation/test/Surface_mesh_deformation/CMakeLists.txt @@ -12,20 +12,20 @@ find_package(CGAL QUIET) if ( CGAL_FOUND ) find_package(Eigen3 3.1.91) #(requires 3.2.0 or greater) - if (EIGEN3_FOUND) + include(CGAL_Eigen_support) + if (TARGET CGAL::Eigen_support) create_single_source_cgal_program( "Cactus_deformation_session.cpp" ) - CGAL_target_use_Eigen(Cactus_deformation_session) + target_link_libraries(Cactus_deformation_session PUBLIC CGAL::Eigen_support) create_single_source_cgal_program( "Cactus_performance_test.cpp" ) - CGAL_target_use_Eigen(Cactus_performance_test) + target_link_libraries(Cactus_performance_test PUBLIC CGAL::Eigen_support) create_single_source_cgal_program( "Symmetry_test.cpp" ) - CGAL_target_use_Eigen(Symmetry_test) + target_link_libraries(Symmetry_test PUBLIC CGAL::Eigen_support) find_package( OpenMesh QUIET ) if ( OpenMesh_FOUND ) include( UseOpenMesh ) create_single_source_cgal_program( "Cactus_deformation_session_OpenMesh.cpp" ) - CGAL_target_use_Eigen(Cactus_deformation_session_OpenMesh) - target_link_libraries( Cactus_deformation_session_OpenMesh PRIVATE ${OPENMESH_LIBRARIES} ) + target_link_libraries( Cactus_deformation_session_OpenMesh PRIVATE ${OPENMESH_LIBRARIES} CGAL::Eigen_support) else() message(STATUS "Example that use OpenMesh will not be compiled.") endif() @@ -37,4 +37,3 @@ else() message(STATUS "NOTICE: These tests require the CGAL library, and will not be compiled.") endif() - diff --git a/Surface_mesh_parameterization/examples/Surface_mesh_parameterization/CMakeLists.txt b/Surface_mesh_parameterization/examples/Surface_mesh_parameterization/CMakeLists.txt index 185aacb9503..eab97c84ecb 100644 --- a/Surface_mesh_parameterization/examples/Surface_mesh_parameterization/CMakeLists.txt +++ b/Surface_mesh_parameterization/examples/Surface_mesh_parameterization/CMakeLists.txt @@ -12,7 +12,8 @@ find_package(CGAL QUIET) if ( CGAL_FOUND ) find_package(Eigen3 3.1.0) #(requires 3.1.0 or greater) - if (EIGEN3_FOUND) + include(CGAL_Eigen_support) + if (TARGET CGAL::Eigen_support) # Executables that require Eigen 3.1 # ------------------------------------------------------------------ @@ -51,29 +52,28 @@ if ( CGAL_FOUND ) # ------------------------------------------------------------------ create_single_source_cgal_program( "discrete_authalic.cpp" ) - CGAL_target_use_Eigen(discrete_authalic) + target_link_libraries(discrete_authalic PUBLIC CGAL::Eigen_support) create_single_source_cgal_program( "lscm.cpp" ) - CGAL_target_use_Eigen(lscm) + target_link_libraries(lscm PUBLIC CGAL::Eigen_support) create_single_source_cgal_program( "orbifold.cpp" ) - CGAL_target_use_Eigen(orbifold) + target_link_libraries(orbifold PUBLIC CGAL::Eigen_support) create_single_source_cgal_program( "seam_Polyhedron_3.cpp" ) - CGAL_target_use_Eigen(seam_Polyhedron_3) + target_link_libraries(seam_Polyhedron_3 PUBLIC CGAL::Eigen_support) create_single_source_cgal_program( "simple_parameterization.cpp" ) - CGAL_target_use_Eigen(simple_parameterization) + target_link_libraries(simple_parameterization PUBLIC CGAL::Eigen_support) create_single_source_cgal_program( "square_border_parameterizer.cpp" ) - CGAL_target_use_Eigen(square_border_parameterizer) + target_link_libraries(square_border_parameterizer PUBLIC CGAL::Eigen_support) if(SuiteSparse_FOUND) target_link_libraries(orbifold PRIVATE ${SuiteSparse_LIBRARIES}) endif() - else(EIGEN3_FOUND) + else() message(STATUS "NOTICE: The examples require Eigen 3.1 (or greater) and will not be compiled.") - endif(EIGEN3_FOUND) + endif() else() message(STATUS "NOTICE: This program requires the CGAL library, and will not be compiled.") endif() - diff --git a/Surface_mesh_parameterization/test/Surface_mesh_parameterization/CMakeLists.txt b/Surface_mesh_parameterization/test/Surface_mesh_parameterization/CMakeLists.txt index 401f37978b4..7141d3fef9a 100644 --- a/Surface_mesh_parameterization/test/Surface_mesh_parameterization/CMakeLists.txt +++ b/Surface_mesh_parameterization/test/Surface_mesh_parameterization/CMakeLists.txt @@ -13,16 +13,16 @@ if ( CGAL_FOUND ) find_package(Eigen3 3.1.0) #(requires 3.1.0 or greater) - if(EIGEN3_FOUND) + include(CGAL_Eigen_support) + if(TARGET CGAL::Eigen_support) create_single_source_cgal_program( "extensive_parameterization_test.cpp" ) - CGAL_target_use_Eigen(extensive_parameterization_test) - else(EIGEN3_FOUND) + target_link_libraries(extensive_parameterization_test PUBLIC CGAL::Eigen_support) + else() message(STATUS "NOTICE: The tests require Eigen 3.1 (or greater) and will not be compiled.") - endif(EIGEN3_FOUND) + endif() else() message(STATUS "NOTICE: This program requires the CGAL library, and will not be compiled.") endif() - diff --git a/Surface_mesh_simplification/examples/Surface_mesh_simplification/CMakeLists.txt b/Surface_mesh_simplification/examples/Surface_mesh_simplification/CMakeLists.txt index cb06fb9d434..bfd216d1e80 100644 --- a/Surface_mesh_simplification/examples/Surface_mesh_simplification/CMakeLists.txt +++ b/Surface_mesh_simplification/examples/Surface_mesh_simplification/CMakeLists.txt @@ -43,9 +43,10 @@ create_single_source_cgal_program( "edge_collapse_bounded_normal_change.cpp" ) create_single_source_cgal_program( "edge_collapse_visitor_surface_mesh.cpp" ) find_package(Eigen3 3.1.0 QUIET) #(3.1.0 or greater) -if( Eigen3_FOUND ) +include(CGAL_Eigen_support) +if( TARGET CGAL::Eigen_support ) create_single_source_cgal_program( "edge_collapse_garland_heckbert.cpp" ) - CGAL_target_use_Eigen(edge_collapse_garland_heckbert) + target_link_libraries(edge_collapse_garland_heckbert PUBLIC CGAL::Eigen_support) else () message(STATUS "Garland-Heckbert polices require the Eigen library, which has not been found; related examples will not be compiled.") endif() diff --git a/Surface_mesh_skeletonization/benchmark/Surface_mesh_skeletonization/CMakeLists.txt b/Surface_mesh_skeletonization/benchmark/Surface_mesh_skeletonization/CMakeLists.txt index 0fb1f28c09d..b5522d61809 100644 --- a/Surface_mesh_skeletonization/benchmark/Surface_mesh_skeletonization/CMakeLists.txt +++ b/Surface_mesh_skeletonization/benchmark/Surface_mesh_skeletonization/CMakeLists.txt @@ -35,17 +35,17 @@ endif() # include for local package find_package(Eigen3 3.2.0) #(requires 3.2.0 or greater) +include(CGAL_Eigen_support) -if(NOT EIGEN3_FOUND) +if(NOT TARGET CGAL::Eigen_support) message(STATUS "NOTICE: Eigen 3.2 (or greater) is not found.") -endif(NOT EIGEN3_FOUND) +endif() # Creating entries for all .cpp/.C files with "main" routine # ########################################################## create_single_source_cgal_program( "solver_benchmark.cpp" ) -CGAL_target_use_Eigen(solver_benchmark) +target_link_libraries(solver_benchmark PUBLIC CGAL::Eigen_support) create_single_source_cgal_program( "mcf_scale_invariance.cpp" ) -CGAL_target_use_Eigen(mcf_scale_invariance) - +target_link_libraries(mcf_scale_invariance PUBLIC CGAL::Eigen_support) diff --git a/Surface_mesh_skeletonization/examples/Surface_mesh_skeletonization/CMakeLists.txt b/Surface_mesh_skeletonization/examples/Surface_mesh_skeletonization/CMakeLists.txt index d3f29d30dc3..e5ee181c4d3 100644 --- a/Surface_mesh_skeletonization/examples/Surface_mesh_skeletonization/CMakeLists.txt +++ b/Surface_mesh_skeletonization/examples/Surface_mesh_skeletonization/CMakeLists.txt @@ -12,8 +12,9 @@ find_package(CGAL QUIET) if ( CGAL_FOUND ) find_package(Eigen3 3.2.0) #(requires 3.2.0 or greater) + include(CGAL_Eigen_support) - if(EIGEN3_FOUND) + if(TARGET CGAL::Eigen_support) create_single_source_cgal_program( "simple_mcfskel_example.cpp" ) create_single_source_cgal_program( "simple_mcfskel_sm_example.cpp" ) create_single_source_cgal_program( "simple_mcfskel_LCC_example.cpp" ) @@ -29,7 +30,7 @@ if ( CGAL_FOUND ) MCF_Skeleton_sm_example MCF_Skeleton_LCC_example segmentation_example) - CGAL_target_use_Eigen(${target}) + target_link_libraries(${target} PUBLIC CGAL::Eigen_support) endforeach() else() message(STATUS "These programs require the Eigen library (3.2 or greater), and will not be compiled.") @@ -40,4 +41,3 @@ else() message(STATUS "This program requires the CGAL library, and will not be compiled.") endif() - diff --git a/Surface_mesh_skeletonization/test/Surface_mesh_skeletonization/CMakeLists.txt b/Surface_mesh_skeletonization/test/Surface_mesh_skeletonization/CMakeLists.txt index fd313cbf499..29adc5293fe 100644 --- a/Surface_mesh_skeletonization/test/Surface_mesh_skeletonization/CMakeLists.txt +++ b/Surface_mesh_skeletonization/test/Surface_mesh_skeletonization/CMakeLists.txt @@ -12,12 +12,13 @@ find_package(CGAL QUIET) if ( CGAL_FOUND ) find_package(Eigen3 3.2.0) #(requires 3.2.0 or greater) + include(CGAL_Eigen_support) - if(EIGEN3_FOUND) + if(TARGET CGAL::Eigen_support) create_single_source_cgal_program( "MCF_Skeleton_test.cpp" ) - CGAL_target_use_Eigen(MCF_Skeleton_test) + target_link_libraries(MCF_Skeleton_test PUBLIC CGAL::Eigen_support) create_single_source_cgal_program( "skeleton_connectivity_test.cpp" ) - CGAL_target_use_Eigen(skeleton_connectivity_test) + target_link_libraries(skeleton_connectivity_test PUBLIC CGAL::Eigen_support) else() message(STATUS "These tests require the Eigen library (3.2 or greater), and will not be compiled.") endif() @@ -26,4 +27,3 @@ else() message(STATUS "This program requires the CGAL library, and will not be compiled.") endif() - diff --git a/TDS_3/test/TDS_3/CMakeLists.txt b/TDS_3/test/TDS_3/CMakeLists.txt index b21488fe951..87f0c8a318e 100644 --- a/TDS_3/test/TDS_3/CMakeLists.txt +++ b/TDS_3/test/TDS_3/CMakeLists.txt @@ -9,10 +9,11 @@ if ( CGAL_FOUND ) include_directories (BEFORE "./include") find_package( TBB QUIET ) + include(CGAL_TBB_support) create_single_source_cgal_program( "test_triangulation_tds_3.cpp" ) create_single_source_cgal_program( "test_io_tds3.cpp" ) - if(TBB_FOUND) - CGAL_target_use_TBB(test_triangulation_tds_3) + if(TARGET CGAL::TBB_support) + target_link_libraries(test_triangulation_tds_3 PUBLIC CGAL::TBB_support) endif() else() message(STATUS "This program requires the CGAL library, and will not be compiled.") diff --git a/Triangulation/applications/Triangulation/CMakeLists.txt b/Triangulation/applications/Triangulation/CMakeLists.txt index d185fab4fdc..1fc7365fd39 100644 --- a/Triangulation/applications/Triangulation/CMakeLists.txt +++ b/Triangulation/applications/Triangulation/CMakeLists.txt @@ -26,6 +26,7 @@ if ( NOT Boost_FOUND ) endif() find_package(Eigen3 3.1.0) +include(CGAL_Eigen_support) # include for local directory include_directories( BEFORE include ) @@ -36,8 +37,6 @@ include_directories( BEFORE include ) # ########################################################## create_single_source_cgal_program( "points_to_RT_to_off.cpp" ) -CGAL_target_use_Eigen(points_to_RT_to_off) +target_link_libraries(points_to_RT_to_off PUBLIC CGAL::Eigen_support) create_single_source_cgal_program( "points_to_DT_to_off.cpp" ) -CGAL_target_use_Eigen(points_to_DT_to_off) - - +target_link_libraries(points_to_DT_to_off PUBLIC CGAL::Eigen_support) diff --git a/Triangulation/benchmark/Triangulation/CMakeLists.txt b/Triangulation/benchmark/Triangulation/CMakeLists.txt index 0e03f970220..681ffd10bc0 100644 --- a/Triangulation/benchmark/Triangulation/CMakeLists.txt +++ b/Triangulation/benchmark/Triangulation/CMakeLists.txt @@ -14,12 +14,13 @@ if ( CGAL_FOUND ) include(${CGAL_USE_FILE}) find_package(Eigen3 3.1.0) - if (EIGEN3_FOUND) + include(CGAL_Eigen_support) + if (TARGET CGAL::Eigen_support) include_directories (BEFORE "include") create_single_source_cgal_program( "delaunay.cpp" ) - CGAL_target_use_Eigen(delaunay) + target_link_libraries(delaunay PUBLIC CGAL::Eigen_support) create_single_source_cgal_program( "Td_vs_T2_and_T3.cpp" ) - CGAL_target_use_Eigen(Td_vs_T2_and_T3) + target_link_libraries(Td_vs_T2_and_T3 PUBLIC CGAL::Eigen_support) else() message(STATUS "NOTICE: Some of the executables in this directory need Eigen 3.1 (or greater) and will not be compiled.") @@ -28,4 +29,3 @@ if ( CGAL_FOUND ) else() message(STATUS "This program requires the CGAL library, and will not be compiled.") endif() - diff --git a/Triangulation/examples/Triangulation/CMakeLists.txt b/Triangulation/examples/Triangulation/CMakeLists.txt index 7f8609612df..f6589b3e63a 100644 --- a/Triangulation/examples/Triangulation/CMakeLists.txt +++ b/Triangulation/examples/Triangulation/CMakeLists.txt @@ -17,7 +17,8 @@ find_package(CGAL QUIET) if ( CGAL_FOUND ) find_package(Eigen3 3.1.0) - if (EIGEN3_FOUND) + include(CGAL_Eigen_support) + if (TARGET CGAL::Eigen_support) create_single_source_cgal_program( "barycentric_subdivision.cpp" ) create_single_source_cgal_program( "delaunay_triangulation.cpp" ) create_single_source_cgal_program( "convex_hull.cpp" ) @@ -34,7 +35,7 @@ if ( CGAL_FOUND ) triangulation triangulation_data_structure_dynamic triangulation_data_structure_static) - CGAL_target_use_Eigen(${target}) + target_link_libraries(${target} PUBLIC CGAL::Eigen_support) endforeach() else() message(STATUS "NOTICE: Some of the executables in this directory need Eigen 3.1 (or greater) and will not be compiled.") @@ -45,4 +46,3 @@ else() message(STATUS "This program requires the CGAL library, and will not be compiled.") endif() - diff --git a/Triangulation/test/Triangulation/CMakeLists.txt b/Triangulation/test/Triangulation/CMakeLists.txt index 2aed902c338..8dd9796ba23 100644 --- a/Triangulation/test/Triangulation/CMakeLists.txt +++ b/Triangulation/test/Triangulation/CMakeLists.txt @@ -15,7 +15,8 @@ find_package(CGAL QUIET) if ( CGAL_FOUND ) find_package(Eigen3 3.1.0) - if (EIGEN3_FOUND) + include(CGAL_Eigen_support) + if (TARGET CGAL::Eigen_support) include_directories (BEFORE "include") create_single_source_cgal_program( "test_triangulation.cpp" ) @@ -31,7 +32,7 @@ if ( CGAL_FOUND ) test_tds test_torture test_insert_if_in_star) - CGAL_target_use_Eigen(${target}) + target_link_libraries(${target} PUBLIC CGAL::Eigen_support) endforeach() else() @@ -41,4 +42,3 @@ if ( CGAL_FOUND ) else() message(STATUS "This program requires the CGAL library, and will not be compiled.") endif() - diff --git a/Triangulation_3/benchmark/Triangulation_3/CMakeLists.txt b/Triangulation_3/benchmark/Triangulation_3/CMakeLists.txt index c6892abd08e..4d0c7c1c778 100644 --- a/Triangulation_3/benchmark/Triangulation_3/CMakeLists.txt +++ b/Triangulation_3/benchmark/Triangulation_3/CMakeLists.txt @@ -49,14 +49,12 @@ find_package(benchmark) if(TARGET benchmark::benchmark) find_package(TBB REQUIRED) - include( CGAL_target_use_TBB ) + include(CGAL_TBB_support) create_single_source_cgal_program( "DT3_benchmark_with_TBB.cpp" ) - CGAL_target_use_TBB(DT3_benchmark_with_TBB) - target_link_libraries(DT3_benchmark_with_TBB PRIVATE benchmark::benchmark) + target_link_libraries(DT3_benchmark_with_TBB PRIVATE benchmark::benchmark CGAL::TBB_support) add_executable(DT3_benchmark_with_TBB_CCC_approximate_size DT3_benchmark_with_TBB.cpp) - CGAL_target_use_TBB(DT3_benchmark_with_TBB_CCC_approximate_size) target_compile_definitions(DT3_benchmark_with_TBB_CCC_approximate_size PRIVATE CGAL_CONCURRENT_COMPACT_CONTAINER_APPROXIMATE_SIZE) - target_link_libraries(DT3_benchmark_with_TBB_CCC_approximate_size PRIVATE CGAL::CGAL benchmark::benchmark) + target_link_libraries(DT3_benchmark_with_TBB_CCC_approximate_size PRIVATE CGAL::CGAL benchmark::benchmark CGAL::TBB_support) endif() diff --git a/Triangulation_3/demo/Triangulation_3/CMakeLists.txt b/Triangulation_3/demo/Triangulation_3/CMakeLists.txt index 99856041fc3..4b659999e15 100644 --- a/Triangulation_3/demo/Triangulation_3/CMakeLists.txt +++ b/Triangulation_3/demo/Triangulation_3/CMakeLists.txt @@ -37,12 +37,14 @@ option(CGAL_ACTIVATE_CONCURRENT_TRIANGULATION_3 if( CGAL_ACTIVATE_CONCURRENT_TRIANGULATION_3 ) add_definitions( -DCGAL_CONCURRENT_TRIANGULATION_3 ) find_package( TBB REQUIRED ) + include(CGAL_TBB_support) else( CGAL_ACTIVATE_CONCURRENT_TRIANGULATION_3 ) option( LINK_WITH_TBB "Link with TBB anyway so we can use TBB timers for profiling" ON) if( LINK_WITH_TBB ) find_package( TBB ) + find_package( TBB REQUIRED ) endif( LINK_WITH_TBB ) endif() @@ -67,8 +69,8 @@ if ( CGAL_FOUND AND CGAL_Qt5_FOUND AND Qt5_FOUND ) target_link_libraries( T3_demo PRIVATE CGAL::CGAL CGAL::CGAL_Qt5) target_link_libraries( T3_demo PRIVATE Qt5::OpenGL Qt5::Xml) - if(TBB_FOUND) - CGAL_target_use_TBB(T3_demo) + if(TARGET CGAL::TBB_support) + target_link_libraries(T3_demo PUBLIC CGAL::TBB_support) endif() include(${CGAL_MODULES_DIR}/CGAL_add_test.cmake) diff --git a/Triangulation_3/examples/Triangulation_3/CMakeLists.txt b/Triangulation_3/examples/Triangulation_3/CMakeLists.txt index d6bd426e464..a44531dec74 100644 --- a/Triangulation_3/examples/Triangulation_3/CMakeLists.txt +++ b/Triangulation_3/examples/Triangulation_3/CMakeLists.txt @@ -39,16 +39,15 @@ if ( CGAL_FOUND ) endif() find_package( TBB QUIET ) + include(CGAL_TBB_support) - if( TBB_FOUND ) - include( CGAL_target_use_TBB ) - + if( TARGET CGAL::TBB_support ) create_single_source_cgal_program( "parallel_insertion_and_removal_in_regular_3.cpp" ) create_single_source_cgal_program( "parallel_insertion_in_delaunay_3.cpp" ) create_single_source_cgal_program( "sequential_parallel.cpp" ) - CGAL_target_use_TBB( parallel_insertion_and_removal_in_regular_3 ) - CGAL_target_use_TBB( parallel_insertion_in_delaunay_3 ) - CGAL_target_use_TBB( sequential_parallel ) + target_link_libraries( parallel_insertion_and_removal_in_regular_3 PUBLIC CGAL::TBB_support) + target_link_libraries( parallel_insertion_in_delaunay_3 PUBLIC CGAL::TBB_support ) + target_link_libraries( sequential_parallel PUBLIC CGAL::TBB_support) else() message(STATUS "NOTICE: a few examples require TBB and will not be compiled.") endif() @@ -58,4 +57,3 @@ else() message(STATUS "This program requires the CGAL library, and will not be compiled.") endif() - diff --git a/Triangulation_3/test/Triangulation_3/CMakeLists.txt b/Triangulation_3/test/Triangulation_3/CMakeLists.txt index a2d10b47143..4dfcc8c4bb5 100644 --- a/Triangulation_3/test/Triangulation_3/CMakeLists.txt +++ b/Triangulation_3/test/Triangulation_3/CMakeLists.txt @@ -12,6 +12,7 @@ find_package(CGAL QUIET) if ( CGAL_FOUND ) find_package( TBB QUIET ) + include(CGAL_TBB_support) include_directories (BEFORE "include") @@ -30,12 +31,12 @@ if ( CGAL_FOUND ) create_single_source_cgal_program( "test_triangulation_3.cpp" ) create_single_source_cgal_program( "test_io_triangulation_3.cpp" ) - if(TBB_FOUND) + if(TARGET CGAL::TBB_support) foreach(target test_delaunay_3 test_regular_3 test_regular_insert_range_with_info) - CGAL_target_use_TBB(${target}) + target_link_libraries(${target} PUBLIC CGAL::TBB_support) endforeach() endif() @@ -54,4 +55,3 @@ else() message(STATUS "This program requires the CGAL library, and will not be compiled.") endif() - From 3668a22d89e4d8c24e13fbab8a713e1255aee75a Mon Sep 17 00:00:00 2001 From: Simon Giraudot Date: Wed, 15 Apr 2020 12:32:28 +0200 Subject: [PATCH 260/568] Update deprecation warnings --- Installation/cmake/modules/UseEigen3.cmake | 2 +- Installation/cmake/modules/UseLASLIB.cmake | 3 +-- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/Installation/cmake/modules/UseEigen3.cmake b/Installation/cmake/modules/UseEigen3.cmake index 850bb638392..ccdb6682bd7 100644 --- a/Installation/cmake/modules/UseEigen3.cmake +++ b/Installation/cmake/modules/UseEigen3.cmake @@ -8,4 +8,4 @@ add_definitions(-DCGAL_EIGEN3_ENABLED) set (EIGEN3_SETUP TRUE) -message(DEPRECATION "This file UseEigen.cmake is deprecated, and the function `CGAL_target_use_Eigen` from CGAL_target_use_Eigen.cmake should be used instead.") +message(DEPRECATION "This file UseEigen.cmake is deprecated, and the imported target `CGAL::Eigen_support` from CGAL_Eigen_support.cmake should be used instead.") diff --git a/Installation/cmake/modules/UseLASLIB.cmake b/Installation/cmake/modules/UseLASLIB.cmake index 99f3374a24f..1af7a023ceb 100644 --- a/Installation/cmake/modules/UseLASLIB.cmake +++ b/Installation/cmake/modules/UseLASLIB.cmake @@ -3,5 +3,4 @@ add_definitions(-DCGAL_LINKED_WITH_LASLIB) -message(DEPRECATION "This file UseLASLIB.cmake is deprecated, and the function `CGAL_target_use_LASLIB` from CGAL_target_use_LASLIB.cmake should be used instead.") - +message(DEPRECATION "This file UseLASLIB.cmake is deprecated, and the imported target `CGAL::TBB_support` from CGAL_LASLIB_support.cmake should be used instead.") From 15c07ff06fd4ddcb5b0619940884dd3eb4c409f8 Mon Sep 17 00:00:00 2001 From: Simon Giraudot Date: Wed, 15 Apr 2020 13:46:42 +0200 Subject: [PATCH 261/568] Update third party doc with imported targets --- .../doc/Documentation/Third_party.txt | 46 +++++++++++-------- 1 file changed, 27 insertions(+), 19 deletions(-) diff --git a/Documentation/doc/Documentation/Third_party.txt b/Documentation/doc/Documentation/Third_party.txt index 0aa2992e0af..b4164de39ab 100644 --- a/Documentation/doc/Documentation/Third_party.txt +++ b/Documentation/doc/Documentation/Third_party.txt @@ -132,8 +132,8 @@ sparse linear solvers and singular value decompositions. A package dependency over \sc{Eigen} is marked on the Package Overview page. In order to use Eigen in \cgal programs, the -provided CMake function `CGAL_target_use_Eigen()` should be -used. +executables should be linked with the CMake imported target +`CGAL::Eigen_support` provided in `CGAL_Eigen_support.cmake`. The \sc{Eigen} web site is `http://eigen.tuxfamily.org`. @@ -142,8 +142,7 @@ The \sc{Eigen} web site is `https://github.com/STORM-IRIT/OpenGR`. @@ -152,8 +151,10 @@ The \sc{OpenGR} web site is `http \sc{libpointmatcher} is a modular library implementing the Iterative Closest Point (ICP) algorithm for aligning point clouds, released under a permissive BSD license. \cgal provides wrappers for the ICP algorithm of \sc{libpointmatcher} in the \ref PkgPointSetProcessing3Ref -packages. In order to use \sc{libpointmatcher} in \cgal programs, the provided CMake function -`CGAL_target_use_pointmatcher()` should be used. +packages. In order to use \sc{libpointmatcher} in \cgal programs, the +executables should be linked with the CMake imported target +`CGAL::pointmatcher_support` provided in +`CGAL_pointmatcher_support.cmake`. The \sc{libpointmatcher} web site is `https://github.com/ethz-asl/libpointmatcher`. @@ -220,8 +221,9 @@ It can be downloaded from `http://esbtl. programs that take advantage of multi-core processors. In \cgal, \sc{Tbb} is used by the packages that offer parallel -code. In order to use \sc{Tbb} in \cgal programs, the provided CMake -function `CGAL_target_use_TBB()` should be used. +code. In order to use \sc{Tbb} in \cgal programs, the executables +should be linked with the CMake imported target `CGAL::TBB_support` +provided in `CGAL_TBB_support.cmake`. The \sc{Tbb} web site is `https://www.threadingbuildingblocks.org`. @@ -231,9 +233,10 @@ The \sc{Tbb} web site is `http the LAS format (or the compressed LAZ format). In \cgal, \sc{LASlib} is used to provide input and output functions in -the \ref PkgPointSetProcessing3 package. In order to use \sc{LASlib} in -\cgal programs, the provided CMake function -`CGAL_target_use_LASLIB()` should be used. +the \ref PkgPointSetProcessing3 package. In order to use \sc{LASlib} +in \cgal programs, the executables should be linked with the CMake +imported target `CGAL::LASLIB_support` provided in +`CGAL_LASLIB_support.cmake`. The \sc{LASlib} web site is `https://rapidlasso.com/lastools/`. \sc{LASlib} @@ -247,8 +250,9 @@ CMake based install procedure. vision, computer graphics and machine learning. In \cgal, \sc{OpenCV} is used by the \ref PkgClassification -package. In order to use \sc{OpenCV} in \cgal programs, the provided -CMake function `CGAL_target_use_OpenCV()` should be used. +package. In order to use \sc{OpenCV} in \cgal programs, the +executables should be linked with the CMake imported target +`CGAL::OpenCV_support` provided in `CGAL_OpenCV_support.cmake`. The \sc{OpenCV} web site is `https://opencv.org/`. @@ -266,8 +270,10 @@ enable and compile the following targets: - `tensorflow_BUILD_PYTHON_BINDINGS` - `tensorflow_BUILD_SHARED_LIB`. -In order to use \sc{TensorFlow} in \cgal programs, the provided CMake -function `CGAL_target_use_TensorFlow()` should be used. +In order to use \sc{TensorFlow} in \cgal programs, the executables +should be linked with the CMake imported target +`CGAL::TensorFlow_support` provided in +`CGAL_TensorFlow_support.cmake`. The \sc{TensorFlow} web site is `https://www.tensorflow.org/`. @@ -310,8 +316,9 @@ for more information. In \cgal, \sc{GLPK} provides an optional linear integer program solver in the \ref PkgPolygonalSurfaceReconstruction package. In order to use -\sc{GLPK} in \cgal programs, the provided CMake function -`CGAL_target_use_GLPK()` should be used. +\sc{GLPK} in \cgal programs, the executables should be linked with the +CMake imported target `CGAL::GLPK_support` provided in +`CGAL_GLPK_support.cmake`. The \sc{GLPK} web site is `https://www.gnu.org/software/glpk/`. @@ -321,8 +328,9 @@ The \sc{GLPK} web site is `https:// In \cgal, \sc{SCIP} provides an optional linear integer program solver in the \ref PkgPolygonalSurfaceReconstruction package. In order to use -\sc{SCIP} in \cgal programs, the provided CMake function -`CGAL_target_use_SCIP()` should be used. +\sc{SCIP} in \cgal programs, the executables should be linked with the +CMake imported target `CGAL::SCIP_support` provided in +`CGAL_SCIP_support.cmake`. The \sc{SCIP} web site is `http://scip.zib.de/`. From 12a51af61f61545434ca471c7a2b08e2e970257c Mon Sep 17 00:00:00 2001 From: Simon Giraudot Date: Wed, 15 Apr 2020 15:02:49 +0200 Subject: [PATCH 262/568] Fixes for imported targets --- .../optimal_rotation/CMakeLists.txt | 6 +++--- Triangulation_3/demo/Triangulation_3/CMakeLists.txt | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/Surface_mesh_deformation/benchmark/Surface_mesh_deformation/optimal_rotation/CMakeLists.txt b/Surface_mesh_deformation/benchmark/Surface_mesh_deformation/optimal_rotation/CMakeLists.txt index 4d24c1d593c..bce18be7df6 100644 --- a/Surface_mesh_deformation/benchmark/Surface_mesh_deformation/optimal_rotation/CMakeLists.txt +++ b/Surface_mesh_deformation/benchmark/Surface_mesh_deformation/optimal_rotation/CMakeLists.txt @@ -10,13 +10,13 @@ if ( CGAL_FOUND ) include(${CGAL_USE_FILE}) find_package(Eigen3 3.1.0) #(requires 3.1.0 or greater) - if (EIGEN3_FOUND) + include(CGAL_Eigen_support) + if (TARGET CGAL::Eigen_support) create_single_source_cgal_program( "benchmark_for_concept_models.cpp" ) - CGAL_target_use_Eigen(benchmark_for_concept_models) + target_link_libraries(benchmark_for_concept_models PUBLIC CGAL::Eigen_support) else() message(STATUS "This program requires the Eigen library, version 3.1 or later and will not be compiled.") endif() else() message(STATUS "This program requires the CGAL library, and will not be compiled.") endif() - diff --git a/Triangulation_3/demo/Triangulation_3/CMakeLists.txt b/Triangulation_3/demo/Triangulation_3/CMakeLists.txt index 4b659999e15..0f3412b545f 100644 --- a/Triangulation_3/demo/Triangulation_3/CMakeLists.txt +++ b/Triangulation_3/demo/Triangulation_3/CMakeLists.txt @@ -44,7 +44,7 @@ else( CGAL_ACTIVATE_CONCURRENT_TRIANGULATION_3 ) ON) if( LINK_WITH_TBB ) find_package( TBB ) - find_package( TBB REQUIRED ) + include(CGAL_TBB_support) endif( LINK_WITH_TBB ) endif() From f96f5fd43ea09262942efea942dab0405fbf6a00 Mon Sep 17 00:00:00 2001 From: Jane Tournois Date: Wed, 15 Apr 2020 15:14:43 +0200 Subject: [PATCH 263/568] first version of tests execution depends on random initialization, with seed printed, to test varying data sets and be able to reproduce errors from the test suite --- .../test/Tetrahedral_remeshing/CMakeLists.txt | 27 ++++ .../test_tetrahedral_remeshing.cpp | 49 ++++++ ...tetrahedral_remeshing_of_one_subdomain.cpp | 78 +++++++++ ...st_tetrahedral_remeshing_with_features.cpp | 153 ++++++++++++++++++ 4 files changed, 307 insertions(+) create mode 100644 Tetrahedral_remeshing/test/Tetrahedral_remeshing/CMakeLists.txt create mode 100644 Tetrahedral_remeshing/test/Tetrahedral_remeshing/test_tetrahedral_remeshing.cpp create mode 100644 Tetrahedral_remeshing/test/Tetrahedral_remeshing/test_tetrahedral_remeshing_of_one_subdomain.cpp create mode 100644 Tetrahedral_remeshing/test/Tetrahedral_remeshing/test_tetrahedral_remeshing_with_features.cpp diff --git a/Tetrahedral_remeshing/test/Tetrahedral_remeshing/CMakeLists.txt b/Tetrahedral_remeshing/test/Tetrahedral_remeshing/CMakeLists.txt new file mode 100644 index 00000000000..66910c93490 --- /dev/null +++ b/Tetrahedral_remeshing/test/Tetrahedral_remeshing/CMakeLists.txt @@ -0,0 +1,27 @@ +# Created by the script cgal_create_CMakeLists +# This is the CMake script for compiling a set of CGAL applications. + +cmake_minimum_required(VERSION 3.1...3.14) + +project( Tetrahedral_remeshing_Tests ) + +# CGAL and its components +find_package( CGAL REQUIRED ) +if ( NOT CGAL_FOUND ) + message(STATUS "This project requires the CGAL library, and will not be compiled.") + return() +endif() + +# Boost and its components +find_package( Boost REQUIRED ) +if ( NOT Boost_FOUND ) + message(STATUS "This project requires the Boost library, and will not be compiled.") + return() +endif() + + +# Creating entries for all C++ files with "main" routine +# ########################################################## +create_single_source_cgal_program( "test_tetrahedral_remeshing.cpp" ) +create_single_source_cgal_program( "test_tetrahedral_remeshing_with_features.cpp") +create_single_source_cgal_program( "test_tetrahedral_remeshing_of_one_subdomain.cpp") diff --git a/Tetrahedral_remeshing/test/Tetrahedral_remeshing/test_tetrahedral_remeshing.cpp b/Tetrahedral_remeshing/test/Tetrahedral_remeshing/test_tetrahedral_remeshing.cpp new file mode 100644 index 00000000000..767b81845f5 --- /dev/null +++ b/Tetrahedral_remeshing/test/Tetrahedral_remeshing/test_tetrahedral_remeshing.cpp @@ -0,0 +1,49 @@ +//#define CGAL_TETRAHEDRAL_REMESHING_VERBOSE + +#include + +#include +#include + +#include +#include +#include + +typedef CGAL::Exact_predicates_inexact_constructions_kernel K; + +typedef CGAL::Tetrahedral_remeshing::Remeshing_triangulation_3 Remeshing_triangulation; + +template +bool generate_input_one_subdomain(const std::size_t nbv, T3& tr) +{ + CGAL::Random rng; + + typedef typename T3::Point Point; + while (tr.number_of_vertices() < nbv) + tr.insert(Point(rng.get_double(-1., 1.), rng.get_double(-1., 1.), rng.get_double(-1., 1.))); + + for (typename T3::Cell_handle c : tr.finite_cell_handles()) + c->set_subdomain_index(1); + + std::string filename("data/triangulation_one_subdomain.binary.cgal"); + std::ofstream out(filename, std::ios_base::out | std::ios_base::binary); + out << "binary CGAL c3t3\n"; + CGAL::set_binary_mode(out); + out << tr; + + return (!out.bad()); +} + +int main(int argc, char* argv[]) +{ + std::cout << "CGAL Random seed = " << CGAL::get_default_random().get_seed() << std::endl; + + Remeshing_triangulation tr; + generate_input_one_subdomain(1000, tr); + + const float target_edge_length = (argc > 1) ? atof(argv[1]) : 0.1f; + + CGAL::tetrahedral_adaptive_remeshing(tr, target_edge_length); + + return EXIT_SUCCESS; +} diff --git a/Tetrahedral_remeshing/test/Tetrahedral_remeshing/test_tetrahedral_remeshing_of_one_subdomain.cpp b/Tetrahedral_remeshing/test/Tetrahedral_remeshing/test_tetrahedral_remeshing_of_one_subdomain.cpp new file mode 100644 index 00000000000..dd0334022ec --- /dev/null +++ b/Tetrahedral_remeshing/test/Tetrahedral_remeshing/test_tetrahedral_remeshing_of_one_subdomain.cpp @@ -0,0 +1,78 @@ +#include + +#include +#include + +#include +#include + +#include + +typedef CGAL::Exact_predicates_inexact_constructions_kernel K; + +typedef CGAL::Tetrahedral_remeshing::Remeshing_triangulation_3 Remeshing_triangulation; + +bool generate_input_two_subdomains(const std::size_t nbv, Remeshing_triangulation& tr) +{ + CGAL::Random rng; + + typedef Remeshing_triangulation::Point Point; + typedef Remeshing_triangulation::Cell_handle Cell_handle; + + while (tr.number_of_vertices() < nbv) + tr.insert(Point(rng.get_double(-1., 1.), rng.get_double(-1., 1.), rng.get_double(-1., 1.))); + + const Remeshing_triangulation::Geom_traits::Plane_3 + plane(Point(0, 0, 0), Point(0, 1, 0), Point(0, 0, 1)); + + for (Cell_handle c : tr.finite_cell_handles()) + { + if (plane.has_on_positive_side( + CGAL::centroid(c->vertex(0)->point(), c->vertex(1)->point(), + c->vertex(2)->point(), c->vertex(3)->point()))) + c->set_subdomain_index(1); + else + c->set_subdomain_index(2); + } + CGAL_assertion(tr.is_valid(true)); + + std::string filename("data/triangulation_two_subdomains.binary.cgal"); + std::ofstream os(filename, std::ios_base::out | std::ios_base::binary); + os << "binary CGAL c3t3\n"; + CGAL::set_binary_mode(os); + + return !!(os << tr); +} + +struct Cells_of_subdomain +{ +private: + const int m_subdomain; + +public: + Cells_of_subdomain(const int& subdomain) + : m_subdomain(subdomain) + {} + + bool operator()(Remeshing_triangulation::Cell_handle c) const + { + return m_subdomain == c->subdomain_index(); + } +}; + +int main(int argc, char* argv[]) +{ + std::cout << "CGAL Random seed = " + << CGAL::get_default_random().get_seed() << std::endl; + + const float target_edge_length = (argc > 1) ? atof(argv[1]) : 0.1f; + + Remeshing_triangulation tr; + generate_input_two_subdomains(1000, tr); + + CGAL::tetrahedral_adaptive_remeshing(tr, target_edge_length, + CGAL::parameters::cell_selector(Cells_of_subdomain(2))); + + return EXIT_SUCCESS; +} + diff --git a/Tetrahedral_remeshing/test/Tetrahedral_remeshing/test_tetrahedral_remeshing_with_features.cpp b/Tetrahedral_remeshing/test/Tetrahedral_remeshing/test_tetrahedral_remeshing_with_features.cpp new file mode 100644 index 00000000000..a5017c5bfe2 --- /dev/null +++ b/Tetrahedral_remeshing/test/Tetrahedral_remeshing/test_tetrahedral_remeshing_with_features.cpp @@ -0,0 +1,153 @@ +#define CGAL_TETRAHEDRAL_REMESHING_VERBOSE +#define CGAL_DUMP_REMESHING_STEPS + +#include + +#include +#include + +#include +#include + +#include + +#include +#include +#include + +typedef CGAL::Exact_predicates_inexact_constructions_kernel K; + +typedef CGAL::Tetrahedral_remeshing::Remeshing_triangulation_3 Remeshing_triangulation; + +typedef Remeshing_triangulation::Point Point; +typedef Remeshing_triangulation::Vertex_handle Vertex_handle; +typedef Remeshing_triangulation::Cell_handle Cell_handle; +typedef Remeshing_triangulation::Edge Edge; + +class Constrained_edges_property_map +{ +public: + typedef bool value_type; + typedef bool reference; + typedef std::pair key_type; + typedef boost::read_write_property_map_tag category; + +private: + boost::unordered_set* m_set_ptr; + +public: + Constrained_edges_property_map() + : m_set_ptr(NULL) + {} + Constrained_edges_property_map(boost::unordered_set* set_) + : m_set_ptr(set_) + {} + +public: + friend void put(Constrained_edges_property_map& map, + const key_type& k, + const bool b) + { + CGAL_assertion(map.m_set_ptr != NULL); + CGAL_assertion(k.first < k.second); + if (b) map.m_set_ptr->insert(k); + else map.m_set_ptr->erase(k); + } + + friend value_type get(const Constrained_edges_property_map& map, + const key_type& k) + { + CGAL_assertion(map.m_set_ptr != NULL); + CGAL_assertion(k.first < k.second); + return map.m_set_ptr->count(k); + } +}; + +void add_edge(Vertex_handle v1, + Vertex_handle v2, + const Remeshing_triangulation& tr, + boost::unordered_set >& constraints) +{ + Cell_handle c; + int i, j; + if(tr.is_edge(v1, v2, c, i, j)) + constraints.insert(std::make_pair(v1, v2)); +} + +void generate_input_cube(const std::size_t& n, + Remeshing_triangulation& tr, + boost::unordered_set >& constraints) +{ + CGAL::Random rng; + + // points in a sphere + while (tr.number_of_vertices() < n) + tr.insert(Point(rng.get_double(-1., 1.), rng.get_double(-1., 1.), rng.get_double(-1., 1.))); + + // vertices of a larger cube + Vertex_handle v0 = tr.insert(Point(-2., -2., -2.)); + Vertex_handle v1 = tr.insert(Point(-2., -2., 2.)); + + Vertex_handle v2 = tr.insert(Point( 2., -2., -2.)); + Vertex_handle v3 = tr.insert(Point( 2., -2., 2.)); + + Vertex_handle v4 = tr.insert(Point(-2., 2., -2.)); + Vertex_handle v5 = tr.insert(Point(-2., 2., 2.)); + + Vertex_handle v6 = tr.insert(Point( 2., 2., -2.)); + Vertex_handle v7 = tr.insert(Point( 2., 2., 2.)); + + // writing file output + std::ofstream oFileT("data/sphere_in_cube.tr.cgal", + std::ios_base::out | std::ios_base::binary); + oFileT << tr; + oFileT.close(); + + // constrain cube edges + add_edge(v0, v1, tr, constraints); + add_edge(v1, v2, tr, constraints); + add_edge(v2, v3, tr, constraints); + add_edge(v3, v0, tr, constraints); + + add_edge(v4, v5, tr, constraints); + add_edge(v5, v6, tr, constraints); + add_edge(v6, v7, tr, constraints); + add_edge(v7, v4, tr, constraints); + + add_edge(v0, v4, tr, constraints); + add_edge(v1, v5, tr, constraints); + add_edge(v2, v6, tr, constraints); + add_edge(v3, v7, tr, constraints); + + CGAL_assertion(tr.is_valid(true)); +} + +void set_subdomain(Remeshing_triangulation& tr, const int index) +{ + for (Cell_handle c : tr.finite_cell_handles()) + c->set_subdomain_index(index); +} + +int main(int argc, char* argv[]) +{ + CGAL::Random rng; + std::cout << "CGAL Random seed = " << CGAL::get_default_random().get_seed() << std::endl; + + Remeshing_triangulation tr; + boost::unordered_set > constraints; + generate_input_cube(1000, tr, constraints); + + double target_edge_length = (argc > 1) ? atof(argv[1]) : 0.02; + int nb_iter = (argc > 2) ? atoi(argv[2]) : 1; + + set_subdomain(tr, 1); + assert(tr.is_valid()); + + CGAL::tetrahedral_adaptive_remeshing(tr, target_edge_length, + CGAL::parameters::edge_is_constrained_map( + Constrained_edges_property_map(&constraints)) + .number_of_iterations(nb_iter)); + + return EXIT_SUCCESS; +} + From a40559c7a21f1d97a015cd7cfad86a91a8d2c6bb Mon Sep 17 00:00:00 2001 From: Jane Tournois Date: Wed, 15 Apr 2020 15:15:52 +0200 Subject: [PATCH 264/568] use load/save for triangulation --- .../Tetrahedral_remeshing/tetrahedral_remeshing_io.h | 4 +--- .../tetrahedral_remeshing_of_one_subdomain.cpp | 8 +++++++- 2 files changed, 8 insertions(+), 4 deletions(-) diff --git a/Tetrahedral_remeshing/examples/Tetrahedral_remeshing/tetrahedral_remeshing_io.h b/Tetrahedral_remeshing/examples/Tetrahedral_remeshing/tetrahedral_remeshing_io.h index 212587bbc28..03ff43afc1f 100644 --- a/Tetrahedral_remeshing/examples/Tetrahedral_remeshing/tetrahedral_remeshing_io.h +++ b/Tetrahedral_remeshing/examples/Tetrahedral_remeshing/tetrahedral_remeshing_io.h @@ -38,7 +38,5 @@ void save_ascii_triangulation(const char* filename, const T3& t3) if (!t3.is_valid(true)) std::cerr << "Invalid triangulation!" << std::endl; - CGAL::Tetrahedral_remeshing::debug::dump_triangulation_cells( - t3, filename); + CGAL::Tetrahedral_remeshing::debug::dump_triangulation_cells(t3, filename); } - diff --git a/Tetrahedral_remeshing/examples/Tetrahedral_remeshing/tetrahedral_remeshing_of_one_subdomain.cpp b/Tetrahedral_remeshing/examples/Tetrahedral_remeshing/tetrahedral_remeshing_of_one_subdomain.cpp index ee6df98925f..e456f2858d9 100644 --- a/Tetrahedral_remeshing/examples/Tetrahedral_remeshing/tetrahedral_remeshing_of_one_subdomain.cpp +++ b/Tetrahedral_remeshing/examples/Tetrahedral_remeshing/tetrahedral_remeshing_of_one_subdomain.cpp @@ -35,9 +35,15 @@ public: int main(int argc, char* argv[]) { - const float target_edge_length = (argc > 1) ? atof(argv[1]) : 0.1f; + const char* filename = (argc > 1) ? argv[1] : "data/triangulation_two_subdomains.binary.cgal"; + const float target_edge_length = (argc > 2) ? atof(argv[2]) : 0.1f; + + std::ifstream input(filename, std::ios_base::in | std::ios_base::binary); + if(!input) + return EXIT_FAILURE; Remeshing_triangulation tr; + load_binary_triangulation(input, tr); CGAL::tetrahedral_adaptive_remeshing(tr, target_edge_length, CGAL::parameters::cell_selector(Cells_of_subdomain(2))); From 49d72dc30cf0c040a6a2aa3de89612d35a059844 Mon Sep 17 00:00:00 2001 From: Jane Tournois Date: Thu, 16 Apr 2020 07:39:46 +0200 Subject: [PATCH 265/568] get all inherited functions from Triangulation_3 --- .../CGAL/Tetrahedral_remeshing/Remeshing_triangulation_3.h | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/Remeshing_triangulation_3.h b/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/Remeshing_triangulation_3.h index 4252508dd1b..0afd527bc84 100644 --- a/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/Remeshing_triangulation_3.h +++ b/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/Remeshing_triangulation_3.h @@ -77,8 +77,9 @@ public: typedef CGAL::Triangulation_data_structure_3< Remeshing_Vb, Remeshing_Cb, Concurrency_tag> Tds; - typedef CGAL::Triangulation_3 Self; - typedef typename Gt::Plane_3 Plane_3; + typedef CGAL::Triangulation_3 Base; + + using Base::Base; }; namespace internal From 07b221e703570fd8c003aa3255d08aa8c1454f12 Mon Sep 17 00:00:00 2001 From: Jane Tournois Date: Thu, 16 Apr 2020 07:41:00 +0200 Subject: [PATCH 266/568] move IO header --- .../tetrahedral_remeshing_example.cpp | 2 +- ...tetrahedral_remeshing_of_one_subdomain.cpp | 6 +---- .../tetrahedral_remeshing_with_features.cpp | 2 +- .../tetrahedral_remeshing_io.h | 26 ++++++++++++------- .../test_tetrahedral_remeshing.cpp | 1 + ...tetrahedral_remeshing_of_one_subdomain.cpp | 7 ++--- ...st_tetrahedral_remeshing_with_features.cpp | 1 + 7 files changed, 26 insertions(+), 19 deletions(-) rename Tetrahedral_remeshing/{examples => include/CGAL}/Tetrahedral_remeshing/tetrahedral_remeshing_io.h (52%) diff --git a/Tetrahedral_remeshing/examples/Tetrahedral_remeshing/tetrahedral_remeshing_example.cpp b/Tetrahedral_remeshing/examples/Tetrahedral_remeshing/tetrahedral_remeshing_example.cpp index 0435c077b6e..308bd2917f4 100644 --- a/Tetrahedral_remeshing/examples/Tetrahedral_remeshing/tetrahedral_remeshing_example.cpp +++ b/Tetrahedral_remeshing/examples/Tetrahedral_remeshing/tetrahedral_remeshing_example.cpp @@ -5,7 +5,7 @@ #include #include -#include "tetrahedral_remeshing_io.h" +#include #include #include diff --git a/Tetrahedral_remeshing/examples/Tetrahedral_remeshing/tetrahedral_remeshing_of_one_subdomain.cpp b/Tetrahedral_remeshing/examples/Tetrahedral_remeshing/tetrahedral_remeshing_of_one_subdomain.cpp index e456f2858d9..d600a92d229 100644 --- a/Tetrahedral_remeshing/examples/Tetrahedral_remeshing/tetrahedral_remeshing_of_one_subdomain.cpp +++ b/Tetrahedral_remeshing/examples/Tetrahedral_remeshing/tetrahedral_remeshing_of_one_subdomain.cpp @@ -3,14 +3,10 @@ #include #include -#include - #include #include -#include - -#include "tetrahedral_remeshing_io.h" +#include typedef CGAL::Exact_predicates_inexact_constructions_kernel K; diff --git a/Tetrahedral_remeshing/examples/Tetrahedral_remeshing/tetrahedral_remeshing_with_features.cpp b/Tetrahedral_remeshing/examples/Tetrahedral_remeshing/tetrahedral_remeshing_with_features.cpp index e0793840e8b..c719094b794 100644 --- a/Tetrahedral_remeshing/examples/Tetrahedral_remeshing/tetrahedral_remeshing_with_features.cpp +++ b/Tetrahedral_remeshing/examples/Tetrahedral_remeshing/tetrahedral_remeshing_with_features.cpp @@ -15,7 +15,7 @@ #include #include -#include "tetrahedral_remeshing_io.h" +#include typedef CGAL::Exact_predicates_inexact_constructions_kernel K; diff --git a/Tetrahedral_remeshing/examples/Tetrahedral_remeshing/tetrahedral_remeshing_io.h b/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/tetrahedral_remeshing_io.h similarity index 52% rename from Tetrahedral_remeshing/examples/Tetrahedral_remeshing/tetrahedral_remeshing_io.h rename to Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/tetrahedral_remeshing_io.h index 03ff43afc1f..a339e73c84c 100644 --- a/Tetrahedral_remeshing/examples/Tetrahedral_remeshing/tetrahedral_remeshing_io.h +++ b/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/tetrahedral_remeshing_io.h @@ -1,13 +1,21 @@ +// Copyright (c) 2020 GeometryFactory (France) and Telecom Paris (France). +// All rights reserved. +// +// This file is part of CGAL (www.cgal.org) +// +// $URL$ +// $Id$ +// SPDX-License-Identifier: GPL-3.0-or-later OR LicenseRef-Commercial +// +// +// Author(s) : Jane Tournois, Noura Faraj -#include -#include #include #include - template -bool load_binary_triangulation(std::istream& is, T3& t3) +bool load_triangulation(std::istream& is, T3& t3) { std::string s; if (!(is >> s)) return false; @@ -20,6 +28,7 @@ bool load_binary_triangulation(std::istream& is, T3& t3) std::getline(is, s); if (binary) CGAL::set_binary_mode(is); + else CGAL::set_ascii_mode(is); is >> t3; return bool(is); } @@ -33,10 +42,9 @@ bool save_binary_triangulation(std::ostream& os, const T3& t3) } template -void save_ascii_triangulation(const char* filename, const T3& t3) +void save_ascii_triangulation(std::ostream& os, const T3& t3) { - if (!t3.is_valid(true)) - std::cerr << "Invalid triangulation!" << std::endl; - - CGAL::Tetrahedral_remeshing::debug::dump_triangulation_cells(t3, filename); + os << "CGAL c3t3\n"; + CGAL::set_ascii_mode(os); + return !!(os << t3); } diff --git a/Tetrahedral_remeshing/test/Tetrahedral_remeshing/test_tetrahedral_remeshing.cpp b/Tetrahedral_remeshing/test/Tetrahedral_remeshing/test_tetrahedral_remeshing.cpp index 767b81845f5..cd0b2807702 100644 --- a/Tetrahedral_remeshing/test/Tetrahedral_remeshing/test_tetrahedral_remeshing.cpp +++ b/Tetrahedral_remeshing/test/Tetrahedral_remeshing/test_tetrahedral_remeshing.cpp @@ -4,6 +4,7 @@ #include #include +#include #include #include diff --git a/Tetrahedral_remeshing/test/Tetrahedral_remeshing/test_tetrahedral_remeshing_of_one_subdomain.cpp b/Tetrahedral_remeshing/test/Tetrahedral_remeshing/test_tetrahedral_remeshing_of_one_subdomain.cpp index dd0334022ec..23fe03401ae 100644 --- a/Tetrahedral_remeshing/test/Tetrahedral_remeshing/test_tetrahedral_remeshing_of_one_subdomain.cpp +++ b/Tetrahedral_remeshing/test/Tetrahedral_remeshing/test_tetrahedral_remeshing_of_one_subdomain.cpp @@ -1,13 +1,14 @@ #include -#include -#include - #include #include +#include #include +#include +#include + typedef CGAL::Exact_predicates_inexact_constructions_kernel K; typedef CGAL::Tetrahedral_remeshing::Remeshing_triangulation_3 Remeshing_triangulation; diff --git a/Tetrahedral_remeshing/test/Tetrahedral_remeshing/test_tetrahedral_remeshing_with_features.cpp b/Tetrahedral_remeshing/test/Tetrahedral_remeshing/test_tetrahedral_remeshing_with_features.cpp index a5017c5bfe2..21d869d00e1 100644 --- a/Tetrahedral_remeshing/test/Tetrahedral_remeshing/test_tetrahedral_remeshing_with_features.cpp +++ b/Tetrahedral_remeshing/test/Tetrahedral_remeshing/test_tetrahedral_remeshing_with_features.cpp @@ -5,6 +5,7 @@ #include #include +#include #include #include From e2cd7c7a339056a534b15dcf22f57b5cbec0d728 Mon Sep 17 00:00:00 2001 From: Jane Tournois Date: Thu, 16 Apr 2020 07:41:44 +0200 Subject: [PATCH 267/568] use base class operators << and >> for Remeshing cell base --- .../Remeshing_cell_base.h | 47 ------------------- 1 file changed, 47 deletions(-) diff --git a/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/Remeshing_cell_base.h b/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/Remeshing_cell_base.h index db4324736f2..1d13d8fdf90 100644 --- a/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/Remeshing_cell_base.h +++ b/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/Remeshing_cell_base.h @@ -81,53 +81,6 @@ public: #endif }; - - -template < class Gt, class Cb > -std::istream& -operator>>(std::istream &is, Remeshing_cell_base &c) -{ - typename Remeshing_cell_base::Subdomain_index index; - if (is_ascii(is)) - is >> index; - else - read(is, index); - if (is) { - c.set_subdomain_index(index); -// for (int i = 0; i < 4; ++i) -// { -// typename Compact_mesh_cell_base_3::Surface_patch_index i2; -// if (is_ascii(is)) -// is >> iformat(i2); -// else -// { -// read(is, i2); -// } -// c.set_surface_patch_index(i, i2); -// } - } - return is; -} - -template < class Gt, class Cb > -std::ostream& -operator<<(std::ostream &os, const Remeshing_cell_base &c) -{ - if (is_ascii(os)) - os << c.subdomain_index(); - else - write(os, c.subdomain_index()); - //for (int i = 0; i < 4; ++i) - //{ - // if (is_ascii(os)) - // os << ' ' << oformat(c.surface_patch_index(i)); - // else - // write(os, c.surface_patch_index(i)); - //} - return os; -} - - }//end namespace Tetrahedral_remeshing }//end namespace CGAL From 1a4ad2623f1468774d616b6e48b0799027421289 Mon Sep 17 00:00:00 2001 From: Jane Tournois Date: Thu, 16 Apr 2020 07:42:05 +0200 Subject: [PATCH 268/568] add a test for IO --- .../test/Tetrahedral_remeshing/CMakeLists.txt | 1 + .../test_tetrahedral_remeshing_io.cpp | 59 +++++++++++++++++++ 2 files changed, 60 insertions(+) create mode 100644 Tetrahedral_remeshing/test/Tetrahedral_remeshing/test_tetrahedral_remeshing_io.cpp diff --git a/Tetrahedral_remeshing/test/Tetrahedral_remeshing/CMakeLists.txt b/Tetrahedral_remeshing/test/Tetrahedral_remeshing/CMakeLists.txt index 66910c93490..46119c8c74f 100644 --- a/Tetrahedral_remeshing/test/Tetrahedral_remeshing/CMakeLists.txt +++ b/Tetrahedral_remeshing/test/Tetrahedral_remeshing/CMakeLists.txt @@ -25,3 +25,4 @@ endif() create_single_source_cgal_program( "test_tetrahedral_remeshing.cpp" ) create_single_source_cgal_program( "test_tetrahedral_remeshing_with_features.cpp") create_single_source_cgal_program( "test_tetrahedral_remeshing_of_one_subdomain.cpp") +create_single_source_cgal_program( "test_tetrahedral_remeshing_io.cpp") diff --git a/Tetrahedral_remeshing/test/Tetrahedral_remeshing/test_tetrahedral_remeshing_io.cpp b/Tetrahedral_remeshing/test/Tetrahedral_remeshing/test_tetrahedral_remeshing_io.cpp new file mode 100644 index 00000000000..acda152bece --- /dev/null +++ b/Tetrahedral_remeshing/test/Tetrahedral_remeshing/test_tetrahedral_remeshing_io.cpp @@ -0,0 +1,59 @@ +#include + +#include +#include +#include + +#include + +#include +#include +#include +#include + +typedef CGAL::Exact_predicates_inexact_constructions_kernel K; + +typedef CGAL::Tetrahedral_remeshing::Remeshing_triangulation_3 Remeshing_triangulation; +typedef Remeshing_triangulation::Point Point; +typedef Remeshing_triangulation::Cell_handle Cell_handle; + + +int main(int argc, char* argv[]) +{ + const unsigned int nbv = (argc > 1) ? atoi(argv[1]) : 100; + + CGAL::Random rng; + std::cout << "CGAL Random seed = " << CGAL::get_default_random().get_seed() << std::endl; + + std::vector points; + while (points.size() < nbv) + { + Point p(rng.get_double(-1., 1.), rng.get_double(-1., 1.), rng.get_double(-1., 1.)); + points.push_back(p); + } + + Remeshing_triangulation tr(points.begin(), points.end()); + + for (Cell_handle c : tr.finite_cell_handles()) + c->set_subdomain_index(1); + + std::cout << "save_binary_triangulation : "; + std::cout.flush(); + std::ofstream out1("remeshing_triangulation.binary.cgal", + std::ios_base::out | std::ios_base::binary); + bool ok = save_binary_triangulation(out1, tr); + assert(ok); + std::cout << "done." << std::endl; + + + Remeshing_triangulation tr1; + std::cout << "load_triangulation : "; + std::cout.flush(); + std::ifstream in1("remeshing_triangulation.binary.cgal", + std::ios_base::in | std::ios_base::binary); + ok = load_triangulation(in1, tr1); + assert(ok); + std::cout << "done." << std::endl; + + return EXIT_SUCCESS; +} From 9dd3733efbdde348eb612f3063dbc779f9189808 Mon Sep 17 00:00:00 2001 From: Jane Tournois Date: Thu, 16 Apr 2020 08:38:41 +0200 Subject: [PATCH 269/568] complete IO test with both ascii and binary, save and load --- .../tetrahedral_remeshing_io.h | 2 +- .../test_tetrahedral_remeshing_io.cpp | 32 ++++++++++++++----- 2 files changed, 25 insertions(+), 9 deletions(-) diff --git a/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/tetrahedral_remeshing_io.h b/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/tetrahedral_remeshing_io.h index a339e73c84c..c73bd058ca1 100644 --- a/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/tetrahedral_remeshing_io.h +++ b/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/tetrahedral_remeshing_io.h @@ -42,7 +42,7 @@ bool save_binary_triangulation(std::ostream& os, const T3& t3) } template -void save_ascii_triangulation(std::ostream& os, const T3& t3) +bool save_ascii_triangulation(std::ostream& os, const T3& t3) { os << "CGAL c3t3\n"; CGAL::set_ascii_mode(os); diff --git a/Tetrahedral_remeshing/test/Tetrahedral_remeshing/test_tetrahedral_remeshing_io.cpp b/Tetrahedral_remeshing/test/Tetrahedral_remeshing/test_tetrahedral_remeshing_io.cpp index acda152bece..1ed33138fad 100644 --- a/Tetrahedral_remeshing/test/Tetrahedral_remeshing/test_tetrahedral_remeshing_io.cpp +++ b/Tetrahedral_remeshing/test/Tetrahedral_remeshing/test_tetrahedral_remeshing_io.cpp @@ -37,23 +37,39 @@ int main(int argc, char* argv[]) for (Cell_handle c : tr.finite_cell_handles()) c->set_subdomain_index(1); - std::cout << "save_binary_triangulation : "; + std::cout << "save_ascii_triangulation : "; std::cout.flush(); - std::ofstream out1("remeshing_triangulation.binary.cgal", - std::ios_base::out | std::ios_base::binary); - bool ok = save_binary_triangulation(out1, tr); + std::ofstream out1("remeshing_triangulation.ascii.cgal", + std::ios_base::out); + bool ok = save_ascii_triangulation(out1, tr); assert(ok); std::cout << "done." << std::endl; - Remeshing_triangulation tr1; - std::cout << "load_triangulation : "; + std::cout << "load_triangulation (ascii) : "; std::cout.flush(); - std::ifstream in1("remeshing_triangulation.binary.cgal", - std::ios_base::in | std::ios_base::binary); + std::ifstream in1("remeshing_triangulation.ascii.cgal", + std::ios_base::in); ok = load_triangulation(in1, tr1); assert(ok); std::cout << "done." << std::endl; + std::cout << "save_binary_triangulation : "; + std::cout.flush(); + std::ofstream out2("remeshing_triangulation.binary.cgal", + std::ios_base::out | std::ios_base::binary); + ok = save_binary_triangulation(out2, tr); + assert(ok); + std::cout << "done." << std::endl; + + Remeshing_triangulation tr2; + std::cout << "load_triangulation (binary) : "; + std::cout.flush(); + std::ifstream in2("remeshing_triangulation.binary.cgal", + std::ios_base::in | std::ios_base::binary); + ok = load_triangulation(in2, tr2); + assert(ok); + std::cout << "done." << std::endl; + return EXIT_SUCCESS; } From 395621a5fa074055148ef620400c83b977c27069 Mon Sep 17 00:00:00 2001 From: Jane Tournois Date: Thu, 16 Apr 2020 16:40:50 +0200 Subject: [PATCH 270/568] initialize time stamp with -1 in Mesh_cell_base the time stamper checks whether it is -1 or not, with -1 as default value. It was not initialized so the behaviour was not as expected. --- Mesh_3/include/CGAL/Mesh_cell_base_3.h | 3 +++ 1 file changed, 3 insertions(+) diff --git a/Mesh_3/include/CGAL/Mesh_cell_base_3.h b/Mesh_3/include/CGAL/Mesh_cell_base_3.h index 5c719d22fe6..dbb244bd66a 100644 --- a/Mesh_3/include/CGAL/Mesh_cell_base_3.h +++ b/Mesh_3/include/CGAL/Mesh_cell_base_3.h @@ -141,6 +141,7 @@ public: , next_intrusive_() , previous_intrusive_() #endif + , time_stamp_(-1) {} Mesh_cell_base_3 (Vertex_handle v0, @@ -155,6 +156,7 @@ public: , next_intrusive_() , previous_intrusive_() #endif + , time_stamp_(-1) {} Mesh_cell_base_3 (Vertex_handle v0, @@ -173,6 +175,7 @@ public: , next_intrusive_() , previous_intrusive_() #endif + , time_stamp_(-1) {} // Default copy constructor and assignment operator are ok From 4fb633a6bed348c835bc03be06c6e6c65c2df708 Mon Sep 17 00:00:00 2001 From: Mael Date: Thu, 16 Apr 2020 18:59:54 +0200 Subject: [PATCH 271/568] Add missing include --- STL_Extension/include/CGAL/iterator.h | 1 + 1 file changed, 1 insertion(+) diff --git a/STL_Extension/include/CGAL/iterator.h b/STL_Extension/include/CGAL/iterator.h index f9afdb2234e..6736bec9d72 100644 --- a/STL_Extension/include/CGAL/iterator.h +++ b/STL_Extension/include/CGAL/iterator.h @@ -24,6 +24,7 @@ #include #include #include +#include #include #include #include From cc0420a658ccd317a9ad6f4c0e776f42f012965f Mon Sep 17 00:00:00 2001 From: Mael Date: Thu, 16 Apr 2020 19:14:11 +0200 Subject: [PATCH 272/568] Fix namespace --- Point_set_processing_3/include/CGAL/cluster_point_set.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Point_set_processing_3/include/CGAL/cluster_point_set.h b/Point_set_processing_3/include/CGAL/cluster_point_set.h index 16b394c482f..7da96d2bfba 100644 --- a/Point_set_processing_3/include/CGAL/cluster_point_set.h +++ b/Point_set_processing_3/include/CGAL/cluster_point_set.h @@ -114,7 +114,7 @@ std::size_t cluster_point_set (PointRange& points, // basic geometric types typedef typename PointRange::iterator iterator; typedef typename iterator::value_type value_type; - typedef typename Point_set_processing_3::GetPointMap::type PointMap; + typedef typename CGAL::GetPointMap::type PointMap; typedef typename Point_set_processing_3::GetK::Kernel Kernel; typedef typename Point_set_processing_3::GetAdjacencies::type Adjacencies; typedef typename GetSvdTraits::type SvdTraits; From 73ea825b07d5233ed5d7a0d86254c4df456c8897 Mon Sep 17 00:00:00 2001 From: Mael Date: Thu, 16 Apr 2020 19:37:22 +0200 Subject: [PATCH 273/568] Fix unused warning --- .../examples/Point_set_processing_3/clustering_example.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Point_set_processing_3/examples/Point_set_processing_3/clustering_example.cpp b/Point_set_processing_3/examples/Point_set_processing_3/clustering_example.cpp index d6d2b406cde..08151c1cda6 100644 --- a/Point_set_processing_3/examples/Point_set_processing_3/clustering_example.cpp +++ b/Point_set_processing_3/examples/Point_set_processing_3/clustering_example.cpp @@ -16,7 +16,7 @@ using Point_set = CGAL::Point_set_3; int main (int argc, char** argv) { // Read input file - std::ifstream ifile (argv[1], std::ios_base::binary); + std::ifstream ifile ((argc > 1) ? argv[1] : "data/hippo1.ply", std::ios_base::binary); Point_set points; ifile >> points; From 4c78812c02de417a12c7c7e34cb5a1f66d3b58c5 Mon Sep 17 00:00:00 2001 From: Mael Date: Thu, 16 Apr 2020 19:39:06 +0200 Subject: [PATCH 274/568] Fix clustering example not requiring Eigen in the CMakeLists.txt --- .../examples/Point_set_processing_3/CMakeLists.txt | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/Point_set_processing_3/examples/Point_set_processing_3/CMakeLists.txt b/Point_set_processing_3/examples/Point_set_processing_3/CMakeLists.txt index a91ee87aa08..85f5f79eed8 100644 --- a/Point_set_processing_3/examples/Point_set_processing_3/CMakeLists.txt +++ b/Point_set_processing_3/examples/Point_set_processing_3/CMakeLists.txt @@ -47,7 +47,6 @@ if ( CGAL_FOUND ) create_single_source_cgal_program( "wlop_simplify_and_regularize_point_set_example.cpp" ) create_single_source_cgal_program( "edge_aware_upsample_point_set_example.cpp" ) create_single_source_cgal_program( "structuring_example.cpp" ) - create_single_source_cgal_program( "clustering_example.cpp" ) create_single_source_cgal_program( "read_ply_points_with_colors_example.cpp" ) create_single_source_cgal_program( "write_ply_points_example.cpp" ) @@ -70,7 +69,11 @@ if ( CGAL_FOUND ) create_single_source_cgal_program( "normal_estimation.cpp" ) CGAL_target_use_Eigen(normal_estimation) + create_single_source_cgal_program( "clustering_example.cpp" ) + CGAL_target_use_Eigen(clustering_example) + create_single_source_cgal_program( "edges_example.cpp" ) + CGAL_target_use_Eigen(edges_example) # Executables that require libpointmatcher find_package(libpointmatcher QUIET) @@ -102,8 +105,6 @@ if ( CGAL_FOUND ) message(STATUS "NOTICE : registration_with_opengr_pointmatcher_pipeline requires libpointmatcher and OpenGR, and will not be compiled.") endif() - CGAL_target_use_Eigen(edges_example) - create_single_source_cgal_program( "callback_example.cpp" ) CGAL_target_use_Eigen(callback_example) From bbd24f2946f68629e228a1b8b7db68178daa1aa8 Mon Sep 17 00:00:00 2001 From: Mael Date: Thu, 16 Apr 2020 19:46:09 +0200 Subject: [PATCH 275/568] Fix missing include --- STL_Extension/include/CGAL/iterator.h | 1 + 1 file changed, 1 insertion(+) diff --git a/STL_Extension/include/CGAL/iterator.h b/STL_Extension/include/CGAL/iterator.h index 6736bec9d72..14c76b745e5 100644 --- a/STL_Extension/include/CGAL/iterator.h +++ b/STL_Extension/include/CGAL/iterator.h @@ -22,6 +22,7 @@ #include #include +#include #include #include #include From 5b5595c08c2af78de8609f29a490911c6813840f Mon Sep 17 00:00:00 2001 From: Jane Tournois Date: Fri, 17 Apr 2020 06:52:30 +0200 Subject: [PATCH 276/568] add _3 to vertex base and cell base names --- .../Tetrahedral_remeshing/PackageDescription.txt | 4 ++-- ...shing_cell_base.h => Remeshing_cell_base_3.h} | 14 +++++++------- .../Remeshing_triangulation_3.h | 16 ++++++++-------- ...g_vertex_base.h => Remeshing_vertex_base_3.h} | 14 +++++++------- 4 files changed, 24 insertions(+), 24 deletions(-) rename Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/{Remeshing_cell_base.h => Remeshing_cell_base_3.h} (83%) rename Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/{Remeshing_vertex_base.h => Remeshing_vertex_base_3.h} (82%) diff --git a/Tetrahedral_remeshing/doc/Tetrahedral_remeshing/PackageDescription.txt b/Tetrahedral_remeshing/doc/Tetrahedral_remeshing/PackageDescription.txt index 8900712c8bb..11402caff34 100644 --- a/Tetrahedral_remeshing/doc/Tetrahedral_remeshing/PackageDescription.txt +++ b/Tetrahedral_remeshing/doc/Tetrahedral_remeshing/PackageDescription.txt @@ -47,8 +47,8 @@ targetting high quality meshes with respect to dihedral angles.} \cgalCRPSection{Classes} -- `CGAL::Tetrahedral_remeshing::Remeshing_vertex_base` -- `CGAL::Tetrahedral_remeshing::Remeshing_cell_base` +- `CGAL::Tetrahedral_remeshing::Remeshing_vertex_base_3` +- `CGAL::Tetrahedral_remeshing::Remeshing_cell_base_3` - `CGAL::Tetrahedral_remeshing::Remeshing_triangulation_3` \cgalCRPSection{Function Templates} diff --git a/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/Remeshing_cell_base.h b/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/Remeshing_cell_base_3.h similarity index 83% rename from Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/Remeshing_cell_base.h rename to Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/Remeshing_cell_base_3.h index 1d13d8fdf90..be080d159c6 100644 --- a/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/Remeshing_cell_base.h +++ b/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/Remeshing_cell_base_3.h @@ -10,8 +10,8 @@ // // Author(s) : Jane Tournois, Noura Faraj -#ifndef CGAL_TET_ADAPTIVE_REMESHING_CELL_BASE_H -#define CGAL_TET_ADAPTIVE_REMESHING_CELL_BASE_H +#ifndef CGAL_TET_ADAPTIVE_REMESHING_CELL_BASE_3_H +#define CGAL_TET_ADAPTIVE_REMESHING_CELL_BASE_3_H #include @@ -34,14 +34,14 @@ struct Fake_MD_C /*! \ingroup PkgTetrahedralRemeshingClasses -The class `Remeshing_cell_base` is a model of the concept `MeshCellBase_3`. +The class `Remeshing_cell_base_3` is a model of the concept `MeshCellBase_3`. It is designed to serve as cell base class for the 3D triangulation used in the tetrahedral remeshing process. \tparam Gt is the geometric traits class. It has to be a model of the concept `RemeshingTriangulationTraits_3`. -\tparam Cb is a cell base class from which `Remeshing_cell_base` derives. +\tparam Cb is a cell base class from which `Remeshing_cell_base_3` derives. It must be a model of the `TriangulationCellBase_3` concept. It has the default value `Triangulation_cell_base_3`. @@ -50,7 +50,7 @@ It has the default value `Triangulation_cell_base_3`. */ template > -class Remeshing_cell_base +class Remeshing_cell_base_3 #ifndef DOXYGEN_RUNNING : public CGAL::Mesh_cell_base_3 #endif @@ -65,7 +65,7 @@ public: struct Rebind_TDS { typedef typename Cb::template Rebind_TDS::Other Cb2; - typedef Remeshing_cell_base Other; + typedef Remeshing_cell_base_3 Other; }; using Base::Base; @@ -84,4 +84,4 @@ public: }//end namespace Tetrahedral_remeshing }//end namespace CGAL -#endif //CGAL_TET_ADAPTIVE_REMESHING_CELL_BASE_H +#endif //CGAL_TET_ADAPTIVE_REMESHING_CELL_BASE_3_H diff --git a/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/Remeshing_triangulation_3.h b/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/Remeshing_triangulation_3.h index 0afd527bc84..45b210a2352 100644 --- a/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/Remeshing_triangulation_3.h +++ b/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/Remeshing_triangulation_3.h @@ -18,8 +18,8 @@ #include #include -#include -#include +#include +#include #include #include @@ -47,11 +47,11 @@ It has to be a model of the concept `RemeshingTriangulationTraits_3`. triangulation data structure. Possible values are `Sequential_tag` (the default) and `Parallel_tag`. -\tparam Cb is a cell base class from which `Remeshing_cell_base` derives. +\tparam Cb is a cell base class from which `Remeshing_cell_base_3` derives. It must be a model of the `TriangulationCellBase_3` concept. It has the default value `Triangulation_cell_base_3`. -\tparam Vb is a vertex base class from which `Remeshing_vertex_base` derives. +\tparam Vb is a vertex base class from which `Remeshing_vertex_base_3` derives. It must be a model of the `TriangulationVertexBase_3` concept. It has the default value `Triangulation_vertex_base_3`. @@ -66,14 +66,14 @@ template, - Remeshing_cell_base + Remeshing_vertex_base_3, + Remeshing_cell_base_3 > > { public: - typedef Remeshing_vertex_base Remeshing_Vb; - typedef Remeshing_cell_base Remeshing_Cb; + typedef Remeshing_vertex_base_3 Remeshing_Vb; + typedef Remeshing_cell_base_3 Remeshing_Cb; typedef CGAL::Triangulation_data_structure_3< Remeshing_Vb, Remeshing_Cb, Concurrency_tag> Tds; diff --git a/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/Remeshing_vertex_base.h b/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/Remeshing_vertex_base_3.h similarity index 82% rename from Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/Remeshing_vertex_base.h rename to Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/Remeshing_vertex_base_3.h index f03cbcc7ffc..148ca815d39 100644 --- a/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/Remeshing_vertex_base.h +++ b/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/Remeshing_vertex_base_3.h @@ -10,8 +10,8 @@ // // Author(s) : Jane Tournois, Noura Faraj -#ifndef CGAL_TET_ADAPTIVE_REMESHING_VERTEX_BASE_H -#define CGAL_TET_ADAPTIVE_REMESHING_VERTEX_BASE_H +#ifndef CGAL_TET_ADAPTIVE_REMESHING_VERTEX_BASE_3_H +#define CGAL_TET_ADAPTIVE_REMESHING_VERTEX_BASE_3_H #include @@ -36,14 +36,14 @@ struct Fake_MD_V /*! \ingroup PkgTetrahedralRemeshingClasses -The class `Remeshing_vertex_base` is a model of the concept `MeshVertexBase_3`. +The class `Remeshing_vertex_base_3` is a model of the concept `MeshVertexBase_3`. It is designed to serve as vertex base class for the 3D triangulation used in the tetrahedral remeshing process. \tparam Gt is the geometric traits class. It has to be a model of the concept `RemeshingTriangulationTraits_3`. -\tparam Vb is a vertex base class from which `Remeshing_vertex_base` derives. +\tparam Vb is a vertex base class from which `Remeshing_vertex_base_3` derives. It must be a model of the `TriangulationVertexBase_3` concept. It has the default value `Triangulation_vertex_base_3`. @@ -53,7 +53,7 @@ It has the default value `Triangulation_vertex_base_3`. template > -class Remeshing_vertex_base +class Remeshing_vertex_base_3 #ifndef DOXYGEN_RUNNING : public CGAL::Mesh_vertex_base_3 #endif @@ -65,7 +65,7 @@ public: template < class TDS3 > struct Rebind_TDS { typedef typename Vb::template Rebind_TDS::Other Vb3; - typedef Remeshing_vertex_base Other; + typedef Remeshing_vertex_base_3 Other; }; }; @@ -74,4 +74,4 @@ public: }//end namespace CGAL -#endif //CGAL_TET_ADAPTIVE_REMESHING_VERTEX_BASE_H +#endif //CGAL_TET_ADAPTIVE_REMESHING_VERTEX_BASE_3_H From 7c170f4f69ddb0593122c12d0820eec12340bb34 Mon Sep 17 00:00:00 2001 From: Jane Tournois Date: Fri, 17 Apr 2020 08:34:49 +0200 Subject: [PATCH 277/568] doc : user manual and figs --- Documentation/doc/Documentation/packages.txt | 1 + .../doc/Tetrahedral_remeshing/PackageDescription.txt | 4 +--- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/Documentation/doc/Documentation/packages.txt b/Documentation/doc/Documentation/packages.txt index f33f7dde95b..750ee187836 100644 --- a/Documentation/doc/Documentation/packages.txt +++ b/Documentation/doc/Documentation/packages.txt @@ -90,6 +90,7 @@ \package_listing{Surface_mesher} \package_listing{Skin_surface_3} \package_listing{Mesh_3} +\package_listing{Tetrahedral_remeshing} \package_listing{Periodic_3_mesh_3} \cgalPackageSection{PartReconstruction,Shape Reconstruction} diff --git a/Tetrahedral_remeshing/doc/Tetrahedral_remeshing/PackageDescription.txt b/Tetrahedral_remeshing/doc/Tetrahedral_remeshing/PackageDescription.txt index 11402caff34..483b62af873 100644 --- a/Tetrahedral_remeshing/doc/Tetrahedral_remeshing/PackageDescription.txt +++ b/Tetrahedral_remeshing/doc/Tetrahedral_remeshing/PackageDescription.txt @@ -15,11 +15,9 @@ /*! \addtogroup PkgTetrahedralRemeshingRef -\todo check generated documentation -\todo add pkg-small.png \cgalPkgDescriptionBegin{Tetrahedral Remeshing,PkgTetrahedralRemeshing} -\todo cgalPkgPicture{pkg-small.png} +\cgalPkgPicture{bimba_back_small.png} \cgalPkgSummaryBegin \cgalPkgAuthors{Jane Tournois, Noura Faraj} From eeb239bbb2ec428351f57f44e52c5ecddcec3b4e Mon Sep 17 00:00:00 2001 From: Jane Tournois Date: Fri, 17 Apr 2020 08:35:09 +0200 Subject: [PATCH 278/568] resize image From 07f6879513eb3800e766a4f432299208d8ea83a5 Mon Sep 17 00:00:00 2001 From: Jane Tournois Date: Fri, 17 Apr 2020 09:06:34 +0200 Subject: [PATCH 279/568] uniformize IO and add namespace --- .../tetrahedral_remeshing_example.cpp | 6 ++---- .../tetrahedral_remeshing_of_one_subdomain.cpp | 6 +++--- .../tetrahedral_remeshing_with_features.cpp | 11 ++++++----- .../Tetrahedral_remeshing/tetrahedral_remeshing_io.h | 4 ++++ .../test_tetrahedral_remeshing.cpp | 10 ++++++++-- .../test_tetrahedral_remeshing_io.cpp | 9 +++++---- 6 files changed, 28 insertions(+), 18 deletions(-) diff --git a/Tetrahedral_remeshing/examples/Tetrahedral_remeshing/tetrahedral_remeshing_example.cpp b/Tetrahedral_remeshing/examples/Tetrahedral_remeshing/tetrahedral_remeshing_example.cpp index 308bd2917f4..a3ef1c79a79 100644 --- a/Tetrahedral_remeshing/examples/Tetrahedral_remeshing/tetrahedral_remeshing_example.cpp +++ b/Tetrahedral_remeshing/examples/Tetrahedral_remeshing/tetrahedral_remeshing_example.cpp @@ -27,19 +27,17 @@ int main(int argc, char* argv[]) if (!input) return EXIT_FAILURE; - if( !load_binary_triangulation(input, t3)) + if( !CGAL::load_triangulation(input, t3)) return EXIT_FAILURE; CGAL::tetrahedral_adaptive_remeshing(t3, target_edge_length); // save output const std::string file_in(filename); - - // binary std::string file_out = file_in.substr(0, file_in.find_first_of(".")); file_out.append("_out.binary.cgal"); std::ofstream out(file_out.c_str(), std::ios_base::out | std::ios_base::binary); - save_binary_triangulation(out, t3); + CGAL::save_binary_triangulation(out, t3); return EXIT_SUCCESS; } diff --git a/Tetrahedral_remeshing/examples/Tetrahedral_remeshing/tetrahedral_remeshing_of_one_subdomain.cpp b/Tetrahedral_remeshing/examples/Tetrahedral_remeshing/tetrahedral_remeshing_of_one_subdomain.cpp index d600a92d229..2802add0cd6 100644 --- a/Tetrahedral_remeshing/examples/Tetrahedral_remeshing/tetrahedral_remeshing_of_one_subdomain.cpp +++ b/Tetrahedral_remeshing/examples/Tetrahedral_remeshing/tetrahedral_remeshing_of_one_subdomain.cpp @@ -39,13 +39,13 @@ int main(int argc, char* argv[]) return EXIT_FAILURE; Remeshing_triangulation tr; - load_binary_triangulation(input, tr); + CGAL::load_triangulation(input, tr); CGAL::tetrahedral_adaptive_remeshing(tr, target_edge_length, CGAL::parameters::cell_selector(Cells_of_subdomain(2))); - std::ofstream ofile("output.binary.cgal", std::ios::out); - save_binary_triangulation(ofile, tr); + std::ofstream ofile("output.binary.cgal", std::ios_base::out | std::ios_base::binary); + CGAL::save_binary_triangulation(ofile, tr); return EXIT_SUCCESS; } diff --git a/Tetrahedral_remeshing/examples/Tetrahedral_remeshing/tetrahedral_remeshing_with_features.cpp b/Tetrahedral_remeshing/examples/Tetrahedral_remeshing/tetrahedral_remeshing_with_features.cpp index c719094b794..b990653f90a 100644 --- a/Tetrahedral_remeshing/examples/Tetrahedral_remeshing/tetrahedral_remeshing_with_features.cpp +++ b/Tetrahedral_remeshing/examples/Tetrahedral_remeshing/tetrahedral_remeshing_with_features.cpp @@ -131,11 +131,11 @@ void set_subdomain(Remeshing_triangulation& tr, const int index) int main(int argc, char* argv[]) { - const char* filename = (argc > 1) ? argv[1] : "data/sphere_in_cube.tr.cgal"; + const char* filename = (argc > 1) ? argv[1] : "data/sphere_in_cube.tr.cgal"; double target_edge_length = (argc > 2) ? atof(argv[2]) : 0.02; int nb_iter = (argc > 3) ? atoi(argv[3]) : 1; - std::ifstream input(filename, std::ios::in); + std::ifstream input(filename, std::ios_base::in | std::ios_base::binary); if (!input) { std::cerr << "File " << filename << " could not be found" << std::endl; @@ -143,8 +143,8 @@ int main(int argc, char* argv[]) } Remeshing_triangulation t3; - input >> t3; - set_subdomain(t3, 1); + CGAL::load_triangulation(input, t3); + boost::unordered_set > constraints; make_constraints_from_cube_edges(t3, constraints); @@ -155,7 +155,8 @@ int main(int argc, char* argv[]) Constrained_edges_property_map(&constraints)) .number_of_iterations(nb_iter)); - save_ascii_triangulation("tet_remeshing_with_features_after.mesh", t3); + std::ofstream out("tet_remeshing_with_features_after.mesh", std::ios_base::out); + CGAL::save_ascii_triangulation(out, t3); return EXIT_SUCCESS; } diff --git a/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/tetrahedral_remeshing_io.h b/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/tetrahedral_remeshing_io.h index c73bd058ca1..f76e24c2dfa 100644 --- a/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/tetrahedral_remeshing_io.h +++ b/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/tetrahedral_remeshing_io.h @@ -14,6 +14,8 @@ #include #include +namespace CGAL +{ template bool load_triangulation(std::istream& is, T3& t3) { @@ -48,3 +50,5 @@ bool save_ascii_triangulation(std::ostream& os, const T3& t3) CGAL::set_ascii_mode(os); return !!(os << t3); } + +} \ No newline at end of file diff --git a/Tetrahedral_remeshing/test/Tetrahedral_remeshing/test_tetrahedral_remeshing.cpp b/Tetrahedral_remeshing/test/Tetrahedral_remeshing/test_tetrahedral_remeshing.cpp index cd0b2807702..36f5ffb8df7 100644 --- a/Tetrahedral_remeshing/test/Tetrahedral_remeshing/test_tetrahedral_remeshing.cpp +++ b/Tetrahedral_remeshing/test/Tetrahedral_remeshing/test_tetrahedral_remeshing.cpp @@ -9,6 +9,7 @@ #include #include #include +#include typedef CGAL::Exact_predicates_inexact_constructions_kernel K; @@ -20,8 +21,13 @@ bool generate_input_one_subdomain(const std::size_t nbv, T3& tr) CGAL::Random rng; typedef typename T3::Point Point; - while (tr.number_of_vertices() < nbv) - tr.insert(Point(rng.get_double(-1., 1.), rng.get_double(-1., 1.), rng.get_double(-1., 1.))); + std::vector pts; + while (pts.size() < nbv) + { + const Point p(rng.get_double(-1., 1.), rng.get_double(-1., 1.), rng.get_double(-1., 1.)); + pts.push_back(p); + } + tr.insert(pts.begin(), pts.end()); for (typename T3::Cell_handle c : tr.finite_cell_handles()) c->set_subdomain_index(1); diff --git a/Tetrahedral_remeshing/test/Tetrahedral_remeshing/test_tetrahedral_remeshing_io.cpp b/Tetrahedral_remeshing/test/Tetrahedral_remeshing/test_tetrahedral_remeshing_io.cpp index 1ed33138fad..9c741fc2b74 100644 --- a/Tetrahedral_remeshing/test/Tetrahedral_remeshing/test_tetrahedral_remeshing_io.cpp +++ b/Tetrahedral_remeshing/test/Tetrahedral_remeshing/test_tetrahedral_remeshing_io.cpp @@ -32,6 +32,7 @@ int main(int argc, char* argv[]) points.push_back(p); } + Remeshing_triangulation tr(points.begin(), points.end()); for (Cell_handle c : tr.finite_cell_handles()) @@ -41,7 +42,7 @@ int main(int argc, char* argv[]) std::cout.flush(); std::ofstream out1("remeshing_triangulation.ascii.cgal", std::ios_base::out); - bool ok = save_ascii_triangulation(out1, tr); + bool ok = CGAL::save_ascii_triangulation(out1, tr); assert(ok); std::cout << "done." << std::endl; @@ -50,7 +51,7 @@ int main(int argc, char* argv[]) std::cout.flush(); std::ifstream in1("remeshing_triangulation.ascii.cgal", std::ios_base::in); - ok = load_triangulation(in1, tr1); + ok = CGAL::load_triangulation(in1, tr1); assert(ok); std::cout << "done." << std::endl; @@ -58,7 +59,7 @@ int main(int argc, char* argv[]) std::cout.flush(); std::ofstream out2("remeshing_triangulation.binary.cgal", std::ios_base::out | std::ios_base::binary); - ok = save_binary_triangulation(out2, tr); + ok = CGAL::save_binary_triangulation(out2, tr); assert(ok); std::cout << "done." << std::endl; @@ -67,7 +68,7 @@ int main(int argc, char* argv[]) std::cout.flush(); std::ifstream in2("remeshing_triangulation.binary.cgal", std::ios_base::in | std::ios_base::binary); - ok = load_triangulation(in2, tr2); + ok = CGAL::load_triangulation(in2, tr2); assert(ok); std::cout << "done." << std::endl; From 68277d58ac74a2d77c1384d606d5f5d034341e88 Mon Sep 17 00:00:00 2001 From: Jane Tournois Date: Fri, 17 Apr 2020 09:13:07 +0200 Subject: [PATCH 280/568] doc --- .../doc/Tetrahedral_remeshing/Tetrahedral_remeshing.txt | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/Tetrahedral_remeshing/doc/Tetrahedral_remeshing/Tetrahedral_remeshing.txt b/Tetrahedral_remeshing/doc/Tetrahedral_remeshing/Tetrahedral_remeshing.txt index f601166d063..798dd69baab 100644 --- a/Tetrahedral_remeshing/doc/Tetrahedral_remeshing/Tetrahedral_remeshing.txt +++ b/Tetrahedral_remeshing/doc/Tetrahedral_remeshing/Tetrahedral_remeshing.txt @@ -4,8 +4,13 @@ namespace CGAL { \mainpage User Manual \anchor Chapter_Tetrahedral_Remeshing \anchor userchaptertetrahedralremeshing -\authors Jane Tournois, Noura Faraj + \cgalAutoToc +\authors Jane Tournois, Noura Faraj + +\image html bimba_back.png +\image latex bimba_back.png +
\section secTetRemeshing Multi-Material Tetrahedral Remeshing @@ -41,7 +46,7 @@ dihedral angles are the interval [12,7; 157.7]. \cgalFigureEnd Experimental evidence show that a higher number of remeshing iterations -lead to a mesh with a better fitted sizing criterion, and higher quality dihedral angles. +leads to a mesh with a better fitted sizing criterion, and higher quality dihedral angles. \section secTetRemeshingAPI API From 0e025c588a367b0ec886b0c636f10c7192e22c16 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mael=20Rouxel-Labb=C3=A9?= Date: Fri, 17 Apr 2020 09:22:45 +0200 Subject: [PATCH 281/568] Fix unused typedef warning --- Point_set_processing_3/include/CGAL/cluster_point_set.h | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/Point_set_processing_3/include/CGAL/cluster_point_set.h b/Point_set_processing_3/include/CGAL/cluster_point_set.h index 7da96d2bfba..cf38b4b5fa7 100644 --- a/Point_set_processing_3/include/CGAL/cluster_point_set.h +++ b/Point_set_processing_3/include/CGAL/cluster_point_set.h @@ -117,10 +117,9 @@ std::size_t cluster_point_set (PointRange& points, typedef typename CGAL::GetPointMap::type PointMap; typedef typename Point_set_processing_3::GetK::Kernel Kernel; typedef typename Point_set_processing_3::GetAdjacencies::type Adjacencies; - typedef typename GetSvdTraits::type SvdTraits; - CGAL_static_assertion_msg(!(boost::is_same::NoTraits>::value), + CGAL_static_assertion_msg(!(boost::is_same::type, + typename GetSvdTraits::NoTraits>::value), "Error: no SVD traits"); PointMap point_map = choose_parameter(get_parameter(np, internal_np::point_map), PointMap()); From d6cf97278f5e2811bfe9212564101f1171ae7b16 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mael=20Rouxel-Labb=C3=A9?= Date: Fri, 17 Apr 2020 09:22:57 +0200 Subject: [PATCH 282/568] Fix trailing whitespace --- .../clustering_example.cpp | 2 +- .../internal/bbox_diagonal.h | 6 ++-- .../Point_set/Point_set_clustering_plugin.cpp | 32 +++++++++---------- 3 files changed, 20 insertions(+), 20 deletions(-) diff --git a/Point_set_processing_3/examples/Point_set_processing_3/clustering_example.cpp b/Point_set_processing_3/examples/Point_set_processing_3/clustering_example.cpp index 08151c1cda6..934609dd152 100644 --- a/Point_set_processing_3/examples/Point_set_processing_3/clustering_example.cpp +++ b/Point_set_processing_3/examples/Point_set_processing_3/clustering_example.cpp @@ -57,6 +57,6 @@ int main (int argc, char** argv) std::ofstream ofile ("out.ply", std::ios_base::binary); CGAL::set_binary_mode (ofile); ofile << points; - + return EXIT_SUCCESS; } diff --git a/Point_set_processing_3/include/CGAL/Point_set_processing_3/internal/bbox_diagonal.h b/Point_set_processing_3/include/CGAL/Point_set_processing_3/internal/bbox_diagonal.h index 5f02c1c91fc..84976b8f23c 100644 --- a/Point_set_processing_3/include/CGAL/Point_set_processing_3/internal/bbox_diagonal.h +++ b/Point_set_processing_3/include/CGAL/Point_set_processing_3/internal/bbox_diagonal.h @@ -26,7 +26,7 @@ double bbox_diagonal (const PointRange& points, PointMap point_map, const typena { CGAL::Bbox_2 bbox = CGAL::bbox_2 (CGAL::make_transform_iterator_from_property_map (points.begin(), point_map), CGAL::make_transform_iterator_from_property_map (points.end(), point_map)); - + return CGAL::approximate_sqrt ((bbox.xmax() - bbox.xmin()) * (bbox.xmax() - bbox.xmin()) + (bbox.ymax() - bbox.ymin()) * (bbox.ymax() - bbox.ymin())); @@ -37,10 +37,10 @@ double bbox_diagonal (const PointRange& points, PointMap point_map, const typena { CGAL::Bbox_3 bbox = CGAL::bbox_3 (CGAL::make_transform_iterator_from_property_map (points.begin(), point_map), CGAL::make_transform_iterator_from_property_map (points.end(), point_map)); - + return CGAL::approximate_sqrt ((bbox.xmax() - bbox.xmin()) * (bbox.xmax() - bbox.xmin()) - + (bbox.ymax() - bbox.ymin()) * (bbox.ymax() - bbox.ymin()) + + (bbox.ymax() - bbox.ymin()) * (bbox.ymax() - bbox.ymin()) + (bbox.zmax() - bbox.zmin()) * (bbox.zmax() - bbox.zmin())); } diff --git a/Polyhedron/demo/Polyhedron/Plugins/Point_set/Point_set_clustering_plugin.cpp b/Polyhedron/demo/Polyhedron/Plugins/Point_set/Point_set_clustering_plugin.cpp index b4b11d6b1bd..9cfd1771a93 100644 --- a/Polyhedron/demo/Polyhedron/Plugins/Point_set/Point_set_clustering_plugin.cpp +++ b/Polyhedron/demo/Polyhedron/Plugins/Point_set/Point_set_clustering_plugin.cpp @@ -29,9 +29,9 @@ struct Clustering_functor Point_set* points; Point_set::Property_map cluster_map; const double neighbor_radius; - boost::shared_ptr result; + boost::shared_ptr result; - Clustering_functor (Point_set* points, + Clustering_functor (Point_set* points, const double neighbor_radius, Point_set::Property_map cluster_map) : points (points), cluster_map (cluster_map), @@ -81,7 +81,7 @@ public: public Q_SLOTS: void on_actionCluster_triggered(); -}; // end +}; // end void Polyhedron_demo_point_set_clustering_plugin::on_actionCluster_triggered() { @@ -107,16 +107,16 @@ void Polyhedron_demo_point_set_clustering_plugin::on_actionCluster_triggered() QCheckBox* add_property = dialog.add ("Add a \"cluster\" property to the input item"); add_property->setChecked (true); - + QCheckBox* gen_color = dialog.add ("Generate one colored point set"); gen_color->setChecked (true); - + QCheckBox* gen_sub = dialog.add ("Generate N point subsets"); gen_sub->setChecked (false); - + if (!dialog.exec()) return; - + QApplication::setOverrideCursor(Qt::BusyCursor); QApplication::processEvents(); CGAL::Real_timer task_timer; task_timer.start(); @@ -135,11 +135,11 @@ void Polyhedron_demo_point_set_clustering_plugin::on_actionCluster_triggered() neighbor_radius->setRange (-1, 10000000); neighbor_radius->setValue(-1); } - + // Computes average spacing Clustering_functor functor (points, neighbor_radius->value(), cluster_map); run_with_qprogressdialog (functor, "Clustering...", mw); - + std::size_t nb_clusters = *functor.result; Scene_group_item* group; @@ -177,17 +177,17 @@ void Polyhedron_demo_point_set_clustering_plugin::on_actionCluster_triggered() { Scene_points_with_normal_item* colored; Point_set::Property_map red, green, blue; - + colored = new Scene_points_with_normal_item; colored->setName (QString("%1 (clustering)").arg(item->name())); - + red = colored->point_set()->add_property_map("red", 0).first; green = colored->point_set()->add_property_map("green", 0).first; blue = colored->point_set()->add_property_map("blue", 0).first; colored->point_set()->check_colors(); - + colored->point_set()->reserve (points->size()); - + for (Point_set::Index idx : *points) { Point_set::Index iidx = *(colored->point_set()->insert (points->point(idx))); @@ -205,7 +205,7 @@ void Polyhedron_demo_point_set_clustering_plugin::on_actionCluster_triggered() } scene->addItem(colored); } - + if (gen_sub->isChecked()) { for (Scene_points_with_normal_item* new_item : new_items) @@ -219,10 +219,10 @@ void Polyhedron_demo_point_set_clustering_plugin::on_actionCluster_triggered() delete new_item; } } - + if (!add_property->isChecked()) points->remove_property_map (cluster_map); - + std::size_t memory = CGAL::Memory_sizer().virtual_size(); std::cerr << "Number of clusters = " << nb_clusters << " (" << task_timer.time() << " seconds, " From 9a886d8f279727eed92e37f0099a4d6df13d4804 Mon Sep 17 00:00:00 2001 From: Jane Tournois Date: Fri, 17 Apr 2020 09:32:36 +0200 Subject: [PATCH 283/568] rename tetrahedral_adaptive_remeshing() to tetrahedral_isotropic_remeshing() because it is not adaptive yet the adaptive version will come later, with a named parameter --- .../Tetrahedral_remeshing_plugin.cpp | 4 +-- .../PackageDescription.txt | 2 +- .../Tetrahedral_remeshing.txt | 5 ++-- .../tetrahedral_remeshing_example.cpp | 2 +- ...tetrahedral_remeshing_of_one_subdomain.cpp | 2 +- .../tetrahedral_remeshing_with_features.cpp | 2 +- .../include/CGAL/tetrahedral_remeshing.h | 28 +++++++++---------- .../test_tetrahedral_remeshing.cpp | 2 +- ...tetrahedral_remeshing_of_one_subdomain.cpp | 2 +- ...st_tetrahedral_remeshing_with_features.cpp | 2 +- 10 files changed, 26 insertions(+), 25 deletions(-) diff --git a/Polyhedron/demo/Polyhedron/Plugins/Tetrahedral_remeshing/Tetrahedral_remeshing_plugin.cpp b/Polyhedron/demo/Polyhedron/Plugins/Tetrahedral_remeshing/Tetrahedral_remeshing_plugin.cpp index d272fe1c232..355308f9da8 100644 --- a/Polyhedron/demo/Polyhedron/Plugins/Tetrahedral_remeshing/Tetrahedral_remeshing_plugin.cpp +++ b/Polyhedron/demo/Polyhedron/Plugins/Tetrahedral_remeshing/Tetrahedral_remeshing_plugin.cpp @@ -1,5 +1,5 @@ #define CGAL_TETRAHEDRAL_REMESHING_VERBOSE -#define CGAL_DUMP_REMESHING_STEPS +//#define CGAL_DUMP_REMESHING_STEPS //#define CGAL_TETRAHEDRAL_REMESHING_DEBUG //#define CGAL_TETRAHEDRAL_REMESHING_VERBOSE_PROGRESS //#define CGAL_TETRAHEDRAL_REMESHING_PROFILE @@ -106,7 +106,7 @@ public Q_SLOTS: QTime time; time.start(); - CGAL::tetrahedral_adaptive_remeshing( + CGAL::tetrahedral_isotropic_remeshing( c3t3_item->c3t3(), target_length, CGAL::parameters::remesh_boundaries(!protect) diff --git a/Tetrahedral_remeshing/doc/Tetrahedral_remeshing/PackageDescription.txt b/Tetrahedral_remeshing/doc/Tetrahedral_remeshing/PackageDescription.txt index 483b62af873..1179443eb90 100644 --- a/Tetrahedral_remeshing/doc/Tetrahedral_remeshing/PackageDescription.txt +++ b/Tetrahedral_remeshing/doc/Tetrahedral_remeshing/PackageDescription.txt @@ -51,6 +51,6 @@ targetting high quality meshes with respect to dihedral angles.} \cgalCRPSection{Function Templates} -- `CGAL::tetrahedral_adaptive_remeshing()` +- `CGAL::tetrahedral_isotropic_remeshing()` */ diff --git a/Tetrahedral_remeshing/doc/Tetrahedral_remeshing/Tetrahedral_remeshing.txt b/Tetrahedral_remeshing/doc/Tetrahedral_remeshing/Tetrahedral_remeshing.txt index 798dd69baab..7af1ee5f2d5 100644 --- a/Tetrahedral_remeshing/doc/Tetrahedral_remeshing/Tetrahedral_remeshing.txt +++ b/Tetrahedral_remeshing/doc/Tetrahedral_remeshing/Tetrahedral_remeshing.txt @@ -12,7 +12,7 @@ namespace CGAL { \image latex bimba_back.png
-\section secTetRemeshing Multi-Material Tetrahedral Remeshing +\section secTetRemeshing Multi-Material Isotropic Tetrahedral Remeshing This package implements an algorithm for quality tetrahedral remeshing, introduced by N.Faraj et al in \cgalCite{faraj2016mvr}. @@ -50,7 +50,8 @@ leads to a mesh with a better fitted sizing criterion, and higher quality dihedr \section secTetRemeshingAPI API -The tetrahedral remeshing algorithm is implemented as a single free function that +The tetrahedral remeshing algorithm is implemented as a single free function +`CGAL::tetrahedral_isotropic_remeshing()` that takes only two parameters : the input triangulation, and the desired edge length, which drives the remeshing process. diff --git a/Tetrahedral_remeshing/examples/Tetrahedral_remeshing/tetrahedral_remeshing_example.cpp b/Tetrahedral_remeshing/examples/Tetrahedral_remeshing/tetrahedral_remeshing_example.cpp index a3ef1c79a79..57f764c7d8b 100644 --- a/Tetrahedral_remeshing/examples/Tetrahedral_remeshing/tetrahedral_remeshing_example.cpp +++ b/Tetrahedral_remeshing/examples/Tetrahedral_remeshing/tetrahedral_remeshing_example.cpp @@ -30,7 +30,7 @@ int main(int argc, char* argv[]) if( !CGAL::load_triangulation(input, t3)) return EXIT_FAILURE; - CGAL::tetrahedral_adaptive_remeshing(t3, target_edge_length); + CGAL::tetrahedral_isotropic_remeshing(t3, target_edge_length); // save output const std::string file_in(filename); diff --git a/Tetrahedral_remeshing/examples/Tetrahedral_remeshing/tetrahedral_remeshing_of_one_subdomain.cpp b/Tetrahedral_remeshing/examples/Tetrahedral_remeshing/tetrahedral_remeshing_of_one_subdomain.cpp index 2802add0cd6..7e63fa5de9b 100644 --- a/Tetrahedral_remeshing/examples/Tetrahedral_remeshing/tetrahedral_remeshing_of_one_subdomain.cpp +++ b/Tetrahedral_remeshing/examples/Tetrahedral_remeshing/tetrahedral_remeshing_of_one_subdomain.cpp @@ -41,7 +41,7 @@ int main(int argc, char* argv[]) Remeshing_triangulation tr; CGAL::load_triangulation(input, tr); - CGAL::tetrahedral_adaptive_remeshing(tr, target_edge_length, + CGAL::tetrahedral_isotropic_remeshing(tr, target_edge_length, CGAL::parameters::cell_selector(Cells_of_subdomain(2))); std::ofstream ofile("output.binary.cgal", std::ios_base::out | std::ios_base::binary); diff --git a/Tetrahedral_remeshing/examples/Tetrahedral_remeshing/tetrahedral_remeshing_with_features.cpp b/Tetrahedral_remeshing/examples/Tetrahedral_remeshing/tetrahedral_remeshing_with_features.cpp index b990653f90a..707f04bfdfa 100644 --- a/Tetrahedral_remeshing/examples/Tetrahedral_remeshing/tetrahedral_remeshing_with_features.cpp +++ b/Tetrahedral_remeshing/examples/Tetrahedral_remeshing/tetrahedral_remeshing_with_features.cpp @@ -150,7 +150,7 @@ int main(int argc, char* argv[]) CGAL_assertion(t3.is_valid()); - CGAL::tetrahedral_adaptive_remeshing(t3, target_edge_length, + CGAL::tetrahedral_isotropic_remeshing(t3, target_edge_length, CGAL::parameters::edge_is_constrained_map( Constrained_edges_property_map(&constraints)) .number_of_iterations(nb_iter)); diff --git a/Tetrahedral_remeshing/include/CGAL/tetrahedral_remeshing.h b/Tetrahedral_remeshing/include/CGAL/tetrahedral_remeshing.h index 25421889142..e9f04b59899 100644 --- a/Tetrahedral_remeshing/include/CGAL/tetrahedral_remeshing.h +++ b/Tetrahedral_remeshing/include/CGAL/tetrahedral_remeshing.h @@ -108,13 +108,13 @@ namespace CGAL */ template -void tetrahedral_adaptive_remeshing( +void tetrahedral_isotropic_remeshing( CGAL::Triangulation_3& tr, const double& target_edge_length, const NamedParameters& np) { typedef CGAL::Triangulation_3 Triangulation; - tetrahedral_adaptive_remeshing( + tetrahedral_isotropic_remeshing( tr, [target_edge_length](const typename Triangulation::Point& /* p */) {return target_edge_length;}, @@ -123,13 +123,13 @@ void tetrahedral_adaptive_remeshing( template -void tetrahedral_adaptive_remeshing( +void tetrahedral_isotropic_remeshing( CGAL::Triangulation_3& tr, const float& target_edge_length, const NamedParameters& np) { typedef CGAL::Triangulation_3 Triangulation; - tetrahedral_adaptive_remeshing( + tetrahedral_isotropic_remeshing( tr, [target_edge_length](const typename Triangulation::Point& /* p */) {return target_edge_length; }, @@ -139,7 +139,7 @@ void tetrahedral_adaptive_remeshing( template -void tetrahedral_adaptive_remeshing( +void tetrahedral_isotropic_remeshing( CGAL::Triangulation_3& tr, const SizingFunction& sizing, const NamedParameters& np) @@ -236,11 +236,11 @@ void tetrahedral_adaptive_remeshing( } template -void tetrahedral_adaptive_remeshing( +void tetrahedral_isotropic_remeshing( CGAL::Triangulation_3& tr, const double& target_edge_length) { - tetrahedral_adaptive_remeshing(tr, target_edge_length, + tetrahedral_isotropic_remeshing(tr, target_edge_length, CGAL::parameters::all_default()); } @@ -251,12 +251,12 @@ void tetrahedral_adaptive_remeshing( template -void tetrahedral_adaptive_remeshing( +void tetrahedral_isotropic_remeshing( CGAL::Mesh_complex_3_in_triangulation_3& c3t3, const double& target_edge_length, const NamedParameters& np) { - tetrahedral_adaptive_remeshing( + tetrahedral_isotropic_remeshing( c3t3, [target_edge_length](const typename Tr::Point& /* p */) {return target_edge_length; }, @@ -266,12 +266,12 @@ void tetrahedral_adaptive_remeshing( template -void tetrahedral_adaptive_remeshing( +void tetrahedral_isotropic_remeshing( CGAL::Mesh_complex_3_in_triangulation_3& c3t3, const float& target_edge_length, const NamedParameters& np) { - tetrahedral_adaptive_remeshing( + tetrahedral_isotropic_remeshing( c3t3, [target_edge_length](const typename Tr::Point& p) {return target_edge_length; }, @@ -281,11 +281,11 @@ void tetrahedral_adaptive_remeshing( template -void tetrahedral_adaptive_remeshing( +void tetrahedral_isotropic_remeshing( CGAL::Mesh_complex_3_in_triangulation_3& c3t3, const double& target_edge_length) { - return tetrahedral_adaptive_remeshing(c3t3, target_edge_length, + return tetrahedral_isotropic_remeshing(c3t3, target_edge_length, CGAL::parameters::all_default()); } @@ -293,7 +293,7 @@ template -void tetrahedral_adaptive_remeshing( +void tetrahedral_isotropic_remeshing( CGAL::Mesh_complex_3_in_triangulation_3& c3t3, const SizingFunction& sizing, const NamedParameters& np) diff --git a/Tetrahedral_remeshing/test/Tetrahedral_remeshing/test_tetrahedral_remeshing.cpp b/Tetrahedral_remeshing/test/Tetrahedral_remeshing/test_tetrahedral_remeshing.cpp index 36f5ffb8df7..920e799bdd6 100644 --- a/Tetrahedral_remeshing/test/Tetrahedral_remeshing/test_tetrahedral_remeshing.cpp +++ b/Tetrahedral_remeshing/test/Tetrahedral_remeshing/test_tetrahedral_remeshing.cpp @@ -50,7 +50,7 @@ int main(int argc, char* argv[]) const float target_edge_length = (argc > 1) ? atof(argv[1]) : 0.1f; - CGAL::tetrahedral_adaptive_remeshing(tr, target_edge_length); + CGAL::tetrahedral_isotropic_remeshing(tr, target_edge_length); return EXIT_SUCCESS; } diff --git a/Tetrahedral_remeshing/test/Tetrahedral_remeshing/test_tetrahedral_remeshing_of_one_subdomain.cpp b/Tetrahedral_remeshing/test/Tetrahedral_remeshing/test_tetrahedral_remeshing_of_one_subdomain.cpp index 23fe03401ae..93e1e04b6a6 100644 --- a/Tetrahedral_remeshing/test/Tetrahedral_remeshing/test_tetrahedral_remeshing_of_one_subdomain.cpp +++ b/Tetrahedral_remeshing/test/Tetrahedral_remeshing/test_tetrahedral_remeshing_of_one_subdomain.cpp @@ -71,7 +71,7 @@ int main(int argc, char* argv[]) Remeshing_triangulation tr; generate_input_two_subdomains(1000, tr); - CGAL::tetrahedral_adaptive_remeshing(tr, target_edge_length, + CGAL::tetrahedral_isotropic_remeshing(tr, target_edge_length, CGAL::parameters::cell_selector(Cells_of_subdomain(2))); return EXIT_SUCCESS; diff --git a/Tetrahedral_remeshing/test/Tetrahedral_remeshing/test_tetrahedral_remeshing_with_features.cpp b/Tetrahedral_remeshing/test/Tetrahedral_remeshing/test_tetrahedral_remeshing_with_features.cpp index 21d869d00e1..2418a79449d 100644 --- a/Tetrahedral_remeshing/test/Tetrahedral_remeshing/test_tetrahedral_remeshing_with_features.cpp +++ b/Tetrahedral_remeshing/test/Tetrahedral_remeshing/test_tetrahedral_remeshing_with_features.cpp @@ -144,7 +144,7 @@ int main(int argc, char* argv[]) set_subdomain(tr, 1); assert(tr.is_valid()); - CGAL::tetrahedral_adaptive_remeshing(tr, target_edge_length, + CGAL::tetrahedral_isotropic_remeshing(tr, target_edge_length, CGAL::parameters::edge_is_constrained_map( Constrained_edges_property_map(&constraints)) .number_of_iterations(nb_iter)); From 5005c31f00bdbdde7f0eb97258052ca784e411c3 Mon Sep 17 00:00:00 2001 From: Laurent Rineau Date: Fri, 17 Apr 2020 10:37:20 +0200 Subject: [PATCH 284/568] I/O: close the streams to flush the files buffers --- .../Tetrahedral_remeshing/test_tetrahedral_remeshing_io.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Tetrahedral_remeshing/test/Tetrahedral_remeshing/test_tetrahedral_remeshing_io.cpp b/Tetrahedral_remeshing/test/Tetrahedral_remeshing/test_tetrahedral_remeshing_io.cpp index 9c741fc2b74..c2cbe1406cc 100644 --- a/Tetrahedral_remeshing/test/Tetrahedral_remeshing/test_tetrahedral_remeshing_io.cpp +++ b/Tetrahedral_remeshing/test/Tetrahedral_remeshing/test_tetrahedral_remeshing_io.cpp @@ -43,6 +43,7 @@ int main(int argc, char* argv[]) std::ofstream out1("remeshing_triangulation.ascii.cgal", std::ios_base::out); bool ok = CGAL::save_ascii_triangulation(out1, tr); + out1.close(); assert(ok); std::cout << "done." << std::endl; @@ -60,6 +61,7 @@ int main(int argc, char* argv[]) std::ofstream out2("remeshing_triangulation.binary.cgal", std::ios_base::out | std::ios_base::binary); ok = CGAL::save_binary_triangulation(out2, tr); + out2.close(); assert(ok); std::cout << "done." << std::endl; From e985f038179a1e4b228fc389eb95832de88336df Mon Sep 17 00:00:00 2001 From: Jane Tournois Date: Fri, 17 Apr 2020 14:05:37 +0200 Subject: [PATCH 285/568] initialize time stamp with -1 in Mesh_vertex_base_3 the time stamper checks whether it is -1 or not, with -1 as default value. It was not initialized so the behaviour was not as expected. Similar to what is done in 0e9389b9fe0ad90aaa30ba5d634824d59c7f804d for Mesh_cell_base_3 --- Mesh_3/include/CGAL/Mesh_vertex_base_3.h | 1 + 1 file changed, 1 insertion(+) diff --git a/Mesh_3/include/CGAL/Mesh_vertex_base_3.h b/Mesh_3/include/CGAL/Mesh_vertex_base_3.h index 9ad67147d1b..977782a8932 100644 --- a/Mesh_3/include/CGAL/Mesh_vertex_base_3.h +++ b/Mesh_3/include/CGAL/Mesh_vertex_base_3.h @@ -127,6 +127,7 @@ public: , next_intrusive_() , previous_intrusive_() #endif //CGAL_INTRUSIVE_LIST + , time_stamp_(-1) {} // Default copy constructor and assignment operator are ok From ba15e9f0a9a16d689c76b2ad6d0f879894b3391a Mon Sep 17 00:00:00 2001 From: Jane Tournois Date: Fri, 17 Apr 2020 14:16:44 +0200 Subject: [PATCH 286/568] clean tests and add macro CGAL_TETRAHEDRAL_REMESHING_GENERATE_INPUT_FILES --- .../test_tetrahedral_remeshing.cpp | 10 +++++++--- ...tetrahedral_remeshing_of_one_subdomain.cpp | 9 ++++++--- ...st_tetrahedral_remeshing_with_features.cpp | 19 +++++++++++++------ 3 files changed, 26 insertions(+), 12 deletions(-) diff --git a/Tetrahedral_remeshing/test/Tetrahedral_remeshing/test_tetrahedral_remeshing.cpp b/Tetrahedral_remeshing/test/Tetrahedral_remeshing/test_tetrahedral_remeshing.cpp index 920e799bdd6..7c591955425 100644 --- a/Tetrahedral_remeshing/test/Tetrahedral_remeshing/test_tetrahedral_remeshing.cpp +++ b/Tetrahedral_remeshing/test/Tetrahedral_remeshing/test_tetrahedral_remeshing.cpp @@ -1,4 +1,5 @@ //#define CGAL_TETRAHEDRAL_REMESHING_VERBOSE +#define CGAL_TETRAHEDRAL_REMESHING_GENERATE_INPUT_FILES #include @@ -16,7 +17,7 @@ typedef CGAL::Exact_predicates_inexact_constructions_kernel K; typedef CGAL::Tetrahedral_remeshing::Remeshing_triangulation_3 Remeshing_triangulation; template -bool generate_input_one_subdomain(const std::size_t nbv, T3& tr) +void generate_input_one_subdomain(const std::size_t nbv, T3& tr) { CGAL::Random rng; @@ -32,13 +33,16 @@ bool generate_input_one_subdomain(const std::size_t nbv, T3& tr) for (typename T3::Cell_handle c : tr.finite_cell_handles()) c->set_subdomain_index(1); + CGAL_assertion(tr.is_valid(true)); + +#ifdef CGAL_TETRAHEDRAL_REMESHING_GENERATE_INPUT_FILES std::string filename("data/triangulation_one_subdomain.binary.cgal"); std::ofstream out(filename, std::ios_base::out | std::ios_base::binary); out << "binary CGAL c3t3\n"; CGAL::set_binary_mode(out); out << tr; - - return (!out.bad()); + out.close(); +#endif } int main(int argc, char* argv[]) diff --git a/Tetrahedral_remeshing/test/Tetrahedral_remeshing/test_tetrahedral_remeshing_of_one_subdomain.cpp b/Tetrahedral_remeshing/test/Tetrahedral_remeshing/test_tetrahedral_remeshing_of_one_subdomain.cpp index 93e1e04b6a6..bc010bed1c3 100644 --- a/Tetrahedral_remeshing/test/Tetrahedral_remeshing/test_tetrahedral_remeshing_of_one_subdomain.cpp +++ b/Tetrahedral_remeshing/test/Tetrahedral_remeshing/test_tetrahedral_remeshing_of_one_subdomain.cpp @@ -1,3 +1,5 @@ +#define CGAL_TETRAHEDRAL_REMESHING_GENERATE_INPUT_FILES + #include #include @@ -13,7 +15,7 @@ typedef CGAL::Exact_predicates_inexact_constructions_kernel K; typedef CGAL::Tetrahedral_remeshing::Remeshing_triangulation_3 Remeshing_triangulation; -bool generate_input_two_subdomains(const std::size_t nbv, Remeshing_triangulation& tr) +void generate_input_two_subdomains(const std::size_t nbv, Remeshing_triangulation& tr) { CGAL::Random rng; @@ -37,12 +39,13 @@ bool generate_input_two_subdomains(const std::size_t nbv, Remeshing_triangulatio } CGAL_assertion(tr.is_valid(true)); +#ifdef CGAL_TETRAHEDRAL_REMESHING_GENERATE_INPUT_FILES std::string filename("data/triangulation_two_subdomains.binary.cgal"); std::ofstream os(filename, std::ios_base::out | std::ios_base::binary); os << "binary CGAL c3t3\n"; CGAL::set_binary_mode(os); - - return !!(os << tr); + os.close(); +#endif } struct Cells_of_subdomain diff --git a/Tetrahedral_remeshing/test/Tetrahedral_remeshing/test_tetrahedral_remeshing_with_features.cpp b/Tetrahedral_remeshing/test/Tetrahedral_remeshing/test_tetrahedral_remeshing_with_features.cpp index 2418a79449d..3ac107d3c32 100644 --- a/Tetrahedral_remeshing/test/Tetrahedral_remeshing/test_tetrahedral_remeshing_with_features.cpp +++ b/Tetrahedral_remeshing/test/Tetrahedral_remeshing/test_tetrahedral_remeshing_with_features.cpp @@ -1,5 +1,5 @@ #define CGAL_TETRAHEDRAL_REMESHING_VERBOSE -#define CGAL_DUMP_REMESHING_STEPS +#define CGAL_TETRAHEDRAL_REMESHING_GENERATE_INPUT_FILES #include @@ -14,6 +14,7 @@ #include #include +#include #include typedef CGAL::Exact_predicates_inexact_constructions_kernel K; @@ -82,8 +83,10 @@ void generate_input_cube(const std::size_t& n, CGAL::Random rng; // points in a sphere - while (tr.number_of_vertices() < n) - tr.insert(Point(rng.get_double(-1., 1.), rng.get_double(-1., 1.), rng.get_double(-1., 1.))); + std::vector pts; + while (pts.size() < n) + pts.push_back(Point(rng.get_double(-1., 1.), rng.get_double(-1., 1.), rng.get_double(-1., 1.))); + tr.insert(pts.begin(), pts.end()); // vertices of a larger cube Vertex_handle v0 = tr.insert(Point(-2., -2., -2.)); @@ -98,11 +101,15 @@ void generate_input_cube(const std::size_t& n, Vertex_handle v6 = tr.insert(Point( 2., 2., -2.)); Vertex_handle v7 = tr.insert(Point( 2., 2., 2.)); + CGAL_assertion(tr.is_valid(true)); + // writing file output - std::ofstream oFileT("data/sphere_in_cube.tr.cgal", +#ifdef CGAL_TETRAHEDRAL_REMESHING_GENERATE_INPUT_FILES + std::ofstream outfile("data/sphere_in_cube.tr.cgal", std::ios_base::out | std::ios_base::binary); - oFileT << tr; - oFileT.close(); + CGAL::save_binary_triangulation(outfile, tr); + outfile.close(); +#endif // constrain cube edges add_edge(v0, v1, tr, constraints); From c6fe1e72bbd28b439ad4c567d4ed6c880902a9b2 Mon Sep 17 00:00:00 2001 From: Jane Tournois Date: Fri, 17 Apr 2020 14:35:45 +0200 Subject: [PATCH 287/568] use CGAL::save_binary_triangulation --- .../Tetrahedral_remeshing/test_tetrahedral_remeshing.cpp | 8 +++----- .../test_tetrahedral_remeshing_of_one_subdomain.cpp | 7 +++---- .../test_tetrahedral_remeshing_with_features.cpp | 2 +- 3 files changed, 7 insertions(+), 10 deletions(-) diff --git a/Tetrahedral_remeshing/test/Tetrahedral_remeshing/test_tetrahedral_remeshing.cpp b/Tetrahedral_remeshing/test/Tetrahedral_remeshing/test_tetrahedral_remeshing.cpp index 7c591955425..5e621db6ce8 100644 --- a/Tetrahedral_remeshing/test/Tetrahedral_remeshing/test_tetrahedral_remeshing.cpp +++ b/Tetrahedral_remeshing/test/Tetrahedral_remeshing/test_tetrahedral_remeshing.cpp @@ -36,11 +36,9 @@ void generate_input_one_subdomain(const std::size_t nbv, T3& tr) CGAL_assertion(tr.is_valid(true)); #ifdef CGAL_TETRAHEDRAL_REMESHING_GENERATE_INPUT_FILES - std::string filename("data/triangulation_one_subdomain.binary.cgal"); - std::ofstream out(filename, std::ios_base::out | std::ios_base::binary); - out << "binary CGAL c3t3\n"; - CGAL::set_binary_mode(out); - out << tr; + std::ofstream out("data/triangulation_one_subdomain.binary.cgal", + std::ios_base::out | std::ios_base::binary); + CGAL::save_binary_triangulation(out, tr); out.close(); #endif } diff --git a/Tetrahedral_remeshing/test/Tetrahedral_remeshing/test_tetrahedral_remeshing_of_one_subdomain.cpp b/Tetrahedral_remeshing/test/Tetrahedral_remeshing/test_tetrahedral_remeshing_of_one_subdomain.cpp index bc010bed1c3..1ba6b126bb1 100644 --- a/Tetrahedral_remeshing/test/Tetrahedral_remeshing/test_tetrahedral_remeshing_of_one_subdomain.cpp +++ b/Tetrahedral_remeshing/test/Tetrahedral_remeshing/test_tetrahedral_remeshing_of_one_subdomain.cpp @@ -40,10 +40,9 @@ void generate_input_two_subdomains(const std::size_t nbv, Remeshing_triangulatio CGAL_assertion(tr.is_valid(true)); #ifdef CGAL_TETRAHEDRAL_REMESHING_GENERATE_INPUT_FILES - std::string filename("data/triangulation_two_subdomains.binary.cgal"); - std::ofstream os(filename, std::ios_base::out | std::ios_base::binary); - os << "binary CGAL c3t3\n"; - CGAL::set_binary_mode(os); + std::ofstream os("data/triangulation_two_subdomains.binary.cgal", + std::ios_base::out | std::ios_base::binary); + CGAL::save_binary_triangulation(os, tr); os.close(); #endif } diff --git a/Tetrahedral_remeshing/test/Tetrahedral_remeshing/test_tetrahedral_remeshing_with_features.cpp b/Tetrahedral_remeshing/test/Tetrahedral_remeshing/test_tetrahedral_remeshing_with_features.cpp index 3ac107d3c32..45fd962b677 100644 --- a/Tetrahedral_remeshing/test/Tetrahedral_remeshing/test_tetrahedral_remeshing_with_features.cpp +++ b/Tetrahedral_remeshing/test/Tetrahedral_remeshing/test_tetrahedral_remeshing_with_features.cpp @@ -106,7 +106,7 @@ void generate_input_cube(const std::size_t& n, // writing file output #ifdef CGAL_TETRAHEDRAL_REMESHING_GENERATE_INPUT_FILES std::ofstream outfile("data/sphere_in_cube.tr.cgal", - std::ios_base::out | std::ios_base::binary); + std::ios_base::out | std::ios_base::binary); CGAL::save_binary_triangulation(outfile, tr); outfile.close(); #endif From dacca12c3f8dc2fecd428282ee84ca07c53489db Mon Sep 17 00:00:00 2001 From: Jane Tournois Date: Fri, 17 Apr 2020 15:05:19 +0200 Subject: [PATCH 288/568] reorder Cb and Vb consistently with the ones of T3 and Tds --- .../Remeshing_triangulation_3.h | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/Remeshing_triangulation_3.h b/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/Remeshing_triangulation_3.h index 45b210a2352..6727c3a4c1f 100644 --- a/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/Remeshing_triangulation_3.h +++ b/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/Remeshing_triangulation_3.h @@ -47,21 +47,21 @@ It has to be a model of the concept `RemeshingTriangulationTraits_3`. triangulation data structure. Possible values are `Sequential_tag` (the default) and `Parallel_tag`. -\tparam Cb is a cell base class from which `Remeshing_cell_base_3` derives. -It must be a model of the `TriangulationCellBase_3` concept. -It has the default value `Triangulation_cell_base_3`. - \tparam Vb is a vertex base class from which `Remeshing_vertex_base_3` derives. It must be a model of the `TriangulationVertexBase_3` concept. It has the default value `Triangulation_vertex_base_3`. +\tparam Cb is a cell base class from which `Remeshing_cell_base_3` derives. +It must be a model of the `TriangulationCellBase_3` concept. +It has the default value `Triangulation_cell_base_3`. + \cgalRefines `Triangulation_3` */ template, - typename Vb = CGAL::Triangulation_vertex_base_3 + typename Vb = CGAL::Triangulation_vertex_base_3, + typename Cb = CGAL::Triangulation_cell_base_3 > class Remeshing_triangulation_3 : public CGAL::Triangulation_3 Date: Fri, 17 Apr 2020 15:35:38 +0200 Subject: [PATCH 289/568] hardcode input file name, because cube corners are hardcoded above --- .../tetrahedral_remeshing_with_features.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Tetrahedral_remeshing/examples/Tetrahedral_remeshing/tetrahedral_remeshing_with_features.cpp b/Tetrahedral_remeshing/examples/Tetrahedral_remeshing/tetrahedral_remeshing_with_features.cpp index 707f04bfdfa..422395339fd 100644 --- a/Tetrahedral_remeshing/examples/Tetrahedral_remeshing/tetrahedral_remeshing_with_features.cpp +++ b/Tetrahedral_remeshing/examples/Tetrahedral_remeshing/tetrahedral_remeshing_with_features.cpp @@ -131,9 +131,9 @@ void set_subdomain(Remeshing_triangulation& tr, const int index) int main(int argc, char* argv[]) { - const char* filename = (argc > 1) ? argv[1] : "data/sphere_in_cube.tr.cgal"; - double target_edge_length = (argc > 2) ? atof(argv[2]) : 0.02; - int nb_iter = (argc > 3) ? atoi(argv[3]) : 1; + const char* filename = "data/sphere_in_cube.tr.cgal"; + const double target_edge_length = (argc > 1) ? atof(argv[1]) : 0.02; + cosnt int nb_iter = (argc > 2) ? atoi(argv[2]) : 1; std::ifstream input(filename, std::ios_base::in | std::ios_base::binary); if (!input) From 3d003490c9e8d932a21e59216db8e7492b9e5701 Mon Sep 17 00:00:00 2001 From: Jane Tournois Date: Fri, 17 Apr 2020 15:36:00 +0200 Subject: [PATCH 290/568] remove unused include --- .../tetrahedral_remeshing_of_one_subdomain.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/Tetrahedral_remeshing/examples/Tetrahedral_remeshing/tetrahedral_remeshing_of_one_subdomain.cpp b/Tetrahedral_remeshing/examples/Tetrahedral_remeshing/tetrahedral_remeshing_of_one_subdomain.cpp index 7e63fa5de9b..5519e754235 100644 --- a/Tetrahedral_remeshing/examples/Tetrahedral_remeshing/tetrahedral_remeshing_of_one_subdomain.cpp +++ b/Tetrahedral_remeshing/examples/Tetrahedral_remeshing/tetrahedral_remeshing_of_one_subdomain.cpp @@ -1,6 +1,5 @@ #include -#include #include #include From c951383f48177b9ca775766345034363143cf305 Mon Sep 17 00:00:00 2001 From: Jane Tournois Date: Fri, 17 Apr 2020 16:33:01 +0200 Subject: [PATCH 291/568] fix internal c3t3 when input is not a C3T3 because add_to_complex(cell) does not do anything when subdomain_index is not null, we need to remove cell from c3t3 first --- .../internal/tetrahedral_adaptive_remeshing_impl.h | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/tetrahedral_adaptive_remeshing_impl.h b/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/tetrahedral_adaptive_remeshing_impl.h index 91c688a34b4..763851f7f38 100644 --- a/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/tetrahedral_adaptive_remeshing_impl.h +++ b/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/tetrahedral_adaptive_remeshing_impl.h @@ -325,12 +325,14 @@ private: #endif //tag cells - typedef typename Tr::Cell_handle Cell_handle; for (Cell_handle cit : tr().finite_cell_handles()) { if (m_cell_selector(cit)) { - m_c3t3.add_to_complex(cit, cit->subdomain_index()); + const Subdomain_index index = cit->subdomain_index(); + if(!input_is_c3t3()) + m_c3t3.remove_from_complex(cit); + m_c3t3.add_to_complex(cit, index); #ifdef CGAL_TETRAHEDRAL_REMESHING_DEBUG ++nbc; From 3d181f5fe2b51fb5230939ccd4b4e56dda04698a Mon Sep 17 00:00:00 2001 From: Jane Tournois Date: Fri, 17 Apr 2020 16:44:00 +0200 Subject: [PATCH 292/568] use range iterators --- .../tetrahedral_adaptive_remeshing_impl.h | 15 ++++----------- 1 file changed, 4 insertions(+), 11 deletions(-) diff --git a/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/tetrahedral_adaptive_remeshing_impl.h b/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/tetrahedral_adaptive_remeshing_impl.h index 763851f7f38..641c94e30fa 100644 --- a/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/tetrahedral_adaptive_remeshing_impl.h +++ b/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/tetrahedral_adaptive_remeshing_impl.h @@ -241,12 +241,9 @@ public: FT sqmax = emax * emax; FT sqmin = emin * emin; - typedef typename Tr::Finite_edges_iterator Finite_edges_iterator; - for (Finite_edges_iterator eit = tr().finite_edges_begin(); - eit != tr().finite_edges_end(); - ++eit) + typedef typename Tr::Edge Edge; + for (Edge e : tr().finite_edges()) { - typename Tr::Edge e = *eit; // skip protected edges if (m_protect_boundaries) { @@ -275,9 +272,7 @@ public: #endif std::size_t nb_slivers_peel = 0; - typedef typename Tr::Finite_cells_iterator Finite_cells_iterator; - for (Finite_cells_iterator cit = tr().finite_cells_begin(); - cit != tr().finite_cells_end(); ++cit) + for (Cell_handle cit : tr().finite_cell_handles()) { if(m_c3t3.is_in_complex(cit) && min_dihedral_angle(tr(), cit) < sliver_angle) { @@ -454,9 +449,7 @@ private: bool check_vertex_dimensions() { - typename Tr::Finite_vertices_iterator vit; - for (vit = tr().finite_vertices_begin(); - vit != tr().finite_vertices_end(); ++vit) + for (Vertex_handle vit : tr().finite_vertex_handles()) { // dimension is -1 for Mesh_3 "far points" // for other vertices, it is in [0; 3] From 958c9c5c3e251287850b0b4580309a7c659cf684 Mon Sep 17 00:00:00 2001 From: Jane Tournois Date: Fri, 17 Apr 2020 16:45:30 +0200 Subject: [PATCH 293/568] update input data for examples with valid binary files From fbd1952169a8c3e70dbac38dee6117d11c08594a Mon Sep 17 00:00:00 2001 From: Jane Tournois Date: Fri, 17 Apr 2020 16:46:43 +0200 Subject: [PATCH 294/568] use base class is_facet_on_surface() function --- .../CGAL/Tetrahedral_remeshing/Remeshing_cell_base_3.h | 10 ---------- 1 file changed, 10 deletions(-) diff --git a/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/Remeshing_cell_base_3.h b/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/Remeshing_cell_base_3.h index be080d159c6..df3678dec4f 100644 --- a/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/Remeshing_cell_base_3.h +++ b/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/Remeshing_cell_base_3.h @@ -69,16 +69,6 @@ public: }; using Base::Base; - -#ifndef DOXYGEN_RUNNING - /// TODO : remove this function from here - /// Returns `true` if facet lies on a surface patch - bool is_facet_on_surface(const int facet) const - { - CGAL_precondition(facet >= 0 && facet<4); - return this->subdomain_index() != this->neighbor(facet)->subdomain_index(); - } -#endif }; }//end namespace Tetrahedral_remeshing From bb961ff46601b7158b3856a73ccd7737ebf534cf Mon Sep 17 00:00:00 2001 From: Jane Tournois Date: Fri, 17 Apr 2020 16:51:40 +0200 Subject: [PATCH 295/568] fix typo --- .../tetrahedral_remeshing_with_features.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Tetrahedral_remeshing/examples/Tetrahedral_remeshing/tetrahedral_remeshing_with_features.cpp b/Tetrahedral_remeshing/examples/Tetrahedral_remeshing/tetrahedral_remeshing_with_features.cpp index 422395339fd..11803d908ff 100644 --- a/Tetrahedral_remeshing/examples/Tetrahedral_remeshing/tetrahedral_remeshing_with_features.cpp +++ b/Tetrahedral_remeshing/examples/Tetrahedral_remeshing/tetrahedral_remeshing_with_features.cpp @@ -133,7 +133,7 @@ int main(int argc, char* argv[]) { const char* filename = "data/sphere_in_cube.tr.cgal"; const double target_edge_length = (argc > 1) ? atof(argv[1]) : 0.02; - cosnt int nb_iter = (argc > 2) ? atoi(argv[2]) : 1; + const int nb_iter = (argc > 2) ? atoi(argv[2]) : 1; std::ifstream input(filename, std::ios_base::in | std::ios_base::binary); if (!input) From 96bab4d9e33b1406a05848cf0af6fd0c456ece62 Mon Sep 17 00:00:00 2001 From: Jane Tournois Date: Mon, 20 Apr 2020 07:20:55 +0200 Subject: [PATCH 296/568] fix warning about double brackets and use range iterators --- .../internal/collapse_short_edges.h | 27 +++++-------------- 1 file changed, 7 insertions(+), 20 deletions(-) diff --git a/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/collapse_short_edges.h b/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/collapse_short_edges.h index 122ac9bab8a..fd633e28349 100644 --- a/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/collapse_short_edges.h +++ b/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/collapse_short_edges.h @@ -227,9 +227,8 @@ public: Vertex_handle infinite_vertex = triangulation.infinite_vertex(); bool v0_updated = false; - for (unsigned int i = 0; i < find_incident.size(); i++) + for (const Cell_handle ch : find_incident) { - const Cell_handle ch = find_incident[i]; if (invalid_cells.find(ch) == invalid_cells.end()) //valid cell { if (triangulation.is_infinite(ch)) @@ -242,10 +241,8 @@ public: } //Update the vertex before removing it - for (unsigned int i = 0; i < cells_to_update.size(); i++) + for (Cell_handle ch : cells_to_update) { - Cell_handle & ch = cells_to_update[i]; - if (invalid_cells.find(ch) == invalid_cells.end()) //valid cell { ch->set_vertex(ch->index(vh1), vh0); @@ -268,29 +265,19 @@ public: triangulation.tds().delete_vertex(vh1); //Removing cells - for (unsigned int i = 0; i < cells_to_remove.size(); i++){ - triangulation.tds().delete_cell(cells_to_remove[i]); + for (Cell_handle ch : cells_to_remove){ + triangulation.tds().delete_cell(ch); } - typedef typename Tr::Finite_cells_iterator Finite_cells_iterator; - for (Finite_cells_iterator cit = triangulation.finite_cells_begin(); - cit != triangulation.finite_cells_end(); ++cit) + for (Cell_handle cit : triangulation.finite_cell_handles()) { if (!is_well_oriented(triangulation, cit)) return ORIENTATION_PROBLEM; - } - - typedef typename Tr::Cell_iterator Cell_iterator; - for (Cell_iterator cit = triangulation.cells_begin(); - cit != triangulation.cells_end(); ++cit) - { if (!triangulation.tds().is_valid(cit, true)) return C_PROBLEM; } - typedef typename Tr::Vertex_iterator Vertex_iterator; - for (Vertex_iterator vit = triangulation.vertices_begin(); - vit != triangulation.vertices_end(); ++vit) + for (Vertex_handle vit : triangulation.finite_vertex_handles()) { if (!triangulation.tds().is_valid(vit, true)) return V_PROBLEM; @@ -735,7 +722,7 @@ collapse(const typename C3t3::Cell_handle ch, // update complex edges const std::array, 6> edges - = { 0,1, 0,2, 0,3, 1,2, 1,3, 2,3 }; //vertex indices in cells + = { { 0,1, 0,2, 0,3, 1,2, 1,3, 2,3 } }; //vertex indices in cells const Vertex_handle vkept = vh0; const Vertex_handle vdeleted = vh1; for (const Cell_handle ch : cells_to_update) From 90ad2cb613084d767b1e48f1fc9db9c2de2c95ee Mon Sep 17 00:00:00 2001 From: Simon Giraudot Date: Mon, 20 Apr 2020 08:46:59 +0200 Subject: [PATCH 297/568] Fix warnings and trailing whitespaces --- .../doc/Point_set_processing_3/NamedParameters.txt | 1 - Point_set_processing_3/include/CGAL/cluster_point_set.h | 4 ++-- .../Plugins/Point_set/Point_set_clustering_plugin.cpp | 4 ++-- 3 files changed, 4 insertions(+), 5 deletions(-) diff --git a/Point_set_processing_3/doc/Point_set_processing_3/NamedParameters.txt b/Point_set_processing_3/doc/Point_set_processing_3/NamedParameters.txt index 50275f718f4..ba478f86b6f 100644 --- a/Point_set_processing_3/doc/Point_set_processing_3/NamedParameters.txt +++ b/Point_set_processing_3/doc/Point_set_processing_3/NamedParameters.txt @@ -273,7 +273,6 @@ is an output iterator used to store adjacencies.\n \b Type: a class model of `OutputIterator` that accepts objects of type `std::pair`. \n Default value: `CGAL::Emptyset_iterator`. - \cgalNPEnd \cgalNPTableEnd diff --git a/Point_set_processing_3/include/CGAL/cluster_point_set.h b/Point_set_processing_3/include/CGAL/cluster_point_set.h index cf38b4b5fa7..3098db06c97 100644 --- a/Point_set_processing_3/include/CGAL/cluster_point_set.h +++ b/Point_set_processing_3/include/CGAL/cluster_point_set.h @@ -165,7 +165,7 @@ std::size_t cluster_point_set (PointRange& points, { const value_type& p = *it; - if (get (cluster_map, p) != -1) + if (int(get (cluster_map, p)) != -1) continue; todo.push (it); @@ -175,7 +175,7 @@ std::size_t cluster_point_set (PointRange& points, iterator current = todo.front(); todo.pop(); - if (get (cluster_map, *current) != -1) + if (int(get (cluster_map, *current)) != -1) continue; put (cluster_map, *current, nb_clusters); diff --git a/Polyhedron/demo/Polyhedron/Plugins/Point_set/Point_set_clustering_plugin.cpp b/Polyhedron/demo/Polyhedron/Plugins/Point_set/Point_set_clustering_plugin.cpp index 9cfd1771a93..61eaa766927 100644 --- a/Polyhedron/demo/Polyhedron/Plugins/Point_set/Point_set_clustering_plugin.cpp +++ b/Polyhedron/demo/Polyhedron/Plugins/Point_set/Point_set_clustering_plugin.cpp @@ -191,7 +191,7 @@ void Polyhedron_demo_point_set_clustering_plugin::on_actionCluster_triggered() for (Point_set::Index idx : *points) { Point_set::Index iidx = *(colored->point_set()->insert (points->point(idx))); - if (cluster_size[cluster_map[idx]] >= min_nb->value()) + if (cluster_size[cluster_map[idx]] >= std::size_t(min_nb->value())) { CGAL::Random rand(cluster_map[idx] + 1); unsigned char r, g, b; @@ -210,7 +210,7 @@ void Polyhedron_demo_point_set_clustering_plugin::on_actionCluster_triggered() { for (Scene_points_with_normal_item* new_item : new_items) { - if (new_item->point_set()->size() >= min_nb->value()) + if (new_item->point_set()->size() >= std::size_t(min_nb->value())) { scene->addItem(new_item); scene->changeGroup (new_item, group); From 637695e892dc069c448727ac01e4aaaba336ff89 Mon Sep 17 00:00:00 2001 From: Simon Giraudot Date: Mon, 20 Apr 2020 09:10:23 +0200 Subject: [PATCH 298/568] Fix doc with imported targets --- .../Developer_manual/create_and_use_a_cmakelist.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Documentation/doc/Documentation/Developer_manual/create_and_use_a_cmakelist.txt b/Documentation/doc/Documentation/Developer_manual/create_and_use_a_cmakelist.txt index afc413a7dd7..0fffe791b9b 100644 --- a/Documentation/doc/Documentation/Developer_manual/create_and_use_a_cmakelist.txt +++ b/Documentation/doc/Documentation/Developer_manual/create_and_use_a_cmakelist.txt @@ -18,7 +18,7 @@ find_package(CGAL REQUIRED COMPONENTS Core) target_link_libraries(my_executable CGAL::CGAL CGAL::CGAL_Core) \endcode -There are also some cmake macros to link with \cgal dependencies that can be found in +There are also imported targets to link with \cgal dependencies that can be found in the section \subpage thirdparty. \note The \cgal targets define the following compiler flags: From 93b9f643bc3f7bee051b2706847eefaa8736dca1 Mon Sep 17 00:00:00 2001 From: Maxime Gimeno Date: Mon, 20 Apr 2020 13:23:37 +0200 Subject: [PATCH 299/568] Fix link problem in Io_image_plugin --- Polyhedron/demo/Polyhedron/Plugins/Mesh_3/CMakeLists.txt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Polyhedron/demo/Polyhedron/Plugins/Mesh_3/CMakeLists.txt b/Polyhedron/demo/Polyhedron/Plugins/Mesh_3/CMakeLists.txt index 8f1468406ac..274464901df 100644 --- a/Polyhedron/demo/Polyhedron/Plugins/Mesh_3/CMakeLists.txt +++ b/Polyhedron/demo/Polyhedron/Plugins/Mesh_3/CMakeLists.txt @@ -34,13 +34,13 @@ else() message(STATUS "NOTICE : the DICOM files (.dcm) need VTK libraries to be open and will not be able to.") endif() -find_package(Boost QUIET OPTIONAL_COMPONENTS filesystem) +find_package(Boost QUIET OPTIONAL_COMPONENTS filesystem system) if(Boost_FILESYSTEM_FOUND) qt5_wrap_ui( imgUI_FILES Image_res_dialog.ui raw_image.ui) polyhedron_demo_plugin(io_image_plugin Io_image_plugin Volume_plane_intersection.cpp Raw_image_dialog.cpp ${imgUI_FILES} ${VOLUME_MOC_OUTFILES} KEYWORDS IO Mesh_3) target_link_libraries(io_image_plugin PUBLIC scene_image_item ${VTK_LIBRARIES} CGAL::CGAL_ImageIO) if(TARGET Boost::filesystem) - target_link_libraries(io_image_plugin PUBLIC Boost::filesystem) + target_link_libraries(io_image_plugin PUBLIC Boost::filesystem Boost::system) else() target_link_libraries(io_image_plugin PUBLIC ${Boost_LIBRARIES}) endif() From 081b811cb0d63fc9d09cefca3f97f7cb8925843f Mon Sep 17 00:00:00 2001 From: Jane Tournois Date: Mon, 20 Apr 2020 14:17:00 +0200 Subject: [PATCH 300/568] fix warnings --- .../Tetrahedral_remeshing/internal/FMLS.h | 5 +- .../internal/collapse_short_edges.h | 46 +++++++++---------- .../internal/flip_edges.h | 16 +++---- .../internal/smooth_vertices.h | 14 +++--- .../internal/split_long_edges.h | 26 +++++------ .../internal/tetrahedral_remeshing_helpers.h | 10 ++-- .../test_tetrahedral_remeshing.cpp | 13 ++++-- 7 files changed, 67 insertions(+), 63 deletions(-) diff --git a/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/FMLS.h b/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/FMLS.h index 71e0115a76b..2ce1d842ee5 100644 --- a/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/FMLS.h +++ b/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/FMLS.h @@ -518,10 +518,9 @@ void createMLSSurfaces(Subdomain__FMLS& subdomain_FMLS, Subdomain__FMLS_indices& subdomain_FMLS_indices, const VerticesNormalsMap& vertices_normals, const VerticesSurfaceIndices& vertices_surface_indices, - const C3t3& c3t3) + const C3t3& c3t3, + const int upsample = 2) // can be 0, 1 or 2 { - const int upsample = 2; // can be 0, 1 or 2 - typedef typename C3t3::Surface_patch_index Surface_index; typedef typename C3t3::Triangulation Tr; typedef typename Tr::Edge Edge; diff --git a/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/collapse_short_edges.h b/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/collapse_short_edges.h index fd633e28349..7cfeb21607e 100644 --- a/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/collapse_short_edges.h +++ b/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/collapse_short_edges.h @@ -661,16 +661,16 @@ collapse(const typename C3t3::Cell_handle ch, std::vector cells_to_remove; boost::unordered_set invalid_cells; - for(const Cell_handle circ : inc_cells) + for(const Cell_handle c : inc_cells) { - const int v0_id = circ->index(vh0); - const int v1_id = circ->index(vh1); + const int v0_id = c->index(vh0); + const int v1_id = c->index(vh1); - Cell_handle n0_ch = circ->neighbor(v0_id); - Cell_handle n1_ch = circ->neighbor(v1_id); + Cell_handle n0_ch = c->neighbor(v0_id); + Cell_handle n1_ch = c->neighbor(v1_id); - const int ch_id_in_n0 = n0_ch->index(circ); - const int ch_id_in_n1 = n1_ch->index(circ); + const int ch_id_in_n0 = n0_ch->index(c); + const int ch_id_in_n1 = n1_ch->index(c); //Merge surface patch indices merge_surface_patch_indices(Facet(n0_ch, ch_id_in_n0), @@ -699,22 +699,22 @@ collapse(const typename C3t3::Cell_handle ch, std::cout << "Collapse infinite issue!" << std::endl; return Vertex_handle(); } - cells_to_remove.push_back(circ); + cells_to_remove.push_back(c); - invalid_cells.insert(circ); + invalid_cells.insert(c); } const Vertex_handle infinite_vertex = tr.infinite_vertex(); bool v0_updated = false; - for (const Cell_handle ch : find_incident) + for (const Cell_handle c : find_incident) { - if (invalid_cells.find(ch) == invalid_cells.end())//valid cell + if (invalid_cells.find(c) == invalid_cells.end())//valid cell { - if (tr.is_infinite(ch)) - infinite_vertex->set_cell(ch); + if (tr.is_infinite(c)) + infinite_vertex->set_cell(c); //else { - vh0->set_cell(ch); + vh0->set_cell(c); v0_updated = true; //} } @@ -725,12 +725,12 @@ collapse(const typename C3t3::Cell_handle ch, = { { 0,1, 0,2, 0,3, 1,2, 1,3, 2,3 } }; //vertex indices in cells const Vertex_handle vkept = vh0; const Vertex_handle vdeleted = vh1; - for (const Cell_handle ch : cells_to_update) + for (const Cell_handle c : cells_to_update) { for (const std::array& ei : edges) { - Vertex_handle eiv0 = ch->vertex(ei[0]); - Vertex_handle eiv1 = ch->vertex(ei[1]); + Vertex_handle eiv0 = c->vertex(ei[0]); + Vertex_handle eiv1 = c->vertex(ei[1]); if (eiv1 == vdeleted && eiv0 != vkept) //replace eiv1 by vkept { if (c3t3.is_in_complex(eiv0, eiv1)) @@ -753,17 +753,17 @@ collapse(const typename C3t3::Cell_handle ch, // update complex facets //Update the vertex before removing it - for (const Cell_handle ch : cells_to_update) + for (const Cell_handle c : cells_to_update) { - if (invalid_cells.find(ch) == invalid_cells.end()) //valid cell + if (invalid_cells.find(c) == invalid_cells.end()) //valid cell { - ch->set_vertex(ch->index(vh1), vh0); + c->set_vertex(c->index(vh1), vh0); - if (tr.is_infinite(ch)) - infinite_vertex->set_cell(ch); + if (tr.is_infinite(c)) + infinite_vertex->set_cell(c); //else { if (!v0_updated) { - vh0->set_cell(ch); + vh0->set_cell(c); v0_updated = true; } //} diff --git a/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/flip_edges.h b/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/flip_edges.h index a306580ed8f..f82e1aa749e 100644 --- a/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/flip_edges.h +++ b/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/flip_edges.h @@ -420,15 +420,15 @@ void find_best_flip_to_improve_dh(C3t3& c3t3, do { //Get the ids of the opposite vertices - for (int i = 0; i < 3; ++i) + for (int j = 0; j < 3; ++j) { - Vertex_handle curr_vertex = facet_circulator->first->vertex( - indices(facet_circulator->second, i)); - if (curr_vertex != vh0 && curr_vertex != vh1) + Vertex_handle curr = facet_circulator->first->vertex( + indices(facet_circulator->second, j)); + if (curr != vh0 && curr != vh1) { Cell_handle ch; int i0, i1; - if (tr.is_edge(curr_vertex, vh, ch, i0, i1)) + if (tr.is_edge(curr, vh, ch, i0, i1)) is_edge = true; } } @@ -475,9 +475,8 @@ void find_best_flip_to_improve_dh(C3t3& c3t3, FT min_flip_dihedral_angle = (std::numeric_limits::max)(); - for (std::size_t i = 0; i < facets.size(); ++i) + for (const Facet& fi : facets) { - const Facet& fi = facets[i]; if (!tr.is_infinite(fi.first)) { if (is_well_oriented(tr, vh, fi.first->vertex(indices(fi.second, 0)), @@ -614,9 +613,8 @@ void find_best_flip_to_improve_dh(C3t3& c3t3, while (++cell_circulator != done); FT min_flip_dihedral_angle = (std::numeric_limits::max)(); - for (std::size_t i = 0; i < facets.size(); ++i) + for (const Facet& fi : facets) { - const Facet& fi = facets[i]; if (!tr.is_infinite(fi.first)) { if (is_well_oriented(tr, vh, fi.first->vertex(indices(fi.second, 0)), diff --git a/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/smooth_vertices.h b/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/smooth_vertices.h index dceef9cb515..3ca4481c34d 100644 --- a/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/smooth_vertices.h +++ b/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/smooth_vertices.h @@ -180,14 +180,14 @@ private: facets.push_back(f); while (!facets.empty()) { - const Facet f = facets.front(); + const Facet ff = facets.front(); facets.pop_front(); const typename C3t3::Cell_handle ch = f.first; const std::array, 3> edges - = { (f.second + 1) % 4, (f.second + 2) % 4, //edge 1-2 - (f.second + 2) % 4, (f.second + 3) % 4, //edge 2-3 - (f.second + 3) % 4, (f.second + 1) % 4 //edge 3-1 + = { (ff.second + 1) % 4, (ff.second + 2) % 4, //edge 1-2 + (ff.second + 2) % 4, (ff.second + 3) % 4, //edge 2-3 + (ff.second + 3) % 4, (ff.second + 1) % 4 //edge 3-1 }; //vertex indices in cells const Vector_3& ref = fnormals[f]; @@ -303,7 +303,7 @@ private: int it_nb = 0; const int max_it_nb = 5; - const float epsilon = fmls.getPNScale() / 1000.; + const float epsilon = fmls.getPNScale() / 1000.f; const float sq_eps = CGAL::square(epsilon); do @@ -437,8 +437,8 @@ public: { for (int i = 0; i < 4; ++i) { - const std::size_t id = vertex_id[c->vertex(i)]; - inc_cells[id].push_back(c); + const std::size_t idi = vertex_id[c->vertex(i)]; + inc_cells[idi].push_back(c); } } diff --git a/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/split_long_edges.h b/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/split_long_edges.h index 1b42de85416..f75c940d080 100644 --- a/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/split_long_edges.h +++ b/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/split_long_edges.h @@ -91,39 +91,39 @@ typename C3t3::Vertex_handle split_edge(const typename C3t3::Edge& e, } while (circ != end); - for(Cell_handle circ : inc_cells) + for(Cell_handle c : inc_cells) { - const int index_v1 = circ->index(v1); - const int index_v2 = circ->index(v2); + const int index_v1 = c->index(v1); + const int index_v2 = c->index(v2); //keys are the opposite facets to the ones not containing e, //because they will not be modified - const Subdomain_index subdomain = c3t3.subdomain_index(circ); - const Facet opp_facet1 = tr.mirror_facet(Facet(circ, index_v1)); - const Facet opp_facet2 = tr.mirror_facet(Facet(circ, index_v2)); + const Subdomain_index subdomain = c3t3.subdomain_index(c); + const Facet opp_facet1 = tr.mirror_facet(Facet(c, index_v1)); + const Facet opp_facet2 = tr.mirror_facet(Facet(c, index_v2)); // volume data cells_info.insert(std::make_pair(opp_facet1, subdomain)); cells_info.insert(std::make_pair(opp_facet2, subdomain)); - if (c3t3.is_in_complex(circ)) - c3t3.remove_from_complex(circ); + if (c3t3.is_in_complex(c)) + c3t3.remove_from_complex(c); // surface data for facets of the cells to be split const int findex = CGAL::Triangulation_utils_3::next_around_edge(index_v1, index_v2); - if (c3t3.is_in_complex(circ, findex)) + if (c3t3.is_in_complex(c, findex)) { if (dimension == 3) dimension = 2; } - Surface_patch_index patch = c3t3.surface_patch_index(circ, findex); - Vertex_handle opp_vertex = circ->vertex(findex); + Surface_patch_index patch = c3t3.surface_patch_index(c, findex); + Vertex_handle opp_vertex = c->vertex(findex); facets_info.insert(std::make_pair(opp_facet1, std::make_pair(opp_vertex, patch))); facets_info.insert(std::make_pair(opp_facet2, std::make_pair(opp_vertex, patch))); - if(c3t3.is_in_complex(circ, findex)) - c3t3.remove_from_complex(circ, findex); + if(c3t3.is_in_complex(c, findex)) + c3t3.remove_from_complex(c, findex); } // insert midpoint diff --git a/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/tetrahedral_remeshing_helpers.h b/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/tetrahedral_remeshing_helpers.h index 40201743944..28fe97dde59 100644 --- a/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/tetrahedral_remeshing_helpers.h +++ b/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/tetrahedral_remeshing_helpers.h @@ -62,11 +62,13 @@ const int indices_table[4][3] = { { 3, 1, 2 }, { 3, 0, 1 }, { 2, 1, 0 } }; -int indices(const int& i, const int& j) +int indices(const unsigned int& i, const unsigned int& j) { - CGAL_assertion(i >= 0 && i < 4); - CGAL_assertion(j >= 0 && j < 3); - return indices_table[i][j]; + CGAL_assertion(i < 4 && j < 3); + if(i < 4 && j < 3) + return indices_table[i][j]; + else + return -1; } template diff --git a/Tetrahedral_remeshing/test/Tetrahedral_remeshing/test_tetrahedral_remeshing.cpp b/Tetrahedral_remeshing/test/Tetrahedral_remeshing/test_tetrahedral_remeshing.cpp index 5e621db6ce8..c94e1928d6d 100644 --- a/Tetrahedral_remeshing/test/Tetrahedral_remeshing/test_tetrahedral_remeshing.cpp +++ b/Tetrahedral_remeshing/test/Tetrahedral_remeshing/test_tetrahedral_remeshing.cpp @@ -1,5 +1,7 @@ -//#define CGAL_TETRAHEDRAL_REMESHING_VERBOSE -#define CGAL_TETRAHEDRAL_REMESHING_GENERATE_INPUT_FILES +#define CGAL_TETRAHEDRAL_REMESHING_VERBOSE +#define CGAL_DUMP_REMESHING_STEPS +#define CGAL_TETRAHEDRAL_REMESHING_DEBUG +//#define CGAL_TETRAHEDRAL_REMESHING_GENERATE_INPUT_FILES #include @@ -25,8 +27,11 @@ void generate_input_one_subdomain(const std::size_t nbv, T3& tr) std::vector pts; while (pts.size() < nbv) { - const Point p(rng.get_double(-1., 1.), rng.get_double(-1., 1.), rng.get_double(-1., 1.)); - pts.push_back(p); + const float x = rng.uniform_real(-1.f, 1.f); + const float y = rng.uniform_real(-1.f, 1.f); + const float z = rng.uniform_real(-1.f, 1.f); + + pts.push_back(Point(x, y, z)); } tr.insert(pts.begin(), pts.end()); From 4396909ea629f926a9490eb6f695593af3711fa8 Mon Sep 17 00:00:00 2001 From: Jane Tournois Date: Mon, 20 Apr 2020 14:51:31 +0200 Subject: [PATCH 301/568] fix conversion warnings (and some indentation) --- .../Tetrahedral_remeshing/internal/FMLS.h | 41 +++++++++++-------- 1 file changed, 24 insertions(+), 17 deletions(-) diff --git a/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/FMLS.h b/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/FMLS.h index 2ce1d842ee5..82e860dd575 100644 --- a/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/FMLS.h +++ b/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/FMLS.h @@ -53,9 +53,10 @@ inline float wendland(float x, float h) return 0.0; } -inline void setPNSample(std::vector& p, unsigned int i, - float x, float y, float z, - float nx, float ny, float nz) +inline void setPNSample(std::vector& p, + const std::size_t& i, + const float x, const float y, const float z, + const float nx, const float ny, const float nz) { p[6 * i] = x; p[6 * i + 1] = y; @@ -226,13 +227,17 @@ public: // The strid indicates the offsets in qv (the defautl value of 3 means that the qv // is compact: pv={x0,y0,z0,x1,y1,z1...}. If pv contains also normals for instance, // the stride should be set to 6. - void fastProjectionCPU(const std::vector& pv, unsigned int pvSize, - std::vector& qv, unsigned int stride = 3) const + void fastProjectionCPU(const std::vector& pv, + const std::size_t pvSize, + std::vector& qv, + std::size_t stride = 3) const { - for (int i = 0; i < int(pvSize); i++) { + for (std::size_t i = 0; i < pvSize; i++) + { Vector_3 p(pv[stride * i], pv[stride * i + 1], pv[stride * i + 2]); Vector_3 q, n; - for (unsigned int j = 0; j < numIter; j++) { + for (unsigned int j = 0; j < numIter; j++) + { q = CGAL::NULL_VECTOR; n = CGAL::NULL_VECTOR; fastProjectionCPU(p, q, n); @@ -240,7 +245,6 @@ public: } setPNSample(qv, i, q[0], q[1], q[2], n[0], n[1], n[2]); } - } // Brute force version. O(PNSize) complexity. For comparison only. @@ -528,6 +532,7 @@ void createMLSSurfaces(Subdomain__FMLS& subdomain_FMLS, typedef typename Tr::Geom_traits Gt; typedef typename Gt::Point_3 Point_3; typedef typename Gt::Vector_3 Vector_3; + typedef typename Gt::FT FT; typedef typename VerticesSurfaceIndices::mapped_type VertexSurfaces; typedef typename VerticesSurfaceIndices::const_iterator VerticesSurfaceIterator; @@ -582,12 +587,12 @@ void createMLSSurfaces(Subdomain__FMLS& subdomain_FMLS, it != subdomain_sample_numbers.end(); ++it) { current_subdomain_FMLS_indices[it->first] = count; - pns.push_back(std::vector(it->second * 6, 0)); + pns.push_back(std::vector(it->second * 6, 0.f)); count++; } std::vector current_v_count(count, 0); - std::vector point_spacing(count, 0); + std::vector point_spacing(count, 0.f); std::vector point_spacing_count(count, 0); //Allocation of the PN @@ -692,7 +697,7 @@ void createMLSSurfaces(Subdomain__FMLS& subdomain_FMLS, { Vector_3 space_1 = barycenter - points[i]; - point_spacing[fmls_id] += CGAL::to_double(CGAL::sqrt(space_1 * space_1)); + point_spacing[fmls_id] += CGAL::sqrt(space_1 * space_1); point_spacing_count[fmls_id] ++; } } @@ -715,9 +720,9 @@ void createMLSSurfaces(Subdomain__FMLS& subdomain_FMLS, Vector_3 space_2 = p - points[i1]; Vector_3 space_3 = p - points[i2]; - point_spacing[fmls_id] += CGAL::to_double(CGAL::sqrt(space_1 * space_1)); - point_spacing[fmls_id] += CGAL::to_double(CGAL::sqrt(space_2 * space_2)); - point_spacing[fmls_id] += CGAL::to_double(CGAL::sqrt(space_3 * space_3)); + point_spacing[fmls_id] += CGAL::sqrt(space_1 * space_1); + point_spacing[fmls_id] += CGAL::sqrt(space_2 * space_2); + point_spacing[fmls_id] += CGAL::sqrt(space_3 * space_3); point_spacing_count[fmls_id] += 3; } @@ -753,7 +758,7 @@ void createMLSSurfaces(Subdomain__FMLS& subdomain_FMLS, { nb_of_mls_to_create++; - double current_point_spacing = point_spacing[it->second] / point_spacing_count[it->second]; + float current_point_spacing = point_spacing[it->second] / point_spacing_count[it->second]; point_spacing[it->second] = current_point_spacing; average_point_spacing += current_point_spacing; @@ -771,10 +776,12 @@ void createMLSSurfaces(Subdomain__FMLS& subdomain_FMLS, { if (current_v_count[it->second] > 3) { - double current_point_spacing = point_spacing[it->second]; + float current_point_spacing = point_spacing[it->second]; //subdomain_FMLS[count].toggleHermite(true); - subdomain_FMLS[count].setPN(pns[it->second], current_v_count[it->second], current_point_spacing); + subdomain_FMLS[count].setPN(pns[it->second], + current_v_count[it->second], + current_point_spacing); // subdomain_FMLS[count].toggleHermite(true); subdomain_FMLS_indices[it->first] = count; From 74d89220e2acc3623aefcdad085b422f5ba0afed Mon Sep 17 00:00:00 2001 From: Guillaume Damiand Date: Mon, 20 Apr 2020 15:25:40 +0200 Subject: [PATCH 302/568] Remove warnings --- .../include/CGAL/Compact_container.h | 12 +++---- STL_Extension/include/CGAL/Object.h | 8 ++--- .../CGAL/Triangulation_ds_circulators_2.h | 36 +++++++++---------- 3 files changed, 28 insertions(+), 28 deletions(-) diff --git a/STL_Extension/include/CGAL/Compact_container.h b/STL_Extension/include/CGAL/Compact_container.h index ee83c6c4d0b..be9c223f623 100644 --- a/STL_Extension/include/CGAL/Compact_container.h +++ b/STL_Extension/include/CGAL/Compact_container.h @@ -882,12 +882,12 @@ namespace internal { } // Construction from nullptr - CC_iterator (std::nullptr_t CGAL_assertion_code(n)) + CC_iterator (std::nullptr_t /*CGAL_assertion_code(n)*/) #ifdef CGAL_COMPACT_CONTAINER_DEBUG_TIME_STAMP : ts(0) #endif { - CGAL_assertion (n == nullptr); + //CGAL_assertion (n == nullptr); m_ptr.p = nullptr; } @@ -1090,18 +1090,18 @@ namespace internal { template < class DSC, bool Const > inline bool operator==(const CC_iterator &rhs, - std::nullptr_t CGAL_assertion_code(n)) + std::nullptr_t /*CGAL_assertion_code(n)*/) { - CGAL_assertion( n == nullptr); + //CGAL_assertion( n == nullptr); return rhs.operator->() == nullptr; } template < class DSC, bool Const > inline bool operator!=(const CC_iterator &rhs, - std::nullptr_t CGAL_assertion_code(n)) + std::nullptr_t /*CGAL_assertion_code(n)*/) { - CGAL_assertion( n == nullptr); + //CGAL_assertion( n == nullptr); return rhs.operator->() != nullptr; } diff --git a/STL_Extension/include/CGAL/Object.h b/STL_Extension/include/CGAL/Object.h index 5a901eb3110..346afe964dd 100644 --- a/STL_Extension/include/CGAL/Object.h +++ b/STL_Extension/include/CGAL/Object.h @@ -132,10 +132,10 @@ class Object #ifndef CGAL_NO_DEPRECATED_CODE // The comparisons with nullptr are only there for Nef... - bool operator==(std::nullptr_t CGAL_assertion_code(n)) const - { CGAL_assertion(n == 0); return empty(); } - bool operator!=(std::nullptr_t CGAL_assertion_code(n)) const - { CGAL_assertion(n == 0); return !empty(); } + bool operator==(std::nullptr_t /*CGAL_assertion_code(n)*/) const + { /*CGAL_assertion(n == 0);*/ return empty(); } + bool operator!=(std::nullptr_t /*CGAL_assertion_code(n)*/) const + { /*CGAL_assertion(n == 0);*/ return !empty(); } #endif // CGAL_NO_DEPRECATED_CODE }; diff --git a/TDS_2/include/CGAL/Triangulation_ds_circulators_2.h b/TDS_2/include/CGAL/Triangulation_ds_circulators_2.h index 6ecb08f6757..bf5aa71b9a2 100644 --- a/TDS_2/include/CGAL/Triangulation_ds_circulators_2.h +++ b/TDS_2/include/CGAL/Triangulation_ds_circulators_2.h @@ -71,8 +71,8 @@ public: bool operator!=(const Face_handle &fh) const { return pos != fh; } bool is_empty() const; - bool operator==(std::nullptr_t CGAL_triangulation_assertion_code(n)) const; - bool operator!=(std::nullptr_t CGAL_triangulation_assertion_code(n)) const; + bool operator==(std::nullptr_t /*CGAL_triangulation_assertion_code(n)*/) const; + bool operator!=(std::nullptr_t /*CGAL_triangulation_assertion_code(n)*/) const; Face& operator*() const @@ -152,8 +152,8 @@ public: { return pos->vertex(_ri) != vh; } bool is_empty() const; - bool operator==(std::nullptr_t CGAL_triangulation_assertion_code(n)) const; - bool operator!=(std::nullptr_t CGAL_triangulation_assertion_code(n)) const; + bool operator==(std::nullptr_t /*CGAL_triangulation_assertion_code(n)*/) const; + bool operator!=(std::nullptr_t /*CGAL_triangulation_assertion_code(n)*/) const; Vertex& operator*() const @@ -231,8 +231,8 @@ public: bool operator==(const Edge_circulator &vc) const; bool operator!=(const Edge_circulator &vc) const; bool is_empty() const; - bool operator==(std::nullptr_t CGAL_triangulation_assertion_code(n)) const; - bool operator!=(std::nullptr_t CGAL_triangulation_assertion_code(n)) const; + bool operator==(std::nullptr_t /*CGAL_triangulation_assertion_code(n)*/) const; + bool operator!=(std::nullptr_t /*CGAL_triangulation_assertion_code(n)*/) const; Edge* operator->() const { edge.first=pos; @@ -338,18 +338,18 @@ return (_v == Vertex_handle() || pos == Face_handle() ); template < class Tds > inline bool Triangulation_ds_face_circulator_2 :: -operator==(std::nullptr_t CGAL_triangulation_assertion_code(n)) const +operator==(std::nullptr_t /*CGAL_triangulation_assertion_code(n)*/) const { - CGAL_triangulation_assertion( n == nullptr); + //CGAL_triangulation_assertion( n == nullptr); return (_v == Vertex_handle() || pos == Face_handle() ); } template < class Tds > inline bool Triangulation_ds_face_circulator_2 :: -operator!=(std::nullptr_t CGAL_triangulation_assertion_code(n)) const +operator!=(std::nullptr_t /*CGAL_triangulation_assertion_code(n)*/) const { - CGAL_triangulation_assertion( n == nullptr); + //CGAL_triangulation_assertion( n == nullptr); return ! (*this == nullptr); } @@ -462,18 +462,18 @@ is_empty() const template < class Tds > inline bool Triangulation_ds_vertex_circulator_2 :: -operator==(std::nullptr_t CGAL_triangulation_assertion_code(n)) const +operator==(std::nullptr_t /*CGAL_triangulation_assertion_code(n)*/) const { - CGAL_triangulation_assertion( n == nullptr); + //CGAL_triangulation_assertion( n == nullptr); return (_v == Vertex_handle() || pos == Face_handle()); } template < class Tds > inline bool Triangulation_ds_vertex_circulator_2 :: -operator!=(std::nullptr_t CGAL_triangulation_assertion_code(n)) const +operator!=(std::nullptr_t /*CGAL_triangulation_assertion_code(n)*/) const { - CGAL_triangulation_assertion( n == nullptr); + //CGAL_triangulation_assertion( n == nullptr); return !(*this == nullptr); } @@ -584,18 +584,18 @@ is_empty() const template < class Tds > inline bool Triangulation_ds_edge_circulator_2 :: -operator==(std::nullptr_t CGAL_triangulation_assertion_code(n)) const +operator==(std::nullptr_t /*CGAL_triangulation_assertion_code(n)*/) const { - CGAL_triangulation_assertion( n == nullptr); + //CGAL_triangulation_assertion( n == nullptr); return (_v == Vertex_handle() || pos == Face_handle()); } template < class Tds > inline bool Triangulation_ds_edge_circulator_2 :: -operator!=(std::nullptr_t CGAL_triangulation_assertion_code(n)) const +operator!=(std::nullptr_t /*CGAL_triangulation_assertion_code(n)*/) const { - CGAL_triangulation_assertion( n == nullptr); + //CGAL_triangulation_assertion( n == nullptr); return !(*this == nullptr); } From 7253f16801a2ec2cc7c4a9b04f991c9eaf64b8f4 Mon Sep 17 00:00:00 2001 From: Simon Giraudot Date: Tue, 21 Apr 2020 15:03:48 +0200 Subject: [PATCH 303/568] Update new package OBB's cmake scripts with Eigen imported target --- .../benchmarks/Optimal_bounding_box/CMakeLists.txt | 5 +++-- .../examples/Optimal_bounding_box/CMakeLists.txt | 5 +++-- .../test/Optimal_bounding_box/CMakeLists.txt | 5 +++-- 3 files changed, 9 insertions(+), 6 deletions(-) diff --git a/Optimal_bounding_box/benchmarks/Optimal_bounding_box/CMakeLists.txt b/Optimal_bounding_box/benchmarks/Optimal_bounding_box/CMakeLists.txt index 84cb0ab7dfc..86632a0be7c 100644 --- a/Optimal_bounding_box/benchmarks/Optimal_bounding_box/CMakeLists.txt +++ b/Optimal_bounding_box/benchmarks/Optimal_bounding_box/CMakeLists.txt @@ -16,10 +16,11 @@ endif() include( ${CGAL_USE_FILE} ) find_package(Eigen3 3.1.0 REQUIRED) #(3.1.0 or greater) -if (NOT EIGEN3_FOUND) +include(CGAL_Eigen_support) +if (NOT TARGET CGAL::Eigen_support) message(STATUS "This project requires the Eigen library, and will not be compiled.") return() endif() create_single_source_cgal_program("bench_obb.cpp") -CGAL_target_use_Eigen(bench_obb) +target_link_libraries(bench_obb PUBLIC CGAL::Eigen_support) diff --git a/Optimal_bounding_box/examples/Optimal_bounding_box/CMakeLists.txt b/Optimal_bounding_box/examples/Optimal_bounding_box/CMakeLists.txt index 9a67221542e..9b657c24e1b 100644 --- a/Optimal_bounding_box/examples/Optimal_bounding_box/CMakeLists.txt +++ b/Optimal_bounding_box/examples/Optimal_bounding_box/CMakeLists.txt @@ -14,7 +14,8 @@ endif() include( ${CGAL_USE_FILE} ) find_package(Eigen3 3.1.0 REQUIRED) #(3.1.0 or greater) -if (NOT EIGEN3_FOUND) +include(CGAL_Eigen_support) +if (NOT TARGET CGAL::Eigen_support) message(STATUS "This project requires the Eigen library, and will not be compiled.") return() endif() @@ -27,5 +28,5 @@ foreach(target obb_example obb_with_point_maps_example rotated_aabb_tree_example) - CGAL_target_use_Eigen(${target}) + target_link_libraries(${target} PUBLIC CGAL::Eigen_support) endforeach() diff --git a/Optimal_bounding_box/test/Optimal_bounding_box/CMakeLists.txt b/Optimal_bounding_box/test/Optimal_bounding_box/CMakeLists.txt index c0ce4c74b4a..1ba260a6b92 100644 --- a/Optimal_bounding_box/test/Optimal_bounding_box/CMakeLists.txt +++ b/Optimal_bounding_box/test/Optimal_bounding_box/CMakeLists.txt @@ -14,7 +14,8 @@ endif() include( ${CGAL_USE_FILE} ) find_package(Eigen3 3.1.0 REQUIRED) #(3.1.0 or greater) -if (NOT EIGEN3_FOUND) +include(CGAL_Eigen_support) +if (NOT TARGET CGAL::Eigen_support) message(STATUS "This project requires the Eigen library, and will not be compiled.") return() endif() @@ -27,5 +28,5 @@ foreach(target test_OBB_traits test_nelder_mead test_optimization_algorithms) - CGAL_target_use_Eigen(${target}) + target_link_libraries(${target} PUBLIC CGAL::Eigen_support) endforeach() From 6fcbee1fa951a8032d01557bff75b614cc67e7f4 Mon Sep 17 00:00:00 2001 From: Efi Fogel Date: Tue, 21 Apr 2020 17:12:21 +0300 Subject: [PATCH 304/568] Removed redundant typedef statements --- .../include/CGAL/Arr_circular_line_arc_traits_2.h | 6 ------ .../CGAL/Arr_geometry_traits/Conic_x_monotone_arc_2.h | 1 - .../CGAL/Boolean_set_operations_2/Gps_simplifier_traits.h | 2 +- 3 files changed, 1 insertion(+), 8 deletions(-) diff --git a/Arrangement_on_surface_2/include/CGAL/Arr_circular_line_arc_traits_2.h b/Arrangement_on_surface_2/include/CGAL/Arr_circular_line_arc_traits_2.h index 9e8f8085807..eb9acae74a8 100644 --- a/Arrangement_on_surface_2/include/CGAL/Arr_circular_line_arc_traits_2.h +++ b/Arrangement_on_surface_2/include/CGAL/Arr_circular_line_arc_traits_2.h @@ -301,12 +301,6 @@ namespace CGAL { const boost::variant< Arc1, Arc2 > &c2, OutputIterator oi) const { - typedef CircularKernel CK; - typedef unsigned int Multiplicity; - typedef std::pair - Intersection_point; - typedef boost::variant X_monotone_curve_2; - if ( const Arc1* arc1 = boost::get( &c1 ) ){ if ( const Arc1* arc2 = boost::get( &c2 ) ){ return CircularKernel().intersect_2_object()(*arc1, *arc2, oi); diff --git a/Arrangement_on_surface_2/include/CGAL/Arr_geometry_traits/Conic_x_monotone_arc_2.h b/Arrangement_on_surface_2/include/CGAL/Arr_geometry_traits/Conic_x_monotone_arc_2.h index a2e2d7790d4..b6587f4e1ab 100644 --- a/Arrangement_on_surface_2/include/CGAL/Arr_geometry_traits/Conic_x_monotone_arc_2.h +++ b/Arrangement_on_surface_2/include/CGAL/Arr_geometry_traits/Conic_x_monotone_arc_2.h @@ -844,7 +844,6 @@ public: Intersection_map& inter_map, OutputIterator oi) const { - typedef unsigned int Multiplicity; typedef boost::variant Intersection_result; if (_has_same_supporting_conic(arc)) { diff --git a/Boolean_set_operations_2/include/CGAL/Boolean_set_operations_2/Gps_simplifier_traits.h b/Boolean_set_operations_2/include/CGAL/Boolean_set_operations_2/Gps_simplifier_traits.h index 1238537aba2..fdc111751de 100644 --- a/Boolean_set_operations_2/include/CGAL/Boolean_set_operations_2/Gps_simplifier_traits.h +++ b/Boolean_set_operations_2/include/CGAL/Boolean_set_operations_2/Gps_simplifier_traits.h @@ -182,7 +182,7 @@ public: const Base_x_monotone_curve_2* overlap_cv = boost::get(&xection); - CGAL_assertion_code(overlap_cv != nullptr); + CGAL_assertion(overlap_cv != nullptr); unsigned int ov_bc; unsigned int ov_twin_bc; if (base_cmp_endpoints(cv1) == base_cmp_endpoints(cv2)) { From fe1f731e22c2e2bdf0d0bfb7c2e896f09f6dce43 Mon Sep 17 00:00:00 2001 From: Laurent Rineau Date: Tue, 21 Apr 2020 17:08:57 +0200 Subject: [PATCH 305/568] Fix timestamps --- Mesh_3/include/CGAL/Mesh_cell_base_3.h | 3 --- Mesh_3/include/CGAL/Mesh_vertex_base_3.h | 1 - .../Remeshing_cell_base_3.h | 21 +------------------ .../Remeshing_vertex_base_3.h | 17 +-------------- 4 files changed, 2 insertions(+), 40 deletions(-) diff --git a/Mesh_3/include/CGAL/Mesh_cell_base_3.h b/Mesh_3/include/CGAL/Mesh_cell_base_3.h index dbb244bd66a..5c719d22fe6 100644 --- a/Mesh_3/include/CGAL/Mesh_cell_base_3.h +++ b/Mesh_3/include/CGAL/Mesh_cell_base_3.h @@ -141,7 +141,6 @@ public: , next_intrusive_() , previous_intrusive_() #endif - , time_stamp_(-1) {} Mesh_cell_base_3 (Vertex_handle v0, @@ -156,7 +155,6 @@ public: , next_intrusive_() , previous_intrusive_() #endif - , time_stamp_(-1) {} Mesh_cell_base_3 (Vertex_handle v0, @@ -175,7 +173,6 @@ public: , next_intrusive_() , previous_intrusive_() #endif - , time_stamp_(-1) {} // Default copy constructor and assignment operator are ok diff --git a/Mesh_3/include/CGAL/Mesh_vertex_base_3.h b/Mesh_3/include/CGAL/Mesh_vertex_base_3.h index 977782a8932..9ad67147d1b 100644 --- a/Mesh_3/include/CGAL/Mesh_vertex_base_3.h +++ b/Mesh_3/include/CGAL/Mesh_vertex_base_3.h @@ -127,7 +127,6 @@ public: , next_intrusive_() , previous_intrusive_() #endif //CGAL_INTRUSIVE_LIST - , time_stamp_(-1) {} // Default copy constructor and assignment operator are ok diff --git a/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/Remeshing_cell_base_3.h b/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/Remeshing_cell_base_3.h index df3678dec4f..038182d89fc 100644 --- a/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/Remeshing_cell_base_3.h +++ b/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/Remeshing_cell_base_3.h @@ -50,26 +50,7 @@ It has the default value `Triangulation_cell_base_3`. */ template > -class Remeshing_cell_base_3 -#ifndef DOXYGEN_RUNNING - : public CGAL::Mesh_cell_base_3 -#endif -{ - typedef CGAL::Mesh_cell_base_3 Base; - typedef typename Base::Vertex_handle Vertex_handle; - typedef typename Base::Cell_handle Cell_handle; - -public: - // To get correct cell type in TDS - template < class TDS2 > - struct Rebind_TDS - { - typedef typename Cb::template Rebind_TDS::Other Cb2; - typedef Remeshing_cell_base_3 Other; - }; - - using Base::Base; -}; +using Remeshing_cell_base_3 = CGAL::Mesh_cell_base_3; }//end namespace Tetrahedral_remeshing }//end namespace CGAL diff --git a/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/Remeshing_vertex_base_3.h b/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/Remeshing_vertex_base_3.h index 148ca815d39..ed1baa454a6 100644 --- a/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/Remeshing_vertex_base_3.h +++ b/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/Remeshing_vertex_base_3.h @@ -53,22 +53,7 @@ It has the default value `Triangulation_vertex_base_3`. template > -class Remeshing_vertex_base_3 -#ifndef DOXYGEN_RUNNING - : public CGAL::Mesh_vertex_base_3 -#endif -{ - typedef CGAL::Mesh_vertex_base_3 Base; - -public: - // To get correct vertex type in TDS - template < class TDS3 > - struct Rebind_TDS { - typedef typename Vb::template Rebind_TDS::Other Vb3; - typedef Remeshing_vertex_base_3 Other; - }; - -}; +using Remeshing_vertex_base_3 = CGAL::Mesh_vertex_base_3; }//end namespace Tetrahedral_remeshing From 3790250916caec6b8e0a661c0f7521bbec8eb8f9 Mon Sep 17 00:00:00 2001 From: Laurent Rineau Date: Tue, 21 Apr 2020 17:09:13 +0200 Subject: [PATCH 306/568] Fix a warning --- .../include/CGAL/Tetrahedral_remeshing/internal/FMLS.h | 1 - 1 file changed, 1 deletion(-) diff --git a/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/FMLS.h b/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/FMLS.h index 82e860dd575..8e02dc5a9cd 100644 --- a/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/FMLS.h +++ b/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/FMLS.h @@ -532,7 +532,6 @@ void createMLSSurfaces(Subdomain__FMLS& subdomain_FMLS, typedef typename Tr::Geom_traits Gt; typedef typename Gt::Point_3 Point_3; typedef typename Gt::Vector_3 Vector_3; - typedef typename Gt::FT FT; typedef typename VerticesSurfaceIndices::mapped_type VertexSurfaces; typedef typename VerticesSurfaceIndices::const_iterator VerticesSurfaceIterator; From 5d37a1bbf82239ac6d5b45e7c27be4904728ebfa Mon Sep 17 00:00:00 2001 From: Efi Fogel Date: Wed, 22 Apr 2020 00:31:33 +0300 Subject: [PATCH 307/568] Initialized some fileds of _Linear_object_cached_2 --- .../include/CGAL/Arr_linear_traits_2.h | 27 +++++++------------ 1 file changed, 9 insertions(+), 18 deletions(-) diff --git a/Arrangement_on_surface_2/include/CGAL/Arr_linear_traits_2.h b/Arrangement_on_surface_2/include/CGAL/Arr_linear_traits_2.h index 4c73bcb4880..0e1262db0ec 100644 --- a/Arrangement_on_surface_2/include/CGAL/Arr_linear_traits_2.h +++ b/Arrangement_on_surface_2/include/CGAL/Arr_linear_traits_2.h @@ -140,23 +140,20 @@ public: * \param seg The segment. * \pre The segment is not degenerate. */ - _Linear_object_cached_2(const Segment_2& seg) + _Linear_object_cached_2(const Segment_2& seg) : + has_source(true), + has_target(true) { Kernel kernel; CGAL_assertion_msg(! kernel.is_degenerate_2_object()(seg), "Cannot construct a degenerate segment."); - typename Kernel_::Construct_vertex_2 - construct_vertex = kernel.construct_vertex_2_object(); - + auto construct_vertex = kernel.construct_vertex_2_object(); ps = construct_vertex(seg, 0); - has_source = true; pt = construct_vertex(seg, 1); - has_target = true; Comparison_result res = kernel.compare_xy_2_object()(ps, pt); - CGAL_assertion(res != EQUAL); is_degen = false; is_right = (res == SMALLER); @@ -171,20 +168,18 @@ public: * \param ray The ray. * \pre The ray is not degenerate. */ - _Linear_object_cached_2(const Ray_2& ray) + _Linear_object_cached_2(const Ray_2& ray) : + has_source(true), + has_target(false) { Kernel kernel; CGAL_assertion_msg(! kernel.is_degenerate_2_object()(ray), "Cannot construct a degenerate ray."); - typename Kernel_::Construct_point_on_2 - construct_vertex = kernel.construct_point_on_2_object(); - + auto construct_vertex = kernel.construct_point_on_2_object(); ps = construct_vertex(ray, 0); // The source point. - has_source = true; pt = construct_vertex(ray, 1); // Some point on the ray. - has_target = false; Comparison_result res = kernel.compare_xy_2_object()(ps, pt); CGAL_assertion(res != EQUAL); @@ -211,13 +206,9 @@ public: CGAL_assertion_msg(! kernel.is_degenerate_2_object()(ln), "Cannot construct a degenerate line."); - typename Kernel_::Construct_point_on_2 - construct_vertex = kernel.construct_point_on_2_object(); - + auto construct_vertex = kernel.construct_point_on_2_object(); ps = construct_vertex(ln, 0); // Some point on the line. - has_source = false; pt = construct_vertex(ln, 1); // Some point further on the line. - has_target = false; Comparison_result res = kernel.compare_xy_2_object()(ps, pt); CGAL_assertion(res != EQUAL); From 288c520cd017f35a9afc41f45d6bb4285a5743f4 Mon Sep 17 00:00:00 2001 From: Jane Tournois Date: Mon, 20 Apr 2020 15:23:41 +0200 Subject: [PATCH 308/568] fix more warnings --- .../include/CGAL/Tetrahedral_remeshing/internal/FMLS.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/FMLS.h b/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/FMLS.h index 8e02dc5a9cd..da72aeddf5a 100644 --- a/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/FMLS.h +++ b/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/FMLS.h @@ -329,11 +329,11 @@ private: void computePNScale() { Vector_3 c = CGAL::NULL_VECTOR; - for (unsigned int i = 0; i < PNSize; i++) + for (std::size_t i = 0; i < PNSize; i++) c += Vector_3(PN[6 * i], PN[6 * i + 1], PN[6 * i + 2]); c /= PNSize; PNScale = 0.f; - for (unsigned int i = 0; i < PNSize; i++) { + for (std::size_t i = 0; i < PNSize; i++) { float r = distance(c, Vector_3(PN[6 * i], PN[6 * i + 1], PN[6 * i + 2])); if (r > PNScale) PNScale = r; From 977185466a107755a14d88701997b164f6beb199 Mon Sep 17 00:00:00 2001 From: Jane Tournois Date: Wed, 22 Apr 2020 09:34:46 +0200 Subject: [PATCH 309/568] fix .mesh reader - fix order of vertices depending on parity of i - add infinite facets to incident cells map before assigning neighbors --- Mesh_3/include/CGAL/Mesh_3/tet_soup_to_c3t3.h | 32 +++++++++++-------- 1 file changed, 18 insertions(+), 14 deletions(-) diff --git a/Mesh_3/include/CGAL/Mesh_3/tet_soup_to_c3t3.h b/Mesh_3/include/CGAL/Mesh_3/tet_soup_to_c3t3.h index c5cd5256df3..c9a748ebd11 100644 --- a/Mesh_3/include/CGAL/Mesh_3/tet_soup_to_c3t3.h +++ b/Mesh_3/include/CGAL/Mesh_3/tet_soup_to_c3t3.h @@ -174,10 +174,9 @@ void build_finite_cells(Tr& tr, template void add_infinite_facets_to_incident_cells_map(typename Tr::Cell_handle c, - int inf_vert_pos, - std::map, - std::vector > >& incident_cells_map) + int inf_vert_pos, + boost::unordered_map, + std::vector > >& incident_cells_map) { int l = (inf_vert_pos + 1) % 4; add_facet_to_incident_cells_map(c, l, incident_cells_map); @@ -199,6 +198,8 @@ void build_infinite_cells(Tr& tr, typedef std::pair Incident_cell; typedef boost::unordered_map > Incident_cells_map; + std::vector infinite_cells; + // check the incident cells map for facets who only have one incident cell // and build the infinite cell on the opposite side typename Incident_cells_map::iterator it = incident_cells_map.begin(); @@ -214,28 +215,31 @@ void build_infinite_cells(Tr& tr, Cell_handle opp_c; // the infinite cell that we are creating needs to be well oriented... - int inf_vert_position_in_opp_c = 0; if(i == 0 || i == 2) opp_c = tr.tds().create_cell(tr.infinite_vertex(), - c->vertex((i+1)%4), - c->vertex((i+2)%4), - c->vertex((i+3)%4)); + c->vertex((i + 2) % 4), + c->vertex((i + 1) % 4), + c->vertex((i + 3) % 4)); else opp_c = tr.tds().create_cell(tr.infinite_vertex(), - c->vertex((i+1)%4), - c->vertex((i+3)%4), - c->vertex((i+2)%4)); + c->vertex((i + 3) % 4), + c->vertex((i + 1) % 4), + c->vertex((i + 2) % 4)); + + infinite_cells.push_back(opp_c); // set the infinite_vertex's incident cell if(tr.infinite_vertex()->cell() == Cell_handle()) tr.infinite_vertex()->set_cell(opp_c); - // add the facets to the incident cells map - // the only finite facet - it->second.push_back(std::make_pair(opp_c, inf_vert_position_in_opp_c)); + it->second.push_back(std::make_pair(opp_c, 0)); CGAL_assertion(it->second.size() == 2); } + + // add the facets to the incident cells map + for (const Cell_handle c : infinite_cells) + add_infinite_facets_to_incident_cells_map(c, 0, incident_cells_map); } template From c1d8fb69b78c0a4e9769bc245cdee01eadca8478 Mon Sep 17 00:00:00 2001 From: Simon Giraudot Date: Wed, 22 Apr 2020 13:47:33 +0200 Subject: [PATCH 310/568] Move transform ranges in property_maps --- Property_map/include/CGAL/property_map.h | 34 ++++++++++++++++++++++++ STL_Extension/include/CGAL/iterator.h | 33 ----------------------- 2 files changed, 34 insertions(+), 33 deletions(-) diff --git a/Property_map/include/CGAL/property_map.h b/Property_map/include/CGAL/property_map.h index f58413b9755..988c7ab6583 100644 --- a/Property_map/include/CGAL/property_map.h +++ b/Property_map/include/CGAL/property_map.h @@ -27,6 +27,8 @@ #include // defines std::pair +#include +#include #include #include #include @@ -576,6 +578,38 @@ make_cartesian_converter_property_map(Vpm vpm) return Cartesian_converter_property_map(vpm); } +/// \cond SKIP_IN_MANUAL +// Syntaxic sugar for transform_iterator+pmap_to_unary_function +template +typename boost::transform_iterator, Iterator> +make_transform_iterator_from_property_map (Iterator it, Pmap pmap) +{ + return boost::make_transform_iterator (it, CGAL::Property_map_to_unary_function(pmap)); +} + +// Syntaxic sugar for make_range+transform_iterator+pmap_to_unary_function +template +CGAL::Iterator_range, + typename Range::const_iterator> > +make_transform_range_from_property_map (const Range& range, Pmap pmap) +{ + return CGAL::make_range + (make_transform_iterator_from_property_map (range.begin(), pmap), + make_transform_iterator_from_property_map (range.end(), pmap)); +} + +// Syntaxic sugar for make_range+transform_iterator+pmap_to_unary_function +template +CGAL::Iterator_range, + typename Range::iterator> > +make_transform_range_from_property_map (Range& range, Pmap pmap) +{ + return CGAL::make_range + (make_transform_iterator_from_property_map (range.begin(), pmap), + make_transform_iterator_from_property_map (range.end(), pmap)); +} +/// \endcond + } // namespace CGAL diff --git a/STL_Extension/include/CGAL/iterator.h b/STL_Extension/include/CGAL/iterator.h index 14c76b745e5..ea2b445b6f5 100644 --- a/STL_Extension/include/CGAL/iterator.h +++ b/STL_Extension/include/CGAL/iterator.h @@ -22,10 +22,8 @@ #include #include -#include #include #include -#include #include #include #include @@ -1482,37 +1480,6 @@ struct Range_iterator_type { typedef typename RangeRef::iterato template struct Range_iterator_type { typedef typename RangeRef::const_iterator type; }; -// Syntaxic sugar for transform_iterator+pmap_to_unary_function -template -typename boost::transform_iterator, Iterator> -make_transform_iterator_from_property_map (Iterator it, Pmap pmap) -{ - return boost::make_transform_iterator (it, CGAL::Property_map_to_unary_function(pmap)); -} - -// Syntaxic sugar for make_range+transform_iterator+pmap_to_unary_function -template -CGAL::Iterator_range, - typename Range::const_iterator> > -make_transform_range_from_property_map (const Range& range, Pmap pmap) -{ - return CGAL::make_range - (make_transform_iterator_from_property_map (range.begin(), pmap), - make_transform_iterator_from_property_map (range.end(), pmap)); -} - -// Syntaxic sugar for make_range+transform_iterator+pmap_to_unary_function -template -CGAL::Iterator_range, - typename Range::iterator> > -make_transform_range_from_property_map (Range& range, Pmap pmap) -{ - return CGAL::make_range - (make_transform_iterator_from_property_map (range.begin(), pmap), - make_transform_iterator_from_property_map (range.end(), pmap)); -} - - } //namespace CGAL #include From adaa8e02bb99a188e9ece850bc7d39123380f8cb Mon Sep 17 00:00:00 2001 From: Jane Tournois Date: Wed, 22 Apr 2020 15:50:43 +0200 Subject: [PATCH 311/568] remove extra template parameter --- Tetrahedral_remeshing/include/CGAL/tetrahedral_remeshing.h | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/Tetrahedral_remeshing/include/CGAL/tetrahedral_remeshing.h b/Tetrahedral_remeshing/include/CGAL/tetrahedral_remeshing.h index e9f04b59899..dcf7336a63d 100644 --- a/Tetrahedral_remeshing/include/CGAL/tetrahedral_remeshing.h +++ b/Tetrahedral_remeshing/include/CGAL/tetrahedral_remeshing.h @@ -279,8 +279,7 @@ void tetrahedral_isotropic_remeshing( } template + typename CornerIndex, typename CurveIndex> void tetrahedral_isotropic_remeshing( CGAL::Mesh_complex_3_in_triangulation_3& c3t3, const double& target_edge_length) From f4f3ec034f6b5c29bf24b4bada22bd696dd2298f Mon Sep 17 00:00:00 2001 From: Jane Tournois Date: Thu, 23 Apr 2020 06:32:19 +0200 Subject: [PATCH 312/568] fix the code when Surface_patch_index is pair --- .../tetrahedral_adaptive_remeshing_impl.h | 23 +++++++++++++++++-- 1 file changed, 21 insertions(+), 2 deletions(-) diff --git a/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/tetrahedral_adaptive_remeshing_impl.h b/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/tetrahedral_adaptive_remeshing_impl.h index 641c94e30fa..477cc450937 100644 --- a/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/tetrahedral_adaptive_remeshing_impl.h +++ b/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/tetrahedral_adaptive_remeshing_impl.h @@ -359,7 +359,10 @@ private: || get(fcmap, mf) || (m_c3t3_pbackup == NULL && f.first->is_facet_on_surface(f.second))) { - m_c3t3.add_to_complex(f, 1); + Surface_patch_index patch = f.first->surface_patch_index(f.second); + if(patch == Surface_patch_index()) + set_surface_patch_index_to_default(s1, s2, patch); + m_c3t3.add_to_complex(f, patch); const int i = f.second; for (int j = 0; j < 3; ++j) @@ -446,7 +449,6 @@ private: } private: - bool check_vertex_dimensions() { for (Vertex_handle vit : tr().finite_vertex_handles()) @@ -459,6 +461,23 @@ private: return true; } + template + void set_surface_patch_index_to_default(const Subdomain_index&, + const Subdomain_index&, + PatchIndex& patch) + { + if(m_c3t3.number_of_facets() == 0) + patch = 1; + else + patch = m_c3t3.surface_patch_index(*m_c3t3.facets_begin()); + } + + void set_surface_patch_index_to_default(const Subdomain_index& s1, + const Subdomain_index& s2, + std::pair& patch) + { + patch = (s1 < s2) ? std::make_pair(s1, s2) : std::make_pair(s2, s1); + } public: Tr& tr() From 206499d4aa5bdf408c550c6aed17b280c6943f29 Mon Sep 17 00:00:00 2001 From: Jane Tournois Date: Thu, 23 Apr 2020 06:32:19 +0200 Subject: [PATCH 313/568] fix the code when Surface_patch_index is pair --- .../CGAL/Tetrahedral_remeshing/internal/smooth_vertices.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/smooth_vertices.h b/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/smooth_vertices.h index 3ca4481c34d..3e010ecedb9 100644 --- a/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/smooth_vertices.h +++ b/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/smooth_vertices.h @@ -313,7 +313,7 @@ private: fmls.fastProjectionCPU(point, result, res_normal); if (std::isnan(result[0]) || std::isnan(result[1]) || std::isnan(result[2])) { - std::cout << "MLS error detected si " << si + std::cout << "MLS error detected si " //<< si << "\t(size : " << fmls.getPNSize() << ")" << "\t(point = " << point << " )" << std::endl; return {}; From c372c04a6bf2e0e1a89439898413e7e82511ba1d Mon Sep 17 00:00:00 2001 From: Maxime Gimeno Date: Thu, 23 Apr 2020 14:24:14 +0200 Subject: [PATCH 314/568] Change script for use zith new dicker image. --- .../developer_scripts/Bundle_polyhedron_demo_with_appimage.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Scripts/developer_scripts/Bundle_polyhedron_demo_with_appimage.sh b/Scripts/developer_scripts/Bundle_polyhedron_demo_with_appimage.sh index e2911620838..146060a4000 100644 --- a/Scripts/developer_scripts/Bundle_polyhedron_demo_with_appimage.sh +++ b/Scripts/developer_scripts/Bundle_polyhedron_demo_with_appimage.sh @@ -4,5 +4,5 @@ if [ "$1" == '--help' ]; then echo "Builds and packages the Polyhedron demo form the CGAL dir." exit 0 fi -docker run --rm -v "$2":/results:Z -v "$1":/cgal:ro docker.io/cgal/bundle-3d-demo "/scripts/build.sh -j$3 && /scripts/deploy.sh" +docker run --rm -v "$2":/results:Z -v "$1":/cgal:ro -e "NUMBER_OF_DEDICATED_CORES=$3" docker.io/cgal/bundle-3d-demo From b090c8fbacbe28de184dc79947f52b0d37d7227a Mon Sep 17 00:00:00 2001 From: Jane Tournois Date: Thu, 23 Apr 2020 14:34:20 +0200 Subject: [PATCH 315/568] make sure shell scripts remain LS through git --- .gitattributes | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.gitattributes b/.gitattributes index 35a3066ee9c..ccb9bc4d4b5 100644 --- a/.gitattributes +++ b/.gitattributes @@ -18,7 +18,6 @@ *.js text *.hmtl text *.bib text -*.sh text *.css text *.ui text *.qrc text @@ -36,6 +35,7 @@ *.pdb text # Declare files that will always have LF line endings on checkout. +*.sh text eol=lf Documentation/Doxyfile text eol=lf Documentation/pkglist_filter text eol=lf Installation/update_CHANGES text eol=lf From 02e7841421badca65f826ed1cbd382d48a2b2dff Mon Sep 17 00:00:00 2001 From: Jane Tournois Date: Thu, 23 Apr 2020 14:36:51 +0200 Subject: [PATCH 316/568] update .travis.yml --- .travis.yml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/.travis.yml b/.travis.yml index 321a2122cf6..2c2fe62d3f4 100644 --- a/.travis.yml +++ b/.travis.yml @@ -49,10 +49,10 @@ env: - PACKAGE='Surface_mesh_parameterization Surface_mesh_segmentation Surface_mesh_shortest_path ' - PACKAGE='Surface_mesh_simplification Surface_mesh_skeletonization Surface_mesh_topology ' - PACKAGE='Surface_mesher Surface_sweep_2 TDS_2 ' - - PACKAGE='Testsuite Tetrahedral_remeshing Three ' - - PACKAGE='Triangulation Triangulation_2 Triangulation_3 ' - - PACKAGE='Union_find Visibility_2 Voronoi_diagram_2 ' - - PACKAGE='wininst ' + - PACKAGE='TDS_3 Testsuite Tetrahedral_remeshing ' + - PACKAGE='Three Triangulation Triangulation_2 ' + - PACKAGE='Triangulation_3 Union_find Visibility_2 ' + - PACKAGE='Voronoi_diagram_2 wininst ' compiler: clang install: - echo "$PWD" From ea6f94a490a0bdf8676bf78e89bd7c0d83cf3e8a Mon Sep 17 00:00:00 2001 From: Efi Fogel Date: Thu, 23 Apr 2020 22:54:46 +0300 Subject: [PATCH 317/568] Changed ray-shooting strategy when landmark is not supported --- .../VerticalRayShootCallback.h | 77 +++++++++++++++++++ 1 file changed, 77 insertions(+) diff --git a/Arrangement_on_surface_2/demo/Arrangement_on_surface_2/VerticalRayShootCallback.h b/Arrangement_on_surface_2/demo/Arrangement_on_surface_2/VerticalRayShootCallback.h index 53cb0fcb76e..00b841f2d6f 100644 --- a/Arrangement_on_surface_2/demo/Arrangement_on_surface_2/VerticalRayShootCallback.h +++ b/Arrangement_on_surface_2/demo/Arrangement_on_surface_2/VerticalRayShootCallback.h @@ -127,7 +127,11 @@ protected: void highlightPointLocation( QGraphicsSceneMouseEvent *event ); Face_const_handle getFace( const CGAL::Object& o ); CGAL::Object rayShootUp( const Kernel_point_2& point ); + CGAL::Object rayShootUp( const Kernel_point_2& point, CGAL::Tag_true ); + CGAL::Object rayShootUp( const Kernel_point_2& point, CGAL::Tag_false ); CGAL::Object rayShootDown( const Kernel_point_2& point ); + CGAL::Object rayShootDown( const Kernel_point_2& point, CGAL::Tag_true ); + CGAL::Object rayShootDown( const Kernel_point_2& point, CGAL::Tag_false ); using Superclass::scene; using Superclass::shootingUp; @@ -304,6 +308,14 @@ VerticalRayShootCallback< Arr_ >::getFace( const CGAL::Object& obj ) template < typename Arr_ > CGAL::Object VerticalRayShootCallback< Arr_ >::rayShootUp( const Kernel_point_2& pt ) +{ + typename Supports_landmarks< Arrangement >::Tag supportsLandmarks; + return this->rayShootUp( pt, supportsLandmarks ); +} + +template < typename Arr_ > +CGAL::Object VerticalRayShootCallback< Arr_ >::rayShootUp( const Kernel_point_2& pt, + CGAL::Tag_true ) { CGAL::Object pointLocationResult; Walk_pl_strategy* walkStrategy; @@ -334,9 +346,48 @@ VerticalRayShootCallback< Arr_ >::rayShootUp( const Kernel_point_2& pt ) return pointLocationResult; } +template < typename Arr_ > +CGAL::Object VerticalRayShootCallback< Arr_ >::rayShootUp( const Kernel_point_2& pt, + CGAL::Tag_false ) +{ + CGAL::Object pointLocationResult; + Walk_pl_strategy* walkStrategy; + TrapezoidPointLocationStrategy* trapezoidStrategy; + SimplePointLocationStrategy* simpleStrategy; + + Point_2 point = this->toArrPoint( pt ); + + if ( CGAL::assign( walkStrategy, this->pointLocationStrategy ) ) + { + pointLocationResult = walkStrategy->ray_shoot_up( point ); + } + else if ( CGAL::assign( trapezoidStrategy, this->pointLocationStrategy ) ) + { + pointLocationResult = trapezoidStrategy->ray_shoot_up( point ); + } + else if ( CGAL::assign( simpleStrategy, this->pointLocationStrategy ) ) + { + pointLocationResult = simpleStrategy->ray_shoot_up( point ); + } + else + { + std::cout<<"Didn't find the right strategy\n"; + } + + return pointLocationResult; +} + template < typename Arr_ > CGAL::Object VerticalRayShootCallback< Arr_ >::rayShootDown( const Kernel_point_2& pt ) +{ + typename Supports_landmarks< Arrangement >::Tag supportsLandmarks; + return this->rayShootDown( pt, supportsLandmarks ); +} + +template < typename Arr_ > +CGAL::Object +VerticalRayShootCallback< Arr_ >::rayShootDown( const Kernel_point_2& pt, CGAL::Tag_true ) { CGAL::Object pointLocationResult; Walk_pl_strategy* walkStrategy; @@ -367,4 +418,30 @@ VerticalRayShootCallback< Arr_ >::rayShootDown( const Kernel_point_2& pt ) return pointLocationResult; } +template < typename Arr_ > +CGAL::Object +VerticalRayShootCallback< Arr_ >::rayShootDown( const Kernel_point_2& pt, CGAL::Tag_false ) +{ + CGAL::Object pointLocationResult; + Walk_pl_strategy* walkStrategy; + TrapezoidPointLocationStrategy* trapezoidStrategy; + SimplePointLocationStrategy* simpleStrategy; + + Point_2 point = this->toArrPoint( pt ); + + if ( CGAL::assign( walkStrategy, this->pointLocationStrategy ) ) + { + pointLocationResult = walkStrategy->ray_shoot_down( point ); + } + else if ( CGAL::assign( trapezoidStrategy, this->pointLocationStrategy ) ) + { + pointLocationResult = trapezoidStrategy->ray_shoot_down( point ); + } + else if ( CGAL::assign( simpleStrategy, this->pointLocationStrategy ) ) + { + pointLocationResult = simpleStrategy->ray_shoot_down( point ); + } + return pointLocationResult; +} + #endif // VERTICAL_RAY_SHOOT_CALLBACK_H From 0039cf45cc80c6ab7adefd93cfcc6b035e960cee Mon Sep 17 00:00:00 2001 From: Jane Tournois Date: Fri, 24 Apr 2020 08:02:07 +0200 Subject: [PATCH 318/568] fix compilation with some C3t3 types --- .../CGAL/Tetrahedral_remeshing/internal/FMLS.h | 17 +++++++++++------ .../internal/smooth_vertices.h | 5 +++-- .../tetrahedral_adaptive_remeshing_impl.h | 2 +- 3 files changed, 15 insertions(+), 9 deletions(-) diff --git a/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/FMLS.h b/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/FMLS.h index da72aeddf5a..37418c04e16 100644 --- a/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/FMLS.h +++ b/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/FMLS.h @@ -566,9 +566,12 @@ void createMLSSurfaces(Subdomain__FMLS& subdomain_FMLS, if (upsample > 0) { +#ifdef CGAL_TETRAHEDRAL_REMESHING_VERBOSE std::cout << "Up sampling MLS " << upsample << std::endl; - for (typename C3t3::Facet_iterator fit = c3t3.facets_begin(); - fit != c3t3.facets_end(); ++fit) +#endif + for (typename C3t3::Facets_in_complex_iterator + fit = c3t3.facets_in_complex_begin(); + fit != c3t3.facets_in_complex_end(); ++fit) { const Surface_index surf_i = c3t3.surface_patch_index(*fit); if (upsample == 1) @@ -629,8 +632,9 @@ void createMLSSurfaces(Subdomain__FMLS& subdomain_FMLS, { std::unordered_set > edgeMap; - for (typename C3t3::Facet_iterator fit = c3t3.facets_begin(); - fit != c3t3.facets_end(); ++fit) + for (typename C3t3::Facets_in_complex_iterator + fit = c3t3.facets_in_complex_begin(); + fit != c3t3.facets_in_complex_end(); ++fit) { for (int i = 0; i < 2; i++) { @@ -661,8 +665,9 @@ void createMLSSurfaces(Subdomain__FMLS& subdomain_FMLS, if (upsample > 0) { - for (typename C3t3::Facet_iterator fit = c3t3.facets_begin(); - fit != c3t3.facets_end(); ++fit) + for (typename C3t3::Facets_in_complex_iterator + fit = c3t3.facets_in_complex_begin(); + fit != c3t3.facets_in_complex_end(); ++fit) { const Surface_index surf_i = c3t3.surface_patch_index(*fit); diff --git a/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/smooth_vertices.h b/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/smooth_vertices.h index 3e010ecedb9..8aabb863cc7 100644 --- a/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/smooth_vertices.h +++ b/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/smooth_vertices.h @@ -368,8 +368,9 @@ private: boost::unordered_map >& vertices_surface_indices) { - for (typename C3t3::Facet_iterator fit = c3t3.facets_begin(); - fit != c3t3.facets_end(); ++fit) + for (typename C3t3::Facets_in_complex_iterator + fit = c3t3.facets_in_complex_begin(); + fit != c3t3.facets_in_complex_end(); ++fit) { const Surface_patch_index& surface_index = c3t3.surface_patch_index(*fit); diff --git a/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/tetrahedral_adaptive_remeshing_impl.h b/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/tetrahedral_adaptive_remeshing_impl.h index 477cc450937..6e2e0072e8f 100644 --- a/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/tetrahedral_adaptive_remeshing_impl.h +++ b/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/tetrahedral_adaptive_remeshing_impl.h @@ -469,7 +469,7 @@ private: if(m_c3t3.number_of_facets() == 0) patch = 1; else - patch = m_c3t3.surface_patch_index(*m_c3t3.facets_begin()); + patch = m_c3t3.surface_patch_index(*m_c3t3.facets_in_complex_begin()); } void set_surface_patch_index_to_default(const Subdomain_index& s1, From 09f98fc5cd75b4ee2596161b49c7be448d036c98 Mon Sep 17 00:00:00 2001 From: Jane Tournois Date: Fri, 24 Apr 2020 13:51:25 +0200 Subject: [PATCH 319/568] remove trailing whitespaces --- .../internal/tetrahedral_adaptive_remeshing_impl.h | 1 - 1 file changed, 1 deletion(-) diff --git a/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/tetrahedral_adaptive_remeshing_impl.h b/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/tetrahedral_adaptive_remeshing_impl.h index 6e2e0072e8f..fb4234781ee 100644 --- a/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/tetrahedral_adaptive_remeshing_impl.h +++ b/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/tetrahedral_adaptive_remeshing_impl.h @@ -318,7 +318,6 @@ private: std::size_t nbe = 0; std::size_t nbv = 0; #endif - //tag cells for (Cell_handle cit : tr().finite_cell_handles()) { From 3f275b8fcb5ca7c994efc52ad34523b6dda9d1e6 Mon Sep 17 00:00:00 2001 From: Jane Tournois Date: Fri, 24 Apr 2020 16:03:28 +0200 Subject: [PATCH 320/568] add missing include --- .../CGAL/Tetrahedral_remeshing/tetrahedral_remeshing_io.h | 1 + 1 file changed, 1 insertion(+) diff --git a/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/tetrahedral_remeshing_io.h b/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/tetrahedral_remeshing_io.h index f76e24c2dfa..7ecfff2b82c 100644 --- a/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/tetrahedral_remeshing_io.h +++ b/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/tetrahedral_remeshing_io.h @@ -10,6 +10,7 @@ // // Author(s) : Jane Tournois, Noura Faraj +#include #include #include From a94cb6bc1e9b230ad22067bad5e4edb88174dfea Mon Sep 17 00:00:00 2001 From: Simon Giraudot Date: Mon, 27 Apr 2020 10:06:16 +0200 Subject: [PATCH 321/568] Add missing dependency --- Point_set_3/package_info/Point_set_3/dependencies | 1 + 1 file changed, 1 insertion(+) diff --git a/Point_set_3/package_info/Point_set_3/dependencies b/Point_set_3/package_info/Point_set_3/dependencies index cab851ef527..6f0ec394588 100644 --- a/Point_set_3/package_info/Point_set_3/dependencies +++ b/Point_set_3/package_info/Point_set_3/dependencies @@ -1,5 +1,6 @@ Algebraic_foundations BGL +Circulator GraphicsView Installation Interval_support From 4e3465c36c3aa5816b21baf9a9ff5a3c25acd7f0 Mon Sep 17 00:00:00 2001 From: Maxime Gimeno Date: Mon, 27 Apr 2020 11:20:11 +0200 Subject: [PATCH 322/568] Add a fake windows.h for travis to detect the most common mistakes. --- .travis/build_package.sh | 2 +- .travis/windows.h | 12 ++++++++++++ 2 files changed, 13 insertions(+), 1 deletion(-) create mode 100644 .travis/windows.h diff --git a/.travis/build_package.sh b/.travis/build_package.sh index 7fbe3c29aa2..35af173cd9d 100755 --- a/.travis/build_package.sh +++ b/.travis/build_package.sh @@ -11,7 +11,7 @@ function mytime { function build_examples { mkdir -p build-travis cd build-travis - mytime cmake -DCGAL_DIR="/usr/local/lib/cmake/CGAL" -DCMAKE_CXX_FLAGS="${CXX_FLAGS}" -DCGAL_BUILD_THREE_DOC=TRUE .. + mytime cmake -DCGAL_DIR="/usr/local/lib/cmake/CGAL" -DCMAKE_CXX_FLAGS="${CXX_FLAGS} -I/home/travis/build/CGAL/cgal/.travis/" -DCGAL_BUILD_THREE_DOC=TRUE .. mytime make -j2 VERBOSE=1 } diff --git a/.travis/windows.h b/.travis/windows.h new file mode 100644 index 00000000000..a774a068df3 --- /dev/null +++ b/.travis/windows.h @@ -0,0 +1,12 @@ +#define MAX(a,b) (((a) > (b)) ? (a) : (b)) +#define max(a,b) (((a) > (b)) ? (a) : (b)) + +#define MIN(a,b) (((a) < (b)) ? (a) : (b)) +#define min(a,b) (((a) < (b)) ? (a) : (b)) + + +#define FAR #error named reserved in windows.h +#define far #error named reserved in windows.h + +#define Polyline #error named reserved in windows.h +#define Polygon #error named reserved in windows.h From b1d5cb27c3281a62c2309a0aefed7425f3c78fa8 Mon Sep 17 00:00:00 2001 From: Maxime Gimeno Date: Mon, 27 Apr 2020 15:43:36 +0200 Subject: [PATCH 323/568] add missing cmake flags --- .travis/build_package.sh | 72 ++++++++++++++++++++-------------------- 1 file changed, 36 insertions(+), 36 deletions(-) diff --git a/.travis/build_package.sh b/.travis/build_package.sh index 35af173cd9d..44bf911a20c 100755 --- a/.travis/build_package.sh +++ b/.travis/build_package.sh @@ -11,7 +11,7 @@ function mytime { function build_examples { mkdir -p build-travis cd build-travis - mytime cmake -DCGAL_DIR="/usr/local/lib/cmake/CGAL" -DCMAKE_CXX_FLAGS="${CXX_FLAGS} -I/home/travis/build/CGAL/cgal/.travis/" -DCGAL_BUILD_THREE_DOC=TRUE .. + mytime cmake -DCGAL_DIR="/usr/local/lib/cmake/CGAL" -DCMAKE_CXX_FLAGS="${CXX_FLAGS} -I/home/travis/build/CGAL/cgal/.travis/" -DCGAL_BUILD_THREE_DOC=TRUE -DCGAL_INCLUDE_WINDOWS_DOT_H .. mytime make -j2 VERBOSE=1 } @@ -28,7 +28,7 @@ function build_demo { EXTRA_CXX_FLAGS="-Werror=inconsistent-missing-override" ;; esac - mytime cmake -DCGAL_DIR="/usr/local/lib/cmake/CGAL" -DCGAL_DONT_OVERRIDE_CMAKE_FLAGS:BOOL=ON -DCMAKE_CXX_FLAGS="${CXX_FLAGS} ${EXTRA_CXX_FLAGS}" .. + mytime cmake -DCGAL_DIR="/usr/local/lib/cmake/CGAL" -DCGAL_DONT_OVERRIDE_CMAKE_FLAGS:BOOL=ON -DCMAKE_CXX_FLAGS="${CXX_FLAGS} ${EXTRA_CXX_FLAGS} -I/home/travis/build/CGAL/cgal/.travis/" -DCGAL_INCLUDE_WINDOWS_DOT_H .. mytime make -j2 VERBOSE=1 } old_IFS=$IFS @@ -57,41 +57,41 @@ cd $ROOT cd .. IFS=$old_IFS mytime zsh $ROOT/Scripts/developer_scripts/test_merge_of_branch HEAD - #test dependencies + #test dependencies cd $ROOT mytime bash Scripts/developer_scripts/cgal_check_dependencies.sh --check_headers /usr/bin/doxygen cd .travis - #parse current matrix and check that no package has been forgotten + #parse current matrix and check that no package has been forgotten - IFS=$'\n' - COPY=0 - MATRIX=() - for LINE in $(cat "$PWD/packages.txt") - do - MATRIX+="$LINE " - done - - PACKAGES=() - cd .. - for f in * - do - if [ -d "$f/package_info/$f" ] - then - PACKAGES+="$f " - fi - done - - DIFFERENCE=$(echo ${MATRIX[@]} ${PACKAGES[@]} | tr ' ' '\n' | sort | uniq -u) - IFS=$' ' - if [ "${DIFFERENCE[0]}" != "" ] - then - echo "The matrix and the actual package list differ : ." - echo ${DIFFERENCE[*]} + IFS=$'\n' + COPY=0 + MATRIX=() + for LINE in $(cat "$PWD/packages.txt") + do + MATRIX+="$LINE " + done + + PACKAGES=() + cd .. + for f in * + do + if [ -d "$f/package_info/$f" ] + then + PACKAGES+="$f " + fi + done + + DIFFERENCE=$(echo ${MATRIX[@]} ${PACKAGES[@]} | tr ' ' '\n' | sort | uniq -u) + IFS=$' ' + if [ "${DIFFERENCE[0]}" != "" ] + then + echo "The matrix and the actual package list differ : ." + echo ${DIFFERENCE[*]} echo "You should run generate_travis.sh." - exit 1 - fi - echo "Matrix is up to date." + exit 1 + fi + echo "Matrix is up to date." #check if non standard cgal installation works cd $ROOT mkdir build_test @@ -126,7 +126,7 @@ cd $ROOT fi IFS=$' ' EXAMPLES="$ARG/examples/$ARG" - TEST="$ARG/test/$ARG" + TEST="$ARG/test/$ARG" DEMOS=$ROOT/$ARG/demo/* if [ -d "$ROOT/$EXAMPLES" ] @@ -168,17 +168,17 @@ cd $ROOT for DEMO in $DEMOS; do DEMO=${DEMO#"$ROOT"} echo $DEMO - #If there is no demo subdir, try in GraphicsView + #If there is no demo subdir, try in GraphicsView if [ ! -d "$ROOT/$DEMO" ] || [ ! -f "$ROOT/$DEMO/CMakeLists.txt" ]; then DEMO="GraphicsView/demo/$ARG" fi - if [ "$ARG" != Polyhedron ] && [ -d "$ROOT/$DEMO" ] - then + if [ "$ARG" != Polyhedron ] && [ -d "$ROOT/$DEMO" ] + then cd $ROOT/$DEMO build_demo elif [ "$ARG" != Polyhedron_demo ]; then echo "No demo found for $ARG" - fi + fi done if [ "$ARG" = Polyhedron_demo ]; then DEMO=Polyhedron/demo/Polyhedron From e9383b47903e5ab74060f433f21a1acd0603129b Mon Sep 17 00:00:00 2001 From: Jane Tournois Date: Tue, 28 Apr 2020 09:21:02 +0200 Subject: [PATCH 324/568] fix dependencies --- .../package_info/Tetrahedral_remeshing/dependencies | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/Tetrahedral_remeshing/package_info/Tetrahedral_remeshing/dependencies b/Tetrahedral_remeshing/package_info/Tetrahedral_remeshing/dependencies index 15622284ce4..984e3ed4d28 100644 --- a/Tetrahedral_remeshing/package_info/Tetrahedral_remeshing/dependencies +++ b/Tetrahedral_remeshing/package_info/Tetrahedral_remeshing/dependencies @@ -1,25 +1,32 @@ -AABB_tree Algebraic_foundations Arithmetic_kernel +BGL Cartesian_kernel Circulator Distance_2 Distance_3 Filtered_kernel -Generator +Hash_map Homogeneous_kernel Installation Interval_support +Intersections_2 +Intersections_3 Kernel_23 +Kernel_d Mesh_3 Modular_arithmetic Number_types +Polygon Polygon_mesh_processing Profiling_tools Property_map +Random_numbers +Skin_surface_3 +Spatial_sorting STL_Extension -Spatial_searching Stream_support +Tetrahedral_remeshing TDS_3 Triangulation_3 Union_find From 0df35c783610df51f622a2d81300940d590e8605 Mon Sep 17 00:00:00 2001 From: Simon Giraudot Date: Wed, 29 Apr 2020 13:34:26 +0200 Subject: [PATCH 325/568] Fix unused parameter warning --- .../Plugins/Point_set/Point_set_clustering_plugin.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Polyhedron/demo/Polyhedron/Plugins/Point_set/Point_set_clustering_plugin.cpp b/Polyhedron/demo/Polyhedron/Plugins/Point_set/Point_set_clustering_plugin.cpp index 61eaa766927..c68a2ab3c07 100644 --- a/Polyhedron/demo/Polyhedron/Plugins/Point_set/Point_set_clustering_plugin.cpp +++ b/Polyhedron/demo/Polyhedron/Plugins/Point_set/Point_set_clustering_plugin.cpp @@ -73,7 +73,7 @@ public: return QList() << actionCluster; } - bool applicable(QAction* action) const { + bool applicable(QAction*) const { Scene_points_with_normal_item* item = qobject_cast(scene->item(scene->mainSelectionIndex())); return item; } From f4581c2b13c07cbffa870f596345150668542a49 Mon Sep 17 00:00:00 2001 From: Laurent Rineau Date: Fri, 1 May 2020 15:00:35 +0200 Subject: [PATCH 326/568] Add CGALConfigVersion.cmake, and CTest tests --- CGALConfigVersion.cmake | 1 + Installation/CGALConfigVersion.cmake | 1 + .../lib/cmake/CGAL/CGALConfigVersion.cmake | 21 ++++++++++++ Installation/test/Installation/CMakeLists.txt | 34 +++++++++++++++++++ .../Installation/test_find_package.cmake.in | 14 ++++++++ 5 files changed, 71 insertions(+) create mode 100644 CGALConfigVersion.cmake create mode 100644 Installation/CGALConfigVersion.cmake create mode 100644 Installation/lib/cmake/CGAL/CGALConfigVersion.cmake create mode 100644 Installation/test/Installation/test_find_package.cmake.in diff --git a/CGALConfigVersion.cmake b/CGALConfigVersion.cmake new file mode 100644 index 00000000000..f1363d9a8f6 --- /dev/null +++ b/CGALConfigVersion.cmake @@ -0,0 +1 @@ +include(${CMAKE_CURRENT_LIST_DIR}/Installation/lib/cmake/CGAL/CGALConfigVersion.cmake) diff --git a/Installation/CGALConfigVersion.cmake b/Installation/CGALConfigVersion.cmake new file mode 100644 index 00000000000..9b0b10600b1 --- /dev/null +++ b/Installation/CGALConfigVersion.cmake @@ -0,0 +1 @@ +include(${CMAKE_CURRENT_LIST_DIR}/lib/cmake/CGAL/CGALConfigVersion.cmake) diff --git a/Installation/lib/cmake/CGAL/CGALConfigVersion.cmake b/Installation/lib/cmake/CGAL/CGALConfigVersion.cmake new file mode 100644 index 00000000000..77b73b21be0 --- /dev/null +++ b/Installation/lib/cmake/CGAL/CGALConfigVersion.cmake @@ -0,0 +1,21 @@ +set(CGAL_MAJOR_VERSION 4) +set(CGAL_MINOR_VERSION 14) +set(CGAL_BUGFIX_VERSION 4) +set(CGAL_VERSION_PUBLIC_RELEASE_NAME "CGAL-4.14.4") + +if (CGAL_BUGFIX_VERSION AND CGAL_BUGFIX_VERSION GREATER 0) + set(CGAL_CREATED_VERSION_NUM "${CGAL_MAJOR_VERSION}.${CGAL_MINOR_VERSION}.${CGAL_BUGFIX_VERSION}") +else() + set(CGAL_CREATED_VERSION_NUM "${CGAL_MAJOR_VERSION}.${CGAL_MINOR_VERSION}") +endif() + +set(PACKAGE_VERSION ${CGAL_CREATED_VERSION_NUM}) + +if(PACKAGE_VERSION VERSION_LESS PACKAGE_FIND_VERSION) + set(PACKAGE_VERSION_COMPATIBLE FALSE) +else() + set(PACKAGE_VERSION_COMPATIBLE TRUE) + if(PACKAGE_FIND_VERSION STREQUAL PACKAGE_VERSION) + set(PACKAGE_VERSION_EXACT TRUE) + endif() +endif() diff --git a/Installation/test/Installation/CMakeLists.txt b/Installation/test/Installation/CMakeLists.txt index 1c0af2324dd..64aa39edf93 100644 --- a/Installation/test/Installation/CMakeLists.txt +++ b/Installation/test/Installation/CMakeLists.txt @@ -102,3 +102,37 @@ else() message(STATUS "NOTICE: This program requires the CGAL library, and will not be compiled.") endif() + +function(CGAL_installation_test_find_package_version mode) + set(EXACT) + if(mode STREQUAL "less") + MATH(EXPR CGAL_MAJOR_VERSION "${CGAL_MAJOR_VERSION} - 1") + endif() + if(mode STREQUAL "greater" OR mode STREQUAL "fail-exact") + MATH(EXPR CGAL_MINOR_VERSION "${CGAL_MINOR_VERSION} + 1") + endif() + if(mode STREQUAL "exact" OR mode STREQUAL "fail-exact") + set(EXACT "EXACT ") + endif() + if (CGAL_BUGFIX_VERSION AND CGAL_BUGFIX_VERSION GREATER 0) + set(VERSION "${CGAL_MAJOR_VERSION}.${CGAL_MINOR_VERSION}.${CGAL_BUGFIX_VERSION}") + else() + set(VERSION "${CGAL_MAJOR_VERSION}.${CGAL_MINOR_VERSION}") + endif() + file(REMOVE_RECURSE "${CMAKE_CURRENT_BINARY_DIR}/build-test_find_package_version_${mode}") + file(MAKE_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/build-test_find_package_version_${mode}) + file(MAKE_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/test_find_package_version_${mode}) + configure_file(test_find_package.cmake.in ${CMAKE_CURRENT_BINARY_DIR}/test_find_package_version_${mode}/CMakeLists.txt) + add_test(NAME test_find_package_version_${mode} + COMMAND ${CMAKE_COMMAND} -S ${CMAKE_CURRENT_BINARY_DIR}/test_find_package_version_${mode} -B ${CMAKE_CURRENT_BINARY_DIR}/build-test_find_package_version_${mode}) +endfunction() + +CGAL_installation_test_find_package_version(less) +CGAL_installation_test_find_package_version(equal) +CGAL_installation_test_find_package_version(greater) +CGAL_installation_test_find_package_version(exact) +CGAL_installation_test_find_package_version(fail-exact) +set_tests_properties( + test_find_package_version_greater + test_find_package_version_fail-exact + PROPERTIES WILL_FAIL TRUE) diff --git a/Installation/test/Installation/test_find_package.cmake.in b/Installation/test/Installation/test_find_package.cmake.in new file mode 100644 index 00000000000..fc7152ef4d4 --- /dev/null +++ b/Installation/test/Installation/test_find_package.cmake.in @@ -0,0 +1,14 @@ +cmake_minimum_required(VERSION ${CMAKE_VERSION}) +project( test_find_package_${mode} ) +find_package(CGAL ${VERSION} ${EXACT}REQUIRED + PATHS ${CGAL_DIR} + NO_DEFAULT_PATH + NO_PACKAGE_ROOT_PATH + NO_CMAKE_PATH + NO_CMAKE_ENVIRONMENT_PATH + NO_SYSTEM_ENVIRONMENT_PATH + NO_CMAKE_PACKAGE_REGISTRY + NO_CMAKE_BUILDS_PATH + NO_CMAKE_SYSTEM_PATH + NO_CMAKE_SYSTEM_PACKAGE_REGISTRY + ) From 891c162c56cbb6dd938db48e42e7f2fdbf63f26c Mon Sep 17 00:00:00 2001 From: Jane Tournois Date: Mon, 4 May 2020 07:32:55 +0200 Subject: [PATCH 327/568] doc reviews --- .../Concepts/RemeshingTriangulationTraits_3.h | 2 +- .../Tetrahedral_remeshing.txt | 37 ++++++++++--------- .../tetrahedral_remeshing_example.cpp | 4 +- .../Remeshing_triangulation_3.h | 5 +-- .../Remeshing_vertex_base_3.h | 1 - .../include/CGAL/tetrahedral_remeshing.h | 20 +++++----- 6 files changed, 36 insertions(+), 33 deletions(-) diff --git a/Tetrahedral_remeshing/doc/Tetrahedral_remeshing/Concepts/RemeshingTriangulationTraits_3.h b/Tetrahedral_remeshing/doc/Tetrahedral_remeshing/Concepts/RemeshingTriangulationTraits_3.h index 48cfd4c4db2..8f001943705 100644 --- a/Tetrahedral_remeshing/doc/Tetrahedral_remeshing/Concepts/RemeshingTriangulationTraits_3.h +++ b/Tetrahedral_remeshing/doc/Tetrahedral_remeshing/Concepts/RemeshingTriangulationTraits_3.h @@ -7,7 +7,7 @@ The concept `RemeshingTriangulationTraits_3` is the first template parameter of the class `Remeshing_triangulation_3`. It defines the geometric objects -(points, segments, triangles and tetrahedra) forming the triangulation together with a few +(points, segments, triangles, and tetrahedra) forming the triangulation together with a few geometric predicates and constructions on these objects. \cgalHasModel All models of `Kernel`. diff --git a/Tetrahedral_remeshing/doc/Tetrahedral_remeshing/Tetrahedral_remeshing.txt b/Tetrahedral_remeshing/doc/Tetrahedral_remeshing/Tetrahedral_remeshing.txt index 7af1ee5f2d5..bca4311f67d 100644 --- a/Tetrahedral_remeshing/doc/Tetrahedral_remeshing/Tetrahedral_remeshing.txt +++ b/Tetrahedral_remeshing/doc/Tetrahedral_remeshing/Tetrahedral_remeshing.txt @@ -17,11 +17,12 @@ namespace CGAL { This package implements an algorithm for quality tetrahedral remeshing, introduced by N.Faraj et al in \cgalCite{faraj2016mvr}. This practical iterative remeshing algorithm is designed to remesh -multi-material tetrahedral meshes, by iteratively performing a sequence of simple +multi-material tetrahedral meshes, by iteratively performing a sequence of elementary operations such as edge splits, edge collapses, edge flips, and vertex relocations following a Laplacian smoothing. -The algorithm results in high quality isotropic meshes, with the desired mesh density, -while preserving the input geometric linear and surfacic features. +The algorithm results in high-quality uniform isotropic meshes, +with the desired mesh density, +while preserving the input geometric curve and surface features. Specific remeshing rules have been designed to satisfy the following criteria. First, the algorithm preserves the geometric complex topology, including @@ -35,30 +36,31 @@ All the local atomic operations that are performed by the algorithm preserve the input topology of the geometric complex. The tetrahedral remeshing algorithm improves the quality of dihedral angles, -while targetting the user-defined uniform sizing field and preserving the +while targeting the user-defined uniform sizing field and preserving the topology of the feature complex, as highlighted by Figure \cgalFigureRef{Remesh_liver}. \cgalFigureBegin{Remesh_liver, tetrahedral_remeshing_before_after.png} -Tetrahedral mesh, modified by the uniform tetrahedral remeshing algorithm. +Tetrahedral mesh, improved by the uniform tetrahedral remeshing algorithm. (Left) Before remeshing, dihedral angles were in the interval [0.7; 178.9]. (Right) After remeshing and keeping the same density, dihedral angles are the interval [12,7; 157.7]. \cgalFigureEnd -Experimental evidence show that a higher number of remeshing iterations -leads to a mesh with a better fitted sizing criterion, and higher quality dihedral angles. +Experimental evidence shows that a higher number of remeshing iterations +leads to a mesh with a improved fidelity to the sizing criterion, +and higher quality dihedral angles. \section secTetRemeshingAPI API The tetrahedral remeshing algorithm is implemented as a single free function `CGAL::tetrahedral_isotropic_remeshing()` that -takes only two parameters : the input triangulation, and the desired edge length, +takes only two required parameters: the input triangulation, and the desired edge length, which drives the remeshing process. \ref BGLNamedParameters are used to deal with optional parameters. -The page \ref Remeshing_namedparameters describes their usage -and provides a list of the parameters that are used in this package for tuning -of the remeshing process and results. +The page \ref Remeshing_namedparameters provides a description +of their usage, and of all the available parameters for tuning +the remeshing process and results. \section secTetRemeshingExamples Examples @@ -66,8 +68,8 @@ of the remeshing process and results. \subsection ssecEx1 Tetrahedral Remeshing Example The following example shows the simplest use of the tetrahedral remeshing function. -The only needed parameter is a given target edge length that will drive the remeshing process -towards a high quality tetrahedral mesh with improved dihedral angles, and a more +The only required parameter is a given target edge length that drives the remeshing process +towards a high-quality tetrahedral mesh with improved dihedral angles, and a more uniform mesh, with edge lengths getting closer to the input parameter value. \cgalExample{Tetrahedral_remeshing/tetrahedral_remeshing_example.cpp } @@ -75,7 +77,7 @@ uniform mesh, with edge lengths getting closer to the input parameter value. \subsection ssecEx2 Tetrahedral Remeshing of A Selection -Optional BGL named parameters can be used to get more precise +Optional BGL named parameters offer more precise control on the remeshing process. In this example, a triangulation with two subdomains (defined by indices stored in cells) is given as input, but only one (defined by the `Subdomain_index` 2) @@ -86,11 +88,12 @@ of its subdomains is remeshed. \subsection ssecEx3 Tetrahedral Remeshing With Polyline Features -Optional BGL named parameters can be used to get more precise +Optional BGL named parameters offer more precise control on the remeshing process. In this example, a triangulation with polyline features that should be preserved - though resampled - -during the remeshing process. It would also be possible to preserve -the input polyline features exactly. +during the remeshing process, is given as input. +Preserving all surfaces exactly could also be achieved by +setting the named parameter `remesh_boundaries` to `false`. \cgalExample{Tetrahedral_remeshing/tetrahedral_remeshing_with_features.cpp } diff --git a/Tetrahedral_remeshing/examples/Tetrahedral_remeshing/tetrahedral_remeshing_example.cpp b/Tetrahedral_remeshing/examples/Tetrahedral_remeshing/tetrahedral_remeshing_example.cpp index 57f764c7d8b..529ea62187e 100644 --- a/Tetrahedral_remeshing/examples/Tetrahedral_remeshing/tetrahedral_remeshing_example.cpp +++ b/Tetrahedral_remeshing/examples/Tetrahedral_remeshing/tetrahedral_remeshing_example.cpp @@ -18,8 +18,8 @@ typedef CGAL::Tetrahedral_remeshing::Remeshing_triangulation_3 Remeshing_tria int main(int argc, char* argv[]) { - const char* filename = (argc > 1) ? argv[1] : "data/triangulation_one_subdomain.binary.cgal"; - float target_edge_length = (argc > 2) ? atof(argv[2]) : 0.1f; + const char* filename = (argc > 1) ? argv[1] : "data/triangulation_one_subdomain.binary.cgal"; + const float target_edge_length = (argc > 2) ? atof(argv[2]) : 0.1f; std::ifstream input(filename, std::ios::in | std::ios::binary); diff --git a/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/Remeshing_triangulation_3.h b/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/Remeshing_triangulation_3.h index 6727c3a4c1f..3e91a6dfd23 100644 --- a/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/Remeshing_triangulation_3.h +++ b/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/Remeshing_triangulation_3.h @@ -45,7 +45,8 @@ It has to be a model of the concept `RemeshingTriangulationTraits_3`. \tparam Concurrency_tag enables sequential versus parallel implementation of the triangulation data structure. -Possible values are `Sequential_tag` (the default) and `Parallel_tag`. +Possible values are `Sequential_tag` (the default), `Parallel_tag`, +and `Parallel_if_available_tag`. \tparam Vb is a vertex base class from which `Remeshing_vertex_base_3` derives. It must be a model of the `TriangulationVertexBase_3` concept. @@ -55,8 +56,6 @@ It has the default value `Triangulation_vertex_base_3`. It must be a model of the `TriangulationCellBase_3` concept. It has the default value `Triangulation_cell_base_3`. -\cgalRefines `Triangulation_3` - */ template`. \cgalModels `MeshVertexBase_3` -\cgalRefines `Triangulation_vertex_base_3` */ template`. +* @param tr the triangulation to be remeshed, of type `Triangulation_3`. * `Remeshing_triangulation` is a helper class that satisfies all the requirements * of its template parameters. * @param target_edge_length the uniform target edge length. This parameter provides a @@ -83,7 +85,8 @@ namespace CGAL * sequence of atomic operations * performed (listed in the above description) * \cgalParamEnd -* \cgalParamBegin{remesh_boundaries} If `false`, none of the volume boundaries can be modified. +* \cgalParamBegin{remesh_boundaries} If `false`, none of the input volume boundaries +* can be modified. * Otherwise, the topology is preserved, but atomic operations can be performed on the * surfaces, and along feature polylines, such that boundaries are remeshed. * \cgalParamEnd @@ -103,8 +106,7 @@ namespace CGAL * \cgalParamEnd * \cgalNamedParamsEnd -* @todo implement 1D smoothing for constrained edges -* @todo implement sizing field instead of uniform target edge length +* @todo implement non-uniform sizing field instead of uniform target edge length */ template From b91eed1bfbe557a93c57a5b1063b91c1225c547d Mon Sep 17 00:00:00 2001 From: Jane Tournois Date: Mon, 4 May 2020 07:39:31 +0200 Subject: [PATCH 328/568] more doc reviews --- .../CGAL/Tetrahedral_remeshing/Remeshing_cell_base_3.h | 7 ++++++- .../CGAL/Tetrahedral_remeshing/Remeshing_vertex_base_3.h | 7 ++++++- 2 files changed, 12 insertions(+), 2 deletions(-) diff --git a/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/Remeshing_cell_base_3.h b/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/Remeshing_cell_base_3.h index 038182d89fc..ff9a074ecb9 100644 --- a/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/Remeshing_cell_base_3.h +++ b/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/Remeshing_cell_base_3.h @@ -50,7 +50,12 @@ It has the default value `Triangulation_cell_base_3`. */ template > -using Remeshing_cell_base_3 = CGAL::Mesh_cell_base_3; +using Remeshing_cell_base_3 +#ifndef DOXYGEN_RUNNING + = CGAL::Mesh_cell_base_3; +#else + = unspecified_type; +#endif }//end namespace Tetrahedral_remeshing }//end namespace CGAL diff --git a/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/Remeshing_vertex_base_3.h b/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/Remeshing_vertex_base_3.h index c2672827116..6c6513e7655 100644 --- a/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/Remeshing_vertex_base_3.h +++ b/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/Remeshing_vertex_base_3.h @@ -52,7 +52,12 @@ It has the default value `Triangulation_vertex_base_3`. template > -using Remeshing_vertex_base_3 = CGAL::Mesh_vertex_base_3; +using Remeshing_vertex_base_3 +#ifndef DOXYGEN_RUNNING + = CGAL::Mesh_vertex_base_3; +#else + = unspecified_type; +#endif }//end namespace Tetrahedral_remeshing From ab1063194cf9e632019a3a194ffd50d6300589f9 Mon Sep 17 00:00:00 2001 From: Jane Tournois Date: Mon, 4 May 2020 07:51:03 +0200 Subject: [PATCH 329/568] fix conversion warnings --- .../Tetrahedral_remeshing/internal/FMLS.h | 28 ++++++++++--------- 1 file changed, 15 insertions(+), 13 deletions(-) diff --git a/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/FMLS.h b/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/FMLS.h index 37418c04e16..fa99e1adf3a 100644 --- a/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/FMLS.h +++ b/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/FMLS.h @@ -153,7 +153,7 @@ public: return std::vector(size * SURFEL_SIZE); } - void setPN(const std::vector& newPN, + void setPN(const std::vector& newPN, const unsigned int newPNSize, const float pointSpacing) { @@ -294,8 +294,8 @@ public: // Number of elements of the PN. One elemnt is a 6-float32 chunk. inline unsigned int getPNSize() const { return PNSize; } - inline std::vector& getPN() { return PN; } - inline const std::vector& getPN() const { return PN; } + inline std::vector& getPN() { return PN; } + inline const std::vector& getPN() const { return PN; } // Min/Max corners of PN's bounding volume inline const float* getMinMax() const { return grid.getMinMax(); } @@ -358,7 +358,7 @@ private: clear(); } - void init(const std::vector& PN, unsigned int PNSize, float sigma_s) + void init(const std::vector& PN, unsigned int PNSize, float sigma_s) { cellSize = sigma_s; for (unsigned int i = 0; i < 3; i++) { @@ -429,7 +429,7 @@ private: // Accessors - inline const std::array getMinMax() const { return minMax; } + inline const std::array getMinMax() const { return minMax; } inline const std::array getRes() const { return res; } inline float getCellSize() const { return cellSize; } inline std::vector& getLUT() { return LUT; } @@ -480,7 +480,7 @@ private: } private: - std::array minMax; + std::array minMax; float cellSize; std::array res; std::vector LUT; // 3D Index Look-Up Table @@ -502,7 +502,7 @@ private: // CPU Data // -------------------------------------------------------------- - std::vector PN; + std::vector PN; unsigned int PNSize; float PNScale; // size of the bounding sphere radius float MLSRadius; @@ -581,7 +581,7 @@ void createMLSSurfaces(Subdomain__FMLS& subdomain_FMLS, } } - std::vector< std::vector > pns; + std::vector< std::vector > pns; int count = 0; //Memory allocation for the point plus normals of the point samples @@ -589,7 +589,7 @@ void createMLSSurfaces(Subdomain__FMLS& subdomain_FMLS, it != subdomain_sample_numbers.end(); ++it) { current_subdomain_FMLS_indices[it->first] = count; - pns.push_back(std::vector(it->second * 6, 0.f)); + pns.push_back(std::vector(it->second * 6, 0.)); count++; } @@ -654,8 +654,9 @@ void createMLSSurfaces(Subdomain__FMLS& subdomain_FMLS, const Surface_index surf_i = c3t3.surface_patch_index(*fit); const int fmls_id = current_subdomain_FMLS_indices[surf_i]; - point_spacing[fmls_id] += CGAL::approximate_sqrt( - CGAL::squared_distance(point(vh0->point()), point(vh1->point()))); + point_spacing[fmls_id] += static_cast( + CGAL::approximate_sqrt( + CGAL::squared_distance(point(vh0->point()), point(vh1->point())))); point_spacing_count[fmls_id] ++; } } @@ -690,7 +691,7 @@ void createMLSSurfaces(Subdomain__FMLS& subdomain_FMLS, Vector_3 barycenter = (points[0] + points[1] + points[2]) / 3.; Vector_3 n_barycenter = (normals[0] + normals[1] + normals[2]); - n_barycenter = n_barycenter / CGAL::sqrt((n_barycenter * n_barycenter)); + n_barycenter = n_barycenter / CGAL::approximate_sqrt((n_barycenter * n_barycenter)); points_to_add.push_back(barycenter); n_points_to_add.push_back(n_barycenter); @@ -701,7 +702,8 @@ void createMLSSurfaces(Subdomain__FMLS& subdomain_FMLS, { Vector_3 space_1 = barycenter - points[i]; - point_spacing[fmls_id] += CGAL::sqrt(space_1 * space_1); + point_spacing[fmls_id] += + static_cast(CGAL::approximate_sqrt(space_1 * space_1)); point_spacing_count[fmls_id] ++; } } From 3c42e84a387309d2080feed325352d5d4002a352 Mon Sep 17 00:00:00 2001 From: Jane Tournois Date: Mon, 4 May 2020 14:01:46 +0200 Subject: [PATCH 330/568] name points to improve readability of example --- .../tetrahedral_remeshing_with_features.cpp | 26 ++++++++++++------- 1 file changed, 17 insertions(+), 9 deletions(-) diff --git a/Tetrahedral_remeshing/examples/Tetrahedral_remeshing/tetrahedral_remeshing_with_features.cpp b/Tetrahedral_remeshing/examples/Tetrahedral_remeshing/tetrahedral_remeshing_with_features.cpp index 11803d908ff..eef842f7234 100644 --- a/Tetrahedral_remeshing/examples/Tetrahedral_remeshing/tetrahedral_remeshing_with_features.cpp +++ b/Tetrahedral_remeshing/examples/Tetrahedral_remeshing/tetrahedral_remeshing_with_features.cpp @@ -80,27 +80,35 @@ void make_constraints_from_cube_edges( Remeshing_triangulation& tr, boost::unordered_set >& constraints) { + const Point p0(-2., -2., -2.); + const Point p1(-2., -2., -2.); + const Point p2( 2., -2., -2.); + const Point p3( 2., -2., 2.); + const Point p4(-2., 2., -2.); + const Point p5(-2., 2., 2.); + const Point p6( 2., 2., -2.); + const Point p7( 2., 2., 2.); + Remeshing_triangulation::Locate_type lt; int li, lj; - - Cell_handle c = tr.locate(Point(-2., -2., -2.), lt, li, lj); + Cell_handle c = tr.locate(p0, lt, li, lj); Vertex_handle v0 = c->vertex(li); - c = tr.locate(Point(-2., -2., 2.)); + c = tr.locate(p1, lt, li, lj); Vertex_handle v1 = c->vertex(li); - c = tr.locate(Point( 2., -2., -2.)); + c = tr.locate(p2, lt, li, lj); Vertex_handle v2 = c->vertex(li); - c = tr.locate(Point( 2., -2., 2.)); + c = tr.locate(p3, lt, li, lj); Vertex_handle v3 = c->vertex(li); - c = tr.locate(Point(-2., 2., -2.)); + c = tr.locate(p4, lt, li, lj); Vertex_handle v4 = c->vertex(li); - c = tr.locate(Point(-2., 2., 2.)); + c = tr.locate(p5, lt, li, lj); Vertex_handle v5 = c->vertex(li); - c = tr.locate(Point( 2., 2., -2.)); + c = tr.locate(p6, lt, li, lj); Vertex_handle v6 = c->vertex(li); - c = tr.locate(Point( 2., 2., 2.)); + c = tr.locate(p7, lt, li, lj); Vertex_handle v7 = c->vertex(li); // constrain cube edges From 8ec09f40fc2b4805fe865133fea4bd98b7a49ead Mon Sep 17 00:00:00 2001 From: Jane Tournois Date: Mon, 4 May 2020 16:09:27 +0200 Subject: [PATCH 331/568] remove dependency on Skin_surface_3 by replacing Triangulation_incremental_builder_3 by build_triangulation() from tet_soup_to_c3t3.h (which is part of Mesh_3 as C3T3) --- Mesh_3/include/CGAL/Mesh_3/tet_soup_to_c3t3.h | 72 ++++-- .../internal/collapse_short_edges.h | 210 ++++++++++++------ .../internal/tetrahedral_remeshing_helpers.h | 35 +++ .../Tetrahedral_remeshing/dependencies | 1 - 4 files changed, 225 insertions(+), 93 deletions(-) diff --git a/Mesh_3/include/CGAL/Mesh_3/tet_soup_to_c3t3.h b/Mesh_3/include/CGAL/Mesh_3/tet_soup_to_c3t3.h index c9a748ebd11..0d0c1c1cb6b 100644 --- a/Mesh_3/include/CGAL/Mesh_3/tet_soup_to_c3t3.h +++ b/Mesh_3/include/CGAL/Mesh_3/tet_soup_to_c3t3.h @@ -23,7 +23,7 @@ #include #include -#include +#include #include @@ -50,8 +50,8 @@ void build_vertices(Tr& tr, template void add_facet_to_incident_cells_map(const typename Tr::Cell_handle c, int i, - boost::unordered_map, - std::vector > >& incident_cells_map) + boost::unordered_map, + std::vector > >& incident_cells_map) { typedef typename Tr::Vertex_handle Vertex_handle; typedef typename Tr::Cell_handle Cell_handle; @@ -74,6 +74,21 @@ void add_facet_to_incident_cells_map(const typename Tr::Cell_handle c, int i, if(!is_insert_successful.second) // the entry already exists in the map { // a facet must have exactly two incident cells +// if (is_insert_successful.first->second.size() != 1) +// { +// typename Tr::Geom_traits::Construct_point_3 point +// = typename Tr::Geom_traits().construct_point_3_object(); +// for (auto fi : incident_cells_map.at(f)) +// { +// std::cout << point(fi.first->vertex((fi.second + 1) % 4)->point()) +// << " " << point(fi.first->vertex((fi.second + 2) % 4)->point()) +// << " " << point(fi.first->vertex((fi.second + 3) % 4)->point()) << std::endl; +// } +// std::cout << "finite facet : " << std::endl; +// std::cout << point(c->vertex(1)->point()) +// << " " << point(c->vertex(2)->point()) +// << " " << point(c->vertex(3)->point()) << std::endl; +// } CGAL_assertion(is_insert_successful.first->second.size() == 1); is_insert_successful.first->second.push_back(e); } @@ -81,13 +96,13 @@ void add_facet_to_incident_cells_map(const typename Tr::Cell_handle c, int i, template void build_finite_cells(Tr& tr, - const std::vector >& finite_cells, + const std::vector >& finite_cells, const std::vector& vertex_handle_vector, boost::unordered_map, std::vector > >& incident_cells_map, - const std::map, int>& border_facets) + const std::map, int>& border_facets) { - typedef boost::array Tet_with_ref; // 4 ids + 1 reference + typedef std::array Tet_with_ref; // 4 ids + 1 reference typedef typename Tr::Vertex_handle Vertex_handle; typedef typename Tr::Cell_handle Cell_handle; @@ -101,7 +116,7 @@ void build_finite_cells(Tr& tr, for(std::size_t i=0; i vs; + std::array vs; for(int j=0; j<4; ++j) { @@ -118,9 +133,8 @@ void build_finite_cells(Tr& tr, == POSITIVE); Cell_handle c = tr.tds().create_cell(vs[0], vs[1], vs[2], vs[3]); - c->info() = tet[4]; // the cell's info keeps the reference of the tetrahedron + c->set_subdomain_index(tet[4]); // the cell's info keeps the reference of the tetrahedron - CGAL_precondition(tet[4] > 0); // assign cells to vertices for(int j=0; j<4; ++j) { @@ -134,14 +148,14 @@ void build_finite_cells(Tr& tr, add_facet_to_incident_cells_map(c, j, incident_cells_map); if(border_facets.size() != 0) { - boost::array facet; + std::array facet; facet[0]=tet[(j+1) % 4]; facet[1]=tet[(j+2) % 4]; facet[2]=tet[(j+3) % 4]; //find the circular permutation that puts the smallest index in the first place. int n0 = (std::min)((std::min)(facet[0], facet[1]), facet[2]); int k=0; - boost::array f; + std::array f; do { f[0]=facet[(0+k)%3]; @@ -150,7 +164,7 @@ void build_finite_cells(Tr& tr, ++k; } while(f[0] != n0); - typename std::map, int>::const_iterator it = border_facets.find(f); + typename std::map, int>::const_iterator it = border_facets.find(f); if(it != border_facets.end()) { c->set_surface_patch_index(j, it->second); @@ -274,8 +288,10 @@ bool assign_neighbors(Tr& tr, template bool build_triangulation(Tr& tr, const std::vector& points, - const std::vector >& finite_cells, - const std::map, int>& border_facets) + const std::vector >& finite_cells, + const std::map, int>& border_facets, + std::vector& vertex_handle_vector, + const bool verbose = false) { typedef typename Tr::Vertex_handle Vertex_handle; typedef typename Tr::Cell_handle Cell_handle; @@ -286,7 +302,9 @@ bool build_triangulation(Tr& tr, typedef boost::unordered_map > Incident_cells_map; Incident_cells_map incident_cells_map; - std::vector vertex_handle_vector(points.size() + 1); // id to vertex_handle + vertex_handle_vector.resize(points.size() + 1); // id to vertex_handle + //index 0 is for infinite vertex + // 1 to n for points in `points` CGAL_precondition(!points.empty()); @@ -302,22 +320,26 @@ bool build_triangulation(Tr& tr, { vh->set_dimension(-1); } - if(!finite_cells.empty()) + if (!finite_cells.empty()) { build_finite_cells(tr, finite_cells, vertex_handle_vector, incident_cells_map, border_facets); build_infinite_cells(tr, incident_cells_map); tr.tds().set_dimension(3); - if(!assign_neighbors(tr, incident_cells_map)) + if (!assign_neighbors(tr, incident_cells_map)) return false; - std::cout << "built triangulation : " << std::endl; - std::cout << tr.number_of_cells() << " cells" << std::endl; + if (verbose) + { + std::cout << "built triangulation : " << std::endl; + std::cout << tr.number_of_cells() << " cells" << std::endl; + } } - std::cout << tr.number_of_vertices() << " vertices" << std::endl; + if(verbose) + std::cout << tr.number_of_vertices() << " vertices" << std::endl; if(c3t3_loader_failed) return true; else - return tr.is_valid(true); + return tr.tds().is_valid(); } template @@ -326,8 +348,8 @@ bool build_triangulation_from_file(std::istream& is, { typedef typename Tr::Point Point_3; - typedef boost::array Facet; // 3 = id - typedef boost::array Tet_with_ref; // first 4 = id, fifth = reference + typedef std::array Facet; // 3 = id + typedef std::array Tet_with_ref; // first 4 = id, fifth = reference std::vector finite_cells; std::vector points; @@ -408,7 +430,9 @@ bool build_triangulation_from_file(std::istream& is, if(finite_cells.empty()) return false; - bool is_well_built = build_triangulation(tr, points, finite_cells, border_facets); + std::vector vertices(points.size() + 1); + bool is_well_built = build_triangulation(tr, + points, finite_cells, border_facets, vertices); return is_well_built; } diff --git a/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/collapse_short_edges.h b/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/collapse_short_edges.h index 7cfeb21607e..2032af1df97 100644 --- a/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/collapse_short_edges.h +++ b/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/collapse_short_edges.h @@ -22,11 +22,14 @@ #include #include -#include - #include #include +#include +#include +#include +#include +#include #include @@ -43,7 +46,7 @@ enum Result_type { VALID, V_PROBLEM, C_PROBLEM, E_PROBLEM, TOPOLOGICAL_PROBLEM, ORIENTATION_PROBLEM, SHARED_NEIGHBOR_PROBLEM }; -template +template class CollapseTriangulation { typedef typename C3t3::Triangulation Tr; @@ -54,96 +57,166 @@ class CollapseTriangulation typedef typename C3t3::Triangulation::Point Point_3; typedef typename C3t3::Triangulation::Geom_traits::Vector_3 Vector_3; - typedef CGAL::Triangulation_incremental_builder_3 Builder; - public: CollapseTriangulation(C3t3& c3t3, - const Edge& edge, - Collapse_type _collapse_type, - Visitor& visitor) + const Edge& e, + Collapse_type _collapse_type) + : v0_init(e.first->vertex(e.second)) + , v1_init(e.first->vertex(e.third)) + , collapse_type(_collapse_type) { - v0_init = edge.first->vertex(edge.second); - v1_init = edge.first->vertex(edge.third); + typedef std::array Facet; // 3 = id + typedef std::array Tet_with_ref; // first 4 = id, fifth = reference + + std::vector finite_cells; + std::vector points; + std::map border_facets; std::vector vertices_to_insert; c3t3.triangulation().finite_incident_vertices(v0_init, std::back_inserter(vertices_to_insert)); vertices_to_insert.push_back(v0_init); c3t3.triangulation().finite_incident_vertices(v1_init, - std::back_inserter(vertices_to_insert)); + std::back_inserter(vertices_to_insert)); - // create incremental builder - Builder builder(triangulation, true); - builder.begin_triangulation(3); + CGAL_assertion(vertices_to_insert.end() + != std::find(vertices_to_insert.begin(), vertices_to_insert.end(), v1_init)); - collapse_type = _collapse_type; + std::unordered_map v2i;/*vertex of main tr - vertex of collapse tr*/ //To add the vertices only once + int index = 0; for (Vertex_handle vh : vertices_to_insert) { - if (v2v.left.find(vh) == v2v.left.end()) + if (v2i.find(vh) == v2i.end()) { - Vertex_handle new_vh = builder.add_vertex(); - new_vh->set_point(vh->point()); - new_vh->set_dimension(vh->in_dimension()); - - v2v.left.insert(std::make_pair(vh, new_vh)); + points.push_back(vh->point()); + v2i.insert(std::make_pair(vh, index++)); } } - std::vector cells_to_insert; - c3t3.triangulation().finite_incident_cells(v0_init, std::back_inserter(cells_to_insert)); - c3t3.triangulation().finite_incident_cells(v1_init, std::back_inserter(cells_to_insert)); + std::unordered_set cells_to_insert; + c3t3.triangulation().finite_incident_cells(v0_init, + std::inserter(cells_to_insert, cells_to_insert.end())); + c3t3.triangulation().finite_incident_cells(v1_init, + std::inserter(cells_to_insert, cells_to_insert.end())); - //To add the cells only once for (Cell_handle ch : cells_to_insert) { - if (c2c.left.find(ch) == c2c.left.end()) - { - Cell_handle new_ch = builder.add_cell(v2v.left.at(ch->vertex(0)), v2v.left.at(ch->vertex(1)), - v2v.left.at(ch->vertex(2)), v2v.left.at(ch->vertex(3))); - new_ch->set_subdomain_index(ch->subdomain_index()); - visitor.after_add_cell(ch, new_ch); - - c2c.left.insert(std::make_pair(ch, new_ch)); - } + Tet_with_ref t = { { v2i.at(ch->vertex(0)), + v2i.at(ch->vertex(1)), + v2i.at(ch->vertex(2)), + v2i.at(ch->vertex(3)), + ch->subdomain_index() } }; + finite_cells.push_back(t); } - // finished - builder.end_triangulation(); - } +// std::cout << "cells_to_insert : " << cells_to_insert.size() << std::endl; +// make_cells_set_manifold(c3t3, cells_to_insert); +// std::cout << "cells_to_insert : " << cells_to_insert.size() << std::endl; +// +// std::cout << "Collapse : " << point(v0_init->point()) << " " << point(v1_init->point()) << std::endl; +// debug::dump_cells_polylines(cells_to_insert, "collapse_cells_to_insert.polylines.txt"); +// debug::dump_cells(cells_to_insert, "collapse_cells_to_insert.mesh"); - void update() - { - vh0 = v2v.left.at(v0_init); - vh1 = v2v.left.at(v1_init); + // finished + std::vector new_vertices; + CGAL_assertion_code(bool built = ) + CGAL::build_triangulation(triangulation, + points, finite_cells, border_facets, + new_vertices, false/*verbose*/); + CGAL_assertion(built); + + if (!triangulation.tds().is_valid()) + { + std::cout << point(v0_init->point()) << " " << point(v1_init->point()) << std::endl; + debug::dump_cells_off(triangulation, "collapse_triangulation_finite_cells.off"); + CGAL_assertion(false); + } + + // update() + vh0 = new_vertices[v2i.at(v0_init) + 1]; + vh1 = new_vertices[v2i.at(v1_init) + 1]; Cell_handle ch; int i0, i1; not_an_edge = true; + CGAL_assertion(triangulation.tds().is_vertex(vh0)); + CGAL_assertion(triangulation.tds().is_vertex(vh1)); if (triangulation.is_edge(vh0, vh1, ch, i0, i1)) { edge = Edge(ch, i0, i1); not_an_edge = false; } + CGAL_assertion(!not_an_edge); - to_remove.clear(); - sharing_neighbor.clear(); + //std::unordered_map to_remove; //default is false + //std::unordered_map sharing_neighbor;//default is false - typedef typename Tr::Cell_circulator Cell_circulator; - Cell_circulator circ = triangulation.incident_cells(edge); - Cell_circulator done = circ; - do + //typedef typename Tr::Cell_circulator Cell_circulator; + //Cell_circulator circ = triangulation.incident_cells(edge); + //Cell_circulator done = circ; + //do + //{ + // to_remove[circ] = true; + // if (circ->neighbor(circ->index(vh0))->has_neighbor(circ->neighbor(circ->index(vh1)))) + // { + // sharing_neighbor[circ->neighbor(circ->index(vh0))] = true; + // sharing_neighbor[circ->neighbor(circ->index(vh1))] = true; + // } + //} while (++circ != done); + } + + void make_cells_set_manifold(const C3t3& c3t3, + std::unordered_set& cells) + { + typedef Vertex_handle Vh; + typedef std::array FV; + typedef std::pair EV; + + boost::unordered_map facets; + for (Cell_handle c : cells) { - to_remove[circ] = true; - if (circ->neighbor(circ->index(vh0))->has_neighbor(circ->neighbor(circ->index(vh1)))) + for (int i = 0; i < 4; ++i) { - sharing_neighbor[circ->neighbor(circ->index(vh0))] = true; - sharing_neighbor[circ->neighbor(circ->index(vh1))] = true; + const FV fvi = make_vertex_array(c->vertex((i + 1) % 4), + c->vertex((i + 2) % 4), + c->vertex((i + 3) % 4)); + typename boost::unordered_map::iterator fit = facets.find(fvi); + if(fit == facets.end()) + facets.insert(std::make_pair(fvi, 1)); + else + fit->second++; } - } while (++circ != done); + } - collapsed = false; + boost::unordered_map edges; + for (const std::pair& fvv : facets) + { + if(fvv.second != 1) + continue; + + for (int i = 0; i < 3; ++i) + { + const EV evi = make_vertex_pair(fvv.first[i], fvv.first[(i + 1) % 3]); + typename boost::unordered_map::iterator eit = edges.find(evi); + if (eit == edges.end()) + edges.insert(std::make_pair(evi, 1)); + else + eit->second++; + } + } + + for (const std::pair& evv : edges) + { + if (evv.second != 2) + { + c3t3.triangulation().finite_incident_cells(evv.first.first, + std::inserter(cells, cells.begin())); + c3t3.triangulation().finite_incident_cells(evv.first.second, + std::inserter(cells, cells.begin())); + } + } } Result_type collapse() @@ -179,7 +252,7 @@ public: std::vector cells_to_update; triangulation.incident_cells(vh1, std::back_inserter(cells_to_update)); -// Result_type r = VALID; + Result_type r = VALID; do { int v0_id = circ->index(vh0); @@ -191,8 +264,8 @@ public: int ch_id_in_n0 = n0_ch->index(circ); int ch_id_in_n1 = n1_ch->index(circ); -// if (n0_ch->has_neighbor(n1_ch)) -// r = SHARED_NEIGHBOR_PROBLEM; + if (n0_ch->has_neighbor(n1_ch)) + r = SHARED_NEIGHBOR_PROBLEM; //Update neighbors before removing cell n0_ch->set_neighbor(ch_id_in_n0, n1_ch); @@ -297,23 +370,17 @@ public: protected: Tr triangulation; - boost::bimap v2v;/*vertex of main tr - vertex of collapse tr*/ - boost::bimap c2c;/*cell of main tr - cell of collapse tr*/ - boost::unordered_map to_remove; //default is false - boost::unordered_map sharing_neighbor;//default is false + const Collapse_type collapse_type; - Collapse_type collapse_type; - - Vertex_handle v0_init; - Vertex_handle v1_init; + const Vertex_handle v0_init; + const Vertex_handle v1_init; Vertex_handle vh0; Vertex_handle vh1; Edge edge; - bool collapsed; bool not_an_edge; }; @@ -852,7 +919,7 @@ typename C3t3::Vertex_handle collapse_edge(typename C3t3::Edge& edge, const typename C3t3::Triangulation::Geom_traits::FT& sqhigh, const bool /* protect_boundaries */, CellSelector cell_selector, - Visitor& visitor) + Visitor& ) { typedef typename C3t3::Triangulation Tr; typedef typename Tr::Point Point; @@ -922,8 +989,13 @@ typename C3t3::Vertex_handle collapse_edge(typename C3t3::Edge& edge, if (are_edge_lengths_valid(edge, c3t3, new_pos, sqhigh, cell_selector/*, adaptive = false*/)) { - CollapseTriangulation local_tri(c3t3, edge, collapse_type, visitor); - local_tri.update(); + CGAL_assertion_code(typename Tr::Cell_handle dc); + CGAL_assertion_code(int di); + CGAL_assertion_code(int dj); + CGAL_assertion(c3t3.triangulation().is_edge(edge.first->vertex(edge.second), + edge.first->vertex(edge.third), dc, di, dj)); + + CollapseTriangulation local_tri(c3t3, edge, collapse_type); Result_type res = local_tri.collapse(); if (res == VALID) @@ -1087,6 +1159,8 @@ void collapse_short_edges(C3T3& c3t3, short_edges.insert(short_edge(make_vertex_pair(eshort), sqlen)); } + //debug::dump_c3t3(c3t3, "dump_after_collapse"); + //CGAL_assertion(c3t3.triangulation().tds().is_valid()); #ifdef CGAL_TETRAHEDRAL_REMESHING_VERBOSE ++nb_collapses; #endif diff --git a/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/tetrahedral_remeshing_helpers.h b/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/tetrahedral_remeshing_helpers.h index 28fe97dde59..89e313666c4 100644 --- a/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/tetrahedral_remeshing_helpers.h +++ b/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/tetrahedral_remeshing_helpers.h @@ -16,10 +16,12 @@ #include #include +#include #include #include #include +#include #include @@ -174,6 +176,16 @@ CGAL::Triple make_vertex_triple(const Vh vh0, const Vh vh1, const Vh return ft; } +template +std::array make_vertex_array(const Vh vh0, const Vh vh1, const Vh vh2) +{ + std::array ft = { {vh0, vh1, vh2} }; + if (ft[1] < ft[0]) std::swap(ft[0], ft[1]); + if (ft[2] < ft[1]) std::swap(ft[1], ft[2]); + if (ft[1] < ft[0]) std::swap(ft[0], ft[1]); + return ft; +} + template Facet canonical_facet(const Facet& f) { @@ -1046,6 +1058,29 @@ void dump_cells_off(const Tr& tr, const char* filename) ofs.close(); } +template +void dump_cells_polylines(const CellRange& cells, const char* filename) +{ + std::ofstream ofs(filename); + ofs.precision(17); + for (auto c : cells) + { + ofs << "2 " << point(c->vertex(0)->point()) << " " + << point(c->vertex(1)->point()) <vertex(0)->point()) << " " + << point(c->vertex(2)->point()) << std::endl; + ofs << "2 " << point(c->vertex(0)->point()) << " " + << point(c->vertex(3)->point()) << std::endl; + ofs << "2 " << point(c->vertex(1)->point()) << " " + << point(c->vertex(2)->point()) << std::endl; + ofs << "2 " << point(c->vertex(1)->point()) << " " + << point(c->vertex(3)->point()) << std::endl; + ofs << "2 " << point(c->vertex(2)->point()) << " " + << point(c->vertex(3)->point()) << std::endl; + } + ofs.close(); +} + template void dump_cells(const CellRange& cells, const IndexRange& indices, diff --git a/Tetrahedral_remeshing/package_info/Tetrahedral_remeshing/dependencies b/Tetrahedral_remeshing/package_info/Tetrahedral_remeshing/dependencies index 984e3ed4d28..8004efd9b07 100644 --- a/Tetrahedral_remeshing/package_info/Tetrahedral_remeshing/dependencies +++ b/Tetrahedral_remeshing/package_info/Tetrahedral_remeshing/dependencies @@ -22,7 +22,6 @@ Polygon_mesh_processing Profiling_tools Property_map Random_numbers -Skin_surface_3 Spatial_sorting STL_Extension Stream_support From 0a43f88f5d600b29ec26b3a46286fd20bc0759ab Mon Sep 17 00:00:00 2001 From: Jane Tournois Date: Mon, 4 May 2020 16:20:06 +0200 Subject: [PATCH 332/568] update .travis.yml --- .travis.yml | 53 ++++++++++++++++++++++++++++------------------------- 1 file changed, 28 insertions(+), 25 deletions(-) diff --git a/.travis.yml b/.travis.yml index 2c2fe62d3f4..26946424096 100644 --- a/.travis.yml +++ b/.travis.yml @@ -4,6 +4,34 @@ sudo: required git: depth: 3 env: + matrix: + PACKAGES_MATRIX + +compiler: clang +install: + - echo "$PWD" + - if [ -n "$TRAVIS_PULL_REQUEST_BRANCH" ] && [ "$PACKAGE" != CHECK ]; then DO_IGNORE=FALSE; for ARG in $(echo "$PACKAGE");do if [ "$ARG" = "Maintenance" ]; then continue; fi; . $PWD/.travis/test_package.sh "$PWD" "$ARG"; echo "DO_IGNORE is $DO_IGNORE"; if [ "$DO_IGNORE" = "FALSE" ]; then break; fi; done; if [ "$DO_IGNORE" = "TRUE" ]; then travis_terminate 0; fi;fi + - /usr/bin/time -f 'Spend time of %C -- %E (real)' bash .travis/install.sh + - export CXX=clang++ CC=clang; +before_script: + - wget -O doxygen_exe https://cgal.geometryfactory.com/~mgimeno/doxygen_exe + - sudo mv doxygen_exe /usr/bin/doxygen + - sudo chmod +x /usr/bin/doxygen + - mkdir -p build + - cd build + - /usr/bin/time -f 'Spend time of %C -- %E (real)' cmake -DCMAKE_CXX_FLAGS="-std=c++1y" -DCGAL_HEADER_ONLY=ON -DCMAKE_CXX_FLAGS_RELEASE=-DCGAL_NDEBUG -DWITH_examples=ON -DWITH_demos=ON -DWITH_tests=ON .. + - /usr/bin/time -f 'Spend time of %C -- %E (real)' make + - /usr/bin/time -f 'Spend time of %C -- %E (real)' sudo make install &>/dev/null + - cd .. +script: + - cd ./.travis + - /usr/bin/time -f 'Spend time of %C -- %E (real)' bash ./build_package.sh $PACKAGE +notifications: + email: + on_success: change + # default: always + on_failure: always + # default: always matrix: - PACKAGE='CHECK' - PACKAGE='AABB_tree Advancing_front_surface_reconstruction Algebraic_foundations ' @@ -53,28 +81,3 @@ env: - PACKAGE='Three Triangulation Triangulation_2 ' - PACKAGE='Triangulation_3 Union_find Visibility_2 ' - PACKAGE='Voronoi_diagram_2 wininst ' -compiler: clang -install: - - echo "$PWD" - - if [ -n "$TRAVIS_PULL_REQUEST_BRANCH" ] && [ "$PACKAGE" != CHECK ]; then DO_IGNORE=FALSE; for ARG in $(echo "$PACKAGE");do if [ "$ARG" = "Maintenance" ]; then continue; fi; . $PWD/.travis/test_package.sh "$PWD" "$ARG"; echo "DO_IGNORE is $DO_IGNORE"; if [ "$DO_IGNORE" = "FALSE" ]; then break; fi; done; if [ "$DO_IGNORE" = "TRUE" ]; then travis_terminate 0; fi;fi - - /usr/bin/time -f 'Spend time of %C -- %E (real)' bash .travis/install.sh - - export CXX=clang++ CC=clang; -before_script: - - wget -O doxygen_exe https://cgal.geometryfactory.com/~mgimeno/doxygen_exe - - sudo mv doxygen_exe /usr/bin/doxygen - - sudo chmod +x /usr/bin/doxygen - - mkdir -p build - - cd build - - /usr/bin/time -f 'Spend time of %C -- %E (real)' cmake -DCMAKE_CXX_FLAGS="-std=c++1y" -DCGAL_HEADER_ONLY=ON -DCMAKE_CXX_FLAGS_RELEASE=-DCGAL_NDEBUG -DWITH_examples=ON -DWITH_demos=ON -DWITH_tests=ON .. - - /usr/bin/time -f 'Spend time of %C -- %E (real)' make - - /usr/bin/time -f 'Spend time of %C -- %E (real)' sudo make install &>/dev/null - - cd .. -script: - - cd ./.travis - - /usr/bin/time -f 'Spend time of %C -- %E (real)' bash ./build_package.sh $PACKAGE -notifications: - email: - on_success: change - # default: always - on_failure: always - # default: always From 3951c38637df580ec3652f999294554acc434809 Mon Sep 17 00:00:00 2001 From: Laurent Rineau Date: Mon, 4 May 2020 18:54:19 +0200 Subject: [PATCH 333/568] Fix UBSAN error: do not bind reference to null pointer Equivalent to #4683 --- Mesh_3/include/CGAL/Compact_mesh_cell_base_3.h | 10 +++++----- TDS_3/include/CGAL/Triangulation_ds_cell_base_3.h | 8 ++++---- 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/Mesh_3/include/CGAL/Compact_mesh_cell_base_3.h b/Mesh_3/include/CGAL/Compact_mesh_cell_base_3.h index 0a055ddbb72..4df69ac5252 100644 --- a/Mesh_3/include/CGAL/Compact_mesh_cell_base_3.h +++ b/Mesh_3/include/CGAL/Compact_mesh_cell_base_3.h @@ -408,7 +408,7 @@ public: void set_neighbor(int i, Cell_handle n) { CGAL_triangulation_precondition( i >= 0 && i <= 3); - CGAL_triangulation_precondition( this != &*n ); + CGAL_triangulation_precondition( this != n.operator->() ); N[i] = n; } @@ -421,10 +421,10 @@ public: void set_neighbors(Cell_handle n0, Cell_handle n1, Cell_handle n2, Cell_handle n3) { - CGAL_triangulation_precondition( this != &*n0 ); - CGAL_triangulation_precondition( this != &*n1 ); - CGAL_triangulation_precondition( this != &*n2 ); - CGAL_triangulation_precondition( this != &*n3 ); + CGAL_triangulation_precondition( this != n0.operator->() ); + CGAL_triangulation_precondition( this != n1.operator->() ); + CGAL_triangulation_precondition( this != n2.operator->() ); + CGAL_triangulation_precondition( this != n3.operator->() ); N[0] = n0; N[1] = n1; N[2] = n2; diff --git a/TDS_3/include/CGAL/Triangulation_ds_cell_base_3.h b/TDS_3/include/CGAL/Triangulation_ds_cell_base_3.h index 423b072f9bf..664fb53b5b2 100644 --- a/TDS_3/include/CGAL/Triangulation_ds_cell_base_3.h +++ b/TDS_3/include/CGAL/Triangulation_ds_cell_base_3.h @@ -190,10 +190,10 @@ public: void set_neighbors(Cell_handle n0, Cell_handle n1, Cell_handle n2, Cell_handle n3) { - CGAL_triangulation_precondition( this != &*n0 ); - CGAL_triangulation_precondition( this != &*n1 ); - CGAL_triangulation_precondition( this != &*n2 ); - CGAL_triangulation_precondition( this != &*n3 ); + CGAL_triangulation_precondition( this != n0.operator->() ); + CGAL_triangulation_precondition( this != n1.operator->() ); + CGAL_triangulation_precondition( this != n2.operator->() ); + CGAL_triangulation_precondition( this != n3.operator->() ); N[0] = n0; N[1] = n1; N[2] = n2; From 5988befc687ec6d0e93c65c93750e9f4577f104c Mon Sep 17 00:00:00 2001 From: Maxime Gimeno Date: Tue, 5 May 2020 10:02:32 +0200 Subject: [PATCH 334/568] Fix remaining std::max --- .../Plugins/Classification/Cluster_classification.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Polyhedron/demo/Polyhedron/Plugins/Classification/Cluster_classification.cpp b/Polyhedron/demo/Polyhedron/Plugins/Classification/Cluster_classification.cpp index 3f77fe4efff..0a4c06f9feb 100644 --- a/Polyhedron/demo/Polyhedron/Plugins/Classification/Cluster_classification.cpp +++ b/Polyhedron/demo/Polyhedron/Plugins/Classification/Cluster_classification.cpp @@ -527,7 +527,7 @@ void Cluster_classification::change_color (int index, float* vmin, float* vmax) int cid = m_cluster_id[*it]; if (cid != -1) { - float v = std::max (0.f, (std::min)(1.f, m_label_probabilities[corrected_index][cid])); + float v = (std::max) (0.f, (std::min)(1.f, m_label_probabilities[corrected_index][cid])); m_points->point_set()->set_color(*it, ramp.r(v) * 255, ramp.g(v) * 255, ramp.b(v) * 255); } else From 12eb23c4955c9c81620b7f8b645fad86ea149b64 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9bastien=20Loriot?= Date: Tue, 5 May 2020 11:57:09 +0200 Subject: [PATCH 335/568] add more debug --- .../Corefinement/Face_graph_output_builder.h | 33 +++++++++++++++++++ 1 file changed, 33 insertions(+) diff --git a/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/internal/Corefinement/Face_graph_output_builder.h b/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/internal/Corefinement/Face_graph_output_builder.h index 325a3693d5b..c3929c5c3cc 100644 --- a/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/internal/Corefinement/Face_graph_output_builder.h +++ b/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/internal/Corefinement/Face_graph_output_builder.h @@ -682,6 +682,10 @@ public: halfedge_descriptor h1 = it->second.first[&tm1]; halfedge_descriptor h2 = it->second.first[&tm2]; +#ifdef CGAL_COREFINEMENT_DEBUG + std::cout << "Looking at triangles around edge " << tm1.point(source(h1, tm1)) << " " << tm1.point(target(h1, tm1)) << "\n"; +#endif + CGAL_assertion(ids.first==vertex_to_node_id1[source(h1,tm1)]); CGAL_assertion(ids.second==vertex_to_node_id1[target(h1,tm1)]); CGAL_assertion(ids.first==vertex_to_node_id2[source(h2,tm2)]); @@ -713,6 +717,9 @@ public: //Nothing allowed if (!used_to_clip_a_surface) { +#ifdef CGAL_COREFINEMENT_DEBUG + std::cout << " Non-manifold edge case 1\n"; +#endif impossible_operation.set(); return; } @@ -723,6 +730,9 @@ public: //Ambiguous, we can do nothing if (!used_to_clip_a_surface) { +#ifdef CGAL_COREFINEMENT_DEBUG + std::cout << " Non-manifold edge case 2\n"; +#endif impossible_operation.set(); return; } @@ -776,6 +786,9 @@ public: { CGAL_assertion(!used_to_clip_a_surface); //Ambiguous, we do nothing +#ifdef CGAL_COREFINEMENT_DEBUG + std::cout << " Non-manifold edge case 3\n"; +#endif impossible_operation.set(); return; } @@ -971,6 +984,9 @@ public: // poly_second - poly_first = {0} // poly_first \cap poly_second = q1q2 // opposite( poly_first U poly_second ) = p2p1 +#ifdef CGAL_COREFINEMENT_DEBUG + std::cout << " Non-manifold edge case 4\n"; +#endif impossible_operation.set(TM1_MINUS_TM2); // tm1-tm2 is non-manifold } else{ @@ -982,7 +998,12 @@ public: is_patch_inside_tm2.set(patch_id_p1); is_patch_inside_tm2.set(patch_id_p2); if (!used_to_clip_a_surface) + { +#ifdef CGAL_COREFINEMENT_DEBUG + std::cout << " Non-manifold edge case 5\n"; +#endif impossible_operation.set(INTERSECTION); // tm1 n tm2 is non-manifold + } } } else @@ -997,6 +1018,9 @@ public: { if (!used_to_clip_a_surface) { +#ifdef CGAL_COREFINEMENT_DEBUG + std::cout << " Non-manifold edge case 6\n"; +#endif impossible_operation.set(); return; } @@ -1018,6 +1042,9 @@ public: { if (!used_to_clip_a_surface) { +#ifdef CGAL_COREFINEMENT_DEBUG + std::cout << " Non-manifold edge case 7\n"; +#endif impossible_operation.set(); return; } @@ -1039,6 +1066,9 @@ public: // poly_second - poly_first = q1q2 // poly_first \cap poly_second = {0} // opposite( poly_first U poly_second ) = p2q1 U q2p1 +#ifdef CGAL_COREFINEMENT_DEBUG + std::cout << " Non-manifold edge case 8\n"; +#endif impossible_operation.set(UNION); // tm1 U tm2 is non-manifold } else{ @@ -1049,6 +1079,9 @@ public: // poly_second - poly_first = q1p1 U p2q2 // poly_first \cap poly_second = p1p2 // opposite( poly_first U poly_second ) = q2q1 +#ifdef CGAL_COREFINEMENT_DEBUG + std::cout << " Non-manifold edge case 9\n"; +#endif impossible_operation.set(TM2_MINUS_TM1); // tm2 - tm1 is non-manifold } } From 0c85cbfcf4a8a9c90f946b08fcd56975763bd952 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9bastien=20Loriot?= Date: Tue, 5 May 2020 12:16:14 +0200 Subject: [PATCH 336/568] simplify example --- .../corefinement_consecutive_bool_op.cpp | 87 +++++++------------ 1 file changed, 29 insertions(+), 58 deletions(-) diff --git a/Polygon_mesh_processing/examples/Polygon_mesh_processing/corefinement_consecutive_bool_op.cpp b/Polygon_mesh_processing/examples/Polygon_mesh_processing/corefinement_consecutive_bool_op.cpp index bbe55ca4cbc..7b13f109a6d 100644 --- a/Polygon_mesh_processing/examples/Polygon_mesh_processing/corefinement_consecutive_bool_op.cpp +++ b/Polygon_mesh_processing/examples/Polygon_mesh_processing/corefinement_consecutive_bool_op.cpp @@ -16,7 +16,7 @@ typedef Mesh::Property_map Exact_point_computed; namespace PMP = CGAL::Polygon_mesh_processing; namespace params = PMP::parameters; -struct Coref_point_map +struct Exact_vertex_point_map { // typedef for the property map typedef boost::property_traits::value_type value_type; @@ -25,64 +25,39 @@ struct Coref_point_map typedef boost::property_traits::key_type key_type; // exterior references - Exact_point_computed* exact_point_computed_ptr; - Exact_point_map* exact_point_ptr; - Mesh* mesh_ptr; - - Exact_point_computed& exact_point_computed() const - { - CGAL_assertion(exact_point_computed_ptr!=NULL); - return *exact_point_computed_ptr; - } - - Exact_point_map& exact_point() const - { - CGAL_assertion(exact_point_ptr!=NULL); - return *exact_point_ptr; - } - - Mesh& mesh() const - { - CGAL_assertion(mesh_ptr!=NULL); - return *mesh_ptr; - } + Exact_point_map exact_point_map; + Mesh* tm_ptr; // Converters CGAL::Cartesian_converter to_exact; CGAL::Cartesian_converter to_input; - Coref_point_map() - : exact_point_computed_ptr(NULL) - , exact_point_ptr(NULL) - , mesh_ptr(NULL) + Exact_vertex_point_map() + : tm_ptr(nullptr) {} - Coref_point_map(Exact_point_map& ep, - Exact_point_computed& epc, - Mesh& m) - : exact_point_computed_ptr(&epc) - , exact_point_ptr(&ep) - , mesh_ptr(&m) - {} - - friend - reference get(const Coref_point_map& map, key_type k) + Exact_vertex_point_map(const Exact_point_map& ep, Mesh& tm) + : exact_point_map(ep) + , tm_ptr(&tm) { - // create exact point if it does not exist - if (!map.exact_point_computed()[k]){ - map.exact_point()[k]=map.to_exact(map.mesh().point(k)); - map.exact_point_computed()[k]=true; - } - return map.exact_point()[k]; + for (Mesh::Vertex_index v : vertices(tm)) + exact_point_map[v]=to_exact(tm.point(v)); } friend - void put(const Coref_point_map& map, key_type k, const EK::Point_3& p) + reference get(const Exact_vertex_point_map& map, key_type k) { - map.exact_point_computed()[k]=true; - map.exact_point()[k]=p; + CGAL_precondition(map.tm_ptr!=nullptr); + return map.exact_point_map[k]; + } + + friend + void put(const Exact_vertex_point_map& map, key_type k, const EK::Point_3& p) + { + CGAL_precondition(map.tm_ptr!=nullptr); + map.exact_point_map[k]=p; // create the input point from the exact one - map.mesh().point(k)=map.to_input(p); + map.tm_ptr->point(k)=map.to_input(p); } }; @@ -109,30 +84,26 @@ int main(int argc, char* argv[]) Exact_point_map mesh1_exact_points = mesh1.add_property_map("e:exact_point").first; - Exact_point_computed mesh1_exact_points_computed = - mesh1.add_property_map("e:exact_points_computed").first; Exact_point_map mesh2_exact_points = mesh2.add_property_map("e:exact_point").first; - Exact_point_computed mesh2_exact_points_computed = - mesh2.add_property_map("e:exact_points_computed").first; - Coref_point_map mesh1_pm(mesh1_exact_points, mesh1_exact_points_computed, mesh1); - Coref_point_map mesh2_pm(mesh2_exact_points, mesh2_exact_points_computed, mesh2); + Exact_vertex_point_map mesh1_vpm(mesh1_exact_points, mesh1); + Exact_vertex_point_map mesh2_vpm(mesh2_exact_points, mesh2); if ( PMP::corefine_and_compute_intersection(mesh1, mesh2, mesh1, - params::vertex_point_map(mesh1_pm), - params::vertex_point_map(mesh2_pm), - params::vertex_point_map(mesh1_pm) ) ) + params::vertex_point_map(mesh1_vpm), + params::vertex_point_map(mesh2_vpm), + params::vertex_point_map(mesh1_vpm) ) ) { if ( PMP::corefine_and_compute_union(mesh1, mesh2, mesh2, - params::vertex_point_map(mesh1_pm), - params::vertex_point_map(mesh2_pm), - params::vertex_point_map(mesh2_pm) ) ) + params::vertex_point_map(mesh1_vpm), + params::vertex_point_map(mesh2_vpm), + params::vertex_point_map(mesh2_vpm) ) ) { std::cout << "Intersection and union were successfully computed\n"; std::ofstream output("inter_union.off"); From 53eb106f928452a0329babaa7035743be16de4dd Mon Sep 17 00:00:00 2001 From: Rui Ventura Date: Wed, 6 May 2020 07:44:59 +0100 Subject: [PATCH 337/568] Add missing `print` method to `Aff_transformationC3` --- .../CGAL/Cartesian/Aff_transformation_3.h | 19 +++++++++++++++---- .../CGAL/Cartesian/Aff_transformation_rep_3.h | 4 ++-- 2 files changed, 17 insertions(+), 6 deletions(-) diff --git a/Cartesian_kernel/include/CGAL/Cartesian/Aff_transformation_3.h b/Cartesian_kernel/include/CGAL/Cartesian/Aff_transformation_3.h index 16ed267a7c4..e2d4e677bc3 100644 --- a/Cartesian_kernel/include/CGAL/Cartesian/Aff_transformation_3.h +++ b/Cartesian_kernel/include/CGAL/Cartesian/Aff_transformation_3.h @@ -178,6 +178,9 @@ public: Aff_transformation_3 operator*(const Aff_transformationC3 &t) const { return (*this->Ptr()) * (*t.Ptr()); } + std::ostream & + print(std::ostream &os) const; + bool operator==(const Aff_transformationC3 &t)const { for(int i=0; i<3; ++i) @@ -197,13 +200,21 @@ protected: }; +template < class R > +std::ostream& +Aff_transformationC3::print(std::ostream &os) const +{ + this->Ptr()->print(os); + return os; +} + #ifndef CGAL_NO_OSTREAM_INSERT_AFF_TRANSFORMATIONC3 template < class R > -std::ostream &operator<<(std::ostream &os, - const Aff_transformationC3 &t) +std::ostream& +operator<<(std::ostream &os, const Aff_transformationC3 &t) { - t.print(os); - return os; + t.print(os); + return os; } #endif // CGAL_NO_OSTREAM_INSERT_AFF_TRANSFORMATIONC3 diff --git a/Cartesian_kernel/include/CGAL/Cartesian/Aff_transformation_rep_3.h b/Cartesian_kernel/include/CGAL/Cartesian/Aff_transformation_rep_3.h index 945dbfa23b3..67cfd4a0c94 100644 --- a/Cartesian_kernel/include/CGAL/Cartesian/Aff_transformation_rep_3.h +++ b/Cartesian_kernel/include/CGAL/Cartesian/Aff_transformation_rep_3.h @@ -192,8 +192,8 @@ public: virtual std::ostream &print(std::ostream &os) const { os <<"Aff_transformationC3("< Date: Wed, 6 May 2020 09:01:07 +0200 Subject: [PATCH 338/568] Update CHANGES.md --- Installation/CHANGES.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/Installation/CHANGES.md b/Installation/CHANGES.md index dbc8910ac48..2f973b6c657 100644 --- a/Installation/CHANGES.md +++ b/Installation/CHANGES.md @@ -21,6 +21,10 @@ Release History the signed distance of two points to a line, or the line passing through two given points. Corresponding functors in the model (`Compare_signed_distance_to_line_2`) are also added. +### Point Set Processing + - Add a function `CGAL::cluster_point_set()` that segments a point + cloud into connected components based on a distance threshold. + ### 2D Triangulations - Add function `split_subconstraint_graph_into_constraints()` to `Constrained_triangulation_plus_2` to initialize the constraints From 098cc6abde450a46061723a56c0f745692808294 Mon Sep 17 00:00:00 2001 From: Maxime Gimeno Date: Wed, 6 May 2020 11:31:13 +0200 Subject: [PATCH 339/568] Fix a PMP example --- .../Polygon_mesh_processing/repair_polygon_soup_example.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Polygon_mesh_processing/examples/Polygon_mesh_processing/repair_polygon_soup_example.cpp b/Polygon_mesh_processing/examples/Polygon_mesh_processing/repair_polygon_soup_example.cpp index e44be56106e..4d9003f0d6a 100644 --- a/Polygon_mesh_processing/examples/Polygon_mesh_processing/repair_polygon_soup_example.cpp +++ b/Polygon_mesh_processing/examples/Polygon_mesh_processing/repair_polygon_soup_example.cpp @@ -11,7 +11,7 @@ typedef CGAL::Exact_predicates_inexact_constructions_kernel K; typedef K::Point_3 Point_3; -typedef std::vector Polygon; +typedef std::vector CGAL_Polygon; typedef CGAL::Surface_mesh Mesh; namespace PMP = CGAL::Polygon_mesh_processing; @@ -20,7 +20,7 @@ int main(int, char**) { // First, construct a polygon soup with some problems std::vector points; - std::vector polygons; + std::vector polygons; points.push_back(Point_3(0,0,0)); points.push_back(Point_3(1,0,0)); @@ -30,7 +30,7 @@ int main(int, char**) points.push_back(Point_3(0,1,0)); // duplicate point points.push_back(Point_3(0,-2,0)); // unused point - Polygon p; + CGAL_Polygon p; p.push_back(0); p.push_back(1); p.push_back(2); polygons.push_back(p); From e3f2660b048263dc37074e6a7b2ee1f382e5af11 Mon Sep 17 00:00:00 2001 From: Maxime Gimeno Date: Wed, 6 May 2020 11:33:27 +0200 Subject: [PATCH 340/568] Fix an item in the demo --- .../Plugins/Classification/Surface_mesh_item_classification.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Polyhedron/demo/Polyhedron/Plugins/Classification/Surface_mesh_item_classification.cpp b/Polyhedron/demo/Polyhedron/Plugins/Classification/Surface_mesh_item_classification.cpp index 1d033c02fdb..f726fe42cf4 100644 --- a/Polyhedron/demo/Polyhedron/Plugins/Classification/Surface_mesh_item_classification.cpp +++ b/Polyhedron/demo/Polyhedron/Plugins/Classification/Surface_mesh_item_classification.cpp @@ -151,7 +151,7 @@ void Surface_mesh_item_classification::change_color (int index, float* vmin, flo { BOOST_FOREACH(face_descriptor fd, faces(*(m_mesh->polyhedron()))) { - float v = std::max (0.f, (std::min)(1.f, m_label_probabilities[corrected_index][fd])); + float v = (std::max) (0.f, (std::min)(1.f, m_label_probabilities[corrected_index][fd])); m_color[fd] = CGAL::Color((unsigned char)(ramp.r(v) * 255), (unsigned char)(ramp.g(v) * 255), (unsigned char)(ramp.b(v) * 255)); From 57b37e3e1dba65d2ad1fdd8a1f33debc3faf7650 Mon Sep 17 00:00:00 2001 From: Laurent Rineau Date: Wed, 6 May 2020 12:08:54 +0200 Subject: [PATCH 341/568] Fix so that is runs on Fedora --- .../developer_scripts/Bundle_polyhedron_demo_with_appimage.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Scripts/developer_scripts/Bundle_polyhedron_demo_with_appimage.sh b/Scripts/developer_scripts/Bundle_polyhedron_demo_with_appimage.sh index 146060a4000..815ca57f302 100644 --- a/Scripts/developer_scripts/Bundle_polyhedron_demo_with_appimage.sh +++ b/Scripts/developer_scripts/Bundle_polyhedron_demo_with_appimage.sh @@ -4,5 +4,5 @@ if [ "$1" == '--help' ]; then echo "Builds and packages the Polyhedron demo form the CGAL dir." exit 0 fi -docker run --rm -v "$2":/results:Z -v "$1":/cgal:ro -e "NUMBER_OF_DEDICATED_CORES=$3" docker.io/cgal/bundle-3d-demo +docker run --rm -v "$2":/results:Z -v "$1":/cgal:ro,z -e "NUMBER_OF_DEDICATED_CORES=$3" docker.io/cgal/bundle-3d-demo From 841a2505fa470bdb054bb935cbf045994c356c17 Mon Sep 17 00:00:00 2001 From: Laurent Rineau Date: Wed, 6 May 2020 12:09:42 +0200 Subject: [PATCH 342/568] Catch errors earlier If `$1` and `$2` is either empty, or not a directory, then display the help. Maybe we should check that `$1` is indeed a CGAL directory. --- .../developer_scripts/Bundle_polyhedron_demo_with_appimage.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Scripts/developer_scripts/Bundle_polyhedron_demo_with_appimage.sh b/Scripts/developer_scripts/Bundle_polyhedron_demo_with_appimage.sh index 815ca57f302..dde1f1a2773 100644 --- a/Scripts/developer_scripts/Bundle_polyhedron_demo_with_appimage.sh +++ b/Scripts/developer_scripts/Bundle_polyhedron_demo_with_appimage.sh @@ -1,5 +1,5 @@ #!/bin/bash -if [ "$1" == '--help' ]; then +if [ "$1" == '--help' -o ! -d "$1" -o ! -d "$2" ]; then echo "Usage: $0 " echo "Builds and packages the Polyhedron demo form the CGAL dir." exit 0 From 6fe47eddbe286f7a8707c94f2f444381e848d278 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mael=20Rouxel-Labb=C3=A9?= Date: Wed, 6 May 2020 12:10:48 +0200 Subject: [PATCH 343/568] Make OBB work with EPECK_with_sqrt --- .../Optimal_bounding_box/internal/evolution.h | 9 +++++---- .../internal/optimize_2.h | 19 +++++++++++++++++++ 2 files changed, 24 insertions(+), 4 deletions(-) diff --git a/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/internal/evolution.h b/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/internal/evolution.h index 477c1294fa1..4680993e372 100644 --- a/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/internal/evolution.h +++ b/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/internal/evolution.h @@ -76,7 +76,7 @@ public: std::generate(group4.begin(), group4.end(), [&]{ return m_rng.get_int(0, im); }); // crossover I, pick A or B - constexpr FT lweight = 0.4, uweight = 0.6; + const FT lweight = 0.4, uweight = 0.6; std::vector new_simplices(m); @@ -160,8 +160,6 @@ public: std::cout << std::endl; #endif - // optimize the current best rotation by using the exact OBB 2D algorithm - // along the axes of the current best OBB m_best_v = &(m_population.get_best_vertex()); Matrix& best_m = m_best_v->matrix(); @@ -170,7 +168,10 @@ public: std::cout << "fitness: " << m_best_v->fitness() << std::endl; #endif - optimize_along_OBB_axes(best_m, m_points, m_traits); + // optimize the current best rotation by using the exact OBB 2D algorithm + // along the axes of the current best OBB + Optimizer_along_axes optimizer_2D; + optimizer_2D(best_m, m_points, m_traits); m_best_v->fitness() = compute_fitness(best_m, m_points, m_traits); // stopping criteria diff --git a/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/internal/optimize_2.h b/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/internal/optimize_2.h index 7bd6b4be3e6..d8497ba486a 100644 --- a/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/internal/optimize_2.h +++ b/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/internal/optimize_2.h @@ -214,6 +214,25 @@ void optimize_along_OBB_axes(typename Traits::Matrix& rot, } } +// This operation makes no sense if an exact number type is used, so skip it, if so +template ::Is_exact> +struct Optimizer_along_axes +{ + template + void operator()(typename Traits::Matrix& rot, const PointRange& points, const Traits& traits) + { + return optimize_along_OBB_axes(rot, points, traits); + } +}; + +template +struct Optimizer_along_axes +{ + template + void operator()(typename Traits::Matrix&, const PointRange&, const Traits&) { } +}; + } // namespace internal } // namespace Optimal_bounding_box } // namespace CGAL From 9611eada726046fa017c3dad6fb7005c5a49e318 Mon Sep 17 00:00:00 2001 From: Laurent Rineau Date: Wed, 6 May 2020 12:10:57 +0200 Subject: [PATCH 344/568] Add the +x permission bit --- Scripts/developer_scripts/Bundle_polyhedron_demo_with_appimage.sh | 0 1 file changed, 0 insertions(+), 0 deletions(-) mode change 100644 => 100755 Scripts/developer_scripts/Bundle_polyhedron_demo_with_appimage.sh diff --git a/Scripts/developer_scripts/Bundle_polyhedron_demo_with_appimage.sh b/Scripts/developer_scripts/Bundle_polyhedron_demo_with_appimage.sh old mode 100644 new mode 100755 From c2f7b46c0611205342548b418a522912cc6fa59a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mael=20Rouxel-Labb=C3=A9?= Date: Wed, 6 May 2020 12:11:03 +0200 Subject: [PATCH 345/568] Avoid needless loss of precision with BBox_3 usage --- .../oriented_bounding_box.h | 40 +++++++++++++------ 1 file changed, 27 insertions(+), 13 deletions(-) diff --git a/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/oriented_bounding_box.h b/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/oriented_bounding_box.h index 2c9ed9cda67..07c42a9b4b2 100644 --- a/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/oriented_bounding_box.h +++ b/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/oriented_bounding_box.h @@ -23,7 +23,6 @@ #include #include -#include #include #include #include @@ -64,25 +63,40 @@ void construct_oriented_bounding_box(const PointRange& points, std::array& obb_points, const Traits& traits) { + typedef typename Traits::FT FT; typedef typename Traits::Point_3 Point; + CGAL_precondition(!points.empty()); + // Construct the bbox of the transformed point set - CGAL::Bbox_3 bbox; - for(const Point& pt : points) + typename PointRange::const_iterator pit = std::begin(points); + const Point& first_pt = *pit++; + const Point first_rot_pt = transformation.transform(first_pt); + FT xmin = first_rot_pt.x(), xmax = first_rot_pt.x(); + FT ymin = first_rot_pt.y(), ymax = first_rot_pt.y(); + FT zmin = first_rot_pt.z(), zmax = first_rot_pt.z(); + + for(typename PointRange::const_iterator end=std::end(points); pit!=end; ++pit) { - const Point rotated_pt = transformation.transform(pt); - bbox += traits.construct_bbox_3_object()(rotated_pt); + const Point rot_pt = transformation.transform(*pit); + + xmin = (std::min)(rot_pt.x(), xmin); + ymin = (std::min)(rot_pt.y(), ymin); + zmin = (std::min)(rot_pt.z(), zmin); + xmax = (std::max)(rot_pt.x(), xmax); + ymax = (std::max)(rot_pt.y(), ymax); + zmax = (std::max)(rot_pt.z(), zmax); } - obb_points[0] = Point(bbox.xmin(), bbox.ymin(), bbox.zmin()); - obb_points[1] = Point(bbox.xmax(), bbox.ymin(), bbox.zmin()); - obb_points[2] = Point(bbox.xmax(), bbox.ymax(), bbox.zmin()); - obb_points[3] = Point(bbox.xmin(), bbox.ymax(), bbox.zmin()); + obb_points[0] = Point(xmin, ymin, zmin); + obb_points[1] = Point(xmax, ymin, zmin); + obb_points[2] = Point(xmax, ymax, zmin); + obb_points[3] = Point(xmin, ymax, zmin); - obb_points[4] = Point(bbox.xmin(), bbox.ymax(), bbox.zmax()); // see order in make_hexahedron()... - obb_points[5] = Point(bbox.xmin(), bbox.ymin(), bbox.zmax()); - obb_points[6] = Point(bbox.xmax(), bbox.ymin(), bbox.zmax()); - obb_points[7] = Point(bbox.xmax(), bbox.ymax(), bbox.zmax()); + obb_points[4] = Point(xmin, ymax, zmax); // see order in make_hexahedron()... + obb_points[5] = Point(xmin, ymin, zmax); + obb_points[6] = Point(xmax, ymin, zmax); + obb_points[7] = Point(xmax, ymax, zmax); // Apply the inverse rotation to the rotated axis aligned bounding box for(std::size_t i=0; i<8; ++i) From 4092727cf856181d24ccdb983711218902013477 Mon Sep 17 00:00:00 2001 From: Laurent Rineau Date: Fri, 1 May 2020 15:00:51 +0200 Subject: [PATCH 346/568] Fix CGAL_parse_version_h.cmake when the minor version is less than 10 --- Installation/cmake/modules/CGAL_parse_version_h.cmake | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/Installation/cmake/modules/CGAL_parse_version_h.cmake b/Installation/cmake/modules/CGAL_parse_version_h.cmake index c7b134d4229..fa0b22cd316 100644 --- a/Installation/cmake/modules/CGAL_parse_version_h.cmake +++ b/Installation/cmake/modules/CGAL_parse_version_h.cmake @@ -11,7 +11,8 @@ function(cgal_parse_version_h version_h_file name) # CMAKE_MATCH_3 and CMAKE_MATCH_4 corresponds to the two sub-expressions # of the alternative, and cannot be non-empty at the same time. set(${ARGV2} "${CMAKE_MATCH_3}${CMAKE_MATCH_4}" PARENT_SCOPE) # major version - set(${ARGV3} "${CMAKE_MATCH_5}" PARENT_SCOPE) # minor version + MATH(EXPR ${ARGV3} "${CMAKE_MATCH_5}") # minor version without leading 0 + set(${ARGV3} "${${ARGV3}}" PARENT_SCOPE) set(${ARGV4} "${CMAKE_MATCH_6}" PARENT_SCOPE) # patch number set(${ARGV5} "${CMAKE_MATCH_7}" PARENT_SCOPE) # build number endfunction() From abf414df81cef3dddf9b1ae810168a71b182bb70 Mon Sep 17 00:00:00 2001 From: Laurent Rineau Date: Fri, 1 May 2020 16:24:19 +0200 Subject: [PATCH 347/568] Change create_new_release to use CGALConfigVersion.cmake as input --- Installation/lib/cmake/CGAL/CGALConfigVersion.cmake | 3 ++- Maintenance/release_building/BUGFIX_NUMBER | 1 - Maintenance/release_building/MAJOR_NUMBER | 1 - Maintenance/release_building/MINOR_NUMBER | 1 - Maintenance/release_building/public_release_name | 1 - Scripts/developer_scripts/create_new_release | 13 ++++++++++--- .../create_new_release_evaluate_versions.cmake | 6 ++++++ 7 files changed, 18 insertions(+), 8 deletions(-) delete mode 100644 Maintenance/release_building/BUGFIX_NUMBER delete mode 100644 Maintenance/release_building/MAJOR_NUMBER delete mode 100644 Maintenance/release_building/MINOR_NUMBER delete mode 100644 Maintenance/release_building/public_release_name create mode 100644 Scripts/developer_scripts/create_new_release_evaluate_versions.cmake diff --git a/Installation/lib/cmake/CGAL/CGALConfigVersion.cmake b/Installation/lib/cmake/CGAL/CGALConfigVersion.cmake index 77b73b21be0..16aa829ea9d 100644 --- a/Installation/lib/cmake/CGAL/CGALConfigVersion.cmake +++ b/Installation/lib/cmake/CGAL/CGALConfigVersion.cmake @@ -1,7 +1,8 @@ set(CGAL_MAJOR_VERSION 4) set(CGAL_MINOR_VERSION 14) set(CGAL_BUGFIX_VERSION 4) -set(CGAL_VERSION_PUBLIC_RELEASE_NAME "CGAL-4.14.4") +set(CGAL_VERSION_PUBLIC_RELEASE_VERSION "4.14.4") +set(CGAL_VERSION_PUBLIC_RELEASE_NAME "CGAL-${CGAL_VERSION_PUBLIC_RELEASE_VERSION}") if (CGAL_BUGFIX_VERSION AND CGAL_BUGFIX_VERSION GREATER 0) set(CGAL_CREATED_VERSION_NUM "${CGAL_MAJOR_VERSION}.${CGAL_MINOR_VERSION}.${CGAL_BUGFIX_VERSION}") diff --git a/Maintenance/release_building/BUGFIX_NUMBER b/Maintenance/release_building/BUGFIX_NUMBER deleted file mode 100644 index b8626c4cff2..00000000000 --- a/Maintenance/release_building/BUGFIX_NUMBER +++ /dev/null @@ -1 +0,0 @@ -4 diff --git a/Maintenance/release_building/MAJOR_NUMBER b/Maintenance/release_building/MAJOR_NUMBER deleted file mode 100644 index b8626c4cff2..00000000000 --- a/Maintenance/release_building/MAJOR_NUMBER +++ /dev/null @@ -1 +0,0 @@ -4 diff --git a/Maintenance/release_building/MINOR_NUMBER b/Maintenance/release_building/MINOR_NUMBER deleted file mode 100644 index 8351c19397f..00000000000 --- a/Maintenance/release_building/MINOR_NUMBER +++ /dev/null @@ -1 +0,0 @@ -14 diff --git a/Maintenance/release_building/public_release_name b/Maintenance/release_building/public_release_name deleted file mode 100644 index f36bb69a3f9..00000000000 --- a/Maintenance/release_building/public_release_name +++ /dev/null @@ -1 +0,0 @@ -CGAL-4.14.4 diff --git a/Scripts/developer_scripts/create_new_release b/Scripts/developer_scripts/create_new_release index 9f4ddc266df..443a068a78a 100755 --- a/Scripts/developer_scripts/create_new_release +++ b/Scripts/developer_scripts/create_new_release @@ -180,9 +180,13 @@ else fi # Set the major/minor/bugfix release numbers NUMBERS_DIR=${SOURCES_DIR}/Maintenance/release_building -MAJOR_NUMBER=`cat ${NUMBERS_DIR}/MAJOR_NUMBER` # 2 digits max -MINOR_NUMBER=`cat ${NUMBERS_DIR}/MINOR_NUMBER` # 2 digits max -BUGFIX_NUMBER=`cat ${NUMBERS_DIR}/BUGFIX_NUMBER` # 1 digit max +if [ -f ${NUMBERS_DIR}/MAJOR_NUMBER ]; then + MAJOR_NUMBER=`cat ${NUMBERS_DIR}/MAJOR_NUMBER` # 2 digits max + MINOR_NUMBER=`cat ${NUMBERS_DIR}/MINOR_NUMBER` # 2 digits max + BUGFIX_NUMBER=`cat ${NUMBERS_DIR}/BUGFIX_NUMBER` # 1 digit max +else + eval $(cmake -DCGALCONFIGVERSIONFILE=${SOURCES_DIR}/CGALConfigVersion.cmake -P ${SOURCES_DIR}/Scripts/developer_scripts/create_new_release_evaluate_versions.cmake 2>&1) +fi # Do not show the bugfix number if it is 0. if [ x"$BUGFIX_NUMBER" != "x0" ]; then @@ -302,6 +306,9 @@ if [ -n "$DO_PUBLIC" ]; then else public_release_name="CGAL-${public_release_version}" fi + if ! [ -f ${NUMBERS_DIR}/MAJOR_NUMBER ]; then + eval $(cmake -DCGALCONFIGVERSIONFILE=${SOURCES_DIR}/CGALConfigVersion.cmake -P ${SOURCES_DIR}/Scripts/developer_scripts/create_new_release_evaluate_versions.cmake 2>&1) + fi cmake -DGIT_REPO=${SOURCES_DIR} -DPUBLIC="ON" -DDESTINATION="${DESTINATION}" -DCGAL_VERSION="${public_release_version}" -DCGAL_VERSION_NR="${release_number}" -DVERBOSE="${VERBOSE}" -P ${SOURCES_DIR}/Scripts/developer_scripts/cgal_create_release_with_cmake.cmake pushd "${DESTINATION}/${public_release_name}" diff --git a/Scripts/developer_scripts/create_new_release_evaluate_versions.cmake b/Scripts/developer_scripts/create_new_release_evaluate_versions.cmake new file mode 100644 index 00000000000..4b5cfddd39c --- /dev/null +++ b/Scripts/developer_scripts/create_new_release_evaluate_versions.cmake @@ -0,0 +1,6 @@ +include(${CGALCONFIGVERSIONFILE}) +message("MAJOR_NUMBER=${CGAL_MAJOR_VERSION} +MINOR_NUMBER=${CGAL_MINOR_VERSION} +BUGFIX_NUMBER=${CGAL_BUGFIX_VERSION} +public_release_version=${CGAL_VERSION_PUBLIC_RELEASE_VERSION} +public_release_name=${CGAL_VERSION_PUBLIC_RELEASE_NAME}") From 15f01710130d5f28845c216a056d5ea8353ac556 Mon Sep 17 00:00:00 2001 From: Laurent Rineau Date: Sat, 2 May 2020 13:59:48 +0200 Subject: [PATCH 348/568] Fix for the case where CGAL is configured --- CMakeLists.txt | 1 + Installation/CMakeLists.txt | 4 ---- 2 files changed, 1 insertion(+), 4 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 415e03ab1c0..d224b7434af 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -9,6 +9,7 @@ export(PACKAGE CGAL) set( CGAL_BRANCH_BUILD ON CACHE INTERNAL "Create CGAL from a Git branch" FORCE) +include(${CMAKE_SOURCE_DIR}/CGALConfigVersion.cmake) include(${CMAKE_SOURCE_DIR}/Installation/cmake/modules/CGAL_SCM.cmake) CGAL_detect_git(${CMAKE_SOURCE_DIR}) diff --git a/Installation/CMakeLists.txt b/Installation/CMakeLists.txt index 13ef48188f8..1b396f94a9a 100644 --- a/Installation/CMakeLists.txt +++ b/Installation/CMakeLists.txt @@ -140,10 +140,6 @@ if ( CGAL_BRANCH_BUILD ) # Create version files # - file(STRINGS "${CGAL_MAINTENANCE_PACKAGE_DIR}/release_building/MAJOR_NUMBER" CGAL_MAJOR_VERSION REGEX "[0-9]*") - file(STRINGS "${CGAL_MAINTENANCE_PACKAGE_DIR}/release_building/MINOR_NUMBER" CGAL_MINOR_VERSION REGEX "[0-9]*") - file(STRINGS "${CGAL_MAINTENANCE_PACKAGE_DIR}/release_building/BUGFIX_NUMBER" CGAL_BUGFIX_VERSION REGEX "[0-9]*") - file(REMOVE ${CMAKE_BINARY_DIR}/VERSION) if (CGAL_BUGFIX_VERSION AND CGAL_BUGFIX_VERSION GREATER 0) set(CGAL_CREATED_VERSION_NUM "${CGAL_MAJOR_VERSION}.${CGAL_MINOR_VERSION}.${CGAL_BUGFIX_VERSION}") From 02c518523d13155b5f521b06c741cd604bd12c2d Mon Sep 17 00:00:00 2001 From: Laurent Rineau Date: Sat, 2 May 2020 16:47:43 +0200 Subject: [PATCH 349/568] Fix Documentation/doc/CMakeLists.txt --- Documentation/doc/CMakeLists.txt | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/Documentation/doc/CMakeLists.txt b/Documentation/doc/CMakeLists.txt index df8c81710c4..ebaf38f2f79 100644 --- a/Documentation/doc/CMakeLists.txt +++ b/Documentation/doc/CMakeLists.txt @@ -243,9 +243,7 @@ endif() if (NOT CGAL_CREATED_VERSION_NUM) if (CGAL_BRANCH_BUILD) - file(STRINGS "${CGAL_ROOT}/Maintenance/release_building/MAJOR_NUMBER" CGAL_MAJOR_VERSION REGEX "[0-9]*") - file(STRINGS "${CGAL_ROOT}/Maintenance/release_building/MINOR_NUMBER" CGAL_MINOR_VERSION REGEX "[0-9]*") - file(STRINGS "${CGAL_ROOT}/Maintenance/release_building/BUGFIX_NUMBER" CGAL_BUGFIX_VERSION REGEX "[0-9]*") + include(${CGAL_ROOT}/CGALConfigVersion.cmake) if (CGAL_BUGFIX_VERSION AND CGAL_BUGFIX_VERSION GREATER 0) set(CGAL_CREATED_VERSION_NUM "${CGAL_MAJOR_VERSION}.${CGAL_MINOR_VERSION}.${CGAL_BUGFIX_VERSION}") From 28a9cb150ae9b11f9bb37d972be990d87b05cbcf Mon Sep 17 00:00:00 2001 From: Jane Tournois Date: Wed, 6 May 2020 15:11:06 +0200 Subject: [PATCH 350/568] replace std::set with std::array for facets vertices this should be a lot more efficient --- Mesh_3/include/CGAL/Mesh_3/tet_soup_to_c3t3.h | 143 +++++++++++------- .../Polyhedron/Plugins/IO/VTK_io_plugin.cpp | 8 +- 2 files changed, 93 insertions(+), 58 deletions(-) diff --git a/Mesh_3/include/CGAL/Mesh_3/tet_soup_to_c3t3.h b/Mesh_3/include/CGAL/Mesh_3/tet_soup_to_c3t3.h index 0d0c1c1cb6b..707553f88ae 100644 --- a/Mesh_3/include/CGAL/Mesh_3/tet_soup_to_c3t3.h +++ b/Mesh_3/include/CGAL/Mesh_3/tet_soup_to_c3t3.h @@ -29,6 +29,17 @@ namespace CGAL { + +template +std::array make_ordered_vertex_array(const Vh vh0, const Vh vh1, const Vh vh2) +{ + std::array ft = { {vh0, vh1, vh2} }; + if (ft[1] < ft[0]) std::swap(ft[0], ft[1]); + if (ft[2] < ft[1]) std::swap(ft[1], ft[2]); + if (ft[1] < ft[0]) std::swap(ft[0], ft[1]); + return ft; +} + template void build_vertices(Tr& tr, const std::vector& points, @@ -49,22 +60,22 @@ void build_vertices(Tr& tr, } template -void add_facet_to_incident_cells_map(const typename Tr::Cell_handle c, int i, - boost::unordered_map, - std::vector > >& incident_cells_map) +bool add_facet_to_incident_cells_map(const typename Tr::Cell_handle c, int i, + boost::unordered_map, + std::vector > >& incident_cells_map, + const bool verbose) { typedef typename Tr::Vertex_handle Vertex_handle; typedef typename Tr::Cell_handle Cell_handle; - typedef std::set Facet; + typedef std::array Facet_vvv; typedef std::pair Incident_cell; - typedef boost::unordered_map > Incident_cells_map; + typedef boost::unordered_map > Incident_cells_map; // the opposite vertex of f in c is i - Facet f; - f.insert(c->vertex((i + 1) % 4)); - f.insert(c->vertex((i + 2) % 4)); - f.insert(c->vertex((i + 3) % 4)); - CGAL_precondition(f.size() == 3); + Facet_vvv f = make_ordered_vertex_array(c->vertex((i + 1) % 4), + c->vertex((i + 2) % 4), + c->vertex((i + 3) % 4)); + CGAL_precondition(f[0] != f[1] && f[1] != f[2]); Incident_cell e = std::make_pair(c, i); std::vector vec; @@ -74,33 +85,25 @@ void add_facet_to_incident_cells_map(const typename Tr::Cell_handle c, int i, if(!is_insert_successful.second) // the entry already exists in the map { // a facet must have exactly two incident cells -// if (is_insert_successful.first->second.size() != 1) -// { -// typename Tr::Geom_traits::Construct_point_3 point -// = typename Tr::Geom_traits().construct_point_3_object(); -// for (auto fi : incident_cells_map.at(f)) -// { -// std::cout << point(fi.first->vertex((fi.second + 1) % 4)->point()) -// << " " << point(fi.first->vertex((fi.second + 2) % 4)->point()) -// << " " << point(fi.first->vertex((fi.second + 3) % 4)->point()) << std::endl; -// } -// std::cout << "finite facet : " << std::endl; -// std::cout << point(c->vertex(1)->point()) -// << " " << point(c->vertex(2)->point()) -// << " " << point(c->vertex(3)->point()) << std::endl; -// } - CGAL_assertion(is_insert_successful.first->second.size() == 1); + if (is_insert_successful.first->second.size() != 1) + { + if(verbose) + std::cout << "Error in add_facet_to_incident_cells_map" << std::endl; + return false; + } is_insert_successful.first->second.push_back(e); } + return true; } template -void build_finite_cells(Tr& tr, - const std::vector >& finite_cells, - const std::vector& vertex_handle_vector, - boost::unordered_map, +bool build_finite_cells(Tr& tr, + const std::vector >& finite_cells, + const std::vector& vertex_handle_vector, + boost::unordered_map, std::vector > >& incident_cells_map, - const std::map, int>& border_facets) + const std::map, int>& border_facets, + const bool verbose) { typedef std::array Tet_with_ref; // 4 ids + 1 reference @@ -145,7 +148,8 @@ void build_finite_cells(Tr& tr, // build the map used for adjacency later for(int j=0; j<4; ++j) { - add_facet_to_incident_cells_map(c, j, incident_cells_map); + if(!add_facet_to_incident_cells_map(c, j, incident_cells_map, verbose)) + return false; if(border_facets.size() != 0) { std::array facet; @@ -184,33 +188,36 @@ void build_finite_cells(Tr& tr, } } } + return true; } template -void add_infinite_facets_to_incident_cells_map(typename Tr::Cell_handle c, +bool add_infinite_facets_to_incident_cells_map(typename Tr::Cell_handle c, int inf_vert_pos, - boost::unordered_map, - std::vector > >& incident_cells_map) + boost::unordered_map, + std::vector > >& incident_cells_map, + const bool verbose) { int l = (inf_vert_pos + 1) % 4; - add_facet_to_incident_cells_map(c, l, incident_cells_map); + bool b1 = add_facet_to_incident_cells_map(c, l, incident_cells_map, verbose); l = (inf_vert_pos + 2) % 4; - add_facet_to_incident_cells_map(c, l, incident_cells_map); + bool b2 = add_facet_to_incident_cells_map(c, l, incident_cells_map, verbose); l = (inf_vert_pos + 3) % 4; - add_facet_to_incident_cells_map(c, l, incident_cells_map); + bool b3 = add_facet_to_incident_cells_map(c, l, incident_cells_map, verbose); + return b1 && b2 && b3; } template -void build_infinite_cells(Tr& tr, - boost::unordered_map, - std::vector > >& incident_cells_map) +bool build_infinite_cells(Tr& tr, + boost::unordered_map, + std::vector > >& incident_cells_map, + const bool verbose) { typedef typename Tr::Vertex_handle Vertex_handle; typedef typename Tr::Cell_handle Cell_handle; - typedef std::set Facet; + typedef std::array Facet_vvv; typedef std::pair Incident_cell; - typedef boost::unordered_map > Incident_cells_map; + typedef boost::unordered_map > Incident_cells_map; std::vector infinite_cells; @@ -251,22 +258,45 @@ void build_infinite_cells(Tr& tr, CGAL_assertion(it->second.size() == 2); } +#ifdef CGAL_TET_SOUP_TO_C3T3_DEBUG + for (auto icit : incident_cells_map) + CGAL_assertion(icit.second.size() == 2); + + std::map facets; + for (const Cell_handle c : infinite_cells) + { + for (int i = 1; i < 4; ++i) + { + std::array vs = make_ordered_vertex_array(c->vertex((i + 1) % 4), + c->vertex((i + 2) % 4), + c->vertex((i + 3) % 4)); + if (facets.find(vs) == facets.end()) + facets.insert(std::make_pair(vs, 1)); + else + facets[vs]++; + } + } + for (auto fp : facets) + CGAL_assertion(fp.second == 2); +#endif + // add the facets to the incident cells map for (const Cell_handle c : infinite_cells) - add_infinite_facets_to_incident_cells_map(c, 0, incident_cells_map); + if(!add_infinite_facets_to_incident_cells_map(c, 0, incident_cells_map, verbose)) + return false; + + return true; } template bool assign_neighbors(Tr& tr, - const boost::unordered_map, - std::vector > >& incident_cells_map) + const boost::unordered_map, + std::vector > >& incident_cells_map) { - typedef typename Tr::Vertex_handle Vertex_handle; typedef typename Tr::Cell_handle Cell_handle; - typedef std::set Facet; typedef std::pair Incident_cell; - typedef boost::unordered_map > Incident_cells_map; + typedef boost::unordered_map, + std::vector > Incident_cells_map; typename Incident_cells_map::const_iterator icit = incident_cells_map.begin(); for(; icit!=incident_cells_map.end(); ++icit) @@ -295,11 +325,11 @@ bool build_triangulation(Tr& tr, { typedef typename Tr::Vertex_handle Vertex_handle; typedef typename Tr::Cell_handle Cell_handle; - typedef std::set Facet; + typedef std::array Facet_vvv; // associate to a face the two (at most) incident tets and the id of the face in the cell typedef std::pair Incident_cell; - typedef boost::unordered_map > Incident_cells_map; + typedef boost::unordered_map > Incident_cells_map; Incident_cells_map incident_cells_map; vertex_handle_vector.resize(points.size() + 1); // id to vertex_handle @@ -322,8 +352,11 @@ bool build_triangulation(Tr& tr, } if (!finite_cells.empty()) { - build_finite_cells(tr, finite_cells, vertex_handle_vector, incident_cells_map, border_facets); - build_infinite_cells(tr, incident_cells_map); + if(!build_finite_cells(tr, finite_cells, vertex_handle_vector, incident_cells_map, + border_facets, verbose)) + return false; + if(!build_infinite_cells(tr, incident_cells_map, verbose)) + return false; tr.tds().set_dimension(3); if (!assign_neighbors(tr, incident_cells_map)) return false; diff --git a/Polyhedron/demo/Polyhedron/Plugins/IO/VTK_io_plugin.cpp b/Polyhedron/demo/Polyhedron/Plugins/IO/VTK_io_plugin.cpp index 85df5328597..e1e9044f0b6 100644 --- a/Polyhedron/demo/Polyhedron/Plugins/IO/VTK_io_plugin.cpp +++ b/Polyhedron/demo/Polyhedron/Plugins/IO/VTK_io_plugin.cpp @@ -503,8 +503,8 @@ public: if (is_c3t3) { - typedef boost::array Facet; // 3 = id - typedef boost::array Tet_with_ref; // first 4 = id, fifth = reference + typedef std::array Facet; // 3 = id + typedef std::array Tet_with_ref; // first 4 = id, fifth = reference Scene_c3t3_item* c3t3_item = new Scene_c3t3_item(); c3t3_item->set_valid(false); //build a triangulation from data: @@ -547,7 +547,9 @@ public: std::swap(finite_cells[i][1], finite_cells[i][3]); } } - CGAL::build_triangulation(c3t3_item->c3t3().triangulation(), points, finite_cells, border_facets); + std::vector new_vertices; + CGAL::build_triangulation(c3t3_item->c3t3().triangulation(), + points, finite_cells, border_facets, new_vertices); for( C3t3::Triangulation::Finite_cells_iterator cit = c3t3_item->c3t3().triangulation().finite_cells_begin(); From 9d194e3814cff1734e33199cf1d5e058d1d09c3b Mon Sep 17 00:00:00 2001 From: Jane Tournois Date: Wed, 6 May 2020 15:18:57 +0200 Subject: [PATCH 351/568] add missing includes --- Mesh_3/include/CGAL/Mesh_3/tet_soup_to_c3t3.h | 3 +++ 1 file changed, 3 insertions(+) diff --git a/Mesh_3/include/CGAL/Mesh_3/tet_soup_to_c3t3.h b/Mesh_3/include/CGAL/Mesh_3/tet_soup_to_c3t3.h index 707553f88ae..e20ed8a4144 100644 --- a/Mesh_3/include/CGAL/Mesh_3/tet_soup_to_c3t3.h +++ b/Mesh_3/include/CGAL/Mesh_3/tet_soup_to_c3t3.h @@ -24,6 +24,9 @@ #include #include +#include +#include +#include #include From cb2a3464276fd3630deb39d5dc8b9328fcd8475a Mon Sep 17 00:00:00 2001 From: Jane Tournois Date: Wed, 6 May 2020 15:23:04 +0200 Subject: [PATCH 352/568] add make_cells_set_manifold the surface of `cells_to_insert` may be non manifold using this function improves the chances to build a valid triangulation + use the boolean return value of build_triangulation() --- .../internal/collapse_short_edges.h | 111 +++++++----------- 1 file changed, 45 insertions(+), 66 deletions(-) diff --git a/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/collapse_short_edges.h b/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/collapse_short_edges.h index 2032af1df97..259aaea55c7 100644 --- a/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/collapse_short_edges.h +++ b/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/collapse_short_edges.h @@ -68,23 +68,30 @@ public: typedef std::array Facet; // 3 = id typedef std::array Tet_with_ref; // first 4 = id, fifth = reference - std::vector finite_cells; - std::vector points; - std::map border_facets; + std::unordered_set cells_to_insert; + c3t3.triangulation().finite_incident_cells(v0_init, + std::inserter(cells_to_insert, cells_to_insert.end())); + c3t3.triangulation().finite_incident_cells(v1_init, + std::inserter(cells_to_insert, cells_to_insert.end())); - std::vector vertices_to_insert; - c3t3.triangulation().finite_incident_vertices(v0_init, - std::back_inserter(vertices_to_insert)); - vertices_to_insert.push_back(v0_init); - c3t3.triangulation().finite_incident_vertices(v1_init, - std::back_inserter(vertices_to_insert)); + make_cells_set_manifold(c3t3, cells_to_insert); + + std::unordered_set vertices_to_insert; + for (Cell_handle ch : cells_to_insert) + { + for(int i = 0; i < 4; ++i) + vertices_to_insert.insert(ch->vertex(i)); + } CGAL_assertion(vertices_to_insert.end() != std::find(vertices_to_insert.begin(), vertices_to_insert.end(), v1_init)); + CGAL_assertion(vertices_to_insert.end() + != std::find(vertices_to_insert.begin(), vertices_to_insert.end(), v0_init)); std::unordered_map v2i;/*vertex of main tr - vertex of collapse tr*/ //To add the vertices only once + std::vector points; int index = 0; for (Vertex_handle vh : vertices_to_insert) { @@ -95,12 +102,7 @@ public: } } - std::unordered_set cells_to_insert; - c3t3.triangulation().finite_incident_cells(v0_init, - std::inserter(cells_to_insert, cells_to_insert.end())); - c3t3.triangulation().finite_incident_cells(v1_init, - std::inserter(cells_to_insert, cells_to_insert.end())); - + std::vector finite_cells; for (Cell_handle ch : cells_to_insert) { Tet_with_ref t = { { v2i.at(ch->vertex(0)), @@ -111,60 +113,35 @@ public: finite_cells.push_back(t); } -// std::cout << "cells_to_insert : " << cells_to_insert.size() << std::endl; -// make_cells_set_manifold(c3t3, cells_to_insert); -// std::cout << "cells_to_insert : " << cells_to_insert.size() << std::endl; -// -// std::cout << "Collapse : " << point(v0_init->point()) << " " << point(v1_init->point()) << std::endl; -// debug::dump_cells_polylines(cells_to_insert, "collapse_cells_to_insert.polylines.txt"); -// debug::dump_cells(cells_to_insert, "collapse_cells_to_insert.mesh"); - // finished std::vector new_vertices; - CGAL_assertion_code(bool built = ) - CGAL::build_triangulation(triangulation, - points, finite_cells, border_facets, - new_vertices, false/*verbose*/); - CGAL_assertion(built); - - if (!triangulation.tds().is_valid()) + std::map border_facets; + if (CGAL::build_triangulation(triangulation, + points, finite_cells, border_facets, + new_vertices, false/*verbose*/)) { - std::cout << point(v0_init->point()) << " " << point(v1_init->point()) << std::endl; - debug::dump_cells_off(triangulation, "collapse_triangulation_finite_cells.off"); - CGAL_assertion(false); + CGAL_assertion(triangulation.tds().is_valid()); + CGAL_assertion(triangulation.infinite_vertex() == new_vertices[0]); + + // update() + vh0 = new_vertices[v2i.at(v0_init) + 1]; + vh1 = new_vertices[v2i.at(v1_init) + 1]; + + Cell_handle ch; + int i0, i1; + not_an_edge = true; + CGAL_assertion(triangulation.tds().is_vertex(vh0)); + CGAL_assertion(triangulation.tds().is_vertex(vh1)); + if (triangulation.is_edge(vh0, vh1, ch, i0, i1)) + { + edge = Edge(ch, i0, i1); + not_an_edge = false; + } } - - // update() - vh0 = new_vertices[v2i.at(v0_init) + 1]; - vh1 = new_vertices[v2i.at(v1_init) + 1]; - - Cell_handle ch; - int i0, i1; - not_an_edge = true; - CGAL_assertion(triangulation.tds().is_vertex(vh0)); - CGAL_assertion(triangulation.tds().is_vertex(vh1)); - if (triangulation.is_edge(vh0, vh1, ch, i0, i1)) - { - edge = Edge(ch, i0, i1); - not_an_edge = false; - } - CGAL_assertion(!not_an_edge); - - //std::unordered_map to_remove; //default is false - //std::unordered_map sharing_neighbor;//default is false - - //typedef typename Tr::Cell_circulator Cell_circulator; - //Cell_circulator circ = triangulation.incident_cells(edge); - //Cell_circulator done = circ; - //do - //{ - // to_remove[circ] = true; - // if (circ->neighbor(circ->index(vh0))->has_neighbor(circ->neighbor(circ->index(vh1)))) - // { - // sharing_neighbor[circ->neighbor(circ->index(vh0))] = true; - // sharing_neighbor[circ->neighbor(circ->index(vh1))] = true; - // } - //} while (++circ != done); +#ifdef CGAL_TETRAHEDRAL_REMESHING_VERBOSE + else + std::cout << "Warning : CollapseTriangulation is not valid!" << std::endl; +#endif } void make_cells_set_manifold(const C3t3& c3t3, @@ -223,7 +200,9 @@ public: { if (not_an_edge) { - std::cout << "LocalTriangulation::Not an edge..." << std::endl; +#ifdef CGAL_TETRAHEDRAL_REMESHING_VERBOSE + std::cout << "CollapseTriangulation::Not an edge..." << std::endl; +#endif return E_PROBLEM; } else From 1482f325141c0c6b5ef292049739926f055cd41a Mon Sep 17 00:00:00 2001 From: Jane Tournois Date: Wed, 6 May 2020 15:23:34 +0200 Subject: [PATCH 353/568] add missing helper functions --- .../internal/tetrahedral_remeshing_helpers.h | 53 +++++++++++++++++++ 1 file changed, 53 insertions(+) diff --git a/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/tetrahedral_remeshing_helpers.h b/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/tetrahedral_remeshing_helpers.h index 89e313666c4..2a5c7b83822 100644 --- a/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/tetrahedral_remeshing_helpers.h +++ b/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/tetrahedral_remeshing_helpers.h @@ -1016,6 +1016,59 @@ void dump_surface_off(const Tr& tr, const char* filename) ofs.close(); } +template +void dump_cells_off(const CellRange& cells, const Tr& tr, const char* filename) +{ + typedef typename Tr::Vertex_handle Vertex_handle; + typedef typename Tr::Cell_handle Cell_handle; + typedef boost::bimap Bimap_t; + typedef typename Bimap_t::left_map::value_type value_type; + + Bimap_t vertices; + int index = 0; + boost::unordered_set > facets; + + for (Cell_handle c : cells) + { + //collect vertices + for (int i = 0; i < 4; ++i) + { + Vertex_handle vi = c->vertex(i); + if (vertices.left.find(c->vertex(i)) == vertices.left.end()) + vertices.left.insert(value_type(vi, index++)); + } + //collect facets + for (int i = 0; i < 4; ++i) + { + //if (tr.is_infinite(c->neighbor(i))) + { + std::array fi = make_vertex_array(c->vertex((i + 1) % 4), + c->vertex((i + 2) % 4), + c->vertex((i + 3) % 4)); + facets.insert(fi); + } + } + } + + //write header + std::ofstream ofs(filename); + ofs.precision(17); + ofs << "OFF" << std::endl; + ofs << vertices.size() << " " << facets.size() << " 0" << std::endl << std::endl; + + for(const typename Bimap_t::right_map::value_type& v : vertices.right) + ofs << v.second->point().x() << " " + << v.second->point().y() << " " + << v.second->point().z() << std::endl; + + for(const std::array& f : facets) + ofs << "3 " << vertices.left.at(f[0]) << " " + << vertices.left.at(f[1]) << " " + << vertices.left.at(f[2]) << std::endl; + + ofs.close(); +} + template void dump_cells_off(const Tr& tr, const char* filename) { From 9f40dac8d96e650ead3895cdbc6f4b44f3223960 Mon Sep 17 00:00:00 2001 From: Jane Tournois Date: Wed, 6 May 2020 16:26:48 +0200 Subject: [PATCH 354/568] fix warnings (conversion, initialization order, brackets...) and minor cleaning --- .../Tetrahedral_remeshing/internal/FMLS.h | 76 ++++++++++--------- .../internal/collapse_short_edges.h | 6 +- .../internal/flip_edges.h | 1 - .../internal/smooth_vertices.h | 32 ++++---- 4 files changed, 56 insertions(+), 59 deletions(-) diff --git a/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/FMLS.h b/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/FMLS.h index fa99e1adf3a..d74f98cfd17 100644 --- a/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/FMLS.h +++ b/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/FMLS.h @@ -155,7 +155,7 @@ public: void setPN(const std::vector& newPN, const unsigned int newPNSize, - const float pointSpacing) + const float& pointSpacing) { freeCPUMemory(); PN = newPN; @@ -222,30 +222,30 @@ public: } } - // Compute the MLS projection of the list of point stored in pv and store the resulting - // positions and normal in qv. qv must be preallocated to stroe 6*pvSize float32. - // The strid indicates the offsets in qv (the defautl value of 3 means that the qv - // is compact: pv={x0,y0,z0,x1,y1,z1...}. If pv contains also normals for instance, - // the stride should be set to 6. - void fastProjectionCPU(const std::vector& pv, - const std::size_t pvSize, - std::vector& qv, - std::size_t stride = 3) const - { - for (std::size_t i = 0; i < pvSize; i++) - { - Vector_3 p(pv[stride * i], pv[stride * i + 1], pv[stride * i + 2]); - Vector_3 q, n; - for (unsigned int j = 0; j < numIter; j++) - { - q = CGAL::NULL_VECTOR; - n = CGAL::NULL_VECTOR; - fastProjectionCPU(p, q, n); - p = q; - } - setPNSample(qv, i, q[0], q[1], q[2], n[0], n[1], n[2]); - } - } +// // Compute the MLS projection of the list of point stored in pv and store the resulting +// // positions and normal in qv. qv must be preallocated to stroe 6*pvSize float32. +// // The strid indicates the offsets in qv (the defautl value of 3 means that the qv +// // is compact: pv={x0,y0,z0,x1,y1,z1...}. If pv contains also normals for instance, +// // the stride should be set to 6. +// void fastProjectionCPU(const std::vector& pv, +// const std::size_t pvSize, +// std::vector& qv, +// std::size_t stride = 3) const +// { +// for (std::size_t i = 0; i < pvSize; i++) +// { +// Vector_3 p(pv[stride * i], pv[stride * i + 1], pv[stride * i + 2]); +// Vector_3 q, n; +// for (unsigned int j = 0; j < numIter; j++) +// { +// q = CGAL::NULL_VECTOR; +// n = CGAL::NULL_VECTOR; +// fastProjectionCPU(p, q, n); +// p = q; +// } +// setPNSample(qv, i, q[0], q[1], q[2], n[0], n[1], n[2]); +// } +// } // Brute force version. O(PNSize) complexity. For comparison only. void projectionCPU(const Vector_3& x, Vector_3& q, Vector_3& n) @@ -351,7 +351,11 @@ private: { public: Grid() - : cellSize(1.f) + : minMax() + , cellSize(1.f) + , res() + , LUT() + , indices() {} ~Grid() { @@ -594,7 +598,7 @@ void createMLSSurfaces(Subdomain__FMLS& subdomain_FMLS, } std::vector current_v_count(count, 0); - std::vector point_spacing(count, 0.f); + std::vector point_spacing(count, 0.); std::vector point_spacing_count(count, 0); //Allocation of the PN @@ -654,9 +658,8 @@ void createMLSSurfaces(Subdomain__FMLS& subdomain_FMLS, const Surface_index surf_i = c3t3.surface_patch_index(*fit); const int fmls_id = current_subdomain_FMLS_indices[surf_i]; - point_spacing[fmls_id] += static_cast( - CGAL::approximate_sqrt( - CGAL::squared_distance(point(vh0->point()), point(vh1->point())))); + point_spacing[fmls_id] += CGAL::approximate_sqrt( + CGAL::squared_distance(point(vh0->point()), point(vh1->point()))); point_spacing_count[fmls_id] ++; } } @@ -702,8 +705,7 @@ void createMLSSurfaces(Subdomain__FMLS& subdomain_FMLS, { Vector_3 space_1 = barycenter - points[i]; - point_spacing[fmls_id] += - static_cast(CGAL::approximate_sqrt(space_1 * space_1)); + point_spacing[fmls_id] += CGAL::approximate_sqrt(space_1 * space_1); point_spacing_count[fmls_id] ++; } } @@ -726,9 +728,9 @@ void createMLSSurfaces(Subdomain__FMLS& subdomain_FMLS, Vector_3 space_2 = p - points[i1]; Vector_3 space_3 = p - points[i2]; - point_spacing[fmls_id] += CGAL::sqrt(space_1 * space_1); - point_spacing[fmls_id] += CGAL::sqrt(space_2 * space_2); - point_spacing[fmls_id] += CGAL::sqrt(space_3 * space_3); + point_spacing[fmls_id] += CGAL::approximate_sqrt(space_1 * space_1); + point_spacing[fmls_id] += CGAL::approximate_sqrt(space_2 * space_2); + point_spacing[fmls_id] += CGAL::approximate_sqrt(space_3 * space_3); point_spacing_count[fmls_id] += 3; } @@ -764,7 +766,7 @@ void createMLSSurfaces(Subdomain__FMLS& subdomain_FMLS, { nb_of_mls_to_create++; - float current_point_spacing = point_spacing[it->second] / point_spacing_count[it->second]; + double current_point_spacing = point_spacing[it->second] / point_spacing_count[it->second]; point_spacing[it->second] = current_point_spacing; average_point_spacing += current_point_spacing; @@ -782,7 +784,7 @@ void createMLSSurfaces(Subdomain__FMLS& subdomain_FMLS, { if (current_v_count[it->second] > 3) { - float current_point_spacing = point_spacing[it->second]; + float current_point_spacing = static_cast(point_spacing[it->second]); //subdomain_FMLS[count].toggleHermite(true); subdomain_FMLS[count].setPN(pns[it->second], diff --git a/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/collapse_short_edges.h b/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/collapse_short_edges.h index 259aaea55c7..7ccb528e8b2 100644 --- a/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/collapse_short_edges.h +++ b/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/collapse_short_edges.h @@ -61,9 +61,9 @@ public: CollapseTriangulation(C3t3& c3t3, const Edge& e, Collapse_type _collapse_type) - : v0_init(e.first->vertex(e.second)) + : collapse_type(_collapse_type) + , v0_init(e.first->vertex(e.second)) , v1_init(e.first->vertex(e.third)) - , collapse_type(_collapse_type) { typedef std::array Facet; // 3 = id typedef std::array Tet_with_ref; // first 4 = id, fifth = reference @@ -768,7 +768,7 @@ collapse(const typename C3t3::Cell_handle ch, // update complex edges const std::array, 6> edges - = { { 0,1, 0,2, 0,3, 1,2, 1,3, 2,3 } }; //vertex indices in cells + = { { {{0,1}}, {{0,2}}, {{0,3}}, {{1,2}}, {{1,3}}, {{2,3}} } }; //vertex indices in cells const Vertex_handle vkept = vh0; const Vertex_handle vdeleted = vh1; for (const Cell_handle c : cells_to_update) diff --git a/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/flip_edges.h b/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/flip_edges.h index f82e1aa749e..7a31fd3ed20 100644 --- a/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/flip_edges.h +++ b/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/flip_edges.h @@ -1095,7 +1095,6 @@ std::size_t flip_all_edges(const std::vector& edges, Visitor& visitor) { typedef typename C3t3::Triangulation Tr; -// typedef typename Tr::Vertex_handle Vertex_handle; typedef typename Tr::Cell_handle Cell_handle; typedef typename Tr::Edge Edge; diff --git a/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/smooth_vertices.h b/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/smooth_vertices.h index 8aabb863cc7..202afbd29aa 100644 --- a/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/smooth_vertices.h +++ b/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/smooth_vertices.h @@ -118,20 +118,17 @@ private: return {}; } - template + template Vector_3 compute_normal(const Facet& f, const Vector_3& reference_normal, - const C3t3& c3t3, - const CellSelector& cell_selector) + const Gt& gt) { - CGAL_assertion(is_boundary(c3t3, f, cell_selector)); + typename Gt::Construct_opposite_vector_3 + opp = gt.construct_opposite_vector_3_object(); + typename Gt::Compute_scalar_product_3 + scalar_product = gt.compute_scalar_product_3_object(); - typename Tr::Geom_traits::Construct_opposite_vector_3 - opp = c3t3.triangulation().geom_traits().construct_opposite_vector_3_object(); - typename Tr::Geom_traits::Compute_scalar_product_3 - scalar_product = c3t3.triangulation().geom_traits().compute_scalar_product_3_object(); - - Vector_3 n = CGAL::Tetrahedral_remeshing::normal(f, c3t3.triangulation().geom_traits()); + Vector_3 n = CGAL::Tetrahedral_remeshing::normal(f, gt); if (scalar_product(n, reference_normal) < 0.) n = opp(n); @@ -143,10 +140,9 @@ private: VertexNormalsMap& normals_map, const CellSelector& cell_selector) { + typename Tr::Geom_traits gt = c3t3.triangulation().geom_traits(); typename Tr::Geom_traits::Construct_opposite_vector_3 - opp = c3t3.triangulation().geom_traits().construct_opposite_vector_3_object(); -// typename Tr::Geom_traits::Construct_scaled_vector_3 -// scale = c3t3.triangulation().geom_traits().construct_scaled_vector_3_object(); + opp = gt.construct_opposite_vector_3_object(); const Tr& tr = c3t3.triangulation(); @@ -185,10 +181,10 @@ private: const typename C3t3::Cell_handle ch = f.first; const std::array, 3> edges - = { (ff.second + 1) % 4, (ff.second + 2) % 4, //edge 1-2 - (ff.second + 2) % 4, (ff.second + 3) % 4, //edge 2-3 - (ff.second + 3) % 4, (ff.second + 1) % 4 //edge 3-1 - }; //vertex indices in cells + = {{ {{(ff.second + 1) % 4, (ff.second + 2) % 4}}, //edge 1-2 + {{(ff.second + 2) % 4, (ff.second + 3) % 4}}, //edge 2-3 + {{(ff.second + 3) % 4, (ff.second + 1) % 4}} //edge 3-1 + }}; //vertex indices in cells const Vector_3& ref = fnormals[f]; for (const std::array& ei : edges) @@ -200,7 +196,7 @@ private: const Facet neigh = *neighbor; //already a canonical_facet if (fnormals[neigh] == CGAL::NULL_VECTOR) //check it's not already computed { - fnormals[neigh] = compute_normal(neigh, ref, c3t3, cell_selector); + fnormals[neigh] = compute_normal(neigh, ref, gt); facets.push_back(neigh); } } From f9c886f5cbf1831f54d5251737b924ab6793a290 Mon Sep 17 00:00:00 2001 From: Rui Ventura Date: Wed, 6 May 2020 16:00:15 +0100 Subject: [PATCH 355/568] Implement `operator<<` for `Aff_transformationH2` --- .../include/CGAL/Homogeneous/Aff_transformationH2.h | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/Homogeneous_kernel/include/CGAL/Homogeneous/Aff_transformationH2.h b/Homogeneous_kernel/include/CGAL/Homogeneous/Aff_transformationH2.h index 57b094d3dd5..561c1f4b98d 100644 --- a/Homogeneous_kernel/include/CGAL/Homogeneous/Aff_transformationH2.h +++ b/Homogeneous_kernel/include/CGAL/Homogeneous/Aff_transformationH2.h @@ -782,6 +782,17 @@ operator*(const Aff_transformationH2& right_argument) const right_argument.Ptr()->general_form() ); } +template +std::ostream& +operator<<(std::ostream& out, const Aff_transformationH2& t) +{ + typename R::RT RT0(0); + Aff_transformation_repH2 r = t.Ptr()->general_form(); + return out << "| "<< r.a << ' ' << r.b << ' ' << r.c << " |\n" + << "| "<< r.d << ' ' << r.e << ' ' << r.f << " |\n" + << "| "<< RT0 << ' ' << RT0 << ' ' << r.g << " |\n"; +} + template Aff_transformationH2 _general_transformation_composition( Aff_transformation_repH2 l, From a9b461c1567f1a9ffa96b7b861de99efd5c1aa9e Mon Sep 17 00:00:00 2001 From: Jane Tournois Date: Thu, 7 May 2020 06:31:14 +0200 Subject: [PATCH 356/568] fix warnings --- .../Tetrahedral_remeshing/Tetrahedral_remeshing_plugin.cpp | 4 ++-- .../Tetrahedral_remeshing/internal/collapse_short_edges.h | 3 +-- 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/Polyhedron/demo/Polyhedron/Plugins/Tetrahedral_remeshing/Tetrahedral_remeshing_plugin.cpp b/Polyhedron/demo/Polyhedron/Plugins/Tetrahedral_remeshing/Tetrahedral_remeshing_plugin.cpp index 355308f9da8..bbf5dc24de6 100644 --- a/Polyhedron/demo/Polyhedron/Plugins/Tetrahedral_remeshing/Tetrahedral_remeshing_plugin.cpp +++ b/Polyhedron/demo/Polyhedron/Plugins/Tetrahedral_remeshing/Tetrahedral_remeshing_plugin.cpp @@ -17,7 +17,7 @@ #include #include -#include +#include #include #include #include @@ -103,7 +103,7 @@ public Q_SLOTS: // wait cursor QApplication::setOverrideCursor(Qt::WaitCursor); - QTime time; + QElapsedTimer time; time.start(); CGAL::tetrahedral_isotropic_remeshing( diff --git a/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/collapse_short_edges.h b/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/collapse_short_edges.h index 7ccb528e8b2..8d2cd651a62 100644 --- a/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/collapse_short_edges.h +++ b/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/collapse_short_edges.h @@ -231,7 +231,6 @@ public: std::vector cells_to_update; triangulation.incident_cells(vh1, std::back_inserter(cells_to_update)); - Result_type r = VALID; do { int v0_id = circ->index(vh0); @@ -244,7 +243,7 @@ public: int ch_id_in_n1 = n1_ch->index(circ); if (n0_ch->has_neighbor(n1_ch)) - r = SHARED_NEIGHBOR_PROBLEM; + return SHARED_NEIGHBOR_PROBLEM; //Update neighbors before removing cell n0_ch->set_neighbor(ch_id_in_n0, n1_ch); From 83e007f59e654446e2afecc6c66a83f98288c4b4 Mon Sep 17 00:00:00 2001 From: Jane Tournois Date: Thu, 7 May 2020 08:54:44 +0200 Subject: [PATCH 357/568] fix conversion warnings and comment unused code --- .../Tetrahedral_remeshing/internal/FMLS.h | 293 +++++++++--------- .../internal/smooth_vertices.h | 2 +- .../internal/tetrahedral_remeshing_helpers.h | 2 +- .../test_tetrahedral_remeshing.cpp | 2 +- 4 files changed, 150 insertions(+), 149 deletions(-) diff --git a/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/FMLS.h b/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/FMLS.h index d74f98cfd17..0573a0f0d68 100644 --- a/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/FMLS.h +++ b/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/FMLS.h @@ -44,7 +44,7 @@ namespace internal // MLS Projection // -------------------------------------------------------------- -inline float wendland(float x, float h) +inline double wendland(double x, double h) { x = CGAL::abs(x); if (x < h) @@ -53,18 +53,18 @@ inline float wendland(float x, float h) return 0.0; } -inline void setPNSample(std::vector& p, - const std::size_t& i, - const float x, const float y, const float z, - const float nx, const float ny, const float nz) -{ - p[6 * i] = x; - p[6 * i + 1] = y; - p[6 * i + 2] = z; - p[6 * i + 3] = nx; - p[6 * i + 4] = ny; - p[6 * i + 5] = nz; -} +//inline void setPNSample(std::vector& p, +// const std::size_t& i, +// const float x, const float y, const float z, +// const float nx, const float ny, const float nz) +//{ +// p[6 * i] = x; +// p[6 * i + 1] = y; +// p[6 * i + 2] = z; +// p[6 * i + 3] = nx; +// p[6 * i + 4] = ny; +// p[6 * i + 5] = nz; +//} template inline CGAL::Vector_3 projectOn(const CGAL::Vector_3& x, @@ -98,11 +98,11 @@ template inline void weightedPointCombination(const CGAL::Vector_3& x, const CGAL::Vector_3& pi, const CGAL::Vector_3& ni, - float sigma_s, bool bilateral, float sigma_r, + double sigma_s, bool bilateral, double sigma_r, bool hermite, - CGAL::Vector_3& c, CGAL::Vector_3& nc, float& sumW) + CGAL::Vector_3& c, CGAL::Vector_3& nc, double& sumW) { - float w = wendland(distance(x, pi), sigma_s); + double w = wendland(distance(x, pi), sigma_s); if (bilateral) w *= wendland(length(x - projectOn(x, ni, pi)), sigma_r); if (hermite) @@ -148,14 +148,14 @@ public: // Main Interface // -------------------------------------------------------------- - std::vector createPN(unsigned int size) - { - return std::vector(size * SURFEL_SIZE); - } +// std::vector createPN(std::size_t size) +// { +// return std::vector(size * SURFEL_SIZE); +// } void setPN(const std::vector& newPN, - const unsigned int newPNSize, - const float& pointSpacing) + const std::size_t newPNSize, + const double& pointSpacing) { freeCPUMemory(); PN = newPN; @@ -170,21 +170,22 @@ public: // of p and store the resulting position in q and normal in n. void fastProjectionCPU(const Vector_3& p, Vector_3& q, Vector_3& n) const { - float sigma_s = PNScale * MLSRadius; - float sigma_r = bilateralRange; + double sigma_s = PNScale * MLSRadius; + double sigma_r = bilateralRange; Vector_3 g = (p - Vector_3(grid.getMinMax()[0], grid.getMinMax()[1], grid.getMinMax()[2])) / sigma_s; std::array gxyz = { g.x(), g.y(), g.z() }; - for (unsigned int j = 0; j < 3; j++) { + for (std::size_t j = 0; j < 3; j++) { gxyz[j] = floor(gxyz[j]); if (gxyz[j] < 0.f) gxyz[j] = 0.f; if (gxyz[j] >= grid.getRes()[j]) gxyz[j] = grid.getRes()[j] - 1; } - unsigned int minIt[3], maxIt[3]; - for (unsigned int j = 0; j < 3; j++) { + std::array minIt; + std::array maxIt; + for (std::size_t j = 0; j < 3; j++) { if (((unsigned int)gxyz[j]) == 0) minIt[j] = 0; else @@ -195,17 +196,17 @@ public: maxIt[j] = ((unsigned int)gxyz[j]) + 1; } Vector_3 c = CGAL::NULL_VECTOR; - float sumW = 0.f; - unsigned int it[3]; + double sumW = 0.f; + std::array it; for (it[0] = minIt[0]; it[0] <= maxIt[0]; it[0]++) for (it[1] = minIt[1]; it[1] <= maxIt[1]; it[1]++) for (it[2] = minIt[2]; it[2] <= maxIt[2]; it[2]++) { - unsigned int gridIndex = grid.getLUTElement(it[0], it[1], it[2]); + std::size_t gridIndex = grid.getLUTElement(it[0], it[1], it[2]); if (gridIndex == 2 * PNSize) continue; - unsigned int neigh = grid.getCellIndicesSize(it[0], it[1], it[2]); - for (unsigned int j = 0; j < neigh; j++) { - unsigned int k = grid.getIndicesElement(it[0], it[1], it[2], j); + std::size_t neigh = grid.getCellIndicesSize(it[0], it[1], it[2]); + for (std::size_t j = 0; j < neigh; j++) { + std::size_t k = grid.getIndicesElement(it[0], it[1], it[2], j); Vector_3 pk(PN[6 * k], PN[6 * k + 1], PN[6 * k + 2]); Vector_3 nk(PN[6 * k + 3], PN[6 * k + 4], PN[6 * k + 5]); weightedPointCombination(p, pk, nk, sigma_s, bilateral, sigma_r, hermite, c, n, sumW); @@ -247,69 +248,69 @@ public: // } // } - // Brute force version. O(PNSize) complexity. For comparison only. - void projectionCPU(const Vector_3& x, Vector_3& q, Vector_3& n) - { - float sigma_s = MLSRadius * PNScale; - float sigma_r = bilateralRange; - Vector_3 p(x); - for (unsigned int k = 0; k < numIter; k++) { - Vector_3 c = CGAL::NULL_VECTOR; - n = CGAL::NULL_VECTOR; - float sumW = 0.f; - for (unsigned int j = 0; j < PNSize; j++) { - Vector_3 pj(PN[6 * j], PN[6 * j + 1], PN[6 * j + 2]); - Vector_3 nj(PN[6 * j + 3], PN[6 * j + 4], PN[6 * j + 5]); - weightedPointCombination(p, pj, nj, sigma_s, bilateral, sigma_r, hermite, c, n, sumW); - } - c /= sumW; - n.normalize(); - q = projectOn(p, n, c); - p = q; - } - - } - // Brute force version. O(pvSize*PNSize) complexity. For comparison only. - void projectionCPU(const std::vector& pv, - unsigned int pvSize, - std::vector& qv, - unsigned int stride = 3) - { - for (int i = 0; i < int(pvSize); i++) { - Vector_3 p(pv[stride * i], pv[stride * i + 1], pv[stride * i + 2]); - Vector_3 q, n; - for (unsigned int j = 0; j < numIter; j++) { - q = CGAL::NULL_VECTOR; - n = CGAL::NULL_VECTOR; - projectionCPU(p, q, n); - p = q; - } - setPNSample(qv, i, q[0], q[1], q[2], n[0], n[1], n[2]); - } - } +// // Brute force version. O(PNSize) complexity. For comparison only. +// void projectionCPU(const Vector_3& x, Vector_3& q, Vector_3& n) +// { +// float sigma_s = MLSRadius * PNScale; +// float sigma_r = bilateralRange; +// Vector_3 p(x); +// for (unsigned int k = 0; k < numIter; k++) { +// Vector_3 c = CGAL::NULL_VECTOR; +// n = CGAL::NULL_VECTOR; +// float sumW = 0.f; +// for (unsigned int j = 0; j < PNSize; j++) { +// Vector_3 pj(PN[6 * j], PN[6 * j + 1], PN[6 * j + 2]); +// Vector_3 nj(PN[6 * j + 3], PN[6 * j + 4], PN[6 * j + 5]); +// weightedPointCombination(p, pj, nj, sigma_s, bilateral, sigma_r, hermite, c, n, sumW); +// } +// c /= sumW; +// n.normalize(); +// q = projectOn(p, n, c); +// p = q; +// } +// } +// +// // Brute force version. O(pvSize*PNSize) complexity. For comparison only. +// void projectionCPU(const std::vector& pv, +// unsigned int pvSize, +// std::vector& qv, +// unsigned int stride = 3) +// { +// for (int i = 0; i < int(pvSize); i++) { +// Vector_3 p(pv[stride * i], pv[stride * i + 1], pv[stride * i + 2]); +// Vector_3 q, n; +// for (unsigned int j = 0; j < numIter; j++) { +// q = CGAL::NULL_VECTOR; +// n = CGAL::NULL_VECTOR; +// projectionCPU(p, q, n); +// p = q; +// } +// setPNSample(qv, i, q[0], q[1], q[2], n[0], n[1], n[2]); +// } +// } // -------------------------------------------------------------- // Accessors // -------------------------------------------------------------- // Number of elements of the PN. One elemnt is a 6-float32 chunk. - inline unsigned int getPNSize() const { return PNSize; } + inline std::size_t getPNSize() const { return PNSize; } inline std::vector& getPN() { return PN; } inline const std::vector& getPN() const { return PN; } // Min/Max corners of PN's bounding volume - inline const float* getMinMax() const { return grid.getMinMax(); } + inline const double* getMinMax() const { return grid.getMinMax(); } // Radius of the bounding sphere of the PN - inline float getPNScale() const { return PNScale; } + inline double getPNScale() const { return PNScale; } // Normalized MLS support size - inline float getMLSRadius() const { return MLSRadius; } - inline void setMLSRadius(float s) { MLSRadius = s; grid.clear(); grid.init(PN, PNSize, MLSRadius * PNScale); } + inline double getMLSRadius() const { return MLSRadius; } + inline void setMLSRadius(double s) { MLSRadius = s; grid.clear(); grid.init(PN, PNSize, MLSRadius * PNScale); } // Bilateral weighting for feature preservation (inspired by [Jones 2003]). inline bool isBilateral() const { return bilateral; } inline void toggleBilateral(bool b) { bilateral = b; } // Bilateral support size for the range weight - inline float getBilateralRange() const { return bilateralRange; } - inline void setBilateralRange(float r) { bilateralRange = r; } + inline double getBilateralRange() const { return bilateralRange; } + inline void setBilateralRange(double r) { bilateralRange = r; } // Hermite interpolation [Alexa 2009] inline bool isHermite() const { return hermite; } inline void toggleHermite(bool b) { hermite = b; } @@ -334,7 +335,7 @@ private: c /= PNSize; PNScale = 0.f; for (std::size_t i = 0; i < PNSize; i++) { - float r = distance(c, Vector_3(PN[6 * i], PN[6 * i + 1], PN[6 * i + 2])); + double r = distance(c, Vector_3(PN[6 * i], PN[6 * i + 1], PN[6 * i + 2])); if (r > PNScale) PNScale = r; } @@ -362,48 +363,48 @@ private: clear(); } - void init(const std::vector& PN, unsigned int PNSize, float sigma_s) + void init(const std::vector& PN, std::size_t PNSize, double sigma_s) { cellSize = sigma_s; - for (unsigned int i = 0; i < 3; i++) { + for (std::size_t i = 0; i < 3; i++) { minMax[i] = PN[i]; minMax[3 + i] = PN[i]; } - for (unsigned int i = 0; i < PNSize; i++) - for (unsigned int j = 0; j < 3; j++) { + for (std::size_t i = 0; i < PNSize; i++) + for (std::size_t j = 0; j < 3; j++) { if (PN[6 * i + j] < minMax[j]) minMax[j] = PN[6 * i + j]; if (PN[6 * i + j] > minMax[3 + j]) minMax[3 + j] = PN[6 * i + j]; } - for (unsigned int i = 0; i < 3; i++) { + for (std::size_t i = 0; i < 3; i++) { minMax[i] -= 0.001f; minMax[3 + i] += 0.001f; } - for (unsigned int i = 0; i < 3; i++) - res[i] = (unsigned int)ceil((minMax[3 + i] - minMax[i]) / cellSize); - unsigned int LUTSize = res[0] * res[1] * res[2]; + for (std::size_t i = 0; i < 3; i++) + res[i] = (std::size_t)ceil((minMax[3 + i] - minMax[i]) / cellSize); + std::size_t LUTSize = res[0] * res[1] * res[2]; LUT.resize(LUTSize); LUT.assign(LUTSize, 0); - unsigned int nonEmptyCells = 0; + std::size_t nonEmptyCells = 0; Vector_3 gMin(minMax[0], minMax[1], minMax[2]); Vector_3 gMax(minMax[3], minMax[4], minMax[5]); - for (unsigned int i = 0; i < PNSize; i++) { - unsigned int index = getLUTIndex(Vector_3(PN[6 * i], PN[6 * i + 1], PN[6 * i + 2])); + for (std::size_t i = 0; i < PNSize; i++) { + std::size_t index = getLUTIndex(Vector_3(PN[6 * i], PN[6 * i + 1], PN[6 * i + 2])); if (LUT[index] == 0) nonEmptyCells++; LUT[index]++; } - unsigned int indicesSize = PNSize + nonEmptyCells; + std::size_t indicesSize = PNSize + nonEmptyCells; indices.reserve(indicesSize); indices.assign(indicesSize, 0); - unsigned int cpt = 0; - for (unsigned int i = 0; i < res[0]; i++) - for (unsigned int j = 0; j < res[1]; j++) - for (unsigned int k = 0; k < res[2]; k++) { - unsigned int index = getLUTIndex(i, j, k); + std::size_t cpt = 0; + for (std::size_t i = 0; i < res[0]; i++) + for (std::size_t j = 0; j < res[1]; j++) + for (std::size_t k = 0; k < res[2]; k++) { + std::size_t index = getLUTIndex(i, j, k); if (LUT[index] != 0) { indices[cpt] = LUT[index]; LUT[index] = cpt; @@ -413,15 +414,15 @@ private: else LUT[index] = 2 * PNSize; } - for (unsigned int i = 0; i < PNSize; i++) { + for (std::size_t i = 0; i < PNSize; i++) { Vector_3 p = Vector_3(PN[6 * i], PN[6 * i + 1], PN[6 * i + 2]); - unsigned int indicesIndex = getLUTElement(p); - unsigned int totalCount = indices[indicesIndex]; - unsigned int countIndex = indicesIndex + totalCount; - unsigned int currentCount = indices[countIndex]; + std::size_t indicesIndex = getLUTElement(p); + std::size_t totalCount = indices[indicesIndex]; + std::size_t countIndex = indicesIndex + totalCount; + std::size_t currentCount = indices[countIndex]; if (currentCount < indices[indicesIndex]) indices[countIndex]++; - unsigned int pIndex = indicesIndex + 1 + currentCount; + std::size_t pIndex = indicesIndex + 1 + currentCount; indices[pIndex] = i; } } @@ -434,61 +435,61 @@ private: // Accessors inline const std::array getMinMax() const { return minMax; } - inline const std::array getRes() const { return res; } - inline float getCellSize() const { return cellSize; } - inline std::vector& getLUT() { return LUT; } - inline const std::vector& getLUT() const { return LUT; } - inline unsigned int getLUTIndex(unsigned int i, - unsigned int j, - unsigned int k) const + inline const std::array getRes() const { return res; } + inline double getCellSize() const { return cellSize; } + inline std::vector& getLUT() { return LUT; } + inline const std::vector& getLUT() const { return LUT; } + inline std::size_t getLUTIndex(const std::size_t i, + const std::size_t j, + const std::size_t k) const { return k * res[0] * res[1] + j * res[0] + i; } - inline unsigned int getLUTElement(unsigned int i, - unsigned int j, - unsigned int k) const + inline std::size_t getLUTElement(const std::size_t i, + const std::size_t j, + const std::size_t k) const { return LUT[getLUTIndex(i, j, k)]; } - unsigned int getLUTIndex(const Vector_3& x) const + std::size_t getLUTIndex(const Vector_3& x) const { Vector_3 vp = (x - Vector_3(minMax[0], minMax[1], minMax[2])) / cellSize; std::array p = { vp.x(), vp.y(), vp.z() }; - for (unsigned int j = 0; j < 3; j++) { + for (std::size_t j = 0; j < 3; j++) { p[j] = floor(p[j]); if (p[j] < 0) p[j] = 0.f; if (p[j] >= res[j]) p[j] = res[j] - 1; } - unsigned index = ((unsigned int)floor(p[2])) * res[0] * res[1] - + ((unsigned int)floor(p[1])) * res[0] - + ((unsigned int)floor(p[0])); + std::size_t index = ((std::size_t)floor(p[2])) * res[0] * res[1] + + ((std::size_t)floor(p[1])) * res[0] + + ((std::size_t)floor(p[0])); return index; } - inline unsigned int getLUTElement(const Vector_3& x) const { + inline std::size_t getLUTElement(const Vector_3& x) const { return LUT[getLUTIndex(x)]; } - inline std::vector& getIndices() { return indices; } - inline const std::vector& getIndices() const { return indices; } - inline unsigned int getCellIndicesSize(unsigned int i, - unsigned int j, - unsigned int k) const { + inline std::vector& getIndices() { return indices; } + inline const std::vector& getIndices() const { return indices; } + inline std::size_t getCellIndicesSize(std::size_t i, + std::size_t j, + std::size_t k) const { return indices[getLUTElement(i, j, k)]; } - inline unsigned int getIndicesElement(unsigned int i, - unsigned int j, - unsigned int k, - unsigned int e) const { + inline std::size_t getIndicesElement(std::size_t i, + std::size_t j, + std::size_t k, + std::size_t e) const { return indices[getLUTElement(i, j, k) + 1 + e]; } private: std::array minMax; - float cellSize; - std::array res; - std::vector LUT; // 3D Index Look-Up Table - std::vector indices; // 3D Grid data + double cellSize; + std::array res; + std::vector LUT; // 3D Index Look-Up Table + std::vector indices; // 3D Grid data }; @@ -507,10 +508,10 @@ private: // -------------------------------------------------------------- std::vector PN; - unsigned int PNSize; - float PNScale; // size of the bounding sphere radius - float MLSRadius; - float bilateralRange; + std::size_t PNSize; + double PNScale; // size of the bounding sphere radius + double MLSRadius; + double bilateralRange; bool bilateral; bool hermite; unsigned int numIter; @@ -547,7 +548,7 @@ void createMLSSurfaces(Subdomain__FMLS& subdomain_FMLS, subdomain_FMLS.clear(); subdomain_FMLS_indices.clear(); - typedef boost::unordered_map SurfaceIndexMap; + typedef boost::unordered_map SurfaceIndexMap; SurfaceIndexMap current_subdomain_FMLS_indices; SurfaceIndexMap subdomain_sample_numbers; @@ -587,7 +588,7 @@ void createMLSSurfaces(Subdomain__FMLS& subdomain_FMLS, std::vector< std::vector > pns; - int count = 0; + std::size_t count = 0; //Memory allocation for the point plus normals of the point samples for (typename SurfaceIndexMap::iterator it = subdomain_sample_numbers.begin(); it != subdomain_sample_numbers.end(); ++it) @@ -597,7 +598,7 @@ void createMLSSurfaces(Subdomain__FMLS& subdomain_FMLS, count++; } - std::vector current_v_count(count, 0); + std::vector current_v_count(count, 0); std::vector point_spacing(count, 0.); std::vector point_spacing_count(count, 0); @@ -613,7 +614,7 @@ void createMLSSurfaces(Subdomain__FMLS& subdomain_FMLS, for (const Surface_index& surf_i : v_surface_indices) { - const int fmls_id = current_subdomain_FMLS_indices[surf_i]; + const std::size_t& fmls_id = current_subdomain_FMLS_indices[surf_i]; const Point_3& p = point(vit->point()); @@ -656,7 +657,7 @@ void createMLSSurfaces(Subdomain__FMLS& subdomain_FMLS, edgeMap.insert(e); const Surface_index surf_i = c3t3.surface_patch_index(*fit); - const int fmls_id = current_subdomain_FMLS_indices[surf_i]; + const std::size_t fmls_id = current_subdomain_FMLS_indices[surf_i]; point_spacing[fmls_id] += CGAL::approximate_sqrt( CGAL::squared_distance(point(vh0->point()), point(vh1->point()))); @@ -675,7 +676,7 @@ void createMLSSurfaces(Subdomain__FMLS& subdomain_FMLS, { const Surface_index surf_i = c3t3.surface_patch_index(*fit); - const int fmls_id = current_subdomain_FMLS_indices[surf_i]; + const std::size_t fmls_id = current_subdomain_FMLS_indices[surf_i]; Vertex_handle vhs[3] = { fit->first->vertex(indices(fit->second, 0)), fit->first->vertex(indices(fit->second, 1)), @@ -735,7 +736,7 @@ void createMLSSurfaces(Subdomain__FMLS& subdomain_FMLS, point_spacing_count[fmls_id] += 3; } } - for (unsigned int i = 0; i < points_to_add.size(); i++) + for (std::size_t i = 0; i < points_to_add.size(); i++) { Vector_3& point = points_to_add[i]; @@ -755,7 +756,7 @@ void createMLSSurfaces(Subdomain__FMLS& subdomain_FMLS, } - int nb_of_mls_to_create = 0; + std::size_t nb_of_mls_to_create = 0; double average_point_spacing = 0; //Cretaing the actual MLS surfaces @@ -784,7 +785,7 @@ void createMLSSurfaces(Subdomain__FMLS& subdomain_FMLS, { if (current_v_count[it->second] > 3) { - float current_point_spacing = static_cast(point_spacing[it->second]); + const double current_point_spacing = point_spacing[it->second]; //subdomain_FMLS[count].toggleHermite(true); subdomain_FMLS[count].setPN(pns[it->second], diff --git a/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/smooth_vertices.h b/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/smooth_vertices.h index 202afbd29aa..3c85c72324f 100644 --- a/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/smooth_vertices.h +++ b/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/smooth_vertices.h @@ -50,7 +50,7 @@ class Tetrahedral_remeshing_smoother private: typedef CGAL::Tetrahedral_remeshing::internal::FMLS FMLS; std::vector subdomain_FMLS; - boost::unordered_map subdomain_FMLS_indices; + boost::unordered_map subdomain_FMLS_indices; public: template diff --git a/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/tetrahedral_remeshing_helpers.h b/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/tetrahedral_remeshing_helpers.h index 2a5c7b83822..5ad1cc5cc14 100644 --- a/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/tetrahedral_remeshing_helpers.h +++ b/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/tetrahedral_remeshing_helpers.h @@ -64,7 +64,7 @@ const int indices_table[4][3] = { { 3, 1, 2 }, { 3, 0, 1 }, { 2, 1, 0 } }; -int indices(const unsigned int& i, const unsigned int& j) +int indices(const int& i, const int& j) { CGAL_assertion(i < 4 && j < 3); if(i < 4 && j < 3) diff --git a/Tetrahedral_remeshing/test/Tetrahedral_remeshing/test_tetrahedral_remeshing.cpp b/Tetrahedral_remeshing/test/Tetrahedral_remeshing/test_tetrahedral_remeshing.cpp index c94e1928d6d..b3341824a82 100644 --- a/Tetrahedral_remeshing/test/Tetrahedral_remeshing/test_tetrahedral_remeshing.cpp +++ b/Tetrahedral_remeshing/test/Tetrahedral_remeshing/test_tetrahedral_remeshing.cpp @@ -55,7 +55,7 @@ int main(int argc, char* argv[]) Remeshing_triangulation tr; generate_input_one_subdomain(1000, tr); - const float target_edge_length = (argc > 1) ? atof(argv[1]) : 0.1f; + const double target_edge_length = (argc > 1) ? atof(argv[1]) : 0.1; CGAL::tetrahedral_isotropic_remeshing(tr, target_edge_length); From e6b1e5531c876cb252158a81efc2dabec8794de4 Mon Sep 17 00:00:00 2001 From: Maxime Gimeno Date: Thu, 7 May 2020 09:49:53 +0200 Subject: [PATCH 358/568] Fix affine_transformation_plugin --- .../Polyhedron/Plugins/PCA/Affine_transform_plugin.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/Polyhedron/demo/Polyhedron/Plugins/PCA/Affine_transform_plugin.cpp b/Polyhedron/demo/Polyhedron/Plugins/PCA/Affine_transform_plugin.cpp index d65db7c9dd9..d9c7425b3a2 100644 --- a/Polyhedron/demo/Polyhedron/Plugins/PCA/Affine_transform_plugin.cpp +++ b/Polyhedron/demo/Polyhedron/Plugins/PCA/Affine_transform_plugin.cpp @@ -133,11 +133,11 @@ public: { bbox = bbox + ps.point(*it).bbox(); } - CGAL::qglviewer::Vec min(bbox.xmin(),bbox.ymin(),bbox.zmin()); - CGAL::qglviewer::Vec max(bbox.xmax(),bbox.ymax(),bbox.zmax()); + CGAL::qglviewer::Vec v_min(bbox.xmin(),bbox.ymin(),bbox.zmin()); + CGAL::qglviewer::Vec v_max(bbox.xmax(),bbox.ymax(),bbox.zmax()); - _bbox = Bbox(min.x,min.y,min.z, - max.x,max.y,max.z); + _bbox = Bbox(v_min.x,v_min.y,v_min.z, + v_max.x,v_max.y,v_max.z); } bool isEmpty() const{return false;} Q_SIGNALS: From ec57a2af5be704bb5da32870a45ef1b22f70675e Mon Sep 17 00:00:00 2001 From: Dmitry Anisimov Date: Thu, 7 May 2020 15:18:08 +0200 Subject: [PATCH 359/568] modified cmakelists to fix the boost mp on clang issue #3816 --- Installation/CMakeLists.txt | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/Installation/CMakeLists.txt b/Installation/CMakeLists.txt index 13ef48188f8..25a1e6b06b9 100644 --- a/Installation/CMakeLists.txt +++ b/Installation/CMakeLists.txt @@ -495,6 +495,12 @@ if( "${CMAKE_CXX_COMPILER}" MATCHES "icl" OR "${CMAKE_CXX_COMPILER}" MATCHES "ic endif() endif() +if ("${CMAKE_CXX_COMPILER}" MATCHES "xctoolchain") + message(STATUS "Clang compiler is detected.") + if (CMAKE_CXX_COMPILER_VERSION VERSION_LESS 11.0.3) + uniquely_add_flags(CMAKE_CXX_FLAGS "-DCGAL_DO_NOT_USE_BOOST_MP") + endif() +endif() if ( CMAKE_COMPILER_IS_GNUCXX ) From 89dc46fbac522dc89a61f31fdf1529f932e7c133 Mon Sep 17 00:00:00 2001 From: Dmitry Anisimov Date: Thu, 7 May 2020 20:03:21 +0200 Subject: [PATCH 360/568] fairing bug with cotangent weights fix for the issue #4706 --- .../CGAL/Polygon_mesh_processing/Weights.h | 45 +++++++++++++++++-- .../CGAL/Polygon_mesh_processing/fair.h | 6 ++- 2 files changed, 47 insertions(+), 4 deletions(-) diff --git a/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/Weights.h b/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/Weights.h index b1951e7af34..1a11241bf66 100644 --- a/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/Weights.h +++ b/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/Weights.h @@ -150,9 +150,9 @@ public: Vector a = get(ppmap(), v0) - get(ppmap(), v1); Vector b = get(ppmap(), v2) - get(ppmap(), v1); - double dot_ab = a*b; - double dot_aa = a.squared_length(); - double dot_bb = b.squared_length(); + double dot_ab = CGAL::to_double(a * b); + double dot_aa = CGAL::to_double(a.squared_length()); + double dot_bb = CGAL::to_double(b.squared_length()); double lb = -0.999, ub = 0.999; double cosine = dot_ab / CGAL::sqrt(dot_aa) / CGAL::sqrt(dot_bb); cosine = (cosine < lb) ? lb : cosine; @@ -867,6 +867,45 @@ public: } }; +// Cotangent_value_Meyer has been changed to the version: +// Cotangent_value_Meyer_secure to avoid imprecisions from +// the issue #4706 - https://github.com/CGAL/cgal/issues/4706. +template< +class PolygonMesh, class VertexPointMap = typename boost::property_map::type> +class Cotangent_weight_with_voronoi_area_fairing_secure { + + typedef PolygonMesh PM; + typedef VertexPointMap VPMap; + Voronoi_area voronoi_functor; + Cotangent_weight > cotangent_functor; + +public: + Cotangent_weight_with_voronoi_area_fairing_secure(PM& pmesh_) : + voronoi_functor(pmesh_, get(CGAL::vertex_point, pmesh_)), + cotangent_functor(pmesh_, get(CGAL::vertex_point, pmesh_)) + { } + + Cotangent_weight_with_voronoi_area_fairing_secure(PM& pmesh_, VPMap vpmap_) : + voronoi_functor(pmesh_, vpmap_), + cotangent_functor(pmesh_, vpmap_) + { } + + PM& pmesh() { + return voronoi_functor.pmesh(); + } + + typedef typename boost::graph_traits::halfedge_descriptor halfedge_descriptor; + typedef typename boost::graph_traits::vertex_descriptor vertex_descriptor; + + double w_i(vertex_descriptor v_i) { + return 0.5 / voronoi_functor(v_i); + } + + double w_ij(halfedge_descriptor he) { + return cotangent_functor(he) * 2.0; + } +}; + template class Uniform_weight_fairing { diff --git a/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/fair.h b/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/fair.h index 2ab58d9d060..facf3ad92e1 100644 --- a/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/fair.h +++ b/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/fair.h @@ -146,7 +146,11 @@ namespace internal { #endif typedef typename GetVertexPointMap < TriangleMesh, NamedParameters>::type VPMap; - typedef CGAL::internal::Cotangent_weight_with_voronoi_area_fairing + + // Cotangent_weight_with_voronoi_area_fairing has been changed to the version: + // Cotangent_weight_with_voronoi_area_fairing_secure to avoid imprecisions from + // the issue #4706 - https://github.com/CGAL/cgal/issues/4706. + typedef CGAL::internal::Cotangent_weight_with_voronoi_area_fairing_secure Default_Weight_calculator; VPMap vpmap_ = choose_parameter(get_parameter(np, internal_np::vertex_point), From fc13a42db5beaa86cc9fa66facc093b71d40f2ed Mon Sep 17 00:00:00 2001 From: Dmitry Anisimov Date: Fri, 8 May 2020 11:41:34 +0200 Subject: [PATCH 361/568] added a comment and info message --- Installation/CMakeLists.txt | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Installation/CMakeLists.txt b/Installation/CMakeLists.txt index 25a1e6b06b9..aaa999c0753 100644 --- a/Installation/CMakeLists.txt +++ b/Installation/CMakeLists.txt @@ -495,9 +495,11 @@ if( "${CMAKE_CXX_COMPILER}" MATCHES "icl" OR "${CMAKE_CXX_COMPILER}" MATCHES "ic endif() endif() +# This fixes the issue #3816 - https://github.com/CGAL/cgal/issues/3816. if ("${CMAKE_CXX_COMPILER}" MATCHES "xctoolchain") message(STATUS "Clang compiler is detected.") if (CMAKE_CXX_COMPILER_VERSION VERSION_LESS 11.0.3) + message(STATUS "Boost mp is turned off for all clang versions below 11.0.3!") uniquely_add_flags(CMAKE_CXX_FLAGS "-DCGAL_DO_NOT_USE_BOOST_MP") endif() endif() From 1056c9b428249acbf5b77770fa86c79c777b8670 Mon Sep 17 00:00:00 2001 From: Dmitry Anisimov Date: Fri, 8 May 2020 11:52:53 +0200 Subject: [PATCH 362/568] removed trailing whitespaces --- .../include/CGAL/Polygon_mesh_processing/Weights.h | 12 ++++++------ .../include/CGAL/Polygon_mesh_processing/fair.h | 2 +- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/Weights.h b/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/Weights.h index 1a11241bf66..2dcb1f6f474 100644 --- a/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/Weights.h +++ b/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/Weights.h @@ -868,25 +868,25 @@ public: }; // Cotangent_value_Meyer has been changed to the version: -// Cotangent_value_Meyer_secure to avoid imprecisions from +// Cotangent_value_Meyer_secure to avoid imprecisions from // the issue #4706 - https://github.com/CGAL/cgal/issues/4706. template< class PolygonMesh, class VertexPointMap = typename boost::property_map::type> class Cotangent_weight_with_voronoi_area_fairing_secure { - + typedef PolygonMesh PM; typedef VertexPointMap VPMap; Voronoi_area voronoi_functor; Cotangent_weight > cotangent_functor; public: - Cotangent_weight_with_voronoi_area_fairing_secure(PM& pmesh_) : - voronoi_functor(pmesh_, get(CGAL::vertex_point, pmesh_)), + Cotangent_weight_with_voronoi_area_fairing_secure(PM& pmesh_) : + voronoi_functor(pmesh_, get(CGAL::vertex_point, pmesh_)), cotangent_functor(pmesh_, get(CGAL::vertex_point, pmesh_)) { } - Cotangent_weight_with_voronoi_area_fairing_secure(PM& pmesh_, VPMap vpmap_) : - voronoi_functor(pmesh_, vpmap_), + Cotangent_weight_with_voronoi_area_fairing_secure(PM& pmesh_, VPMap vpmap_) : + voronoi_functor(pmesh_, vpmap_), cotangent_functor(pmesh_, vpmap_) { } diff --git a/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/fair.h b/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/fair.h index facf3ad92e1..a5ceaf9ba32 100644 --- a/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/fair.h +++ b/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/fair.h @@ -148,7 +148,7 @@ namespace internal { typedef typename GetVertexPointMap < TriangleMesh, NamedParameters>::type VPMap; // Cotangent_weight_with_voronoi_area_fairing has been changed to the version: - // Cotangent_weight_with_voronoi_area_fairing_secure to avoid imprecisions from + // Cotangent_weight_with_voronoi_area_fairing_secure to avoid imprecisions from // the issue #4706 - https://github.com/CGAL/cgal/issues/4706. typedef CGAL::internal::Cotangent_weight_with_voronoi_area_fairing_secure Default_Weight_calculator; From afade6d87a80a27c4da672b15b5e37bd050f611c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mael=20Rouxel-Labb=C3=A9?= Date: Sat, 9 May 2020 11:18:38 +0200 Subject: [PATCH 363/568] Fix a number of issues in CHANGES.md-CGAL 5.1 and add links --- Installation/CHANGES.md | 314 +++++++++++++++++++++------------------- 1 file changed, 169 insertions(+), 145 deletions(-) diff --git a/Installation/CHANGES.md b/Installation/CHANGES.md index dbc8910ac48..23c9f37115c 100644 --- a/Installation/CHANGES.md +++ b/Installation/CHANGES.md @@ -1,180 +1,204 @@ Release History =============== -[Release 5.1] (https://github.com/CGAL/cgal/releases/tag/releases%2FCGAL-5.1) - -### 3D Fast Intersection and Distance Computation -- The introduction of the usage of the search tree by default for all distance queries - in the 5.0 release was actually not lazy contrary to what was announced. The behavior of the - search tree is now the following: it will be used except if an explicit call to `do_not_accelerate_distance_queries()` - is made. The construction of the search tree (once insertion of primitives is done) will be triggered by the first - distance query or by an explicit call to `accelerate_distance_queries()`. -- **Breaking change**: `accelerate_distance_queries()` and `do_not_accelerate_distance_queries()` are not longer `const` functions. - -### Optimal Bounding Box (new package) -- This package implements an optimization algorithm that aims to construct a close approximation - of the *optimal bounding box* of a mesh or a point set, which is defined as the smallest - (in terms of volume) bounding box that contains a given mesh or point set. - -### 2D and 3D Linear Geometry Kernel - - Add `CompareSignedDistanceToLine_2` in the 2D/3D Kernel concept to compare - the signed distance of two points to a line, or the line passing through two given points. - Corresponding functors in the model (`Compare_signed_distance_to_line_2`) are also added. - -### 2D Triangulations - - Add function `split_subconstraint_graph_into_constraints()` to - `Constrained_triangulation_plus_2` to initialize the constraints - from a soup of disconnected segments that should first be split - into polylines. - -### 3D Convex Hulls - - The long-deprecated function `CGAL::convex_hull_3_to_polyhedron_3()` has been removed. - The function `CGAL::convex_hull_3_to_face_graph()` should be used instead. - -### dD Spatial Searching - - - The kd-tree can now be built in parallel: `CGAL::Kd_tree::build()` - is given an optional template parameter `ConcurrencyTag` (default - value remains `CGAL::Sequential_tag` for backward compatibility). - -Release 5.0 +[Release 5.1](https://github.com/CGAL/cgal/releases/tag/releases%2FCGAL-5.1) ----------- -Release date: June 2020 +Release date: July 2020 -### Surface Mesh Topology (new package) +### [Surface Mesh Topology](https://doc.cgal.org/5.1/Manual/packages.html#PkgSurfaceMeshTopologySummary) (new package) - - This package allows to compute some topological invariants of - surfaces: - - test if two (closed) curves on a combinatorial surface are homotopic. The user can choose between free homotopy and homotopy with fixed endpoints. - - test is a curve is contractible. - - compute shortest non-contractible cycles on a surface, with or without weights on edges. +- This package enables the computation of some topological invariants of surfaces, such as: + - test if two (closed) curves on a combinatorial surface are homotopic. Users can choose + between free homotopy and homotopy with fixed endpoints; + - test is a curve is contractible; + - compute shortest non-contractible cycles on a surface, with or without weights on edges. -### 3D Fast Intersection and Distance Computation -- **Breaking change**: the internal search tree is now lazily constructed. To disable it, one must call - the new function `do_not_accelerate_distance_queries()` before the first distance query. +### [Optimal Bounding Box](https://doc.cgal.org/5.1/Manual/packages.html#PkgOptimalBoundingBox) (new package) -### Intersecting Sequences of dD Iso-oriented Boxes - - Added parallel versions of the functions `CGAL::box_intersection_d()` and `CGAL::box_self_intersection_d()`. +- This package implements an optimization algorithm that aims to construct a close approximation + of the *optimal bounding box* of a mesh or a point set, which is defined as the smallest + (in terms of volume) bounding box that contains a given mesh or point set. -### CGAL and the Boost Graph Library (BGL) - - Introduced the function `set_triangulation_ids(Triangulation& tr)` which must be used to initialize vertex, - edge, and face indices of a triangulation meant to be used with BGL algorithms. - - Added function `alpha_expansion_graphcut()` which regularizes a - multi-label partition over a user-defined graph. - - Added function `regularize_face_selection_borders()` which uses - this alpha expansion graphcut to regularize the borders of a - selected faces on a triangle mesh. +### [2D and 3D Linear Geometry Kernel](https://doc.cgal.org/5.1/Manual/packages.html#PkgKernel23) -### Polygon Mesh Processing +- Added the functor [`CompareSignedDistanceToLine_2`](https://doc.cgal.org/5.1/Kernel_23/classKernel_1_1CompareSignedDistanceToLine__2.html) + to the 2D/3D [`Kernel`](https://doc.cgal.org/5.1/Kernel_23/classKernel.html) concept to compare + the signed distance of two points to a line, or the line passing through two given points. + Corresponding functors in the model ([`Compare_signed_distance_to_line_2`](https://doc.cgal.org/5.1/Kernel_23/classKernel.html#a066d07dd592ac36ba7ee90988abd349f)) are also added. -- Introduced a new function, `CGAL::Polygon_mesh_processing::remove_connected_components_of_negligible_size()`, +### [dD Geometry Kernel](https://doc.cgal.org/5.1/Manual/packages.html#PkgKernelD) + +- The kernels [`Epick_d`](https://doc.cgal.org/5.1/Kernel_d/structCGAL_1_1Epick__d.html) + and [`Epeck_d`](https://doc.cgal.org/5.1/Kernel_d/structCGAL_1_1Epeck__d.html) gain two new functors: + [`Power_side_of_bounded_power_sphere_d`](https://doc.cgal.org/5.1/Kernel_d/classCGAL_1_1Epeck__d_1_1Power__side__of__bounded__power__sphere__d.html) + and [`Compute_squared_radius_smallest_orthogonal_sphere_d`](https://doc.cgal.org/5.1/Kernel_d/classCGAL_1_1Epeck__d_1_1Compute__squared__radius__smallest__orthogonal__sphere__d.html). + Those are essential for the computation of weighted alpha-complexes. + +### [CGAL and the Boost Graph Library (BGL)](https://doc.cgal.org/5.1/Manual/packages.html#PkgBGL) + +- Added the function [`alpha_expansion_graphcut()`](https://doc.cgal.org/5.1/BGL/group__PkgBGLPartition.html#ga79c3f58b577af51d1140450729d38f22), + which regularizes a multi-label partition over a user-defined graph. +- Added the function [`regularize_face_selection_borders()`](https://doc.cgal.org/5.1/BGL/group__PkgBGLSelectionFct.html#gac71322b0cc7d7d59447531d5e5e345b6), + which uses this alpha expansion graphcut to regularize the borders of a selected faces on a triangle mesh. +- Added the function [`set_triangulation_ids()`](https://doc.cgal.org/5.1/BGL/group__BGLGraphExternalIndices.html#ga1a22cf8bdde32fcdf1a4a78966eed630), + which must be used to initialize vertex, edge, and face indices of a triangulation meant to be used with BGL algorithms. + +### [3D Fast Intersection and Distance Computation](https://doc.cgal.org/5.1/Manual/packages.html#PkgAABBTree) + +- The behavior of the internal search tree used to accelerate distance queries has changed: + usage of the internal search tree will now be enabled by default, and its construction + will be triggered by the first distance query. Automatic construction and usage can be disabled + by calling [`do_not_accelerate_distance_queries()`](https://doc.cgal.org/5.1/AABB_tree/classCGAL_1_1AABB__tree.html#abde62f52ccdf411847151aa5000ba4a4) + before the first distance query, and the tree can be built at any moment by calling + [`accelerate_distance_queries()`](https://doc.cgal.org/5.1/AABB_tree/classCGAL_1_1AABB__tree.html#a5d3877d3f2afbd09341eb4b8c230080b). +- **Breaking change**: [`accelerate_distance_queries()`](https://doc.cgal.org/5.1/AABB_tree/classCGAL_1_1AABB__tree.html#a5d3877d3f2afbd09341eb4b8c230080b) + and [`do_not_accelerate_distance_queries()`](https://doc.cgal.org/5.1/AABB_tree/classCGAL_1_1AABB__tree.html#abde62f52ccdf411847151aa5000ba4a4) + are no longer `const` functions. + +### [dD Spatial Searching](https://doc.cgal.org/5.1/Manual/packages.html#PkgSpatialSearchingD) + +- The kd-tree can now be built in parallel: [`CGAL::Kd_tree::build()`](https://doc.cgal.org/5.1/Spatial_searching/classCGAL_1_1Kd__tree.html#a8559dbe4d7136fbc8ebab5ee290cbe06) + is given an optional template parameter `ConcurrencyTag` (default + value remains [`CGAL::Sequential_tag`](https://doc.cgal.org/5.1/STL_Extension/structCGAL_1_1Sequential__tag.html) + for backward compatibility). +- Improved the performance of the kd-tree in some cases: + - Not storing the points coordinates inside the tree usually + generates a lot of cache misses, leading to non-optimal + performance. This is the case for example + when indices are stored inside the tree, or to a lesser extent when the points + coordinates are stored in a dynamically allocated array (e.g., [`Epick_d`](https://doc.cgal.org/5.1/Kernel_d/structCGAL_1_1Epick__d.html) + with dynamic dimension) — we says "to a lesser extent" because the points + are re-created by the kd-tree in a cache-friendly order after its construction, + so the coordinates are more likely to be stored in a near-optimal order + on the heap. + In these cases, the new `EnablePointsCache` template parameter of the + [`CGAL::Kd_tree`](https://doc.cgal.org/5.1/Spatial_searching/classCGAL_1_1Kd__tree.html) + class can be set to `CGAL::Tag_true`. The points coordinates + will then be cached in an optimal way. This will increase memory + consumption but provides better search performance. See the updated + [`GeneralDistance`](https://doc.cgal.org/5.1/Spatial_searching/classGeneralDistance.html) + and [`FuzzyQueryItem`](https://doc.cgal.org/5.1/Spatial_searching/classFuzzyQueryItem.html) + concepts for additional requirements when using such a cache. + - In most cases (e.g., Euclidean distance), the distance computation + algorithm knows before its end that the distance will be greater + than or equal to some given value. This is used in the (orthogonal) + k-NN search to interrupt some distance computations before its end, + saving precious milliseconds, in particular in medium-to-high dimension. + +### [Intersecting Sequences of dD Iso-oriented Boxes](https://doc.cgal.org/5.1/Manual/packages.html#PkgBoxIntersectionD) + +- Added parallel versions of the functions + [`CGAL::box_intersection_d()`](https://doc.cgal.org/5.1/Box_intersection_d/group__PkgBoxIntersectionD__box__intersection__d.html) + and [`CGAL::box_self_intersection_d()`](https://doc.cgal.org/5.1/Box_intersection_d/group__PkgBoxIntersectionD__box__self__intersection__d.html). + +### [Spatial Sorting](https://doc.cgal.org/5.1/Manual/packages.html#PkgSpatialSorting) + +- Added parallel versions of the functions + [`CGAL::hilbert_sort()`](https://doc.cgal.org/5.1/Spatial_sorting/group__PkgSpatialSortingFunctions.html#ga9da67204747ac19dff65f9c9ff2fca9e) + and [`CGAL::spatial_sort()`](https://doc.cgal.org/5.1/Spatial_sorting/group__PkgSpatialSortingFunctions.html#ga7c597c11a3b3859234ff68526cead84d) + in 2D and 3D when the median policy is used. + The parallel versions use up to four threads in 2D, and up to eight threads in 3D. + +### [3D Convex Hulls](https://doc.cgal.org/5.1/Manual/packages.html#PkgConvexHull3) + +- A new overload for [`CGAL::convex_hull_3()`](https://doc.cgal.org/5.1/Convex_hull_3/group__PkgConvexHull3Functions.html#gaa02a3013808fc9a2e5e2f42b9fde8e30) + that takes a model of `VertexListGraph` has been added. +- The long-deprecated function `CGAL::convex_hull_3_to_polyhedron_3()` has been removed. + The function [`CGAL::convex_hull_3_to_face_graph()`](https://doc.cgal.org/5.1/Convex_hull_3/group__PkgConvexHull3Functions.html#ga2750f7f197588ed643679835c748c671) + should be used instead. + +### [Polygon Mesh Processing](https://doc.cgal.org/5.1/Manual/packages.html#PkgPolygonMeshProcessing) + +- Added the function [`CGAL::Polygon_mesh_processing::volume_connected_component()`](https://doc.cgal.org/5.1/Polygon_mesh_processing/group__PMP__orientation__grp.html#ga133e58280959c152770525f27bb42b91), + which can be used to get information about the nesting of the connected components of a given triangle mesh and about + the volumes defined. +- Added the function [`CGAL::Polygon_mesh_processing::remove_connected_components_of_negligible_size()`](https://doc.cgal.org/5.1/Polygon_mesh_processing/group__PMP__repairing__grp.html#gac544fcaba1d59d330a3a1536caff392a), which can be used to remove connected components whose area or volume is under a certain threshold. Area and volume thresholds are either specified by the user or deduced from the bounding box of the mesh. -- Added the function `CGAL::Polygon_mesh_processing::volume_connected_component()` that can be used to - get information about the nesting of the connected components of a given triangle mesh and about - the volumes defined. -- Added a new named parameter for `keep_large_connected_components()` and `remove_connected_components_of_negligible_size` - that can be used to perform a dry run of the operation, meaning that the function will return the number of connected +- Added a new named parameter for [`CGAL::Polygon_mesh_processing::keep_large_connected_components()`](https://doc.cgal.org/5.1/Polygon_mesh_processing/group__keep__connected__components__grp.html#ga48e7b3e6922ee78cf8ce801e3e325d9a) + and [`CGAL::Polygon_mesh_processing::remove_connected_components_of_negligible_size`](https://doc.cgal.org/5.1/Polygon_mesh_processing/group__PMP__repairing__grp.html#gac544fcaba1d59d330a3a1536caff392a), + which can be used to perform a dry run of the operation, meaning that the function will return the number of connected components that would be removed with the specified threshold, but without actually removing them. -- The function `CGAL::Polygon_mesh_processing::stitch_borders()` now returns the number - of halfedge pairs that were stitched. -- Introduced the new functions `CGAL::Polygon_mesh_processing::merge_reversible_connected_components()`, - `CGAL::Polygon_mesh_processing::duplicate_incompatible_edges_in_polygon_soup()`, - and `CGAL::Polygon_mesh_processing::orient_triangle_soup_with_reference_triangle_mesh()` that can be helpful - when repairing a polygon soup. -- New function to split meshes along a mesh or a plane: - `CGAL::Polygon_mesh_processing::split()` -- New function to split a single mesh containing several connected components into several meshes containing one connected component: - `CGAL::Polygon_mesh_processing::split_connected_components()` - - Added parallel versions of the functions `CGAL::Polygon_mesh_processing::does_self_intersect()` - and `CGAL::Polygon_mesh_processing::self_intersections()`. - - The function `CGAL::Polygon_mesh_processing::polygon_soup_to_polygon_mesh` now allows passing a point map (for the point range) - and a vertex point map (for the polygon mesh) via named parameters. - - Added the function `CGAL::Polygon_mesh_processing::polygon_mesh_to_polygon_soup()`. - - Added a new function `CGAL::Polygon_mesh_processing::sample_triangle_soup()` that generates points on a triangle soup surface. +- Added the function [`CGAL::Polygon_mesh_processing::split()`](https://doc.cgal.org/5.1/Polygon_mesh_processing/group__PMP__corefinement__grp.html#gaa491feee9e41f725332bea0ea1215578), + which can be used to split meshes along a mesh or a plane. +- Added the function [`CGAL::Polygon_mesh_processing::split_connected_components()`](https://doc.cgal.org/5.1/Polygon_mesh_processing/group__keep__connected__components__grp.html#ga9ddd1e4b915a4232b1ce5611985302aa) + to split a single mesh containing several connected components into several meshes containing one connected component. +- Added the functions [`CGAL::Polygon_mesh_processing::merge_reversible_connected_components()`](https://doc.cgal.org/5.1/Polygon_mesh_processing/group__PMP__orientation__grp.html#gae25c1198a89c53d5df2f29dd57fda5ca), + [`CGAL::Polygon_mesh_processing::duplicate_non_manifold_edges_in_polygon_soup()`](https://doc.cgal.org/5.1/Polygon_mesh_processing/group__PMP__orientation__grp.html#ga2aa4f7b500dc51d1fc4747705a050946), + and [`CGAL::Polygon_mesh_processing::orient_triangle_soup_with_reference_triangle_mesh()`](https://doc.cgal.org/5.1/Polygon_mesh_processing/group__PMP__orientation__grp.html#ga31779672b3afd660664fc9a6c4fdf74d), + which can be helpful when repairing a polygon soup. +- Added the function [`CGAL::Polygon_mesh_processing::sample_triangle_soup()`](https://doc.cgal.org/5.1/Polygon_mesh_processing/group__PMP__distance__grp.html#gac7af41d13bf1a7c30852be266ac81db5), + which generates points on a triangle soup surface. +- Added parallel versions of the functions [`CGAL::Polygon_mesh_processing::does_self_intersect()`](https://doc.cgal.org/5.1/Polygon_mesh_processing/group__PMP__intersection__grp.html#gad9fe5d8b433545b69154f43935a11a3b) + and [`CGAL::Polygon_mesh_processing::self_intersections()`](https://doc.cgal.org/5.1/Polygon_mesh_processing/group__PMP__intersection__grp.html#gaf19c80ec12cbff7ebe9e69453f1d40b8). +- The function [`CGAL::Polygon_mesh_processing::stitch_borders()`](https://doc.cgal.org/5.1/Polygon_mesh_processing/group__PMP__repairing__grp.html#ga8ae4352e67d2b099994ac8990c13bd41) + now returns the number of halfedge pairs that were stitched. +- Added the function [`CGAL::Polygon_mesh_processing::polygon_mesh_to_polygon_soup()`](https://doc.cgal.org/5.1/Polygon_mesh_processing/group__PMP__repairing__grp.html#ga76648a509409ff3c3ad3f71eff8ce9d9). +- The function [`CGAL::Polygon_mesh_processing::polygon_soup_to_polygon_mesh`](https://doc.cgal.org/5.1/Polygon_mesh_processing/group__PMP__repairing__grp.html#ga0dec58e8a0112791f72ebbe77bac074b) + now allows passing a point map (for the point range) and a vertex point map (for the polygon mesh) via named parameters. -### Point Set Processing - - Added wrapper functions for registration: - - `CGAL::OpenGR::compute_registration_transformation()` computes the registration transformation - for two point sets using Super4PCS algorithm implemented in the third party library OpenGR. - - `CGAL::OpenGR::register_point_sets()` computes the registration transformation for two point - sets using Super4PCS algorithm implemented in the third party library OpenGR, and registers - the points sets by transforming the data point set using the computed transformation. - - `CGAL::pointmatcher::compute_registration_transformation()` computes the registration - transformation for two point sets using ICP algorithm implemented in the third party library - libpointmatcher. - - `CGAL::pointmatcher::register_point_sets()` computes the registration transformation for two point - sets using ICP algorithm implemented in the third party library libpointmatcher, and registers - the points sets by transforming the data point set using the computed transformation. +### [Point Set Processing](https://doc.cgal.org/5.1/Manual/packages.html#PkgPointSetProcessing3) +- Added wrapper functions for registration: + - [`CGAL::OpenGR::compute_registration_transformation()`](https://doc.cgal.org/5.1/Point_set_processing_3/group__PkgPointSetProcessing3Algorithms.html#gab81663c718960780ddb176aad845e8cd), + which computes the registration transformation for two point sets using the Super4PCS algorithm + implemented in the third party library [OpenGR](https://storm-irit.github.io/OpenGR/index.html). + - [`CGAL::OpenGR::register_point_sets()`](https://doc.cgal.org/5.1/Point_set_processing_3/group__PkgPointSetProcessing3Algorithms.html#ga6194087f512e4e23dd945a9364d0931d), + which computes the registration transformation for two point sets using the Super4PCS algorithm + implemented in the third party library [OpenGR](https://storm-irit.github.io/OpenGR/index.html), + and registers the points sets by transforming the data point set using the computed transformation. + - [`CGAL::pointmatcher::compute_registration_transformation()`](https://doc.cgal.org/5.1/Point_set_processing_3/group__PkgPointSetProcessing3Algorithms.html#gaf75af5c1634fa83fa05a33e95570b127) + computes the registration transformation for two point sets using ICP algorithm implemented + in the third party library [libpointmatcher](https://github.com/ethz-asl/libpointmatcher). + - [`CGAL::pointmatcher::register_point_sets()`](https://doc.cgal.org/5.1/Point_set_processing_3/group__PkgPointSetProcessing3Algorithms.html#gaa222278e20a3ce41930d37326cd54ef9), + which computes the registration transformation for two point sets using ICP algorithm implemented + in the third party library [libpointmatcher](https://github.com/ethz-asl/libpointmatcher), and registers + the points sets by transforming the data point set using the computed transformation. + +### [2D Triangulations](https://doc.cgal.org/5.1/Manual/packages.html#PkgTriangulation2) -### 2D Triangulations - To fix an inconsistency between code and documentation and to clarify which types of intersections - are truly allowed in constrained Delaunay triangulations, the tag `CGAL::No_intersection_tag` - has been deprecated in favor of two new tags `CGAL::No_constraint_intersection_tag` - and `CGAL::No_constraint_intersection_requiring_constructions_tag`. + are truly allowed in constrained Delaunay triangulations, the tag [`CGAL::No_intersection_tag`](https://doc.cgal.org/5.1/Triangulation_2/structCGAL_1_1No__intersection__tag.html) + has been deprecated in favor of two new tags: [`CGAL::No_constraint_intersection_tag`](https://doc.cgal.org/5.1/Triangulation_2/structCGAL_1_1No__constraint__intersection__tag.html) + and [`CGAL::No_constraint_intersection_requiring_constructions_tag`](https://doc.cgal.org/5.1/Triangulation_2/structCGAL_1_1No__constraint__intersection__requiring__constructions__tag.html). The latter is equivalent to the now-deprecated `CGAL::No_intersection_tag`, and allows constraints to intersect as long as no new point has to be created to represent that intersection (for example, the intersection of two constraint segments in a 'T'-like junction is an existing point - and does not require any new construction). The former tag, `CGAL::No_constraint_intersection_tag`, + and as such does not require any new construction). The former tag, `CGAL::No_constraint_intersection_tag`, does not allow any intersection, except for the configuration of two constraints having a single common endpoints, for convience. +- Added the function [`CGAL::split_subconstraint_graph_into_constraints()`](https://doc.cgal.org/5.1/Triangulation_2/classCGAL_1_1Constrained__triangulation__plus__2.html#adea77f5db5cd4dfae302e4502f1caa85) + to [`Constrained_triangulation_plus_2`](https://doc.cgal.org/5.1/Triangulation_2/classCGAL_1_1Constrained__triangulation__plus__2.html) to initialize the constraints + from a soup of disconnected segments that should first be split into polylines. -### 3D Triangulations -- The free function `CGAL::file_input()` and the member function `CGAL::Triangulation_3::file_input()` - have been added. The first allows to load a `Triangulation_3` from an input stream, using functors to create vertices and cells. +### [3D Triangulations](https://doc.cgal.org/5.1/Manual/packages.html#PkgTriangulation3) + +- The free function `CGAL::file_input()` and the member function [`CGAL::Triangulation_3::file_input()`](https://doc.cgal.org/5.1/Triangulation_3/group__PkgIOTriangulation3.html#gadd94d0613e2dd9cdd2e88d2c74d5b1c8) + have been added. The first allows to load a [`CGAL::Triangulation_3`](https://doc.cgal.org/5.1/Triangulation_3/classCGAL_1_1Triangulation__3.html) + from an input stream, using functors to create vertices and cells. The second is simply the member function version of the first one. -### 3D Triangulation Data Structure -- The free function `CGAL::file_input()` and the member function `CGAL::TDS_3::file_input()` - have been added. The first allows to load a `TDS_3` from an input stream, using functors to create vertices and cells. - The second is simply the member function version of the first one. +### [3D Triangulation Data Structure](https://doc.cgal.org/5.1/Manual/packages.html#PkgTDS3) -### dD Spatial Searching +- The free function `CGAL::file_input()` and the member function [`CGAL::TDS_3::file_input()`](https://doc.cgal.org/5.1/TDS_3/group__PkgIOTDS3.html#ga381446a02a9240cc83e79c48b37cd119) + have been added. The first allows to load a [`CGAL::Triangulation_data_structure_3`](https://doc.cgal.org/5.1/TDS_3/classCGAL_1_1Triangulation__data__structure__3.html) + from an input stream, using functors to create vertices and cells. + The second is simply the member function version of the first one. -- Improved the performance of the kd-tree in some cases: - - Not storing the points coordinates inside the tree usually - generates a lot of cache misses, leading to non-optimal - performance. This is the case for example - when indices are stored inside the tree, or to a lesser extent when the points - coordinates are stored in a dynamically allocated array (e.g., `Epick_d` - with dynamic dimension) — we says "to a lesser extent" because the points - are re-created by the kd-tree in a cache-friendly order after its construction, - so the coordinates are more likely to be stored in a near-optimal order - on the heap. - In these cases, the new `EnablePointsCache` template parameter of the - `CGAL::Kd_tree` class can be set to `CGAL::Tag_true`. The points coordinates - will then be cached in an optimal way. This will increase memory - consumption but provides better search performance. See the updated - `GeneralDistance` and `FuzzyQueryItem` - concepts for additional requirements when using such a cache. - - In most cases (e.g., Euclidean distance), the distance computation - algorithm knows before its end that the distance will be greater - than or equal to some given value. This is used in the (orthogonal) - k-NN search to interrupt some distance computations before its end, - saving precious milliseconds, in particular in medium-to-high dimension. +### [Surface Mesh Simplification](https://doc.cgal.org/5.1/Manual/packages.html#PkgSurfaceMeshSimplification) -### Spatial Sorting - - Added parallel versions of `hilbert_sort()` and `spatial_sort()` in 2D and 3D when the median policy is used. - The parallel versions use up to four threads in 2D, and up to eight threads in 3D. +- Added a [new simplification method](https://doc.cgal.org/5.1/Surface_mesh_simplification/classCGAL_1_1Surface__mesh__simplification_1_1GarlandHeckbert__policies.html) + based on the quadric error defined by Garland and Heckbert. +- The concept `EdgeProfile` has been removed. This concept was not actually in use as the CGAL-provided model [`CGAL::Edge_profile`](https://doc.cgal.org/5.1/Surface_mesh_simplification/classCGAL_1_1Surface__mesh__simplification_1_1Edge__profile.html) + was imposed to the user. Other concepts have been clarified to reflect the fact that the API uses this particular class. -### dD Geometry Kernel -- Epick\_d and Epeck\_d gain 2 new functors: `Power_side_of_bounded_power_sphere_d` and - `Compute_squared_radius_smallest_orthogonal_sphere_d`. Those are - essential for the computation of weighted alpha-complexes. +### [STL Extensions for CGAL](https://doc.cgal.org/5.1/Manual/packages.html#PkgSTLExtension) -### Surface Mesh Simplification -- Added a new simplification method based on the quadric error defined by Garland and Heckbert. -- The concept "EdgeProfile" has been removed. This concept was not actually in use as the CGAL-provided model `CGAL::Edge_profile` - was imposed to the user. Other concepts have been clarified to reflect the fact that the API uses this particular class. - -### STL Extensions for CGAL - - Added a new concurrency tag: `CGAL::Parallel_if_available_tag`. This tag is a convenience typedef to `CGAL::Parallel_tag` - if the third party library TBB has been found and linked with, and to `CGAL::Sequential_tag` otherwise. - -### Convex_hull_3 -- A new overload for `convex_hull_3()` that takes a model of `VertexListGraph` has been added. +- Added a new concurrency tag: [`CGAL::Parallel_if_available_tag`](https://doc.cgal.org/5.1/STL_Extension/structCGAL_1_1Parallel__if__available__tag.html). + This tag is a convenience typedef to [`CGAL::Parallel_tag`](https://doc.cgal.org/5.1/STL_Extension/structCGAL_1_1Parallel__tag.html) + if the third party library TBB has been found and linked with, and to + [`CGAL::Sequential_tag`](https://doc.cgal.org/5.1/STL_Extension/structCGAL_1_1Sequential__tag.html) otherwise. [Release 5.0](https://github.com/CGAL/cgal/releases/tag/releases%2FCGAL-5.0) From 94d98ed0dcaae94a549b1cfbe30c386aefd74ea9 Mon Sep 17 00:00:00 2001 From: Jane Tournois Date: Mon, 11 May 2020 06:47:13 +0200 Subject: [PATCH 364/568] c3t3 cell info in the .mesh file is subdomain_index() the recent internal changes in build_triangulation() use subdomain_index(), which is part of the concept MeshCellBase_3 --- Mesh_3/test/Mesh_3/test_c3t3_into_facegraph.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Mesh_3/test/Mesh_3/test_c3t3_into_facegraph.cpp b/Mesh_3/test/Mesh_3/test_c3t3_into_facegraph.cpp index 124cb0f75aa..6df89caf971 100644 --- a/Mesh_3/test/Mesh_3/test_c3t3_into_facegraph.cpp +++ b/Mesh_3/test/Mesh_3/test_c3t3_into_facegraph.cpp @@ -49,8 +49,8 @@ int main (int argc, char** argv){ cit != c3t3.triangulation().finite_cells_end(); ++cit) { - CGAL_assertion(cit->info() >= 0); - c3t3.add_to_complex(cit, cit->info()); + CGAL_assertion(cit->subdomain_index() >= 0); + c3t3.add_to_complex(cit, cit->subdomain_index()); for(int i=0; i < 4; ++i) { if(cit->surface_patch_index(i)>0) From 171ef5a0e760dada72045bfba909a487d844fda1 Mon Sep 17 00:00:00 2001 From: Maxime Gimeno Date: Mon, 11 May 2020 10:10:49 +0200 Subject: [PATCH 365/568] Fix CHANGES.MD for file_input --- Installation/CHANGES.md | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/Installation/CHANGES.md b/Installation/CHANGES.md index 23c9f37115c..35d24f35b0d 100644 --- a/Installation/CHANGES.md +++ b/Installation/CHANGES.md @@ -174,17 +174,15 @@ Release date: July 2020 ### [3D Triangulations](https://doc.cgal.org/5.1/Manual/packages.html#PkgTriangulation3) -- The free function `CGAL::file_input()` and the member function [`CGAL::Triangulation_3::file_input()`](https://doc.cgal.org/5.1/Triangulation_3/group__PkgIOTriangulation3.html#gadd94d0613e2dd9cdd2e88d2c74d5b1c8) - have been added. The first allows to load a [`CGAL::Triangulation_3`](https://doc.cgal.org/5.1/Triangulation_3/classCGAL_1_1Triangulation__3.html) +- The member function [`CGAL::Triangulation_3::file_input()`](https://doc.cgal.org/5.1/Triangulation_3/group__PkgIOTriangulation3.html#gadd94d0613e2dd9cdd2e88d2c74d5b1c8) + have been added. It allows to load a [`CGAL::Triangulation_3`](https://doc.cgal.org/5.1/Triangulation_3/classCGAL_1_1Triangulation__3.html) from an input stream, using functors to create vertices and cells. - The second is simply the member function version of the first one. ### [3D Triangulation Data Structure](https://doc.cgal.org/5.1/Manual/packages.html#PkgTDS3) -- The free function `CGAL::file_input()` and the member function [`CGAL::TDS_3::file_input()`](https://doc.cgal.org/5.1/TDS_3/group__PkgIOTDS3.html#ga381446a02a9240cc83e79c48b37cd119) - have been added. The first allows to load a [`CGAL::Triangulation_data_structure_3`](https://doc.cgal.org/5.1/TDS_3/classCGAL_1_1Triangulation__data__structure__3.html) +- The member function [`CGAL::TDS_3::file_input()`](https://doc.cgal.org/5.1/TDS_3/group__PkgIOTDS3.html#ga381446a02a9240cc83e79c48b37cd119) + have been added. It allows to load a [`CGAL::Triangulation_data_structure_3`](https://doc.cgal.org/5.1/TDS_3/classCGAL_1_1Triangulation__data__structure__3.html) from an input stream, using functors to create vertices and cells. - The second is simply the member function version of the first one. ### [Surface Mesh Simplification](https://doc.cgal.org/5.1/Manual/packages.html#PkgSurfaceMeshSimplification) From 2ef4e362c1a3cb2cc00be355fdbb5125fd46fc0b Mon Sep 17 00:00:00 2001 From: Dmitry Anisimov Date: Mon, 11 May 2020 11:29:54 +0200 Subject: [PATCH 366/568] integrated review for the fix --- Installation/CMakeLists.txt | 8 -------- .../cmake/modules/CGAL_GeneratorSpecificSettings.cmake | 9 +++++++++ 2 files changed, 9 insertions(+), 8 deletions(-) diff --git a/Installation/CMakeLists.txt b/Installation/CMakeLists.txt index aaa999c0753..13ef48188f8 100644 --- a/Installation/CMakeLists.txt +++ b/Installation/CMakeLists.txt @@ -495,14 +495,6 @@ if( "${CMAKE_CXX_COMPILER}" MATCHES "icl" OR "${CMAKE_CXX_COMPILER}" MATCHES "ic endif() endif() -# This fixes the issue #3816 - https://github.com/CGAL/cgal/issues/3816. -if ("${CMAKE_CXX_COMPILER}" MATCHES "xctoolchain") - message(STATUS "Clang compiler is detected.") - if (CMAKE_CXX_COMPILER_VERSION VERSION_LESS 11.0.3) - message(STATUS "Boost mp is turned off for all clang versions below 11.0.3!") - uniquely_add_flags(CMAKE_CXX_FLAGS "-DCGAL_DO_NOT_USE_BOOST_MP") - endif() -endif() if ( CMAKE_COMPILER_IS_GNUCXX ) diff --git a/Installation/cmake/modules/CGAL_GeneratorSpecificSettings.cmake b/Installation/cmake/modules/CGAL_GeneratorSpecificSettings.cmake index 366378ea74e..6fc2e5c9edc 100644 --- a/Installation/cmake/modules/CGAL_GeneratorSpecificSettings.cmake +++ b/Installation/cmake/modules/CGAL_GeneratorSpecificSettings.cmake @@ -46,6 +46,15 @@ if ( NOT CGAL_GENERATOR_SPECIFIC_SETTINGS_FILE_INCLUDED ) message(STATUS "Mac Leopard detected") set(CGAL_APPLE_LEOPARD 1) endif() + + # This fixes the issue #3816 - https://github.com/CGAL/cgal/issues/3816. + if ("${CMAKE_CXX_COMPILER_ID}" MATCHES "AppleClang") + message(STATUS "Apple Clang version ${CMAKE_CXX_COMPILER_VERSION} compiler detected") + if (CMAKE_CXX_COMPILER_VERSION VERSION_LESS 11.0.3) + message(STATUS "Boost MP is turned off for all Apple Clang versions below 11.0.3!") + uniquely_add_flags(CMAKE_CXX_FLAGS "-DCGAL_DO_NOT_USE_BOOST_MP") + endif() + endif() endif() if ( NOT "${CMAKE_CFG_INTDIR}" STREQUAL "." ) From 8a52dd339357ac740b370dbfc515000cfe33c39f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mael=20Rouxel-Labb=C3=A9?= Date: Tue, 12 May 2020 11:21:06 +0200 Subject: [PATCH 367/568] Remove trailing whitespace / tabs --- Kernel_23/include/CGAL/determinant.h | 92 +++++++++---------- Kernel_23/test/Kernel_23/determinant.cpp | 2 +- .../include/CGAL/NewKernel_d/LA_eigen/LA.h | 6 +- Number_types/include/CGAL/Mpzf.h | 6 +- 4 files changed, 53 insertions(+), 53 deletions(-) diff --git a/Kernel_23/include/CGAL/determinant.h b/Kernel_23/include/CGAL/determinant.h index cce36365429..678db0c8e1a 100644 --- a/Kernel_23/include/CGAL/determinant.h +++ b/Kernel_23/include/CGAL/determinant.h @@ -220,13 +220,13 @@ determinant( const RT m04 = a00*a41 - a40*a01; const RT m05 = a00*a51 - a50*a01; const RT m06 = a00*a61 - a60*a01; - + const RT m12 = a10*a21 - a20*a11; const RT m13 = a10*a31 - a30*a11; const RT m14 = a10*a41 - a40*a11; const RT m15 = a10*a51 - a50*a11; const RT m16 = a10*a61 - a60*a11; - + const RT m23 = a20*a31 - a30*a21; const RT m24 = a20*a41 - a40*a21; const RT m25 = a20*a51 - a50*a21; @@ -235,19 +235,19 @@ determinant( const RT m34 = a30*a41 - a40*a31; const RT m35 = a30*a51 - a50*a31; const RT m36 = a30*a61 - a60*a31; - + const RT m45 = a40*a51 - a50*a41; const RT m46 = a40*a61 - a60*a41; const RT m56 = a50*a61 - a60*a51; - + // Now compute the minors of rank 3 const RT m012 = m01*a22 - m02*a12 + m12*a02; const RT m013 = m01*a32 - m03*a12 + m13*a02; const RT m014 = m01*a42 - m04*a12 + m14*a02; const RT m015 = m01*a52 - m05*a12 + m15*a02; const RT m016 = m01*a62 - m06*a12 + m16*a02; - + const RT m023 = m02*a32 - m03*a22 + m23*a02; const RT m024 = m02*a42 - m04*a22 + m24*a02; const RT m025 = m02*a52 - m05*a22 + m25*a02; @@ -255,43 +255,43 @@ determinant( const RT m034 = m03*a42 - m04*a32 + m34*a02; const RT m035 = m03*a52 - m05*a32 + m35*a02; const RT m036 = m03*a62 - m06*a32 + m36*a02; - + const RT m045 = m04*a52 - m05*a42 + m45*a02; const RT m046 = m04*a62 - m06*a42 + m46*a02; - + const RT m056 = m05*a62 - m06*a52 + m56*a02; - + const RT m123 = m12*a32 - m13*a22 + m23*a12; const RT m124 = m12*a42 - m14*a22 + m24*a12; const RT m125 = m12*a52 - m15*a22 + m25*a12; const RT m126 = m12*a62 - m16*a22 + m26*a12; - + const RT m134 = m13*a42 - m14*a32 + m34*a12; const RT m135 = m13*a52 - m15*a32 + m35*a12; const RT m136 = m13*a62 - m16*a32 + m36*a12; - + const RT m145 = m14*a52 - m15*a42 + m45*a12; const RT m146 = m14*a62 - m16*a42 + m46*a12; const RT m156 = m15*a62 - m16*a52 + m56*a12; - + const RT m234 = m23*a42 - m24*a32 + m34*a22; const RT m235 = m23*a52 - m25*a32 + m35*a22; const RT m236 = m23*a62 - m26*a32 + m36*a22; - + const RT m245 = m24*a52 - m25*a42 + m45*a22; const RT m246 = m24*a62 - m26*a42 + m46*a22; const RT m256 = m25*a62 - m26*a52 + m56*a22; - + const RT m345 = m34*a52 - m35*a42 + m45*a32; const RT m346 = m34*a62 - m36*a42 + m46*a32; - + const RT m356 = m35*a62 - m36*a52 + m56*a32; - + const RT m456 = m45*a62 - m46*a52 + m56*a42; - + // Now compute the minors of rank 4 const RT m0123 = m012*a33 - m013*a23 + m023*a13 - m123*a03; @@ -305,43 +305,43 @@ determinant( const RT m0145 = m014*a53 - m015*a43 + m045*a13 - m145*a03; const RT m0146 = m014*a63 - m016*a43 + m046*a13 - m146*a03; - + const RT m0156 = m015*a63 - m016*a53 + m056*a13 - m156*a03; const RT m0234 = m023*a43 - m024*a33 + m034*a23 - m234*a03; const RT m0235 = m023*a53 - m025*a33 + m035*a23 - m235*a03; const RT m0236 = m023*a63 - m026*a33 + m036*a23 - m236*a03; - + const RT m0245 = m024*a53 - m025*a43 + m045*a23 - m245*a03; const RT m0246 = m024*a63 - m026*a43 + m046*a23 - m246*a03; - + const RT m0256 = m025*a63 - m026*a53 + m056*a23 - m256*a03; const RT m0345 = m034*a53 - m035*a43 + m045*a33 - m345*a03; const RT m0346 = m034*a63 - m036*a43 + m046*a33 - m346*a03; - + const RT m0356 = m035*a63 - m036*a53 + m056*a33 - m356*a03; const RT m0456 = m045*a63 - m046*a53 + m056*a43 - m456*a03; - + const RT m1234 = m123*a43 - m124*a33 + m134*a23 - m234*a13; const RT m1235 = m123*a53 - m125*a33 + m135*a23 - m235*a13; const RT m1236 = m123*a63 - m126*a33 + m136*a23 - m236*a13; - + const RT m1245 = m124*a53 - m125*a43 + m145*a23 - m245*a13; const RT m1246 = m124*a63 - m126*a43 + m146*a23 - m246*a13; - + const RT m1256 = m125*a63 - m126*a53 + m156*a23 - m256*a13; const RT m1345 = m134*a53 - m135*a43 + m145*a33 - m345*a13; const RT m1346 = m134*a63 - m136*a43 + m146*a33 - m346*a13; - + const RT m1356 = m135*a63 - m136*a53 + m156*a33 - m356*a13; const RT m1456 = m145*a63 - m146*a53 + m156*a43 - m456*a13; const RT m2345 = m234*a53 - m235*a43 + m245*a33 - m345*a23; const RT m2346 = m234*a63 - m236*a43 + m246*a33 - m346*a23; - + const RT m2356 = m235*a63 - m236*a53 + m256*a33 - m356*a23; const RT m2456 = m245*a63 - m246*a53 + m256*a43 - m456*a23; @@ -350,39 +350,39 @@ determinant( // Now compute the minors of rank 5 const RT m01234 = m0123*a44 - m0124*a34 + m0134*a24 - m0234*a14 + m1234*a04; - + const RT m01235 = m0123*a54 - m0125*a34 + m0135*a24 - m0235*a14 + m1235*a04; - + const RT m01236 = m0123*a64 - m0126*a34 + m0136*a24 - m0236*a14 + m1236*a04; - + const RT m01245 = m0124*a54 - m0125*a44 + m0145*a24 - m0245*a14 + m1245*a04; const RT m01246 = m0124*a64 - m0126*a44 + m0146*a24 - m0246*a14 + m1246*a04; - + const RT m01256 = m0125*a64 - m0126*a54 + m0156*a24 - m0256*a14 + m1256*a04; - + const RT m01345 = m0134*a54 - m0135*a44 + m0145*a34 - m0345*a14 + m1345*a04; const RT m01346 = m0134*a64 - m0136*a44 + m0146*a34 - m0346*a14 + m1346*a04; - + const RT m01356 = m0135*a64 - m0136*a54 + m0156*a34 - m0356*a14 + m1356*a04; const RT m01456 = m0145*a64 - m0146*a54 + m0156*a44 - m0456*a14 + m1456*a04; - + const RT m02345 = m0234*a54 - m0235*a44 + m0245*a34 - m0345*a24 + m2345*a04; const RT m02346 = m0234*a64 - m0236*a44 + m0246*a34 - m0346*a24 + m2346*a04; - + const RT m02356 = m0235*a64 - m0236*a54 + m0256*a34 - m0356*a24 + m2356*a04; const RT m02456 = m0245*a64 - m0246*a54 + m0256*a44 - m0456*a24 + m2456*a04; const RT m03456 = m0345*a64 - m0346*a54 + m0356*a44 - m0456*a34 + m3456*a04; - + const RT m12345 = m1234*a54 - m1235*a44 + m1245*a34 - m1345*a24 + m2345*a14; const RT m12346 = m1234*a64 - m1236*a44 + m1246*a34 - m1346*a24 + m2346*a14; - - + + const RT m12356 = m1235*a64 - m1236*a54 + m1256*a34 - m1356*a24 + m2356*a14; const RT m12456 = m1245*a64 - m1246*a54 + m1256*a44 - m1456*a24 + m2456*a14; const RT m13456 = m1345*a64 - m1346*a54 + m1356*a44 - m1456*a34 + m3456*a14; const RT m23456 = m2345*a64 - m2346*a54 + m2356*a44 - m2456*a34 + m3456*a24; - + // Now compute the minors of rank 6 const RT m012345 = m01234*a55 - m01235*a45 + m01245*a35 - m01345*a25 + m02345*a15 - m12345*a05; const RT m012346 = m01234*a65 - m01236*a45 + m01246*a35 - m01346*a25 + m02346*a15 - m12346*a05; @@ -391,12 +391,12 @@ determinant( const RT m013456 = m01345*a65 - m01346*a55 + m01356*a45 - m01456*a35 + m03456*a15 - m13456*a05; const RT m023456 = m02345*a65 - m02346*a55 + m02356*a45 - m02456*a35 + m03456*a25 - m23456*a05; const RT m123456 = m12345*a65 - m12346*a55 + m12356*a45 - m12456*a35 + m13456*a25 - m23456*a15; - + // Now compute the minors of rank 7 const RT m0123456 = m012345 * a66 - m012346 * a56 + m012356 * a46 - m012456 * a36 + m013456 * a26 - m023456 * a16 + m123456 * a06; -#ifdef CGAL_CHECK_DETERMINANT +#ifdef CGAL_CHECK_DETERMINANT { const RT r1 = a06 * determinant( @@ -414,7 +414,7 @@ determinant( a40, a41, a42, a43, a44, a45, a50, a51, a52, a53, a54, a55, a60, a61, a62, a63, a64, a65); - + const RT r3= a26 * determinant(a00, a01, a02, a03, a04, a05, a10, a11, a12, a13, a14, a15, @@ -422,7 +422,7 @@ determinant( a40, a41, a42, a43, a44, a45, a50, a51, a52, a53, a54, a55, a60, a61, a62, a63, a64, a65); - + const RT r4 = - a36 * determinant(a00, a01, a02, a03, a04, a05, a10, a11, a12, a13, a14, a15, a20, a21, a22, a23, a24, a25, @@ -430,7 +430,7 @@ determinant( a40, a41, a42, a43, a44, a45, a50, a51, a52, a53, a54, a55, a60, a61, a62, a63, a64, a65); - + const RT r5 = a46 * determinant(a00, a01, a02, a03, a04, a05, a10, a11, a12, a13, a14, a15, a20, a21, a22, a23, a24, a25, @@ -438,15 +438,15 @@ determinant( a50, a51, a52, a53, a54, a55, a60, a61, a62, a63, a64, a65); - + const RT r6 = - a56 * determinant(a00, a01, a02, a03, a04, a05, a10, a11, a12, a13, a14, a15, a20, a21, a22, a23, a24, a25, a30, a31, a32, a33, a34, a35, a40, a41, a42, a43, a44, a45, - + a60, a61, a62, a63, a64, a65); - + const RT r7 = a66 * determinant(a00, a01, a02, a03, a04, a05, a10, a11, a12, a13, a14, a15, a20, a21, a22, a23, a24, a25, @@ -458,7 +458,7 @@ determinant( const RT rt = r1 + r2 + r3 + r4 + r5 + r6 + r7; CGAL_assertion(rt == m0123456); } -#endif +#endif return m0123456; } diff --git a/Kernel_23/test/Kernel_23/determinant.cpp b/Kernel_23/test/Kernel_23/determinant.cpp index ba11ec6fef2..ad92bb0a2d1 100644 --- a/Kernel_23/test/Kernel_23/determinant.cpp +++ b/Kernel_23/test/Kernel_23/determinant.cpp @@ -9,7 +9,7 @@ int main() 6, 3, 3, 6, 2, 4, 5, 1, 4, 3, 5, 5, 6 ,1, 1, 3, 2, 7, 9, 6, 1, - 7, 6, 5, 4, 6, 2, 2, + 7, 6, 5, 4, 6, 2, 2, 2, 3, 5, 7, 4, 3, 3) == 763); return 0; } diff --git a/NewKernel_d/include/CGAL/NewKernel_d/LA_eigen/LA.h b/NewKernel_d/include/CGAL/NewKernel_d/LA_eigen/LA.h index 6d92765a34a..3d4afd905e5 100644 --- a/NewKernel_d/include/CGAL/NewKernel_d/LA_eigen/LA.h +++ b/NewKernel_d/include/CGAL/NewKernel_d/LA_eigen/LA.h @@ -109,9 +109,9 @@ template struct LA_eigen { return m.determinant(); } - // TODO: https://gitlab.com/libeigen/eigen/-/issues/1782 - // Implement a version of (sign_of_)determinant that works - // without (inexact) division in any dimension + // TODO: https://gitlab.com/libeigen/eigen/-/issues/1782 + // Implement a version of (sign_of_)determinant that works + // without (inexact) division in any dimension template static NT determinant(Mat_ const&m,bool=false){ switch(m.rows()){ //case 0: diff --git a/Number_types/include/CGAL/Mpzf.h b/Number_types/include/CGAL/Mpzf.h index 46ee60a70bf..89165187d93 100644 --- a/Number_types/include/CGAL/Mpzf.h +++ b/Number_types/include/CGAL/Mpzf.h @@ -364,9 +364,9 @@ struct Mpzf { if (xd != x.cache) { data() = x.data(); if (td != cache) { - pool::push(td+1); - // should we instead give it to x in case x is reused? - // x.data() = td + 1; + pool::push(td+1); + // should we instead give it to x in case x is reused? + // x.data() = td + 1; } x.init(); } else { From cb08f676d1f59fd721ae1c0f4e0bc8f847675171 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mael=20Rouxel-Labb=C3=A9?= Date: Tue, 12 May 2020 11:56:18 +0200 Subject: [PATCH 368/568] Move check code from determinant.h to Kernel_23/test + more tests --- Kernel_23/include/CGAL/determinant.h | 64 ----------- Kernel_23/test/Kernel_23/determinant.cpp | 15 --- Kernel_23/test/Kernel_23/determinant_77.cpp | 121 ++++++++++++++++++++ 3 files changed, 121 insertions(+), 79 deletions(-) delete mode 100644 Kernel_23/test/Kernel_23/determinant.cpp create mode 100644 Kernel_23/test/Kernel_23/determinant_77.cpp diff --git a/Kernel_23/include/CGAL/determinant.h b/Kernel_23/include/CGAL/determinant.h index 678db0c8e1a..f470720d560 100644 --- a/Kernel_23/include/CGAL/determinant.h +++ b/Kernel_23/include/CGAL/determinant.h @@ -396,70 +396,6 @@ determinant( // Now compute the minors of rank 7 const RT m0123456 = m012345 * a66 - m012346 * a56 + m012356 * a46 - m012456 * a36 + m013456 * a26 - m023456 * a16 + m123456 * a06; -#ifdef CGAL_CHECK_DETERMINANT - - { - const RT r1 = a06 * determinant( - a10, a11, a12, a13, a14, a15, - a20, a21, a22, a23, a24, a25, - a30, a31, a32, a33, a34, a35, - a40, a41, a42, a43, a44, a45, - a50, a51, a52, a53, a54, a55, - a60, a61, a62, a63, a64, a65); - - const RT r2 = - a16 * determinant(a00, a01, a02, a03, a04, a05, - - a20, a21, a22, a23, a24, a25, - a30, a31, a32, a33, a34, a35, - a40, a41, a42, a43, a44, a45, - a50, a51, a52, a53, a54, a55, - a60, a61, a62, a63, a64, a65); - - const RT r3= a26 * determinant(a00, a01, a02, a03, a04, a05, - a10, a11, a12, a13, a14, a15, - - a30, a31, a32, a33, a34, a35, - a40, a41, a42, a43, a44, a45, - a50, a51, a52, a53, a54, a55, - a60, a61, a62, a63, a64, a65); - - const RT r4 = - a36 * determinant(a00, a01, a02, a03, a04, a05, - a10, a11, a12, a13, a14, a15, - a20, a21, a22, a23, a24, a25, - - a40, a41, a42, a43, a44, a45, - a50, a51, a52, a53, a54, a55, - a60, a61, a62, a63, a64, a65); - - const RT r5 = a46 * determinant(a00, a01, a02, a03, a04, a05, - a10, a11, a12, a13, a14, a15, - a20, a21, a22, a23, a24, a25, - a30, a31, a32, a33, a34, a35, - - a50, a51, a52, a53, a54, a55, - a60, a61, a62, a63, a64, a65); - - const RT r6 = - a56 * determinant(a00, a01, a02, a03, a04, a05, - a10, a11, a12, a13, a14, a15, - a20, a21, a22, a23, a24, a25, - a30, a31, a32, a33, a34, a35, - a40, a41, a42, a43, a44, a45, - - a60, a61, a62, a63, a64, a65); - - const RT r7 = a66 * determinant(a00, a01, a02, a03, a04, a05, - a10, a11, a12, a13, a14, a15, - a20, a21, a22, a23, a24, a25, - a30, a31, a32, a33, a34, a35, - a40, a41, a42, a43, a44, a45, - a50, a51, a52, a53, a54, a55 - ); - - const RT rt = r1 + r2 + r3 + r4 + r5 + r6 + r7; - CGAL_assertion(rt == m0123456); - } -#endif - return m0123456; } diff --git a/Kernel_23/test/Kernel_23/determinant.cpp b/Kernel_23/test/Kernel_23/determinant.cpp deleted file mode 100644 index ad92bb0a2d1..00000000000 --- a/Kernel_23/test/Kernel_23/determinant.cpp +++ /dev/null @@ -1,15 +0,0 @@ -#define CGAL_CHECK_DETERMINANT - -#include - -int main() -{ - assert(CGAL::determinant(4, 5, 1, 4, 6, 3, 1, - 4, 3, 6, 4, 2, 7, 3, - 6, 3, 3, 6, 2, 4, 5, - 1, 4, 3, 5, 5, 6 ,1, - 1, 3, 2, 7, 9, 6, 1, - 7, 6, 5, 4, 6, 2, 2, - 2, 3, 5, 7, 4, 3, 3) == 763); - return 0; -} diff --git a/Kernel_23/test/Kernel_23/determinant_77.cpp b/Kernel_23/test/Kernel_23/determinant_77.cpp new file mode 100644 index 00000000000..c48be9908d8 --- /dev/null +++ b/Kernel_23/test/Kernel_23/determinant_77.cpp @@ -0,0 +1,121 @@ +#include +#include + +#include + +#include + +using CGAL::determinant; + +template +RT det_77_alt(const RT& a00, const RT& a01, const RT& a02, const RT& a03, const RT& a04, const RT& a05, const RT& a06, + const RT& a10, const RT& a11, const RT& a12, const RT& a13, const RT& a14, const RT& a15, const RT& a16, + const RT& a20, const RT& a21, const RT& a22, const RT& a23, const RT& a24, const RT& a25, const RT& a26, + const RT& a30, const RT& a31, const RT& a32, const RT& a33, const RT& a34, const RT& a35, const RT& a36, + const RT& a40, const RT& a41, const RT& a42, const RT& a43, const RT& a44, const RT& a45, const RT& a46, + const RT& a50, const RT& a51, const RT& a52, const RT& a53, const RT& a54, const RT& a55, const RT& a56, + const RT& a60, const RT& a61, const RT& a62, const RT& a63, const RT& a64, const RT& a65, const RT& a66) +{ + const RT r1 = a06 * determinant( + a10, a11, a12, a13, a14, a15, + a20, a21, a22, a23, a24, a25, + a30, a31, a32, a33, a34, a35, + a40, a41, a42, a43, a44, a45, + a50, a51, a52, a53, a54, a55, + a60, a61, a62, a63, a64, a65); + + const RT r2 = - a16 * determinant(a00, a01, a02, a03, a04, a05, + + a20, a21, a22, a23, a24, a25, + a30, a31, a32, a33, a34, a35, + a40, a41, a42, a43, a44, a45, + a50, a51, a52, a53, a54, a55, + a60, a61, a62, a63, a64, a65); + + const RT r3 = a26 * determinant(a00, a01, a02, a03, a04, a05, + a10, a11, a12, a13, a14, a15, + + a30, a31, a32, a33, a34, a35, + a40, a41, a42, a43, a44, a45, + a50, a51, a52, a53, a54, a55, + a60, a61, a62, a63, a64, a65); + + const RT r4 = - a36 * determinant(a00, a01, a02, a03, a04, a05, + a10, a11, a12, a13, a14, a15, + a20, a21, a22, a23, a24, a25, + + a40, a41, a42, a43, a44, a45, + a50, a51, a52, a53, a54, a55, + a60, a61, a62, a63, a64, a65); + + const RT r5 = a46 * determinant(a00, a01, a02, a03, a04, a05, + a10, a11, a12, a13, a14, a15, + a20, a21, a22, a23, a24, a25, + a30, a31, a32, a33, a34, a35, + + a50, a51, a52, a53, a54, a55, + a60, a61, a62, a63, a64, a65); + + const RT r6 = - a56 * determinant(a00, a01, a02, a03, a04, a05, + a10, a11, a12, a13, a14, a15, + a20, a21, a22, a23, a24, a25, + a30, a31, a32, a33, a34, a35, + a40, a41, a42, a43, a44, a45, + + a60, a61, a62, a63, a64, a65); + + const RT r7 = a66 * determinant(a00, a01, a02, a03, a04, a05, + a10, a11, a12, a13, a14, a15, + a20, a21, a22, a23, a24, a25, + a30, a31, a32, a33, a34, a35, + a40, a41, a42, a43, a44, a45, + a50, a51, a52, a53, a54, a55 + + ); + + return r1 + r2 + r3 + r4 + r5 + r6 + r7; +} + +int main(int, char**) +{ + assert(determinant(4, 5, 1, 4, 6, 3, 1, + 4, 3, 6, 4, 2, 7, 3, + 6, 3, 3, 6, 2, 4, 5, + 1, 4, 3, 5, 5, 6 ,1, + 1, 3, 2, 7, 9, 6, 1, + 7, 6, 5, 4, 6, 2, 2, + 2, 3, 5, 7, 4, 3, 3) == 763); + + CGAL::Random rnd; + std::cout << "Seed: " << rnd.get_seed() << std::endl; + + for(int k=0; k<100; ++k) + { + std::array, 7> mat; + for(int i=0; i<7; ++i) + for(int j=0; j<7; ++j) + mat[i][j] = rnd.get_int(-18, 18); + + const int det_1 = determinant(mat[0][0], mat[0][1], mat[0][2], mat[0][3], mat[0][4], mat[0][5], mat[0][6], + mat[1][0], mat[1][1], mat[1][2], mat[1][3], mat[1][4], mat[1][5], mat[1][6], + mat[2][0], mat[2][1], mat[2][2], mat[2][3], mat[2][4], mat[2][5], mat[2][6], + mat[3][0], mat[3][1], mat[3][2], mat[3][3], mat[3][4], mat[3][5], mat[3][6], + mat[4][0], mat[4][1], mat[4][2], mat[4][3], mat[4][4], mat[4][5], mat[4][6], + mat[0][0], mat[5][1], mat[5][2], mat[5][3], mat[5][4], mat[5][5], mat[5][6], + mat[6][0], mat[6][1], mat[6][2], mat[6][3], mat[6][4], mat[6][5], mat[6][6]); + + const int det_2 = det_77_alt(mat[0][0], mat[0][1], mat[0][2], mat[0][3], mat[0][4], mat[0][5], mat[0][6], + mat[1][0], mat[1][1], mat[1][2], mat[1][3], mat[1][4], mat[1][5], mat[1][6], + mat[2][0], mat[2][1], mat[2][2], mat[2][3], mat[2][4], mat[2][5], mat[2][6], + mat[3][0], mat[3][1], mat[3][2], mat[3][3], mat[3][4], mat[3][5], mat[3][6], + mat[4][0], mat[4][1], mat[4][2], mat[4][3], mat[4][4], mat[4][5], mat[4][6], + mat[0][0], mat[5][1], mat[5][2], mat[5][3], mat[5][4], mat[5][5], mat[5][6], + mat[6][0], mat[6][1], mat[6][2], mat[6][3], mat[6][4], mat[6][5], mat[6][6]); + + std::cout << "dets: " << det_1 << " " << det_2 << std::endl; + assert(det_1 == det_2); + } + + std::cout << "Done!" << std::endl; + return EXIT_SUCCESS; +} From b2f8ef30d5418c6959492b06bedf2a330db42b5d Mon Sep 17 00:00:00 2001 From: Andreas Fabri Date: Fri, 27 Mar 2020 10:57:48 +0100 Subject: [PATCH 369/568] Add non-recursive determinant for 7x7 matrix --- Kernel_23/include/CGAL/determinant.h | 237 ++++++++++++++++++++------- 1 file changed, 179 insertions(+), 58 deletions(-) diff --git a/Kernel_23/include/CGAL/determinant.h b/Kernel_23/include/CGAL/determinant.h index 6ae01fe02d7..711a8ac0897 100644 --- a/Kernel_23/include/CGAL/determinant.h +++ b/Kernel_23/include/CGAL/determinant.h @@ -214,77 +214,198 @@ determinant( template RT determinant( - const RT& a00, const RT& a01, const RT& a02, const RT& a03, const RT& a04, - const RT& a05, const RT& a06, - const RT& a10, const RT& a11, const RT& a12, const RT& a13, const RT& a14, - const RT& a15, const RT& a16, - const RT& a20, const RT& a21, const RT& a22, const RT& a23, const RT& a24, - const RT& a25, const RT& a26, - const RT& a30, const RT& a31, const RT& a32, const RT& a33, const RT& a34, - const RT& a35, const RT& a36, - const RT& a40, const RT& a41, const RT& a42, const RT& a43, const RT& a44, - const RT& a45, const RT& a46, - const RT& a50, const RT& a51, const RT& a52, const RT& a53, const RT& a54, - const RT& a55, const RT& a56, - const RT& a60, const RT& a61, const RT& a62, const RT& a63, const RT& a64, - const RT& a65, const RT& a66) + const RT& a00, const RT& a01, const RT& a02, const RT& a03, const RT& a04, const RT& a05, const RT& a06, + const RT& a10, const RT& a11, const RT& a12, const RT& a13, const RT& a14, const RT& a15, const RT& a16, + const RT& a20, const RT& a21, const RT& a22, const RT& a23, const RT& a24, const RT& a25, const RT& a26, + const RT& a30, const RT& a31, const RT& a32, const RT& a33, const RT& a34, const RT& a35, const RT& a36, + const RT& a40, const RT& a41, const RT& a42, const RT& a43, const RT& a44, const RT& a45, const RT& a46, + const RT& a50, const RT& a51, const RT& a52, const RT& a53, const RT& a54, const RT& a55, const RT& a56, + const RT& a60, const RT& a61, const RT& a62, const RT& a63, const RT& a64, const RT& a65, const RT& a66) { - return a00 * determinant( - a11, a12, a13, a14, a15, a16, - a21, a22, a23, a24, a25, a26, - a31, a32, a33, a34, a35, a36, - a41, a42, a43, a44, a45, a46, - a51, a52, a53, a54, a55, a56, - a61, a62, a63, a64, a65, a66) +// First compute the det2x2 + const RT m01 = a00*a11 - a10*a01; + const RT m02 = a00*a21 - a20*a01; + const RT m03 = a00*a31 - a30*a01; + const RT m04 = a00*a41 - a40*a01; + const RT m05 = a00*a51 - a50*a01; + const RT m06 = a00*a61 - a60*a01; - - a10 * determinant(a01, a02, a03, a04, a05, a06, + const RT m12 = a10*a21 - a20*a11; + const RT m13 = a10*a31 - a30*a11; + const RT m14 = a10*a41 - a40*a11; + const RT m15 = a10*a51 - a50*a11; + const RT m16 = a10*a61 - a60*a11; - a21, a22, a23, a24, a25, a26, - a31, a32, a33, a34, a35, a36, - a41, a42, a43, a44, a45, a46, - a51, a52, a53, a54, a55, a56, - a61, a62, a63, a64, a65, a66) + const RT m23 = a20*a31 - a30*a21; + const RT m24 = a20*a41 - a40*a21; + const RT m25 = a20*a51 - a50*a21; + const RT m26 = a20*a61 - a60*a21; - + a20 * determinant(a01, a02, a03, a04, a05, a06, - a11, a12, a13, a14, a15, a16, + const RT m34 = a30*a41 - a40*a31; + const RT m35 = a30*a51 - a50*a31; + const RT m36 = a30*a61 - a60*a31; - a31, a32, a33, a34, a35, a36, - a41, a42, a43, a44, a45, a46, - a51, a52, a53, a54, a55, a56, - a61, a62, a63, a64, a65, a66) + const RT m45 = a40*a51 - a50*a41; + const RT m46 = a40*a61 - a60*a41; - - a30 * determinant(a01, a02, a03, a04, a05, a06, - a11, a12, a13, a14, a15, a16, - a21, a22, a23, a24, a25, a26, + const RT m56 = a50*a61 - a60*a51; - a41, a42, a43, a44, a45, a46, - a51, a52, a53, a54, a55, a56, - a61, a62, a63, a64, a65, a66) +// Now compute the minors of rank 3 + const RT m012 = m01*a22 - m02*a12 + m12*a02; + const RT m013 = m01*a32 - m03*a12 + m13*a02; + const RT m014 = m01*a42 - m04*a12 + m14*a02; + const RT m015 = m01*a52 - m05*a12 + m15*a02; + const RT m016 = m01*a62 - m06*a12 + m16*a02; - + a40 * determinant(a01, a02, a03, a04, a05, a06, - a11, a12, a13, a14, a15, a16, - a21, a22, a23, a24, a25, a26, - a31, a32, a33, a34, a35, a36, + const RT m023 = m02*a32 - m03*a22 + m23*a02; + const RT m024 = m02*a42 - m04*a22 + m24*a02; + const RT m025 = m02*a52 - m05*a22 + m25*a02; + const RT m026 = m02*a62 - m06*a22 + m26*a02; + const RT m034 = m03*a42 - m04*a32 + m34*a02; + const RT m035 = m03*a52 - m05*a32 + m35*a02; + const RT m036 = m03*a62 - m06*a32 + m36*a02; - a51, a52, a53, a54, a55, a56, - a61, a62, a63, a64, a65, a66) + const RT m045 = m04*a52 - m05*a42 + m45*a02; + const RT m046 = m04*a62 - m06*a42 + m46*a02; - - a50 * determinant(a01, a02, a03, a04, a05, a06, - a11, a12, a13, a14, a15, a16, - a21, a22, a23, a24, a25, a26, - a31, a32, a33, a34, a35, a36, - a41, a42, a43, a44, a45, a46, + const RT m056 = m05*a62 - m06*a52 + m56*a02; - a61, a62, a63, a64, a65, a66) - + a60 * determinant(a01, a02, a03, a04, a05, a06, - a11, a12, a13, a14, a15, a16, - a21, a22, a23, a24, a25, a26, - a31, a32, a33, a34, a35, a36, - a41, a42, a43, a44, a45, a46, - a51, a52, a53, a54, a55, a56 + const RT m123 = m12*a32 - m13*a22 + m23*a12; + const RT m124 = m12*a42 - m14*a22 + m24*a12; + const RT m125 = m12*a52 - m15*a22 + m25*a12; + const RT m126 = m12*a62 - m16*a22 + m26*a12; - ); + const RT m134 = m13*a42 - m14*a32 + m34*a12; + const RT m135 = m13*a52 - m15*a32 + m35*a12; + const RT m136 = m13*a62 - m16*a32 + m36*a12; + + const RT m145 = m14*a52 - m15*a42 + m45*a12; + const RT m146 = m14*a62 - m16*a42 + m46*a12; + + const RT m156 = m15*a62 - m16*a52 + m56*a12; + + const RT m234 = m23*a42 - m24*a32 + m34*a22; + const RT m235 = m23*a52 - m25*a32 + m35*a22; + const RT m236 = m23*a62 - m26*a32 + m36*a22; + + const RT m245 = m24*a52 - m25*a42 + m45*a22; + const RT m246 = m24*a62 - m26*a42 + m46*a22; + + const RT m256 = m25*a62 - m26*a52 + m56*a22; + + const RT m345 = m34*a52 - m35*a42 + m45*a32; + const RT m346 = m34*a62 - m36*a42 + m46*a32; + + const RT m356 = m35*a62 - m36*a52 + m56*a32; + + const RT m456 = m45*a62 - m46*a52 + m56*a42; + +// Now compute the minors of rank 4 + const RT m0123 = m012*a33 - m013*a23 + m023*a13 - m123*a03; + + const RT m0124 = m012*a43 - m014*a23 + m024*a13 - m124*a03; + const RT m0125 = m012*a53 - m015*a23 + m025*a13 - m125*a03; + const RT m0126 = m012*a63 - m016*a23 + m026*a13 - m126*a03; + + const RT m0134 = m013*a43 - m014*a33 + m034*a13 - m134*a03; + const RT m0135 = m013*a53 - m015*a33 + m035*a13 - m135*a03; + const RT m0136 = m013*a63 - m016*a33 + m036*a13 - m136*a03; + + const RT m0145 = m014*a53 - m015*a43 + m045*a13 - m145*a03; + const RT m0146 = m014*a63 - m016*a43 + m046*a13 - m146*a03; + + const RT m0156 = m015*a63 - m016*a53 + m056*a13 - m156*a03; + + const RT m0234 = m023*a43 - m024*a33 + m034*a23 - m234*a03; + const RT m0235 = m023*a53 - m025*a33 + m035*a23 - m235*a03; + const RT m0236 = m023*a63 - m026*a33 + m036*a23 - m236*a03; + + const RT m0245 = m024*a53 - m025*a43 + m045*a23 - m245*a03; + const RT m0246 = m024*a63 - m026*a43 + m046*a23 - m246*a03; + + const RT m0256 = m025*a63 - m026*a53 + m056*a23 - m256*a03; + + const RT m0345 = m034*a53 - m035*a43 + m045*a33 - m345*a03; + const RT m0346 = m034*a63 - m036*a43 + m046*a33 - m346*a03; + + const RT m0356 = m035*a63 - m036*a53 + m056*a33 - m356*a03; + + const RT m0456 = m045*a63 - m046*a53 + m056*a43 - m456*a03; + + const RT m1234 = m123*a43 - m124*a33 + m134*a23 - m234*a13; + const RT m1235 = m123*a53 - m125*a33 + m135*a23 - m235*a13; + const RT m1236 = m123*a63 - m126*a33 + m136*a23 - m236*a13; + + const RT m1245 = m124*a53 - m125*a43 + m145*a23 - m245*a13; + const RT m1246 = m124*a63 - m126*a43 + m146*a23 - m246*a13; + + const RT m1256 = m125*a63 - m126*a53 + m156*a23 - m256*a13; + + const RT m1345 = m134*a53 - m135*a43 + m145*a33 - m345*a13; + const RT m1346 = m134*a63 - m136*a43 + m146*a33 - m346*a13; + + const RT m1356 = m135*a63 - m136*a53 + m156*a33 - m356*a13; + const RT m1456 = m145*a63 - m146*a53 + m156*a43 - m456*a13; + + const RT m2345 = m234*a53 - m235*a43 + m245*a33 - m345*a23; + const RT m2346 = m234*a63 - m236*a43 + m246*a33 - m346*a23; + + const RT m2356 = m235*a63 - m236*a53 + m256*a33 - m356*a23; + const RT m2456 = m245*a63 - m246*a53 + m256*a43 - m456*a23; + + const RT m3456 = m345*a63 - m346*a53 + m356*a43 - m456*a33; + + + // Now compute the minors of rank 5 + const RT m01234 = m0123*a44 - m0124*a34 + m0134*a24 - m0234*a14 + m1234*a04; + + const RT m01235 = m0123*a54 - m0125*a34 + m0135*a24 - m0235*a14 + m1235*a04; + + const RT m01236 = m0123*a64 - m0126*a34 + m0136*a24 - m0236*a14 + m1236*a04; + + const RT m01245 = m0124*a54 - m0125*a44 + m0145*a24 - m0245*a14 + m1245*a04; + const RT m01246 = m0124*a64 - m0126*a44 + m0146*a24 - m0246*a14 + m1246*a04; + + const RT m01256 = m0125*a64 - m0126*a54 + m0156*a24 - m0256*a14 + m1256*a04; + + const RT m01345 = m0134*a54 - m0135*a44 + m0145*a34 - m0345*a14 + m1345*a04; + const RT m01346 = m0134*a64 - m0136*a44 + m0146*a34 - m0346*a14 + m1346*a04; + + const RT m01356 = m0135*a64 - m0136*a54 + m0156*a34 - m0356*a14 + m1356*a04; + const RT m01456 = m0145*a64 - m0146*a54 + m0156*a44 - m0456*a14 + m1456*a04; + + const RT m02345 = m0234*a54 - m0235*a44 + m0245*a34 - m0345*a24 + m2345*a04; + const RT m02346 = m0234*a64 - m0236*a44 + m0246*a34 - m0346*a24 + m2346*a04; + + const RT m02356 = m0235*a64 - m0236*a54 + m0256*a34 - m0356*a24 + m2356*a04; + const RT m02456 = m0245*a64 - m0246*a54 + m0256*a44 - m0456*a24 + m2456*a04; + const RT m03456 = m0345*a64 - m0346*a54 + m0356*a44 - m0456*a34 + m3456*a04; + + const RT m12345 = m1234*a54 - m1235*a44 + m1245*a34 - m1345*a24 + m2345*a14; + const RT m12346 = m1234*a64 - m1236*a44 + m1246*a34 - m1346*a24 + m2346*a14; + + + const RT m12356 = m1235*a64 - m1236*a54 + m1256*a34 - m1356*a24 + m2356*a14; + const RT m12456 = m1245*a64 - m1246*a54 + m1256*a44 - m1456*a24 + m2456*a14; + const RT m13456 = m1345*a64 - m1346*a54 + m1356*a44 - m1456*a34 + m3456*a14; + + const RT m23456 = m2345*a64 - m2346*a54 + m2356*a44 - m2456*a34 + m3456*a24; + +// Now compute the minors of rank 6 + const RT m012345 = m01234*a55 - m01235*a45 + m01245*a35 - m01345*a25 + m02345*a15 - m12345*a05; + const RT m012346 = m01234*a65 - m01236*a45 + m01246*a35 - m01346*a25 + m02346*a15 - m12346*a05; + const RT m012356 = m01235*a65 - m01236*a55 + m01256*a35 - m01356*a25 + m02356*a15 - m12356*a05; + const RT m012456 = m01245*a65 - m01246*a55 + m01256*a45 - m01456*a25 + m02456*a15 - m12456*a05; + const RT m013456 = m01345*a65 - m01346*a55 + m01356*a45 - m01456*a35 + m03456*a15 - m13456*a05; + const RT m023456 = m02345*a65 - m02346*a55 + m02356*a45 - m02456*a35 + m03456*a25 - m23456*a05; + const RT m123456 = m12345*a65 - m12346*a55 + m12356*a45 - m12456*a35 + m13456*a25 - m23456*a15; + + + // Now compute the minors of rank 7 + const RT m0123456 = m012345 * a66 - m012346 * a56 + m012356 * a46 - m012456 * a36 + m013456 * a26 - m023456 * a16 + m123456 * a06; + + return m0123456; } From 4e3f92ce5106b3c688438be174a9de6598df291d Mon Sep 17 00:00:00 2001 From: Marc Glisse Date: Wed, 8 Apr 2020 14:42:47 +0200 Subject: [PATCH 370/568] Remove outdated comment. --- NewKernel_d/include/CGAL/Epick_d.h | 2 -- 1 file changed, 2 deletions(-) diff --git a/NewKernel_d/include/CGAL/Epick_d.h b/NewKernel_d/include/CGAL/Epick_d.h index cc16803352b..a6b5dc88f1b 100644 --- a/NewKernel_d/include/CGAL/Epick_d.h +++ b/NewKernel_d/include/CGAL/Epick_d.h @@ -48,8 +48,6 @@ struct Epick_d_help1 CGAL_CONSTEXPR Epick_d_help1(int d):CGAL_BASE(d){} }; #undef CGAL_BASE -// determinant is only safe for use with integers with this condition, see LA_eigen/LA.h - #define CGAL_BASE \ Cartesian_filter_K< \ Epick_d_help1, \ From 556731d5be40e58aa27f430fbbd37c72336e03e5 Mon Sep 17 00:00:00 2001 From: Marc Glisse Date: Wed, 8 Apr 2020 18:43:28 +0200 Subject: [PATCH 371/568] Use members rather than private bases --- .../CGAL/NewKernel_d/Cartesian_filter_K.h | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/NewKernel_d/include/CGAL/NewKernel_d/Cartesian_filter_K.h b/NewKernel_d/include/CGAL/NewKernel_d/Cartesian_filter_K.h index 21b31e97691..1a94550d342 100644 --- a/NewKernel_d/include/CGAL/NewKernel_d/Cartesian_filter_K.h +++ b/NewKernel_d/include/CGAL/NewKernel_d/Cartesian_filter_K.h @@ -51,26 +51,26 @@ template<> struct Functors_without_division > { }; template < typename Base_, typename AK_, typename EK_, typename Pred_list = typeset_all > -struct Cartesian_filter_K : public Base_, - private Store_kernel +struct Cartesian_filter_K : public Base_ { - CGAL_CONSTEXPR Cartesian_filter_K(){} - CGAL_CONSTEXPR Cartesian_filter_K(int d):Base_(d){} + CGAL_NO_UNIQUE_ADDRESS Store_kernel sak; + CGAL_NO_UNIQUE_ADDRESS Store_kernel sek; //FIXME: or do we want an instance of AK and EK belonging to this kernel, //instead of a reference to external ones? - CGAL_CONSTEXPR Cartesian_filter_K(AK_ const&,EK_ const&b):Base_(),Store_kernel(b){} - CGAL_CONSTEXPR Cartesian_filter_K(int d,AK_ const&,EK_ const&b):Base_(d),Store_kernel(b){} + CGAL_CONSTEXPR Cartesian_filter_K(AK_ const&a,EK_ const&b):Base_(),sak(a),sek(b){} + CGAL_CONSTEXPR Cartesian_filter_K(int d,AK_ const&a,EK_ const&b):Base_(d),sak(a),sek(b){} typedef Base_ Kernel_base; typedef AK_ AK; typedef EK_ EK; - CGAL_static_assertion_msg(internal::Do_not_store_kernel::value, "Only handle stateless kernels as AK"); - AK approximate_kernel()const{return {};} + typedef typename Store_kernel::reference_type AK_rt; + AK_rt approximate_kernel()const{return sak.kernel();} typedef typename Store_kernel::reference_type EK_rt; - EK_rt exact_kernel()const{return this->Store_kernel::kernel();} + EK_rt exact_kernel()const{return sek.kernel();} // MSVC is too dumb to perform the empty base optimization. typedef boost::mpl::and_< internal::Do_not_store_kernel, + internal::Do_not_store_kernel, internal::Do_not_store_kernel > Do_not_store_kernel; //TODO: C2A/C2E could be able to convert *this into this->kernel() or this->kernel2(). From 0e1a871b0cc2bed3d3727c8605d6f62a96432b04 Mon Sep 17 00:00:00 2001 From: Marc Glisse Date: Thu, 9 Apr 2020 23:50:26 +0200 Subject: [PATCH 372/568] Add comments --- NewKernel_d/include/CGAL/NewKernel_d/Cartesian_filter_K.h | 4 ++++ NewKernel_d/include/CGAL/NewKernel_d/LA_eigen/LA.h | 3 +++ 2 files changed, 7 insertions(+) diff --git a/NewKernel_d/include/CGAL/NewKernel_d/Cartesian_filter_K.h b/NewKernel_d/include/CGAL/NewKernel_d/Cartesian_filter_K.h index 1a94550d342..1b2a80a2a69 100644 --- a/NewKernel_d/include/CGAL/NewKernel_d/Cartesian_filter_K.h +++ b/NewKernel_d/include/CGAL/NewKernel_d/Cartesian_filter_K.h @@ -50,6 +50,10 @@ template<> struct Functors_without_division > { typedef typeset type; }; +// FIXME: +// - Is_exact (which should be renamed to Uses_no_arithmetic) predicates should not be filtered +// - Functors_without_division should be defined near/in the actual functors + template < typename Base_, typename AK_, typename EK_, typename Pred_list = typeset_all > struct Cartesian_filter_K : public Base_ { diff --git a/NewKernel_d/include/CGAL/NewKernel_d/LA_eigen/LA.h b/NewKernel_d/include/CGAL/NewKernel_d/LA_eigen/LA.h index 758a6260f13..051bff5a942 100644 --- a/NewKernel_d/include/CGAL/NewKernel_d/LA_eigen/LA.h +++ b/NewKernel_d/include/CGAL/NewKernel_d/LA_eigen/LA.h @@ -122,6 +122,9 @@ template struct LA_eigen { return m.determinant(); } + // TODO: https://gitlab.com/libeigen/eigen/-/issues/1782 + // Implement a version of (sign_of_)determinant that works + // without (inexact) division in any dimension template static NT determinant(Mat_ const&m,bool=false){ switch(m.rows()){ //case 0: From 01d5e5f2b884613c4e85715b2bf22c1a7c47ab58 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mael=20Rouxel-Labb=C3=A9?= Date: Tue, 12 May 2020 12:53:59 +0200 Subject: [PATCH 373/568] Add CGAL_NO_UNIQUE_ADDRESS --- Installation/include/CGAL/config.h | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/Installation/include/CGAL/config.h b/Installation/include/CGAL/config.h index 80194819096..24a30f8a756 100644 --- a/Installation/include/CGAL/config.h +++ b/Installation/include/CGAL/config.h @@ -554,6 +554,12 @@ using std::max; # define CGAL_NORETURN #endif +// Macro to specify [[no_unique_address]] if supported +#if __has_cpp_attribute(no_unique_address) +# define CGAL_NO_UNIQUE_ADDRESS [[no_unique_address]] +#else +# define CGAL_NO_UNIQUE_ADDRESS +#endif // Macro CGAL_ASSUME // Call a builtin of the compiler to pass a hint to the compiler From bace047a5f226f4d7f83685b88027c88814e8b4c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mael=20Rouxel-Labb=C3=A9?= Date: Tue, 12 May 2020 12:58:30 +0200 Subject: [PATCH 374/568] Remove trailing whitespaces / tabs --- NewKernel_d/include/CGAL/NewKernel_d/LA_eigen/LA.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/NewKernel_d/include/CGAL/NewKernel_d/LA_eigen/LA.h b/NewKernel_d/include/CGAL/NewKernel_d/LA_eigen/LA.h index 051bff5a942..c8de1d39029 100644 --- a/NewKernel_d/include/CGAL/NewKernel_d/LA_eigen/LA.h +++ b/NewKernel_d/include/CGAL/NewKernel_d/LA_eigen/LA.h @@ -122,9 +122,9 @@ template struct LA_eigen { return m.determinant(); } - // TODO: https://gitlab.com/libeigen/eigen/-/issues/1782 - // Implement a version of (sign_of_)determinant that works - // without (inexact) division in any dimension + // TODO: https://gitlab.com/libeigen/eigen/-/issues/1782 + // Implement a version of (sign_of_)determinant that works + // without (inexact) division in any dimension template static NT determinant(Mat_ const&m,bool=false){ switch(m.rows()){ //case 0: From a0f9d58efeb62f3f1f394eabe7ebea1a632d822f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mael=20Rouxel-Labb=C3=A9?= Date: Tue, 12 May 2020 13:49:52 +0200 Subject: [PATCH 375/568] Fix bad conflict resolution that erased some constructors --- NewKernel_d/include/CGAL/NewKernel_d/Cartesian_filter_K.h | 3 +++ 1 file changed, 3 insertions(+) diff --git a/NewKernel_d/include/CGAL/NewKernel_d/Cartesian_filter_K.h b/NewKernel_d/include/CGAL/NewKernel_d/Cartesian_filter_K.h index 1b2a80a2a69..ed0aeeb7af5 100644 --- a/NewKernel_d/include/CGAL/NewKernel_d/Cartesian_filter_K.h +++ b/NewKernel_d/include/CGAL/NewKernel_d/Cartesian_filter_K.h @@ -59,6 +59,9 @@ struct Cartesian_filter_K : public Base_ { CGAL_NO_UNIQUE_ADDRESS Store_kernel sak; CGAL_NO_UNIQUE_ADDRESS Store_kernel sek; + + constexpr Cartesian_filter_K(){} + constexpr Cartesian_filter_K(int d):Base_(d){} //FIXME: or do we want an instance of AK and EK belonging to this kernel, //instead of a reference to external ones? CGAL_CONSTEXPR Cartesian_filter_K(AK_ const&a,EK_ const&b):Base_(),sak(a),sek(b){} From 916d09f45112fcd9bd423fdff83708efa70a7fbf Mon Sep 17 00:00:00 2001 From: Jane Tournois Date: Wed, 13 May 2020 07:47:07 +0200 Subject: [PATCH 376/568] prevent surface from self-folding during collapse collapse_preserves_surface_star() checks that normals to the surface do not get inverted and the surface stars do not "fold" on themselves --- .../internal/collapse_short_edges.h | 152 +++++++++++++++++- 1 file changed, 148 insertions(+), 4 deletions(-) diff --git a/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/collapse_short_edges.h b/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/collapse_short_edges.h index 8d2cd651a62..4183bb3cb88 100644 --- a/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/collapse_short_edges.h +++ b/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/collapse_short_edges.h @@ -568,6 +568,151 @@ bool is_valid_collapse(const typename C3t3::Edge& edge, return is_valid_collapse(edge, c3t3); } +template +bool facet_has_edge(const Facet& f, const Vh v0, const Vh v1) +{ + std::array, 3> edges = {{ {{1,2}}, {{2,3}}, {{3,1}} }}; + + for (int i = 0; i < 3; ++i) + { + const std::array& ei = edges[i]; + if ( f.first->vertex((f.second + ei[0]) % 4) == v0 + && f.first->vertex((f.second + ei[1]) % 4) == v1) + return true; + if ( f.first->vertex((f.second + ei[0]) % 4) == v1 + && f.first->vertex((f.second + ei[1]) % 4) == v0) + return true; + } + return false; +} + +template +bool collapse_preserves_surface_star(const typename C3t3::Edge& edge, + const C3t3& c3t3, + const typename C3t3::Triangulation::Point& new_pos, + const CellSelector& cell_selector) +{ + typedef typename C3t3::Triangulation Tr; + typedef typename C3t3::Vertex_handle Vertex_handle; + typedef typename C3t3::Facet Facet; + typedef typename Tr::Geom_traits::Vector_3 Vector_3; + typedef typename Tr::Geom_traits::Point_3 Point_3; + + const Tr& tr = c3t3.triangulation(); + + const Vertex_handle v0 = edge.first->vertex(edge.second); + const Vertex_handle v1 = edge.first->vertex(edge.third); + if (c3t3.in_dimension(v0) != 2 || c3t3.in_dimension(v1) != 2) + return true;//other cases should not be treated here + + typename Tr::Geom_traits gt = c3t3.triangulation().geom_traits(); + typename Tr::Geom_traits::Construct_opposite_vector_3 + opp = gt.construct_opposite_vector_3_object(); + typename Tr::Geom_traits::Compute_scalar_product_3 + product = gt.compute_scalar_product_3_object(); + typename Tr::Geom_traits::Construct_normal_3 + normal = gt.construct_normal_3_object(); + + boost::unordered_set facets; + tr.finite_incident_facets(v0, std::inserter(facets, facets.end())); + tr.finite_incident_facets(v1, std::inserter(facets, facets.end())); + +// note : checking a 2nd ring of facets does not change the result +// boost::unordered_set ring2; +// for (const Facet& f : facets) +// { +// for (int i = 1; i < 4; ++i) +// { +// Vertex_handle vi = f.first->vertex((f.second + i) % 4); +// tr.finite_incident_facets(vi, std::inserter(ring2, ring2.end())); +// } +// } +// facets.insert(ring2.begin(), ring2.end()); + + Vector_3 reference_normal = CGAL::NULL_VECTOR; + //Point_3 reference_c; + for (const Facet& f : facets) + { + if (!is_boundary(c3t3, f, cell_selector)) + continue; + if (facet_has_edge(f, v0, v1)) + continue; //this facet will collapse if collapse happens + + std::array pts = {{ point(f.first->vertex((f.second + 1) % 4)->point()), + point(f.first->vertex((f.second + 2) % 4)->point()), + point(f.first->vertex((f.second + 3) % 4)->point()) }}; + if(f.second % 2 == 0) + std::swap(pts[0], pts[1]); + + Vector_3 n_before_collapse = normal(pts[0], pts[1], pts[2]); + + const Facet& mf = tr.mirror_facet(f); + bool do_opp = false; + if ( c3t3.triangulation().is_infinite(mf.first) + || c3t3.subdomain_index(mf.first) < c3t3.subdomain_index(f.first)) + { + n_before_collapse = opp(n_before_collapse); + do_opp = true; + } + + if (reference_normal == CGAL::NULL_VECTOR) + { + //reference_c = CGAL::centroid(pts[0], pts[1], pts[2]); + reference_normal = n_before_collapse; + } + + // check after move + for (int i = 0; i < 3; ++i) + { + const Vertex_handle vi = f.first->vertex((f.second + i + 1) % 4); + if (vi == v0 || vi == v1) + { + if (f.second % 2 == 0) + { + if(i == 0) pts[1] = point(new_pos); + else if(i == 1) pts[0] = point(new_pos); + else pts[2] = point(new_pos); + } + else + pts[i] = point(new_pos); + break; + } + } + + Vector_3 n_after_collapse = normal(pts[0], pts[1], pts[2]); + if(do_opp) + n_after_collapse = opp(n_after_collapse); + + const double dotref = product(reference_normal, n_after_collapse); + if(dotref < 0) + return false; + const double dot = product(n_before_collapse, n_after_collapse); + if(dot < 0) + return false; + +// if (dot * dotref < 0) +// { +// std::cout << "collapse edge : " << std::endl; +// std::cout << point(v0->point()) << " " << point(v1->point()) << std::endl; +// std::cout << "facet : " << std::endl; +// std::cout << pts[0] << " " << pts[1] << " " << pts[2] << std::endl; +// +// Point_3 c = CGAL::centroid(pts[0], pts[1], pts[2]); +// std::cout << "n_before_collapse "; +// std::cout << c << " " << (c + n_before_collapse) << std::endl; +// std::cout << "n_after_collapse "; +// std::cout << c << " " << (c + n_after_collapse) << std::endl; +// std::cout << "reference_normal "; +// std::cout << reference_c << " " << (reference_c + reference_normal) << std::endl; +// std::cout << std::endl; +// } +// if (dotref < 0 || dot < 0) +// return false; + } + + return true; +} + template bool are_edge_lengths_valid(const typename C3t3::Edge& edge, const C3t3& c3t3, @@ -965,7 +1110,8 @@ typename C3t3::Vertex_handle collapse_edge(typename C3t3::Edge& edge, } } - if (are_edge_lengths_valid(edge, c3t3, new_pos, sqhigh, cell_selector/*, adaptive = false*/)) + if (are_edge_lengths_valid(edge, c3t3, new_pos, sqhigh, cell_selector/*, adaptive = false*/) + && collapse_preserves_surface_star(edge, c3t3, new_pos, cell_selector)) { CGAL_assertion_code(typename Tr::Cell_handle dc); CGAL_assertion_code(int di); @@ -1063,10 +1209,8 @@ void collapse_short_edges(C3T3& c3t3, //collect long edges Boost_bimap short_edges; - for (Finite_edges_iterator eit = tr.finite_edges_begin(); - eit != tr.finite_edges_end(); ++eit) + for (const Edge& e : tr.finite_edges()) { - const Edge& e = *eit; if (!can_be_collapsed(e, c3t3, protect_boundaries, cell_selector)) continue; From 84fe1d2af083c073274c67f73ccc982922ae197f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9bastien=20Loriot?= Date: Wed, 13 May 2020 09:16:50 +0200 Subject: [PATCH 377/568] hide verbose/debug code --- .../repair_self_intersections.h | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/repair_self_intersections.h b/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/repair_self_intersections.h index b67ac5dc5d6..def4359d132 100644 --- a/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/repair_self_intersections.h +++ b/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/repair_self_intersections.h @@ -1161,8 +1161,9 @@ bool fill_hole_with_constraints(std::vector(patch)) { +#ifdef CGAL_PMP_REMOVE_SELF_INTERSECTION_DEBUG std::cout << "Unhealthy patch, use base fill_hole" << std::endl; +#endif return fill_hole(cc_border_hedges, cc_faces, working_face_range, tmesh, vpm, gt); } @@ -1796,9 +1799,9 @@ bool remove_self_intersections(const FaceRange& face_range, // TODO : possible optimization to reduce the range to check with the bbox // of the previous patches or something. self_intersections(working_face_range, tmesh, std::back_inserter(self_inter)); - +#ifdef CGAL_PMP_REMOVE_SELF_INTERSECTION_DEBUG std::cout << self_inter.size() << " intersecting pairs" << std::endl; - +#endif for(const Face_pair& fp : self_inter) { faces_to_remove.insert(fp.first); From cab06077f182fc9726ea02d6709735f50f4ad94e Mon Sep 17 00:00:00 2001 From: Simon Giraudot Date: Wed, 13 May 2020 16:12:43 +0200 Subject: [PATCH 378/568] Fix warnings --- .../Plugins/Point_set/Point_set_clustering_plugin.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Polyhedron/demo/Polyhedron/Plugins/Point_set/Point_set_clustering_plugin.cpp b/Polyhedron/demo/Polyhedron/Plugins/Point_set/Point_set_clustering_plugin.cpp index c68a2ab3c07..951ca806115 100644 --- a/Polyhedron/demo/Polyhedron/Plugins/Point_set/Point_set_clustering_plugin.cpp +++ b/Polyhedron/demo/Polyhedron/Plugins/Point_set/Point_set_clustering_plugin.cpp @@ -142,7 +142,7 @@ void Polyhedron_demo_point_set_clustering_plugin::on_actionCluster_triggered() std::size_t nb_clusters = *functor.result; - Scene_group_item* group; + Scene_group_item* group = nullptr; std::vector new_items; if (gen_sub->isChecked()) @@ -154,7 +154,7 @@ void Polyhedron_demo_point_set_clustering_plugin::on_actionCluster_triggered() { Scene_points_with_normal_item* new_item = new Scene_points_with_normal_item; new_item->point_set()->copy_properties (*points); - CGAL::Random rand(i); + CGAL::Random rand((unsigned int)(i)); unsigned char r, g, b; r = static_cast(64 + rand.get_int(0, 192)); g = static_cast(64 + rand.get_int(0, 192)); @@ -193,7 +193,7 @@ void Polyhedron_demo_point_set_clustering_plugin::on_actionCluster_triggered() Point_set::Index iidx = *(colored->point_set()->insert (points->point(idx))); if (cluster_size[cluster_map[idx]] >= std::size_t(min_nb->value())) { - CGAL::Random rand(cluster_map[idx] + 1); + CGAL::Random rand((unsigned int)(cluster_map[idx] + 1)); unsigned char r, g, b; r = static_cast(64 + rand.get_int(0, 192)); g = static_cast(64 + rand.get_int(0, 192)); From bd48aed9b864ca07cbf0223e652122640a26a80e Mon Sep 17 00:00:00 2001 From: Mael Date: Wed, 13 May 2020 17:59:22 +0200 Subject: [PATCH 379/568] Use the traits class to construct points --- .../Optimal_bounding_box/oriented_bounding_box.h | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/oriented_bounding_box.h b/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/oriented_bounding_box.h index 07c42a9b4b2..4cfe1770c1b 100644 --- a/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/oriented_bounding_box.h +++ b/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/oriented_bounding_box.h @@ -88,15 +88,15 @@ void construct_oriented_bounding_box(const PointRange& points, zmax = (std::max)(rot_pt.z(), zmax); } - obb_points[0] = Point(xmin, ymin, zmin); - obb_points[1] = Point(xmax, ymin, zmin); - obb_points[2] = Point(xmax, ymax, zmin); - obb_points[3] = Point(xmin, ymax, zmin); + obb_points[0] = traits.construct_point_3_object()(xmin, ymin, zmin); + obb_points[1] = traits.construct_point_3_object()(xmax, ymin, zmin); + obb_points[2] = traits.construct_point_3_object()(xmax, ymax, zmin); + obb_points[3] = traits.construct_point_3_object()(xmin, ymax, zmin); - obb_points[4] = Point(xmin, ymax, zmax); // see order in make_hexahedron()... - obb_points[5] = Point(xmin, ymin, zmax); - obb_points[6] = Point(xmax, ymin, zmax); - obb_points[7] = Point(xmax, ymax, zmax); + obb_points[4] = traits.construct_point_3_object()(xmin, ymax, zmax); // see order in make_hexahedron()... + obb_points[5] = traits.construct_point_3_object()(xmin, ymin, zmax); + obb_points[6] = traits.construct_point_3_object()(xmax, ymin, zmax); + obb_points[7] = traits.construct_point_3_object()(xmax, ymax, zmax); // Apply the inverse rotation to the rotated axis aligned bounding box for(std::size_t i=0; i<8; ++i) From 41d1898abfc92c229ebe2bafae154fee5fdffb7a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9bastien=20Loriot?= Date: Wed, 13 May 2020 18:45:18 +0200 Subject: [PATCH 380/568] fix warning --- .../CGAL/Tetrahedral_remeshing/internal/collapse_short_edges.h | 1 - 1 file changed, 1 deletion(-) diff --git a/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/collapse_short_edges.h b/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/collapse_short_edges.h index 4183bb3cb88..4e163f07372 100644 --- a/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/collapse_short_edges.h +++ b/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/collapse_short_edges.h @@ -1184,7 +1184,6 @@ void collapse_short_edges(C3T3& c3t3, typedef typename C3T3::Triangulation T3; typedef typename T3::Cell_handle Cell_handle; typedef typename T3::Edge Edge; - typedef typename T3::Finite_edges_iterator Finite_edges_iterator; typedef typename T3::Vertex_handle Vertex_handle; typedef typename std::pair Edge_vv; From 7d64c59b860d73d4cb8a74f038e979cc17309060 Mon Sep 17 00:00:00 2001 From: Laurent Rineau Date: Wed, 13 May 2020 21:15:34 +0200 Subject: [PATCH 381/568] Fix the lack of LABEL for test_find_package_version_* --- Installation/test/Installation/CMakeLists.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/Installation/test/Installation/CMakeLists.txt b/Installation/test/Installation/CMakeLists.txt index 64aa39edf93..e4aacdf867c 100644 --- a/Installation/test/Installation/CMakeLists.txt +++ b/Installation/test/Installation/CMakeLists.txt @@ -125,6 +125,7 @@ function(CGAL_installation_test_find_package_version mode) configure_file(test_find_package.cmake.in ${CMAKE_CURRENT_BINARY_DIR}/test_find_package_version_${mode}/CMakeLists.txt) add_test(NAME test_find_package_version_${mode} COMMAND ${CMAKE_COMMAND} -S ${CMAKE_CURRENT_BINARY_DIR}/test_find_package_version_${mode} -B ${CMAKE_CURRENT_BINARY_DIR}/build-test_find_package_version_${mode}) + cgal_setup_test_properties(test_find_package_version_${mode}) endfunction() CGAL_installation_test_find_package_version(less) From d30dfacf5fefa4ff2dc8552be77f0adc3e4232d5 Mon Sep 17 00:00:00 2001 From: Laurent Rineau Date: Wed, 13 May 2020 21:15:55 +0200 Subject: [PATCH 382/568] Fix the testsuite of test/Installation/ with CTest --- Installation/CMakeLists.txt | 2 ++ .../modules/CGALConfigVersion_binary_header_only.cmake.in | 5 +++++ Installation/cmake/modules/CGAL_add_test.cmake | 4 +--- 3 files changed, 8 insertions(+), 3 deletions(-) create mode 100644 Installation/cmake/modules/CGALConfigVersion_binary_header_only.cmake.in diff --git a/Installation/CMakeLists.txt b/Installation/CMakeLists.txt index 1b396f94a9a..161b8b394ad 100644 --- a/Installation/CMakeLists.txt +++ b/Installation/CMakeLists.txt @@ -871,6 +871,8 @@ if(NOT CGAL_HEADER_ONLY) else() configure_file("${CGAL_MODULES_DIR}/CGALConfig_binary_header_only.cmake.in" "${CMAKE_BINARY_DIR}/CGALConfig.cmake" @ONLY) + configure_file("${CGAL_MODULES_DIR}/CGALConfigVersion_binary_header_only.cmake.in" + "${CMAKE_BINARY_DIR}/CGALConfigVersion.cmake" @ONLY) endif() #-------------------------------------------------------------------------------------------------- diff --git a/Installation/cmake/modules/CGALConfigVersion_binary_header_only.cmake.in b/Installation/cmake/modules/CGALConfigVersion_binary_header_only.cmake.in new file mode 100644 index 00000000000..9b30fbcad5f --- /dev/null +++ b/Installation/cmake/modules/CGALConfigVersion_binary_header_only.cmake.in @@ -0,0 +1,5 @@ +# +# This file points to the CGALConfigVersion.cmake for header-only CGAL. +# + +include(@CGAL_INSTALLATION_PACKAGE_DIR@/lib/cmake/CGAL/CGALConfigVersion.cmake) diff --git a/Installation/cmake/modules/CGAL_add_test.cmake b/Installation/cmake/modules/CGAL_add_test.cmake index a2c565aeb9b..eb80d4b4695 100644 --- a/Installation/cmake/modules/CGAL_add_test.cmake +++ b/Installation/cmake/modules/CGAL_add_test.cmake @@ -104,12 +104,10 @@ function(cgal_add_compilation_test exe_name) if(NOT TARGET cgal_check_build_system) add_custom_target(cgal_check_build_system) add_dependencies( ALL_CGAL_TARGETS cgal_check_build_system ) - endif() - if(NOT TEST check_build_system) add_test(NAME "check_build_system" COMMAND "${CMAKE_COMMAND}" --build "${CMAKE_BINARY_DIR}" --target "cgal_check_build_system" --config "$") set_property(TEST "check_build_system" - APPEND PROPERTY LABELS "Installation") + APPEND PROPERTY LABELS "${PROJECT_NAME}") if(POLICY CMP0066) # cmake 3.7 or later set_property(TEST "check_build_system" PROPERTY FIXTURES_SETUP "check_build_system_SetupFixture") From f12f6f5f0808e74831cb234c06a71bcf593e9b7e Mon Sep 17 00:00:00 2001 From: Laurent Rineau Date: Wed, 13 May 2020 21:22:07 +0200 Subject: [PATCH 383/568] Fix #4720 --- Installation/cmake/modules/CGAL_Macros.cmake | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Installation/cmake/modules/CGAL_Macros.cmake b/Installation/cmake/modules/CGAL_Macros.cmake index 23049fbb26e..f035184b1e8 100644 --- a/Installation/cmake/modules/CGAL_Macros.cmake +++ b/Installation/cmake/modules/CGAL_Macros.cmake @@ -404,7 +404,7 @@ if( NOT CGAL_MACROS_FILE_INCLUDED ) # CGALConfig.cmake is platform specific so it is generated and stored in the binary folder. configure_file("${CGAL_MODULES_DIR}/CGALConfig_binary.cmake.in" "${CMAKE_BINARY_DIR}/CGALConfig.cmake" @ONLY) write_basic_package_version_file("${CMAKE_BINARY_DIR}/CGALConfigVersion.cmake" - VERSION "${CGAL_MAJOR_VERSION}.${CGAL_MINOR_VERSION}.${CGAL_BUILD_VERSION}" + VERSION "${CGAL_MAJOR_VERSION}.${CGAL_MINOR_VERSION}.${CGAL_BUGFIX_VERSION}" COMPATIBILITY SameMajorVersion) # There is also a version of CGALConfig.cmake that is prepared in case CGAL in installed in CMAKE_INSTALL_PREFIX. From c9fab91c9ad818c53554b21cec98088dfdd30dfa Mon Sep 17 00:00:00 2001 From: Jane Tournois Date: Thu, 14 May 2020 08:45:48 +0200 Subject: [PATCH 384/568] fix conversion warnings and constify what should be --- .../tetrahedral_remeshing_example.cpp | 2 +- ...tetrahedral_remeshing_of_one_subdomain.cpp | 2 +- .../Tetrahedral_remeshing/internal/FMLS.h | 54 ++++++++++--------- .../internal/smooth_vertices.h | 4 +- ...tetrahedral_remeshing_of_one_subdomain.cpp | 2 +- ...st_tetrahedral_remeshing_with_features.cpp | 4 +- 6 files changed, 37 insertions(+), 31 deletions(-) diff --git a/Tetrahedral_remeshing/examples/Tetrahedral_remeshing/tetrahedral_remeshing_example.cpp b/Tetrahedral_remeshing/examples/Tetrahedral_remeshing/tetrahedral_remeshing_example.cpp index 529ea62187e..5cad680f8be 100644 --- a/Tetrahedral_remeshing/examples/Tetrahedral_remeshing/tetrahedral_remeshing_example.cpp +++ b/Tetrahedral_remeshing/examples/Tetrahedral_remeshing/tetrahedral_remeshing_example.cpp @@ -19,7 +19,7 @@ typedef CGAL::Tetrahedral_remeshing::Remeshing_triangulation_3 Remeshing_tria int main(int argc, char* argv[]) { const char* filename = (argc > 1) ? argv[1] : "data/triangulation_one_subdomain.binary.cgal"; - const float target_edge_length = (argc > 2) ? atof(argv[2]) : 0.1f; + const double target_edge_length = (argc > 2) ? atof(argv[2]) : 0.1f; std::ifstream input(filename, std::ios::in | std::ios::binary); diff --git a/Tetrahedral_remeshing/examples/Tetrahedral_remeshing/tetrahedral_remeshing_of_one_subdomain.cpp b/Tetrahedral_remeshing/examples/Tetrahedral_remeshing/tetrahedral_remeshing_of_one_subdomain.cpp index 5519e754235..a98f9f84a92 100644 --- a/Tetrahedral_remeshing/examples/Tetrahedral_remeshing/tetrahedral_remeshing_of_one_subdomain.cpp +++ b/Tetrahedral_remeshing/examples/Tetrahedral_remeshing/tetrahedral_remeshing_of_one_subdomain.cpp @@ -31,7 +31,7 @@ public: int main(int argc, char* argv[]) { const char* filename = (argc > 1) ? argv[1] : "data/triangulation_two_subdomains.binary.cgal"; - const float target_edge_length = (argc > 2) ? atof(argv[2]) : 0.1f; + const double target_edge_length = (argc > 2) ? atof(argv[2]) : 0.1; std::ifstream input(filename, std::ios_base::in | std::ios_base::binary); if(!input) diff --git a/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/FMLS.h b/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/FMLS.h index 0573a0f0d68..8f3d157a7b3 100644 --- a/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/FMLS.h +++ b/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/FMLS.h @@ -173,27 +173,31 @@ public: double sigma_s = PNScale * MLSRadius; double sigma_r = bilateralRange; - Vector_3 g = (p - Vector_3(grid.getMinMax()[0], grid.getMinMax()[1], grid.getMinMax()[2])) / sigma_s; - std::array gxyz = { g.x(), g.y(), g.z() }; + const Vector_3 g = (p - Vector_3(grid.getMinMax()[0], grid.getMinMax()[1], grid.getMinMax()[2])) / sigma_s; - for (std::size_t j = 0; j < 3; j++) { - gxyz[j] = floor(gxyz[j]); - if (gxyz[j] < 0.f) - gxyz[j] = 0.f; - if (gxyz[j] >= grid.getRes()[j]) + std::array gxyz; + for (int j = 0; j < 3; ++j) + { + if (g[j] < 0.) + gxyz[j] = 0; + if (g[j] >= grid.getRes()[j]) gxyz[j] = grid.getRes()[j] - 1; + else + gxyz[j] = static_cast(std::floor(g[j])); } + std::array minIt; std::array maxIt; - for (std::size_t j = 0; j < 3; j++) { - if (((unsigned int)gxyz[j]) == 0) + for (std::size_t j = 0; j < 3; ++j) + { + if (gxyz[j] == 0) minIt[j] = 0; else - minIt[j] = ((unsigned int)gxyz[j]) - 1; - if (((unsigned int)gxyz[j]) == (grid.getRes()[j] - 1)) + minIt[j] = gxyz[j] - 1; + if (gxyz[j] == grid.getRes()[j] - 1) maxIt[j] = (grid.getRes()[j] - 1); else - maxIt[j] = ((unsigned int)gxyz[j]) + 1; + maxIt[j] = gxyz[j] + 1; } Vector_3 c = CGAL::NULL_VECTOR; double sumW = 0.f; @@ -332,8 +336,8 @@ private: Vector_3 c = CGAL::NULL_VECTOR; for (std::size_t i = 0; i < PNSize; i++) c += Vector_3(PN[6 * i], PN[6 * i + 1], PN[6 * i + 2]); - c /= PNSize; - PNScale = 0.f; + c /= (double)PNSize; + PNScale = 0.; for (std::size_t i = 0; i < PNSize; i++) { double r = distance(c, Vector_3(PN[6 * i], PN[6 * i + 1], PN[6 * i + 2])); if (r > PNScale) @@ -453,18 +457,20 @@ private: } std::size_t getLUTIndex(const Vector_3& x) const { - Vector_3 vp = (x - Vector_3(minMax[0], minMax[1], minMax[2])) / cellSize; - std::array p = { vp.x(), vp.y(), vp.z() }; - for (std::size_t j = 0; j < 3; j++) { - p[j] = floor(p[j]); - if (p[j] < 0) - p[j] = 0.f; - if (p[j] >= res[j]) + const Vector_3 vp = (x - Vector_3(minMax[0], minMax[1], minMax[2])) / cellSize; + std::array p; + for (int j = 0; j < 3; j++) + { + if (vp[j] < 0) + p[j] = 0.; + if (vp[j] >= res[j]) p[j] = res[j] - 1; + else + p[j] = static_cast(std::floor(vp[j])); } - std::size_t index = ((std::size_t)floor(p[2])) * res[0] * res[1] - + ((std::size_t)floor(p[1])) * res[0] - + ((std::size_t)floor(p[0])); + std::size_t index = p[2] * res[0] * res[1] + + p[1] * res[0] + + p[0]; return index; } inline std::size_t getLUTElement(const Vector_3& x) const { diff --git a/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/smooth_vertices.h b/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/smooth_vertices.h index 3c85c72324f..660fb3507d4 100644 --- a/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/smooth_vertices.h +++ b/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/smooth_vertices.h @@ -299,8 +299,8 @@ private: int it_nb = 0; const int max_it_nb = 5; - const float epsilon = fmls.getPNScale() / 1000.f; - const float sq_eps = CGAL::square(epsilon); + const double epsilon = fmls.getPNScale() / 1000.; + const double sq_eps = CGAL::square(epsilon); do { diff --git a/Tetrahedral_remeshing/test/Tetrahedral_remeshing/test_tetrahedral_remeshing_of_one_subdomain.cpp b/Tetrahedral_remeshing/test/Tetrahedral_remeshing/test_tetrahedral_remeshing_of_one_subdomain.cpp index 1ba6b126bb1..6133e647b0e 100644 --- a/Tetrahedral_remeshing/test/Tetrahedral_remeshing/test_tetrahedral_remeshing_of_one_subdomain.cpp +++ b/Tetrahedral_remeshing/test/Tetrahedral_remeshing/test_tetrahedral_remeshing_of_one_subdomain.cpp @@ -68,7 +68,7 @@ int main(int argc, char* argv[]) std::cout << "CGAL Random seed = " << CGAL::get_default_random().get_seed() << std::endl; - const float target_edge_length = (argc > 1) ? atof(argv[1]) : 0.1f; + const double target_edge_length = (argc > 1) ? atof(argv[1]) : 0.1; Remeshing_triangulation tr; generate_input_two_subdomains(1000, tr); diff --git a/Tetrahedral_remeshing/test/Tetrahedral_remeshing/test_tetrahedral_remeshing_with_features.cpp b/Tetrahedral_remeshing/test/Tetrahedral_remeshing/test_tetrahedral_remeshing_with_features.cpp index 45fd962b677..528b1a33285 100644 --- a/Tetrahedral_remeshing/test/Tetrahedral_remeshing/test_tetrahedral_remeshing_with_features.cpp +++ b/Tetrahedral_remeshing/test/Tetrahedral_remeshing/test_tetrahedral_remeshing_with_features.cpp @@ -145,8 +145,8 @@ int main(int argc, char* argv[]) boost::unordered_set > constraints; generate_input_cube(1000, tr, constraints); - double target_edge_length = (argc > 1) ? atof(argv[1]) : 0.02; - int nb_iter = (argc > 2) ? atoi(argv[2]) : 1; + const double target_edge_length = (argc > 1) ? atof(argv[1]) : 0.02; + const int nb_iter = (argc > 2) ? atoi(argv[2]) : 1; set_subdomain(tr, 1); assert(tr.is_valid()); From 0e7cf9da7076f343b85db45cf7ac390f7e27ecec Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mael=20Rouxel-Labb=C3=A9?= Date: Thu, 14 May 2020 09:42:40 +0200 Subject: [PATCH 385/568] Factorize functor construction --- .../oriented_bounding_box.h | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) diff --git a/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/oriented_bounding_box.h b/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/oriented_bounding_box.h index 4cfe1770c1b..6253c629fe4 100644 --- a/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/oriented_bounding_box.h +++ b/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/oriented_bounding_box.h @@ -88,15 +88,17 @@ void construct_oriented_bounding_box(const PointRange& points, zmax = (std::max)(rot_pt.z(), zmax); } - obb_points[0] = traits.construct_point_3_object()(xmin, ymin, zmin); - obb_points[1] = traits.construct_point_3_object()(xmax, ymin, zmin); - obb_points[2] = traits.construct_point_3_object()(xmax, ymax, zmin); - obb_points[3] = traits.construct_point_3_object()(xmin, ymax, zmin); + const typename Traits::Construct_point_3 cp = traits.construct_point_3_object(); - obb_points[4] = traits.construct_point_3_object()(xmin, ymax, zmax); // see order in make_hexahedron()... - obb_points[5] = traits.construct_point_3_object()(xmin, ymin, zmax); - obb_points[6] = traits.construct_point_3_object()(xmax, ymin, zmax); - obb_points[7] = traits.construct_point_3_object()(xmax, ymax, zmax); + obb_points[0] = cp(xmin, ymin, zmin); + obb_points[1] = cp(xmax, ymin, zmin); + obb_points[2] = cp(xmax, ymax, zmin); + obb_points[3] = cp(xmin, ymax, zmin); + + obb_points[4] = cp(xmin, ymax, zmax); // see order in make_hexahedron()... + obb_points[5] = cp(xmin, ymin, zmax); + obb_points[6] = cp(xmax, ymin, zmax); + obb_points[7] = cp(xmax, ymax, zmax); // Apply the inverse rotation to the rotated axis aligned bounding box for(std::size_t i=0; i<8; ++i) From f7dee23b5d798ad890e90b740bdc224359ce646d Mon Sep 17 00:00:00 2001 From: Mael Date: Thu, 14 May 2020 09:54:08 +0200 Subject: [PATCH 386/568] Remove erroneous 'const' The concept `Kernel::ConstructPoint_3::operator()` is not required to be const. --- .../include/CGAL/Optimal_bounding_box/oriented_bounding_box.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/oriented_bounding_box.h b/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/oriented_bounding_box.h index 6253c629fe4..cea95a73c30 100644 --- a/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/oriented_bounding_box.h +++ b/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/oriented_bounding_box.h @@ -88,7 +88,7 @@ void construct_oriented_bounding_box(const PointRange& points, zmax = (std::max)(rot_pt.z(), zmax); } - const typename Traits::Construct_point_3 cp = traits.construct_point_3_object(); + typename Traits::Construct_point_3 cp = traits.construct_point_3_object(); obb_points[0] = cp(xmin, ymin, zmin); obb_points[1] = cp(xmax, ymin, zmin); From c15d63000fdd706913b3e18746bb6d587beb6f1b Mon Sep 17 00:00:00 2001 From: Maxime Gimeno Date: Thu, 14 May 2020 10:49:12 +0200 Subject: [PATCH 387/568] Fix min max errors --- Number_types/include/CGAL/Mpzf.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Number_types/include/CGAL/Mpzf.h b/Number_types/include/CGAL/Mpzf.h index 89165187d93..2612e29b3a0 100644 --- a/Number_types/include/CGAL/Mpzf.h +++ b/Number_types/include/CGAL/Mpzf.h @@ -578,10 +578,10 @@ struct Mpzf { friend bool operator!=(Mpzf const&a, Mpzf const&b){ return !(a==b); } - friend Mpzf const&min(Mpzf const&a, Mpzf const&b){ + friend Mpzf const& min BOOST_PREVENT_MACRO_SUBSTITUTION (Mpzf const&a, Mpzf const&b){ return (b Date: Thu, 14 May 2020 10:55:02 +0200 Subject: [PATCH 388/568] Cosmetic: use variables from GNUInstallDirs instead of our guesses --- Installation/CMakeLists.txt | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Installation/CMakeLists.txt b/Installation/CMakeLists.txt index 161b8b394ad..780679eb6ca 100644 --- a/Installation/CMakeLists.txt +++ b/Installation/CMakeLists.txt @@ -25,7 +25,7 @@ if(POLICY CMP0056) cmake_policy(SET CMP0056 NEW) endif() -# Use GNUInstallDirst to get canonical paths +# Use GNUInstallDirs to get canonical paths include(GNUInstallDirs) #-------------------------------------------------------------------------------------------------- @@ -773,11 +773,11 @@ set ( CGAL_INSTALL_CMAKE_DIR "${CGAL_INSTALL_LIB_DIR}/cmake/CGAL" CACHE STRING "The folder where CGAL CMake modules will be installed, relative to CMAKE_INSTALL_PREFIX" ) -set ( CGAL_INSTALL_DOC_DIR "${CMAKE_INSTALL_DATAROOTDIR}/doc/${CGAL_VERSION_DIR}" +set ( CGAL_INSTALL_DOC_DIR "${CMAKE_INSTALL_DOCDIR}" CACHE STRING "The folder where CGAL documentation and license files will be installed, relative to CMAKE_INSTALL_PREFIX" ) -set ( CGAL_INSTALL_MAN_DIR "${CMAKE_INSTALL_DATAROOTDIR}/man/man1" +set ( CGAL_INSTALL_MAN_DIR "${CMAKE_INSTALL_MANDIR}/man1" CACHE STRING "The folder where manual pages for CGAL scripts will be installed, relative to CMAKE_INSTALL_PREFIX" ) From d85396c148245a40f087c43e51300f8fdddee268 Mon Sep 17 00:00:00 2001 From: Laurent Rineau Date: Thu, 14 May 2020 11:10:04 +0200 Subject: [PATCH 389/568] Make CGAL relocatable again It will be relocatable if the user does not change `CGAL_INSTALL_CMAKE_DIR` from its default. --- Installation/CMakeLists.txt | 14 +++++++++----- Installation/lib/cmake/CGAL/CGALConfig.cmake | 5 ++++- 2 files changed, 13 insertions(+), 6 deletions(-) diff --git a/Installation/CMakeLists.txt b/Installation/CMakeLists.txt index 780679eb6ca..0bf9476ef95 100644 --- a/Installation/CMakeLists.txt +++ b/Installation/CMakeLists.txt @@ -926,12 +926,17 @@ if(NOT CGAL_HEADER_ONLY) ${CMAKE_BINARY_DIR}/config/CGALConfig.cmake DESTINATION ${CGAL_INSTALL_CMAKE_DIR} ) else() - configure_file(${CMAKE_CURRENT_LIST_DIR}/lib/cmake/CGAL/CGALConfig-installation-dirs.cmake.in - ${CMAKE_BINARY_DIR}/config/CGALConfig-installation-dirs.cmake) install(FILES - ${CMAKE_BINARY_DIR}/config/CGALConfig-installation-dirs.cmake ${CMAKE_CURRENT_LIST_DIR}/lib/cmake/CGAL/CGALConfig.cmake - DESTINATION ${CGAL_INSTALL_CMAKE_DIR} ) + ${CMAKE_CURRENT_LIST_DIR}/lib/cmake/CGAL/CGALConfigVersion.cmake + DESTINATION ${CGAL_INSTALL_CMAKE_DIR}) + if(NOT CGAL_INSTALL_CMAKE_DIR STREQUAL "${CGAL_INSTALL_LIB_DIR}/cmake/CGAL") + configure_file(${CMAKE_CURRENT_LIST_DIR}/lib/cmake/CGAL/CGALConfig-installation-dirs.cmake.in + ${CMAKE_BINARY_DIR}/config/CGALConfig-installation-dirs.cmake) + install(FILES + ${CMAKE_BINARY_DIR}/config/CGALConfig-installation-dirs.cmake + DESTINATION ${CGAL_INSTALL_CMAKE_DIR}) + endif() endif() if(CGAL_INSTALL_MAN_DIR) @@ -1379,4 +1384,3 @@ if(NOT CGAL_BRANCH_BUILD AND EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/doc") # in a non-branch build this is the top-level CMakeLists.txt add_subdirectory("${CMAKE_CURRENT_SOURCE_DIR}/doc") endif() - diff --git a/Installation/lib/cmake/CGAL/CGALConfig.cmake b/Installation/lib/cmake/CGAL/CGALConfig.cmake index 5605aed01ba..0801425b90e 100644 --- a/Installation/lib/cmake/CGAL/CGALConfig.cmake +++ b/Installation/lib/cmake/CGAL/CGALConfig.cmake @@ -1,4 +1,4 @@ -# +# # This file is the CGALConfig.cmake for a header-only CGAL installation # @@ -53,6 +53,9 @@ else() if(NOT EXISTS ${CGAL_ROOT}/include/CGAL/config.h) get_filename_component(CGAL_ROOT "${CGAL_ROOT}" DIRECTORY) endif() + if(NOT EXISTS ${CGAL_ROOT}/include/CGAL/config.h) + get_filename_component(CGAL_ROOT "${CGAL_ROOT}" DIRECTORY) + endif() endif() # not BRANCH_BUILD: it can be an installed CGAL, or the tarball layout if(EXISTS ${CGAL_CONFIG_DIR}/CGAL_add_test.cmake) From 252b58d39fb3a997365b584b84a43bc75d7b655f Mon Sep 17 00:00:00 2001 From: Laurent Rineau Date: Thu, 14 May 2020 11:26:00 +0200 Subject: [PATCH 390/568] Change the version compatibility to SameMajorVersion and change the testsuite --- Installation/lib/cmake/CGAL/CGALConfigVersion.cmake | 6 +++++- Installation/test/Installation/CMakeLists.txt | 7 ++++++- 2 files changed, 11 insertions(+), 2 deletions(-) diff --git a/Installation/lib/cmake/CGAL/CGALConfigVersion.cmake b/Installation/lib/cmake/CGAL/CGALConfigVersion.cmake index 16aa829ea9d..ee71a01063c 100644 --- a/Installation/lib/cmake/CGAL/CGALConfigVersion.cmake +++ b/Installation/lib/cmake/CGAL/CGALConfigVersion.cmake @@ -15,7 +15,11 @@ set(PACKAGE_VERSION ${CGAL_CREATED_VERSION_NUM}) if(PACKAGE_VERSION VERSION_LESS PACKAGE_FIND_VERSION) set(PACKAGE_VERSION_COMPATIBLE FALSE) else() - set(PACKAGE_VERSION_COMPATIBLE TRUE) + if(PACKAGE_FIND_VERSION_MAJOR STREQUAL CGAL_MAJOR_VERSION) + set(PACKAGE_VERSION_COMPATIBLE TRUE) + else() + set(PACKAGE_VERSION_COMPATIBLE FALSE) + endif() if(PACKAGE_FIND_VERSION STREQUAL PACKAGE_VERSION) set(PACKAGE_VERSION_EXACT TRUE) endif() diff --git a/Installation/test/Installation/CMakeLists.txt b/Installation/test/Installation/CMakeLists.txt index e4aacdf867c..cbb6b6b9681 100644 --- a/Installation/test/Installation/CMakeLists.txt +++ b/Installation/test/Installation/CMakeLists.txt @@ -106,7 +106,10 @@ endif() function(CGAL_installation_test_find_package_version mode) set(EXACT) if(mode STREQUAL "less") - MATH(EXPR CGAL_MAJOR_VERSION "${CGAL_MAJOR_VERSION} - 1") + set(CGAL_MINOR_VERSION 0) + endif() + if(mode STREQUAL "less_major") + set(CGAL_MAJOR_VERSION 0) endif() if(mode STREQUAL "greater" OR mode STREQUAL "fail-exact") MATH(EXPR CGAL_MINOR_VERSION "${CGAL_MINOR_VERSION} + 1") @@ -129,11 +132,13 @@ function(CGAL_installation_test_find_package_version mode) endfunction() CGAL_installation_test_find_package_version(less) +CGAL_installation_test_find_package_version(less_major) CGAL_installation_test_find_package_version(equal) CGAL_installation_test_find_package_version(greater) CGAL_installation_test_find_package_version(exact) CGAL_installation_test_find_package_version(fail-exact) set_tests_properties( test_find_package_version_greater + test_find_package_version_less_major test_find_package_version_fail-exact PROPERTIES WILL_FAIL TRUE) From 52186a04e05059c48be3b19e244d302f6d3779b0 Mon Sep 17 00:00:00 2001 From: Guillaume Damiand Date: Thu, 14 May 2020 11:38:15 +0200 Subject: [PATCH 391/568] Two bug fixes: (1) computation of cycle lengths, when some halfedges are flip; (2) when we use of face graph wrapper with surface mesh we can not use nullptr. --- .../Surface_mesh_topology/edgewidth_lcc.cpp | 3 +- .../shortest_noncontractible_cycle.cpp | 3 +- .../include/CGAL/Face_graph_wrapper.h | 6 ++++ .../include/CGAL/Path_on_surface.h | 20 +++++++------ .../include/CGAL/Polygonal_schema.h | 28 +++++++++---------- .../internal/Shortest_noncontractible_cycle.h | 4 +-- 6 files changed, 38 insertions(+), 26 deletions(-) diff --git a/Surface_mesh_topology/examples/Surface_mesh_topology/edgewidth_lcc.cpp b/Surface_mesh_topology/examples/Surface_mesh_topology/edgewidth_lcc.cpp index 35f13e026c0..84cd8900fe0 100644 --- a/Surface_mesh_topology/examples/Surface_mesh_topology/edgewidth_lcc.cpp +++ b/Surface_mesh_topology/examples/Surface_mesh_topology/edgewidth_lcc.cpp @@ -14,7 +14,8 @@ double cycle_length(const LCC_3& lcc, const Path_on_surface& cycle) double res=0; for (std::size_t i=0; i:: + run(mmap.get_fg(), it); + } + private: const Self & mmap; mutable typename Self::size_type msize; diff --git a/Surface_mesh_topology/include/CGAL/Path_on_surface.h b/Surface_mesh_topology/include/CGAL/Path_on_surface.h index 96a0c56a029..5eecbcb9b65 100644 --- a/Surface_mesh_topology/include/CGAL/Path_on_surface.h +++ b/Surface_mesh_topology/include/CGAL/Path_on_surface.h @@ -133,6 +133,10 @@ public: m_is_closed=false; } + /// @return true iff the prev index exists + bool prev_index_exists(std::size_t i) const + { return is_closed() || i>0; } + /// @return true iff the next index exists bool next_index_exists(std::size_t i) const { return is_closed() || i<(m_path.size()-1); } @@ -164,25 +168,25 @@ public: { return get_ith_dart(i); } /// @return the dart before the ith dart of the path, - /// nullptr if such a dart does not exist. + /// Map::null_handle if such a dart does not exist. Dart_const_handle get_prev_dart(std::size_t i) const { CGAL_assertion(i& edge_label_to_dart) { - if (dart_same_label!=nullptr && dart_opposite_label!=nullptr) + if (dart_same_label!=CMap::null_handle && dart_opposite_label!=CMap::null_handle) { std::cerr<<"Polygonal_schema ERROR: "<<"both labels "<(prev_dart, res); } - if (dart_opposite_label!=nullptr) + if (dart_opposite_label!=CMap::null_handle) { cmap.template link_beta<2>(res, dart_opposite_label); } return res; @@ -111,13 +111,13 @@ namespace Surface_mesh_topology { std::unordered_map& edge_label_to_dart) { - if (dart_same_label!=nullptr && dart_opposite_label!=nullptr) + if (dart_same_label!=GMap::null_handle && dart_opposite_label!=GMap::null_handle) { std::cerr<<"Polygonal_schema ERROR: "<<"both labels "<(res, gmap.template alpha<0>(prev_dart)); } - if (dart_same_label!=nullptr) - { // Here dart_same_label!=nullptr + if (dart_same_label!=GMap::null_handle) + { // Here dart_same_label!=GMap::null_handle std::string s2=internal::opposite_label(s); edge_label_to_dart[s2]=dh2; gmap.info(dh2).m_label=s2; @@ -136,11 +136,11 @@ namespace Surface_mesh_topology { gmap.template sew<2>(res, dart_same_label); } else - { // Here either dart_opposite_label!=nullptr, or both are nullptr + { // Here either dart_opposite_label!=GMap::null_handle, or both are GMap::null_handle edge_label_to_dart[s]=res; gmap.info(res).m_label=s; - if (dart_opposite_label!=nullptr) + if (dart_opposite_label!=GMap::null_handle) { std::string s2=internal::opposite_label(s); edge_label_to_dart[s2]=res; @@ -304,7 +304,7 @@ namespace Surface_mesh_topology { std::cerr<<"Polygonal_schema ERROR: " <<"you try to end a facet" <<" but the facet is not yet started."<null_handle && prev_dart!=this->null_handle ); @@ -314,12 +314,12 @@ namespace Surface_mesh_topology { return first_dart; } - /// @return dart with the given label, nullptr if this dart does not exist. + /// @return dart with the given label, Map::null_handle if this dart does not exist. Dart_handle get_dart_labeled(const std::string& s) const { auto ite=edge_label_to_dart.find(s); if (ite==edge_label_to_dart.end()) - { return nullptr; } + { return Map::null_handle; } return ite->second; } diff --git a/Surface_mesh_topology/include/CGAL/Surface_mesh_topology/internal/Shortest_noncontractible_cycle.h b/Surface_mesh_topology/include/CGAL/Surface_mesh_topology/internal/Shortest_noncontractible_cycle.h index 50980839814..fd5fbb83d0d 100644 --- a/Surface_mesh_topology/include/CGAL/Surface_mesh_topology/internal/Shortest_noncontractible_cycle.h +++ b/Surface_mesh_topology/include/CGAL/Surface_mesh_topology/internal/Shortest_noncontractible_cycle.h @@ -159,8 +159,8 @@ public: template Path compute_shortest_non_contractible_cycle(typename WeightFunctor::Weight_t* length, - const WeightFunctor& wf, - bool display_time=false) + const WeightFunctor& wf, + bool display_time=false) { CGAL::Timer t; if (display_time) From 3d5fc5c1ca52c30e6272f0d147013d65043396c0 Mon Sep 17 00:00:00 2001 From: Jane Tournois Date: Thu, 14 May 2020 13:51:41 +0200 Subject: [PATCH 392/568] silent warning "STL4009: std::allocator is deprecated in C++17." from boost-1_71\boost/bimap/detail/manage_additional_parameters.hpp(86): warning C4996: 'std::allocator': warning STL4009: std::allocator is deprecated in C++17. You can define _SILENCE_CXX17_ALLOCATOR_VOID_DEPRECATION_WARNING or _SILENCE_ALL_CXX17_DEPRECATION_WARNINGS to acknowledge that you have received this warning. see https://github.com/boostorg/beast/issues/1272 it seems that this warning is an error in msvc --- Installation/include/CGAL/config.h | 3 +++ 1 file changed, 3 insertions(+) diff --git a/Installation/include/CGAL/config.h b/Installation/include/CGAL/config.h index a215cbbf4e5..abadb8f26ef 100644 --- a/Installation/include/CGAL/config.h +++ b/Installation/include/CGAL/config.h @@ -740,5 +740,8 @@ typedef const void * Nullptr_t; // Anticipate C++0x's std::nullptr_t /// @} #include +#ifdef BOOST_MSVC +#define _SILENCE_CXX17_ALLOCATOR_VOID_DEPRECATION_WARNING 1 +#endif #endif // CGAL_CONFIG_H From 35446f5180d1dbff19f959849ecb955e45c9d822 Mon Sep 17 00:00:00 2001 From: Guillaume Damiand Date: Thu, 14 May 2020 18:58:35 +0200 Subject: [PATCH 393/568] Remove one warning in unsew_edgewidth_repeatedly.cpp example --- .../Surface_mesh_topology/unsew_edgewidth_repeatedly.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/Surface_mesh_topology/examples/Surface_mesh_topology/unsew_edgewidth_repeatedly.cpp b/Surface_mesh_topology/examples/Surface_mesh_topology/unsew_edgewidth_repeatedly.cpp index 37ff1b0af57..f66cec0b7af 100644 --- a/Surface_mesh_topology/examples/Surface_mesh_topology/unsew_edgewidth_repeatedly.cpp +++ b/Surface_mesh_topology/examples/Surface_mesh_topology/unsew_edgewidth_repeatedly.cpp @@ -81,7 +81,10 @@ int main(int argc, char* argv[]) { std::cout<<"Program unsew_edgewidth_repeatedly started."< Date: Fri, 15 May 2020 11:19:35 +0200 Subject: [PATCH 394/568] add missing const --- .../examples/Spatial_searching/distance_browsing.cpp | 2 +- Spatial_searching/include/CGAL/Incremental_neighbor_search.h | 2 +- .../include/CGAL/Orthogonal_incremental_neighbor_search.h | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/Spatial_searching/examples/Spatial_searching/distance_browsing.cpp b/Spatial_searching/examples/Spatial_searching/distance_browsing.cpp index 9d5880abc13..8ef9f285c0e 100644 --- a/Spatial_searching/examples/Spatial_searching/distance_browsing.cpp +++ b/Spatial_searching/examples/Spatial_searching/distance_browsing.cpp @@ -35,7 +35,7 @@ int main() { std::cout << "The first 5 nearest neighbours with positive x-coord are: " << std::endl; for (int j=0; (j < 5)&&(it!=end); ++j,++it) - std::cout << (*it).first << " at squared distance = " << (*it).second << std::endl; + std::cout << (*it).first << " at squared distance = " << it->second << std::endl; return 0; } diff --git a/Spatial_searching/include/CGAL/Incremental_neighbor_search.h b/Spatial_searching/include/CGAL/Incremental_neighbor_search.h index 8d697711d1a..c3feb395e25 100644 --- a/Spatial_searching/include/CGAL/Incremental_neighbor_search.h +++ b/Spatial_searching/include/CGAL/Incremental_neighbor_search.h @@ -147,7 +147,7 @@ namespace CGAL { typedef std::input_iterator_tag iterator_category; typedef Point_with_transformed_distance value_type; - typedef Point_with_transformed_distance* pointer; + typedef const Point_with_transformed_distance* pointer; typedef const Point_with_transformed_distance& reference; typedef std::size_t size_type; typedef std::ptrdiff_t difference_type; diff --git a/Spatial_searching/include/CGAL/Orthogonal_incremental_neighbor_search.h b/Spatial_searching/include/CGAL/Orthogonal_incremental_neighbor_search.h index d7e1050c2f9..512dc0c9658 100644 --- a/Spatial_searching/include/CGAL/Orthogonal_incremental_neighbor_search.h +++ b/Spatial_searching/include/CGAL/Orthogonal_incremental_neighbor_search.h @@ -480,7 +480,7 @@ namespace CGAL { typedef std::input_iterator_tag iterator_category; typedef Point_with_transformed_distance value_type; - typedef Point_with_transformed_distance* pointer; + typedef const Point_with_transformed_distance* pointer; typedef const Point_with_transformed_distance& reference; typedef std::size_t size_type; typedef std::ptrdiff_t difference_type; From b6912d92eadfff1db25270cb8d3d134cd8f022fd Mon Sep 17 00:00:00 2001 From: Jane Tournois Date: Fri, 15 May 2020 13:54:19 +0200 Subject: [PATCH 395/568] fix warnings - move #define a better location - conversion double/size_t - unused parameters - automatic conversion int/boolean --- Installation/include/CGAL/config.h | 8 +- .../Remeshing_triangulation_3.h | 192 +++++++++--------- .../Tetrahedral_remeshing/internal/FMLS.h | 2 +- .../internal/tetrahedral_remeshing_helpers.h | 2 +- .../include/CGAL/tetrahedral_remeshing.h | 2 +- ...st_tetrahedral_remeshing_with_features.cpp | 2 +- 6 files changed, 103 insertions(+), 105 deletions(-) diff --git a/Installation/include/CGAL/config.h b/Installation/include/CGAL/config.h index abadb8f26ef..225470e0216 100644 --- a/Installation/include/CGAL/config.h +++ b/Installation/include/CGAL/config.h @@ -36,6 +36,10 @@ # define WIN64 #endif +#ifdef BOOST_MSVC +#define _SILENCE_CXX17_ALLOCATOR_VOID_DEPRECATION_WARNING 1 +#endif + #ifdef CGAL_INCLUDE_WINDOWS_DOT_H // Mimic users including this file which defines min max macros // and other names leading to name clashes @@ -740,8 +744,4 @@ typedef const void * Nullptr_t; // Anticipate C++0x's std::nullptr_t /// @} #include -#ifdef BOOST_MSVC -#define _SILENCE_CXX17_ALLOCATOR_VOID_DEPRECATION_WARNING 1 -#endif - #endif // CGAL_CONFIG_H diff --git a/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/Remeshing_triangulation_3.h b/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/Remeshing_triangulation_3.h index 3e91a6dfd23..ecb52808729 100644 --- a/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/Remeshing_triangulation_3.h +++ b/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/Remeshing_triangulation_3.h @@ -81,103 +81,101 @@ public: using Base::Base; }; -namespace internal -{ -template -struct Vertex_converter -{ - //This operator is used to create the vertex from v_src. - typename TDS_tgt::Vertex operator()(const typename TDS_src::Vertex& v_src) const - { - typedef typename CGAL::Kernel_traits< - typename TDS_src::Vertex::Point>::Kernel GT_src; - typedef typename CGAL::Kernel_traits< - typename TDS_tgt::Vertex::Point>::Kernel GT_tgt; - CGAL::Cartesian_converter conv; - - typedef typename TDS_tgt::Vertex::Point Tgt_point; - - typename TDS_tgt::Vertex v_tgt; - v_tgt.set_point(Tgt_point(conv(point(v_src.point())))); - v_tgt.set_time_stamp(-1); - v_tgt.set_dimension(3);//-1 if unset, 0,1,2, or 3 if set - return v_tgt; - } - //This operator is meant to be used in case heavy data should transferred to v_tgt. - void operator()(const typename TDS_src::Vertex& v_src, - typename TDS_tgt::Vertex& v_tgt) const - { - typedef typename CGAL::Kernel_traits< - typename TDS_src::Vertex::Point>::Kernel GT_src; - typedef typename CGAL::Kernel_traits< - typename TDS_tgt::Vertex::Point>::Kernel GT_tgt; - CGAL::Cartesian_converter conv; - - typedef typename TDS_tgt::Vertex::Point Tgt_point; - - v_tgt.set_point(Tgt_point(conv(point(v_src.point())))); - v_tgt.set_dimension(3);//v_src.info()); - } -}; - -template -struct Cell_converter -{ - //This operator is used to create the cell from c_src. - typename TDS_tgt::Cell operator()(const typename TDS_src::Cell& c_src) const - { - typename TDS_tgt::Cell c_tgt; - c_tgt.set_subdomain_index(1);//c_src.subdomain_index()); -// c_tgt.info() = c_src.info(); - c_tgt.set_time_stamp(-1); - return c_tgt; - } - //This operator is meant to be used in case heavy data should transferred to c_tgt. - void operator()(const typename TDS_src::Cell& c_src, - typename TDS_tgt::Cell& c_tgt) const - { -// c_tgt.set_subdomain_index(c_src.subdomain_index()); - // c_tgt.info() = c_src.info(); - } -}; - -} - - -template -void build_remeshing_triangulation(const T3& tr, - Remeshing_triangulation_3& remeshing_tr) -{ - typedef typename T3::Triangulation_data_structure Tds; - typedef typename Remeshing_triangulation_3::Tds RTds; - - remeshing_tr.clear(); - - remeshing_tr.set_infinite_vertex( - remeshing_tr.tds().copy_tds( - tr.tds(), - tr.infinite_vertex(), - internal::Vertex_converter(), - internal::Cell_converter())); -} - -template -void build_from_remeshing_triangulation( - const Remeshing_triangulation_3& remeshing_tr, - T3& tr) -{ - typedef typename T3::Triangulation_data_structure Tds; - typedef typename Remeshing_triangulation_3::Tds RTds; - - tr.clear(); - - tr.set_infinite_vertex( - tr.tds().copy_tds( - remeshing_tr.tds(), - remeshing_tr.infinite_vertex(), - internal::Vertex_converter(), - internal::Cell_converter())); -} +//namespace internal +//{ +//template +//struct Vertex_converter +//{ +// //This operator is used to create the vertex from v_src. +// typename TDS_tgt::Vertex operator()(const typename TDS_src::Vertex& v_src) const +// { +// typedef typename CGAL::Kernel_traits< +// typename TDS_src::Vertex::Point>::Kernel GT_src; +// typedef typename CGAL::Kernel_traits< +// typename TDS_tgt::Vertex::Point>::Kernel GT_tgt; +// CGAL::Cartesian_converter conv; +// +// typedef typename TDS_tgt::Vertex::Point Tgt_point; +// +// typename TDS_tgt::Vertex v_tgt; +// v_tgt.set_point(Tgt_point(conv(point(v_src.point())))); +// v_tgt.set_time_stamp(-1); +// v_tgt.set_dimension(3);//-1 if unset, 0,1,2, or 3 if set +// return v_tgt; +// } +// //This operator is meant to be used in case heavy data should transferred to v_tgt. +// void operator()(const typename TDS_src::Vertex& v_src, +// typename TDS_tgt::Vertex& v_tgt) const +// { +// typedef typename CGAL::Kernel_traits< +// typename TDS_src::Vertex::Point>::Kernel GT_src; +// typedef typename CGAL::Kernel_traits< +// typename TDS_tgt::Vertex::Point>::Kernel GT_tgt; +// CGAL::Cartesian_converter conv; +// +// typedef typename TDS_tgt::Vertex::Point Tgt_point; +// +// v_tgt.set_point(Tgt_point(conv(point(v_src.point())))); +// v_tgt.set_dimension(3);//v_src.info()); +// } +//}; +// +//template +//struct Cell_converter +//{ +// //This operator is used to create the cell from c_src. +// typename TDS_tgt::Cell operator()(const typename TDS_src::Cell& c_src) const +// { +// typename TDS_tgt::Cell c_tgt; +// c_tgt.set_subdomain_index(c_src.subdomain_index()); +// c_tgt.set_time_stamp(-1); +// return c_tgt; +// } +// //This operator is meant to be used in case heavy data should transferred to c_tgt. +// void operator()(const typename TDS_src::Cell& c_src, +// typename TDS_tgt::Cell& c_tgt) const +// { +// c_tgt.set_subdomain_index(c_src.subdomain_index()); +// } +//}; +// +//} +// +// +//template +//void build_remeshing_triangulation(const T3& tr, +// Remeshing_triangulation_3& remeshing_tr) +//{ +// typedef typename T3::Triangulation_data_structure Tds; +// typedef typename Remeshing_triangulation_3::Tds RTds; +// +// remeshing_tr.clear(); +// +// remeshing_tr.set_infinite_vertex( +// remeshing_tr.tds().copy_tds( +// tr.tds(), +// tr.infinite_vertex(), +// internal::Vertex_converter(), +// internal::Cell_converter())); +//} +// +//template +//void build_from_remeshing_triangulation( +// const Remeshing_triangulation_3& remeshing_tr, +// T3& tr) +//{ +// typedef typename T3::Triangulation_data_structure Tds; +// typedef typename Remeshing_triangulation_3::Tds RTds; +// +// tr.clear(); +// +// tr.set_infinite_vertex( +// tr.tds().copy_tds( +// remeshing_tr.tds(), +// remeshing_tr.infinite_vertex(), +// internal::Vertex_converter(), +// internal::Cell_converter())); +//} }//end namespace Tetrahedral_remeshing }//end namespace CGAL diff --git a/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/FMLS.h b/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/FMLS.h index 8f3d157a7b3..07f6e3e3286 100644 --- a/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/FMLS.h +++ b/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/FMLS.h @@ -462,7 +462,7 @@ private: for (int j = 0; j < 3; j++) { if (vp[j] < 0) - p[j] = 0.; + p[j] = 0; if (vp[j] >= res[j]) p[j] = res[j] - 1; else diff --git a/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/tetrahedral_remeshing_helpers.h b/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/tetrahedral_remeshing_helpers.h index 5ad1cc5cc14..d8e18c6d8fe 100644 --- a/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/tetrahedral_remeshing_helpers.h +++ b/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/tetrahedral_remeshing_helpers.h @@ -1017,7 +1017,7 @@ void dump_surface_off(const Tr& tr, const char* filename) } template -void dump_cells_off(const CellRange& cells, const Tr& tr, const char* filename) +void dump_cells_off(const CellRange& cells, const Tr& /*tr*/, const char* filename) { typedef typename Tr::Vertex_handle Vertex_handle; typedef typename Tr::Cell_handle Cell_handle; diff --git a/Tetrahedral_remeshing/include/CGAL/tetrahedral_remeshing.h b/Tetrahedral_remeshing/include/CGAL/tetrahedral_remeshing.h index 38aaadc0009..31123ed41e4 100644 --- a/Tetrahedral_remeshing/include/CGAL/tetrahedral_remeshing.h +++ b/Tetrahedral_remeshing/include/CGAL/tetrahedral_remeshing.h @@ -275,7 +275,7 @@ void tetrahedral_isotropic_remeshing( { tetrahedral_isotropic_remeshing( c3t3, - [target_edge_length](const typename Tr::Point& p) + [target_edge_length](const typename Tr::Point& /*p*/) {return target_edge_length; }, np); } diff --git a/Tetrahedral_remeshing/test/Tetrahedral_remeshing/test_tetrahedral_remeshing_with_features.cpp b/Tetrahedral_remeshing/test/Tetrahedral_remeshing/test_tetrahedral_remeshing_with_features.cpp index 528b1a33285..3ca850d78e6 100644 --- a/Tetrahedral_remeshing/test/Tetrahedral_remeshing/test_tetrahedral_remeshing_with_features.cpp +++ b/Tetrahedral_remeshing/test/Tetrahedral_remeshing/test_tetrahedral_remeshing_with_features.cpp @@ -61,7 +61,7 @@ public: { CGAL_assertion(map.m_set_ptr != NULL); CGAL_assertion(k.first < k.second); - return map.m_set_ptr->count(k); + return map.m_set_ptr->count(k) > 0; } }; From 7eb640c655657c70c06ad56c2c922bda893888aa Mon Sep 17 00:00:00 2001 From: Jane Tournois Date: Fri, 15 May 2020 14:53:47 +0200 Subject: [PATCH 396/568] warning "may be used uninitialized" --- .../CGAL/Tetrahedral_remeshing/internal/smooth_vertices.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/smooth_vertices.h b/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/smooth_vertices.h index 660fb3507d4..04e20d13d92 100644 --- a/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/smooth_vertices.h +++ b/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/smooth_vertices.h @@ -292,7 +292,7 @@ private: CGAL_assertion(!std::isnan(gi.x()) && !std::isnan(gi.y()) && !std::isnan(gi.z())); Vector_3 point(gi.x(), gi.y(), gi.z()); - Vector_3 res_normal; + Vector_3 res_normal = CGAL::NULL_VECTOR; Vector_3 result(point); const FMLS& fmls = subdomain_FMLS[subdomain_FMLS_indices.at(si)]; From 65e612d26a1fe8be147bab6d04b2696c914914c4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mael=20Rouxel-Labb=C3=A9?= Date: Fri, 15 May 2020 14:59:25 +0200 Subject: [PATCH 397/568] Do not use the deprecated API of copy_face_graph in stitching tests --- .../test/Polygon_mesh_processing/test_stitching.cpp | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) diff --git a/Polygon_mesh_processing/test/Polygon_mesh_processing/test_stitching.cpp b/Polygon_mesh_processing/test/Polygon_mesh_processing/test_stitching.cpp index e261c14edab..a4782d4f0dd 100644 --- a/Polygon_mesh_processing/test/Polygon_mesh_processing/test_stitching.cpp +++ b/Polygon_mesh_processing/test/Polygon_mesh_processing/test_stitching.cpp @@ -25,9 +25,7 @@ template void test_stitch_boundary_cycles(const char* fname, const std::size_t expected_n) { - 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; std::cout << "Testing stitch_boundary_cycles(); file: " << fname << "..." << std::flush; @@ -44,15 +42,11 @@ void test_stitch_boundary_cycles(const char* fname, if(!is_border(h, mesh)) continue; - std::unordered_map v2v; std::unordered_map h2h; - std::unordered_map f2f; Mesh mesh_cpy; CGAL::copy_face_graph(mesh, mesh_cpy, - std::inserter(v2v, v2v.end()), - std::inserter(h2h, h2h.end()), - std::inserter(f2f, f2f.end())); + CGAL::parameters::halfedge_to_halfedge_output_iterator(std::inserter(h2h, h2h.end()))); assert(is_border(h2h.at(h), mesh_cpy)); From 7a6bdc1946e8b6d7e23b4ad0dfb22bb9e3011175 Mon Sep 17 00:00:00 2001 From: Andreas Fabri Date: Fri, 15 May 2020 14:16:56 +0100 Subject: [PATCH 398/568] Mesh_2: make it deterministic --- .../include/CGAL/Delaunay_mesh_face_base_2.h | 9 ++ Mesh_2/test/Mesh_2/reproductibility.cpp | 110 ++++++++++++++++++ .../CGAL/Triangulation_data_structure_2.h | 4 +- .../CGAL/Constrained_triangulation_2.h | 26 +++++ 4 files changed, 148 insertions(+), 1 deletion(-) create mode 100644 Mesh_2/test/Mesh_2/reproductibility.cpp diff --git a/Mesh_2/include/CGAL/Delaunay_mesh_face_base_2.h b/Mesh_2/include/CGAL/Delaunay_mesh_face_base_2.h index 696edc53ba8..b706db459d6 100644 --- a/Mesh_2/include/CGAL/Delaunay_mesh_face_base_2.h +++ b/Mesh_2/include/CGAL/Delaunay_mesh_face_base_2.h @@ -17,6 +17,7 @@ #include +#include namespace CGAL { @@ -67,6 +68,14 @@ public: /** compatibility with CGAL-3.2 */ inline void set_marked(const bool b) { in_domain=b; } + + typedef Tag_true Has_timestamp; + + std::size_t time_stamp() const { return time_stamp_; } + + void set_time_stamp(const std::size_t& ts) { time_stamp_ = ts; } + + std::size_t time_stamp_; }; } // namespace CGAL diff --git a/Mesh_2/test/Mesh_2/reproductibility.cpp b/Mesh_2/test/Mesh_2/reproductibility.cpp new file mode 100644 index 00000000000..d58eb53b005 --- /dev/null +++ b/Mesh_2/test/Mesh_2/reproductibility.cpp @@ -0,0 +1,110 @@ +//#define CGAL_MESH_2_DEBUG_BAD_FACES +//#define CGAL_MESH_2_DEBUG_CLUSTERS + +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +using K = CGAL::Exact_predicates_inexact_constructions_kernel; +using Vb = CGAL::Triangulation_vertex_base_2; +using Fb = CGAL::Delaunay_mesh_face_base_2; +using Tds = CGAL::Triangulation_data_structure_2; +using CDT = CGAL::Constrained_Delaunay_triangulation_2; +using Criteria = CGAL::Delaunay_mesh_size_criteria_2; +using Mesher = CGAL::Delaunay_mesher_2; + +using Vertex_handle = CDT::Vertex_handle; +using Point = CDT::Point; + +int main(int argc, char* argv[]) +{ + std::string path = argv[0]; + path = path.substr(0, path.rfind('/') + 1); + + std::cout << "Current dir:" << path << std::endl; + + auto triangulate = [&path](int index) + { + CDT cdt; + + auto write_tr = [&](const std::string& filename) + { +// std::ofstream file(path + filename + "_" + std::to_string(index) + ".off"); +// +// cdt.file_output(file); +// file.close(); + }; + + Vertex_handle va = cdt.insert(Point(-0.74397572, -0.54545455)); + Vertex_handle vb = cdt.insert(Point(-0.13526831, -1)); + Vertex_handle vc = cdt.insert(Point(0.067634156, -1)); + Vertex_handle vd = cdt.insert(Point(0.33817078, -0.54545455)); + Vertex_handle ve = cdt.insert(Point(0.74397572, 0.27272727)); + Vertex_handle vf = cdt.insert(Point(0.74397572, 0.54545455)); + Vertex_handle vg = cdt.insert(Point(0.067634156, 1)); + Vertex_handle vh = cdt.insert(Point(-0.13526831, 1)); + Vertex_handle vi = cdt.insert(Point(-0.74397572, -0.18181818)); + + cdt.insert_constraint(va, vb); + cdt.insert_constraint(vb, vc); + cdt.insert_constraint(vc, vd); + cdt.insert_constraint(vd, ve); + cdt.insert_constraint(ve, vf); + cdt.insert_constraint(vf, vg); + cdt.insert_constraint(vg, vh); + cdt.insert_constraint(vh, vi); + cdt.insert_constraint(vi, va); + + const std::vector points{ + Point(0.65605132, 0.43821259), + Point(0.23073753, -0.4476739), + Point(-0.037496007, -0.93636364), + Point(-0.00095596601, 0.88181818), + Point(-0.62452925, -0.30720903), + Point(-0.69663181, -0.45045525), + }; + + cdt.insert(points.cbegin(), points.cend()); + + std::cout << "Meshing: " << index << std::endl; + + std::cout << "Number of vertices before: " << cdt.number_of_vertices() << std::endl; + + write_tr("before_refine"); + + Mesher mesher(cdt); + mesher.set_criteria(Criteria(0.125, 0.05*std::sqrt(2))); + +// mesher.clear_seeds(); +// mesher.init(); + + mesher.refine_mesh(); + + write_tr("after_refine"); + + std::cout << "Number of vertices after: " << cdt.number_of_vertices() << std::endl; + + std::stringstream ss; + ss << cdt; + + return ss.str(); + }; + + const std::string ref_cdts = triangulate(0); + + for (int i = 1; i < 20; ++i) + { + const std::string cdts = triangulate(i); + if (ref_cdts != cdts) + return 1; + } + + return 0; +} diff --git a/TDS_2/include/CGAL/Triangulation_data_structure_2.h b/TDS_2/include/CGAL/Triangulation_data_structure_2.h index ed684feef47..3f88bbf5fa1 100644 --- a/TDS_2/include/CGAL/Triangulation_data_structure_2.h +++ b/TDS_2/include/CGAL/Triangulation_data_structure_2.h @@ -1032,7 +1032,9 @@ insert_dim_up(Vertex_handle w, bool orient) for ( ; lfit != faces_list.end() ; ++lfit) { f = * lfit; - g = create_face(f); //calls copy constructor of face + g = create_face(f->vertex(0),f->vertex(1),f->vertex(2), + f->neighbor(0),f->neighbor(1),f->neighbor(2)); + f->set_vertex(dim,v); g->set_vertex(dim,w); set_adjacency(f, dim, g, dim); diff --git a/Triangulation_2/include/CGAL/Constrained_triangulation_2.h b/Triangulation_2/include/CGAL/Constrained_triangulation_2.h index 272aec6a330..50c2d76c452 100644 --- a/Triangulation_2/include/CGAL/Constrained_triangulation_2.h +++ b/Triangulation_2/include/CGAL/Constrained_triangulation_2.h @@ -148,6 +148,7 @@ public: using Triangulation::all_edges_begin; using Triangulation::all_edges_end; using Triangulation::mirror_index; + using Triangulation::mirror_edge; using Triangulation::orientation; #endif @@ -656,6 +657,19 @@ insert(const Point& a, Locate_type lt, Face_handle loc, int li) Vertex_handle v1, v2; bool insert_in_constrained_edge = false; + std::list > constrained_edges; + bool one_dimensional = false; + if(dimension() == 1){ + one_dimensional = true; + for(Finite_edges_iterator it = finite_edges_begin(); + it != finite_edges_end(); + ++it){ + if(is_constrained(*it)){ + constrained_edges.push_back(std::make_pair(it->first->vertex(cw(it->second)), + it->first->vertex(ccw(it->second)))); + } + } + } if ( lt == Triangulation::EDGE && loc->is_constrained(li) ) { if(boost::is_same::value) @@ -668,6 +682,18 @@ insert(const Point& a, Locate_type lt, Face_handle loc, int li) va = Triangulation::insert(a,lt,loc,li); + if(one_dimensional && (dimension() == 2)){ + for(const std::pair vp : constrained_edges){ + Face_handle fh; + int i; + if(this->is_edge(vp.first, vp.second, fh,i)){ + fh->set_constraint(i,true); + boost::tie(fh,i) = mirror_edge(Edge(fh,i)); + fh->set_constraint(i,true); + } + } + } + if (insert_in_constrained_edge) update_constraints_incident(va, v1,v2); else if(lt != Triangulation::VERTEX) From f144de393a8339b0d3d1466683c3956b3671f354 Mon Sep 17 00:00:00 2001 From: Maxime Gimeno Date: Fri, 15 May 2020 15:49:06 +0200 Subject: [PATCH 399/568] Add binary support for surf reading. --- .../Polyhedron/Plugins/IO/Surf_io_plugin.cpp | 2 +- .../include/CGAL/IO/read_surf_trianglemesh.h | 305 +++++++++++++++--- 2 files changed, 258 insertions(+), 49 deletions(-) diff --git a/Polyhedron/demo/Polyhedron/Plugins/IO/Surf_io_plugin.cpp b/Polyhedron/demo/Polyhedron/Plugins/IO/Surf_io_plugin.cpp index bad79971d59..ea5138c22ed 100644 --- a/Polyhedron/demo/Polyhedron/Plugins/IO/Surf_io_plugin.cpp +++ b/Polyhedron/demo/Polyhedron/Plugins/IO/Surf_io_plugin.cpp @@ -27,7 +27,7 @@ class Surf_io_plugin: public: QString name() const { return "surf_io_plugin"; } - QString nameFilters() const { return "Amira files (*.surf)"; } + QString nameFilters() const { return "Amira files (*.surf);;Amira binary files (*.surf.am)"; } bool canLoad(QFileInfo) const{ return true; } template CGAL::Three::Scene_item* actual_load(QFileInfo fileinfo); diff --git a/Polyhedron/demo/Polyhedron/include/CGAL/IO/read_surf_trianglemesh.h b/Polyhedron/demo/Polyhedron/include/CGAL/IO/read_surf_trianglemesh.h index 5d6b1fe41ae..9548ee658b9 100644 --- a/Polyhedron/demo/Polyhedron/include/CGAL/IO/read_surf_trianglemesh.h +++ b/Polyhedron/demo/Polyhedron/include/CGAL/IO/read_surf_trianglemesh.h @@ -168,6 +168,8 @@ void treat_surf_inner_region(std::istream& input, iss.str(input_line); std::string dump; iss >> dump >> name; + name.erase(std::remove(name.begin(), name.end(), '"'), name.end()); + name.erase(std::remove(name.begin(), name.end(), ','), name.end()); for(std::size_t j=0; j +bool fill_binary_vertices(std::istream& is, std::vector& points, const std::size_t& nb_points) +{ + float f[3]; + std::size_t pos = 0; + while(pos < nb_points) + { + is.read(reinterpret_cast(&f[0]), sizeof(f[0])); + if(!is.good()) + return false; + is.read(reinterpret_cast(&f[1]), sizeof(f[1])); + if(!is.good()) + return false; + is.read(reinterpret_cast(&f[2]), sizeof(f[2])); + if(!is.good()) + return false; + points.push_back(Point(f[0], f[1], f[2])); + ++pos; + } + return true; +} + +bool fill_binary_triangles(std::istream& is, std::vector >& triangles, const std::size_t& nb_trs) +{ + int tr[7]; + std::size_t pos = 0; + while(pos < nb_trs) + { + for(int i = 0; i < 7; ++i) + { + is.read(reinterpret_cast(&tr[i]), sizeof(tr[i])); + if(!is.good()) + return false; + } + std::array tri; + for(int i = 0; i < 3; ++i) + tri[i] = tr[i]; + triangles.push_back(tri); + ++pos; + } + return true; +} + +bool fill_binary_patch(std::istream& is, std::vector& patch, std::size_t size) +{ + int id = 0; + std::size_t pos = 0; + while(pos < size) + { + is.read(reinterpret_cast(&id), sizeof(int)); + if(!is.good()) + return false; + patch.push_back(id); + ++pos; + } + return true; +} + +template +bool build_binary_surf_patch(DuplicatedPointsOutIterator& out, + std::vector& output, + std::vector& points, + const std::vector >& polygons, + const std::vector& patch, + const std::size_t i) +{ + namespace PMP = CGAL::Polygon_mesh_processing; + typedef std::array Triangle_ind; + std::vector triangles; + triangles.reserve(patch.size()); + for(const std::size_t& id : patch) + { + triangles.push_back(polygons[id]); + } + if (!PMP::is_polygon_soup_a_polygon_mesh(triangles)) + { + std::cout << "Orientation of patch #" << (i + 1) << "..."; + std::cout.flush(); + + const std::size_t nbp_init = points.size(); + bool no_duplicates = + PMP::orient_polygon_soup(points, triangles);//returns false if some points + //were duplicated + + std::cout << "\rOrientation of patch #" << (i + 1) << " done"; + + if(!no_duplicates) //collect duplicates + { + for (std::size_t i = nbp_init; i < points.size(); ++i) + *out++ = points[i]; + std::cout << " (non manifold -> " + << (points.size() - nbp_init) << " duplicated vertices)"; + } + std::cout << "." << std::endl; + } + + Mesh& mesh = output[i]; + + PMP::internal::PS_to_PM_converter, std::vector > converter(points, triangles); + converter(mesh, false/*insert_isolated_vertices*/); + + CGAL_assertion(PMP::remove_isolated_vertices(mesh) == 0); + CGAL_assertion(is_valid_polygon_mesh(mesh)); + return true; +} }//end internal }//end IO @@ -292,72 +399,174 @@ bool read_surf(std::istream& input, std::vector& output, std::vector points; std::string line; - std::istringstream iss; std::size_t nb_vertices(0); std::vector materials; //ignore header int material_id = 0; int nb_patches = 0; - while(std::getline(input, line)) + if(!std::getline(input, line)) + return false; + bool binary = (line.find("BINARY") != std::string::npos); + if(!binary) { - if (line_starts_with(line, "Materials")) - { - if(!IO::internal::treat_surf_materials(input, materials, material_id)) - return false; - } - - //get grid box - if (line_starts_with(line, "GridBox")) - { - IO::internal::treat_surf_grid_box(line, grid_box); - } - - //get grid size - if (line_starts_with(line, "GridSize")) - { - IO::internal::treat_surf_grid_size(line, grid_size); - } - - //get number of vertices - if (line_starts_with(line, "Vertices")) - { - IO::internal::treat_surf_vertices(input, line, nb_vertices, points); - } - - //get number of patches - if (line_starts_with(line, "Patches")) - { - IO::internal::get_surf_patches(line, nb_patches, metadata, output); - break; - } - } - - for(int i=0; i < nb_patches; ++i) - { - std::size_t nb_triangles(0); - //get metada while(std::getline(input, line)) { - if (line_starts_with(line, "InnerRegion")) + if (line_starts_with(line, "Materials")) { - IO::internal::treat_surf_inner_region(input, line, materials, metadata, i); + if(!IO::internal::treat_surf_materials(input, materials, material_id)) + return false; } - if (line_starts_with(line, "Triangles")) + + //get grid box + if (line_starts_with(line, "GridBox")) { - IO::internal::treat_surf_triangles(line, nb_triangles); + IO::internal::treat_surf_grid_box(line, grid_box); + } + + //get grid size + if (line_starts_with(line, "GridSize")) + { + IO::internal::treat_surf_grid_size(line, grid_size); + } + + //get number of vertices + if (line_starts_with(line, "Vertices")) + { + IO::internal::treat_surf_vertices(input, line, nb_vertices, points); + } + + //get number of patches + if (line_starts_with(line, "Patches")) + { + IO::internal::get_surf_patches(line, nb_patches, metadata, output); break; } } - //connect triangles + for(int i=0; i < nb_patches; ++i) + { + std::size_t nb_triangles(0); + //get metada + while(std::getline(input, line)) + { + if (line_starts_with(line, "InnerRegion")) + { + IO::internal::treat_surf_inner_region(input, line, materials, metadata, i); + } + if (line_starts_with(line, "Triangles")) + { + IO::internal::treat_surf_triangles(line, nb_triangles); + break; + } + } + //connect triangles + typedef std::array Triangle_ind; + std::vector polygons; + IO::internal::connect_surf_triangles(input, nb_triangles, polygons); + + //build patch + IO::internal::build_surf_patch(out, output, points, polygons, i); + } // end loop on patches + } + else + { + int nTriangles = 0; typedef std::array Triangle_ind; - std::vector polygons; - IO::internal::connect_surf_triangles(input, nb_triangles, polygons); + std::vector triangles; + std::vector tr_per_patches; + int patch_counter = -1; + while(std::getline(input, line)) + { + //get nb vertices + if (line_starts_with(line, "nVertices")) + { + std::istringstream iss; + iss.str(line); + std::string dump; + if(!(iss >> dump >> nb_vertices)) + return false; + } + //get nb triangles + if (line_starts_with(line, "nTriangles")) + { + std::istringstream iss; + iss.str(line); + std::string dump; + if(!(iss >> dump >> nTriangles)) + return false; + std::cout<> dump >> dump >> nb_patches)) + return false; + std::cout<> dump >> dump >> nb_tr)) + return false; + tr_per_patches.push_back(nb_tr); + ++patch_counter; + } + else + { + std::cerr<<"Error in input file. Incoherent number of materials."< patch; + IO::internal::fill_binary_patch(input, patch, tr_per_patches[patch_counter]); + IO::internal::build_binary_surf_patch(out, output, points, triangles, patch, patch_counter++); + } + } + } return true; } From 8a53e00155adf596c214b520b727b60b4c68eb0b Mon Sep 17 00:00:00 2001 From: Andreas Fabri Date: Fri, 15 May 2020 15:27:02 +0100 Subject: [PATCH 400/568] polish --- Triangulation_2/include/CGAL/Constrained_triangulation_2.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Triangulation_2/include/CGAL/Constrained_triangulation_2.h b/Triangulation_2/include/CGAL/Constrained_triangulation_2.h index 50c2d76c452..fde9ea2365a 100644 --- a/Triangulation_2/include/CGAL/Constrained_triangulation_2.h +++ b/Triangulation_2/include/CGAL/Constrained_triangulation_2.h @@ -665,8 +665,8 @@ insert(const Point& a, Locate_type lt, Face_handle loc, int li) it != finite_edges_end(); ++it){ if(is_constrained(*it)){ - constrained_edges.push_back(std::make_pair(it->first->vertex(cw(it->second)), - it->first->vertex(ccw(it->second)))); + constrained_edges.emplace_back(it->first->vertex(cw(it->second)), + it->first->vertex(ccw(it->second))); } } } @@ -683,7 +683,7 @@ insert(const Point& a, Locate_type lt, Face_handle loc, int li) va = Triangulation::insert(a,lt,loc,li); if(one_dimensional && (dimension() == 2)){ - for(const std::pair vp : constrained_edges){ + for(const std::pair& vp : constrained_edges){ Face_handle fh; int i; if(this->is_edge(vp.first, vp.second, fh,i)){ From a7ccc80f18d7aa239bb17ab2490aba25453fd409 Mon Sep 17 00:00:00 2001 From: Marc Glisse Date: Sun, 17 May 2020 11:42:10 +0200 Subject: [PATCH 401/568] comparisons for MP_Float --- Number_types/include/CGAL/MP_Float.h | 47 +++++++++++++--------------- 1 file changed, 22 insertions(+), 25 deletions(-) diff --git a/Number_types/include/CGAL/MP_Float.h b/Number_types/include/CGAL/MP_Float.h index 56e22b7e39b..b0a161837c1 100644 --- a/Number_types/include/CGAL/MP_Float.h +++ b/Number_types/include/CGAL/MP_Float.h @@ -27,6 +27,7 @@ #include #include #include +#include // MP_Float : multiprecision scaled integers. @@ -106,7 +107,13 @@ MP_Float operator*(const MP_Float &a, const MP_Float &b); MP_Float operator%(const MP_Float &a, const MP_Float &b); -class MP_Float +class MP_Float : boost::totally_ordered1 > +#endif + > { public: typedef short limb; @@ -223,6 +230,20 @@ public: MP_Float& operator*=(const MP_Float &a) { return *this = *this * a; } MP_Float& operator%=(const MP_Float &a) { return *this = *this % a; } + friend bool operator<(const MP_Float &a, const MP_Float &b) + { return INTERN_MP_FLOAT::compare(a, b) == SMALLER; } + + friend bool operator==(const MP_Float &a, const MP_Float &b) + { return (a.v == b.v) && (a.v.empty() || (a.exp == b.exp)); } + +#ifdef _MSC_VER + // Needed because without /permissive-, it makes hidden friends visible (operator== from Quotient) + friend bool operator==(const MP_Float &a, int b) + { return a == MP_Float(b); } + friend bool operator==(const MP_Float &a, double b) + { return a == MP_Float(b); } +#endif + exponent_type max_exp() const { return exponent_type(v.size()) + exp; @@ -365,30 +386,6 @@ inline void swap(MP_Float &m, MP_Float &n) { m.swap(n); } -inline -bool operator<(const MP_Float &a, const MP_Float &b) -{ return INTERN_MP_FLOAT::compare(a, b) == SMALLER; } - -inline -bool operator>(const MP_Float &a, const MP_Float &b) -{ return b < a; } - -inline -bool operator>=(const MP_Float &a, const MP_Float &b) -{ return ! (a < b); } - -inline -bool operator<=(const MP_Float &a, const MP_Float &b) -{ return ! (a > b); } - -inline -bool operator==(const MP_Float &a, const MP_Float &b) -{ return (a.v == b.v) && (a.v.empty() || (a.exp == b.exp)); } - -inline -bool operator!=(const MP_Float &a, const MP_Float &b) -{ return ! (a == b); } - MP_Float approximate_sqrt(const MP_Float &d); From 3a2b25062679fdf299cc146e39db093b6bf16e8d Mon Sep 17 00:00:00 2001 From: Laurent Rineau Date: Mon, 18 May 2020 11:43:59 +0200 Subject: [PATCH 402/568] Fix a warning https://cgal.geometryfactory.com/CGAL/testsuite/CGAL-5.1-Ic-152/Installation/TestReport_Friedrich_Ubuntu-gcc-7.gz ``` CMake Warning at /home/gimeno/foutoir/cgal_root/CGAL-5.1-Ic-152/cmake/modules/CGAL_enable_end_of_configuration_hook.cmake:99 (message): ======================================================================= CGAL performance notice: The variable CMAKE_BUILD_TYPE is set to "". For performance reasons, you should set CMAKE_BUILD_TYPE to "Release". Set CGAL_DO_NOT_WARN_ABOUT_CMAKE_BUILD_TYPE to TRUE if you want to disable this warning. ======================================================================= Call Stack (most recent call first): CMakeLists.txt:9223372036854775807 (CGAL_run_at_the_end_of_configuration) ``` --- Installation/test/Installation/CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Installation/test/Installation/CMakeLists.txt b/Installation/test/Installation/CMakeLists.txt index cbb6b6b9681..4c65d534f84 100644 --- a/Installation/test/Installation/CMakeLists.txt +++ b/Installation/test/Installation/CMakeLists.txt @@ -127,7 +127,7 @@ function(CGAL_installation_test_find_package_version mode) file(MAKE_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/test_find_package_version_${mode}) configure_file(test_find_package.cmake.in ${CMAKE_CURRENT_BINARY_DIR}/test_find_package_version_${mode}/CMakeLists.txt) add_test(NAME test_find_package_version_${mode} - COMMAND ${CMAKE_COMMAND} -S ${CMAKE_CURRENT_BINARY_DIR}/test_find_package_version_${mode} -B ${CMAKE_CURRENT_BINARY_DIR}/build-test_find_package_version_${mode}) + COMMAND ${CMAKE_COMMAND} -S ${CMAKE_CURRENT_BINARY_DIR}/test_find_package_version_${mode} -B ${CMAKE_CURRENT_BINARY_DIR}/build-test_find_package_version_${mode} -DCGAL_DO_NOT_WARN_ABOUT_CMAKE_BUILD_TYPE=ON) cgal_setup_test_properties(test_find_package_version_${mode}) endfunction() From 9af250625b29b40e9a22f6123c6a7c52a334bc30 Mon Sep 17 00:00:00 2001 From: Maxime Gimeno Date: Wed, 6 May 2020 17:02:32 +0200 Subject: [PATCH 403/568] clear() actually removes the property_maps --- .../include/CGAL/Surface_mesh/Surface_mesh.h | 37 +++++++++++++------ 1 file changed, 25 insertions(+), 12 deletions(-) diff --git a/Surface_mesh/include/CGAL/Surface_mesh/Surface_mesh.h b/Surface_mesh/include/CGAL/Surface_mesh/Surface_mesh.h index 96ef666128f..441ffdce437 100644 --- a/Surface_mesh/include/CGAL/Surface_mesh/Surface_mesh.h +++ b/Surface_mesh/include/CGAL/Surface_mesh/Surface_mesh.h @@ -2838,20 +2838,33 @@ void Surface_mesh

:: clear() { - vprops_.resize(0); - hprops_.resize(0); - eprops_.resize(0); - fprops_.resize(0); + vprops_.clear(); + hprops_.clear(); + eprops_.clear(); + fprops_.clear(); - vprops_.shrink_to_fit(); - hprops_.shrink_to_fit(); - eprops_.shrink_to_fit(); - fprops_.shrink_to_fit(); + vprops_.resize(0); + hprops_.resize(0); + eprops_.resize(0); + fprops_.resize(0); - removed_vertices_ = removed_edges_ = removed_faces_ = 0; - vertices_freelist_ = edges_freelist_ = faces_freelist_ = (std::numeric_limits::max)(); - garbage_ = false; - anonymous_property_ = 0; + vprops_.shrink_to_fit(); + hprops_.shrink_to_fit(); + eprops_.shrink_to_fit(); + fprops_.shrink_to_fit(); + + vconn_ = add_property_map("v:connectivity").first; + hconn_ = add_property_map("h:connectivity").first; + fconn_ = add_property_map("f:connectivity").first; + vpoint_ = add_property_map("v:point").first; + vremoved_ = add_property_map("v:removed", false).first; + eremoved_ = add_property_map("e:removed", false).first; + fremoved_ = add_property_map("f:removed", false).first; + + removed_vertices_ = removed_edges_ = removed_faces_ = 0; + vertices_freelist_ = edges_freelist_ = faces_freelist_ = (std::numeric_limits::max)(); + garbage_ = false; + anonymous_property_ = 0; } //----------------------------------------------------------------------------- From 380e7c579e70a1b02ae72d6430ff047d7928a852 Mon Sep 17 00:00:00 2001 From: Maxime Gimeno Date: Mon, 18 May 2020 12:25:28 +0200 Subject: [PATCH 404/568] Update doc and CHANGES.MD --- Installation/CHANGES.md | 4 ++++ Surface_mesh/include/CGAL/Surface_mesh/Surface_mesh.h | 2 ++ 2 files changed, 6 insertions(+) diff --git a/Installation/CHANGES.md b/Installation/CHANGES.md index dbc8910ac48..8656ae9466f 100644 --- a/Installation/CHANGES.md +++ b/Installation/CHANGES.md @@ -37,6 +37,10 @@ Release History is given an optional template parameter `ConcurrencyTag` (default value remains `CGAL::Sequential_tag` for backward compatibility). +### Surface Mesh + + - The function `CGAL::Surface_mesh::clear()` now removes all non-default properties instead of just emptying them. + Release 5.0 ----------- diff --git a/Surface_mesh/include/CGAL/Surface_mesh/Surface_mesh.h b/Surface_mesh/include/CGAL/Surface_mesh/Surface_mesh.h index 441ffdce437..ef546224112 100644 --- a/Surface_mesh/include/CGAL/Surface_mesh/Surface_mesh.h +++ b/Surface_mesh/include/CGAL/Surface_mesh/Surface_mesh.h @@ -1129,6 +1129,8 @@ public: } /// removes all vertices, halfedge, edges and faces. Collects garbage and clears all properties. + /// + /// After calling this method, the object is the same as a newly constructed object. The additional properties (such as normal vectors) are also removed and must thus be re-added if needed. void clear(); From 5a95259849117c78efdd8f01cb77bf06004222ab Mon Sep 17 00:00:00 2001 From: Simon Giraudot Date: Mon, 18 May 2020 13:40:31 +0200 Subject: [PATCH 405/568] Fix for cmake > 3.11 --- .../modules/CGAL_Boost_iostreams_support.cmake | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/Installation/cmake/modules/CGAL_Boost_iostreams_support.cmake b/Installation/cmake/modules/CGAL_Boost_iostreams_support.cmake index ae665d404fe..6a9680b5f0f 100644 --- a/Installation/cmake/modules/CGAL_Boost_iostreams_support.cmake +++ b/Installation/cmake/modules/CGAL_Boost_iostreams_support.cmake @@ -31,7 +31,14 @@ if(Boost_IOSTREAMS_FOUND AND NOT TARGET CGAL::Boost_iostreams_support) endif() add_library(CGAL::Boost_iostreams_support INTERFACE IMPORTED) - set_target_properties(CGAL::Boost_iostreams_support PROPERTIES - INTERFACE_COMPILE_DEFINITIONS "CGAL_LINKED_WITH_BOOST_IOSTREAMS" - INTERFACE_LINK_LIBRARIES "${Boost_LIB};${ZLIB_LIBS}") + + if(CMAKE_VERSION VERSION_LESS 3.11) + set_target_properties(CGAL::Boost_iostreams_support PROPERTIES + INTERFACE_COMPILE_DEFINITIONS "CGAL_LINKED_WITH_BOOST_IOSTREAMS" + INTERFACE_LINK_LIBRARIES "${Boost_LIB};${ZLIB_LIBS}") + else() + set_target_properties(CGAL::Boost_iostreams_support PROPERTIES + INTERFACE_COMPILE_DEFINITIONS "CGAL_LINKED_WITH_BOOST_IOSTREAMS") + target_link_libraries(CGAL::Boost_iostreams_support INTERFACE "${Boost_LIB};${ZLIB_LIBS}") + endif() endif() From b44c9917e4d1294b660ad89fdb85d19b5907e060 Mon Sep 17 00:00:00 2001 From: Simon Giraudot Date: Thu, 16 Apr 2020 10:44:34 +0200 Subject: [PATCH 406/568] WIP: enhance remove outliers --- .../include/CGAL/remove_outliers.h | 90 +++++++++++++++---- 1 file changed, 73 insertions(+), 17 deletions(-) diff --git a/Point_set_processing_3/include/CGAL/remove_outliers.h b/Point_set_processing_3/include/CGAL/remove_outliers.h index 611269da396..0669a93eb66 100644 --- a/Point_set_processing_3/include/CGAL/remove_outliers.h +++ b/Point_set_processing_3/include/CGAL/remove_outliers.h @@ -17,6 +17,8 @@ #include #include +#include +#include #include #include #include @@ -24,10 +26,16 @@ #include #include +#include + #include #include #include +#ifdef CGAL_LINKED_WITH_TBB +#include +#endif + namespace CGAL { @@ -132,7 +140,8 @@ compute_avg_knn_sq_distance_3( account; if `threshold_distance=0` only `threshold_percent` is taken into account. */ -template typename PointRange::iterator @@ -178,53 +187,100 @@ remove_outliers( CGAL_point_set_processing_precondition(threshold_percent >= 0 && threshold_percent <= 100); + CGAL::Real_timer t; + t.start(); + Neighbor_query neighbor_query (points, point_map); + t.stop(); + std::cerr << "Building kd-tree = " << t.time() << std::endl; + t.reset(); + + t.start(); std::size_t nb_points = points.size(); // iterate over input points and add them to multimap sorted by distance to k - std::multimap sorted_points; - std::size_t nb = 0; - for(const value_type& vt : points) - { - FT sq_distance = internal::compute_avg_knn_sq_distance_3( - get(point_map, vt), - neighbor_query, k, neighbor_radius); - sorted_points.insert( std::make_pair(sq_distance, vt) ); - if (callback && !callback ((nb+1) / double(nb_points))) - return points.end(); - ++ nb; - } + std::vector > sorted_points; + sorted_points.reserve (nb_points); + for (iterator it = points.begin(); it != points.end(); ++ it) + sorted_points.push_back(std::make_pair (0, it)); + + t.stop(); + std::cerr << "Copies = " << t.time() << std::endl; + t.reset(); + + Point_set_processing_3::internal::Callback_wrapper + callback_wrapper (callback, nb_points); + + t.start(); + + CGAL::for_each + (sorted_points, + [&](std::pair& p) -> bool + { + if (callback_wrapper.interrupted()) + return false; + + p.first = internal::compute_avg_knn_sq_distance_3( + get(point_map, *(p.second)), + neighbor_query, k, neighbor_radius); + + ++ callback_wrapper.advancement(); + return true; + }); + + t.stop(); + std::cerr << "Queries = " << t.time() << std::endl; + t.reset(); + + t.start(); + +#ifdef CGAL_LINKED_WITH_TBB + if (std::is_same::value) + tbb::parallel_sort (sorted_points.begin(), sorted_points.end()); + else +#endif + std::sort (sorted_points.begin(), sorted_points.end()); + + t.stop(); + std::cerr << "Sort = " << t.time() << std::endl; + t.reset(); + + t.start(); // Replaces [points.begin(), points.end()) range by the multimap content. // Returns the iterator after the (100-threshold_percent) % best points. typename PointRange::iterator first_point_to_remove = points.begin(); typename PointRange::iterator dst = points.begin(); int first_index_to_remove = int(double(sorted_points.size()) * ((100.0-threshold_percent)/100.0)); - typename std::multimap::iterator src; + typename std::vector >::iterator src; int index; for (src = sorted_points.begin(), index = 0; src != sorted_points.end(); ++src, ++index) { - *dst++ = src->second; + *dst++ = *src->second; if (index <= first_index_to_remove || src->first < threshold_distance * threshold_distance) first_point_to_remove = dst; } + t.stop(); + std::cerr << "Copies = " << t.time() << std::endl; + t.reset(); + return first_point_to_remove; } /// \cond SKIP_IN_MANUAL // variant with default NP -template +template typename PointRange::iterator remove_outliers( PointRange& points, unsigned int k) ///< number of neighbors. { - return remove_outliers (points, k, CGAL::Point_set_processing_3::parameters::all_default(points)); + return remove_outliers (points, k, CGAL::Point_set_processing_3::parameters::all_default(points)); } /// \endcond From 82479e780bdaeb4c7257a3a1593f2e68e638d24e Mon Sep 17 00:00:00 2001 From: Simon Giraudot Date: Thu, 16 Apr 2020 12:58:42 +0200 Subject: [PATCH 407/568] Better remove outliers using partition and nth_element --- .../include/CGAL/remove_outliers.h | 74 ++++++------------- 1 file changed, 21 insertions(+), 53 deletions(-) diff --git a/Point_set_processing_3/include/CGAL/remove_outliers.h b/Point_set_processing_3/include/CGAL/remove_outliers.h index 0669a93eb66..bedeca84cea 100644 --- a/Point_set_processing_3/include/CGAL/remove_outliers.h +++ b/Point_set_processing_3/include/CGAL/remove_outliers.h @@ -32,10 +32,6 @@ #include #include -#ifdef CGAL_LINKED_WITH_TBB -#include -#endif - namespace CGAL { @@ -187,33 +183,19 @@ remove_outliers( CGAL_point_set_processing_precondition(threshold_percent >= 0 && threshold_percent <= 100); - CGAL::Real_timer t; - t.start(); - Neighbor_query neighbor_query (points, point_map); - t.stop(); - std::cerr << "Building kd-tree = " << t.time() << std::endl; - t.reset(); - - t.start(); std::size_t nb_points = points.size(); // iterate over input points and add them to multimap sorted by distance to k std::vector > sorted_points; sorted_points.reserve (nb_points); for (iterator it = points.begin(); it != points.end(); ++ it) - sorted_points.push_back(std::make_pair (0, it)); - - t.stop(); - std::cerr << "Copies = " << t.time() << std::endl; - t.reset(); + sorted_points.push_back(std::make_pair (FT(0), it)); Point_set_processing_3::internal::Callback_wrapper callback_wrapper (callback, nb_points); - t.start(); - CGAL::for_each (sorted_points, [&](std::pair& p) -> bool @@ -229,47 +211,33 @@ remove_outliers( return true; }); - t.stop(); - std::cerr << "Queries = " << t.time() << std::endl; - t.reset(); + std::size_t first_index_to_remove = std::size_t(double(sorted_points.size()) * ((100.0-threshold_percent)/100.0)); - t.start(); + typename std::vector >::iterator f2r + = sorted_points.begin(); -#ifdef CGAL_LINKED_WITH_TBB - if (std::is_same::value) - tbb::parallel_sort (sorted_points.begin(), sorted_points.end()); - else -#endif - std::sort (sorted_points.begin(), sorted_points.end()); + if (threshold_distance != FT(0)) + f2r = std::partition (sorted_points.begin(), sorted_points.end(), + [&threshold_distance](const std::pair& p) -> bool + { + return p.first < threshold_distance * threshold_distance; + }); - t.stop(); - std::cerr << "Sort = " << t.time() << std::endl; - t.reset(); - - t.start(); - - // Replaces [points.begin(), points.end()) range by the multimap content. - // Returns the iterator after the (100-threshold_percent) % best points. - typename PointRange::iterator first_point_to_remove = points.begin(); - typename PointRange::iterator dst = points.begin(); - int first_index_to_remove = int(double(sorted_points.size()) * ((100.0-threshold_percent)/100.0)); - typename std::vector >::iterator src; - int index; - for (src = sorted_points.begin(), index = 0; - src != sorted_points.end(); - ++src, ++index) + if (std::distance (sorted_points.begin(), f2r) < first_index_to_remove) { - *dst++ = *src->second; - if (index <= first_index_to_remove || - src->first < threshold_distance * threshold_distance) - first_point_to_remove = dst; + std::nth_element (f2r, + sorted_points.begin() + first_index_to_remove, + sorted_points.end()); + f2r = sorted_points.begin() + first_index_to_remove; } - t.stop(); - std::cerr << "Copies = " << t.time() << std::endl; - t.reset(); + // Replaces [points.begin(), points.end()) range by the sorted content. + iterator it = points.begin(); + for (const auto& p : sorted_points) + *it++ = *p.second; - return first_point_to_remove; + // Returns the iterator on the first point to remove + return f2r->second; } /// \cond SKIP_IN_MANUAL From 1772709b94c9e472b55d6fde239a0b795e0cff56 Mon Sep 17 00:00:00 2001 From: Simon Giraudot Date: Thu, 16 Apr 2020 13:55:24 +0200 Subject: [PATCH 408/568] Update remove_outliers with new API --- .../remove_outliers_example.cpp | 2 +- .../Point_set_processing_3/remove_outliers_test.cpp | 6 +++--- .../tutorial_example.cpp | 7 ++++--- .../Point_set/Point_set_outliers_removal_plugin.cpp | 13 +++++++------ 4 files changed, 15 insertions(+), 13 deletions(-) diff --git a/Point_set_processing_3/examples/Point_set_processing_3/remove_outliers_example.cpp b/Point_set_processing_3/examples/Point_set_processing_3/remove_outliers_example.cpp index 89dd118252b..ea7827c82b8 100644 --- a/Point_set_processing_3/examples/Point_set_processing_3/remove_outliers_example.cpp +++ b/Point_set_processing_3/examples/Point_set_processing_3/remove_outliers_example.cpp @@ -39,7 +39,7 @@ int main(int argc, char*argv[]) // FIRST OPTION // // I don't know the ratio of outliers present in the point set std::vector::iterator first_to_remove - = CGAL::remove_outliers + = CGAL::remove_outliers (points, nb_neighbors, CGAL::parameters::threshold_percent (100.). // No limit on the number of outliers to remove diff --git a/Point_set_processing_3/test/Point_set_processing_3/remove_outliers_test.cpp b/Point_set_processing_3/test/Point_set_processing_3/remove_outliers_test.cpp index 474d2aa23ac..aa8e5be878a 100644 --- a/Point_set_processing_3/test/Point_set_processing_3/remove_outliers_test.cpp +++ b/Point_set_processing_3/test/Point_set_processing_3/remove_outliers_test.cpp @@ -50,8 +50,9 @@ void test_avg_knn_sq_distance(std::deque& points, // input point set << nb_neighbors_remove_outliers << ")...\n"; // Removes outliers using erase-remove idiom - points.erase(CGAL::remove_outliers(points, nb_neighbors_remove_outliers, - CGAL::parameters::threshold_percent(removed_percentage)), + points.erase(CGAL::remove_outliers + (points, nb_neighbors_remove_outliers, + CGAL::parameters::threshold_percent(removed_percentage)), points.end()); // Optional: after erase(), use Scott Meyer's "swap trick" to trim excess capacity @@ -139,4 +140,3 @@ int main(int argc, char * argv[]) std::cerr << "Tool returned " << accumulated_fatal_err << std::endl; return accumulated_fatal_err; } - diff --git a/Poisson_surface_reconstruction_3/examples/Poisson_surface_reconstruction_3/tutorial_example.cpp b/Poisson_surface_reconstruction_3/examples/Poisson_surface_reconstruction_3/tutorial_example.cpp index ff58e34ed31..594961714d4 100644 --- a/Poisson_surface_reconstruction_3/examples/Poisson_surface_reconstruction_3/tutorial_example.cpp +++ b/Poisson_surface_reconstruction_3/examples/Poisson_surface_reconstruction_3/tutorial_example.cpp @@ -63,9 +63,10 @@ int main(int argc, char*argv[]) /////////////////////////////////////////////////////////////////// //! [Outlier removal] - CGAL::remove_outliers (points, - 24, // Number of neighbors considered for evaluation - points.parameters().threshold_percent (5.0)); // Percentage of points to remove + CGAL::remove_outliers + (points, + 24, // Number of neighbors considered for evaluation + points.parameters().threshold_percent (5.0)); // Percentage of points to remove std::cout << points.number_of_removed_points() << " point(s) are outliers." << std::endl; diff --git a/Polyhedron/demo/Polyhedron/Plugins/Point_set/Point_set_outliers_removal_plugin.cpp b/Polyhedron/demo/Polyhedron/Plugins/Point_set/Point_set_outliers_removal_plugin.cpp index f5a217a91c9..c79b878dd32 100644 --- a/Polyhedron/demo/Polyhedron/Plugins/Point_set/Point_set_outliers_removal_plugin.cpp +++ b/Polyhedron/demo/Polyhedron/Plugins/Point_set/Point_set_outliers_removal_plugin.cpp @@ -40,12 +40,13 @@ struct Outlier_removal_functor { // Computes outliers *result = - CGAL::remove_outliers(*points, - nb_neighbors, - points->parameters(). - threshold_percent(removed_percentage). - threshold_distance(distance_threshold). - callback (*(this->callback()))); + CGAL::remove_outliers + (*points, + nb_neighbors, + points->parameters(). + threshold_percent(removed_percentage). + threshold_distance(distance_threshold). + callback (*(this->callback()))); } }; From 79dbfbf14e6bc94268a0376f39ace81a0cafbfd3 Mon Sep 17 00:00:00 2001 From: Simon Giraudot Date: Thu, 16 Apr 2020 13:55:38 +0200 Subject: [PATCH 409/568] Update doc of remove_outliers --- .../Point_set_processing_3/Point_set_processing_3.txt | 11 ++++++----- Point_set_processing_3/include/CGAL/remove_outliers.h | 6 +++++- 2 files changed, 11 insertions(+), 6 deletions(-) diff --git a/Point_set_processing_3/doc/Point_set_processing_3/Point_set_processing_3.txt b/Point_set_processing_3/doc/Point_set_processing_3/Point_set_processing_3.txt index 2c9af7219d1..6cb72a014bf 100644 --- a/Point_set_processing_3/doc/Point_set_processing_3/Point_set_processing_3.txt +++ b/Point_set_processing_3/doc/Point_set_processing_3/Point_set_processing_3.txt @@ -643,11 +643,12 @@ computed and stored as colors in a PLY file: \section Point_set_processing_3OutlierRemoval Outlier Removal -Function `remove_outliers()` deletes a user-specified fraction -of outliers from an input point set. More specifically, it sorts the -input points in increasing order of average squared distances to their -nearest neighbors and deletes the points with largest value. The user -can either specify a fixed number of nearest neighbors or a fixed +Function `remove_outliers()` deletes a user-specified fraction of +outliers from an input point set. More specifically, it partitions the +input points with respect to the average squared distances to their +nearest neighbors and deletes the points with largest value, either +partitionning with a threshold or removing a fixed percentage. The +user can either specify a fixed number of nearest neighbors or a fixed spherical neighborhood radius. \subsection Point_set_processing_3Example_outlier_removal Example diff --git a/Point_set_processing_3/include/CGAL/remove_outliers.h b/Point_set_processing_3/include/CGAL/remove_outliers.h index bedeca84cea..38f756a2d48 100644 --- a/Point_set_processing_3/include/CGAL/remove_outliers.h +++ b/Point_set_processing_3/include/CGAL/remove_outliers.h @@ -88,7 +88,9 @@ compute_avg_knn_sq_distance_3( \ingroup PkgPointSetProcessing3Algorithms Removes outliers: - computes average squared distance to the nearest neighbors, - - and sorts the points in increasing order of average distance. + - and partitions the points either using a threshold on the of + average distance or selecting a fixed percentage of points with + the highest average distances This method modifies the order of input points so as to pack all remaining points first, and returns an iterator over the first point to remove (see erase-remove idiom). @@ -96,6 +98,8 @@ compute_avg_knn_sq_distance_3( \pre `k >= 2` + \tparam ConcurrencyTag enables sequential versus parallel algorithm. Possible values are `Sequential_tag`, + `Parallel_tag`, and `Parallel_if_available_tag`. \tparam PointRange is a model of `Range`. The value type of its iterator is the key type of the named parameter `point_map`. From eb34b655fa8352f12f4df0aa35894c1c4819a163 Mon Sep 17 00:00:00 2001 From: Simon Giraudot Date: Thu, 16 Apr 2020 15:40:49 +0200 Subject: [PATCH 410/568] Fix outlier removal output --- .../remove_outliers_example.cpp | 2 +- .../include/CGAL/remove_outliers.h | 34 +++++++++++-------- 2 files changed, 21 insertions(+), 15 deletions(-) diff --git a/Point_set_processing_3/examples/Point_set_processing_3/remove_outliers_example.cpp b/Point_set_processing_3/examples/Point_set_processing_3/remove_outliers_example.cpp index ea7827c82b8..579829b2b4c 100644 --- a/Point_set_processing_3/examples/Point_set_processing_3/remove_outliers_example.cpp +++ b/Point_set_processing_3/examples/Point_set_processing_3/remove_outliers_example.cpp @@ -55,7 +55,7 @@ int main(int argc, char*argv[]) // I know the ratio of outliers present in the point set const double removed_percentage = 5.0; // percentage of points to remove - points.erase(CGAL::remove_outliers + points.erase(CGAL::remove_outliers (points, nb_neighbors, CGAL::parameters::threshold_percent(removed_percentage). // Minimum percentage to remove diff --git a/Point_set_processing_3/include/CGAL/remove_outliers.h b/Point_set_processing_3/include/CGAL/remove_outliers.h index 38f756a2d48..9122aa818fd 100644 --- a/Point_set_processing_3/include/CGAL/remove_outliers.h +++ b/Point_set_processing_3/include/CGAL/remove_outliers.h @@ -171,9 +171,6 @@ remove_outliers( typedef typename PointRange::iterator iterator; typedef typename iterator::value_type value_type; - // actual type of input points - typedef typename std::iterator_traits::value_type Enriched_point; - // types for K nearest neighbors search structure typedef Point_set_processing_3::internal::Neighbor_query Neighbor_query; @@ -192,23 +189,23 @@ remove_outliers( std::size_t nb_points = points.size(); // iterate over input points and add them to multimap sorted by distance to k - std::vector > sorted_points; + std::vector > sorted_points; sorted_points.reserve (nb_points); - for (iterator it = points.begin(); it != points.end(); ++ it) - sorted_points.push_back(std::make_pair (FT(0), it)); + for (const value_type& p : points) + sorted_points.push_back(std::make_pair (FT(0), p)); Point_set_processing_3::internal::Callback_wrapper callback_wrapper (callback, nb_points); CGAL::for_each (sorted_points, - [&](std::pair& p) -> bool + [&](std::pair& p) -> bool { if (callback_wrapper.interrupted()) return false; p.first = internal::compute_avg_knn_sq_distance_3( - get(point_map, *(p.second)), + get(point_map, p.second), neighbor_query, k, neighbor_radius); ++ callback_wrapper.advancement(); @@ -217,12 +214,12 @@ remove_outliers( std::size_t first_index_to_remove = std::size_t(double(sorted_points.size()) * ((100.0-threshold_percent)/100.0)); - typename std::vector >::iterator f2r + typename std::vector >::iterator f2r = sorted_points.begin(); if (threshold_distance != FT(0)) f2r = std::partition (sorted_points.begin(), sorted_points.end(), - [&threshold_distance](const std::pair& p) -> bool + [&threshold_distance](const std::pair& p) -> bool { return p.first < threshold_distance * threshold_distance; }); @@ -236,12 +233,21 @@ remove_outliers( } // Replaces [points.begin(), points.end()) range by the sorted content. - iterator it = points.begin(); - for (const auto& p : sorted_points) - *it++ = *p.second; + iterator pit = points.begin(); + iterator out = points.begin(); + + for (auto sit = sorted_points.begin(); sit != sorted_points.end(); ++ sit) + { + *pit = sit->second; + if (sit == f2r) + out = pit; + ++ pit; + } + + callback_wrapper.join(); // Returns the iterator on the first point to remove - return f2r->second; + return out; } /// \cond SKIP_IN_MANUAL From 700631da335afde36f1a32e7dde863376b5c9f6a Mon Sep 17 00:00:00 2001 From: Simon Giraudot Date: Mon, 18 May 2020 13:56:31 +0200 Subject: [PATCH 411/568] Update CHANGES.md --- Installation/CHANGES.md | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/Installation/CHANGES.md b/Installation/CHANGES.md index 2f973b6c657..0a30e188894 100644 --- a/Installation/CHANGES.md +++ b/Installation/CHANGES.md @@ -24,6 +24,11 @@ Release History ### Point Set Processing - Add a function `CGAL::cluster_point_set()` that segments a point cloud into connected components based on a distance threshold. + - **Breaking change:** `CGAL::remove_outliers()` has been + parallelized and thus has a new template parameter + `ConcurrencyTag`. To update your code simply add as first template + parameter `CGAL::Sequential_tag` or `CGAL::Parallel_tag` when + calling this function. ### 2D Triangulations - Add function `split_subconstraint_graph_into_constraints()` to From d2c88507e7d30bb4403f41a434f6af505f1c74ab Mon Sep 17 00:00:00 2001 From: Jane Tournois Date: Mon, 18 May 2020 14:50:35 +0200 Subject: [PATCH 412/568] remove commented code --- .../Remeshing_triangulation_3.h | 96 ------------------- 1 file changed, 96 deletions(-) diff --git a/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/Remeshing_triangulation_3.h b/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/Remeshing_triangulation_3.h index ecb52808729..635b4e2d5c4 100644 --- a/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/Remeshing_triangulation_3.h +++ b/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/Remeshing_triangulation_3.h @@ -81,102 +81,6 @@ public: using Base::Base; }; -//namespace internal -//{ -//template -//struct Vertex_converter -//{ -// //This operator is used to create the vertex from v_src. -// typename TDS_tgt::Vertex operator()(const typename TDS_src::Vertex& v_src) const -// { -// typedef typename CGAL::Kernel_traits< -// typename TDS_src::Vertex::Point>::Kernel GT_src; -// typedef typename CGAL::Kernel_traits< -// typename TDS_tgt::Vertex::Point>::Kernel GT_tgt; -// CGAL::Cartesian_converter conv; -// -// typedef typename TDS_tgt::Vertex::Point Tgt_point; -// -// typename TDS_tgt::Vertex v_tgt; -// v_tgt.set_point(Tgt_point(conv(point(v_src.point())))); -// v_tgt.set_time_stamp(-1); -// v_tgt.set_dimension(3);//-1 if unset, 0,1,2, or 3 if set -// return v_tgt; -// } -// //This operator is meant to be used in case heavy data should transferred to v_tgt. -// void operator()(const typename TDS_src::Vertex& v_src, -// typename TDS_tgt::Vertex& v_tgt) const -// { -// typedef typename CGAL::Kernel_traits< -// typename TDS_src::Vertex::Point>::Kernel GT_src; -// typedef typename CGAL::Kernel_traits< -// typename TDS_tgt::Vertex::Point>::Kernel GT_tgt; -// CGAL::Cartesian_converter conv; -// -// typedef typename TDS_tgt::Vertex::Point Tgt_point; -// -// v_tgt.set_point(Tgt_point(conv(point(v_src.point())))); -// v_tgt.set_dimension(3);//v_src.info()); -// } -//}; -// -//template -//struct Cell_converter -//{ -// //This operator is used to create the cell from c_src. -// typename TDS_tgt::Cell operator()(const typename TDS_src::Cell& c_src) const -// { -// typename TDS_tgt::Cell c_tgt; -// c_tgt.set_subdomain_index(c_src.subdomain_index()); -// c_tgt.set_time_stamp(-1); -// return c_tgt; -// } -// //This operator is meant to be used in case heavy data should transferred to c_tgt. -// void operator()(const typename TDS_src::Cell& c_src, -// typename TDS_tgt::Cell& c_tgt) const -// { -// c_tgt.set_subdomain_index(c_src.subdomain_index()); -// } -//}; -// -//} -// -// -//template -//void build_remeshing_triangulation(const T3& tr, -// Remeshing_triangulation_3& remeshing_tr) -//{ -// typedef typename T3::Triangulation_data_structure Tds; -// typedef typename Remeshing_triangulation_3::Tds RTds; -// -// remeshing_tr.clear(); -// -// remeshing_tr.set_infinite_vertex( -// remeshing_tr.tds().copy_tds( -// tr.tds(), -// tr.infinite_vertex(), -// internal::Vertex_converter(), -// internal::Cell_converter())); -//} -// -//template -//void build_from_remeshing_triangulation( -// const Remeshing_triangulation_3& remeshing_tr, -// T3& tr) -//{ -// typedef typename T3::Triangulation_data_structure Tds; -// typedef typename Remeshing_triangulation_3::Tds RTds; -// -// tr.clear(); -// -// tr.set_infinite_vertex( -// tr.tds().copy_tds( -// remeshing_tr.tds(), -// remeshing_tr.infinite_vertex(), -// internal::Vertex_converter(), -// internal::Cell_converter())); -//} - }//end namespace Tetrahedral_remeshing }//end namespace CGAL From 47bcce0a1c612b465b6fd563f48b7b2032136b17 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9bastien=20Loriot?= Date: Wed, 13 May 2020 18:43:19 +0200 Subject: [PATCH 413/568] fix warning --- Point_set_processing_3/include/CGAL/remove_outliers.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Point_set_processing_3/include/CGAL/remove_outliers.h b/Point_set_processing_3/include/CGAL/remove_outliers.h index 9122aa818fd..ce5b7154879 100644 --- a/Point_set_processing_3/include/CGAL/remove_outliers.h +++ b/Point_set_processing_3/include/CGAL/remove_outliers.h @@ -224,7 +224,7 @@ remove_outliers( return p.first < threshold_distance * threshold_distance; }); - if (std::distance (sorted_points.begin(), f2r) < first_index_to_remove) + if (static_cast(std::distance (sorted_points.begin(), f2r)) < first_index_to_remove) { std::nth_element (f2r, sorted_points.begin() + first_index_to_remove, From 243a8b68c973cf97bf57aea559da3a1888a52d56 Mon Sep 17 00:00:00 2001 From: Andreas Fabri Date: Mon, 18 May 2020 15:27:59 +0100 Subject: [PATCH 414/568] Add using and typedef --- Triangulation_2/include/CGAL/Constrained_triangulation_2.h | 3 +++ 1 file changed, 3 insertions(+) diff --git a/Triangulation_2/include/CGAL/Constrained_triangulation_2.h b/Triangulation_2/include/CGAL/Constrained_triangulation_2.h index fde9ea2365a..3f3effd78cd 100644 --- a/Triangulation_2/include/CGAL/Constrained_triangulation_2.h +++ b/Triangulation_2/include/CGAL/Constrained_triangulation_2.h @@ -87,6 +87,7 @@ public: typedef typename Triangulation::size_type size_type; typedef typename Triangulation::Locate_type Locate_type; typedef typename Triangulation::All_faces_iterator All_faces_iterator; + typedef typename Triangulation::Finite_edges_iterator Finite_edges_iterator; typedef typename Triangulation::Face_circulator Face_circulator; typedef typename Triangulation::Edge_circulator Edge_circulator; typedef typename Triangulation::Vertex_circulator Vertex_circulator; @@ -129,6 +130,8 @@ public: using Triangulation::geom_traits; using Triangulation::all_faces_begin; using Triangulation::all_faces_end; + using Triangulation::finite_edges_begin; + using Triangulation::finite_edges_end; using Triangulation::side_of_oriented_circle; using Triangulation::is_infinite; using Triangulation::collinear_between; From 34538bcbeaebea87e640c11e713f3d924e59802d Mon Sep 17 00:00:00 2001 From: Jane Date: Tue, 19 May 2020 09:07:26 +0100 Subject: [PATCH 415/568] UPDATupdateE# (use "git push" to publish your local commits) --- .../CMakeCache.txt | 761 ------------------ .../init.cmake | 27 + .../setup | 4 +- 3 files changed, 30 insertions(+), 762 deletions(-) delete mode 100644 Maintenance/infrastructure/gauguin.geometryfactory.com/reference_platforms/x64_Cygwin-Windows10_MSVC2017-Debug-64bits/CMakeCache.txt create mode 100644 Maintenance/infrastructure/gauguin.geometryfactory.com/reference_platforms/x64_Cygwin-Windows10_MSVC2017-Debug-64bits/init.cmake diff --git a/Maintenance/infrastructure/gauguin.geometryfactory.com/reference_platforms/x64_Cygwin-Windows10_MSVC2017-Debug-64bits/CMakeCache.txt b/Maintenance/infrastructure/gauguin.geometryfactory.com/reference_platforms/x64_Cygwin-Windows10_MSVC2017-Debug-64bits/CMakeCache.txt deleted file mode 100644 index d21e9b70bb9..00000000000 --- a/Maintenance/infrastructure/gauguin.geometryfactory.com/reference_platforms/x64_Cygwin-Windows10_MSVC2017-Debug-64bits/CMakeCache.txt +++ /dev/null @@ -1,761 +0,0 @@ -# This is the CMakeCache file. -# For build in directory: c:/CGAL/reference_platforms/x64_Cygwin-Windows10_MSVC2017-Debug-64bits -# It was generated by CMake: C:/dev/CMake/bin/cmake.exe -# You can edit this file to change values found and used by cmake. -# If you do not want to change any of the values, simply exit the editor. -# If you do want to change a value, simply edit, save, and exit the editor. -# The syntax for the file is as follows: -# KEY:TYPE=VALUE -# KEY is the name of a variable in the cache. -# TYPE is a hint to GUIs for the type of VALUE, DO NOT EDIT TYPE!. -# VALUE is the current value for the KEY. - -######################## -# EXTERNAL cache entries -######################## - -//Build shared libraries -BUILD_SHARED_LIBS:BOOL=ON - -//Build the testing tree. -BUILD_TESTING:BOOL=OFF - -//Activate the debug messages of the script FindBoost -Boost_DEBUG:BOOL=OFF - -//Path to a file. -Boost_INCLUDE_DIR:PATH=C:/3rdPartyLibs/boost/boost_1_67_0 - -//Value Computed by CMake -CGAL_BINARY_DIR:STATIC=C:/CGAL/reference_platforms/x64_Cygwin-Windows10_MSVC2017-Debug-64bits - -//Link with static Boost libraries -CGAL_Boost_USE_STATIC_LIBS:BOOL=OFF - -//User-defined flags -CGAL_CXX_FLAGS:STRING= -D_CRT_SECURE_NO_DEPRECATE -D_SCL_SECURE_NO_DEPRECATE -D_CRT_SECURE_NO_WARNINGS -D_SCL_SECURE_NO_WARNINGS /fp:strict /fp:except- /wd4503 /bigobj - -//Dependencies for the target -CGAL_Core_LIB_DEPENDS:STATIC=general;C:/3rdPartyLibs/VC-64/gmp-5.0.1_and_mpfr-3.0.0/lib/libmpfr-4.lib;general;C:/3rdPartyLibs/VC-64/gmp-5.0.1_and_mpfr-3.0.0/lib/libgmp-10.lib;general;CGAL; - -//Set this to TRUE if you want to define or modify any of CMAKE_*_FLAGS. -// When this is FALSE, all the CMAKE_*_FLAGS flags are overriden -// with the values used when building the CGAL libs. For CGAL_*_flags -// (used for ADDITIONAL flags) , there is no need to set this to -// TRUE. -CGAL_DONT_OVERRIDE_CMAKE_FLAGS:BOOL=TRUE - -//Select to allow to preconfiguration of external libraries -CGAL_ENABLE_PRECONFIG:BOOL=ON - -//Enable the header only version of CGAL -CGAL_HEADER_ONLY:BOOL=OFF - -//The folder where CGAL user-side scripts will be installed, relative -// to CMAKE_INSTALL_PREFIX -CGAL_INSTALL_BIN_DIR:STRING=bin - -//The folder where CGAL CMake modules will be installed, relative -// to CMAKE_INSTALL_PREFIX -CGAL_INSTALL_CMAKE_DIR:STRING=lib/CGAL - -//The folder where CGAL documentation and license files will be -// installed, relative to CMAKE_INSTALL_PREFIX -CGAL_INSTALL_DOC_DIR:STRING=C:/Program Files (x86)/CGAL/share/doc/CGAL-4.9 - -//The folder where CGAL header files will be installed, relative -// to CMAKE_INSTALL_PREFIX -CGAL_INSTALL_INC_DIR:STRING=include - -//The folder where CGAL libraries will be installed, relative to -// CMAKE_INSTALL_PREFIX -CGAL_INSTALL_LIB_DIR:STRING=lib - -//The folder where manual pages for CGAL scripts will be installed, -// relative to CMAKE_INSTALL_PREFIX -CGAL_INSTALL_MAN_DIR:STRING=C:/Program Files (x86)/CGAL/share/man/man1 - -//Dependencies for the target -CGAL_ImageIO_LIB_DEPENDS:STATIC=general;C:/3rdPartyLibs/VC-64/gmp-5.0.1_and_mpfr-3.0.0/lib/libmpfr-4.lib;general;C:/3rdPartyLibs/VC-64/gmp-5.0.1_and_mpfr-3.0.0/lib/libgmp-10.lib;general;CGAL;general;C:/3rdPartyLibs/zlib-1.2.11/build_msvc2013/lib/zlib.lib; - -//Dependencies for the target -CGAL_LIB_DEPENDS:STATIC=general;C:/3rdPartyLibs/VC-64/gmp-5.0.1_and_mpfr-3.0.0/lib/libmpfr-4.lib;general;C:/3rdPartyLibs/VC-64/gmp-5.0.1_and_mpfr-3.0.0/lib/libgmp-10.lib; - -//Dependencies for the target -CGAL_Qt5_LIB_DEPENDS:STATIC=general;C:/3rdPartyLibs/VC-64/gmp-5.0.1_and_mpfr-3.0.0/lib/libmpfr-4.lib;general;C:/3rdPartyLibs/VC-64/gmp-5.0.1_and_mpfr-3.0.0/lib/libgmp-10.lib;general;Qt5::OpenGL;general;Qt5::Svg;general;CGAL;general;glu32;general;opengl32; - -//Value Computed by CMake -CGAL_SOURCE_DIR:STATIC=C:/CGAL/CGAL-4.9 - -//Path to a program. -CMAKE_AR:FILEPATH=CMAKE_AR-NOTFOUND - -//Build type: Release or Debug -CMAKE_BUILD_TYPE:STRING=Debug - -//Enable/Disable color output during build. -CMAKE_COLOR_MAKEFILE:BOOL=ON - -//Semicolon separated list of supported configuration types, only -// supports Debug, Release, MinSizeRel, and RelWithDebInfo, anything -// else will be ignored. -CMAKE_CONFIGURATION_TYPES:STRING=Debug;Release;MinSizeRel;RelWithDebInfo - -//User-defined flags -CMAKE_CXX_FLAGS:STRING=/DWIN32 /D_WINDOWS /W3 /GR /EHsc -D_CRT_SECURE_NO_DEPRECATE -D_SCL_SECURE_NO_DEPRECATE -D_CRT_SECURE_NO_WARNINGS -D_SCL_SECURE_NO_WARNINGS /fp:strict /fp:except- /wd4503 /bigobj /permissive- /std:c++latest - -//Flags used by the compiler during debug builds. -CMAKE_CXX_FLAGS_DEBUG:STRING=/D_DEBUG /MDd /Ob0 /Od /RTC1 - -//Flags used by the compiler during release builds for minimum -// size. -CMAKE_CXX_FLAGS_MINSIZEREL:STRING=/MD /O1 /Ob1 /DNDEBUG - -//Flags used by the compiler during release builds. -CMAKE_CXX_FLAGS_RELEASE:STRING=/MD /O2 /Ob2 /DCGAL_NDEBUG - -//Flags used by the compiler during release builds with debug info. -CMAKE_CXX_FLAGS_RELWITHDEBINFO:STRING=/MD /O2 /Ob1 /DNDEBUG - -//Libraries linked by default with all C++ applications. -CMAKE_CXX_STANDARD_LIBRARIES:STRING=kernel32.lib user32.lib gdi32.lib winspool.lib shell32.lib ole32.lib oleaut32.lib uuid.lib comdlg32.lib advapi32.lib - -//Flags used by the compiler during all build types. -CMAKE_C_FLAGS:STRING=/DWIN32 /D_WINDOWS /W3 - -//Flags used by the compiler during debug builds. -CMAKE_C_FLAGS_DEBUG:STRING=/D_DEBUG /MDd /Ob0 /Od /RTC1 - -//Flags used by the compiler during release builds for minimum -// size. -CMAKE_C_FLAGS_MINSIZEREL:STRING=/MD /O1 /Ob1 /DNDEBUG - -//Flags used by the compiler during release builds. -CMAKE_C_FLAGS_RELEASE:STRING=/MD /O2 /Ob2 /DCGAL_NDEBUG - -//Flags used by the compiler during release builds with debug info. -CMAKE_C_FLAGS_RELWITHDEBINFO:STRING=/MD /O2 /Ob1 /DNDEBUG - -//Libraries linked by default with all C applications. -CMAKE_C_STANDARD_LIBRARIES:STRING=kernel32.lib user32.lib gdi32.lib winspool.lib shell32.lib ole32.lib oleaut32.lib uuid.lib comdlg32.lib advapi32.lib - -//Flags used by the linker. -CMAKE_EXE_LINKER_FLAGS:STRING=/machine:x64 /INCREMENTAL:NO /DEBUG:NONE - -//Flags used by the linker during debug builds. -CMAKE_EXE_LINKER_FLAGS_DEBUG:STRING=/INCREMENTAL:NO /DEBUG:NONE - -//Flags used by the linker during release minsize builds. -CMAKE_EXE_LINKER_FLAGS_MINSIZEREL:STRING=/INCREMENTAL:NO /DEBUG:NONE - -//Flags used by the linker during release builds. -CMAKE_EXE_LINKER_FLAGS_RELEASE:STRING=/INCREMENTAL:NO /DEBUG:NONE - -//Flags used by the linker during Release with Debug Info builds. -CMAKE_EXE_LINKER_FLAGS_RELWITHDEBINFO:STRING=/INCREMENTAL:NO /DEBUG:NONE - -//user executables (bin) -CMAKE_INSTALL_BINDIR:PATH=bin - -//read-only architecture-independent data (DATAROOTDIR) -CMAKE_INSTALL_DATADIR:PATH= - -//read-only architecture-independent data root (share) -CMAKE_INSTALL_DATAROOTDIR:PATH=share - -//documentation root (DATAROOTDIR/doc/PROJECT_NAME) -CMAKE_INSTALL_DOCDIR:PATH= - -//C header files (include) -CMAKE_INSTALL_INCLUDEDIR:PATH=include - -//info documentation (DATAROOTDIR/info) -CMAKE_INSTALL_INFODIR:PATH= - -//object code libraries (lib) -CMAKE_INSTALL_LIBDIR:PATH=lib - -//program executables (libexec) -CMAKE_INSTALL_LIBEXECDIR:PATH=libexec - -//locale-dependent data (DATAROOTDIR/locale) -CMAKE_INSTALL_LOCALEDIR:PATH= - -//modifiable single-machine data (var) -CMAKE_INSTALL_LOCALSTATEDIR:PATH=var - -//man documentation (DATAROOTDIR/man) -CMAKE_INSTALL_MANDIR:PATH= - -//C header files for non-gcc (/usr/include) -CMAKE_INSTALL_OLDINCLUDEDIR:PATH=/usr/include - -//Install path prefix, prepended onto install directories. -CMAKE_INSTALL_PREFIX:PATH=C:/Program Files (x86)/CGAL - -//Run-time variable data (LOCALSTATEDIR/run) -CMAKE_INSTALL_RUNSTATEDIR:PATH= - -//system admin executables (sbin) -CMAKE_INSTALL_SBINDIR:PATH=sbin - -//modifiable architecture-independent data (com) -CMAKE_INSTALL_SHAREDSTATEDIR:PATH=com - -//read-only single-machine data (etc) -CMAKE_INSTALL_SYSCONFDIR:PATH=etc - -//Path to a program. -CMAKE_LINKER:FILEPATH=C:/Program Files (x86)/Microsoft Visual Studio/2017/Professional/VC/Tools/MSVC/14.11.25503/bin/HostX86/x64/link.exe - -//Flags used by the linker during the creation of modules. -CMAKE_MODULE_LINKER_FLAGS:STRING=/machine:x64 /DEBUG:NONE /INCREMENTAL:NO - -//Flags used by the linker during debug builds. -CMAKE_MODULE_LINKER_FLAGS_DEBUG:STRING= - -//Flags used by the linker during release minsize builds. -CMAKE_MODULE_LINKER_FLAGS_MINSIZEREL:STRING= - -//Flags used by the linker during release builds. -CMAKE_MODULE_LINKER_FLAGS_RELEASE:STRING= - -//Flags used by the linker during Release with Debug Info builds. -CMAKE_MODULE_LINKER_FLAGS_RELWITHDEBINFO:STRING= - -//Value Computed by CMake -CMAKE_PROJECT_NAME:STATIC=CGAL - -//RC compiler -CMAKE_RC_COMPILER:FILEPATH=rc - -//Flags for Windows Resource Compiler. -CMAKE_RC_FLAGS:STRING=/DWIN32 - -//Flags for Windows Resource Compiler during debug builds. -CMAKE_RC_FLAGS_DEBUG:STRING=/D_DEBUG - -//Flags for Windows Resource Compiler during release builds for -// minimum size. -CMAKE_RC_FLAGS_MINSIZEREL:STRING= - -//Flags for Windows Resource Compiler during release builds. -CMAKE_RC_FLAGS_RELEASE:STRING= - -//Flags for Windows Resource Compiler during release builds with -// debug info. -CMAKE_RC_FLAGS_RELWITHDEBINFO:STRING= - -//Flags used by the linker during the creation of dll's. -CMAKE_SHARED_LINKER_FLAGS:STRING=/machine:x64 /debug:NONE /INCREMENTAL:NO - -//Flags used by the linker during debug builds. -CMAKE_SHARED_LINKER_FLAGS_DEBUG:STRING= - -//Flags used by the linker during release minsize builds. -CMAKE_SHARED_LINKER_FLAGS_MINSIZEREL:STRING= - -//Flags used by the linker during release builds. -CMAKE_SHARED_LINKER_FLAGS_RELEASE:STRING= - -//Flags used by the linker during Release with Debug Info builds. -CMAKE_SHARED_LINKER_FLAGS_RELWITHDEBINFO:STRING= - -//If set, runtime paths are not added when installing shared libraries, -// but are added when building. -CMAKE_SKIP_INSTALL_RPATH:BOOL=OFF - -//If set, runtime paths are not added when using shared libraries. -CMAKE_SKIP_RPATH:BOOL=OFF - -//Flags used by the linker during the creation of static libraries. -CMAKE_STATIC_LINKER_FLAGS:STRING=/machine:x64 /debug:NONE /INCREMENTAL:NO - -//Flags used by the linker during debug builds. -CMAKE_STATIC_LINKER_FLAGS_DEBUG:STRING= - -//Flags used by the linker during release minsize builds. -CMAKE_STATIC_LINKER_FLAGS_MINSIZEREL:STRING= - -//Flags used by the linker during release builds. -CMAKE_STATIC_LINKER_FLAGS_RELEASE:STRING= - -//Flags used by the linker during Release with Debug Info builds. -CMAKE_STATIC_LINKER_FLAGS_RELWITHDEBINFO:STRING= - -//If this value is on, makefiles will be generated without the -// .SILENT directive, and all commands will be echoed to the console -// during the make. This is useful for debugging only. With Visual -// Studio IDE projects all commands are done without /nologo. -CMAKE_VERBOSE_MAKEFILE:BOOL=OFF - -//The directory containing the ESBTL header files WITHOUT the ESBTL -// prefix -ESBTL_INCLUDE_DIR:PATH=C:/3rdPartyLibs/esbtl/include - -//The directory containing the GMP header files -GMP_INCLUDE_DIR:PATH=C:/3rdPartyLibs/VC-64/gmp-5.0.1_and_mpfr-3.0.0/include - -//Path to the GMP library -GMP_LIBRARIES:FILEPATH=C:/3rdPartyLibs/VC-64/gmp-5.0.1_and_mpfr-3.0.0/lib/libgmp-10.lib - -GMP_LIBRARIES_DIR:FILEPATH=C:/3rdPartyLibs/VC-64/gmp-5.0.1_and_mpfr-3.0.0/lib - -//The directory containing the MPFR header files -MPFR_INCLUDE_DIR:PATH=C:/3rdPartyLibs/VC-64/gmp-5.0.1_and_mpfr-3.0.0/include - -//Path to the MPFR library -MPFR_LIBRARIES:FILEPATH=C:/3rdPartyLibs/VC-64/gmp-5.0.1_and_mpfr-3.0.0/lib/libmpfr-4.lib - -MPFR_LIBRARIES_DIR:FILEPATH=C:/3rdPartyLibs/VC-64/gmp-5.0.1_and_mpfr-3.0.0/lib - -//OpenGL library for win32 -OPENGL_gl_LIBRARY:STRING=opengl32 - -//GLU library for win32 -OPENGL_glu_LIBRARY:STRING=glu32 - -//The directory containing a CMake configuration file for Qt5Core. -Qt5Core_DIR:PATH=C:/3rdPartyLibs/Qt/5.9.1/msvc2017_64/lib/cmake/Qt5Core - -//The directory containing a CMake configuration file for Qt5Gui. -Qt5Gui_DIR:PATH=C:/3rdPartyLibs/Qt/5.9.1/msvc2017_64/lib/cmake/Qt5Gui - -//The directory containing a CMake configuration file for Qt5OpenGL. -Qt5OpenGL_DIR:PATH=C:/3rdPartyLibs/Qt/5.9.1/msvc2017_64/lib/cmake/Qt5OpenGL - -//The directory containing a CMake configuration file for Qt5Svg. -Qt5Svg_DIR:PATH=C:/3rdPartyLibs/Qt/5.9.1/msvc2017_64/lib/cmake/Qt5Svg - -//The directory containing a CMake configuration file for Qt5Widgets. -Qt5Widgets_DIR:PATH=C:/3rdPartyLibs/Qt/5.9.1/msvc2017_64/lib/cmake/Qt5Widgets - -//The directory containing a CMake configuration file for Qt5. -Qt5_DIR:PATH=C:/3rdPartyLibs/Qt/5.9.1/msvc2017_64/lib/cmake/Qt5 - -//Select external library BLAS -WITH_BLAS:BOOL=OFF - -//Enable CGAL component CGAL_Core -WITH_CGAL_Core:BOOL=ON - -//Enable CGAL component CGAL_ImageIO -WITH_CGAL_ImageIO:BOOL=ON - -//Enable CGAL component CGAL_Qt5 -WITH_CGAL_Qt5:BOOL=ON - -//Select external library Coin3D -WITH_Coin3D:BOOL=OFF - -//Select external library ESBTL -WITH_ESBTL:BOOL=ON - -//Select external library Eigen3 -WITH_Eigen3:BOOL=OFF - -//Select external library GMP -WITH_GMP:BOOL=ON - -//Select external library IPE -WITH_IPE:BOOL=OFF - -//Select external library LAPACK -WITH_LAPACK:BOOL=OFF - -//Select external library LEDA -WITH_LEDA:BOOL=OFF - -//Select external library MPFI -WITH_MPFI:BOOL=OFF - -//Select external library MPFR -WITH_MPFR:BOOL=ON - -//Select external library NTL -WITH_NTL:BOOL=OFF - -//Select external library OpenGL -WITH_OpenGL:BOOL=OFF - -//Select external library OpenNL -WITH_OpenNL:BOOL=OFF - -//Select external library QGLViewer -WITH_QGLViewer:BOOL=OFF - -//Select external library RS -WITH_RS:BOOL=OFF - -//Select external library RS3 -WITH_RS3:BOOL=OFF - -//Select external library ZLIB -WITH_ZLIB:BOOL=ON - -//Select demos -WITH_demos:BOOL=OFF - -//Select examples -WITH_examples:BOOL=OFF - -//Path to a file. -ZLIB_INCLUDE_DIR:PATH=C:/3rdPartyLibs/zlib-1.2.11/build_msvc2013/include - -//Path to a library. -ZLIB_LIBRARY_DEBUG:FILEPATH=C:/3rdPartyLibs/zlib-1.2.11/build_msvc2013/lib/zlib.lib - -//Path to a library. -ZLIB_LIBRARY_RELEASE:FILEPATH=C:/3rdPartyLibs/zlib-1.2.11/build_msvc2013/lib/zlib.lib - - -######################## -# INTERNAL cache entries -######################## - -//ADVANCED property for variable: Boost_DEBUG -Boost_DEBUG-ADVANCED:INTERNAL=1 -//ADVANCED property for variable: Boost_INCLUDE_DIR -Boost_INCLUDE_DIR-ADVANCED:INTERNAL=1 -//Avoid future search of boost-cmake -Boost_NO_BOOST_CMAKE:INTERNAL=TRUE -CGAL_3RD_PARTY_DEFINITIONS:INTERNAL=-DBOOST_ALL_DYN_LINK -CGAL_3RD_PARTY_INCLUDE_DIRS:INTERNAL=C:/3rdPartyLibs/boost/boost_1_67_0 -CGAL_3RD_PARTY_LIBRARIES:INTERNAL= -CGAL_3RD_PARTY_LIBRARIES_DIRS:INTERNAL= -CGAL_3RD_PARTY_PRECONFIGURED:INTERNAL= -//ADVANCED property for variable: CGAL_Boost_USE_STATIC_LIBS -CGAL_Boost_USE_STATIC_LIBS-ADVANCED:INTERNAL=1 -//Test CGAL_CFG_DENORMALS_COMPILE_BUG -CGAL_CFG_DENORMALS_COMPILE_BUG:INTERNAL=1 -//Result of TRY_COMPILE -CGAL_CFG_DENORMALS_COMPILE_BUG_COMPILED:INTERNAL=TRUE -//Test CGAL_CFG_FPU_ROUNDING_MODE_UNWINDING_VC_BUG -CGAL_CFG_FPU_ROUNDING_MODE_UNWINDING_VC_BUG:INTERNAL= -//Result of TRY_COMPILE -CGAL_CFG_FPU_ROUNDING_MODE_UNWINDING_VC_BUG_COMPILED:INTERNAL=TRUE -//Test CGAL_CFG_IEEE_754_BUG -CGAL_CFG_IEEE_754_BUG:INTERNAL=1 -//Result of TRY_COMPILE -CGAL_CFG_IEEE_754_BUG_COMPILED:INTERNAL=TRUE -//Test CGAL_CFG_ISTREAM_INT_BUG -CGAL_CFG_ISTREAM_INT_BUG:INTERNAL=1 -//Result of TRY_COMPILE -CGAL_CFG_ISTREAM_INT_BUG_COMPILED:INTERNAL=TRUE -//Test CGAL_CFG_MATCHING_BUG_5 -CGAL_CFG_MATCHING_BUG_5:INTERNAL=1 -//Result of TRY_COMPILE -CGAL_CFG_MATCHING_BUG_5_COMPILED:INTERNAL=TRUE -//Test CGAL_CFG_MATCHING_BUG_6 -CGAL_CFG_MATCHING_BUG_6:INTERNAL= -//Result of TRY_COMPILE -CGAL_CFG_MATCHING_BUG_6_COMPILED:INTERNAL=FALSE -//Test CGAL_CFG_MATCHING_BUG_7 -CGAL_CFG_MATCHING_BUG_7:INTERNAL=1 -//Result of TRY_COMPILE -CGAL_CFG_MATCHING_BUG_7_COMPILED:INTERNAL=TRUE -//Test CGAL_CFG_MATCHING_BUG_8 -CGAL_CFG_MATCHING_BUG_8:INTERNAL=1 -//Result of TRY_COMPILE -CGAL_CFG_MATCHING_BUG_8_COMPILED:INTERNAL=TRUE -//Test CGAL_CFG_NESTED_CLASS_FRIEND_DECLARATION_BUG -CGAL_CFG_NESTED_CLASS_FRIEND_DECLARATION_BUG:INTERNAL=1 -//Result of TRY_COMPILE -CGAL_CFG_NESTED_CLASS_FRIEND_DECLARATION_BUG_COMPILED:INTERNAL=TRUE -//Test CGAL_CFG_NO_LIMITS -CGAL_CFG_NO_LIMITS:INTERNAL=1 -//Result of TRY_COMPILE -CGAL_CFG_NO_LIMITS_COMPILED:INTERNAL=TRUE -//Test CGAL_CFG_NO_NEXTAFTER -CGAL_CFG_NO_NEXTAFTER:INTERNAL=1 -//Result of TRY_COMPILE -CGAL_CFG_NO_NEXTAFTER_COMPILED:INTERNAL=TRUE -//Test CGAL_CFG_NO_STL -CGAL_CFG_NO_STL:INTERNAL=1 -//Result of TRY_COMPILE -CGAL_CFG_NO_STL_COMPILED:INTERNAL=TRUE -//Test CGAL_CFG_NUMERIC_LIMITS_BUG -CGAL_CFG_NUMERIC_LIMITS_BUG:INTERNAL=1 -//Result of TRY_COMPILE -CGAL_CFG_NUMERIC_LIMITS_BUG_COMPILED:INTERNAL=TRUE -//Test CGAL_CFG_OUTOFLINE_MEMBER_DEFINITION_BUG -CGAL_CFG_OUTOFLINE_MEMBER_DEFINITION_BUG:INTERNAL=1 -//Result of TRY_COMPILE -CGAL_CFG_OUTOFLINE_MEMBER_DEFINITION_BUG_COMPILED:INTERNAL=TRUE -//Test CGAL_CFG_TEMPLATE_IN_DEFAULT_PARAMETER_BUG -CGAL_CFG_TEMPLATE_IN_DEFAULT_PARAMETER_BUG:INTERNAL=1 -//Result of TRY_COMPILE -CGAL_CFG_TEMPLATE_IN_DEFAULT_PARAMETER_BUG_COMPILED:INTERNAL=TRUE -//Test CGAL_CFG_TYPENAME_BEFORE_DEFAULT_ARGUMENT_BUG -CGAL_CFG_TYPENAME_BEFORE_DEFAULT_ARGUMENT_BUG:INTERNAL=1 -//Result of TRY_COMPILE -CGAL_CFG_TYPENAME_BEFORE_DEFAULT_ARGUMENT_BUG_COMPILED:INTERNAL=TRUE -//Test CGAL_CFG_USING_BASE_MEMBER_BUG_2 -CGAL_CFG_USING_BASE_MEMBER_BUG_2:INTERNAL=1 -//Result of TRY_COMPILE -CGAL_CFG_USING_BASE_MEMBER_BUG_2_COMPILED:INTERNAL=TRUE -CGAL_CONFIGURED_LIBRARIES:INTERNAL=CGAL_Core;CGAL_ImageIO;CGAL_Qt5 -//Directory containing the Core package -CGAL_CORE_PACKAGE_DIR:INTERNAL=C:/CGAL/CGAL-4.9 -CGAL_Core_3RD_PARTY_DEFINITIONS:INTERNAL= -CGAL_Core_3RD_PARTY_INCLUDE_DIRS:INTERNAL= -CGAL_Core_3RD_PARTY_LIBRARIES:INTERNAL= -CGAL_Core_3RD_PARTY_LIBRARIES_DIRS:INTERNAL= -CGAL_Core_LIBRARY:INTERNAL= -//Variable hidden from user -CGAL_ESSENTIAL_3RD_PARTY_LIBRARIES:INTERNAL=GMP;MPFR -CGAL_EXECUTABLE_TARGETS:INTERNAL= -//Variable hidden from user -CGAL_EXT_LIB_BLAS_PREFIX:INTERNAL=BLAS -//Variable hidden from user -CGAL_EXT_LIB_Coin3D_PREFIX:INTERNAL=COIN3D -//Variable hidden from user -CGAL_EXT_LIB_ESBTL_PREFIX:INTERNAL=ESBTL -//Variable hidden from user -CGAL_EXT_LIB_Eigen3_PREFIX:INTERNAL=EIGEN3 -//Variable hidden from user -CGAL_EXT_LIB_GMP_PREFIX:INTERNAL=GMP -//Variable hidden from user -CGAL_EXT_LIB_IPE_PREFIX:INTERNAL=IPE -//Variable hidden from user -CGAL_EXT_LIB_LAPACK_PREFIX:INTERNAL=LAPACK -//Variable hidden from user -CGAL_EXT_LIB_LEDA_PREFIX:INTERNAL=LEDA -//Variable hidden from user -CGAL_EXT_LIB_MPFI_PREFIX:INTERNAL=MPFI -//Variable hidden from user -CGAL_EXT_LIB_MPFR_PREFIX:INTERNAL=MPFR -//Variable hidden from user -CGAL_EXT_LIB_NTL_PREFIX:INTERNAL=NTL -//Variable hidden from user -CGAL_EXT_LIB_OpenGL_PREFIX:INTERNAL=OpenGL -//Variable hidden from user -CGAL_EXT_LIB_OpenNL_PREFIX:INTERNAL=OpenNL -//Variable hidden from user -CGAL_EXT_LIB_QGLViewer_PREFIX:INTERNAL=QGLVIEWER -//Variable hidden from user -CGAL_EXT_LIB_RS3_PREFIX:INTERNAL=RS3 -//Variable hidden from user -CGAL_EXT_LIB_RS_PREFIX:INTERNAL=RS -//Variable hidden from user -CGAL_EXT_LIB_ZLIB_PREFIX:INTERNAL=ZLIB -//Directory containing the GraphicsView package -CGAL_GRAPHICSVIEW_PACKAGE_DIR:INTERNAL=C:/CGAL/CGAL-4.9 -//Directory containing the Installation package -CGAL_INSTALLATION_PACKAGE_DIR:INTERNAL=C:/CGAL/CGAL-4.9 -CGAL_ImageIO_3RD_PARTY_DEFINITIONS:INTERNAL=-DCGAL_USE_ZLIB -CGAL_ImageIO_3RD_PARTY_INCLUDE_DIRS:INTERNAL=C:/3rdPartyLibs/zlib-1.2.11/build_msvc2013/include -CGAL_ImageIO_3RD_PARTY_LIBRARIES:INTERNAL=C:/3rdPartyLibs/zlib-1.2.11/build_msvc2013/lib/zlib.lib -CGAL_ImageIO_3RD_PARTY_LIBRARIES_DIRS:INTERNAL= -CGAL_ImageIO_LIBRARY:INTERNAL= -CGAL_ImageIO_USE_ZLIB:INTERNAL=ON -//Directory containing the Maintenance package -CGAL_MAINTENANCE_PACKAGE_DIR:INTERNAL=C:/CGAL/CGAL-4.9 -CGAL_Qt5_3RD_PARTY_DEFINITIONS:INTERNAL= -CGAL_Qt5_3RD_PARTY_INCLUDE_DIRS:INTERNAL= -CGAL_Qt5_3RD_PARTY_LIBRARIES:INTERNAL=glu32;opengl32 -CGAL_Qt5_3RD_PARTY_LIBRARIES_DIRS:INTERNAL= -CGAL_Qt5_LIBRARY:INTERNAL= -//Variable hidden from user -CGAL_SUPPORTING_3RD_PARTY_LIBRARIES:INTERNAL=GMP;MPFR;ZLIB;OpenGL;LEDA;MPFI;RS;RS3;OpenNL;Eigen3;BLAS;LAPACK;QGLViewer;ESBTL;Coin3D;NTL;IPE -//This is the cygwin platform. -CGAL_WIN32_CMAKE_ON_CYGWIN:INTERNAL=TRUE -//This is the directory where this CMakeCache.txt was created -CMAKE_CACHEFILE_DIR:INTERNAL=c:/CGAL/reference_platforms/x64_Cygwin-Windows10_MSVC2017-Debug-64bits -//Major version of cmake used to create the current loaded cache -CMAKE_CACHE_MAJOR_VERSION:INTERNAL=3 -//Minor version of cmake used to create the current loaded cache -CMAKE_CACHE_MINOR_VERSION:INTERNAL=9 -//Patch version of cmake used to create the current loaded cache -CMAKE_CACHE_PATCH_VERSION:INTERNAL=3 -//Path to CMake executable. -CMAKE_COMMAND:INTERNAL=C:/dev/CMake/bin/cmake.exe -//Path to cpack program executable. -CMAKE_CPACK_COMMAND:INTERNAL=C:/dev/CMake/bin/cpack.exe -//Path to ctest program executable. -CMAKE_CTEST_COMMAND:INTERNAL=C:/dev/CMake/bin/ctest.exe -//ADVANCED property for variable: CMAKE_CXX_FLAGS -CMAKE_CXX_FLAGS-ADVANCED:INTERNAL=1 -//ADVANCED property for variable: CMAKE_CXX_FLAGS_DEBUG -CMAKE_CXX_FLAGS_DEBUG-ADVANCED:INTERNAL=1 -//ADVANCED property for variable: CMAKE_CXX_FLAGS_MINSIZEREL -CMAKE_CXX_FLAGS_MINSIZEREL-ADVANCED:INTERNAL=1 -//ADVANCED property for variable: CMAKE_CXX_FLAGS_RELEASE -CMAKE_CXX_FLAGS_RELEASE-ADVANCED:INTERNAL=1 -//ADVANCED property for variable: CMAKE_CXX_FLAGS_RELWITHDEBINFO -CMAKE_CXX_FLAGS_RELWITHDEBINFO-ADVANCED:INTERNAL=1 -//ADVANCED property for variable: CMAKE_CXX_STANDARD_LIBRARIES -CMAKE_CXX_STANDARD_LIBRARIES-ADVANCED:INTERNAL=1 -//ADVANCED property for variable: CMAKE_C_FLAGS -CMAKE_C_FLAGS-ADVANCED:INTERNAL=1 -//ADVANCED property for variable: CMAKE_C_FLAGS_DEBUG -CMAKE_C_FLAGS_DEBUG-ADVANCED:INTERNAL=1 -//ADVANCED property for variable: CMAKE_C_FLAGS_MINSIZEREL -CMAKE_C_FLAGS_MINSIZEREL-ADVANCED:INTERNAL=1 -//ADVANCED property for variable: CMAKE_C_FLAGS_RELEASE -CMAKE_C_FLAGS_RELEASE-ADVANCED:INTERNAL=1 -//ADVANCED property for variable: CMAKE_C_FLAGS_RELWITHDEBINFO -CMAKE_C_FLAGS_RELWITHDEBINFO-ADVANCED:INTERNAL=1 -//ADVANCED property for variable: CMAKE_C_STANDARD_LIBRARIES -CMAKE_C_STANDARD_LIBRARIES-ADVANCED:INTERNAL=1 -//Executable file format -CMAKE_EXECUTABLE_FORMAT:INTERNAL=Unknown -//ADVANCED property for variable: CMAKE_EXE_LINKER_FLAGS -CMAKE_EXE_LINKER_FLAGS-ADVANCED:INTERNAL=1 -//ADVANCED property for variable: CMAKE_EXE_LINKER_FLAGS_DEBUG -CMAKE_EXE_LINKER_FLAGS_DEBUG-ADVANCED:INTERNAL=1 -//ADVANCED property for variable: CMAKE_EXE_LINKER_FLAGS_MINSIZEREL -CMAKE_EXE_LINKER_FLAGS_MINSIZEREL-ADVANCED:INTERNAL=1 -//ADVANCED property for variable: CMAKE_EXE_LINKER_FLAGS_RELEASE -CMAKE_EXE_LINKER_FLAGS_RELEASE-ADVANCED:INTERNAL=1 -//ADVANCED property for variable: CMAKE_EXE_LINKER_FLAGS_RELWITHDEBINFO -CMAKE_EXE_LINKER_FLAGS_RELWITHDEBINFO-ADVANCED:INTERNAL=1 -//Name of external makefile project generator. -CMAKE_EXTRA_GENERATOR:INTERNAL= -//Name of generator. -CMAKE_GENERATOR:INTERNAL=Visual Studio 15 2017 Win64 -//Name of generator platform. -CMAKE_GENERATOR_PLATFORM:INTERNAL= -//Name of generator toolset. -CMAKE_GENERATOR_TOOLSET:INTERNAL= -//Source directory with the top level CMakeLists.txt file for this -// project -CMAKE_HOME_DIRECTORY:INTERNAL=C:/CGAL/CGAL-4.9 -//ADVANCED property for variable: CMAKE_INSTALL_BINDIR -CMAKE_INSTALL_BINDIR-ADVANCED:INTERNAL=1 -//ADVANCED property for variable: CMAKE_INSTALL_DATADIR -CMAKE_INSTALL_DATADIR-ADVANCED:INTERNAL=1 -//ADVANCED property for variable: CMAKE_INSTALL_DATAROOTDIR -CMAKE_INSTALL_DATAROOTDIR-ADVANCED:INTERNAL=1 -//ADVANCED property for variable: CMAKE_INSTALL_DOCDIR -CMAKE_INSTALL_DOCDIR-ADVANCED:INTERNAL=1 -//ADVANCED property for variable: CMAKE_INSTALL_INCLUDEDIR -CMAKE_INSTALL_INCLUDEDIR-ADVANCED:INTERNAL=1 -//ADVANCED property for variable: CMAKE_INSTALL_INFODIR -CMAKE_INSTALL_INFODIR-ADVANCED:INTERNAL=1 -//ADVANCED property for variable: CMAKE_INSTALL_LIBDIR -CMAKE_INSTALL_LIBDIR-ADVANCED:INTERNAL=1 -//ADVANCED property for variable: CMAKE_INSTALL_LIBEXECDIR -CMAKE_INSTALL_LIBEXECDIR-ADVANCED:INTERNAL=1 -//ADVANCED property for variable: CMAKE_INSTALL_LOCALEDIR -CMAKE_INSTALL_LOCALEDIR-ADVANCED:INTERNAL=1 -//ADVANCED property for variable: CMAKE_INSTALL_LOCALSTATEDIR -CMAKE_INSTALL_LOCALSTATEDIR-ADVANCED:INTERNAL=1 -//ADVANCED property for variable: CMAKE_INSTALL_MANDIR -CMAKE_INSTALL_MANDIR-ADVANCED:INTERNAL=1 -//ADVANCED property for variable: CMAKE_INSTALL_OLDINCLUDEDIR -CMAKE_INSTALL_OLDINCLUDEDIR-ADVANCED:INTERNAL=1 -//ADVANCED property for variable: CMAKE_INSTALL_RUNSTATEDIR -CMAKE_INSTALL_RUNSTATEDIR-ADVANCED:INTERNAL=1 -//ADVANCED property for variable: CMAKE_INSTALL_SBINDIR -CMAKE_INSTALL_SBINDIR-ADVANCED:INTERNAL=1 -//ADVANCED property for variable: CMAKE_INSTALL_SHAREDSTATEDIR -CMAKE_INSTALL_SHAREDSTATEDIR-ADVANCED:INTERNAL=1 -//ADVANCED property for variable: CMAKE_INSTALL_SYSCONFDIR -CMAKE_INSTALL_SYSCONFDIR-ADVANCED:INTERNAL=1 -//ADVANCED property for variable: CMAKE_LINKER -CMAKE_LINKER-ADVANCED:INTERNAL=1 -//ADVANCED property for variable: CMAKE_MODULE_LINKER_FLAGS -CMAKE_MODULE_LINKER_FLAGS-ADVANCED:INTERNAL=1 -//ADVANCED property for variable: CMAKE_MODULE_LINKER_FLAGS_DEBUG -CMAKE_MODULE_LINKER_FLAGS_DEBUG-ADVANCED:INTERNAL=1 -//ADVANCED property for variable: CMAKE_MODULE_LINKER_FLAGS_MINSIZEREL -CMAKE_MODULE_LINKER_FLAGS_MINSIZEREL-ADVANCED:INTERNAL=1 -//ADVANCED property for variable: CMAKE_MODULE_LINKER_FLAGS_RELEASE -CMAKE_MODULE_LINKER_FLAGS_RELEASE-ADVANCED:INTERNAL=1 -//ADVANCED property for variable: CMAKE_MODULE_LINKER_FLAGS_RELWITHDEBINFO -CMAKE_MODULE_LINKER_FLAGS_RELWITHDEBINFO-ADVANCED:INTERNAL=1 -//number of local generators -CMAKE_NUMBER_OF_MAKEFILES:INTERNAL=6 -//Platform information initialized -CMAKE_PLATFORM_INFO_INITIALIZED:INTERNAL=1 -//ADVANCED property for variable: CMAKE_RC_COMPILER -CMAKE_RC_COMPILER-ADVANCED:INTERNAL=1 -CMAKE_RC_COMPILER_WORKS:INTERNAL=1 -//ADVANCED property for variable: CMAKE_RC_FLAGS -CMAKE_RC_FLAGS-ADVANCED:INTERNAL=1 -//ADVANCED property for variable: CMAKE_RC_FLAGS_DEBUG -CMAKE_RC_FLAGS_DEBUG-ADVANCED:INTERNAL=1 -//ADVANCED property for variable: CMAKE_RC_FLAGS_MINSIZEREL -CMAKE_RC_FLAGS_MINSIZEREL-ADVANCED:INTERNAL=1 -//ADVANCED property for variable: CMAKE_RC_FLAGS_RELEASE -CMAKE_RC_FLAGS_RELEASE-ADVANCED:INTERNAL=1 -//ADVANCED property for variable: CMAKE_RC_FLAGS_RELWITHDEBINFO -CMAKE_RC_FLAGS_RELWITHDEBINFO-ADVANCED:INTERNAL=1 -//Path to CMake installation. -CMAKE_ROOT:INTERNAL=C:/dev/CMake/share/cmake-3.9 -//ADVANCED property for variable: CMAKE_SHARED_LINKER_FLAGS -CMAKE_SHARED_LINKER_FLAGS-ADVANCED:INTERNAL=1 -//ADVANCED property for variable: CMAKE_SHARED_LINKER_FLAGS_DEBUG -CMAKE_SHARED_LINKER_FLAGS_DEBUG-ADVANCED:INTERNAL=1 -//ADVANCED property for variable: CMAKE_SHARED_LINKER_FLAGS_MINSIZEREL -CMAKE_SHARED_LINKER_FLAGS_MINSIZEREL-ADVANCED:INTERNAL=1 -//ADVANCED property for variable: CMAKE_SHARED_LINKER_FLAGS_RELEASE -CMAKE_SHARED_LINKER_FLAGS_RELEASE-ADVANCED:INTERNAL=1 -//ADVANCED property for variable: CMAKE_SHARED_LINKER_FLAGS_RELWITHDEBINFO -CMAKE_SHARED_LINKER_FLAGS_RELWITHDEBINFO-ADVANCED:INTERNAL=1 -//ADVANCED property for variable: CMAKE_SKIP_INSTALL_RPATH -CMAKE_SKIP_INSTALL_RPATH-ADVANCED:INTERNAL=1 -//ADVANCED property for variable: CMAKE_SKIP_RPATH -CMAKE_SKIP_RPATH-ADVANCED:INTERNAL=1 -//ADVANCED property for variable: CMAKE_STATIC_LINKER_FLAGS -CMAKE_STATIC_LINKER_FLAGS-ADVANCED:INTERNAL=1 -//ADVANCED property for variable: CMAKE_STATIC_LINKER_FLAGS_DEBUG -CMAKE_STATIC_LINKER_FLAGS_DEBUG-ADVANCED:INTERNAL=1 -//ADVANCED property for variable: CMAKE_STATIC_LINKER_FLAGS_MINSIZEREL -CMAKE_STATIC_LINKER_FLAGS_MINSIZEREL-ADVANCED:INTERNAL=1 -//ADVANCED property for variable: CMAKE_STATIC_LINKER_FLAGS_RELEASE -CMAKE_STATIC_LINKER_FLAGS_RELEASE-ADVANCED:INTERNAL=1 -//ADVANCED property for variable: CMAKE_STATIC_LINKER_FLAGS_RELWITHDEBINFO -CMAKE_STATIC_LINKER_FLAGS_RELWITHDEBINFO-ADVANCED:INTERNAL=1 -//Variable hidden from user -CMAKE_UNAME:INTERNAL=C:/cygwin/bin/uname.exe -//ADVANCED property for variable: CMAKE_VERBOSE_MAKEFILE -CMAKE_VERBOSE_MAKEFILE-ADVANCED:INTERNAL=1 -//Details about finding GMP -FIND_PACKAGE_MESSAGE_DETAILS_GMP:INTERNAL=[C:/3rdPartyLibs/VC-64/gmp-5.0.1_and_mpfr-3.0.0/lib/libgmp-10.lib][C:/3rdPartyLibs/VC-64/gmp-5.0.1_and_mpfr-3.0.0/include][v()] -//Details about finding MPFR -FIND_PACKAGE_MESSAGE_DETAILS_MPFR:INTERNAL=[C:/3rdPartyLibs/VC-64/gmp-5.0.1_and_mpfr-3.0.0/lib/libmpfr-4.lib][C:/3rdPartyLibs/VC-64/gmp-5.0.1_and_mpfr-3.0.0/include][v()] -//Details about finding ZLIB -FIND_PACKAGE_MESSAGE_DETAILS_ZLIB:INTERNAL=[C:/3rdPartyLibs/zlib-1.2.11/build_msvc2013/lib/zlib.lib][C:/3rdPartyLibs/zlib-1.2.11/build_msvc2013/include][v1.2.11()] -//Result of TRY_COMPILE -GMP_COMPILE_RES:INTERNAL=TRUE -GMP_IN_CGAL_AUXILIARY:INTERNAL=TRUE -//Result of TRY_RUN -GMP_RUN_RES:INTERNAL=0 -//Generator uses intermediate configuration directory -HAS_CFG_INTDIR:INTERNAL=TRUE -//Result of TRY_COMPILE -MPFR_COMPILE_RES:INTERNAL=TRUE -MPFR_IN_CGAL_AUXILIARY:INTERNAL=TRUE -//Result of TRY_RUN -MPFR_RUN_RES:INTERNAL=0 -//ADVANCED property for variable: OPENGL_gl_LIBRARY -OPENGL_gl_LIBRARY-ADVANCED:INTERNAL=1 -//ADVANCED property for variable: OPENGL_glu_LIBRARY -OPENGL_glu_LIBRARY-ADVANCED:INTERNAL=1 -//Result of TRY_COMPILE -ZLIB_COMPILE_RES:INTERNAL=TRUE -//ADVANCED property for variable: ZLIB_INCLUDE_DIR -ZLIB_INCLUDE_DIR-ADVANCED:INTERNAL=1 -//ADVANCED property for variable: ZLIB_LIBRARY_DEBUG -ZLIB_LIBRARY_DEBUG-ADVANCED:INTERNAL=1 -//ADVANCED property for variable: ZLIB_LIBRARY_RELEASE -ZLIB_LIBRARY_RELEASE-ADVANCED:INTERNAL=1 -//Result of TRY_RUN -ZLIB_RUN_RES:INTERNAL=0 -//Last used Boost_ADDITIONAL_VERSIONS value. -_Boost_ADDITIONAL_VERSIONS_LAST:INTERNAL=1.69.1;1.69.0;1.69;1.68.1;1.68.0;1.68;1.67.1;1.67.0;1.67;1.66.1;1.66.0;1.66;1.65.1;1.65.0;1.65;1.64.1;1.64.0;1.64;1.63.1;1.63.0;1.63;1.62.1;1.62.0;1.62;1.61.1;1.61.0;1.61;1.60.1;1.60.0;1.60;1.59.1;1.59.0;1.59;1.58.1;1.58.0;1.58;1.57.1;1.57.0;1.57;1.56.1;1.56.0;1.56;1.55.1;1.55.0;1.55;1.54.1;1.54.0;1.54;1.53.1;1.53.0;1.53;1.52.1;1.52.0;1.52;1.51.1;1.51.0;1.51;1.50.1;1.50.0;1.50;1.49.1;1.49.0;1.49;1.48.1;1.48.0;1.48;1.47.1;1.47.0;1.47;1.46.1;1.46.0;1.46;1.45.1;1.45.0;1.45;1.44.1;1.44.0;1.44;1.43.1;1.43.0;1.43;1.42.1;1.42.0;1.42;1.41.1;1.41.0;1.41;1.40.1;1.40.0;1.40;1.39.1;1.39.0;1.39;1.38.1;1.38.0;1.38;1.37.1;1.37.0;1.37 -//Components requested for this build tree. -_Boost_COMPONENTS_SEARCHED:INTERNAL= -//Last used Boost_INCLUDE_DIR value. -_Boost_INCLUDE_DIR_LAST:INTERNAL=C:/3rdPartyLibs/boost/boost_1_67_0 -//Last used Boost_NAMESPACE value. -_Boost_NAMESPACE_LAST:INTERNAL=boost -//Last used Boost_USE_MULTITHREADED value. -_Boost_USE_MULTITHREADED_LAST:INTERNAL=TRUE -//Last used Boost_USE_STATIC_LIBS value. -_Boost_USE_STATIC_LIBS_LAST:INTERNAL=OFF -//CMAKE_INSTALL_PREFIX during last run -_GNUInstallDirs_LAST_CMAKE_INSTALL_PREFIX:INTERNAL=C:/Program Files (x86)/CGAL - diff --git a/Maintenance/infrastructure/gauguin.geometryfactory.com/reference_platforms/x64_Cygwin-Windows10_MSVC2017-Debug-64bits/init.cmake b/Maintenance/infrastructure/gauguin.geometryfactory.com/reference_platforms/x64_Cygwin-Windows10_MSVC2017-Debug-64bits/init.cmake new file mode 100644 index 00000000000..14386bd1103 --- /dev/null +++ b/Maintenance/infrastructure/gauguin.geometryfactory.com/reference_platforms/x64_Cygwin-Windows10_MSVC2017-Debug-64bits/init.cmake @@ -0,0 +1,27 @@ +#SET( Ceres_DIR "C:\\3rdPartyLibs\\ceres-solver\\install-dir\\CMake" CACHE STRING "") + +SET(CMAKE_BUILD_TYPE "Debug" CACHE STRING "") + +SET(CMAKE_CXX_FLAGS "/DWIN32 /D_WINDOWS /W3 /GR /EHsc -D_CRT_SECURE_NO_DEPRECATE -D_SCL_SECURE_NO_DEPRECATE -D_CRT_SECURE_NO_WARNINGS -D_SCL_SECURE_NO_WARNINGS -D_SILENCE_CXX17_ADAPTOR_TYPEDEFS_DEPRECATION_WARNING /fp:strict /fp:except- /wd4503 /bigobj /permissive- /std:c++17" CACHE STRING "") + +SET(CMAKE_CXX_FLAGS_DEBUG "/D_DEBUG /MDd /Ob0 /Od /RTC1" CACHE STRING "") + +SET(CMAKE_CXX_FLAGS_RELEASE "/MD /O2 /Ob2 /DCGAL_NDEBUG" CACHE STRING "") + +SET(TBBROOT "C:/3rdPartyLibs/tbb2018_20170919oss" CACHE STRING "") + +SET(WITH_GMP ON CACHE BOOL "") + +SET(WITH_GMPXX OFF CACHE BOOL "") + +SET(WITH_MPFR ON CACHE BOOL "") + +SET(WITH_NTL OFF CACHE BOOL "") + +SET(WITH_demos ON CACHE BOOL "") + +SET(CGAL_HEADER_ONLY ON CACHE BOOL "") + +SET(Boost_DIR "C:\\3rdPartyLibs\\boost_master\\install_dir\\lib\\cmake\\Boost-1.71.0" CACHE PATH "") + +SET(CGAL_Boost_USE_STATIC_LIBS ON CACHE BOOL "") \ No newline at end of file diff --git a/Maintenance/infrastructure/gauguin.geometryfactory.com/reference_platforms/x64_Cygwin-Windows10_MSVC2017-Debug-64bits/setup b/Maintenance/infrastructure/gauguin.geometryfactory.com/reference_platforms/x64_Cygwin-Windows10_MSVC2017-Debug-64bits/setup index 9b4c6c4e4ec..c365c26798c 100644 --- a/Maintenance/infrastructure/gauguin.geometryfactory.com/reference_platforms/x64_Cygwin-Windows10_MSVC2017-Debug-64bits/setup +++ b/Maintenance/infrastructure/gauguin.geometryfactory.com/reference_platforms/x64_Cygwin-Windows10_MSVC2017-Debug-64bits/setup @@ -3,9 +3,11 @@ export VC_VERSION="14.1" export VC_VERSION_YEAR="2017" export ARCH="64" export QT_VERSION="5.9.1" +BOOST_VERSION="1.71" export PLATFORM_REFERENCE="/cygdrive/c/CGAL/reference_platforms" -export BOOST_VERSION=1_67_0 export TBB_ARCH="intel64" export EIGEN3_DIR="C:/3rdPartyLibs/eigen-master" +export INIT_FILE="C:\\CGAL\\reference_platforms\\x64_Cygwin-Windows10_MSVC2017-Debug-64bits\\init.cmake" export OPENMESH_DIR="C:\3rdPartyLibs\OpenMesh_7_1" source "${PLATFORM_REFERENCE}/setup_common" +export PATH="/cygdrive/c/3rdPartyLibs/boost_master/install_dir/lib:${PATH}" From 12c7bb2abdabec9b6c56f0c2fb18a5a0e249d4b2 Mon Sep 17 00:00:00 2001 From: Marc Glisse Date: Tue, 19 May 2020 11:24:12 +0200 Subject: [PATCH 416/568] More mixed MP_Float operations for visual studio --- Number_types/include/CGAL/MP_Float.h | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/Number_types/include/CGAL/MP_Float.h b/Number_types/include/CGAL/MP_Float.h index b0a161837c1..68cfdecde44 100644 --- a/Number_types/include/CGAL/MP_Float.h +++ b/Number_types/include/CGAL/MP_Float.h @@ -109,8 +109,8 @@ MP_Float operator%(const MP_Float &a, const MP_Float &b); class MP_Float : boost::totally_ordered1 > #endif > @@ -237,11 +237,13 @@ public: { return (a.v == b.v) && (a.v.empty() || (a.exp == b.exp)); } #ifdef _MSC_VER - // Needed because without /permissive-, it makes hidden friends visible (operator== from Quotient) - friend bool operator==(const MP_Float &a, int b) - { return a == MP_Float(b); } - friend bool operator==(const MP_Float &a, double b) - { return a == MP_Float(b); } + // Needed because without /permissive-, it makes hidden friends visible (from Quotient) + friend bool operator==(const MP_Float &a, int b) { return a == MP_Float(b); } + friend bool operator==(const MP_Float &a, double b) { return a == MP_Float(b); } + friend bool operator< (const MP_Float &a, int b) { return a < MP_Float(b); } + friend bool operator< (const MP_Float &a, double b) { return a < MP_Float(b); } + friend bool operator> (const MP_Float &a, int b) { return a > MP_Float(b); } + friend bool operator> (const MP_Float &a, double b) { return a > MP_Float(b); } #endif exponent_type max_exp() const From 2622ffd209b19844d5b1caad7366122375e87b47 Mon Sep 17 00:00:00 2001 From: Maxime Gimeno Date: Tue, 19 May 2020 13:06:54 +0200 Subject: [PATCH 417/568] Externalize WS server --- Polyhedron/demo/Polyhedron/CMakeLists.txt | 7 ++ Polyhedron/demo/Polyhedron/MainWindow.cpp | 93 -------------------- Polyhedron/demo/Polyhedron/MainWindow.h | 29 ------- Polyhedron/demo/Polyhedron/MainWindow.ui | 12 --- Polyhedron/demo/Polyhedron/Server_ws.cpp | 100 ++++++++++++++++++++++ Polyhedron/demo/Polyhedron/Server_ws.h | 30 +++++++ 6 files changed, 137 insertions(+), 134 deletions(-) create mode 100644 Polyhedron/demo/Polyhedron/Server_ws.cpp create mode 100644 Polyhedron/demo/Polyhedron/Server_ws.h diff --git a/Polyhedron/demo/Polyhedron/CMakeLists.txt b/Polyhedron/demo/Polyhedron/CMakeLists.txt index 9e00808a516..32da38d5618 100644 --- a/Polyhedron/demo/Polyhedron/CMakeLists.txt +++ b/Polyhedron/demo/Polyhedron/CMakeLists.txt @@ -402,6 +402,13 @@ add_executable ( CGAL_PMP PMP.cpp ) add_dependencies(CGAL_PMP PMP) target_link_libraries( CGAL_PMP PRIVATE polyhedron_demo ) add_to_cached_list( CGAL_EXECUTABLE_TARGETS CGAL_PMP ) + +#WS Server +if(TARGET Qt5::WebSockets) + add_executable (WS_server Server_ws.cpp) + target_link_libraries(WS_server PUBLIC Qt5::WebSockets) + message(STATUS "Qt5WebSockets was found. Using WebSockets is therefore possible.") +endif() # # Exporting # diff --git a/Polyhedron/demo/Polyhedron/MainWindow.cpp b/Polyhedron/demo/Polyhedron/MainWindow.cpp index bd370cd7827..8f266c195bb 100644 --- a/Polyhedron/demo/Polyhedron/MainWindow.cpp +++ b/Polyhedron/demo/Polyhedron/MainWindow.cpp @@ -77,12 +77,6 @@ #include "Color_map.h" -#ifdef CGAL_USE_WEBSOCKETS -#include -#include -#include -#endif - using namespace CGAL::Three; QScriptValue myScene_itemToScriptValue(QScriptEngine *engine, @@ -3681,90 +3675,3 @@ void MainWindow::on_actionLoad_a_Scene_from_a_Script_File_triggered() tmp_file.remove(); } } - -#ifdef CGAL_USE_WEBSOCKETS -void MainWindow::on_action_Start_a_Session_triggered() -{ - QAction * action= findChild("action_Start_a_Session"); - static EchoServer *server =nullptr; - if(action->isChecked()){ - server = new EchoServer(1234); - QObject::connect(server, &EchoServer::closed, server,&EchoServer::deleteLater); - } - else - { - server->deleteLater(); - } -} - -EchoServer::EchoServer(quint16 port) : - QObject(CGAL::Three::Three::mainWindow()), - m_pWebSocketServer(new QWebSocketServer(QStringLiteral("Echo Server"), - QWebSocketServer::NonSecureMode, this)) -{ - if (m_pWebSocketServer->listen(QHostAddress::Any, port)) { - connect(m_pWebSocketServer, &QWebSocketServer::newConnection, - this, &EchoServer::onNewConnection); - connect(m_pWebSocketServer, &QWebSocketServer::closed, this, &EchoServer::closed); - } - QHostAddress local_host("0.0.0.0"); - - //to avoid printing 127.0.0.1. Not realy sure it won't ever print the external ipv4 though. - const QHostAddress &localhost = QHostAddress(QHostAddress::LocalHost); - for (const QHostAddress &address: QNetworkInterface::allAddresses()) { - if (address.protocol() == QAbstractSocket::IPv4Protocol && address != localhost) - { - local_host= address; - break; - } - } - QMessageBox mb(QMessageBox::NoIcon, "WS Server", - tr("WebSockets Server started.\nEnter the following address in\nyour Network Preferences to be able to join it :\n" - "ws://%1:%2").arg(local_host.toString()).arg(port), QMessageBox::Ok, CGAL::Three::Three::mainWindow()); - mb.setTextInteractionFlags(Qt::TextSelectableByMouse); - mb.exec(); -} - -EchoServer::~EchoServer() -{ - m_pWebSocketServer->close(); - qDeleteAll(m_clients.begin(), m_clients.end()); -} - -void EchoServer::onNewConnection() -{ - QWebSocket *pSocket = m_pWebSocketServer->nextPendingConnection(); - - connect(pSocket, &QWebSocket::textMessageReceived, this, &EchoServer::processTextMessage); - connect(pSocket, &QWebSocket::binaryMessageReceived, this, &EchoServer::processBinaryMessage); - connect(pSocket, &QWebSocket::disconnected, this, &EchoServer::socketDisconnected); - - m_clients << pSocket; -} - -void EchoServer::processTextMessage(QString message) -{ - QWebSocket *pClient = qobject_cast(sender()); - for(auto *client : m_clients) { - if(client != pClient) - client->sendTextMessage(message); - } -} - -void EchoServer::processBinaryMessage(QByteArray message) -{ - QWebSocket *pClient = qobject_cast(sender()); - if (pClient) { - pClient->sendBinaryMessage(message); - } -} - -void EchoServer::socketDisconnected() -{ - QWebSocket *pClient = qobject_cast(sender()); - if (pClient) { - m_clients.removeAll(pClient); - pClient->deleteLater(); - } -} -#endif diff --git a/Polyhedron/demo/Polyhedron/MainWindow.h b/Polyhedron/demo/Polyhedron/MainWindow.h index 4e544c08378..8f681a3b3c8 100644 --- a/Polyhedron/demo/Polyhedron/MainWindow.h +++ b/Polyhedron/demo/Polyhedron/MainWindow.h @@ -354,10 +354,6 @@ protected Q_SLOTS: void save(QString filename, QList& to_save); //!Calls the function saveSnapShot of the viewer. void on_actionSaveSnapshot_triggered(); -#ifdef CGAL_USE_WEBSOCKETS - //!Starts a new WS server if none is already exist. Else, does nothing. - void on_action_Start_a_Session_triggered(); -#endif //!Opens a Dialog to choose a color and make it the background color. void setBackgroundColor(); //!Opens a Dialog to change the lighting settings @@ -501,30 +497,5 @@ protected: private: bool is_main; }; -#ifdef CGAL_USE_WEBSOCKETS -QT_FORWARD_DECLARE_CLASS(QWebSocketServer) -QT_FORWARD_DECLARE_CLASS(QWebSocket) -class EchoServer : public QObject -{ - Q_OBJECT -public: - explicit EchoServer(quint16 port); - ~EchoServer(); - - -Q_SIGNALS: - void closed(); - -private Q_SLOTS: - void onNewConnection(); - void processTextMessage(QString message); - void processBinaryMessage(QByteArray message); - void socketDisconnected(); - -private: - QWebSocketServer *m_pWebSocketServer; - QList m_clients; -}; -#endif #endif // ifndef MAINWINDOW_H diff --git a/Polyhedron/demo/Polyhedron/MainWindow.ui b/Polyhedron/demo/Polyhedron/MainWindow.ui index 6273a37bd16..a56c2c1afe8 100644 --- a/Polyhedron/demo/Polyhedron/MainWindow.ui +++ b/Polyhedron/demo/Polyhedron/MainWindow.ui @@ -97,7 +97,6 @@ - @@ -470,17 +469,6 @@ Load a Scene &from a Script File... - - - true - - - &Start a Session - - - Start a WebSocket Server to Share your Camera with Others on your Network. - - diff --git a/Polyhedron/demo/Polyhedron/Server_ws.cpp b/Polyhedron/demo/Polyhedron/Server_ws.cpp new file mode 100644 index 00000000000..82bea309a37 --- /dev/null +++ b/Polyhedron/demo/Polyhedron/Server_ws.cpp @@ -0,0 +1,100 @@ +#include +#include +#include +#include +#include +#include +#include "Server_ws.h" + +#include + + +EchoServer::EchoServer(quint16 port) : + QObject(), + m_pWebSocketServer(new QWebSocketServer(QStringLiteral("Echo Server"), + QWebSocketServer::NonSecureMode, this)) +{ + if (m_pWebSocketServer->listen(QHostAddress::Any, port)) { + connect(m_pWebSocketServer, &QWebSocketServer::newConnection, + this, &EchoServer::onNewConnection); + connect(m_pWebSocketServer, &QWebSocketServer::closed, this, &EchoServer::closed); + } + QHostAddress local_host("0.0.0.0"); + + //to avoid printing 127.0.0.1. Not realy sure it won't ever print the external ipv4 though. + const QHostAddress &localhost = QHostAddress(QHostAddress::LocalHost); + for (const QHostAddress &address: QNetworkInterface::allAddresses()) { + if (address.protocol() == QAbstractSocket::IPv4Protocol && address != localhost) + { + local_host= address; + break; + } + } + QMessageBox mb(QMessageBox::NoIcon, "WS Server", + tr("WebSockets Server started.\nEnter the following address in\nyour Network Preferences to be able to join it :\n" + "ws://%1:%2").arg(local_host.toString()).arg(port), QMessageBox::Ok); + mb.setTextInteractionFlags(Qt::TextSelectableByMouse); + mb.exec(); +} + +EchoServer::~EchoServer() +{ + m_pWebSocketServer->close(); + qDeleteAll(m_clients.begin(), m_clients.end()); +} + +void EchoServer::onNewConnection() +{ + QWebSocket *pSocket = m_pWebSocketServer->nextPendingConnection(); + + connect(pSocket, &QWebSocket::textMessageReceived, this, &EchoServer::processTextMessage); + connect(pSocket, &QWebSocket::binaryMessageReceived, this, &EchoServer::processBinaryMessage); + connect(pSocket, &QWebSocket::disconnected, this, &EchoServer::socketDisconnected); + + m_clients << pSocket; +} + +void EchoServer::processTextMessage(QString message) +{ + QWebSocket *pClient = qobject_cast(sender()); + for(auto *client : m_clients) { + if(client != pClient) + client->sendTextMessage(message); + } +} + +void EchoServer::processBinaryMessage(QByteArray message) +{ + QWebSocket *pClient = qobject_cast(sender()); + if (pClient) { + pClient->sendBinaryMessage(message); + } +} + +void EchoServer::socketDisconnected() +{ + QWebSocket *pClient = qobject_cast(sender()); + if (pClient) { + m_clients.removeAll(pClient); + pClient->deleteLater(); + } +} + +int main(int argc, char *argv[]) +{ + QApplication a(argc, argv); + QCommandLineParser parser; + parser.setApplicationDescription("WS Server"); + parser.addHelpOption(); + QCommandLineOption portOption(QStringList() << "p" << "port", + QCoreApplication::translate("main", "Port for echoserver [default: 1234]."), + QCoreApplication::translate("main", "port"), QLatin1Literal("1234")); + parser.addOption(portOption); + parser.process(a); + int port = parser.value(portOption).toInt(); + EchoServer *server = new EchoServer(port); + QObject::connect(server, &EchoServer::closed, &a, &QCoreApplication::quit); + + return a.exec(); +} + diff --git a/Polyhedron/demo/Polyhedron/Server_ws.h b/Polyhedron/demo/Polyhedron/Server_ws.h new file mode 100644 index 00000000000..fe94f6b2d08 --- /dev/null +++ b/Polyhedron/demo/Polyhedron/Server_ws.h @@ -0,0 +1,30 @@ +#ifndef SERVER_WS_H +#define SERVER_WS_H + +#include +#include +#include + +class EchoServer : public QObject +{ + Q_OBJECT +public: + explicit EchoServer(quint16 port); + ~EchoServer(); + + +Q_SIGNALS: + void closed(); + +private Q_SLOTS: + void onNewConnection(); + void processTextMessage(QString message); + void processBinaryMessage(QByteArray message); + void socketDisconnected(); + +private: + QWebSocketServer *m_pWebSocketServer; + QList m_clients; +}; + +#endif // SERVER_WS_H From 2fcf16c859c182f8ae0188bfb0161ae7a6713d15 Mon Sep 17 00:00:00 2001 From: Maxime Gimeno Date: Tue, 19 May 2020 13:21:06 +0200 Subject: [PATCH 418/568] Silence gl spamm --- Polyhedron/demo/Polyhedron/Viewer.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/Polyhedron/demo/Polyhedron/Viewer.cpp b/Polyhedron/demo/Polyhedron/Viewer.cpp index ecadeba815a..8c2246b04fc 100644 --- a/Polyhedron/demo/Polyhedron/Viewer.cpp +++ b/Polyhedron/demo/Polyhedron/Viewer.cpp @@ -1690,6 +1690,9 @@ void Viewer::setTotalPass(int p) void Viewer::messageLogged(QOpenGLDebugMessage msg) { + //filter out useless warning + if(msg.message().contains("is being recompiled")) + return; QString error; // Format based on severity From cd4586b4dbaa20c600e4f766b532e04c4a6c2e0f Mon Sep 17 00:00:00 2001 From: Maxime Gimeno Date: Tue, 19 May 2020 13:21:59 +0200 Subject: [PATCH 419/568] Fix Generate ObjeCt --- .../demo/Polyhedron/Plugins/PCA/Basic_generator_plugin.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Polyhedron/demo/Polyhedron/Plugins/PCA/Basic_generator_plugin.cpp b/Polyhedron/demo/Polyhedron/Plugins/PCA/Basic_generator_plugin.cpp index 184770f685b..4215c75421b 100644 --- a/Polyhedron/demo/Polyhedron/Plugins/PCA/Basic_generator_plugin.cpp +++ b/Polyhedron/demo/Polyhedron/Plugins/PCA/Basic_generator_plugin.cpp @@ -59,7 +59,7 @@ public : QMenu* menu = menuFile->findChild("menuGenerateObject"); if(!menu){ QAction* actionLoad = mw->findChild("actionLoadPlugin"); - menu = new QMenu(tr("Generate &Objet"), menuFile); + menu = new QMenu(tr("Generate &Object"), menuFile); menu->setObjectName("menuGenerateObject"); menuFile->insertMenu(actionLoad, menu); } From 685c3aa859d8023343900b82071be0e8f49e088b Mon Sep 17 00:00:00 2001 From: Maxime Gimeno Date: Tue, 19 May 2020 13:22:40 +0200 Subject: [PATCH 420/568] Fix typo --- Polyhedron/demo/Polyhedron/Plugins/Point_set/CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Polyhedron/demo/Polyhedron/Plugins/Point_set/CMakeLists.txt b/Polyhedron/demo/Polyhedron/Plugins/Point_set/CMakeLists.txt index d29ca1cf7b8..b5a7c159731 100644 --- a/Polyhedron/demo/Polyhedron/Plugins/Point_set/CMakeLists.txt +++ b/Polyhedron/demo/Polyhedron/Plugins/Point_set/CMakeLists.txt @@ -59,7 +59,7 @@ if(EIGEN3_FOUND) CGAL_target_use_pointmatcher(register_point_sets_plugin) endif() else() - message(STATUS "NOTICE: OpenGR and libpointmatcher were not found. Registrationp plugin will not be available.") + message(STATUS "NOTICE: OpenGR and libpointmatcher were not found. Registration plugin will not be available.") endif() else(EIGEN3_FOUND) From 08af169d6cd6047c1bd118b9f1e0ea6e61854576 Mon Sep 17 00:00:00 2001 From: Maxime Gimeno Date: Tue, 19 May 2020 08:59:56 +0200 Subject: [PATCH 421/568] fix travis --- .travis/build_package.sh | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.travis/build_package.sh b/.travis/build_package.sh index 44bf911a20c..cb046d1e29f 100755 --- a/.travis/build_package.sh +++ b/.travis/build_package.sh @@ -11,7 +11,7 @@ function mytime { function build_examples { mkdir -p build-travis cd build-travis - mytime cmake -DCGAL_DIR="/usr/local/lib/cmake/CGAL" -DCMAKE_CXX_FLAGS="${CXX_FLAGS} -I/home/travis/build/CGAL/cgal/.travis/" -DCGAL_BUILD_THREE_DOC=TRUE -DCGAL_INCLUDE_WINDOWS_DOT_H .. + mytime cmake -DCGAL_DIR="/usr/local/lib/cmake/CGAL" -DCMAKE_CXX_FLAGS="${CXX_FLAGS}" -DCGAL_BUILD_THREE_DOC=TRUE .. mytime make -j2 VERBOSE=1 } @@ -28,7 +28,7 @@ function build_demo { EXTRA_CXX_FLAGS="-Werror=inconsistent-missing-override" ;; esac - mytime cmake -DCGAL_DIR="/usr/local/lib/cmake/CGAL" -DCGAL_DONT_OVERRIDE_CMAKE_FLAGS:BOOL=ON -DCMAKE_CXX_FLAGS="${CXX_FLAGS} ${EXTRA_CXX_FLAGS} -I/home/travis/build/CGAL/cgal/.travis/" -DCGAL_INCLUDE_WINDOWS_DOT_H .. + mytime cmake -DCGAL_DIR="/usr/local/lib/cmake/CGAL" -DCGAL_DONT_OVERRIDE_CMAKE_FLAGS:BOOL=ON -DCMAKE_CXX_FLAGS="${CXX_FLAGS} ${EXTRA_CXX_FLAGS}" .. mytime make -j2 VERBOSE=1 } old_IFS=$IFS From bad269b3ecaf910c1c5ccf9886b812aacdb0fea8 Mon Sep 17 00:00:00 2001 From: Maxime Gimeno Date: Tue, 19 May 2020 14:44:28 +0200 Subject: [PATCH 422/568] SSH actions use agent if possible --- Polyhedron/demo/Polyhedron/MainWindow.cpp | 85 ++++++++++--------- Polyhedron/demo/Polyhedron/Use_ssh.cpp | 73 ++++++++++++++++ .../demo/Polyhedron/include/CGAL/Use_ssh.h | 6 ++ 3 files changed, 126 insertions(+), 38 deletions(-) diff --git a/Polyhedron/demo/Polyhedron/MainWindow.cpp b/Polyhedron/demo/Polyhedron/MainWindow.cpp index 8f266c195bb..e547916ace7 100644 --- a/Polyhedron/demo/Polyhedron/MainWindow.cpp +++ b/Polyhedron/demo/Polyhedron/MainWindow.cpp @@ -2934,25 +2934,12 @@ void MainWindow::on_actionSa_ve_Scene_as_Script_triggered() bool do_upload = false; #ifdef CGAL_USE_SSH QString user = settings.value("ssh_user", QString()).toString(); - QString pass; if(!user.isEmpty()) { QMessageBox::StandardButton doyou = QMessageBox::question(this, tr("Upload ?"), tr("Do you wish to upload the scene" " using the SSH preferences ?")); - bool ok; do_upload = (doyou == QMessageBox::Yes); - if(do_upload) - { - pass = QInputDialog::getText(this, "SSH Password", - "Enter ssh key password:", - QLineEdit::Password, - tr(""), - &ok); - if(!ok) - return; - pass = pass.trimmed(); - } } #endif @@ -3103,12 +3090,31 @@ void MainWindow::on_actionSa_ve_Scene_as_Script_triggered() path.prepend("Polyhedron_demo_"); try{ ssh_session session; - bool res = establish_ssh_session(session, - user.toStdString().c_str(), - server.toStdString().c_str(), - pk.toStdString().c_str(), - privK.toStdString().c_str(), - pass.toStdString().c_str()); + bool res = establish_ssh_session_from_agent(session, + user.toStdString().c_str(), + server.toStdString().c_str(), + pk.toStdString().c_str()); + + if(!res) + { + bool ok; + QString pass; + pass = QInputDialog::getText(this, "SSH Password", + "Enter ssh key password:", + QLineEdit::Password, + tr(""), + &ok); + if(!ok) + return; + pass = pass.trimmed(); + res = establish_ssh_session(session, + user.toStdString().c_str(), + server.toStdString().c_str(), + pk.toStdString().c_str(), + privK.toStdString().c_str(), + pass.toStdString().c_str()); + } + if(!res) { QMessageBox::warning(this, @@ -3584,25 +3590,13 @@ void MainWindow::on_actionLoad_a_Scene_from_a_Script_File_triggered() #ifdef CGAL_USE_SSH QString user = settings.value("ssh_user", QString()).toString(); - QString pass; + if(!user.isEmpty()) { QMessageBox::StandardButton doyou = QMessageBox::question(this, tr("Download ?"), tr("Do you wish to download the scene" " using the SSH preferences ?")); - bool ok; do_download= (doyou == QMessageBox::Yes); - if(do_download) - { - pass = QInputDialog::getText(this, "SSH Password", - "Enter ssh key password:", - QLineEdit::Password, - tr(""), - &ok); - if(!ok) - return; - pass = pass.trimmed(); - } } #endif @@ -3627,12 +3621,27 @@ void MainWindow::on_actionLoad_a_Scene_from_a_Script_File_triggered() path.prepend("Polyhedron_demo_"); try{ ssh_session session; - bool res = establish_ssh_session(session, - user.toStdString().c_str(), - server.toStdString().c_str(), - pk.toStdString().c_str(), - privK.toStdString().c_str(), - pass.toStdString().c_str()); + bool res = establish_ssh_session_from_agent(session, + user.toStdString().c_str(), + server.toStdString().c_str(), + pk.toStdString().c_str()); + if(!res){ + bool ok; + QString pass= QInputDialog::getText(this, "SSH Password", + "Enter ssh key password:", + QLineEdit::Password, + tr(""), + &ok); + if(!ok) + return; + pass = pass.trimmed(); + res = establish_ssh_session(session, + user.toStdString().c_str(), + server.toStdString().c_str(), + pk.toStdString().c_str(), + privK.toStdString().c_str(), + pass.toStdString().c_str()); + } if(!res) { QMessageBox::warning(this, diff --git a/Polyhedron/demo/Polyhedron/Use_ssh.cpp b/Polyhedron/demo/Polyhedron/Use_ssh.cpp index 8acc1801b8e..c54d4ff14f1 100644 --- a/Polyhedron/demo/Polyhedron/Use_ssh.cpp +++ b/Polyhedron/demo/Polyhedron/Use_ssh.cpp @@ -135,6 +135,79 @@ bool establish_ssh_session(ssh_session &session, return true; } + +bool establish_ssh_session_from_agent(ssh_session& session, + const char *user, + const char *server, + const char *pub_key_path) +{ + int port = 22; + + //Can use SSH_LOG_PROTOCOL here for verbose output + int verbosity = SSH_LOG_NOLOG; + int res; + //retry 4 times max each time the connection asks to be retried. + for(int k = 0; k < 4; ++k) + { + session = ssh_new(); + ssh_options_set( session, SSH_OPTIONS_LOG_VERBOSITY, &verbosity ); + ssh_options_set( session, SSH_OPTIONS_PORT, &port ); + ssh_options_set( session, SSH_OPTIONS_USER, user ); + ssh_options_set( session, SSH_OPTIONS_HOST, server); + + ssh_connect(session); +#if LIBSSH_VERSION_MAJOR <1 && LIBSSH_VERSION_MINOR < 8 + if( ssh_is_server_known(session) != SSH_SERVER_KNOWN_OK ) +#else + if( ssh_session_is_known_server(session) != SSH_KNOWN_HOSTS_OK ) +#endif + { + if(QMessageBox::warning(CGAL::Three::Three::mainWindow(), QString("Unknown Server"), + QString ("The server you are trying to join is not known.\n" + "Do you wish to add it to the known servers list and continue?"), + QMessageBox::Yes | QMessageBox::No) != QMessageBox::Yes) + { + return false; + } +#if LIBSSH_VERSION_MAJOR <1 && LIBSSH_VERSION_MINOR < 8 + if( ssh_write_knownhost(session) != SSH_OK ) +#else + if( ssh_session_update_known_hosts(session) != SSH_OK ) +#endif + { + std::cerr << "writeKnownHost failed" << std::endl; + return false; + } + else + { + ssh_connect(session); + } + } + ssh_key pubkey = ssh_key_new(); + ssh_pki_import_pubkey_file(pub_key_path, &pubkey); + res = ssh_userauth_try_publickey(session, NULL, pubkey); + if(res == SSH_AUTH_AGAIN) + ssh_disconnect(session); + else + break; + } + + + if(!test_result(res)) + { + ssh_disconnect(session); + return false; + } + + res = ssh_userauth_agent(session, user); + if(!test_result(res)) + { + ssh_disconnect(session); + return false; + } + return true; +} + void close_connection(ssh_session &session) { ssh_disconnect(session); diff --git a/Polyhedron/demo/Polyhedron/include/CGAL/Use_ssh.h b/Polyhedron/demo/Polyhedron/include/CGAL/Use_ssh.h index 2cdca27452b..7d3ea0bdcc9 100644 --- a/Polyhedron/demo/Polyhedron/include/CGAL/Use_ssh.h +++ b/Polyhedron/demo/Polyhedron/include/CGAL/Use_ssh.h @@ -12,6 +12,12 @@ bool establish_ssh_session(ssh_session& session, const char *pub_key_path, const char *priv_key_path, const char *priv_key_password); + +bool establish_ssh_session_from_agent(ssh_session& session, + const char *user, + const char *server, + const char *pub_key_path); + void close_connection(ssh_session& session); bool push_file(ssh_session& session, From 8be919e7b6c663118212b139c85070b35d31dd9b Mon Sep 17 00:00:00 2001 From: Maxime Gimeno Date: Tue, 19 May 2020 15:41:36 +0200 Subject: [PATCH 423/568] Smooth the ws cam --- Polyhedron/demo/Polyhedron/Viewer.cpp | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/Polyhedron/demo/Polyhedron/Viewer.cpp b/Polyhedron/demo/Polyhedron/Viewer.cpp index 8c2246b04fc..57896da54a6 100644 --- a/Polyhedron/demo/Polyhedron/Viewer.cpp +++ b/Polyhedron/demo/Polyhedron/Viewer.cpp @@ -2020,7 +2020,12 @@ void Viewer::onTextMessageSocketReceived(QString message) if(session != d->session){ return; } - moveCameraToCoordinates(position, 0.05f); + QStringList sl = position.split(" "); + CGAL::qglviewer::Vec pos(sl[0].toDouble(),sl[1].toDouble(),sl[2].toDouble()); + CGAL::qglviewer::Quaternion q(sl[3].toDouble(),sl[4].toDouble(), + sl[5].toDouble(),sl[6].toDouble()); + camera()->frame()->setPositionAndOrientation(pos, q); + update(); } #endif #include "Viewer.moc" From 6f946f21109b6413989afa299e97a806e87ed662 Mon Sep 17 00:00:00 2001 From: Maxime Gimeno Date: Tue, 19 May 2020 16:27:36 +0200 Subject: [PATCH 424/568] Check string list size --- Polyhedron/demo/Polyhedron/Viewer.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/Polyhedron/demo/Polyhedron/Viewer.cpp b/Polyhedron/demo/Polyhedron/Viewer.cpp index 57896da54a6..71351434517 100644 --- a/Polyhedron/demo/Polyhedron/Viewer.cpp +++ b/Polyhedron/demo/Polyhedron/Viewer.cpp @@ -2021,6 +2021,9 @@ void Viewer::onTextMessageSocketReceived(QString message) return; } QStringList sl = position.split(" "); + if(sl.size() != 7) + return; + CGAL::qglviewer::Vec pos(sl[0].toDouble(),sl[1].toDouble(),sl[2].toDouble()); CGAL::qglviewer::Quaternion q(sl[3].toDouble(),sl[4].toDouble(), sl[5].toDouble(),sl[6].toDouble()); From ed6c1cb95ed340cc2dda45cca4d74a70cec0e27f Mon Sep 17 00:00:00 2001 From: Maxime Gimeno Date: Tue, 19 May 2020 16:35:24 +0200 Subject: [PATCH 425/568] give urls to explain why ignore warnings --- Polyhedron/demo/Polyhedron/Viewer.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/Polyhedron/demo/Polyhedron/Viewer.cpp b/Polyhedron/demo/Polyhedron/Viewer.cpp index 71351434517..57ed3f9d84f 100644 --- a/Polyhedron/demo/Polyhedron/Viewer.cpp +++ b/Polyhedron/demo/Polyhedron/Viewer.cpp @@ -1691,6 +1691,9 @@ void Viewer::setTotalPass(int p) void Viewer::messageLogged(QOpenGLDebugMessage msg) { //filter out useless warning + // From those two links, we decided we didn't care for this warning: + // https://community.khronos.org/t/vertex-shader-in-program-2-is-being-recompiled-based-on-gl-state/76019 + // https://stackoverflow.com/questions/12004396/opengl-debug-context-performance-warning if(msg.message().contains("is being recompiled")) return; QString error; From 12c0ec0935b1d42a880d93a6b916c4edb688ac8e Mon Sep 17 00:00:00 2001 From: Laurent Rineau Date: Tue, 19 May 2020 17:11:18 +0200 Subject: [PATCH 426/568] New debug code in ... tested in `test/Triangulation_2/test_cdt_degenerate_case.cpp`. --- .../CGAL/Constrained_triangulation_2.h | 110 +++++++++++++++++- .../test/Triangulation_2/issue_4405.cpp | 32 ++++- .../test_cdt_degenerate_case.cpp | 38 +++++- 3 files changed, 176 insertions(+), 4 deletions(-) diff --git a/Triangulation_2/include/CGAL/Constrained_triangulation_2.h b/Triangulation_2/include/CGAL/Constrained_triangulation_2.h index a433e3ddd5c..3d496107b55 100644 --- a/Triangulation_2/include/CGAL/Constrained_triangulation_2.h +++ b/Triangulation_2/include/CGAL/Constrained_triangulation_2.h @@ -52,6 +52,23 @@ struct Exact_predicates_tag{}; // to be used with filtered exact number namespace internal { +#ifdef CGAL_CDT_2_DEBUG_INTERSECTIONS + struct Indentation_level { + int n = 0; + friend std::ostream& operator<<(std::ostream& os, Indentation_level level) { + return os << std::string(2*level.n, ' '); + } + Indentation_level& operator++() { ++n; return *this; } + Indentation_level& operator--() { --n; return *this; } + struct Exit_guard { + Indentation_level& level; + ~Exit_guard() { --level; } + }; + Exit_guard exit_guard() { return Exit_guard{*this}; } + Exit_guard open_new_scope() { return Exit_guard{++*this}; } + } cdt_2_indent_level; +#endif // CGAL_CDT_2_DEBUG_INTERSECTIONS + template struct Itag { typedef typename boost::mpl::if_::Is_exact, @@ -690,10 +707,25 @@ insert_constraint(Vertex_handle vaa, Vertex_handle vbb) std::stack > stack; stack.push(std::make_pair(vaa,vbb)); +#ifdef CGAL_CDT_2_DEBUG_INTERSECTIONS + std::cerr << CGAL::internal::cdt_2_indent_level + << "CT_2::insert_constraint( #" << vaa->time_stamp() << "= " << vaa->point() + << " , #" << vbb->time_stamp() << "= " << vbb->point() + << " )\n"; + auto exit_guard = CGAL::internal::cdt_2_indent_level.open_new_scope(); +#endif // CGAL_CDT_2_DEBUG_INTERSECTIONS while(! stack.empty()){ boost::tie(vaa,vbb) = stack.top(); stack.pop(); CGAL_triangulation_precondition( vaa != vbb); +#ifdef CGAL_CDT_2_DEBUG_INTERSECTIONS + std::cerr << CGAL::internal::cdt_2_indent_level + << "CT_2::insert_constraint, stack pop=( #" << vaa->time_stamp() << "= " << vaa->point() + << " , #" << vbb->time_stamp() << "= " << vbb->point() + << " ) remaining stack size: " + << stack.size() << '\n'; + CGAL_assertion(this->is_valid()); +#endif // CGAL_CDT_2_DEBUG_INTERSECTIONS Vertex_handle vi; Face_handle fr; @@ -716,10 +748,26 @@ insert_constraint(Vertex_handle vaa, Vertex_handle vbb) vi); if ( intersection) { if (vi != vaa && vi != vbb) { +#ifdef CGAL_CDT_2_DEBUG_INTERSECTIONS + std::cerr << CGAL::internal::cdt_2_indent_level + << "CT_2::insert_constraint stask push [vaa, vi] ( #" << vaa->time_stamp() << "= " << vaa->point() + << " , #" << vi->time_stamp() << "= " << vi->point() + << " )\n"; + std::cerr << CGAL::internal::cdt_2_indent_level + << "CT_2::insert_constraint stask push [vi, vbb] ( #" << vi->time_stamp() << "= " << vi->point() + << " , #" << vbb->time_stamp() << "= " << vbb->point() + << " )\n"; +#endif // CGAL_CDT_2_DEBUG_INTERSECTIONS stack.push(std::make_pair(vaa,vi)); stack.push(std::make_pair(vi,vbb)); } else{ +#ifdef CGAL_CDT_2_DEBUG_INTERSECTIONS + std::cerr << CGAL::internal::cdt_2_indent_level + << "CT_2::insert_constraint stask push [vaa, vbb]( #" << vaa->time_stamp() << "= " << vaa->point() + << " , #" << vbb->time_stamp() << "= " << vbb->point() + << " )\n"; +#endif // CGAL_CDT_2_DEBUG_INTERSECTIONS stack.push(std::make_pair(vaa,vbb)); } continue; @@ -763,6 +811,30 @@ find_intersected_faces(Vertex_handle vaa, // to deal with the case where the first crossed edge // is constrained +#ifdef CGAL_CDT_2_DEBUG_INTERSECTIONS + std::cerr << CGAL::internal::cdt_2_indent_level + << "CT_2::find_intersected_faces ( #" << vaa->time_stamp() << "= " << vaa->point() + << " , #" << vbb->time_stamp() << "= " << vbb->point() + << " )\n" + << CGAL::internal::cdt_2_indent_level + << "> current constrained edges are:\n"; + for(Constrained_edges_iterator edge_it = this->constrained_edges_begin(), + end = this->constrained_edges_end(); + edge_it != end; ++edge_it) + { + std::cerr < (#" + << edge_it->first->vertex(cw(edge_it->second))->time_stamp() + << ", #" + << edge_it->first->vertex(ccw(edge_it->second))->time_stamp() + << ")\n"; + } + std::cerr << CGAL::internal::cdt_2_indent_level + << "> current face is ( #" << current_face->vertex(0)->time_stamp() + << " #" << current_face->vertex(1)->time_stamp() + << " #" << current_face->vertex(2)->time_stamp() << " )\n"; +#endif // CGAL_CDT_2_DEBUG_INTERSECTIONS + if(current_face->is_constrained(ind)) { vi=intersect(current_face, ind, vaa, vbb); return true; @@ -909,6 +981,14 @@ intersect(Face_handle f, int i, const Point& pc = vcc->point(); const Point& pd = vdd->point(); +#ifdef CGAL_CDT_2_DEBUG_INTERSECTIONS + std::cerr << CGAL::internal::cdt_2_indent_level + << "CT_2::intersect segment ( #" << vaa->time_stamp() << "= " << vaa->point() + << " , #" << vbb->time_stamp() << "= " << vbb->point() + << " ) with edge ( #"<< vcc->time_stamp() << "= " << vcc->point() + << " , #" << vdd->time_stamp() << "= " << vdd->point() + << " )\n"; +#endif // CGAL_CDT_2_DEBUG_INTERSECTIONS Point pi; //creator for point is required here Itag itag = Itag(); bool ok = intersection(geom_traits(), pa, pb, pc, pd, pi, itag ); @@ -930,6 +1010,11 @@ intersect(Face_handle f, int i, remove_constrained_edge(f, i); vi = virtual_insert(pi, f); } +#ifdef CGAL_CDT_2_DEBUG_INTERSECTIONS + std::cerr << CGAL::internal::cdt_2_indent_level + << "CT_2::intersect, `vi` is ( #" << vi->time_stamp() << "= " << vi->point() + << " )\n"; +#endif // CGAL_CDT_2_DEBUG_INTERSECTIONS // vi == vc or vi == vd may happen even if intersection==true // due to approximate construction of the intersection @@ -1185,6 +1270,14 @@ void Constrained_triangulation_2:: remove_constrained_edge(Face_handle f, int i) { +#ifdef CGAL_CDT_2_DEBUG_INTERSECTIONS + std::cerr << CGAL::internal::cdt_2_indent_level + << "CT_2::remove_constrained_edge ( #" + << f->vertex(cw(i))->time_stamp() + << ", #" + << f->vertex(ccw(i))->time_stamp() + << ")\n"; +#endif // CGAL_CDT_2_DEBUG_INTERSECTIONS f->set_constraint(i, false); if (dimension() == 2) (f->neighbor(i))->set_constraint(this->mirror_index(f,i), false); @@ -1443,7 +1536,8 @@ intersection(const Gt& gt, if(!result) return result; if(pi == pa || pi == pb || pi == pc || pi == pd) { #ifdef CGAL_CDT_2_DEBUG_INTERSECTIONS - std::cerr << " CT_2::intersection: intersection is an existing point " + std::cerr << CGAL::internal::cdt_2_indent_level + << " CT_2::intersection: intersection is an existing point " << pi << std::endl; #endif return result; @@ -1465,7 +1559,8 @@ intersection(const Gt& gt, if(do_overlap(bb, bbox(pd))) pi = pd; #ifdef CGAL_CDT_2_DEBUG_INTERSECTIONS if(pi == pa || pi == pb || pi == pc || pi == pd) { - std::cerr << " CT_2::intersection: intersection SNAPPED to an existing point " + std::cerr << CGAL::internal::cdt_2_indent_level + << " CT_2::intersection: intersection SNAPPED to an existing point " << pi << std::endl; } #endif @@ -1503,6 +1598,17 @@ compute_intersection(const Gt& gt, construct_segment=gt.construct_segment_2_object(); Object result = compute_intersec(construct_segment(pa,pb), construct_segment(pc,pd)); +#ifdef CGAL_CDT_2_DEBUG_INTERSECTIONS + typename Gt::Segment_2 s; + if(assign(s, result)) { + std::cerr << CGAL::internal::cdt_2_indent_level + << "compute_intersection: " << s << '\n'; + } + if(assign(pi, result)) { + std::cerr << CGAL::internal::cdt_2_indent_level + << "compute_intersection: " << pi << '\n'; + } +#endif // CGAL_CDT_2_DEBUG_INTERSECTIONS return assign(pi, result); } diff --git a/Triangulation_2/test/Triangulation_2/issue_4405.cpp b/Triangulation_2/test/Triangulation_2/issue_4405.cpp index 89199d56141..770cd6c761c 100644 --- a/Triangulation_2/test/Triangulation_2/issue_4405.cpp +++ b/Triangulation_2/test/Triangulation_2/issue_4405.cpp @@ -9,13 +9,43 @@ typedef CGAL::Epick Kernel; typedef Kernel::FT FieldNumberType; typedef Kernel::Point_2 Point2; typedef Kernel::Point_3 Point3; + +template +class My_vertex_base : public Vb { + std::size_t time_stamp_; +public: + My_vertex_base() : Vb(), time_stamp_(-1) { + } + + My_vertex_base(const My_vertex_base& other) : + Vb(other), + time_stamp_(other.time_stamp_) + {} + + typedef CGAL::Tag_true Has_timestamp; + + std::size_t time_stamp() const { + return time_stamp_; + } + void set_time_stamp(const std::size_t& ts) { + time_stamp_ = ts; + } + + template < class TDS > + struct Rebind_TDS { + typedef typename Vb::template Rebind_TDS::Other Vb2; + typedef My_vertex_base Other; + }; +}; + struct FaceInfo2 { unsigned long long m_id; }; typedef CGAL::Projection_traits_xy_3 TriangulationTraits; typedef CGAL::Triangulation_vertex_base_with_id_2 VertexBaseWithId; -typedef CGAL::Triangulation_vertex_base_2 VertexBase; +typedef My_vertex_base Vb2; +typedef CGAL::Triangulation_vertex_base_2 VertexBase; typedef CGAL::Triangulation_face_base_with_info_2 FaceBaseWithInfo; typedef CGAL::Constrained_triangulation_face_base_2 FaceBase; typedef CGAL::Triangulation_data_structure_2 TriangulationData; diff --git a/Triangulation_2/test/Triangulation_2/test_cdt_degenerate_case.cpp b/Triangulation_2/test/Triangulation_2/test_cdt_degenerate_case.cpp index 5dc1d1c7afa..952a7428f5b 100644 --- a/Triangulation_2/test/Triangulation_2/test_cdt_degenerate_case.cpp +++ b/Triangulation_2/test/Triangulation_2/test_cdt_degenerate_case.cpp @@ -1,3 +1,4 @@ +#define CGAL_CDT_2_DEBUG_INTERSECTIONS 1 #include #include #include @@ -5,7 +6,41 @@ typedef CGAL::Exact_predicates_inexact_constructions_kernel EPIC; typedef EPIC::Point_2 Point_2; -typedef CGAL::Triangulation_vertex_base_2 Vb; + +template +class My_vertex_base : public Vb { + std::size_t time_stamp_; +public: + My_vertex_base() : Vb(), time_stamp_(-1) { + } + + My_vertex_base(const My_vertex_base& other) : + Vb(other), + time_stamp_(other.time_stamp_) + {} + + typedef CGAL::Tag_true Has_timestamp; + + std::size_t time_stamp() const { + return time_stamp_; + } + void set_time_stamp(const std::size_t& ts) { + time_stamp_ = ts; + } + + template < class TDS > + struct Rebind_TDS { + typedef typename Vb::template Rebind_TDS::Other Vb2; + typedef My_vertex_base Other; + }; +}; + +#ifdef CGAL_CDT_2_DEBUG_INTERSECTIONS +using Vb = My_vertex_base>; +#else +using Vb = CGAL::Triangulation_vertex_base_2; +#endif + typedef CGAL::Constrained_triangulation_face_base_2 Fb; typedef CGAL::Triangulation_data_structure_2 TDS; typedef CGAL::Exact_predicates_tag Itag; @@ -14,6 +49,7 @@ typedef CGAL::Constrained_triangulation_plus_2 CDTp2; template void test() { + std::cerr.precision(17); CDT cdt; cdt.insert_constraint(Point_2( 48.0923419883269, 299.7232779774145 ), Point_2( 66.05373710316852, 434.231770798343 )); From 3cd52cdc3e4eddc17ad33fe68fdc6db2b8c67028 Mon Sep 17 00:00:00 2001 From: Laurent Rineau Date: Tue, 19 May 2020 17:12:02 +0200 Subject: [PATCH 427/568] Fix a bug in The function parameter was locally shadowed by a local `int i` variable! Then the edge `(f, i)` in the call `remove_constrained_edge(f, i)` was the wrong one! The bug was introduced by ecfd82e287378977a325ae34e21087a2075a05cd, ten years ago. The bug was only triggered on degenerated cases, when two constraints intersect, but the code failed to compute the intersection. Then, if the intersection vertex `vi` was either `vaa` or `vbb` (and not `vcc` or `vdd`), then the edge `(f, i)` was the wrong one. --- Triangulation_2/include/CGAL/Constrained_triangulation_2.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Triangulation_2/include/CGAL/Constrained_triangulation_2.h b/Triangulation_2/include/CGAL/Constrained_triangulation_2.h index 3d496107b55..916acdcfd97 100644 --- a/Triangulation_2/include/CGAL/Constrained_triangulation_2.h +++ b/Triangulation_2/include/CGAL/Constrained_triangulation_2.h @@ -995,8 +995,8 @@ intersect(Face_handle f, int i, Vertex_handle vi; if ( !ok) { //intersection detected but not computed - int i = limit_intersection(geom_traits(), pa, pb, pc, pd, itag); - switch(i){ + int int_index = limit_intersection(geom_traits(), pa, pb, pc, pd, itag); + switch(int_index){ case 0 : vi = vaa; break; case 1 : vi = vbb; break; case 2 : vi = vcc; break; From 6b05f820e7dc9131c8db9163b4faa04f1bf2fd1d Mon Sep 17 00:00:00 2001 From: Laurent Rineau Date: Tue, 19 May 2020 20:28:11 +0200 Subject: [PATCH 428/568] Markdown formatting of code --- Installation/CHANGES.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Installation/CHANGES.md b/Installation/CHANGES.md index 2918a16911e..0f71f6532db 100644 --- a/Installation/CHANGES.md +++ b/Installation/CHANGES.md @@ -49,7 +49,7 @@ Release date: June 2020 ### 2D Arrangement on Surface - Changed intersection return type from legacy `CGAL::Object` to modern `boost::variant` in all traits concepts and models. - As there is an implicit conversion from boost::variant to CGAL::Object, the + As there is an implicit conversion from `boost::variant` to `CGAL::Object`, the new code is backward compatible. However, it is recommended that all calls to the intersection functions are fixed to use the new return type. From b495c0045054a4a7b9adfee3c8d0fba7b7288282 Mon Sep 17 00:00:00 2001 From: Jing Yang Date: Tue, 19 May 2020 23:42:56 -0700 Subject: [PATCH 429/568] add include of other modules --- Installation/lib/cmake/CGAL/CGALConfig.cmake | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/Installation/lib/cmake/CGAL/CGALConfig.cmake b/Installation/lib/cmake/CGAL/CGALConfig.cmake index 11ff7810d31..de6a495a1bc 100644 --- a/Installation/lib/cmake/CGAL/CGALConfig.cmake +++ b/Installation/lib/cmake/CGAL/CGALConfig.cmake @@ -159,7 +159,17 @@ endforeach() cgal_setup_module_path() set(CGAL_USE_FILE ${CGAL_MODULES_DIR}/UseCGAL.cmake) +include(${CGAL_MODULES_DIR}/CGAL_target_use_Boost_IOStreams.cmake) +include(${CGAL_MODULES_DIR}/CGAL_target_use_Boost_Serialization.cmake) +include(${CGAL_MODULES_DIR}/CGAL_target_use_Eigen.cmake) +include(${CGAL_MODULES_DIR}/CGAL_target_use_GLPK.cmake) +include(${CGAL_MODULES_DIR}/CGAL_target_use_LASLIB.cmake) +include(${CGAL_MODULES_DIR}/CGAL_target_use_OpenCV.cmake) +include(${CGAL_MODULES_DIR}/CGAL_target_use_OpenGR.cmake) +include(${CGAL_MODULES_DIR}/CGAL_target_use_SCIP.cmake) include(${CGAL_MODULES_DIR}/CGAL_target_use_TBB.cmake) +include(${CGAL_MODULES_DIR}/CGAL_target_use_TensorFlow.cmake) +include(${CGAL_MODULES_DIR}/CGAL_target_use_pointmatcher.cmake) include("${CGAL_MODULES_DIR}/CGAL_parse_version_h.cmake") cgal_parse_version_h( "${CGAL_INSTALLATION_PACKAGE_DIR}/include/CGAL/version.h" From 319383c9631b1418be20ac0998b290b401318778 Mon Sep 17 00:00:00 2001 From: Laurent Rineau Date: Wed, 20 May 2020 09:47:58 +0200 Subject: [PATCH 430/568] Revert "Merge pull request #4519 from lrineau/Kernel_23-Epeck_objects_in_Compact_container-lrineau_gdamiand" This reverts commit bcab082f8272a45d68a3bdf09fed7c053f0bcaf1, reversing changes made to 2d3e126450991ab7a42d067d30f613b883d6802e. --- .../CGAL/Arr_point_location/Td_X_trapezoid.h | 10 ++-- .../CGAL/Arr_point_location/Td_active_edge.h | 8 ++-- .../Td_active_fictitious_vertex.h | 8 ++-- .../Arr_point_location/Td_active_trapezoid.h | 8 ++-- .../Arr_point_location/Td_active_vertex.h | 8 ++-- .../include/CGAL/Arr_point_location/Td_dag.h | 18 +++---- .../CGAL/Arr_point_location/Td_dag_node.h | 18 +++---- .../Arr_point_location/Td_inactive_edge.h | 6 +-- .../Td_inactive_fictitious_vertex.h | 6 +-- .../Arr_point_location/Td_inactive_vertex.h | 6 +-- .../include/CGAL/IO/Tee_for_output_iterator.h | 4 +- Filtered_kernel/include/CGAL/Lazy.h | 8 ++-- STL_Extension/include/CGAL/Handle.h | 48 ++++++++----------- 13 files changed, 75 insertions(+), 81 deletions(-) diff --git a/Arrangement_on_surface_2/include/CGAL/Arr_point_location/Td_X_trapezoid.h b/Arrangement_on_surface_2/include/CGAL/Arr_point_location/Td_X_trapezoid.h index a52f91db9d2..e7202ffe935 100644 --- a/Arrangement_on_surface_2/include/CGAL/Arr_point_location/Td_X_trapezoid.h +++ b/Arrangement_on_surface_2/include/CGAL/Arr_point_location/Td_X_trapezoid.h @@ -142,7 +142,7 @@ public: private: - Trpz_parameter_space* ptr() const { return (Trpz_parameter_space*)(PTR.p); } + Trpz_parameter_space* ptr() const { return (Trpz_parameter_space*)(PTR); } #ifndef CGAL_TD_DEBUG @@ -323,7 +323,7 @@ public: { //define the initial trapezoid: left, right, btm, top are at infinity. // its type is TD_TRAPEZOID ,it is on all boundaries, and has no neighbours - PTR.p = new Trpz_parameter_space + PTR = new Trpz_parameter_space (Traits::vtx_at_left_infinity(), Traits::vtx_at_right_infinity(), Traits::he_at_bottom_infinity(), @@ -353,7 +353,7 @@ public: else //tp == TD_VERTEX type_flag |= CGAL_TD_VERTEX; - PTR.p = new Trpz_parameter_space + PTR = new Trpz_parameter_space (l, r, b, t, type_flag | boundness_flag, lb, lt, rb, rt); m_dag_node = node; } @@ -370,7 +370,7 @@ public: Self* rb = 0, Self* rt = 0, Dag_node* node = 0) { - PTR.p = new Trpz_parameter_space + PTR = new Trpz_parameter_space (l ? *l : Traits::vtx_at_left_infinity(), r ? *r : Traits::vtx_at_right_infinity(), b ? *b : Traits::he_at_bottom_infinity(), @@ -436,7 +436,7 @@ public: /*! Access the trapezoid id (PTR). */ CGAL_TD_INLINE unsigned long id() const { - return (unsigned long) PTR.p; + return (unsigned long) PTR; } /*! Access trapezoid left. */ diff --git a/Arrangement_on_surface_2/include/CGAL/Arr_point_location/Td_active_edge.h b/Arrangement_on_surface_2/include/CGAL/Arr_point_location/Td_active_edge.h index 2cdeee6bca5..61259f33547 100644 --- a/Arrangement_on_surface_2/include/CGAL/Arr_point_location/Td_active_edge.h +++ b/Arrangement_on_surface_2/include/CGAL/Arr_point_location/Td_active_edge.h @@ -135,7 +135,7 @@ public: private: - Data* ptr() const { return (Data*)(PTR.p); } + Data* ptr() const { return (Data*)(PTR); } #ifndef CGAL_TD_DEBUG @@ -194,7 +194,7 @@ public: Td_active_edge () { - PTR.p = new Data + PTR = new Data (Traits::empty_he_handle(), Td_map_item(0), nullptr); //m_dag_node = nullptr; } @@ -204,7 +204,7 @@ public: boost::optional next = boost::none) { - PTR.p = new Data(he, (next) ? *next : Td_map_item(0), node); + PTR = new Data(he, (next) ? *next : Td_map_item(0), node); //m_dag_node = node; } @@ -261,7 +261,7 @@ public: /*! Access the trapezoid id (PTR). */ CGAL_TD_INLINE unsigned long id() const { - return (unsigned long) PTR.p; + return (unsigned long) PTR; } diff --git a/Arrangement_on_surface_2/include/CGAL/Arr_point_location/Td_active_fictitious_vertex.h b/Arrangement_on_surface_2/include/CGAL/Arr_point_location/Td_active_fictitious_vertex.h index 6bfb3d5e6f2..b75de1b9d97 100644 --- a/Arrangement_on_surface_2/include/CGAL/Arr_point_location/Td_active_fictitious_vertex.h +++ b/Arrangement_on_surface_2/include/CGAL/Arr_point_location/Td_active_fictitious_vertex.h @@ -129,7 +129,7 @@ public: }; private: - Data* ptr() const { return (Data*)(PTR.p); } + Data* ptr() const { return (Data*)(PTR); } Curve_end vtx_to_ce(Vertex_const_handle v) const { @@ -180,14 +180,14 @@ public: Td_active_fictitious_vertex() { - PTR.p = new Data(Traits::empty_vtx_handle(), Traits::empty_he_handle(), nullptr); + PTR = new Data(Traits::empty_vtx_handle(), Traits::empty_he_handle(), nullptr); } /*! Constructor given Vertex & Halfedge handles. */ Td_active_fictitious_vertex(Vertex_const_handle v, Halfedge_const_handle cw_he, Dag_node* node = 0) - { PTR.p = new Data(v, cw_he, node); } + { PTR = new Data(v, cw_he, node); } /*! Copy constructor. */ @@ -224,7 +224,7 @@ public: inline const Self& self() const { return *this; } /*! Access the trapezoid id (PTR). */ - inline unsigned long id() const { return (unsigned long) PTR.p; } + inline unsigned long id() const { return (unsigned long) PTR; } /*! Access trapezoid left. * filters out the infinite case which returns predefined dummy values diff --git a/Arrangement_on_surface_2/include/CGAL/Arr_point_location/Td_active_trapezoid.h b/Arrangement_on_surface_2/include/CGAL/Arr_point_location/Td_active_trapezoid.h index 2b565adba74..8b92b739626 100644 --- a/Arrangement_on_surface_2/include/CGAL/Arr_point_location/Td_active_trapezoid.h +++ b/Arrangement_on_surface_2/include/CGAL/Arr_point_location/Td_active_trapezoid.h @@ -144,7 +144,7 @@ public: private: - Data* ptr() const { return (Data*)(PTR.p); } + Data* ptr() const { return (Data*)(PTR); } public: @@ -255,7 +255,7 @@ private: { //define the initial trapezoid: left, right, btm, top are at infinity. // has no neighbours - PTR.p = new Data + PTR = new Data (Traits::empty_vtx_handle(), Traits::empty_vtx_handle(), Traits::empty_he_handle(), @@ -274,7 +274,7 @@ private: boost::optional rt = boost::none, Dag_node* node = 0) { - PTR.p = new Data (l, r, b, t, (lb) ? *lb : Td_map_item(0), (lt) ? *lt : Td_map_item(0), + PTR = new Data (l, r, b, t, (lb) ? *lb : Td_map_item(0), (lt) ? *lt : Td_map_item(0), (rb) ? *rb : Td_map_item(0), (rt) ? *rt : Td_map_item(0), node); //m_dag_node = node; } @@ -332,7 +332,7 @@ private: /*! Access the trapezoid id (PTR). */ inline unsigned long id() const { - return (unsigned long) PTR.p; + return (unsigned long) PTR; } /*! Access trapezoid left. diff --git a/Arrangement_on_surface_2/include/CGAL/Arr_point_location/Td_active_vertex.h b/Arrangement_on_surface_2/include/CGAL/Arr_point_location/Td_active_vertex.h index de4000ebfd9..3b3e86aa0c6 100644 --- a/Arrangement_on_surface_2/include/CGAL/Arr_point_location/Td_active_vertex.h +++ b/Arrangement_on_surface_2/include/CGAL/Arr_point_location/Td_active_vertex.h @@ -134,7 +134,7 @@ public: }; private: - Data* ptr() const { return (Data*)(PTR.p); } + Data* ptr() const { return (Data*)(PTR); } Curve_end vtx_to_ce(Vertex_const_handle v) const { @@ -184,14 +184,14 @@ public: Td_active_vertex() { - PTR.p = new Data(Traits::empty_vtx_handle(), Traits::empty_he_handle(), nullptr); + PTR = new Data(Traits::empty_vtx_handle(), Traits::empty_he_handle(), nullptr); } /*! Constructor given Vertex & Halfedge handles. */ Td_active_vertex(Vertex_const_handle v, Halfedge_const_handle cw_he, Dag_node* node = 0) - { PTR.p = new Data(v, cw_he, node); } + { PTR = new Data(v, cw_he, node); } /*! Copy constructor. */ @@ -228,7 +228,7 @@ public: inline const Self& self() const { return *this; } /*! Access the trapezoid id (PTR). */ - inline unsigned long id() const { return (unsigned long) PTR.p; } + inline unsigned long id() const { return (unsigned long) PTR; } inline Vertex_const_handle vertex() const { return ptr()->v; } diff --git a/Arrangement_on_surface_2/include/CGAL/Arr_point_location/Td_dag.h b/Arrangement_on_surface_2/include/CGAL/Arr_point_location/Td_dag.h index e5eee91e724..f8a47536c85 100644 --- a/Arrangement_on_surface_2/include/CGAL/Arr_point_location/Td_dag.h +++ b/Arrangement_on_surface_2/include/CGAL/Arr_point_location/Td_dag.h @@ -41,14 +41,14 @@ public: //iddo (for CC-7.2) maybe protected? typedef const T & const_reference; protected: - void init() { PTR.p = 0; } + void init() { PTR = 0; } public: Td_dag_base() {init();} Td_dag_base(const Td_dag_base & x) : Handle(x) {} Td_dag_base & operator=(const Td_dag_base & x) {Handle::operator=(x); return *this; } - bool operator!() const { return PTR.p == 0; } + bool operator!() const { return PTR == 0; } }; template @@ -96,9 +96,9 @@ public: Td_dag(){} Td_dag(const Td_dag_handle& dag):Td_dag_handle(dag){} Td_dag(const Self& dag):Td_dag_handle(dag){} - Td_dag(const T& rootValue){PTR.p = new node(rootValue);} + Td_dag(const T& rootValue){PTR = new node(rootValue);} Td_dag(const T& rootValue, const Self& left, const Self& right) - {PTR.p = new node(rootValue, left, right); rebalance_depth();} + {PTR = new node(rootValue, left, right); rebalance_depth();} ~Td_dag(){} /* --------information retrieval -------*/ @@ -145,7 +145,7 @@ public: } bool operator==(const Self& b) const { - return PTR.p==b.PTR.p; + return PTR==b.PTR; } bool operator!=(const Self& b) const { @@ -189,7 +189,7 @@ public: // detach left son,redirect to dummy set_left(dummy); // set left son pointer to 0 - ptr()->leftPtr.PTR.p=0; + ptr()->leftPtr.PTR=0; // delete dummy Td_dag delete dummy.ptr(); } @@ -204,7 +204,7 @@ public: // detach right son,redirect to dummy set_right(dummy); // set right son pointer to 0 - ptr()->rightPtr.PTR.p=0; + ptr()->rightPtr.PTR=0; // delete dummy Td_dag delete dummy.ptr(); } @@ -371,7 +371,7 @@ protected: } #endif private: - node* ptr() const {return (node*)PTR.p;} + node* ptr() const {return (node*)PTR;} }; template @@ -441,7 +441,7 @@ template std::ostream& operator<<(std::ostream& out, tech notes: The code is Handle designed. left(),right() are designed to cope with Handle(Handle& x) - precondition x.PTR.p!=0 + precondition x.PTR!=0 operator=() performs shallow copy operator*() returns data type output is done as a binary tree. diff --git a/Arrangement_on_surface_2/include/CGAL/Arr_point_location/Td_dag_node.h b/Arrangement_on_surface_2/include/CGAL/Arr_point_location/Td_dag_node.h index bbf45831519..ec4a961d8f1 100644 --- a/Arrangement_on_surface_2/include/CGAL/Arr_point_location/Td_dag_node.h +++ b/Arrangement_on_surface_2/include/CGAL/Arr_point_location/Td_dag_node.h @@ -39,7 +39,7 @@ template class Td_dag_node_base : public Handle { protected: - void init() { PTR.p = 0; } //MICHAL: I think it is not used - so need to be removed + void init() { PTR = 0; } //MICHAL: I think it is not used - so need to be removed public: //c'tors @@ -57,12 +57,12 @@ public: return *this; } - //bool operator!() const { return PTR.p == 0; } //MICHAL: maybe use ptr(), and also can change to is_null or something similar - bool is_null() const { return PTR.p == 0; } - Rep * ptr() const { return (Rep*) PTR.p; } + //bool operator!() const { return PTR == 0; } //MICHAL: maybe use ptr(), and also can change to is_null or something similar + bool is_null() const { return PTR == 0; } + Rep * ptr() const { return (Rep*) PTR; } protected: - //Rep *& ptr() { return (Rep*) PTR.p; } - void set_ptr(Rep* rep) { PTR.p = rep; } + //Rep *& ptr() { return (Rep*) PTR; } + void set_ptr(Rep* rep) { PTR = rep; } }; @@ -94,7 +94,7 @@ public: #ifndef CGAL_CFG_USING_BASE_MEMBER_BUG_2 public: - //using Td_dag_node_handle::PTR.p; + //using Td_dag_node_handle::PTR; //using Td_dag_node_handle::operator!; #endif //CGAL_CFG_USING_BASE_MEMBER_BUG_2 @@ -549,7 +549,7 @@ protected: private: - Node* node() const { return (Node*)Base::PTR.p; } + Node* node() const { return (Node*)Base::PTR; } }; @@ -629,7 +629,7 @@ std::ostream& operator<< (std::ostream& out, tech notes: The code is Handle designed. left_child(),right_child() are designed to cope with Handle(Handle& x) - precondition x.PTR.p!=0 + precondition x.PTR!=0 operator=() performs shallow copy operator*() returns data type output is done as a binary tree. diff --git a/Arrangement_on_surface_2/include/CGAL/Arr_point_location/Td_inactive_edge.h b/Arrangement_on_surface_2/include/CGAL/Arr_point_location/Td_inactive_edge.h index 0d85f93f148..bb57f7c6d1c 100644 --- a/Arrangement_on_surface_2/include/CGAL/Arr_point_location/Td_inactive_edge.h +++ b/Arrangement_on_surface_2/include/CGAL/Arr_point_location/Td_inactive_edge.h @@ -128,7 +128,7 @@ public: private: - Data* ptr() const { return (Data*)(PTR.p); } + Data* ptr() const { return (Data*)(PTR); } #ifndef CGAL_TD_DEBUG @@ -161,7 +161,7 @@ public: /*! Constructor given Vertex & Halfedge handles. */ Td_inactive_edge (boost::shared_ptr& cv, Dag_node* node = nullptr) { - PTR.p = new Data(cv,node); + PTR = new Data(cv,node); } /*! Copy constructor. */ @@ -215,7 +215,7 @@ public: /*! Access the trapezoid id (PTR). */ inline unsigned long id() const { - return (unsigned long) PTR.p; + return (unsigned long) PTR; } inline X_monotone_curve_2& curve() const diff --git a/Arrangement_on_surface_2/include/CGAL/Arr_point_location/Td_inactive_fictitious_vertex.h b/Arrangement_on_surface_2/include/CGAL/Arr_point_location/Td_inactive_fictitious_vertex.h index cf2d75d79ec..03ca8d563c7 100644 --- a/Arrangement_on_surface_2/include/CGAL/Arr_point_location/Td_inactive_fictitious_vertex.h +++ b/Arrangement_on_surface_2/include/CGAL/Arr_point_location/Td_inactive_fictitious_vertex.h @@ -133,7 +133,7 @@ public: private: - Data* ptr() const { return (Data*)(PTR.p); } + Data* ptr() const { return (Data*)(PTR); } Curve_end vtx_to_ce(Vertex_const_handle v) const { @@ -185,7 +185,7 @@ public: { Curve_end v_ce(vtx_to_ce(v_before_rem)); - PTR.p = new Data( v_ce.cv(), v_ce.ce(), node); + PTR = new Data( v_ce.cv(), v_ce.ce(), node); } @@ -241,7 +241,7 @@ public: /*! Access the trapezoid id (PTR). */ inline unsigned long id() const { - return (unsigned long) PTR.p; + return (unsigned long) PTR; } diff --git a/Arrangement_on_surface_2/include/CGAL/Arr_point_location/Td_inactive_vertex.h b/Arrangement_on_surface_2/include/CGAL/Arr_point_location/Td_inactive_vertex.h index 0c42b1e7669..409a6f576ee 100644 --- a/Arrangement_on_surface_2/include/CGAL/Arr_point_location/Td_inactive_vertex.h +++ b/Arrangement_on_surface_2/include/CGAL/Arr_point_location/Td_inactive_vertex.h @@ -127,7 +127,7 @@ public: private: - Data* ptr() const { return (Data*)(PTR.p); } + Data* ptr() const { return (Data*)(PTR); } #ifndef CGAL_TD_DEBUG @@ -162,7 +162,7 @@ public: /*! Constructor given Vertex & Halfedge handles. */ Td_inactive_vertex (Vertex_const_handle v_before_rem, Dag_node* node = nullptr) { - PTR.p = new Data(v_before_rem->point(), node); + PTR = new Data(v_before_rem->point(), node); } @@ -217,7 +217,7 @@ public: /*! Access the trapezoid id (PTR). */ inline unsigned long id() const { - return (unsigned long) PTR.p; + return (unsigned long) PTR; } inline Point& point() const diff --git a/Convex_hull_2/include/CGAL/IO/Tee_for_output_iterator.h b/Convex_hull_2/include/CGAL/IO/Tee_for_output_iterator.h index 3a298f6b6c0..26aee3bba75 100644 --- a/Convex_hull_2/include/CGAL/IO/Tee_for_output_iterator.h +++ b/Convex_hull_2/include/CGAL/IO/Tee_for_output_iterator.h @@ -39,7 +39,7 @@ class Tee_for_output_iterator public: Tee_for_output_iterator(const OutputIterator& o) : o_it(o) - { PTR.p = (Rep*) new _Tee_for_output_iterator_rep(); } + { PTR = (Rep*) new _Tee_for_output_iterator_rep(); } Tee_for_output_iterator& operator=(const T& value) @@ -82,7 +82,7 @@ public: _Tee_for_output_iterator_rep* ptr() - { return (_Tee_for_output_iterator_rep*)(PTR.p); } + { return (_Tee_for_output_iterator_rep*)PTR; } protected: OutputIterator o_it; diff --git a/Filtered_kernel/include/CGAL/Lazy.h b/Filtered_kernel/include/CGAL/Lazy.h index df94fc2de19..067fbe57463 100644 --- a/Filtered_kernel/include/CGAL/Lazy.h +++ b/Filtered_kernel/include/CGAL/Lazy.h @@ -718,17 +718,17 @@ public : Lazy(Self_rep *r) { - PTR.p = r; + PTR = r; } Lazy(const ET& e) { - PTR.p = new Lazy_rep_0(e); + PTR = new Lazy_rep_0(e); } Lazy(ET&& e) { - PTR.p = new Lazy_rep_0(std::move(e)); + PTR = new Lazy_rep_0(std::move(e)); } friend void swap(Lazy& a, Lazy& b) noexcept @@ -768,7 +768,7 @@ public : return z; } - Self_rep * ptr() const { return (Self_rep*) PTR.p; } + Self_rep * ptr() const { return (Self_rep*) PTR; } }; // The magic functor for Construct_bbox_[2,3], as there is no Lazy diff --git a/STL_Extension/include/CGAL/Handle.h b/STL_Extension/include/CGAL/Handle.h index ca3366524cb..af5297ae2e5 100644 --- a/STL_Extension/include/CGAL/Handle.h +++ b/STL_Extension/include/CGAL/Handle.h @@ -40,31 +40,31 @@ class Handle typedef std::ptrdiff_t Id_type ; Handle() noexcept - : PTR{static_cast(0)} {} + : PTR(static_cast(0)) {} // FIXME: if the precondition throws in a noexcept function, the program terminates Handle(const Handle& x) noexcept { - CGAL_precondition( x.PTR.p != static_cast(0) ); - PTR.p = x.PTR.p; - CGAL_assume (PTR.p->count > 0); - PTR.p->count++; + CGAL_precondition( x.PTR != static_cast(0) ); + PTR = x.PTR; + CGAL_assume (PTR->count > 0); + PTR->count++; } ~Handle() { - if ( PTR.p && (--PTR.p->count == 0)) - delete PTR.p; + if ( PTR && (--PTR->count == 0)) + delete PTR; } Handle& operator=(const Handle& x) noexcept { - CGAL_precondition( x.PTR.p != static_cast(0) ); - x.PTR.p->count++; - if ( PTR.p && (--PTR.p->count == 0)) - delete PTR.p; - PTR.p = x.PTR.p; + CGAL_precondition( x.PTR != static_cast(0) ); + x.PTR->count++; + if ( PTR && (--PTR->count == 0)) + delete PTR; + PTR = x.PTR; return *this; } @@ -72,29 +72,23 @@ class Handle void reset() { - if (PTR.p) + if (PTR) { - if (--PTR.p->count==0) - delete PTR.p; - PTR.p=0; + if (--PTR->count==0) + delete PTR; + PTR=0; } } - int refs() const noexcept { return PTR.p->count; } + int + refs() const noexcept { return PTR->count; } - Id_type id() const noexcept { return PTR.p - static_cast(0); } + Id_type id() const noexcept { return PTR - static_cast(0); } - bool identical(const Handle& h) const noexcept { return PTR.p == h.PTR.p; } - - void* for_compact_container() const { return PTR.vp; } - void*& for_compact_container() { return PTR.vp; } + bool identical(const Handle& h) const noexcept { return PTR == h.PTR; } protected: - - union { - Rep* p; - void* vp; - } PTR; + Rep* PTR; }; //inline Handle::Id_type id(const Handle& x) { return x.id() ; } From 8b474ddf59f5a9872969baafbd3cc0da86d8fd6a Mon Sep 17 00:00:00 2001 From: Laurent Rineau Date: Wed, 20 May 2020 10:32:03 +0200 Subject: [PATCH 431/568] Re-add the use of Lazy objects in Compact_container --- STL_Extension/include/CGAL/Handle.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/STL_Extension/include/CGAL/Handle.h b/STL_Extension/include/CGAL/Handle.h index af5297ae2e5..0d652ccb4cb 100644 --- a/STL_Extension/include/CGAL/Handle.h +++ b/STL_Extension/include/CGAL/Handle.h @@ -87,6 +87,8 @@ class Handle bool identical(const Handle& h) const noexcept { return PTR == h.PTR; } + void * for_compact_container() const { return PTR; } + void for_compact_container(void* p) { PTR = static_cast(p); } protected: Rep* PTR; }; From ad758d0e6efd2d2d43d725d141d7f6c26ffb9926 Mon Sep 17 00:00:00 2001 From: Marc Glisse Date: Wed, 20 May 2020 11:59:03 +0200 Subject: [PATCH 432/568] Revert spaceship on Gmpq it causes trouble with other classes, and not just for visual studio --- Number_types/include/CGAL/GMP/Gmpq_type.h | 46 +---------------------- 1 file changed, 2 insertions(+), 44 deletions(-) diff --git a/Number_types/include/CGAL/GMP/Gmpq_type.h b/Number_types/include/CGAL/GMP/Gmpq_type.h index 634d5adfc2b..451d2b00cdd 100644 --- a/Number_types/include/CGAL/GMP/Gmpq_type.h +++ b/Number_types/include/CGAL/GMP/Gmpq_type.h @@ -35,10 +35,6 @@ #include #include -#if __cpp_impl_three_way_comparison >= 201907L -# include -#endif - #if defined(BOOST_MSVC) # pragma warning(push) # pragma warning(disable:4146) @@ -65,17 +61,8 @@ private: class Gmpq - : Handle_for -#if __cpp_impl_three_way_comparison >= 201907L - , boost::field_operators2< Gmpq, int - , boost::field_operators2< Gmpq, long - , boost::field_operators2< Gmpq, long long - , boost::field_operators2< Gmpq, double - , boost::field_operators2< Gmpq, Gmpz - , boost::field_operators2< Gmpq, Gmpfr - > > > > > > -#else - , boost::totally_ordered1< Gmpq + : Handle_for, + boost::totally_ordered1< Gmpq , boost::ordered_field_operators2< Gmpq, int , boost::ordered_field_operators2< Gmpq, long , boost::ordered_field_operators2< Gmpq, long long @@ -83,7 +70,6 @@ class Gmpq , boost::ordered_field_operators2< Gmpq, Gmpz , boost::ordered_field_operators2< Gmpq, Gmpfr > > > > > > > -#endif { typedef Handle_for Base; public: @@ -237,11 +223,7 @@ public: Gmpq& operator/=(const Gmpq &q); bool operator==(const Gmpq &q) const noexcept { return mpq_equal(this->mpq(), q.mpq()) != 0;} -#if __cpp_impl_three_way_comparison >= 201907L - std::strong_ordering operator<=>(const Gmpq&q) const { return mpq_cmp(this->mpq(), q.mpq()) <=> 0; } -#else bool operator< (const Gmpq &q) const { return mpq_cmp(this->mpq(), q.mpq()) < 0; } -#endif double to_double() const noexcept; Sign sign() const noexcept; @@ -263,78 +245,54 @@ public: Gmpq& operator-=(int z){return (*this)-= Gmpq(z);} Gmpq& operator*=(int z){return (*this)*= Gmpq(z);} Gmpq& operator/=(int z){return (*this)/= Gmpq(z);} -#if __cpp_impl_three_way_comparison >= 201907L - std::strong_ordering operator<=>(int z) const { return mpq_cmp_si(mpq(),z,1) <=> 0; } -#else bool operator==(int z) const {return mpq_cmp_si(mpq(),z,1)==0;} bool operator< (int z) const {return mpq_cmp_si(mpq(),z,1)<0;} bool operator> (int z) const {return mpq_cmp_si(mpq(),z,1)>0;} -#endif // Interoperability with long Gmpq& operator+=(long z){return (*this)+= Gmpq(z);} Gmpq& operator-=(long z){return (*this)-= Gmpq(z);} Gmpq& operator*=(long z){return (*this)*= Gmpq(z);} Gmpq& operator/=(long z){return (*this)/= Gmpq(z);} -#if __cpp_impl_three_way_comparison >= 201907L - std::strong_ordering operator<=>(long z) const { return mpq_cmp_si(mpq(),z,1) <=> 0; } -#else bool operator==(long z) const {return mpq_cmp_si(mpq(),z,1)==0;} bool operator< (long z) const {return mpq_cmp_si(mpq(),z,1)<0;} bool operator> (long z) const {return mpq_cmp_si(mpq(),z,1)>0;} -#endif // Interoperability with long long Gmpq& operator+=(long long z){return (*this)+= Gmpq(z);} Gmpq& operator-=(long long z){return (*this)-= Gmpq(z);} Gmpq& operator*=(long long z){return (*this)*= Gmpq(z);} Gmpq& operator/=(long long z){return (*this)/= Gmpq(z);} -#if __cpp_impl_three_way_comparison >= 201907L - std::strong_ordering operator<=>(long long z) const { return *this <=> Gmpq(z); } -#else bool operator==(long long z) const {return (*this)== Gmpq(z);} bool operator< (long long z) const {return (*this)< Gmpq(z);} bool operator> (long long z) const {return (*this)> Gmpq(z);} -#endif // Interoperability with double Gmpq& operator+=(double d){return (*this)+= Gmpq(d);} Gmpq& operator-=(double d){return (*this)-= Gmpq(d);} Gmpq& operator*=(double d){return (*this)*= Gmpq(d);} Gmpq& operator/=(double d){return (*this)/= Gmpq(d);} -#if __cpp_impl_three_way_comparison >= 201907L - std::strong_ordering operator<=>(double d) const { return *this <=> Gmpq(d); } -#else bool operator==(double d) const {return (*this)== Gmpq(d);} bool operator< (double d) const {return (*this)< Gmpq(d);} bool operator> (double d) const {return (*this)> Gmpq(d);} -#endif // Interoperability with Gmpz Gmpq& operator+=(const Gmpz&); Gmpq& operator-=(const Gmpz&); Gmpq& operator*=(const Gmpz&); Gmpq& operator/=(const Gmpz&); -#if __cpp_impl_three_way_comparison >= 201907L - std::strong_ordering operator<=>(const Gmpz& z) const { return *this <=> Gmpq(z); } -#else bool operator==(const Gmpz &z) const {return (*this)== Gmpq(z);} bool operator< (const Gmpz &z) const {return (*this)< Gmpq(z);} bool operator> (const Gmpz &z) const {return (*this)> Gmpq(z);} -#endif // Interoperability with Gmpfr Gmpq& operator+=(const Gmpfr &f){return (*this)+= Gmpq(f);} Gmpq& operator-=(const Gmpfr &f){return (*this)-= Gmpq(f);} Gmpq& operator*=(const Gmpfr &f){return (*this)*= Gmpq(f);} Gmpq& operator/=(const Gmpfr &f){return (*this)/= Gmpq(f);} -#if __cpp_impl_three_way_comparison >= 201907L - std::strong_ordering operator<=>(const Gmpfr& f) const { return 0 <=> mpfr_cmp_q(f.fr(),mpq()); } -#else bool operator==(const Gmpfr &f) const {return mpfr_cmp_q(f.fr(),mpq())==0;} bool operator< (const Gmpfr &f) const {return mpfr_cmp_q(f.fr(),mpq())>0;} bool operator> (const Gmpfr &f) const {return mpfr_cmp_q(f.fr(),mpq())<0;} -#endif }; From 314e4312fee14bd1a695898882fe24d906049f0a Mon Sep 17 00:00:00 2001 From: Marc Glisse Date: Wed, 20 May 2020 16:21:36 +0200 Subject: [PATCH 433/568] Polynomial: C++20 vs boost operators --- Polynomial/include/CGAL/Polynomial/Polynomial_type.h | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/Polynomial/include/CGAL/Polynomial/Polynomial_type.h b/Polynomial/include/CGAL/Polynomial/Polynomial_type.h index b30cf524458..05d2bce319c 100644 --- a/Polynomial/include/CGAL/Polynomial/Polynomial_type.h +++ b/Polynomial/include/CGAL/Polynomial/Polynomial_type.h @@ -190,9 +190,18 @@ template class Polynomial : public Handle_with_policy< internal::Polynomial_rep >, public boost::ordered_field_operators1< Polynomial , +#if __cpp_impl_three_way_comparison >= 201907L + boost::less_than_comparable2< Polynomial , NT_ , + boost::less_than_comparable2< Polynomial , CGAL_icoeff(NT_), + boost::less_than_comparable2< Polynomial , CGAL_int(NT_), + boost::field_operators2< Polynomial , NT_ , + boost::field_operators2< Polynomial , CGAL_icoeff(NT_), + boost::field_operators2< Polynomial , CGAL_int(NT_) > > > > > > > +#else boost::ordered_field_operators2< Polynomial , NT_ , boost::ordered_field_operators2< Polynomial , CGAL_icoeff(NT_), boost::ordered_field_operators2< Polynomial , CGAL_int(NT_) > > > > +#endif { typedef typename internal::Innermost_coefficient_type::Type Innermost_coefficient_type; public: From 9d218a45e0b339819875b69f9de3c927566ea1f6 Mon Sep 17 00:00:00 2001 From: Marc Glisse Date: Thu, 21 May 2020 11:42:35 +0200 Subject: [PATCH 434/568] use rebind_alloc in Union_find --- Union_find/include/CGAL/Union_find.h | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/Union_find/include/CGAL/Union_find.h b/Union_find/include/CGAL/Union_find.h index a76cf515856..88edb3e206b 100644 --- a/Union_find/include/CGAL/Union_find.h +++ b/Union_find/include/CGAL/Union_find.h @@ -114,8 +114,7 @@ public: #ifdef _MSC_VER typedef CGAL_ALLOCATOR(Union_find_struct) allocator; #else - typedef typename A::template rebind Rebind; - typedef typename Rebind::other allocator; + typedef typename std::allocator_traits::rebind_alloc allocator; #endif private: From f3d5a573dff4ad78b17d1ebf0f708e6f7ca68ce5 Mon Sep 17 00:00:00 2001 From: Marc Glisse Date: Thu, 21 May 2020 11:52:21 +0200 Subject: [PATCH 435/568] Use allocator_traits for destroy --- STL_Extension/include/CGAL/Concurrent_compact_container.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/STL_Extension/include/CGAL/Concurrent_compact_container.h b/STL_Extension/include/CGAL/Concurrent_compact_container.h index 5ab9eca6790..2cf395fdba6 100644 --- a/STL_Extension/include/CGAL/Concurrent_compact_container.h +++ b/STL_Extension/include/CGAL/Concurrent_compact_container.h @@ -718,7 +718,7 @@ void Concurrent_compact_container::clear() size_type s = it->second; for (pointer pp = p + 1; pp != p + s - 1; ++pp) { if (type(pp) == USED) - m_alloc.destroy(pp); + std::allocator_traits::destroy(m_alloc, pp); } m_alloc.deallocate(p, s); } From d7ce01da007f78ace4700dde34abfc15fd90a32f Mon Sep 17 00:00:00 2001 From: Andreas Fabri Date: Thu, 21 May 2020 16:21:32 +0100 Subject: [PATCH 436/568] Add a figure and an example for dimension < 2 --- .../Triangulation_2/fig/low_dimensional.svg | Bin 0 -> 45079 bytes .../Triangulation_2/low_dimensional.cpp | 74 ++++++++++++++++++ 2 files changed, 74 insertions(+) create mode 100644 Triangulation_2/doc/Triangulation_2/fig/low_dimensional.svg create mode 100644 Triangulation_2/examples/Triangulation_2/low_dimensional.cpp diff --git a/Triangulation_2/doc/Triangulation_2/fig/low_dimensional.svg b/Triangulation_2/doc/Triangulation_2/fig/low_dimensional.svg new file mode 100644 index 0000000000000000000000000000000000000000..147a847ec473f959696fc41824ca91629f626198 GIT binary patch literal 45079 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≦oitYIh0{m2Ng)9K`cUA zfr4NZ2_`|zjYK3u!yzW(QPBF*V-0=2EkuYi{Ky&8{y#l}S0ADir_`%&&`=dTTn~a}1i%HAIS^WKD zcSzlRJMwG}UEykCxbK$#S69)T3Cj80ogMDdur(#*{q1H{&cD@=!+5MygV}Yoz4M1g zoULZiB145(##jtsA~+R6P@_s%Xe;$PIXu@CR=yF`oO3*Zn!-t>B^I@v7N!C~%f`A# zQua|zzk#CTuJ+$ZfH>-dagsV;W}>1RY9WHlv^_dH1K_ z1mL4%J4FDOuu8>otOAp7jeiaS9qV;g5D=}JSQP?VM%Fb5 z2sarBuw7CiP}rDuQlP>Dk__KPY@|XwN`p9-iOq7)KsW=TTHLnL>L;7Pbefm~LfgpJ z0>RdTyQ9VRj!3Z2?M&Hd^o2Qe%*4dD)^|q283{Whp*8NTkkB%+bx5$e`F?@WsBvIX zHx{SK)Y?3a4zT19ORS}Z%ozx0AnXi;mWfrPgO-u41A;Z!{Q|+J{uB`;R??#WW?u#% z$OyHg%mK$42WK4Yj)PSTQ#feZ*g6>4dCC34!0zi%FraC6mfFz(!2qEw7A&>cIOE`q zgWYkkYGM@*T1K`G2-a`!421Kf*&Zg%M2NK!al#ul1}ZmmEWj~!hmJY3-4~YAE+kqr z0Zt^>3Mgl7HO7=C8_j{q9Cpp)Nz6~2=Z%lE15czJE0$Si%^fkchQRX}knMTn=ck9w z?2v;2TgaQ-x93^?sMgP>aV<(=ce9^wEvKY}R39(UvO6$qjrj6!GAXh$GO_W=T1 zrKs|VR%>bythVP2f-?yAw-+0X2tmf1xe&w7tq_}d?YOA}1Fv5|iexCU0Z4(M)f$C? zc6-hks4>u?7%&|>i*xI^-daf^u>(7ag|mtB5c%bKE$RDMOWIznQ^mBFkpZ}ytuj|@ z5aA)jj%z6t3Y@+7b!bnprrNqSjK8p&E+DoTTR1x7;9MixwMK+74%mrY6H_>78`<_a zpcT8_tBPC>1#P@Ua`BJdEaZ#lw+lJvJ2njYiDgHs_LavmHceqp19T$bobPV7*Fi}r4yBQ_=2?U z`7UY44QYS&V8a3EQ-tDf3By>X-oJP$HmPNyh~j>f#sOFv5{Z3l*z$&L^|DVKFxcgv zKnFYwq+pEhrse6vkoHxTQ7d&jHL#V`bp&Z@NU!HuQLOW6a%D&oEe3Z35p<*yG(?Os zSdx#0P?$Ofvx!e!Ct#ew-ga!@PE*O~P%OeodcJ@Ju+$>yV}1=?w?nv7!kwSJU<>%l zxVfUs8t^&yH5>Li(@h&s5oEyM^blQQo7T0;z?s?VjwySnq7FLZM zTQ;_3h(%$uJG_o2#b|0+Ew$w;7O9F+c1^nUq1vC@3OFp1vHMveVtoaJ66i^sN++?s zV$J|Vv?#Io0&y$VZ4uel#G`FIqx&%q5m!FSxv#Tgb^2prR;6 zsLQ~QWwZ=s#)yAO=CIpoo9Xs;Cr-k&_12jt?~#tms*uwbm%?sKV9pF`P03{Vd#UbW zk_C6i;W~b$CVU+P>6R&CWh{7RFk(9jBvi&2zNQIxcwKaEQDfL?mDcg*exaM1r=H|H zV*b7!F-XGoj{mMSL4BaPkvPu0n0$Z$+W`wXCRt_rS{I@vUZv^qSx#-s*g-Q9G=lBg zZLMK!Q%|Z4s63TRJ2wmMOX>mkAK6q!>-gQ{xGk@$+|!a+7m%%x4}oMZ!Mq{BJ7zpG zA(<8{(Y7&LZq|0Ck!)L~wY&q8U-UKGKU;gLR(qXs4fRk+A~=g3&PVcVJjMuFvM{mv zLbHwPB7yY~pw?_kOu+Yn#o8R~Xn@m%-8<%ZWCPsB7<6SRpbeys*lKF;0a!3NGInl=(C!eVGN$dMvl`qXtq(0R?EsU=z8Jf zrBty&2#njvppnJKC%mc;~Y0aqH zrfu%Al}(?Vd)~}+nib`l2bL0i3qvr-8P!w{7H}nJlvpzcvRHhlAw$ubfloR`utl`) z$B=jmo?mDKg%E~~&wW%$pe#E`>lU<=uy;Fzz2zC?JZx*KA_`bjd5AdD$8Z8w&y?)x z6;bFEoyUd&8iCw8kB+nxyLx4YH3%k-t4bJ-Lj4Z4o>sES)SFS*!AJdtrw!|It;AD( N&Et~3adZ8{{{yg$mVy8P literal 0 HcmV?d00001 diff --git a/Triangulation_2/examples/Triangulation_2/low_dimensional.cpp b/Triangulation_2/examples/Triangulation_2/low_dimensional.cpp new file mode 100644 index 00000000000..fed87295eb0 --- /dev/null +++ b/Triangulation_2/examples/Triangulation_2/low_dimensional.cpp @@ -0,0 +1,74 @@ +#include + +#include +#include + +typedef CGAL::Exact_predicates_inexact_constructions_kernel K; +typedef CGAL::Triangulation_2 Triangulation; +typedef Triangulation::Vertex_handle Vertex_handle; +typedef Triangulation::Face_handle Face_handle; +typedef Triangulation::All_faces_iterator All_faces_iterator; +typedef Triangulation::All_edges_iterator All_edges_iterator; +typedef Triangulation::Point Point; + +int main() { + + Point p(0,0), q(1,0); + + Triangulation t; + + Vertex_handle inf = t.infinite_vertex(); + Face_handle fh = inf->face(); + assert(fh->vertex(0) == inf); + assert(fh->vertex(1) == Vertex_handle()); + assert(fh->vertex(2) == Vertex_handle()); + + assert(t.all_faces_begin() == t.all_faces_end()); + assert(t.all_edges_begin() == t.all_edges_end()); + + t.insert(p); + Vertex_handle pvh = t.finite_vertices_begin(); + Face_handle pfh = pvh->face(); + assert(pfh->neighbor(0) == fh); + + t.insert(q); + + assert(t.infinite_vertex()->face() == fh); + + assert( (fh->vertex(0) == inf) || (fh->vertex(1) == inf) ); + + std::cout << "After the insertion of the second point" <point() << " -- ";} + if (v1 == inf) {std::cout << "inf\n";}else{ std::cout<< v1->point() << std::endl;} + } + + std::cout << "Edge traversal by hand" << std::endl; + Face_handle done = fh; + do { + assert(fh->vertex(2) == Vertex_handle()); + assert(fh->neighbor(2) == Face_handle()); + Vertex_handle v0 = fh->vertex(0); + Vertex_handle v1 = fh->vertex(1); + std::cout << "Edge: "; + if (v0 == inf) {std::cout << "inf -- ";}else{ std::cout<< v0->point() << " -- ";} + if (v1 == inf) {std::cout << "inf\n";}else{ std::cout<< v1->point() << std::endl;} + fh = fh->neighbor(0); + } while (fh != done); + + std::cout << std::endl; + + return 0; +} From cf5e0d49c31b17efd1e6381133b716190be1bee1 Mon Sep 17 00:00:00 2001 From: Andreas Fabri Date: Fri, 22 May 2020 07:51:41 +0100 Subject: [PATCH 437/568] Add figure --- .../doc/Triangulation_2/Triangulation_2.txt | 22 ++++++++++++------- .../doc/Triangulation_2/examples.txt | 1 + 2 files changed, 15 insertions(+), 8 deletions(-) diff --git a/Triangulation_2/doc/Triangulation_2/Triangulation_2.txt b/Triangulation_2/doc/Triangulation_2/Triangulation_2.txt index 90446677a4c..e2a4661cf63 100644 --- a/Triangulation_2/doc/Triangulation_2/Triangulation_2.txt +++ b/Triangulation_2/doc/Triangulation_2/Triangulation_2.txt @@ -152,6 +152,17 @@ Therefore, each edge of the triangulation is incident to exactly two faces and the set of faces of a triangulation is topologically equivalent to a two-dimensional sphere. + +Note that +the *infinite vertex* has no significant +coordinates and that no geometric predicate can be applied on it +nor on an infinite face. + +\cgalFigureBegin{Triangulation_2D_Fig_infinite_vertex,infinite.png} +Infinite vertex and infinite faces +\cgalFigureEnd + + This extends to lower dimensional triangulations arising in degenerate cases or when the triangulations as less than three vertices. @@ -163,15 +174,11 @@ A zero dimensional triangulation, whose domain is reduced to a single point, is represented by two vertices that is topologically equivalent to a \f$ 0\f$-sphere. -Note that -the *infinite vertex* has no significant -coordinates and that no geometric predicate can be applied on it -nor on an infinite face. - -\cgalFigureBegin{Triangulation_2D_Fig_infinite_vertex,infinite.png} -Infinite vertex and infinite faces +\cgalFigureBegin{Triangulation_2D_Fig_low_dimensional,lowdimensional.svg} +Triangulations with zero, one, and two finite vertices. \cgalFigureEnd + \subsection Triangulation_2ARepresentationBasedonFaces A Representation Based on Faces and Vertices Because a triangulation is a set of @@ -1355,4 +1362,3 @@ Julia Flötotto, Monique Teillaud and Mariette Yvinec. */ } /* namespace CGAL */ - diff --git a/Triangulation_2/doc/Triangulation_2/examples.txt b/Triangulation_2/doc/Triangulation_2/examples.txt index 7061593de13..459982e56a2 100644 --- a/Triangulation_2/doc/Triangulation_2/examples.txt +++ b/Triangulation_2/doc/Triangulation_2/examples.txt @@ -21,4 +21,5 @@ \example Triangulation_2/polylines_triangulation.cpp \example Triangulation_2/segment_soup_to_polylines.cpp \example Triangulation_2/draw_triangulation_2.cpp +\example Triangulation_2/low_dimensional.cpp */ From 7cc653d1f851cf17a7bbf95cdb1a5d3427fade3b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9bastien=20Loriot?= Date: Fri, 22 May 2020 10:04:57 +0200 Subject: [PATCH 438/568] typos + backticks --- .../Surface_mesh_topology/CGAL/Curves_on_surface_topology.h | 6 +++--- .../doc/Surface_mesh_topology/CGAL/Path_on_surface.h | 4 ++-- .../Surface_mesh_topology/CGAL/Polygonal_schema_min_items.h | 2 +- .../Surface_mesh_topology/CGAL/draw_face_graph_with_paths.h | 4 ++-- .../doc/Surface_mesh_topology/Concepts/PolygonalSchema.h | 4 ++-- .../Surface_mesh_topology/Concepts/PolygonalSchemaItems.h | 2 +- .../doc/Surface_mesh_topology/Concepts/WeightFunctor.h | 2 +- .../doc/Surface_mesh_topology/Surface_mesh_topology.txt | 2 +- 8 files changed, 13 insertions(+), 13 deletions(-) diff --git a/Surface_mesh_topology/doc/Surface_mesh_topology/CGAL/Curves_on_surface_topology.h b/Surface_mesh_topology/doc/Surface_mesh_topology/CGAL/Curves_on_surface_topology.h index ada0f528d73..b37e714ee5e 100644 --- a/Surface_mesh_topology/doc/Surface_mesh_topology/CGAL/Curves_on_surface_topology.h +++ b/Surface_mesh_topology/doc/Surface_mesh_topology/CGAL/Curves_on_surface_topology.h @@ -4,7 +4,7 @@ namespace Surface_mesh_topology { /*! \ingroup PkgSurfaceMeshTopologyClasses - The class `Curves_on_surface_topology` provides methods to compute shortest non contracible cycles and to test homotopy on paths. Each object of this class is constructed from an external mesh, either a \ref CombinatorialMap "2D combinatorial map" or a model of a FaceGraph. It maintains a correspondence between this mesh and an internal representation, computed the first time an homotopy test is called. The user must not modify the input surface as long as homotopy tests are performed with this `Curves_on_surface_topology`. + The class `Curves_on_surface_topology` provides methods to compute shortest non contractible cycles and to test homotopy on paths. Each object of this class is constructed from an external mesh, either a \ref CombinatorialMap "2D combinatorial map" or a model of a FaceGraph. It maintains a correspondence between this mesh and an internal representation, computed the first time an homotopy test is called. The user must not modify the input surface as long as homotopy tests are performed with this `Curves_on_surface_topology`. \tparam Mesh a model of `CombinatorialMap` or of `FaceGraph` */ @@ -14,7 +14,7 @@ namespace Surface_mesh_topology { public: /*! - %halfedge_descriptor type. A handle to `Dart` for combinatorial/generalized maps, or a halfedge descriptor for models of the `FaceGraph` concept. + A handle to `Dart` for combinatorial/generalized maps, or a halfedge descriptor for models of the `FaceGraph` concept. */ typedef unspecified_type halfedge_descriptor; @@ -53,7 +53,7 @@ namespace Surface_mesh_topology { template Path_on_surface compute_shortest_non_contractible_cycle_with_base_point(halfedge_descriptor dh, const WeightFunctor& wf=WeightFunctor()) const; - /*! returns a vector of darts representing a non-contractible curve with a minimal number of intersection with the graph of the mesh. This curve can be decribed by the alternating sequence of faces and vertices it goes through, so that each dart in the returned vector belongs to both a face and the next vertex in the alternating sequence. (Here, faces and vertices are viewed as subsets of darts.) The size of the returned vector is the face width of the mesh. + /*! returns a vector of darts representing a non-contractible curve with a minimal number of intersection with the graph of the mesh. This curve can be described by the alternating sequence of faces and vertices it goes through, so that each dart in the returned vector belongs to both a face and the next vertex in the alternating sequence. (Here, faces and vertices are viewed as subsets of darts.) The size of the returned vector is the face width of the mesh. */ std::vector compute_face_width() const; }; diff --git a/Surface_mesh_topology/doc/Surface_mesh_topology/CGAL/Path_on_surface.h b/Surface_mesh_topology/doc/Surface_mesh_topology/CGAL/Path_on_surface.h index 0a3b1f99806..bd7ead4deda 100644 --- a/Surface_mesh_topology/doc/Surface_mesh_topology/CGAL/Path_on_surface.h +++ b/Surface_mesh_topology/doc/Surface_mesh_topology/CGAL/Path_on_surface.h @@ -13,7 +13,7 @@ namespace Surface_mesh_topology { { public: /*! - %halfedge_descriptor type. A handle to `Dart` for combinatorial/generalized maps, or a halfedge descriptor for models of the `FaceGraph` concept. + A handle to `Dart` for combinatorial/generalized maps, or a halfedge descriptor for models of the `FaceGraph` concept. */ typedef unspecified_type halfedge_descriptor; @@ -39,7 +39,7 @@ namespace Surface_mesh_topology { /// clears this path. void clear(); - /// returns `true` iff `hd` can be added at the end of this path. If `flip` is true, `hd`'s direction is reversed before checking + /// returns `true` iff `hd` can be added at the end of this path. If `flip` is true, the direction of `hd` is reversed before checking bool can_be_pushed(halfedge_descriptor hd, bool flip=false) const; /// adds `hd` at the end of this path. If `flip` is true, the opposite of `hd` is considered. diff --git a/Surface_mesh_topology/doc/Surface_mesh_topology/CGAL/Polygonal_schema_min_items.h b/Surface_mesh_topology/doc/Surface_mesh_topology/CGAL/Polygonal_schema_min_items.h index db4bfee78f9..06fe49ab963 100644 --- a/Surface_mesh_topology/doc/Surface_mesh_topology/CGAL/Polygonal_schema_min_items.h +++ b/Surface_mesh_topology/doc/Surface_mesh_topology/CGAL/Polygonal_schema_min_items.h @@ -4,7 +4,7 @@ namespace Surface_mesh_topology { /*! \ingroup PkgSurfaceMeshTopologyClasses -The class `Polygonal_schema_min_items` defines a struct with a std::string as the information associated with darts, and no attribute is enabled. +The class `Polygonal_schema_min_items` defines a struct with a `std::string` as the information associated with darts, and no attribute is enabled. \cgalModels `PolygonalSchemaItems` diff --git a/Surface_mesh_topology/doc/Surface_mesh_topology/CGAL/draw_face_graph_with_paths.h b/Surface_mesh_topology/doc/Surface_mesh_topology/CGAL/draw_face_graph_with_paths.h index 6801173ad08..e2a13b4bf5f 100644 --- a/Surface_mesh_topology/doc/Surface_mesh_topology/CGAL/draw_face_graph_with_paths.h +++ b/Surface_mesh_topology/doc/Surface_mesh_topology/CGAL/draw_face_graph_with_paths.h @@ -4,7 +4,7 @@ namespace CGAL { \ingroup PkgDrawFaceGraphWithPaths opens a new window and draws `amesh`, either a 2D linear cell complex or a model of the FaceGraph concept, plus the paths lying on this mesh given in `apaths`. -A call to this function is blocking, that is the program continues as soon as the user closes the window. This function requires CGAL_Qt5, and is only available if the flag CGAL_USE_BASIC_VIEWER is defined at compile time. +A call to this function is blocking, that is the program continues as soon as the user closes the window. This function requires `CGAL_Qt5`, and is only available if the flag `CGAL_USE_BASIC_VIEWER` is defined at compile time. \tparam Mesh either a 2D linear cell complex or a model of the FaceGraph concept. \param amesh the mesh to draw. \param apaths the paths to draw, which should lie on `amesh`. @@ -17,7 +17,7 @@ void draw(const Mesh& amesh, \ingroup PkgDrawFaceGraphWithPaths opens a new window and draws `amesh`, either a 2D linear cell complex or a model of the FaceGraph concept, plus the paths lying on this mesh given in `apaths`. -A call to this function is blocking, that is the program continues as soon as the user closes the window. This function requires CGAL_Qt5, and is only available if the flag CGAL_USE_BASIC_VIEWER is defined at compile time. +A call to this function is blocking, that is the program continues as soon as the user closes the window. This function requires `CGAL_Qt5`, and is only available if the flag `CGAL_USE_BASIC_VIEWER` is defined at compile time. \tparam Mesh either a 2D linear cell complex or a model of the FaceGraph concept. \param amesh the mesh to draw. \param apaths the paths to draw, which should lie on `amesh`. diff --git a/Surface_mesh_topology/doc/Surface_mesh_topology/Concepts/PolygonalSchema.h b/Surface_mesh_topology/doc/Surface_mesh_topology/Concepts/PolygonalSchema.h index e2ddc169269..c8ba31b3905 100644 --- a/Surface_mesh_topology/doc/Surface_mesh_topology/Concepts/PolygonalSchema.h +++ b/Surface_mesh_topology/doc/Surface_mesh_topology/Concepts/PolygonalSchema.h @@ -48,7 +48,7 @@ public: /// returns true iff the facet containing `dh` is perforated. bool is_perforated(Dart_const_handle dh) const; - /// Shortcut for is_perforated(get_dart_labeled(s)). + /// Shortcut for `is_perforated(get_dart_labeled(s))`. bool is_perforated(const std::string & s) const; /// perforates the facet containing `dh`. Returns the number of darts of the face; 0 if the facet was already perforated. @@ -60,6 +60,6 @@ public: /// fills the facet containing `dh`. Returns the number of darts of the face; 0 if the facet was already filled. size_type fill_facet(Dart_handle dh); - /// Shortcut for fill_facet(get_dart_labeled(s)). + /// Shortcut for `fill_facet(get_dart_labeled(s))`. size_type fill_facet(const std::string & s); }; diff --git a/Surface_mesh_topology/doc/Surface_mesh_topology/Concepts/PolygonalSchemaItems.h b/Surface_mesh_topology/doc/Surface_mesh_topology/Concepts/PolygonalSchemaItems.h index ec6d956b8f1..a92d7a1af8b 100644 --- a/Surface_mesh_topology/doc/Surface_mesh_topology/Concepts/PolygonalSchemaItems.h +++ b/Surface_mesh_topology/doc/Surface_mesh_topology/Concepts/PolygonalSchemaItems.h @@ -2,7 +2,7 @@ \ingroup PkgSurfaceMeshTopologyConcepts \cgalConcept - The concept `PolygonalSchemaItems` allows to customize a PolygonalSchema by choosing the information associated with darts, and by enabling and disabling some attributes. `%Dart_wrapper::%Dart_info`, should be a class having a public data member std::string m_label. + The concept `PolygonalSchemaItems` allows to customize a `PolygonalSchema` by choosing the information associated with darts, and by enabling and disabling some attributes. `%Dart_wrapper::%Dart_info`, should be a class having a public data member std::string m_label. \cgalRefines GenericMapItems diff --git a/Surface_mesh_topology/doc/Surface_mesh_topology/Concepts/WeightFunctor.h b/Surface_mesh_topology/doc/Surface_mesh_topology/Concepts/WeightFunctor.h index cb2fe08f63b..291b0196170 100644 --- a/Surface_mesh_topology/doc/Surface_mesh_topology/Concepts/WeightFunctor.h +++ b/Surface_mesh_topology/doc/Surface_mesh_topology/Concepts/WeightFunctor.h @@ -14,7 +14,7 @@ public: /// @{ /*! - %halfedge_descriptor type. A handle to `Dart` for combinatorial/generalized maps, or a halfedge descriptor for models of the `FaceGraph` concept. + A handle to `Dart` for combinatorial/generalized maps, or a halfedge descriptor for models of the `FaceGraph` concept. */ typedef unspecified_type halfedge_descriptor; diff --git a/Surface_mesh_topology/doc/Surface_mesh_topology/Surface_mesh_topology.txt b/Surface_mesh_topology/doc/Surface_mesh_topology/Surface_mesh_topology.txt index 6d13664f032..36ea7108b94 100644 --- a/Surface_mesh_topology/doc/Surface_mesh_topology/Surface_mesh_topology.txt +++ b/Surface_mesh_topology/doc/Surface_mesh_topology/Surface_mesh_topology.txt @@ -25,7 +25,7 @@ A closed curve, either topological or combinatorial, that cannot be continuously - Given a surface mesh \f$\cal{M}\f$, compute a shortest non-contractible combinatorial curve without the previous vertex requirement. When all the edges have the same unit length, the length of a shortest non-contractible curve is known as the edge width of the surface, - Given a surface mesh \f$\cal{M}\f$, compute a shortest non-contractible topological curve. It can be assumed that this curve does not cross the edges of \f$\cal{M}\f$ and only passes through the vertices. It follows that the curve can be described by a circular sequence of traversed faces alternating with the vertices it passes through. The length of this curve (i.e., the number of vertices it passes through) is known as the face width of the surface. -It is important to clarify how we compare the lengths of two combinatorial curves in order to compute the shortest one. "Shortest" can be understood as "having the least amount of edges" or "having the smallest total length of its edges". In the former case, we consider that the mesh is unweighted; in the latter case, we consider that the mesh is weighted, and one must specify how the weight, or length, of each edge is calculated (see concept `WeightFunctor`). When the vertices of the mesh have Euclidean coordinates, the Eudlidean distance between two connected vertices defines a natural weight for the corresponding edge. A weight functor \link CGAL::Surface_mesh_topology::Euclidean_length_weight_functor `Euclidean_length_weight_functor`\endlink is provided for this purpose. +It is important to clarify how we compare the lengths of two combinatorial curves in order to compute the shortest one. "Shortest" can be understood as "having the least amount of edges" or "having the smallest total length of its edges". In the former case, we consider that the mesh is unweighted; in the latter case, we consider that the mesh is weighted, and one must specify how the weight, or length, of each edge is calculated (see concept `WeightFunctor`). When the vertices of the mesh have Euclidean coordinates, the Euclidean distance between two connected vertices defines a natural weight for the corresponding edge. A weight functor \link CGAL::Surface_mesh_topology::Euclidean_length_weight_functor `Euclidean_length_weight_functor`\endlink is provided for this purpose. The algorithm to find a shortest non-contractible curve through a specified vertex is based on the paper by Cabello et al. \cgalCite{cvl-ew-12}. The time complexity is linear, though in the weighted case it is raised by a logarithmic factor, assuming that the weight computation takes constant time per edge. Computing the edge width takes quadratic time by running the first function on each vertex, and its complexity is also raised by a logarithmic factor when considering a weighted map. Computing the face width consists of constructing the radial graph of the original mesh and computing the edge width of the radial graph. It thus takes quadratic time. Computing face width on weighted maps is currently not supported. From 5e70fceba91f47a211dda533779b264b632ef10a Mon Sep 17 00:00:00 2001 From: Adrian Bunk Date: Fri, 22 May 2020 11:21:09 +0300 Subject: [PATCH 439/568] Fix gcc option setting for Alpha --- Installation/cmake/modules/CGAL_SetupCGALDependencies.cmake | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Installation/cmake/modules/CGAL_SetupCGALDependencies.cmake b/Installation/cmake/modules/CGAL_SetupCGALDependencies.cmake index 9125a477c93..f87ee9dda2a 100644 --- a/Installation/cmake/modules/CGAL_SetupCGALDependencies.cmake +++ b/Installation/cmake/modules/CGAL_SetupCGALDependencies.cmake @@ -166,7 +166,7 @@ function(CGAL_setup_CGAL_dependencies target) endif() if ( "${CMAKE_SYSTEM_PROCESSOR}" MATCHES "alpha" ) message( STATUS "Using gcc on alpha. Adding -mieee -mfp-rounding-mode=d" ) - target_compile_options(${target} ${keyword} "-mieee -mfp-rounding-mode=d" ) + target_compile_options(${target} ${keyword} "-mieee" "-mfp-rounding-mode=d" ) endif() endif() endfunction() From fcd4e578231eae61d7df5e8382891c612d48c9a3 Mon Sep 17 00:00:00 2001 From: Marc Glisse Date: Fri, 22 May 2020 11:29:03 +0200 Subject: [PATCH 440/568] Missing 'template' --- Union_find/include/CGAL/Union_find.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Union_find/include/CGAL/Union_find.h b/Union_find/include/CGAL/Union_find.h index 88edb3e206b..16dc14bdb74 100644 --- a/Union_find/include/CGAL/Union_find.h +++ b/Union_find/include/CGAL/Union_find.h @@ -114,7 +114,7 @@ public: #ifdef _MSC_VER typedef CGAL_ALLOCATOR(Union_find_struct) allocator; #else - typedef typename std::allocator_traits::rebind_alloc allocator; + typedef typename std::allocator_traits::template rebind_alloc allocator; #endif private: From 257a92d60cb61a295819f3585bde340905da6dd6 Mon Sep 17 00:00:00 2001 From: Marc Glisse Date: Fri, 22 May 2020 12:22:53 +0200 Subject: [PATCH 441/568] friend comparisons for Polynomial That's less likely to break if the C++20 rules get reverted This class is strange, it uses boost operators, but still provides some operators that boost already provides (and the boost ones have priority). --- .../include/CGAL/Polynomial/Polynomial_type.h | 151 ++++++------------ 1 file changed, 46 insertions(+), 105 deletions(-) diff --git a/Polynomial/include/CGAL/Polynomial/Polynomial_type.h b/Polynomial/include/CGAL/Polynomial/Polynomial_type.h index 05d2bce319c..540f17bd203 100644 --- a/Polynomial/include/CGAL/Polynomial/Polynomial_type.h +++ b/Polynomial/include/CGAL/Polynomial/Polynomial_type.h @@ -190,18 +190,9 @@ template class Polynomial : public Handle_with_policy< internal::Polynomial_rep >, public boost::ordered_field_operators1< Polynomial , -#if __cpp_impl_three_way_comparison >= 201907L - boost::less_than_comparable2< Polynomial , NT_ , - boost::less_than_comparable2< Polynomial , CGAL_icoeff(NT_), - boost::less_than_comparable2< Polynomial , CGAL_int(NT_), - boost::field_operators2< Polynomial , NT_ , - boost::field_operators2< Polynomial , CGAL_icoeff(NT_), - boost::field_operators2< Polynomial , CGAL_int(NT_) > > > > > > > -#else boost::ordered_field_operators2< Polynomial , NT_ , boost::ordered_field_operators2< Polynomial , CGAL_icoeff(NT_), boost::ordered_field_operators2< Polynomial , CGAL_int(NT_) > > > > -#endif { typedef typename internal::Innermost_coefficient_type::Type Innermost_coefficient_type; public: @@ -966,6 +957,52 @@ public: } friend Polynomial operator - <> (const Polynomial&); + + // + // Comparison Operators + // + + // polynomials only + friend bool operator == (const Polynomial& p1, const Polynomial& p2) { + CGAL_precondition(p1.degree() >= 0); + CGAL_precondition(p2.degree() >= 0); + if (p1.is_identical(p2)) return true; + if (p1.degree() != p2.degree()) return false; + for (int i = p1.degree(); i >= 0; i--) if (p1[i] != p2[i]) return false; + return true; + } + friend bool operator < (const Polynomial& p1, const Polynomial& p2) + { return ( p1.compare(p2) < 0 ); } + + // operators NT + friend bool operator == (const Polynomial& p, const NT& num) { + CGAL_precondition(p.degree() >= 0); + return p.degree() == 0 && p[0] == num; + } + friend bool operator < (const Polynomial& p,const NT& num) + { return ( p.compare(num) < 0 );} + friend bool operator > (const Polynomial& p,const NT& num) + { return ( p.compare(num) > 0 );} + + // compare int ################################# + friend bool operator == (const Polynomial& p, const CGAL_int(NT)& num) { + CGAL_precondition(p.degree() >= 0); + return p.degree() == 0 && p[0] == NT(num); + } + friend bool operator < (const Polynomial& p, const CGAL_int(NT)& num) + { return ( p.compare(NT(num)) < 0 );} + friend bool operator > (const Polynomial& p, const CGAL_int(NT)& num) + { return ( p.compare(NT(num)) > 0 );} + + // compare icoeff ################################### + friend bool operator == (const Polynomial& p, const CGAL_icoeff(NT)& num) { + CGAL_precondition(p.degree() >= 0); + return p.degree() == 0 && p[0] == NT(num); + } + friend bool operator < (const Polynomial& p, const CGAL_icoeff(NT)& num) + { return ( p.compare(NT(num)) < 0 );} + friend bool operator > (const Polynomial& p, const CGAL_icoeff(NT)& num) + { return ( p.compare(NT(num)) > 0 );} }; // class Polynomial // Arithmetic Operators, Part III: @@ -1008,102 +1045,6 @@ Polynomial operator * (const Polynomial& p1, } -// -// Comparison Operators -// - -// polynomials only -template inline -bool operator == (const Polynomial& p1, const Polynomial& p2) { - CGAL_precondition(p1.degree() >= 0); - CGAL_precondition(p2.degree() >= 0); - if (p1.is_identical(p2)) return true; - if (p1.degree() != p2.degree()) return false; - for (int i = p1.degree(); i >= 0; i--) if (p1[i] != p2[i]) return false; - return true; -} -template inline -bool operator < (const Polynomial& p1, const Polynomial& p2) -{ return ( p1.compare(p2) < 0 ); } -template inline -bool operator > (const Polynomial& p1, const Polynomial& p2) -{ return ( p1.compare(p2) > 0 ); } - -// operators NT -template inline -bool operator == (const NT& num, const Polynomial& p) { - CGAL_precondition(p.degree() >= 0); - return p.degree() == 0 && p[0] == num; -} -template inline -bool operator == (const Polynomial& p, const NT& num) { - CGAL_precondition(p.degree() >= 0); - return p.degree() == 0 && p[0] == num; -} -template inline -bool operator < (const NT& num, const Polynomial& p) -{ return ( p.compare(num) > 0 );} -template inline -bool operator < (const Polynomial& p,const NT& num) -{ return ( p.compare(num) < 0 );} -template inline -bool operator > (const NT& num, const Polynomial& p) -{ return ( p.compare(num) < 0 );} -template inline -bool operator > (const Polynomial& p,const NT& num) -{ return ( p.compare(num) > 0 );} - - -// compare int ################################# -template inline -bool operator == (const CGAL_int(NT)& num, const Polynomial& p) { - CGAL_precondition(p.degree() >= 0); - return p.degree() == 0 && p[0] == NT(num); -} -template inline -bool operator == (const Polynomial& p, const CGAL_int(NT)& num) { - CGAL_precondition(p.degree() >= 0); - return p.degree() == 0 && p[0] == NT(num); -} -template inline -bool operator < (const CGAL_int(NT)& num, const Polynomial& p) -{ return ( p.compare(NT(num)) > 0 );} -template inline -bool operator < (const Polynomial& p, const CGAL_int(NT)& num) -{ return ( p.compare(NT(num)) < 0 );} -template inline -bool operator > (const CGAL_int(NT)& num, const Polynomial& p) -{ return ( p.compare(NT(num)) < 0 );} -template inline -bool operator > (const Polynomial& p, const CGAL_int(NT)& num) -{ return ( p.compare(NT(num)) > 0 );} - -// compare icoeff ################################### -template inline -bool operator == (const CGAL_icoeff(NT)& num, const Polynomial& p) { - CGAL_precondition(p.degree() >= 0); - return p.degree() == 0 && p[0] == NT(num); -} -template inline -bool operator == (const Polynomial& p, const CGAL_icoeff(NT)& num) { - CGAL_precondition(p.degree() >= 0); - return p.degree() == 0 && p[0] == NT(num); -} -template inline -bool operator < (const CGAL_icoeff(NT)& num, const Polynomial& p) -{ return ( p.compare(NT(num)) > 0 );} -template inline -bool operator < (const Polynomial& p, const CGAL_icoeff(NT)& num) -{ return ( p.compare(NT(num)) < 0 );} - - -template inline -bool operator > (const CGAL_icoeff(NT)& num, const Polynomial& p) -{ return ( p.compare(NT(num)) < 0 );} -template inline -bool operator > (const Polynomial& p, const CGAL_icoeff(NT)& num) -{ return ( p.compare(NT(num)) > 0 );} - // // Algebraically non-trivial operations // From 7a35fbe6fb9d7baeed51671901dfdc3bdcb30264 Mon Sep 17 00:00:00 2001 From: Marc Glisse Date: Fri, 22 May 2020 12:28:46 +0200 Subject: [PATCH 442/568] Drop useless template parameter --- Number_types/include/CGAL/Quotient.h | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/Number_types/include/CGAL/Quotient.h b/Number_types/include/CGAL/Quotient.h index 41e9423d9b7..56c17c1515f 100644 --- a/Number_types/include/CGAL/Quotient.h +++ b/Number_types/include/CGAL/Quotient.h @@ -129,13 +129,13 @@ class Quotient Quotient& operator*= (const CGAL_double(NT)& r); Quotient& operator/= (const CGAL_double(NT)& r); - friend bool operator==(const Quotient& x, const Quotient& y) + friend bool operator==(const Quotient& x, const Quotient& y) { return x.num * y.den == x.den * y.num; } - friend bool operator==(const Quotient& x, const NT& y) + friend bool operator==(const Quotient& x, const NT& y) { return x.den * y == x.num; } - friend inline bool operator==(const Quotient& x, const CGAL_int(NT) & y) + friend inline bool operator==(const Quotient& x, const CGAL_int(NT) & y) { return x.den * y == x.num; } - friend inline bool operator==(const Quotient& x, const CGAL_double(NT) & y) + friend inline bool operator==(const Quotient& x, const CGAL_double(NT) & y) { return x.den * y == x.num; } // Uh? Quotient& normalize(); From f8c1bc5aa79d8d0dbd0319f54c8d4e2b49adfe9e Mon Sep 17 00:00:00 2001 From: Maxime Gimeno Date: Fri, 22 May 2020 13:30:43 +0200 Subject: [PATCH 443/568] Display the scene files available when loading a scene from ssh. --- Polyhedron/demo/Polyhedron/MainWindow.cpp | 24 +++++--- Polyhedron/demo/Polyhedron/Use_ssh.cpp | 61 ++++++++++++++++++- .../demo/Polyhedron/include/CGAL/Use_ssh.h | 7 +++ 3 files changed, 83 insertions(+), 9 deletions(-) diff --git a/Polyhedron/demo/Polyhedron/MainWindow.cpp b/Polyhedron/demo/Polyhedron/MainWindow.cpp index e547916ace7..ee2274122fe 100644 --- a/Polyhedron/demo/Polyhedron/MainWindow.cpp +++ b/Polyhedron/demo/Polyhedron/MainWindow.cpp @@ -3611,14 +3611,7 @@ void MainWindow::on_actionLoad_a_Scene_from_a_Script_File_triggered() server = server.trimmed(); pk = pk.trimmed(); privK=privK.trimmed(); - QString path; - path = QInputDialog::getText(this, - "", - tr("Enter the name of the scene file.")); - if(path.isEmpty()) - return; - if(!path.contains("Polyhedron_demo_")) - path.prepend("Polyhedron_demo_"); + try{ ssh_session session; bool res = establish_ssh_session_from_agent(session, @@ -3649,7 +3642,22 @@ void MainWindow::on_actionLoad_a_Scene_from_a_Script_File_triggered() "The SSH session could not be started."); return; } + QStringList names; + if(!CGAL::ssh_internal::explore_the_galaxy(session, names)) + { + QMessageBox::warning(this, + "Error", + "Could not find remote directory."); + } + QString path; + path = QInputDialog::getItem(this, + "Choose a file", + tr("Choose the scene file."), + names); filename = QString("%1/load_scene.js").arg(QDir::tempPath()); + if(path.isEmpty()) + return; + path.prepend("Polyhedron_demo_"); path = tr("/tmp/%2").arg(path); res = pull_file(session,path.toStdString().c_str(), filename.toStdString().c_str()); if(!res) diff --git a/Polyhedron/demo/Polyhedron/Use_ssh.cpp b/Polyhedron/demo/Polyhedron/Use_ssh.cpp index c54d4ff14f1..028909251c2 100644 --- a/Polyhedron/demo/Polyhedron/Use_ssh.cpp +++ b/Polyhedron/demo/Polyhedron/Use_ssh.cpp @@ -20,8 +20,10 @@ #include #include #include +#include #include +#include bool test_result(int res) { @@ -355,5 +357,62 @@ bool pull_file(ssh_session &session, return true; } -}} +bool explore_the_galaxy(ssh_session &session, + QStringList& files) +{ + ssh_channel channel; + int rc; + channel = ssh_channel_new(session); + if (channel == NULL) return false; + rc = ssh_channel_open_session(channel); + if (rc != SSH_OK) + { + ssh_channel_free(channel); + return rc; + } + rc = ssh_channel_request_exec(channel, "ls /tmp"); + if (rc != SSH_OK) + { + ssh_channel_close(channel); + ssh_channel_free(channel); + return rc; + } + + char buffer[256]; + int nbytes; + nbytes = ssh_channel_read(channel, buffer, sizeof(buffer), 0); + while (nbytes > 0) + { + + std::string sbuf(buffer, nbytes); + if(sbuf.find("Polyhedron_demo_") != std::string::npos) + { + std::istringstream iss(sbuf); + std::string file; + while(iss >> file) + { + if(file.find("Polyhedron_demo_") != std::string::npos) + { + QString name(file.c_str()); + files.push_back(name.remove("Polyhedron_demo_")); + } + } + } + + nbytes = ssh_channel_read(channel, buffer, sizeof(buffer), 0); + } + if (nbytes < 0) + { + ssh_channel_close(channel); + ssh_channel_free(channel); + return false; + } + ssh_channel_send_eof(channel); + ssh_channel_close(channel); + ssh_channel_free(channel); + return true; +} + +}// end of ssh_internal +}// end of CGAL #endif diff --git a/Polyhedron/demo/Polyhedron/include/CGAL/Use_ssh.h b/Polyhedron/demo/Polyhedron/include/CGAL/Use_ssh.h index 7d3ea0bdcc9..5d24a129302 100644 --- a/Polyhedron/demo/Polyhedron/include/CGAL/Use_ssh.h +++ b/Polyhedron/demo/Polyhedron/include/CGAL/Use_ssh.h @@ -1,6 +1,10 @@ #ifndef USE_SSH_H #define USE_SSH_H #include +#include + +class QStringList; + namespace CGAL{ namespace ssh_internal{ //should be used inside a try/catch(ssh::SshException e) @@ -27,5 +31,8 @@ bool pull_file(ssh_session &session, const char *from_path, const char *to_path); +bool explore_the_galaxy(ssh_session &session, + QStringList &files); + }} #endif From 0ea385712fd158cd86c9cc20a84a40402a441b49 Mon Sep 17 00:00:00 2001 From: Laurent Rineau Date: Fri, 22 May 2020 14:52:18 +0200 Subject: [PATCH 444/568] Fix compatibility with C++03 --- STL_Extension/include/CGAL/Compact_container.h | 2 +- .../include/CGAL/Constrained_triangulation_2.h | 10 ++++++---- .../test/Triangulation_2/test_cdt_degenerate_case.cpp | 4 ++-- 3 files changed, 9 insertions(+), 7 deletions(-) diff --git a/STL_Extension/include/CGAL/Compact_container.h b/STL_Extension/include/CGAL/Compact_container.h index 02d21c775ea..0e9d638a33d 100644 --- a/STL_Extension/include/CGAL/Compact_container.h +++ b/STL_Extension/include/CGAL/Compact_container.h @@ -1320,7 +1320,7 @@ namespace handle { template struct Hash_functor; template - struct Hash_functor>{ + struct Hash_functor >{ std::size_t operator()(const CC_iterator& i) { diff --git a/Triangulation_2/include/CGAL/Constrained_triangulation_2.h b/Triangulation_2/include/CGAL/Constrained_triangulation_2.h index 916acdcfd97..6fc2ff05675 100644 --- a/Triangulation_2/include/CGAL/Constrained_triangulation_2.h +++ b/Triangulation_2/include/CGAL/Constrained_triangulation_2.h @@ -54,18 +54,20 @@ namespace internal { #ifdef CGAL_CDT_2_DEBUG_INTERSECTIONS struct Indentation_level { - int n = 0; + int n; + Indentation_level() : n(0) {} friend std::ostream& operator<<(std::ostream& os, Indentation_level level) { return os << std::string(2*level.n, ' '); } Indentation_level& operator++() { ++n; return *this; } Indentation_level& operator--() { --n; return *this; } struct Exit_guard { + Exit_guard(Indentation_level& level): level(level) { ++level; } + Exit_guard(const Exit_guard& other) : level(other.level) { ++level; } Indentation_level& level; ~Exit_guard() { --level; } }; - Exit_guard exit_guard() { return Exit_guard{*this}; } - Exit_guard open_new_scope() { return Exit_guard{++*this}; } + Exit_guard open_new_scope() { return Exit_guard(*this); } } cdt_2_indent_level; #endif // CGAL_CDT_2_DEBUG_INTERSECTIONS @@ -712,7 +714,7 @@ insert_constraint(Vertex_handle vaa, Vertex_handle vbb) << "CT_2::insert_constraint( #" << vaa->time_stamp() << "= " << vaa->point() << " , #" << vbb->time_stamp() << "= " << vbb->point() << " )\n"; - auto exit_guard = CGAL::internal::cdt_2_indent_level.open_new_scope(); + internal::Indentation_level::Exit_guard exit_guard = CGAL::internal::cdt_2_indent_level.open_new_scope(); #endif // CGAL_CDT_2_DEBUG_INTERSECTIONS while(! stack.empty()){ boost::tie(vaa,vbb) = stack.top(); diff --git a/Triangulation_2/test/Triangulation_2/test_cdt_degenerate_case.cpp b/Triangulation_2/test/Triangulation_2/test_cdt_degenerate_case.cpp index 952a7428f5b..b4de0e1e0f7 100644 --- a/Triangulation_2/test/Triangulation_2/test_cdt_degenerate_case.cpp +++ b/Triangulation_2/test/Triangulation_2/test_cdt_degenerate_case.cpp @@ -36,9 +36,9 @@ public: }; #ifdef CGAL_CDT_2_DEBUG_INTERSECTIONS -using Vb = My_vertex_base>; +typedef My_vertex_base > Vb; #else -using Vb = CGAL::Triangulation_vertex_base_2; +typedef CGAL::Triangulation_vertex_base_2 Vb; #endif typedef CGAL::Constrained_triangulation_face_base_2 Fb; From 243e3d040f15d200cdf954398c85d87d59406f1a Mon Sep 17 00:00:00 2001 From: Andreas Fabri Date: Fri, 22 May 2020 15:47:46 +0100 Subject: [PATCH 445/568] fix warnings --- Mesh_2/test/Mesh_2/reproductibility.cpp | 24 ++---------------------- 1 file changed, 2 insertions(+), 22 deletions(-) diff --git a/Mesh_2/test/Mesh_2/reproductibility.cpp b/Mesh_2/test/Mesh_2/reproductibility.cpp index d58eb53b005..504525a1763 100644 --- a/Mesh_2/test/Mesh_2/reproductibility.cpp +++ b/Mesh_2/test/Mesh_2/reproductibility.cpp @@ -23,25 +23,12 @@ using Mesher = CGAL::Delaunay_mesher_2; using Vertex_handle = CDT::Vertex_handle; using Point = CDT::Point; -int main(int argc, char* argv[]) +int main(int, char*) { - std::string path = argv[0]; - path = path.substr(0, path.rfind('/') + 1); - - std::cout << "Current dir:" << path << std::endl; - - auto triangulate = [&path](int index) + auto triangulate = [](int index) { CDT cdt; - auto write_tr = [&](const std::string& filename) - { -// std::ofstream file(path + filename + "_" + std::to_string(index) + ".off"); -// -// cdt.file_output(file); -// file.close(); - }; - Vertex_handle va = cdt.insert(Point(-0.74397572, -0.54545455)); Vertex_handle vb = cdt.insert(Point(-0.13526831, -1)); Vertex_handle vc = cdt.insert(Point(0.067634156, -1)); @@ -77,18 +64,11 @@ int main(int argc, char* argv[]) std::cout << "Number of vertices before: " << cdt.number_of_vertices() << std::endl; - write_tr("before_refine"); - Mesher mesher(cdt); mesher.set_criteria(Criteria(0.125, 0.05*std::sqrt(2))); -// mesher.clear_seeds(); -// mesher.init(); - mesher.refine_mesh(); - write_tr("after_refine"); - std::cout << "Number of vertices after: " << cdt.number_of_vertices() << std::endl; std::stringstream ss; From d7224e5f66e45d3d6d4fc21806e4399478fa1196 Mon Sep 17 00:00:00 2001 From: Marc Glisse Date: Sun, 24 May 2020 11:08:44 +0200 Subject: [PATCH 446/568] Weirdo constructor --- Interpolation/include/CGAL/interpolation_functions.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Interpolation/include/CGAL/interpolation_functions.h b/Interpolation/include/CGAL/interpolation_functions.h index 58780776458..0c672580504 100644 --- a/Interpolation/include/CGAL/interpolation_functions.h +++ b/Interpolation/include/CGAL/interpolation_functions.h @@ -34,7 +34,7 @@ struct Data_access typedef typename Map::mapped_type Data_type; typedef typename Map::key_type Key_type; - Data_access(const Map& m): map(m){} + Data_access(const Map& m): map(m){} std::pair< Data_type, bool> operator()(const Key_type& p) const From 2756b2ac35efdb96cb1874ee01aa468e3e742201 Mon Sep 17 00:00:00 2001 From: Marc Glisse Date: Sun, 24 May 2020 11:11:32 +0200 Subject: [PATCH 447/568] More weirdo constructors --- .../CGAL/Boolean_set_operations_2/Polygon_2_curve_iterator.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Boolean_set_operations_2/include/CGAL/Boolean_set_operations_2/Polygon_2_curve_iterator.h b/Boolean_set_operations_2/include/CGAL/Boolean_set_operations_2/Polygon_2_curve_iterator.h index 39a5e7dd34a..833f9afd571 100644 --- a/Boolean_set_operations_2/include/CGAL/Boolean_set_operations_2/Polygon_2_curve_iterator.h +++ b/Boolean_set_operations_2/include/CGAL/Boolean_set_operations_2/Polygon_2_curve_iterator.h @@ -60,9 +60,9 @@ public: Edge_const_iterator m_curr_edge; // points to the current edge iterator public: - Polygon_2_curve_iterator< X_monotone_curve_2_, Polygon_ >(){} + Polygon_2_curve_iterator(){} - Polygon_2_curve_iterator< X_monotone_curve_2_, Polygon_ > + Polygon_2_curve_iterator (const Polygon* pgn, Edge_const_iterator ci) : m_pgn(pgn), m_curr_edge(ci) {} From 0fcbaf5aa4e55352f9d0766b12e66036f1d49432 Mon Sep 17 00:00:00 2001 From: Marc Glisse Date: Sun, 24 May 2020 11:15:12 +0200 Subject: [PATCH 448/568] More weirdo constructors --- .../include/CGAL/Largest_empty_iso_rectangle_2.h | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/Inscribed_areas/include/CGAL/Largest_empty_iso_rectangle_2.h b/Inscribed_areas/include/CGAL/Largest_empty_iso_rectangle_2.h index 601f4d3e9d6..382c80e2c0b 100644 --- a/Inscribed_areas/include/CGAL/Largest_empty_iso_rectangle_2.h +++ b/Inscribed_areas/include/CGAL/Largest_empty_iso_rectangle_2.h @@ -233,12 +233,11 @@ public: ~Largest_empty_iso_rectangle_2(); //! An operator= - Largest_empty_iso_rectangle_2& - operator =(const Largest_empty_iso_rectangle_2& ler); + Largest_empty_iso_rectangle_2& + operator =(const Largest_empty_iso_rectangle_2& ler); //! A copy constructor - Largest_empty_iso_rectangle_2( - const Largest_empty_iso_rectangle_2& ler); + Largest_empty_iso_rectangle_2(const Largest_empty_iso_rectangle_2& ler); struct Internal_point { Point_2 x_part;// the x coordinate of the point From e2a77e54b8ac1c9e86ab30819d2a16837237a3fb Mon Sep 17 00:00:00 2001 From: Marc Glisse Date: Sun, 24 May 2020 11:18:01 +0200 Subject: [PATCH 449/568] More weirdo constructors --- .../include/CGAL/Gps_circle_segment_traits_2.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Boolean_set_operations_2/include/CGAL/Gps_circle_segment_traits_2.h b/Boolean_set_operations_2/include/CGAL/Gps_circle_segment_traits_2.h index 1d29214e267..4b88536cf14 100644 --- a/Boolean_set_operations_2/include/CGAL/Gps_circle_segment_traits_2.h +++ b/Boolean_set_operations_2/include/CGAL/Gps_circle_segment_traits_2.h @@ -27,7 +27,7 @@ class Gps_circle_segment_traits_2 : public Gps_traits_2 > { public: - Gps_circle_segment_traits_2(bool use_cache = false) : + Gps_circle_segment_traits_2(bool use_cache = false) : Gps_traits_2 >() { this->m_use_cache = use_cache; From 0119877009fcf698eac1089834ab07994ae5884a Mon Sep 17 00:00:00 2001 From: Andreas Fabri Date: Mon, 25 May 2020 07:19:33 +0100 Subject: [PATCH 450/568] char** --- Mesh_2/test/Mesh_2/reproductibility.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Mesh_2/test/Mesh_2/reproductibility.cpp b/Mesh_2/test/Mesh_2/reproductibility.cpp index 504525a1763..bb470c98b67 100644 --- a/Mesh_2/test/Mesh_2/reproductibility.cpp +++ b/Mesh_2/test/Mesh_2/reproductibility.cpp @@ -23,7 +23,7 @@ using Mesher = CGAL::Delaunay_mesher_2; using Vertex_handle = CDT::Vertex_handle; using Point = CDT::Point; -int main(int, char*) +int main(int, char**) { auto triangulate = [](int index) { From 3ab72f217a52ad7f41b0ad00e07d66d6bec7f5c2 Mon Sep 17 00:00:00 2001 From: Maxime Gimeno Date: Mon, 25 May 2020 09:07:48 +0200 Subject: [PATCH 451/568] Add 'breaking change' to the change log --- Installation/CHANGES.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Installation/CHANGES.md b/Installation/CHANGES.md index 8656ae9466f..63622bfd592 100644 --- a/Installation/CHANGES.md +++ b/Installation/CHANGES.md @@ -39,7 +39,7 @@ Release History ### Surface Mesh - - The function `CGAL::Surface_mesh::clear()` now removes all non-default properties instead of just emptying them. + - **Breaking change**: The function `CGAL::Surface_mesh::clear()` now removes all non-default properties instead of just emptying them. Release 5.0 ----------- From 69d174571a95d17c8e36ad5bb26bfe3f5c6d2be2 Mon Sep 17 00:00:00 2001 From: Dmitry Anisimov Date: Mon, 25 May 2020 11:25:01 +0200 Subject: [PATCH 452/568] added the missing macros include --- Installation/cmake/modules/CGAL_GeneratorSpecificSettings.cmake | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Installation/cmake/modules/CGAL_GeneratorSpecificSettings.cmake b/Installation/cmake/modules/CGAL_GeneratorSpecificSettings.cmake index 6fc2e5c9edc..5cf46f1adda 100644 --- a/Installation/cmake/modules/CGAL_GeneratorSpecificSettings.cmake +++ b/Installation/cmake/modules/CGAL_GeneratorSpecificSettings.cmake @@ -1,3 +1,5 @@ +include(${CMAKE_CURRENT_LIST_DIR}/CGAL_Macros.cmake) + if ( NOT CGAL_GENERATOR_SPECIFIC_SETTINGS_FILE_INCLUDED ) set( CGAL_GENERATOR_SPECIFIC_SETTINGS_FILE_INCLUDED 1 ) From 51959b615f8ab825ec7629c400f386777097bdcf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9bastien=20Loriot?= Date: Mon, 25 May 2020 13:31:10 +0200 Subject: [PATCH 453/568] typo --- .../doc/Surface_mesh_topology/PackageDescription.txt | 2 +- .../doc/Surface_mesh_topology/Surface_mesh_topology.txt | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Surface_mesh_topology/doc/Surface_mesh_topology/PackageDescription.txt b/Surface_mesh_topology/doc/Surface_mesh_topology/PackageDescription.txt index 5a2e6da0e3c..45a0fcebbea 100644 --- a/Surface_mesh_topology/doc/Surface_mesh_topology/PackageDescription.txt +++ b/Surface_mesh_topology/doc/Surface_mesh_topology/PackageDescription.txt @@ -21,7 +21,7 @@ \cgalPkgPicture{surface-mesh-topology-logo.png} \cgalPkgSummaryBegin \cgalPkgAuthor{Guillaume Damiand, Francis Lazarus} -\cgalPkgDesc{This package provides a toolbox for manipulating curves on a combinatorial surface from the topological viewpoint. Two main functionalities are proposed. One is the computation of shortest curves that cannot be continuously deformed to a point. This includes the computation of the so-called edge width and face width of the vertex-edge graph of a combinatorial surface. The other functionality is the homotopy test for deciding if two given curves on a combinatorial surface can be continuously deformed one into the other.} +\cgalPkgDesc{This package provides a toolbox for manipulating curves on a combinatorial surface from the topological point of view. Two main functionalities are proposed. One is the computation of shortest curves that cannot be continuously deformed to a point. This includes the computation of the so-called edge width and face width of the vertex-edge graph of a combinatorial surface. The other functionality is the homotopy test for deciding if two given curves on a combinatorial surface can be continuously deformed one into the other.} \cgalPkgManuals{Chapter_Surface_Mesh_Topology,PkgSurfaceMeshTopology} \cgalPkgSummaryEnd \cgalPkgShortInfoBegin diff --git a/Surface_mesh_topology/doc/Surface_mesh_topology/Surface_mesh_topology.txt b/Surface_mesh_topology/doc/Surface_mesh_topology/Surface_mesh_topology.txt index 36ea7108b94..b85cc68b45c 100644 --- a/Surface_mesh_topology/doc/Surface_mesh_topology/Surface_mesh_topology.txt +++ b/Surface_mesh_topology/doc/Surface_mesh_topology/Surface_mesh_topology.txt @@ -8,7 +8,7 @@ namespace CGAL { \cgalAutoToc \author Guillaume Damiand and Francis Lazarus -This package provides a toolbox for manipulating curves on a combinatorial surface from the topological viewpoint. Two main functionalities are proposed. One is the computation of shortest curves that cannot be continuously deformed to a point. This includes the computation of the so-called edge width and face width of the vertex-edge graph of a combinatorial surface. The other functionality is the homotopy test for deciding if two given curves on a combinatorial surface can be continuously deformed one into the other. +This package provides a toolbox for manipulating curves on a combinatorial surface from the topological point of view. Two main functionalities are proposed. One is the computation of shortest curves that cannot be continuously deformed to a point. This includes the computation of the so-called edge width and face width of the vertex-edge graph of a combinatorial surface. The other functionality is the homotopy test for deciding if two given curves on a combinatorial surface can be continuously deformed one into the other. \section SMTopology Introduction From f51fe6052f58b895f11fa33c435c29a4d52725ee Mon Sep 17 00:00:00 2001 From: Jane Tournois Date: Tue, 26 May 2020 15:00:06 +0200 Subject: [PATCH 454/568] fix automatic conversion to bool warning --- .../tetrahedral_remeshing_with_features.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Tetrahedral_remeshing/examples/Tetrahedral_remeshing/tetrahedral_remeshing_with_features.cpp b/Tetrahedral_remeshing/examples/Tetrahedral_remeshing/tetrahedral_remeshing_with_features.cpp index eef842f7234..c064c5100ec 100644 --- a/Tetrahedral_remeshing/examples/Tetrahedral_remeshing/tetrahedral_remeshing_with_features.cpp +++ b/Tetrahedral_remeshing/examples/Tetrahedral_remeshing/tetrahedral_remeshing_with_features.cpp @@ -61,7 +61,7 @@ public: { CGAL_assertion(map.m_set_ptr != NULL); CGAL_assertion(k.first < k.second); - return map.m_set_ptr->count(k); + return (map.m_set_ptr->count(k) > 0); } }; From 4dda7b6c801690c336cbc69b02deaf1bb608b6fe Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9bastien=20Loriot?= Date: Wed, 27 May 2020 15:53:05 +0200 Subject: [PATCH 455/568] update license of c3t3 related files a proper package must be created in a later release --- Mesh_3/include/CGAL/IO/File_binary_mesh_3.h | 2 +- Mesh_3/include/CGAL/IO/File_maya.h | 2 +- Mesh_3/include/CGAL/IO/File_medit.h | 2 +- Mesh_3/include/CGAL/IO/facets_in_complex_3_to_triangle_mesh.h | 2 +- Mesh_3/include/CGAL/Mesh_3/Has_features.h | 2 +- .../CGAL/Mesh_3/Mesh_complex_3_in_triangulation_3_base.h | 2 +- Mesh_3/include/CGAL/Mesh_3/Mesh_surface_cell_base_3.h | 2 +- Mesh_3/include/CGAL/Mesh_3/config.h | 2 +- Mesh_3/include/CGAL/Mesh_3/io_signature.h | 2 +- Mesh_3/include/CGAL/Mesh_3/tet_soup_to_c3t3.h | 2 +- Mesh_3/include/CGAL/Mesh_3/utilities.h | 2 +- Mesh_3/include/CGAL/Mesh_cell_base_3.h | 2 +- Mesh_3/include/CGAL/Mesh_complex_3_in_triangulation_3.h | 2 +- Mesh_3/include/CGAL/Mesh_vertex_base_3.h | 2 +- ...undary_of_subdomain_of_complex_3_in_triangulation_3_to_off.h | 2 +- Mesh_3/include/CGAL/internal/Mesh_3/get_index.h | 2 +- Mesh_3/include/CGAL/internal/Mesh_3/indices_management.h | 2 +- 17 files changed, 17 insertions(+), 17 deletions(-) diff --git a/Mesh_3/include/CGAL/IO/File_binary_mesh_3.h b/Mesh_3/include/CGAL/IO/File_binary_mesh_3.h index b4ef55cc46b..52ac49d057b 100644 --- a/Mesh_3/include/CGAL/IO/File_binary_mesh_3.h +++ b/Mesh_3/include/CGAL/IO/File_binary_mesh_3.h @@ -13,7 +13,7 @@ #ifndef CGAL_IO_FILE_BINARY_MESH_3_H #define CGAL_IO_FILE_BINARY_MESH_3_H -#include +#include #include diff --git a/Mesh_3/include/CGAL/IO/File_maya.h b/Mesh_3/include/CGAL/IO/File_maya.h index 15a38ee55ad..b9e67d978ee 100644 --- a/Mesh_3/include/CGAL/IO/File_maya.h +++ b/Mesh_3/include/CGAL/IO/File_maya.h @@ -12,7 +12,7 @@ #ifndef CGAL_IO_FILE_MAYA_H #define CGAL_IO_FILE_MAYA_H -#include +#include #include #include diff --git a/Mesh_3/include/CGAL/IO/File_medit.h b/Mesh_3/include/CGAL/IO/File_medit.h index a0005e98894..42501a7fd63 100644 --- a/Mesh_3/include/CGAL/IO/File_medit.h +++ b/Mesh_3/include/CGAL/IO/File_medit.h @@ -14,7 +14,7 @@ #ifndef CGAL_IO_FILE_MEDIT_H #define CGAL_IO_FILE_MEDIT_H -#include +#include #include diff --git a/Mesh_3/include/CGAL/IO/facets_in_complex_3_to_triangle_mesh.h b/Mesh_3/include/CGAL/IO/facets_in_complex_3_to_triangle_mesh.h index 132df01c693..d69f445716f 100644 --- a/Mesh_3/include/CGAL/IO/facets_in_complex_3_to_triangle_mesh.h +++ b/Mesh_3/include/CGAL/IO/facets_in_complex_3_to_triangle_mesh.h @@ -14,7 +14,7 @@ #ifndef CGAL_FACETS_IN_COMPLEX_3_TO_TRIANGLE_MESH_H #define CGAL_FACETS_IN_COMPLEX_3_TO_TRIANGLE_MESH_H -#include +#include #include #include diff --git a/Mesh_3/include/CGAL/Mesh_3/Has_features.h b/Mesh_3/include/CGAL/Mesh_3/Has_features.h index 2eb7f6844fa..94d9b02de4b 100644 --- a/Mesh_3/include/CGAL/Mesh_3/Has_features.h +++ b/Mesh_3/include/CGAL/Mesh_3/Has_features.h @@ -13,7 +13,7 @@ #ifndef CGAL_MESH_3_HAS_FEATURES_H #define CGAL_MESH_3_HAS_FEATURES_H -#include +#include #include diff --git a/Mesh_3/include/CGAL/Mesh_3/Mesh_complex_3_in_triangulation_3_base.h b/Mesh_3/include/CGAL/Mesh_3/Mesh_complex_3_in_triangulation_3_base.h index 02b31a987b9..af999cd1bc9 100644 --- a/Mesh_3/include/CGAL/Mesh_3/Mesh_complex_3_in_triangulation_3_base.h +++ b/Mesh_3/include/CGAL/Mesh_3/Mesh_complex_3_in_triangulation_3_base.h @@ -18,7 +18,7 @@ #ifndef CGAL_MESH_3_MESH_COMPLEX_3_IN_TRIANGULATION_3_BASE_H #define CGAL_MESH_3_MESH_COMPLEX_3_IN_TRIANGULATION_3_BASE_H -#include +#include #include diff --git a/Mesh_3/include/CGAL/Mesh_3/Mesh_surface_cell_base_3.h b/Mesh_3/include/CGAL/Mesh_3/Mesh_surface_cell_base_3.h index 4bd39365f22..f4b279a0fdc 100644 --- a/Mesh_3/include/CGAL/Mesh_3/Mesh_surface_cell_base_3.h +++ b/Mesh_3/include/CGAL/Mesh_3/Mesh_surface_cell_base_3.h @@ -18,7 +18,7 @@ #ifndef CGAL_MESH_3_MESH_SURFACE_CELL_BASE_3_H #define CGAL_MESH_3_MESH_SURFACE_CELL_BASE_3_H -#include +#include #include diff --git a/Mesh_3/include/CGAL/Mesh_3/config.h b/Mesh_3/include/CGAL/Mesh_3/config.h index 07e7c765993..ccb05647ef5 100644 --- a/Mesh_3/include/CGAL/Mesh_3/config.h +++ b/Mesh_3/include/CGAL/Mesh_3/config.h @@ -12,7 +12,7 @@ #ifndef CGAL_MESH_3_CONFIG_H #define CGAL_MESH_3_CONFIG_H 1 -#include +#include #include diff --git a/Mesh_3/include/CGAL/Mesh_3/io_signature.h b/Mesh_3/include/CGAL/Mesh_3/io_signature.h index 286d5e5e3ac..d871b8ffe7d 100644 --- a/Mesh_3/include/CGAL/Mesh_3/io_signature.h +++ b/Mesh_3/include/CGAL/Mesh_3/io_signature.h @@ -13,7 +13,7 @@ #ifndef CGAL_MESH_3_IO_SIGNATURE_H #define CGAL_MESH_3_IO_SIGNATURE_H -#include +#include #define CGAL_MESH_3_IO_H // the old include macro, tested by other files diff --git a/Mesh_3/include/CGAL/Mesh_3/tet_soup_to_c3t3.h b/Mesh_3/include/CGAL/Mesh_3/tet_soup_to_c3t3.h index e20ed8a4144..632d87a83d8 100644 --- a/Mesh_3/include/CGAL/Mesh_3/tet_soup_to_c3t3.h +++ b/Mesh_3/include/CGAL/Mesh_3/tet_soup_to_c3t3.h @@ -17,7 +17,7 @@ #ifndef CGAL_MESH_3_TET_SOUP_TO_C3T3_H #define CGAL_MESH_3_TET_SOUP_TO_C3T3_H -#include +#include #include #include diff --git a/Mesh_3/include/CGAL/Mesh_3/utilities.h b/Mesh_3/include/CGAL/Mesh_3/utilities.h index 4d73f43de53..5e49f7a617e 100644 --- a/Mesh_3/include/CGAL/Mesh_3/utilities.h +++ b/Mesh_3/include/CGAL/Mesh_3/utilities.h @@ -17,7 +17,7 @@ #ifndef CGAL_MESH_3_UTILITIES_H #define CGAL_MESH_3_UTILITIES_H -#include +#include #include #include diff --git a/Mesh_3/include/CGAL/Mesh_cell_base_3.h b/Mesh_3/include/CGAL/Mesh_cell_base_3.h index 5c719d22fe6..2babd0cc5db 100644 --- a/Mesh_3/include/CGAL/Mesh_cell_base_3.h +++ b/Mesh_3/include/CGAL/Mesh_cell_base_3.h @@ -15,7 +15,7 @@ #ifndef CGAL_MESH_CELL_BASE_3_H #define CGAL_MESH_CELL_BASE_3_H -#include +#include // #define CGAL_DEPRECATED_HEADER "" diff --git a/Mesh_3/include/CGAL/Mesh_complex_3_in_triangulation_3.h b/Mesh_3/include/CGAL/Mesh_complex_3_in_triangulation_3.h index 954478ccee7..8fb53524d81 100644 --- a/Mesh_3/include/CGAL/Mesh_complex_3_in_triangulation_3.h +++ b/Mesh_3/include/CGAL/Mesh_complex_3_in_triangulation_3.h @@ -18,7 +18,7 @@ #ifndef CGAL_MESH_COMPLEX_3_IN_TRIANGULATION_3_H #define CGAL_MESH_COMPLEX_3_IN_TRIANGULATION_3_H -#include +#include #include #include diff --git a/Mesh_3/include/CGAL/Mesh_vertex_base_3.h b/Mesh_3/include/CGAL/Mesh_vertex_base_3.h index 9ad67147d1b..aeb3411a1e1 100644 --- a/Mesh_3/include/CGAL/Mesh_vertex_base_3.h +++ b/Mesh_3/include/CGAL/Mesh_vertex_base_3.h @@ -20,7 +20,7 @@ #ifndef CGAL_COMPACT_MESH_VERTEX_BASE_3_H #define CGAL_COMPACT_MESH_VERTEX_BASE_3_H -#include +#include #include diff --git a/Mesh_3/include/CGAL/internal/Mesh_3/Boundary_of_subdomain_of_complex_3_in_triangulation_3_to_off.h b/Mesh_3/include/CGAL/internal/Mesh_3/Boundary_of_subdomain_of_complex_3_in_triangulation_3_to_off.h index 08ecbdb070a..b08974e545e 100644 --- a/Mesh_3/include/CGAL/internal/Mesh_3/Boundary_of_subdomain_of_complex_3_in_triangulation_3_to_off.h +++ b/Mesh_3/include/CGAL/internal/Mesh_3/Boundary_of_subdomain_of_complex_3_in_triangulation_3_to_off.h @@ -12,7 +12,7 @@ #ifndef CGAL_INTERNAL_MESH_3_BOUNDARY_OF_SUDDOMAIN_OF_COMPLEX_3_IN_TRIANGULATION_3_TO_OFF_H #define CGAL_INTERNAL_MESH_3_BOUNDARY_OF_SUDDOMAIN_OF_COMPLEX_3_IN_TRIANGULATION_3_TO_OFF_H -#include +#include #include diff --git a/Mesh_3/include/CGAL/internal/Mesh_3/get_index.h b/Mesh_3/include/CGAL/internal/Mesh_3/get_index.h index b84f4639b51..1bbf2f971aa 100644 --- a/Mesh_3/include/CGAL/internal/Mesh_3/get_index.h +++ b/Mesh_3/include/CGAL/internal/Mesh_3/get_index.h @@ -17,7 +17,7 @@ #ifndef CGAL_INTERNAL_MESH_3_GET_INDEX_3_H #define CGAL_INTERNAL_MESH_3_GET_INDEX_3_H -#include +#include #include diff --git a/Mesh_3/include/CGAL/internal/Mesh_3/indices_management.h b/Mesh_3/include/CGAL/internal/Mesh_3/indices_management.h index 6f637bebb48..62bde6e2135 100644 --- a/Mesh_3/include/CGAL/internal/Mesh_3/indices_management.h +++ b/Mesh_3/include/CGAL/internal/Mesh_3/indices_management.h @@ -18,7 +18,7 @@ #ifndef CGAL_INTERNAL_MESH_3_INDICES_MANAGEMENT_H #define CGAL_INTERNAL_MESH_3_INDICES_MANAGEMENT_H -#include +#include #include From 8b3c1eeb48f8c08ed3e6a3de4c82ff7e87ea2c07 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9bastien=20Loriot?= Date: Wed, 27 May 2020 16:24:25 +0200 Subject: [PATCH 456/568] fix doc issues --- .../doc/Tetrahedral_remeshing/PackageDescription.txt | 10 ++-------- .../CGAL/Tetrahedral_remeshing/Remeshing_cell_base_3.h | 6 ++++-- .../Tetrahedral_remeshing/Remeshing_vertex_base_3.h | 7 ++++--- 3 files changed, 10 insertions(+), 13 deletions(-) diff --git a/Tetrahedral_remeshing/doc/Tetrahedral_remeshing/PackageDescription.txt b/Tetrahedral_remeshing/doc/Tetrahedral_remeshing/PackageDescription.txt index 1179443eb90..b8672c0cdd5 100644 --- a/Tetrahedral_remeshing/doc/Tetrahedral_remeshing/PackageDescription.txt +++ b/Tetrahedral_remeshing/doc/Tetrahedral_remeshing/PackageDescription.txt @@ -7,12 +7,6 @@ /// \defgroup PkgTetrahedralRemeshingClasses Classes /// \ingroup PkgTetrahedralRemeshingRef -/// \defgroup PkgPACKAGETraitsClasses Traits Classes -/// \ingroup PkgPACKAGE - -/// \defgroup PkgPACKAGEMiscellaneous Miscellaneous -/// \ingroup PkgPACKAGE - /*! \addtogroup PkgTetrahedralRemeshingRef @@ -22,14 +16,14 @@ \cgalPkgSummaryBegin \cgalPkgAuthors{Jane Tournois, Noura Faraj} \cgalPkgDesc{ -The package provides a function for remeshing of tetrahedral meshes, +The package provides a function for remeshing tetrahedral meshes, targetting high quality meshes with respect to dihedral angles.} \cgalPkgManuals{Chapter_Tetrahedral_Remeshing,PkgTetrahedralRemeshingRef} \cgalPkgSummaryEnd \cgalPkgShortInfoBegin \cgalPkgSince{5.1} -\cgalPkgDependsOn{\ref PkgTriangulation3, PkgMesh3} +\cgalPkgDependsOn{\ref PkgTriangulation3} \cgalPkgBib{faraj2016mvr} \cgalPkgLicense{\ref licensesGPL "GPL"} \cgalPkgDemo{Polyhedron demo,polyhedron_3.zip} diff --git a/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/Remeshing_cell_base_3.h b/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/Remeshing_cell_base_3.h index ff9a074ecb9..e64f67c41f2 100644 --- a/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/Remeshing_cell_base_3.h +++ b/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/Remeshing_cell_base_3.h @@ -48,13 +48,15 @@ It has the default value `Triangulation_cell_base_3`. \cgalModels `MeshCellBase_3` */ +#ifndef DOXYGEN_RUNNING template > using Remeshing_cell_base_3 -#ifndef DOXYGEN_RUNNING = CGAL::Mesh_cell_base_3; #else - = unspecified_type; +template > +class Remeshing_cell_base_3; #endif }//end namespace Tetrahedral_remeshing diff --git a/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/Remeshing_vertex_base_3.h b/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/Remeshing_vertex_base_3.h index 6c6513e7655..2d056e8e244 100644 --- a/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/Remeshing_vertex_base_3.h +++ b/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/Remeshing_vertex_base_3.h @@ -49,14 +49,15 @@ It has the default value `Triangulation_vertex_base_3`. \cgalModels `MeshVertexBase_3` */ - +#ifndef DOXYGEN_RUNNING template > using Remeshing_vertex_base_3 -#ifndef DOXYGEN_RUNNING = CGAL::Mesh_vertex_base_3; #else - = unspecified_type; +template > +class Remeshing_vertex_base_3; #endif }//end namespace Tetrahedral_remeshing From fd9618d36159aa3c563041caba31b418f5baeb3e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9bastien=20Loriot?= Date: Wed, 27 May 2020 18:16:46 +0200 Subject: [PATCH 457/568] remove debug macros --- .../Tetrahedral_remeshing/tetrahedral_remeshing_example.cpp | 2 -- .../tetrahedral_remeshing_with_features.cpp | 3 --- 2 files changed, 5 deletions(-) diff --git a/Tetrahedral_remeshing/examples/Tetrahedral_remeshing/tetrahedral_remeshing_example.cpp b/Tetrahedral_remeshing/examples/Tetrahedral_remeshing/tetrahedral_remeshing_example.cpp index 5cad680f8be..ce2e18a8e7b 100644 --- a/Tetrahedral_remeshing/examples/Tetrahedral_remeshing/tetrahedral_remeshing_example.cpp +++ b/Tetrahedral_remeshing/examples/Tetrahedral_remeshing/tetrahedral_remeshing_example.cpp @@ -1,5 +1,3 @@ -//#define CGAL_TETRAHEDRAL_REMESHING_VERBOSE - #include #include diff --git a/Tetrahedral_remeshing/examples/Tetrahedral_remeshing/tetrahedral_remeshing_with_features.cpp b/Tetrahedral_remeshing/examples/Tetrahedral_remeshing/tetrahedral_remeshing_with_features.cpp index c064c5100ec..af366a13cf8 100644 --- a/Tetrahedral_remeshing/examples/Tetrahedral_remeshing/tetrahedral_remeshing_with_features.cpp +++ b/Tetrahedral_remeshing/examples/Tetrahedral_remeshing/tetrahedral_remeshing_with_features.cpp @@ -1,6 +1,3 @@ -#define CGAL_TETRAHEDRAL_REMESHING_VERBOSE -#define CGAL_DUMP_REMESHING_STEPS - #include #include From f386790eaa878f4b28185197fca15ccfa1f90f72 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9bastien=20Loriot?= Date: Wed, 27 May 2020 18:38:38 +0200 Subject: [PATCH 458/568] add new concepts to ease the reading + few doc fixes --- .../Tetrahedral_remeshing/PackageDescription.txt | 2 ++ .../include/CGAL/tetrahedral_remeshing.h | 13 +++++++++---- 2 files changed, 11 insertions(+), 4 deletions(-) diff --git a/Tetrahedral_remeshing/doc/Tetrahedral_remeshing/PackageDescription.txt b/Tetrahedral_remeshing/doc/Tetrahedral_remeshing/PackageDescription.txt index b8672c0cdd5..b0935baf35a 100644 --- a/Tetrahedral_remeshing/doc/Tetrahedral_remeshing/PackageDescription.txt +++ b/Tetrahedral_remeshing/doc/Tetrahedral_remeshing/PackageDescription.txt @@ -36,6 +36,8 @@ targetting high quality meshes with respect to dihedral angles.} \cgalCRPSection{Concepts} - `RemeshingTriangulationTraits_3` +- `RemeshingVertexBase_3` +- `RemeshingCellBase_3` \cgalCRPSection{Classes} diff --git a/Tetrahedral_remeshing/include/CGAL/tetrahedral_remeshing.h b/Tetrahedral_remeshing/include/CGAL/tetrahedral_remeshing.h index 31123ed41e4..446d3eb70e7 100644 --- a/Tetrahedral_remeshing/include/CGAL/tetrahedral_remeshing.h +++ b/Tetrahedral_remeshing/include/CGAL/tetrahedral_remeshing.h @@ -39,6 +39,9 @@ namespace CGAL * \ingroup PkgTetrahedralRemeshingRef * remeshes a tetrahedral mesh. * +* A good default for the `Triangulation_3` type is to use `CGAL::Tetrahedral_remeshing::Remeshing_triangulation_3` +* that inherits from `Triangulation_3` with a `TDS` suitable for this function. +* * This function takes as input a 3-dimensional triangulation * and performs a sequence of atomic operations * in order to generate as output a high quality mesh with a prescribed @@ -57,7 +60,7 @@ namespace CGAL * * Subdomains are defined by indices that * are stored in the cells of the input triangulation, following the `MeshCellBase_3` -* concept. +* concept (refined by `RemeshingCellBase_3`). * The surfacic interfaces between subdomains are formed by facets whose two incident cells * have different subdomain indices. * The edges where three or more subdomains meet form feature polylines, @@ -67,8 +70,8 @@ namespace CGAL * @tparam Traits is the geometric traits, model of `RemeshingTriangulationTraits_3` * @tparam TDS is the triangulation data structure for `Triangulation_3`, * model of ` TriangulationDataStructure_3`, -* with cell base model of `MeshCellBase_3` -* and vertex base model of `MeshVertexBase_3`. +* with cell base model of `RemeshingCellBase_3` +* and vertex base model of `RemeshingVertexBase_3`. * @tparam SLDS is an optional parameter for `Triangulation_3`, that * specifies the type of the spatial lock data structure. * @tparam NamedParameters a sequence of \ref Remeshing_namedparameters "Named Parameters" @@ -105,7 +108,9 @@ namespace CGAL * By default, all cells with a non-zero `Subdomain_index` are selected. * \cgalParamEnd * \cgalNamedParamsEnd - +* +* \sa `CGAL::Tetrahedral_remeshing::Remeshing_triangulation_3` +* * @todo implement non-uniform sizing field instead of uniform target edge length */ template Date: Wed, 27 May 2020 18:41:56 +0200 Subject: [PATCH 459/568] add missing files --- .../Concepts/RemeshingCellBase_3.h | 13 +++++++++++++ .../Concepts/RemeshingVertexBase_3.h | 13 +++++++++++++ 2 files changed, 26 insertions(+) create mode 100644 Tetrahedral_remeshing/doc/Tetrahedral_remeshing/Concepts/RemeshingCellBase_3.h create mode 100644 Tetrahedral_remeshing/doc/Tetrahedral_remeshing/Concepts/RemeshingVertexBase_3.h diff --git a/Tetrahedral_remeshing/doc/Tetrahedral_remeshing/Concepts/RemeshingCellBase_3.h b/Tetrahedral_remeshing/doc/Tetrahedral_remeshing/Concepts/RemeshingCellBase_3.h new file mode 100644 index 00000000000..619886c702a --- /dev/null +++ b/Tetrahedral_remeshing/doc/Tetrahedral_remeshing/Concepts/RemeshingCellBase_3.h @@ -0,0 +1,13 @@ +/*! +\ingroup PkgTetrahedralRemeshingConcepts +\cgalConcept + +\cgalRefines MeshCellBase_3 + +Cell base concept to be used in the triangulation type given to the function `CGAL::tetrahedral_isotropic_remeshing()`. + +\cgalHasModel All models of `CGAL::Tetrahedral_remeshing::Remeshing_cell_base_3`. + +*/ +class RemeshingCellBase_3 +{}; diff --git a/Tetrahedral_remeshing/doc/Tetrahedral_remeshing/Concepts/RemeshingVertexBase_3.h b/Tetrahedral_remeshing/doc/Tetrahedral_remeshing/Concepts/RemeshingVertexBase_3.h new file mode 100644 index 00000000000..38051e0e4a6 --- /dev/null +++ b/Tetrahedral_remeshing/doc/Tetrahedral_remeshing/Concepts/RemeshingVertexBase_3.h @@ -0,0 +1,13 @@ +/*! +\ingroup PkgTetrahedralRemeshingConcepts +\cgalConcept + +\cgalRefines MeshVertexBase_3 + +Vertex base concept to be used in the triangulation type given to the function `CGAL::tetrahedral_isotropic_remeshing()`. + +\cgalHasModel All models of `CGAL::Tetrahedral_remeshing::Remeshing_vertex_base_3`. + +*/ +class RemeshingVertexBase_3 +{}; \ No newline at end of file From 9333cdb5b342781afe1d36e2367691561c8ecbf2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9bastien=20Loriot?= Date: Wed, 27 May 2020 18:45:00 +0200 Subject: [PATCH 460/568] improvements --- .../doc/Tetrahedral_remeshing/Concepts/RemeshingCellBase_3.h | 2 +- .../Tetrahedral_remeshing/Concepts/RemeshingVertexBase_3.h | 4 ++-- Tetrahedral_remeshing/include/CGAL/tetrahedral_remeshing.h | 4 ++-- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/Tetrahedral_remeshing/doc/Tetrahedral_remeshing/Concepts/RemeshingCellBase_3.h b/Tetrahedral_remeshing/doc/Tetrahedral_remeshing/Concepts/RemeshingCellBase_3.h index 619886c702a..6a55d55b842 100644 --- a/Tetrahedral_remeshing/doc/Tetrahedral_remeshing/Concepts/RemeshingCellBase_3.h +++ b/Tetrahedral_remeshing/doc/Tetrahedral_remeshing/Concepts/RemeshingCellBase_3.h @@ -6,7 +6,7 @@ Cell base concept to be used in the triangulation type given to the function `CGAL::tetrahedral_isotropic_remeshing()`. -\cgalHasModel All models of `CGAL::Tetrahedral_remeshing::Remeshing_cell_base_3`. +\cgalHasModel `CGAL::Tetrahedral_remeshing::Remeshing_cell_base_3`. */ class RemeshingCellBase_3 diff --git a/Tetrahedral_remeshing/doc/Tetrahedral_remeshing/Concepts/RemeshingVertexBase_3.h b/Tetrahedral_remeshing/doc/Tetrahedral_remeshing/Concepts/RemeshingVertexBase_3.h index 38051e0e4a6..fa524edef74 100644 --- a/Tetrahedral_remeshing/doc/Tetrahedral_remeshing/Concepts/RemeshingVertexBase_3.h +++ b/Tetrahedral_remeshing/doc/Tetrahedral_remeshing/Concepts/RemeshingVertexBase_3.h @@ -6,8 +6,8 @@ Vertex base concept to be used in the triangulation type given to the function `CGAL::tetrahedral_isotropic_remeshing()`. -\cgalHasModel All models of `CGAL::Tetrahedral_remeshing::Remeshing_vertex_base_3`. +\cgalHasModel `CGAL::Tetrahedral_remeshing::Remeshing_vertex_base_3`. */ class RemeshingVertexBase_3 -{}; \ No newline at end of file +{}; diff --git a/Tetrahedral_remeshing/include/CGAL/tetrahedral_remeshing.h b/Tetrahedral_remeshing/include/CGAL/tetrahedral_remeshing.h index 446d3eb70e7..cb27ec3b81f 100644 --- a/Tetrahedral_remeshing/include/CGAL/tetrahedral_remeshing.h +++ b/Tetrahedral_remeshing/include/CGAL/tetrahedral_remeshing.h @@ -39,8 +39,8 @@ namespace CGAL * \ingroup PkgTetrahedralRemeshingRef * remeshes a tetrahedral mesh. * -* A good default for the `Triangulation_3` type is to use `CGAL::Tetrahedral_remeshing::Remeshing_triangulation_3` -* that inherits from `Triangulation_3` with a `TDS` suitable for this function. +* It is recommended to use `CGAL::Tetrahedral_remeshing::Remeshing_triangulation_3` +* for the first parameter, as it inherits from `Triangulation_3` with a `TDS` suitable for this function. * * This function takes as input a 3-dimensional triangulation * and performs a sequence of atomic operations From 924239544cee08cec4f96d1de6fecda9193b7016 Mon Sep 17 00:00:00 2001 From: Jane Tournois Date: Wed, 27 May 2020 18:50:54 +0200 Subject: [PATCH 461/568] remove load/save from examples and introduce a new header to generate random input at each run --- .../tetrahedral_remeshing_example.cpp | 24 +-- .../tetrahedral_remeshing_generate_input.h | 191 ++++++++++++++++++ ...tetrahedral_remeshing_of_one_subdomain.cpp | 17 +- .../tetrahedral_remeshing_with_features.cpp | 84 +------- 4 files changed, 206 insertions(+), 110 deletions(-) create mode 100644 Tetrahedral_remeshing/examples/Tetrahedral_remeshing/tetrahedral_remeshing_generate_input.h diff --git a/Tetrahedral_remeshing/examples/Tetrahedral_remeshing/tetrahedral_remeshing_example.cpp b/Tetrahedral_remeshing/examples/Tetrahedral_remeshing/tetrahedral_remeshing_example.cpp index ce2e18a8e7b..da292fe7d0a 100644 --- a/Tetrahedral_remeshing/examples/Tetrahedral_remeshing/tetrahedral_remeshing_example.cpp +++ b/Tetrahedral_remeshing/examples/Tetrahedral_remeshing/tetrahedral_remeshing_example.cpp @@ -4,6 +4,7 @@ #include #include +#include "tetrahedral_remeshing_generate_input.h" #include #include @@ -16,26 +17,13 @@ typedef CGAL::Tetrahedral_remeshing::Remeshing_triangulation_3 Remeshing_tria int main(int argc, char* argv[]) { - const char* filename = (argc > 1) ? argv[1] : "data/triangulation_one_subdomain.binary.cgal"; - const double target_edge_length = (argc > 2) ? atof(argv[2]) : 0.1f; + const double target_edge_length = (argc > 1) ? atof(argv[1]) : 0.1; + const std::size_t nbv = (argc > 2) ? atoi(argv[2]) : 1000; - std::ifstream input(filename, std::ios::in | std::ios::binary); + Remeshing_triangulation tr; + CGAL::Tetrahedral_remeshing::generate_input_one_subdomain(nbv, tr); - Remeshing_triangulation t3; - if (!input) - return EXIT_FAILURE; - - if( !CGAL::load_triangulation(input, t3)) - return EXIT_FAILURE; - - CGAL::tetrahedral_isotropic_remeshing(t3, target_edge_length); - - // save output - const std::string file_in(filename); - std::string file_out = file_in.substr(0, file_in.find_first_of(".")); - file_out.append("_out.binary.cgal"); - std::ofstream out(file_out.c_str(), std::ios_base::out | std::ios_base::binary); - CGAL::save_binary_triangulation(out, t3); + CGAL::tetrahedral_isotropic_remeshing(tr, target_edge_length); return EXIT_SUCCESS; } diff --git a/Tetrahedral_remeshing/examples/Tetrahedral_remeshing/tetrahedral_remeshing_generate_input.h b/Tetrahedral_remeshing/examples/Tetrahedral_remeshing/tetrahedral_remeshing_generate_input.h new file mode 100644 index 00000000000..041e127b053 --- /dev/null +++ b/Tetrahedral_remeshing/examples/Tetrahedral_remeshing/tetrahedral_remeshing_generate_input.h @@ -0,0 +1,191 @@ +// Copyright (c) 2020 GeometryFactory (France) and Telecom Paris (France). +// All rights reserved. +// +// This file is part of CGAL (www.cgal.org) +// +// $URL$ +// $Id$ +// SPDX-License-Identifier: GPL-3.0-or-later OR LicenseRef-Commercial +// +// +// Author(s) : Jane Tournois, Noura Faraj + +#include + +#include +#include + +namespace CGAL +{ +namespace Tetrahedral_remeshing +{ + template + void generate_input_two_subdomains(const std::size_t& nbv, Tr& tr) + { + CGAL::Random rng; + + typedef Tr::Point Point; + typedef Tr::Cell_handle Cell_handle; + + while (tr.number_of_vertices() < nbv) + tr.insert(Point(rng.get_double(-1., 1.), rng.get_double(-1., 1.), rng.get_double(-1., 1.))); + + const Tr::Geom_traits::Plane_3 + plane(Point(0, 0, 0), Point(0, 1, 0), Point(0, 0, 1)); + + for (Cell_handle c : tr.finite_cell_handles()) + { + if (plane.has_on_positive_side( + CGAL::centroid(c->vertex(0)->point(), c->vertex(1)->point(), + c->vertex(2)->point(), c->vertex(3)->point()))) + c->set_subdomain_index(1); + else + c->set_subdomain_index(2); + } + CGAL_assertion(tr.is_valid(true)); + } + + + template + void generate_input_one_subdomain(const std::size_t nbv, Tr& tr) + { + CGAL::Random rng; + + typedef typename Tr::Point Point; + std::vector pts; + while (pts.size() < nbv) + { + const double x = rng.get_double(-1., 1.); + const double y = rng.get_double(-1., 1.); + const double z = rng.get_double(-1., 1.); + + pts.push_back(Point(x, y, z)); + } + tr.insert(pts.begin(), pts.end()); + + for (typename Tr::Cell_handle c : tr.finite_cell_handles()) + c->set_subdomain_index(1); + + CGAL_assertion(tr.is_valid(true)); + } + + template + void add_edge(typename Tr::Vertex_handle v1, + typename Tr::Vertex_handle v2, + const Tr& tr, + boost::unordered_set >& constraints) + { + typename Tr::Cell_handle c; + int i, j; + if (tr.is_edge(v1, v2, c, i, j)) + constraints.insert(std::make_pair(v1, v2)); + } + + template + void make_constraints_from_cube_edges( + Tr& tr, + boost::unordered_set >& constraints) + { + typedef typename Tr::Point Point; + typedef typename Tr::Vertex_handle Vertex_handle; + typedef typename Tr::Cell_handle Cell_handle; + + const Point p0(-2., -2., -2.); + const Point p1(-2., -2., -2.); + const Point p2(2., -2., -2.); + const Point p3(2., -2., 2.); + const Point p4(-2., 2., -2.); + const Point p5(-2., 2., 2.); + const Point p6(2., 2., -2.); + const Point p7(2., 2., 2.); + + typename Tr::Locate_type lt; + int li, lj; + Cell_handle c = tr.locate(p0, lt, li, lj); + Vertex_handle v0 = c->vertex(li); + c = tr.locate(p1, lt, li, lj); + Vertex_handle v1 = c->vertex(li); + + c = tr.locate(p2, lt, li, lj); + Vertex_handle v2 = c->vertex(li); + c = tr.locate(p3, lt, li, lj); + Vertex_handle v3 = c->vertex(li); + + c = tr.locate(p4, lt, li, lj); + Vertex_handle v4 = c->vertex(li); + c = tr.locate(p5, lt, li, lj); + Vertex_handle v5 = c->vertex(li); + + c = tr.locate(p6, lt, li, lj); + Vertex_handle v6 = c->vertex(li); + c = tr.locate(p7, lt, li, lj); + Vertex_handle v7 = c->vertex(li); + + // constrain cube edges + add_edge(v0, v1, tr, constraints); + add_edge(v1, v2, tr, constraints); + add_edge(v2, v3, tr, constraints); + add_edge(v3, v0, tr, constraints); + + add_edge(v4, v5, tr, constraints); + add_edge(v5, v6, tr, constraints); + add_edge(v6, v7, tr, constraints); + add_edge(v7, v4, tr, constraints); + + add_edge(v0, v4, tr, constraints); + add_edge(v1, v5, tr, constraints); + add_edge(v2, v6, tr, constraints); + add_edge(v3, v7, tr, constraints); + } + + template + void generate_input_cube(const std::size_t& n, + Tr& tr, + boost::unordered_set >& constraints) + { + typedef typename Tr::Vertex_handle Vertex_handle; + typedef typename Tr::Point Point; + CGAL::Random rng; + + // points in a sphere + std::vector pts; + while (pts.size() < n) + pts.push_back(Point(rng.get_double(-1., 1.), rng.get_double(-1., 1.), rng.get_double(-1., 1.))); + tr.insert(pts.begin(), pts.end()); + + // vertices of a larger cube + Vertex_handle v0 = tr.insert(Point(-2., -2., -2.)); + Vertex_handle v1 = tr.insert(Point(-2., -2., 2.)); + + Vertex_handle v2 = tr.insert(Point(2., -2., -2.)); + Vertex_handle v3 = tr.insert(Point(2., -2., 2.)); + + Vertex_handle v4 = tr.insert(Point(-2., 2., -2.)); + Vertex_handle v5 = tr.insert(Point(-2., 2., 2.)); + + Vertex_handle v6 = tr.insert(Point(2., 2., -2.)); + Vertex_handle v7 = tr.insert(Point(2., 2., 2.)); + + // constrain cube edges + add_edge(v0, v1, tr, constraints); + add_edge(v1, v2, tr, constraints); + add_edge(v2, v3, tr, constraints); + add_edge(v3, v0, tr, constraints); + + add_edge(v4, v5, tr, constraints); + add_edge(v5, v6, tr, constraints); + add_edge(v6, v7, tr, constraints); + add_edge(v7, v4, tr, constraints); + + add_edge(v0, v4, tr, constraints); + add_edge(v1, v5, tr, constraints); + add_edge(v2, v6, tr, constraints); + add_edge(v3, v7, tr, constraints); + + CGAL_assertion(tr.is_valid(true)); + } +} +} \ No newline at end of file diff --git a/Tetrahedral_remeshing/examples/Tetrahedral_remeshing/tetrahedral_remeshing_of_one_subdomain.cpp b/Tetrahedral_remeshing/examples/Tetrahedral_remeshing/tetrahedral_remeshing_of_one_subdomain.cpp index a98f9f84a92..6f108c48789 100644 --- a/Tetrahedral_remeshing/examples/Tetrahedral_remeshing/tetrahedral_remeshing_of_one_subdomain.cpp +++ b/Tetrahedral_remeshing/examples/Tetrahedral_remeshing/tetrahedral_remeshing_of_one_subdomain.cpp @@ -1,11 +1,9 @@ #include -#include - #include #include -#include +#include "tetrahedral_remeshing_generate_input.h" typedef CGAL::Exact_predicates_inexact_constructions_kernel K; @@ -30,22 +28,15 @@ public: int main(int argc, char* argv[]) { - const char* filename = (argc > 1) ? argv[1] : "data/triangulation_two_subdomains.binary.cgal"; - const double target_edge_length = (argc > 2) ? atof(argv[2]) : 0.1; - - std::ifstream input(filename, std::ios_base::in | std::ios_base::binary); - if(!input) - return EXIT_FAILURE; + const double target_edge_length = (argc > 1) ? atof(argv[1]) : 0.1; + const std::size_t nbv = (argc > 2) ? atoi(argv[2]) : 1000; Remeshing_triangulation tr; - CGAL::load_triangulation(input, tr); + CGAL::Tetrahedral_remeshing::generate_input_two_subdomains(nbv, tr); CGAL::tetrahedral_isotropic_remeshing(tr, target_edge_length, CGAL::parameters::cell_selector(Cells_of_subdomain(2))); - std::ofstream ofile("output.binary.cgal", std::ios_base::out | std::ios_base::binary); - CGAL::save_binary_triangulation(ofile, tr); - return EXIT_SUCCESS; } diff --git a/Tetrahedral_remeshing/examples/Tetrahedral_remeshing/tetrahedral_remeshing_with_features.cpp b/Tetrahedral_remeshing/examples/Tetrahedral_remeshing/tetrahedral_remeshing_with_features.cpp index af366a13cf8..581dd0a85db 100644 --- a/Tetrahedral_remeshing/examples/Tetrahedral_remeshing/tetrahedral_remeshing_with_features.cpp +++ b/Tetrahedral_remeshing/examples/Tetrahedral_remeshing/tetrahedral_remeshing_with_features.cpp @@ -3,16 +3,14 @@ #include #include -#include #include #include #include -#include #include -#include +#include "tetrahedral_remeshing_generate_input.h" typedef CGAL::Exact_predicates_inexact_constructions_kernel K; @@ -62,69 +60,6 @@ public: } }; -void add_edge(Vertex_handle v1, - Vertex_handle v2, - const Remeshing_triangulation& tr, - boost::unordered_set >& constraints) -{ - Cell_handle c; - int i, j; - if(tr.is_edge(v1, v2, c, i, j)) - constraints.insert(std::make_pair(v1, v2)); -} - -void make_constraints_from_cube_edges( - Remeshing_triangulation& tr, - boost::unordered_set >& constraints) -{ - const Point p0(-2., -2., -2.); - const Point p1(-2., -2., -2.); - const Point p2( 2., -2., -2.); - const Point p3( 2., -2., 2.); - const Point p4(-2., 2., -2.); - const Point p5(-2., 2., 2.); - const Point p6( 2., 2., -2.); - const Point p7( 2., 2., 2.); - - Remeshing_triangulation::Locate_type lt; - int li, lj; - Cell_handle c = tr.locate(p0, lt, li, lj); - Vertex_handle v0 = c->vertex(li); - c = tr.locate(p1, lt, li, lj); - Vertex_handle v1 = c->vertex(li); - - c = tr.locate(p2, lt, li, lj); - Vertex_handle v2 = c->vertex(li); - c = tr.locate(p3, lt, li, lj); - Vertex_handle v3 = c->vertex(li); - - c = tr.locate(p4, lt, li, lj); - Vertex_handle v4 = c->vertex(li); - c = tr.locate(p5, lt, li, lj); - Vertex_handle v5 = c->vertex(li); - - c = tr.locate(p6, lt, li, lj); - Vertex_handle v6 = c->vertex(li); - c = tr.locate(p7, lt, li, lj); - Vertex_handle v7 = c->vertex(li); - - // constrain cube edges - add_edge(v0, v1, tr, constraints); - add_edge(v1, v2, tr, constraints); - add_edge(v2, v3, tr, constraints); - add_edge(v3, v0, tr, constraints); - - add_edge(v4, v5, tr, constraints); - add_edge(v5, v6, tr, constraints); - add_edge(v6, v7, tr, constraints); - add_edge(v7, v4, tr, constraints); - - add_edge(v0, v4, tr, constraints); - add_edge(v1, v5, tr, constraints); - add_edge(v2, v6, tr, constraints); - add_edge(v3, v7, tr, constraints); -} - void set_subdomain(Remeshing_triangulation& tr, const int index) { for (Remeshing_triangulation::Finite_cells_iterator cit = tr.finite_cells_begin(); @@ -136,21 +71,15 @@ void set_subdomain(Remeshing_triangulation& tr, const int index) int main(int argc, char* argv[]) { - const char* filename = "data/sphere_in_cube.tr.cgal"; const double target_edge_length = (argc > 1) ? atof(argv[1]) : 0.02; const int nb_iter = (argc > 2) ? atoi(argv[2]) : 1; - - std::ifstream input(filename, std::ios_base::in | std::ios_base::binary); - if (!input) - { - std::cerr << "File " << filename << " could not be found" << std::endl; - return EXIT_FAILURE; - } + const int nbv = (argc > 3) ? atoi(argv[3]) : 500; Remeshing_triangulation t3; - CGAL::load_triangulation(input, t3); - boost::unordered_set > constraints; + + CGAL::Tetrahedral_remeshing::generate_input_cube(nbv, t3, constraints); + make_constraints_from_cube_edges(t3, constraints); CGAL_assertion(t3.is_valid()); @@ -160,9 +89,6 @@ int main(int argc, char* argv[]) Constrained_edges_property_map(&constraints)) .number_of_iterations(nb_iter)); - std::ofstream out("tet_remeshing_with_features_after.mesh", std::ios_base::out); - CGAL::save_ascii_triangulation(out, t3); - return EXIT_SUCCESS; } From e8b3abdc51d73a7d5102e99a986564450a7f0ec2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9bastien=20Loriot?= Date: Wed, 27 May 2020 18:54:19 +0200 Subject: [PATCH 462/568] mimic Mesh_triangulation_3 --- .../Remeshing_triangulation_3.h | 17 ++++++----------- 1 file changed, 6 insertions(+), 11 deletions(-) diff --git a/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/Remeshing_triangulation_3.h b/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/Remeshing_triangulation_3.h index 635b4e2d5c4..80701a04648 100644 --- a/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/Remeshing_triangulation_3.h +++ b/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/Remeshing_triangulation_3.h @@ -48,19 +48,14 @@ triangulation data structure. Possible values are `Sequential_tag` (the default), `Parallel_tag`, and `Parallel_if_available_tag`. -\tparam Vb is a vertex base class from which `Remeshing_vertex_base_3` derives. -It must be a model of the `TriangulationVertexBase_3` concept. -It has the default value `Triangulation_vertex_base_3`. - -\tparam Cb is a cell base class from which `Remeshing_cell_base_3` derives. -It must be a model of the `TriangulationCellBase_3` concept. -It has the default value `Triangulation_cell_base_3`. +\tparam Vb is a model of `RemeshingVertexBase_3`. It has the default value ` Remeshing_vertex_base_3`. +\tparam Cb is a model of `RemeshingCellBase_3`. It has the default value ` Remeshing_cell_base_3`. */ template, - typename Cb = CGAL::Triangulation_cell_base_3 + typename Vb = Remeshing_vertex_base_3, + typename Cb = Remeshing_cell_base_3 > class Remeshing_triangulation_3 : public CGAL::Triangulation_3 { public: - typedef Remeshing_vertex_base_3 Remeshing_Vb; - typedef Remeshing_cell_base_3 Remeshing_Cb; + typedef Vb Remeshing_Vb; + typedef Cb Remeshing_Cb; typedef CGAL::Triangulation_data_structure_3< Remeshing_Vb, Remeshing_Cb, Concurrency_tag> Tds; From 25b0dc510827bd03ba96d61f671f129bda875a5e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9bastien=20Loriot?= Date: Wed, 27 May 2020 19:04:46 +0200 Subject: [PATCH 463/568] fix compilation issues --- .../tetrahedral_remeshing_generate_input.h | 6 +++--- .../CGAL/Tetrahedral_remeshing/Remeshing_triangulation_3.h | 7 +------ 2 files changed, 4 insertions(+), 9 deletions(-) diff --git a/Tetrahedral_remeshing/examples/Tetrahedral_remeshing/tetrahedral_remeshing_generate_input.h b/Tetrahedral_remeshing/examples/Tetrahedral_remeshing/tetrahedral_remeshing_generate_input.h index 041e127b053..7f020ae5c6a 100644 --- a/Tetrahedral_remeshing/examples/Tetrahedral_remeshing/tetrahedral_remeshing_generate_input.h +++ b/Tetrahedral_remeshing/examples/Tetrahedral_remeshing/tetrahedral_remeshing_generate_input.h @@ -24,13 +24,13 @@ namespace Tetrahedral_remeshing { CGAL::Random rng; - typedef Tr::Point Point; - typedef Tr::Cell_handle Cell_handle; + typedef typename Tr::Point Point; + typedef typename Tr::Cell_handle Cell_handle; while (tr.number_of_vertices() < nbv) tr.insert(Point(rng.get_double(-1., 1.), rng.get_double(-1., 1.), rng.get_double(-1., 1.))); - const Tr::Geom_traits::Plane_3 + const typename Tr::Geom_traits::Plane_3 plane(Point(0, 0, 0), Point(0, 1, 0), Point(0, 0, 1)); for (Cell_handle c : tr.finite_cell_handles()) diff --git a/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/Remeshing_triangulation_3.h b/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/Remeshing_triangulation_3.h index 80701a04648..1a25ab1aace 100644 --- a/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/Remeshing_triangulation_3.h +++ b/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/Remeshing_triangulation_3.h @@ -58,12 +58,7 @@ template > class Remeshing_triangulation_3 - : public CGAL::Triangulation_3, - Remeshing_cell_base_3 - > - > + : public CGAL::Triangulation_3 > { public: typedef Vb Remeshing_Vb; From 802eb6add5bd6a26dc84f1a081910da774d9c6dc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9bastien=20Loriot?= Date: Thu, 28 May 2020 08:01:01 +0200 Subject: [PATCH 464/568] add missing empty line --- Tetrahedral_remeshing/include/CGAL/tetrahedral_remeshing.h | 1 + 1 file changed, 1 insertion(+) diff --git a/Tetrahedral_remeshing/include/CGAL/tetrahedral_remeshing.h b/Tetrahedral_remeshing/include/CGAL/tetrahedral_remeshing.h index cb27ec3b81f..7877002a0d5 100644 --- a/Tetrahedral_remeshing/include/CGAL/tetrahedral_remeshing.h +++ b/Tetrahedral_remeshing/include/CGAL/tetrahedral_remeshing.h @@ -83,6 +83,7 @@ namespace CGAL * mesh density target for the remeshing algorithm. * @param np optional sequence of \ref Remeshing_namedparameters "Named Parameters" * among the ones listed below +* * \cgalNamedParamsBegin * \cgalParamBegin{number_of_iterations} the number of iterations for the full * sequence of atomic operations From a8301c0d9cba9bff8040cde59637c991e901e5d7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9bastien=20Loriot?= Date: Thu, 28 May 2020 08:10:00 +0200 Subject: [PATCH 465/568] add missing _ --- Triangulation_2/doc/Triangulation_2/Triangulation_2.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Triangulation_2/doc/Triangulation_2/Triangulation_2.txt b/Triangulation_2/doc/Triangulation_2/Triangulation_2.txt index e2a4661cf63..7e63547e242 100644 --- a/Triangulation_2/doc/Triangulation_2/Triangulation_2.txt +++ b/Triangulation_2/doc/Triangulation_2/Triangulation_2.txt @@ -174,7 +174,7 @@ A zero dimensional triangulation, whose domain is reduced to a single point, is represented by two vertices that is topologically equivalent to a \f$ 0\f$-sphere. -\cgalFigureBegin{Triangulation_2D_Fig_low_dimensional,lowdimensional.svg} +\cgalFigureBegin{Triangulation_2D_Fig_low_dimensional,low_dimensional.svg} Triangulations with zero, one, and two finite vertices. \cgalFigureEnd From b2fe891802cd1f635b4ea20a5fc5f534bfb3fa8a Mon Sep 17 00:00:00 2001 From: Simon Giraudot Date: Thu, 28 May 2020 08:59:18 +0200 Subject: [PATCH 466/568] Fix cmake --- Installation/lib/cmake/CGAL/CGALConfig.cmake | 10 ---------- .../examples/Point_set_processing_3/CMakeLists.txt | 1 - 2 files changed, 11 deletions(-) diff --git a/Installation/lib/cmake/CGAL/CGALConfig.cmake b/Installation/lib/cmake/CGAL/CGALConfig.cmake index de6a495a1bc..11ff7810d31 100644 --- a/Installation/lib/cmake/CGAL/CGALConfig.cmake +++ b/Installation/lib/cmake/CGAL/CGALConfig.cmake @@ -159,17 +159,7 @@ endforeach() cgal_setup_module_path() set(CGAL_USE_FILE ${CGAL_MODULES_DIR}/UseCGAL.cmake) -include(${CGAL_MODULES_DIR}/CGAL_target_use_Boost_IOStreams.cmake) -include(${CGAL_MODULES_DIR}/CGAL_target_use_Boost_Serialization.cmake) -include(${CGAL_MODULES_DIR}/CGAL_target_use_Eigen.cmake) -include(${CGAL_MODULES_DIR}/CGAL_target_use_GLPK.cmake) -include(${CGAL_MODULES_DIR}/CGAL_target_use_LASLIB.cmake) -include(${CGAL_MODULES_DIR}/CGAL_target_use_OpenCV.cmake) -include(${CGAL_MODULES_DIR}/CGAL_target_use_OpenGR.cmake) -include(${CGAL_MODULES_DIR}/CGAL_target_use_SCIP.cmake) include(${CGAL_MODULES_DIR}/CGAL_target_use_TBB.cmake) -include(${CGAL_MODULES_DIR}/CGAL_target_use_TensorFlow.cmake) -include(${CGAL_MODULES_DIR}/CGAL_target_use_pointmatcher.cmake) include("${CGAL_MODULES_DIR}/CGAL_parse_version_h.cmake") cgal_parse_version_h( "${CGAL_INSTALLATION_PACKAGE_DIR}/include/CGAL/version.h" diff --git a/Point_set_processing_3/examples/Point_set_processing_3/CMakeLists.txt b/Point_set_processing_3/examples/Point_set_processing_3/CMakeLists.txt index f362e4d9e35..83253368016 100644 --- a/Point_set_processing_3/examples/Point_set_processing_3/CMakeLists.txt +++ b/Point_set_processing_3/examples/Point_set_processing_3/CMakeLists.txt @@ -78,7 +78,6 @@ if ( CGAL_FOUND ) foreach(target jet_smoothing_example normal_estimation - edges_example clustering_example edges_example callback_example From 3c85811101cdc415d333cd5d419f23ca8789ad0c Mon Sep 17 00:00:00 2001 From: Andreas Fabri Date: Thu, 28 May 2020 07:59:51 +0100 Subject: [PATCH 467/568] Refer to the example --- Triangulation_2/doc/Triangulation_2/Triangulation_2.txt | 3 +++ 1 file changed, 3 insertions(+) diff --git a/Triangulation_2/doc/Triangulation_2/Triangulation_2.txt b/Triangulation_2/doc/Triangulation_2/Triangulation_2.txt index 7e63547e242..009f3845620 100644 --- a/Triangulation_2/doc/Triangulation_2/Triangulation_2.txt +++ b/Triangulation_2/doc/Triangulation_2/Triangulation_2.txt @@ -173,6 +173,9 @@ topologically equivalent to a \f$ 1\f$-sphere. A zero dimensional triangulation, whose domain is reduced to a single point, is represented by two vertices that is topologically equivalent to a \f$ 0\f$-sphere. +This is illustrated in \cgalFigureRef{Triangulation_2D_Fig_low_dimensional} +and the example \ref Triangulation_2/low_dimensional.cpp +shows how to traverse a low dimensional triangulation. \cgalFigureBegin{Triangulation_2D_Fig_low_dimensional,low_dimensional.svg} Triangulations with zero, one, and two finite vertices. From f4fec8c0c152db4103f1510adcbabe2830c14668 Mon Sep 17 00:00:00 2001 From: Laurent Rineau Date: Thu, 28 May 2020 11:06:30 +0200 Subject: [PATCH 468/568] Fix C++20 errors (patch suggested by Marc Glisse) See https://github.com/CGAL/cgal/pull/4640#issuecomment-635200332 --- .../Surface_mesh_shortest_path/Surface_mesh_shortest_path.h | 4 ++-- Surface_sweep_2/include/CGAL/Surface_sweep_2/Curve_pair.h | 6 +++--- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/Surface_mesh_shortest_path/include/CGAL/Surface_mesh_shortest_path/Surface_mesh_shortest_path.h b/Surface_mesh_shortest_path/include/CGAL/Surface_mesh_shortest_path/Surface_mesh_shortest_path.h index 86316179c41..6d24ecfcab3 100644 --- a/Surface_mesh_shortest_path/include/CGAL/Surface_mesh_shortest_path/Surface_mesh_shortest_path.h +++ b/Surface_mesh_shortest_path/include/CGAL/Surface_mesh_shortest_path/Surface_mesh_shortest_path.h @@ -257,12 +257,12 @@ public: return temp; } - bool operator==(const Source_point_iterator& other) + bool operator==(const Source_point_iterator& other) const { return m_iterator == other.m_iterator; } - bool operator!=(const Source_point_iterator& other) + bool operator!=(const Source_point_iterator& other) const { return m_iterator != other.m_iterator; } diff --git a/Surface_sweep_2/include/CGAL/Surface_sweep_2/Curve_pair.h b/Surface_sweep_2/include/CGAL/Surface_sweep_2/Curve_pair.h index 6f6ce6dfd0a..1a50dfdcecb 100644 --- a/Surface_sweep_2/include/CGAL/Surface_sweep_2/Curve_pair.h +++ b/Surface_sweep_2/include/CGAL/Surface_sweep_2/Curve_pair.h @@ -157,19 +157,19 @@ public: return (temp); } - bool operator==(const Self& other) + bool operator==(const Self& other) const { CGAL_precondition(m_container == other.m_container); return (m_index == other.m_index); } - bool operator!=(const Self& other) + bool operator!=(const Self& other) const { CGAL_precondition(m_container == other.m_container); return !(*this == other); } - unsigned int operator-(const Self& other) + unsigned int operator-(const Self& other) const { CGAL_precondition(m_container == other.m_container); return (m_index - other.m_index); From dc4427c99824466fcf1da37d267be396e5a59781 Mon Sep 17 00:00:00 2001 From: Laurent Rineau Date: Thu, 28 May 2020 12:44:25 +0200 Subject: [PATCH 469/568] Move the code in CGAL_SetupCGALDependencies.cmake --- .../modules/CGAL_GeneratorSpecificSettings.cmake | 11 ----------- .../cmake/modules/CGAL_SetupCGALDependencies.cmake | 10 ++++++++-- 2 files changed, 8 insertions(+), 13 deletions(-) diff --git a/Installation/cmake/modules/CGAL_GeneratorSpecificSettings.cmake b/Installation/cmake/modules/CGAL_GeneratorSpecificSettings.cmake index 5cf46f1adda..366378ea74e 100644 --- a/Installation/cmake/modules/CGAL_GeneratorSpecificSettings.cmake +++ b/Installation/cmake/modules/CGAL_GeneratorSpecificSettings.cmake @@ -1,5 +1,3 @@ -include(${CMAKE_CURRENT_LIST_DIR}/CGAL_Macros.cmake) - if ( NOT CGAL_GENERATOR_SPECIFIC_SETTINGS_FILE_INCLUDED ) set( CGAL_GENERATOR_SPECIFIC_SETTINGS_FILE_INCLUDED 1 ) @@ -48,15 +46,6 @@ if ( NOT CGAL_GENERATOR_SPECIFIC_SETTINGS_FILE_INCLUDED ) message(STATUS "Mac Leopard detected") set(CGAL_APPLE_LEOPARD 1) endif() - - # This fixes the issue #3816 - https://github.com/CGAL/cgal/issues/3816. - if ("${CMAKE_CXX_COMPILER_ID}" MATCHES "AppleClang") - message(STATUS "Apple Clang version ${CMAKE_CXX_COMPILER_VERSION} compiler detected") - if (CMAKE_CXX_COMPILER_VERSION VERSION_LESS 11.0.3) - message(STATUS "Boost MP is turned off for all Apple Clang versions below 11.0.3!") - uniquely_add_flags(CMAKE_CXX_FLAGS "-DCGAL_DO_NOT_USE_BOOST_MP") - endif() - endif() endif() if ( NOT "${CMAKE_CFG_INTDIR}" STREQUAL "." ) diff --git a/Installation/cmake/modules/CGAL_SetupCGALDependencies.cmake b/Installation/cmake/modules/CGAL_SetupCGALDependencies.cmake index ddfd3299009..16efcefef8f 100644 --- a/Installation/cmake/modules/CGAL_SetupCGALDependencies.cmake +++ b/Installation/cmake/modules/CGAL_SetupCGALDependencies.cmake @@ -85,7 +85,7 @@ function(CGAL_setup_CGAL_dependencies target) set(keyword PUBLIC) endif() if(CGAL_DISABLE_GMP) - target_compile_definitions(${target} ${keyword} CGAL_DISABLE_GMP=1) + target_compile_definitions(${target} ${keyword} CGAL_DISABLE_GMP=1) else() use_CGAL_GMP_support(${target} ${keyword}) set(CGAL_USE_GMP TRUE CACHE INTERNAL "CGAL library is configured to use GMP") @@ -95,7 +95,7 @@ function(CGAL_setup_CGAL_dependencies target) if(WITH_LEDA) use_CGAL_LEDA_support(${target} ${keyword}) endif() - + if (CGAL_HEADER_ONLY) target_compile_definitions(${target} ${keyword} CGAL_HEADER_ONLY=1) endif() @@ -121,6 +121,12 @@ function(CGAL_setup_CGAL_dependencies target) "/wd4503" # Suppress warnings C4503 about "decorated name length exceeded" "/bigobj" # Use /bigobj by default ) + elseif ("${CMAKE_CXX_COMPILER_ID}" MATCHES "AppleClang") + if (CMAKE_CXX_COMPILER_VERSION VERSION_LESS 11.0.3) + message(STATUS "Apple Clang version ${CMAKE_CXX_COMPILER_VERSION} compiler detected") + message(STATUS "Boost MP is turned off for all Apple Clang versions below 11.0.3!") + target_compile_options(${target} ${keyword} "-DCGAL_DO_NOT_USE_BOOST_MP") + endif() elseif(CMAKE_CXX_COMPILER_ID MATCHES "Intel") message( STATUS "Using Intel Compiler. Adding -fp-model strict" ) if(WIN32) From 75f3a677905a0fd6ce61209cec41d2da1db0fe33 Mon Sep 17 00:00:00 2001 From: Maxime Gimeno Date: Fri, 29 May 2020 15:21:45 +0200 Subject: [PATCH 470/568] Replace parallel_for by parallel_reduce in haudorff --- .../CGAL/Polygon_mesh_processing/distance.h | 38 ++++++++++--------- 1 file changed, 20 insertions(+), 18 deletions(-) diff --git a/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/distance.h b/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/distance.h index 0f8aeb511a0..de1b924c658 100644 --- a/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/distance.h +++ b/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/distance.h @@ -29,7 +29,7 @@ #include #ifdef CGAL_LINKED_WITH_TBB -#include +#include "tbb/parallel_reduce.h" #include #include #endif // CGAL_LINKED_WITH_TBB @@ -81,21 +81,27 @@ struct Distance_computation{ const AABB_tree& tree; const PointRange& sample_points; Point_3 initial_hint; - std::atomic* distance; - + double distance; + //constro Distance_computation( const AABB_tree& tree, const Point_3& p, - const PointRange& sample_points, - std::atomic* d) + const PointRange& sample_points) : tree(tree) , sample_points(sample_points) , initial_hint(p) - , distance(d) + , distance(-1) + {} + //split constro + Distance_computation(Distance_computation& s, tbb::split ) + : tree(s.tree) + , sample_points(s.sample_points) + , initial_hint(s.initial_hint) + , distance(-1) {} void - operator()(const tbb::blocked_range& range) const + operator()(const tbb::blocked_range& range) { Point_3 hint = initial_hint; double hdist = 0; @@ -107,15 +113,11 @@ struct Distance_computation{ if(d > hdist) hdist=d; } - - // update max value stored in distance - double current_value = *distance; - while( current_value < hdist ) - { - if(distance->compare_exchange_weak(current_value, hdist)) - current_value = hdist; - } + if(hdist > distance) + distance = hdist; } + + void join( Distance_computation& rhs ) {distance = std::max(rhs.distance, distance); } }; #endif @@ -136,9 +138,9 @@ double approximate_Hausdorff_distance_impl( { std::atomic distance; distance=0; - Distance_computation f(tree, hint, sample_points, &distance); - tbb::parallel_for(tbb::blocked_range(0, sample_points.size()), f); - return distance; + Distance_computation f(tree, hint, sample_points); + tbb::parallel_reduce(tbb::blocked_range(0, sample_points.size()), f); + return f.distance; } else #endif From 7915057945a48b900286ec1c642526b7cdea1f6b Mon Sep 17 00:00:00 2001 From: Maxime Gimeno Date: Fri, 29 May 2020 16:35:21 +0200 Subject: [PATCH 471/568] add missing includes --- Classification/test/Classification/CMakeLists.txt | 1 + Spatial_searching/examples/Spatial_searching/CMakeLists.txt | 5 +++-- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/Classification/test/Classification/CMakeLists.txt b/Classification/test/Classification/CMakeLists.txt index a93e0277355..e9ad1a332dc 100644 --- a/Classification/test/Classification/CMakeLists.txt +++ b/Classification/test/Classification/CMakeLists.txt @@ -44,6 +44,7 @@ if (NOT TARGET CGAL::Eigen_support) endif() find_package(TBB QUIET) +include(CGAL_TBB_support) if (NOT Classification_dependencies_met) return() diff --git a/Spatial_searching/examples/Spatial_searching/CMakeLists.txt b/Spatial_searching/examples/Spatial_searching/CMakeLists.txt index 731eab89761..6ea87500e55 100644 --- a/Spatial_searching/examples/Spatial_searching/CMakeLists.txt +++ b/Spatial_searching/examples/Spatial_searching/CMakeLists.txt @@ -79,9 +79,10 @@ else() endif() find_package( TBB QUIET ) -if(TBB_FOUND) +include(CGAL_TBB_support) +if(TARGET CGAL::TBB_support) create_single_source_cgal_program( "parallel_kdtree.cpp" ) - cgal_target_use_TBB(parallel_kdtree) + target_link_libraries(parallel_kdtree PUBLIC CGAL::TBB_support) else() message(STATUS "parallel_kdtree.cpp requires TBB and will not be compiled") endif() From d259d56712e7a6a66af4b0a3db50e46a56833381 Mon Sep 17 00:00:00 2001 From: Andreas Fabri Date: Sun, 31 May 2020 17:59:18 +0200 Subject: [PATCH 472/568] Update PackageDescription.txt No need to say that this is CGAL. And if we really want to keep it we have to use the macro or put a % before to avoid the link being generated. --- Shape_detection/doc/Shape_detection/PackageDescription.txt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Shape_detection/doc/Shape_detection/PackageDescription.txt b/Shape_detection/doc/Shape_detection/PackageDescription.txt index 5ace984878d..52001fe612e 100644 --- a/Shape_detection/doc/Shape_detection/PackageDescription.txt +++ b/Shape_detection/doc/Shape_detection/PackageDescription.txt @@ -59,12 +59,12 @@ Deprecated components. \cgalPkgSummaryBegin \cgalPkgAuthors{Sven Oesau, Yannick Verdie, Clément Jamin, Pierre Alliez, Florent Lafarge, Simon Giraudot, Thien Hoang, and Dmitry Anisimov} -\cgalPkgDesc{This CGAL package implements the Efficient RANSAC (RANdom SAmple Consensus) approach +\cgalPkgDesc{This package implements the Efficient RANSAC (RANdom SAmple Consensus) approach for detecting arbitrary shapes in an unorganized point set with unoriented normals and the Region Growing approach for detecting shapes in a set of arbitrary items. With the Efficient RANSAC approach, five canonical shapes can be detected: planes, spheres, cylinders, cones, and tori. Additional shapes can be detected, given a custom shape class by the user. -For the Region Growing approach, CGAL provides three particular shape detection components: +For the Region Growing approach, this package provides three particular shape detection components: detecting lines in a 2D point set, detecting planes in a 3D point set, and detecting planes on a polygon mesh.} \cgalPkgManuals{Chapter_Shape_Detection, PkgShapeDetectionRef} From 4af1e73f69d50ad5847b0af92341d2d8037ff953 Mon Sep 17 00:00:00 2001 From: Maxime Gimeno Date: Tue, 2 Jun 2020 10:11:28 +0200 Subject: [PATCH 473/568] Work around for moc bug --- Installation/include/CGAL/config.h | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/Installation/include/CGAL/config.h b/Installation/include/CGAL/config.h index d70989b2ffb..98b2a2f5c6c 100644 --- a/Installation/include/CGAL/config.h +++ b/Installation/include/CGAL/config.h @@ -101,6 +101,10 @@ // fails as well # define BOOST_TT_HAS_POST_DECREMENT_HPP_INCLUDED # define BOOST_TT_HAS_POST_INCREMENT_HPP_INCLUDED +//work around for moc bug : https://bugreports.qt.io/browse/QTBUG-80990 +#if defined(CGAL_LINKED_WITH_TBB) +#undef CGAL_LINKED_WITH_TBB +#endif #endif // Macro used by Boost Parameter. Mesh_3 needs at least 12, before the From 520fbf7c4b7886b822b8ae0a133aca05d8ce5939 Mon Sep 17 00:00:00 2001 From: Maxime Gimeno Date: Tue, 2 Jun 2020 10:38:56 +0200 Subject: [PATCH 474/568] Add missing include --- Polyhedron/demo/Polyhedron/Plugins/PMP/Distance_plugin.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/Polyhedron/demo/Polyhedron/Plugins/PMP/Distance_plugin.cpp b/Polyhedron/demo/Polyhedron/Plugins/PMP/Distance_plugin.cpp index 587e34051c9..031ac458e76 100644 --- a/Polyhedron/demo/Polyhedron/Plugins/PMP/Distance_plugin.cpp +++ b/Polyhedron/demo/Polyhedron/Plugins/PMP/Distance_plugin.cpp @@ -34,6 +34,7 @@ typedef Scene_surface_mesh_item Scene_face_graph_item; typedef Scene_face_graph_item::Face_graph Face_graph; #if defined(CGAL_LINKED_WITH_TBB) +#include template struct Distance_computation{ const AABB_tree& tree; From a443ad51ccf3a06a6b0f7d2c3d75c7d6012e4de7 Mon Sep 17 00:00:00 2001 From: Laurent Rineau Date: Tue, 2 Jun 2020 10:47:00 +0200 Subject: [PATCH 475/568] Hack to add a warning for the documentation of master --- Documentation/doc/resources/1.8.13/menu_version.js | 9 +++++++++ Documentation/doc/resources/1.8.14/menu_version.js | 9 +++++++++ Documentation/doc/resources/1.8.4/menu_version.js | 9 +++++++++ 3 files changed, 27 insertions(+) diff --git a/Documentation/doc/resources/1.8.13/menu_version.js b/Documentation/doc/resources/1.8.13/menu_version.js index 36b298ee045..64781b67e1d 100644 --- a/Documentation/doc/resources/1.8.13/menu_version.js +++ b/Documentation/doc/resources/1.8.13/menu_version.js @@ -23,6 +23,15 @@ ]; function build_select(current_version) { + if( current_version == 'master') { + let top_elt = document.getElementById("top"); + + let first_element = top_elt.childNodes[0]; + let new_div = document.createElement("p"); + new_div.innerHTML = '⚠️ This documentation corresponds to the master branch of CGAL, that is not yet released.'; + new_div.style.cssText = "background-color: #ff9800; margin: 1ex auto 1ex 1em; padding: 1ex; border-radius: 1ex; width: max-content;" + let OK = top_elt.insertBefore(new_div, first_element); + } var buf = ['']; $.each(all_versions, function(id) { var version = all_versions[id]; diff --git a/Documentation/doc/resources/1.8.4/menu_version.js b/Documentation/doc/resources/1.8.4/menu_version.js index 36b298ee045..64781b67e1d 100644 --- a/Documentation/doc/resources/1.8.4/menu_version.js +++ b/Documentation/doc/resources/1.8.4/menu_version.js @@ -23,6 +23,15 @@ ]; function build_select(current_version) { + if( current_version == 'master') { + let top_elt = document.getElementById("top"); + + let first_element = top_elt.childNodes[0]; + let new_div = document.createElement("p"); + new_div.innerHTML = '⚠️ This documentation corresponds to the master branch of CGAL, that is not yet released.'; + new_div.style.cssText = "background-color: #ff9800; margin: 1ex auto 1ex 1em; padding: 1ex; border-radius: 1ex; width: max-content;" + let OK = top_elt.insertBefore(new_div, first_element); + } var buf = ['']; diff --git a/Documentation/doc/resources/1.8.14/menu_version.js b/Documentation/doc/resources/1.8.14/menu_version.js index 4ccccdef247..0626471f903 100644 --- a/Documentation/doc/resources/1.8.14/menu_version.js +++ b/Documentation/doc/resources/1.8.14/menu_version.js @@ -28,8 +28,8 @@ let first_element = top_elt.childNodes[0]; let new_div = document.createElement("p"); - new_div.innerHTML = '⚠️ This documentation corresponds to the master branch of CGAL, that is not yet released.'; - new_div.style.cssText = "background-color: #ff9800; margin: 1ex auto 1ex 1em; padding: 1ex; border-radius: 1ex; width: max-content;" + new_div.innerHTML = '⚠️ This documentation corresponds to the master development branch of CGAL. It might diverge from the official releases.'; + new_div.style.cssText = "background-color: #ff9800; margin: 1ex auto 1ex 1em; padding: 1ex; border-radius: 1ex; display: inline-block;" let OK = top_elt.insertBefore(new_div, first_element); } var buf = ['']; From 3356d066cc851120c72cb195709bf1f4887d1727 Mon Sep 17 00:00:00 2001 From: Maxime Gimeno Date: Tue, 2 Jun 2020 15:31:55 +0200 Subject: [PATCH 478/568] fix boost zlib targets --- Installation/cmake/modules/CGAL_Boost_iostreams_support.cmake | 4 ++-- .../cmake/modules/CGAL_Boost_serialization_support.cmake | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/Installation/cmake/modules/CGAL_Boost_iostreams_support.cmake b/Installation/cmake/modules/CGAL_Boost_iostreams_support.cmake index 6a9680b5f0f..04c8cc5529b 100644 --- a/Installation/cmake/modules/CGAL_Boost_iostreams_support.cmake +++ b/Installation/cmake/modules/CGAL_Boost_iostreams_support.cmake @@ -35,10 +35,10 @@ if(Boost_IOSTREAMS_FOUND AND NOT TARGET CGAL::Boost_iostreams_support) if(CMAKE_VERSION VERSION_LESS 3.11) set_target_properties(CGAL::Boost_iostreams_support PROPERTIES INTERFACE_COMPILE_DEFINITIONS "CGAL_LINKED_WITH_BOOST_IOSTREAMS" - INTERFACE_LINK_LIBRARIES "${Boost_LIB};${ZLIB_LIBS}") + INTERFACE_LINK_LIBRARIES ${Boost_LIB} ${ZLIB_LIBS}) else() set_target_properties(CGAL::Boost_iostreams_support PROPERTIES INTERFACE_COMPILE_DEFINITIONS "CGAL_LINKED_WITH_BOOST_IOSTREAMS") - target_link_libraries(CGAL::Boost_iostreams_support INTERFACE "${Boost_LIB};${ZLIB_LIBS}") + target_link_libraries(CGAL::Boost_iostreams_support INTERFACE ${Boost_LIB} ${ZLIB_LIBS}) endif() endif() diff --git a/Installation/cmake/modules/CGAL_Boost_serialization_support.cmake b/Installation/cmake/modules/CGAL_Boost_serialization_support.cmake index 236fbb4bf0c..84a5ae6657b 100644 --- a/Installation/cmake/modules/CGAL_Boost_serialization_support.cmake +++ b/Installation/cmake/modules/CGAL_Boost_serialization_support.cmake @@ -8,5 +8,5 @@ if(Boost_SERIALIZATION_FOUND AND NOT TARGET CGAL::Boost_serialization_support) add_library(CGAL::Boost_serialization_support INTERFACE IMPORTED) set_target_properties(CGAL::Boost_serialization_support PROPERTIES INTERFACE_COMPILE_DEFINITIONS "CGAL_LINKED_WITH_BOOST_SERIALIZATION" - INTERFACE_LINK_LIBRARIES "${Boost_LIB}") + INTERFACE_LINK_LIBRARIES ${Boost_LIB}) endif() From 83ed34b6f2b121abf345380590e2c2cc43359964 Mon Sep 17 00:00:00 2001 From: Maxime Gimeno Date: Tue, 2 Jun 2020 16:04:53 +0200 Subject: [PATCH 479/568] reduce limit for triggering offset --- Polyhedron/demo/Polyhedron/MainWindow.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Polyhedron/demo/Polyhedron/MainWindow.cpp b/Polyhedron/demo/Polyhedron/MainWindow.cpp index ee2274122fe..3951ba10c1c 100644 --- a/Polyhedron/demo/Polyhedron/MainWindow.cpp +++ b/Polyhedron/demo/Polyhedron/MainWindow.cpp @@ -1027,7 +1027,7 @@ void MainWindow::computeViewerBBox(CGAL::qglviewer::Vec& vmin, CGAL::qglviewer:: double l_dist = (std::max)((std::abs)(bbox_center.x - viewer->offset().x), (std::max)((std::abs)(bbox_center.y - viewer->offset().y), (std::abs)(bbox_center.z - viewer->offset().z))); - if((std::log2)(l_dist/bbox_diag) > 13.0 ) + if((std::log2)(l_dist/bbox_diag) > 11.0 ) for(int i=0; i<3; ++i) { offset[i] = -bbox_center[i]; From dac2ad159e4924a281225f05e8ef215072ec5fcf Mon Sep 17 00:00:00 2001 From: Maxime Gimeno Date: Tue, 2 Jun 2020 16:08:30 +0200 Subject: [PATCH 480/568] Fix path in partition --- .../Plugins/Operations_on_polyhedra/PartitionDialog.ui | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Polyhedron/demo/Polyhedron/Plugins/Operations_on_polyhedra/PartitionDialog.ui b/Polyhedron/demo/Polyhedron/Plugins/Operations_on_polyhedra/PartitionDialog.ui index 1c939c87a9c..91f3b989f8a 100644 --- a/Polyhedron/demo/Polyhedron/Plugins/Operations_on_polyhedra/PartitionDialog.ui +++ b/Polyhedron/demo/Polyhedron/Plugins/Operations_on_polyhedra/PartitionDialog.ui @@ -67,7 +67,7 @@ p, li { white-space: pre-wrap; } </style></head><body style=" font-family:'Sans Serif'; font-size:9pt; font-weight:400; font-style:normal;"> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Tip: To split your mesh according to the result of this operation, you can click on </p> -<p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600;">Operations-&gt;Operations on Polyhedra-&gt;Split Selected Polyhedra</span></p></body></html> +<p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600;">Operations-&gt;Polygon Mesh Processing-&gt;Split Selected Polyhedra</span></p></body></html> From 8adf6511ffbc6e4c85d3399bb74648636dd0c39a Mon Sep 17 00:00:00 2001 From: Maxime Gimeno Date: Wed, 3 Jun 2020 09:31:46 +0200 Subject: [PATCH 481/568] Fix Polygon soup description --- Polyhedron/demo/Polyhedron/Scene_polygon_soup_item.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Polyhedron/demo/Polyhedron/Scene_polygon_soup_item.cpp b/Polyhedron/demo/Polyhedron/Scene_polygon_soup_item.cpp index dfe4f2898f5..e4d61b95ef9 100644 --- a/Polyhedron/demo/Polyhedron/Scene_polygon_soup_item.cpp +++ b/Polyhedron/demo/Polyhedron/Scene_polygon_soup_item.cpp @@ -512,7 +512,7 @@ Scene_polygon_soup_item::toolTip() const return QString(); QString str = QObject::tr("

%1 (mode: %5, color: %6)
" - "Polygons soup

" + "Polygon soup

" "

Number of vertices: %2
" "Number of polygons: %3

") .arg(this->name()) From ee4f996043e752ef00c64a369929a1c5a93e0680 Mon Sep 17 00:00:00 2001 From: Maxime Gimeno Date: Wed, 3 Jun 2020 11:24:18 +0200 Subject: [PATCH 482/568] Add a clone to the c3t3 and fix an error in the cutting plane orientation --- Polyhedron/demo/Polyhedron/Scene_c3t3_item.cpp | 12 ++++++++++-- Polyhedron/demo/Polyhedron/Scene_c3t3_item.h | 5 ++--- 2 files changed, 12 insertions(+), 5 deletions(-) diff --git a/Polyhedron/demo/Polyhedron/Scene_c3t3_item.cpp b/Polyhedron/demo/Polyhedron/Scene_c3t3_item.cpp index 01c192db153..1595716a2c9 100644 --- a/Polyhedron/demo/Polyhedron/Scene_c3t3_item.cpp +++ b/Polyhedron/demo/Polyhedron/Scene_c3t3_item.cpp @@ -157,7 +157,7 @@ public : const EPICK::Plane_3& plane = qobject_cast(this->parent())->plane(); float shrink_factor = qobject_cast(this->parent())->getShrinkFactor(); QVector4D cp = cgal_plane_to_vector4d(plane); - getTriangleContainer(0)->setPlane(cp); + getTriangleContainer(0)->setPlane(-cp); getTriangleContainer(0)->setShrinkFactor(shrink_factor); // positions_poly is also used for the faces in the cut plane // and changes when the cut plane is moved @@ -569,8 +569,10 @@ Scene_c3t3_item::Scene_c3t3_item(const C3t3& c3t3, bool is_surface) : Scene_group_item("unnamed") , d(new Scene_c3t3_item_priv(c3t3, this)) { - d->reset_cut_plane(); common_constructor(is_surface); + d->reset_cut_plane(); + c3t3_changed(); + changed(); } Scene_c3t3_item::~Scene_c3t3_item() @@ -2097,5 +2099,11 @@ void Scene_c3t3_item::newViewer(Viewer_interface *viewer) d->computeIntersections(viewer); } } + +Scene_c3t3_item* Scene_c3t3_item::clone() const +{ + return new Scene_c3t3_item(d->c3t3, d->is_surface); +} + #include "Scene_c3t3_item.moc" diff --git a/Polyhedron/demo/Polyhedron/Scene_c3t3_item.h b/Polyhedron/demo/Polyhedron/Scene_c3t3_item.h index 1c2e4316451..90b02e87c7b 100644 --- a/Polyhedron/demo/Polyhedron/Scene_c3t3_item.h +++ b/Polyhedron/demo/Polyhedron/Scene_c3t3_item.h @@ -101,9 +101,8 @@ public: { return Scene_item::bbox(); } - Scene_c3t3_item* clone() const Q_DECL_OVERRIDE{ - return 0; - } + + Scene_c3t3_item* clone() const Q_DECL_OVERRIDE; bool load_binary(std::istream& is); From 9551708e88667b7d27121a2ec7ea3388c41c8090 Mon Sep 17 00:00:00 2001 From: Maxime Gimeno Date: Wed, 3 Jun 2020 15:02:58 +0200 Subject: [PATCH 483/568] Fix crash in skeletonization --- Three/include/CGAL/Three/Scene_group_item.h | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/Three/include/CGAL/Three/Scene_group_item.h b/Three/include/CGAL/Three/Scene_group_item.h index 3f46883a8c7..626e69240ab 100644 --- a/Three/include/CGAL/Three/Scene_group_item.h +++ b/Three/include/CGAL/Three/Scene_group_item.h @@ -245,8 +245,12 @@ public Q_SLOTS: { for(int i = 0; i < children.size(); ++i) { - if(children[i] >= removed_id) + if(children[i] > removed_id) --children[i]; + else if(children[i] == removed_id)//child has been removed from the scene, it doesn't exist anymore. + { + children.removeAll(removed_id); + } } } private: From 7d5c8e255833a2bc04fce7fda70384623c7aa4e1 Mon Sep 17 00:00:00 2001 From: Maxime Gimeno Date: Wed, 3 Jun 2020 15:56:13 +0200 Subject: [PATCH 484/568] Restore missing dependency for register_point_set_plugin --- Polyhedron/demo/Polyhedron/Plugins/Point_set/CMakeLists.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/Polyhedron/demo/Polyhedron/Plugins/Point_set/CMakeLists.txt b/Polyhedron/demo/Polyhedron/Plugins/Point_set/CMakeLists.txt index c9850cf0684..a1ec1dec229 100644 --- a/Polyhedron/demo/Polyhedron/Plugins/Point_set/CMakeLists.txt +++ b/Polyhedron/demo/Polyhedron/Plugins/Point_set/CMakeLists.txt @@ -48,6 +48,7 @@ if(TARGET CGAL::Eigen_support) if (TARGET CGAL::OpenGR_support OR CGAL::pointmatcher_support) qt5_wrap_ui(register_point_setsUI_FILES Register_point_sets_plugin.ui) polyhedron_demo_plugin(register_point_sets_plugin Register_point_sets_plugin ${register_point_setsUI_FILES} KEYWORDS PointSetProcessing) + target_link_libraries(register_point_sets_plugin PUBLIC scene_points_with_normal_item) target_link_libraries(register_point_sets_plugin PUBLIC CGAL::Eigen_support) if (TARGET CGAL::OpenGR_support) target_link_libraries(register_point_sets_plugin PUBLIC CGAL::OpenGR_support) From 4a9618f62c1423489b5b56946dccf21d140548f0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mael=20Rouxel-Labb=C3=A9?= Date: Wed, 3 Jun 2020 17:11:38 +0200 Subject: [PATCH 485/568] Add missing links --- Installation/CHANGES.md | 39 +++++++++++++++++++++------------------ 1 file changed, 21 insertions(+), 18 deletions(-) diff --git a/Installation/CHANGES.md b/Installation/CHANGES.md index b7abcf127fb..15b3c0f478f 100644 --- a/Installation/CHANGES.md +++ b/Installation/CHANGES.md @@ -28,13 +28,14 @@ Release date: July 2020 Corresponding functors in the model ([`Compare_signed_distance_to_line_2`](https://doc.cgal.org/5.1/Kernel_23/classKernel.html#a066d07dd592ac36ba7ee90988abd349f)) are also added. ### [dD Geometry Kernel](https://doc.cgal.org/5.1/Manual/packages.html#PkgKernelD) + - The kernels [`Epick_d`](https://doc.cgal.org/5.1/Kernel_d/structCGAL_1_1Epick__d.html) and [`Epeck_d`](https://doc.cgal.org/5.1/Kernel_d/structCGAL_1_1Epeck__d.html) gain two new functors: [`Power_side_of_bounded_power_sphere_d`](https://doc.cgal.org/5.1/Kernel_d/classCGAL_1_1Epeck__d_1_1Power__side__of__bounded__power__sphere__d.html) and [`Compute_squared_radius_smallest_orthogonal_sphere_d`](https://doc.cgal.org/5.1/Kernel_d/classCGAL_1_1Epeck__d_1_1Compute__squared__radius__smallest__orthogonal__sphere__d.html). Those are essential for the computation of weighted alpha-complexes. -### Surface Mesh +### [Surface Mesh](https://doc.cgal.org/5.1/Manual/packages.html#PkgSurfaceMesh) - **Breaking change**: The function `CGAL::Surface_mesh::clear()` now removes all non-default properties instead of just emptying them. @@ -59,21 +60,24 @@ Release date: July 2020 and [`do_not_accelerate_distance_queries()`](https://doc.cgal.org/5.1/AABB_tree/classCGAL_1_1AABB__tree.html#abde62f52ccdf411847151aa5000ba4a4) are no longer `const` functions. -### 2D Arrangement on Surface - - Changed intersection return type from legacy `CGAL::Object` to modern - `boost::variant` in all traits concepts and models. +### [2D Arrangements](https://doc.cgal.org/5.1/Manual/packages.html#PkgArrangementOnSurface2) + + - Changed intersection return type from legacy [`CGAL::Object`](https://doc.cgal.org/5.1/STL_Extension/classCGAL_1_1Object.html) + to modern `boost::variant` in all traits concepts and models. As there exists an implicit conversion from `boost::variant` to `CGAL::Object`, the new code is backward compatible. However, it is recommended that all calls to the intersection functions are fixed to use the new return type. -### 2D Regularized Boolean Operations - - Changed intersection return type from legacy `CGAL::Object` to modern - `boost::variant` in the concept `ArrDirectionalTraits::Intersect_2` and - its models. +### [2D Regularized Boolean Set-Operations](https://doc.cgal.org/5.1/Manual/packages.html#PkgBooleanSetOperations2) -### 2D Minkowski Sums - - Changed intersection return type from legacy `CGAL::Object` to modern - `boost::variant` in the (internally used) model `Arr_labeled_traits_2`. + - Changed intersection return type from legacy [`CGAL::Object`](https://doc.cgal.org/5.1/STL_Extension/classCGAL_1_1Object.html) + to modern `boost::variant` in the concept [`ArrDirectionalTraits::Intersect_2`](https://doc.cgal.org/5.1/Boolean_set_operations_2/namespaceArrDirectionalTraits.html) + and its models. + +### [2D Minkowski Sums](https://doc.cgal.org/5.1/Manual/packages.html#PkgMinkowskiSum2) + + - Changed intersection return type from legacy [`CGAL::Object`](https://doc.cgal.org/5.1/STL_Extension/classCGAL_1_1Object.html) + to modern `boost::variant` in the (internally used) model `Arr_labeled_traits_2`. ### [dD Spatial Searching](https://doc.cgal.org/5.1/Manual/packages.html#PkgSpatialSearchingD) @@ -159,13 +163,12 @@ Release date: July 2020 ### [Point Set Processing](https://doc.cgal.org/5.1/Manual/packages.html#PkgPointSetProcessing3) -- **Breaking change:** `CGAL::remove_outliers()` has been - parallelized and thus has a new template parameter - `ConcurrencyTag`. To update your code simply add as first template - parameter `CGAL::Sequential_tag` or `CGAL::Parallel_tag` when - calling this function. -- Add a function `CGAL::cluster_point_set()` that segments a point - cloud into connected components based on a distance threshold. +- **Breaking change:** [`CGAL::remove_outliers()`](https://doc.cgal.org/5.1/Point_set_processing_3/group__PkgPointSetProcessing3Algorithms.html#ga1ab1dcee59caadde50572c5a504cc41a) + has been parallelized and thus has a new template parameter `ConcurrencyTag`. + To update your code simply add as first template parameter `CGAL::Sequential_tag` or `CGAL::Parallel_tag` + when calling this function. +- Add a function [`CGAL::cluster_point_set()`](https://doc.cgal.org/5.1/Point_set_processing_3/group__PkgPointSetProcessing3Algorithms.html#gafee41d60b5a257ae034e9157d0af8e46) + that segments a point cloud into connected components based on a distance threshold. - Added wrapper functions for registration: - [`CGAL::OpenGR::compute_registration_transformation()`](https://doc.cgal.org/5.1/Point_set_processing_3/group__PkgPointSetProcessing3Algorithms.html#gab81663c718960780ddb176aad845e8cd), which computes the registration transformation for two point sets using the Super4PCS algorithm From 05c36b37ec768f1e1a7aa6684422c9a3bddd1b0d Mon Sep 17 00:00:00 2001 From: Maxime Gimeno Date: Wed, 3 Jun 2020 17:13:39 +0200 Subject: [PATCH 486/568] clean-up --- .../include/CGAL/Polygon_mesh_processing/distance.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/distance.h b/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/distance.h index de1b924c658..d85c07a8566 100644 --- a/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/distance.h +++ b/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/distance.h @@ -29,7 +29,7 @@ #include #ifdef CGAL_LINKED_WITH_TBB -#include "tbb/parallel_reduce.h" +#include #include #include #endif // CGAL_LINKED_WITH_TBB @@ -82,7 +82,7 @@ struct Distance_computation{ const PointRange& sample_points; Point_3 initial_hint; double distance; - //constro + //constructor Distance_computation( const AABB_tree& tree, const Point_3& p, @@ -92,7 +92,7 @@ struct Distance_computation{ , initial_hint(p) , distance(-1) {} - //split constro + //split constructor Distance_computation(Distance_computation& s, tbb::split ) : tree(s.tree) , sample_points(s.sample_points) From 02f80631111fe81955b16208b6bd8ef3804891ec Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mael=20Rouxel-Labb=C3=A9?= Date: Wed, 3 Jun 2020 17:27:44 +0200 Subject: [PATCH 487/568] Add Tetrahedral Remeshing to CHANGES.md --- Installation/CHANGES.md | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/Installation/CHANGES.md b/Installation/CHANGES.md index 15b3c0f478f..f7bf118fd99 100644 --- a/Installation/CHANGES.md +++ b/Installation/CHANGES.md @@ -20,6 +20,11 @@ Release date: July 2020 of the *optimal bounding box* of a mesh or a point set, which is defined as the smallest (in terms of volume) bounding box that contains a given mesh or point set. +### [Tetrahedral Remeshing](https://doc.cgal.org/5.1/Manual/packages.html#PkgTetrahedralRemeshing) (new package) +- This package implements a tetrahedral isotropic remeshing algorithm, + that improves the quality of tetrahedra in terms of dihedral angles, + while targetting a given edge length. + ### [2D and 3D Linear Geometry Kernel](https://doc.cgal.org/5.1/Manual/packages.html#PkgKernel23) - Added the functor [`CompareSignedDistanceToLine_2`](https://doc.cgal.org/5.1/Kernel_23/classKernel_1_1CompareSignedDistanceToLine__2.html) From 613eda4e9d839481fa4ac883b72d161a0d546ef1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mael=20Rouxel-Labb=C3=A9?= Date: Wed, 3 Jun 2020 17:28:02 +0200 Subject: [PATCH 488/568] Resize Tetrahedral Remeshing package icon to the proper (120x120) size --- .../fig/bimba_back_small.png | Bin 26205 -> 11525 bytes 1 file changed, 0 insertions(+), 0 deletions(-) diff --git a/Tetrahedral_remeshing/doc/Tetrahedral_remeshing/fig/bimba_back_small.png b/Tetrahedral_remeshing/doc/Tetrahedral_remeshing/fig/bimba_back_small.png index 5cfbd7e3fd8da8705837dfc17cd6dd6e4f04e095..f0f2c0912f3b3ae6311fda36c8d097aab1b209fa 100644 GIT binary patch literal 11525 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 literal 26205 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 M07*qoM6N<$f^sX_O8@`> From 09fa7feef287fbeac4c90e983a597ed00fd828ad Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mael=20Rouxel-Labb=C3=A9?= Date: Wed, 3 Jun 2020 17:39:29 +0200 Subject: [PATCH 489/568] Misc minor fixes --- Installation/CHANGES.md | 22 ++++++++++++---------- 1 file changed, 12 insertions(+), 10 deletions(-) diff --git a/Installation/CHANGES.md b/Installation/CHANGES.md index f7bf118fd99..fb6c4e12413 100644 --- a/Installation/CHANGES.md +++ b/Installation/CHANGES.md @@ -21,6 +21,7 @@ Release date: July 2020 (in terms of volume) bounding box that contains a given mesh or point set. ### [Tetrahedral Remeshing](https://doc.cgal.org/5.1/Manual/packages.html#PkgTetrahedralRemeshing) (new package) + - This package implements a tetrahedral isotropic remeshing algorithm, that improves the quality of tetrahedra in terms of dihedral angles, while targetting a given edge length. @@ -42,15 +43,16 @@ Release date: July 2020 ### [Surface Mesh](https://doc.cgal.org/5.1/Manual/packages.html#PkgSurfaceMesh) -- **Breaking change**: The function `CGAL::Surface_mesh::clear()` now removes all non-default properties instead of just emptying them. +- **Breaking change**: The function [`CGAL::Surface_mesh::clear()`](https://doc.cgal.org/5.1/Surface_mesh/classCGAL_1_1Surface__mesh.html#a247d4ad3e6b106ae22e5306203812642) + now removes all non-default properties instead of just emptying them. ### [CGAL and the Boost Graph Library (BGL)](https://doc.cgal.org/5.1/Manual/packages.html#PkgBGL) -- Added the function [`alpha_expansion_graphcut()`](https://doc.cgal.org/5.1/BGL/group__PkgBGLPartition.html#ga79c3f58b577af51d1140450729d38f22), +- Added the function [`CGAL::alpha_expansion_graphcut()`](https://doc.cgal.org/5.1/BGL/group__PkgBGLPartition.html#ga79c3f58b577af51d1140450729d38f22), which regularizes a multi-label partition over a user-defined graph. -- Added the function [`regularize_face_selection_borders()`](https://doc.cgal.org/5.1/BGL/group__PkgBGLSelectionFct.html#gac71322b0cc7d7d59447531d5e5e345b6), +- Added the function [`CGAL::regularize_face_selection_borders()`](https://doc.cgal.org/5.1/BGL/group__PkgBGLSelectionFct.html#gac71322b0cc7d7d59447531d5e5e345b6), which uses this alpha expansion graphcut to regularize the borders of a selected faces on a triangle mesh. -- Added the function [`set_triangulation_ids()`](https://doc.cgal.org/5.1/BGL/group__BGLGraphExternalIndices.html#ga1a22cf8bdde32fcdf1a4a78966eed630), +- Added the function [`CGAL::set_triangulation_ids()`](https://doc.cgal.org/5.1/BGL/group__BGLGraphExternalIndices.html#ga1a22cf8bdde32fcdf1a4a78966eed630), which must be used to initialize vertex, edge, and face indices of a triangulation meant to be used with BGL algorithms. ### [3D Fast Intersection and Distance Computation](https://doc.cgal.org/5.1/Manual/packages.html#PkgAABBTree) @@ -58,11 +60,11 @@ Release date: July 2020 - The behavior of the internal search tree used to accelerate distance queries has changed: usage of the internal search tree will now be enabled by default, and its construction will be triggered by the first distance query. Automatic construction and usage can be disabled - by calling [`do_not_accelerate_distance_queries()`](https://doc.cgal.org/5.1/AABB_tree/classCGAL_1_1AABB__tree.html#abde62f52ccdf411847151aa5000ba4a4) + by calling [`CGAL::AABB_tree::do_not_accelerate_distance_queries()`](https://doc.cgal.org/5.1/AABB_tree/classCGAL_1_1AABB__tree.html#abde62f52ccdf411847151aa5000ba4a4) before the first distance query, and the tree can be built at any moment by calling - [`accelerate_distance_queries()`](https://doc.cgal.org/5.1/AABB_tree/classCGAL_1_1AABB__tree.html#a5d3877d3f2afbd09341eb4b8c230080b). -- **Breaking change**: [`accelerate_distance_queries()`](https://doc.cgal.org/5.1/AABB_tree/classCGAL_1_1AABB__tree.html#a5d3877d3f2afbd09341eb4b8c230080b) - and [`do_not_accelerate_distance_queries()`](https://doc.cgal.org/5.1/AABB_tree/classCGAL_1_1AABB__tree.html#abde62f52ccdf411847151aa5000ba4a4) + [`CGAL::AABB_tree::accelerate_distance_queries()`](https://doc.cgal.org/5.1/AABB_tree/classCGAL_1_1AABB__tree.html#a5d3877d3f2afbd09341eb4b8c230080b). +- **Breaking change**: [`CGAL::AABB_tree::accelerate_distance_queries()`](https://doc.cgal.org/5.1/AABB_tree/classCGAL_1_1AABB__tree.html#a5d3877d3f2afbd09341eb4b8c230080b) + and [`CGAL::AABB_tree::do_not_accelerate_distance_queries()`](https://doc.cgal.org/5.1/AABB_tree/classCGAL_1_1AABB__tree.html#abde62f52ccdf411847151aa5000ba4a4) are no longer `const` functions. ### [2D Arrangements](https://doc.cgal.org/5.1/Manual/packages.html#PkgArrangementOnSurface2) @@ -131,7 +133,7 @@ Release date: July 2020 ### [3D Convex Hulls](https://doc.cgal.org/5.1/Manual/packages.html#PkgConvexHull3) - A new overload for [`CGAL::convex_hull_3()`](https://doc.cgal.org/5.1/Convex_hull_3/group__PkgConvexHull3Functions.html#gaa02a3013808fc9a2e5e2f42b9fde8e30) - that takes a model of `VertexListGraph` has been added. + that takes a model of [`VertexListGraph`](https://doc.cgal.org/5.1/BGL/classVertexListGraph.html) has been added. - The long-deprecated function `CGAL::convex_hull_3_to_polyhedron_3()` has been removed. The function [`CGAL::convex_hull_3_to_face_graph()`](https://doc.cgal.org/5.1/Convex_hull_3/group__PkgConvexHull3Functions.html#ga2750f7f197588ed643679835c748c671) should be used instead. @@ -204,7 +206,7 @@ Release date: July 2020 common endpoints, for convience. - Added the function [`CGAL::split_subconstraint_graph_into_constraints()`](https://doc.cgal.org/5.1/Triangulation_2/classCGAL_1_1Constrained__triangulation__plus__2.html#adea77f5db5cd4dfae302e4502f1caa85) to [`Constrained_triangulation_plus_2`](https://doc.cgal.org/5.1/Triangulation_2/classCGAL_1_1Constrained__triangulation__plus__2.html) to initialize the constraints - from a soup of disconnected segments that should first be split into polylines. + from a soup of disconnected segments that should first be split into polylines. ### [3D Triangulations](https://doc.cgal.org/5.1/Manual/packages.html#PkgTriangulation3) From d81184ca9f5a7b03b6ed9b89b1a5f9f197992419 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mael=20Rouxel-Labb=C3=A9?= Date: Wed, 3 Jun 2020 17:47:40 +0200 Subject: [PATCH 490/568] Add links to entries on cgal.org --- Installation/CHANGES.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Installation/CHANGES.md b/Installation/CHANGES.md index fb6c4e12413..90008182baa 100644 --- a/Installation/CHANGES.md +++ b/Installation/CHANGES.md @@ -13,12 +13,14 @@ Release date: July 2020 between free homotopy and homotopy with fixed endpoints; - test is a curve is contractible; - compute shortest non-contractible cycles on a surface, with or without weights on edges. + See also the associated [blog entry](https://www.cgal.org/2020/05/08/Surface_mesh_topology/). ### [Optimal Bounding Box](https://doc.cgal.org/5.1/Manual/packages.html#PkgOptimalBoundingBox) (new package) - This package implements an optimization algorithm that aims to construct a close approximation of the *optimal bounding box* of a mesh or a point set, which is defined as the smallest (in terms of volume) bounding box that contains a given mesh or point set. + See also the associated [blog entry](https://www.cgal.org/2020/04/20/Optimal_bounding_box/). ### [Tetrahedral Remeshing](https://doc.cgal.org/5.1/Manual/packages.html#PkgTetrahedralRemeshing) (new package) From 6607b48dda67811f41bdca40a6eb7ac4ec8dd00f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mael=20Rouxel-Labb=C3=A9?= Date: Wed, 3 Jun 2020 17:47:55 +0200 Subject: [PATCH 491/568] Add an entry in CHANGES.md about the tutorials --- Installation/CHANGES.md | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/Installation/CHANGES.md b/Installation/CHANGES.md index 90008182baa..b41df7b6153 100644 --- a/Installation/CHANGES.md +++ b/Installation/CHANGES.md @@ -28,6 +28,15 @@ Release date: July 2020 that improves the quality of tetrahedra in terms of dihedral angles, while targetting a given edge length. +### [Tutorials](https://doc.cgal.org/5.1/Manual/tutorials.html) + +- Two new, detailed tutorials have been added: + - [Surface Reconstruction from Point Clouds](https://doc.cgal.org/5.1/Manual/tuto_reconstruction.html), + which goes over a typical full processing pipeline in a CGAL environment. + - [Geographic Information Systems (GIS)](https://doc.cgal.org/5.1/Manual/tuto_gis.html), + which demonstrates usage of CGAL data structures and algorithms in the context of a typical GIS application. + In both tutorials, complete code is provided. + ### [2D and 3D Linear Geometry Kernel](https://doc.cgal.org/5.1/Manual/packages.html#PkgKernel23) - Added the functor [`CompareSignedDistanceToLine_2`](https://doc.cgal.org/5.1/Kernel_23/classKernel_1_1CompareSignedDistanceToLine__2.html) From e49babecfb7c97bacccf24438dfa7e0b83226b1c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mael=20Rouxel-Labb=C3=A9?= Date: Wed, 3 Jun 2020 17:50:08 +0200 Subject: [PATCH 492/568] Formatting... --- Installation/CHANGES.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/Installation/CHANGES.md b/Installation/CHANGES.md index b41df7b6153..0352def2515 100644 --- a/Installation/CHANGES.md +++ b/Installation/CHANGES.md @@ -13,6 +13,7 @@ Release date: July 2020 between free homotopy and homotopy with fixed endpoints; - test is a curve is contractible; - compute shortest non-contractible cycles on a surface, with or without weights on edges. + See also the associated [blog entry](https://www.cgal.org/2020/05/08/Surface_mesh_topology/). ### [Optimal Bounding Box](https://doc.cgal.org/5.1/Manual/packages.html#PkgOptimalBoundingBox) (new package) @@ -20,6 +21,7 @@ Release date: July 2020 - This package implements an optimization algorithm that aims to construct a close approximation of the *optimal bounding box* of a mesh or a point set, which is defined as the smallest (in terms of volume) bounding box that contains a given mesh or point set. + See also the associated [blog entry](https://www.cgal.org/2020/04/20/Optimal_bounding_box/). ### [Tetrahedral Remeshing](https://doc.cgal.org/5.1/Manual/packages.html#PkgTetrahedralRemeshing) (new package) @@ -35,6 +37,7 @@ Release date: July 2020 which goes over a typical full processing pipeline in a CGAL environment. - [Geographic Information Systems (GIS)](https://doc.cgal.org/5.1/Manual/tuto_gis.html), which demonstrates usage of CGAL data structures and algorithms in the context of a typical GIS application. + In both tutorials, complete code is provided. ### [2D and 3D Linear Geometry Kernel](https://doc.cgal.org/5.1/Manual/packages.html#PkgKernel23) From 63e77ea2cd2151cf3e74746264c90fbc02f4707b Mon Sep 17 00:00:00 2001 From: Laurent Rineau Date: Wed, 3 Jun 2020 18:18:04 +0200 Subject: [PATCH 493/568] updated crontab (automated commit) --- Maintenance/infrastructure/cgal.geometryfactory.com/crontab | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Maintenance/infrastructure/cgal.geometryfactory.com/crontab b/Maintenance/infrastructure/cgal.geometryfactory.com/crontab index d98d42b770d..9cb5c94bfc7 100644 --- a/Maintenance/infrastructure/cgal.geometryfactory.com/crontab +++ b/Maintenance/infrastructure/cgal.geometryfactory.com/crontab @@ -23,9 +23,9 @@ LC_CTYPE=en_US.UTF-8 # The script also updates the manual tools. # "master" alone -0 21 * * Sun cd $HOME/CGAL/create_internal_release && /usr/bin/time scl enable rh-git29 -- $HOME/bin/create_release $HOME/CGAL/branches/master.git --do-it || echo ERROR +0 21 * * Sun cd $HOME/CGAL/create_internal_release && /usr/bin/time scl enable rh-git29 -- $HOME/bin/create_release $HOME/CGAL/branches/master.git --do-it --beta 1 --public || echo ERROR # "integration" -0 21 * * Mon,Tue,Wed,Thu,Fri cd $HOME/CGAL/create_internal_release && /usr/bin/time scl enable rh-git29 -- $HOME/bin/create_release $HOME/CGAL/branches/integration.git $HOME/CGAL/branches/empty-dir --do-it --public || echo ERROR +0 21 * * Mon,Tue,Wed,Thu,Fri cd $HOME/CGAL/create_internal_release && /usr/bin/time scl enable rh-git29 -- $HOME/bin/create_release $HOME/CGAL/branches/integration.git $HOME/CGAL/branches/empty-dir --do-it --beta 1 --public || echo ERROR # from branch 5.0 0 21 * * Sat cd $HOME/CGAL/create_internal_release-5.0-branch && /usr/bin/time scl enable rh-git29 -- $HOME/bin/create_release $HOME/CGAL/branches/CGAL-5.0-branch.git --public --do-it || echo ERROR # from branch 4.14 From daf86cc7194336b2b8acf0e0024673d62c4488fc Mon Sep 17 00:00:00 2001 From: Laurent Rineau Date: Wed, 3 Jun 2020 17:01:02 +0200 Subject: [PATCH 494/568] Prepare for 5.1-beta1 --- .../doc/resources/1.8.13/menu_version.js | 9 +- .../doc/resources/1.8.14/menu_version.js | 248 +++++++++++------- .../doc/resources/1.8.4/menu_version.js | 248 +++++++++++------- Installation/include/CGAL/version.h | 2 +- .../lib/cmake/CGAL/CGALConfigVersion.cmake | 2 +- 5 files changed, 327 insertions(+), 182 deletions(-) diff --git a/Documentation/doc/resources/1.8.13/menu_version.js b/Documentation/doc/resources/1.8.13/menu_version.js index 36b298ee045..1eb05caa463 100644 --- a/Documentation/doc/resources/1.8.13/menu_version.js +++ b/Documentation/doc/resources/1.8.13/menu_version.js @@ -3,10 +3,11 @@ var url_re = /(cgal\.geometryfactory\.com\/CGAL\/doc\/|doc\.cgal\.org\/)(master|latest|(\d\.\d+|\d\.\d+\.\d+))\//; var url_local = /.*\/doc_output\//; - var current_version_local = '5.1-dev' + var current_version_local = '5.1-beta1' var all_versions = [ 'master', 'latest', + '5.1-beta1', '5.0.2', '4.14.3', '4.13.2', @@ -44,7 +45,7 @@ } function patch_url(url, new_version) { - if(url.includes("doc.cgal.org")||url.includes("cgal.geometryfactory.com")){ + if(url.includes("doc.cgal.org")||url.includes("cgal.geometryfactory.com")){ return url.replace(url_re, 'doc.cgal.org/' + new_version + '/'); } else{ @@ -65,7 +66,7 @@ var motherNode=$("#back-nav ul")[0]; var node = document.createElement("LI"); var spanNode = document.createElement("SPAN"); - var titleNode =document.createTextNode("CGAL Version: "); + var titleNode =document.createTextNode("CGAL Version: "); var textNode = document.createTextNode("x.y"); spanNode.setAttribute("class", "version_menu"); spanNode.appendChild(textNode); @@ -90,4 +91,4 @@ } } }); -})(); +})(); diff --git a/Documentation/doc/resources/1.8.14/menu_version.js b/Documentation/doc/resources/1.8.14/menu_version.js index 36b298ee045..e90af8192e6 100644 --- a/Documentation/doc/resources/1.8.14/menu_version.js +++ b/Documentation/doc/resources/1.8.14/menu_version.js @@ -1,93 +1,165 @@ -(function() { - 'use strict'; +Head: master Merge branch 'releases/CGAL-5.0-branch' +Merge: cgal/master Merge branch 'releases/CGAL-5.0-branch' +Push: cgal/master Merge branch 'releases/CGAL-5.0-branch' +Tag: master_before_no_tws_nor_tabs (1749) - var url_re = /(cgal\.geometryfactory\.com\/CGAL\/doc\/|doc\.cgal\.org\/)(master|latest|(\d\.\d+|\d\.\d+\.\d+))\//; - var url_local = /.*\/doc_output\//; - var current_version_local = '5.1-dev' - var all_versions = [ - 'master', - 'latest', - '5.0.2', - '4.14.3', - '4.13.2', - '4.12.2', - '4.11.3', - '4.10.2', - '4.9.1', - '4.8.2', - '4.7', - '4.6.3', - '4.5.2', - '4.4', - '4.3' - ]; +Untracked files (1) +Documentation/doc/resources/1.8.14/1.8.13 - function build_select(current_version) { - var buf = [''); - return buf.join(''); - } +Unstaged changes (1) +modified Documentation/doc/resources/1.8.13/menu_version.js +@@ -3,10 +3,11 @@ - function patch_url(url, new_version) { - if(url.includes("doc.cgal.org")||url.includes("cgal.geometryfactory.com")){ - return url.replace(url_re, 'doc.cgal.org/' + new_version + '/'); - } - else{ - return url.replace(url_local, 'https://doc.cgal.org/' + new_version + '/'); - } - } + var url_re = /(cgal\.geometryfactory\.com\/CGAL\/doc\/|doc\.cgal\.org\/)(master|latest|(\d\.\d+|\d\.\d+\.\d+))\//; + var url_local = /.*\/doc_output\//; +- var current_version_local = '5.1-dev' ++ var current_version_local = '5.1-beta1' + var all_versions = [ + 'master', + 'latest', ++ '5.1-beta1', + '5.0.2', + '4.14.3', + '4.13.2', +@@ -44,7 +45,7 @@ + } - function on_switch() { - var selected = $(this).children('option:selected').attr('value'); - var url = window.location.href, - new_url = patch_url(url, selected); - if (new_url != url) { - window.location.href = new_url; - } - } - - $(document).ready(function() { - var motherNode=$("#back-nav ul")[0]; - var node = document.createElement("LI"); - var spanNode = document.createElement("SPAN"); - var titleNode =document.createTextNode("CGAL Version: "); - var textNode = document.createTextNode("x.y"); - spanNode.setAttribute("class", "version_menu"); - spanNode.appendChild(textNode); - node.appendChild(titleNode); - node.appendChild(spanNode); - motherNode.insertBefore(node, motherNode.firstChild); - $("#back-nav").css("padding-top", "0").css("padding-bottom", "0"); - var match = url_re.exec(window.location.href); - if (match) { - var version = match[2]; - var select = build_select(version); - spanNode.innerHTML=select; - $('.version_menu select').bind('change', on_switch); - } - else { - match = url_local.exec(window.location.href); - if (match) { - var version = current_version_local; - var select = build_select(version); - spanNode.innerHTML=select; - $('.version_menu select').bind('change', on_switch); - } + function patch_url(url, new_version) { +- if(url.includes("doc.cgal.org")||url.includes("cgal.geometryfactory.com")){ ++ if(url.includes("doc.cgal.org")||url.includes("cgal.geometryfactory.com")){ + return url.replace(url_re, 'doc.cgal.org/' + new_version + '/'); } - }); -})(); + else{ +@@ -65,7 +66,7 @@ + var motherNode=$("#back-nav ul")[0]; + var node = document.createElement("LI"); + var spanNode = document.createElement("SPAN"); +- var titleNode =document.createTextNode("CGAL Version: "); ++ var titleNode =document.createTextNode("CGAL Version: "); + var textNode = document.createTextNode("x.y"); + spanNode.setAttribute("class", "version_menu"); + spanNode.appendChild(textNode); +@@ -90,4 +91,4 @@ + } + } + }); +-})(); ++})(); + +Stashes (104) +stash@{0} WIP on Mesh_3-fix_optimisers_parallel-jtournois-WIP: 46820eda8bf debugging perturber... +stash@{1} WIP on CGAL-5.0-branch: dc12dea7766 Merge branch 'releases/CGAL-4.14-branch' into releases/CGAL-5.0-branch +stash@{2} On Installation-add_CGALConfigVersion-GF: RELOCATABLE? +stash@{3} On Tetrahedral_remeshing-new-jtournois: DEBUG code +stash@{4} WIP on nurbs-viewer-mesher: 495bc2b6022 Fix the link +stash@{5} On master: point_cloud_to_inr +stash@{6} Patch ExxonMobile +stash@{7} WIP on master: b6d5129364a Merge branch 'releases/CGAL-5.0-branch' +stash@{8} Scene_surface_mesh_item::setAllPatchIds +stash@{9} On master: Replaced by "Update warning macro usages #4474" +stash@{10} On master: Cleanup CDT_plus_2 +stash@{11} On master: Fix issue "Warning in Triangulation_2" #4371 +stash@{12} On master: f0c82986576 updated crontab (automated commit) +stash@{13} Surface_mesh: use override instead of virtual +stash@{14} On T3_accelerate_insert_in_hole: TDS::reserve +stash@{15} On T3_accelerate_insert_in_hole: Essai d'utilisation des time stamps +stash@{16} On heads/Triangulation_segment_traverser_3-tvanlank__rewrote_history-GF: 7e0f93f4c9e Add a case (assertion) +stash@{17} On master: cleanup Polyline_constraint_hierarchy_2.h +stash@{18} On Sweep_2-bug_57-GF: 02bfdcf828a Better way to measure the recursion depth +stash@{19} On master: 3d1450b71fb Merge branch 'releases/CGAL-4.14-branch' +stash@{20} WIP on master: 3d1450b71fb Merge branch 'releases/CGAL-4.14-branch' +stash@{21} On Polyhedron-demo__add_qtscript_support_to_Mesh_3_plugin-GF: e068363fbfa Add an API to replace QMessageBox static functions +stash@{22} On CGAL-clang_tidy__nullptr_on_Mesh_2-GF: Mesh_3 plugin +stash@{23} On integration: CORE MemoryPool DEBUG +stash@{24} Try to fix check headers warnings about incorrect flags +stash@{25} WIP on releases/CGAL-4.13-branch: a34c09084c6 Merge pull request #3855 from sgiraudot/Intersections_3-Fix_almost_collinear_segments_bug-GF +stash@{26} WIP on releases/CGAL-4.14-branch: 490589b48f6 Merge branch 'releases/CGAL-4.13-branch' into releases/CGAL-4.14-branch +stash@{27} On integration: 32f063f25f0 Merge pull request #3886 from lrineau/CGAL-Adapt_to_Boost_1.70-GF +stash@{28} On integration: GMPXX by default +stash@{29} On integration: Simplify Mesh_3, and MPZF +stash@{30} On Number_types-intervals3-glisse: Include all header twice +stash@{31} On Mesh_3-tricubic-GF: HACKS +stash@{32} On Mesh_3-fix_polyhedral_complex_domain-GF: 9964b18243c Fix Polyhedral_complex_mesh_domain_3 when detect_features() is not called +stash@{33} On Mesh_3-fix_Index-GF: Mesh_3 with union instead of boost::variant +stash@{34} On Mesh_3-fix_Index-GF: Testsuite/test/parse-ctest-dashboard-xml.py with zlib +stash@{35} On master: Tests with -funsafe-math-optimizations +stash@{36} On Triangulation_2-Debug_CDT2-lrineau: Debug CDT_2 +stash@{37} On releases/CGAL-4.12-branch: Scene_polygon_soup_item: remove duplicated triangles +stash@{38} On integration: Mesh_3: Ident nested #ifdef +stash@{39} On Travis-Check_including_all_headers-GF: Try to improve "check_headers" +stash@{40} On Polyhedron-demo_offset_plugin_Mesh_3_triangle_soup-GF: attempt of a traversal traits +stash@{41} On Polyhedron-demo_offset_plugin_Mesh_3_triangle_soup-GF: Variable offset distance +stash@{42} On master: Problems with SEP image +stash@{43} WIP on master: 441170768df Prepare CGAL-4.12-beta1 +stash@{44} On integration: CSS!! +stash@{45} WIP on Installation-improve_CGAL_DEV_MODE-lrineau: 4811fae85c2 Do not document the CGAL pure header-only mode +stash@{46} Mesh_3: debug trick with CGAL_assertion_msg and a lambda +stash@{47} On integration: CTest +stash@{48} On (no branch): a8704de Merge branch 'releases/CGAL-4.10-branch' +stash@{49} On Mesh_3-fix_NaN-lrineau: DEBUG Sliver_perturber +stash@{50} On Mesh_2-restore_Qt3_demo-lrineau: Doxygen warnings +stash@{51} On integration: Debug Mesh_2 +stash@{52} On Mesh_3-API_with_incidences-GF: e17da6445d1 Write the documentation +stash@{53} On Mesh_3-test_polyhedral_complex_with_surface_mesh-GF: TESTS +stash@{54} ? +stash@{55} On Mesh_3-fix_bug_1944-GF: 4325f22 Merge pull request #2145 from gdamiand/patch-1 +stash@{56} On integration: a5ea993 Merge remote-tracking branch 'cgal/master' into integration +stash@{57} On Polyhedron_demo-Use_sm_in_Deformation-GF: Selection plugin, pb ODR? +stash@{58} On Polyhedron-clipping_snapping_new_snapping-GF-wip: 23e0762 fixup! Add a safety check +stash@{59} On Polyhedron-clipping_snapping_new_snapping-GF-wip: cbfc043 Revert "wip" +stash@{60} On Polyhedron-clipping_snapping_new_snapping-GF-wip: 720086f Add snap_corners_to_curves_when_possible +stash@{61} On (no branch): Debug Mesh_3 +stash@{62} WIP on Polyhedron-clipping_snapping_new_snapping-GF-wip: 50d11a6 Move get_curve_id to Clipping_snapping_tool_details +stash@{63} On Polyhedron-clipping_snapping_new_snapping-GF-wip: WIP on fix corner-to-curve +stash@{64} WIP on Polyhedron-clipping_snapping_new_snapping-GF-wip: 26e2d29 Add missing `#include` +stash@{65} On integration: c540a7e Merge pull request #1808 from MaelRL/Spatial_searching-Fix_fuzzy_query_item_border +stash@{66} WIP on integration: c540a7e Merge pull request #1808 from MaelRL/Spatial_searching-Fix_fuzzy_query_item_border +stash@{67} WIP on integration: c540a7e Merge pull request #1808 from MaelRL/Spatial_searching-Fix_fuzzy_query_item_border +stash@{68} WIP on integration: c540a7e Merge pull request #1808 from MaelRL/Spatial_searching-Fix_fuzzy_query_item_border +stash@{69} WIP on integration: c540a7e Merge pull request #1808 from MaelRL/Spatial_searching-Fix_fuzzy_query_item_border +stash@{70} More assertion in multi-thread Handle.h +stash@{71} CMake: if(NOT CMAKE_CROSSCOMPILING) +stash@{72} Bug Mesh_3 TROU! +stash@{73} WIP on Polyhedron-clipping_snapping_new_snapping-GF-wip: 4f429fa Merge remote-tracking branch 'cgal/master' into Polyhedron-clipping_snapping_new_snapping-GF-wip +stash@{74} On master: convert an image from unsigned short to float +stash@{75} On master: Mesh_3 Robust_weighted_circumcenter_filtered_traits_3 use certainly +stash@{76} On CGAL-remove_support_for_LEDA_5_and_before-GF: 0c69001 Remove all usage of CGAL_LEDA_VERSION +stash@{77} WIP on Mesh_3-new_facet_criterion_with_normals-lrineau: c4b81cf Fix a warning in Sizing_field_with_aabb_tree +stash@{78} On CGAL-license_check-GF: 366976b fix header +stash@{79} Polyhedron demo with keywords for plugins +stash@{80} Mesh_3: save, load a C3t3 and refine it +stash@{81} On master: 2153e65 Fix a typo in doc: remove extra "`" +stash@{82} On Mesh_3-hybrid_mesh_domain-GF: Shifted_sphere_implicit_function +stash@{83} On CGAL_headers_only_step1-gdamiand_cjamin: Fix an error in headers-only +stash@{84} Bug Intel 2017 +stash@{85} WIP on Mesh_3-improve_polylines_to_protect-GF: ee0fb3b Fix the header guard macro, and copyright years +stash@{86} On master: Restore CGAL_Qt3 +stash@{87} On Mesh_2-fix_issue_781-GF: Mesh_2: Display queues sizes +stash@{88} On Mesh_3-improve_images-GF: "Fix" C3t3_io_plugin to deal with INT_MIN +stash@{89} WIP on Polyhedron-clipping_snapping_new_snapping-GF-wip: 7787959 Re-test `modified_features` after a corner-snapping +stash@{90} On Mesh_3-experimental-GF: Experiments on Mesh-3 +stash@{91} On master: Fix orient polygon soup with PMP, temp +stash@{92} On CGAL-Qt5_support-GF: Replace gluErrorString +stash@{93} On master: Mesh_3, for pipeNotWorking +stash@{94} On master: Mesh_3 for Medicim/Nobelbiocare +stash@{95} WIP on Mesh_3-experimental-GF: a1b342e Allow to open a binary CDT_3 +stash@{96} WIP on master: 0df4095 Merge pull request #30 from afabri/Documentation-addHome-GF +stash@{97} WIP on CGAL-Qt5_support-GF: 0d2f838 Allow to find QGLViewer-qt5_ +stash@{98} On master: LICENSE (Dijsktra), Memory_size.h (near) +stash@{99} On Triangulation_2-Fix_CDT_plus-GF: wip +stash@{100} On master: Pretty printers, et Sliver_perturber.h +stash@{101} On master: bench mesh_3 +stash@{102} On Intersection_3-fix-do_intersect_Iso_cuboid_3_Segment_3-lrineau: Fix intersection(Iso_cuboid_3, Segment_3) +stash@{103} On master: Try to fix warnings for CMap + +Recent commits +97123fc3c72 cgal/master Merge branch 'releases/CGAL-5.0-branch' +871c97273af Merge pull request #4496 from lrineau/CGAL-move_semantic_for_triangulations-GF +a828cb0d066 Merge pull request #4620 from janetournois/Tetrahedral_remeshing-new-jtournois +8db45039044 Merge pull request #4710 from danston/CGAL-clangmp_bug_fix-danston +c15030bf39b Merge pull request #4740 from afabri/T2-low_dimensional-GF +814689552b1 Merge pull request #4752 from lrineau/CGAL-fix_cpp20-mglisse_GF +863b1decf69 Merge pull request #4754 from maxGimeno/PMP-Fix_parallel_haussdorf_dist-maxGimeno +4354b2c87f0 releases/CGAL-5.0-branch cgal/releases/CGAL-5.0-branch Merge pull request #4710 from danston/CGAL-clangmp_bug_fix-danston +dc2ae1614c2 Merge remote-tracking branch 'cgal/releases/CGAL-4.14-branch' into releases/CGAL-5.0-branch +520fbf7c4b7 refs/pull/4754/head Add missing include diff --git a/Documentation/doc/resources/1.8.4/menu_version.js b/Documentation/doc/resources/1.8.4/menu_version.js index 36b298ee045..e90af8192e6 100644 --- a/Documentation/doc/resources/1.8.4/menu_version.js +++ b/Documentation/doc/resources/1.8.4/menu_version.js @@ -1,93 +1,165 @@ -(function() { - 'use strict'; +Head: master Merge branch 'releases/CGAL-5.0-branch' +Merge: cgal/master Merge branch 'releases/CGAL-5.0-branch' +Push: cgal/master Merge branch 'releases/CGAL-5.0-branch' +Tag: master_before_no_tws_nor_tabs (1749) - var url_re = /(cgal\.geometryfactory\.com\/CGAL\/doc\/|doc\.cgal\.org\/)(master|latest|(\d\.\d+|\d\.\d+\.\d+))\//; - var url_local = /.*\/doc_output\//; - var current_version_local = '5.1-dev' - var all_versions = [ - 'master', - 'latest', - '5.0.2', - '4.14.3', - '4.13.2', - '4.12.2', - '4.11.3', - '4.10.2', - '4.9.1', - '4.8.2', - '4.7', - '4.6.3', - '4.5.2', - '4.4', - '4.3' - ]; +Untracked files (1) +Documentation/doc/resources/1.8.14/1.8.13 - function build_select(current_version) { - var buf = [''); - return buf.join(''); - } +Unstaged changes (1) +modified Documentation/doc/resources/1.8.13/menu_version.js +@@ -3,10 +3,11 @@ - function patch_url(url, new_version) { - if(url.includes("doc.cgal.org")||url.includes("cgal.geometryfactory.com")){ - return url.replace(url_re, 'doc.cgal.org/' + new_version + '/'); - } - else{ - return url.replace(url_local, 'https://doc.cgal.org/' + new_version + '/'); - } - } + var url_re = /(cgal\.geometryfactory\.com\/CGAL\/doc\/|doc\.cgal\.org\/)(master|latest|(\d\.\d+|\d\.\d+\.\d+))\//; + var url_local = /.*\/doc_output\//; +- var current_version_local = '5.1-dev' ++ var current_version_local = '5.1-beta1' + var all_versions = [ + 'master', + 'latest', ++ '5.1-beta1', + '5.0.2', + '4.14.3', + '4.13.2', +@@ -44,7 +45,7 @@ + } - function on_switch() { - var selected = $(this).children('option:selected').attr('value'); - var url = window.location.href, - new_url = patch_url(url, selected); - if (new_url != url) { - window.location.href = new_url; - } - } - - $(document).ready(function() { - var motherNode=$("#back-nav ul")[0]; - var node = document.createElement("LI"); - var spanNode = document.createElement("SPAN"); - var titleNode =document.createTextNode("CGAL Version: "); - var textNode = document.createTextNode("x.y"); - spanNode.setAttribute("class", "version_menu"); - spanNode.appendChild(textNode); - node.appendChild(titleNode); - node.appendChild(spanNode); - motherNode.insertBefore(node, motherNode.firstChild); - $("#back-nav").css("padding-top", "0").css("padding-bottom", "0"); - var match = url_re.exec(window.location.href); - if (match) { - var version = match[2]; - var select = build_select(version); - spanNode.innerHTML=select; - $('.version_menu select').bind('change', on_switch); - } - else { - match = url_local.exec(window.location.href); - if (match) { - var version = current_version_local; - var select = build_select(version); - spanNode.innerHTML=select; - $('.version_menu select').bind('change', on_switch); - } + function patch_url(url, new_version) { +- if(url.includes("doc.cgal.org")||url.includes("cgal.geometryfactory.com")){ ++ if(url.includes("doc.cgal.org")||url.includes("cgal.geometryfactory.com")){ + return url.replace(url_re, 'doc.cgal.org/' + new_version + '/'); } - }); -})(); + else{ +@@ -65,7 +66,7 @@ + var motherNode=$("#back-nav ul")[0]; + var node = document.createElement("LI"); + var spanNode = document.createElement("SPAN"); +- var titleNode =document.createTextNode("CGAL Version: "); ++ var titleNode =document.createTextNode("CGAL Version: "); + var textNode = document.createTextNode("x.y"); + spanNode.setAttribute("class", "version_menu"); + spanNode.appendChild(textNode); +@@ -90,4 +91,4 @@ + } + } + }); +-})(); ++})(); + +Stashes (104) +stash@{0} WIP on Mesh_3-fix_optimisers_parallel-jtournois-WIP: 46820eda8bf debugging perturber... +stash@{1} WIP on CGAL-5.0-branch: dc12dea7766 Merge branch 'releases/CGAL-4.14-branch' into releases/CGAL-5.0-branch +stash@{2} On Installation-add_CGALConfigVersion-GF: RELOCATABLE? +stash@{3} On Tetrahedral_remeshing-new-jtournois: DEBUG code +stash@{4} WIP on nurbs-viewer-mesher: 495bc2b6022 Fix the link +stash@{5} On master: point_cloud_to_inr +stash@{6} Patch ExxonMobile +stash@{7} WIP on master: b6d5129364a Merge branch 'releases/CGAL-5.0-branch' +stash@{8} Scene_surface_mesh_item::setAllPatchIds +stash@{9} On master: Replaced by "Update warning macro usages #4474" +stash@{10} On master: Cleanup CDT_plus_2 +stash@{11} On master: Fix issue "Warning in Triangulation_2" #4371 +stash@{12} On master: f0c82986576 updated crontab (automated commit) +stash@{13} Surface_mesh: use override instead of virtual +stash@{14} On T3_accelerate_insert_in_hole: TDS::reserve +stash@{15} On T3_accelerate_insert_in_hole: Essai d'utilisation des time stamps +stash@{16} On heads/Triangulation_segment_traverser_3-tvanlank__rewrote_history-GF: 7e0f93f4c9e Add a case (assertion) +stash@{17} On master: cleanup Polyline_constraint_hierarchy_2.h +stash@{18} On Sweep_2-bug_57-GF: 02bfdcf828a Better way to measure the recursion depth +stash@{19} On master: 3d1450b71fb Merge branch 'releases/CGAL-4.14-branch' +stash@{20} WIP on master: 3d1450b71fb Merge branch 'releases/CGAL-4.14-branch' +stash@{21} On Polyhedron-demo__add_qtscript_support_to_Mesh_3_plugin-GF: e068363fbfa Add an API to replace QMessageBox static functions +stash@{22} On CGAL-clang_tidy__nullptr_on_Mesh_2-GF: Mesh_3 plugin +stash@{23} On integration: CORE MemoryPool DEBUG +stash@{24} Try to fix check headers warnings about incorrect flags +stash@{25} WIP on releases/CGAL-4.13-branch: a34c09084c6 Merge pull request #3855 from sgiraudot/Intersections_3-Fix_almost_collinear_segments_bug-GF +stash@{26} WIP on releases/CGAL-4.14-branch: 490589b48f6 Merge branch 'releases/CGAL-4.13-branch' into releases/CGAL-4.14-branch +stash@{27} On integration: 32f063f25f0 Merge pull request #3886 from lrineau/CGAL-Adapt_to_Boost_1.70-GF +stash@{28} On integration: GMPXX by default +stash@{29} On integration: Simplify Mesh_3, and MPZF +stash@{30} On Number_types-intervals3-glisse: Include all header twice +stash@{31} On Mesh_3-tricubic-GF: HACKS +stash@{32} On Mesh_3-fix_polyhedral_complex_domain-GF: 9964b18243c Fix Polyhedral_complex_mesh_domain_3 when detect_features() is not called +stash@{33} On Mesh_3-fix_Index-GF: Mesh_3 with union instead of boost::variant +stash@{34} On Mesh_3-fix_Index-GF: Testsuite/test/parse-ctest-dashboard-xml.py with zlib +stash@{35} On master: Tests with -funsafe-math-optimizations +stash@{36} On Triangulation_2-Debug_CDT2-lrineau: Debug CDT_2 +stash@{37} On releases/CGAL-4.12-branch: Scene_polygon_soup_item: remove duplicated triangles +stash@{38} On integration: Mesh_3: Ident nested #ifdef +stash@{39} On Travis-Check_including_all_headers-GF: Try to improve "check_headers" +stash@{40} On Polyhedron-demo_offset_plugin_Mesh_3_triangle_soup-GF: attempt of a traversal traits +stash@{41} On Polyhedron-demo_offset_plugin_Mesh_3_triangle_soup-GF: Variable offset distance +stash@{42} On master: Problems with SEP image +stash@{43} WIP on master: 441170768df Prepare CGAL-4.12-beta1 +stash@{44} On integration: CSS!! +stash@{45} WIP on Installation-improve_CGAL_DEV_MODE-lrineau: 4811fae85c2 Do not document the CGAL pure header-only mode +stash@{46} Mesh_3: debug trick with CGAL_assertion_msg and a lambda +stash@{47} On integration: CTest +stash@{48} On (no branch): a8704de Merge branch 'releases/CGAL-4.10-branch' +stash@{49} On Mesh_3-fix_NaN-lrineau: DEBUG Sliver_perturber +stash@{50} On Mesh_2-restore_Qt3_demo-lrineau: Doxygen warnings +stash@{51} On integration: Debug Mesh_2 +stash@{52} On Mesh_3-API_with_incidences-GF: e17da6445d1 Write the documentation +stash@{53} On Mesh_3-test_polyhedral_complex_with_surface_mesh-GF: TESTS +stash@{54} ? +stash@{55} On Mesh_3-fix_bug_1944-GF: 4325f22 Merge pull request #2145 from gdamiand/patch-1 +stash@{56} On integration: a5ea993 Merge remote-tracking branch 'cgal/master' into integration +stash@{57} On Polyhedron_demo-Use_sm_in_Deformation-GF: Selection plugin, pb ODR? +stash@{58} On Polyhedron-clipping_snapping_new_snapping-GF-wip: 23e0762 fixup! Add a safety check +stash@{59} On Polyhedron-clipping_snapping_new_snapping-GF-wip: cbfc043 Revert "wip" +stash@{60} On Polyhedron-clipping_snapping_new_snapping-GF-wip: 720086f Add snap_corners_to_curves_when_possible +stash@{61} On (no branch): Debug Mesh_3 +stash@{62} WIP on Polyhedron-clipping_snapping_new_snapping-GF-wip: 50d11a6 Move get_curve_id to Clipping_snapping_tool_details +stash@{63} On Polyhedron-clipping_snapping_new_snapping-GF-wip: WIP on fix corner-to-curve +stash@{64} WIP on Polyhedron-clipping_snapping_new_snapping-GF-wip: 26e2d29 Add missing `#include` +stash@{65} On integration: c540a7e Merge pull request #1808 from MaelRL/Spatial_searching-Fix_fuzzy_query_item_border +stash@{66} WIP on integration: c540a7e Merge pull request #1808 from MaelRL/Spatial_searching-Fix_fuzzy_query_item_border +stash@{67} WIP on integration: c540a7e Merge pull request #1808 from MaelRL/Spatial_searching-Fix_fuzzy_query_item_border +stash@{68} WIP on integration: c540a7e Merge pull request #1808 from MaelRL/Spatial_searching-Fix_fuzzy_query_item_border +stash@{69} WIP on integration: c540a7e Merge pull request #1808 from MaelRL/Spatial_searching-Fix_fuzzy_query_item_border +stash@{70} More assertion in multi-thread Handle.h +stash@{71} CMake: if(NOT CMAKE_CROSSCOMPILING) +stash@{72} Bug Mesh_3 TROU! +stash@{73} WIP on Polyhedron-clipping_snapping_new_snapping-GF-wip: 4f429fa Merge remote-tracking branch 'cgal/master' into Polyhedron-clipping_snapping_new_snapping-GF-wip +stash@{74} On master: convert an image from unsigned short to float +stash@{75} On master: Mesh_3 Robust_weighted_circumcenter_filtered_traits_3 use certainly +stash@{76} On CGAL-remove_support_for_LEDA_5_and_before-GF: 0c69001 Remove all usage of CGAL_LEDA_VERSION +stash@{77} WIP on Mesh_3-new_facet_criterion_with_normals-lrineau: c4b81cf Fix a warning in Sizing_field_with_aabb_tree +stash@{78} On CGAL-license_check-GF: 366976b fix header +stash@{79} Polyhedron demo with keywords for plugins +stash@{80} Mesh_3: save, load a C3t3 and refine it +stash@{81} On master: 2153e65 Fix a typo in doc: remove extra "`" +stash@{82} On Mesh_3-hybrid_mesh_domain-GF: Shifted_sphere_implicit_function +stash@{83} On CGAL_headers_only_step1-gdamiand_cjamin: Fix an error in headers-only +stash@{84} Bug Intel 2017 +stash@{85} WIP on Mesh_3-improve_polylines_to_protect-GF: ee0fb3b Fix the header guard macro, and copyright years +stash@{86} On master: Restore CGAL_Qt3 +stash@{87} On Mesh_2-fix_issue_781-GF: Mesh_2: Display queues sizes +stash@{88} On Mesh_3-improve_images-GF: "Fix" C3t3_io_plugin to deal with INT_MIN +stash@{89} WIP on Polyhedron-clipping_snapping_new_snapping-GF-wip: 7787959 Re-test `modified_features` after a corner-snapping +stash@{90} On Mesh_3-experimental-GF: Experiments on Mesh-3 +stash@{91} On master: Fix orient polygon soup with PMP, temp +stash@{92} On CGAL-Qt5_support-GF: Replace gluErrorString +stash@{93} On master: Mesh_3, for pipeNotWorking +stash@{94} On master: Mesh_3 for Medicim/Nobelbiocare +stash@{95} WIP on Mesh_3-experimental-GF: a1b342e Allow to open a binary CDT_3 +stash@{96} WIP on master: 0df4095 Merge pull request #30 from afabri/Documentation-addHome-GF +stash@{97} WIP on CGAL-Qt5_support-GF: 0d2f838 Allow to find QGLViewer-qt5_ +stash@{98} On master: LICENSE (Dijsktra), Memory_size.h (near) +stash@{99} On Triangulation_2-Fix_CDT_plus-GF: wip +stash@{100} On master: Pretty printers, et Sliver_perturber.h +stash@{101} On master: bench mesh_3 +stash@{102} On Intersection_3-fix-do_intersect_Iso_cuboid_3_Segment_3-lrineau: Fix intersection(Iso_cuboid_3, Segment_3) +stash@{103} On master: Try to fix warnings for CMap + +Recent commits +97123fc3c72 cgal/master Merge branch 'releases/CGAL-5.0-branch' +871c97273af Merge pull request #4496 from lrineau/CGAL-move_semantic_for_triangulations-GF +a828cb0d066 Merge pull request #4620 from janetournois/Tetrahedral_remeshing-new-jtournois +8db45039044 Merge pull request #4710 from danston/CGAL-clangmp_bug_fix-danston +c15030bf39b Merge pull request #4740 from afabri/T2-low_dimensional-GF +814689552b1 Merge pull request #4752 from lrineau/CGAL-fix_cpp20-mglisse_GF +863b1decf69 Merge pull request #4754 from maxGimeno/PMP-Fix_parallel_haussdorf_dist-maxGimeno +4354b2c87f0 releases/CGAL-5.0-branch cgal/releases/CGAL-5.0-branch Merge pull request #4710 from danston/CGAL-clangmp_bug_fix-danston +dc2ae1614c2 Merge remote-tracking branch 'cgal/releases/CGAL-4.14-branch' into releases/CGAL-5.0-branch +520fbf7c4b7 refs/pull/4754/head Add missing include diff --git a/Installation/include/CGAL/version.h b/Installation/include/CGAL/version.h index 85ff9e71cad..97b71ba536d 100644 --- a/Installation/include/CGAL/version.h +++ b/Installation/include/CGAL/version.h @@ -17,7 +17,7 @@ #define CGAL_VERSION_H #ifndef SWIG -#define CGAL_VERSION 5.1 +#define CGAL_VERSION 5.1-beta1 #define CGAL_GIT_HASH abcdef #endif #define CGAL_VERSION_NR 1050100000 diff --git a/Installation/lib/cmake/CGAL/CGALConfigVersion.cmake b/Installation/lib/cmake/CGAL/CGALConfigVersion.cmake index bfc6a1fa17d..9c109123e0c 100644 --- a/Installation/lib/cmake/CGAL/CGALConfigVersion.cmake +++ b/Installation/lib/cmake/CGAL/CGALConfigVersion.cmake @@ -1,7 +1,7 @@ set(CGAL_MAJOR_VERSION 5) set(CGAL_MINOR_VERSION 1) set(CGAL_BUGFIX_VERSION 0) -set(CGAL_VERSION_PUBLIC_RELEASE_VERSION "5.1-dev") +set(CGAL_VERSION_PUBLIC_RELEASE_VERSION "5.1-beta1") set(CGAL_VERSION_PUBLIC_RELEASE_NAME "CGAL-${CGAL_VERSION_PUBLIC_RELEASE_VERSION}") if (CGAL_BUGFIX_VERSION AND CGAL_BUGFIX_VERSION GREATER 0) From 45343e39a001d2dbbf3155ccfb4fd45f40a55705 Mon Sep 17 00:00:00 2001 From: Maxime Gimeno Date: Thu, 4 Jun 2020 09:55:23 +0200 Subject: [PATCH 495/568] Protect std::max --- .../include/CGAL/Polygon_mesh_processing/distance.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/distance.h b/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/distance.h index d85c07a8566..08f6d8c997d 100644 --- a/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/distance.h +++ b/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/distance.h @@ -117,7 +117,7 @@ struct Distance_computation{ distance = hdist; } - void join( Distance_computation& rhs ) {distance = std::max(rhs.distance, distance); } + void join( Distance_computation& rhs ) {distance = (std::max)(rhs.distance, distance); } }; #endif From ec2f3f2fa96ecb5c1447052ac706ff72b8fecd91 Mon Sep 17 00:00:00 2001 From: Maxime Gimeno Date: Thu, 4 Jun 2020 10:15:34 +0200 Subject: [PATCH 496/568] Fix brew doc about cgal-qt5 which doesn't exist --- Documentation/doc/Documentation/Usage.txt | 6 ------ 1 file changed, 6 deletions(-) diff --git a/Documentation/doc/Documentation/Usage.txt b/Documentation/doc/Documentation/Usage.txt index 38d2b257697..247348cab68 100644 --- a/Documentation/doc/Documentation/Usage.txt +++ b/Documentation/doc/Documentation/Usage.txt @@ -60,12 +60,6 @@ On most operating systems, package managers offer \cgal and its essential third On macOS, we recommend using of Homebrew in the following way: brew install cgal - brew install cgal-qt5 #(only for GUI) - -You should check that cgal and cgal-qt5 are correctly "linked", especially when upgrading from an old version. If not, run the following command: - - brew link cgal - brew link cgal-qt5 #(if you installed it) On Linux distributions such as `Debian`/`Ubuntu`/`Mint`, use `apt-get` in the following way: From 96cbb19f0be92c71a5bf0bcd149a2daabee8a823 Mon Sep 17 00:00:00 2001 From: Maxime Gimeno Date: Thu, 4 Jun 2020 10:15:34 +0200 Subject: [PATCH 497/568] Fix brew doc about cgal-qt5 which doesn't exist --- Documentation/doc/Documentation/Usage.txt | 6 ------ 1 file changed, 6 deletions(-) diff --git a/Documentation/doc/Documentation/Usage.txt b/Documentation/doc/Documentation/Usage.txt index 38d2b257697..247348cab68 100644 --- a/Documentation/doc/Documentation/Usage.txt +++ b/Documentation/doc/Documentation/Usage.txt @@ -60,12 +60,6 @@ On most operating systems, package managers offer \cgal and its essential third On macOS, we recommend using of Homebrew in the following way: brew install cgal - brew install cgal-qt5 #(only for GUI) - -You should check that cgal and cgal-qt5 are correctly "linked", especially when upgrading from an old version. If not, run the following command: - - brew link cgal - brew link cgal-qt5 #(if you installed it) On Linux distributions such as `Debian`/`Ubuntu`/`Mint`, use `apt-get` in the following way: From a86712d1aae9a1a6d2004db3fc8fcdac6ef6b782 Mon Sep 17 00:00:00 2001 From: Thomas Krijnen Date: Sun, 7 Jun 2020 15:25:18 +0200 Subject: [PATCH 498/568] Don't segfault on empty Nef_nary_x --- Nef_3/include/CGAL/Nef_nary_intersection_3.h | 3 ++- Nef_3/include/CGAL/Nef_nary_union_3.h | 3 ++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/Nef_3/include/CGAL/Nef_nary_intersection_3.h b/Nef_3/include/CGAL/Nef_nary_intersection_3.h index 70fc5791fae..5178705dc2f 100644 --- a/Nef_3/include/CGAL/Nef_nary_intersection_3.h +++ b/Nef_3/include/CGAL/Nef_nary_intersection_3.h @@ -52,7 +52,8 @@ class Nef_nary_intersection_3 { } Polyhedron get_intersection() { - + if (queue.empty()) + return empty; while(queue.size() > 1) intersect(); inserted = 0; diff --git a/Nef_3/include/CGAL/Nef_nary_union_3.h b/Nef_3/include/CGAL/Nef_nary_union_3.h index ecbbae2db59..c8663bb911b 100644 --- a/Nef_3/include/CGAL/Nef_nary_union_3.h +++ b/Nef_3/include/CGAL/Nef_nary_union_3.h @@ -52,7 +52,8 @@ class Nef_nary_union_3 { } Polyhedron get_union() { - + if (queue.empty()) + return empty; while(queue.size() > 1) unite(); inserted = 0; From 1d4d3efcc9b0f91db8e5c962b0dc59614212b502 Mon Sep 17 00:00:00 2001 From: Maxime Gimeno Date: Mon, 8 Jun 2020 10:38:58 +0200 Subject: [PATCH 499/568] Remove useless timer call --- AABB_tree/demo/AABB_tree/Scene.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/AABB_tree/demo/AABB_tree/Scene.cpp b/AABB_tree/demo/AABB_tree/Scene.cpp index b28368d39a6..deba0b8b130 100644 --- a/AABB_tree/demo/AABB_tree/Scene.cpp +++ b/AABB_tree/demo/AABB_tree/Scene.cpp @@ -45,7 +45,6 @@ Scene::Scene() m_blue_ramp.build_blue(); m_max_distance_function = (FT)0.0; texture = new Texture(m_grid_size,m_grid_size); - startTimer(0); ready_to_cut = false; are_buffers_initialized = false; gl_init = false; From 2395583fd76f2c513691b8dfdfd1bfbd15e749ba Mon Sep 17 00:00:00 2001 From: Maxime Gimeno Date: Mon, 8 Jun 2020 11:00:38 +0200 Subject: [PATCH 500/568] setup a singleshot for the planes --- AABB_tree/demo/AABB_tree/Scene.cpp | 20 +++++++++----------- AABB_tree/demo/AABB_tree/Scene.h | 4 ++-- 2 files changed, 11 insertions(+), 13 deletions(-) diff --git a/AABB_tree/demo/AABB_tree/Scene.cpp b/AABB_tree/demo/AABB_tree/Scene.cpp index deba0b8b130..69ba683a21b 100644 --- a/AABB_tree/demo/AABB_tree/Scene.cpp +++ b/AABB_tree/demo/AABB_tree/Scene.cpp @@ -45,7 +45,7 @@ Scene::Scene() m_blue_ramp.build_blue(); m_max_distance_function = (FT)0.0; texture = new Texture(m_grid_size,m_grid_size); - ready_to_cut = false; + ready_to_cut = true; are_buffers_initialized = false; gl_init = false; @@ -518,6 +518,7 @@ void Scene::changed() compute_elements(_UNSIGNED); else compute_elements(_SIGNED); + ready_to_cut=false; are_buffers_initialized = false; } @@ -1225,12 +1226,16 @@ void Scene::cut_segment_plane() m_cut_plane = CUT_SEGMENTS; changed(); } +void Scene::updateCutPlane() +{ + ready_to_cut = true; + QTimer::singleShot(0,this,SLOT(cutting_plane())); +} void Scene::cutting_plane(bool override) { if(ready_to_cut || override) { - ready_to_cut = false; switch( m_cut_plane ) { case UNSIGNED_FACETS: @@ -1303,13 +1308,13 @@ void Scene::refine_loop() void Scene::activate_cutting_plane() { - connect(m_frame, SIGNAL(modified()), this, SLOT(cutting_plane())); + connect(m_frame, SIGNAL(modified()), this, SLOT(updateCutPlane())); m_view_plane = true; } void Scene::deactivate_cutting_plane() { - disconnect(m_frame, SIGNAL(modified()), this, SLOT(cutting_plane())); + disconnect(m_frame, SIGNAL(modified()), this, SLOT(updateCutPlane())); m_view_plane = false; } void Scene::initGL() @@ -1325,10 +1330,3 @@ void Scene::initGL() compile_shaders(); gl_init = true; } - -void Scene::timerEvent(QTimerEvent *) -{ - if(manipulatedFrame()->isSpinning()) - set_fast_distance(true); - ready_to_cut = true; -} diff --git a/AABB_tree/demo/AABB_tree/Scene.h b/AABB_tree/demo/AABB_tree/Scene.h index 4e9fabd735b..95ea74cdc33 100644 --- a/AABB_tree/demo/AABB_tree/Scene.h +++ b/AABB_tree/demo/AABB_tree/Scene.h @@ -173,6 +173,8 @@ private: void attrib_buffers(CGAL::QGLViewer*); void compile_shaders(); void compute_texture(int, int, Color_ramp, Color_ramp); +private slots: + void updateCutPlane(); public: // file menu @@ -251,8 +253,6 @@ public: void activate_cutting_plane(); void deactivate_cutting_plane(); - //timer sends a top when all the events are finished - void timerEvent(QTimerEvent *); public slots: From 8e21da2b91dfb35ed76c604446aa8bc790bd9d90 Mon Sep 17 00:00:00 2001 From: Maxime Gimeno Date: Mon, 8 Jun 2020 16:31:46 +0200 Subject: [PATCH 501/568] Fix typo. --- .../demo/Polyhedron/Plugins/IO/Implicit_function_io_plugin.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Polyhedron/demo/Polyhedron/Plugins/IO/Implicit_function_io_plugin.cpp b/Polyhedron/demo/Polyhedron/Plugins/IO/Implicit_function_io_plugin.cpp index 1a02765e9f8..58f19006f7c 100644 --- a/Polyhedron/demo/Polyhedron/Plugins/IO/Implicit_function_io_plugin.cpp +++ b/Polyhedron/demo/Polyhedron/Plugins/IO/Implicit_function_io_plugin.cpp @@ -96,7 +96,7 @@ init(QMainWindow* mainWindow, CGAL::Three::Scene_interface* scene_interface, Mes QMenu* menu = menuFile->findChild("menuGenerateObject"); if(!menu){ QAction* actionLoad = mw->findChild("actionLoadPlugin"); - menu = new QMenu(tr("Generate &Objet"), menuFile); + menu = new QMenu(tr("Generate &Object"), menuFile); menu->setObjectName("menuGenerateObject"); menuFile->insertMenu(actionLoad, menu); } From 4b23afeb49937cff39315704ebde278e68fe6aa3 Mon Sep 17 00:00:00 2001 From: Laurent Rineau Date: Tue, 9 Jun 2020 18:18:03 +0200 Subject: [PATCH 502/568] updated crontab (automated commit) --- Maintenance/infrastructure/cgal.geometryfactory.com/crontab | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Maintenance/infrastructure/cgal.geometryfactory.com/crontab b/Maintenance/infrastructure/cgal.geometryfactory.com/crontab index 9cb5c94bfc7..8de3a49b3ae 100644 --- a/Maintenance/infrastructure/cgal.geometryfactory.com/crontab +++ b/Maintenance/infrastructure/cgal.geometryfactory.com/crontab @@ -23,13 +23,13 @@ LC_CTYPE=en_US.UTF-8 # The script also updates the manual tools. # "master" alone -0 21 * * Sun cd $HOME/CGAL/create_internal_release && /usr/bin/time scl enable rh-git29 -- $HOME/bin/create_release $HOME/CGAL/branches/master.git --do-it --beta 1 --public || echo ERROR +0 21 * * Sun cd $HOME/CGAL/create_internal_release && /usr/bin/time scl enable rh-git29 -- $HOME/bin/create_release $HOME/CGAL/branches/master.git --do-it --beta 2 --public || echo ERROR # "integration" -0 21 * * Mon,Tue,Wed,Thu,Fri cd $HOME/CGAL/create_internal_release && /usr/bin/time scl enable rh-git29 -- $HOME/bin/create_release $HOME/CGAL/branches/integration.git $HOME/CGAL/branches/empty-dir --do-it --beta 1 --public || echo ERROR +0 21 * * Mon,Wed,Thu,Fri cd $HOME/CGAL/create_internal_release && /usr/bin/time scl enable rh-git29 -- $HOME/bin/create_release $HOME/CGAL/branches/integration.git $HOME/CGAL/branches/empty-dir --do-it --beta 2 --public || echo ERROR # from branch 5.0 0 21 * * Sat cd $HOME/CGAL/create_internal_release-5.0-branch && /usr/bin/time scl enable rh-git29 -- $HOME/bin/create_release $HOME/CGAL/branches/CGAL-5.0-branch.git --public --do-it || echo ERROR # from branch 4.14 -#0 21 * * Sat cd $HOME/CGAL/create_internal_release-4.14-branch && /usr/bin/time scl enable rh-git29 -- $HOME/bin/create_release $HOME/CGAL/branches/CGAL-4.14-branch.git --public --do-it || echo ERROR +0 21 * * Tue cd $HOME/CGAL/create_internal_release-4.14-branch && /usr/bin/time scl enable rh-git29 -- $HOME/bin/create_release $HOME/CGAL/branches/CGAL-4.14-branch.git --public --do-it || echo ERROR ## Older stuff # from branch 4.13 From ec1dd745e0312ac548e28de20386ce9af2e1c5b1 Mon Sep 17 00:00:00 2001 From: Laurent Rineau Date: Tue, 9 Jun 2020 18:27:39 +0200 Subject: [PATCH 503/568] Remove cpp11::(tuple|get) And use `#ifdef CGAL_NO_DEPRECATED_CODE` around the backward compatibility code in ``. --- Installation/include/CGAL/config.h | 3 ++- .../include/CGAL/Orthogonal_incremental_neighbor_search.h | 2 +- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/Installation/include/CGAL/config.h b/Installation/include/CGAL/config.h index d70989b2ffb..f2b3b400d34 100644 --- a/Installation/include/CGAL/config.h +++ b/Installation/include/CGAL/config.h @@ -619,6 +619,7 @@ using std::max; // // Compatibility with CGAL-4.14. +#ifndef CGAL_NO_DEPRECATED_CODE // // That is temporary, and will be replaced by a namespace alias, as // soon as we can remove cpp11::result_of, and and @@ -655,7 +656,7 @@ namespace CGAL { using cpp11::array; using cpp11::copy_n; } // end of the temporary compatibility with CGAL-4.14 - +#endif // CGAL_NO_DEPRECATED_CODE namespace CGAL { // Typedef for the type of nullptr. diff --git a/Spatial_searching/include/CGAL/Orthogonal_incremental_neighbor_search.h b/Spatial_searching/include/CGAL/Orthogonal_incremental_neighbor_search.h index d161e6a36fe..203b914bcc3 100644 --- a/Spatial_searching/include/CGAL/Orthogonal_incremental_neighbor_search.h +++ b/Spatial_searching/include/CGAL/Orthogonal_incremental_neighbor_search.h @@ -23,7 +23,7 @@ #include #include #include -#include +#include // std::get for tuple namespace CGAL { From e6536aaf633acf14328ec2c26e4274e3c6fc1852 Mon Sep 17 00:00:00 2001 From: Laurent Rineau Date: Tue, 9 Jun 2020 20:15:16 +0200 Subject: [PATCH 504/568] Remove cpp11::(tuple|get) And use `#ifdef CGAL_NO_DEPRECATED_CODE` around the backward compatibility code in ``. --- Combinatorial_map/include/CGAL/Combinatorial_map.h | 5 +++-- Generalized_map/include/CGAL/Generalized_map.h | 5 +++-- .../include/CGAL/Orthogonal_incremental_neighbor_search.h | 4 ++-- .../Surface_mesh_topology/internal/Generic_map_selector.h | 4 +++- .../Surface_mesh_topology/internal/Minimal_quadrangulation.h | 3 ++- .../path_with_rle_deformation_tests.cpp | 3 ++- .../test/Surface_mesh_topology/test_homotopy.cpp | 3 ++- 7 files changed, 17 insertions(+), 10 deletions(-) diff --git a/Combinatorial_map/include/CGAL/Combinatorial_map.h b/Combinatorial_map/include/CGAL/Combinatorial_map.h index f45a2864e13..580444e9812 100644 --- a/Combinatorial_map/include/CGAL/Combinatorial_map.h +++ b/Combinatorial_map/include/CGAL/Combinatorial_map.h @@ -41,6 +41,7 @@ #include #include #include +#include #include #include #include @@ -439,7 +440,7 @@ namespace CGAL { bool copy_perforated_darts=false, size_type mark_perforated=INVALID_MARK) { - CGAL::cpp11::tuple<> converters; + std::tuple<> converters; copy(amap, origin_to_copy, copy_to_origin, converters, copy_perforated_darts, mark_perforated); } @@ -454,7 +455,7 @@ namespace CGAL { bool copy_perforated_darts=false, size_type mark_perforated=INVALID_MARK) { - CGAL::cpp11::tuple<> converters; + std::tuple<> converters; copy_from_const(amap, origin_to_copy, copy_to_origin, converters, copy_perforated_darts, mark_perforated); } diff --git a/Generalized_map/include/CGAL/Generalized_map.h b/Generalized_map/include/CGAL/Generalized_map.h index eac7342dac5..3c79b6d2c37 100644 --- a/Generalized_map/include/CGAL/Generalized_map.h +++ b/Generalized_map/include/CGAL/Generalized_map.h @@ -31,6 +31,7 @@ #include #include #include +#include #include #include #include @@ -403,7 +404,7 @@ namespace CGAL { bool copy_perforated_darts=false, size_type mark_perforated=INVALID_MARK) { - CGAL::cpp11::tuple<> converters; + std::tuple<> converters; copy(amap, origin_to_copy, copy_to_origin, converters, copy_perforated_darts, mark_perforated); } @@ -418,7 +419,7 @@ namespace CGAL { bool copy_perforated_darts=false, size_type mark_perforated=INVALID_MARK) { - CGAL::cpp11::tuple<> converters; + std::tuple<> converters; copy_from_const(amap, origin_to_copy, copy_to_origin, converters, copy_perforated_darts, mark_perforated); } diff --git a/Spatial_searching/include/CGAL/Orthogonal_incremental_neighbor_search.h b/Spatial_searching/include/CGAL/Orthogonal_incremental_neighbor_search.h index 588886660e1..28eaaae9d8c 100644 --- a/Spatial_searching/include/CGAL/Orthogonal_incremental_neighbor_search.h +++ b/Spatial_searching/include/CGAL/Orthogonal_incremental_neighbor_search.h @@ -290,7 +290,7 @@ namespace CGAL { bool next_neighbour_found; if (!(PriorityQueue.empty())) { - rd = CGAL::cpp11::get<1>(*PriorityQueue.top()); + rd = std::get<1>(*PriorityQueue.top()); next_neighbour_found = (search_furthest ? multiplication_factor*rd < Item_PriorityQueue.top()->second : multiplication_factor*rd > Item_PriorityQueue.top()->second); @@ -325,7 +325,7 @@ namespace CGAL { bool next_neighbour_found; if (!(PriorityQueue.empty())) { - rd = CGAL::cpp11::get<1>(*PriorityQueue.top()); + rd = std::get<1>(*PriorityQueue.top()); next_neighbour_found = (search_furthest ? multiplication_factor*rd < Item_PriorityQueue.top()->second : multiplication_factor*rd > Item_PriorityQueue.top()->second); diff --git a/Surface_mesh_topology/include/CGAL/Surface_mesh_topology/internal/Generic_map_selector.h b/Surface_mesh_topology/include/CGAL/Surface_mesh_topology/internal/Generic_map_selector.h index 4cca50217f7..fcc5322c084 100644 --- a/Surface_mesh_topology/include/CGAL/Surface_mesh_topology/internal/Generic_map_selector.h +++ b/Surface_mesh_topology/include/CGAL/Surface_mesh_topology/internal/Generic_map_selector.h @@ -22,6 +22,8 @@ #include #include +#include + namespace CGAL { namespace Surface_mesh_topology { namespace internal { @@ -32,7 +34,7 @@ namespace internal { struct Dart_wrapper { using Vertex_attribute = CGAL::Cell_attribute; - using Attributes = CGAL::cpp11::tuple; + using Attributes = std::tuple; }; }; diff --git a/Surface_mesh_topology/include/CGAL/Surface_mesh_topology/internal/Minimal_quadrangulation.h b/Surface_mesh_topology/include/CGAL/Surface_mesh_topology/internal/Minimal_quadrangulation.h index 1506ec864e9..4481eebc353 100644 --- a/Surface_mesh_topology/include/CGAL/Surface_mesh_topology/internal/Minimal_quadrangulation.h +++ b/Surface_mesh_topology/include/CGAL/Surface_mesh_topology/internal/Minimal_quadrangulation.h @@ -30,6 +30,7 @@ #include #include #include +#include #include namespace CGAL { @@ -45,7 +46,7 @@ struct Minimal_quadrangulation_local_map_items typedef std::size_t Dart_info; #endif // CGAL_PWRLE_TURN_V3 typedef CGAL::Cell_attribute Vertex_attribute; - typedef CGAL::cpp11::tuple Attributes; + typedef std::tuple Attributes; }; }; diff --git a/Surface_mesh_topology/test/Surface_mesh_topology/path_with_rle_deformation_tests.cpp b/Surface_mesh_topology/test/Surface_mesh_topology/path_with_rle_deformation_tests.cpp index 90a17e8f79b..e50a45c1587 100644 --- a/Surface_mesh_topology/test/Surface_mesh_topology/path_with_rle_deformation_tests.cpp +++ b/Surface_mesh_topology/test/Surface_mesh_topology/path_with_rle_deformation_tests.cpp @@ -5,6 +5,7 @@ #include #include #include +#include #include "Creation_of_test_cases_for_paths.h" @@ -22,7 +23,7 @@ struct MyItems typedef std::size_t Dart_info; #endif // CGAL_PWRLE_TURN_V3 typedef CGAL::Cell_attribute_with_point Vertex_attrib; - typedef CGAL::cpp11::tuple Attributes; + typedef std::tuple Attributes; }; }; diff --git a/Surface_mesh_topology/test/Surface_mesh_topology/test_homotopy.cpp b/Surface_mesh_topology/test/Surface_mesh_topology/test_homotopy.cpp index 6a95e7a3f26..19af0dc1677 100644 --- a/Surface_mesh_topology/test/Surface_mesh_topology/test_homotopy.cpp +++ b/Surface_mesh_topology/test/Surface_mesh_topology/test_homotopy.cpp @@ -5,6 +5,7 @@ #include #include #include +#include #include "Creation_of_test_cases_for_paths.h" @@ -22,7 +23,7 @@ struct MyItems typedef std::size_t Dart_info; #endif // CGAL_PWRLE_TURN_V3 typedef CGAL::Cell_attribute_with_point Vertex_attrib; - typedef CGAL::cpp11::tuple Attributes; + typedef std::tuple Attributes; }; }; From ec6c0d67589ba44b24227691be1dc5e794344306 Mon Sep 17 00:00:00 2001 From: Laurent Rineau Date: Tue, 9 Jun 2020 22:15:45 +0200 Subject: [PATCH 505/568] Prepare for 5.1-beta2 --- Installation/include/CGAL/version.h | 4 ++-- Installation/lib/cmake/CGAL/CGALConfigVersion.cmake | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/Installation/include/CGAL/version.h b/Installation/include/CGAL/version.h index 97b71ba536d..26a92686edd 100644 --- a/Installation/include/CGAL/version.h +++ b/Installation/include/CGAL/version.h @@ -17,12 +17,12 @@ #define CGAL_VERSION_H #ifndef SWIG -#define CGAL_VERSION 5.1-beta1 +#define CGAL_VERSION 5.1-beta2 #define CGAL_GIT_HASH abcdef #endif #define CGAL_VERSION_NR 1050100000 #define CGAL_SVN_REVISION 99999 -#define CGAL_RELEASE_DATE 20191108 +#define CGAL_RELEASE_DATE 20200609 #include diff --git a/Installation/lib/cmake/CGAL/CGALConfigVersion.cmake b/Installation/lib/cmake/CGAL/CGALConfigVersion.cmake index 9c109123e0c..e0ff35433ce 100644 --- a/Installation/lib/cmake/CGAL/CGALConfigVersion.cmake +++ b/Installation/lib/cmake/CGAL/CGALConfigVersion.cmake @@ -1,7 +1,7 @@ set(CGAL_MAJOR_VERSION 5) set(CGAL_MINOR_VERSION 1) set(CGAL_BUGFIX_VERSION 0) -set(CGAL_VERSION_PUBLIC_RELEASE_VERSION "5.1-beta1") +set(CGAL_VERSION_PUBLIC_RELEASE_VERSION "5.1-beta2") set(CGAL_VERSION_PUBLIC_RELEASE_NAME "CGAL-${CGAL_VERSION_PUBLIC_RELEASE_VERSION}") if (CGAL_BUGFIX_VERSION AND CGAL_BUGFIX_VERSION GREATER 0) From b320d8ea0249f22279fcb123117f8edf31765d2e Mon Sep 17 00:00:00 2001 From: Simon Giraudot Date: Wed, 10 Jun 2020 09:37:12 +0200 Subject: [PATCH 506/568] Fix documentation of hierarchy simplify point set --- .../include/CGAL/hierarchy_simplify_point_set.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Point_set_processing_3/include/CGAL/hierarchy_simplify_point_set.h b/Point_set_processing_3/include/CGAL/hierarchy_simplify_point_set.h index c1e33abe9fb..0ee419a5e00 100644 --- a/Point_set_processing_3/include/CGAL/hierarchy_simplify_point_set.h +++ b/Point_set_processing_3/include/CGAL/hierarchy_simplify_point_set.h @@ -118,7 +118,7 @@ namespace CGAL { \ingroup PkgPointSetProcessing3Algorithms Recursively split the point set in smaller clusters until the - clusters have less than `size` elements or until their variation + clusters have less than `size` elements and until their variation factor is below `var_max`. This method modifies the order of input points so as to pack all remaining points first, From 0f63849a434ac3921fba56ba1bd709d4a6887d7c Mon Sep 17 00:00:00 2001 From: Laurent Rineau Date: Wed, 10 Jun 2020 10:08:48 +0200 Subject: [PATCH 507/568] First draft for the announcement mail --- Installation/CHANGES.md | 42 +-- .../announcement/mailing-beta.eml | 353 ++++++++++++++---- 2 files changed, 293 insertions(+), 102 deletions(-) diff --git a/Installation/CHANGES.md b/Installation/CHANGES.md index 0352def2515..14bfe13c5af 100644 --- a/Installation/CHANGES.md +++ b/Installation/CHANGES.md @@ -28,7 +28,7 @@ Release date: July 2020 - This package implements a tetrahedral isotropic remeshing algorithm, that improves the quality of tetrahedra in terms of dihedral angles, - while targetting a given edge length. + while targeting a given edge length. ### [Tutorials](https://doc.cgal.org/5.1/Manual/tutorials.html) @@ -273,13 +273,13 @@ Release date: November 2019 ### [Polygonal Surface Reconstruction](https://doc.cgal.org/5.0/Manual/packages.html#PkgPolygonalSurfaceReconstruction) (new package) - - This package provides a method for piecewise planar object reconstruction from point clouds. - The method takes as input an unordered point set sampled from a piecewise planar object - and outputs a compact and watertight surface mesh interpolating the input point set. - The method assumes that all necessary major planes are provided (or can be extracted from - the input point set using the shape detection method described in Point Set Shape Detection, - or any other alternative methods).The method can handle arbitrary piecewise planar objects - and is capable of recovering sharp features and is robust to noise and outliers. See also + - This package provides a method for piecewise planar object reconstruction from point clouds. + The method takes as input an unordered point set sampled from a piecewise planar object + and outputs a compact and watertight surface mesh interpolating the input point set. + The method assumes that all necessary major planes are provided (or can be extracted from + the input point set using the shape detection method described in Point Set Shape Detection, + or any other alternative methods).The method can handle arbitrary piecewise planar objects + and is capable of recovering sharp features and is robust to noise and outliers. See also the associated [blog entry](https://www.cgal.org/2019/08/05/Polygonal_surface_reconstruction/). ### [Shape Detection](https://doc.cgal.org/5.0/Manual/packages.html#PkgShapeDetection) (major changes) @@ -294,11 +294,11 @@ Release date: November 2019 ### [2D and 3D Linear Geometry Kernel](https://doc.cgal.org/5.0/Manual/packages.html#PkgKernel23) - Added a new concept, [`ComputeApproximateAngle_3`](https://doc.cgal.org/5.0/Kernel_23/classKernel_1_1ComputeApproximateAngle__3.html), to the 3D Kernel concepts to compute the approximate angle between two 3D vectors. Corresponding functors - in the model ([`Compute_approximate_angle_3`](https://doc.cgal.org/5.0/Kernel_23/classKernel.html#a183c9ac358a4ccddc04e680f8ed16c0b)) + in the model ([`Compute_approximate_angle_3`](https://doc.cgal.org/5.0/Kernel_23/classKernel.html#a183c9ac358a4ccddc04e680f8ed16c0b)) and free function ([`approximate_angle`](https://doc.cgal.org/5.0/Kernel_23/group__approximate__angle__grp.html)) have also been added. - - The following objects are now hashable and thus trivially usable - with [`std::unordered_set`](https://en.cppreference.com/w/cpp/container/unordered_set) + - The following objects are now hashable and thus trivially usable + with [`std::unordered_set`](https://en.cppreference.com/w/cpp/container/unordered_set) and [`std::unordered_map`](https://en.cppreference.com/w/cpp/header/unordered_map): `CGAL::Aff_transformation_2`, `CGAL::Aff_transformation_3`, `CGAL::Bbox_2`, `CGAL::Bbox_3`, `CGAL::Circle_2`, @@ -308,11 +308,11 @@ Release date: November 2019 `CGAL::Weighted_point_2` and `CGAL::Weighted_point_3`. ### [Polygon Mesh Processing](https://doc.cgal.org/latest/Manual/packages.html#PkgPolygonMeshProcessing) - - Introduced a [wide range of new functions](https://doc.cgal.org/5.0/Polygon_mesh_processing/index.html#title36) + - Introduced a [wide range of new functions](https://doc.cgal.org/5.0/Polygon_mesh_processing/index.html#title36) related to location of queries on a triangle mesh, such as [`CGAL::Polygon_mesh_processing::locate(Point, Mesh)`](https://doc.cgal.org/5.0/Polygon_mesh_processing/group__PMP__locate__grp.html#gada09bd8740ba69ead9deca597d53cf15). The location of a point on a triangle mesh is expressed as the pair of a face and the barycentric - coordinates of the point in this face, enabling robust manipulation of locations + coordinates of the point in this face, enabling robust manipulation of locations (for example, intersections of two 3D segments living within the same face). - Added the mesh smoothing function [`smooth_mesh()`](https://doc.cgal.org/5.0/Polygon_mesh_processing/group__PMP__meshing__grp.html#gaa0551d546f6ab2cd9402bea12d8332a3), which can be used to improve the quality of triangle elements based on various geometric characteristics. @@ -335,14 +335,14 @@ Release date: November 2019 or vertices appearing in multiple umbrellas) of a mesh. ### [3D Point Set](https://doc.cgal.org/5.0/Manual/packages.html#PkgPointSet3) - - The [PLY IO functions](https://doc.cgal.org/5.0/Point_set_3/group__PkgPointSet3IO.html) now take an additional optional parameter to + - The [PLY IO functions](https://doc.cgal.org/5.0/Point_set_3/group__PkgPointSet3IO.html) now take an additional optional parameter to read/write comments from/in the PLY header. ### [Point Set Processing](https://doc.cgal.org/latest/Manual/packages.html#PkgPointSetProcessing3) - **Breaking change**: the API using iterators and overloads for optional parameters (deprecated since CGAL 4.12) has been removed. The current (and now only) API uses ranges and Named Parameters. - Added the possibility to use the named parameter - [`neighbor_radius`](https://doc.cgal.org/5.0/Point_set_processing_3/group__psp__namedparameters.html#PSP_neighbor_radius) + [`neighbor_radius`](https://doc.cgal.org/5.0/Point_set_processing_3/group__psp__namedparameters.html#PSP_neighbor_radius) to use spherical neighbor queries instead of K-nearest neighbors queries for the following functions: [`CGAL::bilateral_smooth_point_set()`](https://doc.cgal.org/5.0/Point_set_processing_3/group__PkgPointSetProcessing3Algorithms.html#ga4f82723e2f0bb33f3677e29e0208a256), [`CGAL::jet_estimate_normals()`](https://doc.cgal.org/5.0/Point_set_processing_3/group__PkgPointSetProcessing3Algorithms.html#ga0cd0f87de690d4edf82740e856efa491), @@ -385,7 +385,7 @@ Release date: November 2019 ### [3D Triangulations](https://doc.cgal.org/5.0/Manual/packages.html#PkgTriangulation3) - **Breaking change**: The [constructor](https://doc.cgal.org/5.0/Triangulation_3/classCGAL_1_1Triangulation__3.html#a63f67cf6aaadcee14318cf56a36d247a) and the [`insert()`](https://doc.cgal.org/5.0/Triangulation_3/classCGAL_1_1Triangulation__3.html#ad3353128386bbb51f79d0263e7f67337) - function of [`CGAL::Triangulation_3`](https://doc.cgal.org/5.0/Triangulation_3/classCGAL_1_1Triangulation__3.html) + function of [`CGAL::Triangulation_3`](https://doc.cgal.org/5.0/Triangulation_3/classCGAL_1_1Triangulation__3.html) which take a range of points as argument are now guaranteed to insert the points following the order of `InputIterator`. Note that this change only affects the base class `Triangulation_3` @@ -397,14 +397,14 @@ Release date: November 2019 ### [Surface Mesh](https://doc.cgal.org/5.0/Manual/packages.html#PkgSurfaceMesh) - Introduced new functions to read and write using the PLY format, - [`CGAL::read_ply()`](https://doc.cgal.org/5.0/Surface_mesh/group__PkgSurface__mesh.html#ga42f6ad486ddab74e13d3dc53f511c343) - and [`CGAL::write_ply()`](https://doc.cgal.org/5.0/Surface_mesh/group__PkgSurface__mesh.html#ga77bbb79d449c981895eedb6c3c23bd14), + [`CGAL::read_ply()`](https://doc.cgal.org/5.0/Surface_mesh/group__PkgSurface__mesh.html#ga42f6ad486ddab74e13d3dc53f511c343) + and [`CGAL::write_ply()`](https://doc.cgal.org/5.0/Surface_mesh/group__PkgSurface__mesh.html#ga77bbb79d449c981895eedb6c3c23bd14), enabling users to save and load additional property maps of the surface mesh. ### [CGAL and Solvers](https://doc.cgal.org/5.0/Manual/packages.html#PkgSolverInterface) - Added [concepts](https://doc.cgal.org/5.0/Solver_interface/group__PkgSolverInterfaceConcepts.html) - and [models](https://doc.cgal.org/5.0/Solver_interface/group__PkgSolverInterfaceRef.html) - for solving Mixed Integer Programming (MIP) problems with or without constraints. + and [models](https://doc.cgal.org/5.0/Solver_interface/group__PkgSolverInterfaceRef.html) + for solving Mixed Integer Programming (MIP) problems with or without constraints. ### [3D Boolean Operations on Nef Polyhedra](https://doc.cgal.org/5.0/Manual/packages.html#PkgNef3) - Added a function to convert a Nef_polyhedron_3 to a polygon soup: [`CGAL::convert_nef_polyhedron_to_polygon_soup()`](https://doc.cgal.org/5.0/Nef_3/group__PkgNef3IOFunctions.html#ga28a9eb4da0cd6153f0c16f7f9eaf6665) @@ -433,7 +433,7 @@ Release 4.14 Release date: March 2019 ### 2D Periodic Hyperbolic Triangulations (new package) - + - This package allows the computation of Delaunay triangulations of the Bolza surface. The Bolza surface is the most symmetric hyperbolic surface of genus 2. Its fundamental domain is the diff --git a/Maintenance/public_release/announcement/mailing-beta.eml b/Maintenance/public_release/announcement/mailing-beta.eml index 11251b7563a..999c8503444 100644 --- a/Maintenance/public_release/announcement/mailing-beta.eml +++ b/Maintenance/public_release/announcement/mailing-beta.eml @@ -1,111 +1,302 @@ -Subject: CGAL 5.0 Beta 2 Released, Computational Geometry Algorithms Library +Subject: CGAL 5.1 Beta 1 Released, Computational Geometry Algorithms Library Content-Type: text/plain; charset="utf-8" -Body: +Body: -The CGAL Open Source Project is pleased to announce the release 5.0 Beta 2 +The CGAL Open Source Project is pleased to announce the release 5.1 Beta 1 of CGAL, the Computational Geometry Algorithms Library. -CGAL version 5.0 Beta 2 is a public testing release. It should provide a +CGAL version 5.1 Beta 1 is a public testing release. It should provide a solid ground to report bugs that need to be tackled before the release -of the final version of CGAL 5.0 in November. - -The important changes since CGAL 5.0 Beta 1 are the fix of CMake -issues, with header-only installations, and the update of the section -“Getting Started with CGAL” of the documentation. +of the final version of CGAL 5.1 in July. Besides fixes and general enhancement to existing packages, the following -has changed since CGAL 4.14: - -General changes - -- CGAL 5.0 is the first release of CGAL that requires a C++ compiler - with the support of C++14 or later. The new list of supported - compilers is: - - Visual C++ 14.0 (from Visual Studio 2015 Update 3) or later, - - Gnu g++ 6.3 or later (on Linux or MacOS), - - LLVM Clang version 8.0 or later (on Linux or MacOS), and - - Apple Clang compiler versions 7.0.2 and 10.0.1 (on MacOS). -- Since CGAL 4.9, CGAL can be used as a header-only library, with - dependencies. Since CGAL 5.0, that is now the default, unless - specified differently in the (optional) CMake configuration. -- The section “Getting Started with CGAL” of the documentation has - been updated and reorganized. -- The minimal version of Boost is now 1.57.0. - -Polygonal Surface Reconstruction (new package) - -- This package provides a method for piecewise planar object - reconstruction from point clouds. The method takes as input an - unordered point set sampled from a piecewise planar object and - outputs a compact and watertight surface mesh interpolating the - input point set. The method assumes that all necessary major planes - are provided (or can be extracted from the input point set using the - shape detection method described in Point Set Shape Detection, or - any other alternative methods).The method can handle arbitrary - piecewise planar objects and is capable of recovering sharp features - and is robust to noise and outliers. See also the associated blog - entry: - - https://www.cgal.org/2019/08/05/Polygonal_surface_reconstruction/ +has changed since CGAL 5.0: -Shape Detection (major changes) +Surface Mesh Topology (new package) -- BREAKING CHANGE: The concept ShapeDetectionTraits has been renamed - to EfficientRANSACTraits. -- BREAKING CHANGE: The Shape_detection_3 namespace has been renamed to - Shape_detection. -- Added a new, generic implementation of region growing. This enables - for example applying region growing to inputs such as 2D and 3D - point sets, or models of the FaceGraph concept. Learn more about - this new algorithm with this blog entry: - - https://www.cgal.org/2019/07/30/Shape_detection/ +- This package enables the computation of some topological invariants + of surfaces, such as: + - test if two (closed) curves on a combinatorial surface are + homotopic. Users can choose between free homotopy and homotopy + with fixed endpoints; + - test is a curve is contractible; + - compute shortest non-contractible cycles on a surface, with or + without weights on edges. + See also the associated blog entry: + https://www.cgal.org/2020/05/08/Surface_mesh_topology/ + +Optimal Bounding Box (new package) + +- This package implements an optimization algorithm that aims to + construct a close approximation of the _optimal bounding box_ of a + mesh or a point set, which is defined as the smallest (in terms of + volume) bounding box that contains a given mesh or point set. + + See also the associated blog entry: + https://www.cgal.org/2020/04/20/Optimal_bounding_box/ + +Tetrahedral Remeshing (new package) + +- This package implements a tetrahedral isotropic remeshing algorithm, + that improves the quality of tetrahedra in terms of dihedral angles, + while targeting a given edge length. + +Tutorials + +- Two new, detailed tutorials have been added: + - Surface Reconstruction from Point Clouds, which goes over a + typical full processing pipeline in a CGAL environment. + - Geographic Information Systems (GIS), which demonstrates usage + of CGAL data structures and algorithms in the context of a + typical GIS application. + + In both tutorials, complete code is provided. + + See https://doc.cgal.org/5.1/Manual/tutorials.html + +2D and 3D Linear Geometry Kernel + +- Added the functor CompareSignedDistanceToLine_2 to the 2D/3D Kernel + concept to compare the signed distance of two points to a line, or + the line passing through two given points. Corresponding functors in + the model (Compare_signed_distance_to_line_2) are also added. dD Geometry Kernel -- A new exact kernel, Epeck_d, is now available. +- The kernels Epick_d and Epeck_d gain two new functors: + Power_side_of_bounded_power_sphere_d and + Compute_squared_radius_smallest_orthogonal_sphere_d. Those are + essential for the computation of weighted alpha-complexes. +Surface Mesh -2D and 3D Triangulations +- BREAKING CHANGE: The function CGAL::Surface_mesh::clear() now + removes all non-default properties instead of just emptying them. -- BREAKING CHANGE: Several deprecated functions and classes have been - removed. See the full list of breaking changes in the release notes. +CGAL and the Boost Graph Library (BGL) -- BREAKING CHANGE: The constructor and the insert() function of - CGAL::Triangulation_2 or CGAL::Triangulation_3 which take a range of - points as argument are now guaranteed to insert the points following - the order of InputIterator. Note that this change only affects the - base class CGAL::Triangulation_[23] and not any derived class, such - as CGAL::Delaunay_triangulation_[23]. +- Added the function CGAL::alpha_expansion_graphcut(), which + regularizes a multi-label partition over a user-defined graph. +- Added the function CGAL::regularize_face_selection_borders(), which + uses this alpha expansion graphcut to regularize the borders of a + selected faces on a triangle mesh. +- Added the function CGAL::set_triangulation_ids(), which must be used + to initialize vertex, edge, and face indices of a triangulation + meant to be used with BGL algorithms. + +3D Fast Intersection and Distance Computation + +- The behavior of the internal search tree used to accelerate distance + queries has changed: usage of the internal search tree will now be + enabled by default, and its construction will be triggered by the + first distance query. Automatic construction and usage can be + disabled by calling + CGAL::AABB_tree::do_not_accelerate_distance_queries() before the + first distance query, and the tree can be built at any moment by + calling CGAL::AABB_tree::accelerate_distance_queries(). +- BREAKING CHANGE: CGAL::AABB_tree::accelerate_distance_queries() and + CGAL::AABB_tree::do_not_accelerate_distance_queries() are no longer + const functions. + +2D Arrangements + +- Changed intersection return type from legacy CGAL::Object to modern + boost::variant in all traits concepts and models. As there exists an + implicit conversion from boost::variant to CGAL::Object, the new + code is backward compatible. However, it is recommended that all + calls to the intersection functions are fixed to use the new return + type. + +2D Regularized Boolean Set-Operations + +- Changed intersection return type from legacy CGAL::Object to modern + boost::variant in the concept ArrDirectionalTraits::Intersect_2 and + its models. + +2D Minkowski Sums + +- Changed intersection return type from legacy CGAL::Object to modern + boost::variant in the (internally used) model Arr_labeled_traits_2. + +dD Spatial Searching + +- The kd-tree can now be built in parallel: CGAL::Kd_tree::build() is + given an optional template parameter ConcurrencyTag (default value + remains CGAL::Sequential_tag for backward compatibility). +- Improved the performance of the kd-tree in some cases: + - Not storing the points coordinates inside the tree usually + generates a lot of cache misses, leading to non-optimal + performance. This is the case for example when indices are + stored inside the tree, or to a lesser extent when the points + coordinates are stored in a dynamically allocated array (e.g., + Epick_d with dynamic dimension) — we says “to a lesser extent” + because the points are re-created by the kd-tree in a + cache-friendly order after its construction, so the coordinates + are more likely to be stored in a near-optimal order on the + heap. In these cases, the new EnablePointsCache template + parameter of the CGAL::Kd_tree class can be set to + CGAL::Tag_true. The points coordinates will then be cached in an + optimal way. This will increase memory consumption but provides + better search performance. See the updated GeneralDistance and + FuzzyQueryItem concepts for additional requirements when using + such a cache. + - In most cases (e.g., Euclidean distance), the distance + computation algorithm knows before its end that the distance + will be greater than or equal to some given value. This is used + in the (orthogonal) k-NN search to interrupt some distance + computations before its end, saving precious milliseconds, in + particular in medium-to-high dimension. + +Intersecting Sequences of dD Iso-oriented Boxes + +- Added parallel versions of the functions CGAL::box_intersection_d() + and CGAL::box_self_intersection_d(). + +Spatial Sorting + +- Added parallel versions of the functions CGAL::hilbert_sort() and + CGAL::spatial_sort() in 2D and 3D when the median policy is used. + The parallel versions use up to four threads in 2D, and up to eight + threads in 3D. + +3D Convex Hulls + +- A new overload for CGAL::convex_hull_3() that takes a model of + VertexListGraph has been added. +- The long-deprecated function CGAL::convex_hull_3_to_polyhedron_3() + has been removed. The function CGAL::convex_hull_3_to_face_graph() + should be used instead. Polygon Mesh Processing -- Introduced a wide range of new functions related to location of - queries on a triangle mesh, such as - CGAL::Polygon_mesh_processing::locate(Point, Mesh). The location of - a point on a triangle mesh is expressed as the pair of a face and - the barycentric coordinates of the point in this face, enabling - robust manipulation of locations (for example, intersections of two - 3D segments living within the same face). -- Added the mesh smoothing function smooth_mesh(), which can be used - to improve the quality of triangle elements based on various - geometric characteristics. -- Added the shape smoothing function smooth_shape(), which can be used - to smooth the surface of a triangle mesh, using the mean curvature - flow to perform noise removal. - +- Added the function + CGAL::Polygon_mesh_processing::volume_connected_component(), which + can be used to get information about the nesting of the connected + components of a given triangle mesh and about the volumes defined. +- Added the function + CGAL::Polygon_mesh_processing::remove_connected_components_of_negligible_size(), + which can be used to remove connected components whose area or + volume is under a certain threshold. Area and volume thresholds are + either specified by the user or deduced from the bounding box of the + mesh. +- Added a new named parameter for + CGAL::Polygon_mesh_processing::keep_large_connected_components() and + CGAL::Polygon_mesh_processing::remove_connected_components_of_negligible_size, + which can be used to perform a dry run of the operation, meaning + that the function will return the number of connected components + that would be removed with the specified threshold, but without + actually removing them. +- Added the function CGAL::Polygon_mesh_processing::split(), which can + be used to split meshes along a mesh or a plane. +- Added the function + CGAL::Polygon_mesh_processing::split_connected_components() to split + a single mesh containing several connected components into several + meshes containing one connected component. +- Added the functions + CGAL::Polygon_mesh_processing::merge_reversible_connected_components(), + CGAL::Polygon_mesh_processing::duplicate_non_manifold_edges_in_polygon_soup(), + and + CGAL::Polygon_mesh_processing::orient_triangle_soup_with_reference_triangle_mesh(), + which can be helpful when repairing a polygon soup. +- Added the function + CGAL::Polygon_mesh_processing::sample_triangle_soup(), which + generates points on a triangle soup surface. +- Added parallel versions of the functions + CGAL::Polygon_mesh_processing::does_self_intersect() and + CGAL::Polygon_mesh_processing::self_intersections(). +- The function CGAL::Polygon_mesh_processing::stitch_borders() now + returns the number of halfedge pairs that were stitched. +- Added the function + CGAL::Polygon_mesh_processing::polygon_mesh_to_polygon_soup(). +- The function + CGAL::Polygon_mesh_processing::polygon_soup_to_polygon_mesh now + allows passing a point map (for the point range) and a vertex point + map (for the polygon mesh) via named parameters. Point Set Processing -- BREAKING CHANGE: the API using iterators and overloads for optional - parameters (deprecated since CGAL 4.12) has been removed. The - current (and now only) API uses ranges and Named Parameters. +- BREAKING CHANGE: CGAL::remove_outliers() has been parallelized and + thus has a new template parameter ConcurrencyTag. To update your + code simply add as first template parameter CGAL::Sequential_tag or + CGAL::Parallel_tag when calling this function. +- Add a function CGAL::cluster_point_set() that segments a point cloud + into connected components based on a distance threshold. +- Added wrapper functions for registration: + - CGAL::OpenGR::compute_registration_transformation(), which + computes the registration transformation for two point sets + using the Super4PCS algorithm implemented in the third party + library OpenGR. + - CGAL::OpenGR::register_point_sets(), which computes the + registration transformation for two point sets using the + Super4PCS algorithm implemented in the third party library + OpenGR, and registers the points sets by transforming the data + point set using the computed transformation. + - CGAL::pointmatcher::compute_registration_transformation() + computes the registration transformation for two point sets + using ICP algorithm implemented in the third party library + libpointmatcher. + - CGAL::pointmatcher::register_point_sets(), which computes the + registration transformation for two point sets using ICP + algorithm implemented in the third party library + libpointmatcher, and registers the points sets by transforming + the data point set using the computed transformation. -See https://www.cgal.org/2019/10/31/cgal50-beta2/ for a complete list of +2D Triangulations + +- To fix an inconsistency between code and documentation and to + clarify which types of intersections are truly allowed in + constrained Delaunay triangulations, the tag + CGAL::No_intersection_tag has been deprecated in favor of two new + tags: CGAL::No_constraint_intersection_tag and + CGAL::No_constraint_intersection_requiring_constructions_tag. The + latter is equivalent to the now-deprecated + CGAL::No_intersection_tag, and allows constraints to intersect as + long as no new point has to be created to represent that + intersection (for example, the intersection of two constraint + segments in a ‘T’-like junction is an existing point and as such + does not require any new construction). The former tag, + CGAL::No_constraint_intersection_tag, does not allow any + intersection, except for the configuration of two constraints having + a single common endpoints, for convience. +- Added the function + CGAL::split_subconstraint_graph_into_constraints() to + Constrained_triangulation_plus_2 to initialize the constraints from + a soup of disconnected segments that should first be split into + polylines. + +3D Triangulations + +- The member function CGAL::Triangulation_3::file_input() have been + added. It allows to load a CGAL::Triangulation_3 from an input + stream, using functors to create vertices and cells. + +3D Triangulation Data Structure + +- The member function CGAL::TDS_3::file_input() have been added. It + allows to load a CGAL::Triangulation_data_structure_3 from an input + stream, using functors to create vertices and cells. + +Surface Mesh Simplification + +- Added a new simplification method based on the quadric error defined + by Garland and Heckbert. +- The concept EdgeProfile has been removed. This concept was not + actually in use as the CGAL-provided model CGAL::Edge_profile was + imposed to the user. Other concepts have been clarified to reflect + the fact that the API uses this particular class. + +STL Extensions for CGAL + +- Added a new concurrency tag: CGAL::Parallel_if_available_tag. This + tag is a convenience typedef to CGAL::Parallel_tag if the third + party library TBB has been found and linked with, and to + CGAL::Sequential_tag otherwise. + +See https://www.cgal.org/2020/06/09/cgal51-beta1/ for a complete list of changes. From d127be9d84e4ec1e2c50206b2b5cbe377bcd1eb5 Mon Sep 17 00:00:00 2001 From: Laurent Rineau Date: Wed, 10 Jun 2020 11:59:54 +0200 Subject: [PATCH 508/568] Second draft of the announcement mail, after a collaborative edition --- Installation/CHANGES.md | 14 +- .../announcement/mailing-beta.eml | 262 +++--------------- 2 files changed, 49 insertions(+), 227 deletions(-) diff --git a/Installation/CHANGES.md b/Installation/CHANGES.md index 14bfe13c5af..b6cc3849288 100644 --- a/Installation/CHANGES.md +++ b/Installation/CHANGES.md @@ -6,6 +6,12 @@ Release History Release date: July 2020 +### [Tetrahedral Remeshing](https://doc.cgal.org/5.1/Manual/packages.html#PkgTetrahedralRemeshing) (new package) + +- This package implements a tetrahedral isotropic remeshing algorithm, + that improves the quality of tetrahedra in terms of dihedral angles, + while targeting a given edge length. + ### [Surface Mesh Topology](https://doc.cgal.org/5.1/Manual/packages.html#PkgSurfaceMeshTopologySummary) (new package) - This package enables the computation of some topological invariants of surfaces, such as: @@ -24,12 +30,6 @@ Release date: July 2020 See also the associated [blog entry](https://www.cgal.org/2020/04/20/Optimal_bounding_box/). -### [Tetrahedral Remeshing](https://doc.cgal.org/5.1/Manual/packages.html#PkgTetrahedralRemeshing) (new package) - -- This package implements a tetrahedral isotropic remeshing algorithm, - that improves the quality of tetrahedra in terms of dihedral angles, - while targeting a given edge length. - ### [Tutorials](https://doc.cgal.org/5.1/Manual/tutorials.html) - Two new, detailed tutorials have been added: @@ -38,7 +38,7 @@ Release date: July 2020 - [Geographic Information Systems (GIS)](https://doc.cgal.org/5.1/Manual/tuto_gis.html), which demonstrates usage of CGAL data structures and algorithms in the context of a typical GIS application. - In both tutorials, complete code is provided. + Both tutorials provide complete code. ### [2D and 3D Linear Geometry Kernel](https://doc.cgal.org/5.1/Manual/packages.html#PkgKernel23) diff --git a/Maintenance/public_release/announcement/mailing-beta.eml b/Maintenance/public_release/announcement/mailing-beta.eml index 999c8503444..2603055f765 100644 --- a/Maintenance/public_release/announcement/mailing-beta.eml +++ b/Maintenance/public_release/announcement/mailing-beta.eml @@ -15,6 +15,12 @@ Besides fixes and general enhancement to existing packages, the following has changed since CGAL 5.0: +Tetrahedral Remeshing (new package) + +- This package implements a tetrahedral isotropic remeshing algorithm, + that improves the quality of tetrahedra in terms of dihedral angles, + while targeting a given edge length. + Surface Mesh Topology (new package) - This package enables the computation of some topological invariants @@ -39,12 +45,6 @@ Optimal Bounding Box (new package) See also the associated blog entry: https://www.cgal.org/2020/04/20/Optimal_bounding_box/ -Tetrahedral Remeshing (new package) - -- This package implements a tetrahedral isotropic remeshing algorithm, - that improves the quality of tetrahedra in terms of dihedral angles, - while targeting a given edge length. - Tutorials - Two new, detailed tutorials have been added: @@ -54,39 +54,46 @@ Tutorials of CGAL data structures and algorithms in the context of a typical GIS application. - In both tutorials, complete code is provided. + Both tutorials provide complete code. See https://doc.cgal.org/5.1/Manual/tutorials.html -2D and 3D Linear Geometry Kernel +Point Set Processing -- Added the functor CompareSignedDistanceToLine_2 to the 2D/3D Kernel - concept to compare the signed distance of two points to a line, or - the line passing through two given points. Corresponding functors in - the model (Compare_signed_distance_to_line_2) are also added. +- Added wrapper functions for registration, using the Super4PCS + algorithm implemented in the third party libraries OpenGRand + libpointmatcher. -dD Geometry Kernel -- The kernels Epick_d and Epeck_d gain two new functors: - Power_side_of_bounded_power_sphere_d and - Compute_squared_radius_smallest_orthogonal_sphere_d. Those are - essential for the computation of weighted alpha-complexes. +Surface Mesh Simplification -Surface Mesh +- Added a new simplification method based on the quadric error defined + by Garland and Heckbert. -- BREAKING CHANGE: The function CGAL::Surface_mesh::clear() now - removes all non-default properties instead of just emptying them. +dD Spatial Searching -CGAL and the Boost Graph Library (BGL) +- The kd-tree can now be built in parallel: CGAL::Kd_tree::build() is + given an optional template parameter ConcurrencyTag (default value + remains CGAL::Sequential_tag for backward compatibility). -- Added the function CGAL::alpha_expansion_graphcut(), which - regularizes a multi-label partition over a user-defined graph. -- Added the function CGAL::regularize_face_selection_borders(), which - uses this alpha expansion graphcut to regularize the borders of a - selected faces on a triangle mesh. -- Added the function CGAL::set_triangulation_ids(), which must be used - to initialize vertex, edge, and face indices of a triangulation - meant to be used with BGL algorithms. +Intersecting Sequences of dD Iso-oriented Boxes + +- Added parallel versions of the functions CGAL::box_intersection_d() + and CGAL::box_self_intersection_d(). + +Polygon Mesh Processing + +- Added the function CGAL::Polygon_mesh_processing::split(), which can + be used to split meshes along a mesh or a plane. +- Added the function + CGAL::Polygon_mesh_processing::split_connected_components() to split + a single mesh containing several connected components into several + meshes containing one connected component. +- Added parallel versions of the functions + CGAL::Polygon_mesh_processing::does_self_intersect() and + CGAL::Polygon_mesh_processing::self_intersections(). +- Added several mesh repair functions (see the complete changelog for + more information). 3D Fast Intersection and Distance Computation @@ -102,199 +109,14 @@ CGAL and the Boost Graph Library (BGL) CGAL::AABB_tree::do_not_accelerate_distance_queries() are no longer const functions. -2D Arrangements -- Changed intersection return type from legacy CGAL::Object to modern - boost::variant in all traits concepts and models. As there exists an - implicit conversion from boost::variant to CGAL::Object, the new - code is backward compatible. However, it is recommended that all - calls to the intersection functions are fixed to use the new return - type. +CGAL and the Boost Graph Library (BGL) -2D Regularized Boolean Set-Operations - -- Changed intersection return type from legacy CGAL::Object to modern - boost::variant in the concept ArrDirectionalTraits::Intersect_2 and - its models. - -2D Minkowski Sums - -- Changed intersection return type from legacy CGAL::Object to modern - boost::variant in the (internally used) model Arr_labeled_traits_2. - -dD Spatial Searching - -- The kd-tree can now be built in parallel: CGAL::Kd_tree::build() is - given an optional template parameter ConcurrencyTag (default value - remains CGAL::Sequential_tag for backward compatibility). -- Improved the performance of the kd-tree in some cases: - - Not storing the points coordinates inside the tree usually - generates a lot of cache misses, leading to non-optimal - performance. This is the case for example when indices are - stored inside the tree, or to a lesser extent when the points - coordinates are stored in a dynamically allocated array (e.g., - Epick_d with dynamic dimension) — we says “to a lesser extent” - because the points are re-created by the kd-tree in a - cache-friendly order after its construction, so the coordinates - are more likely to be stored in a near-optimal order on the - heap. In these cases, the new EnablePointsCache template - parameter of the CGAL::Kd_tree class can be set to - CGAL::Tag_true. The points coordinates will then be cached in an - optimal way. This will increase memory consumption but provides - better search performance. See the updated GeneralDistance and - FuzzyQueryItem concepts for additional requirements when using - such a cache. - - In most cases (e.g., Euclidean distance), the distance - computation algorithm knows before its end that the distance - will be greater than or equal to some given value. This is used - in the (orthogonal) k-NN search to interrupt some distance - computations before its end, saving precious milliseconds, in - particular in medium-to-high dimension. - -Intersecting Sequences of dD Iso-oriented Boxes - -- Added parallel versions of the functions CGAL::box_intersection_d() - and CGAL::box_self_intersection_d(). - -Spatial Sorting - -- Added parallel versions of the functions CGAL::hilbert_sort() and - CGAL::spatial_sort() in 2D and 3D when the median policy is used. - The parallel versions use up to four threads in 2D, and up to eight - threads in 3D. - -3D Convex Hulls - -- A new overload for CGAL::convex_hull_3() that takes a model of - VertexListGraph has been added. -- The long-deprecated function CGAL::convex_hull_3_to_polyhedron_3() - has been removed. The function CGAL::convex_hull_3_to_face_graph() - should be used instead. - -Polygon Mesh Processing - -- Added the function - CGAL::Polygon_mesh_processing::volume_connected_component(), which - can be used to get information about the nesting of the connected - components of a given triangle mesh and about the volumes defined. -- Added the function - CGAL::Polygon_mesh_processing::remove_connected_components_of_negligible_size(), - which can be used to remove connected components whose area or - volume is under a certain threshold. Area and volume thresholds are - either specified by the user or deduced from the bounding box of the - mesh. -- Added a new named parameter for - CGAL::Polygon_mesh_processing::keep_large_connected_components() and - CGAL::Polygon_mesh_processing::remove_connected_components_of_negligible_size, - which can be used to perform a dry run of the operation, meaning - that the function will return the number of connected components - that would be removed with the specified threshold, but without - actually removing them. -- Added the function CGAL::Polygon_mesh_processing::split(), which can - be used to split meshes along a mesh or a plane. -- Added the function - CGAL::Polygon_mesh_processing::split_connected_components() to split - a single mesh containing several connected components into several - meshes containing one connected component. -- Added the functions - CGAL::Polygon_mesh_processing::merge_reversible_connected_components(), - CGAL::Polygon_mesh_processing::duplicate_non_manifold_edges_in_polygon_soup(), - and - CGAL::Polygon_mesh_processing::orient_triangle_soup_with_reference_triangle_mesh(), - which can be helpful when repairing a polygon soup. -- Added the function - CGAL::Polygon_mesh_processing::sample_triangle_soup(), which - generates points on a triangle soup surface. -- Added parallel versions of the functions - CGAL::Polygon_mesh_processing::does_self_intersect() and - CGAL::Polygon_mesh_processing::self_intersections(). -- The function CGAL::Polygon_mesh_processing::stitch_borders() now - returns the number of halfedge pairs that were stitched. -- Added the function - CGAL::Polygon_mesh_processing::polygon_mesh_to_polygon_soup(). -- The function - CGAL::Polygon_mesh_processing::polygon_soup_to_polygon_mesh now - allows passing a point map (for the point range) and a vertex point - map (for the polygon mesh) via named parameters. - -Point Set Processing - -- BREAKING CHANGE: CGAL::remove_outliers() has been parallelized and - thus has a new template parameter ConcurrencyTag. To update your - code simply add as first template parameter CGAL::Sequential_tag or - CGAL::Parallel_tag when calling this function. -- Add a function CGAL::cluster_point_set() that segments a point cloud - into connected components based on a distance threshold. -- Added wrapper functions for registration: - - CGAL::OpenGR::compute_registration_transformation(), which - computes the registration transformation for two point sets - using the Super4PCS algorithm implemented in the third party - library OpenGR. - - CGAL::OpenGR::register_point_sets(), which computes the - registration transformation for two point sets using the - Super4PCS algorithm implemented in the third party library - OpenGR, and registers the points sets by transforming the data - point set using the computed transformation. - - CGAL::pointmatcher::compute_registration_transformation() - computes the registration transformation for two point sets - using ICP algorithm implemented in the third party library - libpointmatcher. - - CGAL::pointmatcher::register_point_sets(), which computes the - registration transformation for two point sets using ICP - algorithm implemented in the third party library - libpointmatcher, and registers the points sets by transforming - the data point set using the computed transformation. - -2D Triangulations - -- To fix an inconsistency between code and documentation and to - clarify which types of intersections are truly allowed in - constrained Delaunay triangulations, the tag - CGAL::No_intersection_tag has been deprecated in favor of two new - tags: CGAL::No_constraint_intersection_tag and - CGAL::No_constraint_intersection_requiring_constructions_tag. The - latter is equivalent to the now-deprecated - CGAL::No_intersection_tag, and allows constraints to intersect as - long as no new point has to be created to represent that - intersection (for example, the intersection of two constraint - segments in a ‘T’-like junction is an existing point and as such - does not require any new construction). The former tag, - CGAL::No_constraint_intersection_tag, does not allow any - intersection, except for the configuration of two constraints having - a single common endpoints, for convience. -- Added the function - CGAL::split_subconstraint_graph_into_constraints() to - Constrained_triangulation_plus_2 to initialize the constraints from - a soup of disconnected segments that should first be split into - polylines. - -3D Triangulations - -- The member function CGAL::Triangulation_3::file_input() have been - added. It allows to load a CGAL::Triangulation_3 from an input - stream, using functors to create vertices and cells. - -3D Triangulation Data Structure - -- The member function CGAL::TDS_3::file_input() have been added. It - allows to load a CGAL::Triangulation_data_structure_3 from an input - stream, using functors to create vertices and cells. - -Surface Mesh Simplification - -- Added a new simplification method based on the quadric error defined - by Garland and Heckbert. -- The concept EdgeProfile has been removed. This concept was not - actually in use as the CGAL-provided model CGAL::Edge_profile was - imposed to the user. Other concepts have been clarified to reflect - the fact that the API uses this particular class. - -STL Extensions for CGAL - -- Added a new concurrency tag: CGAL::Parallel_if_available_tag. This - tag is a convenience typedef to CGAL::Parallel_tag if the third - party library TBB has been found and linked with, and to - CGAL::Sequential_tag otherwise. +- Added the function CGAL::alpha_expansion_graphcut(), which + regularizes a multi-label partition over a user-defined graph. +- Added the function CGAL::regularize_face_selection_borders(), which + uses this alpha expansion graphcut to regularize the borders of a + selected faces on a triangle mesh. See https://www.cgal.org/2020/06/09/cgal51-beta1/ for a complete list of changes. From ef88baf8f295cd4c56e4ec637c9b82fd0b723728 Mon Sep 17 00:00:00 2001 From: Laurent Rineau Date: Wed, 10 Jun 2020 17:10:36 +0200 Subject: [PATCH 509/568] Fix the announcement for PSP --- Maintenance/public_release/announcement/mailing-beta.eml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Maintenance/public_release/announcement/mailing-beta.eml b/Maintenance/public_release/announcement/mailing-beta.eml index 2603055f765..9234c02b647 100644 --- a/Maintenance/public_release/announcement/mailing-beta.eml +++ b/Maintenance/public_release/announcement/mailing-beta.eml @@ -60,8 +60,8 @@ Tutorials Point Set Processing -- Added wrapper functions for registration, using the Super4PCS - algorithm implemented in the third party libraries OpenGRand +- Added wrapper functions for registration, using the Super4PCS and + ICP algorithms implemented in the third party libraries OpenGR and libpointmatcher. From 19ed8f9f39151e142fef893fc6c5ee8d853d2c1d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9bastien=20Loriot?= Date: Wed, 10 Jun 2020 17:21:01 +0200 Subject: [PATCH 510/568] take append into account for reserve --- BGL/include/CGAL/boost/graph/copy_face_graph.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/BGL/include/CGAL/boost/graph/copy_face_graph.h b/BGL/include/CGAL/boost/graph/copy_face_graph.h index dcd8c5cedbf..790fd8232f4 100644 --- a/BGL/include/CGAL/boost/graph/copy_face_graph.h +++ b/BGL/include/CGAL/boost/graph/copy_face_graph.h @@ -64,9 +64,9 @@ void copy_face_graph_impl(const SourceMesh& sm, TargetMesh& tm, const tm_face_descriptor tm_null_face = boost::graph_traits::null_face(); const tm_vertex_descriptor tm_null_vertex = boost::graph_traits::null_vertex(); - reserve(tm, static_cast::vertices_size_type>(vertices(sm).size()), - static_cast::edges_size_type>(edges(sm).size()), - static_cast::faces_size_type>(faces(sm).size()) ); + reserve(tm, static_cast::vertices_size_type>(vertices(tm).size()+vertices(sm).size()), + static_cast::edges_size_type>(edges(tm).size()+edges(sm).size()), + static_cast::faces_size_type>(faces(tm).size()+faces(sm).size()) ); //insert halfedges and create each vertex when encountering its halfedge for(sm_edge_descriptor sm_e : edges(sm)) From 983d958e7d1c031acd92f79c31d34597a10bbf0d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9bastien=20Loriot?= Date: Wed, 10 Jun 2020 17:39:56 +0200 Subject: [PATCH 511/568] make the non-manifold test depends on the input size in case of append --- .../CGAL/boost/graph/copy_face_graph.h | 32 ++++++++++++------- 1 file changed, 20 insertions(+), 12 deletions(-) diff --git a/BGL/include/CGAL/boost/graph/copy_face_graph.h b/BGL/include/CGAL/boost/graph/copy_face_graph.h index 790fd8232f4..d63d7f61b5a 100644 --- a/BGL/include/CGAL/boost/graph/copy_face_graph.h +++ b/BGL/include/CGAL/boost/graph/copy_face_graph.h @@ -40,7 +40,6 @@ void copy_face_graph_impl(const SourceMesh& sm, TargetMesh& tm, { typedef typename boost::graph_traits::vertex_descriptor sm_vertex_descriptor; typedef typename boost::graph_traits::vertex_descriptor tm_vertex_descriptor; - typedef typename boost::graph_traits::halfedge_iterator tm_halfedge_iterator; typedef typename boost::graph_traits::face_descriptor sm_face_descriptor; typedef typename boost::graph_traits::face_descriptor tm_face_descriptor; @@ -69,9 +68,12 @@ void copy_face_graph_impl(const SourceMesh& sm, TargetMesh& tm, static_cast::faces_size_type>(faces(tm).size()+faces(sm).size()) ); //insert halfedges and create each vertex when encountering its halfedge + std::vector new_edges; + new_edges.reserve(edges(sm).size()); for(sm_edge_descriptor sm_e : edges(sm)) { tm_edge_descriptor tm_e = add_edge(tm); + new_edges.push_back(tm_e); sm_halfedge_descriptor sm_h = halfedge(sm_e, sm), sm_h_opp = opposite(sm_h, sm); tm_halfedge_descriptor tm_h = halfedge(tm_e, tm), tm_h_opp = opposite(tm_h, tm); @@ -173,9 +175,10 @@ void copy_face_graph_impl(const SourceMesh& sm, TargetMesh& tm, } // detect if there are some non-manifold umbrellas and fix missing halfedge target pointers - for (tm_halfedge_iterator it=halfedges(tm).first; it!=halfedges(tm).second; ++it) + typedef typename std::vector::iterator edge_iterator; + for (edge_iterator it=new_edges.begin(); it!=new_edges.end(); ++it) { - if (target(*it, tm) == tm_null_vertex) + if (target(*it, tm) == tm_null_vertex || source(*it, tm) == tm_null_vertex) { // create and fill a map from target halfedge to source halfedge typedef CGAL::dynamic_halfedge_property_t Dyn_th_tag; @@ -183,17 +186,22 @@ void copy_face_graph_impl(const SourceMesh& sm, TargetMesh& tm, for (sm_halfedge_descriptor hs : halfedges(sm)) put(ht_to_hs, get(hs_to_ht, hs), hs); - for(; it!=halfedges(tm).second; ++it) + for(; it!=new_edges.end(); ++it) { - if (target(*it, tm) == tm_null_vertex) + tm_halfedge_descriptor nh_t = halfedge(*it, tm); + for (int i=0; i<2; ++i) { - // we recover tm_v using the halfedge associated to the target vertex of - // the halfedge in sm corresponding to *it. This is working because we - // set the vertex halfedge pointer to the "same" halfedges. - tm_vertex_descriptor tm_v = - target( get(hs_to_ht, halfedge(target(get(ht_to_hs, *it), sm), sm)), tm); - for(tm_halfedge_descriptor ht : halfedges_around_target(*it, tm)) - set_target(ht, tm_v, tm); + if (target(nh_t, tm) == tm_null_vertex) + { + // we recover tm_v using the halfedge associated to the target vertex of + // the halfedge in sm corresponding to nh_t. This is working because we + // set the vertex halfedge pointer to the "same" halfedges. + tm_vertex_descriptor tm_v = + target( get(hs_to_ht, halfedge(target(get(ht_to_hs, nh_t), sm), sm)), tm); + for(tm_halfedge_descriptor ht : halfedges_around_target(nh_t, tm)) + set_target(ht, tm_v, tm); + } + nh_t = opposite(nh_t, tm); } } break; From 6747341f666a3cb061ff053aa10a8709982e81f8 Mon Sep 17 00:00:00 2001 From: Laurent Rineau Date: Wed, 10 Jun 2020 18:06:52 +0200 Subject: [PATCH 512/568] Fix travis, broken since #4620 (commit 0a43f88f5d60) --- .travis.yml | 53 +++++++++++++++++++++++++---------------------------- 1 file changed, 25 insertions(+), 28 deletions(-) diff --git a/.travis.yml b/.travis.yml index 26946424096..2c2fe62d3f4 100644 --- a/.travis.yml +++ b/.travis.yml @@ -4,34 +4,6 @@ sudo: required git: depth: 3 env: - matrix: - PACKAGES_MATRIX - -compiler: clang -install: - - echo "$PWD" - - if [ -n "$TRAVIS_PULL_REQUEST_BRANCH" ] && [ "$PACKAGE" != CHECK ]; then DO_IGNORE=FALSE; for ARG in $(echo "$PACKAGE");do if [ "$ARG" = "Maintenance" ]; then continue; fi; . $PWD/.travis/test_package.sh "$PWD" "$ARG"; echo "DO_IGNORE is $DO_IGNORE"; if [ "$DO_IGNORE" = "FALSE" ]; then break; fi; done; if [ "$DO_IGNORE" = "TRUE" ]; then travis_terminate 0; fi;fi - - /usr/bin/time -f 'Spend time of %C -- %E (real)' bash .travis/install.sh - - export CXX=clang++ CC=clang; -before_script: - - wget -O doxygen_exe https://cgal.geometryfactory.com/~mgimeno/doxygen_exe - - sudo mv doxygen_exe /usr/bin/doxygen - - sudo chmod +x /usr/bin/doxygen - - mkdir -p build - - cd build - - /usr/bin/time -f 'Spend time of %C -- %E (real)' cmake -DCMAKE_CXX_FLAGS="-std=c++1y" -DCGAL_HEADER_ONLY=ON -DCMAKE_CXX_FLAGS_RELEASE=-DCGAL_NDEBUG -DWITH_examples=ON -DWITH_demos=ON -DWITH_tests=ON .. - - /usr/bin/time -f 'Spend time of %C -- %E (real)' make - - /usr/bin/time -f 'Spend time of %C -- %E (real)' sudo make install &>/dev/null - - cd .. -script: - - cd ./.travis - - /usr/bin/time -f 'Spend time of %C -- %E (real)' bash ./build_package.sh $PACKAGE -notifications: - email: - on_success: change - # default: always - on_failure: always - # default: always matrix: - PACKAGE='CHECK' - PACKAGE='AABB_tree Advancing_front_surface_reconstruction Algebraic_foundations ' @@ -81,3 +53,28 @@ notifications: - PACKAGE='Three Triangulation Triangulation_2 ' - PACKAGE='Triangulation_3 Union_find Visibility_2 ' - PACKAGE='Voronoi_diagram_2 wininst ' +compiler: clang +install: + - echo "$PWD" + - if [ -n "$TRAVIS_PULL_REQUEST_BRANCH" ] && [ "$PACKAGE" != CHECK ]; then DO_IGNORE=FALSE; for ARG in $(echo "$PACKAGE");do if [ "$ARG" = "Maintenance" ]; then continue; fi; . $PWD/.travis/test_package.sh "$PWD" "$ARG"; echo "DO_IGNORE is $DO_IGNORE"; if [ "$DO_IGNORE" = "FALSE" ]; then break; fi; done; if [ "$DO_IGNORE" = "TRUE" ]; then travis_terminate 0; fi;fi + - /usr/bin/time -f 'Spend time of %C -- %E (real)' bash .travis/install.sh + - export CXX=clang++ CC=clang; +before_script: + - wget -O doxygen_exe https://cgal.geometryfactory.com/~mgimeno/doxygen_exe + - sudo mv doxygen_exe /usr/bin/doxygen + - sudo chmod +x /usr/bin/doxygen + - mkdir -p build + - cd build + - /usr/bin/time -f 'Spend time of %C -- %E (real)' cmake -DCMAKE_CXX_FLAGS="-std=c++1y" -DCGAL_HEADER_ONLY=ON -DCMAKE_CXX_FLAGS_RELEASE=-DCGAL_NDEBUG -DWITH_examples=ON -DWITH_demos=ON -DWITH_tests=ON .. + - /usr/bin/time -f 'Spend time of %C -- %E (real)' make + - /usr/bin/time -f 'Spend time of %C -- %E (real)' sudo make install &>/dev/null + - cd .. +script: + - cd ./.travis + - /usr/bin/time -f 'Spend time of %C -- %E (real)' bash ./build_package.sh $PACKAGE +notifications: + email: + on_success: change + # default: always + on_failure: always + # default: always From 127d76c37016f91fcaa5e4618cd1a5d6fa40b087 Mon Sep 17 00:00:00 2001 From: Laurent Rineau Date: Wed, 10 Jun 2020 17:57:54 +0200 Subject: [PATCH 513/568] Fix ambiguous comparisons error with C++20 ``` /home/cgal_tester/build/src/cmake/platforms/ArchLinux-clang-CXX20-Release/test/Kernel_d/afftrafo-test.cpp:136:31: error: use of overloaded operator '==' is ambiguous (with operand types 'VectorHd, CGAL::Linear_algebraHd<__gmp_expr, std::allocator<__gmp_expr > > >::RT, CGAL::VectorHd<__gmp_expr, CGAL::Linear_algebraHd<__gmp_expr, std::allocator<__gmp_expr > > >::LA>' (aka 'VectorHd<__gmp_expr, CGAL::Linear_algebraHd<__gmp_expr, std::allocator<__gmp_expr > > >') and 'Vector_d, CGAL::Linear_algebraHd<__gmp_expr, std::allocator<__gmp_expr > > > >') CGAL_TEST(v.transform(at9)==3*v){} ~~~~~~~~~~~~~~~~^ ~~~ /home/cgal_tester/build/src/cmake/platforms/ArchLinux-clang-CXX20-Release/test/Kernel_d/include/CGAL/test_macros.h:10:28: note: expanded from macro 'CGAL_TEST' ^ /mnt/testsuite/include/CGAL/Kernel_d/VectorHd.h:350:6: note: candidate function bool operator==(const VectorHd& w) const ^ /mnt/testsuite/include/CGAL/Kernel_d/Vector_d.h:90:8: note: candidate function (with reversed parameter order) bool operator==(const Self& w) const ^ ``` ``` /home/cgal_tester/build/src/cmake/platforms/ArchLinux-clang-CXX20-Release/test/Kernel_d/afftrafo-test.cpp:141:33: error: use of overloaded operator '==' is ambiguous (with operand types 'DirectionHd, CGAL::Linear_algebraHd<__gmp_expr, std::allocator<__gmp_expr > > >::RT, CGAL::DirectionHd<__gmp_expr, CGAL::Linear_algebraHd<__gmp_expr, std::allocator<__gmp_expr > > >::LA>' (aka 'DirectionHd<__gmp_expr, CGAL::Linear_algebraHd<__gmp_expr, std::allocator<__gmp_expr > > >') and 'Direction' (aka 'Direction_d > >')) CGAL_TEST(dir.transform(at9)==dir){} ~~~~~~~~~~~~~~~~~~^ ~~~ /home/cgal_tester/build/src/cmake/platforms/ArchLinux-clang-CXX20-Release/test/Kernel_d/include/CGAL/test_macros.h:10:28: note: expanded from macro 'CGAL_TEST' ^ /mnt/testsuite/include/CGAL/Kernel_d/DirectionHd.h:181:6: note: candidate function bool operator==(const DirectionHd& w) const ^ /mnt/testsuite/include/CGAL/Kernel_d/Direction_d.h:61:8: note: candidate function (with reversed parameter order) bool operator==(const Self& w) const ^ ``` --- Kernel_d/include/CGAL/Kernel_d/Direction_d.h | 4 ++++ Kernel_d/include/CGAL/Kernel_d/Vector_d.h | 4 ++++ 2 files changed, 8 insertions(+) diff --git a/Kernel_d/include/CGAL/Kernel_d/Direction_d.h b/Kernel_d/include/CGAL/Kernel_d/Direction_d.h index 4cef344f845..70bd4c1b725 100644 --- a/Kernel_d/include/CGAL/Kernel_d/Direction_d.h +++ b/Kernel_d/include/CGAL/Kernel_d/Direction_d.h @@ -62,6 +62,10 @@ class Direction_d : public pR::Direction_d_base { return Base::operator==(w); } bool operator!=(const Self& w) const { return Base::operator!=(w); } + bool operator==(const Base& w) const + { return Base::operator==(w); } + bool operator!=(const Base& w) const + { return Base::operator!=(w); } }; } //namespace CGAL diff --git a/Kernel_d/include/CGAL/Kernel_d/Vector_d.h b/Kernel_d/include/CGAL/Kernel_d/Vector_d.h index f434e579f6b..ffd79e265ba 100644 --- a/Kernel_d/include/CGAL/Kernel_d/Vector_d.h +++ b/Kernel_d/include/CGAL/Kernel_d/Vector_d.h @@ -91,6 +91,10 @@ class Vector_d : public pR::Vector_d_base { return Base::operator==(w); } bool operator!=(const Self& w) const { return Base::operator!=(w); } + bool operator==(const Base& w) const + { return Base::operator==(w); } + bool operator!=(const Base& w) const + { return Base::operator!=(w); } }; From 489e853a65dbe5f162ec0e9223123fe1ecfd57af Mon Sep 17 00:00:00 2001 From: Laurent Rineau Date: Wed, 10 Jun 2020 18:25:33 +0200 Subject: [PATCH 514/568] Fix ambiguous comparisons error with C++20 with Hyperplane_d as well --- Kernel_d/include/CGAL/Kernel_d/Hyperplane_d.h | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/Kernel_d/include/CGAL/Kernel_d/Hyperplane_d.h b/Kernel_d/include/CGAL/Kernel_d/Hyperplane_d.h index c053826c0cb..88728ded551 100644 --- a/Kernel_d/include/CGAL/Kernel_d/Hyperplane_d.h +++ b/Kernel_d/include/CGAL/Kernel_d/Hyperplane_d.h @@ -75,6 +75,10 @@ public: { return Base::operator==(w); } bool operator!=(const Self& w) const { return Base::operator!=(w); } + bool operator==(const Base& w) const + { return Base::operator==(w); } + bool operator!=(const Base& w) const + { return Base::operator!=(w); } }; } //namespace CGAL From 1d3c8bbbc9795f2456094547767a70c34cf01aaa Mon Sep 17 00:00:00 2001 From: Laurent Rineau Date: Wed, 10 Jun 2020 22:33:26 +0200 Subject: [PATCH 515/568] Fix "error: use of overloaded operator '=='" ... for `Arrangement_on_surface_2`, Boolean_operations_2`, and `Minkowski_sum_2`. --- HalfedgeDS/include/CGAL/HalfedgeDS_iterator.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/HalfedgeDS/include/CGAL/HalfedgeDS_iterator.h b/HalfedgeDS/include/CGAL/HalfedgeDS_iterator.h index 437c1e4ad50..23d1a135eea 100644 --- a/HalfedgeDS/include/CGAL/HalfedgeDS_iterator.h +++ b/HalfedgeDS/include/CGAL/HalfedgeDS_iterator.h @@ -262,6 +262,8 @@ public: bool operator!=( std::nullptr_t p) const { return !(*this == p); } bool operator==( const Self& i) const { return It::operator==(i); } bool operator!=( const Self& i) const { return !(*this == i); } + bool operator==( const It& i) const { return It::operator==(i); } + bool operator!=( const It& i) const { return !(*this == i); } Self& operator++() { this->nt = (*this->nt).next(); From a9795c3562397923578c855e0995b6d25541f370 Mon Sep 17 00:00:00 2001 From: Maxime Gimeno Date: Thu, 11 Jun 2020 13:11:36 +0200 Subject: [PATCH 516/568] Fix deprecation warnings --- .../demo/Alpha_shapes_2/Alpha_shapes_2.cpp | 2 +- .../Apollonius_graph_2/Apollonius_graph_2.cpp | 2 +- .../Bounding_volumes/Bounding_volumes.cpp | 2 +- .../L1_voronoi_diagram_2.cpp | 2 +- .../Periodic_2_Delaunay_triangulation_2.cpp | 2 +- .../demo/Snap_rounding_2/Snap_rounding_2.cpp | 2 +- .../demo/Stream_lines_2/Stream_lines_2.cpp | 2 +- .../Delaunay_triangulation_2.cpp | 2 +- .../Regular_triangulation_2.cpp | 2 +- .../include/CGAL/Qt/DemosMainWindow.h | 2 +- .../CGAL/Qt/GraphicsViewNavigation_impl.h | 17 ++++---- .../CGAL/Qt/manipulatedCameraFrame_impl.h | 2 +- .../include/CGAL/Qt/manipulatedFrame_impl.h | 2 +- GraphicsView/include/CGAL/Qt/qglviewer.h | 6 +-- Polyhedron/demo/Polyhedron/MainWindow.cpp | 4 ++ .../Plugins/PCA/Basic_generator_plugin.cpp | 39 ++++++++++++++++++- .../Plugins/Surface_mesh/UVProjector.h | 2 +- Polyhedron/demo/Polyhedron/Viewer.cpp | 10 ++++- 18 files changed, 73 insertions(+), 29 deletions(-) diff --git a/GraphicsView/demo/Alpha_shapes_2/Alpha_shapes_2.cpp b/GraphicsView/demo/Alpha_shapes_2/Alpha_shapes_2.cpp index c473c373091..374e297f3cc 100644 --- a/GraphicsView/demo/Alpha_shapes_2/Alpha_shapes_2.cpp +++ b/GraphicsView/demo/Alpha_shapes_2/Alpha_shapes_2.cpp @@ -138,7 +138,7 @@ MainWindow::MainWindow() this->graphicsView->setMouseTracking(true); // Turn the vertical axis upside down - this->graphicsView->matrix().scale(1, -1); + this->graphicsView->transform().scale(1, -1); // The navigation adds zooming and translation functionality to the // QGraphicsView diff --git a/GraphicsView/demo/Apollonius_graph_2/Apollonius_graph_2.cpp b/GraphicsView/demo/Apollonius_graph_2/Apollonius_graph_2.cpp index 2847ac24d9e..8292f28262d 100644 --- a/GraphicsView/demo/Apollonius_graph_2/Apollonius_graph_2.cpp +++ b/GraphicsView/demo/Apollonius_graph_2/Apollonius_graph_2.cpp @@ -125,7 +125,7 @@ MainWindow::MainWindow() this->graphicsView->setMouseTracking(true); // Turn the vertical axis upside down - this->graphicsView->matrix().scale(1, -1); + this->graphicsView->transform().scale(1, -1); // The navigation adds zooming and translation functionality to the // QGraphicsView diff --git a/GraphicsView/demo/Bounding_volumes/Bounding_volumes.cpp b/GraphicsView/demo/Bounding_volumes/Bounding_volumes.cpp index fe02e1d0faa..12928ca9897 100644 --- a/GraphicsView/demo/Bounding_volumes/Bounding_volumes.cpp +++ b/GraphicsView/demo/Bounding_volumes/Bounding_volumes.cpp @@ -208,7 +208,7 @@ MainWindow::MainWindow() this->graphicsView->setMouseTracking(true); // Turn the vertical axis upside down - this->graphicsView->matrix().scale(1, -1); + this->graphicsView->transform().scale(1, -1); // The navigation adds zooming and translation functionality to the // QGraphicsView diff --git a/GraphicsView/demo/L1_Voronoi_diagram_2/L1_voronoi_diagram_2.cpp b/GraphicsView/demo/L1_Voronoi_diagram_2/L1_voronoi_diagram_2.cpp index 40b4601ea8f..621a6f6c6c9 100644 --- a/GraphicsView/demo/L1_Voronoi_diagram_2/L1_voronoi_diagram_2.cpp +++ b/GraphicsView/demo/L1_Voronoi_diagram_2/L1_voronoi_diagram_2.cpp @@ -178,7 +178,7 @@ MainWindow::MainWindow() this->graphicsView->setMouseTracking(true); // Turn the vertical axis upside down - this->graphicsView->matrix().scale(1, -1); + this->graphicsView->transform().scale(1, -1); // The navigation adds zooming and translation functionality to the // QGraphicsView diff --git a/GraphicsView/demo/Periodic_2_triangulation_2/Periodic_2_Delaunay_triangulation_2.cpp b/GraphicsView/demo/Periodic_2_triangulation_2/Periodic_2_Delaunay_triangulation_2.cpp index fca48808325..e956d72a171 100644 --- a/GraphicsView/demo/Periodic_2_triangulation_2/Periodic_2_Delaunay_triangulation_2.cpp +++ b/GraphicsView/demo/Periodic_2_triangulation_2/Periodic_2_Delaunay_triangulation_2.cpp @@ -181,7 +181,7 @@ MainWindow::MainWindow() this->graphicsView->setMouseTracking(true); // Turn the vertical axis upside down - this->graphicsView->matrix().scale(1, -1); + this->graphicsView->transform().scale(1, -1); // The navigation adds zooming and translation functionality to the // QGraphicsView diff --git a/GraphicsView/demo/Snap_rounding_2/Snap_rounding_2.cpp b/GraphicsView/demo/Snap_rounding_2/Snap_rounding_2.cpp index f16611b517e..0225624b96e 100644 --- a/GraphicsView/demo/Snap_rounding_2/Snap_rounding_2.cpp +++ b/GraphicsView/demo/Snap_rounding_2/Snap_rounding_2.cpp @@ -132,7 +132,7 @@ MainWindow::MainWindow() scene.setItemIndexMethod(QGraphicsScene::NoIndex); this->graphicsView->setScene(&scene); // Turn the vertical axis upside down - this->graphicsView->matrix().scale(1, -1); + this->graphicsView->transform().scale(1, -1); this->graphicsView->setMouseTracking(true); rgi = new CGAL::Qt::RegularGridGraphicsItem(delta, delta); diff --git a/GraphicsView/demo/Stream_lines_2/Stream_lines_2.cpp b/GraphicsView/demo/Stream_lines_2/Stream_lines_2.cpp index 0eeb169f07f..b0e1fb852ec 100644 --- a/GraphicsView/demo/Stream_lines_2/Stream_lines_2.cpp +++ b/GraphicsView/demo/Stream_lines_2/Stream_lines_2.cpp @@ -106,7 +106,7 @@ MainWindow::MainWindow() this->graphicsView->setScene(&scene); // Turn the vertical axis upside down - this->graphicsView->matrix().scale(1, -1); + this->graphicsView->transform().scale(1, -1); // The navigation adds zooming and translation functionality to the // QGraphicsView diff --git a/GraphicsView/demo/Triangulation_2/Delaunay_triangulation_2.cpp b/GraphicsView/demo/Triangulation_2/Delaunay_triangulation_2.cpp index 62ac4d75501..9d810c04398 100644 --- a/GraphicsView/demo/Triangulation_2/Delaunay_triangulation_2.cpp +++ b/GraphicsView/demo/Triangulation_2/Delaunay_triangulation_2.cpp @@ -171,7 +171,7 @@ MainWindow::MainWindow() this->graphicsView->setMouseTracking(true); // Turn the vertical axis upside down - this->graphicsView->matrix().scale(1, -1); + this->graphicsView->transform().scale(1, -1); // The navigation adds zooming and translation functionality to the // QGraphicsView diff --git a/GraphicsView/demo/Triangulation_2/Regular_triangulation_2.cpp b/GraphicsView/demo/Triangulation_2/Regular_triangulation_2.cpp index fcaf1aba96d..3b5cd7cf76b 100644 --- a/GraphicsView/demo/Triangulation_2/Regular_triangulation_2.cpp +++ b/GraphicsView/demo/Triangulation_2/Regular_triangulation_2.cpp @@ -142,7 +142,7 @@ MainWindow::MainWindow() this->graphicsView->setMouseTracking(true); // Turn the vertical axis upside down - this->graphicsView->matrix().scale(1, -1); + this->graphicsView->transform().scale(1, -1); // The navigation adds zooming and translation functionality to the // QGraphicsView diff --git a/GraphicsView/include/CGAL/Qt/DemosMainWindow.h b/GraphicsView/include/CGAL/Qt/DemosMainWindow.h index 834262cc4c8..856943ad247 100644 --- a/GraphicsView/include/CGAL/Qt/DemosMainWindow.h +++ b/GraphicsView/include/CGAL/Qt/DemosMainWindow.h @@ -72,7 +72,7 @@ private: QMenu* getHelpMenu(); protected: - DemosMainWindow (QWidget * parent = 0, ::Qt::WindowFlags flags = 0 ); + DemosMainWindow (QWidget * parent = 0, ::Qt::WindowFlags flags = ::Qt::WindowFlags(0) ); ~DemosMainWindow(); void setupStatusBar(); void addNavigation(QGraphicsView*); diff --git a/GraphicsView/include/CGAL/Qt/GraphicsViewNavigation_impl.h b/GraphicsView/include/CGAL/Qt/GraphicsViewNavigation_impl.h index 50b4427c131..39863832586 100644 --- a/GraphicsView/include/CGAL/Qt/GraphicsViewNavigation_impl.h +++ b/GraphicsView/include/CGAL/Qt/GraphicsViewNavigation_impl.h @@ -134,15 +134,12 @@ namespace Qt { } // end case KeyRelease case QEvent::Wheel: { QWheelEvent *wheelEvent = static_cast(event); - if(wheelEvent->orientation() != ::Qt::Vertical) { - return false; - } double zoom_ratio = 240.0; if( (wheelEvent->modifiers() & ::Qt::ShiftModifier) || (wheelEvent->modifiers() & ::Qt::ControlModifier) ) { zoom_ratio = 120.0; } - scaleView(v, pow((double)2, -wheelEvent->delta() / zoom_ratio)); + scaleView(v, pow((double)2, -wheelEvent->angleDelta().y() / zoom_ratio)); // display_parameters(); return true; @@ -311,12 +308,12 @@ namespace Qt { boost::format("matrix translation=(%1%, %2%)\n" " rotation=(%3% - %4% )\n" " (%5% - %6% )\n") - % v->matrix().dx() - % v->matrix().dy() - % v->matrix().m11() - % v->matrix().m12() - % v->matrix().m21() - % v->matrix().m22(); + % v->transform().dx() + % v->transform().dy() + % v->transform().m11() + % v->transform().m12() + % v->transform().m21() + % v->transform().m22(); QRect vp_rect = v->viewport()->rect(); QPoint vp_top_left = vp_rect.topLeft(); diff --git a/GraphicsView/include/CGAL/Qt/manipulatedCameraFrame_impl.h b/GraphicsView/include/CGAL/Qt/manipulatedCameraFrame_impl.h index c13808d7320..3dfb1bf5e55 100644 --- a/GraphicsView/include/CGAL/Qt/manipulatedCameraFrame_impl.h +++ b/GraphicsView/include/CGAL/Qt/manipulatedCameraFrame_impl.h @@ -421,7 +421,7 @@ void ManipulatedCameraFrame::wheelEvent(QWheelEvent *const event, case MOVE_BACKWARD: //#CONNECTION# mouseMoveEvent() MOVE_FORWARD case translate( - inverseTransformOf(Vec(0.0, 0.0, 0.2 * flySpeed() * event->delta()))); + inverseTransformOf(Vec(0.0, 0.0, 0.2 * flySpeed() * event->angleDelta().y()))); Q_EMIT manipulated(); break; default: diff --git a/GraphicsView/include/CGAL/Qt/manipulatedFrame_impl.h b/GraphicsView/include/CGAL/Qt/manipulatedFrame_impl.h index 96d03db9adc..11a68ce0c08 100644 --- a/GraphicsView/include/CGAL/Qt/manipulatedFrame_impl.h +++ b/GraphicsView/include/CGAL/Qt/manipulatedFrame_impl.h @@ -295,7 +295,7 @@ qreal ManipulatedFrame::deltaWithPrevPos(QMouseEvent *const event, CGAL_INLINE_FUNCTION qreal ManipulatedFrame::wheelDelta(const QWheelEvent *event) const { static const qreal WHEEL_SENSITIVITY_COEF = 8E-4; - return event->delta() * wheelSensitivity() * WHEEL_SENSITIVITY_COEF; + return event->angleDelta().y() * wheelSensitivity() * WHEEL_SENSITIVITY_COEF; } CGAL_INLINE_FUNCTION diff --git a/GraphicsView/include/CGAL/Qt/qglviewer.h b/GraphicsView/include/CGAL/Qt/qglviewer.h index ed0624ef73b..2db183e6bce 100644 --- a/GraphicsView/include/CGAL/Qt/qglviewer.h +++ b/GraphicsView/include/CGAL/Qt/qglviewer.h @@ -73,11 +73,11 @@ class CGAL_QT_EXPORT QGLViewer : public QOpenGLWidget, public QOpenGLFunctions { public: //todo check if this is used. If not remove it explicit QGLViewer(QGLContext* context, QWidget *parent = 0, - ::Qt::WindowFlags flags = 0); + ::Qt::WindowFlags flags = ::Qt::WindowFlags(0)); explicit QGLViewer(QOpenGLContext* context, QWidget *parent = 0, - ::Qt::WindowFlags flags = 0); + ::Qt::WindowFlags flags = ::Qt::WindowFlags(0)); explicit QGLViewer(QWidget *parent = 0, - ::Qt::WindowFlags flags = 0); + ::Qt::WindowFlags flags = ::Qt::WindowFlags(0)); virtual ~QGLViewer(); diff --git a/Polyhedron/demo/Polyhedron/MainWindow.cpp b/Polyhedron/demo/Polyhedron/MainWindow.cpp index 3951ba10c1c..ae829c69345 100644 --- a/Polyhedron/demo/Polyhedron/MainWindow.cpp +++ b/Polyhedron/demo/Polyhedron/MainWindow.cpp @@ -765,7 +765,11 @@ void MainWindow::loadPlugins() qputenv("PATH", new_path); #endif Q_FOREACH (QString pluginsDir, + #if QT_VERSION < QT_VERSION_CHECK(5, 15, 0) env_path.split(separator, QString::SkipEmptyParts)) { + #else + env_path.split(separator, Qt::SkipEmptyParts)) { + #endif QDir dir(pluginsDir); if(dir.isReadable()) plugins_directories << dir; diff --git a/Polyhedron/demo/Polyhedron/Plugins/PCA/Basic_generator_plugin.cpp b/Polyhedron/demo/Polyhedron/Plugins/PCA/Basic_generator_plugin.cpp index 4215c75421b..89637556188 100644 --- a/Polyhedron/demo/Polyhedron/Plugins/PCA/Basic_generator_plugin.cpp +++ b/Polyhedron/demo/Polyhedron/Plugins/PCA/Basic_generator_plugin.cpp @@ -350,8 +350,11 @@ void Basic_generator_plugin::generateCube() for(int i=0; i<8; ++i) { - +#if QT_VERSION < QT_VERSION_CHECK(5, 15, 0) QStringList list = point_texts[i].split(QRegExp("\\s+"), QString::SkipEmptyParts); +#else + QStringList list = point_texts[i].split(QRegExp("\\s+"), Qt::SkipEmptyParts); +#endif if (list.isEmpty()) return; if (list.size()!=3){ QMessageBox *msgBox = new QMessageBox; @@ -392,7 +395,11 @@ void Basic_generator_plugin::generateCube() else { QString text = dock_widget->extremaEdit->text(); +#if QT_VERSION < QT_VERSION_CHECK(5, 15, 0) QStringList list = text.split(QRegExp("\\s+"), QString::SkipEmptyParts); +#else + QStringList list = text.split(QRegExp("\\s+"), Qt::SkipEmptyParts); +#endif if (list.isEmpty()) return; if (list.size()!=6){ QMessageBox *msgBox = new QMessageBox; @@ -443,7 +450,11 @@ void Basic_generator_plugin::generatePrism() bool is_closed = dock_widget->prismCheckBox->isChecked(); QString text = dock_widget->prism_lineEdit->text(); +#if QT_VERSION < QT_VERSION_CHECK(5, 15, 0) QStringList list = text.split(QRegExp("\\s+"), QString::SkipEmptyParts); +#else + QStringList list = text.split(QRegExp("\\s+"), Qt::SkipEmptyParts); +#endif if (list.isEmpty()) return; if (list.size()!=3){ QMessageBox *msgBox = new QMessageBox; @@ -490,7 +501,11 @@ void Basic_generator_plugin::generatePyramid() bool is_closed = dock_widget->pyramidCheckBox->isChecked(); QString text = dock_widget->pyramid_lineEdit->text(); +#if QT_VERSION < QT_VERSION_CHECK(5, 15, 0) QStringList list = text.split(QRegExp("\\s+"), QString::SkipEmptyParts); +#else + QStringList list = text.split(QRegExp("\\s+"), Qt::SkipEmptyParts); +#endif if (list.isEmpty()) return; if (list.size()!=3){ QMessageBox *msgBox = new QMessageBox; @@ -533,7 +548,11 @@ void Basic_generator_plugin::generateSphere() { int precision = dock_widget->SphereSpinBox->value(); QString text = dock_widget->center_radius_lineEdit->text(); +#if QT_VERSION < QT_VERSION_CHECK(5, 15, 0) QStringList list = text.split(QRegExp("\\s+"), QString::SkipEmptyParts); +#else + QStringList list = text.split(QRegExp("\\s+"), Qt::SkipEmptyParts); +#endif if (list.isEmpty()) return; if (list.size()!=4){ QMessageBox *msgBox = new QMessageBox; @@ -582,8 +601,11 @@ void Basic_generator_plugin::generateTetrahedron() for(int i=0; i<4; ++i) { - +#if QT_VERSION < QT_VERSION_CHECK(5, 15, 0) QStringList list = point_texts[i].split(QRegExp("\\s+"), QString::SkipEmptyParts); +#else + QStringList list = point_texts[i].split(QRegExp("\\s+"), Qt::SkipEmptyParts); +#endif if (list.isEmpty()) return; if (list.size()!=3){ QMessageBox *msgBox = new QMessageBox; @@ -624,7 +646,11 @@ void Basic_generator_plugin::generatePoints() { QString text = dock_widget->point_textEdit->toPlainText(); Scene_points_with_normal_item* item = new Scene_points_with_normal_item(); +#if QT_VERSION < QT_VERSION_CHECK(5, 15, 0) QStringList list = text.split(QRegExp("\\s+"), QString::SkipEmptyParts); +#else + QStringList list = text.split(QRegExp("\\s+"), Qt::SkipEmptyParts); +#endif int counter = 0; double coord[3]; bool ok = true; @@ -682,7 +708,12 @@ void Basic_generator_plugin::generateLines() polylines.resize(polylines.size()+1); std::vector& polyline = *(polylines.rbegin()); QStringList polylines_metadata; + +#if QT_VERSION < QT_VERSION_CHECK(5, 15, 0) QStringList list = text.split(QRegExp("\\s+"), QString::SkipEmptyParts); +#else + QStringList list = text.split(QRegExp("\\s+"), Qt::SkipEmptyParts); +#endif int counter = 0; double coord[3]; bool ok = true; @@ -782,7 +813,11 @@ void Basic_generator_plugin::generateGrid() bool triangulated = dock_widget->grid_checkBox->isChecked(); points_text= dock_widget->grid_lineEdit->text(); +#if QT_VERSION < QT_VERSION_CHECK(5, 15, 0) QStringList list = points_text.split(QRegExp("\\s+"), QString::SkipEmptyParts); +#else + QStringList list = points_text.split(QRegExp("\\s+"), Qt::SkipEmptyParts); +#endif if (list.isEmpty()) return; if (list.size()!=6){ QMessageBox *msgBox = new QMessageBox; diff --git a/Polyhedron/demo/Polyhedron/Plugins/Surface_mesh/UVProjector.h b/Polyhedron/demo/Polyhedron/Plugins/Surface_mesh/UVProjector.h index dd54dad556d..6a726c8db90 100644 --- a/Polyhedron/demo/Polyhedron/Plugins/Surface_mesh/UVProjector.h +++ b/Polyhedron/demo/Polyhedron/Plugins/Surface_mesh/UVProjector.h @@ -108,7 +108,7 @@ protected: } void wheelEvent(QWheelEvent *event) { - if(event->delta() >0) + if(event->angleDelta().y() >0) translation[2] *= 1.2; else translation[2] /= 1.2; diff --git a/Polyhedron/demo/Polyhedron/Viewer.cpp b/Polyhedron/demo/Polyhedron/Viewer.cpp index 57ed3f9d84f..0a41f43ea04 100644 --- a/Polyhedron/demo/Polyhedron/Viewer.cpp +++ b/Polyhedron/demo/Polyhedron/Viewer.cpp @@ -852,7 +852,11 @@ void Viewer::postSelection(const QPoint& pixel) } bool CGAL::Three::Viewer_interface::readFrame(QString s, CGAL::qglviewer::Frame& frame) { +#if QT_VERSION < QT_VERSION_CHECK(5, 15, 0) QStringList list = s.split(" ", QString::SkipEmptyParts); +#else + QStringList list = s.split(" ", ::Qt::SkipEmptyParts); +#endif if(list.size() != 7) return false; float vec[3]; @@ -1422,7 +1426,7 @@ void Viewer::wheelEvent(QWheelEvent* e) { if(e->modifiers().testFlag(Qt::ShiftModifier)) { - double delta = e->delta(); + double delta = e->angleDelta().y(); if(delta>0) { switch(camera()->type()) @@ -1781,7 +1785,11 @@ void Viewer::setLighting() connect(dialog->position_lineEdit, &QLineEdit::editingFinished, [this, dialog]() { +#if QT_VERSION < QT_VERSION_CHECK(5, 15, 0) QStringList list = dialog->position_lineEdit->text().split(QRegExp(","), QString::SkipEmptyParts); +#else + QStringList list = dialog->position_lineEdit->text().split(QRegExp(","), Qt::SkipEmptyParts); +#endif if (list.isEmpty()) return; if (list.size()!=3){ QMessageBox *msgBox = new QMessageBox; From ab05dde7c2b1375a38d2f3c0b4b86f028f28cee5 Mon Sep 17 00:00:00 2001 From: Jane Tournois Date: Fri, 12 Jun 2020 08:08:56 +0200 Subject: [PATCH 517/568] fix the list of authors and add a longer "short description" --- .../Tetrahedral_remeshing/PackageDescription.txt | 14 +++++++++++--- .../Tetrahedral_remeshing.txt | 2 +- .../Tetrahedral_remeshing/Remeshing_cell_base_3.h | 2 +- .../Remeshing_triangulation_3.h | 2 +- .../Remeshing_vertex_base_3.h | 2 +- .../CGAL/Tetrahedral_remeshing/Sizing_field.h | 2 +- .../Tetrahedral_remeshing/Uniform_sizing_field.h | 2 +- .../CGAL/Tetrahedral_remeshing/internal/FMLS.h | 2 +- .../internal/collapse_short_edges.h | 2 +- .../internal/compute_c3t3_statistics.h | 2 +- .../Tetrahedral_remeshing/internal/flip_edges.h | 2 +- .../internal/smooth_vertices.h | 2 +- .../internal/split_long_edges.h | 2 +- .../internal/tetrahedral_adaptive_remeshing_impl.h | 2 +- .../internal/tetrahedral_remeshing_helpers.h | 2 +- .../tetrahedral_remeshing_io.h | 2 +- .../include/CGAL/tetrahedral_remeshing.h | 2 +- 17 files changed, 27 insertions(+), 19 deletions(-) diff --git a/Tetrahedral_remeshing/doc/Tetrahedral_remeshing/PackageDescription.txt b/Tetrahedral_remeshing/doc/Tetrahedral_remeshing/PackageDescription.txt index b0935baf35a..a1558091edb 100644 --- a/Tetrahedral_remeshing/doc/Tetrahedral_remeshing/PackageDescription.txt +++ b/Tetrahedral_remeshing/doc/Tetrahedral_remeshing/PackageDescription.txt @@ -14,17 +14,25 @@ \cgalPkgPicture{bimba_back_small.png} \cgalPkgSummaryBegin -\cgalPkgAuthors{Jane Tournois, Noura Faraj} +\cgalPkgAuthors{Jane Tournois, Noura Faraj, Jean-Marc Thiery, Tamy Boubekeur} \cgalPkgDesc{ The package provides a function for remeshing tetrahedral meshes, -targetting high quality meshes with respect to dihedral angles.} +targeting high quality meshes with respect to dihedral angles. +This practical iterative remeshing algorithm is designed to remesh +multi-material tetrahedral meshes, by iteratively performing a sequence of +elementary operations such as edge splits, edge collapses, edge flips, +and vertex relocations following a Laplacian smoothing. +The algorithm results in high-quality uniform isotropic meshes, +with the desired mesh density, +while preserving the input geometric curve and surface features. +} \cgalPkgManuals{Chapter_Tetrahedral_Remeshing,PkgTetrahedralRemeshingRef} \cgalPkgSummaryEnd \cgalPkgShortInfoBegin \cgalPkgSince{5.1} \cgalPkgDependsOn{\ref PkgTriangulation3} -\cgalPkgBib{faraj2016mvr} +\cgalPkgBib{cgal:tftb-tr} \cgalPkgLicense{\ref licensesGPL "GPL"} \cgalPkgDemo{Polyhedron demo,polyhedron_3.zip} \cgalPkgShortInfoEnd diff --git a/Tetrahedral_remeshing/doc/Tetrahedral_remeshing/Tetrahedral_remeshing.txt b/Tetrahedral_remeshing/doc/Tetrahedral_remeshing/Tetrahedral_remeshing.txt index bca4311f67d..2ec434eaa85 100644 --- a/Tetrahedral_remeshing/doc/Tetrahedral_remeshing/Tetrahedral_remeshing.txt +++ b/Tetrahedral_remeshing/doc/Tetrahedral_remeshing/Tetrahedral_remeshing.txt @@ -6,7 +6,7 @@ namespace CGAL { \anchor userchaptertetrahedralremeshing \cgalAutoToc -\authors Jane Tournois, Noura Faraj +\authors Jane Tournois, Noura Faraj, Jean-Marc Thiery, Tamy Boubekeur \image html bimba_back.png \image latex bimba_back.png diff --git a/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/Remeshing_cell_base_3.h b/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/Remeshing_cell_base_3.h index e64f67c41f2..ca287666196 100644 --- a/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/Remeshing_cell_base_3.h +++ b/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/Remeshing_cell_base_3.h @@ -8,7 +8,7 @@ // SPDX-License-Identifier: GPL-3.0-or-later OR LicenseRef-Commercial // // -// Author(s) : Jane Tournois, Noura Faraj +// Author(s) : Jane Tournois, Noura Faraj, Jean-Marc Thiery, Tamy Boubekeur #ifndef CGAL_TET_ADAPTIVE_REMESHING_CELL_BASE_3_H #define CGAL_TET_ADAPTIVE_REMESHING_CELL_BASE_3_H diff --git a/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/Remeshing_triangulation_3.h b/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/Remeshing_triangulation_3.h index 1a25ab1aace..3104978addb 100644 --- a/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/Remeshing_triangulation_3.h +++ b/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/Remeshing_triangulation_3.h @@ -8,7 +8,7 @@ // SPDX-License-Identifier: GPL-3.0-or-later OR LicenseRef-Commercial // // -// Author(s) : Jane Tournois, Noura Faraj +// Author(s) : Jane Tournois, Noura Faraj, Jean-Marc Thiery, Tamy Boubekeur #ifndef CGAL_TETRAHEDRAL_REMESHING_TRIANGULATION_H #define CGAL_TETRAHEDRAL_REMESHING_TRIANGULATION_H diff --git a/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/Remeshing_vertex_base_3.h b/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/Remeshing_vertex_base_3.h index 2d056e8e244..3d0f8b20170 100644 --- a/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/Remeshing_vertex_base_3.h +++ b/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/Remeshing_vertex_base_3.h @@ -8,7 +8,7 @@ // SPDX-License-Identifier: GPL-3.0-or-later OR LicenseRef-Commercial // // -// Author(s) : Jane Tournois, Noura Faraj +// Author(s) : Jane Tournois, Noura Faraj, Jean-Marc Thiery, Tamy Boubekeur #ifndef CGAL_TET_ADAPTIVE_REMESHING_VERTEX_BASE_3_H #define CGAL_TET_ADAPTIVE_REMESHING_VERTEX_BASE_3_H diff --git a/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/Sizing_field.h b/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/Sizing_field.h index 53448be56a8..39995cc1af0 100644 --- a/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/Sizing_field.h +++ b/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/Sizing_field.h @@ -8,7 +8,7 @@ // SPDX-License-Identifier: GPL-3.0-or-later OR LicenseRef-Commercial // // -// Author(s) : Jane Tournois, Noura Faraj +// Author(s) : Jane Tournois, Noura Faraj, Jean-Marc Thiery, Tamy Boubekeur #ifndef CGAL_SIZING_FIELD_H #define CGAL_SIZING_FIELD_H diff --git a/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/Uniform_sizing_field.h b/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/Uniform_sizing_field.h index 59c7264f502..419483d5be3 100644 --- a/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/Uniform_sizing_field.h +++ b/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/Uniform_sizing_field.h @@ -8,7 +8,7 @@ // SPDX-License-Identifier: GPL-3.0-or-later OR LicenseRef-Commercial // // -// Author(s) : Jane Tournois, Noura Faraj +// Author(s) : Jane Tournois, Noura Faraj, Jean-Marc Thiery, Tamy Boubekeur #ifndef CGAL_UNIFORM_SIZING_FIELD_H #define CGAL_UNIFORM_SIZING_FIELD_H diff --git a/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/FMLS.h b/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/FMLS.h index 07f6e3e3286..abc0b02c4be 100644 --- a/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/FMLS.h +++ b/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/FMLS.h @@ -8,7 +8,7 @@ // SPDX-License-Identifier: GPL-3.0-or-later OR LicenseRef-Commercial // // -// Author(s) : Jane Tournois, Noura Faraj +// Author(s) : Jane Tournois, Noura Faraj, Jean-Marc Thiery, Tamy Boubekeur #ifndef CGAL_TETRAHEDRAL_REMESHING_FMLS_H #define CGAL_TETRAHEDRAL_REMESHING_FMLS_H diff --git a/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/collapse_short_edges.h b/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/collapse_short_edges.h index 4e163f07372..9d96afb9c37 100644 --- a/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/collapse_short_edges.h +++ b/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/collapse_short_edges.h @@ -8,7 +8,7 @@ // SPDX-License-Identifier: GPL-3.0-or-later OR LicenseRef-Commercial // // -// Author(s) : Jane Tournois, Noura Faraj +// Author(s) : Jane Tournois, Noura Faraj, Jean-Marc Thiery, Tamy Boubekeur #ifndef CGAL_INTERNAL_COLLAPSE_SHORT_EDGES_H #define CGAL_INTERNAL_COLLAPSE_SHORT_EDGES_H diff --git a/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/compute_c3t3_statistics.h b/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/compute_c3t3_statistics.h index 15474f84825..36b93215109 100644 --- a/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/compute_c3t3_statistics.h +++ b/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/compute_c3t3_statistics.h @@ -8,7 +8,7 @@ // SPDX-License-Identifier: GPL-3.0-or-later OR LicenseRef-Commercial // // -// Author(s) : Jane Tournois, Noura Faraj +// Author(s) : Jane Tournois, Noura Faraj, Jean-Marc Thiery, Tamy Boubekeur #ifndef CGAL_TR_INTERNAL_COMPUTE_C3T3_STATISTICS_H #define CGAL_TR_INTERNAL_COMPUTE_C3T3_STATISTICS_H diff --git a/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/flip_edges.h b/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/flip_edges.h index 7a31fd3ed20..d10fa40fe45 100644 --- a/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/flip_edges.h +++ b/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/flip_edges.h @@ -8,7 +8,7 @@ // SPDX-License-Identifier: GPL-3.0-or-later OR LicenseRef-Commercial // // -// Author(s) : Jane Tournois, Noura Faraj +// Author(s) : Jane Tournois, Noura Faraj, Jean-Marc Thiery, Tamy Boubekeur #ifndef CGAL_INTERNAL_FLIP_EDGES_H #define CGAL_INTERNAL_FLIP_EDGES_H diff --git a/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/smooth_vertices.h b/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/smooth_vertices.h index 04e20d13d92..947123166e0 100644 --- a/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/smooth_vertices.h +++ b/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/smooth_vertices.h @@ -8,7 +8,7 @@ // SPDX-License-Identifier: GPL-3.0-or-later OR LicenseRef-Commercial // // -// Author(s) : Jane Tournois, Noura Faraj +// Author(s) : Jane Tournois, Noura Faraj, Jean-Marc Thiery, Tamy Boubekeur #ifndef CGAL_INTERNAL_SMOOTH_VERTICES_H #define CGAL_INTERNAL_SMOOTH_VERTICES_H diff --git a/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/split_long_edges.h b/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/split_long_edges.h index f75c940d080..0c6f19a30c9 100644 --- a/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/split_long_edges.h +++ b/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/split_long_edges.h @@ -8,7 +8,7 @@ // SPDX-License-Identifier: GPL-3.0-or-later OR LicenseRef-Commercial // // -// Author(s) : Jane Tournois, Noura Faraj +// Author(s) : Jane Tournois, Noura Faraj, Jean-Marc Thiery, Tamy Boubekeur #ifndef CGAL_INTERNAL_SPLIT_LONG_EDGES_H #define CGAL_INTERNAL_SPLIT_LONG_EDGES_H diff --git a/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/tetrahedral_adaptive_remeshing_impl.h b/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/tetrahedral_adaptive_remeshing_impl.h index fb4234781ee..dfe3ce5fa27 100644 --- a/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/tetrahedral_adaptive_remeshing_impl.h +++ b/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/tetrahedral_adaptive_remeshing_impl.h @@ -8,7 +8,7 @@ // SPDX-License-Identifier: GPL-3.0-or-later OR LicenseRef-Commercial // // -// Author(s) : Jane Tournois, Noura Faraj +// Author(s) : Jane Tournois, Noura Faraj, Jean-Marc Thiery, Tamy Boubekeur #ifndef TETRAHEDRAL_REMESHING_IMPL_H #define TETRAHEDRAL_REMESHING_IMPL_H diff --git a/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/tetrahedral_remeshing_helpers.h b/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/tetrahedral_remeshing_helpers.h index d8e18c6d8fe..e76d4adfe26 100644 --- a/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/tetrahedral_remeshing_helpers.h +++ b/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/tetrahedral_remeshing_helpers.h @@ -8,7 +8,7 @@ // SPDX-License-Identifier: GPL-3.0-or-later OR LicenseRef-Commercial // // -// Author(s) : Jane Tournois, Noura Faraj +// Author(s) : Jane Tournois, Noura Faraj, Jean-Marc Thiery, Tamy Boubekeur #ifndef CGAL_INTERNAL_TET_REMESHING_HELPERS_H #define CGAL_INTERNAL_TET_REMESHING_HELPERS_H diff --git a/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/tetrahedral_remeshing_io.h b/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/tetrahedral_remeshing_io.h index 7ecfff2b82c..cda012efc51 100644 --- a/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/tetrahedral_remeshing_io.h +++ b/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/tetrahedral_remeshing_io.h @@ -8,7 +8,7 @@ // SPDX-License-Identifier: GPL-3.0-or-later OR LicenseRef-Commercial // // -// Author(s) : Jane Tournois, Noura Faraj +// Author(s) : Jane Tournois, Noura Faraj, Jean-Marc Thiery, Tamy Boubekeur #include diff --git a/Tetrahedral_remeshing/include/CGAL/tetrahedral_remeshing.h b/Tetrahedral_remeshing/include/CGAL/tetrahedral_remeshing.h index 7877002a0d5..b59f055e585 100644 --- a/Tetrahedral_remeshing/include/CGAL/tetrahedral_remeshing.h +++ b/Tetrahedral_remeshing/include/CGAL/tetrahedral_remeshing.h @@ -8,7 +8,7 @@ // SPDX-License-Identifier: GPL-3.0-or-later OR LicenseRef-Commercial // // -// Author(s) : Jane Tournois, Noura Faraj +// Author(s) : Jane Tournois, Noura Faraj, Jean-Marc Thiery, Tamy Boubekeur #ifndef TETRAHEDRAL_REMESHING_H #define TETRAHEDRAL_REMESHING_H From 857dcaceb9ee838a92d33be3ad4718faec7404c1 Mon Sep 17 00:00:00 2001 From: Maxime Gimeno Date: Fri, 12 Jun 2020 09:38:27 +0200 Subject: [PATCH 518/568] Add missing find_package(Qt5) for Hyperbolic_triangulation_2 demo --- .../demo/Hyperbolic_triangulation_2/CMakeLists.txt | 3 +++ 1 file changed, 3 insertions(+) diff --git a/Hyperbolic_triangulation_2/demo/Hyperbolic_triangulation_2/CMakeLists.txt b/Hyperbolic_triangulation_2/demo/Hyperbolic_triangulation_2/CMakeLists.txt index e2ddcf402db..61dd2e41455 100644 --- a/Hyperbolic_triangulation_2/demo/Hyperbolic_triangulation_2/CMakeLists.txt +++ b/Hyperbolic_triangulation_2/demo/Hyperbolic_triangulation_2/CMakeLists.txt @@ -14,6 +14,9 @@ endif() find_package(CGAL REQUIRED QUIET OPTIONAL_COMPONENTS Core Qt5) find_package(LEDA QUIET) +# Find Qt5 itself +find_package(Qt5 QUIET COMPONENTS OpenGL Gui) + if(CGAL_FOUND AND CGAL_Qt5_FOUND AND Qt5_FOUND AND (CGAL_Core_FOUND OR LEDA_FOUND)) include_directories( BEFORE ./ ./include ) # ui files, created with Qt Designer From 7de5f28310f390b441957d9a5fe98ae0e31aee35 Mon Sep 17 00:00:00 2001 From: Maxime Gimeno Date: Fri, 12 Jun 2020 09:41:02 +0200 Subject: [PATCH 519/568] Fix pmp example about eigen --- .../examples/Polygon_mesh_processing/CMakeLists.txt | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/Polygon_mesh_processing/examples/Polygon_mesh_processing/CMakeLists.txt b/Polygon_mesh_processing/examples/Polygon_mesh_processing/CMakeLists.txt index 46a7f04d886..8f748d69246 100644 --- a/Polygon_mesh_processing/examples/Polygon_mesh_processing/CMakeLists.txt +++ b/Polygon_mesh_processing/examples/Polygon_mesh_processing/CMakeLists.txt @@ -57,6 +57,8 @@ if (TARGET CGAL::Eigen_support) target_link_libraries(shape_smoothing_example PUBLIC CGAL::Eigen_support) create_single_source_cgal_program( "hole_filling_example_LCC.cpp" ) target_link_libraries(hole_filling_example_LCC PUBLIC CGAL::Eigen_support) + create_single_source_cgal_program( "mesh_smoothing_example.cpp") + target_link_libraries(mesh_smoothing_example PUBLIC CGAL::Eigen_support) endif() create_single_source_cgal_program( "self_intersections_example.cpp" ) @@ -87,7 +89,6 @@ create_single_source_cgal_program( "detect_features_example.cpp" ) create_single_source_cgal_program( "volume_connected_components.cpp" ) create_single_source_cgal_program( "manifoldness_repair_example.cpp" ) create_single_source_cgal_program( "repair_polygon_soup_example.cpp" ) -create_single_source_cgal_program( "mesh_smoothing_example.cpp") create_single_source_cgal_program( "locate_example.cpp") create_single_source_cgal_program( "orientation_pipeline_example.cpp") #create_single_source_cgal_program( "self_snapping_example.cpp") From 624e8e803af285db1fa110bfbb03c0a7373c5540 Mon Sep 17 00:00:00 2001 From: Maxime Gimeno Date: Fri, 12 Jun 2020 10:34:48 +0200 Subject: [PATCH 520/568] Fix flag fix --- GraphicsView/include/CGAL/Qt/DemosMainWindow.h | 2 +- GraphicsView/include/CGAL/Qt/qglviewer.h | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/GraphicsView/include/CGAL/Qt/DemosMainWindow.h b/GraphicsView/include/CGAL/Qt/DemosMainWindow.h index 856943ad247..34dab58fbfc 100644 --- a/GraphicsView/include/CGAL/Qt/DemosMainWindow.h +++ b/GraphicsView/include/CGAL/Qt/DemosMainWindow.h @@ -72,7 +72,7 @@ private: QMenu* getHelpMenu(); protected: - DemosMainWindow (QWidget * parent = 0, ::Qt::WindowFlags flags = ::Qt::WindowFlags(0) ); + DemosMainWindow (QWidget * parent = 0, ::Qt::WindowFlags flags = ::Qt::WindowType(0) ); ~DemosMainWindow(); void setupStatusBar(); void addNavigation(QGraphicsView*); diff --git a/GraphicsView/include/CGAL/Qt/qglviewer.h b/GraphicsView/include/CGAL/Qt/qglviewer.h index 2db183e6bce..8b3ff179e9c 100644 --- a/GraphicsView/include/CGAL/Qt/qglviewer.h +++ b/GraphicsView/include/CGAL/Qt/qglviewer.h @@ -73,11 +73,11 @@ class CGAL_QT_EXPORT QGLViewer : public QOpenGLWidget, public QOpenGLFunctions { public: //todo check if this is used. If not remove it explicit QGLViewer(QGLContext* context, QWidget *parent = 0, - ::Qt::WindowFlags flags = ::Qt::WindowFlags(0)); + ::Qt::WindowFlags flags = ::Qt::WindowType(0)); explicit QGLViewer(QOpenGLContext* context, QWidget *parent = 0, - ::Qt::WindowFlags flags = ::Qt::WindowFlags(0)); + ::Qt::WindowFlags flags = ::Qt::WindowType(0)); explicit QGLViewer(QWidget *parent = 0, - ::Qt::WindowFlags flags = ::Qt::WindowFlags(0)); + ::Qt::WindowFlags flags = ::Qt::WindowType(0)); virtual ~QGLViewer(); From 77af45afc11d72f077b3078e71d7e8c805087f65 Mon Sep 17 00:00:00 2001 From: Maxime Gimeno Date: Fri, 12 Jun 2020 16:13:16 +0200 Subject: [PATCH 521/568] Fix remainings warnings, use #define for split and fix error in filterOperations --- Polyhedron/demo/Polyhedron/MainWindow.cpp | 20 ++++--- .../Plugins/PCA/Basic_generator_plugin.cpp | 55 ++++--------------- .../Plugins/PMP/Engrave_text_plugin.cpp | 2 +- .../Polyhedron/Plugins/PMP/Extrude_plugin.cpp | 2 +- .../Point_set/Point_set_selection_plugin.cpp | 2 +- .../Surface_mesh/Parameterization_plugin.cpp | 2 +- .../Scene_edit_polyhedron_item.cpp | 2 +- Polyhedron/demo/Polyhedron/Viewer.cpp | 12 +--- Three/include/CGAL/Three/Three.h | 7 +++ 9 files changed, 35 insertions(+), 69 deletions(-) diff --git a/Polyhedron/demo/Polyhedron/MainWindow.cpp b/Polyhedron/demo/Polyhedron/MainWindow.cpp index ae829c69345..5a5ed733a40 100644 --- a/Polyhedron/demo/Polyhedron/MainWindow.cpp +++ b/Polyhedron/demo/Polyhedron/MainWindow.cpp @@ -9,6 +9,7 @@ #include #include #include +#include #include #include @@ -401,6 +402,7 @@ MainWindow::MainWindow(const QStringList &keywords, bool verbose, QWidget* paren objectValue); } } + filterOperations(true); // debugger->action(QScriptEngineDebugger::InterruptAction)->trigger(); #endif } @@ -413,10 +415,14 @@ void addActionToMenu(QAction* action, QMenu* menu) QString atxt = action->text().remove("&"), btxt = it->text().remove("&"); int i = 0; - while(atxt[i] == btxt[i] - && i < atxt.size() - && i < btxt.size()) + if(atxt.isEmpty() || btxt.isEmpty()) + continue; + while(i < atxt.size() + && i < btxt.size() + && atxt[i] == btxt[i]) ++i; + if(i == atxt.size() || i == btxt.size()) + continue; bool res = (atxt[i] < btxt[i]); if (res) { @@ -490,12 +496,12 @@ void MainWindow::filterOperations(bool) menu->removeAction(action); } } + Q_FOREACH(QAction* action, action_menu_map.keys()) { QMenu* menu = action_menu_map[action]; addActionToMenu(action, menu); } - QString filter=operationSearchBar.text(); Q_FOREACH(const PluginNamePair& p, plugins) { Q_FOREACH(QAction* action, p.first->actions()) { @@ -765,11 +771,7 @@ void MainWindow::loadPlugins() qputenv("PATH", new_path); #endif Q_FOREACH (QString pluginsDir, - #if QT_VERSION < QT_VERSION_CHECK(5, 15, 0) - env_path.split(separator, QString::SkipEmptyParts)) { - #else - env_path.split(separator, Qt::SkipEmptyParts)) { - #endif + env_path.split(separator, SkipEmptyParts)) { QDir dir(pluginsDir); if(dir.isReadable()) plugins_directories << dir; diff --git a/Polyhedron/demo/Polyhedron/Plugins/PCA/Basic_generator_plugin.cpp b/Polyhedron/demo/Polyhedron/Plugins/PCA/Basic_generator_plugin.cpp index 89637556188..02648fed359 100644 --- a/Polyhedron/demo/Polyhedron/Plugins/PCA/Basic_generator_plugin.cpp +++ b/Polyhedron/demo/Polyhedron/Plugins/PCA/Basic_generator_plugin.cpp @@ -15,6 +15,7 @@ #include "Scene_polylines_item.h" #include #include +#include #include "ui_Basic_generator_widget.h" class GeneratorWidget : @@ -350,11 +351,7 @@ void Basic_generator_plugin::generateCube() for(int i=0; i<8; ++i) { -#if QT_VERSION < QT_VERSION_CHECK(5, 15, 0) - QStringList list = point_texts[i].split(QRegExp("\\s+"), QString::SkipEmptyParts); -#else - QStringList list = point_texts[i].split(QRegExp("\\s+"), Qt::SkipEmptyParts); -#endif + QStringList list = point_texts[i].split(QRegExp("\\s+"), SkipEmptyParts); if (list.isEmpty()) return; if (list.size()!=3){ QMessageBox *msgBox = new QMessageBox; @@ -395,11 +392,7 @@ void Basic_generator_plugin::generateCube() else { QString text = dock_widget->extremaEdit->text(); -#if QT_VERSION < QT_VERSION_CHECK(5, 15, 0) - QStringList list = text.split(QRegExp("\\s+"), QString::SkipEmptyParts); -#else - QStringList list = text.split(QRegExp("\\s+"), Qt::SkipEmptyParts); -#endif + QStringList list = text.split(QRegExp("\\s+"), SkipEmptyParts); if (list.isEmpty()) return; if (list.size()!=6){ QMessageBox *msgBox = new QMessageBox; @@ -450,11 +443,7 @@ void Basic_generator_plugin::generatePrism() bool is_closed = dock_widget->prismCheckBox->isChecked(); QString text = dock_widget->prism_lineEdit->text(); -#if QT_VERSION < QT_VERSION_CHECK(5, 15, 0) - QStringList list = text.split(QRegExp("\\s+"), QString::SkipEmptyParts); -#else - QStringList list = text.split(QRegExp("\\s+"), Qt::SkipEmptyParts); -#endif + QStringList list = text.split(QRegExp("\\s+"), SkipEmptyParts); if (list.isEmpty()) return; if (list.size()!=3){ QMessageBox *msgBox = new QMessageBox; @@ -501,11 +490,7 @@ void Basic_generator_plugin::generatePyramid() bool is_closed = dock_widget->pyramidCheckBox->isChecked(); QString text = dock_widget->pyramid_lineEdit->text(); -#if QT_VERSION < QT_VERSION_CHECK(5, 15, 0) - QStringList list = text.split(QRegExp("\\s+"), QString::SkipEmptyParts); -#else - QStringList list = text.split(QRegExp("\\s+"), Qt::SkipEmptyParts); -#endif + QStringList list = text.split(QRegExp("\\s+"), SkipEmptyParts); if (list.isEmpty()) return; if (list.size()!=3){ QMessageBox *msgBox = new QMessageBox; @@ -548,11 +533,7 @@ void Basic_generator_plugin::generateSphere() { int precision = dock_widget->SphereSpinBox->value(); QString text = dock_widget->center_radius_lineEdit->text(); -#if QT_VERSION < QT_VERSION_CHECK(5, 15, 0) - QStringList list = text.split(QRegExp("\\s+"), QString::SkipEmptyParts); -#else - QStringList list = text.split(QRegExp("\\s+"), Qt::SkipEmptyParts); -#endif + QStringList list = text.split(QRegExp("\\s+"), SkipEmptyParts); if (list.isEmpty()) return; if (list.size()!=4){ QMessageBox *msgBox = new QMessageBox; @@ -601,11 +582,7 @@ void Basic_generator_plugin::generateTetrahedron() for(int i=0; i<4; ++i) { -#if QT_VERSION < QT_VERSION_CHECK(5, 15, 0) - QStringList list = point_texts[i].split(QRegExp("\\s+"), QString::SkipEmptyParts); -#else - QStringList list = point_texts[i].split(QRegExp("\\s+"), Qt::SkipEmptyParts); -#endif + QStringList list = point_texts[i].split(QRegExp("\\s+"), SkipEmptyParts); if (list.isEmpty()) return; if (list.size()!=3){ QMessageBox *msgBox = new QMessageBox; @@ -646,11 +623,7 @@ void Basic_generator_plugin::generatePoints() { QString text = dock_widget->point_textEdit->toPlainText(); Scene_points_with_normal_item* item = new Scene_points_with_normal_item(); -#if QT_VERSION < QT_VERSION_CHECK(5, 15, 0) - QStringList list = text.split(QRegExp("\\s+"), QString::SkipEmptyParts); -#else - QStringList list = text.split(QRegExp("\\s+"), Qt::SkipEmptyParts); -#endif + QStringList list = text.split(QRegExp("\\s+"), SkipEmptyParts); int counter = 0; double coord[3]; bool ok = true; @@ -709,11 +682,7 @@ void Basic_generator_plugin::generateLines() std::vector& polyline = *(polylines.rbegin()); QStringList polylines_metadata; -#if QT_VERSION < QT_VERSION_CHECK(5, 15, 0) - QStringList list = text.split(QRegExp("\\s+"), QString::SkipEmptyParts); -#else - QStringList list = text.split(QRegExp("\\s+"), Qt::SkipEmptyParts); -#endif + QStringList list = text.split(QRegExp("\\s+"), SkipEmptyParts); int counter = 0; double coord[3]; bool ok = true; @@ -813,11 +782,7 @@ void Basic_generator_plugin::generateGrid() bool triangulated = dock_widget->grid_checkBox->isChecked(); points_text= dock_widget->grid_lineEdit->text(); -#if QT_VERSION < QT_VERSION_CHECK(5, 15, 0) - QStringList list = points_text.split(QRegExp("\\s+"), QString::SkipEmptyParts); -#else - QStringList list = points_text.split(QRegExp("\\s+"), Qt::SkipEmptyParts); -#endif + QStringList list = points_text.split(QRegExp("\\s+"), SkipEmptyParts); if (list.isEmpty()) return; if (list.size()!=6){ QMessageBox *msgBox = new QMessageBox; diff --git a/Polyhedron/demo/Polyhedron/Plugins/PMP/Engrave_text_plugin.cpp b/Polyhedron/demo/Polyhedron/Plugins/PMP/Engrave_text_plugin.cpp index dc8eff3084c..bfb6d3c4311 100644 --- a/Polyhedron/demo/Polyhedron/Plugins/PMP/Engrave_text_plugin.cpp +++ b/Polyhedron/demo/Polyhedron/Plugins/PMP/Engrave_text_plugin.cpp @@ -250,7 +250,7 @@ protected: case QEvent::Wheel: { QWheelEvent* event = static_cast(ev); QPointF old_pos = v->mapToScene(event->pos()); - if(event->delta() <0) + if(event->angleDelta().y() <0) v->scale(1.2, 1.2); else v->scale(0.8, 0.8); diff --git a/Polyhedron/demo/Polyhedron/Plugins/PMP/Extrude_plugin.cpp b/Polyhedron/demo/Polyhedron/Plugins/PMP/Extrude_plugin.cpp index 1cb943cf4d6..308bd503d95 100644 --- a/Polyhedron/demo/Polyhedron/Plugins/PMP/Extrude_plugin.cpp +++ b/Polyhedron/demo/Polyhedron/Plugins/PMP/Extrude_plugin.cpp @@ -116,7 +116,7 @@ public : if(event->type() == QEvent::Wheel && ctrl_pressing) { QWheelEvent *mouseEvent = static_cast(event); - int steps = mouseEvent->delta() / 120; + int steps = mouseEvent->angleDelta().y() / 120; if (steps > 0) length_+=tick; else diff --git a/Polyhedron/demo/Polyhedron/Plugins/Point_set/Point_set_selection_plugin.cpp b/Polyhedron/demo/Polyhedron/Plugins/Point_set/Point_set_selection_plugin.cpp index 7c81fbd6e23..59c7c2c9224 100644 --- a/Polyhedron/demo/Polyhedron/Plugins/Point_set/Point_set_selection_plugin.cpp +++ b/Polyhedron/demo/Polyhedron/Plugins/Point_set/Point_set_selection_plugin.cpp @@ -708,7 +708,7 @@ protected: { QApplication::setOverrideCursor(Qt::WaitCursor); QWheelEvent *mouseEvent = static_cast(event); - int steps = mouseEvent->delta() / 120; + int steps = mouseEvent->angleDelta().y() / 120; if (steps > 0) neighborhood.point_set (point_set_item).expand(); else diff --git a/Polyhedron/demo/Polyhedron/Plugins/Surface_mesh/Parameterization_plugin.cpp b/Polyhedron/demo/Polyhedron/Plugins/Surface_mesh/Parameterization_plugin.cpp index ba2a234e0fa..9883c1d376a 100644 --- a/Polyhedron/demo/Polyhedron/Plugins/Surface_mesh/Parameterization_plugin.cpp +++ b/Polyhedron/demo/Polyhedron/Plugins/Surface_mesh/Parameterization_plugin.cpp @@ -144,7 +144,7 @@ protected: case QEvent::Wheel: { QWheelEvent* event = static_cast(ev); QPointF old_pos = v->mapToScene(event->pos()); - if(event->delta() <0) + if(event->angleDelta().y() <0) v->scale(1.2, 1.2); else v->scale(0.8, 0.8); diff --git a/Polyhedron/demo/Polyhedron/Plugins/Surface_mesh_deformation/Scene_edit_polyhedron_item.cpp b/Polyhedron/demo/Polyhedron/Plugins/Surface_mesh_deformation/Scene_edit_polyhedron_item.cpp index 48d85e15612..c6ab13f76f6 100644 --- a/Polyhedron/demo/Polyhedron/Plugins/Surface_mesh_deformation/Scene_edit_polyhedron_item.cpp +++ b/Polyhedron/demo/Polyhedron/Plugins/Surface_mesh_deformation/Scene_edit_polyhedron_item.cpp @@ -885,7 +885,7 @@ bool Scene_edit_polyhedron_item::eventFilter(QObject* /*target*/, QEvent *event) &&d->state.shift_pressing) { QWheelEvent *w_event = static_cast(event); - int steps = w_event->delta() / 120; + int steps = w_event->angleDelta().y() / 120; d->expand_or_reduce(steps, d->sm_item->polyhedron()); } if(event->type() == QEvent::MouseButtonPress || event->type() == QEvent::MouseButtonRelease) diff --git a/Polyhedron/demo/Polyhedron/Viewer.cpp b/Polyhedron/demo/Polyhedron/Viewer.cpp index 0a41f43ea04..3b483fb9723 100644 --- a/Polyhedron/demo/Polyhedron/Viewer.cpp +++ b/Polyhedron/demo/Polyhedron/Viewer.cpp @@ -852,11 +852,7 @@ void Viewer::postSelection(const QPoint& pixel) } bool CGAL::Three::Viewer_interface::readFrame(QString s, CGAL::qglviewer::Frame& frame) { -#if QT_VERSION < QT_VERSION_CHECK(5, 15, 0) - QStringList list = s.split(" ", QString::SkipEmptyParts); -#else - QStringList list = s.split(" ", ::Qt::SkipEmptyParts); -#endif + QStringList list = s.split(" ", SkipEmptyParts); if(list.size() != 7) return false; float vec[3]; @@ -1785,11 +1781,7 @@ void Viewer::setLighting() connect(dialog->position_lineEdit, &QLineEdit::editingFinished, [this, dialog]() { -#if QT_VERSION < QT_VERSION_CHECK(5, 15, 0) - QStringList list = dialog->position_lineEdit->text().split(QRegExp(","), QString::SkipEmptyParts); -#else - QStringList list = dialog->position_lineEdit->text().split(QRegExp(","), Qt::SkipEmptyParts); -#endif + QStringList list = dialog->position_lineEdit->text().split(QRegExp(","), SkipEmptyParts); if (list.isEmpty()) return; if (list.size()!=3){ QMessageBox *msgBox = new QMessageBox; diff --git a/Three/include/CGAL/Three/Three.h b/Three/include/CGAL/Three/Three.h index 38b2ac8ea7d..70c040edffd 100644 --- a/Three/include/CGAL/Three/Three.h +++ b/Three/include/CGAL/Three/Three.h @@ -29,8 +29,15 @@ # define THREE_EXPORT Q_DECL_IMPORT #endif +#if QT_VERSION < QT_VERSION_CHECK(5, 15, 0) +#define SkipEmptyParts QString::SkipEmptyParts +#else +#define SkipEmptyParts ::Qt::SkipEmptyParts +#endif + namespace CGAL{ namespace Three{ +//define enum depending on Qt version class Polyhedron_demo_plugin_interface; class THREE_EXPORT Three{ public: From 8205112d1c27ef892e753cba4c384aa8ea73b577 Mon Sep 17 00:00:00 2001 From: Laurent Rineau Date: Fri, 12 Jun 2020 16:44:43 +0200 Subject: [PATCH 522/568] I forgot to check outside include/ for cpp11 stuff --- .../reconstruction_structured.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/Advancing_front_surface_reconstruction/examples/Advancing_front_surface_reconstruction/reconstruction_structured.cpp b/Advancing_front_surface_reconstruction/examples/Advancing_front_surface_reconstruction/reconstruction_structured.cpp index d944cf985df..d2dda3af49c 100644 --- a/Advancing_front_surface_reconstruction/examples/Advancing_front_surface_reconstruction/reconstruction_structured.cpp +++ b/Advancing_front_surface_reconstruction/examples/Advancing_front_surface_reconstruction/reconstruction_structured.cpp @@ -1,6 +1,7 @@ #include #include #include +#include #include #include @@ -36,7 +37,7 @@ typedef CGAL::Triangulation_data_structure_3 Tds; typedef CGAL::Delaunay_triangulation_3 Triangulation_3; typedef Triangulation_3::Vertex_handle Vertex_handle; -typedef CGAL::cpp11::array Facet; +typedef std::array Facet; // Functor to init the advancing front algorithm with indexed points From d263a63925f2da79fcac9a17aee82ba8f9411543 Mon Sep 17 00:00:00 2001 From: Laurent Rineau Date: Fri, 12 Jun 2020 20:43:42 +0200 Subject: [PATCH 523/568] Refresh examples/Mesh_3/CMakeLists.txt ... and remove the use of the variable `WITH_CGAL_ImageIO`. --- Mesh_3/examples/Mesh_3/CMakeLists.txt | 324 +++++++++++--------------- 1 file changed, 142 insertions(+), 182 deletions(-) diff --git a/Mesh_3/examples/Mesh_3/CMakeLists.txt b/Mesh_3/examples/Mesh_3/CMakeLists.txt index 851ce574dec..cd46b2a100e 100644 --- a/Mesh_3/examples/Mesh_3/CMakeLists.txt +++ b/Mesh_3/examples/Mesh_3/CMakeLists.txt @@ -1,195 +1,155 @@ -# Created by the script cgal_create_cmake_script -# This is the CMake script for compiling a CGAL application. - - cmake_minimum_required(VERSION 3.1...3.15) project( Mesh_3_Examples ) - - add_definitions(-DCGAL_MESH_3_NO_DEPRECATED_SURFACE_INDEX -DCGAL_MESH_3_NO_DEPRECATED_C3T3_ITERATORS) -if ( MESH_3_VERBOSE ) +if ( CGAL_MESH_3_VERBOSE ) add_definitions(-DCGAL_MESH_3_VERBOSE) endif() -if(POLICY CMP0074) - cmake_policy(SET CMP0074 NEW) -endif() - find_package(CGAL COMPONENTS ImageIO) +find_package(Boost) -if ( CGAL_FOUND ) - include( ${CGAL_USE_FILE} ) +option(CGAL_ACTIVATE_CONCURRENT_MESH_3 "Activate parallelism in Mesh_3" OFF) - find_package(Boost) - - # Activate concurrency ? (turned OFF by default) - option(CGAL_ACTIVATE_CONCURRENT_MESH_3 - "Activate parallelism in Mesh_3" - OFF) - - # And add -DCGAL_CONCURRENT_MESH_3 if that option is ON - if( CGAL_ACTIVATE_CONCURRENT_MESH_3 OR ENV{CGAL_ACTIVATE_CONCURRENT_MESH_3} ) - add_definitions( -DCGAL_CONCURRENT_MESH_3 ) - find_package( TBB REQUIRED ) - include(CGAL_TBB_support) - else( CGAL_ACTIVATE_CONCURRENT_MESH_3 OR ENV{CGAL_ACTIVATE_CONCURRENT_MESH_3} ) - option( LINK_WITH_TBB - "Link with TBB anyway so we can use TBB timers for profiling" - ON) - if( LINK_WITH_TBB ) - find_package( TBB ) - include(CGAL_TBB_support) - endif( LINK_WITH_TBB ) - endif() - - # Use Eigen - find_package(Eigen3 3.1.0 REQUIRED) #(3.1.0 or greater) - include(CGAL_Eigen_support) - if (NOT TARGET CGAL::Eigen_support) - message(STATUS "This project requires the Eigen library, and will not be compiled.") - return() - endif() - - find_package(VTK QUIET COMPONENTS vtkImagingGeneral vtkIOImage NO_MODULE) - if(VTK_FOUND) - if(VTK_USE_FILE) - include(${VTK_USE_FILE}) - endif() - if ("${VTK_VERSION_MAJOR}" GREATER "5" OR VTK_VERSION VERSION_GREATER 5) - message(STATUS "VTK found") - if(TARGET VTK::IOImage) - set(VTK_LIBRARIES VTK::ImagingGeneral VTK::IOImage) - endif() - else() - message(STATUS "VTK version 6.0 or greater is required") - endif() - else() - message(STATUS "VTK was not found") - endif() - - - # Compilable examples - create_single_source_cgal_program( "mesh_hybrid_mesh_domain.cpp" ) - target_link_libraries(mesh_hybrid_mesh_domain PUBLIC CGAL::Eigen_support) - - create_single_source_cgal_program( "mesh_implicit_sphere.cpp" ) - target_link_libraries(mesh_implicit_sphere PUBLIC CGAL::Eigen_support) - - create_single_source_cgal_program( "mesh_implicit_sphere_variable_size.cpp" ) - target_link_libraries(mesh_implicit_sphere_variable_size PUBLIC CGAL::Eigen_support) - - create_single_source_cgal_program( "mesh_two_implicit_spheres_with_balls.cpp" ) - target_link_libraries(mesh_two_implicit_spheres_with_balls PUBLIC CGAL::Eigen_support) - - create_single_source_cgal_program( "mesh_implicit_domains_2.cpp" "implicit_functions.cpp" ) - target_link_libraries(mesh_implicit_domains_2 PUBLIC CGAL::Eigen_support) - - create_single_source_cgal_program( "mesh_cubes_intersection.cpp" ) - target_link_libraries(mesh_cubes_intersection PUBLIC CGAL::Eigen_support) - - create_single_source_cgal_program( "mesh_cubes_intersection_with_features.cpp" ) - target_link_libraries(mesh_cubes_intersection_with_features PUBLIC CGAL::Eigen_support) - - create_single_source_cgal_program( "mesh_implicit_domains.cpp" "implicit_functions.cpp" ) - target_link_libraries(mesh_implicit_domains PUBLIC CGAL::Eigen_support) - - create_single_source_cgal_program( "mesh_polyhedral_domain.cpp" ) - target_link_libraries(mesh_polyhedral_domain PUBLIC CGAL::Eigen_support) - - create_single_source_cgal_program( "mesh_polyhedral_domain_sm.cpp" ) - target_link_libraries(mesh_polyhedral_domain_sm PUBLIC CGAL::Eigen_support) - - create_single_source_cgal_program( "mesh_polyhedral_domain_with_surface_inside.cpp" ) - target_link_libraries(mesh_polyhedral_domain_with_surface_inside PUBLIC CGAL::Eigen_support) - - create_single_source_cgal_program( "remesh_polyhedral_surface.cpp" ) - target_link_libraries(remesh_polyhedral_surface PUBLIC CGAL::Eigen_support) - - create_single_source_cgal_program( "remesh_polyhedral_surface_sm.cpp" ) - target_link_libraries(remesh_polyhedral_surface_sm PUBLIC CGAL::Eigen_support) - - create_single_source_cgal_program( "mesh_polyhedral_domain_with_features.cpp" ) - target_link_libraries(mesh_polyhedral_domain_with_features PUBLIC CGAL::Eigen_support) - - create_single_source_cgal_program( "mesh_polyhedral_domain_with_features_sm.cpp" ) - target_link_libraries(mesh_polyhedral_domain_with_features_sm PUBLIC CGAL::Eigen_support) - - create_single_source_cgal_program( "mesh_polyhedral_domain_with_lipschitz_sizing.cpp" ) - target_link_libraries(mesh_polyhedral_domain_with_lipschitz_sizing PUBLIC CGAL::Eigen_support) - - create_single_source_cgal_program( "mesh_polyhedral_complex.cpp" ) - target_link_libraries(mesh_polyhedral_complex PUBLIC CGAL::Eigen_support) - - create_single_source_cgal_program( "mesh_polyhedral_complex_sm.cpp" ) - target_link_libraries(mesh_polyhedral_complex_sm PUBLIC CGAL::Eigen_support) - - if( WITH_CGAL_ImageIO ) - if( VTK_FOUND AND ("${VTK_VERSION_MAJOR}" GREATER "5" OR VTK_VERSION VERSION_GREATER 5) ) - add_executable ( mesh_3D_gray_vtk_image mesh_3D_gray_vtk_image.cpp ) - target_link_libraries( mesh_3D_gray_vtk_image PUBLIC CGAL::Eigen_support ${CGAL_LIBRARIES} ${CGAL_3RD_PARTY_LIBRARIES} ${VTK_LIBRARIES}) - cgal_add_test( mesh_3D_gray_vtk_image ) - add_to_cached_list( CGAL_EXECUTABLE_TARGETS mesh_3D_gray_vtk_image ) - endif() - - create_single_source_cgal_program( "mesh_3D_gray_image.cpp" ) - target_link_libraries(mesh_3D_gray_image PUBLIC CGAL::Eigen_support) - - create_single_source_cgal_program( "mesh_3D_gray_image_multiple_values.cpp" ) - target_link_libraries(mesh_3D_gray_image_multiple_values PUBLIC CGAL::Eigen_support) - - create_single_source_cgal_program( "mesh_3D_image_with_features.cpp" ) - target_link_libraries(mesh_3D_image_with_features PUBLIC CGAL::Eigen_support) - - if( CGAL_ImageIO_USE_ZLIB ) - create_single_source_cgal_program( "mesh_optimization_example.cpp" ) - target_link_libraries(mesh_optimization_example PUBLIC CGAL::Eigen_support) - - create_single_source_cgal_program( "mesh_optimization_lloyd_example.cpp" ) - target_link_libraries(mesh_optimization_lloyd_example PUBLIC CGAL::Eigen_support) - - create_single_source_cgal_program( "mesh_3D_image.cpp" ) - target_link_libraries(mesh_3D_image PUBLIC CGAL::Eigen_support) - - create_single_source_cgal_program( "mesh_3D_image_with_custom_initialization.cpp" ) - target_link_libraries(mesh_3D_image_with_custom_initialization PUBLIC CGAL::Eigen_support) - - create_single_source_cgal_program( "mesh_3D_image_variable_size.cpp" ) - target_link_libraries(mesh_3D_image_variable_size PUBLIC CGAL::Eigen_support) - else() - message( STATUS "NOTICE: The examples mesh_3D_image.cpp, mesh_3D_image_variable_size.cpp, mesh_optimization_example.cpp and mesh_optimization_lloyd_example.cpp need CGAL_ImageIO to be configured with ZLIB support, and will not be compiled." ) - endif() - else() - message( STATUS "NOTICE: Some examples need the CGAL_ImageIO library, and will not be compiled." ) - endif() - -# create_single_source_cgal_program( "mesh_polyhedral_implicit_function.cpp" ) -# create_single_source_cgal_program( "mesh_polyhedral_surface_tolerance_region.cpp" ) -# create_single_source_cgal_program( "mesh_polyhedral_edge_tolerance_region.cpp" ) - - if(CGAL_ACTIVATE_CONCURRENT_MESH_3 AND TARGET CGAL::TBB_support AND TARGET ${target}) - foreach(target - mesh_3D_image_with_features - mesh_3D_image - mesh_polyhedral_domain - mesh_3D_image_with_custom_initialization - mesh_two_implicit_spheres_with_balls - mesh_optimization_lloyd_example - mesh_optimization_example - mesh_implicit_sphere - mesh_polyhedral_complex_sm - mesh_implicit_sphere_variable_size - mesh_polyhedral_domain_sm - mesh_polyhedral_domain_with_lipschitz_sizing - mesh_polyhedral_complex - mesh_polyhedral_domain_with_features - mesh_3D_image_variable_size) - target_link_libraries(${target} PUBLIC CGAL::TBB_support) - endforeach() - endif() - -else() - message(STATUS "This program requires the CGAL library, and will not be compiled.") +if( CGAL_ACTIVATE_CONCURRENT_MESH_3 OR ENV{CGAL_ACTIVATE_CONCURRENT_MESH_3} ) + add_definitions( -DCGAL_CONCURRENT_MESH_3 ) + find_package( TBB REQUIRED ) + include(CGAL_TBB_support) +endif() + +# Use Eigen +find_package(Eigen3 3.1.0 REQUIRED) #(3.1.0 or greater) +include(CGAL_Eigen_support) + +find_package(VTK QUIET COMPONENTS vtkImagingGeneral vtkIOImage NO_MODULE) +if(VTK_FOUND) + if(VTK_USE_FILE) + include(${VTK_USE_FILE}) + endif() + if ("${VTK_VERSION_MAJOR}" GREATER "5" OR VTK_VERSION VERSION_GREATER 5) + message(STATUS "VTK found") + if(TARGET VTK::IOImage) + set(VTK_LIBRARIES VTK::ImagingGeneral VTK::IOImage) + endif() + else() + message(STATUS "VTK version 6.0 or greater is required") + endif() +else() + message(STATUS "VTK was not found") +endif() + +create_single_source_cgal_program( "mesh_hybrid_mesh_domain.cpp" ) +target_link_libraries(mesh_hybrid_mesh_domain PUBLIC CGAL::Eigen_support) + +create_single_source_cgal_program( "mesh_implicit_sphere.cpp" ) +target_link_libraries(mesh_implicit_sphere PUBLIC CGAL::Eigen_support) + +create_single_source_cgal_program( "mesh_implicit_sphere_variable_size.cpp" ) +target_link_libraries(mesh_implicit_sphere_variable_size PUBLIC CGAL::Eigen_support) + +create_single_source_cgal_program( "mesh_two_implicit_spheres_with_balls.cpp" ) +target_link_libraries(mesh_two_implicit_spheres_with_balls PUBLIC CGAL::Eigen_support) + +create_single_source_cgal_program( "mesh_implicit_domains_2.cpp" "implicit_functions.cpp" ) +target_link_libraries(mesh_implicit_domains_2 PUBLIC CGAL::Eigen_support) + +create_single_source_cgal_program( "mesh_cubes_intersection.cpp" ) +target_link_libraries(mesh_cubes_intersection PUBLIC CGAL::Eigen_support) + +create_single_source_cgal_program( "mesh_cubes_intersection_with_features.cpp" ) +target_link_libraries(mesh_cubes_intersection_with_features PUBLIC CGAL::Eigen_support) + +create_single_source_cgal_program( "mesh_implicit_domains.cpp" "implicit_functions.cpp" ) +target_link_libraries(mesh_implicit_domains PUBLIC CGAL::Eigen_support) + +create_single_source_cgal_program( "mesh_polyhedral_domain.cpp" ) +target_link_libraries(mesh_polyhedral_domain PUBLIC CGAL::Eigen_support) + +create_single_source_cgal_program( "mesh_polyhedral_domain_sm.cpp" ) +target_link_libraries(mesh_polyhedral_domain_sm PUBLIC CGAL::Eigen_support) + +create_single_source_cgal_program( "mesh_polyhedral_domain_with_surface_inside.cpp" ) +target_link_libraries(mesh_polyhedral_domain_with_surface_inside PUBLIC CGAL::Eigen_support) + +create_single_source_cgal_program( "remesh_polyhedral_surface.cpp" ) +target_link_libraries(remesh_polyhedral_surface PUBLIC CGAL::Eigen_support) + +create_single_source_cgal_program( "remesh_polyhedral_surface_sm.cpp" ) +target_link_libraries(remesh_polyhedral_surface_sm PUBLIC CGAL::Eigen_support) + +create_single_source_cgal_program( "mesh_polyhedral_domain_with_features.cpp" ) +target_link_libraries(mesh_polyhedral_domain_with_features PUBLIC CGAL::Eigen_support) + +create_single_source_cgal_program( "mesh_polyhedral_domain_with_features_sm.cpp" ) +target_link_libraries(mesh_polyhedral_domain_with_features_sm PUBLIC CGAL::Eigen_support) + +create_single_source_cgal_program( "mesh_polyhedral_domain_with_lipschitz_sizing.cpp" ) +target_link_libraries(mesh_polyhedral_domain_with_lipschitz_sizing PUBLIC CGAL::Eigen_support) + +create_single_source_cgal_program( "mesh_polyhedral_complex.cpp" ) +target_link_libraries(mesh_polyhedral_complex PUBLIC CGAL::Eigen_support) + +create_single_source_cgal_program( "mesh_polyhedral_complex_sm.cpp" ) +target_link_libraries(mesh_polyhedral_complex_sm PUBLIC CGAL::Eigen_support) + +if( TARGET CGAL::CGAL_ImageIO) + if( VTK_FOUND AND ("${VTK_VERSION_MAJOR}" GREATER "5" OR VTK_VERSION VERSION_GREATER 5) ) + add_executable ( mesh_3D_gray_vtk_image mesh_3D_gray_vtk_image.cpp ) + target_link_libraries( mesh_3D_gray_vtk_image PUBLIC CGAL::Eigen_support ${CGAL_LIBRARIES} ${CGAL_3RD_PARTY_LIBRARIES} ${VTK_LIBRARIES}) + cgal_add_test( mesh_3D_gray_vtk_image ) + add_to_cached_list( CGAL_EXECUTABLE_TARGETS mesh_3D_gray_vtk_image ) + endif() + + create_single_source_cgal_program( "mesh_3D_gray_image.cpp" ) + target_link_libraries(mesh_3D_gray_image PUBLIC CGAL::Eigen_support) + + create_single_source_cgal_program( "mesh_3D_gray_image_multiple_values.cpp" ) + target_link_libraries(mesh_3D_gray_image_multiple_values PUBLIC CGAL::Eigen_support) + + create_single_source_cgal_program( "mesh_3D_image_with_features.cpp" ) + target_link_libraries(mesh_3D_image_with_features PUBLIC CGAL::Eigen_support) + + if( CGAL_ImageIO_USE_ZLIB ) + create_single_source_cgal_program( "mesh_optimization_example.cpp" ) + target_link_libraries(mesh_optimization_example PUBLIC CGAL::Eigen_support) + + create_single_source_cgal_program( "mesh_optimization_lloyd_example.cpp" ) + target_link_libraries(mesh_optimization_lloyd_example PUBLIC CGAL::Eigen_support) + + create_single_source_cgal_program( "mesh_3D_image.cpp" ) + target_link_libraries(mesh_3D_image PUBLIC CGAL::Eigen_support) + + create_single_source_cgal_program( "mesh_3D_image_with_custom_initialization.cpp" ) + target_link_libraries(mesh_3D_image_with_custom_initialization PUBLIC CGAL::Eigen_support) + + create_single_source_cgal_program( "mesh_3D_image_variable_size.cpp" ) + target_link_libraries(mesh_3D_image_variable_size PUBLIC CGAL::Eigen_support) + else() + message( STATUS "NOTICE: The examples mesh_3D_image.cpp, mesh_3D_image_variable_size.cpp, mesh_optimization_example.cpp and mesh_optimization_lloyd_example.cpp need CGAL_ImageIO to be configured with ZLIB support, and will not be compiled." ) + endif() +else() + message( STATUS "NOTICE: Some examples need the CGAL_ImageIO library, and will not be compiled." ) +endif() + +if(CGAL_ACTIVATE_CONCURRENT_MESH_3 AND TARGET CGAL::TBB_support AND TARGET ${target}) + foreach(target + mesh_3D_image_with_features + mesh_3D_image + mesh_polyhedral_domain + mesh_3D_image_with_custom_initialization + mesh_two_implicit_spheres_with_balls + mesh_optimization_lloyd_example + mesh_optimization_example + mesh_implicit_sphere + mesh_polyhedral_complex_sm + mesh_implicit_sphere_variable_size + mesh_polyhedral_domain_sm + mesh_polyhedral_domain_with_lipschitz_sizing + mesh_polyhedral_complex + mesh_polyhedral_domain_with_features + mesh_3D_image_variable_size) + target_link_libraries(${target} PUBLIC CGAL::TBB_support) + endforeach() endif() From 04305dc82c28601ed92c4c786b54530d7de2ac7a Mon Sep 17 00:00:00 2001 From: Abhay Raj Singh Date: Sat, 13 Jun 2020 23:39:35 +0530 Subject: [PATCH 524/568] Removed unecessary Destructor --- STL_Extension/include/CGAL/exceptions.h | 2 -- 1 file changed, 2 deletions(-) diff --git a/STL_Extension/include/CGAL/exceptions.h b/STL_Extension/include/CGAL/exceptions.h index 92567623563..9c03348f122 100644 --- a/STL_Extension/include/CGAL/exceptions.h +++ b/STL_Extension/include/CGAL/exceptions.h @@ -97,8 +97,6 @@ public: m_msg( msg) {} - ~Failure_exception() noexcept {} - //! the name of the library that issues this message. std::string library() const { return m_lib; } From 33020868129e7942dce82e80dc2845a84009273f Mon Sep 17 00:00:00 2001 From: Abhay Raj Singh Date: Sat, 13 Jun 2020 23:41:39 +0530 Subject: [PATCH 525/568] Removed Unnecessary Destructor --- STL_Extension/include/CGAL/Uncertain.h | 2 -- 1 file changed, 2 deletions(-) diff --git a/STL_Extension/include/CGAL/Uncertain.h b/STL_Extension/include/CGAL/Uncertain.h index 01a27cc696c..947e3dfcef7 100644 --- a/STL_Extension/include/CGAL/Uncertain.h +++ b/STL_Extension/include/CGAL/Uncertain.h @@ -66,8 +66,6 @@ class Uncertain_conversion_exception public: Uncertain_conversion_exception(const std::string &s) : std::range_error(s) {} - - ~Uncertain_conversion_exception() noexcept {} }; From b4bba7f034c6dffb2d5336550de051d22cc883f0 Mon Sep 17 00:00:00 2001 From: Maxime Gimeno Date: Mon, 15 Jun 2020 08:58:13 +0200 Subject: [PATCH 526/568] rename maccro --- Polyhedron/demo/Polyhedron/MainWindow.cpp | 2 +- .../Plugins/PCA/Basic_generator_plugin.cpp | 18 +++++++++--------- Polyhedron/demo/Polyhedron/Viewer.cpp | 4 ++-- Three/include/CGAL/Three/Three.h | 4 ++-- 4 files changed, 14 insertions(+), 14 deletions(-) diff --git a/Polyhedron/demo/Polyhedron/MainWindow.cpp b/Polyhedron/demo/Polyhedron/MainWindow.cpp index 5a5ed733a40..ea61d6dc810 100644 --- a/Polyhedron/demo/Polyhedron/MainWindow.cpp +++ b/Polyhedron/demo/Polyhedron/MainWindow.cpp @@ -771,7 +771,7 @@ void MainWindow::loadPlugins() qputenv("PATH", new_path); #endif Q_FOREACH (QString pluginsDir, - env_path.split(separator, SkipEmptyParts)) { + env_path.split(separator, CGAL_QT_SKIP_EMPTY_PARTS)) { QDir dir(pluginsDir); if(dir.isReadable()) plugins_directories << dir; diff --git a/Polyhedron/demo/Polyhedron/Plugins/PCA/Basic_generator_plugin.cpp b/Polyhedron/demo/Polyhedron/Plugins/PCA/Basic_generator_plugin.cpp index 02648fed359..672e4fb0f7a 100644 --- a/Polyhedron/demo/Polyhedron/Plugins/PCA/Basic_generator_plugin.cpp +++ b/Polyhedron/demo/Polyhedron/Plugins/PCA/Basic_generator_plugin.cpp @@ -351,7 +351,7 @@ void Basic_generator_plugin::generateCube() for(int i=0; i<8; ++i) { - QStringList list = point_texts[i].split(QRegExp("\\s+"), SkipEmptyParts); + QStringList list = point_texts[i].split(QRegExp("\\s+"), CGAL_QT_SKIP_EMPTY_PARTS); if (list.isEmpty()) return; if (list.size()!=3){ QMessageBox *msgBox = new QMessageBox; @@ -392,7 +392,7 @@ void Basic_generator_plugin::generateCube() else { QString text = dock_widget->extremaEdit->text(); - QStringList list = text.split(QRegExp("\\s+"), SkipEmptyParts); + QStringList list = text.split(QRegExp("\\s+"), CGAL_QT_SKIP_EMPTY_PARTS); if (list.isEmpty()) return; if (list.size()!=6){ QMessageBox *msgBox = new QMessageBox; @@ -443,7 +443,7 @@ void Basic_generator_plugin::generatePrism() bool is_closed = dock_widget->prismCheckBox->isChecked(); QString text = dock_widget->prism_lineEdit->text(); - QStringList list = text.split(QRegExp("\\s+"), SkipEmptyParts); + QStringList list = text.split(QRegExp("\\s+"), CGAL_QT_SKIP_EMPTY_PARTS); if (list.isEmpty()) return; if (list.size()!=3){ QMessageBox *msgBox = new QMessageBox; @@ -490,7 +490,7 @@ void Basic_generator_plugin::generatePyramid() bool is_closed = dock_widget->pyramidCheckBox->isChecked(); QString text = dock_widget->pyramid_lineEdit->text(); - QStringList list = text.split(QRegExp("\\s+"), SkipEmptyParts); + QStringList list = text.split(QRegExp("\\s+"), CGAL_QT_SKIP_EMPTY_PARTS); if (list.isEmpty()) return; if (list.size()!=3){ QMessageBox *msgBox = new QMessageBox; @@ -533,7 +533,7 @@ void Basic_generator_plugin::generateSphere() { int precision = dock_widget->SphereSpinBox->value(); QString text = dock_widget->center_radius_lineEdit->text(); - QStringList list = text.split(QRegExp("\\s+"), SkipEmptyParts); + QStringList list = text.split(QRegExp("\\s+"), CGAL_QT_SKIP_EMPTY_PARTS); if (list.isEmpty()) return; if (list.size()!=4){ QMessageBox *msgBox = new QMessageBox; @@ -582,7 +582,7 @@ void Basic_generator_plugin::generateTetrahedron() for(int i=0; i<4; ++i) { - QStringList list = point_texts[i].split(QRegExp("\\s+"), SkipEmptyParts); + QStringList list = point_texts[i].split(QRegExp("\\s+"), CGAL_QT_SKIP_EMPTY_PARTS); if (list.isEmpty()) return; if (list.size()!=3){ QMessageBox *msgBox = new QMessageBox; @@ -623,7 +623,7 @@ void Basic_generator_plugin::generatePoints() { QString text = dock_widget->point_textEdit->toPlainText(); Scene_points_with_normal_item* item = new Scene_points_with_normal_item(); - QStringList list = text.split(QRegExp("\\s+"), SkipEmptyParts); + QStringList list = text.split(QRegExp("\\s+"), CGAL_QT_SKIP_EMPTY_PARTS); int counter = 0; double coord[3]; bool ok = true; @@ -682,7 +682,7 @@ void Basic_generator_plugin::generateLines() std::vector& polyline = *(polylines.rbegin()); QStringList polylines_metadata; - QStringList list = text.split(QRegExp("\\s+"), SkipEmptyParts); + QStringList list = text.split(QRegExp("\\s+"), CGAL_QT_SKIP_EMPTY_PARTS); int counter = 0; double coord[3]; bool ok = true; @@ -782,7 +782,7 @@ void Basic_generator_plugin::generateGrid() bool triangulated = dock_widget->grid_checkBox->isChecked(); points_text= dock_widget->grid_lineEdit->text(); - QStringList list = points_text.split(QRegExp("\\s+"), SkipEmptyParts); + QStringList list = points_text.split(QRegExp("\\s+"), CGAL_QT_SKIP_EMPTY_PARTS); if (list.isEmpty()) return; if (list.size()!=6){ QMessageBox *msgBox = new QMessageBox; diff --git a/Polyhedron/demo/Polyhedron/Viewer.cpp b/Polyhedron/demo/Polyhedron/Viewer.cpp index 3b483fb9723..8c53251c18c 100644 --- a/Polyhedron/demo/Polyhedron/Viewer.cpp +++ b/Polyhedron/demo/Polyhedron/Viewer.cpp @@ -852,7 +852,7 @@ void Viewer::postSelection(const QPoint& pixel) } bool CGAL::Three::Viewer_interface::readFrame(QString s, CGAL::qglviewer::Frame& frame) { - QStringList list = s.split(" ", SkipEmptyParts); + QStringList list = s.split(" ", CGAL_QT_SKIP_EMPTY_PARTS); if(list.size() != 7) return false; float vec[3]; @@ -1781,7 +1781,7 @@ void Viewer::setLighting() connect(dialog->position_lineEdit, &QLineEdit::editingFinished, [this, dialog]() { - QStringList list = dialog->position_lineEdit->text().split(QRegExp(","), SkipEmptyParts); + QStringList list = dialog->position_lineEdit->text().split(QRegExp(","), CGAL_QT_SKIP_EMPTY_PARTS); if (list.isEmpty()) return; if (list.size()!=3){ QMessageBox *msgBox = new QMessageBox; diff --git a/Three/include/CGAL/Three/Three.h b/Three/include/CGAL/Three/Three.h index 70c040edffd..c62b32e13ca 100644 --- a/Three/include/CGAL/Three/Three.h +++ b/Three/include/CGAL/Three/Three.h @@ -30,9 +30,9 @@ #endif #if QT_VERSION < QT_VERSION_CHECK(5, 15, 0) -#define SkipEmptyParts QString::SkipEmptyParts +#define CGAL_QT_SKIP_EMPTY_PARTS QString::SkipEmptyParts #else -#define SkipEmptyParts ::Qt::SkipEmptyParts +#define CGAL_QT_SKIP_EMPTY_PARTS ::Qt::SkipEmptyParts #endif namespace CGAL{ From 08ce5f17a8823ff4c2d8710094d1e917fb6c036a Mon Sep 17 00:00:00 2001 From: Maxime Gimeno Date: Mon, 15 Jun 2020 10:37:58 +0200 Subject: [PATCH 527/568] Fix more warnings --- .../Optimal_transportation_reconstruction_2/glviewer.cpp | 2 +- .../demo/Polyhedron/Plugins/PMP/Engrave_text_plugin.cpp | 9 +++++++-- .../Plugins/Surface_mesh/Parameterization_plugin.cpp | 9 +++++++-- Surface_mesher/demo/Surface_mesher/values_list.cpp | 8 ++++++++ Triangulation_3/demo/Triangulation_3/Viewer.cpp | 6 +++--- 5 files changed, 26 insertions(+), 8 deletions(-) diff --git a/Optimal_transportation_reconstruction_2/demo/Optimal_transportation_reconstruction_2/glviewer.cpp b/Optimal_transportation_reconstruction_2/demo/Optimal_transportation_reconstruction_2/glviewer.cpp index 64834832676..b459255eb2c 100644 --- a/Optimal_transportation_reconstruction_2/demo/Optimal_transportation_reconstruction_2/glviewer.cpp +++ b/Optimal_transportation_reconstruction_2/demo/Optimal_transportation_reconstruction_2/glviewer.cpp @@ -87,7 +87,7 @@ void GlViewer::paintGL() void GlViewer::wheelEvent(QWheelEvent *event) { if (!m_scene) return; - m_scale += 0.05 * (event->delta() / 120); + m_scale += 0.05 * (event->angleDelta().y() / 120); if (m_scale <= 0.0) m_scale = 0.0; update(); } diff --git a/Polyhedron/demo/Polyhedron/Plugins/PMP/Engrave_text_plugin.cpp b/Polyhedron/demo/Polyhedron/Plugins/PMP/Engrave_text_plugin.cpp index bfb6d3c4311..757c72b6cc1 100644 --- a/Polyhedron/demo/Polyhedron/Plugins/PMP/Engrave_text_plugin.cpp +++ b/Polyhedron/demo/Polyhedron/Plugins/PMP/Engrave_text_plugin.cpp @@ -249,12 +249,17 @@ protected: } case QEvent::Wheel: { QWheelEvent* event = static_cast(ev); - QPointF old_pos = v->mapToScene(event->pos()); +#if QT_VERSION < QT_VERSION_CHECK(5, 14, 0) + QPoint pos = event->pos(); +#else + QPointF pos = event->position(); +#endif + QPointF old_pos = v->mapToScene(pos.x(), pos.y()); if(event->angleDelta().y() <0) v->scale(1.2, 1.2); else v->scale(0.8, 0.8); - QPointF new_pos = v->mapToScene(event->pos()); + QPointF new_pos = v->mapToScene(pos.x(), pos.y()); QPointF delta = new_pos - old_pos; v->translate(delta.x(), delta.y()); v->update(); diff --git a/Polyhedron/demo/Polyhedron/Plugins/Surface_mesh/Parameterization_plugin.cpp b/Polyhedron/demo/Polyhedron/Plugins/Surface_mesh/Parameterization_plugin.cpp index 9883c1d376a..eab69bce277 100644 --- a/Polyhedron/demo/Polyhedron/Plugins/Surface_mesh/Parameterization_plugin.cpp +++ b/Polyhedron/demo/Polyhedron/Plugins/Surface_mesh/Parameterization_plugin.cpp @@ -143,12 +143,17 @@ protected: } case QEvent::Wheel: { QWheelEvent* event = static_cast(ev); - QPointF old_pos = v->mapToScene(event->pos()); +#if QT_VERSION < QT_VERSION_CHECK(5, 14, 0) + QPoint pos = event->pos(); +#else + QPointF pos = event->position(); +#endif + QPointF old_pos = v->mapToScene(pos.x(), pos.y()); if(event->angleDelta().y() <0) v->scale(1.2, 1.2); else v->scale(0.8, 0.8); - QPointF new_pos = v->mapToScene(event->pos()); + QPointF new_pos = v->mapToScene(pos.x(), pos.y()); QPointF delta = new_pos - old_pos; v->translate(delta.x(), delta.y()); v->update(); diff --git a/Surface_mesher/demo/Surface_mesher/values_list.cpp b/Surface_mesher/demo/Surface_mesher/values_list.cpp index f7b1805f18d..b2e8a41e86f 100644 --- a/Surface_mesher/demo/Surface_mesher/values_list.cpp +++ b/Surface_mesher/demo/Surface_mesher/values_list.cpp @@ -20,6 +20,9 @@ #include #include #include +#if QT_VERSION >= QT_VERSION_CHECK(5, 10, 0) +#include +#endif Values_delegate::Values_delegate(QWidget* parent) : QItemDelegate(parent) {} void Values_delegate::paint(QPainter * painter, const QStyleOptionViewItem & option, const QModelIndex & index) const @@ -240,7 +243,12 @@ void Values_list::addValue(const double i) newItem->setData(Value, Qt::CheckStateRole, Qt::Checked); newItem->setData(Value, Qt::DisplayRole, i); QStringList colors = QColor::colorNames(); +#if QT_VERSION < QT_VERSION_CHECK(5, 10, 0) const int color_index = qrand() % colors.size(); +#else +const int color_index = QRandomGenerator::global()->generate() % colors.size(); +#endif + QColor color = QColor(colors[color_index]); newItem->setData(Color, Qt::DisplayRole, color); newItem->setData(Name, Qt::DisplayRole, ""); diff --git a/Triangulation_3/demo/Triangulation_3/Viewer.cpp b/Triangulation_3/demo/Triangulation_3/Viewer.cpp index b12a9304031..097aa3c2546 100644 --- a/Triangulation_3/demo/Triangulation_3/Viewer.cpp +++ b/Triangulation_3/demo/Triangulation_3/Viewer.cpp @@ -2151,7 +2151,7 @@ void Viewer::wheelEvent(QWheelEvent *event) // note: most mouse types work in steps of 15 degrees // positive value: rotate forwards away from the user; // negative value: rotate backwards toward the user. - m_fRadius += (event->delta()*1.f / m_iStep ); // inc-/decrease by 0.1 per step + m_fRadius += (event->angleDelta().y()*1.f / m_iStep ); // inc-/decrease by 0.1 per step if( m_fRadius < 0.1f ) m_fRadius = 0.1f; @@ -2166,7 +2166,7 @@ void Viewer::wheelEvent(QWheelEvent *event) // positive value: rotate forwards away from the user; // negative value: rotate backwards toward the user. float origR = m_fRadius; - m_fRadius += (event->delta()*1.f / m_iStep ); // inc-/decrease by 0.1 per step + m_fRadius += (event->angleDelta().y()*1.f / m_iStep ); // inc-/decrease by 0.1 per step if( m_fRadius < 0.1f ) m_fRadius = 0.1f; // update the new point and its conflict region @@ -2185,7 +2185,7 @@ void Viewer::wheelEvent(QWheelEvent *event) // resize the trackball when moving a point else if( m_curMode == MOVE && modifiers == Qt::SHIFT && m_isMoving ) { float origR = m_fRadius; - m_fRadius += (event->delta()*1.f / m_iStep ); // inc-/decrease by 0.1 per step + m_fRadius += (event->angleDelta().y()*1.f / m_iStep ); // inc-/decrease by 0.1 per step if( m_fRadius < 0.1f ) m_fRadius = 0.1f; origR = m_fRadius / origR; From 39d41664e6a188b4dcf4bace0bfd344924cec92d Mon Sep 17 00:00:00 2001 From: Maxime Gimeno Date: Mon, 15 Jun 2020 11:56:00 +0200 Subject: [PATCH 528/568] Fix addActionToMenu --- Polyhedron/demo/Polyhedron/MainWindow.cpp | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/Polyhedron/demo/Polyhedron/MainWindow.cpp b/Polyhedron/demo/Polyhedron/MainWindow.cpp index ea61d6dc810..27d4717f955 100644 --- a/Polyhedron/demo/Polyhedron/MainWindow.cpp +++ b/Polyhedron/demo/Polyhedron/MainWindow.cpp @@ -410,20 +410,22 @@ MainWindow::MainWindow(const QStringList &keywords, bool verbose, QWidget* paren void addActionToMenu(QAction* action, QMenu* menu) { bool added = false; + QString atxt = action->text().remove("&"); + if(atxt.isEmpty()) + return; for(QAction* it : menu->actions()) { - QString atxt = action->text().remove("&"), - btxt = it->text().remove("&"); + QString btxt = it->text().remove("&"); int i = 0; - if(atxt.isEmpty() || btxt.isEmpty()) + if(btxt.isEmpty()) + { continue; + } while(i < atxt.size() && i < btxt.size() && atxt[i] == btxt[i]) ++i; - if(i == atxt.size() || i == btxt.size()) - continue; - bool res = (atxt[i] < btxt[i]); + bool res = (i == atxt.size() || i == btxt.size() || atxt[i] < btxt[i]); if (res) { menu->insertAction(it, action); From 49e66c4ddfbf0214b7527979ff9e893bd77bd942 Mon Sep 17 00:00:00 2001 From: Maxime Gimeno Date: Mon, 15 Jun 2020 13:08:17 +0200 Subject: [PATCH 529/568] Add missing target --- Mesh_3/examples/Mesh_3/CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Mesh_3/examples/Mesh_3/CMakeLists.txt b/Mesh_3/examples/Mesh_3/CMakeLists.txt index cd46b2a100e..88f738de714 100644 --- a/Mesh_3/examples/Mesh_3/CMakeLists.txt +++ b/Mesh_3/examples/Mesh_3/CMakeLists.txt @@ -97,7 +97,7 @@ target_link_libraries(mesh_polyhedral_complex_sm PUBLIC CGAL::Eigen_support) if( TARGET CGAL::CGAL_ImageIO) if( VTK_FOUND AND ("${VTK_VERSION_MAJOR}" GREATER "5" OR VTK_VERSION VERSION_GREATER 5) ) add_executable ( mesh_3D_gray_vtk_image mesh_3D_gray_vtk_image.cpp ) - target_link_libraries( mesh_3D_gray_vtk_image PUBLIC CGAL::Eigen_support ${CGAL_LIBRARIES} ${CGAL_3RD_PARTY_LIBRARIES} ${VTK_LIBRARIES}) + target_link_libraries( mesh_3D_gray_vtk_image PUBLIC CGAL::Eigen_support CGAL::CGAL ${CGAL_LIBRARIES} ${CGAL_3RD_PARTY_LIBRARIES} ${VTK_LIBRARIES}) cgal_add_test( mesh_3D_gray_vtk_image ) add_to_cached_list( CGAL_EXECUTABLE_TARGETS mesh_3D_gray_vtk_image ) endif() From 113c3d1d6f3b353f1837d2c092f0e1fbfd856862 Mon Sep 17 00:00:00 2001 From: Laurent Rineau Date: Mon, 15 Jun 2020 15:56:28 +0200 Subject: [PATCH 530/568] Continue woraround for MSVC2015 That is a followup to commit 5fbaaa9e4282b3f81551c4fa89e126f5c281055c from PR #4468. I also chose a better name `is_null` instead of `compare_weighted_circumcenter`. --- Mesh_3/include/CGAL/Compact_mesh_cell_base_3.h | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/Mesh_3/include/CGAL/Compact_mesh_cell_base_3.h b/Mesh_3/include/CGAL/Compact_mesh_cell_base_3.h index 9fe85b6765e..dfd0f679537 100644 --- a/Mesh_3/include/CGAL/Compact_mesh_cell_base_3.h +++ b/Mesh_3/include/CGAL/Compact_mesh_cell_base_3.h @@ -54,7 +54,7 @@ void set_weighted_circumcenter(T* &t, std::nullptr_t) t = nullptr; } template -bool compare_weighted_circumcenter(T* t) +bool is_null(T* t) { return t == nullptr; } @@ -80,7 +80,7 @@ void set_weighted_circumcenter(std::atomic& t, std::nullptr_t) } template -bool compare_weighted_circumcenter(std::atomic& t) +bool is_null(std::atomic& t) { return t.load() == nullptr; } @@ -302,7 +302,7 @@ public: public: void invalidate_weighted_circumcenter_cache() const { - if (!internal_tbb::compare_weighted_circumcenter(weighted_circumcenter_)) { + if (!internal_tbb::is_null(weighted_circumcenter_)) { internal_tbb::delete_circumcenter(weighted_circumcenter_); internal_tbb::set_weighted_circumcenter(weighted_circumcenter_, nullptr); } @@ -386,7 +386,7 @@ public: ~Compact_mesh_cell_base_3() { - if(!internal_tbb::compare_weighted_circumcenter(weighted_circumcenter_)){ + if(!internal_tbb::is_null(weighted_circumcenter_)){ internal_tbb::delete_circumcenter(weighted_circumcenter_); internal_tbb::set_weighted_circumcenter(weighted_circumcenter_, nullptr); } @@ -533,7 +533,7 @@ public: { CGAL_static_assertion((boost::is_same::value)); - if (weighted_circumcenter_ == nullptr) { + if (internal_tbb::is_null(weighted_circumcenter_)) { this->try_to_set_circumcenter( new Point_3(gt.construct_weighted_circumcenter_3_object() (this->vertex(0)->point(), From 722fa939274568e93f96cf0530fec42fd54efdf9 Mon Sep 17 00:00:00 2001 From: Maxime Gimeno Date: Mon, 15 Jun 2020 16:05:49 +0200 Subject: [PATCH 531/568] More fixes --- .../demo/Arrangement_on_surface_2/NewTabDialog.cpp | 2 +- .../demo/Hyperbolic_triangulation_2/HDT2.cpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Arrangement_on_surface_2/demo/Arrangement_on_surface_2/NewTabDialog.cpp b/Arrangement_on_surface_2/demo/Arrangement_on_surface_2/NewTabDialog.cpp index cf40a748f04..189db51f5d5 100644 --- a/Arrangement_on_surface_2/demo/Arrangement_on_surface_2/NewTabDialog.cpp +++ b/Arrangement_on_surface_2/demo/Arrangement_on_surface_2/NewTabDialog.cpp @@ -14,7 +14,7 @@ #include "ui_NewTabDialog.h" #include -NewTabDialog::NewTabDialog( QWidget* parent, Qt::WindowFlags f ) : +NewTabDialog::NewTabDialog( QWidget* parent, Qt::WindowFlags f = Qt::WindowType(0) ) : QDialog( parent, f ), ui( new Ui::NewTabDialog ), buttonGroup( new QButtonGroup ) diff --git a/Hyperbolic_triangulation_2/demo/Hyperbolic_triangulation_2/HDT2.cpp b/Hyperbolic_triangulation_2/demo/Hyperbolic_triangulation_2/HDT2.cpp index ccfb1d72a8e..9fbb9e6d730 100644 --- a/Hyperbolic_triangulation_2/demo/Hyperbolic_triangulation_2/HDT2.cpp +++ b/Hyperbolic_triangulation_2/demo/Hyperbolic_triangulation_2/HDT2.cpp @@ -207,7 +207,7 @@ MainWindow::MainWindow() this->graphicsView->shear(230, 230); // Turn the vertical axis upside down - this->graphicsView->matrix().scale(1, -1); + this->graphicsView->transform().scale(1, -1); // The navigation adds zooming and translation functionality to the // QGraphicsView From 9d16a422570b33fcd07ca8ae9ca91e9a7eaed328 Mon Sep 17 00:00:00 2001 From: Laurent Rineau Date: Mon, 15 Jun 2020 17:07:35 +0200 Subject: [PATCH 532/568] Fix ambiguous comparisons error with C++20 --- Nef_2/include/CGAL/Nef_2/iterator_tools.h | 6 ++ Nef_2/include/CGAL/Nef_polynomial.h | 71 +++++++++++------------ 2 files changed, 41 insertions(+), 36 deletions(-) diff --git a/Nef_2/include/CGAL/Nef_2/iterator_tools.h b/Nef_2/include/CGAL/Nef_2/iterator_tools.h index 00dd4c1658c..29175c90755 100644 --- a/Nef_2/include/CGAL/Nef_2/iterator_tools.h +++ b/Nef_2/include/CGAL/Nef_2/iterator_tools.h @@ -48,6 +48,12 @@ public: bool operator!=( const Self& i) const { return !(*this == i); } + bool operator==( const Iter& i ) const { + return Iter::operator==(i); + } + bool operator!=( const Iter& i) const { + return !(*this == i); + } Self& operator++() { Move move; diff --git a/Nef_2/include/CGAL/Nef_polynomial.h b/Nef_2/include/CGAL/Nef_polynomial.h index c03ab4ddd40..ccaedb333b1 100644 --- a/Nef_2/include/CGAL/Nef_polynomial.h +++ b/Nef_2/include/CGAL/Nef_polynomial.h @@ -69,6 +69,41 @@ class Nef_polynomial CGAL_STATIC_THREAD_LOCAL_VARIABLE(NT, R_, 1); return R_; } + + friend bool operator==(const Nef_polynomial &a, const Nef_polynomial &b) + { + return a.polynomial() == b.polynomial(); + } + + friend bool operator==(const Nef_polynomial &a, const NT& b) + { + return a.polynomial() == b; + } + + friend bool operator==(const Nef_polynomial &a, int b) + { + return a.polynomial() == b; + } + + friend bool operator<(const Nef_polynomial &a, const Nef_polynomial &b) + { + return a.polynomial() < b.polynomial(); + } + + friend bool operator<(const Nef_polynomial &a, const NT& b) + { + return a.polynomial() < b; + } + + friend bool operator<(const Nef_polynomial &a, int b) + { + return a.polynomial() < b; + } + + friend bool operator>(const Nef_polynomial &a, int b) + { + return a.polynomial() > b; + } }; template @@ -85,42 +120,6 @@ Nef_polynomial operator-(const Nef_polynomial &a) return - a.polynomial(); } -template -inline -bool operator<(const Nef_polynomial &a, const Nef_polynomial &b) -{ - return a.polynomial() < b.polynomial(); -} - -template -inline -bool operator==(const Nef_polynomial &a, const Nef_polynomial &b) -{ - return a.polynomial() == b.polynomial(); -} - -template -inline -bool operator==(const Nef_polynomial &a, int b) -{ - return a.polynomial() == b; -} - -template -inline -bool operator<(const Nef_polynomial &a, int b) -{ - return a.polynomial() < b; -} - -template -inline -bool operator>(const Nef_polynomial &a, int b) -{ - return a.polynomial() > b; -} - - #undef CGAL_double #undef CGAL_int From 7e12992ee07414b7b92ac11b1747f28bc5f59ece Mon Sep 17 00:00:00 2001 From: Laurent Rineau Date: Mon, 15 Jun 2020 17:12:04 +0200 Subject: [PATCH 533/568] Missing #include --- .../internal/Smoothing/curvature_flow_impl.h | 1 + 1 file changed, 1 insertion(+) diff --git a/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/internal/Smoothing/curvature_flow_impl.h b/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/internal/Smoothing/curvature_flow_impl.h index a201c6e8dde..0c9e2d9fa0e 100644 --- a/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/internal/Smoothing/curvature_flow_impl.h +++ b/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/internal/Smoothing/curvature_flow_impl.h @@ -35,6 +35,7 @@ #include #include #include +#include namespace CGAL { namespace Polygon_mesh_processing { From 5976ee98e9bbc99798478fc1e286388400524b4a Mon Sep 17 00:00:00 2001 From: Maxime Gimeno Date: Tue, 16 Jun 2020 09:06:34 +0200 Subject: [PATCH 534/568] Fix Arrangement_2_demo --- .../demo/Arrangement_on_surface_2/NewTabDialog.cpp | 2 +- .../demo/Arrangement_on_surface_2/NewTabDialog.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Arrangement_on_surface_2/demo/Arrangement_on_surface_2/NewTabDialog.cpp b/Arrangement_on_surface_2/demo/Arrangement_on_surface_2/NewTabDialog.cpp index 189db51f5d5..f0daef178fc 100644 --- a/Arrangement_on_surface_2/demo/Arrangement_on_surface_2/NewTabDialog.cpp +++ b/Arrangement_on_surface_2/demo/Arrangement_on_surface_2/NewTabDialog.cpp @@ -14,7 +14,7 @@ #include "ui_NewTabDialog.h" #include -NewTabDialog::NewTabDialog( QWidget* parent, Qt::WindowFlags f = Qt::WindowType(0) ) : +NewTabDialog::NewTabDialog( QWidget* parent, Qt::WindowFlags f) : QDialog( parent, f ), ui( new Ui::NewTabDialog ), buttonGroup( new QButtonGroup ) diff --git a/Arrangement_on_surface_2/demo/Arrangement_on_surface_2/NewTabDialog.h b/Arrangement_on_surface_2/demo/Arrangement_on_surface_2/NewTabDialog.h index 2121d5daac2..679f30a7887 100644 --- a/Arrangement_on_surface_2/demo/Arrangement_on_surface_2/NewTabDialog.h +++ b/Arrangement_on_surface_2/demo/Arrangement_on_surface_2/NewTabDialog.h @@ -23,7 +23,7 @@ namespace Ui class NewTabDialog : public QDialog { public: - NewTabDialog( QWidget* parent = 0, Qt::WindowFlags f = 0 ); + NewTabDialog( QWidget* parent = 0, Qt::WindowFlags f = Qt::WindowType(0) ); int checkedId( ) const; protected: From 2fe78166ead827a2fc18882e62a9a383c73204bd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9bastien=20Loriot?= Date: Tue, 16 Jun 2020 11:39:26 +0200 Subject: [PATCH 535/568] make Straight_skeleton class copy-constructible as documented --- .../CGAL/Straight_skeleton_halfedge_base_2.h | 2 - .../test_straight_skeleton_copy.cpp | 50 +++++++++++++++++++ 2 files changed, 50 insertions(+), 2 deletions(-) create mode 100644 Straight_skeleton_2/test/Straight_skeleton_2/test_straight_skeleton_copy.cpp diff --git a/Straight_skeleton_2/include/CGAL/Straight_skeleton_halfedge_base_2.h b/Straight_skeleton_2/include/CGAL/Straight_skeleton_halfedge_base_2.h index c6d79ebd4b7..89e941d95a8 100644 --- a/Straight_skeleton_2/include/CGAL/Straight_skeleton_halfedge_base_2.h +++ b/Straight_skeleton_2/include/CGAL/Straight_skeleton_halfedge_base_2.h @@ -134,8 +134,6 @@ public: Straight_skeleton_halfedge_base_2( int aID, Sign aSlope ) : Base_base(aID,aSlope) {} -private: - void set_opposite( Halfedge_handle h ) { Base_base::opposite(h) ; } void set_next ( Halfedge_handle h ) { Base_base::set_next(h) ; } void set_prev ( Halfedge_handle h ) { Base_base::set_prev(h) ; } diff --git a/Straight_skeleton_2/test/Straight_skeleton_2/test_straight_skeleton_copy.cpp b/Straight_skeleton_2/test/Straight_skeleton_2/test_straight_skeleton_copy.cpp new file mode 100644 index 00000000000..acbe7d848b2 --- /dev/null +++ b/Straight_skeleton_2/test/Straight_skeleton_2/test_straight_skeleton_copy.cpp @@ -0,0 +1,50 @@ +#include + +#include + +#include +#include +#include + +typedef CGAL::Exact_predicates_inexact_constructions_kernel K ; + +typedef K::Point_2 Point ; +typedef CGAL::Polygon_2 Polygon_2 ; +typedef CGAL::Straight_skeleton_2 Ss ; + +typedef boost::shared_ptr PolygonPtr ; +typedef boost::shared_ptr SsPtr ; + +typedef std::vector PolygonPtrVector ; + +int main() +{ + std::ifstream in("data/A.poly"); + if (!in) return 1; + int n; + double x,y; + Polygon_2 poly ; + + in >> n; // skip #polylines + in >> n; + for (int i=0; i> x >> y; + poly.push_back( Point(x,y) ) ; + } + // we are only taking the outer contour (sufficient for this test) + + std::cout << poly.size() << "\n"; + + SsPtr ss = CGAL::create_interior_straight_skeleton_2(poly); + Ss ss_copy(*ss); + + double lOffset = 5 ; + + PolygonPtrVector offset_polygons = CGAL::create_offset_polygons_2(lOffset,ss_copy); + + assert(offset_polygons.size()==1); + assert(offset_polygons.front()->size()>10); + + return 0; +} From f216f00ddab598a69f288bec313403023d22a067 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mael=20Rouxel-Labb=C3=A9?= Date: Tue, 16 Jun 2020 16:39:07 +0200 Subject: [PATCH 536/568] Add is_simple_3(HalfedgeRange) --- .../repair_self_intersections.h | 89 +++++++++++++++++++ 1 file changed, 89 insertions(+) diff --git a/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/repair_self_intersections.h b/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/repair_self_intersections.h index def4359d132..37b3516dbc5 100644 --- a/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/repair_self_intersections.h +++ b/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/repair_self_intersections.h @@ -30,6 +30,7 @@ #include #include #include +#include #include #include @@ -1227,6 +1228,94 @@ bool fill_hole_with_constraints(std::vector +struct Strict_intersect_edges // "strict" as in "not sharing a vertex" +{ + typedef typename boost::graph_traits::halfedge_descriptor halfedge_descriptor; + typedef typename GT::Segment_3 Segment; + + mutable OutputIterator m_iterator; + const TM& m_tmesh; + const VPM m_vpmap; + + typename GT::Construct_segment_3 m_construct_segment; + typename GT::Do_intersect_3 m_do_intersect; + + Strict_intersect_edges(const TM& tmesh, VPM vpmap, const GT& gt, OutputIterator it) + : + m_iterator(it), + m_tmesh(tmesh), + m_vpmap(vpmap), + m_construct_segment(gt.construct_segment_3_object()), + m_do_intersect(gt.do_intersect_3_object()) + {} + + void operator()(const Box* b, const Box* c) const + { + const halfedge_descriptor h = b->info(); + const halfedge_descriptor g = c->info(); + + if(source(h, m_tmesh) == target(g, m_tmesh) || target(h, m_tmesh) == source(g, m_tmesh)) + return; + + const Segment s1 = m_construct_segment(get(m_vpmap, source(h, m_tmesh)), get(m_vpmap, target(h, m_tmesh))); + const Segment s2 = m_construct_segment(get(m_vpmap, source(g, m_tmesh)), get(m_vpmap, target(g, m_tmesh))); + + if(m_do_intersect(s1, s2)) + *m_iterator++ = std::make_pair(b->info(), c->info()); + } +}; + +template +bool is_simple_3(const std::vector::halfedge_descriptor>& cc_border_hedges, + const TriangleMesh& tmesh, + VertexPointMap vpm, + const GeomTraits& gt) +{ + typedef typename boost::graph_traits::halfedge_descriptor halfedge_descriptor; + + typedef typename boost::property_traits::reference Point_ref; + + typedef CGAL::Box_intersection_d::ID_FROM_BOX_ADDRESS Box_policy; + typedef CGAL::Box_intersection_d::Box_with_info_d Box; + + std::vector boxes; + boxes.reserve(cc_border_hedges.size()); + + for(halfedge_descriptor h : cc_border_hedges) + { + const Point_ref p = get(vpm, source(h, tmesh)); + const Point_ref q = get(vpm, target(h, tmesh)); + CGAL_assertion(!gt.equal_3_object()(p, q)); + + boxes.emplace_back(p.bbox() + q.bbox(), h); + } + + // generate box pointers + std::vector box_ptr; + box_ptr.reserve(boxes.size()); + + for(Box& b : boxes) + box_ptr.push_back(&b); + + typedef boost::function_output_iterator Throwing_output_iterator; + typedef internal::Strict_intersect_edges Throwing_filter; + Throwing_filter throwing_filter(tmesh, vpm, gt, Throwing_output_iterator()); + + try + { + const std::ptrdiff_t cutoff = 2000; + CGAL::box_self_intersection_d(box_ptr.begin(), box_ptr.end(), throwing_filter, cutoff); + } + catch(CGAL::internal::Throw_at_output_exception&) + { + return false; + } + + return true; +} + template bool remove_self_intersections_with_hole_filling(std::vector::halfedge_descriptor>& cc_border_hedges, std::set::face_descriptor>& cc_faces, From e66bdf00291308490681bac9a80af77db7b12156 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mael=20Rouxel-Labb=C3=A9?= Date: Tue, 16 Jun 2020 16:40:14 +0200 Subject: [PATCH 537/568] Don't attempt to hole fill if the border is not simple --- .../Polygon_mesh_processing/repair_self_intersections.h | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/repair_self_intersections.h b/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/repair_self_intersections.h index 37b3516dbc5..520ea946fe4 100644 --- a/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/repair_self_intersections.h +++ b/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/repair_self_intersections.h @@ -1335,6 +1335,14 @@ bool remove_self_intersections_with_hole_filling(std::vector Date: Tue, 16 Jun 2020 16:40:46 +0200 Subject: [PATCH 538/568] Also count unsolved cases --- .../repair_self_intersections.h | 22 ++++++++++++++++--- 1 file changed, 19 insertions(+), 3 deletions(-) diff --git a/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/repair_self_intersections.h b/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/repair_self_intersections.h index 520ea946fe4..a2d8580620d 100644 --- a/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/repair_self_intersections.h +++ b/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/repair_self_intersections.h @@ -63,6 +63,7 @@ namespace Polygon_mesh_processing { namespace internal { #ifdef CGAL_PMP_REMOVE_SELF_INTERSECTION_DEBUG +static int unsolved_self_intersections = 0; static int self_intersections_solved_by_constrained_smoothing = 0; static int self_intersections_solved_by_unconstrained_smoothing = 0; static int self_intersections_solved_by_constrained_hole_filling = 0; @@ -1394,7 +1395,7 @@ remove_self_intersections_one_step(std::set faces_to_remove_copy = faces_to_remove; #ifdef CGAL_PMP_REMOVE_SELF_INTERSECTION_DEBUG - std::cout << "DEBUG: running remove_self_intersections_one_step, step " << step + std::cout << "##### running remove_self_intersections_one_step, step " << step << " with " << faces_to_remove.size() << " intersecting faces\n"; #endif @@ -1407,9 +1408,12 @@ remove_self_intersections_one_step(std::set (only_border_edges ? 1 : 0)) { #ifdef CGAL_PMP_REMOVE_SELF_INTERSECTION_DEBUG - std::cout << " DEBUG: CC not handled due to the presence of " + std::cout << " DEBUG: CC not handled due to the presence of " << nb_cycles << " of boundary edges\n"; + ++unsolved_self_intersections; #endif topology_issue = true; @@ -1746,6 +1758,7 @@ remove_self_intersections_one_step(std::set Date: Tue, 16 Jun 2020 16:41:04 +0200 Subject: [PATCH 539/568] Avoid bad (self-intersecting) patches even in the last case Usually worsens the result without any benefit --- .../repair_self_intersections.h | 194 +++++++++--------- 1 file changed, 97 insertions(+), 97 deletions(-) diff --git a/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/repair_self_intersections.h b/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/repair_self_intersections.h index a2d8580620d..748b4d6952c 100644 --- a/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/repair_self_intersections.h +++ b/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/repair_self_intersections.h @@ -254,8 +254,7 @@ FaceOutputIterator replace_faces_with_patch(const std::vector -bool fill_hole(std::vector::halfedge_descriptor>& cc_border_hedges, - std::set::face_descriptor>& cc_faces, - std::set::face_descriptor>& working_face_range, - TriangleMesh& tmesh, - VertexPointMap vpm, - const GeomTraits& gt) -{ - typedef typename boost::graph_traits::vertex_descriptor vertex_descriptor; - typedef typename boost::graph_traits::edge_descriptor edge_descriptor; - typedef typename boost::graph_traits::face_descriptor face_descriptor; - - typedef typename boost::property_traits::value_type Point; - -#ifdef CGAL_PMP_REMOVE_SELF_INTERSECTION_DEBUG - std::cout << " DEBUG: Attempting hole-filling (no constraints), " << cc_faces.size() << " faces\n"; -#endif - - if(!order_border_halfedge_range(cc_border_hedges, tmesh)) - { - CGAL_assertion(false); // we shouldn't fail to orient the boundary cycle of the complete hole - return false; - } - - std::set cc_interior_vertices; - std::set cc_interior_edges; - - std::vector cc_border_vertices; - cc_border_vertices.reserve(cc_border_hedges.size()); - - std::vector > patch; - if(!construct_tentative_hole_patch(cc_border_vertices, cc_interior_vertices, cc_interior_edges, - cc_border_hedges, cc_faces, patch, tmesh, vpm, gt)) - { -#ifdef CGAL_PMP_REMOVE_SELF_INTERSECTION_DEBUG - std::cout << " DEBUG: Failed to find acceptable hole patch\n"; -#endif - - return false; - } - - // Could renew the range directly within the patch replacement function - // to avoid erasing and re-adding the same face - for(const face_descriptor f : cc_faces) - working_face_range.erase(f); - - // Plug the new triangles in the mesh, reusing previous edges and faces - replace_faces_with_patch(cc_border_vertices, cc_interior_vertices, - cc_border_hedges, cc_interior_edges, - cc_faces, patch, tmesh, vpm, - std::inserter(working_face_range, working_face_range.end())); - -#ifdef CGAL_PMP_REMOVE_SELF_INTERSECTION_OUTPUT - static int filed_hole_id = 0; - std::stringstream oss; - oss << "results/filled_basic_" << filed_hole_id++ << ".off" << std::ends; - std::ofstream(oss.str().c_str()) << std::setprecision(17) << tmesh; -#endif - - CGAL_postcondition(is_valid_polygon_mesh(tmesh)); - - return true; -} - -// Same function as above but border of the hole is not known -template -bool fill_hole(std::set::face_descriptor>& cc_faces, - std::set::face_descriptor>& working_face_range, - TriangleMesh& tmesh, - VertexPointMap vpm, - const GeomTraits& gt) -{ - typedef typename boost::graph_traits::halfedge_descriptor halfedge_descriptor; - typedef typename boost::graph_traits::face_descriptor face_descriptor; - - std::vector cc_border_hedges; - for(face_descriptor fd : cc_faces) - { - halfedge_descriptor h = halfedge(fd, tmesh); - for(int i=0; i<3; ++i) - { - if(is_border(opposite(h, tmesh), tmesh) || cc_faces.count(face(opposite(h, tmesh), tmesh)) == 0) - cc_border_hedges.push_back(h); - - h = next(h, tmesh); - } - } - - if(order_border_halfedge_range(cc_border_hedges, tmesh)) - return fill_hole(cc_border_hedges, cc_faces, working_face_range, tmesh, vpm, gt); - else - return false; -} - // Patch is not valid if: // - we insert the same face more than once // - insert (geometric) non-manifold edges @@ -1122,6 +1026,102 @@ bool check_patch_sanity(const std::vector >& patch) return true; } +// This function is only called when the hole is NOT subdivided into smaller holes +template +bool fill_hole(std::vector::halfedge_descriptor>& cc_border_hedges, + std::set::face_descriptor>& cc_faces, + std::set::face_descriptor>& working_face_range, + TriangleMesh& tmesh, + VertexPointMap vpm, + const GeomTraits& gt) +{ + typedef typename boost::graph_traits::vertex_descriptor vertex_descriptor; + typedef typename boost::graph_traits::edge_descriptor edge_descriptor; + typedef typename boost::graph_traits::face_descriptor face_descriptor; + + typedef typename boost::property_traits::value_type Point; + +#ifdef CGAL_PMP_REMOVE_SELF_INTERSECTION_DEBUG + std::cout << " DEBUG: Attempting hole-filling (no constraints), " << cc_faces.size() << " faces\n"; +#endif + + if(!order_border_halfedge_range(cc_border_hedges, tmesh)) + { + CGAL_assertion(false); // we shouldn't fail to orient the boundary cycle of the complete hole + return false; + } + + std::set cc_interior_vertices; + std::set cc_interior_edges; + + std::vector cc_border_vertices; + cc_border_vertices.reserve(cc_border_hedges.size()); + + std::vector > patch; + if(!construct_tentative_hole_patch(cc_border_vertices, cc_interior_vertices, cc_interior_edges, + cc_border_hedges, cc_faces, patch, tmesh, vpm, gt) || + !check_patch_sanity(patch)) + { +#ifdef CGAL_PMP_REMOVE_SELF_INTERSECTION_DEBUG + std::cout << " DEBUG: Failed to find acceptable hole patch\n"; +#endif + + return false; + } + + // Could renew the range directly within the patch replacement function + // to avoid erasing and re-adding the same face + for(const face_descriptor f : cc_faces) + working_face_range.erase(f); + + // Plug the new triangles in the mesh, reusing previous edges and faces + replace_faces_with_patch(cc_border_vertices, cc_interior_vertices, + cc_border_hedges, cc_interior_edges, + cc_faces, patch, tmesh, vpm, + std::inserter(working_face_range, working_face_range.end())); + +#ifdef CGAL_PMP_REMOVE_SELF_INTERSECTION_OUTPUT + static int filed_hole_id = 0; + std::stringstream oss; + oss << "results/filled_basic_" << filed_hole_id++ << ".off" << std::ends; + std::ofstream(oss.str().c_str()) << std::setprecision(17) << tmesh; +#endif + + CGAL_postcondition(is_valid_polygon_mesh(tmesh)); + + return true; +} + +// Same function as above but border of the hole is not known +template +bool fill_hole(std::set::face_descriptor>& cc_faces, + std::set::face_descriptor>& working_face_range, + TriangleMesh& tmesh, + VertexPointMap vpm, + const GeomTraits& gt) +{ + typedef typename boost::graph_traits::halfedge_descriptor halfedge_descriptor; + typedef typename boost::graph_traits::face_descriptor face_descriptor; + + std::vector cc_border_hedges; + for(face_descriptor fd : cc_faces) + { + halfedge_descriptor h = halfedge(fd, tmesh); + for(int i=0; i<3; ++i) + { + if(is_border(opposite(h, tmesh), tmesh) || cc_faces.count(face(opposite(h, tmesh), tmesh)) == 0) + cc_border_hedges.push_back(h); + + h = next(h, tmesh); + } + } + + if(order_border_halfedge_range(cc_border_hedges, tmesh)) + return fill_hole(cc_border_hedges, cc_faces, working_face_range, tmesh, vpm, gt); + else + return false; +} + template bool fill_hole_with_constraints(std::vector::halfedge_descriptor>& cc_border_hedges, std::set::face_descriptor>& cc_faces, From 3468c7bf327d5ab33447a738058723a7918e2bd6 Mon Sep 17 00:00:00 2001 From: Laurent Rineau Date: Wed, 17 Jun 2020 12:31:36 +0200 Subject: [PATCH 540/568] Use `timeout` if available, instead of a system of sleep/kill The GNU coreutils software [timeout](https://man7.org/linux/man-pages/man1/timeout.1.html) is a perfect replacement for our buggy function `wait_for_process`. This patch uses it when available. On Linux, brew, Cygwin, it is available in the `coreutils` package. --- Testsuite/test/run_testsuite_with_cmake | 52 ++++++++++++++++++------- 1 file changed, 39 insertions(+), 13 deletions(-) diff --git a/Testsuite/test/run_testsuite_with_cmake b/Testsuite/test/run_testsuite_with_cmake index 269e13a97fb..0bdad3f1d1a 100755 --- a/Testsuite/test/run_testsuite_with_cmake +++ b/Testsuite/test/run_testsuite_with_cmake @@ -21,6 +21,11 @@ if [ -n "$CGAL_TEST_PLATFORM" ]; then else PLATFORM=no-platform fi +if [ -n "${CGAL_TIMEOUT_PROG+x}" ]; then + TIMEOUT=$CGAL_TIMEOUT_PROG +else + TIMEOUT=`which timeout` +fi #clear the error file rm -f "$ERRORFILE" @@ -111,12 +116,17 @@ run_local_cgal_test() MAKEFLAGS= export MAKEFLAGS - eval ./cgal_test_with_cmake > current_compiler_output 2>&1 + if [ -n "$TIMEOUT" ]; then + "$TIMEOUT" $(( $TIME_PERIOD * 5 )) ./cgal_test_with_cmake > current_compiler_output 2>&1 + else + ./cgal_test_with_cmake > current_compiler_output 2>&1 + fi exit_value=$? if [ $exit_value -ne 0 ] then printf "%s\n" "$exit_value" > test_failure fi + return $exit_value } #test_directory @@ -152,23 +162,39 @@ test_directory() export PLATFORM TESTSUITE_CXXFLAGS TESTSUITE_LDFLAGS rm -f error.txt START=`date +%s` - run_local_cgal_test & - TIME_PERIOD=1200 if [ "$1" = "Polyhedron_Demo" ]; then TIME_PERIOD=2400 fi - if wait_for_process "$!" "$TIME_PERIOD" "5" - then - if [ -f test_failure ] ; then - exit_failure=`cat test_failure` - rm -f test_failure - echo "ERROR: cgal_test_with_cmake exited with error condition $exit_value" >> "$ERRORFILE" - echo "ERROR: cgal_test_with_cmake exited with error condition $exit_value" >> "$ERROR_OUTPUT" - fi + if [ -n "$TIMEOUT" ]; then + run_local_cgal_test + return_code=$? + if [ $return_code -eq 124 ]; then + echo "ERROR: cgal_test_with_cmake did not finish within the time bound set" >> "$ERRORFILE" + echo "ERROR: cgal_test_with_cmake did not finish within the time bound set" >> "$ERROR_OUTPUT" + else + if [ -f test_failure ] ; then + exit_failure=`cat test_failure` + rm -f test_failure + echo "ERROR: cgal_test_with_cmake exited with error condition $exit_value" >> "$ERRORFILE" + echo "ERROR: cgal_test_with_cmake exited with error condition $exit_value" >> "$ERROR_OUTPUT" + fi + fi else - echo "ERROR: cgal_test_with_cmake did not finish within the time bound set" >> "$ERRORFILE" - echo "ERROR: cgal_test_with_cmake did not finish within the time bound set" >> "$ERROR_OUTPUT" + run_local_cgal_test & + + if wait_for_process "$!" "$TIME_PERIOD" "5" + then + if [ -f test_failure ] ; then + exit_failure=`cat test_failure` + rm -f test_failure + echo "ERROR: cgal_test_with_cmake exited with error condition $exit_value" >> "$ERRORFILE" + echo "ERROR: cgal_test_with_cmake exited with error condition $exit_value" >> "$ERROR_OUTPUT" + fi + else + echo "ERROR: cgal_test_with_cmake did not finish within the time bound set" >> "$ERRORFILE" + echo "ERROR: cgal_test_with_cmake did not finish within the time bound set" >> "$ERROR_OUTPUT" + fi fi STOP=`date +%s` DURATION=`expr "$STOP" - "$START"` From 7c8bb622a7df41c32e5c8631762b0f0c1a731ba8 Mon Sep 17 00:00:00 2001 From: Laurent Rineau Date: Wed, 17 Jun 2020 12:35:42 +0200 Subject: [PATCH 541/568] Whitespace fixes --- Testsuite/test/run_testsuite_with_cmake | 33 ++++++++++++------------- 1 file changed, 16 insertions(+), 17 deletions(-) diff --git a/Testsuite/test/run_testsuite_with_cmake b/Testsuite/test/run_testsuite_with_cmake index 0bdad3f1d1a..7f0639451ad 100755 --- a/Testsuite/test/run_testsuite_with_cmake +++ b/Testsuite/test/run_testsuite_with_cmake @@ -16,9 +16,9 @@ TESTSUITE_LDFLAGS="" CURRENTDIR=`pwd` ERRORFILE=${CURRENTDIR}/error.txt -if [ -n "$CGAL_TEST_PLATFORM" ]; then +if [ -n "$CGAL_TEST_PLATFORM" ]; then PLATFORM=$CGAL_TEST_PLATFORM -else +else PLATFORM=no-platform fi if [ -n "${CGAL_TIMEOUT_PROG+x}" ]; then @@ -39,9 +39,9 @@ process_tree() local pid=$1 local result= echo $pid - ps -a | awk '!/^ +PID/ {print $1 " " $2}' | { - while read apid appid; do - if [ "$appid" = "$pid" ]; then + ps -a | awk '!/^ +PID/ {print $1 " " $2}' | { + while read apid appid; do + if [ "$appid" = "$pid" ]; then process_tree $apid fi done @@ -58,11 +58,11 @@ wait_for_process() period=$3 while [ $cycles -ne 0 ] do - cycles=`expr $cycles - 1` + cycles=`expr $cycles - 1` # send SIGCONT to the process and check the exit value of kill. # If the process still exists, the call to kill succeeds (and the signal is # ignored). - + kill -CONT $pid 2>kill_output 1>/dev/null; terminated=$? # But under CYGWIN the exit status is not to be trusted. if [ $terminated -eq 0 ]; then @@ -94,7 +94,7 @@ wait_for_process() # Bash, the Bash manual states that it ignores SIGTERM. # However, it does not catch SIGHUP. That is why the first # signal send is SIGHUP. - case "`uname`" in + case "`uname`" in CYGWIN*) pids=`process_tree $pid`;; *) pids=$pid;; @@ -104,7 +104,7 @@ wait_for_process() # If SIGHUP was not enough, SIGKILL will finish the job, 10s after. for p in $pids; do kill -KILL $p 2>/dev/null; done fi - return 1 + return 1 fi return 0 } @@ -136,8 +136,8 @@ test_directory() { cd "$CURRENTDIR" if [ -d $1 ] ; then - echo "DIRECTORY $1:" - echo + echo "DIRECTORY $1:" + echo echo "DIRECTORY $1:" >> "$ERRORFILE" echo >> "$ERRORFILE" @@ -202,7 +202,7 @@ test_directory() printf " # Running time: %s (seconds)\n\n" "$DURATION" >> "$ERROR_OUTPUT" cat current_compiler_output >> "$COMPILER_OUTPUT" cat current_compiler_output - rm -f current_compiler_output + rm -f current_compiler_output if [ -f error.txt ] ; then cat error.txt >> "$ERRORFILE" @@ -227,18 +227,18 @@ test_directory() run_testsuite() { - + echo "---------------------------------------------------------------" - echo "- Testing platform $PLATFORM" + echo "- Testing platform $PLATFORM" echo "---------------------------------------------------------------" - echo + echo echo "---------------------------------------------------------------" >> "$ERRORFILE" echo "- TEST RESULTS FROM PLATFORM $PLATFORM" >> "$ERRORFILE" echo "---------------------------------------------------------------" >> "$ERRORFILE" echo >> "$ERRORFILE" - case "`uname`" in + case "`uname`" in CYGWIN*) PATH=`cygpath "$CGAL_DIR"`/bin:`cygpath "$CGAL_DIR"`/lib:$PATH export PATH @@ -258,4 +258,3 @@ else fi run_testsuite - From a1ea396196d14c9101af4dde03cc06b034e4cd78 Mon Sep 17 00:00:00 2001 From: Laurent Rineau Date: Wed, 17 Jun 2020 12:38:59 +0200 Subject: [PATCH 542/568] Patch for MacOS https://stackoverflow.com/a/21118126/1728537 > You can use > > brew install coreutils > > And then whenever you need timeout, use > > gtimeout --- Testsuite/test/run_testsuite_with_cmake | 1 + 1 file changed, 1 insertion(+) diff --git a/Testsuite/test/run_testsuite_with_cmake b/Testsuite/test/run_testsuite_with_cmake index 7f0639451ad..afceab97fcb 100755 --- a/Testsuite/test/run_testsuite_with_cmake +++ b/Testsuite/test/run_testsuite_with_cmake @@ -25,6 +25,7 @@ if [ -n "${CGAL_TIMEOUT_PROG+x}" ]; then TIMEOUT=$CGAL_TIMEOUT_PROG else TIMEOUT=`which timeout` + [ -z "$TIMEOUT" ] && TIMEOUT=`which gtimeout` fi #clear the error file From 3003fb308f8e7ce335f67df842d6213e77661f50 Mon Sep 17 00:00:00 2001 From: Maxime Gimeno Date: Thu, 18 Jun 2020 13:35:40 +0200 Subject: [PATCH 543/568] More flags warnings --- .../Arrangement_on_surface_2/ArrangementDemoPropertiesDialog.h | 2 +- .../demo/Arrangement_on_surface_2/OverlayDialog.h | 2 +- Polyhedron/demo/Polyhedron/Plugins/Surface_mesh/UVProjector.h | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/Arrangement_on_surface_2/demo/Arrangement_on_surface_2/ArrangementDemoPropertiesDialog.h b/Arrangement_on_surface_2/demo/Arrangement_on_surface_2/ArrangementDemoPropertiesDialog.h index 4e20f9c7835..dd6158edd48 100644 --- a/Arrangement_on_surface_2/demo/Arrangement_on_surface_2/ArrangementDemoPropertiesDialog.h +++ b/Arrangement_on_surface_2/demo/Arrangement_on_surface_2/ArrangementDemoPropertiesDialog.h @@ -43,7 +43,7 @@ class ArrangementDemoPropertiesDialog : public QDialog }; ArrangementDemoPropertiesDialog( ArrangementDemoWindow* parent_ = 0, - Qt::WindowFlags f = 0 ); + Qt::WindowFlags f = Qt::WindowType(0)); QVariant property( int index ); protected: diff --git a/Arrangement_on_surface_2/demo/Arrangement_on_surface_2/OverlayDialog.h b/Arrangement_on_surface_2/demo/Arrangement_on_surface_2/OverlayDialog.h index fc80dc35336..fb1c45ea1bb 100644 --- a/Arrangement_on_surface_2/demo/Arrangement_on_surface_2/OverlayDialog.h +++ b/Arrangement_on_surface_2/demo/Arrangement_on_surface_2/OverlayDialog.h @@ -29,7 +29,7 @@ class OverlayDialog : public QDialog ARRANGEMENT = 32 } OverlayDialogRole; - OverlayDialog( ArrangementDemoWindow* parent, Qt::WindowFlags f = 0 ); + OverlayDialog( ArrangementDemoWindow* parent, Qt::WindowFlags f = Qt::WindowType(0) ); std::vector< CGAL::Object > selectedArrangements( ) const; diff --git a/Polyhedron/demo/Polyhedron/Plugins/Surface_mesh/UVProjector.h b/Polyhedron/demo/Polyhedron/Plugins/Surface_mesh/UVProjector.h index 6a726c8db90..45bb627538c 100644 --- a/Polyhedron/demo/Polyhedron/Plugins/Surface_mesh/UVProjector.h +++ b/Polyhedron/demo/Polyhedron/Plugins/Surface_mesh/UVProjector.h @@ -23,7 +23,7 @@ struct State{ class UVProjector:public QWidget { public: - UVProjector(QWidget* parent = 0, Qt::WindowFlags flags =0) + UVProjector(QWidget* parent = 0, Qt::WindowFlags flags = Qt::WindowType(0)) :QWidget(parent,flags) { setMouseTracking(true); From c6a922c9dc01c796c69cafec4da709d62ca12647 Mon Sep 17 00:00:00 2001 From: Jane Tournois Date: Mon, 18 May 2020 14:51:42 +0200 Subject: [PATCH 544/568] fix Facet_updater parallel `vertex_to_proj` was not locked and this was causing seg faults --- Mesh_3/include/CGAL/Mesh_3/C3T3_helpers.h | 19 +++++++++++-------- 1 file changed, 11 insertions(+), 8 deletions(-) diff --git a/Mesh_3/include/CGAL/Mesh_3/C3T3_helpers.h b/Mesh_3/include/CGAL/Mesh_3/C3T3_helpers.h index 3f4421ed3e9..74cd1da3c9a 100644 --- a/Mesh_3/include/CGAL/Mesh_3/C3T3_helpers.h +++ b/Mesh_3/include/CGAL/Mesh_3/C3T3_helpers.h @@ -1267,6 +1267,7 @@ private: class Facet_updater { + const Self& m_c3t3_helpers; Vertex_set& vertex_to_proj; C3T3& c3t3_; Update_c3t3& c3t3_updater_; @@ -1275,8 +1276,10 @@ private: typedef Facet& reference; typedef const Facet& const_reference; - Facet_updater(C3T3& c3t3, Vertex_set& vertex_to_proj, Update_c3t3& c3t3_updater_) - : vertex_to_proj(vertex_to_proj), c3t3_(c3t3), c3t3_updater_(c3t3_updater_) + Facet_updater(const Self& c3t3_helpers, + C3T3& c3t3, Vertex_set& vertex_to_proj, Update_c3t3& c3t3_updater_) + : m_c3t3_helpers(c3t3_helpers), + vertex_to_proj(vertex_to_proj), c3t3_(c3t3), c3t3_updater_(c3t3_updater_) {} void @@ -1296,9 +1299,9 @@ private: const Vertex_handle& v = f.first->vertex((k+i)&3); if ( c3t3_.in_dimension(v) > 2 ) { - //lock_vertex_to_proj(); + m_c3t3_helpers.lock_vertex_to_proj(); vertex_to_proj.insert(v); - //unlock_vertex_to_proj(); + m_c3t3_helpers.unlock_vertex_to_proj(); } } } @@ -2732,7 +2735,7 @@ rebuild_restricted_delaunay(OutdatedCells& outdated_cells, // Note: ~42% of rebuild_restricted_delaunay time // Facet_vector facets; lock_vertex_to_proj(); - Facet_updater facet_updater(c3t3_,vertex_to_proj, updater); + Facet_updater facet_updater(*this, c3t3_,vertex_to_proj, updater); unlock_vertex_to_proj(); update_facets(outdated_cells_vector, facet_updater); @@ -2761,7 +2764,7 @@ rebuild_restricted_delaunay(OutdatedCells& outdated_cells, // Get facets (returns each canonical facet only once) // Note: ~42% of rebuild_restricted_delaunay time // Facet_vector facets; - Facet_updater facet_updater(c3t3_,vertex_to_proj, updater); + Facet_updater facet_updater(*this, c3t3_,vertex_to_proj, updater); update_facets(outdated_cells, facet_updater); // now we can clear @@ -2949,7 +2952,7 @@ move_point(const Vertex_handle& old_vertex, Cell_vector incident_cells_; incident_cells_.reserve(64); - tr_.incident_cells(old_vertex, std::back_inserter(incident_cells_)); + tr_.incident_cells_threadsafe(old_vertex, std::back_inserter(incident_cells_)); const Weighted_point& position = tr_.point(old_vertex); const Weighted_point& new_position = cwp(translate(cp(position), move)); @@ -3873,7 +3876,7 @@ get_conflict_zone_topo_change(const Vertex_handle& v, // Get triangulation_vertex incident cells : removal conflict zone // TODO: hasn't it already been computed in "perturb_vertex" (when getting the slivers)? // We don't try to lock the incident cells since they've already been locked - tr_.incident_cells(v, removal_conflict_cells); + tr_.incident_cells_threadsafe(v, removal_conflict_cells); // Get conflict_point conflict zone int li=0; From ad9c357f3302ed7f3f43a4a069ea42c1c5218ae0 Mon Sep 17 00:00:00 2001 From: Jane Tournois Date: Wed, 17 Jun 2020 07:13:35 +0200 Subject: [PATCH 545/568] add adjacent_vertices_threadsafe and use it in nearest_power_vertex() --- .../CGAL/Triangulation_data_structure_3.h | 46 +++++++++++++++++++ .../include/CGAL/Regular_triangulation_3.h | 2 +- .../include/CGAL/Triangulation_3.h | 6 +++ 3 files changed, 53 insertions(+), 1 deletion(-) diff --git a/TDS_3/include/CGAL/Triangulation_data_structure_3.h b/TDS_3/include/CGAL/Triangulation_data_structure_3.h index e971ee6a7db..c81a7cab524 100644 --- a/TDS_3/include/CGAL/Triangulation_data_structure_3.h +++ b/TDS_3/include/CGAL/Triangulation_data_structure_3.h @@ -1297,6 +1297,52 @@ public: return adjacent_vertices(v, vertices); } + template + OutputIterator + adjacent_vertices_threadsafe(Vertex_handle v, OutputIterator vertices) const + { + return adjacent_vertices_threadsafe(v, vertices); + } + + template + OutputIterator + adjacent_vertices_threadsafe(Vertex_handle v, OutputIterator vertices, + Filter f = Filter()) const + { + CGAL_triangulation_precondition(v != Vertex_handle()); + CGAL_triangulation_precondition(dimension() >= -1); + CGAL_triangulation_expensive_precondition(is_vertex(v)); + CGAL_triangulation_expensive_precondition(is_valid()); + + if (dimension() == -1) + return vertices; + + if (dimension() == 0) { + Vertex_handle v1 = v->cell()->neighbor(0)->vertex(0); + if (!f(v1)) *vertices++ = v1; + return vertices; + } + + if (dimension() == 1) { + CGAL_triangulation_assertion(number_of_vertices() >= 3); + Cell_handle n0 = v->cell(); + const int index_v_in_n0 = n0->index(v); + CGAL_assume(index_v_in_n0 <= 1); + Cell_handle n1 = n0->neighbor(1 - index_v_in_n0); + const int index_v_in_n1 = n1->index(v); + CGAL_assume(index_v_in_n1 <= 1); + Vertex_handle v1 = n0->vertex(1 - index_v_in_n0); + Vertex_handle v2 = n1->vertex(1 - index_v_in_n1); + if (!f(v1)) *vertices++ = v1; + if (!f(v2)) *vertices++ = v2; + return vertices; + } + return visit_incident_cells_threadsafe< + Vertex_extractor, OutputIterator, Filter, + internal::Has_member_visited::value>, + OutputIterator>(v, vertices, f); + } + template OutputIterator visit_incident_cells(Vertex_handle v, OutputIterator output, Filter f) const diff --git a/Triangulation_3/include/CGAL/Regular_triangulation_3.h b/Triangulation_3/include/CGAL/Regular_triangulation_3.h index a4867cf9946..b93970449ce 100644 --- a/Triangulation_3/include/CGAL/Regular_triangulation_3.h +++ b/Triangulation_3/include/CGAL/Regular_triangulation_3.h @@ -1711,7 +1711,7 @@ nearest_power_vertex(const Bare_point& p, Cell_handle start) const while(true) { Vertex_handle tmp = nearest; - adjacent_vertices(nearest, std::back_inserter(vs)); + adjacent_vertices_threadsafe(nearest, std::back_inserter(vs)); for(typename std::vector::const_iterator vsit = vs.begin(); vsit != vs.end(); ++vsit) tmp = nearest_power_vertex(p, tmp, *vsit); diff --git a/Triangulation_3/include/CGAL/Triangulation_3.h b/Triangulation_3/include/CGAL/Triangulation_3.h index 6941c6c8acf..b412b36471d 100644 --- a/Triangulation_3/include/CGAL/Triangulation_3.h +++ b/Triangulation_3/include/CGAL/Triangulation_3.h @@ -2138,6 +2138,12 @@ public: return _tds.adjacent_vertices(v, vertices); } + template + OutputIterator adjacent_vertices_threadsafe(Vertex_handle v, OutputIterator vertices) const + { + return _tds.adjacent_vertices_threadsafe(v, vertices); + } + template OutputIterator adjacent_vertices_and_cells_3(Vertex_handle v, OutputIterator vertices, std::vector& cells) const From 7cd18cd659d4389f538485c20145e3b589fa80d5 Mon Sep 17 00:00:00 2001 From: Jane Tournois Date: Wed, 17 Jun 2020 13:21:03 +0200 Subject: [PATCH 546/568] unlock after the move, even if there is no topological change to avoid making changes with another thread --- Mesh_3/include/CGAL/Mesh_3/C3T3_helpers.h | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/Mesh_3/include/CGAL/Mesh_3/C3T3_helpers.h b/Mesh_3/include/CGAL/Mesh_3/C3T3_helpers.h index 74cd1da3c9a..c09fc396c76 100644 --- a/Mesh_3/include/CGAL/Mesh_3/C3T3_helpers.h +++ b/Mesh_3/include/CGAL/Mesh_3/C3T3_helpers.h @@ -3070,11 +3070,12 @@ move_point(const Vertex_handle& old_vertex, lock_outdated_cells(); std::copy(incident_cells_.begin(),incident_cells_.end(), std::inserter(outdated_cells_set, outdated_cells_set.end())); - unlock_outdated_cells(); Vertex_handle new_vertex = move_point_no_topo_change(old_vertex, move, new_position); + unlock_outdated_cells(); + // Don't "unlock_all_elements" here, the caller may need it to do it himself return new_vertex; } From f55ffabbe082e11a979271ed28e2ffe2a4845de4 Mon Sep 17 00:00:00 2001 From: Jane Tournois Date: Wed, 17 Jun 2020 13:36:04 +0200 Subject: [PATCH 547/568] add an assertion in make_canonical it also helps to make the code more explicit --- Triangulation_3/include/CGAL/Triangulation_3.h | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/Triangulation_3/include/CGAL/Triangulation_3.h b/Triangulation_3/include/CGAL/Triangulation_3.h index b412b36471d..795aca2d6a0 100644 --- a/Triangulation_3/include/CGAL/Triangulation_3.h +++ b/Triangulation_3/include/CGAL/Triangulation_3.h @@ -4229,19 +4229,21 @@ make_canonical(Vertex_triple& t) const Vertex_handle tmp; switch(i) { - case 0: return; + case 0: break; case 1: tmp = t.first; t.first = t.second; t.second = t.third; t.third = tmp; - return; + break; default: tmp = t.first; t.first = t.third; t.third = t.second; t.second = tmp; } + + CGAL_assertion(t.first < t.second && t.first < t.third); } template < class GT, class Tds, class Lds > From daaf92d0ac0a2ab219c4a9f4967bd082153dccb5 Mon Sep 17 00:00:00 2001 From: Jane Tournois Date: Thu, 18 Jun 2020 13:48:28 +0200 Subject: [PATCH 548/568] rename make_canonical() to make_canonical_oriented_triple() to make it more explicit --- .../include/CGAL/Triangulation_3.h | 46 +++++++++---------- 1 file changed, 23 insertions(+), 23 deletions(-) diff --git a/Triangulation_3/include/CGAL/Triangulation_3.h b/Triangulation_3/include/CGAL/Triangulation_3.h index 795aca2d6a0..a60b57f9676 100644 --- a/Triangulation_3/include/CGAL/Triangulation_3.h +++ b/Triangulation_3/include/CGAL/Triangulation_3.h @@ -1646,7 +1646,7 @@ private: Vertex_handle>::type Vertex_handle_unique_hash_map; Vertex_triple make_vertex_triple(const Facet& f) const; - void make_canonical(Vertex_triple& t) const; + void make_canonical_oriented_triple(Vertex_triple& t) const; template < class VertexRemover > VertexRemover& make_hole_2D(Vertex_handle v, std::list& hole, @@ -4215,7 +4215,7 @@ make_vertex_triple(const Facet& f) const template < class Gt, class Tds, class Lds > void Triangulation_3:: -make_canonical(Vertex_triple& t) const +make_canonical_oriented_triple(Vertex_triple& t) const { int i = (t.first < t.second) ? 0 : 1; if(i==0) @@ -4770,7 +4770,7 @@ make_hole_3D(Vertex_handle v, Cell_handle opp_cit = (*cit)->neighbor(indv); Facet f(opp_cit, opp_cit->index(*cit)); Vertex_triple vt = make_vertex_triple(f); - make_canonical(vt); + make_canonical_oriented_triple(vt); outer_map[vt] = f; for(int i=0; i<4; i++) { @@ -4797,7 +4797,7 @@ make_hole_3D(Vertex_handle v, Cell_handle opp_cit = (*cit)->neighbor(indv); Facet f(opp_cit, opp_cit->index(*cit)); Vertex_triple vt = make_vertex_triple(f); - make_canonical(vt); + make_canonical_oriented_triple(vt); outer_map[vt] = f; for(int i=0; i<4; i++) { @@ -4985,7 +4985,7 @@ remove_3D(Vertex_handle v, VertexRemover& remover) Facet f = std::pair(it,i); Vertex_triple vt_aux = make_vertex_triple(f); Vertex_triple vt(vmap[vt_aux.first], vmap[vt_aux.third], vmap[vt_aux.second]); - make_canonical(vt); + make_canonical_oriented_triple(vt); inner_map[vt]= f; } } @@ -5000,7 +5000,7 @@ remove_3D(Vertex_handle v, VertexRemover& remover) Facet f = std::pair(it,i); Vertex_triple vt_aux = make_vertex_triple(f); Vertex_triple vt(vmap[vt_aux.first], vmap[vt_aux.third], vmap[vt_aux.second]); - make_canonical(vt); + make_canonical_oriented_triple(vt); inner_map[vt]= f; } } @@ -5043,7 +5043,7 @@ remove_3D(Vertex_handle v, VertexRemover& remover) { Facet f = std::pair(new_ch,i); Vertex_triple vt = make_vertex_triple(f); - make_canonical(vt); + make_canonical_oriented_triple(vt); std::swap(vt.second,vt.third); typename Vertex_triple_Facet_map::iterator oit2 = outer_map.find(vt); @@ -5181,7 +5181,7 @@ remove_3D(Vertex_handle v, VertexRemover& remover, Facet f = std::pair(it,i); Vertex_triple vt_aux = make_vertex_triple(f); Vertex_triple vt(vmap[vt_aux.first],vmap[vt_aux.third],vmap[vt_aux.second]); - make_canonical(vt); + make_canonical_oriented_triple(vt); inner_map[vt]= f; } } @@ -5196,7 +5196,7 @@ remove_3D(Vertex_handle v, VertexRemover& remover, Facet f = std::pair(it,i); Vertex_triple vt_aux = make_vertex_triple(f); Vertex_triple vt(vmap[vt_aux.first],vmap[vt_aux.third],vmap[vt_aux.second]); - make_canonical(vt); + make_canonical_oriented_triple(vt); inner_map[vt]= f; } } @@ -5241,7 +5241,7 @@ remove_3D(Vertex_handle v, VertexRemover& remover, { Facet f = std::pair(new_ch,i); Vertex_triple vt = make_vertex_triple(f); - make_canonical(vt); + make_canonical_oriented_triple(vt); std::swap(vt.second,vt.third); typename Vertex_triple_Facet_map::iterator oit2 = outer_map.find(vt); @@ -5485,7 +5485,7 @@ remove_3D(Vertex_handle v, VertexRemover& remover, OutputItCells fit) Facet f = std::pair(it,i); Vertex_triple vt_aux = make_vertex_triple(f); Vertex_triple vt(vmap[vt_aux.first], vmap[vt_aux.third], vmap[vt_aux.second]); - make_canonical(vt); + make_canonical_oriented_triple(vt); inner_map[vt] = f; } } @@ -5499,7 +5499,7 @@ remove_3D(Vertex_handle v, VertexRemover& remover, OutputItCells fit) Facet f = std::pair(it,i); Vertex_triple vt_aux = make_vertex_triple(f); Vertex_triple vt(vmap[vt_aux.first], vmap[vt_aux.third], vmap[vt_aux.second]); - make_canonical(vt); + make_canonical_oriented_triple(vt); inner_map[vt] = f; } } @@ -5546,7 +5546,7 @@ remove_3D(Vertex_handle v, VertexRemover& remover, OutputItCells fit) { Facet f = std::pair(new_ch,i); Vertex_triple vt = make_vertex_triple(f); - make_canonical(vt); + make_canonical_oriented_triple(vt); std::swap(vt.second, vt.third); typename Vertex_triple_Facet_map::iterator oit2 = outer_map.find(vt); if(oit2 == outer_map.end()) @@ -5873,7 +5873,7 @@ move_if_no_collision(Vertex_handle v, const Point& p, Facet f = std::pair(it,i); Vertex_triple vt_aux = make_vertex_triple(f); Vertex_triple vt(vmap[vt_aux.first],vmap[vt_aux.third],vmap[vt_aux.second]); - make_canonical(vt); + make_canonical_oriented_triple(vt); inner_map[vt]= f; } } @@ -5888,7 +5888,7 @@ move_if_no_collision(Vertex_handle v, const Point& p, Facet f = std::pair(it,i); Vertex_triple vt_aux = make_vertex_triple(f); Vertex_triple vt(vmap[vt_aux.first],vmap[vt_aux.third],vmap[vt_aux.second]); - make_canonical(vt); + make_canonical_oriented_triple(vt); inner_map[vt]= f; } } @@ -5934,7 +5934,7 @@ move_if_no_collision(Vertex_handle v, const Point& p, { Facet f = std::pair(new_ch,i); Vertex_triple vt = make_vertex_triple(f); - make_canonical(vt); + make_canonical_oriented_triple(vt); std::swap(vt.second,vt.third); typename Vertex_triple_Facet_map::iterator oit2 = outer_map.find(vt); if(oit2 == outer_map.end()) @@ -6325,7 +6325,7 @@ move_if_no_collision_and_give_new_cells(Vertex_handle v, const Point& p, Facet f = std::pair(it,i); Vertex_triple vt_aux = make_vertex_triple(f); Vertex_triple vt(vmap[vt_aux.first], vmap[vt_aux.third], vmap[vt_aux.second]); - make_canonical(vt); + make_canonical_oriented_triple(vt); inner_map[vt]= f; } } @@ -6340,7 +6340,7 @@ move_if_no_collision_and_give_new_cells(Vertex_handle v, const Point& p, Facet f = std::pair(it,i); Vertex_triple vt_aux = make_vertex_triple(f); Vertex_triple vt(vmap[vt_aux.first], vmap[vt_aux.third], vmap[vt_aux.second]); - make_canonical(vt); + make_canonical_oriented_triple(vt); inner_map[vt]= f; } } @@ -6387,7 +6387,7 @@ move_if_no_collision_and_give_new_cells(Vertex_handle v, const Point& p, { Facet f = std::pair(new_ch, i); Vertex_triple vt = make_vertex_triple(f); - make_canonical(vt); + make_canonical_oriented_triple(vt); std::swap(vt.second,vt.third); typename Vertex_triple_Facet_map::iterator oit2 = outer_map.find(vt); if(oit2 == outer_map.end()) @@ -6519,7 +6519,7 @@ _make_big_hole_3D(Vertex_handle v, Facet f(opp_cit, opp_i); Vertex_triple vt = make_vertex_triple(f); - make_canonical(vt); + make_canonical_oriented_triple(vt); outer_map[vt] = f; v1->set_cell(opp_cit); v2->set_cell(opp_cit); @@ -6664,7 +6664,7 @@ _remove_cluster_3D(InputIterator first, InputIterator beyond, VertexRemover& rem Facet f = std::pair(it,index); Vertex_triple vt_aux = this->make_vertex_triple(f); Vertex_triple vt(vmap[vt_aux.first], vmap[vt_aux.third], vmap[vt_aux.second]); - this->make_canonical(vt); + this->make_canonical_oriented_triple(vt); inner_map[vt]= f; } } @@ -6679,7 +6679,7 @@ _remove_cluster_3D(InputIterator first, InputIterator beyond, VertexRemover& rem Facet f = std::pair(it,index); Vertex_triple vt_aux = this->make_vertex_triple(f); Vertex_triple vt(vmap[vt_aux.first], vmap[vt_aux.third], vmap[vt_aux.second]); - this->make_canonical(vt); + this->make_canonical_oriented_triple(vt); inner_map[vt]= f; } } @@ -6728,7 +6728,7 @@ _remove_cluster_3D(InputIterator first, InputIterator beyond, VertexRemover& rem { Facet f = std::pair(new_ch,index); Vertex_triple vt = this->make_vertex_triple(f); - this->make_canonical(vt); + this->make_canonical_oriented_triple(vt); std::swap(vt.second,vt.third); typename Vertex_triple_Facet_map::iterator oit2 = outer_map.find(vt); if(oit2 == outer_map.end()) From 3b8c06f83631c43b4bce1735d12f51dc729beab1 Mon Sep 17 00:00:00 2001 From: Jane Tournois Date: Thu, 18 Jun 2020 14:23:16 +0200 Subject: [PATCH 549/568] fix adjacent_vertices_threadsafe internal::Has_member_visited is not threadsafe --- TDS_3/include/CGAL/Triangulation_data_structure_3.h | 2 +- Triangulation_3/include/CGAL/Regular_triangulation_3.h | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/TDS_3/include/CGAL/Triangulation_data_structure_3.h b/TDS_3/include/CGAL/Triangulation_data_structure_3.h index c81a7cab524..1024efa0943 100644 --- a/TDS_3/include/CGAL/Triangulation_data_structure_3.h +++ b/TDS_3/include/CGAL/Triangulation_data_structure_3.h @@ -1339,7 +1339,7 @@ public: } return visit_incident_cells_threadsafe< Vertex_extractor, OutputIterator, Filter, - internal::Has_member_visited::value>, + false>, OutputIterator>(v, vertices, f); } diff --git a/Triangulation_3/include/CGAL/Regular_triangulation_3.h b/Triangulation_3/include/CGAL/Regular_triangulation_3.h index b93970449ce..0bf3b88d919 100644 --- a/Triangulation_3/include/CGAL/Regular_triangulation_3.h +++ b/Triangulation_3/include/CGAL/Regular_triangulation_3.h @@ -147,6 +147,7 @@ public: using Tr_Base::geom_traits; #endif using Tr_Base::adjacent_vertices; + using Tr_Base::adjacent_vertices_threadsafe; using Tr_Base::cw; using Tr_Base::ccw; using Tr_Base::construct_point; From 13c0719e8716de2293e35857e4cb321667edfad8 Mon Sep 17 00:00:00 2001 From: Jane Tournois Date: Thu, 18 Jun 2020 14:24:34 +0200 Subject: [PATCH 550/568] fix incident_edges_threadsafe internal::Has_member_visited::value is not threadsafe --- TDS_3/include/CGAL/Triangulation_data_structure_3.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/TDS_3/include/CGAL/Triangulation_data_structure_3.h b/TDS_3/include/CGAL/Triangulation_data_structure_3.h index 1024efa0943..6c5c7e3ee29 100644 --- a/TDS_3/include/CGAL/Triangulation_data_structure_3.h +++ b/TDS_3/include/CGAL/Triangulation_data_structure_3.h @@ -1225,7 +1225,7 @@ public: return visit_incident_cells_threadsafe< Vertex_extractor, OutputIterator, Filter, - internal::Has_member_visited::value>, + false>, OutputIterator>(v, edges, f); } From d4b7af22baf554a6f67612c081b629bb23e9c911 Mon Sep 17 00:00:00 2001 From: Jane Tournois Date: Fri, 29 May 2020 08:41:26 +0200 Subject: [PATCH 551/568] use tr_.try_lock_and_get_incident_cells() and remove a "todo" of CJ --- Mesh_3/include/CGAL/Mesh_3/C3T3_helpers.h | 71 ++--------------------- 1 file changed, 5 insertions(+), 66 deletions(-) diff --git a/Mesh_3/include/CGAL/Mesh_3/C3T3_helpers.h b/Mesh_3/include/CGAL/Mesh_3/C3T3_helpers.h index c09fc396c76..c642cb960ba 100644 --- a/Mesh_3/include/CGAL/Mesh_3/C3T3_helpers.h +++ b/Mesh_3/include/CGAL/Mesh_3/C3T3_helpers.h @@ -839,16 +839,6 @@ public: Moving_vertices_set& moving_vertices, bool *could_lock_zone) const; - /** - * Try to lock the incident cells and return them in \c cells - * Return value: - * - false: everything is unlocked and \c cells is empty - * - true: incident cells are locked and \c cells contains all of them - */ - bool - try_lock_and_get_incident_cells(const Vertex_handle& v, - Cell_vector &cells) const; - /** * Try to lock ALL the incident cells and return in \c cells the ones * whose \c filter says "true". @@ -3041,9 +3031,10 @@ move_point(const Vertex_handle& old_vertex, //======= Get incident cells ========== Cell_vector incident_cells_; incident_cells_.reserve(64); - if (try_lock_and_get_incident_cells(old_vertex, incident_cells_) == false) + if (tr_.try_lock_and_get_incident_cells(old_vertex, incident_cells_) == false) { *could_lock_zone = false; + unlock_all_elements(); return Vertex_handle(); } //======= /Get incident cells ========== @@ -3587,60 +3578,6 @@ get_incident_slivers_without_using_tds_data(const Vertex_handle& v, tr_.incident_cells_threadsafe(v, boost::make_function_output_iterator(f)); } -// CJTODO: call tr_.try_lock_and_get_incident_cells instead? -template -bool -C3T3_helpers:: -try_lock_and_get_incident_cells(const Vertex_handle& v, - Cell_vector &cells) const - { - // We need to lock v individually first, to be sure v->cell() is valid - if (!try_lock_vertex(v)) - return false; - - Cell_handle d = v->cell(); - if (!try_lock_element(d)) // LOCK - { - unlock_all_elements(); - return false; - } - cells.push_back(d); - d->tds_data().mark_in_conflict(); - int head=0; - int tail=1; - do { - Cell_handle c = cells[head]; - - for (int i=0; i<4; ++i) { - if (c->vertex(i) == v) - continue; - Cell_handle next = c->neighbor(i); - - if (!try_lock_element(next)) // LOCK - { - for(Cell_handle ch : cells) - { - ch->tds_data().clear(); - } - cells.clear(); - unlock_all_elements(); - return false; - } - if (! next->tds_data().is_clear()) - continue; - cells.push_back(next); - ++tail; - next->tds_data().mark_in_conflict(); - } - ++head; - } while(head != tail); - for(Cell_handle ch : cells) - { - ch->tds_data().clear(); - } - return true; - } - template template bool @@ -3651,7 +3588,7 @@ try_lock_and_get_incident_cells(const Vertex_handle& v, { std::vector tmp_cells; tmp_cells.reserve(64); - bool ret = try_lock_and_get_incident_cells(v, tmp_cells); + bool ret = tr_.try_lock_and_get_incident_cells(v, tmp_cells); if (ret) { for(Cell_handle ch : tmp_cells) @@ -3660,6 +3597,8 @@ try_lock_and_get_incident_cells(const Vertex_handle& v, cells.push_back(ch); } } + else + tr_.unlock_all_elements(); return ret; } From 83fed40f0b91f54c13a6324baed2b260e01f2a56 Mon Sep 17 00:00:00 2001 From: Maxime Gimeno Date: Fri, 19 Jun 2020 14:45:32 +0200 Subject: [PATCH 552/568] Fix unknown behavior that changed in Visual 2019 --- STL_Extension/include/CGAL/Concurrent_compact_container.h | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/STL_Extension/include/CGAL/Concurrent_compact_container.h b/STL_Extension/include/CGAL/Concurrent_compact_container.h index 5ab9eca6790..40151f27114 100644 --- a/STL_Extension/include/CGAL/Concurrent_compact_container.h +++ b/STL_Extension/include/CGAL/Concurrent_compact_container.h @@ -341,17 +341,25 @@ public: iterator emplace(const Args&... args) { + typedef CCC_internal::Erase_counter_strategy< + CCC_internal::has_increment_erase_counter::value> EraseCounterStrategy; FreeList * fl = get_free_list(); pointer ret = init_insert(fl); + auto erase_counter = EraseCounterStrategy::erase_counter(*ret);; new (ret) value_type(args...); + EraseCounterStrategy::set_erase_counter(*ret, erase_counter); return finalize_insert(ret, fl); } iterator insert(const T &t) { + typedef CCC_internal::Erase_counter_strategy< + CCC_internal::has_increment_erase_counter::value> EraseCounterStrategy; FreeList * fl = get_free_list(); pointer ret = init_insert(fl); + auto erase_counter = EraseCounterStrategy::erase_counter(*ret);; std::allocator_traits::construct(m_alloc, ret, t); + EraseCounterStrategy::set_erase_counter(*ret, erase_counter); return finalize_insert(ret, fl); } From cfc907e6a320e621fc6ff611a30f960884da205c Mon Sep 17 00:00:00 2001 From: Maxime Gimeno Date: Fri, 19 Jun 2020 15:14:21 +0200 Subject: [PATCH 553/568] More fixes --- .../Arrangement_on_surface_2/ArrangementDemoGraphicsView.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Arrangement_on_surface_2/demo/Arrangement_on_surface_2/ArrangementDemoGraphicsView.cpp b/Arrangement_on_surface_2/demo/Arrangement_on_surface_2/ArrangementDemoGraphicsView.cpp index 050a97e81df..cc08513c55b 100644 --- a/Arrangement_on_surface_2/demo/Arrangement_on_surface_2/ArrangementDemoGraphicsView.cpp +++ b/Arrangement_on_surface_2/demo/Arrangement_on_surface_2/ArrangementDemoGraphicsView.cpp @@ -22,8 +22,8 @@ ArrangementDemoGraphicsView::ArrangementDemoGraphicsView( QWidget* parent ) : gridColor( ::Qt::black ), backgroundColor( ::Qt::white ) { - QMatrix m( 1.0, 0.0, 0.0, -1.0, 0.0, 0.0 ); - this->setMatrix( m ); + QTransform m( 1.0, 0.0, 0.0, -1.0, 0.0, 0.0 ); + this->setTransform( m ); this->setBackgroundBrush( QBrush( backgroundColor ) ); } From f221f4ba4a9febac54ea0b1e3a89991479a66e87 Mon Sep 17 00:00:00 2001 From: Maxime Gimeno Date: Fri, 19 Jun 2020 15:53:50 +0200 Subject: [PATCH 554/568] Try to add CGAL::CGAL_Image_IO to the linked target to fix LINK error on MSVC 2019 --- Mesh_3/examples/Mesh_3/CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Mesh_3/examples/Mesh_3/CMakeLists.txt b/Mesh_3/examples/Mesh_3/CMakeLists.txt index 88f738de714..155ac2b00bd 100644 --- a/Mesh_3/examples/Mesh_3/CMakeLists.txt +++ b/Mesh_3/examples/Mesh_3/CMakeLists.txt @@ -97,7 +97,7 @@ target_link_libraries(mesh_polyhedral_complex_sm PUBLIC CGAL::Eigen_support) if( TARGET CGAL::CGAL_ImageIO) if( VTK_FOUND AND ("${VTK_VERSION_MAJOR}" GREATER "5" OR VTK_VERSION VERSION_GREATER 5) ) add_executable ( mesh_3D_gray_vtk_image mesh_3D_gray_vtk_image.cpp ) - target_link_libraries( mesh_3D_gray_vtk_image PUBLIC CGAL::Eigen_support CGAL::CGAL ${CGAL_LIBRARIES} ${CGAL_3RD_PARTY_LIBRARIES} ${VTK_LIBRARIES}) + target_link_libraries( mesh_3D_gray_vtk_image PUBLIC CGAL::Eigen_support CGAL::CGAL CGAL::CGAL_ImageIO ${CGAL_LIBRARIES} ${CGAL_3RD_PARTY_LIBRARIES} ${VTK_LIBRARIES}) cgal_add_test( mesh_3D_gray_vtk_image ) add_to_cached_list( CGAL_EXECUTABLE_TARGETS mesh_3D_gray_vtk_image ) endif() From 50e2539bd7892a3ff1b9e603bb7e8f18ee789e9c Mon Sep 17 00:00:00 2001 From: Maxime Gimeno Date: Mon, 22 Jun 2020 13:44:37 +0200 Subject: [PATCH 555/568] Add CGAL:: before compare() to avoid miximg up the functions --- Distance_3/include/CGAL/squared_distance_3_1.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Distance_3/include/CGAL/squared_distance_3_1.h b/Distance_3/include/CGAL/squared_distance_3_1.h index b212b25fa40..cc72bdbb35c 100644 --- a/Distance_3/include/CGAL/squared_distance_3_1.h +++ b/Distance_3/include/CGAL/squared_distance_3_1.h @@ -226,7 +226,7 @@ compare_distance_pssC3( } } } - return compare(d1*e2, d2*e1); + return CGAL::compare(d1*e2, d2*e1); } template @@ -262,7 +262,7 @@ compare_distance_ppsC3( } } } - return compare(d1*e2, d2); + return CGAL::compare(d1*e2, d2); } From 4cca5b302563aab0cd546904be58ca78d59b0afd Mon Sep 17 00:00:00 2001 From: Laurent Rineau Date: Wed, 24 Jun 2020 11:56:43 +0200 Subject: [PATCH 556/568] Update .gitattributes Remove Pawn, C, and eC from languages detected in CGAL by Github (by linguist). --- .gitattributes | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/.gitattributes b/.gitattributes index ccb9bc4d4b5..8c7144a2f60 100644 --- a/.gitattributes +++ b/.gitattributes @@ -5,7 +5,7 @@ # to native line endings on checkout. *.cpp text *.c text -*.h text +*.h text linguist-language=C++ *.hpp text *.tex text *.txt text @@ -28,11 +28,12 @@ *.xyz text *.qhcp text *.qhp text -*.pwn text +*.pwn text linguist-detectable=false *.poly text *.rb text *.perl text *.pdb text +*.EH linguist-detectable=false # Declare files that will always have LF line endings on checkout. *.sh text eol=lf From e0330c14006a945ffa75823a37477f69b5792f18 Mon Sep 17 00:00:00 2001 From: Laurent Rineau Date: Wed, 24 Jun 2020 12:18:15 +0200 Subject: [PATCH 557/568] Declare Nef_3 data files --- .gitattributes | 3 +++ 1 file changed, 3 insertions(+) diff --git a/.gitattributes b/.gitattributes index 8c7144a2f60..38320ad4f0b 100644 --- a/.gitattributes +++ b/.gitattributes @@ -33,7 +33,10 @@ *.rb text *.perl text *.pdb text + +# Nef_3 data files *.EH linguist-detectable=false +*.SH linguist-detectable=false # Declare files that will always have LF line endings on checkout. *.sh text eol=lf From 1b25bd2c39eceba55cca03e5cd592d094fcc92ce Mon Sep 17 00:00:00 2001 From: Jane Tournois Date: Thu, 25 Jun 2020 08:19:12 +0200 Subject: [PATCH 558/568] add_to_complex(v1, v2) can be used only if edge is not already in the complex --- .../Tetrahedral_remeshing/internal/collapse_short_edges.h | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/collapse_short_edges.h b/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/collapse_short_edges.h index 9d96afb9c37..7ccc110d4fe 100644 --- a/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/collapse_short_edges.h +++ b/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/collapse_short_edges.h @@ -925,7 +925,8 @@ collapse(const typename C3t3::Cell_handle ch, { if (c3t3.is_in_complex(eiv0, eiv1)) { - c3t3.add_to_complex(eiv0, vkept, c3t3.curve_index(eiv0, eiv1)); + if (!c3t3.is_in_complex(eiv0, vkept)) + c3t3.add_to_complex(eiv0, vkept, c3t3.curve_index(eiv0, eiv1)); c3t3.remove_from_complex(eiv0, eiv1); } } @@ -933,7 +934,8 @@ collapse(const typename C3t3::Cell_handle ch, { if (c3t3.is_in_complex(eiv0, eiv1)) { - c3t3.add_to_complex(vkept, eiv1, c3t3.curve_index(eiv0, eiv1)); + if (!c3t3.is_in_complex(vkept, eiv1)) + c3t3.add_to_complex(vkept, eiv1, c3t3.curve_index(eiv0, eiv1)); c3t3.remove_from_complex(eiv0, eiv1); } } From c84e8cec425c74158b1d422cd246c9cc313f2d1d Mon Sep 17 00:00:00 2001 From: Jane Tournois Date: Thu, 25 Jun 2020 08:38:14 +0200 Subject: [PATCH 559/568] update number_of_facets and number_of_cells of the c3t3 before init_c3t3() --- .../internal/tetrahedral_adaptive_remeshing_impl.h | 3 +++ 1 file changed, 3 insertions(+) diff --git a/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/tetrahedral_adaptive_remeshing_impl.h b/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/tetrahedral_adaptive_remeshing_impl.h index dfe3ce5fa27..896f47fde9c 100644 --- a/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/tetrahedral_adaptive_remeshing_impl.h +++ b/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/tetrahedral_adaptive_remeshing_impl.h @@ -318,6 +318,9 @@ private: std::size_t nbe = 0; std::size_t nbv = 0; #endif + //update number_of_cells and number_of_facets in c3t3 + m_c3t3.rescan_after_load_of_triangulation(); + //tag cells for (Cell_handle cit : tr().finite_cell_handles()) { From f304886fee604ee34ca2412bdf4487c64bfe615b Mon Sep 17 00:00:00 2001 From: Jane Tournois Date: Thu, 25 Jun 2020 14:08:29 +0200 Subject: [PATCH 560/568] c3t3.rescan_after_load_of_triangulation() to count facets and cells and make counters valid --- .../demo/Polyhedron/Plugins/Mesh_3/C3t3_io_plugin.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Polyhedron/demo/Polyhedron/Plugins/Mesh_3/C3t3_io_plugin.cpp b/Polyhedron/demo/Polyhedron/Plugins/Mesh_3/C3t3_io_plugin.cpp index 8b708c059f2..95bf0246fe6 100644 --- a/Polyhedron/demo/Polyhedron/Plugins/Mesh_3/C3t3_io_plugin.cpp +++ b/Polyhedron/demo/Polyhedron/Plugins/Mesh_3/C3t3_io_plugin.cpp @@ -129,14 +129,14 @@ Polyhedron_demo_c3t3_binary_io_plugin::load( if(CGAL::build_triangulation_from_file(in, item->c3t3().triangulation())) { + item->c3t3().rescan_after_load_of_triangulation(); for( C3t3::Triangulation::Finite_cells_iterator cit = item->c3t3().triangulation().finite_cells_begin(); cit != item->c3t3().triangulation().finite_cells_end(); ++cit) { - CGAL_assertion(cit->info() >= 0); - if(cit->info() != 0) - item->c3t3().add_to_complex(cit, cit->info()); + if(cit->subdomain_index() != C3t3::Triangulation::Cell::Subdomain_index()) + item->c3t3().add_to_complex(cit, cit->subdomain_index()); for(int i=0; i < 4; ++i) { if(cit->surface_patch_index(i)>0) From dafb52f0fdea2853f7b99fc8415334255a8e156b Mon Sep 17 00:00:00 2001 From: Mael Date: Thu, 25 Jun 2020 16:42:23 +0200 Subject: [PATCH 561/568] Remove wrong 'const' marker in Polyhedron-modifying functions --- .../include/CGAL/boost/graph/graph_traits_Polyhedron_3.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Polyhedron/include/CGAL/boost/graph/graph_traits_Polyhedron_3.h b/Polyhedron/include/CGAL/boost/graph/graph_traits_Polyhedron_3.h index a6351f550de..bd025fcf17b 100644 --- a/Polyhedron/include/CGAL/boost/graph/graph_traits_Polyhedron_3.h +++ b/Polyhedron/include/CGAL/boost/graph/graph_traits_Polyhedron_3.h @@ -287,7 +287,7 @@ template void set_face(typename boost::graph_traits< CGAL::Polyhedron_3 >::halfedge_descriptor h , typename boost::graph_traits< CGAL::Polyhedron_3 >::face_descriptor f - , const CGAL::Polyhedron_3&) + , CGAL::Polyhedron_3&) { // set_face has become private in the halfedge provided by // polyhedron for unknown reasons, although it used to be public @@ -313,7 +313,7 @@ template void set_halfedge(typename boost::graph_traits< CGAL::Polyhedron_3 >::vertex_descriptor v , typename boost::graph_traits< CGAL::Polyhedron_3 >::halfedge_descriptor h - , const CGAL::Polyhedron_3&) + , CGAL::Polyhedron_3&) { typedef typename CGAL::Polyhedron_3::Vertex::Base Sneak; static_cast(*v).set_halfedge(h); From 5308db7bd810a513f56300088b6d774003869b72 Mon Sep 17 00:00:00 2001 From: Jane Tournois Date: Fri, 26 Jun 2020 06:39:15 +0200 Subject: [PATCH 562/568] fix the "peeling" of slivers when only one facet of the sliver was on a surface, it could happen that the 3 others where deeply traversing the volume, leading to a sharp hole on the surface. This should be fixed + add to the complex the new surface facets, after peeling --- .../tetrahedral_adaptive_remeshing_impl.h | 50 ++++++++++++++++++- 1 file changed, 48 insertions(+), 2 deletions(-) diff --git a/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/tetrahedral_adaptive_remeshing_impl.h b/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/tetrahedral_adaptive_remeshing_impl.h index 896f47fde9c..8197843eda7 100644 --- a/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/tetrahedral_adaptive_remeshing_impl.h +++ b/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/tetrahedral_adaptive_remeshing_impl.h @@ -272,19 +272,65 @@ public: #endif std::size_t nb_slivers_peel = 0; + std::vector > > peelable_cells; for (Cell_handle cit : tr().finite_cell_handles()) { + std::array facets_on_surface; + short count = 0; if(m_c3t3.is_in_complex(cit) && min_dihedral_angle(tr(), cit) < sliver_angle) { for (int i = 0; i < 4; ++i) { if (!m_c3t3.is_in_complex(cit->neighbor(i))) { - m_c3t3.remove_from_complex(cit); - ++nb_slivers_peel; + facets_on_surface[i] = true; + ++count; + } + else + facets_on_surface[i] = false; + } + if(count > 1) + peelable_cells.push_back(std::make_pair(cit, facets_on_surface)); + } + } + + for (auto c_i : peelable_cells) + { + Cell_handle c = c_i.first; + std::array f_on_surface = c_i.second; + + bool found = false; + Surface_patch_index patch; + for (int i = 0; i < 4; ++i) + { + if (f_on_surface[i]) + { + Surface_patch_index spi = m_c3t3.surface_patch_index(c, i); + if (found && patch != spi) + { + found = false; + break; + } + else + { + found = true; + patch = spi; } } } + if(!found) + continue; + + for (int i = 0; i < 4; ++i) + { + if(f_on_surface[i]) + m_c3t3.remove_from_complex(c, i); + else + m_c3t3.add_to_complex(c, i, patch); + } + + m_c3t3.remove_from_complex(c); + ++nb_slivers_peel; } CGAL_assertion(tr().tds().is_valid(true)); From bce4b4e80a93a50de9d00caeb409464fb657128f Mon Sep 17 00:00:00 2001 From: Jane Tournois Date: Fri, 26 Jun 2020 14:57:02 +0200 Subject: [PATCH 563/568] Revert "add an assertion in make_canonical" This reverts commit f55ffabbe082e11a979271ed28e2ffe2a4845de4. In the exuder, it can happen that this function takes the triple (Vertex_handle(), Vertex_handle(), Vertex_handle()) so the assertion does not hold --- Triangulation_3/include/CGAL/Triangulation_3.h | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/Triangulation_3/include/CGAL/Triangulation_3.h b/Triangulation_3/include/CGAL/Triangulation_3.h index a60b57f9676..20f76735e6b 100644 --- a/Triangulation_3/include/CGAL/Triangulation_3.h +++ b/Triangulation_3/include/CGAL/Triangulation_3.h @@ -4229,21 +4229,19 @@ make_canonical_oriented_triple(Vertex_triple& t) const Vertex_handle tmp; switch(i) { - case 0: break; + case 0: return; case 1: tmp = t.first; t.first = t.second; t.second = t.third; t.third = tmp; - break; + return; default: tmp = t.first; t.first = t.third; t.third = t.second; t.second = tmp; } - - CGAL_assertion(t.first < t.second && t.first < t.third); } template < class GT, class Tds, class Lds > From 615ac140866492397295c80bdfb66ac7bcbdeb0c Mon Sep 17 00:00:00 2001 From: Jane Tournois Date: Fri, 26 Jun 2020 15:51:15 +0200 Subject: [PATCH 564/568] protect incident_cells_threadsafe with macro Periodic_3_mesh_3 does not have an implementation of these functions because it does not have a parallel implementation --- Mesh_3/include/CGAL/Mesh_3/C3T3_helpers.h | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/Mesh_3/include/CGAL/Mesh_3/C3T3_helpers.h b/Mesh_3/include/CGAL/Mesh_3/C3T3_helpers.h index c642cb960ba..28cb28456f2 100644 --- a/Mesh_3/include/CGAL/Mesh_3/C3T3_helpers.h +++ b/Mesh_3/include/CGAL/Mesh_3/C3T3_helpers.h @@ -2942,7 +2942,11 @@ move_point(const Vertex_handle& old_vertex, Cell_vector incident_cells_; incident_cells_.reserve(64); +#ifdef CGAL_LINKED_WITH_TBB tr_.incident_cells_threadsafe(old_vertex, std::back_inserter(incident_cells_)); +#else + tr_.incident_cells(old_vertex, std::back_inserter(incident_cells_)); +#endif const Weighted_point& position = tr_.point(old_vertex); const Weighted_point& new_position = cwp(translate(cp(position), move)); @@ -3816,7 +3820,11 @@ get_conflict_zone_topo_change(const Vertex_handle& v, // Get triangulation_vertex incident cells : removal conflict zone // TODO: hasn't it already been computed in "perturb_vertex" (when getting the slivers)? // We don't try to lock the incident cells since they've already been locked +#ifdef CGAL_LINKED_WITH_TBB tr_.incident_cells_threadsafe(v, removal_conflict_cells); +#else + tr_.incident_cells(v, removal_conflict_cells); +#endif // Get conflict_point conflict zone int li=0; From 40668a297efabbfb29d5f98ea04c290f5a8b3ba8 Mon Sep 17 00:00:00 2001 From: Jane Tournois Date: Mon, 29 Jun 2020 07:07:13 +0200 Subject: [PATCH 565/568] fix protection of parallel code --- Mesh_3/include/CGAL/Mesh_3/C3T3_helpers.h | 36 ++++++++++++++++------- 1 file changed, 26 insertions(+), 10 deletions(-) diff --git a/Mesh_3/include/CGAL/Mesh_3/C3T3_helpers.h b/Mesh_3/include/CGAL/Mesh_3/C3T3_helpers.h index 28cb28456f2..ec092058b1d 100644 --- a/Mesh_3/include/CGAL/Mesh_3/C3T3_helpers.h +++ b/Mesh_3/include/CGAL/Mesh_3/C3T3_helpers.h @@ -2942,11 +2942,19 @@ move_point(const Vertex_handle& old_vertex, Cell_vector incident_cells_; incident_cells_.reserve(64); -#ifdef CGAL_LINKED_WITH_TBB - tr_.incident_cells_threadsafe(old_vertex, std::back_inserter(incident_cells_)); -#else - tr_.incident_cells(old_vertex, std::back_inserter(incident_cells_)); -#endif + +# ifdef CGAL_LINKED_WITH_TBB + // Parallel + if (boost::is_convertible::value) + { + tr_.incident_cells_threadsafe(old_vertex, std::back_inserter(incident_cells_)); + } + // Sequential + else +# endif // CGAL_LINKED_WITH_TBB + { + tr_.incident_cells(old_vertex, std::back_inserter(incident_cells_)); + } const Weighted_point& position = tr_.point(old_vertex); const Weighted_point& new_position = cwp(translate(cp(position), move)); @@ -3820,11 +3828,19 @@ get_conflict_zone_topo_change(const Vertex_handle& v, // Get triangulation_vertex incident cells : removal conflict zone // TODO: hasn't it already been computed in "perturb_vertex" (when getting the slivers)? // We don't try to lock the incident cells since they've already been locked -#ifdef CGAL_LINKED_WITH_TBB - tr_.incident_cells_threadsafe(v, removal_conflict_cells); -#else - tr_.incident_cells(v, removal_conflict_cells); -#endif + +# ifdef CGAL_LINKED_WITH_TBB +// Parallel + if (boost::is_convertible::value) + { + tr_.incident_cells_threadsafe(v, removal_conflict_cells); + } + // Sequential + else +# endif // CGAL_LINKED_WITH_TBB + { + tr_.incident_cells(v, removal_conflict_cells); + } // Get conflict_point conflict zone int li=0; From 9cfb0401a489b0f35f43a1416c96677e0d411c6c Mon Sep 17 00:00:00 2001 From: Laurent Rineau Date: Tue, 30 Jun 2020 17:18:05 +0200 Subject: [PATCH 566/568] updated crontab (automated commit) --- Maintenance/infrastructure/cgal.geometryfactory.com/crontab | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Maintenance/infrastructure/cgal.geometryfactory.com/crontab b/Maintenance/infrastructure/cgal.geometryfactory.com/crontab index 8de3a49b3ae..bc9df8cdfa9 100644 --- a/Maintenance/infrastructure/cgal.geometryfactory.com/crontab +++ b/Maintenance/infrastructure/cgal.geometryfactory.com/crontab @@ -25,11 +25,11 @@ LC_CTYPE=en_US.UTF-8 # "master" alone 0 21 * * Sun cd $HOME/CGAL/create_internal_release && /usr/bin/time scl enable rh-git29 -- $HOME/bin/create_release $HOME/CGAL/branches/master.git --do-it --beta 2 --public || echo ERROR # "integration" -0 21 * * Mon,Wed,Thu,Fri cd $HOME/CGAL/create_internal_release && /usr/bin/time scl enable rh-git29 -- $HOME/bin/create_release $HOME/CGAL/branches/integration.git $HOME/CGAL/branches/empty-dir --do-it --beta 2 --public || echo ERROR +0 21 * * Mon,Tue,Wed,Thu cd $HOME/CGAL/create_internal_release && /usr/bin/time scl enable rh-git29 -- $HOME/bin/create_release $HOME/CGAL/branches/integration.git $HOME/CGAL/branches/empty-dir --do-it --beta 2 --public || echo ERROR # from branch 5.0 0 21 * * Sat cd $HOME/CGAL/create_internal_release-5.0-branch && /usr/bin/time scl enable rh-git29 -- $HOME/bin/create_release $HOME/CGAL/branches/CGAL-5.0-branch.git --public --do-it || echo ERROR # from branch 4.14 -0 21 * * Tue cd $HOME/CGAL/create_internal_release-4.14-branch && /usr/bin/time scl enable rh-git29 -- $HOME/bin/create_release $HOME/CGAL/branches/CGAL-4.14-branch.git --public --do-it || echo ERROR +0 21 * * Fri cd $HOME/CGAL/create_internal_release-4.14-branch && /usr/bin/time scl enable rh-git29 -- $HOME/bin/create_release $HOME/CGAL/branches/CGAL-4.14-branch.git --public --do-it || echo ERROR ## Older stuff # from branch 4.13 From 80dd558884b23dbd1d2247a2d9036da9bce4a146 Mon Sep 17 00:00:00 2001 From: Laurent Rineau Date: Thu, 2 Jul 2020 15:50:49 +0200 Subject: [PATCH 567/568] Display the compiler version in test results I commit directly to `master`, because there is no way to test that in `integration`. --- Installation/cmake/modules/CGAL_Macros.cmake | 2 +- Maintenance/test_handling/create_testresult_page | 8 ++++++-- Maintenance/test_handling/to_zipped_format | 8 ++++---- 3 files changed, 11 insertions(+), 7 deletions(-) diff --git a/Installation/cmake/modules/CGAL_Macros.cmake b/Installation/cmake/modules/CGAL_Macros.cmake index cbd17669609..e113758a102 100644 --- a/Installation/cmake/modules/CGAL_Macros.cmake +++ b/Installation/cmake/modules/CGAL_Macros.cmake @@ -145,6 +145,7 @@ if( NOT CGAL_MACROS_FILE_INCLUDED ) message("Search dirs:") message("${search_dirs}") endif() + message( STATUS "USING COMPILER_VERSION = '${CMAKE_CXX_COMPILER_ID} ${CMAKE_CXX_COMPILER_VERSION}'" ) endfunction() macro( get_dependency_version LIB ) @@ -702,4 +703,3 @@ function(process_CGAL_subdirectory entry subdir type_name) message(STATUS "${subdir}/${ENTRY_DIR_NAME} is in dont_submit") endif() endfunction() - diff --git a/Maintenance/test_handling/create_testresult_page b/Maintenance/test_handling/create_testresult_page index ce38de030a9..d7e3890aa73 100755 --- a/Maintenance/test_handling/create_testresult_page +++ b/Maintenance/test_handling/create_testresult_page @@ -473,13 +473,16 @@ EOF $pf_no++; # my $pf_short = join('_',parse_platform_2($pf)); (my $pf_short) = ($pf =~ m/_(.*)/); - print OUTPUT "$pf_short"; + print OUTPUT "; # CGAL_VERSION - $_ = ; # TESTER + $_ = ; # COMPILER + chomp; + my $compiler = $_; + print OUTPUT " title=\"$compiler\">$pf_short"; $_ = ; # TESTER_NAME chomp; my $tester_name = $_; @@ -520,6 +523,7 @@ EOF } } } else { + print OUTPUT ">$pf_short"; my $index = 12; while ($index) { print OUTPUT "?\n"; diff --git a/Maintenance/test_handling/to_zipped_format b/Maintenance/test_handling/to_zipped_format index 94ee0fe2e11..3fca5787474 100755 --- a/Maintenance/test_handling/to_zipped_format +++ b/Maintenance/test_handling/to_zipped_format @@ -51,7 +51,7 @@ sub reformat_results($) $_ = $line; open (PLATFORM_INFO,">${platform}.info") or return; open (PLATFORM_NEW_RESULTS,">${platform}.new_results") or return; - my ($CGAL_VERSION,$LEDA_VERSION,$TESTER,$TESTER_NAME,$TESTER_ADDRESS,$GMP,$MPFR,$ZLIB,$OPENGL,$BOOST,$QT,$QT4,$QT5,$CMAKE) = ("-","-","-","-","-","-","-","-","-","-","-","-","-","-","-","no"); + my ($CGAL_VERSION,$LEDA_VERSION,$COMPILER,$TESTER_NAME,$TESTER_ADDRESS,$GMP,$MPFR,$ZLIB,$OPENGL,$BOOST,$QT,$QT4,$QT5,$CMAKE) = ("-","-","-","-","-","-","-","-","-","-","-","-","-","-","-","no"); my ($LDFLAGS,$CXXFLAGS) = ("", ""); while (! /^------/) { if(/^\s*$/) { @@ -69,8 +69,8 @@ sub reformat_results($) if (/LEDAWIN_VERSION = '([^']+)'/) { $LEDA_VERSION="$LEDA_VERSION+win"; } - if (/^TESTER\s+([\w\.-]+)/) { - $TESTER = $1; + if (/^COMPILER_VERSION = '([^']+)'/) { + $COMPILER = $1; } if (/^TESTER_NAME\s+(.*)$/) { $TESTER_NAME = $1; @@ -140,7 +140,7 @@ NEXT: if(! ($_= )) { rename("${platform}.new_results","${platform}.txt") or die "cannot rename!"; print PLATFORM_INFO <<"EOF"; $CGAL_VERSION -$TESTER +$COMPILER $TESTER_NAME $TESTER_ADDRESS $CMAKE From abd53906c5fe93aba0f0943054bbd8274d25c94d Mon Sep 17 00:00:00 2001 From: Laurent Rineau Date: Thu, 2 Jul 2020 15:51:29 +0200 Subject: [PATCH 568/568] Remove trailing whitespaces --- Installation/cmake/modules/CGAL_Macros.cmake | 2 +- .../test_handling/create_testresult_page | 36 +++++++++---------- 2 files changed, 19 insertions(+), 19 deletions(-) diff --git a/Installation/cmake/modules/CGAL_Macros.cmake b/Installation/cmake/modules/CGAL_Macros.cmake index e113758a102..2a937ee19e0 100644 --- a/Installation/cmake/modules/CGAL_Macros.cmake +++ b/Installation/cmake/modules/CGAL_Macros.cmake @@ -324,7 +324,7 @@ if( NOT CGAL_MACROS_FILE_INCLUDED ) endif() else() - if (NOT WITH_CGAL_${component}) + if (NOT WITH_CGAL_${component}) message(STATUS "NOTICE: The CGAL_${component} library seems to be required but is not build. Thus, it is expected that some executables will not be compiled.") endif() diff --git a/Maintenance/test_handling/create_testresult_page b/Maintenance/test_handling/create_testresult_page index d7e3890aa73..87b7eaf83ab 100755 --- a/Maintenance/test_handling/create_testresult_page +++ b/Maintenance/test_handling/create_testresult_page @@ -258,7 +258,7 @@ EOF print OUTPUT ' class="error"'; } elsif ($resulttext eq 'r') { print OUTPUT ' class="requirements"'; - } + } else { print OUTPUT ' class="na"'; } @@ -308,11 +308,11 @@ EOF sub sort_pf { # MSVS first - if($a =~ m/^MS/) { + if($a =~ m/^MS/) { if($b =~ m/^MS/) { return $a cmp $b; } - else + else { return -1; } @@ -320,11 +320,11 @@ sub sort_pf if($b =~ m/^MS/) { return 1; } # g++/gcc second - if($a =~ m/^g[c+][c+]/) { + if($a =~ m/^g[c+][c+]/) { if($b =~ m/^g[c+][c+]/) { return $a cmp $b; } - else + else { return -1; } @@ -332,11 +332,11 @@ sub sort_pf if($b =~ m/^g[c+][c+]/) { return 1; } # Intel third - if($a =~ m/^[iI]/) { + if($a =~ m/^[iI]/) { if($b =~ m/^[iI]/) { return $a cmp $b; } - else + else { return -1; } @@ -344,11 +344,11 @@ sub sort_pf if($b =~ m/^[iI]/) { return 1; } # SunPro last - if($a =~ m/^[Ss][uU[Nn]/) { + if($a =~ m/^[Ss][uU[Nn]/) { if($b =~ m/^[Ss][uU[Nn]/) { return $a cmp $b; } - else + else { return 1; } @@ -508,10 +508,10 @@ EOF chomp; print OUTPUT "\n"; print OUTPUT "$tester_name\n"; - print OUTPUT "$county\n"; - print OUTPUT "$countw\n"; - print OUTPUT "$countn\n"; - print OUTPUT "$countr\n"; + print OUTPUT "$county\n"; + print OUTPUT "$countw\n"; + print OUTPUT "$countn\n"; + print OUTPUT "$countr\n"; $index = 8; while ($index) { $index--; @@ -520,7 +520,7 @@ EOF print OUTPUT "$_\n"; } else { print OUTPUT "$_\n"; - } + } } } else { print OUTPUT ">$pf_short"; @@ -546,12 +546,12 @@ sub print_platforms_numbers() { $class = " class=\""; $tag = " ( "; - if($platform_is_64bits{$platform}) { - $class = "$class os64bits"; + if($platform_is_64bits{$platform}) { + $class = "$class os64bits"; $tag = $tag . "64 bits "; } - if($platform_is_optimized{$platform}) { - $class = "$class highlight"; + if($platform_is_optimized{$platform}) { + $class = "$class highlight"; $tag = $tag ." optimized: $platform_is_optimized{$platform}"; } $class = $class . "\"";