Merge remote-tracking branch 'origin/Weights-new_package-danston' into Barycentric_coordinates_2-danston

This commit is contained in:
Dmitry Anisimov 2021-05-28 15:03:11 +02:00
commit c1aa3c0a61
37 changed files with 1669 additions and 1172 deletions

View File

@ -67,11 +67,13 @@ with notations shown in the figure below.
Here, the distance is computed between the points `p` and `q`.
Alternative formulations are explained in \ref Weights_Implementation.
\cgalFigureBegin{inverse_distance_weight, inverse_distance.svg}
Notation used for the inverse distance weight.
\cgalFigureEnd
\cgalHeading{Other Formulations}
\cgalHeading{Alternative Formulations}
- This weight is a special case of the \ref PkgWeightsRefShepardWeights "Shepard Weight".
\tparam GeomTraits
@ -94,6 +96,9 @@ being the power parameter.
Here, `q` is a query point and the points `p0`, `p1`, and `p2` are ordered.
This weight supports only planar configurations (see more in section about \ref Weights_Flattening)
while alternative formulations are explained in \ref Weights_Implementation.
\cgalFigureBegin{three_point_family_weight, three_point_family.svg}
Notation used for the three point family weight.
\cgalFigureEnd
@ -128,11 +133,14 @@ with notations shown in the figure below.
Here, `q` is a query point and the points `p0`, `p1`, and `p2` are ordered.
This weight supports only planar configurations (see more in section about \ref Weights_Flattening)
while alternative formulations are explained in \ref Weights_Implementation.
\cgalFigureBegin{wachspress_weight, wachspress.svg}
Notation used for the Wachspress weight.
\cgalFigureEnd
\cgalHeading{Other Formulations}
\cgalHeading{Alternative Formulations}
- This weight is equal to the \ref PkgWeightsRefAuthalicWeights "Authalic Weight".
- This weight is a special case of the \ref PkgWeightsRefThreePointFamilyWeights "Three Point Family Weight".
@ -155,11 +163,13 @@ with notations shown in the figure below.
Here, `q` is a query point and the points `p0`, `p1`, and `p2` are ordered.
Alternative formulations are explained in \ref Weights_Implementation.
\cgalFigureBegin{authalic_weight, authalic.svg}
Notation used for the authalic weight.
\cgalFigureEnd
\cgalHeading{Other Formulations}
\cgalHeading{Alternative Formulations}
- This weight is equal to the \ref PkgWeightsRefWachspressWeights "Wachspress Weight".
- This weight is a special case of the \ref PkgWeightsRefThreePointFamilyWeights "Three Point Family Weight".
@ -188,11 +198,14 @@ The \f$\pm\f$ sign is a sign of the weight that depends on the configuration.
Here, `q` is a query point and the points `p0`, `p1`, and `p2` are ordered.
This weight supports only planar configurations (see more in section about \ref Weights_Flattening)
while alternative formulations are explained in \ref Weights_Implementation.
\cgalFigureBegin{mean_value_weight, mean_value.svg}
Notation used for the mean value weight.
\cgalFigureEnd
\cgalHeading{Other Formulations}
\cgalHeading{Alternative Formulations}
- This weight is equal to the \ref PkgWeightsRefTangentWeights "Tangent Weight".
- This weight is a special case of the \ref PkgWeightsRefThreePointFamilyWeights "Three Point Family Weight".
@ -220,11 +233,13 @@ with notations shown in the figure below and dot products
Here, `q` is a query point and the points `p0`, `p1`, and `p2` are ordered.
Alternative formulations are explained in \ref Weights_Implementation.
\cgalFigureBegin{tangent_weight, tangent.svg}
Notation used for the tangent weight.
\cgalFigureEnd
\cgalHeading{Other Formulations}
\cgalHeading{Alternative Formulations}
- This weight is equal to the \ref PkgWeightsRefMeanValueWeights "Mean Value Weight".
- This weight is a special case of the \ref PkgWeightsRefThreePointFamilyWeights "Three Point Family Weight".
@ -247,11 +262,14 @@ with notations shown in the figure below.
Here, `q` is a query point and the points `p0`, `p1`, and `p2` are ordered.
This weight supports only planar configurations (see more in section about \ref Weights_Flattening)
while alternative formulations are explained in \ref Weights_Implementation.
\cgalFigureBegin{discrete_harmonic_weight, discrete_harmonic.svg}
Notation used for the discrete harmonic weight.
\cgalFigureEnd
\cgalHeading{Other Formulations}
\cgalHeading{Alternative Formulations}
- This weight is equal to the \ref PkgWeightsRefCotangentWeights "Cotangent Weight".
- This weight is a special case of the \ref PkgWeightsRefThreePointFamilyWeights "Three Point Family Weight".
@ -274,11 +292,13 @@ with notations shown in the figure below.
Here, `q` is a query point and the points `p0`, `p1`, and `p2` are ordered.
Alternative formulations are explained in \ref Weights_Implementation.
\cgalFigureBegin{cotangent_weight, cotangent.svg}
Notation used for the cotangent weight.
\cgalFigureEnd
\cgalHeading{Other Formulations}
\cgalHeading{Alternative Formulations}
- This weight is equal to the \ref PkgWeightsRefDiscreteHarmonicWeights "Discrete Harmonic Weight".
- This weight is a special case of the \ref PkgWeightsRefThreePointFamilyWeights "Three Point Family Weight".

View File

@ -70,7 +70,7 @@ Sometimes, such weights are referred as *local averaging regions*. These weights
lengths, areas, and volumes of 2D and 3D objects.
\section Weights_Interface Interface
\section Weights_Implementation Implementation
All weights have a simple and unified interface. In particular, all analytic weights take
a query point and three other points in 2D or 3D and return a unique scalar. They all
@ -92,6 +92,48 @@ is a unique scalar.
The parameter `traits` with a traits class can be omitted for all functions and classes
if it can be deduced from the input point type.
Several weights in this package have different implementations. One reason to have it is
explained in section about \ref Weights_Flattening. Another reason is that in different communities
the same weights are named and computed differently. If one searches for these weights,
one needs to know all their alternative names, which is tiresome. We provide the most common
names and implementations of these weights.
\subsection Weights_Flattening Flattening
\cgalFigureBegin{flattening, flattening.svg}
The non-planar configuration (top) is flattened to the planar configuration (bottom).
\cgalFigureEnd
When computing weights for a query point \f$q\f$ with respect to its neighbors
\f$p_0\f$, \f$p_1\f$, and \f$p_2\f$, the local configuration is a quadrilateral
[\f$p_0\f$, \f$p_1\f$, \f$p_2\f$, \f$q\f$] or two connected triangles [\f$q\f$, \f$p_0\f$, \f$p_1\f$]
and [\f$q\f$, \f$p_1\f$, \f$p_2\f$]. When computing 3D weights, these triangles are not
necessarily coplanar. When they are not coplanar, they can be made coplanar through the process
called *flattening* (see the Figure above), however the latter introduces a distortion because the
weights are computed with respect to the flattened configuration rather than to the original
non-flat configuration. Certain weights in this package support only flat configurations,
while other weights support both. The weights, which support non-flat configurations,
provide the corresponding overloads with 3D points, while other weights support only
2D point types. For example, \ref PkgWeightsRefCotangentWeights "cotangent weights" support both flat
and non-flat configurations, while \ref PkgWeightsRefDiscreteHarmonicWeights "discrete harmonic weights"
support only flat configurations.
If you still want to compute the 2D weights in 3D, you can either provide your own way to flatten
the 3D configuration or you can use one of the projection traits available in CGAL as the
last parameter to the weight function (see \ref Weights_Examples_ProjectionTraits for example).
\subsection Weights_Edge_Cases Edge Cases
None of the weights in this package is defined for query points on the boundaries. The boundary cases include:
- *edges*, for example [\f$p_0\f$, \f$p_1\f$] or [\f$p_1\f$, \f$p_2\f$] or any polygon edge and
- *corners*, for example \f$p_0\f$, \f$p_1\f$, or \f$p_2\f$ or any polygon corner.
Several weights also require other conditions to be satisifed. You should address the
reference manual for more details.
\section Weights_Examples Examples
@ -161,8 +203,8 @@ in the custom traits class.
A typical example of using weights is discretizing *Poisson* and *Laplace
equations* which play an important role in various geometry processing applications
such as, for example, \ref PkgSurfaceMeshDeformation "surface mesh deformation" and
\ref PkgSurfaceMeshParameterization "surface mesh parameterization" (see
such as, for example, \ref PkgSurfaceMeshDeformation "Surface Mesh Deformation" and
\ref PkgSurfaceMeshParameterization "Surface Mesh Parameterization" (see
also \ref Weights_Intro "Introduction" for more details). This example shows
how to write the *discretized Laplacian* for all vertices of the given triangle mesh in
matrix notation. We use the standard cotangent discretization weighted by the areas of
@ -171,22 +213,13 @@ the mixed Voronoi cells around each mesh vertex.
\cgalExample{Weights/weighted_laplacian.cpp}
\subsection Weights_Examples_Flattening Flattening and Convergence
\subsection Weights_Examples_Convergence Convergence
When computing weights for a query point `q` with respect to its neighbors
`p0`, `p1`, and `p2`, the local configuration is a quadrilateral `[p0, p1, p2, q]`
or two connected triangles `[q, p0, p1]` and `[q, p1, p2]`. When computing 3D weights,
these triangles are not necessarily coplanar. When they are not coplanar, we make them coplanar,
since several weights cannot be computed for non-coplanar triangles, however this
so-called *flattening* introduces a distortion since the weights are computed
not with respect to the original configuration but to its flattened version. This example
shows how this distortion progresses when the point `q1`, which is not in the plane, moves back
to the original flat configuration with `q0`. Moreover, this example shows how to use the
family of weights which includes multiple types of weights in one function. In particular,
we show how, by changing an input parameter, we converge from the Wachspress weights to
the mean value weights.
This little example shows how to use the family of weights which includes multiple types
of weights in one function. In particular, we show how, by changing an input parameter,
we converge from the Wachspress weights to the mean value weights.
\cgalExample{Weights/flattening.cpp}
\cgalExample{Weights/convergence.cpp}
\section Weights_History History

View File

@ -5,5 +5,5 @@
\example Weights/weighted_laplacian.cpp
\example Weights/projection_traits.cpp
\example Weights/custom_traits.cpp
\example Weights/flattening.cpp
\example Weights/convergence.cpp
*/

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 5.9 KiB

View File

@ -17,7 +17,7 @@ if(CGAL_FOUND)
create_single_source_cgal_program("coordinates_multiple_queries.cpp")
create_single_source_cgal_program("projection_traits.cpp")
create_single_source_cgal_program("custom_traits.cpp")
create_single_source_cgal_program("flattening.cpp")
create_single_source_cgal_program("convergence.cpp")
find_package(Eigen3 REQUIRED)
include(CGAL_Eigen3_support)
@ -25,11 +25,9 @@ if(CGAL_FOUND)
create_single_source_cgal_program("weighted_laplacian.cpp")
target_link_libraries(weighted_laplacian PUBLIC CGAL::Eigen3_support)
else()
message(WARNING
"Several examples require the Eigen library, and will not be compiled.")
message(WARNING "Several examples require the Eigen library, and will not be compiled.")
endif()
else()
message(WARNING
"This program requires the CGAL library, and will not be compiled.")
message(WARNING "This program requires the CGAL library, and will not be compiled.")
endif()

View File

@ -5,16 +5,16 @@
// Typedefs.
using Kernel = CGAL::Simple_cartesian<double>;
using FT = typename Kernel::FT;
using Point_3 = typename Kernel::Point_3;
using Point_2 = typename Kernel::Point_2;
int main() {
std::cout << std::fixed;
// 3D configuration.
const Point_3 p0(0, 1, 1);
const Point_3 p1(2, 0, 1);
const Point_3 p2(7, 1, 1);
const Point_3 q0(3, 1, 1);
const Point_2 p0(0, 1);
const Point_2 p1(2, 0);
const Point_2 p2(7, 1);
const Point_2 q0(3, 1);
// Choose a type of the weight:
// e.g. 0 - Wachspress (WP) weight; 1 - mean value (MV);
@ -35,19 +35,5 @@ int main() {
std::cout << CGAL::Weights::three_point_family_weight(p0, p1, p2, q0, x) << std::endl;
}
// Compute WP weights for q1, which is not on the plane [p0, p1, p2].
Point_3 q1(3, 1, 2);
std::cout << "3D wachspress (WP, q1): ";
std::cout << CGAL::Weights::three_point_family_weight(p0, p1, p2, q1, wp) << std::endl;
// Converge q1 towards q0 that is we flatten the configuration.
// We also compare the result with the authalic weight.
std::cout << "Converge q1 to q0: " << std::endl;
for (FT x = FT(0); x <= FT(1); x += step) {
std::cout << "3D wachspress/authalic: ";
q1 = Point_3(3, 1, FT(2) - x);
std::cout << CGAL::Weights::three_point_family_weight(p0, p1, p2, q1, wp) << "/";
std::cout << CGAL::Weights::authalic_weight(p0, p1, p2, q1) << std::endl;
}
return EXIT_SUCCESS;
}

View File

@ -11,7 +11,9 @@ int main() {
// Create a polygon and a query point.
const std::vector<Point_2> polygon =
{ Point_2(0, 0), Point_2(1, 0), Point_2(1, 1), Point_2(0, 1) };
const Point_2 query(FT(1) / FT(2), FT(1) / FT(2));
const FT half = FT(1) / FT(2);
const Point_2 query(half, half);
// Allocate memory for weights and coordinates.
std::vector<FT> weights;

View File

@ -1,30 +1,30 @@
#include <CGAL/Simple_cartesian.h>
#include <CGAL/Weights/utils.h>
#include <CGAL/Weights/mean_value_weights.h>
#include <CGAL/Weights/internal/Projection_traits_3.h>
#include <CGAL/Projection_traits_xy_3.h>
// Typedefs.
using Kernel = CGAL::Simple_cartesian<double>;
using FT = typename Kernel::FT;
using Point_3 = typename Kernel::Point_3;
using Vector_3 = typename Kernel::Vector_3;
using PTraits = CGAL::Weights::internal::Projection_traits_3<Kernel>;
using PTraits = CGAL::Projection_traits_xy_3<Kernel>;
int main() {
// Create a polygon and a query point.
const std::vector<Point_3> polygon =
{ Point_3(0, 0, 1), Point_3(1, 0, 1), Point_3(1, 1, 0), Point_3(0, 1, 0) };
const Point_3 query(FT(1) / FT(2), FT(1) / FT(2), FT(1) / FT(2));
{ Point_3(0, 0, 1), Point_3(1, 0, 1), Point_3(1, 1, 1), Point_3(0, 1, 1) };
const FT half = FT(1) / FT(2);
const Point_3 query(half, half, 1);
// Allocate memory for weights.
std::vector<FT> weights;
weights.reserve(polygon.size());
// Create projection traits with the right normal.
const FT quater = FT(1) / FT(4);
const Vector_3 normal(0, quater, quater);
const PTraits ptraits(normal);
// Create projection traits.
const PTraits ptraits;
// Compute weights.
CGAL::Weights::mean_value_weights_2(polygon, query, std::back_inserter(weights), ptraits);

View File

@ -3,6 +3,7 @@
// Typedefs.
using Kernel = CGAL::Simple_cartesian<double>;
using FT = typename Kernel::FT;
using Point_2 = typename Kernel::Point_2;
using Point_3 = typename Kernel::Point_3;
@ -25,8 +26,8 @@ int main() {
std::cout << CGAL::Weights::tangent_weight(t3, r3, p3, q3) << std::endl;
std::cout << "2D/3D Shepard weight: ";
std::cout << CGAL::Weights::shepard_weight(r2, q2, 2.0) << "/";
std::cout << CGAL::Weights::shepard_weight(r3, q3, 2.0) << std::endl;
std::cout << CGAL::Weights::shepard_weight(r2, q2, FT(2)) << "/";
std::cout << CGAL::Weights::shepard_weight(r3, q3, FT(2)) << std::endl;
std::cout << "2D/3D barycentric area: ";
std::cout << CGAL::Weights::barycentric_area(p2, q2, r2) << "/";

View File

@ -153,9 +153,7 @@ namespace Weights {
const auto squared_distance_2 =
traits.compute_squared_distance_2_object();
const FT d2 = squared_distance_2(q, r);
return authalic_ns::weight(
cot_gamma, cot_beta, d2);
return authalic_ns::weight(cot_gamma, cot_beta, d2);
}
template<typename GeomTraits>
@ -184,9 +182,7 @@ namespace Weights {
const auto squared_distance_3 =
traits.compute_squared_distance_3_object();
const FT d2 = squared_distance_3(q, r);
return authalic_ns::weight(
cot_gamma, cot_beta, d2);
return authalic_ns::weight(cot_gamma, cot_beta, d2);
}
template<typename GeomTraits>

View File

@ -59,20 +59,6 @@ namespace Weights {
const typename GeomTraits::Point_2& q,
const GeomTraits& traits) { }
/*!
\ingroup PkgWeightsRefDiscreteHarmonicWeights
\brief computes the discrete harmonic weight in 3D at `q` using the points `p0`, `p1`,
and `p2`, given a traits class `traits` with geometric objects, predicates, and constructions.
*/
template<typename GeomTraits>
typename GeomTraits::FT discrete_harmonic_weight(
const typename GeomTraits::Point_3& p0,
const typename GeomTraits::Point_3& p1,
const typename GeomTraits::Point_3& p2,
const typename GeomTraits::Point_3& q,
const GeomTraits& traits) { }
/*!
\ingroup PkgWeightsRefDiscreteHarmonicWeights
@ -86,19 +72,6 @@ namespace Weights {
const CGAL::Point_2<K>& p2,
const CGAL::Point_2<K>& q) { }
/*!
\ingroup PkgWeightsRefDiscreteHarmonicWeights
\brief computes the discrete harmonic weight in 3D at `q` using the points `p0`, `p1`,
and `p2`, which are parameterized by a `Kernel` K.
*/
template<typename K>
typename K::FT discrete_harmonic_weight(
const CGAL::Point_3<K>& p0,
const CGAL::Point_3<K>& p1,
const CGAL::Point_3<K>& p2,
const CGAL::Point_3<K>& q) { }
#endif // DOXYGEN_RUNNING
/// \cond SKIP_IN_MANUAL
@ -137,6 +110,8 @@ namespace Weights {
return discrete_harmonic_weight(t, r, p, q, traits);
}
namespace internal {
template<typename GeomTraits>
typename GeomTraits::FT discrete_harmonic_weight(
const typename GeomTraits::Point_3& t,
@ -151,7 +126,8 @@ namespace Weights {
traits,
t, r, p, q,
tf, rf, pf, qf);
return discrete_harmonic_weight(tf, rf, pf, qf, traits);
return CGAL::Weights::
discrete_harmonic_weight(tf, rf, pf, qf, traits);
}
template<typename GeomTraits>
@ -164,6 +140,9 @@ namespace Weights {
const GeomTraits traits;
return discrete_harmonic_weight(t, r, p, q, traits);
}
} // namespace internal
/// \endcond
/*!

View File

@ -1,95 +0,0 @@
// Copyright (c) 2020 GeometryFactory SARL (France)
// All rights reserved.
//
// This file is part of CGAL (www.cgal.org).
//
// $URL$
// $Id$
// SPDX-License-Identifier: GPL-3.0-or-later OR LicenseRef-Commercial
//
//
// Author(s) : Dmitry Anisimov
//
#ifndef CGAL_WEIGHTS_INTERNAL_PROJECTION_TRAITS_3_H
#define CGAL_WEIGHTS_INTERNAL_PROJECTION_TRAITS_3_H
// #include <CGAL/license/Weights.h>
#include <CGAL/Filtered_predicate_with_state.h>
#include <CGAL/Weights/internal/Projection_traits_base_3.h>
namespace CGAL {
namespace Weights {
namespace internal {
template<class Filtered_kernel >
class Filtered_projection_traits_3
: public Projection_traits_base_3<Filtered_kernel> {
using K = Filtered_kernel;
using Self = Filtered_projection_traits_3<K>;
using Base = Projection_traits_base_3<K>;
using Exact_kernel = typename K::Exact_kernel;
using Approximate_kernel = typename K::Approximate_kernel;
using C2E = typename K::C2E;
using C2F = typename K::C2F;
public:
using Exact_traits = Projection_traits_base_3<Exact_kernel>;
using Filtering_traits = Projection_traits_base_3<Approximate_kernel>;
public:
explicit Filtered_projection_traits_3(
const typename K::Vector_3& normal) : Base(normal) { }
#define CGAL_PROJ_TRAITS_FILTER_PRED(P, Pf, ACCESSOR) \
typedef Filtered_predicate_with_state< \
typename Exact_traits::P, \
typename Filtering_traits::P, \
C2E, \
C2F, \
typename K::Vector_3> P; \
P Pf() const { \
return P(this->ACCESSOR()); \
}
CGAL_PROJ_TRAITS_FILTER_PRED(
Orientation_2,
orientation_2_object,
normal)
CGAL_PROJ_TRAITS_FILTER_PRED(
Collinear_2,
collinear_2_object,
normal)
};
// This declaration is necessary for breaking the cyclic dependency.
template<class Filtered_kernel>
class Filtered_projection_traits_3;
template<class Kernel, bool Has_filtered_predicates = Kernel::Has_filtered_predicates>
class Projection_traits_3
: public Projection_traits_base_3<Kernel> {
public:
explicit Projection_traits_3(const typename Kernel::Vector_3& normal)
: Projection_traits_base_3<Kernel>(normal)
{ }
};
template<class Kernel>
class Projection_traits_3<Kernel, true>
: public Filtered_projection_traits_3<Kernel> {
public:
explicit Projection_traits_3(const typename Kernel::Vector_3& normal) :
Filtered_projection_traits_3<Kernel>(normal)
{ }
};
} // namespace internal
} // namespace Weights
} // namespace CGAL
#endif // CGAL_WEIGHTS_INTERNAL_PROJECTION_TRAITS_3_H

View File

@ -1,272 +0,0 @@
// Copyright (c) 2020 GeometryFactory SARL (France)
// All rights reserved.
//
// This file is part of CGAL (www.cgal.org).
//
// $URL$
// $Id$
// SPDX-License-Identifier: GPL-3.0-or-later OR LicenseRef-Commercial
//
//
// Author(s) : Dmitry Anisimov
//
#ifndef CGAL_WEIGHTS_INTERNAL_PROJECTION_TRAITS_BASE_3_H
#define CGAL_WEIGHTS_INTERNAL_PROJECTION_TRAITS_BASE_3_H
// #include <CGAL/license/Weights.h>
namespace CGAL {
namespace Weights {
namespace internal {
namespace ProjectionTraitsCartesianFunctors {
template <class Traits>
class Compare_along_axis {
using Vector_3 = typename Traits::Vector_3;
using Point = typename Traits::Point_2;
Vector_3 base;
public:
Compare_along_axis(const Vector_3& base) : base(base) { }
using result_type = Comparison_result;
Comparison_result operator() (const Point &p, const Point &q) const {
return compare(base * (p - q), 0);
}
};
template <class Traits>
class Less_along_axis {
using Vector_3 = typename Traits::Vector_3;
using Point = typename Traits::Point_2;
Vector_3 base;
public:
Less_along_axis(const Vector_3& base) : base(base) { }
using result_type = bool;
bool operator() (const Point &p, const Point &q) const {
return base * (p - q) < 0;
}
};
template<class Traits>
class Less_xy_along_axis {
using Vector_3 = typename Traits::Vector_3;
using Point = typename Traits::Point_2;
Vector_3 base1, base2;
public:
Less_xy_along_axis(const Vector_3& base1, const Vector_3& base2) :
base1(base1), base2(base2)
{ }
using result_type = bool;
bool operator() (const Point &p, const Point &q) const {
const Compare_along_axis<Traits> cx(base1);
const Comparison_result crx = cx(p, q);
if (crx == SMALLER) {
return true;
}
if (crx == LARGER) {
return false;
}
const Less_along_axis<Traits> ly(base2);
return ly(p, q);
}
};
template<class Traits>
class Equal_along_axis {
using Vector_3 = typename Traits::Vector_3;
using Point = typename Traits::Point_2;
Vector_3 base1, base2;
public:
Equal_along_axis(const Vector_3& base1, const Vector_3& base2) :
base1(base1), base2(base2)
{ }
using result_type = bool;
bool operator() (const Point &p, const Point &q) const {
const Compare_along_axis<Traits> cx(base1);
const Compare_along_axis<Traits> cy(base2);
const Comparison_result crx = cx(p, q);
const Comparison_result cry = cy(p, q);
if (crx == EQUAL && cry == EQUAL) {
return true;
}
return false;
}
};
template<class Traits>
class Projected_orientation_with_normal_3 {
using K = typename Traits::K;
using Point = typename Traits::Point_2;
using Vector_3 = typename Traits::Vector_3;
Vector_3 normal;
public:
using Orientation = typename K::Orientation;
using result_type = Orientation;
Projected_orientation_with_normal_3(const Vector_3& normal_) : normal(normal_) { }
Orientation operator()(const Point& p, const Point& q, const Point& r) const {
return orientation(q - p, r - p, normal);
}
};
template<class Traits>
class Projected_collinear_with_normal_3 {
using K = typename Traits::K;
using Point = typename Traits::Point_2;
using Vector_3 = typename Traits::Vector_3;
Vector_3 normal;
public:
using Collinear = typename K::Collinear_3;
using result_type = bool;
Projected_collinear_with_normal_3(const Vector_3& normal_) : normal(normal_) { }
bool operator()(const Point& p, const Point& q, const Point& r) const {
return collinear(p, q, r);
}
};
} // namespace ProjectionTraitsCartesianFunctors
template<class Kernel>
class Projection_traits_base_3 {
using Self = Projection_traits_base_3<Kernel>;
typename Kernel::Vector_3 n, b1, b2;
public:
using K = Kernel;
using FT = typename K::FT;
using Point_2 = typename K::Point_3;
using Vector_2 = typename K::Vector_3;
using Vector_3 = typename K::Vector_3;
explicit Projection_traits_base_3(const Vector_3& n_) : n(n_) {
CGAL_precondition(n != Vector_3(0, 0, 0));
const FT nx = n.x();
const FT ny = n.y();
const FT nz = n.z();
if (CGAL::abs(nz) >= CGAL::abs(ny)) {
b1 = Vector_3(nz, FT(0), -nx);
} else {
b1 = Vector_3(ny, -nx, FT(0));
}
b2 = cross_product(n, b1);
}
const Vector_3& normal() const {
return n;
}
const Vector_3& base1() const {
return b1;
}
const Vector_3& base2() const {
return b2;
}
using Less_xy_2
= ProjectionTraitsCartesianFunctors::Less_xy_along_axis<Self>;
using Equal_2
= ProjectionTraitsCartesianFunctors::Equal_along_axis<Self>;
using Orientation_2
= ProjectionTraitsCartesianFunctors::Projected_orientation_with_normal_3<Self>;
using Collinear_2
= ProjectionTraitsCartesianFunctors::Projected_collinear_with_normal_3<Self>;
using Compute_squared_distance_2
= typename K::Compute_squared_distance_3;
using Compute_squared_length_2
= typename K::Compute_squared_length_3;
using Compute_scalar_product_2
= typename K::Compute_scalar_product_3;
using Compute_area_2
= typename K::Compute_area_3;
using Construct_vector_2
= typename K::Construct_vector_3;
using Construct_circumcenter_2
= typename K::Construct_circumcenter_3;
Less_xy_2
less_xy_2_object() const {
return Less_xy_2(this->base1(), this->base2());
}
Equal_2
equal_2_object() const {
return Equal_2(this->base1(), this->base2());
}
Orientation_2
orientation_2_object() const {
return Orientation_2(this->normal());
}
Collinear_2
collinear_2_object() const {
return Collinear_2(this->normal());
}
Compute_squared_distance_2
compute_squared_distance_2_object() const {
return Compute_squared_distance_2();
}
Compute_squared_length_2
compute_squared_length_2_object() const {
return Compute_squared_length_2();
}
Compute_scalar_product_2
compute_scalar_product_2_object() const {
return Compute_scalar_product_2();
}
Compute_area_2
compute_area_2_object() const {
return Compute_area_2();
}
Construct_vector_2
construct_vector_2_object() const {
return Construct_vector_2();
}
Construct_circumcenter_2
construct_circumcenter_2_object() const {
return Construct_circumcenter_2();
}
};
} // namespace internal
} // namespace Weights
} // namespace CGAL
#endif // CGAL_WEIGHTS_INTERNAL_PROJECTION_TRAITS_BASE_3_H

View File

@ -93,20 +93,6 @@ namespace Weights {
const typename GeomTraits::Point_2& q,
const GeomTraits& traits) { }
/*!
\ingroup PkgWeightsRefMeanValueWeights
\brief computes the mean value weight in 3D at `q` using the points `p0`, `p1`,
and `p2`, given a traits class `traits` with geometric objects, predicates, and constructions.
*/
template<typename GeomTraits>
typename GeomTraits::FT mean_value_weight(
const typename GeomTraits::Point_3& p0,
const typename GeomTraits::Point_3& p1,
const typename GeomTraits::Point_3& p2,
const typename GeomTraits::Point_3& q,
const GeomTraits& traits) { }
/*!
\ingroup PkgWeightsRefMeanValueWeights
@ -120,19 +106,6 @@ namespace Weights {
const CGAL::Point_2<K>& p2,
const CGAL::Point_2<K>& q) { }
/*!
\ingroup PkgWeightsRefMeanValueWeights
\brief computes the mean value weight in 3D at `q` using the points `p0`, `p1`,
and `p2`, which are parameterized by a `Kernel` K.
*/
template<typename K>
typename K::FT mean_value_weight(
const CGAL::Point_3<K>& p0,
const CGAL::Point_3<K>& p1,
const CGAL::Point_3<K>& p2,
const CGAL::Point_3<K>& q) { }
#endif // DOXYGEN_RUNNING
/// \cond SKIP_IN_MANUAL
@ -182,6 +155,8 @@ namespace Weights {
return mean_value_weight(t, r, p, q, traits);
}
namespace internal {
template<typename GeomTraits>
typename GeomTraits::FT mean_value_weight(
const typename GeomTraits::Point_3& t,
@ -196,7 +171,8 @@ namespace Weights {
traits,
t, r, p, q,
tf, rf, pf, qf);
return mean_value_weight(tf, rf, pf, qf, traits);
return CGAL::Weights::
mean_value_weight(tf, rf, pf, qf, traits);
}
template<typename GeomTraits>
@ -209,6 +185,9 @@ namespace Weights {
const GeomTraits traits;
return mean_value_weight(t, r, p, q, traits);
}
} // namespace internal
/// \endcond
/*!

View File

@ -50,6 +50,18 @@ namespace Weights {
return w;
}
template<typename FT>
FT weight(const FT t1, const FT t2, const FT r) {
FT w = FT(0);
CGAL_precondition(r != FT(0));
if (r != FT(0)) {
const FT inv = FT(2) / r;
w = (t1 + t2) * inv;
}
return w;
}
template<typename FT>
FT weight(
const FT d1, const FT r, const FT d2,
@ -66,14 +78,76 @@ namespace Weights {
const FT inv2 = FT(2) / P2;
const FT t1 = A1 * inv1;
const FT t2 = A2 * inv2;
CGAL_precondition(r != FT(0));
if (r != FT(0)) {
const FT inv = FT(2) / r;
w = (t1 + t2) * inv;
}
w = weight(t1, t2, r);
}
return w;
}
// This is positive case only.
// This version is based on the positive area.
// This version is more precise for all positive cases.
template<typename GeomTraits>
typename GeomTraits::FT tangent_weight_v1(
const typename GeomTraits::Point_3& t,
const typename GeomTraits::Point_3& r,
const typename GeomTraits::Point_3& p,
const typename GeomTraits::Point_3& q,
const GeomTraits& traits) {
using FT = typename GeomTraits::FT;
const auto dot_product_3 =
traits.compute_scalar_product_3_object();
const auto construct_vector_3 =
traits.construct_vector_3_object();
const auto v1 = construct_vector_3(q, t);
const auto v2 = construct_vector_3(q, r);
const auto v3 = construct_vector_3(q, p);
const FT l1 = internal::length_3(traits, v1);
const FT l2 = internal::length_3(traits, v2);
const FT l3 = internal::length_3(traits, v3);
const FT A1 = internal::positive_area_3(traits, r, q, t);
const FT A2 = internal::positive_area_3(traits, p, q, r);
const FT D1 = dot_product_3(v1, v2);
const FT D2 = dot_product_3(v2, v3);
return weight(l1, l2, l3, A1, A2, D1, D2);
}
// This version handles both positive and negative cases.
// However, it is less precise.
template<typename GeomTraits>
typename GeomTraits::FT tangent_weight_v2(
const typename GeomTraits::Point_3& t,
const typename GeomTraits::Point_3& r,
const typename GeomTraits::Point_3& p,
const typename GeomTraits::Point_3& q,
const GeomTraits& traits) {
using FT = typename GeomTraits::FT;
const auto construct_vector_3 =
traits.construct_vector_3_object();
auto v1 = construct_vector_3(q, t);
auto v2 = construct_vector_3(q, r);
auto v3 = construct_vector_3(q, p);
const FT l2 = internal::length_3(traits, v2);
internal::normalize_3(traits, v1);
internal::normalize_3(traits, v2);
internal::normalize_3(traits, v3);
const double ha_rad_1 = internal::angle_3(traits, v1, v2) / 2.0;
const double ha_rad_2 = internal::angle_3(traits, v2, v3) / 2.0;
const FT t1 = static_cast<FT>(std::tan(ha_rad_1));
const FT t2 = static_cast<FT>(std::tan(ha_rad_2));
return weight(t1, t2, l2);
}
}
/// \endcond
@ -283,28 +357,8 @@ namespace Weights {
const typename GeomTraits::Point_3& q,
const GeomTraits& traits) {
using FT = typename GeomTraits::FT;
const auto dot_product_3 =
traits.compute_scalar_product_3_object();
const auto construct_vector_3 =
traits.construct_vector_3_object();
const auto v1 = construct_vector_3(q, t);
const auto v2 = construct_vector_3(q, r);
const auto v3 = construct_vector_3(q, p);
const FT l1 = internal::length_3(traits, v1);
const FT l2 = internal::length_3(traits, v2);
const FT l3 = internal::length_3(traits, v3);
const FT A1 = internal::positive_area_3(traits, r, q, t);
const FT A2 = internal::positive_area_3(traits, p, q, r);
const FT D1 = dot_product_3(v1, v2);
const FT D2 = dot_product_3(v2, v3);
return tangent_ns::weight(
l1, l2, l3, A1, A2, D1, D2);
// return tangent_ns::tangent_weight_v1(t, r, p, q, traits);
return tangent_ns::tangent_weight_v2(t, r, p, q, traits);
}
template<typename GeomTraits>

View File

@ -75,22 +75,6 @@ namespace Weights {
const typename GeomTraits::FT a,
const GeomTraits& traits) { }
/*!
\ingroup PkgWeightsRefThreePointFamilyWeights
\brief computes the three-point family weight in 3D at `q` using the points `p0`, `p1`,
and `p2` and the power parameter `a`, given a traits class `traits` with geometric objects,
predicates, and constructions.
*/
template<typename GeomTraits>
typename GeomTraits::FT three_point_family_weight(
const typename GeomTraits::Point_3& p0,
const typename GeomTraits::Point_3& p1,
const typename GeomTraits::Point_3& p2,
const typename GeomTraits::Point_3& q,
const typename GeomTraits::FT a,
const GeomTraits& traits) { }
/*!
\ingroup PkgWeightsRefThreePointFamilyWeights
@ -106,21 +90,6 @@ namespace Weights {
const CGAL::Point_2<K>& q,
const typename K::FT a = typename K::FT(1)) { }
/*!
\ingroup PkgWeightsRefThreePointFamilyWeights
\brief computes the three-point family weight in 3D at `q` using the points `p0`, `p1`,
and `p2`, which are parameterized by a `Kernel` K, and the power parameter `a`, which
can be omitted.
*/
template<typename K>
typename K::FT three_point_family_weight(
const CGAL::Point_3<K>& p0,
const CGAL::Point_3<K>& p1,
const CGAL::Point_3<K>& p2,
const CGAL::Point_3<K>& q,
const typename K::FT a = typename K::FT(1)) { }
#endif // DOXYGEN_RUNNING
/// \cond SKIP_IN_MANUAL
@ -159,6 +128,37 @@ namespace Weights {
return three_point_family_weight(t, r, p, q, a, traits);
}
namespace internal {
// Example of flattening:
// 3D configuration.
// const Point_3 p0(0, 1, 1);
// const Point_3 p1(2, 0, 1);
// const Point_3 p2(7, 1, 1);
// const Point_3 q0(3, 1, 1);
// Choose a type of the weight:
// e.g. 0 - Wachspress (WP) weight.
// const FT wp = FT(0);
// Compute WP weights for q1, which is not on the plane [p0, p1, p2].
// Point_3 q1(3, 1, 2);
// std::cout << "3D wachspress (WP, q1): ";
// std::cout << CGAL::Weights::three_point_family_weight(p0, p1, p2, q1, wp) << std::endl;
// Converge q1 towards q0 that is we flatten the configuration.
// We also compare the result with the authalic weight.
// std::cout << "Converge q1 to q0: " << std::endl;
// for (FT x = FT(0); x <= FT(1); x += step) {
// std::cout << "3D wachspress/authalic: ";
// q1 = Point_3(3, 1, FT(2) - x);
// std::cout << CGAL::Weights::three_point_family_weight(p0, p1, p2, q1, wp) << "/";
// std::cout << CGAL::Weights::authalic_weight(p0, p1, p2, q1) << std::endl;
// }
template<typename GeomTraits>
typename GeomTraits::FT three_point_family_weight(
const typename GeomTraits::Point_3& t,
@ -174,7 +174,8 @@ namespace Weights {
traits,
t, r, p, q,
tf, rf, pf, qf);
return three_point_family_weight(tf, rf, pf, qf, a, traits);
return CGAL::Weights::
three_point_family_weight(tf, rf, pf, qf, a, traits);
}
template<typename GeomTraits>
@ -189,6 +190,9 @@ namespace Weights {
const GeomTraits traits;
return three_point_family_weight(t, r, p, q, a, traits);
}
} // namespace internal
/// \endcond
} // namespace Weights

View File

@ -57,20 +57,6 @@ namespace Weights {
const typename GeomTraits::Point_2& q,
const GeomTraits& traits) { }
/*!
\ingroup PkgWeightsRefWachspressWeights
\brief computes the Wachspress weight in 3D at `q` using the points `p0`, `p1`,
and `p2`, given a traits class `traits` with geometric objects, predicates, and constructions.
*/
template<typename GeomTraits>
typename GeomTraits::FT wachspress_weight(
const typename GeomTraits::Point_3& p0,
const typename GeomTraits::Point_3& p1,
const typename GeomTraits::Point_3& p2,
const typename GeomTraits::Point_3& q,
const GeomTraits& traits) { }
/*!
\ingroup PkgWeightsRefWachspressWeights
@ -84,19 +70,6 @@ namespace Weights {
const CGAL::Point_2<K>& p2,
const CGAL::Point_2<K>& q) { }
/*!
\ingroup PkgWeightsRefWachspressWeights
\brief computes the Wachspress weight in 3D at `q` using the points `p0`, `p1`,
and `p2`, which are parameterized by a `Kernel` K.
*/
template<typename K>
typename K::FT wachspress_weight(
const CGAL::Point_3<K>& p0,
const CGAL::Point_3<K>& p1,
const CGAL::Point_3<K>& p2,
const CGAL::Point_3<K>& q) { }
#endif // DOXYGEN_RUNNING
/// \cond SKIP_IN_MANUAL
@ -126,6 +99,8 @@ namespace Weights {
return wachspress_weight(t, r, p, q, traits);
}
namespace internal {
template<typename GeomTraits>
typename GeomTraits::FT wachspress_weight(
const typename GeomTraits::Point_3& t,
@ -140,7 +115,8 @@ namespace Weights {
traits,
t, r, p, q,
tf, rf, pf, qf);
return wachspress_weight(tf, rf, pf, qf, traits);
return CGAL::Weights::
wachspress_weight(tf, rf, pf, qf, traits);
}
template<typename GeomTraits>
@ -153,6 +129,9 @@ namespace Weights {
const GeomTraits traits;
return wachspress_weight(t, r, p, q, traits);
}
} // namespace internal
/// \endcond
/*!

View File

@ -16,6 +16,7 @@ if(CGAL_FOUND)
create_single_source_cgal_program("test_shepard_weights.cpp")
create_single_source_cgal_program("test_inverse_distance_weights.cpp")
create_single_source_cgal_program("test_three_point_family_weights.cpp")
create_single_source_cgal_program("test_projected_weights.cpp")
create_single_source_cgal_program("test_wachspress_weights.cpp")
create_single_source_cgal_program("test_authalic_weights.cpp")
@ -33,6 +34,5 @@ if(CGAL_FOUND)
create_single_source_cgal_program("test_mixed_voronoi_region_weights.cpp")
else()
message(WARNING
"This program requires the CGAL library, and will not be compiled.")
message(WARNING "This program requires the CGAL library, and will not be compiled.")
endif()

View File

@ -0,0 +1,557 @@
#ifndef CGAL_WEIGHTS_TESTS_UTILS_H
#define CGAL_WEIGHTS_TESTS_UTILS_H
// STL includes.
#include <array>
#include <vector>
#include <cassert>
#include <algorithm>
#include <string>
// CGAL includes.
#include <CGAL/assertions.h>
#include <CGAL/Projection_traits_xy_3.h>
#include <CGAL/Weights/utils.h>
namespace tests {
template<typename FT>
FT get_tolerance() {
return FT(1) / FT(10000000000);
}
template<typename Kernel>
std::vector< std::array<typename Kernel::Point_2, 3> >
get_all_triangles() {
using Point_2 = typename Kernel::Point_2;
const std::array<Point_2, 3> triangle0 = {
Point_2(-1, 0), Point_2(0, -1), Point_2(1, 0)
};
const std::array<Point_2, 3> triangle1 = {
Point_2(-2, 0), Point_2(0, -1), Point_2(2, 0)
};
const std::array<Point_2, 3> triangle2 = {
Point_2(-2, 0), Point_2(-2, -2), Point_2(2, 0)
};
const std::array<Point_2, 3> triangle3 = {
Point_2(-2, 0), Point_2(2, -2), Point_2(2, 0)
};
return { triangle0, triangle1, triangle2, triangle3 };
}
template<typename Kernel>
std::vector< std::array<typename Kernel::Point_2, 3> >
get_symmetric_triangles() {
using Point_2 = typename Kernel::Point_2;
const std::array<Point_2, 3> triangle0 = {
Point_2(-1, 0), Point_2(0, -1), Point_2(1, 0)
};
const std::array<Point_2, 3> triangle1 = {
Point_2(-2, 0), Point_2(0, -1), Point_2(2, 0)
};
const std::array<Point_2, 3> triangle2 = {
Point_2(-3, 0), Point_2(0, -1), Point_2(3, 0)
};
return { triangle0, triangle1, triangle2 };
}
template<typename Kernel>
std::vector< std::array<typename Kernel::Point_2, 3> >
get_uniform_triangles() {
using Point_2 = typename Kernel::Point_2;
const std::array<Point_2, 3> triangle0 = {
Point_2(-1, 0), Point_2(0, -1), Point_2(1, 0)
};
const std::array<Point_2, 3> triangle1 = {
Point_2(-2, 0), Point_2(0, -2), Point_2(2, 0)
};
const std::array<Point_2, 3> triangle2 = {
Point_2(1, 0), Point_2(-1, 0), Point_2(-1, -2)
};
const std::array<Point_2, 3> triangle3 = {
Point_2(1, -2), Point_2(1, 0), Point_2(-1, 0)
};
return { triangle0, triangle1, triangle2, triangle3 };
}
template<typename Kernel>
std::vector< std::vector<typename Kernel::Point_2> >
get_all_polygons() {
using Point_2 = typename Kernel::Point_2;
const std::vector<Point_2> polygon0 = {
Point_2(-2, -2), Point_2(2, -2), Point_2(0, 2)
};
const std::vector<Point_2> polygon1 = {
Point_2(-1, -1), Point_2(1, -1), Point_2(1, 1), Point_2(-1, 1)
};
const std::vector<Point_2> polygon2 = {
Point_2(-2, 0), Point_2(0, -2), Point_2(2, 0), Point_2(0, 2)
};
const std::vector<Point_2> polygon3 = {
Point_2(-2, -2), Point_2(2, -2), Point_2(2, 0), Point_2(0, 2), Point_2(-2, 0)
};
return { polygon0, polygon1, polygon2, polygon3 };
}
template<
typename Kernel,
typename Weight_wrapper>
bool test_query(
const Weight_wrapper& wrapper,
const typename Kernel::Point_2& query,
const std::array<typename Kernel::Point_2, 3>& neighbors) {
using FT = typename Kernel::FT;
using Point_2 = typename Kernel::Point_2;
using Point_3 = typename Kernel::Point_3;
const FT tol = get_tolerance<FT>();
// 2D configuration.
const Point_2& t2 = neighbors[0];
const Point_2& r2 = neighbors[1];
const Point_2& p2 = neighbors[2];
const Point_2& q2 = query;
// 3D configuration.
const Point_3 t3(t2.x(), t2.y(), 1);
const Point_3 r3(r2.x(), r2.y(), 1);
const Point_3 p3(p2.x(), p2.y(), 1);
const Point_3 q3(q2.x(), q2.y(), 1);
const auto a2 = wrapper.weight_a(t2, r2, p2, q2);
const auto b2 = wrapper.weight_b(t2, r2, p2, q2);
CGAL_assertion(a2 >= FT(0) && b2 >= FT(0));
if (a2 < FT(0) || b2 < FT(0)) return false;
CGAL_assertion(CGAL::abs(a2 - b2) < tol);
if (CGAL::abs(a2 - b2) >= tol) return false;
if (wrapper.supports_3d()) {
const auto a3 = wrapper.weight_a(t3, r3, p3, q3);
const auto b3 = wrapper.weight_b(t3, r3, p3, q3);
CGAL_assertion(a3 >= FT(0) && b3 >= FT(0));
if (a3 < FT(0) || b3 < FT(0)) return false;
CGAL_assertion(CGAL::abs(a3 - b3) < tol);
if (CGAL::abs(a3 - b3) >= tol) return false;
CGAL_assertion(CGAL::abs(a2 - a3) < tol);
CGAL_assertion(CGAL::abs(b2 - b3) < tol);
if (CGAL::abs(a2 - a3) >= tol) return false;
if (CGAL::abs(b2 - b3) >= tol) return false;
}
return true;
}
template<
typename Kernel,
typename Weight_wrapper>
bool test_symmetry_x(
const Weight_wrapper& wrapper,
const std::array<typename Kernel::Point_2, 3>& neighbors,
const typename Kernel::FT& x) {
using FT = typename Kernel::FT;
using Point_2 = typename Kernel::Point_2;
using Point_3 = typename Kernel::Point_3;
const FT tol = get_tolerance<FT>();
// 2D configuration.
const Point_2& t2 = neighbors[0];
const Point_2& r2 = neighbors[1];
const Point_2& p2 = neighbors[2];
// 3D configuration.
const Point_3 t3(t2.x(), t2.y(), 1);
const Point_3 r3(r2.x(), r2.y(), 1);
const Point_3 p3(p2.x(), p2.y(), 1);
const auto a2 = wrapper.weight_a(t2, r2, p2, Point_2(-x, 0));
const auto b2 = wrapper.weight_a(t2, r2, p2, Point_2(+x, 0));
CGAL_assertion(a2 >= FT(0) && b2 >= FT(0));
if (a2 < FT(0) || b2 < FT(0)) return false;
CGAL_assertion(CGAL::abs(a2 - b2) < tol);
if (CGAL::abs(a2 - b2) >= tol) return false;
if (wrapper.supports_3d()) {
const auto a3 = wrapper.weight_a(t3, r3, p3, Point_3(-x, 0, 1));
const auto b3 = wrapper.weight_a(t3, r3, p3, Point_3(+x, 0, 1));
CGAL_assertion(a3 >= FT(0) && b3 >= FT(0));
if (a3 < FT(0) || b3 < FT(0)) return false;
CGAL_assertion(CGAL::abs(a3 - b3) < tol);
if (CGAL::abs(a3 - b3) >= tol) return false;
CGAL_assertion(CGAL::abs(a2 - a3) < tol);
CGAL_assertion(CGAL::abs(b2 - b3) < tol);
if (CGAL::abs(a2 - a3) >= tol) return false;
if (CGAL::abs(b2 - b3) >= tol) return false;
}
return true;
}
template<
typename Kernel,
typename Weight_wrapper_1,
typename Weight_wrapper_2>
bool test_compare(
const Weight_wrapper_1& wrapper1,
const Weight_wrapper_2& wrapper2,
const typename Kernel::Point_2& query,
const std::array<typename Kernel::Point_2, 3>& neighbors) {
using FT = typename Kernel::FT;
using Point_2 = typename Kernel::Point_2;
using Point_3 = typename Kernel::Point_3;
const FT tol = get_tolerance<FT>();
// 2D configuration.
const Point_2& t2 = neighbors[0];
const Point_2& r2 = neighbors[1];
const Point_2& p2 = neighbors[2];
const Point_2& q2 = query;
// 3D configuration.
const Point_3 t3(t2.x(), t2.y(), 1);
const Point_3 r3(r2.x(), r2.y(), 1);
const Point_3 p3(p2.x(), p2.y(), 1);
const Point_3 q3(q2.x(), q2.y(), 1);
const auto a2 = wrapper1.weight_a(t2, r2, p2, q2);
const auto b2 = wrapper2.weight_a(t2, r2, p2, q2);
CGAL_assertion(a2 >= FT(0) && b2 >= FT(0));
if (a2 < FT(0) || b2 < FT(0)) return false;
CGAL_assertion(CGAL::abs(a2 - b2) < tol);
if (CGAL::abs(a2 - b2) >= tol) return false;
if (wrapper1.supports_3d() && wrapper2.supports_3d()) {
const auto a3 = wrapper1.weight_a(t3, r3, p3, q3);
const auto b3 = wrapper2.weight_a(t3, r3, p3, q3);
CGAL_assertion(a3 >= FT(0) && b3 >= FT(0));
if (a3 < FT(0) || b3 < FT(0)) return false;
CGAL_assertion(CGAL::abs(a3 - b3) < tol);
if (CGAL::abs(a3 - b3) >= tol) return false;
}
return true;
}
template<
typename Kernel,
typename Weight_wrapper>
bool test_neighbors(
const Weight_wrapper& wrapper,
const std::array<typename Kernel::Point_2, 3>& neighbors) {
using FT = typename Kernel::FT;
using Point_2 = typename Kernel::Point_2;
using Point_3 = typename Kernel::Point_3;
const FT tol = get_tolerance<FT>();
// 2D configuration.
const Point_2& p2 = neighbors[0];
const Point_2& q2 = neighbors[1];
const Point_2& r2 = neighbors[2];
// 3D configuration.
const Point_3 p3(p2.x(), p2.y(), 1);
const Point_3 q3(q2.x(), q2.y(), 1);
const Point_3 r3(r2.x(), r2.y(), 1);
const auto a2 = wrapper.weight(p2, q2, r2);
const auto a3 = wrapper.weight(p3, q3, r3);
CGAL_assertion(a2 >= FT(0) && a3 >= FT(0));
if (a2 < FT(0) || a3 < FT(0)) return false;
CGAL_assertion(CGAL::abs(a2 - a3) < tol);
if (CGAL::abs(a2 - a3) >= tol) return false;
return true;
}
template<
typename Kernel,
typename Weight_wrapper>
bool test_area(
const Weight_wrapper& wrapper,
const std::array<typename Kernel::Point_2, 3>& neighbors) {
using FT = typename Kernel::FT;
using Point_2 = typename Kernel::Point_2;
using Point_3 = typename Kernel::Point_3;
// 2D configuration.
const Point_2& p2 = neighbors[0];
const Point_2& q2 = neighbors[1];
const Point_2& r2 = neighbors[2];
// 3D configuration.
const Point_3 p3(p2.x(), p2.y(), 1);
const Point_3 q3(q2.x(), q2.y(), 1);
const Point_3 r3(r2.x(), r2.y(), 1);
const auto a2 = wrapper.weight(p2, q2, r2);
const auto a3 = wrapper.weight(p3, q3, r3);
CGAL_assertion(a2 <= CGAL::Weights::area(p2, q2, r2));
CGAL_assertion(a3 <= CGAL::Weights::area(p3, q3, r3));
if (a2 > CGAL::Weights::area(p2, q2, r2)) return false;
if (a3 > CGAL::Weights::area(p3, q3, r3)) return false;
CGAL_assertion(a2 >= FT(0));
CGAL_assertion(a3 >= FT(0));
if (a2 < FT(0)) return false;
if (a3 < FT(0)) return false;
return true;
}
template<typename FT, typename Point>
bool test_coordinates(
const Point& query,
const std::vector<Point>& polygon,
const std::vector<FT>& weights) {
CGAL_assertion(weights.size() > 0);
if (weights.size() == 0) return false;
// Compute the sum of weights.
const FT tol = get_tolerance<FT>();
FT sum = FT(0);
for (const FT& weight : weights) {
sum += weight;
}
CGAL_assertion(sum >= tol);
if (sum < tol) return false;
// Compute coordinates.
std::vector<FT> coordinates;
coordinates.reserve(weights.size());
for (const FT& weight : weights) {
coordinates.push_back(weight / sum);
}
CGAL_assertion(coordinates.size() == weights.size());
if (coordinates.size() != weights.size()) return false;
// Test partition of unity.
sum = FT(0);
for (const FT& coordinate : coordinates) {
sum += coordinate;
}
CGAL_assertion(CGAL::abs(FT(1) - sum) < tol);
if (CGAL::abs(FT(1) - sum) >= tol) return false;
// Test linear precision.
FT x = FT(0), y = FT(0);
for (std::size_t i = 0; i < polygon.size(); ++i) {
x += coordinates[i] * polygon[i].x();
y += coordinates[i] * polygon[i].y();
}
CGAL_assertion(CGAL::abs(query.x() - x) < tol);
CGAL_assertion(CGAL::abs(query.y() - y) < tol);
if (CGAL::abs(query.x() - x) >= tol) return false;
if (CGAL::abs(query.y() - y) >= tol) return false;
return true;
}
template<
typename Kernel,
typename Weight_wrapper>
bool test_on_polygon(
const Weight_wrapper& wrapper,
const typename Kernel::Point_2& query_2,
const std::vector<typename Kernel::Point_2>& polygon_2) {
// Get weights.
using FT = typename Kernel::FT;
CGAL_assertion(polygon_2.size() >= 3);
if (polygon_2.size() < 3) return false;
// 2D version.
std::vector<FT> weights_2;
weights_2.reserve(polygon_2.size());
wrapper.compute_on_polygon(
polygon_2, query_2, Kernel(), std::back_inserter(weights_2));
CGAL_assertion(weights_2.size() == polygon_2.size());
if (weights_2.size() != polygon_2.size()) return false;
if (!test_coordinates(query_2, polygon_2, weights_2)) return false;
// 3D version.
using Point_3 = typename Kernel::Point_3;
const Point_3 query_3(query_2.x(), query_2.y(), 1);
std::vector<Point_3> polygon_3;
polygon_3.reserve(polygon_2.size());
for (const auto& vertex_2 : polygon_2) {
polygon_3.push_back(Point_3(vertex_2.x(), vertex_2.y(), 1));
}
CGAL_assertion(polygon_3.size() == polygon_2.size());
if (polygon_3.size() != polygon_2.size()) return false;
const CGAL::Projection_traits_xy_3<Kernel> ptraits;
std::vector<FT> weights_3;
weights_3.reserve(polygon_3.size());
wrapper.compute_on_polygon(
polygon_3, query_3, ptraits, std::back_inserter(weights_3));
CGAL_assertion(weights_3.size() == polygon_3.size());
if (weights_3.size() != polygon_3.size()) return false;
if (!test_coordinates(query_3, polygon_3, weights_3)) return false;
return true;
}
template<
typename Kernel,
typename Weight_wrapper>
bool test_barycentric_properties(
const Weight_wrapper& wrapper,
const typename Kernel::Point_2& query,
const std::vector<typename Kernel::Point_2>& polygon) {
// Get weights.
using FT = typename Kernel::FT;
const std::size_t n = polygon.size();
CGAL_assertion(n >= 3);
if (n < 3) return false;
// Check properties.
std::vector<FT> weights;
weights.reserve(n);
for (std::size_t i = 0; i < n; ++i) {
const std::size_t im = (i + n - 1) % n;
const std::size_t ip = (i + 1) % n;
const auto& t = polygon[im];
const auto& r = polygon[i];
const auto& p = polygon[ip];
const auto& q = query;
const FT weight = wrapper.weight_a(t, r, p, q);
weights.push_back(weight);
}
CGAL_assertion(weights.size() == n);
if (weights.size() != n) return false;
if (!test_coordinates(query, polygon, weights)) return false;
return true;
}
template<
typename Kernel,
typename Weight_wrapper_1,
typename Weight_wrapper_2>
bool test_analytic_weight(
const Weight_wrapper_1& weight,
const Weight_wrapper_2& alternative) {
using FT = typename Kernel::FT;
using Point_2 = typename Kernel::Point_2;
// Data.
const FT q = FT(1) / FT(4);
const FT h = FT(1) / FT(2);
const FT t = FT(3) / FT(4);
const Point_2 zero(0, 0);
const std::vector<Point_2> queries = {
Point_2(-q, 0), Point_2(+q, 0), Point_2(0, -q), Point_2(0, +q),
Point_2(-h, 0), Point_2(+h, 0), Point_2(0, -h), Point_2(0, +h),
Point_2(-t, 0), Point_2(+t, 0), Point_2(0, -t), Point_2(0, +t)
};
// Test query points.
auto configs = get_all_triangles<Kernel>();
for (const auto& config : configs) {
if (!test_query<Kernel>(weight, zero, config)) return false;
for (const auto& query : queries) {
if (!test_query<Kernel>(weight, query, config)) return false;
}
}
// Test alternative formulations.
for (const auto& config : configs) {
if (!test_compare<Kernel>(weight, alternative, zero, config)) {
return false;
}
for (const auto& query : queries) {
if (!test_compare<Kernel>(weight, alternative, query, config)) {
return false;
}
}
}
// Test symmetry along x axis.
configs = get_symmetric_triangles<Kernel>();
for (const auto& config : configs) {
if (!test_symmetry_x<Kernel>(weight, config, q)) return false;
if (!test_symmetry_x<Kernel>(weight, config, h)) return false;
if (!test_symmetry_x<Kernel>(weight, config, t)) return false;
}
// Test barycentric properties.
if (weight.is_barycentric()) {
const auto polygons = get_all_polygons<Kernel>();
for (const auto& polygon : polygons) {
if (!test_barycentric_properties<Kernel>(weight, zero, polygon)) {
return false;
}
for (const auto& query : queries) {
if (!test_barycentric_properties<Kernel>(weight, query, polygon)) {
return false;
}
}
}
}
return true;
}
template<
typename Kernel,
typename Weight_wrapper_1,
typename Weight_wrapper_2>
bool test_barycentric_weight(
const Weight_wrapper_1& weight,
const Weight_wrapper_2& alternative) {
using FT = typename Kernel::FT;
using Point_2 = typename Kernel::Point_2;
// Data.
const FT q = FT(1) / FT(4);
const FT h = FT(1) / FT(2);
const Point_2 zero(0, 0);
const std::vector<Point_2> queries = {
Point_2(-h, 0), Point_2(+h, 0), Point_2(-q, 0), Point_2(+q, 0),
Point_2( 0, -h), Point_2( 0, +h), Point_2( 0, -q), Point_2( 0, +q),
Point_2(-h, -h), Point_2(+h, +h), Point_2(-q, -q), Point_2(+q, +q),
Point_2(-h, +q), Point_2(+h, -q), Point_2(-q, +h), Point_2(+q, -h)
};
// Test analytic formulations.
if (!test_analytic_weight<Kernel>(weight, alternative)) {
return false;
}
// Test on polygons.
const auto polygons = get_all_polygons<Kernel>();
for (const auto& polygon : polygons) {
if (!test_on_polygon<Kernel>(weight, zero, polygon)) return false;
for (const auto& query : queries) {
if (!test_on_polygon<Kernel>(weight, query, polygon)) {
return false;
}
}
}
return true;
}
template<
typename Kernel,
typename Weight_wrapper>
bool test_region_weight(const Weight_wrapper& weight) {
// Test neighborhoods.
auto configs = get_all_triangles<Kernel>();
for (const auto& config : configs) {
if (!test_neighbors<Kernel>(weight, config)) return false;
}
// Test areas.
configs = get_uniform_triangles<Kernel>();
for (const auto& config : configs) {
if (!test_area<Kernel>(weight, config)) return false;
}
return true;
}
} // namespace tests
#endif // CGAL_WEIGHTS_TESTS_UTILS_H

View File

@ -0,0 +1,265 @@
#ifndef CGAL_WEIGHTS_TESTS_WRAPPERS_H
#define CGAL_WEIGHTS_TESTS_WRAPPERS_H
// STL includes.
#include <vector>
#include <string>
// CGAL includes.
#include <CGAL/Weights.h>
namespace wrappers {
template<typename Kernel>
struct Authalic_wrapper {
using FT = typename Kernel::FT;
template<typename Point>
FT weight_a(const Point& t, const Point& r, const Point& p, const Point& q) const {
return CGAL::Weights::authalic_weight(t, r, p, q);
}
template<typename Point>
FT weight_b(const Point& t, const Point& r, const Point& p, const Point& q) const {
return
CGAL::Weights::half_authalic_weight(
CGAL::Weights::cotangent(t, r, q),
CGAL::Weights::squared_distance(q, r)) +
CGAL::Weights::half_authalic_weight(
CGAL::Weights::cotangent(q, r, p),
CGAL::Weights::squared_distance(q, r));
}
bool supports_3d() const { return true; }
bool is_barycentric() const { return true; }
};
template<typename Kernel>
struct Cotangent_wrapper {
using FT = typename Kernel::FT;
template<typename Point>
FT weight_a(const Point& t, const Point& r, const Point& p, const Point& q) const {
return CGAL::Weights::cotangent_weight(t, r, p, q);
}
template<typename Point>
FT weight_b(const Point& t, const Point& r, const Point& p, const Point& q) const {
return
CGAL::Weights::half_cotangent_weight(
CGAL::Weights::cotangent(q, t, r)) +
CGAL::Weights::half_cotangent_weight(
CGAL::Weights::cotangent(r, p, q));
}
bool supports_3d() const { return true; }
bool is_barycentric() const { return true; }
};
template<typename Kernel>
struct Tangent_wrapper {
using FT = typename Kernel::FT;
template<typename Point>
FT weight_a(const Point& t, const Point& r, const Point& p, const Point& q) const {
return CGAL::Weights::tangent_weight(t, r, p, q);
}
template<typename Point>
FT weight_b(const Point& t, const Point& r, const Point& p, const Point& q) const {
return
CGAL::Weights::half_tangent_weight(
CGAL::Weights::distance(r, q),
CGAL::Weights::distance(t, q),
CGAL::Weights::area(r, q, t),
CGAL::Weights::scalar_product(r, q, t)) +
CGAL::Weights::half_tangent_weight(
CGAL::Weights::distance(r, q),
CGAL::Weights::distance(p, q),
CGAL::Weights::area(p, q, r),
CGAL::Weights::scalar_product(p, q, r));
}
bool supports_3d() const { return true; }
bool is_barycentric() const { return true; }
};
template<typename Kernel>
struct Wachspress_wrapper {
using FT = typename Kernel::FT;
using Point_2 = typename Kernel::Point_2;
using Point_3 = typename Kernel::Point_3;
FT weight_a(const Point_2& t, const Point_2& r, const Point_2& p, const Point_2& q) const {
return CGAL::Weights::wachspress_weight(t, r, p, q);
}
FT weight_a(const Point_3&, const Point_3&, const Point_3&, const Point_3&) const {
return FT(-1);
}
template<typename Point>
FT weight_b(const Point& t, const Point& r, const Point& p, const Point& q) const {
return weight_a(t, r, p, q);
}
template<typename Polygon, typename Point, typename Traits, typename OutputIterator>
void compute_on_polygon(
const Polygon& polygon, const Point& query, const Traits& traits, OutputIterator out) const {
CGAL::Weights::wachspress_weights_2(polygon, query, out, traits);
}
bool supports_3d() const { return false; }
bool is_barycentric() const { return true; }
};
template<typename Kernel>
struct Discrete_harmonic_wrapper {
using FT = typename Kernel::FT;
using Point_2 = typename Kernel::Point_2;
using Point_3 = typename Kernel::Point_3;
FT weight_a(const Point_2& t, const Point_2& r, const Point_2& p, const Point_2& q) const {
return CGAL::Weights::discrete_harmonic_weight(t, r, p, q);
}
FT weight_a(const Point_3&, const Point_3&, const Point_3&, const Point_3&) const {
return FT(-1);
}
template<typename Point>
FT weight_b(const Point& t, const Point& r, const Point& p, const Point& q) const {
return weight_a(t, r, p, q);
}
template<typename Polygon, typename Point, typename Traits, typename OutputIterator>
void compute_on_polygon(
const Polygon& polygon, const Point& query, const Traits& traits, OutputIterator out) const {
CGAL::Weights::discrete_harmonic_weights_2(polygon, query, out, traits);
}
bool supports_3d() const { return false; }
bool is_barycentric() const { return true; }
};
template<typename Kernel>
struct Mean_value_wrapper {
using FT = typename Kernel::FT;
using Point_2 = typename Kernel::Point_2;
using Point_3 = typename Kernel::Point_3;
FT weight_a(const Point_2& t, const Point_2& r, const Point_2& p, const Point_2& q) const {
return CGAL::Weights::mean_value_weight(t, r, p, q);
}
FT weight_a(const Point_3&, const Point_3&, const Point_3&, const Point_3&) const {
return FT(-1);
}
template<typename Point>
FT weight_b(const Point& t, const Point& r, const Point& p, const Point& q) const {
return weight_a(t, r, p, q);
}
template<typename Polygon, typename Point, typename Traits, typename OutputIterator>
void compute_on_polygon(
const Polygon& polygon, const Point& query, const Traits& traits, OutputIterator out) const {
CGAL::Weights::mean_value_weights_2(polygon, query, out, traits);
}
bool supports_3d() const { return false; }
bool is_barycentric() const { return true; }
};
template<typename Kernel>
struct Three_point_family_wrapper {
using FT = typename Kernel::FT;
using Point_2 = typename Kernel::Point_2;
using Point_3 = typename Kernel::Point_3;
const FT a;
Three_point_family_wrapper(const FT a) : a(a) { }
FT weight_a(const Point_2& t, const Point_2& r, const Point_2& p, const Point_2& q) const {
return CGAL::Weights::three_point_family_weight(t, r, p, q, a);
}
FT weight_a(const Point_3&, const Point_3&, const Point_3&, const Point_3&) const {
return FT(-1);
}
template<typename Point>
FT weight_b(const Point& t, const Point& r, const Point& p, const Point& q) const {
return weight_a(t, r, p, q);
}
bool supports_3d() const { return false; }
bool is_barycentric() const { return true; }
};
template<typename Kernel>
struct Uniform_region_wrapper {
using FT = typename Kernel::FT;
template<typename Point>
FT weight(const Point& p, const Point& q, const Point& r) const {
return CGAL::Weights::uniform_area(p, q, r);
}
};
template<typename Kernel>
struct Triangular_region_wrapper {
using FT = typename Kernel::FT;
template<typename Point>
FT weight(const Point& p, const Point& q, const Point& r) const {
return CGAL::Weights::triangular_area(p, q, r);
}
};
template<typename Kernel>
struct Barycentric_region_wrapper {
using FT = typename Kernel::FT;
template<typename Point>
FT weight(const Point& p, const Point& q, const Point& r) const {
return CGAL::Weights::barycentric_area(p, q, r);
}
};
template<typename Kernel>
struct Voronoi_region_wrapper {
using FT = typename Kernel::FT;
template<typename Point>
FT weight(const Point& p, const Point& q, const Point& r) const {
return CGAL::Weights::voronoi_area(p, q, r);
}
};
template<typename Kernel>
struct Mixed_voronoi_region_wrapper {
using FT = typename Kernel::FT;
template<typename Point>
FT weight(const Point& p, const Point& q, const Point& r) const {
return CGAL::Weights::mixed_voronoi_area(p, q, r);
}
};
template<typename Kernel>
struct Uniform_wrapper {
using FT = typename Kernel::FT;
template<typename Point>
FT weight_a(const Point& t, const Point& r, const Point& p, const Point& q) const {
return CGAL::Weights::uniform_weight(t, r, p, q);
}
template<typename Point>
FT weight_b(const Point& t, const Point& r, const Point& p, const Point& q) const {
return weight_a(t, r, p, q);
}
bool supports_3d() const { return true; }
bool is_barycentric() const { return false; }
};
template<typename Kernel>
struct Inverse_distance_wrapper {
using FT = typename Kernel::FT;
template<typename Point>
FT weight_a(const Point& t, const Point& r, const Point& p, const Point& q) const {
return CGAL::Weights::inverse_distance_weight(t, r, p, q);
}
template<typename Point>
FT weight_b(const Point& t, const Point& r, const Point& p, const Point& q) const {
return weight_a(t, r, p, q);
}
bool supports_3d() const { return true; }
bool is_barycentric() const { return false; }
};
template<typename Kernel>
struct Shepard_wrapper {
using FT = typename Kernel::FT;
const FT a;
Shepard_wrapper(const FT a) : a(a) { }
template<typename Point>
FT weight_a(const Point& t, const Point& r, const Point& p, const Point& q) const {
return CGAL::Weights::shepard_weight(t, r, p, q, a);
}
template<typename Point>
FT weight_b(const Point& t, const Point& r, const Point& p, const Point& q) const {
return weight_a(t, r, p, q);
}
bool supports_3d() const { return true; }
bool is_barycentric() const { return false; }
};
} // namespace wrappers
#endif // CGAL_WEIGHTS_TESTS_WRAPPERS_H

View File

@ -1,52 +1,26 @@
#include <CGAL/Simple_cartesian.h>
#include <CGAL/Weights/utils.h>
#include <CGAL/Weights/authalic_weights.h>
#include <CGAL/Exact_predicates_inexact_constructions_kernel.h>
#include <CGAL/Exact_predicates_exact_constructions_kernel.h>
#include "include/utils.h"
#include "include/wrappers.h"
// Typedefs.
using Kernel = CGAL::Simple_cartesian<double>;
using Point_2 = typename Kernel::Point_2;
using Point_3 = typename Kernel::Point_3;
using SCKER = CGAL::Simple_cartesian<double>;
using EPICK = CGAL::Exact_predicates_inexact_constructions_kernel;
using EPECK = CGAL::Exact_predicates_exact_constructions_kernel;
template<typename Kernel>
bool test_kernel() {
const wrappers::Authalic_wrapper<Kernel> aut;
const wrappers::Wachspress_wrapper<Kernel> whp;
return tests::test_analytic_weight<Kernel>(aut, whp);
}
int main() {
// 2D configuration.
const Point_2 t2 = Point_2(-1, 0);
const Point_2 r2 = Point_2( 0, -1);
const Point_2 p2 = Point_2( 1, 0);
const Point_2 q2 = Point_2( 0, 0);
// 3D configuration.
const Point_3 t3 = Point_3(-1, 0, 1);
const Point_3 r3 = Point_3( 0, -1, 1);
const Point_3 p3 = Point_3( 1, 0, 1);
const Point_3 q3 = Point_3( 0, 0, 1);
// Compute weights.
std::cout << "2D authalic: " <<
CGAL::Weights::authalic_weight(t2, r2, p2, q2) << std::endl;
std::cout << "3D authalic: " <<
CGAL::Weights::authalic_weight(t3, r3, p3, q3) << std::endl;
std::cout << "--------------" << std::endl;
// Construct a 2D weight.
const auto w2 =
CGAL::Weights::half_authalic_weight(
CGAL::Weights::cotangent(t2, r2, q2),
CGAL::Weights::squared_distance(q2, r2)) +
CGAL::Weights::half_authalic_weight(
CGAL::Weights::cotangent(q2, r2, p2),
CGAL::Weights::squared_distance(q2, r2));
std::cout << "2D authalic: " << w2 << std::endl;
// Construct a 3D weight.
const auto w3 =
CGAL::Weights::half_authalic_weight(
CGAL::Weights::cotangent(t3, r3, q3),
CGAL::Weights::squared_distance(q3, r3)) +
CGAL::Weights::half_authalic_weight(
CGAL::Weights::cotangent(q3, r3, p3),
CGAL::Weights::squared_distance(q3, r3));
std::cout << "3D authalic: " << w3 << std::endl;
assert(test_kernel<SCKER>());
assert(test_kernel<EPICK>());
assert(test_kernel<EPECK>());
std::cout << "* test_authalic_weights: SUCCESS" << std::endl;
return EXIT_SUCCESS;
}

View File

@ -1,28 +1,25 @@
#include <CGAL/Simple_cartesian.h>
#include <CGAL/Weights/barycentric_region_weights.h>
#include <CGAL/Exact_predicates_inexact_constructions_kernel.h>
#include <CGAL/Exact_predicates_exact_constructions_kernel.h>
#include "include/utils.h"
#include "include/wrappers.h"
// Typedefs.
using Kernel = CGAL::Simple_cartesian<double>;
using Point_2 = typename Kernel::Point_2;
using Point_3 = typename Kernel::Point_3;
using SCKER = CGAL::Simple_cartesian<double>;
using EPICK = CGAL::Exact_predicates_inexact_constructions_kernel;
using EPECK = CGAL::Exact_predicates_exact_constructions_kernel;
template<typename Kernel>
bool test_kernel() {
const wrappers::Barycentric_region_wrapper<Kernel> bar;
return tests::test_region_weight<Kernel>(bar);
}
int main() {
// 2D configuration.
const Point_2 p2 = Point_2(-1, 0);
const Point_2 q2 = Point_2( 0, 0);
const Point_2 r2 = Point_2( 0, 1);
// 3D configuration.
const Point_3 p3 = Point_3(-1, 0, 1);
const Point_3 q3 = Point_3( 0, 0, 1);
const Point_3 r3 = Point_3( 0, 1, 1);
// Compute weights.
std::cout << "2D barycentric: " <<
CGAL::Weights::barycentric_area(p2, q2, r2) << std::endl;
std::cout << "3D barycentric: " <<
CGAL::Weights::barycentric_area(p3, q3, r3) << std::endl;
assert(test_kernel<SCKER>());
assert(test_kernel<EPICK>());
assert(test_kernel<EPECK>());
std::cout << "* test_barycentric_region_weights: SUCCESS" << std::endl;
return EXIT_SUCCESS;
}

View File

@ -1,48 +1,26 @@
#include <CGAL/Simple_cartesian.h>
#include <CGAL/Weights/utils.h>
#include <CGAL/Weights/cotangent_weights.h>
#include <CGAL/Exact_predicates_inexact_constructions_kernel.h>
#include <CGAL/Exact_predicates_exact_constructions_kernel.h>
#include "include/utils.h"
#include "include/wrappers.h"
// Typedefs.
using Kernel = CGAL::Simple_cartesian<double>;
using Point_2 = typename Kernel::Point_2;
using Point_3 = typename Kernel::Point_3;
using SCKER = CGAL::Simple_cartesian<double>;
using EPICK = CGAL::Exact_predicates_inexact_constructions_kernel;
using EPECK = CGAL::Exact_predicates_exact_constructions_kernel;
template<typename Kernel>
bool test_kernel() {
const wrappers::Cotangent_wrapper<Kernel> cot;
const wrappers::Discrete_harmonic_wrapper<Kernel> dhw;
return tests::test_analytic_weight<Kernel>(cot, dhw);
}
int main() {
// 2D configuration.
const Point_2 t2 = Point_2(-1, 0);
const Point_2 r2 = Point_2( 0, -1);
const Point_2 p2 = Point_2( 1, 0);
const Point_2 q2 = Point_2( 0, 0);
// 3D configuration.
const Point_3 t3 = Point_3(-1, 0, 1);
const Point_3 r3 = Point_3( 0, -1, 1);
const Point_3 p3 = Point_3( 1, 0, 1);
const Point_3 q3 = Point_3( 0, 0, 1);
// Compute weights.
std::cout << "2D cotangent: " <<
CGAL::Weights::cotangent_weight(t2, r2, p2, q2) << std::endl;
std::cout << "3D cotangent: " <<
CGAL::Weights::cotangent_weight(t3, r3, p3, q3) << std::endl;
std::cout << "---------------" << std::endl;
// Construct a 2D weight.
const auto w2 =
CGAL::Weights::half_cotangent_weight(
CGAL::Weights::cotangent(q2, t2, r2)) +
CGAL::Weights::half_cotangent_weight(
CGAL::Weights::cotangent(r2, p2, q2));
std::cout << "2D cotangent: " << w2 << std::endl;
// Construct a 3D weight.
const auto w3 =
CGAL::Weights::half_cotangent_weight(
CGAL::Weights::cotangent(q3, t3, r3)) +
CGAL::Weights::half_cotangent_weight(
CGAL::Weights::cotangent(r3, p3, q3));
std::cout << "3D cotangent: " << w3 << std::endl;
assert(test_kernel<SCKER>());
assert(test_kernel<EPICK>());
assert(test_kernel<EPECK>());
std::cout << "* test_cotangent_weights: SUCCESS" << std::endl;
return EXIT_SUCCESS;
}

View File

@ -1,62 +1,54 @@
#include <CGAL/Simple_cartesian.h>
#include <CGAL/Weights/discrete_harmonic_weights.h>
#include <CGAL/Weights/internal/Projection_traits_3.h>
#include <CGAL/Exact_predicates_inexact_constructions_kernel.h>
#include <CGAL/Exact_predicates_exact_constructions_kernel.h>
#include "include/utils.h"
#include "include/wrappers.h"
// Typedefs.
using Kernel = CGAL::Simple_cartesian<double>;
using Point_2 = typename Kernel::Point_2;
using Point_3 = typename Kernel::Point_3;
using SCKER = CGAL::Simple_cartesian<double>;
using EPICK = CGAL::Exact_predicates_inexact_constructions_kernel;
using EPECK = CGAL::Exact_predicates_exact_constructions_kernel;
template<typename Kernel>
void test_overloads() {
using FT = typename Kernel::FT;
using Point_2 = typename Kernel::Point_2;
using Point_3 = typename Kernel::Point_3;
const Point_2 t1(-1, 0);
const Point_2 r1( 0, -1);
const Point_2 p1( 1, 0);
const Point_2 q1( 0, 0);
const Point_3 t2(-1, 0, 1);
const Point_3 r2( 0, -1, 1);
const Point_3 p2( 1, 0, 1);
const Point_3 q2( 0, 0, 1);
const FT a2 = CGAL::Weights::discrete_harmonic_weight(t1, r1, p1, q1);
const FT a3 = CGAL::Weights::internal::discrete_harmonic_weight(t2, r2, p2, q2);
assert(a2 >= FT(0));
assert(a3 >= FT(0));
assert(a2 == a3);
struct Traits : public Kernel { };
assert(CGAL::Weights::discrete_harmonic_weight(t1, r1, p1, q1, Traits()) == a2);
assert(CGAL::Weights::internal::discrete_harmonic_weight(t2, r2, p2, q2, Traits()) == a3);
CGAL::Projection_traits_xy_3<Kernel> ptraits;
const FT a23 = CGAL::Weights::discrete_harmonic_weight(t2, r2, p2, q2, ptraits);
assert(a23 >= FT(0));
assert(a23 == a2 && a23 == a3);
}
template<typename Kernel>
bool test_kernel() {
test_overloads<Kernel>();
const wrappers::Discrete_harmonic_wrapper<Kernel> dhw;
const wrappers::Cotangent_wrapper<Kernel> cot;
return tests::test_barycentric_weight<Kernel>(dhw, cot);
}
int main() {
// 2D configuration.
const Point_2 t2 = Point_2(-1, 0);
const Point_2 r2 = Point_2( 0, -1);
const Point_2 p2 = Point_2( 1, 0);
const Point_2 q2 = Point_2( 0, 0);
// 3D configuration.
const Point_3 t3 = Point_3(-1, 0, 1);
const Point_3 r3 = Point_3( 0, -1, 1);
const Point_3 p3 = Point_3( 1, 0, 1);
const Point_3 q3 = Point_3( 0, 0, 1);
// Compute weights.
std::cout << "2D discrete harmonic: " <<
CGAL::Weights::discrete_harmonic_weight(t2, r2, p2, q2) << std::endl;
std::cout << "3D discrete harmonic: " <<
CGAL::Weights::discrete_harmonic_weight(t3, r3, p3, q3) << std::endl;
// Compute weights on a polygon.
// 2D configuration.
const std::vector<Point_2> polygon2 = {t2, r2, p2, Point_2(0, 1)};
std::vector<double> weights2;
weights2.reserve(polygon2.size());
CGAL::Weights::discrete_harmonic_weights_2(
polygon2, q2, std::back_inserter(weights2));
std::cout << "2D discrete harmonic (polygon): ";
for (const double weight2 : weights2)
std::cout << weight2 << " ";
std::cout << std::endl;
// 3D configuration.
CGAL::Weights::internal::Projection_traits_3<Kernel> ptraits(
typename Kernel::Vector_3(0, 0, 1));
const std::vector<Point_3> polygon3 = {t3, r3, p3, Point_3(0, 1, 1)};
std::vector<double> weights3;
weights3.reserve(polygon3.size());
CGAL::Weights::discrete_harmonic_weights_2(
polygon3, q3, std::back_inserter(weights3), ptraits);
std::cout << "3D discrete harmonic (polygon): ";
for (const double weight3 : weights3)
std::cout << weight3 << " ";
std::cout << std::endl;
assert(test_kernel<SCKER>());
assert(test_kernel<EPICK>());
assert(test_kernel<EPECK>());
std::cout << "* test_discrete_harmonic_weights: SUCCESS" << std::endl;
return EXIT_SUCCESS;
}

View File

@ -1,37 +1,47 @@
#include <CGAL/Simple_cartesian.h>
#include <CGAL/Weights/inverse_distance_weights.h>
#include <CGAL/Exact_predicates_inexact_constructions_kernel.h>
#include <CGAL/Exact_predicates_exact_constructions_kernel.h>
#include "include/utils.h"
#include "include/wrappers.h"
// Typedefs.
using Kernel = CGAL::Simple_cartesian<double>;
using Point_2 = typename Kernel::Point_2;
using Point_3 = typename Kernel::Point_3;
using SCKER = CGAL::Simple_cartesian<double>;
using EPICK = CGAL::Exact_predicates_inexact_constructions_kernel;
using EPECK = CGAL::Exact_predicates_exact_constructions_kernel;
template<typename Kernel>
void test_overloads() {
using FT = typename Kernel::FT;
using Point_2 = typename Kernel::Point_2;
using Point_3 = typename Kernel::Point_3;
const Point_2 p1(0, 0);
const Point_2 q1(1, 0);
const Point_3 p2(0, 0, 1);
const Point_3 q2(1, 0, 1);
const FT a2 = CGAL::Weights::inverse_distance_weight(p1, q1);
const FT a3 = CGAL::Weights::inverse_distance_weight(p2, q2);
assert(a2 == FT(1));
assert(a3 == FT(1));
assert(CGAL::Weights::inverse_distance_weight(p1, p1, q1, q1) == a2);
assert(CGAL::Weights::inverse_distance_weight(p2, p2, q2, q2) == a3);
struct Traits : public Kernel { };
assert(CGAL::Weights::inverse_distance_weight(p1, p1, q1, q1, Traits()) == a2);
assert(CGAL::Weights::inverse_distance_weight(p2, p2, q2, q2, Traits()) == a3);
}
template<typename Kernel>
bool test_kernel() {
test_overloads<Kernel>();
const wrappers::Inverse_distance_wrapper<Kernel> idw;
const wrappers::Shepard_wrapper<Kernel> spw(1);
return tests::test_analytic_weight<Kernel>(idw, spw);
}
int main() {
// 2D configuration.
const Point_2 t2 = Point_2(-1, 0);
const Point_2 r2 = Point_2( 0, -1);
const Point_2 p2 = Point_2( 1, 0);
const Point_2 q2 = Point_2( 0, 0);
// 3D configuration.
const Point_3 t3 = Point_3(-1, 0, 1);
const Point_3 r3 = Point_3( 0, -1, 1);
const Point_3 p3 = Point_3( 1, 0, 1);
const Point_3 q3 = Point_3( 0, 0, 1);
// Compute weights.
std::cout << "2D inverse distance: " <<
CGAL::Weights::inverse_distance_weight(t2, r2, p2, q2) << std::endl;
std::cout << "3D inverse distance: " <<
CGAL::Weights::inverse_distance_weight(t3, r3, p3, q3) << std::endl;
std::cout << "----------------------" << std::endl;
// Overloads.
std::cout << "2D inverse distance: " <<
CGAL::Weights::inverse_distance_weight(q2, r2) << std::endl;
std::cout << "3D inverse distance: " <<
CGAL::Weights::inverse_distance_weight(q3, r3) << std::endl;
assert(test_kernel<SCKER>());
assert(test_kernel<EPICK>());
assert(test_kernel<EPECK>());
std::cout << "* test_inverse_distance_weights: SUCCESS" << std::endl;
return EXIT_SUCCESS;
}

View File

@ -1,62 +1,54 @@
#include <CGAL/Simple_cartesian.h>
#include <CGAL/Weights/mean_value_weights.h>
#include <CGAL/Weights/internal/Projection_traits_3.h>
#include <CGAL/Exact_predicates_inexact_constructions_kernel.h>
#include <CGAL/Exact_predicates_exact_constructions_kernel.h>
#include "include/utils.h"
#include "include/wrappers.h"
// Typedefs.
using Kernel = CGAL::Simple_cartesian<double>;
using Point_2 = typename Kernel::Point_2;
using Point_3 = typename Kernel::Point_3;
using SCKER = CGAL::Simple_cartesian<double>;
using EPICK = CGAL::Exact_predicates_inexact_constructions_kernel;
using EPECK = CGAL::Exact_predicates_exact_constructions_kernel;
template<typename Kernel>
void test_overloads() {
using FT = typename Kernel::FT;
using Point_2 = typename Kernel::Point_2;
using Point_3 = typename Kernel::Point_3;
const Point_2 t1(-1, 0);
const Point_2 r1( 0, -1);
const Point_2 p1( 1, 0);
const Point_2 q1( 0, 0);
const Point_3 t2(-1, 0, 1);
const Point_3 r2( 0, -1, 1);
const Point_3 p2( 1, 0, 1);
const Point_3 q2( 0, 0, 1);
const FT a2 = CGAL::Weights::mean_value_weight(t1, r1, p1, q1);
const FT a3 = CGAL::Weights::internal::mean_value_weight(t2, r2, p2, q2);
assert(a2 >= FT(0));
assert(a3 >= FT(0));
assert(a2 == a3);
struct Traits : public Kernel { };
assert(CGAL::Weights::mean_value_weight(t1, r1, p1, q1, Traits()) == a2);
assert(CGAL::Weights::internal::mean_value_weight(t2, r2, p2, q2, Traits()) == a3);
CGAL::Projection_traits_xy_3<Kernel> ptraits;
const FT a23 = CGAL::Weights::mean_value_weight(t2, r2, p2, q2, ptraits);
assert(a23 >= FT(0));
assert(a23 == a2 && a23 == a3);
}
template<typename Kernel>
bool test_kernel() {
test_overloads<Kernel>();
const wrappers::Mean_value_wrapper<Kernel> mvw;
const wrappers::Tangent_wrapper<Kernel> tan;
return tests::test_barycentric_weight<Kernel>(mvw, tan);
}
int main() {
// 2D configuration.
const Point_2 t2 = Point_2(-1, 0);
const Point_2 r2 = Point_2( 0, -1);
const Point_2 p2 = Point_2( 1, 0);
const Point_2 q2 = Point_2( 0, 0);
// 3D configuration.
const Point_3 t3 = Point_3(-1, 0, 1);
const Point_3 r3 = Point_3( 0, -1, 1);
const Point_3 p3 = Point_3( 1, 0, 1);
const Point_3 q3 = Point_3( 0, 0, 1);
// Compute weights.
std::cout << "2D mean value: " <<
CGAL::Weights::mean_value_weight(t2, r2, p2, q2) << std::endl;
std::cout << "3D mean value: " <<
CGAL::Weights::mean_value_weight(t3, r3, p3, q3) << std::endl;
// Compute weights on a polygon.
// 2D configuration.
const std::vector<Point_2> polygon2 = {t2, r2, p2, Point_2(0, 1)};
std::vector<double> weights2;
weights2.reserve(polygon2.size());
CGAL::Weights::mean_value_weights_2(
polygon2, q2, std::back_inserter(weights2));
std::cout << "2D mean value (polygon): ";
for (const double weight2 : weights2)
std::cout << weight2 << " ";
std::cout << std::endl;
// 3D configuration.
CGAL::Weights::internal::Projection_traits_3<Kernel> ptraits(
typename Kernel::Vector_3(0, 0, 1));
const std::vector<Point_3> polygon3 = {t3, r3, p3, Point_3(0, 1, 1)};
std::vector<double> weights3;
weights3.reserve(polygon3.size());
CGAL::Weights::mean_value_weights_2(
polygon3, q3, std::back_inserter(weights3), ptraits);
std::cout << "3D mean value (polygon): ";
for (const double weight3 : weights3)
std::cout << weight3 << " ";
std::cout << std::endl;
assert(test_kernel<SCKER>());
assert(test_kernel<EPICK>());
assert(test_kernel<EPECK>());
std::cout << "* test_mean_value_weights: SUCCESS" << std::endl;
return EXIT_SUCCESS;
}

View File

@ -1,28 +1,25 @@
#include <CGAL/Simple_cartesian.h>
#include <CGAL/Weights/mixed_voronoi_region_weights.h>
#include <CGAL/Exact_predicates_inexact_constructions_kernel.h>
#include <CGAL/Exact_predicates_exact_constructions_kernel.h>
#include "include/utils.h"
#include "include/wrappers.h"
// Typedefs.
using Kernel = CGAL::Simple_cartesian<double>;
using Point_2 = typename Kernel::Point_2;
using Point_3 = typename Kernel::Point_3;
using SCKER = CGAL::Simple_cartesian<double>;
using EPICK = CGAL::Exact_predicates_inexact_constructions_kernel;
using EPECK = CGAL::Exact_predicates_exact_constructions_kernel;
template<typename Kernel>
bool test_kernel() {
const wrappers::Mixed_voronoi_region_wrapper<Kernel> mix;
return tests::test_region_weight<Kernel>(mix);
}
int main() {
// 2D configuration.
const Point_2 p2 = Point_2(-1, 0);
const Point_2 q2 = Point_2( 0, 0);
const Point_2 r2 = Point_2( 0, 1);
// 3D configuration.
const Point_3 p3 = Point_3(-1, 0, 1);
const Point_3 q3 = Point_3( 0, 0, 1);
const Point_3 r3 = Point_3( 0, 1, 1);
// Compute weights.
std::cout << "2D mixed voronoi: " <<
CGAL::Weights::mixed_voronoi_area(p2, q2, r2) << std::endl;
std::cout << "3D mixed voronoi: " <<
CGAL::Weights::mixed_voronoi_area(p3, q3, r3) << std::endl;
assert(test_kernel<SCKER>());
assert(test_kernel<EPICK>());
assert(test_kernel<EPECK>());
std::cout << "* test_mixed_voronoi_region_weights: SUCCESS" << std::endl;
return EXIT_SUCCESS;
}

View File

@ -0,0 +1,119 @@
#include <CGAL/Simple_cartesian.h>
#include <CGAL/Exact_predicates_inexact_constructions_kernel.h>
#include <CGAL/Exact_predicates_exact_constructions_kernel.h>
#include <CGAL/Projection_traits_xy_3.h>
#include <CGAL/Projection_traits_xz_3.h>
#include <CGAL/Projection_traits_yz_3.h>
#include <CGAL/Weights.h>
// Typedefs.
using SCKER = CGAL::Simple_cartesian<double>;
using EPICK = CGAL::Exact_predicates_inexact_constructions_kernel;
using EPECK = CGAL::Exact_predicates_exact_constructions_kernel;
template<typename Kernel>
void test_kernel() {
using FT = typename Kernel::FT;
using Point_2 = typename Kernel::Point_2;
using Point_3 = typename Kernel::Point_3;
using XY_Traits = CGAL::Projection_traits_xy_3<Kernel>;
using XZ_Traits = CGAL::Projection_traits_xz_3<Kernel>;
using YZ_Traits = CGAL::Projection_traits_yz_3<Kernel>;
const XY_Traits xy_traits;
const XZ_Traits xz_traits;
const YZ_Traits yz_traits;
const Point_2 t(-1, 0);
const Point_2 r( 0, -1);
const Point_2 p( 1, 0);
const Point_2 q( 0, 0);
// XY.
const Point_3 t1(t.x(), t.y(), 1);
const Point_3 r1(r.x(), r.y(), 1);
const Point_3 p1(p.x(), p.y(), 1);
const Point_3 q1(q.x(), q.y(), 1);
// XZ.
const Point_3 t2(t.x(), 1, t.y());
const Point_3 r2(r.x(), 1, r.y());
const Point_3 p2(p.x(), 1, p.y());
const Point_3 q2(q.x(), 1, q.y());
// YZ.
const Point_3 t3(1, t.x(), t.y());
const Point_3 r3(1, r.x(), r.y());
const Point_3 p3(1, p.x(), p.y());
const Point_3 q3(1, q.x(), q.y());
const FT ref_value = FT(4);
assert(CGAL::Weights::authalic_weight(t1, r1, p1, q1, xy_traits) == ref_value);
assert(CGAL::Weights::authalic_weight(t2, r2, p2, q2, xz_traits) == ref_value);
assert(CGAL::Weights::authalic_weight(t3, r3, p3, q3, yz_traits) == ref_value);
assert(CGAL::Weights::wachspress_weight(t1, r1, p1, q1, xy_traits) == ref_value);
assert(CGAL::Weights::wachspress_weight(t2, r2, p2, q2, xz_traits) == ref_value);
assert(CGAL::Weights::wachspress_weight(t3, r3, p3, q3, yz_traits) == ref_value);
assert(CGAL::Weights::cotangent_weight(t1, r1, p1, q1, xy_traits) == ref_value);
assert(CGAL::Weights::cotangent_weight(t2, r2, p2, q2, xz_traits) == ref_value);
assert(CGAL::Weights::cotangent_weight(t3, r3, p3, q3, yz_traits) == ref_value);
assert(CGAL::Weights::discrete_harmonic_weight(t1, r1, p1, q1, xy_traits) == ref_value);
assert(CGAL::Weights::discrete_harmonic_weight(t2, r2, p2, q2, xz_traits) == ref_value);
assert(CGAL::Weights::discrete_harmonic_weight(t3, r3, p3, q3, yz_traits) == ref_value);
assert(CGAL::Weights::tangent_weight(t1, r1, p1, q1, xy_traits) == ref_value);
assert(CGAL::Weights::tangent_weight(t2, r2, p2, q2, xz_traits) == ref_value);
assert(CGAL::Weights::tangent_weight(t3, r3, p3, q3, yz_traits) == ref_value);
assert(CGAL::Weights::mean_value_weight(t1, r1, p1, q1, xy_traits) == ref_value);
assert(CGAL::Weights::mean_value_weight(t2, r2, p2, q2, xz_traits) == ref_value);
assert(CGAL::Weights::mean_value_weight(t3, r3, p3, q3, yz_traits) == ref_value);
assert(CGAL::Weights::uniform_area(t1, r1, p1, xy_traits) == FT(1));
assert(CGAL::Weights::uniform_area(t2, r2, p2, xz_traits) == FT(1));
assert(CGAL::Weights::uniform_area(t3, r3, p3, yz_traits) == FT(1));
assert(CGAL::Weights::triangular_area(t1, r1, p1, xy_traits) >= FT(0));
assert(CGAL::Weights::triangular_area(t2, r2, p2, xz_traits) >= FT(0));
assert(CGAL::Weights::triangular_area(t3, r3, p3, yz_traits) >= FT(0));
assert(CGAL::Weights::barycentric_area(t1, r1, p1, xy_traits) >= FT(0));
assert(CGAL::Weights::barycentric_area(t2, r2, p2, xz_traits) >= FT(0));
assert(CGAL::Weights::barycentric_area(t3, r3, p3, yz_traits) >= FT(0));
assert(CGAL::Weights::voronoi_area(t1, r1, p1, xy_traits) >= FT(0));
assert(CGAL::Weights::voronoi_area(t2, r2, p2, xz_traits) >= FT(0));
assert(CGAL::Weights::voronoi_area(t3, r3, p3, yz_traits) >= FT(0));
assert(CGAL::Weights::mixed_voronoi_area(t1, r1, p1, xy_traits) >= FT(0));
assert(CGAL::Weights::mixed_voronoi_area(t2, r2, p2, xz_traits) >= FT(0));
assert(CGAL::Weights::mixed_voronoi_area(t3, r3, p3, yz_traits) >= FT(0));
assert(CGAL::Weights::uniform_weight(t1, r1, p1, q1, xy_traits) == FT(1));
assert(CGAL::Weights::uniform_weight(t2, r2, p2, q2, xz_traits) == FT(1));
assert(CGAL::Weights::uniform_weight(t3, r3, p3, q3, yz_traits) == FT(1));
assert(CGAL::Weights::inverse_distance_weight(t1, r1, p1, q1, xy_traits) == FT(1));
assert(CGAL::Weights::inverse_distance_weight(t2, r2, p2, q2, xz_traits) == FT(1));
assert(CGAL::Weights::inverse_distance_weight(t3, r3, p3, q3, yz_traits) == FT(1));
assert(CGAL::Weights::shepard_weight(t1, r1, p1, q1, 1, xy_traits) == FT(1));
assert(CGAL::Weights::shepard_weight(t2, r2, p2, q2, 1, xz_traits) == FT(1));
assert(CGAL::Weights::shepard_weight(t3, r3, p3, q3, 1, yz_traits) == FT(1));
assert(CGAL::Weights::three_point_family_weight(t1, r1, p1, q1, 1, xy_traits) == ref_value);
assert(CGAL::Weights::three_point_family_weight(t2, r2, p2, q2, 1, xz_traits) == ref_value);
assert(CGAL::Weights::three_point_family_weight(t3, r3, p3, q3, 1, yz_traits) == ref_value);
}
int main() {
test_kernel<SCKER>();
test_kernel<EPICK>();
test_kernel<EPECK>();
std::cout << "* test_projected_weights: SUCCESS" << std::endl;
return EXIT_SUCCESS;
}

View File

@ -1,37 +1,49 @@
#include <CGAL/Simple_cartesian.h>
#include <CGAL/Weights/shepard_weights.h>
#include <CGAL/Exact_predicates_inexact_constructions_kernel.h>
#include <CGAL/Exact_predicates_exact_constructions_kernel.h>
#include "include/utils.h"
#include "include/wrappers.h"
// Typedefs.
using Kernel = CGAL::Simple_cartesian<double>;
using Point_2 = typename Kernel::Point_2;
using Point_3 = typename Kernel::Point_3;
using SCKER = CGAL::Simple_cartesian<double>;
using EPICK = CGAL::Exact_predicates_inexact_constructions_kernel;
using EPECK = CGAL::Exact_predicates_exact_constructions_kernel;
template<typename Kernel>
void test_overloads() {
using FT = typename Kernel::FT;
using Point_2 = typename Kernel::Point_2;
using Point_3 = typename Kernel::Point_3;
const Point_2 p1(0, 0);
const Point_2 q1(1, 0);
const Point_3 p2(0, 0, 1);
const Point_3 q2(1, 0, 1);
const FT a2 = CGAL::Weights::shepard_weight(p1, q1);
const FT a3 = CGAL::Weights::shepard_weight(p2, q2);
assert(a2 == FT(1));
assert(a3 == FT(1));
assert(CGAL::Weights::shepard_weight(p1, p1, q1, q1) == a2);
assert(CGAL::Weights::shepard_weight(p2, p2, q2, q2) == a3);
struct Traits : public Kernel { };
assert(CGAL::Weights::shepard_weight(p1, p1, q1, q1, 1, Traits()) == a2);
assert(CGAL::Weights::shepard_weight(p2, p2, q2, q2, 1, Traits()) == a3);
}
template<typename Kernel>
bool test_kernel() {
test_overloads<Kernel>();
const wrappers::Shepard_wrapper<Kernel> spwa(1);
const wrappers::Shepard_wrapper<Kernel> spwb(2);
const wrappers::Inverse_distance_wrapper<Kernel> idw;
assert(tests::test_analytic_weight<Kernel>(spwa, idw));
return tests::test_analytic_weight<Kernel>(spwb, spwb);
}
int main() {
// 2D configuration.
const Point_2 t2 = Point_2(-1, 0);
const Point_2 r2 = Point_2( 0, -1);
const Point_2 p2 = Point_2( 1, 0);
const Point_2 q2 = Point_2( 0, 0);
// 3D configuration.
const Point_3 t3 = Point_3(-1, 0, 1);
const Point_3 r3 = Point_3( 0, -1, 1);
const Point_3 p3 = Point_3( 1, 0, 1);
const Point_3 q3 = Point_3( 0, 0, 1);
// Compute weights.
std::cout << "2D shepard: " <<
CGAL::Weights::shepard_weight(t2, r2, p2, q2) << std::endl;
std::cout << "3D shepard: " <<
CGAL::Weights::shepard_weight(t3, r3, p3, q3, 1.0) << std::endl;
std::cout << "-------------" << std::endl;
// Overloads.
std::cout << "2D shepard: " <<
CGAL::Weights::shepard_weight(q2, r2) << std::endl;
std::cout << "3D shepard: " <<
CGAL::Weights::shepard_weight(q3, r3, 1.0) << std::endl;
assert(test_kernel<SCKER>());
assert(test_kernel<EPICK>());
assert(test_kernel<EPECK>());
std::cout << "* test_shepard_weights: SUCCESS" << std::endl;
return EXIT_SUCCESS;
}

View File

@ -1,64 +1,26 @@
#include <CGAL/Simple_cartesian.h>
#include <CGAL/Weights/utils.h>
#include <CGAL/Weights/tangent_weights.h>
#include <CGAL/Exact_predicates_inexact_constructions_kernel.h>
#include <CGAL/Exact_predicates_exact_constructions_kernel.h>
#include "include/utils.h"
#include "include/wrappers.h"
// Typedefs.
using Kernel = CGAL::Simple_cartesian<double>;
using Point_2 = typename Kernel::Point_2;
using Point_3 = typename Kernel::Point_3;
using SCKER = CGAL::Simple_cartesian<double>;
using EPICK = CGAL::Exact_predicates_inexact_constructions_kernel;
using EPECK = CGAL::Exact_predicates_exact_constructions_kernel;
template<typename Kernel>
bool test_kernel() {
const wrappers::Tangent_wrapper<Kernel> tan;
const wrappers::Mean_value_wrapper<Kernel> mvw;
return tests::test_analytic_weight<Kernel>(tan, mvw);
}
int main() {
// 2D configuration.
const Point_2 t2 = Point_2(-1, 0);
const Point_2 r2 = Point_2( 0, -1);
const Point_2 p2 = Point_2( 1, 0);
const Point_2 q2 = Point_2( 0, 0);
// 3D configuration.
const Point_3 t3 = Point_3(-1, 0, 1);
const Point_3 r3 = Point_3( 0, -1, 1);
const Point_3 p3 = Point_3( 1, 0, 1);
const Point_3 q3 = Point_3( 0, 0, 1);
// Compute weights.
std::cout << "2D tangent: " <<
CGAL::Weights::tangent_weight(t2, r2, p2, q2) << std::endl;
std::cout << "3D tangent: " <<
CGAL::Weights::tangent_weight(t3, r3, p3, q3) << std::endl;
std::cout << "-------------" << std::endl;
// Construct a 2D weight.
const auto w2 =
CGAL::Weights::half_tangent_weight(
CGAL::Weights::distance(r2, q2),
CGAL::Weights::distance(t2, q2),
CGAL::Weights::area(r2, q2, t2),
CGAL::Weights::scalar_product(r2, q2, t2)) +
CGAL::Weights::half_tangent_weight(
CGAL::Weights::distance(r2, q2),
CGAL::Weights::distance(p2, q2),
CGAL::Weights::area(p2, q2, r2),
CGAL::Weights::scalar_product(p2, q2, r2));
std::cout << "2D tangent: " << w2 << std::endl;
// Construct a 3D weight.
const auto w3 =
CGAL::Weights::half_tangent_weight(
CGAL::Weights::tangent_half_angle(
CGAL::Weights::distance(r3, q3),
CGAL::Weights::distance(t3, q3),
CGAL::Weights::area(r3, q3, t3),
CGAL::Weights::scalar_product(r3, q3, t3)),
CGAL::Weights::distance(r3, q3)) +
CGAL::Weights::half_tangent_weight(
CGAL::Weights::tangent_half_angle(
CGAL::Weights::distance(r3, q3),
CGAL::Weights::distance(p3, q3),
CGAL::Weights::area(p3, q3, r3),
CGAL::Weights::scalar_product(p3, q3, r3)),
CGAL::Weights::distance(r3, q3));
std::cout << "3D tangent: " << w3 << std::endl;
assert(test_kernel<SCKER>());
assert(test_kernel<EPICK>());
assert(test_kernel<EPECK>());
std::cout << "* test_tangent_weights: SUCCESS" << std::endl;
return EXIT_SUCCESS;
}

View File

@ -1,30 +1,64 @@
#include <CGAL/Simple_cartesian.h>
#include <CGAL/Weights/three_point_family_weights.h>
#include <CGAL/Exact_predicates_inexact_constructions_kernel.h>
#include <CGAL/Exact_predicates_exact_constructions_kernel.h>
#include "include/utils.h"
#include "include/wrappers.h"
// Typedefs.
using Kernel = CGAL::Simple_cartesian<double>;
using Point_2 = typename Kernel::Point_2;
using Point_3 = typename Kernel::Point_3;
using SCKER = CGAL::Simple_cartesian<double>;
using EPICK = CGAL::Exact_predicates_inexact_constructions_kernel;
using EPECK = CGAL::Exact_predicates_exact_constructions_kernel;
template<typename Kernel>
void test_overloads() {
using FT = typename Kernel::FT;
using Point_2 = typename Kernel::Point_2;
using Point_3 = typename Kernel::Point_3;
const Point_2 t1(-1, 0);
const Point_2 r1( 0, -1);
const Point_2 p1( 1, 0);
const Point_2 q1( 0, 0);
const Point_3 t2(-1, 0, 1);
const Point_3 r2( 0, -1, 1);
const Point_3 p2( 1, 0, 1);
const Point_3 q2( 0, 0, 1);
const FT a2 = CGAL::Weights::three_point_family_weight(t1, r1, p1, q1);
const FT a3 = CGAL::Weights::internal::three_point_family_weight(t2, r2, p2, q2);
assert(a2 >= FT(0));
assert(a3 >= FT(0));
assert(a2 == a3);
struct Traits : public Kernel { };
assert(CGAL::Weights::three_point_family_weight(t1, r1, p1, q1, 1, Traits()) == a2);
assert(CGAL::Weights::internal::three_point_family_weight(t2, r2, p2, q2, 1, Traits()) == a3);
CGAL::Projection_traits_xy_3<Kernel> ptraits;
const FT a23 = CGAL::Weights::three_point_family_weight(t2, r2, p2, q2, 0, ptraits);
assert(a23 >= FT(0));
assert(a23 == a2 && a23 == a3);
}
template<typename Kernel>
bool test_kernel() {
test_overloads<Kernel>();
using FT = typename Kernel::FT;
const FT h = FT(1) / FT(2);
const wrappers::Three_point_family_wrapper<Kernel> tpfa(0);
const wrappers::Three_point_family_wrapper<Kernel> tpfb(1);
const wrappers::Three_point_family_wrapper<Kernel> tpfc(2);
const wrappers::Three_point_family_wrapper<Kernel> tpfd(h);
const wrappers::Wachspress_wrapper<Kernel> whp;
const wrappers::Mean_value_wrapper<Kernel> mvw;
const wrappers::Discrete_harmonic_wrapper<Kernel> dhw;
assert(tests::test_analytic_weight<Kernel>(tpfa, whp));
assert(tests::test_analytic_weight<Kernel>(tpfb, mvw));
assert(tests::test_analytic_weight<Kernel>(tpfc, dhw));
return tests::test_analytic_weight<Kernel>(tpfd, tpfd);
}
int main() {
// 2D configuration.
const Point_2 t2 = Point_2(-1, 0);
const Point_2 r2 = Point_2( 0, -1);
const Point_2 p2 = Point_2( 1, 0);
const Point_2 q2 = Point_2( 0, 0);
// 3D configuration.
const Point_3 t3 = Point_3(-1, 0, 1);
const Point_3 r3 = Point_3( 0, -1, 1);
const Point_3 p3 = Point_3( 1, 0, 1);
const Point_3 q3 = Point_3( 0, 0, 1);
// Compute weights.
std::cout << "2D family: " <<
CGAL::Weights::three_point_family_weight(t2, r2, p2, q2) << std::endl;
std::cout << "3D family: " <<
CGAL::Weights::three_point_family_weight(t3, r3, p3, q3, 1.0) << std::endl;
assert(test_kernel<SCKER>());
assert(test_kernel<EPICK>());
assert(test_kernel<EPECK>());
std::cout << "* test_three_point_family_weights: SUCCESS" << std::endl;
return EXIT_SUCCESS;
}

View File

@ -1,28 +1,25 @@
#include <CGAL/Simple_cartesian.h>
#include <CGAL/Weights/triangular_region_weights.h>
#include <CGAL/Exact_predicates_inexact_constructions_kernel.h>
#include <CGAL/Exact_predicates_exact_constructions_kernel.h>
#include "include/utils.h"
#include "include/wrappers.h"
// Typedefs.
using Kernel = CGAL::Simple_cartesian<double>;
using Point_2 = typename Kernel::Point_2;
using Point_3 = typename Kernel::Point_3;
using SCKER = CGAL::Simple_cartesian<double>;
using EPICK = CGAL::Exact_predicates_inexact_constructions_kernel;
using EPECK = CGAL::Exact_predicates_exact_constructions_kernel;
template<typename Kernel>
bool test_kernel() {
const wrappers::Triangular_region_wrapper<Kernel> tri;
return tests::test_region_weight<Kernel>(tri);
}
int main() {
// 2D configuration.
const Point_2 p2 = Point_2(-1, 0);
const Point_2 q2 = Point_2( 0, 0);
const Point_2 r2 = Point_2( 0, 1);
// 3D configuration.
const Point_3 p3 = Point_3(-1, 0, 1);
const Point_3 q3 = Point_3( 0, 0, 1);
const Point_3 r3 = Point_3( 0, 1, 1);
// Compute weights.
std::cout << "2D triangle: " <<
CGAL::Weights::triangular_area(p2, q2, r2) << std::endl;
std::cout << "3D triangle: " <<
CGAL::Weights::triangular_area(p3, q3, r3) << std::endl;
assert(test_kernel<SCKER>());
assert(test_kernel<EPICK>());
assert(test_kernel<EPECK>());
std::cout << "* test_triangular_region_weights: SUCCESS" << std::endl;
return EXIT_SUCCESS;
}

View File

@ -1,35 +1,42 @@
#include <CGAL/Simple_cartesian.h>
#include <CGAL/Weights/uniform_region_weights.h>
#include <CGAL/Exact_predicates_inexact_constructions_kernel.h>
#include <CGAL/Exact_predicates_exact_constructions_kernel.h>
#include "include/utils.h"
#include "include/wrappers.h"
// Typedefs.
using Kernel = CGAL::Simple_cartesian<double>;
using Point_2 = typename Kernel::Point_2;
using Point_3 = typename Kernel::Point_3;
using SCKER = CGAL::Simple_cartesian<double>;
using EPICK = CGAL::Exact_predicates_inexact_constructions_kernel;
using EPECK = CGAL::Exact_predicates_exact_constructions_kernel;
template<typename Kernel>
void test_overloads() {
using FT = typename Kernel::FT;
using Point_2 = typename Kernel::Point_2;
using Point_3 = typename Kernel::Point_3;
const FT a = CGAL::Weights::uniform_area();
assert(a == FT(1));
const Point_2 p(0, 0);
const Point_3 q(0, 0, 0);
assert(CGAL::Weights::uniform_area(p, p, p) == a);
assert(CGAL::Weights::uniform_area(q, q, q) == a);
struct Traits : public Kernel { };
assert(CGAL::Weights::uniform_area(p, p, p, Traits()) == a);
assert(CGAL::Weights::uniform_area(q, q, q, Traits()) == a);
}
template<typename Kernel>
bool test_kernel() {
test_overloads<Kernel>();
const wrappers::Uniform_region_wrapper<Kernel> uni;
return tests::test_region_weight<Kernel>(uni);
}
int main() {
// 2D configuration.
const Point_2 p2 = Point_2(-1, 0);
const Point_2 q2 = Point_2( 0, 0);
const Point_2 r2 = Point_2( 0, 1);
// 3D configuration.
const Point_3 p3 = Point_3(-1, 0, 1);
const Point_3 q3 = Point_3( 0, 0, 1);
const Point_3 r3 = Point_3( 0, 1, 1);
// Compute weights.
std::cout << "2D uniform: " <<
CGAL::Weights::uniform_area(p2, q2, r2) << std::endl;
std::cout << "3D uniform: " <<
CGAL::Weights::uniform_area(p3, q3, r3) << std::endl;
std::cout << "-------------" << std::endl;
// Overloads.
std::cout << "2D uniform: " <<
CGAL::Weights::uniform_area() << std::endl;
std::cout << "3D uniform: " <<
CGAL::Weights::uniform_area() << std::endl;
assert(test_kernel<SCKER>());
assert(test_kernel<EPICK>());
assert(test_kernel<EPECK>());
std::cout << "* test_uniform_region_weights: SUCCESS" << std::endl;
return EXIT_SUCCESS;
}

View File

@ -1,37 +1,42 @@
#include <CGAL/Simple_cartesian.h>
#include <CGAL/Weights/uniform_weights.h>
#include <CGAL/Exact_predicates_inexact_constructions_kernel.h>
#include <CGAL/Exact_predicates_exact_constructions_kernel.h>
#include "include/utils.h"
#include "include/wrappers.h"
// Typedefs.
using Kernel = CGAL::Simple_cartesian<double>;
using Point_2 = typename Kernel::Point_2;
using Point_3 = typename Kernel::Point_3;
using SCKER = CGAL::Simple_cartesian<double>;
using EPICK = CGAL::Exact_predicates_inexact_constructions_kernel;
using EPECK = CGAL::Exact_predicates_exact_constructions_kernel;
template<typename Kernel>
void test_overloads() {
using FT = typename Kernel::FT;
using Point_2 = typename Kernel::Point_2;
using Point_3 = typename Kernel::Point_3;
const FT a = CGAL::Weights::uniform_weight();
assert(a == FT(1));
const Point_2 p(0, 0);
const Point_3 q(0, 0, 0);
assert(CGAL::Weights::uniform_weight(p, p, p, p) == a);
assert(CGAL::Weights::uniform_weight(q, q, q, q) == a);
struct Traits : public Kernel { };
assert(CGAL::Weights::uniform_weight(p, p, p, p, Traits()) == a);
assert(CGAL::Weights::uniform_weight(q, q, q, q, Traits()) == a);
}
template<typename Kernel>
bool test_kernel() {
test_overloads<Kernel>();
const wrappers::Uniform_wrapper<Kernel> uni;
return tests::test_analytic_weight<Kernel>(uni, uni);
}
int main() {
// 2D configuration.
const Point_2 t2 = Point_2(-1, 0);
const Point_2 r2 = Point_2( 0, -1);
const Point_2 p2 = Point_2( 1, 0);
const Point_2 q2 = Point_2( 0, 0);
// 3D configuration.
const Point_3 t3 = Point_3(-1, 0, 1);
const Point_3 r3 = Point_3( 0, -1, 1);
const Point_3 p3 = Point_3( 1, 0, 1);
const Point_3 q3 = Point_3( 0, 0, 1);
// Compute weights.
std::cout << "2D uniform: " <<
CGAL::Weights::uniform_weight(t2, r2, p2, q2) << std::endl;
std::cout << "3D uniform: " <<
CGAL::Weights::uniform_weight(t3, r3, p3, q3) << std::endl;
std::cout << "-------------" << std::endl;
// Overloads.
std::cout << "2D uniform: " <<
CGAL::Weights::uniform_weight() << std::endl;
std::cout << "3D uniform: " <<
CGAL::Weights::uniform_weight() << std::endl;
assert(test_kernel<SCKER>());
assert(test_kernel<EPICK>());
assert(test_kernel<EPECK>());
std::cout << "* test_uniform_weights: SUCCESS" << std::endl;
return EXIT_SUCCESS;
}

View File

@ -1,28 +1,25 @@
#include <CGAL/Simple_cartesian.h>
#include <CGAL/Weights/voronoi_region_weights.h>
#include <CGAL/Exact_predicates_inexact_constructions_kernel.h>
#include <CGAL/Exact_predicates_exact_constructions_kernel.h>
#include "include/utils.h"
#include "include/wrappers.h"
// Typedefs.
using Kernel = CGAL::Simple_cartesian<double>;
using Point_2 = typename Kernel::Point_2;
using Point_3 = typename Kernel::Point_3;
using SCKER = CGAL::Simple_cartesian<double>;
using EPICK = CGAL::Exact_predicates_inexact_constructions_kernel;
using EPECK = CGAL::Exact_predicates_exact_constructions_kernel;
template<typename Kernel>
bool test_kernel() {
const wrappers::Voronoi_region_wrapper<Kernel> vor;
return tests::test_region_weight<Kernel>(vor);
}
int main() {
// 2D configuration.
const Point_2 p2 = Point_2(-1, 0);
const Point_2 q2 = Point_2( 0, 0);
const Point_2 r2 = Point_2( 0, 1);
// 3D configuration.
const Point_3 p3 = Point_3(-1, 0, 1);
const Point_3 q3 = Point_3( 0, 0, 1);
const Point_3 r3 = Point_3( 0, 1, 1);
// Compute weights.
std::cout << "2D voronoi: " <<
CGAL::Weights::voronoi_area(p2, q2, r2) << std::endl;
std::cout << "3D voronoi: " <<
CGAL::Weights::voronoi_area(p3, q3, r3) << std::endl;
assert(test_kernel<SCKER>());
assert(test_kernel<EPICK>());
assert(test_kernel<EPECK>());
std::cout << "* test_voronoi_region_weights: SUCCESS" << std::endl;
return EXIT_SUCCESS;
}

View File

@ -1,110 +1,54 @@
#include <CGAL/Simple_cartesian.h>
#include <CGAL/Weights/wachspress_weights.h>
#include <CGAL/Weights/internal/Projection_traits_3.h>
#include <CGAL/Exact_predicates_inexact_constructions_kernel.h>
#include <CGAL/Exact_predicates_exact_constructions_kernel.h>
#include "include/utils.h"
#include "include/wrappers.h"
// Typedefs.
using Kernel = CGAL::Simple_cartesian<double>;
using FT = typename Kernel::FT;
using Point_2 = typename Kernel::Point_2;
using Point_3 = typename Kernel::Point_3;
using SCKER = CGAL::Simple_cartesian<double>;
using EPICK = CGAL::Exact_predicates_inexact_constructions_kernel;
using EPECK = CGAL::Exact_predicates_exact_constructions_kernel;
int main() {
// 2D configuration.
const Point_2 t2 = Point_2(-1, 0);
const Point_2 r2 = Point_2( 0, -1);
const Point_2 p2 = Point_2( 1, 0);
const Point_2 q2 = Point_2( 0, 0);
// 3D configuration.
const Point_3 t3 = Point_3(-1, 0, 1);
const Point_3 r3 = Point_3( 0, -1, 1);
const Point_3 p3 = Point_3( 1, 0, 1);
const Point_3 q3 = Point_3( 0, 0, 1);
// Compute weights.
std::cout << "2D wachspress: " <<
CGAL::Weights::wachspress_weight(t2, r2, p2, q2) << std::endl;
std::cout << "3D wachspress: " <<
CGAL::Weights::wachspress_weight(t3, r3, p3, q3) << std::endl;
// 2D configuration.
const std::vector<Point_2> polygon2 = {t2, r2, p2, Point_2(0, 1)};
std::vector<double> weights2;
weights2.reserve(polygon2.size());
CGAL::Weights::wachspress_weights_2(
polygon2, q2, std::back_inserter(weights2));
std::cout << "2D wachspress (polygon): ";
for (const double weight2 : weights2)
std::cout << weight2 << " ";
std::cout << std::endl;
// 3D configuration.
CGAL::Weights::internal::Projection_traits_3<Kernel> ptraits(
typename Kernel::Vector_3(0, 0, 1));
const std::vector<Point_3> polygon3 = {t3, r3, p3, Point_3(0, 1, 1)};
std::vector<double> weights3;
weights3.reserve(polygon3.size());
CGAL::Weights::wachspress_weights_2(
polygon3, q3, std::back_inserter(weights3), ptraits);
std::cout << "3D wachspress (polygon): ";
for (const double weight3 : weights3)
std::cout << weight3 << " ";
std::cout << std::endl;
return EXIT_SUCCESS;
template<typename Kernel>
void test_overloads() {
using FT = typename Kernel::FT;
using Point_2 = typename Kernel::Point_2;
using Point_3 = typename Kernel::Point_3;
const Point_2 t1(-1, 0);
const Point_2 r1( 0, -1);
const Point_2 p1( 1, 0);
const Point_2 q1( 0, 0);
const Point_3 t2(-1, 0, 1);
const Point_3 r2( 0, -1, 1);
const Point_3 p2( 1, 0, 1);
const Point_3 q2( 0, 0, 1);
const FT a2 = CGAL::Weights::wachspress_weight(t1, r1, p1, q1);
const FT a3 = CGAL::Weights::internal::wachspress_weight(t2, r2, p2, q2);
assert(a2 >= FT(0));
assert(a3 >= FT(0));
assert(a2 == a3);
struct Traits : public Kernel { };
assert(CGAL::Weights::wachspress_weight(t1, r1, p1, q1, Traits()) == a2);
assert(CGAL::Weights::internal::wachspress_weight(t2, r2, p2, q2, Traits()) == a3);
CGAL::Projection_traits_xy_3<Kernel> ptraits;
const FT a23 = CGAL::Weights::wachspress_weight(t2, r2, p2, q2, ptraits);
assert(a23 >= FT(0));
assert(a23 == a2 && a23 == a3);
}
// Merge it with the current test!
template<typename Kernel>
bool test_kernel() {
test_overloads<Kernel>();
const wrappers::Wachspress_wrapper<Kernel> whp;
const wrappers::Authalic_wrapper<Kernel> aut;
return tests::test_barycentric_weight<Kernel>(whp, aut);
}
// 2D configuration.
// const Point_2 query2 = Point_2(+FT(0), FT(0));
// const Point_2 vm2 = Point_2(+FT(1), FT(0));
// const Point_2 vj2 = Point_2(+FT(0), FT(1));
// const Point_2 vp2 = Point_2(-FT(1), FT(0));
// Am = 0.5, Aj = 0.5, C = 1, B = 0.
// 3D configuration 1. All points are coplanar on a horizontal plane.
// const Point_3 query3 = Point_3(+FT(0), FT(0), FT(1));
// const Point_3 vm3 = Point_3(+FT(1), FT(0), FT(1));
// const Point_3 vj3 = Point_3(+FT(0), FT(1), FT(1));
// const Point_3 vp3 = Point_3(-FT(1), FT(0), FT(1));
// Am = 0.5, Aj = 0.5, C = 1, B = 0, 2D : 4.
// 3D configuration 2. All points are coplanar on an arbitrary plane.
// const Point_3 query3 = Point_3(-3.25022842347400, +3.9956322466210, +4.000000000000);
// const Point_3 vm3 = Point_3(-4.82908178925400, -0.9535525880045, +0.000000000000);
// const Point_3 vj3 = Point_3(-0.09833607144587, +1.9562179601920, -1.812058795517);
// const Point_3 vp3 = Point_3(+4.54574179746300, +7.9148892979530, +0.000000000000);
// Am = 17.701, Aj = 26.574, C = 13.804, B = 30.471, 3D: 0.0293453.
// 3D configuration 3. The first three points are coplanar whereas vp3 is slightly offsetted.
// const Point_3 query3 = Point_3(-3.25022842347400, +3.9956322466210, +4.0000000000000);
// const Point_3 vm3 = Point_3(-4.82908178925400, -0.9535525880045, +0.0000000000000);
// const Point_3 vj3 = Point_3(-0.09833607144587, +1.9562179601920, -1.8120587955170);
// const Point_3 vp3 = Point_3(+4.22658807629900, +8.2522664687610, -0.2914612626125);
// My area Am should coincide with the area below, but my areas Aj, C, and B should be
// closer to the second configuration than areas below.
// Am = 17.701, Aj = 26.641, C = 13.896, B = 30.524, 3D: 0.0293359.
// 3D configuration 3. The first three points are coplanar whereas vp3 is even more slightly offsetted.
// This configuration should converge to the second one comparing to the previous one.
// const Point_3 query3 = Point_3(-3.25022842347400, +3.9956322466210, +4.0000000000000);
// const Point_3 vm3 = Point_3(-4.82908178925400, -0.9535525880045, +0.0000000000000);
// const Point_3 vj3 = Point_3(-0.09833607144587, +1.9562179601920, -1.8120587955170);
// const Point_3 vp3 = Point_3(+4.41756058270700, +8.0503895685670, -0.1170591355154);
// My area Am should coincide with the area below, but my areas Aj, C, and B should be
// closer to the second configuration than areas below.
// Am = 17.701, Aj = 26.585, C = 13.819, B = 30.480, 3D: 0.0293438.
// Compute weights.
// WP wp;
// std::cout << "2D wachspress: " << wp(query2, vm2, vj2, vp2) << std::endl;
// std::cout << "3D wachspress: " << wp(query3, vm3, vj3, vp3) << std::endl;
int main() {
assert(test_kernel<SCKER>());
assert(test_kernel<EPICK>());
assert(test_kernel<EPECK>());
std::cout << "* test_wachspress_weights: SUCCESS" << std::endl;
return EXIT_SUCCESS;
}

View File

@ -1,24 +1,17 @@
To discuss:
* When computing weights one by one, we recompute certain areas/distances multiple times and so using them e.g. in barycentric coordinates is not efficient. What should we do about that?
* When computing weights one by one, we recompute certain areas/distances multiple times and so using them e.g. in barycentric coordinates is not efficient. What should we do about that? Nothing.
* Why do we have in the orbifold_Tutte_parameterizer "+tangent_weight" while in the MVC_post_processor it is "-tangent_weight"? I have fixed that.
* Do I need to cut-zero the dh weights in the orbifold_Tutte_parameterizer? (line 837) I do cut it for the moment. Otherwise, the results are not equal to the original version.
* Do I need to cut-zero the dh weights in the orbifold_Tutte_parameterizer? (line 837)? I do cut it for the moment. Otherwise, the results are not equal to the original version.
* Skeletonization uses the weird secure version for the cotangent weights.
* In skeletonization, the final example results are not determenistic.
* Should I remove the positive area from the Tangent_weight and substitute it by computing tan(alpha/2)? In this case, I will keep the correct sign in any configuration.
* What about using a solution that we currently use in the triangulate_hole_with_cdt() instead of flattening?
* Should I remove the positive area from the Tangent_weight and substitute it by computing tan(alpha/2)? In this case, I will keep the correct sign in any configuration. Yes. I did that.
Later:
* Cleanup tests.
* Comment the code.
* Check memory leaking.
* Add more pictures/figures.
* Add a concept test as in the heat_method.
* Try to combine cotangent wrappers from the tools.h. Not sure if this is necessary.
* Try to combine mvc and dhc in the orbifold parameterization. Not sure if this is necessary.
* Mention that tangent_weight_3 uses positive areas (no distortions) and can be used only for PMP, while mean_value_weight_2/3 e.g. can have different signs/distortions for 2D and 3D versions due to the flattening of the 3D region.
* Fix all other packages with respect to the new interface.
* Check memory leaking.
To do now:
* What happens with WP/MV/DH weights on the polygon boundary?
* Check if this code works with the Projection_traits_xy class. E.g. the latter does not have the object Construct_centroid_2.
* Add missing functions in Triangulation_2_projection_3 traits.
* Mention that tangent_weight_3 uses positive areas (no distortions) and can be used only for PMP, while mean_value_weight_2/3 e.g. can have different signs/distortions for 2D and 3D versions due to the flattening of the 3D region. See above.
* Fix all other packages with respect to the new interface.