From 6a5dbdc333821ea379b3a5ed1c0802384f8ed8ee Mon Sep 17 00:00:00 2001 From: Clement Jamin Date: Mon, 24 Apr 2017 16:52:55 +0200 Subject: [PATCH 001/363] Add new variants of transformed_distance - Variant taking iterators on coordinates of P instead of P itself - Variant with an additional param `stop_if_geq_to_this`: during the computation, if the partially-computed distance `pcd` gets greater or equal to `stop_if_geq_to_this`, the computation is stopped and `pcd` is returned. --- .../include/CGAL/Euclidean_distance.h | 166 +++++++++++++----- 1 file changed, 125 insertions(+), 41 deletions(-) diff --git a/Spatial_searching/include/CGAL/Euclidean_distance.h b/Spatial_searching/include/CGAL/Euclidean_distance.h index 00e0ad8cfb7..0b362b3def1 100644 --- a/Spatial_searching/include/CGAL/Euclidean_distance.h +++ b/Spatial_searching/include/CGAL/Euclidean_distance.h @@ -57,60 +57,144 @@ namespace CGAL { // default constructor Euclidean_distance(const SearchTraits& traits_=SearchTraits()):traits(traits_) {} - - inline FT transformed_distance(const Query_item& q, const Point_d& p) const { - return transformed_distance(q,p, D()); + // During the computation, if the partially-computed distance `pcd` gets greater or equal + // to `stop_if_geq_to_this`, the computation is stopped and `pcd` is returned + inline FT transformed_distance(const Query_item& q, const Point_d& p, + FT stop_if_geq_to_this = std::numeric_limits::max()) const + { + typename SearchTraits::Construct_cartesian_const_iterator_d construct_it = traits.construct_cartesian_const_iterator_d_object(); + typename SearchTraits::Cartesian_const_iterator_d p_begin = construct_it(p), p_end = construct_it(p, 0); + return transformed_distance(q, p_begin, p_end, stop_if_geq_to_this); } - //Dynamic version for runtime dimension - inline FT transformed_distance(const Query_item& q, const Point_d& p, Dynamic_dimension_tag) const { - FT distance = FT(0); - typename SearchTraits::Construct_cartesian_const_iterator_d construct_it=traits.construct_cartesian_const_iterator_d_object(); - typename SearchTraits::Cartesian_const_iterator_d qit = construct_it(q), - qe = construct_it(q,1), pit = construct_it(p); - for(; qit != qe; qit++, pit++){ - distance += ((*qit)-(*pit))*((*qit)-(*pit)); - } - return distance; + // During the computation, if the partially-computed distance `pcd` gets greater or equal + // to `stop_if_geq_to_this`, the computation is stopped and `pcd` is returned + template + inline FT transformed_distance(const Query_item& q, + Coord_iterator it_coord_begin, Coord_iterator it_coord_end, + FT stop_if_geq_to_this = std::numeric_limits::max()) const + { + return transformed_distance(q, it_coord_begin, it_coord_end, stop_if_geq_to_this, D()); } - //Generic version for DIM > 3 - template < int DIM > - inline FT transformed_distance(const Query_item& q, const Point_d& p, Dimension_tag) const { - FT distance = FT(0); - typename SearchTraits::Construct_cartesian_const_iterator_d construct_it=traits.construct_cartesian_const_iterator_d_object(); - typename SearchTraits::Cartesian_const_iterator_d qit = construct_it(q), - qe = construct_it(q,1), pit = construct_it(p); - for(; qit != qe; qit++, pit++){ - distance += ((*qit)-(*pit))*((*qit)-(*pit)); + // Dynamic version for runtime dimension, taking iterators on coordinates as parameters + // During the computation, if the partially-computed distance `pcd` gets greater or equal + // to `stop_if_geq_to_this`, the computation is stopped and `pcd` is returned + template + inline FT transformed_distance(const Query_item& q, + Coord_iterator it_coord_begin, Coord_iterator it_coord_end, + FT stop_if_geq_to_this, Dynamic_dimension_tag) const + { + FT distance = FT(0); + typename SearchTraits::Construct_cartesian_const_iterator_d construct_it = traits.construct_cartesian_const_iterator_d_object(); + typename SearchTraits::Cartesian_const_iterator_d qit = construct_it(q), + qe = construct_it(q, 1); + if (qe - qit >= 4) + { + // Every 4 coordinates, the current partially-computed distance + // is compared to stop_if_geq_to_this + // Note: the concept SearchTraits specifies that Cartesian_const_iterator_d + // must be a random-access iterator + typename SearchTraits::Cartesian_const_iterator_d qe_minus_3 = qe - 3; + for (; qit < qe_minus_3; ++qit, ++it_coord_begin) { + FT diff = (*qit) - (*it_coord_begin); + distance += diff*diff; + ++qit; ++it_coord_begin; + diff = (*qit) - (*it_coord_begin); + distance += diff*diff; + ++qit; ++it_coord_begin; + diff = (*qit) - (*it_coord_begin); + distance += diff*diff; + + if (distance >= stop_if_geq_to_this) + return distance; + + ++qit; ++it_coord_begin; + diff = (*qit) - (*it_coord_begin); + distance += diff*diff; } - return distance; + } + for (; qit != qe; ++qit, ++it_coord_begin) + { + FT diff = (*qit) - (*it_coord_begin); + distance += diff*diff; + } + return distance; + } + + // Generic version for DIM > 3 taking iterators on coordinates as parameters + // During the computation, if the partially-computed distance `pcd` gets greater or equal + // to `stop_if_geq_to_this`, the computation is stopped and `pcd` is returned + template + inline FT transformed_distance(const Query_item& q, + Coord_iterator it_coord_begin, Coord_iterator it_coord_end, + FT stop_if_geq_to_this, Dimension_tag) const + { + FT distance = FT(0); + typename SearchTraits::Construct_cartesian_const_iterator_d construct_it = traits.construct_cartesian_const_iterator_d_object(); + typename SearchTraits::Cartesian_const_iterator_d qit = construct_it(q), + qe = construct_it(q, 1); + if (qe - qit >= 4) + { + // Every 4 coordinates, the current partially-computed distance + // is compared to stop_if_geq_to_this + // Note: the concept SearchTraits specifies that Cartesian_const_iterator_d + // must be a random-access iterator + typename SearchTraits::Cartesian_const_iterator_d qe_minus_3 = qe - 3; + for (; qit < qe_minus_3; ++qit, ++it_coord_begin) { + FT diff = (*qit) - (*it_coord_begin); + distance += diff*diff; + ++qit; ++it_coord_begin; + diff = (*qit) - (*it_coord_begin); + distance += diff*diff; + ++qit; ++it_coord_begin; + diff = (*qit) - (*it_coord_begin); + distance += diff*diff; + + if (distance >= stop_if_geq_to_this) + return distance; + + ++qit; ++it_coord_begin; + diff = (*qit) - (*it_coord_begin); + distance += diff*diff; + } + } + for (; qit != qe; ++qit, ++it_coord_begin) + { + FT diff = (*qit) - (*it_coord_begin); + distance += diff*diff; + } + return distance; } //DIM = 2 loop unrolled - inline FT transformed_distance(const Query_item& q, const Point_d& p, Dimension_tag<2> ) const { - typename SearchTraits::Construct_cartesian_const_iterator_d construct_it=traits.construct_cartesian_const_iterator_d_object(); - typename SearchTraits::Cartesian_const_iterator_d qit = construct_it(q),pit = construct_it(p); - FT distance = square(*qit - *pit); - qit++;pit++; - distance += square(*qit - *pit); - return distance; + template + inline FT transformed_distance(const Query_item& q, + Coord_iterator it_coord_begin, Coord_iterator /*unused*/, + FT /*unused*/, Dimension_tag<2>) const { + typename SearchTraits::Construct_cartesian_const_iterator_d construct_it = traits.construct_cartesian_const_iterator_d_object(); + typename SearchTraits::Cartesian_const_iterator_d qit = construct_it(q); + FT distance = square(*qit - *it_coord_begin); + qit++; it_coord_begin++; + distance += square(*qit - *it_coord_begin); + return distance; } //DIM = 3 loop unrolled - inline FT transformed_distance(const Query_item& q, const Point_d& p, Dimension_tag<3> ) const { - typename SearchTraits::Construct_cartesian_const_iterator_d construct_it=traits.construct_cartesian_const_iterator_d_object(); - typename SearchTraits::Cartesian_const_iterator_d qit = construct_it(q),pit = construct_it(p); - FT distance = square(*qit - *pit); - qit++;pit++; - distance += square(*qit - *pit); - qit++;pit++; - distance += square(*qit - *pit); - return distance; + template + inline FT transformed_distance(const Query_item& q, + Coord_iterator it_coord_begin, Coord_iterator /*unused*/, + FT /*unused*/, Dimension_tag<3>) const { + typename SearchTraits::Construct_cartesian_const_iterator_d construct_it = traits.construct_cartesian_const_iterator_d_object(); + typename SearchTraits::Cartesian_const_iterator_d qit = construct_it(q); + FT distance = square(*qit - *it_coord_begin); + qit++; it_coord_begin++; + distance += square(*qit - *it_coord_begin); + qit++; it_coord_begin++; + distance += square(*qit - *it_coord_begin); + return distance; } - - inline FT min_distance_to_rectangle(const Query_item& q, const Kd_tree_rectangle& r) const { From 7750f85867d9207d344291c6f26cc42e62fb5142 Mon Sep 17 00:00:00 2001 From: Clement Jamin Date: Mon, 24 Apr 2017 17:04:48 +0200 Subject: [PATCH 002/363] WIP: Use a cache storing contiguously the coordinates of all points Note: not backward-compatible, and not useful for all cases --- Spatial_searching/include/CGAL/Kd_tree.h | 15 +++++++ .../CGAL/Orthogonal_k_neighbor_search.h | 39 +++++++++++++------ .../include/CGAL/Search_traits_adapter.h | 10 ++++- 3 files changed, 50 insertions(+), 14 deletions(-) diff --git a/Spatial_searching/include/CGAL/Kd_tree.h b/Spatial_searching/include/CGAL/Kd_tree.h index 62e8faae346..5f566084e53 100644 --- a/Spatial_searching/include/CGAL/Kd_tree.h +++ b/Spatial_searching/include/CGAL/Kd_tree.h @@ -92,6 +92,10 @@ private: Kd_tree_rectangle* bbox; std::vector pts; + // Store a contiguous copy of the point coordinates + // for faster queries (reduce the number of cache misses) + std::vector points_cache; + // Instead of storing the points in arrays in the Kd_tree_node // we put all the data in a vector in the Kd_tree. // and we only store an iterator range in the Kd_tree_node. @@ -278,8 +282,12 @@ public: //Reorder vector for spatial locality std::vector ptstmp; ptstmp.resize(pts.size()); + points_cache.reserve(dim * pts.size()); for (std::size_t i = 0; i < pts.size(); ++i){ ptstmp[i] = *data[i]; + + typename SearchTraits::Construct_cartesian_const_iterator_d construct_it = traits_.construct_cartesian_const_iterator_d_object(); + points_cache.insert(points_cache.end(), construct_it(ptstmp[i]), construct_it(ptstmp[i], 0)); } for(std::size_t i = 0; i < leaf_nodes.size(); ++i){ std::ptrdiff_t tmp = leaf_nodes[i].begin() - pts.begin(); @@ -538,6 +546,13 @@ public: return *bbox; } + + typename std::vector::const_iterator + cache_begin() const + { + return points_cache.begin(); + } + const_iterator begin() const { diff --git a/Spatial_searching/include/CGAL/Orthogonal_k_neighbor_search.h b/Spatial_searching/include/CGAL/Orthogonal_k_neighbor_search.h index 308d2937247..139a560f312 100644 --- a/Spatial_searching/include/CGAL/Orthogonal_k_neighbor_search.h +++ b/Spatial_searching/include/CGAL/Orthogonal_k_neighbor_search.h @@ -35,23 +35,26 @@ class Orthogonal_k_neighbor_search: public internal::K_neighbor_search dists; + int m_dim; + Tree const& m_tree; + public: typedef typename Base::FT FT; Orthogonal_k_neighbor_search(const Tree& tree, const typename Base::Query_item& q, unsigned int k=1, FT Eps=FT(0.0), bool Search_nearest=true, const Distance& d=Distance(),bool sorted=true) - : Base(q,k,Eps,Search_nearest,d) + : Base(q,k,Eps,Search_nearest,d), m_tree(tree) { if (tree.empty()) return; typename SearchTraits::Construct_cartesian_const_iterator_d construct_it=tree.traits().construct_cartesian_const_iterator_d_object(); query_object_it = construct_it(this->query_object); - int dim = static_cast(std::distance(query_object_it, construct_it(this->query_object,0))); + m_dim = static_cast(std::distance(query_object_it, construct_it(this->query_object,0))); - dists.resize(dim); - for(int i=0;i(N); this->number_of_leaf_nodes_visited++; - bool full = this->queue.full(); - FT worst_dist = this->queue.top().second; + //bool full = this->queue.full(); if (node->size() > 0) { - for (typename Tree::iterator it=node->begin(); it != node->end(); it++) + std::vector::const_iterator cache_point_begin = m_tree.cache_begin() + m_dim*(node->begin() - m_tree.begin()); + for (typename Tree::iterator it = node->begin(); it != node->end(); it++) { this->number_of_items_visited++; - FT distance_to_query_object= - this->distance_instance.transformed_distance(this->query_object,*it); - - if(!full || distance_to_query_object < worst_dist) - this->queue.insert(std::make_pair(&(*it),distance_to_query_object)); + if (!this->queue.full()) + { + FT distance_to_query_object = + this->distance_instance.transformed_distance(this->query_object, cache_point_begin, cache_point_begin + m_dim); + this->queue.insert(std::make_pair(&(*it), distance_to_query_object)); + } + else + { + FT worst_dist = this->queue.top().second; + + FT distance_to_query_object = + this->distance_instance.transformed_distance(this->query_object, cache_point_begin, cache_point_begin + m_dim, worst_dist); + + if (distance_to_query_object < worst_dist) + this->queue.insert(std::make_pair(&(*it), distance_to_query_object)); + } + cache_point_begin += m_dim; } } } diff --git a/Spatial_searching/include/CGAL/Search_traits_adapter.h b/Spatial_searching/include/CGAL/Search_traits_adapter.h index 0a408e13f3f..54a12d32f49 100644 --- a/Spatial_searching/include/CGAL/Search_traits_adapter.h +++ b/Spatial_searching/include/CGAL/Search_traits_adapter.h @@ -148,9 +148,15 @@ public: const PointPropertyMap& point_property_map() const {return ppmap;} - FT transformed_distance(const Query_item& p1, const Point_with_info& p2) const + FT transformed_distance(const Query_item& p1, const Point_with_info& p2, FT worst_dist = std::numeric_limits::max()) const { - return Base_distance::transformed_distance(p1,get(ppmap,p2)); + return Base_distance::transformed_distance(p1,get(ppmap,p2), worst_dist); + } + + template < typename Coord_iterator > + FT transformed_distance(const Query_item& p1, Coord_iterator it_coord_begin, Coord_iterator it_coord_end, FT worst_dist = std::numeric_limits::max()) const + { + return Base_distance::transformed_distance(p1, it_coord_begin, it_coord_end, worst_dist); } template From 89c4e4a8b86d4e5cd988368395e0b7bd1249a817 Mon Sep 17 00:00:00 2001 From: Clement Jamin Date: Thu, 27 Apr 2017 10:15:36 +0200 Subject: [PATCH 003/363] Remove duplicated code --- .../include/CGAL/Euclidean_distance.h | 57 +++---------------- 1 file changed, 7 insertions(+), 50 deletions(-) diff --git a/Spatial_searching/include/CGAL/Euclidean_distance.h b/Spatial_searching/include/CGAL/Euclidean_distance.h index 0b362b3def1..d44ca264653 100644 --- a/Spatial_searching/include/CGAL/Euclidean_distance.h +++ b/Spatial_searching/include/CGAL/Euclidean_distance.h @@ -80,55 +80,10 @@ namespace CGAL { // Dynamic version for runtime dimension, taking iterators on coordinates as parameters // During the computation, if the partially-computed distance `pcd` gets greater or equal // to `stop_if_geq_to_this`, the computation is stopped and `pcd` is returned - template + template inline FT transformed_distance(const Query_item& q, - Coord_iterator it_coord_begin, Coord_iterator it_coord_end, - FT stop_if_geq_to_this, Dynamic_dimension_tag) const - { - FT distance = FT(0); - typename SearchTraits::Construct_cartesian_const_iterator_d construct_it = traits.construct_cartesian_const_iterator_d_object(); - typename SearchTraits::Cartesian_const_iterator_d qit = construct_it(q), - qe = construct_it(q, 1); - if (qe - qit >= 4) - { - // Every 4 coordinates, the current partially-computed distance - // is compared to stop_if_geq_to_this - // Note: the concept SearchTraits specifies that Cartesian_const_iterator_d - // must be a random-access iterator - typename SearchTraits::Cartesian_const_iterator_d qe_minus_3 = qe - 3; - for (; qit < qe_minus_3; ++qit, ++it_coord_begin) { - FT diff = (*qit) - (*it_coord_begin); - distance += diff*diff; - ++qit; ++it_coord_begin; - diff = (*qit) - (*it_coord_begin); - distance += diff*diff; - ++qit; ++it_coord_begin; - diff = (*qit) - (*it_coord_begin); - distance += diff*diff; - - if (distance >= stop_if_geq_to_this) - return distance; - - ++qit; ++it_coord_begin; - diff = (*qit) - (*it_coord_begin); - distance += diff*diff; - } - } - for (; qit != qe; ++qit, ++it_coord_begin) - { - FT diff = (*qit) - (*it_coord_begin); - distance += diff*diff; - } - return distance; - } - - // Generic version for DIM > 3 taking iterators on coordinates as parameters - // During the computation, if the partially-computed distance `pcd` gets greater or equal - // to `stop_if_geq_to_this`, the computation is stopped and `pcd` is returned - template - inline FT transformed_distance(const Query_item& q, - Coord_iterator it_coord_begin, Coord_iterator it_coord_end, - FT stop_if_geq_to_this, Dimension_tag) const + Coord_iterator it_coord_begin, Coord_iterator /*unused*/, + FT stop_if_geq_to_this, Dim) const { FT distance = FT(0); typename SearchTraits::Construct_cartesian_const_iterator_d construct_it = traits.construct_cartesian_const_iterator_d_object(); @@ -171,7 +126,8 @@ namespace CGAL { template inline FT transformed_distance(const Query_item& q, Coord_iterator it_coord_begin, Coord_iterator /*unused*/, - FT /*unused*/, Dimension_tag<2>) const { + FT /*unused*/, Dimension_tag<2>) const + { typename SearchTraits::Construct_cartesian_const_iterator_d construct_it = traits.construct_cartesian_const_iterator_d_object(); typename SearchTraits::Cartesian_const_iterator_d qit = construct_it(q); FT distance = square(*qit - *it_coord_begin); @@ -184,7 +140,8 @@ namespace CGAL { template inline FT transformed_distance(const Query_item& q, Coord_iterator it_coord_begin, Coord_iterator /*unused*/, - FT /*unused*/, Dimension_tag<3>) const { + FT /*unused*/, Dimension_tag<3>) const + { typename SearchTraits::Construct_cartesian_const_iterator_d construct_it = traits.construct_cartesian_const_iterator_d_object(); typename SearchTraits::Cartesian_const_iterator_d qit = construct_it(q); FT distance = square(*qit - *it_coord_begin); From 2548860ddb0fb9b23a20aa6737d4a0d000369e6f Mon Sep 17 00:00:00 2001 From: Clement Jamin Date: Wed, 3 May 2017 16:47:06 +0200 Subject: [PATCH 004/363] Introduce CGAL_GENERATE_MEMBER_DETECTOR macro --- STL_Extension/include/CGAL/Has_member.h | 43 +++++++++++++++++++++++++ 1 file changed, 43 insertions(+) create mode 100644 STL_Extension/include/CGAL/Has_member.h diff --git a/STL_Extension/include/CGAL/Has_member.h b/STL_Extension/include/CGAL/Has_member.h new file mode 100644 index 00000000000..f4d243fa8ad --- /dev/null +++ b/STL_Extension/include/CGAL/Has_member.h @@ -0,0 +1,43 @@ +// Copyright (c) 2017 Inria (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 Lesser 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. +// +// +// +// Author(s) : Clement Jamin + +#ifndef CGAL_HAS_MEMBER_H +#define CGAL_HAS_MEMBER_H + +// Macro used to check if a type T has a member named `X` +// It generates a class has_X where has_X::value is a boolean +// See example in Concurrent_compact_container.h +#define CGAL_GENERATE_MEMBER_DETECTOR(X) \ +template class has_##X { \ + struct Fallback { int X; }; \ + struct Derived : T, Fallback { }; \ + \ + template struct Check; \ + \ + typedef char ArrayOfOne[1]; \ + typedef char ArrayOfTwo[2]; \ + \ + template static ArrayOfOne & func( \ + Check *); \ + template static ArrayOfTwo & func(...); \ + public: \ + typedef has_##X type; \ + enum { value = sizeof(func(0)) == 2 }; \ +} // semicolon is after the macro call + +#endif // CGAL_HAS_MEMBER_H From e3d9db4b9422d60f1cbc49549398501e7d15e7e8 Mon Sep 17 00:00:00 2001 From: Clement Jamin Date: Wed, 3 May 2017 16:50:05 +0200 Subject: [PATCH 005/363] The macro has moved to Has_member.h --- .../CGAL/Concurrent_compact_container.h | 19 +------------------ 1 file changed, 1 insertion(+), 18 deletions(-) diff --git a/STL_Extension/include/CGAL/Concurrent_compact_container.h b/STL_Extension/include/CGAL/Concurrent_compact_container.h index 6f85eb09c00..d7cfaa6d222 100644 --- a/STL_Extension/include/CGAL/Concurrent_compact_container.h +++ b/STL_Extension/include/CGAL/Concurrent_compact_container.h @@ -33,6 +33,7 @@ #include #include #include +#include #include @@ -40,24 +41,6 @@ namespace CGAL { -#define CGAL_GENERATE_MEMBER_DETECTOR(X) \ -template class has_##X { \ - struct Fallback { int X; }; \ - struct Derived : T, Fallback { }; \ - \ - template struct Check; \ - \ - typedef char ArrayOfOne[1]; \ - typedef char ArrayOfTwo[2]; \ - \ - template static ArrayOfOne & func( \ - Check *); \ - template static ArrayOfTwo & func(...); \ - public: \ - typedef has_##X type; \ - enum { value = sizeof(func(0)) == 2 }; \ -} // semicolon is after the macro call - #define CGAL_INIT_CONCURRENT_COMPACT_CONTAINER_BLOCK_SIZE 14 #define CGAL_INCREMENT_CONCURRENT_COMPACT_CONTAINER_BLOCK_SIZE 16 From a6c1dfc7a1606eef642602b0ce93b0c52963a25d Mon Sep 17 00:00:00 2001 From: Clement Jamin Date: Tue, 9 May 2017 16:50:24 +0200 Subject: [PATCH 006/363] Rename the recently-added distance functions --- .../include/CGAL/Euclidean_distance.h | 20 +++++++++++++------ 1 file changed, 14 insertions(+), 6 deletions(-) diff --git a/Spatial_searching/include/CGAL/Euclidean_distance.h b/Spatial_searching/include/CGAL/Euclidean_distance.h index d44ca264653..d48c8930093 100644 --- a/Spatial_searching/include/CGAL/Euclidean_distance.h +++ b/Spatial_searching/include/CGAL/Euclidean_distance.h @@ -59,24 +59,32 @@ namespace CGAL { // During the computation, if the partially-computed distance `pcd` gets greater or equal // to `stop_if_geq_to_this`, the computation is stopped and `pcd` is returned - inline FT transformed_distance(const Query_item& q, const Point_d& p, - FT stop_if_geq_to_this = std::numeric_limits::max()) const + inline FT transformed_distance(const Query_item& q, const Point_d& p) const { typename SearchTraits::Construct_cartesian_const_iterator_d construct_it = traits.construct_cartesian_const_iterator_d_object(); typename SearchTraits::Cartesian_const_iterator_d p_begin = construct_it(p), p_end = construct_it(p, 0); - return transformed_distance(q, p_begin, p_end, stop_if_geq_to_this); + return transformed_distance_from_coordinates(q, p_begin, p_end); } // During the computation, if the partially-computed distance `pcd` gets greater or equal // to `stop_if_geq_to_this`, the computation is stopped and `pcd` is returned template - inline FT transformed_distance(const Query_item& q, + inline FT transformed_distance_from_coordinates(const Query_item& q, + Coord_iterator it_coord_begin, Coord_iterator it_coord_end) const + { + return transformed_distance(q, it_coord_begin, it_coord_end, std::numeric_limits::max(), D()); + } + + // During the computation, if the partially-computed distance `pcd` gets greater or equal + // to `stop_if_geq_to_this`, the computation is stopped and `pcd` is returned + template + inline FT interruptable_transformed_distance(const Query_item& q, Coord_iterator it_coord_begin, Coord_iterator it_coord_end, - FT stop_if_geq_to_this = std::numeric_limits::max()) const + FT stop_if_geq_to_this) const { return transformed_distance(q, it_coord_begin, it_coord_end, stop_if_geq_to_this, D()); } - + // Dynamic version for runtime dimension, taking iterators on coordinates as parameters // During the computation, if the partially-computed distance `pcd` gets greater or equal // to `stop_if_geq_to_this`, the computation is stopped and `pcd` is returned From 26ee6b1a1003eaa8ca8d6b574e92eb3588ccd7ae Mon Sep 17 00:00:00 2001 From: Clement Jamin Date: Tue, 9 May 2017 17:01:05 +0200 Subject: [PATCH 007/363] Auto-detect if the distance functor has some member functions: transformed_distance_from_coordinates interruptable_transformed_distance --- .../CGAL/Orthogonal_k_neighbor_search.h | 218 +++++++++++------- .../include/CGAL/Search_traits_adapter.h | 10 +- 2 files changed, 142 insertions(+), 86 deletions(-) diff --git a/Spatial_searching/include/CGAL/Orthogonal_k_neighbor_search.h b/Spatial_searching/include/CGAL/Orthogonal_k_neighbor_search.h index 139a560f312..06563a4855c 100644 --- a/Spatial_searching/include/CGAL/Orthogonal_k_neighbor_search.h +++ b/Spatial_searching/include/CGAL/Orthogonal_k_neighbor_search.h @@ -22,6 +22,7 @@ #define CGAL_ORTHOGONAL_K_NEIGHBOR_SEARCH_H #include +#include namespace CGAL { @@ -29,18 +30,74 @@ template ::type, class Splitter= Sliding_midpoint , class Tree= Kd_tree > -class Orthogonal_k_neighbor_search: public internal::K_neighbor_search { - typedef internal::K_neighbor_search Base; - - typename SearchTraits::Cartesian_const_iterator_d query_object_it; - - std::vector dists; - int m_dim; - Tree const& m_tree; +class Orthogonal_k_neighbor_search: public internal::K_neighbor_search +{ + typedef internal::K_neighbor_search Base; + typedef typename Tree::Point_d Point; public: typedef typename Base::FT FT; +private: + typename SearchTraits::Cartesian_const_iterator_d query_object_it; + + std::vector dists; + int m_dim; + Tree const& m_tree; + + CGAL_GENERATE_MEMBER_DETECTOR(transformed_distance_from_coordinates); + CGAL_GENERATE_MEMBER_DETECTOR(interruptable_transformed_distance); + + // If transformed_distance_from_coordinates does not exist in `Distance` + template ::value> + FT + transformed_distance_from_coordinates( + const typename Base::Query_item& q, + Point const& p, + typename std::vector::const_iterator it_coord_begin, + typename std::vector::const_iterator it_coord_end) + { + return this->distance_instance.transformed_distance(q, p); + } + // ... or if it exists + template <> + FT + transformed_distance_from_coordinates( + const typename Base::Query_item& q, + Point const& p, + typename std::vector::const_iterator it_coord_begin, + typename std::vector::const_iterator it_coord_end) + { + return this->distance_instance.transformed_distance_from_coordinates(q, it_coord_begin, it_coord_end); + } + + // If interruptable_transformed_distance does not exist in `Distance` + template ::value> + FT + interruptable_transformed_distance( + const typename Base::Query_item& q, + Point const& p, + typename std::vector::const_iterator it_coord_begin, + typename std::vector::const_iterator it_coord_end, + FT) + { + return transformed_distance_from_coordinates(q, p, it_coord_begin, it_coord_end); + } + // ... or if it exists + template <> + FT + interruptable_transformed_distance( + const typename Base::Query_item& q, + Point const& p, + typename std::vector::const_iterator it_coord_begin, + typename std::vector::const_iterator it_coord_end, + FT stop_if_geq_to_this) + { + return this->distance_instance.interruptable_transformed_distance( + q, it_coord_begin, it_coord_end, stop_if_geq_to_this); + } + +public: Orthogonal_k_neighbor_search(const Tree& tree, const typename Base::Query_item& q, unsigned int k=1, FT Eps=FT(0.0), bool Search_nearest=true, const Distance& d=Distance(),bool sorted=true) @@ -77,77 +134,99 @@ private: void compute_nearest_neighbors_orthogonally(typename Base::Node_const_handle N, FT rd) { - if (!(N->is_leaf())) - { - typename Tree::Internal_node_const_handle node = - static_cast(N); - this->number_of_internal_nodes_visited++; - int new_cut_dim=node->cutting_dimension(); - typename Base::Node_const_handle bestChild, otherChild; - FT new_off; - FT val = *(query_object_it + new_cut_dim); - FT diff1 = val - node->upper_low_value(); - FT diff2 = val - node->lower_high_value(); - if ( (diff1 + diff2 < FT(0.0)) ) - { - new_off = diff1; - bestChild = node->lower(); - otherChild = node->upper(); - } - else // compute new distance - { - new_off= diff2; - bestChild = node->upper(); - otherChild = node->lower(); - } - compute_nearest_neighbors_orthogonally(bestChild, rd); - FT dst=dists[new_cut_dim]; - FT new_rd = this->distance_instance.new_distance(rd,dst,new_off,new_cut_dim); - dists[new_cut_dim]=new_off; - if (this->branch_nearest(new_rd)) - { - compute_nearest_neighbors_orthogonally(otherChild, new_rd); - } - dists[new_cut_dim]=dst; - } - else + if (N->is_leaf()) { // n is a leaf typename Tree::Leaf_node_const_handle node = static_cast(N); this->number_of_leaf_nodes_visited++; - //bool full = this->queue.full(); if (node->size() > 0) { - std::vector::const_iterator cache_point_begin = m_tree.cache_begin() + m_dim*(node->begin() - m_tree.begin()); - for (typename Tree::iterator it = node->begin(); it != node->end(); it++) + typename Tree::iterator it_node_point = node->begin(), it_node_point_end = node->end(); + typename std::vector::const_iterator cache_point_begin = m_tree.cache_begin() + m_dim*(it_node_point - m_tree.begin()); + for (; !this->queue.full() && it_node_point != it_node_point_end; ++it_node_point) { this->number_of_items_visited++; - if (!this->queue.full()) - { - FT distance_to_query_object = - this->distance_instance.transformed_distance(this->query_object, cache_point_begin, cache_point_begin + m_dim); - this->queue.insert(std::make_pair(&(*it), distance_to_query_object)); - } - else - { - FT worst_dist = this->queue.top().second; + + FT distance_to_query_object = + transformed_distance_from_coordinates(this->query_object, *it_node_point, cache_point_begin, cache_point_begin + m_dim); + this->queue.insert(std::make_pair(&(*it_node_point), distance_to_query_object)); - FT distance_to_query_object = - this->distance_instance.transformed_distance(this->query_object, cache_point_begin, cache_point_begin + m_dim, worst_dist); + cache_point_begin += m_dim; + } + FT worst_dist = this->queue.top().second; + for (; it_node_point != it_node_point_end; ++it_node_point) + { + this->number_of_items_visited++; - if (distance_to_query_object < worst_dist) - this->queue.insert(std::make_pair(&(*it), distance_to_query_object)); + FT distance_to_query_object = + interruptable_transformed_distance(this->query_object, *it_node_point, cache_point_begin, cache_point_begin + m_dim, worst_dist); + + if (distance_to_query_object < worst_dist) + { + this->queue.insert(std::make_pair(&(*it_node_point), distance_to_query_object)); + worst_dist = this->queue.top().second; } + cache_point_begin += m_dim; } } } + else + { + typename Tree::Internal_node_const_handle node = + static_cast(N); + this->number_of_internal_nodes_visited++; + int new_cut_dim = node->cutting_dimension(); + typename Base::Node_const_handle bestChild, otherChild; + FT new_off; + FT val = *(query_object_it + new_cut_dim); + FT diff1 = val - node->upper_low_value(); + FT diff2 = val - node->lower_high_value(); + if ((diff1 + diff2 < FT(0.0))) + { + new_off = diff1; + bestChild = node->lower(); + otherChild = node->upper(); + } + else // compute new distance + { + new_off = diff2; + bestChild = node->upper(); + otherChild = node->lower(); + } + compute_nearest_neighbors_orthogonally(bestChild, rd); + FT dst = dists[new_cut_dim]; + FT new_rd = this->distance_instance.new_distance(rd, dst, new_off, new_cut_dim); + dists[new_cut_dim] = new_off; + if (this->branch_nearest(new_rd)) + { + compute_nearest_neighbors_orthogonally(otherChild, new_rd); + } + dists[new_cut_dim] = dst; + } } - void compute_furthest_neighbors_orthogonally(typename Base::Node_const_handle N, FT rd) + void compute_furthest_neighbors_orthogonally(typename Base::Node_const_handle N, FT rd) { - if (!(N->is_leaf())) + if (N->is_leaf()) + { + // n is a leaf + typename Tree::Leaf_node_const_handle node = + static_cast(N); + this->number_of_leaf_nodes_visited++; + if (node->size() > 0) + { + for (typename Tree::iterator it_node_point=node->begin(); it_node_point != node->end(); it_node_point++) + { + this->number_of_items_visited++; + FT distance_to_query_object= + this->distance_instance.transformed_distance(this->query_object,*it_node_point); + this->queue.insert(std::make_pair(&(*it_node_point),distance_to_query_object)); + } + } + } + else { typename Tree::Internal_node_const_handle node = static_cast(N); @@ -182,24 +261,7 @@ private: compute_furthest_neighbors_orthogonally(otherChild, new_rd); dists[new_cut_dim]=dst; } - else - { - // n is a leaf - typename Tree::Leaf_node_const_handle node = - static_cast(N); - this->number_of_leaf_nodes_visited++; - if (node->size() > 0) - { - for (typename Tree::iterator it=node->begin(); it != node->end(); it++) - { - this->number_of_items_visited++; - FT distance_to_query_object= - this->distance_instance.transformed_distance(this->query_object,*it); - this->queue.insert(std::make_pair(&(*it),distance_to_query_object)); - } - } - } - } + } }; // class diff --git a/Spatial_searching/include/CGAL/Search_traits_adapter.h b/Spatial_searching/include/CGAL/Search_traits_adapter.h index 54a12d32f49..0a408e13f3f 100644 --- a/Spatial_searching/include/CGAL/Search_traits_adapter.h +++ b/Spatial_searching/include/CGAL/Search_traits_adapter.h @@ -148,15 +148,9 @@ public: const PointPropertyMap& point_property_map() const {return ppmap;} - FT transformed_distance(const Query_item& p1, const Point_with_info& p2, FT worst_dist = std::numeric_limits::max()) const + FT transformed_distance(const Query_item& p1, const Point_with_info& p2) const { - return Base_distance::transformed_distance(p1,get(ppmap,p2), worst_dist); - } - - template < typename Coord_iterator > - FT transformed_distance(const Query_item& p1, Coord_iterator it_coord_begin, Coord_iterator it_coord_end, FT worst_dist = std::numeric_limits::max()) const - { - return Base_distance::transformed_distance(p1, it_coord_begin, it_coord_end, worst_dist); + return Base_distance::transformed_distance(p1,get(ppmap,p2)); } template From efce74597e9dee0b4b96585315840f6eb2ba94cd Mon Sep 17 00:00:00 2001 From: Clement Jamin Date: Thu, 18 May 2017 11:42:04 +0200 Subject: [PATCH 008/363] The macro has moved to Has_member.h --- .../include/CGAL/Compact_container.h | 19 +------------------ 1 file changed, 1 insertion(+), 18 deletions(-) diff --git a/STL_Extension/include/CGAL/Compact_container.h b/STL_Extension/include/CGAL/Compact_container.h index af65d886e3d..d9a9f5e8a18 100644 --- a/STL_Extension/include/CGAL/Compact_container.h +++ b/STL_Extension/include/CGAL/Compact_container.h @@ -35,6 +35,7 @@ #include #include #include +#include #include @@ -87,24 +88,6 @@ namespace CGAL { -#define CGAL_GENERATE_MEMBER_DETECTOR(X) \ -template class has_##X { \ - struct Fallback { int X; }; \ - struct Derived : T, Fallback { }; \ - \ - template struct Check; \ - \ - typedef char ArrayOfOne[1]; \ - typedef char ArrayOfTwo[2]; \ - \ - template static ArrayOfOne & func( \ - Check *); \ - template static ArrayOfTwo & func(...); \ - public: \ - typedef has_##X type; \ - enum { value = sizeof(func(0)) == 2 }; \ -} // semicolon is after the macro call - #define CGAL_INIT_COMPACT_CONTAINER_BLOCK_SIZE 14 #define CGAL_INCREMENT_COMPACT_CONTAINER_BLOCK_SIZE 16 From e9c35e3861048a3b3a54865b5a62e09a48e12654 Mon Sep 17 00:00:00 2001 From: Clement Jamin Date: Fri, 19 May 2017 16:06:02 +0200 Subject: [PATCH 009/363] Allow to enable/disable cache of points --- Spatial_searching/include/CGAL/Kd_tree.h | 29 ++-- Spatial_searching/include/CGAL/Kd_tree_node.h | 71 +++++----- .../CGAL/Orthogonal_k_neighbor_search.h | 129 +++++++++++++----- 3 files changed, 151 insertions(+), 78 deletions(-) diff --git a/Spatial_searching/include/CGAL/Kd_tree.h b/Spatial_searching/include/CGAL/Kd_tree.h index 5f566084e53..415994c0e2b 100644 --- a/Spatial_searching/include/CGAL/Kd_tree.h +++ b/Spatial_searching/include/CGAL/Kd_tree.h @@ -41,7 +41,11 @@ namespace CGAL { //template , class UseExtendedNode = Tag_true > -template , class UseExtendedNode = Tag_true > +template < + class SearchTraits, + class Splitter_=Sliding_midpoint, + class UseExtendedNode = Tag_true, + class EnablePointsCache = Tag_false> class Kd_tree { public: @@ -51,11 +55,11 @@ public: typedef typename Splitter::Container Point_container; typedef typename SearchTraits::FT FT; - typedef Kd_tree_node Node; - typedef Kd_tree_leaf_node Leaf_node; - typedef Kd_tree_internal_node Internal_node; - typedef Kd_tree Tree; - typedef Kd_tree Self; + typedef Kd_tree_node Node; + typedef Kd_tree_leaf_node Leaf_node; + typedef Kd_tree_internal_node Internal_node; + typedef Kd_tree Tree; + typedef Kd_tree Self; typedef Node* Node_handle; typedef const Node* Node_const_handle; @@ -73,6 +77,8 @@ public: typedef typename internal::Get_dimension_tag::Dimension D; + typedef EnablePointsCache Enable_points_cache; + private: SearchTraits traits_; Splitter split; @@ -282,13 +288,18 @@ public: //Reorder vector for spatial locality std::vector ptstmp; ptstmp.resize(pts.size()); - points_cache.reserve(dim * pts.size()); - for (std::size_t i = 0; i < pts.size(); ++i){ + for (std::size_t i = 0; i < pts.size(); ++i) ptstmp[i] = *data[i]; + // Cache? + if (Enable_points_cache::value) + { typename SearchTraits::Construct_cartesian_const_iterator_d construct_it = traits_.construct_cartesian_const_iterator_d_object(); - points_cache.insert(points_cache.end(), construct_it(ptstmp[i]), construct_it(ptstmp[i], 0)); + points_cache.reserve(dim * pts.size()); + for (std::size_t i = 0; i < pts.size(); ++i) + points_cache.insert(points_cache.end(), construct_it(ptstmp[i]), construct_it(ptstmp[i], 0)); } + for(std::size_t i = 0; i < leaf_nodes.size(); ++i){ std::ptrdiff_t tmp = leaf_nodes[i].begin() - pts.begin(); leaf_nodes[i].data = ptstmp.begin() + tmp; diff --git a/Spatial_searching/include/CGAL/Kd_tree_node.h b/Spatial_searching/include/CGAL/Kd_tree_node.h index c9d5e23478e..9cba8004006 100644 --- a/Spatial_searching/include/CGAL/Kd_tree_node.h +++ b/Spatial_searching/include/CGAL/Kd_tree_node.h @@ -28,27 +28,27 @@ namespace CGAL { - template + template class Kd_tree; - template < class TreeTraits, class Splitter, class UseExtendedNode > + template < class TreeTraits, class Splitter, class UseExtendedNode, class EnablePointsCache > class Kd_tree_node { - friend class Kd_tree; + friend class Kd_tree; - typedef typename Kd_tree::Node_handle Node_handle; - typedef typename Kd_tree::Node_const_handle Node_const_handle; - typedef typename Kd_tree::Internal_node_handle Internal_node_handle; - typedef typename Kd_tree::Internal_node_const_handle Internal_node_const_handle; - typedef typename Kd_tree::Leaf_node_handle Leaf_node_handle; - typedef typename Kd_tree::Leaf_node_const_handle Leaf_node_const_handle; + typedef typename Kd_tree::Node_handle Node_handle; + typedef typename Kd_tree::Node_const_handle Node_const_handle; + typedef typename Kd_tree::Internal_node_handle Internal_node_handle; + typedef typename Kd_tree::Internal_node_const_handle Internal_node_const_handle; + typedef typename Kd_tree::Leaf_node_handle Leaf_node_handle; + typedef typename Kd_tree::Leaf_node_const_handle Leaf_node_const_handle; typedef typename TreeTraits::Point_d Point_d; typedef typename TreeTraits::FT FT; - typedef typename Kd_tree::Separator Separator; - typedef typename Kd_tree::Point_d_iterator Point_d_iterator; - typedef typename Kd_tree::iterator iterator; - typedef typename Kd_tree::D D; + typedef typename Kd_tree::Separator Separator; + typedef typename Kd_tree::Point_d_iterator Point_d_iterator; + typedef typename Kd_tree::iterator iterator; + typedef typename Kd_tree::D D; bool leaf; @@ -264,13 +264,13 @@ namespace CGAL { }; - template < class TreeTraits, class Splitter, class UseExtendedNode > - class Kd_tree_leaf_node : public Kd_tree_node< TreeTraits, Splitter, UseExtendedNode >{ + template < class TreeTraits, class Splitter, class UseExtendedNode, class EnablePointsCache > + class Kd_tree_leaf_node : public Kd_tree_node< TreeTraits, Splitter, UseExtendedNode, EnablePointsCache >{ - friend class Kd_tree; + friend class Kd_tree; - typedef typename Kd_tree::iterator iterator; - typedef Kd_tree_node< TreeTraits, Splitter, UseExtendedNode> Base; + typedef typename Kd_tree::iterator iterator; + typedef Kd_tree_node< TreeTraits, Splitter, UseExtendedNode, EnablePointsCache> Base; typedef typename TreeTraits::Point_d Point_d; private: @@ -329,18 +329,18 @@ namespace CGAL { - template < class TreeTraits, class Splitter, class UseExtendedNode> - class Kd_tree_internal_node : public Kd_tree_node< TreeTraits, Splitter, UseExtendedNode >{ + template < class TreeTraits, class Splitter, class UseExtendedNode, class EnablePointsCache> + class Kd_tree_internal_node : public Kd_tree_node< TreeTraits, Splitter, UseExtendedNode, EnablePointsCache >{ - friend class Kd_tree; + friend class Kd_tree; - typedef Kd_tree_node< TreeTraits, Splitter, UseExtendedNode> Base; - typedef typename Kd_tree::Node_handle Node_handle; - typedef typename Kd_tree::Node_const_handle Node_const_handle; + typedef Kd_tree_node< TreeTraits, Splitter, UseExtendedNode, EnablePointsCache> Base; + typedef typename Kd_tree::Node_handle Node_handle; + typedef typename Kd_tree::Node_const_handle Node_const_handle; typedef typename TreeTraits::FT FT; - typedef typename Kd_tree::Separator Separator; - typedef typename Kd_tree::D D; + typedef typename Kd_tree::Separator Separator; + typedef typename Kd_tree::D D; private: @@ -477,18 +477,19 @@ namespace CGAL { } };//internal node - template < class TreeTraits, class Splitter> - class Kd_tree_internal_node : public Kd_tree_node< TreeTraits, Splitter, Tag_false >{ + template < class TreeTraits, class Splitter, class EnablePointsCache> + class Kd_tree_internal_node + : public Kd_tree_node< TreeTraits, Splitter, Tag_false, EnablePointsCache > + { + friend class Kd_tree; - friend class Kd_tree; - - typedef Kd_tree_node< TreeTraits, Splitter, Tag_false> Base; - typedef typename Kd_tree::Node_handle Node_handle; - typedef typename Kd_tree::Node_const_handle Node_const_handle; + typedef Kd_tree_node< TreeTraits, Splitter, Tag_false, EnablePointsCache> Base; + typedef typename Kd_tree::Node_handle Node_handle; + typedef typename Kd_tree::Node_const_handle Node_const_handle; typedef typename TreeTraits::FT FT; - typedef typename Kd_tree::Separator Separator; - typedef typename Kd_tree::D D; + typedef typename Kd_tree::Separator Separator; + typedef typename Kd_tree::D D; private: diff --git a/Spatial_searching/include/CGAL/Orthogonal_k_neighbor_search.h b/Spatial_searching/include/CGAL/Orthogonal_k_neighbor_search.h index 06563a4855c..da3cce984a3 100644 --- a/Spatial_searching/include/CGAL/Orthogonal_k_neighbor_search.h +++ b/Spatial_searching/include/CGAL/Orthogonal_k_neighbor_search.h @@ -24,6 +24,8 @@ #include #include +#include + namespace CGAL { template ::value> @@ -71,6 +74,7 @@ private: return this->distance_instance.transformed_distance_from_coordinates(q, it_coord_begin, it_coord_end); } + // *** Version with cache *** // If interruptable_transformed_distance does not exist in `Distance` template ::value> FT @@ -97,6 +101,30 @@ private: q, it_coord_begin, it_coord_end, stop_if_geq_to_this); } + // *** Version without cache *** + // If interruptable_transformed_distance does not exist in `Distance` + template ::value> + FT + interruptable_transformed_distance( + const typename Base::Query_item& q, + Point const& p, + FT) + { + return this->distance_instance.transformed_distance(q, p); + } + // ... or if it exists + template <> + FT + interruptable_transformed_distance( + const typename Base::Query_item& q, + Point const& p, + FT stop_if_geq_to_this) + { + typename SearchTraits::Construct_cartesian_const_iterator_d construct_it = m_tree.traits().construct_cartesian_const_iterator_d_object(); + return this->distance_instance.interruptable_transformed_distance( + q, construct_it(p), construct_it(p, 0), stop_if_geq_to_this); + } + public: Orthogonal_k_neighbor_search(const Tree& tree, const typename Base::Query_item& q, @@ -124,14 +152,76 @@ public: compute_furthest_neighbors_orthogonally(tree.root(), distance_to_root); } - - - - if (sorted) this->queue.sort(); } private: + template::value && Tree::Enable_points_cache::value)> + void search_in_leaf(typename Tree::Leaf_node_const_handle node); + + // With cache + template<> + void search_in_leaf(typename Tree::Leaf_node_const_handle node) + { + typename Tree::iterator it_node_point = node->begin(), it_node_point_end = node->end(); + typename std::vector::const_iterator cache_point_begin = m_tree.cache_begin() + m_dim*(it_node_point - m_tree.begin()); + for (; !this->queue.full() && it_node_point != it_node_point_end; ++it_node_point) + { + this->number_of_items_visited++; + + FT distance_to_query_object = + transformed_distance_from_coordinates(this->query_object, *it_node_point, cache_point_begin, cache_point_begin + m_dim); + this->queue.insert(std::make_pair(&(*it_node_point), distance_to_query_object)); + + cache_point_begin += m_dim; + } + FT worst_dist = this->queue.top().second; + for (; it_node_point != it_node_point_end; ++it_node_point) + { + this->number_of_items_visited++; + + FT distance_to_query_object = + interruptable_transformed_distance(this->query_object, *it_node_point, cache_point_begin, cache_point_begin + m_dim, worst_dist); + + if (distance_to_query_object < worst_dist) + { + this->queue.insert(std::make_pair(&(*it_node_point), distance_to_query_object)); + worst_dist = this->queue.top().second; + } + + cache_point_begin += m_dim; + } + } + + // Without cache + template<> + void search_in_leaf(typename Tree::Leaf_node_const_handle node) + { + typename Tree::iterator it_node_point = node->begin(), it_node_point_end = node->end(); + for (; !this->queue.full() && it_node_point != it_node_point_end; ++it_node_point) + { + this->number_of_items_visited++; + + FT distance_to_query_object = + this->distance_instance.transformed_distance(this->query_object, *it_node_point); + this->queue.insert(std::make_pair(&(*it_node_point), distance_to_query_object)); + } + FT worst_dist = this->queue.top().second; + for (; it_node_point != it_node_point_end; ++it_node_point) + { + this->number_of_items_visited++; + + FT distance_to_query_object = + interruptable_transformed_distance(this->query_object, *it_node_point, worst_dist); + + if (distance_to_query_object < worst_dist) + { + this->queue.insert(std::make_pair(&(*it_node_point), distance_to_query_object)); + worst_dist = this->queue.top().second; + } + } + } + void compute_nearest_neighbors_orthogonally(typename Base::Node_const_handle N, FT rd) { if (N->is_leaf()) @@ -141,36 +231,7 @@ private: static_cast(N); this->number_of_leaf_nodes_visited++; if (node->size() > 0) - { - typename Tree::iterator it_node_point = node->begin(), it_node_point_end = node->end(); - typename std::vector::const_iterator cache_point_begin = m_tree.cache_begin() + m_dim*(it_node_point - m_tree.begin()); - for (; !this->queue.full() && it_node_point != it_node_point_end; ++it_node_point) - { - this->number_of_items_visited++; - - FT distance_to_query_object = - transformed_distance_from_coordinates(this->query_object, *it_node_point, cache_point_begin, cache_point_begin + m_dim); - this->queue.insert(std::make_pair(&(*it_node_point), distance_to_query_object)); - - cache_point_begin += m_dim; - } - FT worst_dist = this->queue.top().second; - for (; it_node_point != it_node_point_end; ++it_node_point) - { - this->number_of_items_visited++; - - FT distance_to_query_object = - interruptable_transformed_distance(this->query_object, *it_node_point, cache_point_begin, cache_point_begin + m_dim, worst_dist); - - if (distance_to_query_object < worst_dist) - { - this->queue.insert(std::make_pair(&(*it_node_point), distance_to_query_object)); - worst_dist = this->queue.top().second; - } - - cache_point_begin += m_dim; - } - } + search_in_leaf(node); } else { From 5e662a03db9a368d5f87108b68045a0520443928 Mon Sep 17 00:00:00 2001 From: Clement Jamin Date: Mon, 22 May 2017 16:23:58 +0200 Subject: [PATCH 010/363] Fix the way we detect the cache --- .../CGAL/Orthogonal_k_neighbor_search.h | 19 +++++++++++++++++-- 1 file changed, 17 insertions(+), 2 deletions(-) diff --git a/Spatial_searching/include/CGAL/Orthogonal_k_neighbor_search.h b/Spatial_searching/include/CGAL/Orthogonal_k_neighbor_search.h index da3cce984a3..dfd48ecd639 100644 --- a/Spatial_searching/include/CGAL/Orthogonal_k_neighbor_search.h +++ b/Spatial_searching/include/CGAL/Orthogonal_k_neighbor_search.h @@ -28,6 +28,21 @@ namespace CGAL { +template +struct Has_points_cache; + +template +struct Has_points_cache +{ + static const bool value = Tree::Enable_points_cache::value; +}; + +template +struct Has_points_cache +{ + static const bool value = false; +}; + template ::type, class Splitter= Sliding_midpoint , @@ -156,7 +171,7 @@ public: } private: - template::value && Tree::Enable_points_cache::value)> + template void search_in_leaf(typename Tree::Leaf_node_const_handle node); // With cache @@ -231,7 +246,7 @@ private: static_cast(N); this->number_of_leaf_nodes_visited++; if (node->size() > 0) - search_in_leaf(node); + search_in_leaf::type::value>::value>(node); } else { From 069ab04c7ec0904c55a585c41166dc2aaa6cf31f Mon Sep 17 00:00:00 2001 From: Clement Jamin Date: Mon, 22 May 2017 16:42:07 +0200 Subject: [PATCH 011/363] Add comment --- Spatial_searching/include/CGAL/Orthogonal_k_neighbor_search.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Spatial_searching/include/CGAL/Orthogonal_k_neighbor_search.h b/Spatial_searching/include/CGAL/Orthogonal_k_neighbor_search.h index dfd48ecd639..0142e568fa2 100644 --- a/Spatial_searching/include/CGAL/Orthogonal_k_neighbor_search.h +++ b/Spatial_searching/include/CGAL/Orthogonal_k_neighbor_search.h @@ -28,6 +28,8 @@ namespace CGAL { +// Helper struct to know at compile-time if there is a cache of the points +// stored in the tree template struct Has_points_cache; From ce60cf420fc9faabf53dc8abb6154d69af28a352 Mon Sep 17 00:00:00 2001 From: Clement Jamin Date: Tue, 6 Jun 2017 11:42:24 +0200 Subject: [PATCH 012/363] Add a comment about BOOST_TTI_HAS_MEMBER_FUNCTION --- STL_Extension/include/CGAL/Has_member.h | 3 +++ 1 file changed, 3 insertions(+) diff --git a/STL_Extension/include/CGAL/Has_member.h b/STL_Extension/include/CGAL/Has_member.h index f4d243fa8ad..79cf5a31b35 100644 --- a/STL_Extension/include/CGAL/Has_member.h +++ b/STL_Extension/include/CGAL/Has_member.h @@ -22,6 +22,9 @@ // Macro used to check if a type T has a member named `X` // It generates a class has_X where has_X::value is a boolean // See example in Concurrent_compact_container.h +// Note: this macro is similar to BOOST_TTI_HAS_MEMBER_FUNCTION +// which was introduced in Boost 1.54 (CGAL supports version 1.48 and +// later at this time - June 2017) #define CGAL_GENERATE_MEMBER_DETECTOR(X) \ template class has_##X { \ struct Fallback { int X; }; \ From a8012211933ad6a962ca1d0a95a1a828f52ca942 Mon Sep 17 00:00:00 2001 From: Clement Jamin Date: Tue, 13 Jun 2017 17:07:20 +0200 Subject: [PATCH 013/363] Remove the use of numeric_limits + fix typo + better interruptible version --- .../include/CGAL/Euclidean_distance.h | 46 +++++++++++++------ .../CGAL/Orthogonal_k_neighbor_search.h | 26 +++++------ 2 files changed, 44 insertions(+), 28 deletions(-) diff --git a/Spatial_searching/include/CGAL/Euclidean_distance.h b/Spatial_searching/include/CGAL/Euclidean_distance.h index d48c8930093..a14cab203be 100644 --- a/Spatial_searching/include/CGAL/Euclidean_distance.h +++ b/Spatial_searching/include/CGAL/Euclidean_distance.h @@ -57,8 +57,6 @@ namespace CGAL { // default constructor Euclidean_distance(const SearchTraits& traits_=SearchTraits()):traits(traits_) {} - // During the computation, if the partially-computed distance `pcd` gets greater or equal - // to `stop_if_geq_to_this`, the computation is stopped and `pcd` is returned inline FT transformed_distance(const Query_item& q, const Point_d& p) const { typename SearchTraits::Construct_cartesian_const_iterator_d construct_it = traits.construct_cartesian_const_iterator_d_object(); @@ -66,25 +64,40 @@ namespace CGAL { return transformed_distance_from_coordinates(q, p_begin, p_end); } - // During the computation, if the partially-computed distance `pcd` gets greater or equal - // to `stop_if_geq_to_this`, the computation is stopped and `pcd` is returned template inline FT transformed_distance_from_coordinates(const Query_item& q, Coord_iterator it_coord_begin, Coord_iterator it_coord_end) const { - return transformed_distance(q, it_coord_begin, it_coord_end, std::numeric_limits::max(), D()); + return transformed_distance(q, it_coord_begin, it_coord_end, D()); } // During the computation, if the partially-computed distance `pcd` gets greater or equal // to `stop_if_geq_to_this`, the computation is stopped and `pcd` is returned template - inline FT interruptable_transformed_distance(const Query_item& q, + inline FT interruptible_transformed_distance(const Query_item& q, Coord_iterator it_coord_begin, Coord_iterator it_coord_end, FT stop_if_geq_to_this) const { return transformed_distance(q, it_coord_begin, it_coord_end, stop_if_geq_to_this, D()); } - + + // Dynamic version for runtime dimension, taking iterators on coordinates as parameters + template + inline FT transformed_distance(const Query_item& q, + Coord_iterator it_coord_begin, Coord_iterator /*unused*/, + Dim) const + { + FT distance = FT(0); + typename SearchTraits::Construct_cartesian_const_iterator_d construct_it = traits.construct_cartesian_const_iterator_d_object(); + typename SearchTraits::Cartesian_const_iterator_d qit = construct_it(q), qe = construct_it(q, 1); + for (; qit != qe; ++qit, ++it_coord_begin) + { + FT diff = (*qit) - (*it_coord_begin); + distance += diff*diff; + } + return distance; + } + // Dynamic version for runtime dimension, taking iterators on coordinates as parameters // During the computation, if the partially-computed distance `pcd` gets greater or equal // to `stop_if_geq_to_this`, the computation is stopped and `pcd` is returned @@ -95,16 +108,16 @@ namespace CGAL { { FT distance = FT(0); typename SearchTraits::Construct_cartesian_const_iterator_d construct_it = traits.construct_cartesian_const_iterator_d_object(); - typename SearchTraits::Cartesian_const_iterator_d qit = construct_it(q), - qe = construct_it(q, 1); - if (qe - qit >= 4) + typename SearchTraits::Cartesian_const_iterator_d qit = construct_it(q), qe = construct_it(q, 1); + if (qe - qit >= 6) { // Every 4 coordinates, the current partially-computed distance // is compared to stop_if_geq_to_this // Note: the concept SearchTraits specifies that Cartesian_const_iterator_d // must be a random-access iterator - typename SearchTraits::Cartesian_const_iterator_d qe_minus_3 = qe - 3; - for (; qit < qe_minus_3; ++qit, ++it_coord_begin) { + typename SearchTraits::Cartesian_const_iterator_d qe_minus_5 = qe - 5; + for (;;) + { FT diff = (*qit) - (*it_coord_begin); distance += diff*diff; ++qit; ++it_coord_begin; @@ -113,13 +126,16 @@ namespace CGAL { ++qit; ++it_coord_begin; diff = (*qit) - (*it_coord_begin); distance += diff*diff; + ++qit; ++it_coord_begin; + diff = (*qit) - (*it_coord_begin); + distance += diff*diff; + ++qit, ++it_coord_begin; if (distance >= stop_if_geq_to_this) return distance; - ++qit; ++it_coord_begin; - diff = (*qit) - (*it_coord_begin); - distance += diff*diff; + if (qit >= qe_minus_5) + break; } } for (; qit != qe; ++qit, ++it_coord_begin) diff --git a/Spatial_searching/include/CGAL/Orthogonal_k_neighbor_search.h b/Spatial_searching/include/CGAL/Orthogonal_k_neighbor_search.h index 0142e568fa2..9f1baae4c40 100644 --- a/Spatial_searching/include/CGAL/Orthogonal_k_neighbor_search.h +++ b/Spatial_searching/include/CGAL/Orthogonal_k_neighbor_search.h @@ -65,7 +65,7 @@ private: Tree const& m_tree; CGAL_GENERATE_MEMBER_DETECTOR(transformed_distance_from_coordinates); - CGAL_GENERATE_MEMBER_DETECTOR(interruptable_transformed_distance); + CGAL_GENERATE_MEMBER_DETECTOR(interruptible_transformed_distance); BOOST_MPL_HAS_XXX_TRAIT_NAMED_DEF(has_Enable_points_cache, Enable_points_cache, false) // If transformed_distance_from_coordinates does not exist in `Distance` @@ -92,10 +92,10 @@ private: } // *** Version with cache *** - // If interruptable_transformed_distance does not exist in `Distance` - template ::value> + // If interruptible_transformed_distance does not exist in `Distance` + template ::value> FT - interruptable_transformed_distance( + interruptible_transformed_distance( const typename Base::Query_item& q, Point const& p, typename std::vector::const_iterator it_coord_begin, @@ -107,22 +107,22 @@ private: // ... or if it exists template <> FT - interruptable_transformed_distance( + interruptible_transformed_distance( const typename Base::Query_item& q, Point const& p, typename std::vector::const_iterator it_coord_begin, typename std::vector::const_iterator it_coord_end, FT stop_if_geq_to_this) { - return this->distance_instance.interruptable_transformed_distance( + return this->distance_instance.interruptible_transformed_distance( q, it_coord_begin, it_coord_end, stop_if_geq_to_this); } // *** Version without cache *** - // If interruptable_transformed_distance does not exist in `Distance` - template ::value> + // If interruptible_transformed_distance does not exist in `Distance` + template ::value> FT - interruptable_transformed_distance( + interruptible_transformed_distance( const typename Base::Query_item& q, Point const& p, FT) @@ -132,13 +132,13 @@ private: // ... or if it exists template <> FT - interruptable_transformed_distance( + interruptible_transformed_distance( const typename Base::Query_item& q, Point const& p, FT stop_if_geq_to_this) { typename SearchTraits::Construct_cartesian_const_iterator_d construct_it = m_tree.traits().construct_cartesian_const_iterator_d_object(); - return this->distance_instance.interruptable_transformed_distance( + return this->distance_instance.interruptible_transformed_distance( q, construct_it(p), construct_it(p, 0), stop_if_geq_to_this); } @@ -198,7 +198,7 @@ private: this->number_of_items_visited++; FT distance_to_query_object = - interruptable_transformed_distance(this->query_object, *it_node_point, cache_point_begin, cache_point_begin + m_dim, worst_dist); + interruptible_transformed_distance(this->query_object, *it_node_point, cache_point_begin, cache_point_begin + m_dim, worst_dist); if (distance_to_query_object < worst_dist) { @@ -229,7 +229,7 @@ private: this->number_of_items_visited++; FT distance_to_query_object = - interruptable_transformed_distance(this->query_object, *it_node_point, worst_dist); + interruptible_transformed_distance(this->query_object, *it_node_point, worst_dist); if (distance_to_query_object < worst_dist) { From 4cabf30131ff5d23da7ba7a360338f4f9994cd2a Mon Sep 17 00:00:00 2001 From: Clement Jamin Date: Tue, 20 Jun 2017 15:09:55 +0200 Subject: [PATCH 014/363] Shorten typedefs --- Spatial_searching/include/CGAL/Kd_tree_node.h | 32 +++++++++++-------- 1 file changed, 18 insertions(+), 14 deletions(-) diff --git a/Spatial_searching/include/CGAL/Kd_tree_node.h b/Spatial_searching/include/CGAL/Kd_tree_node.h index 9cba8004006..9608046aa88 100644 --- a/Spatial_searching/include/CGAL/Kd_tree_node.h +++ b/Spatial_searching/include/CGAL/Kd_tree_node.h @@ -36,19 +36,21 @@ namespace CGAL { friend class Kd_tree; - typedef typename Kd_tree::Node_handle Node_handle; - typedef typename Kd_tree::Node_const_handle Node_const_handle; - typedef typename Kd_tree::Internal_node_handle Internal_node_handle; - typedef typename Kd_tree::Internal_node_const_handle Internal_node_const_handle; - typedef typename Kd_tree::Leaf_node_handle Leaf_node_handle; - typedef typename Kd_tree::Leaf_node_const_handle Leaf_node_const_handle; + typedef Kd_tree Kdt; + + typedef typename Kdt::Node_handle Node_handle; + typedef typename Kdt::Node_const_handle Node_const_handle; + typedef typename Kdt::Internal_node_handle Internal_node_handle; + typedef typename Kdt::Internal_node_const_handle Internal_node_const_handle; + typedef typename Kdt::Leaf_node_handle Leaf_node_handle; + typedef typename Kdt::Leaf_node_const_handle Leaf_node_const_handle; typedef typename TreeTraits::Point_d Point_d; typedef typename TreeTraits::FT FT; - typedef typename Kd_tree::Separator Separator; - typedef typename Kd_tree::Point_d_iterator Point_d_iterator; - typedef typename Kd_tree::iterator iterator; - typedef typename Kd_tree::D D; + typedef typename Kdt::Separator Separator; + typedef typename Kdt::Point_d_iterator Point_d_iterator; + typedef typename Kdt::iterator iterator; + typedef typename Kdt::D D; bool leaf; @@ -334,13 +336,15 @@ namespace CGAL { friend class Kd_tree; + typedef Kd_tree Kdt; + typedef Kd_tree_node< TreeTraits, Splitter, UseExtendedNode, EnablePointsCache> Base; - typedef typename Kd_tree::Node_handle Node_handle; - typedef typename Kd_tree::Node_const_handle Node_const_handle; + typedef typename Kdt::Node_handle Node_handle; + typedef typename Kdt::Node_const_handle Node_const_handle; typedef typename TreeTraits::FT FT; - typedef typename Kd_tree::Separator Separator; - typedef typename Kd_tree::D D; + typedef typename Kdt::Separator Separator; + typedef typename Kdt::D D; private: From d1659e0315819d561b0c1133fe9cc8e98934a122 Mon Sep 17 00:00:00 2001 From: Clement Jamin Date: Tue, 20 Jun 2017 15:13:02 +0200 Subject: [PATCH 015/363] More minor code improvements --- Spatial_searching/include/CGAL/Kd_tree_node.h | 20 ++++++++++--------- 1 file changed, 11 insertions(+), 9 deletions(-) diff --git a/Spatial_searching/include/CGAL/Kd_tree_node.h b/Spatial_searching/include/CGAL/Kd_tree_node.h index 9608046aa88..0b3ba524055 100644 --- a/Spatial_searching/include/CGAL/Kd_tree_node.h +++ b/Spatial_searching/include/CGAL/Kd_tree_node.h @@ -34,7 +34,7 @@ namespace CGAL { template < class TreeTraits, class Splitter, class UseExtendedNode, class EnablePointsCache > class Kd_tree_node { - friend class Kd_tree; + friend class Kd_tree; typedef Kd_tree Kdt; @@ -269,9 +269,9 @@ namespace CGAL { template < class TreeTraits, class Splitter, class UseExtendedNode, class EnablePointsCache > class Kd_tree_leaf_node : public Kd_tree_node< TreeTraits, Splitter, UseExtendedNode, EnablePointsCache >{ - friend class Kd_tree; + friend class Kd_tree; - typedef typename Kd_tree::iterator iterator; + typedef typename Kd_tree::iterator iterator; typedef Kd_tree_node< TreeTraits, Splitter, UseExtendedNode, EnablePointsCache> Base; typedef typename TreeTraits::Point_d Point_d; @@ -334,7 +334,7 @@ namespace CGAL { template < class TreeTraits, class Splitter, class UseExtendedNode, class EnablePointsCache> class Kd_tree_internal_node : public Kd_tree_node< TreeTraits, Splitter, UseExtendedNode, EnablePointsCache >{ - friend class Kd_tree; + friend class Kd_tree; typedef Kd_tree Kdt; @@ -485,15 +485,17 @@ namespace CGAL { class Kd_tree_internal_node : public Kd_tree_node< TreeTraits, Splitter, Tag_false, EnablePointsCache > { - friend class Kd_tree; + friend class Kd_tree; + + typedef Kd_tree Kdt; typedef Kd_tree_node< TreeTraits, Splitter, Tag_false, EnablePointsCache> Base; - typedef typename Kd_tree::Node_handle Node_handle; - typedef typename Kd_tree::Node_const_handle Node_const_handle; + typedef typename Kdt::Node_handle Node_handle; + typedef typename Kdt::Node_const_handle Node_const_handle; typedef typename TreeTraits::FT FT; - typedef typename Kd_tree::Separator Separator; - typedef typename Kd_tree::D D; + typedef typename Kdt::Separator Separator; + typedef typename Kdt::D D; private: From b5e948be9260e48f476846ca43709322eaf12c7b Mon Sep 17 00:00:00 2001 From: Clement Jamin Date: Tue, 20 Jun 2017 19:46:40 +0200 Subject: [PATCH 016/363] FT is supposed to be public --- Spatial_searching/include/CGAL/Search_traits_adapter.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Spatial_searching/include/CGAL/Search_traits_adapter.h b/Spatial_searching/include/CGAL/Search_traits_adapter.h index 0a408e13f3f..b18f314edf5 100644 --- a/Spatial_searching/include/CGAL/Search_traits_adapter.h +++ b/Spatial_searching/include/CGAL/Search_traits_adapter.h @@ -130,7 +130,6 @@ public: template class Distance_adapter : public Base_distance { PointPropertyMap ppmap; - typedef typename Base_distance::FT FT; CGAL_static_assertion( ( boost::is_same< boost::lvalue_property_map_tag, typename boost::property_traits::category @@ -142,7 +141,8 @@ public: ):Base_distance(distance),ppmap(ppmap_){} using Base_distance::transformed_distance; - + + typedef typename Base_distance::FT FT; typedef Point_with_info Point_d; typedef typename Base_distance::Query_item Query_item; From 17a683484f1bd08af174a0c08b8a0d325d33f6d0 Mon Sep 17 00:00:00 2001 From: Clement Jamin Date: Tue, 20 Jun 2017 19:47:26 +0200 Subject: [PATCH 017/363] Move some code to Distance_helper.h + copyright + bug fix --- .../include/CGAL/Euclidean_distance.h | 1 + Spatial_searching/include/CGAL/Kd_tree.h | 3 +- Spatial_searching/include/CGAL/Kd_tree_node.h | 2 +- .../CGAL/Orthogonal_k_neighbor_search.h | 119 ++------------ .../include/CGAL/internal/Distance_helper.h | 148 ++++++++++++++++++ 5 files changed, 167 insertions(+), 106 deletions(-) create mode 100644 Spatial_searching/include/CGAL/internal/Distance_helper.h diff --git a/Spatial_searching/include/CGAL/Euclidean_distance.h b/Spatial_searching/include/CGAL/Euclidean_distance.h index a14cab203be..6941517fbd1 100644 --- a/Spatial_searching/include/CGAL/Euclidean_distance.h +++ b/Spatial_searching/include/CGAL/Euclidean_distance.h @@ -17,6 +17,7 @@ // // // Author(s) : Hans Tangelder () +// Clement Jamin (clement.jamin.pro@gmail.com) #ifndef CGAL_EUCLIDEAN_DISTANCE_H diff --git a/Spatial_searching/include/CGAL/Kd_tree.h b/Spatial_searching/include/CGAL/Kd_tree.h index 415994c0e2b..68c94695f27 100644 --- a/Spatial_searching/include/CGAL/Kd_tree.h +++ b/Spatial_searching/include/CGAL/Kd_tree.h @@ -16,7 +16,8 @@ // $Id$ // // Author(s) : Hans Tangelder (), -// : Waqar Khan +// : Waqar Khan , +// Clement Jamin (clement.jamin.pro@gmail.com) #ifndef CGAL_KD_TREE_H #define CGAL_KD_TREE_H diff --git a/Spatial_searching/include/CGAL/Kd_tree_node.h b/Spatial_searching/include/CGAL/Kd_tree_node.h index 0b3ba524055..7dff1a6552e 100644 --- a/Spatial_searching/include/CGAL/Kd_tree_node.h +++ b/Spatial_searching/include/CGAL/Kd_tree_node.h @@ -487,7 +487,7 @@ namespace CGAL { { friend class Kd_tree; - typedef Kd_tree Kdt; + typedef Kd_tree Kdt; typedef Kd_tree_node< TreeTraits, Splitter, Tag_false, EnablePointsCache> Base; typedef typename Kdt::Node_handle Node_handle; diff --git a/Spatial_searching/include/CGAL/Orthogonal_k_neighbor_search.h b/Spatial_searching/include/CGAL/Orthogonal_k_neighbor_search.h index 9f1baae4c40..4583b2cee69 100644 --- a/Spatial_searching/include/CGAL/Orthogonal_k_neighbor_search.h +++ b/Spatial_searching/include/CGAL/Orthogonal_k_neighbor_search.h @@ -16,35 +16,18 @@ // $Id$ // // -// Author(s) : Gael Guennebaud (gael.guennebaud@inria.fr), Hans Tangelder () +// Author(s) : Gael Guennebaud (gael.guennebaud@inria.fr), +// Hans Tangelder (), +// Clement Jamin (clement.jamin.pro@gmail.com) #ifndef CGAL_ORTHOGONAL_K_NEIGHBOR_SEARCH_H #define CGAL_ORTHOGONAL_K_NEIGHBOR_SEARCH_H #include -#include - -#include +#include namespace CGAL { -// Helper struct to know at compile-time if there is a cache of the points -// stored in the tree -template -struct Has_points_cache; - -template -struct Has_points_cache -{ - static const bool value = Tree::Enable_points_cache::value; -}; - -template -struct Has_points_cache -{ - static const bool value = false; -}; - template ::type, class Splitter= Sliding_midpoint , @@ -60,93 +43,18 @@ public: private: typename SearchTraits::Cartesian_const_iterator_d query_object_it; + internal::Distance_helper m_distance_helper; std::vector dists; int m_dim; Tree const& m_tree; - CGAL_GENERATE_MEMBER_DETECTOR(transformed_distance_from_coordinates); - CGAL_GENERATE_MEMBER_DETECTOR(interruptible_transformed_distance); - BOOST_MPL_HAS_XXX_TRAIT_NAMED_DEF(has_Enable_points_cache, Enable_points_cache, false) - - // If transformed_distance_from_coordinates does not exist in `Distance` - template ::value> - FT - transformed_distance_from_coordinates( - const typename Base::Query_item& q, - Point const& p, - typename std::vector::const_iterator it_coord_begin, - typename std::vector::const_iterator it_coord_end) - { - return this->distance_instance.transformed_distance(q, p); - } - // ... or if it exists - template <> - FT - transformed_distance_from_coordinates( - const typename Base::Query_item& q, - Point const& p, - typename std::vector::const_iterator it_coord_begin, - typename std::vector::const_iterator it_coord_end) - { - return this->distance_instance.transformed_distance_from_coordinates(q, it_coord_begin, it_coord_end); - } - - // *** Version with cache *** - // If interruptible_transformed_distance does not exist in `Distance` - template ::value> - FT - interruptible_transformed_distance( - const typename Base::Query_item& q, - Point const& p, - typename std::vector::const_iterator it_coord_begin, - typename std::vector::const_iterator it_coord_end, - FT) - { - return transformed_distance_from_coordinates(q, p, it_coord_begin, it_coord_end); - } - // ... or if it exists - template <> - FT - interruptible_transformed_distance( - const typename Base::Query_item& q, - Point const& p, - typename std::vector::const_iterator it_coord_begin, - typename std::vector::const_iterator it_coord_end, - FT stop_if_geq_to_this) - { - return this->distance_instance.interruptible_transformed_distance( - q, it_coord_begin, it_coord_end, stop_if_geq_to_this); - } - - // *** Version without cache *** - // If interruptible_transformed_distance does not exist in `Distance` - template ::value> - FT - interruptible_transformed_distance( - const typename Base::Query_item& q, - Point const& p, - FT) - { - return this->distance_instance.transformed_distance(q, p); - } - // ... or if it exists - template <> - FT - interruptible_transformed_distance( - const typename Base::Query_item& q, - Point const& p, - FT stop_if_geq_to_this) - { - typename SearchTraits::Construct_cartesian_const_iterator_d construct_it = m_tree.traits().construct_cartesian_const_iterator_d_object(); - return this->distance_instance.interruptible_transformed_distance( - q, construct_it(p), construct_it(p, 0), stop_if_geq_to_this); - } - public: Orthogonal_k_neighbor_search(const Tree& tree, const typename Base::Query_item& q, unsigned int k=1, FT Eps=FT(0.0), bool Search_nearest=true, const Distance& d=Distance(),bool sorted=true) - : Base(q,k,Eps,Search_nearest,d), m_tree(tree) + : Base(q,k,Eps,Search_nearest,d), + m_distance_helper(this->distance_instance), + m_tree(tree) { if (tree.empty()) return; @@ -187,7 +95,8 @@ private: this->number_of_items_visited++; FT distance_to_query_object = - transformed_distance_from_coordinates(this->query_object, *it_node_point, cache_point_begin, cache_point_begin + m_dim); + m_distance_helper.transformed_distance_from_coordinates( + this->query_object, *it_node_point, cache_point_begin, cache_point_begin + m_dim); this->queue.insert(std::make_pair(&(*it_node_point), distance_to_query_object)); cache_point_begin += m_dim; @@ -198,7 +107,8 @@ private: this->number_of_items_visited++; FT distance_to_query_object = - interruptible_transformed_distance(this->query_object, *it_node_point, cache_point_begin, cache_point_begin + m_dim, worst_dist); + m_distance_helper.interruptible_transformed_distance( + this->query_object, *it_node_point, cache_point_begin, cache_point_begin + m_dim, worst_dist); if (distance_to_query_object < worst_dist) { @@ -229,7 +139,8 @@ private: this->number_of_items_visited++; FT distance_to_query_object = - interruptible_transformed_distance(this->query_object, *it_node_point, worst_dist); + m_distance_helper.interruptible_transformed_distance( + this->query_object, *it_node_point, worst_dist); if (distance_to_query_object < worst_dist) { @@ -248,7 +159,7 @@ private: static_cast(N); this->number_of_leaf_nodes_visited++; if (node->size() > 0) - search_in_leaf::type::value>::value>(node); + search_in_leaf::type::value>::value>(node); } else { diff --git a/Spatial_searching/include/CGAL/internal/Distance_helper.h b/Spatial_searching/include/CGAL/internal/Distance_helper.h new file mode 100644 index 00000000000..fbe0f8caa4e --- /dev/null +++ b/Spatial_searching/include/CGAL/internal/Distance_helper.h @@ -0,0 +1,148 @@ +// Copyright (c) 2002,2011 Utrecht University (The Netherlands). +// 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) : Clement Jamin (clement.jamin.pro@gmail.com) + +#ifndef CGAL_INTERNAL_DISTANCE_HELPER_H +#define CGAL_INTERNAL_DISTANCE_HELPER_H + +#include + +#include + +namespace CGAL { +namespace internal { + +// Helper struct to know at compile-time if there is a cache of the points +// stored in the tree +template +struct Has_points_cache; + +template +struct Has_points_cache +{ + static const bool value = Tree::Enable_points_cache::value; +}; + +template +struct Has_points_cache +{ + static const bool value = false; +}; + +CGAL_GENERATE_MEMBER_DETECTOR(transformed_distance_from_coordinates); +CGAL_GENERATE_MEMBER_DETECTOR(interruptible_transformed_distance); +BOOST_MPL_HAS_XXX_TRAIT_NAMED_DEF(has_Enable_points_cache, Enable_points_cache, false) + + +template +class Distance_helper +{ + typedef typename Distance::FT FT; + typedef typename Distance::Point_d Point; + typedef typename Distance::Query_item Query_item; + +public: + + Distance_helper(Distance const& distance) + : m_distance(distance) + {} + + // If transformed_distance_from_coordinates does not exist in `Distance` + template ::value> + FT + transformed_distance_from_coordinates( + const typename Query_item& q, + Point const& p, + typename std::vector::const_iterator it_coord_begin, + typename std::vector::const_iterator it_coord_end) + { + return m_distance.transformed_distance(q, p); + } + // ... or if it exists + template <> + FT + transformed_distance_from_coordinates( + const typename Query_item& q, + Point const& p, + typename std::vector::const_iterator it_coord_begin, + typename std::vector::const_iterator it_coord_end) + { + return m_distance.transformed_distance_from_coordinates(q, it_coord_begin, it_coord_end); + } + + // *** Version with cache *** + // If interruptible_transformed_distance does not exist in `Distance` + template ::value> + FT + interruptible_transformed_distance( + const typename Query_item& q, + Point const& p, + typename std::vector::const_iterator it_coord_begin, + typename std::vector::const_iterator it_coord_end, + FT) + { + return transformed_distance_from_coordinates(q, p, it_coord_begin, it_coord_end); + } + // ... or if it exists + template <> + FT + interruptible_transformed_distance( + const typename Query_item& q, + Point const& p, + typename std::vector::const_iterator it_coord_begin, + typename std::vector::const_iterator it_coord_end, + FT stop_if_geq_to_this) + { + return m_distance.interruptible_transformed_distance( + q, it_coord_begin, it_coord_end, stop_if_geq_to_this); + } + + // *** Version without cache *** + // If interruptible_transformed_distance does not exist in `Distance` + template ::value> + FT + interruptible_transformed_distance( + const typename Query_item& q, + Point const& p, + FT) + { + return m_distance.transformed_distance(q, p); + } + // ... or if it exists + template <> + FT + interruptible_transformed_distance( + const typename Query_item& q, + Point const& p, + FT stop_if_geq_to_this) + { + typename SearchTraits::Construct_cartesian_const_iterator_d construct_it = m_tree.traits().construct_cartesian_const_iterator_d_object(); + return m_distance.interruptible_transformed_distance( + q, construct_it(p), construct_it(p, 0), stop_if_geq_to_this); + } + +private: + Distance const & m_distance; + +}; // Distance_helper + + +}} // namespace CGAL::internal + +#endif // CGAL_INTERNAL_DISTANCE_HELPERS_H From 1cfab776341b0c5bff63ac952613119353aeb659 Mon Sep 17 00:00:00 2001 From: Clement Jamin Date: Tue, 20 Jun 2017 19:52:09 +0200 Subject: [PATCH 018/363] Rename header file --- .../include/CGAL/Orthogonal_k_neighbor_search.h | 2 +- .../CGAL/internal/{Distance_helper.h => Search_helpers.h} | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) rename Spatial_searching/include/CGAL/internal/{Distance_helper.h => Search_helpers.h} (97%) diff --git a/Spatial_searching/include/CGAL/Orthogonal_k_neighbor_search.h b/Spatial_searching/include/CGAL/Orthogonal_k_neighbor_search.h index 4583b2cee69..8e7b2899d0a 100644 --- a/Spatial_searching/include/CGAL/Orthogonal_k_neighbor_search.h +++ b/Spatial_searching/include/CGAL/Orthogonal_k_neighbor_search.h @@ -24,7 +24,7 @@ #define CGAL_ORTHOGONAL_K_NEIGHBOR_SEARCH_H #include -#include +#include namespace CGAL { diff --git a/Spatial_searching/include/CGAL/internal/Distance_helper.h b/Spatial_searching/include/CGAL/internal/Search_helpers.h similarity index 97% rename from Spatial_searching/include/CGAL/internal/Distance_helper.h rename to Spatial_searching/include/CGAL/internal/Search_helpers.h index fbe0f8caa4e..782031e2c62 100644 --- a/Spatial_searching/include/CGAL/internal/Distance_helper.h +++ b/Spatial_searching/include/CGAL/internal/Search_helpers.h @@ -18,8 +18,8 @@ // // Author(s) : Clement Jamin (clement.jamin.pro@gmail.com) -#ifndef CGAL_INTERNAL_DISTANCE_HELPER_H -#define CGAL_INTERNAL_DISTANCE_HELPER_H +#ifndef CGAL_INTERNAL_SEARCH_HELPERS_H +#define CGAL_INTERNAL_SEARCH_HELPERS_H #include @@ -145,4 +145,4 @@ private: }} // namespace CGAL::internal -#endif // CGAL_INTERNAL_DISTANCE_HELPERS_H +#endif // CGAL_INTERNAL_SEARCH_HELPERSS_H From 0de1362e093cfa3ab7c924bea5dee50e88d5b01d Mon Sep 17 00:00:00 2001 From: Clement Jamin Date: Wed, 21 Jun 2017 00:34:02 +0200 Subject: [PATCH 019/363] Use cache if available for NEAREST neighbor search --- .../Orthogonal_incremental_neighbor_search.h | 152 +++++++++++++----- 1 file changed, 110 insertions(+), 42 deletions(-) diff --git a/Spatial_searching/include/CGAL/Orthogonal_incremental_neighbor_search.h b/Spatial_searching/include/CGAL/Orthogonal_incremental_neighbor_search.h index 13eca80ece1..13f65c8aa5a 100644 --- a/Spatial_searching/include/CGAL/Orthogonal_incremental_neighbor_search.h +++ b/Spatial_searching/include/CGAL/Orthogonal_incremental_neighbor_search.h @@ -17,6 +17,7 @@ // // // Author(s) : Hans Tangelder () +// Clement Jamin (clement.jamin.pro@gmail.com) #ifndef CGAL_ORTHOGONAL_INCREMENTAL_NEIGHBOR_SEARCH #define CGAL_ORTHOGONAL_INCREMENTAL_NEIGHBOR_SEARCH @@ -29,6 +30,8 @@ #include #include +#include + namespace CGAL { template m_distance_helper; FT multiplication_factor; @@ -88,6 +92,8 @@ namespace CGAL { FT rd; + int m_dim; + Tree const& m_tree; class Priority_higher { public: @@ -143,27 +149,30 @@ namespace CGAL { FT Eps=FT(0.0), bool search_nearest=true) : traits(tree.traits()),number_of_neighbours_computed(0), number_of_internal_nodes_visited(0), number_of_leaf_nodes_visited(0), number_of_items_visited(0), - Orthogonal_distance_instance(tr), multiplication_factor(Orthogonal_distance_instance.transformed_distance(FT(1.0)+Eps)), + orthogonal_distance_instance(tr), + m_distance_helper(orthogonal_distance_instance), + multiplication_factor(orthogonal_distance_instance.transformed_distance(FT(1.0)+Eps)), query_point(q), search_nearest_neighbour(search_nearest), PriorityQueue(Priority_higher(search_nearest)), Item_PriorityQueue(Distance_smaller(search_nearest)), - reference_count(1) + reference_count(1), + m_tree(tree) { - if (tree.empty()) return; + if (m_tree.empty()) return; typename SearchTraits::Construct_cartesian_const_iterator_d ccci=traits.construct_cartesian_const_iterator_d_object(); - int dim = static_cast(std::distance(ccci(q), ccci(q,0))); + m_dim = static_cast(std::distance(ccci(q), ccci(q,0))); - dists.resize(dim); - for(int i=0 ; i + bool search_in_leaf(typename Tree::Leaf_node_const_handle node); + + // With cache + template<> + bool search_in_leaf(typename Tree::Leaf_node_const_handle node) + { + typename Tree::iterator it_node_point = node->begin(), it_node_point_end = node->end(); + typename std::vector::const_iterator cache_point_begin = m_tree.cache_begin() + m_dim*(it_node_point - m_tree.begin()); + + for (; it_node_point != node->end(); ++it_node_point) + { + number_of_items_visited++; + FT distance_to_query_point = + m_distance_helper.transformed_distance_from_coordinates( + query_point, *it_node_point, cache_point_begin, cache_point_begin + m_dim); + + Point_with_transformed_distance *NN_Candidate = + new Point_with_transformed_distance(*it_node_point, distance_to_query_point); + Item_PriorityQueue.push(NN_Candidate); + + cache_point_begin += m_dim; + } + // old top of PriorityQueue has been processed, + // hence update rd + + bool next_neighbour_found; + if (!(PriorityQueue.empty())) + { + rd = CGAL::cpp11::get<1>(*PriorityQueue.top()); + next_neighbour_found = + (multiplication_factor*rd > + Item_PriorityQueue.top()->second); + } + else // priority queue empty => last neighbour found + { + next_neighbour_found = true; + } + + number_of_neighbours_computed++; + return next_neighbour_found; + } + + // Without cache + template<> + bool search_in_leaf(typename Tree::Leaf_node_const_handle node) + { + typename Tree::iterator it_node_point = node->begin(), it_node_point_end = node->end(); + + for (; it_node_point != node->end(); ++it_node_point) + { + number_of_items_visited++; + FT distance_to_query_point= + orthogonal_distance_instance.transformed_distance(query_point, *it_node_point); + + Point_with_transformed_distance *NN_Candidate = + new Point_with_transformed_distance(*it_node_point, distance_to_query_point); + Item_PriorityQueue.push(NN_Candidate); + } + // old top of PriorityQueue has been processed, + // hence update rd + + bool next_neighbour_found; + if (!(PriorityQueue.empty())) + { + rd = CGAL::cpp11::get<1>(*PriorityQueue.top()); + next_neighbour_found = + (multiplication_factor*rd > + Item_PriorityQueue.top()->second); + } + else // priority queue empty => last neighbour found + { + next_neighbour_found=true; + } + + number_of_neighbours_computed++; + return next_neighbour_found; + } + + void Compute_the_next_nearest_neighbour() { @@ -287,7 +377,7 @@ namespace CGAL { FT diff2 = val - node->lower_high_value(); if (diff1 + diff2 < FT(0.0)) { new_rd= - Orthogonal_distance_instance.new_distance(copy_rd,dst,diff1,new_cut_dim); + orthogonal_distance_instance.new_distance(copy_rd,dst,diff1,new_cut_dim); CGAL_assertion(new_rd >= copy_rd); dists[new_cut_dim] = diff1; @@ -299,7 +389,7 @@ namespace CGAL { } else { // compute new distance - new_rd=Orthogonal_distance_instance.new_distance(copy_rd,dst,diff2,new_cut_dim); + new_rd=orthogonal_distance_instance.new_distance(copy_rd,dst,diff2,new_cut_dim); CGAL_assertion(new_rd >= copy_rd); dists[new_cut_dim] = diff2; Node_with_distance *Lower_Child = @@ -313,31 +403,9 @@ namespace CGAL { typename Tree::Leaf_node_const_handle node = static_cast(N); number_of_leaf_nodes_visited++; - if (node->size() > 0) { - for (typename Tree::iterator it=node->begin(); it != node->end(); it++) { - number_of_items_visited++; - FT distance_to_query_point= - Orthogonal_distance_instance.transformed_distance(query_point,*it); - Point_with_transformed_distance *NN_Candidate= - new Point_with_transformed_distance(*it,distance_to_query_point); - Item_PriorityQueue.push(NN_Candidate); - } - // old top of PriorityQueue has been processed, - // hence update rd - - if (!(PriorityQueue.empty())) { - rd = CGAL::cpp11::get<1>(*PriorityQueue.top()); - next_neighbour_found = - (multiplication_factor*rd > - Item_PriorityQueue.top()->second); - } - else // priority queue empty => last neighbour found - { - next_neighbour_found=true; - } - - number_of_neighbours_computed++; - } + if (node->size() > 0) + next_neighbour_found = + search_in_leaf::type::value>::value>(node); } // next_neighbour_found or priority queue is empty // in the latter case also the item priority quee is empty } @@ -374,7 +442,7 @@ namespace CGAL { if (diff1 + diff2 < FT(0.0)) { diff1 = val - node->upper_high_value(); new_rd= - Orthogonal_distance_instance.new_distance(copy_rd,dst,diff1,new_cut_dim); + orthogonal_distance_instance.new_distance(copy_rd,dst,diff1,new_cut_dim); Node_with_distance *Lower_Child = new Node_with_distance(node->lower(), copy_rd, dists); PriorityQueue.push(Lower_Child); @@ -385,7 +453,7 @@ namespace CGAL { } else { // compute new distance diff2 = val - node->lower_low_value(); - new_rd=Orthogonal_distance_instance.new_distance(copy_rd,dst,diff2,new_cut_dim); + new_rd=orthogonal_distance_instance.new_distance(copy_rd,dst,diff2,new_cut_dim); Node_with_distance *Upper_Child = new Node_with_distance(node->upper(), copy_rd, dists); PriorityQueue.push(Upper_Child); @@ -402,7 +470,7 @@ namespace CGAL { for (typename Tree::iterator it=node->begin(); it != node->end(); it++) { number_of_items_visited++; FT distance_to_query_point= - Orthogonal_distance_instance.transformed_distance(query_point,*it); + orthogonal_distance_instance.transformed_distance(query_point,*it); Point_with_transformed_distance *NN_Candidate= new Point_with_transformed_distance(*it,distance_to_query_point); Item_PriorityQueue.push(NN_Candidate); From 82b1ebb063221dda27327f49ca892117ac8e12ed Mon Sep 17 00:00:00 2001 From: Clement Jamin Date: Tue, 27 Jun 2017 17:59:21 +0200 Subject: [PATCH 020/363] Clean-up code --- .../include/CGAL/Euclidean_distance.h | 82 ++++++++----------- 1 file changed, 35 insertions(+), 47 deletions(-) diff --git a/Spatial_searching/include/CGAL/Euclidean_distance.h b/Spatial_searching/include/CGAL/Euclidean_distance.h index 6941517fbd1..79fc65d2c75 100644 --- a/Spatial_searching/include/CGAL/Euclidean_distance.h +++ b/Spatial_searching/include/CGAL/Euclidean_distance.h @@ -69,24 +69,44 @@ namespace CGAL { inline FT transformed_distance_from_coordinates(const Query_item& q, Coord_iterator it_coord_begin, Coord_iterator it_coord_end) const { - return transformed_distance(q, it_coord_begin, it_coord_end, D()); + return transformed_distance_from_coordinates(q, it_coord_begin, it_coord_end, D()); } - // During the computation, if the partially-computed distance `pcd` gets greater or equal - // to `stop_if_geq_to_this`, the computation is stopped and `pcd` is returned + // Static dim = 2 loop unrolled template - inline FT interruptible_transformed_distance(const Query_item& q, - Coord_iterator it_coord_begin, Coord_iterator it_coord_end, - FT stop_if_geq_to_this) const + inline FT transformed_distance_from_coordinates(const Query_item& q, + Coord_iterator it_coord_begin, Coord_iterator /*unused*/, + Dimension_tag<2>) const { - return transformed_distance(q, it_coord_begin, it_coord_end, stop_if_geq_to_this, D()); + typename SearchTraits::Construct_cartesian_const_iterator_d construct_it = traits.construct_cartesian_const_iterator_d_object(); + typename SearchTraits::Cartesian_const_iterator_d qit = construct_it(q); + FT distance = square(*qit - *it_coord_begin); + qit++; it_coord_begin++; + distance += square(*qit - *it_coord_begin); + return distance; } - // Dynamic version for runtime dimension, taking iterators on coordinates as parameters + // Static dim = 3 loop unrolled + template + inline FT transformed_distance_from_coordinates(const Query_item& q, + Coord_iterator it_coord_begin, Coord_iterator /*unused*/, + Dimension_tag<3>) const + { + typename SearchTraits::Construct_cartesian_const_iterator_d construct_it = traits.construct_cartesian_const_iterator_d_object(); + typename SearchTraits::Cartesian_const_iterator_d qit = construct_it(q); + FT distance = square(*qit - *it_coord_begin); + qit++; it_coord_begin++; + distance += square(*qit - *it_coord_begin); + qit++; it_coord_begin++; + distance += square(*qit - *it_coord_begin); + return distance; + } + + // Other cases: static dim > 3 or dynamic dim template - inline FT transformed_distance(const Query_item& q, - Coord_iterator it_coord_begin, Coord_iterator /*unused*/, - Dim) const + inline FT transformed_distance_from_coordinates(const Query_item& q, + Coord_iterator it_coord_begin, Coord_iterator /*unused*/, + Dim) const { FT distance = FT(0); typename SearchTraits::Construct_cartesian_const_iterator_d construct_it = traits.construct_cartesian_const_iterator_d_object(); @@ -99,13 +119,12 @@ namespace CGAL { return distance; } - // Dynamic version for runtime dimension, taking iterators on coordinates as parameters // During the computation, if the partially-computed distance `pcd` gets greater or equal // to `stop_if_geq_to_this`, the computation is stopped and `pcd` is returned - template - inline FT transformed_distance(const Query_item& q, - Coord_iterator it_coord_begin, Coord_iterator /*unused*/, - FT stop_if_geq_to_this, Dim) const + template + inline FT interruptible_transformed_distance(const Query_item& q, + Coord_iterator it_coord_begin, Coord_iterator /*unused*/, + FT stop_if_geq_to_this) const { FT distance = FT(0); typename SearchTraits::Construct_cartesian_const_iterator_d construct_it = traits.construct_cartesian_const_iterator_d_object(); @@ -147,37 +166,6 @@ namespace CGAL { return distance; } - //DIM = 2 loop unrolled - template - inline FT transformed_distance(const Query_item& q, - Coord_iterator it_coord_begin, Coord_iterator /*unused*/, - FT /*unused*/, Dimension_tag<2>) const - { - typename SearchTraits::Construct_cartesian_const_iterator_d construct_it = traits.construct_cartesian_const_iterator_d_object(); - typename SearchTraits::Cartesian_const_iterator_d qit = construct_it(q); - FT distance = square(*qit - *it_coord_begin); - qit++; it_coord_begin++; - distance += square(*qit - *it_coord_begin); - return distance; - } - - //DIM = 3 loop unrolled - template - inline FT transformed_distance(const Query_item& q, - Coord_iterator it_coord_begin, Coord_iterator /*unused*/, - FT /*unused*/, Dimension_tag<3>) const - { - typename SearchTraits::Construct_cartesian_const_iterator_d construct_it = traits.construct_cartesian_const_iterator_d_object(); - typename SearchTraits::Cartesian_const_iterator_d qit = construct_it(q); - FT distance = square(*qit - *it_coord_begin); - qit++; it_coord_begin++; - distance += square(*qit - *it_coord_begin); - qit++; it_coord_begin++; - distance += square(*qit - *it_coord_begin); - return distance; - } - - inline FT min_distance_to_rectangle(const Query_item& q, const Kd_tree_rectangle& r) const { FT distance = FT(0); From 2f305ec10fdc67d4cdd8fb8345b1f9e6851a2969 Mon Sep 17 00:00:00 2001 From: Clement Jamin Date: Fri, 8 Sep 2017 17:37:09 +0200 Subject: [PATCH 021/363] Use cache when computing furthest neighbors --- .../CGAL/Orthogonal_k_neighbor_search.h | 63 +++++++++++++++---- 1 file changed, 50 insertions(+), 13 deletions(-) diff --git a/Spatial_searching/include/CGAL/Orthogonal_k_neighbor_search.h b/Spatial_searching/include/CGAL/Orthogonal_k_neighbor_search.h index 8e7b2899d0a..6b453022cc6 100644 --- a/Spatial_searching/include/CGAL/Orthogonal_k_neighbor_search.h +++ b/Spatial_searching/include/CGAL/Orthogonal_k_neighbor_search.h @@ -82,14 +82,15 @@ public: private: template - void search_in_leaf(typename Tree::Leaf_node_const_handle node); + void search_nearest_in_leaf(typename Tree::Leaf_node_const_handle node); // With cache template<> - void search_in_leaf(typename Tree::Leaf_node_const_handle node) + void search_nearest_in_leaf(typename Tree::Leaf_node_const_handle node) { typename Tree::iterator it_node_point = node->begin(), it_node_point_end = node->end(); typename std::vector::const_iterator cache_point_begin = m_tree.cache_begin() + m_dim*(it_node_point - m_tree.begin()); + // As long as the queue is not full, the node is just inserted for (; !this->queue.full() && it_node_point != it_node_point_end; ++it_node_point) { this->number_of_items_visited++; @@ -101,6 +102,8 @@ private: cache_point_begin += m_dim; } + // Now that the queue is full, we can gain time by keeping track + // of the current worst distance to interrupt the distance computation earlier FT worst_dist = this->queue.top().second; for (; it_node_point != it_node_point_end; ++it_node_point) { @@ -122,9 +125,10 @@ private: // Without cache template<> - void search_in_leaf(typename Tree::Leaf_node_const_handle node) + void search_nearest_in_leaf(typename Tree::Leaf_node_const_handle node) { typename Tree::iterator it_node_point = node->begin(), it_node_point_end = node->end(); + // As long as the queue is not full, the node is just inserted for (; !this->queue.full() && it_node_point != it_node_point_end; ++it_node_point) { this->number_of_items_visited++; @@ -133,6 +137,8 @@ private: this->distance_instance.transformed_distance(this->query_object, *it_node_point); this->queue.insert(std::make_pair(&(*it_node_point), distance_to_query_object)); } + // Now that the queue is full, we can gain time by keeping track + // of the current worst distance to interrupt the distance computation earlier FT worst_dist = this->queue.top().second; for (; it_node_point != it_node_point_end; ++it_node_point) { @@ -159,7 +165,7 @@ private: static_cast(N); this->number_of_leaf_nodes_visited++; if (node->size() > 0) - search_in_leaf::type::value>::value>(node); + search_nearest_in_leaf::type::value>::value>(node); } else { @@ -196,6 +202,45 @@ private: } } + template + void search_furthest_in_leaf(typename Tree::Leaf_node_const_handle node); + + // With cache + template<> + void search_furthest_in_leaf(typename Tree::Leaf_node_const_handle node) + { + typename Tree::iterator it_node_point = node->begin(), it_node_point_end = node->end(); + typename std::vector::const_iterator cache_point_begin = m_tree.cache_begin() + m_dim*(it_node_point - m_tree.begin()); + // In furthest search mode, the interruptible distance cannot be used to optimize + for (; it_node_point != it_node_point_end; ++it_node_point) + { + this->number_of_items_visited++; + + FT distance_to_query_object = + m_distance_helper.transformed_distance_from_coordinates( + this->query_object, *it_node_point, cache_point_begin, cache_point_begin + m_dim); + this->queue.insert(std::make_pair(&(*it_node_point), distance_to_query_object)); + + cache_point_begin += m_dim; + } + } + + // Without cache + template<> + void search_furthest_in_leaf(typename Tree::Leaf_node_const_handle node) + { + typename Tree::iterator it_node_point = node->begin(), it_node_point_end = node->end(); + // In furthest search mode, the interruptible distance cannot be used to optimize + for (; it_node_point != it_node_point_end; ++it_node_point) + { + this->number_of_items_visited++; + + FT distance_to_query_object = + this->distance_instance.transformed_distance(this->query_object, *it_node_point); + this->queue.insert(std::make_pair(&(*it_node_point), distance_to_query_object)); + } + } + void compute_furthest_neighbors_orthogonally(typename Base::Node_const_handle N, FT rd) { if (N->is_leaf()) @@ -205,15 +250,7 @@ private: static_cast(N); this->number_of_leaf_nodes_visited++; if (node->size() > 0) - { - for (typename Tree::iterator it_node_point=node->begin(); it_node_point != node->end(); it_node_point++) - { - this->number_of_items_visited++; - FT distance_to_query_object= - this->distance_instance.transformed_distance(this->query_object,*it_node_point); - this->queue.insert(std::make_pair(&(*it_node_point),distance_to_query_object)); - } - } + search_furthest_in_leaf::type::value>::value>(node); } else { From 1f11dfa00493124d9c9c702a963cd63e237b802a Mon Sep 17 00:00:00 2001 From: Clement Jamin Date: Fri, 8 Sep 2017 18:34:36 +0200 Subject: [PATCH 022/363] Use cache when computing furthest neighbors (incremental seach) --- .../Orthogonal_incremental_neighbor_search.h | 48 +++++-------------- 1 file changed, 13 insertions(+), 35 deletions(-) diff --git a/Spatial_searching/include/CGAL/Orthogonal_incremental_neighbor_search.h b/Spatial_searching/include/CGAL/Orthogonal_incremental_neighbor_search.h index 13f65c8aa5a..af3cf93e1ee 100644 --- a/Spatial_searching/include/CGAL/Orthogonal_incremental_neighbor_search.h +++ b/Spatial_searching/include/CGAL/Orthogonal_incremental_neighbor_search.h @@ -268,11 +268,11 @@ namespace CGAL { template - bool search_in_leaf(typename Tree::Leaf_node_const_handle node); + bool search_in_leaf(typename Tree::Leaf_node_const_handle node, bool search_furthest); // With cache template<> - bool search_in_leaf(typename Tree::Leaf_node_const_handle node) + bool search_in_leaf(typename Tree::Leaf_node_const_handle node, bool search_furthest) { typename Tree::iterator it_node_point = node->begin(), it_node_point_end = node->end(); typename std::vector::const_iterator cache_point_begin = m_tree.cache_begin() + m_dim*(it_node_point - m_tree.begin()); @@ -297,9 +297,9 @@ namespace CGAL { if (!(PriorityQueue.empty())) { rd = CGAL::cpp11::get<1>(*PriorityQueue.top()); - next_neighbour_found = - (multiplication_factor*rd > - Item_PriorityQueue.top()->second); + next_neighbour_found = (search_furthest ? + multiplication_factor*rd < Item_PriorityQueue.top()->second + : multiplication_factor*rd > Item_PriorityQueue.top()->second); } else // priority queue empty => last neighbour found { @@ -312,7 +312,7 @@ namespace CGAL { // Without cache template<> - bool search_in_leaf(typename Tree::Leaf_node_const_handle node) + bool search_in_leaf(typename Tree::Leaf_node_const_handle node, bool search_furthest) { typename Tree::iterator it_node_point = node->begin(), it_node_point_end = node->end(); @@ -333,9 +333,9 @@ namespace CGAL { if (!(PriorityQueue.empty())) { rd = CGAL::cpp11::get<1>(*PriorityQueue.top()); - next_neighbour_found = - (multiplication_factor*rd > - Item_PriorityQueue.top()->second); + next_neighbour_found = (search_furthest ? + multiplication_factor*rd < Item_PriorityQueue.top()->second + : multiplication_factor*rd > Item_PriorityQueue.top()->second); } else // priority queue empty => last neighbour found { @@ -405,7 +405,7 @@ namespace CGAL { number_of_leaf_nodes_visited++; if (node->size() > 0) next_neighbour_found = - search_in_leaf::type::value>::value>(node); + search_in_leaf::type::value>::value>(node, false); } // next_neighbour_found or priority queue is empty // in the latter case also the item priority quee is empty } @@ -466,31 +466,9 @@ namespace CGAL { typename Tree::Leaf_node_const_handle node = static_cast(N); number_of_leaf_nodes_visited++; - if (node->size() > 0) { - for (typename Tree::iterator it=node->begin(); it != node->end(); it++) { - number_of_items_visited++; - FT distance_to_query_point= - orthogonal_distance_instance.transformed_distance(query_point,*it); - Point_with_transformed_distance *NN_Candidate= - new Point_with_transformed_distance(*it,distance_to_query_point); - Item_PriorityQueue.push(NN_Candidate); - } - // old top of PriorityQueue has been processed, - // hence update rd - - if (!(PriorityQueue.empty())) { - rd = CGAL::cpp11::get<1>(*PriorityQueue.top()); - next_neighbour_found = - (multiplication_factor*rd < - Item_PriorityQueue.top()->second); - } - else // priority queue empty => last neighbour found - { - next_neighbour_found=true; - } - - number_of_neighbours_computed++; - } + if (node->size() > 0) + next_neighbour_found = + search_in_leaf::type::value>::value>(node, true); } // next_neighbour_found or priority queue is empty // in the latter case also the item priority quee is empty } From ae1f89b4d3704ff54a36adfa14b0ffb1c0105d1b Mon Sep 17 00:00:00 2001 From: Clement Jamin Date: Wed, 11 Oct 2017 10:23:31 +0200 Subject: [PATCH 023/363] Optimize "search" (all points in ball) when using cache --- .../include/CGAL/Fuzzy_iso_box.h | 10 +++ Spatial_searching/include/CGAL/Fuzzy_sphere.h | 16 ++++ Spatial_searching/include/CGAL/Kd_tree.h | 12 +-- Spatial_searching/include/CGAL/Kd_tree_node.h | 83 +++++++++++++++++-- .../include/CGAL/internal/Search_helpers.h | 15 ++-- 5 files changed, 118 insertions(+), 18 deletions(-) diff --git a/Spatial_searching/include/CGAL/Fuzzy_iso_box.h b/Spatial_searching/include/CGAL/Fuzzy_iso_box.h index f99e44ccf66..f3bb8f0825d 100644 --- a/Spatial_searching/include/CGAL/Fuzzy_iso_box.h +++ b/Spatial_searching/include/CGAL/Fuzzy_iso_box.h @@ -125,6 +125,16 @@ namespace CGAL { return true; } + template + bool contains_point_given_as_coordinates(Coord_iterator it_coord_begin, Coord_iterator /*unused*/) const { + Construct_cartesian_const_iterator_d construct_it=traits.construct_cartesian_const_iterator_d_object(); + Cartesian_const_iterator_d minit= min_begin, maxit = max_begin; + for (unsigned int i = 0; i < dim; ++i, ++it_coord_begin, ++minit, ++maxit) { + if ( ((*it_coord_begin) < (*minit)) || ((*it_coord_begin) >= (*maxit)) ) return false; + } + return true; + } + bool inner_range_intersects(const Kd_tree_rectangle& rectangle) const { Cartesian_const_iterator_d minit= min_begin, maxit = max_begin; for (unsigned int i = 0; i < dim; ++i, ++minit, ++maxit) { diff --git a/Spatial_searching/include/CGAL/Fuzzy_sphere.h b/Spatial_searching/include/CGAL/Fuzzy_sphere.h index 0ed361baf3f..645175ac683 100644 --- a/Spatial_searching/include/CGAL/Fuzzy_sphere.h +++ b/Spatial_searching/include/CGAL/Fuzzy_sphere.h @@ -79,6 +79,22 @@ namespace CGAL { return (distance < squared_radius); } + template + bool contains_point_given_as_coordinates(Coord_iterator it_coord_begin, Coord_iterator /*unused*/) const { + // test whether the distance between c and p is less than the radius + FT squared_radius = r*r; + FT distance = FT(0); + typename SearchTraits::Construct_cartesian_const_iterator_d construct_it = + traits.construct_cartesian_const_iterator_d_object(); + typename SearchTraits::Cartesian_const_iterator_d cit = construct_it(c), + end = construct_it(c, 0); + + for (; cit != end && (distance < squared_radius); ++cit, ++it_coord_begin) + distance += ((*cit) - (*it_coord_begin))*((*cit) - (*it_coord_begin)); + + return (distance < squared_radius); + } + bool inner_range_intersects(const Kd_tree_rectangle& rectangle) const { // test whether the interior of a sphere // with radius (r-eps) intersects 'rectangle', i.e. diff --git a/Spatial_searching/include/CGAL/Kd_tree.h b/Spatial_searching/include/CGAL/Kd_tree.h index 3896706dcfa..151536eb87b 100644 --- a/Spatial_searching/include/CGAL/Kd_tree.h +++ b/Spatial_searching/include/CGAL/Kd_tree.h @@ -112,6 +112,8 @@ private: // std::vector data; + // Dimension of the points + int dim_; #ifdef CGAL_HAS_THREADS mutable CGAL_MUTEX building_mutex;//mutex used to protect const calls inducing build() @@ -121,7 +123,7 @@ private: // protected copy constructor Kd_tree(const Tree& tree) - : traits_(tree.traits_),built_(tree.built_) + : traits_(tree.traits_),built_(tree.built_),dim_(-1) {}; @@ -276,13 +278,13 @@ public: CGAL_assertion(!removed_); const Point_d& p = *pts.begin(); typename SearchTraits::Construct_cartesian_const_iterator_d ccci=traits_.construct_cartesian_const_iterator_d_object(); - int dim = static_cast(std::distance(ccci(p), ccci(p,0))); + dim_ = static_cast(std::distance(ccci(p), ccci(p,0))); data.reserve(pts.size()); for(unsigned int i = 0; i < pts.size(); i++){ data.push_back(&pts[i]); } - Point_container c(dim, data.begin(), data.end(),traits_); + Point_container c(dim_, data.begin(), data.end(),traits_); bbox = new Kd_tree_rectangle(c.bounding_box()); if (c.size() <= split.bucket_size()){ tree_root = create_leaf_node(c); @@ -300,7 +302,7 @@ public: if (Enable_points_cache::value) { typename SearchTraits::Construct_cartesian_const_iterator_d construct_it = traits_.construct_cartesian_const_iterator_d_object(); - points_cache.reserve(dim * pts.size()); + points_cache.reserve(dim_ * pts.size()); for (std::size_t i = 0; i < pts.size(); ++i) points_cache.insert(points_cache.end(), construct_it(ptstmp[i]), construct_it(ptstmp[i], 0)); } @@ -491,7 +493,7 @@ public: const_build(); } Kd_tree_rectangle b(*bbox); - return tree_root->search(it,q,b); + return tree_root->search(it,q,b,begin(),cache_begin(),dim_); } return it; } diff --git a/Spatial_searching/include/CGAL/Kd_tree_node.h b/Spatial_searching/include/CGAL/Kd_tree_node.h index 71fd3d7a8e6..a17d3503116 100644 --- a/Spatial_searching/include/CGAL/Kd_tree_node.h +++ b/Spatial_searching/include/CGAL/Kd_tree_node.h @@ -27,10 +27,14 @@ #include #include +#include +#include #include namespace CGAL { + CGAL_GENERATE_MEMBER_DETECTOR(contains_point_given_as_coordinates); + template class Kd_tree; @@ -193,15 +197,19 @@ namespace CGAL { template OutputIterator search(OutputIterator it, const FuzzyQueryItem& q, - Kd_tree_rectangle& b) const + Kd_tree_rectangle& b, + typename Kdt::const_iterator tree_points_begin, + typename std::vector::const_iterator cache_begin, + int dim) const { if (is_leaf()) { Leaf_node_const_handle node = static_cast(this); - if (node->size()>0) - for (iterator i=node->begin(); i != node->end(); i++) - if (q.contains(*i)) - {*it++=*i;} + if (node->size() > 0) + { + internal::Has_points_cache::type::value>::type dummy; + search_in_leaf(node, q, tree_points_begin, cache_begin, dim, it, dummy); + } } else { Internal_node_const_handle node = @@ -214,12 +222,12 @@ namespace CGAL { it=node->lower()->tree_items(it); else if (q.inner_range_intersects(b)) - it=node->lower()->search(it,q,b); + it=node->lower()->search(it,q,b,tree_points_begin,cache_begin,dim); if (q.outer_range_contains(b_upper)) it=node->upper()->tree_items(it); else if (q.inner_range_intersects(b_upper)) - it=node->upper()->search(it,q,b_upper); + it=node->upper()->search(it,q,b_upper,tree_points_begin,cache_begin,dim); }; return it; } @@ -266,6 +274,67 @@ namespace CGAL { return result; } + private: + + // If contains_point_given_as_coordinates does not exist in `FuzzyQueryItem` + template + bool contains( + const FuzzyQueryItem& q, + Point_d const& p, + typename std::vector::const_iterator it_coord_begin, + typename std::vector::const_iterator it_coord_end, + Tag_false /*has_contains_point_given_as_coordinates*/) const + { + return q.contains(p); + } + // ... or if it exists + template + bool contains( + const typename FuzzyQueryItem& q, + Point_d const& p, + typename std::vector::const_iterator it_coord_begin, + typename std::vector::const_iterator it_coord_end, + Tag_true /*has_contains_point_given_as_coordinates*/) const + { + return q.contains_point_given_as_coordinates(it_coord_begin, it_coord_end); + } + + // With cache + template + void search_in_leaf( + Leaf_node_const_handle node, + const FuzzyQueryItem &q, + typename Kdt::const_iterator tree_points_begin, + typename std::vector::const_iterator cache_begin, + int dim, + OutputIterator oit, + Tag_true /*has_points_cache*/) const + { + typename Kdt::iterator it_node_point = node->begin(), it_node_point_end = node->end(); + typename std::vector::const_iterator cache_point_it = cache_begin + dim*(it_node_point - tree_points_begin); + for (; it_node_point != it_node_point_end; ++it_node_point, cache_point_it += dim) + { + Boolean_tag::value> dummy; + if (contains(q, *it_node_point, cache_point_it, cache_point_it + dim, dummy)) + *oit++ = *it_node_point; + } + } + + // Without cache + template + void search_in_leaf( + Leaf_node_const_handle node, + const FuzzyQueryItem &q, + typename Kdt::const_iterator tree_points_begin, + typename std::vector::const_iterator cache_begin, + int dim, + OutputIterator oit, + Tag_false /*has_points_cache*/) const + { + for (iterator i = node->begin(); i != node->end(); ++i) + if (q.contains(*i)) + *oit++ = *i; + } }; diff --git a/Spatial_searching/include/CGAL/internal/Search_helpers.h b/Spatial_searching/include/CGAL/internal/Search_helpers.h index 782031e2c62..afa2e040b99 100644 --- a/Spatial_searching/include/CGAL/internal/Search_helpers.h +++ b/Spatial_searching/include/CGAL/internal/Search_helpers.h @@ -36,12 +36,14 @@ struct Has_points_cache; template struct Has_points_cache { - static const bool value = Tree::Enable_points_cache::value; + typedef typename Tree::Enable_points_cache type; + static const bool value = type::value; }; template struct Has_points_cache { + typedef Tag_false type; static const bool value = false; }; @@ -50,7 +52,7 @@ CGAL_GENERATE_MEMBER_DETECTOR(interruptible_transformed_distance); BOOST_MPL_HAS_XXX_TRAIT_NAMED_DEF(has_Enable_points_cache, Enable_points_cache, false) -template +template class Distance_helper { typedef typename Distance::FT FT; @@ -59,8 +61,8 @@ class Distance_helper public: - Distance_helper(Distance const& distance) - : m_distance(distance) + Distance_helper(Distance const& distance, SearchTraits const& traits) + : m_distance(distance), m_traits(traits) {} // If transformed_distance_from_coordinates does not exist in `Distance` @@ -132,13 +134,14 @@ public: Point const& p, FT stop_if_geq_to_this) { - typename SearchTraits::Construct_cartesian_const_iterator_d construct_it = m_tree.traits().construct_cartesian_const_iterator_d_object(); + typename SearchTraits::Construct_cartesian_const_iterator_d construct_it = m_traits.construct_cartesian_const_iterator_d_object(); return m_distance.interruptible_transformed_distance( q, construct_it(p), construct_it(p, 0), stop_if_geq_to_this); } private: - Distance const & m_distance; + Distance const& m_distance; + SearchTraits const& m_traits; }; // Distance_helper From 9e2a551ad776e497f054d72c60db5c0ce36903e4 Mon Sep 17 00:00:00 2001 From: Clement Jamin Date: Wed, 18 Oct 2017 11:04:00 +0200 Subject: [PATCH 024/363] Use cache (if available) in search_any_point --- Spatial_searching/include/CGAL/Kd_tree.h | 2 +- Spatial_searching/include/CGAL/Kd_tree_node.h | 67 +++++++++++++++++-- .../Orthogonal_incremental_neighbor_search.h | 4 +- .../CGAL/Orthogonal_k_neighbor_search.h | 4 +- 4 files changed, 65 insertions(+), 12 deletions(-) diff --git a/Spatial_searching/include/CGAL/Kd_tree.h b/Spatial_searching/include/CGAL/Kd_tree.h index 151536eb87b..6521532eee6 100644 --- a/Spatial_searching/include/CGAL/Kd_tree.h +++ b/Spatial_searching/include/CGAL/Kd_tree.h @@ -509,7 +509,7 @@ public: const_build(); } Kd_tree_rectangle b(*bbox); - return tree_root->search_any_point(q,b); + return tree_root->search_any_point(q,b,begin(),cache_begin(),dim_); } return boost::none; } diff --git a/Spatial_searching/include/CGAL/Kd_tree_node.h b/Spatial_searching/include/CGAL/Kd_tree_node.h index a17d3503116..0b6f10a5240 100644 --- a/Spatial_searching/include/CGAL/Kd_tree_node.h +++ b/Spatial_searching/include/CGAL/Kd_tree_node.h @@ -236,16 +236,20 @@ namespace CGAL { template boost::optional search_any_point(const FuzzyQueryItem& q, - Kd_tree_rectangle& b) const + Kd_tree_rectangle& b, + typename Kdt::const_iterator tree_points_begin, + typename std::vector::const_iterator cache_begin, + int dim) const { boost::optional result = boost::none; if (is_leaf()) { Leaf_node_const_handle node = static_cast(this); - if (node->size()>0) - for (iterator i=node->begin(); i != node->end(); i++) - if (q.contains(*i)) - { result = *i; break; } + if (node->size()>0) + { + internal::Has_points_cache::type::value>::type dummy; + result = search_any_point_in_leaf(node, q, tree_points_begin, cache_begin, dim, dummy); + } } else { Internal_node_const_handle node = @@ -258,7 +262,7 @@ namespace CGAL { result = node->lower()->any_tree_item(); }else{ if (q.inner_range_intersects(b)){ - result = node->lower()->search_any_point(q,b); + result = node->lower()->search_any_point(q,b,tree_points_begin,cache_begin,dim); } } if(result){ @@ -268,7 +272,7 @@ namespace CGAL { result = node->upper()->any_tree_item(); }else{ if (q.inner_range_intersects(b_upper)) - result = node->upper()->search_any_point(q,b_upper); + result = node->upper()->search_any_point(q,b_upper,tree_points_begin,cache_begin,dim); } } return result; @@ -332,8 +336,57 @@ namespace CGAL { Tag_false /*has_points_cache*/) const { for (iterator i = node->begin(); i != node->end(); ++i) + { if (q.contains(*i)) *oit++ = *i; + } + } + + // With cache + template + boost::optional search_any_point_in_leaf( + Leaf_node_const_handle node, + const FuzzyQueryItem &q, + typename Kdt::const_iterator tree_points_begin, + typename std::vector::const_iterator cache_begin, + int dim, + Tag_true /*has_points_cache*/) const + { + boost::optional result = boost::none; + typename Kdt::iterator it_node_point = node->begin(), it_node_point_end = node->end(); + typename std::vector::const_iterator cache_point_it = cache_begin + dim*(it_node_point - tree_points_begin); + for (; it_node_point != it_node_point_end; ++it_node_point, cache_point_it += dim) + { + Boolean_tag::value> dummy; + if (contains(q, *it_node_point, cache_point_it, cache_point_it + dim, dummy)) + { + result = *it_node_point; + break; + } + } + return result; + } + + // Without cache + template + boost::optional search_any_point_in_leaf( + Leaf_node_const_handle node, + const FuzzyQueryItem &q, + typename Kdt::const_iterator tree_points_begin, + typename std::vector::const_iterator cache_begin, + int dim, + Tag_false /*has_points_cache*/) const + { + boost::optional result = boost::none; + for (iterator i = node->begin(); i != node->end(); ++i) + { + if (q.contains(*i)) + { + result = *i; + break; + } + } + return result; } }; diff --git a/Spatial_searching/include/CGAL/Orthogonal_incremental_neighbor_search.h b/Spatial_searching/include/CGAL/Orthogonal_incremental_neighbor_search.h index 05df9d48739..b7a810e72e3 100644 --- a/Spatial_searching/include/CGAL/Orthogonal_incremental_neighbor_search.h +++ b/Spatial_searching/include/CGAL/Orthogonal_incremental_neighbor_search.h @@ -83,7 +83,7 @@ namespace CGAL { Distance_vector dists; Distance orthogonal_distance_instance; - internal::Distance_helper m_distance_helper; + internal::Distance_helper m_distance_helper; FT multiplication_factor; @@ -153,7 +153,7 @@ namespace CGAL { : traits(tree.traits()),number_of_neighbours_computed(0), number_of_internal_nodes_visited(0), number_of_leaf_nodes_visited(0), number_of_items_visited(0), orthogonal_distance_instance(tr), - m_distance_helper(orthogonal_distance_instance), + m_distance_helper(orthogonal_distance_instance, traits), multiplication_factor(orthogonal_distance_instance.transformed_distance(FT(1.0)+Eps)), query_point(q), search_nearest_neighbour(search_nearest), PriorityQueue(Priority_higher(search_nearest)), Item_PriorityQueue(Distance_smaller(search_nearest)), diff --git a/Spatial_searching/include/CGAL/Orthogonal_k_neighbor_search.h b/Spatial_searching/include/CGAL/Orthogonal_k_neighbor_search.h index a5431c7b5ec..9829267581c 100644 --- a/Spatial_searching/include/CGAL/Orthogonal_k_neighbor_search.h +++ b/Spatial_searching/include/CGAL/Orthogonal_k_neighbor_search.h @@ -46,7 +46,7 @@ public: private: typename SearchTraits::Cartesian_const_iterator_d query_object_it; - internal::Distance_helper m_distance_helper; + internal::Distance_helper m_distance_helper; std::vector dists; int m_dim; Tree const& m_tree; @@ -56,7 +56,7 @@ public: Orthogonal_k_neighbor_search(const Tree& tree, const typename Base::Query_item& q, unsigned int k=1, FT Eps=FT(0.0), bool Search_nearest=true, const Distance& d=Distance(),bool sorted=true) : Base(q,k,Eps,Search_nearest,d), - m_distance_helper(this->distance_instance), + m_distance_helper(this->distance_instance, tree.traits()), m_tree(tree) { if (tree.empty()) return; From 685d8b043e5cdbeed2bfc4b7a0022257fd27b0e3 Mon Sep 17 00:00:00 2001 From: Clement Jamin Date: Wed, 18 Oct 2017 11:11:55 +0200 Subject: [PATCH 025/363] Document the option to enable a cache + interruptible distance computation --- .../Spatial_searching/CGAL/Fuzzy_iso_box.h | 7 +++++ .../doc/Spatial_searching/CGAL/Fuzzy_sphere.h | 7 +++++ .../doc/Spatial_searching/CGAL/Kd_tree.h | 13 ++++++++- .../Concepts/FuzzyQueryItem.h | 9 +++++++ .../Concepts/GeneralDistance.h | 27 +++++++++++++++++++ .../Spatial_searching/Spatial_searching.txt | 12 +++++++++ 6 files changed, 74 insertions(+), 1 deletion(-) diff --git a/Spatial_searching/doc/Spatial_searching/CGAL/Fuzzy_iso_box.h b/Spatial_searching/doc/Spatial_searching/CGAL/Fuzzy_iso_box.h index 2366cfa35ba..7312edff28f 100644 --- a/Spatial_searching/doc/Spatial_searching/CGAL/Fuzzy_iso_box.h +++ b/Spatial_searching/doc/Spatial_searching/CGAL/Fuzzy_iso_box.h @@ -76,6 +76,13 @@ Test whether the fuzzy iso box contains `p`. */ bool contains(Point_d p) const; +/*! +Test whether the fuzzy iso box contains the point whose coordinates are contained in +the range [`begin`, `end`). +*/ +template +bool contains_point_given_as_coordinates(Coord_iterator begin, Coord_iterator end) const; + /*! Test whether the inner box intersects the rectangle associated with a node of a tree. diff --git a/Spatial_searching/doc/Spatial_searching/CGAL/Fuzzy_sphere.h b/Spatial_searching/doc/Spatial_searching/CGAL/Fuzzy_sphere.h index db3aec07db3..1988463b3d6 100644 --- a/Spatial_searching/doc/Spatial_searching/CGAL/Fuzzy_sphere.h +++ b/Spatial_searching/doc/Spatial_searching/CGAL/Fuzzy_sphere.h @@ -78,6 +78,13 @@ less than \f$ r\f$. */ bool contains(const Point_d& p) const; +/*! +Test whether the fuzzy sphere contains the point whose coordinates are contained in +the range [`begin`, `end`). +*/ +template +bool contains_point_given_as_coordinates(Coord_iterator begin, Coord_iterator end) const; + /*! Test whether the inner sphere intersects the rectangle associated with a node of a tree. diff --git a/Spatial_searching/doc/Spatial_searching/CGAL/Kd_tree.h b/Spatial_searching/doc/Spatial_searching/CGAL/Kd_tree.h index 3c7a21b94de..0303a7ba84b 100644 --- a/Spatial_searching/doc/Spatial_searching/CGAL/Kd_tree.h +++ b/Spatial_searching/doc/Spatial_searching/CGAL/Kd_tree.h @@ -14,13 +14,24 @@ It defaults to `Sliding_midpoint`. \tparam UseExtendedNode must be `Tag_true`, if the tree shall be built with extended nodes, and `Tag_false` otherwise. +\tparam EnablePointsCache can be `Tag_true` or `Tag_false`. +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 when the points +coordinates are stored in a dynamically allocated array. When +`EnablePointsCache` is set to `Tag_true`, the points +coordinates will be cached in an optimal way. This will +increase memory consumption but provide better search performance. +See also the `GeneralDistance` and `FuzzyQueryItem` concepts for +additional requirements when using such a cache. + \sa `CGAL::Kd_tree_node` \sa `CGAL::Search_traits_2` \sa `CGAL::Search_traits_3` \sa `CGAL::Search_traits` */ -template< typename Traits, typename Splitter, typename UseExtendedNode > +template< typename Traits, typename Splitter, typename UseExtendedNode, typename EnablePointsCache > class Kd_tree { public: diff --git a/Spatial_searching/doc/Spatial_searching/Concepts/FuzzyQueryItem.h b/Spatial_searching/doc/Spatial_searching/Concepts/FuzzyQueryItem.h index cc163a57e7e..8ce782c81db 100644 --- a/Spatial_searching/doc/Spatial_searching/Concepts/FuzzyQueryItem.h +++ b/Spatial_searching/doc/Spatial_searching/Concepts/FuzzyQueryItem.h @@ -40,6 +40,15 @@ Test whether the query item contains `p`. */ bool contains(Point_d p) const; +/*! +Optional: must be defined when used with a `Kd_tree` where `EnablePointsCache` +is set to `Tag_true`. +Test whether the query item contains the point whose coordinates are contained in +the range [`begin`, `end`). +*/ +template +bool contains_point_given_as_coordinates(Coord_iterator begin, Coord_iterator end) const; + /*! Test whether the inner approximation of the spatial object intersects a rectangle associated with a node of a tree. diff --git a/Spatial_searching/doc/Spatial_searching/Concepts/GeneralDistance.h b/Spatial_searching/doc/Spatial_searching/Concepts/GeneralDistance.h index d78dd827aee..e1ed793a2a2 100644 --- a/Spatial_searching/doc/Spatial_searching/Concepts/GeneralDistance.h +++ b/Spatial_searching/doc/Spatial_searching/Concepts/GeneralDistance.h @@ -49,6 +49,33 @@ Returns the transformed distance between `q` and `r`. */ FT transformed_distance(Query_item q, Point_d r); +/*! +Optional: must be defined when used with a `Kd_tree` where `EnablePointsCache` +is set to `Tag_true`. + +Returns the transformed distance between `q` and the point whose coordinates +are contained in the range [`begin`, `end`). +*/ +template +FT transformed_distance_from_coordinates( + Query_item q, Coord_iterator begin, Coord_iterator end) const; + +/*! +Optional: 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. In this function, the computation can be stopped when the +distance is going to be greater than or equal to `stop_if_geq_to_this`. In this case, +the only requirement of the return value it to be \f$ \geq \f$ `stop_if_geq_to_this`. +Note that points cache does not have to be activated to enable this optimization. + +Returns the transformed distance between `q` and the point whose coordinates +are contained in the range [`begin`, `end`), or any value \f$ \geq \f$ +`stop_if_geq_to_this` if the transformed distance is \f$ \geq \f$ `stop_if_geq_to_this`. +*/ +template +FT interruptible_transformed_distance( + Query_item q, Coord_iterator begin, Coord_iterator end, FT stop_if_geq_to_this) const; + /*! Returns the transformed distance between `q` and the point on the boundary of `r` closest to `q`. diff --git a/Spatial_searching/doc/Spatial_searching/Spatial_searching.txt b/Spatial_searching/doc/Spatial_searching/Spatial_searching.txt index 40ca743f96f..b03f6f0de88 100644 --- a/Spatial_searching/doc/Spatial_searching/Spatial_searching.txt +++ b/Spatial_searching/doc/Spatial_searching/Spatial_searching.txt @@ -498,6 +498,18 @@ instead of the distance itself. For instance for the Euclidean distance, to avoid the expensive computation of square roots, squared distances are used instead of the Euclidean distance itself. +\cgalModifBegin +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 when the points +coordinates are stored in a dynamically allocated array. In this case, +the `EnablePointsCache` template parameter of the `Kd_tree` class can be +set to `Tag_true`. The points coordinates will then be cached in an optimal +way. This will increase memory consumption but provide better search +performance. See also the `GeneralDistance` and `FuzzyQueryItem` concepts for +additional requirements when using such a cache. +\cgalModif + \section Spatial_searchingImplementationHistory Implementation History The initial implementation of this package was done by Hans Tangelder and From 1978b63fd903dd05cf37ae39f6288a7736c9b3a4 Mon Sep 17 00:00:00 2001 From: Clement Jamin Date: Wed, 18 Oct 2017 15:43:22 +0200 Subject: [PATCH 026/363] Optimize (cache+interruptible) non-orthogonal nearest/furthest neighbor search --- .../CGAL/Incremental_neighbor_search.h | 136 +++++++++++---- .../include/CGAL/K_neighbor_search.h | 164 ++++++++++++++++-- 2 files changed, 250 insertions(+), 50 deletions(-) diff --git a/Spatial_searching/include/CGAL/Incremental_neighbor_search.h b/Spatial_searching/include/CGAL/Incremental_neighbor_search.h index 603dd0100fa..12bbcd00e9f 100644 --- a/Spatial_searching/include/CGAL/Incremental_neighbor_search.h +++ b/Spatial_searching/include/CGAL/Incremental_neighbor_search.h @@ -17,20 +17,23 @@ // // // Author(s) : Hans Tangelder () +// Clement Jamin (clement.jamin.pro@gmail.com) #ifndef CGAL_INCREMENTAL_NEIGHBOR_SEARCH_H #define CGAL_INCREMENTAL_NEIGHBOR_SEARCH_H #include +#include +#include +#include +#include #include #include #include #include -#include -#include -#include +#include // for std::distance namespace CGAL { @@ -95,7 +98,7 @@ namespace CGAL { Query_item m_query; Distance m_dist; FT m_Eps; - bool m_search_nearest; + bool m_search_nearest; public: @@ -271,6 +274,9 @@ namespace CGAL { FT rd; + internal::Distance_helper m_distance_helper; + int m_dim; + Tree const& m_tree; class Priority_higher { @@ -330,7 +336,9 @@ namespace CGAL { // constructor Iterator_implementation(const Tree& tree, const Query_item& q,const Distance& tr, FT Eps, bool search_nearest) - : query_point(q), search_nearest_neighbour(search_nearest), + : query_point(q), search_nearest_neighbour(search_nearest), + m_distance_helper(tr, tree.traits()), + m_tree(tree), PriorityQueue(Priority_higher(search_nearest)), Item_PriorityQueue(Distance_smaller(search_nearest)), distance(tr), reference_count(1), number_of_internal_nodes_visited(0), @@ -338,7 +346,11 @@ namespace CGAL { number_of_neighbours_computed(0) { if (tree.empty()) return; - + + typename SearchTraits::Construct_cartesian_const_iterator_d construct_it = + m_tree.traits().construct_cartesian_const_iterator_d_object(); + m_dim = static_cast(std::distance(construct_it(q), construct_it(q, 0))); + multiplication_factor= distance.transformed_distance(FT(1)+Eps); Node_box *bounding_box = new Node_box((tree.bounding_box())); @@ -429,6 +441,86 @@ namespace CGAL { delete The_item_top; } + + template + bool search_in_leaf(typename Tree::Leaf_node_const_handle node, bool search_furthest); + + // With cache + template<> + bool search_in_leaf(typename Tree::Leaf_node_const_handle node, bool search_furthest) + { + typename Tree::iterator it_node_point = node->begin(), it_node_point_end = node->end(); + typename std::vector::const_iterator cache_point_begin = m_tree.cache_begin() + m_dim*(it_node_point - m_tree.begin()); + + for (; it_node_point != node->end(); ++it_node_point) + { + number_of_items_visited++; + FT distance_to_query_point = + m_distance_helper.transformed_distance_from_coordinates( + query_point, *it_node_point, cache_point_begin, cache_point_begin + m_dim); + + Point_with_transformed_distance *NN_Candidate = + new Point_with_transformed_distance(*it_node_point, distance_to_query_point); + Item_PriorityQueue.push(NN_Candidate); + + cache_point_begin += m_dim; + } + // old top of PriorityQueue has been processed, + // hence update rd + + bool next_neighbour_found; + if (!(PriorityQueue.empty())) + { + rd = PriorityQueue.top()->second; + next_neighbour_found = (search_furthest ? + multiplication_factor*rd < Item_PriorityQueue.top()->second + : multiplication_factor*rd > Item_PriorityQueue.top()->second); + } + else // priority queue empty => last neighbour found + { + next_neighbour_found = true; + } + + number_of_neighbours_computed++; + return next_neighbour_found; + } + + // Without cache + template<> + bool search_in_leaf(typename Tree::Leaf_node_const_handle node, bool search_furthest) + { + typename Tree::iterator it_node_point = node->begin(), it_node_point_end = node->end(); + + for (; it_node_point != node->end(); ++it_node_point) + { + number_of_items_visited++; + FT distance_to_query_point = + orthogonal_distance_instance.transformed_distance(query_point, *it_node_point); + + Point_with_transformed_distance *NN_Candidate = + new Point_with_transformed_distance(*it_node_point, distance_to_query_point); + Item_PriorityQueue.push(NN_Candidate); + } + // old top of PriorityQueue has been processed, + // hence update rd + + bool next_neighbour_found; + if (!(PriorityQueue.empty())) + { + rd = PriorityQueue.top()->second; + next_neighbour_found = (search_furthest ? + multiplication_factor*rd < Item_PriorityQueue.top()->second + : multiplication_factor*rd > Item_PriorityQueue.top()->second); + } + else // priority queue empty => last neighbour found + { + next_neighbour_found = true; + } + + number_of_neighbours_computed++; + return next_neighbour_found; + } + void Compute_the_next_nearest_neighbour() { @@ -508,36 +600,14 @@ namespace CGAL { } } delete B; - typename Tree::Leaf_node_const_handle node = + + // N is a leaf + typename Tree::Leaf_node_const_handle node = static_cast(N); number_of_leaf_nodes_visited++; if (node->size() > 0) { - for (typename Tree::iterator it = node->begin(); it != node->end(); it++) { - number_of_items_visited++; - FT distance_to_query_point= - distance.transformed_distance(query_point,*it); - Point_with_transformed_distance *NN_Candidate= - new Point_with_transformed_distance(*it,distance_to_query_point); - Item_PriorityQueue.push(NN_Candidate); - } - // old top of PriorityQueue has been processed, - // hence update rd - if (!PriorityQueue.empty()) { - rd = PriorityQueue.top()->second; - if (search_nearest_neighbour) - next_neighbour_found = - (multiplication_factor*rd > - Item_PriorityQueue.top()->second); - else - next_neighbour_found = - (multiplication_factor*rd < - Item_PriorityQueue.top()->second); - } - else // priority queue empty => last neighbour found - { - next_neighbour_found=true; - }; - number_of_neighbours_computed++; + next_neighbour_found = + search_in_leaf::type::value>::value>(node, !search_nearest_neighbour); } } // next_neighbour_found or priority queue is empty // in the latter case also the item priority queue is empty diff --git a/Spatial_searching/include/CGAL/K_neighbor_search.h b/Spatial_searching/include/CGAL/K_neighbor_search.h index bc768f48e5e..f4fe3418428 100644 --- a/Spatial_searching/include/CGAL/K_neighbor_search.h +++ b/Spatial_searching/include/CGAL/K_neighbor_search.h @@ -16,18 +16,19 @@ // $Id$ // // -// Author(s) : Hans Tangelder () +// Author(s) : Hans Tangelder (), +// Clement Jamin (clement.jamin.pro@gmail.com) #ifndef CGAL_K_NEIGHBOR_SEARCH_H #define CGAL_K_NEIGHBOR_SEARCH_H #include - #include #include +#include - +#include // for std::distance namespace CGAL { @@ -38,8 +39,10 @@ template ::type, class Splitter= Sliding_midpoint , class Tree= Kd_tree > -class K_neighbor_search: public internal::K_neighbor_search { +class K_neighbor_search: public internal::K_neighbor_search +{ typedef internal::K_neighbor_search Base; + typedef typename Tree::Point_d Point; public: typedef typename Base::FT FT; @@ -47,9 +50,17 @@ public: K_neighbor_search(const Tree& tree, const typename Base::Query_item& q, unsigned int k=1, FT Eps=FT(0.0), bool Search_nearest=true, const Distance& d=Distance(),bool sorted=true) - : Base(q,k,Eps,Search_nearest,d) + : Base(q,k,Eps,Search_nearest,d), + m_distance_helper(this->distance_instance, tree.traits()), + m_tree(tree) { if (tree.empty()) return; + + typename SearchTraits::Construct_cartesian_const_iterator_d construct_it = + m_tree.traits().construct_cartesian_const_iterator_d_object(); + m_dim = static_cast(std::distance( + construct_it(this->query_object), construct_it(this->query_object, 0))); + compute_neighbors_general(tree.root(),tree.bounding_box()); if (sorted) this->queue.sort(); }; @@ -58,6 +69,10 @@ private: typedef typename Base::Node_const_handle Node_const_handle; using Base::branch; + internal::Distance_helper m_distance_helper; + int m_dim; + Tree const& m_tree; + void compute_neighbors_general(typename Base::Node_const_handle N, const Kd_tree_rectangle& r) { @@ -122,21 +137,136 @@ private: } else + { + // n is a leaf + typename Tree::Leaf_node_const_handle node = + static_cast(N); + this->number_of_leaf_nodes_visited++; + if (node->size() > 0) { - // n is a leaf - typename Tree::Leaf_node_const_handle node = - static_cast(N); - this->number_of_leaf_nodes_visited++; - if (node->size() > 0) - for (typename Tree::iterator it = node->begin(); it != node->end(); it++) { - this->number_of_items_visited++; - FT distance_to_query_object = - this->distance_instance.transformed_distance(this->query_object,*it); - this->queue.insert(std::make_pair(&(*it),distance_to_query_object)); - } + if (this->search_nearest) + search_nearest_in_leaf::type::value>::value>(node); + else + search_furthest_in_leaf::type::value>::value>(node); } + } } - + + template + void search_nearest_in_leaf(typename Tree::Leaf_node_const_handle node); + + // With cache + template<> + void search_nearest_in_leaf(typename Tree::Leaf_node_const_handle node) + { + typename Tree::iterator it_node_point = node->begin(), it_node_point_end = node->end(); + typename std::vector::const_iterator cache_point_begin = m_tree.cache_begin() + m_dim*(it_node_point - m_tree.begin()); + // As long as the queue is not full, the node is just inserted + for (; !this->queue.full() && it_node_point != it_node_point_end; ++it_node_point) + { + this->number_of_items_visited++; + + FT distance_to_query_object = + m_distance_helper.transformed_distance_from_coordinates( + this->query_object, *it_node_point, cache_point_begin, cache_point_begin + m_dim); + this->queue.insert(std::make_pair(&(*it_node_point), distance_to_query_object)); + + cache_point_begin += m_dim; + } + // Now that the queue is full, we can gain time by keeping track + // of the current worst distance to interrupt the distance computation earlier + FT worst_dist = this->queue.top().second; + for (; it_node_point != it_node_point_end; ++it_node_point) + { + this->number_of_items_visited++; + + FT distance_to_query_object = + m_distance_helper.interruptible_transformed_distance( + this->query_object, *it_node_point, cache_point_begin, cache_point_begin + m_dim, worst_dist); + + if (distance_to_query_object < worst_dist) + { + this->queue.insert(std::make_pair(&(*it_node_point), distance_to_query_object)); + worst_dist = this->queue.top().second; + } + + cache_point_begin += m_dim; + } + } + + // Without cache + template<> + void search_nearest_in_leaf(typename Tree::Leaf_node_const_handle node) + { + typename Tree::iterator it_node_point = node->begin(), it_node_point_end = node->end(); + // As long as the queue is not full, the node is just inserted + for (; !this->queue.full() && it_node_point != it_node_point_end; ++it_node_point) + { + this->number_of_items_visited++; + + FT distance_to_query_object = + this->distance_instance.transformed_distance(this->query_object, *it_node_point); + this->queue.insert(std::make_pair(&(*it_node_point), distance_to_query_object)); + } + // Now that the queue is full, we can gain time by keeping track + // of the current worst distance to interrupt the distance computation earlier + FT worst_dist = this->queue.top().second; + for (; it_node_point != it_node_point_end; ++it_node_point) + { + this->number_of_items_visited++; + + FT distance_to_query_object = + m_distance_helper.interruptible_transformed_distance( + this->query_object, *it_node_point, worst_dist); + + if (distance_to_query_object < worst_dist) + { + this->queue.insert(std::make_pair(&(*it_node_point), distance_to_query_object)); + worst_dist = this->queue.top().second; + } + } + } + + + template + void search_furthest_in_leaf(typename Tree::Leaf_node_const_handle node); + + // With cache + template<> + void search_furthest_in_leaf(typename Tree::Leaf_node_const_handle node) + { + typename Tree::iterator it_node_point = node->begin(), it_node_point_end = node->end(); + typename std::vector::const_iterator cache_point_begin = m_tree.cache_begin() + m_dim*(it_node_point - m_tree.begin()); + // In furthest search mode, the interruptible distance cannot be used to optimize + for (; it_node_point != it_node_point_end; ++it_node_point) + { + this->number_of_items_visited++; + + FT distance_to_query_object = + m_distance_helper.transformed_distance_from_coordinates( + this->query_object, *it_node_point, cache_point_begin, cache_point_begin + m_dim); + this->queue.insert(std::make_pair(&(*it_node_point), distance_to_query_object)); + + cache_point_begin += m_dim; + } + } + + // Without cache + template<> + void search_furthest_in_leaf(typename Tree::Leaf_node_const_handle node) + { + typename Tree::iterator it_node_point = node->begin(), it_node_point_end = node->end(); + // In furthest search mode, the interruptible distance cannot be used to optimize + for (; it_node_point != it_node_point_end; ++it_node_point) + { + this->number_of_items_visited++; + + FT distance_to_query_object = + this->distance_instance.transformed_distance(this->query_object, *it_node_point); + this->queue.insert(std::make_pair(&(*it_node_point), distance_to_query_object)); + } + } + }; // class } // namespace CGAL From e61e724312a76086d0e9c8814d6708885586448f Mon Sep 17 00:00:00 2001 From: Clement Jamin Date: Wed, 18 Oct 2017 15:44:07 +0200 Subject: [PATCH 027/363] Missing include + fix initialization order --- .../Orthogonal_incremental_neighbor_search.h | 16 ++++++++-------- .../include/CGAL/Orthogonal_k_neighbor_search.h | 3 ++- 2 files changed, 10 insertions(+), 9 deletions(-) diff --git a/Spatial_searching/include/CGAL/Orthogonal_incremental_neighbor_search.h b/Spatial_searching/include/CGAL/Orthogonal_incremental_neighbor_search.h index b7a810e72e3..46d505724d9 100644 --- a/Spatial_searching/include/CGAL/Orthogonal_incremental_neighbor_search.h +++ b/Spatial_searching/include/CGAL/Orthogonal_incremental_neighbor_search.h @@ -24,16 +24,16 @@ #include +#include +#include +#include +#include #include #include #include #include -#include -#include -#include - -#include +#include // for std::distance namespace CGAL { @@ -155,10 +155,10 @@ namespace CGAL { orthogonal_distance_instance(tr), m_distance_helper(orthogonal_distance_instance, traits), multiplication_factor(orthogonal_distance_instance.transformed_distance(FT(1.0)+Eps)), - query_point(q), search_nearest_neighbour(search_nearest), + query_point(q), search_nearest_neighbour(search_nearest), + m_tree(tree), PriorityQueue(Priority_higher(search_nearest)), Item_PriorityQueue(Distance_smaller(search_nearest)), - reference_count(1), - m_tree(tree) + reference_count(1) { diff --git a/Spatial_searching/include/CGAL/Orthogonal_k_neighbor_search.h b/Spatial_searching/include/CGAL/Orthogonal_k_neighbor_search.h index 9829267581c..d1492c4f655 100644 --- a/Spatial_searching/include/CGAL/Orthogonal_k_neighbor_search.h +++ b/Spatial_searching/include/CGAL/Orthogonal_k_neighbor_search.h @@ -25,10 +25,11 @@ #include - #include #include +#include // for std::distance + namespace CGAL { template Date: Fri, 20 Oct 2017 11:52:31 +0200 Subject: [PATCH 028/363] Document changes to Euclidean_distance + minor fixes --- .../Spatial_searching/CGAL/Euclidean_distance.h | 17 +++++++++++++++++ .../Concepts/GeneralDistance.h | 2 +- .../doc/Spatial_searching/Spatial_searching.txt | 2 +- 3 files changed, 19 insertions(+), 2 deletions(-) diff --git a/Spatial_searching/doc/Spatial_searching/CGAL/Euclidean_distance.h b/Spatial_searching/doc/Spatial_searching/CGAL/Euclidean_distance.h index 5c6388c92b8..19be873afa0 100644 --- a/Spatial_searching/doc/Spatial_searching/CGAL/Euclidean_distance.h +++ b/Spatial_searching/doc/Spatial_searching/CGAL/Euclidean_distance.h @@ -64,6 +64,23 @@ Returns the squared Euclidean distance between `q` and `p`. */ FT transformed_distance(Query_item q, Point_d p) const; +/*! +Returns the transformed distance between `q` and the point whose coordinates +are contained in the range [`begin`, `end`). +*/ +template +FT transformed_distance_from_coordinates( + Query_item q, Coord_iterator begin, Coord_iterator end) const; + +/*! +Returns the transformed distance between `q` and the point whose coordinates +are contained in the range [`begin`, `end`), or any value \f$ \geq \f$ +`stop_if_geq_to_this` if the transformed distance is \f$ \geq \f$ `stop_if_geq_to_this`. +*/ +template +FT interruptible_transformed_distance( + Query_item q, Coord_iterator begin, Coord_iterator end, FT stop_if_geq_to_this) const; + /*! Returns the squared Euclidean distance between `q` and the point on the boundary of `r` closest to `q`. diff --git a/Spatial_searching/doc/Spatial_searching/Concepts/GeneralDistance.h b/Spatial_searching/doc/Spatial_searching/Concepts/GeneralDistance.h index e1ed793a2a2..e4da5982357 100644 --- a/Spatial_searching/doc/Spatial_searching/Concepts/GeneralDistance.h +++ b/Spatial_searching/doc/Spatial_searching/Concepts/GeneralDistance.h @@ -61,7 +61,7 @@ FT transformed_distance_from_coordinates( Query_item q, Coord_iterator begin, Coord_iterator end) const; /*! -Optional: in most cases (e.g. Euclidean distance), the distance computation +Optional: 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. In this function, the computation can be stopped when the distance is going to be greater than or equal to `stop_if_geq_to_this`. In this case, diff --git a/Spatial_searching/doc/Spatial_searching/Spatial_searching.txt b/Spatial_searching/doc/Spatial_searching/Spatial_searching.txt index b03f6f0de88..0ba5d9e6f38 100644 --- a/Spatial_searching/doc/Spatial_searching/Spatial_searching.txt +++ b/Spatial_searching/doc/Spatial_searching/Spatial_searching.txt @@ -508,7 +508,7 @@ set to `Tag_true`. The points coordinates will then be cached in an optimal way. This will increase memory consumption but provide better search performance. See also the `GeneralDistance` and `FuzzyQueryItem` concepts for additional requirements when using such a cache. -\cgalModif +\cgalModifEnd \section Spatial_searchingImplementationHistory Implementation History From 01997ce4c30e039e3409f56587c5f65cb4b8fc72 Mon Sep 17 00:00:00 2001 From: Clement Jamin Date: Fri, 20 Oct 2017 15:11:02 +0200 Subject: [PATCH 029/363] Updated changes.html --- Installation/changes.html | 26 +++++++++++++++++++++++++- 1 file changed, 25 insertions(+), 1 deletion(-) diff --git a/Installation/changes.html b/Installation/changes.html index e173b39b5e1..3cc60d2dca9 100644 --- a/Installation/changes.html +++ b/Installation/changes.html @@ -1,4 +1,4 @@ - + @@ -187,6 +187,30 @@ and src/ directories). other types of input than the RANSAC output. +

dD Spatial Searching

+
    +
  • + Improved the performance of the kd-tree in some cases:
    + 1. Not storing the points coordinates inside the tree usually + generates a lot of cache misses, leading to non-optimal + performance. This is the case when indices are stored inside + the tree, or when the points coordinates are stored in a + dynamically allocated array (e.g., CGAL::Epick_d + with dynamic dimension). + In this case, 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 provide better search performance. See the updated + GeneralDistance and FuzzyQueryItem + concepts for additional requirements when using such a cache. + 2. 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. +
  • +
From 878905ac086b39e42c812e36540502c72d980321 Mon Sep 17 00:00:00 2001 From: Clement Jamin Date: Fri, 20 Oct 2017 15:11:22 +0200 Subject: [PATCH 030/363] Improved doc --- .../doc/Spatial_searching/Spatial_searching.txt | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/Spatial_searching/doc/Spatial_searching/Spatial_searching.txt b/Spatial_searching/doc/Spatial_searching/Spatial_searching.txt index 0ba5d9e6f38..121dd383ed2 100644 --- a/Spatial_searching/doc/Spatial_searching/Spatial_searching.txt +++ b/Spatial_searching/doc/Spatial_searching/Spatial_searching.txt @@ -501,8 +501,9 @@ distances are used instead of the Euclidean distance itself. \cgalModifBegin 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 when the points -coordinates are stored in a dynamically allocated array. In this case, +when indices are stored inside the tree, or when the points +coordinates are stored in a dynamically allocated array (e.g., `Epick_d` +with dynamic dimension). In this case, the `EnablePointsCache` template parameter of the `Kd_tree` class can be set to `Tag_true`. The points coordinates will then be cached in an optimal way. This will increase memory consumption but provide better search From b352c90b11e943a34ce93272fdec08c0a1870d68 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9bastien=20Loriot?= Date: Fri, 20 Oct 2017 22:34:07 +0200 Subject: [PATCH 031/363] add missing include directive for license checking --- Spatial_searching/include/CGAL/internal/Search_helpers.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Spatial_searching/include/CGAL/internal/Search_helpers.h b/Spatial_searching/include/CGAL/internal/Search_helpers.h index afa2e040b99..99e58484584 100644 --- a/Spatial_searching/include/CGAL/internal/Search_helpers.h +++ b/Spatial_searching/include/CGAL/internal/Search_helpers.h @@ -21,6 +21,8 @@ #ifndef CGAL_INTERNAL_SEARCH_HELPERS_H #define CGAL_INTERNAL_SEARCH_HELPERS_H +#include + #include #include From 0d351a1750eb5909722babc457dd2e9c7500fefc Mon Sep 17 00:00:00 2001 From: Clement Jamin Date: Sat, 21 Oct 2017 08:17:24 +0200 Subject: [PATCH 032/363] Fix typo --- Installation/changes.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Installation/changes.html b/Installation/changes.html index 3cc60d2dca9..99096ba6b1f 100644 --- a/Installation/changes.html +++ b/Installation/changes.html @@ -201,7 +201,7 @@ and src/ directories). 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 provide better search performance. See the updated + consumption but provides better search performance. See the updated GeneralDistance and FuzzyQueryItem concepts for additional requirements when using such a cache. 2. In most cases (e.g., Euclidean distance), the distance computation From 9f3df944afe5c973e9e5c64822cd97ab0c1a8212 Mon Sep 17 00:00:00 2001 From: Clement Jamin Date: Tue, 24 Oct 2017 14:40:08 +0200 Subject: [PATCH 033/363] Fix already-existing bugs in the doc --- .../doc/Spatial_searching/CGAL/K_neighbor_search.h | 5 ++++- .../Spatial_searching/CGAL/Orthogonal_k_neighbor_search.h | 4 +--- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/Spatial_searching/doc/Spatial_searching/CGAL/K_neighbor_search.h b/Spatial_searching/doc/Spatial_searching/CGAL/K_neighbor_search.h index 25704b43517..fbe80dd9a00 100644 --- a/Spatial_searching/doc/Spatial_searching/CGAL/K_neighbor_search.h +++ b/Spatial_searching/doc/Spatial_searching/CGAL/K_neighbor_search.h @@ -11,12 +11,15 @@ extended or unextended nodes. \tparam Traits must be an implementation of the concept `SearchTraits`, for example `Simple_cartesian`. -\tparam Splitter must be a model of the +\tparam GeneralDistance must be a model of the concept `GeneralDistance`. If `Traits` is `Search_traits_adapter` the default type is `Distance_adapter >`, and `Euclidean_distance` otherwise. +\tparam Splitter must be a model of the concept `Splitter`. +The default type is `Sliding_midpoint`. + \tparam SpatialTree must be an implementation of the concept `SpatialTree`. The default type is `Kd_tree`. The template argument `Tag_false` makes that the tree is built with unextended nodes. diff --git a/Spatial_searching/doc/Spatial_searching/CGAL/Orthogonal_k_neighbor_search.h b/Spatial_searching/doc/Spatial_searching/CGAL/Orthogonal_k_neighbor_search.h index 5656a07bf1c..61039c37646 100644 --- a/Spatial_searching/doc/Spatial_searching/CGAL/Orthogonal_k_neighbor_search.h +++ b/Spatial_searching/doc/Spatial_searching/CGAL/Orthogonal_k_neighbor_search.h @@ -14,9 +14,7 @@ for example `Search_traits_2 >`. concept `OrthogonalDistance`. If `Traits` is `Search_traits_adapter` the default type is `Distance_adapter >`, -and `Euclidean_distance` otherwise. - -The default type is `Euclidean_distance`. +and `Euclidean_distance` otherwise. \tparam Splitter must be a model of the concept `Splitter`. The default type is `Sliding_midpoint`. From 35563ebe73cd1f6bca1b6ed788b495d7a1e4bfd9 Mon Sep 17 00:00:00 2001 From: Clement Jamin Date: Tue, 24 Oct 2017 14:48:44 +0200 Subject: [PATCH 034/363] Fix numbered list --- Installation/changes.html | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/Installation/changes.html b/Installation/changes.html index 99096ba6b1f..9e31e8d04ec 100644 --- a/Installation/changes.html +++ b/Installation/changes.html @@ -191,7 +191,8 @@ and src/ directories).
  • Improved the performance of the kd-tree in some cases:
    - 1. Not storing the points coordinates inside the tree usually +
      +
    1. Not storing the points coordinates inside the tree usually generates a lot of cache misses, leading to non-optimal performance. This is the case when indices are stored inside the tree, or when the points coordinates are stored in a @@ -204,11 +205,14 @@ and src/ directories). consumption but provides better search performance. See the updated GeneralDistance and FuzzyQueryItem concepts for additional requirements when using such a cache. - 2. In most cases (e.g., Euclidean distance), the distance computation +
    2. +
    3. 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. +
    4. +
From 204efcc3f9b70658334d631e39312f75d2902051 Mon Sep 17 00:00:00 2001 From: Clement Jamin Date: Fri, 10 Nov 2017 11:43:11 +0100 Subject: [PATCH 035/363] Clarify doc --- Installation/changes.html | 11 +++++++---- .../doc/Spatial_searching/CGAL/Kd_tree.h | 10 +++++++--- .../doc/Spatial_searching/Spatial_searching.txt | 12 ++++++++---- 3 files changed, 22 insertions(+), 11 deletions(-) diff --git a/Installation/changes.html b/Installation/changes.html index 9e31e8d04ec..0bae04bd252 100644 --- a/Installation/changes.html +++ b/Installation/changes.html @@ -194,10 +194,13 @@ and src/ directories).
  1. Not storing the points coordinates inside the tree usually generates a lot of cache misses, leading to non-optimal - performance. This is the case when indices are stored inside - the tree, or when the points coordinates are stored in a - dynamically allocated array (e.g., CGAL::Epick_d - with dynamic dimension). + 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 this case, the new EnablePointsCache template parameter of the CGAL::Kd_tree class can be set to CGAL::Tag_true. The points coordinates diff --git a/Spatial_searching/doc/Spatial_searching/CGAL/Kd_tree.h b/Spatial_searching/doc/Spatial_searching/CGAL/Kd_tree.h index 0303a7ba84b..9a86c03e7fe 100644 --- a/Spatial_searching/doc/Spatial_searching/CGAL/Kd_tree.h +++ b/Spatial_searching/doc/Spatial_searching/CGAL/Kd_tree.h @@ -17,9 +17,13 @@ tree shall be built with extended nodes, and `Tag_false` otherwise. \tparam EnablePointsCache can be `Tag_true` or `Tag_false`. 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 when the points -coordinates are stored in a dynamically allocated array. When -`EnablePointsCache` is set to `Tag_true`, the points +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. When EnablePointsCache` is set to `Tag_true`, the points coordinates will be cached in an optimal way. This will increase memory consumption but provide better search performance. See also the `GeneralDistance` and `FuzzyQueryItem` concepts for diff --git a/Spatial_searching/doc/Spatial_searching/Spatial_searching.txt b/Spatial_searching/doc/Spatial_searching/Spatial_searching.txt index 121dd383ed2..37c197ebdd2 100644 --- a/Spatial_searching/doc/Spatial_searching/Spatial_searching.txt +++ b/Spatial_searching/doc/Spatial_searching/Spatial_searching.txt @@ -501,10 +501,14 @@ distances are used instead of the Euclidean distance itself. \cgalModifBegin Not storing the points coordinates inside the tree usually generates a lot of cache misses, leading to non-optimal performance. This is the case -when indices are stored inside the tree, or when the points -coordinates are stored in a dynamically allocated array (e.g., `Epick_d` -with dynamic dimension). In this case, -the `EnablePointsCache` template parameter of the `Kd_tree` class can be +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 this case, the `EnablePointsCache` template parameter of the `Kd_tree` class can be set to `Tag_true`. The points coordinates will then be cached in an optimal way. This will increase memory consumption but provide better search performance. See also the `GeneralDistance` and `FuzzyQueryItem` concepts for From 63af2a0b7349922fd17f8b9d4806889606200402 Mon Sep 17 00:00:00 2001 From: Clement Jamin Date: Tue, 14 Nov 2017 11:02:48 +0100 Subject: [PATCH 036/363] Fix: inappropriate typename --- .../include/CGAL/internal/Search_helpers.h | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/Spatial_searching/include/CGAL/internal/Search_helpers.h b/Spatial_searching/include/CGAL/internal/Search_helpers.h index 99e58484584..0c833f587ec 100644 --- a/Spatial_searching/include/CGAL/internal/Search_helpers.h +++ b/Spatial_searching/include/CGAL/internal/Search_helpers.h @@ -71,7 +71,7 @@ public: template ::value> FT transformed_distance_from_coordinates( - const typename Query_item& q, + const Query_item& q, Point const& p, typename std::vector::const_iterator it_coord_begin, typename std::vector::const_iterator it_coord_end) @@ -82,7 +82,7 @@ public: template <> FT transformed_distance_from_coordinates( - const typename Query_item& q, + const Query_item& q, Point const& p, typename std::vector::const_iterator it_coord_begin, typename std::vector::const_iterator it_coord_end) @@ -95,7 +95,7 @@ public: template ::value> FT interruptible_transformed_distance( - const typename Query_item& q, + const Query_item& q, Point const& p, typename std::vector::const_iterator it_coord_begin, typename std::vector::const_iterator it_coord_end, @@ -107,7 +107,7 @@ public: template <> FT interruptible_transformed_distance( - const typename Query_item& q, + const Query_item& q, Point const& p, typename std::vector::const_iterator it_coord_begin, typename std::vector::const_iterator it_coord_end, @@ -122,7 +122,7 @@ public: template ::value> FT interruptible_transformed_distance( - const typename Query_item& q, + const Query_item& q, Point const& p, FT) { @@ -132,7 +132,7 @@ public: template <> FT interruptible_transformed_distance( - const typename Query_item& q, + const Query_item& q, Point const& p, FT stop_if_geq_to_this) { From 05af5bf40873f56ec200db9ff354ed01de3bdf0a Mon Sep 17 00:00:00 2001 From: Clement Jamin Date: Wed, 15 Nov 2017 12:47:40 +0100 Subject: [PATCH 037/363] Typo --- Installation/changes.html | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Installation/changes.html b/Installation/changes.html index 0bae04bd252..9303aadf256 100644 --- a/Installation/changes.html +++ b/Installation/changes.html @@ -201,14 +201,14 @@ and src/ directories). 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 this case, the new EnablePointsCache template parameter of the - CGAL::Kd_tree class can be set to + 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. -
  2. +
  3. 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) From 00f989da6c71d03b44f2dc0c7ac6039a45af55c2 Mon Sep 17 00:00:00 2001 From: Clement Jamin Date: Wed, 15 Nov 2017 12:49:48 +0100 Subject: [PATCH 038/363] Another small fix --- Installation/changes.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Installation/changes.html b/Installation/changes.html index 9303aadf256..44785fd99bd 100644 --- a/Installation/changes.html +++ b/Installation/changes.html @@ -196,7 +196,7 @@ and src/ directories). 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` + 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 From 5e6bb38fff956909a29f0d78502dbfc23fc0b040 Mon Sep 17 00:00:00 2001 From: Clement Jamin Date: Wed, 15 Nov 2017 14:09:16 +0100 Subject: [PATCH 039/363] Doc: use "Cartesian coordinates" instead of just "coordinates" --- .../doc/Spatial_searching/CGAL/Euclidean_distance.h | 11 ++++++----- .../doc/Spatial_searching/CGAL/Fuzzy_iso_box.h | 4 ++-- .../doc/Spatial_searching/CGAL/Fuzzy_sphere.h | 4 ++-- .../doc/Spatial_searching/Concepts/FuzzyQueryItem.h | 4 ++-- .../doc/Spatial_searching/Concepts/GeneralDistance.h | 11 ++++++----- 5 files changed, 18 insertions(+), 16 deletions(-) diff --git a/Spatial_searching/doc/Spatial_searching/CGAL/Euclidean_distance.h b/Spatial_searching/doc/Spatial_searching/CGAL/Euclidean_distance.h index 19be873afa0..6f57a8454f4 100644 --- a/Spatial_searching/doc/Spatial_searching/CGAL/Euclidean_distance.h +++ b/Spatial_searching/doc/Spatial_searching/CGAL/Euclidean_distance.h @@ -65,17 +65,18 @@ Returns the squared Euclidean distance between `q` and `p`. FT transformed_distance(Query_item q, Point_d p) const; /*! -Returns the transformed distance between `q` and the point whose coordinates -are contained in the range [`begin`, `end`). +Returns the transformed distance between `q` and the point whose Cartesian +coordinates are contained in the range [`begin`, `end`). */ template FT transformed_distance_from_coordinates( Query_item q, Coord_iterator begin, Coord_iterator end) const; /*! -Returns the transformed distance between `q` and the point whose coordinates -are contained in the range [`begin`, `end`), or any value \f$ \geq \f$ -`stop_if_geq_to_this` if the transformed distance is \f$ \geq \f$ `stop_if_geq_to_this`. +Returns the transformed distance between `q` and the point whose Cartesian +coordinates are contained in the range [`begin`, `end`), or any value +\f$ \geq \f$ `stop_if_geq_to_this` if the transformed distance is +\f$ \geq \f$ `stop_if_geq_to_this`. */ template FT interruptible_transformed_distance( diff --git a/Spatial_searching/doc/Spatial_searching/CGAL/Fuzzy_iso_box.h b/Spatial_searching/doc/Spatial_searching/CGAL/Fuzzy_iso_box.h index 7312edff28f..1e583f5c38c 100644 --- a/Spatial_searching/doc/Spatial_searching/CGAL/Fuzzy_iso_box.h +++ b/Spatial_searching/doc/Spatial_searching/CGAL/Fuzzy_iso_box.h @@ -77,8 +77,8 @@ Test whether the fuzzy iso box contains `p`. bool contains(Point_d p) const; /*! -Test whether the fuzzy iso box contains the point whose coordinates are contained in -the range [`begin`, `end`). +Test whether the fuzzy iso box contains the point whose Cartesian +coordinates are contained in the range [`begin`, `end`). */ template bool contains_point_given_as_coordinates(Coord_iterator begin, Coord_iterator end) const; diff --git a/Spatial_searching/doc/Spatial_searching/CGAL/Fuzzy_sphere.h b/Spatial_searching/doc/Spatial_searching/CGAL/Fuzzy_sphere.h index 1988463b3d6..64ef3ba6a9c 100644 --- a/Spatial_searching/doc/Spatial_searching/CGAL/Fuzzy_sphere.h +++ b/Spatial_searching/doc/Spatial_searching/CGAL/Fuzzy_sphere.h @@ -79,8 +79,8 @@ less than \f$ r\f$. bool contains(const Point_d& p) const; /*! -Test whether the fuzzy sphere contains the point whose coordinates are contained in -the range [`begin`, `end`). +Test whether the fuzzy sphere contains the point whose Cartesian coordinates +are contained in the range [`begin`, `end`). */ template bool contains_point_given_as_coordinates(Coord_iterator begin, Coord_iterator end) const; diff --git a/Spatial_searching/doc/Spatial_searching/Concepts/FuzzyQueryItem.h b/Spatial_searching/doc/Spatial_searching/Concepts/FuzzyQueryItem.h index 8ce782c81db..de33e1e8140 100644 --- a/Spatial_searching/doc/Spatial_searching/Concepts/FuzzyQueryItem.h +++ b/Spatial_searching/doc/Spatial_searching/Concepts/FuzzyQueryItem.h @@ -43,8 +43,8 @@ bool contains(Point_d p) const; /*! Optional: must be defined when used with a `Kd_tree` where `EnablePointsCache` is set to `Tag_true`. -Test whether the query item contains the point whose coordinates are contained in -the range [`begin`, `end`). +Test whether the query item contains the point whose Cartesian coordinates +are contained in the range [`begin`, `end`). */ template bool contains_point_given_as_coordinates(Coord_iterator begin, Coord_iterator end) const; diff --git a/Spatial_searching/doc/Spatial_searching/Concepts/GeneralDistance.h b/Spatial_searching/doc/Spatial_searching/Concepts/GeneralDistance.h index e4da5982357..647f719e25a 100644 --- a/Spatial_searching/doc/Spatial_searching/Concepts/GeneralDistance.h +++ b/Spatial_searching/doc/Spatial_searching/Concepts/GeneralDistance.h @@ -53,8 +53,8 @@ FT transformed_distance(Query_item q, Point_d r); Optional: must be defined when used with a `Kd_tree` where `EnablePointsCache` is set to `Tag_true`. -Returns the transformed distance between `q` and the point whose coordinates -are contained in the range [`begin`, `end`). +Returns the transformed distance between `q` and the point whose Cartesian +coordinates are contained in the range [`begin`, `end`). */ template FT transformed_distance_from_coordinates( @@ -68,9 +68,10 @@ distance is going to be greater than or equal to `stop_if_geq_to_this`. In this the only requirement of the return value it to be \f$ \geq \f$ `stop_if_geq_to_this`. Note that points cache does not have to be activated to enable this optimization. -Returns the transformed distance between `q` and the point whose coordinates -are contained in the range [`begin`, `end`), or any value \f$ \geq \f$ -`stop_if_geq_to_this` if the transformed distance is \f$ \geq \f$ `stop_if_geq_to_this`. +Returns the transformed distance between `q` and the point whose Cartesian +coordinates are contained in the range [`begin`, `end`), or any value +\f$ \geq \f$ `stop_if_geq_to_this` if the transformed distance is +\f$ \geq \f$ `stop_if_geq_to_this`. */ template FT interruptible_transformed_distance( From bc5a5c22650121f195cef2af033cc1a2b1065867 Mon Sep 17 00:00:00 2001 From: Clement Jamin Date: Thu, 16 Nov 2017 16:46:05 +0100 Subject: [PATCH 040/363] Fix code so that it compiles on Linux --- .../include/CGAL/internal/Search_helpers.h | 193 ++++++++++++------ 1 file changed, 135 insertions(+), 58 deletions(-) diff --git a/Spatial_searching/include/CGAL/internal/Search_helpers.h b/Spatial_searching/include/CGAL/internal/Search_helpers.h index 0c833f587ec..a7e45b25e3a 100644 --- a/Spatial_searching/include/CGAL/internal/Search_helpers.h +++ b/Spatial_searching/include/CGAL/internal/Search_helpers.h @@ -64,11 +64,9 @@ class Distance_helper public: Distance_helper(Distance const& distance, SearchTraits const& traits) - : m_distance(distance), m_traits(traits) + : m_distance(distance), m_tdfc(m_distance), m_itd(traits, distance, m_tdfc) {} - // If transformed_distance_from_coordinates does not exist in `Distance` - template ::value> FT transformed_distance_from_coordinates( const Query_item& q, @@ -76,75 +74,154 @@ public: typename std::vector::const_iterator it_coord_begin, typename std::vector::const_iterator it_coord_end) { - return m_distance.transformed_distance(q, p); - } - // ... or if it exists - template <> - FT - transformed_distance_from_coordinates( - const Query_item& q, - Point const& p, - typename std::vector::const_iterator it_coord_begin, - typename std::vector::const_iterator it_coord_end) - { - return m_distance.transformed_distance_from_coordinates(q, it_coord_begin, it_coord_end); + return m_tdfc(q, p, it_coord_begin, it_coord_end); + } + + FT + interruptible_transformed_distance( + const Query_item& q, + Point const& p, + FT stop_if_geq_to_this) + { + return m_itd(q, p, stop_if_geq_to_this); } - // *** Version with cache *** - // If interruptible_transformed_distance does not exist in `Distance` - template ::value> FT interruptible_transformed_distance( - const Query_item& q, - Point const& p, - typename std::vector::const_iterator it_coord_begin, - typename std::vector::const_iterator it_coord_end, - FT) - { - return transformed_distance_from_coordinates(q, p, it_coord_begin, it_coord_end); - } - // ... or if it exists - template <> - FT - interruptible_transformed_distance( const Query_item& q, Point const& p, typename std::vector::const_iterator it_coord_begin, typename std::vector::const_iterator it_coord_end, FT stop_if_geq_to_this) { - return m_distance.interruptible_transformed_distance( - q, it_coord_begin, it_coord_end, stop_if_geq_to_this); - } - - // *** Version without cache *** - // If interruptible_transformed_distance does not exist in `Distance` - template ::value> - FT - interruptible_transformed_distance( - const Query_item& q, - Point const& p, - FT) - { - return m_distance.transformed_distance(q, p); - } - // ... or if it exists - template <> - FT - interruptible_transformed_distance( - const Query_item& q, - Point const& p, - FT stop_if_geq_to_this) - { - typename SearchTraits::Construct_cartesian_const_iterator_d construct_it = m_traits.construct_cartesian_const_iterator_d_object(); - return m_distance.interruptible_transformed_distance( - q, construct_it(p), construct_it(p, 0), stop_if_geq_to_this); + return m_itd(q, p, it_coord_begin, it_coord_end, stop_if_geq_to_this); } private: - Distance const& m_distance; - SearchTraits const& m_traits; + // If transformed_distance_from_coordinates does not exist in `Distance` + template + class Transformed_distance_from_coordinates + { + public: + Transformed_distance_from_coordinates(Distance const& distance) + : m_distance(distance) + {} + + FT operator() ( + const Query_item& q, + Point const& p, + typename std::vector::const_iterator it_coord_begin, + typename std::vector::const_iterator it_coord_end) const + { + return m_distance.transformed_distance(q, p); + } + + private: + Distance const& m_distance; + }; + // ... or if it exists + template <> + class Transformed_distance_from_coordinates + { + public: + Transformed_distance_from_coordinates(Distance const& distance) + : m_distance(distance) + {} + + FT operator() ( + const Query_item& q, + Point const& p, + typename std::vector::const_iterator it_coord_begin, + typename std::vector::const_iterator it_coord_end) const + { + return m_distance.transformed_distance_from_coordinates(q, it_coord_begin, it_coord_end); + } + + private: + Distance const& m_distance; + }; + + // If interruptible_transformed_distance does not exist in `Distance` + template + class Interruptible_transformed_distance + { + public: + typedef Transformed_distance_from_coordinates< + has_transformed_distance_from_coordinates::value> Tdfc; + + Interruptible_transformed_distance( + SearchTraits const&, Distance const& distance, Tdfc const& tdfc) + : m_distance(distance), m_ref_to_tdfc(tdfc) + {} + + FT operator() ( + const Query_item& q, + Point const& p, + FT) const + { + return m_distance.transformed_distance(q, p); + } + + FT operator() ( + const Query_item& q, + Point const& p, + typename std::vector::const_iterator it_coord_begin, + typename std::vector::const_iterator it_coord_end, + FT) const + { + return m_ref_to_tdfc(q, p, it_coord_begin, it_coord_end); + } + + private: + Distance const& m_distance; + Tdfc const& m_ref_to_tdfc; + }; + // ... or if it exists + template <> + class Interruptible_transformed_distance + { + public: + typedef Transformed_distance_from_coordinates< + has_transformed_distance_from_coordinates::value> Tdfc; + + Interruptible_transformed_distance( + SearchTraits const& traits, Distance const& distance, Tdfc const&) + : m_traits(traits), m_distance(distance) + {} + + FT operator() ( + const Query_item& q, + Point const& p, + FT stop_if_geq_to_this) const + { + typename SearchTraits::Construct_cartesian_const_iterator_d construct_it = + m_traits.construct_cartesian_const_iterator_d_object(); + return m_distance.interruptible_transformed_distance( + q, construct_it(p), construct_it(p, 0), stop_if_geq_to_this); + } + + FT operator() ( + const Query_item& q, + Point const& p, + typename std::vector::const_iterator it_coord_begin, + typename std::vector::const_iterator it_coord_end, + FT stop_if_geq_to_this) const + { + return m_distance.interruptible_transformed_distance( + q, it_coord_begin, it_coord_end, stop_if_geq_to_this); + } + + private: + SearchTraits const& m_traits; + Distance const& m_distance; + }; + + Distance const& m_distance; + Transformed_distance_from_coordinates< + has_transformed_distance_from_coordinates::value> m_tdfc; + Interruptible_transformed_distance< + has_interruptible_transformed_distance::value> m_itd; }; // Distance_helper From 319d2d614c8d1cdb26cb22235a38afe10a6fca06 Mon Sep 17 00:00:00 2001 From: Clement Jamin Date: Thu, 16 Nov 2017 18:48:00 +0100 Subject: [PATCH 041/363] Fix compilation continued --- .../include/CGAL/Euclidean_distance.h | 66 ++++- .../CGAL/Incremental_neighbor_search.h | 15 +- .../include/CGAL/K_neighbor_search.h | 48 ++-- Spatial_searching/include/CGAL/Kd_tree.h | 6 + .../Orthogonal_incremental_neighbor_search.h | 22 +- .../CGAL/Orthogonal_k_neighbor_search.h | 28 +- .../include/CGAL/internal/Search_helpers.h | 260 ++++++++++-------- .../test/Spatial_searching/Distance.h | 1 + 8 files changed, 255 insertions(+), 191 deletions(-) diff --git a/Spatial_searching/include/CGAL/Euclidean_distance.h b/Spatial_searching/include/CGAL/Euclidean_distance.h index 308f4a69680..32354de8aaf 100644 --- a/Spatial_searching/include/CGAL/Euclidean_distance.h +++ b/Spatial_searching/include/CGAL/Euclidean_distance.h @@ -23,6 +23,8 @@ #ifndef CGAL_EUCLIDEAN_DISTANCE_H #define CGAL_EUCLIDEAN_DISTANCE_H +//#define DISABLE_OPTIONAL_FUNCTIONS // disable cache + interruptible optimizations // CJTODO: remove this debug code + #include @@ -30,6 +32,7 @@ #include #include #include +#include namespace CGAL { @@ -61,6 +64,61 @@ namespace CGAL { // default constructor Euclidean_distance(const SearchTraits& traits_=SearchTraits()):traits(traits_) {} +#ifdef DISABLE_OPTIONAL_FUNCTIONS + + inline FT transformed_distance(const Query_item& q, const Point_d& p) const { + return transformed_distance(q, p, D()); + } + + //Dynamic version for runtime dimension + inline FT transformed_distance(const Query_item& q, const Point_d& p, Dynamic_dimension_tag) const { + FT distance = FT(0); + typename SearchTraits::Construct_cartesian_const_iterator_d construct_it = traits.construct_cartesian_const_iterator_d_object(); + typename SearchTraits::Cartesian_const_iterator_d qit = construct_it(q), + qe = construct_it(q, 1), pit = construct_it(p); + for (; qit != qe; qit++, pit++) { + distance += ((*qit) - (*pit))*((*qit) - (*pit)); + } + return distance; + } + + //Generic version for DIM > 3 + template < int DIM > + inline FT transformed_distance(const Query_item& q, const Point_d& p, Dimension_tag) const { + FT distance = FT(0); + typename SearchTraits::Construct_cartesian_const_iterator_d construct_it = traits.construct_cartesian_const_iterator_d_object(); + typename SearchTraits::Cartesian_const_iterator_d qit = construct_it(q), + qe = construct_it(q, 1), pit = construct_it(p); + for (; qit != qe; qit++, pit++) { + distance += ((*qit) - (*pit))*((*qit) - (*pit)); + } + return distance; + } + + //DIM = 2 loop unrolled + inline FT transformed_distance(const Query_item& q, const Point_d& p, Dimension_tag<2>) const { + typename SearchTraits::Construct_cartesian_const_iterator_d construct_it = traits.construct_cartesian_const_iterator_d_object(); + typename SearchTraits::Cartesian_const_iterator_d qit = construct_it(q), pit = construct_it(p); + FT distance = square(*qit - *pit); + qit++; pit++; + distance += square(*qit - *pit); + return distance; + } + + //DIM = 3 loop unrolled + inline FT transformed_distance(const Query_item& q, const Point_d& p, Dimension_tag<3>) const { + typename SearchTraits::Construct_cartesian_const_iterator_d construct_it = traits.construct_cartesian_const_iterator_d_object(); + typename SearchTraits::Cartesian_const_iterator_d qit = construct_it(q), pit = construct_it(p); + FT distance = square(*qit - *pit); + qit++; pit++; + distance += square(*qit - *pit); + qit++; pit++; + distance += square(*qit - *pit); + return distance; + } + +#else // !DISABLE_OPTIONAL_FUNCTIONS + inline FT transformed_distance(const Query_item& q, const Point_d& p) const { typename SearchTraits::Construct_cartesian_const_iterator_d construct_it = traits.construct_cartesian_const_iterator_d_object(); @@ -132,13 +190,14 @@ namespace CGAL { FT distance = FT(0); typename SearchTraits::Construct_cartesian_const_iterator_d construct_it = traits.construct_cartesian_const_iterator_d_object(); typename SearchTraits::Cartesian_const_iterator_d qit = construct_it(q), qe = construct_it(q, 1); - if (qe - qit >= 6) + if (std::distance(qit, qe) >= 6) { // Every 4 coordinates, the current partially-computed distance // is compared to stop_if_geq_to_this // Note: the concept SearchTraits specifies that Cartesian_const_iterator_d // must be a random-access iterator - typename SearchTraits::Cartesian_const_iterator_d qe_minus_5 = qe - 5; + typename SearchTraits::Cartesian_const_iterator_d qe_minus_5 = qe; + std::advance(qe, -5); for (;;) { FT diff = (*qit) - (*it_coord_begin); @@ -157,7 +216,7 @@ namespace CGAL { if (distance >= stop_if_geq_to_this) return distance; - if (qit >= qe_minus_5) + if (std::distance(qe_minus_5, qit) >= 0) break; } } @@ -168,6 +227,7 @@ namespace CGAL { } return distance; } +#endif inline FT min_distance_to_rectangle(const Query_item& q, const Kd_tree_rectangle& r) const { diff --git a/Spatial_searching/include/CGAL/Incremental_neighbor_search.h b/Spatial_searching/include/CGAL/Incremental_neighbor_search.h index 12bbcd00e9f..db42efb151c 100644 --- a/Spatial_searching/include/CGAL/Incremental_neighbor_search.h +++ b/Spatial_searching/include/CGAL/Incremental_neighbor_search.h @@ -442,12 +442,8 @@ namespace CGAL { } - template - bool search_in_leaf(typename Tree::Leaf_node_const_handle node, bool search_furthest); - // With cache - template<> - bool search_in_leaf(typename Tree::Leaf_node_const_handle node, bool search_furthest) + bool search_in_leaf(typename Tree::Leaf_node_const_handle node, Tag_true, bool search_furthest) { typename Tree::iterator it_node_point = node->begin(), it_node_point_end = node->end(); typename std::vector::const_iterator cache_point_begin = m_tree.cache_begin() + m_dim*(it_node_point - m_tree.begin()); @@ -486,8 +482,7 @@ namespace CGAL { } // Without cache - template<> - bool search_in_leaf(typename Tree::Leaf_node_const_handle node, bool search_furthest) + bool search_in_leaf(typename Tree::Leaf_node_const_handle node, Tag_false, bool search_furthest) { typename Tree::iterator it_node_point = node->begin(), it_node_point_end = node->end(); @@ -495,7 +490,7 @@ namespace CGAL { { number_of_items_visited++; FT distance_to_query_point = - orthogonal_distance_instance.transformed_distance(query_point, *it_node_point); + distance.transformed_distance(query_point, *it_node_point); Point_with_transformed_distance *NN_Candidate = new Point_with_transformed_distance(*it_node_point, distance_to_query_point); @@ -606,8 +601,8 @@ namespace CGAL { static_cast(N); number_of_leaf_nodes_visited++; if (node->size() > 0) { - next_neighbour_found = - search_in_leaf::type::value>::value>(node, !search_nearest_neighbour); + typename internal::Has_points_cache::type::value>::type dummy; + next_neighbour_found = search_in_leaf(node, dummy, !search_nearest_neighbour); } } // next_neighbour_found or priority queue is empty // in the latter case also the item priority queue is empty diff --git a/Spatial_searching/include/CGAL/K_neighbor_search.h b/Spatial_searching/include/CGAL/K_neighbor_search.h index f4fe3418428..ebc286ad7f9 100644 --- a/Spatial_searching/include/CGAL/K_neighbor_search.h +++ b/Spatial_searching/include/CGAL/K_neighbor_search.h @@ -58,11 +58,9 @@ public: typename SearchTraits::Construct_cartesian_const_iterator_d construct_it = m_tree.traits().construct_cartesian_const_iterator_d_object(); - m_dim = static_cast(std::distance( - construct_it(this->query_object), construct_it(this->query_object, 0))); compute_neighbors_general(tree.root(),tree.bounding_box()); - if (sorted) this->queue.sort(); + if (sorted) this->queue.sort(); }; private: @@ -70,7 +68,6 @@ private: using Base::branch; internal::Distance_helper m_distance_helper; - int m_dim; Tree const& m_tree; void @@ -144,23 +141,21 @@ private: this->number_of_leaf_nodes_visited++; if (node->size() > 0) { - if (this->search_nearest) - search_nearest_in_leaf::type::value>::value>(node); + typename internal::Has_points_cache::type::value>::type dummy; + if (this->search_nearest) + search_nearest_in_leaf(node, dummy); else - search_furthest_in_leaf::type::value>::value>(node); + search_furthest_in_leaf(node, dummy); } } } - template - void search_nearest_in_leaf(typename Tree::Leaf_node_const_handle node); - // With cache - template<> - void search_nearest_in_leaf(typename Tree::Leaf_node_const_handle node) + void search_nearest_in_leaf(typename Tree::Leaf_node_const_handle node, Tag_true) { typename Tree::iterator it_node_point = node->begin(), it_node_point_end = node->end(); - typename std::vector::const_iterator cache_point_begin = m_tree.cache_begin() + m_dim*(it_node_point - m_tree.begin()); + int dim = m_tree.dim(); + typename std::vector::const_iterator cache_point_begin = m_tree.cache_begin() + dim*(it_node_point - m_tree.begin()); // As long as the queue is not full, the node is just inserted for (; !this->queue.full() && it_node_point != it_node_point_end; ++it_node_point) { @@ -168,10 +163,10 @@ private: FT distance_to_query_object = m_distance_helper.transformed_distance_from_coordinates( - this->query_object, *it_node_point, cache_point_begin, cache_point_begin + m_dim); + this->query_object, *it_node_point, cache_point_begin, cache_point_begin + dim); this->queue.insert(std::make_pair(&(*it_node_point), distance_to_query_object)); - cache_point_begin += m_dim; + cache_point_begin += dim; } // Now that the queue is full, we can gain time by keeping track // of the current worst distance to interrupt the distance computation earlier @@ -182,7 +177,7 @@ private: FT distance_to_query_object = m_distance_helper.interruptible_transformed_distance( - this->query_object, *it_node_point, cache_point_begin, cache_point_begin + m_dim, worst_dist); + this->query_object, *it_node_point, cache_point_begin, cache_point_begin + dim, worst_dist); if (distance_to_query_object < worst_dist) { @@ -190,13 +185,12 @@ private: worst_dist = this->queue.top().second; } - cache_point_begin += m_dim; + cache_point_begin += dim; } } // Without cache - template<> - void search_nearest_in_leaf(typename Tree::Leaf_node_const_handle node) + void search_nearest_in_leaf(typename Tree::Leaf_node_const_handle node, Tag_false) { typename Tree::iterator it_node_point = node->begin(), it_node_point_end = node->end(); // As long as the queue is not full, the node is just inserted @@ -228,15 +222,12 @@ private: } - template - void search_furthest_in_leaf(typename Tree::Leaf_node_const_handle node); - // With cache - template<> - void search_furthest_in_leaf(typename Tree::Leaf_node_const_handle node) + void search_furthest_in_leaf(typename Tree::Leaf_node_const_handle node, Tag_true) { typename Tree::iterator it_node_point = node->begin(), it_node_point_end = node->end(); - typename std::vector::const_iterator cache_point_begin = m_tree.cache_begin() + m_dim*(it_node_point - m_tree.begin()); + int dim = m_tree.dim(); + typename std::vector::const_iterator cache_point_begin = m_tree.cache_begin() + dim*(it_node_point - m_tree.begin()); // In furthest search mode, the interruptible distance cannot be used to optimize for (; it_node_point != it_node_point_end; ++it_node_point) { @@ -244,16 +235,15 @@ private: FT distance_to_query_object = m_distance_helper.transformed_distance_from_coordinates( - this->query_object, *it_node_point, cache_point_begin, cache_point_begin + m_dim); + this->query_object, *it_node_point, cache_point_begin, cache_point_begin + dim); this->queue.insert(std::make_pair(&(*it_node_point), distance_to_query_object)); - cache_point_begin += m_dim; + cache_point_begin += dim; } } // Without cache - template<> - void search_furthest_in_leaf(typename Tree::Leaf_node_const_handle node) + void search_furthest_in_leaf(typename Tree::Leaf_node_const_handle node, Tag_false) { typename Tree::iterator it_node_point = node->begin(), it_node_point_end = node->end(); // In furthest search mode, the interruptible distance cannot be used to optimize diff --git a/Spatial_searching/include/CGAL/Kd_tree.h b/Spatial_searching/include/CGAL/Kd_tree.h index 6521532eee6..9b6fa5a52ce 100644 --- a/Spatial_searching/include/CGAL/Kd_tree.h +++ b/Spatial_searching/include/CGAL/Kd_tree.h @@ -318,6 +318,12 @@ public: built_ = true; } + // Only correct when build() has been called + int dim() const + { + return dim_; + } + private: //any call to this function is for the moment not threadsafe void const_build() const { diff --git a/Spatial_searching/include/CGAL/Orthogonal_incremental_neighbor_search.h b/Spatial_searching/include/CGAL/Orthogonal_incremental_neighbor_search.h index 46d505724d9..a7c743e0150 100644 --- a/Spatial_searching/include/CGAL/Orthogonal_incremental_neighbor_search.h +++ b/Spatial_searching/include/CGAL/Orthogonal_incremental_neighbor_search.h @@ -270,12 +270,9 @@ namespace CGAL { } - template - bool search_in_leaf(typename Tree::Leaf_node_const_handle node, bool search_furthest); // With cache - template<> - bool search_in_leaf(typename Tree::Leaf_node_const_handle node, bool search_furthest) + bool search_in_leaf(typename Tree::Leaf_node_const_handle node, Tag_true, bool search_furthest) { typename Tree::iterator it_node_point = node->begin(), it_node_point_end = node->end(); typename std::vector::const_iterator cache_point_begin = m_tree.cache_begin() + m_dim*(it_node_point - m_tree.begin()); @@ -314,8 +311,7 @@ namespace CGAL { } // Without cache - template<> - bool search_in_leaf(typename Tree::Leaf_node_const_handle node, bool search_furthest) + bool search_in_leaf(typename Tree::Leaf_node_const_handle node, Tag_false, bool search_furthest) { typename Tree::iterator it_node_point = node->begin(), it_node_point_end = node->end(); @@ -406,9 +402,10 @@ namespace CGAL { typename Tree::Leaf_node_const_handle node = static_cast(N); number_of_leaf_nodes_visited++; - if (node->size() > 0) - next_neighbour_found = - search_in_leaf::type::value>::value>(node, false); + if (node->size() > 0) { + typename internal::Has_points_cache::type::value>::type dummy; + next_neighbour_found = search_in_leaf(node, dummy, false); + } } // next_neighbour_found or priority queue is empty // in the latter case also the item priority quee is empty } @@ -469,9 +466,10 @@ namespace CGAL { typename Tree::Leaf_node_const_handle node = static_cast(N); number_of_leaf_nodes_visited++; - if (node->size() > 0) - next_neighbour_found = - search_in_leaf::type::value>::value>(node, true); + if (node->size() > 0) { + typename internal::Has_points_cache::type::value>::type dummy; + next_neighbour_found = search_in_leaf(node, dummy, true); + } } // next_neighbour_found or priority queue is empty // in the latter case also the item priority quee is empty } diff --git a/Spatial_searching/include/CGAL/Orthogonal_k_neighbor_search.h b/Spatial_searching/include/CGAL/Orthogonal_k_neighbor_search.h index d1492c4f655..e2097b7ba8c 100644 --- a/Spatial_searching/include/CGAL/Orthogonal_k_neighbor_search.h +++ b/Spatial_searching/include/CGAL/Orthogonal_k_neighbor_search.h @@ -85,12 +85,8 @@ public: } private: - template - void search_nearest_in_leaf(typename Tree::Leaf_node_const_handle node); - // With cache - template<> - void search_nearest_in_leaf(typename Tree::Leaf_node_const_handle node) + void search_nearest_in_leaf(typename Tree::Leaf_node_const_handle node, Tag_true) { typename Tree::iterator it_node_point = node->begin(), it_node_point_end = node->end(); typename std::vector::const_iterator cache_point_begin = m_tree.cache_begin() + m_dim*(it_node_point - m_tree.begin()); @@ -128,8 +124,7 @@ private: } // Without cache - template<> - void search_nearest_in_leaf(typename Tree::Leaf_node_const_handle node) + void search_nearest_in_leaf(typename Tree::Leaf_node_const_handle node, Tag_false) { typename Tree::iterator it_node_point = node->begin(), it_node_point_end = node->end(); // As long as the queue is not full, the node is just inserted @@ -169,7 +164,10 @@ private: static_cast(N); this->number_of_leaf_nodes_visited++; if (node->size() > 0) - search_nearest_in_leaf::type::value>::value>(node); + { + typename internal::Has_points_cache::type::value>::type dummy; + search_nearest_in_leaf(node, dummy); + } } else { @@ -206,12 +204,8 @@ private: } } - template - void search_furthest_in_leaf(typename Tree::Leaf_node_const_handle node); - // With cache - template<> - void search_furthest_in_leaf(typename Tree::Leaf_node_const_handle node) + void search_furthest_in_leaf(typename Tree::Leaf_node_const_handle node, Tag_true) { typename Tree::iterator it_node_point = node->begin(), it_node_point_end = node->end(); typename std::vector::const_iterator cache_point_begin = m_tree.cache_begin() + m_dim*(it_node_point - m_tree.begin()); @@ -230,8 +224,7 @@ private: } // Without cache - template<> - void search_furthest_in_leaf(typename Tree::Leaf_node_const_handle node) + void search_furthest_in_leaf(typename Tree::Leaf_node_const_handle node, Tag_false) { typename Tree::iterator it_node_point = node->begin(), it_node_point_end = node->end(); // In furthest search mode, the interruptible distance cannot be used to optimize @@ -254,7 +247,10 @@ private: static_cast(N); this->number_of_leaf_nodes_visited++; if (node->size() > 0) - search_furthest_in_leaf::type::value>::value>(node); + { + typename internal::Has_points_cache::type::value>::type dummy; + search_furthest_in_leaf(node, dummy); + } } else { diff --git a/Spatial_searching/include/CGAL/internal/Search_helpers.h b/Spatial_searching/include/CGAL/internal/Search_helpers.h index a7e45b25e3a..7b77f072858 100644 --- a/Spatial_searching/include/CGAL/internal/Search_helpers.h +++ b/Spatial_searching/include/CGAL/internal/Search_helpers.h @@ -54,6 +54,143 @@ CGAL_GENERATE_MEMBER_DETECTOR(interruptible_transformed_distance); BOOST_MPL_HAS_XXX_TRAIT_NAMED_DEF(has_Enable_points_cache, Enable_points_cache, false) + +// If transformed_distance_from_coordinates does not exist in `Distance` +template +class Transformed_distance_from_coordinates +{ + typedef typename Distance::FT FT; + typedef typename Distance::Point_d Point; + typedef typename Distance::Query_item Query_item; + +public: + Transformed_distance_from_coordinates(Distance const& distance) + : m_distance(distance) + {} + + FT operator() ( + const Query_item& q, + Point const& p, + typename std::vector::const_iterator it_coord_begin, + typename std::vector::const_iterator it_coord_end) const + { + return m_distance.transformed_distance(q, p); + } + +private: + Distance const& m_distance; +}; +// ... or if it exists +template +class Transformed_distance_from_coordinates +{ + typedef typename Distance::FT FT; + typedef typename Distance::Point_d Point; + typedef typename Distance::Query_item Query_item; + +public: + Transformed_distance_from_coordinates(Distance const& distance) + : m_distance(distance) + {} + + FT operator() ( + const Query_item& q, + Point const& p, + typename std::vector::const_iterator it_coord_begin, + typename std::vector::const_iterator it_coord_end) const + { + return m_distance.transformed_distance_from_coordinates(q, it_coord_begin, it_coord_end); + } + +private: + Distance const& m_distance; +}; + +// If interruptible_transformed_distance does not exist in `Distance` +template +class Interruptible_transformed_distance +{ + typedef typename Distance::FT FT; + typedef typename Distance::Point_d Point; + typedef typename Distance::Query_item Query_item; + +public: + typedef Transformed_distance_from_coordinates::value> Tdfc; + + Interruptible_transformed_distance( + SearchTraits const&, Distance const& distance, Tdfc const& tdfc) + : m_distance(distance), m_ref_to_tdfc(tdfc) + {} + + FT operator() ( + const Query_item& q, + Point const& p, + FT) const + { + return m_distance.transformed_distance(q, p); + } + + FT operator() ( + const Query_item& q, + Point const& p, + typename std::vector::const_iterator it_coord_begin, + typename std::vector::const_iterator it_coord_end, + FT) const + { + return m_ref_to_tdfc(q, p, it_coord_begin, it_coord_end); + } + +private: + Distance const& m_distance; + Tdfc const& m_ref_to_tdfc; +}; +// ... or if it exists +template +class Interruptible_transformed_distance +{ + typedef typename Distance::FT FT; + typedef typename Distance::Point_d Point; + typedef typename Distance::Query_item Query_item; + +public: + typedef Transformed_distance_from_coordinates::value> Tdfc; + + Interruptible_transformed_distance( + SearchTraits const& traits, Distance const& distance, Tdfc const&) + : m_traits(traits), m_distance(distance) + {} + + FT operator() ( + const Query_item& q, + Point const& p, + FT stop_if_geq_to_this) const + { + typename SearchTraits::Construct_cartesian_const_iterator_d construct_it = + m_traits.construct_cartesian_const_iterator_d_object(); + return m_distance.interruptible_transformed_distance( + q, construct_it(p), construct_it(p, 0), stop_if_geq_to_this); + } + + FT operator() ( + const Query_item& q, + Point const& p, + typename std::vector::const_iterator it_coord_begin, + typename std::vector::const_iterator it_coord_end, + FT stop_if_geq_to_this) const + { + return m_distance.interruptible_transformed_distance( + q, it_coord_begin, it_coord_end, stop_if_geq_to_this); + } + +private: + SearchTraits const& m_traits; + Distance const& m_distance; +}; + + + template class Distance_helper { @@ -98,129 +235,10 @@ public: } private: - - // If transformed_distance_from_coordinates does not exist in `Distance` - template - class Transformed_distance_from_coordinates - { - public: - Transformed_distance_from_coordinates(Distance const& distance) - : m_distance(distance) - {} - - FT operator() ( - const Query_item& q, - Point const& p, - typename std::vector::const_iterator it_coord_begin, - typename std::vector::const_iterator it_coord_end) const - { - return m_distance.transformed_distance(q, p); - } - - private: - Distance const& m_distance; - }; - // ... or if it exists - template <> - class Transformed_distance_from_coordinates - { - public: - Transformed_distance_from_coordinates(Distance const& distance) - : m_distance(distance) - {} - - FT operator() ( - const Query_item& q, - Point const& p, - typename std::vector::const_iterator it_coord_begin, - typename std::vector::const_iterator it_coord_end) const - { - return m_distance.transformed_distance_from_coordinates(q, it_coord_begin, it_coord_end); - } - - private: - Distance const& m_distance; - }; - - // If interruptible_transformed_distance does not exist in `Distance` - template - class Interruptible_transformed_distance - { - public: - typedef Transformed_distance_from_coordinates< - has_transformed_distance_from_coordinates::value> Tdfc; - - Interruptible_transformed_distance( - SearchTraits const&, Distance const& distance, Tdfc const& tdfc) - : m_distance(distance), m_ref_to_tdfc(tdfc) - {} - - FT operator() ( - const Query_item& q, - Point const& p, - FT) const - { - return m_distance.transformed_distance(q, p); - } - - FT operator() ( - const Query_item& q, - Point const& p, - typename std::vector::const_iterator it_coord_begin, - typename std::vector::const_iterator it_coord_end, - FT) const - { - return m_ref_to_tdfc(q, p, it_coord_begin, it_coord_end); - } - - private: - Distance const& m_distance; - Tdfc const& m_ref_to_tdfc; - }; - // ... or if it exists - template <> - class Interruptible_transformed_distance - { - public: - typedef Transformed_distance_from_coordinates< - has_transformed_distance_from_coordinates::value> Tdfc; - - Interruptible_transformed_distance( - SearchTraits const& traits, Distance const& distance, Tdfc const&) - : m_traits(traits), m_distance(distance) - {} - - FT operator() ( - const Query_item& q, - Point const& p, - FT stop_if_geq_to_this) const - { - typename SearchTraits::Construct_cartesian_const_iterator_d construct_it = - m_traits.construct_cartesian_const_iterator_d_object(); - return m_distance.interruptible_transformed_distance( - q, construct_it(p), construct_it(p, 0), stop_if_geq_to_this); - } - - FT operator() ( - const Query_item& q, - Point const& p, - typename std::vector::const_iterator it_coord_begin, - typename std::vector::const_iterator it_coord_end, - FT stop_if_geq_to_this) const - { - return m_distance.interruptible_transformed_distance( - q, it_coord_begin, it_coord_end, stop_if_geq_to_this); - } - - private: - SearchTraits const& m_traits; - Distance const& m_distance; - }; - Distance const& m_distance; - Transformed_distance_from_coordinates< + Transformed_distance_from_coordinates::value> m_tdfc; - Interruptible_transformed_distance< + Interruptible_transformed_distance::value> m_itd; }; // Distance_helper diff --git a/Spatial_searching/test/Spatial_searching/Distance.h b/Spatial_searching/test/Spatial_searching/Distance.h index b5cf20adfff..f8c02b846e5 100644 --- a/Spatial_searching/test/Spatial_searching/Distance.h +++ b/Spatial_searching/test/Spatial_searching/Distance.h @@ -1,4 +1,5 @@ struct Distance { + typedef Point Point_d; typedef Point Query_item; typedef double FT; From 7954d370866dcab6a794cfb154aa3549f1cf069e Mon Sep 17 00:00:00 2001 From: Clement Jamin Date: Thu, 16 Nov 2017 18:57:20 +0100 Subject: [PATCH 042/363] Useless typename --- Spatial_searching/include/CGAL/Kd_tree_node.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Spatial_searching/include/CGAL/Kd_tree_node.h b/Spatial_searching/include/CGAL/Kd_tree_node.h index 0b6f10a5240..4ada42218d1 100644 --- a/Spatial_searching/include/CGAL/Kd_tree_node.h +++ b/Spatial_searching/include/CGAL/Kd_tree_node.h @@ -294,7 +294,7 @@ namespace CGAL { // ... or if it exists template bool contains( - const typename FuzzyQueryItem& q, + const FuzzyQueryItem& q, Point_d const& p, typename std::vector::const_iterator it_coord_begin, typename std::vector::const_iterator it_coord_end, From 005f770ef6a9a436166cc8efbb32640fc67fd7f9 Mon Sep 17 00:00:00 2001 From: Clement Jamin Date: Thu, 16 Nov 2017 19:01:56 +0100 Subject: [PATCH 043/363] Missing typename --- Spatial_searching/include/CGAL/Kd_tree_node.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Spatial_searching/include/CGAL/Kd_tree_node.h b/Spatial_searching/include/CGAL/Kd_tree_node.h index 4ada42218d1..4b45769bd71 100644 --- a/Spatial_searching/include/CGAL/Kd_tree_node.h +++ b/Spatial_searching/include/CGAL/Kd_tree_node.h @@ -207,7 +207,7 @@ namespace CGAL { static_cast(this); if (node->size() > 0) { - internal::Has_points_cache::type::value>::type dummy; + typename internal::Has_points_cache::type::value>::type dummy; search_in_leaf(node, q, tree_points_begin, cache_begin, dim, it, dummy); } } @@ -247,7 +247,7 @@ namespace CGAL { static_cast(this); if (node->size()>0) { - internal::Has_points_cache::type::value>::type dummy; + typename internal::Has_points_cache::type::value>::type dummy; result = search_any_point_in_leaf(node, q, tree_points_begin, cache_begin, dim, dummy); } } From 86dfc07ac1d858db7056445b0d181e417e45b9be Mon Sep 17 00:00:00 2001 From: Clement Jamin Date: Mon, 20 Nov 2017 10:49:10 +0100 Subject: [PATCH 044/363] Missing Point_d in user-defined distance (see concept) --- Spatial_searching/examples/Spatial_searching/Distance.h | 1 + 1 file changed, 1 insertion(+) diff --git a/Spatial_searching/examples/Spatial_searching/Distance.h b/Spatial_searching/examples/Spatial_searching/Distance.h index 6334724c7bc..147ffc6e7ff 100644 --- a/Spatial_searching/examples/Spatial_searching/Distance.h +++ b/Spatial_searching/examples/Spatial_searching/Distance.h @@ -1,5 +1,6 @@ struct Distance { typedef Point Query_item; + typedef Point Point_d; typedef double FT; typedef CGAL::Dimension_tag<3> D; From be5870e26977f894acd6265bdf0887e5cf576278 Mon Sep 17 00:00:00 2001 From: Clement Jamin Date: Mon, 20 Nov 2017 10:55:19 +0100 Subject: [PATCH 045/363] Clean-up debug code --- .../include/CGAL/Euclidean_distance.h | 58 ------------------- 1 file changed, 58 deletions(-) diff --git a/Spatial_searching/include/CGAL/Euclidean_distance.h b/Spatial_searching/include/CGAL/Euclidean_distance.h index 09f0ded93be..20693a3f91d 100644 --- a/Spatial_searching/include/CGAL/Euclidean_distance.h +++ b/Spatial_searching/include/CGAL/Euclidean_distance.h @@ -24,8 +24,6 @@ #ifndef CGAL_EUCLIDEAN_DISTANCE_H #define CGAL_EUCLIDEAN_DISTANCE_H -//#define DISABLE_OPTIONAL_FUNCTIONS // disable cache + interruptible optimizations // CJTODO: remove this debug code - #include @@ -65,61 +63,6 @@ namespace CGAL { // default constructor Euclidean_distance(const SearchTraits& traits_=SearchTraits()):traits(traits_) {} -#ifdef DISABLE_OPTIONAL_FUNCTIONS - - inline FT transformed_distance(const Query_item& q, const Point_d& p) const { - return transformed_distance(q, p, D()); - } - - //Dynamic version for runtime dimension - inline FT transformed_distance(const Query_item& q, const Point_d& p, Dynamic_dimension_tag) const { - FT distance = FT(0); - typename SearchTraits::Construct_cartesian_const_iterator_d construct_it = traits.construct_cartesian_const_iterator_d_object(); - typename SearchTraits::Cartesian_const_iterator_d qit = construct_it(q), - qe = construct_it(q, 1), pit = construct_it(p); - for (; qit != qe; qit++, pit++) { - distance += ((*qit) - (*pit))*((*qit) - (*pit)); - } - return distance; - } - - //Generic version for DIM > 3 - template < int DIM > - inline FT transformed_distance(const Query_item& q, const Point_d& p, Dimension_tag) const { - FT distance = FT(0); - typename SearchTraits::Construct_cartesian_const_iterator_d construct_it = traits.construct_cartesian_const_iterator_d_object(); - typename SearchTraits::Cartesian_const_iterator_d qit = construct_it(q), - qe = construct_it(q, 1), pit = construct_it(p); - for (; qit != qe; qit++, pit++) { - distance += ((*qit) - (*pit))*((*qit) - (*pit)); - } - return distance; - } - - //DIM = 2 loop unrolled - inline FT transformed_distance(const Query_item& q, const Point_d& p, Dimension_tag<2>) const { - typename SearchTraits::Construct_cartesian_const_iterator_d construct_it = traits.construct_cartesian_const_iterator_d_object(); - typename SearchTraits::Cartesian_const_iterator_d qit = construct_it(q), pit = construct_it(p); - FT distance = square(*qit - *pit); - qit++; pit++; - distance += square(*qit - *pit); - return distance; - } - - //DIM = 3 loop unrolled - inline FT transformed_distance(const Query_item& q, const Point_d& p, Dimension_tag<3>) const { - typename SearchTraits::Construct_cartesian_const_iterator_d construct_it = traits.construct_cartesian_const_iterator_d_object(); - typename SearchTraits::Cartesian_const_iterator_d qit = construct_it(q), pit = construct_it(p); - FT distance = square(*qit - *pit); - qit++; pit++; - distance += square(*qit - *pit); - qit++; pit++; - distance += square(*qit - *pit); - return distance; - } - -#else // !DISABLE_OPTIONAL_FUNCTIONS - inline FT transformed_distance(const Query_item& q, const Point_d& p) const { typename SearchTraits::Construct_cartesian_const_iterator_d construct_it = traits.construct_cartesian_const_iterator_d_object(); @@ -228,7 +171,6 @@ namespace CGAL { } return distance; } -#endif inline FT min_distance_to_rectangle(const Query_item& q, const Kd_tree_rectangle& r) const { From 7d69e65cef280cd5ba79ced19ed03da1f3d5af6e Mon Sep 17 00:00:00 2001 From: Clement Jamin Date: Mon, 20 Nov 2017 10:56:47 +0100 Subject: [PATCH 046/363] Fix indentation --- .../include/CGAL/Euclidean_distance.h | 160 +++++++++--------- 1 file changed, 80 insertions(+), 80 deletions(-) diff --git a/Spatial_searching/include/CGAL/Euclidean_distance.h b/Spatial_searching/include/CGAL/Euclidean_distance.h index 20693a3f91d..d379c74eb6f 100644 --- a/Spatial_searching/include/CGAL/Euclidean_distance.h +++ b/Spatial_searching/include/CGAL/Euclidean_distance.h @@ -172,92 +172,92 @@ namespace CGAL { return distance; } - inline FT min_distance_to_rectangle(const Query_item& q, - const Kd_tree_rectangle& r) const { - FT distance = FT(0); - typename SearchTraits::Construct_cartesian_const_iterator_d construct_it=traits.construct_cartesian_const_iterator_d_object(); - typename SearchTraits::Cartesian_const_iterator_d qit = construct_it(q), - qe = construct_it(q,1); - for(unsigned int i = 0;qit != qe; i++, qit++){ - if((*qit) < r.min_coord(i)) - distance += - (r.min_coord(i)-(*qit))*(r.min_coord(i)-(*qit)); - else if ((*qit) > r.max_coord(i)) - distance += - ((*qit)-r.max_coord(i))*((*qit)-r.max_coord(i)); - - } - return distance; - } + inline FT min_distance_to_rectangle(const Query_item& q, + const Kd_tree_rectangle& r) const { + FT distance = FT(0); + typename SearchTraits::Construct_cartesian_const_iterator_d construct_it = traits.construct_cartesian_const_iterator_d_object(); + typename SearchTraits::Cartesian_const_iterator_d qit = construct_it(q), + qe = construct_it(q, 1); + for (unsigned int i = 0; qit != qe; i++, qit++) { + if ((*qit) < r.min_coord(i)) + distance += + (r.min_coord(i) - (*qit))*(r.min_coord(i) - (*qit)); + else if ((*qit) > r.max_coord(i)) + distance += + ((*qit) - r.max_coord(i))*((*qit) - r.max_coord(i)); - inline FT min_distance_to_rectangle(const Query_item& q, - const Kd_tree_rectangle& r,std::vector& dists) const { - FT distance = FT(0); - typename SearchTraits::Construct_cartesian_const_iterator_d construct_it=traits.construct_cartesian_const_iterator_d_object(); - typename SearchTraits::Cartesian_const_iterator_d qit = construct_it(q), - qe = construct_it(q,1); - for(unsigned int i = 0;qit != qe; i++, qit++){ - if((*qit) < r.min_coord(i)){ - dists[i] = (r.min_coord(i)-(*qit)); - distance += dists[i] * dists[i]; - } - else if ((*qit) > r.max_coord(i)){ - dists[i] = ((*qit)-r.max_coord(i)); - distance += dists[i] * dists[i]; - } - - } - return distance; - } + } + return distance; + } - inline FT max_distance_to_rectangle(const Query_item& q, - const Kd_tree_rectangle& r) const { - FT distance=FT(0); - typename SearchTraits::Construct_cartesian_const_iterator_d construct_it=traits.construct_cartesian_const_iterator_d_object(); - typename SearchTraits::Cartesian_const_iterator_d qit = construct_it(q), - qe = construct_it(q,1); - for(unsigned int i = 0;qit != qe; i++, qit++){ - if ((*qit) <= (r.min_coord(i)+r.max_coord(i))/FT(2.0)) - distance += (r.max_coord(i)-(*qit))*(r.max_coord(i)-(*qit)); - else - distance += ((*qit)-r.min_coord(i))*((*qit)-r.min_coord(i)); - }; - return distance; - } + inline FT min_distance_to_rectangle(const Query_item& q, + const Kd_tree_rectangle& r, std::vector& dists) const { + FT distance = FT(0); + typename SearchTraits::Construct_cartesian_const_iterator_d construct_it = traits.construct_cartesian_const_iterator_d_object(); + typename SearchTraits::Cartesian_const_iterator_d qit = construct_it(q), + qe = construct_it(q, 1); + for (unsigned int i = 0; qit != qe; i++, qit++) { + if ((*qit) < r.min_coord(i)) { + dists[i] = (r.min_coord(i) - (*qit)); + distance += dists[i] * dists[i]; + } + else if ((*qit) > r.max_coord(i)) { + dists[i] = ((*qit) - r.max_coord(i)); + distance += dists[i] * dists[i]; + } - inline FT max_distance_to_rectangle(const Query_item& q, - const Kd_tree_rectangle& r,std::vector& dists ) const { - FT distance=FT(0); - typename SearchTraits::Construct_cartesian_const_iterator_d construct_it=traits.construct_cartesian_const_iterator_d_object(); - typename SearchTraits::Cartesian_const_iterator_d qit = construct_it(q), - qe = construct_it(q,1); - for(unsigned int i = 0;qit != qe; i++, qit++){ - if ((*qit) <= (r.min_coord(i)+r.max_coord(i))/FT(2.0)){ - dists[i] = (r.max_coord(i)-(*qit)); - distance += dists[i] * dists[i]; - } - else{ - dists[i] = ((*qit)-r.min_coord(i)); - distance += dists[i] * dists[i]; - } - }; - return distance; - } + } + return distance; + } - inline FT new_distance(FT dist, FT old_off, FT new_off, - int /* cutting_dimension */) const { - - FT new_dist = dist + (new_off*new_off - old_off*old_off); - return new_dist; - } + inline FT max_distance_to_rectangle(const Query_item& q, + const Kd_tree_rectangle& r) const { + FT distance = FT(0); + typename SearchTraits::Construct_cartesian_const_iterator_d construct_it = traits.construct_cartesian_const_iterator_d_object(); + typename SearchTraits::Cartesian_const_iterator_d qit = construct_it(q), + qe = construct_it(q, 1); + for (unsigned int i = 0; qit != qe; i++, qit++) { + if ((*qit) <= (r.min_coord(i) + r.max_coord(i)) / FT(2.0)) + distance += (r.max_coord(i) - (*qit))*(r.max_coord(i) - (*qit)); + else + distance += ((*qit) - r.min_coord(i))*((*qit) - r.min_coord(i)); + }; + return distance; + } - inline FT transformed_distance(FT d) const { - return d*d; - } + inline FT max_distance_to_rectangle(const Query_item& q, + const Kd_tree_rectangle& r, std::vector& dists) const { + FT distance = FT(0); + typename SearchTraits::Construct_cartesian_const_iterator_d construct_it = traits.construct_cartesian_const_iterator_d_object(); + typename SearchTraits::Cartesian_const_iterator_d qit = construct_it(q), + qe = construct_it(q, 1); + for (unsigned int i = 0; qit != qe; i++, qit++) { + if ((*qit) <= (r.min_coord(i) + r.max_coord(i)) / FT(2.0)) { + dists[i] = (r.max_coord(i) - (*qit)); + distance += dists[i] * dists[i]; + } + else { + dists[i] = ((*qit) - r.min_coord(i)); + distance += dists[i] * dists[i]; + } + }; + return distance; + } - inline FT inverse_of_transformed_distance(FT d) const { - return CGAL::sqrt(d); - } + inline FT new_distance(FT dist, FT old_off, FT new_off, + int /* cutting_dimension */) const { + + FT new_dist = dist + (new_off*new_off - old_off*old_off); + return new_dist; + } + + inline FT transformed_distance(FT d) const { + return d*d; + } + + inline FT inverse_of_transformed_distance(FT d) const { + return CGAL::sqrt(d); + } }; // class Euclidean_distance From 04aa045706475e9be1ad63fa91b3ed1fb33fbfd8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9bastien=20Loriot?= Date: Tue, 21 Nov 2017 13:41:58 +0100 Subject: [PATCH 047/363] add missing identifiers --- STL_Extension/include/CGAL/Has_member.h | 4 +++- Spatial_searching/include/CGAL/internal/Search_helpers.h | 1 + 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/STL_Extension/include/CGAL/Has_member.h b/STL_Extension/include/CGAL/Has_member.h index 79cf5a31b35..d89c6315774 100644 --- a/STL_Extension/include/CGAL/Has_member.h +++ b/STL_Extension/include/CGAL/Has_member.h @@ -12,7 +12,9 @@ // 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: LGPL-3.0+ // // Author(s) : Clement Jamin diff --git a/Spatial_searching/include/CGAL/internal/Search_helpers.h b/Spatial_searching/include/CGAL/internal/Search_helpers.h index 7b77f072858..cf308676fb3 100644 --- a/Spatial_searching/include/CGAL/internal/Search_helpers.h +++ b/Spatial_searching/include/CGAL/internal/Search_helpers.h @@ -14,6 +14,7 @@ // // $URL$ // $Id$ +// SPDX-License-Identifier: GPL-3.0+ // // // Author(s) : Clement Jamin (clement.jamin.pro@gmail.com) From 06b18208e8e6e5316568e63af3b18a107d8a077c Mon Sep 17 00:00:00 2001 From: Clement Jamin Date: Wed, 22 Nov 2017 11:31:58 +0100 Subject: [PATCH 048/363] Specify 4th template argument for Kd_tree + doc --- .../doc/Spatial_searching/CGAL/Incremental_neighbor_search.h | 2 +- .../doc/Spatial_searching/CGAL/Orthogonal_k_neighbor_search.h | 2 +- Spatial_searching/include/CGAL/Incremental_neighbor_search.h | 2 +- Spatial_searching/include/CGAL/K_neighbor_search.h | 2 +- Spatial_searching/include/CGAL/Orthogonal_k_neighbor_search.h | 2 +- 5 files changed, 5 insertions(+), 5 deletions(-) diff --git a/Spatial_searching/doc/Spatial_searching/CGAL/Incremental_neighbor_search.h b/Spatial_searching/doc/Spatial_searching/CGAL/Incremental_neighbor_search.h index 2375a23ffd8..7b0e19babc9 100644 --- a/Spatial_searching/doc/Spatial_searching/CGAL/Incremental_neighbor_search.h +++ b/Spatial_searching/doc/Spatial_searching/CGAL/Incremental_neighbor_search.h @@ -20,7 +20,7 @@ and `Euclidean_distance` otherwise. The default type is `Sliding_midpoint`. \tparam SpatialTree must be a model of the concept `SpatialTree`. -The default type is `Kd_tree`. The +The default type is `Kd_tree`. The template argument `Tag_false` makes that the tree is built with unextended nodes. \sa `CGAL::Orthogonal_incremental_neighbor_search` diff --git a/Spatial_searching/doc/Spatial_searching/CGAL/Orthogonal_k_neighbor_search.h b/Spatial_searching/doc/Spatial_searching/CGAL/Orthogonal_k_neighbor_search.h index 61039c37646..0c6cd01b711 100644 --- a/Spatial_searching/doc/Spatial_searching/CGAL/Orthogonal_k_neighbor_search.h +++ b/Spatial_searching/doc/Spatial_searching/CGAL/Orthogonal_k_neighbor_search.h @@ -20,7 +20,7 @@ and `Euclidean_distance` otherwise. The default type is `Sliding_midpoint`. \tparam SpatialTree must be a model of the concept `SpatialTree`. -The default type is `Kd_tree`. The +The default type is `Kd_tree`. The third template argument must be `Tag_true` because orthogonal search needs extended kd tree nodes. diff --git a/Spatial_searching/include/CGAL/Incremental_neighbor_search.h b/Spatial_searching/include/CGAL/Incremental_neighbor_search.h index cd934459e5d..ff271acc1a1 100644 --- a/Spatial_searching/include/CGAL/Incremental_neighbor_search.h +++ b/Spatial_searching/include/CGAL/Incremental_neighbor_search.h @@ -41,7 +41,7 @@ namespace CGAL { template ::type, class Splitter_ = Sliding_midpoint, - class Tree_=Kd_tree > + class Tree_=Kd_tree > class Incremental_neighbor_search { public: diff --git a/Spatial_searching/include/CGAL/K_neighbor_search.h b/Spatial_searching/include/CGAL/K_neighbor_search.h index f13d7d09b4f..a972a1e11b4 100644 --- a/Spatial_searching/include/CGAL/K_neighbor_search.h +++ b/Spatial_searching/include/CGAL/K_neighbor_search.h @@ -39,7 +39,7 @@ class K_neighbor_search; template ::type, class Splitter= Sliding_midpoint , - class Tree= Kd_tree > + class Tree= Kd_tree > class K_neighbor_search: public internal::K_neighbor_search { typedef internal::K_neighbor_search Base; diff --git a/Spatial_searching/include/CGAL/Orthogonal_k_neighbor_search.h b/Spatial_searching/include/CGAL/Orthogonal_k_neighbor_search.h index f4685028d36..2af8af7941d 100644 --- a/Spatial_searching/include/CGAL/Orthogonal_k_neighbor_search.h +++ b/Spatial_searching/include/CGAL/Orthogonal_k_neighbor_search.h @@ -36,7 +36,7 @@ namespace CGAL { template ::type, class Splitter= Sliding_midpoint , - class Tree= Kd_tree > + class Tree= Kd_tree > class Orthogonal_k_neighbor_search: public internal::K_neighbor_search { typedef internal::K_neighbor_search Base; From c791c765f90a1a4d2b4f33736b55999b024cefc8 Mon Sep 17 00:00:00 2001 From: Clement Jamin Date: Wed, 22 Nov 2017 11:49:17 +0100 Subject: [PATCH 049/363] Missing typedefs in custom distance class --- .../include/CGAL/Search_traits_vertex_handle_3.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Point_set_processing_3/include/CGAL/Search_traits_vertex_handle_3.h b/Point_set_processing_3/include/CGAL/Search_traits_vertex_handle_3.h index 20b0d4ec4b3..518223edd28 100644 --- a/Point_set_processing_3/include/CGAL/Search_traits_vertex_handle_3.h +++ b/Point_set_processing_3/include/CGAL/Search_traits_vertex_handle_3.h @@ -123,8 +123,10 @@ struct Construct_cartesian_const_iterator_vertex_handle_3 template struct Euclidean_distance_vertex_handle_3 { + typedef double FT; typedef CGAL::Point_vertex_handle_3 Point_vertex_handle_3; typedef Point_vertex_handle_3 Query_item; + typedef Point_vertex_handle_3 Point_d; double transformed_distance(const Point_vertex_handle_3& p1, const Point_vertex_handle_3& p2) const { double distx = p1.x()-p2.x(); From 323b40334786529e75207c7f1f732b0ffb83ef6d Mon Sep 17 00:00:00 2001 From: Clement Jamin Date: Fri, 24 Nov 2017 15:34:25 +0100 Subject: [PATCH 050/363] Update doc --- .../doc/Spatial_searching/CGAL/Incremental_neighbor_search.h | 2 +- .../doc/Spatial_searching/CGAL/K_neighbor_search.h | 2 +- .../CGAL/Orthogonal_incremental_neighbor_search.h | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/Spatial_searching/doc/Spatial_searching/CGAL/Incremental_neighbor_search.h b/Spatial_searching/doc/Spatial_searching/CGAL/Incremental_neighbor_search.h index 7b0e19babc9..3273f5b39ca 100644 --- a/Spatial_searching/doc/Spatial_searching/CGAL/Incremental_neighbor_search.h +++ b/Spatial_searching/doc/Spatial_searching/CGAL/Incremental_neighbor_search.h @@ -21,7 +21,7 @@ The default type is `Sliding_midpoint`. \tparam SpatialTree must be a model of the concept `SpatialTree`. The default type is `Kd_tree`. The -template argument `Tag_false` makes that the tree is built with unextended nodes. +third template argument `Tag_false` makes that the tree is built with unextended nodes. \sa `CGAL::Orthogonal_incremental_neighbor_search` diff --git a/Spatial_searching/doc/Spatial_searching/CGAL/K_neighbor_search.h b/Spatial_searching/doc/Spatial_searching/CGAL/K_neighbor_search.h index fbe80dd9a00..8f21698a2e2 100644 --- a/Spatial_searching/doc/Spatial_searching/CGAL/K_neighbor_search.h +++ b/Spatial_searching/doc/Spatial_searching/CGAL/K_neighbor_search.h @@ -21,7 +21,7 @@ and `Euclidean_distance` otherwise. The default type is `Sliding_midpoint`. \tparam SpatialTree must be an implementation of the concept `SpatialTree`. -The default type is `Kd_tree`. The +The default type is `Kd_tree`. The third template argument `Tag_false` makes that the tree is built with unextended nodes. \sa `CGAL::Orthogonal_k_neighbor_search` diff --git a/Spatial_searching/doc/Spatial_searching/CGAL/Orthogonal_incremental_neighbor_search.h b/Spatial_searching/doc/Spatial_searching/CGAL/Orthogonal_incremental_neighbor_search.h index c783b1711db..86a6d31438e 100644 --- a/Spatial_searching/doc/Spatial_searching/CGAL/Orthogonal_incremental_neighbor_search.h +++ b/Spatial_searching/doc/Spatial_searching/CGAL/Orthogonal_incremental_neighbor_search.h @@ -18,7 +18,7 @@ and `Euclidean_distance` otherwise. The default type is `Sliding_midpoint`. \tparam SpatialTree must be a model of the concept `SpatialTree`. -The default type is `Kd_tree`. The +The default type is `Kd_tree`. The third template argument must be `Tag_true` because orthogonal search needs extended kd tree nodes. From 5806c2546065632dfdebe0b5c63db5402b8d4531 Mon Sep 17 00:00:00 2001 From: Clement Jamin Date: Fri, 24 Nov 2017 15:35:14 +0100 Subject: [PATCH 051/363] Specify 4th template argument for Kd_tree --- .../include/CGAL/Orthogonal_incremental_neighbor_search.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Spatial_searching/include/CGAL/Orthogonal_incremental_neighbor_search.h b/Spatial_searching/include/CGAL/Orthogonal_incremental_neighbor_search.h index 8c7f26a6494..da5a2c97cdd 100644 --- a/Spatial_searching/include/CGAL/Orthogonal_incremental_neighbor_search.h +++ b/Spatial_searching/include/CGAL/Orthogonal_incremental_neighbor_search.h @@ -41,7 +41,7 @@ namespace CGAL { template ::type, class Splitter_ = Sliding_midpoint, - class Tree_= Kd_tree > + class Tree_= Kd_tree > class Orthogonal_incremental_neighbor_search { public: From cf4a809457a3b00a2bf5a1741fec4be4533e05f8 Mon Sep 17 00:00:00 2001 From: dangerski Date: Tue, 12 Mar 2019 10:49:43 -0600 Subject: [PATCH 052/363] Prevent infinite loop in Advancing front surface reconstruction. In some cases K can become really large but doesn't get to infinity and instead gets into a situation where K + epsilon == K and the the while loop never exits. So we check for the case where K stops changing and exits. --- .../include/CGAL/Advancing_front_surface_reconstruction.h | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/Advancing_front_surface_reconstruction/include/CGAL/Advancing_front_surface_reconstruction.h b/Advancing_front_surface_reconstruction/include/CGAL/Advancing_front_surface_reconstruction.h index 317c04ee863..14c1523fe17 100644 --- a/Advancing_front_surface_reconstruction/include/CGAL/Advancing_front_surface_reconstruction.h +++ b/Advancing_front_surface_reconstruction/include/CGAL/Advancing_front_surface_reconstruction.h @@ -2005,6 +2005,7 @@ namespace CGAL { { // initilisation de la variable globale K: qualite d'echantillonnage requise K = K_init; // valeur d'initialisation de K pour commencer prudemment... + coord_type K_prev = K; Vertex_handle v1, v2; if (_ordered_border.empty()){ @@ -2069,12 +2070,12 @@ namespace CGAL { } while((!_ordered_border.empty())&& (_ordered_border.begin()->first < STANDBY_CANDIDATE_BIS)); - + K_prev = K; K += (std::max)(K_step, min_K - K + eps); // on augmente progressivement le K mais on a deja rempli sans // faire des betises auparavant... } - while((!_ordered_border.empty())&&(K <= K)&&(min_K != infinity())); + while((!_ordered_border.empty())&&(K <= K)&&(min_K != infinity())&&(K!=K_prev)); #ifdef VERBOSE if ((min_K < infinity())&&(!_ordered_border.empty())) { From 97d44ba776fe9975fb858379eb779bf5e362ec55 Mon Sep 17 00:00:00 2001 From: Jasmeet Singh Date: Mon, 3 Jun 2019 17:53:39 -0700 Subject: [PATCH 053/363] Add viewer for Voronoi Diagram 2. Only points viewed for now. CGAL::draw() implemented for Voronoi_diagram_2. Currently viewing only points. Added draw() to example vd_2_point_location. Will add separate example in future. --- .../examples/Voronoi_diagram_2/CMakeLists.txt | 11 +- .../Voronoi_diagram_2/vd_2_point_location.cpp | 5 + .../include/CGAL/draw_voronoi_diagram_2.h | 183 ++++++++++++++++++ 3 files changed, 198 insertions(+), 1 deletion(-) create mode 100644 Voronoi_diagram_2/include/CGAL/draw_voronoi_diagram_2.h diff --git a/Voronoi_diagram_2/examples/Voronoi_diagram_2/CMakeLists.txt b/Voronoi_diagram_2/examples/Voronoi_diagram_2/CMakeLists.txt index 92893d16599..56d96a57c23 100644 --- a/Voronoi_diagram_2/examples/Voronoi_diagram_2/CMakeLists.txt +++ b/Voronoi_diagram_2/examples/Voronoi_diagram_2/CMakeLists.txt @@ -6,7 +6,11 @@ project( Voronoi_diagram_2_Examples ) cmake_minimum_required(VERSION 3.1) -find_package(CGAL QUIET) +find_package(CGAL COMPONENTS Qt5) + +if(CGAL_Qt5_FOUND) + add_definitions(-DCGAL_USE_BASIC_VIEWER -DQT_NO_KEYWORDS) +endif() if ( CGAL_FOUND ) @@ -14,6 +18,11 @@ if ( CGAL_FOUND ) file(GLOB cppfiles RELATIVE ${CMAKE_CURRENT_SOURCE_DIR} ${CMAKE_CURRENT_SOURCE_DIR}/*.cpp) foreach(cppfile ${cppfiles}) create_single_source_cgal_program( "${cppfile}" ) + + if(CGAL_Qt5_FOUND ) + target_link_libraries(vd_2_point_location PUBLIC CGAL::CGAL_Qt5) + endif() + endforeach() else() diff --git a/Voronoi_diagram_2/examples/Voronoi_diagram_2/vd_2_point_location.cpp b/Voronoi_diagram_2/examples/Voronoi_diagram_2/vd_2_point_location.cpp index 8451c216bde..6b2169eee9d 100644 --- a/Voronoi_diagram_2/examples/Voronoi_diagram_2/vd_2_point_location.cpp +++ b/Voronoi_diagram_2/examples/Voronoi_diagram_2/vd_2_point_location.cpp @@ -10,6 +10,9 @@ #include #include +// include to draw the Voronoi diagram +#include + // typedefs for defining the adaptor typedef CGAL::Exact_predicates_inexact_constructions_kernel K; typedef CGAL::Delaunay_triangulation_2 DT; @@ -84,5 +87,7 @@ int main() } ifq.close(); + CGAL::draw(vd); + return 0; } diff --git a/Voronoi_diagram_2/include/CGAL/draw_voronoi_diagram_2.h b/Voronoi_diagram_2/include/CGAL/draw_voronoi_diagram_2.h new file mode 100644 index 00000000000..238a09d2583 --- /dev/null +++ b/Voronoi_diagram_2/include/CGAL/draw_voronoi_diagram_2.h @@ -0,0 +1,183 @@ +// Copyright(c) 2018 INRIA Sophia-Antipolis (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) : Jasmeet Singh + +#ifndef CGAL_DRAW_VORONOI_H +#define CGAL_DRAW_VORONOI_H + +#include +#include + +#ifdef CGAL_USE_BASIC_VIEWER + +#include + +namespace CGAL +{ +// Default color functor; user can change it to have its own face color +struct DefaultColorFunctorV2 +{ + template + static CGAL::Color run(const V2&, + const typename V2::Face_iterator fh) + { + CGAL::Random random((unsigned int)(std::size_t)(&*fh)); + return get_random_color(random); + } +}; + +// Viewer for Voronoi diagram +template +class SimpleVoronoiDiagram2ViewerQt : public Basic_viewer_qt +{ + typedef Basic_viewer_qt Base; + typedef typename V2::Halfedge_iterator Halfedge_const_handle; + typedef typename V2::Face_iterator Face_const_handle; + typedef typename V2::Vertex_iterator Vertex_const_handle; + typedef typename V2::Point_2 Point; + +public: + /// Construct the viewer. + /// @param av2 the voronoi diagram to view + /// @param title the title of the window + /// @param anofaces if true, do not draw faces (faces are not computed; this can be + /// useful for very big object where this time could be long) + SimpleVoronoiDiagram2ViewerQt(QWidget* parent, const V2& av2, + const char* title="Basic Voronoi Viewer", + bool anofaces=false, + const ColorFunctor& fcolor=ColorFunctor()) : + //First draw: vertices; half-edges; faces; multi-color; no inverse normal + Base(parent, title, true, true, true, false, false), + v2(av2), + m_nofaces(anofaces), + m_fcolor(fcolor) + { + compute_elements(); + } + +protected: +// void compute_face(Face_const_handle fh) +// { +// CGAL::Color c=m_fcolor.run(v2, fh); +// face_begin(c); +// add_point_in_face(fh->halfedge()->source()->point()); +// add_point_in_face(fh->halfedge()->source()->point()); +// add_point_in_face(fh->halfedge()->source()->point()); + +// face_end(); +// } + +// void compute_edge(Halfedge_const_handle he) +// { +// add_segment(he->source()->point(), +// he->target()->point()); +// } + + void compute_vertex(Vertex_const_handle vh) + { add_point(vh->point()); } + + void compute_elements() + { + clear(); + +// if (!m_nofaces) +// { +// for (typename V2::Face_iterator it=v2.faces_begin(); +// it!=v2.faces_end(); ++it) +// { compute_face(it); } +// } + +// for (typename V2::Halfedge_iterator it=v2.halfedges_begin(); +// it!=v2.halfedges_end(); ++it) +// { compute_edge(it); } + + for (typename V2::Vertex_iterator it=v2.vertices_begin(); + it!=v2.vertices_end(); ++it) + { compute_vertex(it); } + } + + virtual void keyPressEvent(QKeyEvent *e) + { + // Test key pressed: + // const ::Qt::KeyboardModifiers modifiers = e->modifiers(); + // if ((e->key()==Qt::Key_PageUp) && (modifiers==Qt::NoButton)) { ... } + + // Call: * compute_elements() if the model changed, followed by + // * redraw() if some viewing parameters changed that implies some + // modifications of the buffers + // (eg. type of normal, color/mono) + // * update() just to update the drawing + + // Call the base method to process others/classicals key + Base::keyPressEvent(e); + } + +protected: + const V2& v2; + bool m_nofaces; + const ColorFunctor& m_fcolor; +}; + +template +void draw(const V2& av2, + const char* title, + bool nofill, + const ColorFunctor& fcolor) +{ +#if defined(CGAL_TEST_SUITE) + bool cgal_test_suite=true; +#else + bool cgal_test_suite=false; +#endif + + if (!cgal_test_suite) + { + int argc=1; + const char* argv[2]={"v2_viewer","\0"}; + QApplication app(argc,const_cast(argv)); + SimpleVoronoiDiagram2ViewerQt mainwindow(app.activeWindow(), + av2, + title, + nofill, + fcolor); + mainwindow.show(); + app.exec(); + } +} + +template +void draw(const V2& av2, const char* title, bool nofill) +{ + DefaultColorFunctorV2 c; + draw(av2, title, nofill, c); +} + +template +void draw(const V2& av2, const char* title) +{ draw(av2, title, false); } + +template +void draw(const V2& av2) +{ draw(av2, "Basic Voronoi Diagram Viewer"); } + +} // End namespace CGAL + +#endif // CGAL_USE_BASIC_VIEWER + +#endif // CGAL_DRAW_VORONOI_H From d2eaef16d030e080cb5efa21db71cf0a11f98543 Mon Sep 17 00:00:00 2001 From: Jasmeet Singh Date: Mon, 3 Jun 2019 19:05:24 -0700 Subject: [PATCH 054/363] Add halfedges in viewer which are segments. --- .../examples/Voronoi_diagram_2/CMakeLists.txt | 2 +- .../include/CGAL/draw_voronoi_diagram_2.h | 17 +++++++++-------- 2 files changed, 10 insertions(+), 9 deletions(-) diff --git a/Voronoi_diagram_2/examples/Voronoi_diagram_2/CMakeLists.txt b/Voronoi_diagram_2/examples/Voronoi_diagram_2/CMakeLists.txt index 56d96a57c23..ce38b689dc8 100644 --- a/Voronoi_diagram_2/examples/Voronoi_diagram_2/CMakeLists.txt +++ b/Voronoi_diagram_2/examples/Voronoi_diagram_2/CMakeLists.txt @@ -21,7 +21,7 @@ if ( CGAL_FOUND ) if(CGAL_Qt5_FOUND ) target_link_libraries(vd_2_point_location PUBLIC CGAL::CGAL_Qt5) - endif() + endif() endforeach() diff --git a/Voronoi_diagram_2/include/CGAL/draw_voronoi_diagram_2.h b/Voronoi_diagram_2/include/CGAL/draw_voronoi_diagram_2.h index 238a09d2583..df922fb048e 100644 --- a/Voronoi_diagram_2/include/CGAL/draw_voronoi_diagram_2.h +++ b/Voronoi_diagram_2/include/CGAL/draw_voronoi_diagram_2.h @@ -83,11 +83,12 @@ protected: // face_end(); // } -// void compute_edge(Halfedge_const_handle he) -// { -// add_segment(he->source()->point(), -// he->target()->point()); -// } + void compute_edge(Halfedge_const_handle he) + { + if(he->is_segment()) + add_segment(he->source()->point(), + he->target()->point()); + } void compute_vertex(Vertex_const_handle vh) { add_point(vh->point()); } @@ -103,9 +104,9 @@ protected: // { compute_face(it); } // } -// for (typename V2::Halfedge_iterator it=v2.halfedges_begin(); -// it!=v2.halfedges_end(); ++it) -// { compute_edge(it); } + for (typename V2::Halfedge_iterator it=v2.halfedges_begin(); + it!=v2.halfedges_end(); ++it) + { compute_edge(it); } for (typename V2::Vertex_iterator it=v2.vertices_begin(); it!=v2.vertices_end(); ++it) From 608ba3eee8bc87e2990fdcb0d3d6eb8a373b03bc Mon Sep 17 00:00:00 2001 From: Jasmeet Singh Date: Wed, 12 Jun 2019 23:05:10 -0700 Subject: [PATCH 055/363] Start to implement infinite line in basic viewer. --- GraphicsView/include/CGAL/Buffer_for_vao.h | 14 +++ .../include/CGAL/Qt/Basic_viewer_qt.h | 108 +++++++++++++++++- .../include/CGAL/draw_voronoi_diagram_2.h | 97 ++++++++++++---- 3 files changed, 196 insertions(+), 23 deletions(-) diff --git a/GraphicsView/include/CGAL/Buffer_for_vao.h b/GraphicsView/include/CGAL/Buffer_for_vao.h index a0148cd4c0b..085fb2a3a84 100644 --- a/GraphicsView/include/CGAL/Buffer_for_vao.h +++ b/GraphicsView/include/CGAL/Buffer_for_vao.h @@ -42,6 +42,7 @@ namespace CGAL typedef CGAL::Exact_predicates_inexact_constructions_kernel Local_kernel; typedef Local_kernel::Point_3 Local_point; typedef Local_kernel::Vector_3 Local_vector; + typedef Local_kernel::Ray_2 Local_ray; //------------------------------------------------------------------------------ namespace internal @@ -108,6 +109,11 @@ namespace internal CGAL::Cartesian_converter converter; return converter(v); } + static Local_ray get_local_ray(const typename K::Ray_2& r) + { + CGAL::Cartesian_converter converter; + return converter(r); + } }; // Specialization for Local_kernel, because there is no need of convertion here. @@ -246,6 +252,14 @@ public: add_color(c); } + // 2.2+) Add a line, without color. TODO: Modify comment numbering + template + void add_line(const KPoint& kp1, const KPoint& kp2) + { + add_point(kp1); + add_point(kp2); + } + // 2.3) Add an indexed segment, without color. template void add_indexed_segment(T index1, T index2) diff --git a/GraphicsView/include/CGAL/Qt/Basic_viewer_qt.h b/GraphicsView/include/CGAL/Qt/Basic_viewer_qt.h index 2799c1c5790..3a7a6b8335f 100644 --- a/GraphicsView/include/CGAL/Qt/Basic_viewer_qt.h +++ b/GraphicsView/include/CGAL/Qt/Basic_viewer_qt.h @@ -178,9 +178,11 @@ public: m_use_mono_color(use_mono_color), m_inverse_normal(inverse_normal), m_size_points(7.), - m_size_edges(3.1), + m_size_edges(3.1), + m_size_lines(3.1), m_vertices_mono_color(200, 60, 60), m_edges_mono_color(0, 0, 0), + m_lines_mono_color(0,100,0), m_faces_mono_color(60, 60, 200), m_ambient_color(0.6f, 0.5f, 0.5f, 0.5f), m_are_buffers_initialized(false), @@ -202,6 +204,15 @@ public: &m_bounding_box, &arrays[COLOR_SEGMENTS], NULL, NULL), + m_buffer_for_mono_lines(&arrays[POS_MONO_LINES], + NULL, + &m_bounding_box, + NULL, NULL), + m_buffer_for_colored_lines(&arrays[POS_COLORED_LINES], + NULL, + &m_bounding_box, + &arrays[COLOR_LINES], + NULL, NULL), m_buffer_for_mono_faces(&arrays[POS_MONO_FACES], NULL, &m_bounding_box, @@ -268,7 +279,11 @@ public: template void add_segment(const KPoint& p1, const KPoint& p2, const CGAL::Color& acolor) - { m_buffer_for_colored_segments.add_segment(p1, p2, acolor); } + { m_buffer_for_colored_segments.add_segment(p1, p2, acolor); } + + template + void add_line(const KPoint& p1, const KPoint& p2) + { m_buffer_for_mono_lines.add_line(p1, p2); } bool is_a_face_started() const { @@ -467,6 +482,52 @@ protected: rendering_program_p_l.release(); + // 3) LINE SHADER + + // 3.1) Mono lines + vao[VAO_MONO_LINES].bind(); + + ++bufn; + assert(bufn(arrays[POS_MONO_LINES].size()*sizeof(float))); + rendering_program_p_l.enableAttributeArray("vertex"); + rendering_program_p_l.setAttributeArray("vertex",GL_FLOAT,0,3); + + buffers[bufn].release(); + + rendering_program_p_l.disableAttributeArray("color"); + + vao[VAO_MONO_LINES].release(); + + // 3.2) Color lines + + vao[VAO_COLORED_LINES].bind(); + + ++bufn; + assert(bufn(arrays[POS_COLORED_LINES].size()*sizeof(float))); + rendering_program_p_l.enableAttributeArray("vertex"); + rendering_program_p_l.setAttributeBuffer("vertex",GL_FLOAT,0,3); + + buffers[bufn].release(); + + ++bufn; + assert(bufn(arrays[COLOR_LINES].size()*sizeof(float))); + rendering_program_p_l.enableAttributeArray("color"); + rendering_program_p_l.setAttributeBuffer("color",GL_FLOAT,0,3); + buffers[bufn].release(); + + vao[VAO_COLORED_LINES].release(); + + rendering_program_p_l.release(); + // 3) FACE SHADER rendering_program_face.bind(); @@ -702,6 +763,39 @@ protected: rendering_program_p_l.release(); } + if(m_draw_lines) + { + rendering_program_p_l.bind(); + + vao[VAO_MONO_LINES].bind(); + color.setRgbF((double)m_lines_mono_color.red()/(double)255, + (double)m_lines_mono_color.green()/(double)255, + (double)m_lines_mono_color.blue()/(double)255); + rendering_program_p_l.setAttributeValue("color",color); + glLineWidth(m_size_lines); + glDrawArrays(GL_LINES, 0, static_cast(arrays[POS_MONO_LINES].size()/3)); + vao[VAO_MONO_SEGMENTS].release(); + + vao[VAO_COLORED_SEGMENTS].bind(); + if (m_use_mono_color) + { + color.setRgbF((double)m_lines_mono_color.red()/(double)255, + (double)m_lines_mono_color.green()/(double)255, + (double)m_lines_mono_color.blue()/(double)255); + rendering_program_p_l.disableAttributeArray("color"); + rendering_program_p_l.setAttributeValue("color",color); + } + else + { + rendering_program_p_l.enableAttributeArray("color"); + } + glLineWidth(m_size_lines); + glDrawArrays(GL_LINES, 0, static_cast(arrays[POS_COLORED_LINES].size()/3)); + vao[VAO_COLORED_LINES].release(); + + rendering_program_p_l.release(); + } + if (m_draw_faces) { rendering_program_face.bind(); @@ -985,6 +1079,7 @@ protected: protected: bool m_draw_vertices; bool m_draw_edges; + bool m_draw_lines; bool m_draw_faces; bool m_flatShading; bool m_use_mono_color; @@ -992,9 +1087,11 @@ protected: double m_size_points; double m_size_edges; + double m_size_lines; CGAL::Color m_vertices_mono_color; CGAL::Color m_edges_mono_color; + CGAL::Color m_lines_mono_color; CGAL::Color m_faces_mono_color; QVector4D m_ambient_color; @@ -1009,12 +1106,15 @@ protected: POS_COLORED_POINTS, POS_MONO_SEGMENTS, POS_COLORED_SEGMENTS, + POS_MONO_LINES, + POS_COLORED_LINES, POS_MONO_FACES, POS_COLORED_FACES, END_POS, BEGIN_COLOR=END_POS, COLOR_POINTS=BEGIN_COLOR, COLOR_SEGMENTS, + COLOR_LINES, COLOR_FACES, END_COLOR, BEGIN_NORMAL=END_COLOR, @@ -1031,6 +1131,8 @@ protected: Buffer_for_vao m_buffer_for_colored_points; Buffer_for_vao m_buffer_for_mono_segments; Buffer_for_vao m_buffer_for_colored_segments; + Buffer_for_vao m_buffer_for_mono_lines; + Buffer_for_vao m_buffer_for_colored_lines; Buffer_for_vao m_buffer_for_mono_faces; Buffer_for_vao m_buffer_for_colored_faces; @@ -1045,6 +1147,8 @@ protected: VAO_COLORED_POINTS, VAO_MONO_SEGMENTS, VAO_COLORED_SEGMENTS, + VAO_MONO_LINES, + VAO_COLORED_LINES, VAO_MONO_FACES, VAO_COLORED_FACES, NB_VAO_BUFFERS diff --git a/Voronoi_diagram_2/include/CGAL/draw_voronoi_diagram_2.h b/Voronoi_diagram_2/include/CGAL/draw_voronoi_diagram_2.h index df922fb048e..f93c92b24ba 100644 --- a/Voronoi_diagram_2/include/CGAL/draw_voronoi_diagram_2.h +++ b/Voronoi_diagram_2/include/CGAL/draw_voronoi_diagram_2.h @@ -26,10 +26,17 @@ #ifdef CGAL_USE_BASIC_VIEWER +#include +#include +#include +#include +#include +#include #include namespace CGAL { + // Default color functor; user can change it to have its own face color struct DefaultColorFunctorV2 { @@ -46,11 +53,21 @@ struct DefaultColorFunctorV2 template class SimpleVoronoiDiagram2ViewerQt : public Basic_viewer_qt { - typedef Basic_viewer_qt Base; - typedef typename V2::Halfedge_iterator Halfedge_const_handle; - typedef typename V2::Face_iterator Face_const_handle; - typedef typename V2::Vertex_iterator Vertex_const_handle; - typedef typename V2::Point_2 Point; + typedef Basic_viewer_qt Base; + typedef typename V2::Halfedge_iterator Halfedge_const_handle; + typedef typename V2::Face_iterator Face_const_handle; + typedef typename V2::Vertex_iterator Vertex_const_handle; + typedef typename V2::Point_2 Point; + typedef typename V2::Delaunay_vertex_handle Delaunay_vertex_const_handle; + typedef typename V2::Ccb_halfedge_circulator Ccb_halfedge_circulator; + typedef typename V2::Delaunay_geom_traits Delaunay_geom_traits; + + typedef CGAL::Exact_predicates_inexact_constructions_kernel Kernel; + typedef CGAL_VORONOI_DIAGRAM_2_INS::Face Face; + typedef CGAL_VORONOI_DIAGRAM_2_INS::Handle_adaptor Face_handle; + typedef CGAL_VORONOI_DIAGRAM_2_INS::Vertex Vertex; + typedef CGAL_VORONOI_DIAGRAM_2_INS::Handle_adaptor Vertex_handle; + typedef Triangulation_cw_ccw_2 CW_CCW_2; public: /// Construct the viewer. @@ -72,22 +89,56 @@ public: } protected: -// void compute_face(Face_const_handle fh) -// { + void compute_face(Face_const_handle fh) + { // CGAL::Color c=m_fcolor.run(v2, fh); // face_begin(c); -// add_point_in_face(fh->halfedge()->source()->point()); -// add_point_in_face(fh->halfedge()->source()->point()); -// add_point_in_face(fh->halfedge()->source()->point()); +// Ccb_halfedge_circulator ec_start = fh->ccb(); +// Ccb_halfedge_circulator ec = ec_start; + +// do{ +// if( ec->has_source() ) +// add_point_in_face(ec->source()->point()); +// else if(ec->has_target()) +// add_point_in_face(ec->target()->point()); +// } while(++ec != ec_start); // face_end(); -// } + } void compute_edge(Halfedge_const_handle he) { - if(he->is_segment()) - add_segment(he->source()->point(), - he->target()->point()); + if(he->is_segment()){ + add_segment(he->source()->point(), + he->target()->point()); + } else if(he->is_ray()){ + Delaunay_vertex_const_handle v1 = he->up(); + Delaunay_vertex_const_handle v2 = he->down(); + Kernel::Vector_2 direction(v1->point().y()-v2->point().y(), + v2->point().x()-v1->point().x()); + Kernel::Point_2 end_point; + if(he->has_source()){ + end_point = he->source()->point(); + } else { + end_point = he->target()->point(); + } + Kernel::Ray_2 ray(end_point, direction); + CGAL::Bbox_3 bb; + if (bb==bounding_box()) // Case of "empty" bounding box + { bb=Local_point(CGAL::ORIGIN).bbox(); + bb=bb + Local_point(500,500,500).bbox(); // To avoid a warning from Qglviewer + } + else + { bb=bounding_box(); } + Kernel::Iso_rectangle_2 clipping_rect(bb.xmin(), bb.ymin(), + bb.xmax(), bb.ymax()); + Object o = CGAL::intersection(ray, clipping_rect); + typedef Kernel::Segment_2 Segment_2; + typedef Kernel::Point_2 Point_2; + if(const Segment_2 *s = CGAL::object_cast(&o)){ + add_segment(s->source(), s->target()); + } + } } void compute_vertex(Vertex_const_handle vh) @@ -97,13 +148,16 @@ protected: { clear(); -// if (!m_nofaces) -// { -// for (typename V2::Face_iterator it=v2.faces_begin(); -// it!=v2.faces_end(); ++it) -// { compute_face(it); } -// } - + if (!m_nofaces) + { + for (typename V2::Face_iterator it=v2.faces_begin(); + it!=v2.faces_end(); ++it) + { compute_face(it); } + } +// for(Delaunay_vertex_const_handle it = v2.dual().finite_vertices_begin(); +// it!=v2.dual().finite_vertices_end(); ++it) +// { compute_vertex(it);} + for (typename V2::Halfedge_iterator it=v2.halfedges_begin(); it!=v2.halfedges_end(); ++it) { compute_edge(it); } @@ -130,6 +184,7 @@ protected: } protected: + CGAL::Qt::Converter convert; const V2& v2; bool m_nofaces; const ColorFunctor& m_fcolor; From a06f4f9aa2a8d40155e8f1f2869c9334f1082a31 Mon Sep 17 00:00:00 2001 From: Jasmeet Singh Date: Wed, 12 Jun 2019 23:38:38 -0700 Subject: [PATCH 056/363] Add method add_line(point, vector) in Basic_viewer_qt to view rays. --- .../include/CGAL/Qt/Basic_viewer_qt.h | 30 +++++++++++++++++-- .../include/CGAL/draw_voronoi_diagram_2.h | 17 +---------- 2 files changed, 28 insertions(+), 19 deletions(-) diff --git a/GraphicsView/include/CGAL/Qt/Basic_viewer_qt.h b/GraphicsView/include/CGAL/Qt/Basic_viewer_qt.h index 3a7a6b8335f..ed41961c75c 100644 --- a/GraphicsView/include/CGAL/Qt/Basic_viewer_qt.h +++ b/GraphicsView/include/CGAL/Qt/Basic_viewer_qt.h @@ -281,9 +281,33 @@ public: const CGAL::Color& acolor) { m_buffer_for_colored_segments.add_segment(p1, p2, acolor); } - template - void add_line(const KPoint& p1, const KPoint& p2) - { m_buffer_for_mono_lines.add_line(p1, p2); } + template + void add_line(const KPoint& p, const KVector& v) + { CGAL::Bbox_3 bb; + if (bb==bounding_box()) // Case of "empty" bounding box + { + bb=Local_point(CGAL::ORIGIN).bbox(); + bb=bb + Local_point(200,200,200).bbox(); // To avoid a warning from Qglviewer + } + else + { bb=bounding_box(); } + this->camera()->setSceneBoundingBox(CGAL::qglviewer::Vec(bb.xmin(), + bb.ymin(), + bb.zmin()), + CGAL::qglviewer::Vec(bb.xmax(), + bb.ymax(), + bb.zmax())); + this->showEntireScene(); + Local_kernel::Iso_rectangle_2 clipping_rect(bb.xmin(), bb.ymin(), + bb.xmax(), bb.ymax()); + Local_kernel::Ray_2 ray(p, v); + Object o = CGAL::intersection(ray, clipping_rect); + typedef Local_kernel::Segment_2 Segment_2; + typedef Local_kernel::Point_2 Point_2; + if(const Segment_2 *s = CGAL::object_cast(&o)){ + add_segment(s->source(), s->target()); + } + } bool is_a_face_started() const { diff --git a/Voronoi_diagram_2/include/CGAL/draw_voronoi_diagram_2.h b/Voronoi_diagram_2/include/CGAL/draw_voronoi_diagram_2.h index f93c92b24ba..9d31291a1d5 100644 --- a/Voronoi_diagram_2/include/CGAL/draw_voronoi_diagram_2.h +++ b/Voronoi_diagram_2/include/CGAL/draw_voronoi_diagram_2.h @@ -122,22 +122,7 @@ protected: } else { end_point = he->target()->point(); } - Kernel::Ray_2 ray(end_point, direction); - CGAL::Bbox_3 bb; - if (bb==bounding_box()) // Case of "empty" bounding box - { bb=Local_point(CGAL::ORIGIN).bbox(); - bb=bb + Local_point(500,500,500).bbox(); // To avoid a warning from Qglviewer - } - else - { bb=bounding_box(); } - Kernel::Iso_rectangle_2 clipping_rect(bb.xmin(), bb.ymin(), - bb.xmax(), bb.ymax()); - Object o = CGAL::intersection(ray, clipping_rect); - typedef Kernel::Segment_2 Segment_2; - typedef Kernel::Point_2 Point_2; - if(const Segment_2 *s = CGAL::object_cast(&o)){ - add_segment(s->source(), s->target()); - } + add_line(end_point, direction); } } From abe9f2f7e448da5c1ff12654c3a797bf8a847016 Mon Sep 17 00:00:00 2001 From: Jasmeet Singh Date: Fri, 14 Jun 2019 19:18:28 -0700 Subject: [PATCH 057/363] Checking directions of rays. --- .../include/CGAL/Qt/Basic_viewer_qt.h | 11 ++++---- .../include/CGAL/draw_voronoi_diagram_2.h | 28 +++++++++++++++++-- 2 files changed, 32 insertions(+), 7 deletions(-) diff --git a/GraphicsView/include/CGAL/Qt/Basic_viewer_qt.h b/GraphicsView/include/CGAL/Qt/Basic_viewer_qt.h index ed41961c75c..ab53e0f99bd 100644 --- a/GraphicsView/include/CGAL/Qt/Basic_viewer_qt.h +++ b/GraphicsView/include/CGAL/Qt/Basic_viewer_qt.h @@ -283,7 +283,7 @@ public: template void add_line(const KPoint& p, const KVector& v) - { CGAL::Bbox_3 bb; + { /* CGAL::Bbox_3 bb; if (bb==bounding_box()) // Case of "empty" bounding box { bb=Local_point(CGAL::ORIGIN).bbox(); @@ -297,15 +297,16 @@ public: CGAL::qglviewer::Vec(bb.xmax(), bb.ymax(), bb.zmax())); - this->showEntireScene(); - Local_kernel::Iso_rectangle_2 clipping_rect(bb.xmin(), bb.ymin(), - bb.xmax(), bb.ymax()); + this->showEntireScene();*/ + Local_kernel::Point_2 p1(-200., -200.); + Local_kernel::Point_2 p2(200., 200.); + Local_kernel::Iso_rectangle_2 clipping_rect(p1, p2); Local_kernel::Ray_2 ray(p, v); Object o = CGAL::intersection(ray, clipping_rect); typedef Local_kernel::Segment_2 Segment_2; typedef Local_kernel::Point_2 Point_2; if(const Segment_2 *s = CGAL::object_cast(&o)){ - add_segment(s->source(), s->target()); + m_buffer_for_mono_lines.add_line(s->source(), s->target()); } } diff --git a/Voronoi_diagram_2/include/CGAL/draw_voronoi_diagram_2.h b/Voronoi_diagram_2/include/CGAL/draw_voronoi_diagram_2.h index 9d31291a1d5..1d2dab4d21b 100644 --- a/Voronoi_diagram_2/include/CGAL/draw_voronoi_diagram_2.h +++ b/Voronoi_diagram_2/include/CGAL/draw_voronoi_diagram_2.h @@ -114,12 +114,36 @@ protected: } else if(he->is_ray()){ Delaunay_vertex_const_handle v1 = he->up(); Delaunay_vertex_const_handle v2 = he->down(); - Kernel::Vector_2 direction(v1->point().y()-v2->point().y(), - v2->point().x()-v1->point().x()); + + std::cout << "Up vertex of ray: " << std::endl; + std::cout << v1->point() << std::endl; + std::cout << "Down vertex of ray: " << std::endl; + std::cout << v2->point() << std::endl; + + Kernel::Direction_2 direction; Kernel::Point_2 end_point; + if(he->has_source()){ + std::cout << "Left vertex of ray: " << std::endl; + std::cout << he->left()->point() << std::endl; + std::cout << "Source vertex of ray: " << std::endl; + std::cout << he->source()->point() << std::endl; + direction = Kernel::Direction_2(v1->point().y()-v2->point().y(), + v2->point().x()-v1->point().x()); + std::cout << "Direction of ray: " << std::endl; + std::cout << direction.dx() << ' ' << direction.dy() << std::endl + << std::endl; end_point = he->source()->point(); } else { + std::cout << "Right vertex of ray: " << std::endl; + std::cout << he->right()->point() << std::endl; + std::cout << "Target vertex of ray: " << std::endl; + std::cout << he->target()->point() << std::endl; + direction = Kernel::Direction_2(v1->point().y()-v2->point().y(), + v2->point().x()-v1->point().x()); + std::cout << "Direction of ray: " << std::endl; + std::cout << direction.dx() << ' ' << direction.dy() << std::endl + << std::endl; end_point = he->target()->point(); } add_line(end_point, direction); From 1c852ed586808b3440ae363bd8e1253f5f83e8f2 Mon Sep 17 00:00:00 2001 From: Jasmeet Singh Date: Fri, 14 Jun 2019 21:58:58 -0700 Subject: [PATCH 058/363] Add several points to display a ray. The viewer stopped displaying anything. --- .../include/CGAL/Qt/Basic_viewer_qt.h | 32 +++++++++++++------ .../include/CGAL/draw_voronoi_diagram_2.h | 10 +++--- 2 files changed, 27 insertions(+), 15 deletions(-) diff --git a/GraphicsView/include/CGAL/Qt/Basic_viewer_qt.h b/GraphicsView/include/CGAL/Qt/Basic_viewer_qt.h index ab53e0f99bd..098609e787c 100644 --- a/GraphicsView/include/CGAL/Qt/Basic_viewer_qt.h +++ b/GraphicsView/include/CGAL/Qt/Basic_viewer_qt.h @@ -167,12 +167,14 @@ public: const char* title="", bool draw_vertices=false, bool draw_edges=true, + bool draw_lines=true, bool draw_faces=true, bool use_mono_color=false, bool inverse_normal=false) : CGAL::QGLViewer(parent), m_draw_vertices(draw_vertices), m_draw_edges(draw_edges), + m_draw_lines(draw_lines), m_draw_faces(draw_faces), m_flatShading(true), m_use_mono_color(use_mono_color), @@ -298,16 +300,26 @@ public: bb.ymax(), bb.zmax())); this->showEntireScene();*/ - Local_kernel::Point_2 p1(-200., -200.); - Local_kernel::Point_2 p2(200., 200.); - Local_kernel::Iso_rectangle_2 clipping_rect(p1, p2); - Local_kernel::Ray_2 ray(p, v); - Object o = CGAL::intersection(ray, clipping_rect); - typedef Local_kernel::Segment_2 Segment_2; - typedef Local_kernel::Point_2 Point_2; - if(const Segment_2 *s = CGAL::object_cast(&o)){ - m_buffer_for_mono_lines.add_line(s->source(), s->target()); - } +// Local_kernel::Point_2 p1(-200., -200.); +// Local_kernel::Point_2 p2(200., 200.); +// Local_kernel::Iso_rectangle_2 clipping_rect(p1, p2); +// Local_kernel::Ray_2 ray(p, v); +// Object o = CGAL::intersection(ray, clipping_rect); +// typedef Local_kernel::Segment_2 Segment_2; +// typedef Local_kernel::Point_2 Point_2; +// if(const Segment_2 *s = CGAL::object_cast(&o)){ +// m_buffer_for_mono_lines.add_line(s->source(), s->target()); +// } + Local_kernel::Point_2 moving_point(p); + std::cout << "Ray starting from " << p << " with direction " << v << std::endl; + + for(int i =0; i< 5; i++) + { + m_buffer_for_mono_lines.add_point(moving_point); + moving_point += v; + std::cout << moving_point << std::endl; + } + std::cout << std::endl; } bool is_a_face_started() const diff --git a/Voronoi_diagram_2/include/CGAL/draw_voronoi_diagram_2.h b/Voronoi_diagram_2/include/CGAL/draw_voronoi_diagram_2.h index 1d2dab4d21b..2801597a6d9 100644 --- a/Voronoi_diagram_2/include/CGAL/draw_voronoi_diagram_2.h +++ b/Voronoi_diagram_2/include/CGAL/draw_voronoi_diagram_2.h @@ -120,7 +120,7 @@ protected: std::cout << "Down vertex of ray: " << std::endl; std::cout << v2->point() << std::endl; - Kernel::Direction_2 direction; + Kernel::Vector_2 direction; Kernel::Point_2 end_point; if(he->has_source()){ @@ -128,10 +128,10 @@ protected: std::cout << he->left()->point() << std::endl; std::cout << "Source vertex of ray: " << std::endl; std::cout << he->source()->point() << std::endl; - direction = Kernel::Direction_2(v1->point().y()-v2->point().y(), + direction = Kernel::Vector_2(v1->point().y()-v2->point().y(), v2->point().x()-v1->point().x()); std::cout << "Direction of ray: " << std::endl; - std::cout << direction.dx() << ' ' << direction.dy() << std::endl + std::cout << direction.x() << ' ' << direction.y() << std::endl << std::endl; end_point = he->source()->point(); } else { @@ -139,10 +139,10 @@ protected: std::cout << he->right()->point() << std::endl; std::cout << "Target vertex of ray: " << std::endl; std::cout << he->target()->point() << std::endl; - direction = Kernel::Direction_2(v1->point().y()-v2->point().y(), + direction = Kernel::Vector_2(v1->point().y()-v2->point().y(), v2->point().x()-v1->point().x()); std::cout << "Direction of ray: " << std::endl; - std::cout << direction.dx() << ' ' << direction.dy() << std::endl + std::cout << direction.x() << ' ' << direction.y() << std::endl << std::endl; end_point = he->target()->point(); } From 1a04afdae42e15b26bbe39848f1fbab3cc948425 Mon Sep 17 00:00:00 2001 From: jasmeet9323 Date: Mon, 17 Jun 2019 14:20:30 -0700 Subject: [PATCH 059/363] Experimenting with bounding box-ray intersection --- .../include/CGAL/Qt/Basic_viewer_qt.h | 104 ++++++++++++------ .../include/CGAL/draw_voronoi_diagram_2.h | 57 +++++----- 2 files changed, 97 insertions(+), 64 deletions(-) diff --git a/GraphicsView/include/CGAL/Qt/Basic_viewer_qt.h b/GraphicsView/include/CGAL/Qt/Basic_viewer_qt.h index 098609e787c..65027317330 100644 --- a/GraphicsView/include/CGAL/Qt/Basic_viewer_qt.h +++ b/GraphicsView/include/CGAL/Qt/Basic_viewer_qt.h @@ -284,42 +284,78 @@ public: { m_buffer_for_colored_segments.add_segment(p1, p2, acolor); } template - void add_line(const KPoint& p, const KVector& v) - { /* CGAL::Bbox_3 bb; - if (bb==bounding_box()) // Case of "empty" bounding box - { - bb=Local_point(CGAL::ORIGIN).bbox(); - bb=bb + Local_point(200,200,200).bbox(); // To avoid a warning from Qglviewer - } - else - { bb=bounding_box(); } - this->camera()->setSceneBoundingBox(CGAL::qglviewer::Vec(bb.xmin(), - bb.ymin(), - bb.zmin()), - CGAL::qglviewer::Vec(bb.xmax(), - bb.ymax(), - bb.zmax())); - this->showEntireScene();*/ -// Local_kernel::Point_2 p1(-200., -200.); -// Local_kernel::Point_2 p2(200., 200.); -// Local_kernel::Iso_rectangle_2 clipping_rect(p1, p2); -// Local_kernel::Ray_2 ray(p, v); -// Object o = CGAL::intersection(ray, clipping_rect); -// typedef Local_kernel::Segment_2 Segment_2; -// typedef Local_kernel::Point_2 Point_2; -// if(const Segment_2 *s = CGAL::object_cast(&o)){ -// m_buffer_for_mono_lines.add_line(s->source(), s->target()); -// } - Local_kernel::Point_2 moving_point(p); - std::cout << "Ray starting from " << p << " with direction " << v << std::endl; + void add_ray_points(const KPoint& p, const KVector& v) + { std::cout << "Ray starting from " << p << " with direction " << v << std::endl; + std::cout << "Bounding_box" << m_bounding_box << std::endl; + m_buffer_for_mono_segments.add_segment(p, p+v); + //m_buffer_for_mono_points.add_point(p+v); + } - for(int i =0; i< 5; i++) - { - m_buffer_for_mono_lines.add_point(moving_point); - moving_point += v; - std::cout << moving_point << std::endl; + template + void add_ray_segment(const KPoint& p, const KVector& v) + { + Local_kernel::Vector_2 V(v/CGAL::sqrt(v.squared_length())); + std::cout << "v: " << V << std::endl; + + Local_kernel::Vector_2 inV = V/CGAL::sqrt(v.squared_length()); + + Local_kernel::Vector_2 boundsMin(m_bounding_box.xmin(), m_bounding_box.zmin()); + Local_kernel::Vector_2 boundsMax(m_bounding_box.xmax(), m_bounding_box.zmax()); + + Local_kernel::Point_3 bb_min(m_bounding_box.xmin(), m_bounding_box.ymin(), m_bounding_box.zmin()); + Local_kernel::Point_3 bb_max(m_bounding_box.xmax(), m_bounding_box.ymax(), m_bounding_box.zmax()); + + CGAL::qglviewer::Vec testPoint2(100,100, 50); + CGAL::qglviewer::Vec utestPoint2 = this->camera()->unprojectedCoordinatesOf(testPoint2); + + Local_kernel::Point_3 testPoint1(utestPoint2.x, utestPoint2.y, utestPoint2.z); + + m_buffer_for_mono_points.add_point(testPoint1); + + m_buffer_for_mono_segments.add_segment(bb_min, bb_max); + + std::cout << "bb_min: " << boundsMin << std:: endl; + std::cout << "bb_max: " << boundsMax << std::endl; + float txmin, txmax, tymin, tymax; + if(v.x() >=0 ){ + txmin = (boundsMin.x() - p.x()) * inV.x(); + txmax = (boundsMax.x() - p.x()) * inV.x(); + } else{ + txmin = (boundsMax.x() - p.x()) * inV.x(); + txmax = (boundsMin.x() - p.x()) * inV.x(); } - std::cout << std::endl; + if(v.y() >=0 ){ + tymin = (boundsMin.y() - p.y()) * inV.y(); + tymax = (boundsMax.y() - p.y()) * inV.y(); + } else{ + tymin = (boundsMax.y() - p.y()) * inV.y(); + tymax = (boundsMin.y() - p.y()) * inV.y(); + } + if(txmin > txmax) std::swap(txmin, txmax); + if(tymin > tymax ) std::swap(tymin, tymax); + + if(txmax > tymax) + txmax = tymax; + if(tymin > txmin) + txmin = tymin; + + Local_kernel::Point_2 p1(txmin, tymin); + Local_kernel::Point_2 p2(txmax, tymax); + + std::cout << "vmin: " << p1 << std::endl; + std::cout << "vmax: " << p2 << std::endl; + + CGAL::qglviewer::Vec testPoint(50, 50, 0); + int viewport[4]; + this->camera()->getViewport(viewport); + std::cout << "viewport: " << viewport[0] << ' ' << viewport[1] << ' ' + << viewport[2] << ' ' << viewport[3] << std::endl; + + CGAL::qglviewer::Vec up = this->camera()->unprojectedCoordinatesOf(testPoint); + std::cout << "origin: " << up << std::endl; + + m_buffer_for_mono_lines.add_segment(p1,p2); + //m_buffer_for_mono_lines.add_segment(p, p+ (10*v)); } bool is_a_face_started() const diff --git a/Voronoi_diagram_2/include/CGAL/draw_voronoi_diagram_2.h b/Voronoi_diagram_2/include/CGAL/draw_voronoi_diagram_2.h index 2801597a6d9..a956e056c36 100644 --- a/Voronoi_diagram_2/include/CGAL/draw_voronoi_diagram_2.h +++ b/Voronoi_diagram_2/include/CGAL/draw_voronoi_diagram_2.h @@ -106,7 +106,7 @@ protected: // face_end(); } - void compute_edge(Halfedge_const_handle he) + void compute_ray_points(Halfedge_const_handle he) { if(he->is_segment()){ add_segment(he->source()->point(), @@ -115,41 +115,34 @@ protected: Delaunay_vertex_const_handle v1 = he->up(); Delaunay_vertex_const_handle v2 = he->down(); - std::cout << "Up vertex of ray: " << std::endl; - std::cout << v1->point() << std::endl; - std::cout << "Down vertex of ray: " << std::endl; - std::cout << v2->point() << std::endl; - - Kernel::Vector_2 direction; + Kernel::Vector_2 direction(v1->point().y()-v2->point().y(), + v2->point().x()-v1->point().x());; Kernel::Point_2 end_point; if(he->has_source()){ - std::cout << "Left vertex of ray: " << std::endl; - std::cout << he->left()->point() << std::endl; - std::cout << "Source vertex of ray: " << std::endl; - std::cout << he->source()->point() << std::endl; - direction = Kernel::Vector_2(v1->point().y()-v2->point().y(), - v2->point().x()-v1->point().x()); - std::cout << "Direction of ray: " << std::endl; - std::cout << direction.x() << ' ' << direction.y() << std::endl - << std::endl; end_point = he->source()->point(); - } else { - std::cout << "Right vertex of ray: " << std::endl; - std::cout << he->right()->point() << std::endl; - std::cout << "Target vertex of ray: " << std::endl; - std::cout << he->target()->point() << std::endl; - direction = Kernel::Vector_2(v1->point().y()-v2->point().y(), - v2->point().x()-v1->point().x()); - std::cout << "Direction of ray: " << std::endl; - std::cout << direction.x() << ' ' << direction.y() << std::endl - << std::endl; - end_point = he->target()->point(); + add_ray_points(end_point, direction); } - add_line(end_point, direction); } } + void compute_rays(Halfedge_const_handle he){ + if(he->is_ray()){ + Delaunay_vertex_const_handle v1 = he->up(); + Delaunay_vertex_const_handle v2 = he->down(); + + Kernel::Vector_2 direction(v1->point().y()-v2->point().y(), + v2->point().x()-v1->point().x());; + Kernel::Point_2 end_point; + if(he->has_source()){ + end_point = he->source()->point(); + std::cout << "Bounding_box" << m_bounding_box << std::endl; + add_ray_segment(end_point, direction); + } + } + } + + void compute_vertex(Vertex_const_handle vh) { add_point(vh->point()); } @@ -169,11 +162,15 @@ protected: for (typename V2::Halfedge_iterator it=v2.halfedges_begin(); it!=v2.halfedges_end(); ++it) - { compute_edge(it); } + { compute_ray_points(it); } + + for (typename V2::Halfedge_iterator it=v2.halfedges_begin(); + it!=v2.halfedges_end(); ++it) + { compute_rays(it); } for (typename V2::Vertex_iterator it=v2.vertices_begin(); it!=v2.vertices_end(); ++it) - { compute_vertex(it); } + { compute_vertex(it); } } virtual void keyPressEvent(QKeyEvent *e) From 1d4b6242f42bbcdd541c316020c88a6cd5ab20d8 Mon Sep 17 00:00:00 2001 From: Jasmeet Singh Date: Mon, 17 Jun 2019 20:02:08 -0700 Subject: [PATCH 060/363] Show rays upto a bounding box --- GraphicsView/include/CGAL/Buffer_for_vao.h | 3 +- .../include/CGAL/Qt/Basic_viewer_qt.h | 1439 ++++++++--------- .../include/CGAL/draw_voronoi_diagram_2.h | 248 ++- 3 files changed, 808 insertions(+), 882 deletions(-) diff --git a/GraphicsView/include/CGAL/Buffer_for_vao.h b/GraphicsView/include/CGAL/Buffer_for_vao.h index 085fb2a3a84..8f448fe7d46 100644 --- a/GraphicsView/include/CGAL/Buffer_for_vao.h +++ b/GraphicsView/include/CGAL/Buffer_for_vao.h @@ -471,8 +471,9 @@ public: } return true; } + CGAL::Bbox_3 *bb() const { return m_bb; } -protected: + protected: void face_begin_internal(bool has_color, bool has_normal) { if (is_a_face_started()) diff --git a/GraphicsView/include/CGAL/Qt/Basic_viewer_qt.h b/GraphicsView/include/CGAL/Qt/Basic_viewer_qt.h index 65027317330..f428623faa2 100644 --- a/GraphicsView/include/CGAL/Qt/Basic_viewer_qt.h +++ b/GraphicsView/include/CGAL/Qt/Basic_viewer_qt.h @@ -15,7 +15,7 @@ // $URL$ // $Id$ // SPDX-License-Identifier: GPL-3.0+ -// +// // // Author(s) : Guillaume Damiand @@ -27,10 +27,10 @@ #ifdef CGAL_USE_BASIC_VIEWER -#ifdef __GNUC__ -#if __GNUC__ >= 9 -# pragma GCC diagnostic push -# pragma GCC diagnostic ignored "-Wdeprecated-copy" +#ifdef __GNUC__ +#if __GNUC__ >= 9 +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wdeprecated-copy" #endif #endif @@ -38,56 +38,51 @@ #include #include +#include #include #include -#include -#include #include +#include -#ifdef __GNUC__ +#ifdef __GNUC__ #if __GNUC__ >= 9 -# pragma GCC diagnostic pop +#pragma GCC diagnostic pop #endif #endif -#include #include +#include #include #include #include -namespace CGAL -{ +namespace CGAL { //------------------------------------------------------------------------------ -const char vertex_source_color[] = - { - "#version 120 \n" - "attribute highp vec4 vertex;\n" - "attribute highp vec3 normal;\n" - "attribute highp vec3 color;\n" - - "uniform highp mat4 mvp_matrix;\n" - "uniform highp mat4 mv_matrix; \n" - - "varying highp vec4 fP; \n" - "varying highp vec3 fN; \n" - "varying highp vec4 fColor; \n" - - "uniform highp float point_size; \n" - "void main(void)\n" - "{\n" - " fP = mv_matrix * vertex; \n" - " fN = mat3(mv_matrix)* normal; \n" - " fColor = vec4(color, 1.0); \n" - " gl_PointSize = point_size;\n" - " gl_Position = mvp_matrix * vertex;\n" - "}" - }; +const char vertex_source_color[] = {"#version 120 \n" + "attribute highp vec4 vertex;\n" + "attribute highp vec3 normal;\n" + "attribute highp vec3 color;\n" -const char fragment_source_color[] = - { + "uniform highp mat4 mvp_matrix;\n" + "uniform highp mat4 mv_matrix; \n" + + "varying highp vec4 fP; \n" + "varying highp vec3 fN; \n" + "varying highp vec4 fColor; \n" + + "uniform highp float point_size; \n" + "void main(void)\n" + "{\n" + " fP = mv_matrix * vertex; \n" + " fN = mat3(mv_matrix)* normal; \n" + " fColor = vec4(color, 1.0); \n" + " gl_PointSize = point_size;\n" + " gl_Position = mvp_matrix * vertex;\n" + "}"}; + +const char fragment_source_color[] = { "#version 120 \n" "varying highp vec4 fP; \n" "varying highp vec3 fN; \n" @@ -97,138 +92,96 @@ const char fragment_source_color[] = "uniform vec4 light_spec; \n" "uniform vec4 light_amb; \n" "uniform float spec_power ; \n" - + "void main(void) { \n" - + " vec3 L = light_pos.xyz - fP.xyz; \n" " vec3 V = -fP.xyz; \n" - + " vec3 N = normalize(fN); \n" " L = normalize(L); \n" " V = normalize(V); \n" - + " vec3 R = reflect(-L, N); \n" " vec4 diffuse = max(dot(N,L), 0.0) * light_diff * fColor; \n" " vec4 specular = pow(max(dot(R,V), 0.0), spec_power) * light_spec; \n" - + "gl_FragColor = light_amb*fColor + diffuse ; \n" "} \n" - "\n" - }; + "\n"}; -const char vertex_source_p_l[] = - { - "#version 120 \n" - "attribute highp vec4 vertex;\n" - "attribute highp vec3 color;\n" - "uniform highp mat4 mvp_matrix;\n" - "varying highp vec4 fColor; \n" - "uniform highp float point_size; \n" - "void main(void)\n" - "{\n" - " gl_PointSize = point_size;\n" - " fColor = vec4(color, 1.0); \n" - " gl_Position = mvp_matrix * vertex;\n" - "}" - }; +const char vertex_source_p_l[] = {"#version 120 \n" + "attribute highp vec4 vertex;\n" + "attribute highp vec3 color;\n" + "uniform highp mat4 mvp_matrix;\n" + "varying highp vec4 fColor; \n" + "uniform highp float point_size; \n" + "void main(void)\n" + "{\n" + " gl_PointSize = point_size;\n" + " fColor = vec4(color, 1.0); \n" + " gl_Position = mvp_matrix * vertex;\n" + "}"}; -const char fragment_source_p_l[] = - { - "#version 120 \n" - "varying highp vec4 fColor; \n" - "void main(void) { \n" - "gl_FragColor = fColor; \n" - "} \n" - "\n" - }; +const char fragment_source_p_l[] = {"#version 120 \n" + "varying highp vec4 fColor; \n" + "void main(void) { \n" + "gl_FragColor = fColor; \n" + "} \n" + "\n"}; //------------------------------------------------------------------------------ -inline CGAL::Color get_random_color(CGAL::Random& random) -{ +inline CGAL::Color get_random_color(CGAL::Random &random) { CGAL::Color res; - do - { - res=CGAL::Color(random.get_int(0,256), - random.get_int(0,256), - random.get_int(0,256)); - } - while(res.red()==255 && res.green()==255 && res.blue()==255); + do { + res = CGAL::Color(random.get_int(0, 256), random.get_int(0, 256), + random.get_int(0, 256)); + } while (res.red() == 255 && res.green() == 255 && res.blue() == 255); return res; } //------------------------------------------------------------------------------ -class Basic_viewer_qt : public CGAL::QGLViewer -{ +class Basic_viewer_qt : public CGAL::QGLViewer { public: typedef CGAL::Exact_predicates_inexact_constructions_kernel Local_kernel; - typedef Local_kernel::Point_3 Local_point; + typedef Local_kernel::Point_3 Local_point; typedef Local_kernel::Vector_3 Local_vector; // Constructor/Destructor - Basic_viewer_qt(QWidget* parent, - const char* title="", - bool draw_vertices=false, - bool draw_edges=true, - bool draw_lines=true, - bool draw_faces=true, - bool use_mono_color=false, - bool inverse_normal=false) : - CGAL::QGLViewer(parent), - m_draw_vertices(draw_vertices), - m_draw_edges(draw_edges), - m_draw_lines(draw_lines), - m_draw_faces(draw_faces), - m_flatShading(true), - m_use_mono_color(use_mono_color), - m_inverse_normal(inverse_normal), - m_size_points(7.), - m_size_edges(3.1), - m_size_lines(3.1), - m_vertices_mono_color(200, 60, 60), - m_edges_mono_color(0, 0, 0), - m_lines_mono_color(0,100,0), - m_faces_mono_color(60, 60, 200), - m_ambient_color(0.6f, 0.5f, 0.5f, 0.5f), - m_are_buffers_initialized(false), - m_buffer_for_mono_points(&arrays[POS_MONO_POINTS], - NULL, - &m_bounding_box, - NULL, NULL, NULL), - m_buffer_for_colored_points(&arrays[POS_COLORED_POINTS], - NULL, - &m_bounding_box, - &arrays[COLOR_POINTS], + Basic_viewer_qt(QWidget *parent, const char *title = "", + bool draw_vertices = false, bool draw_edges = true, + bool draw_lines = true, bool draw_faces = true, + bool use_mono_color = false, bool inverse_normal = false) + : CGAL::QGLViewer(parent), m_draw_vertices(draw_vertices), + m_draw_edges(draw_edges), m_draw_lines(draw_lines), + m_draw_faces(draw_faces), m_flatShading(true), + m_use_mono_color(use_mono_color), m_inverse_normal(inverse_normal), + m_size_points(7.), m_size_edges(3.1), m_size_lines(3.1), + m_vertices_mono_color(200, 60, 60), m_edges_mono_color(0, 0, 0), + m_lines_mono_color(0, 100, 0), m_faces_mono_color(60, 60, 200), + m_ambient_color(0.6f, 0.5f, 0.5f, 0.5f), + m_are_buffers_initialized(false), + m_buffer_for_mono_points(&arrays[POS_MONO_POINTS], NULL, + &m_bounding_box, NULL, NULL, NULL), + m_buffer_for_colored_points(&arrays[POS_COLORED_POINTS], NULL, + &m_bounding_box, &arrays[COLOR_POINTS], + NULL, NULL), + m_buffer_for_mono_segments(&arrays[POS_MONO_SEGMENTS], NULL, + &m_bounding_box, NULL, NULL, NULL), + m_buffer_for_colored_segments(&arrays[POS_COLORED_SEGMENTS], NULL, + &m_bounding_box, &arrays[COLOR_SEGMENTS], + NULL, NULL), + m_buffer_for_mono_lines(&arrays[POS_MONO_LINES], NULL, &m_bounding_box, NULL, NULL), - m_buffer_for_mono_segments(&arrays[POS_MONO_SEGMENTS], - NULL, - &m_bounding_box, - NULL, NULL, NULL), - m_buffer_for_colored_segments(&arrays[POS_COLORED_SEGMENTS], - NULL, - &m_bounding_box, - &arrays[COLOR_SEGMENTS], - NULL, NULL), - m_buffer_for_mono_lines(&arrays[POS_MONO_LINES], - NULL, - &m_bounding_box, - NULL, NULL), - m_buffer_for_colored_lines(&arrays[POS_COLORED_LINES], - NULL, - &m_bounding_box, - &arrays[COLOR_LINES], - NULL, NULL), - m_buffer_for_mono_faces(&arrays[POS_MONO_FACES], - NULL, - &m_bounding_box, - NULL, - &arrays[FLAT_NORMAL_MONO_FACES], - &arrays[SMOOTH_NORMAL_MONO_FACES]), - m_buffer_for_colored_faces(&arrays[POS_COLORED_FACES], - NULL, - &m_bounding_box, - &arrays[COLOR_FACES], - &arrays[FLAT_NORMAL_COLORED_FACES], - &arrays[SMOOTH_NORMAL_COLORED_FACES]) - { - if (title[0]==0) + m_buffer_for_colored_lines(&arrays[POS_COLORED_LINES], NULL, + &m_bounding_box, &arrays[COLOR_LINES], NULL, + NULL), + m_buffer_for_mono_faces(&arrays[POS_MONO_FACES], NULL, &m_bounding_box, + NULL, &arrays[FLAT_NORMAL_MONO_FACES], + &arrays[SMOOTH_NORMAL_MONO_FACES]), + m_buffer_for_colored_faces(&arrays[POS_COLORED_FACES], NULL, + &m_bounding_box, &arrays[COLOR_FACES], + &arrays[FLAT_NORMAL_COLORED_FACES], + &arrays[SMOOTH_NORMAL_COLORED_FACES]) { + if (title[0] == 0) setWindowTitle("CGAL Basic Viewer"); else setWindowTitle(title); @@ -236,25 +189,23 @@ public: resize(500, 450); } - ~Basic_viewer_qt() - { - for (unsigned int i=0; i - void add_point(const KPoint& p) - { m_buffer_for_mono_points.add_point(p); } + const CGAL::Bbox_3 &bounding_box() const { return m_bounding_box; } - template - void add_point(const KPoint& p, const CGAL::Color& acolor) - { m_buffer_for_colored_points.add_point(p, acolor); } - - template - void add_segment(const KPoint& p1, const KPoint& p2) - { m_buffer_for_mono_segments.add_segment(p1, p2); } - - template - void add_segment(const KPoint& p1, const KPoint& p2, - const CGAL::Color& acolor) - { m_buffer_for_colored_segments.add_segment(p1, p2, acolor); } - - template - void add_ray_points(const KPoint& p, const KVector& v) - { std::cout << "Ray starting from " << p << " with direction " << v << std::endl; - std::cout << "Bounding_box" << m_bounding_box << std::endl; - m_buffer_for_mono_segments.add_segment(p, p+v); - //m_buffer_for_mono_points.add_point(p+v); + template void add_point(const KPoint &p) { + m_buffer_for_mono_points.add_point(p); } - template - void add_ray_segment(const KPoint& p, const KVector& v) - { - Local_kernel::Vector_2 V(v/CGAL::sqrt(v.squared_length())); - std::cout << "v: " << V << std::endl; - - Local_kernel::Vector_2 inV = V/CGAL::sqrt(v.squared_length()); - - Local_kernel::Vector_2 boundsMin(m_bounding_box.xmin(), m_bounding_box.zmin()); - Local_kernel::Vector_2 boundsMax(m_bounding_box.xmax(), m_bounding_box.zmax()); - - Local_kernel::Point_3 bb_min(m_bounding_box.xmin(), m_bounding_box.ymin(), m_bounding_box.zmin()); - Local_kernel::Point_3 bb_max(m_bounding_box.xmax(), m_bounding_box.ymax(), m_bounding_box.zmax()); - - CGAL::qglviewer::Vec testPoint2(100,100, 50); - CGAL::qglviewer::Vec utestPoint2 = this->camera()->unprojectedCoordinatesOf(testPoint2); - - Local_kernel::Point_3 testPoint1(utestPoint2.x, utestPoint2.y, utestPoint2.z); - - m_buffer_for_mono_points.add_point(testPoint1); - - m_buffer_for_mono_segments.add_segment(bb_min, bb_max); - - std::cout << "bb_min: " << boundsMin << std:: endl; - std::cout << "bb_max: " << boundsMax << std::endl; - float txmin, txmax, tymin, tymax; - if(v.x() >=0 ){ - txmin = (boundsMin.x() - p.x()) * inV.x(); - txmax = (boundsMax.x() - p.x()) * inV.x(); - } else{ - txmin = (boundsMax.x() - p.x()) * inV.x(); - txmax = (boundsMin.x() - p.x()) * inV.x(); - } - if(v.y() >=0 ){ - tymin = (boundsMin.y() - p.y()) * inV.y(); - tymax = (boundsMax.y() - p.y()) * inV.y(); - } else{ - tymin = (boundsMax.y() - p.y()) * inV.y(); - tymax = (boundsMin.y() - p.y()) * inV.y(); - } - if(txmin > txmax) std::swap(txmin, txmax); - if(tymin > tymax ) std::swap(tymin, tymax); - - if(txmax > tymax) - txmax = tymax; - if(tymin > txmin) - txmin = tymin; - - Local_kernel::Point_2 p1(txmin, tymin); - Local_kernel::Point_2 p2(txmax, tymax); - - std::cout << "vmin: " << p1 << std::endl; - std::cout << "vmax: " << p2 << std::endl; - - CGAL::qglviewer::Vec testPoint(50, 50, 0); - int viewport[4]; - this->camera()->getViewport(viewport); - std::cout << "viewport: " << viewport[0] << ' ' << viewport[1] << ' ' - << viewport[2] << ' ' << viewport[3] << std::endl; - - CGAL::qglviewer::Vec up = this->camera()->unprojectedCoordinatesOf(testPoint); - std::cout << "origin: " << up << std::endl; - - m_buffer_for_mono_lines.add_segment(p1,p2); - //m_buffer_for_mono_lines.add_segment(p, p+ (10*v)); + template + void add_point(const KPoint &p, const CGAL::Color &acolor) { + m_buffer_for_colored_points.add_point(p, acolor); } - bool is_a_face_started() const - { + template + void add_segment(const KPoint &p1, const KPoint &p2) { + m_buffer_for_mono_segments.add_segment(p1, p2); + } + + template + void add_segment(const KPoint &p1, const KPoint &p2, + const CGAL::Color &acolor) { + m_buffer_for_colored_segments.add_segment(p1, p2, acolor); + } + + template + void add_ray_points(const KPoint &p, const KVector &v) { + m_buffer_for_mono_points.add_point(p); + m_buffer_for_mono_points.add_point(p + v); + } + + template + void add_ray_segment(const KPoint &p, const KVector &v) { + Local_kernel::Vector_2 boundsMin(m_bounding_box.xmin(), + m_bounding_box.zmin()); + Local_kernel::Vector_2 boundsMax(m_bounding_box.xmax(), + m_bounding_box.zmax()); + + Local_kernel::Vector_2 inv(1 / v.x(), 1 / v.y()); + + double txmax, txmin, tymax, tymin; + + if (inv.x() >= 0) { + txmax = (boundsMax.x() - p.x()) * inv.x(); + txmin = (boundsMin.x() - p.x()) * inv.x(); + } else { + txmax = (boundsMin.x() - p.x()) * inv.x(); + txmin = (boundsMax.x() - p.x()) * inv.x(); + } + + if (inv.y() >= 0) { + tymax = (boundsMax.y() - p.y()) * inv.y(); + tymin = (boundsMin.y() - p.y()) * inv.y(); + } else { + tymax = (boundsMin.y() - p.y()) * inv.y(); + tymin = (boundsMax.y() - p.y()) * inv.y(); + } + + if (tymin > txmin) + txmin = tymin; + if (tymax < txmax) + txmax = tymax; + + Local_kernel::Point_2 p1; + if (v.x() == 0) { + p1 = Local_kernel::Point_2(p.x(), p.y() + tymax * v.y()); + } else if (v.y() == 0) { + p1 = Local_kernel::Point_2(p.x() + txmax * v.x(), p.y()); + } else { + p1 = Local_kernel::Point_2(p.x() + txmax * v.x(), p.y() + tymax * v.y()); + } + + m_buffer_for_mono_segments.add_segment(p, p1); + } + + bool is_a_face_started() const { return m_buffer_for_mono_faces.is_a_face_started() || - m_buffer_for_colored_faces.is_a_face_started(); - } - - void face_begin() - { - if (is_a_face_started()) - { - std::cerr<<"You cannot start a new face before to finish the previous one."< - bool add_point_in_face(const KPoint& kp) - { - if (m_buffer_for_mono_faces.is_a_face_started()) - { return m_buffer_for_mono_faces.add_point_in_face(kp); } - else if (m_buffer_for_colored_faces.is_a_face_started()) - { return m_buffer_for_colored_faces.add_point_in_face(kp); } - return false; + void face_begin() { + if (is_a_face_started()) { + std::cerr + << "You cannot start a new face before to finish the previous one." + << std::endl; + } else { + m_buffer_for_mono_faces.face_begin(); + } } - - template - bool add_point_in_face(const KPoint& kp, const KVector& p_normal) - { - if (m_buffer_for_mono_faces.is_a_face_started()) - { return m_buffer_for_mono_faces.add_point_in_face(kp, p_normal); } - else if (m_buffer_for_colored_faces.is_a_face_started()) - { return m_buffer_for_colored_faces.add_point_in_face(kp, p_normal); } + + void face_begin(const CGAL::Color &acolor) { + if (is_a_face_started()) { + std::cerr + << "You cannot start a new face before to finish the previous one." + << std::endl; + } else { + m_buffer_for_colored_faces.face_begin(acolor); + } + } + + template bool add_point_in_face(const KPoint &kp) { + if (m_buffer_for_mono_faces.is_a_face_started()) { + return m_buffer_for_mono_faces.add_point_in_face(kp); + } else if (m_buffer_for_colored_faces.is_a_face_started()) { + return m_buffer_for_colored_faces.add_point_in_face(kp); + } return false; } - void face_end() - { - if (m_buffer_for_mono_faces.is_a_face_started()) - { m_buffer_for_mono_faces.face_end(); } - else if (m_buffer_for_colored_faces.is_a_face_started()) - { return m_buffer_for_colored_faces.face_end(); } + template + bool add_point_in_face(const KPoint &kp, const KVector &p_normal) { + if (m_buffer_for_mono_faces.is_a_face_started()) { + return m_buffer_for_mono_faces.add_point_in_face(kp, p_normal); + } else if (m_buffer_for_colored_faces.is_a_face_started()) { + return m_buffer_for_colored_faces.add_point_in_face(kp, p_normal); + } + return false; + } + + void face_end() { + if (m_buffer_for_mono_faces.is_a_face_started()) { + m_buffer_for_mono_faces.face_end(); + } else if (m_buffer_for_colored_faces.is_a_face_started()) { + return m_buffer_for_colored_faces.face_end(); + } } protected: - void compile_shaders() - { + void compile_shaders() { rendering_program_face.removeAllShaders(); rendering_program_p_l.removeAllShaders(); - + // Create the buffers - for (unsigned int i=0; icompileSourceCode(vertex_source_p_l)) - { std::cerr<<"Compiling vertex source FAILED"<compileSourceCode(vertex_source_p_l)) { + std::cerr << "Compiling vertex source FAILED" << std::endl; + } - QOpenGLShader *fragment_shader_p_l= new QOpenGLShader(QOpenGLShader::Fragment); - if(!fragment_shader_p_l->compileSourceCode(fragment_source_p_l)) - { std::cerr<<"Compiling fragmentsource FAILED"<compileSourceCode(fragment_source_p_l)) { + std::cerr << "Compiling fragmentsource FAILED" << std::endl; + } - if(!rendering_program_p_l.addShader(vertex_shader_p_l)) - { std::cerr<<"adding vertex shader FAILED"<compileSourceCode(vertex_source_color)) - { std::cerr<<"Compiling vertex source FAILED"<compileSourceCode(vertex_source_color)) { + std::cerr << "Compiling vertex source FAILED" << std::endl; + } - QOpenGLShader *fragment_shader_face= new QOpenGLShader(QOpenGLShader::Fragment); - if(!fragment_shader_face->compileSourceCode(fragment_source_color)) - { std::cerr<<"Compiling fragmentsource FAILED"<compileSourceCode(fragment_source_color)) { + std::cerr << "Compiling fragmentsource FAILED" << std::endl; + } - if(!rendering_program_face.addShader(vertex_shader_face)) - { std::cerr<<"adding vertex shader FAILED"<(arrays[POS_MONO_POINTS].size()*sizeof(float))); + buffers[bufn].allocate( + arrays[POS_MONO_POINTS].data(), + static_cast(arrays[POS_MONO_POINTS].size() * sizeof(float))); rendering_program_p_l.enableAttributeArray("vertex"); - rendering_program_p_l.setAttributeBuffer("vertex",GL_FLOAT,0,3); + rendering_program_p_l.setAttributeBuffer("vertex", GL_FLOAT, 0, 3); buffers[bufn].release(); rendering_program_p_l.disableAttributeArray("color"); - + vao[VAO_MONO_POINTS].release(); - + // 1.2) Color points vao[VAO_COLORED_POINTS].bind(); ++bufn; - assert(bufn(arrays[POS_COLORED_POINTS].size()*sizeof(float))); + buffers[bufn].allocate( + arrays[POS_COLORED_POINTS].data(), + static_cast(arrays[POS_COLORED_POINTS].size() * sizeof(float))); rendering_program_p_l.enableAttributeArray("vertex"); - rendering_program_p_l.setAttributeBuffer("vertex",GL_FLOAT,0,3); + rendering_program_p_l.setAttributeBuffer("vertex", GL_FLOAT, 0, 3); buffers[bufn].release(); - ++bufn; - assert(bufn(arrays[COLOR_POINTS].size()*sizeof(float))); + buffers[bufn].allocate( + arrays[COLOR_POINTS].data(), + static_cast(arrays[COLOR_POINTS].size() * sizeof(float))); rendering_program_p_l.enableAttributeArray("color"); - rendering_program_p_l.setAttributeBuffer("color",GL_FLOAT,0,3); + rendering_program_p_l.setAttributeBuffer("color", GL_FLOAT, 0, 3); buffers[bufn].release(); vao[VAO_COLORED_POINTS].release(); // 2) SEGMENT SHADER - + // 2.1) Mono segments vao[VAO_MONO_SEGMENTS].bind(); - - ++bufn; - assert(bufn(arrays[POS_MONO_SEGMENTS].size()*sizeof(float))); + buffers[bufn].allocate( + arrays[POS_MONO_SEGMENTS].data(), + static_cast(arrays[POS_MONO_SEGMENTS].size() * sizeof(float))); rendering_program_p_l.enableAttributeArray("vertex"); - rendering_program_p_l.setAttributeBuffer("vertex",GL_FLOAT,0,3); + rendering_program_p_l.setAttributeBuffer("vertex", GL_FLOAT, 0, 3); buffers[bufn].release(); @@ -531,42 +472,45 @@ protected: // 1.2) Color segments vao[VAO_COLORED_SEGMENTS].bind(); - + ++bufn; - assert(bufn(arrays[POS_COLORED_SEGMENTS].size()*sizeof(float))); + buffers[bufn].allocate( + arrays[POS_COLORED_SEGMENTS].data(), + static_cast(arrays[POS_COLORED_SEGMENTS].size() * sizeof(float))); rendering_program_p_l.enableAttributeArray("vertex"); - rendering_program_p_l.setAttributeBuffer("vertex",GL_FLOAT,0,3); + rendering_program_p_l.setAttributeBuffer("vertex", GL_FLOAT, 0, 3); buffers[bufn].release(); ++bufn; - assert(bufn(arrays[COLOR_SEGMENTS].size()*sizeof(float))); + buffers[bufn].allocate( + arrays[COLOR_SEGMENTS].data(), + static_cast(arrays[COLOR_SEGMENTS].size() * sizeof(float))); rendering_program_p_l.enableAttributeArray("color"); - rendering_program_p_l.setAttributeBuffer("color",GL_FLOAT,0,3); + rendering_program_p_l.setAttributeBuffer("color", GL_FLOAT, 0, 3); buffers[bufn].release(); vao[VAO_COLORED_SEGMENTS].release(); - + rendering_program_p_l.release(); - + // 3) LINE SHADER // 3.1) Mono lines vao[VAO_MONO_LINES].bind(); ++bufn; - assert(bufn(arrays[POS_MONO_LINES].size()*sizeof(float))); + buffers[bufn].allocate( + arrays[POS_MONO_LINES].data(), + static_cast(arrays[POS_MONO_LINES].size() * sizeof(float))); rendering_program_p_l.enableAttributeArray("vertex"); - rendering_program_p_l.setAttributeArray("vertex",GL_FLOAT,0,3); + rendering_program_p_l.setAttributeArray("vertex", GL_FLOAT, 0, 3); buffers[bufn].release(); @@ -579,22 +523,24 @@ protected: vao[VAO_COLORED_LINES].bind(); ++bufn; - assert(bufn(arrays[POS_COLORED_LINES].size()*sizeof(float))); + buffers[bufn].allocate( + arrays[POS_COLORED_LINES].data(), + static_cast(arrays[POS_COLORED_LINES].size() * sizeof(float))); rendering_program_p_l.enableAttributeArray("vertex"); - rendering_program_p_l.setAttributeBuffer("vertex",GL_FLOAT,0,3); + rendering_program_p_l.setAttributeBuffer("vertex", GL_FLOAT, 0, 3); buffers[bufn].release(); ++bufn; - assert(bufn(arrays[COLOR_LINES].size()*sizeof(float))); + buffers[bufn].allocate( + arrays[COLOR_LINES].data(), + static_cast(arrays[COLOR_LINES].size() * sizeof(float))); rendering_program_p_l.enableAttributeArray("color"); - rendering_program_p_l.setAttributeBuffer("color",GL_FLOAT,0,3); + rendering_program_p_l.setAttributeBuffer("color", GL_FLOAT, 0, 3); buffers[bufn].release(); vao[VAO_COLORED_LINES].release(); @@ -609,34 +555,34 @@ protected: // 3.1.1) points of the mono faces ++bufn; - assert(bufn(arrays[POS_MONO_FACES].size()*sizeof(float))); + buffers[bufn].allocate( + arrays[POS_MONO_FACES].data(), + static_cast(arrays[POS_MONO_FACES].size() * sizeof(float))); rendering_program_face.enableAttributeArray("vertex"); - rendering_program_face.setAttributeBuffer("vertex",GL_FLOAT,0,3); + rendering_program_face.setAttributeBuffer("vertex", GL_FLOAT, 0, 3); buffers[bufn].release(); - + // 3.1.2) normals of the mono faces ++bufn; - assert(bufn(arrays[FLAT_NORMAL_MONO_FACES].size()* - sizeof(float))); - } - else - { - buffers[bufn].allocate(arrays[SMOOTH_NORMAL_MONO_FACES].data(), - static_cast(arrays[SMOOTH_NORMAL_MONO_FACES].size()* - sizeof(float))); + if (m_flatShading) { + buffers[bufn].allocate( + arrays[FLAT_NORMAL_MONO_FACES].data(), + static_cast(arrays[FLAT_NORMAL_MONO_FACES].size() * + sizeof(float))); + } else { + buffers[bufn].allocate( + arrays[SMOOTH_NORMAL_MONO_FACES].data(), + static_cast(arrays[SMOOTH_NORMAL_MONO_FACES].size() * + sizeof(float))); } rendering_program_face.enableAttributeArray("normal"); - rendering_program_face.setAttributeBuffer("normal",GL_FLOAT,0,3); - + rendering_program_face.setAttributeBuffer("normal", GL_FLOAT, 0, 3); + buffers[bufn].release(); // 3.1.3) color of the mono faces @@ -645,96 +591,88 @@ protected: // 3.2) Color faces vao[VAO_COLORED_FACES].bind(); - - // 3.2.1) points of the color faces + + // 3.2.1) points of the color faces ++bufn; - assert(bufn(arrays[POS_COLORED_FACES].size()*sizeof(float))); + buffers[bufn].allocate( + arrays[POS_COLORED_FACES].data(), + static_cast(arrays[POS_COLORED_FACES].size() * sizeof(float))); rendering_program_face.enableAttributeArray("vertex"); - rendering_program_face.setAttributeBuffer("vertex",GL_FLOAT,0,3); - + rendering_program_face.setAttributeBuffer("vertex", GL_FLOAT, 0, 3); + buffers[bufn].release(); - + // 3.2.2) normals of the color faces ++bufn; - assert(bufn(arrays[FLAT_NORMAL_COLORED_FACES].size()* - sizeof(float))); - } - else - { - buffers[bufn].allocate(arrays[SMOOTH_NORMAL_COLORED_FACES].data(), - static_cast(arrays[SMOOTH_NORMAL_COLORED_FACES].size()* - sizeof(float))); + if (m_flatShading) { + buffers[bufn].allocate( + arrays[FLAT_NORMAL_COLORED_FACES].data(), + static_cast(arrays[FLAT_NORMAL_COLORED_FACES].size() * + sizeof(float))); + } else { + buffers[bufn].allocate( + arrays[SMOOTH_NORMAL_COLORED_FACES].data(), + static_cast(arrays[SMOOTH_NORMAL_COLORED_FACES].size() * + sizeof(float))); } rendering_program_face.enableAttributeArray("normal"); - rendering_program_face.setAttributeBuffer("normal",GL_FLOAT,0,3); - + rendering_program_face.setAttributeBuffer("normal", GL_FLOAT, 0, 3); + buffers[bufn].release(); - + // 3.2.3) colors of the faces ++bufn; - assert(bufn(arrays[COLOR_FACES].size()*sizeof(float))); + buffers[bufn].allocate( + arrays[COLOR_FACES].data(), + static_cast(arrays[COLOR_FACES].size() * sizeof(float))); rendering_program_face.enableAttributeArray("color"); - rendering_program_face.setAttributeBuffer("color",GL_FLOAT,0,3); - + rendering_program_face.setAttributeBuffer("color", GL_FLOAT, 0, 3); + buffers[bufn].release(); - + vao[VAO_COLORED_FACES].release(); - + rendering_program_face.release(); - + m_are_buffers_initialized = true; } - void attrib_buffers(CGAL::QGLViewer* viewer) - { + void attrib_buffers(CGAL::QGLViewer *viewer) { QMatrix4x4 mvpMatrix; QMatrix4x4 mvMatrix; double mat[16]; viewer->camera()->getModelViewProjectionMatrix(mat); - for(int i=0; i < 16; i++) - { + for (int i = 0; i < 16; i++) { mvpMatrix.data()[i] = (float)mat[i]; } viewer->camera()->getModelViewMatrix(mat); - for(int i=0; i < 16; i++) - { + for (int i = 0; i < 16; i++) { mvMatrix.data()[i] = (float)mat[i]; } // define material - QVector4D diffuse( 0.9f, - 0.9f, - 0.9f, - 0.9f ); + QVector4D diffuse(0.9f, 0.9f, 0.9f, 0.9f); - QVector4D specular( 0.0f, - 0.0f, - 0.0f, - 1.0f ); + QVector4D specular(0.0f, 0.0f, 0.0f, 1.0f); CGAL::Bbox_3 bb; - if (bb==bounding_box()) // Case of "empty" bounding box - { - bb=Local_point(CGAL::ORIGIN).bbox(); - bb=bb + Local_point(1,1,1).bbox(); // To avoid a warning from Qglviewer + if (bb == bounding_box()) // Case of "empty" bounding box + { + bb = Local_point(CGAL::ORIGIN).bbox(); + bb = + bb + Local_point(1, 1, 1).bbox(); // To avoid a warning from Qglviewer + } else { + bb = bounding_box(); } - else - { bb=bounding_box(); } - - QVector4D position((bb.xmax()-bb.xmin())/2, - (bb.ymax()-bb.ymin())/2, + + QVector4D position((bb.xmax() - bb.xmin()) / 2, (bb.ymax() - bb.ymin()) / 2, bb.zmax(), 0.0); - GLfloat shininess = 1.0f; + GLfloat shininess = 1.0f; rendering_program_face.bind(); int mvpLocation = rendering_program_face.uniformLocation("mvp_matrix"); @@ -754,187 +692,187 @@ protected: rendering_program_face.setUniformValue(mvpLocation, mvpMatrix); rendering_program_face.setUniformValue(mvLocation, mvMatrix); rendering_program_face.release(); - + rendering_program_p_l.bind(); int mvpLocation2 = rendering_program_p_l.uniformLocation("mvp_matrix"); rendering_program_p_l.setUniformValue(mvpLocation2, mvpMatrix); rendering_program_p_l.release(); } - virtual void draw() - { + virtual void draw() { glEnable(GL_DEPTH_TEST); - if(!m_are_buffers_initialized) - { initialize_buffers(); } + if (!m_are_buffers_initialized) { + initialize_buffers(); + } QColor color; attrib_buffers(this); - if(m_draw_vertices) - { + if (m_draw_vertices) { rendering_program_p_l.bind(); vao[VAO_MONO_POINTS].bind(); - color.setRgbF((double)m_vertices_mono_color.red()/(double)255, - (double)m_vertices_mono_color.green()/(double)255, - (double)m_vertices_mono_color.blue()/(double)255); - rendering_program_p_l.setAttributeValue("color",color); - rendering_program_p_l.setUniformValue("point_size", GLfloat(m_size_points)); - glDrawArrays(GL_POINTS, 0, static_cast(arrays[POS_MONO_POINTS].size()/3)); + color.setRgbF((double)m_vertices_mono_color.red() / (double)255, + (double)m_vertices_mono_color.green() / (double)255, + (double)m_vertices_mono_color.blue() / (double)255); + rendering_program_p_l.setAttributeValue("color", color); + rendering_program_p_l.setUniformValue("point_size", + GLfloat(m_size_points)); + glDrawArrays(GL_POINTS, 0, + static_cast(arrays[POS_MONO_POINTS].size() / 3)); vao[VAO_MONO_POINTS].release(); - + vao[VAO_COLORED_POINTS].bind(); - if (m_use_mono_color) - { - color.setRgbF((double)m_vertices_mono_color.red()/(double)255, - (double)m_vertices_mono_color.green()/(double)255, - (double)m_vertices_mono_color.blue()/(double)255); + if (m_use_mono_color) { + color.setRgbF((double)m_vertices_mono_color.red() / (double)255, + (double)m_vertices_mono_color.green() / (double)255, + (double)m_vertices_mono_color.blue() / (double)255); rendering_program_p_l.disableAttributeArray("color"); - rendering_program_p_l.setAttributeValue("color",color); - } - else - { + rendering_program_p_l.setAttributeValue("color", color); + } else { rendering_program_p_l.enableAttributeArray("color"); } - rendering_program_p_l.setUniformValue("point_size", GLfloat(m_size_points)); - glDrawArrays(GL_POINTS, 0, static_cast(arrays[POS_COLORED_POINTS].size()/3)); + rendering_program_p_l.setUniformValue("point_size", + GLfloat(m_size_points)); + glDrawArrays(GL_POINTS, 0, + static_cast(arrays[POS_COLORED_POINTS].size() / 3)); vao[VAO_COLORED_POINTS].release(); rendering_program_p_l.release(); } - if(m_draw_edges) - { + if (m_draw_edges) { rendering_program_p_l.bind(); vao[VAO_MONO_SEGMENTS].bind(); - color.setRgbF((double)m_edges_mono_color.red()/(double)255, - (double)m_edges_mono_color.green()/(double)255, - (double)m_edges_mono_color.blue()/(double)255); - rendering_program_p_l.setAttributeValue("color",color); + color.setRgbF((double)m_edges_mono_color.red() / (double)255, + (double)m_edges_mono_color.green() / (double)255, + (double)m_edges_mono_color.blue() / (double)255); + rendering_program_p_l.setAttributeValue("color", color); glLineWidth(m_size_edges); - glDrawArrays(GL_LINES, 0, static_cast(arrays[POS_MONO_SEGMENTS].size()/3)); + glDrawArrays(GL_LINES, 0, + static_cast(arrays[POS_MONO_SEGMENTS].size() / 3)); vao[VAO_MONO_SEGMENTS].release(); vao[VAO_COLORED_SEGMENTS].bind(); - if (m_use_mono_color) - { - color.setRgbF((double)m_edges_mono_color.red()/(double)255, - (double)m_edges_mono_color.green()/(double)255, - (double)m_edges_mono_color.blue()/(double)255); + if (m_use_mono_color) { + color.setRgbF((double)m_edges_mono_color.red() / (double)255, + (double)m_edges_mono_color.green() / (double)255, + (double)m_edges_mono_color.blue() / (double)255); rendering_program_p_l.disableAttributeArray("color"); - rendering_program_p_l.setAttributeValue("color",color); - } - else - { + rendering_program_p_l.setAttributeValue("color", color); + } else { rendering_program_p_l.enableAttributeArray("color"); } glLineWidth(m_size_edges); - glDrawArrays(GL_LINES, 0, static_cast(arrays[POS_COLORED_SEGMENTS].size()/3)); + glDrawArrays( + GL_LINES, 0, + static_cast(arrays[POS_COLORED_SEGMENTS].size() / 3)); vao[VAO_COLORED_SEGMENTS].release(); rendering_program_p_l.release(); } - if(m_draw_lines) - { - rendering_program_p_l.bind(); + if (m_draw_lines) { + rendering_program_p_l.bind(); - vao[VAO_MONO_LINES].bind(); - color.setRgbF((double)m_lines_mono_color.red()/(double)255, - (double)m_lines_mono_color.green()/(double)255, - (double)m_lines_mono_color.blue()/(double)255); - rendering_program_p_l.setAttributeValue("color",color); - glLineWidth(m_size_lines); - glDrawArrays(GL_LINES, 0, static_cast(arrays[POS_MONO_LINES].size()/3)); - vao[VAO_MONO_SEGMENTS].release(); + vao[VAO_MONO_LINES].bind(); + color.setRgbF((double)m_lines_mono_color.red() / (double)255, + (double)m_lines_mono_color.green() / (double)255, + (double)m_lines_mono_color.blue() / (double)255); + rendering_program_p_l.setAttributeValue("color", color); + glLineWidth(m_size_lines); + glDrawArrays(GL_LINES, 0, + static_cast(arrays[POS_MONO_LINES].size() / 3)); + vao[VAO_MONO_LINES].release(); - vao[VAO_COLORED_SEGMENTS].bind(); - if (m_use_mono_color) - { - color.setRgbF((double)m_lines_mono_color.red()/(double)255, - (double)m_lines_mono_color.green()/(double)255, - (double)m_lines_mono_color.blue()/(double)255); - rendering_program_p_l.disableAttributeArray("color"); - rendering_program_p_l.setAttributeValue("color",color); - } - else - { - rendering_program_p_l.enableAttributeArray("color"); - } - glLineWidth(m_size_lines); - glDrawArrays(GL_LINES, 0, static_cast(arrays[POS_COLORED_LINES].size()/3)); - vao[VAO_COLORED_LINES].release(); + vao[VAO_COLORED_LINES].bind(); + if (m_use_mono_color) { + color.setRgbF((double)m_lines_mono_color.red() / (double)255, + (double)m_lines_mono_color.green() / (double)255, + (double)m_lines_mono_color.blue() / (double)255); + rendering_program_p_l.disableAttributeArray("color"); + rendering_program_p_l.setAttributeValue("color", color); + } else { + rendering_program_p_l.enableAttributeArray("color"); + } + glLineWidth(m_size_lines); + glDrawArrays(GL_LINES, 0, + static_cast(arrays[POS_COLORED_LINES].size() / 3)); + vao[VAO_COLORED_LINES].release(); - rendering_program_p_l.release(); + rendering_program_p_l.release(); } - if (m_draw_faces) - { + if (m_draw_faces) { rendering_program_face.bind(); vao[VAO_MONO_FACES].bind(); - color.setRgbF((double)m_faces_mono_color.red()/(double)255, - (double)m_faces_mono_color.green()/(double)255, - (double)m_faces_mono_color.blue()/(double)255); - rendering_program_face.setAttributeValue("color",color); - glDrawArrays(GL_TRIANGLES, 0, static_cast(arrays[POS_MONO_FACES].size()/3)); + color.setRgbF((double)m_faces_mono_color.red() / (double)255, + (double)m_faces_mono_color.green() / (double)255, + (double)m_faces_mono_color.blue() / (double)255); + rendering_program_face.setAttributeValue("color", color); + glDrawArrays(GL_TRIANGLES, 0, + static_cast(arrays[POS_MONO_FACES].size() / 3)); vao[VAO_MONO_FACES].release(); vao[VAO_COLORED_FACES].bind(); - if (m_use_mono_color) - { - color.setRgbF((double)m_faces_mono_color.red()/(double)255, - (double)m_faces_mono_color.green()/(double)255, - (double)m_faces_mono_color.blue()/(double)255); + if (m_use_mono_color) { + color.setRgbF((double)m_faces_mono_color.red() / (double)255, + (double)m_faces_mono_color.green() / (double)255, + (double)m_faces_mono_color.blue() / (double)255); rendering_program_face.disableAttributeArray("color"); - rendering_program_face.setAttributeValue("color",color); - } - else - { + rendering_program_face.setAttributeValue("color", color); + } else { rendering_program_face.enableAttributeArray("color"); } - glDrawArrays(GL_TRIANGLES, 0, static_cast(arrays[POS_COLORED_FACES].size()/3)); + glDrawArrays(GL_TRIANGLES, 0, + static_cast(arrays[POS_COLORED_FACES].size() / 3)); vao[VAO_COLORED_FACES].release(); rendering_program_face.release(); } } - virtual void redraw() - { + virtual void redraw() { initialize_buffers(); update(); } - - virtual void init() - { + + virtual void init() { // Restore previous viewer state. restoreStateFromFile(); initializeOpenGLFunctions(); // Define 'Control+Q' as the new exit shortcut (default was 'Escape') - setShortcut(qglviewer::EXIT_VIEWER, ::Qt::CTRL+::Qt::Key_Q); + setShortcut(qglviewer::EXIT_VIEWER, ::Qt::CTRL + ::Qt::Key_Q); // Add custom key description (see keyPressEvent). setKeyDescription(::Qt::Key_E, "Toggles edges display"); setKeyDescription(::Qt::Key_F, "Toggles faces display"); - setKeyDescription(::Qt::Key_G, "Switch between flat/Gouraud shading display"); + setKeyDescription(::Qt::Key_G, + "Switch between flat/Gouraud shading display"); setKeyDescription(::Qt::Key_M, "Toggles mono color"); setKeyDescription(::Qt::Key_N, "Inverse direction of normals"); setKeyDescription(::Qt::Key_V, "Toggles vertices display"); setKeyDescription(::Qt::Key_Plus, "Increase size of edges"); setKeyDescription(::Qt::Key_Minus, "Decrease size of edges"); - setKeyDescription(::Qt::Key_Plus+::Qt::ControlModifier, "Increase size of vertices"); - setKeyDescription(::Qt::Key_Minus+::Qt::ControlModifier, "Decrease size of vertices"); - setKeyDescription(::Qt::Key_PageDown, "Increase light (all colors, use shift/alt/ctrl for one rgb component)"); - setKeyDescription(::Qt::Key_PageUp, "Decrease light (all colors, use shift/alt/ctrl for one rgb component)"); + setKeyDescription(::Qt::Key_Plus + ::Qt::ControlModifier, + "Increase size of vertices"); + setKeyDescription(::Qt::Key_Minus + ::Qt::ControlModifier, + "Decrease size of vertices"); + setKeyDescription(::Qt::Key_PageDown, + "Increase light (all colors, use shift/alt/ctrl for one " + "rgb component)"); + setKeyDescription(::Qt::Key_PageUp, + "Decrease light (all colors, use shift/alt/ctrl for one " + "rgb component)"); // Light default parameters glLineWidth(m_size_edges); glEnable(GL_POLYGON_OFFSET_FILL); - glPolygonOffset(1.f,1.f); - glClearColor(1.0f,1.0f,1.0f,0.0f); + glPolygonOffset(1.f, 1.f); + glClearColor(1.0f, 1.0f, 1.0f, 0.0f); glDisable(GL_BLEND); glEnable(GL_LINE_SMOOTH); glDisable(GL_POLYGON_SMOOTH_HINT); @@ -944,207 +882,215 @@ protected: compile_shaders(); CGAL::Bbox_3 bb; - if (bb==bounding_box()) // Case of "empty" bounding box - { - bb=Local_point(CGAL::ORIGIN).bbox(); - bb=bb + Local_point(1,1,1).bbox(); // To avoid a warning from Qglviewer + if (bb == bounding_box()) // Case of "empty" bounding box + { + bb = Local_point(CGAL::ORIGIN).bbox(); + bb = + bb + Local_point(1, 1, 1).bbox(); // To avoid a warning from Qglviewer + } else { + bb = bounding_box(); } - else - { bb=bounding_box(); } - this->camera()->setSceneBoundingBox(CGAL::qglviewer::Vec(bb.xmin(), - bb.ymin(), - bb.zmin()), - CGAL::qglviewer::Vec(bb.xmax(), - bb.ymax(), - bb.zmax())); + this->camera()->setSceneBoundingBox( + CGAL::qglviewer::Vec(bb.xmin(), bb.ymin(), bb.zmin()), + CGAL::qglviewer::Vec(bb.xmax(), bb.ymax(), bb.zmax())); this->showEntireScene(); } - void negate_all_normals() - { - for (unsigned int k=BEGIN_NORMAL; kmodifiers(); - if ((e->key()==::Qt::Key_E) && (modifiers==::Qt::NoButton)) - { - m_draw_edges=!m_draw_edges; - displayMessage(QString("Draw edges=%1.").arg(m_draw_edges?"true":"false")); + if ((e->key() == ::Qt::Key_E) && (modifiers == ::Qt::NoButton)) { + m_draw_edges = !m_draw_edges; + displayMessage( + QString("Draw edges=%1.").arg(m_draw_edges ? "true" : "false")); update(); - } - else if ((e->key()==::Qt::Key_F) && (modifiers==::Qt::NoButton)) - { - m_draw_faces=!m_draw_faces; - displayMessage(QString("Draw faces=%1.").arg(m_draw_faces?"true":"false")); + } else if ((e->key() == ::Qt::Key_F) && (modifiers == ::Qt::NoButton)) { + m_draw_faces = !m_draw_faces; + displayMessage( + QString("Draw faces=%1.").arg(m_draw_faces ? "true" : "false")); update(); - } - else if ((e->key()==::Qt::Key_G) && (modifiers==::Qt::NoButton)) - { - m_flatShading=!m_flatShading; + } else if ((e->key() == ::Qt::Key_G) && (modifiers == ::Qt::NoButton)) { + m_flatShading = !m_flatShading; if (m_flatShading) displayMessage("Flat shading."); else displayMessage("Gouraud shading."); redraw(); - } - else if ((e->key()==::Qt::Key_M) && (modifiers==::Qt::NoButton)) - { - m_use_mono_color=!m_use_mono_color; - displayMessage(QString("Mono color=%1.").arg(m_use_mono_color?"true":"false")); + } else if ((e->key() == ::Qt::Key_M) && (modifiers == ::Qt::NoButton)) { + m_use_mono_color = !m_use_mono_color; + displayMessage( + QString("Mono color=%1.").arg(m_use_mono_color ? "true" : "false")); update(); - } - else if ((e->key()==::Qt::Key_N) && (modifiers==::Qt::NoButton)) - { - m_inverse_normal=!m_inverse_normal; - displayMessage(QString("Inverse normal=%1.").arg(m_inverse_normal?"true":"false")); + } else if ((e->key() == ::Qt::Key_N) && (modifiers == ::Qt::NoButton)) { + m_inverse_normal = !m_inverse_normal; + displayMessage(QString("Inverse normal=%1.") + .arg(m_inverse_normal ? "true" : "false")); negate_all_normals(); redraw(); - } - else if ((e->key()==::Qt::Key_V) && (modifiers==::Qt::NoButton)) - { - m_draw_vertices=!m_draw_vertices; - displayMessage(QString("Draw vertices=%1.").arg(m_draw_vertices?"true":"false")); + } else if ((e->key() == ::Qt::Key_V) && (modifiers == ::Qt::NoButton)) { + m_draw_vertices = !m_draw_vertices; + displayMessage( + QString("Draw vertices=%1.").arg(m_draw_vertices ? "true" : "false")); update(); - } - else if ((e->key()==::Qt::Key_Plus) && (!modifiers.testFlag(::Qt::ControlModifier))) // No ctrl + } else if ((e->key() == ::Qt::Key_Plus) && + (!modifiers.testFlag(::Qt::ControlModifier))) // No ctrl { - m_size_edges+=.5; + m_size_edges += .5; displayMessage(QString("Size of edges=%1.").arg(m_size_edges)); update(); - } - else if ((e->key()==::Qt::Key_Minus) && (!modifiers.testFlag(::Qt::ControlModifier))) // No ctrl + } else if ((e->key() == ::Qt::Key_Minus) && + (!modifiers.testFlag(::Qt::ControlModifier))) // No ctrl { - if (m_size_edges>.5) m_size_edges-=.5; + if (m_size_edges > .5) + m_size_edges -= .5; displayMessage(QString("Size of edges=%1.").arg(m_size_edges)); update(); - } - else if ((e->key()==::Qt::Key_Plus) && (modifiers.testFlag(::Qt::ControlModifier))) - { - m_size_points+=.5; + } else if ((e->key() == ::Qt::Key_Plus) && + (modifiers.testFlag(::Qt::ControlModifier))) { + m_size_points += .5; displayMessage(QString("Size of points=%1.").arg(m_size_points)); update(); - } - else if ((e->key()==::Qt::Key_Minus) && (modifiers.testFlag(::Qt::ControlModifier))) - { - if (m_size_points>.5) m_size_points-=.5; + } else if ((e->key() == ::Qt::Key_Minus) && + (modifiers.testFlag(::Qt::ControlModifier))) { + if (m_size_points > .5) + m_size_points -= .5; displayMessage(QString("Size of points=%1.").arg(m_size_points)); update(); - } - else if ((e->key()==::Qt::Key_PageUp) && (modifiers==::Qt::NoButton)) - { - m_ambient_color.setX(m_ambient_color.x()+.1); - if (m_ambient_color.x()>1.) m_ambient_color.setX(1.); - m_ambient_color.setY(m_ambient_color.x()+.1); - if (m_ambient_color.y()>1.) m_ambient_color.setY(1.); - m_ambient_color.setZ(m_ambient_color.x()+.1); - if (m_ambient_color.z()>1.) m_ambient_color.setZ(1.); - displayMessage(QString("Light color=(%1 %2 %3)."). - arg(m_ambient_color.x()).arg(m_ambient_color.y()).arg(m_ambient_color.z())); + } else if ((e->key() == ::Qt::Key_PageUp) && + (modifiers == ::Qt::NoButton)) { + m_ambient_color.setX(m_ambient_color.x() + .1); + if (m_ambient_color.x() > 1.) + m_ambient_color.setX(1.); + m_ambient_color.setY(m_ambient_color.x() + .1); + if (m_ambient_color.y() > 1.) + m_ambient_color.setY(1.); + m_ambient_color.setZ(m_ambient_color.x() + .1); + if (m_ambient_color.z() > 1.) + m_ambient_color.setZ(1.); + displayMessage(QString("Light color=(%1 %2 %3).") + .arg(m_ambient_color.x()) + .arg(m_ambient_color.y()) + .arg(m_ambient_color.z())); update(); - } - else if ((e->key()==::Qt::Key_PageDown) && (modifiers==::Qt::NoButton)) - { - m_ambient_color.setX(m_ambient_color.x()-.1); - if (m_ambient_color.x()<0.) m_ambient_color.setX(0.); - m_ambient_color.setY(m_ambient_color.y()-.1); - if (m_ambient_color.y()<0.) m_ambient_color.setY(0.); - m_ambient_color.setZ(m_ambient_color.z()-.1); - if (m_ambient_color.z()<0.) m_ambient_color.setZ(0.); - displayMessage(QString("Light color=(%1 %2 %3)."). - arg(m_ambient_color.x()).arg(m_ambient_color.y()).arg(m_ambient_color.z())); + } else if ((e->key() == ::Qt::Key_PageDown) && + (modifiers == ::Qt::NoButton)) { + m_ambient_color.setX(m_ambient_color.x() - .1); + if (m_ambient_color.x() < 0.) + m_ambient_color.setX(0.); + m_ambient_color.setY(m_ambient_color.y() - .1); + if (m_ambient_color.y() < 0.) + m_ambient_color.setY(0.); + m_ambient_color.setZ(m_ambient_color.z() - .1); + if (m_ambient_color.z() < 0.) + m_ambient_color.setZ(0.); + displayMessage(QString("Light color=(%1 %2 %3).") + .arg(m_ambient_color.x()) + .arg(m_ambient_color.y()) + .arg(m_ambient_color.z())); update(); - } - else if ((e->key()==::Qt::Key_PageUp) && (modifiers==::Qt::ShiftModifier)) - { - m_ambient_color.setX(m_ambient_color.x()+.1); - if (m_ambient_color.x()>1.) m_ambient_color.setX(1.); - displayMessage(QString("Light color=(%1 %2 %3)."). - arg(m_ambient_color.x()).arg(m_ambient_color.y()).arg(m_ambient_color.z())); + } else if ((e->key() == ::Qt::Key_PageUp) && + (modifiers == ::Qt::ShiftModifier)) { + m_ambient_color.setX(m_ambient_color.x() + .1); + if (m_ambient_color.x() > 1.) + m_ambient_color.setX(1.); + displayMessage(QString("Light color=(%1 %2 %3).") + .arg(m_ambient_color.x()) + .arg(m_ambient_color.y()) + .arg(m_ambient_color.z())); update(); - } - else if ((e->key()==::Qt::Key_PageUp) && (modifiers==::Qt::AltModifier)) - { - m_ambient_color.setY(m_ambient_color.y()+.1); - if (m_ambient_color.y()>1.) m_ambient_color.setY(1.); - displayMessage(QString("Light color=(%1 %2 %3)."). - arg(m_ambient_color.x()).arg(m_ambient_color.y()).arg(m_ambient_color.z())); + } else if ((e->key() == ::Qt::Key_PageUp) && + (modifiers == ::Qt::AltModifier)) { + m_ambient_color.setY(m_ambient_color.y() + .1); + if (m_ambient_color.y() > 1.) + m_ambient_color.setY(1.); + displayMessage(QString("Light color=(%1 %2 %3).") + .arg(m_ambient_color.x()) + .arg(m_ambient_color.y()) + .arg(m_ambient_color.z())); update(); - } - else if ((e->key()==::Qt::Key_PageUp) && (modifiers==::Qt::ControlModifier)) - { - m_ambient_color.setZ(m_ambient_color.z()+.1); - if (m_ambient_color.z()>1.) m_ambient_color.setZ(1.); - displayMessage(QString("Light color=(%1 %2 %3)."). - arg(m_ambient_color.x()).arg(m_ambient_color.y()).arg(m_ambient_color.z())); + } else if ((e->key() == ::Qt::Key_PageUp) && + (modifiers == ::Qt::ControlModifier)) { + m_ambient_color.setZ(m_ambient_color.z() + .1); + if (m_ambient_color.z() > 1.) + m_ambient_color.setZ(1.); + displayMessage(QString("Light color=(%1 %2 %3).") + .arg(m_ambient_color.x()) + .arg(m_ambient_color.y()) + .arg(m_ambient_color.z())); update(); - } - else if ((e->key()==::Qt::Key_PageDown) && (modifiers==::Qt::ShiftModifier)) - { - m_ambient_color.setX(m_ambient_color.x()-.1); - if (m_ambient_color.x()<0.) m_ambient_color.setX(0.); - displayMessage(QString("Light color=(%1 %2 %3)."). - arg(m_ambient_color.x()).arg(m_ambient_color.y()).arg(m_ambient_color.z())); + } else if ((e->key() == ::Qt::Key_PageDown) && + (modifiers == ::Qt::ShiftModifier)) { + m_ambient_color.setX(m_ambient_color.x() - .1); + if (m_ambient_color.x() < 0.) + m_ambient_color.setX(0.); + displayMessage(QString("Light color=(%1 %2 %3).") + .arg(m_ambient_color.x()) + .arg(m_ambient_color.y()) + .arg(m_ambient_color.z())); update(); - } - else if ((e->key()==::Qt::Key_PageDown) && (modifiers==::Qt::AltModifier)) - { - m_ambient_color.setY(m_ambient_color.y()-.1); - if (m_ambient_color.y()<0.) m_ambient_color.setY(0.); - displayMessage(QString("Light color=(%1 %2 %3)."). - arg(m_ambient_color.x()).arg(m_ambient_color.y()).arg(m_ambient_color.z())); + } else if ((e->key() == ::Qt::Key_PageDown) && + (modifiers == ::Qt::AltModifier)) { + m_ambient_color.setY(m_ambient_color.y() - .1); + if (m_ambient_color.y() < 0.) + m_ambient_color.setY(0.); + displayMessage(QString("Light color=(%1 %2 %3).") + .arg(m_ambient_color.x()) + .arg(m_ambient_color.y()) + .arg(m_ambient_color.z())); update(); - } - else if ((e->key()==::Qt::Key_PageDown) && (modifiers==::Qt::ControlModifier)) - { - m_ambient_color.setZ(m_ambient_color.z()-.1); - if (m_ambient_color.z()<0.) m_ambient_color.setZ(0.); - displayMessage(QString("Light color=(%1 %2 %3)."). - arg(m_ambient_color.x()).arg(m_ambient_color.y()).arg(m_ambient_color.z())); + } else if ((e->key() == ::Qt::Key_PageDown) && + (modifiers == ::Qt::ControlModifier)) { + m_ambient_color.setZ(m_ambient_color.z() - .1); + if (m_ambient_color.z() < 0.) + m_ambient_color.setZ(0.); + displayMessage(QString("Light color=(%1 %2 %3).") + .arg(m_ambient_color.x()) + .arg(m_ambient_color.y()) + .arg(m_ambient_color.z())); update(); - } - else + } else CGAL::QGLViewer::keyPressEvent(e); } - virtual QString helpString() const - { return helpString("CGAL Basic Viewer"); } + virtual QString helpString() const { return helpString("CGAL Basic Viewer"); } - virtual QString helpString(const char* title) const - { - QString text(QString("

    ")+QString(title)+QString("

    ")); + virtual QString helpString(const char *title) const { + QString text(QString("

    ") + QString(title) + QString("

    ")); text += "Use the mouse to move the camera around the object. "; text += "You can respectively revolve around, zoom and translate with " - "the three mouse buttons. "; + "the three mouse buttons. "; text += "Left and middle buttons pressed together rotate around the " - "camera view direction axis

    "; + "camera view direction axis

    "; text += "Pressing Alt and one of the function keys " - "(F1..F12) defines a camera keyFrame. "; + "(F1..F12) defines a camera keyFrame. "; text += "Simply press the function key again to restore it. " - "Several keyFrames define a "; + "Several keyFrames define a "; text += "camera path. Paths are saved when you quit the application " - "and restored at next start.

    "; + "and restored at next start.

    "; text += "Press F to display the frame rate, A for the " - "world axis, "; + "world axis, "; text += "Alt+Return for full screen mode and Control+S " - "to save a snapshot. "; + "to save a snapshot. "; text += "See the Keyboard tab in this window for a complete " - "shortcut list.

    "; + "shortcut list.

    "; text += "Double clicks automates single click actions: A left button " - "double click aligns the closer axis with the camera (if close enough). "; + "double click aligns the closer axis with the camera (if close " + "enough). "; text += "A middle button double click fits the zoom of the camera and " - "the right button re-centers the scene.

    "; + "the right button re-centers the scene.

    "; text += "A left button double click while holding right button pressed " - "defines the camera Revolve Around Point. "; + "defines the camera Revolve Around Point. "; text += "See the Mouse tab and the documentation web pages for " - "details.

    "; + "details.

    "; text += "Press Escape to exit the viewer."; return text; } @@ -1157,7 +1103,7 @@ protected: bool m_flatShading; bool m_use_mono_color; bool m_inverse_normal; - + double m_size_points; double m_size_edges; double m_size_lines; @@ -1166,16 +1112,16 @@ protected: CGAL::Color m_edges_mono_color; CGAL::Color m_lines_mono_color; CGAL::Color m_faces_mono_color; - QVector4D m_ambient_color; + QVector4D m_ambient_color; bool m_are_buffers_initialized; CGAL::Bbox_3 m_bounding_box; - - // The following enum gives the indices of different elements of arrays vectors. - enum - { - BEGIN_POS=0, - POS_MONO_POINTS=BEGIN_POS, + + // The following enum gives the indices of different elements of arrays + // vectors. + enum { + BEGIN_POS = 0, + POS_MONO_POINTS = BEGIN_POS, POS_COLORED_POINTS, POS_MONO_SEGMENTS, POS_COLORED_SEGMENTS, @@ -1184,19 +1130,19 @@ protected: POS_MONO_FACES, POS_COLORED_FACES, END_POS, - BEGIN_COLOR=END_POS, - COLOR_POINTS=BEGIN_COLOR, + BEGIN_COLOR = END_POS, + COLOR_POINTS = BEGIN_COLOR, COLOR_SEGMENTS, COLOR_LINES, COLOR_FACES, END_COLOR, - BEGIN_NORMAL=END_COLOR, - SMOOTH_NORMAL_MONO_FACES=BEGIN_NORMAL, + BEGIN_NORMAL = END_COLOR, + SMOOTH_NORMAL_MONO_FACES = BEGIN_NORMAL, FLAT_NORMAL_MONO_FACES, SMOOTH_NORMAL_COLORED_FACES, FLAT_NORMAL_COLORED_FACES, END_NORMAL, - LAST_INDEX=END_NORMAL + LAST_INDEX = END_NORMAL }; std::vector arrays[LAST_INDEX]; @@ -1208,24 +1154,25 @@ protected: Buffer_for_vao m_buffer_for_colored_lines; Buffer_for_vao m_buffer_for_mono_faces; Buffer_for_vao m_buffer_for_colored_faces; - - static const unsigned int NB_VBO_BUFFERS=(END_POS-BEGIN_POS)+ - (END_COLOR-BEGIN_COLOR)+2; // +2 for 2 vectors of normals + + static const unsigned int NB_VBO_BUFFERS = (END_POS - BEGIN_POS) + + (END_COLOR - BEGIN_COLOR) + + 2; // +2 for 2 vectors of normals QGLBuffer buffers[NB_VBO_BUFFERS]; // The following enum gives the indices of the differents vao. - enum - { VAO_MONO_POINTS=0, - VAO_COLORED_POINTS, - VAO_MONO_SEGMENTS, - VAO_COLORED_SEGMENTS, - VAO_MONO_LINES, - VAO_COLORED_LINES, - VAO_MONO_FACES, - VAO_COLORED_FACES, - NB_VAO_BUFFERS - }; + enum { + VAO_MONO_POINTS = 0, + VAO_COLORED_POINTS, + VAO_MONO_SEGMENTS, + VAO_COLORED_SEGMENTS, + VAO_MONO_LINES, + VAO_COLORED_LINES, + VAO_MONO_FACES, + VAO_COLORED_FACES, + NB_VAO_BUFFERS + }; QOpenGLVertexArrayObject vao[NB_VAO_BUFFERS]; QOpenGLShaderProgram rendering_program_face; @@ -1236,35 +1183,31 @@ protected: #else // CGAL_USE_BASIC_VIEWER -namespace CGAL -{ +namespace CGAL { -template -void draw(const T&, const char*, bool, const ColorFunctor&) -{ - std::cerr<<"Impossible to draw because CGAL_USE_BASIC_VIEWER is not defined." - < +void draw(const T &, const char *, bool, const ColorFunctor &) { + std::cerr + << "Impossible to draw because CGAL_USE_BASIC_VIEWER is not defined." + << std::endl; } - -template -void draw(const T&, const char*, bool) -{ - std::cerr<<"Impossible to draw because CGAL_USE_BASIC_VIEWER is not defined." - < void draw(const T &, const char *, bool) { + std::cerr + << "Impossible to draw because CGAL_USE_BASIC_VIEWER is not defined." + << std::endl; } - -template -void draw(const T&, const char*) -{ - std::cerr<<"Impossible to draw because CGAL_USE_BASIC_VIEWER is not defined." - < void draw(const T &, const char *) { + std::cerr + << "Impossible to draw because CGAL_USE_BASIC_VIEWER is not defined." + << std::endl; } - -template -void draw(const T&) -{ - std::cerr<<"Impossible to draw because CGAL_USE_BASIC_VIEWER is not defined." - < void draw(const T &) { + std::cerr + << "Impossible to draw because CGAL_USE_BASIC_VIEWER is not defined." + << std::endl; } } // End namespace CGAL diff --git a/Voronoi_diagram_2/include/CGAL/draw_voronoi_diagram_2.h b/Voronoi_diagram_2/include/CGAL/draw_voronoi_diagram_2.h index a956e056c36..459b315eda5 100644 --- a/Voronoi_diagram_2/include/CGAL/draw_voronoi_diagram_2.h +++ b/Voronoi_diagram_2/include/CGAL/draw_voronoi_diagram_2.h @@ -21,164 +21,155 @@ #ifndef CGAL_DRAW_VORONOI_H #define CGAL_DRAW_VORONOI_H -#include #include +#include #ifdef CGAL_USE_BASIC_VIEWER -#include -#include -#include -#include -#include #include #include +#include +#include +#include +#include +#include -namespace CGAL -{ +namespace CGAL { // Default color functor; user can change it to have its own face color -struct DefaultColorFunctorV2 -{ - template - static CGAL::Color run(const V2&, - const typename V2::Face_iterator fh) - { +struct DefaultColorFunctorV2 { + template + static CGAL::Color run(const V2 &, const typename V2::Face_iterator fh) { CGAL::Random random((unsigned int)(std::size_t)(&*fh)); return get_random_color(random); } }; // Viewer for Voronoi diagram -template -class SimpleVoronoiDiagram2ViewerQt : public Basic_viewer_qt -{ - typedef Basic_viewer_qt Base; - typedef typename V2::Halfedge_iterator Halfedge_const_handle; - typedef typename V2::Face_iterator Face_const_handle; - typedef typename V2::Vertex_iterator Vertex_const_handle; - typedef typename V2::Point_2 Point; - typedef typename V2::Delaunay_vertex_handle Delaunay_vertex_const_handle; +template +class SimpleVoronoiDiagram2ViewerQt : public Basic_viewer_qt { + typedef Basic_viewer_qt Base; + typedef typename V2::Halfedge_iterator Halfedge_const_handle; + typedef typename V2::Face_iterator Face_const_handle; + typedef typename V2::Vertex_iterator Vertex_const_handle; + typedef typename V2::Point_2 Point; + typedef typename V2::Delaunay_vertex_handle Delaunay_vertex_const_handle; typedef typename V2::Ccb_halfedge_circulator Ccb_halfedge_circulator; - typedef typename V2::Delaunay_geom_traits Delaunay_geom_traits; + typedef typename V2::Delaunay_geom_traits Delaunay_geom_traits; typedef CGAL::Exact_predicates_inexact_constructions_kernel Kernel; - typedef CGAL_VORONOI_DIAGRAM_2_INS::Face Face; - typedef CGAL_VORONOI_DIAGRAM_2_INS::Handle_adaptor Face_handle; + typedef CGAL_VORONOI_DIAGRAM_2_INS::Face Face; + typedef CGAL_VORONOI_DIAGRAM_2_INS::Handle_adaptor Face_handle; typedef CGAL_VORONOI_DIAGRAM_2_INS::Vertex Vertex; - typedef CGAL_VORONOI_DIAGRAM_2_INS::Handle_adaptor Vertex_handle; - typedef Triangulation_cw_ccw_2 CW_CCW_2; + typedef CGAL_VORONOI_DIAGRAM_2_INS::Handle_adaptor Vertex_handle; + typedef Triangulation_cw_ccw_2 CW_CCW_2; public: /// Construct the viewer. /// @param av2 the voronoi diagram to view /// @param title the title of the window - /// @param anofaces if true, do not draw faces (faces are not computed; this can be + /// @param anofaces if true, do not draw faces (faces are not computed; this + /// can be /// useful for very big object where this time could be long) - SimpleVoronoiDiagram2ViewerQt(QWidget* parent, const V2& av2, - const char* title="Basic Voronoi Viewer", - bool anofaces=false, - const ColorFunctor& fcolor=ColorFunctor()) : - //First draw: vertices; half-edges; faces; multi-color; no inverse normal - Base(parent, title, true, true, true, false, false), - v2(av2), - m_nofaces(anofaces), - m_fcolor(fcolor) - { + SimpleVoronoiDiagram2ViewerQt(QWidget *parent, const V2 &av2, + const char *title = "Basic Voronoi Viewer", + bool anofaces = false, + const ColorFunctor &fcolor = ColorFunctor()) + : // First draw: vertices; half-edges; faces; multi-color; no inverse + // normal + Base(parent, title, true, true, true, false, false), v2(av2), + m_nofaces(anofaces), m_fcolor(fcolor) { compute_elements(); } protected: - void compute_face(Face_const_handle fh) - { -// CGAL::Color c=m_fcolor.run(v2, fh); -// face_begin(c); -// Ccb_halfedge_circulator ec_start = fh->ccb(); -// Ccb_halfedge_circulator ec = ec_start; + void compute_face(Face_const_handle fh) { + // CGAL::Color c=m_fcolor.run(v2, fh); + // face_begin(c); + // Ccb_halfedge_circulator ec_start = fh->ccb(); + // Ccb_halfedge_circulator ec = ec_start; -// do{ -// if( ec->has_source() ) -// add_point_in_face(ec->source()->point()); -// else if(ec->has_target()) -// add_point_in_face(ec->target()->point()); -// } while(++ec != ec_start); + // do{ + // if( ec->has_source() ) + // add_point_in_face(ec->source()->point()); + // else if(ec->has_target()) + // add_point_in_face(ec->target()->point()); + // } while(++ec != ec_start); -// face_end(); + // face_end(); } - void compute_ray_points(Halfedge_const_handle he) - { - if(he->is_segment()){ - add_segment(he->source()->point(), - he->target()->point()); - } else if(he->is_ray()){ - Delaunay_vertex_const_handle v1 = he->up(); - Delaunay_vertex_const_handle v2 = he->down(); + void compute_ray_points(Halfedge_const_handle he) { + if (he->is_segment()) { + add_segment(he->source()->point(), he->target()->point()); + } else if (he->is_ray()) { + Delaunay_vertex_const_handle v1 = he->up(); + Delaunay_vertex_const_handle v2 = he->down(); - Kernel::Vector_2 direction(v1->point().y()-v2->point().y(), - v2->point().x()-v1->point().x());; - Kernel::Point_2 end_point; + Kernel::Vector_2 direction(v1->point().y() - v2->point().y(), + v2->point().x() - v1->point().x()); + Kernel::Point_2 end_point; - if(he->has_source()){ - end_point = he->source()->point(); - add_ray_points(end_point, direction); - } + if (he->has_source()) { + end_point = he->source()->point(); + add_ray_points(end_point, direction); } + } } - void compute_rays(Halfedge_const_handle he){ - if(he->is_ray()){ - Delaunay_vertex_const_handle v1 = he->up(); - Delaunay_vertex_const_handle v2 = he->down(); + void compute_rays(Halfedge_const_handle he) { + if (he->is_ray()) { + Delaunay_vertex_const_handle v1 = he->up(); + Delaunay_vertex_const_handle v2 = he->down(); - Kernel::Vector_2 direction(v1->point().y()-v2->point().y(), - v2->point().x()-v1->point().x());; - Kernel::Point_2 end_point; - if(he->has_source()){ - end_point = he->source()->point(); - std::cout << "Bounding_box" << m_bounding_box << std::endl; - add_ray_segment(end_point, direction); - } + Kernel::Vector_2 direction(v1->point().y() - v2->point().y(), + v2->point().x() - v1->point().x()); + Kernel::Point_2 end_point; + if (he->has_source()) { + end_point = he->source()->point(); + std::cout << "Bounding_box" << m_bounding_box << std::endl; + add_ray_segment(end_point, direction); } + } } + void compute_vertex(Vertex_const_handle vh) { add_point(vh->point()); } - void compute_vertex(Vertex_const_handle vh) - { add_point(vh->point()); } - - void compute_elements() - { + void compute_elements() { clear(); - if (!m_nofaces) - { - for (typename V2::Face_iterator it=v2.faces_begin(); - it!=v2.faces_end(); ++it) - { compute_face(it); } + if (!m_nofaces) { + for (typename V2::Face_iterator it = v2.faces_begin(); + it != v2.faces_end(); ++it) { + compute_face(it); + } } -// for(Delaunay_vertex_const_handle it = v2.dual().finite_vertices_begin(); -// it!=v2.dual().finite_vertices_end(); ++it) -// { compute_vertex(it);} + // for(Delaunay_vertex_const_handle it = + // v2.dual().finite_vertices_begin(); + // it!=v2.dual().finite_vertices_end(); ++it) + // { compute_vertex(it);} - for (typename V2::Halfedge_iterator it=v2.halfedges_begin(); - it!=v2.halfedges_end(); ++it) - { compute_ray_points(it); } + for (typename V2::Halfedge_iterator it = v2.halfedges_begin(); + it != v2.halfedges_end(); ++it) { + compute_ray_points(it); + } - for (typename V2::Halfedge_iterator it=v2.halfedges_begin(); - it!=v2.halfedges_end(); ++it) - { compute_rays(it); } + for (typename V2::Halfedge_iterator it = v2.halfedges_begin(); + it != v2.halfedges_end(); ++it) { + compute_rays(it); + } - for (typename V2::Vertex_iterator it=v2.vertices_begin(); - it!=v2.vertices_end(); ++it) - { compute_vertex(it); } + for (typename V2::Vertex_iterator it = v2.vertices_begin(); + it != v2.vertices_end(); ++it) { + compute_vertex(it); + } } - virtual void keyPressEvent(QKeyEvent *e) - { + virtual void keyPressEvent(QKeyEvent *e) { // Test key pressed: // const ::Qt::KeyboardModifiers modifiers = e->modifiers(); // if ((e->key()==Qt::Key_PageUp) && (modifiers==Qt::NoButton)) { ... } - + // Call: * compute_elements() if the model changed, followed by // * redraw() if some viewing parameters changed that implies some // modifications of the buffers @@ -191,52 +182,43 @@ protected: protected: CGAL::Qt::Converter convert; - const V2& v2; + const V2 &v2; bool m_nofaces; - const ColorFunctor& m_fcolor; + const ColorFunctor &m_fcolor; }; -template -void draw(const V2& av2, - const char* title, - bool nofill, - const ColorFunctor& fcolor) -{ +template +void draw(const V2 &av2, const char *title, bool nofill, + const ColorFunctor &fcolor) { #if defined(CGAL_TEST_SUITE) - bool cgal_test_suite=true; + bool cgal_test_suite = true; #else - bool cgal_test_suite=false; + bool cgal_test_suite = false; #endif - if (!cgal_test_suite) - { - int argc=1; - const char* argv[2]={"v2_viewer","\0"}; - QApplication app(argc,const_cast(argv)); - SimpleVoronoiDiagram2ViewerQt mainwindow(app.activeWindow(), - av2, - title, - nofill, - fcolor); + if (!cgal_test_suite) { + int argc = 1; + const char *argv[2] = {"v2_viewer", "\0"}; + QApplication app(argc, const_cast(argv)); + SimpleVoronoiDiagram2ViewerQt mainwindow( + app.activeWindow(), av2, title, nofill, fcolor); mainwindow.show(); app.exec(); } } -template -void draw(const V2& av2, const char* title, bool nofill) -{ +template void draw(const V2 &av2, const char *title, bool nofill) { DefaultColorFunctorV2 c; draw(av2, title, nofill, c); } -template -void draw(const V2& av2, const char* title) -{ draw(av2, title, false); } +template void draw(const V2 &av2, const char *title) { + draw(av2, title, false); +} -template -void draw(const V2& av2) -{ draw(av2, "Basic Voronoi Diagram Viewer"); } +template void draw(const V2 &av2) { + draw(av2, "Basic Voronoi Diagram Viewer"); +} } // End namespace CGAL From 1cc0d12aa45e122445bb41e8c66f598fe6aad566 Mon Sep 17 00:00:00 2001 From: Jasmeet Singh Date: Mon, 17 Jun 2019 20:13:30 -0700 Subject: [PATCH 061/363] Revert formatting of the rest of Basic_viewer_qt.h file --- .../include/CGAL/Qt/Basic_viewer_qt.h | 1273 +++++++++-------- 1 file changed, 653 insertions(+), 620 deletions(-) diff --git a/GraphicsView/include/CGAL/Qt/Basic_viewer_qt.h b/GraphicsView/include/CGAL/Qt/Basic_viewer_qt.h index f428623faa2..e67997b05fe 100644 --- a/GraphicsView/include/CGAL/Qt/Basic_viewer_qt.h +++ b/GraphicsView/include/CGAL/Qt/Basic_viewer_qt.h @@ -28,9 +28,9 @@ #ifdef CGAL_USE_BASIC_VIEWER #ifdef __GNUC__ -#if __GNUC__ >= 9 -#pragma GCC diagnostic push -#pragma GCC diagnostic ignored "-Wdeprecated-copy" +#if __GNUC__ >= 9 +# pragma GCC diagnostic push +# pragma GCC diagnostic ignored "-Wdeprecated-copy" #endif #endif @@ -38,51 +38,56 @@ #include #include -#include #include #include -#include #include +#include +#include #ifdef __GNUC__ #if __GNUC__ >= 9 -#pragma GCC diagnostic pop +# pragma GCC diagnostic pop #endif #endif -#include #include +#include #include #include #include -namespace CGAL { +namespace CGAL +{ //------------------------------------------------------------------------------ -const char vertex_source_color[] = {"#version 120 \n" - "attribute highp vec4 vertex;\n" - "attribute highp vec3 normal;\n" - "attribute highp vec3 color;\n" +const char vertex_source_color[] = + { + "#version 120 \n" + "attribute highp vec4 vertex;\n" + "attribute highp vec3 normal;\n" + "attribute highp vec3 color;\n" - "uniform highp mat4 mvp_matrix;\n" - "uniform highp mat4 mv_matrix; \n" + "uniform highp mat4 mvp_matrix;\n" + "uniform highp mat4 mv_matrix; \n" - "varying highp vec4 fP; \n" - "varying highp vec3 fN; \n" - "varying highp vec4 fColor; \n" + "varying highp vec4 fP; \n" + "varying highp vec3 fN; \n" + "varying highp vec4 fColor; \n" - "uniform highp float point_size; \n" - "void main(void)\n" - "{\n" - " fP = mv_matrix * vertex; \n" - " fN = mat3(mv_matrix)* normal; \n" - " fColor = vec4(color, 1.0); \n" - " gl_PointSize = point_size;\n" - " gl_Position = mvp_matrix * vertex;\n" - "}"}; + "uniform highp float point_size; \n" + "void main(void)\n" + "{\n" + " fP = mv_matrix * vertex; \n" + " fN = mat3(mv_matrix)* normal; \n" + " fColor = vec4(color, 1.0); \n" + " gl_PointSize = point_size;\n" + " gl_Position = mvp_matrix * vertex;\n" + "}" + }; -const char fragment_source_color[] = { +const char fragment_source_color[] = + { "#version 120 \n" "varying highp vec4 fP; \n" "varying highp vec3 fN; \n" @@ -108,80 +113,122 @@ const char fragment_source_color[] = { "gl_FragColor = light_amb*fColor + diffuse ; \n" "} \n" - "\n"}; + "\n" + }; -const char vertex_source_p_l[] = {"#version 120 \n" - "attribute highp vec4 vertex;\n" - "attribute highp vec3 color;\n" - "uniform highp mat4 mvp_matrix;\n" - "varying highp vec4 fColor; \n" - "uniform highp float point_size; \n" - "void main(void)\n" - "{\n" - " gl_PointSize = point_size;\n" - " fColor = vec4(color, 1.0); \n" - " gl_Position = mvp_matrix * vertex;\n" - "}"}; +const char vertex_source_p_l[] = + { + "#version 120 \n" + "attribute highp vec4 vertex;\n" + "attribute highp vec3 color;\n" + "uniform highp mat4 mvp_matrix;\n" + "varying highp vec4 fColor; \n" + "uniform highp float point_size; \n" + "void main(void)\n" + "{\n" + " gl_PointSize = point_size;\n" + " fColor = vec4(color, 1.0); \n" + " gl_Position = mvp_matrix * vertex;\n" + "}" + }; -const char fragment_source_p_l[] = {"#version 120 \n" - "varying highp vec4 fColor; \n" - "void main(void) { \n" - "gl_FragColor = fColor; \n" - "} \n" - "\n"}; +const char fragment_source_p_l[] = + { + "#version 120 \n" + "varying highp vec4 fColor; \n" + "void main(void) { \n" + "gl_FragColor = fColor; \n" + "} \n" + "\n" + }; //------------------------------------------------------------------------------ -inline CGAL::Color get_random_color(CGAL::Random &random) { +inline CGAL::Color get_random_color(CGAL::Random& random) +{ CGAL::Color res; - do { - res = CGAL::Color(random.get_int(0, 256), random.get_int(0, 256), - random.get_int(0, 256)); - } while (res.red() == 255 && res.green() == 255 && res.blue() == 255); + do + { + res=CGAL::Color(random.get_int(0,256), + random.get_int(0,256), + random.get_int(0,256)); + } + while(res.red()==255 && res.green()==255 && res.blue()==255); return res; } //------------------------------------------------------------------------------ -class Basic_viewer_qt : public CGAL::QGLViewer { +class Basic_viewer_qt : public CGAL::QGLViewer +{ public: typedef CGAL::Exact_predicates_inexact_constructions_kernel Local_kernel; - typedef Local_kernel::Point_3 Local_point; + typedef Local_kernel::Point_3 Local_point; typedef Local_kernel::Vector_3 Local_vector; // Constructor/Destructor - Basic_viewer_qt(QWidget *parent, const char *title = "", - bool draw_vertices = false, bool draw_edges = true, - bool draw_lines = true, bool draw_faces = true, - bool use_mono_color = false, bool inverse_normal = false) - : CGAL::QGLViewer(parent), m_draw_vertices(draw_vertices), - m_draw_edges(draw_edges), m_draw_lines(draw_lines), - m_draw_faces(draw_faces), m_flatShading(true), - m_use_mono_color(use_mono_color), m_inverse_normal(inverse_normal), - m_size_points(7.), m_size_edges(3.1), m_size_lines(3.1), - m_vertices_mono_color(200, 60, 60), m_edges_mono_color(0, 0, 0), - m_lines_mono_color(0, 100, 0), m_faces_mono_color(60, 60, 200), - m_ambient_color(0.6f, 0.5f, 0.5f, 0.5f), - m_are_buffers_initialized(false), - m_buffer_for_mono_points(&arrays[POS_MONO_POINTS], NULL, - &m_bounding_box, NULL, NULL, NULL), - m_buffer_for_colored_points(&arrays[POS_COLORED_POINTS], NULL, - &m_bounding_box, &arrays[COLOR_POINTS], - NULL, NULL), - m_buffer_for_mono_segments(&arrays[POS_MONO_SEGMENTS], NULL, - &m_bounding_box, NULL, NULL, NULL), - m_buffer_for_colored_segments(&arrays[POS_COLORED_SEGMENTS], NULL, - &m_bounding_box, &arrays[COLOR_SEGMENTS], - NULL, NULL), - m_buffer_for_mono_lines(&arrays[POS_MONO_LINES], NULL, &m_bounding_box, + Basic_viewer_qt(QWidget* parent, + const char* title="", + bool draw_vertices=false, + bool draw_edges=true, + bool draw_lines=true, + bool draw_faces=true, + bool use_mono_color=false, + bool inverse_normal=false) : + CGAL::QGLViewer(parent), + m_draw_vertices(draw_vertices), + m_draw_edges(draw_edges), + m_draw_lines(draw_lines), + m_draw_faces(draw_faces), + m_flatShading(true), + m_use_mono_color(use_mono_color), + m_inverse_normal(inverse_normal), + m_size_points(7.), + m_size_edges(3.1), + m_size_lines(3.1), + m_vertices_mono_color(200, 60, 60), + m_edges_mono_color(0, 0, 0), + m_lines_mono_color(0,100,0), + m_faces_mono_color(60, 60, 200), + m_ambient_color(0.6f, 0.5f, 0.5f, 0.5f), + m_are_buffers_initialized(false), + m_buffer_for_mono_points(&arrays[POS_MONO_POINTS], + NULL, + &m_bounding_box, + NULL, NULL, NULL), + m_buffer_for_colored_points(&arrays[POS_COLORED_POINTS], + NULL, + &m_bounding_box, + &arrays[COLOR_POINTS], NULL, NULL), - m_buffer_for_colored_lines(&arrays[POS_COLORED_LINES], NULL, - &m_bounding_box, &arrays[COLOR_LINES], NULL, - NULL), - m_buffer_for_mono_faces(&arrays[POS_MONO_FACES], NULL, &m_bounding_box, - NULL, &arrays[FLAT_NORMAL_MONO_FACES], - &arrays[SMOOTH_NORMAL_MONO_FACES]), - m_buffer_for_colored_faces(&arrays[POS_COLORED_FACES], NULL, - &m_bounding_box, &arrays[COLOR_FACES], - &arrays[FLAT_NORMAL_COLORED_FACES], - &arrays[SMOOTH_NORMAL_COLORED_FACES]) { - if (title[0] == 0) + m_buffer_for_mono_segments(&arrays[POS_MONO_SEGMENTS], + NULL, + &m_bounding_box, + NULL, NULL, NULL), + m_buffer_for_colored_segments(&arrays[POS_COLORED_SEGMENTS], + NULL, + &m_bounding_box, + &arrays[COLOR_SEGMENTS], + NULL, NULL), + m_buffer_for_mono_lines(&arrays[POS_MONO_LINES], + NULL, + &m_bounding_box, + NULL, NULL), + m_buffer_for_colored_lines(&arrays[POS_COLORED_LINES], + NULL, + &m_bounding_box, + &arrays[COLOR_LINES], + NULL, NULL), + m_buffer_for_mono_faces(&arrays[POS_MONO_FACES], + NULL, + &m_bounding_box, + NULL, + &arrays[FLAT_NORMAL_MONO_FACES], + &arrays[SMOOTH_NORMAL_MONO_FACES]), + m_buffer_for_colored_faces(&arrays[POS_COLORED_FACES], + NULL, + &m_bounding_box, + &arrays[COLOR_FACES], + &arrays[FLAT_NORMAL_COLORED_FACES], + &arrays[SMOOTH_NORMAL_COLORED_FACES]) + { + if (title[0]==0) setWindowTitle("CGAL Basic Viewer"); else setWindowTitle(title); @@ -189,23 +236,25 @@ public: resize(500, 450); } - ~Basic_viewer_qt() { - for (unsigned int i = 0; i < NB_VBO_BUFFERS; ++i) + ~Basic_viewer_qt() + { + for (unsigned int i=0; i void add_point(const KPoint &p) { - m_buffer_for_mono_points.add_point(p); - } + template + void add_point(const KPoint& p) + { m_buffer_for_mono_points.add_point(p); } - template - void add_point(const KPoint &p, const CGAL::Color &acolor) { - m_buffer_for_colored_points.add_point(p, acolor); - } + template + void add_point(const KPoint& p, const CGAL::Color& acolor) + { m_buffer_for_colored_points.add_point(p, acolor); } - template - void add_segment(const KPoint &p1, const KPoint &p2) { - m_buffer_for_mono_segments.add_segment(p1, p2); - } + template + void add_segment(const KPoint& p1, const KPoint& p2) + { m_buffer_for_mono_segments.add_segment(p1, p2); } + + template + void add_segment(const KPoint& p1, const KPoint& p2, + const CGAL::Color& acolor) + { m_buffer_for_colored_segments.add_segment(p1, p2, acolor); } - template - void add_segment(const KPoint &p1, const KPoint &p2, - const CGAL::Color &acolor) { - m_buffer_for_colored_segments.add_segment(p1, p2, acolor); - } template void add_ray_points(const KPoint &p, const KVector &v) { - m_buffer_for_mono_points.add_point(p); - m_buffer_for_mono_points.add_point(p + v); + m_buffer_for_mono_points.add_point(p); + m_buffer_for_mono_points.add_point(p + v); } template void add_ray_segment(const KPoint &p, const KVector &v) { - Local_kernel::Vector_2 boundsMin(m_bounding_box.xmin(), - m_bounding_box.zmin()); - Local_kernel::Vector_2 boundsMax(m_bounding_box.xmax(), - m_bounding_box.zmax()); + Local_kernel::Vector_2 boundsMin(m_bounding_box.xmin(), + m_bounding_box.zmin()); + Local_kernel::Vector_2 boundsMax(m_bounding_box.xmax(), + m_bounding_box.zmax()); - Local_kernel::Vector_2 inv(1 / v.x(), 1 / v.y()); + Local_kernel::Vector_2 inv(1 / v.x(), 1 / v.y()); - double txmax, txmin, tymax, tymin; + double txmax, txmin, tymax, tymin; - if (inv.x() >= 0) { - txmax = (boundsMax.x() - p.x()) * inv.x(); - txmin = (boundsMin.x() - p.x()) * inv.x(); - } else { - txmax = (boundsMin.x() - p.x()) * inv.x(); - txmin = (boundsMax.x() - p.x()) * inv.x(); - } + if (inv.x() >= 0) { + txmax = (boundsMax.x() - p.x()) * inv.x(); + txmin = (boundsMin.x() - p.x()) * inv.x(); + } else { + txmax = (boundsMin.x() - p.x()) * inv.x(); + txmin = (boundsMax.x() - p.x()) * inv.x(); + } - if (inv.y() >= 0) { - tymax = (boundsMax.y() - p.y()) * inv.y(); - tymin = (boundsMin.y() - p.y()) * inv.y(); - } else { - tymax = (boundsMin.y() - p.y()) * inv.y(); - tymin = (boundsMax.y() - p.y()) * inv.y(); - } + if (inv.y() >= 0) { + tymax = (boundsMax.y() - p.y()) * inv.y(); + tymin = (boundsMin.y() - p.y()) * inv.y(); + } else { + tymax = (boundsMin.y() - p.y()) * inv.y(); + tymin = (boundsMax.y() - p.y()) * inv.y(); + } - if (tymin > txmin) - txmin = tymin; - if (tymax < txmax) - txmax = tymax; + if (tymin > txmin) + txmin = tymin; + if (tymax < txmax) + txmax = tymax; - Local_kernel::Point_2 p1; - if (v.x() == 0) { - p1 = Local_kernel::Point_2(p.x(), p.y() + tymax * v.y()); - } else if (v.y() == 0) { - p1 = Local_kernel::Point_2(p.x() + txmax * v.x(), p.y()); - } else { - p1 = Local_kernel::Point_2(p.x() + txmax * v.x(), p.y() + tymax * v.y()); - } + Local_kernel::Point_2 p1; + if (v.x() == 0) { + p1 = Local_kernel::Point_2(p.x(), p.y() + tymax * v.y()); + } else if (v.y() == 0) { + p1 = Local_kernel::Point_2(p.x() + txmax * v.x(), p.y()); + } else { + p1 = Local_kernel::Point_2(p.x() + txmax * v.x(), p.y() + tymax * v.y()); + } - m_buffer_for_mono_segments.add_segment(p, p1); + m_buffer_for_mono_segments.add_segment(p, p1); } - bool is_a_face_started() const { + bool is_a_face_started() const + { return m_buffer_for_mono_faces.is_a_face_started() || - m_buffer_for_colored_faces.is_a_face_started(); + m_buffer_for_colored_faces.is_a_face_started(); } - void face_begin() { - if (is_a_face_started()) { - std::cerr - << "You cannot start a new face before to finish the previous one." - << std::endl; - } else { - m_buffer_for_mono_faces.face_begin(); + void face_begin() + { + if (is_a_face_started()) + { + std::cerr<<"You cannot start a new face before to finish the previous one."< bool add_point_in_face(const KPoint &kp) { - if (m_buffer_for_mono_faces.is_a_face_started()) { - return m_buffer_for_mono_faces.add_point_in_face(kp); - } else if (m_buffer_for_colored_faces.is_a_face_started()) { - return m_buffer_for_colored_faces.add_point_in_face(kp); - } + template + bool add_point_in_face(const KPoint& kp) + { + if (m_buffer_for_mono_faces.is_a_face_started()) + { return m_buffer_for_mono_faces.add_point_in_face(kp); } + else if (m_buffer_for_colored_faces.is_a_face_started()) + { return m_buffer_for_colored_faces.add_point_in_face(kp); } return false; } - template - bool add_point_in_face(const KPoint &kp, const KVector &p_normal) { - if (m_buffer_for_mono_faces.is_a_face_started()) { - return m_buffer_for_mono_faces.add_point_in_face(kp, p_normal); - } else if (m_buffer_for_colored_faces.is_a_face_started()) { - return m_buffer_for_colored_faces.add_point_in_face(kp, p_normal); - } + template + bool add_point_in_face(const KPoint& kp, const KVector& p_normal) + { + if (m_buffer_for_mono_faces.is_a_face_started()) + { return m_buffer_for_mono_faces.add_point_in_face(kp, p_normal); } + else if (m_buffer_for_colored_faces.is_a_face_started()) + { return m_buffer_for_colored_faces.add_point_in_face(kp, p_normal); } return false; } - void face_end() { - if (m_buffer_for_mono_faces.is_a_face_started()) { - m_buffer_for_mono_faces.face_end(); - } else if (m_buffer_for_colored_faces.is_a_face_started()) { - return m_buffer_for_colored_faces.face_end(); - } + void face_end() + { + if (m_buffer_for_mono_faces.is_a_face_started()) + { m_buffer_for_mono_faces.face_end(); } + else if (m_buffer_for_colored_faces.is_a_face_started()) + { return m_buffer_for_colored_faces.face_end(); } } protected: - void compile_shaders() { + void compile_shaders() + { rendering_program_face.removeAllShaders(); rendering_program_p_l.removeAllShaders(); // Create the buffers - for (unsigned int i = 0; i < NB_VBO_BUFFERS; ++i) { - if (!buffers[i].isCreated() && !buffers[i].create()) { - std::cerr << "VBO Creation number " << i << " FAILED" << std::endl; - } + for (unsigned int i=0; icompileSourceCode(vertex_source_p_l)) { - std::cerr << "Compiling vertex source FAILED" << std::endl; - } + if(!vertex_shader_p_l->compileSourceCode(vertex_source_p_l)) + { std::cerr<<"Compiling vertex source FAILED"<compileSourceCode(fragment_source_p_l)) { - std::cerr << "Compiling fragmentsource FAILED" << std::endl; - } + QOpenGLShader *fragment_shader_p_l= new QOpenGLShader(QOpenGLShader::Fragment); + if(!fragment_shader_p_l->compileSourceCode(fragment_source_p_l)) + { std::cerr<<"Compiling fragmentsource FAILED"<compileSourceCode(vertex_source_color)) { - std::cerr << "Compiling vertex source FAILED" << std::endl; - } + QOpenGLShader *vertex_shader_face = new QOpenGLShader(QOpenGLShader::Vertex); + if(!vertex_shader_face->compileSourceCode(vertex_source_color)) + { std::cerr<<"Compiling vertex source FAILED"<compileSourceCode(fragment_source_color)) { - std::cerr << "Compiling fragmentsource FAILED" << std::endl; - } + QOpenGLShader *fragment_shader_face= new QOpenGLShader(QOpenGLShader::Fragment); + if(!fragment_shader_face->compileSourceCode(fragment_source_color)) + { std::cerr<<"Compiling fragmentsource FAILED"<(arrays[POS_MONO_POINTS].size() * sizeof(float))); + buffers[bufn].allocate(arrays[POS_MONO_POINTS].data(), + static_cast(arrays[POS_MONO_POINTS].size()*sizeof(float))); rendering_program_p_l.enableAttributeArray("vertex"); - rendering_program_p_l.setAttributeBuffer("vertex", GL_FLOAT, 0, 3); + rendering_program_p_l.setAttributeBuffer("vertex",GL_FLOAT,0,3); buffers[bufn].release(); @@ -429,23 +467,21 @@ protected: vao[VAO_COLORED_POINTS].bind(); ++bufn; - assert(bufn < NB_VBO_BUFFERS); + assert(bufn(arrays[POS_COLORED_POINTS].size() * sizeof(float))); + buffers[bufn].allocate(arrays[POS_COLORED_POINTS].data(), + static_cast(arrays[POS_COLORED_POINTS].size()*sizeof(float))); rendering_program_p_l.enableAttributeArray("vertex"); - rendering_program_p_l.setAttributeBuffer("vertex", GL_FLOAT, 0, 3); + rendering_program_p_l.setAttributeBuffer("vertex",GL_FLOAT,0,3); buffers[bufn].release(); ++bufn; - assert(bufn < NB_VBO_BUFFERS); + assert(bufn(arrays[COLOR_POINTS].size() * sizeof(float))); + buffers[bufn].allocate(arrays[COLOR_POINTS].data(), + static_cast(arrays[COLOR_POINTS].size()*sizeof(float))); rendering_program_p_l.enableAttributeArray("color"); - rendering_program_p_l.setAttributeBuffer("color", GL_FLOAT, 0, 3); + rendering_program_p_l.setAttributeBuffer("color",GL_FLOAT,0,3); buffers[bufn].release(); vao[VAO_COLORED_POINTS].release(); @@ -456,13 +492,12 @@ protected: vao[VAO_MONO_SEGMENTS].bind(); ++bufn; - assert(bufn < NB_VBO_BUFFERS); + assert(bufn(arrays[POS_MONO_SEGMENTS].size() * sizeof(float))); + buffers[bufn].allocate(arrays[POS_MONO_SEGMENTS].data(), + static_cast(arrays[POS_MONO_SEGMENTS].size()*sizeof(float))); rendering_program_p_l.enableAttributeArray("vertex"); - rendering_program_p_l.setAttributeBuffer("vertex", GL_FLOAT, 0, 3); + rendering_program_p_l.setAttributeBuffer("vertex",GL_FLOAT,0,3); buffers[bufn].release(); @@ -474,24 +509,22 @@ protected: vao[VAO_COLORED_SEGMENTS].bind(); ++bufn; - assert(bufn < NB_VBO_BUFFERS); + assert(bufn(arrays[POS_COLORED_SEGMENTS].size() * sizeof(float))); + buffers[bufn].allocate(arrays[POS_COLORED_SEGMENTS].data(), + static_cast(arrays[POS_COLORED_SEGMENTS].size()*sizeof(float))); rendering_program_p_l.enableAttributeArray("vertex"); - rendering_program_p_l.setAttributeBuffer("vertex", GL_FLOAT, 0, 3); + rendering_program_p_l.setAttributeBuffer("vertex",GL_FLOAT,0,3); buffers[bufn].release(); ++bufn; - assert(bufn < NB_VBO_BUFFERS); + assert(bufn(arrays[COLOR_SEGMENTS].size() * sizeof(float))); + buffers[bufn].allocate(arrays[COLOR_SEGMENTS].data(), + static_cast(arrays[COLOR_SEGMENTS].size()*sizeof(float))); rendering_program_p_l.enableAttributeArray("color"); - rendering_program_p_l.setAttributeBuffer("color", GL_FLOAT, 0, 3); + rendering_program_p_l.setAttributeBuffer("color",GL_FLOAT,0,3); buffers[bufn].release(); vao[VAO_COLORED_SEGMENTS].release(); @@ -504,13 +537,12 @@ protected: vao[VAO_MONO_LINES].bind(); ++bufn; - assert(bufn < NB_VBO_BUFFERS); + assert(bufn(arrays[POS_MONO_LINES].size() * sizeof(float))); + buffers[bufn].allocate(arrays[POS_MONO_LINES].data(), + static_cast(arrays[POS_MONO_LINES].size()*sizeof(float))); rendering_program_p_l.enableAttributeArray("vertex"); - rendering_program_p_l.setAttributeArray("vertex", GL_FLOAT, 0, 3); + rendering_program_p_l.setAttributeArray("vertex",GL_FLOAT,0,3); buffers[bufn].release(); @@ -523,24 +555,22 @@ protected: vao[VAO_COLORED_LINES].bind(); ++bufn; - assert(bufn < NB_VBO_BUFFERS); + assert(bufn(arrays[POS_COLORED_LINES].size() * sizeof(float))); + buffers[bufn].allocate(arrays[POS_COLORED_LINES].data(), + static_cast(arrays[POS_COLORED_LINES].size()*sizeof(float))); rendering_program_p_l.enableAttributeArray("vertex"); - rendering_program_p_l.setAttributeBuffer("vertex", GL_FLOAT, 0, 3); + rendering_program_p_l.setAttributeBuffer("vertex",GL_FLOAT,0,3); buffers[bufn].release(); ++bufn; - assert(bufn < NB_VBO_BUFFERS); + assert(bufn(arrays[COLOR_LINES].size() * sizeof(float))); + buffers[bufn].allocate(arrays[COLOR_LINES].data(), + static_cast(arrays[COLOR_LINES].size()*sizeof(float))); rendering_program_p_l.enableAttributeArray("color"); - rendering_program_p_l.setAttributeBuffer("color", GL_FLOAT, 0, 3); + rendering_program_p_l.setAttributeBuffer("color",GL_FLOAT,0,3); buffers[bufn].release(); vao[VAO_COLORED_LINES].release(); @@ -555,33 +585,33 @@ protected: // 3.1.1) points of the mono faces ++bufn; - assert(bufn < NB_VBO_BUFFERS); + assert(bufn(arrays[POS_MONO_FACES].size() * sizeof(float))); + buffers[bufn].allocate(arrays[POS_MONO_FACES].data(), + static_cast(arrays[POS_MONO_FACES].size()*sizeof(float))); rendering_program_face.enableAttributeArray("vertex"); - rendering_program_face.setAttributeBuffer("vertex", GL_FLOAT, 0, 3); + rendering_program_face.setAttributeBuffer("vertex",GL_FLOAT,0,3); buffers[bufn].release(); // 3.1.2) normals of the mono faces ++bufn; - assert(bufn < NB_VBO_BUFFERS); + assert(bufn(arrays[FLAT_NORMAL_MONO_FACES].size() * - sizeof(float))); - } else { - buffers[bufn].allocate( - arrays[SMOOTH_NORMAL_MONO_FACES].data(), - static_cast(arrays[SMOOTH_NORMAL_MONO_FACES].size() * - sizeof(float))); + if (m_flatShading) + { + buffers[bufn].allocate(arrays[FLAT_NORMAL_MONO_FACES].data(), + static_cast(arrays[FLAT_NORMAL_MONO_FACES].size()* + sizeof(float))); + } + else + { + buffers[bufn].allocate(arrays[SMOOTH_NORMAL_MONO_FACES].data(), + static_cast(arrays[SMOOTH_NORMAL_MONO_FACES].size()* + sizeof(float))); } rendering_program_face.enableAttributeArray("normal"); - rendering_program_face.setAttributeBuffer("normal", GL_FLOAT, 0, 3); + rendering_program_face.setAttributeBuffer("normal",GL_FLOAT,0,3); buffers[bufn].release(); @@ -594,45 +624,44 @@ protected: // 3.2.1) points of the color faces ++bufn; - assert(bufn < NB_VBO_BUFFERS); + assert(bufn(arrays[POS_COLORED_FACES].size() * sizeof(float))); + buffers[bufn].allocate(arrays[POS_COLORED_FACES].data(), + static_cast(arrays[POS_COLORED_FACES].size()*sizeof(float))); rendering_program_face.enableAttributeArray("vertex"); - rendering_program_face.setAttributeBuffer("vertex", GL_FLOAT, 0, 3); + rendering_program_face.setAttributeBuffer("vertex",GL_FLOAT,0,3); buffers[bufn].release(); // 3.2.2) normals of the color faces ++bufn; - assert(bufn < NB_VBO_BUFFERS); + assert(bufn(arrays[FLAT_NORMAL_COLORED_FACES].size() * - sizeof(float))); - } else { - buffers[bufn].allocate( - arrays[SMOOTH_NORMAL_COLORED_FACES].data(), - static_cast(arrays[SMOOTH_NORMAL_COLORED_FACES].size() * - sizeof(float))); + if (m_flatShading) + { + buffers[bufn].allocate(arrays[FLAT_NORMAL_COLORED_FACES].data(), + static_cast(arrays[FLAT_NORMAL_COLORED_FACES].size()* + sizeof(float))); + } + else + { + buffers[bufn].allocate(arrays[SMOOTH_NORMAL_COLORED_FACES].data(), + static_cast(arrays[SMOOTH_NORMAL_COLORED_FACES].size()* + sizeof(float))); } rendering_program_face.enableAttributeArray("normal"); - rendering_program_face.setAttributeBuffer("normal", GL_FLOAT, 0, 3); + rendering_program_face.setAttributeBuffer("normal",GL_FLOAT,0,3); buffers[bufn].release(); // 3.2.3) colors of the faces ++bufn; - assert(bufn < NB_VBO_BUFFERS); + assert(bufn(arrays[COLOR_FACES].size() * sizeof(float))); + buffers[bufn].allocate(arrays[COLOR_FACES].data(), + static_cast(arrays[COLOR_FACES].size()*sizeof(float))); rendering_program_face.enableAttributeArray("color"); - rendering_program_face.setAttributeBuffer("color", GL_FLOAT, 0, 3); + rendering_program_face.setAttributeBuffer("color",GL_FLOAT,0,3); buffers[bufn].release(); @@ -643,36 +672,45 @@ protected: m_are_buffers_initialized = true; } - void attrib_buffers(CGAL::QGLViewer *viewer) { + void attrib_buffers(CGAL::QGLViewer* viewer) + { QMatrix4x4 mvpMatrix; QMatrix4x4 mvMatrix; double mat[16]; viewer->camera()->getModelViewProjectionMatrix(mat); - for (int i = 0; i < 16; i++) { + for(int i=0; i < 16; i++) + { mvpMatrix.data()[i] = (float)mat[i]; } viewer->camera()->getModelViewMatrix(mat); - for (int i = 0; i < 16; i++) { + for(int i=0; i < 16; i++) + { mvMatrix.data()[i] = (float)mat[i]; } // define material - QVector4D diffuse(0.9f, 0.9f, 0.9f, 0.9f); + QVector4D diffuse( 0.9f, + 0.9f, + 0.9f, + 0.9f ); - QVector4D specular(0.0f, 0.0f, 0.0f, 1.0f); + QVector4D specular( 0.0f, + 0.0f, + 0.0f, + 1.0f ); CGAL::Bbox_3 bb; - if (bb == bounding_box()) // Case of "empty" bounding box + if (bb==bounding_box()) // Case of "empty" bounding box { - bb = Local_point(CGAL::ORIGIN).bbox(); - bb = - bb + Local_point(1, 1, 1).bbox(); // To avoid a warning from Qglviewer - } else { - bb = bounding_box(); + bb=Local_point(CGAL::ORIGIN).bbox(); + bb=bb + Local_point(1,1,1).bbox(); // To avoid a warning from Qglviewer } + else + { bb=bounding_box(); } - QVector4D position((bb.xmax() - bb.xmin()) / 2, (bb.ymax() - bb.ymin()) / 2, + QVector4D position((bb.xmax()-bb.xmin())/2, + (bb.ymax()-bb.ymin())/2, bb.zmax(), 0.0); - GLfloat shininess = 1.0f; + GLfloat shininess = 1.0f; rendering_program_face.bind(); int mvpLocation = rendering_program_face.uniformLocation("mvp_matrix"); @@ -699,180 +737,180 @@ protected: rendering_program_p_l.release(); } - virtual void draw() { + virtual void draw() + { glEnable(GL_DEPTH_TEST); - if (!m_are_buffers_initialized) { - initialize_buffers(); - } + if(!m_are_buffers_initialized) + { initialize_buffers(); } QColor color; attrib_buffers(this); - if (m_draw_vertices) { + if(m_draw_vertices) + { rendering_program_p_l.bind(); vao[VAO_MONO_POINTS].bind(); - color.setRgbF((double)m_vertices_mono_color.red() / (double)255, - (double)m_vertices_mono_color.green() / (double)255, - (double)m_vertices_mono_color.blue() / (double)255); - rendering_program_p_l.setAttributeValue("color", color); - rendering_program_p_l.setUniformValue("point_size", - GLfloat(m_size_points)); - glDrawArrays(GL_POINTS, 0, - static_cast(arrays[POS_MONO_POINTS].size() / 3)); + color.setRgbF((double)m_vertices_mono_color.red()/(double)255, + (double)m_vertices_mono_color.green()/(double)255, + (double)m_vertices_mono_color.blue()/(double)255); + rendering_program_p_l.setAttributeValue("color",color); + rendering_program_p_l.setUniformValue("point_size", GLfloat(m_size_points)); + glDrawArrays(GL_POINTS, 0, static_cast(arrays[POS_MONO_POINTS].size()/3)); vao[VAO_MONO_POINTS].release(); vao[VAO_COLORED_POINTS].bind(); - if (m_use_mono_color) { - color.setRgbF((double)m_vertices_mono_color.red() / (double)255, - (double)m_vertices_mono_color.green() / (double)255, - (double)m_vertices_mono_color.blue() / (double)255); + if (m_use_mono_color) + { + color.setRgbF((double)m_vertices_mono_color.red()/(double)255, + (double)m_vertices_mono_color.green()/(double)255, + (double)m_vertices_mono_color.blue()/(double)255); rendering_program_p_l.disableAttributeArray("color"); - rendering_program_p_l.setAttributeValue("color", color); - } else { + rendering_program_p_l.setAttributeValue("color",color); + } + else + { rendering_program_p_l.enableAttributeArray("color"); } - rendering_program_p_l.setUniformValue("point_size", - GLfloat(m_size_points)); - glDrawArrays(GL_POINTS, 0, - static_cast(arrays[POS_COLORED_POINTS].size() / 3)); + rendering_program_p_l.setUniformValue("point_size", GLfloat(m_size_points)); + glDrawArrays(GL_POINTS, 0, static_cast(arrays[POS_COLORED_POINTS].size()/3)); vao[VAO_COLORED_POINTS].release(); rendering_program_p_l.release(); } - if (m_draw_edges) { + if(m_draw_edges) + { rendering_program_p_l.bind(); vao[VAO_MONO_SEGMENTS].bind(); - color.setRgbF((double)m_edges_mono_color.red() / (double)255, - (double)m_edges_mono_color.green() / (double)255, - (double)m_edges_mono_color.blue() / (double)255); - rendering_program_p_l.setAttributeValue("color", color); + color.setRgbF((double)m_edges_mono_color.red()/(double)255, + (double)m_edges_mono_color.green()/(double)255, + (double)m_edges_mono_color.blue()/(double)255); + rendering_program_p_l.setAttributeValue("color",color); glLineWidth(m_size_edges); - glDrawArrays(GL_LINES, 0, - static_cast(arrays[POS_MONO_SEGMENTS].size() / 3)); + glDrawArrays(GL_LINES, 0, static_cast(arrays[POS_MONO_SEGMENTS].size()/3)); vao[VAO_MONO_SEGMENTS].release(); vao[VAO_COLORED_SEGMENTS].bind(); - if (m_use_mono_color) { - color.setRgbF((double)m_edges_mono_color.red() / (double)255, - (double)m_edges_mono_color.green() / (double)255, - (double)m_edges_mono_color.blue() / (double)255); + if (m_use_mono_color) + { + color.setRgbF((double)m_edges_mono_color.red()/(double)255, + (double)m_edges_mono_color.green()/(double)255, + (double)m_edges_mono_color.blue()/(double)255); rendering_program_p_l.disableAttributeArray("color"); - rendering_program_p_l.setAttributeValue("color", color); - } else { + rendering_program_p_l.setAttributeValue("color",color); + } + else + { rendering_program_p_l.enableAttributeArray("color"); } glLineWidth(m_size_edges); - glDrawArrays( - GL_LINES, 0, - static_cast(arrays[POS_COLORED_SEGMENTS].size() / 3)); + glDrawArrays(GL_LINES, 0, static_cast(arrays[POS_COLORED_SEGMENTS].size()/3)); vao[VAO_COLORED_SEGMENTS].release(); rendering_program_p_l.release(); } - if (m_draw_lines) { - rendering_program_p_l.bind(); + if(m_draw_lines) + { + rendering_program_p_l.bind(); - vao[VAO_MONO_LINES].bind(); - color.setRgbF((double)m_lines_mono_color.red() / (double)255, - (double)m_lines_mono_color.green() / (double)255, - (double)m_lines_mono_color.blue() / (double)255); - rendering_program_p_l.setAttributeValue("color", color); - glLineWidth(m_size_lines); - glDrawArrays(GL_LINES, 0, - static_cast(arrays[POS_MONO_LINES].size() / 3)); - vao[VAO_MONO_LINES].release(); + vao[VAO_MONO_LINES].bind(); + color.setRgbF((double)m_lines_mono_color.red()/(double)255, + (double)m_lines_mono_color.green()/(double)255, + (double)m_lines_mono_color.blue()/(double)255); + rendering_program_p_l.setAttributeValue("color",color); + glLineWidth(m_size_lines); + glDrawArrays(GL_LINES, 0, static_cast(arrays[POS_MONO_LINES].size()/3)); + vao[VAO_MONO_LINES].release(); - vao[VAO_COLORED_LINES].bind(); - if (m_use_mono_color) { - color.setRgbF((double)m_lines_mono_color.red() / (double)255, - (double)m_lines_mono_color.green() / (double)255, - (double)m_lines_mono_color.blue() / (double)255); - rendering_program_p_l.disableAttributeArray("color"); - rendering_program_p_l.setAttributeValue("color", color); - } else { - rendering_program_p_l.enableAttributeArray("color"); - } - glLineWidth(m_size_lines); - glDrawArrays(GL_LINES, 0, - static_cast(arrays[POS_COLORED_LINES].size() / 3)); - vao[VAO_COLORED_LINES].release(); + vao[VAO_COLORED_LINES].bind(); + if (m_use_mono_color) + { + color.setRgbF((double)m_lines_mono_color.red()/(double)255, + (double)m_lines_mono_color.green()/(double)255, + (double)m_lines_mono_color.blue()/(double)255); + rendering_program_p_l.disableAttributeArray("color"); + rendering_program_p_l.setAttributeValue("color",color); + } + else + { + rendering_program_p_l.enableAttributeArray("color"); + } + glLineWidth(m_size_lines); + glDrawArrays(GL_LINES, 0, static_cast(arrays[POS_COLORED_LINES].size()/3)); + vao[VAO_COLORED_LINES].release(); - rendering_program_p_l.release(); + rendering_program_p_l.release(); } - if (m_draw_faces) { + if (m_draw_faces) + { rendering_program_face.bind(); vao[VAO_MONO_FACES].bind(); - color.setRgbF((double)m_faces_mono_color.red() / (double)255, - (double)m_faces_mono_color.green() / (double)255, - (double)m_faces_mono_color.blue() / (double)255); - rendering_program_face.setAttributeValue("color", color); - glDrawArrays(GL_TRIANGLES, 0, - static_cast(arrays[POS_MONO_FACES].size() / 3)); + color.setRgbF((double)m_faces_mono_color.red()/(double)255, + (double)m_faces_mono_color.green()/(double)255, + (double)m_faces_mono_color.blue()/(double)255); + rendering_program_face.setAttributeValue("color",color); + glDrawArrays(GL_TRIANGLES, 0, static_cast(arrays[POS_MONO_FACES].size()/3)); vao[VAO_MONO_FACES].release(); vao[VAO_COLORED_FACES].bind(); - if (m_use_mono_color) { - color.setRgbF((double)m_faces_mono_color.red() / (double)255, - (double)m_faces_mono_color.green() / (double)255, - (double)m_faces_mono_color.blue() / (double)255); + if (m_use_mono_color) + { + color.setRgbF((double)m_faces_mono_color.red()/(double)255, + (double)m_faces_mono_color.green()/(double)255, + (double)m_faces_mono_color.blue()/(double)255); rendering_program_face.disableAttributeArray("color"); - rendering_program_face.setAttributeValue("color", color); - } else { + rendering_program_face.setAttributeValue("color",color); + } + else + { rendering_program_face.enableAttributeArray("color"); } - glDrawArrays(GL_TRIANGLES, 0, - static_cast(arrays[POS_COLORED_FACES].size() / 3)); + glDrawArrays(GL_TRIANGLES, 0, static_cast(arrays[POS_COLORED_FACES].size()/3)); vao[VAO_COLORED_FACES].release(); rendering_program_face.release(); } } - virtual void redraw() { + virtual void redraw() + { initialize_buffers(); update(); } - virtual void init() { + virtual void init() + { // Restore previous viewer state. restoreStateFromFile(); initializeOpenGLFunctions(); // Define 'Control+Q' as the new exit shortcut (default was 'Escape') - setShortcut(qglviewer::EXIT_VIEWER, ::Qt::CTRL + ::Qt::Key_Q); + setShortcut(qglviewer::EXIT_VIEWER, ::Qt::CTRL+::Qt::Key_Q); // Add custom key description (see keyPressEvent). setKeyDescription(::Qt::Key_E, "Toggles edges display"); setKeyDescription(::Qt::Key_F, "Toggles faces display"); - setKeyDescription(::Qt::Key_G, - "Switch between flat/Gouraud shading display"); + setKeyDescription(::Qt::Key_G, "Switch between flat/Gouraud shading display"); setKeyDescription(::Qt::Key_M, "Toggles mono color"); setKeyDescription(::Qt::Key_N, "Inverse direction of normals"); setKeyDescription(::Qt::Key_V, "Toggles vertices display"); setKeyDescription(::Qt::Key_Plus, "Increase size of edges"); setKeyDescription(::Qt::Key_Minus, "Decrease size of edges"); - setKeyDescription(::Qt::Key_Plus + ::Qt::ControlModifier, - "Increase size of vertices"); - setKeyDescription(::Qt::Key_Minus + ::Qt::ControlModifier, - "Decrease size of vertices"); - setKeyDescription(::Qt::Key_PageDown, - "Increase light (all colors, use shift/alt/ctrl for one " - "rgb component)"); - setKeyDescription(::Qt::Key_PageUp, - "Decrease light (all colors, use shift/alt/ctrl for one " - "rgb component)"); + setKeyDescription(::Qt::Key_Plus+::Qt::ControlModifier, "Increase size of vertices"); + setKeyDescription(::Qt::Key_Minus+::Qt::ControlModifier, "Decrease size of vertices"); + setKeyDescription(::Qt::Key_PageDown, "Increase light (all colors, use shift/alt/ctrl for one rgb component)"); + setKeyDescription(::Qt::Key_PageUp, "Decrease light (all colors, use shift/alt/ctrl for one rgb component)"); // Light default parameters glLineWidth(m_size_edges); glEnable(GL_POLYGON_OFFSET_FILL); - glPolygonOffset(1.f, 1.f); - glClearColor(1.0f, 1.0f, 1.0f, 0.0f); + glPolygonOffset(1.f,1.f); + glClearColor(1.0f,1.0f,1.0f,0.0f); glDisable(GL_BLEND); glEnable(GL_LINE_SMOOTH); glDisable(GL_POLYGON_SMOOTH_HINT); @@ -882,215 +920,207 @@ protected: compile_shaders(); CGAL::Bbox_3 bb; - if (bb == bounding_box()) // Case of "empty" bounding box + if (bb==bounding_box()) // Case of "empty" bounding box { - bb = Local_point(CGAL::ORIGIN).bbox(); - bb = - bb + Local_point(1, 1, 1).bbox(); // To avoid a warning from Qglviewer - } else { - bb = bounding_box(); + bb=Local_point(CGAL::ORIGIN).bbox(); + bb=bb + Local_point(1,1,1).bbox(); // To avoid a warning from Qglviewer } - this->camera()->setSceneBoundingBox( - CGAL::qglviewer::Vec(bb.xmin(), bb.ymin(), bb.zmin()), - CGAL::qglviewer::Vec(bb.xmax(), bb.ymax(), bb.zmax())); + else + { bb=bounding_box(); } + this->camera()->setSceneBoundingBox(CGAL::qglviewer::Vec(bb.xmin(), + bb.ymin(), + bb.zmin()), + CGAL::qglviewer::Vec(bb.xmax(), + bb.ymax(), + bb.zmax())); this->showEntireScene(); } - void negate_all_normals() { - for (unsigned int k = BEGIN_NORMAL; k < END_NORMAL; ++k) { - for (std::size_t i = 0; i < arrays[k].size(); ++i) { - arrays[k][i] = -arrays[k][i]; - } + void negate_all_normals() + { + for (unsigned int k=BEGIN_NORMAL; kmodifiers(); - if ((e->key() == ::Qt::Key_E) && (modifiers == ::Qt::NoButton)) { - m_draw_edges = !m_draw_edges; - displayMessage( - QString("Draw edges=%1.").arg(m_draw_edges ? "true" : "false")); + if ((e->key()==::Qt::Key_E) && (modifiers==::Qt::NoButton)) + { + m_draw_edges=!m_draw_edges; + displayMessage(QString("Draw edges=%1.").arg(m_draw_edges?"true":"false")); update(); - } else if ((e->key() == ::Qt::Key_F) && (modifiers == ::Qt::NoButton)) { - m_draw_faces = !m_draw_faces; - displayMessage( - QString("Draw faces=%1.").arg(m_draw_faces ? "true" : "false")); + } + else if ((e->key()==::Qt::Key_F) && (modifiers==::Qt::NoButton)) + { + m_draw_faces=!m_draw_faces; + displayMessage(QString("Draw faces=%1.").arg(m_draw_faces?"true":"false")); update(); - } else if ((e->key() == ::Qt::Key_G) && (modifiers == ::Qt::NoButton)) { - m_flatShading = !m_flatShading; + } + else if ((e->key()==::Qt::Key_G) && (modifiers==::Qt::NoButton)) + { + m_flatShading=!m_flatShading; if (m_flatShading) displayMessage("Flat shading."); else displayMessage("Gouraud shading."); redraw(); - } else if ((e->key() == ::Qt::Key_M) && (modifiers == ::Qt::NoButton)) { - m_use_mono_color = !m_use_mono_color; - displayMessage( - QString("Mono color=%1.").arg(m_use_mono_color ? "true" : "false")); + } + else if ((e->key()==::Qt::Key_M) && (modifiers==::Qt::NoButton)) + { + m_use_mono_color=!m_use_mono_color; + displayMessage(QString("Mono color=%1.").arg(m_use_mono_color?"true":"false")); update(); - } else if ((e->key() == ::Qt::Key_N) && (modifiers == ::Qt::NoButton)) { - m_inverse_normal = !m_inverse_normal; - displayMessage(QString("Inverse normal=%1.") - .arg(m_inverse_normal ? "true" : "false")); + } + else if ((e->key()==::Qt::Key_N) && (modifiers==::Qt::NoButton)) + { + m_inverse_normal=!m_inverse_normal; + displayMessage(QString("Inverse normal=%1.").arg(m_inverse_normal?"true":"false")); negate_all_normals(); redraw(); - } else if ((e->key() == ::Qt::Key_V) && (modifiers == ::Qt::NoButton)) { - m_draw_vertices = !m_draw_vertices; - displayMessage( - QString("Draw vertices=%1.").arg(m_draw_vertices ? "true" : "false")); - update(); - } else if ((e->key() == ::Qt::Key_Plus) && - (!modifiers.testFlag(::Qt::ControlModifier))) // No ctrl + } + else if ((e->key()==::Qt::Key_V) && (modifiers==::Qt::NoButton)) { - m_size_edges += .5; + m_draw_vertices=!m_draw_vertices; + displayMessage(QString("Draw vertices=%1.").arg(m_draw_vertices?"true":"false")); + update(); + } + else if ((e->key()==::Qt::Key_Plus) && (!modifiers.testFlag(::Qt::ControlModifier))) // No ctrl + { + m_size_edges+=.5; displayMessage(QString("Size of edges=%1.").arg(m_size_edges)); update(); - } else if ((e->key() == ::Qt::Key_Minus) && - (!modifiers.testFlag(::Qt::ControlModifier))) // No ctrl + } + else if ((e->key()==::Qt::Key_Minus) && (!modifiers.testFlag(::Qt::ControlModifier))) // No ctrl { - if (m_size_edges > .5) - m_size_edges -= .5; + if (m_size_edges>.5) m_size_edges-=.5; displayMessage(QString("Size of edges=%1.").arg(m_size_edges)); update(); - } else if ((e->key() == ::Qt::Key_Plus) && - (modifiers.testFlag(::Qt::ControlModifier))) { - m_size_points += .5; + } + else if ((e->key()==::Qt::Key_Plus) && (modifiers.testFlag(::Qt::ControlModifier))) + { + m_size_points+=.5; displayMessage(QString("Size of points=%1.").arg(m_size_points)); update(); - } else if ((e->key() == ::Qt::Key_Minus) && - (modifiers.testFlag(::Qt::ControlModifier))) { - if (m_size_points > .5) - m_size_points -= .5; + } + else if ((e->key()==::Qt::Key_Minus) && (modifiers.testFlag(::Qt::ControlModifier))) + { + if (m_size_points>.5) m_size_points-=.5; displayMessage(QString("Size of points=%1.").arg(m_size_points)); update(); - } else if ((e->key() == ::Qt::Key_PageUp) && - (modifiers == ::Qt::NoButton)) { - m_ambient_color.setX(m_ambient_color.x() + .1); - if (m_ambient_color.x() > 1.) - m_ambient_color.setX(1.); - m_ambient_color.setY(m_ambient_color.x() + .1); - if (m_ambient_color.y() > 1.) - m_ambient_color.setY(1.); - m_ambient_color.setZ(m_ambient_color.x() + .1); - if (m_ambient_color.z() > 1.) - m_ambient_color.setZ(1.); - displayMessage(QString("Light color=(%1 %2 %3).") - .arg(m_ambient_color.x()) - .arg(m_ambient_color.y()) - .arg(m_ambient_color.z())); + } + else if ((e->key()==::Qt::Key_PageUp) && (modifiers==::Qt::NoButton)) + { + m_ambient_color.setX(m_ambient_color.x()+.1); + if (m_ambient_color.x()>1.) m_ambient_color.setX(1.); + m_ambient_color.setY(m_ambient_color.x()+.1); + if (m_ambient_color.y()>1.) m_ambient_color.setY(1.); + m_ambient_color.setZ(m_ambient_color.x()+.1); + if (m_ambient_color.z()>1.) m_ambient_color.setZ(1.); + displayMessage(QString("Light color=(%1 %2 %3)."). + arg(m_ambient_color.x()).arg(m_ambient_color.y()).arg(m_ambient_color.z())); update(); - } else if ((e->key() == ::Qt::Key_PageDown) && - (modifiers == ::Qt::NoButton)) { - m_ambient_color.setX(m_ambient_color.x() - .1); - if (m_ambient_color.x() < 0.) - m_ambient_color.setX(0.); - m_ambient_color.setY(m_ambient_color.y() - .1); - if (m_ambient_color.y() < 0.) - m_ambient_color.setY(0.); - m_ambient_color.setZ(m_ambient_color.z() - .1); - if (m_ambient_color.z() < 0.) - m_ambient_color.setZ(0.); - displayMessage(QString("Light color=(%1 %2 %3).") - .arg(m_ambient_color.x()) - .arg(m_ambient_color.y()) - .arg(m_ambient_color.z())); + } + else if ((e->key()==::Qt::Key_PageDown) && (modifiers==::Qt::NoButton)) + { + m_ambient_color.setX(m_ambient_color.x()-.1); + if (m_ambient_color.x()<0.) m_ambient_color.setX(0.); + m_ambient_color.setY(m_ambient_color.y()-.1); + if (m_ambient_color.y()<0.) m_ambient_color.setY(0.); + m_ambient_color.setZ(m_ambient_color.z()-.1); + if (m_ambient_color.z()<0.) m_ambient_color.setZ(0.); + displayMessage(QString("Light color=(%1 %2 %3)."). + arg(m_ambient_color.x()).arg(m_ambient_color.y()).arg(m_ambient_color.z())); update(); - } else if ((e->key() == ::Qt::Key_PageUp) && - (modifiers == ::Qt::ShiftModifier)) { - m_ambient_color.setX(m_ambient_color.x() + .1); - if (m_ambient_color.x() > 1.) - m_ambient_color.setX(1.); - displayMessage(QString("Light color=(%1 %2 %3).") - .arg(m_ambient_color.x()) - .arg(m_ambient_color.y()) - .arg(m_ambient_color.z())); + } + else if ((e->key()==::Qt::Key_PageUp) && (modifiers==::Qt::ShiftModifier)) + { + m_ambient_color.setX(m_ambient_color.x()+.1); + if (m_ambient_color.x()>1.) m_ambient_color.setX(1.); + displayMessage(QString("Light color=(%1 %2 %3)."). + arg(m_ambient_color.x()).arg(m_ambient_color.y()).arg(m_ambient_color.z())); update(); - } else if ((e->key() == ::Qt::Key_PageUp) && - (modifiers == ::Qt::AltModifier)) { - m_ambient_color.setY(m_ambient_color.y() + .1); - if (m_ambient_color.y() > 1.) - m_ambient_color.setY(1.); - displayMessage(QString("Light color=(%1 %2 %3).") - .arg(m_ambient_color.x()) - .arg(m_ambient_color.y()) - .arg(m_ambient_color.z())); + } + else if ((e->key()==::Qt::Key_PageUp) && (modifiers==::Qt::AltModifier)) + { + m_ambient_color.setY(m_ambient_color.y()+.1); + if (m_ambient_color.y()>1.) m_ambient_color.setY(1.); + displayMessage(QString("Light color=(%1 %2 %3)."). + arg(m_ambient_color.x()).arg(m_ambient_color.y()).arg(m_ambient_color.z())); update(); - } else if ((e->key() == ::Qt::Key_PageUp) && - (modifiers == ::Qt::ControlModifier)) { - m_ambient_color.setZ(m_ambient_color.z() + .1); - if (m_ambient_color.z() > 1.) - m_ambient_color.setZ(1.); - displayMessage(QString("Light color=(%1 %2 %3).") - .arg(m_ambient_color.x()) - .arg(m_ambient_color.y()) - .arg(m_ambient_color.z())); + } + else if ((e->key()==::Qt::Key_PageUp) && (modifiers==::Qt::ControlModifier)) + { + m_ambient_color.setZ(m_ambient_color.z()+.1); + if (m_ambient_color.z()>1.) m_ambient_color.setZ(1.); + displayMessage(QString("Light color=(%1 %2 %3)."). + arg(m_ambient_color.x()).arg(m_ambient_color.y()).arg(m_ambient_color.z())); update(); - } else if ((e->key() == ::Qt::Key_PageDown) && - (modifiers == ::Qt::ShiftModifier)) { - m_ambient_color.setX(m_ambient_color.x() - .1); - if (m_ambient_color.x() < 0.) - m_ambient_color.setX(0.); - displayMessage(QString("Light color=(%1 %2 %3).") - .arg(m_ambient_color.x()) - .arg(m_ambient_color.y()) - .arg(m_ambient_color.z())); + } + else if ((e->key()==::Qt::Key_PageDown) && (modifiers==::Qt::ShiftModifier)) + { + m_ambient_color.setX(m_ambient_color.x()-.1); + if (m_ambient_color.x()<0.) m_ambient_color.setX(0.); + displayMessage(QString("Light color=(%1 %2 %3)."). + arg(m_ambient_color.x()).arg(m_ambient_color.y()).arg(m_ambient_color.z())); update(); - } else if ((e->key() == ::Qt::Key_PageDown) && - (modifiers == ::Qt::AltModifier)) { - m_ambient_color.setY(m_ambient_color.y() - .1); - if (m_ambient_color.y() < 0.) - m_ambient_color.setY(0.); - displayMessage(QString("Light color=(%1 %2 %3).") - .arg(m_ambient_color.x()) - .arg(m_ambient_color.y()) - .arg(m_ambient_color.z())); + } + else if ((e->key()==::Qt::Key_PageDown) && (modifiers==::Qt::AltModifier)) + { + m_ambient_color.setY(m_ambient_color.y()-.1); + if (m_ambient_color.y()<0.) m_ambient_color.setY(0.); + displayMessage(QString("Light color=(%1 %2 %3)."). + arg(m_ambient_color.x()).arg(m_ambient_color.y()).arg(m_ambient_color.z())); update(); - } else if ((e->key() == ::Qt::Key_PageDown) && - (modifiers == ::Qt::ControlModifier)) { - m_ambient_color.setZ(m_ambient_color.z() - .1); - if (m_ambient_color.z() < 0.) - m_ambient_color.setZ(0.); - displayMessage(QString("Light color=(%1 %2 %3).") - .arg(m_ambient_color.x()) - .arg(m_ambient_color.y()) - .arg(m_ambient_color.z())); + } + else if ((e->key()==::Qt::Key_PageDown) && (modifiers==::Qt::ControlModifier)) + { + m_ambient_color.setZ(m_ambient_color.z()-.1); + if (m_ambient_color.z()<0.) m_ambient_color.setZ(0.); + displayMessage(QString("Light color=(%1 %2 %3)."). + arg(m_ambient_color.x()).arg(m_ambient_color.y()).arg(m_ambient_color.z())); update(); - } else + } + else CGAL::QGLViewer::keyPressEvent(e); } - virtual QString helpString() const { return helpString("CGAL Basic Viewer"); } + virtual QString helpString() const + { return helpString("CGAL Basic Viewer"); } - virtual QString helpString(const char *title) const { - QString text(QString("

    ") + QString(title) + QString("

    ")); + virtual QString helpString(const char* title) const + { + QString text(QString("

    ")+QString(title)+QString("

    ")); text += "Use the mouse to move the camera around the object. "; text += "You can respectively revolve around, zoom and translate with " - "the three mouse buttons. "; + "the three mouse buttons. "; text += "Left and middle buttons pressed together rotate around the " - "camera view direction axis

    "; + "camera view direction axis

    "; text += "Pressing Alt and one of the function keys " - "(F1..F12) defines a camera keyFrame. "; + "(F1..F12) defines a camera keyFrame. "; text += "Simply press the function key again to restore it. " - "Several keyFrames define a "; + "Several keyFrames define a "; text += "camera path. Paths are saved when you quit the application " - "and restored at next start.

    "; + "and restored at next start.

    "; text += "Press F to display the frame rate, A for the " - "world axis, "; + "world axis, "; text += "Alt+Return for full screen mode and Control+S " - "to save a snapshot. "; + "to save a snapshot. "; text += "See the Keyboard tab in this window for a complete " - "shortcut list.

    "; + "shortcut list.

    "; text += "Double clicks automates single click actions: A left button " - "double click aligns the closer axis with the camera (if close " - "enough). "; + "double click aligns the closer axis with the camera (if close enough). "; text += "A middle button double click fits the zoom of the camera and " - "the right button re-centers the scene.

    "; + "the right button re-centers the scene.

    "; text += "A left button double click while holding right button pressed " - "defines the camera Revolve Around Point. "; + "defines the camera Revolve Around Point. "; text += "See the Mouse tab and the documentation web pages for " - "details.

    "; + "details.

    "; text += "Press Escape to exit the viewer."; return text; } @@ -1112,16 +1142,16 @@ protected: CGAL::Color m_edges_mono_color; CGAL::Color m_lines_mono_color; CGAL::Color m_faces_mono_color; - QVector4D m_ambient_color; + QVector4D m_ambient_color; bool m_are_buffers_initialized; CGAL::Bbox_3 m_bounding_box; - // The following enum gives the indices of different elements of arrays - // vectors. - enum { - BEGIN_POS = 0, - POS_MONO_POINTS = BEGIN_POS, + // The following enum gives the indices of different elements of arrays vectors. + enum + { + BEGIN_POS=0, + POS_MONO_POINTS=BEGIN_POS, POS_COLORED_POINTS, POS_MONO_SEGMENTS, POS_COLORED_SEGMENTS, @@ -1130,19 +1160,19 @@ protected: POS_MONO_FACES, POS_COLORED_FACES, END_POS, - BEGIN_COLOR = END_POS, - COLOR_POINTS = BEGIN_COLOR, + BEGIN_COLOR=END_POS, + COLOR_POINTS=BEGIN_COLOR, COLOR_SEGMENTS, COLOR_LINES, COLOR_FACES, END_COLOR, - BEGIN_NORMAL = END_COLOR, - SMOOTH_NORMAL_MONO_FACES = BEGIN_NORMAL, + BEGIN_NORMAL=END_COLOR, + SMOOTH_NORMAL_MONO_FACES=BEGIN_NORMAL, FLAT_NORMAL_MONO_FACES, SMOOTH_NORMAL_COLORED_FACES, FLAT_NORMAL_COLORED_FACES, END_NORMAL, - LAST_INDEX = END_NORMAL + LAST_INDEX=END_NORMAL }; std::vector arrays[LAST_INDEX]; @@ -1155,24 +1185,23 @@ protected: Buffer_for_vao m_buffer_for_mono_faces; Buffer_for_vao m_buffer_for_colored_faces; - static const unsigned int NB_VBO_BUFFERS = (END_POS - BEGIN_POS) + - (END_COLOR - BEGIN_COLOR) + - 2; // +2 for 2 vectors of normals + static const unsigned int NB_VBO_BUFFERS=(END_POS-BEGIN_POS)+ + (END_COLOR-BEGIN_COLOR)+2; // +2 for 2 vectors of normals QGLBuffer buffers[NB_VBO_BUFFERS]; // The following enum gives the indices of the differents vao. - enum { - VAO_MONO_POINTS = 0, - VAO_COLORED_POINTS, - VAO_MONO_SEGMENTS, - VAO_COLORED_SEGMENTS, - VAO_MONO_LINES, - VAO_COLORED_LINES, - VAO_MONO_FACES, - VAO_COLORED_FACES, - NB_VAO_BUFFERS - }; + enum + { VAO_MONO_POINTS=0, + VAO_COLORED_POINTS, + VAO_MONO_SEGMENTS, + VAO_COLORED_SEGMENTS, + VAO_MONO_LINES, + VAO_COLORED_LINES, + VAO_MONO_FACES, + VAO_COLORED_FACES, + NB_VAO_BUFFERS + }; QOpenGLVertexArrayObject vao[NB_VAO_BUFFERS]; QOpenGLShaderProgram rendering_program_face; @@ -1183,31 +1212,35 @@ protected: #else // CGAL_USE_BASIC_VIEWER -namespace CGAL { +namespace CGAL +{ -template -void draw(const T &, const char *, bool, const ColorFunctor &) { - std::cerr - << "Impossible to draw because CGAL_USE_BASIC_VIEWER is not defined." - << std::endl; +template +void draw(const T&, const char*, bool, const ColorFunctor&) +{ + std::cerr<<"Impossible to draw because CGAL_USE_BASIC_VIEWER is not defined." + < void draw(const T &, const char *, bool) { - std::cerr - << "Impossible to draw because CGAL_USE_BASIC_VIEWER is not defined." - << std::endl; +template +void draw(const T&, const char*, bool) +{ + std::cerr<<"Impossible to draw because CGAL_USE_BASIC_VIEWER is not defined." + < void draw(const T &, const char *) { - std::cerr - << "Impossible to draw because CGAL_USE_BASIC_VIEWER is not defined." - << std::endl; +template +void draw(const T&, const char*) +{ + std::cerr<<"Impossible to draw because CGAL_USE_BASIC_VIEWER is not defined." + < void draw(const T &) { - std::cerr - << "Impossible to draw because CGAL_USE_BASIC_VIEWER is not defined." - << std::endl; +template +void draw(const T&) +{ + std::cerr<<"Impossible to draw because CGAL_USE_BASIC_VIEWER is not defined." + < Date: Mon, 17 Jun 2019 20:45:04 -0700 Subject: [PATCH 062/363] Toggle ray display with keypress R. Start adding face viewer --- .../include/CGAL/Qt/Basic_viewer_qt.h | 9 +++++++- .../include/CGAL/draw_voronoi_diagram_2.h | 22 +++++++++---------- 2 files changed, 19 insertions(+), 12 deletions(-) diff --git a/GraphicsView/include/CGAL/Qt/Basic_viewer_qt.h b/GraphicsView/include/CGAL/Qt/Basic_viewer_qt.h index e67997b05fe..78c47b42b56 100644 --- a/GraphicsView/include/CGAL/Qt/Basic_viewer_qt.h +++ b/GraphicsView/include/CGAL/Qt/Basic_viewer_qt.h @@ -331,7 +331,7 @@ public: p1 = Local_kernel::Point_2(p.x() + txmax * v.x(), p.y() + tymax * v.y()); } - m_buffer_for_mono_segments.add_segment(p, p1); + m_buffer_for_mono_lines.add_segment(p, p1); } bool is_a_face_started() const @@ -894,6 +894,7 @@ protected: // Add custom key description (see keyPressEvent). setKeyDescription(::Qt::Key_E, "Toggles edges display"); + setKeyDescription(::Qt::Key_R, "Toggles rays display"); setKeyDescription(::Qt::Key_F, "Toggles faces display"); setKeyDescription(::Qt::Key_G, "Switch between flat/Gouraud shading display"); setKeyDescription(::Qt::Key_M, "Toggles mono color"); @@ -956,6 +957,12 @@ protected: displayMessage(QString("Draw edges=%1.").arg(m_draw_edges?"true":"false")); update(); } + if ((e->key()==::Qt::Key_R) && (modifiers==::Qt::NoButton)) + { + m_draw_lines=!m_draw_lines; + displayMessage(QString("Draw rays=%1.").arg(m_draw_lines?"true":"false")); + update(); + } else if ((e->key()==::Qt::Key_F) && (modifiers==::Qt::NoButton)) { m_draw_faces=!m_draw_faces; diff --git a/Voronoi_diagram_2/include/CGAL/draw_voronoi_diagram_2.h b/Voronoi_diagram_2/include/CGAL/draw_voronoi_diagram_2.h index 459b315eda5..0dcf8a5b35b 100644 --- a/Voronoi_diagram_2/include/CGAL/draw_voronoi_diagram_2.h +++ b/Voronoi_diagram_2/include/CGAL/draw_voronoi_diagram_2.h @@ -84,19 +84,19 @@ public: protected: void compute_face(Face_const_handle fh) { - // CGAL::Color c=m_fcolor.run(v2, fh); - // face_begin(c); - // Ccb_halfedge_circulator ec_start = fh->ccb(); - // Ccb_halfedge_circulator ec = ec_start; + CGAL::Color c=m_fcolor.run(v2, fh); + face_begin(c); + Ccb_halfedge_circulator ec_start = fh->ccb(); + Ccb_halfedge_circulator ec = ec_start; - // do{ - // if( ec->has_source() ) - // add_point_in_face(ec->source()->point()); - // else if(ec->has_target()) - // add_point_in_face(ec->target()->point()); - // } while(++ec != ec_start); + do{ + if( ec->has_source() ) + add_point_in_face(ec->source()->point()); + else if(ec->has_target()) + add_point_in_face(ec->target()->point()); + } while(++ec != ec_start); - // face_end(); + face_end(); } void compute_ray_points(Halfedge_const_handle he) { From ff5e9a3820f490f36650a8becc9ef8bcfc47c7c9 Mon Sep 17 00:00:00 2001 From: Jasmeet Singh Date: Tue, 18 Jun 2019 17:51:18 -0700 Subject: [PATCH 063/363] Add compute_face() functionality and get_second_point() to find intersection of ray with bounding box Show wireframe. Not building successfully as qOpenGLFunctions do not support glPolygonMode(). Comitting to save progress. --- .../include/CGAL/Qt/Basic_viewer_qt.h | 19 ++- .../examples/Voronoi_diagram_2/CMakeLists.txt | 11 +- .../include/CGAL/draw_voronoi_diagram_2.h | 119 +++++++++++++----- 3 files changed, 111 insertions(+), 38 deletions(-) diff --git a/GraphicsView/include/CGAL/Qt/Basic_viewer_qt.h b/GraphicsView/include/CGAL/Qt/Basic_viewer_qt.h index f6ec356531a..b6898fc9430 100644 --- a/GraphicsView/include/CGAL/Qt/Basic_viewer_qt.h +++ b/GraphicsView/include/CGAL/Qt/Basic_viewer_qt.h @@ -170,7 +170,8 @@ public: bool draw_lines=true, bool draw_faces=true, bool use_mono_color=false, - bool inverse_normal=false) : + bool inverse_normal=false, + bool draw_wireframe=false) : CGAL::QGLViewer(parent), m_draw_vertices(draw_vertices), m_draw_edges(draw_edges), @@ -179,6 +180,7 @@ public: m_flatShading(true), m_use_mono_color(use_mono_color), m_inverse_normal(inverse_normal), + m_wireframe(draw_wireframe), m_size_points(7.), m_size_edges(3.1), m_size_lines(3.1), @@ -896,6 +898,7 @@ protected: setKeyDescription(::Qt::Key_E, "Toggles edges display"); setKeyDescription(::Qt::Key_R, "Toggles rays display"); setKeyDescription(::Qt::Key_F, "Toggles faces display"); + setKeyDescription(::Qt::Key_W, "Toggles Wireframe Polygon Mode"); setKeyDescription(::Qt::Key_G, "Switch between flat/Gouraud shading display"); setKeyDescription(::Qt::Key_M, "Toggles mono color"); setKeyDescription(::Qt::Key_N, "Inverse direction of normals"); @@ -957,7 +960,18 @@ protected: displayMessage(QString("Draw edges=%1.").arg(m_draw_edges?"true":"false")); update(); } - if ((e->key()==::Qt::Key_R) && (modifiers==::Qt::NoButton)) + else if ((e->key()==::Qt::Key_W) && (modifiers==::Qt::NoButton)) + { + m_wireframe=!m_wireframe; + if(m_wireframe){ + glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); + } else { + glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); + } + displayMessage(QString("Wireframe=%1.").arg(m_wireframe?"true":"false")); + update(); + } + else if ((e->key()==::Qt::Key_R) && (modifiers==::Qt::NoButton)) { m_draw_lines=!m_draw_lines; displayMessage(QString("Draw rays=%1.").arg(m_draw_lines?"true":"false")); @@ -1140,6 +1154,7 @@ protected: bool m_flatShading; bool m_use_mono_color; bool m_inverse_normal; + bool m_wireframe; double m_size_points; double m_size_edges; diff --git a/Voronoi_diagram_2/examples/Voronoi_diagram_2/CMakeLists.txt b/Voronoi_diagram_2/examples/Voronoi_diagram_2/CMakeLists.txt index ce38b689dc8..d1df68cdc52 100644 --- a/Voronoi_diagram_2/examples/Voronoi_diagram_2/CMakeLists.txt +++ b/Voronoi_diagram_2/examples/Voronoi_diagram_2/CMakeLists.txt @@ -18,13 +18,14 @@ if ( CGAL_FOUND ) file(GLOB cppfiles RELATIVE ${CMAKE_CURRENT_SOURCE_DIR} ${CMAKE_CURRENT_SOURCE_DIR}/*.cpp) foreach(cppfile ${cppfiles}) create_single_source_cgal_program( "${cppfile}" ) - - if(CGAL_Qt5_FOUND ) - target_link_libraries(vd_2_point_location PUBLIC CGAL::CGAL_Qt5) - endif() - endforeach() + if(CGAL_Qt5_FOUND ) + target_link_libraries(vd_2_point_location PUBLIC CGAL::CGAL_Qt5) + target_link_libraries(vd_2_point_location_sdg_linf PUBLIC CGAL::CGAL_Qt5) + endif() + + else() message(STATUS "This program requires the CGAL library, and will not be compiled.") diff --git a/Voronoi_diagram_2/include/CGAL/draw_voronoi_diagram_2.h b/Voronoi_diagram_2/include/CGAL/draw_voronoi_diagram_2.h index 0dcf8a5b35b..43b544d3a1d 100644 --- a/Voronoi_diagram_2/include/CGAL/draw_voronoi_diagram_2.h +++ b/Voronoi_diagram_2/include/CGAL/draw_voronoi_diagram_2.h @@ -1,4 +1,4 @@ -// Copyright(c) 2018 INRIA Sophia-Antipolis (France). +// Copyright(c) 2019 INRIA Sophia-Antipolis (France). // All rights reserved. // // This file is part of CGAL (www.cgal.org). @@ -26,7 +26,6 @@ #ifdef CGAL_USE_BASIC_VIEWER -#include #include #include #include @@ -62,6 +61,7 @@ class SimpleVoronoiDiagram2ViewerQt : public Basic_viewer_qt { typedef CGAL_VORONOI_DIAGRAM_2_INS::Handle_adaptor Face_handle; typedef CGAL_VORONOI_DIAGRAM_2_INS::Vertex Vertex; typedef CGAL_VORONOI_DIAGRAM_2_INS::Handle_adaptor Vertex_handle; + typedef typename V2::Halfedge_handle Halfedge_handle; typedef Triangulation_cw_ccw_2 CW_CCW_2; public: @@ -90,16 +90,25 @@ protected: Ccb_halfedge_circulator ec = ec_start; do{ - if( ec->has_source() ) + if( ec->has_source() ){ add_point_in_face(ec->source()->point()); - else if(ec->has_target()) - add_point_in_face(ec->target()->point()); + } + else{ + add_point_in_face(get_second_point(ec->twin())); + } } while(++ec != ec_start); +// if(ec == ec_start){ +// if(ec->has_target()){ +// add_point_in_face(ec->target()->point()); +// } else { +// add_point_in_face(get_second_point(ec->twin())); +// } +// } face_end(); } - void compute_ray_points(Halfedge_const_handle he) { + void compute_ray_points(Halfedge_handle he) { if (he->is_segment()) { add_segment(he->source()->point(), he->target()->point()); } else if (he->is_ray()) { @@ -117,18 +126,67 @@ protected: } } + Local_kernel::Point_2 get_second_point(Halfedge_handle ray){ + Delaunay_vertex_const_handle v1 = ray->up(); + Delaunay_vertex_const_handle v2 = ray->down(); + + // calculate direction of ray and its inverse + Kernel::Vector_2 v(v1->point().y() - v2->point().y(), + v2->point().x() - v1->point().x()); + Local_kernel::Vector_2 inv(1 / v.x(), 1 / v.y()); + + // origin of the ray + Kernel::Point_2 p; + if(ray->has_source()){ + p = ray->source()->point(); + }else{ + p = ray->target()->point(); + } + + // get the bounding box of the viewer + Local_kernel::Vector_2 boundsMin(m_bounding_box.xmin(), + m_bounding_box.zmin()); + Local_kernel::Vector_2 boundsMax(m_bounding_box.xmax(), + m_bounding_box.zmax()); + // calculate intersection + double txmax, txmin, tymax, tymin; + + if (inv.x() >= 0) { + txmax = (boundsMax.x() - p.x()) * inv.x(); + txmin = (boundsMin.x() - p.x()) * inv.x(); + } else { + txmax = (boundsMin.x() - p.x()) * inv.x(); + txmin = (boundsMax.x() - p.x()) * inv.x(); + } + + if (inv.y() >= 0) { + tymax = (boundsMax.y() - p.y()) * inv.y(); + tymin = (boundsMin.y() - p.y()) * inv.y(); + } else { + tymax = (boundsMin.y() - p.y()) * inv.y(); + tymin = (boundsMax.y() - p.y()) * inv.y(); + } + + if (tymin > txmin) + txmin = tymin; + if (tymax < txmax) + txmax = tymax; + + Local_kernel::Point_2 p1; + if (v.x() == 0) { + p1 = Local_kernel::Point_2(p.x(), p.y() + tymax * v.y()); + } else if (v.y() == 0) { + p1 = Local_kernel::Point_2(p.x() + txmax * v.x(), p.y()); + } else { + p1 = Local_kernel::Point_2(p.x() + txmax * v.x(), p.y() + tymax * v.y()); + } + return p1; + } + void compute_rays(Halfedge_const_handle he) { if (he->is_ray()) { - Delaunay_vertex_const_handle v1 = he->up(); - Delaunay_vertex_const_handle v2 = he->down(); - - Kernel::Vector_2 direction(v1->point().y() - v2->point().y(), - v2->point().x() - v1->point().x()); - Kernel::Point_2 end_point; if (he->has_source()) { - end_point = he->source()->point(); - std::cout << "Bounding_box" << m_bounding_box << std::endl; - add_ray_segment(end_point, direction); + add_segment(he->source()->point(), get_second_point(he)); } } } @@ -138,6 +196,21 @@ protected: void compute_elements() { clear(); + for (typename V2::Vertex_iterator it = v2.vertices_begin(); + it != v2.vertices_end(); ++it) { + compute_vertex(it); + } + + for (typename V2::Halfedge_iterator it = v2.halfedges_begin(); + it != v2.halfedges_end(); ++it) { + compute_ray_points(it); + } + + for (typename V2::Halfedge_iterator it = v2.halfedges_begin(); + it != v2.halfedges_end(); ++it) { + compute_rays(it); + } + if (!m_nofaces) { for (typename V2::Face_iterator it = v2.faces_begin(); it != v2.faces_end(); ++it) { @@ -148,21 +221,6 @@ protected: // v2.dual().finite_vertices_begin(); // it!=v2.dual().finite_vertices_end(); ++it) // { compute_vertex(it);} - - for (typename V2::Halfedge_iterator it = v2.halfedges_begin(); - it != v2.halfedges_end(); ++it) { - compute_ray_points(it); - } - - for (typename V2::Halfedge_iterator it = v2.halfedges_begin(); - it != v2.halfedges_end(); ++it) { - compute_rays(it); - } - - for (typename V2::Vertex_iterator it = v2.vertices_begin(); - it != v2.vertices_end(); ++it) { - compute_vertex(it); - } } virtual void keyPressEvent(QKeyEvent *e) { @@ -181,7 +239,6 @@ protected: } protected: - CGAL::Qt::Converter convert; const V2 &v2; bool m_nofaces; const ColorFunctor &m_fcolor; From cd3cfc0bc57def6400d8735603e00a963981e640 Mon Sep 17 00:00:00 2001 From: Jasmeet Singh Date: Tue, 18 Jun 2019 18:27:00 -0700 Subject: [PATCH 064/363] Remove wireframe toggle button as it is unavailable in qOpenGLFunctions --- .../include/CGAL/Qt/Basic_viewer_qt.h | 26 ++++--------------- 1 file changed, 5 insertions(+), 21 deletions(-) diff --git a/GraphicsView/include/CGAL/Qt/Basic_viewer_qt.h b/GraphicsView/include/CGAL/Qt/Basic_viewer_qt.h index b6898fc9430..5f9ece77629 100644 --- a/GraphicsView/include/CGAL/Qt/Basic_viewer_qt.h +++ b/GraphicsView/include/CGAL/Qt/Basic_viewer_qt.h @@ -170,8 +170,7 @@ public: bool draw_lines=true, bool draw_faces=true, bool use_mono_color=false, - bool inverse_normal=false, - bool draw_wireframe=false) : + bool inverse_normal=false) : CGAL::QGLViewer(parent), m_draw_vertices(draw_vertices), m_draw_edges(draw_edges), @@ -180,7 +179,6 @@ public: m_flatShading(true), m_use_mono_color(use_mono_color), m_inverse_normal(inverse_normal), - m_wireframe(draw_wireframe), m_size_points(7.), m_size_edges(3.1), m_size_lines(3.1), @@ -898,7 +896,6 @@ protected: setKeyDescription(::Qt::Key_E, "Toggles edges display"); setKeyDescription(::Qt::Key_R, "Toggles rays display"); setKeyDescription(::Qt::Key_F, "Toggles faces display"); - setKeyDescription(::Qt::Key_W, "Toggles Wireframe Polygon Mode"); setKeyDescription(::Qt::Key_G, "Switch between flat/Gouraud shading display"); setKeyDescription(::Qt::Key_M, "Toggles mono color"); setKeyDescription(::Qt::Key_N, "Inverse direction of normals"); @@ -959,23 +956,11 @@ protected: m_draw_edges=!m_draw_edges; displayMessage(QString("Draw edges=%1.").arg(m_draw_edges?"true":"false")); update(); - } - else if ((e->key()==::Qt::Key_W) && (modifiers==::Qt::NoButton)) + }else if((e->key()==::Qt::Key_R) && (modifiers==::Qt::NoButton)) { - m_wireframe=!m_wireframe; - if(m_wireframe){ - glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); - } else { - glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); - } - displayMessage(QString("Wireframe=%1.").arg(m_wireframe?"true":"false")); - update(); - } - else if ((e->key()==::Qt::Key_R) && (modifiers==::Qt::NoButton)) - { - m_draw_lines=!m_draw_lines; - displayMessage(QString("Draw rays=%1.").arg(m_draw_lines?"true":"false")); - update(); + m_draw_lines=!m_draw_lines; + displayMessage(QString("Draw rays=%1.").arg(m_draw_lines?"true":"false")); + update(); } else if ((e->key()==::Qt::Key_F) && (modifiers==::Qt::NoButton)) { @@ -1154,7 +1139,6 @@ protected: bool m_flatShading; bool m_use_mono_color; bool m_inverse_normal; - bool m_wireframe; double m_size_points; double m_size_edges; From 955a982a5f67c15c5c906b7ca590acaccb279819 Mon Sep 17 00:00:00 2001 From: Jasmeet Singh Date: Wed, 19 Jun 2019 13:43:07 -0700 Subject: [PATCH 065/363] Add an example for Voronoi diagram basic viewer. For rays: draw a really big segment without modifying bounding box. Hence, the initial screen of the viewer is correctly adjusted. For faces: drawing only bounded faces for now. The function getSecondPoint(Halfedge) can help to draw unbounded faces. Keypress R to view/unview rays. --- GraphicsView/include/CGAL/Buffer_for_vao.h | 18 ++- .../include/CGAL/Qt/Basic_viewer_qt.h | 140 +++++++----------- .../examples/Voronoi_diagram_2/CMakeLists.txt | 1 + .../Voronoi_diagram_2/data/data4.dt.cin | 10 ++ .../draw_voronoi_diagram_2.cpp | 54 +++++++ .../Voronoi_diagram_2/vd_2_point_location.cpp | 2 - .../include/CGAL/draw_voronoi_diagram_2.h | 45 +++--- 7 files changed, 157 insertions(+), 113 deletions(-) create mode 100644 Voronoi_diagram_2/examples/Voronoi_diagram_2/data/data4.dt.cin create mode 100644 Voronoi_diagram_2/examples/Voronoi_diagram_2/draw_voronoi_diagram_2.cpp diff --git a/GraphicsView/include/CGAL/Buffer_for_vao.h b/GraphicsView/include/CGAL/Buffer_for_vao.h index 8cec37ad124..1d91823126c 100644 --- a/GraphicsView/include/CGAL/Buffer_for_vao.h +++ b/GraphicsView/include/CGAL/Buffer_for_vao.h @@ -219,6 +219,16 @@ public: return m_pos_buffer->size()-3; } + template + std::size_t add_point_infinity(const KPoint& kp) + { + if (!has_position()) return (std::size_t)-1; + + Local_point p=internal::get_local_point(kp); + add_point_in_buffer(p, *m_pos_buffer); + return m_pos_buffer->size()-3; + } + // 1.2) Add a point, with color. template void add_point(const KPoint& kp, const CGAL::Color& c) @@ -252,12 +262,12 @@ public: add_color(c); } - // 2.2+) Add a line, without color. TODO: Modify comment numbering - template - void add_line(const KPoint& kp1, const KPoint& kp2) + // 2.2) Add a ray segment, without color + template + void add_ray_segment(const KPoint& kp1, const KVector& kp2) { add_point(kp1); - add_point(kp2); + add_point_infinity(kp2); } // 2.3) Add an indexed segment, without color. diff --git a/GraphicsView/include/CGAL/Qt/Basic_viewer_qt.h b/GraphicsView/include/CGAL/Qt/Basic_viewer_qt.h index 5f9ece77629..e760d372ba9 100644 --- a/GraphicsView/include/CGAL/Qt/Basic_viewer_qt.h +++ b/GraphicsView/include/CGAL/Qt/Basic_viewer_qt.h @@ -52,6 +52,7 @@ #include #include +#include #include #include @@ -167,24 +168,24 @@ public: const char* title="", bool draw_vertices=false, bool draw_edges=true, - bool draw_lines=true, + bool draw_rays=true, bool draw_faces=true, bool use_mono_color=false, bool inverse_normal=false) : CGAL::QGLViewer(parent), m_draw_vertices(draw_vertices), m_draw_edges(draw_edges), - m_draw_lines(draw_lines), + m_draw_rays(draw_rays), m_draw_faces(draw_faces), m_flatShading(true), m_use_mono_color(use_mono_color), m_inverse_normal(inverse_normal), m_size_points(7.), m_size_edges(3.1), - m_size_lines(3.1), + m_size_rays(3.1), m_vertices_mono_color(200, 60, 60), m_edges_mono_color(0, 0, 0), - m_lines_mono_color(0,100,0), + m_rays_mono_color(0, 0, 0), m_faces_mono_color(60, 60, 200), m_ambient_color(0.6f, 0.5f, 0.5f, 0.5f), m_are_buffers_initialized(false), @@ -206,14 +207,14 @@ public: &m_bounding_box, &arrays[COLOR_SEGMENTS], nullptr, nullptr), - m_buffer_for_mono_lines(&arrays[POS_MONO_LINES], + m_buffer_for_mono_rays(&arrays[POS_MONO_RAYS], NULL, &m_bounding_box, nullptr, nullptr), - m_buffer_for_colored_lines(&arrays[POS_COLORED_LINES], + m_buffer_for_colored_rays(&arrays[POS_COLORED_RAYS], NULL, &m_bounding_box, - &arrays[COLOR_LINES], + &arrays[COLOR_RAYS], nullptr, nullptr), m_buffer_for_mono_faces(&arrays[POS_MONO_FACES], nullptr, @@ -287,51 +288,14 @@ public: template void add_ray_points(const KPoint &p, const KVector &v) { m_buffer_for_mono_points.add_point(p); - m_buffer_for_mono_points.add_point(p + v); + CGAL::Bbox_2 b = (p+v).bbox(); + m_bounding_box += CGAL::Bbox_3(b.xmin(), 0, b.ymin(), b.xmax(), 0, b.ymax()); } template void add_ray_segment(const KPoint &p, const KVector &v) { - Local_kernel::Vector_2 boundsMin(m_bounding_box.xmin(), - m_bounding_box.zmin()); - Local_kernel::Vector_2 boundsMax(m_bounding_box.xmax(), - m_bounding_box.zmax()); - - Local_kernel::Vector_2 inv(1 / v.x(), 1 / v.y()); - - double txmax, txmin, tymax, tymin; - - if (inv.x() >= 0) { - txmax = (boundsMax.x() - p.x()) * inv.x(); - txmin = (boundsMin.x() - p.x()) * inv.x(); - } else { - txmax = (boundsMin.x() - p.x()) * inv.x(); - txmin = (boundsMax.x() - p.x()) * inv.x(); - } - - if (inv.y() >= 0) { - tymax = (boundsMax.y() - p.y()) * inv.y(); - tymin = (boundsMin.y() - p.y()) * inv.y(); - } else { - tymax = (boundsMin.y() - p.y()) * inv.y(); - tymin = (boundsMax.y() - p.y()) * inv.y(); - } - - if (tymin > txmin) - txmin = tymin; - if (tymax < txmax) - txmax = tymax; - - Local_kernel::Point_2 p1; - if (v.x() == 0) { - p1 = Local_kernel::Point_2(p.x(), p.y() + tymax * v.y()); - } else if (v.y() == 0) { - p1 = Local_kernel::Point_2(p.x() + txmax * v.x(), p.y()); - } else { - p1 = Local_kernel::Point_2(p.x() + txmax * v.x(), p.y() + tymax * v.y()); - } - - m_buffer_for_mono_lines.add_segment(p, p1); + float bigNumber = 1e30; + m_buffer_for_mono_rays.add_ray_segment(p, (p + (bigNumber) * v)); } bool is_a_face_started() const @@ -531,16 +495,16 @@ protected: rendering_program_p_l.release(); - // 3) LINE SHADER + // 3) RAYS SHADER - // 3.1) Mono lines - vao[VAO_MONO_LINES].bind(); + // 3.1) Mono rays + vao[VAO_MONO_RAYS].bind(); ++bufn; assert(bufn(arrays[POS_MONO_LINES].size()*sizeof(float))); + buffers[bufn].allocate(arrays[POS_MONO_RAYS].data(), + static_cast(arrays[POS_MONO_RAYS].size()*sizeof(float))); rendering_program_p_l.enableAttributeArray("vertex"); rendering_program_p_l.setAttributeArray("vertex",GL_FLOAT,0,3); @@ -548,17 +512,17 @@ protected: rendering_program_p_l.disableAttributeArray("color"); - vao[VAO_MONO_LINES].release(); + vao[VAO_MONO_RAYS].release(); - // 3.2) Color lines + // 3.2) Color rays - vao[VAO_COLORED_LINES].bind(); + vao[VAO_COLORED_RAYS].bind(); ++bufn; assert(bufn(arrays[POS_COLORED_LINES].size()*sizeof(float))); + buffers[bufn].allocate(arrays[POS_COLORED_RAYS].data(), + static_cast(arrays[POS_COLORED_RAYS].size()*sizeof(float))); rendering_program_p_l.enableAttributeArray("vertex"); rendering_program_p_l.setAttributeBuffer("vertex",GL_FLOAT,0,3); @@ -567,13 +531,13 @@ protected: ++bufn; assert(bufn(arrays[COLOR_LINES].size()*sizeof(float))); + buffers[bufn].allocate(arrays[COLOR_RAYS].data(), + static_cast(arrays[COLOR_RAYS].size()*sizeof(float))); rendering_program_p_l.enableAttributeArray("color"); rendering_program_p_l.setAttributeBuffer("color",GL_FLOAT,0,3); buffers[bufn].release(); - vao[VAO_COLORED_LINES].release(); + vao[VAO_COLORED_RAYS].release(); rendering_program_p_l.release(); @@ -812,25 +776,25 @@ protected: rendering_program_p_l.release(); } - if(m_draw_lines) + if(m_draw_rays) { rendering_program_p_l.bind(); - vao[VAO_MONO_LINES].bind(); - color.setRgbF((double)m_lines_mono_color.red()/(double)255, - (double)m_lines_mono_color.green()/(double)255, - (double)m_lines_mono_color.blue()/(double)255); + vao[VAO_MONO_RAYS].bind(); + color.setRgbF((double)m_rays_mono_color.red()/(double)255, + (double)m_rays_mono_color.green()/(double)255, + (double)m_rays_mono_color.blue()/(double)255); rendering_program_p_l.setAttributeValue("color",color); - glLineWidth(m_size_lines); - glDrawArrays(GL_LINES, 0, static_cast(arrays[POS_MONO_LINES].size()/3)); - vao[VAO_MONO_LINES].release(); + glLineWidth(m_size_rays); + glDrawArrays(GL_LINES, 0, static_cast(arrays[POS_MONO_RAYS].size()/3)); + vao[VAO_MONO_RAYS].release(); - vao[VAO_COLORED_LINES].bind(); + vao[VAO_COLORED_RAYS].bind(); if (m_use_mono_color) { - color.setRgbF((double)m_lines_mono_color.red()/(double)255, - (double)m_lines_mono_color.green()/(double)255, - (double)m_lines_mono_color.blue()/(double)255); + color.setRgbF((double)m_rays_mono_color.red()/(double)255, + (double)m_rays_mono_color.green()/(double)255, + (double)m_rays_mono_color.blue()/(double)255); rendering_program_p_l.disableAttributeArray("color"); rendering_program_p_l.setAttributeValue("color",color); } @@ -838,9 +802,9 @@ protected: { rendering_program_p_l.enableAttributeArray("color"); } - glLineWidth(m_size_lines); - glDrawArrays(GL_LINES, 0, static_cast(arrays[POS_COLORED_LINES].size()/3)); - vao[VAO_COLORED_LINES].release(); + glLineWidth(m_size_rays); + glDrawArrays(GL_LINES, 0, static_cast(arrays[POS_COLORED_RAYS].size()/3)); + vao[VAO_COLORED_RAYS].release(); rendering_program_p_l.release(); } @@ -958,8 +922,8 @@ protected: update(); }else if((e->key()==::Qt::Key_R) && (modifiers==::Qt::NoButton)) { - m_draw_lines=!m_draw_lines; - displayMessage(QString("Draw rays=%1.").arg(m_draw_lines?"true":"false")); + m_draw_rays=!m_draw_rays; + displayMessage(QString("Draw rays=%1.").arg(m_draw_rays?"true":"false")); update(); } else if ((e->key()==::Qt::Key_F) && (modifiers==::Qt::NoButton)) @@ -1134,7 +1098,7 @@ protected: protected: bool m_draw_vertices; bool m_draw_edges; - bool m_draw_lines; + bool m_draw_rays; bool m_draw_faces; bool m_flatShading; bool m_use_mono_color; @@ -1142,11 +1106,11 @@ protected: double m_size_points; double m_size_edges; - double m_size_lines; + double m_size_rays; CGAL::Color m_vertices_mono_color; CGAL::Color m_edges_mono_color; - CGAL::Color m_lines_mono_color; + CGAL::Color m_rays_mono_color; CGAL::Color m_faces_mono_color; QVector4D m_ambient_color; @@ -1161,15 +1125,15 @@ protected: POS_COLORED_POINTS, POS_MONO_SEGMENTS, POS_COLORED_SEGMENTS, - POS_MONO_LINES, - POS_COLORED_LINES, + POS_MONO_RAYS, + POS_COLORED_RAYS, POS_MONO_FACES, POS_COLORED_FACES, END_POS, BEGIN_COLOR=END_POS, COLOR_POINTS=BEGIN_COLOR, COLOR_SEGMENTS, - COLOR_LINES, + COLOR_RAYS, COLOR_FACES, END_COLOR, BEGIN_NORMAL=END_COLOR, @@ -1186,8 +1150,8 @@ protected: Buffer_for_vao m_buffer_for_colored_points; Buffer_for_vao m_buffer_for_mono_segments; Buffer_for_vao m_buffer_for_colored_segments; - Buffer_for_vao m_buffer_for_mono_lines; - Buffer_for_vao m_buffer_for_colored_lines; + Buffer_for_vao m_buffer_for_mono_rays; + Buffer_for_vao m_buffer_for_colored_rays; Buffer_for_vao m_buffer_for_mono_faces; Buffer_for_vao m_buffer_for_colored_faces; @@ -1202,8 +1166,8 @@ protected: VAO_COLORED_POINTS, VAO_MONO_SEGMENTS, VAO_COLORED_SEGMENTS, - VAO_MONO_LINES, - VAO_COLORED_LINES, + VAO_MONO_RAYS, + VAO_COLORED_RAYS, VAO_MONO_FACES, VAO_COLORED_FACES, NB_VAO_BUFFERS diff --git a/Voronoi_diagram_2/examples/Voronoi_diagram_2/CMakeLists.txt b/Voronoi_diagram_2/examples/Voronoi_diagram_2/CMakeLists.txt index d1df68cdc52..ef2705d980c 100644 --- a/Voronoi_diagram_2/examples/Voronoi_diagram_2/CMakeLists.txt +++ b/Voronoi_diagram_2/examples/Voronoi_diagram_2/CMakeLists.txt @@ -23,6 +23,7 @@ if ( CGAL_FOUND ) if(CGAL_Qt5_FOUND ) target_link_libraries(vd_2_point_location PUBLIC CGAL::CGAL_Qt5) target_link_libraries(vd_2_point_location_sdg_linf PUBLIC CGAL::CGAL_Qt5) + target_link_libraries(draw_voronoi_diagram_2 PUBLIC CGAL::CGAL_Qt5) endif() diff --git a/Voronoi_diagram_2/examples/Voronoi_diagram_2/data/data4.dt.cin b/Voronoi_diagram_2/examples/Voronoi_diagram_2/data/data4.dt.cin new file mode 100644 index 00000000000..4f0d7b4565e --- /dev/null +++ b/Voronoi_diagram_2/examples/Voronoi_diagram_2/data/data4.dt.cin @@ -0,0 +1,10 @@ +0 0 +100 0 +100 100 +0 100 +200 0 +300 0 +350 0 +150 150 +100 150 +300 325 diff --git a/Voronoi_diagram_2/examples/Voronoi_diagram_2/draw_voronoi_diagram_2.cpp b/Voronoi_diagram_2/examples/Voronoi_diagram_2/draw_voronoi_diagram_2.cpp new file mode 100644 index 00000000000..6c540a6a5a1 --- /dev/null +++ b/Voronoi_diagram_2/examples/Voronoi_diagram_2/draw_voronoi_diagram_2.cpp @@ -0,0 +1,54 @@ +// Copyright(c) 2019 Foundation for Research and Technology-Hellas (Greece). +// 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) : Jasmeet Singh + +#include +#include +#include +#include +#include +#include +#include + +// typedefs for defining the adaptor +typedef CGAL::Exact_predicates_inexact_constructions_kernel K; +typedef CGAL::Delaunay_triangulation_2 DT; +typedef CGAL::Delaunay_triangulation_adaptation_traits_2
    AT; +typedef CGAL::Delaunay_triangulation_caching_degeneracy_removal_policy_2
    AP; +typedef CGAL::Voronoi_diagram_2 VD; + +// typedef for the result type of the point location +typedef AT::Site_2 Site_2; + +int main() +{ + VD vd; + std::ifstream ifs("data/data4.dt.cin"); + assert(ifs); + + Site_2 t; + while ( ifs >> t ) { vd.insert(t); } + ifs.close(); + + assert( vd.is_valid() ); + + CGAL::draw(vd); + + return EXIT_SUCCESS; +} diff --git a/Voronoi_diagram_2/examples/Voronoi_diagram_2/vd_2_point_location.cpp b/Voronoi_diagram_2/examples/Voronoi_diagram_2/vd_2_point_location.cpp index 6b2169eee9d..025a6b7869e 100644 --- a/Voronoi_diagram_2/examples/Voronoi_diagram_2/vd_2_point_location.cpp +++ b/Voronoi_diagram_2/examples/Voronoi_diagram_2/vd_2_point_location.cpp @@ -87,7 +87,5 @@ int main() } ifq.close(); - CGAL::draw(vd); - return 0; } diff --git a/Voronoi_diagram_2/include/CGAL/draw_voronoi_diagram_2.h b/Voronoi_diagram_2/include/CGAL/draw_voronoi_diagram_2.h index 43b544d3a1d..adc11b8a0bc 100644 --- a/Voronoi_diagram_2/include/CGAL/draw_voronoi_diagram_2.h +++ b/Voronoi_diagram_2/include/CGAL/draw_voronoi_diagram_2.h @@ -1,4 +1,4 @@ -// Copyright(c) 2019 INRIA Sophia-Antipolis (France). +// Copyright(c) 2019 Foundation for Research and Technology-Hellas (Greece). // All rights reserved. // // This file is part of CGAL (www.cgal.org). @@ -85,27 +85,28 @@ public: protected: void compute_face(Face_const_handle fh) { CGAL::Color c=m_fcolor.run(v2, fh); - face_begin(c); + Ccb_halfedge_circulator ec_start = fh->ccb(); Ccb_halfedge_circulator ec = ec_start; - do{ - if( ec->has_source() ){ + if(!fh->is_unbounded()){ + face_begin(c); + do{ add_point_in_face(ec->source()->point()); - } - else{ - add_point_in_face(get_second_point(ec->twin())); - } - } while(++ec != ec_start); - -// if(ec == ec_start){ -// if(ec->has_target()){ -// add_point_in_face(ec->target()->point()); -// } else { -// add_point_in_face(get_second_point(ec->twin())); -// } -// } - face_end(); + }while(++ec != ec_start); + face_end(); + } + // Test: for unbounded faces + // else { + // do{ + // if( ec->has_source() ){ + // add_point_in_face(ec->source()->point()); + // } + // else{ + // add_point_in_face(get_second_point(ec->twin())); + // } + // } while(++ec != ec_start); + // } } void compute_ray_points(Halfedge_handle he) { @@ -186,7 +187,13 @@ protected: void compute_rays(Halfedge_const_handle he) { if (he->is_ray()) { if (he->has_source()) { - add_segment(he->source()->point(), get_second_point(he)); + Delaunay_vertex_const_handle v1 = he->up(); + Delaunay_vertex_const_handle v2 = he->down(); + + Kernel::Vector_2 direction(v1->point().y() - v2->point().y(), + v2->point().x() - v1->point().x()); + //add_ray_segment(he->source()->point(), get_second_point(he)); + add_ray_segment(he->source()->point(), direction); } } } From 43015b0059a36018b1959d50f75a37b2812d5872 Mon Sep 17 00:00:00 2001 From: Jasmeet Singh Date: Wed, 19 Jun 2019 14:24:40 -0700 Subject: [PATCH 066/363] Add special KeyPressEvent for rays. Format typedefs. Set cgal_test_suit = qEnvironmentVariableIsSet("CGAL_TEST_SUITE") Adding these changes after learning from the viewers generated by GDamiand. --- .../include/CGAL/Qt/Basic_viewer_qt.h | 9 +-- .../include/CGAL/draw_voronoi_diagram_2.h | 70 ++++++++++--------- 2 files changed, 38 insertions(+), 41 deletions(-) diff --git a/GraphicsView/include/CGAL/Qt/Basic_viewer_qt.h b/GraphicsView/include/CGAL/Qt/Basic_viewer_qt.h index e760d372ba9..78319fa51fe 100644 --- a/GraphicsView/include/CGAL/Qt/Basic_viewer_qt.h +++ b/GraphicsView/include/CGAL/Qt/Basic_viewer_qt.h @@ -858,7 +858,6 @@ protected: // Add custom key description (see keyPressEvent). setKeyDescription(::Qt::Key_E, "Toggles edges display"); - setKeyDescription(::Qt::Key_R, "Toggles rays display"); setKeyDescription(::Qt::Key_F, "Toggles faces display"); setKeyDescription(::Qt::Key_G, "Switch between flat/Gouraud shading display"); setKeyDescription(::Qt::Key_M, "Toggles mono color"); @@ -920,13 +919,7 @@ protected: m_draw_edges=!m_draw_edges; displayMessage(QString("Draw edges=%1.").arg(m_draw_edges?"true":"false")); update(); - }else if((e->key()==::Qt::Key_R) && (modifiers==::Qt::NoButton)) - { - m_draw_rays=!m_draw_rays; - displayMessage(QString("Draw rays=%1.").arg(m_draw_rays?"true":"false")); - update(); - } - else if ((e->key()==::Qt::Key_F) && (modifiers==::Qt::NoButton)) + }else if ((e->key()==::Qt::Key_F) && (modifiers==::Qt::NoButton)) { m_draw_faces=!m_draw_faces; displayMessage(QString("Draw faces=%1.").arg(m_draw_faces?"true":"false")); diff --git a/Voronoi_diagram_2/include/CGAL/draw_voronoi_diagram_2.h b/Voronoi_diagram_2/include/CGAL/draw_voronoi_diagram_2.h index adc11b8a0bc..28f744afc8d 100644 --- a/Voronoi_diagram_2/include/CGAL/draw_voronoi_diagram_2.h +++ b/Voronoi_diagram_2/include/CGAL/draw_voronoi_diagram_2.h @@ -47,30 +47,29 @@ struct DefaultColorFunctorV2 { // Viewer for Voronoi diagram template class SimpleVoronoiDiagram2ViewerQt : public Basic_viewer_qt { - typedef Basic_viewer_qt Base; - typedef typename V2::Halfedge_iterator Halfedge_const_handle; - typedef typename V2::Face_iterator Face_const_handle; - typedef typename V2::Vertex_iterator Vertex_const_handle; - typedef typename V2::Point_2 Point; - typedef typename V2::Delaunay_vertex_handle Delaunay_vertex_const_handle; - typedef typename V2::Ccb_halfedge_circulator Ccb_halfedge_circulator; - typedef typename V2::Delaunay_geom_traits Delaunay_geom_traits; + typedef Basic_viewer_qt Base; + typedef typename V2::Halfedge_iterator Halfedge_const_handle; + typedef typename V2::Face_iterator Face_const_handle; + typedef typename V2::Vertex_iterator Vertex_const_handle; + typedef typename V2::Point_2 Point; + typedef typename V2::Delaunay_vertex_handle Delaunay_vertex_const_handle; + typedef typename V2::Ccb_halfedge_circulator Ccb_halfedge_circulator; + typedef typename V2::Delaunay_geom_traits Delaunay_geom_traits; - typedef CGAL::Exact_predicates_inexact_constructions_kernel Kernel; - typedef CGAL_VORONOI_DIAGRAM_2_INS::Face Face; - typedef CGAL_VORONOI_DIAGRAM_2_INS::Handle_adaptor Face_handle; - typedef CGAL_VORONOI_DIAGRAM_2_INS::Vertex Vertex; - typedef CGAL_VORONOI_DIAGRAM_2_INS::Handle_adaptor Vertex_handle; - typedef typename V2::Halfedge_handle Halfedge_handle; - typedef Triangulation_cw_ccw_2 CW_CCW_2; + typedef CGAL::Exact_predicates_inexact_constructions_kernel Kernel; + typedef CGAL_VORONOI_DIAGRAM_2_INS::Face Face; + typedef CGAL_VORONOI_DIAGRAM_2_INS::Handle_adaptor Face_handle; + typedef CGAL_VORONOI_DIAGRAM_2_INS::Vertex Vertex; + typedef CGAL_VORONOI_DIAGRAM_2_INS::Handle_adaptor Vertex_handle; + typedef typename V2::Halfedge_handle Halfedge_handle; + typedef Triangulation_cw_ccw_2 CW_CCW_2; public: /// Construct the viewer. /// @param av2 the voronoi diagram to view /// @param title the title of the window /// @param anofaces if true, do not draw faces (faces are not computed; this - /// can be - /// useful for very big object where this time could be long) + /// can be useful for very big object where this time could be long) SimpleVoronoiDiagram2ViewerQt(QWidget *parent, const V2 &av2, const char *title = "Basic Voronoi Viewer", bool anofaces = false, @@ -78,7 +77,11 @@ public: : // First draw: vertices; half-edges; faces; multi-color; no inverse // normal Base(parent, title, true, true, true, false, false), v2(av2), - m_nofaces(anofaces), m_fcolor(fcolor) { + m_nofaces(anofaces), m_fcolor(fcolor) + { + // Add custom key description (see keyPressEvent) + setKeyDescription(::Qt::Key_R, "Toggles rays display"); + compute_elements(); } @@ -230,21 +233,22 @@ protected: // { compute_vertex(it);} } - virtual void keyPressEvent(QKeyEvent *e) { - // Test key pressed: - // const ::Qt::KeyboardModifiers modifiers = e->modifiers(); - // if ((e->key()==Qt::Key_PageUp) && (modifiers==Qt::NoButton)) { ... } - - // Call: * compute_elements() if the model changed, followed by - // * redraw() if some viewing parameters changed that implies some - // modifications of the buffers - // (eg. type of normal, color/mono) - // * update() just to update the drawing - - // Call the base method to process others/classicals key - Base::keyPressEvent(e); + virtual void keyPressEvent(QKeyEvent *e) + { + /// [Keypress] + const ::Qt::KeyboardModifiers modifiers = e->modifiers(); + if((e->key()==::Qt::Key_R) && (modifiers==::Qt::NoButton)) + { + m_draw_rays=!m_draw_rays; + displayMessage(QString("Draw rays=%1.").arg(m_draw_rays?"true":"false")); + update(); + } + else { + // Call the base method to process others/classicals key + Base::keyPressEvent(e); + } + /// [Keypress] } - protected: const V2 &v2; bool m_nofaces; @@ -257,7 +261,7 @@ void draw(const V2 &av2, const char *title, bool nofill, #if defined(CGAL_TEST_SUITE) bool cgal_test_suite = true; #else - bool cgal_test_suite = false; + bool cgal_test_suite = qEnvironmentVariableIsSet("CGAL_TEST_SUITE"); #endif if (!cgal_test_suite) { From 001fda493be1aeb76cfc628f4bd0497009e947cb Mon Sep 17 00:00:00 2001 From: Jasmeet Singh Date: Wed, 19 Jun 2019 16:30:56 -0700 Subject: [PATCH 067/363] Add documentation for voronoi diagram viewer. --- .../CGAL/draw_voronoi_diagram.h | 17 +++++++++++++ .../Voronoi_diagram_2/PackageDescription.txt | 12 +++++++++ .../Voronoi_diagram_2/Voronoi_diagram_2.txt | 14 +++++++++++ .../doc/Voronoi_diagram_2/examples.txt | 1 + .../fig/draw_voronoi_diagram.png | Bin 0 -> 12217 bytes .../draw_voronoi_diagram_2.cpp | 23 +++--------------- 6 files changed, 47 insertions(+), 20 deletions(-) create mode 100644 Voronoi_diagram_2/doc/Voronoi_diagram_2/CGAL/draw_voronoi_diagram.h create mode 100644 Voronoi_diagram_2/doc/Voronoi_diagram_2/fig/draw_voronoi_diagram.png diff --git a/Voronoi_diagram_2/doc/Voronoi_diagram_2/CGAL/draw_voronoi_diagram.h b/Voronoi_diagram_2/doc/Voronoi_diagram_2/CGAL/draw_voronoi_diagram.h new file mode 100644 index 00000000000..de954014d51 --- /dev/null +++ b/Voronoi_diagram_2/doc/Voronoi_diagram_2/CGAL/draw_voronoi_diagram.h @@ -0,0 +1,17 @@ +namespace CGAL { + +/*! +\ingroup PkgDrawVoronoiDiagram2 + +Open a new window and draw `av2`, the `Voronoi_diagram_2` constructed from a Delaunay Graph which is a model of `DelaunayGraph_2` concept. +The class `Voronoi_diagram_2` provides an adaptor to view a triangulated Delaunay graph as their dual subdivision, the +Voronoi diagram. The 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 V2 a model of the `Voronoi2` concept. +\param av2 the voronoi diagram to draw. + +*/ +template +void draw(const V2& av2); + +} /* namespace CGAL */ \ No newline at end of file diff --git a/Voronoi_diagram_2/doc/Voronoi_diagram_2/PackageDescription.txt b/Voronoi_diagram_2/doc/Voronoi_diagram_2/PackageDescription.txt index 379a9b01b4e..a173d3af29b 100644 --- a/Voronoi_diagram_2/doc/Voronoi_diagram_2/PackageDescription.txt +++ b/Voronoi_diagram_2/doc/Voronoi_diagram_2/PackageDescription.txt @@ -12,6 +12,14 @@ /// \defgroup PkgVoronoiDiagram2Disks Voronoi Diagram of Disks /// \ingroup PkgVoronoiDiagram2Ref +/*! + \code + #include + \endcode +*/ +/// \defgroup PkgDrawVoronoiDiagram2 Draw a 2D Voronoi Diagram +/// \ingroup PkgVoronoiDiagram2Ref + /*! \addtogroup PkgVoronoiDiagram2Ref \todo check generated documentation @@ -81,5 +89,9 @@ performing this adaptation. - `CGAL::Segment_Delaunay_graph_degeneracy_removal_policy_2` - `CGAL::Segment_Delaunay_graph_caching_degeneracy_removal_policy_2` +\cgalCRPSection{Draw Voronoi Diagram} + +- \link PkgDrawVoronoiDiagram2 CGAL::draw() \endlink + */ diff --git a/Voronoi_diagram_2/doc/Voronoi_diagram_2/Voronoi_diagram_2.txt b/Voronoi_diagram_2/doc/Voronoi_diagram_2/Voronoi_diagram_2.txt index 163719da3aa..e9fe5e9164e 100644 --- a/Voronoi_diagram_2/doc/Voronoi_diagram_2/Voronoi_diagram_2.txt +++ b/Voronoi_diagram_2/doc/Voronoi_diagram_2/Voronoi_diagram_2.txt @@ -488,6 +488,20 @@ location queries. \cgalExample{Voronoi_diagram_2/vd_2_point_location.cpp} +\section secvda2drawvoronoi Draw a Voronoi Diagram + +A 2D Voronoi Diagram can be visualized by calling the \link PkgDrawVoronoiDiagram2 CGAL::draw() \endlink function as +shown in the following example. This function opens a new window showing the Voronoi Diagram of the given input sites/vertix locations. 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. + +\cgalExample{Voronoi_diagram_2/draw_voronoi_diagram_2.cpp} + +\cgalFigureBegin{draw_voronoi_diagram, draw_voronoi_diagram.png} +Result of the draw_voronoi_diagram_2 program. A window shows the Voronoi vertices and edges. +The window allows navigation through the 3D scene. +\cgalFigureEnd + */ } /* namespace CGAL */ diff --git a/Voronoi_diagram_2/doc/Voronoi_diagram_2/examples.txt b/Voronoi_diagram_2/doc/Voronoi_diagram_2/examples.txt index 059a4823bc2..2c2e063da4c 100644 --- a/Voronoi_diagram_2/doc/Voronoi_diagram_2/examples.txt +++ b/Voronoi_diagram_2/doc/Voronoi_diagram_2/examples.txt @@ -1,4 +1,5 @@ /*! \example Voronoi_diagram_2/vd_2_point_location.cpp \example Voronoi_diagram_2/vd_2_point_location_sdg_linf.cpp +\example Voronoi_diagram_2/draw_voronoi_diagram_2.cpp */ diff --git a/Voronoi_diagram_2/doc/Voronoi_diagram_2/fig/draw_voronoi_diagram.png b/Voronoi_diagram_2/doc/Voronoi_diagram_2/fig/draw_voronoi_diagram.png new file mode 100644 index 0000000000000000000000000000000000000000..a16496273be237725e3eac9b3da0b174e19b0774 GIT binary patch literal 12217 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 literal 0 HcmV?d00001 diff --git a/Voronoi_diagram_2/examples/Voronoi_diagram_2/draw_voronoi_diagram_2.cpp b/Voronoi_diagram_2/examples/Voronoi_diagram_2/draw_voronoi_diagram_2.cpp index 6c540a6a5a1..faa24a70034 100644 --- a/Voronoi_diagram_2/examples/Voronoi_diagram_2/draw_voronoi_diagram_2.cpp +++ b/Voronoi_diagram_2/examples/Voronoi_diagram_2/draw_voronoi_diagram_2.cpp @@ -1,30 +1,13 @@ -// Copyright(c) 2019 Foundation for Research and Technology-Hellas (Greece). -// 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) : Jasmeet Singh +// standard includes +#include +// includes for drawing the Voronoi Diagram #include #include #include #include #include #include -#include // typedefs for defining the adaptor typedef CGAL::Exact_predicates_inexact_constructions_kernel K; From ce1b306d004ac28b1640e841a9d695aefdbac012 Mon Sep 17 00:00:00 2001 From: Jasmeet Singh Date: Wed, 19 Jun 2019 19:49:09 -0700 Subject: [PATCH 068/363] Add m_buffer_for_mono_lines and m_buffer_for_colored_lines to view lines. Trying to visualize bisectors. Formatting changes. --- GraphicsView/include/CGAL/Buffer_for_vao.h | 12 +- .../include/CGAL/Qt/Basic_viewer_qt.h | 153 ++++++++++++++++-- .../include/CGAL/draw_voronoi_diagram_2.h | 68 ++++---- 3 files changed, 184 insertions(+), 49 deletions(-) diff --git a/GraphicsView/include/CGAL/Buffer_for_vao.h b/GraphicsView/include/CGAL/Buffer_for_vao.h index 1d91823126c..0ca294aa892 100644 --- a/GraphicsView/include/CGAL/Buffer_for_vao.h +++ b/GraphicsView/include/CGAL/Buffer_for_vao.h @@ -266,8 +266,16 @@ public: template void add_ray_segment(const KPoint& kp1, const KVector& kp2) { - add_point(kp1); - add_point_infinity(kp2); + add_point(kp1); + add_point_infinity(kp2); + } + + // 2.2) Add a line + template + void add_line_segment(const KPoint& kp1, const KPoint& kp2) + { + add_point_infinity(kp1); + add_point_infinity(kp2); } // 2.3) Add an indexed segment, without color. diff --git a/GraphicsView/include/CGAL/Qt/Basic_viewer_qt.h b/GraphicsView/include/CGAL/Qt/Basic_viewer_qt.h index 78319fa51fe..7cd6853d67f 100644 --- a/GraphicsView/include/CGAL/Qt/Basic_viewer_qt.h +++ b/GraphicsView/include/CGAL/Qt/Basic_viewer_qt.h @@ -169,6 +169,7 @@ public: bool draw_vertices=false, bool draw_edges=true, bool draw_rays=true, + bool draw_lines=true, bool draw_faces=true, bool use_mono_color=false, bool inverse_normal=false) : @@ -176,6 +177,7 @@ public: m_draw_vertices(draw_vertices), m_draw_edges(draw_edges), m_draw_rays(draw_rays), + m_draw_lines(draw_lines), m_draw_faces(draw_faces), m_flatShading(true), m_use_mono_color(use_mono_color), @@ -183,9 +185,11 @@ public: m_size_points(7.), m_size_edges(3.1), m_size_rays(3.1), + m_size_lines(3.1), m_vertices_mono_color(200, 60, 60), m_edges_mono_color(0, 0, 0), m_rays_mono_color(0, 0, 0), + m_lines_mono_color(0, 0, 0), m_faces_mono_color(60, 60, 200), m_ambient_color(0.6f, 0.5f, 0.5f, 0.5f), m_are_buffers_initialized(false), @@ -216,6 +220,15 @@ public: &m_bounding_box, &arrays[COLOR_RAYS], nullptr, nullptr), + m_buffer_for_mono_lines(&arrays[POS_MONO_RAYS], + NULL, + &m_bounding_box, + nullptr, nullptr), + m_buffer_for_colored_lines(&arrays[POS_COLORED_LINES], + NULL, + &m_bounding_box, + &arrays[COLOR_LINES], + nullptr, nullptr), m_buffer_for_mono_faces(&arrays[POS_MONO_FACES], nullptr, &m_bounding_box, @@ -286,18 +299,38 @@ public: template - void add_ray_points(const KPoint &p, const KVector &v) { - m_buffer_for_mono_points.add_point(p); - CGAL::Bbox_2 b = (p+v).bbox(); - m_bounding_box += CGAL::Bbox_3(b.xmin(), 0, b.ymin(), b.xmax(), 0, b.ymax()); + void update_bounding_box_for_ray(const KPoint &p, const KVector &v) { + //m_buffer_for_mono_points.add_point(p); + Local_point lp = internal::get_local_point(p); + Local_vector lv = internal::get_local_vector(v); + CGAL::Bbox_3 b = (lp+lv).bbox(); + m_bounding_box += b; + //m_bounding_box += CGAL::Bbox_3(b.xmin(), 0, b.ymin(), b.xmax(), 0, b.ymax()); } template - void add_ray_segment(const KPoint &p, const KVector &v) { + void update_bounding_box_for_line(const KPoint &p, const KVector &v, const KVector &pv) { + Local_point lp = internal::get_local_point(p); + Local_vector lv = internal::get_local_vector(v); + Local_vector lpv = internal::get_local_vector(pv); + + CGAL::Bbox_3 b = lp.bbox() + (lp+lv).bbox() + (lp+lpv).bbox(); + m_bounding_box += b; + } + + template + void add_ray(const KPoint &p, const KVector &v) { float bigNumber = 1e30; m_buffer_for_mono_rays.add_ray_segment(p, (p + (bigNumber) * v)); } + template + void add_line(const KPoint &p, const KVector &v) { + float bigNumber = 1e30; + m_buffer_for_mono_lines.add_line_segment((p - (bigNumber) * v), + (p + (bigNumber) * v)); + } + bool is_a_face_started() const { return m_buffer_for_mono_faces.is_a_face_started() || @@ -469,7 +502,7 @@ protected: vao[VAO_MONO_SEGMENTS].release(); - // 1.2) Color segments + // 2.1) Color segments vao[VAO_COLORED_SEGMENTS].bind(); ++bufn; @@ -541,13 +574,58 @@ protected: rendering_program_p_l.release(); - // 3) FACE SHADER + // 4) LINES SHADER + // 4.1) Mono lines + vao[VAO_MONO_LINES].bind(); + + ++bufn; + assert(bufn(arrays[POS_MONO_LINES].size()*sizeof(float))); + rendering_program_p_l.enableAttributeArray("vertex"); + rendering_program_p_l.setAttributeArray("vertex",GL_FLOAT,0,3); + + buffers[bufn].release(); + + rendering_program_p_l.disableAttributeArray("color"); + + vao[VAO_MONO_LINES].release(); + + // 4.2 Color lines + + vao[VAO_COLORED_LINES].bind(); + + ++bufn; + assert(bufn(arrays[POS_COLORED_LINES].size()*sizeof(float))); + rendering_program_p_l.enableAttributeArray("vertex"); + rendering_program_p_l.setAttributeBuffer("vertex",GL_FLOAT,0,3); + + buffers[bufn].release(); + + ++bufn; + assert(bufn(arrays[COLOR_LINES].size()*sizeof(float))); + rendering_program_p_l.enableAttributeArray("color"); + rendering_program_p_l.setAttributeBuffer("color",GL_FLOAT,0,3); + buffers[bufn].release(); + + vao[VAO_COLORED_LINES].release(); + + rendering_program_p_l.release(); + + // 5) FACE SHADER rendering_program_face.bind(); - // 3.1) Mono faces + // 5.1) Mono faces vao[VAO_MONO_FACES].bind(); - // 3.1.1) points of the mono faces + // 5.1.1) points of the mono faces ++bufn; assert(bufn(arrays[POS_MONO_LINES].size()/3)); + vao[VAO_MONO_LINES].release(); + + rendering_program_p_l.release(); + + vao[VAO_COLORED_LINES].bind(); + if (m_use_mono_color) + { + color.setRgbF((double)m_rays_mono_color.red()/(double)255, + (double)m_rays_mono_color.green()/(double)255, + (double)m_rays_mono_color.blue()/(double)255); + rendering_program_p_l.disableAttributeArray("color"); + rendering_program_p_l.setAttributeValue("color",color); + } + else + { + rendering_program_p_l.enableAttributeArray("color"); + } + glLineWidth(m_size_lines); + glDrawArrays(GL_LINES, 0, static_cast(arrays[POS_COLORED_LINES].size()/3)); + vao[VAO_COLORED_LINES].release(); + + rendering_program_p_l.release(); + } + if (m_draw_faces) { rendering_program_face.bind(); @@ -1092,6 +1205,7 @@ protected: bool m_draw_vertices; bool m_draw_edges; bool m_draw_rays; + bool m_draw_lines; bool m_draw_faces; bool m_flatShading; bool m_use_mono_color; @@ -1100,10 +1214,12 @@ protected: double m_size_points; double m_size_edges; double m_size_rays; + double m_size_lines; CGAL::Color m_vertices_mono_color; CGAL::Color m_edges_mono_color; CGAL::Color m_rays_mono_color; + CGAL::Color m_lines_mono_color; CGAL::Color m_faces_mono_color; QVector4D m_ambient_color; @@ -1120,6 +1236,8 @@ protected: POS_COLORED_SEGMENTS, POS_MONO_RAYS, POS_COLORED_RAYS, + POS_MONO_LINES, + POS_COLORED_LINES, POS_MONO_FACES, POS_COLORED_FACES, END_POS, @@ -1127,6 +1245,7 @@ protected: COLOR_POINTS=BEGIN_COLOR, COLOR_SEGMENTS, COLOR_RAYS, + COLOR_LINES, COLOR_FACES, END_COLOR, BEGIN_NORMAL=END_COLOR, @@ -1144,6 +1263,8 @@ protected: Buffer_for_vao m_buffer_for_mono_segments; Buffer_for_vao m_buffer_for_colored_segments; Buffer_for_vao m_buffer_for_mono_rays; + Buffer_for_vao m_buffer_for_mono_lines; + Buffer_for_vao m_buffer_for_colored_lines; Buffer_for_vao m_buffer_for_colored_rays; Buffer_for_vao m_buffer_for_mono_faces; Buffer_for_vao m_buffer_for_colored_faces; @@ -1161,6 +1282,8 @@ protected: VAO_COLORED_SEGMENTS, VAO_MONO_RAYS, VAO_COLORED_RAYS, + VAO_MONO_LINES, + VAO_COLORED_LINES, VAO_MONO_FACES, VAO_COLORED_FACES, NB_VAO_BUFFERS diff --git a/Voronoi_diagram_2/include/CGAL/draw_voronoi_diagram_2.h b/Voronoi_diagram_2/include/CGAL/draw_voronoi_diagram_2.h index 28f744afc8d..c0d0e26b18f 100644 --- a/Voronoi_diagram_2/include/CGAL/draw_voronoi_diagram_2.h +++ b/Voronoi_diagram_2/include/CGAL/draw_voronoi_diagram_2.h @@ -47,22 +47,15 @@ struct DefaultColorFunctorV2 { // Viewer for Voronoi diagram template class SimpleVoronoiDiagram2ViewerQt : public Basic_viewer_qt { - typedef Basic_viewer_qt Base; - typedef typename V2::Halfedge_iterator Halfedge_const_handle; - typedef typename V2::Face_iterator Face_const_handle; - typedef typename V2::Vertex_iterator Vertex_const_handle; - typedef typename V2::Point_2 Point; - typedef typename V2::Delaunay_vertex_handle Delaunay_vertex_const_handle; - typedef typename V2::Ccb_halfedge_circulator Ccb_halfedge_circulator; - typedef typename V2::Delaunay_geom_traits Delaunay_geom_traits; + typedef Basic_viewer_qt Base; + typedef typename V2::Halfedge_iterator Halfedge_const_handle; + typedef typename V2::Face_iterator Face_const_handle; + typedef typename V2::Vertex_iterator Vertex_const_handle; + typedef typename V2::Delaunay_vertex_handle Delaunay_vertex_const_handle; + typedef typename V2::Ccb_halfedge_circulator Ccb_halfedge_circulator; + typedef typename V2::Halfedge_handle Halfedge_handle; typedef CGAL::Exact_predicates_inexact_constructions_kernel Kernel; - typedef CGAL_VORONOI_DIAGRAM_2_INS::Face Face; - typedef CGAL_VORONOI_DIAGRAM_2_INS::Handle_adaptor Face_handle; - typedef CGAL_VORONOI_DIAGRAM_2_INS::Vertex Vertex; - typedef CGAL_VORONOI_DIAGRAM_2_INS::Handle_adaptor Vertex_handle; - typedef typename V2::Halfedge_handle Halfedge_handle; - typedef Triangulation_cw_ccw_2 CW_CCW_2; public: /// Construct the viewer. @@ -112,20 +105,27 @@ protected: // } } - void compute_ray_points(Halfedge_handle he) { + void add_segments_and_update_bounding_box(Halfedge_handle he) { if (he->is_segment()) { add_segment(he->source()->point(), he->target()->point()); - } else if (he->is_ray()) { + }else { Delaunay_vertex_const_handle v1 = he->up(); Delaunay_vertex_const_handle v2 = he->down(); Kernel::Vector_2 direction(v1->point().y() - v2->point().y(), v2->point().x() - v1->point().x()); - Kernel::Point_2 end_point; - - if (he->has_source()) { - end_point = he->source()->point(); - add_ray_points(end_point, direction); + if (he->is_ray()) { + Kernel::Point_2 end_point; + if (he->has_source()) { + end_point = he->source()->point(); + update_bounding_box_for_ray(end_point, direction); + } + } else if (he->is_bisector()){ + Kernel::Point_2 pointOnLine((v1->point().x() + v2->point().x())/2, + (v1->point().y() + v2->point().y())/2); + Kernel::Vector_2 perpendicularDirection(v2->point().x() - v1->point().x(), + v2->point().y() - v1->point().y()); + update_bounding_box_for_line(pointOnLine, direction, perpendicularDirection); } } } @@ -187,17 +187,21 @@ protected: return p1; } - void compute_rays(Halfedge_const_handle he) { + void compute_rays_and_bisectors(Halfedge_const_handle he) { + Delaunay_vertex_const_handle v1 = he->up(); + Delaunay_vertex_const_handle v2 = he->down(); + + Kernel::Vector_2 direction(v1->point().y() - v2->point().y(), + v2->point().x() - v1->point().x()); if (he->is_ray()) { if (he->has_source()) { - Delaunay_vertex_const_handle v1 = he->up(); - Delaunay_vertex_const_handle v2 = he->down(); - - Kernel::Vector_2 direction(v1->point().y() - v2->point().y(), - v2->point().x() - v1->point().x()); - //add_ray_segment(he->source()->point(), get_second_point(he)); - add_ray_segment(he->source()->point(), direction); - } + //add_ray_segment(he->source()->point(), get_second_point(he)); + add_ray(he->source()->point(), direction); + } + } else if(he->is_bisector()){ + Kernel::Point_2 pointOnLine((v1->point().x() + v2->point().x())/2, + (v1->point().y() + v2->point().y())/2); + add_line(pointOnLine, direction); } } @@ -213,12 +217,12 @@ protected: for (typename V2::Halfedge_iterator it = v2.halfedges_begin(); it != v2.halfedges_end(); ++it) { - compute_ray_points(it); + add_segments_and_update_bounding_box(it); } for (typename V2::Halfedge_iterator it = v2.halfedges_begin(); it != v2.halfedges_end(); ++it) { - compute_rays(it); + compute_rays_and_bisectors(it); } if (!m_nofaces) { From a48cb941ba524af1654b143308e409bb7a8913aa Mon Sep 17 00:00:00 2001 From: Jasmeet Singh Date: Thu, 20 Jun 2019 12:09:38 -0700 Subject: [PATCH 069/363] Draw Dual Vertices in the voronoi diagram. Update doc image for drawing voronoi diagram. Toggle with D to view/unview dual vertices. Vertex view should be ON as dual vertices use the buffer for colored vertices. --- .../fig/draw_voronoi_diagram.png | Bin 12217 -> 13122 bytes .../include/CGAL/draw_voronoi_diagram_2.h | 42 +++++++++++++----- 2 files changed, 31 insertions(+), 11 deletions(-) diff --git a/Voronoi_diagram_2/doc/Voronoi_diagram_2/fig/draw_voronoi_diagram.png b/Voronoi_diagram_2/doc/Voronoi_diagram_2/fig/draw_voronoi_diagram.png index a16496273be237725e3eac9b3da0b174e19b0774..01713d47a19c80ae2ee016fa9b98b24f71c04030 100644 GIT binary patch literal 13122 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 literal 12217 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 diff --git a/Voronoi_diagram_2/include/CGAL/draw_voronoi_diagram_2.h b/Voronoi_diagram_2/include/CGAL/draw_voronoi_diagram_2.h index c0d0e26b18f..76d11b6d3b5 100644 --- a/Voronoi_diagram_2/include/CGAL/draw_voronoi_diagram_2.h +++ b/Voronoi_diagram_2/include/CGAL/draw_voronoi_diagram_2.h @@ -52,6 +52,7 @@ class SimpleVoronoiDiagram2ViewerQt : public Basic_viewer_qt { typedef typename V2::Face_iterator Face_const_handle; typedef typename V2::Vertex_iterator Vertex_const_handle; typedef typename V2::Delaunay_vertex_handle Delaunay_vertex_const_handle; + typedef typename V2::Delaunay_graph::Finite_vertices_iterator Dual_vertices_iterator; typedef typename V2::Ccb_halfedge_circulator Ccb_halfedge_circulator; typedef typename V2::Halfedge_handle Halfedge_handle; @@ -66,14 +67,16 @@ public: SimpleVoronoiDiagram2ViewerQt(QWidget *parent, const V2 &av2, const char *title = "Basic Voronoi Viewer", bool anofaces = false, + bool draw_delaunay_vertices = true, const ColorFunctor &fcolor = ColorFunctor()) : // First draw: vertices; half-edges; faces; multi-color; no inverse // normal Base(parent, title, true, true, true, false, false), v2(av2), - m_nofaces(anofaces), m_fcolor(fcolor) + m_nofaces(anofaces), m_draw_dual_vertices(draw_delaunay_vertices), m_fcolor(fcolor) { // Add custom key description (see keyPressEvent) setKeyDescription(::Qt::Key_R, "Toggles rays display"); + setKeyDescription(::Qt::Key_D, "Toggles dual vertices display"); compute_elements(); } @@ -206,6 +209,10 @@ protected: } void compute_vertex(Vertex_const_handle vh) { add_point(vh->point()); } + void compute_delaunay_vertex(Dual_vertices_iterator vi) + { + add_point(vi->point(), CGAL::Color(black())); + } void compute_elements() { clear(); @@ -231,10 +238,13 @@ protected: compute_face(it); } } - // for(Delaunay_vertex_const_handle it = - // v2.dual().finite_vertices_begin(); - // it!=v2.dual().finite_vertices_end(); ++it) - // { compute_vertex(it);} + if (m_draw_dual_vertices) { + for (Dual_vertices_iterator it = v2.dual().finite_vertices_begin(); + it != v2.dual().finite_vertices_end(); + ++it) { + compute_delaunay_vertex(it); + } + } } virtual void keyPressEvent(QKeyEvent *e) @@ -246,8 +256,13 @@ protected: m_draw_rays=!m_draw_rays; displayMessage(QString("Draw rays=%1.").arg(m_draw_rays?"true":"false")); update(); - } - else { + } else if((e->key()==::Qt::Key_D) && (modifiers==::Qt::NoButton)) + { + m_draw_dual_vertices=!m_draw_dual_vertices; + displayMessage(QString("Dual vertices=%1.").arg(m_draw_dual_vertices?"true":"false")); + compute_elements(); + redraw(); + } else { // Call the base method to process others/classicals key Base::keyPressEvent(e); } @@ -256,11 +271,12 @@ protected: protected: const V2 &v2; bool m_nofaces; + bool m_draw_dual_vertices; const ColorFunctor &m_fcolor; }; template -void draw(const V2 &av2, const char *title, bool nofill, +void draw(const V2 &av2, const char *title, bool nofill, bool draw_dual_vertices, const ColorFunctor &fcolor) { #if defined(CGAL_TEST_SUITE) bool cgal_test_suite = true; @@ -273,15 +289,19 @@ void draw(const V2 &av2, const char *title, bool nofill, const char *argv[2] = {"v2_viewer", "\0"}; QApplication app(argc, const_cast(argv)); SimpleVoronoiDiagram2ViewerQt mainwindow( - app.activeWindow(), av2, title, nofill, fcolor); + app.activeWindow(), av2, title, nofill, draw_dual_vertices, fcolor); mainwindow.show(); app.exec(); } } -template void draw(const V2 &av2, const char *title, bool nofill) { +template void draw(const V2 &av2, const char *title, bool nofill, bool draw_dual_vertices) { DefaultColorFunctorV2 c; - draw(av2, title, nofill, c); + draw(av2, title, nofill, draw_dual_vertices, c); +} + +template void draw(const V2 &av2, const char *title, bool nofill) { + draw(av2, title, nofill, true); } template void draw(const V2 &av2, const char *title) { From 11070419336f1e2e2cf2f88698e8764082ceaffa Mon Sep 17 00:00:00 2001 From: Jasmeet Singh Date: Fri, 21 Jun 2019 11:12:01 -0700 Subject: [PATCH 070/363] Remove header draw_voronoi from vd_2_point_location as a separate example is added. Change CMakLists.txt accordingly. --- Voronoi_diagram_2/examples/Voronoi_diagram_2/CMakeLists.txt | 2 -- .../examples/Voronoi_diagram_2/vd_2_point_location.cpp | 3 --- 2 files changed, 5 deletions(-) diff --git a/Voronoi_diagram_2/examples/Voronoi_diagram_2/CMakeLists.txt b/Voronoi_diagram_2/examples/Voronoi_diagram_2/CMakeLists.txt index ef2705d980c..d00324f5907 100644 --- a/Voronoi_diagram_2/examples/Voronoi_diagram_2/CMakeLists.txt +++ b/Voronoi_diagram_2/examples/Voronoi_diagram_2/CMakeLists.txt @@ -21,8 +21,6 @@ if ( CGAL_FOUND ) endforeach() if(CGAL_Qt5_FOUND ) - target_link_libraries(vd_2_point_location PUBLIC CGAL::CGAL_Qt5) - target_link_libraries(vd_2_point_location_sdg_linf PUBLIC CGAL::CGAL_Qt5) target_link_libraries(draw_voronoi_diagram_2 PUBLIC CGAL::CGAL_Qt5) endif() diff --git a/Voronoi_diagram_2/examples/Voronoi_diagram_2/vd_2_point_location.cpp b/Voronoi_diagram_2/examples/Voronoi_diagram_2/vd_2_point_location.cpp index 025a6b7869e..8451c216bde 100644 --- a/Voronoi_diagram_2/examples/Voronoi_diagram_2/vd_2_point_location.cpp +++ b/Voronoi_diagram_2/examples/Voronoi_diagram_2/vd_2_point_location.cpp @@ -10,9 +10,6 @@ #include #include -// include to draw the Voronoi diagram -#include - // typedefs for defining the adaptor typedef CGAL::Exact_predicates_inexact_constructions_kernel K; typedef CGAL::Delaunay_triangulation_2 DT; From d1295ce3389cceb505bd1b8a25526c3b5f90f3ee Mon Sep 17 00:00:00 2001 From: Jasmeet Singh Date: Fri, 21 Jun 2019 11:30:22 -0700 Subject: [PATCH 071/363] Change order of constructor arguments so that existing derived classes from Basic_viewer which call this constructor set the arguments correctly. --- GraphicsView/include/CGAL/Qt/Basic_viewer_qt.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/GraphicsView/include/CGAL/Qt/Basic_viewer_qt.h b/GraphicsView/include/CGAL/Qt/Basic_viewer_qt.h index 7cd6853d67f..fb3afb2dbb7 100644 --- a/GraphicsView/include/CGAL/Qt/Basic_viewer_qt.h +++ b/GraphicsView/include/CGAL/Qt/Basic_viewer_qt.h @@ -168,11 +168,11 @@ public: const char* title="", bool draw_vertices=false, bool draw_edges=true, - bool draw_rays=true, - bool draw_lines=true, bool draw_faces=true, bool use_mono_color=false, - bool inverse_normal=false) : + bool inverse_normal=false, + bool draw_rays=true, + bool draw_lines=true) : CGAL::QGLViewer(parent), m_draw_vertices(draw_vertices), m_draw_edges(draw_edges), From 58dec73f743351471c90b0ac8afdbecc24e0f60e Mon Sep 17 00:00:00 2001 From: Jasmeet Singh Date: Fri, 21 Jun 2019 12:17:22 -0700 Subject: [PATCH 072/363] Update dependencies for Voronoi Diagram package: Add GraphicsView. --- Voronoi_diagram_2/package_info/Voronoi_diagram_2/dependencies | 1 + 1 file changed, 1 insertion(+) diff --git a/Voronoi_diagram_2/package_info/Voronoi_diagram_2/dependencies b/Voronoi_diagram_2/package_info/Voronoi_diagram_2/dependencies index 59ff755db76..47ba473b701 100644 --- a/Voronoi_diagram_2/package_info/Voronoi_diagram_2/dependencies +++ b/Voronoi_diagram_2/package_info/Voronoi_diagram_2/dependencies @@ -1,6 +1,7 @@ Algebraic_foundations Apollonius_graph_2 Circulator +GraphicsView Hash_map Installation Interval_support From e769c14b0054ce35c055d6983c12137c792f6c68 Mon Sep 17 00:00:00 2001 From: Jasmeet Singh Date: Fri, 21 Jun 2019 13:20:23 -0700 Subject: [PATCH 073/363] Change NULL to nullptr in buffer initialization. --- GraphicsView/include/CGAL/Qt/Basic_viewer_qt.h | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/GraphicsView/include/CGAL/Qt/Basic_viewer_qt.h b/GraphicsView/include/CGAL/Qt/Basic_viewer_qt.h index fb3afb2dbb7..291baabdcaa 100644 --- a/GraphicsView/include/CGAL/Qt/Basic_viewer_qt.h +++ b/GraphicsView/include/CGAL/Qt/Basic_viewer_qt.h @@ -212,20 +212,20 @@ public: &arrays[COLOR_SEGMENTS], nullptr, nullptr), m_buffer_for_mono_rays(&arrays[POS_MONO_RAYS], - NULL, + nullptr, &m_bounding_box, nullptr, nullptr), m_buffer_for_colored_rays(&arrays[POS_COLORED_RAYS], - NULL, + nullptr, &m_bounding_box, &arrays[COLOR_RAYS], nullptr, nullptr), m_buffer_for_mono_lines(&arrays[POS_MONO_RAYS], - NULL, + nullptr, &m_bounding_box, nullptr, nullptr), m_buffer_for_colored_lines(&arrays[POS_COLORED_LINES], - NULL, + nullptr, &m_bounding_box, &arrays[COLOR_LINES], nullptr, nullptr), From 677cbc7c07a3f1c040a704a5341fbf377f25b161 Mon Sep 17 00:00:00 2001 From: Jasmeet Singh Date: Sat, 22 Jun 2019 17:53:18 -0700 Subject: [PATCH 074/363] Add Periodic_2_triangulation_2 viewer. Add example - draw_periodic_2_triangulation_2.cpp. Keypress 1-UNIQUE, 2-UNIQUE_COVER_DOMAIN, 3-STORED, 4-STORED_COVER_DOMAIN, D-draw the domain. Color values for faces are fixed for now. Boundaries of faces are also viewed with a light gray color so as to properly display a triangular face. --- .../Periodic_2_triangulation_2/CMakeLists.txt | 9 +- .../data/data1.dt.cin | 3 + .../draw_periodic_2_triangulation_2.cpp | 30 ++ .../CGAL/draw_periodic_2_triangulation_2.h | 300 ++++++++++++++++++ 4 files changed, 341 insertions(+), 1 deletion(-) create mode 100644 Periodic_2_triangulation_2/examples/Periodic_2_triangulation_2/data/data1.dt.cin create mode 100644 Periodic_2_triangulation_2/examples/Periodic_2_triangulation_2/draw_periodic_2_triangulation_2.cpp create mode 100644 Periodic_2_triangulation_2/include/CGAL/draw_periodic_2_triangulation_2.h diff --git a/Periodic_2_triangulation_2/examples/Periodic_2_triangulation_2/CMakeLists.txt b/Periodic_2_triangulation_2/examples/Periodic_2_triangulation_2/CMakeLists.txt index 2f9d63ad422..22c0a81ce02 100644 --- a/Periodic_2_triangulation_2/examples/Periodic_2_triangulation_2/CMakeLists.txt +++ b/Periodic_2_triangulation_2/examples/Periodic_2_triangulation_2/CMakeLists.txt @@ -6,7 +6,11 @@ project( Periodic_2_triangulation_2_Examples ) cmake_minimum_required(VERSION 3.1) -find_package(CGAL QUIET) +find_package(CGAL COMPONENTS Qt5) + +if(CGAL_Qt5_FOUND) + add_definitions(-DCGAL_USE_BASIC_VIEWER -DQT_NO_KEYWORDS) +endif() if ( CGAL_FOUND ) @@ -16,6 +20,9 @@ if ( CGAL_FOUND ) create_single_source_cgal_program( "${cppfile}" ) endforeach() + if(CGAL_Qt5_FOUND) + target_link_libraries(draw_periodic_2_triangulation_2 PUBLIC CGAL::CGAL_Qt5) + endif() else() message(STATUS "This program requires the CGAL library, and will not be compiled.") diff --git a/Periodic_2_triangulation_2/examples/Periodic_2_triangulation_2/data/data1.dt.cin b/Periodic_2_triangulation_2/examples/Periodic_2_triangulation_2/data/data1.dt.cin new file mode 100644 index 00000000000..c1c3fe53450 --- /dev/null +++ b/Periodic_2_triangulation_2/examples/Periodic_2_triangulation_2/data/data1.dt.cin @@ -0,0 +1,3 @@ +0.6 0.2 +0.4 0.4 +0.2 0.8 diff --git a/Periodic_2_triangulation_2/examples/Periodic_2_triangulation_2/draw_periodic_2_triangulation_2.cpp b/Periodic_2_triangulation_2/examples/Periodic_2_triangulation_2/draw_periodic_2_triangulation_2.cpp new file mode 100644 index 00000000000..9702e4a1c54 --- /dev/null +++ b/Periodic_2_triangulation_2/examples/Periodic_2_triangulation_2/draw_periodic_2_triangulation_2.cpp @@ -0,0 +1,30 @@ +#include +#include +#include + +#include + +typedef CGAL::Exact_predicates_inexact_constructions_kernel K; +typedef CGAL::Periodic_2_triangulation_traits_2 GT; + +typedef CGAL::Periodic_2_triangulation_2 PDT; + +typedef PDT::Point Point; + +int main(int argc, char* argv[]) +{ + // Declare periodic triangulation 2D + PDT T; + + // Read points and insert in T + Point p; + std::ifstream ifs((argc > 1) ? argv[1] : "data/data1.dt.cin"); + assert(ifs); + while (ifs >> p) { + T.insert(p); + } + assert(T.is_valid()); + + // Draw the periodic triangulation + CGAL::draw(T); +} diff --git a/Periodic_2_triangulation_2/include/CGAL/draw_periodic_2_triangulation_2.h b/Periodic_2_triangulation_2/include/CGAL/draw_periodic_2_triangulation_2.h new file mode 100644 index 00000000000..19ad11bb060 --- /dev/null +++ b/Periodic_2_triangulation_2/include/CGAL/draw_periodic_2_triangulation_2.h @@ -0,0 +1,300 @@ +// Copyright (c) 2019 INRIA Sophia-Antipolis (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) : Jasmeet Singh + +#ifndef DRAW_PERIODIC_2_TRIANGULATION_2_H +#define DRAW_PERIODIC_2_TRIANGULATION_2_H + +#include +#include + +#ifdef CGAL_USE_BASIC_VIEWER + +#include + +namespace CGAL { + +// Default color functor; user can change it to have its own face color +struct DefaultColorFunctorP2T2 { + template + static CGAL::Color run(const P2T2 &, + const typename P2T2::Periodic_triangle_iterator ti) { + CGAL::Random random((unsigned int)(std::size_t)(&*ti)); + return get_random_color(random); + } +}; + +// Viewer class for P2T2 +template +class SimplePeriodic2Triangulation2ViewerQt : public Basic_viewer_qt +{ + typedef Basic_viewer_qt Base; + + typedef typename P2T2::Iterator_type Iterator_type; + + // Vertex iterators + typedef typename P2T2::Periodic_point_iterator Periodic_point_iterator; + + // Edge iterators + typedef typename P2T2::Periodic_segment_iterator Periodic_segment_iterator; + typedef typename P2T2::Segment Segment; + + // Face iterators + typedef typename P2T2::Periodic_triangle_iterator Periodic_triangle_iterator; + typedef typename P2T2::Triangle Triangle; + + typedef CGAL::Exact_predicates_inexact_constructions_kernel Kernel; + +public: + /// Construct the viewer. + /// @param ap2t2 the p2t2 to view + /// @param title the title of the window + /// @param anofaces if true, do not draw faces (faces are not computed; this can be + /// usefull for very big object where this time could be long) + SimplePeriodic2Triangulation2ViewerQt(QWidget* parent, const P2T2& ap2t2, + const char* title="Basic P2T2 Viewer", + bool anofaces=false, + const ColorFunctor& fcolor=ColorFunctor()) : + // First draw: vertices; edges, faces; multi-color; no inverse normal + Base(parent, title, true, true, true, false, false), + p2t2(ap2t2), + m_nofaces(anofaces), + m_fcolor(fcolor), + m_display_type(STORED_COVER_DOMAIN), + m_domain(true) + { + // Add custom key description (see keyPressEvent). + setKeyDescription(::Qt::Key_1, "STORED: Display all geometric primitives as they are stored in " + "Triangulation_data_structure_2"); + setKeyDescription(::Qt::Key_2, "UNIQUE: Display only one representative of each geometric primitive even " + "if the triangulation is computed in multiply sheeted covering space."); + setKeyDescription(::Qt::Key_3, "STORED_COVER_DOMAIN: Same as STORED but also display " + "all primitives whose intersection with the original " + "domain of the current covering space is non-empty"); + setKeyDescription(::Qt::Key_4, "UNIQUE_COVER_DOMAIN: Same as UNIQUE but also display " + "all primitives whose intersection with the original " + "domain of the current covering space is non-empty"); + + compute_elements(); + } +protected: + void compute_vertex(Periodic_point_iterator pi) + { + // Construct the point in 9-sheeted covering space and add to viewer + add_point(p2t2.point(*pi)); + } + + void compute_edge(Periodic_segment_iterator si) + { + // Construct the segment in 9-sheeted covering space and add to viewer + Segment s(p2t2.segment(*si)); + add_segment(s[0], s[1]); + } + + void compute_face(Periodic_triangle_iterator ti) + { + // Construct the triangle in 9-sheeted covering space and add to viewer + Triangle t(p2t2.triangle(*ti)); + + //CGAL::Color c=m_fcolor.run(p2t2, ti); + face_begin(CGAL::Color(73, 250, 117)); + add_point_in_face(t[0]); + add_point_in_face(t[1]); + add_point_in_face(t[2]); + face_end(); + + add_segment(t[0], t[1], CGAL::Color(207, 213, 211)); + add_segment(t[1], t[2], CGAL::Color(207, 213, 211)); + add_segment(t[2], t[0], CGAL::Color(207, 213, 211)); + } + + void compute_domain() + { + Kernel::Iso_rectangle_2 orig_domain = p2t2.domain(); + std::array covering_sheets = p2t2.number_of_sheets(); + + for(int i = 0; i < covering_sheets[0]; i++){ + for(int j = 0; j < covering_sheets[1]; j++){ + Kernel::Vector_2 shift(i * (orig_domain.xmax() - orig_domain.xmin()), + j * orig_domain.ymax() - orig_domain.ymin()); + Kernel::Point_2 p1(orig_domain.min()); + Kernel::Point_2 p2(orig_domain.xmin(), orig_domain.ymax()); + Kernel::Point_2 p3(orig_domain.xmax(), orig_domain.ymin()); + Kernel::Point_2 p4(orig_domain.max()); + + add_segment(p1 + shift, p2 + shift, CGAL::Color(96, 104, 252)); + add_segment(p1 + shift, p3 + shift, CGAL::Color(96, 104, 252)); + add_segment(p2 + shift, p4 + shift, CGAL::Color(96, 104, 252)); + add_segment(p3 + shift, p4 + shift, CGAL::Color(96, 104, 252)); + } + } + } + + void compute_elements() { + // Clear the buffers + clear(); + + // Get the display type, iterate through periodic elements according + // to the display type + Iterator_type it_type = (Iterator_type)m_display_type; + + // Iterate through vertices, edges and faces, add elements to buffer + for (Periodic_point_iterator it = + p2t2.periodic_points_begin(it_type); + it != p2t2.periodic_points_end(it_type); it++) + { + compute_vertex(it); + } + + for (Periodic_segment_iterator it = + p2t2.periodic_segments_begin(it_type); + it != p2t2.periodic_segments_end(it_type); it++) + { + compute_edge(it); + } + + for (Periodic_triangle_iterator it = + p2t2.periodic_triangles_begin(it_type); + it != p2t2.periodic_triangles_end(it_type); it++) + { + compute_face(it); + } + + if(m_domain){ + // Compute the (9-sheet covering space) domain of the periodic triangulation + compute_domain(); + } + } + + virtual void keyPressEvent(QKeyEvent *e) + { + // Test key pressed: + // const ::Qt::KeyboardModifiers modifiers = e->modifiers(); + // if ((e->key()==Qt::Key_PageUp) && (modifiers==Qt::NoButton)) { ... } + + // Call: * compute_elements() if the model changed, followed by + // * redraw() if some viewing parameters changed that implies some + // modifications of the buffers + // (eg. type of normal, color/mono) + // * update() just to update the drawing + + // Call the base method to process others/classicals key + const ::Qt::KeyboardModifiers modifiers = e->modifiers(); + if ((e->key() == ::Qt::Key_1) && (modifiers == ::Qt::NoButton)) + { + m_display_type = Display_type::UNIQUE; + displayMessage( + QString("Display type= UNIQUE")); + compute_elements(); + redraw(); + } else if ((e->key() == ::Qt::Key_2) && (modifiers == ::Qt::NoButton)) + { + m_display_type = Display_type::UNIQUE_COVER_DOMAIN; + displayMessage( + QString("Display type= UNIQUE_COVER_DOMAIN")); + compute_elements(); + redraw(); + } else if ((e->key() == ::Qt::Key_3) && (modifiers == ::Qt::NoButton)) + { + m_display_type = Display_type::STORED; + displayMessage( + QString("Display type= STORED")); + compute_elements(); + redraw(); + } else if ((e->key() == ::Qt::Key_4) && (modifiers == ::Qt::NoButton)) + { + m_display_type = Display_type::STORED_COVER_DOMAIN; + displayMessage( + QString("Display type= STORED_COVER_DOMAIN")); + compute_elements(); + redraw(); + } else if ((e->key() == ::Qt::Key_D) && (modifiers == ::Qt::NoButton)) + { + m_domain=!m_domain; + displayMessage( + QString("Draw domain=%1.").arg(m_domain?"true":"false")); + compute_elements(); + redraw(); + } else { + Base::keyPressEvent(e); + } + } + +protected: + const P2T2& p2t2; + bool m_nofaces; + const ColorFunctor& m_fcolor; + enum Display_type + { + STORED = 0, + UNIQUE, // 1 + STORED_COVER_DOMAIN, // 2 + UNIQUE_COVER_DOMAIN // 3 + }; + Display_type m_display_type; + bool m_domain; +}; + +template +void draw(const P2T2& ap2t2, + const char* title, + bool nofill, + const ColorFunctor& fcolor) +{ +#if defined(CGAL_TEST_SUITE) + bool cgal_test_suite=true; +#else + bool cgal_test_suite=false; +#endif + + if (!cgal_test_suite) + { + int argc=1; + const char* argv[2]={"p2t2_viewer","\0"}; + QApplication app(argc,const_cast(argv)); + SimplePeriodic2Triangulation2ViewerQt mainwindow(app.activeWindow(), + ap2t2, + title, + nofill, + fcolor); + mainwindow.show(); + app.exec(); + } +} + +template +void draw(const P2T2& ap2t2, const char* title, bool nofill) +{ + DefaultColorFunctorP2T2 c; + draw(ap2t2, title, nofill, c); +} + +template +void draw(const P2T2& ap2t2, const char* title) +{ draw(ap2t2, title, false); } + +template +void draw(const P2T2& ap2t2) +{ draw(ap2t2, "Basic 2D Periodic Triangulation Viewer"); } + +} // namespace CGAL + +#endif // CGAL_USE_BASIC_VIEWER + +#endif // DRAW_PERIODIC_2_TRIANGULATION_2_H From a9eae8a297a884e0e0465e08cdc33de28b9781bb Mon Sep 17 00:00:00 2001 From: Jasmeet Singh Date: Sat, 22 Jun 2019 18:00:01 -0700 Subject: [PATCH 075/363] Add Key description for Key D which displays the domain. --- .../draw_periodic_2_triangulation_2.cpp | 1 - .../include/CGAL/draw_periodic_2_triangulation_2.h | 1 + 2 files changed, 1 insertion(+), 1 deletion(-) diff --git a/Periodic_2_triangulation_2/examples/Periodic_2_triangulation_2/draw_periodic_2_triangulation_2.cpp b/Periodic_2_triangulation_2/examples/Periodic_2_triangulation_2/draw_periodic_2_triangulation_2.cpp index 9702e4a1c54..c8f6aeb27f7 100644 --- a/Periodic_2_triangulation_2/examples/Periodic_2_triangulation_2/draw_periodic_2_triangulation_2.cpp +++ b/Periodic_2_triangulation_2/examples/Periodic_2_triangulation_2/draw_periodic_2_triangulation_2.cpp @@ -6,7 +6,6 @@ typedef CGAL::Exact_predicates_inexact_constructions_kernel K; typedef CGAL::Periodic_2_triangulation_traits_2 GT; - typedef CGAL::Periodic_2_triangulation_2 PDT; typedef PDT::Point Point; diff --git a/Periodic_2_triangulation_2/include/CGAL/draw_periodic_2_triangulation_2.h b/Periodic_2_triangulation_2/include/CGAL/draw_periodic_2_triangulation_2.h index 19ad11bb060..60c63b513dc 100644 --- a/Periodic_2_triangulation_2/include/CGAL/draw_periodic_2_triangulation_2.h +++ b/Periodic_2_triangulation_2/include/CGAL/draw_periodic_2_triangulation_2.h @@ -90,6 +90,7 @@ public: setKeyDescription(::Qt::Key_4, "UNIQUE_COVER_DOMAIN: Same as UNIQUE but also display " "all primitives whose intersection with the original " "domain of the current covering space is non-empty"); + setKeyDescription(::Qt::Key_D, "Toggle 9-sheeted domain display"); compute_elements(); } From f8bc47dbf6223c98e37c203471b6957b9871f5b0 Mon Sep 17 00:00:00 2001 From: Jasmeet Singh Date: Sat, 22 Jun 2019 18:49:49 -0700 Subject: [PATCH 076/363] Check visualization for Periodic Delaunay Triangulation as well. Change example to a delaunay triangulation. Add is_triangulation_in_1_sheet() check and then convert to 9-sheet if the triangulation isn't so already. --- .../data/data1.dt.cin | 23 ++++++++++++++++--- .../draw_periodic_2_triangulation_2.cpp | 13 +++++++---- .../CGAL/draw_periodic_2_triangulation_2.h | 2 ++ 3 files changed, 31 insertions(+), 7 deletions(-) diff --git a/Periodic_2_triangulation_2/examples/Periodic_2_triangulation_2/data/data1.dt.cin b/Periodic_2_triangulation_2/examples/Periodic_2_triangulation_2/data/data1.dt.cin index c1c3fe53450..30765637fa5 100644 --- a/Periodic_2_triangulation_2/examples/Periodic_2_triangulation_2/data/data1.dt.cin +++ b/Periodic_2_triangulation_2/examples/Periodic_2_triangulation_2/data/data1.dt.cin @@ -1,3 +1,20 @@ -0.6 0.2 -0.4 0.4 -0.2 0.8 +0.192592592592593 0.037037037037037 +0.17037037037037 0.177777777777778 +0.451851851851852 0.111111111111111 +0.274074074074074 0.37037037037037 +0.133333333333333 0.592592592592593 +0.037037037037037 0.688888888888889 +0.177777777777778 0.844444444444444 +0.288888888888889 0.674074074074074 +0.318518518518519 0.925925925925926 +0.540740740740741 0.844444444444444 +0.637037037037037 0.703703703703704 +0.511111111111111 0.496296296296296 +0.725925925925926 0.237037037037037 +0.933333333333333 0.22962962962963 +0.733333333333333 0.511111111111111 +0.925925925925926 0.459259259259259 +0.866666666666667 0.777777777777778 +0.77037037037037 0.925925925925926 +0.881481481481482 0.977777777777778 +0.990000000000000 0.911111111111111 diff --git a/Periodic_2_triangulation_2/examples/Periodic_2_triangulation_2/draw_periodic_2_triangulation_2.cpp b/Periodic_2_triangulation_2/examples/Periodic_2_triangulation_2/draw_periodic_2_triangulation_2.cpp index c8f6aeb27f7..676ca27746d 100644 --- a/Periodic_2_triangulation_2/examples/Periodic_2_triangulation_2/draw_periodic_2_triangulation_2.cpp +++ b/Periodic_2_triangulation_2/examples/Periodic_2_triangulation_2/draw_periodic_2_triangulation_2.cpp @@ -1,12 +1,12 @@ -#include -#include +#include +#include #include #include typedef CGAL::Exact_predicates_inexact_constructions_kernel K; -typedef CGAL::Periodic_2_triangulation_traits_2 GT; -typedef CGAL::Periodic_2_triangulation_2 PDT; +typedef CGAL::Periodic_2_Delaunay_triangulation_traits_2 GT; +typedef CGAL::Periodic_2_Delaunay_triangulation_2 PDT; typedef PDT::Point Point; @@ -24,6 +24,11 @@ int main(int argc, char* argv[]) } assert(T.is_valid()); + if( T.is_triangulation_in_1_sheet()) + T.convert_to_9_sheeted_covering(); + // Draw the periodic triangulation CGAL::draw(T); + + return EXIT_SUCCESS; } diff --git a/Periodic_2_triangulation_2/include/CGAL/draw_periodic_2_triangulation_2.h b/Periodic_2_triangulation_2/include/CGAL/draw_periodic_2_triangulation_2.h index 60c63b513dc..a20f4d21f50 100644 --- a/Periodic_2_triangulation_2/include/CGAL/draw_periodic_2_triangulation_2.h +++ b/Periodic_2_triangulation_2/include/CGAL/draw_periodic_2_triangulation_2.h @@ -120,6 +120,8 @@ protected: add_point_in_face(t[2]); face_end(); + // Display the edges of the faces as segments with a + // light gray color for better visualization add_segment(t[0], t[1], CGAL::Color(207, 213, 211)); add_segment(t[1], t[2], CGAL::Color(207, 213, 211)); add_segment(t[2], t[0], CGAL::Color(207, 213, 211)); From 8096f383367dc07e283c7e735dd21a3e875aaa3f Mon Sep 17 00:00:00 2001 From: Jasmeet Singh Date: Sat, 22 Jun 2019 19:29:30 -0700 Subject: [PATCH 077/363] Add documentation for 2D Periodic Triangulation viewer. --- .../PackageDescription.txt | 8 ++++++++ .../Periodic_2_triangulation_2.txt | 18 ++++++++++++++++++ .../Periodic_2_triangulation_2/dependencies | 1 + .../Periodic_2_triangulation_2/examples.txt | 1 + .../fig/stored-cover.png | Bin 0 -> 39865 bytes .../Periodic_2_triangulation_2/fig/stored.png | Bin 0 -> 36724 bytes .../fig/unique-cover.png | Bin 0 -> 17438 bytes .../Periodic_2_triangulation_2/fig/unique.png | Bin 0 -> 15508 bytes 8 files changed, 28 insertions(+) create mode 100644 Periodic_2_triangulation_2/doc/Periodic_2_triangulation_2/fig/stored-cover.png create mode 100644 Periodic_2_triangulation_2/doc/Periodic_2_triangulation_2/fig/stored.png create mode 100644 Periodic_2_triangulation_2/doc/Periodic_2_triangulation_2/fig/unique-cover.png create mode 100644 Periodic_2_triangulation_2/doc/Periodic_2_triangulation_2/fig/unique.png diff --git a/Periodic_2_triangulation_2/doc/Periodic_2_triangulation_2/PackageDescription.txt b/Periodic_2_triangulation_2/doc/Periodic_2_triangulation_2/PackageDescription.txt index 91e32e18995..bdfc450c4a8 100644 --- a/Periodic_2_triangulation_2/doc/Periodic_2_triangulation_2/PackageDescription.txt +++ b/Periodic_2_triangulation_2/doc/Periodic_2_triangulation_2/PackageDescription.txt @@ -15,6 +15,14 @@ /// \defgroup PkgPeriodic2Triangulation2Enums Enums /// \ingroup PkgPeriodic2Triangulation2Ref +/*! Draw. + \code + #include + \endcode +*/ +/// \defgroup PkgPeriodic2Triangulation2Draw Draw a 2D Periodic Triangulation +/// \ingroup PkgPeriodic2Triangulation2Ref + /*! \addtogroup PkgPeriodic2Triangulation2Ref diff --git a/Periodic_2_triangulation_2/doc/Periodic_2_triangulation_2/Periodic_2_triangulation_2.txt b/Periodic_2_triangulation_2/doc/Periodic_2_triangulation_2/Periodic_2_triangulation_2.txt index a0a56502ead..4ebe43ddabb 100644 --- a/Periodic_2_triangulation_2/doc/Periodic_2_triangulation_2/Periodic_2_triangulation_2.txt +++ b/Periodic_2_triangulation_2/doc/Periodic_2_triangulation_2/Periodic_2_triangulation_2.txt @@ -394,6 +394,24 @@ in the unit rectangle. The tests were done on an Intel i7 @ 2.67GHz. \image html p2dt2_performance.png \image latex p2dt2_performance.png +\section P2T2_Draw_Periodic_Triangulation Draw a 2D Periodic Triangulation + +A 2D periodic triangulation can be visualized by calling the 'CGAL::draw()' function as shown in the following example. This function opens a new window showing the given Periodic Triangulation. Elements of the periodic triangulation can be viewed in four different modes: + +- STORED Display all geometric primitives as they are stored in Triangulation_data_structure_2 +- UNIQUE Display only one representative of each geometric primitive even if the triangulation is computed in multiply sheeted covering space. +- STORED_COVER_DOMAIN Same as STORED but also display all primitives whose intersection with the original domain of the current covering space is non-empty +- UNIQUE_COVER_DOMAIN Same as UNIQUE but also display all primitives whose intersection with the original domain of the current covering space is non-empty + +The domain can also be visualized by a key press. To see how to visualize the Periodic Triangulation in various modes, press key H when the viewer window is active and go to Keyboard tab. See \cgalFigureRef{P2Triangulation2figdraw1} and \cgalFigureRef{P2Triangulation2figdraw2} + +\cgalFigureBegin{P2Triangulation2figdraw1, unique.png, unique-cover.png} +Result of the run of the draw_periodic_2_triangulation_2 program for display modes Unique(left) and Unique Cover Domain(right). The window allows to navigate through the 3D scene. +\cgalFigureEnd +\cgalFigureBegin{P2Triangulation2figdraw2, stored.png, stored-cover.png} +Result of the run of the draw_periodic_2_triangulation_2 program for display modes Stored(left) and Stored Cover Domain(right). +\cgalFigureEnd + \section P2T2_Design Design and Implementation History The periodic 2D-triangulation is based on the 2D triangulation package diff --git a/Periodic_2_triangulation_2/doc/Periodic_2_triangulation_2/dependencies b/Periodic_2_triangulation_2/doc/Periodic_2_triangulation_2/dependencies index 32fa6fbdf73..b0b47131d59 100644 --- a/Periodic_2_triangulation_2/doc/Periodic_2_triangulation_2/dependencies +++ b/Periodic_2_triangulation_2/doc/Periodic_2_triangulation_2/dependencies @@ -7,3 +7,4 @@ Stream_support TDS_2 Triangulation_2 Spatial_sorting +GraphicsView diff --git a/Periodic_2_triangulation_2/doc/Periodic_2_triangulation_2/examples.txt b/Periodic_2_triangulation_2/doc/Periodic_2_triangulation_2/examples.txt index 9be1a7e1709..37a43d200ff 100644 --- a/Periodic_2_triangulation_2/doc/Periodic_2_triangulation_2/examples.txt +++ b/Periodic_2_triangulation_2/doc/Periodic_2_triangulation_2/examples.txt @@ -9,4 +9,5 @@ \example Periodic_2_triangulation_2/p2t2_info_insert_with_transform_iterator_2.cpp \example Periodic_2_triangulation_2/p2t2_info_insert_with_zip_iterator_2.cpp \example Periodic_2_triangulation_2/p2t2_large_point_set.cpp +\example Periodic_2_triangulation_2/draw_periodic_2_triangulation_2.cpp */ diff --git a/Periodic_2_triangulation_2/doc/Periodic_2_triangulation_2/fig/stored-cover.png b/Periodic_2_triangulation_2/doc/Periodic_2_triangulation_2/fig/stored-cover.png new file mode 100644 index 0000000000000000000000000000000000000000..ead02c3044c76c9549e06379bf9f2d3043a16a55 GIT binary patch literal 39865 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 literal 0 HcmV?d00001 diff --git a/Periodic_2_triangulation_2/doc/Periodic_2_triangulation_2/fig/stored.png b/Periodic_2_triangulation_2/doc/Periodic_2_triangulation_2/fig/stored.png new file mode 100644 index 0000000000000000000000000000000000000000..cc14f2a0de1933371979b7dc8c2e70c227514574 GIT binary patch literal 36724 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 Sh;qpfR|etgF@ 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 aGe}__{ROU%lc@m!sxLK_%U`_x^j`qVVdZ@Q literal 0 HcmV?d00001 diff --git a/Periodic_2_triangulation_2/doc/Periodic_2_triangulation_2/fig/unique.png b/Periodic_2_triangulation_2/doc/Periodic_2_triangulation_2/fig/unique.png new file mode 100644 index 0000000000000000000000000000000000000000..66008914fe576636e53e752fa6bee59c4d3682e1 GIT binary patch literal 15508 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 Date: Mon, 24 Jun 2019 10:24:32 +0200 Subject: [PATCH 078/363] Change test of keys in periodic triangulation 2 viewer to solve a problem with azerty keyboards. --- .../CGAL/draw_periodic_2_triangulation_2.h | 23 ++++++++----------- 1 file changed, 9 insertions(+), 14 deletions(-) diff --git a/Periodic_2_triangulation_2/include/CGAL/draw_periodic_2_triangulation_2.h b/Periodic_2_triangulation_2/include/CGAL/draw_periodic_2_triangulation_2.h index a20f4d21f50..b5122a0e906 100644 --- a/Periodic_2_triangulation_2/include/CGAL/draw_periodic_2_triangulation_2.h +++ b/Periodic_2_triangulation_2/include/CGAL/draw_periodic_2_triangulation_2.h @@ -199,39 +199,34 @@ protected: // Call the base method to process others/classicals key const ::Qt::KeyboardModifiers modifiers = e->modifiers(); - if ((e->key() == ::Qt::Key_1) && (modifiers == ::Qt::NoButton)) + if (e->text()=="1") { m_display_type = Display_type::UNIQUE; - displayMessage( - QString("Display type= UNIQUE")); + displayMessage(QString("Display type= UNIQUE")); compute_elements(); redraw(); - } else if ((e->key() == ::Qt::Key_2) && (modifiers == ::Qt::NoButton)) + } else if (e->text()=="2") { m_display_type = Display_type::UNIQUE_COVER_DOMAIN; - displayMessage( - QString("Display type= UNIQUE_COVER_DOMAIN")); + displayMessage(QString("Display type= UNIQUE_COVER_DOMAIN")); compute_elements(); redraw(); - } else if ((e->key() == ::Qt::Key_3) && (modifiers == ::Qt::NoButton)) + } else if (e->text()=="3") { m_display_type = Display_type::STORED; - displayMessage( - QString("Display type= STORED")); + displayMessage(QString("Display type= STORED")); compute_elements(); redraw(); - } else if ((e->key() == ::Qt::Key_4) && (modifiers == ::Qt::NoButton)) + } else if (e->text()=="4") { m_display_type = Display_type::STORED_COVER_DOMAIN; - displayMessage( - QString("Display type= STORED_COVER_DOMAIN")); + displayMessage(QString("Display type= STORED_COVER_DOMAIN")); compute_elements(); redraw(); } else if ((e->key() == ::Qt::Key_D) && (modifiers == ::Qt::NoButton)) { m_domain=!m_domain; - displayMessage( - QString("Draw domain=%1.").arg(m_domain?"true":"false")); + displayMessage(QString("Draw domain=%1.").arg(m_domain?"true":"false")); compute_elements(); redraw(); } else { From 1a3ba3d4e05b2a0201c2e236b440cf8efd2469a2 Mon Sep 17 00:00:00 2001 From: Jasmeet Singh Date: Mon, 24 Jun 2019 10:28:31 -0700 Subject: [PATCH 079/363] Change file name to match documentation --- .../CGAL/draw_voronoi_diagram_2.h | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) create mode 100644 Voronoi_diagram_2/doc/Voronoi_diagram_2/CGAL/draw_voronoi_diagram_2.h diff --git a/Voronoi_diagram_2/doc/Voronoi_diagram_2/CGAL/draw_voronoi_diagram_2.h b/Voronoi_diagram_2/doc/Voronoi_diagram_2/CGAL/draw_voronoi_diagram_2.h new file mode 100644 index 00000000000..de954014d51 --- /dev/null +++ b/Voronoi_diagram_2/doc/Voronoi_diagram_2/CGAL/draw_voronoi_diagram_2.h @@ -0,0 +1,17 @@ +namespace CGAL { + +/*! +\ingroup PkgDrawVoronoiDiagram2 + +Open a new window and draw `av2`, the `Voronoi_diagram_2` constructed from a Delaunay Graph which is a model of `DelaunayGraph_2` concept. +The class `Voronoi_diagram_2` provides an adaptor to view a triangulated Delaunay graph as their dual subdivision, the +Voronoi diagram. The 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 V2 a model of the `Voronoi2` concept. +\param av2 the voronoi diagram to draw. + +*/ +template +void draw(const V2& av2); + +} /* namespace CGAL */ \ No newline at end of file From 1401212d14de29eda6db5710b348ceb8e17da7dc Mon Sep 17 00:00:00 2001 From: Jasmeet Singh Date: Mon, 24 Jun 2019 12:40:42 -0700 Subject: [PATCH 080/363] Remove old name doc file --- .../CGAL/draw_voronoi_diagram.h | 17 ----------------- 1 file changed, 17 deletions(-) delete mode 100644 Voronoi_diagram_2/doc/Voronoi_diagram_2/CGAL/draw_voronoi_diagram.h diff --git a/Voronoi_diagram_2/doc/Voronoi_diagram_2/CGAL/draw_voronoi_diagram.h b/Voronoi_diagram_2/doc/Voronoi_diagram_2/CGAL/draw_voronoi_diagram.h deleted file mode 100644 index de954014d51..00000000000 --- a/Voronoi_diagram_2/doc/Voronoi_diagram_2/CGAL/draw_voronoi_diagram.h +++ /dev/null @@ -1,17 +0,0 @@ -namespace CGAL { - -/*! -\ingroup PkgDrawVoronoiDiagram2 - -Open a new window and draw `av2`, the `Voronoi_diagram_2` constructed from a Delaunay Graph which is a model of `DelaunayGraph_2` concept. -The class `Voronoi_diagram_2` provides an adaptor to view a triangulated Delaunay graph as their dual subdivision, the -Voronoi diagram. The 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 V2 a model of the `Voronoi2` concept. -\param av2 the voronoi diagram to draw. - -*/ -template -void draw(const V2& av2); - -} /* namespace CGAL */ \ No newline at end of file From c412d3b0f719e5cbbe1a51a55e428c0f21f2d778 Mon Sep 17 00:00:00 2001 From: Jasmeet Singh Date: Mon, 24 Jun 2019 15:21:16 -0700 Subject: [PATCH 081/363] Fix bugs in Voronoi Diagram Viewer. Format code. Fix bug in voronoi diagram documentation. Faces have the same color after toggling vertices - fixed. Rays and dual vertices have different colors from edges and voronoi vertices - fixed. Toggle for Voronoi vertices created, now V would only toggle vornoi vertices, not all vertices - fixed --- GraphicsView/include/CGAL/Buffer_for_vao.h | 56 ++- .../include/CGAL/Qt/Basic_viewer_qt.h | 65 ++-- .../CGAL/draw_periodic_2_triangulation_2.h | 18 +- .../fig/draw_voronoi_diagram.png | Bin 13122 -> 12948 bytes .../include/CGAL/draw_voronoi_diagram_2.h | 324 ++++++++++-------- 5 files changed, 284 insertions(+), 179 deletions(-) diff --git a/GraphicsView/include/CGAL/Buffer_for_vao.h b/GraphicsView/include/CGAL/Buffer_for_vao.h index 0ca294aa892..efd188cd3f8 100644 --- a/GraphicsView/include/CGAL/Buffer_for_vao.h +++ b/GraphicsView/include/CGAL/Buffer_for_vao.h @@ -260,23 +260,7 @@ public: add_segment(kp1, kp2); add_color(c); add_color(c); - } - - // 2.2) Add a ray segment, without color - template - void add_ray_segment(const KPoint& kp1, const KVector& kp2) - { - add_point(kp1); - add_point_infinity(kp2); - } - - // 2.2) Add a line - template - void add_line_segment(const KPoint& kp1, const KPoint& kp2) - { - add_point_infinity(kp1); - add_point_infinity(kp2); - } + } // 2.3) Add an indexed segment, without color. template @@ -286,6 +270,44 @@ public: add_indexed_point(index2); } + // 3.1) Add a ray segment, without color + template + void add_ray_segment(const KPoint& kp1, const KVector& kp2) + { + add_point(kp1); + add_point_infinity(kp2); + } + + //3.2) Add a ray segment, with color + template + void add_ray_segment(const KPoint& kp1, const KVector& kp2, + const CGAL::Color& c) + { + add_point(kp1); + add_point_infinity(kp2); + add_color(c); + add_color(c); + } + + // 4.1) Add a line, without color + template + void add_line_segment(const KPoint& kp1, const KPoint& kp2) + { + add_point_infinity(kp1); + add_point_infinity(kp2); + } + + // 4.1) Add a line, with color + template + void add_line_segment(const KPoint& kp1, const KPoint& kp2, + const CGAL::Color& c) + { + add_point_infinity(kp1); + add_point_infinity(kp2); + add_color(c); + add_color(c); + } + /// @return true iff a face has begun. bool is_a_face_started() const { return m_face_started; } diff --git a/GraphicsView/include/CGAL/Qt/Basic_viewer_qt.h b/GraphicsView/include/CGAL/Qt/Basic_viewer_qt.h index 291baabdcaa..64e044d5d4e 100644 --- a/GraphicsView/include/CGAL/Qt/Basic_viewer_qt.h +++ b/GraphicsView/include/CGAL/Qt/Basic_viewer_qt.h @@ -273,6 +273,10 @@ public: m_buffer_for_colored_points.is_empty() && m_buffer_for_mono_segments.is_empty() && m_buffer_for_colored_segments.is_empty() && + m_buffer_for_mono_rays.is_empty() && + m_buffer_for_colored_rays.is_empty() && + m_buffer_for_mono_lines.is_empty() && + m_buffer_for_colored_lines.is_empty() && m_buffer_for_mono_faces.is_empty() && m_buffer_for_colored_faces.is_empty()); } @@ -297,38 +301,57 @@ public: const CGAL::Color& acolor) { m_buffer_for_colored_segments.add_segment(p1, p2, acolor); } - template void update_bounding_box_for_ray(const KPoint &p, const KVector &v) { - //m_buffer_for_mono_points.add_point(p); - Local_point lp = internal::get_local_point(p); - Local_vector lv = internal::get_local_vector(v); - CGAL::Bbox_3 b = (lp+lv).bbox(); - m_bounding_box += b; - //m_bounding_box += CGAL::Bbox_3(b.xmin(), 0, b.ymin(), b.xmax(), 0, b.ymax()); + // m_buffer_for_mono_points.add_point(p); + Local_point lp = internal::get_local_point(p); + Local_vector lv = internal::get_local_vector(v); + CGAL::Bbox_3 b = (lp + lv).bbox(); + m_bounding_box += b; + // m_bounding_box += CGAL::Bbox_3(b.xmin(), 0, b.ymin(), b.xmax(), 0, + // b.ymax()); } template - void update_bounding_box_for_line(const KPoint &p, const KVector &v, const KVector &pv) { - Local_point lp = internal::get_local_point(p); - Local_vector lv = internal::get_local_vector(v); - Local_vector lpv = internal::get_local_vector(pv); + void update_bounding_box_for_line(const KPoint &p, const KVector &v, + const KVector &pv) + { + Local_point lp = internal::get_local_point(p); + Local_vector lv = internal::get_local_vector(v); + Local_vector lpv = internal::get_local_vector(pv); - CGAL::Bbox_3 b = lp.bbox() + (lp+lv).bbox() + (lp+lpv).bbox(); - m_bounding_box += b; + CGAL::Bbox_3 b = lp.bbox() + (lp + lv).bbox() + (lp + lpv).bbox(); + m_bounding_box += b; } template - void add_ray(const KPoint &p, const KVector &v) { - float bigNumber = 1e30; - m_buffer_for_mono_rays.add_ray_segment(p, (p + (bigNumber) * v)); + void add_ray(const KPoint &p, const KVector &v) + { + float bigNumber = 1e30; + m_buffer_for_mono_rays.add_ray_segment(p, (p + (bigNumber)*v)); } template - void add_line(const KPoint &p, const KVector &v) { - float bigNumber = 1e30; - m_buffer_for_mono_lines.add_line_segment((p - (bigNumber) * v), - (p + (bigNumber) * v)); + void add_ray(const KPoint &p, const KVector &v, const CGAL::Color &acolor) + { + float bigNumber = 1e30; + m_buffer_for_colored_rays.add_ray_segment(p, (p + (bigNumber)*v), acolor); + } + + template + void add_line(const KPoint &p, const KVector &v) + { + float bigNumber = 1e30; + m_buffer_for_mono_lines.add_line_segment((p - (bigNumber)*v), + (p + (bigNumber)*v)); + } + + template + void add_line(const KPoint &p, const KVector &v, const CGAL::Color &acolor) + { + float bigNumber = 1e30; + m_buffer_for_colored_lines.add_line_segment((p - (bigNumber)*v), + (p + (bigNumber)*v), acolor); } bool is_a_face_started() const @@ -1263,9 +1286,9 @@ protected: Buffer_for_vao m_buffer_for_mono_segments; Buffer_for_vao m_buffer_for_colored_segments; Buffer_for_vao m_buffer_for_mono_rays; + Buffer_for_vao m_buffer_for_colored_rays; Buffer_for_vao m_buffer_for_mono_lines; Buffer_for_vao m_buffer_for_colored_lines; - Buffer_for_vao m_buffer_for_colored_rays; Buffer_for_vao m_buffer_for_mono_faces; Buffer_for_vao m_buffer_for_colored_faces; diff --git a/Periodic_2_triangulation_2/include/CGAL/draw_periodic_2_triangulation_2.h b/Periodic_2_triangulation_2/include/CGAL/draw_periodic_2_triangulation_2.h index a20f4d21f50..82a2fa3dddc 100644 --- a/Periodic_2_triangulation_2/include/CGAL/draw_periodic_2_triangulation_2.h +++ b/Periodic_2_triangulation_2/include/CGAL/draw_periodic_2_triangulation_2.h @@ -35,8 +35,9 @@ struct DefaultColorFunctorP2T2 { template static CGAL::Color run(const P2T2 &, const typename P2T2::Periodic_triangle_iterator ti) { - CGAL::Random random((unsigned int)(std::size_t)(&*ti)); - return get_random_color(random); + //CGAL::Random random((unsigned int)(std::size_t)(&*ti)); + //return get_random_color(random); + return CGAL::Color(73, 250, 117); } }; @@ -113,8 +114,8 @@ protected: // Construct the triangle in 9-sheeted covering space and add to viewer Triangle t(p2t2.triangle(*ti)); - //CGAL::Color c=m_fcolor.run(p2t2, ti); - face_begin(CGAL::Color(73, 250, 117)); + CGAL::Color c=m_fcolor.run(p2t2, ti); + face_begin(c); add_point_in_face(t[0]); add_point_in_face(t[1]); add_point_in_face(t[2]); @@ -300,4 +301,13 @@ void draw(const P2T2& ap2t2) #endif // CGAL_USE_BASIC_VIEWER +#else // CGAL_USE_BASIC_VIEWER + +template +void draw_periodic_2_triangulation_2(CGAL::Periodic_2_Triangulation_2&) +{ + std::cerr << "Impossible to draw, CGAL_USE_BASIC_VIEWER is not defined." + << std::endl; +} + #endif // DRAW_PERIODIC_2_TRIANGULATION_2_H diff --git a/Voronoi_diagram_2/doc/Voronoi_diagram_2/fig/draw_voronoi_diagram.png b/Voronoi_diagram_2/doc/Voronoi_diagram_2/fig/draw_voronoi_diagram.png index 01713d47a19c80ae2ee016fa9b98b24f71c04030..b48e63207a5592d2f7bd429e1b8a933658f1f78a 100644 GIT binary patch literal 12948 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 literal 13122 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 diff --git a/Voronoi_diagram_2/include/CGAL/draw_voronoi_diagram_2.h b/Voronoi_diagram_2/include/CGAL/draw_voronoi_diagram_2.h index 76d11b6d3b5..ad073532e7f 100644 --- a/Voronoi_diagram_2/include/CGAL/draw_voronoi_diagram_2.h +++ b/Voronoi_diagram_2/include/CGAL/draw_voronoi_diagram_2.h @@ -36,27 +36,32 @@ namespace CGAL { // Default color functor; user can change it to have its own face color -struct DefaultColorFunctorV2 { +struct DefaultColorFunctorV2 +{ template static CGAL::Color run(const V2 &, const typename V2::Face_iterator fh) { - CGAL::Random random((unsigned int)(std::size_t)(&*fh)); - return get_random_color(random); + //CGAL::Random random((unsigned int)(std::size_t)(&*fh)); + //return get_random_color(random); + return CGAL::Color(73, 250, 117); } }; // Viewer for Voronoi diagram template -class SimpleVoronoiDiagram2ViewerQt : public Basic_viewer_qt { +class SimpleVoronoiDiagram2ViewerQt : public Basic_viewer_qt +{ typedef Basic_viewer_qt Base; - typedef typename V2::Halfedge_iterator Halfedge_const_handle; - typedef typename V2::Face_iterator Face_const_handle; typedef typename V2::Vertex_iterator Vertex_const_handle; typedef typename V2::Delaunay_vertex_handle Delaunay_vertex_const_handle; typedef typename V2::Delaunay_graph::Finite_vertices_iterator Dual_vertices_iterator; + + typedef typename V2::Halfedge_iterator Halfedge_const_handle; typedef typename V2::Ccb_halfedge_circulator Ccb_halfedge_circulator; typedef typename V2::Halfedge_handle Halfedge_handle; - typedef CGAL::Exact_predicates_inexact_constructions_kernel Kernel; + typedef typename V2::Face_iterator Face_const_handle; + + typedef CGAL::Exact_predicates_inexact_constructions_kernel Kernel; public: /// Construct the viewer. @@ -67,51 +72,37 @@ public: SimpleVoronoiDiagram2ViewerQt(QWidget *parent, const V2 &av2, const char *title = "Basic Voronoi Viewer", bool anofaces = false, + bool draw_voronoi_vertices = true, bool draw_delaunay_vertices = true, const ColorFunctor &fcolor = ColorFunctor()) : // First draw: vertices; half-edges; faces; multi-color; no inverse // normal - Base(parent, title, true, true, true, false, false), v2(av2), - m_nofaces(anofaces), m_draw_dual_vertices(draw_delaunay_vertices), m_fcolor(fcolor) - { + Base(parent, title, true, true, true, false, false, true, true), + v2(av2), m_nofaces(anofaces), + m_draw_voronoi_vertices(draw_voronoi_vertices), + m_draw_dual_vertices(draw_delaunay_vertices), m_fcolor(fcolor) { // Add custom key description (see keyPressEvent) setKeyDescription(::Qt::Key_R, "Toggles rays display"); setKeyDescription(::Qt::Key_D, "Toggles dual vertices display"); + setKeyDescription(::Qt::Key_V, "Toggles voronoi vertices display"); compute_elements(); } protected: - void compute_face(Face_const_handle fh) { - CGAL::Color c=m_fcolor.run(v2, fh); - Ccb_halfedge_circulator ec_start = fh->ccb(); - Ccb_halfedge_circulator ec = ec_start; + void compute_vertex(Vertex_const_handle vh) { add_point(vh->point()); } - if(!fh->is_unbounded()){ - face_begin(c); - do{ - add_point_in_face(ec->source()->point()); - }while(++ec != ec_start); - face_end(); - } - // Test: for unbounded faces - // else { - // do{ - // if( ec->has_source() ){ - // add_point_in_face(ec->source()->point()); - // } - // else{ - // add_point_in_face(get_second_point(ec->twin())); - // } - // } while(++ec != ec_start); - // } + void compute_dual_vertex(Dual_vertices_iterator vi) + { + add_point(vi->point(), CGAL::Color(50, 100, 180)); } - void add_segments_and_update_bounding_box(Halfedge_handle he) { + void add_segments_and_update_bounding_box(Halfedge_handle he) + { if (he->is_segment()) { add_segment(he->source()->point(), he->target()->point()); - }else { + } else { Delaunay_vertex_const_handle v1 = he->up(); Delaunay_vertex_const_handle v2 = he->down(); @@ -123,74 +114,78 @@ protected: end_point = he->source()->point(); update_bounding_box_for_ray(end_point, direction); } - } else if (he->is_bisector()){ - Kernel::Point_2 pointOnLine((v1->point().x() + v2->point().x())/2, - (v1->point().y() + v2->point().y())/2); - Kernel::Vector_2 perpendicularDirection(v2->point().x() - v1->point().x(), - v2->point().y() - v1->point().y()); - update_bounding_box_for_line(pointOnLine, direction, perpendicularDirection); + } else if (he->is_bisector()) { + Kernel::Point_2 pointOnLine((v1->point().x() + v2->point().x()) / 2, + (v1->point().y() + v2->point().y()) / 2); + Kernel::Vector_2 perpendicularDirection( + v2->point().x() - v1->point().x(), + v2->point().y() - v1->point().y()); + update_bounding_box_for_line(pointOnLine, direction, + perpendicularDirection); } } } - Local_kernel::Point_2 get_second_point(Halfedge_handle ray){ - Delaunay_vertex_const_handle v1 = ray->up(); - Delaunay_vertex_const_handle v2 = ray->down(); + Local_kernel::Point_2 get_second_point(Halfedge_handle ray) + { + Delaunay_vertex_const_handle v1 = ray->up(); + Delaunay_vertex_const_handle v2 = ray->down(); - // calculate direction of ray and its inverse - Kernel::Vector_2 v(v1->point().y() - v2->point().y(), - v2->point().x() - v1->point().x()); - Local_kernel::Vector_2 inv(1 / v.x(), 1 / v.y()); + // calculate direction of ray and its inverse + Kernel::Vector_2 v(v1->point().y() - v2->point().y(), + v2->point().x() - v1->point().x()); + Local_kernel::Vector_2 inv(1 / v.x(), 1 / v.y()); - // origin of the ray - Kernel::Point_2 p; - if(ray->has_source()){ - p = ray->source()->point(); - }else{ - p = ray->target()->point(); - } + // origin of the ray + Kernel::Point_2 p; + if (ray->has_source()) { + p = ray->source()->point(); + } else { + p = ray->target()->point(); + } - // get the bounding box of the viewer - Local_kernel::Vector_2 boundsMin(m_bounding_box.xmin(), - m_bounding_box.zmin()); - Local_kernel::Vector_2 boundsMax(m_bounding_box.xmax(), - m_bounding_box.zmax()); - // calculate intersection - double txmax, txmin, tymax, tymin; + // get the bounding box of the viewer + Local_kernel::Vector_2 boundsMin(m_bounding_box.xmin(), + m_bounding_box.zmin()); + Local_kernel::Vector_2 boundsMax(m_bounding_box.xmax(), + m_bounding_box.zmax()); + // calculate intersection + double txmax, txmin, tymax, tymin; - if (inv.x() >= 0) { - txmax = (boundsMax.x() - p.x()) * inv.x(); - txmin = (boundsMin.x() - p.x()) * inv.x(); - } else { - txmax = (boundsMin.x() - p.x()) * inv.x(); - txmin = (boundsMax.x() - p.x()) * inv.x(); - } + if (inv.x() >= 0) { + txmax = (boundsMax.x() - p.x()) * inv.x(); + txmin = (boundsMin.x() - p.x()) * inv.x(); + } else { + txmax = (boundsMin.x() - p.x()) * inv.x(); + txmin = (boundsMax.x() - p.x()) * inv.x(); + } - if (inv.y() >= 0) { - tymax = (boundsMax.y() - p.y()) * inv.y(); - tymin = (boundsMin.y() - p.y()) * inv.y(); - } else { - tymax = (boundsMin.y() - p.y()) * inv.y(); - tymin = (boundsMax.y() - p.y()) * inv.y(); - } + if (inv.y() >= 0) { + tymax = (boundsMax.y() - p.y()) * inv.y(); + tymin = (boundsMin.y() - p.y()) * inv.y(); + } else { + tymax = (boundsMin.y() - p.y()) * inv.y(); + tymin = (boundsMax.y() - p.y()) * inv.y(); + } - if (tymin > txmin) - txmin = tymin; - if (tymax < txmax) - txmax = tymax; + if (tymin > txmin) + txmin = tymin; + if (tymax < txmax) + txmax = tymax; - Local_kernel::Point_2 p1; - if (v.x() == 0) { - p1 = Local_kernel::Point_2(p.x(), p.y() + tymax * v.y()); - } else if (v.y() == 0) { - p1 = Local_kernel::Point_2(p.x() + txmax * v.x(), p.y()); - } else { - p1 = Local_kernel::Point_2(p.x() + txmax * v.x(), p.y() + tymax * v.y()); - } - return p1; + Local_kernel::Point_2 p1; + if (v.x() == 0) { + p1 = Local_kernel::Point_2(p.x(), p.y() + tymax * v.y()); + } else if (v.y() == 0) { + p1 = Local_kernel::Point_2(p.x() + txmax * v.x(), p.y()); + } else { + p1 = Local_kernel::Point_2(p.x() + txmax * v.x(), p.y() + tymax * v.y()); + } + return p1; } - void compute_rays_and_bisectors(Halfedge_const_handle he) { + void compute_rays_and_bisectors(Halfedge_const_handle he) + { Delaunay_vertex_const_handle v1 = he->up(); Delaunay_vertex_const_handle v2 = he->down(); @@ -198,38 +193,72 @@ protected: v2->point().x() - v1->point().x()); if (he->is_ray()) { if (he->has_source()) { - //add_ray_segment(he->source()->point(), get_second_point(he)); - add_ray(he->source()->point(), direction); - } - } else if(he->is_bisector()){ - Kernel::Point_2 pointOnLine((v1->point().x() + v2->point().x())/2, - (v1->point().y() + v2->point().y())/2); - add_line(pointOnLine, direction); + // add_ray_segment(he->source()->point(), get_second_point(he)); + add_ray(he->source()->point(), direction, CGAL::Color(100, 0, 0)); + } + } else if (he->is_bisector()) { + Kernel::Point_2 pointOnLine((v1->point().x() + v2->point().x()) / 2, + (v1->point().y() + v2->point().y()) / 2); + add_line(pointOnLine, direction); } } - void compute_vertex(Vertex_const_handle vh) { add_point(vh->point()); } - void compute_delaunay_vertex(Dual_vertices_iterator vi) + void compute_face(Face_const_handle fh) { - add_point(vi->point(), CGAL::Color(black())); + CGAL::Color c = m_fcolor.run(v2, fh); + + Ccb_halfedge_circulator ec_start = fh->ccb(); + Ccb_halfedge_circulator ec = ec_start; + + if (!fh->is_unbounded()) { + face_begin(c); + do { + add_point_in_face(ec->source()->point()); + } while (++ec != ec_start); + face_end(); + } + // Test: for unbounded faces + // else { + // do{ + // if( ec->has_source() ){ + // add_point_in_face(ec->source()->point()); + // } + // else{ + // add_point_in_face(get_second_point(ec->twin())); + // } + // } while(++ec != ec_start); + // } } - void compute_elements() { + void compute_elements() + { clear(); - for (typename V2::Vertex_iterator it = v2.vertices_begin(); - it != v2.vertices_end(); ++it) { + // Draw the voronoi vertices + if (m_draw_voronoi_vertices) { + for (typename V2::Vertex_iterator it = v2.vertices_begin(); + it != v2.vertices_end(); ++it) { compute_vertex(it); + } + } + + // Draw the dual vertices + if (m_draw_dual_vertices) { + for (Dual_vertices_iterator it = v2.dual().finite_vertices_begin(); + it != v2.dual().finite_vertices_end(); ++it) { + compute_dual_vertex(it); + } + } + + // Add segments and update bounding box + for (typename V2::Halfedge_iterator it = v2.halfedges_begin(); + it != v2.halfedges_end(); ++it) { + add_segments_and_update_bounding_box(it); } for (typename V2::Halfedge_iterator it = v2.halfedges_begin(); it != v2.halfedges_end(); ++it) { - add_segments_and_update_bounding_box(it); - } - - for (typename V2::Halfedge_iterator it = v2.halfedges_begin(); - it != v2.halfedges_end(); ++it) { - compute_rays_and_bisectors(it); + compute_rays_and_bisectors(it); } if (!m_nofaces) { @@ -238,45 +267,47 @@ protected: compute_face(it); } } - if (m_draw_dual_vertices) { - for (Dual_vertices_iterator it = v2.dual().finite_vertices_begin(); - it != v2.dual().finite_vertices_end(); - ++it) { - compute_delaunay_vertex(it); - } - } } virtual void keyPressEvent(QKeyEvent *e) { - /// [Keypress] - const ::Qt::KeyboardModifiers modifiers = e->modifiers(); - if((e->key()==::Qt::Key_R) && (modifiers==::Qt::NoButton)) - { - m_draw_rays=!m_draw_rays; - displayMessage(QString("Draw rays=%1.").arg(m_draw_rays?"true":"false")); - update(); - } else if((e->key()==::Qt::Key_D) && (modifiers==::Qt::NoButton)) - { - m_draw_dual_vertices=!m_draw_dual_vertices; - displayMessage(QString("Dual vertices=%1.").arg(m_draw_dual_vertices?"true":"false")); - compute_elements(); - redraw(); - } else { - // Call the base method to process others/classicals key - Base::keyPressEvent(e); - } - /// [Keypress] + /// [Keypress] + const ::Qt::KeyboardModifiers modifiers = e->modifiers(); + if ((e->key() == ::Qt::Key_R) && (modifiers == ::Qt::NoButton)) { + m_draw_rays = !m_draw_rays; + displayMessage( + QString("Draw rays=%1.").arg(m_draw_rays ? "true" : "false")); + update(); + } else if ((e->key() == ::Qt::Key_V) && (modifiers == ::Qt::NoButton)) { + m_draw_voronoi_vertices = !m_draw_voronoi_vertices; + displayMessage( + QString("Voronoi vertices=%1.").arg(m_draw_voronoi_vertices? "true" : "false")); + compute_elements(); + redraw(); + } else if ((e->key() == ::Qt::Key_D) && (modifiers == ::Qt::NoButton)) { + m_draw_dual_vertices = !m_draw_dual_vertices; + displayMessage(QString("Dual vertices=%1.") + .arg(m_draw_dual_vertices ? "true" : "false")); + compute_elements(); + redraw(); + } else { + // Call the base method to process others/classicals key + Base::keyPressEvent(e); + } + /// [Keypress] } + protected: const V2 &v2; bool m_nofaces; + bool m_draw_voronoi_vertices; bool m_draw_dual_vertices; const ColorFunctor &m_fcolor; }; template -void draw(const V2 &av2, const char *title, bool nofill, bool draw_dual_vertices, +void draw(const V2 &av2, const char *title, bool nofill, + bool draw_voronoi_vertices, bool draw_dual_vertices, const ColorFunctor &fcolor) { #if defined(CGAL_TEST_SUITE) bool cgal_test_suite = true; @@ -289,15 +320,25 @@ void draw(const V2 &av2, const char *title, bool nofill, bool draw_dual_vertices const char *argv[2] = {"v2_viewer", "\0"}; QApplication app(argc, const_cast(argv)); SimpleVoronoiDiagram2ViewerQt mainwindow( - app.activeWindow(), av2, title, nofill, draw_dual_vertices, fcolor); + app.activeWindow(), av2, title, nofill, draw_voronoi_vertices, + draw_dual_vertices, fcolor); mainwindow.show(); app.exec(); } } -template void draw(const V2 &av2, const char *title, bool nofill, bool draw_dual_vertices) { +template +void draw(const V2 &av2, const char *title, bool nofill, + bool draw_voronoi_vertices, bool draw_dual_vertices) { DefaultColorFunctorV2 c; - draw(av2, title, nofill, draw_dual_vertices, c); + draw(av2, title, nofill, draw_voronoi_vertices, draw_dual_vertices, c); +} + +template +void draw(const V2 &av2, const char *title, bool nofill, + bool draw_voronoi_vertices) { + DefaultColorFunctorV2 c; + draw(av2, title, nofill, draw_voronoi_vertices, true); } template void draw(const V2 &av2, const char *title, bool nofill) { @@ -314,6 +355,15 @@ template void draw(const V2 &av2) { } // End namespace CGAL +#else // CGAL_USE_BASIC_VIEWER + +template +void draw_voronoi_diagram_2(CGAL::VoronoiDiagram_2&) +{ + std::cerr << "Impossible to draw, CGAL_USE_BASIC_VIEWER is not defined." + << std::endl; +} + #endif // CGAL_USE_BASIC_VIEWER #endif // CGAL_DRAW_VORONOI_H From e661cfb261c240cd1e121eb37d8ff12996f6c06f Mon Sep 17 00:00:00 2001 From: Jasmeet Singh Date: Mon, 24 Jun 2019 16:33:33 -0700 Subject: [PATCH 082/363] Update documentation. --- .../doc/Periodic_2_triangulation_2/PackageDescription.txt | 5 ++++- .../Periodic_2_triangulation_2.txt | 2 +- .../doc/Voronoi_diagram_2/CGAL/draw_voronoi_diagram_2.h | 6 +++--- 3 files changed, 8 insertions(+), 5 deletions(-) diff --git a/Periodic_2_triangulation_2/doc/Periodic_2_triangulation_2/PackageDescription.txt b/Periodic_2_triangulation_2/doc/Periodic_2_triangulation_2/PackageDescription.txt index bdfc450c4a8..4f3a46a85b1 100644 --- a/Periodic_2_triangulation_2/doc/Periodic_2_triangulation_2/PackageDescription.txt +++ b/Periodic_2_triangulation_2/doc/Periodic_2_triangulation_2/PackageDescription.txt @@ -20,7 +20,7 @@ #include \endcode */ -/// \defgroup PkgPeriodic2Triangulation2Draw Draw a 2D Periodic Triangulation +/// \defgroup PkgDrawPeriodic2Triangulation2 Draw a 2D Periodic Triangulation /// \ingroup PkgPeriodic2Triangulation2Ref /*! @@ -111,5 +111,8 @@ of the concept `Periodic_2Offset_2`. - `CGAL::Periodic_2_triangulation_2::Iterator_type` - `CGAL::Periodic_2_triangulation_2::Locate_type` +\cgalCRPSection{Draw 2D Periodic Triangulation} + - \link PkgDrawPeriodic2Triangulation2 CGAL::draw() \endlink + */ diff --git a/Periodic_2_triangulation_2/doc/Periodic_2_triangulation_2/Periodic_2_triangulation_2.txt b/Periodic_2_triangulation_2/doc/Periodic_2_triangulation_2/Periodic_2_triangulation_2.txt index 4ebe43ddabb..843944cba95 100644 --- a/Periodic_2_triangulation_2/doc/Periodic_2_triangulation_2/Periodic_2_triangulation_2.txt +++ b/Periodic_2_triangulation_2/doc/Periodic_2_triangulation_2/Periodic_2_triangulation_2.txt @@ -396,7 +396,7 @@ in the unit rectangle. The tests were done on an Intel i7 @ 2.67GHz. \section P2T2_Draw_Periodic_Triangulation Draw a 2D Periodic Triangulation -A 2D periodic triangulation can be visualized by calling the 'CGAL::draw()' function as shown in the following example. This function opens a new window showing the given Periodic Triangulation. Elements of the periodic triangulation can be viewed in four different modes: +A 2D periodic triangulation can be visualized by calling the \link PkgDrawPeriodic2Triangulation2 CGAL::draw() \endlink function as shown in the following example. This function opens a new window showing the given Periodic Triangulation. Elements of the periodic triangulation can be viewed in four different modes: - STORED Display all geometric primitives as they are stored in Triangulation_data_structure_2 - UNIQUE Display only one representative of each geometric primitive even if the triangulation is computed in multiply sheeted covering space. diff --git a/Voronoi_diagram_2/doc/Voronoi_diagram_2/CGAL/draw_voronoi_diagram_2.h b/Voronoi_diagram_2/doc/Voronoi_diagram_2/CGAL/draw_voronoi_diagram_2.h index de954014d51..bc3bb64e1c6 100644 --- a/Voronoi_diagram_2/doc/Voronoi_diagram_2/CGAL/draw_voronoi_diagram_2.h +++ b/Voronoi_diagram_2/doc/Voronoi_diagram_2/CGAL/draw_voronoi_diagram_2.h @@ -3,11 +3,11 @@ namespace CGAL { /*! \ingroup PkgDrawVoronoiDiagram2 -Open a new window and draw `av2`, the `Voronoi_diagram_2` constructed from a Delaunay Graph which is a model of `DelaunayGraph_2` concept. +Opens a new window and draws `av2`, the `Voronoi_diagram_2` constructed from a Delaunay Graph which is a model of `DelaunayGraph_2` concept. The class `Voronoi_diagram_2` provides an adaptor to view a triangulated Delaunay graph as their dual subdivision, the -Voronoi diagram. The function is blocking, that is the program continues as soon as the user closes the window. +Voronoi diagram. 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 V2 a model of the `Voronoi2` concept. +\tparam V2 a model of the `AdaptationTraits_2` concept. \param av2 the voronoi diagram to draw. */ From 628b24e57fdeec2ea2b1236a30d3bf2db65ce37d Mon Sep 17 00:00:00 2001 From: Jasmeet Singh Date: Mon, 24 Jun 2019 18:14:13 -0700 Subject: [PATCH 083/363] Update headers, trying to deal with Travis CI errors. --- .../CGAL/draw_periodic_2_triangulation_2.h | 9 --------- .../include/CGAL/draw_voronoi_diagram_2.h | 15 +++------------ 2 files changed, 3 insertions(+), 21 deletions(-) diff --git a/Periodic_2_triangulation_2/include/CGAL/draw_periodic_2_triangulation_2.h b/Periodic_2_triangulation_2/include/CGAL/draw_periodic_2_triangulation_2.h index 8c25a218a52..2406915d842 100644 --- a/Periodic_2_triangulation_2/include/CGAL/draw_periodic_2_triangulation_2.h +++ b/Periodic_2_triangulation_2/include/CGAL/draw_periodic_2_triangulation_2.h @@ -296,13 +296,4 @@ void draw(const P2T2& ap2t2) #endif // CGAL_USE_BASIC_VIEWER -#else // CGAL_USE_BASIC_VIEWER - -template -void draw_periodic_2_triangulation_2(CGAL::Periodic_2_Triangulation_2&) -{ - std::cerr << "Impossible to draw, CGAL_USE_BASIC_VIEWER is not defined." - << std::endl; -} - #endif // DRAW_PERIODIC_2_TRIANGULATION_2_H diff --git a/Voronoi_diagram_2/include/CGAL/draw_voronoi_diagram_2.h b/Voronoi_diagram_2/include/CGAL/draw_voronoi_diagram_2.h index ad073532e7f..4b4e4a6c652 100644 --- a/Voronoi_diagram_2/include/CGAL/draw_voronoi_diagram_2.h +++ b/Voronoi_diagram_2/include/CGAL/draw_voronoi_diagram_2.h @@ -18,8 +18,8 @@ // // Author(s) : Jasmeet Singh -#ifndef CGAL_DRAW_VORONOI_H -#define CGAL_DRAW_VORONOI_H +#ifndef CGAL_DRAW_VORONOI_DIAGRAM_2_H +#define CGAL_DRAW_VORONOI_DIAGRAM_2_H #include #include @@ -355,15 +355,6 @@ template void draw(const V2 &av2) { } // End namespace CGAL -#else // CGAL_USE_BASIC_VIEWER - -template -void draw_voronoi_diagram_2(CGAL::VoronoiDiagram_2&) -{ - std::cerr << "Impossible to draw, CGAL_USE_BASIC_VIEWER is not defined." - << std::endl; -} - #endif // CGAL_USE_BASIC_VIEWER -#endif // CGAL_DRAW_VORONOI_H +#endif // CGAL_DRAW_VORONOI_DIAGRAM_2_H From 6c5bbe002e0b8ed4a0bb5faf2c720de7cdfd1d2a Mon Sep 17 00:00:00 2001 From: Guillaume Damiand Date: Tue, 25 Jun 2019 09:48:47 +0200 Subject: [PATCH 084/363] Small modifs in doc of new viewers. --- .../Periodic_2_triangulation_2.txt | 12 ++++++------ .../Voronoi_diagram_2/CGAL/draw_voronoi_diagram_2.h | 4 ++-- .../doc/Voronoi_diagram_2/Voronoi_diagram_2.txt | 2 +- 3 files changed, 9 insertions(+), 9 deletions(-) diff --git a/Periodic_2_triangulation_2/doc/Periodic_2_triangulation_2/Periodic_2_triangulation_2.txt b/Periodic_2_triangulation_2/doc/Periodic_2_triangulation_2/Periodic_2_triangulation_2.txt index 843944cba95..19a0f572fba 100644 --- a/Periodic_2_triangulation_2/doc/Periodic_2_triangulation_2/Periodic_2_triangulation_2.txt +++ b/Periodic_2_triangulation_2/doc/Periodic_2_triangulation_2/Periodic_2_triangulation_2.txt @@ -398,15 +398,15 @@ in the unit rectangle. The tests were done on an Intel i7 @ 2.67GHz. A 2D periodic triangulation can be visualized by calling the \link PkgDrawPeriodic2Triangulation2 CGAL::draw() \endlink function as shown in the following example. This function opens a new window showing the given Periodic Triangulation. Elements of the periodic triangulation can be viewed in four different modes: -- STORED Display all geometric primitives as they are stored in Triangulation_data_structure_2 -- UNIQUE Display only one representative of each geometric primitive even if the triangulation is computed in multiply sheeted covering space. -- STORED_COVER_DOMAIN Same as STORED but also display all primitives whose intersection with the original domain of the current covering space is non-empty -- UNIQUE_COVER_DOMAIN Same as UNIQUE but also display all primitives whose intersection with the original domain of the current covering space is non-empty +- STORED Display all geometric primitives as they are stored in Triangulation_data_structure_2; +- UNIQUE Display only one representative of each geometric primitive even if the triangulation is computed in multiply sheeted covering space; +- STORED_COVER_DOMAIN Same as STORED but also display all primitives whose intersection with the original domain of the current covering space is non-empty; +- UNIQUE_COVER_DOMAIN Same as UNIQUE but also display all primitives whose intersection with the original domain of the current covering space is non-empty. -The domain can also be visualized by a key press. To see how to visualize the Periodic Triangulation in various modes, press key H when the viewer window is active and go to Keyboard tab. See \cgalFigureRef{P2Triangulation2figdraw1} and \cgalFigureRef{P2Triangulation2figdraw2} +The domain can also be visualized by a key press. To see how to visualize the Periodic Triangulation in various modes, press key H when the viewer window is active and go to Keyboard tab. See \cgalFigureRef{P2Triangulation2figdraw1} and \cgalFigureRef{P2Triangulation2figdraw2}. \cgalFigureBegin{P2Triangulation2figdraw1, unique.png, unique-cover.png} -Result of the run of the draw_periodic_2_triangulation_2 program for display modes Unique(left) and Unique Cover Domain(right). The window allows to navigate through the 3D scene. +Result of the run of the draw_periodic_2_triangulation_2 program for display modes Unique(left) and Unique Cover Domain(right). The window allows to navigate through the 2D scene. \cgalFigureEnd \cgalFigureBegin{P2Triangulation2figdraw2, stored.png, stored-cover.png} Result of the run of the draw_periodic_2_triangulation_2 program for display modes Stored(left) and Stored Cover Domain(right). diff --git a/Voronoi_diagram_2/doc/Voronoi_diagram_2/CGAL/draw_voronoi_diagram_2.h b/Voronoi_diagram_2/doc/Voronoi_diagram_2/CGAL/draw_voronoi_diagram_2.h index bc3bb64e1c6..ef273cb1734 100644 --- a/Voronoi_diagram_2/doc/Voronoi_diagram_2/CGAL/draw_voronoi_diagram_2.h +++ b/Voronoi_diagram_2/doc/Voronoi_diagram_2/CGAL/draw_voronoi_diagram_2.h @@ -3,7 +3,7 @@ namespace CGAL { /*! \ingroup PkgDrawVoronoiDiagram2 -Opens a new window and draws `av2`, the `Voronoi_diagram_2` constructed from a Delaunay Graph which is a model of `DelaunayGraph_2` concept. +opens a new window and draws `av2`, the `Voronoi_diagram_2` constructed from a Delaunay Graph which is a model of `DelaunayGraph_2` concept. The class `Voronoi_diagram_2` provides an adaptor to view a triangulated Delaunay graph as their dual subdivision, the Voronoi diagram. 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. @@ -14,4 +14,4 @@ Voronoi diagram. A call to this function is blocking, that is the program contin template void draw(const V2& av2); -} /* namespace CGAL */ \ No newline at end of file +} /* namespace CGAL */ diff --git a/Voronoi_diagram_2/doc/Voronoi_diagram_2/Voronoi_diagram_2.txt b/Voronoi_diagram_2/doc/Voronoi_diagram_2/Voronoi_diagram_2.txt index e9fe5e9164e..41b3f9828cf 100644 --- a/Voronoi_diagram_2/doc/Voronoi_diagram_2/Voronoi_diagram_2.txt +++ b/Voronoi_diagram_2/doc/Voronoi_diagram_2/Voronoi_diagram_2.txt @@ -499,7 +499,7 @@ This function requires CGAL_Qt5, and is only available if the flag CGAL_USE_BASI \cgalFigureBegin{draw_voronoi_diagram, draw_voronoi_diagram.png} Result of the draw_voronoi_diagram_2 program. A window shows the Voronoi vertices and edges. -The window allows navigation through the 3D scene. +The window allows navigation through the 2D scene. \cgalFigureEnd */ From 02254e998e35cbf29f73680731e8e8e348d61ffa Mon Sep 17 00:00:00 2001 From: Jasmeet Singh Date: Tue, 25 Jun 2019 11:47:13 -0700 Subject: [PATCH 085/363] Add dependency in Voronoi doc. Add draw_periodic_2_triangulation_2.h --- .../CGAL/draw_periodic_2_triangulation_2.h | 15 +++++++++++++++ .../doc/Voronoi_diagram_2/dependencies | 1 + 2 files changed, 16 insertions(+) create mode 100644 Periodic_2_triangulation_2/doc/Periodic_2_triangulation_2/CGAL/draw_periodic_2_triangulation_2.h diff --git a/Periodic_2_triangulation_2/doc/Periodic_2_triangulation_2/CGAL/draw_periodic_2_triangulation_2.h b/Periodic_2_triangulation_2/doc/Periodic_2_triangulation_2/CGAL/draw_periodic_2_triangulation_2.h new file mode 100644 index 00000000000..e8d456cd261 --- /dev/null +++ b/Periodic_2_triangulation_2/doc/Periodic_2_triangulation_2/CGAL/draw_periodic_2_triangulation_2.h @@ -0,0 +1,15 @@ +namespace CGAL { + +/*! +\ingroup PkgDrawPeriodic2Triangulation2 + +Opens a new window and draws `ap2t2`, the `Periodic_2_Triangulation_2`. 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 P2T2 a model of the `Periodic_2TriangulationTraits_2` concept. +\param ap2t2 the 2D periodic trinagulation to draw. + +*/ +template +void draw(const P2T2& ap2t2); + +} /* namespace CGAL */ \ No newline at end of file diff --git a/Voronoi_diagram_2/doc/Voronoi_diagram_2/dependencies b/Voronoi_diagram_2/doc/Voronoi_diagram_2/dependencies index 8cd9d01cbec..e89d9d8be77 100644 --- a/Voronoi_diagram_2/doc/Voronoi_diagram_2/dependencies +++ b/Voronoi_diagram_2/doc/Voronoi_diagram_2/dependencies @@ -7,3 +7,4 @@ Stream_support Triangulation_2 Segment_Delaunay_graph_2 Apollonius_graph_2 +GraphicsView From 6843c2ed69105f4b50c85b9716e953ea14d54750 Mon Sep 17 00:00:00 2001 From: Jasmeet Singh Date: Thu, 27 Jun 2019 12:44:34 -0700 Subject: [PATCH 086/363] Add viewer for Nef Polyhedra. Only points viewed for now. File Buffer_for_vao.h modified to classify the ambiguous call to the function newell_single_step_3(). Added namespace identifier 'internal::' to avoid conflict with function in normal_vector_newell_3.h included in Nef_polyhedron_3.h --- GraphicsView/include/CGAL/Buffer_for_vao.h | 2 +- Nef_3/examples/Nef_3/CMakeLists.txt | 10 +- Nef_3/examples/Nef_3/draw_nef_3.cpp | 35 +++ Nef_3/include/CGAL/draw_nef_3.h | 259 +++++++++++++++++++++ 4 files changed, 304 insertions(+), 2 deletions(-) create mode 100644 Nef_3/examples/Nef_3/draw_nef_3.cpp create mode 100644 Nef_3/include/CGAL/draw_nef_3.h diff --git a/GraphicsView/include/CGAL/Buffer_for_vao.h b/GraphicsView/include/CGAL/Buffer_for_vao.h index efd188cd3f8..c89eaa6b81b 100644 --- a/GraphicsView/include/CGAL/Buffer_for_vao.h +++ b/GraphicsView/include/CGAL/Buffer_for_vao.h @@ -66,7 +66,7 @@ namespace internal unsigned int nb = 0; for (std::size_t i=0; i +#include +#include +#include +#include +#include +#include + +typedef CGAL::Exact_integer NT; +typedef CGAL::Extended_homogeneous Kernel; +typedef CGAL::Nef_polyhedron_3 Nef_polyhedron; +typedef Nef_polyhedron::Plane_3 Plane_3; +typedef CGAL::Polyhedron_3 Polyhedron; + +int main(int argc, char* argv[]) { + Nef_polyhedron N1(Plane_3( 1, 0, 0,-1),Nef_polyhedron::INCLUDED); + Nef_polyhedron N2(Plane_3(-1, 0, 0,-1),Nef_polyhedron::INCLUDED); + Nef_polyhedron N3(Plane_3( 0, 1, 0,-1),Nef_polyhedron::INCLUDED); + Nef_polyhedron N4(Plane_3( 0,-1, 0,-1),Nef_polyhedron::INCLUDED); + Nef_polyhedron N5(Plane_3( 0, 0, 1,-1),Nef_polyhedron::INCLUDED); + Nef_polyhedron N6(Plane_3( 0, 0,-1,-1),Nef_polyhedron::INCLUDED); + Nef_polyhedron I1(!N1+!N2); + Nef_polyhedron I2(N3-!N4); + Nef_polyhedron I3(N5^N6); + Nef_polyhedron Cube1(I2 *!I1); + Cube1 *= !I3; + //Nef_polyhedron Cube2 = N1 * N2 * N3 * N4 * N5 * N6; + //CGAL_assertion (Cube1 == Cube2); + +// Polyhedron P; +// Cube1.convert_to_Polyhedron(P); +// std::cout << P; + + CGAL::draw(Cube1); +} diff --git a/Nef_3/include/CGAL/draw_nef_3.h b/Nef_3/include/CGAL/draw_nef_3.h new file mode 100644 index 00000000000..a72ae2e910d --- /dev/null +++ b/Nef_3/include/CGAL/draw_nef_3.h @@ -0,0 +1,259 @@ +// Copyright (c) 2019 Max-Planck-Institute Saarbruecken (Germany). +// 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) : Jasmeet Singh + +#ifndef DRAW_NEF_3_H +#define DRAW_NEF_3_H + +#include +#include + +#ifdef CGAL_USE_BASIC_VIEWER + +//#include +#include + +namespace CGAL { + +// Default color functor; user can change it to have its own face color +struct DefaultColorFunctorNefPolyhedron +{ + template + static CGAL::Color run(const NefPolyhedron&, + typename NefPolyhedron::Halffacet_const_handle fh) + { + if (fh==boost::graph_traits::null_face()) // use to get the mono color + return CGAL::Color(100, 125, 200); // R G B between 0-255 + + CGAL::Random random((unsigned int)(std::size_t)(&(*fh))); + return get_random_color(random); + } +}; + +// Viewer class for Nef Polyhedron +template +class SimpleNefPolyhedronViewerQt : public Basic_viewer_qt +{ + typedef Basic_viewer_qt Base; + typedef typename Nef_Polyhedron::Kernel Kernel; + typedef typename Nef_Polyhedron::Vertex_const_iterator Vertex_const_iterator; + typedef typename Nef_Polyhedron::Vertex_const_handle Vertex_const_handle; + typedef typename Nef_Polyhedron::SNC_const_decorator SNC_const_decorator; + typedef typename Nef_Polyhedron::SNC_structure SNC_structure; +public: + /// Construct the viewer + /// @param anef the nef polyhedron to view + /// @param title the title of the window + /// @param anofaces if true, do not draw faces (faces are not + /// computed: this can be useful for big objects) + SimpleNefPolyhedronViewerQt(QWidget* parent, + const Nef_Polyhedron& anef, + const char* title="Basic Nef Polyhedron Viewer", + bool anofaces=false, + const ColorFunctor& fcolor=ColorFunctor()) : + //First draw: no vertex; edges, faces; mon-color; inverse normal + Base(parent, title, true, true, true, true, false), + nef(anef), + m_nofaces(anofaces), + m_fcolor(fcolor) + { + compute_elements(); + } +protected: +// void compute_face(Facet_const_handle fh) +// { +// CGAL::Color c=m_fcolor.run(poly, fh); +// face_begin(c); +// Halfedge_const_handle he=fh->facet_begin(); +// do +// { +// add_point_in_face(he->vertex()->point(), +// get_vertex_normal(he)); +// he=he->next(); +// } +// while (he!=fh->facet_begin()); +// face_end(); +// } + +// void compute_edge(Halfedge_const_handle he) +// { +// add_segment(he->vertex()->point(), +// he->opposite()->vertex()->point()); +// // We can use add_segment(p1, p2, c) with c a CGAL::Color to add a colored segment +// } + + void compute_vertex(Vertex_const_handle vh) + { + add_point(vh->point()); + // We can use add_point(p, c) with c a CGAL::Color to add a colored point + } + + void compute_elements() + { + clear(); + + + +// if (!m_nofaces) { +// for (typename Polyhedron_3::Facet_const_iterator f = poly.facets_begin(); +// f != poly.facets_end(); f++) +// { +// if (f != boost::graph_traits::null_face()) +// { +// compute_face(f); +// } +// } +// } + +// for (typename Polyhedron_3::Halfedge_const_iterator e = +// poly.halfedges_begin(); +// e != poly.halfedges_end(); ++e) +// { +// if (e < e->opposite()) +// { +// compute_edge(e); +// } +// } +// Vertex_const_iterator vi; +// SNC_structure sncp(nef.sncp()); +// SNC_const_decorator scd; +// CGAL_forall_vertices(v, scd) +// { + +// } + + Vertex_const_iterator vi; + for(vi = nef.vertices_begin(); vi != nef.vertices_end(); + vi++) + { + compute_vertex(vi); + } + } + + virtual void keyPressEvent(QKeyEvent *e) + { + // Test key pressed: + // const ::Qt::KeyboardModifiers modifiers = e->modifiers(); + // if ((e->key()==Qt::Key_PageUp) && (modifiers==Qt::NoButton)) { ... } + + // Call: * compute_elements() if the model changed, followed by + // * redraw() if some viewing parameters changed that implies some + // modifications of the buffers + // (eg. type of normal, color/mono) + // * update() just to update the drawing + + // Call the base method to process others/classicals key + Base::keyPressEvent(e); + } + +protected: +// Local_vector get_face_normal(Halfedge_const_handle he) +// { +// Local_vector normal = CGAL::NULL_VECTOR; +// Halfedge_const_handle end = he; +// unsigned int nb = 0; +// do +// { +// internal::newell_single_step_3( +// internal::Geom_utils::get_local_point(he->vertex()->point()), +// internal::Geom_utils::get_local_point( +// he->next()->vertex()->point()), +// normal); +// ++nb; +// he = he->next(); +// } while (he != end); +// assert(nb > 0); +// return (typename Local_kernel::Construct_scaled_vector_3()(normal, 1.0 / nb)); +// } + +// Local_vector get_vertex_normal(Halfedge_const_handle he) +// { +// Local_vector normal = CGAL::NULL_VECTOR; +// Halfedge_const_handle end = he; +// do +// { +// if (!he->is_border()) +// { +// Local_vector n = get_face_normal(he); +// normal = typename Local_kernel::Construct_sum_of_vectors_3()(normal, n); +// } +// he = he->next()->opposite(); +// } while (he != end); + +// if (!typename Local_kernel::Equal_3()(normal, CGAL::NULL_VECTOR)) +// { +// normal = (typename Local_kernel::Construct_scaled_vector_3()( +// normal, 1.0 / CGAL::sqrt(normal.squared_length()))); +// } + +// return normal; +// } + +protected: + const Nef_Polyhedron &nef; + bool m_nofaces; + const ColorFunctor &m_fcolor; +}; + +template +void draw(const Nef_Polyhedron &anef, const char *title, bool nofill, + const ColorFunctor &fcolor) +{ +#if defined(CGAL_TEST_SUITE) + bool cgal_test_suite = true; +#else + bool cgal_test_suite = false; +#endif + + if (!cgal_test_suite) + { + int argc = 1; + const char *argv[2] = {"nef_polyhedron_viewer", "\0"}; + QApplication app(argc, const_cast(argv)); + SimpleNefPolyhedronViewerQt mainwindow( + app.activeWindow(), anef, title, nofill, fcolor); + mainwindow.show(); + app.exec(); + } +} + +template +void draw(const Nef_Polyhedron &anef, const char *title, bool nofill) +{ + DefaultColorFunctorNefPolyhedron c; + draw(anef, title, nofill, c); +} + +template +void draw(const Nef_Polyhedron &anef, const char *title) +{ + draw(anef, title, false); +} + +template void draw(const Nef_Polyhedron &anef) +{ + draw(anef, "Basic Nef Polyhedron Viewer"); +} + +} // End namespace CGAL + +#endif // CGAL_USE_BASIC_VIEWER + +#endif // DRAW_NEF_3_H From 9995083b9ef841590098b8f65b0571313a300eab Mon Sep 17 00:00:00 2001 From: Jasmeet Singh Date: Fri, 28 Jun 2019 11:44:52 -0700 Subject: [PATCH 087/363] Add a visitor class to view the elements of Nef Polyhedron. Only vertices viewed for now. --- Nef_3/include/CGAL/draw_nef_3.h | 73 +++++++++++++++++++++++---------- 1 file changed, 51 insertions(+), 22 deletions(-) diff --git a/Nef_3/include/CGAL/draw_nef_3.h b/Nef_3/include/CGAL/draw_nef_3.h index a72ae2e910d..87a89a9d745 100644 --- a/Nef_3/include/CGAL/draw_nef_3.h +++ b/Nef_3/include/CGAL/draw_nef_3.h @@ -27,7 +27,7 @@ #ifdef CGAL_USE_BASIC_VIEWER -//#include +#include #include namespace CGAL { @@ -57,6 +57,18 @@ class SimpleNefPolyhedronViewerQt : public Basic_viewer_qt typedef typename Nef_Polyhedron::Vertex_const_handle Vertex_const_handle; typedef typename Nef_Polyhedron::SNC_const_decorator SNC_const_decorator; typedef typename Nef_Polyhedron::SNC_structure SNC_structure; + typedef typename SNC_structure::Infi_box Infi_box; + + typedef typename Nef_Polyhedron::Shell_entry_const_iterator Shell_entry_const_iterator; + typedef typename Nef_Polyhedron::SFace_const_handle SFace_const_handle; + typedef typename Nef_Polyhedron::Volume_const_iterator Volume_const_iterator; + + typedef typename Nef_Polyhedron::Halfedge_const_handle Halfedge_const_handle; + typedef typename Nef_Polyhedron::Halffacet_const_handle Halffacet_const_handle; + typedef typename Nef_Polyhedron::SHalfedge_const_handle SHalfedge_const_handle; + typedef typename Nef_Polyhedron::SHalfloop_const_handle SHalfloop_const_handle; + typedef typename Kernel::Point_3 Point_3; + public: /// Construct the viewer /// @param anef the nef polyhedron to view @@ -98,6 +110,23 @@ protected: // he->opposite()->vertex()->point()); // // We can use add_segment(p1, p2, c) with c a CGAL::Color to add a colored segment // } + class Nef_Visitor { + public: + Nef_Visitor(SimpleNefPolyhedronViewerQt &v) : viewer(v) {} + + void visit(Vertex_const_handle vh) { + viewer.add_point(vh->point()); + } + + void visit(Halfedge_const_handle ) {} + void visit(Halffacet_const_handle ) {} + void visit(SHalfedge_const_handle ) {} + void visit(SHalfloop_const_handle ) {} + void visit(SFace_const_handle ) {} + protected: + + SimpleNefPolyhedronViewerQt& viewer; + }; void compute_vertex(Vertex_const_handle vh) { @@ -109,19 +138,24 @@ protected: { clear(); + Vertex_const_iterator vi; + Volume_const_iterator c; + //SNC_structure sncp(nef.sncp()); + //SNC_const_decorator scd; + int ic = 0; + Nef_Visitor V(*this); + CGAL_forall_volumes(c, nef) + { + std::cout << "Volume " << ic++ << std::endl; + int is = 0; + Shell_entry_const_iterator it; + CGAL_forall_shells_of(it, c) + { + nef.visit_shell_objects(SFace_const_handle(it), V); + } -// if (!m_nofaces) { -// for (typename Polyhedron_3::Facet_const_iterator f = poly.facets_begin(); -// f != poly.facets_end(); f++) -// { -// if (f != boost::graph_traits::null_face()) -// { -// compute_face(f); -// } -// } -// } - + } // for (typename Polyhedron_3::Halfedge_const_iterator e = // poly.halfedges_begin(); // e != poly.halfedges_end(); ++e) @@ -131,20 +165,15 @@ protected: // compute_edge(e); // } // } -// Vertex_const_iterator vi; -// SNC_structure sncp(nef.sncp()); -// SNC_const_decorator scd; -// CGAL_forall_vertices(v, scd) + // { // } - Vertex_const_iterator vi; - for(vi = nef.vertices_begin(); vi != nef.vertices_end(); - vi++) - { - compute_vertex(vi); - } +// for (Vertex_const_iterator vi = nef.vertices_begin(); +// vi != nef.vertices_end(); vi++) { +// compute_vertex(vi); +// } } virtual void keyPressEvent(QKeyEvent *e) From 42c09f550d29b2914e14be409c7cdca3b05b9589 Mon Sep 17 00:00:00 2001 From: Jasmeet Singh Date: Fri, 28 Jun 2019 13:25:09 -0700 Subject: [PATCH 088/363] Add viewer for faces of Nef Polyhedron. --- Nef_3/include/CGAL/draw_nef_3.h | 37 ++++++++++++++++++++++++++++++++- 1 file changed, 36 insertions(+), 1 deletion(-) diff --git a/Nef_3/include/CGAL/draw_nef_3.h b/Nef_3/include/CGAL/draw_nef_3.h index 87a89a9d745..919d50786a9 100644 --- a/Nef_3/include/CGAL/draw_nef_3.h +++ b/Nef_3/include/CGAL/draw_nef_3.h @@ -28,6 +28,7 @@ #ifdef CGAL_USE_BASIC_VIEWER #include +#include #include namespace CGAL { @@ -59,6 +60,12 @@ class SimpleNefPolyhedronViewerQt : public Basic_viewer_qt typedef typename Nef_Polyhedron::SNC_structure SNC_structure; typedef typename SNC_structure::Infi_box Infi_box; + typedef typename SNC_structure::Halffacet_cycle_const_iterator + Halffacet_cycle_const_iterator; + + typedef typename SNC_structure::SHalfedge_around_facet_const_circulator + SHalfedge_around_facet_const_circulator; + typedef typename Nef_Polyhedron::Shell_entry_const_iterator Shell_entry_const_iterator; typedef typename Nef_Polyhedron::SFace_const_handle SFace_const_handle; typedef typename Nef_Polyhedron::Volume_const_iterator Volume_const_iterator; @@ -118,8 +125,36 @@ protected: viewer.add_point(vh->point()); } + void visit(Halffacet_const_handle opposite_facet) + { + SHalfedge_const_handle se; + Halffacet_cycle_const_iterator fc; + + Halffacet_const_handle f = opposite_facet->twin(); + + SHalfedge_around_facet_const_circulator sfc1(f->facet_cycles_begin()), + sfc2(sfc1); +// if(++f->facet_cycles_begin() != f->facet_cycles_end() || +// ++(++(++sfc1)) != sfc2) +// { +// ; +// } else +// { + viewer.face_begin(); + fc = f->facet_cycles_begin(); + se = SHalfedge_const_handle(fc); + CGAL_assertion(se!=0); + SHalfedge_around_facet_const_circulator hc_start(se); + SHalfedge_around_facet_const_circulator hc_end(hc_start); + CGAL_For_all(hc_start, hc_end) + { + viewer.add_point_in_face(hc_start->source()->center_vertex()->point()); + } + viewer.face_end(); +// } + } + void visit(Halfedge_const_handle ) {} - void visit(Halffacet_const_handle ) {} void visit(SHalfedge_const_handle ) {} void visit(SHalfloop_const_handle ) {} void visit(SFace_const_handle ) {} From 5b19e7d1a5c93d521f70ed10c12907f0ada01e63 Mon Sep 17 00:00:00 2001 From: Jasmeet Singh Date: Sat, 29 Jun 2019 14:25:43 -0700 Subject: [PATCH 089/363] Add debug output. Classify newell_single_step_3 function using namespace CGAL to avoid ambiguity. Add example file to draw. --- Nef_3/examples/Nef_3/data/cross.off | 85 +++++++++++++++++++++ Nef_3/examples/Nef_3/draw_nef_3.cpp | 72 +++++++++++------ Nef_3/include/CGAL/draw_nef_3.h | 17 ++++- Nef_3/include/CGAL/normal_vector_newell_3.h | 4 +- 4 files changed, 148 insertions(+), 30 deletions(-) create mode 100644 Nef_3/examples/Nef_3/data/cross.off diff --git a/Nef_3/examples/Nef_3/data/cross.off b/Nef_3/examples/Nef_3/data/cross.off new file mode 100644 index 00000000000..0f08a5b0f18 --- /dev/null +++ b/Nef_3/examples/Nef_3/data/cross.off @@ -0,0 +1,85 @@ +OFF +40 38 0 + +0 3 0 +1 3 0 +2 3 0 +2 4 0 +2 5 0 +3 5 0 +3 4 0 +3 3 0 +4 3 0 +5 3 0 +5 2 0 +4 2 0 +3 2 0 +3 1 0 +3 0 0 +2 0 0 +2 1 0 +2 2 0 +1 2 0 +0 2 0 + +0 3 1 +1 3 1 +2 3 1 +2 4 1 +2 5 1 +3 5 1 +3 4 1 +3 3 1 +4 3 1 +5 3 1 +5 2 1 +4 2 1 +3 2 1 +3 1 1 +3 0 1 +2 0 1 +2 1 1 +2 2 1 +1 2 1 +0 2 1 + +4 0 1 18 19 +4 1 2 17 18 +4 2 7 12 17 +4 2 3 6 7 +4 3 4 5 6 +4 7 8 11 12 +4 8 9 10 11 +4 12 13 16 17 +4 13 14 15 16 + +4 1 0 20 21 +4 2 1 21 22 +4 3 2 22 23 +4 4 3 23 24 +4 5 4 24 25 +4 6 5 25 26 +4 7 6 26 27 +4 8 7 27 28 +4 9 8 28 29 +4 10 9 29 30 +4 11 10 30 31 +4 12 11 31 32 +4 13 12 32 33 +4 14 13 33 34 +4 15 14 34 35 +4 16 15 35 36 +4 17 16 36 37 +4 18 17 37 38 +4 19 18 38 39 +4 0 19 39 20 + +4 39 38 21 20 +4 38 37 22 21 +4 37 32 27 22 +4 27 26 23 22 +4 26 25 24 23 +4 32 31 28 27 +4 31 30 29 28 +4 37 36 33 32 +4 36 35 34 33 diff --git a/Nef_3/examples/Nef_3/draw_nef_3.cpp b/Nef_3/examples/Nef_3/draw_nef_3.cpp index 3477ad76616..66a133f1f69 100644 --- a/Nef_3/examples/Nef_3/draw_nef_3.cpp +++ b/Nef_3/examples/Nef_3/draw_nef_3.cpp @@ -1,35 +1,57 @@ -#include -#include +#include +//#include #include #include #include +#include +#include + #include #include -typedef CGAL::Exact_integer NT; -typedef CGAL::Extended_homogeneous Kernel; -typedef CGAL::Nef_polyhedron_3 Nef_polyhedron; -typedef Nef_polyhedron::Plane_3 Plane_3; -typedef CGAL::Polyhedron_3 Polyhedron; +typedef CGAL::Exact_predicates_exact_constructions_kernel Kernel; +//typedef CGAL::Extended_homogeneous Kernel; +typedef CGAL::Surface_mesh Surface_mesh; +typedef CGAL::Nef_polyhedron_3 Nef_polyhedron; +typedef Nef_polyhedron::Plane_3 Plane_3; +typedef CGAL::Polyhedron_3 Polyhedron; -int main(int argc, char* argv[]) { - Nef_polyhedron N1(Plane_3( 1, 0, 0,-1),Nef_polyhedron::INCLUDED); - Nef_polyhedron N2(Plane_3(-1, 0, 0,-1),Nef_polyhedron::INCLUDED); - Nef_polyhedron N3(Plane_3( 0, 1, 0,-1),Nef_polyhedron::INCLUDED); - Nef_polyhedron N4(Plane_3( 0,-1, 0,-1),Nef_polyhedron::INCLUDED); - Nef_polyhedron N5(Plane_3( 0, 0, 1,-1),Nef_polyhedron::INCLUDED); - Nef_polyhedron N6(Plane_3( 0, 0,-1,-1),Nef_polyhedron::INCLUDED); - Nef_polyhedron I1(!N1+!N2); - Nef_polyhedron I2(N3-!N4); - Nef_polyhedron I3(N5^N6); - Nef_polyhedron Cube1(I2 *!I1); - Cube1 *= !I3; - //Nef_polyhedron Cube2 = N1 * N2 * N3 * N4 * N5 * N6; - //CGAL_assertion (Cube1 == Cube2); +int main(int argc, char *argv[]) +{ + Polyhedron P; + std::ifstream ifs((argc > 1) ? argv[1] : "data/cross.off"); + ifs >> P; + std::cout << "============== Polyhedron =============" << std::endl + << std::endl; + std::cout << P.size_of_vertices() << std::endl; + std::cout << P.size_of_halfedges() << std::endl; + std::cout << P.size_of_facets() << std::endl << std::endl; -// Polyhedron P; -// Cube1.convert_to_Polyhedron(P); -// std::cout << P; + Nef_polyhedron N(P); - CGAL::draw(Cube1); + std::cout << "================= Nef ==================" << std::endl + << std::endl; + std::cout << "Number of volumes: " << N.number_of_volumes() << std::endl; + std::cout << "Number of vertices: " << N.number_of_vertices() << std::endl; + std::cout << "Number of edges: " << N.number_of_edges() << std::endl; + std::cout << "Number of facets: " << N.number_of_facets() << std::endl + << std::endl; + std::cout << "Number of halfedges: " << N.number_of_halfedges() << std::endl; + std::cout << "Number of halffacets: " << N.number_of_halffacets() << std::endl + << std::endl; + std::cout << "Number of sfaces: " << N.number_of_sfaces() << std::endl; + std::cout << "Number of shalfedges : " << N.number_of_shalfedges() + << std::endl; + std::cout << "Number of shalfloops: " << N.number_of_shalfloops() << std::endl + << std::endl; + + // output the result into a Surface_mesh + Surface_mesh output; + CGAL::convert_nef_polyhedron_to_polygon_mesh(N, output); + std::ofstream out; + out.open("out.off"); + out << output; + out.close(); + + CGAL::draw(N); } diff --git a/Nef_3/include/CGAL/draw_nef_3.h b/Nef_3/include/CGAL/draw_nef_3.h index 919d50786a9..63347992e10 100644 --- a/Nef_3/include/CGAL/draw_nef_3.h +++ b/Nef_3/include/CGAL/draw_nef_3.h @@ -30,6 +30,7 @@ #include #include #include +#include namespace CGAL { @@ -119,7 +120,8 @@ protected: // } class Nef_Visitor { public: - Nef_Visitor(SimpleNefPolyhedronViewerQt &v) : viewer(v) {} + Nef_Visitor(SimpleNefPolyhedronViewerQt &v) + : viewer(v), done(), n_faces(0) {} void visit(Vertex_const_handle vh) { viewer.add_point(vh->point()); @@ -132,6 +134,12 @@ protected: Halffacet_const_handle f = opposite_facet->twin(); + if (done.find(f) != done.end() || + done.find(opposite_facet) != done.end()) + { + return; + } + SHalfedge_around_facet_const_circulator sfc1(f->facet_cycles_begin()), sfc2(sfc1); // if(++f->facet_cycles_begin() != f->facet_cycles_end() || @@ -151,6 +159,8 @@ protected: viewer.add_point_in_face(hc_start->source()->center_vertex()->point()); } viewer.face_end(); + done[f] = true; + n_faces++; // } } @@ -158,8 +168,9 @@ protected: void visit(SHalfedge_const_handle ) {} void visit(SHalfloop_const_handle ) {} void visit(SFace_const_handle ) {} + int n_faces; protected: - + std::unordered_map done; SimpleNefPolyhedronViewerQt& viewer; }; @@ -189,7 +200,7 @@ protected: { nef.visit_shell_objects(SFace_const_handle(it), V); } - + std::cout << "Faces drawn: " << V.n_faces << std::endl; } // for (typename Polyhedron_3::Halfedge_const_iterator e = // poly.halfedges_begin(); diff --git a/Nef_3/include/CGAL/normal_vector_newell_3.h b/Nef_3/include/CGAL/normal_vector_newell_3.h index a4231831c93..fbf59e04009 100644 --- a/Nef_3/include/CGAL/normal_vector_newell_3.h +++ b/Nef_3/include/CGAL/normal_vector_newell_3.h @@ -108,11 +108,11 @@ void normal_vector_newell_3( IC first, IC last, VertexPointMap vpm, Vector& n ) IC prev = first; ++first; while( first != last) { - newell_single_step_3( get(vpm,*prev), get(vpm,*first), n); + CGAL::newell_single_step_3( get(vpm,*prev), get(vpm,*first), n); prev = first; ++first; } - newell_single_step_3( get(vpm,*prev), get(vpm,*start_point), n); + CGAL::newell_single_step_3( get(vpm,*prev), get(vpm,*start_point), n); CGAL_NEF_TRACEN("newell normal vector "< Date: Sat, 29 Jun 2019 17:53:35 -0700 Subject: [PATCH 090/363] Add face normal computation. --- Nef_3/include/CGAL/draw_nef_3.h | 142 +++++++++++++------------------- 1 file changed, 56 insertions(+), 86 deletions(-) diff --git a/Nef_3/include/CGAL/draw_nef_3.h b/Nef_3/include/CGAL/draw_nef_3.h index 63347992e10..caf70b2fcbd 100644 --- a/Nef_3/include/CGAL/draw_nef_3.h +++ b/Nef_3/include/CGAL/draw_nef_3.h @@ -129,39 +129,34 @@ protected: void visit(Halffacet_const_handle opposite_facet) { - SHalfedge_const_handle se; - Halffacet_cycle_const_iterator fc; - Halffacet_const_handle f = opposite_facet->twin(); if (done.find(f) != done.end() || - done.find(opposite_facet) != done.end()) - { + done.find(opposite_facet) != done.end()) { return; } - SHalfedge_around_facet_const_circulator sfc1(f->facet_cycles_begin()), - sfc2(sfc1); -// if(++f->facet_cycles_begin() != f->facet_cycles_end() || -// ++(++(++sfc1)) != sfc2) -// { -// ; -// } else -// { - viewer.face_begin(); - fc = f->facet_cycles_begin(); - se = SHalfedge_const_handle(fc); - CGAL_assertion(se!=0); - SHalfedge_around_facet_const_circulator hc_start(se); - SHalfedge_around_facet_const_circulator hc_end(hc_start); - CGAL_For_all(hc_start, hc_end) - { - viewer.add_point_in_face(hc_start->source()->center_vertex()->point()); - } - viewer.face_end(); - done[f] = true; - n_faces++; -// } + SHalfedge_const_handle se; + Halffacet_cycle_const_iterator fc; + fc = f->facet_cycles_begin(); + + se = SHalfedge_const_handle(fc); // non-zero if shalfedge is returned + if(se == 0) + { //return if not-shalfedge + return; + } + + viewer.face_begin(CGAL::Color(yellow())); + + SHalfedge_around_facet_const_circulator hc_start(se); + SHalfedge_around_facet_const_circulator hc_end(hc_start); + CGAL_For_all(hc_start, hc_end) { + viewer.add_point_in_face(hc_start->source()->center_vertex()->point(), + viewer.get_vertex_normal(hc_start)); + } + viewer.face_end(); + done[f] = true; + n_faces++; } void visit(Halfedge_const_handle ) {} @@ -184,10 +179,7 @@ protected: { clear(); - Vertex_const_iterator vi; Volume_const_iterator c; - //SNC_structure sncp(nef.sncp()); - //SNC_const_decorator scd; int ic = 0; Nef_Visitor V(*this); @@ -202,24 +194,6 @@ protected: } std::cout << "Faces drawn: " << V.n_faces << std::endl; } -// for (typename Polyhedron_3::Halfedge_const_iterator e = -// poly.halfedges_begin(); -// e != poly.halfedges_end(); ++e) -// { -// if (e < e->opposite()) -// { -// compute_edge(e); -// } -// } - -// { - -// } - -// for (Vertex_const_iterator vi = nef.vertices_begin(); -// vi != nef.vertices_end(); vi++) { -// compute_vertex(vi); -// } } virtual void keyPressEvent(QKeyEvent *e) @@ -239,47 +213,43 @@ protected: } protected: -// Local_vector get_face_normal(Halfedge_const_handle he) -// { -// Local_vector normal = CGAL::NULL_VECTOR; -// Halfedge_const_handle end = he; -// unsigned int nb = 0; -// do -// { -// internal::newell_single_step_3( -// internal::Geom_utils::get_local_point(he->vertex()->point()), -// internal::Geom_utils::get_local_point( -// he->next()->vertex()->point()), -// normal); -// ++nb; -// he = he->next(); -// } while (he != end); -// assert(nb > 0); -// return (typename Local_kernel::Construct_scaled_vector_3()(normal, 1.0 / nb)); -// } + Local_vector get_face_normal(SHalfedge_around_facet_const_circulator he) + { + Local_vector normal = CGAL::NULL_VECTOR; + SHalfedge_around_facet_const_circulator end = he; + unsigned int nb = 0; -// Local_vector get_vertex_normal(Halfedge_const_handle he) -// { -// Local_vector normal = CGAL::NULL_VECTOR; -// Halfedge_const_handle end = he; -// do -// { -// if (!he->is_border()) -// { -// Local_vector n = get_face_normal(he); -// normal = typename Local_kernel::Construct_sum_of_vectors_3()(normal, n); -// } -// he = he->next()->opposite(); -// } while (he != end); + CGAL_For_all(he, end) + { + internal::newell_single_step_3(internal::Geom_utils::get_local_point(he->source()->center_vertex()->point()), + internal::Geom_utils::get_local_point(he->next()->source()->center_vertex()->point()), + normal); + ++nb; + } -// if (!typename Local_kernel::Equal_3()(normal, CGAL::NULL_VECTOR)) -// { -// normal = (typename Local_kernel::Construct_scaled_vector_3()( -// normal, 1.0 / CGAL::sqrt(normal.squared_length()))); -// } + assert(nb > 0); + return (typename Local_kernel::Construct_scaled_vector_3()(normal, 1.0 / nb)); + } -// return normal; -// } + Local_vector get_vertex_normal(SHalfedge_around_facet_const_circulator he) + { + Local_vector normal = CGAL::NULL_VECTOR; + SHalfedge_around_facet_const_circulator end = he; + + CGAL_For_all(he, end) + { + Local_vector n = get_face_normal(he); + normal = typename Local_kernel::Construct_sum_of_vectors_3()(normal, n); + } + + if (!typename Local_kernel::Equal_3()(normal, CGAL::NULL_VECTOR)) + { + normal = (typename Local_kernel::Construct_scaled_vector_3()( + normal, 1.0 / CGAL::sqrt(normal.squared_length()))); + } + + return normal; + } protected: const Nef_Polyhedron &nef; From 625ab7583d0efa3897318c28add4930567879fc0 Mon Sep 17 00:00:00 2001 From: Jasmeet Singh Date: Sat, 29 Jun 2019 18:08:07 -0700 Subject: [PATCH 091/363] Count and tally the number of edges drawn for validation. --- Nef_3/examples/Nef_3/draw_nef_3.cpp | 7 ++-- Nef_3/include/CGAL/draw_nef_3.h | 53 ++++++++++++++--------------- 2 files changed, 29 insertions(+), 31 deletions(-) diff --git a/Nef_3/examples/Nef_3/draw_nef_3.cpp b/Nef_3/examples/Nef_3/draw_nef_3.cpp index 66a133f1f69..3c4a422b2b9 100644 --- a/Nef_3/examples/Nef_3/draw_nef_3.cpp +++ b/Nef_3/examples/Nef_3/draw_nef_3.cpp @@ -23,9 +23,10 @@ int main(int argc, char *argv[]) ifs >> P; std::cout << "============== Polyhedron =============" << std::endl << std::endl; - std::cout << P.size_of_vertices() << std::endl; - std::cout << P.size_of_halfedges() << std::endl; - std::cout << P.size_of_facets() << std::endl << std::endl; + std::cout << "Number of vertices: " << P.size_of_vertices() << std::endl; + std::cout << "Number of halfedges: " << P.size_of_halfedges() << std::endl; + std::cout << "Number of facets: " << P.size_of_facets() << std::endl + << std::endl; Nef_polyhedron N(P); diff --git a/Nef_3/include/CGAL/draw_nef_3.h b/Nef_3/include/CGAL/draw_nef_3.h index caf70b2fcbd..049db660e9e 100644 --- a/Nef_3/include/CGAL/draw_nef_3.h +++ b/Nef_3/include/CGAL/draw_nef_3.h @@ -97,31 +97,10 @@ public: compute_elements(); } protected: -// void compute_face(Facet_const_handle fh) -// { -// CGAL::Color c=m_fcolor.run(poly, fh); -// face_begin(c); -// Halfedge_const_handle he=fh->facet_begin(); -// do -// { -// add_point_in_face(he->vertex()->point(), -// get_vertex_normal(he)); -// he=he->next(); -// } -// while (he!=fh->facet_begin()); -// face_end(); -// } - -// void compute_edge(Halfedge_const_handle he) -// { -// add_segment(he->vertex()->point(), -// he->opposite()->vertex()->point()); -// // We can use add_segment(p1, p2, c) with c a CGAL::Color to add a colored segment -// } class Nef_Visitor { public: Nef_Visitor(SimpleNefPolyhedronViewerQt &v) - : viewer(v), done(), n_faces(0) {} + : viewer(v), facets_done(), n_faces(0), n_edges(0) {} void visit(Vertex_const_handle vh) { viewer.add_point(vh->point()); @@ -131,8 +110,8 @@ protected: { Halffacet_const_handle f = opposite_facet->twin(); - if (done.find(f) != done.end() || - done.find(opposite_facet) != done.end()) { + if (facets_done.find(f) != facets_done.end() || + facets_done.find(opposite_facet) != facets_done.end()) { return; } @@ -155,17 +134,33 @@ protected: viewer.get_vertex_normal(hc_start)); } viewer.face_end(); - done[f] = true; + facets_done[f] = true; n_faces++; } - void visit(Halfedge_const_handle ) {} + void visit(Halfedge_const_handle he) + { + Halfedge_const_handle twin = he->twin(); + if (edges_done.find(he) != edges_done.end() || + edges_done.find(twin) != edges_done.end()) + { + // Edge already added + return; + } + + viewer.add_segment(he->source()->point(), he->target()->point()); + edges_done[he] = true; + n_edges++; + } + void visit(SHalfedge_const_handle ) {} void visit(SHalfloop_const_handle ) {} void visit(SFace_const_handle ) {} int n_faces; + int n_edges; protected: - std::unordered_map done; + std::unordered_map facets_done; + std::unordered_map edges_done; SimpleNefPolyhedronViewerQt& viewer; }; @@ -192,8 +187,10 @@ protected: { nef.visit_shell_objects(SFace_const_handle(it), V); } - std::cout << "Faces drawn: " << V.n_faces << std::endl; } + + std::cout << "Total faces drawn: " << V.n_faces << std::endl; + std::cout << "Total edges drawn: " << V.n_edges << std::endl; } virtual void keyPressEvent(QKeyEvent *e) From 16992e743e2bcb2a25629be623a640aa981329dd Mon Sep 17 00:00:00 2001 From: Jasmeet Singh Date: Sat, 29 Jun 2019 19:12:43 -0700 Subject: [PATCH 092/363] Add color to faces. Code cleanup --- Nef_3/examples/Nef_3/draw_nef_3.cpp | 2 ++ Nef_3/include/CGAL/draw_nef_3.h | 33 ++++++++++++++--------------- 2 files changed, 18 insertions(+), 17 deletions(-) diff --git a/Nef_3/examples/Nef_3/draw_nef_3.cpp b/Nef_3/examples/Nef_3/draw_nef_3.cpp index 3c4a422b2b9..d15584675db 100644 --- a/Nef_3/examples/Nef_3/draw_nef_3.cpp +++ b/Nef_3/examples/Nef_3/draw_nef_3.cpp @@ -1,4 +1,5 @@ #include +//#include //#include #include #include @@ -10,6 +11,7 @@ #include typedef CGAL::Exact_predicates_exact_constructions_kernel Kernel; +//typedef CGAL::Exact_integer NT; //typedef CGAL::Extended_homogeneous Kernel; typedef CGAL::Surface_mesh Surface_mesh; typedef CGAL::Nef_polyhedron_3 Nef_polyhedron; diff --git a/Nef_3/include/CGAL/draw_nef_3.h b/Nef_3/include/CGAL/draw_nef_3.h index 049db660e9e..9ccbd0e4575 100644 --- a/Nef_3/include/CGAL/draw_nef_3.h +++ b/Nef_3/include/CGAL/draw_nef_3.h @@ -41,8 +41,8 @@ struct DefaultColorFunctorNefPolyhedron static CGAL::Color run(const NefPolyhedron&, typename NefPolyhedron::Halffacet_const_handle fh) { - if (fh==boost::graph_traits::null_face()) // use to get the mono color - return CGAL::Color(100, 125, 200); // R G B between 0-255 + //if (fh==boost::graph_traits::null_face()) // use to get the mono color + // return CGAL::Color(100, 125, 200); // R G B between 0-255 CGAL::Random random((unsigned int)(std::size_t)(&(*fh))); return get_random_color(random); @@ -55,12 +55,8 @@ class SimpleNefPolyhedronViewerQt : public Basic_viewer_qt { typedef Basic_viewer_qt Base; typedef typename Nef_Polyhedron::Kernel Kernel; - typedef typename Nef_Polyhedron::Vertex_const_iterator Vertex_const_iterator; typedef typename Nef_Polyhedron::Vertex_const_handle Vertex_const_handle; - typedef typename Nef_Polyhedron::SNC_const_decorator SNC_const_decorator; typedef typename Nef_Polyhedron::SNC_structure SNC_structure; - typedef typename SNC_structure::Infi_box Infi_box; - typedef typename SNC_structure::Halffacet_cycle_const_iterator Halffacet_cycle_const_iterator; @@ -71,12 +67,10 @@ class SimpleNefPolyhedronViewerQt : public Basic_viewer_qt typedef typename Nef_Polyhedron::SFace_const_handle SFace_const_handle; typedef typename Nef_Polyhedron::Volume_const_iterator Volume_const_iterator; - typedef typename Nef_Polyhedron::Halfedge_const_handle Halfedge_const_handle; - typedef typename Nef_Polyhedron::Halffacet_const_handle Halffacet_const_handle; - typedef typename Nef_Polyhedron::SHalfedge_const_handle SHalfedge_const_handle; - typedef typename Nef_Polyhedron::SHalfloop_const_handle SHalfloop_const_handle; - typedef typename Kernel::Point_3 Point_3; - + typedef typename Nef_Polyhedron::Halfedge_const_handle Halfedge_const_handle; + typedef typename Nef_Polyhedron::Halffacet_const_handle Halffacet_const_handle; + typedef typename Nef_Polyhedron::SHalfedge_const_handle SHalfedge_const_handle; + typedef typename Nef_Polyhedron::SHalfloop_const_handle SHalfloop_const_handle; public: /// Construct the viewer /// @param anef the nef polyhedron to view @@ -88,8 +82,8 @@ public: const char* title="Basic Nef Polyhedron Viewer", bool anofaces=false, const ColorFunctor& fcolor=ColorFunctor()) : - //First draw: no vertex; edges, faces; mon-color; inverse normal - Base(parent, title, true, true, true, true, false), + //First draw: vertex; edges, faces; mon-color; inverse normal + Base(parent, title, true, true, true, false, false), nef(anef), m_nofaces(anofaces), m_fcolor(fcolor) @@ -97,6 +91,7 @@ public: compute_elements(); } protected: + // Visitor class to iterate through shell objects class Nef_Visitor { public: Nef_Visitor(SimpleNefPolyhedronViewerQt &v) @@ -125,7 +120,8 @@ protected: return; } - viewer.face_begin(CGAL::Color(yellow())); + CGAL::Color c = viewer.run_color(f); + viewer.face_begin(c); SHalfedge_around_facet_const_circulator hc_start(se); SHalfedge_around_facet_const_circulator hc_end(hc_start); @@ -176,11 +172,9 @@ protected: Volume_const_iterator c; - int ic = 0; Nef_Visitor V(*this); CGAL_forall_volumes(c, nef) { - std::cout << "Volume " << ic++ << std::endl; int is = 0; Shell_entry_const_iterator it; CGAL_forall_shells_of(it, c) @@ -193,6 +187,11 @@ protected: std::cout << "Total edges drawn: " << V.n_edges << std::endl; } + CGAL::Color run_color(Halffacet_const_handle fh) + { + return m_fcolor.run(nef, fh); + } + virtual void keyPressEvent(QKeyEvent *e) { // Test key pressed: From ae40ed9343ee8f43aaa2efd5063d54ce8677b92f Mon Sep 17 00:00:00 2001 From: Jasmeet Singh Date: Tue, 2 Jul 2019 16:32:59 -0700 Subject: [PATCH 093/363] Update dependencies --- .../package_info/Periodic_2_triangulation_2/dependencies | 1 + 1 file changed, 1 insertion(+) diff --git a/Periodic_2_triangulation_2/package_info/Periodic_2_triangulation_2/dependencies b/Periodic_2_triangulation_2/package_info/Periodic_2_triangulation_2/dependencies index 9ee86e3775d..a78447643d8 100644 --- a/Periodic_2_triangulation_2/package_info/Periodic_2_triangulation_2/dependencies +++ b/Periodic_2_triangulation_2/package_info/Periodic_2_triangulation_2/dependencies @@ -4,6 +4,7 @@ Circulator Distance_2 Distance_3 Filtered_kernel +GraphicsView Hash_map Installation Intersections_2 From ac5b76c0d10bb4cc71ddb43017c0853cbbdf3f73 Mon Sep 17 00:00:00 2001 From: Jasmeet Singh Date: Tue, 2 Jul 2019 16:35:53 -0700 Subject: [PATCH 094/363] Remove unused compute_vertex() method, display nef in one color --- Nef_3/include/CGAL/draw_nef_3.h | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) diff --git a/Nef_3/include/CGAL/draw_nef_3.h b/Nef_3/include/CGAL/draw_nef_3.h index 9ccbd0e4575..9e661641daa 100644 --- a/Nef_3/include/CGAL/draw_nef_3.h +++ b/Nef_3/include/CGAL/draw_nef_3.h @@ -42,7 +42,7 @@ struct DefaultColorFunctorNefPolyhedron typename NefPolyhedron::Halffacet_const_handle fh) { //if (fh==boost::graph_traits::null_face()) // use to get the mono color - // return CGAL::Color(100, 125, 200); // R G B between 0-255 + return CGAL::Color(100, 125, 200); // R G B between 0-255 CGAL::Random random((unsigned int)(std::size_t)(&(*fh))); return get_random_color(random); @@ -160,12 +160,6 @@ protected: SimpleNefPolyhedronViewerQt& viewer; }; - void compute_vertex(Vertex_const_handle vh) - { - add_point(vh->point()); - // We can use add_point(p, c) with c a CGAL::Color to add a colored point - } - void compute_elements() { clear(); From e5986189a55fc406cad53f310e934bea89686fc0 Mon Sep 17 00:00:00 2001 From: Jasmeet Singh Date: Wed, 3 Jul 2019 13:53:08 -0700 Subject: [PATCH 095/363] Correct vertex normals. Gourard Shading works. --- Nef_3/include/CGAL/draw_nef_3.h | 49 +++++++++++++++++---------------- 1 file changed, 25 insertions(+), 24 deletions(-) diff --git a/Nef_3/include/CGAL/draw_nef_3.h b/Nef_3/include/CGAL/draw_nef_3.h index 9e661641daa..bf47c9b9a2f 100644 --- a/Nef_3/include/CGAL/draw_nef_3.h +++ b/Nef_3/include/CGAL/draw_nef_3.h @@ -41,7 +41,7 @@ struct DefaultColorFunctorNefPolyhedron static CGAL::Color run(const NefPolyhedron&, typename NefPolyhedron::Halffacet_const_handle fh) { - //if (fh==boost::graph_traits::null_face()) // use to get the mono color + if (fh == nullptr) // use to get the mono color return CGAL::Color(100, 125, 200); // R G B between 0-255 CGAL::Random random((unsigned int)(std::size_t)(&(*fh))); @@ -55,22 +55,21 @@ class SimpleNefPolyhedronViewerQt : public Basic_viewer_qt { typedef Basic_viewer_qt Base; typedef typename Nef_Polyhedron::Kernel Kernel; - typedef typename Nef_Polyhedron::Vertex_const_handle Vertex_const_handle; - typedef typename Nef_Polyhedron::SNC_structure SNC_structure; - typedef typename SNC_structure::Halffacet_cycle_const_iterator - Halffacet_cycle_const_iterator; - typedef typename SNC_structure::SHalfedge_around_facet_const_circulator - SHalfedge_around_facet_const_circulator; + typedef typename Nef_Polyhedron::Halffacet_cycle_const_iterator Halffacet_cycle_const_iterator; + typedef typename Nef_Polyhedron::SHalfedge_around_facet_const_circulator SHalfedge_around_facet_const_circulator; - typedef typename Nef_Polyhedron::Shell_entry_const_iterator Shell_entry_const_iterator; - typedef typename Nef_Polyhedron::SFace_const_handle SFace_const_handle; - typedef typename Nef_Polyhedron::Volume_const_iterator Volume_const_iterator; + typedef typename Nef_Polyhedron::Shell_entry_const_iterator Shell_entry_const_iterator; + typedef typename Nef_Polyhedron::SHalfedge_const_iterator SHalfedge_const_iterator; + typedef typename Nef_Polyhedron::Volume_const_iterator Volume_const_iterator; + typedef typename Nef_Polyhedron::Vertex_const_handle Vertex_const_handle; + typedef typename Nef_Polyhedron::SFace_const_handle SFace_const_handle; typedef typename Nef_Polyhedron::Halfedge_const_handle Halfedge_const_handle; typedef typename Nef_Polyhedron::Halffacet_const_handle Halffacet_const_handle; typedef typename Nef_Polyhedron::SHalfedge_const_handle SHalfedge_const_handle; typedef typename Nef_Polyhedron::SHalfloop_const_handle SHalfloop_const_handle; + public: /// Construct the viewer /// @param anef the nef polyhedron to view @@ -83,7 +82,7 @@ public: bool anofaces=false, const ColorFunctor& fcolor=ColorFunctor()) : //First draw: vertex; edges, faces; mon-color; inverse normal - Base(parent, title, true, true, true, false, false), + Base(parent, title, false, true, true, true, false), nef(anef), m_nofaces(anofaces), m_fcolor(fcolor) @@ -126,8 +125,9 @@ protected: SHalfedge_around_facet_const_circulator hc_start(se); SHalfedge_around_facet_const_circulator hc_end(hc_start); CGAL_For_all(hc_start, hc_end) { - viewer.add_point_in_face(hc_start->source()->center_vertex()->point(), - viewer.get_vertex_normal(hc_start)); + Vertex_const_handle vh = hc_start->source()->center_vertex(); + viewer.add_point_in_face(vh->point(), + viewer.get_vertex_normal(vh)); } viewer.face_end(); facets_done[f] = true; @@ -177,8 +177,7 @@ protected: } } - std::cout << "Total faces drawn: " << V.n_faces << std::endl; - std::cout << "Total edges drawn: " << V.n_edges << std::endl; + negate_all_normals(); } CGAL::Color run_color(Halffacet_const_handle fh) @@ -203,16 +202,17 @@ protected: } protected: - Local_vector get_face_normal(SHalfedge_around_facet_const_circulator he) + Local_vector get_face_normal(SHalfedge_const_handle she) { + SHalfedge_around_facet_const_circulator he(she); Local_vector normal = CGAL::NULL_VECTOR; SHalfedge_around_facet_const_circulator end = he; unsigned int nb = 0; CGAL_For_all(he, end) { - internal::newell_single_step_3(internal::Geom_utils::get_local_point(he->source()->center_vertex()->point()), - internal::Geom_utils::get_local_point(he->next()->source()->center_vertex()->point()), + internal::newell_single_step_3(internal::Geom_utils::get_local_point(he->next()->source()->center_vertex()->point()), + internal::Geom_utils::get_local_point(he->source()->center_vertex()->point()), normal); ++nb; } @@ -221,16 +221,17 @@ protected: return (typename Local_kernel::Construct_scaled_vector_3()(normal, 1.0 / nb)); } - Local_vector get_vertex_normal(SHalfedge_around_facet_const_circulator he) + Local_vector get_vertex_normal(Vertex_const_handle vh) { Local_vector normal = CGAL::NULL_VECTOR; - SHalfedge_around_facet_const_circulator end = he; - CGAL_For_all(he, end) - { - Local_vector n = get_face_normal(he); + SHalfedge_const_iterator it = vh->shalfedges_begin(); + SHalfedge_const_handle end = it; + do { + Local_vector n = get_face_normal(it); normal = typename Local_kernel::Construct_sum_of_vectors_3()(normal, n); - } + it = it->snext(); + } while( it != end ); if (!typename Local_kernel::Equal_3()(normal, CGAL::NULL_VECTOR)) { From 53bed9f541120220f1c2d8eb596e36c315950e28 Mon Sep 17 00:00:00 2001 From: Jasmeet Singh Date: Wed, 3 Jul 2019 13:57:51 -0700 Subject: [PATCH 096/363] Clean up draw_nef_3 example --- Nef_3/examples/Nef_3/draw_nef_3.cpp | 49 +++++------------------------ 1 file changed, 8 insertions(+), 41 deletions(-) diff --git a/Nef_3/examples/Nef_3/draw_nef_3.cpp b/Nef_3/examples/Nef_3/draw_nef_3.cpp index d15584675db..06727eac187 100644 --- a/Nef_3/examples/Nef_3/draw_nef_3.cpp +++ b/Nef_3/examples/Nef_3/draw_nef_3.cpp @@ -1,60 +1,27 @@ #include -//#include -//#include #include #include #include -#include -#include #include #include -typedef CGAL::Exact_predicates_exact_constructions_kernel Kernel; -//typedef CGAL::Exact_integer NT; -//typedef CGAL::Extended_homogeneous Kernel; -typedef CGAL::Surface_mesh Surface_mesh; -typedef CGAL::Nef_polyhedron_3 Nef_polyhedron; -typedef Nef_polyhedron::Plane_3 Plane_3; -typedef CGAL::Polyhedron_3 Polyhedron; +typedef CGAL::Exact_predicates_exact_constructions_kernel Kernel; +typedef CGAL::Polyhedron_3 Polyhedron; +typedef CGAL::Nef_polyhedron_3 Nef_polyhedron; int main(int argc, char *argv[]) { + // read OFF file into a polyhedron Polyhedron P; std::ifstream ifs((argc > 1) ? argv[1] : "data/cross.off"); ifs >> P; - std::cout << "============== Polyhedron =============" << std::endl - << std::endl; - std::cout << "Number of vertices: " << P.size_of_vertices() << std::endl; - std::cout << "Number of halfedges: " << P.size_of_halfedges() << std::endl; - std::cout << "Number of facets: " << P.size_of_facets() << std::endl - << std::endl; + // initialize nef from polyhedron Nef_polyhedron N(P); - std::cout << "================= Nef ==================" << std::endl - << std::endl; - std::cout << "Number of volumes: " << N.number_of_volumes() << std::endl; - std::cout << "Number of vertices: " << N.number_of_vertices() << std::endl; - std::cout << "Number of edges: " << N.number_of_edges() << std::endl; - std::cout << "Number of facets: " << N.number_of_facets() << std::endl - << std::endl; - std::cout << "Number of halfedges: " << N.number_of_halfedges() << std::endl; - std::cout << "Number of halffacets: " << N.number_of_halffacets() << std::endl - << std::endl; - std::cout << "Number of sfaces: " << N.number_of_sfaces() << std::endl; - std::cout << "Number of shalfedges : " << N.number_of_shalfedges() - << std::endl; - std::cout << "Number of shalfloops: " << N.number_of_shalfloops() << std::endl - << std::endl; - - // output the result into a Surface_mesh - Surface_mesh output; - CGAL::convert_nef_polyhedron_to_polygon_mesh(N, output); - std::ofstream out; - out.open("out.off"); - out << output; - out.close(); - + // draw Nef Polyhedron CGAL::draw(N); + + return EXIT_SUCCESS; } From ff2a498d9edb4f7bdef3ca06345e04d5020d39e2 Mon Sep 17 00:00:00 2001 From: Jasmeet Singh Date: Wed, 3 Jul 2019 15:06:13 -0700 Subject: [PATCH 097/363] Add documentation for Nef Polyhedron Viewer. --- Nef_3/doc/Nef_3/Nef_3.txt | 12 ++++++++++++ Nef_3/doc/Nef_3/PackageDescription.txt | 10 ++++++++++ Nef_3/doc/Nef_3/dependencies | 1 + Nef_3/doc/Nef_3/examples.txt | 1 + Nef_3/doc/Nef_3/fig/draw_nef_3.png | Bin 0 -> 20712 bytes Nef_3/package_info/Nef_3/dependencies | 1 + .../Periodic_2_triangulation_2.txt | 2 ++ 7 files changed, 27 insertions(+) create mode 100644 Nef_3/doc/Nef_3/fig/draw_nef_3.png diff --git a/Nef_3/doc/Nef_3/Nef_3.txt b/Nef_3/doc/Nef_3/Nef_3.txt index b1bd50533b8..c4d45087f12 100644 --- a/Nef_3/doc/Nef_3/Nef_3.txt +++ b/Nef_3/doc/Nef_3/Nef_3.txt @@ -425,6 +425,18 @@ the symbolical value, large but finite, for the size of the infimaximal box. \cgalExample{Nef_3/extended_kernel.cpp} +\subsection Nef_3DrawNefPolyhedron Draw a Nef Polyhedron + +A nef polyhedron can be visualised by calling the \link PkgDrawNef3 CGAL::draw() \endlink function as shown in the following example. This function opens a new window showing the given Nef Polyhedron. + +\cgalExample{Nef_3/draw_nef_3.cpp} + +This function requires CGAL_Qt5, and is only available if the flag CGAL_USE_BASIC_VIEWER is defined at compile time. + +\cgalFigureBegin{fig_draw_nef_polyhedron, draw_nef_3.png} +Result of the run of the draw_nef_3 program. A window shows the nef polyhedron and allows to navigate through the 3D scene. +\cgalFigureEnd + \section Nef_3File File I/O \anchor sectionNef_3IO diff --git a/Nef_3/doc/Nef_3/PackageDescription.txt b/Nef_3/doc/Nef_3/PackageDescription.txt index b8a0ab9c5e1..91de0089d8d 100644 --- a/Nef_3/doc/Nef_3/PackageDescription.txt +++ b/Nef_3/doc/Nef_3/PackageDescription.txt @@ -3,6 +3,13 @@ /// \defgroup PkgNef3IOFunctions I/O Functions /// \ingroup PkgNef3Ref +/*! Draw. + \code + #include + \endcode +*/ +/// \defgroup PkgDrawNef3 Draw a Nef Polyhedron +/// \ingroup PkgNef3Ref /*! \addtogroup PkgNef3Ref @@ -64,5 +71,8 @@ a simple OpenGL visualization for debugging and illustrations. - \link PkgNef3IOFunctions `CGAL::operator<<()` \endlink - \link PkgNef3IOFunctions `CGAL::operator>>()` \endlink +\cgalCRPSection{Draw a Nef Polyhedron} +- \link PkgDrawNef3 CGAL::draw() \endlink + */ diff --git a/Nef_3/doc/Nef_3/dependencies b/Nef_3/doc/Nef_3/dependencies index 92b8ee474e4..467cacb769e 100644 --- a/Nef_3/doc/Nef_3/dependencies +++ b/Nef_3/doc/Nef_3/dependencies @@ -11,3 +11,4 @@ Number_types BGL Surface_mesh Polygon_mesh_processing +GraphicsView diff --git a/Nef_3/doc/Nef_3/examples.txt b/Nef_3/doc/Nef_3/examples.txt index 3c394cfd017..4a790f646bc 100644 --- a/Nef_3/doc/Nef_3/examples.txt +++ b/Nef_3/doc/Nef_3/examples.txt @@ -17,4 +17,5 @@ \example Nef_3/topological_operations.cpp \example Nef_3/transformation.cpp \example Nef_3/nef_3_to_surface_mesh.cpp +\example Nef_3/draw_nef_3.cpp */ diff --git a/Nef_3/doc/Nef_3/fig/draw_nef_3.png b/Nef_3/doc/Nef_3/fig/draw_nef_3.png new file mode 100644 index 0000000000000000000000000000000000000000..03d51641277d209fe5f9e033cf22dde75d6eba20 GIT binary patch literal 20712 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 ptN() \endlink function as shown in the following example. This function opens a new window showing the given Periodic Triangulation. Elements of the periodic triangulation can be viewed in four different modes: +\cgalExample{Periodic_2_triangulation_2/draw_periodic_2_triangulation_2.cpp} + - STORED Display all geometric primitives as they are stored in Triangulation_data_structure_2; - UNIQUE Display only one representative of each geometric primitive even if the triangulation is computed in multiply sheeted covering space; - STORED_COVER_DOMAIN Same as STORED but also display all primitives whose intersection with the original domain of the current covering space is non-empty; From 35008aeeea40261931e12c99f67975fbc1713a0e Mon Sep 17 00:00:00 2001 From: Jasmeet Singh Date: Wed, 3 Jul 2019 15:14:57 -0700 Subject: [PATCH 098/363] Update draw_periodic_2_triangulation_2.h --- .../CGAL/draw_periodic_2_triangulation_2.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Periodic_2_triangulation_2/doc/Periodic_2_triangulation_2/CGAL/draw_periodic_2_triangulation_2.h b/Periodic_2_triangulation_2/doc/Periodic_2_triangulation_2/CGAL/draw_periodic_2_triangulation_2.h index e8d456cd261..6365c1c51c8 100644 --- a/Periodic_2_triangulation_2/doc/Periodic_2_triangulation_2/CGAL/draw_periodic_2_triangulation_2.h +++ b/Periodic_2_triangulation_2/doc/Periodic_2_triangulation_2/CGAL/draw_periodic_2_triangulation_2.h @@ -3,7 +3,7 @@ namespace CGAL { /*! \ingroup PkgDrawPeriodic2Triangulation2 -Opens a new window and draws `ap2t2`, the `Periodic_2_Triangulation_2`. A call to this function is blocking, that is the program continues as soon as the user closes the window. +opens a new window and draws `ap2t2`, the `Periodic_2_Triangulation_2`. 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 P2T2 a model of the `Periodic_2TriangulationTraits_2` concept. \param ap2t2 the 2D periodic trinagulation to draw. @@ -12,4 +12,4 @@ Opens a new window and draws `ap2t2`, the `Periodic_2_Triangulation_2`. A call t template void draw(const P2T2& ap2t2); -} /* namespace CGAL */ \ No newline at end of file +} /* namespace CGAL */ From 09fcb98c65d26bb2087635095b5fd2bd024cf040 Mon Sep 17 00:00:00 2001 From: Jasmeet Singh Date: Wed, 3 Jul 2019 15:19:25 -0700 Subject: [PATCH 099/363] Add the documentation header file draw_nef_3.h --- Nef_3/doc/Nef_3/CGAL/draw_nef_3.h | 15 +++++++++++++++ 1 file changed, 15 insertions(+) create mode 100644 Nef_3/doc/Nef_3/CGAL/draw_nef_3.h diff --git a/Nef_3/doc/Nef_3/CGAL/draw_nef_3.h b/Nef_3/doc/Nef_3/CGAL/draw_nef_3.h new file mode 100644 index 00000000000..3ec9c0b2a8c --- /dev/null +++ b/Nef_3/doc/Nef_3/CGAL/draw_nef_3.h @@ -0,0 +1,15 @@ +namespace CGAL { + +/*! +\ingroup PkgDrawNef3 + +Open a new window and draws `anef3`, the `Nef_polyhedron_3`. 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 Nef3 a model of the `Nef_polyhedron_3` concept. +\param anef3 the nef polyhedron to draw. + +*/ +template +void draw(const Nef3& anef3); + +} /* namespace CGAL */ \ No newline at end of file From 2047eaa7dbe9cdd6a6ac2b822c7bc249247d1591 Mon Sep 17 00:00:00 2001 From: Jasmeet Singh Date: Wed, 3 Jul 2019 15:28:02 -0700 Subject: [PATCH 100/363] Add code of example to P2T2 documentation --- .../Periodic_2_triangulation_2/Periodic_2_triangulation_2.txt | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Periodic_2_triangulation_2/doc/Periodic_2_triangulation_2/Periodic_2_triangulation_2.txt b/Periodic_2_triangulation_2/doc/Periodic_2_triangulation_2/Periodic_2_triangulation_2.txt index 19a0f572fba..a2bf64e5519 100644 --- a/Periodic_2_triangulation_2/doc/Periodic_2_triangulation_2/Periodic_2_triangulation_2.txt +++ b/Periodic_2_triangulation_2/doc/Periodic_2_triangulation_2/Periodic_2_triangulation_2.txt @@ -398,6 +398,8 @@ in the unit rectangle. The tests were done on an Intel i7 @ 2.67GHz. A 2D periodic triangulation can be visualized by calling the \link PkgDrawPeriodic2Triangulation2 CGAL::draw() \endlink function as shown in the following example. This function opens a new window showing the given Periodic Triangulation. Elements of the periodic triangulation can be viewed in four different modes: +\cgalExample{Periodic_2_triangulation_2/draw_periodic_2_triangulation_2.cpp} + - STORED Display all geometric primitives as they are stored in Triangulation_data_structure_2; - UNIQUE Display only one representative of each geometric primitive even if the triangulation is computed in multiply sheeted covering space; - STORED_COVER_DOMAIN Same as STORED but also display all primitives whose intersection with the original domain of the current covering space is non-empty; From 91dc961b18db6424be5532d6a5d9d4cdc1b9494b Mon Sep 17 00:00:00 2001 From: Simon Giraudot Date: Tue, 2 Jul 2019 09:54:17 +0200 Subject: [PATCH 101/363] Use cache optimisation for KD Tree on indices for classification + shape detection --- .../include/CGAL/Classification/Point_set_neighborhood.h | 2 +- .../Region_growing_on_point_set/K_neighbor_query.h | 2 +- .../Region_growing_on_point_set/Sphere_neighbor_query.h | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/Classification/include/CGAL/Classification/Point_set_neighborhood.h b/Classification/include/CGAL/Classification/Point_set_neighborhood.h index a69fd8bbe40..fd0078bdda1 100644 --- a/Classification/include/CGAL/Classification/Point_set_neighborhood.h +++ b/Classification/include/CGAL/Classification/Point_set_neighborhood.h @@ -90,7 +90,7 @@ class Point_set_neighborhood typedef Search_traits_adapter Search_traits; typedef Sliding_midpoint Splitter; typedef Distance_adapter > Distance; - typedef Kd_tree Tree; + typedef Kd_tree Tree; typedef Fuzzy_sphere Sphere; typedef Orthogonal_k_neighbor_search Knn; diff --git a/Shape_detection/include/CGAL/Shape_detection/Region_growing/Region_growing_on_point_set/K_neighbor_query.h b/Shape_detection/include/CGAL/Shape_detection/Region_growing/Region_growing_on_point_set/K_neighbor_query.h index ba2d46453f0..f885a689195 100644 --- a/Shape_detection/include/CGAL/Shape_detection/Region_growing/Region_growing_on_point_set/K_neighbor_query.h +++ b/Shape_detection/include/CGAL/Shape_detection/Region_growing/Region_growing_on_point_set/K_neighbor_query.h @@ -104,7 +104,7 @@ namespace Point_set { CGAL::Sliding_midpoint; using Search_tree = - CGAL::Kd_tree; + CGAL::Kd_tree; using Neighbor_search = CGAL::Orthogonal_k_neighbor_search< diff --git a/Shape_detection/include/CGAL/Shape_detection/Region_growing/Region_growing_on_point_set/Sphere_neighbor_query.h b/Shape_detection/include/CGAL/Shape_detection/Region_growing/Region_growing_on_point_set/Sphere_neighbor_query.h index 246e433e27b..0749d04b106 100644 --- a/Shape_detection/include/CGAL/Shape_detection/Region_growing/Region_growing_on_point_set/Sphere_neighbor_query.h +++ b/Shape_detection/include/CGAL/Shape_detection/Region_growing/Region_growing_on_point_set/Sphere_neighbor_query.h @@ -110,7 +110,7 @@ namespace Point_set { = CGAL::Fuzzy_sphere; using Tree - = CGAL::Kd_tree; + = CGAL::Kd_tree; /// \endcond /// @} From 9b02d9d426da7d19e2fa1216d139c255c96108b6 Mon Sep 17 00:00:00 2001 From: Simon Giraudot Date: Thu, 4 Jul 2019 13:25:56 +0200 Subject: [PATCH 102/363] Fix warnings --- .../include/CGAL/Incremental_neighbor_search.h | 2 +- .../include/CGAL/K_neighbor_search.h | 3 --- Spatial_searching/include/CGAL/Kd_tree_node.h | 18 +++++++++--------- .../Orthogonal_incremental_neighbor_search.h | 2 +- .../include/CGAL/internal/Search_helpers.h | 8 ++++---- 5 files changed, 15 insertions(+), 18 deletions(-) diff --git a/Spatial_searching/include/CGAL/Incremental_neighbor_search.h b/Spatial_searching/include/CGAL/Incremental_neighbor_search.h index 8b6d3d499f5..11e4f0a2bd5 100644 --- a/Spatial_searching/include/CGAL/Incremental_neighbor_search.h +++ b/Spatial_searching/include/CGAL/Incremental_neighbor_search.h @@ -488,7 +488,7 @@ namespace CGAL { { typename Tree::iterator it_node_point = node->begin(), it_node_point_end = node->end(); - for (; it_node_point != node->end(); ++it_node_point) + for (; it_node_point != it_node_point_end; ++it_node_point) { number_of_items_visited++; FT distance_to_query_point = diff --git a/Spatial_searching/include/CGAL/K_neighbor_search.h b/Spatial_searching/include/CGAL/K_neighbor_search.h index 49b74854c78..1f8973e7f21 100644 --- a/Spatial_searching/include/CGAL/K_neighbor_search.h +++ b/Spatial_searching/include/CGAL/K_neighbor_search.h @@ -59,9 +59,6 @@ public: { if (tree.empty()) return; - typename SearchTraits::Construct_cartesian_const_iterator_d construct_it = - m_tree.traits().construct_cartesian_const_iterator_d_object(); - compute_neighbors_general(tree.root(),tree.bounding_box()); if (sorted) this->queue.sort(); }; diff --git a/Spatial_searching/include/CGAL/Kd_tree_node.h b/Spatial_searching/include/CGAL/Kd_tree_node.h index 7b6e2602e6e..647124d6fec 100644 --- a/Spatial_searching/include/CGAL/Kd_tree_node.h +++ b/Spatial_searching/include/CGAL/Kd_tree_node.h @@ -277,8 +277,8 @@ namespace CGAL { bool contains( const FuzzyQueryItem& q, Point_d const& p, - typename std::vector::const_iterator it_coord_begin, - typename std::vector::const_iterator it_coord_end, + typename std::vector::const_iterator /*it_coord_begin*/, + typename std::vector::const_iterator /*it_coord_end*/, Tag_false /*has_contains_point_given_as_coordinates*/) const { return q.contains(p); @@ -287,7 +287,7 @@ namespace CGAL { template bool contains( const FuzzyQueryItem& q, - Point_d const& p, + Point_d const& /*p*/, typename std::vector::const_iterator it_coord_begin, typename std::vector::const_iterator it_coord_end, Tag_true /*has_contains_point_given_as_coordinates*/) const @@ -321,9 +321,9 @@ namespace CGAL { void search_in_leaf( Leaf_node_const_handle node, const FuzzyQueryItem &q, - typename Kdt::const_iterator tree_points_begin, - typename std::vector::const_iterator cache_begin, - int dim, + typename Kdt::const_iterator /*tree_points_begin*/, + typename std::vector::const_iterator /*cache_begin*/, + int /*dim*/, OutputIterator oit, Tag_false /*has_points_cache*/) const { @@ -364,9 +364,9 @@ namespace CGAL { boost::optional search_any_point_in_leaf( Leaf_node_const_handle node, const FuzzyQueryItem &q, - typename Kdt::const_iterator tree_points_begin, - typename std::vector::const_iterator cache_begin, - int dim, + typename Kdt::const_iterator /*tree_points_begin*/, + typename std::vector::const_iterator /*cache_begin*/, + int /*dim*/, Tag_false /*has_points_cache*/) const { boost::optional result = boost::none; diff --git a/Spatial_searching/include/CGAL/Orthogonal_incremental_neighbor_search.h b/Spatial_searching/include/CGAL/Orthogonal_incremental_neighbor_search.h index a892b460bd0..4c7957b9ac8 100644 --- a/Spatial_searching/include/CGAL/Orthogonal_incremental_neighbor_search.h +++ b/Spatial_searching/include/CGAL/Orthogonal_incremental_neighbor_search.h @@ -317,7 +317,7 @@ namespace CGAL { { typename Tree::iterator it_node_point = node->begin(), it_node_point_end = node->end(); - for (; it_node_point != node->end(); ++it_node_point) + for (; it_node_point != it_node_point_end; ++it_node_point) { number_of_items_visited++; FT distance_to_query_point= diff --git a/Spatial_searching/include/CGAL/internal/Search_helpers.h b/Spatial_searching/include/CGAL/internal/Search_helpers.h index cf308676fb3..68807cf33f7 100644 --- a/Spatial_searching/include/CGAL/internal/Search_helpers.h +++ b/Spatial_searching/include/CGAL/internal/Search_helpers.h @@ -72,8 +72,8 @@ public: FT operator() ( const Query_item& q, Point const& p, - typename std::vector::const_iterator it_coord_begin, - typename std::vector::const_iterator it_coord_end) const + typename std::vector::const_iterator /*it_coord_begin*/, + typename std::vector::const_iterator /*it_coord_end*/) const { return m_distance.transformed_distance(q, p); } @@ -96,7 +96,7 @@ public: FT operator() ( const Query_item& q, - Point const& p, + Point const& /*p*/, typename std::vector::const_iterator it_coord_begin, typename std::vector::const_iterator it_coord_end) const { @@ -176,7 +176,7 @@ public: FT operator() ( const Query_item& q, - Point const& p, + Point const& /*p*/, typename std::vector::const_iterator it_coord_begin, typename std::vector::const_iterator it_coord_end, FT stop_if_geq_to_this) const From 7a9d0ccea8093a3b4de2dccd24f1af62216f395a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mael=20Rouxel-Labb=C3=A9?= Date: Tue, 9 Jul 2019 15:26:01 +0200 Subject: [PATCH 103/363] Add some naive code to remove needles and caps --- .../Polygon_mesh_processing/CMakeLists.txt | 1 + .../clean_degeneracies.cpp | 33 +++ .../remove_degeneracies.h | 220 ++++++++++++++++++ .../include/CGAL/polygon_mesh_processing.h | 1 + 4 files changed, 255 insertions(+) create mode 100644 Polygon_mesh_processing/examples/Polygon_mesh_processing/clean_degeneracies.cpp create mode 100644 Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/remove_degeneracies.h diff --git a/Polygon_mesh_processing/examples/Polygon_mesh_processing/CMakeLists.txt b/Polygon_mesh_processing/examples/Polygon_mesh_processing/CMakeLists.txt index 23fad404af5..b3364c27c55 100644 --- a/Polygon_mesh_processing/examples/Polygon_mesh_processing/CMakeLists.txt +++ b/Polygon_mesh_processing/examples/Polygon_mesh_processing/CMakeLists.txt @@ -88,6 +88,7 @@ create_single_source_cgal_program( "hole_filling_example_LCC.cpp" ) create_single_source_cgal_program( "detect_features_example.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( "clean_degeneracies.cpp" ) if(OpenMesh_FOUND) create_single_source_cgal_program( "compute_normals_example_OM.cpp" ) diff --git a/Polygon_mesh_processing/examples/Polygon_mesh_processing/clean_degeneracies.cpp b/Polygon_mesh_processing/examples/Polygon_mesh_processing/clean_degeneracies.cpp new file mode 100644 index 00000000000..ce7e30acd0b --- /dev/null +++ b/Polygon_mesh_processing/examples/Polygon_mesh_processing/clean_degeneracies.cpp @@ -0,0 +1,33 @@ +#include +#include + +#include + +#include +#include +#include + +typedef CGAL::Exact_predicates_inexact_constructions_kernel K; +typedef CGAL::Surface_mesh Mesh; + +typedef boost::graph_traits::halfedge_descriptor halfedge_descriptor; +typedef boost::graph_traits::edge_descriptor edge_descriptor; +typedef boost::graph_traits::face_descriptor face_descriptor; + +namespace PMP = CGAL::Polygon_mesh_processing; + +int main(int argc, char** argv) +{ + const char* filename = (argc > 1) ? argv[1] : "data/pig.off"; + std::ifstream input(filename); + + Mesh mesh; + if (!input || !(input >> mesh) || !CGAL::is_triangle_mesh(mesh)) { + std::cerr << "Not a valid input file." << std::endl; + return 1; + } + + PMP::remove_almost_degenerate_faces(mesh); + + return 0; +} diff --git a/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/remove_degeneracies.h b/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/remove_degeneracies.h new file mode 100644 index 00000000000..90ce2dadbe9 --- /dev/null +++ b/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/remove_degeneracies.h @@ -0,0 +1,220 @@ +// 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) : Sebastien Loriot, +// Mael Rouxel-Labbé + +#ifndef CGAL_POLYGON_MESH_PROCESSING_REMOVE_DEGENERACIES_H +#define CGAL_POLYGON_MESH_PROCESSING_REMOVE_DEGENERACIES_H + +#include + +#include + +#include + +#include + +#include +#include // @tmp +#include +#include // @tmp + +namespace CGAL { +namespace Polygon_mesh_processing { +namespace internal { + +template +bool is_face_incident_to_border(const typename boost::graph_traits::face_descriptor f, + const TriangleMesh& tmesh) +{ + typedef typename boost::graph_traits::halfedge_descriptor halfedge_descriptor; + + for(halfedge_descriptor h : CGAL::halfedges_around_face(halfedge(f, tmesh), tmesh)) + { + if(is_border_edge(h, tmesh)) + return true; + } + + return false; +} + +template +void add_if_badly_shaped(const typename boost::graph_traits::face_descriptor f, + TriangleMesh& tmesh, + EdgeContainer& edges_to_collapse, + EdgeContainer& edges_to_flip, + const NamedParameters& np) +{ + typedef typename boost::graph_traits::halfedge_descriptor halfedge_descriptor; + + // @todo parameters + const double needle_threshold = 4; // longest edge / shortest edge over this ratio ==> needle + const double cap_threshold = std::cos(160. / 180 * CGAL_PI); // angle over 120° ==> cap + + if(is_face_incident_to_border(f, tmesh)) + return; + + halfedge_descriptor res = CGAL::Polygon_mesh_processing::is_needle_triangle_face(f, tmesh, needle_threshold, np); + if(res != boost::graph_traits::null_halfedge()) + { + std::cout << "add new needle: " << res << std::endl; + edges_to_collapse.insert(edge(res, tmesh)); + } + else // let's not make it possible to have a face be both a cap and a needle fo(for now) + { + res = CGAL::Polygon_mesh_processing::is_cap_triangle_face(f, tmesh, cap_threshold, np); + if(res != boost::graph_traits::null_halfedge()) + { + std::cout << "add new cap: " << res << std::endl; + edges_to_flip.insert(edge(res, tmesh)); + } + } +} + +} // namespace internal + +template +bool remove_almost_degenerate_faces(const FaceRange& face_range, + TriangleMesh& tmesh, + const NamedParameters& np) +{ + typedef typename boost::graph_traits::vertex_descriptor vertex_descriptor; + typedef typename boost::graph_traits::halfedge_descriptor halfedge_descriptor; + typedef typename boost::graph_traits::edge_descriptor edge_descriptor; + typedef typename boost::graph_traits::face_descriptor face_descriptor; + + std::set edges_to_collapse; + std::set edges_to_flip; + + // @todo could probably do something a bit better by looping edges, consider the incident faces + // f1 / f2 and look at f1 if f1 next_edges_to_collapse; + std::set next_edges_to_flip; + + // treat needles + for(edge_descriptor e : edges_to_collapse) + { + std::cout << "treat needle: " << e << " (" << tmesh.point(source (e, tmesh)) << " --- " << tmesh.point(target(e, tmesh)) << ")" << std::endl; + if(CGAL::Euler::does_satisfy_link_condition(e, tmesh)) + { + vertex_descriptor v = Euler::collapse_edge(e, tmesh); // @todo move 'v' to the midpoint? + + edges_to_flip.erase(e); + + // The geometry of all the faces incident to 'v' has changed and so we recompute their badness + // @fixme nasty complexity, use tags or something... + for(halfedge_descriptor inc_h : CGAL::halfedges_around_target(v, tmesh)) + { + if(is_border_edge(inc_h, tmesh)) + continue; + + // since the 'bad' edge of a face incident to 'v' might not be an incident edge + for(halfedge_descriptor other_h : CGAL::halfedges_around_face(inc_h, tmesh)) + { + edge_descriptor other_e = edge(other_h, tmesh); + + if(other_e != e) // erasing the current position while looping is undefined behavior + edges_to_collapse.erase(other_e); + edges_to_flip.erase(other_e); + } + + // adding directly to 'edges_to_flip' + internal::add_if_badly_shaped(face(inc_h, tmesh), tmesh, next_edges_to_collapse, edges_to_flip, np); + } + } + else + { + std::cerr << "Warning: uncollapsable edge! " << tmesh.point(source(e, tmesh)) << " --- " + << tmesh.point(target(e, tmesh)) << std::endl; + } + } + + // treat caps + for(edge_descriptor e : edges_to_flip) + { + std::cout << "treat cap: " << e << " (" << tmesh.point(source (e, tmesh)) << " --- " << tmesh.point(target(e, tmesh)) << ")" << std::endl; + halfedge_descriptor h = halfedge(e, tmesh); + + // condition for the flip to be valid (the edge to be created does not already exist) + if(!halfedge(target(next(h, tmesh), tmesh), + target(next(opposite(h, tmesh), tmesh), tmesh), tmesh).second) + { + std::cout << "Flippin!" << std::endl; + Euler::flip_edge(h, tmesh); + + internal::add_if_badly_shaped(face(h, tmesh), tmesh, next_edges_to_collapse, next_edges_to_flip, np); + internal::add_if_badly_shaped(face(opposite(h, tmesh), tmesh), tmesh, next_edges_to_collapse, next_edges_to_flip, np); + } + else + { + std::cerr << "Warning: unflippable edge! " << tmesh.point(source(h, tmesh)) << " --- " + << tmesh.point(target(h, tmesh)) << std::endl; + } + } + + std::swap(edges_to_collapse, next_edges_to_collapse); + std::swap(edges_to_flip, next_edges_to_flip); + } + + return false; +} + +template +bool remove_almost_degenerate_faces(const FaceRange& face_range, + TriangleMesh& tmesh) +{ + return remove_almost_degenerate_faces(face_range, tmesh, parameters::all_default()); +} + +template +bool remove_almost_degenerate_faces(TriangleMesh& tmesh, + const CGAL_PMP_NP_CLASS& np) +{ + return remove_almost_degenerate_faces(faces(tmesh), tmesh, np); +} + +template +bool remove_almost_degenerate_faces(TriangleMesh& tmesh) +{ + return remove_almost_degenerate_faces(tmesh, CGAL::parameters::all_default()); +} + +} // namespace Polygon_mesh_processing +} // namespace CGAL + +#endif // CGAL_POLYGON_MESH_PROCESSING_REMOVE_DEGENERACIES_H diff --git a/Polygon_mesh_processing/include/CGAL/polygon_mesh_processing.h b/Polygon_mesh_processing/include/CGAL/polygon_mesh_processing.h index 1bfacaf330a..ffb4862c504 100644 --- a/Polygon_mesh_processing/include/CGAL/polygon_mesh_processing.h +++ b/Polygon_mesh_processing/include/CGAL/polygon_mesh_processing.h @@ -52,6 +52,7 @@ #include #include #include +#include // the named parameter header being not documented the doc is put here for now #ifdef DOXYGEN_RUNNING From 675cd33dbc573068edb4c3e45828aa58caba07b4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mael=20Rouxel-Labb=C3=A9?= Date: Tue, 9 Jul 2019 15:43:01 +0200 Subject: [PATCH 104/363] Fix some edges not being properly cleaned from the active sets --- .../remove_degeneracies.h | 24 ++++++++++++++++++- 1 file changed, 23 insertions(+), 1 deletion(-) diff --git a/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/remove_degeneracies.h b/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/remove_degeneracies.h index 90ce2dadbe9..be56521054b 100644 --- a/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/remove_degeneracies.h +++ b/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/remove_degeneracies.h @@ -132,10 +132,21 @@ bool remove_almost_degenerate_faces(const FaceRange& face_range, std::cout << "treat needle: " << e << " (" << tmesh.point(source (e, tmesh)) << " --- " << tmesh.point(target(e, tmesh)) << ")" << std::endl; if(CGAL::Euler::does_satisfy_link_condition(e, tmesh)) { + CGAL_assertion(!is_border(e, tmesh)); + vertex_descriptor v = Euler::collapse_edge(e, tmesh); // @todo move 'v' to the midpoint? edges_to_flip.erase(e); + // the following edges are removed by the collapse + edge_descriptor pe = edge(prev(halfedge(e, tmesh), tmesh), tmesh); + edge_descriptor poe = edge(prev(opposite(halfedge(e, tmesh), tmesh), tmesh), tmesh); + + edges_to_collapse.erase(pe); + edges_to_collapse.erase(poe); + edges_to_flip.erase(pe); + edges_to_flip.erase(poe); + // The geometry of all the faces incident to 'v' has changed and so we recompute their badness // @fixme nasty complexity, use tags or something... for(halfedge_descriptor inc_h : CGAL::halfedges_around_target(v, tmesh)) @@ -153,7 +164,7 @@ bool remove_almost_degenerate_faces(const FaceRange& face_range, edges_to_flip.erase(other_e); } - // adding directly to 'edges_to_flip' + // adding directly to 'edges_to_flip' because we're treating caps next internal::add_if_badly_shaped(face(inc_h, tmesh), tmesh, next_edges_to_collapse, edges_to_flip, np); } } @@ -177,8 +188,19 @@ bool remove_almost_degenerate_faces(const FaceRange& face_range, std::cout << "Flippin!" << std::endl; Euler::flip_edge(h, tmesh); + // commented code below is not needed as long as you can't have both needle & caps but might become relevant later +// edges_to_flip.erase(edge(prev(h, tmesh), tmesh)); +// edges_to_flip.erase(edge(next(h, tmesh), tmesh)); +// edges_to_flip.erase(edge(prev(opposite(h, tmesh), tmesh), tmesh)); +// edges_to_flip.erase(edge(next(opposite(h, tmesh), tmesh), tmesh)); + internal::add_if_badly_shaped(face(h, tmesh), tmesh, next_edges_to_collapse, next_edges_to_flip, np); internal::add_if_badly_shaped(face(opposite(h, tmesh), tmesh), tmesh, next_edges_to_collapse, next_edges_to_flip, np); + +// internal::add_if_badly_shaped(face(opposite(prev(h, tmesh), tmesh), tmesh), tmesh, next_edges_to_collapse, next_edges_to_flip, np); +// internal::add_if_badly_shaped(face(opposite(next(h, tmesh), tmesh), tmesh), tmesh, next_edges_to_collapse, next_edges_to_flip, np); +// internal::add_if_badly_shaped(face(opposite(prev(opposite(h, tmesh), tmesh), tmesh), tmesh), tmesh, next_edges_to_collapse, next_edges_to_flip, np); +// internal::add_if_badly_shaped(face(opposite(next(opposite(h, tmesh), tmesh), tmesh), tmesh), tmesh, next_edges_to_collapse, next_edges_to_flip, np); } else { From 596a186963f63763e6e31c34f8a72098c4739bf8 Mon Sep 17 00:00:00 2001 From: Jasmeet Singh Date: Wed, 10 Jul 2019 17:08:34 -0700 Subject: [PATCH 105/363] Update has_zero_*() methods to incorporate rays and lines. --- GraphicsView/include/CGAL/Qt/Basic_viewer_qt.h | 18 +++++++++++++++--- 1 file changed, 15 insertions(+), 3 deletions(-) diff --git a/GraphicsView/include/CGAL/Qt/Basic_viewer_qt.h b/GraphicsView/include/CGAL/Qt/Basic_viewer_qt.h index a753870034f..b153c17e077 100644 --- a/GraphicsView/include/CGAL/Qt/Basic_viewer_qt.h +++ b/GraphicsView/include/CGAL/Qt/Basic_viewer_qt.h @@ -293,7 +293,11 @@ public: m_buffer_for_mono_segments.has_zero_x() && m_buffer_for_colored_segments.has_zero_x() && m_buffer_for_mono_faces.has_zero_x() && - m_buffer_for_colored_faces.has_zero_x(); + m_buffer_for_colored_faces.has_zero_x() && + m_buffer_for_mono_rays.has_zero_x() && + m_buffer_for_colored_rays.has_zero_x() && + m_buffer_for_mono_lines.has_zero_x() && + m_buffer_for_colored_lines.has_zero_x(); } bool has_zero_y() const @@ -304,7 +308,11 @@ public: m_buffer_for_mono_segments.has_zero_y() && m_buffer_for_colored_segments.has_zero_y() && m_buffer_for_mono_faces.has_zero_y() && - m_buffer_for_colored_faces.has_zero_y(); + m_buffer_for_colored_faces.has_zero_y() && + m_buffer_for_mono_rays.has_zero_y() && + m_buffer_for_colored_rays.has_zero_y() && + m_buffer_for_mono_lines.has_zero_y() && + m_buffer_for_colored_lines.has_zero_y(); } bool has_zero_z() const @@ -315,7 +323,11 @@ public: m_buffer_for_mono_segments.has_zero_z() && m_buffer_for_colored_segments.has_zero_z() && m_buffer_for_mono_faces.has_zero_z() && - m_buffer_for_colored_faces.has_zero_z(); + m_buffer_for_colored_faces.has_zero_z() && + m_buffer_for_mono_rays.has_zero_z() && + m_buffer_for_colored_rays.has_zero_z() && + m_buffer_for_mono_lines.has_zero_z() && + m_buffer_for_colored_lines.has_zero_z(); } template From 899b6d9e097aea6f56a743c316dfb76d9df68162 Mon Sep 17 00:00:00 2001 From: Jasmeet Singh Date: Wed, 10 Jul 2019 17:08:58 -0700 Subject: [PATCH 106/363] Update draw() method call for Voronoi Diagram to be similar to other viewers. Draw method for P2T2 and Nef_3 needs to be updated if this works. --- .../include/CGAL/draw_voronoi_diagram_2.h | 68 +++++++++++-------- 1 file changed, 39 insertions(+), 29 deletions(-) diff --git a/Voronoi_diagram_2/include/CGAL/draw_voronoi_diagram_2.h b/Voronoi_diagram_2/include/CGAL/draw_voronoi_diagram_2.h index 4b4e4a6c652..c139f5a390d 100644 --- a/Voronoi_diagram_2/include/CGAL/draw_voronoi_diagram_2.h +++ b/Voronoi_diagram_2/include/CGAL/draw_voronoi_diagram_2.h @@ -32,6 +32,7 @@ #include #include #include +#include namespace CGAL { @@ -305,10 +306,18 @@ protected: const ColorFunctor &m_fcolor; }; -template -void draw(const V2 &av2, const char *title, bool nofill, - bool draw_voronoi_vertices, bool draw_dual_vertices, - const ColorFunctor &fcolor) { +// Specialization of draw function. +#define CGAL_VORONOI_TYPE CGAL::Voronoi_diagram_2 + +template> +void draw(const CGAL_VORONOI_TYPE &av2, + const char *title="Voronoi Diagram Basic Viewer", + bool nofill = false, + bool draw_voronoi_vertices = true, + bool draw_dual_vertices = true) +{ #if defined(CGAL_TEST_SUITE) bool cgal_test_suite = true; #else @@ -317,41 +326,42 @@ void draw(const V2 &av2, const char *title, bool nofill, if (!cgal_test_suite) { int argc = 1; - const char *argv[2] = {"v2_viewer", "\0"}; + const char *argv[2] = {"voronoi_2_viewer", "\0"}; QApplication app(argc, const_cast(argv)); - SimpleVoronoiDiagram2ViewerQt mainwindow( - app.activeWindow(), av2, title, nofill, draw_voronoi_vertices, - draw_dual_vertices, fcolor); + DefaultColorFunctorV2 fcolor; + SimpleVoronoiDiagram2ViewerQt + mainwindow(app.activeWindow(), av2, title, nofill, + draw_voronoi_vertices, draw_dual_vertices, fcolor); mainwindow.show(); app.exec(); } } -template -void draw(const V2 &av2, const char *title, bool nofill, - bool draw_voronoi_vertices, bool draw_dual_vertices) { - DefaultColorFunctorV2 c; - draw(av2, title, nofill, draw_voronoi_vertices, draw_dual_vertices, c); -} +//template +//void draw(const V2 &av2, const char *title, bool nofill, +// bool draw_voronoi_vertices, bool draw_dual_vertices) { +// DefaultColorFunctorV2 c; +// draw(av2, title, nofill, draw_voronoi_vertices, draw_dual_vertices, c); +//} -template -void draw(const V2 &av2, const char *title, bool nofill, - bool draw_voronoi_vertices) { - DefaultColorFunctorV2 c; - draw(av2, title, nofill, draw_voronoi_vertices, true); -} +//template +//void draw(const V2 &av2, const char *title, bool nofill, +// bool draw_voronoi_vertices) { +// DefaultColorFunctorV2 c; +// draw(av2, title, nofill, draw_voronoi_vertices, true); +//} -template void draw(const V2 &av2, const char *title, bool nofill) { - draw(av2, title, nofill, true); -} +//template void draw(const V2 &av2, const char *title, bool nofill) { +// draw(av2, title, nofill, true); +//} -template void draw(const V2 &av2, const char *title) { - draw(av2, title, false); -} +//template void draw(const V2 &av2, const char *title) { +// draw(av2, title, false); +//} -template void draw(const V2 &av2) { - draw(av2, "Basic Voronoi Diagram Viewer"); -} +//template void draw(const V2 &av2) { +// draw(av2, "Basic Voronoi Diagram Viewer"); +//} } // End namespace CGAL From 9a40d573b95a1acf1f14cc29aa1db69c12648622 Mon Sep 17 00:00:00 2001 From: Laurent Rineau Date: Mon, 17 Jun 2019 15:07:13 +0200 Subject: [PATCH 107/363] Easy fix --- Documentation/doc/Documentation/Installation.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Documentation/doc/Documentation/Installation.txt b/Documentation/doc/Documentation/Installation.txt index f6a6b8e6ee0..bb3a857b869 100644 --- a/Documentation/doc/Documentation/Installation.txt +++ b/Documentation/doc/Documentation/Installation.txt @@ -285,7 +285,7 @@ purpose of this file is explained below. \section seclibraries CGAL Libraries -\cgal is split into five libraries. During configuration, you can select the libraries that +\cgal is split into four libraries. During configuration, you can select the libraries that you would like to build by setting a CMake variable of the form WITH_. By default all are switched `ON`. All activated libraries are build after configuration; see \ref secbuilding From c249351ef8022b197e766b1a8fcad80550aa3cfd Mon Sep 17 00:00:00 2001 From: Laurent Rineau Date: Wed, 19 Jun 2019 15:18:00 +0200 Subject: [PATCH 108/363] First pass on the documentation --- .../doc/Documentation/Installation.txt | 113 +++++++----------- 1 file changed, 44 insertions(+), 69 deletions(-) diff --git a/Documentation/doc/Documentation/Installation.txt b/Documentation/doc/Documentation/Installation.txt index bb3a857b869..543939cca22 100644 --- a/Documentation/doc/Documentation/Installation.txt +++ b/Documentation/doc/Documentation/Installation.txt @@ -4,51 +4,39 @@ \authors Eric Berberich, Joachim Reichel, and Fernando Cacciola \section installation_introduction Introduction - -This document describes how to install \cgal on Windows, Unix-like systems, and MacOS X. -Ideally, setting up \cgal amounts to: +Since \cgal version 5.0, \cgal is header-only be default, which means +that there is no need to compile and install anything before it can be +used. The dependencies of \cgal still have to be installed. -

    -cd CGAL-\cgalReleaseNumber # go to \cgal directory
    -cmake . # configure \cgal
    -make # build the \cgal libraries
    -
    +Ideally, compiling an example or a demo shipped with \cgal is +as simple as: -Compiling an example or a demo shipped with \cgal is similarly simple: - -
    -cd examples/Triangulation_2 # go to an example directory
    -cmake -DCGAL_DIR=$HOME/CGAL-\cgalReleaseNumber . # configure the examples
    -make # build the examples 
    -
    - -
    -cd demo/Triangulation_2 # go to a demo directory
    -cmake -DCGAL_DIR=$HOME/CGAL-\cgalReleaseNumber . # configure the demos
    -make # build the demos 
    -
    + cd examples/Triangulation_2 # go to an example directory + cmake -DCGAL_DIR=$HOME/CGAL-\cgalReleaseNumber . # configure the examples + make # build the examples + + cd demo/Triangulation_2 # go to a demo directory + cmake -DCGAL_DIR=$HOME/CGAL-\cgalReleaseNumber . # configure the demos + make # build the demos Compiling an own non-shipped program is also close: -
    -cd /path/to/program 
    -cgal_create_CMakeLists -s executable 
    -cmake -DCGAL_DIR=$HOME/CGAL-\cgalReleaseNumber . 
    -make
    -
    + cd /path/to/program + cgal_create_CMakeLists -s executable + cmake -DCGAL_DIR=$HOME/CGAL-\cgalReleaseNumber . + make where the second line creates a `CMakeLists.txt` file (check its options in Section \ref seccreate_cgal_CMakeLists for various details). -In a less ideal world, you probably have to install CMake, a makefile -generator, and third party libraries. That is what this manual is about. +In a less ideal world, you probably have to install required tools, and third party libraries. That is what this manual is about. \section secprerequisites Prerequisites -Installing \cgal requires a few components to be installed ahead: a -supported compiler (see Section \ref seccompilers, CMake, \sc{Boost}, and at least \sc{Gmp}, and \sc{Mpfr}; see +Using \cgal requires a few components to be installed ahead: a +supported compiler (see Section \ref seccompilers), \sc{Boost}, \sc{Gmp}, and \sc{Mpfr}; see Section \ref secessential3rdpartysoftware for more details on essential third party software. @@ -59,35 +47,21 @@ essential third party software through the manager, for instance, Mac OS X, or some Linux distribution (e.g. Debian). For Windows, an installer is provided. -\subsection sseccgalmacosxe CGAL on MAC OS X +\subsection sseccgalmacosxe CGAL on macOS -For instance, use macports in the following way: +The \cgal project recommends the use of
    Homebrew, in the following way: -
    -sudo port install cgal
    -
    - -or if Qt5 are desired - -
    -sudo port install cgal +qt5 +universal +demos
    -
    - -The setup is similar for homebrew . + brew install cgal \subsection sseccgaldebian CGAL on Linux -For instance in debian/Ubuntu, use apt-get in the following way: +For instance in Debian/Ubuntu, use apt-get in the following way: -
    -sudo apt-get install libcgal-dev
    -
    + sudo apt-get install libcgal-dev To get the demos use -
    -sudo apt-get install libcgal-demo
    -
    + sudo apt-get install libcgal-demo Check the \cgal-FAQ for source repository of newest releases. @@ -95,7 +69,7 @@ On other distributions, please consult your package manager documentation. \subsection sseccgalwindows CGAL on Windows -You can download and run `CGAL-\cgalReleaseNumber``-Setup.exe` from https://www.cgal.org/download.html. +You can download and run `CGAL-\cgalReleaseNumber``-Setup.exe` from https://www.cgal.org/download/windows.html. It is a self extracting executable that installs the \cgal source, and that allows you to select and download some precompiled third party libraries. However, you will need to compile the library using your favorite compiler. @@ -122,17 +96,17 @@ In both cases the directory `CGAL-\cgalReleaseNumber` will be created. This dire contains the following subdirectories: -| Directory | Contents | -| :-----------| :----------| -| `auxiliary` | precompiled \sc{Gmp} and \sc{Mpfr} for Windows | +| Directory | Contents | +| :----------- | :----------| +| `auxiliary` | precompiled \sc{Gmp} and \sc{Mpfr} for Windows | | `cmake/modules` | modules for finding and using libraries | -| `config` |configuration files for install script | -| `demo` | demo programs (most of them need \sc{Qt}, geomview or other third-party products) | -| `doc_html` |documentation (HTML) | -| `examples` | example programs | -| `include` | header files | -| `scripts` | some useful scripts (e.g. for creating CMakeLists.txt files) | -| `src` | source files | +| `config` | configuration files for install script | +| `demo` | demo programs (most of them need \sc{Qt}, geomview or other third-party products) | +| `doc_html` | documentation (HTML) | +| `examples` | example programs | +| `include` | header files | +| `scripts` | some useful scripts (e.g. for creating CMakeLists.txt files) | +| `src` | source files | The directories `include/CGAL/CORE` and `src/CGALCore` contain a @@ -151,17 +125,18 @@ installation manual. The \cgal manual must be downloaded separately from \section seccompilers Supported Compilers -In order to build the \cgal libraries, you need a \cpp compiler. +In order to build a program using \cgal, you need a \cpp compiler +supporting C++14 or later. \cgal \cgalReleaseNumber is supported, that is continuously tested, for the following compilers/operating systems: | Compiler | Operating System | | :------- | :--------------- | -|\sc{Gnu} `g++` 4.1 or later\cgalFootnote{`http://gcc.gnu.org/`} | Linux / MacOS X | +|\sc{Gnu} `g++` 6.3 or later\cgalFootnote{`http://gcc.gnu.org/`} | Linux / MacOS X | | | \sc{MS} Windows | -|\sc{MS} Visual `C++` 12.0, 14.0, 15.9 (\sc{Visual Studio} 2013, 2015, and 2017)\cgalFootnote{`https://visualstudio.microsoft.com/`} | \sc{MS} Windows | -| `Clang` \cgalFootnote{`http://clang.llvm.org/`} compiler version 7.0.1 | Linux | -| Apple `Clang` compiler version 7.0.2 | MacOS X | +|\sc{MS} Visual `C++` 14.0, 15.9, 16.0 (\sc{Visual Studio} 2015, 2017, and 2019)\cgalFootnote{`https://visualstudio.microsoft.com/`} | \sc{MS} Windows | +| `Clang` \cgalFootnote{`http://clang.llvm.org/`} compiler version 8.0.0 | Linux | +| Apple `Clang` compiler versions 7.0.2 and 10.0.1 | MacOS X | It may work for older versions of the above listed compilers. @@ -176,7 +151,7 @@ This manual explains only those features of CMake which are needed in order to build \cgal. Please refer to the CMake documentation at `https://cmake.org/` for further details. -Before building \cgal you have to choose the compiler/linker, +Before building anything using \cgal you have to choose the compiler/linker, set compiler and linker flags, specify which third-party libraries you want to use and where they can be found, and which \cgal libraries you want to build. Gathering @@ -321,7 +296,7 @@ variable `BUILD_SHARED_LIBS` to `FALSE`. If you use \subsubsection subsection_headeronly_withconfiguration Header-only with CMake Configuration -Since \cgal 4.9, \cgal can be used in header-only mode, i.e. without compiling the \cgal libraries and linking with these libraries when compiling examples, tests and demos. This possibility can be enabled by setting the value of the CMake variable `CGAL_HEADER_ONLY` to `ON`. CMake version 3.0.0 or higher is required to use this option. +Since \cgal 4.9, \cgal can be used in header-only mode, i.e. without compiling the \cgal libraries and linking with these libraries when compiling examples, tests and demos. This possibility can be enabled by setting the value of the CMake variable `CGAL_HEADER_ONLY` to `ON`. One advantage of using \cgal in header-only mode is that you do not need to compile and install \cgal libraries before compiling a given example or demo. Note that even in header-only mode we still need to run CMake on \cgal in order to generate different configuration files. So, setting up \cgal becomes now: From 4342262420652423c596e5d9fbc20ef6a90ff72b Mon Sep 17 00:00:00 2001 From: Laurent Rineau Date: Wed, 19 Jun 2019 15:28:27 +0200 Subject: [PATCH 109/363] Remove the section "Custom Flags in the Programs Using CGAL" That section is completely outdated. See https://doc.cgal.org/4.14/Manual/installation.html#title46 --- .../doc/Documentation/Installation.txt | 34 ------------------- 1 file changed, 34 deletions(-) diff --git a/Documentation/doc/Documentation/Installation.txt b/Documentation/doc/Documentation/Installation.txt index 543939cca22..8ee8c146822 100644 --- a/Documentation/doc/Documentation/Installation.txt +++ b/Documentation/doc/Documentation/Installation.txt @@ -828,40 +828,6 @@ libCGAL_ImageIO (ImageIO), and libCGAL_Qt5 A user is free to create the `CMakeLists.txt` without calling the script (manual creation). -\subsection installation_custom Custom Flags in the Programs Using CGAL - -Normally, programs linked with \cgal must be compiled with the same flags -used by the compilation of \cgal libraries. For this reason, the very first time -a program is configured, all the flags given by the CMake variables `CMAKE_*_FLAGS` -are locked in the sense that the values recorded in `CGALConfig.cmake` -are used to override any values given by CMake itself or yourself. - -This does not apply to the additional flags that can be given via `CGAL_*_FLAGS`. - -Such inherited values are then recorded in the current CMake cache for the program. -The flags are then unlocked in the sense that at any subsequent configuration you can -provide your own flags and this time they will not be overridden. - -When using the interactive `cmake-gui` the first press on `Configure` unlocks -the flags, so that you can edit them as needed. - -\cgalAdvancedBegin -The locking of flags is controlled by the variable -`CGAL_DONT_OVERRIDE_CMAKE_FLAGS` which starts out FALSE and is -toggled right after the flags have been loaded from -`CGALConfig.cmake`. - -If you use the command line tool you can specify flags directly by setting the -controlling variable right up front: - -
    -cd CGAL-\cgalReleaseNumber
    -cmake -DCMAKE_BUILD_TYPE=Release -DCMAKE_CXX_FLAGS=-g .
    -cd CGAL-\cgalReleaseNumber/examples/Triangulation_2
    -cmake -DCGAL_DIR=CGAL-\cgalReleaseNumber -DCMAKE_BUILD_TYPE=Debug -DCMAKE_CXX_FLAGS=-O2 -DCGAL_DONT_OVERRIDE_CMAKE_FLAGS=TRUE . 
    -
    -\cgalAdvancedEnd - \section installation_summary Summary of CGAL's Configuration Variables Most configuration variables are not environment variables but From e89dae2a244a7dc4cb413dff589878c32f86a0c6 Mon Sep 17 00:00:00 2001 From: Laurent Rineau Date: Wed, 19 Jun 2019 15:31:23 +0200 Subject: [PATCH 110/363] Remove section "Compiler Optimizations" That section has been both wrong (for several releases), and useless. Se https://doc.cgal.org/4.14/Manual/installation.html#title65 --- Documentation/doc/Documentation/Installation.txt | 5 ----- 1 file changed, 5 deletions(-) diff --git a/Documentation/doc/Documentation/Installation.txt b/Documentation/doc/Documentation/Installation.txt index 8ee8c146822..156aa7e8d1a 100644 --- a/Documentation/doc/Documentation/Installation.txt +++ b/Documentation/doc/Documentation/Installation.txt @@ -1166,10 +1166,5 @@ The file `CGAL/compiler_config.h` is included from ``. which is included by all \cgal header files. -\section seccompileroptimisations Compiler Optimizations - -By default CMake generates makefiles for Release mode, with -optimization flags switched on, and vcproj files for Release -and Debug modes. */ From cd17a9486ebae4d62dd98469cbbf0cdb22797b5f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mael=20Rouxel-Labb=C3=A9?= Date: Fri, 12 Jul 2019 09:04:15 +0200 Subject: [PATCH 111/363] Re-organize Manual for 5.0 (WIP) --- .../Documentation/Configuration_variables.txt | 346 ++++++ .../Developer_manual/Chapter_portability.txt | 4 +- .../doc/Documentation/Getting_started.txt | 5 +- .../doc/Documentation/Installation.txt | 1073 +---------------- .../doc/Documentation/Preliminaries.txt | 10 +- .../doc/Documentation/Third_party.txt | 259 ++++ Documentation/doc/Documentation/Usage.txt | 338 ++++++ 7 files changed, 999 insertions(+), 1036 deletions(-) create mode 100644 Documentation/doc/Documentation/Configuration_variables.txt create mode 100644 Documentation/doc/Documentation/Third_party.txt create mode 100644 Documentation/doc/Documentation/Usage.txt diff --git a/Documentation/doc/Documentation/Configuration_variables.txt b/Documentation/doc/Documentation/Configuration_variables.txt new file mode 100644 index 00000000000..7403a1ded71 --- /dev/null +++ b/Documentation/doc/Documentation/Configuration_variables.txt @@ -0,0 +1,346 @@ +/*! + +\page configurationvariables Summary of CGAL's Configuration Variables +\cgalAutoToc +\author %CGAL Editorial Board + + +\section installation_summary Summary of CGAL's Configuration Variables + +Most configuration variables are not environment variables but +CMake variables. They are given in the command line to CMake +via the `-D` option, or passed from the interactive interface +of `cmake-gui`. Unless indicated differently, all the variables +summarized below are CMake variables. + +\subsection installation_component_selection Component Selection + +The following boolean variables indicate which \cgal components to +configure and build. Their values can be ON or OFF. + + +| Variable | %Default Value | +| :------- | :--------------- | +| `WITH_examples` | OFF | +| `WITH_demos` | OFF | +| `WITH_CGAL_Core` | ON | +| `WITH_CGAL_Qt5` | ON | +| `WITH_CGAL_ImageIO` | ON | + +\subsection installation_flags Compiler and Linker Flags + +The following variables specify compiler and linker flags. Each variable holds a +space-separated list of command-line switches for the compiler and linker and +their default values are automatically defined by CMake based on the target platform. + +Have in mind that these variables specify a list of flags, not just one +single flag. If you provide your own definition for a variable, you will entirely override +the list of flags chosen by CMake for that particular variable. + +The variables that correspond to both debug and release builds are always +used in conjunction with those for the specific build type. + + +| Program | Both Debug and Release | Release Only | Debug Only | +| :------ | :---------------------- | :------------- | :----------- | +| C++ Compiler | `CMAKE_CXX_FLAGS` | `CMAKE_CXX_FLAGS_RELEASE` | `CMAKE_CXX_FLAGS_DEBUG` | +| Linker (shared libs) | `CMAKE_SHARED_LINKER_FLAGS` | `CMAKE_SHARED_LINKER_FLAGS_RELEASE` | `CMAKE_SHARED_LINKER_FLAGS_DEBUG` | +| Linker (static libs) | `CMAKE_MODULE_LINKER_FLAGS` | `CMAKE_MODULE_LINKER_FLAGS_RELEASE` | `CMAKE_MODULE_LINKER_FLAGS_DEBUG` | +| Linker (programs) | `CMAKE_EXE_LINKER_FLAGS` | `CMAKE_EXE_LINKER_FLAGS_RELEASE` | `CMAKE_EXE_LINKER_FLAGS_DEBUG`| + + +\subsection installation_additional_flags Additional Compiler and Linker Flags + +The following variables can be used to add flags without overriding the ones +defined by cmake. + + +| Program | Both Debug and Release | Release Only | Debug Only | +| :------ | :---------------------- | :------------- | :----------- | +| C++ Compiler | `CGAL_CXX_FLAGS` | `CGAL_CXX_FLAGS_RELEASE` | `CGAL_CXX_FLAGS_DEBUG` | +| Linker (shared libs) | `CGAL_SHARED_LINKER_FLAGS` | `CGAL_SHARED_LINKER_FLAGS_RELEASE` | `CGAL_SHARED_LINKER_FLAGS_DEBUG` | +| Linker (static libs) | `CGAL_MODULE_LINKER_FLAGS` | `CGAL_MODULE_LINKER_FLAGS_RELEASE` | `CGAL_MODULE_LINKER_FLAGS_DEBUG` | +| Linker (programs) | `CGAL_EXE_LINKER_FLAGS` | `CGAL_EXE_LINKER_FLAGS_RELEASE` | `CGAL_EXE_LINKER_FLAGS_DEBUG` | + +\subsection installation_misc Miscellaneous Variables + + +| Variable | Description | Type | %Default Value | +| :- | :- | :- | :- | +| `CMAKE_BUILD_TYPE` | Indicates type of build. Possible values are 'Debug' or 'Release' | CMake | Release | +| `CMAKE_CXX_COMPILER` | Full-path to the executable corresponding to the C++ compiler to use. | CMake | platform-dependent | +| `CXX` | Idem | Environment | Idem | + + +\subsection installation_variables_building Variables Used Only When Building Programs (Such as Demos or Examples) + + +| Variable | Description | Type | %Default Value | +| :- | :- | :- | :- | +| `CGAL_DIR` | Full-path to the binary directory where \cgal was configured |Either CMake or Environment | none | + + +\subsection installation_variables_third_party Variables Providing Information About 3rd-Party Libraries +\anchor sec3partysoftwareconfig + +The following variables provide information about the availability and +location of the 3rd party libraries used by \cgal. CMake automatically +searches for dependencies so you need to specify these variables if +CMake was unable to locate something. This is indicated by a value ending in +`NOTFOUND`. + +Since 3rd-party libraries are system wide, many of the CMake variables listed below can alternatively +be given as similarly-named environment variables instead. Keep in mind that you must provide one or the +other but never both. + +\subsection installation_boost Boost Libraries + +In most cases, if \sc{Boost} is not automatically found, setting the `BOOST_ROOT` +variable is enough. If it is not, you can specify the header and library +directories individually. You can also provide the full pathname to a specific compiled library +if it cannot be found in the library directory or its name is non-standard. + +By default, when \sc{Boost} binary libraries are needed, the shared versions +are used if present. You can set the variable +`CGAL_Boost_USE_STATIC_LIBS` to `ON` if you want to link +with static versions explicitly. + +On Windows, if you link with \sc{Boost} shared libraries, you must ensure that +the `.dll` files are found by the dynamic linker, at run time. +For example, you can add the path to the \sc{Boost} `.dll` to the +`PATH` environment variable. + +| Variable | Description | Type | +| :- | :- | :- | +| `BOOST_ROOT`\cgalFootnote{The environment variable can be spelled either `BOOST_ROOT` or `BOOSTROOT`} | Root directory of your \sc{Boost} installation | Either CMake or Environment | +| `Boost_INCLUDE_DIR` | Directory containing the `boost/version.hpp` file | CMake | +| `BOOST_INCLUDEDIR` | Idem | Environment | +| `Boost_LIBRARY_DIRS` | Directory containing the compiled \sc{Boost} libraries | CMake | +| `BOOST_LIBRARYDIR` | Idem | Environment | +| `Boost_(xyz)_LIBRARY_RELEASE` | Full pathname to a release build of the compiled 'xyz' \sc{Boost} library | CMake | +| `Boost_(xyz)_LIBRARY_DEBUG` | Full pathname to a debug build of the compiled 'xyz' \sc{Boost} library | CMake | + + +\subsection installation_gmp GMP and MPFR Libraries + +Under Windows, auto-linking is used, so only the directory +containing the libraries is needed and you would specify `GMP|MPFR_LIBRARY_DIR` rather than +`GMP|MPFR_LIBRARIES`. On the other hand, under Linux the actual library filename is needed. +Thus you would specify `GMP|MPFR_LIBRARIES`. In no case you need to specify both. + +\cgal uses both \sc{Gmp} and \sc{Mpfr} so both need to be supported. If either of them is unavailable the +usage of \sc{Gmp} and of \sc{Mpfr} will be disabled. + + +| Variable | Description | Type | +| :- | :- | :- | +| `CGAL_DISABLE_GMP` | Indicates whether to search and use \sc{Gmp}/\sc{Mpfr} or not | CMake | +| `GMP_DIR` | Directory of \sc{Gmp} default installation | Environment | +| `GMP_INCLUDE_DIR` | Directory containing the `gmp.h` file | CMake | +| `GMP_INC_DIR` | Idem | Environment | +| `GMP_LIBRARIES_DIR` | Directory containing the compiled \sc{Gmp} library | CMake | +| `GMP_LIB_DIR` | Idem | Environment | +| `GMP_LIBRARIES` | Full pathname of the compiled \sc{Gmp} library | CMake | +| `MPFR_INCLUDE_DIR` | Directory containing the `mpfr.h` file | CMake | +| `MPFR_INC_DIR` | Idem | Environment | +| `MPFR_LIBRARIES_DIR` | Directory containing the compiled \sc{Mpfr} library | CMake | +| `MPFR_LIB_DIR` | Idem | Environment | +| `MPFR_LIBRARIES` | Full pathname of the compiled \sc{Mpfr} library | CMake | + + + +Under Linux, the \sc{Gmpxx} is also searched for, and you may specify the following variables: + + +| Variable | Description | Type | +| :- | :- | :- | +| `GMPXX_DIR` | Directory of \sc{gmpxx} default installation | Environment | +| `GMPXX_INCLUDE_DIR` | Directory containing the `gmpxx.h` file | CMake | +| `GMPXX_LIBRARIES` | Full pathname of the compiled \sc{Gmpxx} library | CMake | + + + +\subsection installation_qt5 Qt5 Library + +You must set the cmake or environment variable `Qt5_DIR` to point to the path +to the directory containing the file `Qt5Config.cmake` created by your \sc{Qt}5 installation. If you are +using the open source edition it should be `/qt-everywhere-opensource-src-/qtbase/lib/cmake/Qt5`. + +\subsection installation_leda LEDA Library + +When the \leda libraries are not automatically found, yet they are installed on the system +with base names 'leda' and 'ledaD' (for the release and debug versions resp.), it might +be sufficient to just indicate the library directory via the `LEDA_LIBRARY_DIRS` variable. +If that doesn't work because, for example, the names are different, you can provide the full pathnames of each variant +via `LEDA_LIBRARY_RELEASE` and `LEDA_LIBRARY_DEBUG`. + +The variables specifying definitions and flags can be left undefined if they are not needed by LEDA. + + +| Variable | Description | Type | +| :- | :- | :- | +| `WITH_LEDA` | Indicates whether to search and use \leda or not | CMake | +| `LEDA_DIR` | Directory of \sc{LEDA} default installation | Environment | +| `LEDA_INCLUDE_DIR` | Directory containing the file `LEDA/system/basic.h` | CMake | +| `LEDA_LIBRARIES` | Directory containing the compiled \leda libraries | CMake | +| `LEDA_INC_DIR` | Directory containing the file `LEDA/system/basic.h` | Environment | +| `LEDA_LIB_DIR` | Directory containing the compiled \leda libraries | Environment | +| `LEDA_LIBRARY_RELEASE` | Full pathname to a release build of the \leda library | CMake | +| `LEDA_LIBRARY_DEBUG` | Full pathname to a debug build of the \leda library | CMake | +| `LEDA_DEFINITIONS` | Preprocessor definitions | CMake | +| `LEDA_CXX_FLAGS` | Compiler flags | CMake | +| `LEDA_LINKER_FLAGS` | Linker flags | CMake | + + +\subsection installation_mpfi MPFI Library + +\cgal provides a number type based on this library, but the \cgal library +itself does not depend on \sc{Mpfi}. This means that this library must be +configured when compiling an application that uses the above number type. + +When \sc{Mpfi} files are not on the standard path, the locations of the headers +and library files must be specified by using environment variables. + + +| Variable | Description | Type | +| :- | :- | :- | +| `MPFI_DIR` |Directory of \sc{MPFI} default installation | Environment | +| `MPFI_INCLUDE_DIR` | Directory containing the `mpfi.h` file | CMake | +| `MPFI_INC_DIR` | Idem | Environment | +| `MPFI_LIBRARIES_DIR` | Directory containing the compiled \sc{Mpfi} library | CMake | +| `MPFI_LIB_DIR` | Idem | Environment | +| `MPFI_LIBRARIES` | Full pathname of the compiled \sc{Mpfi} library | CMake | + + + +\subsection installation_rs RS and RS3 Library + +As said before, only the \cgal univariate algebraic kernel depends on the +library Rs. As the algebraic kernel is not compiled as a part of the \cgal +library, this library is not detected nor configured at installation time. + +CMake will try to find Rs in the standard header and library +directories. When it is not automatically detected, the locations of the +headers and library files must be specified using environment variables. + +Rs needs \sc{Gmp} 4.2 or later and \sc{Mpfi} 1.3.4 or later. The variables +related to the latter library may also need to be defined. + + +| Variable | Description | Type | +| :- | :- | :- | +| `RS_DIR` | Directory of \sc{Rs} default installation | Environment | +| `RS_INCLUDE_DIR` | Directory containing the `rs_exports.h` file | CMake | +| `RS_INC_DIR` | Idem | Environment | +| `RS_LIBRARIES_DIR` | Directory containing the compiled \sc{Rs} library | CMake | +| `RS_LIB_DIR` | Idem | Environment | +| `RS_LIBRARIES` | Full pathname of the compiled \sc{Rs} library | CMake | + +Similar variables exist for \sc{Rs3}. + +| Variable | Description | Type | +| :- | :- | :- +| `RS3_DIR` | Directory of \sc{Rs3} default installation | Environment | +| `RS3_INCLUDE_DIR` | Directory containing the file `rs3_fncts.h` file | CMake | +| `RS3_INC_DIR` | Idem | Environment | +| `RS3_LIBRARIES_DIR` | Directory containing the compiled \sc{Rs3} library | CMake | +| `RS3_LIB_DIR` | Idem | Environment | +| `RS3_LIBRARIES` | Full pathname of the compiled \sc{Rs3} library | CMake | + + +\subsection installation_ntl NTL Library + +Some polynomial computations in \cgal's algebraic kernel +are speed up when \sc{Ntl} is available. +As the algebraic kernel is not compiled as a part of the \cgal +library, this library is not detected nor configured at installation time. + +CMake will try to find \sc{Ntl} in the standard header and library +directories. When it is not automatically detected, the locations of the +headers and library files must be specified using environment variables. + +| Variable | Description | Type | +| :- | :- | :- | +| `NTL_DIR` | Directory of \sc{NTL} default installation | Environment | +| `NTL_INCLUDE_DIR` | Directory containing the `NTL/ZZX.h` file | CMake | +| `NTL_INC_DIR` | Idem | Environment | +| `NTL_LIBRARIES_DIR` | Directory containing the compiled \sc{Ntl} library | CMake | +| `NTL_LIB_DIR` | Idem | Environment | +| `NTL_LIBRARIES` | Full pathname of the compiled \sc{Ntl} library | CMake | + +\subsection installation_eigen Eigen Library + +\sc{Eigen} is a header-only template library. +Only the directory containing the header files of \sc{Eigen} 3.1 (or greater) is needed. + + +| Variable | Description | Type | +| :- | :- | :- | +| `EIGEN3_INCLUDE_DIR` | Directory containing the file `signature_of_eigen3_matrix_library` | CMake | +| `EIGEN3_INC_DIR` | Idem | Environment | + +\subsection installation_esbtl ESBTL Library + +One skin surface example requires the \sc{Esbtl} library in order to read \sc{Pdb} files. + +If \sc{Esbtl} is not automatically found, setting the `ESBTL_INC_DIR` +environment variable is sufficient. + + +| Variable | Description | Type | +| :- | :- | :- | +| `ESBTL_DIR` | Directory of \sc{ESBTL} default installation | Environment | +| `ESBTL_INC_DIR` | Directory containing the `ESBTL/default.h` file | Environment | +| `ESBTL_INCLUDE_DIR` | Directory containing the `ESBTL/default.h` file | CMake | + +\subsection installation_tbb TBB Library + +If \sc{Tbb} is not automatically found, the user must set the `TBBROOT` +environment variable. The environment variable `TBB_ARCH_PLATFORM=/` must be set. +`` is `ia32` or `intel64`. `` describes the Linux kernel, gcc version or Visual Studio version +used. It should be set to what is used in `$TBBROOT/lib/`. + +For windows users, the folder `TBBROOT/bin//` should be added to the `PATH` variable. + +Note that the variables in the table below are being used. + +| Variable | Description | Type | +| :- | :- | :- | +| `TBBROOT` | Directory of \sc{Tbb} default installation | Environment | +| `TBB_INCLUDE_DIRS` | Directory containing the `tbb/tbb.h` file | CMake | +| `TBB_LIBRARY_DIRS` | Directory(ies) containing the compiled TBB libraries | CMake | +| `TBB_LIBRARIES` | Full pathnames of the compiled TBB libraries (both release and debug versions, using "optimized" and "debug" CMake keywords). Note that if the debug versions are not found, the release versions will be used instead for the debug mode. | CMake | +| `TBB_RELEASE_LIBRARY` | Full pathname of the compiled TBB release library | CMake | +| `TBB_MALLOC_RELEASE_LIBRARY` | Full pathname of the compiled TBB release malloc library | CMake | +| `TBB_DEBUG_LIBRARY` | Full pathname of the compiled TBB debug library | CMake | +| `TBB_MALLOC_DEBUG_LIBRARY` | Full pathname of the compiled TBB debug malloc library | CMake | +| `TBB_MALLOCPROXY_DEBUG_LIBRARY` | Full pathname of the compiled TBB debug malloc_proxy library (optional) | CMake | +| `TBB_MALLOCPROXY_RELEASE_LIBRARY` | Full pathname of the compiled TBB release malloc_proxy library (optional) | CMake | + +\section installation_compiler_workarounds Compiler Workarounds + +A number of boolean flags are used to workaround compiler bugs and +limitations. They all start with the prefix `CGAL_CFG`. These +flags are used to work around compiler bugs and limitations. For +example, the flag `CGAL_CFG_NO_CPP0X_LONG_LONG` denotes +that the compiler does not know the type `long long`. + +For each installation a file +is defined, with the correct +settings of all flags. This file is generated automatically by CMake, +and it is located in the `include` directory of where you run +CMake. For an in-source configuration this means +`CGAL-\cgalReleaseNumber``/include`. + +The test programs used to generate the `compiler_config.h` +file can be found in `config/testfiles`. +Both +`compiler_config.h` and the test programs contain a short +description of the problem. In case of trouble with one of the +`CGAL_CFG` flags, it is a good idea to take a look at it. + +The file `CGAL/compiler_config.h` is included from +``. +which is included by all \cgal header files. + +*/ diff --git a/Documentation/doc/Documentation/Developer_manual/Chapter_portability.txt b/Documentation/doc/Documentation/Developer_manual/Chapter_portability.txt index 84a7d8078b4..16ef913c408 100644 --- a/Documentation/doc/Documentation/Developer_manual/Chapter_portability.txt +++ b/Documentation/doc/Documentation/Developer_manual/Chapter_portability.txt @@ -236,8 +236,8 @@ operating system and compiler that is defined as follows. quite compiler specific). -Examples are mips_IRIX64-6.5_CC-n32-7.30 or sparc_SunOS-5.6_g++-2.95. For more information, see the \cgal -\link installation installation guide \endlink. +Examples are mips_IRIX64-6.5_CC-n32-7.30 or sparc_SunOS-5.6_g++-2.95. +For more information, see the \cgal \link usage usage guide \endlink. This platform-specific configuration file is created during diff --git a/Documentation/doc/Documentation/Getting_started.txt b/Documentation/doc/Documentation/Getting_started.txt index d8dcfa659f2..a9ea3882e0b 100644 --- a/Documentation/doc/Documentation/Getting_started.txt +++ b/Documentation/doc/Documentation/Getting_started.txt @@ -1,13 +1,14 @@ /*! \page general_intro Getting Started -- \subpage installation describes how to install %CGAL, and lists the third party libraries on which %CGAL depends, or for which %CGAL provides interfaces. +- \subpage usage describes how to use %CGAL - \subpage manual gives an idea where you should look for documentation. The documentation for a class, may be spread over manual pages of base classes, and reference manual pages of concepts the class is a model of. - - \subpage preliminaries lists the licenses under which the %CGAL datastructures and algorithms are distributed, how to control inlining, thread safety, code deprecation, checking of pre- and postconditions, and how to alter the failure behavior. +- \subpage thirdparty lists the third party libraries on which %CGAL depends, or for which %CGAL provides interfaces. + */ diff --git a/Documentation/doc/Documentation/Installation.txt b/Documentation/doc/Documentation/Installation.txt index 156aa7e8d1a..82899c3489b 100644 --- a/Documentation/doc/Documentation/Installation.txt +++ b/Documentation/doc/Documentation/Installation.txt @@ -3,265 +3,14 @@ \cgalAutoToc \authors Eric Berberich, Joachim Reichel, and Fernando Cacciola -\section installation_introduction Introduction - -Since \cgal version 5.0, \cgal is header-only be default, which means +Since \cgal version 5.0, \cgal is header-only be default, which means that there is no need to compile and install anything before it can be -used. The dependencies of \cgal still have to be installed. +used. However, the dependencies of \cgal might still need to be installed. -Ideally, compiling an example or a demo shipped with \cgal is -as simple as: +\section seclibraries CGAL Libraries - cd examples/Triangulation_2 # go to an example directory - cmake -DCGAL_DIR=$HOME/CGAL-\cgalReleaseNumber . # configure the examples - make # build the examples - - cd demo/Triangulation_2 # go to a demo directory - cmake -DCGAL_DIR=$HOME/CGAL-\cgalReleaseNumber . # configure the demos - make # build the demos - -Compiling an own non-shipped program is also close: - - cd /path/to/program - cgal_create_CMakeLists -s executable - cmake -DCGAL_DIR=$HOME/CGAL-\cgalReleaseNumber . - make - -where the second line creates a `CMakeLists.txt` file (check -its options in Section \ref seccreate_cgal_CMakeLists for various details). - - -In a less ideal world, you probably have to install required tools, and third party libraries. That is what this manual is about. - -\section secprerequisites Prerequisites - -Using \cgal requires a few components to be installed ahead: a -supported compiler (see Section \ref seccompilers), \sc{Boost}, \sc{Gmp}, and \sc{Mpfr}; see -Section \ref secessential3rdpartysoftware for more details on -essential third party software. - -\section secshippedcgal OS Specific Installation - -Some operating systems with package managers offer \cgal and its -essential third party software through the manager, -for instance, Mac OS X, or some Linux distribution (e.g. Debian). -For Windows, an installer is provided. - -\subsection sseccgalmacosxe CGAL on macOS - -The \cgal project recommends the use of Homebrew, in the following way: - - brew install cgal - -\subsection sseccgaldebian CGAL on Linux - -For instance in Debian/Ubuntu, use apt-get in the following way: - - sudo apt-get install libcgal-dev - -To get the demos use - - sudo apt-get install libcgal-demo - -Check the \cgal-FAQ for source repository of newest releases. - -On other distributions, please consult your package manager documentation. - -\subsection sseccgalwindows CGAL on Windows - -You can download and run `CGAL-\cgalReleaseNumber``-Setup.exe` from https://www.cgal.org/download/windows.html. -It is a self extracting executable that installs the \cgal source, and that allows you -to select and download some precompiled third party libraries. However, you will need to compile -the library using your favorite compiler. - -A tutorial is provided on how to proceed with Microsoft Visual Studio. - - - -\section secgettingcgal Downloading CGAL - -You can obtain the \cgal library from -https://www.cgal.org/download.html -and install it yourself. - -After you have downloaded the file `CGAL-\cgalReleaseNumber``.tar.gz` containing the -\cgal sources, you have to unpack it. Under a Unix-like shell, use the -command: - -
    -tar xzf CGAL-\cgalReleaseNumber.tar.gz
    -
    - -In both cases the directory `CGAL-\cgalReleaseNumber` will be created. This directory -contains the following subdirectories: - - -| Directory | Contents | -| :----------- | :----------| -| `auxiliary` | precompiled \sc{Gmp} and \sc{Mpfr} for Windows | -| `cmake/modules` | modules for finding and using libraries | -| `config` | configuration files for install script | -| `demo` | demo programs (most of them need \sc{Qt}, geomview or other third-party products) | -| `doc_html` | documentation (HTML) | -| `examples` | example programs | -| `include` | header files | -| `scripts` | some useful scripts (e.g. for creating CMakeLists.txt files) | -| `src` | source files | - - -The directories `include/CGAL/CORE` and `src/CGALCore` contain a -distribution of the \sc{Core} library\cgalFootnote{`https://cs.nyu.edu/exact/`} version 1.7 for -dealing with algebraic numbers. \sc{Core} is not part of \cgal and has its -own license. - -The directory `include/CGAL/OpenNL` contains a distribution of the -Open Numerical Library which provides solvers for sparse linear systems, -especially designed for the Computer Graphics community. \sc{OpenNL} is not part -of \cgal and has its own license. - -The only documentation shipped with \cgal sources is the present -installation manual. The \cgal manual must be downloaded separately from -`https://www.cgal.org/download.html`. - -\section seccompilers Supported Compilers - -In order to build a program using \cgal, you need a \cpp compiler -supporting C++14 or later. -\cgal \cgalReleaseNumber is supported, that is continuously tested, for the following compilers/operating systems: - - -| Compiler | Operating System | -| :------- | :--------------- | -|\sc{Gnu} `g++` 6.3 or later\cgalFootnote{`http://gcc.gnu.org/`} | Linux / MacOS X | -| | \sc{MS} Windows | -|\sc{MS} Visual `C++` 14.0, 15.9, 16.0 (\sc{Visual Studio} 2015, 2017, and 2019)\cgalFootnote{`https://visualstudio.microsoft.com/`} | \sc{MS} Windows | -| `Clang` \cgalFootnote{`http://clang.llvm.org/`} compiler version 8.0.0 | Linux | -| Apple `Clang` compiler versions 7.0.2 and 10.0.1 | MacOS X | - -It may work for older versions of the above listed compilers. - - -\section secconfigwithcmake Configuring CGAL with CMake - -In order to configure, build, and install the \cgal libraries, examples and -demos, you need CMake, a cross-platform "makefile generator". -If CMake is not installed already you can obtain it from `https://cmake.org/`. -CMake version 3.1 or higher is required. -This manual explains only those features of -CMake which are needed in order to build \cgal. Please refer to the -CMake documentation at `https://cmake.org/` for further details. - -Before building anything using \cgal you have to choose the compiler/linker, -set compiler and linker flags, specify which -third-party libraries you want to use and where they can be found, and -which \cgal libraries you want to build. Gathering -all this information is called configuration. -The end of the process is marked by the generation of a makefile or a -Visual \cpp solution and project file that you can use to build \cgal. - -\subsection installation_configuring_gui Configuring CGAL with the CMake GUI - -The simplest way to start the configuration is to run the graphical -user interface of CMake. We recommend to use `cmake-gui`. You must pass as -argument the root directory of \cgal. For example: - -
    -cd CGAL-\cgalReleaseNumber
    -cmake-gui . # Notice the dot to indicate the current directory.
    -
    - -After `cmake-gui` opens, press 'Configure'. -A dialog will pop up and you will have to choose what shall gets generated. -After you have made your choice and pressed 'Finish', you will see -the output of configuration tests in the lower portion of the application. -When these tests are done, you will see many -red entries in the upper portion of the application. Just ignore them and press 'Configure'. -By now CMake should have found many libraries and have initialized variables. -If you still find red entries, you have to provide the necessary information. -This typically happens if you have installed software at non-standard locations. -Providing information and pressing 'Configure' goes on until -all entries are grayed. You are now ready to press 'Generate'. Once this is -done, you can quit `cmake-gui`. - -\subsection installation_configuring_cmd Configuring CGAL with the cmake Command-Line Tool - -Alternatively, you can run the command-line tool called -`cmake`. You pass as argument the root directory of -\cgal. For example: - -
    -cd CGAL-\cgalReleaseNumber
    -cmake . # Notice the dot to indicate the current directory.
    -
    - -The very first thing CMake does is to detect the compiler to use. This -detection is performed by a special CMake module called a -generator. -A CMake generator understands the build requirements for a -particular compiler/linker and generates the necessary files for that. For -example, the UNIX Makefiles generator understands the GNU chain -of tools (\gcc, ld etc.) and produces makefiles, which can be used to build a -target by a simple call to `make`. Likewise, the Visual Studio -2010 generator produces solution and project files and can be manually -launched in the VS IDE to build the target. - -Each platform has a default generator, so you only need to select one when -the default is not what you want. For example, under Windows, it is -possible to generate NMakefiles instead of Visual Studio project -files in order to build the library with `nmake`. Running -`cmake` with no parameters in a command-line prints the list of -available generators supported by your platform and CMake version. If the -generator you need is not listed there, you can try a newer -CMake version, as generators are hardcoded into CMake, and additional -generators are added with each release. - -Since the choice of the generator determines the type of build files to generate, in some cases -you choose a particular generator as a mean to choose a specific compiler (because they use different -build files). For example, the following generates solution files for -use in Visual \cpp 15.0 on a 64bit machine: - -
    -cd CGAL-\cgalReleaseNumber
    -cmake -G"Visual Studio 15 2017 Win64" . 
    -
    - -In other cases, however, the generator doesn't directly identify a -specific compiler but a chain of tools. -For example, the `UNIX Makefiles` generator produces `makefiles` that call some auto-detected -command-line compiler, like \gcc. If you need the makefiles to use a different compiler, you need to -specify the desired compiler in the call to CMake, as in this example: - -
    -cd CGAL-\cgalReleaseNumber
    -cmake -DCMAKE_CXX_COMPILER:FILEPATH=g++-4.7 . 
    -
    - -CMake maintains configuration parameters in so-called cmake variables, like the `CMAKE_CXX_COMPILER` -in the example above. These variables are not environment variables but CMake variables. Some of the CMake -variables represent user choices, such as `WITH_examples` or `CMAKE_BUILD_TYPE=Release`, while others -indicate the details of a third-party library, such as `Boost_INCLUDE_DIR` or the compiler flags to use, -such as `CMAKE_CXX_FLAGS`. - -The command line tool `cmake` accepts CMake variables as arguments of the form `-D:=`, as -in the example above, but this is only useful if you already know which variables need to be explicitly defined. - -\cgalAdvancedBegin -CMake keeps the variables that a user can manipulate in a -so-called CMake cache, a simple text file named -`CMakeCache.txt`, whose entries are of the form -`VARIABLE:TYPE=VALUE`. Advanced users can manually edit this file, -instead of going through the interactive configuration session. -\cgalAdvancedEnd - -The configuration process not only determines the location of the required dependencies, it also dynamically generates a -`compiler_config.h` file, which encodes the properties of your system and a special file named -`CGALConfig.cmake`, which is used to build programs using \cgal. The -purpose of this file is explained below. - -\section seclibraries CGAL Libraries - -\cgal is split into four libraries. During configuration, you can select the libraries that -you would like to build by setting a CMake variable of the form WITH_. By default all +\cgal is split into four libraries. During configuration, you can select the libraries that +you would like to build by setting a CMake variable of the form WITH_. By default all are switched `ON`. All activated libraries are build after configuration; see \ref secbuilding @@ -292,137 +41,6 @@ can choose to produce static libraries instead by setting the CMake variable `BUILD_SHARED_LIBS` to `FALSE`. If you use `cmake-gui`, a tick box for that variable is available to set it. -\subsection subsection_headeronly Header-only Option - -\subsubsection subsection_headeronly_withconfiguration Header-only with CMake Configuration - -Since \cgal 4.9, \cgal can be used in header-only mode, i.e. without compiling the \cgal libraries and linking with these libraries when compiling examples, tests and demos. This possibility can be enabled by setting the value of the CMake variable `CGAL_HEADER_ONLY` to `ON`. - -One advantage of using \cgal in header-only mode is that you do not need to compile and install \cgal libraries before compiling a given example or demo. Note that even in header-only mode we still need to run CMake on \cgal in order to generate different configuration files. So, setting up \cgal becomes now: - -
    -cd CGAL-\cgalReleaseNumber # go to \cgal directory
    -cmake -DCGAL_HEADER_ONLY=ON . # configure \cgal
    -
    - -and we do not need to run `make` anymore. - -\subsubsection subsection_headeronly_without_configuration Header-only without CMake Configuration - -Since \cgal 4.12, \cgal can be used in header-only mode, without even -configuring \cgal\. Programs using \cgal (examples, tests, demos, etc.) -must be directly configured using CMake. In this case, \cgal will be -configured at the same time. The variable `CGAL_DIR` must point to the root -directory of the \cgal source code (either the root of the unpacked release -tarball, or the root of the Git working directory). - -So, using \cgal becomes now: - -
    -cd /path/to/your/code # go to the directory of the code source using \cgal
    -cmake -DCGAL_DIR= .
    -
    - -\subsubsection subsection_headeronly_dependencies CGAL Dependencies - -\cgal can be used as a header-only library, though not all its dependencies -are header-only. The libraries \sc{Gmp} and \sc{Mpfr}, for example, are not -header-only. - -\subsubsection subsection_headeronly_pbonwindows Possible Problem on Windows - -There is one possible problem when using \cgal in header-only mode on a Windows operating system when compiling a program using several modules (executable programs or dynamic-link libraries DLL). If two different modules use the same static variable, this variable is defined independently in each of these modules. If one module modifies the value of this variable, it will not be modified in the other module, which could induce an unexpected behavior. In \cgal, this concerns only a few specific variables: the default random, the failure behavior, `CGAL::IO::Mode`. One example is the following: if you change the default random in one DLL, then if you use the default random in another DLL, you will not obtain the modified default random but the original one. - -\section secessential3rdpartysoftware Essential Third Party Libraries - -The focus of \cgal is on geometry, and we rely on other -highly specialized libraries and software for non-geometric issues, -for instance, for numeric solvers, or visualization. We first list software -that is essential to build (all) libraries of \cgal, that is, -this software must be found during the configuration of \cgal for an -actived library of \cgal (i.e.\ WITH_=ON); -see \ref sec3partysoftwareconfig to specify the location of 3rd -party software. - -The libraries \stl (shipped with any compiler) and \sc{Boost} are essential to all components (i.e.\ libCGAL, -libCGAL_Core, libCGAL_ImageIO, and libCGAL_Qt5). - -\subsection thirdpartystl Standard Template Library (STL) - -\cgal heavily uses the \stl, and in particular adopted -many of its design ideas. You can find online -documentation for the \stl at various web sites, for instance, -`http://www.cplusplus.com/reference/`, -or `https://msdn.microsoft.com/en-us/library/1fe2x6kt(v=vs.140).aspx`. - -The \stl comes with the compiler, so there is nothing to install. - -\subsection thirdpartyBoost Boost - -The \sc{Boost} libraries are a set of portable C++ source libraries. Most of -\sc{Boost} libraries are header-only, but a few of them need to be compiled or -installed as binaries. - -\cgal only requires the headers of the \sc{Boost} libraries, but some demos and examples depend on the binary library `Boost.Program_options`. - -As an exception, because of a bug in the \gcc compiler about the \cpp 11 -keyword `thread_local`, the `CGAL_Core` library always requires -the binary library `Boost.Thread` if the \gcc compiler version 9.0 or -earlier is used. - -In case the \sc{Boost} libraries are not installed on your system already, you -can obtain them from `https://www.boost.org/`. For Visual C++ you can download precompiled libraries -from `https://sourceforge.net/projects/boost/files/boost-binaries/`. - -As on Windows there is no canonical directory for where to find -\sc{Boost}, we recommend that you define the environment variable -`BOOST_ROOT` and set it to where you have installed \sc{Boost}, e.g., -`C:\boost\boost_1_41_0`. - -\subsection thirdpartyMPFR GMP and MPFR - -The components libCGAL, libCGAL_Core, and libCGAL_Qt5 require -\sc{Gmp} and \sc{Mpfr} which are libraries for multi precision integers and rational numbers, -and for multi precision floating point numbers. - -\cgal combines floating point arithmetic with exact arithmetic, -in order to be efficient and reliable. \cgal has a built-in -number type for that, but \sc{Gmp} and \sc{Mpfr} provide a faster -solution, and we recommend to use them. - -Having \sc{Gmp} version 4.2 or higher and \sc{Mpfr} version 2.2.1 or higher -installed is recommended. These libraries can be obtained from -`https://gmplib.org/` and `https://www.mpfr.org/`, respectively. - -As Visual \cpp is not properly -supported by the \sc{Gmp} and \sc{Mpfr} projects, we provide precompiled versions -of \sc{Gmp} and \sc{Mpfr}, which can be downloaded with the installer -`CGAL-\cgalReleaseNumber``-Setup.exe`. - -\subsection thirdpartyzlib zlib - -\sc{zlib} is a data compression library, and is essential for the component libCGAL_ImageIO. - -In \cgal this library is used in the examples of the \ref PkgSurfaceMesher3Ref package. - -If it is not already on your system, -for instance, on Windows, you can download it from `http://www.zlib.net/`. - -\subsection thirdpartyQt Qt5 - -Qt is a cross-platform application and UI framework. - -The component libCGAL_Qt5 requires \sc{Qt}5 installed on your system. -In case \sc{Qt} is not yet installed on your system, you can download -it from `http://www.qt-project.org/`. - - -The exhaustive list of \sc{Qt}5 components used in demos is: -`Core`, `Gui`, `Help`, `OpenGL`, `Script`, `ScriptTools`, `Svg`, `Widgets`, -`qcollectiongenerator` (with `sqlite` driver plugin) and `Xml`. - -\sc{Qt} version 5.9.0 or later is required. - \section installation_examples CGAL Examples and Demos \cgal is distributed with a large collection of examples and demos. By default, these are not configured along with @@ -431,165 +49,24 @@ the \cgal libraries, unless you set the variables `WITH_examples=ON` and/or `WIT Nevertheless, even when configured with \cgal, they are not automatically built along with the libraries. You must build the `examples` or `demos` targets (or IDE projects) explicitly. -If you do not plan to compile any demos, you might skip some of the essential libraries (as \sc{Qt}), +If you do not plan to compile any demos, you might skip some of the essential libraries (such as \sc{Qt}), as the corresponding \cgal-libraries are not linked. But for your own demos you might need these \cgal-libraries. -\section secoptional3rdpartysoftware Optional Third Party Libraries - -Optional 3rd party software can be used by \cgal for various reasons: -Usually certain optional libraries are required to build examples and -demos shipped with \cgal or to build your own project using \cgal. -Another reason is to speed up basic tasks. - -\subsection thirdpartyLeda LEDA - -\leda is a library of efficient data structures and -algorithms. Like \sc{Core}, \leda offers a real number data type. - -In \cgal this library is optional, and its number types can -be used as an alternative to \sc{Gmp}, \sc{Mpfr}, and \sc{Core}. - -Free and commercial editions of \leda are available from `https://www.algorithmic-solutions.com`. - -\subsection thirdpartyMPFI MPFI - -\sc{Mpfi} provides arbitrary precision interval arithmetic with intervals -represented using \sc{Mpfr} reliable floating-point numbers. -It is based on the libraries \sc{Gmp} and \sc{Mpfr}. -In the setting of \cgal, this library is -optional: it is used by some models of the -\ref PkgAlgebraicKernelDRef "Algebraic Kernel". - -\sc{Mpfi} can be downloaded from `http://mpfi.gforge.inria.fr/`. Version 1.4 or higher is recommended. - -\subsection thirdpartyRS3 RS and RS3 - -\sc{Rs} (Real Solutions) is devoted to the study of the real roots of -polynomial systems with a finite number of complex roots (including -univariate polynomials). In \cgal, \sc{Rs} is used by one model of the -\ref PkgAlgebraicKernelDRef "Algebraic Kernel". - -\sc{Rs} is freely distributable for non-commercial use. You can download it -from `http://vegas.loria.fr/rs/`. Actually, the \sc{Rs} package also includes \sc{Rs3}, the -successor of \sc{Rs}, which is used in conjunction with it. - -The libraries \sc{Rs} and \sc{Rs3} need \sc{Mpfi}, which can be downloaded from -`http://mpfi.gforge.inria.fr/`. - -\subsection thirdpartyNTL NTL - -\sc{Ntl} provides data structures and algorithms for signed, arbitrary -length integers, and for vectors, matrices, and polynomials over the -integers and over finite fields. The optional library \sc{Ntl} is used by \cgal -to speed up operations of the Polynomial package, such as GCDs. It is recommended to install \sc{Ntl} with support from \sc{Gmp}. - -\sc{Ntl} can be downloaded from `http://www.shoup.net/ntl/`. Version 5.1 or higher is recommended. - -\subsection thirdpartyEigen Eigen - -\sc{Eigen} is a `C++` template library for linear algebra. \sc{Eigen} supports all -matrix sizes, various matrix decomposition methods and sparse linear solvers. - -In \cgal, \sc{Eigen} provides sparse linear solvers in the \ref PkgPoissonSurfaceReconstruction3Ref -and the \ref PkgSurfaceMeshParameterizationRef packages. - -In addition, \sc{Eigen} also provides singular value decomposition for the \ref PkgJetFitting3Ref -and the \ref PkgRidges3Ref packages. - -The \sc{Eigen} web site is `http://eigen.tuxfamily.org`. - -\subsection thirdpartyESBTL ESBTL - -The \sc{Esbtl} (Easy Structural Biology Template Library) is a library that allows -the handling of \sc{Pdb} data. - -In \cgal the \sc{Esbtl} is used in an example of the -\ref PkgSkinSurface3Ref package. - -It can be downloaded from `http://esbtl.sourceforge.net/`. - -\subsection thirdpartyTBB Intel TBB - -\sc{Tbb} (Threading Building Blocks) is a library developed by Intel Corporation for writing software -programs that take advantage of multi-core processors. - -In \cgal, \sc{Tbb} is used by the packages that offer parallel code. - -The \sc{Tbb} web site is `https://www.threadingbuildingblocks.org`. - -\subsection thirdpartyLASlib LASlib - -\sc{LASlib} is a `C++` library for handling LIDAR data sets stored in -the LAS format (or the compressed LAZ format). - -In \cgal, \sc{LASlib} is used to provide input and output functions in -the \ref PkgPointSetProcessing3Ref package. - -The \sc{LASlib} web site is `https://rapidlasso.com/lastools/`. \sc{LASlib} -is usually distributed along with LAStools: for simplicity, \cgal -provides a fork with a -CMake based install procedure. - -\subsection thirdpartyOpenCV OpenCV - -\sc{OpenCV} (Open Computer Vision) is a library designed for computer -vision, computer graphics and machine learning. - -In \cgal, \sc{OpenCV} is used by the \ref PkgClassificationRef package. - -The \sc{OpenCV} web site is `https://opencv.org/`. - -\subsection thirdpartyTensorFlow TensorFlow - -\sc{TensorFlow} is a library designed for machine learning and deep learning. - -In \cgal, the C++ API of \sc{TensorFlow} is used by the \ref -PkgClassificationRef package for neural network. The C++ API can be -compiled using CMake: it is distributed as part of the official -package and is located in `tensorflow/contrib/cmake`. Be sure to -enable and compile the following targets: - -- `tensorflow_BUILD_ALL_KERNELS` -- `tensorflow_BUILD_PYTHON_BINDINGS` -- `tensorflow_BUILD_SHARED_LIB`. - -The \sc{TensorFlow} web site is `https://www.tensorflow.org/`. - -\subsection thirdpartyMETIS METIS - -\sc{METIS} is a library developed by the Karypis Lab -and designed to partition graphs and produce fill-reducing matrix orderings. - -\cgal offers wrappers around some of the methods of the \sc{METIS} library -to allow the partitioning of graphs that are models of the concepts of the -Boost Graph Library, -and, by extension, of surface meshes (see Section \ref BGLPartitioning of the package \ref PkgBGL). - -More information is available on the METIS library -at `http://glaros.dtc.umn.edu/gkhome/metis/metis/overview`. - -\section secbuilding Building CGAL +\section secbuilding Building CGAL The results of a successful configuration are build files that control the build step. -The nature of the build files depends on the generator used during configuration, but in all cases they -contain several targets, one per library, and a default global target corresponding +The nature of the build files depends on the generator used during configuration, but in all cases they +contain several targets, one per library, and a default global target corresponding to all the libraries. For example, in a \sc{Unix}-like environment the default generator produces makefiles. You can use the `make` command-line tool for the succeeding build step as follows: -
    -
    -cd CGAL-\cgalReleaseNumber
    -
    -# build all the selected libraries at once
    -
    -make 
    -
    -
    + cd CGAL-\cgalReleaseNumber + # build all the selected libraries at once + make The resulting libraries are placed in the subdirectory `lib` under `` (which is `CGAL-\cgalReleaseNumber` in case you run an in-source-configuration). @@ -602,11 +79,7 @@ above, which you can manually build as with any other solution/project within yo Alternatively, you can build it with the command line version of the \sc{Visual Studio Ide}: -
    -
    -devenv CGAL.sln /Build Debug
    -
    -
    + devenv CGAL.sln /Build Debug The "Debug" argument is needed because CMake creates solution files for all four configurations, and you need to explicitly choose one when building @@ -633,15 +106,11 @@ None of these targets are included by default, so you need to build them explici The targets `examples` and `demos` include themselves all the targets for examples and demos respectively. -
    +    # build all examples at once
    +    make examples
     
    -# build all examples at once
    -make examples 
    -
    -# build all demos at once
    -make demos
    -
    -
    + # build all demos at once + make demos \cgalAdvancedBegin When using `UNIX Makefiles` you can find out the @@ -649,7 +118,7 @@ exact name of the example or demo target of a particular package by typing `make help | grep `. \cgalAdvancedEnd -\section secinstalling Installing CGAL +\section secinstalling Installing CGAL On many platforms, library pieces such as headers, docs and binaries are expected to be placed in specific locations. A typical example @@ -659,25 +128,21 @@ of placing or copying the library elements into its standard location is sometimes referred to as Installation and it is a postprocessing step after the build step. -CMake carries out the installation by producing a build target named install. +CMake carries out the installation by producing a build target named install. The following example shows a typical session from configuration to installation in a \sc{Unix}-like environment: -
    +    cd CGAL-\cgalReleaseNumber
     
    -cd CGAL-\cgalReleaseNumber
    -
    -cmake . # configure
    -make # compile
    -make install # install
    -
    -
    + cmake . # configure + make # compile + make install # install If you use a generator that produces IDE files (for Visual Studio for instance) there will be an optional `INSTALL` project, which you will be able to "build" to execute the installation step. \cgalAdvancedBegin -The files are copied into a directory tree relative to the installation directory determined by the +The files are copied into a directory tree relative to the installation directory determined by the CMake variable `CMAKE_INSTALL_PREFIX`. This variable defaults to `/usr/local` under \sc{Unix}-like operating systems and `C:\Program Files` under Windows. If you want to install to a different location, you must override that CMake variable explicitly at the configuration time and not when executing the install step. @@ -686,485 +151,39 @@ variable explicitly at the configuration time and not when executing the The file `CGALConfig.cmake` is installed by default in `$CMAKE_INSTALLED_PREFIX/lib/``CGAL-\cgalReleaseNumber`. -\section seccmakeoutofsource Multiple Variants of Makefiles (out-of-source build) +\section secshippedcgal OS Specific Installation +Some operating systems with package managers offer \cgal and its +essential third party software through the manager, +for instance, Mac OS X, or some Linux distribution (e.g. Debian). +For Windows, an installer is provided. -While you can choose between release or debug builds, and shared or static libraries, -it is not possible to generate different variants during a single configuration. You need to run CMake in a -different directory for each variant you are interested in, each with its own selection of configuration parameters. +\subsection sseccgalmacosxe CGAL on macOS -CMake stores the resulting makefiles and project files, along with several temporary and auxiliary files such -as the variables cache, in the directory where it is executed, called `CMAKE_BINARY_DIR`, but it -takes the source files and configuration scripts from -`CMAKE_SOURCE_DIR`. +The \cgal project recommends the use of Homebrew, in the following way: -The binary and source directories do not need to be the same. Thus, you can configure multiple variants by creating a -distinct directory for each configuration and by running CMake from there. This is known in CMake terminology -as out-of-source configuration, as opposite to an in-source -configuration, as showed in the previous sections. + brew install cgal -You can, for example, generate subdirectories `CGAL-\cgalReleaseNumber``/cmake/platforms/debug` and -`CGAL-\cgalReleaseNumber``/cmake/platforms/release` for two configurations, respectively: +\subsection sseccgaldebian CGAL on Linux -
    -mkdir CGAL-\cgalReleaseNumber/cmake/platforms/debug
    -cd CGAL-\cgalReleaseNumber/cmake/platforms/debug
    -cmake -DCMAKE_BUILD_TYPE=Debug ../../..
    +For instance in Debian/Ubuntu, use apt-get in the following way:
     
    -mkdir CGAL-\cgalReleaseNumber/cmake/platforms/release
    -cd CGAL-\cgalReleaseNumber/cmake/platforms/release
    -cmake -DCMAKE_BUILD_TYPE=Release ../../..
    -
    + sudo apt-get install libcgal-dev -\section installation_configuring_using Configuring and Building Programs Using CGAL +To get the demos use -Ideally, configuring and compiling a demo/example/program amounts to + sudo apt-get install libcgal-demo -
    +Check the \cgal-FAQ for source repository of newest releases.
     
    -cd CGAL-\cgalReleaseNumber/examples/Triangulation_2
    -cmake -DCGAL_DIR=$HOME/CGAL-\cgalReleaseNumber .
    -make
    +On other distributions, please consult your package manager documentation.
     
    -
    +\subsection sseccgalwindows CGAL on Windows -In this ideal world, as for all shipped examples and demos of \cgal, the -required `CMakeLists.txt` is already provided. +You can download and run `CGAL-\cgalReleaseNumber``-Setup.exe` from https://www.cgal.org/download/windows.html. +It is a self extracting executable that installs the \cgal source, and that allows you +to select and download some precompiled third party libraries. However, you will need to compile +the library using your favorite compiler. +A tutorial is provided on how to proceed with Microsoft Visual Studio. -CMake can also be used to configure and build user programs via such -CMake-scripts. In this less ideal world, one has to provide the -`CMakeLists.txt` script either manually, or with the help of a -shell-script that is introduced below. - -For a user program `executable.cpp`, the ideal world looks like this: - -
    -cd /path/to/program 
    -cgal_create_CMakeLists -s executable
    -cmake -DCGAL_DIR=$HOME/CGAL-\cgalReleaseNumber . 
    -make
    -
    - -In both examples we specify the `CGAL_DIR`: -During configuration of the \cgal libraries a file named `CGALConfig.cmake` is generated in \cgal's root directory (in contrast -to \cgal's source directory that has been used for installation). This file -contains the definitions of several CMake variable that summarize the -configuration of \cgal. In order to configure a program, you need -to indicate the location of that config file in the CMake variable -`CGAL_DIR` (as indicated in the example above). -`CGAL_DIR` can also be an environment variable. Setting -`CGAL_DIR` makes particular sense if having multiple -out-of-source builds of \cgal as in Section \ref seccmakeoutofsource. - -If you have installed \cgal, `CGAL_DIR` must afterwards be set to -`$CMAKE_INSTALLED_PREFIX/lib/CGAL`. Note that \cgal is -recommended to be installed in release mode when using it to build programs. - -\subsection installation_creating Creating a CMake Script for a Program Using CGAL - -For compiling a non-shipped program, it is -recommended, to also rely on a CMake-supported configuration using a -`CMakeLists.txt` used for configuration. - -Use the following Bourne-shell script for programs that are relatively -simple to configure: - -\subsection seccreate_cgal_CMakeLists cgal_create_CMakeLists - -The Bourne-shell script `cgal_create_CMakeLists.txt` resides in the -`CGAL-\cgalReleaseNumber``/scripts` directory. It can be used to create -`CMakeLists.txt` files for compiling \cgal applications. Executing -`cgal_create_CMakeLists.txt` in an application directory creates a -`CMakeLists.txt` containing rules to build the contained -application(s). Three command line options determine details of the -configuration. - -
    -
    `-s source`
    If this parameter is given the script will -create a single executable for 'source' linked with -compilations of all other source files -(`*.cc`, `*.cp`, `*.cxx`, `*.cpp`, `*.CPP`, `*.c++`, or `*.C`). -This behaviour is usually needed for (graphical) demos. - -If the parameter is not given, the script creates one executable for each given -source file. -
    `-c com1:com2:...`
    Lists components ("com1", -"com2") of \cgal to which the executable(s) should be linked. Valid components are \cgal's -libraries (i.e.\ "Core", "ImageIO", and "Qt5"). An example is `-c Core`. - -
    `-b boost1:boost2:...`
    Lists components ("boost1", -"boost2") of \sc{Boost} to which the executable(s) should be -linked. Valid options are, for instance, "filesystem" or "program_options". - -
    - -This options should suffice to create `CMakeLists.txt` script -for most directories containing programs. However, in some special -cases, it might still be required to create the script manually, for -instance, if some source files/executables need a different linking than -other source files. - -\subsection seccreate_cgal_cmake_script cgal_create_cmake_script - -\deprecated For backward-compatibility we still provide the -Bourne-shell script `cgal_create_cmake_script` that is -contained in the `CGAL-\cgalReleaseNumber``/scripts` directory. It can be used -to create `CMakeLists.txt` files for compiling \cgal -applications. Executing `cgal_create_cmake_script` in an -application directory creates a `CMakeLists.txt` containing -rules for every C++ source file there. The script is deprecated, -as it only works for applications with a single course file that only -need libCGAL and libCGAL_Core. - -Such a shell-script simply creates a CMake script. Processing it -with CMake, searches for \cgal using `find_package`. If found, -the variable `CGAL_USE_FILE` is set to a compilation environment CMake file. Including -this file within a CMake script sets up include paths and libraries to -link with \cgal and essential third party libraries. Beyond, -`find_package` can demand for `COMPONENTS` of \cgal, -that is, all \cgal libraries `libCGAL_Core` (Core), -libCGAL_ImageIO (ImageIO), and libCGAL_Qt5 -(Qt5) or optional 3rd party software such as MPFI, RS3. -A user is free to create the `CMakeLists.txt` -without calling the script (manual creation). - -\section installation_summary Summary of CGAL's Configuration Variables - -Most configuration variables are not environment variables but -CMake variables. They are given in the command line to CMake -via the `-D` option, or passed from the interactive interface -of `cmake-gui`. Unless indicated differently, all the variables -summarized below are CMake variables. - -\subsection installation_component_selection Component Selection - -The following boolean variables indicate which \cgal components to -configure and build. Their values can be ON or OFF. - - -| Variable | %Default Value | -| :------- | :--------------- | -| `WITH_examples` | OFF | -| `WITH_demos` | OFF | -| `WITH_CGAL_Core` | ON | -| `WITH_CGAL_Qt5` | ON | -| `WITH_CGAL_ImageIO` | ON | - -\subsection installation_flags Compiler and Linker Flags - -The following variables specify compiler and linker flags. Each variable holds a -space-separated list of command-line switches for the compiler and linker and -their default values are automatically defined by CMake based on the target platform. - -Have in mind that these variables specify a list of flags, not just one -single flag. If you provide your own definition for a variable, you will entirely override -the list of flags chosen by CMake for that particular variable. - -The variables that correspond to both debug and release builds are always -used in conjunction with those for the specific build type. - - -| Program | Both Debug and Release | Release Only | Debug Only | -| :------ | :---------------------- | :------------- | :----------- | -| C++ Compiler | `CMAKE_CXX_FLAGS` | `CMAKE_CXX_FLAGS_RELEASE` | `CMAKE_CXX_FLAGS_DEBUG` | -| Linker (shared libs) | `CMAKE_SHARED_LINKER_FLAGS` | `CMAKE_SHARED_LINKER_FLAGS_RELEASE` | `CMAKE_SHARED_LINKER_FLAGS_DEBUG` | -| Linker (static libs) | `CMAKE_MODULE_LINKER_FLAGS` | `CMAKE_MODULE_LINKER_FLAGS_RELEASE` | `CMAKE_MODULE_LINKER_FLAGS_DEBUG` | -| Linker (programs) | `CMAKE_EXE_LINKER_FLAGS` | `CMAKE_EXE_LINKER_FLAGS_RELEASE` | `CMAKE_EXE_LINKER_FLAGS_DEBUG`| - - -\subsection installation_additional_flags Additional Compiler and Linker Flags - -The following variables can be used to add flags without overriding the ones -defined by cmake. - - -| Program | Both Debug and Release | Release Only | Debug Only | -| :------ | :---------------------- | :------------- | :----------- | -| C++ Compiler | `CGAL_CXX_FLAGS` | `CGAL_CXX_FLAGS_RELEASE` | `CGAL_CXX_FLAGS_DEBUG` | -| Linker (shared libs) | `CGAL_SHARED_LINKER_FLAGS` | `CGAL_SHARED_LINKER_FLAGS_RELEASE` | `CGAL_SHARED_LINKER_FLAGS_DEBUG` | -| Linker (static libs) | `CGAL_MODULE_LINKER_FLAGS` | `CGAL_MODULE_LINKER_FLAGS_RELEASE` | `CGAL_MODULE_LINKER_FLAGS_DEBUG` | -| Linker (programs) | `CGAL_EXE_LINKER_FLAGS` | `CGAL_EXE_LINKER_FLAGS_RELEASE` | `CGAL_EXE_LINKER_FLAGS_DEBUG` | - -\subsection installation_misc Miscellaneous Variables - - -| Variable | Description | Type | %Default Value | -| :- | :- | :- | :- | -| `CMAKE_BUILD_TYPE` | Indicates type of build. Possible values are 'Debug' or 'Release' | CMake | Release | -| `CMAKE_CXX_COMPILER` | Full-path to the executable corresponding to the C++ compiler to use. | CMake | platform-dependent | -| `CXX` | Idem | Environment | Idem | - - -\subsection installation_variables_building Variables Used Only When Building Programs (Such as Demos or Examples) - - -| Variable | Description | Type | %Default Value | -| :- | :- | :- | :- | -| `CGAL_DIR` | Full-path to the binary directory where \cgal was configured |Either CMake or Environment | none | - - -\subsection installation_variables_third_party Variables Providing Information About 3rd-Party Libraries -\anchor sec3partysoftwareconfig - -The following variables provide information about the availability and -location of the 3rd party libraries used by \cgal. CMake automatically -searches for dependencies so you need to specify these variables if -CMake was unable to locate something. This is indicated by a value ending in -`NOTFOUND`. - -Since 3rd-party libraries are system wide, many of the CMake variables listed below can alternatively -be given as similarly-named environment variables instead. Keep in mind that you must provide one or the -other but never both. - -\subsection installation_boost Boost Libraries - -In most cases, if \sc{Boost} is not automatically found, setting the `BOOST_ROOT` -variable is enough. If it is not, you can specify the header and library -directories individually. You can also provide the full pathname to a specific compiled library -if it cannot be found in the library directory or its name is non-standard. - -By default, when \sc{Boost} binary libraries are needed, the shared versions -are used if present. You can set the variable -`CGAL_Boost_USE_STATIC_LIBS` to `ON` if you want to link -with static versions explicitly. - -On Windows, if you link with \sc{Boost} shared libraries, you must ensure that -the `.dll` files are found by the dynamic linker, at run time. -For example, you can add the path to the \sc{Boost} `.dll` to the -`PATH` environment variable. - -| Variable | Description | Type | -| :- | :- | :- | -| `BOOST_ROOT`\cgalFootnote{The environment variable can be spelled either `BOOST_ROOT` or `BOOSTROOT`} | Root directory of your \sc{Boost} installation | Either CMake or Environment | -| `Boost_INCLUDE_DIR` | Directory containing the `boost/version.hpp` file | CMake | -| `BOOST_INCLUDEDIR` | Idem | Environment | -| `Boost_LIBRARY_DIRS` | Directory containing the compiled \sc{Boost} libraries | CMake | -| `BOOST_LIBRARYDIR` | Idem | Environment | -| `Boost_(xyz)_LIBRARY_RELEASE` | Full pathname to a release build of the compiled 'xyz' \sc{Boost} library | CMake | -| `Boost_(xyz)_LIBRARY_DEBUG` | Full pathname to a debug build of the compiled 'xyz' \sc{Boost} library | CMake | - - -\subsection installation_gmp GMP and MPFR Libraries - -Under Windows, auto-linking is used, so only the directory -containing the libraries is needed and you would specify `GMP|MPFR_LIBRARY_DIR` rather than -`GMP|MPFR_LIBRARIES`. On the other hand, under Linux the actual library filename is needed. -Thus you would specify `GMP|MPFR_LIBRARIES`. In no case you need to specify both. - -\cgal uses both \sc{Gmp} and \sc{Mpfr} so both need to be supported. If either of them is unavailable the -usage of \sc{Gmp} and of \sc{Mpfr} will be disabled. - - -| Variable | Description | Type | -| :- | :- | :- | -| `CGAL_DISABLE_GMP` | Indicates whether to search and use \sc{Gmp}/\sc{Mpfr} or not | CMake | -| `GMP_DIR` | Directory of \sc{Gmp} default installation | Environment | -| `GMP_INCLUDE_DIR` | Directory containing the `gmp.h` file | CMake | -| `GMP_INC_DIR` | Idem | Environment | -| `GMP_LIBRARIES_DIR` | Directory containing the compiled \sc{Gmp} library | CMake | -| `GMP_LIB_DIR` | Idem | Environment | -| `GMP_LIBRARIES` | Full pathname of the compiled \sc{Gmp} library | CMake | -| `MPFR_INCLUDE_DIR` | Directory containing the `mpfr.h` file | CMake | -| `MPFR_INC_DIR` | Idem | Environment | -| `MPFR_LIBRARIES_DIR` | Directory containing the compiled \sc{Mpfr} library | CMake | -| `MPFR_LIB_DIR` | Idem | Environment | -| `MPFR_LIBRARIES` | Full pathname of the compiled \sc{Mpfr} library | CMake | - - - -Under Linux, the \sc{Gmpxx} is also searched for, and you may specify the following variables: - - -| Variable | Description | Type | -| :- | :- | :- | -| `GMPXX_DIR` | Directory of \sc{gmpxx} default installation | Environment | -| `GMPXX_INCLUDE_DIR` | Directory containing the `gmpxx.h` file | CMake | -| `GMPXX_LIBRARIES` | Full pathname of the compiled \sc{Gmpxx} library | CMake | - - - -\subsection installation_qt5 Qt5 Library - -You must set the cmake or environment variable `Qt5_DIR` to point to the path -to the directory containing the file `Qt5Config.cmake` created by your \sc{Qt}5 installation. If you are -using the open source edition it should be `/qt-everywhere-opensource-src-/qtbase/lib/cmake/Qt5`. - -\subsection installation_leda LEDA Library - -When the \leda libraries are not automatically found, yet they are installed on the system -with base names 'leda' and 'ledaD' (for the release and debug versions resp.), it might -be sufficient to just indicate the library directory via the `LEDA_LIBRARY_DIRS` variable. -If that doesn't work because, for example, the names are different, you can provide the full pathnames of each variant -via `LEDA_LIBRARY_RELEASE` and `LEDA_LIBRARY_DEBUG`. - -The variables specifying definitions and flags can be left undefined if they are not needed by LEDA. - - -| Variable | Description | Type | -| :- | :- | :- | -| `WITH_LEDA` | Indicates whether to search and use \leda or not | CMake | -| `LEDA_DIR` | Directory of \sc{LEDA} default installation | Environment | -| `LEDA_INCLUDE_DIR` | Directory containing the file `LEDA/system/basic.h` | CMake | -| `LEDA_LIBRARIES` | Directory containing the compiled \leda libraries | CMake | -| `LEDA_INC_DIR` | Directory containing the file `LEDA/system/basic.h` | Environment | -| `LEDA_LIB_DIR` | Directory containing the compiled \leda libraries | Environment | -| `LEDA_LIBRARY_RELEASE` | Full pathname to a release build of the \leda library | CMake | -| `LEDA_LIBRARY_DEBUG` | Full pathname to a debug build of the \leda library | CMake | -| `LEDA_DEFINITIONS` | Preprocessor definitions | CMake | -| `LEDA_CXX_FLAGS` | Compiler flags | CMake | -| `LEDA_LINKER_FLAGS` | Linker flags | CMake | - - -\subsection installation_mpfi MPFI Library - -\cgal provides a number type based on this library, but the \cgal library -itself does not depend on \sc{Mpfi}. This means that this library must be -configured when compiling an application that uses the above number type. - -When \sc{Mpfi} files are not on the standard path, the locations of the headers -and library files must be specified by using environment variables. - - -| Variable | Description | Type | -| :- | :- | :- | -| `MPFI_DIR` |Directory of \sc{MPFI} default installation | Environment | -| `MPFI_INCLUDE_DIR` | Directory containing the `mpfi.h` file | CMake | -| `MPFI_INC_DIR` | Idem | Environment | -| `MPFI_LIBRARIES_DIR` | Directory containing the compiled \sc{Mpfi} library | CMake | -| `MPFI_LIB_DIR` | Idem | Environment | -| `MPFI_LIBRARIES` | Full pathname of the compiled \sc{Mpfi} library | CMake | - - - -\subsection installation_rs RS and RS3 Library - -As said before, only the \cgal univariate algebraic kernel depends on the -library Rs. As the algebraic kernel is not compiled as a part of the \cgal -library, this library is not detected nor configured at installation time. - -CMake will try to find Rs in the standard header and library -directories. When it is not automatically detected, the locations of the -headers and library files must be specified using environment variables. - -Rs needs \sc{Gmp} 4.2 or later and \sc{Mpfi} 1.3.4 or later. The variables -related to the latter library may also need to be defined. - - -| Variable | Description | Type | -| :- | :- | :- | -| `RS_DIR` | Directory of \sc{Rs} default installation | Environment | -| `RS_INCLUDE_DIR` | Directory containing the `rs_exports.h` file | CMake | -| `RS_INC_DIR` | Idem | Environment | -| `RS_LIBRARIES_DIR` | Directory containing the compiled \sc{Rs} library | CMake | -| `RS_LIB_DIR` | Idem | Environment | -| `RS_LIBRARIES` | Full pathname of the compiled \sc{Rs} library | CMake | - -Similar variables exist for \sc{Rs3}. - -| Variable | Description | Type | -| :- | :- | :- -| `RS3_DIR` | Directory of \sc{Rs3} default installation | Environment | -| `RS3_INCLUDE_DIR` | Directory containing the file `rs3_fncts.h` file | CMake | -| `RS3_INC_DIR` | Idem | Environment | -| `RS3_LIBRARIES_DIR` | Directory containing the compiled \sc{Rs3} library | CMake | -| `RS3_LIB_DIR` | Idem | Environment | -| `RS3_LIBRARIES` | Full pathname of the compiled \sc{Rs3} library | CMake | - - -\subsection installation_ntl NTL Library - -Some polynomial computations in \cgal's algebraic kernel -are speed up when \sc{Ntl} is available. -As the algebraic kernel is not compiled as a part of the \cgal -library, this library is not detected nor configured at installation time. - -CMake will try to find \sc{Ntl} in the standard header and library -directories. When it is not automatically detected, the locations of the -headers and library files must be specified using environment variables. - -| Variable | Description | Type | -| :- | :- | :- | -| `NTL_DIR` | Directory of \sc{NTL} default installation | Environment | -| `NTL_INCLUDE_DIR` | Directory containing the `NTL/ZZX.h` file | CMake | -| `NTL_INC_DIR` | Idem | Environment | -| `NTL_LIBRARIES_DIR` | Directory containing the compiled \sc{Ntl} library | CMake | -| `NTL_LIB_DIR` | Idem | Environment | -| `NTL_LIBRARIES` | Full pathname of the compiled \sc{Ntl} library | CMake | - -\subsection installation_eigen Eigen Library - -\sc{Eigen} is a header-only template library. -Only the directory containing the header files of \sc{Eigen} 3.1 (or greater) is needed. - - -| Variable | Description | Type | -| :- | :- | :- | -| `EIGEN3_INCLUDE_DIR` | Directory containing the file `signature_of_eigen3_matrix_library` | CMake | -| `EIGEN3_INC_DIR` | Idem | Environment | - -\subsection installation_esbtl ESBTL Library - -One skin surface example requires the \sc{Esbtl} library in order to read \sc{Pdb} files. - -If \sc{Esbtl} is not automatically found, setting the `ESBTL_INC_DIR` -environment variable is sufficient. - - -| Variable | Description | Type | -| :- | :- | :- | -| `ESBTL_DIR` | Directory of \sc{ESBTL} default installation | Environment | -| `ESBTL_INC_DIR` | Directory containing the `ESBTL/default.h` file | Environment | -| `ESBTL_INCLUDE_DIR` | Directory containing the `ESBTL/default.h` file | CMake | - -\subsection installation_tbb TBB Library - -If \sc{Tbb} is not automatically found, the user must set the `TBBROOT` -environment variable. The environment variable `TBB_ARCH_PLATFORM=/` must be set. -`` is `ia32` or `intel64`. `` describes the Linux kernel, gcc version or Visual Studio version -used. It should be set to what is used in `$TBBROOT/lib/`. - -For windows users, the folder `TBBROOT/bin//` should be added to the `PATH` variable. - -Note that the variables in the table below are being used. - -| Variable | Description | Type | -| :- | :- | :- | -| `TBBROOT` | Directory of \sc{Tbb} default installation | Environment | -| `TBB_INCLUDE_DIRS` | Directory containing the `tbb/tbb.h` file | CMake | -| `TBB_LIBRARY_DIRS` | Directory(ies) containing the compiled TBB libraries | CMake | -| `TBB_LIBRARIES` | Full pathnames of the compiled TBB libraries (both release and debug versions, using "optimized" and "debug" CMake keywords). Note that if the debug versions are not found, the release versions will be used instead for the debug mode. | CMake | -| `TBB_RELEASE_LIBRARY` | Full pathname of the compiled TBB release library | CMake | -| `TBB_MALLOC_RELEASE_LIBRARY` | Full pathname of the compiled TBB release malloc library | CMake | -| `TBB_DEBUG_LIBRARY` | Full pathname of the compiled TBB debug library | CMake | -| `TBB_MALLOC_DEBUG_LIBRARY` | Full pathname of the compiled TBB debug malloc library | CMake | -| `TBB_MALLOCPROXY_DEBUG_LIBRARY` | Full pathname of the compiled TBB debug malloc_proxy library (optional) | CMake | -| `TBB_MALLOCPROXY_RELEASE_LIBRARY` | Full pathname of the compiled TBB release malloc_proxy library (optional) | CMake | - -\section installation_compiler_workarounds Compiler Workarounds - -A number of boolean flags are used to workaround compiler bugs and -limitations. They all start with the prefix `CGAL_CFG`. These -flags are used to work around compiler bugs and limitations. For -example, the flag `CGAL_CFG_NO_CPP0X_LONG_LONG` denotes -that the compiler does not know the type `long long`. - -For each installation a file -is defined, with the correct -settings of all flags. This file is generated automatically by CMake, -and it is located in the `include` directory of where you run -CMake. For an in-source configuration this means -`CGAL-\cgalReleaseNumber``/include`. - -The test programs used to generate the `compiler_config.h` -file can be found in `config/testfiles`. -Both -`compiler_config.h` and the test programs contain a short -description of the problem. In case of trouble with one of the -`CGAL_CFG` flags, it is a good idea to take a look at it. - -The file `CGAL/compiler_config.h` is included from -``. -which is included by all \cgal header files. - - -*/ +*/ diff --git a/Documentation/doc/Documentation/Preliminaries.txt b/Documentation/doc/Documentation/Preliminaries.txt index 6d03fb0d21d..62ddb9f4c79 100644 --- a/Documentation/doc/Documentation/Preliminaries.txt +++ b/Documentation/doc/Documentation/Preliminaries.txt @@ -63,9 +63,9 @@ http://www.geometryfactory.com/. License fees paid by commercial customers are reinvested in R\&D performed by the \cgal project partners, as well as in evolutive maintenance. -\subsection licenseCheck License Checking +\subsection licenseCheck License Checking -Users who have a commercial license for specific packages can check that +Users who have a commercial license for specific packages can check that they do not accidentally use packages for which they do not have a commercial license. The same holds for users who want to be sure that they only use packages of \cgal released under the \sc{Lgpl}. @@ -155,7 +155,7 @@ to force its definition on the command line, and it is possible to prevent its d definition by setting `CGAL_HAS_NO_THREADS` from the command line. -\section Preliminaries_cc0x C++11 Support +\section Preliminaries_cc0x C++11 Support \cgal is based on the \CC standard released in 1998 (and later refined in 2003). A new major version of this standard has been released, and is refered to as \cpp11. @@ -182,7 +182,7 @@ return type of calling the functor with an argument of type Much of the \cgal code contains assert statements for preconditions, and postconditions of functions as well as in the code. These assertions can be switched on and off per package -and the user can change the error behaviour. For details see Section \ref secchecks +and the user can change the error behaviour. For details see Section \ref secchecks of Chapter \ref Chapter_STL_Extensions_for_CGAL. \section seccgal_version Identifying the Version of CGAL @@ -208,7 +208,7 @@ public release 3.2.4 this number is 1030241000; for internal release 3.2-I-30.
    `CGAL_VERSION_NUMBER(M,m,b)`
    -
    +
    a function macro computing the version number macro from the M.m.b release version. Note that the internal release number is dropped here. Example: `CGAL_VERSION_NUMBER(3,2,4)` is equal to diff --git a/Documentation/doc/Documentation/Third_party.txt b/Documentation/doc/Documentation/Third_party.txt new file mode 100644 index 00000000000..46a0522a5b8 --- /dev/null +++ b/Documentation/doc/Documentation/Third_party.txt @@ -0,0 +1,259 @@ +/*! + +\page thirdparty Essential and Optional Third Party Dependencies +\cgalAutoToc +\author %CGAL Editorial Board + +\section seccompilers Supported Compilers + +In order to build a program using \cgal, you need a \cpp compiler +supporting C++14 or later. +\cgal \cgalReleaseNumber is supported, that is continuously tested, for the following compilers/operating systems: + +| Operating System | Compiler | +| :------- | :--------------- | +| Linux | \sc{Gnu} `g++` 6.3 or later\cgalFootnote{`http://gcc.gnu.org/`} | +| | `Clang` \cgalFootnote{`http://clang.llvm.org/`} compiler version 8.0.0 | +| \sc{MS} Windows | \sc{Gnu} `g++` 6.3 or later\cgalFootnote{`http://gcc.gnu.org/`} | +| | \sc{MS} Visual `C++` 14.0, 15.9, 16.0 (\sc{Visual Studio} 2015, 2017, and 2019)\cgalFootnote{`https://visualstudio.microsoft.com/`} | +| MacOS X | \sc{Gnu} `g++` 6.3 or later\cgalFootnote{`http://gcc.gnu.org/`} | +| | Apple `Clang` compiler versions 7.0.2 and 10.0.1 | + +It may work for older versions of the above listed compilers. + +\section seccmake CMake + +In order to configure and build the \cgal libraries, examples, and demos, +you need CMake, a cross-platform "makefile generator". +If CMake is not already installed you can obtain it from `https://cmake.org/`. +CMake version 3.1 or higher is required. + +This manual explains only those features of +CMake which are needed in order to build \cgal. Please refer to the +CMake documentation at `https://cmake.org/` for further details. + +\section secessential3rdpartysoftware Essential Third Party Libraries + +The focus of \cgal is on geometry, and we rely on other +highly specialized libraries and software for non-geometric issues, +for instance, for numeric solvers, or visualization. We first list software +that is essential to build (all) libraries of \cgal, that is, +this software must be found during the configuration of \cgal for an +actived library of \cgal (i.e.\ WITH_=ON); +see the page \ref configurationvariables to specify the location of 3rd +party software. + +The libraries \stl (shipped with any compiler) and \sc{Boost} are essential to all components (i.e.\ libCGAL, +libCGAL_Core, libCGAL_ImageIO, and libCGAL_Qt5). + +\subsection thirdpartystl Standard Template Library (STL) + +\cgal heavily uses the \stl, and in particular adopted +many of its design ideas. You can find online +documentation for the \stl at various web sites, for instance, +`https://en.cppreference.com `, +or `https://msdn.microsoft.com`. + +The \stl comes with the compiler, so there is nothing to install. + +\subsection thirdpartyBoost Boost + +The \sc{Boost} libraries are a set of portable C++ source libraries. Most of +\sc{Boost} libraries are header-only, but a few of them need to be compiled or +installed as binaries. + +\cgal only requires the headers of the \sc{Boost} libraries, but some demos and examples depend on the binary library `Boost.Program_options`. + +As an exception, because of a bug in the \gcc compiler about the \cpp 11 +keyword `thread_local`, the `CGAL_Core` library always requires +the binary library `Boost.Thread` if the \gcc compiler version 9.0 or +earlier is used. + +In case the \sc{Boost} libraries are not installed on your system already, you +can obtain them from `https://www.boost.org/`. For Visual C++ you can download precompiled libraries +from `https://sourceforge.net/projects/boost/files/boost-binaries/`. + +As on Windows there is no canonical directory for where to find +\sc{Boost}, we recommend that you define the environment variable +`BOOST_ROOT` and set it to where you have installed \sc{Boost}, e.g., +`C:\boost\boost_1_41_0`. + +\subsection thirdpartyMPFR GMP and MPFR + +The components libCGAL, libCGAL_Core, and libCGAL_Qt5 require +\sc{Gmp} and \sc{Mpfr} which are libraries for multi precision integers and rational numbers, +and for multi precision floating point numbers. + +\cgal combines floating point arithmetic with exact arithmetic, +in order to be efficient and reliable. \cgal has a built-in +number type for that, but \sc{Gmp} and \sc{Mpfr} provide a faster +solution, and we recommend to use them. + +Having \sc{Gmp} version 4.2 or higher and \sc{Mpfr} version 2.2.1 or higher +installed is recommended. These libraries can be obtained from +`https://gmplib.org/` and `https://www.mpfr.org/`, respectively. + +As Visual \cpp is not properly +supported by the \sc{Gmp} and \sc{Mpfr} projects, we provide precompiled versions +of \sc{Gmp} and \sc{Mpfr}, which can be downloaded with the installer +`CGAL-\cgalReleaseNumber``-Setup.exe`. + +\subsection thirdpartyzlib zlib + +\sc{zlib} is a data compression library, and is essential for the component libCGAL_ImageIO. + +In \cgal this library is used in the examples of the \ref PkgSurfaceMesher3Ref package. + +If it is not already on your system, +for instance, on Windows, you can download it from `https://www.zlib.net/`. + +\subsection thirdpartyQt Qt5 + +Qt is a cross-platform application and UI framework. + +The component libCGAL_Qt5 requires \sc{Qt}5 installed on your system. +In case \sc{Qt} is not yet installed on your system, you can download +it from `https://www.qt-project.org/`. + +The exhaustive list of \sc{Qt}5 components used in demos is: +`Core`, `Gui`, `Help`, `OpenGL`, `Script`, `ScriptTools`, `Svg`, `Widgets`, +`qcollectiongenerator` (with `sqlite` driver plugin) and `Xml`. + +\sc{Qt} version 5.9.0 or later is required. + +\section secoptional3rdpartysoftware Optional Third Party Libraries + +Optional 3rd party software can be used by \cgal for various reasons: +Usually certain optional libraries are required to build examples and +demos shipped with \cgal or to build your own project using \cgal. +Another reason is to speed up basic tasks. + +\subsection thirdpartyLeda LEDA + +\leda is a library of efficient data structures and +algorithms. Like \sc{Core}, \leda offers a real number data type. + +In \cgal this library is optional, and its number types can +be used as an alternative to \sc{Gmp}, \sc{Mpfr}, and \sc{Core}. + +Free and commercial editions of \leda are available from `https://www.algorithmic-solutions.com`. + +\subsection thirdpartyMPFI MPFI + +\sc{Mpfi} provides arbitrary precision interval arithmetic with intervals +represented using \sc{Mpfr} reliable floating-point numbers. +It is based on the libraries \sc{Gmp} and \sc{Mpfr}. +In the setting of \cgal, this library is +optional: it is used by some models of the +\ref PkgAlgebraicKernelDRef "Algebraic Kernel". + +\sc{Mpfi} can be downloaded from `https://mpfi.gforge.inria.fr/`. Version 1.4 or higher is recommended. + +\subsection thirdpartyRS3 RS and RS3 + +\sc{Rs} (Real Solutions) is devoted to the study of the real roots of +polynomial systems with a finite number of complex roots (including +univariate polynomials). In \cgal, \sc{Rs} is used by one model of the +\ref PkgAlgebraicKernelDRef "Algebraic Kernel". + +\sc{Rs} is freely distributable for non-commercial use. You can download it +from `http://vegas.loria.fr/rs/`. Actually, the \sc{Rs} package also includes \sc{Rs3}, the +successor of \sc{Rs}, which is used in conjunction with it. + +The libraries \sc{Rs} and \sc{Rs3} need \sc{Mpfi}, which can be downloaded from +`https://mpfi.gforge.inria.fr/`. + +\subsection thirdpartyNTL NTL + +\sc{Ntl} provides data structures and algorithms for signed, arbitrary +length integers, and for vectors, matrices, and polynomials over the +integers and over finite fields. The optional library \sc{Ntl} is used by \cgal +to speed up operations of the Polynomial package, such as GCDs. It is recommended to install \sc{Ntl} with support from \sc{Gmp}. + +\sc{Ntl} can be downloaded from `https://www.shoup.net/ntl/`. Version 5.1 or higher is recommended. + +\subsection thirdpartyEigen Eigen + +\sc{Eigen} is a `C++` template library for linear algebra. \sc{Eigen} supports all +matrix sizes, various matrix decomposition methods and sparse linear solvers. + +In \cgal, \sc{Eigen} provides sparse linear solvers in the \ref PkgPoissonSurfaceReconstruction3Ref +and the \ref PkgSurfaceMeshParameterizationRef packages. + +In addition, \sc{Eigen} also provides singular value decomposition for the \ref PkgJetFitting3Ref +and the \ref PkgRidges3Ref packages. + +The \sc{Eigen} web site is `http://eigen.tuxfamily.org`. + +\subsection thirdpartyESBTL ESBTL + +The \sc{Esbtl} (Easy Structural Biology Template Library) is a library that allows +the handling of \sc{Pdb} data. + +In \cgal the \sc{Esbtl} is used in an example of the +\ref PkgSkinSurface3Ref package. + +It can be downloaded from `http://esbtl.sourceforge.net/`. + +\subsection thirdpartyTBB Intel TBB + +\sc{Tbb} (Threading Building Blocks) is a library developed by Intel Corporation for writing software +programs that take advantage of multi-core processors. + +In \cgal, \sc{Tbb} is used by the packages that offer parallel code. + +The \sc{Tbb} web site is `https://www.threadingbuildingblocks.org`. + +\subsection thirdpartyLASlib LASlib + +\sc{LASlib} is a `C++` library for handling LIDAR data sets stored in +the LAS format (or the compressed LAZ format). + +In \cgal, \sc{LASlib} is used to provide input and output functions in +the \ref PkgPointSetProcessing3Ref package. + +The \sc{LASlib} web site is `https://rapidlasso.com/lastools/`. \sc{LASlib} +is usually distributed along with LAStools: for simplicity, \cgal +provides a fork with a +CMake based install procedure. + +\subsection thirdpartyOpenCV OpenCV + +\sc{OpenCV} (Open Computer Vision) is a library designed for computer +vision, computer graphics and machine learning. + +In \cgal, \sc{OpenCV} is used by the \ref PkgClassificationRef package. + +The \sc{OpenCV} web site is `https://opencv.org/`. + +\subsection thirdpartyTensorFlow TensorFlow + +\sc{TensorFlow} is a library designed for machine learning and deep learning. + +In \cgal, the C++ API of \sc{TensorFlow} is used by the \ref +PkgClassificationRef package for neural network. The C++ API can be +compiled using CMake: it is distributed as part of the official +package and is located in `tensorflow/contrib/cmake`. Be sure to +enable and compile the following targets: + +- `tensorflow_BUILD_ALL_KERNELS` +- `tensorflow_BUILD_PYTHON_BINDINGS` +- `tensorflow_BUILD_SHARED_LIB`. + +The \sc{TensorFlow} web site is `https://www.tensorflow.org/`. + +\subsection thirdpartyMETIS METIS + +\sc{METIS} is a library developed by the Karypis Lab +and designed to partition graphs and produce fill-reducing matrix orderings. + +\cgal offers wrappers around some of the methods of the \sc{METIS} library +to allow the partitioning of graphs that are models of the concepts of the +Boost Graph Library, +and, by extension, of surface meshes (see Section \ref BGLPartitioning of the package \ref PkgBGL). + +More information is available on the METIS library +at `http://glaros.dtc.umn.edu/gkhome/metis/metis/overview`. + +*/ diff --git a/Documentation/doc/Documentation/Usage.txt b/Documentation/doc/Documentation/Usage.txt new file mode 100644 index 00000000000..1e6061471e3 --- /dev/null +++ b/Documentation/doc/Documentation/Usage.txt @@ -0,0 +1,338 @@ +/*! +\page usage Usage +\cgalAutoToc +\authors Eric Berberich, Joachim Reichel, and Fernando Cacciola + +Since \cgal version 5.0, \cgal is header-only be default, which means +that there is no need to compile and install anything before it can be +used. However, the dependencies of \cgal might still need to be installed. + +\section usage_introduction Quick Start + +Ideally, compiling an example or a demo shipped with \cgal is as simple as: + + cd examples/Triangulation_2 # go to an example directory + cmake -DCGAL_DIR=$HOME/CGAL-\cgalReleaseNumber . # configure the examples + make # build the examples + + cd demo/Triangulation_2 # go to a demo directory + cmake -DCGAL_DIR=$HOME/CGAL-\cgalReleaseNumber . # configure the demos + make # build the demos + +Compiling your own program is similar: + + cd /path/to/program + cgal_create_CMakeLists -s executable + cmake -DCGAL_DIR=$HOME/CGAL-\cgalReleaseNumber . + make + +where the second line creates a file `CMakeLists.txt` (see Section \ref seccreate_cgal_CMakeLists for more details). + +In a less ideal world, you might have to install required tools, and third party libraries. +This is what this page is about. + +\section secprerequisites Prerequisites + +Using \cgal requires a few core components to be previously installed: +
      +
    • a supported compiler (see Section \ref seccompilers),
    • +
    • \ref seccmake
    • +
    • \ref thirdpartyBoost,
    • +
    • \ref thirdpartyMPFR.
    • +
    + +See Section \ref secessential3rdpartysoftware for more details on essential third party software. + +\section secgettingcgal Downloading CGAL + +You can obtain the \cgal library from +https://www.cgal.org/download.html. + +After you have downloaded the file `CGAL-\cgalReleaseNumber``.tar.gz` containing the +\cgal sources, you have to unpack it. Under a Unix-like shell, use the +command: + + tar xzf CGAL-\cgalReleaseNumber.tar.gz + +In both cases the directory `CGAL-\cgalReleaseNumber` will be created. This directory +contains the following subdirectories: + + +| Directory | Contents | +| :----------- | :----------| +| `auxiliary` | precompiled \sc{Gmp} and \sc{Mpfr} for Windows | +| `cmake/modules` | modules for finding and using libraries | +| `config` | configuration files for install script | +| `demo` | demo programs (most of them need \sc{Qt}, geomview or other third-party products) | +| `doc_html` | documentation (HTML) | +| `examples` | example programs | +| `include` | header files | +| `scripts` | some useful scripts (e.g. for creating CMakeLists.txt files) | +| `src` | source files | + + +The directories `include/CGAL/CORE` and `src/CGALCore` contain a +distribution of the \sc{Core} library\cgalFootnote{`https://cs.nyu.edu/exact/`} version 1.7 for +dealing with algebraic numbers. \sc{Core} is not part of \cgal and has its +own license. + +The directory `include/CGAL/OpenNL` contains a distribution of the +Open Numerical Library which provides solvers for sparse linear systems, +especially designed for the Computer Graphics community. \sc{OpenNL} is not part +of \cgal and has its own license. + +The only documentation shipped within \cgal sources is the present +installation manual. The \cgal manual can be accessed online at +`https://doc.cgal.org` +or downloaded separately from +`https://github.com/CGAL/cgal/releases`. + +\section subsection_headeronly Header-only Usage + +Since \cgal 4.12, \cgal can be used in header-only mode, without even +configuring \cgal\. Programs using \cgal (examples, tests, demos, etc.) +must be directly configured using CMake. In this case, \cgal will be +configured at the same time. The variable `CGAL_DIR` must point to the root +directory of the \cgal source code (either the root of the unpacked release +tarball, or the root of the Git working directory). + +So, using \cgal becomes now: + + cd /path/to/your/code # go to the directory of the code source using CGAL + cmake -DCGAL_DIR= . + +\subsection subsection_headeronly_dependencies CGAL Dependencies + +\cgal can be used as a header-only library, though not all its dependencies +are header-only. The libraries \sc{Gmp} and \sc{Mpfr}, for example, are not +header-only. + +\subsection subsection_headeronly_pbonwindows Possible Problem on Windows + +There is one possible problem when using \cgal in header-only mode on a Windows operating system +when compiling a program using several modules (executable programs or dynamic-link libraries DLL). +If two different modules use the same static variable, this variable is defined independently +in each of these modules. If one module modifies the value of this variable, it will not be modified +in the other module, which could induce an unexpected behavior. In \cgal, this concerns only +a few specific variables: the default random, +the failure behavior, +`CGAL::IO::Mode`. One example is the following: if you change the default random in one DLL, then +if you use the default random in another DLL, you will not obtain the modified default random but the original one. + +\cgalModifBegin +EXPLAIN THAT YOU CAN INSTALL IN CASE OF MEETING THIS PROBLEM (?) +\cgalModifEnd + +\section installation_configuring_using Configuring and Building Programs Using CGAL + +Configuring and compiling a demo/example/program amounts to + + cd CGAL-\cgalReleaseNumber/examples/Triangulation_2 + cmake -DCGAL_DIR=$HOME/CGAL-\cgalReleaseNumber . + make + +The required `CMakeLists.txt` is already provided for all shipped examples and demos of \cgal. +For other programs, CMake can also be used to configure and build user programs, +but one has to provide the `CMakeLists.txt` script either manually, or with the help of a +shell-script that is introduced below. For a user program `executable.cpp`, this ideally then resumes to: + + cd /path/to/program + cgal_create_CMakeLists -s executable + cmake -DCGAL_DIR=$HOME/CGAL-\cgalReleaseNumber . + make + +The script `cgal_create_CMakeLists` and its options are detailed in Section \ref seccreate_cgal_CMakeLists. + +Note that in both examples we specify the `CGAL_DIR`: during configuration of the \cgal libraries +a file named `CGALConfig.cmake` is generated in \cgal's root directory (in contrast +to \cgal's source directory that has been used for installation). This file +contains the definitions of several CMake variable that summarize the +configuration of \cgal. In order to configure a program, you need +to indicate the location of that config file in the CMake variable +`CGAL_DIR` (as indicated in the example above). +`CGAL_DIR` can also be an environment variable. Setting +`CGAL_DIR` makes particular sense if having multiple +out-of-source builds of \cgal as in Section \ref seccmakeoutofsource. + +If you have installed \cgal, `CGAL_DIR` must afterwards be set to +`$CMAKE_INSTALLED_PREFIX/lib/CGAL`. Note that \cgal is +recommended to be installed in release mode when using it to build programs. + +\subsection seccreate_cgal_CMakeLists Creating a CMake Script for a Program Using CGAL + +For compiling a non-shipped program, it is recommended to also rely on a CMake-supported configuration using a +`CMakeLists.txt` used for configuration. The Bourne-shell script `cgal_create_CMakeLists.txt` can +be used to create `CMakeLists.txt` files for compiling \cgal applications +This script resides in the `CGAL-\cgalReleaseNumber``/scripts` directory. +Executing `cgal_create_CMakeLists.txt` in an application directory creates a +`CMakeLists.txt` containing rules to build the contained +application(s). Three command line options determine details of the +configuration. + +
    +
    `-s source`
    If this parameter is given the script will +create a single executable for 'source' linked with +compilations of all other source files +(`*.cc`, `*.cp`, `*.cxx`, `*.cpp`, `*.CPP`, `*.c++`, or `*.C`). +This behaviour is usually needed for (graphical) demos. + +If the parameter is not given, the script creates one executable for each given +source file. +
    `-c com1:com2:...`
    Lists components ("com1", +"com2") of \cgal to which the executable(s) should be linked. Valid components are \cgal's +libraries (i.e.\ "Core", "ImageIO", and "Qt5"). An example is `-c Core`. + +
    `-b boost1:boost2:...`
    Lists components ("boost1", +"boost2") of \sc{Boost} to which the executable(s) should be +linked. Valid options are, for instance, "filesystem" or "program_options". + +
    + +This options should suffice to create `CMakeLists.txt` script +for most directories containing programs. However, in some special +cases, it might still be required to create the script manually, for +instance, if some source files/executables need a different linking than +other source files. + +\section secconfigwithcmake Configuring CGAL with CMake + +Before building anything using \cgal you have to choose the compiler/linker, +set compiler and linker flags, specify which +third-party libraries you want to use and where they can be found, and +which \cgal libraries you want to build. Gathering +all this information is called configuration. +The end of the process is marked by the generation of a makefile or a +Visual \cpp solution and project file that you can use to build \cgal. + +\subsection installation_configuring_gui Configuring CGAL with the CMake GUI + +The simplest way to start the configuration is to run the graphical +user interface of CMake. We recommend to use `cmake-gui`. You must pass as +argument the root directory of \cgal. For example: + + cd CGAL-\cgalReleaseNumber + cmake-gui . # Notice the dot to indicate the current directory. + +After `cmake-gui` opens, press 'Configure'. +A dialog will pop up and you will have to choose what shall gets generated. +After you have made your choice and pressed 'Finish', you will see +the output of configuration tests in the lower portion of the application. +When these tests are done, you will see many +red entries in the upper portion of the application. Just ignore them and press 'Configure'. +By now CMake should have found many libraries and have initialized variables. +If you still find red entries, you have to provide the necessary information. +This typically happens if you have installed software at non-standard locations. +Providing information and pressing 'Configure' goes on until +all entries are grayed. You are now ready to press 'Generate'. Once this is +done, you can quit `cmake-gui`. + +\subsection installation_configuring_cmd Configuring CGAL with the cmake Command-Line Tool + +\cgalModifBegin +MERGE THAT WITH ABOVE, ADAPT TO FIT EXAMPLE CONFIG RATHER THAN CGAL CONFIG, TRIM IT +\cgalModifEnd + +Alternatively, you can run the command-line tool called +`cmake`. You pass as argument the root directory of +\cgal. For example: + + cd CGAL-\cgalReleaseNumber + cmake . # Notice the dot to indicate the current directory. + +The very first thing CMake does is to detect the compiler to use. This +detection is performed by a special CMake module called a +generator. +A CMake generator understands the build requirements for a +particular compiler/linker and generates the necessary files for that. For +example, the UNIX Makefiles generator understands the GNU chain +of tools (\gcc, ld etc.) and produces makefiles, which can be used to build a +target by a simple call to `make`. Likewise, the Visual Studio +2010 generator produces solution and project files and can be manually +launched in the VS IDE to build the target. + +Each platform has a default generator, so you only need to select one when +the default is not what you want. For example, under Windows, it is +possible to generate NMakefiles instead of Visual Studio project +files in order to build the library with `nmake`. Running +`cmake` with no parameters in a command-line prints the list of +available generators supported by your platform and CMake version. If the +generator you need is not listed there, you can try a newer +CMake version, as generators are hardcoded into CMake, and additional +generators are added with each release. + +Since the choice of the generator determines the type of build files to generate, in some cases +you choose a particular generator as a mean to choose a specific compiler (because they use different +build files). For example, the following generates solution files for +use in Visual \cpp 15.0 on a 64bit machine: + + cd CGAL-\cgalReleaseNumber + cmake -G"Visual Studio 15 2017 Win64" . + +In other cases, however, the generator doesn't directly identify a +specific compiler but a chain of tools. +For example, the `UNIX Makefiles` generator produces `makefiles` that call some auto-detected +command-line compiler, like \gcc. If you need the makefiles to use a different compiler, you need to +specify the desired compiler in the call to CMake, as in this example: + + cd CGAL-\cgalReleaseNumber + cmake -DCMAKE_CXX_COMPILER:FILEPATH=g++-4.7 . + +CMake maintains configuration parameters in so-called cmake variables, like the `CMAKE_CXX_COMPILER` +in the example above. These variables are not environment variables but CMake variables. Some of the CMake +variables represent user choices, such as `WITH_examples` or `CMAKE_BUILD_TYPE=Release`, while others +indicate the details of a third-party library, such as `Boost_INCLUDE_DIR` or the compiler flags to use, +such as `CMAKE_CXX_FLAGS`. + +The command line tool `cmake` accepts CMake variables as arguments of the form `-D:=`, as +in the example above, but this is only useful if you already know which variables need to be explicitly defined. + +\cgalAdvancedBegin +CMake keeps the variables that a user can manipulate in a +so-called CMake cache, a simple text file named +`CMakeCache.txt`, whose entries are of the form +`VARIABLE:TYPE=VALUE`. Advanced users can manually edit this file, +instead of going through the interactive configuration session. +\cgalAdvancedEnd + +The configuration process not only determines the location of the required dependencies, it also dynamically generates a +`compiler_config.h` file, which encodes the properties of your system and a special file named +`CGALConfig.cmake`, which is used to build programs using \cgal. The +purpose of this file is explained below. + +\section seccmakeoutofsource Multiple Variants of Makefiles (out-of-source build) + +While you can choose between release or debug builds, and shared or static libraries, +it is not possible to generate different variants during a single configuration. You need to run CMake in a +different directory for each variant you are interested in, each with its own selection of configuration parameters. + +CMake stores the resulting makefiles and project files, along with several temporary and auxiliary files such +as the variables cache, in the directory where it is executed, called `CMAKE_BINARY_DIR`, but it +takes the source files and configuration scripts from +`CMAKE_SOURCE_DIR`. + +The binary and source directories do not need to be the same. Thus, you can configure multiple variants by creating a +distinct directory for each configuration and by running CMake from there. This is known in CMake terminology +as out-of-source configuration, as opposite to an in-source +configuration, as showed in the previous sections. + +You can, for example, generate subdirectories `CGAL-\cgalReleaseNumber``/cmake/platforms/debug` and +`CGAL-\cgalReleaseNumber``/cmake/platforms/release` for two configurations, respectively: + + mkdir CGAL-\cgalReleaseNumber/cmake/platforms/debug + cd CGAL-\cgalReleaseNumber/cmake/platforms/debug + cmake -DCMAKE_BUILD_TYPE=Debug ../../.. + + mkdir CGAL-\cgalReleaseNumber/cmake/platforms/release + cd CGAL-\cgalReleaseNumber/cmake/platforms/release + cmake -DCMAKE_BUILD_TYPE=Release ../../.. + +\section installingcgal Installing CGAL + +Although header-only makes building \cgal obsolete, it is still possible to configure, build, +and install \cgal. Head to \ref installation for more information. + +\cgalModifBegin ++ might still be required to build some cgal libs like cgal-qt? +\cgalModifEnd + +*/ From 8c2f10fec62006927586799840853121fedab304 Mon Sep 17 00:00:00 2001 From: Jasmeet Singh Date: Fri, 12 Jul 2019 10:13:51 -0700 Subject: [PATCH 112/363] Fix bug in is_empty() method which was making the viewer window crash. --- GraphicsView/include/CGAL/Buffer_for_vao.h | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/GraphicsView/include/CGAL/Buffer_for_vao.h b/GraphicsView/include/CGAL/Buffer_for_vao.h index b413a591634..81b5712586b 100644 --- a/GraphicsView/include/CGAL/Buffer_for_vao.h +++ b/GraphicsView/include/CGAL/Buffer_for_vao.h @@ -189,11 +189,11 @@ public: bool is_empty() const { return - (m_pos_buffer!=nullptr && m_pos_buffer->empty()) && - (m_color_buffer!=nullptr || m_color_buffer->empty()) && - (m_flat_normal_buffer!=nullptr || m_flat_normal_buffer->empty()) && - (m_gouraud_normal_buffer!=nullptr || m_gouraud_normal_buffer->empty()) && - (m_index_buffer!=nullptr || m_index_buffer->empty()); + (m_pos_buffer==nullptr && m_pos_buffer->empty()) && + (m_color_buffer==nullptr || m_color_buffer->empty()) && + (m_flat_normal_buffer==nullptr || m_flat_normal_buffer->empty()) && + (m_gouraud_normal_buffer==nullptr || m_gouraud_normal_buffer->empty()) && + (m_index_buffer==nullptr || m_index_buffer->empty()); } bool has_position() const From 1565773fdad723f1b941d53961b07149568e727a Mon Sep 17 00:00:00 2001 From: Jasmeet Singh Date: Fri, 12 Jul 2019 10:46:48 -0700 Subject: [PATCH 113/363] Specialization of draw() function for P2T2, can be called together with another viewer now. --- .../CGAL/draw_periodic_2_triangulation_2.h | 40 +++++++------------ .../include/CGAL/draw_voronoi_diagram_2.h | 26 ------------ 2 files changed, 14 insertions(+), 52 deletions(-) diff --git a/Periodic_2_triangulation_2/include/CGAL/draw_periodic_2_triangulation_2.h b/Periodic_2_triangulation_2/include/CGAL/draw_periodic_2_triangulation_2.h index 2406915d842..3e158d7fd85 100644 --- a/Periodic_2_triangulation_2/include/CGAL/draw_periodic_2_triangulation_2.h +++ b/Periodic_2_triangulation_2/include/CGAL/draw_periodic_2_triangulation_2.h @@ -250,16 +250,20 @@ protected: bool m_domain; }; -template -void draw(const P2T2& ap2t2, - const char* title, - bool nofill, - const ColorFunctor& fcolor) +// Specialization of draw function +#define CGAL_P2T2_TYPE CGAL::Periodic_2_triangulation_2 \ + + +template < class Gt, + class Tds > +void draw(const CGAL_P2T2_TYPE& ap2t2, + const char* title = "2D Periodic Triangulation Viewer", + bool nofill = false) { #if defined(CGAL_TEST_SUITE) bool cgal_test_suite=true; #else - bool cgal_test_suite=false; + bool cgal_test_suite=qEnvironmentVariableIsSet("CGAL_TEST_SUITE"); #endif if (!cgal_test_suite) @@ -267,31 +271,15 @@ void draw(const P2T2& ap2t2, int argc=1; const char* argv[2]={"p2t2_viewer","\0"}; QApplication app(argc,const_cast(argv)); - SimplePeriodic2Triangulation2ViewerQt mainwindow(app.activeWindow(), - ap2t2, - title, - nofill, - fcolor); + DefaultColorFunctorP2T2 fcolor; + SimplePeriodic2Triangulation2ViewerQt + mainwindow(app.activeWindow(), ap2t2, title, nofill, fcolor); mainwindow.show(); app.exec(); } } -template -void draw(const P2T2& ap2t2, const char* title, bool nofill) -{ - DefaultColorFunctorP2T2 c; - draw(ap2t2, title, nofill, c); -} - -template -void draw(const P2T2& ap2t2, const char* title) -{ draw(ap2t2, title, false); } - -template -void draw(const P2T2& ap2t2) -{ draw(ap2t2, "Basic 2D Periodic Triangulation Viewer"); } - } // namespace CGAL #endif // CGAL_USE_BASIC_VIEWER diff --git a/Voronoi_diagram_2/include/CGAL/draw_voronoi_diagram_2.h b/Voronoi_diagram_2/include/CGAL/draw_voronoi_diagram_2.h index c139f5a390d..3e425074553 100644 --- a/Voronoi_diagram_2/include/CGAL/draw_voronoi_diagram_2.h +++ b/Voronoi_diagram_2/include/CGAL/draw_voronoi_diagram_2.h @@ -337,32 +337,6 @@ void draw(const CGAL_VORONOI_TYPE &av2, } } -//template -//void draw(const V2 &av2, const char *title, bool nofill, -// bool draw_voronoi_vertices, bool draw_dual_vertices) { -// DefaultColorFunctorV2 c; -// draw(av2, title, nofill, draw_voronoi_vertices, draw_dual_vertices, c); -//} - -//template -//void draw(const V2 &av2, const char *title, bool nofill, -// bool draw_voronoi_vertices) { -// DefaultColorFunctorV2 c; -// draw(av2, title, nofill, draw_voronoi_vertices, true); -//} - -//template void draw(const V2 &av2, const char *title, bool nofill) { -// draw(av2, title, nofill, true); -//} - -//template void draw(const V2 &av2, const char *title) { -// draw(av2, title, false); -//} - -//template void draw(const V2 &av2) { -// draw(av2, "Basic Voronoi Diagram Viewer"); -//} - } // End namespace CGAL #endif // CGAL_USE_BASIC_VIEWER From a943d8e4790cb833d768461e5cb11113937addc7 Mon Sep 17 00:00:00 2001 From: Jasmeet Singh Date: Fri, 12 Jul 2019 11:12:57 -0700 Subject: [PATCH 114/363] Specialize draw() function for Nef_3 viewer --- Nef_3/include/CGAL/draw_nef_3.h | 34 ++++++------------- .../include/CGAL/draw_voronoi_diagram_2.h | 4 +-- 2 files changed, 12 insertions(+), 26 deletions(-) diff --git a/Nef_3/include/CGAL/draw_nef_3.h b/Nef_3/include/CGAL/draw_nef_3.h index bf47c9b9a2f..ffe49dcbf39 100644 --- a/Nef_3/include/CGAL/draw_nef_3.h +++ b/Nef_3/include/CGAL/draw_nef_3.h @@ -248,10 +248,12 @@ protected: const ColorFunctor &m_fcolor; }; -template -void draw(const Nef_Polyhedron &anef, const char *title, bool nofill, - const ColorFunctor &fcolor) -{ +#define CGAL_NEF3_TYPE Nef_polyhedron_3 + +template +void draw(const CGAL_NEF3_TYPE &anef, + const char *title = "Nef Polyhedron Viewer", + bool nofill = false) { #if defined(CGAL_TEST_SUITE) bool cgal_test_suite = true; #else @@ -263,31 +265,15 @@ void draw(const Nef_Polyhedron &anef, const char *title, bool nofill, int argc = 1; const char *argv[2] = {"nef_polyhedron_viewer", "\0"}; QApplication app(argc, const_cast(argv)); - SimpleNefPolyhedronViewerQt mainwindow( - app.activeWindow(), anef, title, nofill, fcolor); + DefaultColorFunctorNefPolyhedron fcolor; + SimpleNefPolyhedronViewerQt + mainwindow(app.activeWindow(), anef, title, nofill, fcolor); mainwindow.show(); app.exec(); } } -template -void draw(const Nef_Polyhedron &anef, const char *title, bool nofill) -{ - DefaultColorFunctorNefPolyhedron c; - draw(anef, title, nofill, c); -} - -template -void draw(const Nef_Polyhedron &anef, const char *title) -{ - draw(anef, title, false); -} - -template void draw(const Nef_Polyhedron &anef) -{ - draw(anef, "Basic Nef Polyhedron Viewer"); -} - } // End namespace CGAL #endif // CGAL_USE_BASIC_VIEWER diff --git a/Voronoi_diagram_2/include/CGAL/draw_voronoi_diagram_2.h b/Voronoi_diagram_2/include/CGAL/draw_voronoi_diagram_2.h index 3e425074553..fa2cee97587 100644 --- a/Voronoi_diagram_2/include/CGAL/draw_voronoi_diagram_2.h +++ b/Voronoi_diagram_2/include/CGAL/draw_voronoi_diagram_2.h @@ -311,9 +311,9 @@ protected: template> + class AP> void draw(const CGAL_VORONOI_TYPE &av2, - const char *title="Voronoi Diagram Basic Viewer", + const char *title="2D Voronoi Diagram Basic Viewer", bool nofill = false, bool draw_voronoi_vertices = true, bool draw_dual_vertices = true) From b188dabef45390a95969c0fd7bb25ca0f5b144e1 Mon Sep 17 00:00:00 2001 From: Jasmeet Singh Date: Fri, 12 Jul 2019 11:45:55 -0700 Subject: [PATCH 115/363] Small Environment variable fix. --- Nef_3/include/CGAL/draw_nef_3.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Nef_3/include/CGAL/draw_nef_3.h b/Nef_3/include/CGAL/draw_nef_3.h index ffe49dcbf39..39f9f3aa398 100644 --- a/Nef_3/include/CGAL/draw_nef_3.h +++ b/Nef_3/include/CGAL/draw_nef_3.h @@ -257,7 +257,7 @@ void draw(const CGAL_NEF3_TYPE &anef, #if defined(CGAL_TEST_SUITE) bool cgal_test_suite = true; #else - bool cgal_test_suite = false; + bool cgal_test_suite = qEnvironmentVariableIsSet("CGAL_TEST_SUITE"); #endif if (!cgal_test_suite) From c94965a0e1f72095c066ac8f0a54543cf9cc689a Mon Sep 17 00:00:00 2001 From: Jasmeet Singh Date: Fri, 12 Jul 2019 11:59:06 -0700 Subject: [PATCH 116/363] Minor fix in is_empty() method. --- GraphicsView/include/CGAL/Buffer_for_vao.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/GraphicsView/include/CGAL/Buffer_for_vao.h b/GraphicsView/include/CGAL/Buffer_for_vao.h index 81b5712586b..1386c4115c7 100644 --- a/GraphicsView/include/CGAL/Buffer_for_vao.h +++ b/GraphicsView/include/CGAL/Buffer_for_vao.h @@ -189,7 +189,7 @@ public: bool is_empty() const { return - (m_pos_buffer==nullptr && m_pos_buffer->empty()) && + (m_pos_buffer==nullptr || m_pos_buffer->empty()) && (m_color_buffer==nullptr || m_color_buffer->empty()) && (m_flat_normal_buffer==nullptr || m_flat_normal_buffer->empty()) && (m_gouraud_normal_buffer==nullptr || m_gouraud_normal_buffer->empty()) && From 8b207c6aefa2a4d7fb896f2ce66290215c03aaa2 Mon Sep 17 00:00:00 2001 From: Marc Glisse Date: Sat, 13 Jul 2019 23:24:50 +0200 Subject: [PATCH 117/363] Add functors for weighted alpha-complexes. Not sure why I have both Side_of_bounded_sphere and Side_of_bounded_circumsphere for the unweighted case. --- .../CGAL/NewKernel_d/Kernel_d_interface.h | 13 ++ .../CGAL/NewKernel_d/Types/Weighted_point.h | 115 +++++++++++++++--- .../include/CGAL/NewKernel_d/functor_tags.h | 1 + 3 files changed, 110 insertions(+), 19 deletions(-) diff --git a/NewKernel_d/include/CGAL/NewKernel_d/Kernel_d_interface.h b/NewKernel_d/include/CGAL/NewKernel_d/Kernel_d_interface.h index e536b083f0a..af7ab00c8cd 100644 --- a/NewKernel_d/include/CGAL/NewKernel_d/Kernel_d_interface.h +++ b/NewKernel_d/include/CGAL/NewKernel_d/Kernel_d_interface.h @@ -67,6 +67,7 @@ template struct Kernel_d_interface : public Base_ { typedef typename Get_functor::type Point_dimension_d; typedef typename Get_functor::type Side_of_oriented_sphere_d; typedef typename Get_functor::type Power_side_of_power_sphere_d; + typedef typename Get_functor::type Power_side_of_bounded_power_sphere_d; typedef typename Get_functor::type Power_center_d; typedef typename Get_functor::type Power_distance_d; typedef typename Get_functor::type Contained_in_affine_hull_d; @@ -175,6 +176,16 @@ template struct Kernel_d_interface : public Base_ { return typename Get_functor::type(this->kernel())(b,e); } }; + struct Compute_squared_radius_smallest_orthogonal_sphere_d : private Store_kernel { + typedef Kernel R_; // for the macro + CGAL_FUNCTOR_INIT_STORE(Compute_squared_radius_smallest_orthogonal_sphere_d) + typedef FT result_type; + template FT operator()(I b, I e)const{ + typename Get_functor::type pw(this->kernel()); + typename Get_functor::type pc(this->kernel()); + return pw(pc(b,e)); + } + }; typedef typename Construct_cartesian_const_iterator_d::result_type Cartesian_const_iterator_d; typedef typename Get_functor::type Squared_distance_d; typedef typename Get_functor::type Squared_length_d; @@ -219,6 +230,7 @@ template struct Kernel_d_interface : public Base_ { Point_of_sphere_d point_of_sphere_d_object()const{ return Point_of_sphere_d(*this); } Side_of_oriented_sphere_d side_of_oriented_sphere_d_object()const{ return Side_of_oriented_sphere_d(*this); } Power_side_of_power_sphere_d power_side_of_power_sphere_d_object()const{ return Power_side_of_power_sphere_d(*this); } + Power_side_of_bounded_power_sphere_d power_side_of_bounded_power_sphere_d_object()const{ return Power_side_of_bounded_power_sphere_d(*this); } Power_center_d power_center_d_object()const{ return Power_center_d(*this); } Power_distance_d power_distance_d_object()const{ return Power_distance_d(*this); } Side_of_bounded_sphere_d side_of_bounded_sphere_d_object()const{ return Side_of_bounded_sphere_d(*this); } @@ -252,6 +264,7 @@ template struct Kernel_d_interface : public Base_ { Construct_sphere_d construct_sphere_d_object()const{ return Construct_sphere_d(*this); } Construct_hyperplane_d construct_hyperplane_d_object()const{ return Construct_hyperplane_d(*this); } Compute_squared_radius_d compute_squared_radius_d_object()const{ return Compute_squared_radius_d(*this); } + Compute_squared_radius_smallest_orthogonal_sphere_d compute_squared_radius_smallest_orthogonal_sphere_d_object()const{ return Compute_squared_radius_smallest_orthogonal_sphere_d(*this); } Squared_distance_d squared_distance_d_object()const{ return Squared_distance_d(*this); } Squared_length_d squared_length_d_object()const{ return Squared_length_d(*this); } Scalar_product_d scalar_product_d_object()const{ return Scalar_product_d(*this); } diff --git a/NewKernel_d/include/CGAL/NewKernel_d/Types/Weighted_point.h b/NewKernel_d/include/CGAL/NewKernel_d/Types/Weighted_point.h index 815766787b6..fa19a0e8530 100644 --- a/NewKernel_d/include/CGAL/NewKernel_d/Types/Weighted_point.h +++ b/NewKernel_d/include/CGAL/NewKernel_d/Types/Weighted_point.h @@ -178,29 +178,105 @@ template struct Power_center : Store_kernel { WPoint const& wp0 = *f; Point const& p0 = pdw(wp0); int d = pd(p0); - FT const& n0 = sdo(p0) - pw(wp0); - Matrix m(d,d); - Vec b = typename CVec::Dimension()(d); - // Write the point coordinates in lines. - int i; - for(i=0; ++f!=e; ++i) { - WPoint const& wp=*f; - Point const& p=pdw(wp); - for(int j=0;j(std::distance(f,e)); + if (d+1 == k) + { + FT const& n0 = sdo(p0) - pw(wp0); + Matrix m(d,d); + Vec b = typename CVec::Dimension()(d); + // Write the point coordinates in lines. + int i; + for(i=0; ++f!=e; ++i) { + WPoint const& wp=*f; + Point const& p=pdw(wp); + for(int j=0;j::Other LAd; + typedef typename LAd::Square_matrix Matrix; + typedef typename LAd::Vector Vec; + typename Get_functor::type sp(this->kernel()); + Matrix m(k,k); + Vec b(k); + Vec l(k); + int j,i=0; + for(Iter f2=f; f2!=e; ++f2,++i){ + WPoint const& wp = *f2; + Point const& p = pdw(wp); + b(i) = m(i,i) = sdo(p) - pw(wp); + j=0; + for(Iter f3=f; f3!=e; ++f3,++j){ + // FIXME: scalar product of points ??? + m(j,i) = m(i,j) = sp(pdw(*f2),pdw(*f3)); + } + } + for(i=1;i struct Power_side_of_bounded_power_circumsphere : private Store_kernel { + CGAL_FUNCTOR_INIT_STORE(Power_side_of_bounded_power_circumsphere) + typedef typename Get_type::type result_type; + + template + result_type operator()(Iter f, Iter const& e, P const& p0) const { + // TODO: Special case when the dimension is full. + typename Get_functor::type pc(this->kernel()); + typename Get_functor::type pd(this->kernel()); + + // ON_UNBOUNDED_SIDE = -1 + return enum_cast(-CGAL::sign(pd(pc(f, e), p0))); + } +}; + } CGAL_KD_DEFAULT_TYPE(Weighted_point_tag,(CGAL::KerD::Weighted_point),(Point_tag),()); CGAL_KD_DEFAULT_FUNCTOR(Construct_ttag,(CartesianDKernelFunctors::Construct_weighted_point),(Weighted_point_tag,Point_tag),()); @@ -211,5 +287,6 @@ CGAL_KD_DEFAULT_FUNCTOR(In_flat_power_side_of_power_sphere_tag,(CartesianDKernel CGAL_KD_DEFAULT_FUNCTOR(Power_distance_tag,(CartesianDKernelFunctors::Power_distance),(Weighted_point_tag,Point_tag),(Squared_distance_tag,Point_drop_weight_tag,Point_weight_tag)); CGAL_KD_DEFAULT_FUNCTOR(Power_distance_to_point_tag,(CartesianDKernelFunctors::Power_distance_to_point),(Weighted_point_tag,Point_tag),(Squared_distance_tag,Point_drop_weight_tag,Point_weight_tag)); CGAL_KD_DEFAULT_FUNCTOR(Power_center_tag,(CartesianDKernelFunctors::Power_center),(Weighted_point_tag,Point_tag),(Compute_point_cartesian_coordinate_tag,Construct_ttag,Construct_ttag,Point_dimension_tag,Squared_distance_to_origin_tag,Point_drop_weight_tag,Point_weight_tag,Power_distance_to_point_tag)); +CGAL_KD_DEFAULT_FUNCTOR(Power_side_of_bounded_power_circumsphere_tag,(CartesianDKernelFunctors::Power_side_of_bounded_power_circumsphere),(Weighted_point_tag),(Power_distance_tag,Power_center_tag)); } // namespace CGAL #endif diff --git a/NewKernel_d/include/CGAL/NewKernel_d/functor_tags.h b/NewKernel_d/include/CGAL/NewKernel_d/functor_tags.h index ebe4eae4382..67bd8419736 100644 --- a/NewKernel_d/include/CGAL/NewKernel_d/functor_tags.h +++ b/NewKernel_d/include/CGAL/NewKernel_d/functor_tags.h @@ -312,6 +312,7 @@ namespace CGAL { CGAL_DECL_PREDICATE(Contained_in_simplex); CGAL_DECL_PREDICATE(Power_side_of_power_sphere_raw); CGAL_DECL_PREDICATE(Power_side_of_power_sphere); + CGAL_DECL_PREDICATE(Power_side_of_bounded_power_circumsphere); CGAL_DECL_PREDICATE(In_flat_power_side_of_power_sphere_raw); CGAL_DECL_PREDICATE(In_flat_power_side_of_power_sphere); #undef CGAL_DECL_PREDICATE From 5ed0bca7a6a575fbd9f4f97473727d3e474204d8 Mon Sep 17 00:00:00 2001 From: Marc Glisse Date: Sun, 14 Jul 2019 14:58:10 +0200 Subject: [PATCH 118/363] Document the 2 new functors. --- Kernel_d/doc/Kernel_d/CGAL/Epeck_d.h | 20 ++++++++++++++++++++ Kernel_d/doc/Kernel_d/CGAL/Epick_d.h | 20 ++++++++++++++++++++ 2 files changed, 40 insertions(+) diff --git a/Kernel_d/doc/Kernel_d/CGAL/Epeck_d.h b/Kernel_d/doc/Kernel_d/CGAL/Epeck_d.h index 5e2faa6a59f..31a94e2fe6a 100644 --- a/Kernel_d/doc/Kernel_d/CGAL/Epeck_d.h +++ b/Kernel_d/doc/Kernel_d/CGAL/Epeck_d.h @@ -121,6 +121,15 @@ public: template FT operator()(ForwardIterator first, ForwardIterator last); }; +class Compute_squared_radius_smallest_orthogonal_sphere_d { +public: +/*! returns the radius of the sphere defined by `A=tuple[first,last)`. The sphere is centered in the affine hull of A and orthogonal to all the spheres of A. The order of the points of A does not matter. + \pre A is affinely independent. + \tparam ForwardIterator has `Epeck_d::Weighted_point_d` as value type. + */ +template +FT operator()(ForwardIterator first, ForwardIterator last); +}; /*! \cgalModels `Kernel_d::Side_of_bounded_sphere_d` */ class Side_of_bounded_sphere_d { @@ -132,8 +141,19 @@ public: template Bounded_side operator()(ForwardIterator first, ForwardIterator last, const Point_d&p); }; +class Power_side_of_bounded_power_sphere_d { +public: +/*! returns the relative position of weighted point p to the sphere defined by `A=tuple[first,last)`. The sphere is centered in the affine hull of A and orthogonal to all the spheres of A. The order of the points of A does not matter. + \pre A is affinely independent. + \tparam ForwardIterator has `Epeck_d::Weighted_point_d` as value type. + */ +template +Bounded_side operator()(ForwardIterator first, ForwardIterator last, const Weighted_point_d&p); +}; Construct_circumcenter_d construct_circumcenter_d_object(); Compute_squared_radius_d compute_squared_radius_d_object(); +Compute_squared_radius_smallest_orthogonal_sphere_d compute_squared_radius_smallest_orthogonal_sphere_d_object(); +Power_side_of_bounded_power_sphere_d power_side_of_bounded_power_sphere_d_object(); }; /* end Epeck_d */ } /* end namespace CGAL */ /// \cgalModifEnd diff --git a/Kernel_d/doc/Kernel_d/CGAL/Epick_d.h b/Kernel_d/doc/Kernel_d/CGAL/Epick_d.h index 1999d676423..50295d58d96 100644 --- a/Kernel_d/doc/Kernel_d/CGAL/Epick_d.h +++ b/Kernel_d/doc/Kernel_d/CGAL/Epick_d.h @@ -109,6 +109,15 @@ public: template FT operator()(ForwardIterator first, ForwardIterator last); }; +class Compute_squared_radius_smallest_orthogonal_sphere_d { +public: +/*! returns the radius of the sphere defined by `A=tuple[first,last)`. The sphere is centered in the affine hull of A and orthogonal to all the spheres of A. The order of the points of A does not matter. + \pre A is affinely independent. + \tparam ForwardIterator has `Epick_d::Weighted_point_d` as value type. + */ +template +FT operator()(ForwardIterator first, ForwardIterator last); +}; /*! \cgalModels `Kernel_d::Side_of_bounded_sphere_d` */ class Side_of_bounded_sphere_d { @@ -120,7 +129,18 @@ public: template Bounded_side operator()(ForwardIterator first, ForwardIterator last, const Point_d&p); }; +class Power_side_of_bounded_power_sphere_d { +public: +/*! returns the relative position of weighted point p to the sphere defined by `A=tuple[first,last)`. The sphere is centered in the affine hull of A and orthogonal to all the spheres of A. The order of the points of A does not matter. + \pre A is affinely independent. + \tparam ForwardIterator has `Epick_d::Weighted_point_d` as value type. + */ +template +Bounded_side operator()(ForwardIterator first, ForwardIterator last, const Weighted_point_d&p); +}; Construct_circumcenter_d construct_circumcenter_d_object(); Compute_squared_radius_d compute_squared_radius_d_object(); +Compute_squared_radius_smallest_orthogonal_sphere_d compute_squared_radius_smallest_orthogonal_sphere_d_object(); +Power_side_of_bounded_power_sphere_d power_side_of_bounded_power_sphere_d_object(); }; /* end Epick_d */ } /* end namespace CGAL */ From 21cb3ddeb42a27af5f14fd1932c1529bd057a433 Mon Sep 17 00:00:00 2001 From: Marc Glisse Date: Sun, 14 Jul 2019 18:48:14 +0200 Subject: [PATCH 119/363] Test the new functors --- NewKernel_d/test/NewKernel_d/Epick_d.cpp | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/NewKernel_d/test/NewKernel_d/Epick_d.cpp b/NewKernel_d/test/NewKernel_d/Epick_d.cpp index 197e5cd85f9..7a4a3b8ac24 100644 --- a/NewKernel_d/test/NewKernel_d/Epick_d.cpp +++ b/NewKernel_d/test/NewKernel_d/Epick_d.cpp @@ -143,8 +143,9 @@ void test2(){ typedef typename K1::Translated_point_d TP; typedef typename K1::Power_center_d PC; typedef typename K1::Power_distance_d PoD; - typedef typename K1::Weighted_point_d WP; typedef typename K1::Construct_weighted_point_d CWP; + typedef typename K1::Power_side_of_bounded_power_sphere_d PSBPS; + typedef typename K1::Compute_squared_radius_smallest_orthogonal_sphere_d CSRSOS; //typedef typename K1::Point_drop_weight_d PDW; typedef CP PDW; typedef typename K1::Compute_weight_d PW; @@ -215,6 +216,8 @@ void test2(){ PDW const& pdw = cp; PW pw Kinit(compute_weight_d_object); PoD pod Kinit(power_distance_d_object); + PSBPS psbps Kinit(power_side_of_bounded_power_sphere_d_object); + CSRSOS csrsos Kinit(compute_squared_radius_smallest_orthogonal_sphere_d_object); CGAL_USE(bc); CGAL_USE(pol); @@ -378,7 +381,13 @@ void test2(){ assert(pdw(xw)[0]>2.5); assert(pw(xw)<2.95); assert(pw(xw)>2.5); - + assert(psbps(tw+0,tw+3,cwp(cp(5,0),1.499)) == CGAL::ON_UNBOUNDED_SIDE); + assert(psbps(tw+0,tw+3,cwp(cp(5,0),1.500)) == CGAL::ON_BOUNDARY); + assert(psbps(tw+0,tw+3,cwp(cp(5,0),1.501)) == CGAL::ON_BOUNDED_SIDE); + WP tw2[]={cwp(cp(-3,2),1),cwp(cp(5,2),2),cwp(cp(1,6),1)}; + assert(psbps(tw2+0,tw2+2,tw2[2]) == CGAL::ON_UNBOUNDED_SIDE); + assert(abs(csrsos(tw2+0,tw2+2)-14.5039)<.0001); + assert(abs(csrsos(tw2+0,tw2+1)+1)<.0001); P tl=cp(2,5); P br=cp(4,-1); From 50bcc2c1c6db9e946a3d599e154cf47eff2f8cbf Mon Sep 17 00:00:00 2001 From: Jasmeet Singh Date: Mon, 15 Jul 2019 12:18:22 -0700 Subject: [PATCH 120/363] Fix the overlap of faces over edges. Edges visible in two-dimensional basic viewers now. --- GraphicsView/include/CGAL/Qt/Basic_viewer_qt.h | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/GraphicsView/include/CGAL/Qt/Basic_viewer_qt.h b/GraphicsView/include/CGAL/Qt/Basic_viewer_qt.h index b153c17e077..489d13ef12a 100644 --- a/GraphicsView/include/CGAL/Qt/Basic_viewer_qt.h +++ b/GraphicsView/include/CGAL/Qt/Basic_viewer_qt.h @@ -991,6 +991,13 @@ protected: rendering_program_p_l.release(); } + // Fix Z-fighting by drawing faces at a depth + GLfloat offset_factor; + GLfloat offset_units; + glGetFloatv(GL_POLYGON_OFFSET_FACTOR, &offset_factor); + glGetFloatv(GL_POLYGON_OFFSET_UNITS, &offset_units); + glPolygonOffset(0.1f, 0.9f); + if (m_draw_faces) { rendering_program_face.bind(); @@ -1018,7 +1025,7 @@ protected: } glDrawArrays(GL_TRIANGLES, 0, static_cast(arrays[POS_COLORED_FACES].size()/3)); vao[VAO_COLORED_FACES].release(); - + glPolygonOffset(offset_factor, offset_units); rendering_program_face.release(); } From 29209076b1072caa4390110d04168516853bdb85 Mon Sep 17 00:00:00 2001 From: Jasmeet Singh Date: Thu, 18 Jul 2019 12:13:20 -0700 Subject: [PATCH 121/363] Offset Polygons only in the case of 2D data structures. --- .../include/CGAL/Qt/Basic_viewer_qt.h | 20 ++++++++++++++----- 1 file changed, 15 insertions(+), 5 deletions(-) diff --git a/GraphicsView/include/CGAL/Qt/Basic_viewer_qt.h b/GraphicsView/include/CGAL/Qt/Basic_viewer_qt.h index 489d13ef12a..215c348978b 100644 --- a/GraphicsView/include/CGAL/Qt/Basic_viewer_qt.h +++ b/GraphicsView/include/CGAL/Qt/Basic_viewer_qt.h @@ -848,6 +848,11 @@ protected: rendering_program_p_l.release(); } + // Returns true if the data structure can be viewed on a plane + bool is_two_dimensional() { + return (!is_empty() && (has_zero_x() || has_zero_y() || has_zero_z())); + } + virtual void draw() { glEnable(GL_DEPTH_TEST); @@ -994,9 +999,11 @@ protected: // Fix Z-fighting by drawing faces at a depth GLfloat offset_factor; GLfloat offset_units; - glGetFloatv(GL_POLYGON_OFFSET_FACTOR, &offset_factor); - glGetFloatv(GL_POLYGON_OFFSET_UNITS, &offset_units); - glPolygonOffset(0.1f, 0.9f); + if (is_two_dimensional()) { + glGetFloatv(GL_POLYGON_OFFSET_FACTOR, &offset_factor); + glGetFloatv(GL_POLYGON_OFFSET_UNITS, &offset_units); + glPolygonOffset(0.1f, 0.9f); + } if (m_draw_faces) { @@ -1025,11 +1032,14 @@ protected: } glDrawArrays(GL_TRIANGLES, 0, static_cast(arrays[POS_COLORED_FACES].size()/3)); vao[VAO_COLORED_FACES].release(); - glPolygonOffset(offset_factor, offset_units); + + if (is_two_dimensional()) + glPolygonOffset(offset_factor, offset_units); + rendering_program_face.release(); } - if (!is_empty() && (has_zero_x() || has_zero_y() || has_zero_z())) + if (is_two_dimensional()) { camera()->setType(CGAL::qglviewer::Camera::ORTHOGRAPHIC); // Camera Constraint: From 8250ae7ce02915136b19a231ff812a9aab031695 Mon Sep 17 00:00:00 2001 From: Jasmeet Singh Date: Thu, 18 Jul 2019 12:16:03 -0700 Subject: [PATCH 122/363] Correct comment. --- GraphicsView/include/CGAL/Qt/Basic_viewer_qt.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/GraphicsView/include/CGAL/Qt/Basic_viewer_qt.h b/GraphicsView/include/CGAL/Qt/Basic_viewer_qt.h index 215c348978b..7768dfa10e8 100644 --- a/GraphicsView/include/CGAL/Qt/Basic_viewer_qt.h +++ b/GraphicsView/include/CGAL/Qt/Basic_viewer_qt.h @@ -848,7 +848,7 @@ protected: rendering_program_p_l.release(); } - // Returns true if the data structure can be viewed on a plane + // Returns true if the data structure lies on a plane bool is_two_dimensional() { return (!is_empty() && (has_zero_x() || has_zero_y() || has_zero_z())); } From 215d05f71496583ee34061273fe481d49712c69c Mon Sep 17 00:00:00 2001 From: Marc Glisse Date: Tue, 23 Jul 2019 14:52:51 +0200 Subject: [PATCH 123/363] TAB-allergy --- .../CGAL/NewKernel_d/Kernel_d_interface.h | 26 +++++++++---------- .../CGAL/NewKernel_d/Types/Weighted_point.h | 20 +++++++------- .../include/CGAL/NewKernel_d/functor_tags.h | 2 +- 3 files changed, 24 insertions(+), 24 deletions(-) diff --git a/NewKernel_d/include/CGAL/NewKernel_d/Kernel_d_interface.h b/NewKernel_d/include/CGAL/NewKernel_d/Kernel_d_interface.h index af7ab00c8cd..b14892e0465 100644 --- a/NewKernel_d/include/CGAL/NewKernel_d/Kernel_d_interface.h +++ b/NewKernel_d/include/CGAL/NewKernel_d/Kernel_d_interface.h @@ -67,7 +67,7 @@ template struct Kernel_d_interface : public Base_ { typedef typename Get_functor::type Point_dimension_d; typedef typename Get_functor::type Side_of_oriented_sphere_d; typedef typename Get_functor::type Power_side_of_power_sphere_d; - typedef typename Get_functor::type Power_side_of_bounded_power_sphere_d; + typedef typename Get_functor::type Power_side_of_bounded_power_sphere_d; typedef typename Get_functor::type Power_center_d; typedef typename Get_functor::type Power_distance_d; typedef typename Get_functor::type Contained_in_affine_hull_d; @@ -176,16 +176,16 @@ template struct Kernel_d_interface : public Base_ { return typename Get_functor::type(this->kernel())(b,e); } }; - struct Compute_squared_radius_smallest_orthogonal_sphere_d : private Store_kernel { - typedef Kernel R_; // for the macro - CGAL_FUNCTOR_INIT_STORE(Compute_squared_radius_smallest_orthogonal_sphere_d) - typedef FT result_type; - template FT operator()(I b, I e)const{ - typename Get_functor::type pw(this->kernel()); - typename Get_functor::type pc(this->kernel()); - return pw(pc(b,e)); - } - }; + struct Compute_squared_radius_smallest_orthogonal_sphere_d : private Store_kernel { + typedef Kernel R_; // for the macro + CGAL_FUNCTOR_INIT_STORE(Compute_squared_radius_smallest_orthogonal_sphere_d) + typedef FT result_type; + template FT operator()(I b, I e)const{ + typename Get_functor::type pw(this->kernel()); + typename Get_functor::type pc(this->kernel()); + return pw(pc(b,e)); + } + }; typedef typename Construct_cartesian_const_iterator_d::result_type Cartesian_const_iterator_d; typedef typename Get_functor::type Squared_distance_d; typedef typename Get_functor::type Squared_length_d; @@ -230,7 +230,7 @@ template struct Kernel_d_interface : public Base_ { Point_of_sphere_d point_of_sphere_d_object()const{ return Point_of_sphere_d(*this); } Side_of_oriented_sphere_d side_of_oriented_sphere_d_object()const{ return Side_of_oriented_sphere_d(*this); } Power_side_of_power_sphere_d power_side_of_power_sphere_d_object()const{ return Power_side_of_power_sphere_d(*this); } - Power_side_of_bounded_power_sphere_d power_side_of_bounded_power_sphere_d_object()const{ return Power_side_of_bounded_power_sphere_d(*this); } + Power_side_of_bounded_power_sphere_d power_side_of_bounded_power_sphere_d_object()const{ return Power_side_of_bounded_power_sphere_d(*this); } Power_center_d power_center_d_object()const{ return Power_center_d(*this); } Power_distance_d power_distance_d_object()const{ return Power_distance_d(*this); } Side_of_bounded_sphere_d side_of_bounded_sphere_d_object()const{ return Side_of_bounded_sphere_d(*this); } @@ -264,7 +264,7 @@ template struct Kernel_d_interface : public Base_ { Construct_sphere_d construct_sphere_d_object()const{ return Construct_sphere_d(*this); } Construct_hyperplane_d construct_hyperplane_d_object()const{ return Construct_hyperplane_d(*this); } Compute_squared_radius_d compute_squared_radius_d_object()const{ return Compute_squared_radius_d(*this); } - Compute_squared_radius_smallest_orthogonal_sphere_d compute_squared_radius_smallest_orthogonal_sphere_d_object()const{ return Compute_squared_radius_smallest_orthogonal_sphere_d(*this); } + Compute_squared_radius_smallest_orthogonal_sphere_d compute_squared_radius_smallest_orthogonal_sphere_d_object()const{ return Compute_squared_radius_smallest_orthogonal_sphere_d(*this); } Squared_distance_d squared_distance_d_object()const{ return Squared_distance_d(*this); } Squared_length_d squared_length_d_object()const{ return Squared_length_d(*this); } Scalar_product_d scalar_product_d_object()const{ return Scalar_product_d(*this); } diff --git a/NewKernel_d/include/CGAL/NewKernel_d/Types/Weighted_point.h b/NewKernel_d/include/CGAL/NewKernel_d/Types/Weighted_point.h index fa19a0e8530..6029435be1b 100644 --- a/NewKernel_d/include/CGAL/NewKernel_d/Types/Weighted_point.h +++ b/NewKernel_d/include/CGAL/NewKernel_d/Types/Weighted_point.h @@ -187,12 +187,12 @@ template struct Power_center : Store_kernel { // Write the point coordinates in lines. int i; for(i=0; ++f!=e; ++i) { - WPoint const& wp=*f; - Point const& p=pdw(wp); - for(int j=0;j struct Power_center : Store_kernel { Vec l(k); int j,i=0; for(Iter f2=f; f2!=e; ++f2,++i){ - WPoint const& wp = *f2; - Point const& p = pdw(wp); + WPoint const& wp = *f2; + Point const& p = pdw(wp); b(i) = m(i,i) = sdo(p) - pw(wp); j=0; for(Iter f3=f; f3!=e; ++f3,++j){ - // FIXME: scalar product of points ??? + // FIXME: scalar product of points ??? m(j,i) = m(i,j) = sp(pdw(*f2),pdw(*f3)); } } @@ -272,7 +272,7 @@ template struct Power_side_of_bounded_power_circumsphere : private Sto typename Get_functor::type pc(this->kernel()); typename Get_functor::type pd(this->kernel()); - // ON_UNBOUNDED_SIDE = -1 + // ON_UNBOUNDED_SIDE = -1 return enum_cast(-CGAL::sign(pd(pc(f, e), p0))); } }; diff --git a/NewKernel_d/include/CGAL/NewKernel_d/functor_tags.h b/NewKernel_d/include/CGAL/NewKernel_d/functor_tags.h index 67bd8419736..a5d19ecbaef 100644 --- a/NewKernel_d/include/CGAL/NewKernel_d/functor_tags.h +++ b/NewKernel_d/include/CGAL/NewKernel_d/functor_tags.h @@ -312,7 +312,7 @@ namespace CGAL { CGAL_DECL_PREDICATE(Contained_in_simplex); CGAL_DECL_PREDICATE(Power_side_of_power_sphere_raw); CGAL_DECL_PREDICATE(Power_side_of_power_sphere); - CGAL_DECL_PREDICATE(Power_side_of_bounded_power_circumsphere); + CGAL_DECL_PREDICATE(Power_side_of_bounded_power_circumsphere); CGAL_DECL_PREDICATE(In_flat_power_side_of_power_sphere_raw); CGAL_DECL_PREDICATE(In_flat_power_side_of_power_sphere); #undef CGAL_DECL_PREDICATE From 869baed46fb87a691accc61d6efd928f0681cd8b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mael=20Rouxel-Labb=C3=A9?= Date: Mon, 19 Aug 2019 17:18:29 +0200 Subject: [PATCH 124/363] Fix not throwing on overlapping constraints --- .../CGAL/Constrained_triangulation_2.h | 33 +++++++++++++++++-- 1 file changed, 31 insertions(+), 2 deletions(-) diff --git a/Triangulation_2/include/CGAL/Constrained_triangulation_2.h b/Triangulation_2/include/CGAL/Constrained_triangulation_2.h index cd79f2c2914..d0f26f5bfb9 100644 --- a/Triangulation_2/include/CGAL/Constrained_triangulation_2.h +++ b/Triangulation_2/include/CGAL/Constrained_triangulation_2.h @@ -43,6 +43,7 @@ #include #include +#include namespace CGAL { @@ -301,7 +302,21 @@ insert_constraint(Vertex_handle vaa, Vertex_handle vbb, OutputIterator out) Face_handle fr; int i; - if(includes_edge(vaa,vbb,vi,fr,i)) { + if(includes_edge(vaa,vbb,vi,fr,i)) + { + // if the segment (or a subpart of the segment) that we are trying to constraint is already + // present in the triangulation and is already marked as constrained, + // then this is an intersection + if(boost::is_same::value) { + if(dimension() == 1) { + if(fr->is_constrained(2)) + throw Intersection_of_constraints_exception(); + } else { + if(fr->is_constrained(i)) + throw Intersection_of_constraints_exception(); + } + } + mark_constraint(fr,i); if (vi != vbb) { insert_constraint(vi,vbb,out); @@ -720,7 +735,21 @@ insert_constraint(Vertex_handle vaa, Vertex_handle vbb) Face_handle fr; int i; - if(includes_edge(vaa,vbb,vi,fr,i)) { + if(includes_edge(vaa,vbb,vi,fr,i)) + { + // if the segment (or a subpart of the segment) that we are trying to constraint is already + // present in the triangulation and is already marked as constrained, + // then this is an intersection + if(boost::is_same::value) { + if(dimension() == 1) { + if(fr->is_constrained(2)) + throw Intersection_of_constraints_exception(); + } else { + if(fr->is_constrained(i)) + throw Intersection_of_constraints_exception(); + } + } + mark_constraint(fr,i); if (vi != vbb) { stack.push(std::make_pair(vi,vbb)); From f3ccb18da0b372e404dafed3eaec83edda85272f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mael=20Rouxel-Labb=C3=A9?= Date: Mon, 19 Aug 2019 17:18:55 +0200 Subject: [PATCH 125/363] Fix typo --- Triangulation_2/include/CGAL/Constrained_triangulation_2.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Triangulation_2/include/CGAL/Constrained_triangulation_2.h b/Triangulation_2/include/CGAL/Constrained_triangulation_2.h index d0f26f5bfb9..f1fc1f16744 100644 --- a/Triangulation_2/include/CGAL/Constrained_triangulation_2.h +++ b/Triangulation_2/include/CGAL/Constrained_triangulation_2.h @@ -928,7 +928,7 @@ intersect(Face_handle f, int i, "would avoid cascading intersection computation\n" " and be much more efficient\n" "This message is shown only if CGAL_NO_CDT_2_WARNING" - "is not defined.\n"); + " is not defined.\n"); #endif const Point& pa = vaa->point(); const Point& pb = vbb->point(); From 5ef8c966eac0839bc5f144d43c1c222b71c596ac Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mael=20Rouxel-Labb=C3=A9?= Date: Mon, 19 Aug 2019 17:19:15 +0200 Subject: [PATCH 126/363] Add some tests for CDT throwing on intersections --- .../_test_cls_constrained_triangulation_2.h | 54 +++++++++++++++++-- .../test_constrained_triangulation_2.cpp | 2 + 2 files changed, 53 insertions(+), 3 deletions(-) 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 4c937317dba..f06bc6d0a37 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 @@ -24,6 +24,32 @@ #include #include +#include + +template +void +_test_cdt_throwing(const Pt& p0, const Pt& p1, const Pt& p2, const Pt& p3, const bool intersect) +{ + std::cout << "test_cdt_throwing [" << p0 << "] - [" << p1 << "] || [" << p2 << "] - [" << p3 << "]" << std::endl; + + try + { + Triang tr; + tr.insert_constraint(p0, p1); + tr.insert_constraint(p2, p3); + } + catch (typename Triang::Intersection_of_constraints_exception& e) + { + std::cout << "threw, expected it? " << std::boolalpha << intersect << std::endl; + assert(intersect); + assert((boost::is_same::value)); + return; + } + + if(intersect) { + assert(!(boost::is_same::value)); + } +} template void @@ -134,7 +160,7 @@ _test_cls_constrained_triangulation(const Triang &) // between constrained and Constrained Delaunay Triang T2_5; for (int j=0; j < 20; j++) T2_5.insert(lpt[j]); - T2_5.insert( Point(1,0.5), Point(2.5, 3.5)); + T2_5.insert_constraint( Point(1,0.5), Point(2.5, 3.5)); T2_5.is_valid(); @@ -220,8 +246,9 @@ _test_cls_constrained_triangulation(const Triang &) assert(T1_2.is_edge(vha,vhb, fh, ih)); assert(fh->is_constrained(ih)); T1_2.remove_constrained_edge(fh,ih); + assert(!fh->is_constrained(ih)); assert(T1_2.is_valid()); - T1_2.insert(Point(0,0),Point(3,2)); + T1_2.insert_constraint(Point(0,0),Point(3,2)); fh = T1_2.locate(Point(3,2),lt,li); assert( lt == Triang::VERTEX ); vhb = fh->vertex(li); assert(T1_2.are_there_incident_constraints(vhb)); @@ -241,7 +268,6 @@ _test_cls_constrained_triangulation(const Triang &) assert(ic_edges.size() == 1); T1_2.remove(vha); assert(T1_2.is_valid()); - // remove_constraint and remove 2 dim std::cout << "remove_constrained_edge and remove 2-dim " << std::endl; @@ -290,4 +316,26 @@ _test_cls_constrained_triangulation(const Triang &) T2_6.insert_constraint(Point(1,0.1), Point(2,0.2)); assert(std::distance(T2_6.constrained_edges_begin(), T2_6.constrained_edges_end()) == 1); + + // test throwing/not throwing on intersecting constraints + _test_cdt_throwing(Point(0, 0), Point(1, 1), Point(2, 2), Point(2, 3), false /*no intersection*/); + _test_cdt_throwing(Point(0, 0), Point(1, 1), Point(1, 1), Point(2, 2), false); // common point + _test_cdt_throwing(Point(2, 2), Point(0, 0), Point(2, 2), Point(3, 3), false); // ^ + _test_cdt_throwing(Point(0, 0), Point(2, 2), Point(1, 1), Point(3, 3), true); // overlapping + _test_cdt_throwing(Point(2, 2), Point(0, 0), Point(1, 1), Point(3, 3), true); // ^ + _test_cdt_throwing(Point(2, 2), Point(0, 0), Point(0, 0), Point(3, 3), true); // ^ + _test_cdt_throwing(Point(2, 2), Point(0, 0), Point(3, 3), Point(0, 0), true); // ^ + _test_cdt_throwing(Point(0, 0), Point(3, 3), Point(1, 1), Point(2, 2), true); // contains + _test_cdt_throwing(Point(3, 3), Point(0, 0), Point(1, 1), Point(2, 2), true); // ^ + _test_cdt_throwing(Point(3, 3), Point(0, 0), Point(0, 0), Point(3, 3), true); // same constraint + _test_cdt_throwing(Point(3, 3), Point(0, 0), Point(1, 1), Point(1, 1), true); // degenerate entry + _test_cdt_throwing(Point(0, 0), Point(0, 0), Point(0, 0), Point(0, 0), false); // degenerate same entry + + // non aligned + _test_cdt_throwing(Point(0, 0), Point(3, 3), Point(1, 0), Point(4, 0), false); + _test_cdt_throwing(Point(0, 2), Point(2, 2), Point(1, 0), Point(1, 3), true); // generic intersection + _test_cdt_throwing(Point(0, 0), Point(2, 2), Point(1, 3), Point(1, 0), true); + + // extremity on the interior of another segment + _test_cdt_throwing(Point(0, 0), Point(2, 0), Point(1, 0), Point(1, 4), true); } diff --git a/Triangulation_2/test/Triangulation_2/test_constrained_triangulation_2.cpp b/Triangulation_2/test/Triangulation_2/test_constrained_triangulation_2.cpp index d5ef24f9624..16be9b3eec3 100644 --- a/Triangulation_2/test/Triangulation_2/test_constrained_triangulation_2.cpp +++ b/Triangulation_2/test/Triangulation_2/test_constrained_triangulation_2.cpp @@ -20,6 +20,8 @@ // coordinator : INRIA Sophia-Antipolis // ============================================================================ +#define CGAL_NO_CDT_2_WARNING + #include #include From 59e0e87e24f9adeb4ec1a63f9ce5ef39dfaef6d6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mael=20Rouxel-Labb=C3=A9?= Date: Mon, 19 Aug 2019 17:55:26 +0200 Subject: [PATCH 127/363] Readability (no real changes) --- .../include/CGAL/Constrained_triangulation_2.h | 13 +++++++++---- .../include/CGAL/Constrained_triangulation_plus_2.h | 1 + 2 files changed, 10 insertions(+), 4 deletions(-) diff --git a/Triangulation_2/include/CGAL/Constrained_triangulation_2.h b/Triangulation_2/include/CGAL/Constrained_triangulation_2.h index f1fc1f16744..bf43485cf59 100644 --- a/Triangulation_2/include/CGAL/Constrained_triangulation_2.h +++ b/Triangulation_2/include/CGAL/Constrained_triangulation_2.h @@ -672,9 +672,15 @@ insert(const Point& a, Locate_type lt, Face_handle loc, int li) } va = Triangulation::insert(a,lt,loc,li); - if (insert_in_constrained_edge) update_constraints_incident(va, v1,v2); - else if(lt != Triangulation::VERTEX) clear_constraints_incident(va); - if (dimension() == 2) update_constraints_opposite(va); + + if (insert_in_constrained_edge) + update_constraints_incident(va, v1,v2); + else if(lt != Triangulation::VERTEX) + clear_constraints_incident(va); + + if (dimension() == 2) + update_constraints_opposite(va); + return va; } @@ -759,7 +765,6 @@ insert_constraint(Vertex_handle vaa, Vertex_handle vbb) List_faces intersected_faces; List_edges conflict_boundary_ab, conflict_boundary_ba; - bool intersection = find_intersected_faces( vaa, vbb, intersected_faces, conflict_boundary_ab, diff --git a/Triangulation_2/include/CGAL/Constrained_triangulation_plus_2.h b/Triangulation_2/include/CGAL/Constrained_triangulation_plus_2.h index 255abb52a11..921ee6dbf22 100644 --- a/Triangulation_2/include/CGAL/Constrained_triangulation_plus_2.h +++ b/Triangulation_2/include/CGAL/Constrained_triangulation_plus_2.h @@ -946,6 +946,7 @@ insert(const Point& a, Locate_type lt, Face_handle loc, int li) v1=loc->vertex(ccw(li)); //endpoint of the constraint v2=loc->vertex(cw(li)); // endpoint of the constraint } + Vertex_handle va = Triangulation::insert(a,lt,loc,li); // update the hierarchy if (insert_in_constrained_edge) { From 013272a466131295c14f3b3c3b3905dae7bc0a48 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mael=20Rouxel-Labb=C3=A9?= Date: Mon, 19 Aug 2019 17:55:39 +0200 Subject: [PATCH 128/363] Fix not throwing on T-like segment intersection (extremity on interior) --- Triangulation_2/include/CGAL/Constrained_triangulation_2.h | 6 +++++- .../include/CGAL/Constrained_triangulation_plus_2.h | 7 ++++++- 2 files changed, 11 insertions(+), 2 deletions(-) diff --git a/Triangulation_2/include/CGAL/Constrained_triangulation_2.h b/Triangulation_2/include/CGAL/Constrained_triangulation_2.h index bf43485cf59..888154dd97d 100644 --- a/Triangulation_2/include/CGAL/Constrained_triangulation_2.h +++ b/Triangulation_2/include/CGAL/Constrained_triangulation_2.h @@ -665,7 +665,11 @@ insert(const Point& a, Locate_type lt, Face_handle loc, int li) Vertex_handle v1, v2; bool insert_in_constrained_edge = false; - if ( lt == Triangulation::EDGE && loc->is_constrained(li) ){ + if ( lt == Triangulation::EDGE && loc->is_constrained(li) ) + { + if(boost::is_same::value) + throw Intersection_of_constraints_exception(); + insert_in_constrained_edge = true; v1=loc->vertex(ccw(li)); //endpoint of the constraint v2=loc->vertex(cw(li)); // endpoint of the constraint diff --git a/Triangulation_2/include/CGAL/Constrained_triangulation_plus_2.h b/Triangulation_2/include/CGAL/Constrained_triangulation_plus_2.h index 921ee6dbf22..d2fda45e417 100644 --- a/Triangulation_2/include/CGAL/Constrained_triangulation_plus_2.h +++ b/Triangulation_2/include/CGAL/Constrained_triangulation_plus_2.h @@ -30,6 +30,7 @@ #include #include #include +#include #include #include @@ -941,7 +942,11 @@ insert(const Point& a, Locate_type lt, Face_handle loc, int li) Vertex_handle v1, v2; bool insert_in_constrained_edge = false; - if ( lt == Triangulation::EDGE && loc->is_constrained(li) ){ + if ( lt == Triangulation::EDGE && loc->is_constrained(li) ) + { + if(boost::is_same::value) + throw typename Tr::Intersection_of_constraints_exception(); + insert_in_constrained_edge = true; v1=loc->vertex(ccw(li)); //endpoint of the constraint v2=loc->vertex(cw(li)); // endpoint of the constraint From 970b0cfeaa06e6ff98d3d8d8b8b9f442432f83b8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mael=20Rouxel-Labb=C3=A9?= Date: Mon, 19 Aug 2019 18:02:06 +0200 Subject: [PATCH 129/363] Add few more tests --- .../include/CGAL/_test_cls_constrained_triangulation_2.h | 2 ++ 1 file changed, 2 insertions(+) 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 f06bc6d0a37..bf1660f04cc 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 @@ -327,6 +327,8 @@ _test_cls_constrained_triangulation(const Triang &) _test_cdt_throwing(Point(2, 2), Point(0, 0), Point(3, 3), Point(0, 0), true); // ^ _test_cdt_throwing(Point(0, 0), Point(3, 3), Point(1, 1), Point(2, 2), true); // contains _test_cdt_throwing(Point(3, 3), Point(0, 0), Point(1, 1), Point(2, 2), true); // ^ + _test_cdt_throwing(Point(1, 1), Point(2, 2), Point(3, 3), Point(0, 0), true); // ^ + _test_cdt_throwing(Point(2, 2), Point(1, 1), Point(3, 3), Point(0, 0), true); // ^ _test_cdt_throwing(Point(3, 3), Point(0, 0), Point(0, 0), Point(3, 3), true); // same constraint _test_cdt_throwing(Point(3, 3), Point(0, 0), Point(1, 1), Point(1, 1), true); // degenerate entry _test_cdt_throwing(Point(0, 0), Point(0, 0), Point(0, 0), Point(0, 0), false); // degenerate same entry From b60f1f5205bf3ea4fe8b04ba5836f117479ba530 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mael=20Rouxel-Labb=C3=A9?= Date: Wed, 21 Aug 2019 16:24:19 +0200 Subject: [PATCH 130/363] stitch_borders() now returns the number of halfedge pairs that were stitched --- .../Polygon_mesh_processing/stitch_borders.h | 28 +++++++++++-------- 1 file changed, 16 insertions(+), 12 deletions(-) diff --git a/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/stitch_borders.h b/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/stitch_borders.h index fa70d023d65..0bb871f7be9 100644 --- a/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/stitch_borders.h +++ b/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/stitch_borders.h @@ -811,9 +811,9 @@ std::size_t stitch_boundary_cycles(PolygonMesh& pm) template -void stitch_borders(PolygonMesh& pmesh, - const HalfedgePairsRange& hedge_pairs_to_stitch, - const CGAL_PMP_NP_CLASS& np) +std::size_t stitch_borders(PolygonMesh& pmesh, + const HalfedgePairsRange& hedge_pairs_to_stitch, + const CGAL_PMP_NP_CLASS& np) { using parameters::choose_parameter; using parameters::get_parameter; @@ -822,7 +822,7 @@ void stitch_borders(PolygonMesh& pmesh, VPMap vpm = choose_parameter(get_parameter(np, internal_np::vertex_point), get_const_property_map(vertex_point, pmesh)); - internal::stitch_borders_impl(pmesh, hedge_pairs_to_stitch, vpm); + return internal::stitch_borders_impl(pmesh, hedge_pairs_to_stitch, vpm); } ///\endcond @@ -846,10 +846,10 @@ void stitch_borders(PolygonMesh& pmesh, */ template -void stitch_borders(PolygonMesh& pmesh, +std::size_t stitch_borders(PolygonMesh& pmesh, const HalfedgePairsRange& hedge_pairs_to_stitch) { - stitch_borders(pmesh, hedge_pairs_to_stitch, CGAL::parameters::all_default()); + return stitch_borders(pmesh, hedge_pairs_to_stitch, CGAL::parameters::all_default()); } /// \ingroup PMP_repairing_grp @@ -878,11 +878,14 @@ void stitch_borders(PolygonMesh& pmesh, /// \cgalParamBegin{face_index_map} a property map containing the index of each face of `pmesh` \cgalParamEnd /// \cgalNamedParamsEnd /// +/// @return the number of pairs of halfedges that were stitched +/// /// @sa `stitch_boundary_cycle()` /// @sa `stitch_boundary_cycles()` /// template -void stitch_borders(PolygonMesh& pmesh, const CGAL_PMP_NP_CLASS& np) +std::size_t stitch_borders(PolygonMesh& pmesh, + const CGAL_PMP_NP_CLASS& np) { using parameters::choose_parameter; using parameters::get_parameter; @@ -911,26 +914,27 @@ void stitch_borders(PolygonMesh& pmesh, const CGAL_PMP_NP_CLASS& np) internal::Less_for_halfedge(pmesh, vpm), vpm, np); - stitch_borders(pmesh, hedge_pairs_to_stitch, np); + res += stitch_borders(pmesh, hedge_pairs_to_stitch, np); #ifdef CGAL_PMP_STITCHING_DEBUG + std::cout << "------- Stitched " << res << " after cycles & general" << std::endl; std::cout << "------- Stitch cycles (#2)..." << std::endl; #endif res += stitch_boundary_cycles(pmesh, np); #ifdef CGAL_PMP_STITCHING_DEBUG - std::cout << "------- Stitched " << res << " in boundary cycles" << std::endl; + std::cout << "------- Stitched " << res << " (total)" << std::endl; #endif - CGAL_USE(res); + return res; } ///\cond SKIP_IN_MANUAL template -void stitch_borders(PolygonMesh& pmesh) +std::size_t stitch_borders(PolygonMesh& pmesh) { - stitch_borders(pmesh, CGAL::parameters::all_default()); + return stitch_borders(pmesh, CGAL::parameters::all_default()); } ///\endcond From b23151b59860038df7c657c662dc65966e9f009f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mael=20Rouxel-Labb=C3=A9?= Date: Wed, 21 Aug 2019 16:25:09 +0200 Subject: [PATCH 131/363] Update stitch_borders() tests to verify that we stitched what was expected --- .../test_stitching.cpp | 84 +++++++++++-------- 1 file changed, 51 insertions(+), 33 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 e001896c859..f2ae9f68f60 100644 --- a/Polygon_mesh_processing/test/Polygon_mesh_processing/test_stitching.cpp +++ b/Polygon_mesh_processing/test/Polygon_mesh_processing/test_stitching.cpp @@ -33,12 +33,15 @@ void test_stitch_boundary_cycles(const char* fname, } std::size_t res = PMP::stitch_boundary_cycles(mesh); + std::cout << "res: " << res << " (expected: " << expected_n << ")" << std::endl; + assert(res == expected_n); assert(is_valid(mesh)); } template -void test_polyhedron(const char* fname) +void test_polyhedron(const char* fname, + const std::size_t expected_n) { std::cout << "Testing Polyhedron_3 " << fname << "..." << std::flush; @@ -53,15 +56,19 @@ void test_polyhedron(const char* fname) assert(poly.size_of_vertices() > 0); - PMP::stitch_borders(poly); + std::size_t res = PMP::stitch_borders(poly); poly.normalize_border(); + std::cout << "res: " << res << " (expected: " << expected_n << ")" << std::endl; assert(poly.is_valid(false, 5)); + assert(res == expected_n); + std::cout << "OK\n"; } template -void test_polyhedron_cc(const char* fname) +void test_polyhedron_cc(const char* fname, + const std::size_t expected_n) { std::cout << "Testing Polyhedron_3 " << fname << "..." << std::flush; @@ -76,14 +83,18 @@ void test_polyhedron_cc(const char* fname) assert(poly.size_of_vertices() > 0); - PMP::stitch_borders(poly, params::apply_per_connected_component(true)); + std::size_t res = PMP::stitch_borders(poly, params::apply_per_connected_component(true)); poly.normalize_border(); + std::cout << "res: " << res << " (expected: " << expected_n << ")" << std::endl; assert(poly.is_valid(false, 5)); + assert(res == expected_n); + std::cout << "OK\n"; } -void test_surface_mesh(const char* fname) +void test_surface_mesh(const char* fname, + const std::size_t expected_n) { std::cout << "Testing Surface_mesh " << fname << "..." << std::flush; @@ -96,13 +107,17 @@ void test_surface_mesh(const char* fname) return; } - PMP::stitch_borders(mesh); + std::size_t res = PMP::stitch_borders(mesh); + std::cout << "res: " << res << " (expected: " << expected_n << ")" << std::endl; + + assert(res == expected_n); assert(is_valid_polygon_mesh(mesh)); std::cout << "OK\n"; } -void test_surface_mesh_cc(const char* fname) +void test_surface_mesh_cc(const char* fname, + const std::size_t expected_n) { std::cout << "Testing Surface_mesh " << fname << "..." << std::flush; @@ -115,7 +130,10 @@ void test_surface_mesh_cc(const char* fname) return; } - PMP::stitch_borders(mesh, params::apply_per_connected_component(true)); + std::size_t res = PMP::stitch_borders(mesh, params::apply_per_connected_component(true)); + std::cout << "res: " << res << " (expected: " << expected_n << ")" << std::endl; + + assert(res == expected_n); assert(is_valid(mesh)); std::cout << "OK\n"; @@ -140,32 +158,32 @@ int main() test_stitch_boundary_cycles("data_stitching/boundary_cycle.off", 4); test_stitch_boundary_cycles("data_stitching/boundary_cycle_2.off", 2); - test_polyhedron("data_stitching/full_border.off"); - test_polyhedron("data_stitching/full_border.off"); - test_polyhedron("data_stitching/full_border_quads.off"); - test_polyhedron("data_stitching/half_border.off"); - test_polyhedron("data_stitching/mid_border.off"); - test_polyhedron("data_stitching/multiple_incidence.off"); - test_polyhedron("data_stitching/incidence_3.off"); - test_polyhedron("data_stitching/incoherent_patch_orientation.off"); - test_polyhedron("data_stitching/non_stitchable.off"); - test_polyhedron("data_stitching/deg_border.off"); - test_polyhedron("data_stitching/two_patches.off"); - test_polyhedron("data_stitching/non_manifold.off"); - test_polyhedron("data_stitching/non_manifold2.off"); - test_polyhedron_cc("data_stitching/nm_cubes.off"); + test_polyhedron("data_stitching/deg_border.off", 2); + test_polyhedron("data_stitching/full_border.off", 4); + test_polyhedron("data_stitching/full_border.off", 4); + test_polyhedron("data_stitching/full_border_quads.off", 4); + test_polyhedron("data_stitching/half_border.off", 2); + test_polyhedron("data_stitching/incidence_3.off", 3); + test_polyhedron("data_stitching/incoherent_patch_orientation.off", 1); + test_polyhedron("data_stitching/mid_border.off", 2); + test_polyhedron("data_stitching/multiple_incidence.off", 10); + test_polyhedron("data_stitching/non_stitchable.off", 0); + test_polyhedron("data_stitching/non_manifold.off", 0); + test_polyhedron("data_stitching/non_manifold2.off", 0); + test_polyhedron("data_stitching/two_patches.off", 3); + test_polyhedron_cc("data_stitching/nm_cubes.off", 4); - test_surface_mesh("data_stitching/full_border.off"); - test_surface_mesh("data_stitching/full_border_quads.off"); - test_surface_mesh("data_stitching/half_border.off"); - test_surface_mesh("data_stitching/mid_border.off"); - test_surface_mesh("data_stitching/multiple_incidence.off"); - test_surface_mesh("data_stitching/incidence_3.off"); - test_surface_mesh("data_stitching/incoherent_patch_orientation.off"); - test_surface_mesh("data_stitching/non_stitchable.off"); - test_surface_mesh("data_stitching/deg_border.off"); - test_surface_mesh("data_stitching/non_manifold.off"); - test_surface_mesh_cc("data_stitching/nm_cubes.off"); + test_surface_mesh("data_stitching/deg_border.off", 2); + test_surface_mesh("data_stitching/full_border.off", 4); + test_surface_mesh("data_stitching/full_border_quads.off", 4); + test_surface_mesh("data_stitching/half_border.off", 2); + test_surface_mesh("data_stitching/incidence_3.off", 3); + test_surface_mesh("data_stitching/incoherent_patch_orientation.off", 1); + test_surface_mesh("data_stitching/mid_border.off", 2); + test_surface_mesh("data_stitching/multiple_incidence.off", 10); + test_surface_mesh("data_stitching/non_stitchable.off", 0); + test_surface_mesh("data_stitching/non_manifold.off", 0); + test_surface_mesh_cc("data_stitching/nm_cubes.off", 4); bug_test(); From afec55f37527dd82629052d49ea046e29a0aa04c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mael=20Rouxel-Labb=C3=A9?= Date: Wed, 21 Aug 2019 17:06:55 +0200 Subject: [PATCH 132/363] Rephrase end condition --- .../include/CGAL/Polygon_mesh_processing/stitch_borders.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/stitch_borders.h b/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/stitch_borders.h index 0bb871f7be9..966840e40fa 100644 --- a/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/stitch_borders.h +++ b/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/stitch_borders.h @@ -704,7 +704,7 @@ std::size_t stitch_boundary_cycle(const typename boost::graph_traits Date: Thu, 22 Aug 2019 09:06:02 +0200 Subject: [PATCH 133/363] Add const marker --- .../include/CGAL/Polygon_mesh_processing/stitch_borders.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/stitch_borders.h b/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/stitch_borders.h index 966840e40fa..06deb75540c 100644 --- a/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/stitch_borders.h +++ b/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/stitch_borders.h @@ -633,7 +633,7 @@ std::size_t stitch_boundary_cycle(const typename boost::graph_traits unstitchable_halfedges; - halfedge_descriptor null_h = boost::graph_traits::null_halfedge(); + const halfedge_descriptor null_h = boost::graph_traits::null_halfedge(); halfedge_descriptor bh = h; for(;;) // until there is nothing to stitch anymore { From e955c382154f31d7943b262077053809c15e3f7d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mael=20Rouxel-Labb=C3=A9?= Date: Thu, 22 Aug 2019 12:44:16 +0200 Subject: [PATCH 134/363] Add a new tag allowing constraints to intersect if no construction is required --- .../CGAL/Constrained_triangulation_2.h | 45 ++++++++++++++++++- .../CGAL/Constrained_triangulation_plus_2.h | 30 +++++++++---- 2 files changed, 64 insertions(+), 11 deletions(-) diff --git a/Triangulation_2/include/CGAL/Constrained_triangulation_2.h b/Triangulation_2/include/CGAL/Constrained_triangulation_2.h index 888154dd97d..b85b44e7810 100644 --- a/Triangulation_2/include/CGAL/Constrained_triangulation_2.h +++ b/Triangulation_2/include/CGAL/Constrained_triangulation_2.h @@ -48,6 +48,7 @@ namespace CGAL { struct No_intersection_tag{}; +struct No_intersection_requiring_constructions_tag{}; struct Exact_intersections_tag{}; // to be used with an exact number type struct Exact_predicates_tag{}; // to be used with filtered exact number @@ -113,7 +114,7 @@ public: { const char* what() const throw () { - return "Intersection of constraints while using No_intersection_tag"; + return "Unauthorized intersections of constraints"; } }; @@ -471,6 +472,10 @@ protected: Vertex_handle vaa, Vertex_handle vbb, No_intersection_tag); + Vertex_handle intersect(Face_handle f, int i, + Vertex_handle vaa, + Vertex_handle vbb, + No_intersection_requiring_constructions_tag); Vertex_handle intersect(Face_handle f, int i, Vertex_handle vaa, Vertex_handle vbb, @@ -912,7 +917,18 @@ intersect(Face_handle , int , Vertex_handle , No_intersection_tag) { + throw Intersection_of_constraints_exception(); + return Vertex_handle() ; +} +template +typename Constrained_triangulation_2::Vertex_handle +Constrained_triangulation_2:: +intersect(Face_handle , int , + Vertex_handle , + Vertex_handle , + No_intersection_requiring_constructions_tag) +{ throw Intersection_of_constraints_exception(); return Vertex_handle() ; } @@ -1459,7 +1475,20 @@ intersection(const Gt& , { return false; } - + +template +bool +intersection(const Gt& , + const typename Gt::Point_2& , + const typename Gt::Point_2& , + const typename Gt::Point_2& , + const typename Gt::Point_2& , + typename Gt::Point_2& , + No_intersection_requiring_constructions_tag) +{ + return false; +} + template bool intersection(const Gt& gt, @@ -1579,6 +1608,18 @@ limit_intersection(const Gt& , return 0; } +template +int +limit_intersection(const Gt& , + const typename Gt::Point_2& , + const typename Gt::Point_2& , + const typename Gt::Point_2& , + const typename Gt::Point_2& , + No_intersection_requiring_constructions_tag) +{ + return 0; +} + template int limit_intersection(const Gt& , diff --git a/Triangulation_2/include/CGAL/Constrained_triangulation_plus_2.h b/Triangulation_2/include/CGAL/Constrained_triangulation_plus_2.h index d2fda45e417..afa8873bc00 100644 --- a/Triangulation_2/include/CGAL/Constrained_triangulation_plus_2.h +++ b/Triangulation_2/include/CGAL/Constrained_triangulation_plus_2.h @@ -626,6 +626,10 @@ public: Vertex_handle vaa, Vertex_handle vbb, No_intersection_tag); + Vertex_handle intersect(Face_handle f, int i, + Vertex_handle vaa, + Vertex_handle vbb, + No_intersection_requiring_constructions_tag); Vertex_handle intersect(Face_handle f, int i, Vertex_handle vaa, Vertex_handle vbb, @@ -973,16 +977,24 @@ intersect(Face_handle f, int i, template typename Constrained_triangulation_plus_2:: Vertex_handle Constrained_triangulation_plus_2:: - -intersect(Face_handle , int , - Vertex_handle , - Vertex_handle , - No_intersection_tag) +intersect(Face_handle, int, + Vertex_handle, + Vertex_handle, + No_intersection_tag) { - std::cerr << " sorry, this triangulation does not deal with" - << std::endl - << " intersecting constraints" << std::endl; - CGAL_triangulation_assertion(false); + throw typename Tr::Intersection_of_constraints_exception(); + return Vertex_handle(); +} + +template +typename Constrained_triangulation_plus_2:: Vertex_handle +Constrained_triangulation_plus_2:: +intersect(Face_handle, int, + Vertex_handle, + Vertex_handle, + No_intersection_requiring_constructions_tag) +{ + throw typename Tr::Intersection_of_constraints_exception(); return Vertex_handle(); } From 197a29436c59a7cdc88feec4e41f0f989e1666d1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mael=20Rouxel-Labb=C3=A9?= Date: Thu, 22 Aug 2019 12:45:19 +0200 Subject: [PATCH 135/363] Test new tag --- .../_test_cls_constrained_triangulation_2.h | 72 ++++++++++++------- .../test_constrained_triangulation_2.cpp | 6 ++ 2 files changed, 53 insertions(+), 25 deletions(-) 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 bf1660f04cc..60d25f3fb0f 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 @@ -26,9 +26,16 @@ #include #include +enum Intersection_type { + NO_INTERSECTION = 0, + INTERSECTION_WITHOUT_CONSTRUCTION, + INTERSECTION +}; + template void -_test_cdt_throwing(const Pt& p0, const Pt& p1, const Pt& p2, const Pt& p3, const bool intersect) +_test_cdt_throwing(const Pt& p0, const Pt& p1, const Pt& p2, const Pt& p3, + const Intersection_type& intersection_type) { std::cout << "test_cdt_throwing [" << p0 << "] - [" << p1 << "] || [" << p2 << "] - [" << p3 << "]" << std::endl; @@ -40,14 +47,29 @@ _test_cdt_throwing(const Pt& p0, const Pt& p1, const Pt& p2, const Pt& p3, const } catch (typename Triang::Intersection_of_constraints_exception& e) { - std::cout << "threw, expected it? " << std::boolalpha << intersect << std::endl; - assert(intersect); - assert((boost::is_same::value)); + std::cout << "threw, expected: " << intersection_type << std::endl; + + // There must have been an intersection + assert(intersection_type != NO_INTERSECTION); + + // If the intersection requires no construction, then only 'no_intersection_tag' throws + if(intersection_type == INTERSECTION_WITHOUT_CONSTRUCTION) { + assert((boost::is_same::value)); + } else { + assert(intersection_type == INTERSECTION); + assert((boost::is_same::value) || + (boost::is_same::value)); + } + return; } - if(intersect) { + if(intersection_type == INTERSECTION_WITHOUT_CONSTRUCTION) { + // Even with an intersection without construction, 'No_intersection_tag' should throw assert(!(boost::is_same::value)); + } else if(intersection_type == INTERSECTION) { + assert(!(boost::is_same::value) && + !(boost::is_same::value)); } } @@ -318,26 +340,26 @@ _test_cls_constrained_triangulation(const Triang &) assert(std::distance(T2_6.constrained_edges_begin(), T2_6.constrained_edges_end()) == 1); // test throwing/not throwing on intersecting constraints - _test_cdt_throwing(Point(0, 0), Point(1, 1), Point(2, 2), Point(2, 3), false /*no intersection*/); - _test_cdt_throwing(Point(0, 0), Point(1, 1), Point(1, 1), Point(2, 2), false); // common point - _test_cdt_throwing(Point(2, 2), Point(0, 0), Point(2, 2), Point(3, 3), false); // ^ - _test_cdt_throwing(Point(0, 0), Point(2, 2), Point(1, 1), Point(3, 3), true); // overlapping - _test_cdt_throwing(Point(2, 2), Point(0, 0), Point(1, 1), Point(3, 3), true); // ^ - _test_cdt_throwing(Point(2, 2), Point(0, 0), Point(0, 0), Point(3, 3), true); // ^ - _test_cdt_throwing(Point(2, 2), Point(0, 0), Point(3, 3), Point(0, 0), true); // ^ - _test_cdt_throwing(Point(0, 0), Point(3, 3), Point(1, 1), Point(2, 2), true); // contains - _test_cdt_throwing(Point(3, 3), Point(0, 0), Point(1, 1), Point(2, 2), true); // ^ - _test_cdt_throwing(Point(1, 1), Point(2, 2), Point(3, 3), Point(0, 0), true); // ^ - _test_cdt_throwing(Point(2, 2), Point(1, 1), Point(3, 3), Point(0, 0), true); // ^ - _test_cdt_throwing(Point(3, 3), Point(0, 0), Point(0, 0), Point(3, 3), true); // same constraint - _test_cdt_throwing(Point(3, 3), Point(0, 0), Point(1, 1), Point(1, 1), true); // degenerate entry - _test_cdt_throwing(Point(0, 0), Point(0, 0), Point(0, 0), Point(0, 0), false); // degenerate same entry - - // non aligned - _test_cdt_throwing(Point(0, 0), Point(3, 3), Point(1, 0), Point(4, 0), false); - _test_cdt_throwing(Point(0, 2), Point(2, 2), Point(1, 0), Point(1, 3), true); // generic intersection - _test_cdt_throwing(Point(0, 0), Point(2, 2), Point(1, 3), Point(1, 0), true); + _test_cdt_throwing(Point(0, 0), Point(1, 1), Point(2, 2), Point(2, 3), NO_INTERSECTION); + _test_cdt_throwing(Point(0, 0), Point(1, 1), Point(1, 1), Point(2, 2), NO_INTERSECTION); // common point + _test_cdt_throwing(Point(2, 2), Point(0, 0), Point(2, 2), Point(3, 3), NO_INTERSECTION); // ^ + _test_cdt_throwing(Point(0, 0), Point(2, 2), Point(1, 1), Point(3, 3), INTERSECTION_WITHOUT_CONSTRUCTION); // overlapping + _test_cdt_throwing(Point(2, 2), Point(0, 0), Point(1, 1), Point(3, 3), INTERSECTION_WITHOUT_CONSTRUCTION); // ^ + _test_cdt_throwing(Point(2, 2), Point(0, 0), Point(0, 0), Point(3, 3), INTERSECTION_WITHOUT_CONSTRUCTION); // ^ + _test_cdt_throwing(Point(2, 2), Point(0, 0), Point(3, 3), Point(0, 0), INTERSECTION_WITHOUT_CONSTRUCTION); // ^ + _test_cdt_throwing(Point(0, 0), Point(3, 3), Point(1, 1), Point(2, 2), INTERSECTION_WITHOUT_CONSTRUCTION); // contains + _test_cdt_throwing(Point(3, 3), Point(0, 0), Point(1, 1), Point(2, 2), INTERSECTION_WITHOUT_CONSTRUCTION); // ^ + _test_cdt_throwing(Point(1, 1), Point(2, 2), Point(3, 3), Point(0, 0), INTERSECTION_WITHOUT_CONSTRUCTION); // ^ + _test_cdt_throwing(Point(2, 2), Point(1, 1), Point(3, 3), Point(0, 0), INTERSECTION_WITHOUT_CONSTRUCTION); // ^ + _test_cdt_throwing(Point(3, 3), Point(0, 0), Point(0, 0), Point(3, 3), INTERSECTION_WITHOUT_CONSTRUCTION); // same constraint + _test_cdt_throwing(Point(3, 3), Point(0, 0), Point(1, 1), Point(1, 1), INTERSECTION_WITHOUT_CONSTRUCTION); // degenerate entry + _test_cdt_throwing(Point(0, 0), Point(0, 0), Point(0, 0), Point(0, 0), NO_INTERSECTION); // degenerate same entry // extremity on the interior of another segment - _test_cdt_throwing(Point(0, 0), Point(2, 0), Point(1, 0), Point(1, 4), true); + _test_cdt_throwing(Point(0, 0), Point(2, 0), Point(1, 0), Point(1, 4), INTERSECTION_WITHOUT_CONSTRUCTION); + + // non aligned + _test_cdt_throwing(Point(0, 0), Point(3, 3), Point(1, 0), Point(4, 0), NO_INTERSECTION); + _test_cdt_throwing(Point(0, 2), Point(2, 2), Point(1, 0), Point(1, 3), INTERSECTION); // generic intersection + _test_cdt_throwing(Point(0, 0), Point(2, 2), Point(1, 3), Point(1, 0), INTERSECTION); } diff --git a/Triangulation_2/test/Triangulation_2/test_constrained_triangulation_2.cpp b/Triangulation_2/test/Triangulation_2/test_constrained_triangulation_2.cpp index 16be9b3eec3..158700b383d 100644 --- a/Triangulation_2/test/Triangulation_2/test_constrained_triangulation_2.cpp +++ b/Triangulation_2/test/Triangulation_2/test_constrained_triangulation_2.cpp @@ -39,6 +39,12 @@ int main() typedef CGAL::Constrained_triangulation_2 Ct; _test_cls_constrained_triangulation(Ct()); + std::cout << "Testing constrained_triangulation "<< std::endl; + std::cout << " with No_intersection_requiring_constructions_tag : " << std::endl; + typedef CGAL::No_intersection_requiring_constructions_tag CItag; + typedef CGAL::Constrained_triangulation_2 Ctwoc; + _test_cls_constrained_triangulation(Ctwoc()); + std::cout << "Testing constrained_triangulation "<< std::endl; std::cout << " with Exact_predicates_tag : " << std::endl; typedef CGAL::Triangulation_vertex_base_2 Vb; From 6d2ebc7a6edd7053a73f49b3e90d52c6a6dd2c2b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mael=20Rouxel-Labb=C3=A9?= Date: Thu, 22 Aug 2019 13:14:45 +0200 Subject: [PATCH 136/363] Minor doc changes --- .../include/CGAL/Polygon_mesh_processing/stitch_borders.h | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/stitch_borders.h b/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/stitch_borders.h index 06deb75540c..8a5170f3e35 100644 --- a/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/stitch_borders.h +++ b/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/stitch_borders.h @@ -808,6 +808,9 @@ std::size_t stitch_boundary_cycles(PolygonMesh& pm) } ///\cond SKIP_IN_MANUAL +// The VPM is only used here for debugging info purposes as in this overload, the halfedges +// to stitch are already provided and all further checks are combinatorial and not geometrical. +// There is thus nothing interesting to pass via named parameters and this overload is not documented. template @@ -843,6 +846,8 @@ std::size_t stitch_borders(PolygonMesh& pmesh, * @param pmesh the polygon mesh to be modified by stitching * @param hedge_pairs_to_stitch a range of `std::pair` of halfedges to be stitched together * +* @return the number of pairs of halfedges that were stitched. +* */ template @@ -878,7 +883,7 @@ std::size_t stitch_borders(PolygonMesh& pmesh, /// \cgalParamBegin{face_index_map} a property map containing the index of each face of `pmesh` \cgalParamEnd /// \cgalNamedParamsEnd /// -/// @return the number of pairs of halfedges that were stitched +/// @return the number of pairs of halfedges that were stitched. /// /// @sa `stitch_boundary_cycle()` /// @sa `stitch_boundary_cycles()` From 64cd7b67c25d76ac66dac634bd2dcc13010734eb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9bastien=20Loriot?= Date: Thu, 5 Sep 2019 11:26:12 +0200 Subject: [PATCH 137/363] hide debug --- .../remove_degeneracies.h | 25 ++++++++++++++++--- 1 file changed, 22 insertions(+), 3 deletions(-) diff --git a/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/remove_degeneracies.h b/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/remove_degeneracies.h index be56521054b..4d72c56c793 100644 --- a/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/remove_degeneracies.h +++ b/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/remove_degeneracies.h @@ -32,9 +32,11 @@ #include #include -#include // @tmp #include -#include // @tmp +#ifdef CGAL_PMP_DEBUG_REMOVE_DEGENERACIES +#include +#include +#endif namespace CGAL { namespace Polygon_mesh_processing { @@ -74,7 +76,9 @@ void add_if_badly_shaped(const typename boost::graph_traits::face_ halfedge_descriptor res = CGAL::Polygon_mesh_processing::is_needle_triangle_face(f, tmesh, needle_threshold, np); if(res != boost::graph_traits::null_halfedge()) { +#ifdef CGAL_PMP_DEBUG_REMOVE_DEGENERACIES std::cout << "add new needle: " << res << std::endl; +#endif edges_to_collapse.insert(edge(res, tmesh)); } else // let's not make it possible to have a face be both a cap and a needle fo(for now) @@ -82,7 +86,9 @@ void add_if_badly_shaped(const typename boost::graph_traits::face_ res = CGAL::Polygon_mesh_processing::is_cap_triangle_face(f, tmesh, cap_threshold, np); if(res != boost::graph_traits::null_halfedge()) { +#ifdef CGAL_PMP_DEBUG_REMOVE_DEGENERACIES std::cout << "add new cap: " << res << std::endl; +#endif edges_to_flip.insert(edge(res, tmesh)); } } @@ -108,17 +114,20 @@ bool remove_almost_degenerate_faces(const FaceRange& face_range, for(face_descriptor f : face_range) internal::add_if_badly_shaped(f, tmesh, edges_to_collapse, edges_to_flip, np); +#ifdef CGAL_PMP_DEBUG_REMOVE_DEGENERACIES int iter = 0; +#endif for(;;) { +#ifdef CGAL_PMP_DEBUG_REMOVE_DEGENERACIES std::cout << edges_to_collapse.size() << " needles and " << edges_to_flip.size() << " caps" << std::endl; - std::ostringstream oss; oss << "degen_cleaning_iter_" << iter++ << ".off"; std::ofstream out(oss.str().c_str()); out << std::setprecision(17); out << tmesh; out.close(); +#endif if(edges_to_collapse.empty() && edges_to_flip.empty()) return true; @@ -129,7 +138,9 @@ bool remove_almost_degenerate_faces(const FaceRange& face_range, // treat needles for(edge_descriptor e : edges_to_collapse) { +#ifdef CGAL_PMP_DEBUG_REMOVE_DEGENERACIES std::cout << "treat needle: " << e << " (" << tmesh.point(source (e, tmesh)) << " --- " << tmesh.point(target(e, tmesh)) << ")" << std::endl; +#endif if(CGAL::Euler::does_satisfy_link_condition(e, tmesh)) { CGAL_assertion(!is_border(e, tmesh)); @@ -168,24 +179,30 @@ bool remove_almost_degenerate_faces(const FaceRange& face_range, internal::add_if_badly_shaped(face(inc_h, tmesh), tmesh, next_edges_to_collapse, edges_to_flip, np); } } +#ifdef CGAL_PMP_DEBUG_REMOVE_DEGENERACIES else { std::cerr << "Warning: uncollapsable edge! " << tmesh.point(source(e, tmesh)) << " --- " << tmesh.point(target(e, tmesh)) << std::endl; } +#endif } // treat caps for(edge_descriptor e : edges_to_flip) { +#ifdef CGAL_PMP_DEBUG_REMOVE_DEGENERACIES std::cout << "treat cap: " << e << " (" << tmesh.point(source (e, tmesh)) << " --- " << tmesh.point(target(e, tmesh)) << ")" << std::endl; +#endif halfedge_descriptor h = halfedge(e, tmesh); // condition for the flip to be valid (the edge to be created does not already exist) if(!halfedge(target(next(h, tmesh), tmesh), target(next(opposite(h, tmesh), tmesh), tmesh), tmesh).second) { +#ifdef CGAL_PMP_DEBUG_REMOVE_DEGENERACIES std::cout << "Flippin!" << std::endl; +#endif Euler::flip_edge(h, tmesh); // commented code below is not needed as long as you can't have both needle & caps but might become relevant later @@ -202,11 +219,13 @@ bool remove_almost_degenerate_faces(const FaceRange& face_range, // internal::add_if_badly_shaped(face(opposite(prev(opposite(h, tmesh), tmesh), tmesh), tmesh), tmesh, next_edges_to_collapse, next_edges_to_flip, np); // internal::add_if_badly_shaped(face(opposite(next(opposite(h, tmesh), tmesh), tmesh), tmesh), tmesh, next_edges_to_collapse, next_edges_to_flip, np); } +#ifdef CGAL_PMP_DEBUG_REMOVE_DEGENERACIES else { std::cerr << "Warning: unflippable edge! " << tmesh.point(source(h, tmesh)) << " --- " << tmesh.point(target(h, tmesh)) << std::endl; } +#endif } std::swap(edges_to_collapse, next_edges_to_collapse); From acb8b8ffa2f9f5abe95e4cefe7f07edbef40f1d2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9bastien=20Loriot?= Date: Fri, 6 Sep 2019 10:35:29 +0200 Subject: [PATCH 138/363] split the function checking for needles and caps and use it to avoid inifinite flipping loops --- .../clean_degeneracies.cpp | 3 + .../remove_degeneracies.h | 152 +++++++++++------- 2 files changed, 95 insertions(+), 60 deletions(-) diff --git a/Polygon_mesh_processing/examples/Polygon_mesh_processing/clean_degeneracies.cpp b/Polygon_mesh_processing/examples/Polygon_mesh_processing/clean_degeneracies.cpp index ce7e30acd0b..8d9e366b6e4 100644 --- a/Polygon_mesh_processing/examples/Polygon_mesh_processing/clean_degeneracies.cpp +++ b/Polygon_mesh_processing/examples/Polygon_mesh_processing/clean_degeneracies.cpp @@ -29,5 +29,8 @@ int main(int argc, char** argv) PMP::remove_almost_degenerate_faces(mesh); + std::ofstream out("cleaned_mesh.off"); + out << std::setprecision(17) << mesh; + return 0; } diff --git a/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/remove_degeneracies.h b/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/remove_degeneracies.h index 4d72c56c793..47bf83d54a0 100644 --- a/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/remove_degeneracies.h +++ b/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/remove_degeneracies.h @@ -57,6 +57,35 @@ bool is_face_incident_to_border(const typename boost::graph_traits return false; } +template +std::array::halfedge_descriptor, 2> +is_badly_shaped(const typename boost::graph_traits::face_descriptor f, + TriangleMesh& tmesh, + const NamedParameters& np) +{ + typedef typename boost::graph_traits::halfedge_descriptor halfedge_descriptor; + halfedge_descriptor null_halfedge = boost::graph_traits::null_halfedge(); + + // @todo parameters + const double needle_threshold = 4; // longest edge / shortest edge over this ratio ==> needle + const double cap_threshold = std::cos(160. / 180 * CGAL_PI); // angle over 120° ==> cap + + halfedge_descriptor res = CGAL::Polygon_mesh_processing::is_needle_triangle_face(f, tmesh, needle_threshold, np); + if(res != boost::graph_traits::null_halfedge()) + { + return make_array(res, null_halfedge); + } + else // let's not make it possible to have a face be both a cap and a needle (for now) + { + res = CGAL::Polygon_mesh_processing::is_cap_triangle_face(f, tmesh, cap_threshold, np); + if(res != boost::graph_traits::null_halfedge()) + { + return make_array(null_halfedge, res); + } + } + return make_array(null_halfedge, null_halfedge); +} + template void add_if_badly_shaped(const typename boost::graph_traits::face_descriptor f, TriangleMesh& tmesh, @@ -66,30 +95,23 @@ void add_if_badly_shaped(const typename boost::graph_traits::face_ { typedef typename boost::graph_traits::halfedge_descriptor halfedge_descriptor; - // @todo parameters - const double needle_threshold = 4; // longest edge / shortest edge over this ratio ==> needle - const double cap_threshold = std::cos(160. / 180 * CGAL_PI); // angle over 120° ==> cap + std::array res = is_badly_shaped(f, tmesh, np); - if(is_face_incident_to_border(f, tmesh)) - return; - - halfedge_descriptor res = CGAL::Polygon_mesh_processing::is_needle_triangle_face(f, tmesh, needle_threshold, np); - if(res != boost::graph_traits::null_halfedge()) + if(res[0] != boost::graph_traits::null_halfedge()) { #ifdef CGAL_PMP_DEBUG_REMOVE_DEGENERACIES std::cout << "add new needle: " << res << std::endl; #endif - edges_to_collapse.insert(edge(res, tmesh)); + edges_to_collapse.insert(edge(res[0], tmesh)); } - else // let's not make it possible to have a face be both a cap and a needle fo(for now) + else // let's not make it possible to have a face be both a cap and a needle (for now) { - res = CGAL::Polygon_mesh_processing::is_cap_triangle_face(f, tmesh, cap_threshold, np); - if(res != boost::graph_traits::null_halfedge()) + if(res[1] != boost::graph_traits::null_halfedge()) { #ifdef CGAL_PMP_DEBUG_REMOVE_DEGENERACIES std::cout << "add new cap: " << res << std::endl; #endif - edges_to_flip.insert(edge(res, tmesh)); + edges_to_flip.insert(edge(res[1], tmesh)); } } } @@ -101,7 +123,7 @@ bool remove_almost_degenerate_faces(const FaceRange& face_range, TriangleMesh& tmesh, const NamedParameters& np) { - typedef typename boost::graph_traits::vertex_descriptor vertex_descriptor; +// typedef typename boost::graph_traits::vertex_descriptor vertex_descriptor; typedef typename boost::graph_traits::halfedge_descriptor halfedge_descriptor; typedef typename boost::graph_traits::edge_descriptor edge_descriptor; typedef typename boost::graph_traits::face_descriptor face_descriptor; @@ -143,41 +165,24 @@ bool remove_almost_degenerate_faces(const FaceRange& face_range, #endif if(CGAL::Euler::does_satisfy_link_condition(e, tmesh)) { - CGAL_assertion(!is_border(e, tmesh)); - - vertex_descriptor v = Euler::collapse_edge(e, tmesh); // @todo move 'v' to the midpoint? - + // the following edges are removed by the collapse + halfedge_descriptor h = halfedge(e, tmesh); + if (!is_border(h, tmesh)) + { + edge_descriptor pe=edge(prev(h,tmesh), tmesh); + edges_to_flip.erase(pe); + edges_to_collapse.erase(pe); + } + h = opposite(h, tmesh); + if (!is_border(h, tmesh)) + { + edge_descriptor pe=edge(prev(h,tmesh), tmesh); + edges_to_flip.erase(pe); + edges_to_collapse.erase(pe); + } edges_to_flip.erase(e); - // the following edges are removed by the collapse - edge_descriptor pe = edge(prev(halfedge(e, tmesh), tmesh), tmesh); - edge_descriptor poe = edge(prev(opposite(halfedge(e, tmesh), tmesh), tmesh), tmesh); - - edges_to_collapse.erase(pe); - edges_to_collapse.erase(poe); - edges_to_flip.erase(pe); - edges_to_flip.erase(poe); - - // The geometry of all the faces incident to 'v' has changed and so we recompute their badness - // @fixme nasty complexity, use tags or something... - for(halfedge_descriptor inc_h : CGAL::halfedges_around_target(v, tmesh)) - { - if(is_border_edge(inc_h, tmesh)) - continue; - - // since the 'bad' edge of a face incident to 'v' might not be an incident edge - for(halfedge_descriptor other_h : CGAL::halfedges_around_face(inc_h, tmesh)) - { - edge_descriptor other_e = edge(other_h, tmesh); - - if(other_e != e) // erasing the current position while looping is undefined behavior - edges_to_collapse.erase(other_e); - edges_to_flip.erase(other_e); - } - - // adding directly to 'edges_to_flip' because we're treating caps next - internal::add_if_badly_shaped(face(inc_h, tmesh), tmesh, next_edges_to_collapse, edges_to_flip, np); - } + /* vertex_descriptor v = */ Euler::collapse_edge(e, tmesh); // @todo move 'v' to the midpoint? } #ifdef CGAL_PMP_DEBUG_REMOVE_DEGENERACIES else @@ -194,6 +199,20 @@ bool remove_almost_degenerate_faces(const FaceRange& face_range, #ifdef CGAL_PMP_DEBUG_REMOVE_DEGENERACIES std::cout << "treat cap: " << e << " (" << tmesh.point(source (e, tmesh)) << " --- " << tmesh.point(target(e, tmesh)) << ")" << std::endl; #endif + + // special case on the border + if ( is_border(e, tmesh) ) + { + // remove the triangle + halfedge_descriptor h = halfedge(e, tmesh); + if (is_border(h, tmesh)) + h = opposite(h, tmesh); + edges_to_flip.erase(edge(prev(h, tmesh), tmesh)); + edges_to_flip.erase(edge(next(h, tmesh), tmesh)); + Euler::remove_face(h, tmesh); + continue; + } + halfedge_descriptor h = halfedge(e, tmesh); // condition for the flip to be valid (the edge to be created does not already exist) @@ -201,23 +220,36 @@ bool remove_almost_degenerate_faces(const FaceRange& face_range, target(next(opposite(h, tmesh), tmesh), tmesh), tmesh).second) { #ifdef CGAL_PMP_DEBUG_REMOVE_DEGENERACIES - std::cout << "Flippin!" << std::endl; + std::cout << "Flipping" << std::endl; #endif Euler::flip_edge(h, tmesh); - // commented code below is not needed as long as you can't have both needle & caps but might become relevant later -// edges_to_flip.erase(edge(prev(h, tmesh), tmesh)); -// edges_to_flip.erase(edge(next(h, tmesh), tmesh)); -// edges_to_flip.erase(edge(prev(opposite(h, tmesh), tmesh), tmesh)); -// edges_to_flip.erase(edge(next(opposite(h, tmesh), tmesh), tmesh)); + // remove edges from the new faces + edges_to_flip.erase(edge(prev(h, tmesh), tmesh)); + edges_to_flip.erase(edge(next(h, tmesh), tmesh)); + edges_to_flip.erase(edge(prev(opposite(h, tmesh), tmesh), tmesh)); + edges_to_flip.erase(edge(next(opposite(h, tmesh), tmesh), tmesh)); - internal::add_if_badly_shaped(face(h, tmesh), tmesh, next_edges_to_collapse, next_edges_to_flip, np); - internal::add_if_badly_shaped(face(opposite(h, tmesh), tmesh), tmesh, next_edges_to_collapse, next_edges_to_flip, np); - -// internal::add_if_badly_shaped(face(opposite(prev(h, tmesh), tmesh), tmesh), tmesh, next_edges_to_collapse, next_edges_to_flip, np); -// internal::add_if_badly_shaped(face(opposite(next(h, tmesh), tmesh), tmesh), tmesh, next_edges_to_collapse, next_edges_to_flip, np); -// internal::add_if_badly_shaped(face(opposite(prev(opposite(h, tmesh), tmesh), tmesh), tmesh), tmesh, next_edges_to_collapse, next_edges_to_flip, np); -// internal::add_if_badly_shaped(face(opposite(next(opposite(h, tmesh), tmesh), tmesh), tmesh), tmesh, next_edges_to_collapse, next_edges_to_flip, np); + // make sure we do not enter in an infinite loop + if (!is_border(h, tmesh)) + { + std::array hp = internal::is_badly_shaped(face(h, tmesh), tmesh, np); + if (hp[1]!=boost::graph_traits::null_halfedge() && + edge(hp[1], tmesh) != edge(h, tmesh)) // avoid infinite loop + { + next_edges_to_flip.insert( edge(hp[1], tmesh) ); + } + } + h=opposite(h, tmesh); + if (!is_border(h, tmesh)) + { + std::array hp = internal::is_badly_shaped(face(h, tmesh), tmesh, np); + if (hp[1]!=boost::graph_traits::null_halfedge() && + edge(hp[1], tmesh) != edge(h, tmesh)) // avoid infinite loop + { + next_edges_to_flip.insert( edge(hp[1], tmesh) ); + } + } } #ifdef CGAL_PMP_DEBUG_REMOVE_DEGENERACIES else From ee537eb89ca058f025ee54729df1a0a8a5841c80 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9bastien=20Loriot?= Date: Fri, 6 Sep 2019 11:41:19 +0200 Subject: [PATCH 139/363] do not iterate on a container if we remove elements from it --- .../remove_degeneracies.h | 85 ++++++++++++------- 1 file changed, 52 insertions(+), 33 deletions(-) diff --git a/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/remove_degeneracies.h b/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/remove_degeneracies.h index 47bf83d54a0..a7406deea3c 100644 --- a/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/remove_degeneracies.h +++ b/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/remove_degeneracies.h @@ -100,7 +100,7 @@ void add_if_badly_shaped(const typename boost::graph_traits::face_ if(res[0] != boost::graph_traits::null_halfedge()) { #ifdef CGAL_PMP_DEBUG_REMOVE_DEGENERACIES - std::cout << "add new needle: " << res << std::endl; + std::cout << "add new needle: " << res[0] << std::endl; #endif edges_to_collapse.insert(edge(res[0], tmesh)); } @@ -109,7 +109,7 @@ void add_if_badly_shaped(const typename boost::graph_traits::face_ if(res[1] != boost::graph_traits::null_halfedge()) { #ifdef CGAL_PMP_DEBUG_REMOVE_DEGENERACIES - std::cout << "add new cap: " << res << std::endl; + std::cout << "add new cap: " << res[1] << std::endl; #endif edges_to_flip.insert(edge(res[1], tmesh)); } @@ -118,6 +118,7 @@ void add_if_badly_shaped(const typename boost::graph_traits::face_ } // namespace internal +// @todo check what to use as priority queue with removable elements, set might not be optimal template bool remove_almost_degenerate_faces(const FaceRange& face_range, TriangleMesh& tmesh, @@ -141,6 +142,8 @@ bool remove_almost_degenerate_faces(const FaceRange& face_range, #endif for(;;) { + bool something_was_done = false; + #ifdef CGAL_PMP_DEBUG_REMOVE_DEGENERACIES std::cout << edges_to_collapse.size() << " needles and " << edges_to_flip.size() << " caps" << std::endl; std::ostringstream oss; @@ -158,8 +161,11 @@ bool remove_almost_degenerate_faces(const FaceRange& face_range, std::set next_edges_to_flip; // treat needles - for(edge_descriptor e : edges_to_collapse) + while (!edges_to_collapse.empty()) { + edge_descriptor e = *edges_to_collapse.begin(); + edges_to_collapse.erase(edges_to_collapse.begin()); + #ifdef CGAL_PMP_DEBUG_REMOVE_DEGENERACIES std::cout << "treat needle: " << e << " (" << tmesh.point(source (e, tmesh)) << " --- " << tmesh.point(target(e, tmesh)) << ")" << std::endl; #endif @@ -167,35 +173,40 @@ bool remove_almost_degenerate_faces(const FaceRange& face_range, { // the following edges are removed by the collapse halfedge_descriptor h = halfedge(e, tmesh); - if (!is_border(h, tmesh)) + for (int i=0; i<2; ++i) { - edge_descriptor pe=edge(prev(h,tmesh), tmesh); - edges_to_flip.erase(pe); - edges_to_collapse.erase(pe); - } - h = opposite(h, tmesh); - if (!is_border(h, tmesh)) - { - edge_descriptor pe=edge(prev(h,tmesh), tmesh); - edges_to_flip.erase(pe); - edges_to_collapse.erase(pe); + if (!is_border(h, tmesh)) + { + edge_descriptor pe=edge(prev(h,tmesh), tmesh); + edges_to_flip.erase(pe); + next_edges_to_collapse.erase(pe); + edges_to_collapse.erase(pe); + } + h = opposite(h, tmesh); } edges_to_flip.erase(e); /* vertex_descriptor v = */ Euler::collapse_edge(e, tmesh); // @todo move 'v' to the midpoint? + // @todo the collapsed edge is supposed to be smalled so incident faces are not reevaluated but + // maybe we should + something_was_done = true; } -#ifdef CGAL_PMP_DEBUG_REMOVE_DEGENERACIES else { +#ifdef CGAL_PMP_DEBUG_REMOVE_DEGENERACIES std::cerr << "Warning: uncollapsable edge! " << tmesh.point(source(e, tmesh)) << " --- " << tmesh.point(target(e, tmesh)) << std::endl; - } #endif + next_edges_to_collapse.insert(e); + } } // treat caps - for(edge_descriptor e : edges_to_flip) + while (!edges_to_flip.empty()) { + edge_descriptor e = *edges_to_flip.begin(); + edges_to_flip.erase(edges_to_flip.begin()); + #ifdef CGAL_PMP_DEBUG_REMOVE_DEGENERACIES std::cout << "treat cap: " << e << " (" << tmesh.point(source (e, tmesh)) << " --- " << tmesh.point(target(e, tmesh)) << ")" << std::endl; #endif @@ -210,6 +221,7 @@ bool remove_almost_degenerate_faces(const FaceRange& face_range, edges_to_flip.erase(edge(prev(h, tmesh), tmesh)); edges_to_flip.erase(edge(next(h, tmesh), tmesh)); Euler::remove_face(h, tmesh); + something_was_done = true; continue; } @@ -223,6 +235,8 @@ bool remove_almost_degenerate_faces(const FaceRange& face_range, std::cout << "Flipping" << std::endl; #endif Euler::flip_edge(h, tmesh); + CGAL_assertion( edge(h, tmesh) == e ); + something_was_done = true; // remove edges from the new faces edges_to_flip.erase(edge(prev(h, tmesh), tmesh)); @@ -230,25 +244,27 @@ bool remove_almost_degenerate_faces(const FaceRange& face_range, edges_to_flip.erase(edge(prev(opposite(h, tmesh), tmesh), tmesh)); edges_to_flip.erase(edge(next(opposite(h, tmesh), tmesh), tmesh)); - // make sure we do not enter in an infinite loop - if (!is_border(h, tmesh)) + // handle face updates + for (int i=0; i<2; ++i) { - std::array hp = internal::is_badly_shaped(face(h, tmesh), tmesh, np); - if (hp[1]!=boost::graph_traits::null_halfedge() && - edge(hp[1], tmesh) != edge(h, tmesh)) // avoid infinite loop + if (!is_border(h, tmesh)) { - next_edges_to_flip.insert( edge(hp[1], tmesh) ); - } - } - h=opposite(h, tmesh); - if (!is_border(h, tmesh)) - { - std::array hp = internal::is_badly_shaped(face(h, tmesh), tmesh, np); - if (hp[1]!=boost::graph_traits::null_halfedge() && - edge(hp[1], tmesh) != edge(h, tmesh)) // avoid infinite loop - { - next_edges_to_flip.insert( edge(hp[1], tmesh) ); + std::array hp = internal::is_badly_shaped(face(h, tmesh), tmesh, np); + if (hp[1]!=boost::graph_traits::null_halfedge() && + edge(hp[1], tmesh) != e) // avoid infinite loop + { + next_edges_to_flip.insert( edge(hp[1], tmesh) ); + } + else + { + if (hp[0]!=boost::graph_traits::null_halfedge() && + edge(hp[0], tmesh) == e) // only the new edge should be tested + { + next_edges_to_collapse.insert(e); + } + } } + h=opposite(h, tmesh); } } #ifdef CGAL_PMP_DEBUG_REMOVE_DEGENERACIES @@ -262,6 +278,9 @@ bool remove_almost_degenerate_faces(const FaceRange& face_range, std::swap(edges_to_collapse, next_edges_to_collapse); std::swap(edges_to_flip, next_edges_to_flip); + + if (!something_was_done) + return false; } return false; From 89c1c4b3e842dad6b5d6baa51142c1222e466000 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9bastien=20Loriot?= Date: Fri, 6 Sep 2019 15:35:03 +0200 Subject: [PATCH 140/363] check if the edge to be collapsed still verify the needle criteria --- .../remove_degeneracies.h | 33 +++++++++++++++---- 1 file changed, 26 insertions(+), 7 deletions(-) diff --git a/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/remove_degeneracies.h b/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/remove_degeneracies.h index a7406deea3c..02137227c99 100644 --- a/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/remove_degeneracies.h +++ b/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/remove_degeneracies.h @@ -173,6 +173,20 @@ bool remove_almost_degenerate_faces(const FaceRange& face_range, { // the following edges are removed by the collapse halfedge_descriptor h = halfedge(e, tmesh); + CGAL_assertion(!is_border(h, tmesh)); + + std::array nc = internal::is_badly_shaped(face(h, tmesh), tmesh, np); + if (nc[0]!=h) + { +#ifdef CGAL_PMP_DEBUG_REMOVE_DEGENERACIES + std::cerr << "Warning: Needle criteria no longer valid " << tmesh.point(source(e, tmesh)) << " --- " + << tmesh.point(target(e, tmesh)) << std::endl; +#endif + if (nc[0]!=boost::graph_traits::null_halfedge()) + next_edges_to_collapse.insert(edge(nc[0], tmesh)); + continue; + } + for (int i=0; i<2; ++i) { if (!is_border(h, tmesh)) @@ -186,7 +200,12 @@ bool remove_almost_degenerate_faces(const FaceRange& face_range, } edges_to_flip.erase(e); - /* vertex_descriptor v = */ Euler::collapse_edge(e, tmesh); // @todo move 'v' to the midpoint? + // moving to the midpoint is not a good idea. On a circle for example you might endpoint with + // a bad geometry because you iteratively move one point + // auto mp = midpoint(tmesh.point(source(h, tmesh)), tmesh.point(target(h, tmesh))); + + /* vertex_descriptor v = */ Euler::collapse_edge(e, tmesh); + //tmesh.point(v) = mp; // @todo the collapsed edge is supposed to be smalled so incident faces are not reevaluated but // maybe we should something_was_done = true; @@ -249,16 +268,16 @@ bool remove_almost_degenerate_faces(const FaceRange& face_range, { if (!is_border(h, tmesh)) { - std::array hp = internal::is_badly_shaped(face(h, tmesh), tmesh, np); - if (hp[1]!=boost::graph_traits::null_halfedge() && - edge(hp[1], tmesh) != e) // avoid infinite loop + std::array nc = internal::is_badly_shaped(face(h, tmesh), tmesh, np); + if (nc[1]!=boost::graph_traits::null_halfedge() && + edge(nc[1], tmesh) != e) // avoid infinite loop { - next_edges_to_flip.insert( edge(hp[1], tmesh) ); + next_edges_to_flip.insert( edge(nc[1], tmesh) ); } else { - if (hp[0]!=boost::graph_traits::null_halfedge() && - edge(hp[0], tmesh) == e) // only the new edge should be tested + if (nc[0]!=boost::graph_traits::null_halfedge() && + edge(nc[0], tmesh) == e) // only the new edge should be tested { next_edges_to_collapse.insert(e); } From b1df25dcf61f09fe20f19b9451a466614a23c2e7 Mon Sep 17 00:00:00 2001 From: Laurent Rineau Date: Mon, 9 Sep 2019 15:44:05 +0200 Subject: [PATCH 141/363] Remove the useless point_ data member --- .../internal/Polyline_constraint_hierarchy_2.h | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) 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 e468fa4d9de..c901bad3fb8 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 @@ -52,14 +52,12 @@ private: class Node { public: explicit Node(Vertex_handle vh, bool input = false) - : vertex_(vh), point_(vh->point()), id(-1), input(input) + : vertex_(vh), id(-1), input(input) {} - Point& point() { return point_; } - const Point& point() const { return point_; } + const Point& point() const { return vertex_->point(); } Vertex_handle vertex() const { return vertex_; } private: Vertex_handle vertex_; - Point point_; public: int id; bool input; @@ -74,7 +72,7 @@ public: : public boost::iterator_adaptor< Point_it , typename Vertex_list::all_iterator - , Point + , const Point > { public: @@ -82,7 +80,7 @@ public: Point_it(typename Vertex_list::all_iterator it) : Point_it::iterator_adaptor_(it) {} private: friend class boost::iterator_core_access; - Point& dereference() const { return this->base()->point(); } + const Point& dereference() const { return this->base()->point(); } }; // only nodes with a vertex_handle that is still in the triangulation From fe2daaae750bd129b6ec0efb1e83d1520d231902 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9bastien=20Loriot?= Date: Tue, 10 Sep 2019 10:27:12 +0200 Subject: [PATCH 142/363] retest the validity of the criteria before doing the operations + add debug code to dump model before the operation --- .../remove_degeneracies.h | 74 ++++++++++++++++--- 1 file changed, 63 insertions(+), 11 deletions(-) diff --git a/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/remove_degeneracies.h b/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/remove_degeneracies.h index 02137227c99..7d27644ac73 100644 --- a/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/remove_degeneracies.h +++ b/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/remove_degeneracies.h @@ -26,6 +26,7 @@ #include #include +#include #include @@ -64,16 +65,18 @@ is_badly_shaped(const typename boost::graph_traits::face_descripto const NamedParameters& np) { typedef typename boost::graph_traits::halfedge_descriptor halfedge_descriptor; - halfedge_descriptor null_halfedge = boost::graph_traits::null_halfedge(); + const halfedge_descriptor null_halfedge = boost::graph_traits::null_halfedge(); // @todo parameters const double needle_threshold = 4; // longest edge / shortest edge over this ratio ==> needle - const double cap_threshold = std::cos(160. / 180 * CGAL_PI); // angle over 120° ==> cap + const double cap_threshold = std::cos(160. / 180 * CGAL_PI); // angle over 160° ==> cap + const double collapse_threshold = 0.2; // max length of edges allowed to be collapsed halfedge_descriptor res = CGAL::Polygon_mesh_processing::is_needle_triangle_face(f, tmesh, needle_threshold, np); if(res != boost::graph_traits::null_halfedge()) { - return make_array(res, null_halfedge); + if ( edge_length(res, tmesh, np) <= collapse_threshold ) + return make_array(res, null_halfedge); } else // let's not make it possible to have a face be both a cap and a needle (for now) { @@ -144,8 +147,8 @@ bool remove_almost_degenerate_faces(const FaceRange& face_range, { bool something_was_done = false; -#ifdef CGAL_PMP_DEBUG_REMOVE_DEGENERACIES std::cout << edges_to_collapse.size() << " needles and " << edges_to_flip.size() << " caps" << std::endl; +#ifdef CGAL_PMP_DEBUG_REMOVE_DEGENERACIES std::ostringstream oss; oss << "degen_cleaning_iter_" << iter++ << ".off"; std::ofstream out(oss.str().c_str()); @@ -161,6 +164,10 @@ bool remove_almost_degenerate_faces(const FaceRange& face_range, std::set next_edges_to_flip; // treat needles +#ifdef CGAL_PMP_DEBUG_REMOVE_DEGENERACIES_EXTRA + int kk=0; + std::ofstream(std::string("tmp/n-00000.off")) << tmesh; +#endif while (!edges_to_collapse.empty()) { edge_descriptor e = *edges_to_collapse.begin(); @@ -179,11 +186,14 @@ bool remove_almost_degenerate_faces(const FaceRange& face_range, if (nc[0]!=h) { #ifdef CGAL_PMP_DEBUG_REMOVE_DEGENERACIES - std::cerr << "Warning: Needle criteria no longer valid " << tmesh.point(source(e, tmesh)) << " --- " - << tmesh.point(target(e, tmesh)) << std::endl; + std::cerr << "Warning: Needle criteria no longer verified " << tmesh.point(source(e, tmesh)) << " " + << tmesh.point(target(e, tmesh)) << std::endl; #endif if (nc[0]!=boost::graph_traits::null_halfedge()) next_edges_to_collapse.insert(edge(nc[0], tmesh)); + else + if (nc[1]!=boost::graph_traits::null_halfedge()) + next_edges_to_flip.insert(edge(nc[1], tmesh)); continue; } @@ -199,7 +209,10 @@ bool remove_almost_degenerate_faces(const FaceRange& face_range, h = opposite(h, tmesh); } edges_to_flip.erase(e); - +#ifdef CGAL_PMP_DEBUG_REMOVE_DEGENERACIES_EXTRA + std::cerr << " " << kk << " -- Collapsing " << tmesh.point(source(h, tmesh)) << " " + << tmesh.point(target(h, tmesh)) << std::endl; +#endif // moving to the midpoint is not a good idea. On a circle for example you might endpoint with // a bad geometry because you iteratively move one point // auto mp = midpoint(tmesh.point(source(h, tmesh)), tmesh.point(target(h, tmesh))); @@ -208,12 +221,20 @@ bool remove_almost_degenerate_faces(const FaceRange& face_range, //tmesh.point(v) = mp; // @todo the collapsed edge is supposed to be smalled so incident faces are not reevaluated but // maybe we should +#ifdef CGAL_PMP_DEBUG_REMOVE_DEGENERACIES_EXTRA + std::string nb = std::to_string(++kk); + if (kk<10) nb = std::string("0")+nb; + if (kk<100) nb = std::string("0")+nb; + if (kk<1000) nb = std::string("0")+nb; + if (kk<10000) nb = std::string("0")+nb; + std::ofstream(std::string("tmp/n-")+nb+std::string(".off")) << tmesh; +#endif something_was_done = true; } else { #ifdef CGAL_PMP_DEBUG_REMOVE_DEGENERACIES - std::cerr << "Warning: uncollapsable edge! " << tmesh.point(source(e, tmesh)) << " --- " + std::cerr << "Warning: uncollapsable edge! " << tmesh.point(source(e, tmesh)) << " " << tmesh.point(target(e, tmesh)) << std::endl; #endif next_edges_to_collapse.insert(e); @@ -221,6 +242,10 @@ bool remove_almost_degenerate_faces(const FaceRange& face_range, } // treat caps +#ifdef CGAL_PMP_DEBUG_REMOVE_DEGENERACIES_EXTRA + kk=0; + std::ofstream(std::string("tmp/c-000.off")) << tmesh; +#endif while (!edges_to_flip.empty()) { edge_descriptor e = *edges_to_flip.begin(); @@ -230,11 +255,27 @@ bool remove_almost_degenerate_faces(const FaceRange& face_range, std::cout << "treat cap: " << e << " (" << tmesh.point(source (e, tmesh)) << " --- " << tmesh.point(target(e, tmesh)) << ")" << std::endl; #endif + halfedge_descriptor h = halfedge(e, tmesh); + std::array nc = internal::is_badly_shaped(face(h, tmesh), tmesh, np); + // First check the triangle is still a cap + if (nc[1]!=h) + { +#ifdef CGAL_PMP_DEBUG_REMOVE_DEGENERACIES + std::cerr << "Warning: Cap criteria no longer verified " << tmesh.point(source(e, tmesh)) << " --- " + << tmesh.point(target(e, tmesh)) << std::endl; +#endif + if (nc[0]!=boost::graph_traits::null_halfedge()) + next_edges_to_collapse.insert(edge(nc[0], tmesh)); + else + if (nc[1]!=boost::graph_traits::null_halfedge()) + next_edges_to_flip.insert(edge(nc[1], tmesh)); + continue; + } + // special case on the border if ( is_border(e, tmesh) ) { // remove the triangle - halfedge_descriptor h = halfedge(e, tmesh); if (is_border(h, tmesh)) h = opposite(h, tmesh); edges_to_flip.erase(edge(prev(h, tmesh), tmesh)); @@ -244,14 +285,17 @@ bool remove_almost_degenerate_faces(const FaceRange& face_range, continue; } - halfedge_descriptor h = halfedge(e, tmesh); - // condition for the flip to be valid (the edge to be created does not already exist) if(!halfedge(target(next(h, tmesh), tmesh), target(next(opposite(h, tmesh), tmesh), tmesh), tmesh).second) { #ifdef CGAL_PMP_DEBUG_REMOVE_DEGENERACIES std::cout << "Flipping" << std::endl; +#endif +#ifdef CGAL_PMP_DEBUG_REMOVE_DEGENERACIES_EXTRA + std::cerr << "step " << kk << "\n"; + std::cerr << " Flipping " << tmesh.point(source(h, tmesh)) << " " + << tmesh.point(target(h, tmesh)) << std::endl; #endif Euler::flip_edge(h, tmesh); CGAL_assertion( edge(h, tmesh) == e ); @@ -292,6 +336,14 @@ bool remove_almost_degenerate_faces(const FaceRange& face_range, std::cerr << "Warning: unflippable edge! " << tmesh.point(source(h, tmesh)) << " --- " << tmesh.point(target(h, tmesh)) << std::endl; } +#endif +#ifdef CGAL_PMP_DEBUG_REMOVE_DEGENERACIES_EXTRA + std::string nb = std::to_string(++kk); + if (kk<10) nb = std::string("0")+nb; + if (kk<100) nb = std::string("0")+nb; + if (kk<1000) nb = std::string("0")+nb; + if (kk<10000) nb = std::string("0")+nb; + std::ofstream(std::string("tmp/c-")+nb+std::string(".off")) << tmesh; #endif } From 502945633c6b91189eb57a292bf09d82b519b3f8 Mon Sep 17 00:00:00 2001 From: Laurent Rineau Date: Tue, 10 Sep 2019 12:42:03 +0200 Subject: [PATCH 143/363] Rename Data to Point, because it must be the type of Vertex::point() --- .../Polyline_constraint_hierarchy_2.h | 179 +++++++++--------- 1 file changed, 89 insertions(+), 90 deletions(-) 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 c901bad3fb8..ac436166b78 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 @@ -37,12 +37,11 @@ namespace CGAL { // T is expected to be Vertex_handle // Compare is a comparison operator for type T -// Data is intended to store info on a Vertex -template +// Point the point type of vertices +template class Polyline_constraint_hierarchy_2 { public: - typedef Data Point; typedef T Vertex_handle; typedef std::pair Edge; typedef std::pair Constraint; @@ -157,7 +156,7 @@ public: }; class Context { - friend class Polyline_constraint_hierarchy_2; + friend class Polyline_constraint_hierarchy_2; private: Vertex_list* enclosing; Vertex_it pos; @@ -291,8 +290,8 @@ public: void print() const; }; -template -Polyline_constraint_hierarchy_2:: +template +Polyline_constraint_hierarchy_2:: Polyline_constraint_hierarchy_2(const Polyline_constraint_hierarchy_2& ch) : comp(ch.comp) , sc_to_c_map(Pair_compare(comp)) @@ -300,17 +299,17 @@ Polyline_constraint_hierarchy_2(const Polyline_constraint_hierarchy_2& ch) copy(ch); } -template -Polyline_constraint_hierarchy_2& -Polyline_constraint_hierarchy_2:: +template +Polyline_constraint_hierarchy_2& +Polyline_constraint_hierarchy_2:: operator=(const Polyline_constraint_hierarchy_2& ch){ copy(ch); return *this; } -template +template void -Polyline_constraint_hierarchy_2:: +Polyline_constraint_hierarchy_2:: copy(const Polyline_constraint_hierarchy_2& ch1) { // create a identity transfer vertex map @@ -325,9 +324,9 @@ copy(const Polyline_constraint_hierarchy_2& ch1) copy(ch1, vmap); } -template +template void -Polyline_constraint_hierarchy_2:: +Polyline_constraint_hierarchy_2:: copy(const Polyline_constraint_hierarchy_2& ch1, std::map& vmap) // copy with a transfer vertex map { @@ -372,9 +371,9 @@ copy(const Polyline_constraint_hierarchy_2& ch1, std::map +template void -Polyline_constraint_hierarchy_2:: +Polyline_constraint_hierarchy_2:: swap(Polyline_constraint_hierarchy_2& ch) { constraint_set.swap(ch.constraint_set); @@ -383,16 +382,16 @@ swap(Polyline_constraint_hierarchy_2& ch) /* -template -bool Polyline_constraint_hierarchy_2:: +template +bool Polyline_constraint_hierarchy_2:: is_constrained_edge(T va, T vb) const { return( c_to_sc_map.find(make_edge(va, vb)) != c_to_sc_map.end() ); } */ -template -bool Polyline_constraint_hierarchy_2:: +template +bool Polyline_constraint_hierarchy_2:: is_subconstrained_edge(T va, T vb) const { return( sc_to_c_map.find(make_edge(va, vb)) != sc_to_c_map.end() ); @@ -400,8 +399,8 @@ is_subconstrained_edge(T va, T vb) const // af: obsolete -template -bool Polyline_constraint_hierarchy_2:: +template +bool Polyline_constraint_hierarchy_2:: enclosing_constraint(Edge he, Constraint& hc) const { Context_iterator hcit, past; @@ -412,8 +411,8 @@ enclosing_constraint(Edge he, Constraint& hc) const // used by Constrained_triangulation_plus_2::intersect with Exact_intersection_tag -template -bool Polyline_constraint_hierarchy_2:: +template +bool Polyline_constraint_hierarchy_2:: enclosing_constraint(T vaa, T vbb, T& va, T& vb) const { Context_iterator hcit, past; @@ -440,8 +439,8 @@ enclosing_constraint(T vaa, T vbb, T& va, T& vb) const } // af: obsolete -template -bool Polyline_constraint_hierarchy_2:: +template +bool Polyline_constraint_hierarchy_2:: enclosing_constraints(T vaa, T vbb , Constraint_list& hcl) const { Context_iterator hcit, past; @@ -453,9 +452,9 @@ enclosing_constraints(T vaa, T vbb , Constraint_list& hcl) const return true; } -template -typename Polyline_constraint_hierarchy_2::Context -Polyline_constraint_hierarchy_2:: +template +typename Polyline_constraint_hierarchy_2::Context +Polyline_constraint_hierarchy_2:: context(T va, T vb) { Context_iterator hcit, past; @@ -463,9 +462,9 @@ context(T va, T vb) return *hcit; } -template +template std::size_t -Polyline_constraint_hierarchy_2:: +Polyline_constraint_hierarchy_2:: number_of_enclosing_constraints(T va, T vb) const { Context_list* hcl = nullptr; @@ -474,9 +473,9 @@ number_of_enclosing_constraints(T va, T vb) const return hcl->size(); } -template -typename Polyline_constraint_hierarchy_2::Context_iterator -Polyline_constraint_hierarchy_2:: +template +typename Polyline_constraint_hierarchy_2::Context_iterator +Polyline_constraint_hierarchy_2:: contexts_begin(T va, T vb) const { Context_iterator first, last; @@ -484,9 +483,9 @@ contexts_begin(T va, T vb) const return first; } -template -typename Polyline_constraint_hierarchy_2::Context_iterator -Polyline_constraint_hierarchy_2:: +template +typename Polyline_constraint_hierarchy_2::Context_iterator +Polyline_constraint_hierarchy_2:: contexts_end(T va, T vb) const { Context_iterator first, last; @@ -494,9 +493,9 @@ contexts_end(T va, T vb) const return last; } -template +template void -Polyline_constraint_hierarchy_2:: +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(); @@ -550,9 +549,9 @@ swap(Constraint_id first, Constraint_id second){ } -template +template void -Polyline_constraint_hierarchy_2:: +Polyline_constraint_hierarchy_2:: remove_constraint(Constraint_id cid){ constraint_set.erase(cid); @@ -587,8 +586,8 @@ remove_constraint(Constraint_id cid){ // This function removes vertex v from the polyline constraint // It only works for one polyline passing through v // and for the case that the constrained edge u,w has no intersections -template -void Polyline_constraint_hierarchy_2::simplify(Vertex_it uc, +template +void Polyline_constraint_hierarchy_2::simplify(Vertex_it uc, Vertex_it vc, Vertex_it wc) @@ -635,9 +634,9 @@ void Polyline_constraint_hierarchy_2::simplify(Vertex_it uc, } -template +template std::size_t -Polyline_constraint_hierarchy_2::remove_points_without_corresponding_vertex(Constraint_id cid) +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); @@ -650,9 +649,9 @@ Polyline_constraint_hierarchy_2::remove_points_without_correspon return n; } -template +template std::size_t -Polyline_constraint_hierarchy_2::remove_points_without_corresponding_vertex() +Polyline_constraint_hierarchy_2::remove_points_without_corresponding_vertex() { std::size_t n = 0; for(C_iterator it = constraint_set.begin(); it!= constraint_set.end(); ++it){ @@ -662,9 +661,9 @@ Polyline_constraint_hierarchy_2::remove_points_without_correspon } -template -typename Polyline_constraint_hierarchy_2::Constraint_id -Polyline_constraint_hierarchy_2::concatenate(Constraint_id first, Constraint_id second) +template +typename Polyline_constraint_hierarchy_2::Constraint_id +Polyline_constraint_hierarchy_2::concatenate(Constraint_id first, Constraint_id second) { constraint_set.erase(first); constraint_set.erase(second); @@ -715,9 +714,9 @@ Polyline_constraint_hierarchy_2::concatenate(Constraint_id first return first; } -template -typename Polyline_constraint_hierarchy_2::Constraint_id -Polyline_constraint_hierarchy_2::concatenate2(Constraint_id first, Constraint_id second) +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); @@ -771,9 +770,9 @@ Polyline_constraint_hierarchy_2::concatenate2(Constraint_id firs // split a constraint in two constraints, so that vcit becomes the first // vertex of 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) +template +typename Polyline_constraint_hierarchy_2::Constraint_id +Polyline_constraint_hierarchy_2::split(Constraint_id first, Vertex_it vcit) { constraint_set.erase(first); Vertex_list* second = new Vertex_list; @@ -805,9 +804,9 @@ Polyline_constraint_hierarchy_2::split(Constraint_id first, Vert return second; } -template -typename Polyline_constraint_hierarchy_2::Constraint_id -Polyline_constraint_hierarchy_2::split2(Constraint_id first, Vertex_it vcit) +template +typename Polyline_constraint_hierarchy_2::Constraint_id +Polyline_constraint_hierarchy_2::split2(Constraint_id first, Vertex_it vcit) { constraint_set.erase(first); Vertex_list* second = new Vertex_list; @@ -844,9 +843,9 @@ Polyline_constraint_hierarchy_2::split2(Constraint_id first, Ver when a constraint is inserted, it is, at first, both a constraint and a subconstraint */ -template -typename Polyline_constraint_hierarchy_2::Vertex_list* -Polyline_constraint_hierarchy_2:: +template +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; @@ -872,9 +871,9 @@ insert_constraint(T va, T vb){ } -template -typename Polyline_constraint_hierarchy_2::Vertex_list* -Polyline_constraint_hierarchy_2:: +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); @@ -901,9 +900,9 @@ insert_constraint_old_API(T va, T vb){ } -template +template void -Polyline_constraint_hierarchy_2:: +Polyline_constraint_hierarchy_2:: append_constraint(Constraint_id cid, T va, T vb){ Edge he = make_edge(va, vb); Context_list* fathers; @@ -926,8 +925,8 @@ append_constraint(Constraint_id cid, T va, T vb){ } -template -void Polyline_constraint_hierarchy_2:: +template +void Polyline_constraint_hierarchy_2:: clear() { C_iterator cit; @@ -947,8 +946,8 @@ clear() } -template -bool Polyline_constraint_hierarchy_2:: +template +bool Polyline_constraint_hierarchy_2:: next_along_sc(T va, T vb, T& w) const { // find the next vertex after vb along any enclosing constrained @@ -976,8 +975,8 @@ next_along_sc(T va, T vb, T& w) const Attention, le point v DOIT etre un point de Steiner, et les segments va,v et v,vb sont des sous contraintes. */ -template -void Polyline_constraint_hierarchy_2:: +template +void Polyline_constraint_hierarchy_2:: remove_Steiner(T v, T va, T vb) { // remove a Steiner point @@ -1008,16 +1007,16 @@ remove_Steiner(T v, T va, T vb) same as add_Steiner precondition : va,vb est une souscontrainte. */ -template -void Polyline_constraint_hierarchy_2:: +template +void Polyline_constraint_hierarchy_2:: split_constraint(T va, T vb, T vc){ add_Steiner(va, vb, vc); } -template +template void -Polyline_constraint_hierarchy_2:: +Polyline_constraint_hierarchy_2:: add_Steiner(T va, T vb, T vc){ Context_list* hcl=nullptr; if(!get_contexts(va,vb,hcl)) CGAL_triangulation_assertion(false); @@ -1068,19 +1067,19 @@ add_Steiner(T va, T vb, T vc){ } -template +template inline -typename Polyline_constraint_hierarchy_2::Edge -Polyline_constraint_hierarchy_2:: +typename Polyline_constraint_hierarchy_2::Edge +Polyline_constraint_hierarchy_2:: make_edge(T va, T vb) const { return comp(va, vb) ? Edge(va,vb) : Edge(vb,va); } -template +template inline bool -Polyline_constraint_hierarchy_2:: +Polyline_constraint_hierarchy_2:: get_contexts(T va, T vb, Context_list* & hcl) const { Sc_iterator sc_iter = sc_to_c_map.find(make_edge(va,vb)); @@ -1089,10 +1088,10 @@ get_contexts(T va, T vb, Context_list* & hcl) const return true; } -template +template inline bool -Polyline_constraint_hierarchy_2:: +Polyline_constraint_hierarchy_2:: get_contexts(T va, T vb, Context_iterator& ctxt, Context_iterator& past) const @@ -1106,19 +1105,19 @@ get_contexts(T va, T vb, -template +template inline -typename Polyline_constraint_hierarchy_2::Vertex_it -Polyline_constraint_hierarchy_2:: +typename Polyline_constraint_hierarchy_2::Vertex_it +Polyline_constraint_hierarchy_2:: get_pos(T va, T vb) const //return pos in the first context { return (*sc_to_c_map.find(make_edge(va,vb))).second->begin().pos; } -template +template void -Polyline_constraint_hierarchy_2:: +Polyline_constraint_hierarchy_2:: oriented_end(T va, T vb, T& vc) const { Context_iterator ctxt, past; @@ -1130,9 +1129,9 @@ oriented_end(T va, T vb, T& vc) const } -template +template void -Polyline_constraint_hierarchy_2:: +Polyline_constraint_hierarchy_2:: print() const { C_iterator hcit; From f3c2ae6b9861d0e8c7a4ddc584cf725470b240e9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9bastien=20Loriot?= Date: Tue, 10 Sep 2019 14:34:26 +0200 Subject: [PATCH 144/363] re-evaluate triangles after changes --- .../remove_degeneracies.h | 40 ++++++++++--------- 1 file changed, 22 insertions(+), 18 deletions(-) diff --git a/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/remove_degeneracies.h b/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/remove_degeneracies.h index 7d27644ac73..9672b2cb9f8 100644 --- a/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/remove_degeneracies.h +++ b/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/remove_degeneracies.h @@ -90,11 +90,11 @@ is_badly_shaped(const typename boost::graph_traits::face_descripto } template -void add_if_badly_shaped(const typename boost::graph_traits::face_descriptor f, - TriangleMesh& tmesh, - EdgeContainer& edges_to_collapse, - EdgeContainer& edges_to_flip, - const NamedParameters& np) +void collect_badly_shaped_triangles(const typename boost::graph_traits::face_descriptor f, + TriangleMesh& tmesh, + EdgeContainer& edges_to_collapse, + EdgeContainer& edges_to_flip, + const NamedParameters& np) { typedef typename boost::graph_traits::halfedge_descriptor halfedge_descriptor; @@ -127,7 +127,7 @@ bool remove_almost_degenerate_faces(const FaceRange& face_range, TriangleMesh& tmesh, const NamedParameters& np) { -// typedef typename boost::graph_traits::vertex_descriptor vertex_descriptor; + typedef typename boost::graph_traits::vertex_descriptor vertex_descriptor; typedef typename boost::graph_traits::halfedge_descriptor halfedge_descriptor; typedef typename boost::graph_traits::edge_descriptor edge_descriptor; typedef typename boost::graph_traits::face_descriptor face_descriptor; @@ -138,7 +138,7 @@ bool remove_almost_degenerate_faces(const FaceRange& face_range, // @todo could probably do something a bit better by looping edges, consider the incident faces // f1 / f2 and look at f1 if f1 next_edges_to_collapse; std::set next_edges_to_flip; @@ -174,13 +175,13 @@ bool remove_almost_degenerate_faces(const FaceRange& face_range, edges_to_collapse.erase(edges_to_collapse.begin()); #ifdef CGAL_PMP_DEBUG_REMOVE_DEGENERACIES - std::cout << "treat needle: " << e << " (" << tmesh.point(source (e, tmesh)) << " --- " << tmesh.point(target(e, tmesh)) << ")" << std::endl; + std::cout << " treat needle: " << e << " (" << tmesh.point(source (e, tmesh)) << " --- " << tmesh.point(target(e, tmesh)) << ")" << std::endl; #endif if(CGAL::Euler::does_satisfy_link_condition(e, tmesh)) { // the following edges are removed by the collapse halfedge_descriptor h = halfedge(e, tmesh); - CGAL_assertion(!is_border(h, tmesh)); + CGAL_assertion(!is_border(h, tmesh)); // because extracted from a face std::array nc = internal::is_badly_shaped(face(h, tmesh), tmesh, np); if (nc[0]!=h) @@ -190,7 +191,7 @@ bool remove_almost_degenerate_faces(const FaceRange& face_range, << tmesh.point(target(e, tmesh)) << std::endl; #endif if (nc[0]!=boost::graph_traits::null_halfedge()) - next_edges_to_collapse.insert(edge(nc[0], tmesh)); + edges_to_collapse.insert(edge(nc[0], tmesh)); else if (nc[1]!=boost::graph_traits::null_halfedge()) next_edges_to_flip.insert(edge(nc[1], tmesh)); @@ -209,6 +210,7 @@ bool remove_almost_degenerate_faces(const FaceRange& face_range, h = opposite(h, tmesh); } edges_to_flip.erase(e); + next_edges_to_collapse.erase(e); // for edges added in faces incident to a vertex kept after a collapse #ifdef CGAL_PMP_DEBUG_REMOVE_DEGENERACIES_EXTRA std::cerr << " " << kk << " -- Collapsing " << tmesh.point(source(h, tmesh)) << " " << tmesh.point(target(h, tmesh)) << std::endl; @@ -216,11 +218,12 @@ bool remove_almost_degenerate_faces(const FaceRange& face_range, // moving to the midpoint is not a good idea. On a circle for example you might endpoint with // a bad geometry because you iteratively move one point // auto mp = midpoint(tmesh.point(source(h, tmesh)), tmesh.point(target(h, tmesh))); - - /* vertex_descriptor v = */ Euler::collapse_edge(e, tmesh); + vertex_descriptor v = Euler::collapse_edge(e, tmesh); //tmesh.point(v) = mp; - // @todo the collapsed edge is supposed to be smalled so incident faces are not reevaluated but - // maybe we should + // examine all faces incident to the vertex kept + for (halfedge_descriptor hv : halfedges_around_target(v, tmesh)) + internal::collect_badly_shaped_triangles(face(hv, tmesh), tmesh, edges_to_collapse, edges_to_flip, np); + #ifdef CGAL_PMP_DEBUG_REMOVE_DEGENERACIES_EXTRA std::string nb = std::to_string(++kk); if (kk<10) nb = std::string("0")+nb; @@ -268,18 +271,18 @@ bool remove_almost_degenerate_faces(const FaceRange& face_range, next_edges_to_collapse.insert(edge(nc[0], tmesh)); else if (nc[1]!=boost::graph_traits::null_halfedge()) - next_edges_to_flip.insert(edge(nc[1], tmesh)); + edges_to_flip.insert(edge(nc[1], tmesh)); continue; } // special case on the border - if ( is_border(e, tmesh) ) + if ( is_border(opposite(h, tmesh), tmesh) ) { // remove the triangle - if (is_border(h, tmesh)) - h = opposite(h, tmesh); edges_to_flip.erase(edge(prev(h, tmesh), tmesh)); edges_to_flip.erase(edge(next(h, tmesh), tmesh)); + next_edges_to_collapse.erase(edge(prev(h, tmesh), tmesh)); + next_edges_to_collapse.erase(edge(next(h, tmesh), tmesh)); Euler::remove_face(h, tmesh); something_was_done = true; continue; @@ -335,6 +338,7 @@ bool remove_almost_degenerate_faces(const FaceRange& face_range, { std::cerr << "Warning: unflippable edge! " << tmesh.point(source(h, tmesh)) << " --- " << tmesh.point(target(h, tmesh)) << std::endl; + next_edges_to_flip.insert(e); } #endif #ifdef CGAL_PMP_DEBUG_REMOVE_DEGENERACIES_EXTRA From d47f3f57a343cc7893486b6085d09a3fb3a46ebd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9bastien=20Loriot?= Date: Tue, 10 Sep 2019 17:27:03 +0200 Subject: [PATCH 145/363] Test the opposite triangle too (same edge = same key) --- .../remove_degeneracies.h | 32 ++++++++++--------- 1 file changed, 17 insertions(+), 15 deletions(-) diff --git a/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/remove_degeneracies.h b/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/remove_degeneracies.h index 9672b2cb9f8..7aa132c6f58 100644 --- a/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/remove_degeneracies.h +++ b/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/remove_degeneracies.h @@ -103,7 +103,7 @@ void collect_badly_shaped_triangles(const typename boost::graph_traits::null_halfedge()) { #ifdef CGAL_PMP_DEBUG_REMOVE_DEGENERACIES - std::cout << "add new needle: " << res[0] << std::endl; + std::cout << "add new needle: " << edge(res[0], tmesh) << std::endl; #endif edges_to_collapse.insert(edge(res[0], tmesh)); } @@ -112,7 +112,7 @@ void collect_badly_shaped_triangles(const typename boost::graph_traits::null_halfedge()) { #ifdef CGAL_PMP_DEBUG_REMOVE_DEGENERACIES - std::cout << "add new cap: " << res[1] << std::endl; + std::cout << "add new cap: " << edge(res[1],tmesh) << std::endl; #endif edges_to_flip.insert(edge(res[1], tmesh)); } @@ -143,6 +143,7 @@ bool remove_almost_degenerate_faces(const FaceRange& face_range, #ifdef CGAL_PMP_DEBUG_REMOVE_DEGENERACIES int iter = 0; #endif + for(;;) { bool something_was_done = false; @@ -190,12 +191,12 @@ bool remove_almost_degenerate_faces(const FaceRange& face_range, std::cerr << "Warning: Needle criteria no longer verified " << tmesh.point(source(e, tmesh)) << " " << tmesh.point(target(e, tmesh)) << std::endl; #endif - if (nc[0]!=boost::graph_traits::null_halfedge()) - edges_to_collapse.insert(edge(nc[0], tmesh)); - else - if (nc[1]!=boost::graph_traits::null_halfedge()) - next_edges_to_flip.insert(edge(nc[1], tmesh)); - continue; + // the opposite edge might also have been inserted in the set and might still be a needle + h = opposite(h, tmesh); + if (is_border(h, tmesh) ) continue; + nc = internal::is_badly_shaped(face(h, tmesh), tmesh, np); + if (nc[0] != h) + continue; } for (int i=0; i<2; ++i) @@ -222,7 +223,8 @@ bool remove_almost_degenerate_faces(const FaceRange& face_range, //tmesh.point(v) = mp; // examine all faces incident to the vertex kept for (halfedge_descriptor hv : halfedges_around_target(v, tmesh)) - internal::collect_badly_shaped_triangles(face(hv, tmesh), tmesh, edges_to_collapse, edges_to_flip, np); + if (!is_border(hv, tmesh)) + internal::collect_badly_shaped_triangles(face(hv, tmesh), tmesh, edges_to_collapse, edges_to_flip, np); #ifdef CGAL_PMP_DEBUG_REMOVE_DEGENERACIES_EXTRA std::string nb = std::to_string(++kk); @@ -267,12 +269,12 @@ bool remove_almost_degenerate_faces(const FaceRange& face_range, std::cerr << "Warning: Cap criteria no longer verified " << tmesh.point(source(e, tmesh)) << " --- " << tmesh.point(target(e, tmesh)) << std::endl; #endif - if (nc[0]!=boost::graph_traits::null_halfedge()) - next_edges_to_collapse.insert(edge(nc[0], tmesh)); - else - if (nc[1]!=boost::graph_traits::null_halfedge()) - edges_to_flip.insert(edge(nc[1], tmesh)); - continue; + // the opposite edge might also have been inserted in the set and might still be a cap + h = opposite(h, tmesh); + if (is_border(h, tmesh) ) continue; + nc = internal::is_badly_shaped(face(h, tmesh), tmesh, np); + if (nc[1] != h) + continue; } // special case on the border From 5e736889d2a640b295b11c29a81525de409227ec Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9bastien=20Loriot?= Date: Wed, 11 Sep 2019 07:06:23 +0200 Subject: [PATCH 146/363] make sure all elements are removed during one call of the function an additional call should not do anything --- .../remove_degeneracies.h | 43 +++++++++++-------- 1 file changed, 24 insertions(+), 19 deletions(-) diff --git a/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/remove_degeneracies.h b/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/remove_degeneracies.h index 7aa132c6f58..0da9bfbae73 100644 --- a/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/remove_degeneracies.h +++ b/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/remove_degeneracies.h @@ -148,8 +148,8 @@ bool remove_almost_degenerate_faces(const FaceRange& face_range, { bool something_was_done = false; - std::cout << edges_to_collapse.size() << " needles and " << edges_to_flip.size() << " caps" << std::endl; #ifdef CGAL_PMP_DEBUG_REMOVE_DEGENERACIES + std::cout << edges_to_collapse.size() << " needles and " << edges_to_flip.size() << " caps" << std::endl; std::ostringstream oss; oss << "degen_cleaning_iter_" << iter++ << ".off"; std::ofstream out(oss.str().c_str()); @@ -170,6 +170,7 @@ bool remove_almost_degenerate_faces(const FaceRange& face_range, int kk=0; std::ofstream(std::string("tmp/n-00000.off")) << tmesh; #endif + while (!edges_to_collapse.empty()) { edge_descriptor e = *edges_to_collapse.begin(); @@ -220,6 +221,7 @@ bool remove_almost_degenerate_faces(const FaceRange& face_range, // a bad geometry because you iteratively move one point // auto mp = midpoint(tmesh.point(source(h, tmesh)), tmesh.point(target(h, tmesh))); vertex_descriptor v = Euler::collapse_edge(e, tmesh); + //tmesh.point(v) = mp; // examine all faces incident to the vertex kept for (halfedge_descriptor hv : halfedges_around_target(v, tmesh)) @@ -304,36 +306,39 @@ bool remove_almost_degenerate_faces(const FaceRange& face_range, #endif Euler::flip_edge(h, tmesh); CGAL_assertion( edge(h, tmesh) == e ); - something_was_done = true; - - // remove edges from the new faces - edges_to_flip.erase(edge(prev(h, tmesh), tmesh)); - edges_to_flip.erase(edge(next(h, tmesh), tmesh)); - edges_to_flip.erase(edge(prev(opposite(h, tmesh), tmesh), tmesh)); - edges_to_flip.erase(edge(next(opposite(h, tmesh), tmesh), tmesh)); // handle face updates + bool undo = false; for (int i=0; i<2; ++i) { - if (!is_border(h, tmesh)) + CGAL_assertion(!is_border(h, tmesh)); + std::array nc = internal::is_badly_shaped(face(h, tmesh), tmesh, np); + if (nc[1]!=boost::graph_traits::null_halfedge()) { - std::array nc = internal::is_badly_shaped(face(h, tmesh), tmesh, np); - if (nc[1]!=boost::graph_traits::null_halfedge() && - edge(nc[1], tmesh) != e) // avoid infinite loop - { + if (edge(nc[1], tmesh) != e) next_edges_to_flip.insert( edge(nc[1], tmesh) ); - } else + undo = true; + } + else + { + if (nc[0]!=boost::graph_traits::null_halfedge()) { - if (nc[0]!=boost::graph_traits::null_halfedge() && - edge(nc[0], tmesh) == e) // only the new edge should be tested - { - next_edges_to_collapse.insert(e); - } + next_edges_to_collapse.insert(edge(nc[0], tmesh)); } } h=opposite(h, tmesh); } + + if (undo) + { + Euler::flip_edge(h, tmesh); // avoid infinite loop: flip only if a cap is removed + // even if we inserted some edges above these will be tested before flipping (not optimal but it does not harm) + next_edges_to_flip.insert(e); // we add it for the next round in case some other flip fix the loop + continue; + } + + something_was_done = true; } #ifdef CGAL_PMP_DEBUG_REMOVE_DEGENERACIES else From 7cf0c7daad5366a43fbead48548dfff3808a33d6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9bastien=20Loriot?= Date: Wed, 11 Sep 2019 14:44:27 +0200 Subject: [PATCH 147/363] add a geometric test to prevent folding and self-intersections --- .../remove_degeneracies.h | 69 ++++++++++++++++++- 1 file changed, 68 insertions(+), 1 deletion(-) diff --git a/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/remove_degeneracies.h b/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/remove_degeneracies.h index 0da9bfbae73..4b9ce969210 100644 --- a/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/remove_degeneracies.h +++ b/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/remove_degeneracies.h @@ -119,6 +119,56 @@ void collect_badly_shaped_triangles(const typename boost::graph_traits +bool is_collapse_geometrically_valid(typename boost::graph_traits::halfedge_descriptor h, + const TriangleMesh& tmesh, + const NamedParameters& np) +{ + typedef typename boost::graph_traits::halfedge_descriptor halfedge_descriptor; + typedef typename GetVertexPointMap::const_type VPM; + typedef typename boost::property_traits::reference Point_ref; + typedef typename GetGeomTraits::type Traits; + + VPM vpm = choose_param(get_param(np, internal_np::vertex_point), + get_const_property_map(vertex_point, tmesh)); + + +/// @todo handle boundary edges + + h = opposite(h, tmesh); // Euler::collapse edge keeps the target and removes the source + + // source is kept, target is removed + CGAL_assertion( target(h, tmesh)==vertex_removed ); + Point_ref kept = get(vpm, source(h, tmesh)); + Point_ref removed= get(vpm, target(h, tmesh)); + + // consider triangles incident to the vertex removed + halfedge_descriptor stop = prev(opposite(h, tmesh), tmesh); + halfedge_descriptor hi = opposite(next(h, tmesh), tmesh); + + std::vector triangles; + while (hi!=stop) + { + if (!is_border(hi, tmesh)) + { + Point_ref a = get(vpm, target(next(hi, tmesh), tmesh)); + Point_ref b = get(vpm, source(hi, tmesh)); + + //ack a-b-point_remove and a-b-point_kept has a compatible orientation + /// @todo use a predicate + typename Traits::Vector_3 n1 = CGAL::cross_product(removed-a, b-a); + typename Traits::Vector_3 n2 = CGAL::cross_product(kept-a, b-a); + if ( n1*n2 <=0 ) + return false; + } + hi = opposite(next(hi, tmesh), tmesh); + } + + return true; +} + } // namespace internal // @todo check what to use as priority queue with removable elements, set might not be optimal @@ -170,7 +220,6 @@ bool remove_almost_degenerate_faces(const FaceRange& face_range, int kk=0; std::ofstream(std::string("tmp/n-00000.off")) << tmesh; #endif - while (!edges_to_collapse.empty()) { edge_descriptor e = *edges_to_collapse.begin(); @@ -211,6 +260,23 @@ bool remove_almost_degenerate_faces(const FaceRange& face_range, } h = opposite(h, tmesh); } + + if ( !internal::is_collapse_geometrically_valid(h, tmesh, np) ) + { + h = opposite(h, tmesh); + if ( !internal::is_collapse_geometrically_valid(h, tmesh, np) ) + { +#ifdef CGAL_PMP_DEBUG_REMOVE_DEGENERACIES + std::cerr << "Warning: geometrically invalid edge collapse! " + << tmesh.point(source(e, tmesh)) << " " + << tmesh.point(target(e, tmesh)) << std::endl; +#endif + next_edges_to_collapse.insert(e); + continue; + } + e = edge(h, tmesh); // update the edge + } + edges_to_flip.erase(e); next_edges_to_collapse.erase(e); // for edges added in faces incident to a vertex kept after a collapse #ifdef CGAL_PMP_DEBUG_REMOVE_DEGENERACIES_EXTRA @@ -332,6 +398,7 @@ bool remove_almost_degenerate_faces(const FaceRange& face_range, if (undo) { + /// @todo we could decide on a metric and allow the filp only if it is improving the mesh Euler::flip_edge(h, tmesh); // avoid infinite loop: flip only if a cap is removed // even if we inserted some edges above these will be tested before flipping (not optimal but it does not harm) next_edges_to_flip.insert(e); // we add it for the next round in case some other flip fix the loop From 31e44f2580229e3c83730612309583e52542fcbe Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9bastien=20Loriot?= Date: Wed, 11 Sep 2019 16:04:25 +0200 Subject: [PATCH 148/363] keep the vertex minimizing the volume variation --- .../remove_degeneracies.h | 103 ++++++++++++++++-- 1 file changed, 94 insertions(+), 9 deletions(-) diff --git a/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/remove_degeneracies.h b/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/remove_degeneracies.h index 4b9ce969210..ee3a92c28d1 100644 --- a/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/remove_degeneracies.h +++ b/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/remove_degeneracies.h @@ -71,6 +71,7 @@ is_badly_shaped(const typename boost::graph_traits::face_descripto const double needle_threshold = 4; // longest edge / shortest edge over this ratio ==> needle const double cap_threshold = std::cos(160. / 180 * CGAL_PI); // angle over 160° ==> cap const double collapse_threshold = 0.2; // max length of edges allowed to be collapsed + /// @todo add is_constrained edge map halfedge_descriptor res = CGAL::Polygon_mesh_processing::is_needle_triangle_face(f, tmesh, needle_threshold, np); if(res != boost::graph_traits::null_halfedge()) @@ -119,6 +120,7 @@ void collect_badly_shaped_triangles(const typename boost::graph_traits @@ -168,6 +170,91 @@ bool is_collapse_geometrically_valid(typename boost::graph_traits: return true; } +*/ + +template +boost::optional get_collapse_volume(typename boost::graph_traits::halfedge_descriptor h, + const TriangleMesh& tmesh, + const NamedParameters& np) +{ + typedef typename boost::graph_traits::halfedge_descriptor halfedge_descriptor; + typedef typename GetVertexPointMap::const_type VPM; + typedef typename boost::property_traits::reference Point_ref; + typedef typename GetGeomTraits::type Traits; + + const typename Traits::Point_3 origin(ORIGIN); + + VPM vpm = choose_param(get_param(np, internal_np::vertex_point), + get_const_property_map(vertex_point, tmesh)); + + +/// @todo handle boundary edges + + h = opposite(h, tmesh); // Euler::collapse edge keeps the target and removes the source + + // source is kept, target is removed + CGAL_assertion( target(h, tmesh)==vertex_removed ); + Point_ref kept = get(vpm, source(h, tmesh)); + Point_ref removed= get(vpm, target(h, tmesh)); + + // init volume with incident triangles (reversed orientation + double delta_vol = volume(removed, kept, get(vpm,target(next(h, tmesh), tmesh)), origin) + + volume(kept, removed, get(vpm,target(next(opposite(h, tmesh), tmesh), tmesh)), origin); + + // consider triangles incident to the vertex removed + halfedge_descriptor stop = prev(opposite(h, tmesh), tmesh); + halfedge_descriptor hi = opposite(next(h, tmesh), tmesh); + + std::vector triangles; + while (hi!=stop) + { + if (!is_border(hi, tmesh)) + { + Point_ref a = get(vpm, target(next(hi, tmesh), tmesh)); + Point_ref b = get(vpm, source(hi, tmesh)); + + //ack a-b-point_remove and a-b-point_kept has a compatible orientation + /// @todo use a predicate + typename Traits::Vector_3 n1 = CGAL::cross_product(removed-a, b-a); + typename Traits::Vector_3 n2 = CGAL::cross_product(kept-a, b-a); + if ( n1*n2 <=0 ) + return boost::none; + delta_vol += volume(b, a, removed, origin) + volume(a, b, kept, origin); // opposite orientation + } + hi = opposite(next(hi, tmesh), tmesh); + } + + return CGAL::abs(delta_vol); +} + +template +typename boost::graph_traits::halfedge_descriptor +get_best_edge_orientation(typename boost::graph_traits::edge_descriptor e, + const TriangleMesh& tmesh, + const NamedParameters& np) +{ + typedef typename boost::graph_traits::halfedge_descriptor halfedge_descriptor; + + halfedge_descriptor h = halfedge(e, tmesh), ho=opposite(h, tmesh); + + boost::optional dv1 = get_collapse_volume(h, tmesh, np); + boost::optional dv2 = get_collapse_volume(ho, tmesh, np); + + if (dv1 != boost::none) + { + if (dv2 != boost::none) + { + return *dv1 < *dv2 ? h : ho; + } + return h; + } + + if (dv2 != boost::none) + { + return ho; + } + return boost::graph_traits::null_halfedge(); +} } // namespace internal @@ -261,20 +348,18 @@ bool remove_almost_degenerate_faces(const FaceRange& face_range, h = opposite(h, tmesh); } - if ( !internal::is_collapse_geometrically_valid(h, tmesh, np) ) + // pick the orientation of edge to keep the vertex minimizing the volume variation + h = internal::get_best_edge_orientation(e, tmesh, np); + + if ( h == boost::graph_traits::null_halfedge() ) { - h = opposite(h, tmesh); - if ( !internal::is_collapse_geometrically_valid(h, tmesh, np) ) - { #ifdef CGAL_PMP_DEBUG_REMOVE_DEGENERACIES std::cerr << "Warning: geometrically invalid edge collapse! " << tmesh.point(source(e, tmesh)) << " " << tmesh.point(target(e, tmesh)) << std::endl; #endif - next_edges_to_collapse.insert(e); - continue; - } - e = edge(h, tmesh); // update the edge + next_edges_to_collapse.insert(e); + continue; } edges_to_flip.erase(e); @@ -286,7 +371,7 @@ bool remove_almost_degenerate_faces(const FaceRange& face_range, // moving to the midpoint is not a good idea. On a circle for example you might endpoint with // a bad geometry because you iteratively move one point // auto mp = midpoint(tmesh.point(source(h, tmesh)), tmesh.point(target(h, tmesh))); - vertex_descriptor v = Euler::collapse_edge(e, tmesh); + vertex_descriptor v = Euler::collapse_edge(edge(h, tmesh), tmesh); //tmesh.point(v) = mp; // examine all faces incident to the vertex kept From e1366dd184fb61af1711272495a8924ab02bb1b6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9bastien=20Loriot?= Date: Thu, 12 Sep 2019 10:52:41 +0200 Subject: [PATCH 149/363] flip only if the flip is the best quad diagonal --- .../remove_degeneracies.h | 60 +++++++++++++++---- 1 file changed, 47 insertions(+), 13 deletions(-) diff --git a/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/remove_degeneracies.h b/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/remove_degeneracies.h index ee3a92c28d1..314615e295a 100644 --- a/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/remove_degeneracies.h +++ b/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/remove_degeneracies.h @@ -256,6 +256,44 @@ get_best_edge_orientation(typename boost::graph_traits::edge_descr return boost::graph_traits::null_halfedge(); } +// adapted from triangulate_faces +template +bool should_flip(typename boost::graph_traits::edge_descriptor e, + const TriangleMesh& tmesh, + const NamedParameters& np) +{ + typedef typename boost::graph_traits::halfedge_descriptor halfedge_descriptor; + typedef typename GetVertexPointMap::const_type VPM; + typedef typename boost::property_traits::reference Point_ref; + + VPM vpm = choose_param(get_param(np, internal_np::vertex_point), + get_const_property_map(vertex_point, tmesh)); + + CGAL_assertion( !is_border(e, tmesh) ); + + halfedge_descriptor h = halfedge(e, tmesh); + + Point_ref p0 = get(vpm, target(h, tmesh)); + Point_ref p1 = get(vpm, target(next(h, tmesh), tmesh)); + Point_ref p2 = get(vpm, source(h, tmesh)); + Point_ref p3 = get(vpm, target(next(opposite(h, tmesh), tmesh), tmesh)); + + /* Chooses the diagonal that will split the quad in two triangles that maximize + * the scalar product of of the un-normalized normals of the two triangles. + * The lengths of the un-normalized normals (computed using cross-products of two vectors) + * are proportional to the area of the triangles. + * Maximize the scalar product of the two normals will avoid skinny triangles, + * and will also taken into account the cosine of the angle between the two normals. + * In particular, if the two triangles are oriented in different directions, + * the scalar product will be negative. + */ + + double p1p3 = CGAL::cross_product(p2-p1,p3-p2) * CGAL::cross_product(p0-p3,p1-p0); + double p0p2 = CGAL::cross_product(p1-p0,p1-p2) * CGAL::cross_product(p3-p2,p3-p0); + + return p0p2<=p1p3; +} + } // namespace internal // @todo check what to use as priority queue with removable elements, set might not be optimal @@ -447,6 +485,15 @@ bool remove_almost_degenerate_faces(const FaceRange& face_range, if(!halfedge(target(next(h, tmesh), tmesh), target(next(opposite(h, tmesh), tmesh), tmesh), tmesh).second) { + + if (!internal::should_flip(e, tmesh, np)) + { +#ifdef CGAL_PMP_DEBUG_REMOVE_DEGENERACIES + std::cout << "Flipping prevented: not the best diagonal" << std::endl; +#endif + next_edges_to_flip.insert(e); + continue; + } #ifdef CGAL_PMP_DEBUG_REMOVE_DEGENERACIES std::cout << "Flipping" << std::endl; #endif @@ -459,7 +506,6 @@ bool remove_almost_degenerate_faces(const FaceRange& face_range, CGAL_assertion( edge(h, tmesh) == e ); // handle face updates - bool undo = false; for (int i=0; i<2; ++i) { CGAL_assertion(!is_border(h, tmesh)); @@ -468,8 +514,6 @@ bool remove_almost_degenerate_faces(const FaceRange& face_range, { if (edge(nc[1], tmesh) != e) next_edges_to_flip.insert( edge(nc[1], tmesh) ); - else - undo = true; } else { @@ -480,16 +524,6 @@ bool remove_almost_degenerate_faces(const FaceRange& face_range, } h=opposite(h, tmesh); } - - if (undo) - { - /// @todo we could decide on a metric and allow the filp only if it is improving the mesh - Euler::flip_edge(h, tmesh); // avoid infinite loop: flip only if a cap is removed - // even if we inserted some edges above these will be tested before flipping (not optimal but it does not harm) - next_edges_to_flip.insert(e); // we add it for the next round in case some other flip fix the loop - continue; - } - something_was_done = true; } #ifdef CGAL_PMP_DEBUG_REMOVE_DEGENERACIES From ca3a9d21117208ce07795032f0be066f064e202b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9bastien=20Loriot?= Date: Thu, 12 Sep 2019 10:56:27 +0200 Subject: [PATCH 150/363] update example --- .../Polygon_mesh_processing/clean_degeneracies.cpp | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/Polygon_mesh_processing/examples/Polygon_mesh_processing/clean_degeneracies.cpp b/Polygon_mesh_processing/examples/Polygon_mesh_processing/clean_degeneracies.cpp index 8d9e366b6e4..837ec356aed 100644 --- a/Polygon_mesh_processing/examples/Polygon_mesh_processing/clean_degeneracies.cpp +++ b/Polygon_mesh_processing/examples/Polygon_mesh_processing/clean_degeneracies.cpp @@ -1,10 +1,11 @@ #include #include +#include +#include #include #include -#include #include typedef CGAL::Exact_predicates_inexact_constructions_kernel K; @@ -27,10 +28,18 @@ int main(int argc, char** argv) return 1; } + std::cout << "Input mesh has " << edges(mesh).size() << " edges\n"; + if (PMP::does_self_intersect(mesh)) + std::cout << "Input mesh has self-intersections\n"; + PMP::remove_almost_degenerate_faces(mesh); std::ofstream out("cleaned_mesh.off"); out << std::setprecision(17) << mesh; + std::cout << "Output mesh has " << edges(mesh).size() << " edges\n"; + if (PMP::does_self_intersect(mesh)) + std::cout << "Output mesh has self-intersections\n"; + return 0; } From 59dae32b53005c02cf2c64cfc7927dc7bebc033e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mael=20Rouxel-Labb=C3=A9?= Date: Mon, 16 Sep 2019 09:49:53 +0200 Subject: [PATCH 151/363] Add an example of shortest path using 3D point/ray --- .../Surface_mesh_shortest_path.txt | 13 +++- .../Surface_mesh_shortest_path/examples.txt | 1 + .../Surface_mesh_shortest_path/CMakeLists.txt | 1 + .../shortest_path_with_locate.cpp | 78 +++++++++++++++++++ 4 files changed, 92 insertions(+), 1 deletion(-) create mode 100644 Surface_mesh_shortest_path/examples/Surface_mesh_shortest_path/shortest_path_with_locate.cpp diff --git a/Surface_mesh_shortest_path/doc/Surface_mesh_shortest_path/Surface_mesh_shortest_path.txt b/Surface_mesh_shortest_path/doc/Surface_mesh_shortest_path/Surface_mesh_shortest_path.txt index b7af46bd906..cbc0cf43e9b 100644 --- a/Surface_mesh_shortest_path/doc/Surface_mesh_shortest_path/Surface_mesh_shortest_path.txt +++ b/Surface_mesh_shortest_path/doc/Surface_mesh_shortest_path/Surface_mesh_shortest_path.txt @@ -60,7 +60,18 @@ If the traits class used holds some local state, it must also be passed to the c The set of source points for shortest path queries can be populated one by one or using a range. A source point can be specified using either a vertex of the input surface mesh or a face of the input surface mesh with some barycentric coordinates. -Given a point \f$p\f$ that lies inside a triangle face \f$(A,B,C)\f$, its barycentric coordinates are a weight triple \f$(b_0,b_1,b_2)\f$ such that \f$p = b_0\cdot~A + b_1\cdot~B + b_2\cdot~C\f$, and \f$b_0 + b_1 + b_2 = 1\f$. +Given a point \f$p\f$ that lies inside a triangle face \f$(A,B,C)\f$, its barycentric coordinates +are a weight triple \f$(b_0,b_1,b_2)\f$ such that \f$p = b_0\cdot~A + b_1\cdot~B + b_2\cdot~C\f$, +and \f$b_0 + b_1 + b_2 = 1\f$. + +For convenience, a function `Surface_mesh_shortest_path::locate()` is provided to construct face locations from geometric +inputs: +- given a point `p` living in 3D space, this function computes the point closest to `p` on the surface, +and returns the face containing this point, as well as its barycentric coordinates; +- given a ray `r` living in 3D space, this function computes the intersection of the ray with the surface, +and (if an intersection exists) returns the face containing this point, as well as its barycentric coordinates; + +Usage of this function is illustrated in the example \ref Surface_mesh_shortest_path/shortest_path_with_locate.cpp. \subsubsection Surface_mesh_shortest_pathClassBuild Building the Internal Sequence Tree diff --git a/Surface_mesh_shortest_path/doc/Surface_mesh_shortest_path/examples.txt b/Surface_mesh_shortest_path/doc/Surface_mesh_shortest_path/examples.txt index bdb3f6e7aff..a13f2a8bde5 100644 --- a/Surface_mesh_shortest_path/doc/Surface_mesh_shortest_path/examples.txt +++ b/Surface_mesh_shortest_path/doc/Surface_mesh_shortest_path/examples.txt @@ -5,4 +5,5 @@ \example Surface_mesh_shortest_path/shortest_paths_OpenMesh.cpp \example Surface_mesh_shortest_path/shortest_paths_multiple_sources.cpp \example Surface_mesh_shortest_path/shortest_path_sequence.cpp +\example Surface_mesh_shortest_path/shortest_path_with_locate.cpp */ diff --git a/Surface_mesh_shortest_path/examples/Surface_mesh_shortest_path/CMakeLists.txt b/Surface_mesh_shortest_path/examples/Surface_mesh_shortest_path/CMakeLists.txt index 6b757a109e9..513007600bc 100644 --- a/Surface_mesh_shortest_path/examples/Surface_mesh_shortest_path/CMakeLists.txt +++ b/Surface_mesh_shortest_path/examples/Surface_mesh_shortest_path/CMakeLists.txt @@ -17,6 +17,7 @@ if ( CGAL_FOUND ) create_single_source_cgal_program( "shortest_paths_no_id.cpp" ) create_single_source_cgal_program( "shortest_paths_with_id.cpp" ) create_single_source_cgal_program( "shortest_paths.cpp" ) + create_single_source_cgal_program( "shortest_path_with_locate.cpp" ) find_package( OpenMesh QUIET ) if ( OpenMesh_FOUND ) diff --git a/Surface_mesh_shortest_path/examples/Surface_mesh_shortest_path/shortest_path_with_locate.cpp b/Surface_mesh_shortest_path/examples/Surface_mesh_shortest_path/shortest_path_with_locate.cpp new file mode 100644 index 00000000000..de1ef93fb47 --- /dev/null +++ b/Surface_mesh_shortest_path/examples/Surface_mesh_shortest_path/shortest_path_with_locate.cpp @@ -0,0 +1,78 @@ +#include + +#include + +#include +#include +#include +#include + +#include + +#include +#include +#include + +typedef CGAL::Exact_predicates_inexact_constructions_kernel Kernel; +typedef Kernel::Point_3 Point_3; +typedef Kernel::Ray_3 Ray_3; + +typedef CGAL::Surface_mesh Triangle_mesh; +typedef CGAL::Surface_mesh_shortest_path_traits Traits; +typedef CGAL::Surface_mesh_shortest_path Surface_mesh_shortest_path; + +typedef boost::graph_traits Graph_traits; +typedef Graph_traits::vertex_iterator vertex_iterator; +typedef Graph_traits::face_iterator face_iterator; + +typedef typename Surface_mesh_shortest_path::Barycentric_coordinates Barycentric_coordinates; +typedef typename Surface_mesh_shortest_path::Face_location Face_location; + +typedef CGAL::AABB_face_graph_triangle_primitive AABB_face_graph_primitive; +typedef CGAL::AABB_traits AABB_face_graph_traits; +typedef CGAL::AABB_tree AABB_tree; + +int main(int argc, char** argv) +{ + Triangle_mesh tmesh; + std::ifstream input((argc>1) ? argv[1] : "data/elephant.off"); + input >> tmesh; + + Surface_mesh_shortest_path shortest_paths(tmesh); + + // The source point is a 3D point. We must convert it to a face location (that is, + // a face ID and three barycentric coordinates) + const Point_3 source_pt(-0.06, -0.145, 0.182); + Face_location source_loc = shortest_paths.locate(source_pt); // this builds an AABB tree of the mesh + + // Add the source point + shortest_paths.add_source_point(source_loc.first, source_loc.second); + + // The target will be defined by the first intersection of the following ray with the input mesh + const Ray_3 ray(Point_3(0.126, 0.387, 0.324), Point_3(0.126, 0.387, 0.124)); + + // If you intend to call `locate` many times, you should cache the AABB tree + // that is used internally to avoid it being recomputed at each call, as follows: + AABB_tree tree; + shortest_paths.build_aabb_tree(tree); + Face_location target_loc = shortest_paths.locate(ray, tree); + + if(target_loc.first == boost::graph_traits::null_face()) + { + std::cerr << "They ray does not intersect the mesh!" << std::endl; + return EXIT_FAILURE; + } + + // Compute the shortest path between the source and the target + std::vector points; + shortest_paths.shortest_path_points_to_source_points(target_loc.first, target_loc.second, + std::back_inserter(points)); + + // Print the points + std::cout << points.size() << " "; + for (std::size_t i = 0; i < points.size(); ++i) + std::cout << " " << points[i]; + std::cout << std::endl; + + return EXIT_SUCCESS; +} From 7e29cbcf468b591f4031a37d7b2e4ba474e58acd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mael=20Rouxel-Labb=C3=A9?= Date: Mon, 16 Sep 2019 09:51:04 +0200 Subject: [PATCH 152/363] Misc minor changes (wrap / doc fixes) --- .../Surface_mesh_shortest_path.h | 76 ++++++++++++++----- 1 file changed, 57 insertions(+), 19 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 3e713c23161..aa60e53d125 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 @@ -1850,7 +1850,10 @@ private: for (boost::tie(current,end) = vertices(m_graph); current != end; ++current) { - std::cout << "Vertex#" << numVertices << ": p = " << get(m_vertexPointMap,*current) << " , Saddle Vertex: " << (is_saddle_vertex(*current) ? "yes" : "no") << " , Boundary Vertex: " << (is_boundary_vertex(*current) ? "yes" : "no") << std::endl; + std::cout << "Vertex#" << numVertices + << ": p = " << get(m_vertexPointMap,*current) + << " , Saddle Vertex: " << (is_saddle_vertex(*current) ? "yes" : "no") + << " , Boundary Vertex: " << (is_boundary_vertex(*current) ? "yes" : "no") << std::endl; ++numVertices; } } @@ -1925,7 +1928,10 @@ private: case Cone_expansion_event::PSEUDO_SOURCE: if (m_debugOutput) { - std::cout << "PseudoSource Expansion: Parent = " << parent << " , Vertex = " << get(m_vertexIndexMap, event->m_parent->target_vertex()) << " , Distance = " << event->m_distanceEstimate << " , Level = " << event->m_parent->level() + 1 << std::endl; + std::cout << "PseudoSource Expansion: Parent = " << parent + << " , Vertex = " << get(m_vertexIndexMap, event->m_parent->target_vertex()) + << " , Distance = " << event->m_distanceEstimate + << " , Level = " << event->m_parent->level() + 1 << std::endl; } expand_pseudo_source(parent); @@ -1933,7 +1939,11 @@ private: case Cone_expansion_event::LEFT_CHILD: if (m_debugOutput) { - std::cout << "Left Expansion: Parent = " << parent << " Edge = (" << get(m_vertexIndexMap, source(event->m_parent->left_child_edge(), m_graph)) << "," << get(m_vertexIndexMap, target(event->m_parent->left_child_edge(), m_graph)) << ") , Distance = " << event->m_distanceEstimate << " , Level = " << event->m_parent->level() + 1 << std::endl; + std::cout << "Left Expansion: Parent = " << parent + << " Edge = (" << get(m_vertexIndexMap, source(event->m_parent->left_child_edge(), m_graph)) + << "," << get(m_vertexIndexMap, target(event->m_parent->left_child_edge(), m_graph)) + << ") , Distance = " << event->m_distanceEstimate + << " , Level = " << event->m_parent->level() + 1 << std::endl; } expand_left_child(parent, event->m_windowSegment); @@ -1941,7 +1951,11 @@ private: case Cone_expansion_event::RIGHT_CHILD: if (m_debugOutput) { - std::cout << "Right Expansion: Parent = " << parent << " , Edge = (" << get(m_vertexIndexMap, source(event->m_parent->right_child_edge(), m_graph)) << "," << get(m_vertexIndexMap, target(event->m_parent->right_child_edge(), m_graph)) << ") , Distance = " << event->m_distanceEstimate << " , Level = " << event->m_parent->level() + 1 << std::endl; + std::cout << "Right Expansion: Parent = " << parent + << " , Edge = (" << get(m_vertexIndexMap, source(event->m_parent->right_child_edge(), m_graph)) + << "," << get(m_vertexIndexMap, target(event->m_parent->right_child_edge(), m_graph)) + << ") , Distance = " << event->m_distanceEstimate + << " , Level = " << event->m_parent->level() + 1 << std::endl; } expand_right_child(parent, event->m_windowSegment); @@ -2035,7 +2049,12 @@ public: \param traits Optional instance of the traits class to use. */ - Surface_mesh_shortest_path(const Triangle_mesh& tm, Vertex_index_map vertexIndexMap, Halfedge_index_map halfedgeIndexMap, Face_index_map faceIndexMap, Vertex_point_map vertexPointMap, const Traits& traits = Traits()) + Surface_mesh_shortest_path(const Triangle_mesh& tm, + Vertex_index_map vertexIndexMap, + Halfedge_index_map halfedgeIndexMap, + Face_index_map faceIndexMap, + Vertex_point_map vertexPointMap, + const Traits& traits = Traits()) : m_traits(traits) , m_graph(const_cast(tm)) , m_vertexIndexMap(vertexIndexMap) @@ -2471,7 +2490,11 @@ public: return point(f, location, tm, get(CGAL::vertex_point, tm), traits); } - static Point_3 point(face_descriptor f, Barycentric_coordinates location, const Triangle_mesh& tm, Vertex_point_map vertexPointMap, const Traits& traits = Traits()) + static Point_3 point(face_descriptor f, + Barycentric_coordinates location, + const Triangle_mesh& tm, + Vertex_point_map vertexPointMap, + const Traits& traits = Traits()) { return construct_barycenter_in_triangle_3(triangle_from_face(f, tm, vertexPointMap), location, traits); } @@ -2605,7 +2628,7 @@ public: that accept a reference to an `AABB_tree` as input. \details The following static overload is also available: - - `static Face_location locate(const Point_3& p, const Triangle_mesh& tm, Vertex_point_map vertexPointMap, const Traits& traits = Traits())` + - `static Face_location locate(const %Point_3& p, const Triangle_mesh& tm, Vertex_point_map vertexPointMap, const Traits& traits = Traits())` \tparam AABBTraits A model of `AABBTraits` used to define a \cgal `AABB_tree`. @@ -2620,8 +2643,10 @@ public: /// \cond template - static Face_location locate(const Point_3& location, const Triangle_mesh& tm, - Vertex_point_map vertexPointMap, const Traits& traits = Traits()) + static Face_location locate(const Point_3& location, + const Triangle_mesh& tm, + Vertex_point_map vertexPointMap, + const Traits& traits = Traits()) { AABB_tree tree; build_aabb_tree(tm, tree, vertexPointMap); @@ -2634,7 +2659,7 @@ public: \brief Returns the face location nearest to the given point. \details The following static overload is also available: - - static Face_location locate(const Point_3& p, const AABB_tree& tree, const Triangle_mesh& tm, Vertex_point_map vertexPointMap, const Traits& traits = Traits()) + - static Face_location locate(const %Point_3& p, const AABB_tree& tree, const Triangle_mesh& tm, Vertex_point_map vertexPointMap, const Traits& traits = Traits()) \tparam AABBTraits A model of `AABBTraits` used to define a \cgal `AABB_tree`. @@ -2642,7 +2667,8 @@ public: \param tree A `AABB_tree` containing the triangular faces of the input surface mesh to perform the point location with */ template - Face_location locate(const Point_3& p, const AABB_tree& tree) const + Face_location locate(const Point_3& p, + const AABB_tree& tree) const { return locate(p, tree, m_graph, m_vertexPointMap, m_traits); } @@ -2650,7 +2676,11 @@ public: /// \cond template - static Face_location locate(const Point_3& location, const AABB_tree& tree, const Triangle_mesh& tm, Vertex_point_map vertexPointMap, const Traits& traits = Traits()) + static Face_location locate(const Point_3& location, + const AABB_tree& tree, + const Triangle_mesh& tm, + Vertex_point_map vertexPointMap, + const Traits& traits = Traits()) { typename Traits::Construct_barycentric_coordinates_in_triangle_3 cbcit3(traits.construct_barycentric_coordinates_in_triangle_3_object()); typename AABB_tree::Point_and_primitive_id result = tree.closest_point_and_primitive(location); @@ -2670,7 +2700,7 @@ public: that accept a reference to an `AABB_tree` as input. \details The following static overload is also available: - - `static Face_location locate(const Ray_3& ray, const Triangle_mesh& tm, Vertex_point_map vertexPointMap, const Traits& traits = Traits())` + - `static Face_location locate(const %Ray_3& ray, const Triangle_mesh& tm, Vertex_point_map vertexPointMap, const Traits& traits = Traits())` \tparam AABBTraits A model of `AABBTraits` used to define an `AABB_tree`. @@ -2685,8 +2715,10 @@ public: /// \cond template - static Face_location locate(const Ray_3& ray, const Triangle_mesh& tm, - Vertex_point_map vertexPointMap, const Traits& traits = Traits()) + static Face_location locate(const Ray_3& ray, + const Triangle_mesh& tm, + Vertex_point_map vertexPointMap, + const Traits& traits = Traits()) { AABB_tree tree; build_aabb_tree(tm, tree, vertexPointMap); @@ -2700,7 +2732,7 @@ public: its source point. \details The following static overload is also available: - - static Face_location locate(const Ray_3& ray, const AABB_tree& tree, const Triangle_mesh& tm, Vertex_point_map vertexPointMap, const Traits& traits = Traits()) + - static Face_location locate(const %Ray_3& ray, const AABB_tree& tree, const Triangle_mesh& tm, Vertex_point_map vertexPointMap, const Traits& traits = Traits()) \tparam AABBTraits A model of `AABBTraits` used to define a \cgal `AABB_tree`. @@ -2708,7 +2740,8 @@ public: \param tree A `AABB_tree` containing the triangular faces of the input surface mesh to perform the point location with */ template - Face_location locate(const Ray_3& ray, const AABB_tree& tree) const + Face_location locate(const Ray_3& ray, + const AABB_tree& tree) const { return locate(ray, tree, m_graph, m_vertexPointMap, m_traits); } @@ -2716,7 +2749,11 @@ public: /// \cond template - static Face_location locate(const Ray_3& ray, const AABB_tree& tree, const Triangle_mesh& tm, Vertex_point_map vertexPointMap, const Traits& traits = Traits()) + static Face_location locate(const Ray_3& ray, + const AABB_tree& tree, + const Triangle_mesh& tm, + Vertex_point_map vertexPointMap, + const Traits& traits = Traits()) { typedef AABB_tree AABB_face_graph_tree; typename Traits::Construct_barycentric_coordinates_in_triangle_3 cbcit3(traits.construct_barycentric_coordinates_in_triangle_3_object()); @@ -2787,7 +2824,8 @@ public: } template - void build_aabb_tree(AABB_tree& outTree, Vertex_point_map vertexPointMap) const + void build_aabb_tree(AABB_tree& outTree, + Vertex_point_map vertexPointMap) const { build_aabb_tree(m_graph, outTree, vertexPointMap); } From e7f6c3eb2f27e86ab2b9b55d8f8d991d91da9695 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mael=20Rouxel-Labb=C3=A9?= Date: Mon, 16 Sep 2019 09:51:30 +0200 Subject: [PATCH 153/363] Fix build_aabb_tree not being documented --- .../Surface_mesh_shortest_path.h | 9 ++++----- 1 file changed, 4 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 aa60e53d125..a612338a861 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 @@ -2805,9 +2805,7 @@ public: /// \endcond - /// @} - - /* + /*! \brief Creates an `AABB_tree` suitable for use with `locate`. \details The following static overload is also available: @@ -2823,6 +2821,8 @@ public: build_aabb_tree(m_graph, outTree, m_vertexPointMap); } + /// \cond + template void build_aabb_tree(AABB_tree& outTree, Vertex_point_map vertexPointMap) const @@ -2830,8 +2830,6 @@ public: build_aabb_tree(m_graph, outTree, vertexPointMap); } - /// \cond - template static void build_aabb_tree(const Triangle_mesh& tm, AABB_tree& outTree, Vertex_point_map vertexPointMap) @@ -2843,6 +2841,7 @@ public: } /// \endcond + /// @} }; } // namespace CGAL From 2325a08b5dccf6920a1c225c0623ff03276d4a6c Mon Sep 17 00:00:00 2001 From: Guillaume Damiand Date: Mon, 16 Sep 2019 14:18:19 +0200 Subject: [PATCH 154/363] Remove warning --- GraphicsView/include/CGAL/Qt/Basic_viewer_qt.h | 16 ++++++++-------- .../include/CGAL/draw_voronoi_diagram_2.h | 2 +- 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/GraphicsView/include/CGAL/Qt/Basic_viewer_qt.h b/GraphicsView/include/CGAL/Qt/Basic_viewer_qt.h index 7768dfa10e8..41e4a23e36a 100644 --- a/GraphicsView/include/CGAL/Qt/Basic_viewer_qt.h +++ b/GraphicsView/include/CGAL/Qt/Basic_viewer_qt.h @@ -256,7 +256,7 @@ public: for (unsigned int i=0; i void add_ray(const KPoint &p, const KVector &v) { - float bigNumber = 1e30; + double bigNumber = 1e30; m_buffer_for_mono_rays.add_ray_segment(p, (p + (bigNumber)*v)); } template void add_ray(const KPoint &p, const KVector &v, const CGAL::Color &acolor) { - float bigNumber = 1e30; + double bigNumber = 1e30; m_buffer_for_colored_rays.add_ray_segment(p, (p + (bigNumber)*v), acolor); } template void add_line(const KPoint &p, const KVector &v) { - float bigNumber = 1e30; + double bigNumber = 1e30; m_buffer_for_mono_lines.add_line_segment((p - (bigNumber)*v), (p + (bigNumber)*v)); } @@ -395,7 +395,7 @@ public: template void add_line(const KPoint &p, const KVector &v, const CGAL::Color &acolor) { - float bigNumber = 1e30; + double bigNumber = 1e30; m_buffer_for_colored_lines.add_line_segment((p - (bigNumber)*v), (p + (bigNumber)*v), acolor); } @@ -467,7 +467,7 @@ protected: { std::cerr<<"VBO Creation number "<camera()->getModelViewProjectionMatrix(mat); - for(int i=0; i < 16; i++) + for(unsigned int i=0; i < 16; i++) { mvpMatrix.data()[i] = (float)mat[i]; } viewer->camera()->getModelViewMatrix(mat); - for(int i=0; i < 16; i++) + for(unsigned int i=0; i < 16; i++) { mvMatrix.data()[i] = (float)mat[i]; } diff --git a/Voronoi_diagram_2/include/CGAL/draw_voronoi_diagram_2.h b/Voronoi_diagram_2/include/CGAL/draw_voronoi_diagram_2.h index fa2cee97587..9c0e379074c 100644 --- a/Voronoi_diagram_2/include/CGAL/draw_voronoi_diagram_2.h +++ b/Voronoi_diagram_2/include/CGAL/draw_voronoi_diagram_2.h @@ -40,7 +40,7 @@ namespace CGAL { struct DefaultColorFunctorV2 { template - static CGAL::Color run(const V2 &, const typename V2::Face_iterator fh) { + static CGAL::Color run(const V2 &, const typename V2::Face_iterator /*fh*/) { //CGAL::Random random((unsigned int)(std::size_t)(&*fh)); //return get_random_color(random); return CGAL::Color(73, 250, 117); From 2b381af54428bc8de5aad5f8a79f3426ae24a084 Mon Sep 17 00:00:00 2001 From: Guillaume Damiand Date: Mon, 16 Sep 2019 17:19:49 +0200 Subject: [PATCH 155/363] Remove more warnings --- Nef_3/include/CGAL/draw_nef_3.h | 3 +-- .../include/CGAL/draw_periodic_2_triangulation_2.h | 1 + 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Nef_3/include/CGAL/draw_nef_3.h b/Nef_3/include/CGAL/draw_nef_3.h index 39f9f3aa398..665fbb4ca82 100644 --- a/Nef_3/include/CGAL/draw_nef_3.h +++ b/Nef_3/include/CGAL/draw_nef_3.h @@ -94,7 +94,7 @@ protected: class Nef_Visitor { public: Nef_Visitor(SimpleNefPolyhedronViewerQt &v) - : viewer(v), facets_done(), n_faces(0), n_edges(0) {} + : n_faces(0), n_edges(0), viewer(v) {} void visit(Vertex_const_handle vh) { viewer.add_point(vh->point()); @@ -169,7 +169,6 @@ protected: Nef_Visitor V(*this); CGAL_forall_volumes(c, nef) { - int is = 0; Shell_entry_const_iterator it; CGAL_forall_shells_of(it, c) { diff --git a/Periodic_2_triangulation_2/include/CGAL/draw_periodic_2_triangulation_2.h b/Periodic_2_triangulation_2/include/CGAL/draw_periodic_2_triangulation_2.h index 3e158d7fd85..3b63f4a28cd 100644 --- a/Periodic_2_triangulation_2/include/CGAL/draw_periodic_2_triangulation_2.h +++ b/Periodic_2_triangulation_2/include/CGAL/draw_periodic_2_triangulation_2.h @@ -26,6 +26,7 @@ #ifdef CGAL_USE_BASIC_VIEWER +#include #include namespace CGAL { From 7a50939809a4eec7b5cf5196212f4207e34fbca3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mael=20Rouxel-Labb=C3=A9?= Date: Thu, 19 Sep 2019 18:11:33 +0200 Subject: [PATCH 156/363] Deprecate No_intersection_tag Introduce two new tags instead, to make the behavior change clearer. Default tag for CDT2 is changed to keep the same behavior as before (what was called 'No_intersection_tag' and is now called 'No_constraint_intersection_requiring_constructions_tag') --- .../CGAL/Constrained_triangulation_2.h | 88 ++++++++++--------- .../CGAL/Constrained_triangulation_plus_2.h | 38 ++++---- 2 files changed, 66 insertions(+), 60 deletions(-) diff --git a/Triangulation_2/include/CGAL/Constrained_triangulation_2.h b/Triangulation_2/include/CGAL/Constrained_triangulation_2.h index 8765cea6f3a..099053f220b 100644 --- a/Triangulation_2/include/CGAL/Constrained_triangulation_2.h +++ b/Triangulation_2/include/CGAL/Constrained_triangulation_2.h @@ -47,11 +47,17 @@ namespace CGAL { -struct No_intersection_tag{}; -struct No_intersection_requiring_constructions_tag{}; +struct No_constraint_intersection_tag{}; +struct No_constraint_intersection_requiring_constructions_tag{}; struct Exact_intersections_tag{}; // to be used with an exact number type struct Exact_predicates_tag{}; // to be used with filtered exact number +// This tag was deprecated in favor of `No_consNo_constraint_intersection_requiring_constructions_tagint_intersection_requiring_constructions_tag` +// due to an inaccuracy between the code and the documenation. +struct CGAL_DEPRECATED No_intersection_tag : + public No_constraint_intersection_requiring_constructions_tag +{ }; + namespace internal { template @@ -78,7 +84,7 @@ public: Triangulation_vertex_base_2, Constrained_triangulation_face_base_2 > >::type Tds; - typedef typename Default::Get::type Itag; + typedef typename Default::Get::type Itag; typedef Triangulation_2 Triangulation; typedef Constrained_triangulation_2 Constrained_triangulation; @@ -316,7 +322,7 @@ insert_constraint(Vertex_handle vaa, Vertex_handle vbb, OutputIterator out) // if the segment (or a subpart of the segment) that we are trying to constraint is already // present in the triangulation and is already marked as constrained, // then this is an intersection - if(boost::is_same::value) { + if(boost::is_same::value) { if(dimension() == 1) { if(fr->is_constrained(2)) throw Intersection_of_constraints_exception(); @@ -473,25 +479,25 @@ protected: void mark_constraint(Face_handle fr, int i); - virtual Vertex_handle intersect(Face_handle f, int i, - Vertex_handle vaa, - Vertex_handle vbb); - Vertex_handle intersect(Face_handle f, int i, - Vertex_handle vaa, - Vertex_handle vbb, - No_intersection_tag); + virtual Vertex_handle intersect(Face_handle f, int i, + Vertex_handle vaa, + Vertex_handle vbb); Vertex_handle intersect(Face_handle f, int i, Vertex_handle vaa, Vertex_handle vbb, - No_intersection_requiring_constructions_tag); - Vertex_handle intersect(Face_handle f, int i, - Vertex_handle vaa, - Vertex_handle vbb, - Exact_intersections_tag); - Vertex_handle intersect(Face_handle f, int i, - Vertex_handle vaa, - Vertex_handle vbb, - Exact_predicates_tag); + No_constraint_intersection_tag); + Vertex_handle intersect(Face_handle f, int i, + Vertex_handle vaa, + Vertex_handle vbb, + No_constraint_intersection_requiring_constructions_tag); + Vertex_handle intersect(Face_handle f, int i, + Vertex_handle vaa, + Vertex_handle vbb, + Exact_intersections_tag); + Vertex_handle intersect(Face_handle f, int i, + Vertex_handle vaa, + Vertex_handle vbb, + Exact_predicates_tag); private: //made private to avoid using the Triangulation_2 version Vertex_handle move(Vertex_handle v, const Point &) @@ -680,7 +686,7 @@ insert(const Point& a, Locate_type lt, Face_handle loc, int li) if ( lt == Triangulation::EDGE && loc->is_constrained(li) ) { - if(boost::is_same::value) + if(boost::is_same::value) throw Intersection_of_constraints_exception(); insert_in_constrained_edge = true; @@ -763,7 +769,7 @@ insert_constraint(Vertex_handle vaa, Vertex_handle vbb) // if the segment (or a subpart of the segment) that we are trying to constraint is already // present in the triangulation and is already marked as constrained, // then this is an intersection - if(boost::is_same::value) { + if(boost::is_same::value) { if(dimension() == 1) { if(fr->is_constrained(2)) throw Intersection_of_constraints_exception(); @@ -923,7 +929,7 @@ Constrained_triangulation_2:: intersect(Face_handle , int , Vertex_handle , Vertex_handle , - No_intersection_tag) + No_constraint_intersection_tag) { throw Intersection_of_constraints_exception(); return Vertex_handle() ; @@ -935,7 +941,7 @@ Constrained_triangulation_2:: intersect(Face_handle , int , Vertex_handle , Vertex_handle , - No_intersection_requiring_constructions_tag) + No_constraint_intersection_requiring_constructions_tag) { throw Intersection_of_constraints_exception(); return Vertex_handle() ; @@ -1474,12 +1480,12 @@ operator>>(std::istream& is, template bool intersection(const Gt& , - const typename Gt::Point_2& , - const typename Gt::Point_2& , - const typename Gt::Point_2& , - const typename Gt::Point_2& , - typename Gt::Point_2& , - No_intersection_tag) + const typename Gt::Point_2& , + const typename Gt::Point_2& , + const typename Gt::Point_2& , + const typename Gt::Point_2& , + typename Gt::Point_2& , + No_constraint_intersection_tag) { return false; } @@ -1492,7 +1498,7 @@ intersection(const Gt& , const typename Gt::Point_2& , const typename Gt::Point_2& , typename Gt::Point_2& , - No_intersection_requiring_constructions_tag) + No_constraint_intersection_requiring_constructions_tag) { return false; } @@ -1607,11 +1613,11 @@ compute_intersection(const Gt& gt, template int limit_intersection(const Gt& , - const typename Gt::Point_2& , - const typename Gt::Point_2& , - const typename Gt::Point_2& , - const typename Gt::Point_2& , - No_intersection_tag) + const typename Gt::Point_2& , + const typename Gt::Point_2& , + const typename Gt::Point_2& , + const typename Gt::Point_2& , + No_constraint_intersection_tag) { return 0; } @@ -1619,11 +1625,11 @@ limit_intersection(const Gt& , template int limit_intersection(const Gt& , - const typename Gt::Point_2& , - const typename Gt::Point_2& , - const typename Gt::Point_2& , - const typename Gt::Point_2& , - No_intersection_requiring_constructions_tag) + const typename Gt::Point_2& , + const typename Gt::Point_2& , + const typename Gt::Point_2& , + const typename Gt::Point_2& , + No_constraint_intersection_requiring_constructions_tag) { return 0; } diff --git a/Triangulation_2/include/CGAL/Constrained_triangulation_plus_2.h b/Triangulation_2/include/CGAL/Constrained_triangulation_plus_2.h index 0c51c6a5369..0365b58cd7d 100644 --- a/Triangulation_2/include/CGAL/Constrained_triangulation_plus_2.h +++ b/Triangulation_2/include/CGAL/Constrained_triangulation_plus_2.h @@ -686,25 +686,25 @@ public: return cid; } - virtual Vertex_handle intersect(Face_handle f, int i, - Vertex_handle vaa, - Vertex_handle vbb); - Vertex_handle intersect(Face_handle f, int i, - Vertex_handle vaa, - Vertex_handle vbb, - No_intersection_tag); + virtual Vertex_handle intersect(Face_handle f, int i, + Vertex_handle vaa, + Vertex_handle vbb); Vertex_handle intersect(Face_handle f, int i, Vertex_handle vaa, Vertex_handle vbb, - No_intersection_requiring_constructions_tag); - Vertex_handle intersect(Face_handle f, int i, - Vertex_handle vaa, - Vertex_handle vbb, - Exact_intersections_tag); - Vertex_handle intersect(Face_handle f, int i, - Vertex_handle vaa, - Vertex_handle vbb, - Exact_predicates_tag); + No_constraint_intersection_tag); + Vertex_handle intersect(Face_handle f, int i, + Vertex_handle vaa, + Vertex_handle vbb, + No_constraint_intersection_requiring_constructions_tag); + Vertex_handle intersect(Face_handle f, int i, + Vertex_handle vaa, + Vertex_handle vbb, + Exact_intersections_tag); + Vertex_handle intersect(Face_handle f, int i, + Vertex_handle vaa, + Vertex_handle vbb, + Exact_predicates_tag); // REMOVAL @@ -1034,7 +1034,7 @@ insert(const Point& a, Locate_type lt, Face_handle loc, int li) if ( lt == Triangulation::EDGE && loc->is_constrained(li) ) { - if(boost::is_same::value) + if(boost::is_same::value) throw typename Tr::Intersection_of_constraints_exception(); insert_in_constrained_edge = true; @@ -1066,7 +1066,7 @@ Constrained_triangulation_plus_2:: intersect(Face_handle, int, Vertex_handle, Vertex_handle, - No_intersection_tag) + No_constraint_intersection_tag) { throw typename Tr::Intersection_of_constraints_exception(); return Vertex_handle(); @@ -1078,7 +1078,7 @@ Constrained_triangulation_plus_2:: intersect(Face_handle, int, Vertex_handle, Vertex_handle, - No_intersection_requiring_constructions_tag) + No_constraint_intersection_requiring_constructions_tag) { throw typename Tr::Intersection_of_constraints_exception(); return Vertex_handle(); From e4c0bcffa051bc7edfd6c243044634f2c3271790 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mael=20Rouxel-Labb=C3=A9?= Date: Thu, 19 Sep 2019 18:32:34 +0200 Subject: [PATCH 157/363] Update usage of intersection tags --- .../demo/Linear_cell_complex/typedefs.h | 3 +- .../Linear_cell_complex/basic_viewer.h | 1 - Nef_3/include/CGAL/Nef_3/K3_tree.h | 10 +++--- Nef_3/include/CGAL/Nef_3/SNC_point_locator.h | 10 +++--- .../Plugins/Mesh_2/Mesh_2_plugin.cpp | 18 +++++----- .../Plugins/PMP/Engrave_text_plugin.cpp | 8 ++--- .../MVC_post_processor_3.h | 17 +++++---- .../_test_cls_constrained_triangulation_2.h | 36 ++++++++++++------- ...t_cdt_2_projection_traits_special_case.cpp | 8 ++--- .../test_const_del_triangulation_2.cpp | 3 +- .../test_constrained_triangulation_2.cpp | 24 +++++++++---- .../CGAL/Triangular_expansion_visibility_2.h | 12 +++---- 12 files changed, 84 insertions(+), 66 deletions(-) diff --git a/Linear_cell_complex/demo/Linear_cell_complex/typedefs.h b/Linear_cell_complex/demo/Linear_cell_complex/typedefs.h index 572e142aa28..922fa1c654c 100644 --- a/Linear_cell_complex/demo/Linear_cell_complex/typedefs.h +++ b/Linear_cell_complex/demo/Linear_cell_complex/typedefs.h @@ -194,8 +194,7 @@ typedef CGAL::Triangulation_face_base_with_info_2 Fb1; typedef CGAL::Constrained_triangulation_face_base_2 Fb; typedef CGAL::Triangulation_data_structure_2 TDS; -// typedef CGAL::No_intersection_tag Itag; - typedef CGAL::Exact_predicates_tag Itag; +typedef CGAL::Exact_predicates_tag Itag; typedef CGAL::Constrained_Delaunay_triangulation_2 CDT; diff --git a/Linear_cell_complex/examples/Linear_cell_complex/basic_viewer.h b/Linear_cell_complex/examples/Linear_cell_complex/basic_viewer.h index 0ca4f962109..da1ad9e451a 100644 --- a/Linear_cell_complex/examples/Linear_cell_complex/basic_viewer.h +++ b/Linear_cell_complex/examples/Linear_cell_complex/basic_viewer.h @@ -223,7 +223,6 @@ class Basic_viewer : public CGAL::QGLViewer, public QOpenGLFunctions_2_1 typedef CGAL::Constrained_triangulation_face_base_2 Fb; typedef CGAL::Triangulation_data_structure_2 TDS; - // typedef CGAL::No_intersection_tag Itag; typedef CGAL::Exact_predicates_tag Itag; typedef CGAL::Constrained_Delaunay_triangulation_2 CDT; diff --git a/Nef_3/include/CGAL/Nef_3/K3_tree.h b/Nef_3/include/CGAL/Nef_3/K3_tree.h index bf211011575..21f4d3654c8 100644 --- a/Nef_3/include/CGAL/Nef_3/K3_tree.h +++ b/Nef_3/include/CGAL/Nef_3/K3_tree.h @@ -171,11 +171,11 @@ private: template class Triangulation_handler { - typedef typename CGAL::Triangulation_vertex_base_2 Vb; - typedef typename CGAL::Constrained_triangulation_face_base_2 Fb; - typedef typename CGAL::Triangulation_data_structure_2 TDS; - typedef typename CGAL::No_intersection_tag Itag; - typedef typename CGAL::Constrained_triangulation_2 CT; + typedef typename CGAL::Triangulation_vertex_base_2 Vb; + typedef typename CGAL::Constrained_triangulation_face_base_2 Fb; + typedef typename CGAL::Triangulation_data_structure_2 TDS; + typedef typename CGAL::No_constraint_intersection_requiring_constructions_tag Itag; + typedef typename CGAL::Constrained_triangulation_2 CT; typedef typename CT::Face_handle Face_handle; typedef typename CT::Finite_faces_iterator Finite_face_iterator; diff --git a/Nef_3/include/CGAL/Nef_3/SNC_point_locator.h b/Nef_3/include/CGAL/Nef_3/SNC_point_locator.h index 3babbc24689..28738aff817 100644 --- a/Nef_3/include/CGAL/Nef_3/SNC_point_locator.h +++ b/Nef_3/include/CGAL/Nef_3/SNC_point_locator.h @@ -221,11 +221,11 @@ public: template class Triangulation_handler { - typedef typename CGAL::Triangulation_vertex_base_2 Vb; - typedef typename CGAL::Constrained_triangulation_face_base_2 Fb; - typedef typename CGAL::Triangulation_data_structure_2 TDS; - typedef typename CGAL::No_intersection_tag Itag; - typedef typename CGAL::Constrained_triangulation_2 CT; + typedef typename CGAL::Triangulation_vertex_base_2 Vb; + typedef typename CGAL::Constrained_triangulation_face_base_2 Fb; + typedef typename CGAL::Triangulation_data_structure_2 TDS; + typedef typename CGAL::No_constraint_intersection_requiring_constructions_tag Itag; + typedef typename CGAL::Constrained_triangulation_2 CT; typedef typename CT::Face_handle Face_handle; typedef typename CT::Finite_faces_iterator Finite_face_iterator; diff --git a/Polyhedron/demo/Polyhedron/Plugins/Mesh_2/Mesh_2_plugin.cpp b/Polyhedron/demo/Polyhedron/Plugins/Mesh_2/Mesh_2_plugin.cpp index c007f78408f..4eb543bf0de 100644 --- a/Polyhedron/demo/Polyhedron/Plugins/Mesh_2/Mesh_2_plugin.cpp +++ b/Polyhedron/demo/Polyhedron/Plugins/Mesh_2/Mesh_2_plugin.cpp @@ -257,15 +257,15 @@ private: // wait cursor QApplication::setOverrideCursor(Qt::WaitCursor); - typedef ProjectionTraits Gt; - typedef CGAL::Delaunay_mesh_vertex_base_2 Vb; - typedef CGAL::Delaunay_mesh_face_base_2 Fm; - typedef CGAL::Triangulation_face_base_with_info_2 Fb; - typedef CGAL::Triangulation_data_structure_2 TDS; - typedef CGAL::No_intersection_tag Tag; - typedef CGAL::Constrained_Delaunay_triangulation_2 CDT; - typedef CGAL::Delaunay_mesh_size_criteria_2 Criteria; - typedef CGAL::Delaunay_mesher_2 Mesher; + typedef ProjectionTraits Gt; + typedef CGAL::Delaunay_mesh_vertex_base_2 Vb; + typedef CGAL::Delaunay_mesh_face_base_2 Fm; + typedef CGAL::Triangulation_face_base_with_info_2 Fb; + typedef CGAL::Triangulation_data_structure_2 TDS; + typedef CGAL::No_constraint_intersection_requiring_constructions_tag Tag; + typedef CGAL::Constrained_Delaunay_triangulation_2 CDT; + typedef CGAL::Delaunay_mesh_size_criteria_2 Criteria; + typedef CGAL::Delaunay_mesher_2 Mesher; QTime time; // global timer time.start(); diff --git a/Polyhedron/demo/Polyhedron/Plugins/PMP/Engrave_text_plugin.cpp b/Polyhedron/demo/Polyhedron/Plugins/PMP/Engrave_text_plugin.cpp index fbd416ee949..9d9f937cbe1 100644 --- a/Polyhedron/demo/Polyhedron/Plugins/PMP/Engrave_text_plugin.cpp +++ b/Polyhedron/demo/Polyhedron/Plugins/PMP/Engrave_text_plugin.cpp @@ -105,11 +105,11 @@ struct Top typedef EPICK Gt; typedef CGAL::Triangulation_vertex_base_2 Vb; -typedef CGAL::Triangulation_face_base_with_info_2 Fbb; +typedef CGAL::Triangulation_face_base_with_info_2 Fbb; typedef CGAL::Constrained_triangulation_face_base_2 Fb; -typedef CGAL::Triangulation_data_structure_2 TDS; -typedef CGAL::No_intersection_tag Tag; -typedef CGAL::Constrained_Delaunay_triangulation_2 CDT; +typedef CGAL::Triangulation_data_structure_2 TDS; +typedef CGAL::No_constraint_intersection_requiring_constructions_tag Tag; +typedef CGAL::Constrained_Delaunay_triangulation_2 CDT; //Parameterization and text displaying class ParamItem : public QGraphicsItem diff --git a/Surface_mesh_parameterization/include/CGAL/Surface_mesh_parameterization/MVC_post_processor_3.h b/Surface_mesh_parameterization/include/CGAL/Surface_mesh_parameterization/MVC_post_processor_3.h index 1daced092cc..14354576b32 100644 --- a/Surface_mesh_parameterization/include/CGAL/Surface_mesh_parameterization/MVC_post_processor_3.h +++ b/Surface_mesh_parameterization/include/CGAL/Surface_mesh_parameterization/MVC_post_processor_3.h @@ -137,17 +137,16 @@ private: // Types used for the convexification of the mesh // Each triangulation vertex is associated its corresponding vertex_descriptor - typedef CGAL::Triangulation_vertex_base_with_info_2 Vb; - // Each triangultaion face is associated a color (inside/outside information) - typedef CGAL::Triangulation_face_base_with_info_2 Fb; - typedef CGAL::Constrained_triangulation_face_base_2 Cfb; - typedef CGAL::Triangulation_data_structure_2 TDS; - typedef CGAL::No_intersection_tag Itag; + typedef CGAL::Triangulation_vertex_base_with_info_2 Vb; + // Each triangulation face is associated a color (inside/outside information) + typedef CGAL::Triangulation_face_base_with_info_2 Fb; + typedef CGAL::Constrained_triangulation_face_base_2 Cfb; + typedef CGAL::Triangulation_data_structure_2 TDS; + typedef CGAL::No_constraint_intersection_requiring_constructions_tag Itag; // Can choose either a triangulation or a Delaunay triangulation - typedef CGAL::Constrained_triangulation_2 CT; -// typedef CGAL::Constrained_Delaunay_triangulation_2 CT; + typedef CGAL::Constrained_triangulation_2 CT; +// typedef CGAL::Constrained_Delaunay_triangulation_2 CT; // Private fields private: 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 60d25f3fb0f..d7419f80846 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 @@ -52,24 +52,36 @@ _test_cdt_throwing(const Pt& p0, const Pt& p1, const Pt& p2, const Pt& p3, // There must have been an intersection assert(intersection_type != NO_INTERSECTION); - // If the intersection requires no construction, then only 'no_intersection_tag' throws - if(intersection_type == INTERSECTION_WITHOUT_CONSTRUCTION) { - assert((boost::is_same::value)); - } else { + // If the intersection requires no construction, then only 'No_constraint_intersection_tag' throws + if(intersection_type == INTERSECTION_WITHOUT_CONSTRUCTION) + { + assert((boost::is_same::value)); + } + else // threw and it's not a construction-less intersection ---> real intersection + { assert(intersection_type == INTERSECTION); - assert((boost::is_same::value) || - (boost::is_same::value)); + assert((boost::is_same::value) || +#ifndef CGAL_NO_DEPRECATED_CODE + (boost::is_same::value) || +#endif + (boost::is_same::value)); } return; } - if(intersection_type == INTERSECTION_WITHOUT_CONSTRUCTION) { - // Even with an intersection without construction, 'No_intersection_tag' should throw - assert(!(boost::is_same::value)); - } else if(intersection_type == INTERSECTION) { - assert(!(boost::is_same::value) && - !(boost::is_same::value)); + if(intersection_type == INTERSECTION_WITHOUT_CONSTRUCTION) + { + // Even with an intersection without construction, 'No_constraint_intersection_tag' should have thrown + assert(!(boost::is_same::value)); + } + else if(intersection_type == INTERSECTION) + { + assert(!(boost::is_same::value) && +#ifndef CGAL_NO_DEPRECATED_CODE + !(boost::is_same::value) && +#endif + !(boost::is_same::value)); } } diff --git a/Triangulation_2/test/Triangulation_2/test_cdt_2_projection_traits_special_case.cpp b/Triangulation_2/test/Triangulation_2/test_cdt_2_projection_traits_special_case.cpp index f37eb4174a1..26693b95a28 100644 --- a/Triangulation_2/test/Triangulation_2/test_cdt_2_projection_traits_special_case.cpp +++ b/Triangulation_2/test/Triangulation_2/test_cdt_2_projection_traits_special_case.cpp @@ -29,10 +29,10 @@ bool test(std::string test_name) std::cerr << "Testing " << test_name << std::endl; const unsigned nb_input_points = sizeof(input)/sizeof(vec); - typedef CGAL::Constrained_triangulation_face_base_2 CDT_2_fb; - typedef CGAL::Triangulation_vertex_base_2 CDT_2_vb; - typedef CGAL::Triangulation_data_structure_2 CDT_2_tds; - typedef CGAL::No_intersection_tag CDT_2_itag; + typedef CGAL::Constrained_triangulation_face_base_2 CDT_2_fb; + typedef CGAL::Triangulation_vertex_base_2 CDT_2_vb; + typedef CGAL::Triangulation_data_structure_2 CDT_2_tds; + typedef CGAL::No_constraint_intersection_requiring_constructions_tag CDT_2_itag; typedef CGAL::Constrained_Delaunay_triangulation_2 CDT_2; diff --git a/Triangulation_2/test/Triangulation_2/test_const_del_triangulation_2.cpp b/Triangulation_2/test/Triangulation_2/test_const_del_triangulation_2.cpp index 2ef4cd90a17..3f1c18b5d73 100644 --- a/Triangulation_2/test/Triangulation_2/test_const_del_triangulation_2.cpp +++ b/Triangulation_2/test/Triangulation_2/test_const_del_triangulation_2.cpp @@ -30,9 +30,8 @@ template class CGAL::Constrained_Delaunay_triangulation_2; int main() { - std::cout << "Testing constrained_Delaunay_triangulation "<< std::endl; - std::cout << " with No_intersection_tag : " << std::endl; + std::cout << " with No_constraint_intersection_requiring_constructions_tag : " << std::endl; typedef CGAL::Constrained_Delaunay_triangulation_2 CDt2; _test_cls_const_Del_triangulation(CDt2()); diff --git a/Triangulation_2/test/Triangulation_2/test_constrained_triangulation_2.cpp b/Triangulation_2/test/Triangulation_2/test_constrained_triangulation_2.cpp index 4af4b90c470..64851021f7b 100644 --- a/Triangulation_2/test/Triangulation_2/test_constrained_triangulation_2.cpp +++ b/Triangulation_2/test/Triangulation_2/test_constrained_triangulation_2.cpp @@ -22,6 +22,8 @@ #define CGAL_NO_CDT_2_WARNING +#include + #include #include @@ -33,16 +35,24 @@ template class CGAL::Constrained_triangulation_2; int main() { std::cout << "Testing constrained_triangulation "<< std::endl; - std::cout << " with No_intersection_tag : " << std::endl; - typedef CGAL::Constrained_triangulation_2 Ct; - _test_cls_constrained_triangulation(Ct()); - - std::cout << "Testing constrained_triangulation "<< std::endl; - std::cout << " with No_intersection_requiring_constructions_tag : " << std::endl; - typedef CGAL::No_intersection_requiring_constructions_tag CItag; + std::cout << " with No_constraint_intersection_tag : " << std::endl; + typedef CGAL::No_constraint_intersection_tag CItag; typedef CGAL::Constrained_triangulation_2 Ctwoc; _test_cls_constrained_triangulation(Ctwoc()); + std::exit(1); + + std::cout << "Testing constrained_triangulation "<< std::endl; + std::cout << " with No_constraint_intersection_requiring_constructions_tag (default): " << std::endl; + +#ifndef CGAL_NO_DEPRECATED_CODE + typedef CGAL::No_intersection_tag CDItag; + typedef CGAL::Constrained_triangulation_2 Ct; +#else + typedef CGAL::Constrained_triangulation_2 Ct; +#endif + _test_cls_constrained_triangulation(Ct()); + std::cout << "Testing constrained_triangulation "<< std::endl; std::cout << " with Exact_predicates_tag : " << std::endl; typedef CGAL::Triangulation_vertex_base_2 Vb; diff --git a/Visibility_2/include/CGAL/Triangular_expansion_visibility_2.h b/Visibility_2/include/CGAL/Triangular_expansion_visibility_2.h index a878bd2b96f..9956dd7c32c 100644 --- a/Visibility_2/include/CGAL/Triangular_expansion_visibility_2.h +++ b/Visibility_2/include/CGAL/Triangular_expansion_visibility_2.h @@ -75,13 +75,13 @@ public: typedef CGAL::Tag_true Supports_simple_polygon_category; private: - typedef CGAL::Triangulation_vertex_base_2 Vb; - typedef CGAL::Constrained_triangulation_face_base_2 Fb; - typedef CGAL::Triangulation_data_structure_2 TDS; - typedef CGAL::No_intersection_tag Itag; - typedef CGAL::Constrained_Delaunay_triangulation_2 CDT; + typedef CGAL::Triangulation_vertex_base_2 Vb; + typedef CGAL::Constrained_triangulation_face_base_2 Fb; + typedef CGAL::Triangulation_data_structure_2 TDS; + typedef CGAL::No_constraint_intersection_requiring_constructions_tag Itag; + typedef CGAL::Constrained_Delaunay_triangulation_2 CDT; - typedef std::pair Constraint; + typedef std::pair Constraint; // Functor to create edge constraints for the CDT out of Halfedges struct Make_constraint From ea8e6f3c98af541287301b3cd5687420e4e15735 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mael=20Rouxel-Labb=C3=A9?= Date: Thu, 19 Sep 2019 18:32:58 +0200 Subject: [PATCH 158/363] Update CDT2 intersection tag documentation --- .../Constrained_Delaunay_triangulation_2.h | 13 +++++--- .../CGAL/Constrained_triangulation_2.h | 32 ++++++++++++++++--- .../doc/Triangulation_2/Triangulation_2.txt | 14 +++++--- .../CGAL/Constrained_triangulation_2.h | 2 +- 4 files changed, 46 insertions(+), 15 deletions(-) diff --git a/Triangulation_2/doc/Triangulation_2/CGAL/Constrained_Delaunay_triangulation_2.h b/Triangulation_2/doc/Triangulation_2/CGAL/Constrained_Delaunay_triangulation_2.h index 85295f0243f..311210184b8 100644 --- a/Triangulation_2/doc/Triangulation_2/CGAL/Constrained_Delaunay_triangulation_2.h +++ b/Triangulation_2/doc/Triangulation_2/CGAL/Constrained_Delaunay_triangulation_2.h @@ -34,11 +34,16 @@ and has then to be also a model of the concept \tparam Tds must be a model of `TriangulationDataStructure_2`or `Default`. \tparam Itag allows to select if intersecting constraints are supported and how they are handled. -- `No_intersection_tag` if intersections of -input constraints are disallowed, +- `No_constraint_intersection_tag` if intersections of +input constraints are disallowed, except for the configuration of a single common extremity; +- `No_constraint_intersection_requiring_constructions_tag` if intersections of +input constraints are disallowed, except if no actual construction is needed to represent the intersection. +For example, if two constraints intersect in a 'T'-like junction, the intersection point is one of +the constraints' extremity and as such, no construction is in fact needed. Other similar configurations include +overlapping segments, common extremities, or equal constraints. - `Exact_predicates_tag` allows intersections between input constraints and is to be used when the traits class provides exact -predicates but approximate constructions of the intersection points, +predicates but approximate constructions of the intersection points; - `Exact_intersections_tag` allows intersections between input constraints and is to be used in conjunction with an exact arithmetic type. @@ -71,7 +76,7 @@ the default for and the default for the triangulation data structure parameter is the class `Triangulation_data_structure_2< CGAL::Triangulation_vertex_base_2, Constrained_triangulation_face_base_2 >`. -The default intersection tag is `No_intersection_tag`. +The default intersection tag is `No_constraint_intersection_requiring_constructions_tag`. \cgalHeading{Types} diff --git a/Triangulation_2/doc/Triangulation_2/CGAL/Constrained_triangulation_2.h b/Triangulation_2/doc/Triangulation_2/CGAL/Constrained_triangulation_2.h index 181dc976ff6..5ce9bc25611 100644 --- a/Triangulation_2/doc/Triangulation_2/CGAL/Constrained_triangulation_2.h +++ b/Triangulation_2/doc/Triangulation_2/CGAL/Constrained_triangulation_2.h @@ -5,10 +5,29 @@ namespace CGAL { /*! \ingroup PkgTriangulation2TriangulationClasses +\deprecated This class is deprecated since \cgal 5.1 as it was ambiguous. Users should instead +use the tags `No_constraint_intersection_tag` and `No_constraint_intersection_requiring_constructions_tag`, +depending on their needs. + Intersection tag for constrained triangulations, when input constraints do not intersect. */ struct No_intersection_tag{}; +/*! +\ingroup PkgTriangulation2TriangulationClasses + +Intersection tag for constrained triangulations, when input constraints are not allowed to intersect +except at a single common extremity. +*/ +struct No_constraint_intersection_tag{}; + +/*! +\ingroup PkgTriangulation2TriangulationClasses + +Intersection tag for constrained triangulations, when input constraints are not allowed to intersect +except if the intersection does not require any new point construction. +*/ +struct No_constraint_intersection_requiring_constructions_tag{}; /*! \ingroup PkgTriangulation2TriangulationClasses @@ -99,8 +118,11 @@ of the concept `TriangulationDataStructure_2` or `Default`. which serves to choose between the different strategies to deal with constraints intersections. \cgal provides three valid types for this parameter: -- `No_intersection_tag` disallows intersections of -input constraints, +- `No_constraint_intersection_tag` disallows intersections of input constraints +except for the case of a single common extremity, +- `No_constraint_intersection_requiring_constructions_tag` disallows intersections of input constraints +except for configurations where the intersection can be represented without requiring the construction +of a new point (e.g. overlapping constraints), - `Exact_predicates_tag` is to be used when the traits class provides exact predicates but approximate constructions of the @@ -130,7 +152,7 @@ the default for and the default for the triangulation data structure parameter is the class `Triangulation_data_structure_2 < Triangulation_vertex_base_2, Constrained_triangulation_face_base_2 >`. -The default intersection tag is `No_intersection_tag`. +The default intersection tag is `No_constraint_intersection_requiring_constructions_tag`. \sa `CGAL::Triangulation_2` \sa `TriangulationDataStructure_2` @@ -344,8 +366,8 @@ template std::istream& operator>>(std::istream& is,Constrained_triangulation_2 Ct& ct); /*! Exception used by constrained triangulations configured with -the tag `No_intersection_tag`. It is thrown upon insertion of a constraint -that is intersecting an already inserted constraint in its interior. +the tags `No_constraint_intersection_tag` or `No_constraint_intersection_requiring_constructions_tag` +when the insertion of a new constraint would break the respective conditions associated to each tag. */ class Intersection_of_constraints_exception; } /* end namespace CGAL */ diff --git a/Triangulation_2/doc/Triangulation_2/Triangulation_2.txt b/Triangulation_2/doc/Triangulation_2/Triangulation_2.txt index 742ea922347..584c1927185 100644 --- a/Triangulation_2/doc/Triangulation_2/Triangulation_2.txt +++ b/Triangulation_2/doc/Triangulation_2/Triangulation_2.txt @@ -842,8 +842,13 @@ The third parameter `Itag` is the intersection tag which serves to choose how intersecting constraints are dealt with. This parameter has to be instantiated by one of the following classes: -- `No_intersection_tag` when input constraints do not -intersect +- `No_constraint_intersection_tag` if intersections of +input constraints are disallowed, except for the configuration of a single common extremity; +- `No_constraint_intersection_requiring_constructions_tag` if intersections of +input constraints are disallowed, except if no actual construction is needed to represent the intersection. +For example, if two constraints intersect in a 'T'-like junction, the intersection point is one of +the constraints' extremity and as such, no construction is in fact needed. Other similar configurations include +overlapping segments, common extremities, or equal constraints. - `Exact_predicates_tag` if the geometric traits class provides exact predicates but approximate constructions - `Exact_intersections_tag` when exact predicates @@ -941,9 +946,8 @@ As in the case of constrained triangulations, the third parameter `Itag` is the intersection tag and serves to choose how intersecting constraints are dealt with. It can be instantiated with one of the following -classes: `No_intersection_tag`, -`Exact_predicates_tag`, -`Exact_intersections_tag` +classes: `No_constraint_intersection_tag`, `No_constraint_intersection_requiring_constructions_tag` +`Exact_predicates_tag`, or `Exact_intersections_tag` (see Section \ref Section_2D_Triangulations_Constrained). A constrained Delaunay triangulation is not a Delaunay diff --git a/Triangulation_2/include/CGAL/Constrained_triangulation_2.h b/Triangulation_2/include/CGAL/Constrained_triangulation_2.h index 099053f220b..0602a0e8b72 100644 --- a/Triangulation_2/include/CGAL/Constrained_triangulation_2.h +++ b/Triangulation_2/include/CGAL/Constrained_triangulation_2.h @@ -52,7 +52,7 @@ struct No_constraint_intersection_requiring_constructions_tag{}; struct Exact_intersections_tag{}; // to be used with an exact number type struct Exact_predicates_tag{}; // to be used with filtered exact number -// This tag was deprecated in favor of `No_consNo_constraint_intersection_requiring_constructions_tagint_intersection_requiring_constructions_tag` +// This was deprecated in favor of `No_consNo_constraint_intersection_requiring_constructions_tagint_intersection_requiring_constructions_tag` // due to an inaccuracy between the code and the documenation. struct CGAL_DEPRECATED No_intersection_tag : public No_constraint_intersection_requiring_constructions_tag From 371f4bbf3f5f37f2a55b1545f9b41979858d4244 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mael=20Rouxel-Labb=C3=A9?= Date: Fri, 20 Sep 2019 17:20:15 +0200 Subject: [PATCH 159/363] Progress on Manual improvements --- .../Documentation/Configuration_variables.txt | 12 +- .../doc/Documentation/Installation.txt | 186 +++++++++++-- Documentation/doc/Documentation/License.txt | 72 +++++ .../doc/Documentation/Preliminaries.txt | 77 ------ .../doc/Documentation/Third_party.txt | 88 +++---- Documentation/doc/Documentation/Usage.txt | 247 +++++++----------- .../doc/Documentation/cmakelist_script.txt | 39 +++ Documentation/doc/Documentation/main.txt | 2 +- 8 files changed, 418 insertions(+), 305 deletions(-) create mode 100644 Documentation/doc/Documentation/License.txt create mode 100644 Documentation/doc/Documentation/cmakelist_script.txt diff --git a/Documentation/doc/Documentation/Configuration_variables.txt b/Documentation/doc/Documentation/Configuration_variables.txt index 7403a1ded71..eec18702b94 100644 --- a/Documentation/doc/Documentation/Configuration_variables.txt +++ b/Documentation/doc/Documentation/Configuration_variables.txt @@ -1,9 +1,7 @@ /*! -\page configurationvariables Summary of CGAL's Configuration Variables +\page configurationvariables Summary of %CGAL's Configuration Variables \cgalAutoToc -\author %CGAL Editorial Board - \section installation_summary Summary of CGAL's Configuration Variables @@ -295,18 +293,18 @@ environment variable is sufficient. \subsection installation_tbb TBB Library -If \sc{Tbb} is not automatically found, the user must set the `TBBROOT` +If \sc{Tbb} is not automatically found, the user must set the `TBB_ROOT` environment variable. The environment variable `TBB_ARCH_PLATFORM=/` must be set. `` is `ia32` or `intel64`. `` describes the Linux kernel, gcc version or Visual Studio version -used. It should be set to what is used in `$TBBROOT/lib/`. +used. It should be set to what is used in `$TBB_ROOT/lib/`. -For windows users, the folder `TBBROOT/bin//` should be added to the `PATH` variable. +For windows users, the folder `TBB_ROOT/bin//` should be added to the `PATH` variable. Note that the variables in the table below are being used. | Variable | Description | Type | | :- | :- | :- | -| `TBBROOT` | Directory of \sc{Tbb} default installation | Environment | +| `TBB_ROOT` | Directory of \sc{Tbb} default installation | Environment | | `TBB_INCLUDE_DIRS` | Directory containing the `tbb/tbb.h` file | CMake | | `TBB_LIBRARY_DIRS` | Directory(ies) containing the compiled TBB libraries | CMake | | `TBB_LIBRARIES` | Full pathnames of the compiled TBB libraries (both release and debug versions, using "optimized" and "debug" CMake keywords). Note that if the debug versions are not found, the release versions will be used instead for the debug mode. | CMake | diff --git a/Documentation/doc/Documentation/Installation.txt b/Documentation/doc/Documentation/Installation.txt index 82899c3489b..344ece43ff5 100644 --- a/Documentation/doc/Documentation/Installation.txt +++ b/Documentation/doc/Documentation/Installation.txt @@ -1,18 +1,32 @@ /*! \page installation Installation \cgalAutoToc -\authors Eric Berberich, Joachim Reichel, and Fernando Cacciola Since \cgal version 5.0, \cgal is header-only be default, which means that there is no need to compile and install anything before it can be used. However, the dependencies of \cgal might still need to be installed. -\section seclibraries CGAL Libraries +This page is a step-by-step description of how to configure, build, and install \cgal, +in case you do not wish to use the (enabled by default) header-only mode of \cgal. +It is also possible to install \cgal using package managers on some operating systems, +see Section \ref sseccgalmacosxe. + +\section installation_configwithcmake Configuring CGAL with CMake + +Before building anything using \cgal you have to choose the compiler/linker, +set compiler and linker flags, specify which +third-party libraries you want to use and where they can be found, and +which \cgal libraries you want to build. Gathering +all this information is called configuration. +The end of the process is marked by the generation of a makefile or a +Visual \cpp solution and project file that you can use to build \cgal. + +\subsection seclibraries CGAL Libraries \cgal is split into four libraries. During configuration, you can select the libraries that you would like to build by setting a CMake variable of the form WITH_. By default all are switched `ON`. All activated libraries are build after -configuration; see \ref secbuilding +configuration; see \ref secbuilding. We next list the libraries and essential 3rd party software (see \ref secessential3rdpartysoftware) for each library: @@ -20,20 +34,11 @@ We next list the libraries and essential 3rd party software | Library | CMake Variable | Functionality | Dependencies | | :-------- | :------------- | :------------ | :----------- | | `%CGAL` | none | Main library | \sc{Gmp}, \sc{Mpfr}, \sc{Boost} (headers) | -| `CGAL_Core` | `WITH_CGAL_Core` | The CORE library for algebraic numbers.\cgalFootnote{CGAL_Core is not part of \cgal, but a custom version of the \sc{Core} library distributed by \cgal for the user convenience and it has it's own license.} | \sc{Gmp} and \sc{Mpfr} | -| `CGAL_ImageIO` | `WITH_CGAL_ImageIO` | Utilities to read and write image files | \sc{zlib}, \sc{Vtk}(optional) | +| `CGAL_Core` | `WITH_CGAL_Core` | The %CORE library for algebraic numbers.\cgalFootnote{CGAL_Core is not part of \cgal, but a custom version of the \sc{Core} library distributed by \cgal for the user convenience and it has it's own license.} | \sc{Gmp} and \sc{Mpfr} | +| `CGAL_ImageIO` | `WITH_CGAL_ImageIO` | Utilities to read and write image files | \sc{zlib}, \sc{Vtk} (optional) | | `CGAL_Qt5` | `WITH_CGAL_Qt5` | `QGraphicsView` support for \sc{Qt}5-based demos | \sc{Qt}5 | -\subsection installation_debug Debug vs. Release - -The CMake variable `CMAKE_BUILD_TYPE` indicates how to build -the libraries. It accepts the values `Release` or -`Debug`. The default is `Release` and should be kept, unless you want to debug -your program. - -This is not an issue for solution/project files, as there the user selects the build type from within the IDE. - -\subsection installation_static Static vs. Shared Libraries +\subsubsection installation_static Static vs. Shared Libraries Shared libraries, also called dynamic-link libraries, are built by default (`.dll` on Windows, `.so` on Linux, `.dylib` on MacOS). You @@ -41,17 +46,121 @@ can choose to produce static libraries instead by setting the CMake variable `BUILD_SHARED_LIBS` to `FALSE`. If you use `cmake-gui`, a tick box for that variable is available to set it. -\section installation_examples CGAL Examples and Demos +\subsection installation_examples CGAL Examples and Demos \cgal is distributed with a large collection of examples and demos. By default, these are not configured along with the \cgal libraries, unless you set the variables `WITH_examples=ON` and/or `WITH_demos=ON`. - -Nevertheless, even when configured with \cgal, they are not automatically built along with the libraries. +Additionally, even when configured with \cgal, they are not automatically built along with the libraries. You must build the `examples` or `demos` targets (or IDE projects) explicitly. -If you do not plan to compile any demos, you might skip some of the essential libraries (such as \sc{Qt}), -as the corresponding \cgal-libraries are not linked. But for -your own demos you might need these \cgal-libraries. +If you do not plan to compile any demos, you may skip some of the dependencies (such as \sc{Qt}), +as the corresponding \cgal-libraries will not be used. Note, however, that your own demos +might need these \cgal-libraries and thus their dependencies. + +\subsection installation_cmakevariables CMake Variables + +The CMake variable `CMAKE_BUILD_TYPE` indicates how to build the libraries. +It accepts the values `Debug` or `Release`. Note that the default value is `Debug` as it is +default value in `CMake` and if you do not plan on debugging, it is important to set the variable +to `Release` for performance reasons. + +This is not an issue for solution/project files, since the user selects the build type +from within the IDE in this environment. + +\subsection installation_configuring_gui Configuring CGAL with the CMake GUI + +The simplest way to start the configuration is to run the graphical +user interface of CMake. We recommend to use `cmake-gui`. You must pass as +argument the root directory of \cgal. For example: + + cd CGAL-\cgalReleaseNumber + cmake-gui . # Notice the dot to indicate the current directory. + +After `cmake-gui` opens, press 'Configure'. +A dialog will pop up and you will have to choose what shall be generated. +After you have made your choice and pressed 'Finish', you will see +the output of configuration tests in the lower portion of the application. +When these tests are done, you will see many +red entries in the upper portion of the application. Just ignore them and press 'Configure'. +By now CMake should have found many libraries and have initialized variables. +If you still find red entries, you have to provide the necessary information. +This typically happens if you have installed software at non-standard locations. +Providing information and pressing 'Configure' goes on until +all entries are grayed. You are now ready to press 'Generate'. Once this is +done, you can quit `cmake-gui`. + +\subsection installation_configuring_cmd Configuring CGAL with the cmake Command-Line Tool + +\cgalModifBegin +MERGE THAT WITH ABOVE, ADAPT TO FIT EXAMPLE CONFIG RATHER THAN CGAL CONFIG, TRIM IT +\cgalModifEnd + +Alternatively, you can run the command-line tool called +`cmake`. You pass as argument the root directory of +\cgal. For example: + + cd CGAL-\cgalReleaseNumber + cmake . # Notice the dot to indicate the current directory. + +The very first thing CMake does is to detect the compiler to use. This +detection is performed by a special CMake module called a +generator. +A CMake generator understands the build requirements for a +particular compiler/linker and generates the necessary files for that. For +example, the UNIX Makefiles generator understands the GNU chain +of tools (\gcc, ld etc.) and produces makefiles, which can be used to build a +target by a simple call to `make`. Likewise, the Visual Studio +2010 generator produces solution and project files and can be manually +launched in the VS IDE to build the target. + +Each platform has a default generator, so you only need to select one when +the default is not what you want. For example, under Windows, it is +possible to generate NMakefiles instead of Visual Studio project +files in order to build the library with `nmake`. Running +`cmake` with no parameters in a command-line prints the list of +available generators supported by your platform and CMake version. If the +generator you need is not listed there, you can try a newer +CMake version, as generators are hardcoded into CMake, and additional +generators are added with each release. + +Since the choice of the generator determines the type of build files to generate, in some cases +you choose a particular generator as a mean to choose a specific compiler (because they use different +build files). For example, the following generates solution files for +use in Visual \cpp 15.0 on a 64bit machine: + + cd CGAL-\cgalReleaseNumber + cmake -G"Visual Studio 15 2017 Win64" . + +In other cases, however, the generator doesn't directly identify a +specific compiler but a chain of tools. +For example, the `UNIX Makefiles` generator produces `makefiles` that call some auto-detected +command-line compiler, like \gcc. If you need the makefiles to use a different compiler, you need to +specify the desired compiler in the call to CMake, as in this example: + + cd CGAL-\cgalReleaseNumber + cmake -DCMAKE_CXX_COMPILER:FILEPATH=g++-9.2 . + +CMake maintains configuration parameters in so-called cmake variables, like the `CMAKE_CXX_COMPILER` +in the example above. These variables are not environment variables but CMake variables. Some of the CMake +variables represent user choices, such as `WITH_examples` or `CMAKE_BUILD_TYPE=Release`, while others +indicate the details of a third-party library, such as `Boost_INCLUDE_DIR` or the compiler flags to use, +such as `CMAKE_CXX_FLAGS`. + +The command line tool `cmake` accepts CMake variables as arguments of the form `-D:=`, as +in the example above, but this is only useful if you already know which variables need to be explicitly defined. + +\cgalAdvancedBegin +CMake keeps the variables that a user can manipulate in a +so-called CMake cache, a simple text file named +`CMakeCache.txt`, whose entries are of the form +`VARIABLE:TYPE=VALUE`. Advanced users can manually edit this file, +instead of going through the interactive configuration session. +\cgalAdvancedEnd + +The configuration process not only determines the location of the required dependencies, it also dynamically generates a +`compiler_config.h` file, which encodes the properties of your system and a special file named +`CGALConfig.cmake`, which is used to build programs using \cgal. The +purpose of this file is explained below. \section secbuilding Building CGAL @@ -83,7 +192,7 @@ Alternatively, you can build it with the command line version of the The "Debug" argument is needed because CMake creates solution files for all four configurations, and you need to explicitly choose one when building -(the other choices are Release, RelWithDebInfo and MinSizeRel). +(the other choices are `Release`, `RelWithDebInfo`, and `MinSizeRel`). \cgalAdvancedBegin The build files produced by CMake are autoconfigured. That @@ -151,6 +260,33 @@ variable explicitly at the configuration time and not when executing the The file `CGALConfig.cmake` is installed by default in `$CMAKE_INSTALLED_PREFIX/lib/``CGAL-\cgalReleaseNumber`. +\section seccmakeoutofsource Multiple Variants of Makefiles (out-of-source build) + +While you can choose between release or debug builds, and shared or static libraries, +it is not possible to generate different variants during a single configuration. You need to run CMake in a +different directory for each variant you are interested in, each with its own selection of configuration parameters. + +CMake stores the resulting makefiles and project files, along with several temporary and auxiliary files such +as the variables cache, in the directory where it is executed, called `CMAKE_BINARY_DIR`, but it +takes the source files and configuration scripts from +`CMAKE_SOURCE_DIR`. + +The binary and source directories do not need to be the same. Thus, you can configure multiple variants by creating a +distinct directory for each configuration and by running CMake from there. This is known in CMake terminology +as out-of-source configuration, as opposite to an in-source +configuration, as showed in the previous sections. + +You can, for example, generate subdirectories `CGAL-\cgalReleaseNumber``/cmake/platforms/debug` and +`CGAL-\cgalReleaseNumber``/cmake/platforms/release` for two configurations, respectively: + + mkdir CGAL-\cgalReleaseNumber/cmake/platforms/debug + cd CGAL-\cgalReleaseNumber/cmake/platforms/debug + cmake -DCMAKE_BUILD_TYPE=Debug ../../.. + + mkdir CGAL-\cgalReleaseNumber/cmake/platforms/release + cd CGAL-\cgalReleaseNumber/cmake/platforms/release + cmake -DCMAKE_BUILD_TYPE=Release ../../.. + \section secshippedcgal OS Specific Installation Some operating systems with package managers offer \cgal and its @@ -170,13 +306,11 @@ For instance in Debian/Ubuntu, use apt-get in the following way: sudo apt-get install libcgal-dev -To get the demos use +To get the demos, use: sudo apt-get install libcgal-demo -Check the \cgal-FAQ for source repository of newest releases. - -On other distributions, please consult your package manager documentation. +For other distributions, please consult your respective package manager documentation. \subsection sseccgalwindows CGAL on Windows diff --git a/Documentation/doc/Documentation/License.txt b/Documentation/doc/Documentation/License.txt new file mode 100644 index 00000000000..e6a966bd6cf --- /dev/null +++ b/Documentation/doc/Documentation/License.txt @@ -0,0 +1,72 @@ +/*! +\page cgallicensepage License +\cgalAutoToc + +\cgal is distributed under a dual license scheme, that is under the +\sc{Gpl}/\sc{Lgpl} open source license, as well as under commercial licenses. + +\cgal consists of different parts covered by different open source licenses. +In this section we explain the essence of the different licenses, as well as +the rationale why we have chosen them. + +The fact that \cgal is Open Source software does not mean that users are free +to do whatever they want with the software. Using the software means to accept +the license, which has the status of a contract between the user and the owner +of the \cgal software. + +\section licensesGPL GPL + +The \sc{Gpl} is an Open Source license that, if you distribute your software +based on \sc{Gpl}ed \cgal data structures, obliges you to distribute the +source code of your software under the \sc{Gpl}. + +The exact license terms can be found at the Free Software Foundation +web site: http://www.gnu.org/copyleft/gpl.html. + +\section licensesLGPL LGPL + +The \sc{Lgpl} is an Open Source license that obliges you to distribute +modifications you make on \cgal software accessible to the users. +In contrast to the \sc{Gpl}, there is no obligation to make the source +code of software you build on top of \sc{Lgpl}ed \cgal data structures. + +The exact license terms can be found at the Free Software Foundation web site: +http://www.gnu.org/copyleft/lesser.html. + +\section licensesRationale Rationale of the License Choice + +We have chosen the \sc{Gpl} and the \sc{Lgpl} as they are well-known +and well-understood open source licenses. The former restricts +commercial use, and the latter allows to promote software as de facto standard +so that people can build new higher level data structures on top. + +Therefore, the packages forming a foundation layer are distributed under +the \sc{Lgpl}, and the higher level packages under the \sc{Gpl}. +The package overview states for each package under which license it is distributed. + +\section licensesCommercial Commercial Licenses + +Users who cannot comply with the Open Source license terms can buy individual +data structures under various commercial licenses from GeometryFactory: +http://www.geometryfactory.com/. License fees paid by commercial +customers are reinvested in R\&D performed by the \cgal project partners, +as well as in evolutive maintenance. + +\section licenseCheck License Checking + +Users who have a commercial license for specific packages can check that +they do not accidentally use packages for which they do not have a commercial +license. The same holds for users who want to be sure that they only +use packages of \cgal released under the \sc{Lgpl}. + +To enable checking, users have to define one of the following macros: + +| Macro Name | Effect | +| :--------- | :------ | +| `CGAL_LICENSE_WARNING` | get a warning during the compilation | +| `CGAL_LICENSE_ERROR` | get an error during the compilation | + +The license checking is not a mean to control users as no information +is collected or transmitted. + +*/ diff --git a/Documentation/doc/Documentation/Preliminaries.txt b/Documentation/doc/Documentation/Preliminaries.txt index 62ddb9f4c79..c56900ea3eb 100644 --- a/Documentation/doc/Documentation/Preliminaries.txt +++ b/Documentation/doc/Documentation/Preliminaries.txt @@ -2,92 +2,15 @@ \page preliminaries Preliminaries \cgalAutoToc -\author %CGAL Editorial Board -This chapter lists the licenses -under which the \cgal datastructures and algorithms are distributed. The chapter further explains how to control inlining, thread safety, code deprecation, checking of pre- and postconditions, and how to alter the failure behavior. -\section licenseIssues License Issues - -\cgal is distributed under a dual license scheme, that is under the -\sc{Gpl}/\sc{Lgpl} open source license, as well as under commercial licenses. - -\cgal consists of different parts covered by different open source licenses. -In this section we explain the essence of the different licenses, as well as -the rationale why we have chosen them. - -The fact that \cgal is Open Source software does not mean that users are free -to do whatever they want with the software. Using the software means to accept -the license, which has the status of a contract between the user and the owner -of the \cgal software. - -\subsection licensesGPL GPL - -The \sc{Gpl} is an Open Source license that, if you distribute your software -based on \sc{Gpl}ed \cgal data structures,you are obliged to distribute the -source code of your software under the \sc{Gpl}. - -The exact license terms can be found at the Free Software Foundation -web site: http://www.gnu.org/copyleft/gpl.html. - -\subsection licensesLGPL LGPL - -The \sc{Lgpl} is an Open Source license that obliges you to distribute -modifications you make on \cgal software accessible to the users. -In contrast to the \sc{Gpl}, there is no obligation to make the source -code of software you build on top of \sc{Lgpl}ed \cgal data structures - -The exact license terms can be found at the Free Software Foundation web site: -http://www.gnu.org/copyleft/lesser.html. - -\subsection licensesRationale Rationale of the License Choice - -We have chosen the \sc{Gpl} and the \sc{Lgpl} as they are well known -and well understood open source licenses. The former restricts -commercial use, and the latter allows to promote software as de facto standard -so that people can build new higher level data structures on top. - -Therefore, the packages forming a foundation layer are distributed under -the \sc{Lgpl}, and the higher level packages under the \sc{Gpl}. -The package overview states for each package under which license -it is distributed. - -\subsection licensesCommercial Commercial Licenses - -Users who cannot comply with the Open Source license terms can buy individual -data structures under various commercial licenses from GeometryFactory: -http://www.geometryfactory.com/. License fees paid by commercial -customers are reinvested in R\&D performed by the \cgal project partners, -as well as in evolutive maintenance. - -\subsection licenseCheck License Checking - -Users who have a commercial license for specific packages can check that -they do not accidentally use packages for which they do not have a commercial -license. The same holds for users who want to be sure that they only -use packages of \cgal released under the \sc{Lgpl}. - -To enable checking, users have to define one of the following macros: - -| Macro Name | Effect | -| :--------- | :------ | -| `CGAL_LICENSE_WARNING` | get a warning during the compilation | -| `CGAL_LICENSE_ERROR` | get an error during the compilation | - - -The license checking is not a mean to control users as no information -is collected or transmitted. - - - \section markingSpecialFunctionality Marking of Special Functionality In this manual you will encounter sections marked as follows. - \subsection advanced_features Advanced Features Some functionality is considered more advanced, for example because it is diff --git a/Documentation/doc/Documentation/Third_party.txt b/Documentation/doc/Documentation/Third_party.txt index 46a0522a5b8..af75baa2d64 100644 --- a/Documentation/doc/Documentation/Third_party.txt +++ b/Documentation/doc/Documentation/Third_party.txt @@ -2,13 +2,12 @@ \page thirdparty Essential and Optional Third Party Dependencies \cgalAutoToc -\author %CGAL Editorial Board \section seccompilers Supported Compilers In order to build a program using \cgal, you need a \cpp compiler supporting C++14 or later. -\cgal \cgalReleaseNumber is supported, that is continuously tested, for the following compilers/operating systems: +\cgal \cgalReleaseNumber is supported (continuously tested) for the following compilers/operating systems: | Operating System | Compiler | | :------- | :--------------- | @@ -19,68 +18,62 @@ supporting C++14 or later. | MacOS X | \sc{Gnu} `g++` 6.3 or later\cgalFootnote{`http://gcc.gnu.org/`} | | | Apple `Clang` compiler versions 7.0.2 and 10.0.1 | -It may work for older versions of the above listed compilers. +Older versions of the above listed compilers might work, but no guarantee is provided. \section seccmake CMake -In order to configure and build the \cgal libraries, examples, and demos, -you need CMake, a cross-platform "makefile generator". -If CMake is not already installed you can obtain it from `https://cmake.org/`. +In order to configure and build the \cgal examples, demos, or libraries, +you need CMake, a cross-platform "makefile generator". CMake version 3.1 or higher is required. -This manual explains only those features of -CMake which are needed in order to build \cgal. Please refer to the -CMake documentation at `https://cmake.org/` for further details. +This manual explains only the features of CMake which are needed in order to build \cgal. +Please refer to the CMake documentation +for further details. \section secessential3rdpartysoftware Essential Third Party Libraries The focus of \cgal is on geometry, and we rely on other highly specialized libraries and software for non-geometric issues, -for instance, for numeric solvers, or visualization. We first list software -that is essential to build (all) libraries of \cgal, that is, -this software must be found during the configuration of \cgal for an -actived library of \cgal (i.e.\ WITH_=ON); -see the page \ref configurationvariables to specify the location of 3rd -party software. - -The libraries \stl (shipped with any compiler) and \sc{Boost} are essential to all components (i.e.\ libCGAL, -libCGAL_Core, libCGAL_ImageIO, and libCGAL_Qt5). +for instance for numeric solvers or visualization. We first list software +that is essential to most of \cgal, and must therefore be found during the configuration of \cgal. +The page \ref configurationvariables can be used to learn which variables can be used to specify +the location of third-party software. \subsection thirdpartystl Standard Template Library (STL) -\cgal heavily uses the \stl, and in particular adopted -many of its design ideas. You can find online +\cgal heavily uses the \stl, and in particular adopted many of its design ideas. You can find online documentation for the \stl at various web sites, for instance, `https://en.cppreference.com `, or `https://msdn.microsoft.com`. -The \stl comes with the compiler, so there is nothing to install. +The \stl comes with the compiler, and as such no installation is required. \subsection thirdpartyBoost Boost -The \sc{Boost} libraries are a set of portable C++ source libraries. Most of -\sc{Boost} libraries are header-only, but a few of them need to be compiled or +The \sc{Boost} libraries are a set of portable C++ source libraries. +Most of \sc{Boost} libraries are header-only, but a few of them need to be compiled or installed as binaries. -\cgal only requires the headers of the \sc{Boost} libraries, but some demos and examples depend on the binary library `Boost.Program_options`. +\cgal only requires the headers of the \sc{Boost} libraries, but some demos and examples +depend on the binary library `Boost.Program_options`. -As an exception, because of a bug in the \gcc compiler about the \cpp 11 +As an exception and because of a bug in the \gcc compiler about the \cpp 11 keyword `thread_local`, the `CGAL_Core` library always requires the binary library `Boost.Thread` if the \gcc compiler version 9.0 or earlier is used. In case the \sc{Boost} libraries are not installed on your system already, you -can obtain them from `https://www.boost.org/`. For Visual C++ you can download precompiled libraries +can obtain them from `https://www.boost.org/`. +For Visual C++ you can download precompiled libraries from `https://sourceforge.net/projects/boost/files/boost-binaries/`. -As on Windows there is no canonical directory for where to find -\sc{Boost}, we recommend that you define the environment variable -`BOOST_ROOT` and set it to where you have installed \sc{Boost}, e.g., -`C:\boost\boost_1_41_0`. +As there is no canonical directory for where to find \sc{Boost} on Windows, +we recommend that you define the environment variable +`BOOST_ROOT` and set it to where you have installed \sc{Boost}, e.g., `C:\boost\boost_1_69_0`. \subsection thirdpartyMPFR GMP and MPFR -The components libCGAL, libCGAL_Core, and libCGAL_Qt5 require +The components `libCGAL`, `libCGAL_Core`, and `libCGAL_Qt5` require \sc{Gmp} and \sc{Mpfr} which are libraries for multi precision integers and rational numbers, and for multi precision floating point numbers. @@ -96,22 +89,21 @@ installed is recommended. These libraries can be obtained from As Visual \cpp is not properly supported by the \sc{Gmp} and \sc{Mpfr} projects, we provide precompiled versions of \sc{Gmp} and \sc{Mpfr}, which can be downloaded with the installer -`CGAL-\cgalReleaseNumber``-Setup.exe`. +`CGAL-\cgalReleaseNumber``-Setup.exe`. -\subsection thirdpartyzlib zlib +\section secoptional3rdpartysoftware Optional Third Party Libraries -\sc{zlib} is a data compression library, and is essential for the component libCGAL_ImageIO. - -In \cgal this library is used in the examples of the \ref PkgSurfaceMesher3Ref package. - -If it is not already on your system, -for instance, on Windows, you can download it from `https://www.zlib.net/`. +Optional 3rd party software can be used by \cgal for various reasons: +Usually certain optional libraries are required to build examples and +demos shipped with \cgal or to build your own project using \cgal. +Another reason is to speed up basic tasks. \subsection thirdpartyQt Qt5 Qt is a cross-platform application and UI framework. -The component libCGAL_Qt5 requires \sc{Qt}5 installed on your system. +The component libCGAL_Qt5 is essential to run the \cgal demos and basic viewers. +It requires \sc{Qt}5 installed on your system. In case \sc{Qt} is not yet installed on your system, you can download it from `https://www.qt-project.org/`. @@ -121,13 +113,6 @@ The exhaustive list of \sc{Qt}5 components used in demos is: \sc{Qt} version 5.9.0 or later is required. -\section secoptional3rdpartysoftware Optional Third Party Libraries - -Optional 3rd party software can be used by \cgal for various reasons: -Usually certain optional libraries are required to build examples and -demos shipped with \cgal or to build your own project using \cgal. -Another reason is to speed up basic tasks. - \subsection thirdpartyLeda LEDA \leda is a library of efficient data structures and @@ -256,4 +241,13 @@ and, by extension, of surface meshes (see Section \ref BGLPartitioning of the pa More information is available on the METIS library at `http://glaros.dtc.umn.edu/gkhome/metis/metis/overview`. +\subsection thirdpartyzlib zlib + +\sc{zlib} is a data compression library, and is essential for the component libCGAL_ImageIO. + +In \cgal this library is used in the examples of the \ref PkgSurfaceMesher3Ref package. + +If it is not already on your system, +for instance, on Windows, you can download it from `https://www.zlib.net/`. + */ diff --git a/Documentation/doc/Documentation/Usage.txt b/Documentation/doc/Documentation/Usage.txt index 1e6061471e3..70d0bdaf26b 100644 --- a/Documentation/doc/Documentation/Usage.txt +++ b/Documentation/doc/Documentation/Usage.txt @@ -1,34 +1,33 @@ /*! \page usage Usage \cgalAutoToc -\authors Eric Berberich, Joachim Reichel, and Fernando Cacciola Since \cgal version 5.0, \cgal is header-only be default, which means that there is no need to compile and install anything before it can be -used. However, the dependencies of \cgal might still need to be installed. +used. However, some dependencies of \cgal might still need to be installed.
    \section usage_introduction Quick Start -Ideally, compiling an example or a demo shipped with \cgal is as simple as: +Ideally, compiling an example shipped with \cgal is as simple as: cd examples/Triangulation_2 # go to an example directory - cmake -DCGAL_DIR=$HOME/CGAL-\cgalReleaseNumber . # configure the examples + cmake -DCGAL_DIR=$HOME/CGAL-\cgalReleaseNumber -DCMAKE_BUILD_TYPE=Release . # configure the examples make # build the examples - - cd demo/Triangulation_2 # go to a demo directory - cmake -DCGAL_DIR=$HOME/CGAL-\cgalReleaseNumber . # configure the demos - make # build the demos Compiling your own program is similar: - cd /path/to/program + cd /path/to/your/program cgal_create_CMakeLists -s executable - cmake -DCGAL_DIR=$HOME/CGAL-\cgalReleaseNumber . + cmake -DCGAL_DIR=$HOME/CGAL-\cgalReleaseNumber -DCMAKE_BUILD_TYPE=Release . make -where the second line creates a file `CMakeLists.txt` (see Section \ref seccreate_cgal_CMakeLists for more details). +The script `cgal_create_CMakeLists` and its options are detailed in Section \ref manual_create_cgal_CMakeLists. -In a less ideal world, you might have to install required tools, and third party libraries. +\cgalModifBegin +Something about Windows? +\cgalModifEnd + +In a less ideal world, you might have to install the required tools and third party libraries. This is what this page is about. \section secprerequisites Prerequisites @@ -41,14 +40,15 @@ Using \cgal requires a few core components to be previously installed:
  4. \ref thirdpartyMPFR.
  5. -See Section \ref secessential3rdpartysoftware for more details on essential third party software. +Optional third-party software might be required to build examples and demos shipped with \cgal, +or to build your own project using \cgal, see Section \ref secoptional3rdpartysoftware. \section secgettingcgal Downloading CGAL You can obtain the \cgal library from https://www.cgal.org/download.html. -After you have downloaded the file `CGAL-\cgalReleaseNumber``.tar.gz` containing the +Once you have downloaded the file `CGAL-\cgalReleaseNumber``.tar.gz` containing the \cgal sources, you have to unpack it. Under a Unix-like shell, use the command: @@ -57,59 +57,51 @@ command: In both cases the directory `CGAL-\cgalReleaseNumber` will be created. This directory contains the following subdirectories: - -| Directory | Contents | -| :----------- | :----------| -| `auxiliary` | precompiled \sc{Gmp} and \sc{Mpfr} for Windows | -| `cmake/modules` | modules for finding and using libraries | -| `config` | configuration files for install script | -| `demo` | demo programs (most of them need \sc{Qt}, geomview or other third-party products) | -| `doc_html` | documentation (HTML) | -| `examples` | example programs | -| `include` | header files | -| `scripts` | some useful scripts (e.g. for creating CMakeLists.txt files) | -| `src` | source files | - +| Directory | Contents | +| :------------------------- | :----------| +| `auxiliary` (Windows only) | precompiled \sc{Gmp} and \sc{Mpfr} for Windows | +| `cmake/modules` | modules for finding and using libraries | +| `config` | configuration files for install script | +| `demo` | demo programs (most of them need \sc{Qt}, geomview or other third-party products) | +| `doc_html` | documentation (HTML) | +| `examples` | example programs | +| `include` | header files | +| `scripts` | some useful scripts (e.g. for creating CMakeLists.txt files) | +| `src` | source files | The directories `include/CGAL/CORE` and `src/CGALCore` contain a -distribution of the \sc{Core} library\cgalFootnote{`https://cs.nyu.edu/exact/`} version 1.7 for -dealing with algebraic numbers. \sc{Core} is not part of \cgal and has its +distribution of the \sc{Core} library version 1.7 for +dealing with algebraic numbers. Note that \sc{Core} is not part of \cgal and has its own license. The directory `include/CGAL/OpenNL` contains a distribution of the -Open Numerical Library which provides solvers for sparse linear systems, -especially designed for the Computer Graphics community. \sc{OpenNL} is not part -of \cgal and has its own license. +Open Numerical Library, +which provides solvers for sparse linear systems, especially designed for the Computer Graphics community. +\sc{OpenNL} is not part of \cgal and has its own license. The only documentation shipped within \cgal sources is the present installation manual. The \cgal manual can be accessed online at `https://doc.cgal.org` -or downloaded separately from +or downloaded separately at `https://github.com/CGAL/cgal/releases`. -\section subsection_headeronly Header-only Usage +\section section_headeronly Header-only Usage -Since \cgal 4.12, \cgal can be used in header-only mode, without even -configuring \cgal\. Programs using \cgal (examples, tests, demos, etc.) -must be directly configured using CMake. In this case, \cgal will be -configured at the same time. The variable `CGAL_DIR` must point to the root -directory of the \cgal source code (either the root of the unpacked release -tarball, or the root of the Git working directory). +Since \cgal 4.12, it has been possible to use \cgal in header-only mode, +without even configuring \cgal\. Programs using \cgal (examples, tests, demos, etc.) +are instead configured using CMake and \cgal will be configured at the same time. -So, using \cgal becomes now: - - cd /path/to/your/code # go to the directory of the code source using CGAL - cmake -DCGAL_DIR= . - -\subsection subsection_headeronly_dependencies CGAL Dependencies - -\cgal can be used as a header-only library, though not all its dependencies +Note that even though \cgal can be used as a header-only library, not all its dependencies are header-only. The libraries \sc{Gmp} and \sc{Mpfr}, for example, are not -header-only. +header-only. As such, these dependencies must be built or installed independently. -\subsection subsection_headeronly_pbonwindows Possible Problem on Windows +\subsection subsection_headeronly_pbonwindows Potential Issue on Windows -There is one possible problem when using \cgal in header-only mode on a Windows operating system +\cgalModifBegin +(RE)MOVE THAT? +\cgalModifEnd + +A potential issue when using \cgal in header-only mode on a Windows operating system can arise when compiling a program using several modules (executable programs or dynamic-link libraries DLL). If two different modules use the same static variable, this variable is defined independently in each of these modules. If one module modifies the value of this variable, it will not be modified @@ -119,92 +111,58 @@ the `-b boost1:boost2:...`
    Lists components ("boost1", -"boost2") of \sc{Boost} to which the executable(s) should be -linked. Valid options are, for instance, "filesystem" or "program_options". - - - -This options should suffice to create `CMakeLists.txt` script -for most directories containing programs. However, in some special -cases, it might still be required to create the script manually, for -instance, if some source files/executables need a different linking than -other source files. - -\section secconfigwithcmake Configuring CGAL with CMake - -Before building anything using \cgal you have to choose the compiler/linker, -set compiler and linker flags, specify which -third-party libraries you want to use and where they can be found, and -which \cgal libraries you want to build. Gathering -all this information is called configuration. -The end of the process is marked by the generation of a makefile or a -Visual \cpp solution and project file that you can use to build \cgal. - -\subsection installation_configuring_gui Configuring CGAL with the CMake GUI +\subsection usage_configuring_gui Configuring CGAL with the CMake GUI The simplest way to start the configuration is to run the graphical user interface of CMake. We recommend to use `cmake-gui`. You must pass as @@ -214,7 +172,7 @@ argument the root directory of \cgal. For example: cmake-gui . # Notice the dot to indicate the current directory. After `cmake-gui` opens, press 'Configure'. -A dialog will pop up and you will have to choose what shall gets generated. +A dialog will pop up and you will have to choose what shall be generated. After you have made your choice and pressed 'Finish', you will see the output of configuration tests in the lower portion of the application. When these tests are done, you will see many @@ -226,7 +184,7 @@ Providing information and pressing 'Configure' goes on until all entries are grayed. You are now ready to press 'Generate'. Once this is done, you can quit `cmake-gui`. -\subsection installation_configuring_cmd Configuring CGAL with the cmake Command-Line Tool +\subsection usage_configuring_cmd Configuring CGAL with the cmake Command-Line Tool \cgalModifBegin MERGE THAT WITH ABOVE, ADAPT TO FIT EXAMPLE CONFIG RATHER THAN CGAL CONFIG, TRIM IT @@ -299,40 +257,35 @@ The configuration process not only determines the location of the required depen `CGALConfig.cmake`, which is used to build programs using \cgal. The purpose of this file is explained below. -\section seccmakeoutofsource Multiple Variants of Makefiles (out-of-source build) +\section usage_building_program Building your Program -While you can choose between release or debug builds, and shared or static libraries, -it is not possible to generate different variants during a single configuration. You need to run CMake in a -different directory for each variant you are interested in, each with its own selection of configuration parameters. +The results of a successful configuration are build files that control the build step. +The nature of the build files depends on the generator used during configuration, but in most cases +they contain several targets, such as all the examples of the Triangulation_2 package. -CMake stores the resulting makefiles and project files, along with several temporary and auxiliary files such -as the variables cache, in the directory where it is executed, called `CMAKE_BINARY_DIR`, but it -takes the source files and configuration scripts from -`CMAKE_SOURCE_DIR`. +In a \sc{Unix}-like environment the default generator produces makefiles. +You can use the `make` command-line tool for the succeeding build step as follows: -The binary and source directories do not need to be the same. Thus, you can configure multiple variants by creating a -distinct directory for each configuration and by running CMake from there. This is known in CMake terminology -as out-of-source configuration, as opposite to an in-source -configuration, as showed in the previous sections. + cd CGAL-\cgalReleaseNumber/examples/Triangulation_2 + make # build all the examples of the Triangulation_2 package -You can, for example, generate subdirectories `CGAL-\cgalReleaseNumber``/cmake/platforms/debug` and -`CGAL-\cgalReleaseNumber``/cmake/platforms/release` for two configurations, respectively: +With generators other than `UNIX Makefiles` the resulting build files are solution and project files +which should be launched in an \sc{Ide}, such as Visual Studio or KDevelop3. They will contain the targets described +above, which you can manually build as with any other solution/project within your \sc{Ide}. - mkdir CGAL-\cgalReleaseNumber/cmake/platforms/debug - cd CGAL-\cgalReleaseNumber/cmake/platforms/debug - cmake -DCMAKE_BUILD_TYPE=Debug ../../.. +Alternatively, you can build it with the command line version of the \sc{Visual Studio Ide}: - mkdir CGAL-\cgalReleaseNumber/cmake/platforms/release - cd CGAL-\cgalReleaseNumber/cmake/platforms/release - cmake -DCMAKE_BUILD_TYPE=Release ../../.. + devenv CGAL.sln /Build Release -\section installingcgal Installing CGAL +The "Release" argument is needed because CMake creates solution files for +all four configurations, and you need to explicitly choose one when building +(the other choices are `Debug`, `RelWithDebInfo`, and `MinSizeRel`). -Although header-only makes building \cgal obsolete, it is still possible to configure, build, -and install \cgal. Head to \ref installation for more information. - -\cgalModifBegin -+ might still be required to build some cgal libs like cgal-qt? -\cgalModifEnd +\cgalAdvancedBegin +The build files produced by CMake are autoconfigured. That is, if you change any of the dependencies, +the build step automatically goes all the way back to the configuration step. This way, once the target +has been configured the very first time by invoking cmake, you don't necessarily need to invoke `cmake` +again. Rebuilding will call itself `cmake` and re-generate the build file whenever needed. +\cgalAdvancedEnd */ diff --git a/Documentation/doc/Documentation/cmakelist_script.txt b/Documentation/doc/Documentation/cmakelist_script.txt new file mode 100644 index 00000000000..cfa5a0e52c3 --- /dev/null +++ b/Documentation/doc/Documentation/cmakelist_script.txt @@ -0,0 +1,39 @@ +/*! + +\page manual_create_cgal_CMakeLists Creating a CMake Script for a Program Using %CGAL + +To compile a program that is not shipped with \cgal, it is recommended to also rely on a CMake-supported +configuration using a `CMakeLists.txt`. The Bourne-shell script `cgal_create_CMakeLists.txt` +can be used to create such `CMakeLists.txt` files. +This script resides in the `CGAL-\cgalReleaseNumber``/scripts` directory. +Executing `cgal_create_CMakeLists.txt` in an application directory creates a +`CMakeLists.txt` containing rules to build the contained +application(s). Three command line options determine details of the +configuration. + +
    +
    `-s source`
    If this parameter is given the script will +create a single executable for 'source' linked with +compilations of all other source files +(`*.cc`, `*.cp`, `*.cxx`, `*.cpp`, `*.CPP`, `*.c++`, or `*.C`). +This behaviour is usually needed for (graphical) demos. + +If the parameter is not given, the script creates one executable for each given +source file. +
    `-c com1:com2:...`
    Lists components ("com1", +"com2") of \cgal to which the executable(s) should be linked. Valid components are \cgal's +libraries (i.e.\ "Core", "ImageIO", and "Qt5"). An example is `-c Core`. + +
    `-b boost1:boost2:...`
    Lists components ("boost1", +"boost2") of \sc{Boost} to which the executable(s) should be +linked. Valid options are, for instance, "filesystem" or "program_options". + +
    + +This options should suffice to create `CMakeLists.txt` script +for most directories containing programs. However, in some special +cases, it might still be required to create the script manually, for +instance, if some source files/executables need a different linking than +other source files. + +*/ diff --git a/Documentation/doc/Documentation/main.txt b/Documentation/doc/Documentation/main.txt index 22a8407f82e..761b8505a75 100644 --- a/Documentation/doc/Documentation/main.txt +++ b/Documentation/doc/Documentation/main.txt @@ -35,7 +35,7 @@ License together with Open Source software free of charge. Using %CGAL in other contexts can be done by obtaining a commercial license from [GeometryFactory](http://www.geometryfactory.com). For more details -see the \ref licenseIssues "License" page. +see the \ref cgallicensepage "License" page. Manuals for the Previous Releases ================================= From d5301515c718345c2e2f51f081275eb90b45987e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mael=20Rouxel-Labb=C3=A9?= Date: Fri, 20 Sep 2019 22:16:08 +0200 Subject: [PATCH 160/363] Some more progress on cleaning the package 'Documentation' --- .../cmakelist_script.txt | 5 +- .../Developer_manual/developer_manual.txt | 2 +- .../doc/Documentation/Getting_started.txt | 12 +- Documentation/doc/Documentation/License.txt | 34 +++- .../doc/Documentation/Preliminaries.txt | 49 +---- .../doc/Documentation/Third_party.txt | 2 +- .../Tutorials/Tutorial_hello_world.txt | 143 ++++++-------- Documentation/doc/Documentation/Usage.txt | 180 ++++++------------ .../Configuration_variables.txt | 0 .../{ => advanced}/Installation.txt | 58 +++--- .../doc/Documentation/advanced/advanced.txt | 8 + Documentation/doc/Documentation/main.txt | 32 ++-- 12 files changed, 225 insertions(+), 300 deletions(-) rename Documentation/doc/Documentation/{ => Developer_manual}/cmakelist_script.txt (88%) rename Documentation/doc/Documentation/{ => advanced}/Configuration_variables.txt (100%) rename Documentation/doc/Documentation/{ => advanced}/Installation.txt (93%) create mode 100644 Documentation/doc/Documentation/advanced/advanced.txt diff --git a/Documentation/doc/Documentation/cmakelist_script.txt b/Documentation/doc/Documentation/Developer_manual/cmakelist_script.txt similarity index 88% rename from Documentation/doc/Documentation/cmakelist_script.txt rename to Documentation/doc/Documentation/Developer_manual/cmakelist_script.txt index cfa5a0e52c3..47ca6a404c9 100644 --- a/Documentation/doc/Documentation/cmakelist_script.txt +++ b/Documentation/doc/Documentation/Developer_manual/cmakelist_script.txt @@ -1,11 +1,12 @@ /*! -\page manual_create_cgal_CMakeLists Creating a CMake Script for a Program Using %CGAL +\page devman_create_cgal_CMakeLists Creating a CMake Script for a Program Using %CGAL To compile a program that is not shipped with \cgal, it is recommended to also rely on a CMake-supported configuration using a `CMakeLists.txt`. The Bourne-shell script `cgal_create_CMakeLists.txt` can be used to create such `CMakeLists.txt` files. -This script resides in the `CGAL-\cgalReleaseNumber``/scripts` directory. +This script resides in the `scripts` directory of \cgal (e.g. `CGAL-\cgalReleaseNumber``/scripts` +directory if you have downloaded a tarball). Executing `cgal_create_CMakeLists.txt` in an application directory creates a `CMakeLists.txt` containing rules to build the contained application(s). Three command line options determine details of the diff --git a/Documentation/doc/Documentation/Developer_manual/developer_manual.txt b/Documentation/doc/Documentation/Developer_manual/developer_manual.txt index 7d96af6c9e6..2dbccf670fa 100644 --- a/Documentation/doc/Documentation/Developer_manual/developer_manual.txt +++ b/Documentation/doc/Documentation/Developer_manual/developer_manual.txt @@ -19,6 +19,6 @@ - \subpage devman_testing - \subpage devman_submission - \subpage devman_info +- \subpage devman_create_cgal_CMakeLists - \subpage deprecated - */ diff --git a/Documentation/doc/Documentation/Getting_started.txt b/Documentation/doc/Documentation/Getting_started.txt index a9ea3882e0b..c97361772d6 100644 --- a/Documentation/doc/Documentation/Getting_started.txt +++ b/Documentation/doc/Documentation/Getting_started.txt @@ -1,14 +1,12 @@ /*! \page general_intro Getting Started -- \subpage usage describes how to use %CGAL - -- \subpage manual gives an idea where you should look for documentation. - The documentation for a class, may be spread over manual pages of - base classes, and reference manual pages of concepts the class is a model of. - -- \subpage preliminaries lists the licenses under which the %CGAL datastructures and algorithms are distributed, how to control inlining, thread safety, code deprecation, checking of pre- and postconditions, and how to alter the failure behavior. +- \subpage usage describes how to use %CGAL. - \subpage thirdparty lists the third party libraries on which %CGAL depends, or for which %CGAL provides interfaces. +- \subpage manual gives an idea where you should look for documentation. + +- \subpage preliminaries lists how to control inlining, thread safety, code deprecation, checking of pre- and postconditions, and how to alter the failure behavior. + */ diff --git a/Documentation/doc/Documentation/License.txt b/Documentation/doc/Documentation/License.txt index e6a966bd6cf..fddf4a1bd8f 100644 --- a/Documentation/doc/Documentation/License.txt +++ b/Documentation/doc/Documentation/License.txt @@ -1,5 +1,5 @@ /*! -\page cgallicensepage License +\page license License \cgalAutoToc \cgal is distributed under a dual license scheme, that is under the @@ -69,4 +69,36 @@ To enable checking, users have to define one of the following macros: The license checking is not a mean to control users as no information is collected or transmitted. +\section seccgal_version Identifying the Version of CGAL + +Every release of \cgal defines the following preprocessor macros: + +
    +
    `CGAL_VERSION_STR`
    +
    a textual description of the current release (e.g., or 3.3 or 3.2.1 or 3.2.1-I-15) as a string literal
    +
    `CGAL_VERSION_NR`
    +
    a numerical description of the current release such that more recent +releases have higher number. + +More precisely, it is defined as `1MMmmbiiii`, where `MM` is +the major release number (e.g. 03), `mm` is the minor release +number (e.g. 02), `b` is the bug-fix release number (e.g. 0), +and `iiii` is the internal release number (e.g. 0001). For +public releases, the latter is defined as 1000. Examples: for the +public release 3.2.4 this number is 1030241000; for internal release +3.2-I-1, it is 1030200001. Note that this scheme was modified around +3.2-I-30. +
    +
    `CGAL_VERSION_NUMBER(M,m,b)`
    +
    +a function macro computing the version number macro from the +M.m.b release version. Note that the internal release number is +dropped here. Example: `CGAL_VERSION_NUMBER(3,2,4)` is equal to +1030241000. +
    +
    + +The macro `CGAL_VERSION` is deprecated. It is the same as +`CGAL_VERSION_STR`, but not as a string literal. + */ diff --git a/Documentation/doc/Documentation/Preliminaries.txt b/Documentation/doc/Documentation/Preliminaries.txt index c56900ea3eb..f464d9314c1 100644 --- a/Documentation/doc/Documentation/Preliminaries.txt +++ b/Documentation/doc/Documentation/Preliminaries.txt @@ -77,19 +77,10 @@ defined, unless `BOOST_HAS_THREADS` or `_OPENMP` is defined. It is possible to force its definition on the command line, and it is possible to prevent its default definition by setting `CGAL_HAS_NO_THREADS` from the command line. +\section Preliminaries_cc0x C++14 Support -\section Preliminaries_cc0x C++11 Support - -\cgal is based on the \CC standard released in 1998 (and later refined in 2003). -A new major version of this standard has been released, and is refered to as \cpp11. -Some compilers and standard library implementations already provide some of the -functionality of this new standard, as a preview. For example, \gcc provides -a command-line switch (`-std=c++0x` or or `-std=c++11` depending on the compiler version) -which enables some of those features. - -\cgal attempts to support this mode progressively, and already makes use of -some of these features if they are available, although no extensive support has -been implemented yet. +After being based on the \CC standard released in 1998 (and later refined in 2003) for a long time, +\cgal is now based on a newer major version of the standard, C++14. \section Preliminaries_functor Functor Return Types @@ -108,40 +99,6 @@ as well as in the code. These assertions can be switched on and off per package and the user can change the error behaviour. For details see Section \ref secchecks of Chapter \ref Chapter_STL_Extensions_for_CGAL. -\section seccgal_version Identifying the Version of CGAL - -`` - -Every release of \cgal defines the following preprocessor macros: - -
    -
    `CGAL_VERSION_STR`
    -
    a textual description of the current release (e.g., or 3.3 or 3.2.1 or 3.2.1-I-15) as a string literal
    -
    `CGAL_VERSION_NR`
    -
    a numerical description of the current release such that more recent -releases have higher number. - -More precisely, it is defined as `1MMmmbiiii`, where `MM` is -the major release number (e.g. 03), `mm` is the minor release -number (e.g. 02), `b` is the bug-fix release number (e.g. 0), -and `iiii` is the internal release number (e.g. 0001). For -public releases, the latter is defined as 1000. Examples: for the -public release 3.2.4 this number is 1030241000; for internal release -3.2-I-1, it is 1030200001. Note that this scheme was modified around -3.2-I-30. -
    -
    `CGAL_VERSION_NUMBER(M,m,b)`
    -
    -a function macro computing the version number macro from the -M.m.b release version. Note that the internal release number is -dropped here. Example: `CGAL_VERSION_NUMBER(3,2,4)` is equal to -1030241000. -
    -
    - -The macro `CGAL_VERSION` is deprecated. It is the same as -`CGAL_VERSION_STR`, but not as a string literal. - \section Preliminaries_flags Compile-time Flags to Control Inlining Making functions inlined can, at times, improve the efficiency of your code. diff --git a/Documentation/doc/Documentation/Third_party.txt b/Documentation/doc/Documentation/Third_party.txt index af75baa2d64..bbc0a312a6f 100644 --- a/Documentation/doc/Documentation/Third_party.txt +++ b/Documentation/doc/Documentation/Third_party.txt @@ -36,7 +36,7 @@ The focus of \cgal is on geometry, and we rely on other highly specialized libraries and software for non-geometric issues, for instance for numeric solvers or visualization. We first list software that is essential to most of \cgal, and must therefore be found during the configuration of \cgal. -The page \ref configurationvariables can be used to learn which variables can be used to specify +The page \ref configurationvariables lists variables which can be used to specify the location of third-party software. \subsection thirdpartystl Standard Template Library (STL) diff --git a/Documentation/doc/Documentation/Tutorials/Tutorial_hello_world.txt b/Documentation/doc/Documentation/Tutorials/Tutorial_hello_world.txt index e90944007da..a3938229867 100644 --- a/Documentation/doc/Documentation/Tutorials/Tutorial_hello_world.txt +++ b/Documentation/doc/Documentation/Tutorials/Tutorial_hello_world.txt @@ -15,24 +15,23 @@ namespace CGAL { \cgalAutoToc \author %CGAL Editorial Board -This tutorial is for the %CGAL newbie, who knows C++ and has +This tutorial is for the %CGAL newbie, who knows \CC and has a basic knowledge of geometric algorithms. The first section shows how to define a point and segment class, and how to apply geometric predicates on them. The section further raises the awareness that that there are serious issues when using -floating point numbers for coordinates. In the second section -you see how the 2D convex hull function gets its input -and where it puts the result. The third section shows what -we mean with a \em Traits class, and the fourth section explains -the notion of \em concept and \em model. +floating point numbers for coordinates. In the second section, +you will meet a typical \cgal function, which computes a 2D convex hull. +The third section shows what we mean with a \em Traits class, +and the fourth section explains the notion of \em concept and \em model. \section intro_Three Three Points and One Segment -In this first example we see how to construct some points -and a segment, and we perform some basic operations on them. - -All \cgal header files are in the subdirectory `include/CGAL`. All \cgal -classes and functions are in the namespace `CGAL`. +In this first example, we demonstrate how to construct some points +and a segment, and perform some basic operations on them. + +All \cgal header files are in the subdirectory `include/CGAL`. All \cgal +classes and functions are in the namespace `CGAL`. Classes start with a capital letter, global function with a lowercase letter, and constants are all uppercase. The dimension of an object is expressed with a suffix. @@ -42,24 +41,20 @@ The kernel we have chosen for this first example uses `double` precision floating point numbers for the %Cartesian coordinates of the point. Besides the types we see \em predicates like the orientation test for -three points, and \em constructions like the distance and midpoint +three points, and \em constructions like the distance and midpoint computation. A predicate has a discrete set of possible results, whereas a construction produces either a number, or another geometric entity. - - \cgalExample{Kernel_23/points_and_segment.cpp} - - To do geometry with floating point numbers can be surprising as the next example shows. \cgalExample{Kernel_23/surprising.cpp} -When reading the code, we would assume that it prints three times "collinear". -However we obtain: +Reading the code, we could assume that it would print three times "collinear". +However the actual output is the following: \verbatim not collinear @@ -67,19 +62,18 @@ not collinear collinear \endverbatim - -As the fractions are not representable as double precision number -the collinearity test will internally compute a determinant of a 3x3 matrix +This is because these fractions are not representable as double-precision numbers, +and the collinearity test will internally compute a determinant of a 3x3 matrix which is close but not equal to zero, and hence the non collinearity for the -first two tests. +first two tests. Something similar can happen with points that perform a left turn, but due to rounding errors during the determinant computation, it seems that the points are collinear, or perform a right turn. -If you need that the numbers get interpreted at their full precision -you can use a \cgal kernel that performs exact predicates and -extract constructions. +If you must ensure that your numbers get interpreted at their full precision +you can use a \cgal kernel that performs exact predicates and +extract constructions. \cgalExample{Kernel_23/exact.cpp} @@ -95,7 +89,7 @@ In the first block the points are still not collinear, for the simple reason that the coordinates you see as text get turned into floating point numbers. When they are then turned into arbitrary precision rationals, they exactly -represent the floating point number, but not the text. +represent the floating point number, but not the text! This is different in the second block, which corresponds to reading numbers from a file. The arbitrary precision @@ -106,67 +100,63 @@ In the third block you see that constructions as midpoint constructions are exact, just as the name of the kernel type suggests. - -In many cases you will have floating point numbers that are "exact", +In many cases, you will have floating point numbers that are "exact", in the sense that they were computed by some application or obtained -from a sensor. They are not the string "0.1" or computed on the +from a sensor. They are not the string "0.1" or computed on the fly as "1.0/10.0", but a full precision floating point number. -If they are input to an algorithm that makes no constructions -you can use a kernel that provides exact predicates, but inexact -constructions. An example for that is the convex hull algorithm +If they are input to an algorithm that makes no constructions, +you can use a kernel that provides exact predicates but inexact +constructions. One such example is the convex hull algorithm which we will see in the next section. -The output is a subset of the input, and the algorithm -only compares coordinates and performs orientation tests. +The output is a subset of the input, and the algorithm +only compares coordinates and performs orientation tests. At a first glance the kernel doing exact predicates and constructions seems to be the perfect choice, but performance requirements -or limited memory resources make that it is not. Also for many +or limited memory resources make that it is not. Furthermore, for many algorithms it is irrelevant to do exact constructions. For example a surface mesh simplification algorithm that iteratively contracts -an edge, by collapsing it to the midpoint of the edge. - -Most \cgal packages explain what kind of kernel they need or support. +an edge by collapsing it to the midpoint of the edge. +Most \cgal packages explain which kind of kernel they should use or support. \section intro_convex_hull The Convex Hull of a Sequence of Points All examples in this section compute the 2D convex hull of a set of points. -We show that algorithms get their input as a begin/end iterator pair -denoting a range of points, and that they write the result, in the -example the points on the convex hull, into an output iterator. - +We show that algorithms get their input as a begin/end iterator pair +denoting a range of points, and that they write the result (in the +example the points on the convex hull) into an output iterator. \subsection intro_array The Convex Hull of Points in a Built-in Array -In the first example we have as input an array of five points. -As the convex hull of these points is a subset of the input +In the first example, we have as input an array of five points. +As the convex hull of these points is a subset of the input, it is safe to provide an array for storing the result which has the same size. \cgalExample{Convex_hull_2/array_convex_hull_2.cpp} - We saw in the previous section that \cgal comes -with several kernels. As the convex hull algorithm only makes +We have seen in the previous section that \cgal comes +with several kernels. Since the convex hull algorithm only makes comparisons of coordinates and orientation tests of input points, -we can choose a kernel that provides exact predicates, but no +we can choose a kernel that provides exact predicates, but no exact geometric constructions. The convex hull function takes three arguments, the start -and past-the-end pointer for the input, and the start pointer of the +and past-the-end pointer for the input, and the start pointer of the array for the result. The function returns the pointer into the result array just behind the last convex hull point written, so the pointer difference tells us how -many points are on the convex hull. - +many points are on the convex hull. \subsection intro_vector The Convex Hull of Points in a Vector -In the second example we replace the built-in array -by a `std::vector` of the Standard Template Library. +In the second example, we replace the built-in array +by an `std::vector` of the Standard Template Library. \cgalExample{Convex_hull_2/vector_convex_hull_2.cpp} -We put some points in the vector calling the `push_back()` +We put some points in the vector, calling the `push_back()` method of the `std::vector` class. We then call the convex hull function. The first two arguments, @@ -175,8 +165,8 @@ generalization of pointers: they can be dereferenced and incremented. The convex hull function is *generic* in the sense that it takes as input whatever can be dereferenced and incremented. -The third argument is where the result gets written to. In the -previous example we provided a pointer to allocated memory. The +The third argument is where the result gets written to. In the +previous example we provided a pointer to allocated memory. The generalization of such a pointer is the *output iterator*, which allows to increment and assign a value to the dereferenced iterator. In this example we start with an empty vector which grows as needed. @@ -185,34 +175,32 @@ iterator generated by the helper function `std::back_inserter(result)`. This output iterator does nothing when incremented, and calls `result.push_back(..)` on the assignment. - If you know the \stl, the Standard Template Library, the above makes perfect sense, as this is the way the \stl decouples algorithms from containers. If you don't know the \stl, you maybe better first familiarize yourself with its basic ideas. - \section intro_traits About Kernels and Traits Classes -In this section we show how we express the requirements that must +In this section, we show how we express the requirements that must be fulfilled in order that a function like `convex_hull_2()` can be used with an arbitrary point type. If you look at the manual page of the function `convex_hull_2()` and the other 2D convex hull algorithms, you see that they come in two -versions. In the examples we have seen so far the function that takes two +versions. In the examples we have seen so far, the function that takes two iterators for the range of input points and an output iterator for writing the result to. The second version has an additional template parameter `Traits`, and an additional parameter of this type. \code{.cpp} template -OutputIterator +OutputIterator convex_hull_2(InputIterator first, InputIterator beyond, OutputIterator result, const Traits & ch_traits) -\endcode +\endcode What are the geometric primitives a typical convex hull algorithm uses? Of course, this depends on the algorithm, so let us consider @@ -238,10 +226,8 @@ test, while `Less_xy_2` is used for sorting the points. The requirements these types have to satisfy are documented in full with the concept `ConvexHullTraits_2`. - - The types are regrouped for a simple reason. The alternative would -have been a rather lengthy function template, and an even longer +have been a rather lengthy function template, and an even longer function call. \code{.cpp} @@ -258,7 +244,7 @@ this template parameter? And why do we have template parameters at all? To answer the first question, any model of the %CGAL concept `Kernel` provides what is required by the concept `ConvexHullTraits_2`. -As for the second question, think about an application where we want to +As for the second question, think about an application where we want to compute the convex hull of 3D points projected into the `yz` plane. Using the class `Projection_traits_yz_3` this is a small modification of the previous example. @@ -277,15 +263,14 @@ traits object to store state, for example if the projection plane was given by a direction, which is hardwired in the class `Projection_traits_yz_3`. - \section intro_concept Concepts and Models -In the previous section we wrote that "Any model of the CGAL concept +In the previous section, we wrote that "Any model of the CGAL concept Kernel provides what is required by the concept ConvexHullTraits_2". A \em concept is a set of requirements on a type, namely that it has certain nested types, certain member functions, or comes with certain -free functions that take the type as it. A \em model of a concept +free functions that take the type as it. A \em model of a concept is a class that fulfills the requirements of the concept. Let's have a look at the following function. @@ -299,30 +284,30 @@ duplicate(T t) } \endcode -If you want to instantiate this function with a class `C` this -class must at least provide a copy constructor, and we -say that class `C` must be a model of `CopyConstructible`. +If you want to instantiate this function with a class `C`, this +class must at least provide a copy constructor, and we +say that class `C` must be a model of `CopyConstructible`. A singleton class does not fulfill this requirment. -Another example is the function +Another example is the function: \code{.cpp} -template +template T& std::min(const T& a, const T& b) { return (a `std::iterator_traits`
    must exist (or the generic template must be applicable). @@ -333,11 +318,9 @@ Tutorial and Reference" by Nicolai M. Josuttis from Addison-Wesley, or "Generic Programming and the STL" by Matthew H. Austern for the \stl and its notion of *concepts* and *models*. -Other resources for \cgal are the rest of the \ref tutorials "tutorials" - and the user support page at -https://www.cgal.org/. +Other resources for \cgal are the rest of the \ref tutorials "tutorials" +and the user support page at https://www.cgal.org/. */ } /* namespace CGAL */ - diff --git a/Documentation/doc/Documentation/Usage.txt b/Documentation/doc/Documentation/Usage.txt index 70d0bdaf26b..43794617ca6 100644 --- a/Documentation/doc/Documentation/Usage.txt +++ b/Documentation/doc/Documentation/Usage.txt @@ -21,7 +21,7 @@ Compiling your own program is similar: cmake -DCGAL_DIR=$HOME/CGAL-\cgalReleaseNumber -DCMAKE_BUILD_TYPE=Release . make -The script `cgal_create_CMakeLists` and its options are detailed in Section \ref manual_create_cgal_CMakeLists. +The script `cgal_create_CMakeLists` and its options are detailed in Section \ref devman_create_cgal_CMakeLists. \cgalModifBegin Something about Windows? @@ -118,144 +118,74 @@ to configure, build, and install \cgal. Head over to \ref installation for more however advised by the \cgal project to use the much simpler header-only mode, and the present page assumes that this configuration is being used. -\section usage_configuring_cgal Configuring your Program +\section usage_configuring Configuring your Program Before building anything using \cgal you have to choose the compiler/linker, set compiler and linker flags, specify which third-party libraries you want to use and where they can be found. Gathering all this information is called configuration. The end of the process is marked by the generation of a makefile or a Visual \cpp solution and project file that you can use -to build your program. Configuring a program such as a \cgal example amounts to: +to build your program. + +CMake maintains configuration parameters in so-called cmake variables, like the `CMAKE_CXX_COMPILER` +in the example above. These variables are not environment variables but CMake variables. +Some of the CMake variables represent user choices, such as `CMAKE_BUILD_TYPE`, +whereas others indicate the details of a third-party library, such as `Boost_INCLUDE_DIR` +or the compiler flags to use, such as `CMAKE_CXX_FLAGS`. + +In a typical installation of dependencies, almost all CMake variables will be set automatically; +users need only to provide the variable `CGAL_DIR`, which must point to the root directory +of the \cgal source code (either the root of the unpacked release tarball, or the root +of the Git working directory). +It is also strongly recommended to set the build type to `Release` for performance reasons +if no debugging is intended. Users should thus run: cd CGAL-\cgalReleaseNumber/examples/Triangulation_2 - cmake -DCGAL_DIR=$HOME/CGAL-\cgalReleaseNumber . + cmake -DCGAL_DIR=$HOME/CGAL-\cgalReleaseNumber -CMAKE_BUILD_TYPE=Release . -The required `CMakeLists.txt` is already provided for all shipped examples and demos of \cgal. -For other programs, CMake can also be used to configure and build user programs, -but one has to provide the `CMakeLists.txt` script either manually, or with the help of a -shell-script that is described in Section \ref manual_create_cgal_CMakeLists. For a user program -`executable.cpp`, this then ideally resumes to: +\subsection usage_configuring_cmake_gui Specifying Missing Dependencies + +This configuration might however fail if CMake fails to find all the required dependencies. +This might typically happen if you have installed dependencies at non-standard locations. +Although the command line tool `cmake` accepts CMake variables as arguments of the form +`-D:=`, this is only useful if you already know which variables +need to be explicitly defined. or this reason, the simplest way to manually set the missing variables +is to run the graphical user interface of CMake, `cmake-gui`. + + cd CGAL-\cgalReleaseNumber/examples/Triangulation_2 + cmake-gui -DCGAL_DIR=$HOME/CGAL-\cgalReleaseNumber -CMAKE_BUILD_TYPE=Release . + +After the `CMake` window opens, press 'Configure'. A dialog will pop up and you will have to choose +what shall be generated. After you have made your choice and pressed 'Finish', you will see +the output of configuration tests in the lower portion of the application. +Once these tests are done, you will see many red entries in the upper portion of the application. +Just ignore them, and press 'Configure' again. By now, CMake should have found most required +libraries and have initialized variables. + +If red entries are still present, you must provide the necessary information (paths/values). +When all entries have been appropriately filled and lines are gray, you are now ready to press 'Generate', +and to exit `cmake-gui` afterwards. + +\subsection usage_configuring_external Configuring an External Program + +Running `cmake` (or `cmake-gui`) requires a `CMakeLists.txt` file. This file is automatically provided +for all shipped examples and demos of \cgal. For other programs, CMake can also be used to configure +and build user programs, but one has to provide the corresponding `CMakeLists.txt`. +This script can be generated either manually, or with the help of a shell-script, +see Section \ref devman_create_cgal_CMakeLists. Using this shell-script, +the process of configuring a user's program called `executable.cpp` amounts to: cd /path/to/your/program cgal_create_CMakeLists -s executable - cmake -DCGAL_DIR=$HOME/CGAL-\cgalReleaseNumber . + cmake -DCGAL_DIR=$HOME/CGAL-\cgalReleaseNumber -CMAKE_BUILD_TYPE=Release . -Note that in both examples we have specified the `CGAL_DIR` variable, which must point -to the root directory of the \cgal source code (either the root of the unpacked release tarball, -or the root of the Git working directory). +\subsection usage_configuring_advanced_cmake Advanced Configuration Options -\cgalModifBegin -TMP -Note that in both examples we have specified the `CGAL_DIR` variable: during configuration -of the \cgal libraries a file named `CGALConfig.cmake` is generated in \cgal's root directory -(in contrast to \cgal's source directory that has been used for installation). -This file contains the definitions of several CMake variables that summarize the -configuration of \cgal. -In order to configure a program, you need to indicate the location of this config file -in the CMake variable `CGAL_DIR` (as indicated in the example above). -`CGAL_DIR` can also be an environment variable. +CMake keeps the variables that a user can manipulate in a so-called CMake cache, a simple text file +named `CMakeCache.txt`, whose entries are of the form `VARIABLE:TYPE=VALUE`. Advanced users can manually +edit this file, instead of going through the interactive configuration session. -Setting `CGAL_DIR` makes particular sense if having multiple -out-of-source builds of \cgal as in Section \ref seccmakeoutofsource. - -TMP If you have installed \cgal, `CGAL_DIR` must afterwards be set to -`$CMAKE_INSTALLED_PREFIX/lib/CGAL`. Note that \cgal is -recommended to be installed in release mode when using it to build programs. -\cgalModifEnd - -\subsection usage_configuring_gui Configuring CGAL with the CMake GUI - -The simplest way to start the configuration is to run the graphical -user interface of CMake. We recommend to use `cmake-gui`. You must pass as -argument the root directory of \cgal. For example: - - cd CGAL-\cgalReleaseNumber - cmake-gui . # Notice the dot to indicate the current directory. - -After `cmake-gui` opens, press 'Configure'. -A dialog will pop up and you will have to choose what shall be generated. -After you have made your choice and pressed 'Finish', you will see -the output of configuration tests in the lower portion of the application. -When these tests are done, you will see many -red entries in the upper portion of the application. Just ignore them and press 'Configure'. -By now CMake should have found many libraries and have initialized variables. -If you still find red entries, you have to provide the necessary information. -This typically happens if you have installed software at non-standard locations. -Providing information and pressing 'Configure' goes on until -all entries are grayed. You are now ready to press 'Generate'. Once this is -done, you can quit `cmake-gui`. - -\subsection usage_configuring_cmd Configuring CGAL with the cmake Command-Line Tool - -\cgalModifBegin -MERGE THAT WITH ABOVE, ADAPT TO FIT EXAMPLE CONFIG RATHER THAN CGAL CONFIG, TRIM IT -\cgalModifEnd - -Alternatively, you can run the command-line tool called -`cmake`. You pass as argument the root directory of -\cgal. For example: - - cd CGAL-\cgalReleaseNumber - cmake . # Notice the dot to indicate the current directory. - -The very first thing CMake does is to detect the compiler to use. This -detection is performed by a special CMake module called a -generator. -A CMake generator understands the build requirements for a -particular compiler/linker and generates the necessary files for that. For -example, the UNIX Makefiles generator understands the GNU chain -of tools (\gcc, ld etc.) and produces makefiles, which can be used to build a -target by a simple call to `make`. Likewise, the Visual Studio -2010 generator produces solution and project files and can be manually -launched in the VS IDE to build the target. - -Each platform has a default generator, so you only need to select one when -the default is not what you want. For example, under Windows, it is -possible to generate NMakefiles instead of Visual Studio project -files in order to build the library with `nmake`. Running -`cmake` with no parameters in a command-line prints the list of -available generators supported by your platform and CMake version. If the -generator you need is not listed there, you can try a newer -CMake version, as generators are hardcoded into CMake, and additional -generators are added with each release. - -Since the choice of the generator determines the type of build files to generate, in some cases -you choose a particular generator as a mean to choose a specific compiler (because they use different -build files). For example, the following generates solution files for -use in Visual \cpp 15.0 on a 64bit machine: - - cd CGAL-\cgalReleaseNumber - cmake -G"Visual Studio 15 2017 Win64" . - -In other cases, however, the generator doesn't directly identify a -specific compiler but a chain of tools. -For example, the `UNIX Makefiles` generator produces `makefiles` that call some auto-detected -command-line compiler, like \gcc. If you need the makefiles to use a different compiler, you need to -specify the desired compiler in the call to CMake, as in this example: - - cd CGAL-\cgalReleaseNumber - cmake -DCMAKE_CXX_COMPILER:FILEPATH=g++-4.7 . - -CMake maintains configuration parameters in so-called cmake variables, like the `CMAKE_CXX_COMPILER` -in the example above. These variables are not environment variables but CMake variables. Some of the CMake -variables represent user choices, such as `WITH_examples` or `CMAKE_BUILD_TYPE=Release`, while others -indicate the details of a third-party library, such as `Boost_INCLUDE_DIR` or the compiler flags to use, -such as `CMAKE_CXX_FLAGS`. - -The command line tool `cmake` accepts CMake variables as arguments of the form `-D:=`, as -in the example above, but this is only useful if you already know which variables need to be explicitly defined. - -\cgalAdvancedBegin -CMake keeps the variables that a user can manipulate in a -so-called CMake cache, a simple text file named -`CMakeCache.txt`, whose entries are of the form -`VARIABLE:TYPE=VALUE`. Advanced users can manually edit this file, -instead of going through the interactive configuration session. -\cgalAdvancedEnd - -The configuration process not only determines the location of the required dependencies, it also dynamically generates a -`compiler_config.h` file, which encodes the properties of your system and a special file named -`CGALConfig.cmake`, which is used to build programs using \cgal. The -purpose of this file is explained below. +In addition, the page \ref configurationvariables lists variables which can be used to specify +the location of third-party software while specifying depending in a command line run `cmake`. \section usage_building_program Building your Program diff --git a/Documentation/doc/Documentation/Configuration_variables.txt b/Documentation/doc/Documentation/advanced/Configuration_variables.txt similarity index 100% rename from Documentation/doc/Documentation/Configuration_variables.txt rename to Documentation/doc/Documentation/advanced/Configuration_variables.txt diff --git a/Documentation/doc/Documentation/Installation.txt b/Documentation/doc/Documentation/advanced/Installation.txt similarity index 93% rename from Documentation/doc/Documentation/Installation.txt rename to Documentation/doc/Documentation/advanced/Installation.txt index 344ece43ff5..b0615888465 100644 --- a/Documentation/doc/Documentation/Installation.txt +++ b/Documentation/doc/Documentation/advanced/Installation.txt @@ -7,9 +7,9 @@ that there is no need to compile and install anything before it can be used. However, the dependencies of \cgal might still need to be installed. This page is a step-by-step description of how to configure, build, and install \cgal, -in case you do not wish to use the (enabled by default) header-only mode of \cgal. +in case you do not wish to use the (now enabled by default) header-only mode of \cgal. It is also possible to install \cgal using package managers on some operating systems, -see Section \ref sseccgalmacosxe. +see Section \ref secspecificinstall. \section installation_configwithcmake Configuring CGAL with CMake @@ -21,6 +21,22 @@ all this information is called configuration. The end of the process is marked by the generation of a makefile or a Visual \cpp solution and project file that you can use to build \cgal. +CMake maintains configuration parameters in so-called cmake variables, like the `CMAKE_CXX_COMPILER` +in the example above. These variables are not environment variables but CMake variables. Some of the CMake +variables represent user choices, such as `CMAKE_BUILD_TYPE`, while others +indicate the details of a third-party library, such as `Boost_INCLUDE_DIR` or the compiler flags to use, +such as `CMAKE_CXX_FLAGS`. + +\subsection installation_buildtype Build Type + +The CMake variable `CMAKE_BUILD_TYPE` indicates how to build the libraries. +It accepts the values `Debug` or `Release`. Note that the default value is `Debug` as it is +default value in `CMake` and if you do not plan on debugging, it is important to set the variable +to `Release` for performance reasons. + +This is not an issue for solution/project files, since the user selects the build type +from within the IDE in this environment. + \subsection seclibraries CGAL Libraries \cgal is split into four libraries. During configuration, you can select the libraries that @@ -57,16 +73,6 @@ If you do not plan to compile any demos, you may skip some of the dependencies ( as the corresponding \cgal-libraries will not be used. Note, however, that your own demos might need these \cgal-libraries and thus their dependencies. -\subsection installation_cmakevariables CMake Variables - -The CMake variable `CMAKE_BUILD_TYPE` indicates how to build the libraries. -It accepts the values `Debug` or `Release`. Note that the default value is `Debug` as it is -default value in `CMake` and if you do not plan on debugging, it is important to set the variable -to `Release` for performance reasons. - -This is not an issue for solution/project files, since the user selects the build type -from within the IDE in this environment. - \subsection installation_configuring_gui Configuring CGAL with the CMake GUI The simplest way to start the configuration is to run the graphical @@ -91,10 +97,6 @@ done, you can quit `cmake-gui`. \subsection installation_configuring_cmd Configuring CGAL with the cmake Command-Line Tool -\cgalModifBegin -MERGE THAT WITH ABOVE, ADAPT TO FIT EXAMPLE CONFIG RATHER THAN CGAL CONFIG, TRIM IT -\cgalModifEnd - Alternatively, you can run the command-line tool called `cmake`. You pass as argument the root directory of \cgal. For example: @@ -140,12 +142,6 @@ specify the desired compiler in the call to CMake, as in this example: cd CGAL-\cgalReleaseNumber cmake -DCMAKE_CXX_COMPILER:FILEPATH=g++-9.2 . -CMake maintains configuration parameters in so-called cmake variables, like the `CMAKE_CXX_COMPILER` -in the example above. These variables are not environment variables but CMake variables. Some of the CMake -variables represent user choices, such as `WITH_examples` or `CMAKE_BUILD_TYPE=Release`, while others -indicate the details of a third-party library, such as `Boost_INCLUDE_DIR` or the compiler flags to use, -such as `CMAKE_CXX_FLAGS`. - The command line tool `cmake` accepts CMake variables as arguments of the form `-D:=`, as in the example above, but this is only useful if you already know which variables need to be explicitly defined. @@ -162,6 +158,22 @@ The configuration process not only determines the location of the required depen `CGALConfig.cmake`, which is used to build programs using \cgal. The purpose of this file is explained below. +\subsection installation_cgalconfig CGALConfig.cmake + +During configuration of the \cgal libraries a file named `CGALConfig.cmake` is generated +in \cgal's root directory (in contrast to \cgal's source directory that has been used +for installation). This file contains the definitions of several CMake variables +that summarize the configuration of \cgal. +In order to configure a program, you need to indicate the location of this config file +in the CMake variable `CGAL_DIR` (as indicated in the example above). +`CGAL_DIR` can also be an environment variable. + +Setting `CGAL_DIR` makes particular sense if having multiple +out-of-source builds of \cgal as in Section \ref seccmakeoutofsource. + +If you have installed \cgal, `CGAL_DIR` must afterwards be set to +`$CMAKE_INSTALLED_PREFIX/lib/CGAL`. + \section secbuilding Building CGAL The results of a successful configuration are build files that control the build step. @@ -287,7 +299,7 @@ You can, for example, generate subdirectories `CGAL-\cgalReleaseNumber``/cmake/p cd CGAL-\cgalReleaseNumber/cmake/platforms/release cmake -DCMAKE_BUILD_TYPE=Release ../../.. -\section secshippedcgal OS Specific Installation +\section secspecificinstall OS Specific Installation Some operating systems with package managers offer \cgal and its essential third party software through the manager, diff --git a/Documentation/doc/Documentation/advanced/advanced.txt b/Documentation/doc/Documentation/advanced/advanced.txt new file mode 100644 index 00000000000..f93f7c2b25a --- /dev/null +++ b/Documentation/doc/Documentation/advanced/advanced.txt @@ -0,0 +1,8 @@ +/*! + +\page advanced Advanced + +- \subpage configurationvariables +- \subpage installation + +*/ diff --git a/Documentation/doc/Documentation/main.txt b/Documentation/doc/Documentation/main.txt index 761b8505a75..8b0ec46a568 100644 --- a/Documentation/doc/Documentation/main.txt +++ b/Documentation/doc/Documentation/main.txt @@ -2,13 +2,15 @@ \mainpage -The goal of the \cgal Open Source Project is to provide easy access to -efficient and reliable geometric algorithms in the form of a C++ -library. +The Computational Geometry Algorithms Library (\cgal) is a software project +that provides easy access to efficient and reliable geometric algorithms +in the form of a C++ library. -The Computational Geometry Algorithms Library offers data structures -and algorithms like \ref PartTriangulationsAndDelaunayTriangulations "triangulations", \ref PartVoronoiDiagrams "Voronoi diagrams", \ref PartPolygons, \ref PartPolyhedra, \ref PartArrangements "arrangements of curves", \ref PartMeshing "mesh generation", \ref PartGeometryProcessing "geometry processing", \ref PartConvexHullAlgorithms "convex hull algorithms", to name just -a few. +\cgal offers data structures and algorithms like \ref PartTriangulationsAndDelaunayTriangulations "triangulations", +\ref PartVoronoiDiagrams "Voronoi diagrams", \ref PartPolygons, \ref PartPolyhedra, +\ref PartArrangements "arrangements of curves", \ref PartMeshing "mesh generation", +\ref PartGeometryProcessing "geometry processing", \ref PartConvexHullAlgorithms "convex hull algorithms", +to name just a few. All these data structures and algorithms operate on geometric objects like points and segments, and perform geometric tests on them. These @@ -20,14 +22,15 @@ solver for linear and quadratic programs. It further offers interfaces to third party software such as the GUI libraries Qt, Geomview, and the Boost Graph Library. -Demos and Examples -================== +Getting Started +=============== -In the distribution of the library you find the two directories *demo* -and *examples*. They contain subdirectories for the \cgal packages. -The demos use third party libraries for the graphical user interface. The -examples don't have this dependency and most examples are refered to in the -user manual. +In the distribution of the library, you will find the directories *demo* and *examples*. +They contain subdirectories for the \cgal packages. +The demos use third-party libraries for the graphical user interface. +The examples do not have this dependency and most examples are referred to in the user manual. + +Head over to the page \ref general_intro, which will guide your first steps with \cgal. License ======= @@ -35,7 +38,7 @@ License together with Open Source software free of charge. Using %CGAL in other contexts can be done by obtaining a commercial license from [GeometryFactory](http://www.geometryfactory.com). For more details -see the \ref cgallicensepage "License" page. +see the \ref license "License" page. Manuals for the Previous Releases ================================= @@ -52,6 +55,7 @@ For releases X.Y, with 3.1 <= X.Y <= 4.1 visit \endhtmlonly \subpage general_intro +\subpage advanced \subpage tutorials \subpage packages \subpage dev_manual From 3b5de6fe78b253f24090ffa0f7ebd692d2e6b45d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mael=20Rouxel-Labb=C3=A9?= Date: Mon, 23 Sep 2019 12:42:37 +0200 Subject: [PATCH 161/363] More re-organization of /Documentation --- .../Developer_manual/developer_manual.txt | 2 + .../doc/Documentation/Getting_started.txt | 4 +- .../doc/Documentation/Preliminaries.txt | 51 +---- .../doc/Documentation/Third_party.txt | 114 +++++++---- Documentation/doc/Documentation/Usage.txt | 24 +-- .../advanced/Configuration_variables.txt | 8 +- .../Documentation/advanced/Installation.txt | 181 ++++++++++-------- .../doc/Documentation/advanced/advanced.txt | 4 +- Documentation/doc/Documentation/main.txt | 3 +- Documentation/doc/Documentation/manual.txt | 57 +++++- README.md | 15 +- 11 files changed, 260 insertions(+), 203 deletions(-) diff --git a/Documentation/doc/Documentation/Developer_manual/developer_manual.txt b/Documentation/doc/Documentation/Developer_manual/developer_manual.txt index 2dbccf670fa..b229577bbbc 100644 --- a/Documentation/doc/Documentation/Developer_manual/developer_manual.txt +++ b/Documentation/doc/Documentation/Developer_manual/developer_manual.txt @@ -2,6 +2,8 @@ \page dev_manual Developer Manual +The developer manual is primarly aimed at \cgal developers, but may also be interesting to any \cgal user. + - \subpage devman_intro - \subpage devman_code_format - \subpage devman_kernels diff --git a/Documentation/doc/Documentation/Getting_started.txt b/Documentation/doc/Documentation/Getting_started.txt index c97361772d6..9c31836b258 100644 --- a/Documentation/doc/Documentation/Getting_started.txt +++ b/Documentation/doc/Documentation/Getting_started.txt @@ -1,7 +1,7 @@ /*! -\page general_intro Getting Started +\page general_intro Getting Started with %CGAL -- \subpage usage describes how to use %CGAL. +- \subpage usage describes the few steps required to build a program using %CGAL. - \subpage thirdparty lists the third party libraries on which %CGAL depends, or for which %CGAL provides interfaces. diff --git a/Documentation/doc/Documentation/Preliminaries.txt b/Documentation/doc/Documentation/Preliminaries.txt index f464d9314c1..9f23bbda960 100644 --- a/Documentation/doc/Documentation/Preliminaries.txt +++ b/Documentation/doc/Documentation/Preliminaries.txt @@ -1,53 +1,12 @@ /*! -\page preliminaries Preliminaries +\page preliminaries General Information \cgalAutoToc -The chapter further explains how to control inlining, thread safety, -code deprecation, checking of pre- and postconditions, -and how to alter the failure behavior. +The chapter explains some basic features of \cgal such as thread safety, code deprecation, +checking of pre- and postconditions and altering the failure behavior, and how to control inlining. -\section markingSpecialFunctionality Marking of Special Functionality - -In this manual you will encounter sections marked as follows. - -\subsection advanced_features Advanced Features - -Some functionality is considered more advanced, for example because it is -relatively low-level, or requires special care to be properly used. - -\cgalAdvancedBegin -Such functionality is identified this way in the manual. -\cgalAdvancedEnd - -\subsection debugging_support Debugging Support Features - -Usually related to advanced features that for example may not guarantee -class invariants, some functionality is provided that helps debugging, -for example by performing invariants checks on demand. - -\cgalDebugBegin -Such functionality is identified this way in the manual. -\cgalDebugEnd - -\subsection deprecated_code Deprecated Code - -Sometimes, the \cgal project decides that a feature is deprecated. This means -that it still works in the current release, but it will be removed in the next, -or a subsequent release. This can happen when we have found a better way to do -something, and we would like to reduce the maintenance cost of \cgal at some -point in the future. There is a trade-off between maintaining backward -compatibility and implementing new features more easily. - -In order to help users manage the changes to apply to their code, we attempt -to make \cgal code emit warnings when deprecated code is used. This can be -done using some compiler specific features. Those warnings can be disabled -by defining the macro `CGAL_NO_DEPRECATION_WARNINGS`. On top of this, we -also provide a macro, `CGAL_NO_DEPRECATED_CODE`, which, when defined, -disables all deprecated features. This allows users to easily test if their -code relies on deprecated features. - -\deprecated Such functionality is identified this way in the manual. +These concepts are further developed in the \ref dev_manual. \section Preliminaries_namespace Namespace CGAL @@ -80,7 +39,7 @@ definition by setting `CGAL_HAS_NO_THREADS` from the command line. \section Preliminaries_cc0x C++14 Support After being based on the \CC standard released in 1998 (and later refined in 2003) for a long time, -\cgal is now based on a newer major version of the standard, C++14. +\cgal is now based on a newer major version of the standard, C++14. \section Preliminaries_functor Functor Return Types diff --git a/Documentation/doc/Documentation/Third_party.txt b/Documentation/doc/Documentation/Third_party.txt index bbc0a312a6f..27a3b4301e9 100644 --- a/Documentation/doc/Documentation/Third_party.txt +++ b/Documentation/doc/Documentation/Third_party.txt @@ -21,10 +21,11 @@ supporting C++14 or later. Older versions of the above listed compilers might work, but no guarantee is provided. \section seccmake CMake +Version 3.1 or later In order to configure and build the \cgal examples, demos, or libraries, you need CMake, a cross-platform "makefile generator". -CMake version 3.1 or higher is required. + This manual explains only the features of CMake which are needed in order to build \cgal. Please refer to the CMake documentation @@ -36,8 +37,8 @@ The focus of \cgal is on geometry, and we rely on other highly specialized libraries and software for non-geometric issues, for instance for numeric solvers or visualization. We first list software that is essential to most of \cgal, and must therefore be found during the configuration of \cgal. -The page \ref configurationvariables lists variables which can be used to specify -the location of third-party software. +The page \ref configurationvariables lists CMake and environment variables which can be used to specify +the location of third-party software during configuration. \subsection thirdpartystl Standard Template Library (STL) @@ -49,6 +50,7 @@ or `h The \stl comes with the compiler, and as such no installation is required. \subsection thirdpartyBoost Boost +Version 1.48 or later The \sc{Boost} libraries are a set of portable C++ source libraries. Most of \sc{Boost} libraries are header-only, but a few of them need to be compiled or @@ -56,7 +58,6 @@ installed as binaries. \cgal only requires the headers of the \sc{Boost} libraries, but some demos and examples depend on the binary library `Boost.Program_options`. - As an exception and because of a bug in the \gcc compiler about the \cpp 11 keyword `thread_local`, the `CGAL_Core` library always requires the binary library `Boost.Thread` if the \gcc compiler version 9.0 or @@ -71,34 +72,36 @@ As there is no canonical directory for where to find \sc{Boost} on Windows, we recommend that you define the environment variable `BOOST_ROOT` and set it to where you have installed \sc{Boost}, e.g., `C:\boost\boost_1_69_0`. -\subsection thirdpartyMPFR GMP and MPFR +\subsection thirdpartyMPFR GNU Multiple Precision Arithmetic (GMP) and GNU Multiple Precision Floating-Point Reliably (MPFR) Libraries +GMP Version 4.2 or later, MPFR Version 2.2.1 or later The components `libCGAL`, `libCGAL_Core`, and `libCGAL_Qt5` require \sc{Gmp} and \sc{Mpfr} which are libraries for multi precision integers and rational numbers, and for multi precision floating point numbers. -\cgal combines floating point arithmetic with exact arithmetic, +\cgal combines floating point arithmetic with exact arithmetic in order to be efficient and reliable. \cgal has a built-in number type for that, but \sc{Gmp} and \sc{Mpfr} provide a faster solution, and we recommend to use them. -Having \sc{Gmp} version 4.2 or higher and \sc{Mpfr} version 2.2.1 or higher -installed is recommended. These libraries can be obtained from -`https://gmplib.org/` and `https://www.mpfr.org/`, respectively. - -As Visual \cpp is not properly -supported by the \sc{Gmp} and \sc{Mpfr} projects, we provide precompiled versions -of \sc{Gmp} and \sc{Mpfr}, which can be downloaded with the installer +These libraries can be obtained from `https://gmplib.org/` +and `https://www.mpfr.org/`. +Since Visual \cpp is not properly supported by the \sc{Gmp} and \sc{Mpfr} projects, +we provide precompiled versions of \sc{Gmp} and \sc{Mpfr}, which can be downloaded with the installer `CGAL-\cgalReleaseNumber``-Setup.exe`. \section secoptional3rdpartysoftware Optional Third Party Libraries Optional 3rd party software can be used by \cgal for various reasons: -Usually certain optional libraries are required to build examples and -demos shipped with \cgal or to build your own project using \cgal. -Another reason is to speed up basic tasks. +certain optional libraries might be required to build examples and +demos shipped with \cgal or to build your own project using \cgal; +another reason is to speed up basic tasks where specialized libraries can be faster than the default +version shipped with \cgal. +The page \ref configurationvariables lists CMake and environment variables which can be used to specify +the location of third-party software during configuration. \subsection thirdpartyQt Qt5 +Version 5.9.0 or later Qt is a cross-platform application and UI framework. @@ -109,11 +112,23 @@ it from `https://www.qt-project.org/`. The exhaustive list of \sc{Qt}5 components used in demos is: `Core`, `Gui`, `Help`, `OpenGL`, `Script`, `ScriptTools`, `Svg`, `Widgets`, -`qcollectiongenerator` (with `sqlite` driver plugin) and `Xml`. +`qcollectiongenerator` (with `sqlite` driver plugin), and `Xml`. -\sc{Qt} version 5.9.0 or later is required. +\subsection thirdpartyEigen Eigen +Version 3.1 or later + +\sc{Eigen} is a `C++` template library for linear algebra. \sc{Eigen} supports all +matrix sizes, various matrix decomposition methods and sparse linear solvers. + +In \cgal, \sc{Eigen} is used in many packages such as \ref PkgPoissonSurfaceReconstruction3 +or \ref PkgJetFitting3, providing sparse linear solvers and singular value decompositions. +A package dependency over \sc{Eigen} is marked on the +Package Overview page. + +The \sc{Eigen} web site is `http://eigen.tuxfamily.org`. \subsection thirdpartyLeda LEDA +Version 6.2 or later \leda is a library of efficient data structures and algorithms. Like \sc{Core}, \leda offers a real number data type. @@ -123,23 +138,24 @@ be used as an alternative to \sc{Gmp}, \sc{Mpfr}, and \sc{Core}. Free and commercial editions of \leda are available from `https://www.algorithmic-solutions.com`. -\subsection thirdpartyMPFI MPFI +\subsection thirdpartyMPFI Multiple Precision Floating-point Interval (MPFI) +Version 1.4 or later \sc{Mpfi} provides arbitrary precision interval arithmetic with intervals represented using \sc{Mpfr} reliable floating-point numbers. It is based on the libraries \sc{Gmp} and \sc{Mpfr}. In the setting of \cgal, this library is optional: it is used by some models of the -\ref PkgAlgebraicKernelDRef "Algebraic Kernel". +\ref PkgAlgebraicKernelD "Algebraic Kernel". -\sc{Mpfi} can be downloaded from `https://mpfi.gforge.inria.fr/`. Version 1.4 or higher is recommended. +\sc{Mpfi} can be downloaded from `https://mpfi.gforge.inria.fr/`. \subsection thirdpartyRS3 RS and RS3 \sc{Rs} (Real Solutions) is devoted to the study of the real roots of polynomial systems with a finite number of complex roots (including univariate polynomials). In \cgal, \sc{Rs} is used by one model of the -\ref PkgAlgebraicKernelDRef "Algebraic Kernel". +\ref PkgAlgebraicKernelD "Algebraic Kernel". \sc{Rs} is freely distributable for non-commercial use. You can download it from `http://vegas.loria.fr/rs/`. Actually, the \sc{Rs} package also includes \sc{Rs3}, the @@ -149,34 +165,21 @@ The libraries \sc{Rs} and \sc{Rs3} need \sc{Mpfi}, which can be downloaded from `https://mpfi.gforge.inria.fr/`. \subsection thirdpartyNTL NTL +Version 5.1 or later \sc{Ntl} provides data structures and algorithms for signed, arbitrary length integers, and for vectors, matrices, and polynomials over the integers and over finite fields. The optional library \sc{Ntl} is used by \cgal to speed up operations of the Polynomial package, such as GCDs. It is recommended to install \sc{Ntl} with support from \sc{Gmp}. -\sc{Ntl} can be downloaded from `https://www.shoup.net/ntl/`. Version 5.1 or higher is recommended. - -\subsection thirdpartyEigen Eigen - -\sc{Eigen} is a `C++` template library for linear algebra. \sc{Eigen} supports all -matrix sizes, various matrix decomposition methods and sparse linear solvers. - -In \cgal, \sc{Eigen} provides sparse linear solvers in the \ref PkgPoissonSurfaceReconstruction3Ref -and the \ref PkgSurfaceMeshParameterizationRef packages. - -In addition, \sc{Eigen} also provides singular value decomposition for the \ref PkgJetFitting3Ref -and the \ref PkgRidges3Ref packages. - -The \sc{Eigen} web site is `http://eigen.tuxfamily.org`. +\sc{Ntl} can be downloaded from `https://www.shoup.net/ntl/`. \subsection thirdpartyESBTL ESBTL The \sc{Esbtl} (Easy Structural Biology Template Library) is a library that allows the handling of \sc{Pdb} data. -In \cgal the \sc{Esbtl} is used in an example of the -\ref PkgSkinSurface3Ref package. +In \cgal the \sc{Esbtl} is used in an example of the \ref PkgSkinSurface3 package. It can be downloaded from `http://esbtl.sourceforge.net/`. @@ -195,7 +198,7 @@ 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 PkgPointSetProcessing3Ref package. +the \ref PkgPointSetProcessing3 package. The \sc{LASlib} web site is `https://rapidlasso.com/lastools/`. \sc{LASlib} @@ -208,7 +211,7 @@ CMake based install procedure. \sc{OpenCV} (Open Computer Vision) is a library designed for computer vision, computer graphics and machine learning. -In \cgal, \sc{OpenCV} is used by the \ref PkgClassificationRef package. +In \cgal, \sc{OpenCV} is used by the \ref PkgClassification package. The \sc{OpenCV} web site is `https://opencv.org/`. @@ -217,7 +220,7 @@ The \sc{OpenCV} web site is `https://opencv.org/`< \sc{TensorFlow} is a library designed for machine learning and deep learning. In \cgal, the C++ API of \sc{TensorFlow} is used by the \ref -PkgClassificationRef package for neural network. The C++ API can be +PkgClassification package for neural network. The C++ API can be compiled using CMake: it is distributed as part of the official package and is located in `tensorflow/contrib/cmake`. Be sure to enable and compile the following targets: @@ -229,6 +232,7 @@ enable and compile the following targets: The \sc{TensorFlow} web site is `https://www.tensorflow.org/`. \subsection thirdpartyMETIS METIS +Version 5.1 or later \sc{METIS} is a library developed by the Karypis Lab and designed to partition graphs and produce fill-reducing matrix orderings. @@ -245,9 +249,35 @@ at `http://glaro \sc{zlib} is a data compression library, and is essential for the component libCGAL_ImageIO. -In \cgal this library is used in the examples of the \ref PkgSurfaceMesher3Ref package. +In \cgal this library is used in the examples of the \ref PkgSurfaceMesher3 package. If it is not already on your system, for instance, on Windows, you can download it from `https://www.zlib.net/`. +\subsection thirdpartyCeres Ceres Solver + +\sc{Ceres} is an open source C++ library for modeling and solving large, complicated optimization problems. + +In \cgal, \sc{Ceres} is used by the \ref PkgPolygonMeshProcessingRef package for mesh smoothing, which +requires solving complex non-linear least squares problems. + +Visit the official website of the library at `ceres-solver.org` +for more information. + +\subsection thirdpartyGLPK GLPK + +\sc{GLPK} (GNU Linear Programming Kit) is a library for solving linear programming (LP), mixed integer programming (MIP), and other related problems. + +In \cgal, \sc{GLPK} provides an optional linear integer program solver in the \ref PkgPolygonalSurfaceReconstruction package. + +The \sc{GLPK} web site is `https://www.gnu.org/software/glpk/`. + +\subsection thirdpartySCIP SCIP + +\sc{SCIP} (Solving Constraint Integer Programs) is currently one of the fastest open source solvers for mixed integer programming (MIP) and mixed integer nonlinear programming (MINLP). + +In \cgal, \sc{SCIP} provides an optional linear integer program solver in the \ref PkgPolygonalSurfaceReconstruction package. + +The \sc{SCIP} web site is `http://scip.zib.de/`. + */ diff --git a/Documentation/doc/Documentation/Usage.txt b/Documentation/doc/Documentation/Usage.txt index 43794617ca6..7ba365705b4 100644 --- a/Documentation/doc/Documentation/Usage.txt +++ b/Documentation/doc/Documentation/Usage.txt @@ -2,9 +2,9 @@ \page usage Usage \cgalAutoToc -Since \cgal version 5.0, \cgal is header-only be default, which means -that there is no need to compile and install anything before it can be -used. However, some dependencies of \cgal might still need to be installed. +Since \cgal version 5.0, \cgal is header-only be default, which means +that there is no need to build or install \cgal before it can be used. +However, some dependencies of \cgal might still need to be installed. \section usage_introduction Quick Start @@ -12,7 +12,7 @@ Ideally, compiling an example shipped with \cgal is as simple as: cd examples/Triangulation_2 # go to an example directory cmake -DCGAL_DIR=$HOME/CGAL-\cgalReleaseNumber -DCMAKE_BUILD_TYPE=Release . # configure the examples - make # build the examples + make # build all Triangulation_2 examples Compiling your own program is similar: @@ -27,7 +27,7 @@ The script `cgal_create_CMakeLists` and its options are detailed in Section \ref Something about Windows? \cgalModifEnd -In a less ideal world, you might have to install the required tools and third party libraries. +In a less ideal world, you might have to install some required tools and third-party libraries. This is what this page is about. \section secprerequisites Prerequisites @@ -54,7 +54,7 @@ command: tar xzf CGAL-\cgalReleaseNumber.tar.gz -In both cases the directory `CGAL-\cgalReleaseNumber` will be created. This directory +In both cases, the directory `CGAL-\cgalReleaseNumber` will be created. This directory contains the following subdirectories: | Directory | Contents | @@ -144,8 +144,9 @@ if no debugging is intended. Users should thus run: \subsection usage_configuring_cmake_gui Specifying Missing Dependencies -This configuration might however fail if CMake fails to find all the required dependencies. -This might typically happen if you have installed dependencies at non-standard locations. +The configuration process launched above might however fail if CMake fails to find +all the required dependencies. This might typically happen if you have installed dependencies +at non-standard locations. Although the command line tool `cmake` accepts CMake variables as arguments of the form `-D:=`, this is only useful if you already know which variables need to be explicitly defined. or this reason, the simplest way to manually set the missing variables @@ -165,6 +166,10 @@ If red entries are still present, you must provide the necessary information (pa When all entries have been appropriately filled and lines are gray, you are now ready to press 'Generate', and to exit `cmake-gui` afterwards. +Note that if you decide to solve missing dependencies using the command line tool (not the recommended way), +the page \ref configurationvariables lists variables which can be used to specify +the location of third-party software. + \subsection usage_configuring_external Configuring an External Program Running `cmake` (or `cmake-gui`) requires a `CMakeLists.txt` file. This file is automatically provided @@ -184,9 +189,6 @@ CMake keeps the variables that a user can manipulate in a so-called CMake cache, named `CMakeCache.txt`, whose entries are of the form `VARIABLE:TYPE=VALUE`. Advanced users can manually edit this file, instead of going through the interactive configuration session. -In addition, the page \ref configurationvariables lists variables which can be used to specify -the location of third-party software while specifying depending in a command line run `cmake`. - \section usage_building_program Building your Program The results of a successful configuration are build files that control the build step. diff --git a/Documentation/doc/Documentation/advanced/Configuration_variables.txt b/Documentation/doc/Documentation/advanced/Configuration_variables.txt index eec18702b94..343a513afb2 100644 --- a/Documentation/doc/Documentation/advanced/Configuration_variables.txt +++ b/Documentation/doc/Documentation/advanced/Configuration_variables.txt @@ -62,13 +62,17 @@ defined by cmake. \subsection installation_misc Miscellaneous Variables +Note that the default build type is `Debug`, which should only be used to debug +and will serverly limit performances. | Variable | Description | Type | %Default Value | | :- | :- | :- | :- | -| `CMAKE_BUILD_TYPE` | Indicates type of build. Possible values are 'Debug' or 'Release' | CMake | Release | +| `CMAKE_BUILD_TYPE` | Indicates type of build. Possible values are 'Debug' or 'Release' | CMake | | +| `CMAKE_INSTALL_PREFIX`| Installation directory path | CMake | Debug | +| `CMAKE_C_COMPILER` | Full-path to the executable corresponding to the C compiler to use. | CMake | platform-dependent | | `CMAKE_CXX_COMPILER` | Full-path to the executable corresponding to the C++ compiler to use. | CMake | platform-dependent | | `CXX` | Idem | Environment | Idem | - +| `BUILD_SHARED_LIBS` | Whether to build shared or static libraries. | CMake | TRUE | \subsection installation_variables_building Variables Used Only When Building Programs (Such as Demos or Examples) diff --git a/Documentation/doc/Documentation/advanced/Installation.txt b/Documentation/doc/Documentation/advanced/Installation.txt index b0615888465..e219fb92540 100644 --- a/Documentation/doc/Documentation/advanced/Installation.txt +++ b/Documentation/doc/Documentation/advanced/Installation.txt @@ -6,14 +6,14 @@ that there is no need to compile and install anything before it can be used. However, the dependencies of \cgal might still need to be installed. -This page is a step-by-step description of how to configure, build, and install \cgal, -in case you do not wish to use the (now enabled by default) header-only mode of \cgal. +This page is a step-by-step description of how to configure, build, and install \cgal +in case you do not wish to use the - now enabled by default - header-only mode of \cgal. It is also possible to install \cgal using package managers on some operating systems, see Section \ref secspecificinstall. \section installation_configwithcmake Configuring CGAL with CMake -Before building anything using \cgal you have to choose the compiler/linker, +Before building \cgal, or anything using \cgal, you have to choose the compiler/linker, set compiler and linker flags, specify which third-party libraries you want to use and where they can be found, and which \cgal libraries you want to build. Gathering @@ -21,31 +21,22 @@ all this information is called configuration. The end of the process is marked by the generation of a makefile or a Visual \cpp solution and project file that you can use to build \cgal. -CMake maintains configuration parameters in so-called cmake variables, like the `CMAKE_CXX_COMPILER` -in the example above. These variables are not environment variables but CMake variables. Some of the CMake +CMake maintains configuration parameters in so-called cmake variables. Some of the CMake variables represent user choices, such as `CMAKE_BUILD_TYPE`, while others -indicate the details of a third-party library, such as `Boost_INCLUDE_DIR` or the compiler flags to use, +indicate the details of a third-party library, such as `Boost_INCLUDE_DIR` or which compiler flags to use, such as `CMAKE_CXX_FLAGS`. -\subsection installation_buildtype Build Type - -The CMake variable `CMAKE_BUILD_TYPE` indicates how to build the libraries. -It accepts the values `Debug` or `Release`. Note that the default value is `Debug` as it is -default value in `CMake` and if you do not plan on debugging, it is important to set the variable -to `Release` for performance reasons. - -This is not an issue for solution/project files, since the user selects the build type -from within the IDE in this environment. +The next sections first present the CMake variables related to \cgal, followed by more generic variables, +and finally the configuration and build processes. \subsection seclibraries CGAL Libraries \cgal is split into four libraries. During configuration, you can select the libraries that you would like to build by setting a CMake variable of the form WITH_. By default all -are switched `ON`. All activated libraries are build after -configuration; see \ref secbuilding. +are switched `ON`. All activated libraries are to be built after configuration. -We next list the libraries and essential 3rd party software -(see \ref secessential3rdpartysoftware) for each library: +Note that some libraries have specific dependencies in addition to the essential ones. See the page +\ref secessential3rdpartysoftware for more information. | Library | CMake Variable | Functionality | Dependencies | | :-------- | :------------- | :------------ | :----------- | @@ -54,13 +45,10 @@ We next list the libraries and essential 3rd party software | `CGAL_ImageIO` | `WITH_CGAL_ImageIO` | Utilities to read and write image files | \sc{zlib}, \sc{Vtk} (optional) | | `CGAL_Qt5` | `WITH_CGAL_Qt5` | `QGraphicsView` support for \sc{Qt}5-based demos | \sc{Qt}5 | -\subsubsection installation_static Static vs. Shared Libraries - Shared libraries, also called dynamic-link libraries, are built by default (`.dll` on Windows, `.so` on Linux, `.dylib` on MacOS). You -can choose to produce static libraries instead by setting the CMake -variable `BUILD_SHARED_LIBS` to `FALSE`. If you use -`cmake-gui`, a tick box for that variable is available to set it. +can choose to produce static libraries instead, by setting the CMake +variable `BUILD_SHARED_LIBS` to `FALSE`. \subsection installation_examples CGAL Examples and Demos @@ -71,12 +59,53 @@ You must build the `examples` or `demos` targets (or IDE projects) explicitly. If you do not plan to compile any demos, you may skip some of the dependencies (such as \sc{Qt}), as the corresponding \cgal-libraries will not be used. Note, however, that your own demos -might need these \cgal-libraries and thus their dependencies. +might need these \cgal-libraries and thus their dependencies. See the page +\ref secessential3rdpartysoftware for more information. + +\subsection installation_debugrelease Debug vs. Release + +The CMake variable `CMAKE_BUILD_TYPE` indicates how to build the libraries. +It accepts the values `Debug` or `Release`. Note that the default value is `Debug`, since it is +default value in `CMake`. If you do not plan on debugging, it is important to set the variable +to `Release` for performance reasons. + +This is however not an issue for solution/project files, since the user selects the build type +from within the IDE in this environment. + +\subsection installation_miscvariables Other CMake Variables + +There are many more variables that can be used during configuration. The most important ones are: +
      +
    • `CMAKE_INSTALL_PREFIX=` installation directory [/usr/local]
    • +
    • `CMAKE_BUILD_TYPE=` build type [Release]
    • +
    • `BUILD_SHARED_LIBS=` shared or static libraries [TRUE]
    • +
    • `CMAKE_C_COMPILER=` C compiler [gcc]
    • +
    • `CMAKE_CXX_COMPILER=` C++ compiler [g++]
    • +
    + +In case you want to add additional compiler and linker flags, you can use +
      +
    • `CGAL_CXX_FLAGS` additional compiler flags
    • +
    • `CGAL_MODULE_LINKER_FLAGS` add. linker flags (static libraries)
    • +
    • `CGAL_SHARED_LINKER_FLAGS` add. linker flags (shared libraries)
    • +
    • `CGAL_EXE_LINKER_FLAGS` add. linker flags (executables)
    • +
    + +Variants with the additional suffix "_DEBUG" and "_RELEASE" allow to set +separate values for debug and release builds. In case you do not want to add +additional flags, but to override the default flags, replace "CGAL" by +"CMAKE" in the variable names above. + +A comprehensive list of CMake variables can be found on the \ref configurationvariables page. + +Note that CMake maintains a cache name `CMakeCache.txt`. If you change options +(or your environment changes), it is best to remove that file to avoid +problems. \subsection installation_configuring_gui Configuring CGAL with the CMake GUI -The simplest way to start the configuration is to run the graphical -user interface of CMake. We recommend to use `cmake-gui`. You must pass as +The simplest way to start the configuration process is to run the graphical +user interface of CMake, `cmake-gui`. You must pass as argument the root directory of \cgal. For example: cd CGAL-\cgalReleaseNumber @@ -91,60 +120,24 @@ red entries in the upper portion of the application. Just ignore them and press By now CMake should have found many libraries and have initialized variables. If you still find red entries, you have to provide the necessary information. This typically happens if you have installed software at non-standard locations. + +If you use `cmake-gui`, a tick box for that variable is available to set it. + Providing information and pressing 'Configure' goes on until all entries are grayed. You are now ready to press 'Generate'. Once this is done, you can quit `cmake-gui`. \subsection installation_configuring_cmd Configuring CGAL with the cmake Command-Line Tool -Alternatively, you can run the command-line tool called -`cmake`. You pass as argument the root directory of -\cgal. For example: +Alternatively, you can run the command-line tool called `cmake`. +You pass as argument the root directory of \cgal. +The command line tool `cmake` accepts CMake variables as arguments of the form `-D:=`, as +in the example above, but this is only useful if you already know which variables need to be explicitly defined. +For example: cd CGAL-\cgalReleaseNumber cmake . # Notice the dot to indicate the current directory. -The very first thing CMake does is to detect the compiler to use. This -detection is performed by a special CMake module called a -generator. -A CMake generator understands the build requirements for a -particular compiler/linker and generates the necessary files for that. For -example, the UNIX Makefiles generator understands the GNU chain -of tools (\gcc, ld etc.) and produces makefiles, which can be used to build a -target by a simple call to `make`. Likewise, the Visual Studio -2010 generator produces solution and project files and can be manually -launched in the VS IDE to build the target. - -Each platform has a default generator, so you only need to select one when -the default is not what you want. For example, under Windows, it is -possible to generate NMakefiles instead of Visual Studio project -files in order to build the library with `nmake`. Running -`cmake` with no parameters in a command-line prints the list of -available generators supported by your platform and CMake version. If the -generator you need is not listed there, you can try a newer -CMake version, as generators are hardcoded into CMake, and additional -generators are added with each release. - -Since the choice of the generator determines the type of build files to generate, in some cases -you choose a particular generator as a mean to choose a specific compiler (because they use different -build files). For example, the following generates solution files for -use in Visual \cpp 15.0 on a 64bit machine: - - cd CGAL-\cgalReleaseNumber - cmake -G"Visual Studio 15 2017 Win64" . - -In other cases, however, the generator doesn't directly identify a -specific compiler but a chain of tools. -For example, the `UNIX Makefiles` generator produces `makefiles` that call some auto-detected -command-line compiler, like \gcc. If you need the makefiles to use a different compiler, you need to -specify the desired compiler in the call to CMake, as in this example: - - cd CGAL-\cgalReleaseNumber - cmake -DCMAKE_CXX_COMPILER:FILEPATH=g++-9.2 . - -The command line tool `cmake` accepts CMake variables as arguments of the form `-D:=`, as -in the example above, but this is only useful if you already know which variables need to be explicitly defined. - \cgalAdvancedBegin CMake keeps the variables that a user can manipulate in a so-called CMake cache, a simple text file named @@ -163,16 +156,8 @@ purpose of this file is explained below. During configuration of the \cgal libraries a file named `CGALConfig.cmake` is generated in \cgal's root directory (in contrast to \cgal's source directory that has been used for installation). This file contains the definitions of several CMake variables -that summarize the configuration of \cgal. -In order to configure a program, you need to indicate the location of this config file -in the CMake variable `CGAL_DIR` (as indicated in the example above). -`CGAL_DIR` can also be an environment variable. - -Setting `CGAL_DIR` makes particular sense if having multiple -out-of-source builds of \cgal as in Section \ref seccmakeoutofsource. - -If you have installed \cgal, `CGAL_DIR` must afterwards be set to -`$CMAKE_INSTALLED_PREFIX/lib/CGAL`. +that summarize the configuration of \cgal and will be essential during the configuration and +building of a program using \cgal, see Section \ref installation_buildprogram. \section secbuilding Building CGAL @@ -243,7 +228,7 @@ typing `make help | grep `. On many platforms, library pieces such as headers, docs and binaries are expected to be placed in specific locations. A typical example -being `/usr/include` and `/usr/lib` on \sc{Unix}-like +being `/usr/include` and `/usr/lib` on \sc{Unix}-like operating systems or `C:/Program Files/` on Windows. The process of placing or copying the library elements into its standard location is sometimes referred to as Installation and it is a @@ -265,13 +250,41 @@ If you use a generator that produces IDE files (for Visual Studio for instance) \cgalAdvancedBegin The files are copied into a directory tree relative to the installation directory determined by the CMake variable `CMAKE_INSTALL_PREFIX`. This variable defaults to `/usr/local` under \sc{Unix}-like operating systems -and `C:\Program Files` under Windows. If you want to install to a different location, you must override that CMake +and `C:\Program Files` under Windows. If you want to install to a different location, you must override that CMake variable explicitly at the configuration time and not when executing the install step. \cgalAdvancedEnd The file `CGALConfig.cmake` is installed by default in `$CMAKE_INSTALLED_PREFIX/lib/``CGAL-\cgalReleaseNumber`. +\section installation_buildprogram Building a Program using CGAL + +Similarly to \cgal and its libraries, compiling a program using \cgal is done in the usual +two steps of configuration and building. + +The configuration process is also done using `cmake` (or `cmake-gui`) and requires a `CMakeLists.txt` file. +This file is automatically provided for all shipped examples and demos of \cgal. +For other programs, CMake can also be used to configure +and build user programs, but one has to provide the corresponding `CMakeLists.txt`. +This script can be generated either manually, or with the help of a shell-script, +see Section \ref devman_create_cgal_CMakeLists. Using this shell-script, +the process of configuring a user's program called `executable.cpp` amounts to: + + cd /path/to/your/program + cgal_create_CMakeLists -s executable + cmake -DCGAL_DIR=XXXXXX -CMAKE_BUILD_TYPE=Release . + +In order to configure a program, you need to indicate the location of the configuration file +in the CMake variable `CGAL_DIR` (as indicated in the example above). + +If you have installed \cgal, `CGAL_DIR` must afterwards be set to `$CMAKE_INSTALLED_PREFIX/lib/CGAL`. + +The variable `CGAL_DIR` can also be an environment variable, but setting it manually makes particular sense +if having multiple out-of-source builds of \cgal as in Section \ref seccmakeoutofsource. + +Once you have successfully configured (either through `cmake` or `cmake-gui`), you are now ready +to build your program. + \section seccmakeoutofsource Multiple Variants of Makefiles (out-of-source build) While you can choose between release or debug builds, and shared or static libraries, @@ -303,7 +316,7 @@ You can, for example, generate subdirectories `CGAL-\cgalReleaseNumber``/cmake/p Some operating systems with package managers offer \cgal and its essential third party software through the manager, -for instance, Mac OS X, or some Linux distribution (e.g. Debian). +for instance, Mac OS X or some Linux distribution (e.g. Debian). For Windows, an installer is provided. \subsection sseccgalmacosxe CGAL on macOS diff --git a/Documentation/doc/Documentation/advanced/advanced.txt b/Documentation/doc/Documentation/advanced/advanced.txt index f93f7c2b25a..b6136edda22 100644 --- a/Documentation/doc/Documentation/advanced/advanced.txt +++ b/Documentation/doc/Documentation/advanced/advanced.txt @@ -2,7 +2,7 @@ \page advanced Advanced -- \subpage configurationvariables -- \subpage installation +- \subpage configurationvariables lists the various CMake variables that can be used to help find third-party dependencies. +- \subpage installation describes the (optional) process of building and installing %CGAL itself. */ diff --git a/Documentation/doc/Documentation/main.txt b/Documentation/doc/Documentation/main.txt index 8b0ec46a568..7679f65c4f9 100644 --- a/Documentation/doc/Documentation/main.txt +++ b/Documentation/doc/Documentation/main.txt @@ -48,8 +48,6 @@ For releases >= 4.2, visit [https://doc.cgal.org/X.Y](https://doc.cgal.org/4.2) For releases X.Y, with 3.1 <= X.Y <= 4.1 visit [https://doc.cgal.org/Manual/X.Y/doc_html/cgal_manual/packages.html](https://doc.cgal.org/Manual/3.1/doc_html/cgal_manual/packages.html) - - \htmlonly[block]
    \endhtmlonly @@ -59,6 +57,7 @@ For releases X.Y, with 3.1 <= X.Y <= 4.1 visit \subpage tutorials \subpage packages \subpage dev_manual +\subpage license \htmlonly[block]
    diff --git a/Documentation/doc/Documentation/manual.txt b/Documentation/doc/Documentation/manual.txt index dbada72f28d..33354eecf6d 100644 --- a/Documentation/doc/Documentation/manual.txt +++ b/Documentation/doc/Documentation/manual.txt @@ -1,17 +1,14 @@ -namespace CGAL { - /*! \page manual Organization of the Manual \cgalAutoToc \author %CGAL Editorial Board - -Organization of the Manual -========================== +\section secorganization Organization of the Manual This manual is organized in several parts covering the many domains -of computational geometry. Each part consists of several chapters, +of computational geometry. +Each part consists of several chapters, and each chapter is split into a *User Manual* and a *Reference Manual*. The User Manual gives the general idea and comes with examples. The Reference Manual presents the \sc{Api} of the various classes @@ -28,8 +25,7 @@ The scope of the search box is the package you currently look at and the packages it depends on, or it is the whole manual when you are in a top level page such as the package overview. -Organization of the Reference Manual -==================================== +\section secorganizationref Organization of the Reference Manual The \cgal library is a library of class templates. Consequently, we express the requirements on template arguments by specifying \em concepts @@ -70,6 +66,47 @@ As pointed out in Section \ref intro_concept "Concepts and Models" the notion of a \em concept is about requirements, and it can be a required global function or a required traits class. -*/ -} /* namespace CGAL */ +\section markingSpecialFunctionality Marking of Special Functionality + +In this manual, you will encounter sections marked as follows. + +\subsection advanced_features Advanced Features + +Some functionality is considered more advanced, for example because it is +relatively low-level, or requires special care to be properly used. + +\cgalAdvancedBegin +Such functionality is identified this way in the manual. +\cgalAdvancedEnd + +\subsection debugging_support Debugging Support Features + +Usually related to advanced features that for example may not guarantee +class invariants, some functionality is provided that helps debugging, +for example by performing invariants checks on demand. + +\cgalDebugBegin +Such functionality is identified this way in the manual. +\cgalDebugEnd + +\subsection deprecated_code Deprecated Code + +Sometimes, the \cgal project decides that a feature is deprecated. This means +that it still works in the current release, but it will be removed in the next, +or a subsequent release. This can happen when we have found a better way to do +something, and we would like to reduce the maintenance cost of \cgal at some +point in the future. There is a trade-off between maintaining backward +compatibility and implementing new features more easily. + +In order to help users manage the changes to apply to their code, we attempt +to make \cgal code emit warnings when deprecated code is used. This can be +done using some compiler specific features. Those warnings can be disabled +by defining the macro `CGAL_NO_DEPRECATION_WARNINGS`. On top of this, we +also provide a macro, `CGAL_NO_DEPRECATED_CODE`, which, when defined, +disables all deprecated features. This allows users to easily test if their +code relies on deprecated features. + +\deprecated Such functionality is identified this way in the manual. + +*/ diff --git a/README.md b/README.md index 95dffac80e6..024922dc3c4 100644 --- a/README.md +++ b/README.md @@ -10,8 +10,18 @@ CGAL releases ============= The primary vector of distribution of CGAL are sources tarballs, released twice a year, announced on [the web site of CGAL](https://www.cgal.org/). -The sources distributed that way can be built using the -[CGAL installation manual](https://doc.cgal.org/latest/Manual/installation.html). + +Header-only +=========== + +Since version 5.0, CGAL is header-only by default, which means +that there is **no need to build or install \cgal before it can be used**. + +Getting started with CGAL +========================= + +Head over to the [CGAL manual](https://doc.cgal.org/latest/Manual/general_intro.html) +for usage guides and tutorials that will get you started smoothly. CGAL Git repository layout ========================== @@ -32,6 +42,7 @@ or `Triangulation_3`); however some packages serve special needs: Compilation and installation ============================ + The compilation and installation of CGAL from a sources tarball are described in the [CGAL installation manual](https://doc.cgal.org/latest/Manual/installation.html) From 168463e038d9d60e982125bb093be76da830d074 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9bastien=20Loriot?= Date: Tue, 24 Sep 2019 08:51:22 +0200 Subject: [PATCH 162/363] remove extra assertion --- .../include/CGAL/Polygon_mesh_processing/remove_degeneracies.h | 1 - 1 file changed, 1 deletion(-) diff --git a/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/remove_degeneracies.h b/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/remove_degeneracies.h index 314615e295a..63b70c55c09 100644 --- a/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/remove_degeneracies.h +++ b/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/remove_degeneracies.h @@ -193,7 +193,6 @@ boost::optional get_collapse_volume(typename boost::graph_traits Date: Tue, 24 Sep 2019 09:42:06 +0200 Subject: [PATCH 163/363] Clean code --- .../remove_degeneracies.h | 114 +++++++++--------- 1 file changed, 57 insertions(+), 57 deletions(-) diff --git a/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/remove_degeneracies.h b/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/remove_degeneracies.h index 63b70c55c09..ed56cd72854 100644 --- a/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/remove_degeneracies.h +++ b/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/remove_degeneracies.h @@ -76,7 +76,7 @@ is_badly_shaped(const typename boost::graph_traits::face_descripto halfedge_descriptor res = CGAL::Polygon_mesh_processing::is_needle_triangle_face(f, tmesh, needle_threshold, np); if(res != boost::graph_traits::null_halfedge()) { - if ( edge_length(res, tmesh, np) <= collapse_threshold ) + if(edge_length(res, tmesh, np) <= collapse_threshold ) return make_array(res, null_halfedge); } else // let's not make it possible to have a face be both a cap and a needle (for now) @@ -103,7 +103,7 @@ void collect_badly_shaped_triangles(const typename boost::graph_traits::null_halfedge()) { -#ifdef CGAL_PMP_DEBUG_REMOVE_DEGENERACIES +#ifdef CGAL_PMP_DEBUG_REMOVE_DEGENERACIES std::cout << "add new needle: " << edge(res[0], tmesh) << std::endl; #endif edges_to_collapse.insert(edge(res[0], tmesh)); @@ -112,7 +112,7 @@ void collect_badly_shaped_triangles(const typename boost::graph_traits::null_halfedge()) { -#ifdef CGAL_PMP_DEBUG_REMOVE_DEGENERACIES +#ifdef CGAL_PMP_DEBUG_REMOVE_DEGENERACIES std::cout << "add new cap: " << edge(res[1],tmesh) << std::endl; #endif edges_to_flip.insert(edge(res[1], tmesh)); @@ -151,9 +151,9 @@ bool is_collapse_geometrically_valid(typename boost::graph_traits: halfedge_descriptor hi = opposite(next(h, tmesh), tmesh); std::vector triangles; - while (hi!=stop) + while(hi!=stop) { - if (!is_border(hi, tmesh)) + if(!is_border(hi, tmesh)) { Point_ref a = get(vpm, target(next(hi, tmesh), tmesh)); Point_ref b = get(vpm, source(hi, tmesh)); @@ -162,7 +162,7 @@ bool is_collapse_geometrically_valid(typename boost::graph_traits: /// @todo use a predicate typename Traits::Vector_3 n1 = CGAL::cross_product(removed-a, b-a); typename Traits::Vector_3 n2 = CGAL::cross_product(kept-a, b-a); - if ( n1*n2 <=0 ) + if(n1*n2 <=0 ) return false; } hi = opposite(next(hi, tmesh), tmesh); @@ -205,9 +205,9 @@ boost::optional get_collapse_volume(typename boost::graph_traits triangles; - while (hi!=stop) + while(hi!=stop) { - if (!is_border(hi, tmesh)) + if(!is_border(hi, tmesh)) { Point_ref a = get(vpm, target(next(hi, tmesh), tmesh)); Point_ref b = get(vpm, source(hi, tmesh)); @@ -216,7 +216,7 @@ boost::optional get_collapse_volume(typename boost::graph_traits::edge_descr boost::optional dv1 = get_collapse_volume(h, tmesh, np); boost::optional dv2 = get_collapse_volume(ho, tmesh, np); - if (dv1 != boost::none) + if(dv1 != boost::none) { - if (dv2 != boost::none) + if(dv2 != boost::none) { return *dv1 < *dv2 ? h : ho; } return h; } - if (dv2 != boost::none) + if(dv2 != boost::none) { return ho; } @@ -314,7 +314,7 @@ bool remove_almost_degenerate_faces(const FaceRange& face_range, for(face_descriptor f : face_range) internal::collect_badly_shaped_triangles(f, tmesh, edges_to_collapse, edges_to_flip, np); -#ifdef CGAL_PMP_DEBUG_REMOVE_DEGENERACIES +#ifdef CGAL_PMP_DEBUG_REMOVE_DEGENERACIES int iter = 0; #endif @@ -322,7 +322,7 @@ bool remove_almost_degenerate_faces(const FaceRange& face_range, { bool something_was_done = false; -#ifdef CGAL_PMP_DEBUG_REMOVE_DEGENERACIES +#ifdef CGAL_PMP_DEBUG_REMOVE_DEGENERACIES std::cout << edges_to_collapse.size() << " needles and " << edges_to_flip.size() << " caps" << std::endl; std::ostringstream oss; oss << "degen_cleaning_iter_" << iter++ << ".off"; @@ -340,16 +340,16 @@ bool remove_almost_degenerate_faces(const FaceRange& face_range, std::set next_edges_to_flip; // treat needles -#ifdef CGAL_PMP_DEBUG_REMOVE_DEGENERACIES_EXTRA +#ifdef CGAL_PMP_DEBUG_REMOVE_DEGENERACIES_EXTRA int kk=0; std::ofstream(std::string("tmp/n-00000.off")) << tmesh; #endif - while (!edges_to_collapse.empty()) + while(!edges_to_collapse.empty()) { edge_descriptor e = *edges_to_collapse.begin(); edges_to_collapse.erase(edges_to_collapse.begin()); -#ifdef CGAL_PMP_DEBUG_REMOVE_DEGENERACIES +#ifdef CGAL_PMP_DEBUG_REMOVE_DEGENERACIES std::cout << " treat needle: " << e << " (" << tmesh.point(source (e, tmesh)) << " --- " << tmesh.point(target(e, tmesh)) << ")" << std::endl; #endif if(CGAL::Euler::does_satisfy_link_condition(e, tmesh)) @@ -359,23 +359,23 @@ bool remove_almost_degenerate_faces(const FaceRange& face_range, CGAL_assertion(!is_border(h, tmesh)); // because extracted from a face std::array nc = internal::is_badly_shaped(face(h, tmesh), tmesh, np); - if (nc[0]!=h) + if(nc[0]!=h) { -#ifdef CGAL_PMP_DEBUG_REMOVE_DEGENERACIES +#ifdef CGAL_PMP_DEBUG_REMOVE_DEGENERACIES std::cerr << "Warning: Needle criteria no longer verified " << tmesh.point(source(e, tmesh)) << " " << tmesh.point(target(e, tmesh)) << std::endl; #endif // the opposite edge might also have been inserted in the set and might still be a needle h = opposite(h, tmesh); - if (is_border(h, tmesh) ) continue; + if(is_border(h, tmesh) ) continue; nc = internal::is_badly_shaped(face(h, tmesh), tmesh, np); - if (nc[0] != h) + if(nc[0] != h) continue; } - for (int i=0; i<2; ++i) + for(int i=0; i<2; ++i) { - if (!is_border(h, tmesh)) + if(!is_border(h, tmesh)) { edge_descriptor pe=edge(prev(h,tmesh), tmesh); edges_to_flip.erase(pe); @@ -388,9 +388,9 @@ bool remove_almost_degenerate_faces(const FaceRange& face_range, // pick the orientation of edge to keep the vertex minimizing the volume variation h = internal::get_best_edge_orientation(e, tmesh, np); - if ( h == boost::graph_traits::null_halfedge() ) + if(h == boost::graph_traits::null_halfedge() ) { -#ifdef CGAL_PMP_DEBUG_REMOVE_DEGENERACIES +#ifdef CGAL_PMP_DEBUG_REMOVE_DEGENERACIES std::cerr << "Warning: geometrically invalid edge collapse! " << tmesh.point(source(e, tmesh)) << " " << tmesh.point(target(e, tmesh)) << std::endl; @@ -401,7 +401,7 @@ bool remove_almost_degenerate_faces(const FaceRange& face_range, edges_to_flip.erase(e); next_edges_to_collapse.erase(e); // for edges added in faces incident to a vertex kept after a collapse -#ifdef CGAL_PMP_DEBUG_REMOVE_DEGENERACIES_EXTRA +#ifdef CGAL_PMP_DEBUG_REMOVE_DEGENERACIES_EXTRA std::cerr << " " << kk << " -- Collapsing " << tmesh.point(source(h, tmesh)) << " " << tmesh.point(target(h, tmesh)) << std::endl; #endif @@ -412,23 +412,23 @@ bool remove_almost_degenerate_faces(const FaceRange& face_range, //tmesh.point(v) = mp; // examine all faces incident to the vertex kept - for (halfedge_descriptor hv : halfedges_around_target(v, tmesh)) - if (!is_border(hv, tmesh)) + for(halfedge_descriptor hv : halfedges_around_target(v, tmesh)) + if(!is_border(hv, tmesh)) internal::collect_badly_shaped_triangles(face(hv, tmesh), tmesh, edges_to_collapse, edges_to_flip, np); -#ifdef CGAL_PMP_DEBUG_REMOVE_DEGENERACIES_EXTRA +#ifdef CGAL_PMP_DEBUG_REMOVE_DEGENERACIES_EXTRA std::string nb = std::to_string(++kk); - if (kk<10) nb = std::string("0")+nb; - if (kk<100) nb = std::string("0")+nb; - if (kk<1000) nb = std::string("0")+nb; - if (kk<10000) nb = std::string("0")+nb; + if(kk<10) nb = std::string("0")+nb; + if(kk<100) nb = std::string("0")+nb; + if(kk<1000) nb = std::string("0")+nb; + if(kk<10000) nb = std::string("0")+nb; std::ofstream(std::string("tmp/n-")+nb+std::string(".off")) << tmesh; #endif something_was_done = true; } else { -#ifdef CGAL_PMP_DEBUG_REMOVE_DEGENERACIES +#ifdef CGAL_PMP_DEBUG_REMOVE_DEGENERACIES std::cerr << "Warning: uncollapsable edge! " << tmesh.point(source(e, tmesh)) << " " << tmesh.point(target(e, tmesh)) << std::endl; #endif @@ -437,38 +437,38 @@ bool remove_almost_degenerate_faces(const FaceRange& face_range, } // treat caps -#ifdef CGAL_PMP_DEBUG_REMOVE_DEGENERACIES_EXTRA +#ifdef CGAL_PMP_DEBUG_REMOVE_DEGENERACIES_EXTRA kk=0; std::ofstream(std::string("tmp/c-000.off")) << tmesh; #endif - while (!edges_to_flip.empty()) + while(!edges_to_flip.empty()) { edge_descriptor e = *edges_to_flip.begin(); edges_to_flip.erase(edges_to_flip.begin()); -#ifdef CGAL_PMP_DEBUG_REMOVE_DEGENERACIES +#ifdef CGAL_PMP_DEBUG_REMOVE_DEGENERACIES std::cout << "treat cap: " << e << " (" << tmesh.point(source (e, tmesh)) << " --- " << tmesh.point(target(e, tmesh)) << ")" << std::endl; #endif halfedge_descriptor h = halfedge(e, tmesh); std::array nc = internal::is_badly_shaped(face(h, tmesh), tmesh, np); // First check the triangle is still a cap - if (nc[1]!=h) + if(nc[1]!=h) { -#ifdef CGAL_PMP_DEBUG_REMOVE_DEGENERACIES +#ifdef CGAL_PMP_DEBUG_REMOVE_DEGENERACIES std::cerr << "Warning: Cap criteria no longer verified " << tmesh.point(source(e, tmesh)) << " --- " << tmesh.point(target(e, tmesh)) << std::endl; #endif // the opposite edge might also have been inserted in the set and might still be a cap h = opposite(h, tmesh); - if (is_border(h, tmesh) ) continue; + if(is_border(h, tmesh) ) continue; nc = internal::is_badly_shaped(face(h, tmesh), tmesh, np); - if (nc[1] != h) + if(nc[1] != h) continue; } // special case on the border - if ( is_border(opposite(h, tmesh), tmesh) ) + if(is_border(opposite(h, tmesh), tmesh) ) { // remove the triangle edges_to_flip.erase(edge(prev(h, tmesh), tmesh)); @@ -485,18 +485,18 @@ bool remove_almost_degenerate_faces(const FaceRange& face_range, target(next(opposite(h, tmesh), tmesh), tmesh), tmesh).second) { - if (!internal::should_flip(e, tmesh, np)) + if(!internal::should_flip(e, tmesh, np)) { -#ifdef CGAL_PMP_DEBUG_REMOVE_DEGENERACIES +#ifdef CGAL_PMP_DEBUG_REMOVE_DEGENERACIES std::cout << "Flipping prevented: not the best diagonal" << std::endl; #endif next_edges_to_flip.insert(e); continue; } -#ifdef CGAL_PMP_DEBUG_REMOVE_DEGENERACIES +#ifdef CGAL_PMP_DEBUG_REMOVE_DEGENERACIES std::cout << "Flipping" << std::endl; #endif -#ifdef CGAL_PMP_DEBUG_REMOVE_DEGENERACIES_EXTRA +#ifdef CGAL_PMP_DEBUG_REMOVE_DEGENERACIES_EXTRA std::cerr << "step " << kk << "\n"; std::cerr << " Flipping " << tmesh.point(source(h, tmesh)) << " " << tmesh.point(target(h, tmesh)) << std::endl; @@ -505,18 +505,18 @@ bool remove_almost_degenerate_faces(const FaceRange& face_range, CGAL_assertion( edge(h, tmesh) == e ); // handle face updates - for (int i=0; i<2; ++i) + for(int i=0; i<2; ++i) { CGAL_assertion(!is_border(h, tmesh)); std::array nc = internal::is_badly_shaped(face(h, tmesh), tmesh, np); - if (nc[1]!=boost::graph_traits::null_halfedge()) + if(nc[1]!=boost::graph_traits::null_halfedge()) { - if (edge(nc[1], tmesh) != e) + if(edge(nc[1], tmesh) != e) next_edges_to_flip.insert( edge(nc[1], tmesh) ); } else { - if (nc[0]!=boost::graph_traits::null_halfedge()) + if(nc[0]!=boost::graph_traits::null_halfedge()) { next_edges_to_collapse.insert(edge(nc[0], tmesh)); } @@ -525,7 +525,7 @@ bool remove_almost_degenerate_faces(const FaceRange& face_range, } something_was_done = true; } -#ifdef CGAL_PMP_DEBUG_REMOVE_DEGENERACIES +#ifdef CGAL_PMP_DEBUG_REMOVE_DEGENERACIES else { std::cerr << "Warning: unflippable edge! " << tmesh.point(source(h, tmesh)) << " --- " @@ -533,12 +533,12 @@ bool remove_almost_degenerate_faces(const FaceRange& face_range, next_edges_to_flip.insert(e); } #endif -#ifdef CGAL_PMP_DEBUG_REMOVE_DEGENERACIES_EXTRA +#ifdef CGAL_PMP_DEBUG_REMOVE_DEGENERACIES_EXTRA std::string nb = std::to_string(++kk); - if (kk<10) nb = std::string("0")+nb; - if (kk<100) nb = std::string("0")+nb; - if (kk<1000) nb = std::string("0")+nb; - if (kk<10000) nb = std::string("0")+nb; + if(kk<10) nb = std::string("0")+nb; + if(kk<100) nb = std::string("0")+nb; + if(kk<1000) nb = std::string("0")+nb; + if(kk<10000) nb = std::string("0")+nb; std::ofstream(std::string("tmp/c-")+nb+std::string(".off")) << tmesh; #endif } @@ -546,7 +546,7 @@ bool remove_almost_degenerate_faces(const FaceRange& face_range, std::swap(edges_to_collapse, next_edges_to_collapse); std::swap(edges_to_flip, next_edges_to_flip); - if (!something_was_done) + if(!something_was_done) return false; } From 15d42d6cd282dbb0cbde1ecd92d44afb8b198ee7 Mon Sep 17 00:00:00 2001 From: Maxime Gimeno Date: Tue, 24 Sep 2019 11:38:19 +0200 Subject: [PATCH 164/363] Make the accelerate_distance_query() lazy and add a function to disable it. --- AABB_tree/demo/AABB_tree/Scene.cpp | 2 -- AABB_tree/include/CGAL/AABB_tree.h | 29 ++++++++++++++++++++++------- Installation/CHANGES.md | 8 ++++++++ 3 files changed, 30 insertions(+), 9 deletions(-) diff --git a/AABB_tree/demo/AABB_tree/Scene.cpp b/AABB_tree/demo/AABB_tree/Scene.cpp index 6303fb2140b..a0bc61b75d0 100644 --- a/AABB_tree/demo/AABB_tree/Scene.cpp +++ b/AABB_tree/demo/AABB_tree/Scene.cpp @@ -806,7 +806,6 @@ void Scene::build_facet_tree() timer.start(); std::cout << "Construct Facet AABB tree..."; m_facet_tree.rebuild(faces(*m_pPolyhedron).first, faces(*m_pPolyhedron).second,*m_pPolyhedron); - m_facet_tree.accelerate_distance_queries(); std::cout << "done (" << timer.time() << " s)" << std::endl; } @@ -826,7 +825,6 @@ void Scene::build_edge_tree() timer.start(); std::cout << "Construct Edge AABB tree..."; m_edge_tree.rebuild(edges(*m_pPolyhedron).first,edges(*m_pPolyhedron).second,*m_pPolyhedron); - m_edge_tree.accelerate_distance_queries(); std::cout << "done (" << timer.time() << " s)" << std::endl; } diff --git a/AABB_tree/include/CGAL/AABB_tree.h b/AABB_tree/include/CGAL/AABB_tree.h index 42c732f7ca4..0e6ca291047 100644 --- a/AABB_tree/include/CGAL/AABB_tree.h +++ b/AABB_tree/include/CGAL/AABB_tree.h @@ -185,7 +185,7 @@ namespace CGAL { clear_nodes(); m_primitives.clear(); clear_search_tree(); - m_default_search_tree_constructed = false; + m_default_search_tree_constructed = m_use_lazy_kd_tree; } /// Returns the axis-aligned bounding box of the whole tree. @@ -439,6 +439,9 @@ public: /// a point set taken on the internal primitives /// returns `true` iff successful memory allocation bool accelerate_distance_queries() const; + ///Turns off the lazy construction of the internal search tree. + /// Must be called before the first distance query. + void do_not_accelerate_distance_queries() const; /// Constructs an internal KD-tree containing the specified point /// set, to be used as the set of potential hints for accelerating @@ -590,6 +593,7 @@ public: // search KD-tree mutable const Search_tree* m_p_search_tree; mutable bool m_search_tree_constructed; + mutable bool m_use_lazy_kd_tree; mutable bool m_default_search_tree_constructed; // indicates whether the internal kd-tree should be built bool m_need_build; @@ -610,7 +614,8 @@ public: , m_p_root_node(nullptr) , m_p_search_tree(nullptr) , m_search_tree_constructed(false) - , m_default_search_tree_constructed(false) + , m_use_lazy_kd_tree(true) + , m_default_search_tree_constructed(true) , m_need_build(false) {} @@ -621,10 +626,11 @@ public: T&& ... t) : m_traits() , m_primitives() - , m_p_root_node(nullptr) + , m_p_root_node(nullptr) , m_p_search_tree(nullptr) , m_search_tree_constructed(false) - , m_default_search_tree_constructed(false) + , m_use_lazy_kd_tree(true) + , m_default_search_tree_constructed(true) , m_need_build(false) { // Insert each primitive into tree @@ -682,7 +688,6 @@ public: void AABB_tree::build() { clear_nodes(); - if(m_primitives.size() > 1) { // allocates tree nodes @@ -704,8 +709,9 @@ public: // In case the users has switched on the accelerated distance query // data structure with the default arguments, then it has to be // /built/rebuilt. - if(m_default_search_tree_constructed) + if(m_default_search_tree_constructed){ build_kd_tree(); + } m_need_build = false; } // constructs the search KD tree from given points @@ -737,7 +743,7 @@ public: ConstPointIterator beyond) const { m_p_search_tree = new Search_tree(first, beyond); - m_default_search_tree_constructed = true; + m_default_search_tree_constructed = true; if(m_p_search_tree != nullptr) { m_search_tree_constructed = true; @@ -750,6 +756,15 @@ public: } } + template + void AABB_tree::do_not_accelerate_distance_queries()const + { + clear_search_tree(); + m_use_lazy_kd_tree = false; + m_default_search_tree_constructed = false; + } + + // constructs the search KD tree from internal primitives template bool AABB_tree::accelerate_distance_queries() const diff --git a/Installation/CHANGES.md b/Installation/CHANGES.md index b0d3bf73941..498099a30e6 100644 --- a/Installation/CHANGES.md +++ b/Installation/CHANGES.md @@ -1,5 +1,13 @@ Release History =============== +Release 5.1 +----------- +Release date: March 2020 + +### 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. + Release 5.0 ----------- From a52592909fd9d287554c7e872b85144ca4c9b85d Mon Sep 17 00:00:00 2001 From: Maxime Gimeno Date: Tue, 24 Sep 2019 11:42:49 +0200 Subject: [PATCH 165/363] Remove all calls to accelerate_distance_queries(), now redundant. --- AABB_tree/demo/AABB_tree/benchmarks.cpp | 5 +---- .../examples/AABB_tree/AABB_face_graph_triangle_example.cpp | 1 - .../examples/AABB_tree/AABB_halfedge_graph_edge_example.cpp | 1 - AABB_tree/examples/AABB_tree/AABB_insertion_example.cpp | 2 -- .../examples/AABB_tree/AABB_polyhedron_edge_example.cpp | 1 - .../AABB_tree/AABB_polyhedron_facet_distance_example.cpp | 1 - AABB_tree/examples/AABB_tree/AABB_segment_3_example.cpp | 1 - AABB_tree/test/AABB_tree/aabb_test_empty_tree.cpp | 1 - AABB_tree/test/AABB_tree/aabb_test_singleton_tree.cpp | 1 - .../CGAL/Mesh_3/experimental/Lipschitz_sizing_experimental.h | 1 - .../CGAL/Mesh_3/experimental/Lipschitz_sizing_polyhedron.h | 1 - .../CGAL/Mesh_3/polyhedral_to_labeled_function_wrapper.h | 4 +--- .../poisson_reconstruction.cpp | 1 - .../include/CGAL/Polygon_mesh_processing/distance.h | 1 - .../internal/Isotropic_remeshing/remesh_impl.h | 1 - .../CGAL/Polygon_mesh_processing/random_perturbation.h | 1 - .../include/CGAL/Polygon_mesh_processing/smooth_mesh.h | 1 - Polyhedron/demo/Polyhedron/Plugins/PMP/Distance_plugin.cpp | 1 - .../Plugins/Point_set/Point_set_to_mesh_distance_plugin.cpp | 1 - .../Point_set/Surface_reconstruction_poisson_impl.cpp | 1 - .../Plugins/Surface_mesh/Offset_meshing_plugin.cpp | 2 -- .../internal/Surface_mesh_segmentation/SDF_calculation.h | 3 --- 22 files changed, 2 insertions(+), 31 deletions(-) diff --git a/AABB_tree/demo/AABB_tree/benchmarks.cpp b/AABB_tree/demo/AABB_tree/benchmarks.cpp index 1375ecaca7c..364d19bc04e 100644 --- a/AABB_tree/demo/AABB_tree/benchmarks.cpp +++ b/AABB_tree/demo/AABB_tree/benchmarks.cpp @@ -77,7 +77,6 @@ void Scene::benchmark_distances(const double duration) timer.start(); std::cout << "Construct AABB tree and internal KD tree..."; Facet_tree tree(faces(*m_pPolyhedron).first, faces(*m_pPolyhedron).second,*m_pPolyhedron); - tree.accelerate_distance_queries(); std::cout << "done (" << timer.time() << " s)" << std::endl; // benchmark @@ -123,7 +122,7 @@ void Scene::bench_memory() typedef CGAL::Memory_sizer::size_type size_type; size_type before = CGAL::Memory_sizer().virtual_size(); Facet_tree tree(faces(*m_pPolyhedron).first, faces(*m_pPolyhedron).second,*m_pPolyhedron); - // tree.accelerate_distance_queries(); // 150 vs 61 bytes per primitive! + tree.do_not_accelerate_distance_queries(); // 150 vs 61 bytes per primitive! size_type after = CGAL::Memory_sizer().virtual_size(); size_type bytes = after - before; // in Bytes @@ -165,7 +164,6 @@ void Scene::bench_construction() CGAL::Timer time2; time2.start(); Facet_tree tree2(faces(*m_pPolyhedron).first, faces(*m_pPolyhedron).second,*m_pPolyhedron); - tree2.accelerate_distance_queries(); double duration_construction_and_kdtree = time2.time(); std::cout << m_pPolyhedron->size_of_facets() << "\t" @@ -248,7 +246,6 @@ void Scene::bench_distances_vs_nbt() // constructs tree (out of timing) Facet_tree tree(faces(*m_pPolyhedron).first, faces(*m_pPolyhedron).second, *m_pPolyhedron); - tree.accelerate_distance_queries(); // calls queries CGAL::Timer timer; diff --git a/AABB_tree/examples/AABB_tree/AABB_face_graph_triangle_example.cpp b/AABB_tree/examples/AABB_tree/AABB_face_graph_triangle_example.cpp index 54bb75ade1e..244909cb1b1 100644 --- a/AABB_tree/examples/AABB_tree/AABB_face_graph_triangle_example.cpp +++ b/AABB_tree/examples/AABB_tree/AABB_face_graph_triangle_example.cpp @@ -25,7 +25,6 @@ void run(const FaceGraph& graph){ // constructs the AABB tree and the internal search tree for // efficient distance queries. Tree tree( faces(graph).first, faces(graph).second, graph); - tree.accelerate_distance_queries(); // counts #intersections with a triangle query Segment segment_query(p,q); diff --git a/AABB_tree/examples/AABB_tree/AABB_halfedge_graph_edge_example.cpp b/AABB_tree/examples/AABB_tree/AABB_halfedge_graph_edge_example.cpp index a98753b7a1c..7767ba735c0 100644 --- a/AABB_tree/examples/AABB_tree/AABB_halfedge_graph_edge_example.cpp +++ b/AABB_tree/examples/AABB_tree/AABB_halfedge_graph_edge_example.cpp @@ -27,7 +27,6 @@ void run(const HalfedgeGraph& graph){ // efficient distance queries. Tree tree( CGAL::edges(graph).first, CGAL::edges(graph).second, graph); - tree.accelerate_distance_queries(); // counts #intersections with a triangle query Triangle triangle_query(p,q,r); diff --git a/AABB_tree/examples/AABB_tree/AABB_insertion_example.cpp b/AABB_tree/examples/AABB_tree/AABB_insertion_example.cpp index ede70be1005..90719fda49f 100644 --- a/AABB_tree/examples/AABB_tree/AABB_insertion_example.cpp +++ b/AABB_tree/examples/AABB_tree/AABB_insertion_example.cpp @@ -37,8 +37,6 @@ int main() // data structure to accelerate distance queries Tree tree(faces(polyhedron1).first, faces(polyhedron1).second, polyhedron1); - tree.accelerate_distance_queries(); - tree.insert(faces(polyhedron2).first, faces(polyhedron2).second, polyhedron2); // query point diff --git a/AABB_tree/examples/AABB_tree/AABB_polyhedron_edge_example.cpp b/AABB_tree/examples/AABB_tree/AABB_polyhedron_edge_example.cpp index da354a36e72..cac955a5b8f 100644 --- a/AABB_tree/examples/AABB_tree/AABB_polyhedron_edge_example.cpp +++ b/AABB_tree/examples/AABB_tree/AABB_polyhedron_edge_example.cpp @@ -31,7 +31,6 @@ int main() Tree tree( CGAL::edges(polyhedron).first, CGAL::edges(polyhedron).second, polyhedron); - tree.accelerate_distance_queries(); // counts #intersections with a triangle query Triangle triangle_query(p,q,r); diff --git a/AABB_tree/examples/AABB_tree/AABB_polyhedron_facet_distance_example.cpp b/AABB_tree/examples/AABB_tree/AABB_polyhedron_facet_distance_example.cpp index eb3e3ed806d..bb9ad89e463 100644 --- a/AABB_tree/examples/AABB_tree/AABB_polyhedron_facet_distance_example.cpp +++ b/AABB_tree/examples/AABB_tree/AABB_polyhedron_facet_distance_example.cpp @@ -31,7 +31,6 @@ int main() // constructs AABB tree and computes internal KD-tree // data structure to accelerate distance queries Tree tree(faces(polyhedron).first, faces(polyhedron).second, polyhedron); - tree.accelerate_distance_queries(); // query point Point query(0.0, 0.0, 3.0); diff --git a/AABB_tree/examples/AABB_tree/AABB_segment_3_example.cpp b/AABB_tree/examples/AABB_tree/AABB_segment_3_example.cpp index 46a0c51118e..95e8c1c7664 100644 --- a/AABB_tree/examples/AABB_tree/AABB_segment_3_example.cpp +++ b/AABB_tree/examples/AABB_tree/AABB_segment_3_example.cpp @@ -36,7 +36,6 @@ int main() // constructs the AABB tree and the internal search tree for // efficient distance computations. Tree tree(segments.begin(),segments.end()); - tree.accelerate_distance_queries(); // counts #intersections with a plane query Plane plane_query(a,b,d); diff --git a/AABB_tree/test/AABB_tree/aabb_test_empty_tree.cpp b/AABB_tree/test/AABB_tree/aabb_test_empty_tree.cpp index 63b72a7d4e9..3ba40764130 100644 --- a/AABB_tree/test/AABB_tree/aabb_test_empty_tree.cpp +++ b/AABB_tree/test/AABB_tree/aabb_test_empty_tree.cpp @@ -34,7 +34,6 @@ int main() // Test calls to all functions but those who have `!empty()` as // precondition. CGAL::Emptyset_iterator devnull; - tree.accelerate_distance_queries(); tree.all_intersections(triangle_query, devnull); tree.all_intersected_primitives(triangle_query, devnull); assert(!tree.any_intersected_primitive(triangle_query)); diff --git a/AABB_tree/test/AABB_tree/aabb_test_singleton_tree.cpp b/AABB_tree/test/AABB_tree/aabb_test_singleton_tree.cpp index 09c88d37f01..aaf49dbf12b 100644 --- a/AABB_tree/test/AABB_tree/aabb_test_singleton_tree.cpp +++ b/AABB_tree/test/AABB_tree/aabb_test_singleton_tree.cpp @@ -36,7 +36,6 @@ int main() // Test calls to all functions CGAL::Emptyset_iterator devnull; - tree.accelerate_distance_queries(); tree.all_intersections(triangle_query, devnull); tree.all_intersected_primitives(triangle_query, devnull); assert(tree.any_intersected_primitive(triangle_query)); diff --git a/Mesh_3/include/CGAL/Mesh_3/experimental/Lipschitz_sizing_experimental.h b/Mesh_3/include/CGAL/Mesh_3/experimental/Lipschitz_sizing_experimental.h index 27f5ec12ec6..b20132ed6dd 100644 --- a/Mesh_3/include/CGAL/Mesh_3/experimental/Lipschitz_sizing_experimental.h +++ b/Mesh_3/include/CGAL/Mesh_3/experimental/Lipschitz_sizing_experimental.h @@ -319,7 +319,6 @@ public: m_own_ptree.reset(new Tree(triangles.begin(), triangles.end())); m_own_ptree->build(); - m_own_ptree->accelerate_distance_queries(); } private: diff --git a/Mesh_3/include/CGAL/Mesh_3/experimental/Lipschitz_sizing_polyhedron.h b/Mesh_3/include/CGAL/Mesh_3/experimental/Lipschitz_sizing_polyhedron.h index fa6f3670567..19db8a32100 100644 --- a/Mesh_3/include/CGAL/Mesh_3/experimental/Lipschitz_sizing_polyhedron.h +++ b/Mesh_3/include/CGAL/Mesh_3/experimental/Lipschitz_sizing_polyhedron.h @@ -140,7 +140,6 @@ public: m_own_ptree.reset(new Tree(triangles.begin(), triangles.end())); m_own_ptree->build(); - m_own_ptree->accelerate_distance_queries(); } private: diff --git a/Mesh_3/include/CGAL/Mesh_3/polyhedral_to_labeled_function_wrapper.h b/Mesh_3/include/CGAL/Mesh_3/polyhedral_to_labeled_function_wrapper.h index f6150d92b90..f2e5c64e8e3 100644 --- a/Mesh_3/include/CGAL/Mesh_3/polyhedral_to_labeled_function_wrapper.h +++ b/Mesh_3/include/CGAL/Mesh_3/polyhedral_to_labeled_function_wrapper.h @@ -99,7 +99,7 @@ public: , step_size_(step_size) , first_level_(first_level) { - tree_->accelerate_distance_queries(); + } // Default copy constructor and assignment operator are ok @@ -216,7 +216,6 @@ public: , sq_tolerance_size_(tolerance_size*tolerance_size) , hint_(p.facets_begin()->halfedge()->vertex()->point()) { - tree_->accelerate_distance_queries(); } // Default copy constructor and assignment operator are ok @@ -292,7 +291,6 @@ public: , sq_tolerance_size_(tolerance_size*tolerance_size) , hint_(p.facets_begin()->halfedge()->vertex()->point()) { - tree_->accelerate_distance_queries(); } // Default copy constructor and assignment operator are ok diff --git a/Poisson_surface_reconstruction_3/examples/Poisson_surface_reconstruction_3/poisson_reconstruction.cpp b/Poisson_surface_reconstruction_3/examples/Poisson_surface_reconstruction_3/poisson_reconstruction.cpp index c451cf51205..885a70b900e 100644 --- a/Poisson_surface_reconstruction_3/examples/Poisson_surface_reconstruction_3/poisson_reconstruction.cpp +++ b/Poisson_surface_reconstruction_3/examples/Poisson_surface_reconstruction_3/poisson_reconstruction.cpp @@ -360,7 +360,6 @@ int main(int argc, char * argv[]) // Constructs AABB tree and computes internal KD-tree // data structure to accelerate distance queries AABB_tree tree(faces(output_mesh).first, faces(output_mesh).second, output_mesh); - tree.accelerate_distance_queries(); // Computes distance from each input point to reconstructed mesh double max_distance = DBL_MIN; 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 34c6fc2078c..63f0e644add 100644 --- a/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/distance.h +++ b/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/distance.h @@ -558,7 +558,6 @@ double approximate_Hausdorff_distance( Tree tree( faces(tm).first, faces(tm).second, tm); tree.build(); - tree.accelerate_distance_queries(); Point_3 hint = get(vpm, *vertices(tm).first); return internal::approximate_Hausdorff_distance_impl diff --git a/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/internal/Isotropic_remeshing/remesh_impl.h b/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/internal/Isotropic_remeshing/remesh_impl.h index 61605258385..aa985e921fe 100644 --- a/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/internal/Isotropic_remeshing/remesh_impl.h +++ b/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/internal/Isotropic_remeshing/remesh_impl.h @@ -381,7 +381,6 @@ namespace internal { } for(std::size_t i=0; i < trees.size(); ++i){ trees[i]->build(); - trees[i]->accelerate_distance_queries(); } } diff --git a/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/random_perturbation.h b/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/random_perturbation.h index cc66bccf967..ee9804e83e4 100644 --- a/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/random_perturbation.h +++ b/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/random_perturbation.h @@ -83,7 +83,6 @@ namespace internal { if(do_project) { tree.rebuild(faces(tmesh).first, faces(tmesh).second, tmesh); - tree.accelerate_distance_queries(); } typename GT::Construct_translated_point_3 translate = gt.construct_translated_point_3_object(); diff --git a/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/smooth_mesh.h b/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/smooth_mesh.h index 5eefc513f33..95323681fe0 100644 --- a/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/smooth_mesh.h +++ b/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/smooth_mesh.h @@ -225,7 +225,6 @@ void smooth_mesh(const FaceRange& faces, } Tree aabb_tree(input_triangles.begin(), input_triangles.end()); - aabb_tree.accelerate_distance_queries(); // Setup the working ranges and check some preconditions Angle_smoother angle_smoother(tmesh, vpmap, vcmap, gt); diff --git a/Polyhedron/demo/Polyhedron/Plugins/PMP/Distance_plugin.cpp b/Polyhedron/demo/Polyhedron/Plugins/PMP/Distance_plugin.cpp index 1a7b64458dd..6c9347d72d7 100644 --- a/Polyhedron/demo/Polyhedron/Plugins/PMP/Distance_plugin.cpp +++ b/Polyhedron/demo/Polyhedron/Plugins/PMP/Distance_plugin.cpp @@ -133,7 +133,6 @@ private: typedef CGAL::AABB_tree< Traits > Tree; Tree tree( faces(m).first, faces(m).second, m); - tree.accelerate_distance_queries(); tree.build(); boost::graph_traits::vertex_descriptor vd = *(vertices(m).first); Traits::Point_3 hint = get(CGAL::vertex_point,m, vd); diff --git a/Polyhedron/demo/Polyhedron/Plugins/Point_set/Point_set_to_mesh_distance_plugin.cpp b/Polyhedron/demo/Polyhedron/Plugins/Point_set/Point_set_to_mesh_distance_plugin.cpp index 797a5ba644a..e0d8c395e8a 100644 --- a/Polyhedron/demo/Polyhedron/Plugins/Point_set/Point_set_to_mesh_distance_plugin.cpp +++ b/Polyhedron/demo/Polyhedron/Plugins/Point_set/Point_set_to_mesh_distance_plugin.cpp @@ -77,7 +77,6 @@ double compute_distances(const Mesh& m, typedef CGAL::AABB_tree< Traits > Tree; Tree tree( faces(m).first, faces(m).second, m); - tree.accelerate_distance_queries(); tree.build(); typedef typename boost::property_map::const_type VPMap; VPMap vpmap = get(boost::vertex_point, m); diff --git a/Polyhedron/demo/Polyhedron/Plugins/Point_set/Surface_reconstruction_poisson_impl.cpp b/Polyhedron/demo/Polyhedron/Plugins/Point_set/Surface_reconstruction_poisson_impl.cpp index 77511d670f4..a6987e4f759 100644 --- a/Polyhedron/demo/Polyhedron/Plugins/Point_set/Surface_reconstruction_poisson_impl.cpp +++ b/Polyhedron/demo/Polyhedron/Plugins/Point_set/Surface_reconstruction_poisson_impl.cpp @@ -358,7 +358,6 @@ SMesh* poisson_reconstruct(Point_set& points, // Constructs AABB tree and computes internal KD-tree // data structure to accelerate distance queries AABB_tree tree(faces(*mesh).first, faces(*mesh).second, *mesh); - tree.accelerate_distance_queries(); // Computes distance from each input point to reconstructed mesh double max_distance = DBL_MIN; diff --git a/Polyhedron/demo/Polyhedron/Plugins/Surface_mesh/Offset_meshing_plugin.cpp b/Polyhedron/demo/Polyhedron/Plugins/Surface_mesh/Offset_meshing_plugin.cpp index ebaf3adee56..46ac1ac4796 100644 --- a/Polyhedron/demo/Polyhedron/Plugins/Surface_mesh/Offset_meshing_plugin.cpp +++ b/Polyhedron/demo/Polyhedron/Plugins/Surface_mesh/Offset_meshing_plugin.cpp @@ -58,7 +58,6 @@ public: , m_is_closed( is_closed(tm) ) { CGAL_assertion(!m_tree_ptr->empty()); - m_tree_ptr->accelerate_distance_queries(); } double operator()(const typename GeomTraits::Point_3& p) const @@ -188,7 +187,6 @@ public: , m_offset_distance(offset_distance) { CGAL_assertion(! m_tree_ptr->empty() ); - m_tree_ptr->accelerate_distance_queries(); } double operator()(const EPICK::Point_3& p) const diff --git a/Surface_mesh_segmentation/include/CGAL/internal/Surface_mesh_segmentation/SDF_calculation.h b/Surface_mesh_segmentation/include/CGAL/internal/Surface_mesh_segmentation/SDF_calculation.h index b4d79c41816..5c07db3255c 100644 --- a/Surface_mesh_segmentation/include/CGAL/internal/Surface_mesh_segmentation/SDF_calculation.h +++ b/Surface_mesh_segmentation/include/CGAL/internal/Surface_mesh_segmentation/SDF_calculation.h @@ -173,9 +173,6 @@ public: } tree.build(); - if(build_kd_tree) { - tree.accelerate_distance_queries(); - } if(use_diagonal) { CGAL::Bbox_3 bbox = tree.bbox(); From dd566a2c962a8ce2064c8fb20c295ec2cbc1326b Mon Sep 17 00:00:00 2001 From: Maxime Gimeno Date: Tue, 24 Sep 2019 13:49:10 +0200 Subject: [PATCH 166/363] Fixes --- AABB_tree/include/CGAL/AABB_tree.h | 7 +------ .../internal/Surface_mesh_segmentation/SDF_calculation.h | 4 +++- 2 files changed, 4 insertions(+), 7 deletions(-) diff --git a/AABB_tree/include/CGAL/AABB_tree.h b/AABB_tree/include/CGAL/AABB_tree.h index 0e6ca291047..8e977c76f57 100644 --- a/AABB_tree/include/CGAL/AABB_tree.h +++ b/AABB_tree/include/CGAL/AABB_tree.h @@ -185,7 +185,7 @@ namespace CGAL { clear_nodes(); m_primitives.clear(); clear_search_tree(); - m_default_search_tree_constructed = m_use_lazy_kd_tree; + m_default_search_tree_constructed = true; } /// Returns the axis-aligned bounding box of the whole tree. @@ -440,7 +440,6 @@ public: /// returns `true` iff successful memory allocation bool accelerate_distance_queries() const; ///Turns off the lazy construction of the internal search tree. - /// Must be called before the first distance query. void do_not_accelerate_distance_queries() const; /// Constructs an internal KD-tree containing the specified point @@ -593,7 +592,6 @@ public: // search KD-tree mutable const Search_tree* m_p_search_tree; mutable bool m_search_tree_constructed; - mutable bool m_use_lazy_kd_tree; mutable bool m_default_search_tree_constructed; // indicates whether the internal kd-tree should be built bool m_need_build; @@ -614,7 +612,6 @@ public: , m_p_root_node(nullptr) , m_p_search_tree(nullptr) , m_search_tree_constructed(false) - , m_use_lazy_kd_tree(true) , m_default_search_tree_constructed(true) , m_need_build(false) {} @@ -629,7 +626,6 @@ public: , m_p_root_node(nullptr) , m_p_search_tree(nullptr) , m_search_tree_constructed(false) - , m_use_lazy_kd_tree(true) , m_default_search_tree_constructed(true) , m_need_build(false) { @@ -760,7 +756,6 @@ public: void AABB_tree::do_not_accelerate_distance_queries()const { clear_search_tree(); - m_use_lazy_kd_tree = false; m_default_search_tree_constructed = false; } diff --git a/Surface_mesh_segmentation/include/CGAL/internal/Surface_mesh_segmentation/SDF_calculation.h b/Surface_mesh_segmentation/include/CGAL/internal/Surface_mesh_segmentation/SDF_calculation.h index 5c07db3255c..58d85972962 100644 --- a/Surface_mesh_segmentation/include/CGAL/internal/Surface_mesh_segmentation/SDF_calculation.h +++ b/Surface_mesh_segmentation/include/CGAL/internal/Surface_mesh_segmentation/SDF_calculation.h @@ -171,9 +171,11 @@ public: if(!test) tree.insert(Primitive(it, mesh, vertex_point_map)); } + if(!build_kd_tree) { + tree.do_not_accelerate_distance_queries(); + } tree.build(); - if(use_diagonal) { CGAL::Bbox_3 bbox = tree.bbox(); max_diagonal = From f138c6614289a2d7a808d412f85b2650f4bfeea8 Mon Sep 17 00:00:00 2001 From: Andreas Fabri Date: Tue, 24 Sep 2019 15:06:56 +0200 Subject: [PATCH 167/363] Surface_mesh: Disable comparison of mixed index types --- .../include/CGAL/Surface_mesh/Surface_mesh.h | 82 +++++++++++++++---- 1 file changed, 64 insertions(+), 18 deletions(-) diff --git a/Surface_mesh/include/CGAL/Surface_mesh/Surface_mesh.h b/Surface_mesh/include/CGAL/Surface_mesh/Surface_mesh.h index 63e3eeb4a63..0a9d4d24e4f 100644 --- a/Surface_mesh/include/CGAL/Surface_mesh/Surface_mesh.h +++ b/Surface_mesh/include/CGAL/Surface_mesh/Surface_mesh.h @@ -90,21 +90,6 @@ namespace CGAL { return idx_ != inf; } - /// are two indices equal? - bool operator==(const T& _rhs) const { - return idx_ == _rhs.idx_; - } - - /// are two indices different? - bool operator!=(const T& _rhs) const { - return idx_ != _rhs.idx_; - } - - /// Comparison by index. - bool operator<(const T& _rhs) const { - return idx_ < _rhs.idx_; - } - // Compatibility with OpenMesh handle size_type idx() const { return idx_; @@ -130,7 +115,7 @@ namespace CGAL { SM_Index operator+=(std::ptrdiff_t n) { idx_ = size_type(std::ptrdiff_t(idx_) + n); return *this; } - private: + protected: size_type idx_; }; @@ -141,8 +126,8 @@ namespace CGAL { return ret; } - // Implementation for Surface_mesh::Vertex_index - + + // Implementation for Surface_mesh::Vertex_index class SM_Vertex_index : public SM_Index { @@ -152,6 +137,25 @@ namespace CGAL { explicit SM_Vertex_index(size_type _idx) : SM_Index(_idx) {} + template bool operator==(const T&) const = delete; + template bool operator!=(const T&) const = delete; + template bool operator<(const T&) const = delete; + + /// are two indices equal? + bool operator==(const SM_Vertex_index& _rhs) const { + return this->idx_ == _rhs.idx_; + } + + /// are two indices different? + bool operator!=(const SM_Vertex_index& _rhs) const { + return this->idx_ != _rhs.idx_; + } + + /// Comparison by index. + bool operator<(const SM_Vertex_index& _rhs) const { + return this->idx_ < _rhs.idx_; + } + friend std::ostream& operator<<(std::ostream& os, SM_Vertex_index const& v) { @@ -177,6 +181,25 @@ namespace CGAL { SM_Halfedge_index() : SM_Index((std::numeric_limits::max)()) {} explicit SM_Halfedge_index(size_type _idx) : SM_Index(_idx) {} + + template bool operator==(const T&) const = delete; + template bool operator!=(const T&) const = delete; + template bool operator<(const T&) const = delete; + + /// are two indices equal? + bool operator==(const SM_Halfedge_index& _rhs) const { + return this->idx_ == _rhs.idx_; + } + + /// are two indices different? + bool operator!=(const SM_Halfedge_index& _rhs) const { + return this->idx_ != _rhs.idx_; + } + + /// Comparison by index. + bool operator<(const SM_Halfedge_index& _rhs) const { + return this->idx_ < _rhs.idx_; + } friend std::ostream& operator<<(std::ostream& os, SM_Halfedge_index const& h) { @@ -193,7 +216,25 @@ namespace CGAL { SM_Face_index() : SM_Index((std::numeric_limits::max)()) {} explicit SM_Face_index(size_type _idx) : SM_Index(_idx) {} + + template bool operator==(const T&) const = delete; + template bool operator!=(const T&) const = delete; + template bool operator<(const T&) const = delete; + /// are two indices equal? + bool operator==(const SM_Face_index& _rhs) const { + return this->idx_ == _rhs.idx_; + } + + /// are two indices different? + bool operator!=(const SM_Face_index& _rhs) const { + return this->idx_ != _rhs.idx_; + } + + /// Comparison by index. + bool operator<(const SM_Face_index& _rhs) const { + return this->idx_ < _rhs.idx_; + } friend std::ostream& operator<<(std::ostream& os, SM_Face_index const& f) { @@ -228,6 +269,11 @@ namespace CGAL { // returns whether the index is valid, i.e., the index is not equal to std::numeric_limits::max(). bool is_valid() const { return halfedge_.is_valid(); } + + template bool operator==(const T&) const = delete; + template bool operator!=(const T&) const = delete; + template bool operator<(const T&) const = delete; + // Are two indices equal? bool operator==(const SM_Edge_index& other) const { return (size_type)(*this) == (size_type)other; } From 898663245f510e5a726969fac2dfb4e2f707c39a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mael=20Rouxel-Labb=C3=A9?= Date: Tue, 24 Sep 2019 16:58:10 +0200 Subject: [PATCH 168/363] Allow needle/cap/length threshold to be passed as NP + edge constraint map + general code cleaning --- .../remove_degeneracies.h | 304 +++++++++++------- 1 file changed, 189 insertions(+), 115 deletions(-) diff --git a/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/remove_degeneracies.h b/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/remove_degeneracies.h index ed56cd72854..e241561e8ca 100644 --- a/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/remove_degeneracies.h +++ b/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/remove_degeneracies.h @@ -29,6 +29,8 @@ #include #include +#include +#include #include @@ -43,63 +45,59 @@ namespace CGAL { namespace Polygon_mesh_processing { namespace internal { -template -bool is_face_incident_to_border(const typename boost::graph_traits::face_descriptor f, - const TriangleMesh& tmesh) -{ - typedef typename boost::graph_traits::halfedge_descriptor halfedge_descriptor; - - for(halfedge_descriptor h : CGAL::halfedges_around_face(halfedge(f, tmesh), tmesh)) - { - if(is_border_edge(h, tmesh)) - return true; - } - - return false; -} - -template +template std::array::halfedge_descriptor, 2> is_badly_shaped(const typename boost::graph_traits::face_descriptor f, - TriangleMesh& tmesh, - const NamedParameters& np) + TriangleMesh& tmesh, + const VPM& vpm, + const ECM& ecm, + const Traits& gt, + const double cap_threshold, // angle over 160° ==> cap + const double needle_threshold, // longest edge / shortest edge over this ratio ==> needle + const double collapse_length_threshold) // max length of edges allowed to be collapsed { + namespace PMP = CGAL::Polygon_mesh_processing; + typedef typename boost::graph_traits::halfedge_descriptor halfedge_descriptor; - const halfedge_descriptor null_halfedge = boost::graph_traits::null_halfedge(); - // @todo parameters - const double needle_threshold = 4; // longest edge / shortest edge over this ratio ==> needle - const double cap_threshold = std::cos(160. / 180 * CGAL_PI); // angle over 160° ==> cap - const double collapse_threshold = 0.2; // max length of edges allowed to be collapsed - /// @todo add is_constrained edge map + const halfedge_descriptor null_h = boost::graph_traits::null_halfedge(); - halfedge_descriptor res = CGAL::Polygon_mesh_processing::is_needle_triangle_face(f, tmesh, needle_threshold, np); - if(res != boost::graph_traits::null_halfedge()) + halfedge_descriptor res = PMP::is_needle_triangle_face(f, tmesh, needle_threshold, + parameters::vertex_point_map(vpm) + .geom_traits(gt)); + if(res != null_h && !get(ecm, edge(res, tmesh))) { - if(edge_length(res, tmesh, np) <= collapse_threshold ) - return make_array(res, null_halfedge); + // don't want to collapse edges that are too large + if(edge_length(res, tmesh, parameters::vertex_point_map(vpm).geom_traits(gt)) <= collapse_length_threshold) + return make_array(res, null_h); } else // let's not make it possible to have a face be both a cap and a needle (for now) { - res = CGAL::Polygon_mesh_processing::is_cap_triangle_face(f, tmesh, cap_threshold, np); - if(res != boost::graph_traits::null_halfedge()) - { - return make_array(null_halfedge, res); - } + res = PMP::is_cap_triangle_face(f, tmesh, cap_threshold, parameters::vertex_point_map(vpm).geom_traits(gt)); + if(res != null_h && !get(ecm, edge(res, tmesh))) + return make_array(null_h, res); } - return make_array(null_halfedge, null_halfedge); + + return make_array(null_h, null_h); } -template +template void collect_badly_shaped_triangles(const typename boost::graph_traits::face_descriptor f, TriangleMesh& tmesh, + const VPM& vpm, + const ECM& ecm, + const Traits& gt, + const double cap_threshold, // angle over this threshold (as a cosine) ==> cap + const double needle_threshold, // longest edge / shortest edge over this ratio ==> needle + const double collapse_length_threshold, // max length of edges allowed to be collapsed EdgeContainer& edges_to_collapse, - EdgeContainer& edges_to_flip, - const NamedParameters& np) + EdgeContainer& edges_to_flip) { typedef typename boost::graph_traits::halfedge_descriptor halfedge_descriptor; - std::array res = is_badly_shaped(f, tmesh, np); + std::array res = is_badly_shaped(f, tmesh, vpm, ecm, gt, cap_threshold, + needle_threshold, collapse_length_threshold); if(res[0] != boost::graph_traits::null_halfedge()) { @@ -128,21 +126,24 @@ bool is_collapse_geometrically_valid(typename boost::graph_traits: const TriangleMesh& tmesh, const NamedParameters& np) { - typedef typename boost::graph_traits::halfedge_descriptor halfedge_descriptor; - typedef typename GetVertexPointMap::const_type VPM; - typedef typename boost::property_traits::reference Point_ref; - typedef typename GetGeomTraits::type Traits; + using CGAL::parameters::choose_parameter; + using CGAL::parameters::get_parameter; - VPM vpm = choose_param(get_param(np, internal_np::vertex_point), - get_const_property_map(vertex_point, tmesh)); + typedef typename boost::graph_traits::halfedge_descriptor halfedge_descriptor; + typedef typename GetVertexPointMap::const_type VPM; + typedef typename boost::property_traits::reference Point_ref; + typedef typename GetGeomTraits::type Traits; + VPM vpm = choose_parameter(get_parameter(np, internal_np::vertex_point), + get_const_property_map(vertex_point, tmesh)); + Traits gt = choose_parameter(get_parameter(np, internal_np::geom_traits), Traits()); /// @todo handle boundary edges h = opposite(h, tmesh); // Euler::collapse edge keeps the target and removes the source // source is kept, target is removed - CGAL_assertion( target(h, tmesh)==vertex_removed ); + CGAL_assertion(target(h, tmesh) == vertex_removed); Point_ref kept = get(vpm, source(h, tmesh)); Point_ref removed= get(vpm, target(h, tmesh)); @@ -151,7 +152,7 @@ bool is_collapse_geometrically_valid(typename boost::graph_traits: halfedge_descriptor hi = opposite(next(h, tmesh), tmesh); std::vector triangles; - while(hi!=stop) + while(hi != stop) { if(!is_border(hi, tmesh)) { @@ -160,11 +161,12 @@ bool is_collapse_geometrically_valid(typename boost::graph_traits: //ack a-b-point_remove and a-b-point_kept has a compatible orientation /// @todo use a predicate - typename Traits::Vector_3 n1 = CGAL::cross_product(removed-a, b-a); - typename Traits::Vector_3 n2 = CGAL::cross_product(kept-a, b-a); - if(n1*n2 <=0 ) + typename Traits::Vector_3 n1 = gt.construct_cross_product_vector_3_object()(removed-a, b-a); + typename Traits::Vector_3 n2 = gt.construct_cross_product_vector_3_object()(kept-a, b-a); + if(gt.compute_scalar_product_3_object()(n1, n2) <= 0) return false; } + hi = opposite(next(hi, tmesh), tmesh); } @@ -172,22 +174,17 @@ bool is_collapse_geometrically_valid(typename boost::graph_traits: } */ -template +template boost::optional get_collapse_volume(typename boost::graph_traits::halfedge_descriptor h, const TriangleMesh& tmesh, - const NamedParameters& np) + const VPM& vpm, + const Traits& gt) { - typedef typename boost::graph_traits::halfedge_descriptor halfedge_descriptor; - typedef typename GetVertexPointMap::const_type VPM; - typedef typename boost::property_traits::reference Point_ref; - typedef typename GetGeomTraits::type Traits; + typedef typename boost::graph_traits::halfedge_descriptor halfedge_descriptor; + typedef typename boost::property_traits::reference Point_ref; const typename Traits::Point_3 origin(ORIGIN); - VPM vpm = choose_param(get_param(np, internal_np::vertex_point), - get_const_property_map(vertex_point, tmesh)); - - /// @todo handle boundary edges h = opposite(h, tmesh); // Euler::collapse edge keeps the target and removes the source @@ -197,15 +194,15 @@ boost::optional get_collapse_volume(typename boost::graph_traits triangles; - while(hi!=stop) + while(hi != stop) { if(!is_border(hi, tmesh)) { @@ -214,61 +211,61 @@ boost::optional get_collapse_volume(typename boost::graph_traits +template typename boost::graph_traits::halfedge_descriptor get_best_edge_orientation(typename boost::graph_traits::edge_descriptor e, const TriangleMesh& tmesh, - const NamedParameters& np) + const VPM& vpm, + const Traits& gt) { typedef typename boost::graph_traits::halfedge_descriptor halfedge_descriptor; - halfedge_descriptor h = halfedge(e, tmesh), ho=opposite(h, tmesh); + halfedge_descriptor h = halfedge(e, tmesh), ho = opposite(h, tmesh); - boost::optional dv1 = get_collapse_volume(h, tmesh, np); - boost::optional dv2 = get_collapse_volume(ho, tmesh, np); + boost::optional dv1 = get_collapse_volume(h, tmesh, vpm, gt); + boost::optional dv2 = get_collapse_volume(ho, tmesh, vpm, gt); if(dv1 != boost::none) { if(dv2 != boost::none) - { - return *dv1 < *dv2 ? h : ho; - } + return (*dv1 < *dv2) ? h : ho; + return h; } if(dv2 != boost::none) - { return ho; - } + return boost::graph_traits::null_halfedge(); } // adapted from triangulate_faces -template +template bool should_flip(typename boost::graph_traits::edge_descriptor e, const TriangleMesh& tmesh, - const NamedParameters& np) + const VPM& vpm, + const Traits& gt) { typedef typename boost::graph_traits::halfedge_descriptor halfedge_descriptor; - typedef typename GetVertexPointMap::const_type VPM; - typedef typename boost::property_traits::reference Point_ref; - VPM vpm = choose_param(get_param(np, internal_np::vertex_point), - get_const_property_map(vertex_point, tmesh)); + typedef typename boost::property_traits::reference Point_ref; + typedef typename Traits::Vector_3 Vector_3; - CGAL_assertion( !is_border(e, tmesh) ); + CGAL_precondition(!is_border(e, tmesh)); halfedge_descriptor h = halfedge(e, tmesh); @@ -287,10 +284,26 @@ bool should_flip(typename boost::graph_traits::edge_descriptor e, * the scalar product will be negative. */ - double p1p3 = CGAL::cross_product(p2-p1,p3-p2) * CGAL::cross_product(p0-p3,p1-p0); - double p0p2 = CGAL::cross_product(p1-p0,p1-p2) * CGAL::cross_product(p3-p2,p3-p0); +// CGAL::cross_product(p2-p1, p3-p2) * CGAL::cross_product(p0-p3, p1-p0); +// CGAL::cross_product(p1-p0, p1-p2) * CGAL::cross_product(p3-p2, p3-p0); - return p0p2<=p1p3; + const Vector_3 v01 = gt.construct_vector_3_object()(p0, p1); + const Vector_3 v12 = gt.construct_vector_3_object()(p1, p2); + const Vector_3 v23 = gt.construct_vector_3_object()(p2, p3); + const Vector_3 v30 = gt.construct_vector_3_object()(p3, p0); + + const double p1p3 = gt.compute_scalar_product_3_object()( + gt.construct_cross_product_vector_3_object()(v12, v23), + gt.construct_cross_product_vector_3_object()(v30, v01)); + + const Vector_3 v21 = gt.construct_opposite_vector_3_object()(v12); + const Vector_3 v03 = gt.construct_opposite_vector_3_object()(v30); + + const double p0p2 = gt.compute_scalar_product_3_object()( + gt.construct_cross_product_vector_3_object()(v01, v21), + gt.construct_cross_product_vector_3_object()(v23, v03)); + + return p0p2 <= p1p3; } } // namespace internal @@ -299,20 +312,42 @@ bool should_flip(typename boost::graph_traits::edge_descriptor e, template bool remove_almost_degenerate_faces(const FaceRange& face_range, TriangleMesh& tmesh, + const double cap_threshold, + const double needle_threshold, + const double collapse_length_threshold, const NamedParameters& np) { + using CGAL::parameters::choose_parameter; + using CGAL::parameters::get_parameter; + typedef typename boost::graph_traits::vertex_descriptor vertex_descriptor; typedef typename boost::graph_traits::halfedge_descriptor halfedge_descriptor; typedef typename boost::graph_traits::edge_descriptor edge_descriptor; typedef typename boost::graph_traits::face_descriptor face_descriptor; + typedef typename internal_np::Lookup_named_param_def //default + > ::type ECM; + ECM ecm = choose_parameter(get_parameter(np, internal_np::edge_is_constrained), + Constant_property_map(false) /*default*/); + + typedef typename GetVertexPointMap::const_type VPM; + VPM vpm = choose_parameter(get_parameter(np, internal_np::vertex_point), + get_const_property_map(vertex_point, tmesh)); + + typedef typename GetGeomTraits::type Traits; + Traits gt = choose_parameter(get_parameter(np, internal_np::geom_traits), Traits()); + std::set edges_to_collapse; std::set edges_to_flip; // @todo could probably do something a bit better by looping edges, consider the incident faces // f1 / f2 and look at f1 if f1 nc = internal::is_badly_shaped(face(h, tmesh), tmesh, np); - if(nc[0]!=h) + std::array nc = + internal::is_badly_shaped(face(h, tmesh), tmesh, vpm, ecm, gt, + cap_threshold, needle_threshold, collapse_length_threshold); + + if(nc[0] != h) { #ifdef CGAL_PMP_DEBUG_REMOVE_DEGENERACIES std::cerr << "Warning: Needle criteria no longer verified " << tmesh.point(source(e, tmesh)) << " " @@ -367,8 +406,12 @@ bool remove_almost_degenerate_faces(const FaceRange& face_range, #endif // the opposite edge might also have been inserted in the set and might still be a needle h = opposite(h, tmesh); - if(is_border(h, tmesh) ) continue; - nc = internal::is_badly_shaped(face(h, tmesh), tmesh, np); + if(is_border(h, tmesh)) + continue; + + nc = internal::is_badly_shaped(face(h, tmesh), tmesh, vpm, ecm, gt, + cap_threshold, needle_threshold, + collapse_length_threshold); if(nc[0] != h) continue; } @@ -377,18 +420,19 @@ bool remove_almost_degenerate_faces(const FaceRange& face_range, { if(!is_border(h, tmesh)) { - edge_descriptor pe=edge(prev(h,tmesh), tmesh); + edge_descriptor pe = edge(prev(h, tmesh), tmesh); edges_to_flip.erase(pe); next_edges_to_collapse.erase(pe); edges_to_collapse.erase(pe); } + h = opposite(h, tmesh); } // pick the orientation of edge to keep the vertex minimizing the volume variation - h = internal::get_best_edge_orientation(e, tmesh, np); + h = internal::get_best_edge_orientation(e, tmesh, vpm, gt); - if(h == boost::graph_traits::null_halfedge() ) + if(h == boost::graph_traits::null_halfedge()) { #ifdef CGAL_PMP_DEBUG_REMOVE_DEGENERACIES std::cerr << "Warning: geometrically invalid edge collapse! " @@ -403,7 +447,7 @@ bool remove_almost_degenerate_faces(const FaceRange& face_range, next_edges_to_collapse.erase(e); // for edges added in faces incident to a vertex kept after a collapse #ifdef CGAL_PMP_DEBUG_REMOVE_DEGENERACIES_EXTRA std::cerr << " " << kk << " -- Collapsing " << tmesh.point(source(h, tmesh)) << " " - << tmesh.point(target(h, tmesh)) << std::endl; + << tmesh.point(target(h, tmesh)) << std::endl; #endif // moving to the midpoint is not a good idea. On a circle for example you might endpoint with // a bad geometry because you iteratively move one point @@ -413,8 +457,14 @@ bool remove_almost_degenerate_faces(const FaceRange& face_range, //tmesh.point(v) = mp; // examine all faces incident to the vertex kept for(halfedge_descriptor hv : halfedges_around_target(v, tmesh)) + { if(!is_border(hv, tmesh)) - internal::collect_badly_shaped_triangles(face(hv, tmesh), tmesh, edges_to_collapse, edges_to_flip, np); + { + internal::collect_badly_shaped_triangles(face(hv, tmesh), tmesh, vpm, ecm, gt, + cap_threshold, needle_threshold, collapse_length_threshold, + edges_to_collapse, edges_to_flip); + } + } #ifdef CGAL_PMP_DEBUG_REMOVE_DEGENERACIES_EXTRA std::string nb = std::to_string(++kk); @@ -447,28 +497,34 @@ bool remove_almost_degenerate_faces(const FaceRange& face_range, edges_to_flip.erase(edges_to_flip.begin()); #ifdef CGAL_PMP_DEBUG_REMOVE_DEGENERACIES - std::cout << "treat cap: " << e << " (" << tmesh.point(source (e, tmesh)) << " --- " << tmesh.point(target(e, tmesh)) << ")" << std::endl; + std::cout << "treat cap: " << e << " (" << tmesh.point(source(e, tmesh)) + << " --- " << tmesh.point(target(e, tmesh)) << ")" << std::endl; #endif halfedge_descriptor h = halfedge(e, tmesh); - std::array nc = internal::is_badly_shaped(face(h, tmesh), tmesh, np); + std::array nc = internal::is_badly_shaped(face(h, tmesh), tmesh, vpm, ecm, gt, + cap_threshold, needle_threshold, + collapse_length_threshold); // First check the triangle is still a cap - if(nc[1]!=h) + if(nc[1] != h) { #ifdef CGAL_PMP_DEBUG_REMOVE_DEGENERACIES std::cerr << "Warning: Cap criteria no longer verified " << tmesh.point(source(e, tmesh)) << " --- " - << tmesh.point(target(e, tmesh)) << std::endl; + << tmesh.point(target(e, tmesh)) << std::endl; #endif // the opposite edge might also have been inserted in the set and might still be a cap h = opposite(h, tmesh); - if(is_border(h, tmesh) ) continue; - nc = internal::is_badly_shaped(face(h, tmesh), tmesh, np); + if(is_border(h, tmesh)) + continue; + + nc = internal::is_badly_shaped(face(h, tmesh), tmesh, vpm, ecm, gt, + cap_threshold, needle_threshold, collapse_length_threshold); if(nc[1] != h) continue; } // special case on the border - if(is_border(opposite(h, tmesh), tmesh) ) + if(is_border(opposite(h, tmesh), tmesh)) { // remove the triangle edges_to_flip.erase(edge(prev(h, tmesh), tmesh)); @@ -485,7 +541,7 @@ bool remove_almost_degenerate_faces(const FaceRange& face_range, target(next(opposite(h, tmesh), tmesh), tmesh), tmesh).second) { - if(!internal::should_flip(e, tmesh, np)) + if(!internal::should_flip(e, tmesh, vpm, gt)) { #ifdef CGAL_PMP_DEBUG_REMOVE_DEGENERACIES std::cout << "Flipping prevented: not the best diagonal" << std::endl; @@ -493,6 +549,7 @@ bool remove_almost_degenerate_faces(const FaceRange& face_range, next_edges_to_flip.insert(e); continue; } + #ifdef CGAL_PMP_DEBUG_REMOVE_DEGENERACIES std::cout << "Flipping" << std::endl; #endif @@ -502,26 +559,29 @@ bool remove_almost_degenerate_faces(const FaceRange& face_range, << tmesh.point(target(h, tmesh)) << std::endl; #endif Euler::flip_edge(h, tmesh); - CGAL_assertion( edge(h, tmesh) == e ); + CGAL_assertion(edge(h, tmesh) == e); // handle face updates for(int i=0; i<2; ++i) { CGAL_assertion(!is_border(h, tmesh)); - std::array nc = internal::is_badly_shaped(face(h, tmesh), tmesh, np); - if(nc[1]!=boost::graph_traits::null_halfedge()) + std::array nc = + internal::is_badly_shaped(face(h, tmesh), tmesh, vpm, ecm, gt, + cap_threshold, needle_threshold, collapse_length_threshold); + + if(nc[1] != boost::graph_traits::null_halfedge()) { if(edge(nc[1], tmesh) != e) - next_edges_to_flip.insert( edge(nc[1], tmesh) ); + next_edges_to_flip.insert(edge(nc[1], tmesh)); } else { - if(nc[0]!=boost::graph_traits::null_halfedge()) + if(nc[0] != boost::graph_traits::null_halfedge()) { next_edges_to_collapse.insert(edge(nc[0], tmesh)); } } - h=opposite(h, tmesh); + h = opposite(h, tmesh); } something_was_done = true; } @@ -555,22 +615,36 @@ bool remove_almost_degenerate_faces(const FaceRange& face_range, template bool remove_almost_degenerate_faces(const FaceRange& face_range, - TriangleMesh& tmesh) + TriangleMesh& tmesh, + const double cap_threshold, + const double needle_threshold, + const double collapse_length_threshold) { - return remove_almost_degenerate_faces(face_range, tmesh, parameters::all_default()); + return remove_almost_degenerate_faces(face_range, tmesh, + cap_threshold, needle_threshold, collapse_length_threshold, + CGAL::parameters::all_default()); } template bool remove_almost_degenerate_faces(TriangleMesh& tmesh, + const double cap_threshold, + const double needle_threshold, + const double collapse_length_threshold, const CGAL_PMP_NP_CLASS& np) { - return remove_almost_degenerate_faces(faces(tmesh), tmesh, np); + return remove_almost_degenerate_faces(faces(tmesh), tmesh, cap_threshold, needle_threshold, + collapse_length_threshold, np); } template -bool remove_almost_degenerate_faces(TriangleMesh& tmesh) +bool remove_almost_degenerate_faces(TriangleMesh& tmesh, + const double cap_threshold, + const double needle_threshold, + const double collapse_length_threshold) { - return remove_almost_degenerate_faces(tmesh, CGAL::parameters::all_default()); + return remove_almost_degenerate_faces(faces(tmesh), tmesh, + cap_threshold, needle_threshold, collapse_length_threshold, + CGAL::parameters::all_default()); } } // namespace Polygon_mesh_processing From a6ff3301909e6ab0e239f764ac1f5084ec08a21e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mael=20Rouxel-Labb=C3=A9?= Date: Tue, 24 Sep 2019 17:32:50 +0200 Subject: [PATCH 169/363] Use traits' functors --- .../Polygon_mesh_processing/remove_degeneracies.h | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/remove_degeneracies.h b/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/remove_degeneracies.h index e241561e8ca..b7289a2282c 100644 --- a/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/remove_degeneracies.h +++ b/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/remove_degeneracies.h @@ -181,7 +181,9 @@ boost::optional get_collapse_volume(typename boost::graph_traits::halfedge_descriptor halfedge_descriptor; + typedef typename boost::property_traits::reference Point_ref; + typedef typename Traits::Vector_3 Vector_3; const typename Traits::Point_3 origin(ORIGIN); @@ -211,9 +213,13 @@ boost::optional get_collapse_volume(typename boost::graph_traits Date: Tue, 24 Sep 2019 18:02:33 +0200 Subject: [PATCH 170/363] Add support for VCM --- .../remove_degeneracies.h | 62 +++++++++++++++++-- 1 file changed, 56 insertions(+), 6 deletions(-) diff --git a/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/remove_degeneracies.h b/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/remove_degeneracies.h index b7289a2282c..b6e5fc424c6 100644 --- a/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/remove_degeneracies.h +++ b/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/remove_degeneracies.h @@ -28,6 +28,7 @@ #include #include +#include #include #include #include @@ -231,17 +232,26 @@ boost::optional get_collapse_volume(typename boost::graph_traits +template typename boost::graph_traits::halfedge_descriptor get_best_edge_orientation(typename boost::graph_traits::edge_descriptor e, const TriangleMesh& tmesh, const VPM& vpm, + const VCM& vcm, const Traits& gt) { typedef typename boost::graph_traits::halfedge_descriptor halfedge_descriptor; halfedge_descriptor h = halfedge(e, tmesh), ho = opposite(h, tmesh); + CGAL_assertion(!get(vcm, source(h, tmesh)) || !get(vcm, target(h, tmesh))); + + // the resulting point of the collapse of a halfedge is the target of the halfedge before collapse + if(get(vcm, source(h, tmesh))) + return ho; + if(get(vcm, target(h, tmesh))) + return h; + boost::optional dv1 = get_collapse_volume(h, tmesh, vpm, gt); boost::optional dv2 = get_collapse_volume(ho, tmesh, vpm, gt); @@ -331,12 +341,17 @@ bool remove_almost_degenerate_faces(const FaceRange& face_range, typedef typename boost::graph_traits::edge_descriptor edge_descriptor; typedef typename boost::graph_traits::face_descriptor face_descriptor; + typedef Constant_property_map Default_VCM; + typedef typename internal_np::Lookup_named_param_def::type VCM; + VCM vcm_np = choose_parameter(get_parameter(np, internal_np::vertex_is_constrained), Default_VCM(false)); + + typedef Constant_property_map Default_ECM; typedef typename internal_np::Lookup_named_param_def //default - > ::type ECM; - ECM ecm = choose_parameter(get_parameter(np, internal_np::edge_is_constrained), - Constant_property_map(false) /*default*/); + Default_ECM>::type ECM; + ECM ecm = choose_parameter(get_parameter(np, internal_np::edge_is_constrained), Default_ECM(false)); typedef typename GetVertexPointMap::const_type VPM; VPM vpm = choose_parameter(get_parameter(np, internal_np::vertex_point), @@ -345,6 +360,30 @@ bool remove_almost_degenerate_faces(const FaceRange& face_range, typedef typename GetGeomTraits::type Traits; Traits gt = choose_parameter(get_parameter(np, internal_np::geom_traits), Traits()); + // Vertex property map that combines the VCM and the fact that extremities of a constrained edge should be constrained + typedef CGAL::dynamic_vertex_property_t Vertex_property_tag; + typedef typename boost::property_map::type DVCM; + DVCM vcm = get(Vertex_property_tag(), tmesh); + + for(face_descriptor f : face_range) + { + if(f == boost::graph_traits::null_face()) + continue; + + for(halfedge_descriptor h : CGAL::halfedges_around_face(halfedge(f, tmesh), tmesh)) + { + if(get(vcm_np, target(h, tmesh))) + put(vcm, target(h, tmesh), true); + + if(get(ecm, edge(h, tmesh))) + { + put(vcm, source(h, tmesh), true); + put(vcm, target(h, tmesh), true); + } + } + } + + // Start the process of removing bad elements std::set edges_to_collapse; std::set edges_to_flip; @@ -390,6 +429,11 @@ bool remove_almost_degenerate_faces(const FaceRange& face_range, edge_descriptor e = *edges_to_collapse.begin(); edges_to_collapse.erase(edges_to_collapse.begin()); + CGAL_assertion(!get(ecm, e)); + + if(get(vcm, source(e, tmesh)) && get(vcm, target(e, tmesh))) + continue; + #ifdef CGAL_PMP_DEBUG_REMOVE_DEGENERACIES std::cout << " treat needle: " << e << " (" << tmesh.point(source (e, tmesh)) << " --- " << tmesh.point(target(e, tmesh)) << ")" << std::endl; @@ -436,7 +480,7 @@ bool remove_almost_degenerate_faces(const FaceRange& face_range, } // pick the orientation of edge to keep the vertex minimizing the volume variation - h = internal::get_best_edge_orientation(e, tmesh, vpm, gt); + h = internal::get_best_edge_orientation(e, tmesh, vpm, vcm, gt); if(h == boost::graph_traits::null_halfedge()) { @@ -458,6 +502,7 @@ bool remove_almost_degenerate_faces(const FaceRange& face_range, // moving to the midpoint is not a good idea. On a circle for example you might endpoint with // a bad geometry because you iteratively move one point // auto mp = midpoint(tmesh.point(source(h, tmesh)), tmesh.point(target(h, tmesh))); + vertex_descriptor v = Euler::collapse_edge(edge(h, tmesh), tmesh); //tmesh.point(v) = mp; @@ -502,6 +547,11 @@ bool remove_almost_degenerate_faces(const FaceRange& face_range, edge_descriptor e = *edges_to_flip.begin(); edges_to_flip.erase(edges_to_flip.begin()); + CGAL_assertion(!get(ecm, e)); + + if(get(vcm, source(e, tmesh)) && get(vcm, target(e, tmesh))) + continue; + #ifdef CGAL_PMP_DEBUG_REMOVE_DEGENERACIES std::cout << "treat cap: " << e << " (" << tmesh.point(source(e, tmesh)) << " --- " << tmesh.point(target(e, tmesh)) << ")" << std::endl; From 3bd071175ecf9b20a9db31027c4a631cce469355 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mael=20Rouxel-Labb=C3=A9?= Date: Wed, 25 Sep 2019 09:40:21 +0200 Subject: [PATCH 171/363] Tiny optimization --- .../CGAL/Polygon_mesh_processing/remove_degeneracies.h | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/remove_degeneracies.h b/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/remove_degeneracies.h index b6e5fc424c6..f6d8117873e 100644 --- a/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/remove_degeneracies.h +++ b/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/remove_degeneracies.h @@ -372,14 +372,15 @@ bool remove_almost_degenerate_faces(const FaceRange& face_range, for(halfedge_descriptor h : CGAL::halfedges_around_face(halfedge(f, tmesh), tmesh)) { - if(get(vcm_np, target(h, tmesh))) - put(vcm, target(h, tmesh), true); - if(get(ecm, edge(h, tmesh))) { put(vcm, source(h, tmesh), true); put(vcm, target(h, tmesh), true); } + else if(get(vcm_np, target(h, tmesh))) + { + put(vcm, target(h, tmesh), true); + } } } From b831e41013b95b11a392b3e0190c558a694c296a Mon Sep 17 00:00:00 2001 From: Maxime Gimeno Date: Wed, 25 Sep 2019 13:03:12 +0200 Subject: [PATCH 172/363] Use a bbox in Side-of_triangle_mesh until a request is inside, only then use the tree. Make it faster when working with disjoint meshes. --- .../include/CGAL/Side_of_triangle_mesh.h | 22 ++++++++++++++++++- 1 file changed, 21 insertions(+), 1 deletion(-) diff --git a/Polygon_mesh_processing/include/CGAL/Side_of_triangle_mesh.h b/Polygon_mesh_processing/include/CGAL/Side_of_triangle_mesh.h index 7b5b1254f43..10e75779b99 100644 --- a/Polygon_mesh_processing/include/CGAL/Side_of_triangle_mesh.h +++ b/Polygon_mesh_processing/include/CGAL/Side_of_triangle_mesh.h @@ -28,6 +28,7 @@ #include #include +#include #include #include @@ -104,6 +105,8 @@ class Side_of_triangle_mesh typename GeomTraits::Construct_vector_3 vector_functor; const AABB_tree_* tree_ptr; bool own_tree; + CGAL::Bbox_3 box; + mutable bool tree_built; public: @@ -135,6 +138,8 @@ public: tree_ptr = new AABB_tree(faces(tmesh).first, faces(tmesh).second, tmesh, vpmap); + box = Polygon_mesh_processing::bbox(tmesh, parameters::vertex_point_map(vpmap)); + tree_built = false; } /** @@ -157,6 +162,8 @@ public: tree_ptr = new AABB_tree(faces(tmesh).first, faces(tmesh).second, tmesh); + box = Polygon_mesh_processing::bbox(tmesh); + tree_built = false; } /** @@ -195,8 +202,21 @@ public: */ Bounded_side operator()(const Point& point) const { + bool is_outside = tree_built; + if(!is_outside){ + is_outside = (point.x() < box.xmin() + || point.x() > box.xmax() + || point.y() < box.ymin() + || point.y() > box.ymax() + || point.z() < box.zmin() + || point.z() > box.zmax()); + if(is_outside) + return CGAL::ON_UNBOUNDED_SIDE; + } + + tree_built = true; return internal::Point_inside_vertical_ray_cast()( - point, *tree_ptr, ray_functor, vector_functor); + point, *tree_ptr, ray_functor, vector_functor); } }; From 6cedfac39a45e8a9849f0363708657a8728f91f9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9bastien=20Loriot?= Date: Fri, 27 Sep 2019 08:35:03 +0200 Subject: [PATCH 173/363] move code to internal/experimental and example to test also update test that was no longer compiling --- .../Polygon_mesh_processing/CMakeLists.txt | 1 - .../{ => internal}/remove_degeneracies.h | 3 + .../Polygon_mesh_processing/CMakeLists.txt | 1 + .../test/Polygon_mesh_processing/data/pig.off | 1361 +++++++++++++++++ .../test_remove_caps_needles.cpp} | 8 +- 5 files changed, 1370 insertions(+), 4 deletions(-) rename Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/{ => internal}/remove_degeneracies.h (99%) create mode 100644 Polygon_mesh_processing/test/Polygon_mesh_processing/data/pig.off rename Polygon_mesh_processing/{examples/Polygon_mesh_processing/clean_degeneracies.cpp => test/Polygon_mesh_processing/test_remove_caps_needles.cpp} (80%) diff --git a/Polygon_mesh_processing/examples/Polygon_mesh_processing/CMakeLists.txt b/Polygon_mesh_processing/examples/Polygon_mesh_processing/CMakeLists.txt index b08791a0ff8..88701b9e196 100644 --- a/Polygon_mesh_processing/examples/Polygon_mesh_processing/CMakeLists.txt +++ b/Polygon_mesh_processing/examples/Polygon_mesh_processing/CMakeLists.txt @@ -85,7 +85,6 @@ create_single_source_cgal_program( "detect_features_example.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( "clean_degeneracies.cpp" ) if(OpenMesh_FOUND) create_single_source_cgal_program( "compute_normals_example_OM.cpp" ) diff --git a/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/remove_degeneracies.h b/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/internal/remove_degeneracies.h similarity index 99% rename from Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/remove_degeneracies.h rename to Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/internal/remove_degeneracies.h index f6d8117873e..d5fafb09f48 100644 --- a/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/remove_degeneracies.h +++ b/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/internal/remove_degeneracies.h @@ -324,6 +324,8 @@ bool should_flip(typename boost::graph_traits::edge_descriptor e, } // namespace internal +namespace experimental { + // @todo check what to use as priority queue with removable elements, set might not be optimal template bool remove_almost_degenerate_faces(const FaceRange& face_range, @@ -704,6 +706,7 @@ bool remove_almost_degenerate_faces(TriangleMesh& tmesh, CGAL::parameters::all_default()); } +} // namespace experimental } // namespace Polygon_mesh_processing } // namespace CGAL diff --git a/Polygon_mesh_processing/test/Polygon_mesh_processing/CMakeLists.txt b/Polygon_mesh_processing/test/Polygon_mesh_processing/CMakeLists.txt index 40a606b3124..02f55be25dd 100644 --- a/Polygon_mesh_processing/test/Polygon_mesh_processing/CMakeLists.txt +++ b/Polygon_mesh_processing/test/Polygon_mesh_processing/CMakeLists.txt @@ -95,6 +95,7 @@ endif() create_single_source_cgal_program("remove_degeneracies_test.cpp") create_single_source_cgal_program("test_pmp_manifoldness.cpp") create_single_source_cgal_program("test_mesh_smoothing.cpp") + create_single_source_cgal_program("test_remove_caps_needles.cpp") if( TBB_FOUND ) CGAL_target_use_TBB(test_pmp_distance) diff --git a/Polygon_mesh_processing/test/Polygon_mesh_processing/data/pig.off b/Polygon_mesh_processing/test/Polygon_mesh_processing/data/pig.off new file mode 100644 index 00000000000..a6cd4ef4653 --- /dev/null +++ b/Polygon_mesh_processing/test/Polygon_mesh_processing/data/pig.off @@ -0,0 +1,1361 @@ +OFF +468 891 0 +0.063974 0.101970 -0.415827 +0.028523 0.114259 -0.442328 +0.063412 0.118087 -0.415381 +0.077614 0.162174 -0.435627 +0.128990 0.122892 -0.393541 +0.122864 -0.147913 0.401369 +0.178320 -0.063881 0.376630 +0.131227 -0.089511 0.441084 +0.164639 -0.008344 0.415245 +0.103820 -0.043044 -0.278399 +0.091834 -0.084101 -0.204746 +0.079859 -0.055424 -0.310790 +0.118637 -0.026027 -0.235186 +0.099707 0.153598 0.166104 +0.094930 0.196480 0.152483 +0.115864 0.191688 0.136248 +0.171734 0.181103 0.136002 +0.193585 0.183376 0.154622 +0.164526 0.109059 0.214381 +-0.153221 0.150924 -0.394866 +-0.081493 0.167834 -0.436769 +-0.072517 0.124239 -0.414300 +-0.161186 0.176848 -0.378966 +-0.176790 0.132941 -0.334836 +-0.171249 0.164538 -0.303896 +-0.080475 0.201851 -0.109296 +-0.071494 0.183497 -0.140195 +-0.097522 0.199020 -0.144832 +-0.056652 0.190914 -0.054368 +-0.039241 0.197263 -0.153247 +-0.141604 0.199711 -0.154047 +-0.129425 0.157767 -0.137661 +-0.165583 0.197728 -0.148208 +-0.190944 0.201695 -0.114791 +-0.184883 0.199199 -0.132786 +-0.178540 0.131594 -0.070966 +-0.153766 0.018107 -0.272151 +-0.130012 -0.023104 -0.280793 +-0.113295 -0.035252 -0.248969 +-0.199246 0.193683 0.195561 +-0.180750 0.123251 0.255085 +-0.181651 0.208804 0.233547 +-0.193764 0.183287 0.154611 +-0.183901 0.083655 0.279856 +-0.171726 0.068282 0.231479 +0.149160 0.094349 0.371830 +0.173037 0.085349 0.334114 +0.168678 0.151411 0.318997 +-0.168351 0.090355 0.342446 +-0.191982 0.004460 0.346603 +0.010306 -0.068937 0.495666 +-0.054048 -0.045698 0.495964 +-0.036648 -0.113382 0.498431 +0.049415 -0.137244 0.485860 +-0.135590 0.204770 -0.026654 +-0.164959 0.204458 -0.052698 +-0.119997 0.140111 0.025175 +0.172825 0.080263 -0.317843 +0.160628 0.062369 -0.340044 +0.177177 0.143953 -0.350070 +0.118606 0.021487 -0.375861 +0.165354 0.008939 -0.353730 +0.237839 0.022829 -0.306004 +0.212030 0.037710 -0.318516 +0.235958 0.004327 -0.346347 +0.269290 -0.012961 -0.323921 +0.177418 -0.011732 -0.301843 +0.134912 0.006718 -0.402388 +0.237840 -0.015554 -0.414292 +0.177088 -0.010878 -0.417488 +0.234583 -0.001111 -0.396570 +0.165512 -0.038754 -0.394103 +0.274848 -0.015963 -0.391667 +0.284810 -0.026997 -0.376984 +0.281300 -0.029101 -0.338206 +0.217331 -0.034592 -0.352687 +0.196409 -0.028130 -0.326693 +0.146613 0.129225 0.183979 +0.125633 0.114296 0.184366 +0.168417 0.063049 0.228672 +0.131279 0.094069 0.157481 +0.093427 0.144615 0.148946 +0.151538 0.030944 0.165340 +0.040532 0.197143 -0.154026 +0.056681 0.209038 -0.212225 +0.002775 0.206856 -0.166610 +0.117369 0.153354 -0.205966 +0.124488 0.200090 -0.152498 +0.086066 0.183902 -0.142107 +0.091309 0.198441 -0.138090 +0.064272 0.187025 -0.133132 +0.080301 0.201940 -0.109295 +0.087605 0.207177 -0.050256 +0.071100 0.186484 -0.043141 +0.144787 0.163143 -0.404482 +0.163037 0.176611 -0.376916 +0.093064 0.199241 -0.432443 +0.133133 0.208266 -0.382604 +0.143249 0.191538 -0.272444 +0.158095 0.192739 -0.314330 +-0.139488 0.186720 -0.261262 +-0.151500 0.199626 -0.324260 +-0.098372 0.223627 -0.288685 +-0.078536 0.189639 -0.197355 +-0.039805 0.227673 -0.260155 +0.097127 0.229527 -0.341482 +0.062369 0.228756 -0.395152 +0.036595 0.231173 -0.450000 +-0.028016 0.125004 -0.448876 +-0.036461 0.096667 -0.434533 +-0.083077 0.090894 -0.414311 +-0.082268 0.070800 -0.428081 +-0.123341 -0.003528 -0.217671 +-0.111649 -0.041351 -0.203434 +-0.143481 0.129458 -0.120457 +-0.166571 0.125111 -0.100292 +-0.091445 0.155603 -0.139780 +-0.108949 0.126603 -0.132705 +-0.155764 -0.002392 -0.117269 +-0.109909 -0.047484 -0.302472 +-0.091801 -0.053960 -0.282808 +-0.111273 -0.076464 -0.152548 +-0.089774 -0.101654 -0.175408 +-0.131191 -0.018764 -0.145092 +-0.117239 -0.118603 -0.106400 +-0.186719 -0.019496 0.218873 +0.094316 -0.206017 0.232131 +0.055117 -0.224837 0.203521 +0.079552 -0.189464 0.070678 +0.040403 -0.204104 0.063479 +0.071493 -0.170167 -0.083686 +-0.180726 -0.068980 0.362373 +-0.182633 -0.099623 0.308202 +-0.158938 -0.138266 0.334999 +0.085658 0.200413 0.176418 +0.065852 0.170004 0.177725 +-0.001292 0.195544 -0.033434 +-0.285400 -0.031989 -0.344981 +-0.271603 -0.015198 -0.325428 +-0.278372 -0.020235 -0.389284 +-0.206668 0.006555 -0.349794 +-0.225044 -0.007684 -0.420462 +-0.238803 0.004342 -0.347955 +-0.158634 0.013703 -0.350809 +-0.228727 0.004252 -0.318223 +-0.223154 0.035457 -0.308571 +-0.193549 0.057123 -0.317739 +-0.210450 -0.029622 -0.405169 +0.172645 -0.045708 -0.037575 +0.158143 -0.075581 -0.062747 +0.161129 -0.053779 -0.087832 +0.151586 -0.077141 0.017952 +0.172046 0.216581 0.250518 +0.160045 0.220693 0.263343 +0.199056 0.193772 0.195561 +0.181331 0.122923 0.257005 +0.183238 0.081029 0.279971 +0.186394 0.009376 0.360522 +0.200356 -0.009475 0.302375 +0.186432 0.204012 -0.088367 +0.166519 0.185025 -0.035652 +0.178625 0.148640 -0.039831 +0.162273 -0.038823 0.020282 +0.164324 0.000657 0.028308 +0.191989 -0.031903 0.230015 +0.188950 -0.072032 0.237843 +0.159438 -0.018081 0.152399 +0.179961 -0.012368 0.206350 +0.154184 -0.071463 0.150146 +0.157446 -0.054932 0.128257 +0.146606 -0.094660 0.103787 +-0.085574 0.204703 0.235486 +-0.100152 0.207801 0.255866 +-0.059913 0.174502 0.263217 +-0.177675 0.138122 0.302573 +-0.166640 0.138235 0.331535 +-0.160235 0.220604 0.263332 +0.065130 0.176233 0.262848 +0.085351 0.204781 0.235497 +0.062759 0.177657 0.222293 +0.099947 0.207890 0.255911 +0.029319 0.167713 0.235458 +-0.007308 0.176521 0.212726 +0.018184 0.155832 0.282328 +0.016196 0.134242 0.331153 +-0.115478 0.114685 0.373666 +-0.138087 0.098705 0.375545 +-0.107498 0.047438 0.447839 +-0.136533 0.029923 0.438192 +-0.151444 0.150957 0.333934 +-0.128669 0.172997 0.320075 +-0.141960 0.217696 0.269060 +-0.070700 0.154566 0.313918 +-0.089073 0.135316 0.352129 +0.113012 -0.180473 0.171463 +0.103166 -0.168475 0.072737 +0.137034 -0.171125 0.287599 +0.153718 -0.147893 0.232349 +0.149223 0.117836 -0.382727 +0.122958 0.086674 -0.404777 +0.070966 0.060503 -0.432879 +0.046513 0.085855 -0.431266 +0.092912 0.013673 -0.404533 +0.090952 -0.016720 -0.385023 +0.077405 -0.042537 -0.356280 +0.058093 -0.059147 -0.335116 +0.068427 -0.123215 -0.187213 +0.101335 -0.132006 -0.117248 +0.097814 -0.149292 -0.079001 +0.122020 -0.125228 -0.016951 +0.126097 -0.138388 0.097790 +0.126318 -0.145156 0.141802 +0.174282 -0.112276 0.330051 +0.190029 -0.084340 0.294626 +0.058942 -0.222818 0.301995 +0.098418 -0.193164 0.340401 +0.058809 -0.206985 0.375651 +0.021923 -0.222862 0.367343 +0.014505 -0.238117 0.299646 +0.122283 0.121443 0.075831 +0.113763 0.148142 0.020311 +0.140282 0.123337 0.018261 +0.027980 -0.177863 -0.119253 +0.026130 -0.193179 -0.070708 +-0.001321 -0.211350 0.079165 +-0.001523 -0.197311 -0.066313 +0.166925 0.094073 -0.266778 +0.163733 0.142170 -0.259072 +0.127467 0.088406 -0.181953 +0.150376 0.077937 0.039615 +0.190766 0.201784 -0.114791 +0.178517 0.136767 -0.071037 +0.184704 0.199288 -0.132775 +0.166379 0.133552 -0.102642 +0.165222 0.047122 -0.102044 +0.078264 0.226830 -0.278641 +0.019112 0.233265 -0.274429 +-0.039110 -0.233486 0.287357 +-0.021609 -0.223013 0.367699 +0.001943 -0.188166 0.439819 +-0.066652 -0.213379 0.338708 +0.027726 -0.233930 0.210941 +-0.000203 -0.237188 0.219039 +-0.136376 -0.172085 0.288837 +-0.099814 -0.201744 0.258297 +-0.027582 -0.234160 0.217991 +-0.060662 -0.218919 0.186226 +-0.055734 -0.201562 0.080354 +-0.029186 -0.209148 0.081362 +-0.029001 -0.192501 -0.071644 +-0.160342 0.063827 0.024713 +-0.177523 0.015890 -0.001911 +-0.162105 0.020607 0.040724 +-0.180080 0.125890 -0.032858 +-0.185297 0.023823 -0.038772 +-0.175803 -0.030161 -0.021666 +-0.149501 -0.083919 0.026313 +-0.160461 -0.041091 0.033786 +-0.156993 -0.049877 0.148952 +-0.179046 0.029177 -0.073993 +-0.177954 -0.024883 -0.058372 +-0.151976 0.126423 -0.229667 +-0.163106 0.092405 -0.253555 +-0.121432 0.099265 -0.173188 +-0.111794 0.137703 -0.178117 +-0.166077 0.091402 -0.340017 +-0.161312 0.070001 -0.345025 +-0.167665 0.059706 -0.282855 +-0.171035 0.078014 -0.296062 +-0.126978 0.030384 -0.171087 +-0.129126 0.050437 -0.192177 +-0.131368 0.059086 -0.126361 +-0.134950 0.025663 -0.131342 +-0.143437 -0.069595 -0.109286 +-0.148269 -0.039929 -0.120515 +-0.163978 -0.065334 -0.065543 +-0.167235 -0.061629 -0.042774 +0.002745 0.189510 0.110554 +0.036689 0.188942 0.019665 +-0.036527 0.174422 0.177147 +-0.087796 0.207088 -0.050265 +-0.076524 0.172540 0.006138 +-0.087508 0.177933 -0.017043 +-0.108099 0.206330 -0.029115 +-0.072629 0.172458 0.181190 +-0.090040 0.162292 0.168261 +-0.089665 0.198396 0.161152 +-0.063826 0.178856 0.211964 +-0.149794 0.182785 0.130788 +-0.116064 0.191599 0.136236 +-0.150418 0.160583 0.151346 +-0.171912 0.181013 0.135924 +-0.138972 0.123679 0.183787 +-0.105455 0.169777 0.154956 +-0.106937 0.141313 0.167043 +-0.064997 0.162208 0.148704 +-0.089200 0.146757 0.141467 +-0.116460 0.121274 0.141967 +0.130312 0.041995 0.435860 +0.129704 -0.002210 0.453987 +0.119563 0.095019 0.389830 +0.106258 -0.067817 0.474757 +0.072458 -0.092968 0.490348 +0.035744 -0.100524 0.501598 +0.090915 -0.018706 0.481902 +0.063954 -0.018620 0.488394 +0.012687 0.019863 0.473158 +-0.066639 0.014188 0.477250 +-0.001853 -0.014358 0.486138 +-0.073991 0.051995 0.453618 +0.015992 0.056915 0.445325 +-0.072272 0.083609 0.419400 +0.125713 0.148591 0.340006 +0.151075 0.147959 0.335541 +0.120626 0.212102 0.266920 +0.069491 0.149561 0.322080 +0.091434 0.136280 0.349720 +0.076196 0.038920 0.461948 +0.080702 0.078897 0.423801 +0.006477 0.083890 0.414722 +0.003928 0.102802 0.385224 +-0.068084 0.039517 -0.430070 +-0.017676 0.023776 -0.427482 +0.193970 0.042648 -0.293997 +0.172856 0.064667 -0.285834 +0.158578 0.030796 -0.272331 +0.140866 -0.005417 -0.270488 +0.134432 0.029296 -0.214306 +0.126251 0.015555 -0.188439 +0.132124 0.003792 -0.136979 +0.125810 -0.029504 -0.153529 +0.129423 0.061526 -0.128092 +0.108063 0.127431 -0.132395 +0.091794 0.155522 -0.139751 +0.124048 0.145248 -0.131126 +0.184444 0.016147 -0.030529 +0.181489 -0.003989 -0.053023 +0.141425 0.199800 -0.154047 +0.165405 0.197817 -0.148141 +0.144876 0.183940 -0.146208 +0.154368 0.144703 -0.122262 +0.146068 0.119123 -0.117735 +0.154841 -0.033503 -0.111889 +0.143738 -0.032315 -0.128787 +0.113871 -0.078221 -0.157136 +0.112005 -0.054404 -0.183556 +0.010090 -0.146944 0.487883 +0.011570 -0.146473 0.485554 +0.010090 -0.136782 0.493756 +-0.015165 -0.128494 0.494118 +-0.010143 -0.136180 0.492642 +-0.030104 -0.153530 0.480762 +-0.010143 -0.146454 0.487048 +-0.006480 -0.157970 0.476349 +0.045456 -0.167686 0.453108 +0.029848 -0.154023 0.480267 +0.030579 -0.132753 -0.220866 +0.021176 -0.090002 -0.310105 +0.181147 0.115479 -0.036001 +0.175183 0.070269 -0.003253 +0.161619 0.042238 0.028286 +0.156945 0.037056 0.086395 +0.051155 0.182427 -0.491632 +0.031566 0.180896 -0.501667 +0.002176 0.193366 -0.489790 +-0.037122 0.180476 -0.500027 +-0.025020 0.194670 -0.492815 +0.055556 0.214167 -0.473439 +0.066526 0.214610 -0.467774 +-0.082413 0.208049 -0.429210 +-0.065055 0.215687 -0.469354 +-0.062206 0.204472 -0.479930 +-0.036973 0.231911 -0.450571 +-0.036983 0.226530 -0.458574 +-0.125722 0.187261 -0.415111 +-0.091376 0.197028 -0.433439 +-0.109535 0.220672 -0.374442 +-0.132871 0.206436 -0.383456 +-0.068993 0.234380 -0.324450 +-0.054731 0.231939 -0.379365 +-0.015007 0.238836 -0.387236 +0.010198 0.238083 -0.347126 +-0.171832 0.010661 0.394832 +-0.164229 -0.033313 0.411342 +-0.071226 -0.093884 0.490608 +-0.099723 -0.021444 0.479401 +-0.106460 -0.079934 0.470702 +-0.126287 -0.023902 0.459235 +-0.151985 -0.067142 0.420950 +-0.147699 -0.107939 0.402674 +-0.109438 -0.119557 0.446423 +-0.020037 -0.195034 0.426407 +-0.045003 -0.203863 0.398142 +-0.079909 -0.190588 0.383979 +-0.073176 -0.153947 0.447608 +-0.060832 -0.134709 0.479062 +-0.132591 -0.160951 0.350157 +-0.119567 -0.148332 0.402715 +-0.065793 -0.128601 -0.175205 +-0.097272 -0.145676 -0.099799 +-0.002565 -0.181714 -0.122217 +-0.024515 -0.179484 -0.119506 +-0.064586 -0.176266 -0.074826 +-0.059683 -0.167369 -0.114486 +-0.099658 -0.163716 0.022325 +-0.040368 -0.148020 -0.173886 +-0.152092 0.033745 0.173508 +-0.159192 -0.012910 0.157435 +-0.186610 0.203923 -0.088370 +-0.183267 0.184340 -0.063974 +-0.136575 0.103373 0.069442 +-0.143137 0.116556 0.022602 +-0.200449 -0.005081 0.293234 +-0.198541 -0.044298 0.289997 +-0.176233 -0.086749 0.211940 +-0.129605 -0.146690 0.159205 +-0.172832 -0.114168 0.232984 +-0.146311 -0.094428 0.150409 +-0.147372 -0.095199 0.103658 +-0.110455 -0.178169 0.151965 +-0.128236 -0.127687 0.039765 +-0.128792 -0.120162 -0.025065 +0.064160 0.162938 0.145558 +0.035172 0.172321 0.185202 +-0.006127 0.202885 -0.099910 +-0.034296 0.191647 -0.029673 +-0.131196 0.116627 -0.390365 +-0.142598 0.108734 -0.385698 +-0.118388 0.084666 -0.406795 +-0.122705 0.099621 -0.397329 +-0.118280 0.017285 -0.383763 +-0.138200 0.021970 -0.357392 +-0.083219 -0.042897 -0.356408 +-0.171574 -0.015949 -0.418570 +-0.079870 -0.020831 -0.382774 +-0.146033 -0.002291 -0.413268 +-0.099733 0.026973 -0.404345 +-0.098251 0.013991 -0.401317 +0.044369 -0.016396 -0.405838 +0.042389 0.006708 -0.423304 +-0.042891 -0.004873 -0.416215 +-0.012107 -0.020909 -0.408756 +-0.205436 -0.024781 -0.328409 +-0.223220 -0.034022 -0.353666 +-0.149992 -0.036689 -0.391942 +-0.164885 -0.044415 -0.367829 +-0.091425 -0.051851 -0.329759 +-0.067188 -0.061962 -0.316028 +0.032718 -0.045780 -0.374356 +0.001142 -0.045018 -0.382344 +-0.008169 -0.088329 -0.317598 +-0.061474 -0.052657 -0.346404 +-0.036931 -0.052082 -0.363104 +-0.163689 -0.139768 0.263934 +-0.134461 -0.171429 0.220297 +-0.093110 -0.202067 0.185697 +-0.083335 -0.193614 0.109481 +-0.161181 0.096630 0.214117 +-0.169578 0.129140 0.197122 +-0.136316 0.091909 0.186973 +-0.137551 0.081713 0.154719 +0.129236 0.172656 -0.007278 +0.135409 0.204859 -0.026639 +0.107912 0.206419 -0.029102 +0.080873 0.173368 -0.015229 +0.100091 0.179921 -0.016858 +-0.000035 -0.119696 -0.260509 +-0.020383 -0.117167 -0.258779 +3 0 1 2 +3 2 3 4 +3 1 3 2 +3 5 6 7 +3 6 8 7 +3 9 10 11 +3 9 12 10 +3 13 14 15 +3 15 16 13 +3 17 18 16 +3 19 20 21 +3 22 23 24 +3 23 22 19 +3 25 26 27 +3 28 29 26 +3 30 31 32 +3 27 26 30 +3 30 26 31 +3 33 34 35 +3 36 37 38 +3 39 40 41 +3 42 40 39 +3 43 40 44 +3 45 46 47 +3 48 43 49 +3 50 51 52 +3 5 7 53 +3 54 55 56 +3 57 58 59 +3 60 58 61 +3 62 63 57 +3 63 64 61 +3 63 61 58 +3 63 58 57 +3 65 64 63 +3 65 63 62 +3 66 65 62 +3 61 67 60 +3 68 69 70 +3 71 69 68 +3 69 67 70 +3 70 67 61 +3 61 64 70 +3 72 73 68 +3 72 68 70 +3 72 70 64 +3 72 65 73 +3 72 64 65 +3 73 65 74 +3 68 73 71 +3 75 74 76 +3 74 65 76 +3 76 65 66 +3 76 66 9 +3 75 76 11 +3 76 9 11 +3 75 11 71 +3 71 73 75 +3 73 74 75 +3 77 16 18 +3 78 77 18 +3 78 18 79 +3 78 80 81 +3 78 13 77 +3 16 77 13 +3 13 78 81 +3 78 82 80 +3 82 78 79 +3 83 84 85 +3 83 86 84 +3 85 29 28 +3 87 88 89 +3 89 88 90 +3 91 89 90 +3 92 91 93 +3 90 93 91 +3 94 95 59 +3 95 94 96 +3 95 96 97 +3 3 96 94 +3 86 98 84 +3 59 95 99 +3 99 95 97 +3 100 101 24 +3 101 22 24 +3 101 100 102 +3 103 102 100 +3 102 103 104 +3 103 29 104 +3 104 29 85 +3 99 105 98 +3 105 97 106 +3 99 97 105 +3 96 106 97 +3 106 96 107 +3 21 108 109 +3 21 20 108 +3 110 21 109 +3 110 109 111 +3 112 38 113 +3 112 36 38 +3 114 115 32 +3 114 32 31 +3 115 35 34 +3 34 32 115 +3 116 117 114 +3 116 114 31 +3 31 26 116 +3 29 116 26 +3 116 29 103 +3 114 118 115 +3 117 118 114 +3 119 120 37 +3 38 37 120 +3 121 113 122 +3 38 122 113 +3 38 120 122 +3 123 113 121 +3 122 124 121 +3 44 125 43 +3 126 127 128 +3 128 129 130 +3 129 128 127 +3 131 132 133 +3 134 14 135 +3 135 14 13 +3 13 81 135 +3 136 90 83 +3 137 138 139 +3 140 141 142 +3 139 142 141 +3 139 138 142 +3 140 143 141 +3 144 36 145 +3 138 144 145 +3 143 145 146 +3 143 140 145 +3 140 142 145 +3 138 145 142 +3 36 144 37 +3 147 137 139 +3 141 147 139 +3 148 149 150 +3 151 149 148 +3 152 153 47 +3 154 152 47 +3 47 46 154 +3 18 155 156 +3 79 18 156 +3 18 17 155 +3 154 155 17 +3 156 155 46 +3 154 46 155 +3 157 6 158 +3 156 157 158 +3 46 157 156 +3 157 46 45 +3 157 45 8 +3 8 6 157 +3 159 160 161 +3 162 148 163 +3 151 148 162 +3 164 156 158 +3 164 158 165 +3 166 82 167 +3 167 79 164 +3 79 156 164 +3 82 79 167 +3 168 169 166 +3 168 170 169 +3 167 168 166 +3 164 168 167 +3 164 165 168 +3 170 151 169 +3 162 169 151 +3 163 169 162 +3 163 166 169 +3 171 172 173 +3 41 174 175 +3 40 174 41 +3 40 43 174 +3 175 174 48 +3 48 174 43 +3 41 175 176 +3 177 178 179 +3 177 180 178 +3 134 179 178 +3 134 135 179 +3 181 182 183 +3 179 181 183 +3 183 182 173 +3 183 184 177 +3 177 179 183 +3 179 135 181 +3 185 186 187 +3 48 186 175 +3 188 186 48 +3 188 187 186 +3 176 189 190 +3 190 189 185 +3 176 175 189 +3 189 175 186 +3 186 185 189 +3 191 176 190 +3 192 193 184 +3 192 184 183 +3 173 192 183 +3 192 173 172 +3 193 192 191 +3 192 172 191 +3 191 190 193 +3 190 185 193 +3 194 128 195 +3 128 130 195 +3 196 194 197 +3 196 126 194 +3 126 128 194 +3 198 199 0 +3 4 198 0 +3 198 4 3 +3 198 3 94 +3 94 59 198 +3 58 198 59 +3 198 58 199 +3 60 199 58 +3 200 201 199 +3 109 108 201 +3 201 108 1 +3 201 1 0 +3 199 201 0 +3 202 67 203 +3 199 202 200 +3 202 199 60 +3 67 202 60 +3 67 69 203 +3 71 203 69 +3 203 204 202 +3 71 204 203 +3 205 204 11 +3 11 10 205 +3 204 71 11 +3 130 206 207 +3 10 207 206 +3 206 205 10 +3 207 150 149 +3 195 208 209 +3 151 170 209 +3 195 130 208 +3 208 130 207 +3 149 209 208 +3 149 151 209 +3 208 207 149 +3 209 210 195 +3 170 210 209 +3 210 168 211 +3 210 170 168 +3 168 165 211 +3 197 211 165 +3 195 210 211 +3 194 211 197 +3 194 195 211 +3 212 197 213 +3 213 197 165 +3 213 165 158 +3 213 6 212 +3 213 158 6 +3 5 212 6 +3 5 196 212 +3 212 196 197 +3 214 215 216 +3 215 126 196 +3 5 215 196 +3 5 216 215 +3 216 217 214 +3 218 214 217 +3 214 218 127 +3 215 214 126 +3 127 126 214 +3 219 220 81 +3 80 219 81 +3 220 219 221 +3 221 161 160 +3 222 130 223 +3 223 130 129 +3 129 224 223 +3 223 225 222 +3 225 223 224 +3 226 227 228 +3 226 59 227 +3 226 57 59 +3 59 99 227 +3 227 99 98 +3 227 98 86 +3 228 227 86 +3 161 221 229 +3 221 219 229 +3 229 219 80 +3 161 230 159 +3 230 161 231 +3 232 230 233 +3 233 231 234 +3 230 231 233 +3 235 105 236 +3 98 105 235 +3 104 85 236 +3 235 236 84 +3 235 84 98 +3 84 236 85 +3 237 218 238 +3 217 238 218 +3 217 239 238 +3 237 238 240 +3 224 241 242 +3 129 241 224 +3 127 241 129 +3 242 241 218 +3 241 127 218 +3 218 237 242 +3 240 243 244 +3 240 244 237 +3 242 245 224 +3 246 245 237 +3 237 244 246 +3 245 242 237 +3 247 248 246 +3 248 247 249 +3 248 249 225 +3 224 248 225 +3 245 248 224 +3 245 246 248 +3 250 251 252 +3 253 251 250 +3 251 254 255 +3 254 251 253 +3 253 35 254 +3 256 257 255 +3 257 258 252 +3 252 251 257 +3 255 257 251 +3 259 118 260 +3 35 259 254 +3 35 115 259 +3 118 259 115 +3 254 259 260 +3 260 255 254 +3 261 24 262 +3 261 100 24 +3 24 23 262 +3 263 264 261 +3 264 263 117 +3 117 116 264 +3 116 103 264 +3 264 103 100 +3 261 264 100 +3 265 266 146 +3 23 19 265 +3 267 268 146 +3 267 262 268 +3 268 262 23 +3 268 23 265 +3 146 268 265 +3 145 267 146 +3 145 36 267 +3 267 36 112 +3 269 263 270 +3 270 112 269 +3 270 263 261 +3 270 261 262 +3 267 270 262 +3 270 267 112 +3 112 113 269 +3 123 269 113 +3 271 272 118 +3 123 272 269 +3 117 271 118 +3 272 271 263 +3 272 263 269 +3 263 271 117 +3 121 273 274 +3 124 273 121 +3 274 260 118 +3 272 274 118 +3 272 123 274 +3 274 123 121 +3 275 276 260 +3 276 256 255 +3 276 255 260 +3 275 260 274 +3 275 274 273 +3 275 273 124 +3 136 277 278 +3 277 136 279 +3 277 279 182 +3 93 90 278 +3 278 90 136 +3 28 26 280 +3 25 280 26 +3 281 282 56 +3 281 28 282 +3 280 282 28 +3 283 282 280 +3 283 54 282 +3 56 282 54 +3 284 285 286 +3 284 286 287 +3 171 287 286 +3 171 173 287 +3 182 287 173 +3 279 284 287 +3 279 287 182 +3 288 289 290 +3 288 290 291 +3 290 292 291 +3 293 294 290 +3 292 290 294 +3 289 293 290 +3 289 286 293 +3 293 285 294 +3 286 285 293 +3 295 281 296 +3 284 279 295 +3 56 296 281 +3 56 297 296 +3 297 294 296 +3 295 296 285 +3 284 295 285 +3 285 296 294 +3 298 299 8 +3 8 45 298 +3 45 300 298 +3 7 8 301 +3 299 301 8 +3 53 301 302 +3 301 53 7 +3 303 53 302 +3 301 304 302 +3 299 304 301 +3 298 304 299 +3 304 305 303 +3 304 303 302 +3 303 305 50 +3 306 307 308 +3 305 306 308 +3 51 308 307 +3 50 308 51 +3 308 50 305 +3 309 307 306 +3 310 309 306 +3 193 185 311 +3 311 187 309 +3 309 187 307 +3 185 187 311 +3 153 312 313 +3 313 47 153 +3 153 314 312 +3 313 312 45 +3 45 47 313 +3 300 45 312 +3 315 180 177 +3 315 177 184 +3 300 312 316 +3 316 314 315 +3 314 180 315 +3 314 316 312 +3 317 318 310 +3 310 306 317 +3 305 317 306 +3 305 304 317 +3 298 317 304 +3 317 298 318 +3 298 300 318 +3 318 300 316 +3 319 320 311 +3 315 184 320 +3 320 184 193 +3 193 311 320 +3 319 311 309 +3 310 319 309 +3 318 319 310 +3 320 319 316 +3 316 315 320 +3 318 316 319 +3 321 111 322 +3 109 322 111 +3 201 322 109 +3 201 200 322 +3 62 323 66 +3 57 324 323 +3 62 57 323 +3 324 57 226 +3 66 325 326 +3 9 326 12 +3 66 326 9 +3 323 325 66 +3 323 324 325 +3 324 226 325 +3 327 228 328 +3 328 12 327 +3 12 326 327 +3 326 325 327 +3 226 327 325 +3 226 228 327 +3 329 330 328 +3 329 328 228 +3 331 329 228 +3 331 228 332 +3 333 332 86 +3 332 228 86 +3 333 86 83 +3 83 90 333 +3 90 88 333 +3 333 88 334 +3 335 148 336 +3 335 163 148 +3 148 150 336 +3 336 231 335 +3 336 234 231 +3 337 338 339 +3 88 339 334 +3 337 339 87 +3 87 339 88 +3 340 341 334 +3 339 340 334 +3 340 339 338 +3 340 338 232 +3 233 340 232 +3 233 341 340 +3 233 234 341 +3 341 332 333 +3 341 333 334 +3 234 336 342 +3 343 342 150 +3 336 150 342 +3 331 343 329 +3 331 332 343 +3 332 341 343 +3 342 343 234 +3 343 330 329 +3 343 341 234 +3 330 344 345 +3 328 345 12 +3 328 330 345 +3 330 343 344 +3 344 343 150 +3 344 150 207 +3 345 344 10 +3 12 345 10 +3 207 10 344 +3 346 347 348 +3 303 347 53 +3 347 303 348 +3 349 350 303 +3 348 303 350 +3 50 349 303 +3 50 52 349 +3 52 351 349 +3 352 349 353 +3 352 350 349 +3 349 351 353 +3 351 239 353 +3 346 352 353 +3 353 347 346 +3 354 53 355 +3 354 355 239 +3 347 355 53 +3 347 353 355 +3 355 353 239 +3 354 239 217 +3 216 354 217 +3 5 354 216 +3 5 53 354 +3 205 356 357 +3 356 205 206 +3 356 206 130 +3 222 356 130 +3 335 231 358 +3 161 358 231 +3 358 161 359 +3 359 161 229 +3 335 358 359 +3 335 359 163 +3 360 361 163 +3 359 360 163 +3 360 229 361 +3 359 229 360 +3 80 361 229 +3 361 80 82 +3 361 82 166 +3 163 361 166 +3 3 362 96 +3 362 1 363 +3 1 362 3 +3 364 363 365 +3 363 1 365 +3 1 108 365 +3 364 365 366 +3 20 365 108 +3 367 107 368 +3 96 368 107 +3 368 96 362 +3 363 367 368 +3 364 367 363 +3 362 363 368 +3 369 370 371 +3 371 366 365 +3 365 20 371 +3 372 373 370 +3 107 373 372 +3 369 372 370 +3 107 367 373 +3 373 367 364 +3 364 366 373 +3 366 371 373 +3 371 370 373 +3 20 374 375 +3 375 369 371 +3 375 371 20 +3 19 374 20 +3 374 19 22 +3 376 369 377 +3 369 375 377 +3 377 101 376 +3 377 375 374 +3 374 22 377 +3 101 377 22 +3 101 102 376 +3 378 379 376 +3 369 379 372 +3 376 379 369 +3 376 102 378 +3 102 104 378 +3 380 378 381 +3 379 380 372 +3 379 378 380 +3 378 104 381 +3 236 381 104 +3 105 381 236 +3 105 106 381 +3 381 107 380 +3 380 107 372 +3 381 106 107 +3 382 383 188 +3 383 382 131 +3 188 48 382 +3 48 49 382 +3 49 131 382 +3 384 52 51 +3 384 51 385 +3 307 385 51 +3 386 385 387 +3 387 385 188 +3 386 384 385 +3 187 385 307 +3 187 188 385 +3 387 188 383 +3 388 131 389 +3 131 133 389 +3 389 390 388 +3 388 390 386 +3 386 387 388 +3 387 383 388 +3 388 383 131 +3 238 391 392 +3 392 393 240 +3 240 238 392 +3 239 391 238 +3 351 392 391 +3 391 239 351 +3 392 394 393 +3 351 395 394 +3 392 351 394 +3 52 395 351 +3 384 395 52 +3 395 384 386 +3 395 390 394 +3 395 386 390 +3 396 393 397 +3 393 394 397 +3 390 397 394 +3 389 397 390 +3 396 397 133 +3 389 133 397 +3 243 396 133 +3 243 240 396 +3 240 393 396 +3 124 398 399 +3 124 122 398 +3 122 120 398 +3 400 356 222 +3 400 222 225 +3 249 401 400 +3 225 249 400 +3 402 399 403 +3 399 402 404 +3 398 403 399 +3 398 405 403 +3 405 401 403 +3 249 402 403 +3 247 402 249 +3 403 401 249 +3 406 252 407 +3 407 252 258 +3 407 258 125 +3 406 407 44 +3 125 44 407 +3 408 33 409 +3 408 409 55 +3 33 35 409 +3 409 35 253 +3 250 410 411 +3 250 252 410 +3 411 410 56 +3 56 410 297 +3 411 56 55 +3 411 55 409 +3 253 411 409 +3 411 253 250 +3 412 125 413 +3 412 413 49 +3 413 132 131 +3 413 131 49 +3 412 49 43 +3 412 43 125 +3 414 415 416 +3 414 125 258 +3 416 413 414 +3 414 413 125 +3 416 132 413 +3 415 417 418 +3 414 417 415 +3 418 417 258 +3 414 258 417 +3 418 258 257 +3 256 418 257 +3 404 419 420 +3 415 420 419 +3 418 420 415 +3 418 256 420 +3 404 420 421 +3 420 256 421 +3 421 256 276 +3 275 421 276 +3 124 421 275 +3 124 399 421 +3 404 421 399 +3 422 135 81 +3 81 220 422 +3 422 278 423 +3 423 278 277 +3 277 182 423 +3 182 181 423 +3 135 422 423 +3 423 181 135 +3 136 424 425 +3 281 295 425 +3 295 279 425 +3 425 279 136 +3 424 136 83 +3 424 83 85 +3 425 424 28 +3 28 281 425 +3 424 85 28 +3 426 19 21 +3 265 427 266 +3 265 19 427 +3 19 426 427 +3 428 266 427 +3 429 428 427 +3 426 429 427 +3 429 110 428 +3 110 111 428 +3 430 143 431 +3 146 431 143 +3 266 431 146 +3 141 143 430 +3 432 433 434 +3 141 435 433 +3 141 430 435 +3 141 433 147 +3 431 436 430 +3 431 266 436 +3 266 428 436 +3 111 436 428 +3 436 111 321 +3 430 436 437 +3 436 321 437 +3 434 433 437 +3 435 437 433 +3 435 430 437 +3 438 439 202 +3 202 204 438 +3 322 200 439 +3 439 200 202 +3 437 440 434 +3 437 321 440 +3 322 440 321 +3 441 440 439 +3 441 439 438 +3 322 439 440 +3 442 144 443 +3 443 119 442 +3 138 443 144 +3 137 443 138 +3 147 443 137 +3 119 37 442 +3 37 144 442 +3 444 432 445 +3 147 444 445 +3 444 147 433 +3 432 444 433 +3 147 445 443 +3 446 447 119 +3 119 443 446 +3 445 446 443 +3 432 446 445 +3 398 447 405 +3 120 447 398 +3 120 119 447 +3 438 448 449 +3 449 448 357 +3 448 438 204 +3 448 204 205 +3 357 448 205 +3 450 449 357 +3 449 441 438 +3 451 405 447 +3 451 447 446 +3 432 451 446 +3 451 434 452 +3 451 432 434 +3 452 434 440 +3 441 452 440 +3 449 452 441 +3 451 452 450 +3 449 450 452 +3 133 453 243 +3 133 132 453 +3 416 454 453 +3 416 453 132 +3 416 415 454 +3 419 454 415 +3 243 453 454 +3 454 244 243 +3 455 456 247 +3 246 455 247 +3 244 455 246 +3 244 454 455 +3 455 419 456 +3 419 455 454 +3 404 456 419 +3 402 456 404 +3 402 247 456 +3 292 457 458 +3 458 457 40 +3 457 44 40 +3 458 40 42 +3 291 458 42 +3 292 458 291 +3 44 457 459 +3 459 457 292 +3 294 459 292 +3 460 406 459 +3 459 297 460 +3 459 406 44 +3 459 294 297 +3 297 410 460 +3 410 252 460 +3 406 460 252 +3 461 160 462 +3 462 463 461 +3 220 221 461 +3 221 160 461 +3 159 462 160 +3 422 464 278 +3 464 220 465 +3 464 422 220 +3 461 465 220 +3 463 465 461 +3 463 92 465 +3 464 465 93 +3 464 93 278 +3 93 465 92 +3 466 357 356 +3 400 466 356 +3 466 400 467 +3 400 401 467 +3 467 401 405 +3 405 451 467 +3 466 467 450 +3 466 450 357 +3 450 467 451 diff --git a/Polygon_mesh_processing/examples/Polygon_mesh_processing/clean_degeneracies.cpp b/Polygon_mesh_processing/test/Polygon_mesh_processing/test_remove_caps_needles.cpp similarity index 80% rename from Polygon_mesh_processing/examples/Polygon_mesh_processing/clean_degeneracies.cpp rename to Polygon_mesh_processing/test/Polygon_mesh_processing/test_remove_caps_needles.cpp index 837ec356aed..f6e418b23a7 100644 --- a/Polygon_mesh_processing/examples/Polygon_mesh_processing/clean_degeneracies.cpp +++ b/Polygon_mesh_processing/test/Polygon_mesh_processing/test_remove_caps_needles.cpp @@ -3,7 +3,7 @@ #include #include -#include +#include #include #include @@ -32,8 +32,10 @@ int main(int argc, char** argv) if (PMP::does_self_intersect(mesh)) std::cout << "Input mesh has self-intersections\n"; - PMP::remove_almost_degenerate_faces(mesh); - + PMP::experimental::remove_almost_degenerate_faces(mesh, + std::cos(160. / 180 * CGAL_PI), + 4, + 0.14); std::ofstream out("cleaned_mesh.off"); out << std::setprecision(17) << mesh; From 80a462d9a4350f8f206d86f95a94d87abd36c948 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9bastien=20Loriot?= Date: Fri, 27 Sep 2019 11:08:10 +0200 Subject: [PATCH 174/363] disable the max length test if 0 is given as threshold --- .../Polygon_mesh_processing/internal/remove_degeneracies.h | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/internal/remove_degeneracies.h b/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/internal/remove_degeneracies.h index d5fafb09f48..ddee18d3081 100644 --- a/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/internal/remove_degeneracies.h +++ b/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/internal/remove_degeneracies.h @@ -69,8 +69,11 @@ is_badly_shaped(const typename boost::graph_traits::face_descripto if(res != null_h && !get(ecm, edge(res, tmesh))) { // don't want to collapse edges that are too large - if(edge_length(res, tmesh, parameters::vertex_point_map(vpm).geom_traits(gt)) <= collapse_length_threshold) + if(collapse_length_threshold != 0 && + edge_length(res, tmesh, parameters::vertex_point_map(vpm).geom_traits(gt)) <= collapse_length_threshold) + { return make_array(res, null_h); + } } else // let's not make it possible to have a face be both a cap and a needle (for now) { From 429bf8676bf47b8e605fdd36ee261aa553d7c9a0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9bastien=20Loriot?= Date: Fri, 27 Sep 2019 11:15:34 +0200 Subject: [PATCH 175/363] fix handling of constrained vertices in geometric test for collapse --- .../internal/remove_degeneracies.h | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/internal/remove_degeneracies.h b/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/internal/remove_degeneracies.h index ddee18d3081..781f20d6008 100644 --- a/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/internal/remove_degeneracies.h +++ b/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/internal/remove_degeneracies.h @@ -249,15 +249,18 @@ get_best_edge_orientation(typename boost::graph_traits::edge_descr CGAL_assertion(!get(vcm, source(h, tmesh)) || !get(vcm, target(h, tmesh))); - // the resulting point of the collapse of a halfedge is the target of the halfedge before collapse - if(get(vcm, source(h, tmesh))) - return ho; - if(get(vcm, target(h, tmesh))) - return h; - boost::optional dv1 = get_collapse_volume(h, tmesh, vpm, gt); boost::optional dv2 = get_collapse_volume(ho, tmesh, vpm, gt); + // the resulting point of the collapse of a halfedge is the target of the halfedge before collapse + if(get(vcm, source(h, tmesh))) + return dv2 != boost::none ? ho + : boost::graph_traits::null_halfedge(); + + if(get(vcm, target(h, tmesh))) + return dv1 != boost::none ? h + : boost::graph_traits::null_halfedge(); + if(dv1 != boost::none) { if(dv2 != boost::none) From ee8528e02ba5c09da57fb700fe589fe9fb154092 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9bastien=20Loriot?= Date: Fri, 27 Sep 2019 11:45:57 +0200 Subject: [PATCH 176/363] fix the test --- .../CGAL/Polygon_mesh_processing/internal/remove_degeneracies.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/internal/remove_degeneracies.h b/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/internal/remove_degeneracies.h index 781f20d6008..762fcc9bee6 100644 --- a/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/internal/remove_degeneracies.h +++ b/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/internal/remove_degeneracies.h @@ -69,7 +69,7 @@ is_badly_shaped(const typename boost::graph_traits::face_descripto if(res != null_h && !get(ecm, edge(res, tmesh))) { // don't want to collapse edges that are too large - if(collapse_length_threshold != 0 && + if(collapse_length_threshold == 0 || edge_length(res, tmesh, parameters::vertex_point_map(vpm).geom_traits(gt)) <= collapse_length_threshold) { return make_array(res, null_h); From c18ad651d69a149b4d46afbd874b2dc5ad1a98e3 Mon Sep 17 00:00:00 2001 From: Maxime Gimeno Date: Tue, 1 Oct 2019 10:19:54 +0200 Subject: [PATCH 177/363] Fix last constro --- Polygon_mesh_processing/include/CGAL/Side_of_triangle_mesh.h | 1 + 1 file changed, 1 insertion(+) diff --git a/Polygon_mesh_processing/include/CGAL/Side_of_triangle_mesh.h b/Polygon_mesh_processing/include/CGAL/Side_of_triangle_mesh.h index 10e75779b99..4e21aff044d 100644 --- a/Polygon_mesh_processing/include/CGAL/Side_of_triangle_mesh.h +++ b/Polygon_mesh_processing/include/CGAL/Side_of_triangle_mesh.h @@ -182,6 +182,7 @@ public: , tree_ptr(&tree) , own_tree(false) { + tree_built = false; } ~Side_of_triangle_mesh() From 362c4f917b64ba10ec63d235eb42b93fb86a99aa Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mael=20Rouxel-Labb=C3=A9?= Date: Tue, 1 Oct 2019 13:31:56 +0200 Subject: [PATCH 178/363] Remove wild 'std::exit(1)' --- .../test/Triangulation_2/test_constrained_triangulation_2.cpp | 2 -- 1 file changed, 2 deletions(-) diff --git a/Triangulation_2/test/Triangulation_2/test_constrained_triangulation_2.cpp b/Triangulation_2/test/Triangulation_2/test_constrained_triangulation_2.cpp index 64851021f7b..5a00013a564 100644 --- a/Triangulation_2/test/Triangulation_2/test_constrained_triangulation_2.cpp +++ b/Triangulation_2/test/Triangulation_2/test_constrained_triangulation_2.cpp @@ -40,8 +40,6 @@ int main() typedef CGAL::Constrained_triangulation_2 Ctwoc; _test_cls_constrained_triangulation(Ctwoc()); - std::exit(1); - std::cout << "Testing constrained_triangulation "<< std::endl; std::cout << " with No_constraint_intersection_requiring_constructions_tag (default): " << std::endl; From dd9e6340fe9ecffc67aeb2a69d41cfaccc2bd035 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mael=20Rouxel-Labb=C3=A9?= Date: Tue, 1 Oct 2019 13:39:21 +0200 Subject: [PATCH 179/363] Silence some warnings --- .../include/CGAL/_test_cls_constrained_triangulation_2.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) 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 d7419f80846..455ff4828b8 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 @@ -61,7 +61,7 @@ _test_cdt_throwing(const Pt& p0, const Pt& p1, const Pt& p2, const Pt& p3, { assert(intersection_type == INTERSECTION); assert((boost::is_same::value) || -#ifndef CGAL_NO_DEPRECATED_CODE +#if !defined(CGAL_NO_DEPRECATED_CODE) && defined(CGAL_NO_DEPRECATION_WARNINGS) (boost::is_same::value) || #endif (boost::is_same::value)); @@ -78,7 +78,7 @@ _test_cdt_throwing(const Pt& p0, const Pt& p1, const Pt& p2, const Pt& p3, else if(intersection_type == INTERSECTION) { assert(!(boost::is_same::value) && -#ifndef CGAL_NO_DEPRECATED_CODE +#if !defined(CGAL_NO_DEPRECATED_CODE) && defined(CGAL_NO_DEPRECATION_WARNINGS) !(boost::is_same::value) && #endif !(boost::is_same::value)); From faf55abc7391238559a56bab4ecdd3280afb447a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mael=20Rouxel-Labb=C3=A9?= Date: Tue, 1 Oct 2019 14:35:02 +0200 Subject: [PATCH 180/363] Doc improvements --- .../Concepts/TriangulationDataStructure_2.h | 2 +- .../CGAL/Constrained_triangulation_2.h | 72 ++++++++----------- .../doc/Triangulation_2/Triangulation_2.txt | 6 +- 3 files changed, 34 insertions(+), 46 deletions(-) diff --git a/TDS_2/doc/TDS_2/Concepts/TriangulationDataStructure_2.h b/TDS_2/doc/TDS_2/Concepts/TriangulationDataStructure_2.h index e193a21c460..4b025c1b7e4 100644 --- a/TDS_2/doc/TDS_2/Concepts/TriangulationDataStructure_2.h +++ b/TDS_2/doc/TDS_2/Concepts/TriangulationDataStructure_2.h @@ -68,7 +68,7 @@ for faces of maximal dimension instead of faces. \sa `TriangulationDataStructure_2::Face` \sa `TriangulationDataStructure_2::Vertex` -\sa `CGAL::Triangulation_2` +\sa `CGAL::Triangulation_2` */ diff --git a/Triangulation_2/doc/Triangulation_2/CGAL/Constrained_triangulation_2.h b/Triangulation_2/doc/Triangulation_2/CGAL/Constrained_triangulation_2.h index 5ce9bc25611..47f4a38c217 100644 --- a/Triangulation_2/doc/Triangulation_2/CGAL/Constrained_triangulation_2.h +++ b/Triangulation_2/doc/Triangulation_2/CGAL/Constrained_triangulation_2.h @@ -5,11 +5,11 @@ namespace CGAL { /*! \ingroup PkgTriangulation2TriangulationClasses +Intersection tag for constrained triangulations, when input constraints do not intersect. + \deprecated This class is deprecated since \cgal 5.1 as it was ambiguous. Users should instead use the tags `No_constraint_intersection_tag` and `No_constraint_intersection_requiring_constructions_tag`, depending on their needs. - -Intersection tag for constrained triangulations, when input constraints do not intersect. */ struct No_intersection_tag{}; @@ -26,6 +26,11 @@ struct No_constraint_intersection_tag{}; Intersection tag for constrained triangulations, when input constraints are not allowed to intersect except if the intersection does not require any new point construction. + +This for example allows configurations such as two segments intersecting in a 'T', or overlapping (and +even identical) segments. + +This is the default tag. */ struct No_constraint_intersection_requiring_constructions_tag{}; @@ -100,7 +105,6 @@ as it avoids the cascading of intersection computations. \image html constraints.png \image latex constraints.png - \tparam Traits is a geometric traits class and must be a model of the concept `TriangulationTraits_2`. When intersection of input constraints are supported, @@ -110,48 +114,32 @@ to compute the intersection of two segments. It has then to be a model of the concept `ConstrainedTriangulationTraits_2`. +\tparam Tds must be a model of the concept `TriangulationDataStructure_2` or `Default`. +The information about constrained edges is stored in the faces of the triangulation. Thus the nested `Face` +type of a constrained triangulation offers additional functionalities to deal with this information. +These additional functionalities induce additional requirements on the face base class +plugged into the triangulation data structure of a constrained Delaunay triangulation. +The face base of a constrained Delaunay triangulation has to be a model of the concept +`ConstrainedTriangulationFaceBase_2`. -\tparam Tds must be a model -of the concept `TriangulationDataStructure_2` or `Default`. - -\tparam Itag is the intersection tag -which serves to choose between the different -strategies to deal with constraints intersections. -\cgal provides three valid types for this parameter: +\tparam Itag is the intersection tag +which serves to choose between the different +strategies to deal with constraints intersections. +\cgal provides three valid types for this parameter: - `No_constraint_intersection_tag` disallows intersections of input constraints -except for the case of a single common extremity, -- `No_constraint_intersection_requiring_constructions_tag` disallows intersections of input constraints -except for configurations where the intersection can be represented without requiring the construction -of a new point (e.g. overlapping constraints), -- `Exact_predicates_tag` is to be used when the traits -class -provides exact predicates but approximate constructions of the -intersection points. -- `Exact_intersections_tag` is to be used in conjunction -with an exact arithmetic type. +except for the case of a single common extremity; +- `No_constraint_intersection_requiring_constructions_tag` (default value) disallows intersections +of input constraints except for configurations where the intersection can be represented +without requiring the construction of a new point such as overlapping constraints; +- `Exact_predicates_tag` is to be used when the traits class +provides exact predicates but approximate constructions of the +intersection points; +- `Exact_intersections_tag` is to be used in conjunction +with an exact arithmetic type. -The information about constrained edges is stored in the -faces of the triangulation. Thus the nested `Face` -type of a constrained triangulation offers -additional functionalities to deal with this information. -These additional functionalities -induce additional requirements on the face base class -plugged into the triangulation data structure of -a constrained Delaunay triangulation. -The face base of a constrained Delaunay triangulation -has to be a model of the concept -`ConstrainedTriangulationFaceBase_2`. - -\cgal provides default instantiations for the template parameters -`Tds` and `Itag`, and for the `ConstrainedTriangulationFaceBase_2`. -If `Gt` is the geometric traits class -parameter, -the default for -`ConstrainedTriangulationFaceBase_2` is the class -`Constrained_triangulation_face_base_2` -and the default for the -triangulation data structure parameter is the class -`Triangulation_data_structure_2 < Triangulation_vertex_base_2, Constrained_triangulation_face_base_2 >`. +\cgal provides default instantiations for the template parameters `Tds` and `Itag`. +If `Gt` is the geometric traits class parameter, the default triangulation data structure +is the class is the class `Triangulation_data_structure_2, Constrained_triangulation_face_base_2 >`. The default intersection tag is `No_constraint_intersection_requiring_constructions_tag`. \sa `CGAL::Triangulation_2` diff --git a/Triangulation_2/doc/Triangulation_2/Triangulation_2.txt b/Triangulation_2/doc/Triangulation_2/Triangulation_2.txt index 584c1927185..9451f88be77 100644 --- a/Triangulation_2/doc/Triangulation_2/Triangulation_2.txt +++ b/Triangulation_2/doc/Triangulation_2/Triangulation_2.txt @@ -848,9 +848,9 @@ input constraints are disallowed, except for the configuration of a single commo input constraints are disallowed, except if no actual construction is needed to represent the intersection. For example, if two constraints intersect in a 'T'-like junction, the intersection point is one of the constraints' extremity and as such, no construction is in fact needed. Other similar configurations include -overlapping segments, common extremities, or equal constraints. +overlapping segments, common extremities, or equal constraints; - `Exact_predicates_tag` if the geometric traits class provides -exact predicates but approximate constructions +exact predicates but approximate constructions; - `Exact_intersections_tag` when exact predicates and exact constructions are provided. @@ -946,7 +946,7 @@ As in the case of constrained triangulations, the third parameter `Itag` is the intersection tag and serves to choose how intersecting constraints are dealt with. It can be instantiated with one of the following -classes: `No_constraint_intersection_tag`, `No_constraint_intersection_requiring_constructions_tag` +classes: `No_constraint_intersection_tag`, `No_constraint_intersection_requiring_constructions_tag`, `Exact_predicates_tag`, or `Exact_intersections_tag` (see Section \ref Section_2D_Triangulations_Constrained). From da89481d9cde9aa3daeecf556c6698e6b8869cb2 Mon Sep 17 00:00:00 2001 From: Maxime Gimeno Date: Tue, 1 Oct 2019 14:47:29 +0200 Subject: [PATCH 181/363] Add an action in the demo --- .../Polyhedron/Plugins/PMP/CMakeLists.txt | 3 +- .../Plugins/PMP/RemoveNeedlesDialog.ui | 161 ++++++++++++++++++ .../Plugins/PMP/Repair_polyhedron_plugin.cpp | 35 +++- 3 files changed, 197 insertions(+), 2 deletions(-) create mode 100644 Polyhedron/demo/Polyhedron/Plugins/PMP/RemoveNeedlesDialog.ui diff --git a/Polyhedron/demo/Polyhedron/Plugins/PMP/CMakeLists.txt b/Polyhedron/demo/Polyhedron/Plugins/PMP/CMakeLists.txt index 669b8e85ce1..b97c86f9879 100644 --- a/Polyhedron/demo/Polyhedron/Plugins/PMP/CMakeLists.txt +++ b/Polyhedron/demo/Polyhedron/Plugins/PMP/CMakeLists.txt @@ -78,7 +78,8 @@ target_link_libraries(corefinement_plugin PUBLIC scene_surface_mesh_item) polyhedron_demo_plugin(surface_intersection_plugin Surface_intersection_plugin KEYWORDS PMP) target_link_libraries(surface_intersection_plugin PUBLIC scene_surface_mesh_item scene_polylines_item scene_points_with_normal_item) -polyhedron_demo_plugin(repair_polyhedron_plugin Repair_polyhedron_plugin KEYWORDS PMP) +qt5_wrap_ui( repairUI_FILES RemoveNeedlesDialog.ui) +polyhedron_demo_plugin(repair_polyhedron_plugin Repair_polyhedron_plugin ${repairUI_FILES} KEYWORDS PMP) target_link_libraries(repair_polyhedron_plugin PUBLIC scene_surface_mesh_item) qt5_wrap_ui( isotropicRemeshingUI_FILES Isotropic_remeshing_dialog.ui) diff --git a/Polyhedron/demo/Polyhedron/Plugins/PMP/RemoveNeedlesDialog.ui b/Polyhedron/demo/Polyhedron/Plugins/PMP/RemoveNeedlesDialog.ui new file mode 100644 index 00000000000..4ade4b7b8a1 --- /dev/null +++ b/Polyhedron/demo/Polyhedron/Plugins/PMP/RemoveNeedlesDialog.ui @@ -0,0 +1,161 @@ + + + NeedleDialog + + + + 0 + 0 + 400 + 300 + + + + Remove Needles and Cap + + + + + + + + Threshold in degrees + + + Cap Threshold + + + + + + + + + + + + + + 2 + + + 360.000000000000000 + + + 160.000000000000000 + + + + + + + + + + + + (size+big edge )/(size+small edge) + + + Needle Threshold + + + + + + + + Threshold in degrees + + + 2 + + + 1000.000000000000000 + + + 4.000000000000000 + + + + + + + + + + + + Do not collapse edges begger than this threshold. + + + Collapse Length Threshold + + + + + + + + Threshold in degrees + + + 2 + + + + + + + + + + + + + + Qt::Horizontal + + + QDialogButtonBox::Cancel|QDialogButtonBox::Ok + + + + + + + + + buttonBox + accepted() + NeedleDialog + accept() + + + 248 + 254 + + + 157 + 274 + + + + + buttonBox + rejected() + NeedleDialog + reject() + + + 316 + 260 + + + 286 + 274 + + + + + diff --git a/Polyhedron/demo/Polyhedron/Plugins/PMP/Repair_polyhedron_plugin.cpp b/Polyhedron/demo/Polyhedron/Plugins/PMP/Repair_polyhedron_plugin.cpp index a02cae1f847..46f5b96a9ba 100644 --- a/Polyhedron/demo/Polyhedron/Plugins/PMP/Repair_polyhedron_plugin.cpp +++ b/Polyhedron/demo/Polyhedron/Plugins/PMP/Repair_polyhedron_plugin.cpp @@ -16,6 +16,9 @@ #include #include #include +#include + +#include "ui_RemoveNeedlesDialog.h" using namespace CGAL::Three; class Polyhedron_demo_repair_polyhedron_plugin : @@ -43,6 +46,7 @@ public: actionDuplicateNMVertices = new QAction(tr("Duplicate Non-Manifold Vertices"), mw); actionAutorefine = new QAction(tr("Autorefine Mesh"), mw); actionAutorefineAndRMSelfIntersections = new QAction(tr("Autorefine and Remove Self-Intersections"), mw); + actionRemoveNeedlesAndCaps = new QAction(tr("Remove Needles And Caps")); actionRemoveIsolatedVertices->setObjectName("actionRemoveIsolatedVertices"); actionRemoveDegenerateFaces->setObjectName("actionRemoveDegenerateFaces"); @@ -51,6 +55,7 @@ public: actionDuplicateNMVertices->setObjectName("actionDuplicateNMVertices"); actionAutorefine->setObjectName("actionAutorefine"); actionAutorefineAndRMSelfIntersections->setObjectName("actionAutorefineAndRMSelfIntersections"); + actionRemoveNeedlesAndCaps->setObjectName("actionRemoveNeedlesAndCaps"); actionRemoveDegenerateFaces->setProperty("subMenuName", "Polygon Mesh Processing/Repair/Experimental"); actionStitchCloseBorderHalfedges->setProperty("subMenuName", "Polygon Mesh Processing/Repair/Experimental"); @@ -59,6 +64,7 @@ public: actionDuplicateNMVertices->setProperty("subMenuName", "Polygon Mesh Processing/Repair"); actionAutorefine->setProperty("subMenuName", "Polygon Mesh Processing/Repair/Experimental"); actionAutorefineAndRMSelfIntersections->setProperty("subMenuName", "Polygon Mesh Processing/Repair/Experimental"); + actionRemoveNeedlesAndCaps->setProperty("subMenuName", "Polygon Mesh Processing/Repair/Experimental"); autoConnectActions(); } @@ -71,7 +77,8 @@ public: << actionStitchCloseBorderHalfedges << actionDuplicateNMVertices << actionAutorefine - << actionAutorefineAndRMSelfIntersections; + << actionAutorefineAndRMSelfIntersections + << actionRemoveNeedlesAndCaps; } bool applicable(QAction*) const @@ -102,6 +109,7 @@ public Q_SLOTS: void on_actionDuplicateNMVertices_triggered(); void on_actionAutorefine_triggered(); void on_actionAutorefineAndRMSelfIntersections_triggered(); + void on_actionRemoveNeedlesAndCaps_triggered(); private: QAction* actionRemoveIsolatedVertices; @@ -111,6 +119,7 @@ private: QAction* actionDuplicateNMVertices; QAction* actionAutorefine; QAction* actionAutorefineAndRMSelfIntersections; + QAction* actionRemoveNeedlesAndCaps; Messages_interface* messages; }; // end Polyhedron_demo_repair_polyhedron_plugin @@ -140,6 +149,30 @@ void Polyhedron_demo_repair_polyhedron_plugin::on_actionRemoveIsolatedVertices_t QApplication::restoreOverrideCursor(); } +void Polyhedron_demo_repair_polyhedron_plugin::on_actionRemoveNeedlesAndCaps_triggered() +{ + CGAL::Three::Three::CursorScopeGuard(Qt::WaitCursor); + const Scene_interface::Item_id index = scene->mainSelectionIndex(); + Scene_surface_mesh_item* sm_item = qobject_cast(scene->item(index)); + if(!sm_item) + { + return; + } + + QDialog dialog; + Ui::NeedleDialog ui; + ui.setupUi(&dialog); + ui.collapseBox->setValue(sm_item->diagonalBbox()*0.01); + if(dialog.exec() != QDialog::Accepted) + return; + CGAL::Polygon_mesh_processing::experimental::remove_almost_degenerate_faces(*sm_item->face_graph(), + std::cos((ui.capBox->value()/180.0) * CGAL_PI), + ui.needleBox->value(), + ui.collapseBox->value()); + sm_item->invalidateOpenGLBuffers(); + sm_item->itemChanged(); +} + template void Polyhedron_demo_repair_polyhedron_plugin::on_actionRemoveDegenerateFaces_triggered(Scene_interface::Item_id index) { From e42c87b54f3f2aabc172ba3edb0db2c794a1288d Mon Sep 17 00:00:00 2001 From: Maxime Gimeno Date: Wed, 2 Oct 2019 09:35:41 +0200 Subject: [PATCH 182/363] add the missing box --- Polygon_mesh_processing/include/CGAL/Side_of_triangle_mesh.h | 1 + 1 file changed, 1 insertion(+) diff --git a/Polygon_mesh_processing/include/CGAL/Side_of_triangle_mesh.h b/Polygon_mesh_processing/include/CGAL/Side_of_triangle_mesh.h index 4e21aff044d..82b078df652 100644 --- a/Polygon_mesh_processing/include/CGAL/Side_of_triangle_mesh.h +++ b/Polygon_mesh_processing/include/CGAL/Side_of_triangle_mesh.h @@ -183,6 +183,7 @@ public: , own_tree(false) { tree_built = false; + box = tree.bbox(); } ~Side_of_triangle_mesh() From 130d4a5e24d13f146112e33776a83f20f0ad9c36 Mon Sep 17 00:00:00 2001 From: Maxime Gimeno Date: Wed, 2 Oct 2019 09:56:07 +0200 Subject: [PATCH 183/363] remove useless bool --- .../include/CGAL/Side_of_triangle_mesh.h | 17 +++++++---------- 1 file changed, 7 insertions(+), 10 deletions(-) diff --git a/Polygon_mesh_processing/include/CGAL/Side_of_triangle_mesh.h b/Polygon_mesh_processing/include/CGAL/Side_of_triangle_mesh.h index 82b078df652..ec11f7482cf 100644 --- a/Polygon_mesh_processing/include/CGAL/Side_of_triangle_mesh.h +++ b/Polygon_mesh_processing/include/CGAL/Side_of_triangle_mesh.h @@ -204,18 +204,15 @@ public: */ Bounded_side operator()(const Point& point) const { - bool is_outside = tree_built; - if(!is_outside){ - is_outside = (point.x() < box.xmin() - || point.x() > box.xmax() - || point.y() < box.ymin() - || point.y() > box.ymax() - || point.z() < box.zmin() - || point.z() > box.zmax()); - if(is_outside) + if(!tree_built){ + if(point.x() < box.xmin() + || point.x() > box.xmax() + || point.y() < box.ymin() + || point.y() > box.ymax() + || point.z() < box.zmin() + || point.z() > box.zmax()) return CGAL::ON_UNBOUNDED_SIDE; } - tree_built = true; return internal::Point_inside_vertical_ray_cast()( point, *tree_ptr, ray_functor, vector_functor); From fe746764cf3dab58a70afa7945c4ab26a0489d45 Mon Sep 17 00:00:00 2001 From: Maxime Gimeno Date: Wed, 2 Oct 2019 15:20:18 +0200 Subject: [PATCH 184/363] remove the bool. --- .../include/CGAL/Side_of_triangle_mesh.h | 28 +++++++++---------- 1 file changed, 13 insertions(+), 15 deletions(-) diff --git a/Polygon_mesh_processing/include/CGAL/Side_of_triangle_mesh.h b/Polygon_mesh_processing/include/CGAL/Side_of_triangle_mesh.h index ec11f7482cf..de8b78f0834 100644 --- a/Polygon_mesh_processing/include/CGAL/Side_of_triangle_mesh.h +++ b/Polygon_mesh_processing/include/CGAL/Side_of_triangle_mesh.h @@ -106,7 +106,6 @@ class Side_of_triangle_mesh const AABB_tree_* tree_ptr; bool own_tree; CGAL::Bbox_3 box; - mutable bool tree_built; public: @@ -139,7 +138,6 @@ public: faces(tmesh).second, tmesh, vpmap); box = Polygon_mesh_processing::bbox(tmesh, parameters::vertex_point_map(vpmap)); - tree_built = false; } /** @@ -163,7 +161,6 @@ public: faces(tmesh).second, tmesh); box = Polygon_mesh_processing::bbox(tmesh); - tree_built = false; } /** @@ -182,7 +179,6 @@ public: , tree_ptr(&tree) , own_tree(false) { - tree_built = false; box = tree.bbox(); } @@ -204,18 +200,20 @@ public: */ Bounded_side operator()(const Point& point) const { - if(!tree_built){ - if(point.x() < box.xmin() - || point.x() > box.xmax() - || point.y() < box.ymin() - || point.y() > box.ymax() - || point.z() < box.zmin() - || point.z() > box.zmax()) - return CGAL::ON_UNBOUNDED_SIDE; + if(point.x() < box.xmin() + || point.x() > box.xmax() + || point.y() < box.ymin() + || point.y() > box.ymax() + || point.z() < box.zmin() + || point.z() > box.zmax()) + { + return CGAL::ON_UNBOUNDED_SIDE; + } + else + { + return internal::Point_inside_vertical_ray_cast()( + point, *tree_ptr, ray_functor, vector_functor); } - tree_built = true; - return internal::Point_inside_vertical_ray_cast()( - point, *tree_ptr, ray_functor, vector_functor); } }; From 962e8b10a65b5409aef1b717f2c9148d9b06c05e Mon Sep 17 00:00:00 2001 From: Mael Date: Thu, 3 Oct 2019 08:12:16 +0200 Subject: [PATCH 185/363] Fix typo --- 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 0602a0e8b72..dcda38324be 100644 --- a/Triangulation_2/include/CGAL/Constrained_triangulation_2.h +++ b/Triangulation_2/include/CGAL/Constrained_triangulation_2.h @@ -52,8 +52,8 @@ struct No_constraint_intersection_requiring_constructions_tag{}; struct Exact_intersections_tag{}; // to be used with an exact number type struct Exact_predicates_tag{}; // to be used with filtered exact number -// This was deprecated in favor of `No_consNo_constraint_intersection_requiring_constructions_tagint_intersection_requiring_constructions_tag` -// due to an inaccuracy between the code and the documenation. +// This was deprecated and replaced by ` No_constraint_intersection_tag` and `No_constraint_intersection_requiring_constructions_tag` +// due to an inconsistency between the code and the documenation. struct CGAL_DEPRECATED No_intersection_tag : public No_constraint_intersection_requiring_constructions_tag { }; From 79026c255e7c2a0889228799201d1f6bfd484574 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mael=20Rouxel-Labb=C3=A9?= Date: Tue, 8 Oct 2019 15:35:29 +0200 Subject: [PATCH 186/363] Fix documentation of CGAL::make_grid (bad line break, bad links) --- BGL/include/CGAL/boost/graph/generators.h | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/BGL/include/CGAL/boost/graph/generators.h b/BGL/include/CGAL/boost/graph/generators.h index 5189bd7297d..abcd8982f6d 100644 --- a/BGL/include/CGAL/boost/graph/generators.h +++ b/BGL/include/CGAL/boost/graph/generators.h @@ -742,11 +742,12 @@ make_icosahedron(Graph& g, * If `triangulated` is `true`, the diagonal of each cell is oriented from (0,0) to (1,1) * in the cell coordinates. * - *\tparam CoordinateFunctor a function object providing `Point_3 operator()(size_type I, size_type J)` with `Point_3` being - * the value_type of the internal property_map for `CGAL::vertex_point_t`. - * and outputs a `boost::property_traits::%type>::%value_type`. - * It will be called with arguments (`w`, `h`), with `w` in [0..`i`] and `h` in [0..`j`]. - *

    %Default: a point with positive integer coordinates (`w`, `h`, 0), with `w` in [0..`i`] and `h` in [0..`j`] + *\tparam CoordinateFunctor a function object providing: + * `%Point_3 operator()(size_type I, size_type J)`, with `%Point_3` being the value_type + * of the internal property_map for `CGAL::vertex_point_t` and outputs an object of type + * `boost::property_traits::%type>::%value_type`. + * It will be called with arguments (`w`, `h`), with `w` in [0..`i`] and `h` in [0..`j`].
    + * %Default: a point with positive integer coordinates (`w`, `h`, 0), with `w` in [0..`i`] and `h` in [0..`j`] * * \returns the non-border non-diagonal halfedge that has the target vertex associated with the first point of the grid (default is (0,0,0) ). */ From 0b67e30c018a66696902cabd21920c7bcdff8e80 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mael=20Rouxel-Labb=C3=A9?= Date: Tue, 8 Oct 2019 15:37:08 +0200 Subject: [PATCH 187/363] Improve user-friendliness of PMP::Locate by removing the class Location_traits The problem was that Location_traits is templated by Named Parameters, and it is extremely unpractical to have to explicitly write the type (it's nested classes all the way down). Instead, we use template aliases for most types, and template by the field type (FT) when necessary, which is much easier to write for the user. Since template aliases cannot automatically deduce template parameters, non-Doxygen versions of functions must be written without them from time to time. Other fixes: - Simplify implementation of function 'random_location_halfedge' - Don't initialize FTs from doubles - Minor doc improvements - reference to points when using VPMs --- .../CGAL/Polygon_mesh_processing/locate.h | 804 ++++++++++-------- 1 file changed, 444 insertions(+), 360 deletions(-) diff --git a/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/locate.h b/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/locate.h index 14e5e9192ac..f82daed743b 100644 --- a/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/locate.h +++ b/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/locate.h @@ -60,9 +60,7 @@ // - `w2` corresponds to `target(next(halfedge(f, tm), tm), tm)` namespace CGAL { - namespace Polygon_mesh_processing { - namespace internal { // The Ray must have the same ambient dimension as the property map's value type (aka, the point type) @@ -75,91 +73,87 @@ struct Ray_type_selector typedef typename Kernel::Ray_2 type; }; -template +template struct Ray_type_selector { typedef typename CGAL::Kernel_traits::type Kernel; typedef typename Kernel::Ray_3 type; }; +// Just for convenience +template > +struct Location_traits +{ + typedef typename GetVertexPointMap::const_type VertexPointMap; + typedef typename boost::property_traits::value_type Point; + typedef typename internal::Ray_type_selector::type Ray; + + typedef typename GetGeomTraits::type Geom_traits; + typedef typename Geom_traits::FT FT; + + typedef typename boost::graph_traits::face_descriptor face_descriptor; + + typedef std::array Barycentric_coordinates; + typedef std::pair Face_location; +}; + } // end namespace internal /// \ingroup PMP_locate_grp /// -/// \brief Helper class whose sole purpose is to make it easier to access some useful types. +/// A variant used in the function `get_descriptor_from_location()`. +template +using descriptor_variant = boost::variant::vertex_descriptor, + typename boost::graph_traits::halfedge_descriptor, + typename boost::graph_traits::face_descriptor>; + +/// \ingroup PMP_locate_grp /// -/// \tparam TriangleMesh a model of `FaceListGraph` -/// \tparam NamedParameters a sequence of \ref pmp_namedparameters "Named Parameters" +/// A triplet of coordinates describing the barycentric coordinates of a point +/// with respect to the vertices of a triangular face. /// -template > -class Location_traits -{ -public: - 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; - typedef boost::variant descriptor_variant; +/// \sa `Face_location` +template +using Barycentric_coordinates = std::array; -#ifdef DOXYGEN_RUNNING - /// This is the type of the vertex point property map, either the one passed through the named parameters - /// or the default, internal one of the mesh. - typedef unspecified_type VPM; - - /// The traits class, either passed as a named parameter or deduced from the Point type - /// of the vertex property map (the point type must then be compatible with `CGAL::Kernel_traits`) - typedef unspecified_type Geom_traits; -#else - typedef typename GetVertexPointMap::const_type VPM; - typedef typename GetGeomTraits::type Geom_traits; -#endif - - typedef typename boost::property_traits::value_type Point; - typedef typename Geom_traits::FT FT; - -#ifdef DOXYGEN_RUNNING - /// Either Geom_traits::Ray_2 or Geom_traits::Ray_3, depending on the ambient dimension of the mesh - typedef unspecified_type Ray; -#else - typedef typename internal::Ray_type_selector::type Ray; -#endif - - typedef std::array Barycentric_coordinates; - - /// If `tm` is the input triangulated surface mesh and given the pair (`f`, `bc`) - /// such that `bc` is the triplet of barycentric coordinates `(w0, w1, w2)`, the correspondance - /// between the coordinates in `bc` and the vertices of the face `f` is the following: - /// - `w0` corresponds to `source(halfedge(f, tm), tm)` - /// - `w1` corresponds to `target(halfedge(f, tm), tm)` - /// - `w2` corresponds to `target(next(halfedge(f, tm), tm), tm)` - typedef std::pair Face_location; -}; +/// \ingroup PMP_locate_grp +/// +/// If `tm` is the input triangulated surface mesh and given the pair (`f`, `bc`) +/// such that `bc` is the triplet of barycentric coordinates `(w0, w1, w2)`, the correspondance +/// between the coordinates in `bc` and the vertices of the face `f` is the following: +/// - `w0` corresponds to `source(halfedge(f, tm), tm)` +/// - `w1` corresponds to `target(halfedge(f, tm), tm)` +/// - `w2` corresponds to `target(next(halfedge(f, tm), tm), tm)` +template +using Face_location = std::pair::face_descriptor, + Barycentric_coordinates >; // forward declarations -template -bool is_in_face(const typename Location_traits::Face_location& loc, +template +bool is_in_face(const std::pair::face_descriptor, + std::array >& loc, const TriangleMesh& tm); -template -typename Location_traits::descriptor_variant -get_descriptor_from_location(const typename Location_traits::Face_location& loc, +template +descriptor_variant +get_descriptor_from_location(const std::pair::face_descriptor, + std::array >& loc, const TriangleMesh& tm); -template -typename Location_traits::Face_location -locate_in_face(typename boost::graph_traits::halfedge_descriptor he, - typename Location_traits::FT t, +template +Face_location +locate_in_face(typename boost::graph_traits::halfedge_descriptor hd, + const FT t, const TriangleMesh& tm); // end of forward declarations namespace internal { -template +template OutputIterator -incident_faces(const typename Location_traits::Face_location& location, +incident_faces(const std::pair::face_descriptor, + std::array >& location, const TriangleMesh& tm, OutputIterator out) { @@ -167,11 +161,7 @@ incident_faces(const typename Location_traits::Face_location& loca typedef typename boost::graph_traits::halfedge_descriptor halfedge_descriptor; typedef typename boost::graph_traits::face_descriptor face_descriptor; - typedef boost::variant descriptor_variant; - - descriptor_variant dv = get_descriptor_from_location(location, tm); + const descriptor_variant dv = get_descriptor_from_location(location, tm); if(const vertex_descriptor* vd_ptr = boost::get(&dv)) { @@ -195,14 +185,11 @@ incident_faces(const typename Location_traits::Face_location& loca } // Snapping coordinates for robustness -template +template bool -snap_coordinates_to_border(typename Location_traits::Barycentric_coordinates& coords, - const typename Location_traits::FT tolerance = - std::numeric_limits::FT>::epsilon()) +snap_coordinates_to_border(std::array& coords, + const FT tolerance = std::numeric_limits::epsilon()) { - typedef typename Location_traits::FT FT; - #ifdef CGAL_PMP_LOCATE_DEBUG std::cout << "Pre-snapping: " << coords[0] << " " << coords[1] << " " << coords[2] << std::endl; std::cout << "Sum: " << coords[0] + coords[1] + coords[2] << std::endl; @@ -210,7 +197,7 @@ snap_coordinates_to_border(typename Location_traits::Barycentric_c #endif // To still keep a sum roughly equals to 1, keep in memory the small changes - FT residue = 0.; + FT residue(0); bool snapped = false; for(int i=0; i<3; ++i) @@ -219,20 +206,20 @@ snap_coordinates_to_border(typename Location_traits::Barycentric_c { snapped = true; residue += coords[i]; - coords[i] = 0.; + coords[i] = FT(0); } - else if(CGAL::abs(1 - coords[i]) <= tolerance) + else if(CGAL::abs(FT(1) - coords[i]) <= tolerance) { snapped = true; - residue -= 1. - coords[i]; - coords[i] = 1.; + residue -= FT(1) - coords[i]; + coords[i] = FT(1); } } // Dump the residue into one of the barycentric values that is neither 0 nor 1 for(int i=0; i<3; ++i) { - if(coords[i] != 0. && coords[i] != 1.) + if(coords[i] != FT(0) && coords[i] != FT(1)) { coords[i] += residue; break; @@ -249,13 +236,14 @@ snap_coordinates_to_border(typename Location_traits::Barycentric_c return snapped; } -template +template bool -snap_location_to_border(typename Location_traits::Face_location& loc, - const typename Location_traits::FT tolerance = - std::numeric_limits::FT>::epsilon()) +snap_location_to_border(std::pair::face_descriptor, + std::array >& loc, + const TriangleMesh /*tm*/, + const FT tolerance = std::numeric_limits::epsilon()) { - return snap_coordinates_to_border(loc.second, tolerance); + return snap_coordinates_to_border(loc.second, tolerance); } template @@ -287,7 +275,7 @@ struct Barycentric_coordinate_calculator // 2D version FT d21 = csp2(v2, v1); FT denom = d00 * d11 - d01 * d01; - CGAL_assertion((d00 * d11 - d01 * d01) != FT(0)); // denom != 0. + CGAL_assertion((d00 * d11 - d01 * d01) != FT(0)); // denom != 0 FT v = (d11 * d20 - d01 * d21) / denom; FT w = (d00 * d21 - d01 * d20) / denom; @@ -324,8 +312,8 @@ struct Barycentric_coordinate_calculator FT d20 = csp3(v2, v0); FT d21 = csp3(v2, v1); - CGAL_assertion((d00 * d11 - d01 * d01) != FT(0)); // denom != 0. - FT denom_inv = 1. / (d00 * d11 - d01 * d01); + CGAL_assertion((d00 * d11 - d01 * d01) != FT(0)); // denom != 0 + FT denom_inv = FT(1) / (d00 * d11 - d01 * d01); FT v = (d11 * d20 - d01 * d21) * denom_inv; FT w = (d00 * d21 - d01 * d20) * denom_inv; @@ -343,7 +331,7 @@ struct Barycentric_point_constructor // 2D version const K& /*k*/) const { FT sum = wp + wq + wr; - CGAL_assertion(sum != 0); + CGAL_assertion(sum != FT(0)); // In theory, this should be compute_x_2(compute_point_2(...)) and construct_P() at the end... FT x = (wp * p.x() + wq * q.x() + wr * r.x()) / sum; @@ -362,7 +350,7 @@ struct Barycentric_point_constructor // 3D version const K& /*k*/) const { FT sum = wp + wq + wr; - CGAL_assertion(sum != 0); + CGAL_assertion(sum != FT(0)); FT x = (wp * p.x() + wq * q.x() + wr * r.x()) / sum; FT y = (wp * p.y() + wq * q.y() + wr * r.y()) / sum; FT z = (wp * p.z() + wq * q.z() + wr * r.z()) / sum; @@ -378,25 +366,24 @@ struct Barycentric_point_constructor // 3D version /// \brief Given a set of three points and a query point, computes the barycentric /// coordinates of the query point with respect to the first three points. /// +/// \tparam GeomTraits the type of a geometric traits. Must be a model of `Kernel` and be compatible +/// with the template parameter `Point`. /// \tparam Point the type of a geometric 2D or 3D point -/// \tparam K the type of a geometric traits. Must be a model of `Kernel`. /// /// \param p,q,r three points with respect to whom the barycentric coordinates of `query` will be computed /// \param query the query point whose barycentric coordinates will be computed -/// \param k an instance of the geometric traits +/// \param gt an instance of the geometric traits /// /// \pre `p`, `q`, and `r` are not collinear. -/// \pre It must be possible to extract a kernel type model of `Kernel`, using `CGAL::Kernel_traits

    ` -/// (this is the case for all standard %CGAL point types and classes inheriting such point types). /// \pre `query` lies on the plane defined by `p`, `q`, and `r`. /// -template -std::array +template +std::array barycentric_coordinates(const Point& p, const Point& q, const Point& r, const Point& query, - const K& k) + const GeomTraits& gt) { - internal::Barycentric_coordinate_calculator calculator; - return calculator(p, q, r, query, k); + internal::Barycentric_coordinate_calculator calculator; + return calculator(p, q, r, query, gt); } template @@ -420,24 +407,30 @@ barycentric_coordinates(const Point& p, const Point& q, const Point& r, const Po /// a value `t` between `0` and `1` and setting the barycentric coordinates to `t`, `1-t`, /// and `0` for respetively the source and target of `hd`, and the third vertex. /// +/// \tparam FT must be a model of `FieldNumberType` /// \tparam TriangleMesh a model of `FaceGraph` /// /// \param hd a halfedge of `tm` /// \param tm a triangulated surface mesh /// \param rnd optional random number generator /// -template -typename Location_traits::Face_location +template +Face_location random_location_on_halfedge(typename boost::graph_traits::halfedge_descriptor hd, const TriangleMesh& tm, CGAL::Random& rnd = get_default_random()) { - typedef typename Location_traits::FT FT; - CGAL_precondition(CGAL::is_triangle_mesh(tm)); - FT t(rnd.uniform_real(0., 1.)); - return locate_in_face(hd, t, tm); + const int h_id = halfedge_index_in_face(hd, tm); + const FT t(rnd.uniform_real(0., 1.)); + + std::array coordinates; + coordinates[h_id] = t; + coordinates[(h_id+1)%3] = FT(1-t); + coordinates[(h_id+2)%3] = FT(0); + + return std::make_pair(face(hd, tm), coordinates); } /// \ingroup PMP_locate_grp @@ -449,20 +442,19 @@ random_location_on_halfedge(typename boost::graph_traits::halfedge /// a value `v` between `1-u`, and setting the barycentric coordinates to `u`, `v`, and /// `1-u-v` for respectively the source and target of `halfedge(fd, tm)`, and the third point. /// +/// \tparam FT must be a model of `FieldNumberType` /// \tparam TriangleMesh a model of `FaceGraph` /// /// \param fd a face of `tm` /// \param tm a triangulated surface mesh /// \param rnd optional random number generator /// -template -typename Location_traits::Face_location +template +Face_location random_location_on_face(typename boost::graph_traits::face_descriptor fd, const TriangleMesh& tm, CGAL::Random& rnd = get_default_random()) { - typedef typename Location_traits::FT FT; - CGAL_USE(tm); CGAL_precondition(CGAL::is_triangle_mesh(tm)); CGAL_precondition(fd != boost::graph_traits::null_face()); @@ -482,6 +474,7 @@ random_location_on_face(typename boost::graph_traits::face_descrip /// a random point on that face. The barycentric coordinates of the point in the face /// are thus all positive. Note that all faces have the same probability to be chosen. /// +/// \tparam FT must be a model of `FieldNumberType` /// \tparam TriangleMesh a model of `FaceGraph` /// /// \param tm a triangulated surface mesh @@ -489,26 +482,25 @@ random_location_on_face(typename boost::graph_traits::face_descrip /// /// \sa `random_location_on_face()` /// -template -typename Location_traits::Face_location -random_location_on_mesh(const TriangleMesh& tm, CGAL::Random& rnd = get_default_random()) +template +Face_location +random_location_on_mesh(const TriangleMesh& tm, + CGAL::Random& rnd = get_default_random()) { typedef typename boost::graph_traits::face_descriptor face_descriptor; CGAL_precondition(CGAL::is_triangle_mesh(tm)); face_descriptor fd = CGAL::internal::random_face_in_mesh(tm, rnd); - return random_location_on_face(fd, tm, rnd); + return random_location_on_face(fd, tm, rnd); } /// @} /// \ingroup PMP_locate_grp /// -/// \brief Given a location, that is an ordered pair composed of a -/// `boost::graph_traits::%face_descriptor` and an array -/// of barycentric coordinates, returns a descriptor to the simplex -/// of smallest dimension on which the point corresponding to the location lies. +/// \brief Given a location, returns a descriptor to the simplex of smallest dimension +/// on which the point corresponding to the location lies. /// /// \details In other words: /// - if the point lies on a vertex, this function returns a `boost::graph_traits::%vertex_descriptor` `v`; @@ -517,24 +509,30 @@ random_location_on_mesh(const TriangleMesh& tm, CGAL::Random& rnd = get_default_ /// - otherwise, this function returns a `boost::graph_traits::%face_descriptor` /// `fd` (equal to `loc.first`). /// +/// \tparam FT must be a model of `FieldNumberType` /// \tparam TriangleMesh a model of `FaceGraph` /// /// \param loc a location with `loc.first` a face of `tm` /// \param tm a triangulated surface mesh /// -/// \pre the location corresponds to a point that is within a face of `tm`. -/// \pre `loc` describes the barycentric coordinates of a point that lives on the face (boundary included), +/// \pre `loc.first` is a face descriptor corresponding to a face of `tm`. +/// \pre `loc` describes the barycentric coordinates of a point that lives within the face (boundary included), /// meaning the barycentric coordinates are all positive. /// -template -typename Location_traits::descriptor_variant -get_descriptor_from_location(const typename Location_traits::Face_location& loc, +template +descriptor_variant +#ifdef DOXYGEN_RUNNING // just for convenience because template alias do not allow template deduction +get_descriptor_from_location(const Face_location& loc, +#else +get_descriptor_from_location(const std::pair::face_descriptor, + std::array >& loc, +#endif const TriangleMesh& tm) { typedef typename boost::graph_traits::halfedge_descriptor halfedge_descriptor; typedef typename boost::graph_traits::face_descriptor face_descriptor; - typedef typename Location_traits::Barycentric_coordinates Barycentric_coordinates; + typedef Barycentric_coordinates Barycentric_coordinates; const face_descriptor fd = loc.first; const Barycentric_coordinates& bar = loc.second; @@ -549,7 +547,7 @@ get_descriptor_from_location(const typename Location_traits::Face_ // check if the point is a vertex for(int i=0; i<3; ++i) { - if(bar[i] == 1) // coordinate at target(hd, tm) + if(bar[i] == FT(1)) // coordinate at target(hd, tm) return target(hd, tm); hd = next(hd, tm); } @@ -558,7 +556,7 @@ get_descriptor_from_location(const typename Location_traits::Face_ // check if the point is on an edge for(int i=0; i<3; ++i) { - if(bar[i] == 0) // coordinate at target(hd, tm) + if(bar[i] == FT(0)) // coordinate at target(hd, tm) return prev(hd, tm); hd = next(hd, tm); } @@ -568,15 +566,14 @@ get_descriptor_from_location(const typename Location_traits::Face_ /// \ingroup PMP_locate_grp /// -/// \brief Given a location, that is an ordered pair composed of a -/// `boost::graph_traits::%face_descriptor` and an array -/// of barycentric coordinates, returns the geometric position described +/// \brief Given a location in a face, returns the geometric position described /// by these coordinates, as a point. /// +/// \tparam FT must be a model of `FieldNumberType` /// \tparam TriangleMesh a model of `FaceGraph` /// \tparam NamedParameters a sequence of \ref pmp_namedparameters "Named Parameters" /// -/// \param loc the location to transform into a point +/// \param loc the location from which a point is constructed /// \param tm a triangulated surface mesh /// \param np an optional sequence of \ref pmp_namedparameters "Named Parameters" among the ones listed below: /// @@ -587,44 +584,61 @@ get_descriptor_from_location(const typename Location_traits::Face_ /// `boost::vertex_point_t` must be available in `TriangleMesh`. /// \cgalParamEnd /// \cgalParamBegin{geom_traits} -/// a geometric traits class instance, model of `Kernel`. +/// a geometric traits class instance, model of `Kernel`. If such traits class is provided, +/// its type `FT` must be identical to the template parameter `FT` of this function. /// \cgalParamEnd /// \cgalNamedParamsEnd /// /// \pre `loc.first` is a face descriptor corresponding to a face of `tm`. /// -template -typename Location_traits::Point -construct_point(const typename Location_traits::Face_location& loc, +/// \returns a point whose type is the same as the value type of the vertex point property map +/// provided by the user or via named parameters, or the internal point map of the mesh `tm`. +/// +template +#ifdef DOXYGEN_RUNNING +Point +construct_point(const Face_location& loc, +#else +typename internal::Location_traits::Point +construct_point(const std::pair::face_descriptor, + std::array >& loc, +#endif const TriangleMesh& tm, const NamedParameters& np) { typedef typename boost::graph_traits::halfedge_descriptor halfedge_descriptor; + typedef typename GetGeomTraits::type Geom_traits; + typedef typename GetVertexPointMap::const_type VertexPointMap; typedef typename boost::property_traits::value_type Point; - typedef typename GetGeomTraits::type Geom_traits; + typedef typename boost::property_traits::reference Point_reference; + using parameters::get_parameter; using parameters::choose_parameter; CGAL_precondition(CGAL::is_triangle_mesh(tm)); - VertexPointMap vpm = parameters::choose_parameter(parameters::get_parameter(np, internal_np::vertex_point), get_const_property_map(boost::vertex_point, tm)); Geom_traits gt = choose_parameter(get_parameter(np, internal_np::geom_traits), Geom_traits()); halfedge_descriptor hd = halfedge(loc.first, tm); - const Point& p0 = get(vpm, source(hd, tm)); - const Point& p1 = get(vpm, target(hd, tm)); - const Point& p2 = get(vpm, target(next(hd, tm), tm)); + const Point_reference p0 = get(vpm, source(hd, tm)); + const Point_reference p1 = get(vpm, target(hd, tm)); + const Point_reference p2 = get(vpm, target(next(hd, tm), tm)); internal::Barycentric_point_constructor bp_constructor; return bp_constructor(p0, loc.second[0], p1, loc.second[1], p2, loc.second[2], gt); } -template +template typename property_map_value::type -construct_point(const typename Location_traits::Face_location& loc, +#ifdef DOXYGEN_RUNNING +construct_point(const Face_location& loc, +#else +construct_point(const std::pair::face_descriptor, + std::array >& loc, +#endif const TriangleMesh& tm) { return construct_point(loc, tm, parameters::all_default()); @@ -635,10 +649,7 @@ construct_point(const typename Location_traits::Face_location& loc /// \ingroup PMP_locate_grp /// -/// \brief Given a location, that is an ordered pair composed of a -/// `boost::graph_traits::%face_descriptor` and an array -/// of barycentric coordinates, returns whether the location is -/// on the vertex `vd` or not. +/// \brief Given a location, returns whether the location is on the vertex `vd` or not. /// /// \details If `tm` is the input triangulated surface mesh and given the pair (`f`, `bc`) /// such that `bc` is the triplet of barycentric coordinates `(w0, w1, w2)`, the correspondance @@ -647,6 +658,7 @@ construct_point(const typename Location_traits::Face_location& loc /// - `w1` corresponds to `target(halfedge(f, tm), tm)` /// - `w2` corresponds to `target(next(halfedge(f, tm), tm), tm)` /// +/// \tparam FT a model of `FieldNumberType` /// \tparam TriangleMesh a model of `FaceGraph` /// /// \param loc a location with `loc.first` a face of `tm` @@ -655,19 +667,23 @@ construct_point(const typename Location_traits::Face_location& loc /// /// \pre `loc.first` is a face descriptor corresponding to a face of `tm`. /// -template +template bool -is_on_vertex(const typename Location_traits::Face_location& loc, +#ifdef DOXYGEN_RUNNING +is_on_vertex(const Face_location& loc, +#else +is_on_vertex(const std::pair::face_descriptor, + std::array >& loc, +#endif const typename boost::graph_traits::vertex_descriptor vd, const TriangleMesh& tm) { typedef typename boost::graph_traits::vertex_descriptor vertex_descriptor; - typedef typename Location_traits::descriptor_variant descriptor_variant; if(!is_in_face(loc, tm)) return false; - descriptor_variant dv = get_descriptor_from_location(loc, tm); + const descriptor_variant dv = get_descriptor_from_location(loc, tm); if(const vertex_descriptor* vd_ptr = boost::get(&dv)) return (vd == *vd_ptr); @@ -677,10 +693,7 @@ is_on_vertex(const typename Location_traits::Face_location& loc, /// \ingroup PMP_locate_grp /// -/// \brief Given a location, that is an ordered pair composed of a -/// `boost::graph_traits::%face_descriptor` and an array -/// of barycentric coordinates, returns whether the location is -/// on the halfedge `hd` or not. +/// \brief Given a location, returns whether this location is on the halfedge `hd` or not. /// /// \details If `tm` is the input triangulated surface mesh and given the pair (`f`, `bc`) /// such that `bc` is the triplet of barycentric coordinates `(w0, w1, w2)`, the correspondance @@ -689,6 +702,7 @@ is_on_vertex(const typename Location_traits::Face_location& loc, /// - `w1` corresponds to `target(halfedge(f, tm), tm)` /// - `w2` corresponds to `target(next(halfedge(f, tm), tm), tm)` /// +/// \tparam FT a model of `FieldNumberType` /// \tparam TriangleMesh a model of `FaceGraph` /// /// \param loc a location with `loc.first` a face of `tm` @@ -697,20 +711,24 @@ is_on_vertex(const typename Location_traits::Face_location& loc, /// /// \pre `loc.first` is a face descriptor corresponding to a face of `tm`. /// -template +template bool -is_on_halfedge(const typename Location_traits::Face_location& loc, +#ifdef DOXYGEN_RUNNING +is_on_halfedge(const Face_location& loc, +#else +is_on_halfedge(const std::pair::face_descriptor, + std::array >& loc, +#endif const typename boost::graph_traits::halfedge_descriptor hd, const TriangleMesh& tm) { typedef typename boost::graph_traits::vertex_descriptor vertex_descriptor; typedef typename boost::graph_traits::halfedge_descriptor halfedge_descriptor; - typedef typename Location_traits::descriptor_variant descriptor_variant; if(!is_in_face(loc, tm)) return false; - descriptor_variant dv = get_descriptor_from_location(loc, tm); + const descriptor_variant dv = get_descriptor_from_location(loc, tm); if(const vertex_descriptor* vd_ptr = boost::get(&dv)) return (*vd_ptr == source(hd, tm) || *vd_ptr == target(hd, tm)); @@ -733,14 +751,19 @@ is_on_halfedge(const typename Location_traits::Face_location& loc, /// - `w1` corresponds to `target(halfedge(f, tm), tm)` /// - `w2` corresponds to `target(next(halfedge(f, tm), tm), tm)` /// +/// \tparam FT a model of `FieldNumberType` /// \tparam TriangleMesh a model of `FaceGraph` /// /// \param bar an array of barycentric coordinates /// \param tm a triangulated surface mesh /// -template +template bool -is_in_face(const typename Location_traits::Barycentric_coordinates& bar, +#ifdef DOXYGEN_RUNNING +is_in_face(const Barycentric_coordinates& bar, +#else +is_in_face(const std::array& bar, +#endif const TriangleMesh& tm) { CGAL_USE(tm); @@ -750,7 +773,7 @@ is_in_face(const typename Location_traits::Barycentric_coordinates { // "|| bar[i] > 1." is not needed because if everything is positive and the sum is '1', // then each coefficient is below '1'. - if(bar[i] < 0.) + if(bar[i] < FT(0)) return false; } @@ -759,10 +782,7 @@ is_in_face(const typename Location_traits::Barycentric_coordinates /// \ingroup PMP_locate_grp /// -/// \brief Given a location, that is an ordered pair composed of a -/// `boost::graph_traits::%face_descriptor` and an array -/// of barycentric coordinates, returns whether the location is -/// in the face (boundary included) or not. +/// \brief Given a location, returns whether the location is in the face (boundary included) or not. /// /// \details If `tm` is the input triangulated surface mesh and given the pair (`f`, `bc`) /// such that `bc` is the triplet of barycentric coordinates `(w0, w1, w2)`, the correspondance @@ -771,6 +791,7 @@ is_in_face(const typename Location_traits::Barycentric_coordinates /// - `w1` corresponds to `target(halfedge(f, tm), tm)` /// - `w2` corresponds to `target(next(halfedge(f, tm), tm), tm)` /// +/// \tparam FT a model of `FieldNumberType` /// \tparam TriangleMesh a model of `FaceGraph` /// /// \param loc a location with `loc.first` a face of `tm` @@ -778,9 +799,14 @@ is_in_face(const typename Location_traits::Barycentric_coordinates /// /// \pre `loc.first` is a face descriptor corresponding to a face of `tm`. /// -template +template bool -is_in_face(const typename Location_traits::Face_location& loc, +#ifdef DOXYGEN_RUNNING +is_in_face(const Face_location& loc, +#else +is_in_face(const std::pair::face_descriptor, + std::array >& loc, +#endif const TriangleMesh& tm) { return is_in_face(loc.second, tm); @@ -788,10 +814,7 @@ is_in_face(const typename Location_traits::Face_location& loc, /// \ingroup PMP_locate_grp /// -/// \brief Given a location, that is an ordered pair composed of a -/// `boost::graph_traits::%face_descriptor` and an array -/// of barycentric coordinates, returns whether the location is on the boundary -/// of the face or not. +/// \brief Given a location, returns whether the location is on the boundary of the face or not. /// /// \details If `tm` is the input triangulated surface mesh and given the pair (`f`, `bc`) /// such that `bc` is the triplet of barycentric coordinates `(w0, w1, w2)`, the correspondance @@ -800,6 +823,7 @@ is_in_face(const typename Location_traits::Face_location& loc, /// - `w1` corresponds to `target(halfedge(f, tm), tm)` /// - `w2` corresponds to `target(next(halfedge(f, tm), tm), tm)` /// +/// \tparam FT a model of `FieldNumberType` /// \tparam TriangleMesh a model of `FaceGraph` /// /// \param loc a location with `loc.first` a face of `tm` @@ -807,21 +831,23 @@ is_in_face(const typename Location_traits::Face_location& loc, /// /// \pre `loc.first` is a face descriptor corresponding to a face of `tm`. /// -template +template bool -is_on_face_border(const typename Location_traits::Face_location& loc, +#ifdef DOXYGEN_RUNNING +is_on_face_border(const Face_location& loc, +#else +is_on_face_border(const std::pair::face_descriptor, + std::array >& loc, +#endif const TriangleMesh& tm) { - typedef typename Location_traits::Face_location Face_location; - typedef typename Face_location::second_type Barycentric_coordinates; - if(!is_in_face(loc, tm)) return false; - const Barycentric_coordinates& bar = loc.second; + const Barycentric_coordinates& bar = loc.second; for(int i=0; i<3; ++i) - if(bar[i] == 0.) + if(bar[i] == FT(0)) return true; return false; @@ -829,10 +855,7 @@ is_on_face_border(const typename Location_traits::Face_location& l /// \ingroup PMP_locate_grp /// -/// \brief Given a location, that is an ordered pair composed of a -/// `boost::graph_traits::%face_descriptor` and an array -/// of barycentric coordinates, returns whether the location is -/// on the border of the mesh or not. +/// \brief Given a location, returns whether the location is on the border of the mesh or not. /// /// \details If `tm` is the input triangulated surface mesh and given the pair (`f`, `bc`) /// such that `bc` is the triplet of barycentric coordinates `(w0, w1, w2)`, the correspondance @@ -841,6 +864,7 @@ is_on_face_border(const typename Location_traits::Face_location& l /// - `w1` corresponds to `target(halfedge(f, tm), tm)` /// - `w2` corresponds to `target(next(halfedge(f, tm), tm), tm)` /// +/// \tparam FT a model of `FieldNumberType` /// \tparam TriangleMesh a model of `FaceGraph` /// /// \param loc a location with `loc.first` a face of `tm` @@ -848,19 +872,21 @@ is_on_face_border(const typename Location_traits::Face_location& l /// /// \pre `loc.first` is a face descriptor corresponding to a face of `tm`. /// -template +template bool -is_on_mesh_border(const typename Location_traits::Face_location& loc, +#ifdef DOXYGEN_RUNNING +is_on_mesh_border(const Face_location& loc, +#else +is_on_mesh_border(const std::pair::face_descriptor, + std::array >& loc, +#endif const TriangleMesh& tm) { typedef typename boost::graph_traits::halfedge_descriptor halfedge_descriptor; typedef typename boost::graph_traits::face_descriptor face_descriptor; - typedef typename Location_traits::Face_location Face_location; - typedef typename Face_location::second_type Barycentric_coordinates; - const face_descriptor fd = loc.first; - const Barycentric_coordinates& bar = loc.second; + const Barycentric_coordinates& bar = loc.second; if(!is_in_face(bar, tm)) return false; @@ -871,7 +897,7 @@ is_on_mesh_border(const typename Location_traits::Face_location& l // check if the point is a vertex for(int i=0; i<3; ++i) { - if(bar[i] == 1.) // coordinate at target(hd, tm) + if(bar[i] == FT(1)) // coordinate at target(hd, tm) return bool(CGAL::is_border(target(hd, tm), tm)); hd = next(hd, tm); } @@ -880,7 +906,7 @@ is_on_mesh_border(const typename Location_traits::Face_location& l // check if the point is on an edge for(int i=0; i<3; ++i) { - if(bar[i] == 0.) // coordinate at target(hd, tm) + if(bar[i] == FT(0)) // coordinate at target(hd, tm) return CGAL::is_border(edge(prev(hd, tm), tm), tm); hd = next(hd, tm); } @@ -907,6 +933,7 @@ is_on_mesh_border(const typename Location_traits::Face_location& l /// - `w1` corresponds to `target(halfedge(f, tm), tm)` /// - `w2` corresponds to `target(next(halfedge(f, tm), tm), tm)` /// +/// \tparam FT a model of `FieldNumberType` /// \tparam TriangleMesh a model of `FaceGraph` /// /// \param vd a vertex of `tm` @@ -914,34 +941,33 @@ is_on_mesh_border(const typename Location_traits::Face_location& l /// /// \pre `vd` is not an isolated vertex /// -template -typename Location_traits::Face_location -locate_in_face(typename boost::graph_traits::vertex_descriptor vd, - const TriangleMesh& tm) +template +Face_location +locate_vertex(typename boost::graph_traits::vertex_descriptor vd, + const TriangleMesh& tm) { typedef typename boost::graph_traits::halfedge_descriptor halfedge_descriptor; typedef typename boost::graph_traits::face_descriptor face_descriptor; - typedef typename Location_traits::FT FT; - typedef typename Location_traits::Face_location Face_location; + typedef Face_location Face_location; - halfedge_descriptor he = halfedge(vd, tm); + halfedge_descriptor hd = halfedge(vd, tm); - // Find a real face in case 'he' is a border halfedge - for(halfedge_descriptor hd : halfedges_around_target(he, tm)) + // Find a real face in case 'hd' is a border halfedge + for(halfedge_descriptor thd : halfedges_around_target(hd, tm)) { - if(!is_border(hd, tm)) + if(!is_border(thd, tm)) { - he = hd; + hd = thd; break; } } - CGAL_postcondition(!CGAL::is_border(he, tm)); // must find a 'real' face incident to 'vd' + CGAL_postcondition(!CGAL::is_border(hd, tm)); // must find a 'real' face incident to 'vd' - face_descriptor fd = face(he, tm); + face_descriptor fd = face(hd, tm); - CGAL_assertion(target(he, tm) == vd); + CGAL_assertion(target(hd, tm) == vd); CGAL_assertion(fd != boost::graph_traits::null_face()); // isolated vertex @@ -949,8 +975,8 @@ locate_in_face(typename boost::graph_traits::vertex_descriptor vd, return Face_location(); FT coords[3] = { FT(0), FT(0), FT(0) }; - he = next(he, tm); // so that source(he, tm) == vd and it's simpler to handle 'index_in_face' - std::size_t halfedge_local_index = halfedge_index_in_face(he, tm); + hd = next(hd, tm); // so that source(hd, tm) == vd and it's simpler to handle 'index_in_face' + int halfedge_local_index = halfedge_index_in_face(hd, tm); coords[halfedge_local_index] = FT(1); return std::make_pair(fd, CGAL::make_array(coords[0], coords[1], coords[2])); @@ -969,6 +995,7 @@ locate_in_face(typename boost::graph_traits::vertex_descriptor vd, /// - `w1` corresponds to `target(halfedge(f, tm), tm)` /// - `w2` corresponds to `target(next(halfedge(f, tm), tm), tm)` /// +/// \tparam FT a model of `FieldNumberType` /// \tparam TriangleMesh a model of `FaceGraph` /// /// \param vd a vertex of `tm` and a vertex of the face `fd` @@ -977,14 +1004,12 @@ locate_in_face(typename boost::graph_traits::vertex_descriptor vd, /// /// \pre `fd` is not the null face /// -template -typename Location_traits::Face_location -locate_in_face(const typename boost::graph_traits::vertex_descriptor vd, - const typename boost::graph_traits::face_descriptor fd, - const TriangleMesh& tm) +template +Face_location +locate_vertex(const typename boost::graph_traits::vertex_descriptor vd, + const typename boost::graph_traits::face_descriptor fd, + const TriangleMesh& tm) { - typedef typename Location_traits::FT FT; - CGAL_precondition(fd != boost::graph_traits::null_face()); FT coords[3] = { FT(0), FT(0), FT(0) }; @@ -996,8 +1021,8 @@ locate_in_face(const typename boost::graph_traits::vertex_descript /// \ingroup PMP_locate_grp /// -/// \brief Given a point described by a halfedge `he` and a scalar `t` -/// as `p = (1 - t) * source(he, tm) + t * target(he, tm)`, +/// \brief Given a point described by a halfedge `hd` and a scalar `t` +/// as `p = (1 - t) * source(hd, tm) + t * target(hd, tm)`, /// returns this location along the given edge as a location, that is /// an ordered pair specifying a face containing the location and the /// barycentric coordinates of that location in that face. @@ -1009,23 +1034,23 @@ locate_in_face(const typename boost::graph_traits::vertex_descript /// - `w1` corresponds to `target(halfedge(f, tm), tm)` /// - `w2` corresponds to `target(next(halfedge(f, tm), tm), tm)` /// +/// \tparam FT a model of `FieldNumberType` /// \tparam TriangleMesh a model of `FaceGraph` /// -/// \param he a halfedge of `tm` -/// \param t the parametric distance of the desired point along `he` +/// \param hd a halfedge of `tm` +/// \param t the parametric distance of the desired point along `hd` /// \param tm a triangulated surface mesh /// -template -typename Location_traits::Face_location -locate_in_face(const typename boost::graph_traits::halfedge_descriptor he, - const typename Location_traits::FT t, - const TriangleMesh& tm) +template +Face_location +locate_on_halfedge(const typename boost::graph_traits::halfedge_descriptor hd, + const FT t, + const TriangleMesh& tm) { typedef typename boost::graph_traits::face_descriptor face_descriptor; - typedef typename Location_traits::FT FT; - face_descriptor fd = face(he, tm); - std::size_t edge_local_index = halfedge_index_in_face(he, tm); + face_descriptor fd = face(hd, tm); + int edge_local_index = halfedge_index_in_face(hd, tm); const FT one_minus_t(FT(1) - t); FT coords[3] = { FT(0), FT(0), FT(0) }; @@ -1052,7 +1077,8 @@ locate_in_face(const typename boost::graph_traits::halfedge_descri /// \tparam TriangleMesh a model of `FaceGraph` /// \tparam NamedParameters a sequence of \ref pmp_namedparameters "Named Parameters" /// -/// \param query a point +/// \param query a point, whose type is equal to the value type of the vertex point property map +/// (either user-provided via named parameters or the internal point map of the mesh `tm`) /// \param fd a face of `tm` /// \param tm a triangulated surface mesh /// \param np an optional sequence of \ref pmp_namedparameters "Named Parameters" among the ones listed below: @@ -1064,7 +1090,9 @@ locate_in_face(const typename boost::graph_traits::halfedge_descri /// `boost::vertex_point_t` must be available in `TriangleMesh`. /// \cgalParamEnd /// \cgalParamBegin{geom_traits} -/// a geometric traits class instance, model of `Kernel`. +/// a geometric traits class instance, model of `Kernel`. If provided, the types `FT` and `Kernel::FT` +/// must be identical and the traits class must be compatible with the value type of the vertex point +/// property map. /// \cgalParamEnd /// \cgalParamBegin{snapping_tolerance} /// a tolerance value used to snap barycentric coordinates. Depending on the geometric traits used, @@ -1077,21 +1105,31 @@ locate_in_face(const typename boost::graph_traits::halfedge_descri /// /// \pre `fd` is not the null face /// +/// \returns a face location. The type `FT` is deduced from the geometric traits, either provided by +/// the user via named parameters (with `geom_traits`) or using `CGAL::Kernel_traits` +/// and the point type of the vertex point property map in use. +/// template -typename Location_traits::Face_location -locate_in_face(const typename Location_traits::Point& query, +#ifdef DOXYGEN_RUNNING +Face_location +locate_in_face(const Point& query, +#else +typename internal::Location_traits::Face_location +locate_in_face(const typename internal::Location_traits::Point& query, +#endif const typename boost::graph_traits::face_descriptor fd, const TriangleMesh& tm, const NamedParameters& np) { - typedef typename boost::graph_traits::vertex_descriptor vertex_descriptor; + typedef typename boost::graph_traits::vertex_descriptor vertex_descriptor; - typedef typename Location_traits::FT FT; + typedef typename GetVertexPointMap::const_type VertexPointMap; + typedef typename boost::property_traits::value_type Point; + typedef typename boost::property_traits::reference Point_reference; + + typedef typename GetGeomTraits::type Geom_traits; + typedef typename Geom_traits::FT FT; - // VertexPointMap - typedef typename GetGeomTraits::type Geom_traits; - typedef typename GetVertexPointMap::const_type VertexPointMap; - typedef typename boost::property_traits::value_type Point; using parameters::get_parameter; using parameters::choose_parameter; @@ -1107,9 +1145,9 @@ locate_in_face(const typename Location_traits::Po vertex_descriptor vd1 = target(halfedge(fd, tm), tm); vertex_descriptor vd2 = target(next(halfedge(fd, tm), tm), tm); - const Point& p0 = get(vpm, vd0); - const Point& p1 = get(vpm, vd1); - const Point& p2 = get(vpm, vd2); + const Point_reference p0 = get(vpm, vd0); + const Point_reference p1 = get(vpm, vd1); + const Point_reference p2 = get(vpm, vd2); std::array coords = barycentric_coordinates(p0, p1, p2, query, gt); @@ -1120,7 +1158,7 @@ locate_in_face(const typename Location_traits::Po // Try to to snap the coordinates, hoping the problem is just a -1e-17ish epsilon // pushing the coordinates over the edge - internal::snap_coordinates_to_border(coords, snap_tolerance); + internal::snap_coordinates_to_border(coords, snap_tolerance); } return std::make_pair(fd, coords); @@ -1128,8 +1166,8 @@ locate_in_face(const typename Location_traits::Po #ifndef DOXYGEN_RUNNING // because this is in the middle of a @{ @} doxygen group template -typename Location_traits::Face_location -locate_in_face(const typename property_map_value::type& query, +typename internal::Location_traits::Face_location +locate_in_face(const typename internal::Location_traits::Point& query, const typename boost::graph_traits::face_descriptor f, const TriangleMesh& tm) { @@ -1139,10 +1177,7 @@ locate_in_face(const typename property_map_value::%face_descriptor` and an array -/// of barycentric coordinates, and a second face adjacent to the first, -/// return the location of the point in the second face. +/// \brief Given a location and a second face adjacent to the first, returns the location of the point in the second face. /// /// \details If `tm` is the input triangulated surface mesh and given the pair (`f`, `bc`) /// such that `bc` is the triplet of barycentric coordinates `(w0, w1, w2)`, the correspondance @@ -1151,17 +1186,23 @@ locate_in_face(const typename property_map_value -typename Location_traits::Face_location -locate_in_adjacent_face(const typename Location_traits::Face_location& loc, +template +Face_location +#ifdef DOXYGEN_RUNNING +locate_in_adjacent_face(const Face_location& loc, +#else +locate_in_adjacent_face(const std::pair::face_descriptor, + std::array >& loc, +#endif const typename boost::graph_traits::face_descriptor fd, const TriangleMesh& tm) { @@ -1169,23 +1210,16 @@ locate_in_adjacent_face(const typename Location_traits::Face_locat typedef typename boost::graph_traits::halfedge_descriptor halfedge_descriptor; typedef typename boost::graph_traits::face_descriptor face_descriptor; - typedef boost::variant descriptor_variant; - - typedef typename Location_traits::Face_location Face_location; - typedef typename Location_traits::FT FT; - if(loc.first == fd) return loc; - Face_location loc_in_fd = std::make_pair(fd, CGAL::make_array(FT(0), FT(0), FT(0))); - descriptor_variant dv = get_descriptor_from_location(loc, tm); + Face_location loc_in_fd = std::make_pair(fd, CGAL::make_array(FT(0), FT(0), FT(0))); + const descriptor_variant dv = get_descriptor_from_location(loc, tm); if(const vertex_descriptor* vd_ptr = boost::get(&dv)) { int index_of_vd = vertex_index_in_face(*vd_ptr, fd, tm); - loc_in_fd.second[index_of_vd] = 1.; + loc_in_fd.second[index_of_vd] = FT(1); // Note that the barycentric coordinates were initialized to 0, // so the second and third coordinates are already set up properly. } @@ -1234,21 +1268,22 @@ locate_in_adjacent_face(const typename Location_traits::Face_locat // - the first location must be known // - the second must be a point in a face incident to get_descriptor_from_location(known_location) // note: not returning the query location to emphasis that the known location can change too. -template +template bool -locate_in_common_face(typename Location_traits::Face_location& known_location, - const typename Location_traits::Point& query, - typename Location_traits::Face_location& query_location, +locate_in_common_face(std::pair::face_descriptor, + std::array >& known_location, + const typename internal::Location_traits::Point& query, + std::pair::face_descriptor, + std::array >& query_location, const TriangleMesh& tm, - const typename Location_traits::FT tolerance = - std::numeric_limits::FT>::epsilon()) + const NamedParameters& np, + const FT tolerance = std::numeric_limits::epsilon()) { 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; - typedef boost::variant descriptor_variant; - descriptor_variant dv = get_descriptor_from_location(known_location, tm); + descriptor_variant dv = get_descriptor_from_location(known_location, tm); bool is_query_location_in_face = false; @@ -1263,8 +1298,8 @@ locate_in_common_face(typename Location_traits::Face_location& kno continue; // check if 'query' can be found in that face - query_location = locate_in_face(query, fd, tm); - internal::snap_location_to_border(query_location, tolerance); // @tmp keep or not ? + query_location = locate_in_face(query, fd, tm, np); + internal::snap_location_to_border(query_location, tm, tolerance); // @tmp keep or not ? is_query_location_in_face = is_in_face(query_location, tm); @@ -1279,15 +1314,15 @@ locate_in_common_face(typename Location_traits::Face_location& kno if(fd != boost::graph_traits::null_face()) { - query_location = locate_in_face(query, fd, tm); - internal::snap_location_to_border(query_location, tolerance); // @tmp keep or not ? + query_location = locate_in_face(query, fd, tm, np); + internal::snap_location_to_border(query_location, tm, tolerance); // @tmp keep or not ? is_query_location_in_face = is_in_face(query_location, tm); } if(!is_query_location_in_face) { fd = face(opposite(hd, tm), tm); - query_location = locate_in_face(query, fd, tm); + query_location = locate_in_face(query, fd, tm, np); is_query_location_in_face = is_in_face(query_location, tm); } } @@ -1297,8 +1332,8 @@ locate_in_common_face(typename Location_traits::Face_location& kno CGAL_precondition(fd != boost::graph_traits::null_face()); - query_location = locate_in_face(query, fd, tm); - internal::snap_location_to_border(query_location, tolerance); // @tmp keep or not ? + query_location = locate_in_face(query, fd, tm, np); + internal::snap_location_to_border(query_location, tm, tolerance); // @tmp keep or not ? is_query_location_in_face = is_in_face(query_location, tm); } @@ -1311,10 +1346,12 @@ locate_in_common_face(typename Location_traits::Face_location& kno // Finding a common face to two locations // - both locations must be known but can change -template +template bool -locate_in_common_face(typename Location_traits::Face_location& first_location, - typename Location_traits::Face_location& second_location, +locate_in_common_face(std::pair::face_descriptor, + std::array >& first_location, + std::pair::face_descriptor, + std::array >& second_location, const TriangleMesh& tm) { typedef typename boost::graph_traits::face_descriptor face_descriptor; @@ -1380,38 +1417,38 @@ locate_in_common_face(typename Location_traits::Face_location& fir namespace internal { -template::value> +template ::value> struct Point_to_Point_3 // 2D case { - typedef typename Location_traits::Geom_traits::Point_3 Point_3; + typedef typename GetGeomTraits::type::Point_3 Point_3; Point_3 operator()(const Point& p) const { return Point_3(p.x(), p.y(), 0); } }; -template +template struct Point_to_Point_3::Geom_traits::Point_3, + typename GetGeomTraits::type::Point_3, 3> // 3D case with nothing to do { - typedef typename Location_traits::Geom_traits::Point_3 Point_3; + typedef typename GetGeomTraits::type::Point_3 Point_3; const Point_3& operator()(const Point_3& p) const { return p; } }; -template +template struct Point_to_Point_3 // Generic 3D case { - typedef typename Location_traits::Geom_traits::Point_3 Point_3; + typedef typename GetGeomTraits::type::Point_3 Point_3; Point_3 operator()(const Point& p) const { return Point_3(p.x(), p.y(), p.z()); } }; -template +template struct Ray_to_Ray_3 // 2D case { - typedef typename Location_traits::Geom_traits Geom_traits; + typedef typename GetGeomTraits::type Geom_traits; typedef typename Geom_traits::Ray_2 Ray_2; typedef typename Geom_traits::Ray_3 Ray_3; typedef Point_to_Point_3 P2_to_P3; @@ -1426,9 +1463,9 @@ struct Ray_to_Ray_3 // 2D case }; // Readable property map that converts the output of a given vertex point map to a 3D point -template::const_type> +template ::const_type> struct Point_to_Point_3_VPM { private: @@ -1511,7 +1548,7 @@ void build_AABB_tree(const TriangleMesh& tm, /// to call location functions on more than a single point (or ray) should first compute an AABB /// tree to store it (otherwise, it will be recomputed every time). Note that since the AABB tree /// class is a 3D structure, it might be required to wrap your point property map to convert your -/// point type to the 3D point type (i.e., your kernel's `%Point_3`) if you are working +/// point type to the 3D point type (i.e., your traits' `%Point_3`) if you are working /// with a 2D triangle structure. /// /// @{ @@ -1527,7 +1564,7 @@ void build_AABB_tree(const TriangleMesh& tm, /// /// \tparam TriangleMesh a model of `FaceListGraph` /// \tparam Point3VPM a class model of `ReadablePropertyMap` with `boost::graph_traits::%vertex_descriptor` -/// as key type and the \cgal 3D point type (your kernel's `%Point_3`) as value type. +/// as key type and the \cgal 3D point type (your traits' `%Point_3`) as value type. /// \tparam NamedParameters a sequence of \ref pmp_namedparameters "Named Parameters" /// /// \param tm a triangulated surface mesh @@ -1540,18 +1577,28 @@ void build_AABB_tree(const TriangleMesh& tm, /// If this parameter is omitted, an internal property map for /// `boost::vertex_point_t` must be available in `TriangleMesh`. /// \cgalParamEnd +/// \cgalParamBegin{geom_traits} +/// a geometric traits class instance, model of `Kernel` compatible with the point type held +/// in the vertex point property map (either user-provided or internal to the mesh). +/// Must be identical to the traits used in the template parameter of the `AABB_traits`. +/// \cgalParamEnd /// \cgalNamedParamsEnd /// template -void build_AABB_tree(const TriangleMesh& tm, - AABB_tree< - CGAL::AABB_traits< - typename Location_traits::Geom_traits, - CGAL::AABB_face_graph_triangle_primitive - > >& outTree, - const NamedParameters& np) +void +build_AABB_tree(const TriangleMesh& tm, + AABB_tree< + AABB_traits< +#ifdef DOXYGEN_RUNNING + Geom_traits, +#else + typename GetGeomTraits::type, +#endif + CGAL::AABB_face_graph_triangle_primitive > >& outTree, + const NamedParameters& np) { typedef typename GetVertexPointMap::const_type VertexPointMap; + using parameters::get_parameter; using parameters::choose_parameter; @@ -1563,8 +1610,7 @@ void build_AABB_tree(const TriangleMesh& tm, #ifndef DOXYGEN_RUNNING template -void build_AABB_tree(const TriangleMesh& tm, - AABB_tree& outTree) +void build_AABB_tree(const TriangleMesh& tm, AABB_tree& outTree) { return build_AABB_tree(tm, outTree, parameters::all_default()); } @@ -1580,7 +1626,7 @@ void build_AABB_tree(const TriangleMesh& tm, /// /// \tparam TriangleMesh a model of `FaceListGraph` /// \tparam Point3VPM a class model of `ReadablePropertyMap` with `boost::graph_traits::%vertex_descriptor` -/// as key type and the \cgal 3D point type (your kernel's `%Point_3`) as value type. +/// as key type and the \cgal 3D point type (your traits' `%Point_3`) as value type. /// \tparam NamedParameters a sequence of \ref pmp_namedparameters "Named Parameters" /// /// \param p the point to locate on the input triangulated surface mesh @@ -1595,9 +1641,11 @@ void build_AABB_tree(const TriangleMesh& tm, /// `boost::vertex_point_t` must be available in `TriangleMesh`. /// \cgalParamEnd /// \cgalParamBegin{geom_traits} -/// a geometric traits class instance, model of `Kernel`. +/// a geometric traits class instance, model of `Kernel` compatible with the point type held +/// in the vertex point property map (either user-provided or internal to the mesh). +/// Must be identical to the traits used in the template parameter of the `AABB_traits`. /// \cgalParamEnd -/// \cgalParamBegin{snapping_tolerance} +/// \cgalParamBegin{snapping_tolerance} /// a tolerance value used to snap barycentric coordinates. Depending on the geometric traits used, /// the computation of the barycentric coordinates might be an inexact construction, thus leading /// to sometimes surprising values (e.g. a triplet `[0.5, 0.5, -1-e17]` for a point at the middle @@ -1606,36 +1654,47 @@ void build_AABB_tree(const TriangleMesh& tm, /// \cgalParamEnd /// \cgalNamedParamsEnd /// +/// \returns a face location. The type `FT` is deduced from the geometric traits, either provided by +/// the user via named parameters (with `geom_traits`) or using `CGAL::Kernel_traits` +/// and the point type of the vertex point property map in use. +/// template -typename Location_traits::Face_location -locate_with_AABB_tree(const typename Location_traits::Point& p, - const AABB_tree< - CGAL::AABB_traits< - typename Location_traits::Geom_traits, - CGAL::AABB_face_graph_triangle_primitive - > >& tree, +#ifdef DOXYGEN_RUNNING +Face_location +locate_with_AABB_tree(const Point& p, + const AABB_tree > >& tree, +#else +typename internal::Location_traits::Face_location +locate_with_AABB_tree(const typename internal::Location_traits::Point& p, + const AABB_tree::type, + CGAL::AABB_face_graph_triangle_primitive > >& tree, +#endif const TriangleMesh& tm, const NamedParameters& np) { - typedef typename Location_traits::Point Point; - typedef internal::Point_to_Point_3 P_to_P3; - typedef typename boost::property_traits::value_type Point_3; + typedef typename internal::Location_traits::Point Point; + typedef internal::Point_to_Point_3 P_to_P3; + typedef typename boost::property_traits::value_type Point_3; CGAL_static_assertion((std::is_same::value)); - typedef typename Location_traits::Geom_traits Geom_traits; - typedef typename CGAL::AABB_face_graph_triangle_primitive Primitive; - typedef typename CGAL::AABB_traits AABB_traits; + typedef typename GetGeomTraits::type Geom_traits; + typedef typename CGAL::AABB_face_graph_triangle_primitive Primitive; + typedef typename CGAL::AABB_traits AABB_traits; - typedef typename GetVertexPointMap::const_type VertexPointMap; - typedef internal::Point_to_Point_3_VPM WrappedVPM; + typedef typename GetVertexPointMap::const_type VertexPointMap; + typedef internal::Point_to_Point_3_VPM WrappedVPM; const Point_3& p3 = P_to_P3()(p); typename AABB_tree::Point_and_primitive_id result = tree.closest_point_and_primitive(p3); + typedef typename GetGeomTraits::type Geom_traits; + using parameters::get_parameter; using parameters::choose_parameter; - // The VPM might return a point of any dimension, but the AABB tree necessarily returns + // The VPM might return a point of any dimension, but the AABB tree necl1671essarily returns // a Point_3. So, wrap the VPM (again) to give a Point_3. Even if it's already wrapped, we're just // forwarding a const& anyway. const VertexPointMap vpm = parameters::choose_parameter(parameters::get_parameter(np, internal_np::vertex_point), @@ -1647,8 +1706,8 @@ locate_with_AABB_tree(const typename Location_traits -typename Location_traits::Face_location -locate_with_AABB_tree(const typename Location_traits::Point& p, +typename internal::Location_traits::Face_location +locate_with_AABB_tree(const typename internal::Location_traits::Point& p, const AABB_tree& tree, const TriangleMesh& tm) { @@ -1678,7 +1737,8 @@ locate_with_AABB_tree(const typename Location_traits::Point& p, /// `boost::vertex_point_t` must be available in `TriangleMesh`. /// \cgalParamEnd /// \cgalParamBegin{geom_traits} -/// a geometric traits class instance, model of `Kernel`. +/// a geometric traits class instance, model of `Kernel` compatible with the point type held +/// in the vertex point property map (either user-provided or internal to the mesh). /// \cgalParamEnd /// \cgalParamBegin{snapping_tolerance} /// a tolerance value used to snap barycentric coordinates. Depending on the geometric traits used, @@ -1690,24 +1750,29 @@ locate_with_AABB_tree(const typename Location_traits::Point& p, /// \cgalNamedParamsEnd /// template -typename Location_traits::Face_location -locate(const typename Location_traits::Point& p, +#ifdef DOXYGEN_RUNNING +Face_location +locate(const Point& p, +#else +typename internal::Location_traits::Face_location +locate(const typename internal::Location_traits::Point& p, +#endif const TriangleMesh& tm, const NamedParameters& np) { // Wrap the input VPM with a one converting to 3D (costs nothing if the input VPM // already has value type Kernel::Point_3) - typedef typename GetVertexPointMap::const_type VertexPointMap; - typedef internal::Point_to_Point_3_VPM WrappedVPM; - typedef typename Location_traits::Point Intrinsic_point; + typedef typename GetVertexPointMap::const_type VertexPointMap; + typedef internal::Point_to_Point_3_VPM WrappedVPM; + typedef typename internal::Location_traits::Point Intrinsic_point; - typedef AABB_face_graph_triangle_primitive AABB_face_graph_primitive; - typedef CGAL::AABB_traits< - typename Location_traits::Geom_traits, - AABB_face_graph_primitive> AABB_face_graph_traits; + typedef typename GetGeomTraits::type Geom_traits; - typedef internal::Point_to_Point_3 P_to_P3; - typedef typename AABB_face_graph_traits::Point_3 Point_3; + typedef AABB_face_graph_triangle_primitive AABB_face_graph_primitive; + typedef CGAL::AABB_traits AABB_face_graph_traits; + + typedef internal::Point_to_Point_3 P_to_P3; + typedef typename AABB_face_graph_traits::Point_3 Point_3; using parameters::get_parameter; using parameters::choose_parameter; @@ -1727,7 +1792,7 @@ locate(const typename Location_traits::Point& p, #ifndef DOXYGEN_RUNNING template -typename Location_traits::Face_location +typename internal::Location_traits::Face_location locate(const typename property_map_value::type& p, const TriangleMesh& tm) { @@ -1743,7 +1808,7 @@ locate(const typename property_map_value::t /// /// \tparam TriangleMesh a model of `FaceListGraph`. /// \tparam Point3VPM a class model of `ReadablePropertyMap` with `boost::graph_traits::%vertex_descriptor` -/// as key type and the \cgal 3D point type (your kernel's `%Point_3`) as value type. +/// as key type and the \cgal 3D point type (your traits' `%Point_3`) as value type. /// \tparam NamedParameters a sequence of \ref pmp_namedparameters "Named Parameters" /// /// \param ray a ray to intersect with the input triangulated surface mesh @@ -1758,7 +1823,9 @@ locate(const typename property_map_value::t /// `boost::vertex_point_t` must be available in `TriangleMesh`. /// \cgalParamEnd /// \cgalParamBegin{geom_traits} -/// a geometric traits class instance, model of `Kernel`. +/// a geometric traits class instance, model of `Kernel` compatible with the point type held +/// in the vertex point property map (either user-provided or internal to the mesh). +/// Must be identical to the traits used in the template parameter of the `AABB_traits`. /// \cgalParamEnd /// \cgalParamBegin{snapping_tolerance} /// a tolerance value used to snap barycentric coordinates. Depending on the geometric traits used, @@ -1769,34 +1836,42 @@ locate(const typename property_map_value::t /// \cgalParamEnd /// \cgalNamedParamsEnd /// +/// \pre `ray` is an object with the same ambient dimension as the point type (the value type of the vertex point map). +/// template -typename Location_traits::Face_location -locate_with_AABB_tree(const typename Location_traits::Ray& ray, +#ifdef DOXYGEN_RUNNING +Face_location +locate_with_AABB_tree(const Ray& ray, + const AABB_tree > >& tree, +#else +typename internal::Location_traits::Face_location +locate_with_AABB_tree(const typename internal::Location_traits::Ray& ray, const AABB_tree< CGAL::AABB_traits< - typename Location_traits::Geom_traits, + typename GetGeomTraits::type, CGAL::AABB_face_graph_triangle_primitive > >& tree, +#endif const TriangleMesh& tm, const NamedParameters& np) { - typedef typename Location_traits::Geom_traits Geom_traits; + typedef typename GetGeomTraits::type Geom_traits; - typedef typename Geom_traits::FT FT; - typedef typename Geom_traits::Point_3 Point_3; - typedef typename Geom_traits::Ray_3 Ray_3; + typedef typename Geom_traits::FT FT; + typedef typename Geom_traits::Point_3 Point_3; + typedef typename Geom_traits::Ray_3 Ray_3; - typedef typename boost::graph_traits::face_descriptor face_descriptor; + typedef typename boost::graph_traits::face_descriptor face_descriptor; - typedef typename GetVertexPointMap::const_type VertexPointMap; - typedef internal::Point_to_Point_3_VPM WrappedVPM; - typedef internal::Ray_to_Ray_3 R_to_R3; + typedef typename GetVertexPointMap::const_type VertexPointMap; + typedef internal::Point_to_Point_3_VPM WrappedVPM; + typedef internal::Ray_to_Ray_3 R_to_R3; - typedef typename CGAL::AABB_face_graph_triangle_primitive Primitive; - typedef typename CGAL::AABB_traits AABB_traits; - typedef AABB_tree AABB_face_graph_tree; + typedef typename CGAL::AABB_face_graph_triangle_primitive Primitive; + typedef typename CGAL::AABB_traits AABB_traits; + typedef AABB_tree AABB_face_graph_tree; typedef typename AABB_face_graph_tree::template Intersection_and_primitive_id::Type Intersection_type; - typedef boost::optional Ray_intersection; + typedef boost::optional Ray_intersection; using parameters::get_parameter; using parameters::choose_parameter; @@ -1849,8 +1924,8 @@ locate_with_AABB_tree(const typename Location_traits -typename Location_traits::Face_location -locate_with_AABB_tree(const typename Location_traits::Ray& ray, +typename internal::Location_traits::Face_location +locate_with_AABB_tree(const typename internal::Location_traits::Ray& ray, const AABB_tree& tree, const TriangleMesh& tm) { @@ -1883,9 +1958,10 @@ locate_with_AABB_tree(const typename Location_traits::Ray& ray, /// `boost::vertex_point_t` must be available in `TriangleMesh`. /// \cgalParamEnd /// \cgalParamBegin{geom_traits} -/// a geometric traits class instance, model of `Kernel`. +/// a geometric traits class instance, model of `Kernel` compatible with the point type held +/// in the vertex point property map (either user-provided or internal to the mesh). /// \cgalParamEnd -/// \cgalParamBegin{snapping_tolerance} +/// \cgalParamBegin{snapping_tolerance} /// a tolerance value used to snap barycentric coordinates. Depending on the geometric traits used, /// the computation of the barycentric coordinates might be an inexact construction, thus leading /// to sometimes surprising values (e.g. a triplet `[0.5, 0.5, -1-e17]` for a point at the middle @@ -1894,9 +1970,16 @@ locate_with_AABB_tree(const typename Location_traits::Ray& ray, /// \cgalParamEnd /// \cgalNamedParamsEnd /// +/// \pre `ray` is an object with the same ambient dimension as the point type (the value type of the vertex point map). +/// template -typename Location_traits::Face_location -locate(const typename Location_traits::Ray& ray, +#ifdef DOXYGEN_RUNNING +Face_location +locate(const Ray& ray, +#else +typename internal::Location_traits::Face_location +locate(const typename internal::Location_traits::Ray& ray, +#endif const TriangleMesh& tm, const NamedParameters& np) { @@ -1906,9 +1989,10 @@ locate(const typename Location_traits::Ray& ray, // already has value type Geom_traits::Point_3) typedef internal::Point_to_Point_3_VPM VPM; + typedef typename GetGeomTraits::type Geom_traits; + typedef AABB_face_graph_triangle_primitive AABB_face_graph_primitive; - typedef CGAL::AABB_traits::Geom_traits, - AABB_face_graph_primitive> AABB_face_graph_traits; + typedef CGAL::AABB_traits AABB_face_graph_traits; using parameters::get_parameter; using parameters::choose_parameter; @@ -1924,9 +2008,9 @@ locate(const typename Location_traits::Ray& ray, #ifndef DOXYGEN_RUNNING template -typename Location_traits::Face_location +typename internal::Location_traits::Face_location locate(const typename internal::Ray_type_selector< - typename Location_traits::Point>::type& ray, + typename internal::Location_traits::Point>::type& ray, const TriangleMesh& tm) { return locate(ray, tm, parameters::all_default()); From 413d4986bcc8e73da58d2e44f55cde71bfafc368 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mael=20Rouxel-Labb=C3=A9?= Date: Tue, 8 Oct 2019 15:42:27 +0200 Subject: [PATCH 188/363] Add an example showing the usage of PMP::Locate --- .../Polygon_mesh_processing.txt | 2 + .../doc/Polygon_mesh_processing/examples.txt | 1 + .../Polygon_mesh_processing/CMakeLists.txt | 1 + .../locate_example.cpp | 113 ++++++++++++++++++ 4 files changed, 117 insertions(+) create mode 100644 Polygon_mesh_processing/examples/Polygon_mesh_processing/locate_example.cpp diff --git a/Polygon_mesh_processing/doc/Polygon_mesh_processing/Polygon_mesh_processing.txt b/Polygon_mesh_processing/doc/Polygon_mesh_processing/Polygon_mesh_processing.txt index 3cf3d142e12..e3c97c7e1f7 100644 --- a/Polygon_mesh_processing/doc/Polygon_mesh_processing/Polygon_mesh_processing.txt +++ b/Polygon_mesh_processing/doc/Polygon_mesh_processing/Polygon_mesh_processing.txt @@ -535,6 +535,8 @@ finding the nearest point on a mesh given a point or a ray (`CGAL::Polygon_mesh_processing::locate_with_AABB_tree()`, and similar), and location-based predicates (for example, `CGAL::Polygon_mesh_processing::is_on_face_border()`). +The example \ref Polygon_mesh_processing/locate_example.cpp presents a few of these functions. + **************************************** \section PMPOrientation Orientation diff --git a/Polygon_mesh_processing/doc/Polygon_mesh_processing/examples.txt b/Polygon_mesh_processing/doc/Polygon_mesh_processing/examples.txt index 4165c6bf51b..a9350578648 100644 --- a/Polygon_mesh_processing/doc/Polygon_mesh_processing/examples.txt +++ b/Polygon_mesh_processing/doc/Polygon_mesh_processing/examples.txt @@ -25,4 +25,5 @@ \example Polygon_mesh_processing/repair_polygon_soup_example.cpp \example Polygon_mesh_processing/mesh_smoothing_example.cpp \example Polygon_mesh_processing/shape_smoothing_example.cpp +\example Polygon_mesh_processing/locate_example.cpp */ diff --git a/Polygon_mesh_processing/examples/Polygon_mesh_processing/CMakeLists.txt b/Polygon_mesh_processing/examples/Polygon_mesh_processing/CMakeLists.txt index 88701b9e196..95a539040ac 100644 --- a/Polygon_mesh_processing/examples/Polygon_mesh_processing/CMakeLists.txt +++ b/Polygon_mesh_processing/examples/Polygon_mesh_processing/CMakeLists.txt @@ -85,6 +85,7 @@ create_single_source_cgal_program( "detect_features_example.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") if(OpenMesh_FOUND) create_single_source_cgal_program( "compute_normals_example_OM.cpp" ) diff --git a/Polygon_mesh_processing/examples/Polygon_mesh_processing/locate_example.cpp b/Polygon_mesh_processing/examples/Polygon_mesh_processing/locate_example.cpp new file mode 100644 index 00000000000..2235be77dfd --- /dev/null +++ b/Polygon_mesh_processing/examples/Polygon_mesh_processing/locate_example.cpp @@ -0,0 +1,113 @@ +#include + +#include + +#include +#include +#include +#include +#include +#include +#include + +typedef CGAL::Exact_predicates_inexact_constructions_kernel K; +typedef K::FT FT; +typedef K::Point_2 Point_2; +typedef K::Ray_2 Ray_2; +typedef K::Point_3 Point_3; +typedef K::Ray_3 Ray_3; + +typedef CGAL::Surface_mesh Mesh; +typedef typename boost::graph_traits::vertex_descriptor vertex_descriptor; +typedef typename boost::graph_traits::face_descriptor face_descriptor; + +namespace CP = CGAL::parameters; +namespace PMP = CGAL::Polygon_mesh_processing; + +typedef PMP::Barycentric_coordinates Barycentric_coordinates; +typedef PMP::Face_location Face_location; + +int main(int /*argc*/, char** /*argv*/) +{ + // Generate a simple 3D triangle mesh that with vertices on the plane xOy + Mesh tm; + CGAL::make_grid(10, 10, tm); + PMP::triangulate_faces(tm); + + // Basic usage + Face_location random_location = PMP::random_location_on_mesh(tm); + const face_descriptor f = random_location.first; + const Barycentric_coordinates& coordinates = random_location.second; + + std::cout << "Random location on the mesh: face " << f + << " and with coordinates [" << coordinates[0] << "; " + << coordinates[1] << "; " + << coordinates[2] << "]\n"; + std::cout << "It corresponds to point (" << PMP::construct_point(random_location, tm) << ")\n\n"; + + // Locate a known 3D point in the mesh + const Point_3 query(1.2, 7.4, 0); + Face_location query_location = PMP::locate(query, tm); + + std::cout << "Point (" << query << ") is located in face " << query_location.first + << " with barycentric coordinates [" << query_location.second[0] << "; " + << query_location.second[1] << "; " + << query_location.second[2] << "]\n\n"; + + // Locate a 3D point in the mesh as the intersection of the mesh and a 3D ray. + // The AABB tree can be cached in case many queries are performed (otherwise, it is rebuilt + // on each call, which is expensive). + typedef CGAL::AABB_face_graph_triangle_primitive AABB_face_graph_primitive; + typedef CGAL::AABB_traits AABB_face_graph_traits; + + CGAL::AABB_tree tree; + PMP::build_AABB_tree(tm, tree); + + const Ray_3 ray_3(Point_3(4.2, 6.8, 2.4), Point_3(7.2, 2.3, -5.8)); + Face_location ray_location = PMP::locate_with_AABB_tree(ray_3, tree, tm); + + std::cout << "Intersection of the 3D ray and the mesh is in face " << ray_location.first + << " with barycentric coordinates [" << ray_location.second[0] << " " + << ray_location.second[1] << " " + << ray_location.second[2] << "]\n"; + std::cout << "It corresponds to point (" << PMP::construct_point(ray_location, tm) << ")\n"; + std::cout << "Is it on the face's border? " << (PMP::is_on_face_border(ray_location, tm) ? "Yes" : "No") << "\n\n"; + + // ----------------------------------------------------------------------------------------------- + // Now, we artifically project the mesh to the natural 2D dimensional plane, with a little translation + // via a custom vertex point property map + + typedef CGAL::dynamic_vertex_property_t Point_2_property; + typedef typename boost::property_map::type Projection_pmap; + Projection_pmap projection_pmap = get(Point_2_property(), tm); + + for(vertex_descriptor v : vertices(tm)) + { + const Point_3& p = tm.point(v); + put(projection_pmap, v, Point_2(p.x() + 1, p.y())); // simply ignoring the z==0 coordinate and translating along Ox + } + + // Locate the same 3D point but in a 2D context + const Point_2 query_2(query.x() + 1, query.y()); + Face_location query_location_2 = PMP::locate(query_2, tm, CP::vertex_point_map(projection_pmap)); + + std::cout << "Point (" << query_2 << ") is located in face " << query_location_2.first + << " with barycentric coordinates [" << query_location_2.second[0] << "; " + << query_location_2.second[1] << "; " + << query_location_2.second[2] << "]\n\n"; + + // Shoot a 2D ray and locate the intersection with the mesh in 2D + const Ray_2 ray_2(Point_2(-10, -10), Point_2(10, 10)); + Face_location ray_location_2 = PMP::locate(ray_2, tm, CP::vertex_point_map(projection_pmap)); // This rebuilds an AABB tree on each call + + std::cout << "Intersection of the 2D ray and the mesh is in face " << ray_location_2.first + << " with barycentric coordinates [" << ray_location_2.second[0] << "; " + << ray_location_2.second[1] << "; " + << ray_location_2.second[2] << "]\n"; + std::cout << "It corresponds to point (" << PMP::construct_point(ray_location_2, tm, CP::vertex_point_map(projection_pmap)) << ")\n"; + + if(PMP::is_on_mesh_border(ray_location_2, tm)) + std::cout << "It is on the border of the mesh!\n" << std::endl; + + return EXIT_SUCCESS; +} From 22092a357aa69b78466f3756ff60d0039071630b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mael=20Rouxel-Labb=C3=A9?= Date: Tue, 8 Oct 2019 15:42:41 +0200 Subject: [PATCH 189/363] Update tests of PMP::Locate (and fix some VPM usages) --- .../test_pmp_locate.cpp | 383 ++++++++++-------- 1 file changed, 213 insertions(+), 170 deletions(-) diff --git a/Polygon_mesh_processing/test/Polygon_mesh_processing/test_pmp_locate.cpp b/Polygon_mesh_processing/test/Polygon_mesh_processing/test_pmp_locate.cpp index 5b704de13bb..03e74b71eec 100644 --- a/Polygon_mesh_processing/test/Polygon_mesh_processing/test_pmp_locate.cpp +++ b/Polygon_mesh_processing/test/Polygon_mesh_processing/test_pmp_locate.cpp @@ -42,6 +42,7 @@ namespace PMP = CGAL::Polygon_mesh_processing; typedef CGAL::Exact_predicates_inexact_constructions_kernel EPICK; typedef CGAL::Exact_predicates_exact_constructions_kernel EPECK; + typedef CGAL::Simple_cartesian::Type> Exact_kernel; template @@ -96,32 +97,31 @@ bool is_equal(const FT& a, const FT& b) return (a == b); } -template +template void test_snappers(const G& g) { std::cout << " test snappers..." << std::endl; - typedef typename PMP::Location_traits::FT FT; + typedef typename K::FT FT; - typename PMP::Location_traits::Barycentric_coordinates coords = CGAL::make_array(FT(1e-6), FT(0.9999999999999999999), FT(1e-7)); - typename PMP::Location_traits::Face_location loc = std::make_pair(*(faces(g).first), coords); + PMP::Barycentric_coordinates coords = CGAL::make_array(FT(1e-6), FT(0.9999999999999999999), FT(1e-7)); + PMP::Face_location loc = std::make_pair(*(faces(g).first), coords); // --------------------------------------------------------------------------- - PMP::internal::snap_coordinates_to_border(coords); // uses numeric_limits' epsilon() + PMP::internal::snap_coordinates_to_border(coords); // uses numeric_limits' epsilon() assert(coords[0] == FT(1e-6) && coords[1] == FT(1) && coords[2] == FT(1e-7)); - PMP::internal::snap_coordinates_to_border(coords, 1e-5); + PMP::internal::snap_coordinates_to_border(coords, FT(1e-5)); assert(coords[0] == FT(0) && coords[1] == FT(1) && coords[2] == FT(0)); // --------------------------------------------------------------------------- - PMP::internal::snap_location_to_border(loc); // uses numeric_limits' epsilon() + PMP::internal::snap_location_to_border(loc, g); // uses numeric_limits' epsilon() assert(!PMP::is_on_face_border(loc, g)); - PMP::internal::snap_location_to_border(loc, 1e-7); + PMP::internal::snap_location_to_border(loc, g, FT(1e-7)); assert(PMP::is_on_face_border(loc, g)); } - template struct Point_to_bare_point { @@ -134,49 +134,48 @@ struct Point_to_bare_point typedef typename K::Point_3 type; }; -template -void test_constructions(const G& g, CGAL::Random& rnd) +template +void test_constructions(const G& g, + const VPM vpm, + CGAL::Random& rnd) { std::cout << " test constructions..." << std::endl; 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; - typedef typename PMP::Location_traits::descriptor_variant descriptor_variant; + typedef typename PMP::descriptor_variant descriptor_variant; - typedef typename boost::property_map_value::type Point; - typedef typename CGAL::Kernel_traits::type Kernel; - typedef typename Kernel::FT FT; - typedef typename Point_to_bare_point::type Bare_point; + typedef typename boost::property_traits::value_type Point; + typedef typename boost::property_traits::reference Point_reference; + typedef typename K::FT FT; + typedef typename Point_to_bare_point::type Bare_point; - typedef typename PMP::Location_traits::Barycentric_coordinates Barycentric_coordinates; - typedef typename PMP::Location_traits::Face_location Face_location; - - typedef typename boost::property_map::const_type VPM; - VPM vpm = CGAL::get_const_property_map(boost::vertex_point, g); + typedef typename PMP::Barycentric_coordinates Barycentric_coordinates; + typedef typename PMP::Face_location Face_location; face_descriptor f = CGAL::internal::random_face_in_mesh(g, rnd); halfedge_descriptor h = halfedge(f, g); vertex_descriptor v = source(h, g); - Point p = get(vpm, v); - Point q = get(vpm, target(h, g)); - Point r = get(vpm, target(next(h, g), g)); + Point_reference p = get(vpm, v); + Point_reference q = get(vpm, target(h, g)); + Point_reference r = get(vpm, target(next(h, g), g)); - Bare_point bp(p); - Bare_point bq(q); - Bare_point br(r); + const Bare_point bp(p); + const Bare_point bq(q); + const Bare_point br(r); Barycentric_coordinates bar; Face_location loc; loc.first = f; // --------------------------------------------------------------------------- - bar = PMP::barycentric_coordinates(p, q, r, p, Kernel()); + bar = PMP::barycentric_coordinates(p, q, r, p, K()); assert(is_equal(bar[0], FT(1)) && is_equal(bar[1], FT(0)) && is_equal(bar[2], FT(0))); - bar = PMP::barycentric_coordinates(p, q, r, q, Kernel()); + bar = PMP::barycentric_coordinates(p, q, r, q, K()); assert(is_equal(bar[0], FT(0)) && is_equal(bar[1], FT(1)) && is_equal(bar[2], FT(0))); - bar = PMP::barycentric_coordinates(p, q, r, r, Kernel()); + bar = PMP::barycentric_coordinates(p, q, r, r, K()); assert(is_equal(bar[0], FT(0)) && is_equal(bar[1], FT(0)) && is_equal(bar[2], FT(1))); Point mp = Point(CGAL::midpoint(bp, bq)); @@ -190,12 +189,18 @@ void test_constructions(const G& g, CGAL::Random& rnd) const FT b = rnd.get_double(-1., 1.); const FT c = 1. - a - b; + // Point to location and inversely Bare_point barycentric_pt = CGAL::barycenter(bp, a, bq, b, br, c); bar = PMP::barycentric_coordinates(p, q, r, Point(barycentric_pt)); assert(is_equal(bar[0], a) && is_equal(bar[1], b) && is_equal(bar[2], c)); loc.second = bar; - const FT sq_dist = CGAL::squared_distance(barycentric_pt, Bare_point(PMP::construct_point(loc, g))); + const Bare_point barycentric_pt_2 = + Bare_point(PMP::construct_point(loc, g, + CGAL::parameters::vertex_point_map(vpm) + .geom_traits(K()))); + + const FT sq_dist = CGAL::squared_distance(barycentric_pt, barycentric_pt_2); assert(is_equal(sq_dist, FT(0))); } @@ -216,13 +221,12 @@ void test_constructions(const G& g, CGAL::Random& rnd) if(const vertex_descriptor* v = boost::get(&dv)) { } else { assert(false); } // --------------------------------------------------------------------------- - - Point s = PMP::construct_point(loc, g, CGAL::parameters::all_default()); - s = PMP::construct_point(loc, g); - assert(s == get(vpm, source(halfedge(f, g), g))); + // just to check the API + PMP::construct_point(loc, g); + PMP::construct_point(loc, g, CGAL::parameters::all_default()); } -template +template void test_random_entities(const G& g, CGAL::Random& rnd) { std::cout << " test random entities..." << std::endl; @@ -230,11 +234,8 @@ void test_random_entities(const G& g, CGAL::Random& rnd) typedef typename boost::graph_traits::halfedge_descriptor halfedge_descriptor; typedef typename boost::graph_traits::face_descriptor face_descriptor; - typedef typename PMP::Location_traits::Face_location Face_location; - - typedef typename boost::property_map_value::type Point; - typedef typename CGAL::Kernel_traits::type Kernel; - typedef typename Kernel::FT FT; + typedef typename K::FT FT; + typedef typename PMP::Face_location Face_location; // --------------------------------------------------------------------------- Face_location loc; @@ -247,19 +248,19 @@ void test_random_entities(const G& g, CGAL::Random& rnd) int nn = 100; while(nn --> 0) // the infamous 'go to zero' operator { - loc = PMP::random_location_on_mesh(g, rnd); + loc = PMP::random_location_on_mesh(g, rnd); assert(loc.first != boost::graph_traits::null_face()); assert(loc.second[0] >= FT(0) && loc.second[0] <= FT(1) && loc.second[1] >= FT(0) && loc.second[1] <= FT(1) && loc.second[2] >= FT(0) && loc.second[2] <= FT(1)); - loc = PMP::random_location_on_face(f, g, rnd); + loc = PMP::random_location_on_face(f, g, rnd); assert(loc.first == f); assert(loc.second[0] >= FT(0) && loc.second[0] <= FT(1) && loc.second[1] >= FT(0) && loc.second[1] <= FT(1) && loc.second[2] >= FT(0) && loc.second[2] <= FT(1)); - loc = PMP::random_location_on_halfedge(h, g, rnd); + loc = PMP::random_location_on_halfedge(h, g, rnd); assert(loc.first == face(h, g)); assert(loc.second[0] >= FT(0) && loc.second[0] <= FT(1) && loc.second[1] >= FT(0) && loc.second[1] <= FT(1) && @@ -269,7 +270,7 @@ void test_random_entities(const G& g, CGAL::Random& rnd) } } -template +template void test_helpers(const G& g, CGAL::Random& rnd) { std::cout << " test helpers..." << std::endl; @@ -278,7 +279,8 @@ void test_helpers(const G& g, CGAL::Random& rnd) typedef typename boost::graph_traits::halfedge_descriptor halfedge_descriptor; typedef typename boost::graph_traits::face_descriptor face_descriptor; - typedef typename PMP::Location_traits::Face_location Face_location; + typedef typename K::FT FT; + typedef typename PMP::Face_location Face_location; face_descriptor f = CGAL::internal::random_face_in_mesh(g, rnd); halfedge_descriptor h = halfedge(f, g); @@ -302,31 +304,31 @@ void test_helpers(const G& g, CGAL::Random& rnd) // --------------------------------------------------------------------------- // Incident faces - Face_location loc = PMP::random_location_on_face(f, g, rnd); + Face_location loc = PMP::random_location_on_face(f, g, rnd); std::set s; PMP::internal::incident_faces(loc, g, std::inserter(s, s.begin())); assert(PMP::is_on_face_border(loc, g) || s.size() == 1); - loc = PMP::random_location_on_halfedge(h, g, rnd); + loc = PMP::random_location_on_halfedge(h, g, rnd); std::vector vec; PMP::internal::incident_faces(loc, g, std::back_inserter(vec)); - assert(PMP::is_on_vertex(loc, source(h, g), g) || PMP::is_on_vertex(loc, target(h, g), g) || vec.size() == 2); + assert(PMP::is_on_vertex(loc, source(h, g), g) || + PMP::is_on_vertex(loc, target(h, g), g) || + vec.size() == 2); } -template +template void test_predicates(const G& g, CGAL::Random& rnd) { std::cout << " test predicates..." << std::endl; - typedef typename boost::property_map_value::type Point; - typedef typename CGAL::Kernel_traits::type Kernel; - typedef typename Kernel::FT FT; + typedef typename K::FT FT; 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; - typedef typename PMP::Location_traits::Face_location Face_location; + typedef typename PMP::Face_location Face_location; face_descriptor f = CGAL::internal::random_face_in_mesh(g, rnd); halfedge_descriptor h = halfedge(f, g); @@ -334,39 +336,39 @@ void test_predicates(const G& g, CGAL::Random& rnd) // --------------------------------------------------------------------------- Face_location loc(f, CGAL::make_array(FT(1), FT(0), FT(0))); - assert(PMP::is_on_vertex(loc, v, g)); + assert(PMP::is_on_vertex(loc, v, g)); loc = Face_location(f, CGAL::make_array(FT(0), FT(1), FT(0))); - assert(PMP::is_on_vertex(loc, target(h, g), g)); + assert(PMP::is_on_vertex(loc, target(h, g), g)); loc = Face_location(f, CGAL::make_array(FT(0), FT(0), FT(1))); - assert(PMP::is_on_vertex(loc, target(next(h, g), g), g)); + assert(PMP::is_on_vertex(loc, target(next(h, g), g), g)); loc = Face_location(f, CGAL::make_array(FT(-1), FT(1), FT(1))); - assert(!PMP::is_on_vertex(loc, target(next(h, g), g), g)); + assert(!PMP::is_on_vertex(loc, target(next(h, g), g), g)); // --------------------------------------------------------------------------- loc = Face_location(f, CGAL::make_array(FT(0.5), FT(0.5), FT(0))); - assert(PMP::is_on_halfedge(loc, h, g)); + assert(PMP::is_on_halfedge(loc, h, g)); loc = Face_location(f, CGAL::make_array(FT(0), FT(0.5), FT(0.5))); - assert(PMP::is_on_halfedge(loc, next(h, g), g)); + assert(PMP::is_on_halfedge(loc, next(h, g), g)); loc = Face_location(f, CGAL::make_array(FT(-0.5), FT(1.5), FT(0))); - assert(!PMP::is_on_halfedge(loc, h, g)); + assert(!PMP::is_on_halfedge(loc, h, g)); loc = Face_location(f, CGAL::make_array(FT(0.1), FT(-0.6), FT(1.5))); - assert(!PMP::is_on_halfedge(loc, h, g)); + assert(!PMP::is_on_halfedge(loc, h, g)); // --------------------------------------------------------------------------- loc = Face_location(f, CGAL::make_array(FT(0.3), FT(0.3), FT(0.4))); - assert(PMP::is_in_face(loc, g)); + assert(PMP::is_in_face(loc, g)); loc = Face_location(f, CGAL::make_array(FT(0), FT(0), FT(1))); - assert(PMP::is_in_face(loc, g)); + assert(PMP::is_in_face(loc, g)); loc = Face_location(f, CGAL::make_array(FT(0), FT(2), FT(-1))); - assert(!PMP::is_in_face(loc, g)); + assert(!PMP::is_in_face(loc, g)); // --------------------------------------------------------------------------- loc = Face_location(f, CGAL::make_array(FT(0.3), FT(0.3), FT(0.4))); - assert(!PMP::is_on_face_border(loc, g)); + assert(!PMP::is_on_face_border(loc, g)); loc = Face_location(f, CGAL::make_array(FT(0), FT(0.6), FT(0.4))); - assert(PMP::is_on_face_border(loc, g)); + assert(PMP::is_on_face_border(loc, g)); loc = Face_location(f, CGAL::make_array(FT(0), FT(0), FT(1))); - assert(PMP::is_on_face_border(loc, g)); + assert(PMP::is_on_face_border(loc, g)); loc = Face_location(f, CGAL::make_array(FT(-0.2), FT(0), FT(1.2))); assert(!PMP::is_on_face_border(loc, g)); @@ -388,68 +390,69 @@ void test_predicates(const G& g, CGAL::Random& rnd) loc.second[(id_of_h+1)%3] = FT(0); loc.second[(id_of_h+2)%3] = FT(0); boost::optional opt_hd = CGAL::is_border(source(h, g), g); - assert(PMP::is_on_mesh_border(loc, g) == (opt_hd != boost::none)); + assert(PMP::is_on_mesh_border(loc, g) == (opt_hd != boost::none)); loc.second[id_of_h] = FT(0.5); loc.second[(id_of_h+1)%3] = FT(0.5); - assert(PMP::is_on_mesh_border(loc, g) == CGAL::is_border(edge(h, g), g)); + assert(PMP::is_on_mesh_border(loc, g) == CGAL::is_border(edge(h, g), g)); // Even if the point does lie on the border of the mesh, 'false' is returned because // another face descriptor should be used. loc.second[id_of_h] = -0.5; loc.second[(id_of_h+1)%3] = 1.5; - assert(!PMP::is_on_mesh_border(loc, g)); + assert(!PMP::is_on_mesh_border(loc, g)); if(++counter > max) break; } } -template -void test_locate_in_face(const G& g, CGAL::Random& rnd) +template +void test_locate_in_face(const G& g, + const VPM vpm, + CGAL::Random& rnd) { std::cout << " test locate_in_face()..." << std::endl; - typedef typename boost::property_map_value::type Point; - typedef typename CGAL::Kernel_traits::type Kernel; - typedef typename Kernel::FT FT; + typedef typename boost::property_traits::reference Point_reference; + typedef typename K::FT FT; 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; - typedef typename PMP::Location_traits::Face_location Face_location; - - typedef typename boost::property_map::const_type VertexPointMap; - VertexPointMap vpm = CGAL::get_const_property_map(boost::vertex_point, g); + typedef typename PMP::Face_location Face_location; const face_descriptor f = CGAL::internal::random_face_in_mesh(g, rnd); const halfedge_descriptor h = halfedge(f, g); const vertex_descriptor v = target(h, g); Face_location loc; - typename PMP::Location_traits::FT a = 0.1; - Point p = get(vpm, v); + FT a = 0.1; + Point_reference p = get(vpm, v); - loc = PMP::locate_in_face(v, g); + loc = PMP::locate_vertex(v, g); assert(is_equal(loc.second[CGAL::vertex_index_in_face(v, loc.first, g)], FT(1))); assert(is_equal(loc.second[(CGAL::vertex_index_in_face(v, loc.first, g)+1)%3], FT(0))); assert(is_equal(loc.second[(CGAL::vertex_index_in_face(v, loc.first, g)+2)%3], FT(0))); - loc = PMP::locate_in_face(v, f, g); + loc = PMP::locate_vertex(v, f, g); assert(loc.first == f); assert(is_equal(loc.second[0], FT(0)) && is_equal(loc.second[1], FT(1)) && is_equal(loc.second[2], FT(0))); - loc = PMP::locate_in_face(h, a, g); + loc = PMP::locate_on_halfedge(h, a, g); const int h_id = CGAL::halfedge_index_in_face(h, g); assert(loc.first == f && is_equal(loc.second[(h_id+2)%3], FT(0))); - loc = PMP::locate_in_face(p, f, g, CGAL::parameters::all_default()); + loc = PMP::locate_in_face(p, f, g, CGAL::parameters::vertex_point_map(vpm).geom_traits(K())); int v_id = CGAL::vertex_index_in_face(v, f, g); assert(loc.first == f && is_equal(loc.second[v_id], FT(1))); - loc = PMP::locate_in_face(p, f, g); - v_id = CGAL::vertex_index_in_face(v, f, g); + // Internal vertex point pmap + typedef typename boost::property_map_value::type Point; + + Point p2 = get(CGAL::vertex_point, g, v); + PMP::locate_in_face(p2, f, g); assert(loc.first == f && is_equal(loc.second[v_id], FT(1))); // --------------------------------------------------------------------------- @@ -473,84 +476,82 @@ void test_locate_in_face(const G& g, CGAL::Random& rnd) PMP::locate_in_adjacent_face(loc, neigh_f, g); - assert(PMP::locate_in_common_face(loc, neigh_loc, g)); + assert(PMP::locate_in_common_face(loc, neigh_loc, g)); - assert(PMP::locate_in_common_face(loc, p, neigh_loc, g)); - assert(PMP::locate_in_common_face(loc, p, neigh_loc, g, 1e-7)); + assert(PMP::locate_in_common_face(loc, p, neigh_loc, g, CGAL::parameters::vertex_point_map(vpm).geom_traits(K()))); + assert(PMP::locate_in_common_face(loc, p, neigh_loc, g, CGAL::parameters::vertex_point_map(vpm).geom_traits(K()), 1e-7)); } } -template +template ::value_type>::value> struct Locate_with_AABB_tree_Tester // 2D case { template - void operator()(const G& g, CGAL::Random& rnd) const + void test(const G& g, const VPM vpm, CGAL::Random& rnd) const { std::cout << " test locate_with_AABB_tree (2D)..." << std::endl; - typedef typename boost::property_map_value::type Point; + typedef typename boost::property_traits::reference Point_reference; - typedef typename boost::property_map::const_type VertexPointMap; - - typedef typename CGAL::Kernel_traits::type Kernel; - typedef typename Kernel::FT FT; - typedef typename Kernel::Ray_2 Ray_2; - typedef typename Kernel::Ray_3 Ray_3; - typedef typename Kernel::Point_3 Point_3; + typedef typename K::FT FT; + typedef typename K::Ray_2 Ray_2; + typedef typename K::Ray_3 Ray_3; + typedef typename K::Point_3 Point_3; 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; - typedef typename PMP::Location_traits::Face_location Face_location; + typedef typename PMP::Face_location Face_location; face_descriptor f = CGAL::internal::random_face_in_mesh(g, rnd); halfedge_descriptor h = halfedge(f, g); vertex_descriptor v = target(h, g); // --------------------------------------------------------------------------- - typedef typename boost::property_traits::value_type Intrinsic_point; + typedef typename boost::property_traits::value_type Intrinsic_point; typedef PMP::internal::Point_to_Point_3 Intrinsic_point_to_Point_3; - typedef PMP::internal::Point_to_Point_3_VPM WrappedVertexPointMap; - typedef CGAL::AABB_face_graph_triangle_primitive AABB_face_graph_primitive; - typedef CGAL::AABB_traits AABB_face_graph_traits; + typedef PMP::internal::Point_to_Point_3_VPM WrappedVPM; + typedef CGAL::AABB_face_graph_triangle_primitive AABB_face_graph_primitive; + typedef CGAL::AABB_traits AABB_face_graph_traits; CGAL_static_assertion((std::is_same::value)); Intrinsic_point_to_Point_3 to_p3; CGAL::AABB_tree tree_a; - VertexPointMap vpm_a = CGAL::get_const_property_map(boost::vertex_point, g); - typename boost::property_traits::value_type p_a = get(vpm_a, v); + Point_reference p_a = get(vpm, v); const Point_3& p3_a = to_p3(p_a); CGAL::AABB_tree tree_b; - WrappedVertexPointMap vpm_b(g); + WrappedVPM vpm_b(vpm); // --------------------------------------------------------------------------- - PMP::build_AABB_tree(g, tree_a); - assert(tree_a.size() == num_faces(g)); - + PMP::build_AABB_tree(g, tree_a, CGAL::parameters::vertex_point_map(vpm)); PMP::build_AABB_tree(g, tree_b, CGAL::parameters::vertex_point_map(vpm_b)); assert(tree_b.size() == num_faces(g)); - Face_location loc = PMP::locate_with_AABB_tree(p_a, tree_a, g); + Face_location loc = PMP::locate_with_AABB_tree(p_a, tree_a, g, CGAL::parameters::vertex_point_map(vpm)); // sanitize otherwise some test platforms fail - PMP::internal::snap_location_to_border(loc, 1e-7); + PMP::internal::snap_location_to_border(loc, g, FT(1e-7)); assert(PMP::is_on_vertex(loc, v, g)); // might fail du to precision issues... assert(is_equal(loc.second[CGAL::vertex_index_in_face(v, loc.first, g)], FT(1))); assert(is_equal(loc.second[(CGAL::vertex_index_in_face(v, loc.first, g)+1)%3], FT(0))); assert(is_equal(loc.second[(CGAL::vertex_index_in_face(v, loc.first, g)+2)%3], FT(0))); - assert(is_equal(CGAL::squared_distance(to_p3(PMP::construct_point(loc, g)), p3_a), FT(0))); + assert(is_equal(CGAL::squared_distance(to_p3( + PMP::construct_point(loc, g, CGAL::parameters::vertex_point_map(vpm))), p3_a), FT(0))); - loc = PMP::locate_with_AABB_tree(p_a, tree_a, g, CGAL::parameters::vertex_point_map(vpm_a)); - assert(is_equal(CGAL::squared_distance(to_p3(PMP::construct_point(loc, g)), p3_a), FT(0))); + loc = PMP::locate_with_AABB_tree(p_a, tree_a, g, CGAL::parameters::vertex_point_map(vpm)); + assert(is_equal(CGAL::squared_distance(to_p3( + PMP::construct_point(loc, g, CGAL::parameters::vertex_point_map(vpm))), p3_a), FT(0))); // --------------------------------------------------------------------------- - loc = PMP::locate(p_a, g); - assert(is_equal(CGAL::squared_distance(to_p3(PMP::construct_point(loc, g)), p3_a), FT(0))); + loc = PMP::locate(p_a, g, CGAL::parameters::vertex_point_map(vpm)); + assert(is_equal(CGAL::squared_distance(to_p3( + PMP::construct_point(loc, g, CGAL::parameters::vertex_point_map(vpm))), p3_a), FT(0))); assert(PMP::is_in_face(loc, g)); loc = PMP::locate_with_AABB_tree(CGAL::ORIGIN, tree_b, g, CGAL::parameters::vertex_point_map(vpm_b)); @@ -561,12 +562,13 @@ struct Locate_with_AABB_tree_Tester // 2D case // --------------------------------------------------------------------------- Ray_2 r2 = random_2D_ray >(tree_a, rnd); - loc = PMP::locate_with_AABB_tree(r2, tree_a, g); + loc = PMP::locate_with_AABB_tree(r2, tree_a, g, CGAL::parameters::vertex_point_map(vpm)); if(loc.first != boost::graph_traits::null_face()) assert(PMP::is_in_face(loc, g)); Ray_3 r3 = random_3D_ray >(tree_b, rnd); - loc = PMP::locate_with_AABB_tree(r3, tree_b, g, CGAL::parameters::vertex_point_map(vpm_b)); + loc = PMP::locate_with_AABB_tree(r3, tree_b, g, CGAL::parameters::vertex_point_map(vpm_b) + .geom_traits(K())); } }; @@ -575,7 +577,7 @@ struct My_3D_Point { typedef typename K::FT FT; - typedef K R; + typedef K R; // so that we can use Kernel_traits typedef CGAL::Dimension_tag<3> Ambient_dimension; typedef CGAL::Dimension_tag<0> Feature_dimension; @@ -591,112 +593,117 @@ private: FT cx, cy, cz; }; -template <> -struct Locate_with_AABB_tree_Tester<3> // 3D +template +struct Locate_with_AABB_tree_Tester // 3D { template - void operator()(const G& g, CGAL::Random& rnd) const + void test(const G& g, const VPM vpm, CGAL::Random& rnd) const { std::cout << " test locate_with_AABB_tree (3D)..." << std::endl; - typedef typename boost::property_map_value::type Point; + typedef typename boost::property_traits::reference Point_reference; - typedef typename CGAL::Kernel_traits::type Kernel; - typedef typename Kernel::FT FT; - typedef typename Kernel::Ray_3 Ray_3; - typedef typename Kernel::Point_3 Point_3; + typedef typename K::FT FT; + typedef typename K::Ray_3 Ray_3; + typedef typename K::Point_3 Point_3; 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; - typedef typename PMP::Location_traits::Face_location Face_location; + typedef typename PMP::Face_location Face_location; face_descriptor f = CGAL::internal::random_face_in_mesh(g, rnd); halfedge_descriptor h = halfedge(f, g); vertex_descriptor v = target(h, g); // --------------------------------------------------------------------------- - typedef typename PMP::Location_traits::VPM VertexPointMap; - typedef CGAL::AABB_face_graph_triangle_primitive AABB_face_graph_primitive; - typedef CGAL::AABB_traits AABB_face_graph_traits; + typedef CGAL::AABB_face_graph_triangle_primitive AABB_face_graph_primitive; + typedef CGAL::AABB_traits AABB_face_graph_traits; CGAL_static_assertion((std::is_same::value)); CGAL::AABB_tree tree_a; - VertexPointMap vpm_a = CGAL::get_const_property_map(boost::vertex_point, g); - typename boost::property_traits::value_type p3_a = get(vpm_a, v); + Point_reference p3_a = get(vpm, v); // below tests the case where the value type of the VPM is not Kernel::Point_3 - typedef My_3D_Point Intrinsic_point; - typedef std::map Custom_map; + typedef My_3D_Point Custom_point; + typedef std::map Custom_map; typedef boost::associative_property_map Custom_VPM; - typedef PMP::internal::Point_to_Point_3_VPM WrappedVertexPointMap; - typedef CGAL::AABB_face_graph_triangle_primitive AABB_face_graph_primitive_with_WVPM; - typedef CGAL::AABB_traits AABB_face_graph_traits_with_WVPM; + typedef PMP::internal::Point_to_Point_3_VPM WrappedVPM; + typedef CGAL::AABB_face_graph_triangle_primitive AABB_face_graph_primitive_with_WVPM; + typedef CGAL::AABB_traits AABB_face_graph_traits_with_WVPM; CGAL::AABB_tree tree_b; Custom_map custom_map; for(vertex_descriptor vd : vertices(g)) { - const Point_3& p = get(vpm_a, vd); - custom_map[vd] = Intrinsic_point(p.x(), p.y(), p.z()); + const Point_reference p = get(vpm, vd); + custom_map[vd] = Custom_point(p.x(), p.y(), p.z()); } Custom_VPM custom_vpm(custom_map); - WrappedVertexPointMap vpm_b(custom_vpm); + WrappedVPM custom_vpm_3D(custom_vpm); // --------------------------------------------------------------------------- - PMP::build_AABB_tree(g, tree_a); + PMP::build_AABB_tree(g, tree_a); // just for the API assert(tree_a.size() == num_faces(g)); - PMP::build_AABB_tree(g, tree_b, CGAL::parameters::vertex_point_map(vpm_b)); + PMP::build_AABB_tree(g, tree_a, CGAL::parameters::vertex_point_map(vpm)); + PMP::build_AABB_tree(g, tree_b, CGAL::parameters::vertex_point_map(custom_vpm_3D)); assert(tree_b.size() == num_faces(g)); - Face_location loc = PMP::locate_with_AABB_tree(p3_a, tree_a, g); + Face_location loc = PMP::locate_with_AABB_tree(p3_a, tree_a, g, CGAL::parameters::vertex_point_map(vpm)); assert(is_equal(loc.second[CGAL::vertex_index_in_face(v, loc.first, g)], FT(1))); assert(is_equal(loc.second[(CGAL::vertex_index_in_face(v, loc.first, g)+1)%3], FT(0))); assert(is_equal(loc.second[(CGAL::vertex_index_in_face(v, loc.first, g)+2)%3], FT(0))); assert(is_equal(CGAL::squared_distance(PMP::construct_point(loc, g), p3_a), FT(0))); - loc = PMP::locate_with_AABB_tree(p3_a, tree_a, g, CGAL::parameters::vertex_point_map(vpm_a)); + loc = PMP::locate_with_AABB_tree(p3_a, tree_a, g, CGAL::parameters::vertex_point_map(vpm)); assert(is_equal(CGAL::squared_distance(PMP::construct_point(loc, g), p3_a), FT(0))); // --------------------------------------------------------------------------- loc = PMP::locate(p3_a, g, CGAL::parameters::snapping_tolerance(1e-7)); - std::cout << "loc: " << loc.second[0] << " " << loc.second[1] << " " << loc.second[2] << std::endl; // @tmp assert(is_equal(CGAL::squared_distance(PMP::construct_point(loc, g), p3_a), FT(0))); assert(PMP::is_in_face(loc, g)); - loc = PMP::locate_with_AABB_tree(CGAL::ORIGIN, tree_b, g, CGAL::parameters::vertex_point_map(vpm_b)); + loc = PMP::locate_with_AABB_tree(CGAL::ORIGIN, tree_b, g, CGAL::parameters::vertex_point_map(custom_vpm_3D)); assert(PMP::is_in_face(loc, g)); - // doesn't necessarily have to wrap with a P_to_P3 here, it'll do it internally + // Doesn't necessarily have to wrap with a P_to_P3: it can be done automatically internally loc = PMP::locate(CGAL::ORIGIN, g, CGAL::parameters::vertex_point_map(custom_vpm)); assert(PMP::is_in_face(loc, g)); // --------------------------------------------------------------------------- Ray_3 r3 = random_3D_ray >(tree_b, rnd); - loc = PMP::locate_with_AABB_tree(r3, tree_b, g, CGAL::parameters::vertex_point_map(vpm_b)); + loc = PMP::locate_with_AABB_tree(r3, tree_b, g, CGAL::parameters::vertex_point_map(custom_vpm_3D)); } }; -template -void test_locate(const G& g, CGAL::Random& rnd) +template +void test_locate(const G& g, + const VPM vpm, + CGAL::Random& rnd) { assert(num_vertices(g) != 0 && num_faces(g) != 0); - test_snappers(g); - test_constructions(g, rnd); - test_random_entities(g, rnd); - test_helpers(g, rnd); - test_predicates(g, rnd); - test_locate_in_face(g, rnd); + test_snappers(g); + test_constructions(g, vpm, rnd); + test_random_entities(g, rnd); + test_helpers(g, rnd); + test_predicates(g, rnd); + test_locate_in_face(g, vpm, rnd); // This test has slight syntax changes between 2D and 3D (e.g. testing ray_2 in 3D makes no sense) - Locate_with_AABB_tree_Tester< - CGAL::Ambient_dimension::Point>::value>()(g, rnd); + Locate_with_AABB_tree_Tester AABB_tester; + AABB_tester.test(g, vpm, rnd); +} + +template +void test_locate(const G& g, CGAL::Random& rnd) +{ + return test_locate(g, CGAL::get_const_property_map(boost::vertex_point, g), rnd); } template @@ -737,7 +744,7 @@ void test_2D_triangulation(const char* fname, CGAL::Random& rnd) std::cout << " (" << tr.number_of_vertices() << " vertices)..." << std::endl; std::cout << "Kernel: " << typeid(K()).name() << std::endl; - test_locate(tr, rnd); + test_locate(tr, rnd); } template @@ -759,16 +766,16 @@ void test_2D_surface_mesh(const char* fname, CGAL::Random& rnd) return; } - test_locate(tm, rnd); + test_locate(tm, rnd); } template -void test_3D_surface_mesh(const char* fname, CGAL::Random& rnd) +void test_surface_mesh_3D(const char* fname, CGAL::Random& rnd) { typedef typename K::Point_3 Point; typedef CGAL::Surface_mesh Mesh; - std::cout << "Testing Surface_mesh " << fname << "..." << std::endl; + std::cout << "Testing (3D) Surface_mesh " << fname << "..." << std::endl; std::cout << "Kernel: " << typeid(K()).name() << std::endl; std::ifstream input(fname); @@ -779,7 +786,42 @@ void test_3D_surface_mesh(const char* fname, CGAL::Random& rnd) return; } - test_locate(tm, rnd); + typedef typename boost::property_map::const_type VertexPointMap; + VertexPointMap vpm = CGAL::get_const_property_map(boost::vertex_point, tm); + + test_locate(tm, vpm, rnd); +} + +template +void test_surface_mesh_projection(const char* fname, CGAL::Random& rnd) +{ + typedef typename K::Point_3 Point; + typedef CGAL::Surface_mesh Mesh; + typedef typename K::Point_2 Projected_point; + + typedef typename boost::graph_traits::vertex_descriptor vertex_descriptor; + + std::cout << "Testing Projected Surface_mesh " << fname << "..." << std::endl; + std::cout << "Kernel: " << typeid(K()).name() << std::endl; + + std::ifstream input(fname); + Mesh tm; + if(!input || !(input >> tm)) + { + std::cerr << "Error: cannot read file."; + return; + } + + const auto& proj_vpm = tm.template add_property_map("P2", Projected_point()).first; + + for(vertex_descriptor v : vertices(tm)) + { + const Point& p = tm.point(v); + put(proj_vpm, v, Projected_point(p.x(), p.y())); + } + + test_locate(tm, proj_vpm, rnd); } template @@ -798,15 +840,16 @@ void test_polyhedron(const char* fname, CGAL::Random& rnd) return; } - test_locate(poly, rnd); + test_locate(poly, rnd); } template void test(CGAL::Random& rnd) { test_2D_triangulation("data/stair.xy", rnd); -// test_2D_surface_mesh("data/blobby_2D.off", rnd); // temporarily, until Surface_mesh's IO is "fixed" - test_3D_surface_mesh("data/mech-holes-shark.off", rnd); +// test_2D_surface_mesh("data/blobby_2D.off", rnd); // temporarily disabled, until Surface_mesh's IO is "fixed" + test_surface_mesh_3D("data/mech-holes-shark.off", rnd); + test_surface_mesh_projection("data/unit-grid.off", rnd); test_polyhedron("data-coref/elephant_split_2.off", rnd); } From d9328b1131604541baf338b74a4bd3c08aba8967 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mael=20Rouxel-Labb=C3=A9?= Date: Tue, 8 Oct 2019 15:57:34 +0200 Subject: [PATCH 190/363] Data file for PMP Location tests --- .../data/unit-grid.off | 323 ++++++++++++++++++ 1 file changed, 323 insertions(+) create mode 100644 Polygon_mesh_processing/test/Polygon_mesh_processing/data/unit-grid.off diff --git a/Polygon_mesh_processing/test/Polygon_mesh_processing/data/unit-grid.off b/Polygon_mesh_processing/test/Polygon_mesh_processing/data/unit-grid.off new file mode 100644 index 00000000000..22af0f9741f --- /dev/null +++ b/Polygon_mesh_processing/test/Polygon_mesh_processing/data/unit-grid.off @@ -0,0 +1,323 @@ +OFF +121 200 0 +0 0 0 +0.10000000000000001 0 0 +0.20000000000000001 0 0 +0.29999999999999999 0 0 +0.40000000000000002 0 0 +0.5 0 0 +0.59999999999999998 0 0 +0.69999999999999996 0 0 +0.80000000000000004 0 0 +0.90000000000000002 0 0 +1 0 0 +0 0.10000000000000001 0 +0.10000000000000001 0.10000000000000001 0 +0.20000000000000001 0.10000000000000001 0 +0.29999999999999999 0.10000000000000001 0 +0.40000000000000002 0.10000000000000001 0 +0.5 0.10000000000000001 0 +0.59999999999999998 0.10000000000000001 0 +0.69999999999999996 0.10000000000000001 0 +0.80000000000000004 0.10000000000000001 0 +0.90000000000000002 0.10000000000000001 0 +1 0.10000000000000001 0 +0 0.20000000000000001 0 +0.10000000000000001 0.20000000000000001 0 +0.20000000000000001 0.20000000000000001 0 +0.29999999999999999 0.20000000000000001 0 +0.40000000000000002 0.20000000000000001 0 +0.5 0.20000000000000001 0 +0.59999999999999998 0.20000000000000001 0 +0.69999999999999996 0.20000000000000001 0 +0.80000000000000004 0.20000000000000001 0 +0.90000000000000002 0.20000000000000001 0 +1 0.20000000000000001 0 +0 0.29999999999999999 0 +0.10000000000000001 0.29999999999999999 0 +0.20000000000000001 0.29999999999999999 0 +0.29999999999999999 0.29999999999999999 0 +0.40000000000000002 0.29999999999999999 0 +0.5 0.29999999999999999 0 +0.59999999999999998 0.29999999999999999 0 +0.69999999999999996 0.29999999999999999 0 +0.80000000000000004 0.29999999999999999 0 +0.90000000000000002 0.29999999999999999 0 +1 0.29999999999999999 0 +0 0.40000000000000002 0 +0.10000000000000001 0.40000000000000002 0 +0.20000000000000001 0.40000000000000002 0 +0.29999999999999999 0.40000000000000002 0 +0.40000000000000002 0.40000000000000002 0 +0.5 0.40000000000000002 0 +0.59999999999999998 0.40000000000000002 0 +0.69999999999999996 0.40000000000000002 0 +0.80000000000000004 0.40000000000000002 0 +0.90000000000000002 0.40000000000000002 0 +1 0.40000000000000002 0 +0 0.5 0 +0.10000000000000001 0.5 0 +0.20000000000000001 0.5 0 +0.29999999999999999 0.5 0 +0.40000000000000002 0.5 0 +0.5 0.5 0 +0.59999999999999998 0.5 0 +0.69999999999999996 0.5 0 +0.80000000000000004 0.5 0 +0.90000000000000002 0.5 0 +1 0.5 0 +0 0.59999999999999998 0 +0.10000000000000001 0.59999999999999998 0 +0.20000000000000001 0.59999999999999998 0 +0.29999999999999999 0.59999999999999998 0 +0.40000000000000002 0.59999999999999998 0 +0.5 0.59999999999999998 0 +0.59999999999999998 0.59999999999999998 0 +0.69999999999999996 0.59999999999999998 0 +0.80000000000000004 0.59999999999999998 0 +0.90000000000000002 0.59999999999999998 0 +1 0.59999999999999998 0 +0 0.69999999999999996 0 +0.10000000000000001 0.69999999999999996 0 +0.20000000000000001 0.69999999999999996 0 +0.29999999999999999 0.69999999999999996 0 +0.40000000000000002 0.69999999999999996 0 +0.5 0.69999999999999996 0 +0.59999999999999998 0.69999999999999996 0 +0.69999999999999996 0.69999999999999996 0 +0.80000000000000004 0.69999999999999996 0 +0.90000000000000002 0.69999999999999996 0 +1 0.69999999999999996 0 +0 0.80000000000000004 0 +0.10000000000000001 0.80000000000000004 0 +0.20000000000000001 0.80000000000000004 0 +0.29999999999999999 0.80000000000000004 0 +0.40000000000000002 0.80000000000000004 0 +0.5 0.80000000000000004 0 +0.59999999999999998 0.80000000000000004 0 +0.69999999999999996 0.80000000000000004 0 +0.80000000000000004 0.80000000000000004 0 +0.90000000000000002 0.80000000000000004 0 +1 0.80000000000000004 0 +0 0.90000000000000002 0 +0.10000000000000001 0.90000000000000002 0 +0.20000000000000001 0.90000000000000002 0 +0.29999999999999999 0.90000000000000002 0 +0.40000000000000002 0.90000000000000002 0 +0.5 0.90000000000000002 0 +0.59999999999999998 0.90000000000000002 0 +0.69999999999999996 0.90000000000000002 0 +0.80000000000000004 0.90000000000000002 0 +0.90000000000000002 0.90000000000000002 0 +1 0.90000000000000002 0 +0 1 0 +0.10000000000000001 1 0 +0.20000000000000001 1 0 +0.29999999999999999 1 0 +0.40000000000000002 1 0 +0.5 1 0 +0.59999999999999998 1 0 +0.69999999999999996 1 0 +0.80000000000000004 1 0 +0.90000000000000002 1 0 +1 1 0 +3 0 1 11 +3 1 12 11 +3 11 12 22 +3 12 23 22 +3 22 23 33 +3 23 34 33 +3 33 34 44 +3 34 45 44 +3 44 45 55 +3 45 56 55 +3 55 56 66 +3 56 67 66 +3 66 67 77 +3 67 78 77 +3 77 78 88 +3 78 89 88 +3 88 89 99 +3 89 100 99 +3 99 100 110 +3 100 111 110 +3 1 2 12 +3 2 13 12 +3 12 13 23 +3 13 24 23 +3 23 24 34 +3 24 35 34 +3 34 35 45 +3 35 46 45 +3 45 46 56 +3 46 57 56 +3 56 57 67 +3 57 68 67 +3 67 68 78 +3 68 79 78 +3 78 79 89 +3 79 90 89 +3 89 90 100 +3 90 101 100 +3 100 101 111 +3 101 112 111 +3 2 3 13 +3 3 14 13 +3 13 14 24 +3 14 25 24 +3 24 25 35 +3 25 36 35 +3 35 36 46 +3 36 47 46 +3 46 47 57 +3 47 58 57 +3 57 58 68 +3 58 69 68 +3 68 69 79 +3 69 80 79 +3 79 80 90 +3 80 91 90 +3 90 91 101 +3 91 102 101 +3 101 102 112 +3 102 113 112 +3 3 4 14 +3 4 15 14 +3 14 15 25 +3 15 26 25 +3 25 26 36 +3 26 37 36 +3 36 37 47 +3 37 48 47 +3 47 48 58 +3 48 59 58 +3 58 59 69 +3 59 70 69 +3 69 70 80 +3 70 81 80 +3 80 81 91 +3 81 92 91 +3 91 92 102 +3 92 103 102 +3 102 103 113 +3 103 114 113 +3 4 5 15 +3 5 16 15 +3 15 16 26 +3 16 27 26 +3 26 27 37 +3 27 38 37 +3 37 38 48 +3 38 49 48 +3 48 49 59 +3 49 60 59 +3 59 60 70 +3 60 71 70 +3 70 71 81 +3 71 82 81 +3 81 82 92 +3 82 93 92 +3 92 93 103 +3 93 104 103 +3 103 104 114 +3 104 115 114 +3 5 6 16 +3 6 17 16 +3 16 17 27 +3 17 28 27 +3 27 28 38 +3 28 39 38 +3 38 39 49 +3 39 50 49 +3 49 50 60 +3 50 61 60 +3 60 61 71 +3 61 72 71 +3 71 72 82 +3 72 83 82 +3 82 83 93 +3 83 94 93 +3 93 94 104 +3 94 105 104 +3 104 105 115 +3 105 116 115 +3 6 7 17 +3 7 18 17 +3 17 18 28 +3 18 29 28 +3 28 29 39 +3 29 40 39 +3 39 40 50 +3 40 51 50 +3 50 51 61 +3 51 62 61 +3 61 62 72 +3 62 73 72 +3 72 73 83 +3 73 84 83 +3 83 84 94 +3 84 95 94 +3 94 95 105 +3 95 106 105 +3 105 106 116 +3 106 117 116 +3 7 8 18 +3 8 19 18 +3 18 19 29 +3 19 30 29 +3 29 30 40 +3 30 41 40 +3 40 41 51 +3 41 52 51 +3 51 52 62 +3 52 63 62 +3 62 63 73 +3 63 74 73 +3 73 74 84 +3 74 85 84 +3 84 85 95 +3 85 96 95 +3 95 96 106 +3 96 107 106 +3 106 107 117 +3 107 118 117 +3 8 9 19 +3 9 20 19 +3 19 20 30 +3 20 31 30 +3 30 31 41 +3 31 42 41 +3 41 42 52 +3 42 53 52 +3 52 53 63 +3 53 64 63 +3 63 64 74 +3 64 75 74 +3 74 75 85 +3 75 86 85 +3 85 86 96 +3 86 97 96 +3 96 97 107 +3 97 108 107 +3 107 108 118 +3 108 119 118 +3 9 10 20 +3 10 21 20 +3 20 21 31 +3 21 32 31 +3 31 32 42 +3 32 43 42 +3 42 43 53 +3 43 54 53 +3 53 54 64 +3 54 65 64 +3 64 65 75 +3 65 76 75 +3 75 76 86 +3 76 87 86 +3 86 87 97 +3 87 98 97 +3 97 98 108 +3 98 109 108 +3 108 109 119 +3 109 120 119 From 3801a35eb3272d710b1396d22dce47dcd6411e9a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mael=20Rouxel-Labb=C3=A9?= Date: Tue, 8 Oct 2019 16:03:51 +0200 Subject: [PATCH 191/363] Tiny fixes --- .../include/CGAL/Polygon_mesh_processing/locate.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/locate.h b/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/locate.h index f82daed743b..5616b9e3c7f 100644 --- a/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/locate.h +++ b/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/locate.h @@ -427,7 +427,7 @@ random_location_on_halfedge(typename boost::graph_traits::halfedge std::array coordinates; coordinates[h_id] = t; - coordinates[(h_id+1)%3] = FT(1-t); + coordinates[(h_id+1)%3] = FT(1)-t; coordinates[(h_id+2)%3] = FT(0); return std::make_pair(face(hd, tm), coordinates); @@ -1208,7 +1208,7 @@ locate_in_adjacent_face(const std::pair::vertex_descriptor vertex_descriptor; typedef typename boost::graph_traits::halfedge_descriptor halfedge_descriptor; - typedef typename boost::graph_traits::face_descriptor face_descriptor; + CGAL_assertion_code(typedef typename boost::graph_traits::face_descriptor face_descriptor;) if(loc.first == fd) return loc; From 937423bb9f49b681bf2069e05698c883b0f65611 Mon Sep 17 00:00:00 2001 From: Andreas Fabri Date: Wed, 9 Oct 2019 11:59:12 +0200 Subject: [PATCH 192/363] Surface_mesh: Fix Property_container::swap() --- Surface_mesh/include/CGAL/Surface_mesh/Properties.h | 1 + 1 file changed, 1 insertion(+) diff --git a/Surface_mesh/include/CGAL/Surface_mesh/Properties.h b/Surface_mesh/include/CGAL/Surface_mesh/Properties.h index c975f23d1d6..1300f31253c 100644 --- a/Surface_mesh/include/CGAL/Surface_mesh/Properties.h +++ b/Surface_mesh/include/CGAL/Surface_mesh/Properties.h @@ -486,6 +486,7 @@ public: void swap (Property_container& other) { this->parrays_.swap (other.parrays_); + std::swap(this->size_, other.size_); } private: From acec5469feecc78f1556597e93c0736ee513cd7e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9bastien=20Loriot?= Date: Thu, 10 Oct 2019 07:57:26 +0200 Subject: [PATCH 193/363] lazily build the tree --- .../include/CGAL/Side_of_triangle_mesh.h | 58 ++++++++++++------- 1 file changed, 36 insertions(+), 22 deletions(-) diff --git a/Polygon_mesh_processing/include/CGAL/Side_of_triangle_mesh.h b/Polygon_mesh_processing/include/CGAL/Side_of_triangle_mesh.h index de8b78f0834..b0923db9cda 100644 --- a/Polygon_mesh_processing/include/CGAL/Side_of_triangle_mesh.h +++ b/Polygon_mesh_processing/include/CGAL/Side_of_triangle_mesh.h @@ -76,7 +76,7 @@ namespace CGAL { */ template + typename VertexPointMap__> struct AABB_tree_default { typedef CGAL::AABB_face_graph_triangle_primitive Primitive; + VertexPointMap__> Primitive; typedef CGAL::AABB_traits Traits; typedef CGAL::AABB_tree type; }; typedef typename Default::Lazy_get + VertexPointMap_> >::type AABB_tree_; + typedef typename Default::Get::const_type>::type + VertexPointMap; typedef typename GeomTraits::Point_3 Point; //members typename GeomTraits::Construct_ray_3 ray_functor; typename GeomTraits::Construct_vector_3 vector_functor; - const AABB_tree_* tree_ptr; + mutable const AABB_tree_* tree_ptr; + const TriangleMesh* tm_ptr; + boost::optional opt_vpm; bool own_tree; CGAL::Bbox_3 box; +#ifdef CGAL_HAS_THREADS + mutable CGAL_MUTEX tree_mutex; +#endif public: @@ -129,14 +138,13 @@ public: const GeomTraits& gt=GeomTraits()) : ray_functor(gt.construct_ray_3_object()) , vector_functor(gt.construct_vector_3_object()) + , tree_ptr(nullptr) + , tm_ptr(&tmesh) + , opt_vpm(vpmap) , own_tree(true) { CGAL_assertion(CGAL::is_triangle_mesh(tmesh)); CGAL_assertion(CGAL::is_closed(tmesh)); - - tree_ptr = new AABB_tree(faces(tmesh).first, - faces(tmesh).second, - tmesh, vpmap); box = Polygon_mesh_processing::bbox(tmesh, parameters::vertex_point_map(vpmap)); } @@ -150,18 +158,8 @@ public: */ Side_of_triangle_mesh(const TriangleMesh& tmesh, const GeomTraits& gt=GeomTraits()) - : ray_functor(gt.construct_ray_3_object()) - , vector_functor(gt.construct_vector_3_object()) - , own_tree(true) - { - CGAL_assertion(CGAL::is_triangle_mesh(tmesh)); - CGAL_assertion(CGAL::is_closed(tmesh)); - - tree_ptr = new AABB_tree(faces(tmesh).first, - faces(tmesh).second, - tmesh); - box = Polygon_mesh_processing::bbox(tmesh); - } + : Side_of_triangle_mesh(tmesh, get(vertex_point, tmesh), gt) + {} /** * Constructor that takes a pre-built \cgal `AABB_tree` @@ -184,7 +182,7 @@ public: ~Side_of_triangle_mesh() { - if (own_tree) + if (own_tree && tree_ptr!=nullptr) delete tree_ptr; } @@ -211,6 +209,22 @@ public: } else { + // Lazily build the tree only when needed + if (tree_ptr==nullptr) + { +#ifdef CGAL_HAS_THREADS + CGAL_SCOPED_LOCK(tree_mutex); +#endif + CGAL_assertion(tm_ptr != nullptr && opt_vpm!=boost::none); + if (tree_ptr==nullptr) + { + tree_ptr = new AABB_tree(faces(*tm_ptr).first, + faces(*tm_ptr).second, + *tm_ptr, *opt_vpm); + const_cast(tree_ptr)->build(); + } + } + return internal::Point_inside_vertical_ray_cast()( point, *tree_ptr, ray_functor, vector_functor); } From 9221290bef3b1e6c2773678a2497bd93f98942b0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9bastien=20Loriot?= Date: Fri, 11 Oct 2019 08:07:02 +0200 Subject: [PATCH 194/363] add missing const --- .../include/CGAL/AABB_face_graph_triangle_primitive.h | 2 +- .../CGAL/AABB_halfedge_graph_segment_primitive.h | 10 +++++----- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/AABB_tree/include/CGAL/AABB_face_graph_triangle_primitive.h b/AABB_tree/include/CGAL/AABB_face_graph_triangle_primitive.h index 7663d0d78c7..563f9fa665b 100644 --- a/AABB_tree/include/CGAL/AABB_face_graph_triangle_primitive.h +++ b/AABB_tree/include/CGAL/AABB_face_graph_triangle_primitive.h @@ -47,7 +47,7 @@ namespace CGAL { *\tparam FaceGraph is a model of the face graph concept. *\tparam VertexPointPMap is a property map with `boost::graph_traits::%vertex_descriptor` * as key type and a \cgal Kernel `Point_3` as value type. - * The default is `typename boost::property_map< FaceGraph,vertex_point_t>::%type`. + * The default is `typename boost::property_map< FaceGraph,vertex_point_t>::%const_type`. *\tparam OneFaceGraphPerTree is either `CGAL::Tag_true` or `CGAL::Tag_false`. * In the former case, we guarantee that all the primitives will be from a * common `FaceGraph` and some data will be factorized so that the size of diff --git a/AABB_tree/include/CGAL/AABB_halfedge_graph_segment_primitive.h b/AABB_tree/include/CGAL/AABB_halfedge_graph_segment_primitive.h index 1eb27965e6c..870fea421af 100644 --- a/AABB_tree/include/CGAL/AABB_halfedge_graph_segment_primitive.h +++ b/AABB_tree/include/CGAL/AABB_halfedge_graph_segment_primitive.h @@ -58,7 +58,7 @@ namespace CGAL { * \tparam HalfedgeGraph is a model of the halfedge graph concept. * as key type and a \cgal Kernel `Point_3` as value type. * \tparam VertexPointPMap is a property map with `boost::graph_traits::%vertex_descriptor`. - * The default is `typename boost::property_map< HalfedgeGraph,vertex_point_t>::%type`. + * The default is `typename boost::property_map< HalfedgeGraph,vertex_point_t>::%const_type`. * \tparam OneHalfedgeGraphPerTree is either `CGAL::Tag_true` or `CGAL::Tag_false`. * In the former case, we guarantee that all the primitives will be from a * common `HalfedgeGraph` and some data will be factorized so that the size of @@ -86,17 +86,17 @@ class AABB_halfedge_graph_segment_primitive HalfedgeGraph, typename Default::Get::type >::type >, + vertex_point_t>::const_type >::type >, Source_point_from_edge_descriptor_map< HalfedgeGraph, typename Default::Get::type >::type >, + vertex_point_t>::const_type >::type >, OneHalfedgeGraphPerTree, CacheDatum > #endif { - typedef typename Default::Get::type >::type VertexPointPMap_; + typedef typename Default::Get::const_type >::type VertexPointPMap_; typedef typename boost::graph_traits::edge_descriptor ED; typedef typename boost::mpl::if_ >::type Id_; @@ -127,7 +127,7 @@ public: /*! The point type. */ - typedef boost::property_traits< boost::property_map< HalfedgeGraph, vertex_point_t>::type >::value_type Point; + typedef boost::property_traits< boost::property_map< HalfedgeGraph, vertex_point_t>::const_type >::value_type Point; /*! Geometric data type. */ From 7a233375b23c36a65daaa8cf2c2c65a30b5e18f2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9bastien=20Loriot?= Date: Fri, 11 Oct 2019 08:07:21 +0200 Subject: [PATCH 195/363] add missing const if non-const was provided, the same map should have been provided to the tree --- Mesh_3/include/CGAL/Polyhedral_mesh_domain_3.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Mesh_3/include/CGAL/Polyhedral_mesh_domain_3.h b/Mesh_3/include/CGAL/Polyhedral_mesh_domain_3.h index 6b013766433..136d8cb3813 100644 --- a/Mesh_3/include/CGAL/Polyhedral_mesh_domain_3.h +++ b/Mesh_3/include/CGAL/Polyhedral_mesh_domain_3.h @@ -215,7 +215,7 @@ public: struct Primitive_type { //setting OneFaceGraphPerTree to false transforms the id type into //std::pair. - typedef AABB_face_graph_triangle_primitive::type, CGAL::Tag_false> type; + typedef AABB_face_graph_triangle_primitive::const_type, CGAL::Tag_false> type; static typename IGT_::Triangle_3 datum(const typename type::Id primitive_id) { From e919441cf605f4cf2f8d08ce174c73350aa8ce93 Mon Sep 17 00:00:00 2001 From: Mael Date: Fri, 11 Oct 2019 09:05:31 +0200 Subject: [PATCH 196/363] Remove useless macro --- .../test/Triangulation_2/test_constrained_triangulation_2.cpp | 2 -- 1 file changed, 2 deletions(-) diff --git a/Triangulation_2/test/Triangulation_2/test_constrained_triangulation_2.cpp b/Triangulation_2/test/Triangulation_2/test_constrained_triangulation_2.cpp index 5a00013a564..8125d01805a 100644 --- a/Triangulation_2/test/Triangulation_2/test_constrained_triangulation_2.cpp +++ b/Triangulation_2/test/Triangulation_2/test_constrained_triangulation_2.cpp @@ -20,8 +20,6 @@ // coordinator : INRIA Sophia-Antipolis // ============================================================================ -#define CGAL_NO_CDT_2_WARNING - #include #include From 9721942d8a9c8856ed9b30ed590fb095eef67403 Mon Sep 17 00:00:00 2001 From: Guillaume Damiand Date: Mon, 14 Oct 2019 14:26:23 +0200 Subject: [PATCH 197/363] Add possibility to draw text. --- .../include/CGAL/Qt/Basic_viewer_qt.h | 49 ++++++++++++++++++- 1 file changed, 47 insertions(+), 2 deletions(-) diff --git a/GraphicsView/include/CGAL/Qt/Basic_viewer_qt.h b/GraphicsView/include/CGAL/Qt/Basic_viewer_qt.h index 6c7cc69e840..7bb75cb1446 100644 --- a/GraphicsView/include/CGAL/Qt/Basic_viewer_qt.h +++ b/GraphicsView/include/CGAL/Qt/Basic_viewer_qt.h @@ -24,6 +24,8 @@ #include #include +#include +#include #ifdef CGAL_USE_BASIC_VIEWER @@ -258,7 +260,8 @@ public: bool use_mono_color=false, bool inverse_normal=false, bool draw_rays=true, - bool draw_lines=true) : + bool draw_lines=true, + bool draw_text=true) : CGAL::QGLViewer(parent), m_draw_vertices(draw_vertices), m_draw_edges(draw_edges), @@ -268,6 +271,7 @@ public: m_flatShading(true), m_use_mono_color(use_mono_color), m_inverse_normal(inverse_normal), + m_draw_text(draw_text), m_size_points(7.), m_size_edges(3.1), m_size_rays(3.1), @@ -351,6 +355,7 @@ public: { arrays[i].clear(); } m_bounding_box=CGAL::Bbox_3(); + m_texts.clear(); } bool is_empty() const @@ -485,6 +490,21 @@ public: (p + (bigNumber)*v), acolor); } + template + void add_text(const KPoint& kp, const QString& txt) + { + Local_point p=internal::get_local_point(kp); + m_texts.push_back(std::make_tuple(p, txt)); + } + + template + void add_text(const KPoint& kp, const char* txt) + { add_text(kp, QString(txt)); } + + template + void add_text(const KPoint& kp, const std::string& txt) + { add_text(kp, txt.c_str()); } + bool is_a_face_started() const { return m_buffer_for_mono_faces.is_a_face_started() || @@ -1158,6 +1178,21 @@ protected: constraint.setRotationConstraintDirection(CGAL::qglviewer::Vec(cx, cy, cz)); camera()->frame()->setConstraint(&constraint); } + + if (m_draw_text) + { + glDisable(GL_LIGHTING); + for (std::size_t i=0; iprojectedCoordinatesOf + (CGAL::qglviewer::Vec(std::get<0>(m_texts[i]).x(), + std::get<0>(m_texts[i]).y(), + std::get<0>(m_texts[i]).z())); + + drawText((int)screenPos[0], (int)screenPos[1], std::get<1>(m_texts[i])); + } + glEnable(GL_LIGHTING); + } } virtual void redraw() @@ -1181,6 +1216,7 @@ protected: setKeyDescription(::Qt::Key_G, "Switch between flat/Gouraud shading display"); setKeyDescription(::Qt::Key_M, "Toggles mono color"); setKeyDescription(::Qt::Key_N, "Inverse direction of normals"); + setKeyDescription(::Qt::Key_T, "Toggles text display"); setKeyDescription(::Qt::Key_V, "Toggles vertices display"); setKeyDescription(::Qt::Key_Plus, "Increase size of edges"); setKeyDescription(::Qt::Key_Minus, "Decrease size of edges"); @@ -1266,6 +1302,12 @@ protected: negate_all_normals(); redraw(); } + else if ((e->key()==::Qt::Key_T) && (modifiers==::Qt::NoButton)) + { + m_draw_text=!m_draw_text; + displayMessage(QString("Draw text=%1.").arg(m_draw_text?"true":"false")); + update(); + } else if ((e->key()==::Qt::Key_V) && (modifiers==::Qt::NoButton)) { m_draw_vertices=!m_draw_vertices; @@ -1416,7 +1458,8 @@ protected: bool m_flatShading; bool m_use_mono_color; bool m_inverse_normal; - + bool m_draw_text; + double m_size_points; double m_size_edges; double m_size_rays; @@ -1501,6 +1544,8 @@ protected: QOpenGLShaderProgram rendering_program_face; QOpenGLShaderProgram rendering_program_p_l; + + std::vector > m_texts; }; } // End namespace CGAL From 77e0937fb29ef49e97f851c06538d277713f5250 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mael=20Rouxel-Labb=C3=A9?= Date: Tue, 15 Oct 2019 13:13:16 +0200 Subject: [PATCH 198/363] Uniformize tparam formulation --- .../CGAL/Polygon_mesh_processing/locate.h | 68 +++++++++---------- 1 file changed, 34 insertions(+), 34 deletions(-) diff --git a/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/locate.h b/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/locate.h index 5616b9e3c7f..688599e16be 100644 --- a/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/locate.h +++ b/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/locate.h @@ -408,7 +408,7 @@ barycentric_coordinates(const Point& p, const Point& q, const Point& r, const Po /// and `0` for respetively the source and target of `hd`, and the third vertex. /// /// \tparam FT must be a model of `FieldNumberType` -/// \tparam TriangleMesh a model of `FaceGraph` +/// \tparam TriangleMesh must be a model of `FaceGraph` /// /// \param hd a halfedge of `tm` /// \param tm a triangulated surface mesh @@ -443,7 +443,7 @@ random_location_on_halfedge(typename boost::graph_traits::halfedge /// `1-u-v` for respectively the source and target of `halfedge(fd, tm)`, and the third point. /// /// \tparam FT must be a model of `FieldNumberType` -/// \tparam TriangleMesh a model of `FaceGraph` +/// \tparam TriangleMesh must be a model of `FaceGraph` /// /// \param fd a face of `tm` /// \param tm a triangulated surface mesh @@ -475,7 +475,7 @@ random_location_on_face(typename boost::graph_traits::face_descrip /// are thus all positive. Note that all faces have the same probability to be chosen. /// /// \tparam FT must be a model of `FieldNumberType` -/// \tparam TriangleMesh a model of `FaceGraph` +/// \tparam TriangleMesh must be a model of `FaceGraph` /// /// \param tm a triangulated surface mesh /// \param rnd optional random number generator @@ -510,7 +510,7 @@ random_location_on_mesh(const TriangleMesh& tm, /// `fd` (equal to `loc.first`). /// /// \tparam FT must be a model of `FieldNumberType` -/// \tparam TriangleMesh a model of `FaceGraph` +/// \tparam TriangleMesh must be a model of `FaceGraph` /// /// \param loc a location with `loc.first` a face of `tm` /// \param tm a triangulated surface mesh @@ -570,7 +570,7 @@ get_descriptor_from_location(const std::pair::face /// - `w1` corresponds to `target(halfedge(f, tm), tm)` /// - `w2` corresponds to `target(next(halfedge(f, tm), tm), tm)` /// -/// \tparam FT a model of `FieldNumberType` -/// \tparam TriangleMesh a model of `FaceGraph` +/// \tparam FT must be a model of `FieldNumberType` +/// \tparam TriangleMesh must be a model of `FaceGraph` /// /// \param loc a location with `loc.first` a face of `tm` /// \param vd a vertex of `tm` @@ -702,8 +702,8 @@ is_on_vertex(const std::pair::face_de /// - `w1` corresponds to `target(halfedge(f, tm), tm)` /// - `w2` corresponds to `target(next(halfedge(f, tm), tm), tm)` /// -/// \tparam FT a model of `FieldNumberType` -/// \tparam TriangleMesh a model of `FaceGraph` +/// \tparam FT must be a model of `FieldNumberType` +/// \tparam TriangleMesh must be a model of `FaceGraph` /// /// \param loc a location with `loc.first` a face of `tm` /// \param hd a halfedge of `tm` @@ -751,8 +751,8 @@ is_on_halfedge(const std::pair::face_ /// - `w1` corresponds to `target(halfedge(f, tm), tm)` /// - `w2` corresponds to `target(next(halfedge(f, tm), tm), tm)` /// -/// \tparam FT a model of `FieldNumberType` -/// \tparam TriangleMesh a model of `FaceGraph` +/// \tparam FT must be a model of `FieldNumberType` +/// \tparam TriangleMesh must be a model of `FaceGraph` /// /// \param bar an array of barycentric coordinates /// \param tm a triangulated surface mesh @@ -791,8 +791,8 @@ is_in_face(const std::array& bar, /// - `w1` corresponds to `target(halfedge(f, tm), tm)` /// - `w2` corresponds to `target(next(halfedge(f, tm), tm), tm)` /// -/// \tparam FT a model of `FieldNumberType` -/// \tparam TriangleMesh a model of `FaceGraph` +/// \tparam FT must be a model of `FieldNumberType` +/// \tparam TriangleMesh must be a model of `FaceGraph` /// /// \param loc a location with `loc.first` a face of `tm` /// \param tm a triangulated surface mesh @@ -823,8 +823,8 @@ is_in_face(const std::pair::face_desc /// - `w1` corresponds to `target(halfedge(f, tm), tm)` /// - `w2` corresponds to `target(next(halfedge(f, tm), tm), tm)` /// -/// \tparam FT a model of `FieldNumberType` -/// \tparam TriangleMesh a model of `FaceGraph` +/// \tparam FT must be a model of `FieldNumberType` +/// \tparam TriangleMesh must be a model of `FaceGraph` /// /// \param loc a location with `loc.first` a face of `tm` /// \param tm a triangulated surface mesh @@ -864,8 +864,8 @@ is_on_face_border(const std::pair::fa /// - `w1` corresponds to `target(halfedge(f, tm), tm)` /// - `w2` corresponds to `target(next(halfedge(f, tm), tm), tm)` /// -/// \tparam FT a model of `FieldNumberType` -/// \tparam TriangleMesh a model of `FaceGraph` +/// \tparam FT must be a model of `FieldNumberType` +/// \tparam TriangleMesh must be a model of `FaceGraph` /// /// \param loc a location with `loc.first` a face of `tm` /// \param tm a triangulated surface mesh @@ -933,8 +933,8 @@ is_on_mesh_border(const std::pair::fa /// - `w1` corresponds to `target(halfedge(f, tm), tm)` /// - `w2` corresponds to `target(next(halfedge(f, tm), tm), tm)` /// -/// \tparam FT a model of `FieldNumberType` -/// \tparam TriangleMesh a model of `FaceGraph` +/// \tparam FT must be a model of `FieldNumberType` +/// \tparam TriangleMesh must be a model of `FaceGraph` /// /// \param vd a vertex of `tm` /// \param tm a triangulated surface mesh @@ -995,8 +995,8 @@ locate_vertex(typename boost::graph_traits::vertex_descriptor vd, /// - `w1` corresponds to `target(halfedge(f, tm), tm)` /// - `w2` corresponds to `target(next(halfedge(f, tm), tm), tm)` /// -/// \tparam FT a model of `FieldNumberType` -/// \tparam TriangleMesh a model of `FaceGraph` +/// \tparam FT must be a model of `FieldNumberType` +/// \tparam TriangleMesh must be a model of `FaceGraph` /// /// \param vd a vertex of `tm` and a vertex of the face `fd` /// \param fd a face of `tm` @@ -1034,8 +1034,8 @@ locate_vertex(const typename boost::graph_traits::vertex_descripto /// - `w1` corresponds to `target(halfedge(f, tm), tm)` /// - `w2` corresponds to `target(next(halfedge(f, tm), tm), tm)` /// -/// \tparam FT a model of `FieldNumberType` -/// \tparam TriangleMesh a model of `FaceGraph` +/// \tparam FT must be a model of `FieldNumberType` +/// \tparam TriangleMesh must be a model of `FaceGraph` /// /// \param hd a halfedge of `tm` /// \param t the parametric distance of the desired point along `hd` @@ -1074,7 +1074,7 @@ locate_on_halfedge(const typename boost::graph_traits::halfedge_de /// - `w1` corresponds to `target(halfedge(f, tm), tm)` /// - `w2` corresponds to `target(next(halfedge(f, tm), tm), tm)` /// -/// \tparam TriangleMesh a model of `FaceGraph` +/// \tparam TriangleMesh must be a model of `FaceGraph` /// \tparam NamedParameters a sequence of \ref pmp_namedparameters "Named Parameters" /// /// \param query a point, whose type is equal to the value type of the vertex point property map @@ -1186,8 +1186,8 @@ locate_in_face(const typename internal::Location_traits::Point& qu /// - `w1` corresponds to `target(halfedge(f, tm), tm)` /// - `w2` corresponds to `target(next(halfedge(f, tm), tm), tm)` /// -/// \tparam FT a model of `FieldNumberType` -/// \tparam TriangleMesh a model of `FaceGraph` +/// \tparam FT must be a model of `FieldNumberType` +/// \tparam TriangleMesh must be a model of `FaceGraph` /// /// \param loc the first location, with `loc.first` being a face of `tm` /// \param fd the second face, adjacent to `loc.first` @@ -1562,8 +1562,8 @@ void build_AABB_tree(const TriangleMesh& tm, /// `locate_with_AABB_tree()` that takes as parameter an AABB tree, instead of calling `locate()` /// multiple times, which will build a new AABB tree on every call. /// -/// \tparam TriangleMesh a model of `FaceListGraph` -/// \tparam Point3VPM a class model of `ReadablePropertyMap` with `boost::graph_traits::%vertex_descriptor` +/// \tparam TriangleMesh must be a model of `FaceListGraph` +/// \tparam Point3VPM must be a class model of `ReadablePropertyMap` with `boost::graph_traits::%vertex_descriptor` /// as key type and the \cgal 3D point type (your traits' `%Point_3`) as value type. /// \tparam NamedParameters a sequence of \ref pmp_namedparameters "Named Parameters" /// @@ -1624,8 +1624,8 @@ void build_AABB_tree(const TriangleMesh& tm, AABB_tree& outTree) /// is a 2D triangulation, or a CGAL::Surface_mesh >), as long as an appropriate /// vertex point property map is passed in the AABB tree, which will convert from 2D to 3D. /// -/// \tparam TriangleMesh a model of `FaceListGraph` -/// \tparam Point3VPM a class model of `ReadablePropertyMap` with `boost::graph_traits::%vertex_descriptor` +/// \tparam TriangleMesh must be a model of `FaceListGraph` +/// \tparam Point3VPM must be a class model of `ReadablePropertyMap` with `boost::graph_traits::%vertex_descriptor` /// as key type and the \cgal 3D point type (your traits' `%Point_3`) as value type. /// \tparam NamedParameters a sequence of \ref pmp_namedparameters "Named Parameters" /// @@ -1723,7 +1723,7 @@ locate_with_AABB_tree(const typename internal::Location_traits::Po /// to call this function more than once, first use `build_AABB_tree()` to create a /// an AABB tree that you can store and use the function `locate_with_AABB_tree()`. /// -/// \tparam TriangleMesh a model of `FaceListGraph`. +/// \tparam TriangleMesh must be a model of `FaceListGraph`. /// \tparam NamedParameters a sequence of \ref pmp_namedparameters "Named Parameters" /// /// \param p the point to locate on the input triangulated surface mesh @@ -1806,8 +1806,8 @@ locate(const typename property_map_value::t /// /// If the ray does not intersect the mesh, a default constructed location is returned. /// -/// \tparam TriangleMesh a model of `FaceListGraph`. -/// \tparam Point3VPM a class model of `ReadablePropertyMap` with `boost::graph_traits::%vertex_descriptor` +/// \tparam TriangleMesh must be a model of `FaceListGraph`. +/// \tparam Point3VPM must be a class model of `ReadablePropertyMap` with `boost::graph_traits::%vertex_descriptor` /// as key type and the \cgal 3D point type (your traits' `%Point_3`) as value type. /// \tparam NamedParameters a sequence of \ref pmp_namedparameters "Named Parameters" /// @@ -1944,7 +1944,7 @@ locate_with_AABB_tree(const typename internal::Location_traits::Ra /// copy of the `AABB_tree`, and use the overloads of this function /// that accept a reference to an AABB tree as input. /// -/// \tparam TriangleMesh a model of `FaceListGraph`. +/// \tparam TriangleMesh must be a model of `FaceListGraph`. /// \tparam NamedParameters a sequence of \ref pmp_namedparameters "Named Parameters" /// /// \param ray a ray to intersect with the input triangulated surface mesh From d76a984aeec30fdd880ab9620345638a43c0ac77 Mon Sep 17 00:00:00 2001 From: Maxime Gimeno Date: Tue, 15 Oct 2019 14:44:08 +0200 Subject: [PATCH 199/363] Add a custom class to replace the QDoubleSpinBox --- .../demo/Polyhedron/CGAL_double_edit.cpp | 14 ++++++ Polyhedron/demo/Polyhedron/CGAL_double_edit.h | 22 +++++++++ Polyhedron/demo/Polyhedron/CMakeLists.txt | 3 +- .../Plugins/PMP/Isotropic_remeshing_dialog.ui | 45 ++++++++++--------- .../PMP/Isotropic_remeshing_plugin.cpp | 14 +++--- 5 files changed, 67 insertions(+), 31 deletions(-) create mode 100644 Polyhedron/demo/Polyhedron/CGAL_double_edit.cpp create mode 100644 Polyhedron/demo/Polyhedron/CGAL_double_edit.h diff --git a/Polyhedron/demo/Polyhedron/CGAL_double_edit.cpp b/Polyhedron/demo/Polyhedron/CGAL_double_edit.cpp new file mode 100644 index 00000000000..5536cafdd7d --- /dev/null +++ b/Polyhedron/demo/Polyhedron/CGAL_double_edit.cpp @@ -0,0 +1,14 @@ +#include "CGAL_double_edit.h" + +#include + + DoubleEdit::DoubleEdit(QWidget* parent = nullptr) + : QLineEdit(parent) + { + QDoubleValidator* validator = new QDoubleValidator(parent); + validator->setLocale(QLocale::C); + this->setValidator(validator); + } + + #include "CGAL_double_edit.moc" + diff --git a/Polyhedron/demo/Polyhedron/CGAL_double_edit.h b/Polyhedron/demo/Polyhedron/CGAL_double_edit.h new file mode 100644 index 00000000000..eb458dae263 --- /dev/null +++ b/Polyhedron/demo/Polyhedron/CGAL_double_edit.h @@ -0,0 +1,22 @@ +#ifndef CGAL_DOUBLE_EDIT_H +#define CGAL_DOUBLE_EDIT_H + + + +#include +#include +#include +#ifdef cgal_double_edit_EXPORTS +# define CGAL_DOUBLE_EDIT_EXPORT Q_DECL_EXPORT +#else +# define CGAL_DOUBLE_EDIT_EXPORT Q_DECL_IMPORT +#endif + +class CGAL_DOUBLE_EDIT_EXPORT DoubleEdit : public QLineEdit { + + Q_OBJECT + +public: + DoubleEdit(QWidget *parent); +}; +#endif // CGAL_DOUBLE_EDIT_H diff --git a/Polyhedron/demo/Polyhedron/CMakeLists.txt b/Polyhedron/demo/Polyhedron/CMakeLists.txt index fc4afa3bb09..6427dc55d7d 100644 --- a/Polyhedron/demo/Polyhedron/CMakeLists.txt +++ b/Polyhedron/demo/Polyhedron/CMakeLists.txt @@ -190,7 +190,8 @@ if(CGAL_Qt5_FOUND AND Qt5_FOUND) Scene_item_rendering_helper.cpp Scene_item_rendering_helper_moc.cpp Primitive_container.cpp - Polyhedron_demo_plugin_helper.cpp) + Polyhedron_demo_plugin_helper.cpp + CGAL_double_edit.cpp) target_link_libraries(demo_framework PUBLIC Qt5::OpenGL Qt5::Widgets Qt5::Gui Qt5::Script ) diff --git a/Polyhedron/demo/Polyhedron/Plugins/PMP/Isotropic_remeshing_dialog.ui b/Polyhedron/demo/Polyhedron/Plugins/PMP/Isotropic_remeshing_dialog.ui index 155c8331f9f..68b8ee3a92f 100644 --- a/Polyhedron/demo/Polyhedron/Plugins/PMP/Isotropic_remeshing_dialog.ui +++ b/Polyhedron/demo/Polyhedron/Plugins/PMP/Isotropic_remeshing_dialog.ui @@ -10,7 +10,7 @@ 0 0 376 - 368 + 369 @@ -98,9 +98,6 @@ Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter - - edgeLength_dspinbox - @@ -176,22 +173,6 @@ - - - - - 110 - 0 - - - - 1000.000000000000000 - - - 0.100000000000000 - - - @@ -208,6 +189,22 @@ + + + + Qt::ImhNone + + + + + + + + + 0.00 + + + @@ -239,9 +236,15 @@ + + + DoubleEdit + QLineEdit +

    CGAL_double_edit.h
    + + splitEdgesOnly_checkbox - edgeLength_dspinbox nbIterations_spinbox nbSmoothing_spinbox protect_checkbox diff --git a/Polyhedron/demo/Polyhedron/Plugins/PMP/Isotropic_remeshing_plugin.cpp b/Polyhedron/demo/Polyhedron/Plugins/PMP/Isotropic_remeshing_plugin.cpp index 8f1ec8d723e..f779addae8c 100644 --- a/Polyhedron/demo/Polyhedron/Plugins/PMP/Isotropic_remeshing_plugin.cpp +++ b/Polyhedron/demo/Polyhedron/Plugins/PMP/Isotropic_remeshing_plugin.cpp @@ -51,6 +51,7 @@ typedef Scene_surface_mesh_item Scene_facegraph_item; typedef Scene_facegraph_item::Face_graph FaceGraph; typedef boost::graph_traits::face_descriptor face_descriptor; + // give a halfedge and a target edge length, put in `out` points // which the edge equally spaced such that splitting the edge // using the sequence of points make the edges shorter than @@ -331,7 +332,7 @@ public Q_SLOTS: } bool edges_only = ui.splitEdgesOnly_checkbox->isChecked(); bool preserve_duplicates = ui.preserveDuplicates_checkbox->isChecked(); - double target_length = ui.edgeLength_dspinbox->value(); + double target_length = ui.edgeLength_dspinbox->text().toDouble(); unsigned int nb_iter = ui.nbIterations_spinbox->value(); unsigned int nb_smooth = ui.nbSmoothing_spinbox->value(); bool protect = ui.protect_checkbox->isChecked(); @@ -672,7 +673,7 @@ public Q_SLOTS: edges_only = ui.splitEdgesOnly_checkbox->isChecked(); preserve_duplicates = ui.preserveDuplicates_checkbox->isChecked(); - target_length = ui.edgeLength_dspinbox->value(); + target_length = ui.edgeLength_dspinbox->text().toDouble(); nb_iter = ui.nbIterations_spinbox->value(); protect = ui.protect_checkbox->isChecked(); smooth_features = ui.smooth1D_checkbox->isChecked(); @@ -904,14 +905,9 @@ private: 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->setText(tr("%1").arg(0.05 * diago_length)); std::ostringstream oss; oss << "Diagonal length of the Bbox of the selection to remesh is "; From 3b54dc2f923533f58864ac7e4e2acc619235c37a Mon Sep 17 00:00:00 2001 From: Maxime Gimeno Date: Tue, 15 Oct 2019 15:33:45 +0200 Subject: [PATCH 200/363] WIP Replace all double spin box. Remove resetRampButton as it hase become useless at some point. --- .../demo/Polyhedron/CGAL_double_edit.cpp | 29 +++++++++-- Polyhedron/demo/Polyhedron/CGAL_double_edit.h | 10 +++- .../Classification/Classification_plugin.cpp | 24 ++++----- .../Classification/Cluster_classification.cpp | 2 +- .../Point_set_item_classification.cpp | 2 +- .../Surface_mesh_item_classification.cpp | 2 +- .../Plugins/Display/Display_property.ui | 49 ++++++------------- .../Display/Display_property_plugin.cpp | 26 ---------- .../Point_set/Point_set_selection_plugin.cpp | 18 +++---- 9 files changed, 69 insertions(+), 93 deletions(-) diff --git a/Polyhedron/demo/Polyhedron/CGAL_double_edit.cpp b/Polyhedron/demo/Polyhedron/CGAL_double_edit.cpp index 5536cafdd7d..5878b1ac3fe 100644 --- a/Polyhedron/demo/Polyhedron/CGAL_double_edit.cpp +++ b/Polyhedron/demo/Polyhedron/CGAL_double_edit.cpp @@ -2,13 +2,36 @@ #include - DoubleEdit::DoubleEdit(QWidget* parent = nullptr) - : QLineEdit(parent) + DoubleEdit::DoubleEdit(QWidget *parent) + : QLineEdit() { - QDoubleValidator* validator = new QDoubleValidator(parent); + validator = new QDoubleValidator(this); validator->setLocale(QLocale::C); this->setValidator(validator); } + DoubleEdit::~DoubleEdit() + { + delete validator; + } + double DoubleEdit::value() const + { + return this->text().toDouble(); + } + + void DoubleEdit::setValue(double d) + { + this->setText(tr("%1").arg(d)); + } + + void DoubleEdit::setMinimum(double d) + { + this->validator->setBottom(d); + } + + void DoubleEdit::setMaximum(double d) + { + this->validator->setTop(d); + } #include "CGAL_double_edit.moc" diff --git a/Polyhedron/demo/Polyhedron/CGAL_double_edit.h b/Polyhedron/demo/Polyhedron/CGAL_double_edit.h index eb458dae263..11794728757 100644 --- a/Polyhedron/demo/Polyhedron/CGAL_double_edit.h +++ b/Polyhedron/demo/Polyhedron/CGAL_double_edit.h @@ -12,11 +12,19 @@ # define CGAL_DOUBLE_EDIT_EXPORT Q_DECL_IMPORT #endif +class QDoubleValidator; class CGAL_DOUBLE_EDIT_EXPORT DoubleEdit : public QLineEdit { Q_OBJECT public: - DoubleEdit(QWidget *parent); + DoubleEdit(QWidget* parent = nullptr); + ~DoubleEdit(); + double value() const; + void setValue(double d); + void setMinimum(double d); + void setMaximum(double d); +private: + QDoubleValidator* validator; }; #endif // CGAL_DOUBLE_EDIT_H diff --git a/Polyhedron/demo/Polyhedron/Plugins/Classification/Classification_plugin.cpp b/Polyhedron/demo/Polyhedron/Plugins/Classification/Classification_plugin.cpp index b02c0e2f14d..d561a3d5323 100644 --- a/Polyhedron/demo/Polyhedron/Plugins/Classification/Classification_plugin.cpp +++ b/Polyhedron/demo/Polyhedron/Plugins/Classification/Classification_plugin.cpp @@ -38,7 +38,7 @@ #include #include #include -#include +#include "CGAL_double_edit.h" #include #include @@ -619,17 +619,14 @@ public Q_SLOTS: scales->setRange (1, 99); scales->setValue (5); - QDoubleSpinBox* voxel_size = dialog.add ("Voxel size (0 for automatic):"); - voxel_size->setRange (0.0, 10000.0); - voxel_size->setValue (0.0); - voxel_size->setSingleStep (0.01); + DoubleEdit* voxel_size = dialog.add ("Voxel size (0 for automatic):"); if (dialog.exec() != QDialog::Accepted) return; QApplication::setOverrideCursor(Qt::WaitCursor); - float vsize = float(voxel_size->value()); + float vsize = float(voxel_size->text().toDouble()); if (vsize == 0.f) vsize = -1.f; // auto value @@ -921,10 +918,9 @@ public Q_SLOTS: subdivisions->setRange (1, 9999); subdivisions->setValue (16); - QDoubleSpinBox* smoothing = dialog.add ("Regularization weight: "); - smoothing->setRange (0.0, 100.0); - smoothing->setValue (0.5); - smoothing->setSingleStep (0.1); + DoubleEdit* smoothing = dialog.add ("Regularization weight: "); + + smoothing->setText(tr("%1").arg(0.5)); if (dialog.exec() != QDialog::Accepted) return; @@ -932,7 +928,7 @@ public Q_SLOTS: QApplication::setOverrideCursor(Qt::WaitCursor); CGAL::Real_timer t; t.start(); - run (classif, 2, std::size_t(subdivisions->value()), smoothing->value()); + run (classif, 2, std::size_t(subdivisions->value()), smoothing->text().toDouble()); t.stop(); std::cerr << "Graph Cut classification computed in " << t.time() << " second(s)" << std::endl; QApplication::restoreOverrideCursor(); @@ -1371,10 +1367,8 @@ public Q_SLOTS: QSpinBox* trials = dialog.add ("Number of trials: ", "trials"); trials->setRange (1, 99999); trials->setValue (500); - QDoubleSpinBox* rate = dialog.add ("Learning rate: ", "learning_rate"); - rate->setRange (0.00001, 10000.0); - rate->setValue (0.001); - rate->setDecimals (5); + DoubleEdit* rate = dialog.add ("Learning rate: ", "learning_rate"); + rate->setText(tr("%1").arg(0.001)); QSpinBox* batch = dialog.add ("Batch size: ", "batch_size"); batch->setRange (1, 2000000000); batch->setValue (1000); diff --git a/Polyhedron/demo/Polyhedron/Plugins/Classification/Cluster_classification.cpp b/Polyhedron/demo/Polyhedron/Plugins/Classification/Cluster_classification.cpp index d962e2f491d..2db5ec4b353 100644 --- a/Polyhedron/demo/Polyhedron/Plugins/Classification/Cluster_classification.cpp +++ b/Polyhedron/demo/Polyhedron/Plugins/Classification/Cluster_classification.cpp @@ -910,7 +910,7 @@ void Cluster_classification::train(int classifier, const QMultipleInputDialog& d m_neural_network->train (training, dialog.get("restart")->isChecked(), dialog.get("trials")->value(), - dialog.get("learning_rate")->value(), + dialog.get("learning_rate")->value(), dialog.get("batch_size")->value(), hidden_layers); diff --git a/Polyhedron/demo/Polyhedron/Plugins/Classification/Point_set_item_classification.cpp b/Polyhedron/demo/Polyhedron/Plugins/Classification/Point_set_item_classification.cpp index aee56b923e6..feb5779e208 100644 --- a/Polyhedron/demo/Polyhedron/Plugins/Classification/Point_set_item_classification.cpp +++ b/Polyhedron/demo/Polyhedron/Plugins/Classification/Point_set_item_classification.cpp @@ -800,7 +800,7 @@ void Point_set_item_classification::train(int classifier, const QMultipleInputDi m_neural_network->train (training, dialog.get("restart")->isChecked(), dialog.get("trials")->value(), - dialog.get("learning_rate")->value(), + dialog.get("learning_rate")->value(), dialog.get("batch_size")->value(), hidden_layers); 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 bdd3adbf9c5..2c032b631f9 100644 --- a/Polyhedron/demo/Polyhedron/Plugins/Classification/Surface_mesh_item_classification.cpp +++ b/Polyhedron/demo/Polyhedron/Plugins/Classification/Surface_mesh_item_classification.cpp @@ -366,7 +366,7 @@ void Surface_mesh_item_classification::train (int classifier, const QMultipleInp m_neural_network->train (training, dialog.get("restart")->isChecked(), dialog.get("trials")->value(), - dialog.get("learning_rate")->value(), + dialog.get("learning_rate")->value(), dialog.get("batch_size")->value(), hidden_layers); diff --git a/Polyhedron/demo/Polyhedron/Plugins/Display/Display_property.ui b/Polyhedron/demo/Polyhedron/Plugins/Display/Display_property.ui index 2513e099a25..d79b215e714 100644 --- a/Polyhedron/demo/Polyhedron/Plugins/Display/Display_property.ui +++ b/Polyhedron/demo/Polyhedron/Plugins/Display/Display_property.ui @@ -110,44 +110,18 @@ - - - - - - 2.000000000000000 + + + 0,00 - - - - - Qt::Horizontal - - - - 40 - 20 - - - - - - - - Compute Ramp Extremas - - - Reset - - - false - - - - + + + 2,00 + + @@ -223,6 +197,13 @@ + + + DoubleEdit + QLineEdit +
    CGAL_double_edit.h
    +
    +
    diff --git a/Polyhedron/demo/Polyhedron/Plugins/Display/Display_property_plugin.cpp b/Polyhedron/demo/Polyhedron/Plugins/Display/Display_property_plugin.cpp index 71ffd20d3df..df09bc33f2d 100644 --- a/Polyhedron/demo/Polyhedron/Plugins/Display/Display_property_plugin.cpp +++ b/Polyhedron/demo/Polyhedron/Plugins/Display/Display_property_plugin.cpp @@ -443,9 +443,6 @@ public: connect(dock_widget->deleteButton, &QPushButton::clicked, this, &DisplayPropertyPlugin::delete_group); - connect(dock_widget->resetButton, &QPushButton::pressed, - this, &DisplayPropertyPlugin::resetRampExtremas); - dock_widget->zoomToMaxButton->setEnabled(false); dock_widget->zoomToMinButton->setEnabled(false); Scene* scene_obj =static_cast(scene); @@ -464,29 +461,6 @@ private Q_SLOTS: dock_widget->raise(); } } - void resetRampExtremas() - { - Scene_surface_mesh_item* item = - qobject_cast(scene->item(scene->mainSelectionIndex())); - if(!item) - return; - QApplication::setOverrideCursor(Qt::WaitCursor); - item->face_graph()->collect_garbage(); - bool ok; - switch(dock_widget->propertyBox->currentIndex()) - { - case 0: - ok = resetAngles(item); - break; - default: - ok = resetScaledJacobian(item); - break; - } - QApplication::restoreOverrideCursor(); - if(!ok) - QMessageBox::warning(mw, "Error", "You must first run colorize once to initialize the values."); - } - void colorize() { Scene_heat_item* h_item = nullptr; 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 ebff326b116..45740cc84e3 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 @@ -32,7 +32,7 @@ #include #include -#include +#include "CGAL_double_edit.h" #include #include @@ -821,19 +821,15 @@ protected Q_SLOTS: return; QMultipleInputDialog dialog ("Region Selection Parameters", mw); - QDoubleSpinBox* epsilon = dialog.add ("Epsilon: "); - epsilon->setRange (0.00001, 1000000.); - epsilon->setDecimals (5); + DoubleEdit* epsilon = dialog.add ("Epsilon: "); if (rg_epsilon < 0.) rg_epsilon = (std::max)(0.00001, 0.005 * scene->len_diagonal()); - epsilon->setValue (rg_epsilon); + epsilon->setText(tr("%1").arg(rg_epsilon)); - QDoubleSpinBox* cluster_epsilon = dialog.add ("Cluster epsilon: "); - cluster_epsilon->setRange (0.00001, 1000000.); - cluster_epsilon->setDecimals (5); + DoubleEdit* cluster_epsilon = dialog.add ("Cluster epsilon: "); if (rg_cluster_epsilon < 0.) rg_cluster_epsilon = (std::max)(0.00001, 0.03 * scene->len_diagonal()); - cluster_epsilon->setValue (rg_cluster_epsilon); + cluster_epsilon->setText(tr("%1").arg(rg_cluster_epsilon)); QSpinBox* normal_threshold = dialog.add ("Normal threshold: "); normal_threshold->setRange (0, 90); @@ -842,8 +838,8 @@ protected Q_SLOTS: if (dialog.exec()) { - rg_epsilon = epsilon->value(); - rg_cluster_epsilon = cluster_epsilon->value(); + rg_epsilon = epsilon->text().toDouble(); + rg_cluster_epsilon = cluster_epsilon->text().toDouble(); rg_normal_threshold = normal_threshold->value(); } } From 264f2d1e06807d846ba43285775a0246ffd4f7ba Mon Sep 17 00:00:00 2001 From: Maxime Gimeno Date: Tue, 15 Oct 2019 16:30:00 +0200 Subject: [PATCH 201/363] finish replacing doublespinboxes --- .../demo/Polyhedron/CGAL_double_edit.cpp | 6 + Polyhedron/demo/Polyhedron/CGAL_double_edit.h | 1 + .../Plugins/Mesh_2/Mesh_2_plugin.cpp | 2 - .../Plugins/Mesh_2/mesh_2_dialog.ui | 35 +++--- .../Plugins/Mesh_3/Mesh_3_plugin.cpp | 4 - .../Plugins/Mesh_3/Meshing_dialog.ui | 112 ++++++------------ .../Plugins/PCA/Basic_generator_widget.ui | 52 ++++---- .../Plugins/PCA/MeshOnGrid_dialog.ui | 49 ++++---- .../Polyhedron/Plugins/PMP/Fairing_widget.ui | 19 +-- .../Plugins/PMP/Hole_filling_widget.ui | 24 ++-- .../Plugins/PMP/Random_perturbation_dialog.ui | 42 +++---- .../PMP/Random_perturbation_plugin.cpp | 4 - .../Plugins/PMP/Smoothing_plugin.cpp | 1 - .../Plugins/PMP/Smoothing_plugin.ui | 32 +++-- .../Point_set_to_mesh_distance_widget.ui | 24 ++-- .../Mesh_plane_detection_dialog.ui | 33 +++--- .../Surface_mesh/Mesh_segmentation_widget.ui | 41 +++---- .../Surface_mesh_deformation/Deform_mesh.ui | 17 ++- 18 files changed, 238 insertions(+), 260 deletions(-) diff --git a/Polyhedron/demo/Polyhedron/CGAL_double_edit.cpp b/Polyhedron/demo/Polyhedron/CGAL_double_edit.cpp index 5878b1ac3fe..fc4177cefc7 100644 --- a/Polyhedron/demo/Polyhedron/CGAL_double_edit.cpp +++ b/Polyhedron/demo/Polyhedron/CGAL_double_edit.cpp @@ -33,5 +33,11 @@ { this->validator->setTop(d); } + + void DoubleEdit::setRange(double min, double max) + { + setMinimum(min); + setMaximum(max); + } #include "CGAL_double_edit.moc" diff --git a/Polyhedron/demo/Polyhedron/CGAL_double_edit.h b/Polyhedron/demo/Polyhedron/CGAL_double_edit.h index 11794728757..4ec17b28bcd 100644 --- a/Polyhedron/demo/Polyhedron/CGAL_double_edit.h +++ b/Polyhedron/demo/Polyhedron/CGAL_double_edit.h @@ -24,6 +24,7 @@ public: void setValue(double d); void setMinimum(double d); void setMaximum(double d); + void setRange(double min, double max); private: QDoubleValidator* validator; }; diff --git a/Polyhedron/demo/Polyhedron/Plugins/Mesh_2/Mesh_2_plugin.cpp b/Polyhedron/demo/Polyhedron/Plugins/Mesh_2/Mesh_2_plugin.cpp index c007f78408f..6053d4a236f 100644 --- a/Polyhedron/demo/Polyhedron/Plugins/Mesh_2/Mesh_2_plugin.cpp +++ b/Polyhedron/demo/Polyhedron/Plugins/Mesh_2/Mesh_2_plugin.cpp @@ -195,8 +195,6 @@ private: ui.edgeLength_dspinbox, SLOT(setEnabled(bool))); //Set default parameter edge length - ui.edgeLength_dspinbox->setDecimals(3); - ui.edgeLength_dspinbox->setSingleStep(0.001); ui.edgeLength_dspinbox->setRange(1e-6 * diag_length, //min 2. * diag_length);//max ui.edgeLength_dspinbox->setValue(0.05 * diag_length); diff --git a/Polyhedron/demo/Polyhedron/Plugins/Mesh_2/mesh_2_dialog.ui b/Polyhedron/demo/Polyhedron/Plugins/Mesh_2/mesh_2_dialog.ui index 566c4df41c5..bbcb20b1949 100644 --- a/Polyhedron/demo/Polyhedron/Plugins/Mesh_2/mesh_2_dialog.ui +++ b/Polyhedron/demo/Polyhedron/Plugins/Mesh_2/mesh_2_dialog.ui @@ -10,7 +10,7 @@ 0 0 424 - 301 + 302 @@ -38,9 +38,6 @@ Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter - - edgeLength_dspinbox - @@ -56,22 +53,6 @@ - - - - - 110 - 0 - - - - 1000.000000000000000 - - - 0.100000000000000 - - - @@ -157,6 +138,13 @@ + + + + 0,00 + + + @@ -185,6 +173,13 @@ + + + DoubleEdit + QLineEdit +
    CGAL_double_edit.h
    +
    +
    buttonBox diff --git a/Polyhedron/demo/Polyhedron/Plugins/Mesh_3/Mesh_3_plugin.cpp b/Polyhedron/demo/Polyhedron/Plugins/Mesh_3/Mesh_3_plugin.cpp index 7b3324cc49d..efaf2d3b819 100644 --- a/Polyhedron/demo/Polyhedron/Plugins/Mesh_3/Mesh_3_plugin.cpp +++ b/Polyhedron/demo/Polyhedron/Plugins/Mesh_3/Mesh_3_plugin.cpp @@ -361,8 +361,6 @@ void Mesh_3_plugin::mesh_3(const bool surface_only, const bool use_defaults) double diag = 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())); int decimals = 0; double sizing_default = get_approximate(diag * 0.05, 2, decimals); - ui.facetSizing->setDecimals(-decimals+2); - ui.facetSizing->setSingleStep(std::pow(10.,decimals)); ui.facetSizing->setRange(diag * 10e-6, // min diag); // max ui.facetSizing->setValue(sizing_default); // default value @@ -375,8 +373,6 @@ void Mesh_3_plugin::mesh_3(const bool surface_only, const bool use_defaults) ui.tetSizing->setValue(sizing_default); // default value double approx_default = get_approximate(diag * 0.005, 2, decimals); - ui.approx->setDecimals(-decimals+2); - ui.approx->setSingleStep(std::pow(10.,decimals)); ui.approx->setRange(diag * 10e-7, // min diag); // max ui.approx->setValue(approx_default); diff --git a/Polyhedron/demo/Polyhedron/Plugins/Mesh_3/Meshing_dialog.ui b/Polyhedron/demo/Polyhedron/Plugins/Mesh_3/Meshing_dialog.ui index 56e918bf8b8..a0a34411242 100644 --- a/Polyhedron/demo/Polyhedron/Plugins/Mesh_3/Meshing_dialog.ui +++ b/Polyhedron/demo/Polyhedron/Plugins/Mesh_3/Meshing_dialog.ui @@ -115,9 +115,6 @@ Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter - - sharpEdgesAngle - @@ -128,9 +125,6 @@ Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter - - edgeSizing - @@ -140,29 +134,6 @@ - - - - 4 - - - 0.000000000000000 - - - 0.000000000000000 - - - - - - - 180.000000000000000 - - - 60.000000000000000 - - - @@ -186,6 +157,20 @@ + + + + 60,00 + + + + + + + 0,0 + + + @@ -216,9 +201,6 @@ Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter - - approx - @@ -234,16 +216,6 @@ - - - - - 110 - 0 - - - - @@ -252,22 +224,6 @@ Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter - - facetAngle - - - - - - - - 110 - 0 - - - - 4 - @@ -359,27 +315,25 @@ Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter - - facetSizing + + + + + + 0,00 + + + - - - - 110 - 0 - + + + 25,00 - - 0.000000000000000 - - - 30.000000000000000 - - - 25.000000000000000 + + 25,00 @@ -597,12 +551,16 @@ + + + DoubleEdit + QLineEdit +
    CGAL_double_edit.h
    +
    +
    - approx noApprox - facetSizing noFacetSizing - facetAngle noAngle tetSizing noTetSizing diff --git a/Polyhedron/demo/Polyhedron/Plugins/PCA/Basic_generator_widget.ui b/Polyhedron/demo/Polyhedron/Plugins/PCA/Basic_generator_widget.ui index 4e215cf956f..cc3a3fedc6a 100644 --- a/Polyhedron/demo/Polyhedron/Plugins/PCA/Basic_generator_widget.ui +++ b/Polyhedron/demo/Polyhedron/Plugins/PCA/Basic_generator_widget.ui @@ -31,7 +31,7 @@ - :/cgal/Polyhedron_3/resources/prism.png + :/cgal/Polyhedron_3/resources/prism.png false @@ -136,15 +136,9 @@ QGroupBox::title { - - - 5 - - - 1000000000000000000.000000000000000 - - - 1.000000000000000 + + + 1,00 @@ -163,15 +157,9 @@ QGroupBox::title { - - - 5 - - - 1000000000000000000.000000000000000 - - - 1.000000000000000 + + + 1,00 @@ -235,7 +223,7 @@ QGroupBox::title { - :/cgal/Polyhedron_3/resources/icosphere.png + :/cgal/Polyhedron_3/resources/icosphere.png @@ -558,7 +546,7 @@ QGroupBox::title { - :/cgal/Polyhedron_3/resources/hexahedron.png + :/cgal/Polyhedron_3/resources/hexahedron.png false @@ -768,7 +756,7 @@ QGroupBox::title { - :/cgal/Polyhedron_3/resources/tetrahedron.png + :/cgal/Polyhedron_3/resources/tetrahedron.png @@ -899,7 +887,7 @@ QGroupBox::title { - :/cgal/Polyhedron_3/resources/grid.png + :/cgal/Polyhedron_3/resources/grid.png @@ -1068,7 +1056,7 @@ QGroupBox::title { <html><head><meta name="qrichtext" content="1" /><style type="text/css"> 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="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:10pt;"><br /></p></body></html> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'Sans Serif'; font-size:10pt;"><br /></p></body></html> false @@ -1105,7 +1093,7 @@ p, li { white-space: pre-wrap; } <html><head><meta name="qrichtext" content="1" /><style type="text/css"> 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="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:10pt;"><br /></p></body></html> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'Sans Serif'; font-size:10pt;"><br /></p></body></html> false @@ -1183,11 +1171,13 @@ p, li { white-space: pre-wrap; } - - - - - - + + + DoubleEdit + QLineEdit +
    CGAL_double_edit.h
    +
    +
    + diff --git a/Polyhedron/demo/Polyhedron/Plugins/PCA/MeshOnGrid_dialog.ui b/Polyhedron/demo/Polyhedron/Plugins/PCA/MeshOnGrid_dialog.ui index f4ae9f081f0..392c3820a15 100644 --- a/Polyhedron/demo/Polyhedron/Plugins/PCA/MeshOnGrid_dialog.ui +++ b/Polyhedron/demo/Polyhedron/Plugins/PCA/MeshOnGrid_dialog.ui @@ -26,13 +26,6 @@ Along X
    - - - - 99999999999999999475366575191804932315794610450682175621941694731908308538307845136842752.000000000000000 - - - @@ -57,6 +50,13 @@ + + + + 0,00 + + + @@ -66,13 +66,6 @@ Along Y - - - - 99999999999999999475366575191804932315794610450682175621941694731908308538307845136842752.000000000000000 - - - @@ -97,6 +90,13 @@ + + + + 0,00 + + + @@ -106,13 +106,6 @@ Along Z - - - - 99999999999999999475366575191804932315794610450682175621941694731908308538307845136842752.000000000000000 - - - @@ -137,6 +130,13 @@ + + + + 0,00 + + + @@ -165,6 +165,13 @@ + + + DoubleEdit + QLineEdit +
    CGAL_double_edit.h
    +
    +
    diff --git a/Polyhedron/demo/Polyhedron/Plugins/PMP/Fairing_widget.ui b/Polyhedron/demo/Polyhedron/Plugins/PMP/Fairing_widget.ui index 0b516bbf303..ec17b2f7811 100644 --- a/Polyhedron/demo/Polyhedron/Plugins/PMP/Fairing_widget.ui +++ b/Polyhedron/demo/Polyhedron/Plugins/PMP/Fairing_widget.ui @@ -99,15 +99,9 @@ - - - 96.989999999999995 - - - 0.200000000000000 - - - 2.410000000000000 + + + 2,41 @@ -139,6 +133,13 @@ + + + DoubleEdit + QLineEdit +
    CGAL_double_edit.h
    +
    +
    diff --git a/Polyhedron/demo/Polyhedron/Plugins/PMP/Hole_filling_widget.ui b/Polyhedron/demo/Polyhedron/Plugins/PMP/Hole_filling_widget.ui index 40f8d143cf7..b6470ecb123 100644 --- a/Polyhedron/demo/Polyhedron/Plugins/PMP/Hole_filling_widget.ui +++ b/Polyhedron/demo/Polyhedron/Plugins/PMP/Hole_filling_widget.ui @@ -123,15 +123,18 @@ - - - 96.989999999999995 + + + + 0 + 0 + - - 0.200000000000000 + + 1,41 - - 1.410000000000000 + + Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter @@ -333,6 +336,13 @@ + + + DoubleEdit + QLineEdit +
    CGAL_double_edit.h
    +
    +
    diff --git a/Polyhedron/demo/Polyhedron/Plugins/PMP/Random_perturbation_dialog.ui b/Polyhedron/demo/Polyhedron/Plugins/PMP/Random_perturbation_dialog.ui index 3013e3b95dd..db2891e8c6d 100644 --- a/Polyhedron/demo/Polyhedron/Plugins/PMP/Random_perturbation_dialog.ui +++ b/Polyhedron/demo/Polyhedron/Plugins/PMP/Random_perturbation_dialog.ui @@ -10,7 +10,7 @@ 0 0 377 - 292 + 293 @@ -55,9 +55,6 @@ Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter - - moveSize_dspinbox - @@ -70,22 +67,6 @@ - - - - - 110 - 0 - - - - 1000.000000000000000 - - - 0.100000000000000 - - - @@ -96,6 +77,19 @@ + + + + + 0 + 0 + + + + 0,00 + + + @@ -198,8 +192,14 @@ + + + DoubleEdit + QLineEdit +
    CGAL_double_edit.h
    +
    +
    - moveSize_dspinbox project_checkbox buttonBox diff --git a/Polyhedron/demo/Polyhedron/Plugins/PMP/Random_perturbation_plugin.cpp b/Polyhedron/demo/Polyhedron/Plugins/PMP/Random_perturbation_plugin.cpp index c7f58900e67..f5ee0e486c8 100644 --- a/Polyhedron/demo/Polyhedron/Plugins/PMP/Random_perturbation_plugin.cpp +++ b/Polyhedron/demo/Polyhedron/Plugins/PMP/Random_perturbation_plugin.cpp @@ -196,12 +196,8 @@ public Q_SLOTS: 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); //parameters - ui.moveSize_dspinbox->setDecimals(nb_decimals); - ui.moveSize_dspinbox->setSingleStep(1e-3); ui.moveSize_dspinbox->setRange(0., diago_length); ui.moveSize_dspinbox->setValue(0.05 * diago_length); diff --git a/Polyhedron/demo/Polyhedron/Plugins/PMP/Smoothing_plugin.cpp b/Polyhedron/demo/Polyhedron/Plugins/PMP/Smoothing_plugin.cpp index 98c9059b02b..3f463f6ce60 100644 --- a/Polyhedron/demo/Polyhedron/Plugins/PMP/Smoothing_plugin.cpp +++ b/Polyhedron/demo/Polyhedron/Plugins/PMP/Smoothing_plugin.cpp @@ -95,7 +95,6 @@ public: void init_ui() { ui_widget.time_step_spinBox->setValue(0.00001); - ui_widget.time_step_spinBox->setSingleStep(0.00001); ui_widget.time_step_spinBox->setMinimum(1e-6); ui_widget.smooth_iter_spinBox->setValue(1); diff --git a/Polyhedron/demo/Polyhedron/Plugins/PMP/Smoothing_plugin.ui b/Polyhedron/demo/Polyhedron/Plugins/PMP/Smoothing_plugin.ui index a67bce5ef47..ccb455625a9 100644 --- a/Polyhedron/demo/Polyhedron/Plugins/PMP/Smoothing_plugin.ui +++ b/Polyhedron/demo/Polyhedron/Plugins/PMP/Smoothing_plugin.ui @@ -31,13 +31,13 @@ Shape Smoothing - - - - 6 + + + + The time step should not be too large or the smoothing will be unsatisfactory - - 0.000001000000000 + + Time Step: @@ -48,13 +48,16 @@ - - - - The time step should not be too large or the smoothing will be unsatisfactory + + + + + 0 + 0 + - Time Step: + 0,000001 @@ -173,6 +176,13 @@ + + + DoubleEdit + QLineEdit +
    CGAL_double_edit.h
    +
    +
    diff --git a/Polyhedron/demo/Polyhedron/Plugins/Point_set/Point_set_to_mesh_distance_widget.ui b/Polyhedron/demo/Polyhedron/Plugins/Point_set/Point_set_to_mesh_distance_widget.ui index 9b90b30d4e5..34c678aae20 100644 --- a/Polyhedron/demo/Polyhedron/Plugins/Point_set/Point_set_to_mesh_distance_widget.ui +++ b/Polyhedron/demo/Polyhedron/Plugins/Point_set/Point_set_to_mesh_distance_widget.ui @@ -140,16 +140,6 @@ - - - - Points further than this distance will be selected. - - - 6 - - - @@ -167,6 +157,13 @@ + + + + 0,00 + + + @@ -190,6 +187,13 @@ + + + DoubleEdit + QLineEdit +
    CGAL_double_edit.h
    +
    +
    diff --git a/Polyhedron/demo/Polyhedron/Plugins/Surface_mesh/Mesh_plane_detection_dialog.ui b/Polyhedron/demo/Polyhedron/Plugins/Surface_mesh/Mesh_plane_detection_dialog.ui index 9e7625e4af3..41487bf5351 100644 --- a/Polyhedron/demo/Polyhedron/Plugins/Surface_mesh/Mesh_plane_detection_dialog.ui +++ b/Polyhedron/demo/Polyhedron/Plugins/Surface_mesh/Mesh_plane_detection_dialog.ui @@ -23,25 +23,6 @@ - - - - 5 - - - 0.000010000000000 - - - 1000000.000000000000000 - - - 0.010000000000000 - - - 0.010000000000000 - - - @@ -65,6 +46,13 @@ + + + + 0,01 + + + @@ -92,6 +80,13 @@ + + + DoubleEdit + QLineEdit +
    CGAL_double_edit.h
    +
    +
    diff --git a/Polyhedron/demo/Polyhedron/Plugins/Surface_mesh/Mesh_segmentation_widget.ui b/Polyhedron/demo/Polyhedron/Plugins/Surface_mesh/Mesh_segmentation_widget.ui index b2d0588f42c..485397d80dc 100644 --- a/Polyhedron/demo/Polyhedron/Plugins/Surface_mesh/Mesh_segmentation_widget.ui +++ b/Polyhedron/demo/Polyhedron/Plugins/Surface_mesh/Mesh_segmentation_widget.ui @@ -31,13 +31,6 @@ - - - - 25 - - - @@ -58,6 +51,13 @@ + + + + 25 + + + @@ -100,19 +100,6 @@ - - - - 10.000000000000000 - - - 0.010000000000000 - - - 0.260000000000000 - - - @@ -136,6 +123,13 @@ + + + + 0,26 + + + @@ -194,6 +188,13 @@ + + + DoubleEdit + QLineEdit +
    CGAL_double_edit.h
    +
    +
    diff --git a/Polyhedron/demo/Polyhedron/Plugins/Surface_mesh_deformation/Deform_mesh.ui b/Polyhedron/demo/Polyhedron/Plugins/Surface_mesh_deformation/Deform_mesh.ui index 28d648d8c43..64126a6c88b 100644 --- a/Polyhedron/demo/Polyhedron/Plugins/Surface_mesh_deformation/Deform_mesh.ui +++ b/Polyhedron/demo/Polyhedron/Plugins/Surface_mesh_deformation/Deform_mesh.ui @@ -18,7 +18,7 @@ - 0 + 1 @@ -199,7 +199,7 @@ - + @@ -214,7 +214,11 @@ - + + + 0,00 + + @@ -435,6 +439,13 @@ + + + DoubleEdit + QLineEdit +
    CGAL_double_edit.h
    +
    +
    From 74db722b965ff5ae8e43acc9ca0095fb4164942f Mon Sep 17 00:00:00 2001 From: Maxime Gimeno Date: Wed, 16 Oct 2019 11:04:40 +0200 Subject: [PATCH 202/363] fixes after review + new batch of transformations --- .../demo/Polyhedron/CGAL_double_edit.cpp | 34 +++- Polyhedron/demo/Polyhedron/CGAL_double_edit.h | 13 +- .../Classification/Classification_plugin.cpp | 7 +- .../Plugins/Display/Display_property.ui | 4 +- .../Plugins/Mesh_2/mesh_2_dialog.ui | 2 +- .../Plugins/Mesh_3/Local_optimizers_dialog.ui | 90 ++++----- .../Plugins/Mesh_3/Mesh_3_plugin.cpp | 5 +- .../Plugins/Mesh_3/Meshing_dialog.ui | 85 +++------ .../Polyhedron/Plugins/Mesh_3/Rib_dialog.ui | 89 +++++---- .../Plugins/Mesh_3/Smoother_dialog.ui | 93 +++------- .../Plugins/PCA/Basic_generator_widget.ui | 46 ++--- .../Plugins/PCA/MeshOnGrid_dialog.ui | 6 +- .../Polyhedron/Plugins/PMP/Fairing_widget.ui | 2 +- .../Plugins/PMP/Hole_filling_widget.ui | 17 +- .../PMP/Isotropic_remeshing_plugin.cpp | 6 +- .../Mean_curvature_flow_skeleton_plugin.cpp | 8 - .../Mean_curvature_flow_skeleton_plugin.ui | 59 +++++- .../Plugins/PMP/Random_perturbation_dialog.ui | 2 +- .../Plugins/PMP/Smoothing_plugin.ui | 2 +- .../Point_set/Features_detection_plugin.ui | 62 ++++--- .../Point_set_normal_estimation_plugin.ui | 55 +++--- .../Point_set_outliers_removal_plugin.ui | 25 +-- .../Point_set/Point_set_selection_plugin.cpp | 6 +- .../Point_set_shape_detection_plugin.ui | 133 +++++-------- .../Point_set_simplification_plugin.cpp | 1 + .../Point_set_simplification_plugin.ui | 135 +++++++------- .../Point_set_to_mesh_distance_widget.ui | 2 +- .../Point_set/Point_set_upsampling_plugin.cpp | 1 + .../Point_set/Point_set_upsampling_plugin.ui | 168 ++++++++--------- .../Surface_reconstruction_plugin.ui | 3 +- .../Mesh_plane_detection_dialog.ui | 2 +- .../Surface_mesh/Mesh_segmentation_widget.ui | 2 +- .../Mesh_simplification_dialog.ui | 19 +- .../Surface_mesh/Offset_meshing_plugin.cpp | 3 +- .../Plugins/Surface_mesh/Remeshing_dialog.ui | 112 ++++++----- .../Surface_mesh_approximation_dockwidget.ui | 174 +++++++----------- .../Surface_mesh_approximation_plugin.cpp | 2 + .../Surface_mesh_deformation/Deform_mesh.ui | 4 +- 38 files changed, 664 insertions(+), 815 deletions(-) diff --git a/Polyhedron/demo/Polyhedron/CGAL_double_edit.cpp b/Polyhedron/demo/Polyhedron/CGAL_double_edit.cpp index fc4177cefc7..a631b7e01c5 100644 --- a/Polyhedron/demo/Polyhedron/CGAL_double_edit.cpp +++ b/Polyhedron/demo/Polyhedron/CGAL_double_edit.cpp @@ -2,11 +2,32 @@ #include - DoubleEdit::DoubleEdit(QWidget *parent) - : QLineEdit() +class DoubleValidator : public QDoubleValidator +{ +public: + DoubleValidator(QObject* parent = nullptr) + : QDoubleValidator(parent) { - validator = new QDoubleValidator(this); - validator->setLocale(QLocale::C); + setLocale(QLocale::C); + } + + void fixup ( QString & input ) const + { + input.replace(".", locale().decimalPoint()); + input.replace(",", locale().decimalPoint()); + QDoubleValidator::fixup(input); + } + QValidator::State validate ( QString & input, int & pos ) const + { + fixup(input); + return QDoubleValidator::validate(input, pos); + } +}; + + DoubleEdit::DoubleEdit(QWidget *parent) + : QLineEdit(parent) + { + validator = new DoubleValidator(this); this->setValidator(validator); } @@ -14,6 +35,8 @@ { delete validator; } + + double DoubleEdit::value() const { return this->text().toDouble(); @@ -36,8 +59,7 @@ void DoubleEdit::setRange(double min, double max) { - setMinimum(min); - setMaximum(max); + this->validator->setRange(min, max); } #include "CGAL_double_edit.moc" diff --git a/Polyhedron/demo/Polyhedron/CGAL_double_edit.h b/Polyhedron/demo/Polyhedron/CGAL_double_edit.h index 4ec17b28bcd..0cacb15ea49 100644 --- a/Polyhedron/demo/Polyhedron/CGAL_double_edit.h +++ b/Polyhedron/demo/Polyhedron/CGAL_double_edit.h @@ -6,14 +6,11 @@ #include #include #include -#ifdef cgal_double_edit_EXPORTS -# define CGAL_DOUBLE_EDIT_EXPORT Q_DECL_EXPORT -#else -# define CGAL_DOUBLE_EDIT_EXPORT Q_DECL_IMPORT -#endif +#include "Scene_config.h" -class QDoubleValidator; -class CGAL_DOUBLE_EDIT_EXPORT DoubleEdit : public QLineEdit { + +class DoubleValidator; +class SCENE_EXPORT DoubleEdit : public QLineEdit { Q_OBJECT @@ -26,6 +23,6 @@ public: void setMaximum(double d); void setRange(double min, double max); private: - QDoubleValidator* validator; + DoubleValidator* validator; }; #endif // CGAL_DOUBLE_EDIT_H diff --git a/Polyhedron/demo/Polyhedron/Plugins/Classification/Classification_plugin.cpp b/Polyhedron/demo/Polyhedron/Plugins/Classification/Classification_plugin.cpp index d561a3d5323..7ae9229ba59 100644 --- a/Polyhedron/demo/Polyhedron/Plugins/Classification/Classification_plugin.cpp +++ b/Polyhedron/demo/Polyhedron/Plugins/Classification/Classification_plugin.cpp @@ -626,7 +626,7 @@ public Q_SLOTS: QApplication::setOverrideCursor(Qt::WaitCursor); - float vsize = float(voxel_size->text().toDouble()); + float vsize = float(voxel_size->value()); if (vsize == 0.f) vsize = -1.f; // auto value @@ -928,7 +928,7 @@ public Q_SLOTS: QApplication::setOverrideCursor(Qt::WaitCursor); CGAL::Real_timer t; t.start(); - run (classif, 2, std::size_t(subdivisions->value()), smoothing->text().toDouble()); + run (classif, 2, std::size_t(subdivisions->value()), smoothing->value()); t.stop(); std::cerr << "Graph Cut classification computed in " << t.time() << " second(s)" << std::endl; QApplication::restoreOverrideCursor(); @@ -1368,7 +1368,8 @@ public Q_SLOTS: trials->setRange (1, 99999); trials->setValue (500); DoubleEdit* rate = dialog.add ("Learning rate: ", "learning_rate"); - rate->setText(tr("%1").arg(0.001)); + rate->setRange (0.00001, 10000.0); + rate->setValue (0.001); QSpinBox* batch = dialog.add ("Batch size: ", "batch_size"); batch->setRange (1, 2000000000); batch->setValue (1000); diff --git a/Polyhedron/demo/Polyhedron/Plugins/Display/Display_property.ui b/Polyhedron/demo/Polyhedron/Plugins/Display/Display_property.ui index d79b215e714..95538bdfcff 100644 --- a/Polyhedron/demo/Polyhedron/Plugins/Display/Display_property.ui +++ b/Polyhedron/demo/Polyhedron/Plugins/Display/Display_property.ui @@ -112,14 +112,14 @@ - 0,00 + 0.00 - 2,00 + 2.00 diff --git a/Polyhedron/demo/Polyhedron/Plugins/Mesh_2/mesh_2_dialog.ui b/Polyhedron/demo/Polyhedron/Plugins/Mesh_2/mesh_2_dialog.ui index bbcb20b1949..b809786a2b6 100644 --- a/Polyhedron/demo/Polyhedron/Plugins/Mesh_2/mesh_2_dialog.ui +++ b/Polyhedron/demo/Polyhedron/Plugins/Mesh_2/mesh_2_dialog.ui @@ -141,7 +141,7 @@ - 0,00 + 0.00 diff --git a/Polyhedron/demo/Polyhedron/Plugins/Mesh_3/Local_optimizers_dialog.ui b/Polyhedron/demo/Polyhedron/Plugins/Mesh_3/Local_optimizers_dialog.ui index 7b910b9acf3..b9b36481a0b 100644 --- a/Polyhedron/demo/Polyhedron/Plugins/Mesh_3/Local_optimizers_dialog.ui +++ b/Polyhedron/demo/Polyhedron/Plugins/Mesh_3/Local_optimizers_dialog.ui @@ -6,7 +6,7 @@ 0 0 - 546 + 556 317 @@ -50,43 +50,11 @@ Parameters - - - + + + - Max CPU running time (s) - - - Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter - - - maxTime - - - - - - - - 100 - 0 - - - - 1 - - - 9999.000000000000000 - - - 60.000000000000000 - - - - - - - No time limit + No angle bound @@ -98,37 +66,36 @@ Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter - - sliverBound + + + + + + No time limit - - - - - 100 - 0 - + + + + Max CPU running time (s) - - false + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter - - 1 - - - 180.000000000000000 - - - 8.000000000000000 + + + + + + 60.0 - + - No angle bound + 8.0 @@ -180,6 +147,13 @@ + + + DoubleEdit + QLineEdit +
    CGAL_double_edit.h
    +
    +
    diff --git a/Polyhedron/demo/Polyhedron/Plugins/Mesh_3/Mesh_3_plugin.cpp b/Polyhedron/demo/Polyhedron/Plugins/Mesh_3/Mesh_3_plugin.cpp index efaf2d3b819..26d6d59792e 100644 --- a/Polyhedron/demo/Polyhedron/Plugins/Mesh_3/Mesh_3_plugin.cpp +++ b/Polyhedron/demo/Polyhedron/Plugins/Mesh_3/Mesh_3_plugin.cpp @@ -293,6 +293,9 @@ void Mesh_3_plugin::mesh_3(const bool surface_only, const bool use_defaults) Ui::Meshing_dialog ui; ui.setupUi(&dialog); + ui.facetAngle->setRange(0.0, 20.0); + ui.facetAngle->setValue(25.0); + ui.advanced->setVisible(false); connect(ui.facetTopologyLabel, &QLabel::linkActivated, @@ -366,8 +369,6 @@ void Mesh_3_plugin::mesh_3(const bool surface_only, const bool use_defaults) ui.facetSizing->setValue(sizing_default); // default value ui.edgeSizing->setValue(sizing_default); - ui.tetSizing->setDecimals(-decimals+2); - ui.tetSizing->setSingleStep(std::pow(10.,decimals)); ui.tetSizing->setRange(diag * 10e-6, // min diag); // max ui.tetSizing->setValue(sizing_default); // default value diff --git a/Polyhedron/demo/Polyhedron/Plugins/Mesh_3/Meshing_dialog.ui b/Polyhedron/demo/Polyhedron/Plugins/Mesh_3/Meshing_dialog.ui index a0a34411242..a29054048fa 100644 --- a/Polyhedron/demo/Polyhedron/Plugins/Mesh_3/Meshing_dialog.ui +++ b/Polyhedron/demo/Polyhedron/Plugins/Mesh_3/Meshing_dialog.ui @@ -160,14 +160,14 @@ - 60,00 + 60.00 - 0,0 + 0.0 @@ -320,7 +320,7 @@ - 0,00 + 0.00 @@ -372,35 +372,6 @@
    - - - - - 110 - 0 - - - - 1.000000000000000 - - - 3.000000000000000 - - - - - - - - 110 - 0 - - - - 4 - - - @@ -409,9 +380,6 @@ Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter - - tetShape - @@ -422,8 +390,19 @@ Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter - - tetSizing + + + + + + 0.00 + + + + + + + 3.00 @@ -458,22 +437,6 @@ - - - - -65536.000000000000000 - - - 65536.000000000000000 - - - 3.000000000000000 - - - - - - @@ -513,6 +476,20 @@ + + + + 0.00 + + + + + + + 3.00 + + + @@ -562,9 +539,7 @@ noApprox noFacetSizing noAngle - tetSizing noTetSizing - tetShape noTetShape checkBox manifoldCheckBox diff --git a/Polyhedron/demo/Polyhedron/Plugins/Mesh_3/Rib_dialog.ui b/Polyhedron/demo/Polyhedron/Plugins/Mesh_3/Rib_dialog.ui index 03a4514d7b6..c3639f5115a 100644 --- a/Polyhedron/demo/Polyhedron/Plugins/Mesh_3/Rib_dialog.ui +++ b/Polyhedron/demo/Polyhedron/Plugins/Mesh_3/Rib_dialog.ui @@ -22,20 +22,6 @@ - - - - 4 - - - - - - - 4 - - - @@ -50,6 +36,20 @@ + + + + 0.00 + + + + + + + 0.00 + + + @@ -70,13 +70,6 @@ - - - - Ambient Light - - - @@ -87,29 +80,10 @@ - - - - 1.000000000000000 - - - 0.010000000000000 - - - 0.150000000000000 - - - - - - - 1.000000000000000 - - - 0.010000000000000 - - - 0.850000000000000 + + + + Shadow Light @@ -123,10 +97,24 @@ - - + + - Shadow Light + Ambient Light + + + + + + + 0.15 + + + + + + + 0.85 @@ -245,6 +233,13 @@ + + + DoubleEdit + QLineEdit +
    CGAL_double_edit.h
    +
    +
    diff --git a/Polyhedron/demo/Polyhedron/Plugins/Mesh_3/Smoother_dialog.ui b/Polyhedron/demo/Polyhedron/Plugins/Mesh_3/Smoother_dialog.ui index 1f4fdcc0a8f..85ee2953a27 100644 --- a/Polyhedron/demo/Polyhedron/Plugins/Mesh_3/Smoother_dialog.ui +++ b/Polyhedron/demo/Polyhedron/Plugins/Mesh_3/Smoother_dialog.ui @@ -7,7 +7,7 @@ 0 0 507 - 328 + 331 @@ -50,7 +50,7 @@ Parameters - + 8 @@ -68,9 +68,6 @@ Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter - - maxTime -
    @@ -84,21 +81,9 @@ - - - - 100 - 0 - - - - 1 - - - 9999.000000000000000 - - - 60.000000000000000 + + + 60.0 @@ -122,7 +107,7 @@ false - + 8 @@ -148,19 +133,6 @@
    - - - - 0 - - - 200.000000000000000 - - - 100.000000000000000 - - - @@ -177,22 +149,6 @@ - - - - 4 - - - 0.000100000000000 - - - 1.000000000000000 - - - 0.010000000000000 - - - @@ -207,27 +163,29 @@ Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter - - freezeRatio + + + + + + 0.001 - - - - 4 - - - 0.000000000000000 + + + + 0.000 + + + + - 1.000000000000000 - - - 0.001000000000000 + 200 - 0.000000000000000 + 100 @@ -279,6 +237,13 @@
    + + + DoubleEdit + QLineEdit +
    CGAL_double_edit.h
    +
    +
    diff --git a/Polyhedron/demo/Polyhedron/Plugins/PCA/Basic_generator_widget.ui b/Polyhedron/demo/Polyhedron/Plugins/PCA/Basic_generator_widget.ui index cc3a3fedc6a..865622d53a5 100644 --- a/Polyhedron/demo/Polyhedron/Plugins/PCA/Basic_generator_widget.ui +++ b/Polyhedron/demo/Polyhedron/Plugins/PCA/Basic_generator_widget.ui @@ -18,7 +18,7 @@ - 0 + 2 @@ -138,7 +138,7 @@ QGroupBox::title { - 1,00 + 1.00 @@ -159,7 +159,7 @@ QGroupBox::title { - 1,00 + 1.00 @@ -412,18 +412,15 @@ QGroupBox::title { - - - 5 + + + + 0 + 0 + - - -999999.000000000000000 - - - 999999.000000000000000 - - - 1.000000000000000 + + 1.00 @@ -457,7 +454,7 @@ QGroupBox::title { - + @@ -469,18 +466,15 @@ QGroupBox::title { - - - 5 + + + + 0 + 0 + - - -999999.000000000000000 - - - 999999.000000000000000 - - - 1.000000000000000 + + 1.00 diff --git a/Polyhedron/demo/Polyhedron/Plugins/PCA/MeshOnGrid_dialog.ui b/Polyhedron/demo/Polyhedron/Plugins/PCA/MeshOnGrid_dialog.ui index 392c3820a15..2529489ac10 100644 --- a/Polyhedron/demo/Polyhedron/Plugins/PCA/MeshOnGrid_dialog.ui +++ b/Polyhedron/demo/Polyhedron/Plugins/PCA/MeshOnGrid_dialog.ui @@ -53,7 +53,7 @@ - 0,00 + 0.00 @@ -93,7 +93,7 @@ - 0,00 + 0.00 @@ -133,7 +133,7 @@ - 0,00 + 0.00 diff --git a/Polyhedron/demo/Polyhedron/Plugins/PMP/Fairing_widget.ui b/Polyhedron/demo/Polyhedron/Plugins/PMP/Fairing_widget.ui index ec17b2f7811..632322e2edd 100644 --- a/Polyhedron/demo/Polyhedron/Plugins/PMP/Fairing_widget.ui +++ b/Polyhedron/demo/Polyhedron/Plugins/PMP/Fairing_widget.ui @@ -101,7 +101,7 @@ - 2,41 + 2.41 diff --git a/Polyhedron/demo/Polyhedron/Plugins/PMP/Hole_filling_widget.ui b/Polyhedron/demo/Polyhedron/Plugins/PMP/Hole_filling_widget.ui index b6470ecb123..7fae391312e 100644 --- a/Polyhedron/demo/Polyhedron/Plugins/PMP/Hole_filling_widget.ui +++ b/Polyhedron/demo/Polyhedron/Plugins/PMP/Hole_filling_widget.ui @@ -87,18 +87,9 @@ - - - 0 - - - 999999999.000000000000000 - - - 1.000000000000000 - - - 10.000000000000000 + + + 10.0 @@ -131,7 +122,7 @@ - 1,41 + 1.41 Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter diff --git a/Polyhedron/demo/Polyhedron/Plugins/PMP/Isotropic_remeshing_plugin.cpp b/Polyhedron/demo/Polyhedron/Plugins/PMP/Isotropic_remeshing_plugin.cpp index f779addae8c..66c8db3bef5 100644 --- a/Polyhedron/demo/Polyhedron/Plugins/PMP/Isotropic_remeshing_plugin.cpp +++ b/Polyhedron/demo/Polyhedron/Plugins/PMP/Isotropic_remeshing_plugin.cpp @@ -332,7 +332,7 @@ public Q_SLOTS: } bool edges_only = ui.splitEdgesOnly_checkbox->isChecked(); bool preserve_duplicates = ui.preserveDuplicates_checkbox->isChecked(); - double target_length = ui.edgeLength_dspinbox->text().toDouble(); + 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(); @@ -673,7 +673,7 @@ public Q_SLOTS: edges_only = ui.splitEdgesOnly_checkbox->isChecked(); preserve_duplicates = ui.preserveDuplicates_checkbox->isChecked(); - target_length = ui.edgeLength_dspinbox->text().toDouble(); + target_length = ui.edgeLength_dspinbox->value(); nb_iter = ui.nbIterations_spinbox->value(); protect = ui.protect_checkbox->isChecked(); smooth_features = ui.smooth1D_checkbox->isChecked(); @@ -907,7 +907,7 @@ private: + (bbox.zmax()-bbox.zmin())*(bbox.zmax()-bbox.zmin())); - ui.edgeLength_dspinbox->setText(tr("%1").arg(0.05 * diago_length)); + ui.edgeLength_dspinbox->setValue(0.05 * diago_length); std::ostringstream oss; oss << "Diagonal length of the Bbox of the selection to remesh is "; diff --git a/Polyhedron/demo/Polyhedron/Plugins/PMP/Mean_curvature_flow_skeleton_plugin.cpp b/Polyhedron/demo/Polyhedron/Plugins/PMP/Mean_curvature_flow_skeleton_plugin.cpp index f6a1137ff31..f31f81bcdba 100644 --- a/Polyhedron/demo/Polyhedron/Plugins/PMP/Mean_curvature_flow_skeleton_plugin.cpp +++ b/Polyhedron/demo/Polyhedron/Plugins/PMP/Mean_curvature_flow_skeleton_plugin.cpp @@ -189,17 +189,9 @@ public: "to a surface mesh item. The generated mcf group must be selected in " "order to continue an on-going set of operations. "));}); ui->omega_H->setValue(0.1); - ui->omega_H->setSingleStep(0.1); - ui->omega_H->setDecimals(3); ui->omega_P->setValue(0.2); - ui->omega_P->setSingleStep(0.1); - ui->omega_P->setDecimals(3); - ui->min_edge_length->setDecimals(7); ui->min_edge_length->setValue(0.002 * diag); - ui->min_edge_length->setSingleStep(0.0000001); - ui->delta_area->setDecimals(7); ui->delta_area->setValue(1e-4); - ui->delta_area->setSingleStep(1e-5); ui->is_medially_centered->setChecked(false); ui->label_omega_H->setToolTip(QString("omega_H controls the velocity of movement and approximation quality")); diff --git a/Polyhedron/demo/Polyhedron/Plugins/PMP/Mean_curvature_flow_skeleton_plugin.ui b/Polyhedron/demo/Polyhedron/Plugins/PMP/Mean_curvature_flow_skeleton_plugin.ui index 9bb3b0c53f1..f7c8563efb8 100644 --- a/Polyhedron/demo/Polyhedron/Plugins/PMP/Mean_curvature_flow_skeleton_plugin.ui +++ b/Polyhedron/demo/Polyhedron/Plugins/PMP/Mean_curvature_flow_skeleton_plugin.ui @@ -6,7 +6,7 @@ 0 0 - 483 + 498 279 @@ -51,7 +51,7 @@ - + @@ -60,12 +60,22 @@ - + + + + 0 + 0 + + + + 0.00 + + - + @@ -74,12 +84,22 @@ - + + + + 0 + 0 + + + + 0.00 + + - + @@ -88,12 +108,16 @@ - + + + 0.00 + + - + @@ -102,7 +126,17 @@ - + + + + 0 + 0 + + + + 0.00 + + @@ -203,6 +237,13 @@ + + + DoubleEdit + QLineEdit +
    CGAL_double_edit.h
    +
    +
    diff --git a/Polyhedron/demo/Polyhedron/Plugins/PMP/Random_perturbation_dialog.ui b/Polyhedron/demo/Polyhedron/Plugins/PMP/Random_perturbation_dialog.ui index db2891e8c6d..1d368c3dd59 100644 --- a/Polyhedron/demo/Polyhedron/Plugins/PMP/Random_perturbation_dialog.ui +++ b/Polyhedron/demo/Polyhedron/Plugins/PMP/Random_perturbation_dialog.ui @@ -86,7 +86,7 @@ - 0,00 + 0.00
    diff --git a/Polyhedron/demo/Polyhedron/Plugins/PMP/Smoothing_plugin.ui b/Polyhedron/demo/Polyhedron/Plugins/PMP/Smoothing_plugin.ui index ccb455625a9..d2d5b957acf 100644 --- a/Polyhedron/demo/Polyhedron/Plugins/PMP/Smoothing_plugin.ui +++ b/Polyhedron/demo/Polyhedron/Plugins/PMP/Smoothing_plugin.ui @@ -57,7 +57,7 @@ - 0,000001 + 0.000001 diff --git a/Polyhedron/demo/Polyhedron/Plugins/Point_set/Features_detection_plugin.ui b/Polyhedron/demo/Polyhedron/Plugins/Point_set/Features_detection_plugin.ui index 98e2975c184..b6d841ec851 100644 --- a/Polyhedron/demo/Polyhedron/Plugins/Point_set/Features_detection_plugin.ui +++ b/Polyhedron/demo/Polyhedron/Plugins/Point_set/Features_detection_plugin.ui @@ -6,8 +6,8 @@ 0 0 - 254 - 153 + 271 + 141 @@ -15,7 +15,7 @@ - + @@ -24,22 +24,22 @@ - - - 3 + + + + 0 + 0 + - - 0.050000000000000 - - - 0.100000000000000 + + 0.100 - + @@ -48,19 +48,22 @@ - - - 3 + + + + 0 + 0 + - - 0.050000000000000 + + 0.00 - + @@ -69,15 +72,15 @@ - - - 3 + + + + 0 + 0 + - - 0.020000000000000 - - - 0.160000000000000 + + 0.160 @@ -108,6 +111,13 @@ + + + DoubleEdit + QLineEdit +
    CGAL_double_edit.h
    +
    +
    diff --git a/Polyhedron/demo/Polyhedron/Plugins/Point_set/Point_set_normal_estimation_plugin.ui b/Polyhedron/demo/Polyhedron/Plugins/Point_set/Point_set_normal_estimation_plugin.ui index 8ceaeaea887..baf03b4ef0c 100644 --- a/Polyhedron/demo/Polyhedron/Plugins/Point_set/Point_set_normal_estimation_plugin.ui +++ b/Polyhedron/demo/Polyhedron/Plugins/Point_set/Point_set_normal_estimation_plugin.ui @@ -6,7 +6,7 @@ 0 0 - 301 + 330 372 @@ -139,22 +139,6 @@ - - - - 0.010000000000000 - - - 0.010000000000000 - - - 0.100000000000000 - - - - - - @@ -185,6 +169,20 @@ + + + + 0.10 + + + + + + + 0.00 + + + @@ -213,6 +211,13 @@ + + + DoubleEdit + QLineEdit +
    CGAL_double_edit.h
    +
    +
    @@ -263,22 +268,6 @@ - - buttonRadius - toggled(bool) - m_convolution_radius - setEnabled(bool) - - - 90 - 242 - - - 285 - 245 - - - buttonNeighbors toggled(bool) diff --git a/Polyhedron/demo/Polyhedron/Plugins/Point_set/Point_set_outliers_removal_plugin.ui b/Polyhedron/demo/Polyhedron/Plugins/Point_set/Point_set_outliers_removal_plugin.ui index bda8af50aa6..af3b64b7ea8 100644 --- a/Polyhedron/demo/Polyhedron/Plugins/Point_set/Point_set_outliers_removal_plugin.ui +++ b/Polyhedron/demo/Polyhedron/Plugins/Point_set/Point_set_outliers_removal_plugin.ui @@ -91,26 +91,21 @@ - - - 6 - - - 0.000000000000000 - - - 100000.000000000000000 - - - 0.100000000000000 - - - 0.500000000000000 + + + 0.5 + + + DoubleEdit + QLineEdit +
    CGAL_double_edit.h
    +
    +
    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 45740cc84e3..25ad888c165 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 @@ -824,7 +824,7 @@ protected Q_SLOTS: DoubleEdit* epsilon = dialog.add ("Epsilon: "); if (rg_epsilon < 0.) rg_epsilon = (std::max)(0.00001, 0.005 * scene->len_diagonal()); - epsilon->setText(tr("%1").arg(rg_epsilon)); + epsilon->setValue(rg_epsilon); DoubleEdit* cluster_epsilon = dialog.add ("Cluster epsilon: "); if (rg_cluster_epsilon < 0.) @@ -838,8 +838,8 @@ protected Q_SLOTS: if (dialog.exec()) { - rg_epsilon = epsilon->text().toDouble(); - rg_cluster_epsilon = cluster_epsilon->text().toDouble(); + rg_epsilon = epsilon->value(); + rg_cluster_epsilon = cluster_epsilon->value(); rg_normal_threshold = normal_threshold->value(); } } diff --git a/Polyhedron/demo/Polyhedron/Plugins/Point_set/Point_set_shape_detection_plugin.ui b/Polyhedron/demo/Polyhedron/Plugins/Point_set/Point_set_shape_detection_plugin.ui index 185d418fffc..684acace812 100644 --- a/Polyhedron/demo/Polyhedron/Plugins/Point_set/Point_set_shape_detection_plugin.ui +++ b/Polyhedron/demo/Polyhedron/Plugins/Point_set/Point_set_shape_detection_plugin.ui @@ -124,7 +124,7 @@ - + @@ -133,31 +133,22 @@ - - - Fitting tolerance in Euclidean distance + + + + 0 + 0 + - - 8 - - - 0.000001000000000 - - - 1000000.000000000000000 - - - 0.001000000000000 - - - 0.002000000000000 + + 0.002 - + @@ -166,28 +157,22 @@ - - - Normal angle deviation tolerance as cosine of the angle + + + + 0 + 0 + - - 0.010000000000000 - - - 1.000000000000000 - - - 0.010000000000000 - - - 0.900000000000000 + + 0.90 - + @@ -214,7 +199,7 @@ - + @@ -223,31 +208,22 @@ - - - Maximum world distance between points on a shape to be considered as connected + + + + 0 + 0 + - - 8 - - - 0.000001000000000 - - - 1000000.000000000000000 - - - 0.010000000000000 - - - 0.020000000000000 + + 0.002 - + @@ -259,27 +235,15 @@ - - - false + + + + 0 + 0 + - - Probability to overlook the largest primitive in one extraction iteration - - - 5 - - - 0.000010000000000 - - - 1.000000000000000 - - - 0.010000000000000 - - - 0.050000000000000 + + 0.05 @@ -356,6 +320,13 @@ + + + DoubleEdit + QLineEdit +
    CGAL_double_edit.h
    +
    +
    @@ -486,21 +457,5 @@ - - ransac - toggled(bool) - m_probability_field - setEnabled(bool) - - - 70 - 46 - - - 352 - 214 - - - diff --git a/Polyhedron/demo/Polyhedron/Plugins/Point_set/Point_set_simplification_plugin.cpp b/Polyhedron/demo/Polyhedron/Plugins/Point_set/Point_set_simplification_plugin.cpp index 9d838794b69..c027c4275da 100644 --- a/Polyhedron/demo/Polyhedron/Plugins/Point_set/Point_set_simplification_plugin.cpp +++ b/Polyhedron/demo/Polyhedron/Plugins/Point_set/Point_set_simplification_plugin.cpp @@ -134,6 +134,7 @@ class Point_set_demo_point_set_simplification_dialog : public QDialog, private U Point_set_demo_point_set_simplification_dialog(QWidget * /*parent*/ = 0) { setupUi(this); + m_maximumSurfaceVariation->setRange(0.000010, 0.33330); } unsigned int simplificationMethod() const diff --git a/Polyhedron/demo/Polyhedron/Plugins/Point_set/Point_set_simplification_plugin.ui b/Polyhedron/demo/Polyhedron/Plugins/Point_set/Point_set_simplification_plugin.ui index 3293552fd46..45b189faf13 100644 --- a/Polyhedron/demo/Polyhedron/Plugins/Point_set/Point_set_simplification_plugin.ui +++ b/Polyhedron/demo/Polyhedron/Plugins/Point_set/Point_set_simplification_plugin.ui @@ -7,24 +7,20 @@ 0 0 392 - 248 + 249 Simplification - - + + - Maximum Cluster Size + Random - - - - - - Grid + + true @@ -44,37 +40,6 @@ - - - - Maximum Surface Variation - - - - - - - Random - - - true - - - - - - - Hierarchy - - - - - - - Points to Remove Randomly - - - @@ -82,16 +47,6 @@ - - - - Qt::Horizontal - - - QDialogButtonBox::Cancel|QDialogButtonBox::Ok - - - @@ -114,28 +69,10 @@ - - - - false - - - - - - 5 - - - 0.000010000000000 - - - 0.333330000000000 - - - 0.012340000000000 - - - 0.333330000000000 + + + + Maximum Surface Variation @@ -177,8 +114,60 @@ + + + + Maximum Cluster Size + + + + + + + Points to Remove Randomly + + + + + + + Grid + + + + + + + Hierarchy + + + + + + + Qt::Horizontal + + + QDialogButtonBox::Cancel|QDialogButtonBox::Ok + + + + + + + 0.333333 + + + + + + DoubleEdit + QLineEdit +
    CGAL_double_edit.h
    +
    +
    diff --git a/Polyhedron/demo/Polyhedron/Plugins/Point_set/Point_set_to_mesh_distance_widget.ui b/Polyhedron/demo/Polyhedron/Plugins/Point_set/Point_set_to_mesh_distance_widget.ui index 34c678aae20..e6c3dac8755 100644 --- a/Polyhedron/demo/Polyhedron/Plugins/Point_set/Point_set_to_mesh_distance_widget.ui +++ b/Polyhedron/demo/Polyhedron/Plugins/Point_set/Point_set_to_mesh_distance_widget.ui @@ -160,7 +160,7 @@ - 0,00 + 0.00 diff --git a/Polyhedron/demo/Polyhedron/Plugins/Point_set/Point_set_upsampling_plugin.cpp b/Polyhedron/demo/Polyhedron/Plugins/Point_set/Point_set_upsampling_plugin.cpp index 2fba3abfcb8..d99910aa5a9 100644 --- a/Polyhedron/demo/Polyhedron/Plugins/Point_set/Point_set_upsampling_plugin.cpp +++ b/Polyhedron/demo/Polyhedron/Plugins/Point_set/Point_set_upsampling_plugin.cpp @@ -67,6 +67,7 @@ public: Point_set_demo_point_set_upsampling_dialog(QWidget * /*parent*/ = 0) { setupUi(this); + m_edgeSensitivity->setMaximum(1.0); } unsigned int sharpness_angle () const { return m_sharpnessAngle->value(); } diff --git a/Polyhedron/demo/Polyhedron/Plugins/Point_set/Point_set_upsampling_plugin.ui b/Polyhedron/demo/Polyhedron/Plugins/Point_set/Point_set_upsampling_plugin.ui index 1bd40c30b9e..f8da092c47a 100644 --- a/Polyhedron/demo/Polyhedron/Plugins/Point_set/Point_set_upsampling_plugin.ui +++ b/Polyhedron/demo/Polyhedron/Plugins/Point_set/Point_set_upsampling_plugin.ui @@ -7,13 +7,36 @@ 0 0 348 - 167 + 168 Edge Aware Upsampling + + + + Qt::Horizontal + + + QDialogButtonBox::Cancel|QDialogButtonBox::Ok + + + + + + + Qt::Vertical + + + + 20 + 40 + + + + @@ -21,6 +44,59 @@ + + + + Neighborhood Radius + + + + + + + Edge Sensitivity + + + + + + + ° + + + 90 + + + 25 + + + + + + + + + + * input size + + + 1.000000000000000 + + + 1000.000000000000000 + + + 4.000000000000000 + + + + + + + Sharpness Angle + + + @@ -43,94 +119,22 @@ - - - - Qt::Horizontal - - - QDialogButtonBox::Cancel|QDialogButtonBox::Ok - - - - - - 1.000000000000000 - - - 0.010000000000000 - - - - - - - - - - * input size - - - 1.000000000000000 - - - 1000.000000000000000 - - - 4.000000000000000 - - - - - + - Edge Sensitivity + 0.00 - - - - Sharpness Angle - - - - - - - Neighborhood Radius - - - - - - - ° - - - 90 - - - 25 - - - - - - - Qt::Vertical - - - - 20 - 40 - - - - + + + DoubleEdit + QLineEdit +
    CGAL_double_edit.h
    +
    +
    diff --git a/Polyhedron/demo/Polyhedron/Plugins/Point_set/Surface_reconstruction_plugin.ui b/Polyhedron/demo/Polyhedron/Plugins/Point_set/Surface_reconstruction_plugin.ui index 8cbfe7f1c2a..084a6a9a81e 100644 --- a/Polyhedron/demo/Polyhedron/Plugins/Point_set/Surface_reconstruction_plugin.ui +++ b/Polyhedron/demo/Polyhedron/Plugins/Point_set/Surface_reconstruction_plugin.ui @@ -6,7 +6,7 @@ 0 0 - 404 + 427 482 @@ -736,7 +736,6 @@ - tabWidget_2 diff --git a/Polyhedron/demo/Polyhedron/Plugins/Surface_mesh/Mesh_plane_detection_dialog.ui b/Polyhedron/demo/Polyhedron/Plugins/Surface_mesh/Mesh_plane_detection_dialog.ui index 41487bf5351..e855d47f55c 100644 --- a/Polyhedron/demo/Polyhedron/Plugins/Surface_mesh/Mesh_plane_detection_dialog.ui +++ b/Polyhedron/demo/Polyhedron/Plugins/Surface_mesh/Mesh_plane_detection_dialog.ui @@ -49,7 +49,7 @@ - 0,01 + 0.01 diff --git a/Polyhedron/demo/Polyhedron/Plugins/Surface_mesh/Mesh_segmentation_widget.ui b/Polyhedron/demo/Polyhedron/Plugins/Surface_mesh/Mesh_segmentation_widget.ui index 485397d80dc..ce8020ce7e3 100644 --- a/Polyhedron/demo/Polyhedron/Plugins/Surface_mesh/Mesh_segmentation_widget.ui +++ b/Polyhedron/demo/Polyhedron/Plugins/Surface_mesh/Mesh_segmentation_widget.ui @@ -126,7 +126,7 @@ - 0,26 + 0.26 diff --git a/Polyhedron/demo/Polyhedron/Plugins/Surface_mesh/Mesh_simplification_dialog.ui b/Polyhedron/demo/Polyhedron/Plugins/Surface_mesh/Mesh_simplification_dialog.ui index e544450deb2..7b973c78bf1 100644 --- a/Polyhedron/demo/Polyhedron/Plugins/Surface_mesh/Mesh_simplification_dialog.ui +++ b/Polyhedron/demo/Polyhedron/Plugins/Surface_mesh/Mesh_simplification_dialog.ui @@ -105,15 +105,9 @@ - - - true - - - 5 - - - 10000.000000000000000 + + + 0.000 @@ -144,6 +138,13 @@ + + + DoubleEdit + QLineEdit +
    CGAL_double_edit.h
    +
    +
    diff --git a/Polyhedron/demo/Polyhedron/Plugins/Surface_mesh/Offset_meshing_plugin.cpp b/Polyhedron/demo/Polyhedron/Plugins/Surface_mesh/Offset_meshing_plugin.cpp index ebaf3adee56..e4b1fb40cc9 100644 --- a/Polyhedron/demo/Polyhedron/Plugins/Surface_mesh/Offset_meshing_plugin.cpp +++ b/Polyhedron/demo/Polyhedron/Plugins/Surface_mesh/Offset_meshing_plugin.cpp @@ -452,17 +452,16 @@ void Polyhedron_demo_offset_meshing_plugin::offset_meshing() QDialog dialog(mw); Ui::Remeshing_dialog ui; ui.setupUi(&dialog); + ui.angle->setRange(1.0, 30.0); connect(ui.buttonBox, SIGNAL(accepted()), &dialog, SLOT(accept())); connect(ui.buttonBox, SIGNAL(rejected()), &dialog, SLOT(reject())); - ui.sizing->setDecimals(4); ui.sizing->setRange(diag * 10e-6, // min diag); // max ui.sizing->setValue(diag * 0.05); // default value - ui.approx->setDecimals(6); ui.approx->setRange(diag * 10e-7, // min diag); // max ui.approx->setValue(diag * 0.005); diff --git a/Polyhedron/demo/Polyhedron/Plugins/Surface_mesh/Remeshing_dialog.ui b/Polyhedron/demo/Polyhedron/Plugins/Surface_mesh/Remeshing_dialog.ui index cfd2350787d..8366a6dcab3 100644 --- a/Polyhedron/demo/Polyhedron/Plugins/Surface_mesh/Remeshing_dialog.ui +++ b/Polyhedron/demo/Polyhedron/Plugins/Surface_mesh/Remeshing_dialog.ui @@ -15,69 +15,14 @@ - - - - - &Angle: - - - Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter - - - angle - - - - - - - 1.000000000000000 - - - 30.000000000000000 - - - 25.000000000000000 - - - - - - - &Size: - - - Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter - - - sizing - - - + - - - 4 - - - - - + - Approximation &error: - - - Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter - - - approx + 0.00 - - - @@ -97,6 +42,36 @@ + + + + &Angle: + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + + + + + &Size: + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + + + + + Approximation &error: + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + @@ -110,6 +85,20 @@ + + + + 0.00 + + + + + + + 25.0 + + + @@ -137,6 +126,13 @@ + + + DoubleEdit + QLineEdit +
    CGAL_double_edit.h
    +
    +
    diff --git a/Polyhedron/demo/Polyhedron/Plugins/Surface_mesh/Surface_mesh_approximation_dockwidget.ui b/Polyhedron/demo/Polyhedron/Plugins/Surface_mesh/Surface_mesh_approximation_dockwidget.ui index 8b67236b224..d8a1dec5bc3 100644 --- a/Polyhedron/demo/Polyhedron/Plugins/Surface_mesh/Surface_mesh_approximation_dockwidget.ui +++ b/Polyhedron/demo/Polyhedron/Plugins/Surface_mesh/Surface_mesh_approximation_dockwidget.ui @@ -6,7 +6,7 @@ 0 0 - 667 + 652 360 @@ -64,20 +64,19 @@ - - - - + + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter - - Error drop + + QAbstractSpinBox::NoButtons - - - - - - #Proxies + + 999 + + + 20 @@ -88,6 +87,26 @@ + + + + + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + @@ -104,47 +123,20 @@ - - - - Qt::Horizontal - - - - 40 - 20 - - - - - - - - false - + + - Negative value is ignored + - - Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + Error drop - - QAbstractSpinBox::NoButtons - - - 4 - - - 0.001000000000000 - - - 1.000000000000000 - - - 0.010000000000000 - - - 0.100000000000000 + + + + + + #Proxies @@ -168,26 +160,10 @@ - - - - Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter - - - QAbstractSpinBox::NoButtons - - - 999 - - - 20 - - - - - + + - + 0.1 @@ -410,25 +386,6 @@ - - - - Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter - - - QAbstractSpinBox::NoButtons - - - 10.000000000000000 - - - 0.100000000000000 - - - 3.000000000000000 - - - @@ -436,6 +393,19 @@ + + + + + 0 + 0 + + + + 3.00 + + + @@ -491,23 +461,13 @@ + + + DoubleEdit + QLineEdit +
    CGAL_double_edit.h
    +
    +
    - - - enable_error_drop - toggled(bool) - error_drop - setEnabled(bool) - - - 127 - 168 - - - 153 - 167 - - - - + diff --git a/Polyhedron/demo/Polyhedron/Plugins/Surface_mesh/Surface_mesh_approximation_plugin.cpp b/Polyhedron/demo/Polyhedron/Plugins/Surface_mesh/Surface_mesh_approximation_plugin.cpp index befcbbd0099..cebffa08e4d 100644 --- a/Polyhedron/demo/Polyhedron/Plugins/Surface_mesh/Surface_mesh_approximation_plugin.cpp +++ b/Polyhedron/demo/Polyhedron/Plugins/Surface_mesh/Surface_mesh_approximation_plugin.cpp @@ -81,6 +81,8 @@ public: dock_widget = new QDockWidget("Mesh approximation parameters", mw); dock_widget->setVisible(false); ui_widget.setupUi(dock_widget); + ui_widget.chord_error->setRange(0.0, 10.0); + ui_widget.error_drop->setRange(0.01, 1.0); mw->addDockWidget(Qt::LeftDockWidgetArea, dock_widget); // connect ui actions diff --git a/Polyhedron/demo/Polyhedron/Plugins/Surface_mesh_deformation/Deform_mesh.ui b/Polyhedron/demo/Polyhedron/Plugins/Surface_mesh_deformation/Deform_mesh.ui index 64126a6c88b..2f7fdca658e 100644 --- a/Polyhedron/demo/Polyhedron/Plugins/Surface_mesh_deformation/Deform_mesh.ui +++ b/Polyhedron/demo/Polyhedron/Plugins/Surface_mesh_deformation/Deform_mesh.ui @@ -18,7 +18,7 @@ - 1 + 0 @@ -216,7 +216,7 @@ - 0,00 + 0.00 From a67361fe4537376e0f07d3c75723e2f92f1fdab4 Mon Sep 17 00:00:00 2001 From: Maxime Gimeno Date: Wed, 16 Oct 2019 11:39:40 +0200 Subject: [PATCH 203/363] Add ranges --- .../Polyhedron/Plugins/Mesh_3/C3t3_rib_exporter_plugin.cpp | 4 +++- Polyhedron/demo/Polyhedron/Plugins/Mesh_3/Mesh_3_plugin.cpp | 6 +++++- .../demo/Polyhedron/Plugins/Mesh_3/Optimization_plugin.cpp | 4 ++++ Polyhedron/demo/Polyhedron/Plugins/PMP/Fairing_plugin.cpp | 1 + .../demo/Polyhedron/Plugins/PMP/Hole_filling_plugin.cpp | 1 + .../Point_set/Point_set_normal_estimation_plugin.cpp | 1 + .../Plugins/Point_set/Point_set_outliers_removal_plugin.cpp | 1 + .../Plugins/Point_set/Point_set_shape_detection_plugin.cpp | 5 +++++ .../Plugins/Point_set/Point_set_upsampling_plugin.cpp | 3 +++ .../Plugins/Surface_mesh/Mesh_plane_detection_plugin.cpp | 2 +- .../Plugins/Surface_mesh/Mesh_segmentation_plugin.cpp | 1 + 11 files changed, 26 insertions(+), 3 deletions(-) diff --git a/Polyhedron/demo/Polyhedron/Plugins/Mesh_3/C3t3_rib_exporter_plugin.cpp b/Polyhedron/demo/Polyhedron/Plugins/Mesh_3/C3t3_rib_exporter_plugin.cpp index 12c3dd6649d..89b8a92ecc3 100644 --- a/Polyhedron/demo/Polyhedron/Plugins/Mesh_3/C3t3_rib_exporter_plugin.cpp +++ b/Polyhedron/demo/Polyhedron/Plugins/Mesh_3/C3t3_rib_exporter_plugin.cpp @@ -305,7 +305,9 @@ get_parameters_from_dialog() QDialog dialog(mw); Ui::Rib_dialog ui; ui.setupUi(&dialog); - + ui.ambientIntensity->setMaximum(1.0); + ui.shadowIntensity->setMaximum(1.0); + connect(ui.buttonBox, SIGNAL(accepted()), &dialog, SLOT(accept())); connect(ui.buttonBox, SIGNAL(rejected()), &dialog, SLOT(reject())); connect(ui.resWidth, SIGNAL(valueChanged(int)), this, SLOT(width_changed(int))); diff --git a/Polyhedron/demo/Polyhedron/Plugins/Mesh_3/Mesh_3_plugin.cpp b/Polyhedron/demo/Polyhedron/Plugins/Mesh_3/Mesh_3_plugin.cpp index 26d6d59792e..8a6f182fa17 100644 --- a/Polyhedron/demo/Polyhedron/Plugins/Mesh_3/Mesh_3_plugin.cpp +++ b/Polyhedron/demo/Polyhedron/Plugins/Mesh_3/Mesh_3_plugin.cpp @@ -293,8 +293,12 @@ void Mesh_3_plugin::mesh_3(const bool surface_only, const bool use_defaults) Ui::Meshing_dialog ui; ui.setupUi(&dialog); - ui.facetAngle->setRange(0.0, 20.0); + ui.facetAngle->setRange(0.0, 30.0); ui.facetAngle->setValue(25.0); + ui.edgeSizing->setMinimum(0.0); + ui.sharpEdgesAngle->setMaximum(180); + ui.iso_value_spinBox->setRange(-65536.0, 65536.0); + ui.tetShape->setMinimum(1.0); ui.advanced->setVisible(false); connect(ui.facetTopologyLabel, diff --git a/Polyhedron/demo/Polyhedron/Plugins/Mesh_3/Optimization_plugin.cpp b/Polyhedron/demo/Polyhedron/Plugins/Mesh_3/Optimization_plugin.cpp index 303e38fd5cc..d069d109672 100644 --- a/Polyhedron/demo/Polyhedron/Plugins/Mesh_3/Optimization_plugin.cpp +++ b/Polyhedron/demo/Polyhedron/Plugins/Mesh_3/Optimization_plugin.cpp @@ -227,6 +227,9 @@ Mesh_3_optimization_plugin::odt() QDialog dialog(mw); Ui::Smoother_dialog ui; ui.setupUi(&dialog); + ui.convergenceRatio->setMaximum(1.0); + ui.convergenceRatio->setMinimum(0.0001); + ui.freezeRatio->setMinimum(0.0); dialog.setWindowFlags(Qt::Dialog|Qt::CustomizeWindowHint|Qt::WindowCloseButtonHint); dialog.setWindowTitle(tr("ODT-smoothing parameters")); @@ -362,6 +365,7 @@ Mesh_3_optimization_plugin::perturb() QDialog dialog(mw); Ui::LocalOptim_dialog ui; ui.setupUi(&dialog); + ui.sliverBound->setRange(0,180); dialog.setWindowFlags(Qt::Dialog|Qt::CustomizeWindowHint|Qt::WindowCloseButtonHint); dialog.setWindowTitle(tr("Sliver perturbation parameters")); diff --git a/Polyhedron/demo/Polyhedron/Plugins/PMP/Fairing_plugin.cpp b/Polyhedron/demo/Polyhedron/Plugins/PMP/Fairing_plugin.cpp index e35106929a4..f496b01bcd2 100644 --- a/Polyhedron/demo/Polyhedron/Plugins/PMP/Fairing_plugin.cpp +++ b/Polyhedron/demo/Polyhedron/Plugins/PMP/Fairing_plugin.cpp @@ -64,6 +64,7 @@ public: dock_widget->setVisible(false); ui_widget.setupUi(dock_widget); + ui_widget.Density_control_factor_spin_box->setMaximum(96.989999999999995); addDockWidget(dock_widget); dock_widget->setWindowTitle(tr( "Fairing " diff --git a/Polyhedron/demo/Polyhedron/Plugins/PMP/Hole_filling_plugin.cpp b/Polyhedron/demo/Polyhedron/Plugins/PMP/Hole_filling_plugin.cpp index ca87a529133..fcdb9f65551 100644 --- a/Polyhedron/demo/Polyhedron/Plugins/PMP/Hole_filling_plugin.cpp +++ b/Polyhedron/demo/Polyhedron/Plugins/PMP/Hole_filling_plugin.cpp @@ -443,6 +443,7 @@ void Polyhedron_demo_hole_filling_plugin::init(QMainWindow* mainWindow, dock_widget->installEventFilter(this); ui_widget.setupUi(dock_widget); + ui_widget.Density_control_factor_spin_box->setMaximum(96.989999999999995); ui_widget.Accept_button->setVisible(false); ui_widget.Reject_button->setVisible(false); diff --git a/Polyhedron/demo/Polyhedron/Plugins/Point_set/Point_set_normal_estimation_plugin.cpp b/Polyhedron/demo/Polyhedron/Plugins/Point_set/Point_set_normal_estimation_plugin.cpp index 89ef88a006a..ff215dfa0e3 100644 --- a/Polyhedron/demo/Polyhedron/Plugins/Point_set/Point_set_normal_estimation_plugin.cpp +++ b/Polyhedron/demo/Polyhedron/Plugins/Point_set/Point_set_normal_estimation_plugin.cpp @@ -152,6 +152,7 @@ class Point_set_demo_normal_estimation_dialog : public QDialog, private Ui::Norm Point_set_demo_normal_estimation_dialog(QWidget* /*parent*/ = 0) { setupUi(this); + m_offset_radius->setMinimum(0.01); } int pca_neighbors() const { return m_pca_neighbors->value(); } 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 db4b46da4eb..62e27951f45 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 @@ -92,6 +92,7 @@ class Point_set_demo_outlier_removal_dialog : public QDialog, private Ui::Outlie Point_set_demo_outlier_removal_dialog(QWidget * /*parent*/ = 0) { setupUi(this); + m_distanceThreshold->setMinimum(0.0); } double percentage() const { return m_inputPercentage->value(); } diff --git a/Polyhedron/demo/Polyhedron/Plugins/Point_set/Point_set_shape_detection_plugin.cpp b/Polyhedron/demo/Polyhedron/Plugins/Point_set/Point_set_shape_detection_plugin.cpp index 27057b15b54..d9497aba999 100644 --- a/Polyhedron/demo/Polyhedron/Plugins/Point_set/Point_set_shape_detection_plugin.cpp +++ b/Polyhedron/demo/Polyhedron/Plugins/Point_set/Point_set_shape_detection_plugin.cpp @@ -79,6 +79,11 @@ public: Point_set_demo_point_set_shape_detection_dialog(QWidget * /*parent*/ = 0) { setupUi(this); + m_normal_tolerance_field->setMaximum(1.0); + m_probability_field->setRange(0.00001, 1.0); + m_epsilon_field->setMinimum(0.000001); + m_normal_tolerance_field->setMinimum(0.01); + m_cluster_epsilon_field->setMinimum(0.000001); } bool region_growing() const { return m_region_growing->isChecked(); } diff --git a/Polyhedron/demo/Polyhedron/Plugins/Point_set/Point_set_upsampling_plugin.cpp b/Polyhedron/demo/Polyhedron/Plugins/Point_set/Point_set_upsampling_plugin.cpp index d99910aa5a9..c3740307ffa 100644 --- a/Polyhedron/demo/Polyhedron/Plugins/Point_set/Point_set_upsampling_plugin.cpp +++ b/Polyhedron/demo/Polyhedron/Plugins/Point_set/Point_set_upsampling_plugin.cpp @@ -68,6 +68,9 @@ public: { setupUi(this); m_edgeSensitivity->setMaximum(1.0); + m_neighborhoodRadius->setRange(0.1, 10.0); + + } unsigned int sharpness_angle () const { return m_sharpnessAngle->value(); } diff --git a/Polyhedron/demo/Polyhedron/Plugins/Surface_mesh/Mesh_plane_detection_plugin.cpp b/Polyhedron/demo/Polyhedron/Plugins/Surface_mesh/Mesh_plane_detection_plugin.cpp index 28de24b4acc..989131b3ec3 100644 --- a/Polyhedron/demo/Polyhedron/Plugins/Surface_mesh/Mesh_plane_detection_plugin.cpp +++ b/Polyhedron/demo/Polyhedron/Plugins/Surface_mesh/Mesh_plane_detection_plugin.cpp @@ -191,7 +191,7 @@ void Polyhedron_demo_mesh_plane_detection_plugin::on_actionPlaneDetection_trigge QDialog dialog(mw); Ui::Mesh_plane_detection_dialog ui; ui.setupUi(&dialog); - + ui.minimumAreaDoubleSpinBox->setMinimum(0.00001); // check user cancellation if(dialog.exec() == QDialog::Rejected) return; diff --git a/Polyhedron/demo/Polyhedron/Plugins/Surface_mesh/Mesh_segmentation_plugin.cpp b/Polyhedron/demo/Polyhedron/Plugins/Surface_mesh/Mesh_segmentation_plugin.cpp index 0546a3555bb..66ac1b6dd68 100644 --- a/Polyhedron/demo/Polyhedron/Plugins/Surface_mesh/Mesh_segmentation_plugin.cpp +++ b/Polyhedron/demo/Polyhedron/Plugins/Surface_mesh/Mesh_segmentation_plugin.cpp @@ -92,6 +92,7 @@ public: dock_widget = new QDockWidget("Mesh segmentation parameters", mw); dock_widget->setVisible(false); // do not show at the beginning ui_widget.setupUi(dock_widget); + ui_widget.Smoothness_spin_box->setMaximum(10.0); mw->addDockWidget(Qt::LeftDockWidgetArea, dock_widget); connect(ui_widget.Partition_button, SIGNAL(clicked()), this, SLOT(on_Partition_button_clicked())); From 76cc4a6863934e3fa7ad332f2aec7dcbffafcec6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9bastien=20Loriot?= Date: Thu, 17 Oct 2019 14:36:00 +0200 Subject: [PATCH 204/363] pass on the doc --- .../advanced/Configuration_variables.txt | 348 ----------------- .../Documentation/advanced/Installation.txt | 357 ------------------ .../doc/Documentation/advanced/advanced.txt | 8 - 3 files changed, 713 deletions(-) delete mode 100644 Documentation/doc/Documentation/advanced/Configuration_variables.txt delete mode 100644 Documentation/doc/Documentation/advanced/Installation.txt delete mode 100644 Documentation/doc/Documentation/advanced/advanced.txt diff --git a/Documentation/doc/Documentation/advanced/Configuration_variables.txt b/Documentation/doc/Documentation/advanced/Configuration_variables.txt deleted file mode 100644 index 343a513afb2..00000000000 --- a/Documentation/doc/Documentation/advanced/Configuration_variables.txt +++ /dev/null @@ -1,348 +0,0 @@ -/*! - -\page configurationvariables Summary of %CGAL's Configuration Variables -\cgalAutoToc - -\section installation_summary Summary of CGAL's Configuration Variables - -Most configuration variables are not environment variables but -CMake variables. They are given in the command line to CMake -via the `-D` option, or passed from the interactive interface -of `cmake-gui`. Unless indicated differently, all the variables -summarized below are CMake variables. - -\subsection installation_component_selection Component Selection - -The following boolean variables indicate which \cgal components to -configure and build. Their values can be ON or OFF. - - -| Variable | %Default Value | -| :------- | :--------------- | -| `WITH_examples` | OFF | -| `WITH_demos` | OFF | -| `WITH_CGAL_Core` | ON | -| `WITH_CGAL_Qt5` | ON | -| `WITH_CGAL_ImageIO` | ON | - -\subsection installation_flags Compiler and Linker Flags - -The following variables specify compiler and linker flags. Each variable holds a -space-separated list of command-line switches for the compiler and linker and -their default values are automatically defined by CMake based on the target platform. - -Have in mind that these variables specify a list of flags, not just one -single flag. If you provide your own definition for a variable, you will entirely override -the list of flags chosen by CMake for that particular variable. - -The variables that correspond to both debug and release builds are always -used in conjunction with those for the specific build type. - - -| Program | Both Debug and Release | Release Only | Debug Only | -| :------ | :---------------------- | :------------- | :----------- | -| C++ Compiler | `CMAKE_CXX_FLAGS` | `CMAKE_CXX_FLAGS_RELEASE` | `CMAKE_CXX_FLAGS_DEBUG` | -| Linker (shared libs) | `CMAKE_SHARED_LINKER_FLAGS` | `CMAKE_SHARED_LINKER_FLAGS_RELEASE` | `CMAKE_SHARED_LINKER_FLAGS_DEBUG` | -| Linker (static libs) | `CMAKE_MODULE_LINKER_FLAGS` | `CMAKE_MODULE_LINKER_FLAGS_RELEASE` | `CMAKE_MODULE_LINKER_FLAGS_DEBUG` | -| Linker (programs) | `CMAKE_EXE_LINKER_FLAGS` | `CMAKE_EXE_LINKER_FLAGS_RELEASE` | `CMAKE_EXE_LINKER_FLAGS_DEBUG`| - - -\subsection installation_additional_flags Additional Compiler and Linker Flags - -The following variables can be used to add flags without overriding the ones -defined by cmake. - - -| Program | Both Debug and Release | Release Only | Debug Only | -| :------ | :---------------------- | :------------- | :----------- | -| C++ Compiler | `CGAL_CXX_FLAGS` | `CGAL_CXX_FLAGS_RELEASE` | `CGAL_CXX_FLAGS_DEBUG` | -| Linker (shared libs) | `CGAL_SHARED_LINKER_FLAGS` | `CGAL_SHARED_LINKER_FLAGS_RELEASE` | `CGAL_SHARED_LINKER_FLAGS_DEBUG` | -| Linker (static libs) | `CGAL_MODULE_LINKER_FLAGS` | `CGAL_MODULE_LINKER_FLAGS_RELEASE` | `CGAL_MODULE_LINKER_FLAGS_DEBUG` | -| Linker (programs) | `CGAL_EXE_LINKER_FLAGS` | `CGAL_EXE_LINKER_FLAGS_RELEASE` | `CGAL_EXE_LINKER_FLAGS_DEBUG` | - -\subsection installation_misc Miscellaneous Variables - -Note that the default build type is `Debug`, which should only be used to debug -and will serverly limit performances. - -| Variable | Description | Type | %Default Value | -| :- | :- | :- | :- | -| `CMAKE_BUILD_TYPE` | Indicates type of build. Possible values are 'Debug' or 'Release' | CMake | | -| `CMAKE_INSTALL_PREFIX`| Installation directory path | CMake | Debug | -| `CMAKE_C_COMPILER` | Full-path to the executable corresponding to the C compiler to use. | CMake | platform-dependent | -| `CMAKE_CXX_COMPILER` | Full-path to the executable corresponding to the C++ compiler to use. | CMake | platform-dependent | -| `CXX` | Idem | Environment | Idem | -| `BUILD_SHARED_LIBS` | Whether to build shared or static libraries. | CMake | TRUE | - -\subsection installation_variables_building Variables Used Only When Building Programs (Such as Demos or Examples) - - -| Variable | Description | Type | %Default Value | -| :- | :- | :- | :- | -| `CGAL_DIR` | Full-path to the binary directory where \cgal was configured |Either CMake or Environment | none | - - -\subsection installation_variables_third_party Variables Providing Information About 3rd-Party Libraries -\anchor sec3partysoftwareconfig - -The following variables provide information about the availability and -location of the 3rd party libraries used by \cgal. CMake automatically -searches for dependencies so you need to specify these variables if -CMake was unable to locate something. This is indicated by a value ending in -`NOTFOUND`. - -Since 3rd-party libraries are system wide, many of the CMake variables listed below can alternatively -be given as similarly-named environment variables instead. Keep in mind that you must provide one or the -other but never both. - -\subsection installation_boost Boost Libraries - -In most cases, if \sc{Boost} is not automatically found, setting the `BOOST_ROOT` -variable is enough. If it is not, you can specify the header and library -directories individually. You can also provide the full pathname to a specific compiled library -if it cannot be found in the library directory or its name is non-standard. - -By default, when \sc{Boost} binary libraries are needed, the shared versions -are used if present. You can set the variable -`CGAL_Boost_USE_STATIC_LIBS` to `ON` if you want to link -with static versions explicitly. - -On Windows, if you link with \sc{Boost} shared libraries, you must ensure that -the `.dll` files are found by the dynamic linker, at run time. -For example, you can add the path to the \sc{Boost} `.dll` to the -`PATH` environment variable. - -| Variable | Description | Type | -| :- | :- | :- | -| `BOOST_ROOT`\cgalFootnote{The environment variable can be spelled either `BOOST_ROOT` or `BOOSTROOT`} | Root directory of your \sc{Boost} installation | Either CMake or Environment | -| `Boost_INCLUDE_DIR` | Directory containing the `boost/version.hpp` file | CMake | -| `BOOST_INCLUDEDIR` | Idem | Environment | -| `Boost_LIBRARY_DIRS` | Directory containing the compiled \sc{Boost} libraries | CMake | -| `BOOST_LIBRARYDIR` | Idem | Environment | -| `Boost_(xyz)_LIBRARY_RELEASE` | Full pathname to a release build of the compiled 'xyz' \sc{Boost} library | CMake | -| `Boost_(xyz)_LIBRARY_DEBUG` | Full pathname to a debug build of the compiled 'xyz' \sc{Boost} library | CMake | - - -\subsection installation_gmp GMP and MPFR Libraries - -Under Windows, auto-linking is used, so only the directory -containing the libraries is needed and you would specify `GMP|MPFR_LIBRARY_DIR` rather than -`GMP|MPFR_LIBRARIES`. On the other hand, under Linux the actual library filename is needed. -Thus you would specify `GMP|MPFR_LIBRARIES`. In no case you need to specify both. - -\cgal uses both \sc{Gmp} and \sc{Mpfr} so both need to be supported. If either of them is unavailable the -usage of \sc{Gmp} and of \sc{Mpfr} will be disabled. - - -| Variable | Description | Type | -| :- | :- | :- | -| `CGAL_DISABLE_GMP` | Indicates whether to search and use \sc{Gmp}/\sc{Mpfr} or not | CMake | -| `GMP_DIR` | Directory of \sc{Gmp} default installation | Environment | -| `GMP_INCLUDE_DIR` | Directory containing the `gmp.h` file | CMake | -| `GMP_INC_DIR` | Idem | Environment | -| `GMP_LIBRARIES_DIR` | Directory containing the compiled \sc{Gmp} library | CMake | -| `GMP_LIB_DIR` | Idem | Environment | -| `GMP_LIBRARIES` | Full pathname of the compiled \sc{Gmp} library | CMake | -| `MPFR_INCLUDE_DIR` | Directory containing the `mpfr.h` file | CMake | -| `MPFR_INC_DIR` | Idem | Environment | -| `MPFR_LIBRARIES_DIR` | Directory containing the compiled \sc{Mpfr} library | CMake | -| `MPFR_LIB_DIR` | Idem | Environment | -| `MPFR_LIBRARIES` | Full pathname of the compiled \sc{Mpfr} library | CMake | - - - -Under Linux, the \sc{Gmpxx} is also searched for, and you may specify the following variables: - - -| Variable | Description | Type | -| :- | :- | :- | -| `GMPXX_DIR` | Directory of \sc{gmpxx} default installation | Environment | -| `GMPXX_INCLUDE_DIR` | Directory containing the `gmpxx.h` file | CMake | -| `GMPXX_LIBRARIES` | Full pathname of the compiled \sc{Gmpxx} library | CMake | - - - -\subsection installation_qt5 Qt5 Library - -You must set the cmake or environment variable `Qt5_DIR` to point to the path -to the directory containing the file `Qt5Config.cmake` created by your \sc{Qt}5 installation. If you are -using the open source edition it should be `/qt-everywhere-opensource-src-/qtbase/lib/cmake/Qt5`. - -\subsection installation_leda LEDA Library - -When the \leda libraries are not automatically found, yet they are installed on the system -with base names 'leda' and 'ledaD' (for the release and debug versions resp.), it might -be sufficient to just indicate the library directory via the `LEDA_LIBRARY_DIRS` variable. -If that doesn't work because, for example, the names are different, you can provide the full pathnames of each variant -via `LEDA_LIBRARY_RELEASE` and `LEDA_LIBRARY_DEBUG`. - -The variables specifying definitions and flags can be left undefined if they are not needed by LEDA. - - -| Variable | Description | Type | -| :- | :- | :- | -| `WITH_LEDA` | Indicates whether to search and use \leda or not | CMake | -| `LEDA_DIR` | Directory of \sc{LEDA} default installation | Environment | -| `LEDA_INCLUDE_DIR` | Directory containing the file `LEDA/system/basic.h` | CMake | -| `LEDA_LIBRARIES` | Directory containing the compiled \leda libraries | CMake | -| `LEDA_INC_DIR` | Directory containing the file `LEDA/system/basic.h` | Environment | -| `LEDA_LIB_DIR` | Directory containing the compiled \leda libraries | Environment | -| `LEDA_LIBRARY_RELEASE` | Full pathname to a release build of the \leda library | CMake | -| `LEDA_LIBRARY_DEBUG` | Full pathname to a debug build of the \leda library | CMake | -| `LEDA_DEFINITIONS` | Preprocessor definitions | CMake | -| `LEDA_CXX_FLAGS` | Compiler flags | CMake | -| `LEDA_LINKER_FLAGS` | Linker flags | CMake | - - -\subsection installation_mpfi MPFI Library - -\cgal provides a number type based on this library, but the \cgal library -itself does not depend on \sc{Mpfi}. This means that this library must be -configured when compiling an application that uses the above number type. - -When \sc{Mpfi} files are not on the standard path, the locations of the headers -and library files must be specified by using environment variables. - - -| Variable | Description | Type | -| :- | :- | :- | -| `MPFI_DIR` |Directory of \sc{MPFI} default installation | Environment | -| `MPFI_INCLUDE_DIR` | Directory containing the `mpfi.h` file | CMake | -| `MPFI_INC_DIR` | Idem | Environment | -| `MPFI_LIBRARIES_DIR` | Directory containing the compiled \sc{Mpfi} library | CMake | -| `MPFI_LIB_DIR` | Idem | Environment | -| `MPFI_LIBRARIES` | Full pathname of the compiled \sc{Mpfi} library | CMake | - - - -\subsection installation_rs RS and RS3 Library - -As said before, only the \cgal univariate algebraic kernel depends on the -library Rs. As the algebraic kernel is not compiled as a part of the \cgal -library, this library is not detected nor configured at installation time. - -CMake will try to find Rs in the standard header and library -directories. When it is not automatically detected, the locations of the -headers and library files must be specified using environment variables. - -Rs needs \sc{Gmp} 4.2 or later and \sc{Mpfi} 1.3.4 or later. The variables -related to the latter library may also need to be defined. - - -| Variable | Description | Type | -| :- | :- | :- | -| `RS_DIR` | Directory of \sc{Rs} default installation | Environment | -| `RS_INCLUDE_DIR` | Directory containing the `rs_exports.h` file | CMake | -| `RS_INC_DIR` | Idem | Environment | -| `RS_LIBRARIES_DIR` | Directory containing the compiled \sc{Rs} library | CMake | -| `RS_LIB_DIR` | Idem | Environment | -| `RS_LIBRARIES` | Full pathname of the compiled \sc{Rs} library | CMake | - -Similar variables exist for \sc{Rs3}. - -| Variable | Description | Type | -| :- | :- | :- -| `RS3_DIR` | Directory of \sc{Rs3} default installation | Environment | -| `RS3_INCLUDE_DIR` | Directory containing the file `rs3_fncts.h` file | CMake | -| `RS3_INC_DIR` | Idem | Environment | -| `RS3_LIBRARIES_DIR` | Directory containing the compiled \sc{Rs3} library | CMake | -| `RS3_LIB_DIR` | Idem | Environment | -| `RS3_LIBRARIES` | Full pathname of the compiled \sc{Rs3} library | CMake | - - -\subsection installation_ntl NTL Library - -Some polynomial computations in \cgal's algebraic kernel -are speed up when \sc{Ntl} is available. -As the algebraic kernel is not compiled as a part of the \cgal -library, this library is not detected nor configured at installation time. - -CMake will try to find \sc{Ntl} in the standard header and library -directories. When it is not automatically detected, the locations of the -headers and library files must be specified using environment variables. - -| Variable | Description | Type | -| :- | :- | :- | -| `NTL_DIR` | Directory of \sc{NTL} default installation | Environment | -| `NTL_INCLUDE_DIR` | Directory containing the `NTL/ZZX.h` file | CMake | -| `NTL_INC_DIR` | Idem | Environment | -| `NTL_LIBRARIES_DIR` | Directory containing the compiled \sc{Ntl} library | CMake | -| `NTL_LIB_DIR` | Idem | Environment | -| `NTL_LIBRARIES` | Full pathname of the compiled \sc{Ntl} library | CMake | - -\subsection installation_eigen Eigen Library - -\sc{Eigen} is a header-only template library. -Only the directory containing the header files of \sc{Eigen} 3.1 (or greater) is needed. - - -| Variable | Description | Type | -| :- | :- | :- | -| `EIGEN3_INCLUDE_DIR` | Directory containing the file `signature_of_eigen3_matrix_library` | CMake | -| `EIGEN3_INC_DIR` | Idem | Environment | - -\subsection installation_esbtl ESBTL Library - -One skin surface example requires the \sc{Esbtl} library in order to read \sc{Pdb} files. - -If \sc{Esbtl} is not automatically found, setting the `ESBTL_INC_DIR` -environment variable is sufficient. - - -| Variable | Description | Type | -| :- | :- | :- | -| `ESBTL_DIR` | Directory of \sc{ESBTL} default installation | Environment | -| `ESBTL_INC_DIR` | Directory containing the `ESBTL/default.h` file | Environment | -| `ESBTL_INCLUDE_DIR` | Directory containing the `ESBTL/default.h` file | CMake | - -\subsection installation_tbb TBB Library - -If \sc{Tbb} is not automatically found, the user must set the `TBB_ROOT` -environment variable. The environment variable `TBB_ARCH_PLATFORM=/` must be set. -`` is `ia32` or `intel64`. `` describes the Linux kernel, gcc version or Visual Studio version -used. It should be set to what is used in `$TBB_ROOT/lib/`. - -For windows users, the folder `TBB_ROOT/bin//` should be added to the `PATH` variable. - -Note that the variables in the table below are being used. - -| Variable | Description | Type | -| :- | :- | :- | -| `TBB_ROOT` | Directory of \sc{Tbb} default installation | Environment | -| `TBB_INCLUDE_DIRS` | Directory containing the `tbb/tbb.h` file | CMake | -| `TBB_LIBRARY_DIRS` | Directory(ies) containing the compiled TBB libraries | CMake | -| `TBB_LIBRARIES` | Full pathnames of the compiled TBB libraries (both release and debug versions, using "optimized" and "debug" CMake keywords). Note that if the debug versions are not found, the release versions will be used instead for the debug mode. | CMake | -| `TBB_RELEASE_LIBRARY` | Full pathname of the compiled TBB release library | CMake | -| `TBB_MALLOC_RELEASE_LIBRARY` | Full pathname of the compiled TBB release malloc library | CMake | -| `TBB_DEBUG_LIBRARY` | Full pathname of the compiled TBB debug library | CMake | -| `TBB_MALLOC_DEBUG_LIBRARY` | Full pathname of the compiled TBB debug malloc library | CMake | -| `TBB_MALLOCPROXY_DEBUG_LIBRARY` | Full pathname of the compiled TBB debug malloc_proxy library (optional) | CMake | -| `TBB_MALLOCPROXY_RELEASE_LIBRARY` | Full pathname of the compiled TBB release malloc_proxy library (optional) | CMake | - -\section installation_compiler_workarounds Compiler Workarounds - -A number of boolean flags are used to workaround compiler bugs and -limitations. They all start with the prefix `CGAL_CFG`. These -flags are used to work around compiler bugs and limitations. For -example, the flag `CGAL_CFG_NO_CPP0X_LONG_LONG` denotes -that the compiler does not know the type `long long`. - -For each installation a file -is defined, with the correct -settings of all flags. This file is generated automatically by CMake, -and it is located in the `include` directory of where you run -CMake. For an in-source configuration this means -`CGAL-\cgalReleaseNumber``/include`. - -The test programs used to generate the `compiler_config.h` -file can be found in `config/testfiles`. -Both -`compiler_config.h` and the test programs contain a short -description of the problem. In case of trouble with one of the -`CGAL_CFG` flags, it is a good idea to take a look at it. - -The file `CGAL/compiler_config.h` is included from -``. -which is included by all \cgal header files. - -*/ diff --git a/Documentation/doc/Documentation/advanced/Installation.txt b/Documentation/doc/Documentation/advanced/Installation.txt deleted file mode 100644 index cf6d2679b62..00000000000 --- a/Documentation/doc/Documentation/advanced/Installation.txt +++ /dev/null @@ -1,357 +0,0 @@ -/*! -\page installation Installation -\cgalAutoToc - -Since \cgal version 5.0, \cgal is header-only be default, which means -that there is no need to compile and install anything before it can be used. -However, the dependencies of \cgal might still need to be installed. - -This page is a step-by-step description of how to configure, build, and install \cgal -in case you do not wish to use the - now enabled by default - header-only mode of \cgal. -It is also possible to install \cgal using package managers on some operating systems, -see Section \ref secspecificinstall. - -\section installation_idealworld Quick Installation - -Ideally, compiling and installing \cgal, as well as compiling some examples shipped by \cgal is as simple as: - - cd $HOME/CGAL-\cgalReleaseNumber - cmake -DCMAKE_BUILD_TYPE=Release . # configure CGAL - make # build CGAL - make install # install CGAL - cd examples/Triangulation_2 # go to an example directory - cmake -DCGAL_DIR=$HOME/CGAL-\cgalReleaseNumber -DCMAKE_BUILD_TYPE=Release . # configure the examples - make # build the examples - -In a less ideal world, you might have to install some required tools and third-party libraries. -This is what this page is about. - -\section installation_configwithcmake Configuring CGAL with CMake - -Before building \cgal, or anything using \cgal, you have to choose the compiler/linker, -set compiler and linker flags, specify which -third-party libraries you want to use and where they can be found, and -which \cgal libraries you want to build. Gathering -all this information is called configuration. -The end of the process is marked by the generation of a makefile or a -Visual \cpp solution and project file that you can use to build \cgal. - -CMake maintains configuration parameters in so-called cmake variables. Some of the CMake -variables represent user choices, such as `CMAKE_BUILD_TYPE`, while others -indicate the details of a third-party library, such as `Boost_INCLUDE_DIR` or which compiler flags to use, -such as `CMAKE_CXX_FLAGS`. - -The next sections first present the CMake variables related to \cgal, followed by more generic variables, -and finally the configuration and build processes. - -\subsection seclibraries CGAL Libraries - -\cgal is split into four libraries. During configuration, you can select the libraries that -you would like to build by setting a CMake variable of the form WITH_. By default all -are switched `ON`. All activated libraries are to be built after configuration. - -Note that some libraries have specific dependencies in addition to the essential ones. See the page -\ref secessential3rdpartysoftware for more information. - -| Library | CMake Variable | Functionality | Dependencies | -| :-------- | :------------- | :------------ | :----------- | -| `%CGAL` | none | Main library | \sc{Gmp}, \sc{Mpfr}, \sc{Boost} (headers) | -| `CGAL_Core` | `WITH_CGAL_Core` | The %CORE library for algebraic numbers.\cgalFootnote{CGAL_Core is not part of \cgal, but a custom version of the \sc{Core} library distributed by \cgal for the user convenience and it has it's own license.} | \sc{Gmp} and \sc{Mpfr} | -| `CGAL_ImageIO` | `WITH_CGAL_ImageIO` | Utilities to read and write image files | \sc{zlib}, \sc{Vtk} (optional) | -| `CGAL_Qt5` | `WITH_CGAL_Qt5` | `QGraphicsView` support for \sc{Qt}5-based demos | \sc{Qt}5 | - -Shared libraries, also called dynamic-link libraries, are built by default -(`.dll` on Windows, `.so` on Linux, `.dylib` on MacOS). You -can choose to produce static libraries instead, by setting the CMake -variable `BUILD_SHARED_LIBS` to `FALSE`. - -\subsection installation_examples CGAL Examples and Demos - -\cgal is distributed with a large collection of examples and demos. By default, these are not configured along with -the \cgal libraries, unless you set the variables `WITH_examples=ON` and/or `WITH_demos=ON`. -Additionally, even when configured with \cgal, they are not automatically built along with the libraries. -You must build the `examples` or `demos` targets (or IDE projects) explicitly. - -If you do not plan to compile any demos, you may skip some of the dependencies (such as \sc{Qt}), -as the corresponding \cgal-libraries will not be used. Note, however, that your own demos -might need these \cgal-libraries and thus their dependencies. See the page -\ref secessential3rdpartysoftware for more information. - -\subsection installation_debugrelease Debug vs. Release - -The CMake variable `CMAKE_BUILD_TYPE` indicates how to build the libraries. -It accepts the values `Debug` or `Release`. Note that the default value is `Debug`, since it is -default value in `CMake`. If you do not plan on debugging, it is important to set the variable -to `Release` for performance reasons. - -This is however not an issue for solution/project files, since the user selects the build type -from within the IDE in this environment. - -\subsection installation_miscvariables Other CMake Variables - -There are many more variables that can be used during configuration. The most important ones are: -
      -
    • `CMAKE_INSTALL_PREFIX=` installation directory [/usr/local]
    • -
    • `CMAKE_BUILD_TYPE=` build type [Release]
    • -
    • `BUILD_SHARED_LIBS=` shared or static libraries [TRUE]
    • -
    • `CMAKE_C_COMPILER=` C compiler [gcc]
    • -
    • `CMAKE_CXX_COMPILER=` C++ compiler [g++]
    • -
    - -In case you want to add additional compiler and linker flags, you can use -
      -
    • `CGAL_CXX_FLAGS` additional compiler flags
    • -
    • `CGAL_MODULE_LINKER_FLAGS` add. linker flags (static libraries)
    • -
    • `CGAL_SHARED_LINKER_FLAGS` add. linker flags (shared libraries)
    • -
    • `CGAL_EXE_LINKER_FLAGS` add. linker flags (executables)
    • -
    - -Variants with the additional suffix "_DEBUG" and "_RELEASE" allow to set -separate values for debug and release builds. In case you do not want to add -additional flags, but to override the default flags, replace "CGAL" by -"CMAKE" in the variable names above. - -A comprehensive list of CMake variables can be found on the \ref configurationvariables page. - -Note that CMake maintains a cache name `CMakeCache.txt`. If you change options -(or your environment changes), it is best to remove that file to avoid -problems. - -\subsection installation_configuring_gui Configuring CGAL with the CMake GUI - -The simplest way to start the configuration process is to run the graphical -user interface of CMake, `cmake-gui`. You must pass as -argument the root directory of \cgal. For example: - - cd CGAL-\cgalReleaseNumber - cmake-gui . # Notice the dot to indicate the current directory - -After `cmake-gui` opens, press 'Configure'. -A dialog will pop up and you will have to choose what shall be generated. -After you have made your choice and pressed 'Finish', you will see -the output of configuration tests in the lower portion of the application. -When these tests are done, you will see many -red entries in the upper portion of the application. Just ignore them and press 'Configure'. -By now CMake should have found many libraries and have initialized variables. -If you still find red entries, you have to provide the necessary information. -This typically happens if you have installed software at non-standard locations. - -Providing information and pressing 'Configure' goes on until -all entries are grayed. You are now ready to press 'Generate'. Once this is -done, you can quit `cmake-gui`. - -\subsection installation_configuring_cmd Configuring CGAL with the cmake Command-Line Tool - -Alternatively, you can run the command-line tool called `cmake`. -You pass as argument the root directory of \cgal. -The command line tool `cmake` accepts CMake variables as arguments of the form `-D:=`, as -in the example above, but this is only useful if you already know which variables need to be explicitly defined. -For example: - - cd CGAL-\cgalReleaseNumber - cmake . # Notice the dot to indicate the current directory - -The configuration process not only determines the location of the required dependencies, it also dynamically generates a -`compiler_config.h` file, which encodes the properties of your system and a special file named -`CGALConfig.cmake`, which is used to build programs using \cgal. The -purpose of this file is explained below. - -\cgalAdvancedBegin -CMake keeps the variables that a user can manipulate in a -so-called CMake cache, a simple text file named -`CMakeCache.txt`, whose entries are of the form -`VARIABLE:TYPE=VALUE`. Advanced users can manually edit this file, -instead of going through the interactive configuration session. -\cgalAdvancedEnd - -\subsection installation_cgalconfig CGALConfig.cmake - -During configuration of the \cgal libraries a file named `CGALConfig.cmake` is generated -in \cgal's root directory (in contrast to \cgal's source directory that has been used -for installation). This file contains the definitions of several CMake variables -that summarize the configuration of \cgal and will be essential during the configuration and -building of a program using \cgal, see Section \ref installation_buildprogram. - -\section seccmakeoutofsource Multiple Variants of Makefiles (Out-of-Source Builds) - -While you can choose between release or debug builds, and shared or static libraries, -it is not possible to generate different variants during a single configuration. You need to run CMake in a -different directory for each variant you are interested in, each with its own selection of configuration parameters. - -CMake stores the resulting makefiles and project files, along with several temporary and auxiliary files such -as the variables cache, in the directory where it is executed, called `CMAKE_BINARY_DIR`, but it -takes the source files and configuration scripts from -`CMAKE_SOURCE_DIR`. - -The binary and source directories do not need to be the same. Thus, you can configure multiple variants by creating a -distinct directory for each configuration and by running CMake from there. This is known in CMake terminology -as out-of-source configuration, as opposite to an in-source -configuration, as showed in the previous sections. -You can, for example, generate subdirectories `CGAL-\cgalReleaseNumber``/cmake/platforms/debug` and -`CGAL-\cgalReleaseNumber``/cmake/platforms/release` for two configurations, respectively: - - mkdir CGAL-\cgalReleaseNumber/cmake/platforms/debug - cd CGAL-\cgalReleaseNumber/cmake/platforms/debug - cmake -DCMAKE_BUILD_TYPE=Debug ../../.. - - mkdir CGAL-\cgalReleaseNumber/cmake/platforms/release - cd CGAL-\cgalReleaseNumber/cmake/platforms/release - cmake -DCMAKE_BUILD_TYPE=Release ../../.. - -\section secbuilding Building CGAL - -The results of a successful configuration are build files that control the build step. -The nature of the build files depends on the generator used during configuration, but in all cases they -contain several targets, one per library, and a default global target corresponding -to all the libraries. - -For example, in a \sc{Unix}-like environment the default generator produces -makefiles. You can use the `make` command-line tool for the -succeeding build step as follows: - - # build all the selected libraries at once - make - -The resulting libraries are placed in the subdirectory `lib` under `` -(which is `CGAL-\cgalReleaseNumber` in case you run an in-source-configuration). - -With generators other than `UNIX Makefiles`, the resulting build files -are solution and project files which should be launched in an \sc{Ide}, -such as Visual Studio or KDevelop3. They will contain the targets described -above, which you can manually build as with any other solution/project within your \sc{Ide}. - -Alternatively, you can build it with the command line version of the -\sc{Visual Studio Ide}: - - devenv CGAL.sln /Build Debug - -The "Debug" argument is needed because CMake creates solution files for -all four configurations, and you need to explicitly choose one when building -(the other choices are `Release`, `RelWithDebInfo`, and `MinSizeRel`). - -\cgalAdvancedBegin -The build files produced by CMake are autoconfigured. That -is, if you change any of the dependencies, the build step -automatically goes all the way back to the configuration step. This -way, once the target has been configured the very first time by -invoking cmake, you don't necessarily need to invoke `cmake` -again. Rebuilding will call itself `cmake` and re-generate the -build file whenever needed. Keep this in mind if you configure \cgal -for the Visual Studio IDE since a build could then change the -solution/project file in-place and VS will prompt you to reload it. -\cgalAdvancedEnd - -\subsection ssec_installation_build_ex_demos Building Examples and Demos - -If you have turned on the configuration of examples -(`-DWITH_examples=ON`) and/or demos (`-DWITH_demos=ON`), there will be additional -targets named `examples` and `demos`, plus one target for -each example and each demo in the build files. -None of these targets are included by default, so you need to build them explicitly -after the \cgal libraries have been successfully built. -The targets `examples` and `demos` include themselves all the targets -for examples and demos respectively. - - # build all examples at once - make examples - - # build all demos at once - make demos - -If you are interested in the demos or examples of just a particular module, you can build them in the following way: - - make -C demo/Alpha_shapes_2 # equivalent to "cd demo/Alpha_shapes_2; make" - make -C examples/Alpha_shapes_2 # equivalent to "cd examples/Alpha_shapes_2; make" - -When using `UNIX Makefiles`, you can find out the exact name of the example or demo target -of a particular package by typing `make help | grep `. - -\section secinstalling Installing CGAL - -On many platforms, library pieces such as headers, docs and binaries -are expected to be placed in specific locations. A typical example -being `/usr/include` and `/usr/lib` on \sc{Unix}-like -operating systems or `C:/Program Files/` on Windows. The process -of placing or copying the library elements into its standard location -is sometimes referred to as Installation and it is a -postprocessing step after the build step. - -CMake carries out the installation by producing a build target named install. -Assuming you have successfully configured and built \cgal as demonstrated in the previous sections, -the installation simply amounts (in a \sc{Unix}-like environment) to: - - # install CGAL - make install - -If you use a generator that produces IDE files (for Visual Studio for instance), there will be an optional -`INSTALL` project, which you will be able to "build" to execute the installation step. - -\cgalAdvancedBegin -The files are copied into a directory tree relative to the installation directory determined by the -CMake variable `CMAKE_INSTALL_PREFIX`. This variable defaults to `/usr/local` under \sc{Unix}-like operating systems -and `C:\Program Files` under Windows. If you want to install to a different location, you must override that CMake -variable explicitly at the configuration time and not when executing the install step. -\cgalAdvancedEnd - -The file `CGALConfig.cmake` is installed by default in -`$CMAKE_INSTALLED_PREFIX/lib/``CGAL-\cgalReleaseNumber`. - -\section installation_buildprogram Building a Program using CGAL - -Similarly to \cgal and its libraries, compiling a program using \cgal is done in the usual -two steps of configuration and building. - -The configuration process is also done using `cmake` (or `cmake-gui`) and requires a `CMakeLists.txt` file. -This file is automatically provided for all shipped examples and demos of \cgal. -For other programs, CMake can also be used to configure -and build user programs, but one has to provide the corresponding `CMakeLists.txt`. -This script can be generated either manually, or with the help of a shell-script, -see Section \ref devman_create_cgal_CMakeLists. Using this shell-script, -the process of configuring a user's program called `executable.cpp` amounts to: - - cd /path/to/your/program - cgal_create_CMakeLists -s executable - cmake -DCGAL_DIR=XXXXXX -CMAKE_BUILD_TYPE=Release . - make - -In order to configure a program, you need to indicate the location of the configuration file -in the CMake variable `CGAL_DIR` (as indicated in the example above). -If you have installed \cgal, `CGAL_DIR` must afterwards be set to `$CMAKE_INSTALLED_PREFIX/lib/CGAL`. - -The variable `CGAL_DIR` can also be an environment variable, but setting it manually makes particular sense -if having multiple out-of-source builds of \cgal as in Section \ref seccmakeoutofsource. - -\section secspecificinstall OS Specific Installation - -Some operating systems with package managers offer \cgal and its -essential third party software through the manager, -for instance, Mac OS X or some Linux distribution (e.g. Debian). -For Windows, an installer is provided. - -\subsection sseccgalmacosxe CGAL on macOS - -The \cgal project recommends the use of Homebrew, in the following way: - - brew install cgal - -\subsection sseccgaldebian CGAL on Linux - -For instance in Debian/Ubuntu, use apt-get in the following way: - - sudo apt-get install libcgal-dev - -To get the demos, use: - - sudo apt-get install libcgal-demo - -For other distributions, please consult your respective package manager documentation. - -\subsection sseccgalwindows CGAL on Windows - -You can download and run `CGAL-\cgalReleaseNumber``-Setup.exe` from https://www.cgal.org/download/windows.html. -It is a self extracting executable that installs the \cgal source, and that allows you -to select and download some precompiled third party libraries. However, you will need to compile -the library using your favorite compiler. -A tutorial is provided on how to proceed with Microsoft Visual Studio. - -*/ diff --git a/Documentation/doc/Documentation/advanced/advanced.txt b/Documentation/doc/Documentation/advanced/advanced.txt deleted file mode 100644 index b6136edda22..00000000000 --- a/Documentation/doc/Documentation/advanced/advanced.txt +++ /dev/null @@ -1,8 +0,0 @@ -/*! - -\page advanced Advanced - -- \subpage configurationvariables lists the various CMake variables that can be used to help find third-party dependencies. -- \subpage installation describes the (optional) process of building and installing %CGAL itself. - -*/ From bbfb23181e2ca8cd9801960d267bda20ab35bcca Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9bastien=20Loriot?= Date: Thu, 17 Oct 2019 15:02:47 +0200 Subject: [PATCH 205/363] pass on the doc --- .../doc/Documentation/Getting_started.txt | 4 +- .../doc/Documentation/Preliminaries.txt | 4 - .../doc/Documentation/Third_party.txt | 347 +++++++++++++++++- Documentation/doc/Documentation/Usage.txt | 72 ++-- Documentation/doc/Documentation/main.txt | 9 - INSTALL.md | 55 +-- Installation/INSTALL.md | 15 +- Installation/doc_html/index.html | 10 +- README.md | 19 +- 9 files changed, 404 insertions(+), 131 deletions(-) diff --git a/Documentation/doc/Documentation/Getting_started.txt b/Documentation/doc/Documentation/Getting_started.txt index 5109bb23c9a..721df7da0b0 100644 --- a/Documentation/doc/Documentation/Getting_started.txt +++ b/Documentation/doc/Documentation/Getting_started.txt @@ -1,9 +1,9 @@ /*! \page general_intro Getting Started with %CGAL -- \subpage usage describes the few steps required to build a program using \cgal. +- \subpage usage describes how to get \cgal and the few steps required to build a program using \cgal. -- \subpage thirdparty lists the third party libraries on which \cgal depends, or for which \cgal provides interfaces. +- \subpage thirdparty lists required and optional third party libraries. - \subpage manual gives an idea of where you should look for documentation. diff --git a/Documentation/doc/Documentation/Preliminaries.txt b/Documentation/doc/Documentation/Preliminaries.txt index 9295914ac78..9f23bbda960 100644 --- a/Documentation/doc/Documentation/Preliminaries.txt +++ b/Documentation/doc/Documentation/Preliminaries.txt @@ -3,10 +3,6 @@ \page preliminaries General Information \cgalAutoToc -\cgalModifBegin -This page is bad... -\cgalModifEnd - The chapter explains some basic features of \cgal such as thread safety, code deprecation, checking of pre- and postconditions and altering the failure behavior, and how to control inlining. diff --git a/Documentation/doc/Documentation/Third_party.txt b/Documentation/doc/Documentation/Third_party.txt index 8f08e5bdd45..ef84bcb1fa4 100644 --- a/Documentation/doc/Documentation/Third_party.txt +++ b/Documentation/doc/Documentation/Third_party.txt @@ -37,7 +37,7 @@ The focus of \cgal is on geometry, and we rely on other highly specialized libraries and software for non-geometric issues, for instance for numeric solvers or visualization. We first list software that is essential to most of \cgal, and must therefore be found during the configuration of \cgal. -The page \ref configurationvariables lists CMake and environment variables which can be used to specify +The section \ref configurationvariables lists CMake and environment variables which can be used to specify the location of third-party software during configuration. \subsection thirdpartystl Standard Template Library (STL) @@ -97,7 +97,7 @@ certain optional libraries might be required to build examples and demos shipped with \cgal or to build your own project using \cgal; another reason is to speed up basic tasks where specialized libraries can be faster than the default version shipped with \cgal. -The page \ref configurationvariables lists CMake and environment variables which can be used to specify +The section \ref configurationvariables lists CMake and environment variables which can be used to specify the location of third-party software during configuration. \subsection thirdpartyQt Qt5 @@ -280,4 +280,347 @@ In \cgal, \sc{SCIP} provides an optional linear integer program solver in the \r The \sc{SCIP} web site is `http://scip.zib.de/`. +\section configurationvariables Summary of CGAL's Configuration Variables + +Most configuration variables are not environment variables but +CMake variables. They are given in the command line to CMake +via the `-D` option, or passed from the interactive interface +of `cmake-gui`. Unless indicated differently, all the variables +summarized below are CMake variables. + +\subsection installation_component_selection Component Selection + +The following Boolean variables enable the compilation of all examples and demos +at the same time. Their values can be ON or OFF. New corresponding targets will be +created, the compilation will be triggered by calling `make examples` and `make demos`. +To build a particular subset of examples or demos, from your build directory go +to the subdirectory `demo/PKG` or `example/PKG` and simply call make from there. + +| Variable | %Default Value | +| :------- | :--------------- | +| `WITH_examples` | OFF | +| `WITH_demos` | OFF | + +\subsection installation_flags Compiler and Linker Flags + +The following variables specify compiler and linker flags. Each variable holds a +space-separated list of command-line switches for the compiler and linker and +their default values are automatically defined by CMake based on the target platform. + +Have in mind that these variables specify a list of flags, not just one +single flag. If you provide your own definition for a variable, you will entirely override +the list of flags chosen by CMake for that particular variable. + +The variables that correspond to both debug and release builds are always +used in conjunction with those for the specific build type. + + +| Program | Both Debug and Release | Release Only | Debug Only | +| :------ | :---------------------- | :------------- | :----------- | +| C++ Compiler | `CMAKE_CXX_FLAGS` | `CMAKE_CXX_FLAGS_RELEASE` | `CMAKE_CXX_FLAGS_DEBUG` | +| Linker (shared libs) | `CMAKE_SHARED_LINKER_FLAGS` | `CMAKE_SHARED_LINKER_FLAGS_RELEASE` | `CMAKE_SHARED_LINKER_FLAGS_DEBUG` | +| Linker (static libs) | `CMAKE_MODULE_LINKER_FLAGS` | `CMAKE_MODULE_LINKER_FLAGS_RELEASE` | `CMAKE_MODULE_LINKER_FLAGS_DEBUG` | +| Linker (programs) | `CMAKE_EXE_LINKER_FLAGS` | `CMAKE_EXE_LINKER_FLAGS_RELEASE` | `CMAKE_EXE_LINKER_FLAGS_DEBUG`| + + +\subsection installation_additional_flags Additional Compiler and Linker Flags + +The following variables can be used to add flags without overriding the ones +defined by cmake. + + +| Program | Both Debug and Release | Release Only | Debug Only | +| :------ | :---------------------- | :------------- | :----------- | +| C++ Compiler | `CGAL_CXX_FLAGS` | `CGAL_CXX_FLAGS_RELEASE` | `CGAL_CXX_FLAGS_DEBUG` | +| Linker (shared libs) | `CGAL_SHARED_LINKER_FLAGS` | `CGAL_SHARED_LINKER_FLAGS_RELEASE` | `CGAL_SHARED_LINKER_FLAGS_DEBUG` | +| Linker (static libs) | `CGAL_MODULE_LINKER_FLAGS` | `CGAL_MODULE_LINKER_FLAGS_RELEASE` | `CGAL_MODULE_LINKER_FLAGS_DEBUG` | +| Linker (programs) | `CGAL_EXE_LINKER_FLAGS` | `CGAL_EXE_LINKER_FLAGS_RELEASE` | `CGAL_EXE_LINKER_FLAGS_DEBUG` | + +\subsection installation_misc Miscellaneous Variables + +Note that the default build type is `Debug`, which should only be used to debug +and will serverly limit performances. + +| Variable | Description | Type | %Default Value | +| :- | :- | :- | :- | +| `CMAKE_BUILD_TYPE` | Indicates type of build. Possible values are 'Debug' or 'Release' | CMake | | +| `CMAKE_INSTALL_PREFIX`| Installation directory path | CMake | Debug | +| `CMAKE_C_COMPILER` | Full-path to the executable corresponding to the C compiler to use. | CMake | platform-dependent | +| `CMAKE_CXX_COMPILER` | Full-path to the executable corresponding to the C++ compiler to use. | CMake | platform-dependent | +| `CXX` | Idem | Environment | Idem | +| `BUILD_SHARED_LIBS` | Whether to build shared or static libraries. | CMake | TRUE | + +\subsection installation_variables_building Variables Used Only When Building Programs (Such as Demos or Examples) + + +| Variable | Description | Type | %Default Value | +| :- | :- | :- | :- | +| `CGAL_DIR` | Full-path to the binary directory where \cgal was configured |Either CMake or Environment | none | + + +\subsection installation_variables_third_party Variables Providing Information About 3rd-Party Libraries +\anchor sec3partysoftwareconfig + +The following variables provide information about the availability and +location of the 3rd party libraries used by \cgal. CMake automatically +searches for dependencies so you need to specify these variables if +CMake was unable to locate something. This is indicated by a value ending in +`NOTFOUND`. + +Since 3rd-party libraries are system wide, many of the CMake variables listed below can alternatively +be given as similarly-named environment variables instead. Keep in mind that you must provide one or the +other but never both. + +\subsection installation_boost Boost Libraries + +In most cases, if \sc{Boost} is not automatically found, setting the `BOOST_ROOT` +variable is enough. If it is not, you can specify the header and library +directories individually. You can also provide the full pathname to a specific compiled library +if it cannot be found in the library directory or its name is non-standard. + +By default, when \sc{Boost} binary libraries are needed, the shared versions +are used if present. You can set the variable +`CGAL_Boost_USE_STATIC_LIBS` to `ON` if you want to link +with static versions explicitly. + +On Windows, if you link with \sc{Boost} shared libraries, you must ensure that +the `.dll` files are found by the dynamic linker, at run time. +For example, you can add the path to the \sc{Boost} `.dll` to the +`PATH` environment variable. + +| Variable | Description | Type | +| :- | :- | :- | +| `BOOST_ROOT`\cgalFootnote{The environment variable can be spelled either `BOOST_ROOT` or `BOOSTROOT`} | Root directory of your \sc{Boost} installation | Either CMake or Environment | +| `Boost_INCLUDE_DIR` | Directory containing the `boost/version.hpp` file | CMake | +| `BOOST_INCLUDEDIR` | Idem | Environment | +| `Boost_LIBRARY_DIRS` | Directory containing the compiled \sc{Boost} libraries | CMake | +| `BOOST_LIBRARYDIR` | Idem | Environment | +| `Boost_(xyz)_LIBRARY_RELEASE` | Full pathname to a release build of the compiled 'xyz' \sc{Boost} library | CMake | +| `Boost_(xyz)_LIBRARY_DEBUG` | Full pathname to a debug build of the compiled 'xyz' \sc{Boost} library | CMake | + + +\subsection installation_gmp GMP and MPFR Libraries + +Under Windows, auto-linking is used, so only the directory +containing the libraries is needed and you would specify `GMP|MPFR_LIBRARY_DIR` rather than +`GMP|MPFR_LIBRARIES`. On the other hand, under Linux the actual library filename is needed. +Thus you would specify `GMP|MPFR_LIBRARIES`. In no case you need to specify both. + +\cgal uses both \sc{Gmp} and \sc{Mpfr} so both need to be supported. If either of them is unavailable the +usage of \sc{Gmp} and of \sc{Mpfr} will be disabled. + + +| Variable | Description | Type | +| :- | :- | :- | +| `CGAL_DISABLE_GMP` | Indicates whether to search and use \sc{Gmp}/\sc{Mpfr} or not | CMake | +| `GMP_DIR` | Directory of \sc{Gmp} default installation | Environment | +| `GMP_INCLUDE_DIR` | Directory containing the `gmp.h` file | CMake | +| `GMP_INC_DIR` | Idem | Environment | +| `GMP_LIBRARIES_DIR` | Directory containing the compiled \sc{Gmp} library | CMake | +| `GMP_LIB_DIR` | Idem | Environment | +| `GMP_LIBRARIES` | Full pathname of the compiled \sc{Gmp} library | CMake | +| `MPFR_INCLUDE_DIR` | Directory containing the `mpfr.h` file | CMake | +| `MPFR_INC_DIR` | Idem | Environment | +| `MPFR_LIBRARIES_DIR` | Directory containing the compiled \sc{Mpfr} library | CMake | +| `MPFR_LIB_DIR` | Idem | Environment | +| `MPFR_LIBRARIES` | Full pathname of the compiled \sc{Mpfr} library | CMake | + + + +Under Linux, the \sc{Gmpxx} is also searched for, and you may specify the following variables: + + +| Variable | Description | Type | +| :- | :- | :- | +| `GMPXX_DIR` | Directory of \sc{gmpxx} default installation | Environment | +| `GMPXX_INCLUDE_DIR` | Directory containing the `gmpxx.h` file | CMake | +| `GMPXX_LIBRARIES` | Full pathname of the compiled \sc{Gmpxx} library | CMake | + + + +\subsection installation_qt5 Qt5 Library + +You must set the cmake or environment variable `Qt5_DIR` to point to the path +to the directory containing the file `Qt5Config.cmake` created by your \sc{Qt}5 installation. If you are +using the open source edition it should be `/qt-everywhere-opensource-src-/qtbase/lib/cmake/Qt5`. + +\subsection installation_leda LEDA Library + +When the \leda libraries are not automatically found, yet they are installed on the system +with base names 'leda' and 'ledaD' (for the release and debug versions resp.), it might +be sufficient to just indicate the library directory via the `LEDA_LIBRARY_DIRS` variable. +If that doesn't work because, for example, the names are different, you can provide the full pathnames of each variant +via `LEDA_LIBRARY_RELEASE` and `LEDA_LIBRARY_DEBUG`. + +The variables specifying definitions and flags can be left undefined if they are not needed by LEDA. + + +| Variable | Description | Type | +| :- | :- | :- | +| `WITH_LEDA` | Indicates whether to search and use \leda or not | CMake | +| `LEDA_DIR` | Directory of \sc{LEDA} default installation | Environment | +| `LEDA_INCLUDE_DIR` | Directory containing the file `LEDA/system/basic.h` | CMake | +| `LEDA_LIBRARIES` | Directory containing the compiled \leda libraries | CMake | +| `LEDA_INC_DIR` | Directory containing the file `LEDA/system/basic.h` | Environment | +| `LEDA_LIB_DIR` | Directory containing the compiled \leda libraries | Environment | +| `LEDA_LIBRARY_RELEASE` | Full pathname to a release build of the \leda library | CMake | +| `LEDA_LIBRARY_DEBUG` | Full pathname to a debug build of the \leda library | CMake | +| `LEDA_DEFINITIONS` | Preprocessor definitions | CMake | +| `LEDA_CXX_FLAGS` | Compiler flags | CMake | +| `LEDA_LINKER_FLAGS` | Linker flags | CMake | + + +\subsection installation_mpfi MPFI Library + +\cgal provides a number type based on this library, but the \cgal library +itself does not depend on \sc{Mpfi}. This means that this library must be +configured when compiling an application that uses the above number type. + +When \sc{Mpfi} files are not on the standard path, the locations of the headers +and library files must be specified by using environment variables. + + +| Variable | Description | Type | +| :- | :- | :- | +| `MPFI_DIR` |Directory of \sc{MPFI} default installation | Environment | +| `MPFI_INCLUDE_DIR` | Directory containing the `mpfi.h` file | CMake | +| `MPFI_INC_DIR` | Idem | Environment | +| `MPFI_LIBRARIES_DIR` | Directory containing the compiled \sc{Mpfi} library | CMake | +| `MPFI_LIB_DIR` | Idem | Environment | +| `MPFI_LIBRARIES` | Full pathname of the compiled \sc{Mpfi} library | CMake | + + + +\subsection installation_rs RS and RS3 Library + +As said before, only the \cgal univariate algebraic kernel depends on the +library Rs. As the algebraic kernel is not compiled as a part of the \cgal +library, this library is not detected nor configured at installation time. + +CMake will try to find Rs in the standard header and library +directories. When it is not automatically detected, the locations of the +headers and library files must be specified using environment variables. + +Rs needs \sc{Gmp} 4.2 or later and \sc{Mpfi} 1.3.4 or later. The variables +related to the latter library may also need to be defined. + + +| Variable | Description | Type | +| :- | :- | :- | +| `RS_DIR` | Directory of \sc{Rs} default installation | Environment | +| `RS_INCLUDE_DIR` | Directory containing the `rs_exports.h` file | CMake | +| `RS_INC_DIR` | Idem | Environment | +| `RS_LIBRARIES_DIR` | Directory containing the compiled \sc{Rs} library | CMake | +| `RS_LIB_DIR` | Idem | Environment | +| `RS_LIBRARIES` | Full pathname of the compiled \sc{Rs} library | CMake | + +Similar variables exist for \sc{Rs3}. + +| Variable | Description | Type | +| :- | :- | :- +| `RS3_DIR` | Directory of \sc{Rs3} default installation | Environment | +| `RS3_INCLUDE_DIR` | Directory containing the file `rs3_fncts.h` file | CMake | +| `RS3_INC_DIR` | Idem | Environment | +| `RS3_LIBRARIES_DIR` | Directory containing the compiled \sc{Rs3} library | CMake | +| `RS3_LIB_DIR` | Idem | Environment | +| `RS3_LIBRARIES` | Full pathname of the compiled \sc{Rs3} library | CMake | + + +\subsection installation_ntl NTL Library + +Some polynomial computations in \cgal's algebraic kernel +are speed up when \sc{Ntl} is available. +As the algebraic kernel is not compiled as a part of the \cgal +library, this library is not detected nor configured at installation time. + +CMake will try to find \sc{Ntl} in the standard header and library +directories. When it is not automatically detected, the locations of the +headers and library files must be specified using environment variables. + +| Variable | Description | Type | +| :- | :- | :- | +| `NTL_DIR` | Directory of \sc{NTL} default installation | Environment | +| `NTL_INCLUDE_DIR` | Directory containing the `NTL/ZZX.h` file | CMake | +| `NTL_INC_DIR` | Idem | Environment | +| `NTL_LIBRARIES_DIR` | Directory containing the compiled \sc{Ntl} library | CMake | +| `NTL_LIB_DIR` | Idem | Environment | +| `NTL_LIBRARIES` | Full pathname of the compiled \sc{Ntl} library | CMake | + +\subsection installation_eigen Eigen Library + +\sc{Eigen} is a header-only template library. +Only the directory containing the header files of \sc{Eigen} 3.1 (or greater) is needed. + + +| Variable | Description | Type | +| :- | :- | :- | +| `EIGEN3_INCLUDE_DIR` | Directory containing the file `signature_of_eigen3_matrix_library` | CMake | +| `EIGEN3_INC_DIR` | Idem | Environment | + +\subsection installation_esbtl ESBTL Library + +One skin surface example requires the \sc{Esbtl} library in order to read \sc{Pdb} files. + +If \sc{Esbtl} is not automatically found, setting the `ESBTL_INC_DIR` +environment variable is sufficient. + + +| Variable | Description | Type | +| :- | :- | :- | +| `ESBTL_DIR` | Directory of \sc{ESBTL} default installation | Environment | +| `ESBTL_INC_DIR` | Directory containing the `ESBTL/default.h` file | Environment | +| `ESBTL_INCLUDE_DIR` | Directory containing the `ESBTL/default.h` file | CMake | + +\subsection installation_tbb TBB Library + +If \sc{Tbb} is not automatically found, the user must set the `TBB_ROOT` +environment variable. The environment variable `TBB_ARCH_PLATFORM=/` must be set. +`` is `ia32` or `intel64`. `` describes the Linux kernel, gcc version or Visual Studio version +used. It should be set to what is used in `$TBB_ROOT/lib/`. + +For windows users, the folder `TBB_ROOT/bin//` should be added to the `PATH` variable. + +Note that the variables in the table below are being used. + +| Variable | Description | Type | +| :- | :- | :- | +| `TBB_ROOT` | Directory of \sc{Tbb} default installation | Environment | +| `TBB_INCLUDE_DIRS` | Directory containing the `tbb/tbb.h` file | CMake | +| `TBB_LIBRARY_DIRS` | Directory(ies) containing the compiled TBB libraries | CMake | +| `TBB_LIBRARIES` | Full pathnames of the compiled TBB libraries (both release and debug versions, using "optimized" and "debug" CMake keywords). Note that if the debug versions are not found, the release versions will be used instead for the debug mode. | CMake | +| `TBB_RELEASE_LIBRARY` | Full pathname of the compiled TBB release library | CMake | +| `TBB_MALLOC_RELEASE_LIBRARY` | Full pathname of the compiled TBB release malloc library | CMake | +| `TBB_DEBUG_LIBRARY` | Full pathname of the compiled TBB debug library | CMake | +| `TBB_MALLOC_DEBUG_LIBRARY` | Full pathname of the compiled TBB debug malloc library | CMake | +| `TBB_MALLOCPROXY_DEBUG_LIBRARY` | Full pathname of the compiled TBB debug malloc_proxy library (optional) | CMake | +| `TBB_MALLOCPROXY_RELEASE_LIBRARY` | Full pathname of the compiled TBB release malloc_proxy library (optional) | CMake | + +\subsection installation_compiler_workarounds Compiler Workarounds + +A number of boolean flags are used to workaround compiler bugs and +limitations. They all start with the prefix `CGAL_CFG`. These +flags are used to work around compiler bugs and limitations. For +example, the flag `CGAL_CFG_NO_CPP0X_LONG_LONG` denotes +that the compiler does not know the type `long long`. + +For each installation a file +is defined, with the correct +settings of all flags. This file is generated automatically by CMake, +and it is located in the `include` directory of where you run +CMake. For an in-source configuration this means +`CGAL-\cgalReleaseNumber``/include`. + +The test programs used to generate the `compiler_config.h` +file can be found in `config/testfiles`. +Both +`compiler_config.h` and the test programs contain a short +description of the problem. In case of trouble with one of the +`CGAL_CFG` flags, it is a good idea to take a look at it. + +The file `CGAL/compiler_config.h` is included from +``. +which is included by all \cgal header files. + + + */ diff --git a/Documentation/doc/Documentation/Usage.txt b/Documentation/doc/Documentation/Usage.txt index 252d769ab52..9deb7935c69 100644 --- a/Documentation/doc/Documentation/Usage.txt +++ b/Documentation/doc/Documentation/Usage.txt @@ -6,14 +6,16 @@ Since \cgal version 5.0, \cgal is header-only be default, which means that there is no need to build or install \cgal before it can be used. However, some dependencies of \cgal might still need to be installed. -\section usage_introduction Quick Start +\section usage_introduction Quick Start: Compiling a Program using CGAL -Ideally, compiling an example shipped with \cgal is as simple as: +Given that you have extracted the \cgal source archive in `$HOME`, compiling an example shipped with \cgal is as simple as: - cd examples/Triangulation_2 # go to an example directory + cd $HOME/CGAL-\cgalReleaseNumber/examples/Triangulation_2 # go to an example directory cmake -DCGAL_DIR=$HOME/CGAL-\cgalReleaseNumber -DCMAKE_BUILD_TYPE=Release . # configure the examples make # build the examples +On Windows, instead of calling `make` simply double-click on the generated solution (`.sln`) to open Visual C++. + Compiling your own program is similar: cd /path/to/your/program @@ -23,14 +25,10 @@ Compiling your own program is similar: The script `cgal_create_CMakeLists` and its options are detailed in Section \ref devman_create_cgal_CMakeLists. -\cgalModifBegin -Something about Windows? -\cgalModifEnd - In a less ideal world, you might have to install some required tools and third-party libraries. This is what this page is about. -\section secprerequisites Prerequisites +\section secprerequisites Prerequisites Using \cgal requires a few core components to be previously installed:
      @@ -45,6 +43,41 @@ or to build your own project using \cgal, see Section \ref secoptional3rdpartyso \section secgettingcgal Downloading CGAL +\subsection secusingpkgman Using a Package Manager + +On most common operating systems, package managers offer \cgal and its essential third party dependencies. + +On macOS we recommend to use of Homebrew in the following way: + + brew install cgal + +If not automatically found, the `CGAL_DIR` to provide to cmake when configuring a program using \cgal should be something like `/usr/local/Cellar/cgal/4.14.1/lib/cmake/CGAL`. + +On Linux distributions like Debian/Ubuntu/Mint, use `apt-get` in the following way: + + sudo apt-get install libcgal-dev + +If not automatically found, the `CGAL_DIR` to provide to cmake when configuring a program using \cgal should be something like `/usr/lib/x86_64-linux-gnu/cmake/CGAL`. + +On Windows, we recommand to use vcpkg in the following way: + + vcpkg install cgal + +If not automatically found, the `CGAL_DIR` to provide to cmake when configuring a program using \cgal should be something like `VCPK_DIR/packages/cgal_x64-windows/lib/cgal` + +For other distributions or package manager, please consult your respective documentation. + +\subsection sseccgalwindows Using CGAL installer on Windows + +You can download and run `CGAL-\cgalReleaseNumber``-Setup.exe` from https://www.cgal.org/download/windows.html. +It is a self extracting executable that installs the \cgal source, and that allows you +to select and download some precompiled third party libraries. However, you will need to compile +the library using your favorite compiler. +A tutorial is provided on how to proceed with Microsoft Visual Studio. + + +\subsection secusingwebsite From CGAL website + You can obtain the \cgal library from https://www.cgal.org/download.html. @@ -95,29 +128,6 @@ Note that even though \cgal can be used as a header-only library, not all its de are header-only. The libraries \sc{Gmp} and \sc{Mpfr}, for example, are not header-only. As such, these dependencies must be built or installed independently. -\subsection subsection_headeronly_pbonwindows Potential Issue on Windows - -\cgalModifBegin -(RE)MOVE THAT? -\cgalModifEnd - -A potential issue when using \cgal in header-only mode on a Windows operating system can arise -when compiling a program using several modules (executable programs or dynamic-link libraries DLL). -If two different modules use the same static variable, this variable is defined independently -in each of these modules. If one module modifies the value of this variable, it will not be modified -in the other module, which could induce an unexpected behavior. In \cgal, this concerns only -a few specific variables: the default random, -the failure behavior, -`CGAL::IO::Mode`. One example is the following: if you change the default random in one DLL, then -if you use the default random in another DLL, you will not obtain the modified default random but the original one. - -\subsection usage_installingcgal Building and Installing CGAL - -Although using the header-only mode makes building and installing \cgal obsolete, it is still possible -to configure, build, and install \cgal. Head over to \ref installation for more information. It is -however advised by the \cgal project to use the much simpler header-only mode, and the present page -assumes that this configuration is being used. - \section usage_configuring Configuring your Program Before building anything using \cgal you have to choose the compiler/linker, set compiler diff --git a/Documentation/doc/Documentation/main.txt b/Documentation/doc/Documentation/main.txt index 694fed1c507..499cfae41fb 100644 --- a/Documentation/doc/Documentation/main.txt +++ b/Documentation/doc/Documentation/main.txt @@ -25,14 +25,6 @@ the Boost Graph Library. Getting Started =============== -\cgalModifBegin -remove? -In the distribution of the library, you will find the directories *demo* and *examples*. -They contain subdirectories for the \cgal packages. -The demos use third-party libraries for the graphical user interface. -The examples do not have this dependency and most examples are referred to in the user manual. -\cgalModifEnd - Head over to the page \ref general_intro, which will guide your first steps with \cgal. License @@ -56,7 +48,6 @@ For releases X.Y, with 3.1 <= X.Y <= 4.1 visit \endhtmlonly \subpage general_intro -\subpage advanced \subpage tutorials \subpage packages \subpage dev_manual diff --git a/INSTALL.md b/INSTALL.md index 0a5b795a378..8913be934e0 100644 --- a/INSTALL.md +++ b/INSTALL.md @@ -1,9 +1,8 @@ NOTICE ====== -Since Version 5.0, CGAL is now header-only by default, meaning that it is no longer mandatory -to build (and install) CGAL and its libraries. Usage of CGAL as a header-only library should -thus simply amount to: +Since Version 5.0, CGAL is a header-only library it is not needed +to build and install it. Usage of CGAL should thus simply amount to: ``` {.bash} git clone https://github.com/CGAL/cgal.git /path/to/cgal.git @@ -16,38 +15,17 @@ make in the case of the building of an example in debug mode. -More information on dependencies, configuration flags, and useful scripts to build programs that are not shipped -with CGAL can be found on header-only usage at https://doc.cgal.org/latest/Manual/general_intro.html, -noting that this page describes the setting of CGAL as a sources release and, as such, +For more information head over to the [CGAL manual](https://doc.cgal.org/latest/Manual/general_intro.html). +Note that this page describes the setting of CGAL as a sources release and, as such, files are organized in a slightly different way, see the [Layout of the CGAL Git Repository](README.md). -BRANCH BUILD OF CGAL -==================== - -Although not recommended, it is still possible to build (and install) CGAL. - -The cmake script at the root of the repository is the one to use to -build the CGAL library from a branch. It will collect the list of packages -of the branch and will append their include folder to the include path. -This is main noticeable difference with a build using a regular *flat* release. - -Here is an example of how to build the library in Release: -``` {.bash} -git clone https://github.com/CGAL/cgal.git /path/to/cgal.git -cd /path/to/cgal.git -mkdir -p build/release -cd build/release -cmake -DCMAKE_BUILD_TYPE=Release ../.. -make -``` - -Note that *no installation is required* to use that version of CGAL once it has been compiled. Building a Program Using CGAL ============================= To compile a program using CGAL, simply set `CGAL_DIR` to the location -of where you have built the library (environment or cmake variable). +of the directory containing `CGALConfig.cmake` (for example the root +of the extracted source archive or the root of a git checkout). Here is an example of how to build in debug the examples from the 3D Triangulations package: @@ -55,7 +33,7 @@ Here is an example of how to build in debug the examples from the 3D Triangulati cd /path/to/cgal.git/Triangulation_3/examples/Triangulation_3 mkdir -p build/debug cd build/debug - cmake -DCGAL_DIR:PATH=/path/to/cgal.git/build/debug ../.. + cmake -DCGAL_DIR:PATH=/path/to/cgal.git ../.. make ``` @@ -70,23 +48,8 @@ Here is an example for the examples of the 2D Triangulation package: cd /path/to/cgal.git/Triangulation_2/examples/Triangulation_2 mkdir -p build/debug cd build/debug - cmake -DCGAL_DIR:PATH=/path/to/cgal.git/build/debug ../.. + cmake -DCGAL_DIR:PATH=/path/to/cgal.git ../.. make ``` -More information on building and installing CGAL is available in the CGAL manual, -at https://doc.cgal.org/latest/Manual/installation.html, noting that this page describes the setting -of CGAL as a sources release and, as such, files are organized in a slightly different way, -see the [Layout of the CGAL Git Repository](README.md). - -Note If You Switch Between Branches -=================================== - -A build may be outdated after an include/dir has been deleted, -switched or even updated. This might lead to compile problems (link -with outdated version). Thus, it is recommended to build CGAL after -each update, switch, merge of a branch (in particular if directories -have been added/deleted, or cpp files have been added, deleted or -altered). - - +For more information head over to the [CGAL manual](https://doc.cgal.org/latest/Manual/general_intro.html). diff --git a/Installation/INSTALL.md b/Installation/INSTALL.md index 226b26077c6..54d011ef408 100644 --- a/Installation/INSTALL.md +++ b/Installation/INSTALL.md @@ -1,8 +1,7 @@ NOTICE ====== -Since Version 5.0, CGAL is now header-only by default, meaning that it is no longer mandatory -to build (and install) CGAL and its libraries. Usage of CGAL as a header-only library +Since Version 5.0, CGAL is now header-only by default, meaning that you do not need to build and install CGAL. Usage of CGAL as a header-only library simply amounts to, for example: ``` {.bash} @@ -13,14 +12,4 @@ cmake -DCMAKE_BUILD_TYPE=Debug -DCGAL_DIR=/path/to/cgal make ``` -More information on header-only dependencies, configuration flags, and useful scripts to build programs -that are not shipped with CGAL is available in this distribution in the file ./doc_html/index.html -("Getting Started with CGAL"), or on the CGAL website at https://doc.cgal.org/latest/Manual/general_intro.html - -BUILDING AND INSTALLING CGAL -============================ - -Although not recommended, it is still possible to build and install CGAL. More information on -building and installing CGAL is available in this distribution in the file ./doc_html/index.html -("Advanced" > "Installation"), or on the CGAL website at https://doc.cgal.org/latest/Manual/installation.html - +For more information head over to the [CGAL manual](https://doc.cgal.org/latest/Manual/general_intro.html). diff --git a/Installation/doc_html/index.html b/Installation/doc_html/index.html index 0c67b663e5e..1c7c7682d48 100644 --- a/Installation/doc_html/index.html +++ b/Installation/doc_html/index.html @@ -25,13 +25,9 @@ in the form of a C++ library.

      Manuals

      - - + @@ -39,7 +35,7 @@ in the form of a C++ library. diff --git a/README.md b/README.md index 9a075d50731..2f816f729cb 100644 --- a/README.md +++ b/README.md @@ -14,27 +14,12 @@ twice a year, announced on [the web site of CGAL](https://www.cgal.org/). Getting Started with CGAL ========================= -**Since version 5.0, CGAL is header-only by default, meaning that -it is no longer necessary to build or install CGAL before it can be used.** +**Since version 5.0, CGAL is a header-only library, meaning that +it is no longer needed to build or install CGAL before it can be used.** Head over to the [CGAL manual](https://doc.cgal.org/latest/Manual/general_intro.html) for usage guides and tutorials that will get you started smoothly. -Compilation and Installation -============================ - -If you do not wish to use the header-only mode of CGAL, it is still possible to build CGAL itself. - -The compilation and installation of CGAL from a sources tarball are -described in the [CGAL installation manual](https://doc.cgal.org/latest/Manual/installation.html) -and in the file [INSTALL.md](Installation/INSTALL.md) that is at the root -of any sources tarball. - -You can also clone this repository and compile from your local Git repository. -This kind of compilation is called a *branch build*, and is -described in the file [INSTALL.md](INSTALL.md) that is at the root of the -Git repository. - License ======= See the file [LICENSE.md](LICENSE.md). From 71cb5d2ccd8b19014afb37cab65d6065d8e71e6a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9bastien=20Loriot?= Date: Fri, 18 Oct 2019 09:27:57 +0200 Subject: [PATCH 206/363] mention vcpkg doc --- Documentation/doc/Documentation/Usage.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/Documentation/doc/Documentation/Usage.txt b/Documentation/doc/Documentation/Usage.txt index 9deb7935c69..92b9fb7c469 100644 --- a/Documentation/doc/Documentation/Usage.txt +++ b/Documentation/doc/Documentation/Usage.txt @@ -63,6 +63,7 @@ On Windows, we recommand to use vc vcpkg install cgal +To see how to use libraries installed with vcpkg refer to the official documentation. If not automatically found, the `CGAL_DIR` to provide to cmake when configuring a program using \cgal should be something like `VCPK_DIR/packages/cgal_x64-windows/lib/cgal` For other distributions or package manager, please consult your respective documentation. From 51d1c58b4628547d2145f9fe4f896a73909eb976 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9bastien=20Loriot?= Date: Fri, 18 Oct 2019 10:01:05 +0200 Subject: [PATCH 207/363] more updates --- Documentation/doc/Documentation/Usage.txt | 4 ++-- Documentation/doc/Documentation/main.txt | 14 +++++++++++++- 2 files changed, 15 insertions(+), 3 deletions(-) diff --git a/Documentation/doc/Documentation/Usage.txt b/Documentation/doc/Documentation/Usage.txt index 92b9fb7c469..472a81ecf72 100644 --- a/Documentation/doc/Documentation/Usage.txt +++ b/Documentation/doc/Documentation/Usage.txt @@ -77,7 +77,7 @@ the library using your favorite compiler. A tutorial is provided on how to proceed with Microsoft Visual Studio. -\subsection secusingwebsite From CGAL website +\subsection secusingwebsite Using CGAL Source Archive You can obtain the \cgal library from https://www.cgal.org/download.html. @@ -88,7 +88,7 @@ command: tar xzf CGAL-\cgalReleaseNumber.tar.gz -In both cases, the directory `CGAL-\cgalReleaseNumber` will be created. This directory +The directory `CGAL-\cgalReleaseNumber` will be created. This directory contains the following subdirectories: | Directory | Contents | diff --git a/Documentation/doc/Documentation/main.txt b/Documentation/doc/Documentation/main.txt index 499cfae41fb..c7b58497673 100644 --- a/Documentation/doc/Documentation/main.txt +++ b/Documentation/doc/Documentation/main.txt @@ -25,7 +25,19 @@ the Boost Graph Library. Getting Started =============== -Head over to the page \ref general_intro, which will guide your first steps with \cgal. + +- \ref usage describes how to get \cgal and the few steps required to build a program using \cgal. + +- \ref thirdparty lists required and optional third party libraries. + +- \ref manual gives an idea of where you should look for documentation. + +- \ref preliminaries lists how to control inlining, thread safety, code deprecation, checking of pre- and postconditions, and how to alter the failure behavior. + +Once you are familiar with building your programs with \cgal and how the documentation is structured, +you can head over to the \ref tutorials for a hand-in-hand introduction to \cgal data structures +and algorithms, or directly to the package(s) that interest you the \ref packages. Each package +contains simple examples of the various functionalities of the package. License ======= From b5669f56108e0bd9eadf4fb002110a792c8fd800 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mael=20Rouxel-Labb=C3=A9?= Date: Sat, 19 Oct 2019 16:18:32 +0200 Subject: [PATCH 208/363] Another pass on the installation documentation --- .../Documentation/Configuration_variables.txt | 345 +++++++++++++++++ .../doc/Documentation/Getting_started.txt | 2 +- .../doc/Documentation/Third_party.txt | 347 +----------------- Documentation/doc/Documentation/Usage.txt | 3 +- Documentation/doc/Documentation/main.txt | 5 +- 5 files changed, 352 insertions(+), 350 deletions(-) create mode 100644 Documentation/doc/Documentation/Configuration_variables.txt diff --git a/Documentation/doc/Documentation/Configuration_variables.txt b/Documentation/doc/Documentation/Configuration_variables.txt new file mode 100644 index 00000000000..7e7080f964f --- /dev/null +++ b/Documentation/doc/Documentation/Configuration_variables.txt @@ -0,0 +1,345 @@ +/*! + +\page configurationvariables Summary of CGAL's Configuration Variables +\cgalAutoToc + +Most configuration variables are not environment variables but +CMake variables. They are given in the command line to CMake +via the `-D` option, or passed from the interactive interface +of `cmake-gui`. Unless indicated differently, all the variables +summarized below are CMake variables. + +\section installation_component_selection Component Selection + +The following Boolean variables enable the compilation of all examples and demos +at the same time. Their values can be ON or OFF. New corresponding targets will be +created, the compilation will be triggered by calling `make examples` and `make demos`. +To build a particular subset of examples or demos, from your build directory go +to the subdirectory `demo/PKG` or `example/PKG` and simply call make from there. + +| Variable | %Default Value | +| :------- | :--------------- | +| `WITH_examples` | OFF | +| `WITH_demos` | OFF | + +\section installation_flags Compiler and Linker Flags + +The following variables specify compiler and linker flags. Each variable holds a +space-separated list of command-line switches for the compiler and linker and +their default values are automatically defined by CMake based on the target platform. + +Have in mind that these variables specify a list of flags, not just one +single flag. If you provide your own definition for a variable, you will entirely override +the list of flags chosen by CMake for that particular variable. + +The variables that correspond to both debug and release builds are always +used in conjunction with those for the specific build type. + + +| Program | Both Debug and Release | Release Only | Debug Only | +| :------ | :---------------------- | :------------- | :----------- | +| C++ Compiler | `CMAKE_CXX_FLAGS` | `CMAKE_CXX_FLAGS_RELEASE` | `CMAKE_CXX_FLAGS_DEBUG` | +| Linker (shared libs) | `CMAKE_SHARED_LINKER_FLAGS` | `CMAKE_SHARED_LINKER_FLAGS_RELEASE` | `CMAKE_SHARED_LINKER_FLAGS_DEBUG` | +| Linker (static libs) | `CMAKE_MODULE_LINKER_FLAGS` | `CMAKE_MODULE_LINKER_FLAGS_RELEASE` | `CMAKE_MODULE_LINKER_FLAGS_DEBUG` | +| Linker (programs) | `CMAKE_EXE_LINKER_FLAGS` | `CMAKE_EXE_LINKER_FLAGS_RELEASE` | `CMAKE_EXE_LINKER_FLAGS_DEBUG`| + + +\section installation_additional_flags Additional Compiler and Linker Flags + +The following variables can be used to add flags without overriding the ones +defined by cmake. + + +| Program | Both Debug and Release | Release Only | Debug Only | +| :------ | :---------------------- | :------------- | :----------- | +| C++ Compiler | `CGAL_CXX_FLAGS` | `CGAL_CXX_FLAGS_RELEASE` | `CGAL_CXX_FLAGS_DEBUG` | +| Linker (shared libs) | `CGAL_SHARED_LINKER_FLAGS` | `CGAL_SHARED_LINKER_FLAGS_RELEASE` | `CGAL_SHARED_LINKER_FLAGS_DEBUG` | +| Linker (static libs) | `CGAL_MODULE_LINKER_FLAGS` | `CGAL_MODULE_LINKER_FLAGS_RELEASE` | `CGAL_MODULE_LINKER_FLAGS_DEBUG` | +| Linker (programs) | `CGAL_EXE_LINKER_FLAGS` | `CGAL_EXE_LINKER_FLAGS_RELEASE` | `CGAL_EXE_LINKER_FLAGS_DEBUG` | + +\section installation_misc Miscellaneous Variables + +Note that the default build type is `Debug`, which should only be used to debug +and will serverly limit performances. + +| Variable | Description | Type | %Default Value | +| :- | :- | :- | :- | +| `CMAKE_BUILD_TYPE` | Indicates type of build. Possible values are 'Debug' or 'Release' | CMake | | +| `CMAKE_INSTALL_PREFIX`| Installation directory path | CMake | Debug | +| `CMAKE_C_COMPILER` | Full-path to the executable corresponding to the C compiler to use. | CMake | platform-dependent | +| `CMAKE_CXX_COMPILER` | Full-path to the executable corresponding to the C++ compiler to use. | CMake | platform-dependent | +| `CXX` | Idem | Environment | Idem | +| `BUILD_SHARED_LIBS` | Whether to build shared or static libraries. | CMake | TRUE | + +\section installation_variables_building Variables Used Only When Building Programs (Such as Demos or Examples) + + +| Variable | Description | Type | %Default Value | +| :- | :- | :- | :- | +| `CGAL_DIR` | Full-path to the binary directory where \cgal was configured |Either CMake or Environment | none | + + +\section installation_variables_third_party Variables Providing Information About 3rd-Party Libraries +\anchor sec3partysoftwareconfig + +The following variables provide information about the availability and +location of the 3rd party libraries used by \cgal. CMake automatically +searches for dependencies so you need to specify these variables if +CMake was unable to locate something. This is indicated by a value ending in +`NOTFOUND`. + +Since 3rd-party libraries are system wide, many of the CMake variables listed below can alternatively +be given as similarly-named environment variables instead. Keep in mind that you must provide one or the +other but never both. + +\section installation_boost Boost Libraries + +In most cases, if \sc{Boost} is not automatically found, setting the `BOOST_ROOT` +variable is enough. If it is not, you can specify the header and library +directories individually. You can also provide the full pathname to a specific compiled library +if it cannot be found in the library directory or its name is non-standard. + +By default, when \sc{Boost} binary libraries are needed, the shared versions +are used if present. You can set the variable +`CGAL_Boost_USE_STATIC_LIBS` to `ON` if you want to link +with static versions explicitly. + +On Windows, if you link with \sc{Boost} shared libraries, you must ensure that +the `.dll` files are found by the dynamic linker, at run time. +For example, you can add the path to the \sc{Boost} `.dll` to the +`PATH` environment variable. + +| Variable | Description | Type | +| :- | :- | :- | +| `BOOST_ROOT`\cgalFootnote{The environment variable can be spelled either `BOOST_ROOT` or `BOOSTROOT`} | Root directory of your \sc{Boost} installation | Either CMake or Environment | +| `Boost_INCLUDE_DIR` | Directory containing the `boost/version.hpp` file | CMake | +| `BOOST_INCLUDEDIR` | Idem | Environment | +| `Boost_LIBRARY_DIRS` | Directory containing the compiled \sc{Boost} libraries | CMake | +| `BOOST_LIBRARYDIR` | Idem | Environment | +| `Boost_(xyz)_LIBRARY_RELEASE` | Full pathname to a release build of the compiled 'xyz' \sc{Boost} library | CMake | +| `Boost_(xyz)_LIBRARY_DEBUG` | Full pathname to a debug build of the compiled 'xyz' \sc{Boost} library | CMake | + + +\section installation_gmp GMP and MPFR Libraries + +Under Windows, auto-linking is used, so only the directory +containing the libraries is needed and you would specify `GMP|MPFR_LIBRARY_DIR` rather than +`GMP|MPFR_LIBRARIES`. On the other hand, under Linux the actual library filename is needed. +Thus you would specify `GMP|MPFR_LIBRARIES`. In no case you need to specify both. + +\cgal uses both \sc{Gmp} and \sc{Mpfr} so both need to be supported. If either of them is unavailable the +usage of \sc{Gmp} and of \sc{Mpfr} will be disabled. + + +| Variable | Description | Type | +| :- | :- | :- | +| `CGAL_DISABLE_GMP` | Indicates whether to search and use \sc{Gmp}/\sc{Mpfr} or not | CMake | +| `GMP_DIR` | Directory of \sc{Gmp} default installation | Environment | +| `GMP_INCLUDE_DIR` | Directory containing the `gmp.h` file | CMake | +| `GMP_INC_DIR` | Idem | Environment | +| `GMP_LIBRARIES_DIR` | Directory containing the compiled \sc{Gmp} library | CMake | +| `GMP_LIB_DIR` | Idem | Environment | +| `GMP_LIBRARIES` | Full pathname of the compiled \sc{Gmp} library | CMake | +| `MPFR_INCLUDE_DIR` | Directory containing the `mpfr.h` file | CMake | +| `MPFR_INC_DIR` | Idem | Environment | +| `MPFR_LIBRARIES_DIR` | Directory containing the compiled \sc{Mpfr} library | CMake | +| `MPFR_LIB_DIR` | Idem | Environment | +| `MPFR_LIBRARIES` | Full pathname of the compiled \sc{Mpfr} library | CMake | + + + +Under Linux, the \sc{Gmpxx} is also searched for, and you may specify the following variables: + + +| Variable | Description | Type | +| :- | :- | :- | +| `GMPXX_DIR` | Directory of \sc{gmpxx} default installation | Environment | +| `GMPXX_INCLUDE_DIR` | Directory containing the `gmpxx.h` file | CMake | +| `GMPXX_LIBRARIES` | Full pathname of the compiled \sc{Gmpxx} library | CMake | + + + +\section installation_qt5 Qt5 Library + +You must set the cmake or environment variable `Qt5_DIR` to point to the path +to the directory containing the file `Qt5Config.cmake` created by your \sc{Qt}5 installation. If you are +using the open source edition it should be `/qt-everywhere-opensource-src-/qtbase/lib/cmake/Qt5`. + +\section installation_leda LEDA Library + +When the \leda libraries are not automatically found, yet they are installed on the system +with base names 'leda' and 'ledaD' (for the release and debug versions resp.), it might +be sufficient to just indicate the library directory via the `LEDA_LIBRARY_DIRS` variable. +If that doesn't work because, for example, the names are different, you can provide the full pathnames of each variant +via `LEDA_LIBRARY_RELEASE` and `LEDA_LIBRARY_DEBUG`. + +The variables specifying definitions and flags can be left undefined if they are not needed by LEDA. + + +| Variable | Description | Type | +| :- | :- | :- | +| `WITH_LEDA` | Indicates whether to search and use \leda or not | CMake | +| `LEDA_DIR` | Directory of \sc{LEDA} default installation | Environment | +| `LEDA_INCLUDE_DIR` | Directory containing the file `LEDA/system/basic.h` | CMake | +| `LEDA_LIBRARIES` | Directory containing the compiled \leda libraries | CMake | +| `LEDA_INC_DIR` | Directory containing the file `LEDA/system/basic.h` | Environment | +| `LEDA_LIB_DIR` | Directory containing the compiled \leda libraries | Environment | +| `LEDA_LIBRARY_RELEASE` | Full pathname to a release build of the \leda library | CMake | +| `LEDA_LIBRARY_DEBUG` | Full pathname to a debug build of the \leda library | CMake | +| `LEDA_DEFINITIONS` | Preprocessor definitions | CMake | +| `LEDA_CXX_FLAGS` | Compiler flags | CMake | +| `LEDA_LINKER_FLAGS` | Linker flags | CMake | + + +\section installation_mpfi MPFI Library + +\cgal provides a number type based on this library, but the \cgal library +itself does not depend on \sc{Mpfi}. This means that this library must be +configured when compiling an application that uses the above number type. + +When \sc{Mpfi} files are not on the standard path, the locations of the headers +and library files must be specified by using environment variables. + + +| Variable | Description | Type | +| :- | :- | :- | +| `MPFI_DIR` |Directory of \sc{MPFI} default installation | Environment | +| `MPFI_INCLUDE_DIR` | Directory containing the `mpfi.h` file | CMake | +| `MPFI_INC_DIR` | Idem | Environment | +| `MPFI_LIBRARIES_DIR` | Directory containing the compiled \sc{Mpfi} library | CMake | +| `MPFI_LIB_DIR` | Idem | Environment | +| `MPFI_LIBRARIES` | Full pathname of the compiled \sc{Mpfi} library | CMake | + + + +\section installation_rs RS and RS3 Library + +As said before, only the \cgal univariate algebraic kernel depends on the +library Rs. As the algebraic kernel is not compiled as a part of the \cgal +library, this library is not detected nor configured at installation time. + +CMake will try to find Rs in the standard header and library +directories. When it is not automatically detected, the locations of the +headers and library files must be specified using environment variables. + +Rs needs \sc{Gmp} 4.2 or later and \sc{Mpfi} 1.3.4 or later. The variables +related to the latter library may also need to be defined. + + +| Variable | Description | Type | +| :- | :- | :- | +| `RS_DIR` | Directory of \sc{Rs} default installation | Environment | +| `RS_INCLUDE_DIR` | Directory containing the `rs_exports.h` file | CMake | +| `RS_INC_DIR` | Idem | Environment | +| `RS_LIBRARIES_DIR` | Directory containing the compiled \sc{Rs} library | CMake | +| `RS_LIB_DIR` | Idem | Environment | +| `RS_LIBRARIES` | Full pathname of the compiled \sc{Rs} library | CMake | + +Similar variables exist for \sc{Rs3}. + +| Variable | Description | Type | +| :- | :- | :- +| `RS3_DIR` | Directory of \sc{Rs3} default installation | Environment | +| `RS3_INCLUDE_DIR` | Directory containing the file `rs3_fncts.h` file | CMake | +| `RS3_INC_DIR` | Idem | Environment | +| `RS3_LIBRARIES_DIR` | Directory containing the compiled \sc{Rs3} library | CMake | +| `RS3_LIB_DIR` | Idem | Environment | +| `RS3_LIBRARIES` | Full pathname of the compiled \sc{Rs3} library | CMake | + + +\section installation_ntl NTL Library + +Some polynomial computations in \cgal's algebraic kernel +are speed up when \sc{Ntl} is available. +As the algebraic kernel is not compiled as a part of the \cgal +library, this library is not detected nor configured at installation time. + +CMake will try to find \sc{Ntl} in the standard header and library +directories. When it is not automatically detected, the locations of the +headers and library files must be specified using environment variables. + +| Variable | Description | Type | +| :- | :- | :- | +| `NTL_DIR` | Directory of \sc{NTL} default installation | Environment | +| `NTL_INCLUDE_DIR` | Directory containing the `NTL/ZZX.h` file | CMake | +| `NTL_INC_DIR` | Idem | Environment | +| `NTL_LIBRARIES_DIR` | Directory containing the compiled \sc{Ntl} library | CMake | +| `NTL_LIB_DIR` | Idem | Environment | +| `NTL_LIBRARIES` | Full pathname of the compiled \sc{Ntl} library | CMake | + +\section installation_eigen Eigen Library + +\sc{Eigen} is a header-only template library. +Only the directory containing the header files of \sc{Eigen} 3.1 (or greater) is needed. + + +| Variable | Description | Type | +| :- | :- | :- | +| `EIGEN3_INCLUDE_DIR` | Directory containing the file `signature_of_eigen3_matrix_library` | CMake | +| `EIGEN3_INC_DIR` | Idem | Environment | + +\section installation_esbtl ESBTL Library + +One skin surface example requires the \sc{Esbtl} library in order to read \sc{Pdb} files. + +If \sc{Esbtl} is not automatically found, setting the `ESBTL_INC_DIR` +environment variable is sufficient. + + +| Variable | Description | Type | +| :- | :- | :- | +| `ESBTL_DIR` | Directory of \sc{ESBTL} default installation | Environment | +| `ESBTL_INC_DIR` | Directory containing the `ESBTL/default.h` file | Environment | +| `ESBTL_INCLUDE_DIR` | Directory containing the `ESBTL/default.h` file | CMake | + +\section installation_tbb TBB Library + +If \sc{Tbb} is not automatically found, the user must set the `TBB_ROOT` +environment variable. The environment variable `TBB_ARCH_PLATFORM=/` must be set. +`` is `ia32` or `intel64`. `` describes the Linux kernel, gcc version or Visual Studio version +used. It should be set to what is used in `$TBB_ROOT/lib/`. + +For windows users, the folder `TBB_ROOT/bin//` should be added to the `PATH` variable. + +Note that the variables in the table below are being used. + +| Variable | Description | Type | +| :- | :- | :- | +| `TBB_ROOT` | Directory of \sc{Tbb} default installation | Environment | +| `TBB_INCLUDE_DIRS` | Directory containing the `tbb/tbb.h` file | CMake | +| `TBB_LIBRARY_DIRS` | Directory(ies) containing the compiled TBB libraries | CMake | +| `TBB_LIBRARIES` | Full pathnames of the compiled TBB libraries (both release and debug versions, using "optimized" and "debug" CMake keywords). Note that if the debug versions are not found, the release versions will be used instead for the debug mode. | CMake | +| `TBB_RELEASE_LIBRARY` | Full pathname of the compiled TBB release library | CMake | +| `TBB_MALLOC_RELEASE_LIBRARY` | Full pathname of the compiled TBB release malloc library | CMake | +| `TBB_DEBUG_LIBRARY` | Full pathname of the compiled TBB debug library | CMake | +| `TBB_MALLOC_DEBUG_LIBRARY` | Full pathname of the compiled TBB debug malloc library | CMake | +| `TBB_MALLOCPROXY_DEBUG_LIBRARY` | Full pathname of the compiled TBB debug malloc_proxy library (optional) | CMake | +| `TBB_MALLOCPROXY_RELEASE_LIBRARY` | Full pathname of the compiled TBB release malloc_proxy library (optional) | CMake | + +\section installation_compiler_workarounds Compiler Workarounds + +A number of boolean flags are used to workaround compiler bugs and +limitations. They all start with the prefix `CGAL_CFG`. These +flags are used to work around compiler bugs and limitations. For +example, the flag `CGAL_CFG_NO_CPP0X_LONG_LONG` denotes +that the compiler does not know the type `long long`. + +For each installation a file +is defined, with the correct +settings of all flags. This file is generated automatically by CMake, +and it is located in the `include` directory of where you run +CMake. For an in-source configuration this means +`CGAL-\cgalReleaseNumber``/include`. + +The test programs used to generate the `compiler_config.h` +file can be found in `config/testfiles`. +Both +`compiler_config.h` and the test programs contain a short +description of the problem. In case of trouble with one of the +`CGAL_CFG` flags, it is a good idea to take a look at it. + +The file `CGAL/compiler_config.h` is included from +``. +which is included by all \cgal header files. + +*/ diff --git a/Documentation/doc/Documentation/Getting_started.txt b/Documentation/doc/Documentation/Getting_started.txt index 721df7da0b0..63359dbbe04 100644 --- a/Documentation/doc/Documentation/Getting_started.txt +++ b/Documentation/doc/Documentation/Getting_started.txt @@ -1,7 +1,7 @@ /*! \page general_intro Getting Started with %CGAL -- \subpage usage describes how to get \cgal and the few steps required to build a program using \cgal. +- \subpage usage describes how to obtain \cgal and the few steps required to build a program using \cgal. - \subpage thirdparty lists required and optional third party libraries. diff --git a/Documentation/doc/Documentation/Third_party.txt b/Documentation/doc/Documentation/Third_party.txt index 14713197a3c..abedcc34eb7 100644 --- a/Documentation/doc/Documentation/Third_party.txt +++ b/Documentation/doc/Documentation/Third_party.txt @@ -41,7 +41,7 @@ The focus of \cgal is on geometry, and we rely on other highly specialized libraries and software for non-geometric issues, for instance for numeric solvers or visualization. We first list software that is essential to most of \cgal, and must therefore be found during the configuration of \cgal. -The section \ref configurationvariables lists CMake and environment variables which can be used to specify +The page \ref configurationvariables lists CMake and environment variables which can be used to specify the location of third-party software during configuration. \subsection thirdpartystl Standard Template Library (STL) @@ -101,7 +101,7 @@ certain optional libraries might be required to build examples and demos shipped with \cgal or to build your own project using \cgal; another reason is to speed up basic tasks where specialized libraries can be faster than the default version shipped with \cgal. -The section \ref configurationvariables lists CMake and environment variables which can be used to specify +The page \ref configurationvariables lists CMake and environment variables which can be used to specify the location of third-party software during configuration. \subsection thirdpartyQt Qt5 @@ -284,347 +284,4 @@ In \cgal, \sc{SCIP} provides an optional linear integer program solver in the \r The \sc{SCIP} web site is `http://scip.zib.de/`. -\section configurationvariables Summary of CGAL's Configuration Variables - -Most configuration variables are not environment variables but -CMake variables. They are given in the command line to CMake -via the `-D` option, or passed from the interactive interface -of `cmake-gui`. Unless indicated differently, all the variables -summarized below are CMake variables. - -\subsection installation_component_selection Component Selection - -The following Boolean variables enable the compilation of all examples and demos -at the same time. Their values can be ON or OFF. New corresponding targets will be -created, the compilation will be triggered by calling `make examples` and `make demos`. -To build a particular subset of examples or demos, from your build directory go -to the subdirectory `demo/PKG` or `example/PKG` and simply call make from there. - -| Variable | %Default Value | -| :------- | :--------------- | -| `WITH_examples` | OFF | -| `WITH_demos` | OFF | - -\subsection installation_flags Compiler and Linker Flags - -The following variables specify compiler and linker flags. Each variable holds a -space-separated list of command-line switches for the compiler and linker and -their default values are automatically defined by CMake based on the target platform. - -Have in mind that these variables specify a list of flags, not just one -single flag. If you provide your own definition for a variable, you will entirely override -the list of flags chosen by CMake for that particular variable. - -The variables that correspond to both debug and release builds are always -used in conjunction with those for the specific build type. - - -| Program | Both Debug and Release | Release Only | Debug Only | -| :------ | :---------------------- | :------------- | :----------- | -| C++ Compiler | `CMAKE_CXX_FLAGS` | `CMAKE_CXX_FLAGS_RELEASE` | `CMAKE_CXX_FLAGS_DEBUG` | -| Linker (shared libs) | `CMAKE_SHARED_LINKER_FLAGS` | `CMAKE_SHARED_LINKER_FLAGS_RELEASE` | `CMAKE_SHARED_LINKER_FLAGS_DEBUG` | -| Linker (static libs) | `CMAKE_MODULE_LINKER_FLAGS` | `CMAKE_MODULE_LINKER_FLAGS_RELEASE` | `CMAKE_MODULE_LINKER_FLAGS_DEBUG` | -| Linker (programs) | `CMAKE_EXE_LINKER_FLAGS` | `CMAKE_EXE_LINKER_FLAGS_RELEASE` | `CMAKE_EXE_LINKER_FLAGS_DEBUG`| - - -\subsection installation_additional_flags Additional Compiler and Linker Flags - -The following variables can be used to add flags without overriding the ones -defined by cmake. - - -| Program | Both Debug and Release | Release Only | Debug Only | -| :------ | :---------------------- | :------------- | :----------- | -| C++ Compiler | `CGAL_CXX_FLAGS` | `CGAL_CXX_FLAGS_RELEASE` | `CGAL_CXX_FLAGS_DEBUG` | -| Linker (shared libs) | `CGAL_SHARED_LINKER_FLAGS` | `CGAL_SHARED_LINKER_FLAGS_RELEASE` | `CGAL_SHARED_LINKER_FLAGS_DEBUG` | -| Linker (static libs) | `CGAL_MODULE_LINKER_FLAGS` | `CGAL_MODULE_LINKER_FLAGS_RELEASE` | `CGAL_MODULE_LINKER_FLAGS_DEBUG` | -| Linker (programs) | `CGAL_EXE_LINKER_FLAGS` | `CGAL_EXE_LINKER_FLAGS_RELEASE` | `CGAL_EXE_LINKER_FLAGS_DEBUG` | - -\subsection installation_misc Miscellaneous Variables - -Note that the default build type is `Debug`, which should only be used to debug -and will serverly limit performances. - -| Variable | Description | Type | %Default Value | -| :- | :- | :- | :- | -| `CMAKE_BUILD_TYPE` | Indicates type of build. Possible values are 'Debug' or 'Release' | CMake | | -| `CMAKE_INSTALL_PREFIX`| Installation directory path | CMake | Debug | -| `CMAKE_C_COMPILER` | Full-path to the executable corresponding to the C compiler to use. | CMake | platform-dependent | -| `CMAKE_CXX_COMPILER` | Full-path to the executable corresponding to the C++ compiler to use. | CMake | platform-dependent | -| `CXX` | Idem | Environment | Idem | -| `BUILD_SHARED_LIBS` | Whether to build shared or static libraries. | CMake | TRUE | - -\subsection installation_variables_building Variables Used Only When Building Programs (Such as Demos or Examples) - - -| Variable | Description | Type | %Default Value | -| :- | :- | :- | :- | -| `CGAL_DIR` | Full-path to the binary directory where \cgal was configured |Either CMake or Environment | none | - - -\subsection installation_variables_third_party Variables Providing Information About 3rd-Party Libraries -\anchor sec3partysoftwareconfig - -The following variables provide information about the availability and -location of the 3rd party libraries used by \cgal. CMake automatically -searches for dependencies so you need to specify these variables if -CMake was unable to locate something. This is indicated by a value ending in -`NOTFOUND`. - -Since 3rd-party libraries are system wide, many of the CMake variables listed below can alternatively -be given as similarly-named environment variables instead. Keep in mind that you must provide one or the -other but never both. - -\subsection installation_boost Boost Libraries - -In most cases, if \sc{Boost} is not automatically found, setting the `BOOST_ROOT` -variable is enough. If it is not, you can specify the header and library -directories individually. You can also provide the full pathname to a specific compiled library -if it cannot be found in the library directory or its name is non-standard. - -By default, when \sc{Boost} binary libraries are needed, the shared versions -are used if present. You can set the variable -`CGAL_Boost_USE_STATIC_LIBS` to `ON` if you want to link -with static versions explicitly. - -On Windows, if you link with \sc{Boost} shared libraries, you must ensure that -the `.dll` files are found by the dynamic linker, at run time. -For example, you can add the path to the \sc{Boost} `.dll` to the -`PATH` environment variable. - -| Variable | Description | Type | -| :- | :- | :- | -| `BOOST_ROOT`\cgalFootnote{The environment variable can be spelled either `BOOST_ROOT` or `BOOSTROOT`} | Root directory of your \sc{Boost} installation | Either CMake or Environment | -| `Boost_INCLUDE_DIR` | Directory containing the `boost/version.hpp` file | CMake | -| `BOOST_INCLUDEDIR` | Idem | Environment | -| `Boost_LIBRARY_DIRS` | Directory containing the compiled \sc{Boost} libraries | CMake | -| `BOOST_LIBRARYDIR` | Idem | Environment | -| `Boost_(xyz)_LIBRARY_RELEASE` | Full pathname to a release build of the compiled 'xyz' \sc{Boost} library | CMake | -| `Boost_(xyz)_LIBRARY_DEBUG` | Full pathname to a debug build of the compiled 'xyz' \sc{Boost} library | CMake | - - -\subsection installation_gmp GMP and MPFR Libraries - -Under Windows, auto-linking is used, so only the directory -containing the libraries is needed and you would specify `GMP|MPFR_LIBRARY_DIR` rather than -`GMP|MPFR_LIBRARIES`. On the other hand, under Linux the actual library filename is needed. -Thus you would specify `GMP|MPFR_LIBRARIES`. In no case you need to specify both. - -\cgal uses both \sc{Gmp} and \sc{Mpfr} so both need to be supported. If either of them is unavailable the -usage of \sc{Gmp} and of \sc{Mpfr} will be disabled. - - -| Variable | Description | Type | -| :- | :- | :- | -| `CGAL_DISABLE_GMP` | Indicates whether to search and use \sc{Gmp}/\sc{Mpfr} or not | CMake | -| `GMP_DIR` | Directory of \sc{Gmp} default installation | Environment | -| `GMP_INCLUDE_DIR` | Directory containing the `gmp.h` file | CMake | -| `GMP_INC_DIR` | Idem | Environment | -| `GMP_LIBRARIES_DIR` | Directory containing the compiled \sc{Gmp} library | CMake | -| `GMP_LIB_DIR` | Idem | Environment | -| `GMP_LIBRARIES` | Full pathname of the compiled \sc{Gmp} library | CMake | -| `MPFR_INCLUDE_DIR` | Directory containing the `mpfr.h` file | CMake | -| `MPFR_INC_DIR` | Idem | Environment | -| `MPFR_LIBRARIES_DIR` | Directory containing the compiled \sc{Mpfr} library | CMake | -| `MPFR_LIB_DIR` | Idem | Environment | -| `MPFR_LIBRARIES` | Full pathname of the compiled \sc{Mpfr} library | CMake | - - - -Under Linux, the \sc{Gmpxx} is also searched for, and you may specify the following variables: - - -| Variable | Description | Type | -| :- | :- | :- | -| `GMPXX_DIR` | Directory of \sc{gmpxx} default installation | Environment | -| `GMPXX_INCLUDE_DIR` | Directory containing the `gmpxx.h` file | CMake | -| `GMPXX_LIBRARIES` | Full pathname of the compiled \sc{Gmpxx} library | CMake | - - - -\subsection installation_qt5 Qt5 Library - -You must set the cmake or environment variable `Qt5_DIR` to point to the path -to the directory containing the file `Qt5Config.cmake` created by your \sc{Qt}5 installation. If you are -using the open source edition it should be `/qt-everywhere-opensource-src-/qtbase/lib/cmake/Qt5`. - -\subsection installation_leda LEDA Library - -When the \leda libraries are not automatically found, yet they are installed on the system -with base names 'leda' and 'ledaD' (for the release and debug versions resp.), it might -be sufficient to just indicate the library directory via the `LEDA_LIBRARY_DIRS` variable. -If that doesn't work because, for example, the names are different, you can provide the full pathnames of each variant -via `LEDA_LIBRARY_RELEASE` and `LEDA_LIBRARY_DEBUG`. - -The variables specifying definitions and flags can be left undefined if they are not needed by LEDA. - - -| Variable | Description | Type | -| :- | :- | :- | -| `WITH_LEDA` | Indicates whether to search and use \leda or not | CMake | -| `LEDA_DIR` | Directory of \sc{LEDA} default installation | Environment | -| `LEDA_INCLUDE_DIR` | Directory containing the file `LEDA/system/basic.h` | CMake | -| `LEDA_LIBRARIES` | Directory containing the compiled \leda libraries | CMake | -| `LEDA_INC_DIR` | Directory containing the file `LEDA/system/basic.h` | Environment | -| `LEDA_LIB_DIR` | Directory containing the compiled \leda libraries | Environment | -| `LEDA_LIBRARY_RELEASE` | Full pathname to a release build of the \leda library | CMake | -| `LEDA_LIBRARY_DEBUG` | Full pathname to a debug build of the \leda library | CMake | -| `LEDA_DEFINITIONS` | Preprocessor definitions | CMake | -| `LEDA_CXX_FLAGS` | Compiler flags | CMake | -| `LEDA_LINKER_FLAGS` | Linker flags | CMake | - - -\subsection installation_mpfi MPFI Library - -\cgal provides a number type based on this library, but the \cgal library -itself does not depend on \sc{Mpfi}. This means that this library must be -configured when compiling an application that uses the above number type. - -When \sc{Mpfi} files are not on the standard path, the locations of the headers -and library files must be specified by using environment variables. - - -| Variable | Description | Type | -| :- | :- | :- | -| `MPFI_DIR` |Directory of \sc{MPFI} default installation | Environment | -| `MPFI_INCLUDE_DIR` | Directory containing the `mpfi.h` file | CMake | -| `MPFI_INC_DIR` | Idem | Environment | -| `MPFI_LIBRARIES_DIR` | Directory containing the compiled \sc{Mpfi} library | CMake | -| `MPFI_LIB_DIR` | Idem | Environment | -| `MPFI_LIBRARIES` | Full pathname of the compiled \sc{Mpfi} library | CMake | - - - -\subsection installation_rs RS and RS3 Library - -As said before, only the \cgal univariate algebraic kernel depends on the -library Rs. As the algebraic kernel is not compiled as a part of the \cgal -library, this library is not detected nor configured at installation time. - -CMake will try to find Rs in the standard header and library -directories. When it is not automatically detected, the locations of the -headers and library files must be specified using environment variables. - -Rs needs \sc{Gmp} 4.2 or later and \sc{Mpfi} 1.3.4 or later. The variables -related to the latter library may also need to be defined. - - -| Variable | Description | Type | -| :- | :- | :- | -| `RS_DIR` | Directory of \sc{Rs} default installation | Environment | -| `RS_INCLUDE_DIR` | Directory containing the `rs_exports.h` file | CMake | -| `RS_INC_DIR` | Idem | Environment | -| `RS_LIBRARIES_DIR` | Directory containing the compiled \sc{Rs} library | CMake | -| `RS_LIB_DIR` | Idem | Environment | -| `RS_LIBRARIES` | Full pathname of the compiled \sc{Rs} library | CMake | - -Similar variables exist for \sc{Rs3}. - -| Variable | Description | Type | -| :- | :- | :- -| `RS3_DIR` | Directory of \sc{Rs3} default installation | Environment | -| `RS3_INCLUDE_DIR` | Directory containing the file `rs3_fncts.h` file | CMake | -| `RS3_INC_DIR` | Idem | Environment | -| `RS3_LIBRARIES_DIR` | Directory containing the compiled \sc{Rs3} library | CMake | -| `RS3_LIB_DIR` | Idem | Environment | -| `RS3_LIBRARIES` | Full pathname of the compiled \sc{Rs3} library | CMake | - - -\subsection installation_ntl NTL Library - -Some polynomial computations in \cgal's algebraic kernel -are speed up when \sc{Ntl} is available. -As the algebraic kernel is not compiled as a part of the \cgal -library, this library is not detected nor configured at installation time. - -CMake will try to find \sc{Ntl} in the standard header and library -directories. When it is not automatically detected, the locations of the -headers and library files must be specified using environment variables. - -| Variable | Description | Type | -| :- | :- | :- | -| `NTL_DIR` | Directory of \sc{NTL} default installation | Environment | -| `NTL_INCLUDE_DIR` | Directory containing the `NTL/ZZX.h` file | CMake | -| `NTL_INC_DIR` | Idem | Environment | -| `NTL_LIBRARIES_DIR` | Directory containing the compiled \sc{Ntl} library | CMake | -| `NTL_LIB_DIR` | Idem | Environment | -| `NTL_LIBRARIES` | Full pathname of the compiled \sc{Ntl} library | CMake | - -\subsection installation_eigen Eigen Library - -\sc{Eigen} is a header-only template library. -Only the directory containing the header files of \sc{Eigen} 3.1 (or greater) is needed. - - -| Variable | Description | Type | -| :- | :- | :- | -| `EIGEN3_INCLUDE_DIR` | Directory containing the file `signature_of_eigen3_matrix_library` | CMake | -| `EIGEN3_INC_DIR` | Idem | Environment | - -\subsection installation_esbtl ESBTL Library - -One skin surface example requires the \sc{Esbtl} library in order to read \sc{Pdb} files. - -If \sc{Esbtl} is not automatically found, setting the `ESBTL_INC_DIR` -environment variable is sufficient. - - -| Variable | Description | Type | -| :- | :- | :- | -| `ESBTL_DIR` | Directory of \sc{ESBTL} default installation | Environment | -| `ESBTL_INC_DIR` | Directory containing the `ESBTL/default.h` file | Environment | -| `ESBTL_INCLUDE_DIR` | Directory containing the `ESBTL/default.h` file | CMake | - -\subsection installation_tbb TBB Library - -If \sc{Tbb} is not automatically found, the user must set the `TBB_ROOT` -environment variable. The environment variable `TBB_ARCH_PLATFORM=/` must be set. -`` is `ia32` or `intel64`. `` describes the Linux kernel, gcc version or Visual Studio version -used. It should be set to what is used in `$TBB_ROOT/lib/`. - -For windows users, the folder `TBB_ROOT/bin//` should be added to the `PATH` variable. - -Note that the variables in the table below are being used. - -| Variable | Description | Type | -| :- | :- | :- | -| `TBB_ROOT` | Directory of \sc{Tbb} default installation | Environment | -| `TBB_INCLUDE_DIRS` | Directory containing the `tbb/tbb.h` file | CMake | -| `TBB_LIBRARY_DIRS` | Directory(ies) containing the compiled TBB libraries | CMake | -| `TBB_LIBRARIES` | Full pathnames of the compiled TBB libraries (both release and debug versions, using "optimized" and "debug" CMake keywords). Note that if the debug versions are not found, the release versions will be used instead for the debug mode. | CMake | -| `TBB_RELEASE_LIBRARY` | Full pathname of the compiled TBB release library | CMake | -| `TBB_MALLOC_RELEASE_LIBRARY` | Full pathname of the compiled TBB release malloc library | CMake | -| `TBB_DEBUG_LIBRARY` | Full pathname of the compiled TBB debug library | CMake | -| `TBB_MALLOC_DEBUG_LIBRARY` | Full pathname of the compiled TBB debug malloc library | CMake | -| `TBB_MALLOCPROXY_DEBUG_LIBRARY` | Full pathname of the compiled TBB debug malloc_proxy library (optional) | CMake | -| `TBB_MALLOCPROXY_RELEASE_LIBRARY` | Full pathname of the compiled TBB release malloc_proxy library (optional) | CMake | - -\subsection installation_compiler_workarounds Compiler Workarounds - -A number of boolean flags are used to workaround compiler bugs and -limitations. They all start with the prefix `CGAL_CFG`. These -flags are used to work around compiler bugs and limitations. For -example, the flag `CGAL_CFG_NO_CPP0X_LONG_LONG` denotes -that the compiler does not know the type `long long`. - -For each installation a file -is defined, with the correct -settings of all flags. This file is generated automatically by CMake, -and it is located in the `include` directory of where you run -CMake. For an in-source configuration this means -`CGAL-\cgalReleaseNumber``/include`. - -The test programs used to generate the `compiler_config.h` -file can be found in `config/testfiles`. -Both -`compiler_config.h` and the test programs contain a short -description of the problem. In case of trouble with one of the -`CGAL_CFG` flags, it is a good idea to take a look at it. - -The file `CGAL/compiler_config.h` is included from -``. -which is included by all \cgal header files. - - - */ diff --git a/Documentation/doc/Documentation/Usage.txt b/Documentation/doc/Documentation/Usage.txt index 472a81ecf72..c386ef529bb 100644 --- a/Documentation/doc/Documentation/Usage.txt +++ b/Documentation/doc/Documentation/Usage.txt @@ -8,7 +8,8 @@ However, some dependencies of \cgal might still need to be installed. \section usage_introduction Quick Start: Compiling a Program using CGAL -Given that you have extracted the \cgal source archive in `$HOME`, compiling an example shipped with \cgal is as simple as: +Assuming that you have extracted the \cgal source archive in your `$HOME` folder, +compiling an example shipped with \cgal is as simple as: cd $HOME/CGAL-\cgalReleaseNumber/examples/Triangulation_2 # go to an example directory cmake -DCGAL_DIR=$HOME/CGAL-\cgalReleaseNumber -DCMAKE_BUILD_TYPE=Release . # configure the examples diff --git a/Documentation/doc/Documentation/main.txt b/Documentation/doc/Documentation/main.txt index c7b58497673..217a40b19d7 100644 --- a/Documentation/doc/Documentation/main.txt +++ b/Documentation/doc/Documentation/main.txt @@ -5,13 +5,12 @@ The Computational Geometry Algorithms Library (\cgal) is a software project that provides easy access to efficient and reliable geometric algorithms in the form of a C++ library. - +

      \cgal offers data structures and algorithms like \ref PartTriangulationsAndDelaunayTriangulations "triangulations", \ref PartVoronoiDiagrams "Voronoi diagrams", \ref PartPolygons, \ref PartPolyhedra, \ref PartArrangements "arrangements of curves", \ref PartMeshing "mesh generation", \ref PartGeometryProcessing "geometry processing", \ref PartConvexHullAlgorithms "convex hull algorithms", to name just a few. - All these data structures and algorithms operate on geometric objects like points and segments, and perform geometric tests on them. These objects and predicates are regrouped in \ref PartKernels "CGAL Kernels". @@ -26,7 +25,7 @@ Getting Started =============== -- \ref usage describes how to get \cgal and the few steps required to build a program using \cgal. +- \ref usage describes how to obtain \cgal and the few steps required to build a program using \cgal. - \ref thirdparty lists required and optional third party libraries. From bdcc2b64a10b2a8b980ffc8eb61818c552d8e587 Mon Sep 17 00:00:00 2001 From: Maxime Gimeno Date: Mon, 21 Oct 2019 09:14:15 +0200 Subject: [PATCH 209/363] Add properties for valu/min/max --- Polyhedron/demo/Polyhedron/CGAL_double_edit.cpp | 15 +++++++++++++++ Polyhedron/demo/Polyhedron/CGAL_double_edit.h | 7 ++++++- 2 files changed, 21 insertions(+), 1 deletion(-) diff --git a/Polyhedron/demo/Polyhedron/CGAL_double_edit.cpp b/Polyhedron/demo/Polyhedron/CGAL_double_edit.cpp index a631b7e01c5..0acf1bffb6c 100644 --- a/Polyhedron/demo/Polyhedron/CGAL_double_edit.cpp +++ b/Polyhedron/demo/Polyhedron/CGAL_double_edit.cpp @@ -61,5 +61,20 @@ public: { this->validator->setRange(min, max); } + + double DoubleEdit::getValue() + { + return this->value(); + } + + double DoubleEdit::getMinimum() + { + return this->validator->bottom(); + } + + double DoubleEdit::getMaximum() + { + return this->validator->top(); + } #include "CGAL_double_edit.moc" diff --git a/Polyhedron/demo/Polyhedron/CGAL_double_edit.h b/Polyhedron/demo/Polyhedron/CGAL_double_edit.h index 0cacb15ea49..1b542d2bb22 100644 --- a/Polyhedron/demo/Polyhedron/CGAL_double_edit.h +++ b/Polyhedron/demo/Polyhedron/CGAL_double_edit.h @@ -13,7 +13,9 @@ class DoubleValidator; class SCENE_EXPORT DoubleEdit : public QLineEdit { Q_OBJECT - + Q_PROPERTY(double value READ getValue WRITE setValue) + Q_PROPERTY(double minimum READ getMinimum WRITE setMinimum) + Q_PROPERTY(double maximum READ getMaximum WRITE setMaximum) public: DoubleEdit(QWidget* parent = nullptr); ~DoubleEdit(); @@ -22,6 +24,9 @@ public: void setMinimum(double d); void setMaximum(double d); void setRange(double min, double max); + double getValue(); + double getMinimum(); + double getMaximum(); private: DoubleValidator* validator; }; From b1d383da961765652168451d45806dc187c1ebaa Mon Sep 17 00:00:00 2001 From: Maxime Gimeno Date: Mon, 21 Oct 2019 09:29:39 +0200 Subject: [PATCH 210/363] remove unused include to .moc to fix warning --- Polyhedron/demo/Polyhedron/CGAL_double_edit.cpp | 2 -- 1 file changed, 2 deletions(-) diff --git a/Polyhedron/demo/Polyhedron/CGAL_double_edit.cpp b/Polyhedron/demo/Polyhedron/CGAL_double_edit.cpp index 0acf1bffb6c..07c630b7828 100644 --- a/Polyhedron/demo/Polyhedron/CGAL_double_edit.cpp +++ b/Polyhedron/demo/Polyhedron/CGAL_double_edit.cpp @@ -76,5 +76,3 @@ public: { return this->validator->top(); } - #include "CGAL_double_edit.moc" - From dfb4bb436e0e03ab0e7c6b348f2e3c4681dceacf Mon Sep 17 00:00:00 2001 From: Maxime Gimeno Date: Mon, 21 Oct 2019 09:33:43 +0200 Subject: [PATCH 211/363] Add misisng include to QSpinBox in PS selection plugin --- .../Polyhedron/Plugins/Point_set/Point_set_selection_plugin.cpp | 1 + 1 file changed, 1 insertion(+) 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 25ad888c165..9ed293d1f51 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 @@ -30,6 +30,7 @@ #include #include #include +#include #include #include "CGAL_double_edit.h" From ea3dc6c936a65bdbc7df6bfb57f8e7e4491c89ca Mon Sep 17 00:00:00 2001 From: Maxime Gimeno Date: Mon, 21 Oct 2019 16:18:46 +0200 Subject: [PATCH 212/363] Add Cub_3-T_3 intersection --- .../include/CGAL/Intersection_traits_3.h | 19 ++ .../Intersections_3/Iso_cuboid_3_Triangle_3.h | 4 +- .../Iso_cuboid_3_Triangle_3_intersection.h | 210 ++++++++++++++++++ .../Intersections_3/test_intersections_3.cpp | 71 +++++- 4 files changed, 302 insertions(+), 2 deletions(-) create mode 100644 Intersections_3/include/CGAL/Intersections_3/internal/Iso_cuboid_3_Triangle_3_intersection.h diff --git a/Intersections_3/include/CGAL/Intersection_traits_3.h b/Intersections_3/include/CGAL/Intersection_traits_3.h index 88864987cb3..a72bb5c6a59 100644 --- a/Intersections_3/include/CGAL/Intersection_traits_3.h +++ b/Intersections_3/include/CGAL/Intersection_traits_3.h @@ -164,6 +164,25 @@ struct Intersection_traits { typedef typename boost::optional< variant_type > result_type; }; +// Iso_cuboid_3 Triangle_3, variant of 4 +template +struct Intersection_traits { + typedef typename + boost::variant< typename K::Point_3, typename K::Segment_3, + typename K::Triangle_3, std::vector > variant_type; + + typedef typename boost::optional< variant_type > result_type; +}; + +template +struct Intersection_traits { + typedef typename + boost::variant< typename K::Point_3, typename K::Segment_3, + typename K::Triangle_3, std::vector > variant_type; + + typedef typename boost::optional< variant_type > result_type; +}; + // Point_3 Line_3, variant of one template struct Intersection_traits { diff --git a/Intersections_3/include/CGAL/Intersections_3/Iso_cuboid_3_Triangle_3.h b/Intersections_3/include/CGAL/Intersections_3/Iso_cuboid_3_Triangle_3.h index 9c0e6ac71e2..9f56eece4bf 100644 --- a/Intersections_3/include/CGAL/Intersections_3/Iso_cuboid_3_Triangle_3.h +++ b/Intersections_3/include/CGAL/Intersections_3/Iso_cuboid_3_Triangle_3.h @@ -27,9 +27,11 @@ #include #include +#include namespace CGAL { - CGAL_DO_INTERSECT_FUNCTION(Iso_cuboid_3,Triangle_3, 3) + CGAL_DO_INTERSECT_FUNCTION(Iso_cuboid_3, Triangle_3, 3) + CGAL_INTERSECTION_FUNCTION(Iso_cuboid_3, Triangle_3, 3) } #endif // CGAL_INTERSECTIONS_3_BBOX_3_TRIANGLE_3_H diff --git a/Intersections_3/include/CGAL/Intersections_3/internal/Iso_cuboid_3_Triangle_3_intersection.h b/Intersections_3/include/CGAL/Intersections_3/internal/Iso_cuboid_3_Triangle_3_intersection.h new file mode 100644 index 00000000000..0e8f1ebc186 --- /dev/null +++ b/Intersections_3/include/CGAL/Intersections_3/internal/Iso_cuboid_3_Triangle_3_intersection.h @@ -0,0 +1,210 @@ +// 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 Lesser 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: LGPL-3.0+ +// +// +// Author(s) : Maxime Gimeno +// + +#ifndef CGAL_INTERSECTIONS_3_INTERNAL_ISO_CUBOID_3_TRIANGLE_3_INTERSECTION_H +#define CGAL_INTERSECTIONS_3_INTERNAL_ISO_CUBOID_3_TRIANGLE_3_INTERSECTION_H + +#include +#include + +#include +#include + +namespace CGAL { + +namespace Intersections { + +namespace internal { + +//only work for convex polygons, but in here that's always the case +template +void clip_poly_halfspace( + const std::vector& input, + const typename K::Plane_3& pl, + std::vector& output) +{ + if(input.empty()) + return; + + typedef typename K::Point_3 Point; + typedef typename K::Plane_3 Plane; + typedef typename K::Segment_3 S; + + typedef typename Intersection_traits, + CGAL::Segment_3 >::result_type SP_type; + + std::list p_list(input.begin(), input.end()); + auto it = p_list.begin(); + //corefine with plane. + while(it != p_list.end()) + { + Point p = *it; + ++it; + if(it == p_list.end()) + break; + if(do_intersect(S(p, *it), pl)) + { + SP_type inter = typename K::Intersect_3()(S(p, *it), pl); + if(inter) + { + Point* p_inter = boost::get(&*inter); + if(p_inter + && *p_inter != p + && *p_inter != *it) + p_list.insert(it, *p_inter); + } + } + } + + if(input.size() >2) + { + Point p2(p_list.front()), + p1(p_list.back()); + S seg(p1, p2); + if(do_intersect(seg, pl)) + { + SP_type inter = typename K::Intersect_3()(seg, pl); + if(inter) + { + Point* p_inter = boost::get(&*inter); + if(p_inter + && *p_inter != p1 + && *p_inter != p2) + p_list.push_back(*p_inter); + } + } + } + //remove all points on positive side + + for(auto p_it = p_list.begin(); + p_it != p_list.end();) + { + if(pl.has_on_positive_side(*p_it)) + p_it = p_list.erase(p_it); + else + ++p_it; + } + for(auto p : p_list) + output.push_back(p); + +} + +template +typename Intersection_traits::result_type +intersection( + const typename K::Iso_cuboid_3 &cub, + const typename K::Triangle_3 &tr, + const K&) +{ + typedef typename K::Point_3 Point; + typedef typename K::Segment_3 Segment; + typedef typename K::Triangle_3 Triangle; + typedef typename K::Plane_3 Plane_3; + typedef std::vector Poly; + + typedef typename Intersection_traits, + CGAL::Triangle_3 >::result_type Res_type; + + //Lazy implem: clip 6 times the input triangle. + Plane_3 planes[6]; + planes[0] = Plane_3(cub.vertex(0), + cub.vertex(1), + cub.vertex(5)); + + planes[1] = Plane_3(cub.vertex(0), + cub.vertex(4), + cub.vertex(3)); + + planes[2]=Plane_3(cub.vertex(0), + cub.vertex(3), + cub.vertex(1)); + + planes[3] = Plane_3(cub.vertex(7), + cub.vertex(6), + cub.vertex(1)); + + planes[4] = Plane_3(cub.vertex(7), + cub.vertex(3), + cub.vertex(4)); + + planes[5] = Plane_3(cub.vertex(7), + cub.vertex(4), + cub.vertex(6)); + + std::vector poly; + poly.push_back(tr.vertex(0)); + poly.push_back(tr.vertex(1)); + poly.push_back(tr.vertex(2)); + + for (int i = 0; i < 6; ++i) + { + Poly clipped; + clip_poly_halfspace(poly, planes[i], clipped); + poly = clipped; + } + + switch(poly.size()) + { + case 0: + return Res_type(); + break; + case 1: + { + Point res = poly.front(); + return Res_type(std::forward(res)); + } + break; + case 2: + { + Segment res = Segment(poly.front(), poly.back()); + return Res_type(std::forward(res)); + } + break; + case 3: + { + + Triangle res = Triangle (poly[0], poly[1], poly[2]); + return Res_type(std::forward(res)); + } + break; + default: + { + return Res_type(std::forward(poly)); + } + break; + } +} + +template +typename Intersection_traits::result_type +intersection( + const typename K::Triangle_3 &tr, + const typename K::Iso_cuboid_3 &cub, + const K& k) +{ + return intersection(cub, tr, k); +} +}}} + +#endif // CGAL_INTERSECTIONS_3_INTERNAL_ISO_CUBOID_3_TRIANGLE_3_INTERSECTION_H diff --git a/Intersections_3/test/Intersections_3/test_intersections_3.cpp b/Intersections_3/test/Intersections_3/test_intersections_3.cpp index b8c20156922..c4f1c4197d9 100644 --- a/Intersections_3/test/Intersections_3/test_intersections_3.cpp +++ b/Intersections_3/test/Intersections_3/test_intersections_3.cpp @@ -3,6 +3,7 @@ #include #include #include +#include #include #include @@ -563,7 +564,72 @@ struct Test { << do_intersect_counter << "\n"; } // end function Bbox_Tr - void run() + void Cub_Tr(bool is_exact) + { + std::cout << "Triangle_3 - Cuboid_3\n"; + + Cub cub(P(1,1,1), P(2,2,2)); + + check_no_intersection(cub, Tr(P(1.1, 2,0), + P(2, 3, 1), + P(4, 5, 6))); + + //tr in a face + check_intersection(cub, Tr(P(1,1.1,1), + P(1,1.5,1), + P(1,1,1.1)), + Tr(P(1,1.1,1), + P(1,1.5,1), + P(1,1,1.1)) + ); + //face in a tr + + typedef typename CGAL::Intersection_traits::result_type Res; + Tr tr(P(-3, -3, 1), P(3,-3,1), P(1.5,6,1)); + Res res = CGAL::intersection(cub, tr); + if(is_exact) + { + std::vector

      * poly = boost::get >(&*res); + CGAL_assertion(poly != nullptr); + CGAL_assertion(poly->size() == 4); + for(auto p : *poly) + { + CGAL_assertion(tr.has_on(p) && cub.has_on_boundary(p)); + } + } + + //tr adj to a point + + check_intersection (cub, Tr(P(1, 0.5, 0.5), + P(3, 2, 1), + P(3, 1, 2)), + P(2,1,1)); + //tr adj to an edge + check_intersection (cub, Tr(P(1,0,4), P(2,1,0), P(4,3,0)), + S(P(2,1,2), P(2,1,1))); + //tr inside + check_intersection (cub, Tr(P(1.1,1.1,1.1), P(1.8,1.8,1.8), P(1.5,1.8,1.1)), + Tr(P(1.1,1.1,1.1), P(1.8,1.8,1.8), P(1.5,1.8,1.1))); + //tr through + tr = Tr(P(2, 4, 2), + P(1, 3.5, -0.5), + P(1, -1, 1)); + res = CGAL::intersection(cub, tr); + if(is_exact) + { + std::vector

      * poly = boost::get >(&*res); + CGAL_assertion(poly != nullptr); + CGAL_assertion(poly->size() == 4); + for(auto p : *poly) + { + CGAL_assertion(tr.has_on(p) && cub.has_on_boundary(p)); + } + } + } + + void run(bool is_exact = false) { std::cout << "3D Intersection tests\n"; P_do_intersect(); @@ -584,6 +650,7 @@ struct Test { Bbox_L(); Bbox_R(); Bbox_Tr(); + Cub_Tr(is_exact); } }; @@ -592,6 +659,8 @@ int main() { Test< CGAL::Simple_cartesian >().run(); Test< CGAL::Homogeneous >().run(); + Test< CGAL::Epeck >().run(true); + Test< CGAL::Homogeneous >().run(true); // TODO : test more kernels. } From 3f62323de8893cb340eb90481d0eba7db9db985b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mael=20Rouxel-Labb=C3=A9?= Date: Mon, 21 Oct 2019 16:26:17 +0200 Subject: [PATCH 213/363] Update installation manual (package managers is the recommended way) --- Documentation/doc/Documentation/Usage.txt | 68 ++++++++++++++--------- 1 file changed, 41 insertions(+), 27 deletions(-) diff --git a/Documentation/doc/Documentation/Usage.txt b/Documentation/doc/Documentation/Usage.txt index c386ef529bb..02de8021953 100644 --- a/Documentation/doc/Documentation/Usage.txt +++ b/Documentation/doc/Documentation/Usage.txt @@ -8,11 +8,12 @@ However, some dependencies of \cgal might still need to be installed. \section usage_introduction Quick Start: Compiling a Program using CGAL -Assuming that you have extracted the \cgal source archive in your `$HOME` folder, -compiling an example shipped with \cgal is as simple as: +Assuming that you have obtained \cgal through one of the package managers offering \cgal on your platform +(see Section \ref secgettingcgal), compiling \cgal examples, which can be downloaded here, +is as simple as: cd $HOME/CGAL-\cgalReleaseNumber/examples/Triangulation_2 # go to an example directory - cmake -DCGAL_DIR=$HOME/CGAL-\cgalReleaseNumber -DCMAKE_BUILD_TYPE=Release . # configure the examples + cmake -DCMAKE_BUILD_TYPE=Release . # configure the examples make # build the examples On Windows, instead of calling `make` simply double-click on the generated solution (`.sln`) to open Visual C++. @@ -21,7 +22,7 @@ Compiling your own program is similar: cd /path/to/your/program cgal_create_CMakeLists -s executable - cmake -DCGAL_DIR=$HOME/CGAL-\cgalReleaseNumber -DCMAKE_BUILD_TYPE=Release . + cmake -DCMAKE_BUILD_TYPE=Release . make The script `cgal_create_CMakeLists` and its options are detailed in Section \ref devman_create_cgal_CMakeLists. @@ -46,30 +47,26 @@ or to build your own project using \cgal, see Section \ref secoptional3rdpartyso \subsection secusingpkgman Using a Package Manager -On most common operating systems, package managers offer \cgal and its essential third party dependencies. +On most operating systems, package managers offer \cgal and its essential third party dependencies. -On macOS we recommend to use of Homebrew in the following way: +On macOS, we recommend using of Homebrew in the following way: brew install cgal -If not automatically found, the `CGAL_DIR` to provide to cmake when configuring a program using \cgal should be something like `/usr/local/Cellar/cgal/4.14.1/lib/cmake/CGAL`. - -On Linux distributions like Debian/Ubuntu/Mint, use `apt-get` in the following way: +On Linux distributions such as Debian/Ubuntu/Mint, use `apt-get` in the following way: sudo apt-get install libcgal-dev -If not automatically found, the `CGAL_DIR` to provide to cmake when configuring a program using \cgal should be something like `/usr/lib/x86_64-linux-gnu/cmake/CGAL`. - -On Windows, we recommand to use vcpkg in the following way: +On Windows, we recommand using vcpkg in the following way: vcpkg install cgal -To see how to use libraries installed with vcpkg refer to the official documentation. -If not automatically found, the `CGAL_DIR` to provide to cmake when configuring a program using \cgal should be something like `VCPK_DIR/packages/cgal_x64-windows/lib/cgal` +To see how to use libraries installed with vcpkg, +refer to the official documentation. For other distributions or package manager, please consult your respective documentation. -\subsection sseccgalwindows Using CGAL installer on Windows +\subsection sseccgalwindows Using the CGAL Installer on Windows You can download and run `CGAL-\cgalReleaseNumber``-Setup.exe` from https://www.cgal.org/download/windows.html. It is a self extracting executable that installs the \cgal source, and that allows you @@ -77,7 +74,6 @@ to select and download some precompiled third party libraries. However, you will the library using your favorite compiler. A tutorial is provided on how to proceed with Microsoft Visual Studio. - \subsection secusingwebsite Using CGAL Source Archive You can obtain the \cgal library from @@ -122,11 +118,11 @@ or downloaded separately at \section section_headeronly Header-only Usage -Since \cgal 4.12, it has been possible to use \cgal in header-only mode, -without even configuring \cgal\. Programs using \cgal (examples, tests, demos, etc.) +\cgal is a header-only library, and as such +there is no need to even configure it before using it. Programs using \cgal (examples, tests, demos, etc.) are instead configured using CMake and \cgal will be configured at the same time. -Note that even though \cgal can be used as a header-only library, not all its dependencies +Note that even though \cgal is a header-only library, not all its dependencies are header-only. The libraries \sc{Gmp} and \sc{Mpfr}, for example, are not header-only. As such, these dependencies must be built or installed independently. @@ -144,19 +140,32 @@ Some of the CMake variables represent user choices, such as `CMAKE_BUILD_TYPE`, whereas others indicate the details of a third-party library, such as `Boost_INCLUDE_DIR` or the compiler flags to use, such as `CMAKE_CXX_FLAGS`. -In a typical installation of dependencies, almost all CMake variables will be set automatically; -users need only to provide the variable `CGAL_DIR`, which must point to the root directory +The most important CMake variable is the variable `CGAL_DIR`, which will serve to configure \cgal +as you configure your program. + +In a typical installation of dependencies, almost all CMake variables will be set automatically. +The variable `CGAL_DIR` is also generally found when \cgal has been obtained via a package manger. +In the rare event that it has not, the variable `CGAL_DIR` should be set manually to: + +

        +
      • something like `/usr/local/Cellar/cgal/CGAL-\cgalReleaseNumber/lib/cmake/CGAL`, for Brew.
      • +
      • something like `/usr/lib/x86_64-linux-gnu/cmake/CGAL` for Linux distributions.
      • +
      • something like `VCPKG_DIR/packages/cgal_x64-windows/lib/cgal`, for VCPKG_DIR.
      • +
      + +If \cgal has been obtained via other means, `CGAL_DIR` must point to the root directory of the \cgal source code (either the root of the unpacked release tarball or the root of the Git working directory). -It is also strongly recommended to set the build type to `Release` for performance reasons + +It is also strongly recommended to set the build type variable to `Release` for performance reasons if no debugging is intended. Users should thus run: cd CGAL-\cgalReleaseNumber/examples/Triangulation_2 - cmake -DCGAL_DIR=$HOME/CGAL-\cgalReleaseNumber -CMAKE_BUILD_TYPE=Release . + cmake -DCGAL_DIR=$HOME/CGAL-\cgalReleaseNumber -CMAKE_BUILD_TYPE=Release . # we are here using a release tarball \subsection usage_configuring_cmake_gui Specifying Missing Dependencies -The configuration process launched above might however fail if CMake fails to find +The configuration process launched above might fail if CMake fails to find all the required dependencies. This typically happens if you have installed dependencies at non-standard locations. Although the command line tool `cmake` accepts CMake variables as arguments of the form @@ -165,7 +174,7 @@ need to be explicitly defined. or this reason, the simplest way to manually set is to run the graphical user interface of CMake, `cmake-gui`. cd CGAL-\cgalReleaseNumber/examples/Triangulation_2 - cmake-gui -DCGAL_DIR=$HOME/CGAL-\cgalReleaseNumber -CMAKE_BUILD_TYPE=Release . + cmake-gui -CMAKE_BUILD_TYPE=Release . After the `CMake` window opens, press 'Configure'. A dialog will pop up and you will have to choose what shall be generated. After you have made your choice and pressed 'Finish', you will see @@ -179,8 +188,8 @@ if desired) and lines are gray, you are now ready to press 'Generate', and to exit `cmake-gui` afterwards. \cgalAdvancedBegin -If you decide to solve missing dependencies using the command line tool (not the recommended way), -the page \ref configurationvariables lists variables which can be used to specify +You may also decide to solve missing dependencies using the command line tool (which is not recommended). +If so, the page \ref configurationvariables lists variables which can be used to specify the location of third-party software. \cgalAdvancedEnd @@ -197,6 +206,11 @@ the process of configuring a user's program called `executable.cpp` amounts to: cgal_create_CMakeLists -s executable cmake -DCGAL_DIR=$HOME/CGAL-\cgalReleaseNumber -CMAKE_BUILD_TYPE=Release . +Note that the script `cgal_create_CMakeLists` creates a very coarse `CMakeLists.txt` file which +might not properly encode the third party dependencies of your program. Users are advised to look +at the `CMakeLists.txt` files in the example folder(s) of the package that they are using to +learn how to specify their dependencies. + \subsection usage_configuring_advanced_cmake Advanced Configuration Options CMake keeps the variables that a user can manipulate in a so-called CMake cache, a simple text file From ee054a862ceb6de7e98dc746ef8d1be5e769f6ba Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mael=20Rouxel-Labb=C3=A9?= Date: Tue, 22 Oct 2019 11:19:45 +0200 Subject: [PATCH 214/363] Minor improvements to Cuboid/Tr computations - Slight robustness improvements by storing in memory that the intersection points are by construction on the plane. - const& and such Pair programming w/ mgimeno! --- .../Iso_cuboid_3_Triangle_3_intersection.h | 126 ++++++++++-------- 1 file changed, 71 insertions(+), 55 deletions(-) diff --git a/Intersections_3/include/CGAL/Intersections_3/internal/Iso_cuboid_3_Triangle_3_intersection.h b/Intersections_3/include/CGAL/Intersections_3/internal/Iso_cuboid_3_Triangle_3_intersection.h index 0e8f1ebc186..e94f309dc9f 100644 --- a/Intersections_3/include/CGAL/Intersections_3/internal/Iso_cuboid_3_Triangle_3_intersection.h +++ b/Intersections_3/include/CGAL/Intersections_3/internal/Iso_cuboid_3_Triangle_3_intersection.h @@ -26,8 +26,9 @@ #include #include -#include +#include #include +#include namespace CGAL { @@ -38,49 +39,61 @@ namespace internal { //only work for convex polygons, but in here that's always the case template void clip_poly_halfspace( - const std::vector& input, + std::vector& polygon, const typename K::Plane_3& pl, - std::vector& output) + const K& k) { - if(input.empty()) + if(polygon.empty()) return; typedef typename K::Point_3 Point; typedef typename K::Plane_3 Plane; - typedef typename K::Segment_3 S; + typedef typename K::Segment_3 Segment; typedef typename Intersection_traits, CGAL::Segment_3 >::result_type SP_type; - std::list p_list(input.begin(), input.end()); - auto it = p_list.begin(); + // Keep in memory which points we are going to delete later (newer intersection points + // by construction will not be deleted) + std::list > p_list; + for(const Point& p : polygon) + p_list.emplace_back(p, pl.has_on_positive_side(p)); + //corefine with plane. + auto it = p_list.begin(); while(it != p_list.end()) { - Point p = *it; - ++it; + const Point& p1 = (it++)->first; if(it == p_list.end()) break; - if(do_intersect(S(p, *it), pl)) + + const Point& p2 = it->first; + const Segment seg = k.construct_segment_3_object()(p1, p2); + + if(do_intersect(seg, pl)) { - SP_type inter = typename K::Intersect_3()(S(p, *it), pl); + SP_type inter = k.intersect_3_object()(seg, pl); if(inter) { Point* p_inter = boost::get(&*inter); if(p_inter - && *p_inter != p - && *p_inter != *it) - p_list.insert(it, *p_inter); + && !(k.equal_3_object()(*p_inter, p1)) + && !(k.equal_3_object()(*p_inter, p2))) + { + // 'false' because we know the intersection is by construction not on the positive side of the plane + p_list.insert(it, std::make_pair(*p_inter, false)); + } } } } - if(input.size() >2) + if(polygon.size() > 2) { - Point p2(p_list.front()), - p1(p_list.back()); - S seg(p1, p2); + const Point& p2 = p_list.front().first; + const Point& p1 = p_list.back().first; + const Segment seg(p1, p2); + if(do_intersect(seg, pl)) { SP_type inter = typename K::Intersect_3()(seg, pl); @@ -88,25 +101,29 @@ void clip_poly_halfspace( { Point* p_inter = boost::get(&*inter); if(p_inter - && *p_inter != p1 - && *p_inter != p2) - p_list.push_back(*p_inter); + && !(k.equal_3_object()(*p_inter, p1)) + && !(k.equal_3_object()(*p_inter, p2))) + { + // 'false' because we know the intersection is by construction not on the positive side of the plane + p_list.emplace_back(*p_inter, false); + } } } } + //remove all points on positive side - - for(auto p_it = p_list.begin(); - p_it != p_list.end();) + for(auto it = p_list.begin(); it != p_list.end();) { - if(pl.has_on_positive_side(*p_it)) - p_it = p_list.erase(p_it); + if(it->second) + it = p_list.erase(it); else - ++p_it; + ++it; } - for(auto p : p_list) - output.push_back(p); + // Update the polygon + polygon.clear(); + for(const auto& pr : p_list) + polygon.push_back(pr.first); } template @@ -114,12 +131,12 @@ typename Intersection_traits Poly; typedef typename Intersection_traits >::result_type Res_type; //Lazy implem: clip 6 times the input triangle. - Plane_3 planes[6]; - planes[0] = Plane_3(cub.vertex(0), - cub.vertex(1), - cub.vertex(5)); + Plane planes[6]; + planes[0] = Plane(cub.vertex(0), + cub.vertex(1), + cub.vertex(5)); - planes[1] = Plane_3(cub.vertex(0), - cub.vertex(4), - cub.vertex(3)); + planes[1] = Plane(cub.vertex(0), + cub.vertex(4), + cub.vertex(3)); - planes[2]=Plane_3(cub.vertex(0), + planes[2] = Plane(cub.vertex(0), cub.vertex(3), cub.vertex(1)); - planes[3] = Plane_3(cub.vertex(7), - cub.vertex(6), - cub.vertex(1)); + planes[3] = Plane(cub.vertex(7), + cub.vertex(6), + cub.vertex(1)); - planes[4] = Plane_3(cub.vertex(7), - cub.vertex(3), - cub.vertex(4)); + planes[4] = Plane(cub.vertex(7), + cub.vertex(3), + cub.vertex(4)); - planes[5] = Plane_3(cub.vertex(7), - cub.vertex(4), - cub.vertex(6)); + planes[5] = Plane(cub.vertex(7), + cub.vertex(4), + cub.vertex(6)); std::vector poly; poly.push_back(tr.vertex(0)); @@ -158,11 +175,7 @@ intersection( poly.push_back(tr.vertex(2)); for (int i = 0; i < 6; ++i) - { - Poly clipped; - clip_poly_halfspace(poly, planes[i], clipped); - poly = clipped; - } + clip_poly_halfspace(poly, planes[i], k); switch(poly.size()) { @@ -184,7 +197,7 @@ intersection( case 3: { - Triangle res = Triangle (poly[0], poly[1], poly[2]); + Triangle res = Triangle(poly[0], poly[1], poly[2]); return Res_type(std::forward(res)); } break; @@ -205,6 +218,9 @@ intersection( { return intersection(cub, tr, k); } -}}} + +} // namespace internal +} // namespace Intersections +} // namespace CGAL #endif // CGAL_INTERSECTIONS_3_INTERNAL_ISO_CUBOID_3_TRIANGLE_3_INTERSECTION_H From 47717b0c9cfcf68ac6db6a1157c9b58f8347900a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mael=20Rouxel-Labb=C3=A9?= Date: Tue, 22 Oct 2019 11:21:02 +0200 Subject: [PATCH 215/363] Add more tests to Cuboid-Tr intersections --- .../Intersections_3/test_intersections_3.cpp | 196 +++++++++++------- 1 file changed, 120 insertions(+), 76 deletions(-) diff --git a/Intersections_3/test/Intersections_3/test_intersections_3.cpp b/Intersections_3/test/Intersections_3/test_intersections_3.cpp index c4f1c4197d9..12c0e0db629 100644 --- a/Intersections_3/test/Intersections_3/test_intersections_3.cpp +++ b/Intersections_3/test/Intersections_3/test_intersections_3.cpp @@ -62,6 +62,7 @@ struct Test { typedef CGAL::Iso_cuboid_3< K > Cub; typedef CGAL::Sphere_3< K > Sph; typedef CGAL::Bbox_3 Bbox; + typedef std::vector

      Pol; template < typename Type > @@ -95,20 +96,20 @@ struct Test { bool approx_equal(const S & p, const S & q) { - return approx_equal(p.source(), q.source()) && approx_equal(p.target(), q.target()); + return approx_equal(p.source(), q.source()) && approx_equal(p.target(), q.target()); } - /* bool approx_equal(const Pol & p, const Pol & q) { - if (p.size() != q.size()) - return false; - for(typename Pol::const_iterator itp = p.begin(), itq = q.begin(); itp != p.end(); ++itp, ++itq) - if (!approx_equal(*itp, *itq)) - return false; - return true; + if(p.size() != q.size()) + return false; + + for(typename Pol::const_iterator itp = p.begin(), itq = q.begin(); itp != p.end(); ++itp, ++itq) + if(!approx_equal(*itp, *itq)) + return false; + + return true; } - */ template < typename O1, typename O2> void check_no_intersection(const O1& o1, const O2& o2) @@ -565,75 +566,113 @@ struct Test { } // end function Bbox_Tr void Cub_Tr(bool is_exact) + { + typedef typename CGAL::Intersection_traits::result_type Res; + + std::cout << "Triangle_3 - Cuboid_3\n"; + + // tr outside + Cub cub(P(1,1,1), P(2,2,2)); + check_no_intersection(cub, Tr(P(1.1, 2, 0), P(2, 3, 1), P(4, 5, 6))); + + // tr in a face + check_intersection(cub, Tr(P(1, 1.1, 1), P(1, 1.5, 1), P(1, 1, 1.1)), + Tr(P(1, 1.1, 1), P(1, 1.5, 1), P(1, 1, 1.1))); + + //face in a tr + Tr tr(P(-3, -3, 1), P(3, -3, 1), P(1.5, 6, 1)); + Res res = CGAL::intersection(cub, tr); + Pol* poly = boost::get >(&*res); + CGAL_assertion(poly != nullptr); + CGAL_assertion(poly->size() == 4); + if(is_exact) { - std::cout << "Triangle_3 - Cuboid_3\n"; - - Cub cub(P(1,1,1), P(2,2,2)); - - check_no_intersection(cub, Tr(P(1.1, 2,0), - P(2, 3, 1), - P(4, 5, 6))); - - //tr in a face - check_intersection(cub, Tr(P(1,1.1,1), - P(1,1.5,1), - P(1,1,1.1)), - Tr(P(1,1.1,1), - P(1,1.5,1), - P(1,1,1.1)) - ); - //face in a tr - - typedef typename CGAL::Intersection_traits::result_type Res; - Tr tr(P(-3, -3, 1), P(3,-3,1), P(1.5,6,1)); - Res res = CGAL::intersection(cub, tr); - if(is_exact) - { - std::vector

      * poly = boost::get >(&*res); - CGAL_assertion(poly != nullptr); - CGAL_assertion(poly->size() == 4); - for(auto p : *poly) - { - CGAL_assertion(tr.has_on(p) && cub.has_on_boundary(p)); - } - } - - //tr adj to a point - - check_intersection (cub, Tr(P(1, 0.5, 0.5), - P(3, 2, 1), - P(3, 1, 2)), - P(2,1,1)); - //tr adj to an edge - check_intersection (cub, Tr(P(1,0,4), P(2,1,0), P(4,3,0)), - S(P(2,1,2), P(2,1,1))); - //tr inside - check_intersection (cub, Tr(P(1.1,1.1,1.1), P(1.8,1.8,1.8), P(1.5,1.8,1.1)), - Tr(P(1.1,1.1,1.1), P(1.8,1.8,1.8), P(1.5,1.8,1.1))); - //tr through - tr = Tr(P(2, 4, 2), - P(1, 3.5, -0.5), - P(1, -1, 1)); - res = CGAL::intersection(cub, tr); - if(is_exact) - { - std::vector

      * poly = boost::get >(&*res); - CGAL_assertion(poly != nullptr); - CGAL_assertion(poly->size() == 4); - for(auto p : *poly) - { - CGAL_assertion(tr.has_on(p) && cub.has_on_boundary(p)); - } - } + CGAL_assertion_code(for(auto& p : *poly)) + CGAL_assertion(tr.has_on(p) && cub.has_on_boundary(p)); } + //tr adj to a cuboid vertex + check_intersection(cub, Tr(P(1, 0.5, 0.5), P(3, 2, 1), P(3, 1, 2)), P(2,1,1)); + + //tr adj to a point on a cuboid edge + check_intersection(cub, Tr(P(1, 0.5, 0.5), P(3, 2, 1), P(3, 1, 2)), P(2,1,1)); + + //tr adj to a point on a cuboid face + check_intersection(cub, Tr(P(1, 1.5, 1.5), P(0, 0, 0), P(-4, 3, 1)), P(1, 1.5, 1.5)); + + //tr adj to an edge + check_intersection(cub, Tr(P(2, 1.5, 2), P(5, 6, 7), P(4, 7, 6)), P(2, 1.5, 2)); + + //tr sharing an edge + check_intersection(cub, Tr(P(2, 1.5, 2), P(2, 2.5, 2), P(4, 7, 6)), + S(P(2, 1.5, 2), P(2, 2, 2))); + + //tr sharing part of an edge + check_intersection(cub, Tr(P(2, 1.5, 2), P(5, 6, 7), P(4, 7, 6)), P(2, 1.5, 2)); + + //tr inside + check_intersection(cub, Tr(P(1.1,1.1,1.1), P(1.8,1.8,1.8), P(1.5,1.8,1.1)), + Tr(P(1.1,1.1,1.1), P(1.8,1.8,1.8), P(1.5,1.8,1.1))); + + //tr through + tr = Tr(P(2, 4, 2), P(1, 3.5, -0.5), P(1, -1, 1)); + res = CGAL::intersection(cub, tr); + poly = boost::get >(&*res); + CGAL_assertion(poly != nullptr); + CGAL_assertion(poly->size() == 4); + if(is_exact) + { + CGAL_assertion_code(for(const P& p : *poly)) + CGAL_assertion(tr.has_on(p) && cub.has_on_boundary(p)); + } + + //cutting in half along diagonal (intersection == triangle) + check_intersection(cub, Tr(P(1, 1, 1), P(2, 2, 2), P(2, 2, 1)), + Tr(P(1, 1, 1), P(2, 2, 2), P(2, 2, 1))); + + //cutting in half along diagonal (intersection included in triangle) + tr = Tr(P(1, 1, 10), P(10, 10, 1), P(1, 1, 1)); + res = CGAL::intersection(cub, tr); + poly = boost::get >(&*res); + CGAL_assertion(poly != nullptr); + CGAL_assertion(poly->size() == 4); + if(is_exact) + { + CGAL_assertion_code(for(const P& p : *poly)) + CGAL_assertion(tr.has_on(p) && cub.has_on_boundary(p)); + } + + //6 points intersection + tr = Tr(P(18.66, -5.4, -11.33), P(-2.41, -7.33, 19.75), P(-10.29, 20.15, -10.33)); + res = CGAL::intersection(cub, tr); + poly = boost::get >(&*res); + CGAL_assertion(poly != nullptr); + CGAL_assertion(poly->size() == 6); + if(is_exact) + { + CGAL_assertion_code(for(const P& p : *poly)) + CGAL_assertion(tr.has_on(p) && cub.has_on_boundary(p)); + } + + //triangle clipping a cuboid corner + tr = Tr(P(1.02, 1.33, 0.62), P(1.95, 2.54, 0.95), P(0.79, 2.36, 1.92)); + res = CGAL::intersection(cub, tr); + Tr* tr_res = boost::get(&*res); + CGAL_assertion(tr_res != nullptr); + if(is_exact) + { + CGAL_assertion(cub.has_on_boundary((*tr_res)[0])); + CGAL_assertion(cub.has_on_boundary((*tr_res)[1])); + CGAL_assertion(cub.has_on_boundary((*tr_res)[2])); + } + } + void run(bool is_exact = false) { std::cout << "3D Intersection tests\n"; P_do_intersect(); Cub_Cub(); + Cub_Tr(is_exact); L_Cub(); Pl_L(); Pl_Pl(); @@ -650,17 +689,22 @@ struct Test { Bbox_L(); Bbox_R(); Bbox_Tr(); - Cub_Tr(is_exact); } }; int main() { - Test< CGAL::Simple_cartesian >().run(); - Test< CGAL::Homogeneous >().run(); - Test< CGAL::Epeck >().run(true); - Test< CGAL::Homogeneous >().run(true); - // TODO : test more kernels. + std::cout << " |||||||| Test Simple_cartesian ||||||||" << std::endl; + Test< CGAL::Simple_cartesian >().run(); + + std::cout << " |||||||| Test CGAL::Homogeneous ||||||||" << std::endl; + Test< CGAL::Homogeneous >().run(); + + std::cout << " |||||||| Test EPECK ||||||||" << std::endl; + Test< CGAL::Epeck >().run(true); + + std::cout << " |||||||| Test CGAL::Homogeneous ||||||||" << std::endl; + Test< CGAL::Homogeneous >().run(true); } From 89554f6063e3f0a2e02d3ee89ea30bc644fd9287 Mon Sep 17 00:00:00 2001 From: Simon Giraudot Date: Tue, 22 Oct 2019 12:56:36 +0200 Subject: [PATCH 216/363] Fix outputiterator return missing --- Spatial_searching/include/CGAL/Kd_tree_node.h | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/Spatial_searching/include/CGAL/Kd_tree_node.h b/Spatial_searching/include/CGAL/Kd_tree_node.h index 647124d6fec..3659525f2dc 100644 --- a/Spatial_searching/include/CGAL/Kd_tree_node.h +++ b/Spatial_searching/include/CGAL/Kd_tree_node.h @@ -209,7 +209,7 @@ namespace CGAL { if (node->size() > 0) { typename internal::Has_points_cache::type::value>::type dummy; - search_in_leaf(node, q, tree_points_begin, cache_begin, dim, it, dummy); + it = search_in_leaf(node, q, tree_points_begin, cache_begin, dim, it, dummy); } } else { @@ -297,7 +297,7 @@ namespace CGAL { // With cache template - void search_in_leaf( + OutputIterator search_in_leaf( Leaf_node_const_handle node, const FuzzyQueryItem &q, typename Kdt::const_iterator tree_points_begin, @@ -314,11 +314,12 @@ namespace CGAL { if (contains(q, *it_node_point, cache_point_it, cache_point_it + dim, dummy)) *oit++ = *it_node_point; } + return oit; } // Without cache template - void search_in_leaf( + OutputIterator search_in_leaf( Leaf_node_const_handle node, const FuzzyQueryItem &q, typename Kdt::const_iterator /*tree_points_begin*/, @@ -332,6 +333,7 @@ namespace CGAL { if (q.contains(*i)) *oit++ = *i; } + return oit; } // With cache From 54aef42f2db4856414b91cef5908c22fb258604d Mon Sep 17 00:00:00 2001 From: Simon Giraudot Date: Tue, 22 Oct 2019 13:03:35 +0200 Subject: [PATCH 217/363] Fix warning --- .../include/CGAL/Orthogonal_incremental_neighbor_search.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Spatial_searching/include/CGAL/Orthogonal_incremental_neighbor_search.h b/Spatial_searching/include/CGAL/Orthogonal_incremental_neighbor_search.h index 4c7957b9ac8..d1d14522b74 100644 --- a/Spatial_searching/include/CGAL/Orthogonal_incremental_neighbor_search.h +++ b/Spatial_searching/include/CGAL/Orthogonal_incremental_neighbor_search.h @@ -279,7 +279,7 @@ namespace CGAL { typename Tree::iterator it_node_point = node->begin(), it_node_point_end = node->end(); typename std::vector::const_iterator cache_point_begin = m_tree.cache_begin() + m_dim*(it_node_point - m_tree.begin()); - for (; it_node_point != node->end(); ++it_node_point) + for (; it_node_point != it_node_point_end; ++it_node_point) { number_of_items_visited++; FT distance_to_query_point = From 11caea2611e284538f358485fdf3ca4bbcb623aa Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mael=20Rouxel-Labb=C3=A9?= Date: Wed, 23 Oct 2019 09:12:03 +0200 Subject: [PATCH 218/363] Add a note about the different ways to download CGAL --- Documentation/doc/Documentation/Usage.txt | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/Documentation/doc/Documentation/Usage.txt b/Documentation/doc/Documentation/Usage.txt index 02de8021953..71a192c591f 100644 --- a/Documentation/doc/Documentation/Usage.txt +++ b/Documentation/doc/Documentation/Usage.txt @@ -45,6 +45,14 @@ or to build your own project using \cgal, see Section \ref secoptional3rdpartyso \section secgettingcgal Downloading CGAL +\cgal can be obtained through different channels. We recommend using a package manager as +this will ensure that all essential third party dependencies are present, and with the correct versions. +You may also download the sources of \cgal directly, but it is then your responsability to independently +acquire these dependencies. + +The examples and demos of \cgal are not included when you install \cgal with a package manager, +and must be downloaded here. + \subsection secusingpkgman Using a Package Manager On most operating systems, package managers offer \cgal and its essential third party dependencies. From 68b6387e208ffcead71cc42edf04681c25aac0b5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mael=20Rouxel-Labb=C3=A9?= Date: Wed, 23 Oct 2019 09:12:38 +0200 Subject: [PATCH 219/363] Fix a warning --- Documentation/doc/Documentation/Usage.txt | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Documentation/doc/Documentation/Usage.txt b/Documentation/doc/Documentation/Usage.txt index 71a192c591f..80316eb83a3 100644 --- a/Documentation/doc/Documentation/Usage.txt +++ b/Documentation/doc/Documentation/Usage.txt @@ -109,7 +109,7 @@ contains the following subdirectories: | `src` | source files | The directories `include/CGAL/CORE` and `src/CGALCore` contain a -distribution of the \sc{Core} library version 1.7 for +distribution of the Core library version 1.7 for dealing with algebraic numbers. Note that \sc{Core} is not part of \cgal and has its own license. @@ -120,9 +120,9 @@ which provides solvers for sparse linear systems, especially designed for the Co The only documentation shipped within \cgal sources is the present installation manual. The \cgal manual can be accessed online at -`https://doc.cgal.org` +`https://doc.cgal.org` or downloaded separately at -`https://github.com/CGAL/cgal/releases`. +`https://github.com/CGAL/cgal/releases`. \section section_headeronly Header-only Usage From 3000cbbf8be82ad364ac1667f9d834682bbbd053 Mon Sep 17 00:00:00 2001 From: Maxime Gimeno Date: Wed, 23 Oct 2019 10:44:56 +0200 Subject: [PATCH 220/363] Fix warning --- .../internal/Iso_cuboid_3_Triangle_3_intersection.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Intersections_3/include/CGAL/Intersections_3/internal/Iso_cuboid_3_Triangle_3_intersection.h b/Intersections_3/include/CGAL/Intersections_3/internal/Iso_cuboid_3_Triangle_3_intersection.h index e94f309dc9f..2762d9ad588 100644 --- a/Intersections_3/include/CGAL/Intersections_3/internal/Iso_cuboid_3_Triangle_3_intersection.h +++ b/Intersections_3/include/CGAL/Intersections_3/internal/Iso_cuboid_3_Triangle_3_intersection.h @@ -51,7 +51,7 @@ void clip_poly_halfspace( typedef typename K::Segment_3 Segment; typedef typename Intersection_traits, + Plane, CGAL::Segment_3 >::result_type SP_type; // Keep in memory which points we are going to delete later (newer intersection points From 5a38ba5c7ef16ad1811c379dbb39863e07985cb6 Mon Sep 17 00:00:00 2001 From: Andreas Fabri Date: Wed, 23 Oct 2019 15:26:35 +0200 Subject: [PATCH 221/363] small fixes --- Documentation/doc/Documentation/Usage.txt | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Documentation/doc/Documentation/Usage.txt b/Documentation/doc/Documentation/Usage.txt index 80316eb83a3..65cff71be5f 100644 --- a/Documentation/doc/Documentation/Usage.txt +++ b/Documentation/doc/Documentation/Usage.txt @@ -142,7 +142,7 @@ Gathering all this information is called configuration. The end of the pr by the generation of a makefile or a Visual \cpp solution and project file that you can use to build your program. -CMake maintains configuration parameters in so-called cmake variables, like the `CMAKE_CXX_COMPILER` +CMake maintains configuration parameters in so-called Cmake variables, like the `CMAKE_CXX_COMPILER` in the example above. These variables are not environment variables but CMake variables. Some of the CMake variables represent user choices, such as `CMAKE_BUILD_TYPE`, whereas others indicate the details of a third-party library, such as `Boost_INCLUDE_DIR` @@ -152,13 +152,13 @@ The most important CMake variable is the variable `CGAL_DIR`, which will serve t as you configure your program. In a typical installation of dependencies, almost all CMake variables will be set automatically. -The variable `CGAL_DIR` is also generally found when \cgal has been obtained via a package manger. +The variable `CGAL_DIR` is also generally found when \cgal has been obtained via a package manager. In the rare event that it has not, the variable `CGAL_DIR` should be set manually to:

      • something like `/usr/local/Cellar/cgal/CGAL-\cgalReleaseNumber/lib/cmake/CGAL`, for Brew.
      • something like `/usr/lib/x86_64-linux-gnu/cmake/CGAL` for Linux distributions.
      • -
      • something like `VCPKG_DIR/packages/cgal_x64-windows/lib/cgal`, for VCPKG_DIR.
      • +
      • something like `VCPKG_DIR/installed/x64-windows/lib/cgal`, for vcpk.
      If \cgal has been obtained via other means, `CGAL_DIR` must point to the root directory From dbac6ebd85fe5906791df172c2e23ae0fd923244 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mael=20Rouxel-Labb=C3=A9?= Date: Thu, 24 Oct 2019 10:53:27 +0200 Subject: [PATCH 222/363] WIP page about Windows --- .../doc/Documentation/Getting_started.txt | 2 + Documentation/doc/Documentation/windows.txt | 148 ++++++++++++++++++ 2 files changed, 150 insertions(+) create mode 100644 Documentation/doc/Documentation/windows.txt diff --git a/Documentation/doc/Documentation/Getting_started.txt b/Documentation/doc/Documentation/Getting_started.txt index 63359dbbe04..34128eaa5ee 100644 --- a/Documentation/doc/Documentation/Getting_started.txt +++ b/Documentation/doc/Documentation/Getting_started.txt @@ -3,6 +3,8 @@ - \subpage usage describes how to obtain \cgal and the few steps required to build a program using \cgal. +- \subpage windows blabla + - \subpage thirdparty lists required and optional third party libraries. - \subpage manual gives an idea of where you should look for documentation. diff --git a/Documentation/doc/Documentation/windows.txt b/Documentation/doc/Documentation/windows.txt new file mode 100644 index 00000000000..207472a6ef7 --- /dev/null +++ b/Documentation/doc/Documentation/windows.txt @@ -0,0 +1,148 @@ +/*! +\page windows Installing %CGAL for Visual C++ on Windows +\cgalAutoToc + +\cgal is a library that has mandatory dependencies that must be first installed: +\ref thirdpartyBoost and \ref thirdpartyMPFR. + +You have two options to install mandatory dependencies: you can either use +the vcpkg library manager, which will automatically install an appropriate version of +these dependencies as you install \cgal, or you can install the dependencies on your own +(making sure that you are using a supported version) by following their respective +installation instructions. + +If you choose to use `vcpkg`, you might have to bootstrap and download +and compile it, but from then on `vcpkg` will make your life easier. + +[You may opt for not using `vcpkg` because you upgraded and you already +have installed boost, or you need a specific boost version, and not +the latest one, which you would get with `vcpkg`.] + +In the next two sections we explain the two approaches. + +\section installing-with-vcpkg Installing CGAL with the vcpkg Library Manager + +\subsection install-vcpk Installing vcpkg + +The first step is to clone or download `vcpkg` from +https://github.com/microsoft/vcpkg. + +\code{.sh} + C:\dev> git clone https://github.com/microsoft/vcpkg + C:\dev> cd vcpkg + C:\dev\vcpkg> .\bootstrap-vcpkg.bat + C:\dev\vcpkg> .\vcpkg integrate install +\endcode + +The last step requires to run *cmd* with administrator rights. + +\subsection install-cgal-vcpk Installing CGAL itself + +By default `vcpkg` installs for 32 bit and will use the latest version of Visual C++ +installed on your machine. If you develop 64 bit software you must +set the Windows environment variable `VCPKG_DEFAULT_TRIPLE` to `x64-windows` +or pass the option `--triplet x64-windows` whenever you install a package. +We refer to the +official documentation +of `vcpkg` if you want to compile for an older version of a compiler. + +You are now ready to install \cgal: + +\code{.sh} + C:\dev\vcpkg> ./vcpkg.exe install cgal +\endcode + +This will take roughly 15 minutes and it downloads MPIR (a fork of GMP), +MPFR, all boost header files, and it will compile MPIR and MPFR, as well +as several boost libraries. +Afterwards, you will find the include files, libraries, and dlls in the +subdirectory `C:\dev\vcpkg\installed\x64-windows`. + +Note that \cgal is a header-only library, and there is therefore no `lib` or `dll` files. + +\subsection compile-example-vcpk Compiling an Example + +Let's next compile a program that uses \cgal. +The examples you find in these User Manual pages are not downloaded when you install \cgal +with the vcpkg library manager and you must download them separately from the following download page: +CGAL-\cgalReleaseNumber-examples.zip + +Assuming you have unzipped this file in your home directory, we will +next compile an example from the 2D Triangulation package. + +\subsubsection sssectConfiguration Configuring of an Example + +Before building anything using \cgal you have to choose the compiler/linker, set compiler +and linker flags, specify which third-party libraries you want to use and where they can be found. +Gathering all this information is called *configuration* and we use CMake as configuration tool +(see Section \ref seccmake for more information on minimal supported versions and where to +download it). + +The end of the process is marked by the generation of a Visual \cpp solution and +project file that you can use to build your program. + +\code{.sh} + C:\Users\Me\CGAL-5.0> cd examples\Triangulation_2 + C:\Users\Me\CGAL-5.0\examples\Triangulation_2> mkdir build + C:\Users\Me\CGAL-5.0\examples\Triangulation_2> cd build + C:\Users\Me\CGAL-5.0\examples\Triangulation_2\build> cmake-gui .. +\endcode + +When you hit the *Configure* button you must choose the compiler, +you must *Specify the Generator* (Visual Studio 16 2019), you must +specify the *Optional Platform* ('x64' in case you want to create 64 binaries), +and you must select *Specify toolchain file for cross compilation* +(`C:/dev/vcpkg/scripts/buildsystems/vcpkg.cmake`, which you have +to adapt to where you installed * vcpkg* on your machine). +Once the configuration is done, tick *Advanced* and *Grouped* in *cmake-gui*. +You will see entries for where header files and libraries are taken from. + +\subsubsection sssectConfigurationAdditionalDependencies Additional Dependencies + +Individual \cgal packages may also have additional dependencies. During the configuration +of the above examples, you may have observed the following message: + +\code{.sh} + NOTICE: a few examples require Qt and will not be compiled. +\endcode + +\cgal is a library of algorithms and data structures and as such does +not depend on Qt. However, one of the examples does for visualization purposes only. Either you +have Qt installed and you can fill in the requested CMake variables, or we install it now using `vcpkg`: + +\code{.sh} + C:\dev\vcpkg> .\vcpkg.exe install qt5 +\endcode + +Remember to specify `--triplet` or the related enviromnent variable in case you target 64 bit applications. + +When you start *cmake-gui* again and hit the `Configure` button, +the CMake variables concerning Qt should now be filled. + +Note that `cmake-gui` is a graphical user interface for CMake, but you can also run `cmake` +commands from the command line, or even manipulate the file CMakeCache.txt directly +with a text editor. + +\subsubsection sssectCompilation Compilation of an Example + +Hit the *Generate* button, and you will find the file `Triangulation_2_examples.sln` +in the directory `C:\Users\Me\CGAL-5.0\examples\Triangulation_2\build`. +Double click in order to open it. You will see one project per `.cpp` file. +Compile them all or just the one you are interested in. + +\subsection vcpk-my-example Compiling my Code which Uses CGAL + +todo: Explain the script `cgal_create_CMakeLists` and its options are detailed in Section \ref devman_create_cgal_CMakeLists. + +\section install-from-installer Installing By Hand + +You can download and run `CGAL-\cgalReleaseNumber``-Setup.exe` from https://www.cgal.org/download/windows.html. +It is a self extracting executable that downloads the \cgal header files, as well as the source code of the +examples and demos, and that allows you to select and download the precompiled versions of GMP and Mpfr. + +The script `cgal_create_CMakeLists` and its options are detailed in Section \ref devman_create_cgal_CMakeLists. + +In a less ideal world, you might have to install some required tools and third-party libraries. +This is what this page is about. + +*/ From 1a1ce7aebaeaa2d00ea9ceecd5a7558577371c16 Mon Sep 17 00:00:00 2001 From: Andreas Fabri Date: Thu, 24 Oct 2019 15:26:16 +0200 Subject: [PATCH 223/363] Section on the Installer --- Documentation/doc/Documentation/windows.txt | 159 +++++++++++++++++--- 1 file changed, 134 insertions(+), 25 deletions(-) diff --git a/Documentation/doc/Documentation/windows.txt b/Documentation/doc/Documentation/windows.txt index 207472a6ef7..2664d64ff4f 100644 --- a/Documentation/doc/Documentation/windows.txt +++ b/Documentation/doc/Documentation/windows.txt @@ -20,9 +20,9 @@ the latest one, which you would get with `vcpkg`.] In the next two sections we explain the two approaches. -\section installing-with-vcpkg Installing CGAL with the vcpkg Library Manager +\section sec-installing-with-vcpkg Installing CGAL with the vcpkg Library Manager -\subsection install-vcpk Installing vcpkg +\subsection ssec-vcpk-install-vcpk Installing vcpkg The first step is to clone or download `vcpkg` from https://github.com/microsoft/vcpkg. @@ -36,9 +36,9 @@ The first step is to clone or download `vcpkg` from The last step requires to run *cmd* with administrator rights. -\subsection install-cgal-vcpk Installing CGAL itself +\subsection ssec-vcpk-install-cgal Installing CGAL Itself -By default `vcpkg` installs for 32 bit and will use the latest version of Visual C++ +By default `vcpkg` installs for 32 bit binaries and will use the latest version of Visual C++ installed on your machine. If you develop 64 bit software you must set the Windows environment variable `VCPKG_DEFAULT_TRIPLE` to `x64-windows` or pass the option `--triplet x64-windows` whenever you install a package. @@ -60,7 +60,7 @@ subdirectory `C:\dev\vcpkg\installed\x64-windows`. Note that \cgal is a header-only library, and there is therefore no `lib` or `dll` files. -\subsection compile-example-vcpk Compiling an Example +\subsection ssec-vcpkg-compile-example Compiling an Example Let's next compile a program that uses \cgal. The examples you find in these User Manual pages are not downloaded when you install \cgal @@ -70,7 +70,7 @@ with the vcpkg library manager and you must download them separately from the fo Assuming you have unzipped this file in your home directory, we will next compile an example from the 2D Triangulation package. -\subsubsection sssectConfiguration Configuring of an Example +\subsubsection sssec-vcpkg-configuration-example Configuring of an Example Before building anything using \cgal you have to choose the compiler/linker, set compiler and linker flags, specify which third-party libraries you want to use and where they can be found. @@ -89,15 +89,15 @@ project file that you can use to build your program. \endcode When you hit the *Configure* button you must choose the compiler, -you must *Specify the Generator* (Visual Studio 16 2019), you must -specify the *Optional Platform* ('x64' in case you want to create 64 binaries), +you must *Specify the Generator* (e.g., Visual Studio 16 2019), you must +specify the *Optional Platform* (`x64 in case you want to create 64 bit binaries), and you must select *Specify toolchain file for cross compilation* (`C:/dev/vcpkg/scripts/buildsystems/vcpkg.cmake`, which you have -to adapt to where you installed * vcpkg* on your machine). -Once the configuration is done, tick *Advanced* and *Grouped* in *cmake-gui*. +to adapt to where you installed `vcpkg` on your machine). +Once the configuration is done, tick *Advanced* and *Grouped* in `cmake-gui`. You will see entries for where header files and libraries are taken from. -\subsubsection sssectConfigurationAdditionalDependencies Additional Dependencies +\subsubsection sssect-vcpkg-additional-dependencies Additional Dependencies Individual \cgal packages may also have additional dependencies. During the configuration of the above examples, you may have observed the following message: @@ -114,35 +114,144 @@ have Qt installed and you can fill in the requested CMake variables, or we insta C:\dev\vcpkg> .\vcpkg.exe install qt5 \endcode -Remember to specify `--triplet` or the related enviromnent variable in case you target 64 bit applications. +Remember to specify `--triplet` or the related environment variable in case you target 64 bit applications. -When you start *cmake-gui* again and hit the `Configure` button, +When you start *cmake-gui* again and hit the *Configure* button, the CMake variables concerning Qt should now be filled. -Note that `cmake-gui` is a graphical user interface for CMake, but you can also run `cmake` -commands from the command line, or even manipulate the file CMakeCache.txt directly -with a text editor. +Note that not all dependencies are available through the `vcpkg` library manager. +In this case you have to download and install them -\subsubsection sssectCompilation Compilation of an Example +See page \ref configurationvariables et \ref thirdparty + + +\subsubsection sssect-vcpkg-compilation Compilation of an Example Hit the *Generate* button, and you will find the file `Triangulation_2_examples.sln` in the directory `C:\Users\Me\CGAL-5.0\examples\Triangulation_2\build`. Double click in order to open it. You will see one project per `.cpp` file. Compile them all or just the one you are interested in. -\subsection vcpk-my-example Compiling my Code which Uses CGAL -todo: Explain the script `cgal_create_CMakeLists` and its options are detailed in Section \ref devman_create_cgal_CMakeLists. -\section install-from-installer Installing By Hand + + +\section install-with-installer Installing with the Installer You can download and run `CGAL-\cgalReleaseNumber``-Setup.exe` from https://www.cgal.org/download/windows.html. -It is a self extracting executable that downloads the \cgal header files, as well as the source code of the -examples and demos, and that allows you to select and download the precompiled versions of GMP and Mpfr. +It is a self extracting executable that downloads the \cgal header files, and optionally the source code of the +examples and demos. Additionally, it can download the precompiled versions of GMP and Mpfr. -The script `cgal_create_CMakeLists` and its options are detailed in Section \ref devman_create_cgal_CMakeLists. +\subsection ssect-installer-boost Installing boost + +Binary versions of Boost are available on SourceForge. + +The installers install both Boost headers and precompiled libraries. +Please note that the \cgal project is not responsible for the files provided on this web site. +When \cgal \cgalReleaseNumber was released, the latest version of boost was 1.71. + +Download and run the file boost_1_71_0-msvc-XX.Y-64.exe (where XX.Y = 14.0 for VC 2015, XX.Y = 14.1 for 2017, XX.Y = 14.2 for VC 2019). + +Choose to extract the files to a new directory: c:\dev\libboost_1_71_0. + +Set the following two environment variables to point respectively to the path of the libraries and the headers + + BOOST_LIBRARYDIR=C:\dev\libboost_1_71_0\lib64-msvc-XX.Y + BOOST_INCLUDEDIR=C:\dev\libboost_1_71_0 + +as this will help `cmake` to find Boost. + +Add the path to the Boost `dlls` (C:\dev\libboost_1_71_0\lib64-msvc-XX.Y) files to the `PATH` environment variable. + + +\subsection ssect-installer-install-cgal Installing CGAL Itself + +Download and run `CGAL-\cgalReleaseNumber``-Setup.exe` from https://www.cgal.org/download/windows.html. +It is a self extracting executable that downloads the \cgal header files, and optionally the source code of the +examples and demos. Additionally, it can download the precompiled versions of GMP and Mpfr. You must +specify if yoy want the 32 or the 64 bit versions of these two libraries. + +\cgal being a header-only library, there is no need to compile it. Set the environment variable `CGAL_DIR` to `C:\dev\CGAL-5.0, +as this will help `cmake` to find \cgal. + +\subsection ssect-installer-compile-example Compiling an Example + +We assume you have downloaded the examples with the installer. + +Before building anything using \cgal you have to choose the compiler/linker, set compiler +and linker flags, specify which third-party libraries you want to use and where they can be found. +Gathering all this information is called *configuration* and we use CMake as configuration tool +(see Section \ref seccmake for more information on minimal supported versions and where to +download it). + +The end of the process is marked by the generation of a Visual \cpp solution and +project file that you can use to build your program. + +\code{.sh} + C:\dev\CGAL-5.0> cd examples\Triangulation_2 + C:\dev\CGAL-5.0\examples\Triangulation_2> mkdir build + C:\dev\CGAL-5.0\examples\Triangulation_2> cd build + C:\dev\CGAL-5.0\examples\Triangulation_2\build> cmake-gui .. +\endcode + +When you hit the *Configure* button you must choose the compiler, +you must *Specify the Generator* (e.g., Visual Studio 16 2019), you must +specify the *Optional Platform* (`x64 in case you want to create 64 bit binaries). +Once the configuration is done, tick *Advanced* and *Grouped* in `cmake-gui. +You will see entries for where header files and libraries are taken from. + + + +\subsubsection ssect-installer-additional-dependencies Additional Dependencies + +Individual \cgal packages may also have additional dependencies. During the configuration +of the above examples, you may have observed the following message: + +\code{.sh} + NOTICE: a few examples require Qt and will not be compiled. +\endcode + +\cgal is a library of algorithms and data structures and as such does +not depend on Qt. However, one of the examples does for visualization purposes only. Either you +have Qt installed and you can fill in the requested CMake variables, or we install it now. + + +Download and install the Qt library for open source development package for your Visual Studio version at +https://www.qt.io/download/ +(here is the direct link to the offline installers). + +Add the environment variable `QTDIR` pointing to the place you installed Qt, e.g., `C:\dev\Qt\Qt5.13.1`, +as this will help `cmake` to find Qt. + +Add the bin directory of Qt, e.g. add `C:\dev\Qt\Qt5.13.1\msvcXXXX_YY\bin` to `PATH`, where `XXXX_YY` is something like `vc2017_64`. +To avoid any conflict with another dll with the same name from another folder, add this path as the first in the list. + + +When you start *cmake-gui* again and hit the *Configure* button, +the CMake variables concerning Qt should now be filled. + +For other dependencies it will be similar page \ref thirdparty \ref configurationvariables + +\subsubsection sssect-installer-compilation Compilation of an Example + +Hit the *Generate* button, and you will find the file `Triangulation_2_examples.sln` +in the directory `C:\dev\CGAL-5.0\examples\Triangulation_2\build`. +Double click in order to open it. You will see one project per `.cpp` file. +Compile them all or just the one you are interested in. + + + +\section install-with-tarball Installing from the tarball + +Instead of the installer you can also download the tarball. The sole difference is that the installer +also downloads the precompiled GMP and Mpfr libraries. + + +\section sect-my-code Configuring and Compiling My Code Using CGAL + +Configuring and compiling your own code is practically the same as for \cgal examples +if you use `cmake`. You are advised to look at the `CMakeLists.txt` files in the example +folder of the package that you are using to learn how to specify dependencies. -In a less ideal world, you might have to install some required tools and third-party libraries. -This is what this page is about. */ From 1dc880d2a196ecaacf70409d8f147e5858ff6330 Mon Sep 17 00:00:00 2001 From: Maxime Gimeno Date: Thu, 24 Oct 2019 15:55:35 +0200 Subject: [PATCH 224/363] Add squared_distance(Plane_3, Plane_3) and a test. --- Distance_3/include/CGAL/squared_distance_3_2.h | 15 +++++++++++++++ Distance_3/test/Distance_3/test_distance_3.cpp | 12 ++++++++++++ 2 files changed, 27 insertions(+) diff --git a/Distance_3/include/CGAL/squared_distance_3_2.h b/Distance_3/include/CGAL/squared_distance_3_2.h index c0c03104b57..26972588ba0 100644 --- a/Distance_3/include/CGAL/squared_distance_3_2.h +++ b/Distance_3/include/CGAL/squared_distance_3_2.h @@ -399,6 +399,21 @@ squared_distance(const Triangle_3 & t, } +template +inline +typename K::FT +squared_distance(const Plane_3 & p1, + const Plane_3 & p2) { + K k;; + if( k.compute_squared_length_3_object()( + k.construct_cross_product_vector_3_object()(p1.orthogonal_vector(), + p2.orthogonal_vector())) + != 0) + return typename K::FT(0); + else + return internal::squared_distance(p1.point(), p2, k); +} + } //namespace CGAL diff --git a/Distance_3/test/Distance_3/test_distance_3.cpp b/Distance_3/test/Distance_3/test_distance_3.cpp index 5f73a7eb3cf..38abdd0b828 100644 --- a/Distance_3/test/Distance_3/test_distance_3.cpp +++ b/Distance_3/test/Distance_3/test_distance_3.cpp @@ -221,6 +221,17 @@ struct Test { check_squared_distance (L(p(2, -4, 3), p( 3,-8, 4)), Pl(0, 1, 0, 0), 0); } + void Pl_Pl() + { + std::cout << "Plane - Plane\n"; + Pl p1(12, 1, 4, 0); + typename K::Vector_3 v = -p1.orthogonal_vector(); + v /= CGAL::sqrt(v.squared_length()); + Pl p2 = Pl(p1.point()+6*v, -p1.orthogonal_vector()); + check_squared_distance (p1,p2, 36); + check_squared_distance (Pl(-2, 1, 1, 0), Pl(2, 1, 3, 0), 0); + } + void run() { std::cout << "3D Distance tests\n"; @@ -239,6 +250,7 @@ struct Test { S_Pl(); R_Pl(); L_Pl(); + Pl_Pl(); } }; From 726e530029ce4bc8cc4cbbb4a2c0a8214c74edd4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mael=20Rouxel-Labb=C3=A9?= Date: Thu, 24 Oct 2019 16:30:42 +0200 Subject: [PATCH 225/363] Update Usage on Linux / Usage on Windows pages --- .../doc/Documentation/Getting_started.txt | 4 +- Documentation/doc/Documentation/Usage.txt | 52 ++---- Documentation/doc/Documentation/windows.txt | 173 ++++++++++-------- 3 files changed, 105 insertions(+), 124 deletions(-) diff --git a/Documentation/doc/Documentation/Getting_started.txt b/Documentation/doc/Documentation/Getting_started.txt index 34128eaa5ee..1c39617f5f8 100644 --- a/Documentation/doc/Documentation/Getting_started.txt +++ b/Documentation/doc/Documentation/Getting_started.txt @@ -1,9 +1,9 @@ /*! \page general_intro Getting Started with %CGAL -- \subpage usage describes how to obtain \cgal and the few steps required to build a program using \cgal. +- \subpage usage Using \cgal on Unix -- \subpage windows blabla +- \subpage windows Using \cgal on Windows - \subpage thirdparty lists required and optional third party libraries. diff --git a/Documentation/doc/Documentation/Usage.txt b/Documentation/doc/Documentation/Usage.txt index 65cff71be5f..a15d2dde432 100644 --- a/Documentation/doc/Documentation/Usage.txt +++ b/Documentation/doc/Documentation/Usage.txt @@ -1,23 +1,21 @@ /*! -\page usage Usage +\page usage Using %CGAL on UNIX \cgalAutoToc Since \cgal version 5.0, \cgal is header-only be default, which means -that there is no need to build or install \cgal before it can be used. +that there is no need to build \cgal before it can be used. However, some dependencies of \cgal might still need to be installed. \section usage_introduction Quick Start: Compiling a Program using CGAL Assuming that you have obtained \cgal through one of the package managers offering \cgal on your platform -(see Section \ref secgettingcgal), compiling \cgal examples, which can be downloaded here, +(see Section \ref secgettingcgal), compiling \cgal examples is as simple as: cd $HOME/CGAL-\cgalReleaseNumber/examples/Triangulation_2 # go to an example directory cmake -DCMAKE_BUILD_TYPE=Release . # configure the examples make # build the examples -On Windows, instead of calling `make` simply double-click on the generated solution (`.sln`) to open Visual C++. - Compiling your own program is similar: cd /path/to/your/program @@ -34,10 +32,10 @@ This is what this page is about. Using \cgal requires a few core components to be previously installed:
        -
      • a supported compiler (see Section \ref seccompilers),
      • -
      • \ref seccmake
      • -
      • \ref thirdpartyBoost,
      • -
      • \ref thirdpartyMPFR.
      • +
      • a supported compiler (see Section \ref seccompilers),
      • +
      • \ref seccmake,
      • +
      • \ref thirdpartyBoost,
      • +
      • \ref thirdpartyMPFR.
      Optional third-party software might be required to build examples and demos shipped with \cgal, @@ -57,34 +55,19 @@ and must be downloaded here. On most operating systems, package managers offer \cgal and its essential third party dependencies. -On macOS, we recommend using of Homebrew in the following way: +On `macOS`, we recommend using of Homebrew in the following way: brew install cgal -On Linux distributions such as Debian/Ubuntu/Mint, use `apt-get` in the following way: +On Linux distributions such as `Debian`/`Ubuntu`/`Mint`, use `apt-get` in the following way: sudo apt-get install libcgal-dev -On Windows, we recommand using vcpkg in the following way: - - vcpkg install cgal - -To see how to use libraries installed with vcpkg, -refer to the official documentation. - For other distributions or package manager, please consult your respective documentation. -\subsection sseccgalwindows Using the CGAL Installer on Windows - -You can download and run `CGAL-\cgalReleaseNumber``-Setup.exe` from https://www.cgal.org/download/windows.html. -It is a self extracting executable that installs the \cgal source, and that allows you -to select and download some precompiled third party libraries. However, you will need to compile -the library using your favorite compiler. -A tutorial is provided on how to proceed with Microsoft Visual Studio. - \subsection secusingwebsite Using CGAL Source Archive -You can obtain the \cgal library from +You can also obtain the \cgal library sources directly from https://www.cgal.org/download.html. Once you have downloaded the file `CGAL-\cgalReleaseNumber``.tar.gz` containing the @@ -157,8 +140,7 @@ In the rare event that it has not, the variable `CGAL_DIR` should be set manuall
      • something like `/usr/local/Cellar/cgal/CGAL-\cgalReleaseNumber/lib/cmake/CGAL`, for Brew.
      • -
      • something like `/usr/lib/x86_64-linux-gnu/cmake/CGAL` for Linux distributions.
      • -
      • something like `VCPKG_DIR/installed/x64-windows/lib/cgal`, for vcpk.
      • +
      • something like `/usr/lib/x86_64-linux-gnu/cmake/CGAL`, for Linux distributions.
      If \cgal has been obtained via other means, `CGAL_DIR` must point to the root directory @@ -237,18 +219,6 @@ You can use the `make` command-line tool for the succeeding build step as follow cd CGAL-\cgalReleaseNumber/examples/Triangulation_2 make # build all the examples of the Triangulation_2 package -With generators other than `UNIX Makefiles` the resulting build files are solution and project files -which should be launched in an \sc{Ide}, such as Visual Studio or KDevelop3. They will contain the targets described -above, which you can manually build as with any other solution/project within your \sc{Ide}. - -Alternatively, you can build it with the command line version of the \sc{Visual Studio Ide}: - - devenv CGAL.sln /Build Release - -The "Release" argument is needed because CMake creates solution files for -all four configurations, and you need to explicitly choose one when building -(the other choices are `Debug`, `RelWithDebInfo`, and `MinSizeRel`). - \cgalAdvancedBegin The build files produced by CMake are autoconfigured. That is, if you change any of the dependencies, the build step automatically goes all the way back to the configuration step. This way, once the target diff --git a/Documentation/doc/Documentation/windows.txt b/Documentation/doc/Documentation/windows.txt index 2664d64ff4f..ac4c885895f 100644 --- a/Documentation/doc/Documentation/windows.txt +++ b/Documentation/doc/Documentation/windows.txt @@ -18,7 +18,7 @@ and compile it, but from then on `vcpkg` will make your life easier. have installed boost, or you need a specific boost version, and not the latest one, which you would get with `vcpkg`.] -In the next two sections we explain the two approaches. +We explain the two approaches in the next sections. \section sec-installing-with-vcpkg Installing CGAL with the vcpkg Library Manager @@ -34,7 +34,7 @@ The first step is to clone or download `vcpkg` from C:\dev\vcpkg> .\vcpkg integrate install \endcode -The last step requires to run *cmd* with administrator rights. +The last step requires to run `cmd` with administrator rights. \subsection ssec-vcpk-install-cgal Installing CGAL Itself @@ -72,34 +72,34 @@ next compile an example from the 2D Triangulation package. \subsubsection sssec-vcpkg-configuration-example Configuring of an Example -Before building anything using \cgal you have to choose the compiler/linker, set compiler +Before building anything using \cgal, you have to choose the compiler/linker, set compiler and linker flags, specify which third-party libraries you want to use and where they can be found. Gathering all this information is called *configuration* and we use CMake as configuration tool -(see Section \ref seccmake for more information on minimal supported versions and where to -download it). +(see Section \ref seccmake for more information on supported versions and where to download it). -The end of the process is marked by the generation of a Visual \cpp solution and -project file that you can use to build your program. +The end of the process is marked by the generation of a Visual \cpp solution +and a project file that you can use to build your program. \code{.sh} C:\Users\Me\CGAL-5.0> cd examples\Triangulation_2 C:\Users\Me\CGAL-5.0\examples\Triangulation_2> mkdir build C:\Users\Me\CGAL-5.0\examples\Triangulation_2> cd build - C:\Users\Me\CGAL-5.0\examples\Triangulation_2\build> cmake-gui .. + C:\Users\Me\CGAL-5.0\examples\Triangulation_2\build> cmake-gui .. # cmake-gui is the graphical interface for cmake, which we recommend to use \endcode -When you hit the *Configure* button you must choose the compiler, -you must *Specify the Generator* (e.g., Visual Studio 16 2019), you must -specify the *Optional Platform* (`x64 in case you want to create 64 bit binaries), -and you must select *Specify toolchain file for cross compilation* -(`C:/dev/vcpkg/scripts/buildsystems/vcpkg.cmake`, which you have -to adapt to where you installed `vcpkg` on your machine). -Once the configuration is done, tick *Advanced* and *Grouped* in `cmake-gui`. +When you hit the `Configure` button, you must: +
        +
      • specify the `Generator` (e.g., Visual Studio 16 2019),
      • +
      • specify the `Optional Platform` (e.g., `x64` in case you want to create 64 bit binaries),
      • +
      • select `Specify toolchain file for cross compilation` (the file `vcpkg.cmake` within the directory +where you have installed `vcpkg`, e.g. `C:/dev/vcpkg/scripts/buildsystems/vcpkg.cmake`).
      • +
      +Once the configuration process is done, tick `Advanced` and `Grouped` in `cmake-gui`. You will see entries for where header files and libraries are taken from. \subsubsection sssect-vcpkg-additional-dependencies Additional Dependencies -Individual \cgal packages may also have additional dependencies. During the configuration +Some \cgal packages also have additional dependencies. During the configuration of the above examples, you may have observed the following message: \code{.sh} @@ -107,66 +107,79 @@ of the above examples, you may have observed the following message: \endcode \cgal is a library of algorithms and data structures and as such does -not depend on Qt. However, one of the examples does for visualization purposes only. Either you -have Qt installed and you can fill in the requested CMake variables, or we install it now using `vcpkg`: +not depend on `Qt`. However, one of the examples in the Triangulation_2 package does require `Qt` +for visualization purposes. If you already have `Qt` installed, you can simply fill in the requested +CMake variables and paths. Otherwise, you can also install it using `vcpkg`: \code{.sh} C:\dev\vcpkg> .\vcpkg.exe install qt5 \endcode -Remember to specify `--triplet` or the related environment variable in case you target 64 bit applications. +Remember to specify `--triplet` or the related environment variable in case you target 64-bit applications. -When you start *cmake-gui* again and hit the *Configure* button, -the CMake variables concerning Qt should now be filled. +When you start `cmake-gui` again and hit the `Configure` button, +the CMake variables and paths concerning Qt should now be filled. -Note that not all dependencies are available through the `vcpkg` library manager. -In this case you have to download and install them - -See page \ref configurationvariables et \ref thirdparty +Note that not all optional dependencies are available through the `vcpkg` library manager. +In this case, you must download and install them independently (see page \ref thirdparty +for information on support versions and download links) as well as fill the missing information +within the `CMake` interface until configuration is successful (no more red lines indicating +missing dependencies). +\cgalAdvancedBegin +You may also decide to solve missing dependencies using the `CMake` command line tool (which is not recommended). +If so, the page \ref configurationvariables lists variables which can be used to specify +the location of third-party software. +\cgalAdvancedEnd \subsubsection sssect-vcpkg-compilation Compilation of an Example -Hit the *Generate* button, and you will find the file `Triangulation_2_examples.sln` +Hit the `Generate` button, and you will find the file `Triangulation_2_examples.sln` in the directory `C:\Users\Me\CGAL-5.0\examples\Triangulation_2\build`. -Double click in order to open it. You will see one project per `.cpp` file. -Compile them all or just the one you are interested in. - - +Double-click it to open it. There is one project per `.cpp` file in the directory. +Compile them all, or just the one you are interested in. +\subsection subsect-vpckg-my-code Configuring and Compiling My Code Using CGAL +Configuring and compiling your own code is practically the same as for \cgal examples +if you use `cmake`. Running `cmake` (or `cmake-gui`) requires a `CMakeLists.txt` file. +This file is automatically provided for all examples and demos of \cgal. For your own programs, +you are advised to look at the `CMakeLists.txt` files in the example +folder of the package that you are using to learn how to specify CGAL and additional third party +dependencies. \section install-with-installer Installing with the Installer You can download and run `CGAL-\cgalReleaseNumber``-Setup.exe` from https://www.cgal.org/download/windows.html. It is a self extracting executable that downloads the \cgal header files, and optionally the source code of the -examples and demos. Additionally, it can download the precompiled versions of GMP and Mpfr. +examples and demos. Additionally, it can download precompiled versions of GMP and MPFR. -\subsection ssect-installer-boost Installing boost +\subsection ssect-installer-boost Installing `Boost` -Binary versions of Boost are available on SourceForge. +Binary versions of `Boost` are available on SourceForge. -The installers install both Boost headers and precompiled libraries. -Please note that the \cgal project is not responsible for the files provided on this web site. -When \cgal \cgalReleaseNumber was released, the latest version of boost was 1.71. +The installers install both `Boost` headers and precompiled libraries. +Please note that the \cgal project is not responsible for the files provided on this website. +When \cgal \cgalReleaseNumber was released, the latest version of `Boost` was 1.71. -Download and run the file boost_1_71_0-msvc-XX.Y-64.exe (where XX.Y = 14.0 for VC 2015, XX.Y = 14.1 for 2017, XX.Y = 14.2 for VC 2019). - -Choose to extract the files to a new directory: c:\dev\libboost_1_71_0. - -Set the following two environment variables to point respectively to the path of the libraries and the headers +
        +
      • Download and run the file boost_1_71_0-msvc-XX.Y-64.exe (where XX.Y = 14.0 for VC 2015, XX.Y = 14.1 for 2017, XX.Y = 14.2 for VC 2019).
      • +
      • Extract the files to a new directory, e.g. `c:\dev\libboost_1_71_0`.
      • +
      • Set the following two environment variables to point respectively to the path of the libraries and the headers +\code{.sh} BOOST_LIBRARYDIR=C:\dev\libboost_1_71_0\lib64-msvc-XX.Y BOOST_INCLUDEDIR=C:\dev\libboost_1_71_0 +\endcode -as this will help `cmake` to find Boost. - -Add the path to the Boost `dlls` (C:\dev\libboost_1_71_0\lib64-msvc-XX.Y) files to the `PATH` environment variable. - +as this will help `cmake` to find Boost.
      • +
      • Add the path to the Boost `dlls` (`C:\dev\libboost_1_71_0\lib64-msvc-XX.Y`) files to the `PATH` environment variable.
      • +
      \subsection ssect-installer-install-cgal Installing CGAL Itself -Download and run `CGAL-\cgalReleaseNumber``-Setup.exe` from https://www.cgal.org/download/windows.html. +Download and run `CGAL-\cgalReleaseNumber``-Setup.exe` from < +a href="https://www.cgal.org/download/windows.html">https://www.cgal.org/download/windows.html. It is a self extracting executable that downloads the \cgal header files, and optionally the source code of the examples and demos. Additionally, it can download the precompiled versions of GMP and Mpfr. You must specify if yoy want the 32 or the 64 bit versions of these two libraries. @@ -174,34 +187,34 @@ specify if yoy want the 32 or the 64 bit versions of these two libraries. \cgal being a header-only library, there is no need to compile it. Set the environment variable `CGAL_DIR` to `C:\dev\CGAL-5.0, as this will help `cmake` to find \cgal. -\subsection ssect-installer-compile-example Compiling an Example +\subsection ssect-installer-compile-example Compiling an Example We assume you have downloaded the examples with the installer. -Before building anything using \cgal you have to choose the compiler/linker, set compiler +Before building anything using \cgal, you have to choose the compiler/linker, set compiler and linker flags, specify which third-party libraries you want to use and where they can be found. Gathering all this information is called *configuration* and we use CMake as configuration tool (see Section \ref seccmake for more information on minimal supported versions and where to download it). -The end of the process is marked by the generation of a Visual \cpp solution and -project file that you can use to build your program. +The end of the process is marked by the generation of a Visual \cpp solution +and a project file that you can use to build your program. \code{.sh} C:\dev\CGAL-5.0> cd examples\Triangulation_2 C:\dev\CGAL-5.0\examples\Triangulation_2> mkdir build C:\dev\CGAL-5.0\examples\Triangulation_2> cd build - C:\dev\CGAL-5.0\examples\Triangulation_2\build> cmake-gui .. + C:\dev\CGAL-5.0\examples\Triangulation_2\build> cmake-gui .. # cmake-gui is the graphical interface for cmake, which we recommend to use \endcode -When you hit the *Configure* button you must choose the compiler, -you must *Specify the Generator* (e.g., Visual Studio 16 2019), you must -specify the *Optional Platform* (`x64 in case you want to create 64 bit binaries). -Once the configuration is done, tick *Advanced* and *Grouped* in `cmake-gui. +When you hit the `Configure` button you must: +
        +
      • Specify the `Generator`, e.g., Visual Studio 16 2019), and
      • +
      • specify an `Optional Platform` (`x64` in case you want to create 64 bit binaries).
      • +
      +Once the configuration is done, tick `Advanced` and `Grouped` in `cmake-gui. You will see entries for where header files and libraries are taken from. - - \subsubsection ssect-installer-additional-dependencies Additional Dependencies Individual \cgal packages may also have additional dependencies. During the configuration @@ -215,43 +228,41 @@ of the above examples, you may have observed the following message: not depend on Qt. However, one of the examples does for visualization purposes only. Either you have Qt installed and you can fill in the requested CMake variables, or we install it now. - +
        +
      • Download and install the Qt library for open source development package for your Visual Studio version at https://www.qt.io/download/ -(here is the direct link to the offline installers). +(here is the direct link to the offline installers).
      • +
      • Add the environment variable `QTDIR` pointing to the place you installed Qt, e.g., `C:\dev\Qt\Qt5.13.1`, +as this will help `cmake` to find Qt.
      • +
      • Add the bin directory of Qt, e.g. add `C:\dev\Qt\Qt5.13.1\msvcXXXX_YY\bin` to `PATH`, where `XXXX_YY` is something like `vc2017_64`. +To avoid any conflict with another dll with the same name from another folder, add this path as the first in the list.
      • +
      • When you start `cmake-gui` again and hit the `Configure` button, +the CMake variables concerning Qt should now be filled.
      • +
      -Add the environment variable `QTDIR` pointing to the place you installed Qt, e.g., `C:\dev\Qt\Qt5.13.1`, -as this will help `cmake` to find Qt. - -Add the bin directory of Qt, e.g. add `C:\dev\Qt\Qt5.13.1\msvcXXXX_YY\bin` to `PATH`, where `XXXX_YY` is something like `vc2017_64`. -To avoid any conflict with another dll with the same name from another folder, add this path as the first in the list. - - -When you start *cmake-gui* again and hit the *Configure* button, -the CMake variables concerning Qt should now be filled. - -For other dependencies it will be similar page \ref thirdparty \ref configurationvariables +You must follow a similar process for other dependencies (see page \ref thirdparty for information +on supported versions of third party libraries as well as download links). \subsubsection sssect-installer-compilation Compilation of an Example -Hit the *Generate* button, and you will find the file `Triangulation_2_examples.sln` +Hit the `Generate` button, and you will find the file `Triangulation_2_examples.sln` in the directory `C:\dev\CGAL-5.0\examples\Triangulation_2\build`. Double click in order to open it. You will see one project per `.cpp` file. Compile them all or just the one you are interested in. +\subsection subsect-installer-my-code Configuring and Compiling My Code Using CGAL +Configuring and compiling your own code is practically the same as for \cgal examples +if you use `cmake`. Running `cmake` (or `cmake-gui`) requires a `CMakeLists.txt` file. +This file is automatically provided for all examples and demos of \cgal. For your own programs, +you are advised to look at the `CMakeLists.txt` files in the example +folder of the package that you are using to learn how to specify CGAL and additional third party +dependencies. \section install-with-tarball Installing from the tarball -Instead of the installer you can also download the tarball. The sole difference is that the installer -also downloads the precompiled GMP and Mpfr libraries. - - -\section sect-my-code Configuring and Compiling My Code Using CGAL - -Configuring and compiling your own code is practically the same as for \cgal examples -if you use `cmake`. You are advised to look at the `CMakeLists.txt` files in the example -folder of the package that you are using to learn how to specify dependencies. - +Instead of the installer you can also download release tarballs. The sole difference with the installer +procedure is that the installer also downloads precompiled GMP and MPFR libraries. */ From cc9776168a5a4aa58ff67ab858900c3a3a02b813 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mael=20Rouxel-Labb=C3=A9?= Date: Thu, 24 Oct 2019 16:34:47 +0200 Subject: [PATCH 226/363] Add one more link to configuration variables --- Documentation/doc/Documentation/windows.txt | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/Documentation/doc/Documentation/windows.txt b/Documentation/doc/Documentation/windows.txt index ac4c885895f..2feafd6916c 100644 --- a/Documentation/doc/Documentation/windows.txt +++ b/Documentation/doc/Documentation/windows.txt @@ -242,7 +242,15 @@ the CMake variables concerning Qt should now be filled.
    You must follow a similar process for other dependencies (see page \ref thirdparty for information -on supported versions of third party libraries as well as download links). +on supported versions of third party libraries as well as download links) and fill the missing information +within the `CMake` interface until configuration is successful (no more red lines indicating +missing dependencies). + +\cgalAdvancedBegin +You may also decide to solve missing dependencies using the `CMake` command line tool (which is not recommended). +If so, the page \ref configurationvariables lists variables which can be used to specify +the location of third-party software. +\cgalAdvancedEnd \subsubsection sssect-installer-compilation Compilation of an Example From 0c70d440197b15fe340593fb30aec3ae02b04a90 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mael=20Rouxel-Labb=C3=A9?= Date: Thu, 24 Oct 2019 16:40:49 +0200 Subject: [PATCH 227/363] Improve introduction of Windows.txt installation page --- Documentation/doc/Documentation/windows.txt | 20 +++++++++++--------- 1 file changed, 11 insertions(+), 9 deletions(-) diff --git a/Documentation/doc/Documentation/windows.txt b/Documentation/doc/Documentation/windows.txt index 2feafd6916c..9f083ed24dc 100644 --- a/Documentation/doc/Documentation/windows.txt +++ b/Documentation/doc/Documentation/windows.txt @@ -13,12 +13,14 @@ installation instructions. If you choose to use `vcpkg`, you might have to bootstrap and download and compile it, but from then on `vcpkg` will make your life easier. +On the other hand, if you need to specify a specific version, or have already installed +a certain version of a dependency and do not wish to potentially have multiple versions installed, +you will want to use the CGAL Installer. -[You may opt for not using `vcpkg` because you upgraded and you already -have installed boost, or you need a specific boost version, and not -the latest one, which you would get with `vcpkg`.] - -We explain the two approaches in the next sections. +We explain the two approaches in the next sections: +
      +
    • \ref sec-installing-with-vcpkg
    • +
    • \ref install-with-installer
    • \section sec-installing-with-vcpkg Installing CGAL with the vcpkg Library Manager @@ -148,7 +150,7 @@ you are advised to look at the `CMakeLists.txt` files in the example folder of the package that you are using to learn how to specify CGAL and additional third party dependencies. -\section install-with-installer Installing with the Installer +\section install-with-installer Installing with the CGAL Installer You can download and run `CGAL-\cgalReleaseNumber``-Setup.exe` from https://www.cgal.org/download/windows.html. It is a self extracting executable that downloads the \cgal header files, and optionally the source code of the @@ -158,7 +160,7 @@ examples and demos. Additionally, it can download precompiled versions of GMP an Binary versions of `Boost` are available on SourceForge. -The installers install both `Boost` headers and precompiled libraries. +The `Boost` installers install both `Boost` headers and precompiled libraries. Please note that the \cgal project is not responsible for the files provided on this website. When \cgal \cgalReleaseNumber was released, the latest version of `Boost` was 1.71. @@ -189,7 +191,7 @@ as this will help `cmake` to find \cgal. \subsection ssect-installer-compile-example Compiling an Example -We assume you have downloaded the examples with the installer. +We assume you have downloaded the examples with the \cgal Installer. Before building anything using \cgal, you have to choose the compiler/linker, set compiler and linker flags, specify which third-party libraries you want to use and where they can be found. @@ -270,7 +272,7 @@ dependencies. \section install-with-tarball Installing from the tarball -Instead of the installer you can also download release tarballs. The sole difference with the installer +Instead of the installer you can also download release tarballs. The sole difference with the \cgal Installer procedure is that the installer also downloads precompiled GMP and MPFR libraries. */ From fefc2658b70ec7472f53812f52065b2796bc0b26 Mon Sep 17 00:00:00 2001 From: Marc Glisse Date: Thu, 24 Oct 2019 23:31:31 +0200 Subject: [PATCH 228/363] PoC fix for NaN intervals multiplication can currently produce NaN, both in the return value, and internally, in which case the return value is nonsense. --- Number_types/include/CGAL/Interval_nt.h | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/Number_types/include/CGAL/Interval_nt.h b/Number_types/include/CGAL/Interval_nt.h index 79a1ff4e88d..968f9d75370 100644 --- a/Number_types/include/CGAL/Interval_nt.h +++ b/Number_types/include/CGAL/Interval_nt.h @@ -551,13 +551,23 @@ private: __m128d bz = _mm_xor_pd(bb, m); // {bi,bs} bz = IA_opacify128(bz); __m128d c = swap_m128d (bz); // {bs,bi} + + // The multiplications could produce some NaN, with 0 * inf. Replacing it with inf is safe. + // min(x,y) (the order is essential) returns its second argument when the first is NaN. + __m128d big = IA::largest().simd(); __m128d x1 = _mm_mul_pd(aa,bz); // {-ai*bi,as*bs} + x1 = _mm_min_pd(x1,big); // no NaN __m128d x2 = _mm_mul_pd(aa,c); // {-ai*bs,as*bi} + x2 = _mm_min_pd(x2,big); // no NaN __m128d x3 = _mm_mul_pd(ap,bz); // {-as*bi,ai*bs} + x3 = _mm_min_pd(x3,big); // no NaN __m128d x4 = _mm_mul_pd(ap,c); // {-as*bs,ai*bi} + x4 = _mm_min_pd(x4,big); // no NaN + __m128d y1 = _mm_max_pd(x1,x2); __m128d y2 = _mm_max_pd(x3,x4); __m128d r = _mm_max_pd (y1, y2); + // __m128d r = _mm_max_pd(x1,_mm_max_pd(x2,_mm_max_pd(x3,_mm_min_pd(x4,big)))); return IA (IA_opacify128(r)); # elif 0 // we want to multiply ai,as with {ai<0?-bs:-bi,as<0?bi:bs} From e305b72f68126aa8d1700b366eb5d3361d0c7fc5 Mon Sep 17 00:00:00 2001 From: Marc Glisse Date: Fri, 25 Oct 2019 00:51:03 +0200 Subject: [PATCH 229/363] Extend the min trick to the other multiplication methods, change the default. --- Number_types/include/CGAL/Interval_nt.h | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) diff --git a/Number_types/include/CGAL/Interval_nt.h b/Number_types/include/CGAL/Interval_nt.h index 968f9d75370..41859a8d287 100644 --- a/Number_types/include/CGAL/Interval_nt.h +++ b/Number_types/include/CGAL/Interval_nt.h @@ -539,9 +539,9 @@ private: #endif Internal_protector P; #ifdef CGAL_USE_SSE2 -# if 1 +# if !defined __SSE4_1__ && !defined __AVX__ // Brutal, compute all products in all directions. - // The actual winner (by a hair) on recent hardware + // The actual winner (by a hair) on recent hardware before removing NaNs. __m128d aa = IA_opacify128_weak(a.simd()); // {-ai,as} __m128d bb = b.simd(); // {-bi,bs} __m128d m = _mm_set_sd(-0.); // {-0,+0} @@ -569,13 +569,14 @@ private: __m128d r = _mm_max_pd (y1, y2); // __m128d r = _mm_max_pd(x1,_mm_max_pd(x2,_mm_max_pd(x3,_mm_min_pd(x4,big)))); return IA (IA_opacify128(r)); -# elif 0 +# elif 1 // we want to multiply ai,as with {ai<0?-bs:-bi,as<0?bi:bs} // we want to multiply as,ai with {as<0?-bs:-bi,ai<0?bi:bs} // requires SSE4 (otherwise use _mm_cmplt_pd, _mm_and_pd, _mm_andnot_pd and _mm_or_pd to avoid blendv) // probably faster on older hardware __m128d m = _mm_set_sd(-0.); // {-0,+0} __m128d m1 = _mm_set1_pd(-0.); // {-0,-0} + __m128d big = IA::largest().simd(); __m128d aa = a.simd(); // {-ai,as} __m128d az = _mm_xor_pd(aa, m); // {ai,as} az = IA_opacify128_weak(az); @@ -586,7 +587,9 @@ private: __m128d x = _mm_blendv_pd (bb, bp, az); // {ai<0?-bs:-bi,as<0?bi:bs} __m128d y = _mm_blendv_pd (bb, bp, azp); // {as<0?-bs:-bi,ai<0?bi:bs} __m128d p1 = _mm_mul_pd (az, x); + p1 = _mm_min_pd(p1,big); // no NaN __m128d p2 = _mm_mul_pd (azp, y); + p2 = _mm_min_pd(p2,big); // no NaN __m128d r = _mm_max_pd (p1, p2); return IA (IA_opacify128(r)); # elif 0 @@ -594,6 +597,7 @@ private: // we want to multiply -as,ai with {as<0?bs:bi,ai>0?bs:bi} // slightly worse than the previous one __m128d m1 = _mm_set1_pd(-0.); // {-0,-0} + __m128d big = IA::largest().simd(); __m128d aa = IA_opacify128_weak(a.simd()); // {-ai,as} __m128d ax = swap_m128d (aa); // {as,-ai} __m128d ap = _mm_xor_pd (ax, m1); // {-as,ai} @@ -605,13 +609,16 @@ private: __m128d x = _mm_blendv_pd (bbs, bbi, aa); // {ai>0?bi:bs,as<0?bi:bs} __m128d y = _mm_blendv_pd (bbi, bbs, ax); // {as<0?bs:bi,ai>0?bs:bi} __m128d p1 = _mm_mul_pd (aa, x); + p1 = _mm_min_pd(p1,big); // no NaN __m128d p2 = _mm_mul_pd (ap, y); + p2 = _mm_min_pd(p2,big); // no NaN __m128d r = _mm_max_pd (p1, p2); return IA (IA_opacify128(r)); # else // AVX version of the brutal method, same running time or slower __m128d aa = IA_opacify128_weak(a.simd()); // {-ai,as} __m128d bb = b.simd(); // {-bi,bs} + __m256d big = _mm256_set1_pd(std::numeric_limits::infinity()); __m128d m = _mm_set_sd(-0.); // {-0,+0} __m128d m1 = _mm_set1_pd(-0.); // {-0,-0} __m128d ax = swap_m128d (aa); // {as,-ai} @@ -622,7 +629,9 @@ private: __m256d Y1 = _mm256_set_m128d(bz,bz); // {bi,bs,bi,bs} __m256d Y2 = _mm256_permute_pd(Y1,5); // {bs,bi,bs,bi} __m256d Z1 = _mm256_mul_pd(X,Y1); + Z1 = _mm256_min_pd(Z1,big); // no NaN __m256d Z2 = _mm256_mul_pd(X,Y2); + Z2 = _mm256_min_pd(Z2,big); // no NaN __m256d Z = _mm256_max_pd(Z1,Z2); __m128d z1 = _mm256_castpd256_pd128(Z); __m128d z2 = _mm256_extractf128_pd(Z,1); From 6d4a431b1817c750a1d597136c771776422a6e94 Mon Sep 17 00:00:00 2001 From: Andreas Fabri Date: Fri, 25 Oct 2019 10:18:41 +0200 Subject: [PATCH 230/363] polish --- Documentation/doc/Documentation/windows.txt | 83 ++++++++++--------- .../doc/resources/1.8.13/BaseDoxyfile.in | 3 + .../doc/resources/1.8.14/BaseDoxyfile.in | 3 + .../doc/resources/1.8.4/BaseDoxyfile.in | 3 + .../examples/Triangulation_2/CMakeLists.txt | 2 + 5 files changed, 55 insertions(+), 39 deletions(-) diff --git a/Documentation/doc/Documentation/windows.txt b/Documentation/doc/Documentation/windows.txt index 9f083ed24dc..ccdaadd130b 100644 --- a/Documentation/doc/Documentation/windows.txt +++ b/Documentation/doc/Documentation/windows.txt @@ -5,8 +5,8 @@ \cgal is a library that has mandatory dependencies that must be first installed: \ref thirdpartyBoost and \ref thirdpartyMPFR. -You have two options to install mandatory dependencies: you can either use -the vcpkg library manager, which will automatically install an appropriate version of +You have two options to install dependencies: you can either use +the *Vcpkg library manager*, which will automatically install an appropriate version of these dependencies as you install \cgal, or you can install the dependencies on your own (making sure that you are using a supported version) by following their respective installation instructions. @@ -15,14 +15,11 @@ If you choose to use `vcpkg`, you might have to bootstrap and download and compile it, but from then on `vcpkg` will make your life easier. On the other hand, if you need to specify a specific version, or have already installed a certain version of a dependency and do not wish to potentially have multiple versions installed, -you will want to use the CGAL Installer. +you will want to use the \cgal Installer. -We explain the two approaches in the next sections: -
        -
      • \ref sec-installing-with-vcpkg
      • -
      • \ref install-with-installer
      • +We explain the two approaches in the next two sections. -\section sec-installing-with-vcpkg Installing CGAL with the vcpkg Library Manager +\section sec-installing-with-vcpkg Installing CGAL with the Vcpkg library manager \subsection ssec-vcpk-install-vcpk Installing vcpkg @@ -33,10 +30,18 @@ The first step is to clone or download `vcpkg` from C:\dev> git clone https://github.com/microsoft/vcpkg C:\dev> cd vcpkg C:\dev\vcpkg> .\bootstrap-vcpkg.bat +\endcode + +Note that `vcpk` even has a command to integrate installed packages directly into +Visual Studio, that is for all installed libraries it adds the paths to header files, +libraries, and dlls to project settings. + + +\code{.sh} C:\dev\vcpkg> .\vcpkg integrate install \endcode -The last step requires to run `cmd` with administrator rights. +However this step requires to run `cmd` with administrator rights. \subsection ssec-vcpk-install-cgal Installing CGAL Itself @@ -54,19 +59,19 @@ You are now ready to install \cgal: C:\dev\vcpkg> ./vcpkg.exe install cgal \endcode -This will take roughly 15 minutes and it downloads MPIR (a fork of GMP), -MPFR, all boost header files, and it will compile MPIR and MPFR, as well +This will take roughly 15 minutes and it downloads \mpir (a fork of \gmp), +\mpfr, all boost header files, and it will compile \mpir and \mpfr, as well as several boost libraries. Afterwards, you will find the include files, libraries, and dlls in the subdirectory `C:\dev\vcpkg\installed\x64-windows`. -Note that \cgal is a header-only library, and there is therefore no `lib` or `dll` files. +Note that \cgal is a header-only library, and there are therefore no `lib` or `dll` files. \subsection ssec-vcpkg-compile-example Compiling an Example Let's next compile a program that uses \cgal. The examples you find in these User Manual pages are not downloaded when you install \cgal -with the vcpkg library manager and you must download them separately from the following download page: +with the Vcpkg library manager and you must download them separately from the following download page: CGAL-\cgalReleaseNumber-examples.zip Assuming you have unzipped this file in your home directory, we will @@ -89,14 +94,14 @@ and a project file that you can use to build your program. C:\Users\Me\CGAL-5.0\examples\Triangulation_2\build> cmake-gui .. # cmake-gui is the graphical interface for cmake, which we recommend to use \endcode -When you hit the `Configure` button, you must: +When you hit the *Configure* button, you must:
          -
        • specify the `Generator` (e.g., Visual Studio 16 2019),
        • -
        • specify the `Optional Platform` (e.g., `x64` in case you want to create 64 bit binaries),
        • -
        • select `Specify toolchain file for cross compilation` (the file `vcpkg.cmake` within the directory +
        • specify the *Generator* (e.g., Visual Studio 16 2019),
        • +
        • specify the *Optional Platform* (e.g., `x64` in case you want to create 64 bit binaries),
        • +
        • select *Specify toolchain file for cross compilation* (the file `vcpkg.cmake` within the directory where you have installed `vcpkg`, e.g. `C:/dev/vcpkg/scripts/buildsystems/vcpkg.cmake`).
        -Once the configuration process is done, tick `Advanced` and `Grouped` in `cmake-gui`. +Once the configuration process is done, tick *Advanced* and *Grouped* in `cmake-gui`. You will see entries for where header files and libraries are taken from. \subsubsection sssect-vcpkg-additional-dependencies Additional Dependencies @@ -105,7 +110,7 @@ Some \cgal packages also have additional dependencies. During the configuration of the above examples, you may have observed the following message: \code{.sh} - NOTICE: a few examples require Qt and will not be compiled. + NOTICE: The example draw_triangulation_2 requires Qt and will not be compiled \endcode \cgal is a library of algorithms and data structures and as such does @@ -119,10 +124,10 @@ CMake variables and paths. Otherwise, you can also install it using `vcpkg`: Remember to specify `--triplet` or the related environment variable in case you target 64-bit applications. -When you start `cmake-gui` again and hit the `Configure` button, +When you start `cmake-gui` again and hit the *Configure* button, the CMake variables and paths concerning Qt should now be filled. -Note that not all optional dependencies are available through the `vcpkg` library manager. +Note that not all optional dependencies are available through the Vcpkg library manager. In this case, you must download and install them independently (see page \ref thirdparty for information on support versions and download links) as well as fill the missing information within the `CMake` interface until configuration is successful (no more red lines indicating @@ -136,7 +141,7 @@ the location of third-party software. \subsubsection sssect-vcpkg-compilation Compilation of an Example -Hit the `Generate` button, and you will find the file `Triangulation_2_examples.sln` +Hit the *Generate* button, and you will find the file `Triangulation_2_examples.sln` in the directory `C:\Users\Me\CGAL-5.0\examples\Triangulation_2\build`. Double-click it to open it. There is one project per `.cpp` file in the directory. Compile them all, or just the one you are interested in. @@ -147,14 +152,14 @@ Configuring and compiling your own code is practically the same as for \cgal exa if you use `cmake`. Running `cmake` (or `cmake-gui`) requires a `CMakeLists.txt` file. This file is automatically provided for all examples and demos of \cgal. For your own programs, you are advised to look at the `CMakeLists.txt` files in the example -folder of the package that you are using to learn how to specify CGAL and additional third party +folder of the package that you are using to learn how to specify \cgal and additional third party dependencies. \section install-with-installer Installing with the CGAL Installer You can download and run `CGAL-\cgalReleaseNumber``-Setup.exe` from https://www.cgal.org/download/windows.html. It is a self extracting executable that downloads the \cgal header files, and optionally the source code of the -examples and demos. Additionally, it can download precompiled versions of GMP and MPFR. +examples and demos. Additionally, it can download precompiled versions of \gmp and \mpfr. \subsection ssect-installer-boost Installing `Boost` @@ -180,13 +185,13 @@ as this will help `cmake` to find Boost. \subsection ssect-installer-install-cgal Installing CGAL Itself -Download and run `CGAL-\cgalReleaseNumber``-Setup.exe` from < -a href="https://www.cgal.org/download/windows.html">https://www.cgal.org/download/windows.html. +Download and run `CGAL-\cgalReleaseNumber``-Setup.exe` from +https://www.cgal.org/download/windows.html. It is a self extracting executable that downloads the \cgal header files, and optionally the source code of the -examples and demos. Additionally, it can download the precompiled versions of GMP and Mpfr. You must +examples and demos. Additionally, it can download the precompiled versions of \gmp and \mpfr. You must specify if yoy want the 32 or the 64 bit versions of these two libraries. -\cgal being a header-only library, there is no need to compile it. Set the environment variable `CGAL_DIR` to `C:\dev\CGAL-5.0, +\cgal being a header-only library, there is no need to compile it. Set the environment variable `CGAL_DIR` to `C:\dev\CGAL-5.0`, as this will help `cmake` to find \cgal. \subsection ssect-installer-compile-example Compiling an Example @@ -209,12 +214,12 @@ and a project file that you can use to build your program. C:\dev\CGAL-5.0\examples\Triangulation_2\build> cmake-gui .. # cmake-gui is the graphical interface for cmake, which we recommend to use \endcode -When you hit the `Configure` button you must: +When you hit the *Configure* button you must:
          -
        • Specify the `Generator`, e.g., Visual Studio 16 2019), and
        • -
        • specify an `Optional Platform` (`x64` in case you want to create 64 bit binaries).
        • +
        • Specify the *Generator*, e.g., Visual Studio 16 2019), and
        • +
        • specify an *Optional Platform* (`x64` in case you want to create 64 bit binaries).
        -Once the configuration is done, tick `Advanced` and `Grouped` in `cmake-gui. +Once the configuration is done, tick `Advanced` and `Grouped` in `cmake-gui`. You will see entries for where header files and libraries are taken from. \subsubsection ssect-installer-additional-dependencies Additional Dependencies @@ -223,7 +228,7 @@ Individual \cgal packages may also have additional dependencies. During the conf of the above examples, you may have observed the following message: \code{.sh} - NOTICE: a few examples require Qt and will not be compiled. + NOTICE: The example draw_triangulation_2 requires Qt and will not be compiled \endcode \cgal is a library of algorithms and data structures and as such does @@ -239,7 +244,7 @@ Download and install the Qt library for open source development package for your as this will help `cmake` to find Qt.
      • Add the bin directory of Qt, e.g. add `C:\dev\Qt\Qt5.13.1\msvcXXXX_YY\bin` to `PATH`, where `XXXX_YY` is something like `vc2017_64`. To avoid any conflict with another dll with the same name from another folder, add this path as the first in the list.
      • -
      • When you start `cmake-gui` again and hit the `Configure` button, +
      • When you start `cmake-gui` again and hit the *Configure* button, the CMake variables concerning Qt should now be filled.
      @@ -256,7 +261,7 @@ the location of third-party software. \subsubsection sssect-installer-compilation Compilation of an Example -Hit the `Generate` button, and you will find the file `Triangulation_2_examples.sln` +Hit the *Generate* button, and you will find the file `Triangulation_2_examples.sln` in the directory `C:\dev\CGAL-5.0\examples\Triangulation_2\build`. Double click in order to open it. You will see one project per `.cpp` file. Compile them all or just the one you are interested in. @@ -267,12 +272,12 @@ Configuring and compiling your own code is practically the same as for \cgal exa if you use `cmake`. Running `cmake` (or `cmake-gui`) requires a `CMakeLists.txt` file. This file is automatically provided for all examples and demos of \cgal. For your own programs, you are advised to look at the `CMakeLists.txt` files in the example -folder of the package that you are using to learn how to specify CGAL and additional third party +folder of the package that you are using to learn how to specify \cgal and additional third party dependencies. -\section install-with-tarball Installing from the tarball +\section install-with-tarball Installing from the Source Archive -Instead of the installer you can also download release tarballs. The sole difference with the \cgal Installer -procedure is that the installer also downloads precompiled GMP and MPFR libraries. +Instead of the installer you can also download release tarballs. The sole difference +is that the installer also downloads precompiled \gmp and \mpfr libraries. */ diff --git a/Documentation/doc/resources/1.8.13/BaseDoxyfile.in b/Documentation/doc/resources/1.8.13/BaseDoxyfile.in index 34d9e359a51..706be1b14ca 100644 --- a/Documentation/doc/resources/1.8.13/BaseDoxyfile.in +++ b/Documentation/doc/resources/1.8.13/BaseDoxyfile.in @@ -233,6 +233,9 @@ ALIASES = "sc{1}=\1\1\1" ALIASES += "cgal=\sc{%CGAL}" ALIASES += "protocgal=\sc{C++gal}" ALIASES += "plageo=\sc{Plageo}" +ALIASES += "gmp=\sc{GMP}" +ALIASES += "mpir=\sc{MPIR}" +ALIASES += "mpfr=\sc{MPFR}" ALIASES += "stl=\sc{STL}" ALIASES += "leda=\sc{LEDA}" ALIASES += "gcc=\sc{GCC}" diff --git a/Triangulation_2/examples/Triangulation_2/CMakeLists.txt b/Triangulation_2/examples/Triangulation_2/CMakeLists.txt index 4911f1d9872..fe3f5a7f849 100644 --- a/Triangulation_2/examples/Triangulation_2/CMakeLists.txt +++ b/Triangulation_2/examples/Triangulation_2/CMakeLists.txt @@ -31,6 +31,8 @@ if ( CGAL_FOUND ) if(CGAL_Qt5_FOUND) target_link_libraries(draw_triangulation_2 PUBLIC CGAL::CGAL_Qt5) + else() + message(STATUS "NOTICE: The example draw_triangulation_2 requires Qt and will not be compiled.") endif() else() From c80abc7711677d1ed8a018feb869f35bbf9932c9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mael=20Rouxel-Labb=C3=A9?= Date: Fri, 25 Oct 2019 10:20:30 +0200 Subject: [PATCH 231/363] Make parabola sampling a parameter of the sampling function The current API is not so useful because it is is not adapted to other scales --- Apollonius_graph_2/include/CGAL/Parabola_segment_2.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Apollonius_graph_2/include/CGAL/Parabola_segment_2.h b/Apollonius_graph_2/include/CGAL/Parabola_segment_2.h index 0c2f9568b54..2355f075c74 100644 --- a/Apollonius_graph_2/include/CGAL/Parabola_segment_2.h +++ b/Apollonius_graph_2/include/CGAL/Parabola_segment_2.h @@ -75,9 +75,9 @@ public: return int(CGAL::sqrt(CGAL::to_double(tt) / 2)); } - void generate_points(std::vector& p) const + void generate_points(std::vector& p, + const FT STEP = FT(2)) const { - const FT STEP(2); FT s0, s1; s0 = t(p1); From b0916bedfe922b8db2b26658e8575369225cfad5 Mon Sep 17 00:00:00 2001 From: Andreas Fabri Date: Fri, 25 Oct 2019 10:28:22 +0200 Subject: [PATCH 232/363] polish --- Documentation/doc/Documentation/windows.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Documentation/doc/Documentation/windows.txt b/Documentation/doc/Documentation/windows.txt index ccdaadd130b..81ef32a3a7f 100644 --- a/Documentation/doc/Documentation/windows.txt +++ b/Documentation/doc/Documentation/windows.txt @@ -161,7 +161,7 @@ You can download and run `CGAL-\cgalReleaseNumber``-Setup.exe` from https://www. It is a self extracting executable that downloads the \cgal header files, and optionally the source code of the examples and demos. Additionally, it can download precompiled versions of \gmp and \mpfr. -\subsection ssect-installer-boost Installing `Boost` +\subsection ssect-installer-boost Installing Boost Binary versions of `Boost` are available on SourceForge. From d4b0eae3a4f03e8b21866001462431ff90d43096 Mon Sep 17 00:00:00 2001 From: Andreas Fabri Date: Fri, 25 Oct 2019 11:14:03 +0200 Subject: [PATCH 233/363] polish --- Documentation/doc/Documentation/windows.txt | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/Documentation/doc/Documentation/windows.txt b/Documentation/doc/Documentation/windows.txt index 81ef32a3a7f..e37b61415db 100644 --- a/Documentation/doc/Documentation/windows.txt +++ b/Documentation/doc/Documentation/windows.txt @@ -5,7 +5,7 @@ \cgal is a library that has mandatory dependencies that must be first installed: \ref thirdpartyBoost and \ref thirdpartyMPFR. -You have two options to install dependencies: you can either use +You have two options to install \cgal and its dependencies: you can either use the *Vcpkg library manager*, which will automatically install an appropriate version of these dependencies as you install \cgal, or you can install the dependencies on your own (making sure that you are using a supported version) by following their respective @@ -21,7 +21,7 @@ We explain the two approaches in the next two sections. \section sec-installing-with-vcpkg Installing CGAL with the Vcpkg library manager -\subsection ssec-vcpk-install-vcpk Installing vcpkg +\subsection ssec-vcpk-install-vcpk Installing Vcpkg The first step is to clone or download `vcpkg` from https://github.com/microsoft/vcpkg. @@ -41,9 +41,9 @@ libraries, and dlls to project settings. C:\dev\vcpkg> .\vcpkg integrate install \endcode -However this step requires to run `cmd` with administrator rights. +However, this step requires to run `cmd` with administrator rights. -\subsection ssec-vcpk-install-cgal Installing CGAL Itself +\subsection ssec-vcpk-install-cgal Installing with Vcpkg By default `vcpkg` installs for 32 bit binaries and will use the latest version of Visual C++ installed on your machine. If you develop 64 bit software you must From 8251bb9bac4ad63fdd45ee8c0357c869544fb18e Mon Sep 17 00:00:00 2001 From: Maxime Gimeno Date: Fri, 25 Oct 2019 11:21:05 +0200 Subject: [PATCH 234/363] fix after review --- Distance_3/include/CGAL/squared_distance_3_2.h | 9 ++++----- Distance_3/test/Distance_3/test_distance_3.cpp | 4 ++-- 2 files changed, 6 insertions(+), 7 deletions(-) diff --git a/Distance_3/include/CGAL/squared_distance_3_2.h b/Distance_3/include/CGAL/squared_distance_3_2.h index 26972588ba0..bf85329715c 100644 --- a/Distance_3/include/CGAL/squared_distance_3_2.h +++ b/Distance_3/include/CGAL/squared_distance_3_2.h @@ -404,11 +404,10 @@ inline typename K::FT squared_distance(const Plane_3 & p1, const Plane_3 & p2) { - K k;; - if( k.compute_squared_length_3_object()( - k.construct_cross_product_vector_3_object()(p1.orthogonal_vector(), - p2.orthogonal_vector())) - != 0) + K k; + typename K::Construct_orthogonal_vector_3 ortho_vec = + k.construct_orthogonal_vector_3_object(); + if (!internal::is_null(internal::wcross(ortho_vec(p1), ortho_vec(p2), k), k)) return typename K::FT(0); else return internal::squared_distance(p1.point(), p2, k); diff --git a/Distance_3/test/Distance_3/test_distance_3.cpp b/Distance_3/test/Distance_3/test_distance_3.cpp index 38abdd0b828..1413169832b 100644 --- a/Distance_3/test/Distance_3/test_distance_3.cpp +++ b/Distance_3/test/Distance_3/test_distance_3.cpp @@ -224,10 +224,10 @@ struct Test { void Pl_Pl() { std::cout << "Plane - Plane\n"; - Pl p1(12, 1, 4, 0); + Pl p1(0, 1, 0, 0); typename K::Vector_3 v = -p1.orthogonal_vector(); v /= CGAL::sqrt(v.squared_length()); - Pl p2 = Pl(p1.point()+6*v, -p1.orthogonal_vector()); + Pl p2 = Pl(0,-1,0,6); check_squared_distance (p1,p2, 36); check_squared_distance (Pl(-2, 1, 1, 0), Pl(2, 1, 3, 0), 0); } From 001c74c8df5ace80c901c2c990eb7e528e3615a1 Mon Sep 17 00:00:00 2001 From: Andreas Fabri Date: Fri, 25 Oct 2019 12:52:38 +0200 Subject: [PATCH 235/363] Integrate Maxime's comments --- Documentation/doc/Documentation/windows.txt | 36 ++++++++++----------- 1 file changed, 17 insertions(+), 19 deletions(-) diff --git a/Documentation/doc/Documentation/windows.txt b/Documentation/doc/Documentation/windows.txt index e37b61415db..3df201b6470 100644 --- a/Documentation/doc/Documentation/windows.txt +++ b/Documentation/doc/Documentation/windows.txt @@ -32,17 +32,6 @@ The first step is to clone or download `vcpkg` from C:\dev\vcpkg> .\bootstrap-vcpkg.bat \endcode -Note that `vcpk` even has a command to integrate installed packages directly into -Visual Studio, that is for all installed libraries it adds the paths to header files, -libraries, and dlls to project settings. - - -\code{.sh} - C:\dev\vcpkg> .\vcpkg integrate install -\endcode - -However, this step requires to run `cmd` with administrator rights. - \subsection ssec-vcpk-install-cgal Installing with Vcpkg By default `vcpkg` installs for 32 bit binaries and will use the latest version of Visual C++ @@ -59,29 +48,30 @@ You are now ready to install \cgal: C:\dev\vcpkg> ./vcpkg.exe install cgal \endcode -This will take roughly 15 minutes and it downloads \mpir (a fork of \gmp), +This will take several minutes as it downloads \mpir (a fork of \gmp), \mpfr, all boost header files, and it will compile \mpir and \mpfr, as well as several boost libraries. Afterwards, you will find the include files, libraries, and dlls in the subdirectory `C:\dev\vcpkg\installed\x64-windows`. -Note that \cgal is a header-only library, and there are therefore no `lib` or `dll` files. +Note that \cgal is a header-only library, and there are therefore no `lib` or `dll` files for \cgal. + \subsection ssec-vcpkg-compile-example Compiling an Example -Let's next compile a program that uses \cgal. +In this section we show how to compile a program that uses \cgal. The examples you find in these User Manual pages are not downloaded when you install \cgal -with the Vcpkg library manager and you must download them separately from the following download page: +with the Vcpkg library manager. You must download them separately from the following download page: CGAL-\cgalReleaseNumber-examples.zip -Assuming you have unzipped this file in your home directory, we will -next compile an example from the 2D Triangulation package. +Assuming you have unzipped this file in your home directory `C:\Users\Me`, +we will next compile an example from the 2D Triangulation package. \subsubsection sssec-vcpkg-configuration-example Configuring of an Example Before building anything using \cgal, you have to choose the compiler/linker, set compiler and linker flags, specify which third-party libraries you want to use and where they can be found. -Gathering all this information is called *configuration* and we use CMake as configuration tool +Gathering all this information is called *configuration* and we use *CMake* as configuration tool (see Section \ref seccmake for more information on supported versions and where to download it). The end of the process is marked by the generation of a Visual \cpp solution @@ -124,7 +114,15 @@ CMake variables and paths. Otherwise, you can also install it using `vcpkg`: Remember to specify `--triplet` or the related environment variable in case you target 64-bit applications. -When you start `cmake-gui` again and hit the *Configure* button, +As Qt5 is modular and as the \cgal examples and demos use only some of these modules +you can save download and compilation time by specifying an *installation option*: + +\code{.sh} + C:\dev\vcpkg> ./vcpkg.exe install cgal [qt] +\endcode + + +In both cases, when you start `cmake-gui` again and hit the *Configure* button, the CMake variables and paths concerning Qt should now be filled. Note that not all optional dependencies are available through the Vcpkg library manager. From 51fe37f49b5b64a28a9f210b12c954b357aa1b35 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mael=20Rouxel-Labb=C3=A9?= Date: Fri, 25 Oct 2019 12:31:53 +0200 Subject: [PATCH 236/363] Revert "pass on the doc" This reverts commit 76cc4a6863934e3fa7ad332f2aec7dcbffafcec6. Actually don't want to remove that information --- .../advanced/Configuration_variables.txt | 348 +++++++++++++++++ .../Documentation/advanced/Installation.txt | 357 ++++++++++++++++++ .../doc/Documentation/advanced/advanced.txt | 8 + 3 files changed, 713 insertions(+) create mode 100644 Documentation/doc/Documentation/advanced/Configuration_variables.txt create mode 100644 Documentation/doc/Documentation/advanced/Installation.txt create mode 100644 Documentation/doc/Documentation/advanced/advanced.txt diff --git a/Documentation/doc/Documentation/advanced/Configuration_variables.txt b/Documentation/doc/Documentation/advanced/Configuration_variables.txt new file mode 100644 index 00000000000..343a513afb2 --- /dev/null +++ b/Documentation/doc/Documentation/advanced/Configuration_variables.txt @@ -0,0 +1,348 @@ +/*! + +\page configurationvariables Summary of %CGAL's Configuration Variables +\cgalAutoToc + +\section installation_summary Summary of CGAL's Configuration Variables + +Most configuration variables are not environment variables but +CMake variables. They are given in the command line to CMake +via the `-D` option, or passed from the interactive interface +of `cmake-gui`. Unless indicated differently, all the variables +summarized below are CMake variables. + +\subsection installation_component_selection Component Selection + +The following boolean variables indicate which \cgal components to +configure and build. Their values can be ON or OFF. + + +| Variable | %Default Value | +| :------- | :--------------- | +| `WITH_examples` | OFF | +| `WITH_demos` | OFF | +| `WITH_CGAL_Core` | ON | +| `WITH_CGAL_Qt5` | ON | +| `WITH_CGAL_ImageIO` | ON | + +\subsection installation_flags Compiler and Linker Flags + +The following variables specify compiler and linker flags. Each variable holds a +space-separated list of command-line switches for the compiler and linker and +their default values are automatically defined by CMake based on the target platform. + +Have in mind that these variables specify a list of flags, not just one +single flag. If you provide your own definition for a variable, you will entirely override +the list of flags chosen by CMake for that particular variable. + +The variables that correspond to both debug and release builds are always +used in conjunction with those for the specific build type. + + +| Program | Both Debug and Release | Release Only | Debug Only | +| :------ | :---------------------- | :------------- | :----------- | +| C++ Compiler | `CMAKE_CXX_FLAGS` | `CMAKE_CXX_FLAGS_RELEASE` | `CMAKE_CXX_FLAGS_DEBUG` | +| Linker (shared libs) | `CMAKE_SHARED_LINKER_FLAGS` | `CMAKE_SHARED_LINKER_FLAGS_RELEASE` | `CMAKE_SHARED_LINKER_FLAGS_DEBUG` | +| Linker (static libs) | `CMAKE_MODULE_LINKER_FLAGS` | `CMAKE_MODULE_LINKER_FLAGS_RELEASE` | `CMAKE_MODULE_LINKER_FLAGS_DEBUG` | +| Linker (programs) | `CMAKE_EXE_LINKER_FLAGS` | `CMAKE_EXE_LINKER_FLAGS_RELEASE` | `CMAKE_EXE_LINKER_FLAGS_DEBUG`| + + +\subsection installation_additional_flags Additional Compiler and Linker Flags + +The following variables can be used to add flags without overriding the ones +defined by cmake. + + +| Program | Both Debug and Release | Release Only | Debug Only | +| :------ | :---------------------- | :------------- | :----------- | +| C++ Compiler | `CGAL_CXX_FLAGS` | `CGAL_CXX_FLAGS_RELEASE` | `CGAL_CXX_FLAGS_DEBUG` | +| Linker (shared libs) | `CGAL_SHARED_LINKER_FLAGS` | `CGAL_SHARED_LINKER_FLAGS_RELEASE` | `CGAL_SHARED_LINKER_FLAGS_DEBUG` | +| Linker (static libs) | `CGAL_MODULE_LINKER_FLAGS` | `CGAL_MODULE_LINKER_FLAGS_RELEASE` | `CGAL_MODULE_LINKER_FLAGS_DEBUG` | +| Linker (programs) | `CGAL_EXE_LINKER_FLAGS` | `CGAL_EXE_LINKER_FLAGS_RELEASE` | `CGAL_EXE_LINKER_FLAGS_DEBUG` | + +\subsection installation_misc Miscellaneous Variables + +Note that the default build type is `Debug`, which should only be used to debug +and will serverly limit performances. + +| Variable | Description | Type | %Default Value | +| :- | :- | :- | :- | +| `CMAKE_BUILD_TYPE` | Indicates type of build. Possible values are 'Debug' or 'Release' | CMake | | +| `CMAKE_INSTALL_PREFIX`| Installation directory path | CMake | Debug | +| `CMAKE_C_COMPILER` | Full-path to the executable corresponding to the C compiler to use. | CMake | platform-dependent | +| `CMAKE_CXX_COMPILER` | Full-path to the executable corresponding to the C++ compiler to use. | CMake | platform-dependent | +| `CXX` | Idem | Environment | Idem | +| `BUILD_SHARED_LIBS` | Whether to build shared or static libraries. | CMake | TRUE | + +\subsection installation_variables_building Variables Used Only When Building Programs (Such as Demos or Examples) + + +| Variable | Description | Type | %Default Value | +| :- | :- | :- | :- | +| `CGAL_DIR` | Full-path to the binary directory where \cgal was configured |Either CMake or Environment | none | + + +\subsection installation_variables_third_party Variables Providing Information About 3rd-Party Libraries +\anchor sec3partysoftwareconfig + +The following variables provide information about the availability and +location of the 3rd party libraries used by \cgal. CMake automatically +searches for dependencies so you need to specify these variables if +CMake was unable to locate something. This is indicated by a value ending in +`NOTFOUND`. + +Since 3rd-party libraries are system wide, many of the CMake variables listed below can alternatively +be given as similarly-named environment variables instead. Keep in mind that you must provide one or the +other but never both. + +\subsection installation_boost Boost Libraries + +In most cases, if \sc{Boost} is not automatically found, setting the `BOOST_ROOT` +variable is enough. If it is not, you can specify the header and library +directories individually. You can also provide the full pathname to a specific compiled library +if it cannot be found in the library directory or its name is non-standard. + +By default, when \sc{Boost} binary libraries are needed, the shared versions +are used if present. You can set the variable +`CGAL_Boost_USE_STATIC_LIBS` to `ON` if you want to link +with static versions explicitly. + +On Windows, if you link with \sc{Boost} shared libraries, you must ensure that +the `.dll` files are found by the dynamic linker, at run time. +For example, you can add the path to the \sc{Boost} `.dll` to the +`PATH` environment variable. + +| Variable | Description | Type | +| :- | :- | :- | +| `BOOST_ROOT`\cgalFootnote{The environment variable can be spelled either `BOOST_ROOT` or `BOOSTROOT`} | Root directory of your \sc{Boost} installation | Either CMake or Environment | +| `Boost_INCLUDE_DIR` | Directory containing the `boost/version.hpp` file | CMake | +| `BOOST_INCLUDEDIR` | Idem | Environment | +| `Boost_LIBRARY_DIRS` | Directory containing the compiled \sc{Boost} libraries | CMake | +| `BOOST_LIBRARYDIR` | Idem | Environment | +| `Boost_(xyz)_LIBRARY_RELEASE` | Full pathname to a release build of the compiled 'xyz' \sc{Boost} library | CMake | +| `Boost_(xyz)_LIBRARY_DEBUG` | Full pathname to a debug build of the compiled 'xyz' \sc{Boost} library | CMake | + + +\subsection installation_gmp GMP and MPFR Libraries + +Under Windows, auto-linking is used, so only the directory +containing the libraries is needed and you would specify `GMP|MPFR_LIBRARY_DIR` rather than +`GMP|MPFR_LIBRARIES`. On the other hand, under Linux the actual library filename is needed. +Thus you would specify `GMP|MPFR_LIBRARIES`. In no case you need to specify both. + +\cgal uses both \sc{Gmp} and \sc{Mpfr} so both need to be supported. If either of them is unavailable the +usage of \sc{Gmp} and of \sc{Mpfr} will be disabled. + + +| Variable | Description | Type | +| :- | :- | :- | +| `CGAL_DISABLE_GMP` | Indicates whether to search and use \sc{Gmp}/\sc{Mpfr} or not | CMake | +| `GMP_DIR` | Directory of \sc{Gmp} default installation | Environment | +| `GMP_INCLUDE_DIR` | Directory containing the `gmp.h` file | CMake | +| `GMP_INC_DIR` | Idem | Environment | +| `GMP_LIBRARIES_DIR` | Directory containing the compiled \sc{Gmp} library | CMake | +| `GMP_LIB_DIR` | Idem | Environment | +| `GMP_LIBRARIES` | Full pathname of the compiled \sc{Gmp} library | CMake | +| `MPFR_INCLUDE_DIR` | Directory containing the `mpfr.h` file | CMake | +| `MPFR_INC_DIR` | Idem | Environment | +| `MPFR_LIBRARIES_DIR` | Directory containing the compiled \sc{Mpfr} library | CMake | +| `MPFR_LIB_DIR` | Idem | Environment | +| `MPFR_LIBRARIES` | Full pathname of the compiled \sc{Mpfr} library | CMake | + + + +Under Linux, the \sc{Gmpxx} is also searched for, and you may specify the following variables: + + +| Variable | Description | Type | +| :- | :- | :- | +| `GMPXX_DIR` | Directory of \sc{gmpxx} default installation | Environment | +| `GMPXX_INCLUDE_DIR` | Directory containing the `gmpxx.h` file | CMake | +| `GMPXX_LIBRARIES` | Full pathname of the compiled \sc{Gmpxx} library | CMake | + + + +\subsection installation_qt5 Qt5 Library + +You must set the cmake or environment variable `Qt5_DIR` to point to the path +to the directory containing the file `Qt5Config.cmake` created by your \sc{Qt}5 installation. If you are +using the open source edition it should be `/qt-everywhere-opensource-src-/qtbase/lib/cmake/Qt5`. + +\subsection installation_leda LEDA Library + +When the \leda libraries are not automatically found, yet they are installed on the system +with base names 'leda' and 'ledaD' (for the release and debug versions resp.), it might +be sufficient to just indicate the library directory via the `LEDA_LIBRARY_DIRS` variable. +If that doesn't work because, for example, the names are different, you can provide the full pathnames of each variant +via `LEDA_LIBRARY_RELEASE` and `LEDA_LIBRARY_DEBUG`. + +The variables specifying definitions and flags can be left undefined if they are not needed by LEDA. + + +| Variable | Description | Type | +| :- | :- | :- | +| `WITH_LEDA` | Indicates whether to search and use \leda or not | CMake | +| `LEDA_DIR` | Directory of \sc{LEDA} default installation | Environment | +| `LEDA_INCLUDE_DIR` | Directory containing the file `LEDA/system/basic.h` | CMake | +| `LEDA_LIBRARIES` | Directory containing the compiled \leda libraries | CMake | +| `LEDA_INC_DIR` | Directory containing the file `LEDA/system/basic.h` | Environment | +| `LEDA_LIB_DIR` | Directory containing the compiled \leda libraries | Environment | +| `LEDA_LIBRARY_RELEASE` | Full pathname to a release build of the \leda library | CMake | +| `LEDA_LIBRARY_DEBUG` | Full pathname to a debug build of the \leda library | CMake | +| `LEDA_DEFINITIONS` | Preprocessor definitions | CMake | +| `LEDA_CXX_FLAGS` | Compiler flags | CMake | +| `LEDA_LINKER_FLAGS` | Linker flags | CMake | + + +\subsection installation_mpfi MPFI Library + +\cgal provides a number type based on this library, but the \cgal library +itself does not depend on \sc{Mpfi}. This means that this library must be +configured when compiling an application that uses the above number type. + +When \sc{Mpfi} files are not on the standard path, the locations of the headers +and library files must be specified by using environment variables. + + +| Variable | Description | Type | +| :- | :- | :- | +| `MPFI_DIR` |Directory of \sc{MPFI} default installation | Environment | +| `MPFI_INCLUDE_DIR` | Directory containing the `mpfi.h` file | CMake | +| `MPFI_INC_DIR` | Idem | Environment | +| `MPFI_LIBRARIES_DIR` | Directory containing the compiled \sc{Mpfi} library | CMake | +| `MPFI_LIB_DIR` | Idem | Environment | +| `MPFI_LIBRARIES` | Full pathname of the compiled \sc{Mpfi} library | CMake | + + + +\subsection installation_rs RS and RS3 Library + +As said before, only the \cgal univariate algebraic kernel depends on the +library Rs. As the algebraic kernel is not compiled as a part of the \cgal +library, this library is not detected nor configured at installation time. + +CMake will try to find Rs in the standard header and library +directories. When it is not automatically detected, the locations of the +headers and library files must be specified using environment variables. + +Rs needs \sc{Gmp} 4.2 or later and \sc{Mpfi} 1.3.4 or later. The variables +related to the latter library may also need to be defined. + + +| Variable | Description | Type | +| :- | :- | :- | +| `RS_DIR` | Directory of \sc{Rs} default installation | Environment | +| `RS_INCLUDE_DIR` | Directory containing the `rs_exports.h` file | CMake | +| `RS_INC_DIR` | Idem | Environment | +| `RS_LIBRARIES_DIR` | Directory containing the compiled \sc{Rs} library | CMake | +| `RS_LIB_DIR` | Idem | Environment | +| `RS_LIBRARIES` | Full pathname of the compiled \sc{Rs} library | CMake | + +Similar variables exist for \sc{Rs3}. + +| Variable | Description | Type | +| :- | :- | :- +| `RS3_DIR` | Directory of \sc{Rs3} default installation | Environment | +| `RS3_INCLUDE_DIR` | Directory containing the file `rs3_fncts.h` file | CMake | +| `RS3_INC_DIR` | Idem | Environment | +| `RS3_LIBRARIES_DIR` | Directory containing the compiled \sc{Rs3} library | CMake | +| `RS3_LIB_DIR` | Idem | Environment | +| `RS3_LIBRARIES` | Full pathname of the compiled \sc{Rs3} library | CMake | + + +\subsection installation_ntl NTL Library + +Some polynomial computations in \cgal's algebraic kernel +are speed up when \sc{Ntl} is available. +As the algebraic kernel is not compiled as a part of the \cgal +library, this library is not detected nor configured at installation time. + +CMake will try to find \sc{Ntl} in the standard header and library +directories. When it is not automatically detected, the locations of the +headers and library files must be specified using environment variables. + +| Variable | Description | Type | +| :- | :- | :- | +| `NTL_DIR` | Directory of \sc{NTL} default installation | Environment | +| `NTL_INCLUDE_DIR` | Directory containing the `NTL/ZZX.h` file | CMake | +| `NTL_INC_DIR` | Idem | Environment | +| `NTL_LIBRARIES_DIR` | Directory containing the compiled \sc{Ntl} library | CMake | +| `NTL_LIB_DIR` | Idem | Environment | +| `NTL_LIBRARIES` | Full pathname of the compiled \sc{Ntl} library | CMake | + +\subsection installation_eigen Eigen Library + +\sc{Eigen} is a header-only template library. +Only the directory containing the header files of \sc{Eigen} 3.1 (or greater) is needed. + + +| Variable | Description | Type | +| :- | :- | :- | +| `EIGEN3_INCLUDE_DIR` | Directory containing the file `signature_of_eigen3_matrix_library` | CMake | +| `EIGEN3_INC_DIR` | Idem | Environment | + +\subsection installation_esbtl ESBTL Library + +One skin surface example requires the \sc{Esbtl} library in order to read \sc{Pdb} files. + +If \sc{Esbtl} is not automatically found, setting the `ESBTL_INC_DIR` +environment variable is sufficient. + + +| Variable | Description | Type | +| :- | :- | :- | +| `ESBTL_DIR` | Directory of \sc{ESBTL} default installation | Environment | +| `ESBTL_INC_DIR` | Directory containing the `ESBTL/default.h` file | Environment | +| `ESBTL_INCLUDE_DIR` | Directory containing the `ESBTL/default.h` file | CMake | + +\subsection installation_tbb TBB Library + +If \sc{Tbb} is not automatically found, the user must set the `TBB_ROOT` +environment variable. The environment variable `TBB_ARCH_PLATFORM=/` must be set. +`` is `ia32` or `intel64`. `` describes the Linux kernel, gcc version or Visual Studio version +used. It should be set to what is used in `$TBB_ROOT/lib/`. + +For windows users, the folder `TBB_ROOT/bin//` should be added to the `PATH` variable. + +Note that the variables in the table below are being used. + +| Variable | Description | Type | +| :- | :- | :- | +| `TBB_ROOT` | Directory of \sc{Tbb} default installation | Environment | +| `TBB_INCLUDE_DIRS` | Directory containing the `tbb/tbb.h` file | CMake | +| `TBB_LIBRARY_DIRS` | Directory(ies) containing the compiled TBB libraries | CMake | +| `TBB_LIBRARIES` | Full pathnames of the compiled TBB libraries (both release and debug versions, using "optimized" and "debug" CMake keywords). Note that if the debug versions are not found, the release versions will be used instead for the debug mode. | CMake | +| `TBB_RELEASE_LIBRARY` | Full pathname of the compiled TBB release library | CMake | +| `TBB_MALLOC_RELEASE_LIBRARY` | Full pathname of the compiled TBB release malloc library | CMake | +| `TBB_DEBUG_LIBRARY` | Full pathname of the compiled TBB debug library | CMake | +| `TBB_MALLOC_DEBUG_LIBRARY` | Full pathname of the compiled TBB debug malloc library | CMake | +| `TBB_MALLOCPROXY_DEBUG_LIBRARY` | Full pathname of the compiled TBB debug malloc_proxy library (optional) | CMake | +| `TBB_MALLOCPROXY_RELEASE_LIBRARY` | Full pathname of the compiled TBB release malloc_proxy library (optional) | CMake | + +\section installation_compiler_workarounds Compiler Workarounds + +A number of boolean flags are used to workaround compiler bugs and +limitations. They all start with the prefix `CGAL_CFG`. These +flags are used to work around compiler bugs and limitations. For +example, the flag `CGAL_CFG_NO_CPP0X_LONG_LONG` denotes +that the compiler does not know the type `long long`. + +For each installation a file +is defined, with the correct +settings of all flags. This file is generated automatically by CMake, +and it is located in the `include` directory of where you run +CMake. For an in-source configuration this means +`CGAL-\cgalReleaseNumber``/include`. + +The test programs used to generate the `compiler_config.h` +file can be found in `config/testfiles`. +Both +`compiler_config.h` and the test programs contain a short +description of the problem. In case of trouble with one of the +`CGAL_CFG` flags, it is a good idea to take a look at it. + +The file `CGAL/compiler_config.h` is included from +``. +which is included by all \cgal header files. + +*/ diff --git a/Documentation/doc/Documentation/advanced/Installation.txt b/Documentation/doc/Documentation/advanced/Installation.txt new file mode 100644 index 00000000000..cf6d2679b62 --- /dev/null +++ b/Documentation/doc/Documentation/advanced/Installation.txt @@ -0,0 +1,357 @@ +/*! +\page installation Installation +\cgalAutoToc + +Since \cgal version 5.0, \cgal is header-only be default, which means +that there is no need to compile and install anything before it can be used. +However, the dependencies of \cgal might still need to be installed. + +This page is a step-by-step description of how to configure, build, and install \cgal +in case you do not wish to use the - now enabled by default - header-only mode of \cgal. +It is also possible to install \cgal using package managers on some operating systems, +see Section \ref secspecificinstall. + +\section installation_idealworld Quick Installation + +Ideally, compiling and installing \cgal, as well as compiling some examples shipped by \cgal is as simple as: + + cd $HOME/CGAL-\cgalReleaseNumber + cmake -DCMAKE_BUILD_TYPE=Release . # configure CGAL + make # build CGAL + make install # install CGAL + cd examples/Triangulation_2 # go to an example directory + cmake -DCGAL_DIR=$HOME/CGAL-\cgalReleaseNumber -DCMAKE_BUILD_TYPE=Release . # configure the examples + make # build the examples + +In a less ideal world, you might have to install some required tools and third-party libraries. +This is what this page is about. + +\section installation_configwithcmake Configuring CGAL with CMake + +Before building \cgal, or anything using \cgal, you have to choose the compiler/linker, +set compiler and linker flags, specify which +third-party libraries you want to use and where they can be found, and +which \cgal libraries you want to build. Gathering +all this information is called configuration. +The end of the process is marked by the generation of a makefile or a +Visual \cpp solution and project file that you can use to build \cgal. + +CMake maintains configuration parameters in so-called cmake variables. Some of the CMake +variables represent user choices, such as `CMAKE_BUILD_TYPE`, while others +indicate the details of a third-party library, such as `Boost_INCLUDE_DIR` or which compiler flags to use, +such as `CMAKE_CXX_FLAGS`. + +The next sections first present the CMake variables related to \cgal, followed by more generic variables, +and finally the configuration and build processes. + +\subsection seclibraries CGAL Libraries + +\cgal is split into four libraries. During configuration, you can select the libraries that +you would like to build by setting a CMake variable of the form WITH_. By default all +are switched `ON`. All activated libraries are to be built after configuration. + +Note that some libraries have specific dependencies in addition to the essential ones. See the page +\ref secessential3rdpartysoftware for more information. + +| Library | CMake Variable | Functionality | Dependencies | +| :-------- | :------------- | :------------ | :----------- | +| `%CGAL` | none | Main library | \sc{Gmp}, \sc{Mpfr}, \sc{Boost} (headers) | +| `CGAL_Core` | `WITH_CGAL_Core` | The %CORE library for algebraic numbers.\cgalFootnote{CGAL_Core is not part of \cgal, but a custom version of the \sc{Core} library distributed by \cgal for the user convenience and it has it's own license.} | \sc{Gmp} and \sc{Mpfr} | +| `CGAL_ImageIO` | `WITH_CGAL_ImageIO` | Utilities to read and write image files | \sc{zlib}, \sc{Vtk} (optional) | +| `CGAL_Qt5` | `WITH_CGAL_Qt5` | `QGraphicsView` support for \sc{Qt}5-based demos | \sc{Qt}5 | + +Shared libraries, also called dynamic-link libraries, are built by default +(`.dll` on Windows, `.so` on Linux, `.dylib` on MacOS). You +can choose to produce static libraries instead, by setting the CMake +variable `BUILD_SHARED_LIBS` to `FALSE`. + +\subsection installation_examples CGAL Examples and Demos + +\cgal is distributed with a large collection of examples and demos. By default, these are not configured along with +the \cgal libraries, unless you set the variables `WITH_examples=ON` and/or `WITH_demos=ON`. +Additionally, even when configured with \cgal, they are not automatically built along with the libraries. +You must build the `examples` or `demos` targets (or IDE projects) explicitly. + +If you do not plan to compile any demos, you may skip some of the dependencies (such as \sc{Qt}), +as the corresponding \cgal-libraries will not be used. Note, however, that your own demos +might need these \cgal-libraries and thus their dependencies. See the page +\ref secessential3rdpartysoftware for more information. + +\subsection installation_debugrelease Debug vs. Release + +The CMake variable `CMAKE_BUILD_TYPE` indicates how to build the libraries. +It accepts the values `Debug` or `Release`. Note that the default value is `Debug`, since it is +default value in `CMake`. If you do not plan on debugging, it is important to set the variable +to `Release` for performance reasons. + +This is however not an issue for solution/project files, since the user selects the build type +from within the IDE in this environment. + +\subsection installation_miscvariables Other CMake Variables + +There are many more variables that can be used during configuration. The most important ones are: +
        +
      • `CMAKE_INSTALL_PREFIX=` installation directory [/usr/local]
      • +
      • `CMAKE_BUILD_TYPE=` build type [Release]
      • +
      • `BUILD_SHARED_LIBS=` shared or static libraries [TRUE]
      • +
      • `CMAKE_C_COMPILER=` C compiler [gcc]
      • +
      • `CMAKE_CXX_COMPILER=` C++ compiler [g++]
      • +
      + +In case you want to add additional compiler and linker flags, you can use +
        +
      • `CGAL_CXX_FLAGS` additional compiler flags
      • +
      • `CGAL_MODULE_LINKER_FLAGS` add. linker flags (static libraries)
      • +
      • `CGAL_SHARED_LINKER_FLAGS` add. linker flags (shared libraries)
      • +
      • `CGAL_EXE_LINKER_FLAGS` add. linker flags (executables)
      • +
      + +Variants with the additional suffix "_DEBUG" and "_RELEASE" allow to set +separate values for debug and release builds. In case you do not want to add +additional flags, but to override the default flags, replace "CGAL" by +"CMAKE" in the variable names above. + +A comprehensive list of CMake variables can be found on the \ref configurationvariables page. + +Note that CMake maintains a cache name `CMakeCache.txt`. If you change options +(or your environment changes), it is best to remove that file to avoid +problems. + +\subsection installation_configuring_gui Configuring CGAL with the CMake GUI + +The simplest way to start the configuration process is to run the graphical +user interface of CMake, `cmake-gui`. You must pass as +argument the root directory of \cgal. For example: + + cd CGAL-\cgalReleaseNumber + cmake-gui . # Notice the dot to indicate the current directory + +After `cmake-gui` opens, press 'Configure'. +A dialog will pop up and you will have to choose what shall be generated. +After you have made your choice and pressed 'Finish', you will see +the output of configuration tests in the lower portion of the application. +When these tests are done, you will see many +red entries in the upper portion of the application. Just ignore them and press 'Configure'. +By now CMake should have found many libraries and have initialized variables. +If you still find red entries, you have to provide the necessary information. +This typically happens if you have installed software at non-standard locations. + +Providing information and pressing 'Configure' goes on until +all entries are grayed. You are now ready to press 'Generate'. Once this is +done, you can quit `cmake-gui`. + +\subsection installation_configuring_cmd Configuring CGAL with the cmake Command-Line Tool + +Alternatively, you can run the command-line tool called `cmake`. +You pass as argument the root directory of \cgal. +The command line tool `cmake` accepts CMake variables as arguments of the form `-D:=`, as +in the example above, but this is only useful if you already know which variables need to be explicitly defined. +For example: + + cd CGAL-\cgalReleaseNumber + cmake . # Notice the dot to indicate the current directory + +The configuration process not only determines the location of the required dependencies, it also dynamically generates a +`compiler_config.h` file, which encodes the properties of your system and a special file named +`CGALConfig.cmake`, which is used to build programs using \cgal. The +purpose of this file is explained below. + +\cgalAdvancedBegin +CMake keeps the variables that a user can manipulate in a +so-called CMake cache, a simple text file named +`CMakeCache.txt`, whose entries are of the form +`VARIABLE:TYPE=VALUE`. Advanced users can manually edit this file, +instead of going through the interactive configuration session. +\cgalAdvancedEnd + +\subsection installation_cgalconfig CGALConfig.cmake + +During configuration of the \cgal libraries a file named `CGALConfig.cmake` is generated +in \cgal's root directory (in contrast to \cgal's source directory that has been used +for installation). This file contains the definitions of several CMake variables +that summarize the configuration of \cgal and will be essential during the configuration and +building of a program using \cgal, see Section \ref installation_buildprogram. + +\section seccmakeoutofsource Multiple Variants of Makefiles (Out-of-Source Builds) + +While you can choose between release or debug builds, and shared or static libraries, +it is not possible to generate different variants during a single configuration. You need to run CMake in a +different directory for each variant you are interested in, each with its own selection of configuration parameters. + +CMake stores the resulting makefiles and project files, along with several temporary and auxiliary files such +as the variables cache, in the directory where it is executed, called `CMAKE_BINARY_DIR`, but it +takes the source files and configuration scripts from +`CMAKE_SOURCE_DIR`. + +The binary and source directories do not need to be the same. Thus, you can configure multiple variants by creating a +distinct directory for each configuration and by running CMake from there. This is known in CMake terminology +as out-of-source configuration, as opposite to an in-source +configuration, as showed in the previous sections. +You can, for example, generate subdirectories `CGAL-\cgalReleaseNumber``/cmake/platforms/debug` and +`CGAL-\cgalReleaseNumber``/cmake/platforms/release` for two configurations, respectively: + + mkdir CGAL-\cgalReleaseNumber/cmake/platforms/debug + cd CGAL-\cgalReleaseNumber/cmake/platforms/debug + cmake -DCMAKE_BUILD_TYPE=Debug ../../.. + + mkdir CGAL-\cgalReleaseNumber/cmake/platforms/release + cd CGAL-\cgalReleaseNumber/cmake/platforms/release + cmake -DCMAKE_BUILD_TYPE=Release ../../.. + +\section secbuilding Building CGAL + +The results of a successful configuration are build files that control the build step. +The nature of the build files depends on the generator used during configuration, but in all cases they +contain several targets, one per library, and a default global target corresponding +to all the libraries. + +For example, in a \sc{Unix}-like environment the default generator produces +makefiles. You can use the `make` command-line tool for the +succeeding build step as follows: + + # build all the selected libraries at once + make + +The resulting libraries are placed in the subdirectory `lib` under `` +(which is `CGAL-\cgalReleaseNumber` in case you run an in-source-configuration). + +With generators other than `UNIX Makefiles`, the resulting build files +are solution and project files which should be launched in an \sc{Ide}, +such as Visual Studio or KDevelop3. They will contain the targets described +above, which you can manually build as with any other solution/project within your \sc{Ide}. + +Alternatively, you can build it with the command line version of the +\sc{Visual Studio Ide}: + + devenv CGAL.sln /Build Debug + +The "Debug" argument is needed because CMake creates solution files for +all four configurations, and you need to explicitly choose one when building +(the other choices are `Release`, `RelWithDebInfo`, and `MinSizeRel`). + +\cgalAdvancedBegin +The build files produced by CMake are autoconfigured. That +is, if you change any of the dependencies, the build step +automatically goes all the way back to the configuration step. This +way, once the target has been configured the very first time by +invoking cmake, you don't necessarily need to invoke `cmake` +again. Rebuilding will call itself `cmake` and re-generate the +build file whenever needed. Keep this in mind if you configure \cgal +for the Visual Studio IDE since a build could then change the +solution/project file in-place and VS will prompt you to reload it. +\cgalAdvancedEnd + +\subsection ssec_installation_build_ex_demos Building Examples and Demos + +If you have turned on the configuration of examples +(`-DWITH_examples=ON`) and/or demos (`-DWITH_demos=ON`), there will be additional +targets named `examples` and `demos`, plus one target for +each example and each demo in the build files. +None of these targets are included by default, so you need to build them explicitly +after the \cgal libraries have been successfully built. +The targets `examples` and `demos` include themselves all the targets +for examples and demos respectively. + + # build all examples at once + make examples + + # build all demos at once + make demos + +If you are interested in the demos or examples of just a particular module, you can build them in the following way: + + make -C demo/Alpha_shapes_2 # equivalent to "cd demo/Alpha_shapes_2; make" + make -C examples/Alpha_shapes_2 # equivalent to "cd examples/Alpha_shapes_2; make" + +When using `UNIX Makefiles`, you can find out the exact name of the example or demo target +of a particular package by typing `make help | grep `. + +\section secinstalling Installing CGAL + +On many platforms, library pieces such as headers, docs and binaries +are expected to be placed in specific locations. A typical example +being `/usr/include` and `/usr/lib` on \sc{Unix}-like +operating systems or `C:/Program Files/` on Windows. The process +of placing or copying the library elements into its standard location +is sometimes referred to as Installation and it is a +postprocessing step after the build step. + +CMake carries out the installation by producing a build target named install. +Assuming you have successfully configured and built \cgal as demonstrated in the previous sections, +the installation simply amounts (in a \sc{Unix}-like environment) to: + + # install CGAL + make install + +If you use a generator that produces IDE files (for Visual Studio for instance), there will be an optional +`INSTALL` project, which you will be able to "build" to execute the installation step. + +\cgalAdvancedBegin +The files are copied into a directory tree relative to the installation directory determined by the +CMake variable `CMAKE_INSTALL_PREFIX`. This variable defaults to `/usr/local` under \sc{Unix}-like operating systems +and `C:\Program Files` under Windows. If you want to install to a different location, you must override that CMake +variable explicitly at the configuration time and not when executing the install step. +\cgalAdvancedEnd + +The file `CGALConfig.cmake` is installed by default in +`$CMAKE_INSTALLED_PREFIX/lib/``CGAL-\cgalReleaseNumber`. + +\section installation_buildprogram Building a Program using CGAL + +Similarly to \cgal and its libraries, compiling a program using \cgal is done in the usual +two steps of configuration and building. + +The configuration process is also done using `cmake` (or `cmake-gui`) and requires a `CMakeLists.txt` file. +This file is automatically provided for all shipped examples and demos of \cgal. +For other programs, CMake can also be used to configure +and build user programs, but one has to provide the corresponding `CMakeLists.txt`. +This script can be generated either manually, or with the help of a shell-script, +see Section \ref devman_create_cgal_CMakeLists. Using this shell-script, +the process of configuring a user's program called `executable.cpp` amounts to: + + cd /path/to/your/program + cgal_create_CMakeLists -s executable + cmake -DCGAL_DIR=XXXXXX -CMAKE_BUILD_TYPE=Release . + make + +In order to configure a program, you need to indicate the location of the configuration file +in the CMake variable `CGAL_DIR` (as indicated in the example above). +If you have installed \cgal, `CGAL_DIR` must afterwards be set to `$CMAKE_INSTALLED_PREFIX/lib/CGAL`. + +The variable `CGAL_DIR` can also be an environment variable, but setting it manually makes particular sense +if having multiple out-of-source builds of \cgal as in Section \ref seccmakeoutofsource. + +\section secspecificinstall OS Specific Installation + +Some operating systems with package managers offer \cgal and its +essential third party software through the manager, +for instance, Mac OS X or some Linux distribution (e.g. Debian). +For Windows, an installer is provided. + +\subsection sseccgalmacosxe CGAL on macOS + +The \cgal project recommends the use of Homebrew, in the following way: + + brew install cgal + +\subsection sseccgaldebian CGAL on Linux + +For instance in Debian/Ubuntu, use apt-get in the following way: + + sudo apt-get install libcgal-dev + +To get the demos, use: + + sudo apt-get install libcgal-demo + +For other distributions, please consult your respective package manager documentation. + +\subsection sseccgalwindows CGAL on Windows + +You can download and run `CGAL-\cgalReleaseNumber``-Setup.exe` from https://www.cgal.org/download/windows.html. +It is a self extracting executable that installs the \cgal source, and that allows you +to select and download some precompiled third party libraries. However, you will need to compile +the library using your favorite compiler. +A tutorial is provided on how to proceed with Microsoft Visual Studio. + +*/ diff --git a/Documentation/doc/Documentation/advanced/advanced.txt b/Documentation/doc/Documentation/advanced/advanced.txt new file mode 100644 index 00000000000..b6136edda22 --- /dev/null +++ b/Documentation/doc/Documentation/advanced/advanced.txt @@ -0,0 +1,8 @@ +/*! + +\page advanced Advanced + +- \subpage configurationvariables lists the various CMake variables that can be used to help find third-party dependencies. +- \subpage installation describes the (optional) process of building and installing %CGAL itself. + +*/ From 8978d919bd76b1804d38cc30142b28422d08f14c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mael=20Rouxel-Labb=C3=A9?= Date: Fri, 25 Oct 2019 12:32:28 +0200 Subject: [PATCH 237/363] Remove duplicate configuration variable files --- .../Documentation/Configuration_variables.txt | 345 ------------------ 1 file changed, 345 deletions(-) delete mode 100644 Documentation/doc/Documentation/Configuration_variables.txt diff --git a/Documentation/doc/Documentation/Configuration_variables.txt b/Documentation/doc/Documentation/Configuration_variables.txt deleted file mode 100644 index 7e7080f964f..00000000000 --- a/Documentation/doc/Documentation/Configuration_variables.txt +++ /dev/null @@ -1,345 +0,0 @@ -/*! - -\page configurationvariables Summary of CGAL's Configuration Variables -\cgalAutoToc - -Most configuration variables are not environment variables but -CMake variables. They are given in the command line to CMake -via the `-D` option, or passed from the interactive interface -of `cmake-gui`. Unless indicated differently, all the variables -summarized below are CMake variables. - -\section installation_component_selection Component Selection - -The following Boolean variables enable the compilation of all examples and demos -at the same time. Their values can be ON or OFF. New corresponding targets will be -created, the compilation will be triggered by calling `make examples` and `make demos`. -To build a particular subset of examples or demos, from your build directory go -to the subdirectory `demo/PKG` or `example/PKG` and simply call make from there. - -| Variable | %Default Value | -| :------- | :--------------- | -| `WITH_examples` | OFF | -| `WITH_demos` | OFF | - -\section installation_flags Compiler and Linker Flags - -The following variables specify compiler and linker flags. Each variable holds a -space-separated list of command-line switches for the compiler and linker and -their default values are automatically defined by CMake based on the target platform. - -Have in mind that these variables specify a list of flags, not just one -single flag. If you provide your own definition for a variable, you will entirely override -the list of flags chosen by CMake for that particular variable. - -The variables that correspond to both debug and release builds are always -used in conjunction with those for the specific build type. - - -| Program | Both Debug and Release | Release Only | Debug Only | -| :------ | :---------------------- | :------------- | :----------- | -| C++ Compiler | `CMAKE_CXX_FLAGS` | `CMAKE_CXX_FLAGS_RELEASE` | `CMAKE_CXX_FLAGS_DEBUG` | -| Linker (shared libs) | `CMAKE_SHARED_LINKER_FLAGS` | `CMAKE_SHARED_LINKER_FLAGS_RELEASE` | `CMAKE_SHARED_LINKER_FLAGS_DEBUG` | -| Linker (static libs) | `CMAKE_MODULE_LINKER_FLAGS` | `CMAKE_MODULE_LINKER_FLAGS_RELEASE` | `CMAKE_MODULE_LINKER_FLAGS_DEBUG` | -| Linker (programs) | `CMAKE_EXE_LINKER_FLAGS` | `CMAKE_EXE_LINKER_FLAGS_RELEASE` | `CMAKE_EXE_LINKER_FLAGS_DEBUG`| - - -\section installation_additional_flags Additional Compiler and Linker Flags - -The following variables can be used to add flags without overriding the ones -defined by cmake. - - -| Program | Both Debug and Release | Release Only | Debug Only | -| :------ | :---------------------- | :------------- | :----------- | -| C++ Compiler | `CGAL_CXX_FLAGS` | `CGAL_CXX_FLAGS_RELEASE` | `CGAL_CXX_FLAGS_DEBUG` | -| Linker (shared libs) | `CGAL_SHARED_LINKER_FLAGS` | `CGAL_SHARED_LINKER_FLAGS_RELEASE` | `CGAL_SHARED_LINKER_FLAGS_DEBUG` | -| Linker (static libs) | `CGAL_MODULE_LINKER_FLAGS` | `CGAL_MODULE_LINKER_FLAGS_RELEASE` | `CGAL_MODULE_LINKER_FLAGS_DEBUG` | -| Linker (programs) | `CGAL_EXE_LINKER_FLAGS` | `CGAL_EXE_LINKER_FLAGS_RELEASE` | `CGAL_EXE_LINKER_FLAGS_DEBUG` | - -\section installation_misc Miscellaneous Variables - -Note that the default build type is `Debug`, which should only be used to debug -and will serverly limit performances. - -| Variable | Description | Type | %Default Value | -| :- | :- | :- | :- | -| `CMAKE_BUILD_TYPE` | Indicates type of build. Possible values are 'Debug' or 'Release' | CMake | | -| `CMAKE_INSTALL_PREFIX`| Installation directory path | CMake | Debug | -| `CMAKE_C_COMPILER` | Full-path to the executable corresponding to the C compiler to use. | CMake | platform-dependent | -| `CMAKE_CXX_COMPILER` | Full-path to the executable corresponding to the C++ compiler to use. | CMake | platform-dependent | -| `CXX` | Idem | Environment | Idem | -| `BUILD_SHARED_LIBS` | Whether to build shared or static libraries. | CMake | TRUE | - -\section installation_variables_building Variables Used Only When Building Programs (Such as Demos or Examples) - - -| Variable | Description | Type | %Default Value | -| :- | :- | :- | :- | -| `CGAL_DIR` | Full-path to the binary directory where \cgal was configured |Either CMake or Environment | none | - - -\section installation_variables_third_party Variables Providing Information About 3rd-Party Libraries -\anchor sec3partysoftwareconfig - -The following variables provide information about the availability and -location of the 3rd party libraries used by \cgal. CMake automatically -searches for dependencies so you need to specify these variables if -CMake was unable to locate something. This is indicated by a value ending in -`NOTFOUND`. - -Since 3rd-party libraries are system wide, many of the CMake variables listed below can alternatively -be given as similarly-named environment variables instead. Keep in mind that you must provide one or the -other but never both. - -\section installation_boost Boost Libraries - -In most cases, if \sc{Boost} is not automatically found, setting the `BOOST_ROOT` -variable is enough. If it is not, you can specify the header and library -directories individually. You can also provide the full pathname to a specific compiled library -if it cannot be found in the library directory or its name is non-standard. - -By default, when \sc{Boost} binary libraries are needed, the shared versions -are used if present. You can set the variable -`CGAL_Boost_USE_STATIC_LIBS` to `ON` if you want to link -with static versions explicitly. - -On Windows, if you link with \sc{Boost} shared libraries, you must ensure that -the `.dll` files are found by the dynamic linker, at run time. -For example, you can add the path to the \sc{Boost} `.dll` to the -`PATH` environment variable. - -| Variable | Description | Type | -| :- | :- | :- | -| `BOOST_ROOT`\cgalFootnote{The environment variable can be spelled either `BOOST_ROOT` or `BOOSTROOT`} | Root directory of your \sc{Boost} installation | Either CMake or Environment | -| `Boost_INCLUDE_DIR` | Directory containing the `boost/version.hpp` file | CMake | -| `BOOST_INCLUDEDIR` | Idem | Environment | -| `Boost_LIBRARY_DIRS` | Directory containing the compiled \sc{Boost} libraries | CMake | -| `BOOST_LIBRARYDIR` | Idem | Environment | -| `Boost_(xyz)_LIBRARY_RELEASE` | Full pathname to a release build of the compiled 'xyz' \sc{Boost} library | CMake | -| `Boost_(xyz)_LIBRARY_DEBUG` | Full pathname to a debug build of the compiled 'xyz' \sc{Boost} library | CMake | - - -\section installation_gmp GMP and MPFR Libraries - -Under Windows, auto-linking is used, so only the directory -containing the libraries is needed and you would specify `GMP|MPFR_LIBRARY_DIR` rather than -`GMP|MPFR_LIBRARIES`. On the other hand, under Linux the actual library filename is needed. -Thus you would specify `GMP|MPFR_LIBRARIES`. In no case you need to specify both. - -\cgal uses both \sc{Gmp} and \sc{Mpfr} so both need to be supported. If either of them is unavailable the -usage of \sc{Gmp} and of \sc{Mpfr} will be disabled. - - -| Variable | Description | Type | -| :- | :- | :- | -| `CGAL_DISABLE_GMP` | Indicates whether to search and use \sc{Gmp}/\sc{Mpfr} or not | CMake | -| `GMP_DIR` | Directory of \sc{Gmp} default installation | Environment | -| `GMP_INCLUDE_DIR` | Directory containing the `gmp.h` file | CMake | -| `GMP_INC_DIR` | Idem | Environment | -| `GMP_LIBRARIES_DIR` | Directory containing the compiled \sc{Gmp} library | CMake | -| `GMP_LIB_DIR` | Idem | Environment | -| `GMP_LIBRARIES` | Full pathname of the compiled \sc{Gmp} library | CMake | -| `MPFR_INCLUDE_DIR` | Directory containing the `mpfr.h` file | CMake | -| `MPFR_INC_DIR` | Idem | Environment | -| `MPFR_LIBRARIES_DIR` | Directory containing the compiled \sc{Mpfr} library | CMake | -| `MPFR_LIB_DIR` | Idem | Environment | -| `MPFR_LIBRARIES` | Full pathname of the compiled \sc{Mpfr} library | CMake | - - - -Under Linux, the \sc{Gmpxx} is also searched for, and you may specify the following variables: - - -| Variable | Description | Type | -| :- | :- | :- | -| `GMPXX_DIR` | Directory of \sc{gmpxx} default installation | Environment | -| `GMPXX_INCLUDE_DIR` | Directory containing the `gmpxx.h` file | CMake | -| `GMPXX_LIBRARIES` | Full pathname of the compiled \sc{Gmpxx} library | CMake | - - - -\section installation_qt5 Qt5 Library - -You must set the cmake or environment variable `Qt5_DIR` to point to the path -to the directory containing the file `Qt5Config.cmake` created by your \sc{Qt}5 installation. If you are -using the open source edition it should be `/qt-everywhere-opensource-src-/qtbase/lib/cmake/Qt5`. - -\section installation_leda LEDA Library - -When the \leda libraries are not automatically found, yet they are installed on the system -with base names 'leda' and 'ledaD' (for the release and debug versions resp.), it might -be sufficient to just indicate the library directory via the `LEDA_LIBRARY_DIRS` variable. -If that doesn't work because, for example, the names are different, you can provide the full pathnames of each variant -via `LEDA_LIBRARY_RELEASE` and `LEDA_LIBRARY_DEBUG`. - -The variables specifying definitions and flags can be left undefined if they are not needed by LEDA. - - -| Variable | Description | Type | -| :- | :- | :- | -| `WITH_LEDA` | Indicates whether to search and use \leda or not | CMake | -| `LEDA_DIR` | Directory of \sc{LEDA} default installation | Environment | -| `LEDA_INCLUDE_DIR` | Directory containing the file `LEDA/system/basic.h` | CMake | -| `LEDA_LIBRARIES` | Directory containing the compiled \leda libraries | CMake | -| `LEDA_INC_DIR` | Directory containing the file `LEDA/system/basic.h` | Environment | -| `LEDA_LIB_DIR` | Directory containing the compiled \leda libraries | Environment | -| `LEDA_LIBRARY_RELEASE` | Full pathname to a release build of the \leda library | CMake | -| `LEDA_LIBRARY_DEBUG` | Full pathname to a debug build of the \leda library | CMake | -| `LEDA_DEFINITIONS` | Preprocessor definitions | CMake | -| `LEDA_CXX_FLAGS` | Compiler flags | CMake | -| `LEDA_LINKER_FLAGS` | Linker flags | CMake | - - -\section installation_mpfi MPFI Library - -\cgal provides a number type based on this library, but the \cgal library -itself does not depend on \sc{Mpfi}. This means that this library must be -configured when compiling an application that uses the above number type. - -When \sc{Mpfi} files are not on the standard path, the locations of the headers -and library files must be specified by using environment variables. - - -| Variable | Description | Type | -| :- | :- | :- | -| `MPFI_DIR` |Directory of \sc{MPFI} default installation | Environment | -| `MPFI_INCLUDE_DIR` | Directory containing the `mpfi.h` file | CMake | -| `MPFI_INC_DIR` | Idem | Environment | -| `MPFI_LIBRARIES_DIR` | Directory containing the compiled \sc{Mpfi} library | CMake | -| `MPFI_LIB_DIR` | Idem | Environment | -| `MPFI_LIBRARIES` | Full pathname of the compiled \sc{Mpfi} library | CMake | - - - -\section installation_rs RS and RS3 Library - -As said before, only the \cgal univariate algebraic kernel depends on the -library Rs. As the algebraic kernel is not compiled as a part of the \cgal -library, this library is not detected nor configured at installation time. - -CMake will try to find Rs in the standard header and library -directories. When it is not automatically detected, the locations of the -headers and library files must be specified using environment variables. - -Rs needs \sc{Gmp} 4.2 or later and \sc{Mpfi} 1.3.4 or later. The variables -related to the latter library may also need to be defined. - - -| Variable | Description | Type | -| :- | :- | :- | -| `RS_DIR` | Directory of \sc{Rs} default installation | Environment | -| `RS_INCLUDE_DIR` | Directory containing the `rs_exports.h` file | CMake | -| `RS_INC_DIR` | Idem | Environment | -| `RS_LIBRARIES_DIR` | Directory containing the compiled \sc{Rs} library | CMake | -| `RS_LIB_DIR` | Idem | Environment | -| `RS_LIBRARIES` | Full pathname of the compiled \sc{Rs} library | CMake | - -Similar variables exist for \sc{Rs3}. - -| Variable | Description | Type | -| :- | :- | :- -| `RS3_DIR` | Directory of \sc{Rs3} default installation | Environment | -| `RS3_INCLUDE_DIR` | Directory containing the file `rs3_fncts.h` file | CMake | -| `RS3_INC_DIR` | Idem | Environment | -| `RS3_LIBRARIES_DIR` | Directory containing the compiled \sc{Rs3} library | CMake | -| `RS3_LIB_DIR` | Idem | Environment | -| `RS3_LIBRARIES` | Full pathname of the compiled \sc{Rs3} library | CMake | - - -\section installation_ntl NTL Library - -Some polynomial computations in \cgal's algebraic kernel -are speed up when \sc{Ntl} is available. -As the algebraic kernel is not compiled as a part of the \cgal -library, this library is not detected nor configured at installation time. - -CMake will try to find \sc{Ntl} in the standard header and library -directories. When it is not automatically detected, the locations of the -headers and library files must be specified using environment variables. - -| Variable | Description | Type | -| :- | :- | :- | -| `NTL_DIR` | Directory of \sc{NTL} default installation | Environment | -| `NTL_INCLUDE_DIR` | Directory containing the `NTL/ZZX.h` file | CMake | -| `NTL_INC_DIR` | Idem | Environment | -| `NTL_LIBRARIES_DIR` | Directory containing the compiled \sc{Ntl} library | CMake | -| `NTL_LIB_DIR` | Idem | Environment | -| `NTL_LIBRARIES` | Full pathname of the compiled \sc{Ntl} library | CMake | - -\section installation_eigen Eigen Library - -\sc{Eigen} is a header-only template library. -Only the directory containing the header files of \sc{Eigen} 3.1 (or greater) is needed. - - -| Variable | Description | Type | -| :- | :- | :- | -| `EIGEN3_INCLUDE_DIR` | Directory containing the file `signature_of_eigen3_matrix_library` | CMake | -| `EIGEN3_INC_DIR` | Idem | Environment | - -\section installation_esbtl ESBTL Library - -One skin surface example requires the \sc{Esbtl} library in order to read \sc{Pdb} files. - -If \sc{Esbtl} is not automatically found, setting the `ESBTL_INC_DIR` -environment variable is sufficient. - - -| Variable | Description | Type | -| :- | :- | :- | -| `ESBTL_DIR` | Directory of \sc{ESBTL} default installation | Environment | -| `ESBTL_INC_DIR` | Directory containing the `ESBTL/default.h` file | Environment | -| `ESBTL_INCLUDE_DIR` | Directory containing the `ESBTL/default.h` file | CMake | - -\section installation_tbb TBB Library - -If \sc{Tbb} is not automatically found, the user must set the `TBB_ROOT` -environment variable. The environment variable `TBB_ARCH_PLATFORM=/` must be set. -`` is `ia32` or `intel64`. `` describes the Linux kernel, gcc version or Visual Studio version -used. It should be set to what is used in `$TBB_ROOT/lib/`. - -For windows users, the folder `TBB_ROOT/bin//` should be added to the `PATH` variable. - -Note that the variables in the table below are being used. - -| Variable | Description | Type | -| :- | :- | :- | -| `TBB_ROOT` | Directory of \sc{Tbb} default installation | Environment | -| `TBB_INCLUDE_DIRS` | Directory containing the `tbb/tbb.h` file | CMake | -| `TBB_LIBRARY_DIRS` | Directory(ies) containing the compiled TBB libraries | CMake | -| `TBB_LIBRARIES` | Full pathnames of the compiled TBB libraries (both release and debug versions, using "optimized" and "debug" CMake keywords). Note that if the debug versions are not found, the release versions will be used instead for the debug mode. | CMake | -| `TBB_RELEASE_LIBRARY` | Full pathname of the compiled TBB release library | CMake | -| `TBB_MALLOC_RELEASE_LIBRARY` | Full pathname of the compiled TBB release malloc library | CMake | -| `TBB_DEBUG_LIBRARY` | Full pathname of the compiled TBB debug library | CMake | -| `TBB_MALLOC_DEBUG_LIBRARY` | Full pathname of the compiled TBB debug malloc library | CMake | -| `TBB_MALLOCPROXY_DEBUG_LIBRARY` | Full pathname of the compiled TBB debug malloc_proxy library (optional) | CMake | -| `TBB_MALLOCPROXY_RELEASE_LIBRARY` | Full pathname of the compiled TBB release malloc_proxy library (optional) | CMake | - -\section installation_compiler_workarounds Compiler Workarounds - -A number of boolean flags are used to workaround compiler bugs and -limitations. They all start with the prefix `CGAL_CFG`. These -flags are used to work around compiler bugs and limitations. For -example, the flag `CGAL_CFG_NO_CPP0X_LONG_LONG` denotes -that the compiler does not know the type `long long`. - -For each installation a file -is defined, with the correct -settings of all flags. This file is generated automatically by CMake, -and it is located in the `include` directory of where you run -CMake. For an in-source configuration this means -`CGAL-\cgalReleaseNumber``/include`. - -The test programs used to generate the `compiler_config.h` -file can be found in `config/testfiles`. -Both -`compiler_config.h` and the test programs contain a short -description of the problem. In case of trouble with one of the -`CGAL_CFG` flags, it is a good idea to take a look at it. - -The file `CGAL/compiler_config.h` is included from -``. -which is included by all \cgal header files. - -*/ From 61100b870fc638c49255862a04c18e05f59a1695 Mon Sep 17 00:00:00 2001 From: Maxime Gimeno Date: Fri, 25 Oct 2019 14:53:24 +0200 Subject: [PATCH 238/363] Fix fix for nef normals --- .../demo/Polyhedron/Scene_nef_polyhedron_item.cpp | 14 ++------------ 1 file changed, 2 insertions(+), 12 deletions(-) diff --git a/Polyhedron/demo/Polyhedron/Scene_nef_polyhedron_item.cpp b/Polyhedron/demo/Polyhedron/Scene_nef_polyhedron_item.cpp index 362c34ee29b..86ac3f146fa 100644 --- a/Polyhedron/demo/Polyhedron/Scene_nef_polyhedron_item.cpp +++ b/Polyhedron/demo/Polyhedron/Scene_nef_polyhedron_item.cpp @@ -204,8 +204,9 @@ void Scene_nef_polyhedron_item_priv::compute_normals_and_vertices(void) const f != end; ++f) { if(f->is_twin()) continue; + bool incident_volume_marked = f->incident_volume()->mark(); count++; - Nef_polyhedron::Vector_3 v = f->plane().orthogonal_vector(); + Nef_polyhedron::Vector_3 v = (incident_volume_marked? -1:1) * f->plane().orthogonal_vector(); P_traits cdt_traits(v); CDT cdt(cdt_traits); @@ -283,17 +284,6 @@ void Scene_nef_polyhedron_item_priv::compute_normals_and_vertices(void) const } - - - Nef_polyhedron::Vector_3 v = f->plane().orthogonal_vector(); - if(f->plane().a() != 0) - v /= f->plane().a(); - else if(f->plane().b() != 0) - v /= f->plane().b(); - else if(f->plane().c() != 0) - v /= f->plane().c(); - else if(f->plane().d() != 0) - v /= f->plane().d(); GLfloat normal[3]; normal[0] = CGAL::to_double(v.x()); normal[1] = CGAL::to_double(v.y()); From e6eb4812ebe57dd7a5caa2de895fb4484e8a43ff Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mael=20Rouxel-Labb=C3=A9?= Date: Fri, 25 Oct 2019 14:05:15 +0200 Subject: [PATCH 239/363] Misc Installation Documentation Updates --- .../doc/Documentation/Getting_started.txt | 11 +- Documentation/doc/Documentation/Usage.txt | 18 +-- .../Documentation/advanced/Installation.txt | 149 ++++++------------ Documentation/doc/Documentation/windows.txt | 125 +++++++-------- README.md | 2 +- 5 files changed, 120 insertions(+), 185 deletions(-) diff --git a/Documentation/doc/Documentation/Getting_started.txt b/Documentation/doc/Documentation/Getting_started.txt index 1c39617f5f8..b4759c28f95 100644 --- a/Documentation/doc/Documentation/Getting_started.txt +++ b/Documentation/doc/Documentation/Getting_started.txt @@ -1,19 +1,18 @@ /*! \page general_intro Getting Started with %CGAL -- \subpage usage Using \cgal on Unix +- \subpage usage -- \subpage windows Using \cgal on Windows +- \subpage windows -- \subpage thirdparty lists required and optional third party libraries. +- \subpage thirdparty gives information (supported versions, download links) of the required and optional third party libraries. - \subpage manual gives an idea of where you should look for documentation. - \subpage preliminaries lists how to control inlining, thread safety, code deprecation, checking of pre- and postconditions, and how to alter the failure behavior. Once you are familiar with building your programs with \cgal and how the documentation is structured, -you can head over to the \ref tutorials for a hand-in-hand introduction to \cgal data structures -and algorithms, or directly to the package(s) that interest you the \ref packages. Each package -contains simple examples of the various functionalities of the package. +you can head over to the \ref tutorials for a gentle introduction to \cgal, or directly to the package(s) +that interest you the \ref packages. Each package contains simple examples of the various functionalities of the package. */ diff --git a/Documentation/doc/Documentation/Usage.txt b/Documentation/doc/Documentation/Usage.txt index a15d2dde432..54ecb3c7814 100644 --- a/Documentation/doc/Documentation/Usage.txt +++ b/Documentation/doc/Documentation/Usage.txt @@ -1,5 +1,5 @@ /*! -\page usage Using %CGAL on UNIX +\page usage Using %CGAL on Linux and macOS \cgalAutoToc Since \cgal version 5.0, \cgal is header-only be default, which means @@ -9,8 +9,8 @@ However, some dependencies of \cgal might still need to be installed. \section usage_introduction Quick Start: Compiling a Program using CGAL Assuming that you have obtained \cgal through one of the package managers offering \cgal on your platform -(see Section \ref secgettingcgal), compiling \cgal examples -is as simple as: +(see Section \ref secgettingcgal), you can download \cgal examples here +and the compilation of an example is as simple as: cd $HOME/CGAL-\cgalReleaseNumber/examples/Triangulation_2 # go to an example directory cmake -DCMAKE_BUILD_TYPE=Release . # configure the examples @@ -19,7 +19,7 @@ is as simple as: Compiling your own program is similar: cd /path/to/your/program - cgal_create_CMakeLists -s executable + cgal_create_CMakeLists -s your_program cmake -DCMAKE_BUILD_TYPE=Release . make @@ -55,7 +55,7 @@ and must be downloaded here. On most operating systems, package managers offer \cgal and its essential third party dependencies. -On `macOS`, we recommend using of Homebrew in the following way: +On macOS, we recommend using of Homebrew in the following way: brew install cgal @@ -101,8 +101,8 @@ The directory `include/CGAL/OpenNL` contains a distribution of the which provides solvers for sparse linear systems, especially designed for the Computer Graphics community. \sc{OpenNL} is not part of \cgal and has its own license. -The only documentation shipped within \cgal sources is the present -installation manual. The \cgal manual can be accessed online at +The only documentation shipped within \cgal sources is the present manual. +The \cgal manual can also be accessed online at `https://doc.cgal.org` or downloaded separately at `https://github.com/CGAL/cgal/releases`. @@ -190,10 +190,10 @@ for all shipped examples and demos of \cgal. For other programs, CMake can also and build user programs, but one has to provide the corresponding `CMakeLists.txt`. This script can be generated either manually, or with the help of a shell-script, see Section \ref devman_create_cgal_CMakeLists. Using this shell-script, -the process of configuring a user's program called `executable.cpp` amounts to: +the process of configuring a user's program called `your_program.cpp` amounts to: cd /path/to/your/program - cgal_create_CMakeLists -s executable + cgal_create_CMakeLists -s your_program cmake -DCGAL_DIR=$HOME/CGAL-\cgalReleaseNumber -CMAKE_BUILD_TYPE=Release . Note that the script `cgal_create_CMakeLists` creates a very coarse `CMakeLists.txt` file which diff --git a/Documentation/doc/Documentation/advanced/Installation.txt b/Documentation/doc/Documentation/advanced/Installation.txt index cf6d2679b62..6afd8618d1b 100644 --- a/Documentation/doc/Documentation/advanced/Installation.txt +++ b/Documentation/doc/Documentation/advanced/Installation.txt @@ -1,27 +1,31 @@ /*! -\page installation Installation +\page installation Building %CGAL libraries (non header-only mode) \cgalAutoToc Since \cgal version 5.0, \cgal is header-only be default, which means -that there is no need to compile and install anything before it can be used. -However, the dependencies of \cgal might still need to be installed. +that there is no need to compile \cgal or its libraries before it can be used. -This page is a step-by-step description of how to configure, build, and install \cgal +This page is for advanced users that have a good reason to still use the old way. +If this is not your case, head over back to the page \ref general_intro. + +This page is a step-by-step description of how to configure, build, and (optionally) install \cgal in case you do not wish to use the - now enabled by default - header-only mode of \cgal. -It is also possible to install \cgal using package managers on some operating systems, -see Section \ref secspecificinstall. + +It is assumed that you have downloaded a source archive of \cgal, and are using Linux or macOS. \section installation_idealworld Quick Installation Ideally, compiling and installing \cgal, as well as compiling some examples shipped by \cgal is as simple as: cd $HOME/CGAL-\cgalReleaseNumber - cmake -DCMAKE_BUILD_TYPE=Release . # configure CGAL - make # build CGAL - make install # install CGAL - cd examples/Triangulation_2 # go to an example directory - cmake -DCGAL_DIR=$HOME/CGAL-\cgalReleaseNumber -DCMAKE_BUILD_TYPE=Release . # configure the examples - make # build the examples + mkdir build + cd build + cmake -DCMAKE_BUILD_TYPE=Release .. # configure CGAL + make # build CGAL + make install # install CGAL + cd examples/Triangulation_2 # go to an example directory + cmake -DCGAL_DIR=$HOME/CGAL-\cgalReleaseNumber/build -DCMAKE_BUILD_TYPE=Release . # configure the examples + make # build the examples In a less ideal world, you might have to install some required tools and third-party libraries. This is what this page is about. @@ -33,8 +37,7 @@ set compiler and linker flags, specify which third-party libraries you want to use and where they can be found, and which \cgal libraries you want to build. Gathering all this information is called configuration. -The end of the process is marked by the generation of a makefile or a -Visual \cpp solution and project file that you can use to build \cgal. +The end of the process is marked by the generation of a makefile that you can use to build \cgal. CMake maintains configuration parameters in so-called cmake variables. Some of the CMake variables represent user choices, such as `CMAKE_BUILD_TYPE`, while others @@ -61,7 +64,7 @@ Note that some libraries have specific dependencies in addition to the essential | `CGAL_Qt5` | `WITH_CGAL_Qt5` | `QGraphicsView` support for \sc{Qt}5-based demos | \sc{Qt}5 | Shared libraries, also called dynamic-link libraries, are built by default -(`.dll` on Windows, `.so` on Linux, `.dylib` on MacOS). You +(`.so` on Linux, `.dylib` on macOS). You can choose to produce static libraries instead, by setting the CMake variable `BUILD_SHARED_LIBS` to `FALSE`. @@ -123,21 +126,21 @@ The simplest way to start the configuration process is to run the graphical user interface of CMake, `cmake-gui`. You must pass as argument the root directory of \cgal. For example: - cd CGAL-\cgalReleaseNumber - cmake-gui . # Notice the dot to indicate the current directory + cd CGAL-\cgalReleaseNumber/build + cmake-gui .. # The two dots indicate the parent directory -After `cmake-gui` opens, press 'Configure'. +After `cmake-gui` opens, press *Configure*. A dialog will pop up and you will have to choose what shall be generated. -After you have made your choice and pressed 'Finish', you will see +After you have made your choice and pressed *Finish*, you will see the output of configuration tests in the lower portion of the application. When these tests are done, you will see many -red entries in the upper portion of the application. Just ignore them and press 'Configure'. +red entries in the upper portion of the application. Just ignore them and press *Configure*. By now CMake should have found many libraries and have initialized variables. If you still find red entries, you have to provide the necessary information. This typically happens if you have installed software at non-standard locations. -Providing information and pressing 'Configure' goes on until -all entries are grayed. You are now ready to press 'Generate'. Once this is +Providing information and pressing *Configure* goes on until +all entries are grayed. You are now ready to press *Generate*. Once this is done, you can quit `cmake-gui`. \subsection installation_configuring_cmd Configuring CGAL with the cmake Command-Line Tool @@ -148,8 +151,8 @@ The command line tool `cmake` accepts CMake variables as arguments of the form ` in the example above, but this is only useful if you already know which variables need to be explicitly defined. For example: - cd CGAL-\cgalReleaseNumber - cmake . # Notice the dot to indicate the current directory + cd CGAL-\cgalReleaseNumber/build + cmake .. The configuration process not only determines the location of the required dependencies, it also dynamically generates a `compiler_config.h` file, which encodes the properties of your system and a special file named @@ -172,13 +175,13 @@ for installation). This file contains the definitions of several CMake variables that summarize the configuration of \cgal and will be essential during the configuration and building of a program using \cgal, see Section \ref installation_buildprogram. -\section seccmakeoutofsource Multiple Variants of Makefiles (Out-of-Source Builds) +\section seccmakeoutofsource Multiple Builds While you can choose between release or debug builds, and shared or static libraries, it is not possible to generate different variants during a single configuration. You need to run CMake in a different directory for each variant you are interested in, each with its own selection of configuration parameters. -CMake stores the resulting makefiles and project files, along with several temporary and auxiliary files such +CMake stores the resulting makefiles, along with several temporary and auxiliary files such as the variables cache, in the directory where it is executed, called `CMAKE_BINARY_DIR`, but it takes the source files and configuration scripts from `CMAKE_SOURCE_DIR`. @@ -187,16 +190,16 @@ The binary and source directories do not need to be the same. Thus, you can conf distinct directory for each configuration and by running CMake from there. This is known in CMake terminology as out-of-source configuration, as opposite to an in-source configuration, as showed in the previous sections. -You can, for example, generate subdirectories `CGAL-\cgalReleaseNumber``/cmake/platforms/debug` and -`CGAL-\cgalReleaseNumber``/cmake/platforms/release` for two configurations, respectively: +You can, for example, generate subdirectories `CGAL-\cgalReleaseNumber``/build/debug` and +`CGAL-\cgalReleaseNumber``/build/release` for two configurations, respectively: - mkdir CGAL-\cgalReleaseNumber/cmake/platforms/debug - cd CGAL-\cgalReleaseNumber/cmake/platforms/debug - cmake -DCMAKE_BUILD_TYPE=Debug ../../.. + mkdir CGAL-\cgalReleaseNumber/build/debug + cd CGAL-\cgalReleaseNumber/build/debug + cmake -DCMAKE_BUILD_TYPE=Debug ../.. - mkdir CGAL-\cgalReleaseNumber/cmake/platforms/release - cd CGAL-\cgalReleaseNumber/cmake/platforms/release - cmake -DCMAKE_BUILD_TYPE=Release ../../.. + mkdir CGAL-\cgalReleaseNumber/build/release + cd CGAL-\cgalReleaseNumber/build/release + cmake -DCMAKE_BUILD_TYPE=Release ../.. \section secbuilding Building CGAL @@ -205,9 +208,8 @@ The nature of the build files depends on the generator used during configuration contain several targets, one per library, and a default global target corresponding to all the libraries. -For example, in a \sc{Unix}-like environment the default generator produces -makefiles. You can use the `make` command-line tool for the -succeeding build step as follows: +For example, in a \sc{Unix}-like environment the default generator produces makefiles. +You can use the `make` command-line tool for the succeeding build step as follows: # build all the selected libraries at once make @@ -215,20 +217,6 @@ succeeding build step as follows: The resulting libraries are placed in the subdirectory `lib` under `` (which is `CGAL-\cgalReleaseNumber` in case you run an in-source-configuration). -With generators other than `UNIX Makefiles`, the resulting build files -are solution and project files which should be launched in an \sc{Ide}, -such as Visual Studio or KDevelop3. They will contain the targets described -above, which you can manually build as with any other solution/project within your \sc{Ide}. - -Alternatively, you can build it with the command line version of the -\sc{Visual Studio Ide}: - - devenv CGAL.sln /Build Debug - -The "Debug" argument is needed because CMake creates solution files for -all four configurations, and you need to explicitly choose one when building -(the other choices are `Release`, `RelWithDebInfo`, and `MinSizeRel`). - \cgalAdvancedBegin The build files produced by CMake are autoconfigured. That is, if you change any of the dependencies, the build step @@ -236,9 +224,7 @@ automatically goes all the way back to the configuration step. This way, once the target has been configured the very first time by invoking cmake, you don't necessarily need to invoke `cmake` again. Rebuilding will call itself `cmake` and re-generate the -build file whenever needed. Keep this in mind if you configure \cgal -for the Visual Studio IDE since a build could then change the -solution/project file in-place and VS will prompt you to reload it. +build file whenever needed. \cgalAdvancedEnd \subsection ssec_installation_build_ex_demos Building Examples and Demos @@ -270,26 +256,22 @@ of a particular package by typing `make help | grep `. On many platforms, library pieces such as headers, docs and binaries are expected to be placed in specific locations. A typical example -being `/usr/include` and `/usr/lib` on \sc{Unix}-like -operating systems or `C:/Program Files/` on Windows. The process +being `/usr/include` and `/usr/lib`. The process of placing or copying the library elements into its standard location is sometimes referred to as Installation and it is a postprocessing step after the build step. CMake carries out the installation by producing a build target named install. Assuming you have successfully configured and built \cgal as demonstrated in the previous sections, -the installation simply amounts (in a \sc{Unix}-like environment) to: +the installation simply amounts to: # install CGAL make install -If you use a generator that produces IDE files (for Visual Studio for instance), there will be an optional -`INSTALL` project, which you will be able to "build" to execute the installation step. - \cgalAdvancedBegin The files are copied into a directory tree relative to the installation directory determined by the -CMake variable `CMAKE_INSTALL_PREFIX`. This variable defaults to `/usr/local` under \sc{Unix}-like operating systems -and `C:\Program Files` under Windows. If you want to install to a different location, you must override that CMake +CMake variable `CMAKE_INSTALL_PREFIX`. This variable defaults to `/usr/local` under \sc{Unix}-like operating systems. +If you want to install to a different location, you must override that CMake variable explicitly at the configuration time and not when executing the install step. \cgalAdvancedEnd @@ -307,51 +289,18 @@ For other programs, CMake can also be used to configure and build user programs, but one has to provide the corresponding `CMakeLists.txt`. This script can be generated either manually, or with the help of a shell-script, see Section \ref devman_create_cgal_CMakeLists. Using this shell-script, -the process of configuring a user's program called `executable.cpp` amounts to: +the process of configuring a user's program called `your_program.cpp` amounts to: cd /path/to/your/program - cgal_create_CMakeLists -s executable + cgal_create_CMakeLists -s your_program cmake -DCGAL_DIR=XXXXXX -CMAKE_BUILD_TYPE=Release . make -In order to configure a program, you need to indicate the location of the configuration file -in the CMake variable `CGAL_DIR` (as indicated in the example above). +In order to configure a program, you need to indicate the location of the \cgal configuration file +in the CMake variable `CGAL_DIR` (as shown in the example above). If you have installed \cgal, `CGAL_DIR` must afterwards be set to `$CMAKE_INSTALLED_PREFIX/lib/CGAL`. The variable `CGAL_DIR` can also be an environment variable, but setting it manually makes particular sense -if having multiple out-of-source builds of \cgal as in Section \ref seccmakeoutofsource. - -\section secspecificinstall OS Specific Installation - -Some operating systems with package managers offer \cgal and its -essential third party software through the manager, -for instance, Mac OS X or some Linux distribution (e.g. Debian). -For Windows, an installer is provided. - -\subsection sseccgalmacosxe CGAL on macOS - -The \cgal project recommends the use of Homebrew, in the following way: - - brew install cgal - -\subsection sseccgaldebian CGAL on Linux - -For instance in Debian/Ubuntu, use apt-get in the following way: - - sudo apt-get install libcgal-dev - -To get the demos, use: - - sudo apt-get install libcgal-demo - -For other distributions, please consult your respective package manager documentation. - -\subsection sseccgalwindows CGAL on Windows - -You can download and run `CGAL-\cgalReleaseNumber``-Setup.exe` from https://www.cgal.org/download/windows.html. -It is a self extracting executable that installs the \cgal source, and that allows you -to select and download some precompiled third party libraries. However, you will need to compile -the library using your favorite compiler. -A tutorial is provided on how to proceed with Microsoft Visual Studio. +if you have multiple out-of-source builds of \cgal as in Section \ref seccmakeoutofsource. */ diff --git a/Documentation/doc/Documentation/windows.txt b/Documentation/doc/Documentation/windows.txt index 3df201b6470..cc01f5df6cc 100644 --- a/Documentation/doc/Documentation/windows.txt +++ b/Documentation/doc/Documentation/windows.txt @@ -1,5 +1,5 @@ /*! -\page windows Installing %CGAL for Visual C++ on Windows +\page windows Using %CGAL on Windows (with Visual C++) \cgalAutoToc \cgal is a library that has mandatory dependencies that must be first installed: @@ -19,20 +19,18 @@ you will want to use the \cgal Installer. We explain the two approaches in the next two sections. -\section sec-installing-with-vcpkg Installing CGAL with the Vcpkg library manager +\section sec-installing-with-vcpkg Installing CGAL with the Vcpkg Library Manager \subsection ssec-vcpk-install-vcpk Installing Vcpkg The first step is to clone or download `vcpkg` from https://github.com/microsoft/vcpkg. -\code{.sh} - C:\dev> git clone https://github.com/microsoft/vcpkg - C:\dev> cd vcpkg - C:\dev\vcpkg> .\bootstrap-vcpkg.bat -\endcode + C:\dev> git clone https://github.com/microsoft/vcpkg + C:\dev> cd vcpkg + C:\dev\vcpkg> .\bootstrap-vcpkg.bat -\subsection ssec-vcpk-install-cgal Installing with Vcpkg +\subsection ssec-vcpk-install-cgal Installing CGAL with Vcpkg By default `vcpkg` installs for 32 bit binaries and will use the latest version of Visual C++ installed on your machine. If you develop 64 bit software you must @@ -44,9 +42,7 @@ of `vcpkg` if you want to compile for an older version of a compiler. You are now ready to install \cgal: -\code{.sh} - C:\dev\vcpkg> ./vcpkg.exe install cgal -\endcode + C:\dev\vcpkg> ./vcpkg.exe install cgal This will take several minutes as it downloads \mpir (a fork of \gmp), \mpfr, all boost header files, and it will compile \mpir and \mpfr, as well @@ -56,7 +52,6 @@ subdirectory `C:\dev\vcpkg\installed\x64-windows`. Note that \cgal is a header-only library, and there are therefore no `lib` or `dll` files for \cgal. - \subsection ssec-vcpkg-compile-example Compiling an Example In this section we show how to compile a program that uses \cgal. @@ -77,13 +72,12 @@ Gathering all this information is called *configuration* and we use *CMake* as c The end of the process is marked by the generation of a Visual \cpp solution and a project file that you can use to build your program. -\code{.sh} - C:\Users\Me\CGAL-5.0> cd examples\Triangulation_2 - C:\Users\Me\CGAL-5.0\examples\Triangulation_2> mkdir build - C:\Users\Me\CGAL-5.0\examples\Triangulation_2> cd build - C:\Users\Me\CGAL-5.0\examples\Triangulation_2\build> cmake-gui .. # cmake-gui is the graphical interface for cmake, which we recommend to use -\endcode + C:\Users\Me\CGAL-\cgalReleaseNumber> cd examples\Triangulation_2 + C:\Users\Me\CGAL-\cgalReleaseNumber\examples\Triangulation_2> mkdir build + C:\Users\Me\CGAL-\cgalReleaseNumber\examples\Triangulation_2> cd build + C:\Users\Me\CGAL-\cgalReleaseNumber\examples\Triangulation_2\build> cmake-gui .. +The command `cmake-gui` launches the graphical interface for `cmake`. When you hit the *Configure* button, you must:
      • specify the *Generator* (e.g., Visual Studio 16 2019),
      • @@ -96,31 +90,24 @@ You will see entries for where header files and libraries are taken from. \subsubsection sssect-vcpkg-additional-dependencies Additional Dependencies -Some \cgal packages also have additional dependencies. During the configuration -of the above examples, you may have observed the following message: +Some \cgal packages also have additional dependencies. For example, during the configuration process +above, you may have observed the following message: -\code{.sh} - NOTICE: The example draw_triangulation_2 requires Qt and will not be compiled -\endcode + NOTICE: The example draw_triangulation_2 requires Qt and will not be compiled \cgal is a library of algorithms and data structures and as such does not depend on `Qt`. However, one of the examples in the Triangulation_2 package does require `Qt` for visualization purposes. If you already have `Qt` installed, you can simply fill in the requested CMake variables and paths. Otherwise, you can also install it using `vcpkg`: -\code{.sh} - C:\dev\vcpkg> .\vcpkg.exe install qt5 -\endcode + C:\dev\vcpkg> ./vcpkg.exe install qt5 Remember to specify `--triplet` or the related environment variable in case you target 64-bit applications. As Qt5 is modular and as the \cgal examples and demos use only some of these modules you can save download and compilation time by specifying an *installation option*: -\code{.sh} - C:\dev\vcpkg> ./vcpkg.exe install cgal [qt] -\endcode - + C:\dev\vcpkg> ./vcpkg.exe install cgal [qt] In both cases, when you start `cmake-gui` again and hit the *Configure* button, the CMake variables and paths concerning Qt should now be filled. @@ -139,44 +126,44 @@ the location of third-party software. \subsubsection sssect-vcpkg-compilation Compilation of an Example -Hit the *Generate* button, and you will find the file `Triangulation_2_examples.sln` -in the directory `C:\Users\Me\CGAL-5.0\examples\Triangulation_2\build`. +Once the configuration process is successful, hit the *Generate* button, +and you will find the file `Triangulation_2_examples.sln` +in the directory `C:\Users\Me\CGAL-\cgalReleaseNumber\examples\Triangulation_2\build`. Double-click it to open it. There is one project per `.cpp` file in the directory. Compile them all, or just the one you are interested in. -\subsection subsect-vpckg-my-code Configuring and Compiling My Code Using CGAL +\subsection subsect-vpckg-my-code Configuring and Compiling Your Code Using CGAL Configuring and compiling your own code is practically the same as for \cgal examples if you use `cmake`. Running `cmake` (or `cmake-gui`) requires a `CMakeLists.txt` file. This file is automatically provided for all examples and demos of \cgal. For your own programs, you are advised to look at the `CMakeLists.txt` files in the example -folder of the package that you are using to learn how to specify \cgal and additional third party +folder of the package(s) that you are using to learn how to specify \cgal and additional third party dependencies. \section install-with-installer Installing with the CGAL Installer You can download and run `CGAL-\cgalReleaseNumber``-Setup.exe` from https://www.cgal.org/download/windows.html. -It is a self extracting executable that downloads the \cgal header files, and optionally the source code of the +It is a self-extracting executable that downloads the \cgal header files, and optionally the source code of the examples and demos. Additionally, it can download precompiled versions of \gmp and \mpfr. \subsection ssect-installer-boost Installing Boost -Binary versions of `Boost` are available on SourceForge. - +`Boost` is a mandatory dependency of \cgal. Binary versions of `Boost` are available on +SourceForge. The `Boost` installers install both `Boost` headers and precompiled libraries. Please note that the \cgal project is not responsible for the files provided on this website. When \cgal \cgalReleaseNumber was released, the latest version of `Boost` was 1.71. +A typical installation of `Boost` would consist of the following steps:
        • Download and run the file boost_1_71_0-msvc-XX.Y-64.exe (where XX.Y = 14.0 for VC 2015, XX.Y = 14.1 for 2017, XX.Y = 14.2 for VC 2019).
        • Extract the files to a new directory, e.g. `c:\dev\libboost_1_71_0`.
        • Set the following two environment variables to point respectively to the path of the libraries and the headers - -\code{.sh} - BOOST_LIBRARYDIR=C:\dev\libboost_1_71_0\lib64-msvc-XX.Y - BOOST_INCLUDEDIR=C:\dev\libboost_1_71_0 -\endcode - +
            +
          • `BOOST_LIBRARYDIR = C:\dev\libboost_1_71_0\lib64-msvc-XX.Y`
          • +
          • `BOOST_INCLUDEDIR = C:\dev\libboost_1_71_0`
          • +
          as this will help `cmake` to find Boost.
        • Add the path to the Boost `dlls` (`C:\dev\libboost_1_71_0\lib64-msvc-XX.Y`) files to the `PATH` environment variable.
        @@ -186,15 +173,15 @@ as this will help `cmake` to find Boost. Download and run `CGAL-\cgalReleaseNumber``-Setup.exe` from https://www.cgal.org/download/windows.html. It is a self extracting executable that downloads the \cgal header files, and optionally the source code of the -examples and demos. Additionally, it can download the precompiled versions of \gmp and \mpfr. You must -specify if yoy want the 32 or the 64 bit versions of these two libraries. +examples and demos. Additionally, it can download the precompiled versions of \gmp and \mpfr. You must +specify if you want the 32 or the 64 bit versions of these two libraries. -\cgal being a header-only library, there is no need to compile it. Set the environment variable `CGAL_DIR` to `C:\dev\CGAL-5.0`, -as this will help `cmake` to find \cgal. +Setting the environment variable `CGAL_DIR` to `C:\dev\CGAL-\cgalReleaseNumber` is a good idea +to help `cmake` to find \cgal during the configuration process, detailed in the next section. \subsection ssect-installer-compile-example Compiling an Example -We assume you have downloaded the examples with the \cgal Installer. +We assume that you have downloaded the examples with the \cgal Installer. Before building anything using \cgal, you have to choose the compiler/linker, set compiler and linker flags, specify which third-party libraries you want to use and where they can be found. @@ -205,14 +192,13 @@ download it). The end of the process is marked by the generation of a Visual \cpp solution and a project file that you can use to build your program. -\code{.sh} - C:\dev\CGAL-5.0> cd examples\Triangulation_2 - C:\dev\CGAL-5.0\examples\Triangulation_2> mkdir build - C:\dev\CGAL-5.0\examples\Triangulation_2> cd build - C:\dev\CGAL-5.0\examples\Triangulation_2\build> cmake-gui .. # cmake-gui is the graphical interface for cmake, which we recommend to use -\endcode + C:\dev\CGAL-\cgalReleaseNumber> cd examples\Triangulation_2 + C:\dev\CGAL-\cgalReleaseNumber\examples\Triangulation_2> mkdir build + C:\dev\CGAL-\cgalReleaseNumber\examples\Triangulation_2> cd build + C:\dev\CGAL-\cgalReleaseNumber\examples\Triangulation_2\build> cmake-gui .. -When you hit the *Configure* button you must: +The command `cmake-gui` launches the graphical interface for `cmake`. +When you hit the *Configure* button, you must:
        • Specify the *Generator*, e.g., Visual Studio 16 2019), and
        • specify an *Optional Platform* (`x64` in case you want to create 64 bit binaries).
        • @@ -222,16 +208,15 @@ You will see entries for where header files and libraries are taken from. \subsubsection ssect-installer-additional-dependencies Additional Dependencies -Individual \cgal packages may also have additional dependencies. During the configuration -of the above examples, you may have observed the following message: +Some \cgal packages also have additional dependencies. For example, during the configuration process +above, you may have observed the following message: -\code{.sh} - NOTICE: The example draw_triangulation_2 requires Qt and will not be compiled -\endcode + NOTICE: The example draw_triangulation_2 requires Qt and will not be compiled \cgal is a library of algorithms and data structures and as such does -not depend on Qt. However, one of the examples does for visualization purposes only. Either you -have Qt installed and you can fill in the requested CMake variables, or we install it now. +not depend on `Qt`. However, one of the examples does for visualization purposes only. Either you +have Qt installed and you can fill in the requested CMake variables, or you must install it. +A typical `Qt` installation would consist of the following steps:
          • @@ -242,10 +227,11 @@ Download and install the Qt library for open source development package for your as this will help `cmake` to find Qt.
          • Add the bin directory of Qt, e.g. add `C:\dev\Qt\Qt5.13.1\msvcXXXX_YY\bin` to `PATH`, where `XXXX_YY` is something like `vc2017_64`. To avoid any conflict with another dll with the same name from another folder, add this path as the first in the list.
          • -
          • When you start `cmake-gui` again and hit the *Configure* button, -the CMake variables concerning Qt should now be filled.
          +Once you have installed `Qt`, the CMake variables concerning `Qt` should now be filled when you +press *Configure* in the \cgal directory. + You must follow a similar process for other dependencies (see page \ref thirdparty for information on supported versions of third party libraries as well as download links) and fill the missing information within the `CMake` interface until configuration is successful (no more red lines indicating @@ -259,10 +245,11 @@ the location of third-party software. \subsubsection sssect-installer-compilation Compilation of an Example -Hit the *Generate* button, and you will find the file `Triangulation_2_examples.sln` -in the directory `C:\dev\CGAL-5.0\examples\Triangulation_2\build`. -Double click in order to open it. You will see one project per `.cpp` file. -Compile them all or just the one you are interested in. +Once the configuration process is successful, hit the *Generate* button, +and you will find the file `Triangulation_2_examples.sln` +in the directory `C:\dev\CGAL-\cgalReleaseNumber\examples\Triangulation_2\build`. +Double-click it in order to open it. You will see one project per `.cpp` file. +Compile them all, or just the one you are interested in. \subsection subsect-installer-my-code Configuring and Compiling My Code Using CGAL @@ -270,7 +257,7 @@ Configuring and compiling your own code is practically the same as for \cgal exa if you use `cmake`. Running `cmake` (or `cmake-gui`) requires a `CMakeLists.txt` file. This file is automatically provided for all examples and demos of \cgal. For your own programs, you are advised to look at the `CMakeLists.txt` files in the example -folder of the package that you are using to learn how to specify \cgal and additional third party +folder of the package(s) that you are using to learn how to specify \cgal and additional third party dependencies. \section install-with-tarball Installing from the Source Archive diff --git a/README.md b/README.md index 2f816f729cb..0166c3f78ae 100644 --- a/README.md +++ b/README.md @@ -15,7 +15,7 @@ Getting Started with CGAL ========================= **Since version 5.0, CGAL is a header-only library, meaning that -it is no longer needed to build or install CGAL before it can be used.** +it is no longer needed to build CGAL libraries before it can be used.** Head over to the [CGAL manual](https://doc.cgal.org/latest/Manual/general_intro.html) for usage guides and tutorials that will get you started smoothly. From 3434fd88734f84926a803806b97801812d0e0695 Mon Sep 17 00:00:00 2001 From: Maxime Gimeno Date: Fri, 25 Oct 2019 15:55:22 +0200 Subject: [PATCH 240/363] fix assetions --- .../Intersections_3/test_intersections_3.cpp | 40 +++++++++---------- 1 file changed, 20 insertions(+), 20 deletions(-) diff --git a/Intersections_3/test/Intersections_3/test_intersections_3.cpp b/Intersections_3/test/Intersections_3/test_intersections_3.cpp index 12c0e0db629..d2851243da8 100644 --- a/Intersections_3/test/Intersections_3/test_intersections_3.cpp +++ b/Intersections_3/test/Intersections_3/test_intersections_3.cpp @@ -583,12 +583,12 @@ struct Test { Tr tr(P(-3, -3, 1), P(3, -3, 1), P(1.5, 6, 1)); Res res = CGAL::intersection(cub, tr); Pol* poly = boost::get >(&*res); - CGAL_assertion(poly != nullptr); - CGAL_assertion(poly->size() == 4); + assert(poly != nullptr); + assert(poly->size() == 4); if(is_exact) { - CGAL_assertion_code(for(auto& p : *poly)) - CGAL_assertion(tr.has_on(p) && cub.has_on_boundary(p)); + for(auto& p : *poly) + assert(tr.has_on(p) && cub.has_on_boundary(p)); } //tr adj to a cuboid vertex @@ -618,12 +618,12 @@ struct Test { tr = Tr(P(2, 4, 2), P(1, 3.5, -0.5), P(1, -1, 1)); res = CGAL::intersection(cub, tr); poly = boost::get >(&*res); - CGAL_assertion(poly != nullptr); - CGAL_assertion(poly->size() == 4); + assert(poly != nullptr); + assert(poly->size() == 4); if(is_exact) { - CGAL_assertion_code(for(const P& p : *poly)) - CGAL_assertion(tr.has_on(p) && cub.has_on_boundary(p)); + for(const P& p : *poly) + assert(tr.has_on(p) && cub.has_on_boundary(p)); } //cutting in half along diagonal (intersection == triangle) @@ -634,36 +634,36 @@ struct Test { tr = Tr(P(1, 1, 10), P(10, 10, 1), P(1, 1, 1)); res = CGAL::intersection(cub, tr); poly = boost::get >(&*res); - CGAL_assertion(poly != nullptr); - CGAL_assertion(poly->size() == 4); + assert(poly != nullptr); + assert(poly->size() == 4); if(is_exact) { - CGAL_assertion_code(for(const P& p : *poly)) - CGAL_assertion(tr.has_on(p) && cub.has_on_boundary(p)); + for(const P& p : *poly) + assert(tr.has_on(p) && cub.has_on_boundary(p)); } //6 points intersection tr = Tr(P(18.66, -5.4, -11.33), P(-2.41, -7.33, 19.75), P(-10.29, 20.15, -10.33)); res = CGAL::intersection(cub, tr); poly = boost::get >(&*res); - CGAL_assertion(poly != nullptr); - CGAL_assertion(poly->size() == 6); + assert(poly != nullptr); + assert(poly->size() == 6); if(is_exact) { - CGAL_assertion_code(for(const P& p : *poly)) - CGAL_assertion(tr.has_on(p) && cub.has_on_boundary(p)); + for(const P& p : *poly) + assert(tr.has_on(p) && cub.has_on_boundary(p)); } //triangle clipping a cuboid corner tr = Tr(P(1.02, 1.33, 0.62), P(1.95, 2.54, 0.95), P(0.79, 2.36, 1.92)); res = CGAL::intersection(cub, tr); Tr* tr_res = boost::get(&*res); - CGAL_assertion(tr_res != nullptr); + assert(tr_res != nullptr); if(is_exact) { - CGAL_assertion(cub.has_on_boundary((*tr_res)[0])); - CGAL_assertion(cub.has_on_boundary((*tr_res)[1])); - CGAL_assertion(cub.has_on_boundary((*tr_res)[2])); + assert(cub.has_on_boundary((*tr_res)[0])); + assert(cub.has_on_boundary((*tr_res)[1])); + assert(cub.has_on_boundary((*tr_res)[2])); } } From 0302f1b97f3c70af0ae4dcca81f6a9e9f9df32d1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mael=20Rouxel-Labb=C3=A9?= Date: Fri, 25 Oct 2019 16:22:20 +0200 Subject: [PATCH 241/363] Various fixes --- Documentation/doc/Documentation/Usage.txt | 8 +++++--- .../doc/Documentation/advanced/Installation.txt | 17 +++++++++++------ Documentation/doc/Documentation/windows.txt | 4 ++++ 3 files changed, 20 insertions(+), 9 deletions(-) diff --git a/Documentation/doc/Documentation/Usage.txt b/Documentation/doc/Documentation/Usage.txt index 54ecb3c7814..14351c4f234 100644 --- a/Documentation/doc/Documentation/Usage.txt +++ b/Documentation/doc/Documentation/Usage.txt @@ -19,7 +19,7 @@ and the compilation of an example is as simple as: Compiling your own program is similar: cd /path/to/your/program - cgal_create_CMakeLists -s your_program + path/to/cgal/Scripts/scripts/cgal_create_CMakeLists -s your_program cmake -DCMAKE_BUILD_TYPE=Release . make @@ -164,7 +164,7 @@ need to be explicitly defined. or this reason, the simplest way to manually set is to run the graphical user interface of CMake, `cmake-gui`. cd CGAL-\cgalReleaseNumber/examples/Triangulation_2 - cmake-gui -CMAKE_BUILD_TYPE=Release . + cmake-gui . After the `CMake` window opens, press 'Configure'. A dialog will pop up and you will have to choose what shall be generated. After you have made your choice and pressed 'Finish', you will see @@ -183,6 +183,8 @@ If so, the page \ref configurationvariables lists variables which can be used to the location of third-party software. \cgalAdvancedEnd +If you do not need to debug, you should set the variable `CMAKE_BUILD_TYPE` to `Release`. + \subsection usage_configuring_external Configuring an External Program Running `cmake` (or `cmake-gui`) requires a `CMakeLists.txt` file. This file is automatically provided @@ -193,7 +195,7 @@ see Section \ref devman_create_cgal_CMakeLists. Using this shell-script, the process of configuring a user's program called `your_program.cpp` amounts to: cd /path/to/your/program - cgal_create_CMakeLists -s your_program + path/to/cgal/Scripts/scripts/cgal_create_CMakeLists -s your_program cmake -DCGAL_DIR=$HOME/CGAL-\cgalReleaseNumber -CMAKE_BUILD_TYPE=Release . Note that the script `cgal_create_CMakeLists` creates a very coarse `CMakeLists.txt` file which diff --git a/Documentation/doc/Documentation/advanced/Installation.txt b/Documentation/doc/Documentation/advanced/Installation.txt index 6afd8618d1b..50fe9a3c408 100644 --- a/Documentation/doc/Documentation/advanced/Installation.txt +++ b/Documentation/doc/Documentation/advanced/Installation.txt @@ -20,12 +20,12 @@ Ideally, compiling and installing \cgal, as well as compiling some examples ship cd $HOME/CGAL-\cgalReleaseNumber mkdir build cd build - cmake -DCMAKE_BUILD_TYPE=Release .. # configure CGAL - make # build CGAL - make install # install CGAL - cd examples/Triangulation_2 # go to an example directory - cmake -DCGAL_DIR=$HOME/CGAL-\cgalReleaseNumber/build -DCMAKE_BUILD_TYPE=Release . # configure the examples - make # build the examples + cmake -DCGAL_HEADER_ONLY=OFF -DCMAKE_BUILD_TYPE=Release .. # configure CGAL + make # build CGAL + make install # install CGAL + cd examples/Triangulation_2 # go to an example directory + cmake -DCGAL_DIR=$CMAKE_INSTALLED_PREFIX/lib/CGAL -DCMAKE_BUILD_TYPE=Release . # configure the examples + make # build the examples In a less ideal world, you might have to install some required tools and third-party libraries. This is what this page is about. @@ -143,6 +143,11 @@ Providing information and pressing *Configure* goes on until all entries are grayed. You are now ready to press *Generate*. Once this is done, you can quit `cmake-gui`. +Since you intend to build CGAL libraries, you should also ensure that the variable +`CGAL_HEADER_ONLY` has not been set. + +If you do not need to debug, you should set the variable `CMAKE_BUILD_TYPE` to `Release`. + \subsection installation_configuring_cmd Configuring CGAL with the cmake Command-Line Tool Alternatively, you can run the command-line tool called `cmake`. diff --git a/Documentation/doc/Documentation/windows.txt b/Documentation/doc/Documentation/windows.txt index cc01f5df6cc..2594f91ff94 100644 --- a/Documentation/doc/Documentation/windows.txt +++ b/Documentation/doc/Documentation/windows.txt @@ -88,6 +88,8 @@ where you have installed `vcpkg`, e.g. `C:/dev/vcpkg/scripts/buildsystems/vcpkg. Once the configuration process is done, tick *Advanced* and *Grouped* in `cmake-gui`. You will see entries for where header files and libraries are taken from. +If you do not need to debug, you should set the variable `CMAKE_BUILD_TYPE` to `Release`. + \subsubsection sssect-vcpkg-additional-dependencies Additional Dependencies Some \cgal packages also have additional dependencies. For example, during the configuration process @@ -206,6 +208,8 @@ When you hit the *Configure* button, you must: Once the configuration is done, tick `Advanced` and `Grouped` in `cmake-gui`. You will see entries for where header files and libraries are taken from. +If you do not need to debug, you should set the variable `CMAKE_BUILD_TYPE` to `Release`. + \subsubsection ssect-installer-additional-dependencies Additional Dependencies Some \cgal packages also have additional dependencies. For example, during the configuration process From d715ddd148c48dce670118774635484605d7bcfc Mon Sep 17 00:00:00 2001 From: Marc Glisse Date: Fri, 25 Oct 2019 14:38:26 +0200 Subject: [PATCH 242/363] Properly canonicalize the result of a subtraction in Mpzf 1000-999=0001, there are multiple leading 0s to remove. --- Number_types/include/CGAL/Mpzf.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Number_types/include/CGAL/Mpzf.h b/Number_types/include/CGAL/Mpzf.h index bcf2c480c87..f54a0cc85d7 100644 --- a/Number_types/include/CGAL/Mpzf.h +++ b/Number_types/include/CGAL/Mpzf.h @@ -672,7 +672,7 @@ struct Mpzf { rdata=Mpzf_impl::fill_n_ptr(rdata,xexp-absysize,-1); mpn_sub_1(rdata, xdata, absxsize, 1); res.size=absxsize+xexp; - if(res.data()[res.size-1]==0) --res.size; + while(/*res.size>0&&*/res.data()[res.size-1]==0) --res.size; if(xsize<0) res.size=-res.size; return res; } else { From 0ece0ad5bfc89421c9cc226edf52dfba1ec80fcd Mon Sep 17 00:00:00 2001 From: Laurent Rineau Date: Fri, 25 Oct 2019 16:38:57 +0200 Subject: [PATCH 243/363] typo --- Documentation/doc/Documentation/windows.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Documentation/doc/Documentation/windows.txt b/Documentation/doc/Documentation/windows.txt index 2594f91ff94..a1b641f7431 100644 --- a/Documentation/doc/Documentation/windows.txt +++ b/Documentation/doc/Documentation/windows.txt @@ -109,7 +109,7 @@ Remember to specify `--triplet` or the related environment variable in case you As Qt5 is modular and as the \cgal examples and demos use only some of these modules you can save download and compilation time by specifying an *installation option*: - C:\dev\vcpkg> ./vcpkg.exe install cgal [qt] + C:\dev\vcpkg> ./vcpkg.exe install cgal[qt] In both cases, when you start `cmake-gui` again and hit the *Configure* button, the CMake variables and paths concerning Qt should now be filled. From db7ca5e3d1390157ee2b06eb070e4948f1da92d5 Mon Sep 17 00:00:00 2001 From: Marc Glisse Date: Sat, 26 Oct 2019 18:36:44 +0200 Subject: [PATCH 244/363] Complete (?) fix for NaN intervals I hope the slowdown caused by this branch is not too bad... --- Number_types/include/CGAL/Interval_nt.h | 13 +++++++++++-- Number_types/test/Number_types/Interval_nt_new.cpp | 14 ++++++++++++++ 2 files changed, 25 insertions(+), 2 deletions(-) diff --git a/Number_types/include/CGAL/Interval_nt.h b/Number_types/include/CGAL/Interval_nt.h index 41859a8d287..f0f4eb6dc0e 100644 --- a/Number_types/include/CGAL/Interval_nt.h +++ b/Number_types/include/CGAL/Interval_nt.h @@ -645,6 +645,7 @@ private: // b<=0 [a.sup()*b.inf(); a.inf()*b.sup()] // b~=0 [a.sup()*b.inf(); a.sup()*b.sup()] double aa = a.inf(), bb = a.sup(); + if (bb <= 0.) return 0.; // In case b has an infinite bound, avoid NaN. if (b.inf() < 0.0) { aa = bb; @@ -670,8 +671,11 @@ private: else // 0 \in a { if (b.inf()>=0.0) // b>=0 - return IA(-CGAL_IA_MUL(-a.inf(), b.sup()), - CGAL_IA_MUL( a.sup(), b.sup())); + if (b.sup()<=0.0) + return 0.; // In case a has an infinite bound, avoid NaN. + else + return IA(-CGAL_IA_MUL(-a.inf(), b.sup()), + CGAL_IA_MUL( a.sup(), b.sup())); if (b.sup()<=0.0) // b<=0 return IA(-CGAL_IA_MUL( a.sup(), -b.inf()), CGAL_IA_MUL(-a.inf(), -b.inf())); @@ -689,6 +693,7 @@ private: Interval_nt operator* (double a, Interval_nt b) { + CGAL_assertion(is_finite(a)); // return Interval_nt(a)*b; Internal_protector P; if (a < 0) { a = -a; b = -b; } @@ -698,8 +703,12 @@ private: __m128d bb = IA_opacify128_weak(b.simd()); __m128d aa = _mm_set1_pd(IA_opacify(a)); __m128d r = _mm_mul_pd(aa, bb); + // In case a is 0 and b has an infinite bound. This returns an interval + // larger than necessary, but is likely faster to produce. + r = _mm_min_pd(r,largest().simd()); return IA(IA_opacify128(r)); #else + else if (!(a > 0)) return 0.; // We could test this before the SSE block and remove the minpd line. return IA(-CGAL_IA_MUL(a, -b.inf()), CGAL_IA_MUL(a, b.sup())); #endif } diff --git a/Number_types/test/Number_types/Interval_nt_new.cpp b/Number_types/test/Number_types/Interval_nt_new.cpp index eee594ce126..74ee4e563f1 100644 --- a/Number_types/test/Number_types/Interval_nt_new.cpp +++ b/Number_types/test/Number_types/Interval_nt_new.cpp @@ -5,6 +5,7 @@ #include #include #include +#include #define CGAL_catch_error(expr, error) \ { \ @@ -159,6 +160,19 @@ int main() { CGAL_catch_error((bool)(I>=J),CGAL::Uncertain_conversion_exception&); CGAL_catch_error((bool)(I<=J),CGAL::Uncertain_conversion_exception&); } + { // Multiplication + const double inf = std::numeric_limits::infinity(); + // For CGAL's purposes, [0,0]*anything is 0, but we tolerate larger intervals if they can be produced faster. + Interval all = Interval::largest(); + Interval zero = 0; + for (Interval I : { all*zero, zero*all, all*0., 0.*all }) + assert(I.inf()<=0 && I.sup()>=0); + // This should be [0,inf], but again we tolerate more. + Interval a(0,1); + Interval b(1,inf); + for (Interval I : { a*b, b*a }) + assert(I.inf()<=0 && I.sup()==inf); + } {// external functions on Intervals // functions (abs, square, sqrt, pow) {//abs From b8953ab7490e8745fe575d53f0f4fde08bd399f1 Mon Sep 17 00:00:00 2001 From: Marc Glisse Date: Sun, 27 Oct 2019 23:26:01 +0100 Subject: [PATCH 245/363] More tests for NaN interval multiplication --- Number_types/test/Number_types/Interval_nt_new.cpp | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/Number_types/test/Number_types/Interval_nt_new.cpp b/Number_types/test/Number_types/Interval_nt_new.cpp index 74ee4e563f1..291e4e41d23 100644 --- a/Number_types/test/Number_types/Interval_nt_new.cpp +++ b/Number_types/test/Number_types/Interval_nt_new.cpp @@ -162,16 +162,20 @@ int main() { } { // Multiplication const double inf = std::numeric_limits::infinity(); - // For CGAL's purposes, [0,0]*anything is 0, but we tolerate larger intervals if they can be produced faster. Interval all = Interval::largest(); Interval zero = 0; - for (Interval I : { all*zero, zero*all, all*0., 0.*all }) - assert(I.inf()<=0 && I.sup()>=0); - // This should be [0,inf], but again we tolerate more. Interval a(0,1); Interval b(1,inf); - for (Interval I : { a*b, b*a }) + Interval c(-1,inf); + Interval d(0,inf); + // For CGAL's purposes, [0,0]*anything is 0, but we tolerate larger intervals if they can be produced faster. + for (Interval I : { all*zero, zero*all, all*0., 0.*all, b*zero, zero*b, -b*zero, zero*-b, c*zero, zero*c, -c*zero, zero*-c }) + assert(I.inf()<=0 && I.sup()>=0); + // This should be [0,inf], but again we tolerate more. + for (Interval I : { a*b, b*a, -a*-b, -b*-a, d*d, -d*-d }) assert(I.inf()<=0 && I.sup()==inf); + for (Interval I : { all*a, a*all, all*-a, -a*all }) + assert(I.inf()==-inf && I.sup()==inf); } {// external functions on Intervals // functions (abs, square, sqrt, pow) From 240dea6e53de65675b549970132d07f2a4159eae Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9bastien=20Loriot?= Date: Mon, 28 Oct 2019 10:50:59 +0100 Subject: [PATCH 246/363] update header doc --- .../Developer_manual/Chapter_code_format.txt | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) diff --git a/Documentation/doc/Documentation/Developer_manual/Chapter_code_format.txt b/Documentation/doc/Documentation/Developer_manual/Chapter_code_format.txt index bc975974b27..c3d688e62b0 100644 --- a/Documentation/doc/Documentation/Developer_manual/Chapter_code_format.txt +++ b/Documentation/doc/Documentation/Developer_manual/Chapter_code_format.txt @@ -315,11 +315,8 @@ identification of the file. The file header contains:
          • a copyright notice, specifying all the years during which the file has been written or modified, as well as the owner(s) (typically the institutions -employing the authors) of this work, -
          • the corresponding license (at the moment, only LGPLv3+ and GPLv3+ -are allowed in \cgal), and a pointer to the file containing its text in the +employing the authors) of this work, a pointer to the file containing its text in the \cgal distribution, -
          • a disclaimer notice,
          • then, there are 2 keywords, which are automatically expanded at the creation of a new release:
            • \$URL\$ : canonical path to the file on github, @@ -331,6 +328,9 @@ and `SPDX-License-Identifier: LGPL-3.0-or-later OR LicenseRef-Commercial` for L optional affiliation or e-mail address.
            +Note that since \cgal 5.0 the license text is not present in headers anymore, +only SPDX tags are present. + For example and demo programs, the inclusion of the copyright notice is not necessary as this will get in the way if the program is included in the documentation. However, these files should always contain the name of @@ -371,9 +371,6 @@ Here follows what this gives for a file under the LGPL : // Max-Planck-Institute Saarbruecken (Germany), // and Tel-Aviv University (Israel). All rights reserved. // -// Licensees holding a valid commercial license may use this file in -// accordance with the commercial license agreement provided with the software. -// // This file is part of CGAL (www.cgal.org) // // $URL$ From 9af500c5e57f06aa1f7ce70bb6d1255451adc7cf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9bastien=20Loriot?= Date: Mon, 28 Oct 2019 10:52:28 +0100 Subject: [PATCH 247/363] make the message more verbose --- Scripts/developer_scripts/test_merge_of_branch | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Scripts/developer_scripts/test_merge_of_branch b/Scripts/developer_scripts/test_merge_of_branch index fca78d160d2..89a1d80a6e6 100755 --- a/Scripts/developer_scripts/test_merge_of_branch +++ b/Scripts/developer_scripts/test_merge_of_branch @@ -48,7 +48,7 @@ detect_wrong_permissions || exit 1 echo '.. Testing licenses...' detect_packages_licenses || exit 1 if ! ${git} diff --exit-code > /dev/null; then - echo '=> There are modifications in licenses:' + echo '=> There are modifications in licenses (check if all modified/added headers files contain a valid SPDX tag compatible with the one in package_info/PKG/license and that no license text is present):' ${git} status --porcelain exit 1 fi From 5a25827958336632bb6a72e1c8f5adba7f8acc1f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mael=20Rouxel-Labb=C3=A9?= Date: Mon, 28 Oct 2019 11:06:40 +0100 Subject: [PATCH 248/363] Fix extension type of archive and directory structure --- Documentation/doc/Documentation/Usage.txt | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/Documentation/doc/Documentation/Usage.txt b/Documentation/doc/Documentation/Usage.txt index 14351c4f234..65b7c4e6e2f 100644 --- a/Documentation/doc/Documentation/Usage.txt +++ b/Documentation/doc/Documentation/Usage.txt @@ -70,11 +70,11 @@ For other distributions or package manager, please consult your respective docum You can also obtain the \cgal library sources directly from https://www.cgal.org/download.html. -Once you have downloaded the file `CGAL-\cgalReleaseNumber``.tar.gz` containing the +Once you have downloaded the file `CGAL-\cgalReleaseNumber``.tar.xz` containing the \cgal sources, you have to unpack it. Under a Unix-like shell, use the command: - tar xzf CGAL-\cgalReleaseNumber.tar.gz + tar xf CGAL-\cgalReleaseNumber.tar.xz The directory `CGAL-\cgalReleaseNumber` will be created. This directory contains the following subdirectories: @@ -83,7 +83,6 @@ contains the following subdirectories: | :------------------------- | :----------| | `auxiliary` (Windows only) | precompiled \sc{Gmp} and \sc{Mpfr} for Windows | | `cmake/modules` | modules for finding and using libraries | -| `config` | configuration files for install script | | `demo` | demo programs (most of them need \sc{Qt}, geomview or other third-party products) | | `doc_html` | documentation (HTML) | | `examples` | example programs | From 23f516d6e3518f99f399f3e16bc9805cc4a98bb9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mael=20Rouxel-Labb=C3=A9?= Date: Mon, 28 Oct 2019 11:07:03 +0100 Subject: [PATCH 249/363] Fix missing 'D' in build type cmake variable definition in command line --- Documentation/doc/Documentation/Usage.txt | 4 ++-- Documentation/doc/Documentation/advanced/Installation.txt | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/Documentation/doc/Documentation/Usage.txt b/Documentation/doc/Documentation/Usage.txt index 65b7c4e6e2f..00e19f24615 100644 --- a/Documentation/doc/Documentation/Usage.txt +++ b/Documentation/doc/Documentation/Usage.txt @@ -150,7 +150,7 @@ It is also strongly recommended to set the build type variable to `Release` for if no debugging is intended. Users should thus run: cd CGAL-\cgalReleaseNumber/examples/Triangulation_2 - cmake -DCGAL_DIR=$HOME/CGAL-\cgalReleaseNumber -CMAKE_BUILD_TYPE=Release . # we are here using a release tarball + cmake -DCGAL_DIR=$HOME/CGAL-\cgalReleaseNumber -DCMAKE_BUILD_TYPE=Release . # we are here using a release tarball \subsection usage_configuring_cmake_gui Specifying Missing Dependencies @@ -195,7 +195,7 @@ the process of configuring a user's program called `your_program.cpp` amounts to cd /path/to/your/program path/to/cgal/Scripts/scripts/cgal_create_CMakeLists -s your_program - cmake -DCGAL_DIR=$HOME/CGAL-\cgalReleaseNumber -CMAKE_BUILD_TYPE=Release . + cmake -DCGAL_DIR=$HOME/CGAL-\cgalReleaseNumber -DCMAKE_BUILD_TYPE=Release . Note that the script `cgal_create_CMakeLists` creates a very coarse `CMakeLists.txt` file which might not properly encode the third party dependencies of your program. Users are advised to look diff --git a/Documentation/doc/Documentation/advanced/Installation.txt b/Documentation/doc/Documentation/advanced/Installation.txt index 50fe9a3c408..e2f095f6e91 100644 --- a/Documentation/doc/Documentation/advanced/Installation.txt +++ b/Documentation/doc/Documentation/advanced/Installation.txt @@ -298,7 +298,7 @@ the process of configuring a user's program called `your_program.cpp` amounts to cd /path/to/your/program cgal_create_CMakeLists -s your_program - cmake -DCGAL_DIR=XXXXXX -CMAKE_BUILD_TYPE=Release . + cmake -DCGAL_DIR=XXXXXX -DCMAKE_BUILD_TYPE=Release . make In order to configure a program, you need to indicate the location of the \cgal configuration file From 53d4c9b580ecf0d9c5e1cdec2f9cd5146ff9a6fa Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mael=20Rouxel-Labb=C3=A9?= Date: Mon, 28 Oct 2019 11:29:08 +0100 Subject: [PATCH 250/363] Simplify 'Hash_handles_with_or_without_timestamps' (use 'Get_time_stamper') --- .../IO/Complex_3_in_triangulation_3_to_vtk.h | 2 +- Mesh_3/include/CGAL/IO/File_maya.h | 2 +- Mesh_3/include/CGAL/IO/File_tetgen.h | 2 +- .../IO/facets_in_complex_3_to_triangle_mesh.h | 2 +- Mesh_3/include/CGAL/Mesh_3/C3T3_helpers.h | 2 +- .../Mesh_3/Detect_polylines_in_polyhedra.h | 2 +- Mesh_3/include/CGAL/Mesh_3/Lloyd_move.h | 2 +- .../Mesh_complex_3_in_triangulation_3_base.h | 2 +- .../CGAL/Mesh_3/Mesh_global_optimizer.h | 2 +- .../CGAL/Mesh_3/Protect_edges_sizing_field.h | 3 +- .../CGAL/Mesh_3/Refine_facets_manifold_base.h | 4 +- Mesh_3/include/CGAL/Mesh_3/Sliver_perturber.h | 3 +- .../CGAL/Mesh_3/Triangulation_helpers.h | 2 +- .../include/CGAL/Mesh_3/vertex_perturbation.h | 1 + .../CGAL/Mesh_complex_3_in_triangulation_3.h | 2 +- .../Protect_edges_sizing_field.h | 3 +- .../include/CGAL/refine_periodic_3_mesh_3.h | 3 +- .../Hash_handles_with_or_without_timestamps.h | 50 ------------------- STL_Extension/include/CGAL/Time_stamper.h | 11 ++++ 19 files changed, 29 insertions(+), 71 deletions(-) delete mode 100644 STL_Extension/include/CGAL/Hash_handles_with_or_without_timestamps.h diff --git a/Mesh_3/include/CGAL/IO/Complex_3_in_triangulation_3_to_vtk.h b/Mesh_3/include/CGAL/IO/Complex_3_in_triangulation_3_to_vtk.h index 787bf3c7640..c18be2bc370 100644 --- a/Mesh_3/include/CGAL/IO/Complex_3_in_triangulation_3_to_vtk.h +++ b/Mesh_3/include/CGAL/IO/Complex_3_in_triangulation_3_to_vtk.h @@ -15,7 +15,7 @@ #include -#include +#include #include #include diff --git a/Mesh_3/include/CGAL/IO/File_maya.h b/Mesh_3/include/CGAL/IO/File_maya.h index 0eb232d0544..dfb7398d498 100644 --- a/Mesh_3/include/CGAL/IO/File_maya.h +++ b/Mesh_3/include/CGAL/IO/File_maya.h @@ -14,7 +14,7 @@ #include -#include +#include #include #include diff --git a/Mesh_3/include/CGAL/IO/File_tetgen.h b/Mesh_3/include/CGAL/IO/File_tetgen.h index ef00fad211b..9feaa354ef9 100644 --- a/Mesh_3/include/CGAL/IO/File_tetgen.h +++ b/Mesh_3/include/CGAL/IO/File_tetgen.h @@ -15,7 +15,7 @@ #include -#include +#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 718e7baab0c..132df01c693 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 @@ -18,9 +18,9 @@ #include #include -#include #include #include +#include #include #include diff --git a/Mesh_3/include/CGAL/Mesh_3/C3T3_helpers.h b/Mesh_3/include/CGAL/Mesh_3/C3T3_helpers.h index 3f4421ed3e9..a27c9556cb0 100644 --- a/Mesh_3/include/CGAL/Mesh_3/C3T3_helpers.h +++ b/Mesh_3/include/CGAL/Mesh_3/C3T3_helpers.h @@ -26,7 +26,7 @@ #include #include -#include +#include #include #include #include diff --git a/Mesh_3/include/CGAL/Mesh_3/Detect_polylines_in_polyhedra.h b/Mesh_3/include/CGAL/Mesh_3/Detect_polylines_in_polyhedra.h index d71d60c1195..226421ef980 100644 --- a/Mesh_3/include/CGAL/Mesh_3/Detect_polylines_in_polyhedra.h +++ b/Mesh_3/include/CGAL/Mesh_3/Detect_polylines_in_polyhedra.h @@ -19,7 +19,7 @@ #include #include #include -#include +#include #include #include diff --git a/Mesh_3/include/CGAL/Mesh_3/Lloyd_move.h b/Mesh_3/include/CGAL/Mesh_3/Lloyd_move.h index 1bed83025b7..387f1e9c1f1 100644 --- a/Mesh_3/include/CGAL/Mesh_3/Lloyd_move.h +++ b/Mesh_3/include/CGAL/Mesh_3/Lloyd_move.h @@ -23,7 +23,7 @@ #include #include -#include +#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 e621c87d4b1..b2cd9715ee5 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 @@ -31,7 +31,7 @@ #include #include #include -#include +#include #include #include diff --git a/Mesh_3/include/CGAL/Mesh_3/Mesh_global_optimizer.h b/Mesh_3/include/CGAL/Mesh_3/Mesh_global_optimizer.h index 0e4145b26f7..cd4310bf5fb 100644 --- a/Mesh_3/include/CGAL/Mesh_3/Mesh_global_optimizer.h +++ b/Mesh_3/include/CGAL/Mesh_3/Mesh_global_optimizer.h @@ -29,8 +29,8 @@ #include #include #include +#include -#include #include #include diff --git a/Mesh_3/include/CGAL/Mesh_3/Protect_edges_sizing_field.h b/Mesh_3/include/CGAL/Mesh_3/Protect_edges_sizing_field.h index 7516d6e6656..3fdc4cf0b0b 100644 --- a/Mesh_3/include/CGAL/Mesh_3/Protect_edges_sizing_field.h +++ b/Mesh_3/include/CGAL/Mesh_3/Protect_edges_sizing_field.h @@ -41,8 +41,7 @@ #endif #include -#include -#include +#include #include #include #include diff --git a/Mesh_3/include/CGAL/Mesh_3/Refine_facets_manifold_base.h b/Mesh_3/include/CGAL/Mesh_3/Refine_facets_manifold_base.h index 8939cbce2a3..1568ea059aa 100644 --- a/Mesh_3/include/CGAL/Mesh_3/Refine_facets_manifold_base.h +++ b/Mesh_3/include/CGAL/Mesh_3/Refine_facets_manifold_base.h @@ -19,9 +19,9 @@ #include -#include -#include #include +#include +#include #include #include diff --git a/Mesh_3/include/CGAL/Mesh_3/Sliver_perturber.h b/Mesh_3/include/CGAL/Mesh_3/Sliver_perturber.h index 9d5a69d4c2b..ac6e886e4a3 100644 --- a/Mesh_3/include/CGAL/Mesh_3/Sliver_perturber.h +++ b/Mesh_3/include/CGAL/Mesh_3/Sliver_perturber.h @@ -42,8 +42,7 @@ #include #include #include -#include -#include +#include #include #include diff --git a/Mesh_3/include/CGAL/Mesh_3/Triangulation_helpers.h b/Mesh_3/include/CGAL/Mesh_3/Triangulation_helpers.h index 8ac0c8e2340..5eafdc611a1 100644 --- a/Mesh_3/include/CGAL/Mesh_3/Triangulation_helpers.h +++ b/Mesh_3/include/CGAL/Mesh_3/Triangulation_helpers.h @@ -21,7 +21,7 @@ #include #include -#include +#include #include #include diff --git a/Mesh_3/include/CGAL/Mesh_3/vertex_perturbation.h b/Mesh_3/include/CGAL/Mesh_3/vertex_perturbation.h index 82bafa3f43b..07ceaabc6d0 100644 --- a/Mesh_3/include/CGAL/Mesh_3/vertex_perturbation.h +++ b/Mesh_3/include/CGAL/Mesh_3/vertex_perturbation.h @@ -24,6 +24,7 @@ #include #include +#include #ifdef CGAL_MESH_3_PERTURBER_VERBOSE #include 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 9ab9148c55f..954478ccee7 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 @@ -22,10 +22,10 @@ #include #include -#include #include #include #include +#include #include #include diff --git a/Periodic_3_mesh_3/include/CGAL/Periodic_3_mesh_3/Protect_edges_sizing_field.h b/Periodic_3_mesh_3/include/CGAL/Periodic_3_mesh_3/Protect_edges_sizing_field.h index ad881bb4017..e27c762ed34 100644 --- a/Periodic_3_mesh_3/include/CGAL/Periodic_3_mesh_3/Protect_edges_sizing_field.h +++ b/Periodic_3_mesh_3/include/CGAL/Periodic_3_mesh_3/Protect_edges_sizing_field.h @@ -40,13 +40,12 @@ #include #include -#include -#include #include #include #include #include #include +#include #include diff --git a/Periodic_3_mesh_3/include/CGAL/refine_periodic_3_mesh_3.h b/Periodic_3_mesh_3/include/CGAL/refine_periodic_3_mesh_3.h index 9c50a2691c0..acb3b35decd 100644 --- a/Periodic_3_mesh_3/include/CGAL/refine_periodic_3_mesh_3.h +++ b/Periodic_3_mesh_3/include/CGAL/refine_periodic_3_mesh_3.h @@ -24,8 +24,7 @@ #include #include #include - -#include +#include #include #include diff --git a/STL_Extension/include/CGAL/Hash_handles_with_or_without_timestamps.h b/STL_Extension/include/CGAL/Hash_handles_with_or_without_timestamps.h deleted file mode 100644 index 1b557a4bca0..00000000000 --- a/STL_Extension/include/CGAL/Hash_handles_with_or_without_timestamps.h +++ /dev/null @@ -1,50 +0,0 @@ -// Copyright (c) 2014-2017 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) : Laurent Rineau, -// Mael Rouxel-Labbé - -#ifndef CGAL_HASH_HANDLES_WITH_OR_WITHOUT_TIMESTAMPS_H -#define CGAL_HASH_HANDLES_WITH_OR_WITHOUT_TIMESTAMPS_H - -#include - -#include - -#include -#include - -namespace CGAL { - -struct Hash_handles_with_or_without_timestamps -{ - template - std::size_t operator()(const Handle h) const - { - typedef typename std::iterator_traits::value_type Type; - - return hash(h, Boolean_tag::value>()); - } - - template - std::size_t hash(const Handle h, Tag_false) const - { - return boost::hash_value(&*h); - } - - template - std::size_t hash(const Handle h, Tag_true) const - { - return h->time_stamp(); - } -}; - -} // namespace CGAL - -#endif // CGAL_HASH_HANDLES_WITH_OR_WITHOUT_TIMESTAMPS_H diff --git a/STL_Extension/include/CGAL/Time_stamper.h b/STL_Extension/include/CGAL/Time_stamper.h index 82961b37269..7385f4473eb 100644 --- a/STL_Extension/include/CGAL/Time_stamper.h +++ b/STL_Extension/include/CGAL/Time_stamper.h @@ -149,6 +149,17 @@ struct Get_time_stamper{ template struct Time_stamper_impl : public Get_time_stamper::type {}; +struct Hash_handles_with_or_without_timestamps +{ + template + std::size_t operator()(const Handle h) const + { + typedef typename std::iterator_traits::value_type Type; + + return Get_time_stamper::type::hash_value(&*h); + } +}; + } //end of namespace CGAL #endif // CGAL_TIME_STAMPER_H From 13a31ec9af3226cfbd0217a81153345da95739b2 Mon Sep 17 00:00:00 2001 From: Maxime Gimeno Date: Mon, 28 Oct 2019 15:32:31 +0100 Subject: [PATCH 251/363] Add a Viewer option to use a specif shader to make more obvious the orientation of the fragments in the shaded programs. --- Polyhedron/demo/Polyhedron/MainWindow.cpp | 13 +++ Polyhedron/demo/Polyhedron/Preferences.ui | 13 ++- Polyhedron/demo/Polyhedron/Viewer.cpp | 98 ++++++++++++++++++- Polyhedron/demo/Polyhedron/Viewer.h | 2 + .../shader_with_light.frag | 17 +++- .../resources/shader_with_light.frag | 24 ++++- Three/include/CGAL/Three/Viewer_interface.h | 3 + 7 files changed, 161 insertions(+), 9 deletions(-) diff --git a/Polyhedron/demo/Polyhedron/MainWindow.cpp b/Polyhedron/demo/Polyhedron/MainWindow.cpp index 9fb344a24b3..0b1a6661b6c 100644 --- a/Polyhedron/demo/Polyhedron/MainWindow.cpp +++ b/Polyhedron/demo/Polyhedron/MainWindow.cpp @@ -2275,6 +2275,11 @@ void MainWindow::on_actionPreferences_triggered() this->s_defaultPSRM = CGAL::Three::Three::modeFromName(text); }); + connect(prefdiag.backFrontColor_pushButton, &QPushButton::clicked, + this, [this](){ + qobject_cast(CGAL::Three::Three::activeViewer())->setBackFrontColors(); + }); + std::vector items; QBrush successBrush(Qt::green), errorBrush(Qt::red), @@ -2959,6 +2964,9 @@ void MainWindow::setupViewer(Viewer* viewer, SubViewer* subviewer) } viewer->setTotalPass(nb); }); + action= subviewer->findChild("actionBackFrontShading"); + connect(action, SIGNAL(toggled(bool)), + viewer, SLOT(setBackFrontShading(bool))); connect(viewer, SIGNAL(requestContextMenu(QPoint)), this, SLOT(contextMenuRequested(QPoint))); connect(viewer, SIGNAL(selected(int)), @@ -3127,6 +3135,11 @@ SubViewer::SubViewer(QWidget *parent, MainWindow* mw, Viewer* mainviewer) QAction* actionTotalPass = new QAction("Set Transparency Pass &Number...",this); actionTotalPass->setObjectName("actionTotalPass"); viewMenu->addAction(actionTotalPass); + QAction* actionBackFrontShading = new QAction("Activate Back/Front shading.",this); + actionBackFrontShading->setObjectName("actionBackFrontShading"); + actionBackFrontShading->setCheckable(true); + actionBackFrontShading->setChecked(false); + viewMenu->addAction(actionBackFrontShading); if(mainviewer) setAttribute(Qt::WA_DeleteOnClose); setWindowIcon(QIcon(":/cgal/icons/resources/menu.png")); diff --git a/Polyhedron/demo/Polyhedron/Preferences.ui b/Polyhedron/demo/Polyhedron/Preferences.ui index 34613871e8d..10a7f773f85 100644 --- a/Polyhedron/demo/Polyhedron/Preferences.ui +++ b/Polyhedron/demo/Polyhedron/Preferences.ui @@ -58,9 +58,9 @@ 0 - 0 - 278 - 499 + -96 + 275 + 528 @@ -285,6 +285,13 @@ + + + + Change Back/Front Colors... + + + diff --git a/Polyhedron/demo/Polyhedron/Viewer.cpp b/Polyhedron/demo/Polyhedron/Viewer.cpp index cc5cb24d158..bfb1a2331ad 100644 --- a/Polyhedron/demo/Polyhedron/Viewer.cpp +++ b/Polyhedron/demo/Polyhedron/Viewer.cpp @@ -50,6 +50,10 @@ public: QVector4D diffuse; QVector4D specular; float spec_power; + + //Back and Front Colors + QColor front_color; + QColor back_color; // M e s s a g e s QString message; @@ -250,12 +254,23 @@ void Viewer::doBindings() specular.split(",").at(1).toFloat(), specular.split(",").at(2).toFloat(), 1.0f); - + + QString front_color = viewer_settings.value("front_color", QString("1.0,0.0,0.0")).toString(); + d->front_color= QColor(255*front_color.split(",").at(0).toFloat(), + 255*front_color.split(",").at(1).toFloat(), + 255*front_color.split(",").at(2).toFloat(), + 1.0f); + QString back_color = viewer_settings.value("back_color", QString("0.0,0.0,1.0")).toString(); + d->back_color= QColor( 255*back_color.split(",").at(0).toFloat(), + 255*back_color.split(",").at(1).toFloat(), + 255*back_color.split(",").at(2).toFloat(), + 1.0f); d->spec_power = viewer_settings.value("spec_power", 51.8).toFloat(); d->scene = 0; d->projection_is_ortho = false; d->twosides = false; this->setProperty("draw_two_sides", false); + this->setProperty("back_front_shading", false); d->macro_mode = false; d->inFastDrawing = true; d->inDrawWithNames = false; @@ -333,6 +348,7 @@ Viewer::Viewer(QWidget* parent, is_sharing = true; d->antialiasing = antialiasing; this->setProperty("draw_two_sides", false); + this->setProperty("back_front_shading", false); this->setProperty("helpText", QString("This is a sub-viewer. It displays the scene " "from another point of view. \n ")); is_ogl_4_3 = sharedWidget->is_ogl_4_3; @@ -367,6 +383,17 @@ Viewer::~Viewer() .arg(d->specular.z())); viewer_settings.setValue("spec_power", d->spec_power); + viewer_settings.setValue("front_color", + QString("%1,%2,%3") + .arg(d->front_color.redF()) + .arg(d->front_color.greenF()) + .arg(d->front_color.blueF())); + viewer_settings.setValue("back_color", + QString("%1,%2,%3") + .arg(d->back_color.redF()) + .arg(d->back_color.greenF()) + .arg(d->back_color.blueF())); + if(d->_recentFunctions) delete d->_recentFunctions; if(d->painter) @@ -401,6 +428,13 @@ void Viewer::setTwoSides(bool b) } +void Viewer::setBackFrontShading(bool b) +{ + this->setProperty("back_front_shading", b); + update(); +} + + void Viewer::setFastDrawing(bool b) { d->inFastDrawing = b; @@ -947,7 +981,10 @@ void Viewer::attribBuffers(int program_name) const { program->setUniformValue("light_spec", d->specular); program->setUniformValue("light_amb", d->ambient); program->setUniformValue("spec_power", d->spec_power); + program->setUniformValue("front_color", d->front_color); + program->setUniformValue("back_color", d->back_color); program->setUniformValue("is_two_side", d->twosides); + program->setUniformValue("back_front_shading", this->property("back_front_shading").toBool()); break; } switch(program_name) @@ -1805,6 +1842,65 @@ void Viewer::setLighting() } } +void Viewer::setBackFrontColors() +{ + + //save current settings; + + QColor prev_front_color = d->front_color; + QColor prev_back_color = d->back_color; + QDialog *dialog = new QDialog(this); + QDialogButtonBox* buttonBox = new QDialogButtonBox(QDialogButtonBox::Ok + | QDialogButtonBox::Cancel, dialog); + + connect(buttonBox, &QDialogButtonBox::accepted, dialog, &QDialog::accept); + connect(buttonBox, &QDialogButtonBox::rejected, dialog, &QDialog::reject); + + QGridLayout* layout = new QGridLayout(dialog); + layout->addWidget(new QLabel("Front color: ",dialog),0,0); + QPalette front_palette; + front_palette.setColor(QPalette::Button, d->front_color); + QPushButton* frontButton = new QPushButton(dialog); + frontButton->setPalette(front_palette); + QPalette back_palette; + back_palette.setColor(QPalette::Button, d->back_color); + QPushButton* backButton = new QPushButton(dialog); + backButton->setPalette(back_palette); + layout->addWidget(frontButton,0,1); + layout->addWidget(new QLabel("Back color: ",dialog),1,0); + layout->addWidget(backButton,1,1); + layout->addWidget(buttonBox); + dialog->setLayout(layout); + connect(frontButton, &QPushButton::clicked, + [this, dialog, frontButton](){ + QColorDialog *color_dial = new QColorDialog(dialog); + color_dial->exec(); + QColor front_color = color_dial->selectedColor(); + QPalette palette; + palette.setColor(QPalette::Button, front_color); + frontButton->setPalette(palette); + d->front_color= front_color; + }); + connect(backButton, &QPushButton::clicked, + [this, dialog, backButton](){ + QColorDialog *color_dial = new QColorDialog(dialog); + color_dial->exec(); + QColor back_color = color_dial->selectedColor(); + QPalette palette; + palette.setColor(QPalette::Button, back_color); + backButton->setPalette(palette); + d->back_color= back_color; + + }); + if(!dialog->exec()) + { + //restore previous settings + d->front_color= prev_front_color; + d->back_color= prev_back_color; + return; + } +} + void Viewer::setGlPointSize(const GLfloat &p) { d->gl_point_size = p; } const GLfloat& Viewer::getGlPointSize() const { return d->gl_point_size; } diff --git a/Polyhedron/demo/Polyhedron/Viewer.h b/Polyhedron/demo/Polyhedron/Viewer.h index 6d33097f672..600b9a6f041 100644 --- a/Polyhedron/demo/Polyhedron/Viewer.h +++ b/Polyhedron/demo/Polyhedron/Viewer.h @@ -101,6 +101,7 @@ public Q_SLOTS: //! If b is true, facets will be ligted from both internal and external sides. //! If b is false, only the side that is exposed to the light source will be lighted. void setTwoSides(bool b) Q_DECL_OVERRIDE; + void setBackFrontShading(bool b) Q_DECL_OVERRIDE; void SetOrthoProjection( bool b) Q_DECL_OVERRIDE; //! If b is true, some items are displayed in a simplified version when moving the camera. //! If b is false, items display is never altered, even when moving. @@ -127,6 +128,7 @@ public Q_SLOTS: } void setLighting(); + void setBackFrontColors(); void messageLogged(QOpenGLDebugMessage); diff --git a/Polyhedron/demo/Polyhedron/resources/compatibility_shaders/shader_with_light.frag b/Polyhedron/demo/Polyhedron/resources/compatibility_shaders/shader_with_light.frag index 2c0b38aa039..302fa0e6123 100644 --- a/Polyhedron/demo/Polyhedron/resources/compatibility_shaders/shader_with_light.frag +++ b/Polyhedron/demo/Polyhedron/resources/compatibility_shaders/shader_with_light.frag @@ -3,6 +3,8 @@ varying highp vec4 color; varying highp vec4 fP; varying highp vec3 fN; varying highp float dist[6]; +uniform highp vec4 front_color; +uniform highp vec4 back_color; uniform highp vec4 light_pos; uniform highp vec4 light_diff; uniform highp vec4 light_spec; @@ -17,6 +19,7 @@ uniform highp float width; uniform highp float height; uniform bool comparing; uniform bool writing; +uniform bool back_front_shading; uniform sampler2D sampler; uniform highp float alpha; @@ -44,7 +47,6 @@ void main(void) { gl_FragColor = vec4(d,d,d,1.0); else { - highp vec4 my_color = vec4(color.xyz, 1.0); highp vec3 L = light_pos.xyz - fP.xyz; highp vec3 V = -fP.xyz; highp vec3 N; @@ -56,6 +58,19 @@ void main(void) { V = normalize(V); highp vec3 R = reflect(-L, N); highp vec4 diffuse; + float dot_prod = dot(N,L); + highp vec4 my_color; + if(back_front_shading) + { + if (dot_prod > 0) + my_color = front_color; + else + my_color = back_color; + } + else + { + my_color = highp vec4(color.xyz, 1.0); + } if(is_two_side == 1) diffuse = abs(dot(N,L)) * light_diff * color; else diff --git a/Polyhedron/demo/Polyhedron/resources/shader_with_light.frag b/Polyhedron/demo/Polyhedron/resources/shader_with_light.frag index 2bb3354848f..e1fbe4d1139 100644 --- a/Polyhedron/demo/Polyhedron/resources/shader_with_light.frag +++ b/Polyhedron/demo/Polyhedron/resources/shader_with_light.frag @@ -3,6 +3,8 @@ in vec4 color; in vec4 fP; in vec3 fN; in float dist[6]; +uniform vec4 front_color; +uniform vec4 back_color; uniform vec4 light_pos; uniform vec4 light_diff; uniform vec4 light_spec; @@ -17,6 +19,7 @@ uniform float width; uniform float height; uniform bool comparing; uniform bool writing; +uniform bool back_front_shading; uniform sampler2D sampler; uniform float alpha; out vec4 out_color; @@ -45,7 +48,6 @@ void main(void) { out_color = vec4(d,d,d,1.0); else { - vec4 my_color = vec4(color.xyz, 1.0); vec3 L = light_pos.xyz - fP.xyz; vec3 V = -fP.xyz; vec3 N; @@ -57,10 +59,24 @@ void main(void) { V = normalize(V); vec3 R = reflect(-L, N); vec4 diffuse; - if(is_two_side == 1) - diffuse = abs(dot(N,L)) * light_diff * color; + float dot_prod = dot(N,L); + vec4 my_color; + if(back_front_shading) + { + if (dot_prod > 0) + my_color = front_color; + else + my_color = back_color; + } else - diffuse = max(dot(N,L), 0.0) * light_diff * my_color; + { + my_color = vec4(color.xyz, 1.0); + } + if(is_two_side == 1) + diffuse = abs(dot_prod) * light_diff * color; + else + diffuse = max(dot_prod, 0.0) * light_diff * my_color; + vec4 specular = pow(max(dot(R,V), 0.0), spec_power) * light_spec; vec4 ret_color = vec4((my_color*light_amb).xyz + diffuse.xyz + specular.xyz,1); if(is_selected) diff --git a/Three/include/CGAL/Three/Viewer_interface.h b/Three/include/CGAL/Three/Viewer_interface.h index 26b0778098e..0a4ceea06fb 100644 --- a/Three/include/CGAL/Three/Viewer_interface.h +++ b/Three/include/CGAL/Three/Viewer_interface.h @@ -238,6 +238,9 @@ public Q_SLOTS: //! If b is true, faces will be ligted from both internal and external side. //! If b is false, only the side that is exposed to the light source will be lighted. virtual void setTwoSides(bool b) = 0; + //! If b is true, then a special color mask is applied to points and meshes to differenciate + //! front-faced and back-faced elements. + virtual void setBackFrontShading(bool b) =0; //! \brief Sets the fast drawing mode //! @see inFastDrawing() virtual void setFastDrawing(bool b) = 0; From abd8d035aa0131dd848520086718ccc6b8b1c265 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9bastien=20Loriot?= Date: Tue, 29 Oct 2019 08:39:55 +0100 Subject: [PATCH 252/363] improve item naming --- .../Polyhedron/Plugins/Mesh_2/Mesh_2_plugin.cpp | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/Polyhedron/demo/Polyhedron/Plugins/Mesh_2/Mesh_2_plugin.cpp b/Polyhedron/demo/Polyhedron/Plugins/Mesh_2/Mesh_2_plugin.cpp index c007f78408f..f52a2a49058 100644 --- a/Polyhedron/demo/Polyhedron/Plugins/Mesh_2/Mesh_2_plugin.cpp +++ b/Polyhedron/demo/Polyhedron/Plugins/Mesh_2/Mesh_2_plugin.cpp @@ -252,8 +252,7 @@ private: bool runMesh2 = ui.runMesh2_checkbox->isChecked(); double target_length = ui.edgeLength_dspinbox->value(); unsigned int nb_iter = ui.nbIterations_spinbox->value(); - bool runLloyd = ui.runLloyd_checkbox->isChecked(); - + bool runLloyd = runMesh2?ui.runLloyd_checkbox->isChecked():false; // wait cursor QApplication::setOverrideCursor(Qt::WaitCursor); @@ -334,11 +333,12 @@ private: } // export result as a surface_mesh item - QString iname = - polylines_items.size()==1? - polylines_items.front()->name()+QString("_meshed_"): - QString("2dmesh_"); - iname+=QString::number(target_length); + QString iname = runMesh2 ? (( polylines_items.size()==1? + polylines_items.front()->name()+QString("_meshed_"): + QString("2dmesh_") )+QString::number(target_length) ) + : ( polylines_items.size()==1? + polylines_items.front()->name()+QString("_triangulated"): + QString("polylines_triangulation") ); if (runLloyd) iname+=QString("_Lloyd_")+QString::number(nb_iter); Scene_surface_mesh_item* poly_item = new Scene_surface_mesh_item(); poly_item->setName(iname); From 81c7f53d20f2643d42fa987a3450a42c9582265c Mon Sep 17 00:00:00 2001 From: Laurent Rineau Date: Tue, 29 Oct 2019 09:45:16 +0100 Subject: [PATCH 253/363] Add braces to quiet a warning MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ``` In file included from .../include/CGAL/long_double.h:27, from .../include/CGAL/number_type_basic.h:52, from .../include/CGAL/basic.h:33, from .../include/CGAL/Cartesian/Cartesian_base.h:20, from .../include/CGAL/Simple_cartesian.h:20, from /home/cgal_tester/build/src/cmake/platforms/Fedora-32/test/AABB_tree/aabb_test_singleton_tree.cpp:4: .../include/CGAL/Interval_nt.h: In function ‘CGAL::Interval_nt CGAL::operator*(const CGAL::Interval_nt&, const CGAL::Interval_nt&)’: .../include/CGAL/Interval_nt.h:664:10: warning: suggest explicit braces to avoid ambiguous ‘else’ [-Wdangling-else] 664 | if (b.inf()>=0.0) // b>=0 | ^ ``` I have added more than the single necessary pair of braces, by symmetry. --- Number_types/include/CGAL/Interval_nt.h | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/Number_types/include/CGAL/Interval_nt.h b/Number_types/include/CGAL/Interval_nt.h index f0f4eb6dc0e..b8908f2b05b 100644 --- a/Number_types/include/CGAL/Interval_nt.h +++ b/Number_types/include/CGAL/Interval_nt.h @@ -670,15 +670,17 @@ private: } else // 0 \in a { - if (b.inf()>=0.0) // b>=0 + if (b.inf()>=0.0) { // b>=0 if (b.sup()<=0.0) return 0.; // In case a has an infinite bound, avoid NaN. else return IA(-CGAL_IA_MUL(-a.inf(), b.sup()), CGAL_IA_MUL( a.sup(), b.sup())); - if (b.sup()<=0.0) // b<=0 + } + if (b.sup()<=0.0) { // b<=0 return IA(-CGAL_IA_MUL( a.sup(), -b.inf()), CGAL_IA_MUL(-a.inf(), -b.inf())); + } // 0 \in b double tmp1 = CGAL_IA_MUL(-a.inf(), b.sup()); double tmp2 = CGAL_IA_MUL( a.sup(), -b.inf()); From ead5d7478ccb4b9c6977843c8a3e1b2dea25bf38 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mael=20Rouxel-Labb=C3=A9?= Date: Tue, 29 Oct 2019 11:00:39 +0100 Subject: [PATCH 254/363] Doc improvements --- .../doc/Documentation/Getting_started.txt | 14 +++++++- .../doc/Documentation/Third_party.txt | 4 ++- .../Tutorials/Tutorial_hello_world.txt | 2 +- .../doc/Documentation/Tutorials/Tutorials.txt | 9 ++++-- Documentation/doc/Documentation/Usage.txt | 13 ++++++-- .../advanced/Configuration_variables.txt | 5 +++ .../Documentation/advanced/Installation.txt | 6 ++-- .../doc/Documentation/advanced/advanced.txt | 8 ----- Documentation/doc/Documentation/main.txt | 32 ++++++++----------- Documentation/doc/Documentation/windows.txt | 5 ++- 10 files changed, 61 insertions(+), 37 deletions(-) delete mode 100644 Documentation/doc/Documentation/advanced/advanced.txt diff --git a/Documentation/doc/Documentation/Getting_started.txt b/Documentation/doc/Documentation/Getting_started.txt index b4759c28f95..01452b57124 100644 --- a/Documentation/doc/Documentation/Getting_started.txt +++ b/Documentation/doc/Documentation/Getting_started.txt @@ -1,15 +1,27 @@ /*! \page general_intro Getting Started with %CGAL +The following pages describe how to use \cgal on different environments + - \subpage usage - \subpage windows - \subpage thirdparty gives information (supported versions, download links) of the required and optional third party libraries. +The following pages cover advanced installation options + +- \subpage configurationvariables gives information about which CMake variables can be used to help +resolve missing dependencies while using the cmake command line tool. + +- \subpage installation describes the deprecated process of configuring and building \cgal. + +The following pages cover the structure of the manual and general information about \cgal + - \subpage manual gives an idea of where you should look for documentation. -- \subpage preliminaries lists how to control inlining, thread safety, code deprecation, checking of pre- and postconditions, and how to alter the failure behavior. +- \subpage preliminaries lists how to control inlining, thread safety, code deprecation, checking +of pre- and postconditions, and how to alter the failure behavior. Once you are familiar with building your programs with \cgal and how the documentation is structured, you can head over to the \ref tutorials for a gentle introduction to \cgal, or directly to the package(s) diff --git a/Documentation/doc/Documentation/Third_party.txt b/Documentation/doc/Documentation/Third_party.txt index abedcc34eb7..e0220b92691 100644 --- a/Documentation/doc/Documentation/Third_party.txt +++ b/Documentation/doc/Documentation/Third_party.txt @@ -18,6 +18,8 @@ supporting C++14 or later. | MacOS X | \sc{Gnu} `g++` 6.3 or later\cgalFootnote{`http://gcc.gnu.org/`} | | | Apple `Clang` compiler versions 7.0.2 and 10.0.1 | + + Older versions of the above listed compilers might work, but no guarantee is provided. \section seccmake CMake @@ -54,7 +56,7 @@ or `h The \stl comes with the compiler, and as such no installation is required. \subsection thirdpartyBoost Boost -Version 1.48 or later +Version 1.57 or later The \sc{Boost} libraries are a set of portable C++ source libraries. Most of \sc{Boost} libraries are header-only, but a few of them need to be compiled or diff --git a/Documentation/doc/Documentation/Tutorials/Tutorial_hello_world.txt b/Documentation/doc/Documentation/Tutorials/Tutorial_hello_world.txt index a3938229867..f90dbe3d5b5 100644 --- a/Documentation/doc/Documentation/Tutorials/Tutorial_hello_world.txt +++ b/Documentation/doc/Documentation/Tutorials/Tutorial_hello_world.txt @@ -266,7 +266,7 @@ given by a direction, which is hardwired in the class \section intro_concept Concepts and Models In the previous section, we wrote that "Any model of the CGAL concept -Kernel provides what is required by the concept ConvexHullTraits_2". +Kernel provides what is required by the concept `ConvexHullTraits_2`. A \em concept is a set of requirements on a type, namely that it has certain nested types, certain member functions, or comes with certain diff --git a/Documentation/doc/Documentation/Tutorials/Tutorials.txt b/Documentation/doc/Documentation/Tutorials/Tutorials.txt index ac3dd2c9197..aab618e954f 100644 --- a/Documentation/doc/Documentation/Tutorials/Tutorials.txt +++ b/Documentation/doc/Documentation/Tutorials/Tutorials.txt @@ -8,9 +8,7 @@ combined to achieve extensive and complex geometric tasks. The tutorials aim at providing help and ideas on how to use CGAL beyond the simple examples of the User Manual. - - -\section tuto_list List of available tutorials +\section tuto_list List of Available Tutorials - \subpage tutorial_hello_world presents you some short example programs to get a first idea for the look and feel of a program that @@ -19,4 +17,9 @@ User Manual. define what primitives are used by a geometric algorithm, the notions of \em concept and \em model. +\section tuto_examples Package Examples + +Each \cgal package comes with a set of commented examples that illustrate basic features of the package. +See for example Section \ref Triangulation3secexamples of the User Manual of the package \ref PkgTriangulation3. + */ diff --git a/Documentation/doc/Documentation/Usage.txt b/Documentation/doc/Documentation/Usage.txt index 00e19f24615..ee70f537e0f 100644 --- a/Documentation/doc/Documentation/Usage.txt +++ b/Documentation/doc/Documentation/Usage.txt @@ -1,5 +1,5 @@ /*! -\page usage Using %CGAL on Linux and macOS +\page usage Using %CGAL on Unix (Linux, macOS, ...) \cgalAutoToc Since \cgal version 5.0, \cgal is header-only be default, which means @@ -9,7 +9,8 @@ However, some dependencies of \cgal might still need to be installed. \section usage_introduction Quick Start: Compiling a Program using CGAL Assuming that you have obtained \cgal through one of the package managers offering \cgal on your platform -(see Section \ref secgettingcgal), you can download \cgal examples here +(see Section \ref secgettingcgal), you can download \cgal examples +CGAL-\cgalReleaseNumber-examples.tar.xz and the compilation of an example is as simple as: cd $HOME/CGAL-\cgalReleaseNumber/examples/Triangulation_2 # go to an example directory @@ -112,6 +113,14 @@ or downloaded separately at there is no need to even configure it before using it. Programs using \cgal (examples, tests, demos, etc.) are instead configured using CMake and \cgal will be configured at the same time. +There is one exception to the paragraph before: if you want to install \cgal header files to +a standard location (such as `/usr/local/include`): + + cmake . + make install + +For more advanced usage, we refer to Section \ref installation_configwithcmake. + Note that even though \cgal is a header-only library, not all its dependencies are header-only. The libraries \sc{Gmp} and \sc{Mpfr}, for example, are not header-only. As such, these dependencies must be built or installed independently. diff --git a/Documentation/doc/Documentation/advanced/Configuration_variables.txt b/Documentation/doc/Documentation/advanced/Configuration_variables.txt index 343a513afb2..1bebdc5ddd7 100644 --- a/Documentation/doc/Documentation/advanced/Configuration_variables.txt +++ b/Documentation/doc/Documentation/advanced/Configuration_variables.txt @@ -3,6 +3,11 @@ \page configurationvariables Summary of %CGAL's Configuration Variables \cgalAutoToc +\cgalAdvancedBegin +This page lists CMake variables which you can use to help CMake find missing dependencies +while using the command line. We however recommend using the graphical interface (`cmake-gui`). +\cgalAdvancedEnd + \section installation_summary Summary of CGAL's Configuration Variables Most configuration variables are not environment variables but diff --git a/Documentation/doc/Documentation/advanced/Installation.txt b/Documentation/doc/Documentation/advanced/Installation.txt index e2f095f6e91..314ead765e1 100644 --- a/Documentation/doc/Documentation/advanced/Installation.txt +++ b/Documentation/doc/Documentation/advanced/Installation.txt @@ -2,11 +2,13 @@ \page installation Building %CGAL libraries (non header-only mode) \cgalAutoToc -Since \cgal version 5.0, \cgal is header-only be default, which means +\cgalAdvancedBegin +Since \cgal version 5.0, \cgal is header-only be default, which means that there is no need to compile \cgal or its libraries before it can be used. This page is for advanced users that have a good reason to still use the old way. -If this is not your case, head over back to the page \ref general_intro. +If this is not your case, head over back to the page \ref general_intro. +\cgalAdvancedEnd This page is a step-by-step description of how to configure, build, and (optionally) install \cgal in case you do not wish to use the - now enabled by default - header-only mode of \cgal. diff --git a/Documentation/doc/Documentation/advanced/advanced.txt b/Documentation/doc/Documentation/advanced/advanced.txt deleted file mode 100644 index b6136edda22..00000000000 --- a/Documentation/doc/Documentation/advanced/advanced.txt +++ /dev/null @@ -1,8 +0,0 @@ -/*! - -\page advanced Advanced - -- \subpage configurationvariables lists the various CMake variables that can be used to help find third-party dependencies. -- \subpage installation describes the (optional) process of building and installing %CGAL itself. - -*/ diff --git a/Documentation/doc/Documentation/main.txt b/Documentation/doc/Documentation/main.txt index 217a40b19d7..6d9ffe67c1e 100644 --- a/Documentation/doc/Documentation/main.txt +++ b/Documentation/doc/Documentation/main.txt @@ -5,12 +5,15 @@ The Computational Geometry Algorithms Library (\cgal) is a software project that provides easy access to efficient and reliable geometric algorithms in the form of a C++ library. -

            + +

            Package Overview

            + \cgal offers data structures and algorithms like \ref PartTriangulationsAndDelaunayTriangulations "triangulations", \ref PartVoronoiDiagrams "Voronoi diagrams", \ref PartPolygons, \ref PartPolyhedra, \ref PartArrangements "arrangements of curves", \ref PartMeshing "mesh generation", \ref PartGeometryProcessing "geometry processing", \ref PartConvexHullAlgorithms "convex hull algorithms", to name just a few. + All these data structures and algorithms operate on geometric objects like points and segments, and perform geometric tests on them. These objects and predicates are regrouped in \ref PartKernels "CGAL Kernels". @@ -21,33 +24,26 @@ solver for linear and quadratic programs. It further offers interfaces to third party software such as the GUI libraries Qt, Geomview, and the Boost Graph Library. -Getting Started -=============== +The complete list of packages is available on the page \ref packages. +

            Getting Started

            -- \ref usage describes how to obtain \cgal and the few steps required to build a program using \cgal. +Head over to \ref general_intro to learn how to obtain, install, and use \cgal. -- \ref thirdparty lists required and optional third party libraries. +

            License

            -- \ref manual gives an idea of where you should look for documentation. - -- \ref preliminaries lists how to control inlining, thread safety, code deprecation, checking of pre- and postconditions, and how to alter the failure behavior. - -Once you are familiar with building your programs with \cgal and how the documentation is structured, -you can head over to the \ref tutorials for a hand-in-hand introduction to \cgal data structures -and algorithms, or directly to the package(s) that interest you the \ref packages. Each package -contains simple examples of the various functionalities of the package. - -License -======= %CGAL is distributed under a dual-license scheme. %CGAL can be used together with Open Source software free of charge. Using %CGAL in other contexts can be done by obtaining a commercial license from [GeometryFactory](http://www.geometryfactory.com). For more details see the \ref license "License" page. -Manuals for the Previous Releases -================================= +

            Acknowledgement

            + +We provide bibtex entries for each package so that you can cite \cgal correctly in your publications, +see the page \ref how_to_cite_cgal. + +

            Manuals for the Previous Releases

            For releases >= 4.2, visit [https://doc.cgal.org/X.Y](https://doc.cgal.org/4.2) diff --git a/Documentation/doc/Documentation/windows.txt b/Documentation/doc/Documentation/windows.txt index a1b641f7431..a45afc972a5 100644 --- a/Documentation/doc/Documentation/windows.txt +++ b/Documentation/doc/Documentation/windows.txt @@ -2,6 +2,9 @@ \page windows Using %CGAL on Windows (with Visual C++) \cgalAutoToc +\cgal \cgalReleaseNumber is supported for the following \sc{MS} Visual `C++` compilers: +14.0, 15.9, 16.0 (\sc{Visual Studio} 2015, 2017, and 2019). + \cgal is a library that has mandatory dependencies that must be first installed: \ref thirdpartyBoost and \ref thirdpartyMPFR. @@ -57,7 +60,7 @@ Note that \cgal is a header-only library, and there are therefore no `lib` or `d In this section we show how to compile a program that uses \cgal. The examples you find in these User Manual pages are not downloaded when you install \cgal with the Vcpkg library manager. You must download them separately from the following download page: -CGAL-\cgalReleaseNumber-examples.zip +CGAL-\cgalReleaseNumber-examples.zip Assuming you have unzipped this file in your home directory `C:\Users\Me`, we will next compile an example from the 2D Triangulation package. From 593079fab9f3acf3d980b2e981743fb15e15ea1e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mael=20Rouxel-Labb=C3=A9?= Date: Tue, 29 Oct 2019 11:06:39 +0100 Subject: [PATCH 255/363] Tiny rephrase --- Documentation/doc/Documentation/Usage.txt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Documentation/doc/Documentation/Usage.txt b/Documentation/doc/Documentation/Usage.txt index ee70f537e0f..daf1643f4df 100644 --- a/Documentation/doc/Documentation/Usage.txt +++ b/Documentation/doc/Documentation/Usage.txt @@ -113,13 +113,13 @@ or downloaded separately at there is no need to even configure it before using it. Programs using \cgal (examples, tests, demos, etc.) are instead configured using CMake and \cgal will be configured at the same time. -There is one exception to the paragraph before: if you want to install \cgal header files to +There is one exception to the last paragraph: if you want to install \cgal header files to a standard location (such as `/usr/local/include`): cmake . make install -For more advanced usage, we refer to Section \ref installation_configwithcmake. +For more advanced installations, we refer to Section \ref installation_configwithcmake. Note that even though \cgal is a header-only library, not all its dependencies are header-only. The libraries \sc{Gmp} and \sc{Mpfr}, for example, are not From bcf09288f064fbcd697d14d586be483f7dafbcad Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mael=20Rouxel-Labb=C3=A9?= Date: Tue, 29 Oct 2019 11:24:39 +0100 Subject: [PATCH 256/363] Fix examples.zip link --- Documentation/doc/Documentation/Usage.txt | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/Documentation/doc/Documentation/Usage.txt b/Documentation/doc/Documentation/Usage.txt index daf1643f4df..30b3627f683 100644 --- a/Documentation/doc/Documentation/Usage.txt +++ b/Documentation/doc/Documentation/Usage.txt @@ -9,8 +9,8 @@ However, some dependencies of \cgal might still need to be installed. \section usage_introduction Quick Start: Compiling a Program using CGAL Assuming that you have obtained \cgal through one of the package managers offering \cgal on your platform -(see Section \ref secgettingcgal), you can download \cgal examples -CGAL-\cgalReleaseNumber-examples.tar.xz +(see Section \ref secgettingcgal), you can download \cgal examples ( +CGAL-\cgalReleaseNumber-examples.tar.xz) and the compilation of an example is as simple as: cd $HOME/CGAL-\cgalReleaseNumber/examples/Triangulation_2 # go to an example directory @@ -50,7 +50,8 @@ You may also download the sources of \cgal directly, but it is then your respons acquire these dependencies. The examples and demos of \cgal are not included when you install \cgal with a package manager, -and must be downloaded here. +and must be downloaded +here. \subsection secusingpkgman Using a Package Manager From 9ae69bc85a4910b2c55ea2640530fc1f7c5c5175 Mon Sep 17 00:00:00 2001 From: Laurent Rineau Date: Tue, 29 Oct 2019 15:02:01 +0100 Subject: [PATCH 257/363] Bump the Boost version number (and release month) --- Installation/CHANGES.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/Installation/CHANGES.md b/Installation/CHANGES.md index 51e45d1c998..bea1aba3060 100644 --- a/Installation/CHANGES.md +++ b/Installation/CHANGES.md @@ -4,7 +4,7 @@ Release History [Release 5.0](https://github.com/CGAL/cgal/releases/tag/releases%2FCGAL-5.0) ----------- -Release date: October 2019 +Release date: November 2019 ### General changes @@ -18,6 +18,7 @@ Release date: October 2019 - 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 minimal version of Boost is now 1.57.0. ### [Polygonal Surface Reconstruction](https://doc.cgal.org/5.0/Manual/packages.html#PkgPolygonalSurfaceReconstruction) (new package) From d24671eacf2dc896453fe122c70b559a19066614 Mon Sep 17 00:00:00 2001 From: Laurent Rineau Date: Tue, 29 Oct 2019 15:04:55 +0100 Subject: [PATCH 258/363] Announce the changes to the documentation --- Installation/CHANGES.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Installation/CHANGES.md b/Installation/CHANGES.md index bea1aba3060..a9d9270524b 100644 --- a/Installation/CHANGES.md +++ b/Installation/CHANGES.md @@ -18,6 +18,8 @@ Release date: November 2019 - 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. From bbe02d9f7b6392a2ef60c31af53f0e8e757d8064 Mon Sep 17 00:00:00 2001 From: Laurent Rineau Date: Tue, 29 Oct 2019 15:22:49 +0100 Subject: [PATCH 259/363] Fix the license header --- .../internal/Iso_cuboid_3_Triangle_3_intersection.h | 13 ++----------- 1 file changed, 2 insertions(+), 11 deletions(-) diff --git a/Intersections_3/include/CGAL/Intersections_3/internal/Iso_cuboid_3_Triangle_3_intersection.h b/Intersections_3/include/CGAL/Intersections_3/internal/Iso_cuboid_3_Triangle_3_intersection.h index 2762d9ad588..ea8155daf58 100644 --- a/Intersections_3/include/CGAL/Intersections_3/internal/Iso_cuboid_3_Triangle_3_intersection.h +++ b/Intersections_3/include/CGAL/Intersections_3/internal/Iso_cuboid_3_Triangle_3_intersection.h @@ -1,20 +1,11 @@ // 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 Lesser 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: LGPL-3.0+ +// SPDX-License-Identifier: LGPL-3.0-or-later OR LicenseRef-Commercial // // // Author(s) : Maxime Gimeno From 5e1fe8a0b014fcf22782b3791e113e2251655357 Mon Sep 17 00:00:00 2001 From: Laurent Rineau Date: Tue, 29 Oct 2019 15:39:57 +0100 Subject: [PATCH 260/363] fix warnings --- CGAL_ImageIO/include/CGAL/ImageIO/iris_impl.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/CGAL_ImageIO/include/CGAL/ImageIO/iris_impl.h b/CGAL_ImageIO/include/CGAL/ImageIO/iris_impl.h index 7b711d84725..fd395efa657 100644 --- a/CGAL_ImageIO/include/CGAL/ImageIO/iris_impl.h +++ b/CGAL_ImageIO/include/CGAL/ImageIO/iris_impl.h @@ -211,7 +211,7 @@ static void addimgtag(byte *dptr, int xsize, int ysize) /*****************************************************/ static unsigned short getshort( const _image *im) { - byte buf[2]; + byte buf[2] = { '\0', '\0' }; ImageIO_read( im, buf, (size_t) 2); return (unsigned short)((buf[0]<<8)+(buf[1]<<0)); } @@ -219,7 +219,7 @@ static unsigned short getshort( const _image *im) /*****************************************************/ static unsigned long getlong( const _image *im ) { - byte buf[4]; + byte buf[4] = { '\0', '\0', '\0', '\0' }; ImageIO_read( im, buf, (size_t) 4); return (((unsigned long) buf[0])<<24) + (((unsigned long) buf[1])<<16) + (((unsigned long) buf[2])<<8) + buf[3]; From 4d1ae09d6d30c66fe2e3b245a2aea8698b6b2566 Mon Sep 17 00:00:00 2001 From: Mael Date: Wed, 30 Oct 2019 09:58:23 +0100 Subject: [PATCH 261/363] Fix unused typedef warning --- .../test/Polygon_mesh_processing/test_pmp_locate.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Polygon_mesh_processing/test/Polygon_mesh_processing/test_pmp_locate.cpp b/Polygon_mesh_processing/test/Polygon_mesh_processing/test_pmp_locate.cpp index 03e74b71eec..3b285fc6a50 100644 --- a/Polygon_mesh_processing/test/Polygon_mesh_processing/test_pmp_locate.cpp +++ b/Polygon_mesh_processing/test/Polygon_mesh_processing/test_pmp_locate.cpp @@ -605,8 +605,7 @@ struct Locate_with_AABB_tree_Tester // 3D typedef typename K::FT FT; typedef typename K::Ray_3 Ray_3; - typedef typename K::Point_3 Point_3; - + 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; @@ -621,6 +620,7 @@ struct Locate_with_AABB_tree_Tester // 3D typedef CGAL::AABB_face_graph_triangle_primitive AABB_face_graph_primitive; typedef CGAL::AABB_traits AABB_face_graph_traits; + CGAL_assertion_code(typedef typename K::Point_3 Point_3;) CGAL_static_assertion((std::is_same::value)); CGAL::AABB_tree tree_a; From 72548ecb2d2e15b2fb7dd19a970f92d3e9e28b68 Mon Sep 17 00:00:00 2001 From: Marc Glisse Date: Wed, 30 Oct 2019 17:27:00 +0100 Subject: [PATCH 262/363] More NaN fixes for the non-SSE path. --- Number_types/include/CGAL/Interval_nt.h | 7 +++++-- .../test/Number_types/Interval_nt_new.cpp | 19 +++++++++++++++++++ 2 files changed, 24 insertions(+), 2 deletions(-) diff --git a/Number_types/include/CGAL/Interval_nt.h b/Number_types/include/CGAL/Interval_nt.h index b8908f2b05b..e19e1668d04 100644 --- a/Number_types/include/CGAL/Interval_nt.h +++ b/Number_types/include/CGAL/Interval_nt.h @@ -639,6 +639,7 @@ private: return IA (IA_opacify128(r)); # endif #else + // TODO: try to move some NaN tests out of the hot path (test a.inf()>0 instead of >=0?). if (a.inf() >= 0.0) // a>=0 { // b>=0 [a.inf()*b.inf(); a.sup()*b.sup()] @@ -652,7 +653,8 @@ private: if (b.sup() < 0.0) bb = a.inf(); } - return IA(-CGAL_IA_MUL(aa, -b.inf()), CGAL_IA_MUL(bb, b.sup())); + double r = (b.sup() == 0) ? 0. : CGAL_IA_MUL(bb, b.sup()); // In case bb is infinite, avoid NaN. + return IA(-CGAL_IA_MUL(aa, -b.inf()), r); } else if (a.sup()<=0.0) // a<=0 { @@ -663,9 +665,10 @@ private: if (b.inf() < 0.0) { aa=bb; - if (b.sup() < 0.0) + if (b.sup() <= 0.0) bb=a.sup(); } + else if (b.sup() <= 0) return 0.; // In case a has an infinite bound, avoid NaN. return IA(-CGAL_IA_MUL(-bb, b.sup()), CGAL_IA_MUL(-aa, -b.inf())); } else // 0 \in a diff --git a/Number_types/test/Number_types/Interval_nt_new.cpp b/Number_types/test/Number_types/Interval_nt_new.cpp index 291e4e41d23..95d4f5521fe 100644 --- a/Number_types/test/Number_types/Interval_nt_new.cpp +++ b/Number_types/test/Number_types/Interval_nt_new.cpp @@ -170,12 +170,31 @@ int main() { Interval d(0,inf); // For CGAL's purposes, [0,0]*anything is 0, but we tolerate larger intervals if they can be produced faster. for (Interval I : { all*zero, zero*all, all*0., 0.*all, b*zero, zero*b, -b*zero, zero*-b, c*zero, zero*c, -c*zero, zero*-c }) + { + //std::cout << I << '\n'; assert(I.inf()<=0 && I.sup()>=0); + } // This should be [0,inf], but again we tolerate more. for (Interval I : { a*b, b*a, -a*-b, -b*-a, d*d, -d*-d }) + { + //std::cout << I << '\n'; assert(I.inf()<=0 && I.sup()==inf); + } + for (Interval I : { -a*b, -b*a, a*-b, b*-a, -d*d, d*-d }) + { + //std::cout << I << '\n'; + assert(I.inf()==-inf && I.sup()>=0); + } for (Interval I : { all*a, a*all, all*-a, -a*all }) + { + //std::cout << I << '\n'; assert(I.inf()==-inf && I.sup()==inf); + } + for (Interval I : { all*d, d*all, all*-d, -d*all }) + { + //std::cout << I << '\n'; + assert(I.inf()==-inf && I.sup()==inf); + } } {// external functions on Intervals // functions (abs, square, sqrt, pow) From c407516c1be185d5c40ce2c404aff5d4ed76033c Mon Sep 17 00:00:00 2001 From: Marc Glisse Date: Wed, 30 Oct 2019 23:18:11 +0100 Subject: [PATCH 263/363] Speed-up SSE NaN protection for intervals We don't need quite as much protection as I initially added. The essential is to avoid max(x,NaN) which would lose the value of x. max(NaN,x) loses NaN (which means 0 for intervals), but there will always be either another 0 or some +inf elsewhere. --- Number_types/include/CGAL/Interval_nt.h | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/Number_types/include/CGAL/Interval_nt.h b/Number_types/include/CGAL/Interval_nt.h index e19e1668d04..ad8d057b30f 100644 --- a/Number_types/include/CGAL/Interval_nt.h +++ b/Number_types/include/CGAL/Interval_nt.h @@ -554,19 +554,21 @@ private: // The multiplications could produce some NaN, with 0 * inf. Replacing it with inf is safe. // min(x,y) (the order is essential) returns its second argument when the first is NaN. + // An IEEE 754-2019 maximum could help. __m128d big = IA::largest().simd(); __m128d x1 = _mm_mul_pd(aa,bz); // {-ai*bi,as*bs} - x1 = _mm_min_pd(x1,big); // no NaN + //x1 = _mm_min_pd(x1,big); // no NaN __m128d x2 = _mm_mul_pd(aa,c); // {-ai*bs,as*bi} x2 = _mm_min_pd(x2,big); // no NaN __m128d x3 = _mm_mul_pd(ap,bz); // {-as*bi,ai*bs} - x3 = _mm_min_pd(x3,big); // no NaN + //x3 = _mm_min_pd(x3,big); // no NaN __m128d x4 = _mm_mul_pd(ap,c); // {-as*bs,ai*bi} x4 = _mm_min_pd(x4,big); // no NaN __m128d y1 = _mm_max_pd(x1,x2); __m128d y2 = _mm_max_pd(x3,x4); __m128d r = _mm_max_pd (y1, y2); + // Alternative with fewer instructions but more dependency // __m128d r = _mm_max_pd(x1,_mm_max_pd(x2,_mm_max_pd(x3,_mm_min_pd(x4,big)))); return IA (IA_opacify128(r)); # elif 1 @@ -587,7 +589,7 @@ private: __m128d x = _mm_blendv_pd (bb, bp, az); // {ai<0?-bs:-bi,as<0?bi:bs} __m128d y = _mm_blendv_pd (bb, bp, azp); // {as<0?-bs:-bi,ai<0?bi:bs} __m128d p1 = _mm_mul_pd (az, x); - p1 = _mm_min_pd(p1,big); // no NaN + //p1 = _mm_min_pd(p1,big); // no NaN __m128d p2 = _mm_mul_pd (azp, y); p2 = _mm_min_pd(p2,big); // no NaN __m128d r = _mm_max_pd (p1, p2); @@ -609,7 +611,7 @@ private: __m128d x = _mm_blendv_pd (bbs, bbi, aa); // {ai>0?bi:bs,as<0?bi:bs} __m128d y = _mm_blendv_pd (bbi, bbs, ax); // {as<0?bs:bi,ai>0?bs:bi} __m128d p1 = _mm_mul_pd (aa, x); - p1 = _mm_min_pd(p1,big); // no NaN + //p1 = _mm_min_pd(p1,big); // no NaN __m128d p2 = _mm_mul_pd (ap, y); p2 = _mm_min_pd(p2,big); // no NaN __m128d r = _mm_max_pd (p1, p2); @@ -629,7 +631,7 @@ private: __m256d Y1 = _mm256_set_m128d(bz,bz); // {bi,bs,bi,bs} __m256d Y2 = _mm256_permute_pd(Y1,5); // {bs,bi,bs,bi} __m256d Z1 = _mm256_mul_pd(X,Y1); - Z1 = _mm256_min_pd(Z1,big); // no NaN + //Z1 = _mm256_min_pd(Z1,big); // no NaN __m256d Z2 = _mm256_mul_pd(X,Y2); Z2 = _mm256_min_pd(Z2,big); // no NaN __m256d Z = _mm256_max_pd(Z1,Z2); From 3f58a277cdf00f7a9aae849c2286733f644222fd Mon Sep 17 00:00:00 2001 From: Simon Giraudot Date: Thu, 31 Oct 2019 09:37:57 +0100 Subject: [PATCH 264/363] Better IO example in Point_set_3 --- .../Point_set_3/point_set_read_ply.cpp | 27 +++++++++++++------ 1 file changed, 19 insertions(+), 8 deletions(-) diff --git a/Point_set_3/examples/Point_set_3/point_set_read_ply.cpp b/Point_set_3/examples/Point_set_3/point_set_read_ply.cpp index b115781847f..0837329fae3 100644 --- a/Point_set_3/examples/Point_set_3/point_set_read_ply.cpp +++ b/Point_set_3/examples/Point_set_3/point_set_read_ply.cpp @@ -14,14 +14,15 @@ typedef CGAL::Point_set_3 Point_set; int main (int argc, char** argv) { - std::ifstream f (argc > 1 ? argv[1] : "data/example.ply"); + std::ifstream f (argc > 1 ? argv[1] : "data/example.ply", + std::ios_base::binary); // Mandatory on Windows if input is binary PLY Point_set point_set; - if (!f || !CGAL::read_ply_point_set (f, point_set)) - { - std::cerr << "Can't read input file " << std::endl; - } + if (!f || !CGAL::read_ply_point_set (f, point_set)) // same as `f >> point_set` + { + std::cerr << "Can't read input file " << std::endl; + } // Shows which properties are defined std::vector properties = point_set.properties(); @@ -41,9 +42,19 @@ int main (int argc, char** argv) std::cerr << " * " << label_prop[*it] << std::endl; } - std::ofstream out ("out.ply"); - out.precision(17); - CGAL::write_ply_point_set (out, point_set); + if (argc > 2 && argv[2] == "-b") // Optional binary output + { + std::ofstream out ("out.ply", + std::ios_base::binary); // Mandatory on Windows + CGAL::set_binary_mode (out); // Select binary mode (ASCII is default) + out << point_set; // same as `CGAL::write_ply_point_set (out, point_set)` + } + else // ASCII output + { + std::ofstream out ("out.ply"); + out.precision(17); // Use sufficient precision in ASCII + CGAL::write_ply_point_set (out, point_set); // same as `out << point_set` + } return 0; } From 9905205afcb0c0f762bd28d9c4dc70902891eff9 Mon Sep 17 00:00:00 2001 From: Laurent Rineau Date: Thu, 31 Oct 2019 09:47:00 +0100 Subject: [PATCH 265/363] update script to new release tarballs --- Maintenance/public_release/scripts/prepare_release | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/Maintenance/public_release/scripts/prepare_release b/Maintenance/public_release/scripts/prepare_release index 2e3f23db0f0..4ceb0c164ef 100755 --- a/Maintenance/public_release/scripts/prepare_release +++ b/Maintenance/public_release/scripts/prepare_release @@ -17,7 +17,11 @@ PUBLIC_RELEASE_DIR="$1" INTERNAL_RELEASE=`basename ${PUBLIC_RELEASE_DIR/-public/}` -PUBLIC_RELEASE_NAME=`basename ${~${ZIP_TARBALL::="$PUBLIC_RELEASE_DIR"/*.zip}}` +ZIP_TARBALL=("$PUBLIC_RELEASE_DIR"/*-library.zip(N)) +[ -z "$ZIP_TARBALL" ] && ZIP_TARBALL=("$PUBLIC_RELEASE_DIR"/*.zip(N)) + +PUBLIC_RELEASE_NAME=`basename "$ZIP_TARBALL"` +PUBLIC_RELEASE_NAME=${PUBLIC_RELEASE_NAME/-library.zip/} PUBLIC_RELEASE_NAME=${PUBLIC_RELEASE_NAME/.zip/} DEST_DIR="${RELEASE_CANDIDATES_DIR}/$PUBLIC_RELEASE_NAME" From 2305bc6df8a0f588e1d0e1f8726a38a0f485f5ac Mon Sep 17 00:00:00 2001 From: Laurent Rineau Date: Thu, 31 Oct 2019 10:31:52 +0100 Subject: [PATCH 266/363] Announcement for 5.0-beta2 --- .../announcement/announcement-beta.md | 76 +++++++++++++++++++ .../announcement/mailing-beta.eml | 58 +++++++------- 2 files changed, 106 insertions(+), 28 deletions(-) create mode 100644 Maintenance/public_release/announcement/announcement-beta.md diff --git a/Maintenance/public_release/announcement/announcement-beta.md b/Maintenance/public_release/announcement/announcement-beta.md new file mode 100644 index 00000000000..c7029907fed --- /dev/null +++ b/Maintenance/public_release/announcement/announcement-beta.md @@ -0,0 +1,76 @@ +The CGAL Open Source Project is pleased to announce the release 5.0 Beta 2 +of CGAL, the Computational Geometry Algorithms Library. + +CGAL version 5.0 Beta 2 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. + +### 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](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 + 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) + - **Breaking change:** The concept `ShapeDetectionTraits` has been renamed to [`EfficientRANSACTraits`](https://doc.cgal.org/5.0/Shape_detection/classEfficientRANSACTraits.html). + - **Breaking change:** The `Shape_detection_3` namespace has been renamed to [`Shape_detection`](https://doc.cgal.org/5.0/Shape_detection/annotated.html). + - 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`](https://doc.cgal.org/5.0/BGL/classFaceGraph.html) concept. Learn more about this new algorithm with this [blog entry](https://www.cgal.org/2019/07/30/Shape_detection/). + +### [dD Geometry Kernel](https://doc.cgal.org/5.0/Manual/packages.html#PkgKernelD) + - A new exact kernel, [`Epeck_d`](https://doc.cgal.org/5.0/Kernel_d/structCGAL_1_1Epeck__d.html), is now available. + +### 2D and 3D Triangulations + +- **Breaking change:** Several deprecated functions and classes have been + removed. See the full list of breaking changes in the release + notes. + +- **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]`. + + +### [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) + 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 + (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. + - Added the shape smoothing function [`smooth_shape()`](https://doc.cgal.org/5.0/Polygon_mesh_processing/group__PMP__meshing__grp.html#gaaa083ec78bcecf351e04d1bbf460b4a2), + which can be used to smooth the surface of a triangle mesh, using the mean curvature flow to perform noise removal. + (See also the new entry in the [User Manual](https://doc.cgal.org/5.0/Polygon_mesh_processing/index.html#title8)) + +### [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. + +See https://www.cgal.org/2019/10/31/cgal50-beta2/ for a complete list of changes. diff --git a/Maintenance/public_release/announcement/mailing-beta.eml b/Maintenance/public_release/announcement/mailing-beta.eml index 262f7185e04..11251b7563a 100644 --- a/Maintenance/public_release/announcement/mailing-beta.eml +++ b/Maintenance/public_release/announcement/mailing-beta.eml @@ -1,33 +1,38 @@ -Subject: CGAL 5.0 Beta 1 Released, Computational Geometry Algorithms Library +Subject: CGAL 5.0 Beta 2 Released, Computational Geometry Algorithms Library Content-Type: text/plain; charset="utf-8" Body: -The CGAL Open Source Project is pleased to announce the release 5.0 Beta 1 +The CGAL Open Source Project is pleased to announce the release 5.0 Beta 2 of CGAL, the Computational Geometry Algorithms Library. -CGAL version 5.0 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 October. +CGAL version 5.0 Beta 2 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. - -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 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. 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) @@ -68,16 +73,14 @@ dD Geometry Kernel 2D and 3D Triangulations - BREAKING CHANGE: Several deprecated functions and classes have been - removed. See the full list of breaking changes in the release - notes. + removed. See the full list of breaking changes in the release notes. - 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]. - + 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]. Polygon Mesh Processing @@ -102,8 +105,7 @@ Point Set Processing parameters (deprecated since CGAL 4.12) has been removed. The current (and now only) API uses ranges and Named Parameters. - -See https://www.cgal.org/2019/09/30/cgal50-beta1/ for a complete list of +See https://www.cgal.org/2019/10/31/cgal50-beta2/ for a complete list of changes. From 387f55cfcace3f15d76fa2a723b82f81746a3979 Mon Sep 17 00:00:00 2001 From: Laurent Rineau Date: Thu, 31 Oct 2019 10:32:50 +0100 Subject: [PATCH 267/363] Next version in this branch will be 5.0-beta3 (or the final release) --- Installation/include/CGAL/version.h | 6 +++--- Maintenance/release_building/public_release_name | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/Installation/include/CGAL/version.h b/Installation/include/CGAL/version.h index f3edd55ba82..f8dc7b70b07 100644 --- a/Installation/include/CGAL/version.h +++ b/Installation/include/CGAL/version.h @@ -16,11 +16,11 @@ #ifndef CGAL_VERSION_H #define CGAL_VERSION_H -#define CGAL_VERSION 5.0-beta2 -#define CGAL_VERSION_NR 1050000920 +#define CGAL_VERSION 5.0-beta3 +#define CGAL_VERSION_NR 1050000930 #define CGAL_SVN_REVISION 99999 #define CGAL_GIT_HASH abcdef -#define CGAL_RELEASE_DATE 20190930 +#define CGAL_RELEASE_DATE 20191031 #include diff --git a/Maintenance/release_building/public_release_name b/Maintenance/release_building/public_release_name index 35f0924c662..7c0cede8ccf 100644 --- a/Maintenance/release_building/public_release_name +++ b/Maintenance/release_building/public_release_name @@ -1 +1 @@ -CGAL-5.0-beta2 +CGAL-5.0-beta3 From aee346441d2049bb22382a19d873ae6dc30689f2 Mon Sep 17 00:00:00 2001 From: Laurent Rineau Date: Thu, 31 Oct 2019 10:49:50 +0100 Subject: [PATCH 268/363] 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 13e489c8854..8bd5ff843c4 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 --public --do-it --beta 2 || 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 --public --do-it --beta 3 || 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 --beta 2 || 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 --public --beta 3 || 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 # from branch 4.13 From bc735b44a0619611469775af9a4077b3d3da5d0a Mon Sep 17 00:00:00 2001 From: Laurent Rineau Date: Thu, 31 Oct 2019 13:49:22 +0100 Subject: [PATCH 269/363] Check the presence of header When CGAL is installed by package-managers, CGAL_Qt5 headers maybe installed separately: - `libcgal-qt5-dev` on Debian, - `CGAL-qt5-devel` on Fedora, for example. --- .../cmake/modules/CGAL_SetupCGAL_Qt5Dependencies.cmake | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/Installation/cmake/modules/CGAL_SetupCGAL_Qt5Dependencies.cmake b/Installation/cmake/modules/CGAL_SetupCGAL_Qt5Dependencies.cmake index dae96c444e6..2cdc190f75a 100644 --- a/Installation/cmake/modules/CGAL_SetupCGAL_Qt5Dependencies.cmake +++ b/Installation/cmake/modules/CGAL_SetupCGAL_Qt5Dependencies.cmake @@ -36,7 +36,9 @@ endif() if(NOT Qt5_FOUND) set(CGAL_Qt5_MISSING_DEPS "${CGAL_Qt5_MISSING_DEPS} Qt5") endif() - +if(NOT EXISTS ${CGAL_GRAPHICSVIEW_PACKAGE_DIR}/include/CGAL/Qt/GraphicsItem.h) + set(CGAL_Qt5_MISSING_DEPS "${CGAL_Qt5_MISSING_DEPS} headers") +endif() #.rst: # Result Variables From bff5db68e118973bb108ffbbb2859801edf05e6e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9bastien=20Loriot?= Date: Thu, 31 Oct 2019 14:17:20 +0100 Subject: [PATCH 270/363] fix some remaining license notice + add a missing LicenseRef-Commercial --- Installation/include/CGAL/auto_link/auto_link.h | 8 +++----- STL_Extension/include/CGAL/is_streamable.h | 9 --------- Surface_mesh/include/CGAL/Surface_mesh/Surface_mesh.h | 2 +- 3 files changed, 4 insertions(+), 15 deletions(-) diff --git a/Installation/include/CGAL/auto_link/auto_link.h b/Installation/include/CGAL/auto_link/auto_link.h index c02515b95d9..3f9a015f1bb 100644 --- a/Installation/include/CGAL/auto_link/auto_link.h +++ b/Installation/include/CGAL/auto_link/auto_link.h @@ -1,15 +1,13 @@ // This header file is a copy of "boost/config/auto_link.hpp" // from boost version 1.44.0 // but slightly modified to accommodate CGAL libraries. - +// // Before CGAL-4.7-beta1, it has been synchronized with // libs/config/ version boost-1.58.0-39-g15d56c9, file // include/boost/config/auto_link.hpp - +// // (C) Copyright John Maddock 2003. -// Use, modification and distribution are subject to the -// Boost Software License, Version 1.0. (See accompanying file -// LICENSE_1_0.txt or copy at https://www.boost.org/LICENSE_1_0.txt) +// // // $URL$ // $Id$ diff --git a/STL_Extension/include/CGAL/is_streamable.h b/STL_Extension/include/CGAL/is_streamable.h index b19ff487c4e..b20898a2664 100644 --- a/STL_Extension/include/CGAL/is_streamable.h +++ b/STL_Extension/include/CGAL/is_streamable.h @@ -1,15 +1,6 @@ // Copyright (c) 2012 GeometryFactory Sarl (France) // All rights reserved. // -// Distributed under the Boost Software License, Version 1.0. (See accompanying -// file LICENSE_1_0.txt or copy at https://www.boost.org/LICENSE_1_0.txt) -// -// 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: BSL-1.0 diff --git a/Surface_mesh/include/CGAL/Surface_mesh/Surface_mesh.h b/Surface_mesh/include/CGAL/Surface_mesh/Surface_mesh.h index 3fa750abaf0..491f2747353 100644 --- a/Surface_mesh/include/CGAL/Surface_mesh/Surface_mesh.h +++ b/Surface_mesh/include/CGAL/Surface_mesh/Surface_mesh.h @@ -6,7 +6,7 @@ // // $URL$ // $Id$ -// SPDX-License-Identifier: GPL-3.0-or-later +// SPDX-License-Identifier: GPL-3.0-or-later OR LicenseRef-Commercial // From 15d9e1f0ff268e3e823819a8d511125f840497fe Mon Sep 17 00:00:00 2001 From: Laurent Rineau Date: Thu, 31 Oct 2019 14:41:37 +0100 Subject: [PATCH 271/363] Restore the alphabetical order of `dependencies` files --- AABB_tree/package_info/AABB_tree/dependencies | 2 +- .../package_info/Convex_hull_2/dependencies | 3 +-- .../package_info/Convex_hull_d/dependencies | 2 +- Nef_S2/package_info/Nef_S2/dependencies | 2 +- .../dependencies | 2 +- .../dependencies | 6 ++--- .../package_info/Polyhedron/dependencies | 2 +- .../package_info/Shape_detection/dependencies | 26 +++++++++---------- .../dependencies | 2 +- .../Surface_mesh_segmentation/dependencies | 2 +- .../Surface_mesh_shortest_path/dependencies | 2 +- .../package_info/Visibility_2/dependencies | 2 +- 12 files changed, 26 insertions(+), 27 deletions(-) diff --git a/AABB_tree/package_info/AABB_tree/dependencies b/AABB_tree/package_info/AABB_tree/dependencies index c72f4088b6a..2162029e468 100644 --- a/AABB_tree/package_info/AABB_tree/dependencies +++ b/AABB_tree/package_info/AABB_tree/dependencies @@ -4,6 +4,7 @@ BGL Cartesian_kernel Circulator Distance_2 +Distance_3 Installation Intersections_2 Intersections_3 @@ -16,4 +17,3 @@ Property_map STL_Extension Spatial_searching Stream_support -Distance_3 diff --git a/Convex_hull_2/package_info/Convex_hull_2/dependencies b/Convex_hull_2/package_info/Convex_hull_2/dependencies index d5197515f41..9d516ba6e29 100644 --- a/Convex_hull_2/package_info/Convex_hull_2/dependencies +++ b/Convex_hull_2/package_info/Convex_hull_2/dependencies @@ -6,7 +6,6 @@ Kernel_23 Modular_arithmetic Number_types Profiling_tools +Property_map STL_Extension Stream_support -Property_map - diff --git a/Convex_hull_d/package_info/Convex_hull_d/dependencies b/Convex_hull_d/package_info/Convex_hull_d/dependencies index 81659211144..1535e6386bf 100644 --- a/Convex_hull_d/package_info/Convex_hull_d/dependencies +++ b/Convex_hull_d/package_info/Convex_hull_d/dependencies @@ -2,6 +2,7 @@ Algebraic_foundations Circulator Convex_hull_d Distance_2 +Distance_3 Hash_map Installation Intersections_2 @@ -14,4 +15,3 @@ Number_types Profiling_tools STL_Extension Stream_support -Distance_3 diff --git a/Nef_S2/package_info/Nef_S2/dependencies b/Nef_S2/package_info/Nef_S2/dependencies index 75135011028..fcc8ed45ff2 100644 --- a/Nef_S2/package_info/Nef_S2/dependencies +++ b/Nef_S2/package_info/Nef_S2/dependencies @@ -1,6 +1,7 @@ Algebraic_foundations Circulator Distance_2 +Distance_3 Hash_map Installation Intersections_2 @@ -16,4 +17,3 @@ Profiling_tools STL_Extension Stream_support Union_find -Distance_3 diff --git a/Optimal_transportation_reconstruction_2/package_info/Optimal_transportation_reconstruction_2/dependencies b/Optimal_transportation_reconstruction_2/package_info/Optimal_transportation_reconstruction_2/dependencies index 9b809650984..7fb921a03fa 100644 --- a/Optimal_transportation_reconstruction_2/package_info/Optimal_transportation_reconstruction_2/dependencies +++ b/Optimal_transportation_reconstruction_2/package_info/Optimal_transportation_reconstruction_2/dependencies @@ -1,6 +1,7 @@ Algebraic_foundations Circulator Distance_2 +Distance_3 Filtered_kernel Hash_map Installation @@ -20,4 +21,3 @@ Spatial_sorting Stream_support TDS_2 Triangulation_2 -Distance_3 diff --git a/Polygonal_surface_reconstruction/package_info/Polygonal_surface_reconstruction/dependencies b/Polygonal_surface_reconstruction/package_info/Polygonal_surface_reconstruction/dependencies index 8ad0841f42c..cf61d44e4ba 100644 --- a/Polygonal_surface_reconstruction/package_info/Polygonal_surface_reconstruction/dependencies +++ b/Polygonal_surface_reconstruction/package_info/Polygonal_surface_reconstruction/dependencies @@ -20,17 +20,17 @@ Modular_arithmetic Number_types Point_set_3 Point_set_processing_3 -Polygonal_surface_reconstruction Polygon +Polygonal_surface_reconstruction Principal_component_analysis Principal_component_analysis_LGPL Profiling_tools -Solver_interface Property_map Random_numbers +STL_Extension +Solver_interface Spatial_searching Spatial_sorting -STL_Extension Stream_support Surface_mesh TDS_2 diff --git a/Polyhedron/package_info/Polyhedron/dependencies b/Polyhedron/package_info/Polyhedron/dependencies index b810ef1e411..379a6bb6921 100644 --- a/Polyhedron/package_info/Polyhedron/dependencies +++ b/Polyhedron/package_info/Polyhedron/dependencies @@ -2,6 +2,7 @@ Algebraic_foundations BGL Circulator Distance_2 +Distance_3 GraphicsView HalfedgeDS Hash_map @@ -19,4 +20,3 @@ Profiling_tools Property_map STL_Extension Stream_support -Distance_3 diff --git a/Shape_detection/package_info/Shape_detection/dependencies b/Shape_detection/package_info/Shape_detection/dependencies index 2d92a3bf769..b5a74b46fe7 100644 --- a/Shape_detection/package_info/Shape_detection/dependencies +++ b/Shape_detection/package_info/Shape_detection/dependencies @@ -1,33 +1,33 @@ Algebraic_foundations +Arithmetic_kernel +BGL +Cartesian_kernel Circulator Distance_2 Distance_3 +Filtered_kernel +HalfedgeDS +Hash_map +Homogeneous_kernel Installation +Intersections_2 +Intersections_3 Interval_support Kernel_23 Kernel_d +Modifier Modular_arithmetic Number_types -Shape_detection +Polyhedron +Polyhedron_IO Principal_component_analysis Principal_component_analysis_LGPL Profiling_tools Property_map Random_numbers STL_Extension +Shape_detection Solver_interface Spatial_searching Stream_support -BGL -Arithmetic_kernel -Cartesian_kernel -Filtered_kernel -HalfedgeDS -Hash_map -Homogeneous_kernel -Intersections_2 -Intersections_3 -Modifier -Polyhedron -Polyhedron_IO Surface_mesh diff --git a/Surface_mesh_parameterization/package_info/Surface_mesh_parameterization/dependencies b/Surface_mesh_parameterization/package_info/Surface_mesh_parameterization/dependencies index b5bfe486174..6365759ce7c 100644 --- a/Surface_mesh_parameterization/package_info/Surface_mesh_parameterization/dependencies +++ b/Surface_mesh_parameterization/package_info/Surface_mesh_parameterization/dependencies @@ -3,6 +3,7 @@ BGL Box_intersection_d Circulator Distance_2 +Distance_3 Filtered_kernel Hash_map Installation @@ -25,4 +26,3 @@ Stream_support Surface_mesh_parameterization TDS_2 Triangulation_2 -Distance_3 diff --git a/Surface_mesh_segmentation/package_info/Surface_mesh_segmentation/dependencies b/Surface_mesh_segmentation/package_info/Surface_mesh_segmentation/dependencies index e22910d08fd..ea25e29aac6 100644 --- a/Surface_mesh_segmentation/package_info/Surface_mesh_segmentation/dependencies +++ b/Surface_mesh_segmentation/package_info/Surface_mesh_segmentation/dependencies @@ -4,6 +4,7 @@ BGL Cartesian_kernel Circulator Distance_2 +Distance_3 Installation Intersections_2 Intersections_3 @@ -18,4 +19,3 @@ STL_Extension Spatial_searching Stream_support Surface_mesh_segmentation -Distance_3 diff --git a/Surface_mesh_shortest_path/package_info/Surface_mesh_shortest_path/dependencies b/Surface_mesh_shortest_path/package_info/Surface_mesh_shortest_path/dependencies index a903992f736..0acb32e8813 100644 --- a/Surface_mesh_shortest_path/package_info/Surface_mesh_shortest_path/dependencies +++ b/Surface_mesh_shortest_path/package_info/Surface_mesh_shortest_path/dependencies @@ -4,6 +4,7 @@ BGL Cartesian_kernel Circulator Distance_2 +Distance_3 Installation Intersections_2 Intersections_3 @@ -18,4 +19,3 @@ STL_Extension Spatial_searching Stream_support Surface_mesh_shortest_path -Distance_3 diff --git a/Visibility_2/package_info/Visibility_2/dependencies b/Visibility_2/package_info/Visibility_2/dependencies index df17db35a32..bdaf92f883b 100644 --- a/Visibility_2/package_info/Visibility_2/dependencies +++ b/Visibility_2/package_info/Visibility_2/dependencies @@ -2,6 +2,7 @@ Algebraic_foundations Arrangement_on_surface_2 Circulator Distance_2 +Distance_3 Filtered_kernel HalfedgeDS Hash_map @@ -23,4 +24,3 @@ Surface_sweep_2 TDS_2 Triangulation_2 Visibility_2 -Distance_3 From 4f97bd5102b2d4c1589896017cf560cda6a3cc26 Mon Sep 17 00:00:00 2001 From: Laurent Rineau Date: Thu, 31 Oct 2019 14:46:34 +0100 Subject: [PATCH 272/363] Fix dependencies --- Property_map/package_info/Property_map/dependencies | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/Property_map/package_info/Property_map/dependencies b/Property_map/package_info/Property_map/dependencies index 4b1b3cb93f3..90b94d36b57 100644 --- a/Property_map/package_info/Property_map/dependencies +++ b/Property_map/package_info/Property_map/dependencies @@ -1,4 +1,11 @@ +Algebraic_foundations +BGL Installation +Interval_support Kernel_23 +Modular_arithmetic +Number_types Profiling_tools +Property_map STL_Extension +Stream_support From 21fedbf0ad06f81c7b0e015317c7d2e04a71c197 Mon Sep 17 00:00:00 2001 From: Laurent Rineau Date: Thu, 31 Oct 2019 18:34:08 +0100 Subject: [PATCH 273/363] Take the version number from `public_release_name` --- Documentation/doc/CMakeLists.txt | 14 ++++++++++---- .../cgal_create_release_with_cmake.cmake | 4 ++++ 2 files changed, 14 insertions(+), 4 deletions(-) diff --git a/Documentation/doc/CMakeLists.txt b/Documentation/doc/CMakeLists.txt index 83b0918e75f..71c80cb6777 100644 --- a/Documentation/doc/CMakeLists.txt +++ b/Documentation/doc/CMakeLists.txt @@ -253,10 +253,15 @@ if (NOT CGAL_CREATED_VERSION_NUM) set(CGAL_CREATED_VERSION_NUM "${CGAL_MAJOR_VERSION}.${CGAL_MINOR_VERSION}") endif() else() - #read version.h and get the line with CGAL_VERSION - file(STRINGS "${CGAL_ROOT}/include/CGAL/version.h" CGAL_VERSION_LINE REGEX "CGAL_VERSION ") - #extract release id - string(REGEX MATCH "[0-9]+\\.[0-9]+\\.?[0-9]*" CGAL_CREATED_VERSION_NUM "${CGAL_VERSION_LINE}") + if(EXISTS "${CGAL_ROOT}/doc/public_release_name") + file(STRINGS "${CGAL_ROOT}/doc/public_release_name" CGAL_VERSION_LINE) + string(REGEX REPLACE "CGAL-" "" CGAL_CREATED_VERSION_NUM "${CGAL_VERSION_LINE}") + else() + #read version.h and get the line with CGAL_VERSION + file(STRINGS "${CGAL_ROOT}/include/CGAL/version.h" CGAL_VERSION_LINE REGEX "CGAL_VERSION ") + #extract release id + string(REGEX MATCH "[0-9]+\\.[0-9]+\\.?[0-9]*" CGAL_CREATED_VERSION_NUM "${CGAL_VERSION_LINE}") + endif() endif() endif() @@ -264,6 +269,7 @@ endif() # closely to the convoluted versioning code and can adapt without a # huge diff. set(CGAL_DOC_VERSION ${CGAL_CREATED_VERSION_NUM}) +message(CGAL_DOC_VERSION: ${CGAL_DOC_VERSION}) ## generate how_to_cite files if(PYTHONINTERP_FOUND) diff --git a/Scripts/developer_scripts/cgal_create_release_with_cmake.cmake b/Scripts/developer_scripts/cgal_create_release_with_cmake.cmake index f6b3e42b7d7..38905c3e239 100644 --- a/Scripts/developer_scripts/cgal_create_release_with_cmake.cmake +++ b/Scripts/developer_scripts/cgal_create_release_with_cmake.cmake @@ -154,6 +154,10 @@ foreach(pkg ${files}) process_package(${pkg}) endif() endforeach() +if(EXISTS ${GIT_REPO}/Maintenance/release_building/public_release_name) + file(COPY "${GIT_REPO}/Maintenance/release_building/public_release_name" + DESTINATION "${release_dir}/doc") +endif() #create VERSION file(WRITE ${release_dir}/VERSION "${CGAL_VERSION}") From 463a43e23be079f5b8e20dd36d5f397baebcb2a5 Mon Sep 17 00:00:00 2001 From: Laurent Rineau Date: Thu, 31 Oct 2019 18:39:17 +0100 Subject: [PATCH 274/363] Fix the download URLS --- Documentation/doc/Documentation/Usage.txt | 4 ++-- Documentation/doc/Documentation/windows.txt | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/Documentation/doc/Documentation/Usage.txt b/Documentation/doc/Documentation/Usage.txt index 30b3627f683..b1a21d4c121 100644 --- a/Documentation/doc/Documentation/Usage.txt +++ b/Documentation/doc/Documentation/Usage.txt @@ -10,7 +10,7 @@ However, some dependencies of \cgal might still need to be installed. Assuming that you have obtained \cgal through one of the package managers offering \cgal on your platform (see Section \ref secgettingcgal), you can download \cgal examples ( -CGAL-\cgalReleaseNumber-examples.tar.xz) +CGAL-\cgalReleaseNumber-examples.tar.xz) and the compilation of an example is as simple as: cd $HOME/CGAL-\cgalReleaseNumber/examples/Triangulation_2 # go to an example directory @@ -51,7 +51,7 @@ acquire these dependencies. The examples and demos of \cgal are not included when you install \cgal with a package manager, and must be downloaded -here. +here. \subsection secusingpkgman Using a Package Manager diff --git a/Documentation/doc/Documentation/windows.txt b/Documentation/doc/Documentation/windows.txt index a45afc972a5..ca37e021001 100644 --- a/Documentation/doc/Documentation/windows.txt +++ b/Documentation/doc/Documentation/windows.txt @@ -60,7 +60,7 @@ Note that \cgal is a header-only library, and there are therefore no `lib` or `d In this section we show how to compile a program that uses \cgal. The examples you find in these User Manual pages are not downloaded when you install \cgal with the Vcpkg library manager. You must download them separately from the following download page: -CGAL-\cgalReleaseNumber-examples.zip +CGAL-\cgalReleaseNumber-examples.zip Assuming you have unzipped this file in your home directory `C:\Users\Me`, we will next compile an example from the 2D Triangulation package. From 0d4963f455609187d8a0e5130a46e6bd4673c41e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9bastien=20Loriot?= Date: Mon, 4 Nov 2019 09:24:22 +0100 Subject: [PATCH 275/363] also detect BSL --- Scripts/developer_scripts/licensecheck | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/Scripts/developer_scripts/licensecheck b/Scripts/developer_scripts/licensecheck index 8a1c55ee178..ce7a9c537d6 100755 --- a/Scripts/developer_scripts/licensecheck +++ b/Scripts/developer_scripts/licensecheck @@ -594,6 +594,10 @@ sub parselicense { $license = "LGPL (v3)"; } + if ($licensetext =~ /SPDX-License-Identifier BSL-1.0/i) { + $license = "BSL 1.0"; + } + if ($licensetext =~ /SPDX-License-Identifier LicenseRef-RFL/i) { $license = "MIT/X11 (BSD like)"; } From 9a0bff4008965ef14b7b9fbec7a46aa0403db35b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9bastien=20Loriot?= Date: Mon, 4 Nov 2019 10:59:15 +0100 Subject: [PATCH 276/363] remove BOOST_FOREACH added by recent PRs --- .../demo/Apollonius_graph_2/Apollonius_graph_2.cpp | 2 +- .../demo/Bounding_volumes/Bounding_volumes.cpp | 2 +- .../Segment_Delaunay_graph_2/Segment_voronoi_2.cpp | 4 ++-- .../Segment_voronoi_linf_2.cpp | 6 +++--- GraphicsView/demo/Snap_rounding_2/Snap_rounding_2.cpp | 4 ++-- .../Constrained_Delaunay_triangulation_2.cpp | 10 +++++----- .../demo/Triangulation_2/Regular_triangulation_2.cpp | 2 +- Point_set_3/examples/Point_set_3/point_set_algo.cpp | 2 +- .../internal/Corefinement/Face_graph_output_builder.h | 10 +++++----- .../polygon_mesh_slicer_test.cpp | 2 +- .../Polygon_mesh_processing/test_pmp_manifoldness.cpp | 2 -- .../demo/Polyhedron/Plugins/AABB_tree/Cut_plugin.cpp | 4 ++-- .../Polyhedron/Plugins/PCA/Affine_transform_plugin.cpp | 2 +- .../Plugins/Point_set/Alpha_shape_plugin.cpp | 2 +- Polyhedron/demo/Polyhedron/Scene_c3t3_item.cpp | 8 ++++---- Polyhedron/demo/Polyhedron/Scene_surface_mesh_item.cpp | 2 +- .../Polyhedron/Scene_textured_surface_mesh_item.cpp | 2 +- .../Polyline_simplification_2.cpp | 4 ++-- STL_Extension/include/CGAL/Iterator_range.h | 1 - .../examples/Stream_support/Linestring_WKT.cpp | 7 +++---- Stream_support/examples/Stream_support/Point_WKT.cpp | 4 +--- Stream_support/examples/Stream_support/Polygon_WKT.cpp | 6 ++---- Stream_support/examples/Stream_support/read_WKT.cpp | 10 ++++------ Stream_support/test/Stream_support/test_read_WKT.cpp | 2 -- Stream_support/test/Stream_support/test_write_WKT.cpp | 2 -- .../examples/Surface_mesh/sm_draw_small_faces.cpp | 3 +-- 26 files changed, 45 insertions(+), 60 deletions(-) diff --git a/GraphicsView/demo/Apollonius_graph_2/Apollonius_graph_2.cpp b/GraphicsView/demo/Apollonius_graph_2/Apollonius_graph_2.cpp index c41b84b8682..c97a51fe090 100644 --- a/GraphicsView/demo/Apollonius_graph_2/Apollonius_graph_2.cpp +++ b/GraphicsView/demo/Apollonius_graph_2/Apollonius_graph_2.cpp @@ -244,7 +244,7 @@ MainWindow::open(QString fileName) #if BOOST_VERSION >= 105600 && (! defined(BOOST_GCC) || BOOST_GCC >= 40500) std::vector point_3_s; CGAL::read_multi_point_WKT(ifs, point_3_s); - BOOST_FOREACH(const K::Point_3& point_3, point_3_s) + for(const K::Point_3& point_3 : point_3_s) { points.push_back(Apollonius_site_2(K::Point_2(point_3.x(), point_3.y()), point_3.z())); } diff --git a/GraphicsView/demo/Bounding_volumes/Bounding_volumes.cpp b/GraphicsView/demo/Bounding_volumes/Bounding_volumes.cpp index 45e25999ed1..9cd70810ec0 100644 --- a/GraphicsView/demo/Bounding_volumes/Bounding_volumes.cpp +++ b/GraphicsView/demo/Bounding_volumes/Bounding_volumes.cpp @@ -499,7 +499,7 @@ MainWindow::open(QString fileName) { #if BOOST_VERSION >= 105600 && (! defined(BOOST_GCC) || BOOST_GCC >= 40500) CGAL::read_multi_point_WKT(ifs, points); - BOOST_FOREACH(K::Point_2 p, points) + for(K::Point_2 p : points) { mc.insert(p); me.insert(p); diff --git a/GraphicsView/demo/Segment_Delaunay_graph_2/Segment_voronoi_2.cpp b/GraphicsView/demo/Segment_Delaunay_graph_2/Segment_voronoi_2.cpp index 7399174b30a..4694a2a496c 100644 --- a/GraphicsView/demo/Segment_Delaunay_graph_2/Segment_voronoi_2.cpp +++ b/GraphicsView/demo/Segment_Delaunay_graph_2/Segment_voronoi_2.cpp @@ -358,7 +358,7 @@ MainWindow::loadWKTConstraints(QString do{ std::vector polygons; CGAL::read_multi_polygon_WKT(ifs, polygons); - BOOST_FOREACH(const Polygon& poly, polygons) + for(const Polygon& poly : polygons) { if(poly.outer_boundary().is_empty()) continue; @@ -388,7 +388,7 @@ MainWindow::loadWKTConstraints(QString do{ std::vector linestrings; CGAL::read_multi_linestring_WKT(ifs, linestrings); - BOOST_FOREACH(const LineString& ls, linestrings) + for(const LineString& ls : linestrings) { bool first_pass=true; LineString::const_iterator it = ls.begin(); diff --git a/GraphicsView/demo/Segment_Delaunay_graph_Linf_2/Segment_voronoi_linf_2.cpp b/GraphicsView/demo/Segment_Delaunay_graph_Linf_2/Segment_voronoi_linf_2.cpp index ee5ee603726..4b4c74514ff 100644 --- a/GraphicsView/demo/Segment_Delaunay_graph_Linf_2/Segment_voronoi_linf_2.cpp +++ b/GraphicsView/demo/Segment_Delaunay_graph_Linf_2/Segment_voronoi_linf_2.cpp @@ -401,7 +401,7 @@ MainWindow::loadWKT(QString { std::vector mpts; CGAL::read_multi_point_WKT(ifs, mpts); - BOOST_FOREACH(const K::Point_2& p, mpts) + for(const K::Point_2& p : mpts) svd.insert(p); }while(ifs.good() && !ifs.eof()); //Lines @@ -412,7 +412,7 @@ MainWindow::loadWKT(QString typedef std::vector LineString; std::vector mls; CGAL::read_multi_linestring_WKT(ifs, mls); - BOOST_FOREACH(const LineString& ls, mls) + for(const LineString& ls : mls) { if(ls.empty()) continue; @@ -450,7 +450,7 @@ MainWindow::loadWKT(QString typedef CGAL::Polygon_with_holes_2 Polygon; std::vector mps; CGAL::read_multi_polygon_WKT(ifs, mps); - BOOST_FOREACH(const Polygon& poly, mps) + for(const Polygon& poly : mps) { if(poly.outer_boundary().is_empty()) continue; diff --git a/GraphicsView/demo/Snap_rounding_2/Snap_rounding_2.cpp b/GraphicsView/demo/Snap_rounding_2/Snap_rounding_2.cpp index 4be765f84c8..cd337a2b470 100644 --- a/GraphicsView/demo/Snap_rounding_2/Snap_rounding_2.cpp +++ b/GraphicsView/demo/Snap_rounding_2/Snap_rounding_2.cpp @@ -273,7 +273,7 @@ MainWindow::open(QString fileName) #if BOOST_VERSION >= 105600 && (! defined(BOOST_GCC) || BOOST_GCC >= 40500) std::vector > mls; CGAL::read_multi_linestring_WKT(ifs, mls); - BOOST_FOREACH(const std::vector& ls, mls) + for(const std::vector& ls : mls) { if(ls.size() > 2) continue; @@ -315,7 +315,7 @@ MainWindow::on_actionSaveSegments_triggered() { #if BOOST_VERSION >= 105600 && (! defined(BOOST_GCC) || BOOST_GCC >= 40500) std::vector >mls; - BOOST_FOREACH(const Segment_2& seg, input) + for(const Segment_2& seg : input) { std::vector ls(2); ls[0] = seg.source(); diff --git a/GraphicsView/demo/Triangulation_2/Constrained_Delaunay_triangulation_2.cpp b/GraphicsView/demo/Triangulation_2/Constrained_Delaunay_triangulation_2.cpp index 008e227d28c..697b6ca1e00 100644 --- a/GraphicsView/demo/Triangulation_2/Constrained_Delaunay_triangulation_2.cpp +++ b/GraphicsView/demo/Triangulation_2/Constrained_Delaunay_triangulation_2.cpp @@ -572,12 +572,12 @@ MainWindow::loadWKT(QString typedef CGAL::Point_2 Point; std::vector mps; CGAL::read_multi_polygon_WKT(ifs, mps); - BOOST_FOREACH(const Polygon& p, mps) + for(const Polygon& p : mps) { if(p.outer_boundary().is_empty()) continue; - BOOST_FOREACH(Point point, p.outer_boundary().container()) + for(Point point : p.outer_boundary().container()) cdt.insert(point); for(Polygon::General_polygon_2::Edge_const_iterator e_it=p.outer_boundary().edges_begin(); e_it != p.outer_boundary().edges_end(); ++e_it) @@ -586,7 +586,7 @@ MainWindow::loadWKT(QString for(Polygon::Hole_const_iterator h_it = p.holes_begin(); h_it != p.holes_end(); ++h_it) { - BOOST_FOREACH(Point point, h_it->container()) + for(Point point : h_it->container()) cdt.insert(point); for(Polygon::General_polygon_2::Edge_const_iterator e_it=h_it->edges_begin(); e_it != h_it->edges_end(); ++e_it) @@ -604,7 +604,7 @@ MainWindow::loadWKT(QString typedef std::vector LineString; std::vector mls; CGAL::read_multi_linestring_WKT(ifs, mls); - BOOST_FOREACH(const LineString& ls, mls) + for(const LineString& ls : mls) { if(ls.empty()) continue; @@ -642,7 +642,7 @@ MainWindow::loadWKT(QString { std::vector mpts; CGAL::read_multi_point_WKT(ifs, mpts); - BOOST_FOREACH(const K::Point_2& p, mpts) + for(const K::Point_2& p : mpts) { cdt.insert(p); } diff --git a/GraphicsView/demo/Triangulation_2/Regular_triangulation_2.cpp b/GraphicsView/demo/Triangulation_2/Regular_triangulation_2.cpp index ca1023d4b1d..002050f4952 100644 --- a/GraphicsView/demo/Triangulation_2/Regular_triangulation_2.cpp +++ b/GraphicsView/demo/Triangulation_2/Regular_triangulation_2.cpp @@ -260,7 +260,7 @@ MainWindow::on_actionLoadPoints_triggered() #if BOOST_VERSION >= 105600 && (! defined(BOOST_GCC) || BOOST_GCC >= 40500) std::vector points_3; CGAL::read_multi_point_WKT(ifs, points_3); - BOOST_FOREACH(const K::Point_3& p, points_3) + for(const K::Point_3& p : points_3) { points.push_back(Weighted_point_2(K::Point_2(p.x(), p.y()), p.z())); } diff --git a/Point_set_3/examples/Point_set_3/point_set_algo.cpp b/Point_set_3/examples/Point_set_3/point_set_algo.cpp index 80e42dcef6d..f87a4b3e4ef 100644 --- a/Point_set_3/examples/Point_set_3/point_set_algo.cpp +++ b/Point_set_3/examples/Point_set_3/point_set_algo.cpp @@ -70,7 +70,7 @@ int main (int, char**) parameters.normal_threshold = 0.9; ransac.detect(parameters); - BOOST_FOREACH(boost::shared_ptr shape, ransac.shapes()) + for(boost::shared_ptr shape : ransac.shapes()) if (Sphere* sphere = dynamic_cast(shape.get())) std::cerr << "Detected sphere of center " << sphere->center() // Center should be approx 0, 0, 0 << " and of radius " << sphere->radius() << std::endl; // Radius should be approx 1 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 3e585fe691c..d8256bf17d6 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 @@ -1259,7 +1259,7 @@ public: // non-manifold vertices would not be duplicated in interior // vertices of patche) // special code to handle non-manifold vertices on the boundary - BOOST_FOREACH (vertex_descriptor vd, vertices(tm1)) + for (vertex_descriptor vd : vertices(tm1)) { boost::optional op_h = is_border(vd, tm1); if (op_h == boost::none) continue; @@ -1629,12 +1629,12 @@ public: } // Code dedicated to the handling of non-manifold vertices - BOOST_FOREACH(vertex_descriptor vd, border_nm_vertices) + for(vertex_descriptor vd : border_nm_vertices) { // first check if at least one incident patch will be kept boost::unordered_set id_p_rm; bool all_removed=true; - BOOST_FOREACH(halfedge_descriptor h, halfedges_around_target(vd, tm1)) + for(halfedge_descriptor h : halfedges_around_target(vd, tm1)) { face_descriptor f = face(h, tm1); if ( f != GT::null_face() ) @@ -1649,7 +1649,7 @@ public: if (all_removed) id_p_rm.erase(id_p_rm.begin()); // remove the vertex from the interior vertices of patches to be removed - BOOST_FOREACH(std::size_t pid, id_p_rm) + for(std::size_t pid : id_p_rm) patches_of_tm1[pid].interior_vertices.erase(vd); // we now need to update the next/prev relationship induced by the future removal of patches @@ -1703,7 +1703,7 @@ public: while(true); if (hit == end) break; } - BOOST_FOREACH ( const Hedge_pair& p, hedges_to_link) + for(const Hedge_pair& p : hedges_to_link) set_next(p.first, p.second, tm1); } } diff --git a/Polygon_mesh_processing/test/Polygon_mesh_processing/polygon_mesh_slicer_test.cpp b/Polygon_mesh_processing/test/Polygon_mesh_processing/polygon_mesh_slicer_test.cpp index 223a1c58aa0..526bea44ee6 100644 --- a/Polygon_mesh_processing/test/Polygon_mesh_processing/polygon_mesh_slicer_test.cpp +++ b/Polygon_mesh_processing/test/Polygon_mesh_processing/polygon_mesh_slicer_test.cpp @@ -28,7 +28,7 @@ bool is_ccw(int xi, int yi, CGAL::Polygon_2 polygon; if(polyline.front() == polyline.back()) { - BOOST_FOREACH(const typename K::Point_3& p, polyline) + for(const typename K::Point_3& p : polyline) { polygon.push_back(typename K::Point_2(p[xi], p[yi])); } diff --git a/Polygon_mesh_processing/test/Polygon_mesh_processing/test_pmp_manifoldness.cpp b/Polygon_mesh_processing/test/Polygon_mesh_processing/test_pmp_manifoldness.cpp index 788a22e428a..c4b8a98d2fa 100644 --- a/Polygon_mesh_processing/test/Polygon_mesh_processing/test_pmp_manifoldness.cpp +++ b/Polygon_mesh_processing/test/Polygon_mesh_processing/test_pmp_manifoldness.cpp @@ -6,8 +6,6 @@ #include #include -#include - #include #include #include diff --git a/Polyhedron/demo/Polyhedron/Plugins/AABB_tree/Cut_plugin.cpp b/Polyhedron/demo/Polyhedron/Plugins/AABB_tree/Cut_plugin.cpp index ca66b7ce18a..d7a3863ce3a 100644 --- a/Polyhedron/demo/Polyhedron/Plugins/AABB_tree/Cut_plugin.cpp +++ b/Polyhedron/demo/Polyhedron/Plugins/AABB_tree/Cut_plugin.cpp @@ -258,7 +258,7 @@ public: is_tree_empty = tree.empty(); nb_lines = positions_lines.size(); setEdgeContainer(0, new Ec(Vi::PROGRAM_NO_SELECTION, false)); - BOOST_FOREACH(auto v, CGAL::QGLViewer::QGLViewerPool()) + for(auto v : CGAL::QGLViewer::QGLViewerPool()) { CGAL::Three::Viewer_interface* viewer = static_cast(v); initGL(viewer); @@ -488,7 +488,7 @@ public: setEdgeContainer(0, new Ec(Vi::PROGRAM_NO_SELECTION, false)); texture = new ::Texture(m_grid_size,m_grid_size); getTriangleContainer(0)->setTextureSize(QSize(m_grid_size, m_grid_size)); - BOOST_FOREACH(auto v, CGAL::QGLViewer::QGLViewerPool()) + for(auto v : CGAL::QGLViewer::QGLViewerPool()) { CGAL::Three::Viewer_interface* viewer = static_cast(v); initGL(viewer); diff --git a/Polyhedron/demo/Polyhedron/Plugins/PCA/Affine_transform_plugin.cpp b/Polyhedron/demo/Polyhedron/Plugins/PCA/Affine_transform_plugin.cpp index b9766dec3ff..98851af36e8 100644 --- a/Polyhedron/demo/Polyhedron/Plugins/PCA/Affine_transform_plugin.cpp +++ b/Polyhedron/demo/Polyhedron/Plugins/PCA/Affine_transform_plugin.cpp @@ -64,7 +64,7 @@ public: bbox.xmax(),bbox.ymax(),bbox.zmax())); nb_points = points.size(); - BOOST_FOREACH(auto v, CGAL::QGLViewer::QGLViewerPool()) + for(auto v : CGAL::QGLViewer::QGLViewerPool()) { CGAL::Three::Viewer_interface* viewer = static_cast(v); initGL(viewer); diff --git a/Polyhedron/demo/Polyhedron/Plugins/Point_set/Alpha_shape_plugin.cpp b/Polyhedron/demo/Polyhedron/Plugins/Point_set/Alpha_shape_plugin.cpp index bda125617a5..86d819b5b21 100644 --- a/Polyhedron/demo/Polyhedron/Plugins/Point_set/Alpha_shape_plugin.cpp +++ b/Polyhedron/demo/Polyhedron/Plugins/Point_set/Alpha_shape_plugin.cpp @@ -305,7 +305,7 @@ Scene_alpha_shape_item::Scene_alpha_shape_item(Scene_points_with_normal_item *po vertices.push_back(it->point().y()+offset.y); vertices.push_back(it->point().z()+offset.z); } - BOOST_FOREACH(auto v, CGAL::QGLViewer::QGLViewerPool()) + for(auto v : CGAL::QGLViewer::QGLViewerPool()) { CGAL::Three::Viewer_interface* viewer = static_cast(v); if(!isInit(viewer)) diff --git a/Polyhedron/demo/Polyhedron/Scene_c3t3_item.cpp b/Polyhedron/demo/Polyhedron/Scene_c3t3_item.cpp index a1343e70134..9ad4cfa9dc2 100644 --- a/Polyhedron/demo/Polyhedron/Scene_c3t3_item.cpp +++ b/Polyhedron/demo/Polyhedron/Scene_c3t3_item.cpp @@ -532,7 +532,7 @@ void Scene_c3t3_item::common_constructor(bool is_surface) setEdgeContainer(Grid_edges, new Ec(Vi::PROGRAM_NO_SELECTION, false)); setEdgeContainer(C3t3_edges, new Ec(Vi::PROGRAM_C3T3_EDGES, false)); setPointContainer(C3t3_points, new Pc(Vi::PROGRAM_C3T3_EDGES, false)); - BOOST_FOREACH(auto v, CGAL::QGLViewer::QGLViewerPool()) + for(auto v : CGAL::QGLViewer::QGLViewerPool()) { v->installEventFilter(this); } @@ -611,7 +611,7 @@ void Scene_c3t3_item::updateCutPlane() if(!d) return; if(d->need_changed) { - BOOST_FOREACH(auto v, CGAL::QGLViewer::QGLViewerPool()) + for(auto v : CGAL::QGLViewer::QGLViewerPool()) { CGAL::Three::Viewer_interface* viewer = static_cast(v); d->are_intersection_buffers_filled[viewer] = false; @@ -1581,7 +1581,7 @@ Scene_c3t3_item::setColor(QColor c) d->compute_color_map(c); invalidateOpenGLBuffers(); d->invalidate_stats(); - BOOST_FOREACH(auto v, CGAL::QGLViewer::QGLViewerPool()) + for(auto v : CGAL::QGLViewer::QGLViewerPool()) { CGAL::Three::Viewer_interface* viewer = static_cast(v); d->are_intersection_buffers_filled[viewer] = false; @@ -1636,7 +1636,7 @@ void Scene_c3t3_item::show_intersection(bool b) d->intersection->setRenderingMode(renderingMode()); connect(d->intersection, SIGNAL(destroyed()), this, SLOT(reset_intersection_item())); - BOOST_FOREACH(auto v, CGAL::QGLViewer::QGLViewerPool()) + for(auto v : CGAL::QGLViewer::QGLViewerPool()) { CGAL::Three::Viewer_interface* viewer = static_cast(v); d->are_intersection_buffers_filled[viewer] = false; diff --git a/Polyhedron/demo/Polyhedron/Scene_surface_mesh_item.cpp b/Polyhedron/demo/Polyhedron/Scene_surface_mesh_item.cpp index 09dd204eff6..a25bd48cadf 100644 --- a/Polyhedron/demo/Polyhedron/Scene_surface_mesh_item.cpp +++ b/Polyhedron/demo/Polyhedron/Scene_surface_mesh_item.cpp @@ -1295,7 +1295,7 @@ void Scene_surface_mesh_item::invalidate(Gl_data_names name) getEdgeContainer(0)->reset_vbos(name); getPointContainer(0)->reset_vbos(name); bool has_been_init = false; - BOOST_FOREACH(CGAL::QGLViewer* v, CGAL::QGLViewer::QGLViewerPool()) + for(CGAL::QGLViewer* v : CGAL::QGLViewer::QGLViewerPool()) { CGAL::Three::Viewer_interface* viewer = static_cast(v); if(!isInit(viewer)) diff --git a/Polyhedron/demo/Polyhedron/Scene_textured_surface_mesh_item.cpp b/Polyhedron/demo/Polyhedron/Scene_textured_surface_mesh_item.cpp index 816d37d3e60..8d9f55a455f 100644 --- a/Polyhedron/demo/Polyhedron/Scene_textured_surface_mesh_item.cpp +++ b/Polyhedron/demo/Polyhedron/Scene_textured_surface_mesh_item.cpp @@ -165,7 +165,7 @@ void Scene_textured_surface_mesh_item::common_constructor() setEdgeContainer(0, new Ec(Vi::PROGRAM_WITH_TEXTURED_EDGES, false));//edges getTriangleContainer(0)->setTextureSize(QSize(d->texture.GetWidth(), d->texture.GetHeight())); getEdgeContainer(0)->setTextureSize(QSize(d->texture.GetWidth(), d->texture.GetHeight())); - BOOST_FOREACH(auto v, CGAL::QGLViewer::QGLViewerPool()) + for(auto v : CGAL::QGLViewer::QGLViewerPool()) { CGAL::Three::Viewer_interface* viewer = static_cast(v); initGL(viewer); diff --git a/Polyline_simplification_2/demo/Polyline_simplification_2/Polyline_simplification_2.cpp b/Polyline_simplification_2/demo/Polyline_simplification_2/Polyline_simplification_2.cpp index 30a29401f2a..610fefba342 100644 --- a/Polyline_simplification_2/demo/Polyline_simplification_2/Polyline_simplification_2.cpp +++ b/Polyline_simplification_2/demo/Polyline_simplification_2/Polyline_simplification_2.cpp @@ -406,12 +406,12 @@ void MainWindow::loadWKT(QString if(! points.empty()){ std::cout << "Ignore " << points.size() << " isolated points" << std::endl; } - BOOST_FOREACH(LineString poly, polylines){ + for(LineString poly : polylines){ if ( poly.size() > 2 ){ m_pct.insert_constraint(poly.begin(), poly.end()); } } - BOOST_FOREACH(Polygon_with_holes_2 poly, polygons){ + for(Polygon_with_holes_2 poly : polygons){ m_pct.insert_constraint(poly.outer_boundary().vertices_begin(), poly.outer_boundary().vertices_end()); for(Polygon_with_holes_2::Hole_const_iterator it = poly.holes_begin(); it != poly.holes_end(); ++it){ const Polygon_2& hole = *it; diff --git a/STL_Extension/include/CGAL/Iterator_range.h b/STL_Extension/include/CGAL/Iterator_range.h index 06a71f09240..d71cb07f671 100644 --- a/STL_Extension/include/CGAL/Iterator_range.h +++ b/STL_Extension/include/CGAL/Iterator_range.h @@ -13,7 +13,6 @@ #define CGAL_ITERATOR_RANGE_H #include -#include #include namespace CGAL { diff --git a/Stream_support/examples/Stream_support/Linestring_WKT.cpp b/Stream_support/examples/Stream_support/Linestring_WKT.cpp index 5c95562620a..ebc863f9ee3 100644 --- a/Stream_support/examples/Stream_support/Linestring_WKT.cpp +++ b/Stream_support/examples/Stream_support/Linestring_WKT.cpp @@ -6,7 +6,6 @@ #include #include -#include //must be included before WKT for some reason #include #include #include @@ -27,7 +26,7 @@ int main(int argc, char* argv[]) CGAL::read_linestring_WKT(is, ls); is.close(); } - BOOST_FOREACH(Point p, ls) + for(Point p : ls) std::cout< #include -#include - #include //typedef CGAL::Simple_cartesian Kernel; @@ -26,7 +24,7 @@ int main(int argc, char* argv[]) std::ifstream is((argc>1)?argv[1]:"data/multipoint.wkt"); MultiPoint mp; CGAL::read_multi_point_WKT(is, mp); - BOOST_FOREACH(const Point& p, mp) + for(const Point& p : mp) { std::cout< #include -#include - #include #include @@ -35,7 +33,7 @@ int main(int argc, char* argv[]) if(!p.outer_boundary().is_empty()) polys.push_back(p); }while(is.good() && !is.eof()); - BOOST_FOREACH(Polygon p, polys) + for(Polygon p : polys) std::cout<2)?argv[2]:"data/multipolygon.wkt"); MultiPolygon mp; CGAL::read_multi_polygon_WKT(is, mp); - BOOST_FOREACH(Polygon p, mp) + for(Polygon p : mp) std::cout< #include -#include - #include //typedef CGAL::Simple_cartesian Kernel; @@ -35,12 +33,12 @@ int main(int argc, char* argv[]) MultiPolygon polygons; CGAL::read_WKT(is, points,polylines,polygons); - BOOST_FOREACH(Point p, points) + for(Point p : points) std::cout< #include -#include - #include typedef CGAL::Exact_predicates_inexact_constructions_kernel Kernel; diff --git a/Stream_support/test/Stream_support/test_write_WKT.cpp b/Stream_support/test/Stream_support/test_write_WKT.cpp index 9586021beb9..ac602a67a93 100644 --- a/Stream_support/test/Stream_support/test_write_WKT.cpp +++ b/Stream_support/test/Stream_support/test_write_WKT.cpp @@ -11,8 +11,6 @@ #include #include -#include - #include typedef CGAL::Exact_predicates_inexact_constructions_kernel Kernel; diff --git a/Surface_mesh/examples/Surface_mesh/sm_draw_small_faces.cpp b/Surface_mesh/examples/Surface_mesh/sm_draw_small_faces.cpp index 3ab87459e1d..5d07f8a2dfa 100644 --- a/Surface_mesh/examples/Surface_mesh/sm_draw_small_faces.cpp +++ b/Surface_mesh/examples/Surface_mesh/sm_draw_small_faces.cpp @@ -4,7 +4,6 @@ #include #include #include -#include #include "draw_surface_mesh_small_faces.h" typedef CGAL::Simple_cartesian K; @@ -26,7 +25,7 @@ int main(int argc, char* argv[]) boost::tie(faces_size, created)=sm.add_property_map("f:size",0.); CGAL_assertion(created); - BOOST_FOREACH(face_descriptor fd, sm.faces()) + for(face_descriptor fd : sm.faces()) { faces_size[fd]=CGAL::Polygon_mesh_processing::face_area(fd, sm); } draw_surface_mesh_with_small_faces(sm); From b9a079b53056e0d9a8c07b436e0f0d2ffdf31168 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9bastien=20Loriot?= Date: Mon, 4 Nov 2019 11:34:53 +0100 Subject: [PATCH 277/363] remove cpp11/cpp0x --- .../CGAL/Classification/Feature/Color_channel.h | 2 +- NewKernel_d/include/CGAL/NewKernel_d/Lazy_cartesian.h | 2 +- Polygon/include/CGAL/Polygon_2.h | 2 +- .../internal/Corefinement/Face_graph_output_builder.h | 2 +- .../test/Polygon_mesh_processing/test_pmp_clip.cpp | 8 ++++---- Polyhedron_IO/include/CGAL/IO/PLY_reader.h | 2 +- Stream_support/include/CGAL/IO/Color.h | 10 +++++----- .../CGAL/Surface_sweep_2/Surface_sweep_2_impl.h | 2 +- 8 files changed, 15 insertions(+), 15 deletions(-) diff --git a/Classification/include/CGAL/Classification/Feature/Color_channel.h b/Classification/include/CGAL/Classification/Feature/Color_channel.h index 87c4dfa2394..2024c8706e3 100644 --- a/Classification/include/CGAL/Classification/Feature/Color_channel.h +++ b/Classification/include/CGAL/Classification/Feature/Color_channel.h @@ -99,7 +99,7 @@ public: /// \cond SKIP_IN_MANUAL virtual float value (std::size_t pt_index) { - cpp11::array c = get(color_map, *(input.begin()+pt_index)).to_hsv(); + std::array c = get(color_map, *(input.begin()+pt_index)).to_hsv(); return float(c[std::size_t(m_channel)]); } /// \endcond diff --git a/NewKernel_d/include/CGAL/NewKernel_d/Lazy_cartesian.h b/NewKernel_d/include/CGAL/NewKernel_d/Lazy_cartesian.h index e49ba75d9d1..5e0e24254fe 100644 --- a/NewKernel_d/include/CGAL/NewKernel_d/Lazy_cartesian.h +++ b/NewKernel_d/include/CGAL/NewKernel_d/Lazy_cartesian.h @@ -30,7 +30,7 @@ struct Nth_iterator_element : private Store_kernel { typedef typename Get_type::value_tag>::type result_type; template result_type operator()(U&& u, int i) const { typename Get_functor >::type ci(this->kernel()); - return *cpp0x::next(ci(std::forward(u),Begin_tag()),i); + return *std::next(ci(std::forward(u),Begin_tag()),i); } }; //typedef typename Functor::nth_element>::type nth_elem; diff --git a/Polygon/include/CGAL/Polygon_2.h b/Polygon/include/CGAL/Polygon_2.h index 290a6a5a6e6..e18bf7bde52 100644 --- a/Polygon/include/CGAL/Polygon_2.h +++ b/Polygon/include/CGAL/Polygon_2.h @@ -445,7 +445,7 @@ class Polygon_2 { Point_2& vertex(std::size_t i) { CGAL_precondition( i < d_container.size() ); - return *(cpp11::next(d_container.begin(), i)); + return *(std::next(d_container.begin(), i)); } /// Returns a reference to the `i`-th vertex. Point_2& operator[](std::size_t i) 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 d8256bf17d6..2f93d176784 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 @@ -1694,7 +1694,7 @@ public: else { // we push-back the halfedge for the next round only if it was not the first - if (h != *cpp11::prev(hit)) + if (h != *std::prev(hit)) --hit; break; } diff --git a/Polygon_mesh_processing/test/Polygon_mesh_processing/test_pmp_clip.cpp b/Polygon_mesh_processing/test/Polygon_mesh_processing/test_pmp_clip.cpp index e94e16c511b..f330133421e 100644 --- a/Polygon_mesh_processing/test/Polygon_mesh_processing/test_pmp_clip.cpp +++ b/Polygon_mesh_processing/test/Polygon_mesh_processing/test_pmp_clip.cpp @@ -296,7 +296,7 @@ void test() ss.str(std::string()); ss << "OFF\n 7 4 0\n 0 0 0\n2 0 0\n4 0 0\n4 1 0\n0 1 0\n3 1 0\n 1 1 0\n3 0 1 4\n3 1 2 3\n3 1 5 6\n3 1 3 5\n"; ss >> tm1; - CGAL::Euler::remove_face(halfedge(*CGAL::cpp11::prev(faces(tm1).end()),tm1),tm1); + CGAL::Euler::remove_face(halfedge(*std::prev(faces(tm1).end()),tm1),tm1); PMP::clip(tm1, K::Plane_3(-1,0,0,2)); assert(vertices(tm1).size()==6); CGAL::clear(tm1); @@ -305,7 +305,7 @@ void test() ss << "OFF\n 9 7 0\n 0 0 0\n2 0 0\n4 0 0\n4 1 0\n0 1 0\n3 1 0\n 1 1 0\n3 -1 0\n1 -1 0\n3 0 1 4\n3 1 2 3\n3 1 5 6\n3 1 8 7\n3 1 3 5\n3 1 6 4\n3 1 0 8\n"; ss >> tm1; for (int i=0;i<3;++i) - CGAL::Euler::remove_face(halfedge(*CGAL::cpp11::prev(faces(tm1).end()),tm1),tm1); + CGAL::Euler::remove_face(halfedge(*std::prev(faces(tm1).end()),tm1),tm1); PMP::clip(tm1, K::Plane_3(-1,0,0,2)); assert(vertices(tm1).size()==7); CGAL::clear(tm1); @@ -314,7 +314,7 @@ void test() ss << "OFF\n 9 7 0\n 0 0 0\n2 0 0\n4 0 0\n4 1 0\n0 1 0\n3 1 0\n 1 1 0\n3 -1 0\n1 -1 0\n3 0 1 4\n3 1 2 3\n3 1 5 6\n3 1 8 7\n3 1 3 5\n3 1 6 4\n3 1 0 8\n"; ss >> tm1; for (int i=0;i<3;++i) - CGAL::Euler::remove_face(halfedge(*CGAL::cpp11::prev(faces(tm1).end()),tm1),tm1); + CGAL::Euler::remove_face(halfedge(*std::prev(faces(tm1).end()),tm1),tm1); PMP::clip(tm1, K::Plane_3(0,1,0,0)); assert(vertices(tm1).size()==3); CGAL::clear(tm1); @@ -323,7 +323,7 @@ void test() ss << "OFF\n 9 7 0\n 0 0 0\n2 0 0\n4 0 0\n4 1 0\n0 1 0\n3 1 0\n 1 1 0\n3 -1 0\n1 -1 0\n3 0 1 4\n3 1 2 3\n3 1 5 6\n3 1 8 7\n3 1 3 5\n3 1 6 4\n3 1 0 8\n"; ss >> tm1; for (int i=0;i<3;++i) - CGAL::Euler::remove_face(halfedge(*CGAL::cpp11::prev(faces(tm1).end()),tm1),tm1); + CGAL::Euler::remove_face(halfedge(*std::prev(faces(tm1).end()),tm1),tm1); PMP::clip(tm1, K::Plane_3(0,-1,0,0)); assert(vertices(tm1).size()==7); CGAL::clear(tm1); diff --git a/Polyhedron_IO/include/CGAL/IO/PLY_reader.h b/Polyhedron_IO/include/CGAL/IO/PLY_reader.h index 2700ac740ff..ada0165c981 100644 --- a/Polyhedron_IO/include/CGAL/IO/PLY_reader.h +++ b/Polyhedron_IO/include/CGAL/IO/PLY_reader.h @@ -266,7 +266,7 @@ namespace CGAL{ { has_uv = true; } - cpp11::tuple new_hedge; + std::tuple new_hedge; for (std::size_t j = 0; j < element.number_of_items(); ++ j) { for (std::size_t k = 0; k < element.number_of_properties(); ++ k) diff --git a/Stream_support/include/CGAL/IO/Color.h b/Stream_support/include/CGAL/IO/Color.h index 1c9e2709112..bfe902ab8d4 100644 --- a/Stream_support/include/CGAL/IO/Color.h +++ b/Stream_support/include/CGAL/IO/Color.h @@ -48,7 +48,7 @@ class Color { private: - cpp11::array m_data; + std::array m_data; public: @@ -159,21 +159,21 @@ public: /*! returns the array with rgba values. */ - const cpp11::array& to_rgba() const { return m_data; } + const std::array& to_rgba() const { return m_data; } /*! returns the array with rgb values. */ - const cpp11::array& to_rgb() const + const std::array& to_rgb() const { - return reinterpret_cast&>(m_data); + return reinterpret_cast&>(m_data); } /*! computes the hsv (hue, saturation, value) values and returns an array representing them as float values between 0 and 1. */ - cpp11::array to_hsv() const + std::array to_hsv() const { double r = (double)(m_data[0]) / 255.; double g = (double)(m_data[1]) / 255.; 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 e0379d49771..19ec5d88584 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 @@ -280,7 +280,7 @@ void Surface_sweep_2::_handle_overlaps_in_right_curves() Subcurve_iterator next_after = this->m_currentEvent->get_curve_after_on_right(it->first); for (std::size_t i=0; isecond[i], *cpp11::prev(next_after), this->m_currentEvent); + _intersect(it->second[i], *std::prev(next_after), this->m_currentEvent); CGAL_assertion(it->second.size()==nbc); // make sure the container was not updated } } From 56b828d11838421ce83dc50828a94c42309e124b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9bastien=20Loriot?= Date: Tue, 5 Nov 2019 09:07:34 +0100 Subject: [PATCH 278/363] add missing include directive --- STL_Extension/include/CGAL/Iterator_range.h | 1 + 1 file changed, 1 insertion(+) diff --git a/STL_Extension/include/CGAL/Iterator_range.h b/STL_Extension/include/CGAL/Iterator_range.h index d71cb07f671..204d0cd1730 100644 --- a/STL_Extension/include/CGAL/Iterator_range.h +++ b/STL_Extension/include/CGAL/Iterator_range.h @@ -14,6 +14,7 @@ #include #include +#include namespace CGAL { From f4d2b7540acbf9ab0a62338082cb734656e1e32f Mon Sep 17 00:00:00 2001 From: Maxime Gimeno Date: Tue, 5 Nov 2019 15:57:16 +0100 Subject: [PATCH 279/363] fix warning --- Point_set_3/examples/Point_set_3/point_set_read_ply.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Point_set_3/examples/Point_set_3/point_set_read_ply.cpp b/Point_set_3/examples/Point_set_3/point_set_read_ply.cpp index 0837329fae3..7bfc1cb45e0 100644 --- a/Point_set_3/examples/Point_set_3/point_set_read_ply.cpp +++ b/Point_set_3/examples/Point_set_3/point_set_read_ply.cpp @@ -42,7 +42,7 @@ int main (int argc, char** argv) std::cerr << " * " << label_prop[*it] << std::endl; } - if (argc > 2 && argv[2] == "-b") // Optional binary output + if (argc > 2 && strcmp (argv[2], "-b") == 0) // Optional binary output { std::ofstream out ("out.ply", std::ios_base::binary); // Mandatory on Windows From 1fb6abbabdbaba041b2a200b4d1fcbc2453b9c63 Mon Sep 17 00:00:00 2001 From: Laurent Rineau Date: Wed, 6 Nov 2019 09:16:14 +0100 Subject: [PATCH 280/363] Remove the debug message --- Documentation/doc/CMakeLists.txt | 1 - 1 file changed, 1 deletion(-) diff --git a/Documentation/doc/CMakeLists.txt b/Documentation/doc/CMakeLists.txt index 71c80cb6777..81c78f42f15 100644 --- a/Documentation/doc/CMakeLists.txt +++ b/Documentation/doc/CMakeLists.txt @@ -269,7 +269,6 @@ endif() # closely to the convoluted versioning code and can adapt without a # huge diff. set(CGAL_DOC_VERSION ${CGAL_CREATED_VERSION_NUM}) -message(CGAL_DOC_VERSION: ${CGAL_DOC_VERSION}) ## generate how_to_cite files if(PYTHONINTERP_FOUND) From abe9dccd21a36015214ac4cca15d1e1f44265c3a Mon Sep 17 00:00:00 2001 From: Marc Glisse Date: Wed, 6 Nov 2019 13:52:51 +0100 Subject: [PATCH 281/363] Typo in doc for Alpha_shape_3 --- Alpha_shapes_3/doc/Alpha_shapes_3/CGAL/Alpha_shape_3.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Alpha_shapes_3/doc/Alpha_shapes_3/CGAL/Alpha_shape_3.h b/Alpha_shapes_3/doc/Alpha_shapes_3/CGAL/Alpha_shape_3.h index 7d2bf1f3dd2..b51b927b6dc 100644 --- a/Alpha_shapes_3/doc/Alpha_shapes_3/CGAL/Alpha_shape_3.h +++ b/Alpha_shapes_3/doc/Alpha_shapes_3/CGAL/Alpha_shape_3.h @@ -119,8 +119,8 @@ typedef unspecified_type FT; /*! The point type. -For basic alpha shapes, `Point` will be equal to `Gt::Point_2`. For weighted alpha -shapes, `Point` will be equal to `Gt::Weighted_point_2`. +For basic alpha shapes, `Point` will be equal to `Gt::Point_3`. For weighted alpha +shapes, `Point` will be equal to `Gt::Weighted_point_3`. */ typedef Dt::Point Point; From 2331c8c15437f83664ba768e92588576f7c562b1 Mon Sep 17 00:00:00 2001 From: Laurent Rineau Date: Wed, 6 Nov 2019 18:18:04 +0100 Subject: [PATCH 282/363] 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 8bd5ff843c4..dd1f53c191a 100644 --- a/Maintenance/infrastructure/cgal.geometryfactory.com/crontab +++ b/Maintenance/infrastructure/cgal.geometryfactory.com/crontab @@ -25,9 +25,9 @@ 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 --public --do-it --beta 3 || 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 --beta 3 || echo ERROR +0 21 * * Mon,Tue,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 --beta 3 || 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 * * Wed,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 # from branch 4.13 #0 21 * * Fri cd $HOME/CGAL/create_internal_release-4.13-branch && /usr/bin/time scl enable rh-git29 -- $HOME/bin/create_release $HOME/CGAL/branches/CGAL-4.13-branch.git --public --do-it || echo ERROR # from branch 4.12 From 585bb8c7d6aed59dc6d881e19df1d5ef3eea0cfa Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9bastien=20Loriot?= Date: Thu, 7 Nov 2019 06:22:28 +0100 Subject: [PATCH 283/363] fix license issues --- GraphicsView/demo/icons/license.txt | 2 ++ Installation/LICENSE | 2 ++ .../demo/Periodic_3_triangulation_3/icons/license.txt | 2 ++ 3 files changed, 6 insertions(+) diff --git a/GraphicsView/demo/icons/license.txt b/GraphicsView/demo/icons/license.txt index ff11c043161..b9de5ecd798 100644 --- a/GraphicsView/demo/icons/license.txt +++ b/GraphicsView/demo/icons/license.txt @@ -3,3 +3,5 @@ The following files have been copied from Qt Free Edition version 4.4: fileOpen.png fileSave.png, fit-page-32.png + +This Qt version was released under GPL-2 and GPL-3. diff --git a/Installation/LICENSE b/Installation/LICENSE index 677312c96e7..4a393c57241 100644 --- a/Installation/LICENSE +++ b/Installation/LICENSE @@ -33,6 +33,8 @@ licenses: (see LICENSE.LGPL). - OpenNL, in the directory "include/CGAL/OpenNL", is licensed under the LGPL (see LICENSE.LGPL). +- ETH Zurich random forest algorithm, in the directory "CGAL/Classification/ETHZ", + is licensed under a MIT like license (see LICENSE.RFL). All other files that do not have an explicit copyright notice (e.g., all examples and some demos) are licensed under a very permissive license. The diff --git a/Periodic_3_triangulation_3/demo/Periodic_3_triangulation_3/icons/license.txt b/Periodic_3_triangulation_3/demo/Periodic_3_triangulation_3/icons/license.txt index 2cf4f5398aa..f2819459410 100644 --- a/Periodic_3_triangulation_3/demo/Periodic_3_triangulation_3/icons/license.txt +++ b/Periodic_3_triangulation_3/demo/Periodic_3_triangulation_3/icons/license.txt @@ -1,2 +1,4 @@ The following file has been copied from Qt Free Edition version 4.4: fileOpen.png + +This Qt version was released under GPL-2 and GPL-3. From 11762b1f9c823be0b18b8e3fd28b5f51c68f517b Mon Sep 17 00:00:00 2001 From: Laurent Rineau Date: Thu, 7 Nov 2019 14:07:43 +0100 Subject: [PATCH 284/363] 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 dd1f53c191a..8756c36bc21 100644 --- a/Maintenance/infrastructure/cgal.geometryfactory.com/crontab +++ b/Maintenance/infrastructure/cgal.geometryfactory.com/crontab @@ -23,11 +23,11 @@ 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 --public --do-it --beta 3 || echo ERROR +0 21 * * Thu,Sun cd $HOME/CGAL/create_internal_release && /usr/bin/time scl enable rh-git29 -- $HOME/bin/create_release $HOME/CGAL/branches/master.git --public --do-it --beta 3 || echo ERROR # "integration" -0 21 * * Mon,Tue,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 --beta 3 || echo ERROR +0 21 * * Mon,Tue,Wed,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 --beta 3 || echo ERROR # from branch 4.14 -0 21 * * Wed,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 * * 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 # from branch 4.13 #0 21 * * Fri cd $HOME/CGAL/create_internal_release-4.13-branch && /usr/bin/time scl enable rh-git29 -- $HOME/bin/create_release $HOME/CGAL/branches/CGAL-4.13-branch.git --public --do-it || echo ERROR # from branch 4.12 From a73081c7ba2c9d9139fecf9fdb0fa707fa378cd6 Mon Sep 17 00:00:00 2001 From: Laurent Rineau Date: Fri, 8 Nov 2019 10:58:13 +0100 Subject: [PATCH 285/363] updated crontab (automated commit) --- Maintenance/infrastructure/cgal.geometryfactory.com/crontab | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/Maintenance/infrastructure/cgal.geometryfactory.com/crontab b/Maintenance/infrastructure/cgal.geometryfactory.com/crontab index 8756c36bc21..8e748cc7183 100644 --- a/Maintenance/infrastructure/cgal.geometryfactory.com/crontab +++ b/Maintenance/infrastructure/cgal.geometryfactory.com/crontab @@ -23,11 +23,13 @@ LC_CTYPE=en_US.UTF-8 # The script also updates the manual tools. # "master" alone -0 21 * * Thu,Sun cd $HOME/CGAL/create_internal_release && /usr/bin/time scl enable rh-git29 -- $HOME/bin/create_release $HOME/CGAL/branches/master.git --public --do-it --beta 3 || 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 --public --do-it || echo ERROR # "integration" -0 21 * * Mon,Tue,Wed,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 --beta 3 || 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 --public || 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 + +## Older stuff # from branch 4.13 #0 21 * * Fri cd $HOME/CGAL/create_internal_release-4.13-branch && /usr/bin/time scl enable rh-git29 -- $HOME/bin/create_release $HOME/CGAL/branches/CGAL-4.13-branch.git --public --do-it || echo ERROR # from branch 4.12 From 27dcff6141cefb9bddffe74ee08b2c7afc1f2163 Mon Sep 17 00:00:00 2001 From: Laurent Rineau Date: Fri, 8 Nov 2019 10:56:21 +0100 Subject: [PATCH 286/363] Prepare CGAL-5.0 finale version --- Documentation/doc/resources/1.8.13/menu_version.js | 2 +- Documentation/doc/resources/1.8.14/menu_version.js | 2 +- Documentation/doc/resources/1.8.4/menu_version.js | 2 +- Installation/include/CGAL/version.h | 6 +++--- Maintenance/release_building/public_release_name | 1 - 5 files changed, 6 insertions(+), 7 deletions(-) delete mode 100644 Maintenance/release_building/public_release_name diff --git a/Documentation/doc/resources/1.8.13/menu_version.js b/Documentation/doc/resources/1.8.13/menu_version.js index 1f8a8eef476..30505b903ac 100644 --- a/Documentation/doc/resources/1.8.13/menu_version.js +++ b/Documentation/doc/resources/1.8.13/menu_version.js @@ -3,7 +3,7 @@ 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.0-beta2' + var current_version_local = '5.0' var all_versions = [ 'master', 'latest', diff --git a/Documentation/doc/resources/1.8.14/menu_version.js b/Documentation/doc/resources/1.8.14/menu_version.js index 1f8a8eef476..30505b903ac 100644 --- a/Documentation/doc/resources/1.8.14/menu_version.js +++ b/Documentation/doc/resources/1.8.14/menu_version.js @@ -3,7 +3,7 @@ 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.0-beta2' + var current_version_local = '5.0' var all_versions = [ 'master', 'latest', diff --git a/Documentation/doc/resources/1.8.4/menu_version.js b/Documentation/doc/resources/1.8.4/menu_version.js index 1f8a8eef476..30505b903ac 100644 --- a/Documentation/doc/resources/1.8.4/menu_version.js +++ b/Documentation/doc/resources/1.8.4/menu_version.js @@ -3,7 +3,7 @@ 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.0-beta2' + var current_version_local = '5.0' var all_versions = [ 'master', 'latest', diff --git a/Installation/include/CGAL/version.h b/Installation/include/CGAL/version.h index f8dc7b70b07..ff60b6bc5ea 100644 --- a/Installation/include/CGAL/version.h +++ b/Installation/include/CGAL/version.h @@ -16,11 +16,11 @@ #ifndef CGAL_VERSION_H #define CGAL_VERSION_H -#define CGAL_VERSION 5.0-beta3 -#define CGAL_VERSION_NR 1050000930 +#define CGAL_VERSION 5.0 +#define CGAL_VERSION_NR 1050001000 #define CGAL_SVN_REVISION 99999 #define CGAL_GIT_HASH abcdef -#define CGAL_RELEASE_DATE 20191031 +#define CGAL_RELEASE_DATE 20191108 #include diff --git a/Maintenance/release_building/public_release_name b/Maintenance/release_building/public_release_name deleted file mode 100644 index 7c0cede8ccf..00000000000 --- a/Maintenance/release_building/public_release_name +++ /dev/null @@ -1 +0,0 @@ -CGAL-5.0-beta3 From fe6dd48f5fa900f0880beeea7fd47b2c9887d0fd Mon Sep 17 00:00:00 2001 From: Laurent Rineau Date: Fri, 8 Nov 2019 11:23:19 +0100 Subject: [PATCH 287/363] public_release_name is actually required by our NSIS docker image --- Maintenance/release_building/public_release_name | 1 + 1 file changed, 1 insertion(+) create mode 100644 Maintenance/release_building/public_release_name diff --git a/Maintenance/release_building/public_release_name b/Maintenance/release_building/public_release_name new file mode 100644 index 00000000000..629e657c165 --- /dev/null +++ b/Maintenance/release_building/public_release_name @@ -0,0 +1 @@ +CGAL-5.0 From f854a2816ebc089b70e1a4137c4799ddbafffbf2 Mon Sep 17 00:00:00 2001 From: Laurent Rineau Date: Fri, 8 Nov 2019 11:37:45 +0100 Subject: [PATCH 288/363] Prepare the publication of 4.14.2 --- Documentation/doc/resources/1.8.13/menu_version.js | 2 +- Documentation/doc/resources/1.8.14/menu_version.js | 2 +- Documentation/doc/resources/1.8.4/menu_version.js | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/Documentation/doc/resources/1.8.13/menu_version.js b/Documentation/doc/resources/1.8.13/menu_version.js index 30505b903ac..b6eb67f73fc 100644 --- a/Documentation/doc/resources/1.8.13/menu_version.js +++ b/Documentation/doc/resources/1.8.13/menu_version.js @@ -8,7 +8,7 @@ 'master', 'latest', '5.0', - '4.14.1', + '4.14.2', '4.13.2', '4.12.2', '4.11.3', diff --git a/Documentation/doc/resources/1.8.14/menu_version.js b/Documentation/doc/resources/1.8.14/menu_version.js index 30505b903ac..b6eb67f73fc 100644 --- a/Documentation/doc/resources/1.8.14/menu_version.js +++ b/Documentation/doc/resources/1.8.14/menu_version.js @@ -8,7 +8,7 @@ 'master', 'latest', '5.0', - '4.14.1', + '4.14.2', '4.13.2', '4.12.2', '4.11.3', diff --git a/Documentation/doc/resources/1.8.4/menu_version.js b/Documentation/doc/resources/1.8.4/menu_version.js index 30505b903ac..b6eb67f73fc 100644 --- a/Documentation/doc/resources/1.8.4/menu_version.js +++ b/Documentation/doc/resources/1.8.4/menu_version.js @@ -8,7 +8,7 @@ 'master', 'latest', '5.0', - '4.14.1', + '4.14.2', '4.13.2', '4.12.2', '4.11.3', From 65dd48a94c3fceff0867f52584ade75473db5cdd Mon Sep 17 00:00:00 2001 From: Laurent Rineau Date: Fri, 8 Nov 2019 11:47:09 +0100 Subject: [PATCH 289/363] Fix the Windows-installer generation --- Scripts/developer_scripts/create_new_release | 3 +++ 1 file changed, 3 insertions(+) diff --git a/Scripts/developer_scripts/create_new_release b/Scripts/developer_scripts/create_new_release index c34fc3c9a3e..4a5f15aa269 100755 --- a/Scripts/developer_scripts/create_new_release +++ b/Scripts/developer_scripts/create_new_release @@ -322,6 +322,9 @@ fi if [ -n "$DO_PUBLIC" ]; then if docker version > /dev/null; then + # Re-extract the full version of CGAL, with examples/, and doc_html/ + rm -rf ./${public_release_name} + tar -xf ${public_release_name}.tar.xz # Build the Windows installer docker pull cgal/cgal-nsis-dockerfile docker create -v `realpath ${DESTINATION}/${public_release_name}`:/mnt/cgal_release:ro,z \ From 64763c41b08faa2fd73be09c690eb6b5d1814a3d Mon Sep 17 00:00:00 2001 From: Laurent Rineau Date: Fri, 8 Nov 2019 11:55:42 +0100 Subject: [PATCH 290/363] The file to extract was moved just a few line above! --- Scripts/developer_scripts/create_new_release | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Scripts/developer_scripts/create_new_release b/Scripts/developer_scripts/create_new_release index 4a5f15aa269..bbd9c5bf8b3 100755 --- a/Scripts/developer_scripts/create_new_release +++ b/Scripts/developer_scripts/create_new_release @@ -324,7 +324,7 @@ if [ -n "$DO_PUBLIC" ]; then if docker version > /dev/null; then # Re-extract the full version of CGAL, with examples/, and doc_html/ rm -rf ./${public_release_name} - tar -xf ${public_release_name}.tar.xz + tar -xf "${HTML_DIR}/${release_name}-public/${public_release_name}.tar.xz" # Build the Windows installer docker pull cgal/cgal-nsis-dockerfile docker create -v `realpath ${DESTINATION}/${public_release_name}`:/mnt/cgal_release:ro,z \ From bec70a6d52d8aacb0b3d82a7b4edc3caa899184b Mon Sep 17 00:00:00 2001 From: Laurent Rineau Date: Fri, 8 Nov 2019 14:21:39 +0100 Subject: [PATCH 291/363] Adapt the script to new tarballs formats. --- Maintenance/public_release/scripts/prepare_release | 6 ------ 1 file changed, 6 deletions(-) diff --git a/Maintenance/public_release/scripts/prepare_release b/Maintenance/public_release/scripts/prepare_release index 4ceb0c164ef..5768f1fe733 100755 --- a/Maintenance/public_release/scripts/prepare_release +++ b/Maintenance/public_release/scripts/prepare_release @@ -59,12 +59,6 @@ pushd "$DEST_DIR" zip -q -r "$DEST_DIR/${PUBLIC_RELEASE_NAME}-doc_html.zip" doc_html popd -printf "bzip2 doc_html tarball...\n" -bzip2 --best < "$DEST_DIR/${PUBLIC_RELEASE_NAME}-doc_html.tar" > "$DEST_DIR/${PUBLIC_RELEASE_NAME}-doc_html.tar.bz2" - -printf "bzip2 source tarball...\n" -zcat "$DEST_DIR/${PUBLIC_RELEASE_NAME}.tar.gz" | bzip2 --best > "$DEST_DIR/${PUBLIC_RELEASE_NAME}.tar.bz2" - printf "xz doc_html tarball...\n" xz --best < "$DEST_DIR/${PUBLIC_RELEASE_NAME}-doc_html.tar" > "$DEST_DIR/${PUBLIC_RELEASE_NAME}-doc_html.tar.xz" From 97c6485541e9c50f63dc7031d413dd642a15b7ad Mon Sep 17 00:00:00 2001 From: Laurent Rineau Date: Fri, 8 Nov 2019 18:12:05 +0100 Subject: [PATCH 292/363] Announcement for 5.0 --- .../announcement/announcement.md | 75 +++++++++++++++++++ 1 file changed, 75 insertions(+) create mode 100644 Maintenance/public_release/announcement/announcement.md diff --git a/Maintenance/public_release/announcement/announcement.md b/Maintenance/public_release/announcement/announcement.md new file mode 100644 index 00000000000..3f2ce921f63 --- /dev/null +++ b/Maintenance/public_release/announcement/announcement.md @@ -0,0 +1,75 @@ +The CGAL Open Source Project is pleased to announce the release 5.0 +of CGAL, the Computational Geometry Algorithms Library. + +Besides fixes and general enhancement to existing packages, the +following has changed since CGAL 4.14.2: + +### 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](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 + 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) + - **Breaking change:** The concept `ShapeDetectionTraits` has been renamed to [`EfficientRANSACTraits`](https://doc.cgal.org/5.0/Shape_detection/classEfficientRANSACTraits.html). + - **Breaking change:** The `Shape_detection_3` namespace has been renamed to [`Shape_detection`](https://doc.cgal.org/5.0/Shape_detection/annotated.html). + - 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`](https://doc.cgal.org/5.0/BGL/classFaceGraph.html) concept. Learn more about this new algorithm with this [blog entry](https://www.cgal.org/2019/07/30/Shape_detection/). + +### [dD Geometry Kernel](https://doc.cgal.org/5.0/Manual/packages.html#PkgKernelD) + - A new exact kernel, [`Epeck_d`](https://doc.cgal.org/5.0/Kernel_d/structCGAL_1_1Epeck__d.html), is now available. + +### 2D and 3D Triangulations + +- **Breaking change:** Several deprecated functions and classes have been + removed. See the full list of breaking changes in the release + notes. + +- **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]`. + + +### [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) + 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 + (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. + - Added the shape smoothing function [`smooth_shape()`](https://doc.cgal.org/5.0/Polygon_mesh_processing/group__PMP__meshing__grp.html#gaaa083ec78bcecf351e04d1bbf460b4a2), + which can be used to smooth the surface of a triangle mesh, using the mean curvature flow to perform noise removal. + (See also the new entry in the [User Manual](https://doc.cgal.org/5.0/Polygon_mesh_processing/index.html#title8)) + +### [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. + +See https://www.cgal.org/2019/11/08/cgal50/ for a complete list of changes. From 68ca489924ed96398208bc09a975005ad451be9c Mon Sep 17 00:00:00 2001 From: Laurent Rineau Date: Fri, 8 Nov 2019 18:13:44 +0100 Subject: [PATCH 293/363] Next release on master will be 5.1-dev --- Installation/include/CGAL/version.h | 4 ++-- Maintenance/release_building/MINOR_NUMBER | 2 +- Maintenance/release_building/public_release_name | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/Installation/include/CGAL/version.h b/Installation/include/CGAL/version.h index ff60b6bc5ea..5277243907f 100644 --- a/Installation/include/CGAL/version.h +++ b/Installation/include/CGAL/version.h @@ -16,8 +16,8 @@ #ifndef CGAL_VERSION_H #define CGAL_VERSION_H -#define CGAL_VERSION 5.0 -#define CGAL_VERSION_NR 1050001000 +#define CGAL_VERSION 5.1 +#define CGAL_VERSION_NR 1050100000 #define CGAL_SVN_REVISION 99999 #define CGAL_GIT_HASH abcdef #define CGAL_RELEASE_DATE 20191108 diff --git a/Maintenance/release_building/MINOR_NUMBER b/Maintenance/release_building/MINOR_NUMBER index 573541ac970..d00491fd7e5 100644 --- a/Maintenance/release_building/MINOR_NUMBER +++ b/Maintenance/release_building/MINOR_NUMBER @@ -1 +1 @@ -0 +1 diff --git a/Maintenance/release_building/public_release_name b/Maintenance/release_building/public_release_name index 629e657c165..0c48f1e0ed2 100644 --- a/Maintenance/release_building/public_release_name +++ b/Maintenance/release_building/public_release_name @@ -1 +1 @@ -CGAL-5.0 +CGAL-5.1-dev From f0c82986576b0042e2e51024c2afb393761f9bcf Mon Sep 17 00:00:00 2001 From: Laurent Rineau Date: Fri, 8 Nov 2019 18:18:04 +0100 Subject: [PATCH 294/363] updated crontab (automated commit) --- Maintenance/infrastructure/cgal.geometryfactory.com/crontab | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/Maintenance/infrastructure/cgal.geometryfactory.com/crontab b/Maintenance/infrastructure/cgal.geometryfactory.com/crontab index 8e748cc7183..ec794d29533 100644 --- a/Maintenance/infrastructure/cgal.geometryfactory.com/crontab +++ b/Maintenance/infrastructure/cgal.geometryfactory.com/crontab @@ -23,11 +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 --public --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 || 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 +# 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-4.14-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 * * 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 ## Older stuff # from branch 4.13 From abd7f5a0993945c7cd77159a43b54e912b025762 Mon Sep 17 00:00:00 2001 From: Laurent Rineau Date: Fri, 8 Nov 2019 20:57:39 +0100 Subject: [PATCH 295/363] Mext release in this branch will be 5.0.1 --- Installation/include/CGAL/version.h | 4 ++-- Maintenance/release_building/BUGFIX_NUMBER | 2 +- Maintenance/release_building/public_release_name | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/Installation/include/CGAL/version.h b/Installation/include/CGAL/version.h index ff60b6bc5ea..5b07604c596 100644 --- a/Installation/include/CGAL/version.h +++ b/Installation/include/CGAL/version.h @@ -16,8 +16,8 @@ #ifndef CGAL_VERSION_H #define CGAL_VERSION_H -#define CGAL_VERSION 5.0 -#define CGAL_VERSION_NR 1050001000 +#define CGAL_VERSION 5.0.1 +#define CGAL_VERSION_NR 1050011000 #define CGAL_SVN_REVISION 99999 #define CGAL_GIT_HASH abcdef #define CGAL_RELEASE_DATE 20191108 diff --git a/Maintenance/release_building/BUGFIX_NUMBER b/Maintenance/release_building/BUGFIX_NUMBER index 573541ac970..d00491fd7e5 100644 --- a/Maintenance/release_building/BUGFIX_NUMBER +++ b/Maintenance/release_building/BUGFIX_NUMBER @@ -1 +1 @@ -0 +1 diff --git a/Maintenance/release_building/public_release_name b/Maintenance/release_building/public_release_name index 629e657c165..cc3a47abdef 100644 --- a/Maintenance/release_building/public_release_name +++ b/Maintenance/release_building/public_release_name @@ -1 +1 @@ -CGAL-5.0 +CGAL-5.0.1 From 2a0eac67f05a6ceb2fc6d141e5cb1c22034e3e7b Mon Sep 17 00:00:00 2001 From: Marc Glisse Date: Sat, 9 Nov 2019 09:58:21 +0100 Subject: [PATCH 296/363] Remove some unnecessary dereferencing. --- .../include/CGAL/NewKernel_d/function_objects_cartesian.h | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/NewKernel_d/include/CGAL/NewKernel_d/function_objects_cartesian.h b/NewKernel_d/include/CGAL/NewKernel_d/function_objects_cartesian.h index bede1fa2fa3..8cfabbb5518 100644 --- a/NewKernel_d/include/CGAL/NewKernel_d/function_objects_cartesian.h +++ b/NewKernel_d/include/CGAL/NewKernel_d/function_objects_cartesian.h @@ -665,11 +665,13 @@ template struct Construct_circumcenter : Store_kernel { Vec b(k); Vec l(k); int j,i=0; + // We are doing a quadratic number of *f, which can be costly with transforming_iterator. for(Iter f2=f;f2!=e;++f2,++i){ - b(i)=m(i,i)=sdo(*f2); + Point const& p2=*f2; + b(i)=m(i,i)=sdo(p2); j=0; for(Iter f3=f;f3!=e;++f3,++j){ - m(j,i)=m(i,j)=sp(*f2,*f3); + m(j,i)=m(i,j)=sp(p2,*f3); } } for(i=1;i Date: Sat, 9 Nov 2019 10:11:13 +0100 Subject: [PATCH 297/363] Fewer dereferences. --- NewKernel_d/include/CGAL/NewKernel_d/Types/Weighted_point.h | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/NewKernel_d/include/CGAL/NewKernel_d/Types/Weighted_point.h b/NewKernel_d/include/CGAL/NewKernel_d/Types/Weighted_point.h index 6029435be1b..919b6268c7a 100644 --- a/NewKernel_d/include/CGAL/NewKernel_d/Types/Weighted_point.h +++ b/NewKernel_d/include/CGAL/NewKernel_d/Types/Weighted_point.h @@ -233,7 +233,7 @@ template struct Power_center : Store_kernel { j=0; for(Iter f3=f; f3!=e; ++f3,++j){ // FIXME: scalar product of points ??? - m(j,i) = m(i,j) = sp(pdw(*f2),pdw(*f3)); + m(j,i) = m(i,j) = sp(p,pdw(*f3)); } } for(i=1;i struct Power_center : Store_kernel { for(i=0;i Date: Tue, 12 Nov 2019 16:36:03 +0100 Subject: [PATCH 298/363] Fix warning about unused capture --- 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 0b1a6661b6c..d80f0485a0c 100644 --- a/Polyhedron/demo/Polyhedron/MainWindow.cpp +++ b/Polyhedron/demo/Polyhedron/MainWindow.cpp @@ -2276,7 +2276,7 @@ void MainWindow::on_actionPreferences_triggered() }); connect(prefdiag.backFrontColor_pushButton, &QPushButton::clicked, - this, [this](){ + this, [](){ qobject_cast(CGAL::Three::Three::activeViewer())->setBackFrontColors(); }); From 4fff9b1017e691a4fe042a43aa40a260cc9cffb3 Mon Sep 17 00:00:00 2001 From: Maxime Gimeno Date: Tue, 12 Nov 2019 16:43:14 +0100 Subject: [PATCH 299/363] Fix scopeguard error. --- .../demo/Polyhedron/Plugins/PMP/Repair_polyhedron_plugin.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/Polyhedron/demo/Polyhedron/Plugins/PMP/Repair_polyhedron_plugin.cpp b/Polyhedron/demo/Polyhedron/Plugins/PMP/Repair_polyhedron_plugin.cpp index 46f5b96a9ba..1e8fb6578ef 100644 --- a/Polyhedron/demo/Polyhedron/Plugins/PMP/Repair_polyhedron_plugin.cpp +++ b/Polyhedron/demo/Polyhedron/Plugins/PMP/Repair_polyhedron_plugin.cpp @@ -151,7 +151,9 @@ void Polyhedron_demo_repair_polyhedron_plugin::on_actionRemoveIsolatedVertices_t void Polyhedron_demo_repair_polyhedron_plugin::on_actionRemoveNeedlesAndCaps_triggered() { - CGAL::Three::Three::CursorScopeGuard(Qt::WaitCursor); + QCursor tmp_cursor(Qt::WaitCursor); + CGAL::Three::Three::CursorScopeGuard guard(tmp_cursor); + const Scene_interface::Item_id index = scene->mainSelectionIndex(); Scene_surface_mesh_item* sm_item = qobject_cast(scene->item(index)); if(!sm_item) From bb117e9792f1cd0ee1f1707472d45cdf747bdfd8 Mon Sep 17 00:00:00 2001 From: Guillaume Damiand Date: Wed, 13 Nov 2019 11:51:54 +0100 Subject: [PATCH 300/363] Bug fix --- GraphicsView/include/CGAL/Buffer_for_vao.h | 6 ++++-- GraphicsView/include/CGAL/Qt/Basic_viewer_qt.h | 18 ++++++++---------- 2 files changed, 12 insertions(+), 12 deletions(-) diff --git a/GraphicsView/include/CGAL/Buffer_for_vao.h b/GraphicsView/include/CGAL/Buffer_for_vao.h index 9d6f707ea48..4d4f48a68e1 100644 --- a/GraphicsView/include/CGAL/Buffer_for_vao.h +++ b/GraphicsView/include/CGAL/Buffer_for_vao.h @@ -98,7 +98,7 @@ namespace internal CGAL::Cartesian_converter converter; return converter(v); } - static Local_ray get_local_ray(const typename K::Ray_2& r) + static typename Local_kernel::Ray_2 get_local_ray(const typename K::Ray_2& r) { CGAL::Cartesian_converter converter; return converter(r); @@ -121,6 +121,8 @@ namespace internal { return typename Local_kernel::Vector_3(v.x(), 0, v.y()); } static const typename Local_kernel::Vector_3& get_local_vector(const typename Local_kernel::Vector_3& v) { return v; } + static const typename Local_kernel::Ray_2& get_local_ray(const typename Local_kernel::Ray_2& r) + { return r; } }; } // End namespace internal @@ -223,7 +225,7 @@ public: { if (!has_position()) return (std::size_t)-1; - Local_point p=internal::get_local_point(kp); + Local_point p=get_local_point(kp); add_point_in_buffer(p, *m_pos_buffer); return m_pos_buffer->size()-3; } diff --git a/GraphicsView/include/CGAL/Qt/Basic_viewer_qt.h b/GraphicsView/include/CGAL/Qt/Basic_viewer_qt.h index 97150bce320..87762ba030b 100644 --- a/GraphicsView/include/CGAL/Qt/Basic_viewer_qt.h +++ b/GraphicsView/include/CGAL/Qt/Basic_viewer_qt.h @@ -429,23 +429,21 @@ public: { m_buffer_for_colored_segments.add_segment(p1, p2, acolor); } template - void update_bounding_box_for_ray(const KPoint &p, const KVector &v) { - // m_buffer_for_mono_points.add_point(p); - Local_point lp = internal::get_local_point(p); - Local_vector lv = internal::get_local_vector(v); + void update_bounding_box_for_ray(const KPoint &p, const KVector &v) + { + Local_point lp = get_local_point(p); + Local_vector lv = get_local_vector(v); CGAL::Bbox_3 b = (lp + lv).bbox(); m_bounding_box += b; - // m_bounding_box += CGAL::Bbox_3(b.xmin(), 0, b.ymin(), b.xmax(), 0, - // b.ymax()); } template void update_bounding_box_for_line(const KPoint &p, const KVector &v, const KVector &pv) { - Local_point lp = internal::get_local_point(p); - Local_vector lv = internal::get_local_vector(v); - Local_vector lpv = internal::get_local_vector(pv); + Local_point lp = get_local_point(p); + Local_vector lv = get_local_vector(v); + Local_vector lpv = get_local_vector(pv); CGAL::Bbox_3 b = lp.bbox() + (lp + lv).bbox() + (lp + lpv).bbox(); m_bounding_box += b; @@ -484,7 +482,7 @@ public: template void add_text(const KPoint& kp, const QString& txt) { - Local_point p=internal::get_local_point(kp); + Local_point p=get_local_point(kp); m_texts.push_back(std::make_tuple(p, txt)); } From cc663c5e36927a0d1266ba8c49e8117ee0443c7b Mon Sep 17 00:00:00 2001 From: Guillaume Damiand Date: Wed, 13 Nov 2019 12:18:27 +0100 Subject: [PATCH 301/363] Bugfix for negate normals. --- GraphicsView/include/CGAL/Buffer_for_vao.h | 52 ++++++++++++------- .../include/CGAL/Qt/Basic_viewer_qt.h | 10 ++-- 2 files changed, 38 insertions(+), 24 deletions(-) diff --git a/GraphicsView/include/CGAL/Buffer_for_vao.h b/GraphicsView/include/CGAL/Buffer_for_vao.h index 4d4f48a68e1..7ba5a1b7317 100644 --- a/GraphicsView/include/CGAL/Buffer_for_vao.h +++ b/GraphicsView/include/CGAL/Buffer_for_vao.h @@ -151,6 +151,7 @@ public: m_zero_x(true), m_zero_y(true), m_zero_z(true), + m_inverse_normal(false), m_face_started(false) {} @@ -201,6 +202,17 @@ public: bool has_zero_z() const { return m_zero_z; } + void negate_normals() + { + m_inverse_normal=!m_inverse_normal; + for (std::vector*array=m_flat_normal_buffer; array!=nullptr; + array=(array==m_gouraud_normal_buffer?nullptr:m_gouraud_normal_buffer)) + { + for (std::size_t i=0; isize(); ++i) + { (*array)[i]=-(*array)[i]; } + } + } + // 1.1) Add a point, without color. Return the index of the added point. template std::size_t add_point(const KPoint& kp) @@ -445,7 +457,7 @@ public: /// adds `kp` coordinates to `buffer` template - static void add_point_in_buffer(const KPoint& kp, std::vector& buffer) + void add_point_in_buffer(const KPoint& kp, std::vector& buffer) { Local_point p=get_local_point(kp); buffer.push_back(p.x()); @@ -455,16 +467,16 @@ public: /// adds `kv` coordinates to `buffer` template - static void add_normal_in_buffer(const KVector& kv, std::vector& buffer) + void add_normal_in_buffer(const KVector& kv, std::vector& buffer) { - Local_vector n=get_local_vector(kv); + Local_vector n=(m_inverse_normal?-get_local_vector(kv):get_local_vector(kv)); buffer.push_back(n.x()); buffer.push_back(n.y()); buffer.push_back(n.z()); } ///adds `acolor` RGB components to `buffer` - static void add_color_in_buffer(const CGAL::Color& acolor, std::vector& buffer) + void add_color_in_buffer(const CGAL::Color& acolor, std::vector& buffer) { buffer.push_back((float)acolor.red()/(float)255); buffer.push_back((float)acolor.green()/(float)255); @@ -541,23 +553,23 @@ public: if (m_indices_of_points_of_face.size()>0) { add_indexed_point(m_indices_of_points_of_face[i]); - } + } else { add_point(m_points_of_face[i]); // Add the position of the point - if (m_started_face_is_colored) - { add_color(m_color_of_face); } // Add the color - add_flat_normal(normal); // Add the flat normal - // Its smooth normal (if given by the user) - if (m_vertex_normals_for_face.size()>0) - { // Here we have 3 vertex normals; we can use Gouraud - add_gouraud_normal(m_vertex_normals_for_face[i]); - } - else - { // Here user does not provide all vertex normals: we use face normal istead - // and thus we will not be able to use Gouraud - add_gouraud_normal(normal); - } + if (m_started_face_is_colored) + { add_color(m_color_of_face); } // Add the color + add_flat_normal(normal); // Add the flat normal + // Its smooth normal (if given by the user) + if (m_vertex_normals_for_face.size()>0) + { // Here we have 3 vertex normals; we can use Gouraud + add_gouraud_normal(m_vertex_normals_for_face[i]); + } + else + { // Here user does not provide all vertex normals: we use face normal istead + // and thus we will not be able to use Gouraud + add_gouraud_normal(normal); + } } } } @@ -883,8 +895,10 @@ protected: bool m_zero_x; /// True iff all points have x==0 bool m_zero_y; /// True iff all points have y==0 bool m_zero_z; /// True iff all points have z==0 + + bool m_inverse_normal;; - // Local variables, used when we started a new face. + // Local variables, used when we started a new face.g bool m_face_started; bool m_started_face_is_colored; bool m_started_face_has_normal; diff --git a/GraphicsView/include/CGAL/Qt/Basic_viewer_qt.h b/GraphicsView/include/CGAL/Qt/Basic_viewer_qt.h index 87762ba030b..ddb4c99fa57 100644 --- a/GraphicsView/include/CGAL/Qt/Basic_viewer_qt.h +++ b/GraphicsView/include/CGAL/Qt/Basic_viewer_qt.h @@ -329,6 +329,9 @@ public: setWindowTitle(title); resize(500, 450); + + if (inverse_normal) + { negate_all_normals(); } } ~Basic_viewer_qt() @@ -1261,11 +1264,8 @@ protected: void negate_all_normals() { - for (unsigned int k=BEGIN_NORMAL; k Date: Wed, 13 Nov 2019 12:24:30 +0100 Subject: [PATCH 302/363] One more bug --- GraphicsView/include/CGAL/Buffer_for_vao.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/GraphicsView/include/CGAL/Buffer_for_vao.h b/GraphicsView/include/CGAL/Buffer_for_vao.h index 7ba5a1b7317..8c3e044a1fd 100644 --- a/GraphicsView/include/CGAL/Buffer_for_vao.h +++ b/GraphicsView/include/CGAL/Buffer_for_vao.h @@ -71,7 +71,7 @@ namespace internal static typename Local_kernel::Point_3 get_local_point(const typename K::Point_2& p) { CGAL::Cartesian_converter converter; - return Local_point(converter(p.x()), 0, converter(p.y())); + return typename Local_kernel::Point_3(converter(p.x()), 0, converter(p.y())); } static typename Local_kernel::Point_3 get_local_point(const typename K::Weighted_point_2& p) { @@ -91,7 +91,7 @@ namespace internal static typename Local_kernel::Vector_3 get_local_vector(const typename K::Vector_2& v) { CGAL::Cartesian_converter converter; - return Local_vector(converter(v.x()), 0, converter(v.y())); + return typename Local_kernel::Vector_3(converter(v.x()), 0, converter(v.y())); } static typename Local_kernel::Vector_3 get_local_vector(const typename K::Vector_3& v) { From 7d2cf8df71e1508fcfbf939ba5535aa4d0fcd2a5 Mon Sep 17 00:00:00 2001 From: Guillaume Damiand Date: Wed, 13 Nov 2019 14:38:22 +0100 Subject: [PATCH 303/363] Bugfix in draw nef3 --- Nef_3/include/CGAL/draw_nef_3.h | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/Nef_3/include/CGAL/draw_nef_3.h b/Nef_3/include/CGAL/draw_nef_3.h index 665fbb4ca82..8f1aa0959bf 100644 --- a/Nef_3/include/CGAL/draw_nef_3.h +++ b/Nef_3/include/CGAL/draw_nef_3.h @@ -210,9 +210,10 @@ protected: CGAL_For_all(he, end) { - internal::newell_single_step_3(internal::Geom_utils::get_local_point(he->next()->source()->center_vertex()->point()), - internal::Geom_utils::get_local_point(he->source()->center_vertex()->point()), - normal); + internal::newell_single_step_3(this->get_local_point + (he->next()->source()->center_vertex()->point()), + this->get_local_point(he->source()->center_vertex()-> + point()), normal); ++nb; } From f42c9ab89d197399d645fb0262479fbbecb889ed Mon Sep 17 00:00:00 2001 From: Guillaume Damiand Date: Wed, 13 Nov 2019 14:44:45 +0100 Subject: [PATCH 304/363] Update licences --- Nef_3/include/CGAL/draw_nef_3.h | 2 +- .../include/CGAL/draw_periodic_2_triangulation_2.h | 2 +- Voronoi_diagram_2/include/CGAL/draw_voronoi_diagram_2.h | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/Nef_3/include/CGAL/draw_nef_3.h b/Nef_3/include/CGAL/draw_nef_3.h index 8f1aa0959bf..7ec9789d3a9 100644 --- a/Nef_3/include/CGAL/draw_nef_3.h +++ b/Nef_3/include/CGAL/draw_nef_3.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) : Jasmeet Singh diff --git a/Periodic_2_triangulation_2/include/CGAL/draw_periodic_2_triangulation_2.h b/Periodic_2_triangulation_2/include/CGAL/draw_periodic_2_triangulation_2.h index 3b63f4a28cd..1f0cc8922f6 100644 --- a/Periodic_2_triangulation_2/include/CGAL/draw_periodic_2_triangulation_2.h +++ b/Periodic_2_triangulation_2/include/CGAL/draw_periodic_2_triangulation_2.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) : Jasmeet Singh diff --git a/Voronoi_diagram_2/include/CGAL/draw_voronoi_diagram_2.h b/Voronoi_diagram_2/include/CGAL/draw_voronoi_diagram_2.h index 9c0e379074c..efc0ce0e670 100644 --- a/Voronoi_diagram_2/include/CGAL/draw_voronoi_diagram_2.h +++ b/Voronoi_diagram_2/include/CGAL/draw_voronoi_diagram_2.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) : Jasmeet Singh From 1bf02b2d94512a9dacf393c50739364fd906af4a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9bastien=20Loriot?= Date: Wed, 13 Nov 2019 15:28:56 +0100 Subject: [PATCH 305/363] remove license statements --- Nef_3/include/CGAL/draw_nef_3.h | 9 --------- .../include/CGAL/draw_periodic_2_triangulation_2.h | 9 --------- Voronoi_diagram_2/include/CGAL/draw_voronoi_diagram_2.h | 9 --------- 3 files changed, 27 deletions(-) diff --git a/Nef_3/include/CGAL/draw_nef_3.h b/Nef_3/include/CGAL/draw_nef_3.h index 7ec9789d3a9..da8e01bacc8 100644 --- a/Nef_3/include/CGAL/draw_nef_3.h +++ b/Nef_3/include/CGAL/draw_nef_3.h @@ -2,15 +2,6 @@ // 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$ diff --git a/Periodic_2_triangulation_2/include/CGAL/draw_periodic_2_triangulation_2.h b/Periodic_2_triangulation_2/include/CGAL/draw_periodic_2_triangulation_2.h index 1f0cc8922f6..4efd53cf68b 100644 --- a/Periodic_2_triangulation_2/include/CGAL/draw_periodic_2_triangulation_2.h +++ b/Periodic_2_triangulation_2/include/CGAL/draw_periodic_2_triangulation_2.h @@ -2,15 +2,6 @@ // 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$ diff --git a/Voronoi_diagram_2/include/CGAL/draw_voronoi_diagram_2.h b/Voronoi_diagram_2/include/CGAL/draw_voronoi_diagram_2.h index efc0ce0e670..5e32e12d3d4 100644 --- a/Voronoi_diagram_2/include/CGAL/draw_voronoi_diagram_2.h +++ b/Voronoi_diagram_2/include/CGAL/draw_voronoi_diagram_2.h @@ -2,15 +2,6 @@ // 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$ From 7aa94df4896107881075f2ee8f76793165e0366d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mael=20Rouxel-Labb=C3=A9?= Date: Fri, 15 Nov 2019 11:55:32 +0100 Subject: [PATCH 306/363] Mute warning about using CDT_2+ in CDT_2 test --- .../test/Triangulation_2/test_constrained_triangulation_2.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/Triangulation_2/test/Triangulation_2/test_constrained_triangulation_2.cpp b/Triangulation_2/test/Triangulation_2/test_constrained_triangulation_2.cpp index 8125d01805a..18746efd090 100644 --- a/Triangulation_2/test/Triangulation_2/test_constrained_triangulation_2.cpp +++ b/Triangulation_2/test/Triangulation_2/test_constrained_triangulation_2.cpp @@ -22,6 +22,9 @@ #include +// Don't want to be warned about using CDT_2 (and not CDT_2+) with an exact number type +#define CGAL_NO_CDT_2_WARNING + #include #include From 7b05052a27e78f20856199e5f61db653e18de1e3 Mon Sep 17 00:00:00 2001 From: Maxime Gimeno Date: Mon, 18 Nov 2019 10:27:04 +0100 Subject: [PATCH 307/363] Test if the tree is empty before building the kd-tree (to fix all the execution failures in the tests) --- AABB_tree/include/CGAL/AABB_tree.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/AABB_tree/include/CGAL/AABB_tree.h b/AABB_tree/include/CGAL/AABB_tree.h index 8e977c76f57..0c60f3c0a0e 100644 --- a/AABB_tree/include/CGAL/AABB_tree.h +++ b/AABB_tree/include/CGAL/AABB_tree.h @@ -705,7 +705,7 @@ public: // In case the users has switched on the accelerated distance query // data structure with the default arguments, then it has to be // /built/rebuilt. - if(m_default_search_tree_constructed){ + if(m_default_search_tree_constructed && !empty()){ build_kd_tree(); } m_need_build = false; From 157116f7c87cee4b1abbff61155cc66f851f7427 Mon Sep 17 00:00:00 2001 From: Guillaume Damiand Date: Tue, 19 Nov 2019 10:36:08 +0100 Subject: [PATCH 308/363] Re-add add_xxx method as static, since they are used without instance in Polyhedron demo. --- GraphicsView/include/CGAL/Buffer_for_vao.h | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/GraphicsView/include/CGAL/Buffer_for_vao.h b/GraphicsView/include/CGAL/Buffer_for_vao.h index 8c3e044a1fd..e6f7cb8e341 100644 --- a/GraphicsView/include/CGAL/Buffer_for_vao.h +++ b/GraphicsView/include/CGAL/Buffer_for_vao.h @@ -457,7 +457,7 @@ public: /// adds `kp` coordinates to `buffer` template - void add_point_in_buffer(const KPoint& kp, std::vector& buffer) + static void add_point_in_buffer(const KPoint& kp, std::vector& buffer) { Local_point p=get_local_point(kp); buffer.push_back(p.x()); @@ -467,16 +467,17 @@ public: /// adds `kv` coordinates to `buffer` template - void add_normal_in_buffer(const KVector& kv, std::vector& buffer) + static void add_normal_in_buffer(const KVector& kv, std::vector& buffer, + bool inverse_normal=false) { - Local_vector n=(m_inverse_normal?-get_local_vector(kv):get_local_vector(kv)); + Local_vector n=(inverse_normal?-get_local_vector(kv):get_local_vector(kv)); buffer.push_back(n.x()); buffer.push_back(n.y()); buffer.push_back(n.z()); } ///adds `acolor` RGB components to `buffer` - void add_color_in_buffer(const CGAL::Color& acolor, std::vector& buffer) + static void add_color_in_buffer(const CGAL::Color& acolor, std::vector& buffer) { buffer.push_back((float)acolor.red()/(float)255); buffer.push_back((float)acolor.green()/(float)255); @@ -835,14 +836,14 @@ public: void add_flat_normal(const KVector& kv) { if(m_flat_normal_buffer != nullptr) - { add_normal_in_buffer(kv, *m_flat_normal_buffer); } + { add_normal_in_buffer(kv, *m_flat_normal_buffer, m_inverse_normal); } } template void add_gouraud_normal(const KVector& kv) { if(m_gouraud_normal_buffer != nullptr) - { add_normal_in_buffer(kv, *m_gouraud_normal_buffer); } + { add_normal_in_buffer(kv, *m_gouraud_normal_buffer, m_inverse_normal); } } protected: From 853010afa4fc786b652eb8b10b93e9027b5ebfc6 Mon Sep 17 00:00:00 2001 From: Guillaume Damiand Date: Wed, 20 Nov 2019 09:26:50 +0100 Subject: [PATCH 309/363] Add missing #include; remove an unused variable. --- .../draw_periodic_2_triangulation_2.cpp | 26 ++++++++++--------- .../CGAL/draw_periodic_2_triangulation_2.h | 2 +- 2 files changed, 15 insertions(+), 13 deletions(-) diff --git a/Periodic_2_triangulation_2/examples/Periodic_2_triangulation_2/draw_periodic_2_triangulation_2.cpp b/Periodic_2_triangulation_2/examples/Periodic_2_triangulation_2/draw_periodic_2_triangulation_2.cpp index 676ca27746d..28a49c76731 100644 --- a/Periodic_2_triangulation_2/examples/Periodic_2_triangulation_2/draw_periodic_2_triangulation_2.cpp +++ b/Periodic_2_triangulation_2/examples/Periodic_2_triangulation_2/draw_periodic_2_triangulation_2.cpp @@ -1,8 +1,9 @@ #include #include +#include #include -#include +#include typedef CGAL::Exact_predicates_inexact_constructions_kernel K; typedef CGAL::Periodic_2_Delaunay_triangulation_traits_2 GT; @@ -18,17 +19,18 @@ int main(int argc, char* argv[]) // Read points and insert in T Point p; std::ifstream ifs((argc > 1) ? argv[1] : "data/data1.dt.cin"); - assert(ifs); - while (ifs >> p) { - T.insert(p); + if (ifs) + { + while (ifs >> p) + { T.insert(p); } + CGAL_assertion(T.is_valid()); + + if( T.is_triangulation_in_1_sheet()) + { T.convert_to_9_sheeted_covering(); } + + // Draw the periodic triangulation + CGAL::draw(T); } - assert(T.is_valid()); - - if( T.is_triangulation_in_1_sheet()) - T.convert_to_9_sheeted_covering(); - - // Draw the periodic triangulation - CGAL::draw(T); - + return EXIT_SUCCESS; } diff --git a/Periodic_2_triangulation_2/include/CGAL/draw_periodic_2_triangulation_2.h b/Periodic_2_triangulation_2/include/CGAL/draw_periodic_2_triangulation_2.h index 4efd53cf68b..42970bfa8e9 100644 --- a/Periodic_2_triangulation_2/include/CGAL/draw_periodic_2_triangulation_2.h +++ b/Periodic_2_triangulation_2/include/CGAL/draw_periodic_2_triangulation_2.h @@ -26,7 +26,7 @@ namespace CGAL { struct DefaultColorFunctorP2T2 { template static CGAL::Color run(const P2T2 &, - const typename P2T2::Periodic_triangle_iterator ti) { + const typename P2T2::Periodic_triangle_iterator /*ti*/) { //CGAL::Random random((unsigned int)(std::size_t)(&*ti)); //return get_random_color(random); return CGAL::Color(73, 250, 117); From 7ff2ffb2389a73060c5a7e46538ccc16c7dd3cc1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mael=20Rouxel-Labb=C3=A9?= Date: Wed, 20 Nov 2019 13:16:40 +0100 Subject: [PATCH 310/363] Remove some obsolete doc links Mostly a consequence of using stuff from 'std::' rather than 'CGAL::' --- .../doc/Generator/CGAL/point_generators_2.h | 36 --------------- .../doc/Generator/CGAL/point_generators_3.h | 44 +++---------------- .../doc/Generator/CGAL/point_generators_d.h | 9 ---- .../doc/STL_Extension/PackageDescription.txt | 3 -- 4 files changed, 5 insertions(+), 87 deletions(-) diff --git a/Generator/doc/Generator/CGAL/point_generators_2.h b/Generator/doc/Generator/CGAL/point_generators_2.h index 654099e0c08..f22f8aa8497 100644 --- a/Generator/doc/Generator/CGAL/point_generators_2.h +++ b/Generator/doc/Generator/CGAL/point_generators_2.h @@ -146,8 +146,6 @@ distributed in an open disc. The default `Creator` is \cgalModels `InputIterator` \cgalModels `PointGenerator` -\sa `std::copy_n()` -\sa `CGAL::Counting_iterator` \sa `CGAL::Points_on_segment_2` \sa `CGAL::Random_points_in_square_2` \sa `CGAL::Random_points_in_triangle_2` @@ -155,8 +153,6 @@ distributed in an open disc. The default `Creator` is \sa `CGAL::Random_points_on_segment_2` \sa `CGAL::Random_points_on_square_2` \sa `CGAL::Random_points_in_sphere_3` -\sa `std::random_shuffle` - */ template< typename Point_2, typename Creator > class Random_points_in_disc_2 { @@ -214,16 +210,12 @@ distributed in a half-open square. The default `Creator` is \cgalModels `InputIterator` \cgalModels `PointGenerator` -\sa `std::copy_n()` -\sa `CGAL::Counting_iterator` \sa `CGAL::Points_on_segment_2` \sa `CGAL::Random_points_in_triangle_2` \sa `CGAL::Random_points_in_disc_2` \sa `CGAL::Random_points_on_segment_2` \sa `CGAL::Random_points_on_square_2` \sa `CGAL::Random_points_in_cube_3` -\sa `std::random_shuffle` - */ template< typename Point_2, typename Creator > class Random_points_in_square_2 { @@ -283,8 +275,6 @@ distributed inside a triangle. The default `Creator` is \cgalModels `InputIterator` \cgalModels `PointGenerator` -\sa `std::copy_n()` -\sa `CGAL::Counting_iterator` \sa `CGAL::Points_on_segment_2` \sa `CGAL::Random_points_in_disc_2` \sa `CGAL::Random_points_on_segment_2` @@ -292,8 +282,6 @@ distributed inside a triangle. The default `Creator` is \sa `CGAL::Random_points_in_cube_3` \sa `CGAL::Random_points_in_triangle_3` \sa `CGAL::Random_points_in_tetrahedron_3` -\sa `std::random_shuffle` - */ template< typename Point_2, typename Creator > class Random_points_in_triangle_2 { @@ -360,8 +348,6 @@ typedef const Point_2& reference; \cgalModels `InputIterator` \cgalModels `PointGenerator` - \sa `std::copy_n()` - \sa `CGAL::Counting_iterator` \sa `CGAL::Points_on_segment_2` \sa `CGAL::Random_points_in_disc_2` \sa `CGAL::Random_points_on_segment_2` @@ -374,8 +360,6 @@ typedef const Point_2& reference; \sa`CGAL::Random_points_in_tetrahedral_mesh_3` \sa `CGAL::Random_points_in_triangles_3` \sa `CGAL::Random_points_in_triangles_2` - \sa `std::random_shuffle` - */ template< typename Point_2, typename Triangulation, @@ -432,8 +416,6 @@ get_default_random() ); \cgalModels `InputIterator` \cgalModels `PointGenerator` - \sa `std::copy_n()` - \sa `CGAL::Counting_iterator` \sa `CGAL::Points_on_segment_2` \sa `CGAL::Random_points_in_disc_2` \sa `CGAL::Random_points_on_segment_2` @@ -445,8 +427,6 @@ get_default_random() ); \sa `CGAL::Random_points_in_tetrahedral_mesh_boundary_3` \sa `CGAL::Random_points_in_tetrahedral_mesh_3` \sa `CGAL::Random_points_in_triangles_3` - \sa `std::random_shuffle` - */ template< typename Point_2, typename Triangle_2 = typename Kernel_traits::Kernel::Triangle_2, @@ -506,8 +486,6 @@ rounding errors. \cgalModels `InputIterator` \cgalModels `PointGenerator` -\sa `std::copy_n()` -\sa `CGAL::Counting_iterator` \sa `CGAL::Points_on_segment_2` \sa `CGAL::Random_points_in_disc_2` \sa `CGAL::Random_points_in_square_2` @@ -515,8 +493,6 @@ rounding errors. \sa `CGAL::Random_points_on_segment_2` \sa `CGAL::Random_points_on_square_2` \sa `CGAL::Random_points_on_sphere_3` -\sa `std::random_shuffle` - */ template< typename Point_2, typename Creator > class Random_points_on_circle_2 { @@ -577,16 +553,12 @@ distributed on a segment. The default `Creator` is \cgalModels `InputIterator` \cgalModels `PointGenerator` -\sa `std::copy_n()` -\sa `CGAL::Counting_iterator` \sa `CGAL::Points_on_segment_2` \sa `CGAL::Random_points_in_disc_2` \sa `CGAL::Random_points_in_square_2` \sa `CGAL::Random_points_in_triangle_2` \sa `CGAL::Random_points_on_circle_2` \sa `CGAL::Random_points_on_square_2` -\sa `std::random_shuffle` - */ template< typename Point_2, typename Creator > class Random_points_on_segment_2 { @@ -647,16 +619,12 @@ distributed on the boundary of a square. The default `Creator` is \cgalModels `InputIterator` \cgalModels `PointGenerator` -\sa `std::copy_n()` -\sa `CGAL::Counting_iterator` \sa `CGAL::Points_on_segment_2` \sa `CGAL::Random_points_in_disc_2` \sa `CGAL::Random_points_in_square_2` \sa `CGAL::Random_points_in_triangle_2` \sa `CGAL::Random_points_on_circle_2` \sa `CGAL::Random_points_on_segment_2` -\sa `std::random_shuffle` - */ template< typename Point_2, typename Creator > class Random_points_on_square_2 { @@ -717,8 +685,6 @@ endpoints are specified upon construction. The points are equally spaced. \cgalModels `PointGenerator` -\sa `std::copy_n()` -\sa `CGAL::Counting_iterator` \sa `CGAL::points_on_segment` \sa `CGAL::Random_points_in_disc_2` \sa `CGAL::Random_points_in_square_2` @@ -727,8 +693,6 @@ endpoints are specified upon construction. The points are equally spaced. \sa `CGAL::Random_points_on_segment_2` \sa `CGAL::Random_points_on_square_2` \sa `CGAL::random_selection()` -\sa `std::random_shuffle` - */ template< typename Point_2 > class Points_on_segment_2 { diff --git a/Generator/doc/Generator/CGAL/point_generators_3.h b/Generator/doc/Generator/CGAL/point_generators_3.h index e8ea46c7060..1eb5c014f0b 100644 --- a/Generator/doc/Generator/CGAL/point_generators_3.h +++ b/Generator/doc/Generator/CGAL/point_generators_3.h @@ -44,15 +44,11 @@ distributed in a half-open cube. The default `Creator` is \cgalModels `InputIterator` \cgalModels `PointGenerator` -\sa `std::copy_n()` -\sa `CGAL::Counting_iterator` \sa `CGAL::Random_points_in_square_2` \sa `CGAL::Random_points_in_sphere_3` \sa `CGAL::Random_points_in_triangle_3` \sa `CGAL::Random_points_in_tetrahedron_3` \sa `CGAL::Random_points_on_sphere_3` -\sa `std::random_shuffle` - */ template< typename Point_3, typename Creator > class Random_points_in_cube_3 { @@ -113,15 +109,11 @@ distributed strictly inside a sphere. The default `Creator` is \cgalModels `InputIterator` \cgalModels `PointGenerator` -\sa `std::copy_n()` -\sa `CGAL::Counting_iterator` \sa `CGAL::Random_points_in_disc_2` \sa `CGAL::Random_points_in_cube_3` \sa `CGAL::Random_points_in_triangle_3` \sa `CGAL::Random_points_in_tetrahedron_3` \sa `CGAL::Random_points_on_sphere_3` -\sa `std::random_shuffle` - */ template< typename Point_3, typename Creator > class Random_points_in_sphere_3 { @@ -182,14 +174,10 @@ distributed inside a 3D triangle. The default `Creator` is \cgalModels `InputIterator` \cgalModels `PointGenerator` -\sa `std::copy_n()` -\sa `CGAL::Counting_iterator` \sa `CGAL::Random_points_in_disc_2` \sa `CGAL::Random_points_in_cube_3` \sa `CGAL::Random_points_in_tetrahedron_3` \sa `CGAL::Random_points_on_sphere_3` -\sa `std::random_shuffle` - */ template< typename Point_3, typename Creator > class Random_points_in_triangle_3 { @@ -260,10 +248,10 @@ distributed on a segment. The default `Creator` is \cgalModels `InputIterator` \cgalModels `PointGenerator` -\sa `std::copy_n()` -\sa `CGAL::Counting_iterator` -\sa `std::random_shuffle` - +\sa `CGAL::Random_points_in_cube_3` +\sa `CGAL::Random_points_in_triangle_3` +\sa `CGAL::Random_points_on_sphere_3` +\sa `CGAL::Random_points_in_tetrahedron_3` */ template< typename Point_3, typename Creator > class Random_points_on_segment_3 { @@ -326,13 +314,10 @@ distributed inside a tetrahedron. The default `Creator` is \cgalModels `InputIterator` \cgalModels `PointGenerator` -\sa `std::copy_n()` -\sa `CGAL::Counting_iterator` +\sa `CGAL::Random_points_on_segment_3` \sa `CGAL::Random_points_in_cube_3` \sa `CGAL::Random_points_in_triangle_3` \sa `CGAL::Random_points_on_sphere_3` -\sa `std::random_shuffle` - */ template< typename Point_3, typename Creator > class Random_points_in_tetrahedron_3 { @@ -405,8 +390,6 @@ The triangle range must be valid and unchanged while the iterator is used. \cgalModels `InputIterator` \cgalModels `PointGenerator` -\sa `std::copy_n()` -\sa `CGAL::Counting_iterator` \sa `CGAL::Random_points_in_cube_3` \sa `CGAL::Random_points_in_triangle_3` \sa `CGAL::Random_points_in_tetrahedron_3` @@ -414,8 +397,6 @@ The triangle range must be valid and unchanged while the iterator is used. \sa `CGAL::Random_points_in_tetrahedral_mesh_boundary_3` \sa `CGAL::Random_points_in_tetrahedral_mesh_3` \sa `CGAL::Random_points_in_triangles_2` -\sa `std::random_shuffle` - */ template< typename Point_3, typename Triangle_3=typename Kernel_traits::Kernel::Triangle_3, @@ -476,8 +457,6 @@ The triangle mesh must be valid and unchanged while the iterator is used. \cgalModels `InputIterator` \cgalModels `PointGenerator` -\sa `std::copy_n()` -\sa `CGAL::Counting_iterator` \sa `CGAL::Random_points_in_disc_2` \sa `CGAL::Random_points_in_cube_3` \sa `CGAL::Random_points_in_triangle_3` @@ -487,7 +466,6 @@ The triangle mesh must be valid and unchanged while the iterator is used. \sa `CGAL::Random_points_in_tetrahedral_mesh_3` \sa `CGAL::Random_points_in_triangles_2` \sa `CGAL::Random_points_in_triangles_3` -\sa `std::random_shuffle` */ template < class TriangleMesh, @@ -559,8 +537,6 @@ The tetrahedral mesh must be valid and unchanged while the iterator is used. \cgalModels `InputIterator` \cgalModels `PointGenerator` -\sa `std::copy_n()` -\sa `CGAL::Counting_iterator` \sa `CGAL::Random_points_in_disc_2` \sa `CGAL::Random_points_in_cube_3` \sa `CGAL::Random_points_in_triangle_3` @@ -570,8 +546,6 @@ The tetrahedral mesh must be valid and unchanged while the iterator is used. \sa `CGAL::Random_points_in_tetrahedral_mesh_3` \sa `CGAL::Random_points_in_triangles_2` \sa `CGAL::Random_points_in_triangles_3` -\sa `std::random_shuffle` - */ template ` \sa `CGAL::Random_points_in_cube_3` \sa `CGAL::Random_points_in_triangle_3` @@ -648,8 +620,6 @@ The tetrahedral mesh must be valid and unchanged while the iterator is used. \sa `CGAL::Random_points_in_tetrahedral_mesh_boundary_3` \sa `CGAL::Random_points_in_triangles_2` \sa `CGAL::Random_points_in_triangles_3` -\sa `std::random_shuffle` - */ template ` \sa `CGAL::Random_points_in_cube_3` \sa `CGAL::Random_points_in_sphere_3` -\sa `std::random_shuffle` - */ template< typename Point_3, typename Creator > class Random_points_on_sphere_3 { diff --git a/Generator/doc/Generator/CGAL/point_generators_d.h b/Generator/doc/Generator/CGAL/point_generators_d.h index 7a1b71f8c44..a06065a8ac1 100644 --- a/Generator/doc/Generator/CGAL/point_generators_d.h +++ b/Generator/doc/Generator/CGAL/point_generators_d.h @@ -43,13 +43,10 @@ distributed in an open ball in any dimension. \cgalModels `InputIterator` \cgalModels `PointGenerator` -\sa `std::copy_n()` -\sa `CGAL::Counting_iterator` \sa `CGAL::Random_points_in_disc_2` \sa `CGAL::Random_points_in_sphere_3` \sa `CGAL::Random_points_in_cube_d` \sa `CGAL::Random_points_on_sphere_d` - */ template< typename Point_d > class Random_points_in_ball_d { @@ -112,13 +109,10 @@ distributed in an half-open cube. \cgalModels `InputIterator` \cgalModels `PointGenerator` -\sa `std::copy_n()` -\sa `CGAL::Counting_iterator` \sa `CGAL::Random_points_in_square_2` \sa `CGAL::Random_points_in_cube_3` \sa `CGAL::Random_points_in_ball_d` \sa `CGAL::Random_points_on_sphere_d` - */ template< typename Point_d > class Random_points_in_cube_d { @@ -187,13 +181,10 @@ rounding errors. \cgalModels `InputIterator` \cgalModels `PointGenerator` -\sa `std::copy_n()` -\sa `CGAL::Counting_iterator` \sa `CGAL::Random_points_on_circle_2` \sa `CGAL::Random_points_on_sphere_3` \sa `CGAL::Random_points_in_cube_d` \sa `CGAL::Random_points_in_ball_d` - */ template< typename Point_d > class Random_points_on_sphere_d { diff --git a/STL_Extension/doc/STL_Extension/PackageDescription.txt b/STL_Extension/doc/STL_Extension/PackageDescription.txt index df921c5c6e0..b5d4b0141d1 100644 --- a/STL_Extension/doc/STL_Extension/PackageDescription.txt +++ b/STL_Extension/doc/STL_Extension/PackageDescription.txt @@ -41,11 +41,8 @@ - `CGAL::Multiset` \cgalCRPSection{Generic Algorithms} -- `std::copy_n` - `CGAL::copy_n` - `CGAL::min_max_element` -- `std::next` -- `std::prev` - `CGAL::predecessor` - `CGAL::successor` From fd4c75317a2fd98440710f499ea77d943ed0e1c2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mael=20Rouxel-Labb=C3=A9?= Date: Thu, 21 Nov 2019 10:03:06 +0100 Subject: [PATCH 311/363] Don't use preprocessor macros within an assert --- .../CGAL/_test_cls_constrained_triangulation_2.h | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) 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 455ff4828b8..b1616729e7e 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 @@ -60,11 +60,14 @@ _test_cdt_throwing(const Pt& p0, const Pt& p1, const Pt& p2, const Pt& p3, else // threw and it's not a construction-less intersection ---> real intersection { assert(intersection_type == INTERSECTION); - assert((boost::is_same::value) || #if !defined(CGAL_NO_DEPRECATED_CODE) && defined(CGAL_NO_DEPRECATION_WARNINGS) + assert((boost::is_same::value) || (boost::is_same::value) || -#endif (boost::is_same::value)); +#else + assert((boost::is_same::value) || + (boost::is_same::value)); +#endif } return; @@ -78,10 +81,10 @@ _test_cdt_throwing(const Pt& p0, const Pt& p1, const Pt& p2, const Pt& p3, else if(intersection_type == INTERSECTION) { assert(!(boost::is_same::value) && -#if !defined(CGAL_NO_DEPRECATED_CODE) && defined(CGAL_NO_DEPRECATION_WARNINGS) - !(boost::is_same::value) && -#endif !(boost::is_same::value)); +#if !defined(CGAL_NO_DEPRECATED_CODE) && defined(CGAL_NO_DEPRECATION_WARNINGS) + assert(!(boost::is_same::value)); +#endif } } From 6d8ae4661837b7e181b85c4bbe2884173f344c51 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mael=20Rouxel-Labb=C3=A9?= Date: Mon, 25 Nov 2019 09:24:23 +0100 Subject: [PATCH 312/363] Fix unused variable warning --- .../include/CGAL/_test_cls_constrained_triangulation_2.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) 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 b1616729e7e..eaa9e936e1c 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 @@ -45,7 +45,7 @@ _test_cdt_throwing(const Pt& p0, const Pt& p1, const Pt& p2, const Pt& p3, tr.insert_constraint(p0, p1); tr.insert_constraint(p2, p3); } - catch (typename Triang::Intersection_of_constraints_exception& e) + catch (typename Triang::Intersection_of_constraints_exception& /*e*/) { std::cout << "threw, expected: " << intersection_type << std::endl; From e5df49fa547e3270b98919a95f527a9326be325f Mon Sep 17 00:00:00 2001 From: Maxime Gimeno Date: Mon, 25 Nov 2019 16:09:00 +0100 Subject: [PATCH 313/363] Replace a nullptr by NULL --- .../include/CGAL/Surface_sweep_2/Surface_sweep_2_impl.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) 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 8afb7759435..f3529b99ceb 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 @@ -918,7 +918,7 @@ _create_overlapping_curve(const X_monotone_curve_2& overlap_cv, // Get the left end of overlap_cv. Event* left_event; - if (event_on_overlap!=nullptr) + if (event_on_overlap!=NULL) { CGAL_SS_PRINT_EVENT_INFO(event_on_overlap); CGAL_SS_PRINT_EOL(); From c662a5964532249e48848276216033dae340bfa9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9bastien=20Loriot?= Date: Tue, 26 Nov 2019 17:00:59 +0100 Subject: [PATCH 314/363] avoid a construction this helps the sweep working with EPICK in case no new construction are needed --- Arrangement_on_surface_2/include/CGAL/Arr_segment_traits_2.h | 3 ++- 1 file changed, 2 insertions(+), 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 9689695b4f8..a9f3506ea29 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 @@ -459,7 +459,8 @@ public: if (! cv.is_vertical()) { // Compare p with the segment's supporting line. - return (kernel.compare_y_at_x_2_object()(p, cv.line())); + CGAL_assertion( kernel.compare_x_2_object()(cv.left(), cv.right()) == SMALLER ); + return kernel.orientation_2_object()(cv.left(), cv.right(), p); } else { // Compare with the vertical segment's end-points. From d6aabc311a2ed9be9c596e2c422687cfde335b99 Mon Sep 17 00:00:00 2001 From: Laurent Rineau Date: Wed, 27 Nov 2019 14:18:03 +0100 Subject: [PATCH 315/363] updated crontab (automated commit) --- Maintenance/infrastructure/cgal.geometryfactory.com/crontab | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Maintenance/infrastructure/cgal.geometryfactory.com/crontab b/Maintenance/infrastructure/cgal.geometryfactory.com/crontab index ec794d29533..2d11b351e7c 100644 --- a/Maintenance/infrastructure/cgal.geometryfactory.com/crontab +++ b/Maintenance/infrastructure/cgal.geometryfactory.com/crontab @@ -53,7 +53,7 @@ LC_CTYPE=en_US.UTF-8 # Launch our Docker testsuite , at 21:36, # after a pull of all new images at 20:23. -06 20 * * * /usr/bin/time docker pull -a docker.io/cgal/testsuite-docker; docker rmi $(docker images | awk '// {print $3}') +06 20 * * * for i in $(cat /home/lrineau/.config/CGAL/test_cgal_docker_images); do docker pull $i; done; docker rmi $(docker images | awk '// {print $3}') 36 21 * * * cd /home/lrineau/Git/cgal-testsuite-dockerfiles && /usr/bin/time ./test_cgal.py --use-fedora-selinux-policy --force-rm --max-cpus 12 --container-cpus 4 --jobs 5 --upload-results --images $($HOME/bin/docker_images_to_test_today) From 511ff652cda5646274b4b8d351e401da7eacc0a3 Mon Sep 17 00:00:00 2001 From: Simon Giraudot Date: Mon, 2 Dec 2019 16:09:22 +0100 Subject: [PATCH 316/363] Remove cgalModif from doc --- Spatial_searching/doc/Spatial_searching/Spatial_searching.txt | 2 -- 1 file changed, 2 deletions(-) diff --git a/Spatial_searching/doc/Spatial_searching/Spatial_searching.txt b/Spatial_searching/doc/Spatial_searching/Spatial_searching.txt index 70a4ffeeb86..fb7fa79d487 100644 --- a/Spatial_searching/doc/Spatial_searching/Spatial_searching.txt +++ b/Spatial_searching/doc/Spatial_searching/Spatial_searching.txt @@ -503,7 +503,6 @@ instead of the distance itself. For instance for the Euclidean distance, to avoid the expensive computation of square roots, squared distances are used instead of the Euclidean distance itself. -\cgalModifBegin 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, @@ -518,7 +517,6 @@ set to `Tag_true`. The points coordinates will then be cached in an optimal way. This will increase memory consumption but provide better search performance. See also the `GeneralDistance` and `FuzzyQueryItem` concepts for additional requirements when using such a cache. -\cgalModifEnd \section Spatial_searchingImplementationHistory Implementation History From dd43f1c26221b78224f8a69d651a30f4519ea296 Mon Sep 17 00:00:00 2001 From: Simon Giraudot Date: Mon, 2 Dec 2019 16:10:28 +0100 Subject: [PATCH 317/363] Clean CHANGES.md --- Installation/CHANGES.md | 26 ++++++++++---------------- 1 file changed, 10 insertions(+), 16 deletions(-) diff --git a/Installation/CHANGES.md b/Installation/CHANGES.md index 8bbc2b25510..6b2fee77b92 100644 --- a/Installation/CHANGES.md +++ b/Installation/CHANGES.md @@ -73,6 +73,16 @@ Release date: October 2019 - Added the functions [`CGAL::Polygon_mesh_processing::stitch_boundary_cycle()`](https://doc.cgal.org/5.0/Polygon_mesh_processing/group__PMP__repairing__grp.html#ga9c12c4878c08a117b3733bb45f1a34cf) and [`CGAL::Polygon_mesh_processing::stitch_boundary_cycles()`](https://doc.cgal.org/5.0/Polygon_mesh_processing/group__PMP__repairing__grp.html#ga24d5ae37f62064b3fc576ba48a4ccc63), which can be used to try and merge together geometrically compatible but combinatorially different halfedges + that belong to the same boundary cycle. + - It is now possible to pass a face-size property map to [`CGAL::Polygon_mesh_processing::keep_large_connected_components()`](https://doc.cgal.org/5.0/Polygon_mesh_processing/group__keep__connected__components__grp.html#ga48e7b3e6922ee78cf8ce801e3e325d9a) + and [`CGAL::Polygon_mesh_processing::keep_largest_connected_components()`](https://doc.cgal.org/5.0/Polygon_mesh_processing/group__keep__connected__components__grp.html#ga68c6c29dfc6a26a6a2f8befe6944f19d), enabling users to define + how the size of a face is computed (the size of the connected component is the sum of the sizes of its faces). + If no property map is passed, the behavior is unchanged to previous versions: the size + of a connected component is the number of faces it contains. + - Added the function [`CGAL::Polygon_mesh_processing::non_manifold_vertices()`](https://doc.cgal.org/5.0/Polygon_mesh_processing/group__PMP__repairing__grp.html#ga36098d2415efd0604b7b996163bc22db), + which can be used to collect all the non-manifold vertices (i.e. pinched vertices, + or vertices appearing in multiple umbrellas) of a mesh. + ### dD Spatial Searching @@ -98,22 +108,6 @@ Release date: October 2019 k-NN search to interrupt some distance computations before its end, saving precious milliseconds, in particular in medium-to-high dimension. -### Polygon Mesh Processing - - Added the function `CGAL::Polygon_mesh_processing::centroid()`, which computes - the centroid of a closed triangle mesh. -- Added the functions `CGAL::Polygon_mesh_processing::stitch_boundary_cycle()` and - `CGAL::Polygon_mesh_processing::stitch_boundary_cycles()`, which can be used - to try and merge together geometrically compatible but combinatorially different halfedges - that belong to the same boundary cycle. - - It is now possible to pass a face-size property map to [`CGAL::Polygon_mesh_processing::keep_large_connected_components()`](https://doc.cgal.org/5.0/Polygon_mesh_processing/group__keep__connected__components__grp.html#ga48e7b3e6922ee78cf8ce801e3e325d9a) - and [`CGAL::Polygon_mesh_processing::keep_largest_connected_components()`](https://doc.cgal.org/5.0/Polygon_mesh_processing/group__keep__connected__components__grp.html#ga68c6c29dfc6a26a6a2f8befe6944f19d), enabling users to define - how the size of a face is computed (the size of the connected component is the sum of the sizes of its faces). - If no property map is passed, the behavior is unchanged to previous versions: the size - of a connected component is the number of faces it contains. - - Added the function [`CGAL::Polygon_mesh_processing::non_manifold_vertices()`](https://doc.cgal.org/5.0/Polygon_mesh_processing/group__PMP__repairing__grp.html#ga36098d2415efd0604b7b996163bc22db), - which can be used to collect all the non-manifold vertices (i.e. pinched vertices, - 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 read/write comments from/in the PLY header. From 53458f1f423702e76ef4a1e5cd28ddeed27f156c Mon Sep 17 00:00:00 2001 From: Maxime Gimeno Date: Mon, 2 Dec 2019 16:13:20 +0100 Subject: [PATCH 318/363] Indentation --- AABB_tree/include/CGAL/AABB_tree.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/AABB_tree/include/CGAL/AABB_tree.h b/AABB_tree/include/CGAL/AABB_tree.h index 0c60f3c0a0e..2d82c17efd6 100644 --- a/AABB_tree/include/CGAL/AABB_tree.h +++ b/AABB_tree/include/CGAL/AABB_tree.h @@ -623,7 +623,7 @@ public: T&& ... t) : m_traits() , m_primitives() - , m_p_root_node(nullptr) + , m_p_root_node(nullptr) , m_p_search_tree(nullptr) , m_search_tree_constructed(false) , m_default_search_tree_constructed(true) From cb813a5b490f83b626a8defbbabeb098057b37a4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mael=20Rouxel-Labb=C3=A9?= Date: Mon, 2 Dec 2019 16:24:41 +0100 Subject: [PATCH 319/363] Update CHANGES.md --- Installation/CHANGES.md | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/Installation/CHANGES.md b/Installation/CHANGES.md index b0d3bf73941..da238730f21 100644 --- a/Installation/CHANGES.md +++ b/Installation/CHANGES.md @@ -1,6 +1,16 @@ Release History =============== +Release 5.1 +----------- + +Release date: June 2020 + +### Polygon Mesh Processing + +- The function `CGAL::Polygon_mesh_processing::stitch_borders()` now returns the number + of halfedge pairs that were stitched. + Release 5.0 ----------- From 020aa0a4049ac052017e6fd57cbdf8fa58749ddb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mael=20Rouxel-Labb=C3=A9?= Date: Mon, 2 Dec 2019 16:31:35 +0100 Subject: [PATCH 320/363] Update CHANGES.md --- Installation/CHANGES.md | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/Installation/CHANGES.md b/Installation/CHANGES.md index b0d3bf73941..22dcb806766 100644 --- a/Installation/CHANGES.md +++ b/Installation/CHANGES.md @@ -1,6 +1,23 @@ Release History =============== +Release 5.1 +----------- + +Release date: June 2020 + +### 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 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. + Release 5.0 ----------- From b67c16d6d43df148df0431396dfb2ef6a589ce3b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9bastien=20Loriot?= Date: Mon, 2 Dec 2019 17:24:51 +0100 Subject: [PATCH 321/363] remove license notice --- .../internal/remove_degeneracies.h | 12 +----------- 1 file changed, 1 insertion(+), 11 deletions(-) diff --git a/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/internal/remove_degeneracies.h b/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/internal/remove_degeneracies.h index 762fcc9bee6..f6e582cf93f 100644 --- a/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/internal/remove_degeneracies.h +++ b/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/internal/remove_degeneracies.h @@ -2,20 +2,10 @@ // 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+ -// +// SPDX-License-Identifier: GPL-3.0-or-later OR LicenseRef-Commercial // // Author(s) : Sebastien Loriot, // Mael Rouxel-Labbé From fb273ea62aa55d1d838692e19b38f6de4e0a41a7 Mon Sep 17 00:00:00 2001 From: Maxime Gimeno Date: Tue, 3 Dec 2019 09:33:09 +0100 Subject: [PATCH 322/363] Fix indentation --- AABB_tree/include/CGAL/AABB_tree.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/AABB_tree/include/CGAL/AABB_tree.h b/AABB_tree/include/CGAL/AABB_tree.h index 2d82c17efd6..b2956aa795d 100644 --- a/AABB_tree/include/CGAL/AABB_tree.h +++ b/AABB_tree/include/CGAL/AABB_tree.h @@ -739,7 +739,7 @@ public: ConstPointIterator beyond) const { m_p_search_tree = new Search_tree(first, beyond); - m_default_search_tree_constructed = true; + m_default_search_tree_constructed = true; if(m_p_search_tree != nullptr) { m_search_tree_constructed = true; From ad30f5f440846034416fd3257c974ef2456a185f Mon Sep 17 00:00:00 2001 From: Laurent Rineau Date: Tue, 3 Dec 2019 19:25:51 +0100 Subject: [PATCH 323/363] Fix license header --- .../include/CGAL/internal/Search_helpers.h | 11 +---------- 1 file changed, 1 insertion(+), 10 deletions(-) diff --git a/Spatial_searching/include/CGAL/internal/Search_helpers.h b/Spatial_searching/include/CGAL/internal/Search_helpers.h index 68807cf33f7..d63b2deedb7 100644 --- a/Spatial_searching/include/CGAL/internal/Search_helpers.h +++ b/Spatial_searching/include/CGAL/internal/Search_helpers.h @@ -2,19 +2,10 @@ // 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+ +// SPDX-License-Identifier: GPL-3.0-or-later OR LicenseRef-Commercial // // // Author(s) : Clement Jamin (clement.jamin.pro@gmail.com) From b76ce69489b206c3dea601bc7392b5a7a130dd50 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mael=20Rouxel-Labb=C3=A9?= Date: Wed, 4 Dec 2019 12:00:33 +0100 Subject: [PATCH 324/363] Fix two solvers not showing up in documentation --- .../CGAL/GLPK_mixed_integer_program_traits.h | 436 +++++++++--------- .../CGAL/SCIP_mixed_integer_program_traits.h | 355 +++++++------- 2 files changed, 383 insertions(+), 408 deletions(-) diff --git a/Solver_interface/include/CGAL/GLPK_mixed_integer_program_traits.h b/Solver_interface/include/CGAL/GLPK_mixed_integer_program_traits.h index 4890c92c4bf..5023c1cc456 100644 --- a/Solver_interface/include/CGAL/GLPK_mixed_integer_program_traits.h +++ b/Solver_interface/include/CGAL/GLPK_mixed_integer_program_traits.h @@ -13,278 +13,262 @@ #include -#ifdef CGAL_USE_GLPK +#if defined(CGAL_USE_GLPK) || defined(DOXYGEN_RUNNING) #include +#include +#include namespace CGAL { +namespace internal { - /// \ingroup PkgSolver - /// - /// This class provides an interface for formulating and solving - /// mixed integer programs (constrained or unconstrained) using - /// \ref thirdpartyGLPK. - /// - /// \ref thirdpartyGLPK must be available on the system. - /// \note For better performance, please consider using - /// `SCIP_mixed_integer_program_traits`, or derive a new - /// model from `Mixed_integer_program_traits`. - /// - /// \cond SKIP_IN_MANUAL - /// \tparam FT Number type - /// \endcond - /// - /// \cgalModels `MixedIntegerProgramTraits` - /// - /// \sa `SCIP_mixed_integer_program_traits` +// Infers "bound type" (required by GLPK) from the bounds values +template +int bound_type(FT lb, FT ub) +{ + typedef CGAL::Variable Variable; - template - class GLPK_mixed_integer_program_traits : public Mixed_integer_program_traits - { - /// \cond SKIP_IN_MANUAL - public: - typedef CGAL::Mixed_integer_program_traits Base_class; - typedef typename Base_class::Variable Variable; - typedef typename Base_class::Linear_constraint Linear_constraint; - typedef typename Base_class::Linear_objective Linear_objective; - typedef typename Linear_objective::Sense Sense; - typedef typename Variable::Variable_type Variable_type; + if (lb <= -Variable::infinity() && ub >= Variable::infinity()) { + return GLP_FR; // free (unbounded) variable + } else if (lb > -Variable::infinity() && ub >= Variable::infinity()) { + return GLP_LO; // variable with lower bound + } else if (lb <= -Variable::infinity() && ub < Variable::infinity()) { + return GLP_UP; // variable with upper bound + } else { + // lb > -Variable::infinity() && ub < Variable::infinity() + if (lb == ub) + return GLP_FX; // fixed variable + else + return GLP_DB; // double-bounded variable + } +} - public: +} // namespace internal - /// Solves the program. Returns false if fails. - virtual bool solve(); - /// \endcond - }; +/// \ingroup PkgSolver +/// +/// This class provides an interface for formulating and solving +/// constrained or unconstrained mixed integer programs using +/// \ref thirdpartyGLPK, which must be available on the system. +/// +/// \note For better performance, please consider using +/// `SCIP_mixed_integer_program_traits`, or derive a new +/// model from `Mixed_integer_program_traits`. +/// +/// \cgalModels `MixedIntegerProgramTraits` +/// +/// \sa `SCIP_mixed_integer_program_traits` +template +class GLPK_mixed_integer_program_traits + : public Mixed_integer_program_traits +{ + /// \cond SKIP_IN_MANUAL +public: + typedef CGAL::Mixed_integer_program_traits Base_class; + typedef typename Base_class::Variable Variable; + typedef typename Base_class::Linear_constraint Linear_constraint; + typedef typename Base_class::Linear_objective Linear_objective; + typedef typename Linear_objective::Sense Sense; + typedef typename Variable::Variable_type Variable_type; - ////////////////////////////////////////////////////////////////////////// +public: + /// Solves the program. Returns `false` if fails. + virtual bool solve() + { + Base_class::error_message_.clear(); - // implementation + glp_prob* lp = glp_create_prob(); + if (!lp) { + Base_class::error_message_ = "failed creating GLPK program"; + return false; + } - /// \cond SKIP_IN_MANUAL + std::size_t num_integer_variables = 0; - namespace internal { + // Creates variables - // Infers "bound type" (required by GLPK) from the bounds values - template - int bound_type(FT lb, FT ub) { - typedef CGAL::Variable Variable; + // This "static_cast<>" suppresses many annoying warnings: "conversion from 'size_t' to 'int', possible loss of data" + int num_variables = static_cast(Base_class::variables_.size()); - if (lb <= -Variable::infinity() && ub >= Variable::infinity()) - return GLP_FR; // free (unbounded) variable + glp_add_cols(lp, num_variables); + for (int i = 0; i < num_variables; ++i) { + const Variable* var = Base_class::variables_[i]; + glp_set_col_name(lp, i + 1, var->name().c_str()); - else if (lb > -Variable::infinity() && ub >= Variable::infinity()) - return GLP_LO; // variable with lower bound + if (var->variable_type() == Variable::INTEGER) { + glp_set_col_kind(lp, i + 1, GLP_IV); // glpk uses 1-based arrays + ++num_integer_variables; + } else if (var->variable_type() == Variable::BINARY) { + glp_set_col_kind(lp, i + 1, GLP_BV); // glpk uses 1-based arrays + ++num_integer_variables; + } else { + glp_set_col_kind(lp, i + 1, GLP_CV); // Continuous variable + } - else if (lb <= -Variable::infinity() && ub < Variable::infinity()) - return GLP_UP; // variable with upper bound + FT lb, ub; + var->get_bounds(lb, ub); - else {// lb > -Variable::infinity() && ub < Variable::infinity() - if (lb == ub) - return GLP_FX; // fixed variable - else - return GLP_DB; // double-bounded variable - } - } - } - /// \endcond + int type = internal::bound_type(lb, ub); + glp_set_col_bnds(lp, i + 1, type, lb, ub); + } - template - bool GLPK_mixed_integer_program_traits::solve() { - Base_class::error_message_.clear(); + // Adds constraints - glp_prob* lp = glp_create_prob(); - if (!lp) { - Base_class::error_message_ = "failed creating GLPK program"; - return false; - } + // This "static_cast<>" suppresses many annoying warnings: "conversion from 'size_t' to 'int', possible loss of data" + int num_constraints = static_cast(Base_class::constraints_.size()); + glp_add_rows(lp, num_constraints); - std::size_t num_integer_variables = 0; + for (int i = 0; i < num_constraints; ++i) { + const Linear_constraint* c = Base_class::constraints_[i]; + const std::unordered_map& coeffs = c->coefficients(); + typename std::unordered_map::const_iterator cur = coeffs.begin(); - // Creates variables + std::vector indices(coeffs.size() + 1, 0); // glpk uses 1-based arrays + std::vector coefficients(coeffs.size() + 1, 0.0); // glpk uses 1-based arrays + std::size_t idx = 1; // glpk uses 1-based arrays + for (; cur != coeffs.end(); ++cur) { + int var_idx = cur->first->index(); + FT coeff = cur->second; - // This "static_cast<>" suppresses many annoying warnings: "conversion from 'size_t' to 'int', possible loss of data" - int num_variables = static_cast(Base_class::variables_.size()); + indices[idx] = var_idx + 1; // glpk uses 1-based arrays + coefficients[idx] = coeff; + ++idx; + } - glp_add_cols(lp, num_variables); - for (int i = 0; i < num_variables; ++i) { - const Variable* var = Base_class::variables_[i]; - glp_set_col_name(lp, i + 1, var->name().c_str()); + glp_set_mat_row(lp, i + 1, static_cast(coeffs.size()), indices.data(), coefficients.data()); - if (var->variable_type() == Variable::INTEGER) { - glp_set_col_kind(lp, i + 1, GLP_IV); // glpk uses 1-based arrays - ++num_integer_variables; - } - else if (var->variable_type() == Variable::BINARY) { - glp_set_col_kind(lp, i + 1, GLP_BV); // glpk uses 1-based arrays - ++num_integer_variables; - } - else - glp_set_col_kind(lp, i + 1, GLP_CV); // Continuous variable + FT lb, ub; + c->get_bounds(lb, ub); - FT lb, ub; - var->get_bounds(lb, ub); + int type = internal::bound_type(lb, ub); + glp_set_row_bnds(lp, i + 1, type, lb, ub); - int type = internal::bound_type(lb, ub); - glp_set_col_bnds(lp, i + 1, type, lb, ub); - } + glp_set_row_name(lp, i + 1, c->name().c_str()); + } - // Adds constraints + // Sets objective - // This "static_cast<>" suppresses many annoying warnings: "conversion from 'size_t' to 'int', possible loss of data" - int num_constraints = static_cast(Base_class::constraints_.size()); - glp_add_rows(lp, num_constraints); + // Determines the coefficient of each variable in the objective function + const std::unordered_map& obj_coeffs = Base_class::objective_->coefficients(); + typename std::unordered_map::const_iterator cur = obj_coeffs.begin(); + for (; cur != obj_coeffs.end(); ++cur) { + int var_idx = cur->first->index(); + FT coeff = cur->second; + glp_set_obj_coef(lp, var_idx + 1, coeff); // glpk uses 1-based arrays + } - for (int i = 0; i < num_constraints; ++i) { - const Linear_constraint* c = Base_class::constraints_[i]; - const std::unordered_map& coeffs = c->coefficients(); - typename std::unordered_map::const_iterator cur = coeffs.begin(); + // Sets objective function sense + bool minimize = (Base_class::objective_->sense() == Linear_objective::MINIMIZE); + glp_set_obj_dir(lp, minimize ? GLP_MIN : GLP_MAX); + int msg_level = GLP_MSG_ERR; + int status = -1; + if (num_integer_variables == 0) { // Continuous problem + glp_smcp parm; + glp_init_smcp(&parm); + parm.msg_lev = msg_level; + status = glp_simplex(lp, &parm); + } + else { // Solves as MIP problem + glp_iocp parm; + glp_init_iocp(&parm); + parm.msg_lev = msg_level; + parm.presolve = GLP_ON; + // The routine glp_intopt is a driver to the MIP solver based on the branch-and-cut method, + // which is a hybrid of branch-and-bound and cutting plane methods. + status = glp_intopt(lp, &parm); + } - std::vector indices(coeffs.size() + 1, 0); // glpk uses 1-based arrays - std::vector coefficients(coeffs.size() + 1, 0.0); // glpk uses 1-based arrays - std::size_t idx = 1; // glpk uses 1-based arrays - for (; cur != coeffs.end(); ++cur) { - int var_idx = cur->first->index(); - FT coeff = cur->second; + switch (status) { + case 0: { + if (num_integer_variables == 0) { // continuous problem + Base_class::result_.resize(num_variables); + for (int i = 0; i < num_variables; ++i) { + FT x = glp_get_col_prim(lp, i + 1); // glpk uses 1-based arrays + Variable* v = Base_class::variables_[i]; + v->set_solution_value(x); + Base_class::result_[i] = x; + } + } + else { // MIP problem + Base_class::result_.resize(num_variables); + for (int i = 0; i < num_variables; ++i) { + FT x = glp_mip_col_val(lp, i + 1); // glpk uses 1-based arrays - indices[idx] = var_idx + 1; // glpk uses 1-based arrays - coefficients[idx] = coeff; - ++idx; - } + Variable* v = Base_class::variables_[i]; + if (v->variable_type() != Variable::CONTINUOUS) + x = static_cast(std::round(x)); - glp_set_mat_row(lp, i + 1, static_cast(coeffs.size()), indices.data(), coefficients.data()); + v->set_solution_value(x); + Base_class::result_[i] = x; + } + } + break; + } - FT lb, ub; - c->get_bounds(lb, ub); + case GLP_EBOUND: + Base_class::error_message_ = + "Unable to start the search, because some FT-bounded variables have incorrect" + "bounds or some integer variables have non - integer(fractional) bounds."; + break; - int type = internal::bound_type(lb, ub); - glp_set_row_bnds(lp, i + 1, type, lb, ub); + case GLP_EROOT: + Base_class::error_message_ = + "Unable to start the search, because optimal basis for initial LP relaxation is not" + "provided. (This code may appear only if the presolver is disabled.)"; + break; - glp_set_row_name(lp, i + 1, c->name().c_str()); - } + case GLP_ENOPFS: + Base_class::error_message_ = + "Unable to start the search, because LP relaxation of the MIP problem instance has" + "no primal feasible solution. (This code may appear only if the presolver is enabled.)"; + break; - // Sets objective + case GLP_ENODFS: + Base_class::error_message_ = + "Unable to start the search, because LP relaxation of the MIP problem instance has" + "no dual feasible solution.In other word, this code means that if the LP relaxation" + "has at least one primal feasible solution, its optimal solution is unbounded, so if the" + "MIP problem has at least one integer feasible solution, its(integer) optimal solution" + "is also unbounded. (This code may appear only if the presolver is enabled.)"; + break; - // Determines the coefficient of each variable in the objective function - const std::unordered_map& obj_coeffs = Base_class::objective_->coefficients(); - typename std::unordered_map::const_iterator cur = obj_coeffs.begin(); - for (; cur != obj_coeffs.end(); ++cur) { - int var_idx = cur->first->index(); - FT coeff = cur->second; - glp_set_obj_coef(lp, var_idx + 1, coeff); // glpk uses 1-based arrays - } + case GLP_EFAIL: + Base_class::error_message_ = + "The search was prematurely terminated due to the solver failure."; + break; - // Sets objective function sense - bool minimize = (Base_class::objective_->sense() == Linear_objective::MINIMIZE); - glp_set_obj_dir(lp, minimize ? GLP_MIN : GLP_MAX); - int msg_level = GLP_MSG_ERR; - int status = -1; - if (num_integer_variables == 0) { // Continuous problem - glp_smcp parm; - glp_init_smcp(&parm); - parm.msg_lev = msg_level; - status = glp_simplex(lp, &parm); - } - else { // Solves as MIP problem - glp_iocp parm; - glp_init_iocp(&parm); - parm.msg_lev = msg_level; - parm.presolve = GLP_ON; - // The routine glp_intopt is a driver to the MIP solver based on the branch-and-cut method, - // which is a hybrid of branch-and-bound and cutting plane methods. - status = glp_intopt(lp, &parm); - } + case GLP_EMIPGAP: + Base_class::error_message_ = + "The search was prematurely terminated, because the relative mip gap tolerance has been reached."; + break; - switch (status) { - case 0: { - if (num_integer_variables == 0) { // continuous problem - Base_class::result_.resize(num_variables); - for (int i = 0; i < num_variables; ++i) { - FT x = glp_get_col_prim(lp, i + 1); // glpk uses 1-based arrays - Variable* v = Base_class::variables_[i]; - v->set_solution_value(x); - Base_class::result_[i] = x; - } - } - else { // MIP problem - Base_class::result_.resize(num_variables); - for (int i = 0; i < num_variables; ++i) { - FT x = glp_mip_col_val(lp, i + 1); // glpk uses 1-based arrays + case GLP_ETMLIM: + Base_class::error_message_ = + "The search was prematurely terminated, because the time limit has been exceeded."; + break; - Variable* v = Base_class::variables_[i]; - if (v->variable_type() != Variable::CONTINUOUS) - x = static_cast(std::round(x)); + case GLP_ESTOP: + Base_class::error_message_ = + "The search was prematurely terminated by application. (This code may appear only" + "if the advanced solver interface is used.)"; + break; - v->set_solution_value(x); - Base_class::result_[i] = x; - } - } - break; - } + default: + Base_class::error_message_ = + "optimization was stopped with status code " + std::to_string(status); + break; + } - case GLP_EBOUND: - Base_class::error_message_ = - "Unable to start the search, because some FT-bounded variables have incorrect" - "bounds or some integer variables have non - integer(fractional) bounds."; - break; - - case GLP_EROOT: - Base_class::error_message_ = - "Unable to start the search, because optimal basis for initial LP relaxation is not" - "provided. (This code may appear only if the presolver is disabled.)"; - break; - - case GLP_ENOPFS: - Base_class::error_message_ = - "Unable to start the search, because LP relaxation of the MIP problem instance has" - "no primal feasible solution. (This code may appear only if the presolver is enabled.)"; - break; - - case GLP_ENODFS: - Base_class::error_message_ = - "Unable to start the search, because LP relaxation of the MIP problem instance has" - "no dual feasible solution.In other word, this code means that if the LP relaxation" - "has at least one primal feasible solution, its optimal solution is unbounded, so if the" - "MIP problem has at least one integer feasible solution, its(integer) optimal solution" - "is also unbounded. (This code may appear only if the presolver is enabled.)"; - break; - - case GLP_EFAIL: - Base_class::error_message_ = - "The search was prematurely terminated due to the solver failure."; - break; - - case GLP_EMIPGAP: - Base_class::error_message_ = - "The search was prematurely terminated, because the relative mip gap tolerance has been reached."; - break; - - case GLP_ETMLIM: - Base_class::error_message_ = - "The search was prematurely terminated, because the time limit has been exceeded."; - break; - - case GLP_ESTOP: - Base_class::error_message_ = - "The search was prematurely terminated by application. (This code may appear only" - "if the advanced solver interface is used.)"; - break; - - default: - Base_class::error_message_ = - "optimization was stopped with status code " + std::to_string(status); - break; - } - - glp_delete_prob(lp); - - return (status == 0); - } + glp_delete_prob(lp); + return (status == 0); + } + /// \endcond +}; } // namespace CGAL -#endif // CGAL_USE_GLPK +#endif // CGAL_USE_GLPK or DOXYGEN_RUNNING #endif // CGAL_GLPK_MIXED_INTEGER_PROGRAM_TRAITS_H diff --git a/Solver_interface/include/CGAL/SCIP_mixed_integer_program_traits.h b/Solver_interface/include/CGAL/SCIP_mixed_integer_program_traits.h index 6f2952bf0eb..00a35145187 100644 --- a/Solver_interface/include/CGAL/SCIP_mixed_integer_program_traits.h +++ b/Solver_interface/include/CGAL/SCIP_mixed_integer_program_traits.h @@ -13,226 +13,217 @@ #include -#ifdef CGAL_USE_SCIP +#if defined(CGAL_USE_SCIP) || defined(DOXYGEN_RUNNING) #include "scip/scip.h" #include "scip/scipdefplugins.h" +#include +#include +#include +#include + namespace CGAL { - /// \ingroup PkgSolver - /// - /// This class provides an interface for formulating and solving - /// mixed integer programs (constrained or unconstrained) using - /// \ref thirdpartySCIP. - /// - /// \ref thirdpartySCIP must be available on the system. - /// - /// \cond SKIP_IN_MANUAL - /// \tparam FT Number type - /// \endcond - /// - /// \cgalModels `MixedIntegerProgramTraits` - /// - /// \sa `GLPK_mixed_integer_program_traits` +/// \ingroup PkgSolver +/// +/// This class provides an interface for formulating and solving +/// constrained or unconstrained mixed integer programs using +/// \ref thirdpartySCIP (which must be available on the system). +/// +/// \cgalModels `MixedIntegerProgramTraits` +/// +/// \sa `GLPK_mixed_integer_program_traits` +template +class SCIP_mixed_integer_program_traits + : public Mixed_integer_program_traits +{ + /// \cond SKIP_IN_MANUAL +public: + typedef CGAL::Mixed_integer_program_traits Base_class; + typedef typename Base_class::Variable Variable; + typedef typename Base_class::Linear_constraint Linear_constraint; + typedef typename Base_class::Linear_objective Linear_objective; + typedef typename Linear_objective::Sense Sense; + typedef typename Variable::Variable_type Variable_type; - template - class SCIP_mixed_integer_program_traits : public Mixed_integer_program_traits - { - /// \cond SKIP_IN_MANUAL - public: - typedef CGAL::Mixed_integer_program_traits Base_class; - typedef typename Base_class::Variable Variable; - typedef typename Base_class::Linear_constraint Linear_constraint; - typedef typename Base_class::Linear_objective Linear_objective; - typedef typename Linear_objective::Sense Sense; - typedef typename Variable::Variable_type Variable_type; +public: + /// Solves the program. Returns `false` if fails. + virtual bool solve() + { + Base_class::error_message_.clear(); - public: + Scip* scip = 0; + SCIP_CALL(SCIPcreate(&scip)); + SCIP_CALL(SCIPincludeDefaultPlugins(scip)); - /// Solves the program. Returns false if fails. - virtual bool solve(); - /// \endcond - }; + // Disables scip output to stdout + SCIPmessagehdlrSetQuiet(SCIPgetMessagehdlr(scip), TRUE); - ////////////////////////////////////////////////////////////////////////// + // Uses wall clock time because getting CPU user seconds + // involves calling times() which is very expensive + SCIP_CALL(SCIPsetIntParam(scip, "timing/clocktype", SCIP_CLOCKTYPE_WALL)); - // implementation + // Creates empty problem + SCIP_CALL(SCIPcreateProbBasic(scip, "Solver_interface")); - template - bool SCIP_mixed_integer_program_traits::solve() - { - Base_class::error_message_.clear(); + // Creates variables + std::vector scip_variables; + for (std::size_t i = 0; i < Base_class::variables_.size(); ++i) { + const Variable* var = Base_class::variables_[i]; + SCIP_VAR* v = 0; - Scip* scip = 0; - SCIP_CALL(SCIPcreate(&scip)); - SCIP_CALL(SCIPincludeDefaultPlugins(scip)); + double lb, ub; + var->get_bounds(lb, ub); - // Disables scip output to stdout - SCIPmessagehdlrSetQuiet(SCIPgetMessagehdlr(scip), TRUE); + switch (var->variable_type()) + { + case Variable::CONTINUOUS: + SCIP_CALL(SCIPcreateVar(scip, &v, var->name().c_str(), lb, ub, 0.0, SCIP_VARTYPE_CONTINUOUS, TRUE, FALSE, 0, 0, 0, 0, 0)); + break; + case Variable::INTEGER: + SCIP_CALL(SCIPcreateVar(scip, &v, var->name().c_str(), lb, ub, 0.0, SCIP_VARTYPE_INTEGER, TRUE, FALSE, 0, 0, 0, 0, 0)); + break; + case Variable::BINARY: + SCIP_CALL(SCIPcreateVar(scip, &v, var->name().c_str(), 0, 1, 0.0, SCIP_VARTYPE_BINARY, TRUE, FALSE, 0, 0, 0, 0, 0)); + break; + } + // Adds the SCIP_VAR object to the scip problem + SCIP_CALL(SCIPaddVar(scip, v)); - // Uses wall clock time because getting CPU user seconds - // involves calling times() which is very expensive - SCIP_CALL(SCIPsetIntParam(scip, "timing/clocktype", SCIP_CLOCKTYPE_WALL)); + // Stores the SCIP_VAR pointer for later access + scip_variables.push_back(v); + } - // Creates empty problem - SCIP_CALL(SCIPcreateProbBasic(scip, "Solver_interface")); + // Adds constraints - // Creates variables - std::vector scip_variables; - for (std::size_t i = 0; i < Base_class::variables_.size(); ++i) { - const Variable* var = Base_class::variables_[i]; - SCIP_VAR* v = 0; + std::vector scip_constraints; + for (std::size_t i = 0; i < Base_class::constraints_.size(); ++i) { + const Linear_constraint* c = Base_class::constraints_[i]; + const std::unordered_map& coeffs = c->coefficients(); + typename std::unordered_map::const_iterator cur = coeffs.begin(); - double lb, ub; - var->get_bounds(lb, ub); + std::vector cstr_variables(coeffs.size()); + std::vector cstr_values(coeffs.size()); + std::size_t idx = 0; + for (; cur != coeffs.end(); ++cur) { + std::size_t var_idx = cur->first->index(); + double coeff = cur->second; + cstr_variables[idx] = scip_variables[var_idx]; + cstr_values[idx] = coeff; + ++idx; + } - switch (var->variable_type()) - { - case Variable::CONTINUOUS: - SCIP_CALL(SCIPcreateVar(scip, &v, var->name().c_str(), lb, ub, 0.0, SCIP_VARTYPE_CONTINUOUS, TRUE, FALSE, 0, 0, 0, 0, 0)); - break; - case Variable::INTEGER: - SCIP_CALL(SCIPcreateVar(scip, &v, var->name().c_str(), lb, ub, 0.0, SCIP_VARTYPE_INTEGER, TRUE, FALSE, 0, 0, 0, 0, 0)); - break; - case Variable::BINARY: - SCIP_CALL(SCIPcreateVar(scip, &v, var->name().c_str(), 0, 1, 0.0, SCIP_VARTYPE_BINARY, TRUE, FALSE, 0, 0, 0, 0, 0)); - break; - } - // Adds the SCIP_VAR object to the scip problem - SCIP_CALL(SCIPaddVar(scip, v)); + // Creates SCIP_CONS object + SCIP_CONS* cons = 0; + const std::string& name = c->name(); - // Stores the SCIP_VAR pointer for later access - scip_variables.push_back(v); - } + double lb, ub; + c->get_bounds(lb, ub); - // Adds constraints + SCIP_CALL(SCIPcreateConsLinear(scip, &cons, name.c_str(), int(coeffs.size()), cstr_variables.data(), cstr_values.data(), lb, ub, TRUE, TRUE, TRUE, TRUE, TRUE, FALSE, FALSE, FALSE, FALSE, FALSE)); - std::vector scip_constraints; - for (std::size_t i = 0; i < Base_class::constraints_.size(); ++i) { - const Linear_constraint* c = Base_class::constraints_[i]; - const std::unordered_map& coeffs = c->coefficients(); - typename std::unordered_map::const_iterator cur = coeffs.begin(); + // Adds the constraint to scip + SCIP_CALL(SCIPaddCons(scip, cons)); - std::vector cstr_variables(coeffs.size()); - std::vector cstr_values(coeffs.size()); - std::size_t idx = 0; - for (; cur != coeffs.end(); ++cur) { - std::size_t var_idx = cur->first->index(); - double coeff = cur->second; - cstr_variables[idx] = scip_variables[var_idx]; - cstr_values[idx] = coeff; - ++idx; - } + // Stores the constraint for later on + scip_constraints.push_back(cons); + } - // Creates SCIP_CONS object - SCIP_CONS* cons = 0; - const std::string& name = c->name(); + // Sets objective - double lb, ub; - c->get_bounds(lb, ub); + // Determines the coefficient of each variable in the objective function + const std::unordered_map& obj_coeffs = Base_class::objective_->coefficients(); + typename std::unordered_map::const_iterator cur = obj_coeffs.begin(); + for (; cur != obj_coeffs.end(); ++cur) { + const Variable* var = cur->first; + double coeff = cur->second; + SCIP_CALL(SCIPchgVarObj(scip, scip_variables[var->index()], coeff)); + } - SCIP_CALL(SCIPcreateConsLinear(scip, &cons, name.c_str(), int(coeffs.size()), cstr_variables.data(), cstr_values.data(), lb, ub, TRUE, TRUE, TRUE, TRUE, TRUE, FALSE, FALSE, FALSE, FALSE, FALSE)); + // Sets the objective sense + bool minimize = (Base_class::objective_->sense() == Linear_objective::MINIMIZE); + SCIP_CALL(SCIPsetObjsense(scip, minimize ? SCIP_OBJSENSE_MINIMIZE : SCIP_OBJSENSE_MAXIMIZE)); - // Adds the constraint to scip - SCIP_CALL(SCIPaddCons(scip, cons)); + // Turns presolve on (it's the SCIP default). + bool presolve = true; + if (presolve) + SCIP_CALL(SCIPsetIntParam(scip, "presolving/maxrounds", -1)); // maximal number of presolving rounds (-1: unlimited, 0: off) + else + SCIP_CALL(SCIPsetIntParam(scip, "presolving/maxrounds", 0)); // disable presolve - // Stores the constraint for later on - scip_constraints.push_back(cons); - } + bool status = false; + // This tells scip to start the solution process + if (SCIPsolve(scip) == SCIP_OKAY) { + // Gets the best found solution from scip + SCIP_SOL* sol = SCIPgetBestSol(scip); + if (sol) { + // If optimal or feasible solution is found. + Base_class::result_.resize(Base_class::variables_.size()); + for (std::size_t i = 0; i < Base_class::variables_.size(); ++i) { + FT x = SCIPgetSolVal(scip, sol, scip_variables[i]); - // Sets objective + Variable* v = Base_class::variables_[i]; + if (v->variable_type() != Variable::CONTINUOUS) + x = static_cast(std::round(x)); - // Determines the coefficient of each variable in the objective function - const std::unordered_map& obj_coeffs = Base_class::objective_->coefficients(); - typename std::unordered_map::const_iterator cur = obj_coeffs.begin(); - for (; cur != obj_coeffs.end(); ++cur) { - const Variable* var = cur->first; - double coeff = cur->second; - SCIP_CALL(SCIPchgVarObj(scip, scip_variables[var->index()], coeff)); - } + v->set_solution_value(x); + Base_class::result_[i] = x; + } + status = true; + } + } - // Sets the objective sense - bool minimize = (Base_class::objective_->sense() == Linear_objective::MINIMIZE); - SCIP_CALL(SCIPsetObjsense(scip, minimize ? SCIP_OBJSENSE_MINIMIZE : SCIP_OBJSENSE_MAXIMIZE)); + // Reports the status: optimal, infeasible, etc. + SCIP_STATUS scip_status = SCIPgetStatus(scip); + switch (scip_status) { + case SCIP_STATUS_OPTIMAL: + // Provides info only if fails. + break; + case SCIP_STATUS_GAPLIMIT: + // To be consistent with the other solvers. + // Provides info only if fails. + break; + case SCIP_STATUS_INFEASIBLE: + Base_class::error_message_ = "model was infeasible"; + break; + case SCIP_STATUS_UNBOUNDED: + Base_class::error_message_ = "model was unbounded"; + break; + case SCIP_STATUS_INFORUNBD: + Base_class::error_message_ = "model was either infeasible or unbounded"; + break; + case SCIP_STATUS_TIMELIMIT: + Base_class::error_message_ = "aborted due to time limit"; + break; + default: + Base_class::error_message_ = "aborted with status: " + std::to_string(scip_status); + break; + } - // Turns presolve on (it's the SCIP default). - bool presolve = true; - if (presolve) - SCIP_CALL(SCIPsetIntParam(scip, "presolving/maxrounds", -1)); // maximal number of presolving rounds (-1: unlimited, 0: off) - else - SCIP_CALL(SCIPsetIntParam(scip, "presolving/maxrounds", 0)); // disable presolve + SCIP_CALL(SCIPresetParams(scip)); - bool status = false; - // This tells scip to start the solution process - if (SCIPsolve(scip) == SCIP_OKAY) { - // Gets the best found solution from scip - SCIP_SOL* sol = SCIPgetBestSol(scip); - if (sol) { - // If optimal or feasible solution is found. - Base_class::result_.resize(Base_class::variables_.size()); - for (std::size_t i = 0; i < Base_class::variables_.size(); ++i) { - FT x = SCIPgetSolVal(scip, sol, scip_variables[i]); + // Since the SCIPcreateVar captures all variables, we have to release them now + for (std::size_t i = 0; i < scip_variables.size(); ++i) + SCIP_CALL(SCIPreleaseVar(scip, &scip_variables[i])); + scip_variables.clear(); - Variable* v = Base_class::variables_[i]; - if (v->variable_type() != Variable::CONTINUOUS) - x = static_cast(std::round(x)); + // The same for the constraints + for (std::size_t i = 0; i < scip_constraints.size(); ++i) + SCIP_CALL(SCIPreleaseCons(scip, &scip_constraints[i])); + scip_constraints.clear(); - v->set_solution_value(x); - Base_class::result_[i] = x; - } - status = true; - } - } + // After releasing all vars and cons we can free the scip problem. + // Remember this has always to be the last call to scip + SCIP_CALL(SCIPfree(&scip)); - // Reports the status: optimal, infeasible, etc. - SCIP_STATUS scip_status = SCIPgetStatus(scip); - switch (scip_status) { - case SCIP_STATUS_OPTIMAL: - // Provides info only if fails. - break; - case SCIP_STATUS_GAPLIMIT: - // To be consistent with the other solvers. - // Provides info only if fails. - break; - case SCIP_STATUS_INFEASIBLE: - Base_class::error_message_ = "model was infeasible"; - break; - case SCIP_STATUS_UNBOUNDED: - Base_class::error_message_ = "model was unbounded"; - break; - case SCIP_STATUS_INFORUNBD: - Base_class::error_message_ = "model was either infeasible or unbounded"; - break; - case SCIP_STATUS_TIMELIMIT: - Base_class::error_message_ = "aborted due to time limit"; - break; - default: - Base_class::error_message_ = "aborted with status: " + std::to_string(scip_status); - break; - } - - SCIP_CALL(SCIPresetParams(scip)); - - // Since the SCIPcreateVar captures all variables, we have to release them now - for (std::size_t i = 0; i < scip_variables.size(); ++i) - SCIP_CALL(SCIPreleaseVar(scip, &scip_variables[i])); - scip_variables.clear(); - - // The same for the constraints - for (std::size_t i = 0; i < scip_constraints.size(); ++i) - SCIP_CALL(SCIPreleaseCons(scip, &scip_constraints[i])); - scip_constraints.clear(); - - // After releasing all vars and cons we can free the scip problem. - // Remember this has always to be the last call to scip - SCIP_CALL(SCIPfree(&scip)); - - return status; - } + return status; + } + /// \endcond +}; } // namespace CGAL -#endif // CGAL_USE_SCIP +#endif // CGAL_USE_SCIP or DOXYGEN_RUNNING #endif // CGAL_SCIP_MIXED_INTEGER_PROGRAM_TRAITS_H From 420895125212b27dff66a129d5eef7dd6c861e02 Mon Sep 17 00:00:00 2001 From: Laurent Rineau Date: Mon, 2 Dec 2019 11:25:17 +0100 Subject: [PATCH 325/363] revert "Access to the "current" size of the compact container" Reverts commit 2836828d612e6077f9d480ee9347f2b81d3fed18 --- .../CGAL/Concurrent_compact_container.h | 21 +------------------ 1 file changed, 1 insertion(+), 20 deletions(-) diff --git a/STL_Extension/include/CGAL/Concurrent_compact_container.h b/STL_Extension/include/CGAL/Concurrent_compact_container.h index bdcd71cede3..d4fc001e828 100644 --- a/STL_Extension/include/CGAL/Concurrent_compact_container.h +++ b/STL_Extension/include/CGAL/Concurrent_compact_container.h @@ -258,11 +258,6 @@ public: { std::swap(m_alloc, c.m_alloc); std::swap(m_capacity, c.m_capacity); - { // non-atomic swap - size_type other_size = c.m_size; - c.m_size = size_type(m_size); - m_size = other_size; - } std::swap(m_block_size, c.m_block_size); std::swap(m_first_item, c.m_first_item); std::swap(m_last_item, c.m_last_item); @@ -453,7 +448,6 @@ private: #ifndef CGAL_NO_ASSERTIONS std::memset(&*x, 0, sizeof(T)); #endif*/ - --m_size; put_on_free_list(&*x, fl); } public: @@ -474,11 +468,9 @@ public: // The complexity is O(size(free list = capacity-size)). void merge(Self &d); - // If `CGAL_NO_ATOMIC` is defined, do not call this function while others - // are inserting/erasing elements + // Do not call this function while others are inserting/erasing elements size_type size() const { -#ifdef CGAL_NO_ATOMIC size_type size = m_capacity; for( typename Free_lists::iterator it_free_list = m_free_lists.begin() ; it_free_list != m_free_lists.end() ; @@ -487,9 +479,6 @@ public: size -= it_free_list->size(); } return size; -#else // atomic can be used - return m_size; -#endif } size_type max_size() const @@ -601,7 +590,6 @@ private: { CGAL_assertion(type(ret) == USED); fl->dec_size(); - ++m_size; return iterator(ret, 0); } @@ -693,7 +681,6 @@ private: m_first_item = NULL; m_last_item = NULL; m_all_items = All_items(); - m_size = 0; } allocator_type m_alloc; @@ -704,17 +691,11 @@ private: pointer m_last_item; All_items m_all_items; mutable Mutex m_mutex; -#ifdef CGAL_NO_ATOMIC - size_type m_size; -#else - CGAL::cpp11::atomic m_size; -#endif }; template < class T, class Allocator > void Concurrent_compact_container::merge(Self &d) { - m_size += d.m_size; CGAL_precondition(&d != this); // Allocators must be "compatible" : From 12181210e83714c30f1cf5049114afc879a63af9 Mon Sep 17 00:00:00 2001 From: Laurent Rineau Date: Tue, 3 Dec 2019 16:15:11 +0100 Subject: [PATCH 326/363] Add a bench of DT3 with TBB and Google benchmark --- Scripts/scripts/cgal_create_CMakeLists | 4 +- .../benchmark/Triangulation_3/CMakeLists.txt | 57 +++++++++++++++++++ .../DT3_benchmark_with_TBB.cpp | 53 +++++++++++++++++ 3 files changed, 112 insertions(+), 2 deletions(-) create mode 100644 Triangulation_3/benchmark/Triangulation_3/CMakeLists.txt create mode 100644 Triangulation_3/benchmark/Triangulation_3/DT3_benchmark_with_TBB.cpp diff --git a/Scripts/scripts/cgal_create_CMakeLists b/Scripts/scripts/cgal_create_CMakeLists index bcbf427b2d0..1f94a50980f 100755 --- a/Scripts/scripts/cgal_create_CMakeLists +++ b/Scripts/scripts/cgal_create_CMakeLists @@ -99,6 +99,8 @@ create_cmake_script_with_options() # 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.15) + EOF #--------------------------------------------------------------------------- if [ "$SINGLE_SOURCE" = "n" ]; then @@ -111,8 +113,6 @@ EOF cat << 'EOF' -cmake_minimum_required(VERSION 2.8.11) - # CGAL and its components EOF if [ -n "$ENABLE_CTEST" ]; then diff --git a/Triangulation_3/benchmark/Triangulation_3/CMakeLists.txt b/Triangulation_3/benchmark/Triangulation_3/CMakeLists.txt new file mode 100644 index 00000000000..0291f205496 --- /dev/null +++ b/Triangulation_3/benchmark/Triangulation_3/CMakeLists.txt @@ -0,0 +1,57 @@ +# 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.15) + +project( Triangulation_3 ) + + +# CGAL and its components +find_package( CGAL QUIET COMPONENTS ) + +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 for local package + + +# Creating entries for all C++ files with "main" routine +# ########################################################## + + +create_single_source_cgal_program( "incident_edges.cpp" ) + +create_single_source_cgal_program( "simple_2.cpp" ) + +create_single_source_cgal_program( "simple.cpp" ) + +create_single_source_cgal_program( "Triangulation_benchmark_3.cpp" ) + +find_package(benchmark) + +if(TARGET benchmark::benchmark) + find_package(TBB REQUIRED) + include( CGAL_target_use_TBB ) + + 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) +endif() diff --git a/Triangulation_3/benchmark/Triangulation_3/DT3_benchmark_with_TBB.cpp b/Triangulation_3/benchmark/Triangulation_3/DT3_benchmark_with_TBB.cpp new file mode 100644 index 00000000000..dad2b3c1871 --- /dev/null +++ b/Triangulation_3/benchmark/Triangulation_3/DT3_benchmark_with_TBB.cpp @@ -0,0 +1,53 @@ +#include +#include +#include +#include +#include + +#include +#include +#include + +typedef CGAL::Exact_predicates_inexact_constructions_kernel K; +typedef K::Point_3 Point_3; + +typedef CGAL::Triangulation_data_structure_3< + CGAL::Triangulation_vertex_base_3, + CGAL::Triangulation_cell_base_3, + CGAL::Parallel_tag> Tds; +typedef CGAL::Delaunay_triangulation_3 PDT; + +// global variables used by bench_dt3 +int argc; +char** argv; + + + +void bench_dt3(benchmark::State& state) { + CGAL::get_default_random() = CGAL::Random(0); + + std::vector points; + Point_3 p; + + std::ifstream in(argv[1]); + while(in >> p) + points.push_back(p); + + for(auto _ : state) { + CGAL::Bbox_3 bb = CGAL::bounding_box(points.begin(), points.end()).bbox(); + PDT::Lock_data_structure locking_ds(bb, 50); + + PDT pdt(points.begin(), points.end(), &locking_ds); + } + return; +} +BENCHMARK(bench_dt3)->Unit(benchmark::kMillisecond);; + + +int main(int argc, char* argv[]) +{ + benchmark::Initialize(&argc, argv); + ::argc = argc; + ::argv = argv; + benchmark::RunSpecifiedBenchmarks(); +} From 3ade506eba82380bef1d07efeac1c550324f843b Mon Sep 17 00:00:00 2001 From: Laurent Rineau Date: Tue, 3 Dec 2019 14:33:40 +0100 Subject: [PATCH 327/363] Create approximate_size() in Concurrent_compact_container Instead of having an atomic integer for the size of the compact container, now all free lists have an atomic integer for their size, but it is only updated when the size is increased by 10%. --- Mesh_3/include/CGAL/Mesh_3/Mesher_3.h | 31 +++++-- .../CGAL/Concurrent_compact_container.h | 90 ++++++++++++++++++- .../benchmark/Triangulation_3/CMakeLists.txt | 5 ++ 3 files changed, 115 insertions(+), 11 deletions(-) diff --git a/Mesh_3/include/CGAL/Mesh_3/Mesher_3.h b/Mesh_3/include/CGAL/Mesh_3/Mesher_3.h index 327dc902dc3..8d58e71f444 100644 --- a/Mesh_3/include/CGAL/Mesh_3/Mesher_3.h +++ b/Mesh_3/include/CGAL/Mesh_3/Mesher_3.h @@ -296,6 +296,24 @@ private: CGAL::cpp11::atomic* const stop_ptr; #endif +#ifdef CGAL_LINKED_WITH_TBB + std::size_t approximate_number_of_vertices(CGAL::Parallel_tag) const { +# if CGAL_CONCURRENT_COMPACT_CONTAINER_APPROXIMATE_SIZE + return r_c3t3_.triangulation().tds().vertices().approximate_size(); +# else // not CGAL_CONCURRENT_COMPACT_CONTAINER_APPROXIMATE_SIZE + CGAL_error_msg( + "If you want to use the Mesh_3 feature \"maximal_number_of_vertices\"\n" + "with CGAL::Parallel_tag then you need to recompile the code with the\n" + "preprocessor macro CGAL_CONCURRENT_COMPACT_CONTAINER_APPROXIMATE_SIZE\n" + "set to 1. That will induce a performance loss of 3%.\n"); +# endif // not CGAL_CONCURRENT_COMPACT_CONTAINER_APPROXIMATE_SIZE + } +#endif // CGAL_LINKED_WITH_TBB + + std::size_t approximate_number_of_vertices(CGAL::Sequential_tag) const { + return r_c3t3_.triangulation().number_of_vertices(); + } + bool forced_stop() const { #ifndef CGAL_NO_ATOMIC if(stop_ptr != 0 && @@ -306,8 +324,7 @@ private: } #endif // not defined CGAL_NO_ATOMIC if(maximal_number_of_vertices_ != 0 && - r_c3t3_.triangulation().number_of_vertices() >= - maximal_number_of_vertices_) + approximate_number_of_vertices(Concurrency_tag()) >= maximal_number_of_vertices_) { if(error_code_ != 0) { *error_code_ = CGAL_MESH_3_MAXIMAL_NUMBER_OF_VERTICES_REACHED; @@ -510,15 +527,15 @@ refine_mesh(std::string dump_after_refine_surface_prefix) % r_tr.number_of_vertices() % nbsteps % cells_mesher_.debug_info() % (nbsteps / timer.time()); - if(! forced_stop() && - refinement_stage == REFINE_FACETS && + if(refinement_stage == REFINE_FACETS && + ! forced_stop() && facets_mesher_.is_algorithm_done()) { facets_mesher_.scan_edges(); refinement_stage = REFINE_FACETS_AND_EDGES; } - if(! forced_stop() && - refinement_stage == REFINE_FACETS_AND_EDGES && + if(refinement_stage == REFINE_FACETS_AND_EDGES && + ! forced_stop() && facets_mesher_.is_algorithm_done()) { facets_mesher_.scan_vertices(); @@ -801,7 +818,7 @@ status() const if(boost::is_convertible::value) { const WorksharingDataStructureType* ws_ds = this->get_worksharing_data_structure(); - return Mesher_status(r_c3t3_.triangulation().number_of_vertices(), + return Mesher_status(approximate_number_of_vertices(Concurrency_tag()), 0, ws_ds->approximate_number_of_enqueued_element()); } diff --git a/STL_Extension/include/CGAL/Concurrent_compact_container.h b/STL_Extension/include/CGAL/Concurrent_compact_container.h index d4fc001e828..8a0ae67089c 100644 --- a/STL_Extension/include/CGAL/Concurrent_compact_container.h +++ b/STL_Extension/include/CGAL/Concurrent_compact_container.h @@ -124,15 +124,37 @@ namespace CCC_internal { template< typename pointer, typename size_type, typename CCC > class Free_list { public: - Free_list() : m_head(NULL), m_size(0) {} + Free_list() : m_head(NULL), m_size(0) { +#if CGAL_CONCURRENT_COMPACT_CONTAINER_APPROXIMATE_SIZE + // Note that the performance penalty with + // CGAL_CONCURRENT_COMPACT_CONTAINER_APPROXIMATE_SIZE=1 is + // measured to be 3%, in a parallel insertion of 100k random + // points, in Delaunay_triangulation_3. + refresh_approximate_size(); +#endif // CGAL_CONCURRENT_COMPACT_CONTAINER_APPROXIMATE_SIZE + } void init() { m_head = NULL; m_size = 0; } pointer head() const { return m_head; } void set_head(pointer p) { m_head = p; } size_type size() const { return m_size; } - void set_size(size_type s) { m_size = s; } - void inc_size() { ++m_size; } - void dec_size() { --m_size; } + void set_size(size_type s) { + m_size = s; + } + void inc_size() { + ++m_size; +#if CGAL_CONCURRENT_COMPACT_CONTAINER_APPROXIMATE_SIZE + if(m_size > (m_approximate_size * precision_of_approximate_size_plus_1)) + refresh_approximate_size(); +#endif // CGAL_CONCURRENT_COMPACT_CONTAINER_APPROXIMATE_SIZE + } + void dec_size() { + --m_size; +#if CGAL_CONCURRENT_COMPACT_CONTAINER_APPROXIMATE_SIZE + if((m_size * precision_of_approximate_size_plus_1) < m_approximate_size) + refresh_approximate_size(); +#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) @@ -158,9 +180,26 @@ public: other.init(); // clear other } +#if CGAL_CONCURRENT_COMPACT_CONTAINER_APPROXIMATE_SIZE + size_type approximate_size() const { + return m_atomic_approximate_size.load(std::memory_order_relaxed); + } +#endif // CGAL_CONCURRENT_COMPACT_CONTAINER_APPROXIMATE_SIZE + protected: pointer m_head; // the free list head pointer size_type m_size; // the free list size + +#if CGAL_CONCURRENT_COMPACT_CONTAINER_APPROXIMATE_SIZE + // `m_size` plus or minus `precision_of_approximate_size - 1` + static constexpr double precision_of_approximate_size_plus_1 = 1.10; + size_type m_approximate_size; + std::atomic m_atomic_approximate_size; + void refresh_approximate_size() { + m_approximate_size = m_size; + m_atomic_approximate_size.store(m_size, std::memory_order_relaxed); + } +#endif // CGAL_CONCURRENT_COMPACT_CONTAINER_APPROXIMATE_SIZE }; // Class Concurrent_compact_container @@ -257,7 +296,16 @@ public: void swap(Self &c) { 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; + } +#else // not CGAL_CONCURRENT_COMPACT_CONTAINER_APPROXIMATE_SIZE std::swap(m_capacity, c.m_capacity); +#endif // not CGAL_CONCURRENT_COMPACT_CONTAINER_APPROXIMATE_SIZE + std::swap(m_block_size, c.m_block_size); std::swap(m_first_item, c.m_first_item); std::swap(m_last_item, c.m_last_item); @@ -471,7 +519,11 @@ public: // Do not call this function while others are inserting/erasing elements size_type size() const { +#if CGAL_CONCURRENT_COMPACT_CONTAINER_APPROXIMATE_SIZE + size_type size = m_capacity.load(std::memory_order_relaxed); +#else // not CGAL_CONCURRENT_COMPACT_CONTAINER_APPROXIMATE_SIZE size_type size = m_capacity; +#endif // not CGAL_CONCURRENT_COMPACT_CONTAINER_APPROXIMATE_SIZE for( typename Free_lists::iterator it_free_list = m_free_lists.begin() ; it_free_list != m_free_lists.end() ; ++it_free_list ) @@ -481,6 +533,20 @@ public: return size; } +#if CGAL_CONCURRENT_COMPACT_CONTAINER_APPROXIMATE_SIZE + size_type approximate_size() const + { + size_type size = m_capacity.load(std::memory_order_relaxed); + for( typename Free_lists::iterator it_free_list = m_free_lists.begin() ; + it_free_list != m_free_lists.end() ; + ++it_free_list ) + { + size -= it_free_list->approximate_size(); + } + return size; + } +#endif // CGAL_CONCURRENT_COMPACT_CONTAINER_APPROXIMATE_SIZE + size_type max_size() const { #ifdef CGAL_CXX11 @@ -492,7 +558,11 @@ public: size_type capacity() const { +#if CGAL_CONCURRENT_COMPACT_CONTAINER_APPROXIMATE_SIZE + return m_capacity.load(std::memory_order_relaxed); +#else // not CGAL_CONCURRENT_COMPACT_CONTAINER_APPROXIMATE_SIZE return m_capacity; +#endif // not CGAL_CONCURRENT_COMPACT_CONTAINER_APPROXIMATE_SIZE } // void resize(size_type sz, T c = T()); // TODO makes sense ??? @@ -684,7 +754,11 @@ private: } allocator_type m_alloc; +#if CGAL_CONCURRENT_COMPACT_CONTAINER_APPROXIMATE_SIZE + std::atomic m_capacity; +#else // not CGAL_CONCURRENT_COMPACT_CONTAINER_APPROXIMATE_SIZE size_type m_capacity; +#endif // not CGAL_CONCURRENT_COMPACT_CONTAINER_APPROXIMATE_SIZE size_type m_block_size; Free_lists m_free_lists; pointer m_first_item; @@ -734,7 +808,11 @@ void Concurrent_compact_container::merge(Self &d) } m_all_items.insert(m_all_items.end(), d.m_all_items.begin(), d.m_all_items.end()); // Add the capacities. +#if CGAL_CONCURRENT_COMPACT_CONTAINER_APPROXIMATE_SIZE + m_capacity.fetch_add(d.m_capacity, std::memory_order_relaxed); +#else // not CGAL_CONCURRENT_COMPACT_CONTAINER_APPROXIMATE_SIZE m_capacity += d.m_capacity; +#endif // not CGAL_CONCURRENT_COMPACT_CONTAINER_APPROXIMATE_SIZE // It seems reasonnable to take the max of the block sizes. m_block_size = (std::max)(m_block_size, d.m_block_size); // Clear d. @@ -772,7 +850,11 @@ void Concurrent_compact_container:: old_block_size = m_block_size; new_block = m_alloc.allocate(old_block_size + 2); m_all_items.push_back(std::make_pair(new_block, old_block_size + 2)); +#if CGAL_CONCURRENT_COMPACT_CONTAINER_APPROXIMATE_SIZE + m_capacity.fetch_add(old_block_size, std::memory_order_relaxed); +#else // not CGAL_CONCURRENT_COMPACT_CONTAINER_APPROXIMATE_SIZE m_capacity += old_block_size; +#endif // not CGAL_CONCURRENT_COMPACT_CONTAINER_APPROXIMATE_SIZE // We insert this new block at the end. if (m_last_item == NULL) // First time diff --git a/Triangulation_3/benchmark/Triangulation_3/CMakeLists.txt b/Triangulation_3/benchmark/Triangulation_3/CMakeLists.txt index 0291f205496..c6892abd08e 100644 --- a/Triangulation_3/benchmark/Triangulation_3/CMakeLists.txt +++ b/Triangulation_3/benchmark/Triangulation_3/CMakeLists.txt @@ -54,4 +54,9 @@ if(TARGET benchmark::benchmark) 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) + + 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) endif() From e9f1cb405f774cbfea0f16fed2f32b560fdbf92f Mon Sep 17 00:00:00 2001 From: Laurent Rineau Date: Wed, 4 Dec 2019 15:42:54 +0100 Subject: [PATCH 328/363] Improvement for set_size --- STL_Extension/include/CGAL/Concurrent_compact_container.h | 3 +++ 1 file changed, 3 insertions(+) diff --git a/STL_Extension/include/CGAL/Concurrent_compact_container.h b/STL_Extension/include/CGAL/Concurrent_compact_container.h index 756011ea104..5fad68c1719 100644 --- a/STL_Extension/include/CGAL/Concurrent_compact_container.h +++ b/STL_Extension/include/CGAL/Concurrent_compact_container.h @@ -131,6 +131,9 @@ public: size_type size() const { return m_size; } void set_size(size_type s) { m_size = s; +#if CGAL_CONCURRENT_COMPACT_CONTAINER_APPROXIMATE_SIZE + refresh_approximate_size(); +#endif } void inc_size() { ++m_size; From 7aa90a326694d786c3e436759235688162f8f8fd Mon Sep 17 00:00:00 2001 From: Laurent Rineau Date: Thu, 5 Dec 2019 11:10:12 +0100 Subject: [PATCH 329/363] Fix CHANGES.md --- Installation/CHANGES.md | 16 ++++------------ 1 file changed, 4 insertions(+), 12 deletions(-) diff --git a/Installation/CHANGES.md b/Installation/CHANGES.md index 021d7246e51..04a134fe135 100644 --- a/Installation/CHANGES.md +++ b/Installation/CHANGES.md @@ -1,29 +1,20 @@ Release History =============== + Release 5.1 ----------- -Release date: March 2020 + +Release date: June 2020 ### 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. - -Release 5.1 ------------ - -Release date: June 2020 - ### Polygon Mesh Processing - The function `CGAL::Polygon_mesh_processing::stitch_borders()` now returns the number of halfedge pairs that were stitched. -Release 5.1 ------------ - -Release date: June 2020 - ### 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` @@ -36,6 +27,7 @@ Release date: June 2020 does not allow any intersection, except for the configuration of two constraints having a single common endpoints, for convience. + [Release 5.0](https://github.com/CGAL/cgal/releases/tag/releases%2FCGAL-5.0) ----------- From 9149d264927c98a5a25091d8401a8532bf7c4255 Mon Sep 17 00:00:00 2001 From: Laurent Rineau Date: Mon, 9 Dec 2019 15:07:10 +0100 Subject: [PATCH 330/363] Fix check headers Before this commit, headers with their own documentation pages, but not referenced in other documentation pages, were not considered as documented. This is a fix. --- AABB_tree/package_info/AABB_tree/dependencies | 2 +- Convex_hull_d/package_info/Convex_hull_d/dependencies | 2 +- Installation/CMakeLists.txt | 2 +- Nef_S2/package_info/Nef_S2/dependencies | 2 +- .../Optimal_transportation_reconstruction_2/dependencies | 2 +- .../internal/Hole_filling/Triangulate_hole_polyline.h | 1 + Polyhedron/package_info/Polyhedron/dependencies | 2 +- .../package_info/Surface_mesh_parameterization/dependencies | 2 +- .../package_info/Surface_mesh_segmentation/dependencies | 2 +- .../package_info/Surface_mesh_shortest_path/dependencies | 2 +- Visibility_2/package_info/Visibility_2/dependencies | 2 +- 11 files changed, 11 insertions(+), 10 deletions(-) diff --git a/AABB_tree/package_info/AABB_tree/dependencies b/AABB_tree/package_info/AABB_tree/dependencies index c72f4088b6a..2162029e468 100644 --- a/AABB_tree/package_info/AABB_tree/dependencies +++ b/AABB_tree/package_info/AABB_tree/dependencies @@ -4,6 +4,7 @@ BGL Cartesian_kernel Circulator Distance_2 +Distance_3 Installation Intersections_2 Intersections_3 @@ -16,4 +17,3 @@ Property_map STL_Extension Spatial_searching Stream_support -Distance_3 diff --git a/Convex_hull_d/package_info/Convex_hull_d/dependencies b/Convex_hull_d/package_info/Convex_hull_d/dependencies index 81659211144..1535e6386bf 100644 --- a/Convex_hull_d/package_info/Convex_hull_d/dependencies +++ b/Convex_hull_d/package_info/Convex_hull_d/dependencies @@ -2,6 +2,7 @@ Algebraic_foundations Circulator Convex_hull_d Distance_2 +Distance_3 Hash_map Installation Intersections_2 @@ -14,4 +15,3 @@ Number_types Profiling_tools STL_Extension Stream_support -Distance_3 diff --git a/Installation/CMakeLists.txt b/Installation/CMakeLists.txt index 0bf3e4b575d..d02abdc1b46 100644 --- a/Installation/CMakeLists.txt +++ b/Installation/CMakeLists.txt @@ -1194,7 +1194,7 @@ You must disable CGAL_ENABLE_CHECK_HEADERS.") file(GLOB html_files RELATIVE "${DOC_DIR}/doc_output/" "${DOC_DIR}/doc_output/*/*.html") file(GLOB example_files RELATIVE "${CMAKE_SOURCE_DIR}/" "${CMAKE_SOURCE_DIR}/*/examples/*/*.cpp") find_program(AWK awk) - set(awk_arguments [=[{ match($0, /# *include *(<|[<"])(CGAL\/[^>&"]*)([>"]|>)/,arr); if(arr[2]!="") print arr[2] }]=]) + set(awk_arguments [=[{ match($0, /# *include *(<|[<"])(CGAL\/[^>&"]*)([>"]|>)| (CGAL\/[^>&"]*\.h)/,arr); if(arr[2]!="") print arr[2]; if(arr[4]!="") print arr[4] }]=]) message("listing headers from html files") foreach(f ${html_files}) execute_process(COMMAND "${AWK}" "${awk_arguments}" "${DOC_DIR}/doc_output/${f}" diff --git a/Nef_S2/package_info/Nef_S2/dependencies b/Nef_S2/package_info/Nef_S2/dependencies index 75135011028..fcc8ed45ff2 100644 --- a/Nef_S2/package_info/Nef_S2/dependencies +++ b/Nef_S2/package_info/Nef_S2/dependencies @@ -1,6 +1,7 @@ Algebraic_foundations Circulator Distance_2 +Distance_3 Hash_map Installation Intersections_2 @@ -16,4 +17,3 @@ Profiling_tools STL_Extension Stream_support Union_find -Distance_3 diff --git a/Optimal_transportation_reconstruction_2/package_info/Optimal_transportation_reconstruction_2/dependencies b/Optimal_transportation_reconstruction_2/package_info/Optimal_transportation_reconstruction_2/dependencies index 9b809650984..7fb921a03fa 100644 --- a/Optimal_transportation_reconstruction_2/package_info/Optimal_transportation_reconstruction_2/dependencies +++ b/Optimal_transportation_reconstruction_2/package_info/Optimal_transportation_reconstruction_2/dependencies @@ -1,6 +1,7 @@ Algebraic_foundations Circulator Distance_2 +Distance_3 Filtered_kernel Hash_map Installation @@ -20,4 +21,3 @@ Spatial_sorting Stream_support TDS_2 Triangulation_2 -Distance_3 diff --git a/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/internal/Hole_filling/Triangulate_hole_polyline.h b/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/internal/Hole_filling/Triangulate_hole_polyline.h index 3cc8910c252..b4576618ed1 100644 --- a/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/internal/Hole_filling/Triangulate_hole_polyline.h +++ b/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/internal/Hole_filling/Triangulate_hole_polyline.h @@ -43,6 +43,7 @@ #include #include +#include namespace CGAL { namespace internal { diff --git a/Polyhedron/package_info/Polyhedron/dependencies b/Polyhedron/package_info/Polyhedron/dependencies index b810ef1e411..379a6bb6921 100644 --- a/Polyhedron/package_info/Polyhedron/dependencies +++ b/Polyhedron/package_info/Polyhedron/dependencies @@ -2,6 +2,7 @@ Algebraic_foundations BGL Circulator Distance_2 +Distance_3 GraphicsView HalfedgeDS Hash_map @@ -19,4 +20,3 @@ Profiling_tools Property_map STL_Extension Stream_support -Distance_3 diff --git a/Surface_mesh_parameterization/package_info/Surface_mesh_parameterization/dependencies b/Surface_mesh_parameterization/package_info/Surface_mesh_parameterization/dependencies index 9dbfd435104..d4e2305f8d9 100644 --- a/Surface_mesh_parameterization/package_info/Surface_mesh_parameterization/dependencies +++ b/Surface_mesh_parameterization/package_info/Surface_mesh_parameterization/dependencies @@ -3,6 +3,7 @@ BGL Box_intersection_d Circulator Distance_2 +Distance_3 Filtered_kernel Hash_map Installation @@ -24,4 +25,3 @@ Stream_support Surface_mesh_parameterization TDS_2 Triangulation_2 -Distance_3 diff --git a/Surface_mesh_segmentation/package_info/Surface_mesh_segmentation/dependencies b/Surface_mesh_segmentation/package_info/Surface_mesh_segmentation/dependencies index 233d2d2991f..a66a775a09d 100644 --- a/Surface_mesh_segmentation/package_info/Surface_mesh_segmentation/dependencies +++ b/Surface_mesh_segmentation/package_info/Surface_mesh_segmentation/dependencies @@ -4,6 +4,7 @@ BGL Cartesian_kernel Circulator Distance_2 +Distance_3 Installation Intersections_2 Intersections_3 @@ -19,4 +20,3 @@ STL_Extension Spatial_searching Stream_support Surface_mesh_segmentation -Distance_3 diff --git a/Surface_mesh_shortest_path/package_info/Surface_mesh_shortest_path/dependencies b/Surface_mesh_shortest_path/package_info/Surface_mesh_shortest_path/dependencies index 1124ba800da..5336f29d3b6 100644 --- a/Surface_mesh_shortest_path/package_info/Surface_mesh_shortest_path/dependencies +++ b/Surface_mesh_shortest_path/package_info/Surface_mesh_shortest_path/dependencies @@ -4,6 +4,7 @@ BGL Cartesian_kernel Circulator Distance_2 +Distance_3 Installation Intersections_2 Intersections_3 @@ -17,4 +18,3 @@ STL_Extension Spatial_searching Stream_support Surface_mesh_shortest_path -Distance_3 diff --git a/Visibility_2/package_info/Visibility_2/dependencies b/Visibility_2/package_info/Visibility_2/dependencies index df17db35a32..bdaf92f883b 100644 --- a/Visibility_2/package_info/Visibility_2/dependencies +++ b/Visibility_2/package_info/Visibility_2/dependencies @@ -2,6 +2,7 @@ Algebraic_foundations Arrangement_on_surface_2 Circulator Distance_2 +Distance_3 Filtered_kernel HalfedgeDS Hash_map @@ -23,4 +24,3 @@ Surface_sweep_2 TDS_2 Triangulation_2 Visibility_2 -Distance_3 From d4b5bad692e9d8d3601ee650b70ee28c96403855 Mon Sep 17 00:00:00 2001 From: Laurent Rineau Date: Mon, 9 Dec 2019 15:45:29 +0100 Subject: [PATCH 331/363] Fix a compilation error --- Polygon_mesh_processing/include/CGAL/polygon_mesh_processing.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Polygon_mesh_processing/include/CGAL/polygon_mesh_processing.h b/Polygon_mesh_processing/include/CGAL/polygon_mesh_processing.h index fdb012d0a2a..82f712fdc16 100644 --- a/Polygon_mesh_processing/include/CGAL/polygon_mesh_processing.h +++ b/Polygon_mesh_processing/include/CGAL/polygon_mesh_processing.h @@ -45,7 +45,7 @@ #include #include #include -#include +#include // the named parameter header being not documented the doc is put here for now #ifdef DOXYGEN_RUNNING From 247e6f9aea06e2c8d5972b46df98351e6c7da309 Mon Sep 17 00:00:00 2001 From: Laurent Rineau Date: Mon, 9 Dec 2019 16:07:55 +0100 Subject: [PATCH 332/363] Fix the release number --- Maintenance/release_building/BUGFIX_NUMBER | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Maintenance/release_building/BUGFIX_NUMBER b/Maintenance/release_building/BUGFIX_NUMBER index d00491fd7e5..573541ac970 100644 --- a/Maintenance/release_building/BUGFIX_NUMBER +++ b/Maintenance/release_building/BUGFIX_NUMBER @@ -1 +1 @@ -1 +0 From 6462016ce3392b7a73a28225e0abe38df787e74d Mon Sep 17 00:00:00 2001 From: Andreas Fabri Date: Mon, 14 Oct 2019 19:30:59 +0200 Subject: [PATCH 333/363] Use an unordered map to find neighbor cells --- .../include/CGAL/Small_unordered_map.h | 156 ++++++++++++++++++ .../include/CGAL/Triangulation_3.h | 80 ++++++++- 2 files changed, 227 insertions(+), 9 deletions(-) create mode 100644 STL_Extension/include/CGAL/Small_unordered_map.h diff --git a/STL_Extension/include/CGAL/Small_unordered_map.h b/STL_Extension/include/CGAL/Small_unordered_map.h new file mode 100644 index 00000000000..5f542378c7b --- /dev/null +++ b/STL_Extension/include/CGAL/Small_unordered_map.h @@ -0,0 +1,156 @@ +// 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 Lesser 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: LGPL-3.0+ +// +// Author(s) : Andreas Fabri + +#ifndef CGAL_SMALL_UNORDERED_MAP_H +#define CGAL_SMALL_UNORDERED_MAP_H + +#include +#include + +//#define CGAL_SMALL_UNORDERED_MAP_STATS +namespace CGAL { + +template +class Small_unordered_map{ +#ifdef CGAL_SMALL_UNORDERED_MAP_STATS + std::array collisions = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; +#endif + static const unsigned int M = N<<3; + int head = -2; + std::array occupied; + std::array, M> data; + const H hash = {}; + + +public: + Small_unordered_map() + { + occupied.fill(-1); + } + +#ifdef CGAL_SMALL_UNORDERED_MAP_STATS + ~Small_unordered_map() + { + for(int i = 0; i < 10; i++){ + std::cout << i << " " << collisions[i] << std::endl; + } + } +#endif + + /// Set only once for a key and not more than N + void set(const K& k, const T& t) + { + unsigned int h = hash(k)%M; + unsigned i = h; +#ifdef CGAL_SMALL_UNORDERED_MAP_STATS + int collision = 0; +#endif + do { + if(occupied[i]== -1){ + data[i].first = k; + data[i].second = t; + occupied[i] = head; + head = i; +#ifdef CGAL_SMALL_UNORDERED_MAP_STATS + if(collision>9){ + std::cerr << collision << " collisions" << std::endl; + } + ++collisions[collision]; +#endif + return; + } + i = (i+1)%M; +#ifdef CGAL_SMALL_UNORDERED_MAP_STATS + ++collision; +#endif + }while(i != h); + std::cerr << "In set: continue? " << std::flush; + char c; std::cin >> c; + } + + + const T& get(const K& k) const + { + unsigned int h = hash(k)%M; + int i = h; + do{ + if(data[i].first == k){ + return data[i].second; + } + i = (i+1)%M; + }while(i != h); + std::cerr << "In get: continue? " << std::flush; + char c; std::cin >> c; + } + + void clear() + { + head = -2; + occupied.fill(-1); + } + + struct iterator { + const Small_unordered_map& map; + int pos; + + iterator(const Small_unordered_map& map) + : map(map),pos(-2) + {} + + iterator(const Small_unordered_map& map, int pos) + : map(map), pos(pos) + {} + + bool operator==(const iterator& other) const + { + return pos == other.pos; + } + + bool operator!=(const iterator& other) const + { + return pos != other.pos; + } + iterator operator++() + { + pos = map.occupied[pos]; + return *this; + } + + const std::pair& operator*()const + { + return map.data[pos]; + } + }; + + iterator begin() const + { + return iterator(*this,head); + } + + iterator end() const + { + return iterator(*this); + } + + friend struct iterator; +}; + +} // namespace CGAL +#endif // CGAL_SMALL_UNORDERED_MAP_H diff --git a/Triangulation_3/include/CGAL/Triangulation_3.h b/Triangulation_3/include/CGAL/Triangulation_3.h index 2e3771adad4..797146fbddc 100644 --- a/Triangulation_3/include/CGAL/Triangulation_3.h +++ b/Triangulation_3/include/CGAL/Triangulation_3.h @@ -37,9 +37,13 @@ #include #include #include +#include #include #include +// #include +// #include + #include #include #include @@ -56,6 +60,7 @@ #include #include #include +#include #include #include @@ -3586,6 +3591,9 @@ insert(const Point& p, Locate_type lt, Cell_handle c, int li, int lj) } } +#define AF_NEW + + template < class GT, class Tds, class Lds > template < class Conflict_tester, class Hidden_points_visitor > typename Triangulation_3::Vertex_handle @@ -3596,6 +3604,7 @@ insert_in_conflict(const Point& p, Hidden_points_visitor& hider, bool *could_lock_zone) { + if(could_lock_zone) *could_lock_zone = true; @@ -3621,11 +3630,12 @@ insert_in_conflict(const Point& p, cells.reserve(32); Facet facet; + std::vector facets; + facets.reserve(32); + // Parallel if(could_lock_zone) { - std::vector facets; - facets.reserve(32); find_conflicts(c, tester, @@ -3647,8 +3657,6 @@ insert_in_conflict(const Point& p, } return Vertex_handle(); } - - facet = facets.back(); } // Sequential else @@ -3657,22 +3665,76 @@ insert_in_conflict(const Point& p, find_conflicts(c, tester, make_triple( - Oneset_iterator(facet), + std::back_inserter(facets), std::back_inserter(cells), Emptyset_iterator())); } + facet = facets.back(); + // Remember the points that are hidden by the conflicting cells, // as they will be deleted during the insertion. hider.process_cells_in_conflict(cells.begin(), cells.end()); + Vertex_handle nv; + // AF: the new code - Vertex_handle v = _insert_in_hole(p, + if( facets.size() < 128){ + // LESS64++; + typedef std::pair Halfedge; + typedef Small_unordered_map, 128 > Halfedge_facet_map; + // typedef absl::flat_hash_map, Facet// , boost::hash >> E2F; + static Halfedge_facet_map h2f; + nv = tds().create_vertex(); + nv->set_point(p); + for(Facet f : facets){ + + f = mirror_facet(f); + f.first->tds_data().clear(); // was on boundary + Vertex_handle u = f.first->vertex(vertex_triple_index(f.second, 0)); + Vertex_handle v = f.first->vertex(vertex_triple_index(f.second, 1)); + Vertex_handle w = f.first->vertex(vertex_triple_index(f.second, 2)); + u->set_cell(f.first); + v->set_cell(f.first); + w->set_cell(f.first); + Cell_handle nc = tds().create_cell(v, u, w, nv); + nv->set_cell(nc); + nc->set_neighbor(3, f.first); + f.first->set_neighbor(f.second, nc); + + h2f.set(std::make_pair(u,v), Facet(nc,nc->index(w))); + h2f.set(std::make_pair(v,w), Facet(nc,nc->index(u))); + h2f.set(std::make_pair(w,u), Facet(nc,nc->index(v))); + } + + int E = 3* facets.size(); + int ei = 0; + for(auto it = h2f.begin(); it != h2f.end(); ++it){ + if(ei>E){ + std::cout << "Stop"<< std::flush; + char c; std::cin >> c; + } + ++ei; + const std::pair& ef = *it; + if(ef.first.first < ef.first.second){ + Facet f = ef.second; + Facet n = h2f.get(std::make_pair(ef.first.second, ef.first.first)); + f.first->set_neighbor(f.second, n.first); + n.first->set_neighbor(n.second, f.first); + } + } + for(Cell_handle c : cells){ + c->tds_data().clear(); // was in conflict + } + tds().delete_cells(cells.begin(), cells.end()); + h2f.clear(); + }else{ + Vertex_handle nv = _insert_in_hole(p, cells.begin(), cells.end(), facet.first, facet.second); - + } // Store the hidden points in their new cells. - hider.reinsert_vertices(v); - return v; + hider.reinsert_vertices(nv); + return nv; } case 2: { From a3fc6790ca1bc0f70e877ddeee9b924017829a78 Mon Sep 17 00:00:00 2001 From: Andreas Fabri Date: Wed, 16 Oct 2019 12:38:37 +0200 Subject: [PATCH 334/363] Use a boost::small_vector instead of a std::deque in a stack --- Triangulation_3/include/CGAL/Triangulation_3.h | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/Triangulation_3/include/CGAL/Triangulation_3.h b/Triangulation_3/include/CGAL/Triangulation_3.h index 797146fbddc..ffb87b34fec 100644 --- a/Triangulation_3/include/CGAL/Triangulation_3.h +++ b/Triangulation_3/include/CGAL/Triangulation_3.h @@ -72,6 +72,7 @@ #include #include #include +#include #ifndef CGAL_NO_STRUCTURAL_FILTERING #include @@ -1251,7 +1252,11 @@ protected: CGAL_triangulation_precondition(tester(d)); // To store the boundary cells, in case we need to rollback - std::stack cell_stack; + + typedef boost::container::small_vector SV; + SV sv; + std::stack cell_stack(sv); + cell_stack.push(d); d->tds_data().mark_in_conflict(); From 3fd81fc4f2596c0272c077bba77915eb394d4886 Mon Sep 17 00:00:00 2001 From: Andreas Fabri Date: Wed, 16 Oct 2019 22:36:51 +0200 Subject: [PATCH 335/363] Split freelist and occupied (todo: save memory) --- .../include/CGAL/Small_unordered_map.h | 18 +++++++++++++----- 1 file changed, 13 insertions(+), 5 deletions(-) diff --git a/STL_Extension/include/CGAL/Small_unordered_map.h b/STL_Extension/include/CGAL/Small_unordered_map.h index 5f542378c7b..c1871fb4185 100644 --- a/STL_Extension/include/CGAL/Small_unordered_map.h +++ b/STL_Extension/include/CGAL/Small_unordered_map.h @@ -34,7 +34,8 @@ class Small_unordered_map{ #endif static const unsigned int M = N<<3; int head = -2; - std::array occupied; + mutable std::array occupied; + std::array unfreelist; std::array, M> data; const H hash = {}; @@ -64,9 +65,10 @@ public: #endif do { if(occupied[i]== -1){ + occupied[i] = 1; data[i].first = k; data[i].second = t; - occupied[i] = head; + unfreelist[i] = head; head = i; #ifdef CGAL_SMALL_UNORDERED_MAP_STATS if(collision>9){ @@ -91,7 +93,8 @@ public: unsigned int h = hash(k)%M; int i = h; do{ - if(data[i].first == k){ + if((occupied[i] == 1) && (data[i].first == k)){ + occupied[i] = -1; return data[i].second; } i = (i+1)%M; @@ -103,7 +106,7 @@ public: void clear() { head = -2; - occupied.fill(-1); + // occupied.fill(-1); } struct iterator { @@ -129,7 +132,7 @@ public: } iterator operator++() { - pos = map.occupied[pos]; + pos = map.unfreelist[pos]; return *this; } @@ -149,6 +152,11 @@ public: return iterator(*this); } + void clear(const iterator it) + { + occupied[it.pos] = -1; + } + friend struct iterator; }; From f2eea9cf78dd1d993cc9d6d63c261595b62a3078 Mon Sep 17 00:00:00 2001 From: Andreas Fabri Date: Wed, 16 Oct 2019 22:57:53 +0200 Subject: [PATCH 336/363] Call clear() --- Triangulation_3/include/CGAL/Triangulation_3.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Triangulation_3/include/CGAL/Triangulation_3.h b/Triangulation_3/include/CGAL/Triangulation_3.h index ffb87b34fec..7c1ffadce1a 100644 --- a/Triangulation_3/include/CGAL/Triangulation_3.h +++ b/Triangulation_3/include/CGAL/Triangulation_3.h @@ -3666,7 +3666,6 @@ insert_in_conflict(const Point& p, // Sequential else { - cells.reserve(32); find_conflicts(c, tester, make_triple( @@ -3722,6 +3721,7 @@ insert_in_conflict(const Point& p, const std::pair& ef = *it; if(ef.first.first < ef.first.second){ Facet f = ef.second; + h2f.clear(it); Facet n = h2f.get(std::make_pair(ef.first.second, ef.first.first)); f.first->set_neighbor(f.second, n.first); n.first->set_neighbor(n.second, f.first); From a93dd816426033110a91a55c663e8b90cd5fb7aa Mon Sep 17 00:00:00 2001 From: Laurent Rineau Date: Thu, 17 Oct 2019 16:26:57 +0200 Subject: [PATCH 337/363] Cleanup --- STL_Extension/include/CGAL/Small_unordered_map.h | 6 ++---- Triangulation_3/include/CGAL/Triangulation_3.h | 7 ------- 2 files changed, 2 insertions(+), 11 deletions(-) diff --git a/STL_Extension/include/CGAL/Small_unordered_map.h b/STL_Extension/include/CGAL/Small_unordered_map.h index c1871fb4185..a8a0e030861 100644 --- a/STL_Extension/include/CGAL/Small_unordered_map.h +++ b/STL_Extension/include/CGAL/Small_unordered_map.h @@ -83,8 +83,7 @@ public: ++collision; #endif }while(i != h); - std::cerr << "In set: continue? " << std::flush; - char c; std::cin >> c; + CGAL_error(); } @@ -99,8 +98,7 @@ public: } i = (i+1)%M; }while(i != h); - std::cerr << "In get: continue? " << std::flush; - char c; std::cin >> c; + CGAL_error(); } void clear() diff --git a/Triangulation_3/include/CGAL/Triangulation_3.h b/Triangulation_3/include/CGAL/Triangulation_3.h index 7c1ffadce1a..f0f3a577e57 100644 --- a/Triangulation_3/include/CGAL/Triangulation_3.h +++ b/Triangulation_3/include/CGAL/Triangulation_3.h @@ -3710,14 +3710,7 @@ insert_in_conflict(const Point& p, h2f.set(std::make_pair(w,u), Facet(nc,nc->index(v))); } - int E = 3* facets.size(); - int ei = 0; for(auto it = h2f.begin(); it != h2f.end(); ++it){ - if(ei>E){ - std::cout << "Stop"<< std::flush; - char c; std::cin >> c; - } - ++ei; const std::pair& ef = *it; if(ef.first.first < ef.first.second){ Facet f = ef.second; From a9abea6dc744dab3334a0274e87f88103226dca4 Mon Sep 17 00:00:00 2001 From: Laurent Rineau Date: Thu, 17 Oct 2019 16:35:10 +0200 Subject: [PATCH 338/363] Use local small-indices, 2% win. --- .../include/CGAL/Triangulation_3.h | 66 +++++++++++-------- 1 file changed, 39 insertions(+), 27 deletions(-) diff --git a/Triangulation_3/include/CGAL/Triangulation_3.h b/Triangulation_3/include/CGAL/Triangulation_3.h index f0f3a577e57..3d969b3dea9 100644 --- a/Triangulation_3/include/CGAL/Triangulation_3.h +++ b/Triangulation_3/include/CGAL/Triangulation_3.h @@ -3681,41 +3681,53 @@ insert_in_conflict(const Point& p, hider.process_cells_in_conflict(cells.begin(), cells.end()); Vertex_handle nv; // AF: the new code - - if( facets.size() < 128){ + constexpr int maximal_nb_of_facets = 128; + if( facets.size() < maximal_nb_of_facets){ // LESS64++; typedef std::pair Halfedge; - typedef Small_unordered_map, 128 > Halfedge_facet_map; - // typedef absl::flat_hash_map, Facet// , boost::hash >> E2F; - static Halfedge_facet_map h2f; - nv = tds().create_vertex(); - nv->set_point(p); - for(Facet f : facets){ + typedef std::pair Local_facet; + typedef Small_unordered_map, maximal_nb_of_facets> + Halfedge_facet_map; + // typedef + // absl::flat_hash_map, + // Facet// , boost::hash >> + // E2F; + static Halfedge_facet_map h2f; + nv = tds().create_vertex(); + nv->set_point(p); + std::array new_cells; + for (int local_facet_index = 0, end = facets.size(); + local_facet_index < end; ++local_facet_index) { + const Facet f = mirror_facet(facets[local_facet_index]); + f.first->tds_data().clear(); // was on boundary + const Vertex_handle u = f.first->vertex(vertex_triple_index(f.second, 0)); + const Vertex_handle v = f.first->vertex(vertex_triple_index(f.second, 1)); + const Vertex_handle w = f.first->vertex(vertex_triple_index(f.second, 2)); + u->set_cell(f.first); + v->set_cell(f.first); + w->set_cell(f.first); + const Cell_handle nc = tds().create_cell(v, u, w, nv); + new_cells[local_facet_index] = nc; + nv->set_cell(nc); + nc->set_neighbor(3, f.first); + f.first->set_neighbor(f.second, nc); - f = mirror_facet(f); - f.first->tds_data().clear(); // was on boundary - Vertex_handle u = f.first->vertex(vertex_triple_index(f.second, 0)); - Vertex_handle v = f.first->vertex(vertex_triple_index(f.second, 1)); - Vertex_handle w = f.first->vertex(vertex_triple_index(f.second, 2)); - u->set_cell(f.first); - v->set_cell(f.first); - w->set_cell(f.first); - Cell_handle nc = tds().create_cell(v, u, w, nv); - nv->set_cell(nc); - nc->set_neighbor(3, f.first); - f.first->set_neighbor(f.second, nc); - - h2f.set(std::make_pair(u,v), Facet(nc,nc->index(w))); - h2f.set(std::make_pair(v,w), Facet(nc,nc->index(u))); - h2f.set(std::make_pair(w,u), Facet(nc,nc->index(v))); + h2f.set({u, v}, {local_facet_index, + static_cast(nc->index(w))}); + h2f.set({v, w}, {local_facet_index, + static_cast(nc->index(u))}); + h2f.set({w, u}, {local_facet_index, + static_cast(nc->index(v))}); } for(auto it = h2f.begin(); it != h2f.end(); ++it){ - const std::pair& ef = *it; + const std::pair& ef = *it; if(ef.first.first < ef.first.second){ - Facet f = ef.second; + const Facet f = Facet{new_cells[ef.second.first], ef.second.second}; h2f.clear(it); - Facet n = h2f.get(std::make_pair(ef.first.second, ef.first.first)); + const auto p = h2f.get(std::make_pair(ef.first.second, ef.first.first)); + const Facet n = Facet{new_cells[p.first], p.second}; f.first->set_neighbor(f.second, n.first); n.first->set_neighbor(n.second, f.first); } From 8aa4fc547f8c805a402a25722fd4d68d78b073f8 Mon Sep 17 00:00:00 2001 From: Andreas Fabri Date: Sat, 19 Oct 2019 12:47:39 +0200 Subject: [PATCH 339/363] Fix counting collisions --- STL_Extension/include/CGAL/Small_unordered_map.h | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/STL_Extension/include/CGAL/Small_unordered_map.h b/STL_Extension/include/CGAL/Small_unordered_map.h index a8a0e030861..f5c49f35b06 100644 --- a/STL_Extension/include/CGAL/Small_unordered_map.h +++ b/STL_Extension/include/CGAL/Small_unordered_map.h @@ -73,8 +73,9 @@ public: #ifdef CGAL_SMALL_UNORDERED_MAP_STATS if(collision>9){ std::cerr << collision << " collisions" << std::endl; + }else{ + ++collisions[collision]; } - ++collisions[collision]; #endif return; } From 9303a3318ae2d560b1a3b9bfe34707d0caa63604 Mon Sep 17 00:00:00 2001 From: Andreas Fabri Date: Sat, 19 Oct 2019 13:42:53 +0200 Subject: [PATCH 340/363] Use small_vector for find_conflicts() --- 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 3d969b3dea9..8f98c038755 100644 --- a/Triangulation_3/include/CGAL/Triangulation_3.h +++ b/Triangulation_3/include/CGAL/Triangulation_3.h @@ -3631,12 +3631,10 @@ insert_in_conflict(const Point& p, // Ok, we really insert the point now. // First, find the conflict region. - std::vector cells; - cells.reserve(32); + boost::container::small_vector cells; Facet facet; - std::vector facets; - facets.reserve(32); + boost::container::small_vector facets; // Parallel if(could_lock_zone) From febb6079347db80c2b242c35fd558452ff66db1a Mon Sep 17 00:00:00 2001 From: Andreas Fabri Date: Mon, 21 Oct 2019 10:02:33 +0200 Subject: [PATCH 341/363] WIP: Hard coded appromimated hash function --- STL_Extension/include/CGAL/Small_unordered_map.h | 8 +++++++- STL_Extension/include/CGAL/Time_stamper.h | 3 ++- 2 files changed, 9 insertions(+), 2 deletions(-) diff --git a/STL_Extension/include/CGAL/Small_unordered_map.h b/STL_Extension/include/CGAL/Small_unordered_map.h index f5c49f35b06..437b990e2be 100644 --- a/STL_Extension/include/CGAL/Small_unordered_map.h +++ b/STL_Extension/include/CGAL/Small_unordered_map.h @@ -37,8 +37,14 @@ class Small_unordered_map{ mutable std::array occupied; std::array unfreelist; std::array, M> data; - const H hash = {}; + //const H h = {}; + int hash(const K& k)const + { + std::size_t hf = boost::hash()(k.first); + std::size_t hs = boost::hash()(k.second); + return (hf + 1) ^ (419 * (hs + 1)); + } public: Small_unordered_map() diff --git a/STL_Extension/include/CGAL/Time_stamper.h b/STL_Extension/include/CGAL/Time_stamper.h index 904c82b6c98..a9a7e90664a 100644 --- a/STL_Extension/include/CGAL/Time_stamper.h +++ b/STL_Extension/include/CGAL/Time_stamper.h @@ -127,7 +127,8 @@ public: } static std::size_t hash_value(const T* p) { - return reinterpret_cast(p)/sizeof(T); + + return reinterpret_cast(p) >> 5; // sizeof(T); } void reset() {} From 27a93fc25a269340492a1d8ee034609dd5ed31e2 Mon Sep 17 00:00:00 2001 From: Andreas Fabri Date: Mon, 28 Oct 2019 10:57:34 +0100 Subject: [PATCH 342/363] First cleanup --- .../include/CGAL/Small_unordered_map.h | 20 ++++++++++++++----- STL_Extension/include/CGAL/Time_stamper.h | 11 +++++++++- .../include/CGAL/Triangulation_3.h | 9 +-------- 3 files changed, 26 insertions(+), 14 deletions(-) diff --git a/STL_Extension/include/CGAL/Small_unordered_map.h b/STL_Extension/include/CGAL/Small_unordered_map.h index 437b990e2be..9b0bf1eb160 100644 --- a/STL_Extension/include/CGAL/Small_unordered_map.h +++ b/STL_Extension/include/CGAL/Small_unordered_map.h @@ -30,7 +30,7 @@ namespace CGAL { template class Small_unordered_map{ #ifdef CGAL_SMALL_UNORDERED_MAP_STATS - std::array collisions = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; + std::array collisions = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; #endif static const unsigned int M = N<<3; int head = -2; @@ -43,7 +43,11 @@ class Small_unordered_map{ { std::size_t hf = boost::hash()(k.first); std::size_t hs = boost::hash()(k.second); - return (hf + 1) ^ (419 * (hs + 1)); + /* + hs += 1; + hs += (hs << 1) + (hs << 5) + (hs << 7) + (hs << 8); + */ + return (hf + 1) ^ (419 * (hs + 1)); } public: @@ -55,9 +59,15 @@ public: #ifdef CGAL_SMALL_UNORDERED_MAP_STATS ~Small_unordered_map() { - for(int i = 0; i < 10; i++){ - std::cout << i << " " << collisions[i] << std::endl; + int total = 0; + std::cout << "0 " << collisions[0] << std::endl; + for(int i = 1; i < 20; i++){ + total += collisions[i]; + if(collisions[i] != 0){ + std::cout << i << " " << collisions[i] << std::endl; + } } + std::cout << "Total: " << total << " " << 100 * (double(total) / double(total + collisions[0])) << "%" << std::endl; } #endif @@ -77,7 +87,7 @@ public: unfreelist[i] = head; head = i; #ifdef CGAL_SMALL_UNORDERED_MAP_STATS - if(collision>9){ + if(collision>19){ std::cerr << collision << " collisions" << std::endl; }else{ ++collisions[collision]; diff --git a/STL_Extension/include/CGAL/Time_stamper.h b/STL_Extension/include/CGAL/Time_stamper.h index a9a7e90664a..3b93ea54cfb 100644 --- a/STL_Extension/include/CGAL/Time_stamper.h +++ b/STL_Extension/include/CGAL/Time_stamper.h @@ -26,6 +26,14 @@ namespace CGAL { +namespace internal { + +constexpr size_t rounded_down_log2(size_t n) +{ + return ( (n<2) ? 0 : 1+rounded_down_log2(n/2)); +} +} // namespace internal + template struct Time_stamper { @@ -128,7 +136,8 @@ public: static std::size_t hash_value(const T* p) { - return reinterpret_cast(p) >> 5; // sizeof(T); + std::size_t shift = internal::rounded_down_log2(sizeof(p)); + return reinterpret_cast(p) >> shift; // AF: was: / sizeof(T); } void reset() {} diff --git a/Triangulation_3/include/CGAL/Triangulation_3.h b/Triangulation_3/include/CGAL/Triangulation_3.h index 8f98c038755..2113ca63b5b 100644 --- a/Triangulation_3/include/CGAL/Triangulation_3.h +++ b/Triangulation_3/include/CGAL/Triangulation_3.h @@ -41,9 +41,6 @@ #include #include -// #include -// #include - #include #include #include @@ -3686,11 +3683,7 @@ insert_in_conflict(const Point& p, typedef std::pair Local_facet; typedef Small_unordered_map, maximal_nb_of_facets> - Halfedge_facet_map; - // typedef - // absl::flat_hash_map, - // Facet// , boost::hash >> - // E2F; + Halfedge_facet_map; static Halfedge_facet_map h2f; nv = tds().create_vertex(); nv->set_point(p); From 7c9ef9c9f2f4c67e102c191fe96f9a724a1a30bf Mon Sep 17 00:00:00 2001 From: Andreas Fabri Date: Mon, 28 Oct 2019 12:40:24 +0100 Subject: [PATCH 343/363] Move code into TDS_3 and make it work for parallel mode --- .../CGAL/Triangulation_data_structure_3.h | 72 +++++++++++++++++- .../include/CGAL/Triangulation_3.h | 75 +++++-------------- 2 files changed, 89 insertions(+), 58 deletions(-) diff --git a/TDS_3/include/CGAL/Triangulation_data_structure_3.h b/TDS_3/include/CGAL/Triangulation_data_structure_3.h index f9cb9a52713..e4de990ceed 100644 --- a/TDS_3/include/CGAL/Triangulation_data_structure_3.h +++ b/TDS_3/include/CGAL/Triangulation_data_structure_3.h @@ -49,6 +49,7 @@ #include #include +#include #include #include @@ -56,6 +57,7 @@ #include #include +#include #ifdef CGAL_LINKED_WITH_TBB # include @@ -177,6 +179,14 @@ public: typedef Triple Edge; typedef Triangulation_simplex_3 Simplex; + + typedef std::pair Vertex_pair; + typedef std::pair Local_facet; + + static const int maximal_nb_of_facets_of_small_hole = 128; + typedef Small_unordered_map, maximal_nb_of_facets_of_small_hole> Vertex_pair_facet_map; + //#ifndef CGAL_TDS_USE_RECURSIVE_CREATE_STAR_3 //internally used for create_star_3 (faster than a tuple) struct iAdjacency_info{ @@ -200,7 +210,7 @@ public: } }; //#endif - + public: Triangulation_data_structure_3() @@ -505,6 +515,56 @@ public: return insert_in_hole(cell_begin, cell_end, begin, i, create_vertex()); } + template + Vertex_handle _insert_in_small_hole(const Cells& cells, const Facets& facets) + { + CGAL_STATIC_THREAD_LOCAL_VARIABLE_0(Vertex_pair_facet_map, vertex_pair_facet_map); + Vertex_handle nv = create_vertex(); + std::array new_cells; + for (int local_facet_index = 0, end = facets.size(); + local_facet_index < end; ++local_facet_index) { + const Facet f = mirror_facet(facets[local_facet_index]); + f.first->tds_data().clear(); // was on boundary + const Vertex_handle u = f.first->vertex(vertex_triple_index(f.second, 0)); + const Vertex_handle v = f.first->vertex(vertex_triple_index(f.second, 1)); + const Vertex_handle w = f.first->vertex(vertex_triple_index(f.second, 2)); + u->set_cell(f.first); + v->set_cell(f.first); + w->set_cell(f.first); + const Cell_handle nc = create_cell(v, u, w, nv); + new_cells[local_facet_index] = nc; + nv->set_cell(nc); + nc->set_neighbor(3, f.first); + f.first->set_neighbor(f.second, nc); + + vertex_pair_facet_map.set({u, v}, {local_facet_index, + static_cast(nc->index(w))}); + vertex_pair_facet_map.set({v, w}, {local_facet_index, + static_cast(nc->index(u))}); + vertex_pair_facet_map.set({w, u}, {local_facet_index, + static_cast(nc->index(v))}); + } + + for(auto it = vertex_pair_facet_map.begin(); it != vertex_pair_facet_map.end(); ++it){ + const std::pair& ef = *it; + if(ef.first.first < ef.first.second){ + const Facet f = Facet{new_cells[ef.second.first], ef.second.second}; + vertex_pair_facet_map.clear(it); + const auto p = vertex_pair_facet_map.get(std::make_pair(ef.first.second, ef.first.first)); + const Facet n = Facet{new_cells[p.first], p.second}; + f.first->set_neighbor(f.second, n.first); + n.first->set_neighbor(n.second, f.first); + } + } + for(Cell_handle c : cells){ + c->tds_data().clear(); // was in conflict + } + delete_cells(cells.begin(), cells.end()); + vertex_pair_facet_map.clear(); + return nv; + } + + //INSERTION // Create a finite cell with v1, v2, v3 and v4 @@ -1429,6 +1489,11 @@ public: Vertex_range & vertices() const { return const_cast(this)->_vertices; } + bool is_small_hole(std::size_t s) + { + return s <= maximal_nb_of_facets_of_small_hole; + } + private: // Change the orientation of the cell by swapping indices 0 and 1. @@ -1449,6 +1514,11 @@ private: Cell_range _cells; Vertex_range _vertices; + + // Vertex_pair_facet_map vertex_pair_facet_map; + + + // used by is-valid : bool count_vertices(size_type &i, bool verbose = false, int level = 0) const; // counts AND checks the validity diff --git a/Triangulation_3/include/CGAL/Triangulation_3.h b/Triangulation_3/include/CGAL/Triangulation_3.h index 2113ca63b5b..a4fc1d25bd5 100644 --- a/Triangulation_3/include/CGAL/Triangulation_3.h +++ b/Triangulation_3/include/CGAL/Triangulation_3.h @@ -57,7 +57,7 @@ #include #include #include -#include + #include #include @@ -1194,7 +1194,18 @@ public: v->set_point(p); return v; } - + + // Internal function, cells should already be marked. + template + Vertex_handle _insert_in_small_hole(const Point& p, + const Cells& cells, + const Facets& facets ) + { + Vertex_handle v = _tds._insert_in_small_hole(cells, facets); + v->set_point(p); + return v; + } + // Internal function, cells should already be marked. template Vertex_handle _insert_in_hole(const Point& p, @@ -3675,63 +3686,13 @@ insert_in_conflict(const Point& p, // as they will be deleted during the insertion. hider.process_cells_in_conflict(cells.begin(), cells.end()); Vertex_handle nv; - // AF: the new code - constexpr int maximal_nb_of_facets = 128; - if( facets.size() < maximal_nb_of_facets){ - // LESS64++; - typedef std::pair Halfedge; - typedef std::pair Local_facet; - typedef Small_unordered_map, maximal_nb_of_facets> - Halfedge_facet_map; - static Halfedge_facet_map h2f; - nv = tds().create_vertex(); - nv->set_point(p); - std::array new_cells; - for (int local_facet_index = 0, end = facets.size(); - local_facet_index < end; ++local_facet_index) { - const Facet f = mirror_facet(facets[local_facet_index]); - f.first->tds_data().clear(); // was on boundary - const Vertex_handle u = f.first->vertex(vertex_triple_index(f.second, 0)); - const Vertex_handle v = f.first->vertex(vertex_triple_index(f.second, 1)); - const Vertex_handle w = f.first->vertex(vertex_triple_index(f.second, 2)); - u->set_cell(f.first); - v->set_cell(f.first); - w->set_cell(f.first); - const Cell_handle nc = tds().create_cell(v, u, w, nv); - new_cells[local_facet_index] = nc; - nv->set_cell(nc); - nc->set_neighbor(3, f.first); - f.first->set_neighbor(f.second, nc); - h2f.set({u, v}, {local_facet_index, - static_cast(nc->index(w))}); - h2f.set({v, w}, {local_facet_index, - static_cast(nc->index(u))}); - h2f.set({w, u}, {local_facet_index, - static_cast(nc->index(v))}); - } - - for(auto it = h2f.begin(); it != h2f.end(); ++it){ - const std::pair& ef = *it; - if(ef.first.first < ef.first.second){ - const Facet f = Facet{new_cells[ef.second.first], ef.second.second}; - h2f.clear(it); - const auto p = h2f.get(std::make_pair(ef.first.second, ef.first.first)); - const Facet n = Facet{new_cells[p.first], p.second}; - f.first->set_neighbor(f.second, n.first); - n.first->set_neighbor(n.second, f.first); - } - } - for(Cell_handle c : cells){ - c->tds_data().clear(); // was in conflict - } - tds().delete_cells(cells.begin(), cells.end()); - h2f.clear(); + if(tds().is_small_hole(facets.size())){ + nv = _insert_in_small_hole(p, cells, facets); }else{ - Vertex_handle nv = _insert_in_hole(p, - cells.begin(), cells.end(), - facet.first, facet.second); + nv = _insert_in_hole(p, + cells.begin(), cells.end(), + facet.first, facet.second); } // Store the hidden points in their new cells. hider.reinsert_vertices(nv); From 02e3d25914cf9d15186837eba0fded78a772756a Mon Sep 17 00:00:00 2001 From: Andreas Fabri Date: Mon, 28 Oct 2019 13:46:35 +0100 Subject: [PATCH 344/363] cleanup --- STL_Extension/include/CGAL/Small_unordered_map.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/STL_Extension/include/CGAL/Small_unordered_map.h b/STL_Extension/include/CGAL/Small_unordered_map.h index 9b0bf1eb160..f5748f37213 100644 --- a/STL_Extension/include/CGAL/Small_unordered_map.h +++ b/STL_Extension/include/CGAL/Small_unordered_map.h @@ -47,7 +47,7 @@ class Small_unordered_map{ hs += 1; hs += (hs << 1) + (hs << 5) + (hs << 7) + (hs << 8); */ - return (hf + 1) ^ (419 * (hs + 1)); + return (hf+1) ^ (419 * (hs+1)); } public: From 2edab88f8176732b52f9db00d6d8b26920b05246 Mon Sep 17 00:00:00 2001 From: Andreas Fabri Date: Wed, 30 Oct 2019 09:24:58 +0100 Subject: [PATCH 345/363] variable must be constexpr too --- STL_Extension/include/CGAL/Time_stamper.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/STL_Extension/include/CGAL/Time_stamper.h b/STL_Extension/include/CGAL/Time_stamper.h index 3b93ea54cfb..c597ab00a89 100644 --- a/STL_Extension/include/CGAL/Time_stamper.h +++ b/STL_Extension/include/CGAL/Time_stamper.h @@ -136,7 +136,7 @@ public: static std::size_t hash_value(const T* p) { - std::size_t shift = internal::rounded_down_log2(sizeof(p)); + constexpr std::size_t shift = internal::rounded_down_log2(sizeof(p)); return reinterpret_cast(p) >> shift; // AF: was: / sizeof(T); } From 35fa824216202a783e852616e793a0a7e396c027 Mon Sep 17 00:00:00 2001 From: Andreas Fabri Date: Wed, 27 Nov 2019 16:39:59 +0100 Subject: [PATCH 346/363] Move hash --- .../include/CGAL/Small_unordered_map.h | 27 ++++++------------- .../CGAL/Triangulation_data_structure_3.h | 19 ++++++++----- 2 files changed, 21 insertions(+), 25 deletions(-) diff --git a/STL_Extension/include/CGAL/Small_unordered_map.h b/STL_Extension/include/CGAL/Small_unordered_map.h index f5748f37213..4b30404bb7f 100644 --- a/STL_Extension/include/CGAL/Small_unordered_map.h +++ b/STL_Extension/include/CGAL/Small_unordered_map.h @@ -26,30 +26,19 @@ //#define CGAL_SMALL_UNORDERED_MAP_STATS namespace CGAL { + -template +template class Small_unordered_map{ #ifdef CGAL_SMALL_UNORDERED_MAP_STATS std::array collisions = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; #endif - static const unsigned int M = N<<3; int head = -2; - mutable std::array occupied; - std::array unfreelist; + mutable std::array occupied; + std::array unfreelist; std::array, M> data; - //const H h = {}; + const H hash = {}; - int hash(const K& k)const - { - std::size_t hf = boost::hash()(k.first); - std::size_t hs = boost::hash()(k.second); - /* - hs += 1; - hs += (hs << 1) + (hs << 5) + (hs << 7) + (hs << 8); - */ - return (hf+1) ^ (419 * (hs+1)); - } - public: Small_unordered_map() { @@ -103,8 +92,8 @@ public: CGAL_error(); } - - const T& get(const K& k) const + // et only once as it is erased + const T& get_and_erase(const K& k) const { unsigned int h = hash(k)%M; int i = h; @@ -121,7 +110,7 @@ public: void clear() { head = -2; - // occupied.fill(-1); + // without erase we would have to call occupied.fill(-1); which is costly } struct iterator { diff --git a/TDS_3/include/CGAL/Triangulation_data_structure_3.h b/TDS_3/include/CGAL/Triangulation_data_structure_3.h index e4de990ceed..e6eef6bad14 100644 --- a/TDS_3/include/CGAL/Triangulation_data_structure_3.h +++ b/TDS_3/include/CGAL/Triangulation_data_structure_3.h @@ -183,9 +183,20 @@ public: typedef std::pair Vertex_pair; typedef std::pair Local_facet; + struct Small_pair_hash { + + std::size_t operator()(const Vertex_pair& k) const + { + std::size_t hf = boost::hash()(k.first); + std::size_t hs = boost::hash()(k.second); + + return hf ^ 419 * hs; + } + }; + static const int maximal_nb_of_facets_of_small_hole = 128; typedef Small_unordered_map, maximal_nb_of_facets_of_small_hole> Vertex_pair_facet_map; + Small_pair_hash, maximal_nb_of_facets_of_small_hole *8> Vertex_pair_facet_map; //#ifndef CGAL_TDS_USE_RECURSIVE_CREATE_STAR_3 //internally used for create_star_3 (faster than a tuple) @@ -550,7 +561,7 @@ public: if(ef.first.first < ef.first.second){ const Facet f = Facet{new_cells[ef.second.first], ef.second.second}; vertex_pair_facet_map.clear(it); - const auto p = vertex_pair_facet_map.get(std::make_pair(ef.first.second, ef.first.first)); + const auto p = vertex_pair_facet_map.get_and_erase(std::make_pair(ef.first.second, ef.first.first)); const Facet n = Facet{new_cells[p.first], p.second}; f.first->set_neighbor(f.second, n.first); n.first->set_neighbor(n.second, f.first); @@ -1515,10 +1526,6 @@ private: Vertex_range _vertices; - // Vertex_pair_facet_map vertex_pair_facet_map; - - - // used by is-valid : bool count_vertices(size_type &i, bool verbose = false, int level = 0) const; // counts AND checks the validity From 40f747bd455c335076dc583766f260b62cdf2e49 Mon Sep 17 00:00:00 2001 From: Mael Date: Fri, 6 Dec 2019 15:46:59 +0100 Subject: [PATCH 347/363] Fix license --- STL_Extension/include/CGAL/Small_unordered_map.h | 15 +++------------ 1 file changed, 3 insertions(+), 12 deletions(-) diff --git a/STL_Extension/include/CGAL/Small_unordered_map.h b/STL_Extension/include/CGAL/Small_unordered_map.h index 4b30404bb7f..964aa0e7f6a 100644 --- a/STL_Extension/include/CGAL/Small_unordered_map.h +++ b/STL_Extension/include/CGAL/Small_unordered_map.h @@ -1,20 +1,11 @@ -// Copyright (c) 2019 GeometryFactory (France). +// Copyright (c) 2019 GeometryFactory Sarl (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 Lesser 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: LGPL-3.0+ +// SPDX-License-Identifier: LGPL-3.0-or-later OR LicenseRef-Commercial // // Author(s) : Andreas Fabri From 435bb4d4c4c8076119f21c9f98b938765bbd02d9 Mon Sep 17 00:00:00 2001 From: Laurent Rineau Date: Tue, 10 Dec 2019 10:59:13 +0100 Subject: [PATCH 348/363] Cleanup the patch --- STL_Extension/include/CGAL/Time_stamper.h | 4 +- .../CGAL/Triangulation_data_structure_3.h | 89 +++++++++---------- .../include/CGAL/Triangulation_3.h | 29 +++--- 3 files changed, 59 insertions(+), 63 deletions(-) diff --git a/STL_Extension/include/CGAL/Time_stamper.h b/STL_Extension/include/CGAL/Time_stamper.h index c597ab00a89..bd1c6afca1e 100644 --- a/STL_Extension/include/CGAL/Time_stamper.h +++ b/STL_Extension/include/CGAL/Time_stamper.h @@ -26,14 +26,14 @@ namespace CGAL { -namespace internal { +namespace internal { constexpr size_t rounded_down_log2(size_t n) { return ( (n<2) ? 0 : 1+rounded_down_log2(n/2)); } } // namespace internal - + template struct Time_stamper { diff --git a/TDS_3/include/CGAL/Triangulation_data_structure_3.h b/TDS_3/include/CGAL/Triangulation_data_structure_3.h index e6eef6bad14..84ebef429e5 100644 --- a/TDS_3/include/CGAL/Triangulation_data_structure_3.h +++ b/TDS_3/include/CGAL/Triangulation_data_structure_3.h @@ -189,15 +189,15 @@ public: { std::size_t hf = boost::hash()(k.first); std::size_t hs = boost::hash()(k.second); - + return hf ^ 419 * hs; } }; - + static const int maximal_nb_of_facets_of_small_hole = 128; typedef Small_unordered_map Vertex_pair_facet_map; - + //#ifndef CGAL_TDS_USE_RECURSIVE_CREATE_STAR_3 //internally used for create_star_3 (faster than a tuple) struct iAdjacency_info{ @@ -531,50 +531,50 @@ public: { CGAL_STATIC_THREAD_LOCAL_VARIABLE_0(Vertex_pair_facet_map, vertex_pair_facet_map); Vertex_handle nv = create_vertex(); - std::array new_cells; - for (int local_facet_index = 0, end = facets.size(); - local_facet_index < end; ++local_facet_index) { - const Facet f = mirror_facet(facets[local_facet_index]); - f.first->tds_data().clear(); // was on boundary - const Vertex_handle u = f.first->vertex(vertex_triple_index(f.second, 0)); - const Vertex_handle v = f.first->vertex(vertex_triple_index(f.second, 1)); - const Vertex_handle w = f.first->vertex(vertex_triple_index(f.second, 2)); - u->set_cell(f.first); - v->set_cell(f.first); - w->set_cell(f.first); - const Cell_handle nc = create_cell(v, u, w, nv); - new_cells[local_facet_index] = nc; - nv->set_cell(nc); - nc->set_neighbor(3, f.first); - f.first->set_neighbor(f.second, nc); + std::array new_cells; + for (int local_facet_index = 0, end = facets.size(); + local_facet_index < end; ++local_facet_index) { + const Facet f = mirror_facet(facets[local_facet_index]); + f.first->tds_data().clear(); // was on boundary + const Vertex_handle u = f.first->vertex(vertex_triple_index(f.second, 0)); + const Vertex_handle v = f.first->vertex(vertex_triple_index(f.second, 1)); + const Vertex_handle w = f.first->vertex(vertex_triple_index(f.second, 2)); + u->set_cell(f.first); + v->set_cell(f.first); + w->set_cell(f.first); + const Cell_handle nc = create_cell(v, u, w, nv); + new_cells[local_facet_index] = nc; + nv->set_cell(nc); + nc->set_neighbor(3, f.first); + f.first->set_neighbor(f.second, nc); - vertex_pair_facet_map.set({u, v}, {local_facet_index, - static_cast(nc->index(w))}); - vertex_pair_facet_map.set({v, w}, {local_facet_index, - static_cast(nc->index(u))}); - vertex_pair_facet_map.set({w, u}, {local_facet_index, - static_cast(nc->index(v))}); - } + vertex_pair_facet_map.set({u, v}, {local_facet_index, + static_cast(nc->index(w))}); + vertex_pair_facet_map.set({v, w}, {local_facet_index, + static_cast(nc->index(u))}); + vertex_pair_facet_map.set({w, u}, {local_facet_index, + static_cast(nc->index(v))}); + } - for(auto it = vertex_pair_facet_map.begin(); it != vertex_pair_facet_map.end(); ++it){ - const std::pair& ef = *it; - if(ef.first.first < ef.first.second){ - const Facet f = Facet{new_cells[ef.second.first], ef.second.second}; - vertex_pair_facet_map.clear(it); - const auto p = vertex_pair_facet_map.get_and_erase(std::make_pair(ef.first.second, ef.first.first)); - const Facet n = Facet{new_cells[p.first], p.second}; - f.first->set_neighbor(f.second, n.first); - n.first->set_neighbor(n.second, f.first); - } + for(auto it = vertex_pair_facet_map.begin(); it != vertex_pair_facet_map.end(); ++it){ + const std::pair& ef = *it; + if(ef.first.first < ef.first.second){ + const Facet f = Facet{new_cells[ef.second.first], ef.second.second}; + vertex_pair_facet_map.clear(it); + const auto p = vertex_pair_facet_map.get_and_erase(std::make_pair(ef.first.second, ef.first.first)); + const Facet n = Facet{new_cells[p.first], p.second}; + f.first->set_neighbor(f.second, n.first); + n.first->set_neighbor(n.second, f.first); } - for(Cell_handle c : cells){ - c->tds_data().clear(); // was in conflict - } - delete_cells(cells.begin(), cells.end()); - vertex_pair_facet_map.clear(); - return nv; + } + for(Cell_handle c : cells){ + c->tds_data().clear(); // was in conflict + } + delete_cells(cells.begin(), cells.end()); + vertex_pair_facet_map.clear(); + return nv; } - + //INSERTION @@ -1504,7 +1504,7 @@ public: { return s <= maximal_nb_of_facets_of_small_hole; } - + private: // Change the orientation of the cell by swapping indices 0 and 1. @@ -1525,7 +1525,6 @@ private: Cell_range _cells; Vertex_range _vertices; - // used by is-valid : bool count_vertices(size_type &i, bool verbose = false, int level = 0) const; // counts AND checks the validity diff --git a/Triangulation_3/include/CGAL/Triangulation_3.h b/Triangulation_3/include/CGAL/Triangulation_3.h index a4fc1d25bd5..82f3eef1556 100644 --- a/Triangulation_3/include/CGAL/Triangulation_3.h +++ b/Triangulation_3/include/CGAL/Triangulation_3.h @@ -58,7 +58,6 @@ #include #include - #include #include @@ -1194,7 +1193,7 @@ public: v->set_point(p); return v; } - + // Internal function, cells should already be marked. template Vertex_handle _insert_in_small_hole(const Point& p, @@ -1205,7 +1204,7 @@ public: v->set_point(p); return v; } - + // Internal function, cells should already be marked. template Vertex_handle _insert_in_hole(const Point& p, @@ -1264,7 +1263,7 @@ protected: typedef boost::container::small_vector SV; SV sv; std::stack cell_stack(sv); - + cell_stack.push(d); d->tds_data().mark_in_conflict(); @@ -3617,7 +3616,6 @@ insert_in_conflict(const Point& p, Hidden_points_visitor& hider, bool *could_lock_zone) { - if(could_lock_zone) *could_lock_zone = true; @@ -3643,7 +3641,7 @@ insert_in_conflict(const Point& p, Facet facet; boost::container::small_vector facets; - + // Parallel if(could_lock_zone) { @@ -3685,18 +3683,17 @@ insert_in_conflict(const Point& p, // Remember the points that are hidden by the conflicting cells, // as they will be deleted during the insertion. hider.process_cells_in_conflict(cells.begin(), cells.end()); - Vertex_handle nv; - if(tds().is_small_hole(facets.size())){ - nv = _insert_in_small_hole(p, cells, facets); - }else{ - nv = _insert_in_hole(p, - cells.begin(), cells.end(), - facet.first, facet.second); - } + Vertex_handle v = + tds().is_small_hole(facets.size()) ? + _insert_in_small_hole(p, cells, facets) : + _insert_in_hole(p, + cells.begin(), cells.end(), + facet.first, facet.second); + // Store the hidden points in their new cells. - hider.reinsert_vertices(nv); - return nv; + hider.reinsert_vertices(v); + return v; } case 2: { From 3de47e8248808f13a12e02c79fa483a8cf86f091 Mon Sep 17 00:00:00 2001 From: Andreas Fabri Date: Tue, 10 Dec 2019 10:39:13 +0100 Subject: [PATCH 349/363] Fix warning --- 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 84ebef429e5..91cdc928c4d 100644 --- a/TDS_3/include/CGAL/Triangulation_data_structure_3.h +++ b/TDS_3/include/CGAL/Triangulation_data_structure_3.h @@ -532,7 +532,7 @@ public: CGAL_STATIC_THREAD_LOCAL_VARIABLE_0(Vertex_pair_facet_map, vertex_pair_facet_map); Vertex_handle nv = create_vertex(); std::array new_cells; - for (int local_facet_index = 0, end = facets.size(); + for (unsigned char local_facet_index = 0, end = static_cast(facets.size()); local_facet_index < end; ++local_facet_index) { const Facet f = mirror_facet(facets[local_facet_index]); f.first->tds_data().clear(); // was on boundary From 29a4f441c98d83c759f8848e9eda4601d541128b Mon Sep 17 00:00:00 2001 From: Andreas Fabri Date: Tue, 10 Dec 2019 11:55:42 +0100 Subject: [PATCH 350/363] Shift depends on sizeof(T) not on sizeof(T*) --- STL_Extension/include/CGAL/Time_stamper.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/STL_Extension/include/CGAL/Time_stamper.h b/STL_Extension/include/CGAL/Time_stamper.h index bd1c6afca1e..9b4d6770f76 100644 --- a/STL_Extension/include/CGAL/Time_stamper.h +++ b/STL_Extension/include/CGAL/Time_stamper.h @@ -136,8 +136,8 @@ public: static std::size_t hash_value(const T* p) { - constexpr std::size_t shift = internal::rounded_down_log2(sizeof(p)); - return reinterpret_cast(p) >> shift; // AF: was: / sizeof(T); + constexpr std::size_t shift = internal::rounded_down_log2(sizeof(T)); + return reinterpret_cast(p) >> shift; } void reset() {} From 0460176a2bb5655cbb69e2099e5907fed18b648c Mon Sep 17 00:00:00 2001 From: Laurent Rineau Date: Tue, 10 Dec 2019 13:52:33 +0100 Subject: [PATCH 351/363] Fix another warning --- STL_Extension/include/CGAL/Small_unordered_map.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/STL_Extension/include/CGAL/Small_unordered_map.h b/STL_Extension/include/CGAL/Small_unordered_map.h index 964aa0e7f6a..4272d16bb5b 100644 --- a/STL_Extension/include/CGAL/Small_unordered_map.h +++ b/STL_Extension/include/CGAL/Small_unordered_map.h @@ -87,7 +87,7 @@ public: const T& get_and_erase(const K& k) const { unsigned int h = hash(k)%M; - int i = h; + unsigned int i = h; do{ if((occupied[i] == 1) && (data[i].first == k)){ occupied[i] = -1; From 759cb0e4d8471a63669d640561e830bb805d3078 Mon Sep 17 00:00:00 2001 From: Laurent Rineau Date: Tue, 10 Dec 2019 13:52:41 +0100 Subject: [PATCH 352/363] Add an assertion to check that the `unsigned char` is wide enough --- TDS_3/include/CGAL/Triangulation_data_structure_3.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/TDS_3/include/CGAL/Triangulation_data_structure_3.h b/TDS_3/include/CGAL/Triangulation_data_structure_3.h index 0eaa5aac574..e971ee6a7db 100644 --- a/TDS_3/include/CGAL/Triangulation_data_structure_3.h +++ b/TDS_3/include/CGAL/Triangulation_data_structure_3.h @@ -28,6 +28,7 @@ #include #include #include +#include #include #include @@ -525,6 +526,7 @@ public: template Vertex_handle _insert_in_small_hole(const Cells& cells, const Facets& facets) { + CGAL_assertion(facets.size() < (std::numeric_limits::max)()); CGAL_STATIC_THREAD_LOCAL_VARIABLE_0(Vertex_pair_facet_map, vertex_pair_facet_map); Vertex_handle nv = create_vertex(); std::array new_cells; From 048691b45417ecf7b0367c362b988100b1304e0e Mon Sep 17 00:00:00 2001 From: Laurent Rineau Date: Tue, 10 Dec 2019 14:26:12 +0100 Subject: [PATCH 353/363] Fix test_c3t3_io.cpp after the change in cells order As this branch modified `insert_in_hole`, then the order of cells in the cells container is modified. --- .../Mesh_3/data/c3t3_io-hetero.binary.cgal | Bin 1618 -> 1618 bytes Mesh_3/test/Mesh_3/data/c3t3_io-hetero.cgal | 54 +++++++++--------- .../test/Mesh_3/data/c3t3_io-homo.binary.cgal | Bin 1360 -> 1360 bytes Mesh_3/test/Mesh_3/data/c3t3_io-homo.cgal | 54 +++++++++--------- Mesh_3/test/Mesh_3/test_c3t3_io.cpp | 11 ++++ 5 files changed, 65 insertions(+), 54 deletions(-) diff --git a/Mesh_3/test/Mesh_3/data/c3t3_io-hetero.binary.cgal b/Mesh_3/test/Mesh_3/data/c3t3_io-hetero.binary.cgal index 9de545a229b1f1994b867b24908bc70c8161864e..f4c958d923934984575fbf1a79ec79e6f498f161 100644 GIT binary patch literal 1618 zcmdUrOH0E*5Xa-YRu3LLc<>NJB(Zyor%-C82QMB(iXKEl(w4fQNoltQzqKF1Om}~M z1U+~WT*%JO{2w!uOy}wN!|&YQ-1)u8M1FUy(|kC6ON}n_BnqAediZJv{bW?=+%)gy zPNJ52%!2MLOQMEuWJNJCaXd>!YMO(5`mQFXAIGCqkDFTQmeQ)<3RNcy1Z+HXd!h{1 zN#XO=OBmL-JkQ%LzvVe^+xLZwfs3|k?^9QUbLn!lt6bkQ`PS|0y=Q!K5#fZ z=D@e+9@ODg{peq>^ur%N=H9RPq6ddh|Ee$ZHJ;I@?jWGVm)nZr8`QiVaHd!#1pXf&>x7> zTPOL?S1-Qb+;SXew|G|Pyld_kwtBXjsd=B;8JtVoqb+k?i=jEP{fVuPvr*7@ipQMe zuD#f*=)ZZZte@BGyvCBZSpc$AsySe1UDK1-ape1jduV{=TV`?um$Plk@?Vj+iZfs3 zG(z<31+VJq$qwJzm%hnN;Nwe$4~{>+)xF?9`Jw}-#|K~L@bCx6w~C{KPrqjk$j2NW zdzzL9A0B@D7N;jS`~y2^0N6@yaQ5QIUh*NwhkWb-XU=!vOCI*(%YJn1BL{ls_*eJ9 nulllI@`)B7@|LUMqAzR8c-?#1<2TQ`JL~ZNB6}U5|KNN9XTduX diff --git a/Mesh_3/test/Mesh_3/data/c3t3_io-hetero.cgal b/Mesh_3/test/Mesh_3/data/c3t3_io-hetero.cgal index 9d9667f2c8c..f0c10161e35 100644 --- a/Mesh_3/test/Mesh_3/data/c3t3_io-hetero.cgal +++ b/Mesh_3/test/Mesh_3/data/c3t3_io-hetero.cgal @@ -9,38 +9,38 @@ CGAL c3t3 Triangulation_3(Weighted_point,Vb(Tvb_3+i+boost::variantB zs$i`Fg%KjGOpLik?bKh8WD2D=KHn3Ji@5fEEsssiIF7_K`%{l5?S-DzJysr1YYkrn zARFUAu2bdwJFBSy9+XCb_f=g64_$hyOW*YHksiF(x^EqY7;_if&o{I&)Ei2kWTs7w JJr8i^m~_!?XAIj@esr;(GXBmD$@COymVC5w{0k#&JAVKG diff --git a/Mesh_3/test/Mesh_3/data/c3t3_io-homo.cgal b/Mesh_3/test/Mesh_3/data/c3t3_io-homo.cgal index dbe19aec1c0..3f3795ed37d 100644 --- a/Mesh_3/test/Mesh_3/data/c3t3_io-homo.cgal +++ b/Mesh_3/test/Mesh_3/data/c3t3_io-homo.cgal @@ -9,38 +9,38 @@ CGAL c3t3 Triangulation_3(Weighted_point,Vb(Tvb_3+i+i),Cb(i+RTcb_3+(i)[ 3 9 13 0 3 1 12 0 1 3 4 -6 5 3 4 -5 6 0 4 -1 6 3 4 +4 0 1 6 +4 3 5 6 +5 0 4 6 3 2 1 0 -2 0 3 5 -5 0 3 4 -6 1 0 4 -2 1 0 6 -2 6 0 5 -6 2 3 5 -1 2 3 6 -3 6 7 4 -6 3 2 10 -7 6 1 9 -1 0 7 11 -8 0 5 11 -6 10 9 4 -0 1 2 5 -0 2 3 8 -7 9 11 4 -2 5 10 8 -5 1 9 11 -10 3 8 4 +3 0 4 5 +0 3 2 5 +4 1 3 6 +5 3 2 6 +2 3 1 6 +2 0 5 6 +0 2 1 6 +7 5 1 4 +11 7 3 0 +8 3 7 5 +1 2 10 5 +11 0 6 9 +3 2 6 0 +8 10 5 4 +9 2 1 0 +9 10 2 6 +7 11 8 4 +3 8 11 6 +9 1 10 4 0 3 0 0 0 -1 4 0 0 0 -0 0 0 0 0 -2 0 3 0 0 -0 0 0 0 0 -0 0 0 0 0 0 0 4 0 0 +1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +2 0 0 4 3 +0 0 0 0 0 +0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 diff --git a/Mesh_3/test/Mesh_3/test_c3t3_io.cpp b/Mesh_3/test/Mesh_3/test_c3t3_io.cpp index d6cd39136df..bda2c383f8e 100644 --- a/Mesh_3/test/Mesh_3/test_c3t3_io.cpp +++ b/Mesh_3/test/Mesh_3/test_c3t3_io.cpp @@ -384,6 +384,17 @@ struct Test_c3t3_io { return true; } + { + std::string filename(prefix); + filename += "_new"; + if(binary) filename += ".binary"; + filename += ".cgal"; + std::ofstream output(filename.c_str(), + binary ? (std::ios_base::out | std::ios_base::binary) + : std::ios_base::out); + CGAL::Mesh_3::save_binary_file(output, c3t3_bis, binary); + } + c3t3_bis.clear(); { std::ifstream input(filename.c_str(), From e628e6e203dfb85eb98e03be61ebe7f5f618b3f1 Mon Sep 17 00:00:00 2001 From: Laurent Rineau Date: Thu, 12 Dec 2019 10:50:20 +0100 Subject: [PATCH 354/363] This branch target 4.14.3 --- Installation/include/CGAL/version.h | 4 ++-- Maintenance/release_building/BUGFIX_NUMBER | 2 +- Maintenance/release_building/public_release_name | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/Installation/include/CGAL/version.h b/Installation/include/CGAL/version.h index e68dbc7e8d1..23ed764b2bb 100644 --- a/Installation/include/CGAL/version.h +++ b/Installation/include/CGAL/version.h @@ -25,8 +25,8 @@ #ifndef CGAL_VERSION_H #define CGAL_VERSION_H -#define CGAL_VERSION 4.14.2 -#define CGAL_VERSION_NR 1041421000 +#define CGAL_VERSION 4.14.3 +#define CGAL_VERSION_NR 1041431000 #define CGAL_SVN_REVISION 99999 #define CGAL_GIT_HASH abcdef #define CGAL_RELEASE_DATE 20190329 diff --git a/Maintenance/release_building/BUGFIX_NUMBER b/Maintenance/release_building/BUGFIX_NUMBER index 0cfbf08886f..00750edc07d 100644 --- a/Maintenance/release_building/BUGFIX_NUMBER +++ b/Maintenance/release_building/BUGFIX_NUMBER @@ -1 +1 @@ -2 +3 diff --git a/Maintenance/release_building/public_release_name b/Maintenance/release_building/public_release_name index bb5a97b7e18..84b2dff59aa 100644 --- a/Maintenance/release_building/public_release_name +++ b/Maintenance/release_building/public_release_name @@ -1 +1 @@ -CGAL-4.14.2 +CGAL-4.14.3 From 8a48be1dd82f65d42c9eb7c5c65742bac903364c Mon Sep 17 00:00:00 2001 From: Mael Date: Thu, 12 Dec 2019 13:10:25 +0100 Subject: [PATCH 355/363] Remove unused macro --- Triangulation_3/include/CGAL/Triangulation_3.h | 4 ---- 1 file changed, 4 deletions(-) diff --git a/Triangulation_3/include/CGAL/Triangulation_3.h b/Triangulation_3/include/CGAL/Triangulation_3.h index 8aca5b33516..6941c6c8acf 100644 --- a/Triangulation_3/include/CGAL/Triangulation_3.h +++ b/Triangulation_3/include/CGAL/Triangulation_3.h @@ -1333,7 +1333,6 @@ protected: CGAL_triangulation_precondition(tester(d)); // To store the boundary cells, in case we need to rollback - typedef boost::container::small_vector SV; SV sv; std::stack cell_stack(sv); @@ -3728,9 +3727,6 @@ insert(const Point& p, Locate_type lt, Cell_handle c, int li, int lj) } } -#define AF_NEW - - template < class GT, class Tds, class Lds > template < class Conflict_tester, class Hidden_points_visitor > typename Triangulation_3::Vertex_handle From 4d4b89136288e458503d13eac2dd1f64d46517fb Mon Sep 17 00:00:00 2001 From: Andreas Fabri Date: Wed, 11 Dec 2019 15:39:13 +0100 Subject: [PATCH 356/363] T2: Projection_traits::Construct_bbox_2 must return Bbox_2 --- .../CGAL/internal/Projection_traits_3.h | 16 ++++++-- .../ConstrainedTriangulationTraits_2.h | 4 +- .../test/Triangulation_2/issue_4405.cpp | 39 +++++++++++++++++++ 3 files changed, 54 insertions(+), 5 deletions(-) create mode 100644 Triangulation_2/test/Triangulation_2/issue_4405.cpp diff --git a/Kernel_23/include/CGAL/internal/Projection_traits_3.h b/Kernel_23/include/CGAL/internal/Projection_traits_3.h index 0f15a7e084f..556d72ed74e 100644 --- a/Kernel_23/include/CGAL/internal/Projection_traits_3.h +++ b/Kernel_23/include/CGAL/internal/Projection_traits_3.h @@ -52,6 +52,7 @@ struct Projector static typename R::FT y(const typename R::Point_3& p) {return p.z();} static typename R::FT x(const typename R::Vector_3& p) {return p.y();} static typename R::FT y(const typename R::Vector_3& p) {return p.z();} + static Bbox_2 bbox(const Bbox_3& bb) { return Bbox_2(bb.ymin(),bb.zmin(),bb.ymax(),bb.zmax()); } static const int x_index=1; static const int y_index=2; }; @@ -69,6 +70,7 @@ struct Projector static typename R::FT y(const typename R::Point_3& p) {return p.z();} static typename R::FT x(const typename R::Vector_3& p) {return p.x();} static typename R::FT y(const typename R::Vector_3& p) {return p.z();} + static Bbox_2 bbox(const Bbox_3& bb) { return Bbox_2(bb.xmin(),bb.zmin(),bb.xmax(),bb.zmax()); } static const int x_index=0; static const int y_index=2; }; @@ -87,11 +89,18 @@ struct Projector static typename R::FT y(const typename R::Point_3& p) {return p.y();} static typename R::FT x(const typename R::Vector_3& p) {return p.x();} static typename R::FT y(const typename R::Vector_3& p) {return p.y();} + static Bbox_2 bbox(const Bbox_3& bb) { return Bbox_2(bb.xmin(),bb.ymin(),bb.xmax(),bb.ymax()); } static const int x_index=0; static const int y_index=1; }; - +template +class Construct_bbox_projected_2 { +public: + typedef typename R::Point_3 Point; + + Bbox_2 operator()(const Point& p) const { typename R::Construct_bbox_3 bb; return Projector::bbox(bb(p)); } +}; template class Orientation_projected_3 @@ -804,7 +813,8 @@ public: typedef Construct_weighted_circumcenter_projected_3 Construct_weighted_circumcenter_2; typedef Power_side_of_bounded_power_circle_projected_3 Power_side_of_bounded_power_circle_2; typedef Power_side_of_oriented_power_circle_projected_3 Power_side_of_oriented_power_circle_2; - + typedef Construct_bbox_projected_2 Construct_bbox_2; + typedef typename Rp::Construct_point_3 Construct_point_2; typedef typename Rp::Construct_weighted_point_3 Construct_weighted_point_2; typedef typename Rp::Construct_segment_3 Construct_segment_2; @@ -814,7 +824,7 @@ public: typedef typename Rp::Construct_scaled_vector_3 Construct_scaled_vector_2; typedef typename Rp::Construct_triangle_3 Construct_triangle_2; typedef typename Rp::Construct_line_3 Construct_line_2; - typedef typename Rp::Construct_bbox_3 Construct_bbox_2; + struct Less_xy_2 { typedef bool result_type; diff --git a/Triangulation_2/doc/Triangulation_2/Concepts/ConstrainedTriangulationTraits_2.h b/Triangulation_2/doc/Triangulation_2/Concepts/ConstrainedTriangulationTraits_2.h index dd235e31e37..452a7ca27a7 100644 --- a/Triangulation_2/doc/Triangulation_2/Concepts/ConstrainedTriangulationTraits_2.h +++ b/Triangulation_2/doc/Triangulation_2/Concepts/ConstrainedTriangulationTraits_2.h @@ -80,8 +80,8 @@ typedef unspecified_type Compute_squared_distance_2; A function object whose `operator()` computes the bounding box of a point. -`unspecified_type operator()(Point_2 p);` Returns the bounding box of `p`. -The result type is either `Bbox_2` or `Bbox_3` (for projection traits classes). +CGAL::Bbox_2 operator()(Point_2 p);` Returns the bounding box of `p`. +The result type is `CGAL::Bbox_2` (even for projection traits classes). */ typedef unspecified_type Compute_bounding_box_2; diff --git a/Triangulation_2/test/Triangulation_2/issue_4405.cpp b/Triangulation_2/test/Triangulation_2/issue_4405.cpp new file mode 100644 index 00000000000..142ceaaa348 --- /dev/null +++ b/Triangulation_2/test/Triangulation_2/issue_4405.cpp @@ -0,0 +1,39 @@ +#define CGAL_CDT_2_DEBUG_INTERSECTIONS 1 +#include +#include +#include +#include +#include + +typedef CGAL::Epick Kernel; +typedef Kernel::FT FieldNumberType; +typedef Kernel::Point_2 Point2; +typedef Kernel::Point_3 Point3; +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 CGAL::Triangulation_face_base_with_info_2 FaceBaseWithInfo; +typedef CGAL::Constrained_triangulation_face_base_2 FaceBase; +typedef CGAL::Triangulation_data_structure_2 TriangulationData; +typedef CGAL::Constrained_Delaunay_triangulation_2 ConstrainedTriangulation; + typedef CGAL::Constrained_triangulation_plus_2 CDT; + +int main() +{ + CDT cdt; + const Point3 A(539.5294108288881, 332.45151278002265, 109.660400390625); + const Point3 B(538.779296875, 329.10546875, 109.707275390625); + const Point3 C(539.74609375, 332.431640625, 109.660400390625); + const Point3 D(539.68266371486789, 333.13513011783971, 109.649658203125); + const Point3 E(539.52898179930912, 332.45155212665065, 109.660400390625); + + cdt.insert_constraint(A, B); + cdt.insert_constraint(C, A); + cdt.insert_constraint(D, B); + cdt.insert_constraint(C, E); + return 0; +} From 1224939bcbfacdae460606a2a9a2492d396c3f88 Mon Sep 17 00:00:00 2001 From: Laurent Rineau Date: Mon, 16 Dec 2019 10:45:49 +0100 Subject: [PATCH 357/363] Cleanup: remove unused files That is a follow-up to the PR https://github.com/CGAL/cgal/pull/2336. --- .../Mesh_3/Detect_polylines_in_polyhedra.h | 384 ------------------ .../Detect_polylines_in_polyhedra_fwd.h | 36 -- .../Polyhedral_mesh_domain_with_features_3.h | 1 - 3 files changed, 421 deletions(-) delete mode 100644 Mesh_3/include/CGAL/Mesh_3/Detect_polylines_in_polyhedra.h delete mode 100644 Mesh_3/include/CGAL/Mesh_3/Detect_polylines_in_polyhedra_fwd.h diff --git a/Mesh_3/include/CGAL/Mesh_3/Detect_polylines_in_polyhedra.h b/Mesh_3/include/CGAL/Mesh_3/Detect_polylines_in_polyhedra.h deleted file mode 100644 index 226421ef980..00000000000 --- a/Mesh_3/include/CGAL/Mesh_3/Detect_polylines_in_polyhedra.h +++ /dev/null @@ -1,384 +0,0 @@ -// Copyright (c) 2010, 2012 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) : Laurent Rineau -// - -#ifndef CGAL_MESH_3_DETECT_POLYLINES_IN_POLYHEDRA_H -#define CGAL_MESH_3_DETECT_POLYLINES_IN_POLYHEDRA_H - -#include - -#include -#include -#include -#include - -#include -#include -#include - -#include - -namespace CGAL { namespace Mesh_3 { - -template -struct Detect_polylines -{ - typedef typename Polyhedron::Traits Geom_traits; - typedef typename Geom_traits::Point_3 Point_3; - typedef typename Polyhedron::Halfedge_const_handle Halfedge_const_handle; - typedef typename Polyhedron::Halfedge_handle Halfedge_handle; - typedef typename Polyhedron::Vertex_const_handle Vertex_const_handle; - typedef typename Polyhedron::Vertex_handle Vertex_handle; - typedef typename Polyhedron::size_type size_type; - typedef CGAL::Compare_handles_with_or_without_timestamps Compare_handles; - - typedef CGAL::Hash_handles_with_or_without_timestamps Hash_fct; - typedef boost::unordered_set Vertices_set; - typedef boost::unordered_map Vertices_counter; - - typedef boost::unordered_set Feature_edges_set; - - Feature_edges_set edges_to_consider; - Vertices_set corner_vertices; - - // typedef std::vector Polyline_and_context; - - typedef typename Polyhedron::Vertex Polyhedron_vertex; - typedef typename Polyhedron_vertex::Set_of_indices Set_of_indices; - - template - static - void display_index(std::ostream& stream, const T& x) - { - stream << x; - } - - template - static - void display_index(std::ostream& stream, const std::pair& p) - { - stream << p.first << "+" << p.second; - } - - static - void display_set(std::ostream& stream, Set_of_indices set) { - stream << "( "; - for(typename Set_of_indices::value_type i : set) { - display_index(stream, i); - stream << " "; - } - stream << ")"; - } - - static Set_of_indices - edge_indices(const Halfedge_handle he) { - Set_of_indices set_of_indices; - const Set_of_indices& source_set = - he->opposite()->vertex()->incident_patches_ids_set(); - const Set_of_indices& target_set = - he->vertex()->incident_patches_ids_set(); - std::set_intersection(source_set.begin(), source_set.end(), - target_set.begin(), target_set.end(), - std::inserter(set_of_indices, - set_of_indices.begin())); - if(set_of_indices.empty()) { - std::cerr << "Indices set of following edge is empty:\n"; - std::cerr << " " << he->opposite()->vertex()->point() - << " "; - display_set(std::cerr, source_set); - std::cerr << "\n"; - std::cerr << " " << he->vertex()->point() - << " "; - display_set(std::cerr, target_set); - std::cerr << "\n"; - } - return set_of_indices; - } - - static Halfedge_handle canonical(Halfedge_handle he) - { - const Halfedge_handle& op = he->opposite(); - if(Compare_handles()(he, op)) - return he; - else - return op; - } - - static bool is_feature(const Halfedge_handle he) { - return - he->is_feature_edge() || he->opposite()->is_feature_edge(); - } - - /** Follow a polyline or a polygon, from the halfedge he. */ - template - Polylines_output_iterator - follow_half_edge(const Halfedge_handle he, - Polylines_output_iterator polylines_out, - Polyline_and_context = Polyline_and_context()) - { - typename Feature_edges_set::iterator it = - edges_to_consider.find(canonical(he)); - if(it == edges_to_consider.end()) { - return polylines_out; - } - - Polyline_and_context polyline; - polyline.polyline_content.push_back(he->opposite()->vertex()->point()); - - Halfedge_handle current_he = he; - - Set_of_indices set_of_indices_of_current_edge - = edge_indices(current_he); - - do { - CGAL_assertion(!set_of_indices_of_current_edge.empty()); - CGAL_assertion(is_feature(current_he)); - CGAL_assertion_code(const size_type n = ) - edges_to_consider.erase(canonical(current_he)); - CGAL_assertion(n > 0); - Vertex_handle v = current_he->vertex(); - polyline.polyline_content.push_back(v->point()); - // std::cerr << v->point() << std::endl; - if(corner_vertices.count(v) > 0) break; - typename Polyhedron::Halfedge_around_vertex_circulator - loop_he = v->vertex_begin(); - ++loop_he; - // CGAL_assertion((&*loop_he) != (&*current_he) ); - while((&*loop_he) == (&*current_he) || - (!is_feature(loop_he)) ) { - ++loop_he; - // CGAL_assertion((&*loop_he) != (&*current_he) ); - } - - Set_of_indices set_of_indices_of_next_edge = - edge_indices(loop_he); - - if(! (set_of_indices_of_next_edge.size() == - set_of_indices_of_current_edge.size() - && - std::equal(set_of_indices_of_next_edge.begin(), - set_of_indices_of_next_edge.end(), - set_of_indices_of_current_edge.begin())) ) - { - // the vertex is a special vertex, a new corner -#ifdef CGAL_MESH_3_PROTECTION_DEBUG - std::cerr << "New corner vertex " << v->point() << std::endl; - std::cerr << " indices were: "; - for(typename Set_of_indices::value_type i : - set_of_indices_of_current_edge) { - std::cerr << i << " "; - } - std::cerr << "\n now: "; - for(typename Set_of_indices::value_type i : - set_of_indices_of_next_edge) { - std::cerr << i << " "; - } - std::cerr << "\n"; -#endif - ++v->nb_of_feature_edges; - corner_vertices.insert(v); - polyline.context.adjacent_patches_ids=set_of_indices_of_current_edge; - *polylines_out++ = polyline; - polyline.polyline_content.clear(); - polyline.polyline_content.push_back(loop_he->vertex()->point()); - set_of_indices_of_current_edge = set_of_indices_of_next_edge; - } - - current_he = loop_he->opposite(); - } while(current_he != he ); - - polyline.context.adjacent_patches_ids=set_of_indices_of_current_edge; - *polylines_out++ = polyline; - return polylines_out; - } - - /** Loop around a corner vertex, and try to follow a polyline of feature - edges, from each incident edge. */ - template - Polylines_output_iterator - loop_around_corner(const Vertex_handle v, - Polylines_output_iterator polylines_out, - Polyline_and_context empty_polyline = - Polyline_and_context() ) - { - typename Polyhedron::Halfedge_around_vertex_circulator - he = v->vertex_begin(), end(he); - do { - CGAL_assertion(he->vertex() == v); - polylines_out = follow_half_edge(he->opposite(), - polylines_out, - empty_polyline); - ++he; - } while(he != end); - return polylines_out; - } - - /** For a non-corner vertex v (that is incident to two feature edges), - measure the angle between the two edges, and mark the vertex as corner - edge, if the angle is < 120°. **/ - static bool measure_angle(const Vertex_handle v) - { - Halfedge_handle e1; - Halfedge_handle e2; - typename Polyhedron::Halfedge_around_vertex_circulator he = - v->vertex_begin(), end(he); - // std::cerr << "measure_handle(" << (void*)(&*v) - // << " = " << v->point() << ")"; - bool first = true; - bool done = false; - do { - CGAL_assertion(he->vertex() == v); - // std::cerr << he->opposite()->vertex()->point() << std::endl; - if(is_feature(he)) { - if(first) { - e1 = he; - first = false; - } - else { - if(done) { - std::cerr << v->point() << " should be a corner!\n" - << " Too many adjacent feature edges!\n"; - return false; - } - e2 = he; - done = true; - } - // std::cerr << "x"; - } - // else - // std::cerr << "."; - ++he; - } while(he != end); - if(!done) { - std::cerr << v->point() << " should be a corner!\n" - << " Not enough adjacent feature edge!\n"; - return false; - } - // std::cerr << "\n"; - const Point_3 pv = v->point(); - const Point_3 pa = e1->opposite()->vertex()->point(); - const Point_3 pb = e2->opposite()->vertex()->point(); - const typename Geom_traits::Vector_3 av = pv - pa; - const typename Geom_traits::Vector_3 bv = pv - pb; - const typename Geom_traits::FT sc_prod = av * bv; - if( sc_prod >= 0 || - (sc_prod < 0 && - CGAL::square(sc_prod) < (av * av) * (bv * bv) / 4 ) ) - { - // std::cerr << "Corner (" << pa << ", " << pv - // << ", " << pb << ")\n"; - return true; - } - else { - return false; - } - } - - template - Polylines_output_iterator - operator()(Polyhedron* pMesh, - Polylines_output_iterator out_it, - Polyline_and_context empty_polyline) - { - // That call orders the set of edges of the polyhedron, so that the - // feature edges are at the end of the sequence of edges. - // pMesh->normalize_border(); - Vertices_counter feature_vertices; - - // Iterate over all edges, and find out which vertices are corner - // vertices (more than two incident feature edges). - for(typename Polyhedron::Edge_iterator - eit = pMesh->edges_begin (), - end = pMesh->edges_end(); - eit != end; ++eit) - { - if(!eit->is_feature_edge()) continue; - edges_to_consider.insert(canonical(eit)); - typename Polyhedron::Vertex_handle v = eit->vertex(); - for(unsigned i = 0; i < 2; ++i) { - if(++feature_vertices[v] == 3) - corner_vertices.insert(v); - v = eit->opposite()->vertex(); - } - } - - for(typename Polyhedron::Vertex_iterator - vit = pMesh->vertices_begin (), - end = pMesh->vertices_end(); - vit != end; ++vit) - { - if(feature_vertices.count(vit) !=0 && - feature_vertices[vit] == 1) { - corner_vertices.insert(vit); - } - } - -#ifdef CGAL_MESH_3_PROTECTION_DEBUG - std::cerr << "Corner vertices: " << corner_vertices.size() << std::endl; - std::cerr << "Feature vertices: " << feature_vertices.size() << std::endl; -#endif - - // // Iterate over non-corner feature vertices, and measure the angle. - for(typename Vertices_counter::iterator it = feature_vertices.begin(), - end = feature_vertices.end(); it != end; ++it) - { - const Vertex_handle v = it->first; - if(corner_vertices.count(v) == 0) { - CGAL_assertion(it->second == 2); - if(measure_angle(v)) { - corner_vertices.insert(v); - } - } - } -#ifdef CGAL_MESH_3_PROTECTION_DEBUG - std::cerr << "New corner vertices: " - << corner_vertices.size() << std::endl; -#endif - - // Follow the polylines... - for(typename Vertices_set::iterator it = corner_vertices.begin(), - end = corner_vertices.end(); it != end; ++it) - { - out_it = loop_around_corner(*it, out_it, empty_polyline); - } - - // ... and the cycles. - while(! edges_to_consider.empty() ) { - out_it = follow_half_edge(*edges_to_consider.begin(), - out_it, - empty_polyline); - } - - return out_it; - } -}; - -template -Polylines_output_iterator -detect_polylines(Polyhedron* pMesh, - Polylines_output_iterator out_it) { - - Detect_polylines go; - Polyline_and_context empty_polyline; - return go(pMesh, out_it, empty_polyline); -} - -} // end namespace CGAL::Mesh_3 -} // end namespace CGAL - - -#endif // CGAL_MESH_3_DETECT_POLYLINES_IN_POLYHEDRA_H diff --git a/Mesh_3/include/CGAL/Mesh_3/Detect_polylines_in_polyhedra_fwd.h b/Mesh_3/include/CGAL/Mesh_3/Detect_polylines_in_polyhedra_fwd.h deleted file mode 100644 index 184c4cf4ed9..00000000000 --- a/Mesh_3/include/CGAL/Mesh_3/Detect_polylines_in_polyhedra_fwd.h +++ /dev/null @@ -1,36 +0,0 @@ -// Copyright (c) 2010 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) : Laurent Rineau -// - -#ifndef CGAL_DETECT_POLYLINES_IN_POLYHEDRA_FWD_H -#define CGAL_DETECT_POLYLINES_IN_POLYHEDRA_FWD_H - -#include - - -namespace CGAL { namespace Mesh_3 { - -template -struct Detect_polylines; - -template -Polylines_output_iterator -detect_polylines(Polyhedron* pMesh, - Polylines_output_iterator out_it); - -} // end namespace CGAL::Mesh_3 -} // end namespace CGAL - - -#endif // CGAL_DETECT_POLYLINES_IN_POLYHEDRA_FWD_H diff --git a/Mesh_3/include/CGAL/Polyhedral_mesh_domain_with_features_3.h b/Mesh_3/include/CGAL/Polyhedral_mesh_domain_with_features_3.h index e6c1a99fba2..d5f9979bc9b 100644 --- a/Mesh_3/include/CGAL/Polyhedral_mesh_domain_with_features_3.h +++ b/Mesh_3/include/CGAL/Polyhedral_mesh_domain_with_features_3.h @@ -28,7 +28,6 @@ #include #include #include -#include #include #include From 904df880c84e77d4a3f0ea1b20a1e6b84c71630c Mon Sep 17 00:00:00 2001 From: Laurent Rineau Date: Tue, 17 Dec 2019 09:44:44 +0100 Subject: [PATCH 358/363] Better sort order for releases, in test results --- .../test_handling/create_testresult_page | 31 ++++++++++++------- 1 file changed, 20 insertions(+), 11 deletions(-) diff --git a/Maintenance/test_handling/create_testresult_page b/Maintenance/test_handling/create_testresult_page index 2fc447b2eba..3191234af0f 100755 --- a/Maintenance/test_handling/create_testresult_page +++ b/Maintenance/test_handling/create_testresult_page @@ -48,9 +48,10 @@ sub sort_releases($$) my $b = $_[0]; my $a = $_[1]; - #take only the numbers from release id, skipping I and Ic - my @A = ($a =~ /\d+/g); - my @B = ($b =~ /\d+/g); + #take only the numbers from release id, skipping the bug-fix + #number, and I and Ic + my @A = ($a =~ /(\d+)\.(\d+)\.?(:?\d+)?(:?-Ic?-)?(\d+)?/a); + my @B = ($b =~ /(\d+)\.(\d+)\.?(:?\d+)?(:?-Ic?-)?(\d+)?/a); while(@A and @B) { my $av = shift(@A); @@ -67,8 +68,8 @@ sub write_selects() print OUTPUTV "

            You can browse the test results of a different version :

            "; my %releases; foreach $_ (glob("results-*.shtml")) { - $_ =~ /results-([^I]*)((-Ic?)-([^I].*))\.shtml/; - $releases{"$1$3"}=1; + $_ =~ /results-(\d+.\d+)([^I]*)((-Ic?)-([^I].*))\.shtml/a; + $releases{"$1"}=1; } print OUTPUTV "\n"; print OUTPUTV " \n"; @@ -79,7 +80,7 @@ sub write_selects() } print OUTPUTV "\n"; print OUTPUTV "\n"; - write_select("sel", ".*"); + write_select("sel"); $count = 0; foreach $_ (sort sort_releases (keys %releases)) { write_select("sel" . $count, $_); @@ -91,19 +92,27 @@ sub write_selects() sub write_select() { my $id = shift(@_); - my $pattern = shift(@_); + my $pattern = ".*"; + if (@_ != 0) { + $pattern = quotemeta(shift(@_)); + } my($filename, @result); print OUTPUTV " "; From 693d6022d1c09bdb9fdc933a0a73c09875ee0d29 Mon Sep 17 00:00:00 2001 From: Laurent Rineau Date: Tue, 17 Dec 2019 09:51:08 +0100 Subject: [PATCH 359/363] save the current version of the script --- Maintenance/test_handling/create_testresult_page | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Maintenance/test_handling/create_testresult_page b/Maintenance/test_handling/create_testresult_page index 3191234af0f..ce38de030a9 100755 --- a/Maintenance/test_handling/create_testresult_page +++ b/Maintenance/test_handling/create_testresult_page @@ -291,7 +291,7 @@ EOF print_result_table(); if ($PLATFORMS_BESIDE_RESULTS) { - print OUTPUT "
            All releases (last one)
            \n\n"; + print OUTPUT "
            \n\n"; if ($platform_count > 0) { my $repeat_count = (1 + 1.1/16.5)*scalar(keys %test_directories)/($platform_count+0.25); while ($repeat_count >= 1) { From 65d222144970adb5d258d77c53fc66cdd13111c7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mael=20Rouxel-Labb=C3=A9?= Date: Wed, 18 Dec 2019 09:48:56 +0100 Subject: [PATCH 360/363] Fix used but uninitialized warnings (+ add some more tests) --- .../test/Kernel_23/include/CGAL/_test_cls_ray_3.h | 11 ++++++++--- .../test/Kernel_23/include/CGAL/_test_cls_segment_3.h | 11 ++++++++--- 2 files changed, 16 insertions(+), 6 deletions(-) diff --git a/Kernel_23/test/Kernel_23/include/CGAL/_test_cls_ray_3.h b/Kernel_23/test/Kernel_23/include/CGAL/_test_cls_ray_3.h index 83b88ac7254..22e200263fb 100644 --- a/Kernel_23/test/Kernel_23/include/CGAL/_test_cls_ray_3.h +++ b/Kernel_23/test/Kernel_23/include/CGAL/_test_cls_ray_3.h @@ -27,9 +27,6 @@ _test_cls_ray_3(const R& ) typedef typename R::RT RT; typedef typename R::FT FT; - typename R::Ray_3 ir; - CGAL::Ray_3 r1(ir); - RT n1 = 8; RT n2 = 20; RT n3 = 4; @@ -42,10 +39,18 @@ _test_cls_ray_3(const R& ) CGAL::Point_3 p2( n4, n5, n6, n5); CGAL::Point_3 p3( n7, n2, n4, n7); + typename R::Ray_3 ir ( p2, p1 ); + + CGAL::Ray_3 r1( ir ); CGAL::Ray_3 r2( p1, p2 ); CGAL::Ray_3 r3( p2, p1 ); CGAL::Ray_3 r4( r2 ); r1 = r4; + + typename R::Ray_3 ir2 ( r4 ); + ir = r1; + r4 = ir2; + CGAL::Direction_3 dir( p2 - p1 ); CGAL::Vector_3 vec( p2 - p1 ); CGAL::Line_3 l( p1, p2 ); diff --git a/Kernel_23/test/Kernel_23/include/CGAL/_test_cls_segment_3.h b/Kernel_23/test/Kernel_23/include/CGAL/_test_cls_segment_3.h index 025cfb9a13b..a020f307028 100644 --- a/Kernel_23/test/Kernel_23/include/CGAL/_test_cls_segment_3.h +++ b/Kernel_23/test/Kernel_23/include/CGAL/_test_cls_segment_3.h @@ -27,9 +27,6 @@ _test_cls_segment_3(const R& ) typedef typename R::RT RT; typedef typename R::FT FT; - typename R::Segment_3 is; - CGAL::Segment_3 s1(is); - RT n1 = 7; RT n2 = 21; RT n3 = 14; @@ -42,11 +39,19 @@ _test_cls_segment_3(const R& ) CGAL::Point_3 p2( n4, n5, n6, n5); CGAL::Point_3 p3( n2, n8, n2, n8); + typename R::Segment_3 is ( p2, p1 ); + + CGAL::Segment_3 s1( is ); CGAL::Segment_3 s2( p1, p2 ); CGAL::Segment_3 s3( p2, p1 ); CGAL::Segment_3 s4( s2 ); + s1 = s4; + typename R::Segment_3 is2 ( s4 ); + is = s1; + s4 = is2; + assert( CGAL::parallel(s2, s3) ); CGAL::Vector_3 v0(p1, p2); From 349aaee85bfa978c6b4952722fc0633e3bc5ef69 Mon Sep 17 00:00:00 2001 From: Laurent Rineau Date: Thu, 19 Dec 2019 16:18:04 +0100 Subject: [PATCH 361/363] 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 2d11b351e7c..6d4757ab8f2 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 || 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 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 # 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-4.14-branch.git --public --do-it || echo ERROR +0 21 * * fri cd $HOME/CGAL/create_internal_release-5.0-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 # 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 * * 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 ## Older stuff # from branch 4.13 From c328c66299a6ad1b64dc2dbf007675320b860c4c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9bastien=20Loriot?= Date: Fri, 20 Dec 2019 09:26:23 +0100 Subject: [PATCH 362/363] update CHANGES --- Installation/CHANGES.md | 48 ++++++++++++++++++++--------------------- 1 file changed, 23 insertions(+), 25 deletions(-) diff --git a/Installation/CHANGES.md b/Installation/CHANGES.md index deb4e55aaa5..d824cbde6a7 100644 --- a/Installation/CHANGES.md +++ b/Installation/CHANGES.md @@ -27,6 +27,29 @@ Release date: June 2020 does not allow any intersection, except for the configuration of two constraints having a single common endpoints, for convience. +### dD Spatial Searching + +- 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. [Release 5.0](https://github.com/CGAL/cgal/releases/tag/releases%2FCGAL-5.0) ----------- @@ -113,31 +136,6 @@ Release date: November 2019 which can be used to collect all the non-manifold vertices (i.e. pinched vertices, or vertices appearing in multiple umbrellas) of a mesh. - -### dD Spatial Searching - -- 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. - ### [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 read/write comments from/in the PLY header. From 15c14c03579380e54021198d07d7dd5254f9e596 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9bastien=20Loriot?= Date: Fri, 20 Dec 2019 09:30:45 +0100 Subject: [PATCH 363/363] update CHANGES --- Installation/CHANGES.md | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/Installation/CHANGES.md b/Installation/CHANGES.md index d824cbde6a7..d3cc2cd26e5 100644 --- a/Installation/CHANGES.md +++ b/Installation/CHANGES.md @@ -51,6 +51,11 @@ Release date: June 2020 k-NN search to interrupt some distance computations before its end, saving precious milliseconds, in particular in medium-to-high dimension. +### 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. + [Release 5.0](https://github.com/CGAL/cgal/releases/tag/releases%2FCGAL-5.0) -----------