mirror of https://github.com/CGAL/cgal
Merge remote-tracking branch 'cgal/master' into T2-Document_projection_traits_3-maxGimeno
This commit is contained in:
commit
4454c5b3ed
|
|
@ -24,7 +24,7 @@
|
|||
|
||||
#define CGAL_DEPRECATED_HEADER "<CGAL/AABB_polyhedron_segment_primitive.h>"
|
||||
#define CGAL_REPLACEMENT_HEADER "<CGAL/AABB_halfedge_graph_segment_primitive.h>"
|
||||
#include <CGAL/internal/deprecation_warning.h>
|
||||
#include <CGAL/Installation/internal/deprecation_warning.h>
|
||||
|
||||
#include <boost/utility/enable_if.hpp>
|
||||
#include <boost/type_traits/is_same.hpp>
|
||||
|
|
|
|||
|
|
@ -20,7 +20,7 @@
|
|||
|
||||
#define CGAL_DEPRECATED_HEADER "<CGAL/AABB_polyhedron_triangle_primitive.h>"
|
||||
#define CGAL_REPLACEMENT_HEADER "<CGAL/AABB_face_graph_triangle_primitive.h>"
|
||||
#include <CGAL/internal/deprecation_warning.h>
|
||||
#include <CGAL/Installation/internal/deprecation_warning.h>
|
||||
|
||||
#include <boost/utility/enable_if.hpp>
|
||||
#include <boost/type_traits/is_same.hpp>
|
||||
|
|
|
|||
|
|
@ -18,7 +18,7 @@
|
|||
|
||||
#include <CGAL/disable_warnings.h>
|
||||
|
||||
#include <CGAL/internal/AABB_tree/Has_nested_type_Shared_data.h>
|
||||
#include <CGAL/AABB_tree/internal/Has_nested_type_Shared_data.h>
|
||||
#include <CGAL/property_map.h>
|
||||
#include <CGAL/tags.h>
|
||||
|
||||
|
|
|
|||
|
|
@ -21,10 +21,10 @@
|
|||
#include <CGAL/Bbox_3.h>
|
||||
#include <CGAL/Default.h>
|
||||
#include <CGAL/intersections.h>
|
||||
#include <CGAL/internal/AABB_tree/Has_nested_type_Shared_data.h>
|
||||
#include <CGAL/internal/AABB_tree/Is_ray_intersection_geomtraits.h>
|
||||
#include <CGAL/internal/AABB_tree/Primitive_helper.h>
|
||||
#include <CGAL/internal/Has_boolean_tags.h>
|
||||
#include <CGAL/AABB_tree/internal/Has_nested_type_Shared_data.h>
|
||||
#include <CGAL/AABB_tree/internal/Is_ray_intersection_geomtraits.h>
|
||||
#include <CGAL/AABB_tree/internal/Primitive_helper.h>
|
||||
#include <CGAL/Kernel_23/internal/Has_boolean_tags.h>
|
||||
|
||||
|
||||
#include <boost/optional.hpp>
|
||||
|
|
|
|||
|
|
@ -21,11 +21,11 @@
|
|||
|
||||
#include <vector>
|
||||
#include <iterator>
|
||||
#include <CGAL/internal/AABB_tree/AABB_traversal_traits.h>
|
||||
#include <CGAL/internal/AABB_tree/AABB_node.h>
|
||||
#include <CGAL/internal/AABB_tree/AABB_search_tree.h>
|
||||
#include <CGAL/internal/AABB_tree/Has_nested_type_Shared_data.h>
|
||||
#include <CGAL/internal/AABB_tree/Primitive_helper.h>
|
||||
#include <CGAL/AABB_tree/internal/AABB_traversal_traits.h>
|
||||
#include <CGAL/AABB_tree/internal/AABB_node.h>
|
||||
#include <CGAL/AABB_tree/internal/AABB_search_tree.h>
|
||||
#include <CGAL/AABB_tree/internal/Has_nested_type_Shared_data.h>
|
||||
#include <CGAL/AABB_tree/internal/Primitive_helper.h>
|
||||
#include <boost/optional.hpp>
|
||||
#include <boost/lambda/lambda.hpp>
|
||||
|
||||
|
|
@ -1058,7 +1058,7 @@ public:
|
|||
|
||||
} // end namespace CGAL
|
||||
|
||||
#include <CGAL/internal/AABB_tree/AABB_ray_intersection.h>
|
||||
#include <CGAL/AABB_tree/internal/AABB_ray_intersection.h>
|
||||
|
||||
#include <CGAL/enable_warnings.h>
|
||||
|
||||
|
|
|
|||
|
|
@ -16,7 +16,7 @@
|
|||
#include <CGAL/license/AABB_tree.h>
|
||||
|
||||
|
||||
#include <CGAL/internal/AABB_tree/AABB_node.h>
|
||||
#include <CGAL/AABB_tree/internal/AABB_node.h>
|
||||
#include <boost/optional.hpp>
|
||||
|
||||
namespace CGAL {
|
||||
|
|
@ -15,7 +15,7 @@
|
|||
#include <CGAL/license/AABB_tree.h>
|
||||
|
||||
|
||||
#include <CGAL/internal/AABB_tree/Has_nested_type_Shared_data.h>
|
||||
#include <CGAL/AABB_tree/internal/Has_nested_type_Shared_data.h>
|
||||
#include <boost/mpl/has_xxx.hpp>
|
||||
|
||||
namespace CGAL{
|
||||
|
|
@ -25,7 +25,7 @@
|
|||
|
||||
#include <CGAL/disable_warnings.h>
|
||||
|
||||
#include <CGAL/internal/AABB_tree/Primitive_helper.h>
|
||||
#include <CGAL/AABB_tree/internal/Primitive_helper.h>
|
||||
#include <CGAL/use.h>
|
||||
|
||||
#include <boost/mem_fn.hpp>
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
#include <CGAL/assertions.h>
|
||||
#include <CGAL/internal/AABB_tree/Is_ray_intersection_geomtraits.h>
|
||||
#include <CGAL/AABB_tree/internal/Is_ray_intersection_geomtraits.h>
|
||||
#include <CGAL/Simple_cartesian.h>
|
||||
#include <CGAL/Exact_predicates_exact_constructions_kernel.h>
|
||||
|
||||
|
|
|
|||
|
|
@ -36,11 +36,11 @@
|
|||
#include <CGAL/Advancing_front_surface_reconstruction_cell_base_3.h>
|
||||
#include <CGAL/Timer.h>
|
||||
#include <CGAL/Triangulation_data_structure_2.h>
|
||||
#include <CGAL/internal/AFSR/Surface_vertex_base_2.h>
|
||||
#include <CGAL/internal/AFSR/Surface_face_base_2.h>
|
||||
#include <CGAL/internal/AFSR/construct_surface_2.h>
|
||||
#include <CGAL/internal/AFSR/construct_polyhedron.h>
|
||||
#include <CGAL/internal/AFSR/write_triple_indices.h>
|
||||
#include <CGAL/Advancing_front_surface_reconstruction/internal/Surface_vertex_base_2.h>
|
||||
#include <CGAL/Advancing_front_surface_reconstruction/internal/Surface_face_base_2.h>
|
||||
#include <CGAL/Advancing_front_surface_reconstruction/internal/construct_surface_2.h>
|
||||
#include <CGAL/Advancing_front_surface_reconstruction/internal/construct_polyhedron.h>
|
||||
#include <CGAL/Advancing_front_surface_reconstruction/internal/write_triple_indices.h>
|
||||
|
||||
namespace CGAL {
|
||||
|
||||
|
|
|
|||
|
|
@ -1,135 +0,0 @@
|
|||
// Copyright (c) 2015 INRIA Sophia-Antipolis (France).
|
||||
// All rights reserved.
|
||||
//
|
||||
// This file is part of CGAL (www.cgal.org).
|
||||
//
|
||||
// $URL$
|
||||
// $Id$
|
||||
// SPDX-License-Identifier: GPL-3.0-or-later OR LicenseRef-Commercial
|
||||
//
|
||||
// Author(s) : Frank Da, David Cohen-Steiner, Andreas Fabri
|
||||
|
||||
#ifndef CGAL_AFSR_ORIENT_H
|
||||
#define CGAL_AFSR_ORIENT_H
|
||||
|
||||
#include <CGAL/license/Advancing_front_surface_reconstruction.h>
|
||||
|
||||
|
||||
namespace CGAL {
|
||||
namespace AFSR {
|
||||
|
||||
|
||||
template <class Triangulation, class TDS, class Filter>
|
||||
typename TDS::Vertex_handle
|
||||
orient(TDS& tds, const Advancing_front_surface_reconstruction<Triangulation,Filter>& surface)
|
||||
{
|
||||
|
||||
typedef typename TDS::Vertex_handle Vertex_handle;
|
||||
typedef std::pair<Vertex_handle,Vertex_handle> Vh_pair;
|
||||
typedef typename TDS::Face_handle Face_handle;
|
||||
typedef typename TDS::Edge Edge;
|
||||
|
||||
Triangulation& T = surface.triangulation_3();
|
||||
// create an infinite-vertex and infinite faces with the
|
||||
// boundary edges if any.
|
||||
// return the infinite vertex if created
|
||||
Vertex_handle vinf;
|
||||
|
||||
std::vector<Vertex_handle > vvh;
|
||||
if(tds.number_of_vertices() != 0) tds.clear();
|
||||
int dim = 2;
|
||||
tds.set_dimension(dim);
|
||||
|
||||
CGAL::Unique_hash_map<typename Triangulation::Vertex_handle, int> vertex_index_map(-1, T.number_of_vertices());
|
||||
|
||||
int i=0;
|
||||
for (typename Triangulation::Finite_vertices_iterator v_it = T.finite_vertices_begin();
|
||||
v_it != T.finite_vertices_end();
|
||||
v_it++){
|
||||
typename CGAL::Unique_hash_map<typename Triangulation::Vertex_handle, int>::Data& d = vertex_index_map[v_it];
|
||||
if ((!v_it->is_exterior()) && d == -1){
|
||||
d = i;
|
||||
Vertex_handle vh = tds.create_vertex();
|
||||
vvh.push_back(vh);
|
||||
vh->set_point(v_it->point());
|
||||
i++;
|
||||
}
|
||||
}
|
||||
std::map<Vh_pair, Edge> edge_map;
|
||||
|
||||
|
||||
for(typename Triangulation::Finite_facets_iterator f_it = T.finite_facets_begin();
|
||||
f_it != T.finite_facets_end();
|
||||
f_it++)
|
||||
{
|
||||
typename Triangulation::Cell_handle n, c = (*f_it).first;
|
||||
int ni, ci = (*f_it).second;
|
||||
n = c->neighbor(ci);
|
||||
ni = n->index(c);
|
||||
int i1, i2 ,i3;
|
||||
|
||||
if (c->is_selected_facet(ci))
|
||||
{
|
||||
i1 = (ci+1) & 3;
|
||||
i2 = (ci+2) & 3;
|
||||
i3 = (ci+3) & 3;
|
||||
|
||||
Face_handle fh = tds.create_face(vvh[vertex_index_map[c->vertex(i1)]],
|
||||
vvh[vertex_index_map[c->vertex(i2)]],
|
||||
vvh[vertex_index_map[c->vertex(i3)]]);
|
||||
vvh[vertex_index_map[c->vertex(i1)]]->set_face(fh);
|
||||
vvh[vertex_index_map[c->vertex(i2)]]->set_face(fh);
|
||||
vvh[vertex_index_map[c->vertex(i3)]]->set_face(fh);
|
||||
for (int ih = 0; ih < 3; ++ih) {
|
||||
tds.set_adjacency(fh, ih, edge_map);
|
||||
}
|
||||
}
|
||||
|
||||
if (n->is_selected_facet(ni))
|
||||
{
|
||||
i1 = (ni+1) & 3;
|
||||
i2 = (ni+2) & 3;
|
||||
i3 = (ni+3) & 3;
|
||||
Face_handle fh = tds.create_face(vvh[vertex_index_map[n->vertex(i1)]],
|
||||
vvh[vertex_index_map[n->vertex(i2)]],
|
||||
vvh[vertex_index_map[n->vertex(i3)]]);
|
||||
vvh[vertex_index_map[n->vertex(i1)]]->set_face(fh);
|
||||
vvh[vertex_index_map[n->vertex(i2)]]->set_face(fh);
|
||||
vvh[vertex_index_map[n->vertex(i3)]]->set_face(fh);
|
||||
for (int ih = 0; ih < 3; ++ih) {
|
||||
tds.set_adjacency(fh, ih, edge_map);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if ( !edge_map.empty()) {
|
||||
vinf = tds.create_vertex();
|
||||
std::map<Vh_pair, Edge> inf_edge_map;
|
||||
while (!edge_map.empty()) {
|
||||
Face_handle fh = edge_map.begin()->second.first;
|
||||
int ih = edge_map.begin()->second.second;
|
||||
Face_handle fn = tds.create_face( vinf,
|
||||
fh->vertex(TDS::cw(ih)),
|
||||
fh->vertex(TDS::ccw(ih)));
|
||||
vinf->set_face(fn);
|
||||
tds.set_adjacency(fn, 0, fh, ih);
|
||||
tds.set_adjacency(fn, 1, inf_edge_map);
|
||||
tds.set_adjacency(fn, 2, inf_edge_map);
|
||||
edge_map.erase(edge_map.begin());
|
||||
}
|
||||
CGAL_assertion(inf_edge_map.empty());
|
||||
}
|
||||
|
||||
|
||||
tds.reorient_faces();
|
||||
return vinf;
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
} // namespace AFSR
|
||||
} // namespace CGAL
|
||||
|
||||
#endif //CGAL_AFSR_ORIENT_H
|
||||
|
|
@ -15,7 +15,7 @@
|
|||
|
||||
#include <CGAL/license/Alpha_shapes_2.h>
|
||||
|
||||
#include <CGAL/internal/Lazy_alpha_nt_2.h>
|
||||
#include <CGAL/Alpha_shapes_2/internal/Lazy_alpha_nt_2.h>
|
||||
|
||||
// for convenience only
|
||||
#include <CGAL/Alpha_shape_vertex_base_2.h>
|
||||
|
|
|
|||
|
|
@ -17,7 +17,7 @@
|
|||
|
||||
|
||||
#include <CGAL/utility.h>
|
||||
#include <CGAL/internal/Lazy_alpha_nt_2.h>
|
||||
#include <CGAL/Alpha_shapes_2/internal/Lazy_alpha_nt_2.h>
|
||||
#include <CGAL/Default.h>
|
||||
#include <CGAL/Triangulation_face_base_2.h>
|
||||
|
||||
|
|
|
|||
|
|
@ -18,7 +18,7 @@
|
|||
|
||||
#include <utility>
|
||||
#include <CGAL/Triangulation_vertex_base_2.h>
|
||||
#include <CGAL/internal/Lazy_alpha_nt_2.h>
|
||||
#include <CGAL/Alpha_shapes_2/internal/Lazy_alpha_nt_2.h>
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
namespace CGAL {
|
||||
|
|
|
|||
|
|
@ -16,7 +16,7 @@
|
|||
#include <CGAL/license/Alpha_shapes_2.h>
|
||||
|
||||
#include <CGAL/assertions.h>
|
||||
#include <CGAL/internal/Exact_type_selector.h>
|
||||
#include <CGAL/Number_types/internal/Exact_type_selector.h>
|
||||
#include <CGAL/number_type_basic.h>
|
||||
#include <CGAL/Cartesian_converter.h>
|
||||
#include <CGAL/Has_conversion.h>
|
||||
|
|
@ -16,7 +16,7 @@
|
|||
|
||||
#include <CGAL/license/Alpha_shapes_3.h>
|
||||
|
||||
#include <CGAL/internal/Lazy_alpha_nt_3.h>
|
||||
#include <CGAL/Alpha_shapes_3/internal/Lazy_alpha_nt_3.h>
|
||||
#include <CGAL/Alpha_shape_cell_base_3.h> // for Alpha_status
|
||||
|
||||
#include <CGAL/basic.h>
|
||||
|
|
|
|||
|
|
@ -17,7 +17,7 @@
|
|||
#include <vector>
|
||||
#include <CGAL/Compact_container.h>
|
||||
#include <CGAL/Delaunay_triangulation_cell_base_3.h>
|
||||
#include <CGAL/internal/Lazy_alpha_nt_3.h>
|
||||
#include <CGAL/Alpha_shapes_3/internal/Lazy_alpha_nt_3.h>
|
||||
#include <CGAL/Default.h>
|
||||
|
||||
namespace CGAL {
|
||||
|
|
|
|||
|
|
@ -17,7 +17,7 @@
|
|||
|
||||
#include <CGAL/assertions.h>
|
||||
#include <CGAL/Cartesian_converter.h>
|
||||
#include <CGAL/internal/Exact_type_selector.h>
|
||||
#include <CGAL/Number_types/internal/Exact_type_selector.h>
|
||||
#include <CGAL/Has_conversion.h>
|
||||
|
||||
#include <memory>
|
||||
|
|
@ -36,7 +36,7 @@
|
|||
#include <CGAL/IO/Geomview_stream.h> // TBC
|
||||
#endif
|
||||
|
||||
#include <CGAL/internal/Classification_type.h>
|
||||
#include <CGAL/Alpha_shapes_3/internal/Classification_type.h>
|
||||
|
||||
#include <CGAL/Triangulation_3.h>
|
||||
|
||||
|
|
|
|||
|
|
@ -20,7 +20,7 @@
|
|||
#include <vector>
|
||||
#include <CGAL/Compact_container.h>
|
||||
#include <CGAL/Delaunay_triangulation_cell_base_3.h>
|
||||
#include <CGAL/internal/Classification_type.h>
|
||||
#include <CGAL/Alpha_shapes_3/internal/Classification_type.h>
|
||||
|
||||
namespace CGAL {
|
||||
|
||||
|
|
|
|||
|
|
@ -19,7 +19,7 @@
|
|||
|
||||
#include <utility>
|
||||
#include <CGAL/Triangulation_vertex_base_3.h>
|
||||
#include <CGAL/internal/Classification_type.h>
|
||||
#include <CGAL/Alpha_shapes_3/internal/Classification_type.h>
|
||||
|
||||
namespace CGAL {
|
||||
|
||||
|
|
|
|||
|
|
@ -37,7 +37,7 @@
|
|||
#include <CGAL/Apollonius_graph_vertex_base_2.h>
|
||||
|
||||
#include <CGAL/in_place_edge_list.h>
|
||||
#include <CGAL/internal/TDS_2/edge_list.h>
|
||||
#include <CGAL/TDS_2/internal/edge_list.h>
|
||||
#include <CGAL/Apollonius_graph_2/Traits_wrapper_2.h>
|
||||
|
||||
#include <CGAL/Apollonius_graph_2/Constructions_C2.h>
|
||||
|
|
|
|||
|
|
@ -15,7 +15,7 @@
|
|||
|
||||
#define CGAL_DEPRECATED_HEADER "<CGAL/Arr_rational_arc_traits_2.h>"
|
||||
#define CGAL_REPLACEMENT_HEADER "<CGAL/Arr_rational_function_traits_2.h>"
|
||||
#include <CGAL/internal/deprecation_warning.h>
|
||||
#include <CGAL/Installation/internal/deprecation_warning.h>
|
||||
|
||||
/*! \file
|
||||
* Definition of the Arr_rational_arc_traits_2 class.
|
||||
|
|
|
|||
|
|
@ -17,7 +17,7 @@
|
|||
|
||||
#define CGAL_DEPRECATED_HEADER "<CGAL/Arr_face_map.h>"
|
||||
#define CGAL_REPLACEMENT_HEADER "<CGAL/Arr_face_index_map.h>"
|
||||
#include <CGAL/internal/deprecation_warning.h>
|
||||
#include <CGAL/Installation/internal/deprecation_warning.h>
|
||||
|
||||
#include <CGAL/Arr_face_index_map.h>
|
||||
|
||||
|
|
|
|||
|
|
@ -16,7 +16,7 @@
|
|||
|
||||
#define CGAL_DEPRECATED_HEADER "<CGAL/Arr_geometry_traits/Polyline_2.h>"
|
||||
#define CGAL_REPLACEMENT_HEADER "<CGAL/Arr_geometry_traits/Polycurve_2.h>"
|
||||
#include <CGAL/internal/deprecation_warning.h>
|
||||
#include <CGAL/Installation/internal/deprecation_warning.h>
|
||||
|
||||
#include <CGAL/Arr_geometry_traits/Polycurve_2.h>
|
||||
|
||||
|
|
|
|||
|
|
@ -17,7 +17,7 @@
|
|||
|
||||
#define CGAL_DEPRECATED_HEADER "<CGAL/Arr_overlay.h>"
|
||||
#define CGAL_REPLACEMENT_HEADER "<CGAL/Arr_overlay_2.h>"
|
||||
#include <CGAL/internal/deprecation_warning.h>
|
||||
#include <CGAL/Installation/internal/deprecation_warning.h>
|
||||
|
||||
#include <CGAL/Arr_overlay_2.h>
|
||||
|
||||
|
|
|
|||
|
|
@ -131,7 +131,7 @@ private:
|
|||
};
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Memeber-function definitions:
|
||||
// Member-function definitions:
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
|
|
|||
|
|
@ -223,7 +223,7 @@ public:
|
|||
};
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Memeber-function definitions:
|
||||
// Member-function definitions:
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
|
|
|||
|
|
@ -97,7 +97,7 @@ public:
|
|||
};
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Memeber-function definitions:
|
||||
// Member-function definitions:
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
|
|
|||
|
|
@ -100,7 +100,7 @@ public:
|
|||
};
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Memeber-function definitions:
|
||||
// Member-function definitions:
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
|
|
|||
|
|
@ -176,7 +176,7 @@ public:
|
|||
};
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Memeber-function definitions:
|
||||
// Member-function definitions:
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
|
|
|||
|
|
@ -89,7 +89,7 @@ public:
|
|||
};
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Memeber-function definitions:
|
||||
// Member-function definitions:
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
|
|
|||
|
|
@ -107,7 +107,7 @@ public:
|
|||
};
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Memeber-function definitions:
|
||||
// Member-function definitions:
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
|
|
|||
|
|
@ -87,7 +87,7 @@ public:
|
|||
};
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Memeber-function definitions:
|
||||
// Member-function definitions:
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
|
|
|||
|
|
@ -18,7 +18,7 @@
|
|||
|
||||
#define CGAL_DEPRECATED_HEADER "<CGAL/Arr_vertex_map.h>"
|
||||
#define CGAL_REPLACEMENT_HEADER "<CGAL/Arr_vertex_index_map.h>"
|
||||
#include <CGAL/internal/deprecation_warning.h>
|
||||
#include <CGAL/Installation/internal/deprecation_warning.h>
|
||||
|
||||
#include <CGAL/Arr_vertex_index_map.h>
|
||||
|
||||
|
|
|
|||
|
|
@ -112,7 +112,7 @@ public:
|
|||
};
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Memeber-function definitions:
|
||||
// Member-function definitions:
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
|
|
|||
|
|
@ -134,7 +134,7 @@ public:
|
|||
|
||||
/*! using the additional data that we store at the event, we compute
|
||||
* how much we have to jump (he = he->next()->twin()) from the halfedge
|
||||
* that is stored in the event, to the halefge that is previous to 'curve'
|
||||
* that is stored in the event, to the halfedge that is previous to 'curve'
|
||||
* that is about to be inserted into the arrangement.
|
||||
*/
|
||||
int compute_halfedge_jump_count(Subcurve* curve)
|
||||
|
|
|
|||
|
|
@ -262,7 +262,7 @@ private:
|
|||
};
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Memeber-function definitions:
|
||||
// Member-function definitions:
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
|
|
|||
|
|
@ -67,6 +67,21 @@ private:
|
|||
X_monotone_curve_2 sub_cv1; // Auxiliary variables
|
||||
X_monotone_curve_2 sub_cv2; // (used for splitting curves).
|
||||
|
||||
|
||||
// update halfedge pointing to events, case with overlaps
|
||||
template <class Subcurve_>
|
||||
void update_incident_halfedge_after_split(Subcurve_* sc,
|
||||
Halfedge_handle he,
|
||||
Halfedge_handle new_he,
|
||||
Tag_true);
|
||||
|
||||
// update halfedge pointing to events, case without overlaps
|
||||
template <class Subcurve_>
|
||||
void update_incident_halfedge_after_split(Subcurve_* sc,
|
||||
Halfedge_handle he,
|
||||
Halfedge_handle new_he,
|
||||
Tag_false);
|
||||
|
||||
public:
|
||||
/*! A notification invoked when a new subcurve is created. */
|
||||
void add_subcurve(const X_monotone_curve_2& cv, Subcurve* sc);
|
||||
|
|
@ -99,6 +114,43 @@ public:
|
|||
// Member-function definitions:
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// update halfedge pointing to events, case with overlaps
|
||||
//
|
||||
template <typename Hlpr, typename Vis>
|
||||
template <class Subcurve_>
|
||||
void Arr_insertion_ss_visitor<Hlpr, Vis>::
|
||||
update_incident_halfedge_after_split(Subcurve_* sc,
|
||||
Halfedge_handle he,
|
||||
Halfedge_handle new_he,
|
||||
Tag_true)
|
||||
{
|
||||
std::vector<Subcurve*> leaves;
|
||||
sc->all_leaves( std::back_inserter(leaves) );
|
||||
for(Subcurve* ssc : leaves)
|
||||
{
|
||||
Event* last_event_on_ssc = ssc->last_event();
|
||||
if (last_event_on_ssc->halfedge_handle() == he)
|
||||
last_event_on_ssc->set_halfedge_handle(new_he->next());
|
||||
}
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// update halfedge pointing to events, case without overlaps
|
||||
//
|
||||
template <typename Hlpr, typename Vis>
|
||||
template <class Subcurve_>
|
||||
void Arr_insertion_ss_visitor<Hlpr, Vis>::
|
||||
update_incident_halfedge_after_split(Subcurve_* sc,
|
||||
Halfedge_handle he,
|
||||
Halfedge_handle new_he,
|
||||
Tag_false)
|
||||
{
|
||||
Event* last_event_on_sc = sc->last_event();
|
||||
if (last_event_on_sc->halfedge_handle() == he)
|
||||
last_event_on_sc->set_halfedge_handle(new_he->next());
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Check if the halfedge associated with the given subcurve will be split
|
||||
// at the given event.
|
||||
|
|
@ -132,9 +184,8 @@ Arr_insertion_ss_visitor<Hlpr, Vis>::split_edge(Halfedge_handle he, Subcurve* sc
|
|||
Halfedge_handle new_he =
|
||||
this->m_arr_access.split_edge_ex(he, pt.base(),
|
||||
sub_cv1.base(), sub_cv2.base());
|
||||
Event* last_event_on_sc = sc->last_event();
|
||||
if (last_event_on_sc->halfedge_handle() == he)
|
||||
last_event_on_sc->set_halfedge_handle(new_he->next());
|
||||
// update the halfedge incident to events on the left of the split
|
||||
update_incident_halfedge_after_split(sc, he, new_he, typename Subcurve::Handle_overlaps());
|
||||
|
||||
return new_he;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -219,7 +219,7 @@ protected:
|
|||
};
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Memeber-function definitions:
|
||||
// Member-function definitions:
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
|
|
|||
|
|
@ -401,7 +401,7 @@ protected:
|
|||
};
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Memeber-function definitions:
|
||||
// Member-function definitions:
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
|
|
|||
|
|
@ -126,7 +126,7 @@ public:
|
|||
};
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Memeber-function definitions:
|
||||
// Member-function definitions:
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
|
|
|||
|
|
@ -76,6 +76,20 @@ bool test_insert_at_vertices(){
|
|||
return test_insert_at_vertices_1() && test_insert_at_vertices_2();
|
||||
}
|
||||
|
||||
bool test_insert_on_overlap(){
|
||||
Arrangement_2 arr;
|
||||
|
||||
std::vector<Segment_2> segs1, segs2;
|
||||
segs1.emplace_back(Point_2(0, 0), Point_2(0, 4));
|
||||
segs2.emplace_back(Point_2(0, 0), Point_2(4,4));
|
||||
segs2.emplace_back(Point_2(0, 2), Point_2(0, 4));
|
||||
segs2.emplace_back(Point_2(0, 2), Point_2(4,4));
|
||||
CGAL::insert(arr, segs1.begin(), segs1.end());
|
||||
CGAL::insert(arr, segs2.begin(), segs2.end());
|
||||
|
||||
return is_valid(arr);
|
||||
}
|
||||
|
||||
int main ()
|
||||
{
|
||||
Arrangement_2 arr;
|
||||
|
|
@ -136,6 +150,10 @@ int main ()
|
|||
valid=test_insert_at_vertices();
|
||||
std::cout << ( valid ? "valid." : "NOT valid!") << std::endl;
|
||||
|
||||
if (!valid) return 1;
|
||||
std::cout << "Test insert on overlap\n";
|
||||
valid=test_insert_on_overlap();
|
||||
|
||||
return valid?0:1;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -126,6 +126,7 @@ CGAL_add_named_parameter(non_manifold_feature_map_t, non_manifold_feature_map, n
|
|||
CGAL_add_named_parameter(polyhedral_envelope_epsilon_t, polyhedral_envelope_epsilon, polyhedral_envelope_epsilon)
|
||||
CGAL_add_named_parameter(match_faces_t, match_faces, match_faces)
|
||||
CGAL_add_named_parameter(face_epsilon_map_t, face_epsilon_map, face_epsilon_map)
|
||||
CGAL_add_named_parameter(maximum_number_t, maximum_number, maximum_number)
|
||||
CGAL_add_named_parameter(use_one_sided_hausdorff_t, use_one_sided_hausdorff, use_one_sided_hausdorff)
|
||||
|
||||
// List of named parameters that we use in the package 'Surface Mesh Simplification'
|
||||
|
|
@ -179,6 +180,7 @@ CGAL_add_named_parameter(pointmatcher_config_t, pointmatcher_config, pointmatche
|
|||
CGAL_add_named_parameter(adjacencies_t, adjacencies, adjacencies)
|
||||
CGAL_add_named_parameter(scan_angle_t, scan_angle_map, scan_angle_map)
|
||||
CGAL_add_named_parameter(scanline_id_t, scanline_id_map, scanline_id_map)
|
||||
CGAL_add_named_parameter(scalar_t, scalar_map, scalar_map)
|
||||
|
||||
// List of named parameters used in Surface_mesh_approximation package
|
||||
CGAL_add_named_parameter(verbose_level_t, verbose_level, verbose_level)
|
||||
|
|
@ -214,3 +216,16 @@ CGAL_add_named_parameter(accuracy_t, accuracy, accuracy)
|
|||
CGAL_add_named_parameter(maximum_running_time_t, maximum_running_time, maximum_running_time)
|
||||
CGAL_add_named_parameter(overlap_t, overlap, overlap)
|
||||
CGAL_add_named_parameter(maximum_normal_deviation_t, maximum_normal_deviation, maximum_normal_deviation)
|
||||
|
||||
// List of named parameters used in Shape_regularization package
|
||||
CGAL_add_named_parameter(minimum_length_t, minimum_length, minimum_length)
|
||||
CGAL_add_named_parameter(maximum_angle_t, maximum_angle, maximum_angle)
|
||||
CGAL_add_named_parameter(maximum_offset_t, maximum_offset, maximum_offset)
|
||||
CGAL_add_named_parameter(regularize_parallelism_t, regularize_parallelism, regularize_parallelism)
|
||||
CGAL_add_named_parameter(regularize_orthogonality_t, regularize_orthogonality, regularize_orthogonality)
|
||||
CGAL_add_named_parameter(regularize_coplanarity_t, regularize_coplanarity, regularize_coplanarity)
|
||||
CGAL_add_named_parameter(regularize_axis_symmetry_t, regularize_axis_symmetry, regularize_axis_symmetry)
|
||||
CGAL_add_named_parameter(symmetry_direction_t, symmetry_direction, symmetry_direction)
|
||||
CGAL_add_named_parameter(preserve_order_t, preserve_order, preserve_order)
|
||||
CGAL_add_named_parameter(adjust_directions_t, adjust_directions, adjust_directions)
|
||||
CGAL_add_named_parameter(segment_t, segment_map, segment_map)
|
||||
|
|
|
|||
|
|
@ -18,8 +18,8 @@ property uchar green
|
|||
property uchar blue
|
||||
property int label
|
||||
element edge 6
|
||||
property int v0
|
||||
property int v1
|
||||
property int vertex1
|
||||
property int vertex2
|
||||
property float confidence
|
||||
end_header
|
||||
0 0 0 -0.5 -0.5 -0.5 255 255 0 0
|
||||
|
|
|
|||
|
|
@ -18,8 +18,8 @@ property uchar green
|
|||
property uchar blue
|
||||
property int label
|
||||
element edge 6
|
||||
property int v0
|
||||
property int v1
|
||||
property int vertex1
|
||||
property int vertex2
|
||||
property float confidence
|
||||
end_header
|
||||
0 0 0 -0.5 -0.5 -0.5 255 255 0 0
|
||||
|
|
|
|||
|
|
@ -18,8 +18,8 @@ property uchar green
|
|||
property uchar blue
|
||||
property int label
|
||||
element edge 6
|
||||
property int v0
|
||||
property int v1
|
||||
property int vertex1
|
||||
property int vertex2
|
||||
property float confidence
|
||||
end_header
|
||||
0 0 0 -0.5 -0.5 -0.5 0
|
||||
|
|
|
|||
|
|
@ -110,6 +110,7 @@ void test(const NamedParameters& np)
|
|||
assert(get_parameter(np, CGAL::internal_np::non_manifold_feature_map).v == 60);
|
||||
assert(get_parameter(np, CGAL::internal_np::filter).v == 61);
|
||||
assert(get_parameter(np, CGAL::internal_np::face_epsilon_map).v == 62);
|
||||
assert(get_parameter(np, CGAL::internal_np::maximum_number).v == 68);
|
||||
|
||||
// Named parameters that we use in the package 'Surface Mesh Simplification'
|
||||
assert(get_parameter(np, CGAL::internal_np::get_cost_policy).v == 34);
|
||||
|
|
@ -227,6 +228,7 @@ void test(const NamedParameters& np)
|
|||
check_same_type<60>(get_parameter(np, CGAL::internal_np::non_manifold_feature_map));
|
||||
check_same_type<61>(get_parameter(np, CGAL::internal_np::filter));
|
||||
check_same_type<62>(get_parameter(np, CGAL::internal_np::face_epsilon_map));
|
||||
check_same_type<68>(get_parameter(np, CGAL::internal_np::maximum_number));
|
||||
|
||||
// Named parameters that we use in the package 'Surface Mesh Simplification'
|
||||
check_same_type<34>(get_parameter(np, CGAL::internal_np::get_cost_policy));
|
||||
|
|
@ -356,6 +358,7 @@ int main()
|
|||
.non_manifold_feature_map(A<60>(60))
|
||||
.filter(A<61>(61))
|
||||
.face_epsilon_map(A<62>(62))
|
||||
.maximum_number(A<68>(68))
|
||||
.apply_per_connected_component(A<46>(46))
|
||||
.output_iterator(A<47>(47))
|
||||
.erase_all_duplicates(A<48>(48))
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
#include <CGAL/internal/disable_deprecation_warnings_and_errors.h>
|
||||
#include <CGAL/Installation/internal/disable_deprecation_warnings_and_errors.h>
|
||||
|
||||
#include <fstream>
|
||||
#include <iostream>
|
||||
|
|
|
|||
|
|
@ -24,7 +24,8 @@ typedef std::vector<Point_2> Polyline_2;
|
|||
// inserts a polyline into a graph
|
||||
void insert(const std::vector<Point_2>& poly, Graph& graph, Point_vertex_map& pvmap)
|
||||
{
|
||||
vertex_descriptor u, v;
|
||||
vertex_descriptor u = boost::graph_traits<Graph>::null_vertex();
|
||||
vertex_descriptor v;
|
||||
for (std::size_t i = 0; i < poly.size(); i++) {
|
||||
// check if the point is not yet in the graph
|
||||
if (pvmap.find(poly[i]) == pvmap.end()) {
|
||||
|
|
|
|||
|
|
@ -0,0 +1,31 @@
|
|||
# Created by the script cgal_create_cmake_script.
|
||||
# This is the CMake script for compiling a CGAL application.
|
||||
|
||||
project(Barycentric_coordinates_2_Benchmarks)
|
||||
|
||||
cmake_minimum_required(VERSION 3.1...3.15)
|
||||
set(CMAKE_CXX_STANDARD 14)
|
||||
|
||||
find_package(CGAL REQUIRED COMPONENTS Core)
|
||||
include(${CGAL_USE_FILE})
|
||||
include(CGAL_CreateSingleSourceCGALProgram)
|
||||
|
||||
create_single_source_cgal_program("benchmark_segment_coordinates.cpp")
|
||||
create_single_source_cgal_program("benchmark_triangle_coordinates.cpp")
|
||||
create_single_source_cgal_program("benchmark_polygon_4_vertices.cpp")
|
||||
create_single_source_cgal_program("benchmark_polygon_16_vertices.cpp")
|
||||
create_single_source_cgal_program("benchmark_polygon_100_vertices.cpp")
|
||||
create_single_source_cgal_program("benchmark_mv_34_vertices.cpp")
|
||||
|
||||
find_package(Eigen3 3.1.0 QUIET) # (3.1.0 or greater)
|
||||
include(CGAL_Eigen3_support)
|
||||
if(TARGET CGAL::Eigen3_support)
|
||||
|
||||
create_single_source_cgal_program("benchmark_hm_4_vertices.cpp")
|
||||
target_link_libraries(benchmark_hm_4_vertices PUBLIC CGAL::Eigen3_support)
|
||||
create_single_source_cgal_program("benchmark_hm_n_vertices.cpp")
|
||||
target_link_libraries(benchmark_hm_n_vertices PUBLIC CGAL::Eigen3_support)
|
||||
|
||||
else()
|
||||
message(NOTICE "Several coordinates require the Eigen library, and will not be compiled.")
|
||||
endif()
|
||||
|
|
@ -1,70 +0,0 @@
|
|||
// Author: Dmitry Anisimov.
|
||||
// We test speed of discrete harmonic coordinates on a set of automatically generated
|
||||
// points inside a unit square. We use inexact kernel.
|
||||
|
||||
#include <CGAL/Real_timer.h>
|
||||
#include <CGAL/Exact_predicates_inexact_constructions_kernel.h>
|
||||
#include <CGAL/Barycentric_coordinates_2/Discrete_harmonic_2.h>
|
||||
#include <CGAL/Barycentric_coordinates_2/Generalized_barycentric_coordinates_2.h>
|
||||
|
||||
typedef CGAL::Real_timer Timer;
|
||||
|
||||
typedef CGAL::Exact_predicates_inexact_constructions_kernel Kernel;
|
||||
|
||||
typedef Kernel::FT Scalar;
|
||||
typedef Kernel::Point_2 Point;
|
||||
|
||||
typedef std::vector<Scalar> Coordinate_vector;
|
||||
typedef std::vector<Point> Point_vector;
|
||||
|
||||
typedef Coordinate_vector::iterator Overwrite_iterator;
|
||||
|
||||
typedef CGAL::Barycentric_coordinates::Discrete_harmonic_2<Kernel> Discrete_harmonic;
|
||||
typedef CGAL::Barycentric_coordinates::Generalized_barycentric_coordinates_2<Discrete_harmonic, Kernel> Discrete_harmonic_coordinates;
|
||||
|
||||
using std::cout; using std::endl; using std::string;
|
||||
|
||||
int main()
|
||||
{
|
||||
const int number_of_x_coordinates = 1000000;
|
||||
const int number_of_y_coordinates = 1000;
|
||||
const int number_of_runs = 1;
|
||||
|
||||
const Scalar zero = Scalar(0);
|
||||
const Scalar one = Scalar(1);
|
||||
const Scalar x_step = one / Scalar(number_of_x_coordinates);
|
||||
const Scalar y_step = one / Scalar(number_of_y_coordinates);
|
||||
|
||||
Point_vector vertices(4);
|
||||
|
||||
vertices[0] = Point(zero - x_step, zero - y_step); vertices[1] = Point(one + x_step, zero - y_step);
|
||||
vertices[2] = Point(one + x_step, one + y_step); vertices[3] = Point(zero - x_step, one + y_step);
|
||||
|
||||
Discrete_harmonic_coordinates discrete_harmonic_coordinates(vertices.begin(), vertices.end());
|
||||
|
||||
Coordinate_vector coordinates(4);
|
||||
Overwrite_iterator it = coordinates.begin();
|
||||
|
||||
Timer time_to_compute;
|
||||
|
||||
double time = 0.0;
|
||||
for(int i = 0; i < number_of_runs; ++i) {
|
||||
|
||||
time_to_compute.start();
|
||||
for(Scalar x = zero; x <= one; x += x_step) {
|
||||
for(Scalar y = zero; y <= one; y += y_step)
|
||||
discrete_harmonic_coordinates(Point(x, y), it, CGAL::Barycentric_coordinates::ON_BOUNDED_SIDE);
|
||||
}
|
||||
time_to_compute.stop();
|
||||
|
||||
time += time_to_compute.time();
|
||||
|
||||
time_to_compute.reset();
|
||||
}
|
||||
const double mean_time = time / number_of_runs;
|
||||
|
||||
cout.precision(10);
|
||||
cout << endl << "CPU time to compute Discrete Harmonic coordinates (4 vertices) = " << mean_time << " seconds." << endl << endl;
|
||||
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
|
|
@ -1,83 +0,0 @@
|
|||
// Author: Dmitry Anisimov.
|
||||
// We test speed of discrete harmonic coordinates on a set of automatically generated
|
||||
// points inside a regular polygon with 100 vertices. We use inexact kernel.
|
||||
|
||||
#include <CGAL/number_type_config.h>
|
||||
#include <CGAL/Real_timer.h>
|
||||
#include <CGAL/Exact_predicates_inexact_constructions_kernel.h>
|
||||
#include <CGAL/Barycentric_coordinates_2/Discrete_harmonic_2.h>
|
||||
#include <CGAL/Barycentric_coordinates_2/Generalized_barycentric_coordinates_2.h>
|
||||
|
||||
typedef CGAL::Real_timer Timer;
|
||||
|
||||
typedef CGAL::Exact_predicates_inexact_constructions_kernel Kernel;
|
||||
|
||||
typedef Kernel::FT Scalar;
|
||||
typedef Kernel::Point_2 Point;
|
||||
|
||||
typedef std::vector<Scalar> Scalar_vector;
|
||||
typedef std::vector<Point> Point_vector;
|
||||
|
||||
typedef Scalar_vector::iterator Overwrite_iterator;
|
||||
|
||||
typedef CGAL::Barycentric_coordinates::Discrete_harmonic_2<Kernel> Discrete_harmonic;
|
||||
typedef CGAL::Barycentric_coordinates::Generalized_barycentric_coordinates_2<Discrete_harmonic, Kernel> Discrete_harmonic_coordinates;
|
||||
|
||||
using std::cout; using std::endl; using std::string;
|
||||
|
||||
void generate_regular_polygon(const int number_of_vertices, const double polygon_radius, Point_vector &vertices)
|
||||
{
|
||||
const int n = number_of_vertices;
|
||||
const double r = polygon_radius;
|
||||
|
||||
vertices.resize(n);
|
||||
|
||||
for(int i = 0; i < n; ++i)
|
||||
vertices[i] = Point(Scalar(r*sin((CGAL_PI / n) + ((i * 2.0 * CGAL_PI) / n))), Scalar(-r*cos((CGAL_PI / n) + ((i * 2.0 * CGAL_PI) / n))));
|
||||
}
|
||||
|
||||
int main()
|
||||
{
|
||||
const int number_of_x_coordinates = 1000;
|
||||
const int number_of_y_coordinates = 1000;
|
||||
const int number_of_runs = 1;
|
||||
|
||||
const Scalar one = Scalar(1);
|
||||
const Scalar x_step = one / Scalar(number_of_x_coordinates);
|
||||
const Scalar y_step = one / Scalar(number_of_y_coordinates);
|
||||
|
||||
Point_vector vertices;
|
||||
|
||||
const int number_of_vertices = 100;
|
||||
const double polygon_radius = 2;
|
||||
|
||||
generate_regular_polygon(number_of_vertices, polygon_radius, vertices);
|
||||
|
||||
Discrete_harmonic_coordinates discrete_harmonic_coordinates(vertices.begin(), vertices.end());
|
||||
|
||||
Scalar_vector coordinates(number_of_vertices);
|
||||
Overwrite_iterator it = coordinates.begin();
|
||||
|
||||
Timer time_to_compute;
|
||||
|
||||
double time = 0.0;
|
||||
for(int i = 0; i < number_of_runs; ++i) {
|
||||
|
||||
time_to_compute.start();
|
||||
for(Scalar x = -one; x <= one; x += x_step) {
|
||||
for(Scalar y = -one; y <= one; y += y_step)
|
||||
discrete_harmonic_coordinates(Point(x, y), it, CGAL::Barycentric_coordinates::ON_BOUNDED_SIDE);
|
||||
}
|
||||
time_to_compute.stop();
|
||||
|
||||
time += time_to_compute.time();
|
||||
|
||||
time_to_compute.reset();
|
||||
}
|
||||
const double mean_time = time / number_of_runs;
|
||||
|
||||
cout.precision(10);
|
||||
cout << endl << "CPU time to compute Discrete Harmonic coordinates (100 vertices) = " << mean_time << " seconds." << endl << endl;
|
||||
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
|
|
@ -1,76 +0,0 @@
|
|||
// Author: Dmitry Anisimov.
|
||||
// We test speed of discrete harmonic coordinates on a set of automatically generated
|
||||
// points inside a convex polygon with 16 vertices. We use inexact kernel.
|
||||
|
||||
#include <CGAL/Real_timer.h>
|
||||
#include <CGAL/Exact_predicates_inexact_constructions_kernel.h>
|
||||
#include <CGAL/Barycentric_coordinates_2/Discrete_harmonic_2.h>
|
||||
#include <CGAL/Barycentric_coordinates_2/Generalized_barycentric_coordinates_2.h>
|
||||
|
||||
typedef CGAL::Real_timer Timer;
|
||||
|
||||
typedef CGAL::Exact_predicates_inexact_constructions_kernel Kernel;
|
||||
|
||||
typedef Kernel::FT Scalar;
|
||||
typedef Kernel::Point_2 Point;
|
||||
|
||||
typedef std::vector<Scalar> Coordinate_vector;
|
||||
typedef std::vector<Point> Point_vector;
|
||||
|
||||
typedef Coordinate_vector::iterator Overwrite_iterator;
|
||||
|
||||
typedef CGAL::Barycentric_coordinates::Discrete_harmonic_2<Kernel> Discrete_harmonic;
|
||||
typedef CGAL::Barycentric_coordinates::Generalized_barycentric_coordinates_2<Discrete_harmonic, Kernel> Discrete_harmonic_coordinates;
|
||||
|
||||
using std::cout; using std::endl; using std::string;
|
||||
|
||||
int main()
|
||||
{
|
||||
const int number_of_x_coordinates = 100000;
|
||||
const int number_of_y_coordinates = 1000;
|
||||
const int number_of_runs = 1;
|
||||
|
||||
const Scalar zero = Scalar(0);
|
||||
const Scalar one = Scalar(1);
|
||||
const Scalar x_step = one / Scalar(number_of_x_coordinates);
|
||||
const Scalar y_step = one / Scalar(number_of_y_coordinates);
|
||||
|
||||
Point_vector vertices(16);
|
||||
|
||||
vertices[0] = Point(zero, zero - y_step); vertices[1] = Point(one, zero - y_step);
|
||||
vertices[2] = Point(Scalar(3) / Scalar(2), Scalar(1) / Scalar(4)); vertices[3] = Point(2, Scalar(3) / Scalar(4) );
|
||||
vertices[4] = Point(Scalar(9) / Scalar(4), Scalar(5) / Scalar(4)); vertices[5] = Point(Scalar(9) / Scalar(4), Scalar(9) / Scalar(4));
|
||||
vertices[6] = Point(2, Scalar(11) / Scalar(4) ); vertices[7] = Point(Scalar(3) / Scalar(2), Scalar(13) / Scalar(4));
|
||||
vertices[8] = Point(1, Scalar(7) / Scalar(2) ); vertices[9] = Point(0, Scalar(7) / Scalar(2) );
|
||||
vertices[10] = Point(Scalar(-1) / Scalar(2), Scalar(13) / Scalar(4)); vertices[11] = Point(-1, Scalar(11) / Scalar(4) );
|
||||
vertices[12] = Point(Scalar(-5) / Scalar(4), Scalar(9) / Scalar(4)); vertices[13] = Point(Scalar(-5) / Scalar(4), Scalar(5) / Scalar(4));
|
||||
vertices[14] = Point(-1, Scalar(3) / Scalar(4) ); vertices[15] = Point(Scalar(-1) / Scalar(2), Scalar(1) / Scalar(4));
|
||||
|
||||
Discrete_harmonic_coordinates discrete_harmonic_coordinates(vertices.begin(), vertices.end());
|
||||
|
||||
Coordinate_vector coordinates(16);
|
||||
Overwrite_iterator it = coordinates.begin();
|
||||
|
||||
Timer time_to_compute;
|
||||
|
||||
double time = 0.0;
|
||||
for(int i = 0; i < number_of_runs; ++i) {
|
||||
|
||||
time_to_compute.start();
|
||||
for(Scalar x = zero; x <= one; x += x_step) {
|
||||
for(Scalar y = zero; y <= one; y += y_step)
|
||||
discrete_harmonic_coordinates(Point(x, y), it, CGAL::Barycentric_coordinates::ON_BOUNDED_SIDE);
|
||||
}
|
||||
time_to_compute.stop();
|
||||
|
||||
time += time_to_compute.time();
|
||||
|
||||
time_to_compute.reset();
|
||||
}
|
||||
const double mean_time = time / number_of_runs;
|
||||
|
||||
cout.precision(10);
|
||||
cout << endl << "CPU time to compute Discrete Harmonic coordinates (16 vertices) = " << mean_time << " seconds." << endl << endl;
|
||||
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
|
|
@ -1,76 +0,0 @@
|
|||
// Author: Dmitry Anisimov.
|
||||
// We test speed of discrete harmonic coordinates on a set of automatically generated
|
||||
// points inside a convex polygon with 16 vertices. We use inexact kernel.
|
||||
|
||||
#include <CGAL/Real_timer.h>
|
||||
#include <CGAL/Exact_predicates_inexact_constructions_kernel.h>
|
||||
#include <CGAL/Barycentric_coordinates_2/Discrete_harmonic_2.h>
|
||||
#include <CGAL/Barycentric_coordinates_2/Generalized_barycentric_coordinates_2.h>
|
||||
|
||||
typedef CGAL::Real_timer Timer;
|
||||
|
||||
typedef CGAL::Exact_predicates_inexact_constructions_kernel Kernel;
|
||||
|
||||
typedef Kernel::FT Scalar;
|
||||
typedef Kernel::Point_2 Point;
|
||||
|
||||
typedef std::vector<Scalar> Coordinate_vector;
|
||||
typedef std::vector<Point> Point_vector;
|
||||
|
||||
typedef Coordinate_vector::iterator Overwrite_iterator;
|
||||
|
||||
typedef CGAL::Barycentric_coordinates::Discrete_harmonic_2<Kernel> Discrete_harmonic;
|
||||
typedef CGAL::Barycentric_coordinates::Generalized_barycentric_coordinates_2<Discrete_harmonic, Kernel> Discrete_harmonic_coordinates;
|
||||
|
||||
using std::cout; using std::endl; using std::string;
|
||||
|
||||
int main()
|
||||
{
|
||||
const int number_of_x_coordinates = 100000;
|
||||
const int number_of_y_coordinates = 1000;
|
||||
const int number_of_runs = 1;
|
||||
|
||||
const Scalar zero = Scalar(0);
|
||||
const Scalar one = Scalar(1);
|
||||
const Scalar x_step = one / Scalar(number_of_x_coordinates);
|
||||
const Scalar y_step = one / Scalar(number_of_y_coordinates);
|
||||
|
||||
Point_vector vertices(16);
|
||||
|
||||
vertices[0] = Point(zero, zero - y_step); vertices[1] = Point(one, zero - y_step);
|
||||
vertices[2] = Point(Scalar(3) / Scalar(2), Scalar(1) / Scalar(4)); vertices[3] = Point(2, Scalar(3) / Scalar(4) );
|
||||
vertices[4] = Point(Scalar(9) / Scalar(4), Scalar(5) / Scalar(4)); vertices[5] = Point(Scalar(9) / Scalar(4), Scalar(9) / Scalar(4));
|
||||
vertices[6] = Point(2, Scalar(11) / Scalar(4) ); vertices[7] = Point(Scalar(3) / Scalar(2), Scalar(13) / Scalar(4));
|
||||
vertices[8] = Point(1, Scalar(7) / Scalar(2) ); vertices[9] = Point(0, Scalar(7) / Scalar(2) );
|
||||
vertices[10] = Point(Scalar(-1) / Scalar(2), Scalar(13) / Scalar(4)); vertices[11] = Point(-1, Scalar(11) / Scalar(4) );
|
||||
vertices[12] = Point(Scalar(-5) / Scalar(4), Scalar(9) / Scalar(4)); vertices[13] = Point(Scalar(-5) / Scalar(4), Scalar(5) / Scalar(4));
|
||||
vertices[14] = Point(-1, Scalar(3) / Scalar(4) ); vertices[15] = Point(Scalar(-1) / Scalar(2), Scalar(1) / Scalar(4));
|
||||
|
||||
Discrete_harmonic_coordinates discrete_harmonic_coordinates(vertices.begin(), vertices.end());
|
||||
|
||||
Coordinate_vector coordinates(16);
|
||||
Overwrite_iterator it = coordinates.begin();
|
||||
|
||||
Timer time_to_compute;
|
||||
|
||||
double time = 0.0;
|
||||
for(int i = 0; i < number_of_runs; ++i) {
|
||||
|
||||
time_to_compute.start();
|
||||
for(Scalar x = zero; x <= one; x += x_step) {
|
||||
for(Scalar y = zero; y <= one; y += y_step)
|
||||
discrete_harmonic_coordinates(Point(x, y), it, CGAL::Barycentric_coordinates::ON_BOUNDED_SIDE);
|
||||
}
|
||||
time_to_compute.stop();
|
||||
|
||||
time += time_to_compute.time();
|
||||
|
||||
time_to_compute.reset();
|
||||
}
|
||||
const double mean_time = time / number_of_runs;
|
||||
|
||||
cout.precision(10);
|
||||
cout << endl << "CPU time to compute Discrete Harmonic coordinates (16 vertices) = " << mean_time << " seconds." << endl << endl;
|
||||
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
|
|
@ -1,76 +0,0 @@
|
|||
// Author: Dmitry Anisimov.
|
||||
// We test speed of discrete harmonic weights on a set of automatically generated
|
||||
// points inside a convex polygon with 16 vertices. We use inexact kernel.
|
||||
|
||||
#include <CGAL/Real_timer.h>
|
||||
#include <CGAL/Exact_predicates_inexact_constructions_kernel.h>
|
||||
#include <CGAL/Barycentric_coordinates_2/Discrete_harmonic_2.h>
|
||||
#include <CGAL/Barycentric_coordinates_2/Generalized_barycentric_coordinates_2.h>
|
||||
|
||||
typedef CGAL::Real_timer Timer;
|
||||
|
||||
typedef CGAL::Exact_predicates_inexact_constructions_kernel Kernel;
|
||||
|
||||
typedef Kernel::FT Scalar;
|
||||
typedef Kernel::Point_2 Point;
|
||||
|
||||
typedef std::vector<Scalar> Weight_vector;
|
||||
typedef std::vector<Point> Point_vector;
|
||||
|
||||
typedef Weight_vector::iterator Overwrite_iterator;
|
||||
|
||||
typedef CGAL::Barycentric_coordinates::Discrete_harmonic_2<Kernel> Discrete_harmonic;
|
||||
typedef CGAL::Barycentric_coordinates::Generalized_barycentric_coordinates_2<Discrete_harmonic, Kernel> Discrete_harmonic_coordinates;
|
||||
|
||||
using std::cout; using std::endl; using std::string;
|
||||
|
||||
int main()
|
||||
{
|
||||
const int number_of_x_coordinates = 100000;
|
||||
const int number_of_y_coordinates = 1000;
|
||||
const int number_of_runs = 1;
|
||||
|
||||
const Scalar zero = Scalar(0);
|
||||
const Scalar one = Scalar(1);
|
||||
const Scalar x_step = one / Scalar(number_of_x_coordinates);
|
||||
const Scalar y_step = one / Scalar(number_of_y_coordinates);
|
||||
|
||||
Point_vector vertices(16);
|
||||
|
||||
vertices[0] = Point(zero, zero - y_step); vertices[1] = Point(one, zero - y_step);
|
||||
vertices[2] = Point(Scalar(3) / Scalar(2), Scalar(1) / Scalar(4)); vertices[3] = Point(2, Scalar(3) / Scalar(4) );
|
||||
vertices[4] = Point(Scalar(9) / Scalar(4), Scalar(5) / Scalar(4)); vertices[5] = Point(Scalar(9) / Scalar(4), Scalar(9) / Scalar(4));
|
||||
vertices[6] = Point(2, Scalar(11) / Scalar(4) ); vertices[7] = Point(Scalar(3) / Scalar(2), Scalar(13) / Scalar(4));
|
||||
vertices[8] = Point(1, Scalar(7) / Scalar(2) ); vertices[9] = Point(0, Scalar(7) / Scalar(2) );
|
||||
vertices[10] = Point(Scalar(-1) / Scalar(2), Scalar(13) / Scalar(4)); vertices[11] = Point(-1, Scalar(11) / Scalar(4) );
|
||||
vertices[12] = Point(Scalar(-5) / Scalar(4), Scalar(9) / Scalar(4)); vertices[13] = Point(Scalar(-5) / Scalar(4), Scalar(5) / Scalar(4));
|
||||
vertices[14] = Point(-1, Scalar(3) / Scalar(4) ); vertices[15] = Point(Scalar(-1) / Scalar(2), Scalar(1) / Scalar(4));
|
||||
|
||||
Discrete_harmonic_coordinates discrete_harmonic_coordinates(vertices.begin(), vertices.end());
|
||||
|
||||
Weight_vector weights(16);
|
||||
Overwrite_iterator it = weights.begin();
|
||||
|
||||
Timer time_to_compute;
|
||||
|
||||
double time = 0.0;
|
||||
for(int i = 0; i < number_of_runs; ++i) {
|
||||
|
||||
time_to_compute.start();
|
||||
for(Scalar x = zero; x <= one; x += x_step) {
|
||||
for(Scalar y = zero; y <= one; y += y_step)
|
||||
discrete_harmonic_coordinates.compute_weights(Point(x, y), it);
|
||||
}
|
||||
time_to_compute.stop();
|
||||
|
||||
time += time_to_compute.time();
|
||||
|
||||
time_to_compute.reset();
|
||||
}
|
||||
const double mean_time = time / number_of_runs;
|
||||
|
||||
cout.precision(10);
|
||||
cout << endl << "CPU time to compute Discrete Harmonic weights (16 vertices) = " << mean_time << " seconds." << endl << endl;
|
||||
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
|
|
@ -1,70 +0,0 @@
|
|||
// Author: Dmitry Anisimov.
|
||||
// We test speed of mean value coordinates on a set of automatically generated
|
||||
// points inside a unit square. We use inexact kernel.
|
||||
|
||||
#include <CGAL/Real_timer.h>
|
||||
#include <CGAL/Exact_predicates_inexact_constructions_kernel.h>
|
||||
#include <CGAL/Barycentric_coordinates_2/Mean_value_2.h>
|
||||
#include <CGAL/Barycentric_coordinates_2/Generalized_barycentric_coordinates_2.h>
|
||||
|
||||
typedef CGAL::Real_timer Timer;
|
||||
|
||||
typedef CGAL::Exact_predicates_inexact_constructions_kernel Kernel;
|
||||
|
||||
typedef Kernel::FT Scalar;
|
||||
typedef Kernel::Point_2 Point;
|
||||
|
||||
typedef std::vector<Scalar> Coordinate_vector;
|
||||
typedef std::vector<Point> Point_vector;
|
||||
|
||||
typedef Coordinate_vector::iterator Overwrite_iterator;
|
||||
|
||||
typedef CGAL::Barycentric_coordinates::Mean_value_2<Kernel> Mean_value;
|
||||
typedef CGAL::Barycentric_coordinates::Generalized_barycentric_coordinates_2<Mean_value, Kernel> Mean_value_coordinates;
|
||||
|
||||
using std::cout; using std::endl; using std::string;
|
||||
|
||||
int main()
|
||||
{
|
||||
const int number_of_x_coordinates = 1000000;
|
||||
const int number_of_y_coordinates = 1000;
|
||||
const int number_of_runs = 1;
|
||||
|
||||
const Scalar zero = Scalar(0);
|
||||
const Scalar one = Scalar(1);
|
||||
const Scalar x_step = one / Scalar(number_of_x_coordinates);
|
||||
const Scalar y_step = one / Scalar(number_of_y_coordinates);
|
||||
|
||||
Point_vector vertices(4);
|
||||
|
||||
vertices[0] = Point(zero - x_step, zero - y_step); vertices[1] = Point(one + x_step, zero - y_step);
|
||||
vertices[2] = Point(one + x_step, one + y_step); vertices[3] = Point(zero - x_step, one + y_step);
|
||||
|
||||
Mean_value_coordinates mean_value_coordinates(vertices.begin(), vertices.end());
|
||||
|
||||
Coordinate_vector coordinates(4);
|
||||
Overwrite_iterator it = coordinates.begin();
|
||||
|
||||
Timer time_to_compute;
|
||||
|
||||
double time = 0.0;
|
||||
for(int i = 0; i < number_of_runs; ++i) {
|
||||
|
||||
time_to_compute.start();
|
||||
for(Scalar x = zero; x <= one; x += x_step) {
|
||||
for(Scalar y = zero; y <= one; y += y_step)
|
||||
mean_value_coordinates(Point(x, y), it, CGAL::Barycentric_coordinates::ON_BOUNDED_SIDE);
|
||||
}
|
||||
time_to_compute.stop();
|
||||
|
||||
time += time_to_compute.time();
|
||||
|
||||
time_to_compute.reset();
|
||||
}
|
||||
const double mean_time = time / number_of_runs;
|
||||
|
||||
cout.precision(10);
|
||||
cout << endl << "CPU time to compute Mean Value coordinates (4 vertices) = " << mean_time << " seconds." << endl << endl;
|
||||
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
|
|
@ -1,83 +0,0 @@
|
|||
// Author: Dmitry Anisimov.
|
||||
// We test speed of mean value coordinates on a set of automatically generated
|
||||
// points inside a regular polygon with 100 vertices. We use inexact kernel.
|
||||
|
||||
#include <CGAL/number_type_config.h>
|
||||
#include <CGAL/Real_timer.h>
|
||||
#include <CGAL/Exact_predicates_inexact_constructions_kernel.h>
|
||||
#include <CGAL/Barycentric_coordinates_2/Mean_value_2.h>
|
||||
#include <CGAL/Barycentric_coordinates_2/Generalized_barycentric_coordinates_2.h>
|
||||
|
||||
typedef CGAL::Real_timer Timer;
|
||||
|
||||
typedef CGAL::Exact_predicates_inexact_constructions_kernel Kernel;
|
||||
|
||||
typedef Kernel::FT Scalar;
|
||||
typedef Kernel::Point_2 Point;
|
||||
|
||||
typedef std::vector<Scalar> Scalar_vector;
|
||||
typedef std::vector<Point> Point_vector;
|
||||
|
||||
typedef Scalar_vector::iterator Overwrite_iterator;
|
||||
|
||||
typedef CGAL::Barycentric_coordinates::Mean_value_2<Kernel> Mean_value;
|
||||
typedef CGAL::Barycentric_coordinates::Generalized_barycentric_coordinates_2<Mean_value, Kernel> Mean_value_coordinates;
|
||||
|
||||
using std::cout; using std::endl; using std::string;
|
||||
|
||||
void generate_regular_polygon(const int number_of_vertices, const double polygon_radius, Point_vector &vertices)
|
||||
{
|
||||
const int n = number_of_vertices;
|
||||
const double r = polygon_radius;
|
||||
|
||||
vertices.resize(n);
|
||||
|
||||
for(int i = 0; i < n; ++i)
|
||||
vertices[i] = Point(Scalar(r*sin((CGAL_PI / n) + ((i * 2.0 * CGAL_PI) / n))), Scalar(-r*cos((CGAL_PI / n) + ((i * 2.0 * CGAL_PI) / n))));
|
||||
}
|
||||
|
||||
int main()
|
||||
{
|
||||
const int number_of_x_coordinates = 1000;
|
||||
const int number_of_y_coordinates = 1000;
|
||||
const int number_of_runs = 1;
|
||||
|
||||
const Scalar one = Scalar(1);
|
||||
const Scalar x_step = one / Scalar(number_of_x_coordinates);
|
||||
const Scalar y_step = one / Scalar(number_of_y_coordinates);
|
||||
|
||||
Point_vector vertices;
|
||||
|
||||
const int number_of_vertices = 100;
|
||||
const double polygon_radius = 2;
|
||||
|
||||
generate_regular_polygon(number_of_vertices, polygon_radius, vertices);
|
||||
|
||||
Mean_value_coordinates mean_value_coordinates(vertices.begin(), vertices.end());
|
||||
|
||||
Scalar_vector coordinates(number_of_vertices);
|
||||
Overwrite_iterator it = coordinates.begin();
|
||||
|
||||
Timer time_to_compute;
|
||||
|
||||
double time = 0.0;
|
||||
for(int i = 0; i < number_of_runs; ++i) {
|
||||
|
||||
time_to_compute.start();
|
||||
for(Scalar x = -one; x <= one; x += x_step) {
|
||||
for(Scalar y = -one; y <= one; y += y_step)
|
||||
mean_value_coordinates(Point(x, y), it, CGAL::Barycentric_coordinates::ON_BOUNDED_SIDE);
|
||||
}
|
||||
time_to_compute.stop();
|
||||
|
||||
time += time_to_compute.time();
|
||||
|
||||
time_to_compute.reset();
|
||||
}
|
||||
const double mean_time = time / number_of_runs;
|
||||
|
||||
cout.precision(10);
|
||||
cout << endl << "CPU time to compute Mean Value coordinates (100 vertices) = " << mean_time << " seconds." << endl << endl;
|
||||
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
|
|
@ -1,85 +0,0 @@
|
|||
// Author: Dmitry Anisimov.
|
||||
// We test speed of mean value coordinates on a set of automatically generated
|
||||
// points inside a concave polygon with 34 vertices. We use inexact kernel.
|
||||
|
||||
#include <CGAL/Real_timer.h>
|
||||
#include <CGAL/Exact_predicates_inexact_constructions_kernel.h>
|
||||
#include <CGAL/Barycentric_coordinates_2/Mean_value_2.h>
|
||||
#include <CGAL/Barycentric_coordinates_2/Generalized_barycentric_coordinates_2.h>
|
||||
|
||||
typedef CGAL::Real_timer Timer;
|
||||
|
||||
typedef CGAL::Exact_predicates_inexact_constructions_kernel Kernel;
|
||||
|
||||
typedef Kernel::FT Scalar;
|
||||
typedef Kernel::Point_2 Point;
|
||||
|
||||
typedef std::vector<Scalar> Coordinate_vector;
|
||||
typedef std::vector<Point> Point_vector;
|
||||
|
||||
typedef Coordinate_vector::iterator Overwrite_iterator;
|
||||
|
||||
typedef CGAL::Barycentric_coordinates::Mean_value_2<Kernel> Mean_value;
|
||||
typedef CGAL::Barycentric_coordinates::Generalized_barycentric_coordinates_2<Mean_value, Kernel> Mean_value_coordinates;
|
||||
|
||||
using std::cout; using std::endl; using std::string;
|
||||
|
||||
int main()
|
||||
{
|
||||
const int number_of_x_coordinates = 100000;
|
||||
const int number_of_y_coordinates = 1000;
|
||||
const int number_of_runs = 1;
|
||||
|
||||
const Scalar zero = Scalar(0);
|
||||
const Scalar one = Scalar(1);
|
||||
const Scalar x_step = one / Scalar(number_of_x_coordinates);
|
||||
const Scalar y_step = one / Scalar(number_of_y_coordinates);
|
||||
|
||||
Point_vector vertices(34);
|
||||
|
||||
vertices[0] = Point(zero, zero - y_step); vertices[1] = Point(one, zero - y_step);
|
||||
vertices[2] = Point(Scalar(3) / Scalar(2), Scalar(-1) / Scalar(2)); vertices[3] = Point(2, Scalar(-1) / Scalar(2) );
|
||||
vertices[4] = Point(Scalar(5) / Scalar(2), 0); vertices[5] = Point(2, Scalar(1) / Scalar(2) );
|
||||
vertices[6] = Point(Scalar(5) / Scalar(2), 1); vertices[7] = Point(3, Scalar(3) / Scalar(4) );
|
||||
vertices[8] = Point(3, Scalar(5) / Scalar(4)); vertices[9] = Point(Scalar(5) / Scalar(2), Scalar(7) / Scalar(4));
|
||||
vertices[10] = Point(3, Scalar(5) / Scalar(2)); vertices[11] = Point(Scalar(5) / Scalar(2), Scalar(5) / Scalar(2));
|
||||
vertices[12] = Point(Scalar(9) / Scalar(4), 2); vertices[13] = Point(Scalar(7) / Scalar(4), 2);
|
||||
vertices[14] = Point(2, Scalar(5) / Scalar(2)); vertices[15] = Point(Scalar(3) / Scalar(2), Scalar(5) / Scalar(2));
|
||||
vertices[16] = Point(Scalar(5) / Scalar(4), 2); vertices[17] = Point(Scalar(3) / Scalar(4), 2);
|
||||
vertices[18] = Point(1, Scalar(5) / Scalar(2)); vertices[19] = Point(Scalar(1) / Scalar(2), Scalar(5) / Scalar(2));
|
||||
vertices[20] = Point(Scalar(1) / Scalar(4), 2); vertices[21] = Point(Scalar(-1) / Scalar(4), 2);
|
||||
vertices[22] = Point(zero, Scalar(5) / Scalar(2)); vertices[23] = Point(Scalar(-1) / Scalar(2), Scalar(5) / Scalar(2));
|
||||
vertices[24] = Point(Scalar(-3) / Scalar(4), 2); vertices[25] = Point(Scalar(-1) / Scalar(2), Scalar(3) / Scalar(2));
|
||||
vertices[26] = Point(Scalar(-5) / Scalar(4), Scalar(3) / Scalar(2)); vertices[27] = Point(Scalar(-1) / Scalar(2), Scalar(3) / Scalar(4));
|
||||
vertices[28] = Point(-one, Scalar(1) / Scalar(2)); vertices[29] = Point(-one, zero);
|
||||
vertices[30] = Point(Scalar(-3) / Scalar(2), zero); vertices[31] = Point(Scalar(-3) / Scalar(2), Scalar(-1) / Scalar(2));
|
||||
vertices[32] = Point(Scalar(-1) / Scalar(2), Scalar(-1) / Scalar(2)); vertices[33] = Point(Scalar(-1) / Scalar(2), zero - y_step);
|
||||
|
||||
Mean_value_coordinates mean_value_coordinates(vertices.begin(), vertices.end());
|
||||
|
||||
Coordinate_vector coordinates(34);
|
||||
Overwrite_iterator it = coordinates.begin();
|
||||
|
||||
Timer time_to_compute;
|
||||
|
||||
double time = 0.0;
|
||||
for(int i = 0; i < number_of_runs; ++i) {
|
||||
|
||||
time_to_compute.start();
|
||||
for(Scalar x = zero; x <= one; x += x_step) {
|
||||
for(Scalar y = zero; y <= one; y += y_step)
|
||||
mean_value_coordinates(Point(x, y), it, CGAL::Barycentric_coordinates::ON_BOUNDED_SIDE);
|
||||
}
|
||||
time_to_compute.stop();
|
||||
|
||||
time += time_to_compute.time();
|
||||
|
||||
time_to_compute.reset();
|
||||
}
|
||||
const double mean_time = time / number_of_runs;
|
||||
|
||||
cout.precision(10);
|
||||
cout << endl << "CPU time to compute Mean Value coordinates (34 vertices) = " << mean_time << " seconds." << endl << endl;
|
||||
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
|
|
@ -1,76 +0,0 @@
|
|||
// Author: Dmitry Anisimov.
|
||||
// We test speed of mean value coordinates on a set of automatically generated
|
||||
// points inside a convex polygon with 16 vertices. We use inexact kernel.
|
||||
|
||||
#include <CGAL/Real_timer.h>
|
||||
#include <CGAL/Exact_predicates_inexact_constructions_kernel.h>
|
||||
#include <CGAL/Barycentric_coordinates_2/Mean_value_2.h>
|
||||
#include <CGAL/Barycentric_coordinates_2/Generalized_barycentric_coordinates_2.h>
|
||||
|
||||
typedef CGAL::Real_timer Timer;
|
||||
|
||||
typedef CGAL::Exact_predicates_inexact_constructions_kernel Kernel;
|
||||
|
||||
typedef Kernel::FT Scalar;
|
||||
typedef Kernel::Point_2 Point;
|
||||
|
||||
typedef std::vector<Scalar> Coordinate_vector;
|
||||
typedef std::vector<Point> Point_vector;
|
||||
|
||||
typedef Coordinate_vector::iterator Overwrite_iterator;
|
||||
|
||||
typedef CGAL::Barycentric_coordinates::Mean_value_2<Kernel> Mean_value;
|
||||
typedef CGAL::Barycentric_coordinates::Generalized_barycentric_coordinates_2<Mean_value, Kernel> Mean_value_coordinates;
|
||||
|
||||
using std::cout; using std::endl; using std::string;
|
||||
|
||||
int main()
|
||||
{
|
||||
const int number_of_x_coordinates = 100000;
|
||||
const int number_of_y_coordinates = 1000;
|
||||
const int number_of_runs = 1;
|
||||
|
||||
const Scalar zero = Scalar(0);
|
||||
const Scalar one = Scalar(1);
|
||||
const Scalar x_step = one / Scalar(number_of_x_coordinates);
|
||||
const Scalar y_step = one / Scalar(number_of_y_coordinates);
|
||||
|
||||
Point_vector vertices(16);
|
||||
|
||||
vertices[0] = Point(zero, zero - y_step); vertices[1] = Point(one, zero - y_step);
|
||||
vertices[2] = Point(Scalar(3) / Scalar(2), Scalar(1) / Scalar(4)); vertices[3] = Point(2, Scalar(3) / Scalar(4) );
|
||||
vertices[4] = Point(Scalar(9) / Scalar(4), Scalar(5) / Scalar(4)); vertices[5] = Point(Scalar(9) / Scalar(4), Scalar(9) / Scalar(4));
|
||||
vertices[6] = Point(2, Scalar(11) / Scalar(4) ); vertices[7] = Point(Scalar(3) / Scalar(2), Scalar(13) / Scalar(4));
|
||||
vertices[8] = Point(1, Scalar(7) / Scalar(2) ); vertices[9] = Point(0, Scalar(7) / Scalar(2) );
|
||||
vertices[10] = Point(Scalar(-1) / Scalar(2), Scalar(13) / Scalar(4)); vertices[11] = Point(-1, Scalar(11) / Scalar(4) );
|
||||
vertices[12] = Point(Scalar(-5) / Scalar(4), Scalar(9) / Scalar(4)); vertices[13] = Point(Scalar(-5) / Scalar(4), Scalar(5) / Scalar(4));
|
||||
vertices[14] = Point(-1, Scalar(3) / Scalar(4) ); vertices[15] = Point(Scalar(-1) / Scalar(2), Scalar(1) / Scalar(4));
|
||||
|
||||
Mean_value_coordinates mean_value_coordinates(vertices.begin(), vertices.end());
|
||||
|
||||
Coordinate_vector coordinates(16);
|
||||
Overwrite_iterator it = coordinates.begin();
|
||||
|
||||
Timer time_to_compute;
|
||||
|
||||
double time = 0.0;
|
||||
for(int i = 0; i < number_of_runs; ++i) {
|
||||
|
||||
time_to_compute.start();
|
||||
for(Scalar x = zero; x <= one; x += x_step) {
|
||||
for(Scalar y = zero; y <= one; y += y_step)
|
||||
mean_value_coordinates(Point(x, y), it, CGAL::Barycentric_coordinates::ON_BOUNDED_SIDE);
|
||||
}
|
||||
time_to_compute.stop();
|
||||
|
||||
time += time_to_compute.time();
|
||||
|
||||
time_to_compute.reset();
|
||||
}
|
||||
const double mean_time = time / number_of_runs;
|
||||
|
||||
cout.precision(10);
|
||||
cout << endl << "CPU time to compute Mean Value coordinates (16 vertices) = " << mean_time << " seconds." << endl << endl;
|
||||
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
|
|
@ -1,70 +0,0 @@
|
|||
// Author: Dmitry Anisimov.
|
||||
// We test speed of mean value weights on a set of automatically generated
|
||||
// points inside a unit square. We use inexact kernel.
|
||||
|
||||
#include <CGAL/Real_timer.h>
|
||||
#include <CGAL/Exact_predicates_inexact_constructions_kernel.h>
|
||||
#include <CGAL/Barycentric_coordinates_2/Mean_value_2.h>
|
||||
#include <CGAL/Barycentric_coordinates_2/Generalized_barycentric_coordinates_2.h>
|
||||
|
||||
typedef CGAL::Real_timer Timer;
|
||||
|
||||
typedef CGAL::Exact_predicates_inexact_constructions_kernel Kernel;
|
||||
|
||||
typedef Kernel::FT Scalar;
|
||||
typedef Kernel::Point_2 Point;
|
||||
|
||||
typedef std::vector<Scalar> Weight_vector;
|
||||
typedef std::vector<Point> Point_vector;
|
||||
|
||||
typedef Weight_vector::iterator Overwrite_iterator;
|
||||
|
||||
typedef CGAL::Barycentric_coordinates::Mean_value_2<Kernel> Mean_value;
|
||||
typedef CGAL::Barycentric_coordinates::Generalized_barycentric_coordinates_2<Mean_value, Kernel> Mean_value_coordinates;
|
||||
|
||||
using std::cout; using std::endl; using std::string;
|
||||
|
||||
int main()
|
||||
{
|
||||
const int number_of_x_coordinates = 1000000;
|
||||
const int number_of_y_coordinates = 1000;
|
||||
const int number_of_runs = 1;
|
||||
|
||||
const Scalar zero = Scalar(0);
|
||||
const Scalar one = Scalar(1);
|
||||
const Scalar x_step = one / Scalar(number_of_x_coordinates);
|
||||
const Scalar y_step = one / Scalar(number_of_y_coordinates);
|
||||
|
||||
Point_vector vertices(4);
|
||||
|
||||
vertices[0] = Point(zero - x_step, zero - y_step); vertices[1] = Point(one + x_step, zero - y_step);
|
||||
vertices[2] = Point(one + x_step, one + y_step); vertices[3] = Point(zero - x_step, one + y_step);
|
||||
|
||||
Mean_value_coordinates mean_value_coordinates(vertices.begin(), vertices.end());
|
||||
|
||||
Weight_vector weights(4);
|
||||
Overwrite_iterator it = weights.begin();
|
||||
|
||||
Timer time_to_compute;
|
||||
|
||||
double time = 0.0;
|
||||
for(int i = 0; i < number_of_runs; ++i) {
|
||||
|
||||
time_to_compute.start();
|
||||
for(Scalar x = zero; x <= one; x += x_step) {
|
||||
for(Scalar y = zero; y <= one; y += y_step)
|
||||
mean_value_coordinates.compute_weights(Point(x, y), it);
|
||||
}
|
||||
time_to_compute.stop();
|
||||
|
||||
time += time_to_compute.time();
|
||||
|
||||
time_to_compute.reset();
|
||||
}
|
||||
const double mean_time = time / number_of_runs;
|
||||
|
||||
cout.precision(10);
|
||||
cout << endl << "CPU time to compute Mean Value weights (4 vertices) = " << mean_time << " seconds." << endl << endl;
|
||||
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
|
|
@ -1,85 +0,0 @@
|
|||
// Author: Dmitry Anisimov.
|
||||
// We test speed of mean value weights on a set of automatically generated
|
||||
// points inside a concave polygon with 34 vertices. We use inexact kernel.
|
||||
|
||||
#include <CGAL/Real_timer.h>
|
||||
#include <CGAL/Exact_predicates_inexact_constructions_kernel.h>
|
||||
#include <CGAL/Barycentric_coordinates_2/Mean_value_2.h>
|
||||
#include <CGAL/Barycentric_coordinates_2/Generalized_barycentric_coordinates_2.h>
|
||||
|
||||
typedef CGAL::Real_timer Timer;
|
||||
|
||||
typedef CGAL::Exact_predicates_inexact_constructions_kernel Kernel;
|
||||
|
||||
typedef Kernel::FT Scalar;
|
||||
typedef Kernel::Point_2 Point;
|
||||
|
||||
typedef std::vector<Scalar> Weight_vector;
|
||||
typedef std::vector<Point> Point_vector;
|
||||
|
||||
typedef Weight_vector::iterator Overwrite_iterator;
|
||||
|
||||
typedef CGAL::Barycentric_coordinates::Mean_value_2<Kernel> Mean_value;
|
||||
typedef CGAL::Barycentric_coordinates::Generalized_barycentric_coordinates_2<Mean_value, Kernel> Mean_value_coordinates;
|
||||
|
||||
using std::cout; using std::endl; using std::string;
|
||||
|
||||
int main()
|
||||
{
|
||||
const int number_of_x_coordinates = 100000;
|
||||
const int number_of_y_coordinates = 1000;
|
||||
const int number_of_runs = 1;
|
||||
|
||||
const Scalar zero = Scalar(0);
|
||||
const Scalar one = Scalar(1);
|
||||
const Scalar x_step = one / Scalar(number_of_x_coordinates);
|
||||
const Scalar y_step = one / Scalar(number_of_y_coordinates);
|
||||
|
||||
Point_vector vertices(34);
|
||||
|
||||
vertices[0] = Point(zero, zero - y_step); vertices[1] = Point(one, zero - y_step);
|
||||
vertices[2] = Point(Scalar(3) / Scalar(2), Scalar(-1) / Scalar(2)); vertices[3] = Point(2, Scalar(-1) / Scalar(2));
|
||||
vertices[4] = Point(Scalar(5) / Scalar(2), 0); vertices[5] = Point(2, Scalar(1) / Scalar(2));
|
||||
vertices[6] = Point(Scalar(5) / Scalar(2), 1); vertices[7] = Point(3, Scalar(3) / Scalar(4));
|
||||
vertices[8] = Point(3, Scalar(5) / Scalar(4)); vertices[9] = Point(Scalar(5) / Scalar(2), Scalar(7) / Scalar(4));
|
||||
vertices[10] = Point(3, Scalar(5) / Scalar(2)); vertices[11] = Point(Scalar(5) / Scalar(2), Scalar(5) / Scalar(2));
|
||||
vertices[12] = Point(Scalar(9) / Scalar(4), 2); vertices[13] = Point(Scalar(7) / Scalar(4), 2);
|
||||
vertices[14] = Point(2, Scalar(5) / Scalar(2)); vertices[15] = Point(Scalar(3) / Scalar(2), Scalar(5) / Scalar(2));
|
||||
vertices[16] = Point(Scalar(5) / Scalar(4), 2); vertices[17] = Point(Scalar(3) / Scalar(4), 2);
|
||||
vertices[18] = Point(1, Scalar(5) / Scalar(2)); vertices[19] = Point(Scalar(1) / Scalar(2), Scalar(5) / Scalar(2));
|
||||
vertices[20] = Point(Scalar(1) / Scalar(4), 2); vertices[21] = Point(Scalar(-1) / Scalar(4), 2);
|
||||
vertices[22] = Point(zero, Scalar(5) / Scalar(2)); vertices[23] = Point(Scalar(-1) / Scalar(2), Scalar(5) / Scalar(2));
|
||||
vertices[24] = Point(Scalar(-3) / Scalar(4), 2); vertices[25] = Point(Scalar(-1) / Scalar(2), Scalar(3) / Scalar(2));
|
||||
vertices[26] = Point(Scalar(-5) / Scalar(4), Scalar(3) / Scalar(2)); vertices[27] = Point(Scalar(-1) / Scalar(2), Scalar(3) / Scalar(4));
|
||||
vertices[28] = Point(-one, Scalar(1) / Scalar(2)); vertices[29] = Point(-one, zero);
|
||||
vertices[30] = Point(Scalar(-3) / Scalar(2), zero); vertices[31] = Point(Scalar(-3) / Scalar(2), Scalar(-1) / Scalar(2));
|
||||
vertices[32] = Point(Scalar(-1) / Scalar(2), Scalar(-1) / Scalar(2)); vertices[33] = Point(Scalar(-1) / Scalar(2), zero - y_step);
|
||||
|
||||
Mean_value_coordinates mean_value_coordinates(vertices.begin(), vertices.end());
|
||||
|
||||
Weight_vector weights(34);
|
||||
Overwrite_iterator it = weights.begin();
|
||||
|
||||
Timer time_to_compute;
|
||||
|
||||
double time = 0.0;
|
||||
for(int i = 0; i < number_of_runs; ++i) {
|
||||
|
||||
time_to_compute.start();
|
||||
for(Scalar x = zero; x <= one; x += x_step) {
|
||||
for(Scalar y = zero; y <= one; y += y_step)
|
||||
mean_value_coordinates.compute_weights(Point(x, y), it);
|
||||
}
|
||||
time_to_compute.stop();
|
||||
|
||||
time += time_to_compute.time();
|
||||
|
||||
time_to_compute.reset();
|
||||
}
|
||||
const double mean_time = time / number_of_runs;
|
||||
|
||||
cout.precision(10);
|
||||
cout << endl << "CPU time to compute Mean Value weights (34 vertices) = " << mean_time << " seconds." << endl << endl;
|
||||
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
|
|
@ -1,76 +0,0 @@
|
|||
// Author: Dmitry Anisimov.
|
||||
// We test speed of mean value weights on a set of automatically generated
|
||||
// points inside a convex polygon with 16 vertices. We use inexact kernel.
|
||||
|
||||
#include <CGAL/Real_timer.h>
|
||||
#include <CGAL/Exact_predicates_inexact_constructions_kernel.h>
|
||||
#include <CGAL/Barycentric_coordinates_2/Mean_value_2.h>
|
||||
#include <CGAL/Barycentric_coordinates_2/Generalized_barycentric_coordinates_2.h>
|
||||
|
||||
typedef CGAL::Real_timer Timer;
|
||||
|
||||
typedef CGAL::Exact_predicates_inexact_constructions_kernel Kernel;
|
||||
|
||||
typedef Kernel::FT Scalar;
|
||||
typedef Kernel::Point_2 Point;
|
||||
|
||||
typedef std::vector<Scalar> Weight_vector;
|
||||
typedef std::vector<Point> Point_vector;
|
||||
|
||||
typedef Weight_vector::iterator Overwrite_iterator;
|
||||
|
||||
typedef CGAL::Barycentric_coordinates::Mean_value_2<Kernel> Mean_value;
|
||||
typedef CGAL::Barycentric_coordinates::Generalized_barycentric_coordinates_2<Mean_value, Kernel> Mean_value_coordinates;
|
||||
|
||||
using std::cout; using std::endl; using std::string;
|
||||
|
||||
int main()
|
||||
{
|
||||
const int number_of_x_coordinates = 100000;
|
||||
const int number_of_y_coordinates = 1000;
|
||||
const int number_of_runs = 1;
|
||||
|
||||
const Scalar zero = Scalar(0);
|
||||
const Scalar one = Scalar(1);
|
||||
const Scalar x_step = one / Scalar(number_of_x_coordinates);
|
||||
const Scalar y_step = one / Scalar(number_of_y_coordinates);
|
||||
|
||||
Point_vector vertices(16);
|
||||
|
||||
vertices[0] = Point(zero, zero - y_step); vertices[1] = Point(one, zero - y_step);
|
||||
vertices[2] = Point(Scalar(3) / Scalar(2), Scalar(1) / Scalar(4)); vertices[3] = Point(2, Scalar(3) / Scalar(4));
|
||||
vertices[4] = Point(Scalar(9) / Scalar(4), Scalar(5) / Scalar(4)); vertices[5] = Point(Scalar(9) / Scalar(4), Scalar(9) / Scalar(4));
|
||||
vertices[6] = Point(2, Scalar(11) / Scalar(4) ); vertices[7] = Point(Scalar(3) / Scalar(2), Scalar(13) / Scalar(4));
|
||||
vertices[8] = Point(1, Scalar(7) / Scalar(2) ); vertices[9] = Point(0, Scalar(7) / Scalar(2) );
|
||||
vertices[10] = Point(Scalar(-1) / Scalar(2), Scalar(13) / Scalar(4)); vertices[11] = Point(-1, Scalar(11) / Scalar(4) );
|
||||
vertices[12] = Point(Scalar(-5) / Scalar(4), Scalar(9) / Scalar(4)); vertices[13] = Point(Scalar(-5) / Scalar(4), Scalar(5) / Scalar(4));
|
||||
vertices[14] = Point(-1, Scalar(3) / Scalar(4) ); vertices[15] = Point(Scalar(-1) / Scalar(2), Scalar(1) / Scalar(4));
|
||||
|
||||
Mean_value_coordinates mean_value_coordinates(vertices.begin(), vertices.end());
|
||||
|
||||
Weight_vector weights(16);
|
||||
Overwrite_iterator it = weights.begin();
|
||||
|
||||
Timer time_to_compute;
|
||||
|
||||
double time = 0.0;
|
||||
for(int i = 0; i < number_of_runs; ++i) {
|
||||
|
||||
time_to_compute.start();
|
||||
for(Scalar x = zero; x <= one; x += x_step) {
|
||||
for(Scalar y = zero; y <= one; y += y_step)
|
||||
mean_value_coordinates.compute_weights(Point(x, y), it);
|
||||
}
|
||||
time_to_compute.stop();
|
||||
|
||||
time += time_to_compute.time();
|
||||
|
||||
time_to_compute.reset();
|
||||
}
|
||||
const double mean_time = time / number_of_runs;
|
||||
|
||||
cout.precision(10);
|
||||
cout << endl << "CPU time to compute Mean Value weights (16 vertices) = " << mean_time << " seconds." << endl << endl;
|
||||
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
|
|
@ -1,63 +0,0 @@
|
|||
// Author: Dmitry Anisimov.
|
||||
// We test speed of segment coordinates on a set of automatically generated
|
||||
// points inside a unit segment. We use inexact kernel.
|
||||
|
||||
#include <CGAL/Real_timer.h>
|
||||
#include <CGAL/Exact_predicates_inexact_constructions_kernel.h>
|
||||
#include <CGAL/Barycentric_coordinates_2/Segment_coordinates_2.h>
|
||||
|
||||
typedef CGAL::Real_timer Timer;
|
||||
|
||||
typedef CGAL::Exact_predicates_inexact_constructions_kernel Kernel;
|
||||
|
||||
typedef Kernel::FT Scalar;
|
||||
typedef Kernel::Point_2 Point;
|
||||
|
||||
typedef std::vector<Scalar> Coordinate_vector;
|
||||
typedef Coordinate_vector::iterator Overwrite_iterator;
|
||||
|
||||
typedef CGAL::Barycentric_coordinates::Segment_coordinates_2<Kernel> Segment_coordinates;
|
||||
|
||||
using std::cout; using std::endl; using std::string;
|
||||
|
||||
int main()
|
||||
{
|
||||
const int number_of_iterations = 100000;
|
||||
const int number_of_points = 10000;
|
||||
const int number_of_runs = 1;
|
||||
|
||||
const Scalar zero = Scalar(0);
|
||||
const Scalar one = Scalar(1);
|
||||
const Scalar step = one / Scalar(number_of_points);
|
||||
|
||||
const Point first_vertex = Point(zero - step, zero);
|
||||
const Point second_vertex = Point(one + step, zero);
|
||||
|
||||
Segment_coordinates segment_coordinates(first_vertex, second_vertex);
|
||||
|
||||
Coordinate_vector coordinates(2);
|
||||
Overwrite_iterator it = coordinates.begin();
|
||||
|
||||
Timer time_to_compute;
|
||||
|
||||
double time = 0.0;
|
||||
for(int i = 0; i < number_of_runs; ++i) {
|
||||
|
||||
time_to_compute.start();
|
||||
for(int j = 0; j < number_of_iterations; ++j) {
|
||||
for(Scalar x = zero; x <= one; x += step)
|
||||
segment_coordinates(Point(x, zero), it);
|
||||
}
|
||||
time_to_compute.stop();
|
||||
|
||||
time += time_to_compute.time();
|
||||
|
||||
time_to_compute.reset();
|
||||
}
|
||||
const double mean_time = time / number_of_runs;
|
||||
|
||||
cout.precision(10);
|
||||
cout << endl << "CPU time to compute Segment coordinates = " << mean_time << " seconds." << endl << endl;
|
||||
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
|
|
@ -1,66 +0,0 @@
|
|||
// Author: Dmitry Anisimov.
|
||||
// We test speed of triangle coordinates on a set of automatically generated
|
||||
// points inside a right triangle. We use inexact kernel.
|
||||
|
||||
#include <CGAL/Real_timer.h>
|
||||
#include <CGAL/Exact_predicates_inexact_constructions_kernel.h>
|
||||
#include <CGAL/Barycentric_coordinates_2/Triangle_coordinates_2.h>
|
||||
|
||||
typedef CGAL::Real_timer Timer;
|
||||
|
||||
typedef CGAL::Exact_predicates_inexact_constructions_kernel Kernel;
|
||||
|
||||
typedef Kernel::FT Scalar;
|
||||
typedef Kernel::Point_2 Point;
|
||||
|
||||
typedef std::vector<Scalar> Coordinate_vector;
|
||||
typedef Coordinate_vector::iterator Overwrite_iterator;
|
||||
|
||||
typedef CGAL::Barycentric_coordinates::Triangle_coordinates_2<Kernel> Triangle_coordinates;
|
||||
|
||||
using std::cout; using std::endl; using std::string;
|
||||
|
||||
int main()
|
||||
{
|
||||
const int number_of_x_coordinates = 100000;
|
||||
const int number_of_y_coordinates = 10000;
|
||||
const int number_of_runs = 1;
|
||||
|
||||
const Scalar zero = Scalar(0);
|
||||
const Scalar one = Scalar(1);
|
||||
const Scalar two = Scalar(2);
|
||||
const Scalar x_step = one / Scalar(number_of_x_coordinates);
|
||||
const Scalar y_step = one / Scalar(number_of_y_coordinates);
|
||||
|
||||
const Point first_vertex = Point(zero - x_step, zero - x_step);
|
||||
const Point second_vertex = Point(two + y_step, zero - x_step);
|
||||
const Point third_vertex = Point(zero - x_step, two + y_step );
|
||||
|
||||
Triangle_coordinates triangle_coordinates(first_vertex, second_vertex, third_vertex);
|
||||
|
||||
Coordinate_vector coordinates(3);
|
||||
Overwrite_iterator it = coordinates.begin();
|
||||
|
||||
Timer time_to_compute;
|
||||
|
||||
double time = 0.0;
|
||||
for(int i = 0; i < number_of_runs; ++i) {
|
||||
|
||||
time_to_compute.start();
|
||||
for(Scalar x = zero; x <= one; x += x_step) {
|
||||
for(Scalar y = zero; y <= one; y += y_step)
|
||||
triangle_coordinates(Point(x, y), it);
|
||||
}
|
||||
time_to_compute.stop();
|
||||
|
||||
time += time_to_compute.time();
|
||||
|
||||
time_to_compute.reset();
|
||||
}
|
||||
const double mean_time = time / number_of_runs;
|
||||
|
||||
cout.precision(10);
|
||||
cout << endl << "CPU time to compute Triangle coordinates = " << mean_time << " seconds." << endl << endl;
|
||||
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
|
|
@ -1,70 +0,0 @@
|
|||
// Author: Dmitry Anisimov.
|
||||
// We test speed of Wachspress coordinates on a set of automatically generated
|
||||
// points inside a unit square. We use inexact kernel.
|
||||
|
||||
#include <CGAL/Real_timer.h>
|
||||
#include <CGAL/Exact_predicates_inexact_constructions_kernel.h>
|
||||
#include <CGAL/Barycentric_coordinates_2/Wachspress_2.h>
|
||||
#include <CGAL/Barycentric_coordinates_2/Generalized_barycentric_coordinates_2.h>
|
||||
|
||||
typedef CGAL::Real_timer Timer;
|
||||
|
||||
typedef CGAL::Exact_predicates_inexact_constructions_kernel Kernel;
|
||||
|
||||
typedef Kernel::FT Scalar;
|
||||
typedef Kernel::Point_2 Point;
|
||||
|
||||
typedef std::vector<Scalar> Coordinate_vector;
|
||||
typedef std::vector<Point> Point_vector;
|
||||
|
||||
typedef Coordinate_vector::iterator Overwrite_iterator;
|
||||
|
||||
typedef CGAL::Barycentric_coordinates::Wachspress_2<Kernel> Wachspress;
|
||||
typedef CGAL::Barycentric_coordinates::Generalized_barycentric_coordinates_2<Wachspress, Kernel> Wachspress_coordinates;
|
||||
|
||||
using std::cout; using std::endl; using std::string;
|
||||
|
||||
int main()
|
||||
{
|
||||
const int number_of_x_coordinates = 1000000;
|
||||
const int number_of_y_coordinates = 1000;
|
||||
const int number_of_runs = 1;
|
||||
|
||||
const Scalar zero = Scalar(0);
|
||||
const Scalar one = Scalar(1);
|
||||
const Scalar x_step = one / Scalar(number_of_x_coordinates);
|
||||
const Scalar y_step = one / Scalar(number_of_y_coordinates);
|
||||
|
||||
Point_vector vertices(4);
|
||||
|
||||
vertices[0] = Point(zero - x_step, zero - y_step); vertices[1] = Point(one + x_step, zero - y_step);
|
||||
vertices[2] = Point(one + x_step, one + y_step); vertices[3] = Point(zero - x_step, one + y_step);
|
||||
|
||||
Wachspress_coordinates wachspress_coordinates(vertices.begin(), vertices.end());
|
||||
|
||||
Coordinate_vector coordinates(4);
|
||||
Overwrite_iterator it = coordinates.begin();
|
||||
|
||||
Timer time_to_compute;
|
||||
|
||||
double time = 0.0;
|
||||
for(int i = 0; i < number_of_runs; ++i) {
|
||||
|
||||
time_to_compute.start();
|
||||
for(Scalar x = zero; x <= one; x += x_step) {
|
||||
for(Scalar y = zero; y <= one; y += y_step)
|
||||
wachspress_coordinates(Point(x, y), it, CGAL::Barycentric_coordinates::ON_BOUNDED_SIDE);
|
||||
}
|
||||
time_to_compute.stop();
|
||||
|
||||
time += time_to_compute.time();
|
||||
|
||||
time_to_compute.reset();
|
||||
}
|
||||
const double mean_time = time / number_of_runs;
|
||||
|
||||
cout.precision(10);
|
||||
cout << endl << "CPU time to compute Wachspress coordinates (4 vertices) = " << mean_time << " seconds." << endl << endl;
|
||||
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
|
|
@ -1,83 +0,0 @@
|
|||
// Author: Dmitry Anisimov.
|
||||
// We test speed of Wachspress coordinates on a set of automatically generated
|
||||
// points inside a regular polygon with 100 vertices. We use inexact kernel.
|
||||
|
||||
#include <CGAL/number_type_config.h>
|
||||
#include <CGAL/Real_timer.h>
|
||||
#include <CGAL/Exact_predicates_inexact_constructions_kernel.h>
|
||||
#include <CGAL/Barycentric_coordinates_2/Wachspress_2.h>
|
||||
#include <CGAL/Barycentric_coordinates_2/Generalized_barycentric_coordinates_2.h>
|
||||
|
||||
typedef CGAL::Real_timer Timer;
|
||||
|
||||
typedef CGAL::Exact_predicates_inexact_constructions_kernel Kernel;
|
||||
|
||||
typedef Kernel::FT Scalar;
|
||||
typedef Kernel::Point_2 Point;
|
||||
|
||||
typedef std::vector<Scalar> Scalar_vector;
|
||||
typedef std::vector<Point> Point_vector;
|
||||
|
||||
typedef Scalar_vector::iterator Overwrite_iterator;
|
||||
|
||||
typedef CGAL::Barycentric_coordinates::Wachspress_2<Kernel> Wachspress;
|
||||
typedef CGAL::Barycentric_coordinates::Generalized_barycentric_coordinates_2<Wachspress, Kernel> Wachspress_coordinates;
|
||||
|
||||
using std::cout; using std::endl; using std::string;
|
||||
|
||||
void generate_regular_polygon(const int number_of_vertices, const double polygon_radius, Point_vector &vertices)
|
||||
{
|
||||
const int n = number_of_vertices;
|
||||
const double r = polygon_radius;
|
||||
|
||||
vertices.resize(n);
|
||||
|
||||
for(int i = 0; i < n; ++i)
|
||||
vertices[i] = Point(Scalar(r*sin((CGAL_PI / n) + ((i * 2.0 * CGAL_PI) / n))), Scalar(-r*cos((CGAL_PI / n) + ((i * 2.0 * CGAL_PI) / n))));
|
||||
}
|
||||
|
||||
int main()
|
||||
{
|
||||
const int number_of_x_coordinates = 1000;
|
||||
const int number_of_y_coordinates = 1000;
|
||||
const int number_of_runs = 1;
|
||||
|
||||
const Scalar one = Scalar(1);
|
||||
const Scalar x_step = one / Scalar(number_of_x_coordinates);
|
||||
const Scalar y_step = one / Scalar(number_of_y_coordinates);
|
||||
|
||||
Point_vector vertices;
|
||||
|
||||
const int number_of_vertices = 100;
|
||||
const double polygon_radius = 2;
|
||||
|
||||
generate_regular_polygon(number_of_vertices, polygon_radius, vertices);
|
||||
|
||||
Wachspress_coordinates wachspress_coordinates(vertices.begin(), vertices.end());
|
||||
|
||||
Scalar_vector coordinates(number_of_vertices);
|
||||
Overwrite_iterator it = coordinates.begin();
|
||||
|
||||
Timer time_to_compute;
|
||||
|
||||
double time = 0.0;
|
||||
for(int i = 0; i < number_of_runs; ++i) {
|
||||
|
||||
time_to_compute.start();
|
||||
for(Scalar x = -one; x <= one; x += x_step) {
|
||||
for(Scalar y = -one; y <= one; y += y_step)
|
||||
wachspress_coordinates(Point(x, y), it, CGAL::Barycentric_coordinates::ON_BOUNDED_SIDE);
|
||||
}
|
||||
time_to_compute.stop();
|
||||
|
||||
time += time_to_compute.time();
|
||||
|
||||
time_to_compute.reset();
|
||||
}
|
||||
const double mean_time = time / number_of_runs;
|
||||
|
||||
cout.precision(10);
|
||||
cout << endl << "CPU time to compute Wachspress coordinates (100 vertices) = " << mean_time << " seconds." << endl << endl;
|
||||
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
|
|
@ -1,76 +0,0 @@
|
|||
// Author: Dmitry Anisimov.
|
||||
// We test speed of Wachspress coordinates on a set of automatically generated
|
||||
// points inside a convex polygon with 16 vertices. We use inexact kernel.
|
||||
|
||||
#include <CGAL/Real_timer.h>
|
||||
#include <CGAL/Exact_predicates_inexact_constructions_kernel.h>
|
||||
#include <CGAL/Barycentric_coordinates_2/Wachspress_2.h>
|
||||
#include <CGAL/Barycentric_coordinates_2/Generalized_barycentric_coordinates_2.h>
|
||||
|
||||
typedef CGAL::Real_timer Timer;
|
||||
|
||||
typedef CGAL::Exact_predicates_inexact_constructions_kernel Kernel;
|
||||
|
||||
typedef Kernel::FT Scalar;
|
||||
typedef Kernel::Point_2 Point;
|
||||
|
||||
typedef std::vector<Scalar> Coordinate_vector;
|
||||
typedef std::vector<Point> Point_vector;
|
||||
|
||||
typedef Coordinate_vector::iterator Overwrite_iterator;
|
||||
|
||||
typedef CGAL::Barycentric_coordinates::Wachspress_2<Kernel> Wachspress;
|
||||
typedef CGAL::Barycentric_coordinates::Generalized_barycentric_coordinates_2<Wachspress, Kernel> Wachspress_coordinates;
|
||||
|
||||
using std::cout; using std::endl; using std::string;
|
||||
|
||||
int main()
|
||||
{
|
||||
const int number_of_x_coordinates = 100000;
|
||||
const int number_of_y_coordinates = 1000;
|
||||
const int number_of_runs = 1;
|
||||
|
||||
const Scalar zero = Scalar(0);
|
||||
const Scalar one = Scalar(1);
|
||||
const Scalar x_step = one / Scalar(number_of_x_coordinates);
|
||||
const Scalar y_step = one / Scalar(number_of_y_coordinates);
|
||||
|
||||
Point_vector vertices(16);
|
||||
|
||||
vertices[0] = Point(zero, zero - y_step); vertices[1] = Point(one, zero - y_step);
|
||||
vertices[2] = Point(Scalar(3) / Scalar(2), Scalar(1) / Scalar(4)); vertices[3] = Point(2, Scalar(3) / Scalar(4) );
|
||||
vertices[4] = Point(Scalar(9) / Scalar(4), Scalar(5) / Scalar(4)); vertices[5] = Point(Scalar(9) / Scalar(4), Scalar(9) / Scalar(4));
|
||||
vertices[6] = Point(2, Scalar(11) / Scalar(4) ); vertices[7] = Point(Scalar(3) / Scalar(2), Scalar(13) / Scalar(4));
|
||||
vertices[8] = Point(1, Scalar(7) / Scalar(2) ); vertices[9] = Point(0, Scalar(7) / Scalar(2) );
|
||||
vertices[10] = Point(Scalar(-1) / Scalar(2), Scalar(13) / Scalar(4)); vertices[11] = Point(-1, Scalar(11) / Scalar(4) );
|
||||
vertices[12] = Point(Scalar(-5) / Scalar(4), Scalar(9) / Scalar(4)); vertices[13] = Point(Scalar(-5) / Scalar(4), Scalar(5) / Scalar(4));
|
||||
vertices[14] = Point(-1, Scalar(3) / Scalar(4) ); vertices[15] = Point(Scalar(-1) / Scalar(2), Scalar(1) / Scalar(4));
|
||||
|
||||
Wachspress_coordinates wachspress_coordinates(vertices.begin(), vertices.end());
|
||||
|
||||
Coordinate_vector coordinates(16);
|
||||
Overwrite_iterator it = coordinates.begin();
|
||||
|
||||
Timer time_to_compute;
|
||||
|
||||
double time = 0.0;
|
||||
for(int i = 0; i < number_of_runs; ++i) {
|
||||
|
||||
time_to_compute.start();
|
||||
for(Scalar x = zero; x <= one; x += x_step) {
|
||||
for(Scalar y = zero; y <= one; y += y_step)
|
||||
wachspress_coordinates(Point(x, y), it, CGAL::Barycentric_coordinates::ON_BOUNDED_SIDE);
|
||||
}
|
||||
time_to_compute.stop();
|
||||
|
||||
time += time_to_compute.time();
|
||||
|
||||
time_to_compute.reset();
|
||||
}
|
||||
const double mean_time = time / number_of_runs;
|
||||
|
||||
cout.precision(10);
|
||||
cout << endl << "CPU time to compute Wachspress coordinates (16 vertices) = " << mean_time << " seconds." << endl << endl;
|
||||
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
|
|
@ -1,70 +0,0 @@
|
|||
// Author: Dmitry Anisimov.
|
||||
// We test speed of Wachspress weights on a set of automatically generated
|
||||
// points inside a unit square. We use inexact kernel.
|
||||
|
||||
#include <CGAL/Real_timer.h>
|
||||
#include <CGAL/Exact_predicates_inexact_constructions_kernel.h>
|
||||
#include <CGAL/Barycentric_coordinates_2/Wachspress_2.h>
|
||||
#include <CGAL/Barycentric_coordinates_2/Generalized_barycentric_coordinates_2.h>
|
||||
|
||||
typedef CGAL::Real_timer Timer;
|
||||
|
||||
typedef CGAL::Exact_predicates_inexact_constructions_kernel Kernel;
|
||||
|
||||
typedef Kernel::FT Scalar;
|
||||
typedef Kernel::Point_2 Point;
|
||||
|
||||
typedef std::vector<Scalar> Weight_vector;
|
||||
typedef std::vector<Point> Point_vector;
|
||||
|
||||
typedef Weight_vector::iterator Overwrite_iterator;
|
||||
|
||||
typedef CGAL::Barycentric_coordinates::Wachspress_2<Kernel> Wachspress;
|
||||
typedef CGAL::Barycentric_coordinates::Generalized_barycentric_coordinates_2<Wachspress, Kernel> Wachspress_coordinates;
|
||||
|
||||
using std::cout; using std::endl; using std::string;
|
||||
|
||||
int main()
|
||||
{
|
||||
const int number_of_x_coordinates = 1000000;
|
||||
const int number_of_y_coordinates = 1000;
|
||||
const int number_of_runs = 1;
|
||||
|
||||
const Scalar zero = Scalar(0);
|
||||
const Scalar one = Scalar(1);
|
||||
const Scalar x_step = one / Scalar(number_of_x_coordinates);
|
||||
const Scalar y_step = one / Scalar(number_of_y_coordinates);
|
||||
|
||||
Point_vector vertices(4);
|
||||
|
||||
vertices[0] = Point(zero - x_step, zero - y_step); vertices[1] = Point(one + x_step, zero - y_step);
|
||||
vertices[2] = Point(one + x_step, one + y_step); vertices[3] = Point(zero - x_step, one + y_step);
|
||||
|
||||
Wachspress_coordinates wachspress_coordinates(vertices.begin(), vertices.end());
|
||||
|
||||
Weight_vector weights(4);
|
||||
Overwrite_iterator it = weights.begin();
|
||||
|
||||
Timer time_to_compute;
|
||||
|
||||
double time = 0.0;
|
||||
for(int i = 0; i < number_of_runs; ++i) {
|
||||
|
||||
time_to_compute.start();
|
||||
for(Scalar x = zero; x <= one; x += x_step) {
|
||||
for(Scalar y = zero; y <= one; y += y_step)
|
||||
wachspress_coordinates.compute_weights(Point(x, y), it);
|
||||
}
|
||||
time_to_compute.stop();
|
||||
|
||||
time += time_to_compute.time();
|
||||
|
||||
time_to_compute.reset();
|
||||
}
|
||||
const double mean_time = time / number_of_runs;
|
||||
|
||||
cout.precision(10);
|
||||
cout << endl << "CPU time to compute Wachspress weights (4 vertices) = " << mean_time << " seconds." << endl << endl;
|
||||
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
|
|
@ -1,76 +0,0 @@
|
|||
// Author: Dmitry Anisimov.
|
||||
// We test speed of Wachspress weights on a set of automatically generated
|
||||
// points inside a convex polygon with 16 vertices. We use inexact kernel.
|
||||
|
||||
#include <CGAL/Real_timer.h>
|
||||
#include <CGAL/Exact_predicates_inexact_constructions_kernel.h>
|
||||
#include <CGAL/Barycentric_coordinates_2/Wachspress_2.h>
|
||||
#include <CGAL/Barycentric_coordinates_2/Generalized_barycentric_coordinates_2.h>
|
||||
|
||||
typedef CGAL::Real_timer Timer;
|
||||
|
||||
typedef CGAL::Exact_predicates_inexact_constructions_kernel Kernel;
|
||||
|
||||
typedef Kernel::FT Scalar;
|
||||
typedef Kernel::Point_2 Point;
|
||||
|
||||
typedef std::vector<Scalar> Weight_vector;
|
||||
typedef std::vector<Point> Point_vector;
|
||||
|
||||
typedef Weight_vector::iterator Overwrite_iterator;
|
||||
|
||||
typedef CGAL::Barycentric_coordinates::Wachspress_2<Kernel> Wachspress;
|
||||
typedef CGAL::Barycentric_coordinates::Generalized_barycentric_coordinates_2<Wachspress, Kernel> Wachspress_coordinates;
|
||||
|
||||
using std::cout; using std::endl; using std::string;
|
||||
|
||||
int main()
|
||||
{
|
||||
const int number_of_x_coordinates = 100000;
|
||||
const int number_of_y_coordinates = 1000;
|
||||
const int number_of_runs = 1;
|
||||
|
||||
const Scalar zero = Scalar(0);
|
||||
const Scalar one = Scalar(1);
|
||||
const Scalar x_step = one / Scalar(number_of_x_coordinates);
|
||||
const Scalar y_step = one / Scalar(number_of_y_coordinates);
|
||||
|
||||
Point_vector vertices(16);
|
||||
|
||||
vertices[0] = Point(zero, zero - y_step); vertices[1] = Point(one, zero - y_step);
|
||||
vertices[2] = Point(Scalar(3) / Scalar(2), Scalar(1) / Scalar(4)); vertices[3] = Point(2, Scalar(3) / Scalar(4) );
|
||||
vertices[4] = Point(Scalar(9) / Scalar(4), Scalar(5) / Scalar(4)); vertices[5] = Point(Scalar(9) / Scalar(4), Scalar(9) / Scalar(4));
|
||||
vertices[6] = Point(2, Scalar(11) / Scalar(4) ); vertices[7] = Point(Scalar(3) / Scalar(2), Scalar(13) / Scalar(4));
|
||||
vertices[8] = Point(1, Scalar(7) / Scalar(2) ); vertices[9] = Point(0, Scalar(7) / Scalar(2) );
|
||||
vertices[10] = Point(Scalar(-1) / Scalar(2), Scalar(13) / Scalar(4)); vertices[11] = Point(-1, Scalar(11) / Scalar(4) );
|
||||
vertices[12] = Point(Scalar(-5) / Scalar(4), Scalar(9) / Scalar(4)); vertices[13] = Point(Scalar(-5) / Scalar(4), Scalar(5) / Scalar(4));
|
||||
vertices[14] = Point(-1, Scalar(3) / Scalar(4) ); vertices[15] = Point(Scalar(-1) / Scalar(2), Scalar(1) / Scalar(4));
|
||||
|
||||
Wachspress_coordinates wachspress_coordinates(vertices.begin(), vertices.end());
|
||||
|
||||
Weight_vector weights(16);
|
||||
Overwrite_iterator it = weights.begin();
|
||||
|
||||
Timer time_to_compute;
|
||||
|
||||
double time = 0.0;
|
||||
for(int i = 0; i < number_of_runs; ++i) {
|
||||
|
||||
time_to_compute.start();
|
||||
for(Scalar x = zero; x <= one; x += x_step) {
|
||||
for(Scalar y = zero; y <= one; y += y_step)
|
||||
wachspress_coordinates.compute_weights(Point(x, y), it);
|
||||
}
|
||||
time_to_compute.stop();
|
||||
|
||||
time += time_to_compute.time();
|
||||
|
||||
time_to_compute.reset();
|
||||
}
|
||||
const double mean_time = time / number_of_runs;
|
||||
|
||||
cout.precision(10);
|
||||
cout << endl << "CPU time to compute Wachspress weights (16 vertices) = " << mean_time << " seconds." << endl << endl;
|
||||
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
|
|
@ -0,0 +1,124 @@
|
|||
#include <CGAL/Real_timer.h>
|
||||
#include <CGAL/Exact_predicates_inexact_constructions_kernel.h>
|
||||
#include <CGAL/Barycentric_coordinates_2/Delaunay_domain_2.h>
|
||||
#include <CGAL/Barycentric_coordinates_2/Harmonic_coordinates_2.h>
|
||||
|
||||
using Kernel = CGAL::Exact_predicates_inexact_constructions_kernel;
|
||||
using FT = typename Kernel::FT;
|
||||
using Point_2 = typename Kernel::Point_2;
|
||||
using Timer = CGAL::Real_timer;
|
||||
using Vertices = std::vector<Point_2>;
|
||||
|
||||
using Domain = CGAL::Barycentric_coordinates::Delaunay_domain_2<Vertices, Kernel>;
|
||||
using HMC2 = CGAL::Barycentric_coordinates::Harmonic_coordinates_2<Vertices, Domain, Kernel>;
|
||||
|
||||
int save_raw_data() {
|
||||
|
||||
Timer timer;
|
||||
std::cout.precision(10);
|
||||
|
||||
const std::vector<Point_2> vertices = {
|
||||
Point_2(0, 0), Point_2(1, 0),
|
||||
Point_2(1, 1), Point_2(0, 1)
|
||||
};
|
||||
|
||||
const FT min_scale = 0.00158;
|
||||
const FT max_scale = 0.17500;
|
||||
FT step = (max_scale - min_scale) / FT(100);
|
||||
|
||||
std::list<Point_2> seeds;
|
||||
seeds.push_back(Point_2(0.5, 0.5));
|
||||
|
||||
Domain domain(vertices);
|
||||
HMC2 harmonic_coordinates_2(vertices, domain);
|
||||
|
||||
std::size_t count = 0;
|
||||
for (FT scale = max_scale; scale >= min_scale; scale -= step) {
|
||||
if (scale < min_scale) break;
|
||||
if (count == 80) step /= FT(10);
|
||||
++count;
|
||||
|
||||
domain.clear();
|
||||
domain.create(scale, seeds);
|
||||
harmonic_coordinates_2.clear();
|
||||
|
||||
timer.reset(); timer.start();
|
||||
harmonic_coordinates_2.setup();
|
||||
timer.stop();
|
||||
const double setup = timer.time();
|
||||
|
||||
timer.reset(); timer.start();
|
||||
harmonic_coordinates_2.factorize();
|
||||
timer.stop();
|
||||
const double factorize = timer.time();
|
||||
|
||||
timer.reset(); timer.start();
|
||||
harmonic_coordinates_2.solve();
|
||||
timer.stop();
|
||||
const double solve = timer.time();
|
||||
|
||||
std::cout << domain.number_of_vertices() << " " <<
|
||||
setup << " " << factorize << " " << solve << std::endl;
|
||||
}
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
|
||||
int main() {
|
||||
|
||||
// return save_raw_data();
|
||||
|
||||
Timer timer;
|
||||
std::cout.precision(10);
|
||||
const std::size_t number_of_runs = 1;
|
||||
|
||||
const std::vector<Point_2> vertices = {
|
||||
Point_2(0, 0), Point_2(1, 0),
|
||||
Point_2(1, 1), Point_2(0, 1)
|
||||
};
|
||||
|
||||
const std::vector<FT> scales = {
|
||||
0.175, 0.072, 0.05, 0.01, 0.0071, 0.00502, 0.00224, 0.00158
|
||||
};
|
||||
|
||||
std::list<Point_2> seeds;
|
||||
seeds.push_back(Point_2(0.5, 0.5));
|
||||
|
||||
Domain domain(vertices);
|
||||
for (const FT scale : scales) {
|
||||
|
||||
domain.clear();
|
||||
domain.create(scale, seeds);
|
||||
HMC2 harmonic_coordinates_2(vertices, domain);
|
||||
|
||||
double setup = 0.0, factorize = 0.0, solve = 0.0;
|
||||
for (std::size_t k = 0; k < number_of_runs; ++k) {
|
||||
harmonic_coordinates_2.clear();
|
||||
|
||||
timer.reset(); timer.start();
|
||||
harmonic_coordinates_2.setup();
|
||||
timer.stop();
|
||||
setup += timer.time();
|
||||
|
||||
timer.reset(); timer.start();
|
||||
harmonic_coordinates_2.factorize();
|
||||
timer.stop();
|
||||
factorize += timer.time();
|
||||
|
||||
timer.reset(); timer.start();
|
||||
harmonic_coordinates_2.solve();
|
||||
timer.stop();
|
||||
solve += timer.time();
|
||||
}
|
||||
setup /= static_cast<double>(number_of_runs);
|
||||
factorize /= static_cast<double>(number_of_runs);
|
||||
solve /= static_cast<double>(number_of_runs);
|
||||
|
||||
const double total = setup + factorize + solve;
|
||||
std::cout << "benchmark_hm_4_vertices, num queries: " <<
|
||||
domain.number_of_vertices() << std::endl;
|
||||
std::cout <<
|
||||
"benchmark_hm_4_vertices, compute (CPU time setup/factorize/solve/total): " <<
|
||||
setup << "/" << factorize << "/" << solve << "/" << total << " seconds" << std::endl;
|
||||
}
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
|
|
@ -0,0 +1,85 @@
|
|||
#include <CGAL/Real_timer.h>
|
||||
#include <CGAL/Exact_predicates_inexact_constructions_kernel.h>
|
||||
#include <CGAL/Barycentric_coordinates_2/Delaunay_domain_2.h>
|
||||
#include <CGAL/Barycentric_coordinates_2/Harmonic_coordinates_2.h>
|
||||
|
||||
using Kernel = CGAL::Exact_predicates_inexact_constructions_kernel;
|
||||
using FT = typename Kernel::FT;
|
||||
using Point_2 = typename Kernel::Point_2;
|
||||
using Timer = CGAL::Real_timer;
|
||||
using Vertices = std::vector<Point_2>;
|
||||
|
||||
using Domain = CGAL::Barycentric_coordinates::Delaunay_domain_2<Vertices, Kernel>;
|
||||
using HMC2 = CGAL::Barycentric_coordinates::Harmonic_coordinates_2<Vertices, Domain, Kernel>;
|
||||
|
||||
void generate_regular_polygon(
|
||||
const std::size_t n,
|
||||
const double radius,
|
||||
Vertices& vertices) {
|
||||
|
||||
vertices.clear();
|
||||
vertices.reserve(n);
|
||||
for (std::size_t i = 0; i < n; ++i) {
|
||||
vertices.push_back(Point_2(
|
||||
static_cast<FT>(+radius * sin((CGAL_PI / n) + ((i * 2.0 * CGAL_PI) / n))),
|
||||
static_cast<FT>(-radius * cos((CGAL_PI / n) + ((i * 2.0 * CGAL_PI) / n)))));
|
||||
}
|
||||
}
|
||||
|
||||
int main() {
|
||||
|
||||
Timer timer;
|
||||
std::cout.precision(10);
|
||||
const double radius = 1.0;
|
||||
const std::size_t number_of_runs = 1;
|
||||
|
||||
const std::vector<std::size_t> ns = {
|
||||
5, 10, 25, 50, 100, 500, 1000
|
||||
};
|
||||
const std::vector<FT> scales = {
|
||||
0.00718, 0.0086, 0.00885, 0.00886, 0.00887, 0.00888, 0.00888
|
||||
};
|
||||
|
||||
std::list<Point_2> seeds;
|
||||
seeds.push_back(Point_2(0.0, 0.0));
|
||||
for (std::size_t i = 0; i < ns.size(); ++i) {
|
||||
|
||||
Vertices vertices;
|
||||
generate_regular_polygon(ns[i], radius, vertices);
|
||||
|
||||
Domain domain(vertices);
|
||||
domain.create(scales[i], seeds);
|
||||
HMC2 harmonic_coordinates_2(vertices, domain);
|
||||
|
||||
double setup = 0.0, factorize = 0.0, solve = 0.0;
|
||||
for (std::size_t k = 0; k < number_of_runs; ++k) {
|
||||
harmonic_coordinates_2.clear();
|
||||
|
||||
timer.reset(); timer.start();
|
||||
harmonic_coordinates_2.setup();
|
||||
timer.stop();
|
||||
setup += timer.time();
|
||||
|
||||
timer.reset(); timer.start();
|
||||
harmonic_coordinates_2.factorize();
|
||||
timer.stop();
|
||||
factorize += timer.time();
|
||||
|
||||
timer.reset(); timer.start();
|
||||
harmonic_coordinates_2.solve();
|
||||
timer.stop();
|
||||
solve += timer.time();
|
||||
}
|
||||
setup /= static_cast<double>(number_of_runs);
|
||||
factorize /= static_cast<double>(number_of_runs);
|
||||
solve /= static_cast<double>(number_of_runs);
|
||||
|
||||
const double total = setup + factorize + solve;
|
||||
std::cout << "benchmark_hm_n_vertices, num vertices/num queries: " <<
|
||||
ns[i] << "/" << domain.number_of_vertices() << std::endl;
|
||||
std::cout <<
|
||||
"benchmark_hm_n_vertices, compute (CPU time setup/factorize/solve/total): " <<
|
||||
setup << "/" << factorize << "/" << solve << "/" << total << " seconds" << std::endl;
|
||||
}
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
|
|
@ -0,0 +1,73 @@
|
|||
#include <CGAL/Real_timer.h>
|
||||
#include <CGAL/Exact_predicates_inexact_constructions_kernel.h>
|
||||
#include <CGAL/Barycentric_coordinates_2/Mean_value_coordinates_2.h>
|
||||
|
||||
using Kernel = CGAL::Exact_predicates_inexact_constructions_kernel;
|
||||
using FT = typename Kernel::FT;
|
||||
using Point_2 = typename Kernel::Point_2;
|
||||
using Timer = CGAL::Real_timer;
|
||||
using Vertices = std::vector<Point_2>;
|
||||
|
||||
using MVC2 = CGAL::Barycentric_coordinates::Mean_value_coordinates_2<Vertices, Kernel>;
|
||||
|
||||
int main() {
|
||||
|
||||
const std::size_t number_of_x_coordinates = 100000;
|
||||
const std::size_t number_of_y_coordinates = 1000;
|
||||
const std::size_t number_of_runs = 1;
|
||||
|
||||
const FT zero = FT(0);
|
||||
const FT one = FT(1);
|
||||
const FT x_step = one / static_cast<FT>(number_of_x_coordinates);
|
||||
const FT y_step = one / static_cast<FT>(number_of_y_coordinates);
|
||||
|
||||
const std::vector<Point_2> vertices = {
|
||||
Point_2(zero, zero - y_step), Point_2(one, zero - y_step),
|
||||
Point_2(FT(3) / FT(2), -FT(1) / FT(2)), Point_2(2, -FT(1) / FT(2)),
|
||||
Point_2(FT(5) / FT(2), 0), Point_2(2, FT(1) / FT(2)),
|
||||
Point_2(FT(5) / FT(2), 1), Point_2(3, FT(3) / FT(4)),
|
||||
Point_2(3, FT(5) / FT(4)), Point_2(FT(5) / FT(2), FT(7) / FT(4)),
|
||||
Point_2(3, FT(5) / FT(2)), Point_2(FT(5) / FT(2), FT(5) / FT(2)),
|
||||
Point_2(FT(9) / FT(4), 2), Point_2(FT(7) / FT(4), 2),
|
||||
Point_2(2, FT(5) / FT(2)), Point_2(FT(3) / FT(2), FT(5) / FT(2)),
|
||||
Point_2(FT(5) / FT(4), 2), Point_2(FT(3) / FT(4), 2),
|
||||
Point_2(1, FT(5) / FT(2)), Point_2(FT(1) / FT(2), FT(5) / FT(2)),
|
||||
Point_2(FT(1) / FT(4), 2), Point_2(-FT(1) / FT(4), 2),
|
||||
Point_2(zero, FT(5) / FT(2)), Point_2(-FT(1) / FT(2), FT(5) / FT(2)),
|
||||
Point_2(-FT(3) / FT(4), 2), Point_2(-FT(1) / FT(2), FT(3) / FT(2)),
|
||||
Point_2(-FT(5) / FT(4), FT(3) / FT(2)), Point_2(-FT(1) / FT(2), FT(3) / FT(4)),
|
||||
Point_2(-one, FT(1) / FT(2)), Point_2(-one, zero),
|
||||
Point_2(-FT(3) / FT(2), zero), Point_2(-FT(3) / FT(2), -FT(1) / FT(2)),
|
||||
Point_2(-FT(1) / FT(2), -FT(1) / FT(2)), Point_2(-FT(1) / FT(2), zero - y_step)
|
||||
};
|
||||
|
||||
MVC2 mean_value_coordinates_2(
|
||||
vertices, CGAL::Barycentric_coordinates::Computation_policy_2::FAST);
|
||||
|
||||
Timer timer;
|
||||
std::vector<FT> coordinates(34);
|
||||
auto it = coordinates.begin();
|
||||
|
||||
double time = 0.0;
|
||||
for (std::size_t i = 0; i < number_of_runs; ++i) {
|
||||
timer.start();
|
||||
for (FT x = zero; x <= one; x += x_step) {
|
||||
for (FT y = zero; y <= one; y += y_step) {
|
||||
const Point_2 query(x, y);
|
||||
|
||||
mean_value_coordinates_2(query, it);
|
||||
// mean_value_coordinates_2.weights(query, it);
|
||||
}
|
||||
}
|
||||
timer.stop();
|
||||
time += timer.time();
|
||||
timer.reset();
|
||||
}
|
||||
|
||||
const double mean_time =
|
||||
time / static_cast<double>(number_of_runs);
|
||||
std::cout.precision(10);
|
||||
std::cout << "benchmark_mv_34_vertices (CPU time): " <<
|
||||
mean_time << " seconds" << std::endl;
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
|
|
@ -0,0 +1,84 @@
|
|||
#include <CGAL/Real_timer.h>
|
||||
#include <CGAL/Exact_predicates_inexact_constructions_kernel.h>
|
||||
#include <CGAL/Barycentric_coordinates_2/Wachspress_coordinates_2.h>
|
||||
#include <CGAL/Barycentric_coordinates_2/Mean_value_coordinates_2.h>
|
||||
#include <CGAL/Barycentric_coordinates_2/Discrete_harmonic_coordinates_2.h>
|
||||
|
||||
using Kernel = CGAL::Exact_predicates_inexact_constructions_kernel;
|
||||
using FT = typename Kernel::FT;
|
||||
using Point_2 = typename Kernel::Point_2;
|
||||
using Timer = CGAL::Real_timer;
|
||||
using Vertices = std::vector<Point_2>;
|
||||
|
||||
using WPC2 = CGAL::Barycentric_coordinates::Wachspress_coordinates_2<Vertices, Kernel>;
|
||||
using MVC2 = CGAL::Barycentric_coordinates::Mean_value_coordinates_2<Vertices, Kernel>;
|
||||
using DHC2 = CGAL::Barycentric_coordinates::Discrete_harmonic_coordinates_2<Vertices, Kernel>;
|
||||
|
||||
void generate_regular_polygon(
|
||||
const std::size_t n,
|
||||
const double radius,
|
||||
Vertices& vertices) {
|
||||
|
||||
vertices.clear();
|
||||
vertices.reserve(n);
|
||||
for (std::size_t i = 0; i < n; ++i)
|
||||
vertices.push_back(Point_2(
|
||||
static_cast<FT>(+radius * sin((CGAL_PI / n) + ((i * 2.0 * CGAL_PI) / n))),
|
||||
static_cast<FT>(-radius * cos((CGAL_PI / n) + ((i * 2.0 * CGAL_PI) / n)))));
|
||||
}
|
||||
|
||||
int main() {
|
||||
|
||||
const std::size_t number_of_x_coordinates = 1000;
|
||||
const std::size_t number_of_y_coordinates = 1000;
|
||||
const std::size_t number_of_runs = 1;
|
||||
|
||||
const FT one = FT(1);
|
||||
const FT x_step = one / static_cast<FT>(number_of_x_coordinates);
|
||||
const FT y_step = one / static_cast<FT>(number_of_y_coordinates);
|
||||
|
||||
const std::size_t n = 100;
|
||||
const double radius = 2.0;
|
||||
Vertices vertices;
|
||||
generate_regular_polygon(
|
||||
n, radius, vertices);
|
||||
|
||||
WPC2 wachspress_coordinates_2(
|
||||
vertices, CGAL::Barycentric_coordinates::Computation_policy_2::FAST);
|
||||
MVC2 mean_value_coordinates_2(
|
||||
vertices, CGAL::Barycentric_coordinates::Computation_policy_2::FAST);
|
||||
DHC2 discrete_harmonic_coordinates_2(
|
||||
vertices, CGAL::Barycentric_coordinates::Computation_policy_2::FAST);
|
||||
|
||||
Timer timer;
|
||||
std::vector<FT> coordinates(n);
|
||||
auto it = coordinates.begin();
|
||||
|
||||
double time = 0.0;
|
||||
for (std::size_t i = 0; i < number_of_runs; ++i) {
|
||||
timer.start();
|
||||
for (FT x = -one; x <= one; x += x_step) {
|
||||
for (FT y = -one; y <= one; y += y_step) {
|
||||
const Point_2 query(x, y);
|
||||
|
||||
wachspress_coordinates_2(query, it);
|
||||
// mean_value_coordinates_2(query, it);
|
||||
// discrete_harmonic_coordinates_2(query, it);
|
||||
|
||||
// wachspress_coordinates_2.weights(query, it);
|
||||
// mean_value_coordinates_2.weights(query, it);
|
||||
// discrete_harmonic_coordinates_2.weights(query, it);
|
||||
}
|
||||
}
|
||||
timer.stop();
|
||||
time += timer.time();
|
||||
timer.reset();
|
||||
}
|
||||
|
||||
const double mean_time =
|
||||
time / static_cast<double>(number_of_runs);
|
||||
std::cout.precision(10);
|
||||
std::cout << "benchmark_polygon_100_vertices (CPU time): " <<
|
||||
mean_time << " seconds" << std::endl;
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
|
|
@ -0,0 +1,85 @@
|
|||
#include <CGAL/Real_timer.h>
|
||||
#include <CGAL/Exact_predicates_inexact_constructions_kernel.h>
|
||||
#include <CGAL/Barycentric_coordinates_2/Wachspress_coordinates_2.h>
|
||||
#include <CGAL/Barycentric_coordinates_2/Mean_value_coordinates_2.h>
|
||||
#include <CGAL/Barycentric_coordinates_2/Discrete_harmonic_coordinates_2.h>
|
||||
|
||||
using Kernel = CGAL::Exact_predicates_inexact_constructions_kernel;
|
||||
using FT = typename Kernel::FT;
|
||||
using Point_2 = typename Kernel::Point_2;
|
||||
using Timer = CGAL::Real_timer;
|
||||
using Vertices = std::vector<Point_2>;
|
||||
|
||||
using WPC2 = CGAL::Barycentric_coordinates::Wachspress_coordinates_2<Vertices, Kernel>;
|
||||
using MVC2 = CGAL::Barycentric_coordinates::Mean_value_coordinates_2<Vertices, Kernel>;
|
||||
using DHC2 = CGAL::Barycentric_coordinates::Discrete_harmonic_coordinates_2<Vertices, Kernel>;
|
||||
|
||||
int main() {
|
||||
|
||||
const std::size_t number_of_x_coordinates = 100000;
|
||||
const std::size_t number_of_y_coordinates = 1000;
|
||||
const std::size_t number_of_runs = 1;
|
||||
|
||||
const FT zero = FT(0);
|
||||
const FT one = FT(1);
|
||||
const FT x_step = one / static_cast<FT>(number_of_x_coordinates);
|
||||
const FT y_step = one / static_cast<FT>(number_of_y_coordinates);
|
||||
|
||||
const std::vector<Point_2> vertices = {
|
||||
Point_2(zero, zero - y_step),
|
||||
Point_2(one , zero - y_step),
|
||||
Point_2(FT(3) / FT(2), FT(1) / FT(4)),
|
||||
Point_2(2, FT(3) / FT(4)),
|
||||
Point_2(FT(9) / FT(4), FT(5) / FT(4)),
|
||||
Point_2(FT(9) / FT(4), FT(9) / FT(4)),
|
||||
Point_2(2, FT(11) / FT(4)),
|
||||
Point_2(FT(3) / FT(2), FT(13) / FT(4)),
|
||||
Point_2(1, FT(7) / FT(2)),
|
||||
Point_2(0, FT(7) / FT(2)),
|
||||
Point_2(-FT(1) / FT(2), FT(13) / FT(4)),
|
||||
Point_2(-1, FT(11) / FT(4)),
|
||||
Point_2(-FT(5) / FT(4), FT(9) / FT(4)),
|
||||
Point_2(-FT(5) / FT(4), FT(5) / FT(4)),
|
||||
Point_2(-1, FT(3) / FT(4)),
|
||||
Point_2(-FT(1) / FT(2), FT(1) / FT(4))
|
||||
};
|
||||
|
||||
WPC2 wachspress_coordinates_2(
|
||||
vertices, CGAL::Barycentric_coordinates::Computation_policy_2::FAST);
|
||||
MVC2 mean_value_coordinates_2(
|
||||
vertices, CGAL::Barycentric_coordinates::Computation_policy_2::FAST);
|
||||
DHC2 discrete_harmonic_coordinates_2(
|
||||
vertices, CGAL::Barycentric_coordinates::Computation_policy_2::FAST);
|
||||
|
||||
Timer timer;
|
||||
std::vector<FT> coordinates(16);
|
||||
auto it = coordinates.begin();
|
||||
|
||||
double time = 0.0;
|
||||
for (std::size_t i = 0; i < number_of_runs; ++i) {
|
||||
timer.start();
|
||||
for (FT x = zero; x <= one; x += x_step) {
|
||||
for (FT y = zero; y <= one; y += y_step) {
|
||||
const Point_2 query(x, y);
|
||||
|
||||
wachspress_coordinates_2(query, it);
|
||||
// mean_value_coordinates_2(query, it);
|
||||
// discrete_harmonic_coordinates_2(query, it);
|
||||
|
||||
// wachspress_coordinates_2.weights(query, it);
|
||||
// mean_value_coordinates_2.weights(query, it);
|
||||
// discrete_harmonic_coordinates_2.weights(query, it);
|
||||
}
|
||||
}
|
||||
timer.stop();
|
||||
time += timer.time();
|
||||
timer.reset();
|
||||
}
|
||||
|
||||
const double mean_time =
|
||||
time / static_cast<double>(number_of_runs);
|
||||
std::cout.precision(10);
|
||||
std::cout << "benchmark_polygon_16_vertices (CPU time): " <<
|
||||
mean_time << " seconds" << std::endl;
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
|
|
@ -0,0 +1,73 @@
|
|||
#include <CGAL/Real_timer.h>
|
||||
#include <CGAL/Exact_predicates_inexact_constructions_kernel.h>
|
||||
#include <CGAL/Barycentric_coordinates_2/Wachspress_coordinates_2.h>
|
||||
#include <CGAL/Barycentric_coordinates_2/Mean_value_coordinates_2.h>
|
||||
#include <CGAL/Barycentric_coordinates_2/Discrete_harmonic_coordinates_2.h>
|
||||
|
||||
using Kernel = CGAL::Exact_predicates_inexact_constructions_kernel;
|
||||
using FT = typename Kernel::FT;
|
||||
using Point_2 = typename Kernel::Point_2;
|
||||
using Timer = CGAL::Real_timer;
|
||||
using Vertices = std::vector<Point_2>;
|
||||
|
||||
using WPC2 = CGAL::Barycentric_coordinates::Wachspress_coordinates_2<Vertices, Kernel>;
|
||||
using MVC2 = CGAL::Barycentric_coordinates::Mean_value_coordinates_2<Vertices, Kernel>;
|
||||
using DHC2 = CGAL::Barycentric_coordinates::Discrete_harmonic_coordinates_2<Vertices, Kernel>;
|
||||
|
||||
int main() {
|
||||
|
||||
const std::size_t number_of_x_coordinates = 1000000;
|
||||
const std::size_t number_of_y_coordinates = 1000;
|
||||
const std::size_t number_of_runs = 1;
|
||||
|
||||
const FT zero = FT(0);
|
||||
const FT one = FT(1);
|
||||
const FT x_step = one / static_cast<FT>(number_of_x_coordinates);
|
||||
const FT y_step = one / static_cast<FT>(number_of_y_coordinates);
|
||||
|
||||
const std::vector<Point_2> vertices = {
|
||||
Point_2(zero - x_step, zero - y_step),
|
||||
Point_2(one + x_step, zero - y_step),
|
||||
Point_2(one + x_step, one + y_step),
|
||||
Point_2(zero - x_step, one + y_step)
|
||||
};
|
||||
|
||||
WPC2 wachspress_coordinates_2(
|
||||
vertices, CGAL::Barycentric_coordinates::Computation_policy_2::FAST);
|
||||
MVC2 mean_value_coordinates_2(
|
||||
vertices, CGAL::Barycentric_coordinates::Computation_policy_2::FAST);
|
||||
DHC2 discrete_harmonic_coordinates_2(
|
||||
vertices, CGAL::Barycentric_coordinates::Computation_policy_2::FAST);
|
||||
|
||||
Timer timer;
|
||||
std::vector<FT> coordinates(4);
|
||||
auto it = coordinates.begin();
|
||||
|
||||
double time = 0.0;
|
||||
for (std::size_t i = 0; i < number_of_runs; ++i) {
|
||||
timer.start();
|
||||
for (FT x = zero; x <= one; x += x_step) {
|
||||
for (FT y = zero; y <= one; y += y_step) {
|
||||
const Point_2 query(x, y);
|
||||
|
||||
wachspress_coordinates_2(query, it);
|
||||
// mean_value_coordinates_2(query, it);
|
||||
// discrete_harmonic_coordinates_2(query, it);
|
||||
|
||||
// wachspress_coordinates_2.weights(query, it);
|
||||
// mean_value_coordinates_2.weights(query, it);
|
||||
// discrete_harmonic_coordinates_2.weights(query, it);
|
||||
}
|
||||
}
|
||||
timer.stop();
|
||||
time += timer.time();
|
||||
timer.reset();
|
||||
}
|
||||
|
||||
const double mean_time =
|
||||
time / static_cast<double>(number_of_runs);
|
||||
std::cout.precision(10);
|
||||
std::cout << "benchmark_polygon_4_vertices (CPU time): " <<
|
||||
mean_time << " seconds" << std::endl;
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
|
|
@ -0,0 +1,48 @@
|
|||
#include <CGAL/Real_timer.h>
|
||||
#include <CGAL/Exact_predicates_inexact_constructions_kernel.h>
|
||||
#include <CGAL/Barycentric_coordinates_2/segment_coordinates_2.h>
|
||||
|
||||
using Kernel = CGAL::Exact_predicates_inexact_constructions_kernel;
|
||||
using FT = typename Kernel::FT;
|
||||
using Point_2 = typename Kernel::Point_2;
|
||||
using Timer = CGAL::Real_timer;
|
||||
|
||||
int main() {
|
||||
|
||||
const std::size_t number_of_iterations = 100000;
|
||||
const std::size_t number_of_points = 10000;
|
||||
const std::size_t number_of_runs = 1;
|
||||
|
||||
const FT zero = FT(0);
|
||||
const FT one = FT(1);
|
||||
const FT step = one / static_cast<FT>(number_of_points);
|
||||
|
||||
const Point_2 p0 = Point_2(zero - step, zero);
|
||||
const Point_2 p1 = Point_2(one + step, zero);
|
||||
|
||||
Timer timer;
|
||||
std::vector<FT> coordinates(2);
|
||||
auto it = coordinates.begin();
|
||||
|
||||
double time = 0.0;
|
||||
for (std::size_t i = 0; i < number_of_runs; ++i) {
|
||||
timer.start();
|
||||
for (std::size_t j = 0; j < number_of_iterations; ++j) {
|
||||
for (FT x = zero; x <= one; x += step) {
|
||||
const Point_2 query(x, zero);
|
||||
CGAL::Barycentric_coordinates::segment_coordinates_2(
|
||||
p0, p1, query, it);
|
||||
}
|
||||
}
|
||||
timer.stop();
|
||||
time += timer.time();
|
||||
timer.reset();
|
||||
}
|
||||
|
||||
const double mean_time =
|
||||
time / static_cast<double>(number_of_runs);
|
||||
std::cout.precision(10);
|
||||
std::cout << "benchmark_segment_coordinates (CPU time): " <<
|
||||
mean_time << " seconds" << std::endl;
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
|
|
@ -0,0 +1,51 @@
|
|||
#include <CGAL/Real_timer.h>
|
||||
#include <CGAL/Exact_predicates_inexact_constructions_kernel.h>
|
||||
#include <CGAL/Barycentric_coordinates_2/triangle_coordinates_2.h>
|
||||
|
||||
using Kernel = CGAL::Exact_predicates_inexact_constructions_kernel;
|
||||
using FT = typename Kernel::FT;
|
||||
using Point_2 = typename Kernel::Point_2;
|
||||
using Timer = CGAL::Real_timer;
|
||||
|
||||
int main() {
|
||||
|
||||
const std::size_t number_of_x_coordinates = 100000;
|
||||
const std::size_t number_of_y_coordinates = 10000;
|
||||
const std::size_t number_of_runs = 1;
|
||||
|
||||
const FT zero = FT(0);
|
||||
const FT one = FT(1);
|
||||
const FT two = FT(2);
|
||||
const FT x_step = one / static_cast<FT>(number_of_x_coordinates);
|
||||
const FT y_step = one / static_cast<FT>(number_of_y_coordinates);
|
||||
|
||||
const Point_2 p0 = Point_2(zero - x_step, zero - x_step);
|
||||
const Point_2 p1 = Point_2(two + y_step, zero - x_step);
|
||||
const Point_2 p2 = Point_2(zero - x_step, two + y_step);
|
||||
|
||||
Timer timer;
|
||||
std::vector<FT> coordinates(3);
|
||||
auto it = coordinates.begin();
|
||||
|
||||
double time = 0.0;
|
||||
for (std::size_t i = 0; i < number_of_runs; ++i) {
|
||||
timer.start();
|
||||
for (FT x = zero; x <= one; x += x_step) {
|
||||
for (FT y = zero; y <= one; y += y_step) {
|
||||
const Point_2 query(x, y);
|
||||
CGAL::Barycentric_coordinates::triangle_coordinates_2(
|
||||
p0, p1, p2, query, it);
|
||||
}
|
||||
}
|
||||
timer.stop();
|
||||
time += timer.time();
|
||||
timer.reset();
|
||||
}
|
||||
|
||||
const double mean_time =
|
||||
time / static_cast<double>(number_of_runs);
|
||||
std::cout.precision(10);
|
||||
std::cout << "benchmark_triangle_coordinates (CPU time): " <<
|
||||
mean_time << " seconds" << std::endl;
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
|
|
@ -1,283 +1,860 @@
|
|||
namespace CGAL {
|
||||
namespace Barycentric_coordinates {
|
||||
|
||||
/*!
|
||||
|
||||
\mainpage User Manual
|
||||
\anchor Chapter_2D_Generalized_Barycentric_Coordinates
|
||||
\cgalAutoToc
|
||||
|
||||
\authors Dmitry Anisimov, David Bommes, Kai Hormann, and Pierre Alliez
|
||||
|
||||
|
||||
\section gbc_introduction Introduction
|
||||
|
||||
The package <em>2D Generalized Barycentric Coordinates</em> offers an efficient and robust implementation of two-dimensional closed-form generalized barycentric coordinates defined for simple two-dimensional polygons. If coordinates with respect to multivariate scattered points instead of a polygon are required, please refer to natural neighbor coordinates from the package \ref PkgInterpolation2 "2D and Surface Function Interpolation".
|
||||
Barycentric coordinates are widely used in computer graphics and computational mechanics
|
||||
to determine a position of a point in the plane with respect to a triangle. These coordinates
|
||||
have been later generalized to support simple polygons in 2D and polyhedra in 3D.
|
||||
|
||||
In particular, the package includes an implementation of \ref wp_example "Wachspress", \ref mv_example "mean value", and \ref dh_example "discrete harmonic" coordinates and provides some extra functions to compute barycentric coordinates with respect to segments (\ref seg_example "segment coordinates") and triangles (\ref tri_example "triangle coordinates"). The section \ref gbc_theory gives a short introduction to the topic of barycentric coordinates.
|
||||
This package offers an efficient and robust implementation of 2D generalized barycentric
|
||||
coordinates defined for simple polygons in the plane. If coordinates with respect to multivariate
|
||||
scattered points instead of a polygon are required, please refer to natural neighbor coordinates
|
||||
from the package \ref chapinterpolation "2D and Surface Function Interpolation".
|
||||
|
||||
\section gbc_interface Interface
|
||||
In particular, this package includes an implementation of \ref wp_example "Wachspress",
|
||||
\ref dh_example "discrete harmonic", \ref mv_example "mean value", and \ref hm_example "harmonic"
|
||||
coordinates, and provides some extra functions to compute barycentric coordinates with respect
|
||||
to \ref seg_example "segments" and \ref tri_example "triangles".
|
||||
|
||||
Each class that computes barycentric coordinates is parameterized by a traits class. This traits class specifies types and geometric primitives that are used in the computation and must be a model of the concept `BarycentricTraits_2`.
|
||||
\cgalFigureBegin{overview, overview.svg}
|
||||
Wachspress (WP), discrete harmonic (DH), mean value (MV), and harmonic (HM) coordinate functions
|
||||
for a convex polygon plotted with respect to the marked vertex.
|
||||
\cgalFigureEnd
|
||||
|
||||
The main entry point to the component is an input iterator over the vertices of a polygon. The polygon's vertices must follow clockwise or anticlockwise ordering and can be of any type. However, internally the classes use the type `CGAL::Point_2`, that is why an appropriate traits class that converts the user's type to `CGAL::Point_2` must be provided. The same argument holds for query points.
|
||||
|
||||
Mean value coordinates are the most generic coordinates in this package because they allow an arbitrary simple polygon as input. Wachspress and discrete harmonic coordinates are, by definition, limited to strictly convex polygons. Segment coordinates take as input any non-degenerate segment, and triangle coordinates allow an arbitrary non-degenerate triangle.
|
||||
\section gbc_interface Software Design
|
||||
|
||||
Segment and triangle coordinates can be computed by using either a global function or creating the corresponding class. All other generalized coordinates can be computed by creating an instance of the class `CGAL::Barycentric_coordinates::Generalized_barycentric_coordinates_2` parameterized by an appropriate coordinate type that must be a model of the concept `BarycentricCoordinates_2`.
|
||||
Mean value and harmonic coordinates are the most generic coordinates in this package,
|
||||
because they allow an arbitrary simple polygon as input. Wachspress and discrete harmonic coordinates
|
||||
are, by definition, limited to strictly convex polygons. Segment coordinates take as input
|
||||
any non-degenerate segment, and triangle coordinates allow an arbitrary non-degenerate triangle.
|
||||
|
||||
Any point in the plane may be taken as a query point. However, we do not recommend to use Wachspress and discrete harmonic coordinates with query points outside the closure of a polygon because at some of those points these coordinates are not well-defined, as explained in the Section \ref gbc_degeneracies.
|
||||
Wachspress, discrete harmonic, mean value, and harmonic coordinates are all generalized
|
||||
barycentric coordinates. However, while Wachspress, discrete harmonic, and mean value
|
||||
coordinates can be computed analytically, harmonic coordinates cannot. They first need
|
||||
to be approximated over a triangulation of the interior part of the polygon. Once approximated,
|
||||
they can be evaluated analytically at any point inside the polygon.
|
||||
|
||||
Once instantiated for some polygon, the coordinates can be computed multiple times for different query points with respect to all the vertices of the provided polygon. Use the \ref PkgBarycentricCoordinates2Ref "Reference Manual" for the detailed interface.
|
||||
For all analytic coordinates, we provide two algorithms. One has a linear time complexity,
|
||||
but may suffer imprecisions near the polygon boundary, while the second one is precise
|
||||
but has a quadratic time complexity. The user can choose the preferred algorithm by
|
||||
specifying a computation policy `Barycentric_coordinates::Computation_policy_2`.
|
||||
|
||||
All analytic barycentric coordinates for polygons can be computed either by instantiating a class
|
||||
or through one of the free functions. Harmonic coordinates can be computed only by
|
||||
instantiating a class that must be parameterized by a model of the concept `DiscretizedDomain_2`.
|
||||
Segment and triangle coordinates can be computed only through the free functions.
|
||||
For more information see the \ref PkgBarycentricCoordinates2Ref "Reference Manual".
|
||||
|
||||
Any point in the plane may be taken as a query point. However, we do not recommend using
|
||||
Wachspress and discrete harmonic coordinates with query points outside the closure
|
||||
of a polygon, because they are not well-defined for some of these points. The same holds
|
||||
for harmonic coordinates, which are not defined everywhere outside the polygon. For more
|
||||
information see Section \ref gbc_degeneracies.
|
||||
|
||||
The output of the computation is a set of coordinate values at the given query point
|
||||
with respect to the polygon vertices. That means that the number of returned coordinates
|
||||
per query point equates the number of polygon vertices. The ordering of the coordinates
|
||||
is the same as the ordering of polygon vertices.
|
||||
|
||||
All class and function templates are parameterized by a traits class, which is a model
|
||||
of the concept `BarycentricTraits_2`. It provides all necessary geometric primitives,
|
||||
predicates, and constructions, which are required for the computation. All models of `Kernel`
|
||||
can be used. A polygon is provided as a range of vertices with a
|
||||
\ref PkgPropertyMapRef "property map" that maps a vertex from the polygon to `CGAL::Point_2`.
|
||||
|
||||
If you do not know which coordinate function best fits your application, you can address the
|
||||
table below for some advise.
|
||||
|
||||
<table class="markdownTable" align="center">
|
||||
<tr class="markdownTableHead">
|
||||
<th class="markdownTableHeadCenter">Coordinates</th>
|
||||
<th class="markdownTableHeadCenter">Properties</th>
|
||||
<th class="markdownTableHeadCenter">Valid domain</th>
|
||||
<th class="markdownTableHeadCenter">Closed form</th>
|
||||
<th class="markdownTableHeadCenter">Queries</th>
|
||||
<th class="markdownTableHeadCenter">Speed</th>
|
||||
</tr>
|
||||
<tr class="markdownTableBody">
|
||||
<td class="markdownTableBodyCenter">Segment</td>
|
||||
<td class="markdownTableBodyCenter">All</td>
|
||||
<td class="markdownTableBodyCenter">2D non-degenerate segments</td>
|
||||
<td class="markdownTableBodyCenter">Yes</td>
|
||||
<td class="markdownTableBodyCenter">Everywhere on the supporting line</td>
|
||||
<td class="markdownTableBodyCenter">+++</td>
|
||||
</tr>
|
||||
<tr class="markdownTableBody">
|
||||
<td class="markdownTableBodyCenter">Triangle</td>
|
||||
<td class="markdownTableBodyCenter">All</td>
|
||||
<td class="markdownTableBodyCenter">2D non-degenerate triangles</td>
|
||||
<td class="markdownTableBodyCenter">Yes</td>
|
||||
<td class="markdownTableBodyCenter">Everywhere in 2D</td>
|
||||
<td class="markdownTableBodyCenter">+++</td>
|
||||
</tr>
|
||||
<tr class="markdownTableBody">
|
||||
<td class="markdownTableBodyCenter">Discrete harmonic</td>
|
||||
<td class="markdownTableBodyCenter">May be negative</td>
|
||||
<td class="markdownTableBodyCenter">Strongly convex polygons</td>
|
||||
<td class="markdownTableBodyCenter">Yes</td>
|
||||
<td class="markdownTableBodyCenter">Everywhere inside the polygon</td>
|
||||
<td class="markdownTableBodyCenter">++</td>
|
||||
</tr>
|
||||
<tr class="markdownTableBody">
|
||||
<td class="markdownTableBodyCenter">Wachspress</td>
|
||||
<td class="markdownTableBodyCenter">All</td>
|
||||
<td class="markdownTableBodyCenter">Strongly convex polygons</td>
|
||||
<td class="markdownTableBodyCenter">Yes</td>
|
||||
<td class="markdownTableBodyCenter">Everywhere inside the polygon</td>
|
||||
<td class="markdownTableBodyCenter">++</td>
|
||||
</tr>
|
||||
<tr class="markdownTableBody">
|
||||
<td class="markdownTableBodyCenter">Mean value</td>
|
||||
<td class="markdownTableBodyCenter">May be negative</td>
|
||||
<td class="markdownTableBodyCenter">Simple polygons</td>
|
||||
<td class="markdownTableBodyCenter">Yes</td>
|
||||
<td class="markdownTableBodyCenter">Everywhere in 2D</td>
|
||||
<td class="markdownTableBodyCenter">++</td>
|
||||
</tr>
|
||||
<tr class="markdownTableBody">
|
||||
<td class="markdownTableBodyCenter">Harmonic</td>
|
||||
<td class="markdownTableBodyCenter">All</td>
|
||||
<td class="markdownTableBodyCenter">Simple polygons</td>
|
||||
<td class="markdownTableBodyCenter">No</td>
|
||||
<td class="markdownTableBodyCenter">Everywhere inside the polygon</td>
|
||||
<td class="markdownTableBodyCenter">+</td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
\note This is the second version of the package with the modified and improved API.
|
||||
The package still supports the old API. See more details \ref depr_example "here".
|
||||
|
||||
The output of the computation is a set of coordinate values at the current query point with respect to all the vertices of the polygon. This output can be stored in an arbitrary container providing an appropriate output iterator. In addition, all the classes return a pointer to the last stored element and a status of the computation (Boolean true or false).
|
||||
|
||||
\section gbc_examples Examples
|
||||
|
||||
In order to facilitate the process of learning this package, we provide various examples
|
||||
with a basic usage of different barycentric components.
|
||||
|
||||
|
||||
\subsection seg_example Segment Coordinates
|
||||
This is a simple example to show the use of the global function \ref seg_coord_global "CGAL::Barycentric_coordinates::compute_segment_coordinates_2()". We compute coordinates at three green points along the segment \f$[v_0, v_1]\f$ and at two blue points outside this segment but along its supporting line. We use the exact kernel and return coordinates as an array of two values. Again, the symmetry of the query points helps us to recognize errors that may have occurred during the computation.
|
||||
|
||||
This example illustrates the use of the global function `segment_coordinates_2()`.
|
||||
We compute coordinates at three green points along the segment \f$[v_0, v_1]\f$ and at two blue points outside this segment
|
||||
but along its supporting line. The symmetry of the query points helps recognizing errors that
|
||||
may have occurred during construction of the example. The used `Kernel` is exact.
|
||||
|
||||
\anchor seg_coord_example
|
||||
\cgalFigureBegin{seg__example,segment_coordinates_example.png}
|
||||
\cgalFigureBegin{seg_example, seg_coord_example.svg}
|
||||
Example's point pattern.
|
||||
\cgalFigureEnd
|
||||
|
||||
\cgalExample{Barycentric_coordinates_2/Segment_coordinates_example.cpp}
|
||||
\cgalExample{Barycentric_coordinates_2/segment_coordinates.cpp}
|
||||
|
||||
|
||||
\subsection tri_example Triangle Coordinates
|
||||
In this example we show how to use the class `CGAL::Barycentric_coordinates::Triangle_coordinates_2` with the `Simple_cartesian` kernel for double type. We compute coordinates for three sets of points: interior (green), boundary (red), and exterior (blue). Note that some of the coordinate values for the exterior points are negative. We use a standard container of the type <a href="https://en.cppreference.com/w/cpp/container/vector">`std::vector`</a> and <a href="https://en.cppreference.com/w/cpp/iterator/insert_iterator">`std::insert_iterator`</a> to access and store the resulting coordinate values.
|
||||
|
||||
In this example, we show how to use the global function `triangle_coordinates_2()`.
|
||||
We compute coordinates for three sets of points: interior (green), boundary (red), and exterior (blue).
|
||||
Note that some of the coordinate values for the exterior points are negative.
|
||||
The used `Kernel` is inexact.
|
||||
|
||||
\anchor tri_coord_example
|
||||
\cgalFigureBegin{tri__example,triangle_coordinates_example.png}
|
||||
\cgalFigureBegin{tri_example, tri_coord_example.svg}
|
||||
Example's point pattern.
|
||||
\cgalFigureEnd
|
||||
|
||||
\cgalExample{Barycentric_coordinates_2/Triangle_coordinates_example.cpp}
|
||||
\cgalExample{Barycentric_coordinates_2/triangle_coordinates.cpp}
|
||||
|
||||
|
||||
\subsection wp_example Wachspress Coordinates
|
||||
In the following example we create 1000 random points, then we take the convex hull of this set of points as our polygon, and compute Wachspress coordinates at all the defined points. We use the `Simple_cartesian` kernel with double type as a traits class and store obtained coordinate values in a container of the type <a href="https://en.cppreference.com/w/cpp/container/vector">`std::vector`</a>. The output iterator is <a href="https://en.cppreference.com/w/cpp/iterator/back_insert_iterator">`std::back_insert_iterator`</a>.
|
||||
|
||||
\cgalExample{Barycentric_coordinates_2/Wachspress_coordinates_example.cpp}
|
||||
In the following example, we generate 100 random points (green/red/black), then we take the
|
||||
convex hull (red/black) of this set of points as our polygon (black), and compute Wachspress
|
||||
coordinates at all the generated points. The used `Kernel` is inexact.
|
||||
|
||||
\anchor wp_coord_example
|
||||
\cgalFigureBegin{wp_example, wp_coord_example.svg}
|
||||
Example's point pattern.
|
||||
\cgalFigureEnd
|
||||
|
||||
\cgalExample{Barycentric_coordinates_2/wachspress_coordinates.cpp}
|
||||
|
||||
|
||||
\subsection dh_example Discrete Harmonic Coordinates
|
||||
In this example we compute discrete harmonic coordinates for a set of green (interior), red (boundary), and blue (exterior) points with respect to a unit square. We also show how to specify the location of a query point using additional function parameters. The used kernel is exact, and we use an output container of the type <a href="https://en.cppreference.com/w/cpp/container/vector">`std::vector`</a>. Since all the points are symmetric, it is easy to debug the correctness of the obtained coordinate values. The output iterator is <a href="https://en.cppreference.com/w/cpp/iterator/back_insert_iterator">`std::back_insert_iterator`</a>.
|
||||
|
||||
In this example, we compute discrete harmonic coordinates for a set of green (interior),
|
||||
red (boundary), and blue (exterior) points with respect to a unit square. We also demonstrate
|
||||
the use of various containers, both random access and serial access, different property maps,
|
||||
and the ability to choose a computation policy. For points on the polygon boundary,
|
||||
we use the free function `boundary_coordinates_2()`.
|
||||
The used `Kernel` is exact.
|
||||
|
||||
\anchor dh_coord_example
|
||||
\cgalFigureBegin{dh__example,discrete_harmonic_coordinates_example.png}
|
||||
\cgalFigureBegin{dh_example, dh_coord_example.svg}
|
||||
Example's point pattern.
|
||||
\cgalFigureEnd
|
||||
|
||||
\cgalExample{Barycentric_coordinates_2/Discrete_harmonic_coordinates_example.cpp}
|
||||
\cgalExample{Barycentric_coordinates_2/discrete_harmonic_coordinates.cpp}
|
||||
|
||||
|
||||
\subsection mv_example Mean Value Coordinates
|
||||
This is an example that shows how to compute mean value coordinates for a set of green points in a star-shaped polygon. We note that this type of coordinates is well-defined for such a concave polygon while Wachspress and discrete harmonic coordinates are not. However, it may give negative coordinate values for points outside <a href="https://en.wikipedia.org/wiki/Star-shaped_polygon">the polygon's kernel</a> (shown in red). We use an inexact data type, an output container of the type <a href="https://en.cppreference.com/w/cpp/container/vector">`std::vector`</a>, and an output iterator of the type <a href="https://en.cppreference.com/w/cpp/iterator/back_insert_iterator">std::back_insert_iterator</a> to compute, access, and store the resulting coordinate values. We also show how to choose different algorithms to compute generalized barycentric coordinates (one is more precise while the other is faster).
|
||||
|
||||
This is an example that illustrates how to compute mean value coordinates for a set of green points
|
||||
in a star-shaped polygon. We note that this type of coordinates is well-defined for such a concave polygon
|
||||
while Wachspress and discrete harmonic coordinates are not. However, it may yield negative
|
||||
coordinate values for points outside <a href="https://en.wikipedia.org/wiki/Star-shaped_polygon">the polygon's kernel</a>
|
||||
(shown in red). We speed up the computation using the linear time complexity algorithm by specifying
|
||||
a computation policy `Barycentric_coordinates::Computation_policy_2`. The used `Kernel` is inexact.
|
||||
|
||||
\anchor mv_coord_example
|
||||
\cgalFigureBegin{mv__example,mean_value_coordinates_example.png}
|
||||
\cgalFigureBegin{mv_example, mv_coord_example.svg}
|
||||
Example's point pattern.
|
||||
\cgalFigureEnd
|
||||
|
||||
\cgalExample{Barycentric_coordinates_2/Mean_value_coordinates_example.cpp}
|
||||
\cgalExample{Barycentric_coordinates_2/mean_value_coordinates.cpp}
|
||||
|
||||
\subsection height_inter_example Height Interpolation for Terrain Modeling
|
||||
|
||||
This is an advanced example that shows how to use generalized barycentric coordinates for height interpolation with applications to terrain modeling. It also shows how to use a non-default traits class with our package instead of a `Kernel` traits class. Suppose we know the boundary of three-dimensional piece of terrain that can be represented as a polygon with several three-dimensional vertices, where the third dimension gives the corresponding height. The task is to propagate the height from the known sample points on the boundary to the polygon's interior. This gives an approximate estimation of the terrain's surface in this region.
|
||||
\subsection hm_example Harmonic Coordinates
|
||||
This example illustrates how to \ref terrain_triangulation_fig "discretize" the interior part
|
||||
of the \ref terrain_example_fig "polygon" and compute harmonic coordinates at the vertices
|
||||
of the discretized domain, which is represented by a 2D Delaunay triangulation. Once computed,
|
||||
harmonic coordinate functions can be evaluated at any point in the closure of the polygon.
|
||||
To illustrate such an evaluation, we compute the barycenter of each triangle and evaluate harmonic coordinates
|
||||
at this barycenter. Since harmonic coordinates can only be approximated, the used `Kernel` is inexact.
|
||||
|
||||
\cgalFigureBegin{terrain__example,terrain.png}
|
||||
\anchor hm_coord_example
|
||||
\cgalExample{Barycentric_coordinates_2/harmonic_coordinates.cpp}
|
||||
|
||||
|
||||
\subsection height_inter_example Terrain Modeling
|
||||
|
||||
This is an advanced example that illustrates how to use generalized barycentric coordinates
|
||||
for height interpolation with applications to terrain modeling. It also shows how to use
|
||||
a non-default traits class with our package instead of a `Kernel` traits class.
|
||||
Suppose we know the boundary of three-dimensional piece of terrain that can be represented
|
||||
as a polygon with several three-dimensional vertices, where the third dimension indicates
|
||||
the corresponding height. The task is to propagate the height from the known sample points
|
||||
on the boundary to the polygon's interior. This gives an approximate estimation of
|
||||
the terrain's surface in this region.
|
||||
|
||||
\anchor terrain_example_fig
|
||||
\cgalFigureBegin{terrain_example, terrain.svg}
|
||||
A 2D polygon with 50 vertices representing a piece of terrain with convex and concave parts. The height is not shown.
|
||||
\cgalFigureEnd
|
||||
|
||||
In this example we project a three-dimensional polygon orthogonally onto the two-dimensional plane using the class `CGAL::Projection_traits_xy_3`, triangulate its interior using the class `CGAL::Delaunay_mesher_2`, and compute mean value coordinates for all the obtained points with respect to all the polygon's vertices. Finally, we interpolate the height data from the polygon's boundary to its interior using the computed coordinates and the global interpolation function from the package \ref PkgInterpolation2 "2D and Surface Function Interpolation".
|
||||
In this example, we project a 3D polygon orthogonally onto the 2D plane using the class
|
||||
`CGAL::Projection_traits_xy_3`, triangulate its interior using the class `Delaunay_domain_2`,
|
||||
and compute mean value coordinates at the vertices of this triangulation with respect to the polygon vertices.
|
||||
Finally, we interpolate the height data from the polygon boundary to its interior
|
||||
using the computed coordinates and the global interpolation function from the
|
||||
package \ref chapinterpolation "2D and Surface Function Interpolation".
|
||||
|
||||
\cgalExample{Barycentric_coordinates_2/Terrain_height_modeling.cpp}
|
||||
\anchor terrain_example
|
||||
\cgalExample{Barycentric_coordinates_2/terrain_height_modeling.cpp}
|
||||
|
||||
As a result we get a smooth function inside the polygon that approximates the underlying terrain's surface.
|
||||
As a result, we get a smooth function inside the polygon that approximates the underlying terrain surface.
|
||||
|
||||
\cgalFigureBegin{terrain__inter__example,terrain_interpolated.png}
|
||||
\cgalFigureBegin{terrain_interpolation_example, terrain_interpolation.png}
|
||||
The interpolated data. The color bar represents the corresponding height.
|
||||
\cgalFigureEnd
|
||||
|
||||
\section gbc_degeneracies Degeneracies and Special Cases
|
||||
|
||||
\subsection shape_deform_example Shape Deformation
|
||||
|
||||
This is another advanced example that shows how to use generalized barycentric coordinates
|
||||
in order to deform a given 2D shape into another shape as shown in the figure below.
|
||||
Harmonic coordinates satisfy all the properties of barycentric coordinates for complicated
|
||||
concave polygons and hence this is our choice to perform a shape deformation. Note that
|
||||
even though harmonic coordinates are guaranteed to be positive inside a polygon, they
|
||||
do not guarantee a bijective mapping between the source and target shapes that is
|
||||
the target mesh can fold-over the target polygon after the mapping (see the little fold-over
|
||||
in the left shoulder of the target shape).
|
||||
|
||||
\cgalFigureBegin{shape_deformation_example, shape_deformation.svg}
|
||||
The shape on the left is deformed into the shape on the right. The zoom shows a fold-over
|
||||
in the left shoulder of the target shape where the red triangle goes over the polygon boundary.
|
||||
\cgalFigureEnd
|
||||
|
||||
\anchor deformation_example
|
||||
\cgalExample{Barycentric_coordinates_2/shape_deformation.cpp}
|
||||
|
||||
But despite the possible fold-overs, a similar technique can be used for image warping
|
||||
in 2D and character articulation in 3D. For example in 2D, we first enclose an image,
|
||||
which we want to deform, into a simple polygon so-called *cage*, we then
|
||||
bound each image pixel to this cage using barycentric coordinates, and finally deform
|
||||
this cage into a new one, which also deforms the underlying image, as shown
|
||||
in the figure below for harmonic coordinates.
|
||||
|
||||
\cgalFigureBegin{image_warping_example, image_warping.png}
|
||||
An image on the left is deformed into a new image on the right using a 2D concave polygon (grey)
|
||||
and harmonic coordinates computed at each image pixel with respect to the vertices of this polygon.
|
||||
\cgalFigureEnd
|
||||
|
||||
|
||||
\subsection aff_example Affine Coordinates
|
||||
|
||||
This is an example, where we show how a
|
||||
<a href="https://en.cppreference.com/w/cpp/language/lambda">lambda expression</a>
|
||||
can be used to define a model of generalized barycentric coordinates. To make this example
|
||||
useful, we implement affine generalized coordinates for a set of scattered points.
|
||||
The used `Kernel` is inexact.
|
||||
|
||||
\anchor aff_coord_example_fig
|
||||
\cgalFigureBegin{aff_example, aff_coord_example.svg}
|
||||
Example's point pattern.
|
||||
\cgalFigureEnd
|
||||
|
||||
\anchor aff_coord_example
|
||||
\cgalExample{Barycentric_coordinates_2/affine_coordinates.cpp}
|
||||
|
||||
|
||||
\subsection depr_example Deprecated Coordinates
|
||||
|
||||
This example illustrates how to use the deprecated API of this package.
|
||||
The used `Kernel` is inexact and the used coordinates are mean value coordinates.
|
||||
The result is identical to the one from \ref mv_coord_example "this example".
|
||||
|
||||
\anchor depr_coord_example
|
||||
\cgalExample{Barycentric_coordinates_2/deprecated_coordinates.cpp}
|
||||
|
||||
\note The headers `Segment_coordinates_2.h` and `Triangle_coordinates_2.h` are
|
||||
not capitalized in the new version that is they are named `segment_coordinates_2.h`
|
||||
and `triangle_coordinates_2.h`.
|
||||
|
||||
|
||||
\section gbc_degeneracies Edge Cases
|
||||
|
||||
Not all presented coordinates are general enough to handle any query point in the plane, that is
|
||||
why we highly recommend reading this section in order to learn what can be expected from
|
||||
each coordinate function. If you want to get more mathematical details about each coordinate
|
||||
function as well as the complete history and theory behind barycentric coordinates, you should
|
||||
read \cgalCite{cgal:bc:hs-gbcicg-17}. You can also read an overview
|
||||
<a href="https://www.anisimovdmitry.com/assets/files/phd_thesis_anisimov.pdf">here</a>
|
||||
(chapters 1 and 2).
|
||||
|
||||
|
||||
\anchor compute_seg_coord
|
||||
\subsection gbc_deg_segment_coordinates Segment Coordinates
|
||||
Segment coordinates can be computed exactly if an exact data type is chosen. The segment itself, with respect to which we compute coordinates, must be non-degenerate. If both conditions are satisfied, then the computation never fails. However, to compute coordinates, the user must be sure about the query point being exactly on the line \f$L\f$ supporting the segment. Since in many applications this is not the case, and a query point may lie very close but not exactly on this line, the class is also able to handle this situation.
|
||||
|
||||
\cgalFigureBegin{projection,projection.png}
|
||||
The segment coordinate function with respect to a given segment vertex is a linear
|
||||
function along the supporting line of this segment that grows from zero at the opposite
|
||||
vertex to one at the chosen vertex (see the figure below).
|
||||
|
||||
\cgalFigureBegin{seg_coord, seg_coord.svg}
|
||||
The segment coordinate function with respect to the vertex \f$v_0\f$.
|
||||
\cgalFigureEnd
|
||||
|
||||
Segment coordinates can be computed exactly if an exact number type is chosen.
|
||||
The segment itself, with respect to which we compute coordinates, must be non-degenerate.
|
||||
If both conditions are satisfied, then the computation never fails. However, to compute coordinates,
|
||||
the user must ensure that the query point lies exactly on the line \f$L\f$ supporting the segment.
|
||||
Since in many applications this is not the case, and a query point may lie very close but not exactly on this line,
|
||||
we provide a solution to remedy this situation.
|
||||
|
||||
\cgalFigureBegin{seg_coord_projection, seg_coord_projection.svg}
|
||||
The orthogonal projection \f$p'\f$ of the vector \f$p\f$ (green) onto the vector \f$q\f$ (red).
|
||||
\cgalFigureEnd
|
||||
|
||||
Suppose that some query point \f$v\f$ does not lie exactly on the line \f$L\f$, but is some distance \f$d\f$ away as shown in the figure above. If we want to compute the segment barycentric coordinate \f$b_1(v)\f$ with respect to the vertex \f$v_1\f$, we first find the orthogonal projection \f$p'\f$ of the vector \f$p\f$ onto the vector \f$q\f$ and then normalize it by the length of \f$q\f$. This gives the segment barycentric coordinate \f$b_1(v') = b_1(v)\f$ if \f$v\f$ lies exactly on the line.
|
||||
Suppose that some query point \f$v\f$ does not lie exactly on the line \f$L\f$,
|
||||
but is some distance \f$d\f$ away as shown in the figure above. If we want to compute
|
||||
the segment coordinate \f$b_1(v)\f$ with respect to the vertex \f$v_1\f$, we first find the
|
||||
orthogonal projection \f$p'\f$ of the vector \f$p\f$ onto the vector \f$q\f$ and
|
||||
then normalize it by the length of \f$q\f$. This yields the segment coordinate \f$b_1(v') = b_1(v)\f$
|
||||
if \f$v\f$ lies exactly on the line. The other segment coordinate \f$b_0(v')\f$ that is equal
|
||||
to \f$b_0(v)\f$ when \f$v\f$ is on the line \f$L\f$ is computed the same way but with the
|
||||
projection of the vector \f$\vec{vv_1}\f$.
|
||||
|
||||
\b Warning: do not abuse the feature described above because it does not give correct segment barycentric coordinates for the point \f$v\f$ but rather those for \f$v'\f$. Moreover, segment barycentric coordinates for a point \f$v\f$, which does not lie exactly on the line \f$L\f$, do not exist. But if the non-zero distance \f$d\f$ is due to some numerical instability when computing the location of the point \f$v\f$ or any other problem, which causes the point to be not exactly on the line, the final segment coordinates will be, at least approximately, correct.
|
||||
\b Warning: do not abuse the feature described above, because it does not yield correct
|
||||
segment coordinates for the point \f$v\f$ but rather those for \f$v'\f$. Moreover, segment
|
||||
coordinates for a point \f$v\f$, which does not lie exactly on the line \f$L\f$, do not exist.
|
||||
But if the non-zero distance \f$d\f$ is due to some numerical instability when computing the
|
||||
location of the point \f$v\f$ or any other problem, which causes the point to be not exactly on
|
||||
the line, the final segment coordinates will be, at least approximately, correct.
|
||||
|
||||
With inexact data types, the resulting coordinate values are correct up to the precision of the chosen type.
|
||||
With inexact number types, the resulting coordinate values are correct up to the precision of the chosen type.
|
||||
|
||||
|
||||
\anchor compute_tri_coord
|
||||
\subsection gbc_deg_triangular_coordinates Triangle Coordinates
|
||||
|
||||
These coordinates can be computed exactly if an exact data type is chosen, for any query point in the plane and with respect to any non-degenerate triangle. No special cases are handled. The computation always gives the correct result. The notion of correctness depends on the precision of the used data type. Note that for exterior points some coordinate values will be negative.
|
||||
The triangle coordinate function with respect to a given triangle vertex is a linear function
|
||||
that grows from zero along the opposite edge to one at the chosen vertex (see the figure below).
|
||||
|
||||
\cgalFigureBegin{tri_coord, tri_coord.svg}
|
||||
The triangle coordinate function with respect to the vertex \f$v_0\f$.
|
||||
\cgalFigureEnd
|
||||
|
||||
To compute the triangle coordinates of the query point \f$v\f$, we adopt the standard simple formula
|
||||
|
||||
<center>
|
||||
\f$b_i = \frac{A_i}{A}\f$ with \f$i = 0\dots 2\f$
|
||||
</center>
|
||||
|
||||
where \f$A_i\f$ is the signed area of the sub-triangle opposite to the
|
||||
vertex \f$i\f$ and \f$A\f$ is the total area of the triangle that is \f$A = A_0 + A_1 + A_2\f$
|
||||
(see the figure below).
|
||||
|
||||
\anchor tri_notations
|
||||
\cgalFigureBegin{tri_notations, tri_notations.svg}
|
||||
Notation for triangle coordinates.
|
||||
\cgalFigureEnd
|
||||
|
||||
These coordinates can be computed exactly if an exact number type is chosen, for any query point in the plane
|
||||
and with respect to any non-degenerate triangle. No special cases are handled. The computation always
|
||||
yields the correct result. The notion of correctness depends on the precision of the used number type.
|
||||
Note that for exterior points some coordinate values will be negative.
|
||||
|
||||
|
||||
\anchor compute_wp_coord
|
||||
\subsection gbc_deg_wachspress_coordinates Wachspress Coordinates
|
||||
Wachspress coordinates are well-defined in the closure of any <em>strictly convex polygon</em>. Therefore, for any query point from the polygon's closure with an exact data type, these coordinates are computed exactly and no false result is expected. For inexact data types, the resulting precision of the computation is due to the involved algorithm and chosen data type. In the following paragraph we discuss two available algorithms for computing Wachspress coordinates. One of them is `CGAL::Barycentric_coordinates::PRECISE`, the other is `CGAL::Barycentric_coordinates::FAST`.
|
||||
|
||||
Wachspress coordinates are well-defined in the closure of any <em>strictly convex polygon</em>.
|
||||
Therefore, when using an exact number type, for any query point from the polygon's closure,
|
||||
these coordinates are computed exactly and no false result is expected. For exterior query points,
|
||||
the coordinates can also be computed but not everywhere (see below for more details). For inexact number types,
|
||||
the resulting precision of the computation is due to the involved algorithm and a chosen number type.
|
||||
In the following paragraph, we discuss two available algorithms for computing Wachspress coordinates
|
||||
when an inexact number type is used. The chosen algorithm is specified by a computation policy
|
||||
`Barycentric_coordinates::Computation_policy_2`.
|
||||
|
||||
\anchor wp_polygon
|
||||
\cgalFigureBegin{wp__notations,wp_notations.png}
|
||||
\cgalFigureBegin{wp_notations, wp_notations.svg}
|
||||
Notation for Wachspress coordinates.
|
||||
\cgalFigureEnd
|
||||
|
||||
To compute Wachspress weights, we follow \cite cgal:bc:fhk-gcbcocp-06 and use the formula
|
||||
To compute Wachspress weights, we follow \cgalCite{cgal:bc:fhk-gcbcocp-06} and use the formula
|
||||
|
||||
<center>\f$w_i = \frac{C_i}{A_{i-1}A_i}\f$</center>
|
||||
<center>
|
||||
\f$w_i = \frac{C_i}{A_{i-1}A_i}\f$
|
||||
</center>
|
||||
|
||||
with \f$i = 1\dots n\f$ where \f$n\f$ is the number of the polygon's vertices. In order to compute the coordinates, we normalize these weights,
|
||||
with \f$i = 1\dots n\f$ where \f$n\f$ is the number of polygon vertices.
|
||||
In order to compute the coordinates, we normalize these weights,
|
||||
|
||||
<center>\f$b_i = \frac{w_i}{W^{wp}}\qquad\f$ with \f$\qquad W^{wp} = \sum_{j=1}^n w_j.\f$</center>
|
||||
<center>
|
||||
\f$b_i = \frac{w_i}{W^{wp}}\qquad\f$ with \f$\qquad W^{wp} = \sum_{j=1}^n w_j.\f$
|
||||
</center>
|
||||
|
||||
This formula becomes unstable when approaching the boundary of the polygon (\f$\approx 1.0e-10\f$ and closer). To fix the problem, we modify the weights \f$w_i\f$ as
|
||||
This formula becomes unstable when approaching the boundary of the polygon (\f$\approx 1.0e-10\f$ and closer).
|
||||
To fix the problem, we modify the weights \f$w_i\f$ as
|
||||
|
||||
<center>\f$\bar{w}_i = C_i\prod_{j\not=i-1,i} A_j\f$.</center>
|
||||
<center>
|
||||
\f$\bar{w}_i = C_i\prod_{j\not=i-1,i} A_j\f$.
|
||||
</center>
|
||||
|
||||
After the normalization as above, this gives us the precise algorithm to compute Wachspress coordinates but with \f$O(n^2)\f$ performance only. The fast \f$O(n)\f$ algorithm uses the standard weights \f$w_i\f$. Note that mathematically this modification does not change the coordinates.
|
||||
After the above normalization, this gives us the precise algorithm to compute Wachspress coordinates
|
||||
but with \f$O(n^2)\f$ performance only. The max speed \f$O(n)\f$ algorithm uses the standard
|
||||
weights \f$w_i\f$. Note that mathematically this modification does not change the coordinates. One should
|
||||
be cautious when using the unnormalized Wachspress weights. In that case, you must choose the
|
||||
\f$O(n)\f$ type.
|
||||
|
||||
It is known that for strictly convex polygons the denominator's zero set of the Wachspress coordinates (\f$W^{wp} = 0~\f$) is a curve, which (in many cases) lies quite far away from the polygon. Speaking precisely, it interpolates the intersection points of the continuations of the polygon's edges. Therefore, the computation of Wachspress coordinates outside the polygon is possible only at points that do not belong to this curve.
|
||||
It is known that for strictly convex polygons the denominator's zero set of the
|
||||
Wachspress coordinates (\f$W^{wp} = 0~\f$) is a curve, which (in many cases) lies quite
|
||||
far away from the polygon. More specifically, it interpolates the intersection points of
|
||||
the supporting lines of the polygon edges. Therefore, the computation of Wachspress coordinates
|
||||
outside the polygon is possible only at points that do not belong to this curve.
|
||||
|
||||
\cgalFigureBegin{zero__set,zero_set.png}
|
||||
\cgalFigureBegin{wp_zero_set, wp_zero_set.svg}
|
||||
Zero set (red) of the Wachspress coordinates' denominator \f$W^{wp}\f$ for a non-regular hexagon.
|
||||
\cgalFigureEnd
|
||||
|
||||
\b Warning: we do not recommend to use Wachspress coordinates for exterior points!
|
||||
\b Warning: we do not recommend using Wachspress coordinates for exterior points!
|
||||
|
||||
|
||||
\anchor compute_dh_coord
|
||||
\subsection gbc_deg_discrete_harmonic_coordinates Discrete Harmonic Coordinates
|
||||
|
||||
Discrete harmonic coordinates have the same requirements as Wachspress coordinates. They are well-defined in the closure of any <em>strictly convex polygon</em> and, if an exact data type is chosen, they are computed exactly. But, unlike Wachspress basis functions, these coordinates are not necessarily positive. In particular, the weight \f$w_i\f$ is positive if and only if \f$\alpha+\beta < \pi\f$ (see the figure below for notation). For inexact data types, the precision of the computation is due to the involved algorithm and chosen data type. Again, we describe two algorithms to compute the coordinates: one is precise and one is fast.
|
||||
Discrete harmonic coordinates have the same requirements as Wachspress coordinates.
|
||||
They are well-defined in the closure of any <em>strictly convex polygon</em> and,
|
||||
if an exact number type is chosen, they are computed exactly. However, and unlike Wachspress basis functions,
|
||||
these coordinates are not necessarily positive. In particular, the weight \f$w_i\f$ is positive
|
||||
if and only if \f$\alpha+\beta < \pi\f$ (see the figure below for notation). For inexact number types,
|
||||
the precision of the computation is due to the involved algorithm and a chosen number type. Again,
|
||||
we describe two algorithms to compute the coordinates when an inexact number type is used:
|
||||
one is of max precision and one is of max speed.
|
||||
|
||||
\anchor dh_polygon
|
||||
\cgalFigureBegin{dh__notations,dh_notations.png}
|
||||
\cgalFigureBegin{dh_notations, dh_notations.svg}
|
||||
Notation for discrete harmonic coordinates.
|
||||
\cgalFigureEnd
|
||||
|
||||
To compute discrete harmonic weights, we follow \cite cgal:bc:fhk-gcbcocp-06 and use the formula
|
||||
To compute discrete harmonic weights, we follow \cgalCite{cgal:bc:fhk-gcbcocp-06} and use the formula
|
||||
|
||||
<center>\f$w_i = \frac{r_{i+1}^2A_{i-1}-r_i^2B_i+r_{i-1}^2A_i}{A_{i-1}A_i}\f$</center>
|
||||
<center>
|
||||
\f$w_i = \frac{r_{i+1}^2A_{i-1}-r_i^2B_i+r_{i-1}^2A_i}{A_{i-1}A_i}\f$
|
||||
</center>
|
||||
|
||||
with \f$i = 1\dots n\f$ where \f$n\f$ is the number of the polygon's vertices. In order to compute the coordinates, we normalize these weights,
|
||||
with \f$i = 1\dots n\f$ where \f$n\f$ is the number of polygon vertices.
|
||||
In order to compute the coordinates, we normalize these weights,
|
||||
|
||||
<center>\f$b_i = \frac{w_i}{W^{dh}}\qquad\f$ with \f$\qquad W^{dh} = \sum_{j=1}^n w_j.\f$</center>
|
||||
<center>
|
||||
\f$b_i = \frac{w_i}{W^{dh}}\qquad\f$ with \f$\qquad W^{dh} = \sum_{j=1}^n w_j.\f$
|
||||
</center>
|
||||
|
||||
This formula becomes unstable when approaching the boundary of the polygon (\f$\approx 1.0e-10\f$ and closer). To fix the problem, similarly to the previous subsection, we modify the weights \f$w_i\f$ as
|
||||
This formula becomes unstable when approaching the boundary of the polygon (\f$\approx 1.0e-10\f$ and closer).
|
||||
To fix the problem, similarly to the previous subsection, we modify the weights \f$w_i\f$ as
|
||||
|
||||
<center>\f$\bar{w}_i = (r_{i+1}^2A_{i-1}-r_i^2B_i+r_{i-1}^2A_i)\prod_{j\not=i-1,i} A_j\f$.</center>
|
||||
<center>
|
||||
\f$\bar{w}_i = (r_{i+1}^2A_{i-1}-r_i^2B_i+r_{i-1}^2A_i)\prod_{j\not=i-1,i} A_j\f$.
|
||||
</center>
|
||||
|
||||
After the normalization as above, this gives the precise algorithm to compute discrete harmonic coordinates but with \f$O(n^2)\f$ performance only. The fast \f$O(n)\f$ algorithm uses the standard weights \f$w_i\f$. Again, mathematically this modification does not change the coordinates.
|
||||
After the above normalization, this yields the precise algorithm to compute discrete harmonic coordinates
|
||||
but with \f$O(n^2)\f$ performance only. The max speed \f$O(n)\f$ algorithm uses the standard
|
||||
weights \f$w_i\f$. Again, mathematically this modification does not change the coordinates,
|
||||
one should be cautious when using the unnormalized discrete harmonic weights. In that case,
|
||||
you must choose the \f$O(n)\f$ type.
|
||||
|
||||
\b Warning: as for Wachspress coordinates, we do not recommend to use discrete harmonic coordinates for exterior points because the curve \f$W^{dh} = 0\f$ may have several components, and one of them interpolates the polygon's vertices. However, if you are sure that the query point does not belong to this curve, you can compute the coordinates as shown in \ref dh_example " this example".
|
||||
\b Warning: as for Wachspress coordinates, we do not recommend using discrete harmonic coordinates
|
||||
for exterior points, because the curve \f$W^{dh} = 0\f$ may have several components,
|
||||
and one of them interpolates the polygon vertices. However, if you are sure that
|
||||
the query point does not belong to this curve, you can compute the coordinates
|
||||
as shown in \ref dh_example " this example".
|
||||
|
||||
|
||||
\anchor compute_mv_coord
|
||||
\subsection gbc_deg_mean_value_coordinates Mean Value Coordinates
|
||||
|
||||
Unlike the previous coordinates, mean value coordinates cannot be computed exactly due to an inevitable square root operation. Although, if an exact data type is used, the default precision of the computation depends only on two \cgal functions: `CGAL::to_double()` and `CGAL::sqrt()`. On the other hand, mean value coordinates are well-defined everywhere in the plane for any simple polygon. In addition, if your traits class provides a more precise version of the square root function, the final precision of the computation with exact data types will depend only on the precision of that function.
|
||||
Unlike the previous coordinates, mean value coordinates cannot be computed exactly due to
|
||||
an inevitable square root operation. Although, if an exact number type is used, the default precision
|
||||
of the computation depends only on two \cgal functions: `CGAL::to_double()` and `CGAL::sqrt()`.
|
||||
It is worth saying that providing a number type that supports exact or nearly exact computation
|
||||
of the square root is possible, however since such types are usually impractical due to the
|
||||
large overhead, the conversion to a floating-point format above is always effective. On the other hand,
|
||||
mean value coordinates are well-defined everywhere in the plane for any simple polygon. In addition,
|
||||
if your traits class provides a more precise version of the square root function, the final precision
|
||||
of the computation with exact number types will depend only on the precision of that function.
|
||||
|
||||
\anchor mv_polygon
|
||||
\cgalFigureBegin{mv__notations,mv_notations.png}
|
||||
\cgalFigureBegin{mv_notations, mv_notations.svg}
|
||||
Notation for mean value coordinates.
|
||||
\cgalFigureEnd
|
||||
|
||||
For these coordinates we also have two algorithms: one is precise and one is fast. The first one works everywhere in the plane, and the precision of the computation depends only on the chosen data type, including the remarks above. This algorithm is based on the following weight formula from \cite cgal:bc:f-wmvc-14
|
||||
For these coordinates, we provide two algorithms: one is of max precision and one is of max speed.
|
||||
The first one works everywhere in the plane, and the precision of the computation depends only
|
||||
on the chosen number type, including the remarks above. This algorithm is based on the following weight
|
||||
formula from \cgalCite{cgal:bc:f-wmvc-14}
|
||||
|
||||
<center>\f$w_i = \sigma_i\bar{w}_i\qquad\f$ with \f$\qquad\bar{w}_i = (r_{i-1}r_{i+1}-d_{i-1}d_{i+1})^{1/2}\prod_{j\not= i-1,i}(r_jr_{j+1} + d_jd_{j+1})^{1/2}\qquad\f$ where \f$\qquad r_i = \|d_i\|.\f$</center>
|
||||
<center>
|
||||
\f$w_i = \sigma_i\bar{w}_i\qquad\f$ with \f$\qquad\bar{w}_i = (r_{i-1}r_{i+1}-d_{i-1}d_{i+1})^{1/2}\prod_{j\not= i-1,i}(r_jr_{j+1} + d_jd_{j+1})^{1/2}\qquad\f$
|
||||
where \f$\qquad r_i = \|d_i\|.\f$
|
||||
</center>
|
||||
|
||||
Since \f$\bar{w}_i\f$ is always positive, we have to append to it the proper sign \f$\sigma_i\f$ of the signed mean value weight, which can be found efficiently (see the figures below). Basically, this weight is always positive to the left of the red piecewise linear curve, and it is negative to the right of this curve, moving in anticlockwise direction.
|
||||
Since \f$\bar{w}_i\f$ is always positive, we must append to it the proper sign \f$\sigma_i\f$
|
||||
of the signed mean value weight, which can be found efficiently (see the figures below).
|
||||
This weight is always positive to the left of the red piecewise linear curve,
|
||||
and it is negative to the right of this curve, moving in the counterclockwise direction.
|
||||
|
||||
\cgalFigureBegin{mv__weight__signs,mv_weight_signs_convex.png,mv_weight_signs_concave.png}
|
||||
Signs of the mean value weight \f$w_i\f$ depending on the region with respect to a convex polygon \f$P\f$ and a concave polygon \f$P'\f$.
|
||||
\cgalFigureBegin{mv_weight_signs, mv_weight_signs.svg}
|
||||
Signs of the mean value weight \f$w_i\f$ depending on the region with respect to a
|
||||
convex polygon \f$P\f$ and a concave polygon \f$P'\f$.
|
||||
\cgalFigureEnd
|
||||
|
||||
After the normalization of these weights as before
|
||||
|
||||
<center>\f$b_i = \frac{w_i}{W^{mv}}\qquad\f$ with \f$\qquad W^{mv} = \sum_{j=1}^n w_j\f$</center>
|
||||
<center>
|
||||
\f$b_i = \frac{w_i}{W^{mv}}\qquad\f$ with \f$\qquad W^{mv} = \sum_{j=1}^n w_j\f$
|
||||
</center>
|
||||
|
||||
we obtain the precise \f$O(n^2)\f$ algorithm. The fast O(n) algorithm computes the weights \f$w_i\f$ using the pseudocode from <a href="https://www.inf.usi.ch/hormann/nsfworkshop/presentations/Hormann.pdf">here</a>. These weights
|
||||
we obtain the max precision \f$O(n^2)\f$ algorithm. The max speed O(n) algorithm computes the
|
||||
weights \f$w_i\f$ using the pseudocode from <a href="https://www.inf.usi.ch/hormann/nsfworkshop/presentations/Hormann.pdf">here</a>.
|
||||
These weights
|
||||
|
||||
<center>\f$w_i = \frac{t_{i-1} + t_i}{r_i}\qquad\f$ with \f$\qquad t_i = \frac{\text{det}(d_i, d_{i+1})}{r_ir_{i+1} + d_id_{i+1}}\f$</center>
|
||||
<center>
|
||||
\f$w_i = \frac{t_{i-1} + t_i}{r_i}\qquad\f$
|
||||
with \f$\qquad t_i = \frac{\text{det}(d_i, d_{i+1})}{r_ir_{i+1} + d_id_{i+1}}\f$
|
||||
</center>
|
||||
|
||||
are also normalized. Note that they are unstable if a query point is closer than \f$\approx 1.0e-10\f$
|
||||
to the polygon boundary, similarly to Wachspress and discrete harmonic coordinates and
|
||||
one should be cautious when using the unnormalized mean value weights. In that case, you must choose the
|
||||
\f$O(n)\f$ type.
|
||||
|
||||
|
||||
\anchor compute_hm_coord
|
||||
\subsection gbc_deg_harmonic_coordinates Harmonic Coordinates
|
||||
|
||||
The harmonic coordinates are computed by solving the Laplace equation
|
||||
|
||||
<center>
|
||||
\f$\Delta \boldsymbol{b} = \boldsymbol{0}\f$
|
||||
</center>
|
||||
|
||||
subject to suitable Dirichlet boundary conditions. Harmonic coordinates are the only coordinates
|
||||
in this package, which are guaranteed to be non-negative in the closure of any simple polygon and
|
||||
satisfy all properties of barycentric coordinates, however such desirable properties come with the fact
|
||||
that these coordinates are well-defined only inside a polygon. If an exterior query point is provided,
|
||||
its coordinates are set to zero.
|
||||
|
||||
Another disadvantage of these coordinates is that they cannot be computed
|
||||
exactly, because harmonic coordinates do not have a simple closed-form expression and
|
||||
must be approximated. The common way to approximate these coordinates is
|
||||
by discretizing over the space of piecewise linear functions with respect to
|
||||
a triangulation of the polygon. The denser triangulation of the interior part of
|
||||
the polygon, the better approximation of the coordinates. To get a high quality
|
||||
approximation of the coordinates, the user should provide a rather dense partition
|
||||
of the polygon's interior domain that in turn leads to larger running times when
|
||||
computing the coordinates.
|
||||
|
||||
\anchor terrain_triangulation_fig
|
||||
\cgalFigureBegin{terrain_triangulation, terrain_triangulation.svg}
|
||||
Sparse triangulation of the polygon's interior domain (left): smaller running times,
|
||||
lower coordinates quality; dense triangulation (right): larger running times,
|
||||
higher coordinates quality.
|
||||
\cgalFigureEnd
|
||||
|
||||
From all this follows, that any exact `Kernel` will be rejected and it is not possible
|
||||
to compute analytic harmonic weights. However, once the coordinates are computed at the
|
||||
vertices of the triangulation, they can be evaluated analytically at any interior
|
||||
query point. For evaluation, we first locate a triangle that contains the query point
|
||||
and then linearly interpolate harmonic coordinates defined at the vertices of this
|
||||
triangle to the query point with the help of \ref gbc_deg_triangular_coordinates "triangle coordinates" as
|
||||
|
||||
<center>
|
||||
\f$b_i = b_0^{tr} b_i^0 + b_1^{tr} b_i^1 + b_2^{tr} b_i^2\f$
|
||||
</center>
|
||||
|
||||
with \f$i = 1\dots n\f$, where \f$n\f$ is the number of polygon vertices, \f$b_{0}^{tr}\f$,
|
||||
\f$b_{1}^{tr}\f$, and \f$b_{2}^{tr}\f$ are the triangle coordinates of the query point with
|
||||
respect the three vertices of the located triangle, and \f$b_i^{0}\f$, \f$b_i^{1}\f$, and \f$b_i^{2}\f$
|
||||
are the harmonic coordinates pre-computed at the triangle vertices.
|
||||
|
||||
are also normalized. Note that they are unstable if a query point is closer than \f$\approx 1.0e-10\f$ to the polygon's boundary, similarly to Wachspress and discrete harmonic coordinates.
|
||||
|
||||
\section gbc_performance Performance
|
||||
|
||||
Apart from the most important requirement on barycentric coordinates to be as precise as possible, it is very important for them to be as fast as possible to evaluate. These coordinates are used in many applications where they must be computed for millions of points and, thus, the real time usage of coordinates is crucial. When writing the code, we tried to fulfill this important requirement, and in this section we present a few results about the computation times of the implemented coordinates.
|
||||
We strive for robustness and efficiency at the same time. Efficiency is especially important.
|
||||
These coordinates are used in many applications where they must be computed for millions of points
|
||||
and, thus, the real time computation of coordinates has been made possible. In this section,
|
||||
we present next the computation runtimes of the implemented algorithms.
|
||||
|
||||
The structure of the speed test that we ran for all functions consists of computing coordinate values (or weights) at >= 1 million strictly interior points with respect to some polygon (or triangle, or segment). At each iteration of the loop we create a query point, pass it to the function, and compute all the related coordinates. We run this loop 10 times in a row, and the time presented in the log-log scale plot at the end of the section is the arithmetic mean of all trials.
|
||||
The structure of the speed test that we use to evaluate the running times consists
|
||||
of computing coordinate values (or weights) at >= 1 million strictly interior points
|
||||
with respect to a polygon (or triangle, or segment). At each iteration of the loop,
|
||||
we create a query point and compute its coordinates. The time presented in the log-log scale plot
|
||||
at the end of the section is the arithmetic mean of all trials in the loop of 10 iterations.
|
||||
The time presented in the plot is for analytic coordinates only since harmonic coordinates
|
||||
of a reasonable (application-dependent) quality are substantially slower to compute and
|
||||
cannot be fairly compared to the analytic coordinate functions.
|
||||
|
||||
A typical example of this performance test for triangle coordinates with reduced number of query points can be found below. This example also illustrates how to construct an iterator and pass it to the class. In this example we create an iterator that writes coordinate values for each new query point over coordinate values of the previous point in the fixed-size standard C++ array, so that memory is allocated only once.
|
||||
The time to compute coordinates depends on many factors such as memory allocation, input kernel, output container,
|
||||
number of points, etc. In our tests, we used the most standard C++ and \cgal features with minimum memory allocation.
|
||||
Therefore, the final time presented is the average time that can be expected without deep optimization
|
||||
but still with efficient memory allocation. It also means that it may vary depending on the usage of the package.
|
||||
|
||||
\cgalExample{Barycentric_coordinates_2/Triangle_coordinates_speed_test.cpp}
|
||||
To benchmark analytic coordinates, we used a MacBook Pro 2011 with 2 GHz Intel Core i7 processor (2 cores)
|
||||
and 8 GB 1333 MHz DDR3 memory. The installed operating system was OS X 10.9 Maverick.
|
||||
The resulting timings for all closed-form coordinates can be found in the figure below.
|
||||
|
||||
The time to compute coordinates depends on many factors such as memory allocation, input kernel, output container, number of points, etc. In our tests we used the most standard C++ and \cgal features with minimum memory allocation. Therefore, the final time presented is the average time that can be expected without deep optimization but still with efficient memory allocation. It also means that it may vary depending on the usage of the package.
|
||||
|
||||
For all tests we used a MacBook Pro 2011 with 2 GHz Intel Core i7 processor (2 cores) and 8 GB 1333 MHz DDR3 memory. The installed operating system was OS X 10.9 Maverick. In order to compile the speed test suite, we used the Clang 5.0 64bit compiler. The resulting timings can be found in the figure below.
|
||||
|
||||
\cgalFigureBegin{time,time.png}
|
||||
Time in seconds to compute \f$n\f$ coordinate values for a polygon with \f$n\f$ vertices at 1 million points with the fast \f$O(n)\f$ algorithms (dashed) and the slow \f$0(n^2)\f$ algorithms (solid) for Wachspress (blue), discrete harmonic (red), and mean value (green) coordinates.
|
||||
\cgalFigureBegin{analytic_timings, analytic_timings.png}
|
||||
Time in seconds to compute \f$n\f$ coordinate values for a polygon with \f$n\f$ vertices
|
||||
at 1 million query points with the max speed \f$O(n)\f$ algorithms (dashed) and
|
||||
the max precision \f$0(n^2)\f$ algorithms (solid) for Wachspress (blue), discrete
|
||||
harmonic (red), and mean value (green) coordinates.
|
||||
\cgalFigureEnd
|
||||
|
||||
From the figure above it is easy to see that the \f$O(n^2)\f$ algorithm is as fast as the \f$O(n)\f$ algorithm if we have a polygon with a small number of vertices. But as the number of vertices is increased, the linear algorithm outperforms the squared one, as expected. One of the reasons for this behaviour is that for a small number of vertices the multiplications for \f$n-2\f$ elements inside the \f$O(n^2)\f$ algorithm with the fast \f$O(n)\f$ algorithms (dashed) and the slow \f$O(n^2)\f$ algorithms (solid) take almost the same time as the corresponding division in the \f$O(n)\f$ algorithm. For a polygon with many vertices this multiplication is much slower.
|
||||
From the figure above we observe that the \f$O(n^2)\f$ algorithm is as fast
|
||||
as the \f$O(n)\f$ algorithm if we have a polygon with a small number of vertices.
|
||||
But as the number of vertices is increased, the linear algorithm outperforms the squared one,
|
||||
as expected. One of the reasons for this behavior is that for a small number of vertices
|
||||
the multiplications of \f$n-2\f$ elements inside the \f$O(n^2)\f$ algorithm take almost the
|
||||
same time as the corresponding divisions in the \f$O(n)\f$ algorithm. For a polygon with
|
||||
many vertices, these multiplications are substantially slower.
|
||||
|
||||
\section gbc_implementation Implementation Details
|
||||
To benchmark harmonic coordinates, we used a MacBook Pro 2018 with 2.2 GHz Intel Core i7 processor (6 cores)
|
||||
and 32 GB 2400 MHz DDR4 memory. The installed operating system was OS X 10.15 Catalina.
|
||||
The average time to compute harmonic coordinates in the loop of 10 iterations can be found in the tables below.
|
||||
|
||||
The generic design of the package was developed in 2013 by Dmitry Anisimov and David Bommes with many useful comments by Kai Hormann and Pierre Alliez. The package consists of 6 classes, 2 enumerations, and one namespace. Appropriate iterators are used to provide an efficient access to data and to pass them to one of the generic algorithms for computing coordinates. Once instantiated for a polygon (triangle, segment), the coordinates can be computed multiple times for different query points with respect to all the vertices of the provided polygon (triangle, segment). All the classes are fully templated and have a simple and similar design. In particular, we follow the same naming convention for all functions. Yet, the number of functions can differ from one class to another.
|
||||
The first table shows how the time to compute the coordinates on a unit square depends on the number of
|
||||
triangulation vertices. We show separately the time to setup the matrix, factorize it, and solve it
|
||||
with respect to the four vertices of the unit square.
|
||||
|
||||
The implemented algorithms for computing coordinates do not depend on a particular kernel, and all the coordinates can be computed exactly, if an exact kernel is used, apart from mean value coordinates. The latter coordinates involve a square root operation, which results in a slightly worse precision with exact data types due to temporal conversion into a floating point type. The computed coordinates can be stored in an arbitrary container if an appropriate <a href="https://en.cppreference.com/w/cpp/named_req/OutputIterator">output iterator</a> is provided.
|
||||
<table class="markdownTable" align="center">
|
||||
<tr class="markdownTableHead">
|
||||
<th class="markdownTableHeadCenter">Number of queries (approx.)</th>
|
||||
<th class="markdownTableHeadCenter">Setup (in seconds)</th>
|
||||
<th class="markdownTableHeadCenter">Factorize (in seconds)</th>
|
||||
<th class="markdownTableHeadCenter">Solve (in seconds)</th>
|
||||
<th class="markdownTableHeadCenter">Total (in seconds)</th>
|
||||
</tr>
|
||||
<tr class="markdownTableBody">
|
||||
<td class="markdownTableBodyCenter">100</td>
|
||||
<td class="markdownTableBodyCenter">0.000056</td>
|
||||
<td class="markdownTableBodyCenter">0.000099</td>
|
||||
<td class="markdownTableBodyCenter">0.000015</td>
|
||||
<td class="markdownTableBodyCenter">0.000170</td>
|
||||
</tr>
|
||||
<tr class="markdownTableBody">
|
||||
<td class="markdownTableBodyCenter">500</td>
|
||||
<td class="markdownTableBodyCenter">0.000266</td>
|
||||
<td class="markdownTableBodyCenter">0.000574</td>
|
||||
<td class="markdownTableBodyCenter">0.000064</td>
|
||||
<td class="markdownTableBodyCenter">0.000904</td>
|
||||
</tr>
|
||||
<tr class="markdownTableBody">
|
||||
<td class="markdownTableBodyCenter">1,000</td>
|
||||
<td class="markdownTableBodyCenter">0.000509</td>
|
||||
<td class="markdownTableBodyCenter">0.001194</td>
|
||||
<td class="markdownTableBodyCenter">0.000147</td>
|
||||
<td class="markdownTableBodyCenter">0.001850</td>
|
||||
</tr>
|
||||
<tr class="markdownTableBody">
|
||||
<td class="markdownTableBodyCenter">25,000</td>
|
||||
<td class="markdownTableBodyCenter">0.014749</td>
|
||||
<td class="markdownTableBodyCenter">0.071152</td>
|
||||
<td class="markdownTableBodyCenter">0.008191</td>
|
||||
<td class="markdownTableBodyCenter">0.094092</td>
|
||||
</tr>
|
||||
<tr class="markdownTableBody">
|
||||
<td class="markdownTableBodyCenter">50,000</td>
|
||||
<td class="markdownTableBodyCenter">0.034255</td>
|
||||
<td class="markdownTableBodyCenter">0.184237</td>
|
||||
<td class="markdownTableBodyCenter">0.018166</td>
|
||||
<td class="markdownTableBodyCenter">0.236658</td>
|
||||
</tr>
|
||||
<tr class="markdownTableBody">
|
||||
<td class="markdownTableBodyCenter">100,000</td>
|
||||
<td class="markdownTableBodyCenter">0.065117</td>
|
||||
<td class="markdownTableBodyCenter">0.543177</td>
|
||||
<td class="markdownTableBodyCenter">0.044088</td>
|
||||
<td class="markdownTableBodyCenter">0.652382</td>
|
||||
</tr>
|
||||
<tr class="markdownTableBody">
|
||||
<td class="markdownTableBodyCenter">500,000</td>
|
||||
<td class="markdownTableBodyCenter">0.576530</td>
|
||||
<td class="markdownTableBodyCenter">7.697143</td>
|
||||
<td class="markdownTableBodyCenter">0.310765</td>
|
||||
<td class="markdownTableBodyCenter">8.584438</td>
|
||||
</tr>
|
||||
<tr class="markdownTableBody">
|
||||
<td class="markdownTableBodyCenter">1,000,000</td>
|
||||
<td class="markdownTableBodyCenter">1.295163</td>
|
||||
<td class="markdownTableBodyCenter">26.76945</td>
|
||||
<td class="markdownTableBodyCenter">0.737372</td>
|
||||
<td class="markdownTableBodyCenter">28.80199</td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
It is worth noting that the class `CGAL::Barycentric_coordinates::Segment_coordinates_2` is used to compute generalized barycentric coordinates along the polygon's boundary. Hence, one can use the trick for segment coordinates from Section \ref gbc_degeneracies if one is convinced that a point must lie exactly on the polygon's boundary but due to some numerical instabilities it does not.
|
||||
The same results can be seen in the figure.
|
||||
|
||||
The package is implemented in a way that later, if needed, other two-dimensional generalized barycentric coordinates can be easily added to this package.
|
||||
|
||||
\section gbc_theory Theory of 2D Generalized Barycentric Coordinates
|
||||
|
||||
In 1827, the German mathematician and theoretical astronomer <a href="https://en.wikipedia.org/wiki/August_Ferdinand_Möbius">August Ferdinand Möbius</a> (1790--1868) proposed a method \cite cgal:bc:m-dbc-27 to find coordinates of a point in the plane with respect to the vertices of a triangle. These coordinates are called <a href="http://mathworld.wolfram.com/BarycentricCoordinates.html">triangle barycentric coordinates</a> (sometimes <a href="https://en.wikipedia.org/wiki/Barycentric_coordinate_system">area coordinates</a>), and they are widely used in a variety of applications. Some of these applications are linear interpolation over a triangle and a triangle inclusion test. The first one is used for so-called <a href="https://en.wikipedia.org/wiki/Shading">shading</a>, and the second one arises in the <a href="https://en.wikipedia.org/wiki/Rasterization">rasterization</a> step when an image in vector graphics format needs to be converted into a raster image.
|
||||
|
||||
Triangle barycentric coordinates have many important properties, including \em constant and <em>linear precision</em>, <em> the Lagrange property</em>, and <em>positivity inside a triangle</em>. These properties make these coordinates a unique tool in many scientific fields. If we restrict triangle coordinates to one of the edges of a triangle and its supporting line, we get barycentric coordinates with respect to a segment and call them \ref compute_seg_coord "segment coordinates".
|
||||
|
||||
Let us show a couple of plots for the coordinates described above. To plot segment coordinates, we take a line \f$y = 0.4\f$ and define \ref fig__seg__example "a segment" \f$[v_0, v_1]\f$ on this line. Then we sample this segment and compute segment coordinates for all the sample points. If we plot the segment coordinate function at all the defined points with respect to the vertex \f$v_1\f$, we get the blue line depicted in the figure below. It grows from zero at the vertex \f$v_0\f$ to one at the vertex \f$v_1\f$.
|
||||
|
||||
\cgalFigureBegin{seg__coord__interp,seg__coord__interp.png}
|
||||
Segment coordinates (blue) for all the segment points (green) with respect to the vertex \f$v_1 = (2.0,\ 0.4)\f$.
|
||||
\cgalFigureBegin{hm_4_bench, hm_4_bench.svg}
|
||||
Time in seconds to setup (red), factorize (green), and solve (blue) for harmonic
|
||||
coordinate values with respect to a unit square.
|
||||
\cgalFigureEnd
|
||||
|
||||
If we want to plot triangle coordinates, we follow a similar approach. We take \ref fig__tri__example "a triangle" \f$[v_0, v_1, v_2]\f$ in the plane and sample its interior and boundary with a number of points. Once we have this sampling, we plot one of the triangle coordinate functions (here with respect to the third vertex of the triangle) at all the defined sample points. Likewise, we can plot the coordinate function with respect to the first or second vertex. The resulting function is linear (shown in the figure below) that grows from zero along the first edge \f$[v_0, v_1]\f$ to one at the chosen vertex \f$v_2\f$.
|
||||
The second table shows how the time to compute the coordinates for 100k queries depends on the number of
|
||||
the polygon vertices. We show separately the time to setup the matrix, factorize it, and solve it
|
||||
with respect to the \f$n\f$ vertices of the polygon. It can be seen that, unlike in the
|
||||
first table, the time to factorize the matrix here stays constant.
|
||||
|
||||
\cgalFigureBegin{tri__coord__interp,tri__coord__interp.png}
|
||||
Triangle coordinates with respect to \f$v_2 = (1.0,\ 2.0)\f$. The color bar indicates the range of values for the chosen coordinate.
|
||||
<table class="markdownTable" align="center">
|
||||
<tr class="markdownTableHead">
|
||||
<th class="markdownTableHeadCenter">Number of vertices (approx.)</th>
|
||||
<th class="markdownTableHeadCenter">Setup (in seconds)</th>
|
||||
<th class="markdownTableHeadCenter">Factorize (in seconds)</th>
|
||||
<th class="markdownTableHeadCenter">Solve (in seconds)</th>
|
||||
<th class="markdownTableHeadCenter">Total (in seconds)</th>
|
||||
</tr>
|
||||
<tr class="markdownTableBody">
|
||||
<td class="markdownTableBodyCenter">5</td>
|
||||
<td class="markdownTableBodyCenter">0.083444</td>
|
||||
<td class="markdownTableBodyCenter">0.631823</td>
|
||||
<td class="markdownTableBodyCenter">0.059827</td>
|
||||
<td class="markdownTableBodyCenter">0.775094</td>
|
||||
</tr>
|
||||
<tr class="markdownTableBody">
|
||||
<td class="markdownTableBodyCenter">10</td>
|
||||
<td class="markdownTableBodyCenter">0.060294</td>
|
||||
<td class="markdownTableBodyCenter">0.450534</td>
|
||||
<td class="markdownTableBodyCenter">0.094583</td>
|
||||
<td class="markdownTableBodyCenter">0.605411</td>
|
||||
</tr>
|
||||
<tr class="markdownTableBody">
|
||||
<td class="markdownTableBodyCenter">25</td>
|
||||
<td class="markdownTableBodyCenter">0.062760</td>
|
||||
<td class="markdownTableBodyCenter">0.478683</td>
|
||||
<td class="markdownTableBodyCenter">0.254953</td>
|
||||
<td class="markdownTableBodyCenter">0.796396</td>
|
||||
</tr>
|
||||
<tr class="markdownTableBody">
|
||||
<td class="markdownTableBodyCenter">50</td>
|
||||
<td class="markdownTableBodyCenter">0.097359</td>
|
||||
<td class="markdownTableBodyCenter">0.492233</td>
|
||||
<td class="markdownTableBodyCenter">0.539654</td>
|
||||
<td class="markdownTableBodyCenter">1.129246</td>
|
||||
</tr>
|
||||
<tr class="markdownTableBody">
|
||||
<td class="markdownTableBodyCenter">100</td>
|
||||
<td class="markdownTableBodyCenter">0.129487</td>
|
||||
<td class="markdownTableBodyCenter">0.450771</td>
|
||||
<td class="markdownTableBodyCenter">1.152544</td>
|
||||
<td class="markdownTableBodyCenter">1.732802</td>
|
||||
</tr>
|
||||
<tr class="markdownTableBody">
|
||||
<td class="markdownTableBodyCenter">500</td>
|
||||
<td class="markdownTableBodyCenter">0.430694</td>
|
||||
<td class="markdownTableBodyCenter">0.460321</td>
|
||||
<td class="markdownTableBodyCenter">6.620061</td>
|
||||
<td class="markdownTableBodyCenter">7.511076</td>
|
||||
</tr>
|
||||
<tr class="markdownTableBody">
|
||||
<td class="markdownTableBodyCenter">1000</td>
|
||||
<td class="markdownTableBodyCenter">0.812362</td>
|
||||
<td class="markdownTableBodyCenter">0.480052</td>
|
||||
<td class="markdownTableBodyCenter">16.14239</td>
|
||||
<td class="markdownTableBodyCenter">17.43480</td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
The same results can be seen in the figure.
|
||||
|
||||
\cgalFigureBegin{hm_n_bench, hm_n_bench.svg}
|
||||
Time in seconds to setup (red), factorize (green), and solve (blue) for harmonic
|
||||
coordinate values with respect to a polygon with \f$n\f$ vertices at 100k query points.
|
||||
\cgalFigureEnd
|
||||
|
||||
Since many applications require to work with more complex planar geometric shapes than segments and triangles, it seems natural to investigate a generalized version of triangle coordinates with respect to arbitrary polygons. The first attempt was taken in 1975 by E. L. Wachspress \cite cgal:bc:w-rfeb-75, and the resulting generalized barycentric coordinates are now called Wachspress coordinates \cite cgal:bc:mlbd-gbcip-02. \ref gbc_deg_wachspress_coordinates "These coordinates" are well-defined for arbitrary <em>strictly convex polygons</em> and have all the properties of triangle coordinates \cite cgal:bc:fhk-gcbcocp-06. Unfortunately, they are not well-defined for weakly convex and concave polygons.
|
||||
While, in the first table, the most significant step is to factorize the matrix, in the
|
||||
second table, the slowest step is to solve for coordinates, as expected.
|
||||
|
||||
Analogously to the previous cases, we want to plot the Wachspress coordinates and see how they look like. Let us choose a \ref wp_polygon "non-regular hexagon", slightly rotate it, and move one of its vertices towards the line through its two adjacent neighbors. We sample the interior and the boundary of this polygon as before and plot the coordinate function with respect to the vertex that we moved at all the sample points. We see that we get a smooth function, which is linear along all edges and grows from zero to one, as the color bar indicates.
|
||||
|
||||
\anchor wp_plot
|
||||
\cgalFigureBegin{wp__coord__interp,wp__coord__interp.png}
|
||||
The Wachspress coordinate function with respect to the indicated vertex with values from zero to one as the color bar indicates.
|
||||
\cgalFigureEnd
|
||||
\section gbc_history History
|
||||
|
||||
Another type of generalized barycentric coordinates goes back to Pinkall and Polthier in 1993 \cite cgal:pp-cdmsc-93 and Eck et al. in 1995 \cite cgal:bc:eddhls-maam-95 in the context of \ref PkgSurfaceMeshParameterization "triangle mesh parameterization". They are called discrete harmonic coordinates. \ref gbc_deg_discrete_harmonic_coordinates "These coordinates" are well-defined, similarly to Wachspress coordinates, for arbitrary <em>strictly convex polygons</em> and inherit all the properties of triangle coordinates <em>apart from the positivity inside a polygon</em> because they can take on negative values \ref gbc_deg_discrete_harmonic_coordinates "for some polygons". Another interesting property of these coordinate functions is that they coincide with Wachspress coordinates for any polygon whose vertices lie on a common circle.
|
||||
The package was first released in 2015 and included segment, triangle, Wachspress,
|
||||
discrete harmonic, and mean value coordinates. The API of that version is now deprecated
|
||||
but can still be used. An example of the old API can be found \ref depr_example "here".
|
||||
The docs of that API are also preserved and maintained \ref PkgBarycentricCoordinates2RefDeprecated "here".
|
||||
|
||||
To plot discrete harmonic coordinates we take \ref wp_plot "the same polygon" as for Wachspress coordinates and plot the coordinate function with respect to the same vertex. Again, we get a smooth function, which is linear along all edges and grows from zero to one. Isolines in the plot show the difference between discrete harmonic and Wachspress coordinates for the chosen polygon and vertex.
|
||||
In 2018, this package was modified and improved by Keyu Chen and Dmitry Anisimov
|
||||
during the Google Summer of Code. The API was changed to the current version. In 2020, the new version
|
||||
was cleaned up and documented that includes:
|
||||
- the classes `Segment_coordinates_2` and `Triangle_coordinates_2` have been removed, only the free
|
||||
functions are preserved;
|
||||
- the entry class `Generalized_barycentric_coordinates_2` was removed since it is not
|
||||
flexible enough to accommodate all types of 2D barycentric coordinates;
|
||||
- the classes `Wachspress_2`, `Discrete harmonic_2`, and `Mean_value_2` have been renamed
|
||||
and modified so that they can be used now on their own without the class `Generalized_barycentric_coordinates_2`;
|
||||
- harmonic coordinates have been added;
|
||||
- the free functions for segment and triangle coordinates have been modified and improved;
|
||||
- the free functions for Wachspress, discrete harmonic, and mean value weights and coordinates have been added;
|
||||
- the free functions to compute barycentric coordinates for points on the polygon boundary have been added;
|
||||
- all functions and classes are now using ranges and property maps;
|
||||
- examples, tests, and benchmarks are modified/extended/improved;
|
||||
- the docs are refactored and simplified.
|
||||
|
||||
\anchor dh_plot
|
||||
\cgalFigureBegin{dh__coord__interp,dh__coord__interp.png}
|
||||
The discrete harmonic coordinate function with respect to the indicated vertex with values from zero to one as the color bar indicates.
|
||||
\cgalFigureEnd
|
||||
|
||||
The last type of generalized barycentric coordinates that we discuss are mean value coordinates \cite cgal:f-mvc-03 proposed by M. Floater in 2003. Based on the <a href="https://en.wikipedia.org/wiki/Mean_value_theorem">mean value theorem</a>, \ref gbc_deg_mean_value_coordinates "these coordinates", unlike Wachspress and discrete harmonic coordinates, are well-defined for arbitrary <em>simple polygons</em>, inherit all the properties of triangle coordinates for any convex polygon, and <em>lack only the positivity property for general concave polygons</em>. Hormann and Floater prove in \cite cgal:bc:hf-mvcapp-06 that these coordinates are positive inside the kernel of a <a href="https://en.wikipedia.org/wiki/Star-shaped_polygon">star-shaped polygon</a>. They are also positive in the closure of any quadrilateral. Like discrete harmonic weights, mean value weights are often used in the context of \ref PkgSurfaceMeshParameterization "triangle mesh parameterization."
|
||||
|
||||
In order to show the particular behaviour of mean value coordinates with an application to concave polygons, we take \ref fig__mv__example "a star-shaped polygon" with ten vertices \f$[v_0, \dots, v_9]\f$, sample its interior and boundary, and plot the coordinate function with respect to the fourth vertex \f$v_3\f$. As the color bar indicates, the obtained function grows from a slightly negative value to one at the chosen vertex. It is also smooth inside the polygon and linear along all edges.
|
||||
|
||||
\cgalFigureBegin{mv__coord__interp,mv__coord__interp.png}
|
||||
Mean value coordinates with respect to \f$v_3\f$. The color bar indicates the range of values for the chosen coordinate function.
|
||||
\cgalFigureEnd
|
||||
|
||||
<b>Interesting fact</b>: all the coordinates discussed in this section and implemented in the package come from one and the same family of generalized barycentric coordinates named <em>3-point family of coordinates</em> \cite cgal:bc:fhk-gcbcocp-06.
|
||||
|
||||
\section gbc_acknowledgments Acknowledgments
|
||||
The authors wish to thank <a href="https://www.inf.usi.ch/phd/schneider/">Teseo Schneider</a> and <a href="https://search.usi.ch/people/5ae37d3d990b431a02b95b0b606da2e6/Schaerfig-Randolf">Randolf Schaerfig</a> for helpful comments and discussions. We also appreciate the great effort invested in this package by our reviewers <a href="https://geometryfactory.com/who-we-are/">Andreas Fabri and Sébastien Loriot</a>. Finally, to create pictures for this manual, we used two programs: <a href="https://www.geogebra.org">Geogebra</a> and <a href="https://www.mathworks.com/products/matlab.html">Matlab</a>.
|
||||
|
||||
The authors wish to thank <a href="https://cs.nyu.edu/~teseo/">Teseo Schneider</a>
|
||||
and Randolf Schaerfig for helpful comments and discussions. We also appreciate the
|
||||
great effort invested in this package by our reviewers Andreas Fabri, Sébastien Loriot,
|
||||
and Efi Fogel.
|
||||
*/
|
||||
|
||||
}
|
||||
} /* namespace Barycentric_coordinates */
|
||||
} /* namespace CGAL */
|
||||
|
|
|
|||
|
|
@ -1,15 +1,20 @@
|
|||
namespace CGAL {
|
||||
namespace Barycentric_coordinates {
|
||||
|
||||
/*!
|
||||
\ingroup PkgBarycentricCoordinates2Concepts
|
||||
\ingroup PkgBarycentricCoordinates2RefConcepts
|
||||
\cgalConcept
|
||||
|
||||
Requirements of the template parameter `Coordinate_2` for the class `CGAL::Barycentric_coordinates::Generalized_barycentric_coordinates_2`.
|
||||
A concept that describes the set of methods that should be defined for all coordinate
|
||||
models used to parameterize the class `Generalized_barycentric_coordinates_2`.
|
||||
|
||||
\cgalHasModel `CGAL::Barycentric_coordinates::Wachspress_2`
|
||||
\cgalHasModel `CGAL::Barycentric_coordinates::Mean_value_2`
|
||||
\cgalHasModel `CGAL::Barycentric_coordinates::Discrete_harmonic_2`
|
||||
\cgalHasModel
|
||||
- `Wachspress_2`
|
||||
- `Mean_value_2`
|
||||
- `Discrete_harmonic_2`
|
||||
|
||||
\deprecated This part of the package is deprecated since the version 5.4 of \cgal.
|
||||
*/
|
||||
|
||||
class BarycentricCoordinates_2 {
|
||||
|
||||
public:
|
||||
|
|
@ -17,9 +22,16 @@ public:
|
|||
/// \name Creation
|
||||
/// @{
|
||||
|
||||
/// Creates a class that implements generalized barycentric coordinates for any query point that does not belong to the polygon's boundary.
|
||||
/// The polygon is given by a range of vertices of the type `Traits::Point_2` stored in a container of the type <a href="http://en.cppreference.com/w/cpp/container/vector">`std::vector`</a>.
|
||||
BarycentricCoordinates_2(const std::vector<Traits::Point_2> &vertices, const Traits &barycentric_traits);
|
||||
/*!
|
||||
Creates a class that implements generalized barycentric coordinates for any query
|
||||
point that does not belong to the polygon's boundary. The polygon is given by a
|
||||
range of vertices of the type `Traits::Point_2` stored in a container of the
|
||||
type <a href="https://en.cppreference.com/w/cpp/container/vector">`std::vector`</a>.
|
||||
*/
|
||||
BarycentricCoordinates_2(
|
||||
const std::vector<Traits::Point_2>& vertices, const Traits& barycentric_traits) {
|
||||
|
||||
}
|
||||
|
||||
/// @}
|
||||
|
||||
|
|
@ -27,25 +39,50 @@ BarycentricCoordinates_2(const std::vector<Traits::Point_2> &vertices, const Tra
|
|||
/// @{
|
||||
|
||||
/*!
|
||||
A function that computes generalized barycentric coordinates without normalization that are called generalized baycentric weights (as fast as possible algorithm is used).
|
||||
Weights are computed with respect to a query point of the type `Traits::Point_2` and stored in the output iterator `output`. The function returns a pointer to the last stored element.
|
||||
A function that computes generalized barycentric coordinates without normalization
|
||||
that are called generalized barycentric weights (as fast as possible algorithm is used).
|
||||
Weights are computed with respect to a query point of the type `Traits::Point_2` and
|
||||
stored in the output iterator `output`. The function returns a pointer to the last stored element.
|
||||
*/
|
||||
boost::optional<OutputIterator> weights(const Traits::Point_2 &query_point, OutputIterator &output);
|
||||
boost::optional<OutputIterator>
|
||||
weights(
|
||||
const Traits::Point_2& query_point, OutputIterator& output) {
|
||||
|
||||
}
|
||||
|
||||
/*!
|
||||
A function that computes generalized barycentric coordinates on the bounded side of a polygon with one of two possible algorithms: one is precise and one is fast.
|
||||
The algorithm type is specified by the parameter type_of_algorithm. Coordinates are computed with respect to a query point of the type `Traits::Point_2` and stored in the output iterator `output`.
|
||||
The function returns a pointer to the last stored element.
|
||||
A function that computes generalized barycentric coordinates on the bounded side
|
||||
of a polygon with one of two possible algorithms: one is precise and one is fast.
|
||||
The algorithm type is specified by the parameter `type_of_algorithm`. Coordinates
|
||||
are computed with respect to a query point of the type `Traits::Point_2` and stored
|
||||
in the output iterator `output`. The function returns a pointer to the last stored element.
|
||||
*/
|
||||
boost::optional<OutputIterator> coordinates_on_bounded_side(const Traits::Point_2 &query_point, OutputIterator &output, const Type_of_algorithm type_of_algorithm);
|
||||
boost::optional<OutputIterator>
|
||||
coordinates_on_bounded_side(
|
||||
const Traits::Point_2& query_point,
|
||||
OutputIterator& output,
|
||||
const Type_of_algorithm type_of_algorithm) {
|
||||
|
||||
}
|
||||
|
||||
/*!
|
||||
A function that computes generalized barycentric coordinates on the unbounded side of a polygon with one of two possible algorithms: one is precise and one is fast.
|
||||
The algorithm type is specified by the parameter type_of_algorithm. Coordinates are computed with respect to a query point of the type `Traits::Point_2` and stored in the output iterator `output`.
|
||||
The function returns a pointer to the last stored element.
|
||||
A function that computes generalized barycentric coordinates on the unbounded side
|
||||
of a polygon with one of two possible algorithms: one is precise and one is fast.
|
||||
The algorithm type is specified by the parameter `type_of_algorithm`. Coordinates
|
||||
are computed with respect to a query point of the type `Traits::Point_2` and stored
|
||||
in the output iterator `output`. The function returns a pointer to the last stored element.
|
||||
*/
|
||||
boost::optional<OutputIterator> coordinates_on_unbounded_side(const Traits::Point_2 &query_point, OutputIterator &output, const Type_of_algorithm type_of_algorithm);
|
||||
boost::optional<OutputIterator>
|
||||
coordinates_on_unbounded_side(
|
||||
const Traits::Point_2& query_point,
|
||||
OutputIterator& output,
|
||||
const Type_of_algorithm type_of_algorithm) {
|
||||
|
||||
}
|
||||
|
||||
/// @}
|
||||
|
||||
}; /* end BarycentricCoordinates_2 */
|
||||
};
|
||||
|
||||
} // namespace Barycentric_coordinates
|
||||
} // namespace CGAL
|
||||
|
|
|
|||
|
|
@ -1,13 +1,20 @@
|
|||
namespace CGAL {
|
||||
namespace Barycentric_coordinates {
|
||||
|
||||
/*!
|
||||
\ingroup PkgBarycentricCoordinates2Concepts
|
||||
\ingroup PkgBarycentricCoordinates2RefConcepts
|
||||
\cgalConcept
|
||||
|
||||
Requirements of the template parameter `Traits` for all the classes with two-dimensional barycentric coordinates from the namespace `CGAL::Barycentric_coordinates`.
|
||||
|
||||
\cgalHasModel All models of `Kernel`
|
||||
A concept that describes the set of requirements of the template parameter
|
||||
`GeomTraits` used to parameterize all classes and functions with 2D barycentric
|
||||
coordinates from the namespace `CGAL::Barycentric_coordinates`.
|
||||
|
||||
\cgalHasModel
|
||||
- All models of `Kernel`
|
||||
- `CGAL::Projection_traits_xy_3<K>`
|
||||
- `CGAL::Projection_traits_yz_3<K>`
|
||||
- `CGAL::Projection_traits_xz_3<K>`
|
||||
*/
|
||||
|
||||
class BarycentricTraits_2 {
|
||||
|
||||
public:
|
||||
|
|
@ -20,9 +27,19 @@ public:
|
|||
*/
|
||||
typedef unspecified_type FT;
|
||||
|
||||
/*!
|
||||
`CGAL::Comparison_result` or `Uncertain<CGAL::Comparison_result>`.
|
||||
*/
|
||||
typedef unspecified_type Comparison_result;
|
||||
|
||||
/*!
|
||||
`CGAL::Orientation` or `Uncertain<CGAL::Orientation>`.
|
||||
*/
|
||||
typedef unspecified_type Orientation;
|
||||
|
||||
/// @}
|
||||
|
||||
/// \name Two-dimensional Geometric Objects
|
||||
/// \name 2D Geometric Objects
|
||||
/// @{
|
||||
|
||||
/*!
|
||||
|
|
@ -37,56 +54,136 @@ typedef unspecified_type Vector_2;
|
|||
|
||||
/// @}
|
||||
|
||||
/// \name Two-dimensional Constructions
|
||||
/// \name 2D Generalized Constructions
|
||||
/// @{
|
||||
|
||||
/*!
|
||||
A model of this concept must provide an FT operator(const Point_2 &p, const Point_2 &q, const Point_2 &r)
|
||||
that returns the signed area of the triangle defined by the points p, q, and r.
|
||||
A construction object that must provide the function operator:
|
||||
|
||||
`FT operator(const Point_2& p, const Point_2& q, const Point_2& r)`
|
||||
|
||||
that returns the signed area of the triangle defined by the points `p`, `q`, and `r`.
|
||||
*/
|
||||
typedef unspecified_type Compute_area_2;
|
||||
|
||||
/*!
|
||||
A model of this concept must provide an FT operator(const Point_2 &p, const Point_2 &q)
|
||||
that returns the squared Euclidean distance between the points p and q.
|
||||
A construction object that must provide the function operator:
|
||||
|
||||
`FT operator(const Point_2& p, const Point_2& q)`
|
||||
|
||||
that returns the squared Euclidean distance between the points `p` and `q`.
|
||||
*/
|
||||
typedef unspecified_type Compute_squared_distance_2;
|
||||
|
||||
/*!
|
||||
A model of this concept must provide an FT operator(const Vector_2 &p)
|
||||
that returns the squared length of the vector p.
|
||||
A construction object that must provide the function operator:
|
||||
|
||||
`FT operator(const Vector_2& v)`
|
||||
|
||||
that returns the squared length of the vector `v`.
|
||||
*/
|
||||
typedef unspecified_type Compute_squared_length_2;
|
||||
|
||||
/*!
|
||||
A model of this concept must provide an FT operator(const Vector_2 &p, const Vector_2 &q)
|
||||
that returns the scalar product between the vectors p and q.
|
||||
A construction object that must provide the function operator:
|
||||
|
||||
`FT operator(const Vector_2& v, const Vector_2& w)`
|
||||
|
||||
that returns the scalar product of the vectors `v` and `w`.
|
||||
*/
|
||||
typedef unspecified_type Compute_scalar_product_2;
|
||||
|
||||
/*!
|
||||
A construction object that must provide the function operator:
|
||||
|
||||
`FT operator(const Vector_2& v, const Vector_2& w)`
|
||||
|
||||
that returns the determinant of the vectors `v` and `w`.
|
||||
*/
|
||||
typedef unspecified_type Compute_determinant_2;
|
||||
|
||||
/*!
|
||||
A construction object that must provide the function operator:
|
||||
|
||||
`%Vector_2 operator()(const Point_2& p, const Point_2& q)`
|
||||
|
||||
that returns the vector through the points `p` and `q`.
|
||||
*/
|
||||
typedef unspecified_type Construct_vector_2;
|
||||
|
||||
/// @}
|
||||
|
||||
/// \name Two-dimensional Generalized Predicates
|
||||
/// \name 2D Generalized Predicates
|
||||
/// @{
|
||||
|
||||
/*!
|
||||
A model of this concept must provide a bool operator(const Point_2 &p, const Point_2 &q)
|
||||
that returns true if p = q and false otherwise.
|
||||
A predicate object that must provide the function operator:
|
||||
|
||||
`bool operator(const Point_2& p, const Point_2& q)`
|
||||
|
||||
that returns `true` if `p = q` and `false` otherwise.
|
||||
*/
|
||||
typedef unspecified_type Equal_2;
|
||||
|
||||
/*!
|
||||
A model of this concept must provide a bool operator(const Point_2 &p, const Point_2 &q, const Point_2 &r)
|
||||
that returns true if the points p, q, and r are collinear and false otherwise.
|
||||
A predicate object that must provide the function operator:
|
||||
|
||||
`bool operator(const Point_2& p, const Point_2& q, const Point_2& r)`
|
||||
|
||||
that returns `true` if the points `p`, `q`, and `r` are collinear and `false` otherwise.
|
||||
*/
|
||||
typedef unspecified_type Collinear_2;
|
||||
|
||||
/*!
|
||||
A model of this concept must provide a bool operator(const Point_2 &p, const Point_2 &q, const Point_2 &r)
|
||||
that returns true if the point q lies between the points p and r and all three points are collinear.
|
||||
A predicate object that must provide the function operator:
|
||||
|
||||
`bool operator(const Point_2& p, const Point_2& q, const Point_2& r)`
|
||||
|
||||
that returns `true` if the point `q` lies between the points `p` and `r` and all three points are collinear.
|
||||
*/
|
||||
typedef unspecified_type Collinear_are_ordered_along_line_2;
|
||||
|
||||
/*!
|
||||
A predicate object that must provide the function operator:
|
||||
|
||||
`bool operator(const Point_2& p, const Point_2& q)`
|
||||
|
||||
that returns `true` iff the x-coordinate of `p` is smaller than the x-coordinate of `q` or
|
||||
if they are the same and the y-coordinate of `p` is smaller than the y-coordinate of `q`.
|
||||
*/
|
||||
typedef unspecified_type Less_xy_2;
|
||||
|
||||
/*!
|
||||
A predicate object that must provide the function operator:
|
||||
|
||||
`Comparison_result operator(const Point_2& p, const Point_2& q)`
|
||||
|
||||
that compares the Cartesian x-coordinates of the points `p` and `q`.
|
||||
*/
|
||||
typedef unspecified_type Compare_x_2;
|
||||
|
||||
/*!
|
||||
A predicate object that must provide the function operator:
|
||||
|
||||
`Comparison_result operator(const Point_2& p, const Point_2& q)`
|
||||
|
||||
that compares the Cartesian y-coordinates of the points `p` and `q`.
|
||||
*/
|
||||
typedef unspecified_type Compare_y_2;
|
||||
|
||||
/*!
|
||||
A predicate object that must provide the function operator:
|
||||
|
||||
`Orientation operator(const Point_2& p, const Point_2& q, const Point_2& r)`
|
||||
|
||||
that returns `CGAL::LEFT_TURN` if `r` lies to the left of the oriented line `l` defined by `p` and `q`,
|
||||
returns `CGAL::RIGHT_TURN` if `r` lies to the right of `l`, and returns `CGAL::COLLINEAR` if `r` lies on `l`.
|
||||
*/
|
||||
typedef unspecified_type Orientation_2;
|
||||
|
||||
/// @}
|
||||
|
||||
}; /* end BarycentricTraits_2 */
|
||||
};
|
||||
|
||||
} // namespace Barycentric_coordinates
|
||||
} // namespace CGAL
|
||||
|
|
|
|||
|
|
@ -0,0 +1,70 @@
|
|||
namespace CGAL {
|
||||
namespace Barycentric_coordinates {
|
||||
|
||||
/*!
|
||||
\ingroup PkgBarycentricCoordinates2RefConcepts
|
||||
\cgalConcept
|
||||
|
||||
A concept that describes the set of methods that should be defined for all
|
||||
discretized domains obtained by meshing the interior part of a simple polygon.
|
||||
|
||||
After meshing, the interior part of the polygon is split into multiple finite
|
||||
elements, which share common edges and vertices. These finite elements are then
|
||||
used to approximate certain types of generalized barycentric coordinate functions.
|
||||
The domain is bounded by the polygon.
|
||||
|
||||
\cgalHasModel
|
||||
- `Delaunay_domain_2`
|
||||
*/
|
||||
class DiscretizedDomain_2 {
|
||||
|
||||
public:
|
||||
|
||||
/*!
|
||||
returns the number of vertices after meshing the domain.
|
||||
*/
|
||||
std::size_t number_of_vertices() const {
|
||||
|
||||
}
|
||||
|
||||
/*!
|
||||
returns a const reference to the vertex with the index `query_index`, the
|
||||
`Vertex_2` type being a model of `Kernel::Point_2`.
|
||||
*/
|
||||
const Vertex_2& vertex(
|
||||
const std::size_t query_index) const {
|
||||
|
||||
}
|
||||
|
||||
/*!
|
||||
verifies if the vertex with the index `query_index` is on the
|
||||
boundary of the domain.
|
||||
*/
|
||||
bool is_on_boundary(
|
||||
const std::size_t query_index) const {
|
||||
|
||||
}
|
||||
|
||||
/*!
|
||||
fills `neighbors` with the indices of the vertices, which form the one-ring
|
||||
neighborhood of the vertex with the index `query_index`, the neighbors have to
|
||||
be in the counterclockwise order and form a simple polygon.
|
||||
*/
|
||||
void operator()(
|
||||
const std::size_t query_index, std::vector<std::size_t>& neighbors) {
|
||||
|
||||
}
|
||||
|
||||
/*!
|
||||
fills `indices` with the indices of the vertices, which form a finite element
|
||||
of the domain, that contains a `query` point; if no indices are found, the
|
||||
`query` point does not belong to the domain; the type `Query_2` is a model of `Kernel::Point_2`.
|
||||
*/
|
||||
void locate(
|
||||
const Query_2& query, std::vector<std::size_t>& indices) {
|
||||
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace Barycentric_coordinates
|
||||
} // namespace CGAL
|
||||
|
|
@ -1,6 +1,6 @@
|
|||
@INCLUDE = ${CGAL_DOC_PACKAGE_DEFAULTS}
|
||||
|
||||
PROJECT_NAME = "CGAL ${CGAL_DOC_VERSION} - 2D Generalized Barycentric Coordinates"
|
||||
EXTRACT_ALL = false
|
||||
|
||||
HIDE_UNDOC_MEMBERS = true
|
||||
HIDE_UNDOC_CLASSES = true
|
||||
|
|
|
|||
|
|
@ -1,18 +1,48 @@
|
|||
/// \defgroup PkgBarycentricCoordinates2Ref 2D Generalized Barycentric Coordinates Reference
|
||||
|
||||
/// \defgroup PkgBarycentricCoordinates2Concepts Concepts
|
||||
/// \ingroup PkgBarycentricCoordinates2Ref
|
||||
namespace CGAL {
|
||||
namespace Barycentric_coordinates {
|
||||
|
||||
/*!
|
||||
\defgroup PkgBarycentricCoordinates2Ref 2D Generalized Barycentric Coordinates Reference
|
||||
|
||||
\defgroup PkgBarycentricCoordinates2RefConcepts Concepts
|
||||
\ingroup PkgBarycentricCoordinates2Ref
|
||||
|
||||
Generalized barycentric concepts.
|
||||
|
||||
\defgroup PkgBarycentricCoordinates2RefAnalytic Analytic Coordinates
|
||||
\ingroup PkgBarycentricCoordinates2Ref
|
||||
|
||||
Analytic coordinates and related classes.
|
||||
|
||||
\defgroup PkgBarycentricCoordinates2RefHarmonic Harmonic Coordinates
|
||||
\ingroup PkgBarycentricCoordinates2Ref
|
||||
|
||||
Harmonic coordinates and related classes.
|
||||
|
||||
\defgroup PkgBarycentricCoordinates2RefFunctions Free Functions
|
||||
\ingroup PkgBarycentricCoordinates2Ref
|
||||
|
||||
Free functions to compute barycentric weights and coordinates.
|
||||
|
||||
\defgroup PkgBarycentricCoordinates2RefDeprecated Deprecated
|
||||
\ingroup PkgBarycentricCoordinates2Ref
|
||||
|
||||
Deprecated classes and functions.
|
||||
|
||||
\addtogroup PkgBarycentricCoordinates2Ref
|
||||
|
||||
\cgalPkgDescriptionBegin{2D Generalized Barycentric Coordinates, PkgBarycentricCoordinates2}
|
||||
\cgalPkgPicture{barcoord_thumb.png}
|
||||
|
||||
\cgalPkgSummaryBegin
|
||||
\cgalPkgAuthors{Dmitry Anisimov, David Bommes, Kai Hormann, and Pierre Alliez}
|
||||
\cgalPkgDesc{The package 2D Generalized Barycentric Coordinates offers an efficient and robust implementation of two-dimensional closed-form generalized barycentric coordinates defined for simple two-dimensional polygons. If coordinates with respect to multivariate scattered points instead of a polygon are required, please refer to natural neighbor coordinates from the Package \ref PkgInterpolation2.}
|
||||
\cgalPkgDesc{This package offers an efficient and robust implementation of 2D generalized barycentric
|
||||
coordinates defined for simple polygons in the plane. If coordinates with respect to multivariate
|
||||
scattered points instead of a polygon are required, please refer to natural neighbor
|
||||
coordinates from the Package \ref PkgInterpolation2.}
|
||||
\cgalPkgManuals{Chapter_2D_Generalized_Barycentric_Coordinates, PkgBarycentricCoordinates2Ref}
|
||||
\cgalPkgSummaryEnd
|
||||
|
||||
\cgalPkgShortInfoBegin
|
||||
\cgalPkgSince{4.6}
|
||||
\cgalPkgBib{cgal:abha-gbc}
|
||||
|
|
@ -22,30 +52,31 @@
|
|||
|
||||
\cgalClassifedRefPages
|
||||
|
||||
\cgalCRPSection{Concepts}
|
||||
## Concepts ##
|
||||
- `BarycentricTraits_2`
|
||||
- `DiscretizedDomain_2`
|
||||
- `BarycentricCoordinates_2`
|
||||
|
||||
\cgalCRPSection{Namespaces}
|
||||
- `CGAL::Barycentric_coordinates`
|
||||
|
||||
\cgalCRPSection{General Classes}
|
||||
- `CGAL::Barycentric_coordinates::Segment_coordinates_2<Traits>`
|
||||
- `CGAL::Barycentric_coordinates::Triangle_coordinates_2<Traits>`
|
||||
- `CGAL::Barycentric_coordinates::Generalized_barycentric_coordinates_2<Coordinate_2, Traits>`
|
||||
|
||||
\cgalCRPSection{Models of `BarycentricCoordinates_2`}
|
||||
- `CGAL::Barycentric_coordinates::Wachspress_2<Traits>`
|
||||
- `CGAL::Barycentric_coordinates::Mean_value_2<Traits>`
|
||||
- `CGAL::Barycentric_coordinates::Discrete_harmonic_2<Traits>`
|
||||
|
||||
\cgalCRPSection{Enumerations}
|
||||
- `CGAL::Barycentric_coordinates::Query_point_location`
|
||||
- `CGAL::Barycentric_coordinates::Type_of_algorithm`
|
||||
|
||||
@todo To make the code parallel. Get iteration number from the thread. Add parallel class to each type of the coordinate functions. Use begin() + offset. Resize vector. Parallel class takes as parameters list of points and polygon. Use random access iterator. - Done but we have problems with it.
|
||||
|
||||
@todo Add hard tests with epsilon distance away from the polygon’s boundary, which we have discussed during our first group meeting, to current test suit.
|
||||
## Analytic Coordinates ##
|
||||
- `Wachspress_coordinates_2<VertexRange, GeomTraits, PointMap>`
|
||||
- `Mean_value_coordinates_2<VertexRange, GeomTraits, PointMap>`
|
||||
- `Discrete_harmonic_coordinates_2<VertexRange, GeomTraits, PointMap>`
|
||||
|
||||
## Harmonic Coordinates ##
|
||||
- `Delaunay_domain_2<VertexRange, GeomTraits, PointMap>`
|
||||
- `Harmonic_coordinates_2<VertexRange, DiscretizedDomain, GeomTraits, PointMap>`
|
||||
|
||||
## Free Functions ##
|
||||
- `segment_coordinates_2()`
|
||||
- `triangle_coordinates_2()`
|
||||
- `wachspress_weights_2()`
|
||||
- `wachspress_coordinates_2()`
|
||||
- `mean_value_weights_2()`
|
||||
- `mean_value_coordinates_2()`
|
||||
- `discrete_harmonic_weights_2()`
|
||||
- `discrete_harmonic_coordinates_2()`
|
||||
- `boundary_coordinates_2()`
|
||||
*/
|
||||
|
||||
} /* namespace Barycentric_coordinates */
|
||||
} /* namespace CGAL */
|
||||
|
|
|
|||
|
|
@ -1,10 +1,16 @@
|
|||
Manual
|
||||
Mesh_2
|
||||
Polygon
|
||||
Kernel_d
|
||||
Kernel_23
|
||||
Generator
|
||||
Convex_hull_2
|
||||
Number_types
|
||||
Interpolation
|
||||
STL_Extension
|
||||
Triangulation_2
|
||||
Algebraic_foundations
|
||||
Circulator
|
||||
Stream_support
|
||||
Property_map
|
||||
Surface_mesh_parameterization
|
||||
|
|
|
|||
|
|
@ -1,11 +1,12 @@
|
|||
/*!
|
||||
|
||||
\example Barycentric_coordinates_2/Segment_coordinates_example.cpp
|
||||
\example Barycentric_coordinates_2/Triangle_coordinates_example.cpp
|
||||
\example Barycentric_coordinates_2/Wachspress_coordinates_example.cpp
|
||||
\example Barycentric_coordinates_2/Mean_value_coordinates_example.cpp
|
||||
\example Barycentric_coordinates_2/Discrete_harmonic_coordinates_example.cpp
|
||||
\example Barycentric_coordinates_2/Terrain_height_modeling.cpp
|
||||
\example Barycentric_coordinates_2/Triangle_coordinates_speed_test.cpp
|
||||
|
||||
\example Barycentric_coordinates_2/segment_coordinates.cpp
|
||||
\example Barycentric_coordinates_2/triangle_coordinates.cpp
|
||||
\example Barycentric_coordinates_2/wachspress_coordinates.cpp
|
||||
\example Barycentric_coordinates_2/discrete_harmonic_coordinates.cpp
|
||||
\example Barycentric_coordinates_2/mean_value_coordinates.cpp
|
||||
\example Barycentric_coordinates_2/harmonic_coordinates.cpp
|
||||
\example Barycentric_coordinates_2/terrain_height_modeling.cpp
|
||||
\example Barycentric_coordinates_2/shape_deformation.cpp
|
||||
\example Barycentric_coordinates_2/affine_coordinates.cpp
|
||||
\example Barycentric_coordinates_2/deprecated_coordinates.cpp
|
||||
*/
|
||||
|
|
|
|||
|
|
@ -0,0 +1,81 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!-- Generator: Adobe Illustrator 24.0.3, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
|
||||
<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
|
||||
width="297.2px" height="255px" viewBox="0 0 297.2 255" style="enable-background:new 0 0 297.2 255;" xml:space="preserve">
|
||||
<style type="text/css">
|
||||
.st0{fill:none;stroke:#000000;stroke-miterlimit:10;}
|
||||
.st1{fill:none;stroke:#000000;stroke-width:2;stroke-miterlimit:10;}
|
||||
.st2{fill:#4D4DFF;}
|
||||
.st3{stroke:#000000;stroke-width:0.5;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:10;}
|
||||
.st4{fill:#5E7CEA;stroke:#000000;stroke-width:0.5;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:10;}
|
||||
</style>
|
||||
<path class="st0" d="M29.2,235.7"/>
|
||||
<g>
|
||||
<g>
|
||||
<line class="st1" x1="29.2" y1="7.2" x2="29.2" y2="255"/>
|
||||
<g>
|
||||
<polygon points="24.8,10.5 29.2,8.6 33.6,10.5 29.2,0 "/>
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
<path class="st0" d="M29.2,6.9"/>
|
||||
<path class="st0" d="M274.1,170.1"/>
|
||||
<g>
|
||||
<g>
|
||||
<line class="st1" x1="0" y1="170.1" x2="290.1" y2="170.1"/>
|
||||
<g>
|
||||
<polygon points="286.7,174.5 288.6,170.1 286.7,165.6 297.2,170.1 "/>
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
<path class="st0" d="M0,170.1"/>
|
||||
<path class="st2" d="M32.9,170.3c0,2.2-1.8,4-4,4c-2.2,0-4-1.8-4-4c0-2.2,1.8-4,4-4C31.1,166.3,32.9,168.1,32.9,170.3z"/>
|
||||
<path class="st3" d="M32.9,170.3c0,2.2-1.8,4-4,4c-2.2,0-4-1.8-4-4c0-2.2,1.8-4,4-4C31.1,166.3,32.9,168.1,32.9,170.3z"/>
|
||||
<path class="st2" d="M278.1,88.6c0,2.2-1.8,4-4,4c-2.2,0-4-1.8-4-4c0-2.2,1.8-4,4-4C276.3,84.6,278.1,86.4,278.1,88.6z"/>
|
||||
<path class="st3" d="M278.1,88.6c0,2.2-1.8,4-4,4c-2.2,0-4-1.8-4-4c0-2.2,1.8-4,4-4C276.3,84.6,278.1,86.4,278.1,88.6z"/>
|
||||
<path class="st2" d="M196.3,6.9c0,2.2-1.8,4-4,4c-2.2,0-4-1.8-4-4c0-2.2,1.8-4,4-4C194.6,2.9,196.3,4.7,196.3,6.9z"/>
|
||||
<path class="st3" d="M196.3,6.9c0,2.2-1.8,4-4,4c-2.2,0-4-1.8-4-4c0-2.2,1.8-4,4-4C194.6,2.9,196.3,4.7,196.3,6.9z"/>
|
||||
<path class="st2" d="M163.7,235.7c0,2.2-1.8,4-4,4s-4-1.8-4-4c0-2.2,1.8-4,4-4S163.7,233.5,163.7,235.7z"/>
|
||||
<path class="st3" d="M163.7,235.7c0,2.2-1.8,4-4,4s-4-1.8-4-4c0-2.2,1.8-4,4-4S163.7,233.5,163.7,235.7z"/>
|
||||
<path class="st2" d="M98.3,104.9c0,2.2-1.8,4-4,4c-2.2,0-4-1.8-4-4c0-2.2,1.8-4,4-4C96.5,100.9,98.3,102.7,98.3,104.9z"/>
|
||||
<path class="st4" d="M98.3,104.9c0,2.2-1.8,4-4,4c-2.2,0-4-1.8-4-4c0-2.2,1.8-4,4-4C96.5,100.9,98.3,102.7,98.3,104.9z"/>
|
||||
<path class="st2" d="M131,72.3c0,2.2-1.8,4-4,4s-4-1.8-4-4c0-2.2,1.8-4,4-4S131,70,131,72.3z"/>
|
||||
<path class="st4" d="M131,72.3c0,2.2-1.8,4-4,4s-4-1.8-4-4c0-2.2,1.8-4,4-4S131,70,131,72.3z"/>
|
||||
<path class="st2" d="M163.7,39.6c0,2.2-1.8,4-4,4s-4-1.8-4-4c0-2.2,1.8-4,4-4S163.7,37.4,163.7,39.6z"/>
|
||||
<path class="st4" d="M163.7,39.6c0,2.2-1.8,4-4,4s-4-1.8-4-4c0-2.2,1.8-4,4-4S163.7,37.4,163.7,39.6z"/>
|
||||
<g>
|
||||
<g>
|
||||
<path d="M36.6,178.6l-1.6-0.3v-0.6h4v0.6l-2,0.3H36.6z M37.1,177.7l2.6,6.8l-0.7,0.9l2.7-7.6h0.9l-3,8h-0.7l-3.4-8H37.1z
|
||||
M41.7,178.6l-1.7-0.3v-0.6h3.2v0.6l-1.2,0.3H41.7z"/>
|
||||
<path d="M48.4,184.8c0,2.8-1.1,3.7-2.3,3.7c-1.2,0-2.3-1-2.3-3.7c0-2.8,1.1-3.8,2.3-3.8C47.3,181.1,48.4,182,48.4,184.8z
|
||||
M46.1,188c0.7,0,1.3-0.7,1.3-3.2c0-2.6-0.6-3.3-1.3-3.3c-0.7,0-1.3,0.6-1.3,3.3C44.8,187.4,45.4,188,46.1,188z"/>
|
||||
</g>
|
||||
</g>
|
||||
<g>
|
||||
<g>
|
||||
<path d="M282.7,97l-1.6-0.3V96h4v0.6l-2,0.3H282.7z M283.3,96l2.6,6.8l-0.7,0.9l2.7-7.6h0.9l-3,8H285l-3.4-8H283.3z M287.8,97
|
||||
l-1.7-0.3V96h3.2v0.6l-1.2,0.3H287.8z"/>
|
||||
<path d="M294.4,106.3v0.4h-4.1v-0.4l1.6-0.3h0.9L294.4,106.3z M292.7,99.4l0.2,0.1l0,1.6v3.2c0,0.8,0,1.6,0,2.3h-1
|
||||
c0-0.8,0-1.6,0-2.3v-4l-1.5,0.1V100L292.7,99.4z"/>
|
||||
</g>
|
||||
</g>
|
||||
<g>
|
||||
<g>
|
||||
<path d="M202,15.1l-1.6-0.3v-0.6h4v0.6l-2,0.3H202z M202.6,14.2l2.6,6.8l-0.7,0.9l2.7-7.6h0.9l-3,8h-0.7l-3.4-8H202.6z
|
||||
M207.1,15.1l-1.7-0.3v-0.6h3.2v0.6l-1.2,0.3H207.1z"/>
|
||||
<path d="M209.3,24.1c0.6-0.6,1.2-1.2,1.6-1.7c1.1-1.2,1.6-2.1,1.6-3c0-0.9-0.5-1.5-1.3-1.5c-0.3,0-0.7,0.1-1.1,0.2l0.6-0.4l-0.3,1
|
||||
c-0.1,0.5-0.3,0.7-0.6,0.7c-0.2,0-0.4-0.1-0.6-0.4c0.1-1.2,1.1-1.7,2.2-1.7c1.4,0,2,0.8,2,1.9c0,1-0.5,1.7-2.2,3.4
|
||||
c-0.4,0.4-0.9,0.9-1.4,1.4l-0.1-0.2h4.1v0.9h-4.5V24.1z"/>
|
||||
</g>
|
||||
</g>
|
||||
<g>
|
||||
<g>
|
||||
<path d="M168.1,244l-1.6-0.3V243h4v0.6l-2,0.3H168.1z M168.7,243l2.6,6.8l-0.7,0.9l2.7-7.6h0.9l-3,8h-0.7l-3.4-8H168.7z
|
||||
M173.2,244l-1.7-0.3V243h3.2v0.6l-1.2,0.3H173.2z"/>
|
||||
<path d="M177.2,249.7c1,0,1.6-0.5,1.6-1.5c0-0.8-0.5-1.3-1.4-1.3c-0.2,0-0.6,0-0.9,0.2l0.5-0.3l-0.2,0.8c-0.1,0.5-0.3,0.7-0.6,0.7
|
||||
c-0.2,0-0.5-0.1-0.6-0.4c0.2-0.9,1-1.4,2.1-1.4c1.3,0,2.1,0.7,2.1,1.7c0,0.9-0.7,1.7-1.9,1.9v-0.2c1.4,0.1,2.1,0.8,2.1,1.9
|
||||
c0,1.2-1,2.1-2.5,2.1c-1.1,0-1.9-0.5-2.1-1.6c0.1-0.2,0.3-0.4,0.6-0.4c0.4,0,0.5,0.2,0.6,0.8l0.2,0.8l-0.4-0.4
|
||||
c0.4,0.2,0.7,0.2,1,0.2c1.1,0,1.7-0.6,1.7-1.6c0-1-0.6-1.6-1.7-1.6h-0.5v-0.6H177.2z"/>
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 4.6 KiB |
|
Before Width: | Height: | Size: 76 KiB After Width: | Height: | Size: 76 KiB |
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue