Merge remote-tracking branch 'cgal/master' into CGAL-Improve_NP_doc_presentation-GF
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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" )
|
||||
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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();
|
||||
|
|
|
|||
|
|
@ -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();
|
||||
|
||||
|
|
|
|||
|
|
@ -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();
|
||||
|
||||
|
|
|
|||
|
|
@ -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>
|
||||
|
|
|
|||
|
|
@ -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 ;
|
||||
};
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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é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èbvre for
|
||||
Fabri, Jane Tournois, Mariette Yvinec and Sylvain Lefèbvre for
|
||||
helpful comments and discussions.
|
||||
|
||||
*/
|
||||
|
|
|
|||
|
|
@ -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)`.
|
||||
*/
|
||||
|
|
|
|||
|
|
@ -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)`.
|
||||
*/
|
||||
|
|
|
|||
|
|
@ -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>
|
||||
|
|
|
|||
|
|
@ -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){}
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -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>
|
||||
|
|
|
|||
|
|
@ -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){}
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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:
|
||||
|
|
|
|||
|
|
@ -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 ) );
|
||||
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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());
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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. */
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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.
|
||||
|
|
|
|||
|
|
@ -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; }
|
||||
|
||||
|
|
|
|||
|
|
@ -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.
|
||||
|
|
|
|||
|
|
@ -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.
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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));
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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());
|
||||
|
|
|
|||
|
|
@ -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.;
|
||||
|
|
|
|||
|
|
@ -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">
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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 {
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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));
|
||||
|
|
|
|||
|
|
@ -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));
|
||||
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -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() );
|
||||
|
|
|
|||
|
|
@ -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()){
|
||||
|
|
|
|||
|
|
@ -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
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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){
|
||||
|
|
|
|||
|
|
@ -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();
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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()
|
||||
|
||||
|
|
|
|||
|
|
@ -0,0 +1 @@
|
|||
data/b9_training.ply
|
||||
|
|
@ -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;
|
||||
}
|
||||
|
|
@ -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
|
||||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
||||
/// @}
|
||||
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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_>,
|
||||
|
|
|
|||
|
|
@ -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.
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
@ -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 //
|
||||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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()
|
||||
|
|
|
|||
|
|
@ -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 \
|
||||
|
|
|
|||
|
|
@ -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_.
|
||||
|
||||
*/
|
||||
}
|
||||
|
|
@ -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
|
||||
|
||||
|
|
|
|||
|
After Width: | Height: | Size: 78 KiB |
|
After Width: | Height: | Size: 48 KiB |
|
After Width: | Height: | Size: 130 KiB |
|
After Width: | Height: | Size: 39 KiB |
|
After Width: | Height: | Size: 108 KiB |
|
After Width: | Height: | Size: 23 KiB |
|
After Width: | Height: | Size: 124 KiB |
|
|
@ -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}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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.
|
||||
|
|
|
|||
|
|
@ -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>
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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_>,
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
@ -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;
|
||||
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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)){
|
||||
|
|
|
|||
|
|
@ -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`
|
||||
|
|
|
|||
|
|
@ -335,7 +335,6 @@ private:
|
|||
//then go back to top of the stack
|
||||
}
|
||||
}
|
||||
std::cout<< a << " edges were flipped: " << std::endl;
|
||||
}
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -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)){
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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"
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
||||
]=])
|
||||
|
||||
|
|
|
|||