Merge remote-tracking branch 'cgal/master' into CGAL-Improve_NP_doc_presentation-GF

This commit is contained in:
Mael Rouxel-Labbé 2020-05-12 15:12:21 +02:00
commit 038869cab9
265 changed files with 11807 additions and 2389 deletions

View File

@ -11,7 +11,7 @@ function mytime {
function build_examples {
mkdir -p build-travis
cd build-travis
mytime cmake -DCGAL_DIR="/usr/local/lib/cmake/CGAL" -DCMAKE_CXX_FLAGS="${CXX_FLAGS}" ..
mytime cmake -DCGAL_DIR="/usr/local/lib/cmake/CGAL" -DCMAKE_CXX_FLAGS="${CXX_FLAGS}" -DCGAL_BUILD_THREE_DOC=TRUE ..
mytime make -j2 VERBOSE=1
}
@ -96,7 +96,7 @@ cd $ROOT
cd $ROOT
mkdir build_test
cd build_test
mytime cmake -DCMAKE_INSTALL_PREFIX=install/ ..
mytime cmake -DCMAKE_INSTALL_PREFIX=install/ -DCGAL_BUILD_THREE_DOC=TRUE ..
mytime make install
# test install with minimal downstream example
mkdir installtest
@ -110,7 +110,7 @@ cd $ROOT
echo 'target_link_libraries(${PROJECT_NAME} CGAL::CGAL)' >> CMakeLists.txt
echo '#include "CGAL/remove_outliers.h"' >> main.cpp
cd build
mytime cmake -DCMAKE_INSTALL_PREFIX=../../install ..
mytime cmake -DCMAKE_INSTALL_PREFIX=../../install -DCGAL_BUILD_THREE_DOC=TRUE ..
cd ..
exit 0
fi

View File

@ -1,31 +1,11 @@
# Created by the script cgal_create_CMakeLists
# This is the CMake script for compiling a set of CGAL applications.
# Created by the script cgal_create_cmake_script
# This is the CMake script for compiling a CGAL application.
cmake_minimum_required(VERSION 3.1...3.15)
project( AABB_traits_benchmark)
cmake_minimum_required(VERSION 3.1...3.14)
project( AABB_traits_benchmark )
# CGAL and its components
find_package( CGAL QUIET)
if ( CGAL_FOUND )
include( ${CGAL_USE_FILE} )
else ()
message(STATUS "This project requires the CGAL library, and will not be compiled.")
return()
endif()
# Boost and its components
find_package( Boost REQUIRED )
# include for local directory
if ( NOT Boost_FOUND )
message(STATUS "This project requires the Boost library, and will not be compiled.")
return()
endif()
# include for local package
include_directories( BEFORE ../../include )
add_executable (test_ test.cpp)
find_package(CGAL REQUIRED QUIET OPTIONAL_COMPONENTS Core )
create_single_source_cgal_program( "test.cpp" )
create_single_source_cgal_program( "tree_construction.cpp" )

View File

@ -0,0 +1,124 @@
#include <CGAL/Exact_predicates_inexact_constructions_kernel.h>
#include <CGAL/Exact_predicates_exact_constructions_kernel.h>
#include <CGAL/AABB_tree.h>
#include <CGAL/AABB_traits.h>
#include <CGAL/Surface_mesh.h>
#include <CGAL/AABB_face_graph_triangle_primitive.h>
#include <CGAL/Polygon_mesh_processing/bbox.h>
#include <CGAL/Timer.h>
#include <iostream>
#include <fstream>
int longest_axis(const CGAL::Bbox_3& bbox)
{
const double dx = bbox.xmax() - bbox.xmin();
const double dy = bbox.ymax() - bbox.ymin();
const double dz = bbox.zmax() - bbox.zmin();
return (dx>=dy) ? ((dx>=dz) ? 0 : 2) : ((dy>=dz) ? 1 : 2);
}
template <class RPM>
struct Split_primitives
{
Split_primitives(RPM rpm)
: rpm(rpm)
{}
template<typename PrimitiveIterator>
void operator()(PrimitiveIterator first,
PrimitiveIterator beyond,
const CGAL::Bbox_3& bbox) const
{
PrimitiveIterator middle = first + (beyond - first)/2;
typedef typename std::iterator_traits<PrimitiveIterator>::value_type Primitive;
const int crd=longest_axis(bbox);
const RPM& l_rpm=rpm;
std::nth_element(first, middle, beyond,
[l_rpm, crd](const Primitive& p1, const Primitive& p2){ return get(l_rpm, p1.id())[crd] < get(l_rpm, p2.id())[crd];});
}
RPM rpm;
};
template <class BBM>
struct Compute_bbox {
Compute_bbox(const BBM& bbm)
: bbm(bbm)
{}
template<typename ConstPrimitiveIterator>
CGAL::Bbox_3 operator()(ConstPrimitiveIterator first,
ConstPrimitiveIterator beyond) const
{
CGAL::Bbox_3 bbox = get(bbm, first->id());
for(++first; first != beyond; ++first)
{
bbox += get(bbm, first->id());
}
return bbox;
}
BBM bbm;
};
template <class K>
void run(std::string input)
{
typedef typename K::Point_3 Point_3;
typedef CGAL::Surface_mesh<Point_3> Mesh;
typedef CGAL::AABB_face_graph_triangle_primitive<Mesh> Primitive;
typedef CGAL::AABB_traits<K, Primitive> Traits;
typedef CGAL::AABB_tree<Traits> Tree;
Mesh tm;
std::ifstream(input) >> tm;
{
Tree tree(faces(tm).begin(), faces(tm).end(), tm);
CGAL::Timer time;
time.start();
tree.build();
time.stop();
std::cout << " build() time: " << time.time() << "\n";
}
{
Tree tree(faces(tm).begin(), faces(tm).end(), tm);
CGAL::Timer time;
time.start();
typedef CGAL::Pointer_property_map<CGAL::Bbox_3>::type BBM;
typedef CGAL::Pointer_property_map<CGAL::Epick::Point_3>::type RPM; // EPIC on purpose here
std::vector<CGAL::Bbox_3> v_bb;
std::vector<CGAL::Epick::Point_3> v_rp;
std::size_t nbf = num_faces(tm);
v_bb.resize(nbf);
v_rp.resize(nbf);
BBM bbm = CGAL::make_property_map(v_bb);
RPM rpm = CGAL::make_property_map(v_rp);
CGAL::Cartesian_converter<K, CGAL::Epick> to_input;
for(typename Mesh::Face_index f : tm.faces())
{
v_bb[f]=CGAL::Polygon_mesh_processing::face_bbox(f, tm);
v_rp[f]=to_input(tm.point(target(halfedge(f, tm), tm)));
}
Compute_bbox<BBM> compute_bbox(bbm);
Split_primitives<RPM> split_primitives(rpm);
tree.custom_build(compute_bbox, split_primitives);
time.stop();
std::cout << " custom_build() time: " << time.time() << "\n";
}
}
int main(int, char** argv)
{
std::cout << "Build with Epick\n";
run<CGAL::Epick>(argv[1]);
std::cout << "Build with Epeck\n";
run<CGAL::Epeck>(argv[1]);
return EXIT_SUCCESS;
}

View File

@ -855,8 +855,8 @@ void Scene::update_grid_size()
}
void Scene::generate_points_in(const unsigned int nb_points,
const double min,
const double max)
const double vmin,
const double vmax)
{
if(m_pPolyhedron == NULL)
{
@ -875,7 +875,7 @@ void Scene::generate_points_in(const unsigned int nb_points,
CGAL::Timer timer;
timer.start();
std::cout << "Generate " << nb_points << " points in interval ["
<< min << ";" << max << "]";
<< vmin << ";" << vmax << "]";
unsigned int nb_trials = 0;
Vector vec = random_vector();
@ -892,8 +892,8 @@ void Scene::generate_points_in(const unsigned int nb_points,
if(nb_intersections % 2 != 0)
signed_distance *= -1.0;
if(signed_distance >= min &&
signed_distance <= max)
if(signed_distance >= vmin &&
signed_distance <= vmax)
{
m_points.push_back(p);
if(m_points.size()%(nb_points/10) == 0)

View File

@ -192,7 +192,7 @@ public:
void generate_boundary_points(const unsigned int nb_points);
void generate_boundary_segments(const unsigned int nb_slices);
void generate_points_in(const unsigned int nb_points,
const double min, const double max);
const double vmin, const double vmax);
// algorithms/refine
void refine_loop();

View File

@ -132,62 +132,62 @@ typedef unspecified_type Equal_3;
/// @{
/*!
Returns the intersection detection functor.
returns the intersection detection functor.
*/
Do_intersect_3 do_intersect_3_object();
/*!
Returns the intersection constructor.
returns the intersection constructor.
*/
Intersect_3 intersect_3_object();
/*!
Returns the sphere constructor.
returns the sphere constructor.
*/
Construct_sphere_3 construct_sphere_3_object();
/*!
Returns the closest point constructor.
returns the closest point constructor.
*/
Construct_projected_point_3 construct_projected_point_3_object();
/*!
Returns the compare distance constructor.
returns the compare distance constructor.
*/
Compare_distance_3 compare_distance_3_object();
/*!
Returns the closest point constructor.
returns the closest point constructor.
*/
Has_on_bounded_side_3 has_on_bounded_side_3_object();
/*!
Returns the squared radius functor.
returns the squared radius functor.
*/
Compute_squared_radius_3 compute_squared_radius_3_object();
/*!
Returns the squared distance functor.
returns the squared distance functor.
*/
Compute_squared_distance_3 compute_squared_distance_3_object();
/*!
Returns the `Less_x_3` functor.
returns the `Less_x_3` functor.
*/
Less_x_3 less_x_3_object();
/*!
Returns the `Less_y_3` functor.
returns the `Less_y_3` functor.
*/
Less_y_3 less_y_3_object();
/*!
Returns the `Less_z_3` functor.
returns the `Less_z_3` functor.
*/
Less_z_3 less_z_3_object();
/*!
Returns the equal functor.
returns the equal functor.
*/
Equal_3 equal_3_object();

View File

@ -56,17 +56,17 @@ typedef unspecified_type Id;
/// @{
/*!
Returns the datum (geometric object) represented by the primitive.
returns the datum (geometric object) represented by the primitive.
*/
Datum_reference datum();
/*!
Returns the corresponding identifier. This identifier is only used as a reference for the objects in the output of the `AABB_tree` methods.
returns the corresponding identifier. This identifier is only used as a reference for the objects in the output of the `AABB_tree` methods.
*/
Id id();
/*!
Returns a 3D point located on the geometric object represented by the primitive. This function is used to sort the primitives during the AABB tree construction as well as to construct the search KD-tree internal to the AABB tree used to accelerate distance queries.
returns a 3D point located on the geometric object represented by the primitive. This function is used to sort the primitives during the AABB tree construction as well as to construct the search KD-tree internal to the AABB tree used to accelerate distance queries.
*/
Point_reference reference_point();

View File

@ -66,22 +66,22 @@ typedef unspecified_type Shared_data;
/// \name Operations
/// @{
/*!
Returns the datum (geometric object) represented by the primitive.
returns the datum (geometric object) represented by the primitive.
*/
Datum_reference datum(const Shared_data& data);
/*!
Returns the corresponding identifier. This identifier is only used as a reference for the objects in the output of the `AABB_tree` methods.
returns the corresponding identifier. This identifier is only used as a reference for the objects in the output of the `AABB_tree` methods.
*/
Id id();
/*!
Returns a 3D point located on the geometric object represented by the primitive. This function is used to sort the primitives during the AABB tree construction as well as to construct the search KD-tree internal to the AABB tree used to accelerate distance queries.
returns a 3D point located on the geometric object represented by the primitive. This function is used to sort the primitives during the AABB tree construction as well as to construct the search KD-tree internal to the AABB tree used to accelerate distance queries.
*/
Point_reference reference_point(const Shared_data& data);
/*!
A static function responsible for the creation of the shared data of a primitive.
constructs the shared data of a primitive.
The parameter pack is such that there exists a constructor `template <class T1, class ... T> AABBPrimitiveWithSharedData (T1,T...)`.
*/
template <class ... T>

View File

@ -44,7 +44,7 @@ public:
typedef unspecified_type Intersection_distance;
/*!
Returns the intersection distance functor.
returns the intersection distance functor.
*/
Intersection_distance intersection_distance_object() const ;
};

View File

@ -164,42 +164,42 @@ typedef unspecified_type Equal_3;
/// @{
/*!
Returns the primitive splitting functor.
returns the primitive splitting functor.
*/
Split_primitives split_primitives_object();
/*!
Returns the bounding box constructor.
returns the bounding box constructor.
*/
Compute_bbox compute_bbox_object();
/*!
Returns the intersection detection functor.
returns the intersection detection functor.
*/
Do_intersect do_intersect_object();
/*!
Returns the intersection constructor.
returns the intersection constructor.
*/
Intersection intersection_object();
/*!
Returns the distance comparison functor.
returns the distance comparison functor.
*/
Compare_distance compare_distance_object();
/*!
Returns the closest point constructor.
returns the closest point constructor.
*/
Closest_point closest_point_object();
/*!
Returns the squared distance functor.
returns the squared distance functor.
*/
Squared_distance squared_distance_object();
/*!
Returns the equal functor.
returns the equal functor.
*/
Equal_3 equal_3_object();
@ -220,7 +220,7 @@ void set_shared_data(T ... t);
{}
/*!
Returns the shared data of the primitive constructed after a call to `set_shared_data`.
returns the shared data of the primitive constructed after a call to `set_shared_data`.
If no call to `set_shared_data` has been done, `Primitive::Shared_data()` is returned.
*/
const Primitive::Shared_data& shared_data() const;

View File

@ -336,7 +336,7 @@ inside the bounding box.
The experiments described above are neither exhaustive nor conclusive
as we have chosen one specific case where the input primitives are the
facets of a triangle surface polyhedron. Nevertheless we now provide
some general observations and advices about how to put the AABB tree
some general observations and advises about how to put the AABB tree
to use with satisfactory performances. While the tree construction
times and memory occupancy do not fluctuate much in our experiments
depending on the input surface triangle mesh, the performance
@ -423,10 +423,11 @@ primitives at the leafs of the tree. The ball radius is then shrunk to
the distance between `p` and `q` for all remaining recursive
traversals of the tree. Efficiency is achieved through setting the
initial ball radius to a small value still guaranteed to intersect the
input primitives. This is achieved by constructing through the
function `AABB_tree::accelerate_distance_queries()` an internal secondary data
input primitives. This is achieved by constructing an internal secondary data
structure which provides a good hint to the algorithm at the beginning
of the traversal.
of the traversal (done by default).
Calling `do_not_accelerate_distance_queries()` will disable
the construction and the usage of this internal secondary data structure.
\section aabb_tree_history Design and Implementation History
@ -434,10 +435,10 @@ Camille Wormser and Pierre Alliez started working on a data structure
for efficient collision detection in 2007. The generic design for
implementing both intersection and distance queries, and for generic
queries and primitives was developed by Camille Wormser. In 2009,
Pierre Alliez, St&eacute;phane Tayeb and Camille Wormser made the
Pierre Alliez, Stéphane Tayeb and Camille Wormser made the
implementation CGAL-compliant, with the help of Laurent Rineau for
optimizing the tree construction. The authors wish to thank Andreas
Fabri, Jane Tournois, Mariette Yvinec and Sylvain Lef&egrave;bvre for
Fabri, Jane Tournois, Mariette Yvinec and Sylvain Lefèbvre for
helpful comments and discussions.
*/

View File

@ -130,7 +130,7 @@ public:
// constructors
/*!
\tparam Iterator an input iterator with `Id` as value type.
Constructs a primitive.
constructs a primitive.
If `VertexPointPMap` is the default of the class, an additional constructor
is available with `vppm` set to `get(vertex_point, graph)`.
*/
@ -142,7 +142,7 @@ public:
{}
/*!
Constructs a primitive.
constructs a primitive.
If `VertexPointPMap` is the default of the class, an additional constructor
is available with `vppm` set to `get(vertex_point, graph)`.
*/

View File

@ -141,7 +141,7 @@ public:
typedef typename boost::graph_traits<HalfedgeGraph>::edge_descriptor edge_descriptor;
/*!
Constructs a primitive.
constructs a primitive.
\tparam Iterator is an input iterator with `Id` as value type.
This \ref AABB_tree/AABB_halfedge_graph_edge_example.cpp "example" gives a way to call this constructor
using the insert-by-range method of the class `AABB_tree<Traits>`.
@ -156,7 +156,7 @@ public:
{}
/*!
Constructs a primitive.
constructs a primitive.
If `VertexPointPMap` is the default of the class, an additional constructor
is available with `vppm` set to `boost::get(vertex_point, graph)`.
*/

View File

@ -112,14 +112,14 @@ struct AABB_primitive
/// @}
/*!
Constructs a primitive and initializes the property maps.
constructs a primitive and initializes the property maps.
*/
AABB_primitive(Id id,
ObjectPropertyMap o_pmap=ObjectPropertyMap(),
PointPropertyMap p_pmap=PointPropertyMap());
/*!
Constructs a primitive from an iterator with `Id` as value type
constructs a primitive from an iterator with `Id` as value type
and initializes the property maps.
*/
template <class Iterator>

View File

@ -88,7 +88,7 @@ class AABB_segment_primitive
Tag_false,
CacheDatum > Base;
public:
///Constructor from an iterator
///constructor from an iterator
AABB_segment_primitive(Iterator it) : Base(it){}
};

View File

@ -39,7 +39,7 @@ namespace CGAL {
/// @{
/**
* Class AABB_tree is a static data structure for efficient
* Static data structure for efficient
* intersection and distance computations in 3D. It builds a
* hierarchy of axis-aligned bounding boxes (an AABB tree) from a set
* of 3D geometric objects, and can receive intersection and distance
@ -61,6 +61,8 @@ namespace CGAL {
// type of the primitives container
typedef std::vector<typename AABBTraits::Primitive> Primitives;
typedef internal::Primitive_helper<AABBTraits> Helper;
public:
typedef AABBTraits AABB_traits;
@ -107,7 +109,7 @@ namespace CGAL {
/// \name Creation
///@{
/// Constructs an empty tree, and initializes the internally stored traits
/// constructs an empty tree, and initializes the internally stored traits
/// class using `traits`.
AABB_tree(const AABBTraits& traits = AABBTraits());
@ -116,39 +118,45 @@ namespace CGAL {
* @param first iterator over first primitive to insert
* @param beyond past-the-end iterator
*
* It is equivalent to constructing an empty tree and calling `insert(first,last,t...)`.
* constructs an empty tree followed by a call to `insert(first,last,t...)`.
* The tree stays empty if the memory allocation is not successful.
*/
template<typename InputIterator,typename ... T>
AABB_tree(InputIterator first, InputIterator beyond,T&& ...);
/// After one or more calls to `insert()` the internal data
/// structure of the tree must be reconstructed. This procedure
/// has a complexity of \f$O(n log(n))\f$, where \f$n\f$ is the number of
/// primitives of the tree. This procedure is called implicitly
/// at the first call to a query member function. You can call
/// `build()` explicitly to ensure that the next call to
/// query functions will not trigger the reconstruction of the
/// data structure.
/// A call to `AABBTraits::set_shared_data(t...)`
/// is made using the internally stored traits.
/// triggers the (re)construction of the internal tree structure.
/// The internal tree structure is automatically invalidated by the insertion of any primitives
/// after one or more calls to `insert()`.
/// This procedure is called implicitly at the first call to a query member function.
/// An explicit call to `build()` must be made to ensure that the next call to
/// a query function will not trigger the construction of the data structure.
/// A call to `AABBTraits::set_shared_data(t...)` is made using the internally stored traits.
/// This procedure has a complexity of \f$O(n log(n))\f$, where \f$n\f$ is the number of
/// primitives of the tree.
template<typename ... T>
void build(T&& ...);
#ifndef DOXYGEN_RUNNING
void build();
/// triggers the (re)construction of the tree similarly to a call to `build()`
/// but the traits functors `Compute_bbox` and `Split_primitives` are ignored
/// and `compute_bbox` and `split_primitives` are used instead.
template <class ComputeBbox, class SplitPrimitives>
void custom_build(const ComputeBbox& compute_bbox,
const SplitPrimitives& split_primitives);
#endif
///@}
/// \name Operations
///@{
/// Equivalent to calling `clear()` and then `insert(first,last,t...)`.
/// is equivalent to calling `clear()`, `insert(first,last,t...)`, and `build()`
template<typename ConstPrimitiveIterator,typename ... T>
void rebuild(ConstPrimitiveIterator first, ConstPrimitiveIterator beyond,T&& ...);
/// Add a sequence of primitives to the set of primitives of the AABB tree.
/// `%InputIterator` is any iterator and the parameter pack `T` are any types
/// adds a sequence of primitives to the set of primitives of the AABB tree.
/// `%InputIterator` is any iterator and the parameter pack `T` contains any types
/// such that `Primitive` has a constructor with the following signature:
/// `Primitive(%InputIterator, T...)`. If `Primitive` is a model of the concept
/// `AABBPrimitiveWithSharedData`, a call to `AABBTraits::set_shared_data(t...)`
@ -156,30 +164,31 @@ namespace CGAL {
template<typename InputIterator,typename ... T>
void insert(InputIterator first, InputIterator beyond,T&& ...);
/// Adds a primitive to the set of primitives of the tree.
/// adds a primitive to the set of primitives of the tree.
inline void insert(const Primitive& p);
/// Clears and destroys the tree.
/// clears and destroys the tree.
~AABB_tree()
{
clear();
}
/// Returns a const reference to the internally stored traits class.
/// returns a const reference to the internally stored traits class.
const AABBTraits& traits() const{
return m_traits;
}
/// Clears the tree.
/// clears the tree and the search tree if it was constructed,
/// and switches on the usage of the search tree to find the hint for the distance queries
void clear()
{
// clear AABB tree
clear_nodes();
m_primitives.clear();
clear_search_tree();
m_default_search_tree_constructed = true;
m_use_default_search_tree = true;
}
/// Returns the axis-aligned bounding box of the whole tree.
/// returns the axis-aligned bounding box of the whole tree.
/// \pre `!empty()`
const Bounding_box bbox() const {
CGAL_precondition(!empty());
@ -190,10 +199,10 @@ namespace CGAL {
m_primitives.end());
}
/// Returns the number of primitives in the tree.
/// returns the number of primitives in the tree.
size_type size() const { return m_primitives.size(); }
/// Returns \c true, iff the tree contains no primitive.
/// returns \c true, iff the tree contains no primitive.
bool empty() const { return m_primitives.empty(); }
///@}
@ -209,47 +218,46 @@ namespace CGAL {
set_primitive_data_impl(CGAL::Boolean_tag<internal::Has_nested_type_Shared_data<Primitive>::value>(),std::forward<T>(t)...);
}
bool build_kd_tree() const;
bool build_kd_tree();
template<typename ConstPointIterator>
bool build_kd_tree(ConstPointIterator first, ConstPointIterator beyond) const;
bool build_kd_tree(ConstPointIterator first, ConstPointIterator beyond);
public:
/// \name Intersection Tests
///@{
/// Returns `true`, iff the query intersects at least one of
/// the input primitives. \tparam Query must be a type for
/// which `do_intersect` predicates are
/// defined in the traits class `AABBTraits`.
/// returns `true`, iff the query intersects at least one of
/// the input primitives.
/// \tparam Query must be a type for which `Do_intersect` operators are
/// defined in the traits class `AABBTraits`.
template<typename Query>
bool do_intersect(const Query& query) const;
/// Returns the number of primitives intersected by the
/// query. \tparam Query must be a type for which
/// `do_intersect` predicates are defined
/// in the traits class `AABBTraits`.
/// returns the number of primitives intersected by the
/// query.
/// \tparam Query must be a type for which `Do_intersect` operators are
/// defined in the traits class `AABBTraits`.
template<typename Query>
size_type number_of_intersected_primitives(const Query& query) const;
/// Outputs to the iterator the list of all intersected primitives
/// ids. This function does not compute the intersection points
/// puts in `out` the ids of all intersected primitives.
/// This function does not compute the intersection points
/// and is hence faster than the function `all_intersections()`
/// function below. \tparam Query must be a type for which
/// `do_intersect` predicates are defined
/// in the traits class `AABBTraits`.
/// function below.
/// \tparam Query must be a type for which `Do_intersect` operators are
/// defined in the traits class `AABBTraits`.
template<typename Query, typename OutputIterator>
OutputIterator all_intersected_primitives(const Query& query, OutputIterator out) const;
/// Returns the intersected primitive id that is encountered first
/// returns the id of the intersected primitive that is encountered first
/// in the tree traversal, iff
/// the query intersects at least one of the input primitives. No
/// particular order is guaranteed over the tree traversal, such
/// that, e.g, the primitive returned is not necessarily the
/// closest from the source point of a ray query. \tparam Query
/// must be a type for which
/// `do_intersect` predicates are defined
/// in the traits class `AABBTraits`.
/// closest from the source point of a ray query.
/// \tparam Query must be a type for which `Do_intersect` operators are
/// defined in the traits class `AABBTraits`.
template <typename Query>
boost::optional<Primitive_id> any_intersected_primitive(const Query& query) const;
///@}
@ -257,30 +265,29 @@ public:
/// \name Intersections
///@{
/// Outputs the list of all intersections, as objects of
/// puts in `out` all intersections, as objects of
/// `Intersection_and_primitive_id<Query>::%Type`,
/// between the query and the input data to
/// the iterator. `do_intersect()`
/// predicates and intersections must be defined for `Query`
/// in the `AABBTraits` class.
/// the iterator.
/// \tparam Query must be a type for which `Do_intersect` and `Intersection` operators are
/// defined in the traits class `AABBTraits`.
template<typename Query, typename OutputIterator>
OutputIterator all_intersections(const Query& query, OutputIterator out) const;
/// Returns the intersection that is encountered first
/// returns if any the intersection that is encountered first
/// in the tree traversal. No particular
/// order is guaranteed over the tree traversal, e.g, the
/// primitive returned is not necessarily the closest from the
/// source point of a ray query. Type `Query` must be a type
/// for which `do_intersect` predicates
/// and intersections are defined in the traits class AABBTraits.
/// primitive returned is not necessarily the closest from the query.
/// \tparam Query must be a type for which `Do_intersect` and `Intersection` operators are
/// defined in the traits class `AABBTraits`.
template <typename Query>
boost::optional< typename Intersection_and_primitive_id<Query>::Type >
any_intersection(const Query& query) const;
/// Returns the intersection and primitive id closest to the source point of the ray
/// returns the intersection and primitive id closest to the source point of the ray
/// query.
/// \tparam Ray must be the same as `AABBTraits::Ray_3` and
/// `do_intersect` predicates and intersections for it must be
@ -311,7 +318,7 @@ public:
}
/// \endcond
/// Returns the primitive id closest to the source point of the ray
/// returns the primitive id closest to the source point of the ray
/// query.
/// \tparam Ray must be the same as `AABBTraits::Ray_3` and
/// `do_intersect` predicates and intersections for it must be
@ -340,31 +347,22 @@ public:
/// \name Distance Queries
///@{
/// Returns the minimum squared distance between the query point
/// and all input primitives. Method
/// `accelerate_distance_queries()` should be called before the
/// first distance query, so that an internal secondary search
/// structure is build, for improving performance.
/// returns the minimum squared distance between the query point
/// and all input primitives.
/// \pre `!empty()`
FT squared_distance(const Point& query) const;
/// Returns the point in the union of all input primitives which
/// returns the point in the union of all input primitives which
/// is closest to the query. In case there are several closest
/// points, one arbitrarily chosen closest point is
/// returned. Method `accelerate_distance_queries()` should be
/// called before the first distance query, so that an internal
/// secondary search structure is build, for improving
/// performance.
/// returned.
/// \pre `!empty()`
Point closest_point(const Point& query) const;
/// Returns a `Point_and_primitive_id` which realizes the
/// returns a `Point_and_primitive_id` which realizes the
/// smallest distance between the query point and all input
/// primitives. Method `accelerate_distance_queries()` should be
/// called before the first distance query, so that an internal
/// secondary search structure is build, for improving
/// performance.
/// primitives.
/// \pre `!empty()`
Point_and_primitive_id closest_point_and_primitive(const Point& query) const;
@ -404,19 +402,18 @@ public:
/// one may want to provide a much better hint than a vertex of
/// the triangle soup could be. It could be, for example, the
/// barycenter of one of the triangles. But, except with the use
/// of an exact constructions kernel, one cannot easily construct
/// of a kernel with exact constructions, one cannot easily construct
/// points other than the vertices, that lie exactly on a triangle
/// soup. Hence, providing a good hint sometimes means not being
/// able to provide it exactly on the primitives. In rare
/// occasions, this hint can be returned as the closest point.
/// In order to accelerate distance queries significantly, the
/// AABB tree builds an internal KD-tree containing a set of
/// potential hints, when the method
/// `accelerate_distance_queries()` is called. This KD-tree
/// provides very good hints that allow the algorithms to run much
/// faster than with a default hint (such as the
/// `reference_point` of the first primitive). The set of
/// potential hints is a sampling of the union of the primitives,
/// potential hints. This KD-tree provides very good hints
/// that allow the algorithms to run much faster than
/// when `do_not_accelerate_distance_queries()` that makes the
/// hint to always be the `reference_point` of the first primitive.
/// The set of potential hints is a sampling of the union of the primitives,
/// which is obtained, by default, by calling the method
/// `reference_point` of each of the primitives. However, such
/// a sampling with one point per primitive may not be the most
@ -424,45 +421,46 @@ public:
/// inserting more than one sample on them. Conversely, a sparser
/// sampling with less than one point per input primitive is
/// relevant in some cases.
/// The internal KD-tree is always used if no call to `do_not_accelerate_distance_queries()`
/// was made since object creation or the last call to `clear()`. It will be built by
/// the first distance query or by a call to `accelerate_distance_queries()`.
///@{
/// Constructs internal search tree from
/// constructs the internal search tree from
/// 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.
void do_not_accelerate_distance_queries() const;
bool accelerate_distance_queries();
/// turns off the usage of the internal search tree and clears it if it was already constructed.
void do_not_accelerate_distance_queries();
/// Constructs an internal KD-tree containing the specified point
/// constructs an internal KD-tree containing the specified point
/// set, to be used as the set of potential hints for accelerating
/// the distance queries.
/// the distance queries. Note that the search tree built in
/// this function will not be invalidated by the insertion of a new
/// primitive, and an explicit call to `accelerate_distance_queries()`
/// is needed to update the search tree.
/// \tparam ConstPointIterator is an iterator with
/// value type `Point_and_primitive_id`.
template<typename ConstPointIterator>
bool accelerate_distance_queries(ConstPointIterator first, ConstPointIterator beyond) const
bool accelerate_distance_queries(ConstPointIterator first, ConstPointIterator beyond)
{
#ifdef CGAL_HAS_THREADS
//this ensures that this is done once at a time
CGAL_SCOPED_LOCK(kd_tree_mutex);
#endif
clear_search_tree();
m_default_search_tree_constructed = false; // not a default kd-tree
m_use_default_search_tree = false;
return build_kd_tree(first,beyond);
}
/// Returns the minimum squared distance between the query point
/// returns the minimum squared distance between the query point
/// and all input primitives. The internal KD-tree is not used.
/// \pre `!empty()`
FT squared_distance(const Point& query, const Point& hint) const;
/// Returns the point in the union of all input primitives which
/// returns the point in the union of all input primitives which
/// is closest to the query. In case there are several closest
/// points, one arbitrarily chosen closest point is returned. The
/// internal KD-tree is not used.
/// \pre `!empty()`
Point closest_point(const Point& query, const Point& hint) const;
/// Returns a `Point_and_primitive_id` which realizes the
/// returns a `Point_and_primitive_id` which realizes the
/// smallest distance between the query point and all input
/// primitives. The internal KD-tree is not used.
/// \pre `!empty()`
@ -484,15 +482,23 @@ public:
}
// clears internal KD tree
void clear_search_tree() const
void clear_search_tree()
{
#ifdef CGAL_HAS_THREADS
if ( m_atomic_search_tree_constructed.load(std::memory_order_relaxed) )
#else
if ( m_search_tree_constructed )
#endif
{
CGAL_assertion( m_p_search_tree!=nullptr );
delete m_p_search_tree;
m_p_search_tree = nullptr;
#ifdef CGAL_HAS_THREADS
m_atomic_search_tree_constructed.store(false, std::memory_order_relaxed);
#else
m_search_tree_constructed = false;
}
#endif
}
}
public:
@ -523,31 +529,43 @@ public:
{
CGAL_assertion(!empty());
return Point_and_primitive_id(
internal::Primitive_helper<AABB_traits>::get_reference_point(m_primitives[0],m_traits), m_primitives[0].id()
Helper::get_reference_point(m_primitives[0],m_traits), m_primitives[0].id()
);
}
public:
Point_and_primitive_id best_hint(const Point& query) const
{
#ifdef CGAL_HAS_THREADS
bool m_search_tree_constructed = m_atomic_search_tree_constructed.load(std::memory_order_acquire);
#endif
// lazily build the search tree in case the default should be used
if (m_use_default_search_tree && !m_search_tree_constructed)
{
#ifdef CGAL_HAS_THREADS
CGAL_SCOPED_LOCK(build_mutex);
m_search_tree_constructed = m_atomic_search_tree_constructed.load(std::memory_order_relaxed);
if (!m_search_tree_constructed)
#endif
m_search_tree_constructed = const_cast<AABB_tree*>(this)->build_kd_tree();
}
if(m_search_tree_constructed)
{
return m_p_search_tree->closest_point(query);
}
else
return this->any_reference_point_and_id();
}
//! Returns the datum (geometric object) represented `p`.
#ifndef DOXYGEN_RUNNING
typename internal::Primitive_helper<AABBTraits>::Datum_type
typename Helper::Datum_type
#else
typename AABBTraits::Primitive::Datum_reference
#endif
datum(Primitive& p)const
{
return internal::Primitive_helper<AABBTraits>::
get_datum(p, this->traits());
return Helper::get_datum(p, this->traits());
}
private:
@ -556,21 +574,25 @@ public:
// set of input primitives
Primitives m_primitives;
// single root node
Node* m_p_root_node;
Node* m_p_root_node = nullptr;
#ifdef CGAL_HAS_THREADS
mutable CGAL_MUTEX internal_tree_mutex;//mutex used to protect const calls inducing build()
mutable CGAL_MUTEX kd_tree_mutex;//mutex used to protect calls to accelerate_distance_queries
mutable CGAL_MUTEX build_mutex; // mutex used to protect const calls inducing build() and build_kd_tree()
#endif
const Node* root_node() const {
CGAL_assertion(size() > 1);
#ifdef CGAL_HAS_THREADS
bool m_need_build = m_atomic_need_build.load(std::memory_order_acquire);
#endif
if(m_need_build){
#ifdef CGAL_HAS_THREADS
#ifdef CGAL_HAS_THREADS
//this ensures that build() will be called once
CGAL_SCOPED_LOCK(internal_tree_mutex);
CGAL_SCOPED_LOCK(build_mutex);
m_need_build = m_atomic_need_build.load(std::memory_order_relaxed);
if(m_need_build)
#endif
const_cast< AABB_tree<AABBTraits>* >(this)->build();
#endif
const_cast< AABB_tree<AABBTraits>* >(this)->build();
}
return m_p_root_node;
}
@ -581,10 +603,15 @@ public:
}
// search KD-tree
mutable const Search_tree* m_p_search_tree;
mutable bool m_search_tree_constructed;
mutable bool m_default_search_tree_constructed; // indicates whether the internal kd-tree should be built
bool m_need_build;
const Search_tree* m_p_search_tree = nullptr;
bool m_use_default_search_tree = true; // indicates whether the internal kd-tree should be built
#ifdef CGAL_HAS_THREADS
std::atomic<bool> m_atomic_need_build;
std::atomic<bool> m_atomic_search_tree_constructed;
#else
bool m_need_build = false;
mutable bool m_search_tree_constructed = false;
#endif
private:
// Disabled copy constructor & assignment operator
@ -599,12 +626,10 @@ public:
template<typename Tr>
AABB_tree<Tr>::AABB_tree(const Tr& traits)
: m_traits(traits)
, m_primitives()
, m_p_root_node(nullptr)
, m_p_search_tree(nullptr)
, m_search_tree_constructed(false)
, m_default_search_tree_constructed(true)
, m_need_build(false)
#ifdef CGAL_HAS_THREADS
, m_atomic_need_build(false)
, m_atomic_search_tree_constructed(false)
#endif
{}
template<typename Tr>
@ -612,13 +637,10 @@ public:
AABB_tree<Tr>::AABB_tree(ConstPrimitiveIterator first,
ConstPrimitiveIterator beyond,
T&& ... t)
: m_traits()
, m_primitives()
, m_p_root_node(nullptr)
, m_p_search_tree(nullptr)
, m_search_tree_constructed(false)
, m_default_search_tree_constructed(true)
, m_need_build(false)
#ifdef CGAL_HAS_THREADS
: m_atomic_need_build(false)
, m_atomic_search_tree_constructed(false)
#endif
{
// Insert each primitive into tree
insert(first, beyond,std::forward<T>(t)...);
@ -630,13 +652,19 @@ public:
ConstPrimitiveIterator beyond,
T&& ... t)
{
if (m_use_default_search_tree && first!=beyond)
clear_search_tree();
set_shared_data(std::forward<T>(t)...);
while(first != beyond)
{
m_primitives.push_back(Primitive(first,std::forward<T>(t)...));
++first;
}
#ifdef CGAL_HAS_THREADS
m_atomic_need_build.store(true, std::memory_order_relaxed);
#else
m_need_build = true;
#endif
}
// Clears tree and insert a set of primitives
@ -655,24 +683,40 @@ public:
build();
}
template<typename Tr>
template<typename ... T>
void AABB_tree<Tr>::build(T&& ... t)
{
set_shared_data(std::forward<T>(t)...);
build();
}
template<typename Tr>
template<typename ... T>
void AABB_tree<Tr>::build(T&& ... t)
{
set_shared_data(std::forward<T>(t)...);
build();
}
template<typename Tr>
void AABB_tree<Tr>::insert(const Primitive& p)
{
if (m_use_default_search_tree)
clear_search_tree();
m_primitives.push_back(p);
#ifdef CGAL_HAS_THREADS
m_atomic_need_build.store(true, std::memory_order_relaxed);
#else
m_need_build = true;
#endif
}
// Build the data structure, after calls to insert(..)
template<typename Tr>
void AABB_tree<Tr>::build()
{
custom_build(m_traits.compute_bbox_object(),
m_traits.split_primitives_object());
}
#ifndef DOXYGEN_RUNNING
// Build the data structure, after calls to insert(..)
template<typename Tr>
template <class ComputeBbox, class SplitPrimitives>
void AABB_tree<Tr>::custom_build(
const ComputeBbox& compute_bbox,
const SplitPrimitives& split_primitives)
{
clear_nodes();
if(m_primitives.size() > 1) {
@ -689,37 +733,31 @@ public:
// constructs the tree
m_p_root_node->expand(m_primitives.begin(), m_primitives.end(),
m_primitives.size(), m_traits);
}
// 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 && !empty()){
build_kd_tree();
m_primitives.size(),
compute_bbox,
split_primitives,
m_traits);
}
#ifdef CGAL_HAS_THREADS
m_atomic_need_build.store(false, std::memory_order_release); // in case build() is triggered by a call to root_node()
#else
m_need_build = false;
#endif
}
#endif
// constructs the search KD tree from given points
// to accelerate the distance queries
template<typename Tr>
bool AABB_tree<Tr>::build_kd_tree() const
bool AABB_tree<Tr>::build_kd_tree()
{
// iterate over primitives to get reference points on them
std::vector<Point_and_primitive_id> points;
points.reserve(m_primitives.size());
typename Primitives::const_iterator it;
for(it = m_primitives.begin(); it != m_primitives.end(); ++it)
points.push_back( Point_and_primitive_id(
internal::Primitive_helper<AABB_traits>::get_reference_point(
*it,m_traits), it->id() ) );
for(const Primitive& p : m_primitives)
points.push_back( Point_and_primitive_id( Helper::get_reference_point(p, m_traits), p.id() ) );
// clears current KD tree
clear_search_tree();
bool res = build_kd_tree(points.begin(), points.end());
m_default_search_tree_constructed = true;
return res;
return build_kd_tree(points.begin(), points.end());
}
// constructs the search KD tree from given points
@ -727,13 +765,18 @@ public:
template<typename Tr>
template<typename ConstPointIterator>
bool AABB_tree<Tr>::build_kd_tree(ConstPointIterator first,
ConstPointIterator beyond) const
ConstPointIterator beyond)
{
clear_search_tree();
m_p_search_tree = new Search_tree(first, beyond);
m_default_search_tree_constructed = true;
if(m_p_search_tree != nullptr)
{
#ifdef CGAL_HAS_THREADS
m_atomic_search_tree_constructed.store(true, std::memory_order_release); // in case build_kd_tree() is triggered by a call to best_hint()
#else
m_search_tree_constructed = true;
#endif
return true;
}
else
@ -744,41 +787,20 @@ public:
}
template<typename Tr>
void AABB_tree<Tr>::do_not_accelerate_distance_queries()const
void AABB_tree<Tr>::do_not_accelerate_distance_queries()
{
clear_search_tree();
m_default_search_tree_constructed = false;
m_use_default_search_tree = false;
}
// constructs the search KD tree from internal primitives
template<typename Tr>
bool AABB_tree<Tr>::accelerate_distance_queries() const
bool AABB_tree<Tr>::accelerate_distance_queries()
{
m_use_default_search_tree = true;
if(m_primitives.empty()) return true;
if (m_default_search_tree_constructed)
{
if (!m_need_build) return m_search_tree_constructed;
return true; // default return type, no tree built
}
if(!m_need_build) // the tree was already built, build the kd-tree
{
#ifdef CGAL_HAS_THREADS
//this ensures that this function will be done once
CGAL_SCOPED_LOCK(kd_tree_mutex);
#endif
if (!m_need_build)
{
// clears current KD tree
clear_search_tree();
bool res = build_kd_tree();
m_default_search_tree_constructed = true;
return res;
};
}
m_default_search_tree_constructed = true;
return m_search_tree_constructed;
return build_kd_tree();
}
template<typename Tr>

View File

@ -88,7 +88,7 @@ class AABB_triangle_primitive
Tag_false,
CacheDatum > Base;
public:
///Constructor from an iterator
///constructor from an iterator
AABB_triangle_primitive(Iterator it) : Base(it){}
};

View File

@ -56,10 +56,12 @@ public:
*
* [first,last[ is the range of primitives to be added to the tree.
*/
template<typename ConstPrimitiveIterator>
template<typename ConstPrimitiveIterator, typename ComputeBbox, typename SplitPrimitives>
void expand(ConstPrimitiveIterator first,
ConstPrimitiveIterator beyond,
const std::size_t range,
const ComputeBbox& compute_bbox,
const SplitPrimitives& split_primitives,
const AABBTraits&);
/**
@ -117,19 +119,20 @@ private:
}; // end class AABB_node
template<typename Tr>
template<typename ConstPrimitiveIterator>
template<typename ConstPrimitiveIterator, typename ComputeBbox, typename SplitPrimitives>
void
AABB_node<Tr>::expand(ConstPrimitiveIterator first,
ConstPrimitiveIterator beyond,
const std::size_t range,
const ComputeBbox& compute_bbox,
const SplitPrimitives& split_primitives,
const Tr& traits)
{
m_bbox = traits.compute_bbox_object()(first, beyond);
m_bbox = compute_bbox(first, beyond);
// sort primitives along longest axis aabb
traits.split_primitives_object()(first, beyond, m_bbox);
split_primitives(first, beyond, m_bbox);
switch(range)
{
@ -140,14 +143,14 @@ AABB_node<Tr>::expand(ConstPrimitiveIterator first,
case 3:
m_p_left_child = &(*first);
m_p_right_child = static_cast<Node*>(this)+1;
right_child().expand(first+1, beyond, 2,traits);
right_child().expand(first+1, beyond, 2, compute_bbox, split_primitives, traits);
break;
default:
const std::size_t new_range = range/2;
m_p_left_child = static_cast<Node*>(this) + 1;
m_p_right_child = static_cast<Node*>(this) + new_range;
left_child().expand(first, first + new_range, new_range,traits);
right_child().expand(first + new_range, beyond, range - new_range,traits);
left_child().expand(first, first + new_range, new_range, compute_bbox, split_primitives, traits);
right_child().expand(first + new_range, beyond, range - new_range, compute_bbox, split_primitives, traits);
}
}

View File

@ -430,7 +430,11 @@ public:
Curve_analysis_2 operator()
(const Polynomial_2& f) const {
return _m_kernel->curve_cache_2()(f);
if (_m_kernel->is_square_free_2_object()(f)) {
return _m_kernel->curve_cache_2()(f);
} else {
return _m_kernel->curve_cache_2()(_m_kernel->make_square_free_2_object()(f));
}
}
protected:

View File

@ -109,10 +109,10 @@ QRectF ArrangementDemoGraphicsView::getViewportRect( ) const
QPointF p1 = this->mapToScene( 0, 0 );
QPointF p2 = this->mapToScene( this->width( ), this->height( ) );
double xmin = std::min( p1.x( ), p2.x( ) );
double xmax = std::max( p1.x( ), p2.x( ) );
double ymin = std::min( p1.y( ), p2.y( ) );
double ymax = std::max( p1.y( ), p2.y( ) );
double xmin = (std::min)( p1.x( ), p2.x( ) );
double xmax = (std::max)( p1.x( ), p2.x( ) );
double ymin = (std::min)( p1.y( ), p2.y( ) );
double ymax = (std::max)( p1.y( ), p2.y( ) );
QRectF res = QRectF( QPointF( xmin, ymin ), QPointF( xmax, ymax ) );

View File

@ -285,8 +285,8 @@ virtual void before_split_face (Face_handle f,
Halfedge_handle e);
/*!
issued immediately after the existing face `f1` has been split,
such that a portion of it now forms a new face `f2`. The flag
issued immediately after the existing face `f1` has been split
into the two faces `f1` and `f2`. The flag
`is_hole` designates whether `f2` forms a hole inside `f1`.
*/
virtual void after_split_face (Face_handle f1,

View File

@ -1927,8 +1927,13 @@ public:
const Kernel* kernel = m_traits;
typename Kernel::Equal_3 equal = kernel->equal_3_object();
// Down cast to pass to kernel member functions
const Direction_3& xc1_left = xc1.left();
const Direction_3& xc2_left = xc2.left();
const Direction_3& xc1_right = xc1.right();
const Direction_3& xc2_right = xc2.right();
if (xc1.is_degenerate() && xc2.is_degenerate())
return equal(xc1.left(), xc2.left());
return equal(xc1_left, xc2_left);
if ((xc1.is_full() || xc1.is_meridian()) && xc2.is_degenerate())
return xc1.has_on(xc2.left());
if ((xc2.is_full() || xc2.is_meridian()) && xc1.is_degenerate())
@ -1941,8 +1946,8 @@ public:
if (!equal(normal1, normal2) && !equal(opposite_normal1, normal2))
return false;
bool eq1 = equal(xc1.right(), xc2.left());
bool eq2 = equal(xc1.left(), xc2.right());
bool eq1 = equal(xc1_right, xc2_left);
bool eq2 = equal(xc1_left, xc2_right);
#if defined(CGAL_FULL_X_MONOTONE_GEODESIC_ARC_ON_SPHERE_IS_SUPPORTED)
if (eq1 && eq2) return true;
@ -2001,14 +2006,20 @@ public:
const Kernel* kernel = m_traits;
typename Kernel::Equal_3 equal = kernel->equal_3_object();
// Down cast to pass to kernel member functions
const Direction_3& xc1_right = xc1.right();
const Direction_3& xc2_left = xc2.left();
xc.set_is_degenerate(false);
xc.set_is_empty(false);
xc.set_is_vertical(xc1.is_vertical());
bool eq1 = equal(xc1.right(), xc2.left());
bool eq1 = equal(xc1_right, xc2_left);
#if defined(CGAL_FULL_X_MONOTONE_GEODESIC_ARC_ON_SPHERE_IS_SUPPORTED)
bool eq2 = equal(xc1.left(), xc2.right());
const Direction_3& xc1_left = xc1.left();
const Direction_3& xc2_right = xc2.right();
bool eq2 = equal(xc1_left, xc2_right);
if (eq1 && eq2) {
const Point_2& p =
xc1.source().is_mid_boundary() ? xc1.source() : xc1.target();
@ -2017,8 +2028,10 @@ public:
xc.set_normal(xc1.normal());
xc.set_is_full(true);
}
#else
CGAL_assertion_code(const Direction_3& xc1_left = xc1.left();
const Direction_3& xc2_right = xc2.right());
#endif
if (xc1.is_directed_right() || xc2.is_directed_right()) {
xc.set_normal(xc1.is_directed_right() ? xc1.normal() : xc2.normal());
xc.set_is_directed_right(true);
@ -2026,20 +2039,23 @@ public:
if (eq1) {
xc.set_source(xc1.left());
xc.set_target(xc2.right());
} else {
CGAL_assertion(equal(xc1.left(), xc2.right()));
}
else {
CGAL_assertion(equal(xc1_left, xc2_right));
xc.set_source(xc2.left());
xc.set_target(xc1.right());
}
} else {
}
else {
xc.set_normal(xc1.normal());
xc.set_is_directed_right(false);
if (eq1) {
xc.set_source(xc2.right());
xc.set_target(xc1.left());
} else {
CGAL_assertion(equal(xc1.left(), xc2.right()));
}
else {
CGAL_assertion(equal(xc1_left, xc2_right));
xc.set_source(xc1.right());
xc.set_target(xc2.left());
}

View File

@ -950,11 +950,12 @@ _Bezier_x_monotone_2<RatKer, AlgKer, NtTrt, BndTrt>::point_position
if ( p.is_rational() ){
const Rational& px = ((Rat_point_2) p).x();
const Rational px = ((Rat_point_2) p).x();
Integer denom_px=nt_traits.denominator(px);
Integer numer_px=nt_traits.numerator(px);
Polynomial poly_px = CGAL::sign(numer_px) == ZERO ? Polynomial() : nt_traits.construct_polynomial(&numer_px,0);
Integer poly_px_scale = numer_px * _curve.x_norm();
Polynomial poly_px = CGAL::sign(numer_px) == ZERO ? Polynomial() : nt_traits.construct_polynomial(&poly_px_scale,0);
Polynomial poly_x = nt_traits.scale(_curve.x_polynomial(),denom_px) - poly_px;
std::vector <Algebraic> roots;

View File

@ -142,7 +142,7 @@ public:
private:
Trpz_parameter_space* ptr() const { return (Trpz_parameter_space*)(PTR); }
Trpz_parameter_space* ptr() const { return (Trpz_parameter_space*)(PTR.p); }
#ifndef CGAL_TD_DEBUG
@ -323,7 +323,7 @@ public:
{
//define the initial trapezoid: left, right, btm, top are at infinity.
// its type is TD_TRAPEZOID ,it is on all boundaries, and has no neighbours
PTR = new Trpz_parameter_space
PTR.p = new Trpz_parameter_space
(Traits::vtx_at_left_infinity(),
Traits::vtx_at_right_infinity(),
Traits::he_at_bottom_infinity(),
@ -353,7 +353,7 @@ public:
else //tp == TD_VERTEX
type_flag |= CGAL_TD_VERTEX;
PTR = new Trpz_parameter_space
PTR.p = new Trpz_parameter_space
(l, r, b, t, type_flag | boundness_flag, lb, lt, rb, rt);
m_dag_node = node;
}
@ -370,7 +370,7 @@ public:
Self* rb = 0, Self* rt = 0,
Dag_node* node = 0)
{
PTR = new Trpz_parameter_space
PTR.p = new Trpz_parameter_space
(l ? *l : Traits::vtx_at_left_infinity(),
r ? *r : Traits::vtx_at_right_infinity(),
b ? *b : Traits::he_at_bottom_infinity(),
@ -436,7 +436,7 @@ public:
/*! Access the trapezoid id (PTR). */
CGAL_TD_INLINE unsigned long id() const
{
return (unsigned long) PTR;
return (unsigned long) PTR.p;
}
/*! Access trapezoid left. */

View File

@ -135,7 +135,7 @@ public:
private:
Data* ptr() const { return (Data*)(PTR); }
Data* ptr() const { return (Data*)(PTR.p); }
#ifndef CGAL_TD_DEBUG
@ -194,7 +194,7 @@ public:
Td_active_edge ()
{
PTR = new Data
PTR.p = new Data
(Traits::empty_he_handle(), Td_map_item(0), nullptr);
//m_dag_node = nullptr;
}
@ -204,7 +204,7 @@ public:
boost::optional<Td_map_item&> next = boost::none)
{
PTR = new Data(he, (next) ? *next : Td_map_item(0), node);
PTR.p = new Data(he, (next) ? *next : Td_map_item(0), node);
//m_dag_node = node;
}
@ -261,7 +261,7 @@ public:
/*! Access the trapezoid id (PTR). */
CGAL_TD_INLINE unsigned long id() const
{
return (unsigned long) PTR;
return (unsigned long) PTR.p;
}

View File

@ -129,7 +129,7 @@ public:
};
private:
Data* ptr() const { return (Data*)(PTR); }
Data* ptr() const { return (Data*)(PTR.p); }
Curve_end vtx_to_ce(Vertex_const_handle v) const
{
@ -180,14 +180,14 @@ public:
Td_active_fictitious_vertex()
{
PTR = new Data(Traits::empty_vtx_handle(), Traits::empty_he_handle(), nullptr);
PTR.p = new Data(Traits::empty_vtx_handle(), Traits::empty_he_handle(), nullptr);
}
/*! Constructor given Vertex & Halfedge handles. */
Td_active_fictitious_vertex(Vertex_const_handle v,
Halfedge_const_handle cw_he,
Dag_node* node = 0)
{ PTR = new Data(v, cw_he, node); }
{ PTR.p = new Data(v, cw_he, node); }
/*! Copy constructor. */
@ -224,7 +224,7 @@ public:
inline const Self& self() const { return *this; }
/*! Access the trapezoid id (PTR). */
inline unsigned long id() const { return (unsigned long) PTR; }
inline unsigned long id() const { return (unsigned long) PTR.p; }
/*! Access trapezoid left.
* filters out the infinite case which returns predefined dummy values

View File

@ -144,7 +144,7 @@ public:
private:
Data* ptr() const { return (Data*)(PTR); }
Data* ptr() const { return (Data*)(PTR.p); }
public:
@ -255,7 +255,7 @@ private:
{
//define the initial trapezoid: left, right, btm, top are at infinity.
// has no neighbours
PTR = new Data
PTR.p = new Data
(Traits::empty_vtx_handle(),
Traits::empty_vtx_handle(),
Traits::empty_he_handle(),
@ -274,7 +274,7 @@ private:
boost::optional<Td_map_item&> rt = boost::none,
Dag_node* node = 0)
{
PTR = new Data (l, r, b, t, (lb) ? *lb : Td_map_item(0), (lt) ? *lt : Td_map_item(0),
PTR.p = new Data (l, r, b, t, (lb) ? *lb : Td_map_item(0), (lt) ? *lt : Td_map_item(0),
(rb) ? *rb : Td_map_item(0), (rt) ? *rt : Td_map_item(0), node);
//m_dag_node = node;
}
@ -332,7 +332,7 @@ private:
/*! Access the trapezoid id (PTR). */
inline unsigned long id() const
{
return (unsigned long) PTR;
return (unsigned long) PTR.p;
}
/*! Access trapezoid left.

View File

@ -134,7 +134,7 @@ public:
};
private:
Data* ptr() const { return (Data*)(PTR); }
Data* ptr() const { return (Data*)(PTR.p); }
Curve_end vtx_to_ce(Vertex_const_handle v) const
{
@ -184,14 +184,14 @@ public:
Td_active_vertex()
{
PTR = new Data(Traits::empty_vtx_handle(), Traits::empty_he_handle(), nullptr);
PTR.p = new Data(Traits::empty_vtx_handle(), Traits::empty_he_handle(), nullptr);
}
/*! Constructor given Vertex & Halfedge handles. */
Td_active_vertex(Vertex_const_handle v, Halfedge_const_handle cw_he,
Dag_node* node = 0)
{ PTR = new Data(v, cw_he, node); }
{ PTR.p = new Data(v, cw_he, node); }
/*! Copy constructor. */
@ -228,7 +228,7 @@ public:
inline const Self& self() const { return *this; }
/*! Access the trapezoid id (PTR). */
inline unsigned long id() const { return (unsigned long) PTR; }
inline unsigned long id() const { return (unsigned long) PTR.p; }
inline Vertex_const_handle vertex() const { return ptr()->v; }

View File

@ -41,14 +41,14 @@ public: //iddo (for CC-7.2) maybe protected?
typedef const T & const_reference;
protected:
void init() { PTR = 0; }
void init() { PTR.p = 0; }
public:
Td_dag_base() {init();}
Td_dag_base(const Td_dag_base<T> & x) : Handle(x) {}
Td_dag_base & operator=(const Td_dag_base<T> & x)
{Handle::operator=(x); return *this; }
bool operator!() const { return PTR == 0; }
bool operator!() const { return PTR.p == 0; }
};
template<class T>
@ -96,9 +96,9 @@ public:
Td_dag(){}
Td_dag(const Td_dag_handle& dag):Td_dag_handle(dag){}
Td_dag(const Self& dag):Td_dag_handle(dag){}
Td_dag(const T& rootValue){PTR = new node(rootValue);}
Td_dag(const T& rootValue){PTR.p = new node(rootValue);}
Td_dag(const T& rootValue, const Self& left, const Self& right)
{PTR = new node(rootValue, left, right); rebalance_depth();}
{PTR.p = new node(rootValue, left, right); rebalance_depth();}
~Td_dag(){}
/* --------information retrieval -------*/
@ -145,7 +145,7 @@ public:
}
bool operator==(const Self& b) const
{
return PTR==b.PTR;
return PTR.p==b.PTR.p;
}
bool operator!=(const Self& b) const
{
@ -189,7 +189,7 @@ public:
// detach left son,redirect to dummy
set_left(dummy);
// set left son pointer to 0
ptr()->leftPtr.PTR=0;
ptr()->leftPtr.PTR.p=0;
// delete dummy Td_dag
delete dummy.ptr();
}
@ -204,7 +204,7 @@ public:
// detach right son,redirect to dummy
set_right(dummy);
// set right son pointer to 0
ptr()->rightPtr.PTR=0;
ptr()->rightPtr.PTR.p=0;
// delete dummy Td_dag
delete dummy.ptr();
}
@ -371,7 +371,7 @@ protected:
}
#endif
private:
node* ptr() const {return (node*)PTR;}
node* ptr() const {return (node*)PTR.p;}
};
template<class T,class Traits>
@ -441,7 +441,7 @@ template<class T> std::ostream& operator<<(std::ostream& out,
tech notes:
The code is Handle designed.
left(),right() are designed to cope with Handle(Handle& x)
precondition x.PTR!=0
precondition x.PTR.p!=0
operator=() performs shallow copy
operator*() returns data type
output is done as a binary tree.

View File

@ -39,7 +39,7 @@ template<class Traits>
class Td_dag_node_base : public Handle
{
protected:
void init() { PTR = 0; } //MICHAL: I think it is not used - so need to be removed
void init() { PTR.p = 0; } //MICHAL: I think it is not used - so need to be removed
public:
//c'tors
@ -57,12 +57,12 @@ public:
return *this;
}
//bool operator!() const { return PTR == 0; } //MICHAL: maybe use ptr(), and also can change to is_null or something similar
bool is_null() const { return PTR == 0; }
Rep * ptr() const { return (Rep*) PTR; }
//bool operator!() const { return PTR.p == 0; } //MICHAL: maybe use ptr(), and also can change to is_null or something similar
bool is_null() const { return PTR.p == 0; }
Rep * ptr() const { return (Rep*) PTR.p; }
protected:
//Rep *& ptr() { return (Rep*) PTR; }
void set_ptr(Rep* rep) { PTR = rep; }
//Rep *& ptr() { return (Rep*) PTR.p; }
void set_ptr(Rep* rep) { PTR.p = rep; }
};
@ -94,7 +94,7 @@ public:
#ifndef CGAL_CFG_USING_BASE_MEMBER_BUG_2
public:
//using Td_dag_node_handle::PTR;
//using Td_dag_node_handle::PTR.p;
//using Td_dag_node_handle::operator!;
#endif //CGAL_CFG_USING_BASE_MEMBER_BUG_2
@ -549,7 +549,7 @@ protected:
private:
Node* node() const { return (Node*)Base::PTR; }
Node* node() const { return (Node*)Base::PTR.p; }
};
@ -629,7 +629,7 @@ std::ostream& operator<< (std::ostream& out,
tech notes:
The code is Handle designed.
left_child(),right_child() are designed to cope with Handle(Handle& x)
precondition x.PTR!=0
precondition x.PTR.p!=0
operator=() performs shallow copy
operator*() returns data type
output is done as a binary tree.

View File

@ -128,7 +128,7 @@ public:
private:
Data* ptr() const { return (Data*)(PTR); }
Data* ptr() const { return (Data*)(PTR.p); }
#ifndef CGAL_TD_DEBUG
@ -161,7 +161,7 @@ public:
/*! Constructor given Vertex & Halfedge handles. */
Td_inactive_edge (boost::shared_ptr<X_monotone_curve_2>& cv, Dag_node* node = nullptr)
{
PTR = new Data(cv,node);
PTR.p = new Data(cv,node);
}
/*! Copy constructor. */
@ -215,7 +215,7 @@ public:
/*! Access the trapezoid id (PTR). */
inline unsigned long id() const
{
return (unsigned long) PTR;
return (unsigned long) PTR.p;
}
inline X_monotone_curve_2& curve() const

View File

@ -133,7 +133,7 @@ public:
private:
Data* ptr() const { return (Data*)(PTR); }
Data* ptr() const { return (Data*)(PTR.p); }
Curve_end vtx_to_ce(Vertex_const_handle v) const
{
@ -185,7 +185,7 @@ public:
{
Curve_end v_ce(vtx_to_ce(v_before_rem));
PTR = new Data( v_ce.cv(), v_ce.ce(), node);
PTR.p = new Data( v_ce.cv(), v_ce.ce(), node);
}
@ -241,7 +241,7 @@ public:
/*! Access the trapezoid id (PTR). */
inline unsigned long id() const
{
return (unsigned long) PTR;
return (unsigned long) PTR.p;
}

View File

@ -127,7 +127,7 @@ public:
private:
Data* ptr() const { return (Data*)(PTR); }
Data* ptr() const { return (Data*)(PTR.p); }
#ifndef CGAL_TD_DEBUG
@ -162,7 +162,7 @@ public:
/*! Constructor given Vertex & Halfedge handles. */
Td_inactive_vertex (Vertex_const_handle v_before_rem, Dag_node* node = nullptr)
{
PTR = new Data(v_before_rem->point(), node);
PTR.p = new Data(v_before_rem->point(), node);
}
@ -217,7 +217,7 @@ public:
/*! Access the trapezoid id (PTR). */
inline unsigned long id() const
{
return (unsigned long) PTR;
return (unsigned long) PTR.p;
}
inline Point& point() const

View File

@ -2521,11 +2521,8 @@ protected:
template <typename Comparer>
class Compare_points {
private:
typedef Arr_polycurve_basic_traits_2<Subcurve_traits_2>
Polycurve_basic_traits_2;
/*! The polycurve traits (in case it has state). */
const Polycurve_basic_traits_2 m_poly_traits;
const Subcurve_traits_2& m_subcurve_traits;
const Point_2& m_point;
@ -2533,9 +2530,9 @@ protected:
public:
// Constructor
Compare_points(const Polycurve_basic_traits_2& traits, Comparer compare,
Compare_points(const Subcurve_traits_2& traits, Comparer compare,
const Point_2& p) :
m_poly_traits(traits),
m_subcurve_traits(traits),
m_point(p),
m_compare(compare)
{}
@ -2544,10 +2541,9 @@ protected:
Comparison_result operator()(const X_monotone_subcurve_2& xs,
Arr_curve_end ce)
{
const Subcurve_traits_2* geom_traits = m_poly_traits.subcurve_traits_2();
const Point_2& p = (ce == ARR_MAX_END) ?
geom_traits->construct_max_vertex_2_object()(xs) :
geom_traits->construct_min_vertex_2_object()(xs);
m_subcurve_traits.construct_max_vertex_2_object()(xs) :
m_subcurve_traits.construct_min_vertex_2_object()(xs);
return m_compare(p, m_point);
}
};
@ -2696,12 +2692,12 @@ protected:
Comparison_result res = compare_x(min_vertex(xcv[0]), q);
if (res != EQUAL) return INVALID_INDEX;
Compare_points<Compare_xy_2> compare(geom_traits,
Compare_points<Compare_xy_2> compare(*geom_traits,
compare_xy_2_object(), q);
return locate_gen(xcv, compare);
}
Compare_points<Compare_x_2> compare(geom_traits, compare_x_2_object(), q);
Compare_points<Compare_x_2> compare(*geom_traits, compare_x_2_object(), q);
return locate_gen(xcv, compare);
}

View File

@ -3024,8 +3024,8 @@ public:
y_dapprox = y_interval_for_curve_end(*this, CGAL::ARR_MIN_END, prec);
// adapt y-interval
ymin = CGAL::min(ymin, y_dapprox.first);
ymax = CGAL::max(ymax, y_dapprox.second);
ymin = (CGAL::min)(ymin, y_dapprox.first);
ymax = (CGAL::max)(ymax, y_dapprox.second);
// right end
@ -3105,9 +3105,9 @@ public:
(curr_xy, prec);
// adapt y-interval
ymin = CGAL::min(ymin,
ymin = (CGAL::min)(ymin,
CGAL::to_double(xy_approx.first));
ymax = CGAL::max(ymax,
ymax = (CGAL::max)(ymax,
CGAL::to_double(xy_approx.second));
}
}

View File

@ -572,7 +572,7 @@ void draw(const Arc_2& arc,
ref_bound = engine.pixel_h_r/CGAL_REFINE_X;
#ifdef CGAL_CKVA_RENDER_WITH_REFINEMENT
ref_bound = std::min(ref_bound, Rational(CGAL_REFINE_DOUBLE_APPROX));
ref_bound = (std::min)(ref_bound, Rational(CGAL_REFINE_DOUBLE_APPROX));
#endif
Gfx_OUT("computing y-coordinates\n");
@ -912,7 +912,7 @@ bool draw(const Point_2& pt, Coord_2& coord) {
const Coordinate_1& x0 = pt.x();
Rational ref_bound = engine.pixel_w_r / 2;
#ifdef CGAL_CKVA_RENDER_WITH_REFINEMENT
ref_bound = std::min(ref_bound, Rational(CGAL_REFINE_DOUBLE_APPROX));
ref_bound = (std::min)(ref_bound, Rational(CGAL_REFINE_DOUBLE_APPROX));
#endif
typename Curve_kernel_2::Algebraic_kernel_d_1::Approximate_relative_1
@ -932,7 +932,7 @@ bool draw(const Point_2& pt, Coord_2& coord) {
ref_bound = engine.pixel_h_r / CGAL_REFINE_X;
#ifdef CGAL_CKVA_RENDER_WITH_REFINEMENT
ref_bound = std::min(ref_bound, Rational(CGAL_REFINE_DOUBLE_APPROX));
ref_bound = (std::min)(ref_bound, Rational(CGAL_REFINE_DOUBLE_APPROX));
#endif
Coordinate_2 xy(x0, pt.curve(), pt.arcno());

View File

@ -140,7 +140,7 @@ struct Regularization_graph
if (get(pmap.rg->is_selected_map, fd))
{
if (pmap.rg->prevent_unselection)
out[0] = std::numeric_limits<double>::max();
out[0] = (std::numeric_limits<double>::max)();
else
out[0] = value;
out[1] = 0.;

View File

@ -68,14 +68,13 @@ The value type of the `OutputIterator` is either
`Polygon_with_holes_2` or
`General_polygon_with_holes_2`.
The signature of the function is
\code
OutputIterator difference(const Type1 & p1, const Type2 & p2, OutputIterator oi);
\endcode
The signature of the function is:
- `%OutputIterator %difference(const Type1 & p1, const Type2 & p2, %OutputIterator oi);`
\cgalHeading{Parameters}
The types of the paramters of the `difference()` function are any of the following combinations.
The types of the parameters of the `difference()` function are any of the following combinations.
<div align="left">
<table cellpadding=3 border="1">
@ -187,14 +186,13 @@ namespace CGAL {
Each one of these functions computes if the interior of two given
polygons `p1` and `p2` intersect.
The signature of the function is
\code
bool do_intersect(const Type1 & p1, const Type2 & p2);
\endcode
The signature of the function is:
- `bool do_intersect(const Type1 & p1, const Type2 & p2);`
\cgalHeading{Parameters}
The types of the paramters of the `do_intersect()` function are any of the following combinations.
The types of the parameters of the \link ref_bso_do_intersect `do_intersect()` \endlink function are any of the following combinations.
<div align="left">
<table cellpadding=3 border="1">
@ -316,15 +314,14 @@ holes into an output container through a given output iterator
`General_polygon_with_holes_2`.
The signature of the function is
\code
OutputIterator intersection(const Type1 & p1, const Type2 & p2, OutputIterator oi);
\endcode
The signature of the function is:
- `%OutputIterator %intersection(const Type1 & p1, const Type2 & p2, %OutputIterator oi);`
\cgalHeading{Parameters}
The types of the paramters of the `intersection()` function are any of the following combinations.
The types of the parameters of the `intersection()` function are any of the following combinations.
<div align="left">
@ -476,14 +473,13 @@ Each one of these functions computes the union of two given polygons
returns `false`.
The signature of the function is
\code
bool join(const Type1 & p1, const Type2 & p2, General_polygon_with_holes_2 & res);
\endcode
The signature of the function is:
- `bool join(const Type1 & p1, const Type2 & p2, General_polygon_with_holes_2 & res);`
\cgalHeading{Parameters}
The types of the paramters of the `join()` function are any of the following combinations.
The types of the parameters of the `join()` function are any of the following combinations.
<div align="left">
<table cellpadding=3 border="1">
@ -630,14 +626,12 @@ given polygons `p1` and `p2` intersect in their interior,
all, and `ON_ORIENTED_BOUNDARY` if `p1` and `p2` intersect
only in their boundaries.
The signature of the function is
\code
Oriented_side oriented_side(const Type1 & p1, const Type2 & p2);
\endcode
The signature of the function is:
- `Oriented_side oriented_side(const Type1 & p1, const Type2 & p2);`
\cgalHeading{Parameters}
The types of the paramters of the `oriented_side()` function are any of the following combinations.
The types of the parameters of the `oriented_side()` function are any of the following combinations.
<div align="left">
<table cellpadding=3 border="1">
@ -716,14 +710,12 @@ iterator `oi`. The value type of the `OutputIterator` is either
`Polygon_with_holes_2` or
`General_polygon_with_holes_2`.
The signature of the function is
\code
OutputIterator symmetric_difference(const Type1 & p1, const Type2 & p2, OutputIterator oi);
\endcode
The signature of the function is:
- `%OutputIterator symmetric_difference(const Type1 & p1, const Type2 & p2, %OutputIterator oi);`
\cgalHeading{Parameters}
The types of the paramters of the `symmetric_difference()` function are any of the following combinations.
The types of the parameters of the `symmetric_difference()` function are any of the following combinations.
<div align="left">
<table cellpadding=3 border="1">

View File

@ -17,8 +17,8 @@ int nr = 0;
double rerr(double exact,double approx) {
const double e = std::abs((exact-approx)/exact);
mine = std::min(mine,e);
maxe = std::max(maxe,e);
mine = (std::min)(mine,e);
maxe = (std::max)(maxe,e);
avge += e;
++nr;
return e;

View File

@ -4,15 +4,15 @@
#include <CGAL/box_intersection_d.h>
template <typename Polyline>
template <typename Poly>
class Polylines_do_intersect
{
typedef typename Polyline::const_iterator Iterator;
typedef typename Poly::const_iterator Iterator;
typedef typename std::iterator_traits<Iterator>::value_type Point_2;
typedef typename CGAL::Kernel_traits<Point_2>::Kernel::Segment_2 Segment_2;
typedef CGAL::Bbox_2 Bbox_2;
const Polyline& pA, &pB;
const Poly& pA, &pB;
struct Box : public CGAL::Box_intersection_d::Box_with_handle_d<double,2,Iterator> {
@ -31,9 +31,9 @@ class Polylines_do_intersect
class Overlap {
const Polyline& pA, &pB;
const Poly& pA, &pB;
public:
Overlap(const Polyline& pA, const Polyline& pB)
Overlap(const Poly& pA, const Poly& pB)
: pA(pA), pB(pB)
{}
@ -49,7 +49,7 @@ class Polylines_do_intersect
public:
Polylines_do_intersect(const Polyline& pA, const Polyline& pB)
Polylines_do_intersect(const Poly& pA, const Poly& pB)
: pA(pA), pB(pB)
{}
@ -83,22 +83,22 @@ public:
};
template <typename Polyline>
bool polylines_do_intersect(const Polyline& pA,const Polyline& pB)
template <typename Poly>
bool polylines_do_intersect(const Poly& pA,const Poly& pB)
{
Polylines_do_intersect<Polyline> pdi(pA,pB);
Polylines_do_intersect<Poly> pdi(pA,pB);
return pdi();
}
typedef CGAL::Exact_predicates_inexact_constructions_kernel K;
typedef K::Point_2 Point_2;
typedef std::vector<Point_2> Polyline;
typedef std::vector<Point_2> CGAL_polyline;
int main()
{
Polyline pA = { Point_2(0,0), Point_2(1,0) };
Polyline pB = { Point_2(0,0), Point_2(0,1), Point_2(2,1) , Point_2(1,0)};
CGAL_polyline pA = { Point_2(0,0), Point_2(1,0) };
CGAL_polyline pB = { Point_2(0,0), Point_2(0,1), Point_2(2,1) , Point_2(1,0)};
if(polylines_do_intersect(pA,pB)){
std::cout << "intersection" << std::endl;

View File

@ -145,7 +145,7 @@ public:
double maxVal = ( core_abs(val) + maxAbs / x.maxAbs) / xxx + DBL_MIN;
return filteredFp(val, maxVal, 1 + core_max(ind, x.ind + 1));
} else
return filteredFp(getDoubleInfty(), 0.0, 0);
return filteredFp( std::nan(""), getDoubleInfty(), 1);
}
/// square root
filteredFp sqrt () const {

View File

@ -125,9 +125,9 @@ extLong& extLong::operator*= (const extLong& y) {
if (std::fabs(d - p) <= std::fabs(d) * relEps) {
val = p;
flag = 0;
} else if (d > EXTLONG_MAX) {
} else if (d > static_cast<double>(EXTLONG_MAX)) {
*this = CORE_posInfty;
} else if (d < EXTLONG_MIN) {
} else if (d < static_cast<double>(EXTLONG_MIN)) {
*this = CORE_negInfty;
} else {
#ifdef CORE_DEBUG

View File

@ -94,7 +94,7 @@ void ASphapeIpelet::protected_run(int fn)
}
A.set_alpha(alpha==0?std::max(std::numeric_limits<double>::epsilon(),A.get_nth_alpha(0)/2.):
A.set_alpha(alpha==0?(std::max)(std::numeric_limits<double>::epsilon(),A.get_nth_alpha(0)/2.):
(std::size_t) alpha==A.number_of_alphas()?A.get_nth_alpha(alpha-1)+1:A.get_nth_alpha(alpha-1)/2.+A.get_nth_alpha(alpha)/2.);
for ( Alpha_shape_2::Alpha_shape_edges_iterator it=A.alpha_shape_edges_begin();it!=A.alpha_shape_edges_end();++it)
draw_in_ipe(A.segment(*it));

View File

@ -135,8 +135,8 @@ void diagrammeIpelet::protected_run(int fn)
Kernel::FT incr_len=(fn<2)?50:75;
//slightly increase the size of the Bbox
bbox=Iso_rectangle_2(bbox.min()+Kernel::Vector_2(-incr_len,-incr_len),
bbox.max()+Kernel::Vector_2(incr_len,incr_len));
bbox=Iso_rectangle_2((bbox.min)()+Kernel::Vector_2(-incr_len,-incr_len),
(bbox.max)()+Kernel::Vector_2(incr_len,incr_len));

View File

@ -90,8 +90,8 @@ void IpeletMesh2::protected_run(int fn)
double alpha=0;
int x=static_cast<int>( floor(bbox.max().x()-bbox.min().x()) );
int y=static_cast<int>( floor(bbox.max().y()-bbox.min().y()) );
int x=static_cast<int>( floor((bbox.max)().x()-(bbox.min)().x()) );
int y=static_cast<int>( floor((bbox.max)().y()-(bbox.min)().y()) );
int ret_val;
boost::tie(ret_val,alpha)=request_value_from_user<double>((boost::format("Max edge length (BBox %1%x%2%)") % x % y).str() );

View File

@ -76,7 +76,7 @@ void SubSelectIpelet::protected_run(int fn)
for (std::list<Circle_2>::iterator it=cir_list.begin();it!=cir_list.end();++it)
r_offsets.push_back(sqrt(CGAL::to_double(it->squared_radius())));
IpeMatrix tfm (1,0,0,1,-CGAL::to_double(bbox.min().x()),-CGAL::to_double(bbox.min().y()));
IpeMatrix tfm (1,0,0,1,-CGAL::to_double((bbox.min)().x()),-CGAL::to_double((bbox.min)().y()));
for (std::list<Polygon_2>::iterator it=pol_list.begin();it!=pol_list.end();++it)
if(!it->is_simple()){

View File

@ -95,8 +95,8 @@ void MregularIpelet::protected_run(int fn)
draw_in_ipe(rt);
else{//Draw kth Power diagram
double incr_len=75;
bbox=Iso_rectangle_2(bbox.min()+Kernel::Vector_2(-incr_len,-incr_len),
bbox.max()+Kernel::Vector_2(incr_len,incr_len));
bbox=Iso_rectangle_2((bbox.min)()+Kernel::Vector_2(-incr_len,-incr_len),
(bbox.max)()+Kernel::Vector_2(incr_len,incr_len));
draw_dual_in_ipe(rt,bbox); //draw Voronoi Diagram
}
}

View File

@ -105,7 +105,7 @@ void SkeletonIpelet::protected_run(int fn)
std::list<double> offsets;
//~ "Interior skeleton", "Exterior skeleton","Interior offset","Exterior offset","Interior offsets","Exterior offsets", "Help"
SkeletonPtr ss;
double max_edge=std::max((bbox.xmax()-bbox.xmin()),(bbox.ymax()-bbox.ymin()));
double max_edge=(std::max)((bbox.xmax()-bbox.xmin()),(bbox.ymax()-bbox.ymin()));
double dist=0.;
int ret_val=-1;
switch(fn){

View File

@ -96,8 +96,8 @@ namespace CGAL_svdlinf {
Kernel::FT incr_len = 75;
// slightly increase the size of the bbox
bbox = Iso_rectangle_2(
bbox.min()+Kernel::Vector_2(-incr_len,-incr_len),
bbox.max()+Kernel::Vector_2(incr_len,incr_len));
(bbox.min)()+Kernel::Vector_2(-incr_len,-incr_len),
(bbox.max)()+Kernel::Vector_2(incr_len,incr_len));
for (std::list<Segment_2>::iterator
sit = sg_list.begin();

View File

@ -256,8 +256,8 @@ public:
_page->DeselectAll();
Iso_rectangle_2 bbox_cgal(
static_cast<double>(bbox_ipe.Min().iX),static_cast<double>(bbox_ipe.Min().iY),
static_cast<double>(bbox_ipe.Max().iX),static_cast<double>(bbox_ipe.Max().iY)
static_cast<double>((bbox_ipe.Min)().iX),static_cast<double>((bbox_ipe.Min)().iY),
static_cast<double>((bbox_ipe.Max)().iX),static_cast<double>((bbox_ipe.Max)().iY)
);
return bbox_cgal;

View File

@ -61,6 +61,7 @@ create_single_source_cgal_program( "example_feature.cpp" )
create_single_source_cgal_program( "example_generation_and_training.cpp" )
create_single_source_cgal_program( "example_mesh_classification.cpp" )
create_single_source_cgal_program( "example_cluster_classification.cpp" )
create_single_source_cgal_program( "gis_tutorial_example.cpp" )
if (OpenCV_FOUND)
create_single_source_cgal_program( "example_opencv_random_forest.cpp" )
@ -80,7 +81,8 @@ foreach(target
example_mesh_classification
example_cluster_classification
example_opencv_random_forest
example_tensorflow_neural_network)
example_tensorflow_neural_network
gis_tutorial_example)
if(TARGET ${target})
CGAL_target_use_Eigen(${target})
CGAL_target_use_Boost_IOStreams(${target})
@ -90,4 +92,3 @@ foreach(target
endif()
endif()
endforeach()

View File

@ -0,0 +1 @@
data/b9_training.ply

View File

@ -0,0 +1,749 @@
#include <CGAL/Exact_predicates_inexact_constructions_kernel.h>
#include <CGAL/Projection_traits_xy_3.h>
#include <CGAL/Delaunay_triangulation_2.h>
#include <CGAL/Triangulation_vertex_base_with_info_2.h>
#include <CGAL/Triangulation_face_base_with_info_2.h>
#include <CGAL/boost/graph/graph_traits_Delaunay_triangulation_2.h>
#include <CGAL/boost/graph/copy_face_graph.h>
#include <CGAL/Point_set_3.h>
#include <CGAL/Point_set_3/IO.h>
#include <CGAL/compute_average_spacing.h>
#include <CGAL/Surface_mesh.h>
#include <CGAL/Polygon_mesh_processing/locate.h>
#include <CGAL/Polygon_mesh_processing/triangulate_hole.h>
#include <CGAL/Polygon_mesh_processing/border.h>
#include <CGAL/Polygon_mesh_processing/remesh.h>
#include <boost/graph/adjacency_list.hpp>
#include <CGAL/boost/graph/split_graph_into_polylines.h>
#include <CGAL/IO/WKT.h>
#include <CGAL/Constrained_Delaunay_triangulation_2.h>
#include <CGAL/Constrained_triangulation_plus_2.h>
#include <CGAL/Polyline_simplification_2/simplify.h>
#include <CGAL/Polyline_simplification_2/Squared_distance_cost.h>
#include <CGAL/Classification.h>
#include <CGAL/Random.h>
#include <fstream>
#include <queue>
#include "include/Color_ramp.h"
///////////////////////////////////////////////////////////////////
//! [TIN DS]
using Kernel = CGAL::Exact_predicates_inexact_constructions_kernel;
using Projection_traits = CGAL::Projection_traits_xy_3<Kernel>;
using Point_2 = Kernel::Point_2;
using Point_3 = Kernel::Point_3;
using Segment_3 = Kernel::Segment_3;
// Triangulated Irregular Network
using TIN = CGAL::Delaunay_triangulation_2<Projection_traits>;
//! [TIN DS]
///////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////
//! [TIN_with_info DS]
// Triangulated Irregular Network (with info)
using Point_set = CGAL::Point_set_3<Point_3>;
using Vbi = CGAL::Triangulation_vertex_base_with_info_2 <Point_set::Index, Projection_traits>;
using Fbi = CGAL::Triangulation_face_base_with_info_2<int, Projection_traits>;
using TDS = CGAL::Triangulation_data_structure_2<Vbi, Fbi>;
using TIN_with_info = CGAL::Delaunay_triangulation_2<Projection_traits, TDS>;
//! [TIN_with_info DS]
///////////////////////////////////////////////////////////////////
namespace Classification = CGAL::Classification;
#ifdef CGAL_LINKED_WITH_TBB
using Concurrency_tag = CGAL::Parallel_tag;
#else
using Concurrency_tag = CGAL::Sequential_tag;
#endif
///////////////////////////////////////////////////////////////////
//! [Contouring functions]
bool face_has_isovalue (TIN::Face_handle fh, double isovalue)
{
bool above = false, below = false;
for (int i = 0; i < 3; ++ i)
{
// Face has isovalue if one of its vertices is above and another
// one below
if (fh->vertex(i)->point().z() > isovalue)
above = true;
if (fh->vertex(i)->point().z() < isovalue)
below = true;
}
return (above && below);
}
Segment_3 isocontour_in_face (TIN::Face_handle fh, double isovalue)
{
Point_3 source;
Point_3 target;
bool source_found = false;
for (int i = 0; i < 3; ++ i)
{
Point_3 p0 = fh->vertex((i+1) % 3)->point();
Point_3 p1 = fh->vertex((i+2) % 3)->point();
// Check if the isovalue crosses segment (p0,p1)
if ((p0.z() - isovalue) * (p1.z() - isovalue) > 0)
continue;
double zbottom = p0.z();
double ztop = p1.z();
if (zbottom > ztop)
{
std::swap (zbottom, ztop);
std::swap (p0, p1);
}
// Compute position of segment vertex
double ratio = (isovalue - zbottom) / (ztop - zbottom);
Point_3 p = CGAL::barycenter (p0, (1 - ratio), p1,ratio);
if (source_found)
target = p;
else
{
source = p;
source_found = true;
}
}
return Segment_3 (source, target);
}
//! [Contouring functions]
///////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////
//! [Contouring visitor]
template <typename Graph>
class Polylines_visitor
{
private:
std::vector<std::vector<Point_3> >& polylines;
Graph& graph;
public:
Polylines_visitor (Graph& graph, std::vector<std::vector<Point_3> >& polylines)
: polylines (polylines), graph(graph) { }
void start_new_polyline()
{
polylines.push_back (std::vector<Point_3>());
}
void add_node (typename Graph::vertex_descriptor vd)
{
polylines.back().push_back (graph[vd]);
}
void end_polyline()
{
// filter small polylines
if (polylines.back().size() < 50)
polylines.pop_back();
}
};
//! [Contouring visitor]
///////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////
//! [CDT]
namespace PS = CGAL::Polyline_simplification_2;
using CDT_vertex_base = PS::Vertex_base_2<Projection_traits>;
using CDT_face_base = CGAL::Constrained_triangulation_face_base_2<Projection_traits>;
using CDT_TDS = CGAL::Triangulation_data_structure_2<CDT_vertex_base, CDT_face_base>;
using CDT = CGAL::Constrained_Delaunay_triangulation_2<Projection_traits, CDT_TDS>;
using CTP = CGAL::Constrained_triangulation_plus_2<CDT>;
//! [CDT]
///////////////////////////////////////////////////////////////////
int main (int argc, char** argv)
{
if (argc != 2)
{
std::cerr << "Usage: " << argv[0] << " points.ply" << std::endl;
return EXIT_FAILURE;
}
///////////////////////////////////////////////////////////////////
//! [Init DSM]
// Read points
std::ifstream ifile (argv[1], std::ios_base::binary);
CGAL::Point_set_3<Point_3> points;
ifile >> points;
std::cerr << points.size() << " point(s) read" << std::endl;
// Create DSM
TIN dsm (points.points().begin(), points.points().end());
//! [Init DSM]
///////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////
//! [Save DSM]
using Mesh = CGAL::Surface_mesh<Point_3>;
Mesh dsm_mesh;
CGAL::copy_face_graph (dsm, dsm_mesh);
std::ofstream dsm_ofile ("dsm.ply", std::ios_base::binary);
CGAL::set_binary_mode (dsm_ofile);
CGAL::write_ply (dsm_ofile, dsm_mesh);
dsm_ofile.close();
//! [Save DSM]
///////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////
//! [TIN_with_info]
auto idx_to_point_with_info
= [&](const Point_set::Index& idx) -> std::pair<Point_3, Point_set::Index>
{
return std::make_pair (points.point(idx), idx);
};
TIN_with_info tin_with_info
(boost::make_transform_iterator (points.begin(), idx_to_point_with_info),
boost::make_transform_iterator (points.end(), idx_to_point_with_info));
//! [TIN_with_info]
///////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////
//! [Components]
double spacing = CGAL::compute_average_spacing<Concurrency_tag>(points, 6);
spacing *= 2;
auto face_height
= [&](const TIN_with_info::Face_handle fh) -> double
{
double out = 0.;
for (int i = 0; i < 3; ++ i)
out = (std::max) (out, CGAL::abs(fh->vertex(i)->point().z() - fh->vertex((i+1)%3)->point().z()));
return out;
};
// Initialize faces info
for (TIN_with_info::Face_handle fh : tin_with_info.all_face_handles())
if (tin_with_info.is_infinite(fh) || face_height(fh) > spacing) // Filtered faces are given info() = -2
fh->info() = -2;
else // Pending faces are given info() = -1;
fh->info() = -1;
// Flooding algorithm
std::vector<int> component_size;
for (TIN_with_info::Face_handle fh : tin_with_info.finite_face_handles())
{
if (fh->info() != -1)
continue;
std::queue<TIN_with_info::Face_handle> todo;
todo.push(fh);
int size = 0;
while (!todo.empty())
{
TIN_with_info::Face_handle current = todo.front();
todo.pop();
if (current->info() != -1)
continue;
current->info() = int(component_size.size());
++ size;
for (int i = 0; i < 3; ++ i)
todo.push (current->neighbor(i));
}
component_size.push_back (size);
}
std::cerr << component_size.size() << " connected component(s) found" << std::endl;
//! [Components]
///////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////
//! [Save TIN with info]
Mesh tin_colored_mesh;
Mesh::Property_map<Mesh::Face_index, CGAL::Color>
color_map = tin_colored_mesh.add_property_map<Mesh::Face_index, CGAL::Color>("f:color").first;
CGAL::copy_face_graph (tin_with_info, tin_colored_mesh,
CGAL::parameters::face_to_face_output_iterator
(boost::make_function_output_iterator
([&](const std::pair<TIN_with_info::Face_handle, Mesh::Face_index>& ff)
{
// Color unassigned faces gray
if (ff.first->info() < 0)
color_map[ff.second] = CGAL::Color(128, 128, 128);
else
{
// Random color seeded by the component ID
CGAL::Random r (ff.first->info());
color_map[ff.second] = CGAL::Color (r.get_int(64, 192),
r.get_int(64, 192),
r.get_int(64, 192));
}
})));
std::ofstream tin_colored_ofile ("colored_tin.ply", std::ios_base::binary);
CGAL::set_binary_mode (tin_colored_ofile);
CGAL::write_ply (tin_colored_ofile, tin_colored_mesh);
tin_colored_ofile.close();
//! [Save TIN with info]
///////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////
//! [Filtering]
int min_size = int(points.size() / 2);
std::vector<TIN_with_info::Vertex_handle> to_remove;
for (TIN_with_info::Vertex_handle vh : tin_with_info.finite_vertex_handles())
{
TIN_with_info::Face_circulator circ = tin_with_info.incident_faces (vh),
start = circ;
// Remove a vertex if it's only adjacent to components smaller than threshold
bool keep = false;
do
{
if (circ->info() >= 0 && component_size[std::size_t(circ->info())] > min_size)
{
keep = true;
break;
}
}
while (++ circ != start);
if (!keep)
to_remove.push_back (vh);
}
std::cerr << to_remove.size() << " vertices(s) will be removed after filtering" << std::endl;
for (TIN_with_info::Vertex_handle vh : to_remove)
tin_with_info.remove (vh);
//! [Filtering]
///////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////
//! [Hole filling]
// Copy and keep track of overly large faces
Mesh dtm_mesh;
std::vector<Mesh::Face_index> face_selection;
Mesh::Property_map<Mesh::Face_index, bool> face_selection_map
= dtm_mesh.add_property_map<Mesh::Face_index, bool>("is_selected", false).first;
double limit = CGAL::square (5 * spacing);
CGAL::copy_face_graph (tin_with_info, dtm_mesh,
CGAL::parameters::face_to_face_output_iterator
(boost::make_function_output_iterator
([&](const std::pair<TIN_with_info::Face_handle, Mesh::Face_index>& ff)
{
double longest_edge = 0.;
bool border = false;
for (int i = 0; i < 3; ++ i)
{
longest_edge = (std::max)(longest_edge, CGAL::squared_distance
(ff.first->vertex((i+1)%3)->point(),
ff.first->vertex((i+2)%3)->point()));
TIN_with_info::Face_circulator circ
= tin_with_info.incident_faces (ff.first->vertex(i)),
start = circ;
do
{
if (tin_with_info.is_infinite (circ))
{
border = true;
break;
}
}
while (++ circ != start);
if (border)
break;
}
// Select if face is too big AND it's not
// on the border (to have closed holes)
if (!border && longest_edge > limit)
{
face_selection_map[ff.second] = true;
face_selection.push_back (ff.second);
}
})));
// Save original DTM
std::ofstream dtm_ofile ("dtm.ply", std::ios_base::binary);
CGAL::set_binary_mode (dtm_ofile);
CGAL::write_ply (dtm_ofile, dtm_mesh);
dtm_ofile.close();
std::cerr << face_selection.size() << " face(s) are selected for removal" << std::endl;
// Expand face selection to keep a well formed 2-manifold mesh after removal
CGAL::expand_face_selection_for_removal (face_selection, dtm_mesh, face_selection_map);
face_selection.clear();
for (Mesh::Face_index fi : faces(dtm_mesh))
if (face_selection_map[fi])
face_selection.push_back(fi);
std::cerr << face_selection.size() << " face(s) are selected for removal after expansion" << std::endl;
for (Mesh::Face_index fi : face_selection)
CGAL::Euler::remove_face (halfedge(fi, dtm_mesh), dtm_mesh);
dtm_mesh.collect_garbage();
if (!dtm_mesh.is_valid())
std::cerr << "Invalid mesh!" << std::endl;
// Save filtered DTM
std::ofstream dtm_holes_ofile ("dtm_with_holes.ply", std::ios_base::binary);
CGAL::set_binary_mode (dtm_holes_ofile);
CGAL::write_ply (dtm_holes_ofile, dtm_mesh);
dtm_holes_ofile.close();
// Get all holes
std::vector<Mesh::Halfedge_index> holes;
CGAL::Polygon_mesh_processing::extract_boundary_cycles (dtm_mesh, std::back_inserter (holes));
std::cerr << holes.size() << " hole(s) identified" << std::endl;
// Identify outer hull (hole with maximum size)
double max_size = 0.;
Mesh::Halfedge_index outer_hull;
for (Mesh::Halfedge_index hi : holes)
{
CGAL::Bbox_3 hole_bbox;
for (Mesh::Halfedge_index haf : CGAL::halfedges_around_face(hi, dtm_mesh))
{
const Point_3& p = dtm_mesh.point(target(haf, dtm_mesh));
hole_bbox += p.bbox();
}
double size = CGAL::squared_distance (Point_2(hole_bbox.xmin(), hole_bbox.ymin()),
Point_2(hole_bbox.xmax(), hole_bbox.ymax()));
if (size > max_size)
{
max_size = size;
outer_hull = hi;
}
}
// Fill all holes except the bigest (which is the outer hull of the mesh)
for (Mesh::Halfedge_index hi : holes)
if (hi != outer_hull)
CGAL::Polygon_mesh_processing::triangulate_refine_and_fair_hole
(dtm_mesh, hi, CGAL::Emptyset_iterator(), CGAL::Emptyset_iterator());
// Save DTM with holes filled
std::ofstream dtm_filled_ofile ("dtm_filled.ply", std::ios_base::binary);
CGAL::set_binary_mode (dtm_filled_ofile);
CGAL::write_ply (dtm_filled_ofile, dtm_mesh);
dtm_filled_ofile.close();
//! [Hole filling]
///////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////
//! [Remeshing]
CGAL::Polygon_mesh_processing::isotropic_remeshing (faces(dtm_mesh), spacing, dtm_mesh);
std::ofstream dtm_remeshed_ofile ("dtm_remeshed.ply", std::ios_base::binary);
CGAL::set_binary_mode (dtm_remeshed_ofile);
CGAL::write_ply (dtm_remeshed_ofile, dtm_mesh);
dtm_remeshed_ofile.close();
//! [Remeshing]
///////////////////////////////////////////////////////////////////
TIN dtm_clean (dtm_mesh.points().begin(), dtm_mesh.points().end());
///////////////////////////////////////////////////////////////////
//! [Rastering]
CGAL::Bbox_3 bbox = CGAL::bbox_3 (points.points().begin(), points.points().end());
// Generate raster image 1920-pixels large
std::size_t width = 1920;
std::size_t height = std::size_t((bbox.ymax() - bbox.ymin()) * 1920 / (bbox.xmax() - bbox.xmin()));
std::cerr << "Rastering with resolution " << width << "x" << height << std::endl;
// Use PPM format (Portable PixMap) for simplicity
std::ofstream raster_ofile ("raster.ppm", std::ios_base::binary);
// PPM header
raster_ofile << "P6" << std::endl // magic number
<< width << " " << height << std::endl // dimensions of the image
<< 255 << std::endl; // maximum color value
// Use rainbow color ramp output
Color_ramp color_ramp;
// Keeping track of location from one point to its neighbor allows
// for fast locate in DT
TIN::Face_handle location;
// Query each pixel of the image
for (std::size_t y = 0; y < height; ++ y)
for (std::size_t x = 0; x < width; ++ x)
{
Point_3 query (bbox.xmin() + x * (bbox.xmax() - bbox.xmin()) / double(width),
bbox.ymin() + (height-y) * (bbox.ymax() - bbox.ymin()) / double(height),
0); // not relevant for location in 2D
location = dtm_clean.locate (query, location);
// Points outside the convex hull will be colored black
std::array<unsigned char, 3> colors { 0, 0, 0 };
if (!dtm_clean.is_infinite(location))
{
std::array<double, 3> barycentric_coordinates
= CGAL::Polygon_mesh_processing::barycentric_coordinates
(Point_2 (location->vertex(0)->point().x(), location->vertex(0)->point().y()),
Point_2 (location->vertex(1)->point().x(), location->vertex(1)->point().y()),
Point_2 (location->vertex(2)->point().x(), location->vertex(2)->point().y()),
Point_2 (query.x(), query.y()),
Kernel());
double height_at_query
= (barycentric_coordinates[0] * location->vertex(0)->point().z()
+ barycentric_coordinates[1] * location->vertex(1)->point().z()
+ barycentric_coordinates[2] * location->vertex(2)->point().z());
// Color ramp generates a color depending on a value from 0 to 1
double height_ratio = (height_at_query - bbox.zmin()) / (bbox.zmax() - bbox.zmin());
colors = color_ramp.get(height_ratio);
}
raster_ofile.write ((char*)(&colors), 3);
}
raster_ofile.close();
//! [Rastering]
///////////////////////////////////////////////////////////////////
// Smooth heights with 5 successive Gaussian filters
double gaussian_variance = 4 * spacing * spacing;
for (TIN::Vertex_handle vh : dtm_clean.finite_vertex_handles())
{
double z = vh->point().z();
double total_weight = 1;
TIN::Vertex_circulator circ = dtm_clean.incident_vertices (vh),
start = circ;
do
{
if (!dtm_clean.is_infinite(circ))
{
double sq_dist = CGAL::squared_distance (vh->point(), circ->point());
double weight = std::exp(- sq_dist / gaussian_variance);
z += weight * circ->point().z();
total_weight += weight;
}
}
while (++ circ != start);
z /= total_weight;
vh->point() = Point_3 (vh->point().x(), vh->point().y(), z);
}
///////////////////////////////////////////////////////////////////
//! [Contouring extraction]
std::array<double, 50> isovalues; // Contour 50 isovalues
for (std::size_t i = 0; i < isovalues.size(); ++ i)
isovalues[i] = bbox.zmin() + ((i+1) * (bbox.zmax() - bbox.zmin()) / (isovalues.size() - 2));
// First find on each face if they are crossed by some isovalues and
// extract segments in a graph
using Segment_graph = boost::adjacency_list<boost::listS, boost::vecS, boost::undirectedS, Point_3>;
Segment_graph graph;
using Map_p2v = std::map<Point_3, Segment_graph::vertex_descriptor>;
Map_p2v map_p2v;
for (TIN::Face_handle vh : dtm_clean.finite_face_handles())
for (double iv : isovalues)
if (face_has_isovalue (vh, iv))
{
Segment_3 segment = isocontour_in_face (vh, iv);
for (const Point_3& p : { segment.source(), segment.target() })
{
// Only insert end points of segments once to get a well connected graph
Map_p2v::iterator iter;
bool inserted;
std::tie (iter, inserted) = map_p2v.insert (std::make_pair (p, Segment_graph::vertex_descriptor()));
if (inserted)
{
iter->second = boost::add_vertex (graph);
graph[iter->second] = p;
}
}
boost::add_edge (map_p2v[segment.source()], map_p2v[segment.target()], graph);
}
//! [Contouring extraction]
///////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////
//! [Contouring split]
// Split segments into polylines
std::vector<std::vector<Point_3> > polylines;
Polylines_visitor<Segment_graph> visitor (graph, polylines);
CGAL::split_graph_into_polylines (graph, visitor);
std::cerr << polylines.size() << " polylines computed, with "
<< map_p2v.size() << " vertices in total" << std::endl;
// Output to WKT file
std::ofstream contour_ofile ("contour.wkt");
contour_ofile.precision(18);
CGAL::write_multi_linestring_WKT (contour_ofile, polylines);
contour_ofile.close();
//! [Contouring split]
///////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////
//! [Contouring simplify]
// Construct constrained Delaunay triangulation with polylines as constraints
CTP ctp;
for (const std::vector<Point_3>& poly : polylines)
ctp.insert_constraint (poly.begin(), poly.end());
// Simplification algorithm with limit on distance
PS::simplify (ctp, PS::Squared_distance_cost(), PS::Stop_above_cost_threshold (16 * spacing * spacing));
polylines.clear();
for (CTP::Constraint_id cid : ctp.constraints())
{
polylines.push_back (std::vector<Point_3>());
polylines.back().reserve (ctp.vertices_in_constraint (cid).size());
for (CTP::Vertex_handle vh : ctp.vertices_in_constraint(cid))
polylines.back().push_back (vh->point());
}
std::size_t nb_vertices
= std::accumulate (polylines.begin(), polylines.end(), 0,
[](std::size_t size, const std::vector<Point_3>& poly) -> std::size_t
{ return size + poly.size(); });
std::cerr << nb_vertices
<< " vertices remaining after simplification ("
<< 100. * (nb_vertices / double(map_p2v.size())) << "%)" << std::endl;
// Output to WKT file
std::ofstream simplified_ofile ("simplified.wkt");
simplified_ofile.precision(18);
CGAL::write_multi_linestring_WKT (simplified_ofile, polylines);
simplified_ofile.close();
//! [Contouring simplify]
///////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////
//! [Classification]
// Get training from input
Point_set::Property_map<int> training_map;
bool training_found;
std::tie (training_map, training_found) = points.property_map<int>("training");
if (training_found)
{
std::cerr << "Classifying ground/vegetation/building" << std::endl;
// Create labels
Classification::Label_set labels ({ "ground", "vegetation", "building" });
// Generate features
Classification::Feature_set features;
Classification::Point_set_feature_generator<Kernel, Point_set, Point_set::Point_map>
generator (points, points.point_map(), 5); // 5 scales
#ifdef CGAL_LINKED_WITH_TBB
// If TBB is used, features can be computed in parallel
features.begin_parallel_additions();
generator.generate_point_based_features (features);
features.end_parallel_additions();
#else
generator.generate_point_based_features (features);
#endif
// Train a random forest classifier
Classification::ETHZ::Random_forest_classifier classifier (labels, features);
classifier.train (points.range(training_map));
// Classify with graphcut regularization
Point_set::Property_map<int> label_map = points.add_property_map<int>("labels").first;
Classification::classify_with_graphcut<Concurrency_tag>
(points, points.point_map(), labels, classifier,
generator.neighborhood().k_neighbor_query(12), // regularize on 12-neighbors graph
0.5f, // graphcut weight
12, // Subdivide to speed-up process
label_map);
// Evaluate
std::cerr << "Mean IoU on training data = "
<< Classification::Evaluation(labels,
points.range(training_map),
points.range(label_map)).mean_intersection_over_union() << std::endl;
// Save the classified point set
std::ofstream classified_ofile ("classified.ply");
CGAL::set_binary_mode (classified_ofile);
classified_ofile << points;
classified_ofile.close();
}
//! [Classification]
///////////////////////////////////////////////////////////////////
return EXIT_SUCCESS;
}

View File

@ -0,0 +1,45 @@
#ifndef COLOR_RAMP_H
#define COLOR_RAMP_H
class Color_ramp
{
typedef std::array<unsigned char, 3> Color;
typedef std::pair<double, Color> Step;
std::vector<Step> m_steps;
public:
Color_ramp()
{
m_steps.push_back (std::make_pair (0, Color{ 192, 192, 255}));
m_steps.push_back (std::make_pair (0.2, Color{ 0, 0, 255}));
m_steps.push_back (std::make_pair (0.4, Color{ 0, 255, 0}));
m_steps.push_back (std::make_pair (0.6, Color{ 255, 255, 0}));
m_steps.push_back (std::make_pair (0.8, Color{ 255, 0, 0}));
m_steps.push_back (std::make_pair (1.0, Color{ 128, 0, 0}));
}
Color get (double value) const
{
std::size_t idx = 0;
while (m_steps[idx+1].first < value)
++ idx;
double v0 = m_steps[idx].first;
double v1 = m_steps[idx+1].first;
const Color& c0 = m_steps[idx].second;
const Color& c1 = m_steps[idx+1].second;
double ratio = (value - v0) / (v1 - v0);
Color out;
for (std::size_t i = 0; i < 3; ++ i)
out[i] = (unsigned char)((1 - ratio) * c0[i] + ratio * c1[i]);
return out;
}
};
#endif // COLOR_RAMP_H

View File

@ -186,15 +186,17 @@ public:
std::vector<int> gt;
std::vector<float> ft;
for (std::size_t i = 0; i < ground_truth.size(); ++ i)
std::size_t idx = 0;
for (const auto& ig : ground_truth)
{
int g = int(ground_truth[i]);
int g = int(ig);
if (g != -1)
{
for (std::size_t f = 0; f < m_features.size(); ++ f)
ft.push_back(m_features[f]->value(i));
ft.push_back(m_features[f]->value(idx));
gt.push_back(g);
}
++ idx;
}
CGAL_CLASSIFICATION_CERR << "Using " << gt.size() << " inliers" << std::endl;

View File

@ -16,6 +16,10 @@
#include <CGAL/Classification/Label.h>
#include <CGAL/Classification/Label_set.h>
#include <boost/iterator/zip_iterator.hpp>
#include <CGAL/Iterator_range.h>
#include <map>
#include <cmath> // for std::isnan
@ -80,10 +84,13 @@ public:
std::size_t sum_true_positives = 0;
std::size_t total = 0;
for (std::size_t j = 0; j < ground_truth.size(); ++ j)
for (const auto& zip : CGAL::make_range (boost::make_zip_iterator
(boost::make_tuple(ground_truth.begin(), result.begin())),
boost::make_zip_iterator
(boost::make_tuple(ground_truth.end(), result.end()))))
{
int gt = static_cast<int>(ground_truth[j]);
int res = static_cast<int>(result[j]);
int gt = static_cast<int>(boost::get<0>(zip));
int res = static_cast<int>(boost::get<1>(zip));
if (gt == -1 || res == -1)
continue;
++ total;
@ -221,4 +228,3 @@ public:
} // namespace CGAL
#endif // CGAL_CLASSIFICATION_EVALUATION_H

View File

@ -58,8 +58,8 @@ public:
m_values.reserve (clusters.size());
for (std::size_t i = 0; i < clusters.size(); ++ i)
{
float min_z = std::numeric_limits<float>::max();
float max_z = -std::numeric_limits<float>::min();
float min_z = (std::numeric_limits<float>::max)();
float max_z = -(std::numeric_limits<float>::min)();
for (std::size_t j = 0; j < clusters[i].size(); ++ j)
{

View File

@ -88,7 +88,7 @@ public:
Image_float dem(grid.width(),grid.height());
z_max = 0.f;
z_min = std::numeric_limits<float>::max();
z_min = (std::numeric_limits<float>::max)();
for (std::size_t j = 0; j < grid.height(); ++ j)
for (std::size_t i = 0; i < grid.width(); ++ i)
@ -100,8 +100,8 @@ public:
for (typename Grid::iterator it = grid.indices_begin(i,j); it != end; ++ it)
{
float z = float(get(point_map, *(input.begin()+(*it))).z());
z_min = (std::min(z_min, z));
z_max = (std::max(z_max, z));
z_min = ((std::min)(z_min, z));
z_max = ((std::max)(z_max, z));
mean += z;
++ nb;
}

View File

@ -81,13 +81,13 @@ public:
for (std::size_t i = 0; i < grid.width(); ++ i)
if (grid.has_points(i,j))
{
float z_max = -std::numeric_limits<float>::max();
float z_max = -(std::numeric_limits<float>::max)();
typename Grid::iterator end = grid.indices_end(i,j);
for (typename Grid::iterator it = grid.indices_begin(i,j); it != end; ++ it)
{
float z = float(get(point_map, *(input.begin()+(*it))).z());
z_max = (std::max(z_max, z));
z_max = ((std::max)(z_max, z));
}
dtm(i,j) = z_max;

View File

@ -81,13 +81,13 @@ public:
for (std::size_t i = 0; i < grid.width(); ++ i)
if (grid.has_points(i,j))
{
float z_min = std::numeric_limits<float>::max();
float z_min = (std::numeric_limits<float>::max)();
typename Grid::iterator end = grid.indices_end(i,j);
for (typename Grid::iterator it = grid.indices_begin(i,j); it != end; ++ it)
{
float z = float(get(point_map, *(input.begin()+(*it))).z());
z_min = (std::min(z_min, z));
z_min = ((std::min)(z_min, z));
}
dtm(i,j) = z_min;

View File

@ -81,15 +81,15 @@ public:
for (std::size_t i = 0; i < grid.width(); ++ i)
if (grid.has_points(i,j))
{
float z_max = -std::numeric_limits<float>::max();
float z_min = std::numeric_limits<float>::max();
float z_max = -(std::numeric_limits<float>::max)();
float z_min = (std::numeric_limits<float>::max)();
typename Grid::iterator end = grid.indices_end(i,j);
for (typename Grid::iterator it = grid.indices_begin(i,j); it != end; ++ it)
{
float z = float(get(point_map, *(input.begin()+(*it))).z());
z_max = (std::max(z_max, z));
z_min = (std::min(z_min, z));
z_max = ((std::max)(z_max, z));
z_min = ((std::min)(z_min, z));
}
dtm(i,j) = z_max - z_min;

View File

@ -38,6 +38,15 @@ public:
Label_set() { }
/*!
\brief Initializes the set with the provided `labels` names.
*/
Label_set (const std::initializer_list<const char*>& labels)
{
for (const char* l : labels)
add(l);
}
/// \cond SKIP_IN_MANUAL
virtual ~Label_set() { }
/// \endcond

View File

@ -161,9 +161,9 @@ private:
CGAL::Real_timer t;
t.start();
if (lower_grid == nullptr)
neighborhood = new Neighborhood (input, point_map);
neighborhood = new Neighborhood (input, point_map, ConcurrencyTag());
else
neighborhood = new Neighborhood (input, point_map, voxel_size);
neighborhood = new Neighborhood (input, point_map, voxel_size, ConcurrencyTag());
t.stop();
if (lower_grid == nullptr)

View File

@ -173,12 +173,32 @@ public:
/*!
\brief Constructs a neighborhood object based on the input range.
\tparam ConcurrencyTag enables sequential versus parallel
algorithm. Possible values are `Sequential_tag`, `Parallel_tag`,
and `Parallel_if_available_tag`. If no tag is provided,
`Parallel_if_available_tag` is used.
\param input point range.
\param point_map property map to access the input points.
*/
template <typename ConcurrencyTag>
Point_set_neighborhood (const PointRange& input,
PointMap point_map)
PointMap point_map,
const ConcurrencyTag&)
: m_tree (nullptr)
{
init<ConcurrencyTag> (input, point_map);
}
/// \cond SKIP_IN_MANUAL
Point_set_neighborhood (const PointRange& input, PointMap point_map)
: m_tree (nullptr)
{
init<Parallel_if_available_tag> (input, point_map);
}
template <typename ConcurrencyTag>
void init (const PointRange& input, PointMap point_map)
{
My_point_property_map pmap (&input, point_map);
m_tree = new Tree (boost::counting_iterator<boost::uint32_t> (0),
@ -186,8 +206,9 @@ public:
Splitter(),
Search_traits (pmap));
m_distance = Distance (pmap);
m_tree->build();
m_tree->template build<ConcurrencyTag>();
}
/// \endcond
/*!
\brief Constructs a simplified neighborhood object based on the input range.
@ -197,14 +218,36 @@ public:
present in one cell, only the point closest to the centroid of
this subset is used.
\tparam ConcurrencyTag enables sequential versus parallel
algorithm. Possible values are `Sequential_tag`, `Parallel_tag`,
and `Parallel_if_available_tag`. If no tag is provided,
`Parallel_if_available_tag` is used.
\param input input range.
\param point_map property map to access the input points.
\param voxel_size size of the cells of the 3D grid used for simplification.
*/
template <typename ConcurrencyTag>
Point_set_neighborhood (const PointRange& input,
PointMap point_map,
float voxel_size,
const ConcurrencyTag&)
: m_tree (nullptr)
{
init<ConcurrencyTag> (input, point_map, voxel_size);
}
/// \cond SKIP_IN_MANUAL
Point_set_neighborhood (const PointRange& input,
PointMap point_map,
float voxel_size)
: m_tree (nullptr)
{
init<Parallel_if_available_tag> (input, point_map, voxel_size);
}
template <typename ConcurrencyTag>
void init (const PointRange& input, PointMap point_map, float voxel_size)
{
// First, simplify
std::vector<boost::uint32_t> indices;
@ -215,8 +258,9 @@ public:
Splitter(),
Search_traits (pmap));
m_distance = Distance (pmap);
m_tree->build();
m_tree->template build<ConcurrencyTag>();
}
/// \endcond
/// @}

View File

@ -40,15 +40,15 @@ typedef unsigned short compressed_float;
typedef unsigned char compressed_float;
# endif
inline compressed_float compress_float (const float& f, const float& min = 0.f, const float& max = 1.f)
inline compressed_float compress_float (const float& f, const float& fmin = 0.f, const float& fmax = 1.f)
{
return static_cast<compressed_float>
(float(std::numeric_limits<compressed_float>::max()) * (f - min) / (max - min));
(float((std::numeric_limits<compressed_float>::max)()) * (f - fmin) / (fmax - fmin));
}
inline float decompress_float (const compressed_float& t, const float& min = 0.f, const float& max = 1.f)
inline float decompress_float (const compressed_float& t, const float& fmin = 0.f, const float& fmax = 1.f)
{
return ((max - min) * (t / float(std::numeric_limits<compressed_float>::max())) + min);
return ((fmax - fmin) * (t / float((std::numeric_limits<compressed_float>::max)())) + fmin);
}
#endif

View File

@ -14,6 +14,8 @@
#include <CGAL/disable_warnings.h>
#include <CGAL/Combinatorial_map_fwd.h>
#include <CGAL/internal/Combinatorial_map_internal_functors.h>
#include <CGAL/internal/Combinatorial_map_utility.h>
#include <CGAL/internal/Combinatorial_map_group_functors.h>
@ -74,20 +76,15 @@ namespace CGAL {
*/
struct Combinatorial_map_tag {};
struct Generalized_map_tag;
/** Generic definition of combinatorial map in dD.
* The Combinatorial_map class describes an dD combinatorial map. It allows
* mainly to create darts, to use marks onto these darts, to get and set
* the beta links, and to manage enabled attributes.
*/
template < unsigned int d_, class Refs,
#if defined(CGAL_CMAP_DART_DEPRECATED) && !defined(CGAL_NO_DEPRECATED_CODE)
class Items_=Combinatorial_map_min_items<d_>,
#else
class Items_=Generic_map_min_items,
#endif
class Alloc_=CGAL_ALLOCATOR(int),
class Storage_= Combinatorial_map_storage_1<d_, Items_, Alloc_> >
template < unsigned int d_, class Refs_, class Items_,
class Alloc_, class Storage_ >
class Combinatorial_map_base: public Storage_
{
template<typename CMap,unsigned int i,typename Enabled>
@ -114,9 +111,10 @@ namespace CGAL {
typedef Combinatorial_map_tag Combinatorial_data_structure;
/// Types definition
typedef Storage_ Storage;
typedef Storage Base;
typedef Combinatorial_map_base<d_, Refs, Items_, Alloc_, Storage_ > Self;
typedef Storage_ Storage;
typedef Storage Base;
typedef Combinatorial_map_base<d_, Refs_, Items_, Alloc_, Storage_ > Self;
typedef Refs_ Refs;
typedef typename Base::Dart Dart;
typedef typename Base::Dart_handle Dart_handle;
typedef typename Base::Dart_const_handle Dart_const_handle;
@ -214,28 +212,34 @@ namespace CGAL {
/** Copy the given combinatorial map 'amap' into *this.
* Note that both CMap can have different dimensions and/or non void attributes.
* Here CMap2 is necessarily non const; while Dart_handle_2 can be a const or non const handle.
* This is the "generic" method, called by the different variants below.
* Marks reserved and automatic attributes management are not updated.
* @param amap the combinatorial map to copy.
* @param origin_to_copy associative array from original darts to copy darts
* @param origin_to_copy associative array from copy darts to original darts
* @param converters tuple of functors, one per attribute, to transform original attributes into copies
* @param dartinfoconverter functor to transform original information of darts into information of copies
* @param pointconverter functor to transform points in original map into points of copies.
* @param copy_perforated_darts true to copy also darts marked perforated (if any)
* @param mark_perforated_darts true to mark darts wich are copies of perforated darts (if any)
* @post *this is valid.
*/
template <unsigned int d2, typename Refs2, typename Items2, typename Alloc2,
typename Storage2,
template <typename CMap2, typename Dart_handle_2,
typename Converters, typename DartInfoConverter,
typename PointConverter>
void copy(const Combinatorial_map_base<d2, Refs2, Items2, Alloc2, Storage2>& amap,
const Converters& converters,
const DartInfoConverter& dartinfoconverter,
const PointConverter& pointconverter,
boost::unordered_map
<typename Combinatorial_map_base<d2, Refs2, Items2, Alloc2, Storage2>::
Dart_const_handle, Dart_handle>* origin_to_copy=NULL,
boost::unordered_map
<Dart_handle, typename Combinatorial_map_base<d2, Refs2, Items2,
Alloc2, Storage2>::Dart_const_handle>* copy_to_origin=NULL)
void generic_copy(CMap2& amap,
boost::unordered_map<Dart_handle_2, Dart_handle>* origin_to_copy,
boost::unordered_map<Dart_handle, Dart_handle_2>* copy_to_origin,
const Converters& converters,
const DartInfoConverter& dartinfoconverter,
const PointConverter& pointconverter,
bool copy_perforated_darts=false,
size_type mark_perforated=INVALID_MARK)
{
typedef Combinatorial_map_base<d2, Refs2, Items2, Alloc2, Storage2> CMap2;
this->clear();
this->mnb_used_marks = amap.mnb_used_marks;
/*this->mnb_used_marks = amap.mnb_used_marks;
this->mmask_marks = amap.mmask_marks;
this->automatic_attributes_management =
amap.automatic_attributes_management;
@ -249,36 +253,41 @@ namespace CGAL {
this->mnb_times_reserved_marks[i] = amap.mnb_times_reserved_marks[i];
}
init_dart(null_dart_handle, amap.get_marks(amap.null_dart_handle));
init_dart(null_dart_handle, amap.get_marks(amap.null_dart_handle));*/
// Create an mapping between darts of the two maps (originals->copies).
// (here we cannot use CGAL::Unique_hash_map because it does not provide
// iterators...
boost::unordered_map<typename CMap2::Dart_const_handle, Dart_handle>
local_dartmap;
if (origin_to_copy==NULL) // Used local_dartmap if user does not provides its own unordered_map
boost::unordered_map<Dart_handle_2, Dart_handle> local_dartmap;
if (origin_to_copy==NULL) // Use local_dartmap if user does not provides its own unordered_map
{ origin_to_copy=&local_dartmap; }
Dart_handle new_dart;
for (typename CMap2::Dart_const_range::const_iterator
it=amap.darts().begin(), itend=amap.darts().end();
it!=itend; ++it)
for (typename CMap2::Dart_range::iterator it=amap.darts().begin(),
itend=amap.darts().end(); it!=itend; ++it)
{
new_dart=mdarts.emplace();
init_dart(new_dart, amap.get_marks(it));
if (copy_perforated_darts || !amap.is_perforated(it))
{
new_dart=mdarts.emplace();
init_dart(new_dart); // , amap.get_marks(it));
(*origin_to_copy)[it]=new_dart;
if (copy_to_origin!=NULL) { (*copy_to_origin)[new_dart]=it; }
if (mark_perforated!=INVALID_MARK && amap.is_perforated(it))
{ mark(new_dart, mark_perforated); }
internal::Copy_dart_info_functor<Refs2, Refs, DartInfoConverter>::run
(static_cast<const Refs2&>(amap), static_cast<Refs&>(*this),
(*origin_to_copy)[it]=new_dart;
if (copy_to_origin!=NULL) { (*copy_to_origin)[new_dart]=it; }
internal::Copy_dart_info_functor
<typename CMap2::Refs, Refs, DartInfoConverter>::run
(static_cast<typename CMap2::Refs&>(amap), static_cast<Refs&>(*this),
it, new_dart, dartinfoconverter);
}
}
unsigned int min_dim=(dimension<amap.dimension?dimension:amap.dimension);
typename boost::unordered_map<typename CMap2::Dart_const_handle,Dart_handle>
::iterator dartmap_iter, dartmap_iter_end=origin_to_copy->end();
typename boost::unordered_map<Dart_handle_2,Dart_handle>::iterator
dartmap_iter, dartmap_iter_end=origin_to_copy->end();
for (dartmap_iter=origin_to_copy->begin(); dartmap_iter!=dartmap_iter_end;
++dartmap_iter)
{
@ -298,9 +307,9 @@ namespace CGAL {
++dartmap_iter)
{
Helper::template Foreach_enabled_attributes
< internal::Copy_attributes_functor <Refs2, Refs, Converters,
PointConverter> >::
run(static_cast<const Refs2&>(amap), static_cast<Refs&>(*this),
< internal::Copy_attributes_functor<typename CMap2::Refs, Refs,
Converters, PointConverter> >::
run(static_cast<const typename CMap2::Refs&>(amap), static_cast<Refs&>(*this),
dartmap_iter->first, dartmap_iter->second,
converters, pointconverter);
}
@ -308,79 +317,167 @@ namespace CGAL {
CGAL_assertion (is_valid());
}
template <unsigned int d2, typename Refs2, typename Items2, typename Alloc2,
typename Storage2>
void copy(const Combinatorial_map_base<d2, Refs2, Items2, Alloc2, Storage2>& amap,
// (1a) copy(amap, converters, dartinfoconverter, pointconverter)
template<typename CMap2, typename Converters, typename DartInfoConverter,
typename PointConverter>
void copy(CMap2& amap,
boost::unordered_map
<typename Combinatorial_map_base<d2, Refs2, Items2, Alloc2,
Storage2>::Dart_const_handle, Dart_handle>* origin_to_copy=NULL,
<typename CMap2::Dart_handle, Dart_handle>* origin_to_copy,
boost::unordered_map
<Dart_handle, typename Combinatorial_map_base<d2, Refs2, Items2,
Alloc2, Storage2>::Dart_const_handle>* copy_to_origin=NULL)
{
CGAL::cpp11::tuple<> converters;
Default_converter_dart_info<Refs2, Refs> dartinfoconverter;
Default_converter_cmap_0attributes_with_point<Refs2, Refs> pointconverter;
copy(amap, converters, dartinfoconverter, pointconverter,
origin_to_copy, copy_to_origin);
}
template <unsigned int d2, typename Refs2, typename Items2, typename Alloc2,
typename Storage2, typename Converters>
void copy(const Combinatorial_map_base<d2, Refs2, Items2,
Alloc2, Storage2>& amap,
const Converters& converters,
boost::unordered_map
<typename Combinatorial_map_base<d2, Refs2, Items2, Alloc2,
Storage2>::Dart_const_handle, Dart_handle>* origin_to_copy=NULL,
boost::unordered_map
<Dart_handle, typename Combinatorial_map_base<d2, Refs2, Items2,
Alloc2, Storage2>::Dart_const_handle>* copy_to_origin=NULL)
{
Default_converter_cmap_0attributes_with_point<Refs2, Refs> pointconverter;
Default_converter_dart_info<Refs2, Refs> dartinfoconverter;
copy(amap, converters, dartinfoconverter, pointconverter,
origin_to_copy, copy_to_origin);
}
template <unsigned int d2, typename Refs2, typename Items2, typename Alloc2,
typename Storage2,
typename Converters, typename DartInfoConverter>
void copy(const Combinatorial_map_base<d2, Refs2, Items2,
Alloc2, Storage2>& amap,
<Dart_handle, typename CMap2::Dart_handle>* copy_to_origin,
const Converters& converters,
const DartInfoConverter& dartinfoconverter,
boost::unordered_map
<typename Combinatorial_map_base<d2, Refs2, Items2, Alloc2,
Storage2>::Dart_const_handle, Dart_handle>* origin_to_copy=NULL,
boost::unordered_map
<Dart_handle, typename Combinatorial_map_base<d2, Refs2, Items2,
Alloc2, Storage2>::Dart_const_handle>* copy_to_origin=NULL)
const PointConverter& pointconverter,
bool copy_perforated_darts=false,
size_type mark_perforated=INVALID_MARK)
{
Default_converter_cmap_0attributes_with_point<Refs2, Refs> pointconverter;
copy(amap, converters, dartinfoconverter, pointconverter,
origin_to_copy, copy_to_origin);
generic_copy<CMap2, typename CMap2::Dart_handle, Converters,
DartInfoConverter, PointConverter>
(amap, origin_to_copy, copy_to_origin,
converters, dartinfoconverter, pointconverter,
copy_perforated_darts, mark_perforated);
}
// (1b) copy_from_const(const amap, converters, dartinfoconverter, pointconverter)
template<typename CMap2, typename Converters, typename DartInfoConverter,
typename PointConverter>
void copy_from_const(const CMap2& amap,
boost::unordered_map
<typename CMap2::Dart_const_handle, Dart_handle>* origin_to_copy,
boost::unordered_map
<Dart_handle, typename CMap2::Dart_const_handle>* copy_to_origin,
const Converters& converters,
const DartInfoConverter& dartinfoconverter,
const PointConverter& pointconverter,
bool copy_perforated_darts=false,
size_type mark_perforated=INVALID_MARK)
{
generic_copy<CMap2, typename CMap2::Dart_const_handle, Converters,
DartInfoConverter, PointConverter>
(const_cast<CMap2&>(amap), origin_to_copy, copy_to_origin,
converters, dartinfoconverter, pointconverter,
copy_perforated_darts, mark_perforated);
}
// (2a) copy(amap, converters, dartinfoconverter)
template<typename CMap2, typename Converters, typename DartInfoConverter>
void copy(CMap2& amap,
boost::unordered_map
<typename CMap2::Dart_handle, Dart_handle>* origin_to_copy,
boost::unordered_map
<Dart_handle, typename CMap2::Dart_handle>* copy_to_origin,
const Converters& converters,
const DartInfoConverter& dartinfoconverter,
bool copy_perforated_darts=false,
size_type mark_perforated=INVALID_MARK)
{
Default_converter_cmap_0attributes_with_point<typename CMap2::Refs, Refs>
pointconverter;
copy(amap, origin_to_copy, copy_to_origin,
converters, dartinfoconverter, pointconverter,
copy_perforated_darts, mark_perforated);
}
// (2b) copy_from_const(const amap, converters, dartinfoconverter)
template <typename CMap2, typename Converters, typename DartInfoConverter>
void copy_from_const(const CMap2& amap,
boost::unordered_map
<typename CMap2::Dart_const_handle, Dart_handle>* origin_to_copy,
boost::unordered_map
<Dart_handle, typename CMap2::Dart_const_handle>* copy_to_origin,
const Converters& converters,
const DartInfoConverter& dartinfoconverter,
bool copy_perforated_darts=false,
size_type mark_perforated=INVALID_MARK)
{
Default_converter_cmap_0attributes_with_point<typename CMap2::Refs, Refs>
pointconverter;
copy_from_const(amap, origin_to_copy, copy_to_origin,
converters, dartinfoconverter, pointconverter,
copy_perforated_darts, mark_perforated);
}
// (3a) copy(amap, converters)
template<typename CMap2, typename Converters>
void copy(CMap2& amap,
boost::unordered_map
<typename CMap2::Dart_handle, Dart_handle>* origin_to_copy,
boost::unordered_map
<Dart_handle, typename CMap2::Dart_handle>* copy_to_origin,
const Converters& converters,
bool copy_perforated_darts=false,
size_type mark_perforated=INVALID_MARK)
{
Default_converter_dart_info<typename CMap2::Refs, Refs> dartinfoconverter;
copy(amap, origin_to_copy, copy_to_origin, converters, dartinfoconverter,
copy_perforated_darts, mark_perforated);
}
// (3b) copy_from_const(const amap, converters)
template <typename CMap2, typename Converters>
void copy_from_const(const CMap2& amap,
boost::unordered_map
<typename CMap2::Dart_const_handle, Dart_handle>* origin_to_copy,
boost::unordered_map
<Dart_handle, typename CMap2::Dart_const_handle>* copy_to_origin,
const Converters& converters,
bool copy_perforated_darts=false,
size_type mark_perforated=INVALID_MARK)
{
Default_converter_dart_info<typename CMap2::Refs, Refs> dartinfoconverter;
copy_from_const(amap, origin_to_copy, copy_to_origin, converters, dartinfoconverter,
copy_perforated_darts, mark_perforated);
}
// (4a) copy(amap)
template<typename CMap2>
void copy(CMap2& amap,
boost::unordered_map
<typename CMap2::Dart_handle, Dart_handle>* origin_to_copy=nullptr,
boost::unordered_map
<Dart_handle, typename CMap2::Dart_handle>* copy_to_origin=nullptr,
bool copy_perforated_darts=false,
size_type mark_perforated=INVALID_MARK)
{
CGAL::cpp11::tuple<> converters;
copy(amap, origin_to_copy, copy_to_origin, converters,
copy_perforated_darts, mark_perforated);
}
// (4b) copy_from_const(const amap)
template <typename CMap2>
void copy_from_const(const CMap2& amap,
boost::unordered_map
<typename CMap2::Dart_const_handle, Dart_handle>* origin_to_copy=nullptr,
boost::unordered_map
<Dart_handle, typename CMap2::Dart_const_handle>* copy_to_origin=nullptr,
bool copy_perforated_darts=false,
size_type mark_perforated=INVALID_MARK)
{
CGAL::cpp11::tuple<> converters;
copy_from_const(amap, origin_to_copy, copy_to_origin, converters,
copy_perforated_darts, mark_perforated);
}
// Copy constructor from a map having exactly the same type.
Combinatorial_map_base (const Self & amap)
{ copy(amap); }
Combinatorial_map_base (const Self & amap): Combinatorial_map_base()
{ copy_from_const(amap); }
// "Copy constructor" from a map having different type.
template <unsigned int d2, typename Refs2, typename Items2, typename Alloc2,
typename Storage2>
Combinatorial_map_base(const Combinatorial_map_base<d2, Refs2, Items2,
Alloc2, Storage2>& amap)
{ copy(amap); }
Alloc2, Storage2>& amap): Combinatorial_map_base()
{ copy_from_const(amap); }
// "Copy constructor" from a map having different type.
template <unsigned int d2, typename Refs2, typename Items2, typename Alloc2,
typename Storage2, typename Converters>
Combinatorial_map_base(const Combinatorial_map_base<d2, Refs2, Items2,
Alloc2, Storage2>& amap,
const Converters& converters)
{ copy(amap, converters); }
const Converters& converters):
Combinatorial_map_base()
{ copy_from_const(amap, nullptr, nullptr, converters); }
// "Copy constructor" from a map having different type.
template <unsigned int d2, typename Refs2, typename Items2, typename Alloc2,
@ -388,8 +485,9 @@ namespace CGAL {
Combinatorial_map_base(const Combinatorial_map_base<d2, Refs2, Items2,
Alloc2, Storage2>& amap,
const Converters& converters,
const DartInfoConverter& dartinfoconverter)
{ copy(amap, converters, dartinfoconverter); }
const DartInfoConverter& dartinfoconverter):
Combinatorial_map_base()
{ copy_from_const(amap, nullptr, nullptr, converters, dartinfoconverter); }
// "Copy constructor" from a map having different type.
template <unsigned int d2, typename Refs2, typename Items2, typename Alloc2,
@ -400,14 +498,15 @@ namespace CGAL {
Alloc2, Storage2>& amap,
const Converters& converters,
const DartInfoConverter& dartinfoconverter,
const PointConverter& pointconverter)
{ copy(amap, converters, dartinfoconverter, pointconverter); }
const PointConverter& pointconverter):
Combinatorial_map_base()
{ copy_from_const(amap, nullptr, nullptr, converters, dartinfoconverter, pointconverter); }
/** Affectation operation. Copies one map to the other.
* @param amap a combinatorial map.
* @return A copy of that combinatorial map.
*/
Self & operator= (const Self & amap)
Self & operator=(const Self & amap)
{
if (this!=&amap)
{
@ -460,8 +559,9 @@ namespace CGAL {
boost::unordered_map
<Dart_handle,
typename boost::graph_traits<HEG>::halfedge_descriptor>*
copy_to_origin=NULL)
copy_to_origin=NULL,
bool copy_perforated_darts=false,
size_type mark_perforated=INVALID_MARK)
{
// Create an mapping between darts of the two maps (originals->copies).
// (here we cannot use CGAL::Unique_hash_map because it does not provide
@ -477,9 +577,13 @@ namespace CGAL {
it=halfedges(heg).begin(), itend=halfedges(heg).end();
it!=itend; ++it)
{
if (!CGAL::is_border(*it, heg))
if (copy_perforated_darts || !CGAL::is_border(*it, heg))
{
new_dart=mdarts.emplace();
if (mark_perforated!=INVALID_MARK && CGAL::is_border(*it, heg))
{ mark(new_dart, mark_perforated); }
(*origin_to_copy)[*it]=new_dart;
if (copy_to_origin!=NULL) { (*copy_to_origin)[new_dart]=*it; }
}
@ -495,7 +599,8 @@ namespace CGAL {
(*origin_to_copy)[CM_ADL_next(dartmap_iter->first, heg)],
1);
if (!CGAL::is_border(CM_ADL_opposite(dartmap_iter->first, heg), heg) &&
if ((copy_perforated_darts ||
!CGAL::is_border(CM_ADL_opposite(dartmap_iter->first, heg), heg)) &&
(dartmap_iter->first)<CM_ADL_opposite(dartmap_iter->first, heg))
{
basic_link_beta(dartmap_iter->second,
@ -1108,6 +1213,19 @@ namespace CGAL {
size_type unmark_cell(Dart_const_handle adart, size_type amark) const
{ return CGAL::unmark_cell<Self, i, d>(*this, adart, amark); }
template <unsigned int i, unsigned int d=dimension>
size_type mark_oriented_cell(Dart_const_handle adart, size_type amark,
size_type amark2=INVALID_MARK) const
{ return CGAL::mark_oriented_cell<Self, i, d>(*this, adart, amark, amark2); }
template <unsigned int i, unsigned int d=dimension>
size_type unmark_oriented_cell(Dart_const_handle adart, size_type amark,
size_type amark2=INVALID_MARK) const
{ return CGAL::unmark_oriented_cell<Self, i, d>(*this, adart, amark, amark2); }
std::size_t orient(size_type amark) const
{ negate_mark(amark); return number_of_darts(); }
/** Test if this map is without boundary for a given dimension.
* @param i the dimension.
* @return true iff all the darts are not i-free.
@ -2631,7 +2749,7 @@ namespace CGAL {
while (beta<1>(dd1)!=d2)
{
if (this->template is_free<2>(beta<1>(dd1)))
{ return std::numeric_limits<std::size_t>::max(); }
{ return (std::numeric_limits<std::size_t>::max)(); }
++res;
dd1=beta<1, 2>(dd1);
@ -2653,7 +2771,7 @@ namespace CGAL {
if (d2==beta<2>(d1)) { return 0; }
if (this->template is_free<2>(d1) || this->template is_free<2>(d2))
{ return std::numeric_limits<std::size_t>::max(); }
{ return (std::numeric_limits<std::size_t>::max)(); }
d1=beta<2>(d1);
d2=beta<2>(d2);
@ -2662,7 +2780,7 @@ namespace CGAL {
while (beta<0>(dd1)!=d2)
{
if (this->template is_free<2>(beta<0>(dd1)))
{ return std::numeric_limits<std::size_t>::max(); }
{ return (std::numeric_limits<std::size_t>::max)(); }
++res;
dd1=beta<0, 2>(dd1);
@ -4648,14 +4766,7 @@ namespace CGAL {
typename Helper::Merge_functors m_onmerge_functors;
};
template < unsigned int d_,
#if defined(CGAL_CMAP_DART_DEPRECATED) && !defined(CGAL_NO_DEPRECATED_CODE)
class Items_=Combinatorial_map_min_items<d_>,
#else
class Items_=Generic_map_min_items,
#endif
class Alloc_=CGAL_ALLOCATOR(int),
class Storage_= Combinatorial_map_storage_1<d_, Items_, Alloc_> >
template < unsigned int d_, class Items_, class Alloc_, class Storage_ >
class Combinatorial_map :
public Combinatorial_map_base<d_,
Combinatorial_map<d_,Items_,Alloc_, Storage_>,

View File

@ -81,7 +81,7 @@ namespace CGAL
typename Map::size_type amark)
{
amap.negate_mark(amark);
bool res=CGAL::is_whole_orbit_marked<Map,Iterator>(amap, adart, amark);
bool res=CGAL::template is_whole_orbit_marked<Map,Iterator>(amap, adart, amark);
amap.negate_mark(amark);
return res;
}
@ -128,7 +128,7 @@ namespace CGAL
{
amap.negate_mark(amark);
typename Map::size_type
res=CGAL::mark_orbit<Map, Iterator>(amap, adart, amark);
res=CGAL::template mark_orbit<Map, Iterator>(amap, adart, amark);
amap.negate_mark(amark);
return res;
}
@ -154,7 +154,7 @@ namespace CGAL
typename Map::Dart_const_handle adart1,
typename Map::Dart_const_handle adart2)
{
return CGAL::belong_to_same_cell<Map,i,Map::dimension>(amap,adart1,adart2);
return CGAL::template belong_to_same_cell<Map,i,Map::dimension>(amap,adart1,adart2);
}
@ -169,7 +169,7 @@ namespace CGAL
typename Map::Dart_const_handle adart,
typename Map::size_type amark)
{
return CGAL::is_whole_orbit_marked<Map,
return CGAL::template is_whole_orbit_marked<Map,
typename Map::template Dart_of_cell_range<i,d>::const_iterator>
(amap, adart, amark);
}
@ -179,7 +179,8 @@ namespace CGAL
typename Map::Dart_const_handle adart,
typename Map::size_type amark)
{
return CGAL::is_whole_cell_marked<Map,i,Map::dimension>(amap,adart,amark);
return CGAL::template is_whole_cell_marked<Map,i,Map::dimension>
(amap,adart,amark);
}
/** Test if all the darts of a given cell are unmarked.
@ -193,7 +194,7 @@ namespace CGAL
typename Map::Dart_const_handle adart,
typename Map::size_type amark)
{
return CGAL::is_whole_orbit_unmarked<Map,
return CGAL::template is_whole_orbit_unmarked<Map,
typename Map::template Dart_of_cell_range<i,d>::const_iterator>
(amap, adart, amark);
}
@ -203,7 +204,7 @@ namespace CGAL
typename Map::Dart_const_handle adart,
typename Map::size_type amark)
{
return CGAL::is_whole_cell_unmarked<Map,i,Map::dimension>
return CGAL::template is_whole_cell_unmarked<Map,i,Map::dimension>
(amap,adart,amark);
}
@ -218,7 +219,7 @@ namespace CGAL
typename Map::size_type mark_cell(const Map & amap,
typename Map::Dart_const_handle adart,
typename Map::size_type amark)
{ return CGAL::mark_orbit<Map,
{ return CGAL::template mark_orbit<Map,
typename Map::template Dart_of_cell_basic_range<i,d>::const_iterator>
(amap, adart, amark); }
@ -226,9 +227,9 @@ namespace CGAL
typename Map::size_type mark_cell(const Map & amap,
typename Map::Dart_const_handle adart,
typename Map::size_type amark)
{ return CGAL::mark_cell<Map,i,Map::dimension>(amap, adart, amark);}
{ return CGAL::template mark_cell<Map,i,Map::dimension>(amap, adart, amark);}
/** Unmark a given orbit with a given mark.
/** Unmark a given cell with a given mark.
* @param amap a combinatorial map.
* @param adart a dart of the cell.
* @param amark the mark.
@ -239,7 +240,7 @@ namespace CGAL
typename Map::size_type unmark_cell(const Map & amap,
typename Map::Dart_const_handle adart,
typename Map::size_type amark)
{ return CGAL::unmark_orbit<Map,
{ return CGAL::template unmark_orbit<Map,
typename Map::template Dart_of_cell_basic_range<i,d>::const_iterator>
(amap, adart, amark);}
@ -247,7 +248,156 @@ namespace CGAL
typename Map::size_type unmark_cell(const Map & amap,
typename Map::Dart_const_handle adart,
typename Map::size_type amark)
{ return CGAL::unmark_cell<Map,i,Map::dimension>(amap, adart, amark); }
{ return CGAL::template unmark_cell<Map,i,Map::dimension>(amap, adart, amark); }
/// Functor to test if the given dart must be marked, when we want
/// to mark an oriented orbit. By default (for CMap), return true.
template<class Map, class T=typename Map::Combinatorial_data_structure>
struct Need_to_mark_for_oriented_cell
{
static bool run(const Map & /*amap*/,
typename Map::Dart_const_handle /*adart*/,
typename Map::size_type /*amark*/,
OperationState /*op*/)
{ return true; }
};
struct Generalized_map_tag;
/// Specialization for GMap. We mark one out of two darts.
template<class Map>
struct Need_to_mark_for_oriented_cell<Map, CGAL::Generalized_map_tag>
{
static bool run(const Map & amap,
typename Map::Dart_const_handle adart,
typename Map::size_type amark,
OperationState op)
{
CGAL_assertion(op!=OP_END);
if (op==OP_NONE) return true;
bool all_darts_unmarked=true;
for (int i=0; all_darts_unmarked && i<=(int)Map::dimension; ++i)
{
if (!amap.is_free(adart, i) &&
amap.is_marked(amap.alpha(adart, i), amark))
{ all_darts_unmarked=false; }
}
return all_darts_unmarked;
}
};
/** Mark a given oriented orbit with a given mark. For combinatorial map,
* equivalent to mark_orbit. For generalized map, mark one out of two dart
* if the orbit is orientable. If amark2!=INVALID_MARK, mark also all the darts
* of the orbit with amark2.
* @param amap a combinatorial map / generalized.
* @param adart a dart of the orbit.
* @param amark the mark.
* @param amark2 a second mark.
* @return the number of darts of the marked orbit.
* @pre The whole orbit must be unmarked.
*/
template < class Map, class Iterator >
typename Map::size_type mark_oriented_orbit(const Map & amap,
typename Map::Dart_const_handle adart,
typename Map::size_type amark,
typename Map::size_type amark2=Map::INVALID_MARK)
{
CGAL_static_assertion( (boost::is_same<typename Iterator::Basic_iterator,
Tag_true>::value) );
CGAL_assertion( (is_whole_orbit_unmarked<Map,
CMap_non_basic_iterator<Map,Iterator> >
(amap, adart, amark)) );
typename Map::size_type res=0;
typename Map::size_type amark3=(amark2==Map::INVALID_MARK?amap.get_new_mark():amark2);
for (Iterator it(amap, adart, amark3); it.cont(); ++it)
{
amap.mark(it, amark3);
if (CGAL::template Need_to_mark_for_oriented_cell<Map>::
run(amap, it, amark, it.prev_operation()))
{
amap.mark(it, amark);
++res;
}
}
if (amark2==Map::INVALID_MARK)
{
CGAL::template unmark_orbit<Map, Iterator>(amap, adart, amark3);
amap.free_mark(amark3);
}
return res;
}
template < class Map, class Iterator >
typename Map::size_type unmark_oriented_orbit(const Map & amap,
typename Map::Dart_const_handle adart,
typename Map::size_type amark,
typename Map::size_type amark2=Map::INVALID_MARK)
{
amap.negate_mark(amark);
if (amark2!=Map::INVALID_MARK) { amap.negate_mark(amark2); }
typename Map::size_type
res=CGAL::template mark_oriented_orbit<Map, Iterator>(amap, adart, amark, amark2);
amap.negate_mark(amark);
if (amark2!=Map::INVALID_MARK) { amap.negate_mark(amark2); }
return res;
}
/** Mark a given oriented cell with a given mark. For combinatorial map,
* equivalent to mark_cell. For generalized map, mark one out of two dart
* if the cell is orientable. If amark2!=INVALID_MARK, mark also all the darts
* of the cell with amark2.
* @param amap a combinatorial map / generalized.
* @param adart a dart of the cell.
* @param amark the mark.
* @param amark2 a second mark.
* @return the number of darts of the marked cell.
* @pre The whole cell must be unmarked.
*/
template < class Map, unsigned int i, unsigned int d >
typename Map::size_type mark_oriented_cell(const Map & amap,
typename Map::Dart_const_handle adart,
typename Map::size_type amark,
typename Map::size_type amark2=Map::INVALID_MARK)
{ return CGAL::template mark_oriented_orbit
<Map, typename Map::template Dart_of_cell_basic_range<i,d>::const_iterator>
(amap, adart, amark, amark2); }
template < class Map, unsigned int i>
typename Map::size_type mark_oriented_cell(const Map & amap,
typename Map::Dart_const_handle adart,
typename Map::size_type amark,
typename Map::size_type amark2=Map::INVALID_MARK)
{ return CGAL::template mark_oriented_cell<Map,i,Map::dimension>
(amap, adart, amark, amark2);}
/** Unmark a given oriented cell with a given mark.
* @param amap a combinatorial map.
* @param adart a dart of the cell.
* @param amark the mark.
* @return the number of darts of the unmarked cell.
* @pre The whole cell must be marked.
*/
template < class Map, unsigned int i, unsigned int d >
typename Map::size_type unmark_oriented_cell(const Map & amap,
typename Map::Dart_const_handle adart,
typename Map::size_type amark,
typename Map::size_type amark2=Map::INVALID_MARK)
{ return CGAL::template unmark_oriented_orbit
<Map, typename Map::template Dart_of_cell_basic_range<i,d>::const_iterator>
(amap, adart, amark, amark2);}
template < class Map, unsigned int i >
typename Map::size_type unmark_oriented_cell(const Map & amap,
typename Map::Dart_const_handle adart,
typename Map::size_type amark,
typename Map::size_type amark2=Map::INVALID_MARK)
{ return CGAL::template unmark_oriented_cell<Map,i,Map::dimension>
(amap, adart, amark, amark2); }
/** Compute the degree of a given i-cell c.
* The degree is the number of distinct i+1 cells incident to c.

View File

@ -0,0 +1,51 @@
// Copyright (c) 2010-2011 CNRS and LIRIS' Establishments (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) : Guillaume Damiand <guillaume.damiand@liris.cnrs.fr>
//
#ifndef COMBINATORIAL_MAP_FWD_H
#define COMBINATORIAL_MAP_FWD_H 1
#include <CGAL/memory.h>
namespace CGAL {
#if defined(CGAL_CMAP_DART_DEPRECATED) && !defined(CGAL_NO_DEPRECATED_CODE)
template <unsigned int d>
struct Combinatorial_map_min_items;
#else
struct Generic_map_min_items;
#endif
template<unsigned int d_, class Items_, class Alloc_ >
class Combinatorial_map_storage_1;
template < unsigned int d_, class Refs_,
#if defined(CGAL_CMAP_DART_DEPRECATED) && !defined(CGAL_NO_DEPRECATED_CODE)
class Items_=Combinatorial_map_min_items<d_>,
#else
class Items_=Generic_map_min_items,
#endif
class Alloc_=CGAL_ALLOCATOR(int),
class Storage_= Combinatorial_map_storage_1<d_, Items_, Alloc_> >
class Combinatorial_map_base;
template < unsigned int d_,
#if defined(CGAL_CMAP_DART_DEPRECATED) && !defined(CGAL_NO_DEPRECATED_CODE)
class Items_=Combinatorial_map_min_items<d_>,
#else
class Items_=Generic_map_min_items,
#endif
class Alloc_=CGAL_ALLOCATOR(int),
class Storage_= Combinatorial_map_storage_1<d_, Items_, Alloc_> >
class Combinatorial_map;
} // CGAL
#endif // COMBINATORIAL_MAP_FWD_H

View File

@ -1,87 +0,0 @@
// Copyright (c) 2019 CNRS and LIRIS' Establishments (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) : Guillaume Damiand <guillaume.damiand@liris.cnrs.fr>
//
#ifndef CGAL_FUNCTORS_FOR_FACE_GRAPH_WRAPPER_H
#define CGAL_FUNCTORS_FOR_FACE_GRAPH_WRAPPER_H 1
#include <boost/graph/graph_traits.hpp>
#include <CGAL/boost/graph/helpers.h>
#include <CGAL/Iterators_for_face_graph_wrapper.h>
////////////////////////////////////////////////////////////////////////////////
/** This file contains the following functors for Face_graph_wrapper:
* Is_free<typename HEG, unsigned int i>::
operator() (const HEG& heg, Dart_const_handle dh)
* Get_beta<typename HEG, unsigned int i>::
operator() (const HEG& heg, Dart_const_handle dh)
*/
////////////////////////////////////////////////////////////////////////////////
namespace CGAL
{
/// Is_free
//template<typename HEG, unsigned int i>
//struct Is_free
//{
// typedef typename boost::graph_traits<HEG>::halfedge_descriptor Dart_const_handle;
// static bool value(const HEG& /*heg*/, Dart_const_handle /*dh*/)
// { CGAL_static_assertion(i==0 || i==1); return false; }
//};
//template<typename HEG>
//struct Is_free<HEG, 2>
//{
// typedef typename boost::graph_traits<HEG>::halfedge_descriptor Dart_const_handle;
// static bool value(const HEG& heg, Dart_const_handle dh)
// { return is_border(opposite(dh, heg), heg); }
//};
////////////////////////////////////////////////////////////////////////////////
/// Get_beta
template<typename HEG, unsigned int i>
struct Get_beta
{
typedef typename boost::graph_traits<HEG>::halfedge_descriptor Dart_const_handle;
static Dart_const_handle value(const HEG& /*heg*/, Dart_const_handle /*dh*/)
{ /* CGAL_static_assertion(false);*/
std::cout<<"ERROR Get_beta<HEG, "<<i<<">"<<std::endl;
CGAL_assertion(false);
return nullptr;
}
};
template<typename HEG>
struct Get_beta<HEG, 0>
{
typedef typename boost::graph_traits<HEG>::halfedge_descriptor Dart_const_handle;
static Dart_const_handle value(const HEG& heg, Dart_const_handle dh)
{ return prev(dh, heg); }
};
template<typename HEG>
struct Get_beta<HEG, 1>
{
typedef typename boost::graph_traits<HEG>::halfedge_descriptor Dart_const_handle;
static Dart_const_handle value(const HEG& heg, Dart_const_handle dh)
{ return next(dh, heg); }
};
template<typename HEG>
struct Get_beta<HEG, 2>
{
typedef typename boost::graph_traits<HEG>::halfedge_descriptor Dart_const_handle;
static Dart_const_handle value(const HEG& heg, Dart_const_handle dh)
{
//if (Is_free<HEG, 2>::value(heg, dh)) return Dart_const_handle();
return opposite(dh, heg);
}
};
////////////////////////////////////////////////////////////////////////////////
} // namespace CGAL
#endif // CGAL_FUNCTORS_FOR_FACE_GRAPH_WRAPPER_H //
// EOF //

View File

@ -39,7 +39,7 @@ class Tee_for_output_iterator
public:
Tee_for_output_iterator(const OutputIterator& o) : o_it(o)
{ PTR = (Rep*) new _Tee_for_output_iterator_rep<T>(); }
{ PTR.p = (Rep*) new _Tee_for_output_iterator_rep<T>(); }
Tee_for_output_iterator<OutputIterator,T>&
operator=(const T& value)
@ -82,7 +82,7 @@ public:
_Tee_for_output_iterator_rep<T>*
ptr()
{ return (_Tee_for_output_iterator_rep<T>*)PTR; }
{ return (_Tee_for_output_iterator_rep<T>*)(PTR.p); }
protected:
OutputIterator o_it;

View File

@ -201,6 +201,15 @@ if(CGAL_DOC_CREATE_LOGS)
file(MAKE_DIRECTORY "${CGAL_DOC_LOG_DIR}")
endif()
option(CGAL_EXTRACT_ALL_NO_DETAILED_IF_EMPTY "Use CGAL special doxygen setting EXTRACT_ALL_NO_DETAILED_IF_EMPTY." ON)
if(CGAL_EXTRACT_ALL_NO_DETAILED_IF_EMPTY)
set(CGAL_OPT_EXTRACT_ALL_NO_DETAILED_IF_EMPTY "EXTRACT_ALL_NO_DETAILED_IF_EMPTY = YES")
else()
# The default is NO, so we could leave it out, but it is better to have a commented out placeholder
# this will work for versions with and without the setting.
set(CGAL_OPT_EXTRACT_ALL_NO_DETAILED_IF_EMPTY "#EXTRACT_ALL_NO_DETAILED_IF_EMPTY = NO")
endif()
#we use two directories for the generation/reading of tag files to prevent issues
#if the targets are built in parallel
set(CGAL_DOC_TAG_GEN_DIR "${CMAKE_BINARY_DIR}/doc_gen_tags")
@ -344,6 +353,12 @@ else()
endforeach()
endif()
option(CGAL_BUILD_THREE_DOC "Build the documentation of the Three package" OFF)
if (NOT CGAL_BUILD_THREE_DOC)
list(REMOVE_ITEM CGAL_DOC_PACKAGES "Three")
endif()
foreach(package ${CGAL_DOC_PACKAGES})
configure_doxygen_package(${package})
endforeach()

View File

@ -13,7 +13,8 @@ GENERATE_TAGFILE = ${CGAL_DOC_TAG_GEN_DIR}/Manual.tag
EXAMPLE_PATH = ${CGAL_Convex_hull_2_EXAMPLE_DIR} \
${CGAL_Kernel_23_EXAMPLE_DIR} \
${CGAL_Poisson_surface_reconstruction_3_EXAMPLE_DIR} \
${CGAL_Surface_mesh_EXAMPLE_DIR}
${CGAL_Surface_mesh_EXAMPLE_DIR} \
${CGAL_Classification_EXAMPLE_DIR}
FILTER_PATTERNS = *.txt=${CMAKE_BINARY_DIR}/pkglist_filter
HTML_EXTRA_FILES += ${CGAL_DOC_RESOURCE_DIR}/hacks.js \

View File

@ -0,0 +1,320 @@
namespace CGAL {
/*!
\example Classification/gis_tutorial_example.cpp
*/
/*!
\page tuto_gis GIS (Geographic Information System)
\cgalAutoToc
\author Simon Giraudot
Many sensors used in GIS applications (for example LIDAR), generate
dense point clouds. Such applications often take advantage of more
advanced data structures: for example, Triangulated Irregular Networks
(TIN) that can be the base for Digital Evelation Models (DEM) and in
particular for the generation of Digital Terrain Models (DTM). Point
clouds can also be enriched by classification information that
segments the points into ground, vegetation and building points (or
other user-defined labels).
The definitions of some data structures may vary according to
different sources. We will use the following terms within this
tutorial:
- TIN: _Triangulated Irregular Network_, a 2D triangulation structure
that connects 3D points based on their projections on the horizontal
plane.
- DSM: _Digital Surface Model_, a model of the whole scanned surface
including buildings and vegetation. We use a TIN to store the DSM.
- DTM: _Digital Terrain Model_, a model of the bare ground surface
without objects like buildings or vegetation. We both use a TIN and a
raster to store a DTM.
- DEM: _Digital Elevation Model_, a more general term that includes
both DSM and DTM.
This tutorial illustrates the following scenario. From an input point
cloud, we first compute a DSM stored as a TIN. Then, we filter out
overly large facets that correspond either to building facades or to
vegetation noise. Large components corresponding to the ground are
kept. Holes are filled and the obtained DEM is remeshed. A raster DEM
and a set of contour polylines are generated from it. Finally,
supervised 3-label classification is performed to segment vegetation,
building and group points.
\section TutorialGIS_TIN Triangulated Irregular Network (TIN)
\cgal provides several triangulation data structures and algorithms. A
TIN can be generated by combining the 2D Delaunay triangulation with
projection traits: the triangulation structure is computed using the
2D positions of the points along a selected plane (usually, the
XY-plane), while the 3D positions of the points are kept for
visualization and measurements.
A TIN data structure can thus simply be defined the following way:
\snippet Classification/gis_tutorial_example.cpp TIN DS
\section TutorialGIS_DSM Digital Surface Model (DSM)
Point clouds in many formats (XYZ, OFF, PLY, LAS) can be easily loaded
into a `CGAL::Point_set_3` structure, using the stream
operator. Generating a DSM stored in TIN is then straightforward:
\snippet Classification/gis_tutorial_example.cpp Init DSM
Because the Delaunay triangulation of \cgal is a model of
`FaceGraph`, it is straightforward to convert the generated TIN into a
mesh structure such as `CGAL::Surface_mesh` and be saved into whatever
formats are supported by such structure:
\snippet Classification/gis_tutorial_example.cpp Save DSM
An example of a DSM computed this way on the San Fransisco data set
(see \ref TutorialGIS_Reference) is given in
\cgalFigureRef{TutorialGISFigTIN}.
\cgalFigureBegin{TutorialGISFigTIN, tin.jpg}
Input point cloud and output DSM.
\cgalFigureEnd
\section TutorialGIS_DTM Digital Terrain Model (DTM)
The generated DSM is used as a base for DTM computation, that is a
representation of the ground as another TIN after filtering non-ground
points.
We propose, as an example, a simple DTM estimation decomposed in the
following steps:
1. Thresholding the height of the facets to remove brutal changes of
elevation
2. Clustering the other facets into connected components
3. Filtering all components smaller than a user-defined threshold
This algorithm relies on 2 parameters: a height threshold that
corresponds to the minimum height of a building, and a perimeter
threshold that corresponds to the maximum size of a building on the 2D
projection.
\subsection TutorialGIS_DTM_info TIN With Info
Because it takes advantage of the flexible \cgal Delaunay
triangulation API, our TIN can be enriched with information on
vertices and/or on faces. In our case, each vertex keeps track of the
index of the corresponding point in the input point cloud (which will
allow to filter ground points afterwards), and each face is given the
index of its connected component.
\snippet Classification/gis_tutorial_example.cpp TIN_with_info
\subsection TutorialGIS_DTM_components Identifying Connected Components
Connected components are identified through a flooding algorithm: from
a seed face, all incident faces are inserted in the current connected
component unless their heights exceed the user-defined threshold.
\snippet Classification/gis_tutorial_example.cpp Components
This TIN enriched with connected component information can be saved as
a colored mesh:
\snippet Classification/gis_tutorial_example.cpp Save TIN with info
An example of a TIN colored by connected components is
given in \cgalFigureRef{TutorialGISFigComponents}.
\cgalFigureBegin{TutorialGISFigComponents, components.jpg}
TIN colored by connected components. Faces above height threshold are
not assigned to any component and are displayed in gray.
\cgalFigureEnd
\subsection TutorialGIS_DTM_filtering Filtering
Components smaller than the largest building can be removed this way:
\snippet Classification/gis_tutorial_example.cpp Filtering
\subsection Tutorial_DTM_hole_filling Hole Filling and Remeshing
Because simply removing vertices in the large areas covered by
buildings results in large Delaunay faces that offer a poor 3D
representation of the DTM, an additional step can help producing
better shaped meshes: faces larger than a threshold are removed and
filled with a hole filling algorithm that triangulates, refines and
fairs the holes.
The following snippet copies the TIN into a mesh while filtering out
overly large faces, then identifies the holes and fills them all
except for the largest one (which is the outer hull).
\snippet Classification/gis_tutorial_example.cpp Hole filling
Isotropic remeshing can also be performed as a final step in order to
produce a more regular mesh that is not constrained by the shape of 2D
Delaunay faces.
\snippet Classification/gis_tutorial_example.cpp Remeshing
\cgalFigureRef{TutorialGISFigProc} shows how these different steps
affect the output mesh and \cgalFigureRef{TutorialGISFigDTM} shows the
DTM isotropic mesh.
\cgalFigureBegin{TutorialGISFigProc, dtm_proc.jpg}
Raw DTM and postprocessing
\cgalFigureEnd
\cgalFigureBegin{TutorialGISFigDTM, dtm.jpg}
Final DTM.
\cgalFigureEnd
\section TutorialGIS_Raster Rastering
The TIN data structure can be combined with barycentric coordinates in
order to interpolate and thus rasterize a height map at any resolution
needed the information embedded in the vertices.
Because the latest two steps (hole filling and remeshing) were
performed on a 3D mesh, the hypothesis that our DTM is a 2.5D
representation may no longer be valid. We thus first rebuild a TIN
using the vertices of the isotropic DTM mesh lastly computed.
The following snippet generates a raster image of the height in the
form of rainbow ramp PPM file (simple bitmap format):
\snippet Classification/gis_tutorial_example.cpp Rastering
An example of a raster image with a rainbow ramp representing height
is given in \cgalFigureRef{TutorialGISFigRastering}.
\cgalFigureBegin{TutorialGISFigRastering, raster.jpg}
Raster visualisation of height using a rainbow ramp, ranging from
light blue for low values to dark red for high values.
\cgalFigureEnd
\section TutorialGIS_Contour Contouring
Extracting isolevels of a function defined on a TIN is another
application that can be done with \cgal. We demonstrate here how to
extract isolevels of height to build a topographic map.
\subsection TutorialGIS_Contour_Extraction Building a Contour Graph
The first step is to extract, from all faces of the triangulation, the
section of each isolevel that goes through that face, in the form of a
segment. The following functions allow to test if one isovalue does
cross a face, and to extract it then:
\snippet Classification/gis_tutorial_example.cpp Contouring functions
From these functions, we can create a graph of segments to process
later into a set of polylines. To do so, we use the
[boost::adjacency_list](https://www.boost.org/doc/libs/1_72_0/libs/graph/doc/adjacency_list.html)
structure and keep track of a mapping from the positions of
the end points to the vertices of the graph.
The following code computes 50 isovalues evenly distributed between
the minimum and maximum heights of the point cloud and creates a graph
containing all isolevels:
\snippet Classification/gis_tutorial_example.cpp Contouring extraction
\subsection TutorialGIS_Contour_Splitting Splitting Into Polylines
Once the graph is created, splitting it into polylines is easily
performed using the function \link split_graph_into_polylines()
`CGAL::split_graph_into_polylines()` \endlink:
\snippet Classification/gis_tutorial_example.cpp Contouring split
This function requires a visitor which is called when starting a
polyline, when adding a point to it and when ending it. Defining such
a class is straightforward in our case:
\snippet Classification/gis_tutorial_example.cpp Contouring visitor
\subsection TutorialGIS_Contour_Simplifying Simplifying
Because the output is quite noisy, users may want to simplify the
polylines. \cgal provides a polyline simplification algorithm that
guarantees that two polylines won't intersect after
simplification. This algorithm takes advantage of the
`CGAL::Constrained_triangulation_plus_2`, which embeds
polylines as a set of constraints:
\snippet Classification/gis_tutorial_example.cpp CDT
The following code simplifies the polyline set based on the squared
distance to the original polylines, stopping when no more vertex can
be removed without going farther than 4 times the average spacing.
\snippet Classification/gis_tutorial_example.cpp Contouring simplify
Examples of contours and simplifications are given in
\cgalFigureRef{TutorialGISFigContours}.
\cgalFigureBegin{TutorialGISFigContours, contours.png}
Contouring using 50 isovalues evenly spaced. Top: original contouring
using 148k vertices and simplification with a tolerance equal to the
average spacing of the input point cloud (3.4\% of the original
polyline vertices remaining). Bottom: simplification with tolerance 4
times the average spacing (1.3\% of vertices remaining) and with
tolerance 10 times the average spacing (0.9\% of vertices
remaining). Polylines are intersection-free in all cases.
\cgalFigureEnd
\section TutorialGIS_Classify Classifying
\cgal provides a package %Classification which can be used to segment a
point cloud into a user-defined label set. The state-of-the-art
classifier currently available in \cgal is the %random forest from
ETHZ. As it is a supervised classifier, a training set is needed.
The following snippet shows how to use some manually selected training
set to train a %fandom rorest classifier and compute a classification
regularized by a graph cut algorithm:
\snippet Classification/gis_tutorial_example.cpp Classification
An example of training set and resulting classification is given in
\cgalFigureRef{TutorialGISFigClassif}.
\cgalFigureBegin{TutorialGISFigClassif, classif_tuto.jpg}
Top: a slice of the point cloud classified by hand. Bottom: a
classification regularized by graph cut after training on 3 manually
classified slices.
\cgalFigureEnd
\section TutorialGIS_Code Full Code Example
All the code snippets used in this tutorial can be assembled to create
a full GIS pipeline (provided the correct _includes_ are
used). We give a full code example which achieves all the steps
described in this tutorial.
\include Classification/gis_tutorial_example.cpp
\section TutorialGIS_Reference References
This tutorial is based on the following \cgal packages:
- \ref PkgTriangulation2Ref
- \ref PkgPointSet3Ref
- \ref PkgPointSetProcessing3Ref
- \ref PkgSurface_mesh
- \ref PkgBGLRef
- \ref PkgPolygonMeshProcessingRef
- \ref PkgPolylineSimplification2Ref
- \ref PkgClassificationRef
The data set used throughout this tutorial comes from the
https://www.usgs.gov/ database, licensed under the _US Government
Public Domain_.
*/
}

View File

@ -16,8 +16,10 @@ User Manual.
geometric primitives, the notion of <em>traits classes</em> which
define what primitives are used by a geometric algorithm, the
notions of \em concept and \em model.
- \subpage tuto_reconstruction
- \subpage tuto_gis
\section tuto_examples Package Examples

Binary file not shown.

After

Width:  |  Height:  |  Size: 78 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 48 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 130 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 39 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 108 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 23 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 124 KiB

View File

@ -152040,4 +152040,14 @@ pages = {179--189}
Year = {2012},
Pages = {440-449},
Url = {http://arxiv.org/abs/1110.4573}
}
}
@article{cvl-ew-12,
Author = {Cabello, Sergio and de Verdière, {\'E}ric Colin and Lazarus, Francis},
Title = {Algorithms for the edge-width of an embedded graph},
Journal = {Computational Geometry},
Volume = {45},
Pages = {215--224},
Year = {2012},
Url = {http://monge.univ-mlv.fr/~colinde/pub/09edgewidth.pdf}
}

View File

@ -502,17 +502,13 @@ LOOKUP_CACHE_SIZE = 0
EXTRACT_ALL = YES
#---------------------------------------------------------------------------
# Build related configuration options
#---------------------------------------------------------------------------
# When the EXTRACT_ALL tag is set to YES and a member or class as no
# documentation, no detailed section will be produced if the
# EXTRACT_ALL_NO_DETAILED_IF_EMPTY tag is set to YES. This tag has no effect if
# the EXTRACT_ALL tag is set to NO.
# The default value is: NO.
EXTRACT_ALL_NO_DETAILED_IF_EMPTY = YES
${CGAL_OPT_EXTRACT_ALL_NO_DETAILED_IF_EMPTY}
# If the EXTRACT_PRIVATE tag is set to YES, all private members of a class will
# be included in the documentation.

View File

@ -718,17 +718,17 @@ public :
Lazy(Self_rep *r)
{
PTR = r;
PTR.p = r;
}
Lazy(const ET& e)
{
PTR = new Lazy_rep_0<AT,ET,E2A>(e);
PTR.p = new Lazy_rep_0<AT,ET,E2A>(e);
}
Lazy(ET&& e)
{
PTR = new Lazy_rep_0<AT,ET,E2A>(std::move(e));
PTR.p = new Lazy_rep_0<AT,ET,E2A>(std::move(e));
}
friend void swap(Lazy& a, Lazy& b) noexcept
@ -768,7 +768,7 @@ public :
return z;
}
Self_rep * ptr() const { return (Self_rep*) PTR; }
Self_rep * ptr() const { return (Self_rep*) PTR.p; }
};
// The magic functor for Construct_bbox_[2,3], as there is no Lazy<Bbox>

View File

@ -126,7 +126,7 @@ public:
if (maxz < arz) maxz = arz;
if (maxz < atz) maxz = atz;
double d = std::max(maxx, std::max(maxy, maxz));
double d = (std::max)(maxx, (std::max)(maxy, maxz));
double eps = 3.27418e-11 * d * d * d * d * d * d;
if (det > eps) return ON_BOUNDED_SIDE;

View File

@ -12,6 +12,7 @@
#ifndef CGAL_GENERALIZED_MAP_H
#define CGAL_GENERALIZED_MAP_H 1
#include <CGAL/Generalized_map_fwd.h>
#include <CGAL/internal/Combinatorial_map_utility.h>
#include <CGAL/internal/Generalized_map_group_functors.h>
#include <CGAL/internal/Combinatorial_map_copy_functors.h>
@ -51,6 +52,7 @@ namespace CGAL {
* Definition of generic dD Generalized map.
*/
struct Combinatorial_map_tag;
struct Generalized_map_tag {};
/** Generic definition of generalized map in dD.
@ -58,10 +60,7 @@ namespace CGAL {
* mainly to create darts, to use marks onto these darts, to get and set
* the alpha links, and to manage enabled attributes.
*/
template < unsigned int d_, class Refs,
class Items_=Generic_map_min_items,
class Alloc_=CGAL_ALLOCATOR(int),
class Storage_= Generalized_map_storage_1<d_, Items_, Alloc_> >
template<unsigned int d_, class Refs_, class Items_, class Alloc_, class Storage_>
class Generalized_map_base: public Storage_
{
template<typename Gmap,unsigned int i,typename Enabled>
@ -84,9 +83,10 @@ namespace CGAL {
typedef Generalized_map_tag Combinatorial_data_structure;
/// Types definition
typedef Storage_ Storage;
typedef Storage Base;
typedef Generalized_map_base<d_, Refs, Items_, Alloc_, Storage_ > Self;
typedef Storage_ Storage;
typedef Storage Base;
typedef Generalized_map_base<d_, Refs_, Items_, Alloc_, Storage_ > Self;
typedef Refs_ Refs;
typedef typename Base::Dart Dart;
typedef typename Base::Dart_handle Dart_handle;
@ -106,7 +106,7 @@ namespace CGAL {
typedef typename Base::Null_handle_type Null_handle_type;
using Base::null_handle;
using Base::null_dart_handle;
using Base::mdarts;
using Base::get_alpha;
using Base::is_free;
@ -177,29 +177,35 @@ namespace CGAL {
}
/** Copy the given generalized map into *this.
* Note that both Gmap can have different dimensions and/or non void attributes.
* Note that both GMap can have different dimensions and/or non void attributes.
* Here GMap2 is necessarily non const; while Dart_handle_2 can be a const or non const handle.
* This is the "generic" method, called by the different variants below.
* Marks reserved and automatic attributes management are not updated.
* @param amap the generalized map to copy.
* @param origin_to_copy associative array from original darts to copy darts
* @param origin_to_copy associative array from copy darts to original darts
* @param converters tuple of functors, one per attribute, to transform original attributes into copies
* @param dartinfoconverter functor to transform original information of darts into information of copies
* @param pointconverter functor to transform points in original map into points of copies.
* @param copy_perforated_darts true to copy also darts marked perforated (if any)
* @param mark_perforated_darts true to mark darts wich are copies of perforated darts (if any)
* @post *this is valid.
*/
template <unsigned int d2, typename Refs2, typename Items2, typename Alloc2,
typename Storage2,
template <typename GMap2, typename Dart_handle_2,
typename Converters, typename DartInfoConverter,
typename PointConverter>
void copy(const Generalized_map_base<d2, Refs2, Items2, Alloc2, Storage2>& amap,
const Converters& converters,
const DartInfoConverter& dartinfoconverter,
const PointConverter& pointconverter,
boost::unordered_map
<typename Generalized_map_base<d2, Refs2, Items2, Alloc2, Storage2>::
Dart_const_handle, Dart_handle>* origin_to_copy=NULL,
boost::unordered_map
<Dart_handle, typename Generalized_map_base<d2, Refs2, Items2,
Alloc2, Storage2>::Dart_const_handle>* copy_to_origin=NULL)
void generic_copy(GMap2& amap,
boost::unordered_map<Dart_handle_2, Dart_handle>* origin_to_copy,
boost::unordered_map<Dart_handle, Dart_handle_2>* copy_to_origin,
const Converters& converters,
const DartInfoConverter& dartinfoconverter,
const PointConverter& pointconverter,
bool copy_perforated_darts=false,
size_type mark_perforated=INVALID_MARK)
{
typedef Generalized_map_base<d2, Refs2, Items2, Alloc2, Storage2> GMap2;
this->clear();
this->mnb_used_marks = amap.mnb_used_marks;
/*this->mnb_used_marks = amap.mnb_used_marks;
this->mmask_marks = amap.mmask_marks;
this->automatic_attributes_management =
amap.automatic_attributes_management;
@ -211,36 +217,41 @@ namespace CGAL {
this->mindex_marks[i] = amap.mindex_marks[i];
this->mnb_marked_darts[i] = amap.mnb_marked_darts[i];
this->mnb_times_reserved_marks[i] = amap.mnb_times_reserved_marks[i];
}
} */
// Create an mapping between darts of the two maps (originals->copies).
// (here we cannot use CGAL::Unique_hash_map because it does not provide
// iterators...
boost::unordered_map<typename GMap2::Dart_const_handle, Dart_handle>
local_dartmap;
if (origin_to_copy==NULL) // Used local_dartmap if user does not provides its own unordered_map
boost::unordered_map<Dart_handle_2, Dart_handle> local_dartmap;
if (origin_to_copy==NULL) // Use local_dartmap if user does not provides its own unordered_map
{ origin_to_copy=&local_dartmap; }
Dart_handle new_dart;
for (typename GMap2::Dart_const_range::const_iterator
it=amap.darts().begin(), itend=amap.darts().end();
it!=itend; ++it)
for (typename GMap2::Dart_range::iterator it=amap.darts().begin(),
itend=amap.darts().end(); it!=itend; ++it)
{
new_dart=mdarts.emplace();
init_dart(new_dart, amap.get_marks(it));
if (copy_perforated_darts || !amap.is_perforated(it))
{
new_dart=mdarts.emplace();
init_dart(new_dart); //, amap.get_marks(it));
(*origin_to_copy)[it]=new_dart;
if (copy_to_origin!=NULL) { (*copy_to_origin)[new_dart]=it; }
if (mark_perforated!=INVALID_MARK && amap.is_perforated(it))
{ mark(new_dart, mark_perforated); }
internal::Copy_dart_info_functor<Refs2, Refs, DartInfoConverter>::
run(static_cast<const Refs2&>(amap), static_cast<Refs&>(*this),
it, new_dart, dartinfoconverter);
(*origin_to_copy)[it]=new_dart;
if (copy_to_origin!=NULL) { (*copy_to_origin)[new_dart]=it; }
internal::Copy_dart_info_functor
<typename GMap2::Refs, Refs, DartInfoConverter>::run
(static_cast<const typename GMap2::Refs&>(amap), static_cast<Refs&>(*this),
it, new_dart, dartinfoconverter);
}
}
unsigned int min_dim=(dimension<amap.dimension?dimension:amap.dimension);
typename boost::unordered_map<typename GMap2::Dart_const_handle,Dart_handle>
::iterator dartmap_iter, dartmap_iter_end=origin_to_copy->end();
typename boost::unordered_map<Dart_handle_2, Dart_handle>::iterator
dartmap_iter, dartmap_iter_end=origin_to_copy->end();
for (dartmap_iter=origin_to_copy->begin(); dartmap_iter!=dartmap_iter_end;
++dartmap_iter)
{
@ -260,9 +271,9 @@ namespace CGAL {
++dartmap_iter)
{
Helper::template Foreach_enabled_attributes
< internal::Copy_attributes_functor<Refs2, Refs, Converters,
PointConverter> >::
run(static_cast<const Refs2&>(amap), static_cast<Refs&>(*this),
< internal::Copy_attributes_functor<typename GMap2::Refs, Refs,
Converters, PointConverter> >::
run(static_cast<const typename GMap2::Refs&>(amap), static_cast<Refs&>(*this),
dartmap_iter->first, dartmap_iter->second,
converters, pointconverter);
}
@ -270,74 +281,165 @@ namespace CGAL {
CGAL_assertion(is_valid());
}
template <unsigned int d2, typename Refs2, typename Items2, typename Alloc2,
typename Storage2>
void copy(const Generalized_map_base<d2, Refs2, Items2, Alloc2, Storage2>& amap,
// (1a) copy(amap, converters, dartinfoconverter, pointconverter)
template<typename GMap2, typename Converters, typename DartInfoConverter,
typename PointConverter>
void copy(GMap2& amap,
boost::unordered_map
<typename Generalized_map_base<d2, Refs2, Items2, Alloc2, Storage2>::
Dart_const_handle, Dart_handle>* origin_to_copy=NULL,
<typename GMap2::Dart_handle, Dart_handle>* origin_to_copy,
boost::unordered_map
<Dart_handle, typename Generalized_map_base<d2, Refs2, Items2,
Alloc2, Storage2>::Dart_const_handle>* copy_to_origin=NULL)
{
CGAL::cpp11::tuple<> converters;
Default_converter_dart_info<Refs2, Refs> dartinfoconverter;
Default_converter_cmap_0attributes_with_point<Refs2, Refs> pointconverter;
copy(amap, converters, dartinfoconverter, pointconverter,
origin_to_copy, copy_to_origin);
}
template <unsigned int d2, typename Refs2, typename Items2, typename Alloc2,
typename Storage2, typename Converters>
void copy(const Generalized_map_base<d2, Refs2, Items2, Alloc2, Storage2>& amap,
const Converters& converters,
boost::unordered_map
<typename Generalized_map_base<d2, Refs2, Items2, Alloc2, Storage2>::
Dart_const_handle, Dart_handle>* origin_to_copy=NULL,
boost::unordered_map
<Dart_handle, typename Generalized_map_base<d2, Refs2, Items2,
Alloc2, Storage2>::Dart_const_handle>* copy_to_origin=NULL)
{
Default_converter_cmap_0attributes_with_point<Refs2, Refs> pointconverter;
Default_converter_dart_info<Refs2, Refs> dartinfoconverter;
copy(amap, converters, dartinfoconverter, pointconverter,
origin_to_copy, copy_to_origin);
}
template <unsigned int d2, typename Refs2, typename Items2, typename Alloc2,
typename Storage2,
typename Converters, typename DartInfoConverter>
void copy(const Generalized_map_base<d2, Refs2, Items2, Alloc2, Storage2>& amap,
<Dart_handle, typename GMap2::Dart_handle>* copy_to_origin,
const Converters& converters,
const DartInfoConverter& dartinfoconverter,
boost::unordered_map
<typename Generalized_map_base<d2, Refs2, Items2, Alloc2, Storage2>::
Dart_const_handle, Dart_handle>* origin_to_copy=NULL,
boost::unordered_map
<Dart_handle, typename Generalized_map_base<d2, Refs2, Items2,
Alloc2, Storage2>::Dart_const_handle>* copy_to_origin=NULL)
const PointConverter& pointconverter,
bool copy_perforated_darts=false,
size_type mark_perforated=INVALID_MARK)
{
Default_converter_cmap_0attributes_with_point<Refs2, Refs> pointconverter;
copy(amap, converters, dartinfoconverter, pointconverter,
origin_to_copy, copy_to_origin);
generic_copy<GMap2, typename GMap2::Dart_handle, Converters,
DartInfoConverter, PointConverter>
(amap, origin_to_copy, copy_to_origin,
converters, dartinfoconverter, pointconverter,
copy_perforated_darts, mark_perforated);
}
// (1b) copy_from_const(const amap, converters, dartinfoconverter, pointconverter)
template<typename GMap2, typename Converters, typename DartInfoConverter,
typename PointConverter>
void copy_from_const(const GMap2& amap,
boost::unordered_map
<typename GMap2::Dart_const_handle, Dart_handle>* origin_to_copy,
boost::unordered_map
<Dart_handle, typename GMap2::Dart_const_handle>* copy_to_origin,
const Converters& converters,
const DartInfoConverter& dartinfoconverter,
const PointConverter& pointconverter,
bool copy_perforated_darts=false,
size_type mark_perforated=INVALID_MARK)
{
generic_copy<GMap2, typename GMap2::Dart_const_handle,
Converters, DartInfoConverter, PointConverter>
(const_cast<GMap2&>(amap), origin_to_copy, copy_to_origin,
converters, dartinfoconverter, pointconverter,
copy_perforated_darts, mark_perforated);
}
// (2a) copy(amap, converters, dartinfoconverter)
template<typename GMap2, typename Converters, typename DartInfoConverter>
void copy(GMap2& amap,
boost::unordered_map
<typename GMap2::Dart_handle, Dart_handle>* origin_to_copy,
boost::unordered_map
<Dart_handle, typename GMap2::Dart_handle>* copy_to_origin,
const Converters& converters,
const DartInfoConverter& dartinfoconverter,
bool copy_perforated_darts=false,
size_type mark_perforated=INVALID_MARK)
{
Default_converter_cmap_0attributes_with_point<typename GMap2::Refs, Refs>
pointconverter;
copy(amap, origin_to_copy, copy_to_origin, converters,
dartinfoconverter, pointconverter,
copy_perforated_darts, mark_perforated);
}
// (2b) copy_from_const(const amap, converters, dartinfoconverter)
template <typename GMap2, typename Converters, typename DartInfoConverter>
void copy_from_const(const GMap2& amap,
boost::unordered_map
<typename GMap2::Dart_const_handle, Dart_handle>* origin_to_copy,
boost::unordered_map
<Dart_handle, typename GMap2::Dart_const_handle>* copy_to_origin,
const Converters& converters,
const DartInfoConverter& dartinfoconverter,
bool copy_perforated_darts=false,
size_type mark_perforated=INVALID_MARK)
{
Default_converter_cmap_0attributes_with_point<typename GMap2::Refs, Refs>
pointconverter;
copy_from_const(amap, origin_to_copy, copy_to_origin, converters,
dartinfoconverter, pointconverter,
copy_perforated_darts, mark_perforated);
}
// (3a) copy(amap, converters)
template<typename GMap2, typename Converters>
void copy(GMap2& amap,
boost::unordered_map
<typename GMap2::Dart_handle, Dart_handle>* origin_to_copy,
boost::unordered_map
<Dart_handle, typename GMap2::Dart_handle>* copy_to_origin,
const Converters& converters,
bool copy_perforated_darts=false,
size_type mark_perforated=INVALID_MARK)
{
Default_converter_dart_info<typename GMap2::Refs, Refs> dartinfoconverter;
copy(amap, origin_to_copy, copy_to_origin, converters, dartinfoconverter,
copy_perforated_darts, mark_perforated);
}
// (3b) copy_from_const(const amap, converters)
template <typename GMap2, typename Converters>
void copy_from_const(const GMap2& amap,
boost::unordered_map
<typename GMap2::Dart_const_handle, Dart_handle>* origin_to_copy,
boost::unordered_map
<Dart_handle, typename GMap2::Dart_const_handle>* copy_to_origin,
const Converters& converters,
bool copy_perforated_darts=false,
size_type mark_perforated=INVALID_MARK)
{
Default_converter_dart_info<typename GMap2::Refs, Refs> dartinfoconverter;
copy_from_const(amap, origin_to_copy, copy_to_origin, converters, dartinfoconverter,
copy_perforated_darts, mark_perforated);
}
// (4a) copy(amap)
template<typename GMap2>
void copy(GMap2& amap,
boost::unordered_map
<typename GMap2::Dart_handle, Dart_handle>* origin_to_copy=nullptr,
boost::unordered_map
<Dart_handle, typename GMap2::Dart_handle>* copy_to_origin=nullptr,
bool copy_perforated_darts=false,
size_type mark_perforated=INVALID_MARK)
{
CGAL::cpp11::tuple<> converters;
copy(amap, origin_to_copy, copy_to_origin, converters,
copy_perforated_darts, mark_perforated);
}
// (4b) copy_from_const(const amap)
template <typename GMap2>
void copy_from_const(const GMap2& amap,
boost::unordered_map
<typename GMap2::Dart_const_handle, Dart_handle>* origin_to_copy=nullptr,
boost::unordered_map
<Dart_handle, typename GMap2::Dart_const_handle>* copy_to_origin=nullptr,
bool copy_perforated_darts=false,
size_type mark_perforated=INVALID_MARK)
{
CGAL::cpp11::tuple<> converters;
copy_from_const(amap, origin_to_copy, copy_to_origin, converters,
copy_perforated_darts, mark_perforated);
}
// Copy constructor from a map having exactly the same type.
Generalized_map_base (const Self & amap)
{ copy(amap); }
Generalized_map_base(const Self & amap) : Generalized_map_base()
{ copy_from_const(amap); }
// "Copy constructor" from a map having different type.
template <unsigned int d2, typename Refs2, typename Items2, typename Alloc2,
typename Storage2>
Generalized_map_base(const Generalized_map_base<d2, Refs2, Items2, Alloc2, Storage2>& amap)
{ copy(amap); }
Generalized_map_base(const Generalized_map_base<d2, Refs2, Items2, Alloc2, Storage2>& amap):
Generalized_map_base()
{ copy_from_const(amap); }
// "Copy constructor" from a map having different type.
template <unsigned int d2, typename Refs2, typename Items2, typename Alloc2,
typename Storage2, typename Converters>
Generalized_map_base(const Generalized_map_base<d2, Refs2, Items2, Alloc2, Storage2>& amap,
const Converters& converters)
{ copy(amap, converters); }
const Converters& converters): Generalized_map_base()
{ copy_from_const(amap, nullptr, nullptr, converters); }
// "Copy constructor" from a map having different type.
template <unsigned int d2, typename Refs2, typename Items2, typename Alloc2,
@ -345,8 +447,9 @@ namespace CGAL {
typename Converters, typename DartInfoConverter>
Generalized_map_base(const Generalized_map_base<d2, Refs2, Items2, Alloc2, Storage2>& amap,
const Converters& converters,
const DartInfoConverter& dartinfoconverter)
{ copy(amap, converters, dartinfoconverter); }
const DartInfoConverter& dartinfoconverter):
Generalized_map_base()
{ copy_from_const(amap, nullptr, nullptr, converters, dartinfoconverter); }
// "Copy constructor" from a map having different type.
template <unsigned int d2, typename Refs2, typename Items2, typename Alloc2,
@ -356,14 +459,15 @@ namespace CGAL {
Generalized_map_base(const Generalized_map_base<d2, Refs2, Items2, Alloc2, Storage2>& amap,
const Converters& converters,
const DartInfoConverter& dartinfoconverter,
const PointConverter& pointconverter)
{ copy(amap, converters, dartinfoconverter, pointconverter); }
const PointConverter& pointconverter):
Generalized_map_base()
{ copy_from_const(amap, nullptr, nullptr, converters, dartinfoconverter, pointconverter); }
/** Affectation operation. Copies one map to the other.
* @param amap a generalized map.
* @return A copy of that generalized map.
*/
Self & operator= (const Self & amap)
Self & operator=(const Self & amap)
{
if (this!=&amap)
{
@ -496,6 +600,16 @@ namespace CGAL {
{ return mdarts.iterator_to(adart); }
Dart_const_handle dart_handle(const Dart& adart) const
{ return mdarts.iterator_to(adart); }
Dart_handle dart_handle(size_type i)
{
CGAL_assertion(darts().is_used(i));
return mdarts.iterator_to(darts()[i]);
}
Dart_const_handle dart_handle(size_type i) const
{
CGAL_assertion(darts().is_used(i));
return mdarts.iterator_to(darts()[i]);
}
/** Return the highest dimension for which dh is not free.
* @param dh a dart handle
@ -922,6 +1036,31 @@ namespace CGAL {
size_type unmark_cell(Dart_const_handle adart, size_type amark) const
{ return CGAL::unmark_cell<Self, i, d>(*this, adart, amark); }
template <unsigned int i, unsigned int d=dimension>
size_type mark_oriented_cell(Dart_const_handle adart, size_type amark,
size_type amark2=INVALID_MARK) const
{ return CGAL::mark_oriented_cell<Self, i, d>(*this, adart, amark, amark2); }
template <unsigned int i, unsigned int d=dimension>
size_type unmark_oriented_cell(Dart_const_handle adart, size_type amark,
size_type amark2=INVALID_MARK) const
{ return CGAL::unmark_oriented_cell<Self, i, d>(*this, adart, amark, amark2); }
std::size_t orient(size_type amark) const
{
size_type amark2=get_new_mark();
std::size_t res=0;
for (auto it=darts().begin(), itend=darts().end(); it!=itend; ++it)
{
if (!is_marked(it, amark2))
{ res+=mark_oriented_cell<dimension+1>(it, amark, amark2); } // Mark the connected componend
}
CGAL_assertion(is_whole_map_marked(amark2));
free_mark(amark2);
return res;
}
/** Test if this map is without boundary for a given dimension.
* @param i the dimension.
* @return true iff all the darts are not i-free.
@ -1734,7 +1873,7 @@ namespace CGAL {
while (next(dd1)!=d2)
{
if (this->template is_free<2>(next(dd1)))
{ return std::numeric_limits<std::size_t>::max(); }
{ return (std::numeric_limits<std::size_t>::max)(); }
++res;
dd1=opposite2(next(dd1));
@ -1755,7 +1894,7 @@ namespace CGAL {
if (d2==opposite2(d1)) { return 0; }
if (this->template is_free<2>(d1) || this->template is_free<2>(d2))
{ return std::numeric_limits<std::size_t>::max(); }
{ return (std::numeric_limits<std::size_t>::max)(); }
d1=opposite2(d1);
d2=opposite2(d2);
@ -1764,7 +1903,7 @@ namespace CGAL {
while (previous(dd1)!=d2)
{
if (this->template is_free<2>(previous(dd1)))
{ return std::numeric_limits<std::size_t>::max(); }
{ return (std::numeric_limits<std::size_t>::max)(); }
++res;
dd1=opposite2(previous(dd1));
@ -3692,10 +3831,7 @@ namespace CGAL {
typename Helper::Merge_functors m_onmerge_functors;
};
template < unsigned int d_,
class Items_=Generic_map_min_items,
class Alloc_=CGAL_ALLOCATOR(int),
class Storage_= Generalized_map_storage_1<d_, Items_, Alloc_> >
template<unsigned int d_, class Items_, class Alloc_,class Storage_>
class Generalized_map :
public Generalized_map_base<d_,
Generalized_map<d_,Items_,Alloc_, Storage_>,

View File

@ -0,0 +1,38 @@
// Copyright (c) 2016 CNRS and LIRIS' Establishments (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) : Guillaume Damiand <guillaume.damiand@liris.cnrs.fr>
//
#ifndef GENERALIZED_MAP_FWD_H
#define GENERALIZED_MAP_FWD_H 1
#include <CGAL/memory.h>
namespace CGAL {
template<unsigned int d_, class Items_, class Alloc_ >
class Generalized_map_storage_1;
struct Generic_map_min_items;
template < unsigned int d_, class Refs,
class Items_=Generic_map_min_items,
class Alloc_=CGAL_ALLOCATOR(int),
class Storage_= Generalized_map_storage_1<d_, Items_, Alloc_> >
class Generalized_map_base;
template < unsigned int d_,
class Items_=Generic_map_min_items,
class Alloc_=CGAL_ALLOCATOR(int),
class Storage_= Generalized_map_storage_1<d_, Items_, Alloc_> >
class Generalized_map;
} // CGAL
#endif // GENERALIZED_MAP_FWD_H

View File

@ -103,7 +103,7 @@ namespace CGAL {
// Init
void init_storage()
{}
{ null_dart_handle=nullptr; }
/** Return if this dart is free for adimension.
* @param dh a dart handle
@ -402,6 +402,8 @@ namespace CGAL {
}
protected:
Dart_handle null_dart_handle; // To be compatible with combinatorial map
/// Dart container.
Dart_container mdarts;

View File

@ -1218,13 +1218,13 @@ protected:
// 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_M, "Toggles mono color");
setKeyDescription(::Qt::Key_N, "Inverse direction of normals");
setKeyDescription(::Qt::Key_S, "Switch between flat/Gouraud shading display");
setKeyDescription(::Qt::Key_T, "Toggles text display");
setKeyDescription(::Qt::Key_U, "Move camera direction upside down");
setKeyDescription(::Qt::Key_V, "Toggles vertices display");
setKeyDescription(::Qt::Key_W, "Toggles faces 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");
@ -1278,13 +1278,8 @@ 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_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))
else if ((e->key()==::Qt::Key_S) && (modifiers==::Qt::NoButton))
{
m_flatShading=!m_flatShading;
if (m_flatShading)
@ -1306,6 +1301,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_U) && (modifiers==::Qt::NoButton))
{
if (is_two_dimensional())
@ -1330,18 +1331,18 @@ protected:
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;
displayMessage(QString("Draw vertices=%1.").arg(m_draw_vertices?"true":"false"));
update();
}
else if ((e->key()==::Qt::Key_W) && (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_Plus) && (!modifiers.testFlag(::Qt::ControlModifier))) // No ctrl
{
m_size_edges+=.5;

View File

@ -38,20 +38,20 @@ int main(int argc, char* argv[])
Point_3 sp = tm.point(source);
std::cout << "source: " << sp << " " << source << std::endl;
vertex_descriptor far;
vertex_descriptor vfar;
double sdistance = 0;
for(vertex_descriptor vd : vertices(tm)){
std::cout << vd << " is at distance " << get(vertex_distance, vd) << " to " << source << std::endl;
if(get(vertex_distance, vd) > sdistance){
far = vd;
vfar = vd;
sdistance = get(vertex_distance, vd);
}
}
std::cout << "far: " << tm.point(far) << " " << far << std::endl;
std::cout << "vfar: " << tm.point(vfar) << " " << vfar << std::endl;
hm.add_source(far);
hm.add_source(vfar);
hm.estimate_geodesic_distances(vertex_distance);
for(vertex_descriptor vd : vertices(tm)){

View File

@ -887,16 +887,6 @@ public:
base().clear_sources();
}
/**
* get estimated distance from the current source set to a vertex `vd`.
* \warning The return type is `double` even when used with an exact kernel.
*/
double
estimate_geodesic_distance(vertex_descriptor vd) const
{
return base().estimate_geodesic_distance(vd);
}
/**
* returns the source set.
*/
@ -906,7 +896,6 @@ public:
return base().sources();
}
/**
* fills the distance property map with the estimated geodesic distance of each vertex to the closest source vertex.
* \tparam VertexDistanceMap a property map model of `WritablePropertyMap`

View File

@ -335,7 +335,6 @@ private:
//then go back to top of the stack
}
}
std::cout<< a << " edges were flipped: " << std::endl;
}

View File

@ -42,19 +42,19 @@ int main()
//Point_3 sp = sm.point(source);
vertex_descriptor far;
vertex_descriptor vfar;
// double sdistance = 0;
for(vertex_descriptor vd : vertices(sm)){
std::cout << vd << " is at distance " << get(heat_intensity, vd) << " from " << source << std::endl;
/*
if(squared_distance(sp,sm.point(vd)) > sdistance){
far = vd;
vfar = vd;
sdistance = squared_distance(sp,sm.point(vd));
}
*/
}
hm.add_source(far);
hm.add_source(vfar);
hm.estimate_geodesic_distances(heat_intensity);
for(vertex_descriptor vd : vertices(sm)){

View File

@ -36,19 +36,19 @@ int main(int argc, char* argv[])
Point_3 sp = sm.point(source);
std::cout << "source: " << sp << " " << source << std::endl;
vertex_descriptor far;
vertex_descriptor vfar;
double sdistance = 0;
for(vertex_descriptor vd : vertices(sm)){
if(get(vertex_distance,vd) > sdistance){
far = vd;
vfar = vd;
sdistance = get(vertex_distance,vd);
}
}
assert(sdistance > 2.9);
assert(sdistance < CGAL_PI);
hm.add_source(far);
hm.add_source(vfar);
assert(hm.sources().size() == 2);
hm.estimate_geodesic_distances(vertex_distance);
@ -62,7 +62,7 @@ int main(int argc, char* argv[])
assert(sdistance > 1.4);
assert(sdistance < CGAL_PI/2.0);
hm.remove_source(far);
hm.remove_source(vfar);
assert(hm.sources().size() == 1);
hm.clear_sources();
@ -70,7 +70,7 @@ int main(int argc, char* argv[])
// add range of sources
std::vector<vertex_descriptor> vrange;
vrange.push_back(source);
vrange.push_back(far);
vrange.push_back(vfar);
hm.add_sources(vrange);
assert(hm.sources().size() == 2);
hm.estimate_geodesic_distances(vertex_distance);

View File

@ -36,19 +36,19 @@ int main(int argc, char* argv[])
Point_3 sp = sm.point(source);
std::cout << "source: " << sp << " " << source << std::endl;
vertex_descriptor far;
vertex_descriptor vfar;
double sdistance = 0;
for(vertex_descriptor vd : vertices(sm)){
if(get(vertex_distance,vd) > sdistance){
far = vd;
vfar = vd;
sdistance = get(vertex_distance,vd);
}
}
assert(sdistance > 2.9);
assert(sdistance < CGAL_PI);
hm.add_source(far);
hm.add_source(vfar);
assert(hm.sources().size() == 2);
hm.estimate_geodesic_distances(vertex_distance);
@ -62,7 +62,7 @@ int main(int argc, char* argv[])
assert(sdistance > 1.4);
assert(sdistance < CGAL_PI/2.0);
hm.remove_source(far);
hm.remove_source(vfar);
assert(hm.sources().size() == 1);
hm.clear_sources();
@ -70,7 +70,7 @@ int main(int argc, char* argv[])
// add range of sources
std::vector<vertex_descriptor> vrange;
vrange.push_back(source);
vrange.push_back(far);
vrange.push_back(vfar);
hm.add_sources(vrange);
assert(hm.sources().size() == 2);
hm.estimate_geodesic_distances(vertex_distance);

View File

@ -318,7 +318,7 @@ MainWindow::on_actionInsertRandomPoints_triggered()
tr("Enter number of random points"),
100,
0,
std::numeric_limits<int>::max(),
(std::numeric_limits<int>::max)(),
1,
&ok);

View File

@ -3,6 +3,14 @@ Release History
[Release 5.1] (https://github.com/CGAL/cgal/releases/tag/releases%2FCGAL-5.1)
### 3D Fast Intersection and Distance Computation
- The introduction of the usage of the search tree by default for all distance queries
in the 5.0 release was actually not lazy contrary to what was announced. The behavior of the
search tree is now the following: it will be used except if an explicit call to `do_not_accelerate_distance_queries()`
is made. The construction of the search tree (once insertion of primitives is done) will be triggered by the first
distance query or by an explicit call to `accelerate_distance_queries()`.
- **Breaking change**: `accelerate_distance_queries()` and `do_not_accelerate_distance_queries()` are not longer `const` functions.
### Optimal Bounding Box (new package)
- This package implements an optimization algorithm that aims to construct a close approximation
of the *optimal bounding box* of a mesh or a point set, which is defined as the smallest
@ -23,6 +31,12 @@ Release History
- The long-deprecated function `CGAL::convex_hull_3_to_polyhedron_3()` has been removed.
The function `CGAL::convex_hull_3_to_face_graph()` should be used instead.
### dD Spatial Searching
- The kd-tree can now be built in parallel: `CGAL::Kd_tree::build()`
is given an optional template parameter `ConcurrencyTag` (default
value remains `CGAL::Sequential_tag` for backward compatibility).
Release 5.0
-----------
@ -31,10 +45,10 @@ Release date: June 2020
### Surface Mesh Topology (new package)
- This package allows to compute some topological invariants of
surfaces. For now, it is possible to test if two (closed) curves
on a combinatorial surface are homotopic. The user can choose
between free homotopy and homotopy with fixed endpoints.
A contractibility test is also provided.
surfaces:
- test if two (closed) curves on a combinatorial surface are homotopic. The user can choose between free homotopy and homotopy with fixed endpoints.
- test is a curve is contractible.
- compute shortest non-contractible cycles on a surface, with or without weights on edges.
### 3D Fast Intersection and Distance Computation
- **Breaking change**: the internal search tree is now lazily constructed. To disable it, one must call

View File

@ -1171,7 +1171,7 @@ You must disable CGAL_ENABLE_CHECK_HEADERS.")
# Build the doc
set(DOC_DIR "${CMAKE_BINARY_DIR}/build_doc")
file(MAKE_DIRECTORY "${DOC_DIR}")
execute_process(COMMAND "${CMAKE_COMMAND}" -DDOXYGEN_EXECUTABLE=${DOXYGEN_EXECUTABLE} "${CMAKE_SOURCE_DIR}/Documentation/doc"
execute_process(COMMAND "${CMAKE_COMMAND}" -DCGAL_BUILD_THREE_DOC=TRUE -DDOXYGEN_EXECUTABLE=${DOXYGEN_EXECUTABLE} "${CMAKE_SOURCE_DIR}/Documentation/doc"
WORKING_DIRECTORY "${DOC_DIR}"
)
execute_process(COMMAND "${CMAKE_COMMAND}" --build . --target "doc"

View File

@ -23,7 +23,7 @@
int main()
{
double d = std::numeric_limits<double>::denorm_min();
double e = std::numeric_limits<double>::min();
double e = (std::numeric_limits<double>::min)();
// Note : denorm_min == min is actually not necessarily a bug.
// So a better test should be found.
if (d == 0 || d == e)

View File

@ -30,6 +30,7 @@ set(list_of_whitelisted_headers_txt [=[
CGAL/Three/Triangle_container.h
CGAL/Three/Viewer_config.h
CGAL/Three/Viewer_interface.h
CGAL/Three/Three.h
]=])

Some files were not shown because too many files have changed in this diff Show More