Merge remote-tracking branch 'origin' into Number_types-add_benchmarks-danston

This commit is contained in:
Sébastien Loriot 2022-05-03 10:55:14 +02:00
commit bb3e0f2f17
397 changed files with 12795 additions and 9551 deletions

View File

@ -109,7 +109,7 @@ jobs:
mv tmp.html index.html
git add ${PR_NUMBER}/$ROUND index.html && git commit -q --amend -m "base commit" && git push -q -f -u origin master
else
echo "::set-output name=DoxygenError::This round already exists. Overwrite it with /force-build"
echo "::set-output name=DoxygenError::This round already exists. Overwrite it with /force-build."
exit 1
fi
@ -121,7 +121,7 @@ jobs:
const tmp_round = "${{ steps.get_round.outputs.result }}";
const id = tmp_round.indexOf(":");
const round = tmp_round.substring(0,id);
const address = "The documentation is built. It will be available, after a few minutes, here : https://cgal.github.io/${{ steps.get_pr_number.outputs.result }}/"+round+"/Manual/index.html"
const address = "The documentation is built. It will be available, after a few minutes, here: https://cgal.github.io/${{ steps.get_pr_number.outputs.result }}/"+round+"/Manual/index.html"
github.issues.createComment({
owner: "CGAL",
repo: "cgal",

View File

@ -22,11 +22,10 @@ jobs:
if [ -n "$(diff -q ./index.html ./tmp.html)" ]; then
mv tmp.html index.html
fi
if [ -d ${PR_NUMBER} ]; then
git rm -r ${PR_NUMBER}
if [ -d ${PR_NUMBER} ]; then
git rm -r ${PR_NUMBER}
fi
#git diff exits with 1 if there is no diff
if git diff --quiet; then
# `git diff --quiet` exits with 1 if there is a diff
if ! git diff --quiet; then
git commit -a --amend -m"base commit" && git push -f -u origin master
fi

View File

@ -61,7 +61,7 @@ jobs:
uses: actions/github-script@v3
with:
script: |
const address = "The testsuite is lauched. results will be found, after it is done, here : https://cgal.geometryfactory.com/~cgaltest/test_suite/TESTRESULTS/index.shtml "
const address = "Testsuite launched. Results will appear on the following page: https://cgal.geometryfactory.com/~cgaltest/test_suite/TESTRESULTS/index.shtml "
github.issues.createComment({
owner: "CGAL",
repo: "cgal",

View File

@ -3,13 +3,19 @@
\ingroup PkgAABBTreeConcepts
\cgalConcept
The concept `AABBGeomTraits` defines the requirements for the first template parameter of the class `CGAL::AABB_traits<AABBGeomTraits, AABBPrimitive>`. It provides predicates and constructors to detect and compute intersections between query objects and the primitives stored in the AABB tree. In addition, it contains predicates and constructors to compute distances between a point query and the primitives stored in the AABB tree.
The concept `AABBGeomTraits` defines the requirements for the first template parameter of the class
`CGAL::AABB_traits<AABBGeomTraits, AABBPrimitive>`. It provides predicates and constructors to detect
and compute intersections between query objects and the primitives stored in the AABB tree.
In addition, it contains predicates and constructors to compute distances between a point query
and the primitives stored in the AABB tree.
\cgalRefines `SearchGeomTraits_3`
\cgalHasModel Any 3D Kernel is a model of this traits concept.
\cgalHasModel All models of the concept `Kernel`
\sa `CGAL::AABB_traits<AABBGeomTraits,AABBPrimitive>`
\sa `CGAL::AABB_tree<AABBTraits>`
\sa `AABBPrimitive`
*/
@ -19,118 +25,123 @@ public:
/// \name Types
/// @{
/*!
A number type model of `Field`.
*/
typedef unspecified_type FT;
/*!
Sphere type, that should be consistent with the distance function chosen for the distance queries, namely the `Squared_distance_3` functor.
*/
typedef unspecified_type Sphere_3;
/*!
Point type.
*/
typedef unspecified_type Point_3;
/*!
A functor object to detect intersections between two geometric objects.
Provides the operators:
`bool operator()(const Type_1& type_1, const Type_2& type_2);`
where `Type_1` and `Type_2` are relevant types
among `Ray_3`, `Segment_3`, `Line_3`, `Triangle_3`, `Plane_3` and `Bbox_3`. Relevant herein means that a line primitive (ray, segment, line) is tested against a planar or solid primitive (plane, triangle, box), and a solid primitive is tested against another solid primitive (box against box). The operator returns `true` iff `type_1` and `type_2` have a non empty intersection.
Provides the following operators:
`bool operator()(Query, Bbox_3)`,
`bool operator()(Query, Primitive::Datum)`,
`bool operator()(Sphere_3, Bbox_3)`.
The operator returns `true` iff there exists a non-empty intersection.
*/
typedef unspecified_type Do_intersect_3;
/*!
A functor object to construct the intersection between two geometric objects.
Provides the operators:
`decltype(auto) operator()(const A& a, const B& b);`
where `A` and `B` are any relevant types among `Ray_3`, `Segment_3`, `Line_3`,
`Triangle_3`, `Plane_3` and `Bbox_3`.
Relevant herein means that a line primitive (ray, segment, line) is tested
against a planar or solid primitive (plane, triangle, box).
A model of `Kernel::Intersect_3` fulfills those requirements.
Provides the operator:
`return_type operator()(const Query& q, const Primitive::Datum& d)`,
which computes the intersection between `q` and `d`. The type of the returned object
must be a `boost::optional` of a `boost::variant` of the possible intersection types.
*/
typedef unspecified_type Intersect_3;
/*!
A functor object to construct the sphere centered at one point and passing through another one. Provides the operator:
- `Sphere_3 operator()(const Point_3& p, const FT & sr)` which returns the sphere centered at `p` with `sr` as squared radius.
A functor object to construct the sphere centered at one point and passing through another one.
Provides the operator:
`Sphere_3 operator()(const Point_3& p, const FT & sr)`,
which returns the sphere centered at `p` with `sr` as squared radius.
*/
typedef unspecified_type Construct_sphere_3;
/*!
A functor object to compute the point on a geometric primitive which is closest from a query. Provides the operator:
`Point_3 operator()(const Type_2& type_2, const Point_3& p);` where `Type_2` can be any of the following types : `Segment_3`, `Ray_3`, or `Triangle_3`.
The operator returns the point on `type_2` which is closest to `p`.
A functor object to compute the point on a geometric primitive which is closest from a query.
Provides the operator:
`Point_3 operator()(const Primitive::Datum& d, const Point_3& p)`,
which returns the point on `d` that is closest to `p`.
*/
typedef unspecified_type Construct_projected_point_3;
/*!
A functor object to compare the distance of two points wrt a third one.
Provides the operator:
`CGAL::Comparision_result operator()(const Point_3& p1, const Point_3& p2, const Point_3& p3)`. The operator compare the distance between `p1 and `p2`, and between `p2` and `p3`.
A functor object to compare the distance of two points wrt a third one. Provides the operator:
`CGAL::Comparision_result operator()(const Point_3& p1, const Point_3& p2, const Point_3& p3)`,
which compares the distance between `p1 and `p2`, and between `p2` and `p3`.
*/
typedef unspecified_type Compare_distance_3;
/*!
A functor object to detect if a point lies inside a sphere or not.
A functor object to compute the squared radius of a sphere.
Provides the operator:
`bool operator()(const Sphere_3& s, const Point_3& p);` which returns `true` iff the closed volume bounded by `s` contains `p`.
*/
typedef unspecified_type Has_on_bounded_side_3;
/*!
A functor object to compute the squared radius of a sphere. Provides the operator:
`FT operator()(const Sphere_3& s);` which returns the squared radius of `s`.
`FT operator()(const Sphere_3& s),`
which returns the squared radius of `s`.
*/
typedef unspecified_type Compute_squared_radius_3;
/*!
A functor object to compute the squared distance between two points. Provides the operator:
`FT operator()(const Point_3& p, const Point_3& q);}` which returns the squared distance between `p` and `q`.
`FT operator()(const Point_3& p, const Point_3& q),`
which returns the squared distance between `p` and `q`.
*/
typedef unspecified_type Compute_squared_distance_3;
/*!
A functor object to compare the x-coordinates of two points. Provides the operator:
`bool operator()(const Point_3& p, const Point_3& q);}` which returns `true` if the x-coordinate of `p` is smaller
than the x-coordinate of `q`.
`bool operator()(const Point_3& p, const Point_3& q)`,
which returns `true` iff the x-coordinate of `p` is smaller than the x-coordinate of `q`.
*/
typedef unspecified_type Less_x_3;
/*!
A functor object to compare the y-coordinates of two points. Provides the operator:
`bool operator()(const Point_3& p, const Point_3& q);}` which returns `true` if the y-coordinate of `p` is smaller
than the y-coordinate of `q`.
`bool operator()(const Point_3& p, const Point_3& q)`,
which returns `true` iff the y-coordinate of `p` is smaller than the y-coordinate of `q`.
*/
typedef unspecified_type Less_y_3;
/*!
A functor object to compare the z-coordinates of two points. Provides the operator:
`bool operator()(const Point_3& p, const Point_3& q);}` which returns `true` if the z-coordinate of `p` is smaller
than the z-coordinate of `q`.
`bool operator()(const Point_3& p, const Point_3& q)`,
which returns `true` iff the z-coordinate of `p` is smaller than the z-coordinate of `q`.
*/
typedef unspecified_type Less_z_3;
/*!
A functor object to compare two points. Provides the operator:
`bool operator()(const Point_3& p, const Point_3& q);}` which returns `true` if `p` is equal to `q`.
`bool operator()(const Point_3& p, const Point_3& q)`,
which returns `true` iff `p` is equal to `q`.
*/
typedef unspecified_type Equal_3;
/// @}
/// \name Operations
/// @{
/*!
returns the intersection detection functor.
returns the intersection detection predicate.
*/
Do_intersect_3 do_intersect_3_object();
@ -150,15 +161,10 @@ returns the closest point constructor.
Construct_projected_point_3 construct_projected_point_3_object();
/*!
returns the compare distance constructor.
returns the compare distance predicate.
*/
Compare_distance_3 compare_distance_3_object();
/*!
returns the closest point constructor.
*/
Has_on_bounded_side_3 has_on_bounded_side_3_object();
/*!
returns the squared radius functor.
*/
@ -170,22 +176,22 @@ returns the squared distance functor.
Compute_squared_distance_3 compute_squared_distance_3_object();
/*!
returns the `Less_x_3` functor.
returns the `Less_x_3` predicate.
*/
Less_x_3 less_x_3_object();
/*!
returns the `Less_y_3` functor.
returns the `Less_y_3` predicate.
*/
Less_y_3 less_y_3_object();
/*!
returns the `Less_z_3` functor.
returns the `Less_z_3` predicate.
*/
Less_z_3 less_z_3_object();
/*!
returns the equal functor.
returns the equal predicate.
*/
Equal_3 equal_3_object();

View File

@ -8,7 +8,8 @@ concept `AABBGeomTraits`. In addition to the types required by
define the Intersection_distance functor.
\cgalRefines `AABBGeomTraits`
\cgalHasModel Any 3D Kernel is a model of this concept.
\cgalHasModel All models of the concept `Kernel`
\sa `CGAL::AABB_traits<AABBGeomTraits,AABBPrimitive>`
\sa `CGAL::AABB_tree<AABBTraits>`
@ -17,11 +18,6 @@ define the Intersection_distance functor.
*/
class AABBRayIntersectionGeomTraits {
public:
/*!
Type of a 3D point.
*/
typedef unspecified_type Point_3;
/*!
Type of a 3D ray.
*/

View File

@ -9,7 +9,6 @@ distance of an intersection along a ray.
\cgalHasModel `CGAL::AABB_traits<AABBGeomTraits,AABBPrimitive>`
\sa `CGAL::AABB_traits<AABBGeomTraits,AABBPrimitive>`
\sa `CGAL::AABB_tree<AABBTraits>`
\sa `AABBPrimitive`

View File

@ -25,8 +25,10 @@
\cgalCRPSection{Concepts}
- `AABBPrimitive`
- `AABBPrimitiveWithSharedData`
- `AABBTraits`
- `AABBGeomTraits`
- `AABBTraits`
- `AABBRayIntersectionGeomTraits`
- `AABBRayIntersectionTraits`
\cgalCRPSection{Classes}
- `CGAL::AABB_traits<GeomTraits,Primitive>`

View File

@ -44,7 +44,7 @@ struct Skip
int main(int argc, char* argv[])
{
const char* filename = (argc > 1) ? argv[1] : "data/tetrahedron.off";
const std::string filename = (argc > 1) ? argv[1] : CGAL::data_file_path("meshes/tetrahedron.off");
Mesh mesh;
if(!CGAL::IO::read_polygon_mesh(filename, mesh))

View File

@ -160,7 +160,7 @@ class AABB_tree;
/// \tparam BboxMap must be a model of `ReadablePropertyMap` that has as key type a primitive id,
/// and as value type a `Bounding_box`.
/// If the type is `Default` the `Datum` must have the
/// member function `bbox()` that returns the bounding box of the primitive.
/// member function `bbox()` that returns the bounding box of the primitive.
///
/// If the argument `GeomTraits` is a model of the concept \ref
/// AABBRayIntersectionGeomTraits, this class is also a model of \ref
@ -366,7 +366,7 @@ public:
template<typename Query>
boost::optional< typename Intersection_and_primitive_id<Query>::Type >
operator()(const Query& query, const typename AT::Primitive& primitive) const {
auto inter_res = GeomTraits().intersect_3_object()(internal::Primitive_helper<AT>::get_datum(primitive,m_traits),query);
auto inter_res = GeomTraits().intersect_3_object()(query, internal::Primitive_helper<AT>::get_datum(primitive,m_traits));
if (!inter_res)
return boost::none;
return boost::make_optional( std::make_pair(*inter_res, primitive.id()) );
@ -391,9 +391,9 @@ public:
GeomTraits geom_traits;
Point closest_point = geom_traits.construct_projected_point_3_object()(
internal::Primitive_helper<AT>::get_datum(pr,m_traits), p);
return
geom_traits.compare_distance_3_object()(p, closest_point, bound)==LARGER ?
bound : closest_point;
return (geom_traits.compare_distance_3_object()(p, closest_point, bound) == LARGER) ?
bound : closest_point;
}
};
@ -406,15 +406,6 @@ public:
typedef typename AT::FT FT;
typedef typename AT::Primitive Primitive;
public:
template <class Solid>
CGAL::Comparison_result operator()(const Point& p, const Solid& pr, const Point& bound) const
{
return GeomTraits().do_intersect_3_object()
(GeomTraits().construct_sphere_3_object()
(p, GeomTraits().compute_squared_distance_3_object()(p, bound)), pr)?
CGAL::SMALLER : CGAL::LARGER;
}
CGAL::Comparison_result operator()(const Point& p, const Bounding_box& bb, const Point& bound, Tag_true) const
{
return GeomTraits().do_intersect_3_object()
@ -436,6 +427,16 @@ public:
return (*this)(p, bb, bound, Boolean_tag<internal::Has_static_filters<GeomTraits>::value>());
}
// The following functions seem unused...?
template <class Solid>
CGAL::Comparison_result operator()(const Point& p, const Solid& pr, const Point& bound) const
{
return GeomTraits().do_intersect_3_object()
(GeomTraits().construct_sphere_3_object()
(p, GeomTraits().compute_squared_distance_3_object()(p, bound)), pr)?
CGAL::SMALLER : CGAL::LARGER;
}
template <class Solid>
CGAL::Comparison_result operator()(const Point& p, const Solid& pr, const FT& sq_distance) const
{
@ -445,7 +446,6 @@ public:
CGAL::SMALLER :
CGAL::LARGER;
}
};
Closest_point closest_point_object() const {return Closest_point(*this);}

View File

@ -38,7 +38,7 @@ int test()
// load polyhedron
typedef CGAL::Polyhedron_3<K> Polyhedron;
Polyhedron polyhedron;
std::ifstream ifs("./data/tetrahedron.off");
std::ifstream ifs(CGAL::data_file_path("meshes/tetrahedron.off"));
ifs >> polyhedron;
// construct tree from facets
@ -129,4 +129,3 @@ int main()
/* Local Variables: */
/* tab-width: 2 */
/* End: */

View File

@ -12,14 +12,12 @@ struct AABBGeomTraits {
typedef nope Intersect_3;
typedef nope Construct_sphere_3;
typedef nope Compute_closest_point_3;
typedef nope Has_on_bounded_side_3;
typedef nope Compute_squared_radius_3;
typedef nope Compute_squared_distance_3;
Do_intersect_3 do_intersect_3_object();
Intersect_3 intersect_3_object();
Construct_sphere_3 construct_sphere_3_object();
Compute_closest_point_3 compute_closest_point_3_object();
Has_on_bounded_side_3 has_on_bounded_side_3_object();
Compute_squared_radius_3 compute_squared_radius_3_object();
Compute_squared_distance_3 compute_squared_distance_3_object();
}; /* end AABBGeomTraits */

View File

@ -19,7 +19,6 @@ Kernel_d
Modifier
Modular_arithmetic
Number_types
Polygon
Polyhedron
Profiling_tools
Property_map

View File

@ -148,33 +148,26 @@ template<class A , class B, int > struct Coercion_traits_for_level;
CGAL_DEFINE_COERCION_TRAITS_FROM_TO(short,int)
CGAL_DEFINE_COERCION_TRAITS_FROM_TO(short,long)
#ifdef CGAL_USE_LONG_LONG
CGAL_DEFINE_COERCION_TRAITS_FROM_TO(short,long long)
#endif
CGAL_DEFINE_COERCION_TRAITS_FROM_TO(short,long long)
CGAL_DEFINE_COERCION_TRAITS_FROM_TO(short,float)
CGAL_DEFINE_COERCION_TRAITS_FROM_TO(short,double)
CGAL_DEFINE_COERCION_TRAITS_FROM_TO(short,long double)
CGAL_DEFINE_COERCION_TRAITS_FROM_TO(int,long)
#ifdef CGAL_USE_LONG_LONG
CGAL_DEFINE_COERCION_TRAITS_FROM_TO(int,long long)
#endif
CGAL_DEFINE_COERCION_TRAITS_FROM_TO(int,long long)
CGAL_DEFINE_COERCION_TRAITS_FROM_TO(int,float)
CGAL_DEFINE_COERCION_TRAITS_FROM_TO(int,double)
CGAL_DEFINE_COERCION_TRAITS_FROM_TO(int,long double)
#ifdef CGAL_USE_LONG_LONG
CGAL_DEFINE_COERCION_TRAITS_FROM_TO(long,long long)
#endif
CGAL_DEFINE_COERCION_TRAITS_FROM_TO(long,long long)
CGAL_DEFINE_COERCION_TRAITS_FROM_TO(long,float)
CGAL_DEFINE_COERCION_TRAITS_FROM_TO(long,double)
CGAL_DEFINE_COERCION_TRAITS_FROM_TO(long,long double)
#ifdef CGAL_USE_LONG_LONG
CGAL_DEFINE_COERCION_TRAITS_FROM_TO(long long,float)
CGAL_DEFINE_COERCION_TRAITS_FROM_TO(long long,double)
CGAL_DEFINE_COERCION_TRAITS_FROM_TO(long long,long double)
#endif
CGAL_DEFINE_COERCION_TRAITS_FROM_TO(long long,float)
CGAL_DEFINE_COERCION_TRAITS_FROM_TO(long long,double)
CGAL_DEFINE_COERCION_TRAITS_FROM_TO(long long,long double)
CGAL_DEFINE_COERCION_TRAITS_FROM_TO(float,double)
CGAL_DEFINE_COERCION_TRAITS_FROM_TO(float,long double)
@ -198,9 +191,7 @@ struct Coercion_traits<A,A>{
CGAL_DEFINE_COERCION_TRAITS_FOR_SELF(short)
CGAL_DEFINE_COERCION_TRAITS_FOR_SELF(int)
CGAL_DEFINE_COERCION_TRAITS_FOR_SELF(long)
#ifdef CGAL_USE_LONG_LONG
CGAL_DEFINE_COERCION_TRAITS_FOR_SELF(long long)
#endif
CGAL_DEFINE_COERCION_TRAITS_FOR_SELF(long long)
CGAL_DEFINE_COERCION_TRAITS_FOR_SELF(float)
CGAL_DEFINE_COERCION_TRAITS_FOR_SELF(double)
CGAL_DEFINE_COERCION_TRAITS_FOR_SELF(long double)

View File

@ -75,11 +75,9 @@ template <> struct Needs_parens_as_product<long>{
bool operator()(const long& x){return x < long(0);}
};
#ifdef CGAL_USE_LONG_LONG
template <> struct Needs_parens_as_product<long long>{
bool operator()(const long long& x){return x < (long long)(0);}
};
#endif
template <> struct Needs_parens_as_product<float>{
bool operator()(const float& x){return x < float(0);}

View File

@ -11,7 +11,6 @@ Interval_support
Kernel_23
Modular_arithmetic
Number_types
Polygon
Profiling_tools
Property_map
STL_Extension

View File

@ -14,7 +14,6 @@ Interval_support
Kernel_23
Modular_arithmetic
Number_types
Polygon
Profiling_tools
Property_map
STL_Extension

View File

@ -27,6 +27,7 @@
#include <iostream>
#include <string.h>
#include <atomic>
#include <array>
#include <CGAL/basic.h>
#include <CGAL/Arr_enums.h>
@ -885,11 +886,11 @@ public:
/*! Clean all operation counters */
void clear_counters()
{ memset(m_counters, 0, sizeof(m_counters)); }
{ m_counters = {}; }
private:
/*! The operation counters */
mutable size_t m_counters[NUMBER_OF_OPERATIONS];
mutable std::array<size_t, NUMBER_OF_OPERATIONS> m_counters;
};
template <typename Out_stream, class Base_traits>

View File

@ -263,7 +263,7 @@ public:
Comparison_result res =
ker.compare_x_2_object()(this->_source, this->_target);
this->_info = (Conic_arc_2::IS_VALID | DEGREE_1);
this->_info = (static_cast<int>(Conic_arc_2::IS_VALID) | static_cast<int>(DEGREE_1));
if (res == EQUAL) {
// Mark that the segment is vertical.
this->_info = (this->_info | IS_VERTICAL_SEGMENT);

View File

@ -169,19 +169,15 @@ overlay(const Arrangement_on_surface_2<GeometryTraitsA_2, TopologyTraitsA>& arr1
typedef typename Arr_res::Allocator Allocator;
// some type assertions (not all, but better than nothing).
#if !defined(CGAL_NO_ASSERTIONS)
typedef typename Agt2::Point_2 A_point;
typedef typename Bgt2::Point_2 B_point;
typedef typename Rgt2::Point_2 Res_point;
#endif
CGAL_static_assertion((boost::is_convertible<A_point, Res_point>::value));
CGAL_static_assertion((boost::is_convertible<B_point, Res_point>::value));
#if !defined(CGAL_NO_ASSERTIONS)
typedef typename Agt2::X_monotone_curve_2 A_xcv;
typedef typename Bgt2::X_monotone_curve_2 B_xcv;
typedef typename Rgt2::X_monotone_curve_2 Res_xcv;
#endif
CGAL_static_assertion((boost::is_convertible<A_xcv, Res_xcv>::value));
CGAL_static_assertion((boost::is_convertible<B_xcv, Res_xcv>::value));

View File

@ -20,6 +20,7 @@
#include <vector>
#include <fstream>
#include <sstream>
#include <cstdio>
namespace CGAL {
@ -750,14 +751,17 @@ public:
return;
// Prepare a string desribing the color.
char color_desc [10];
sprintf ("#%02x%02x%02x", r, g, b);
std::stringstream out;
out << "0x" << std::hex
<< std::setfill('0') << std::setw(2) << r
<< std::setfill('0') << std::setw(2) << g
<< std::setfill('0') << std::setw(2) << b;
// Write the color to the FIG file.
_ofile << "0 " // Desginates a color pseudo-object.
<< static_cast<int>(color) << ' '
<< color_desc << std::endl;
<< out.str() << std::endl;
// Mark that the color is now defined.
colors[static_cast<int>(color)] = true;
@ -1700,7 +1704,6 @@ protected:
_ofile << ' ' << ix << ' ' << iy << ' ';
// Write the text.
char oct[10];
int i;
for (i = 0; i < len_text; i++)
@ -1712,9 +1715,11 @@ protected:
}
else
{
// Convert the current character to an octal string and write it.
sprintf (oct, "\\%03o", text[i]);
_ofile << oct;
// Convert the current character to an octal string and write
// it.
std::stringstream out;
out << "\\" << std::setfill('0') << std::setw(3) << std::oct << text[i];
_ofile << out.str();
}
}

View File

@ -84,7 +84,7 @@ bool read_PLY_BGL(std::istream& is,
The data is expected to represent a 2-manifold (possibly with borders).
\attention When reading a binary file, the flag `std::ios::binary` flag must be set during the creation of the `ifstream`.
\attention To read a binary file, the flag `std::ios::binary` must be set during the creation of the `ifstream`.
\tparam Graph a model of `MutableFaceGraph`
\tparam NamedParameters a sequence of \ref bgl_namedparameters "Named Parameters"
@ -266,7 +266,9 @@ bool read_PLY(const std::string& fname, Graph& g,
\brief writes the graph in an output stream, using the \ref IOStreamPLY.
\attention When writing a binary file, the flag `std::ios::binary` flag must be set during the creation of the `ofstream`.
\attention To write to a binary file, the flag `std::ios::binary` must be set during the creation
of the `ofstream`, and the \link PkgStreamSupportEnumRef `IO::Mode` \endlink
of the stream must be set to `BINARY`.
\tparam Graph a model of `FaceListGraph`
\tparam NamedParameters a sequence of \ref bgl_namedparameters "Named Parameters"

View File

@ -73,7 +73,7 @@ public:
\attention The graph `g` is not cleared, and the data from the stream are appended.
\attention When reading a binary file, the flag `std::ios::binary` flag must be set during the creation of the `ifstream`.
\attention To read a binary file, the flag `std::ios::binary` must be set during the creation of the `ifstream`.
\tparam Graph a model of `MutableFaceGraph`
\tparam NamedParameters a sequence of \ref bgl_namedparameters "Named Parameters"
@ -208,7 +208,9 @@ bool read_STL(const std::string& fname, Graph& g) { return read_STL(fname, g, pa
\brief writes the graph `g` in the output stream `os`, using the \ref IOStreamSTL.
\attention When writing a binary file, the flag `std::ios::binary` flag must be set during the creation of the `ofstream`.
\attention To write to a binary file, the flag `std::ios::binary` must be set during the creation
of the `ofstream`, and the \link PkgStreamSupportEnumRef `IO::Mode` \endlink of the stream
must be set to `BINARY`.
\tparam Graph a model of `FaceListGraph` and `HalfedgeListGraph`
\tparam NamedParameters a sequence of \ref bgl_namedparameters "Named Parameters"

View File

@ -16,6 +16,7 @@
#include <boost/type_traits/is_same.hpp>
#include <boost/mpl/if.hpp>
#include <type_traits>
#define CGAL_BGL_NP_TEMPLATE_PARAMETERS T, typename Tag, typename Base
#define CGAL_BGL_NP_CLASS CGAL::Named_function_parameters<T,Tag,Base>
@ -38,8 +39,9 @@ enum all_default_t { all_default };
template <typename T, typename Tag, typename Base>
struct Named_params_impl : Base
{
T v; // copy of the parameter
Named_params_impl(T v, const Base& b)
typename std::conditional<std::is_copy_constructible<T>::value,
T, std::reference_wrapper<const T> >::type v; // copy of the parameter if copyable
Named_params_impl(const T& v, const Base& b)
: Base(b)
, v(v)
{}
@ -49,8 +51,9 @@ struct Named_params_impl : Base
template <typename T, typename Tag>
struct Named_params_impl<T, Tag, No_property>
{
T v; // copy of the parameter
Named_params_impl(T v)
typename std::conditional<std::is_copy_constructible<T>::value,
T, std::reference_wrapper<const T> >::type v; // copy of the parameter if copyable
Named_params_impl(const T& v)
: v(v)
{}
};
@ -63,18 +66,39 @@ template< typename T, typename Tag, typename Query_tag>
struct Get_param< Named_params_impl<T, Tag, No_property>, Query_tag >
{
typedef Param_not_found type;
typedef Param_not_found reference;
};
template< typename T, typename Tag, typename Base>
struct Get_param< Named_params_impl<T, Tag, Base>, Tag >
{
typedef T type;
typedef typename std::conditional<std::is_copy_constructible<T>::value,
T, std::reference_wrapper<const T> >::type type;
typedef typename std::conditional<std::is_copy_constructible<T>::value,
T, const T&>::type reference;
};
template< typename T, typename Tag>
struct Get_param< Named_params_impl<T, Tag, No_property>, Tag >
{
typedef T type;
typedef typename std::conditional<std::is_copy_constructible<T>::value,
T, std::reference_wrapper<const T> >::type type;
typedef typename std::conditional<std::is_copy_constructible<T>::value,
T, const T&>::type reference;
};
template< typename T, typename Tag, typename Base>
struct Get_param< Named_params_impl<std::reference_wrapper<T>, Tag, Base>, Tag >
{
typedef std::reference_wrapper<T> type;
typedef T& reference;
};
template< typename T, typename Tag>
struct Get_param< Named_params_impl<std::reference_wrapper<T>, Tag, No_property>, Tag >
{
typedef std::reference_wrapper<T> type;
typedef T& reference;
};
@ -82,6 +106,7 @@ template< typename T, typename Tag, typename Base, typename Query_tag>
struct Get_param< Named_params_impl<T,Tag,Base>, Query_tag>
{
typedef typename Get_param<typename Base::base, Query_tag>::type type;
typedef typename Get_param<typename Base::base, Query_tag>::reference reference;
};
// helper to choose the default
@ -89,16 +114,24 @@ template <typename Query_tag, typename NP, typename D>
struct Lookup_named_param_def
{
typedef typename internal_np::Get_param<typename NP::base, Query_tag>::type NP_type;
typedef typename internal_np::Get_param<typename NP::base, Query_tag>::reference NP_reference;
typedef typename boost::mpl::if_<
boost::is_same<NP_type, internal_np::Param_not_found>,
D, NP_type>::type
type;
typedef typename boost::mpl::if_<
boost::is_same<NP_reference, internal_np::Param_not_found>,
D&, NP_reference>::type
reference;
};
// helper function to extract the value from a named parameter pack given a query tag
template <typename T, typename Tag, typename Base>
T get_parameter_impl(const Named_params_impl<T, Tag, Base>& np, Tag)
typename std::conditional<std::is_copy_constructible<T>::value,
T, std::reference_wrapper<const T> >::type
get_parameter_impl(const Named_params_impl<T, Tag, Base>& np, Tag)
{
return np.v;
}
@ -110,7 +143,9 @@ Param_not_found get_parameter_impl(const Named_params_impl<T, Tag, No_property>&
}
template< typename T, typename Tag>
T get_parameter_impl(const Named_params_impl<T, Tag, No_property>& np, Tag)
typename std::conditional<std::is_copy_constructible<T>::value,
T, std::reference_wrapper<const T> >::type
get_parameter_impl(const Named_params_impl<T, Tag, No_property>& np, Tag)
{
return np.v;
};
@ -123,6 +158,67 @@ get_parameter_impl(const Named_params_impl<T, Tag, Base>& np, Query_tag tag)
return get_parameter_impl(static_cast<const typename Base::base&>(np), tag);
}
// helper for getting references
template <class T>
const T& get_reference(const T& t)
{
return t;
}
template <class T>
T& get_reference(const std::reference_wrapper<T>& r)
{
return r.get();
}
// helper function to extract the reference from a named parameter pack given a query tag
template <typename T, typename Tag, typename Base>
typename std::conditional<std::is_copy_constructible<T>::value,
T, const T& >::type
get_parameter_reference_impl(const Named_params_impl<T, Tag, Base>& np, Tag)
{
return get_reference(np.v);
}
template< typename T, typename Tag, typename Query_tag>
Param_not_found
get_parameter_reference_impl(const Named_params_impl<T, Tag, No_property>&, Query_tag)
{
return Param_not_found();
}
template< typename T, typename Tag>
typename std::conditional<std::is_copy_constructible<T>::value,
T, const T& >::type
get_parameter_reference_impl(const Named_params_impl<T, Tag, No_property>& np, Tag)
{
return get_reference(np.v);
};
template <typename T, typename Tag, typename Base>
T&
get_parameter_reference_impl(const Named_params_impl<std::reference_wrapper<T>, Tag, Base>& np, Tag)
{
return np.v.get();
}
template< typename T, typename Tag>
T&
get_parameter_reference_impl(const Named_params_impl<std::reference_wrapper<T>, Tag, No_property>& np, Tag)
{
return np.v.get();
};
template <typename T, typename Tag, typename Base, typename Query_tag>
typename Get_param<Named_params_impl<T, Tag, Base>, Query_tag>::reference
get_parameter_reference_impl(const Named_params_impl<T, Tag, Base>& np, Query_tag tag)
{
CGAL_static_assertion( (!boost::is_same<Query_tag, Tag>::value) );
return get_parameter_reference_impl(static_cast<const typename Base::base&>(np), tag);
}
} // end of internal_np namespace
@ -133,8 +229,9 @@ struct Named_function_parameters
typedef internal_np::Named_params_impl<T, Tag, Base> base;
typedef Named_function_parameters<T, Tag, Base> self;
Named_function_parameters(T v = T()) : base(v) {}
Named_function_parameters(T v, const Base& b) : base(v, b) {}
Named_function_parameters() : base(T()) {}
Named_function_parameters(const T& v) : base(v) {}
Named_function_parameters(const T& v, const Base& b) : base(v, b) {}
Named_function_parameters<bool, internal_np::all_default_t, self>
all_default() const
@ -178,7 +275,7 @@ inline no_parameters(Named_function_parameters<T,Tag,Base>)
#define CGAL_add_named_parameter(X, Y, Z) \
template <typename K> \
Named_function_parameters<K, internal_np::X> \
Z(K const& p) \
Z(const K& p) \
{ \
typedef Named_function_parameters<K, internal_np::X> Params;\
return Params(p); \
@ -194,13 +291,40 @@ get_parameter(const Named_function_parameters<T, Tag, Base>& np, Query_tag tag)
return internal_np::get_parameter_impl(static_cast<const internal_np::Named_params_impl<T, Tag, Base>&>(np), tag);
}
template <typename T, typename Tag, typename Base, typename Query_tag>
typename internal_np::Get_param<internal_np::Named_params_impl<T, Tag, Base>, Query_tag>::reference
get_parameter_reference(const Named_function_parameters<T, Tag, Base>& np, Query_tag tag)
{
return internal_np::get_parameter_reference_impl(
static_cast<const internal_np::Named_params_impl<T, Tag, Base>&>(np),
tag);
}
// Two parameters, non-trivial default value
template <typename D>
D choose_parameter(const internal_np::Param_not_found&, const D& d)
D& choose_parameter(const internal_np::Param_not_found&, D& d)
{
return d;
}
template <typename D>
const D& choose_parameter(const internal_np::Param_not_found&, const D& d)
{
return d;
}
template <typename D>
D choose_parameter(const internal_np::Param_not_found&, D&& d)
{
return std::forward<D>(d);
}
template <typename T, typename D>
T& choose_parameter(T& t, D&)
{
return t;
}
template <typename T, typename D>
const T& choose_parameter(const T& t, const D&)
{

View File

@ -205,7 +205,7 @@ private:
public:
Halfedge_around_source_iterator()
: anchor(), pos(), g(0)
: anchor(), pos(), g(nullptr), winding(0)
{}
Halfedge_around_source_iterator(halfedge_descriptor hd, const Graph& g, int n=0)
@ -305,7 +305,7 @@ private:
public:
Halfedge_around_target_iterator()
: anchor(), pos(), g(0)
: anchor(), pos(), g(nullptr), winding(0)
{}
Halfedge_around_target_iterator(halfedge_descriptor hd, const Graph& g, int n=0)

View File

@ -153,7 +153,7 @@ void duplicate_terminal_vertices(Graph& graph,
{
typename boost::graph_traits<OrigGraph>::vertex_descriptor orig_v = graph[v];
typename boost::graph_traits<Graph>::degree_size_type deg = degree(v, graph);
if ((deg != 0 && is_terminal(orig_v, orig)) || deg > 2)
if (deg != 2 || is_terminal(orig_v, orig))
{
out_edge_iterator b, e;
boost::tie(b, e) = out_edges(v, graph);
@ -170,7 +170,6 @@ void duplicate_terminal_vertices(Graph& graph,
const std::pair<edge_descriptor, bool> pair = add_edge(vc, w, graph);
graph[pair.first] = orig_e;
}
CGAL_assertion(degree(v, graph) == 1);
}
}

View File

@ -4,6 +4,9 @@
#include <cstdlib>
namespace inp = CGAL::internal_np;
namespace params = CGAL::parameters;
template <int i>
struct A
{
@ -11,6 +14,12 @@ struct A
int v;
};
struct B
{
B(){}
B(const B&) = delete;
};
template <int i, class T>
void check_same_type(T)
{
@ -20,416 +29,78 @@ void check_same_type(T)
}
template<class NamedParameters>
void test(const NamedParameters& np)
void test_values_and_types(const NamedParameters& np)
{
using CGAL::parameters::get_parameter;
using params::get_parameter;
// Test values
// test values
assert(get_parameter(np, inp::vertex_index).v == 0);
assert(get_parameter(np, inp::visitor).v == 1);
// Named parameters that we use in CGAL
assert(get_parameter(np, CGAL::internal_np::vertex_index).v == 0);
assert(get_parameter(np, CGAL::internal_np::visitor).v == 1);
assert(get_parameter(np, CGAL::internal_np::vertex_point).v == 2);
assert(get_parameter(np, CGAL::internal_np::halfedge_index).v == 3);
assert(get_parameter(np, CGAL::internal_np::edge_index).v == 4);
assert(get_parameter(np, CGAL::internal_np::face_index).v == 5);
// test types
check_same_type<0>(get_parameter(np, inp::vertex_index));
check_same_type<1>(get_parameter(np, inp::visitor));
}
assert(get_parameter(np, CGAL::internal_np::edge_is_constrained).v == 6);
assert(get_parameter(np, CGAL::internal_np::first_index).v == 7);
assert(get_parameter(np, CGAL::internal_np::number_of_iterations).v == 8);
template<class NamedParameters>
void test_no_copyable(const NamedParameters& np)
{
typedef typename inp::Get_param<typename NamedParameters::base,inp::visitor_t>::type NP_type;
CGAL_static_assertion( (boost::is_same<NP_type,std::reference_wrapper<const B> >::value) );
assert(get_parameter(np, CGAL::internal_np::METIS_options).v == 800000001);
assert(get_parameter(np, CGAL::internal_np::vertex_partition_id).v == 800000002);
assert(get_parameter(np, CGAL::internal_np::face_partition_id).v == 800000003);
const A<4>& a = params::choose_parameter(params::get_parameter_reference(np, inp::edge_index), A<4>(4));
assert(a.v==4);
}
assert(get_parameter(np, CGAL::internal_np::vertex_to_vertex_output_iterator).v == 800000004);
assert(get_parameter(np, CGAL::internal_np::halfedge_to_halfedge_output_iterator).v == 800000005);
assert(get_parameter(np, CGAL::internal_np::face_to_face_output_iterator).v == 800000006);
template <class NamedParameters>
void test_references(const NamedParameters& np)
{
typedef A<2> Default_type;
Default_type default_value(2);
assert(get_parameter(np, CGAL::internal_np::vertex_to_vertex_map).v == 800000007);
assert(get_parameter(np, CGAL::internal_np::halfedge_to_halfedge_map).v == 800000008);
assert(get_parameter(np, CGAL::internal_np::face_to_face_map).v == 800000009);
// std::reference_wrapper
typedef typename inp::Lookup_named_param_def<inp::visitor_t, NamedParameters, Default_type>::reference Visitor_reference_type;
CGAL_static_assertion( (std::is_same<B&, Visitor_reference_type>::value) );
Visitor_reference_type vis_ref = params::choose_parameter(params::get_parameter_reference(np, inp::visitor), default_value);
CGAL_USE(vis_ref);
assert(get_parameter(np, CGAL::internal_np::implementation_tag).v == 800000010);
assert(get_parameter(np, CGAL::internal_np::prevent_unselection).v == 800000011);
// std::reference_wrapper of const
typedef typename inp::Lookup_named_param_def<inp::face_index_t, NamedParameters, Default_type>::reference FIM_reference_type;
CGAL_static_assertion( (std::is_same<const B&, FIM_reference_type>::value) );
FIM_reference_type fim_ref = params::choose_parameter(params::get_parameter_reference(np, inp::face_index), default_value);
CGAL_USE(fim_ref);
assert(get_parameter(np, CGAL::internal_np::stream_precision).v == 800000012);
// non-copyable
typedef typename inp::Lookup_named_param_def<inp::vertex_point_t, NamedParameters, Default_type>::reference VPM_reference_type;
CGAL_static_assertion( (std::is_same<const B&, VPM_reference_type>::value) );
VPM_reference_type vpm_ref = params::choose_parameter(params::get_parameter_reference(np, inp::vertex_point), default_value);
CGAL_USE(vpm_ref);
// Named parameters that we use in the package 'Mesh_3'
assert(get_parameter(np, CGAL::internal_np::vertex_feature_degree).v == 9);
// passed by copy
typedef typename inp::Lookup_named_param_def<inp::vertex_index_t, NamedParameters, Default_type>::reference VIM_reference_type;
CGAL_static_assertion( (std::is_same<A<0>, VIM_reference_type>::value) );
VIM_reference_type vim_ref = params::choose_parameter(params::get_parameter_reference(np, inp::vertex_index), default_value);
CGAL_USE(vim_ref);
// Named parameters used in the package 'Polygon Mesh Processing'
assert(get_parameter(np, CGAL::internal_np::geom_traits).v == 10);
assert(get_parameter(np, CGAL::internal_np::vertex_incident_patches).v == 11);
assert(get_parameter(np, CGAL::internal_np::density_control_factor).v == 12);
assert(get_parameter(np, CGAL::internal_np::use_delaunay_triangulation).v == 13);
assert(get_parameter(np, CGAL::internal_np::use_2d_constrained_delaunay_triangulation).v == 4573);
assert(get_parameter(np, CGAL::internal_np::fairing_continuity).v == 14);
assert(get_parameter(np, CGAL::internal_np::sparse_linear_solver).v == 15);
assert(get_parameter(np, CGAL::internal_np::number_of_relaxation_steps).v == 16);
assert(get_parameter(np, CGAL::internal_np::protect_constraints).v == 17);
assert(get_parameter(np, CGAL::internal_np::relax_constraints).v == 18);
assert(get_parameter(np, CGAL::internal_np::collapse_constraints).v == 43);
assert(get_parameter(np, CGAL::internal_np::vertex_is_constrained).v == 19);
assert(get_parameter(np, CGAL::internal_np::face_patch).v == 20);
assert(get_parameter(np, CGAL::internal_np::random_uniform_sampling).v == 21);
assert(get_parameter(np, CGAL::internal_np::grid_sampling).v == 22);
assert(get_parameter(np, CGAL::internal_np::monte_carlo_sampling).v == 23);
assert(get_parameter(np, CGAL::internal_np::do_sample_edges).v == 24);
assert(get_parameter(np, CGAL::internal_np::do_sample_vertices).v == 25);
assert(get_parameter(np, CGAL::internal_np::do_sample_faces).v == 26);
assert(get_parameter(np, CGAL::internal_np::number_of_points_on_faces).v == 27);
assert(get_parameter(np, CGAL::internal_np::number_of_points_per_face).v == 28);
assert(get_parameter(np, CGAL::internal_np::grid_spacing).v == 29);
assert(get_parameter(np, CGAL::internal_np::number_of_points_per_edge).v == 30);
assert(get_parameter(np, CGAL::internal_np::number_of_points_on_edges).v == 31);
assert(get_parameter(np, CGAL::internal_np::nb_points_per_area_unit).v == 32);
assert(get_parameter(np, CGAL::internal_np::nb_points_per_distance_unit).v == 33);
assert(get_parameter(np, CGAL::internal_np::throw_on_self_intersection).v == 43);
assert(get_parameter(np, CGAL::internal_np::clip_volume).v == 44);
assert(get_parameter(np, CGAL::internal_np::use_compact_clipper).v == 45);
assert(get_parameter(np, CGAL::internal_np::erase_all_duplicates).v == 48);
assert(get_parameter(np, CGAL::internal_np::require_same_orientation).v == 49);
assert(get_parameter(np, CGAL::internal_np::use_bool_op_to_clip_surface).v == 50);
assert(get_parameter(np, CGAL::internal_np::face_size_map).v == 52);
assert(get_parameter(np, CGAL::internal_np::use_angle_smoothing).v == 53);
assert(get_parameter(np, CGAL::internal_np::use_area_smoothing).v == 54);
assert(get_parameter(np, CGAL::internal_np::use_Delaunay_flips).v == 55);
assert(get_parameter(np, CGAL::internal_np::use_safety_constraints).v == 56);
assert(get_parameter(np, CGAL::internal_np::area_threshold).v == 57);
assert(get_parameter(np, CGAL::internal_np::volume_threshold).v == 58);
assert(get_parameter(np, CGAL::internal_np::snapping_tolerance).v == 59);
assert(get_parameter(np, CGAL::internal_np::dry_run).v == 60);
assert(get_parameter(np, CGAL::internal_np::do_lock_mesh).v == 61);
assert(get_parameter(np, CGAL::internal_np::halfedges_keeper).v == 62);
assert(get_parameter(np, CGAL::internal_np::do_simplify_border).v == 64);
assert(get_parameter(np, CGAL::internal_np::do_not_modify).v == 65);
assert(get_parameter(np, CGAL::internal_np::allow_self_intersections).v == 66);
assert(get_parameter(np, CGAL::internal_np::polyhedral_envelope_epsilon).v == 67);
assert(get_parameter(np, CGAL::internal_np::maximum_number_of_faces).v == 78910);
assert(get_parameter(np, CGAL::internal_np::non_manifold_feature_map).v == 60);
assert(get_parameter(np, CGAL::internal_np::filter).v == 61);
assert(get_parameter(np, CGAL::internal_np::face_epsilon_map).v == 62);
assert(get_parameter(np, CGAL::internal_np::maximum_number).v == 68);
// Named parameters that we use in the package 'Surface Mesh Simplification'
assert(get_parameter(np, CGAL::internal_np::get_cost_policy).v == 34);
assert(get_parameter(np, CGAL::internal_np::get_placement_policy).v == 35);
// Named parameters that we use in the package 'Optimal_bounding_box'
assert(get_parameter(np, CGAL::internal_np::use_convex_hull).v == 63);
// To-be-documented named parameters
assert(get_parameter(np, CGAL::internal_np::face_normal).v == 36);
assert(get_parameter(np, CGAL::internal_np::random_seed).v == 37);
assert(get_parameter(np, CGAL::internal_np::do_project).v == 38);
// Internal named parameters
assert(get_parameter(np, CGAL::internal_np::weight_calculator).v == 39);
assert(get_parameter(np, CGAL::internal_np::preserve_genus).v == 40);
assert(get_parameter(np, CGAL::internal_np::verbosity_level).v == 41);
assert(get_parameter(np, CGAL::internal_np::use_binary_mode).v == 51);
assert(get_parameter(np, CGAL::internal_np::projection_functor).v == 42);
assert(get_parameter(np, CGAL::internal_np::apply_per_connected_component).v == 46);
assert(get_parameter(np, CGAL::internal_np::output_iterator).v == 47);
// Test types
// Named parameters that we use in CGAL
check_same_type<0>(get_parameter(np, CGAL::internal_np::vertex_index));
check_same_type<1>(get_parameter(np, CGAL::internal_np::visitor));
check_same_type<2>(get_parameter(np, CGAL::internal_np::vertex_point));
check_same_type<3>(get_parameter(np, CGAL::internal_np::halfedge_index));
check_same_type<4>(get_parameter(np, CGAL::internal_np::edge_index));
check_same_type<5>(get_parameter(np, CGAL::internal_np::face_index));
check_same_type<6>(get_parameter(np, CGAL::internal_np::edge_is_constrained));
check_same_type<7>(get_parameter(np, CGAL::internal_np::first_index));
check_same_type<8>(get_parameter(np, CGAL::internal_np::number_of_iterations));
check_same_type<800000001>(get_parameter(np, CGAL::internal_np::METIS_options));
check_same_type<800000002>(get_parameter(np, CGAL::internal_np::vertex_partition_id));
check_same_type<800000003>(get_parameter(np, CGAL::internal_np::face_partition_id));
check_same_type<800000004>(get_parameter(np, CGAL::internal_np::vertex_to_vertex_output_iterator));
check_same_type<800000005>(get_parameter(np, CGAL::internal_np::halfedge_to_halfedge_output_iterator));
check_same_type<800000006>(get_parameter(np, CGAL::internal_np::face_to_face_output_iterator));
check_same_type<800000007>(get_parameter(np, CGAL::internal_np::vertex_to_vertex_map));
check_same_type<800000008>(get_parameter(np, CGAL::internal_np::halfedge_to_halfedge_map));
check_same_type<800000009>(get_parameter(np, CGAL::internal_np::face_to_face_map));
check_same_type<800000010>(get_parameter(np, CGAL::internal_np::implementation_tag));
check_same_type<800000011>(get_parameter(np, CGAL::internal_np::prevent_unselection));
check_same_type<800000012>(get_parameter(np, CGAL::internal_np::stream_precision));
// Named parameters that we use in the package 'Mesh_3'
check_same_type<9>(get_parameter(np, CGAL::internal_np::vertex_feature_degree));
// Named parameters used in the package 'Polygon Mesh Processing'
check_same_type<10>(get_parameter(np, CGAL::internal_np::geom_traits));
check_same_type<11>(get_parameter(np, CGAL::internal_np::vertex_incident_patches));
check_same_type<12>(get_parameter(np, CGAL::internal_np::density_control_factor));
check_same_type<13>(get_parameter(np, CGAL::internal_np::use_delaunay_triangulation));
check_same_type<4573>(get_parameter(np, CGAL::internal_np::use_2d_constrained_delaunay_triangulation));
check_same_type<14>(get_parameter(np, CGAL::internal_np::fairing_continuity));
check_same_type<15>(get_parameter(np, CGAL::internal_np::sparse_linear_solver));
check_same_type<16>(get_parameter(np, CGAL::internal_np::number_of_relaxation_steps));
check_same_type<17>(get_parameter(np, CGAL::internal_np::protect_constraints));
check_same_type<18>(get_parameter(np, CGAL::internal_np::relax_constraints));
check_same_type<43>(get_parameter(np, CGAL::internal_np::collapse_constraints));
check_same_type<19>(get_parameter(np, CGAL::internal_np::vertex_is_constrained));
check_same_type<20>(get_parameter(np, CGAL::internal_np::face_patch));
check_same_type<21>(get_parameter(np, CGAL::internal_np::random_uniform_sampling));
check_same_type<22>(get_parameter(np, CGAL::internal_np::grid_sampling));
check_same_type<23>(get_parameter(np, CGAL::internal_np::monte_carlo_sampling));
check_same_type<24>(get_parameter(np, CGAL::internal_np::do_sample_edges));
check_same_type<25>(get_parameter(np, CGAL::internal_np::do_sample_vertices));
check_same_type<26>(get_parameter(np, CGAL::internal_np::do_sample_faces));
check_same_type<27>(get_parameter(np, CGAL::internal_np::number_of_points_on_faces));
check_same_type<28>(get_parameter(np, CGAL::internal_np::number_of_points_per_face));
check_same_type<29>(get_parameter(np, CGAL::internal_np::grid_spacing));
check_same_type<30>(get_parameter(np, CGAL::internal_np::number_of_points_per_edge));
check_same_type<31>(get_parameter(np, CGAL::internal_np::number_of_points_on_edges));
check_same_type<32>(get_parameter(np, CGAL::internal_np::nb_points_per_area_unit));
check_same_type<33>(get_parameter(np, CGAL::internal_np::nb_points_per_distance_unit));
check_same_type<43>(get_parameter(np, CGAL::internal_np::throw_on_self_intersection));
check_same_type<44>(get_parameter(np, CGAL::internal_np::clip_volume));
check_same_type<45>(get_parameter(np, CGAL::internal_np::use_compact_clipper));
check_same_type<48>(get_parameter(np, CGAL::internal_np::erase_all_duplicates));
check_same_type<49>(get_parameter(np, CGAL::internal_np::require_same_orientation));
check_same_type<50>(get_parameter(np, CGAL::internal_np::use_bool_op_to_clip_surface));
check_same_type<52>(get_parameter(np, CGAL::internal_np::face_size_map));
check_same_type<53>(get_parameter(np, CGAL::internal_np::use_angle_smoothing));
check_same_type<54>(get_parameter(np, CGAL::internal_np::use_area_smoothing));
check_same_type<55>(get_parameter(np, CGAL::internal_np::use_Delaunay_flips));
check_same_type<56>(get_parameter(np, CGAL::internal_np::use_safety_constraints));
check_same_type<65>(get_parameter(np, CGAL::internal_np::do_not_modify));
check_same_type<66>(get_parameter(np, CGAL::internal_np::allow_self_intersections));
check_same_type<67>(get_parameter(np, CGAL::internal_np::polyhedral_envelope_epsilon));
check_same_type<12340>(get_parameter(np, CGAL::internal_np::do_self_intersection_tests));
check_same_type<12341>(get_parameter(np, CGAL::internal_np::do_orientation_tests));
check_same_type<12342>(get_parameter(np, CGAL::internal_np::error_codes));
check_same_type<12343>(get_parameter(np, CGAL::internal_np::volume_inclusions));
check_same_type<12344>(get_parameter(np, CGAL::internal_np::face_connected_component_map));
check_same_type<12345>(get_parameter(np, CGAL::internal_np::connected_component_id_to_volume_id));
check_same_type<12346>(get_parameter(np, CGAL::internal_np::is_cc_outward_oriented));
check_same_type<12347>(get_parameter(np, CGAL::internal_np::intersecting_volume_pairs_output_iterator));
check_same_type<12348>(get_parameter(np, CGAL::internal_np::i_used_as_a_predicate));
check_same_type<12349>(get_parameter(np, CGAL::internal_np::nesting_levels));
check_same_type<12350>(get_parameter(np, CGAL::internal_np::i_used_for_volume_orientation));
check_same_type<57>(get_parameter(np, CGAL::internal_np::area_threshold));
check_same_type<58>(get_parameter(np, CGAL::internal_np::volume_threshold));
check_same_type<59>(get_parameter(np, CGAL::internal_np::snapping_tolerance));
check_same_type<60>(get_parameter(np, CGAL::internal_np::dry_run));
check_same_type<61>(get_parameter(np, CGAL::internal_np::do_lock_mesh));
check_same_type<62>(get_parameter(np, CGAL::internal_np::halfedges_keeper));
check_same_type<64>(get_parameter(np, CGAL::internal_np::do_simplify_border));
check_same_type<78910>(get_parameter(np, CGAL::internal_np::maximum_number_of_faces));
check_same_type<60>(get_parameter(np, CGAL::internal_np::non_manifold_feature_map));
check_same_type<61>(get_parameter(np, CGAL::internal_np::filter));
check_same_type<62>(get_parameter(np, CGAL::internal_np::face_epsilon_map));
check_same_type<68>(get_parameter(np, CGAL::internal_np::maximum_number));
// Named parameters that we use in the package 'Surface Mesh Simplification'
check_same_type<34>(get_parameter(np, CGAL::internal_np::get_cost_policy));
check_same_type<35>(get_parameter(np, CGAL::internal_np::get_placement_policy));
// Named parameters that we use in the package 'Optimal_bounding_box'
check_same_type<63>(get_parameter(np, CGAL::internal_np::use_convex_hull));
// To-be-documented named parameters
check_same_type<36>(get_parameter(np, CGAL::internal_np::face_normal));
check_same_type<37>(get_parameter(np, CGAL::internal_np::random_seed));
check_same_type<38>(get_parameter(np, CGAL::internal_np::do_project));
check_same_type<456>(get_parameter(np, CGAL::internal_np::algorithm));
// Internal named parameters
check_same_type<39>(get_parameter(np, CGAL::internal_np::weight_calculator));
check_same_type<40>(get_parameter(np, CGAL::internal_np::preserve_genus));
check_same_type<41>(get_parameter(np, CGAL::internal_np::verbosity_level));
check_same_type<51>(get_parameter(np, CGAL::internal_np::use_binary_mode));
check_same_type<42>(get_parameter(np, CGAL::internal_np::projection_functor));
check_same_type<46>(get_parameter(np, CGAL::internal_np::apply_per_connected_component));
check_same_type<47>(get_parameter(np, CGAL::internal_np::output_iterator));
// Named parameters used in the package 'Point Set Processing'
check_same_type<9000>(get_parameter(np, CGAL::internal_np::point_map));
check_same_type<9001>(get_parameter(np, CGAL::internal_np::query_point_map));
check_same_type<9002>(get_parameter(np, CGAL::internal_np::normal_map));
check_same_type<9003>(get_parameter(np, CGAL::internal_np::diagonalize_traits));
check_same_type<9004>(get_parameter(np, CGAL::internal_np::svd_traits));
check_same_type<9005>(get_parameter(np, CGAL::internal_np::callback));
check_same_type<9006>(get_parameter(np, CGAL::internal_np::sharpness_angle));
check_same_type<9007>(get_parameter(np, CGAL::internal_np::edge_sensitivity));
check_same_type<9008>(get_parameter(np, CGAL::internal_np::neighbor_radius));
check_same_type<9009>(get_parameter(np, CGAL::internal_np::number_of_output_points));
check_same_type<9010>(get_parameter(np, CGAL::internal_np::size));
check_same_type<9011>(get_parameter(np, CGAL::internal_np::maximum_variation));
check_same_type<9012>(get_parameter(np, CGAL::internal_np::degree_fitting));
check_same_type<9013>(get_parameter(np, CGAL::internal_np::degree_monge));
check_same_type<9014>(get_parameter(np, CGAL::internal_np::threshold_percent));
check_same_type<9015>(get_parameter(np, CGAL::internal_np::threshold_distance));
check_same_type<9016>(get_parameter(np, CGAL::internal_np::attraction_factor));
check_same_type<9017>(get_parameter(np, CGAL::internal_np::plane_map));
check_same_type<9018>(get_parameter(np, CGAL::internal_np::plane_index_map));
check_same_type<9019>(get_parameter(np, CGAL::internal_np::select_percentage));
check_same_type<9020>(get_parameter(np, CGAL::internal_np::require_uniform_sampling));
check_same_type<9021>(get_parameter(np, CGAL::internal_np::point_is_constrained));
check_same_type<9022>(get_parameter(np, CGAL::internal_np::number_of_samples));
check_same_type<9023>(get_parameter(np, CGAL::internal_np::accuracy));
check_same_type<9024>(get_parameter(np, CGAL::internal_np::maximum_running_time));
check_same_type<9025>(get_parameter(np, CGAL::internal_np::overlap));
check_same_type<9026>(get_parameter(np, CGAL::internal_np::transformation));
check_same_type<9027>(get_parameter(np, CGAL::internal_np::point_set_filters));
check_same_type<9028>(get_parameter(np, CGAL::internal_np::matcher));
check_same_type<9029>(get_parameter(np, CGAL::internal_np::outlier_filters));
check_same_type<9030>(get_parameter(np, CGAL::internal_np::error_minimizer));
check_same_type<9031>(get_parameter(np, CGAL::internal_np::transformation_checkers));
check_same_type<9032>(get_parameter(np, CGAL::internal_np::inspector));
check_same_type<9033>(get_parameter(np, CGAL::internal_np::logger));
check_same_type<9034>(get_parameter(np, CGAL::internal_np::maximum_normal_deviation));
check_same_type<9035>(get_parameter(np, CGAL::internal_np::scan_angle_map));
check_same_type<9036>(get_parameter(np, CGAL::internal_np::scanline_id_map));
// default
typedef typename inp::Lookup_named_param_def<inp::edge_index_t, NamedParameters, Default_type>::reference EIM_reference_type;
CGAL_static_assertion(( std::is_same<Default_type&, EIM_reference_type>::value) );
EIM_reference_type eim_ref = params::choose_parameter(params::get_parameter_reference(np, inp::edge_index), default_value);
assert(&eim_ref==&default_value);
}
int main()
{
test(CGAL::parameters::vertex_index_map(A<0>(0))
.visitor(A<1>(1))
.vertex_point_map(A<2>(2))
.halfedge_index_map(A<3>(3))
.edge_index_map(A<4>(4))
.face_index_map(A<5>(5))
.edge_is_constrained_map(A<6>(6))
.first_index(A<7>(7))
.number_of_iterations(A<8>(8))
.METIS_options(A<800000001>(800000001))
.vertex_partition_id_map(A<800000002>(800000002))
.face_partition_id_map(A<800000003>(800000003))
.vertex_to_vertex_output_iterator(A<800000004>(800000004))
.halfedge_to_halfedge_output_iterator(A<800000005>(800000005))
.face_to_face_output_iterator(A<800000006>(800000006))
.vertex_to_vertex_map(A<800000007>(800000007))
.halfedge_to_halfedge_map(A<800000008>(800000008))
.face_to_face_map(A<800000009>(800000009))
.implementation_tag(A<800000010>(800000010))
.prevent_unselection(A<800000011>(800000011))
.stream_precision(A<800000012>(800000012))
.vertex_feature_degree_map(A<9>(9))
.geom_traits(A<10>(10))
.vertex_incident_patches_map(A<11>(11))
.density_control_factor(A<12>(12))
.use_delaunay_triangulation(A<13>(13))
.use_2d_constrained_delaunay_triangulation(A<4573>(4573))
.fairing_continuity(A<14>(14))
.sparse_linear_solver(A<15>(15))
.number_of_relaxation_steps(A<16>(16))
.protect_constraints(A<17>(17))
.relax_constraints(A<18>(18))
.collapse_constraints(A<43>(43))
.vertex_is_constrained_map(A<19>(19))
.face_patch_map(A<20>(20))
.use_random_uniform_sampling(A<21>(21))
.use_grid_sampling(A<22>(22))
.use_monte_carlo_sampling(A<23>(23))
.do_sample_edges(A<24>(24))
.do_sample_vertices(A<25>(25))
.do_sample_faces(A<26>(26))
.number_of_points_on_faces(A<27>(27))
.number_of_points_per_face(A<28>(28))
.grid_spacing(A<29>(29))
.number_of_points_per_edge(A<30>(30))
.number_of_points_on_edges(A<31>(31))
.number_of_points_per_area_unit(A<32>(32))
.number_of_points_per_distance_unit(A<33>(33))
.get_cost(A<34>(34))
.get_placement(A<35>(35))
.face_normal_map(A<36>(36))
.random_seed(A<37>(37))
.do_project(A<38>(38))
.algorithm(A<456>(456))
.weight_calculator(A<39>(39))
.preserve_genus(A<40>(40))
.verbosity_level(A<41>(41))
.projection_functor(A<42>(42))
.throw_on_self_intersection(A<43>(43))
.clip_volume(A<44>(44))
.use_compact_clipper(A<45>(45))
.non_manifold_feature_map(A<60>(60))
.filter(A<61>(61))
.face_epsilon_map(A<62>(62))
.maximum_number(A<68>(68))
.apply_per_connected_component(A<46>(46))
.output_iterator(A<47>(47))
.erase_all_duplicates(A<48>(48))
.require_same_orientation(A<49>(49))
.use_bool_op_to_clip_surface(A<50>(50))
.use_binary_mode(A<51>(51))
.face_size_map(A<52>(52))
.use_angle_smoothing(A<53>(53))
.use_area_smoothing(A<54>(54))
.use_Delaunay_flips(A<55>(55))
.use_safety_constraints(A<56>(56))
.do_self_intersection_tests(A<12340>(12340))
.do_orientation_tests(A<12341>(12341))
.error_codes(A<12342>(12342))
.volume_inclusions(A<12343>(12343))
.face_connected_component_map(A<12344>(12344))
.connected_component_id_to_volume_id(A<12345>(12345))
.is_cc_outward_oriented(A<12346>(12346))
.intersecting_volume_pairs_output_iterator(A<12347>(12347))
.i_used_as_a_predicate(A<12348>(12348))
.nesting_levels(A<12349>(12349))
.i_used_for_volume_orientation(A<12350>(12350))
.area_threshold(A<57>(57))
.volume_threshold(A<58>(58))
.snapping_tolerance(A<59>(59))
.dry_run(A<60>(60))
.do_lock_mesh(A<61>(61))
.halfedges_keeper(A<62>(62))
.use_convex_hull(A<63>(63))
.do_simplify_border(A<64>(64))
.do_not_modify(A<65>(65))
.allow_self_intersections(A<66>(66))
.polyhedral_envelope_epsilon(A<67>(67))
.point_map(A<9000>(9000))
.query_point_map(A<9001>(9001))
.normal_map(A<9002>(9002))
.diagonalize_traits(A<9003>(9003))
.svd_traits(A<9004>(9004))
.callback(A<9005>(9005))
.sharpness_angle(A<9006>(9006))
.edge_sensitivity(A<9007>(9007))
.neighbor_radius(A<9008>(9008))
.number_of_output_points(A<9009>(9009))
.size(A<9010>(9010))
.maximum_variation(A<9011>(9011))
.degree_fitting(A<9012>(9012))
.degree_monge(A<9013>(9013))
.threshold_percent(A<9014>(9014))
.threshold_distance(A<9015>(9015))
.attraction_factor(A<9016>(9016))
.plane_map(A<9017>(9017))
.plane_index_map(A<9018>(9018))
.select_percentage(A<9019>(9019))
.require_uniform_sampling(A<9020>(9020))
.point_is_constrained_map(A<9021>(9021))
.number_of_samples(A<9022>(9022))
.accuracy(A<9023>(9023))
.maximum_running_time(A<9024>(9024))
.overlap(A<9025>(9025))
.transformation(A<9026>(9026))
.point_set_filters(A<9027>(9027))
.matcher(A<9028>(9028))
.outlier_filters(A<9029>(9029))
.error_minimizer(A<9030>(9030))
.transformation_checkers(A<9031>(9031))
.inspector(A<9032>(9032))
.logger(A<9033>(9033))
.maximum_normal_deviation(A<9034>(9034))
.scan_angle_map(A<9035>(9035))
.scanline_id_map(A<9036>(9036))
.maximum_number_of_faces(A<78910>(78910))
);
test_values_and_types(params::vertex_index_map(A<0>(0)).visitor(A<1>(1)));
B b;
test_no_copyable(params::visitor(b));
test_references(params::visitor(std::ref(b))
.vertex_point_map(b)
.vertex_index_map(A<0>(0))
.face_index_map(std::reference_wrapper<const B>(b))
);
return EXIT_SUCCESS;
}

View File

@ -32,6 +32,8 @@ namespace CGAL {
// Barycentric coordinates namespace.
namespace Barycentric_coordinates {
#if !defined(CGAL_NO_DEPRECATED_CODE) || defined(DOXYGEN_RUNNING)
// Examples: see the User Manual here - https://doc.cgal.org/latest/Manual/index.html.
// [1] Reference: "M. S. Floater, K. Hormann, and G. Kos. A general construction of barycentric coordinates over convex polygons. Advances in Computational Mathematics, 24(1-4):311-331, 2006.".
@ -430,6 +432,8 @@ private:
}
};
#endif // CGAL_NO_DEPRECATED_CODE
} // namespace Barycentric_coordinates
} // namespace CGAL

View File

@ -32,6 +32,8 @@ namespace CGAL {
// Barycentric coordinates namespace.
namespace Barycentric_coordinates {
#if !defined(CGAL_NO_DEPRECATED_CODE) || defined(DOXYGEN_RUNNING)
// Examples: see the User Manual here - https://doc.cgal.org/latest/Manual/index.html.
/*!
@ -585,6 +587,8 @@ private:
}
};
#endif // CGAL_NO_DEPRECATED_CODE
} // namespace Barycentric_coordinates
} // namespace CGAL

View File

@ -37,6 +37,8 @@ namespace CGAL {
// Barycentric coordinates namespace.
namespace Barycentric_coordinates {
#if !defined(CGAL_NO_DEPRECATED_CODE) || defined(DOXYGEN_RUNNING)
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Try to find a square root object in the provided `Traits` class. If not, then use the default square root from CGAL.
@ -498,6 +500,8 @@ private:
}
};
#endif // CGAL_NO_DEPRECATED_CODE
} // namespace Barycentric_coordinates
} // namespace CGAL

View File

@ -32,6 +32,8 @@ namespace CGAL {
// Barycentric coordinates namespace.
namespace Barycentric_coordinates {
#if !defined(CGAL_NO_DEPRECATED_CODE) || defined(DOXYGEN_RUNNING)
// Examples: see the User Manual here - https://doc.cgal.org/latest/Manual/index.html.
// [1] Reference: "M. S. Floater, K. Hormann, and G. Kos. A general construction of barycentric coordinates over convex polygons. Advances in Computational Mathematics, 24(1-4):311-331, 2006.".
@ -413,6 +415,8 @@ private:
}
};
#endif // CGAL_NO_DEPRECATED_CODE
} // namespace Barycentric_coordinates
} // namespace CGAL

View File

@ -73,6 +73,8 @@ enum class Computation_policy_2 {
namespace CGAL {
namespace Barycentric_coordinates {
#if !defined(CGAL_NO_DEPRECATED_CODE) || defined(DOXYGEN_RUNNING)
/// \name Locations of a Query Point
/// @{
@ -142,6 +144,8 @@ enum Type_of_polygon {
/// \endcond
#endif // CGAL_NO_DEPRECATED_CODE
} // namespace Barycentric_coordinates
} // namespace CGAL

View File

@ -172,6 +172,8 @@ namespace Barycentric_coordinates {
namespace CGAL {
namespace Barycentric_coordinates {
#if !defined(CGAL_NO_DEPRECATED_CODE) || defined(DOXYGEN_RUNNING)
/*!
\ingroup PkgBarycentricCoordinates2RefDeprecated
* The class `Segment_coordinates_2` implements barycentric coordinates with respect to an arbitrary non-degenerate segment along an arbitrary line in the plane.
@ -376,6 +378,8 @@ namespace Barycentric_coordinates {
return CGAL::make_array(b_first, FT(1) - b_first);
}
#endif // CGAL_NO_DEPRECATED_CODE
} // namespace Barycentric_coordinates
} // namespace CGAL

View File

@ -182,6 +182,8 @@ namespace Barycentric_coordinates {
namespace CGAL {
namespace Barycentric_coordinates {
#if !defined(CGAL_NO_DEPRECATED_CODE) || defined(DOXYGEN_RUNNING)
/*!
* \ingroup PkgBarycentricCoordinates2RefDeprecated
* The class `Triangle_coordinates_2` implements barycentric coordinates ( <a href="https://mathworld.wolfram.com/BarycentricCoordinates.html" target=blanc>[1]</a>,
@ -413,6 +415,8 @@ namespace Barycentric_coordinates {
return CGAL::make_array(b_first, b_second, FT(1) - b_first - b_second);
}
#endif // CGAL_NO_DEPRECATED_CODE
} // namespace Barycentric_coordinates
} // namespace CGAL

View File

@ -1,5 +1,3 @@
#include <cmath>
#include <cassert>
#include <CGAL/Installation/internal/disable_deprecation_warnings_and_errors.h>
#include <CGAL/Exact_predicates_exact_constructions_kernel.h>
#include <CGAL/Barycentric_coordinates_2/triangle_coordinates_2.h>

View File

@ -1,7 +1,3 @@
// #define HMC_SparseLU
// #define HMC_SimplicialLLT
// #define HMC_SimplicialLDLT // default
#include <CGAL/Simple_cartesian.h>
#include <CGAL/Barycentric_coordinates_2/Delaunay_domain_2.h>
#include <CGAL/Barycentric_coordinates_2/Harmonic_coordinates_2.h>

View File

@ -1,7 +1,3 @@
// #define HMC_SparseLU
// #define HMC_SimplicialLLT
// #define HMC_SimplicialLDLT // default
#include <CGAL/Exact_predicates_inexact_constructions_kernel.h>
#include <CGAL/Barycentric_coordinates_2/Delaunay_domain_2.h>
#include <CGAL/Barycentric_coordinates_2/Harmonic_coordinates_2.h>

View File

@ -1,7 +1,3 @@
// #define HMC_SparseLU
// #define HMC_SimplicialLLT
// #define HMC_SimplicialLDLT // default
#include <CGAL/Exact_predicates_inexact_constructions_kernel.h>
#include <CGAL/Barycentric_coordinates_2/Delaunay_domain_2.h>
#include <CGAL/Barycentric_coordinates_2/Harmonic_coordinates_2.h>

View File

@ -1,5 +1,3 @@
#include <cmath>
#include <cassert>
#include <CGAL/Installation/internal/disable_deprecation_warnings_and_errors.h>
#include <CGAL/Exact_predicates_inexact_constructions_kernel.h>
#include <CGAL/Barycentric_coordinates_2/triangle_coordinates_2.h>

View File

@ -1,5 +1,3 @@
#include <cmath>
#include <cassert>
#include <CGAL/Installation/internal/disable_deprecation_warnings_and_errors.h>
#include <CGAL/Exact_predicates_exact_constructions_kernel.h>
#include <CGAL/Barycentric_coordinates_2/segment_coordinates_2.h>

View File

@ -1,5 +1,3 @@
#include <cmath>
#include <cassert>
#include <CGAL/Installation/internal/disable_deprecation_warnings_and_errors.h>
#include <CGAL/Exact_predicates_exact_constructions_kernel.h>
#include <CGAL/Barycentric_coordinates_2/triangle_coordinates_2.h>

View File

@ -1,5 +1,3 @@
#include <cmath>
#include <cassert>
#include <CGAL/Installation/internal/disable_deprecation_warnings_and_errors.h>
#include <CGAL/Exact_predicates_exact_constructions_kernel.h>
#include <CGAL/Barycentric_coordinates_2/Wachspress_2.h>

View File

@ -39,6 +39,7 @@
#include <CGAL/disable_warnings.h>
#include <string>
#include <ctype.h>
#include <CGAL/CORE/BigFloat.h>
#include <CGAL/CORE/Expr.h>
@ -1057,8 +1058,8 @@ void BigFloatRep :: fromString(const char *str, extLong prec ) {
CGAL_INLINE_FUNCTION
std::istream& BigFloatRep :: operator >>(std::istream& i) {
int size = 20;
char *str = new char[size];
char *p = str;
std::string str;
str.reserve(size);
char c;
int d = 0, e = 0, s = 0;
// d=1 means dot is found
@ -1084,7 +1085,7 @@ std::istream& BigFloatRep :: operator >>(std::istream& i) {
// the current content in "c" should be the first non-whitespace char
if (c == '-' || c == '+') {
*p++ = c;
str += c;
i.get(c);
}
@ -1096,19 +1097,8 @@ std::istream& BigFloatRep :: operator >>(std::istream& i) {
// xxxx.xxxe+xxx.xxx:
if (e && (c == '.'))
break;
if (p - str == size) {
char *t = str;
str = new char[size*2];
memcpy(str, t, size);
delete [] t;
p = str + size;
size *= 2;
}
#ifdef CGAL_CORE_DEBUG
CGAL_assertion((p-str) < size);
#endif
*p++ = c;
str += c;
if (c == '.')
d = 1;
// Chen Li: fix a bug -- the sign of exponent can not happen before
@ -1120,24 +1110,8 @@ std::istream& BigFloatRep :: operator >>(std::istream& i) {
e = 1;
}
// chenli: make sure that the p is still in the range
if (p - str >= size) {
std::size_t len = p - str;
char *t = str;
str = new char[len + 1];
memcpy(str, t, len);
delete [] t;
p = str + len;
}
#ifdef CGAL_CORE_DEBUG
CGAL_assertion(p - str < size);
#endif
*p = '\0';
i.putback(c);
fromString(str);
delete [] str;
fromString(str.c_str());
return i;
}//operator >>

View File

@ -139,27 +139,6 @@ long gcd(long m, long n) {
return p;
}
// char* core_itoa(int n, char* buffer, int buffer_size)
// returns a pointer to the null-terminated string in buffer
// NOTES:
// 0. Buffer size should be 17 bytes (resp., 33 bytes, 65 bytes) on 16-bit
// (resp., 32-bit, 64-bit) machines. Formula: 1+sizeof(int)*8 bytes.
// 1. itoa(...) is available on some stdlib.h, but it is
// not defined by ANSI-C and so not all compilers support it.
// 2. Our use of sprintf(...) to do the job is known to
// be inefficient, but this is hardly critical for our usage.
// 3. A more general program should take a 3rd argument (the radix of
// output number). We assume radix 10.
CGAL_INLINE_FUNCTION
char * core_itoa(int n, char* buffer, int buffer_size) {
#if defined(_MSC_VER)
sprintf_s(buffer, buffer_size, "%d", n);
#else
CGAL_USE(buffer_size);
std::sprintf(buffer, "%d", n);
#endif
return buffer;
}
/// implements the "integer mantissa" function
// (See CORE_PATH/progs/ieee/frexp.cpp for details)
@ -197,11 +176,8 @@ void core_error(std::string msg, std::string file, int lineno, bool err) {
<< msg << std::endl;
outFile.close();
if (err) {
char buf[65];
// perror((std::string("CORE ERROR") + " (file " + file + ", line "
// + core_itoa(lineno,buf, 65) +"):" + msg + "\n").c_str());
std::cerr << (std::string("CORE ERROR") + " (file " + file + ", line "
+ core_itoa(lineno,buf, 65) +"):" + msg + "\n").c_str();
+ std::to_string(lineno) +"):" + msg + "\n").c_str();
std::exit(1); //Note: do not call abort()
}
}

View File

@ -33,6 +33,7 @@
#include <CGAL/disable_warnings.h>
#include <string>
#include <ctype.h>
#include <CGAL/CORE/Real.h>
#include <CGAL/tss.h>
@ -189,8 +190,9 @@ void Real::constructFromString(const char *str, const extLong& prec )
CGAL_INLINE_FUNCTION
std::istream& operator >>(std::istream& i, Real& x) {
int size = 20;
char *str = new char[size];
char *p = str;
std::string str;
str.reserve(size);
char c;
int d = 0, e = 0, s = 0;
// int done = 0;
@ -211,13 +213,12 @@ std::istream& operator >>(std::istream& i, Real& x) {
if (i.eof()) {
i.clear(std::ios::eofbit | std::ios::failbit);
delete [] str;
return i;
}
// the current content in "c" should be the first non-whitespace char
if (c == '-' || c == '+') {
*p++ = c;
str += c;
i.get(c);
}
@ -230,19 +231,9 @@ std::istream& operator >>(std::istream& i, Real& x) {
// xxxx.xxxe+xxx.xxx:
if (e && (c == '.'))
break;
if (p - str == size) {
char *t = str;
str = new char[size*2];
std::memcpy(str, t, size);
delete [] t;
p = str + size;
size *= 2;
}
#ifdef CORE_DEBUG
CGAL_assertion((p-str) < size);
#endif
*p++ = c;
str += c;
if (c == '.')
d = 1;
// Chen Li: fix a bug -- the sign of exponent can not happen before
@ -255,29 +246,13 @@ std::istream& operator >>(std::istream& i, Real& x) {
}
if (!i && !i.eof()) {
delete [] str;
return i;
}
// chenli: make sure that the p is still in the range
if (p - str >= size) {
std::ptrdiff_t len = p - str;
char *t = str;
str = new char[len + 1];
std::memcpy(str, t, len);
delete [] t;
p = str + len;
}
#ifdef CORE_DEBUG
CGAL_assertion(p - str < size);
#endif
*p = '\0';
i.putback(c);
i.clear();
// old: x = Real(str, i.precision()); // use precision of input stream.
x = Real(str); // default precision = get_static_defInputDigits()
delete [] str;
x = Real(str.c_str()); // default precision = get_static_defInputDigits()
return i;
}//operator >> (std::istream&, Real&)

View File

@ -23,6 +23,8 @@
#include <CGAL/constructions/kernel_ftC2.h>
#include <CGAL/constructions/kernel_ftC3.h>
#include <CGAL/Cartesian/solve_3.h>
#include <CGAL/Distance_3/Point_3_Point_3.h>
#include <CGAL/Distance_3/internal/squared_distance_utils_3.h>
namespace CGAL {
@ -457,6 +459,103 @@ namespace CartesianKernelFunctors {
}
};
namespace internal {
template <class K>
typename K::Comparison_result
compare_distance_pssC3(const typename K::Point_3 &pt,
const typename K::Segment_3 &seg1,
const typename K::Segment_3 &seg2,
const K& k)
{
typedef typename K::Vector_3 Vector_3;
typedef typename K::RT RT;
typedef typename K::FT FT;
typename K::Construct_vector_3 construct_vector;
FT d1=FT(0), d2=FT(0);
RT e1 = RT(1), e2 = RT(1);
// assert that the segment is valid (non zero length).
{
Vector_3 diff = construct_vector(seg1.source(), pt);
Vector_3 segvec = construct_vector(seg1.source(), seg1.target());
RT d = CGAL::internal::wdot(diff,segvec, k);
if (d <= (RT)0){
d1 = (FT(diff*diff));
}else{
RT e = CGAL::internal::wdot(segvec,segvec, k);
if (d > e){
d1 = CGAL::internal::squared_distance(pt, seg1.target(), k);
} else{
Vector_3 wcr = CGAL::internal::wcross(segvec, diff, k);
d1 = FT(wcr*wcr);
e1 = e;
}
}
}
{
Vector_3 diff = construct_vector(seg2.source(), pt);
Vector_3 segvec = construct_vector(seg2.source(), seg2.target());
RT d = CGAL::internal::wdot(diff,segvec, k);
if (d <= (RT)0){
d2 = (FT(diff*diff));
}else{
RT e = CGAL::internal::wdot(segvec,segvec, k);
if (d > e){
d2 = CGAL::internal::squared_distance(pt, seg2.target(), k);
} else{
Vector_3 wcr = CGAL::internal::wcross(segvec, diff, k);
d2 = FT(wcr*wcr);
e2 = e;
}
}
}
return CGAL::compare(d1*e2, d2*e1);
}
template <class K>
typename K::Comparison_result
compare_distance_ppsC3(const typename K::Point_3 &pt,
const typename K::Point_3 &pt2,
const typename K::Segment_3 &seg,
const K& k)
{
typedef typename K::Vector_3 Vector_3;
typedef typename K::RT RT;
typedef typename K::FT FT;
typename K::Construct_vector_3 construct_vector;
RT e2 = RT(1);
// assert that the segment is valid (non zero length).
FT d1 = CGAL::internal::squared_distance(pt, pt2, k);
FT d2 = FT(0);
{
Vector_3 diff = construct_vector(seg.source(), pt);
Vector_3 segvec = construct_vector(seg.source(), seg.target());
RT d = CGAL::internal::wdot(diff,segvec, k);
if (d <= (RT)0){
d2 = (FT(diff*diff));
}else{
RT e = CGAL::internal::wdot(segvec,segvec, k);
if (d > e){
d2 = CGAL::internal::squared_distance(pt, seg.target(), k);
} else{
Vector_3 wcr = CGAL::internal::wcross(segvec, diff, k);
d2 = FT(wcr*wcr);
e2 = e;
}
}
}
return CGAL::compare(d1*e2, d2);
}
} // namespace internal
template <typename K>
class Compare_distance_3
{
@ -476,19 +575,19 @@ namespace CartesianKernelFunctors {
result_type
operator()(const Point_3& p1, const Segment_3& s1, const Segment_3& s2) const
{
return CGAL::internal::compare_distance_pssC3(p1,s1,s2, K());
return internal::compare_distance_pssC3(p1,s1,s2, K());
}
result_type
operator()(const Point_3& p1, const Point_3& p2, const Segment_3& s2) const
{
return CGAL::internal::compare_distance_ppsC3(p1,p2,s2, K());
return internal::compare_distance_ppsC3(p1,p2,s2, K());
}
result_type
operator()(const Point_3& p1, const Segment_3& s2, const Point_3& p2) const
{
return opposite(CGAL::internal::compare_distance_ppsC3(p1,p2,s2, K()));
return opposite(internal::compare_distance_ppsC3(p1,p2,s2, K()));
}
template <class T1, class T2, class T3>
@ -3242,8 +3341,17 @@ namespace CartesianKernelFunctors {
typedef typename K::Segment_3 Segment_3;
typedef typename K::Ray_3 Ray_3;
typedef typename K::FT FT;
public:
typedef Point_3 result_type;
template<typename>
struct result {
typedef const Point_3 type;
};
template<typename F>
struct result<F(Point_3, Point_3)> {
typedef const Point_3& type;
};
Point_3
operator()( const Line_3& l, const Point_3& p ) const
@ -3270,15 +3378,19 @@ namespace CartesianKernelFunctors {
Point_3
operator()( const Triangle_3& t, const Point_3& p ) const
{ return CommonKernelFunctors::Construct_projected_point_3<K>()(p,t,K()); }
{ return CommonKernelFunctors::Construct_projected_point_3<K>()(t,p,K()); }
Point_3
operator()( const Segment_3& s, const Point_3& p ) const
{ return CommonKernelFunctors::Construct_projected_point_3<K>()(p,s,K()); }
{ return CommonKernelFunctors::Construct_projected_point_3<K>()(s,p,K()); }
Point_3
operator()( const Ray_3& r, const Point_3& p ) const
{ return CommonKernelFunctors::Construct_projected_point_3<K>()(p,r,K()); }
{ return CommonKernelFunctors::Construct_projected_point_3<K>()(r,p,K()); }
const Point_3&
operator()( const Point_3& p, const Point_3& q) const
{ return CommonKernelFunctors::Construct_projected_point_3<K>()(p,q,K()); }
};
template <class K>

View File

@ -1 +0,0 @@
4 data/n9.cin

View File

@ -26,26 +26,37 @@ typedef boost::adjacency_list<boost::listS,
int main(int argc, char ** argv)
{
if (argc < 3) {
unsigned int k=4; // By default, no. of cones==4
std::string filename="data/n9.cin"; // file used by default
if (argc > 1 &&
(!strcmp(argv[1],"-h") || !strcmp(argv[1],"--help") || !strcmp(argv[1],"-?")))
{
std::cout << "Usage: " << argv[0] << " <no. of cones> <input filename> [<direction-x> <direction-y>]" << std::endl;
return 1;
}
unsigned int k = atoi(argv[1]);
if (k<2) {
std::cout << "The number of cones should be larger than 1!" << std::endl;
return 1;
if (argc > 1)
{
k = atoi(argv[1]);
if (k<2) {
std::cout << "The number of cones should be larger than 1!" << std::endl;
return 1;
}
}
if (argc > 2)
{ filename=std::string(argv[2]); }
// open the file containing the vertex list
std::ifstream inf(argv[2]);
std::ifstream inf(filename);
if (!inf) {
std::cout << "Cannot open file " << argv[2] << "!" << std::endl;
std::cout << "Cannot open file " << filename << "!" << std::endl;
return 1;
}
Direction_2 initial_direction;
if (argc == 3)
if (argc == 1 || argc == 3)
initial_direction = Direction_2(1, 0); // default initial_direction
else if (argc == 5)
initial_direction = Direction_2(atof(argv[3]), atof(argv[4]));

View File

@ -20,7 +20,7 @@
#include <CGAL/license/Cone_spanners_2.h>
#include <array>
#include <stdexcept>
namespace CGAL {
@ -134,9 +134,8 @@ public:
_Leaf (const key_compare& less, const value_compare& vless, tree_type *const t,
_leaf_type *const prev = nullptr,
_leaf_type *const next = nullptr)
: _node_type (less, vless, t), prev (prev), next (next) {
std::memset (values, 0, 2*sizeof(value_type*));
}
: _node_type (less, vless, t), values({nullptr,nullptr}), prev (prev), next (next)
{}
/* Destructor.
* Frees memory used for storing key-value pair, thus invalidating any
@ -242,7 +241,7 @@ protected:
private:
/* Key-value pairs */
value_type* values[2];
std::array<value_type*,2> values;
/* Linked list structure of the B+ tree */
_leaf_type* prev;
@ -268,11 +267,8 @@ public:
typedef typename _node_type::tree_type tree_type;
_Internal (const Comp& less, const VComp& vless, tree_type *const t)
: _node_type(less, vless, t) {
std::memset (keys, 0, 2*sizeof(key_type*));
std::memset (children, 0, 3*sizeof(_node_type*));
std::memset (vMin, 0, 3*sizeof(mapped_type*));
}
: _node_type(less, vless, t), keys({nullptr, nullptr}), children({nullptr, nullptr, nullptr}), vMin({nullptr, nullptr, nullptr})
{}
virtual ~_Internal() {
keys[0] = nullptr;
@ -492,9 +488,9 @@ protected:
}
private:
const key_type* keys[2];
_node_type* children[3];
const mapped_type* vMin[3];
std::array<const key_type*, 2> keys;
std::array< _node_type*, 3> children;
std::array<const mapped_type*, 3> vMin;
};
template <typename Key, typename T, typename Comp, typename VComp >

View File

@ -212,7 +212,7 @@ template<typename Nef_, typename FTComparison, typename Container>
SNC_point_locator* pl;
public:
Edge_sorter(Container& cin) : c(cin) {}
Edge_sorter(Container& cin) : c(cin), sncp(nullptr), pl(nullptr) {}
void operator()(SNC_and_PL& sncpl) {
sncp = sncpl.sncp;

View File

@ -69,7 +69,8 @@ class Ray_hit_generator2 : public Modifier_base<typename Nef_::SNC_and_PL> {
bool vertex_added;
public:
Ray_hit_generator2(Vector_3 d, Vertex_handle v) : dir(d), vs(v) {}
Ray_hit_generator2(Vector_3 d, Vertex_handle v)
: dir(d), vs(v), sncp(nullptr), pl(nullptr), edge_splitted(false), vertex_added(false) {}
Vertex_handle create_vertex_on_first_hit(const Ray_3& r) {

View File

@ -74,7 +74,7 @@ class Single_wall_creator : public Modifier_base<typename Nef_::SNC_and_PL> {
public:
Single_wall_creator(SVertex_handle e, Vector_3 d)
: ein(e), dir(d)
: ein(e), dir(d), sncp(nullptr), pl(nullptr)
#ifndef CGAL_NEF_NO_INDEXED_ITEMS
, index1(0), index2(0)
#endif

View File

@ -359,6 +359,8 @@ public:
}
}
catch (Uncertain_conversion_exception&){}
Protector protector(CGAL_FE_TONEAREST);
CGAL_expensive_assertion(FPU_get_cw() == CGAL_FE_TONEAREST);
if (ek_plane_ptr==nullptr) {
const typename Exact_K::Point_3 ep = to_EK(p);
ek_plane_ptr = new Vector_plus_point<Exact_K>;

View File

@ -0,0 +1,11 @@
OFF
4 4 0
0.0 0.0 0.0
1.0 0.0 0.0
0.0 1.0 0.0
0.0 0.0 1.0
3 0 1 2
3 0 3 1
3 0 2 3
3 1 3 2

View File

@ -0,0 +1,58 @@
// Copyright (c) 1998-2004
// Utrecht University (The Netherlands),
// ETH Zurich (Switzerland),
// INRIA Sophia-Antipolis (France),
// Max-Planck-Institute Saarbruecken (Germany),
// and Tel-Aviv University (Israel). All rights reserved.
//
// This file is part of CGAL (www.cgal.org)
//
// $URL$
// $Id$
// SPDX-License-Identifier: LGPL-3.0-or-later OR LicenseRef-Commercial
//
//
// Author(s) : Geert-Jan Giezeman
// Michel Hoffmann <hoffmann@inf.ethz.ch>
// Andreas Fabri <Andreas.Fabri@geometryfactory.com>
#ifndef CGAL_DISTANCE_2_LINE_2_LINE_2_H
#define CGAL_DISTANCE_2_LINE_2_LINE_2_H
#include <CGAL/Distance_2/internal/squared_distance_utils_2.h>
#include <CGAL/Kernel/global_functions.h>
#include <CGAL/Line_2.h>
namespace CGAL {
namespace internal {
template <class K>
inline typename K::FT
squared_distance(const typename K::Line_2& line1,
const typename K::Line_2& line2,
const K& k)
{
typedef typename K::FT FT;
typename K::Compute_squared_distance_2 sq_dist = k.compute_squared_distance_2_object();
if(internal::parallel(line1, line2, k))
return sq_dist(line1.point(), line2);
else
return FT(0);
}
} // namespace internal
template <class K>
inline typename K::FT
squared_distance(const Line_2<K>& line1,
const Line_2<K>& line2)
{
return K().compute_squared_distance_2_object()(line1, line2);
}
} // namespace CGAL
#endif // CGAL_DISTANCE_2_LINE_2_LINE_2_H

View File

@ -0,0 +1,89 @@
// Copyright (c) 1998-2004
// Utrecht University (The Netherlands),
// ETH Zurich (Switzerland),
// INRIA Sophia-Antipolis (France),
// Max-Planck-Institute Saarbruecken (Germany),
// and Tel-Aviv University (Israel). All rights reserved.
//
// This file is part of CGAL (www.cgal.org)
//
// $URL$
// $Id$
// SPDX-License-Identifier: LGPL-3.0-or-later OR LicenseRef-Commercial
//
//
// Author(s) : Geert-Jan Giezeman
// Michel Hoffmann <hoffmann@inf.ethz.ch>
// Andreas Fabri <Andreas.Fabri@geometryfactory.com>
#ifndef CGAL_DISTANCE_2_LINE_2_TRIANGLE_2_H
#define CGAL_DISTANCE_2_LINE_2_TRIANGLE_2_H
#include <CGAL/Distance_2/internal/squared_distance_utils_2.h>
#include <CGAL/enum.h>
#include <CGAL/Line_2.h>
#include <CGAL/Triangle_2.h>
namespace CGAL {
namespace internal {
template <class K>
typename K::FT
squared_distance(const typename K::Line_2& line,
const typename K::Triangle_2& triangle,
const K& k)
{
typedef typename K::FT FT;
typename K::Compute_squared_distance_2 sq_dist = k.compute_squared_distance_2_object();
const Oriented_side side0 = line.oriented_side(triangle.vertex(0));
if(line.oriented_side(triangle.vertex(1)) != side0)
return FT(0);
if(line.oriented_side(triangle.vertex(2)) != side0)
return FT(0);
FT mindist = sq_dist(triangle.vertex(0), line);
for(int i=1; i<3; ++i)
{
FT dist = sq_dist(triangle.vertex(i), line);
if(dist < mindist)
mindist = dist;
}
return mindist;
}
template <class K>
inline typename K::FT
squared_distance(const typename K::Triangle_2& triangle,
const typename K::Line_2& line,
const K& k)
{
return internal::squared_distance(line, triangle, k);
}
} // namespace internal
template <class K>
inline typename K::FT
squared_distance(const Line_2<K>& line,
const Triangle_2<K>& triangle)
{
return K().compute_squared_distance_2_object()(line, triangle);
}
template <class K>
inline typename K::FT
squared_distance(const Triangle_2<K>& triangle,
const Line_2<K>& line)
{
return K().compute_squared_distance_2_object()(triangle, line);
}
} // namespace CGAL
#endif // CGAL_DISTANCE_2_LINE_2_TRIANGLE_2_H

View File

@ -0,0 +1,108 @@
// Copyright (c) 1998-2004
// Utrecht University (The Netherlands),
// ETH Zurich (Switzerland),
// INRIA Sophia-Antipolis (France),
// Max-Planck-Institute Saarbruecken (Germany),
// and Tel-Aviv University (Israel). All rights reserved.
//
// This file is part of CGAL (www.cgal.org)
//
// $URL$
// $Id$
// SPDX-License-Identifier: LGPL-3.0-or-later OR LicenseRef-Commercial
//
//
// Author(s) : Geert-Jan Giezeman
// Michel Hoffmann <hoffmann@inf.ethz.ch>
// Andreas Fabri <Andreas.Fabri@geometryfactory.com>
#ifndef CGAL_DISTANCE_2_POINT_2_LINE_2_H
#define CGAL_DISTANCE_2_POINT_2_LINE_2_H
#include <CGAL/Rational_traits.h>
#include <CGAL/number_utils.h>
#include <CGAL/tags.h>
#include <CGAL/Line_2.h>
#include <CGAL/Point_2.h>
namespace CGAL {
namespace internal {
template <class K>
typename K::FT
squared_distance(const typename K::Point_2& pt,
const typename K::Line_2& line,
const K&,
const Homogeneous_tag&)
{
typedef typename K::RT RT;
typedef typename K::FT FT;
const RT& a = line.a();
const RT& b = line.b();
const RT& w = pt.hw();
RT n = a*pt.hx() + b*pt.hy() + w*line.c();
RT d = (CGAL_NTS square(a) + CGAL_NTS square(b)) * CGAL_NTS square(w);
return Rational_traits<FT>().make_rational(CGAL_NTS square(n), d);
}
template <class K>
typename K::FT
squared_distance(const typename K::Point_2& pt,
const typename K::Line_2& line,
const K&,
const Cartesian_tag&)
{
typedef typename K::FT FT;
const FT& a = line.a();
const FT& b = line.b();
FT n = a*pt.x() + b*pt.y() + line.c();
FT d = CGAL_NTS square(a) + CGAL_NTS square(b);
return CGAL_NTS square(n)/d;
}
template <class K>
typename K::FT
squared_distance(const typename K::Point_2& pt,
const typename K::Line_2& line,
const K& k)
{
typedef typename K::Kernel_tag Tag;
Tag tag;
return squared_distance(pt, line, k, tag);
}
template <class K>
inline typename K::FT
squared_distance(const typename K::Line_2& line,
const typename K::Point_2& pt,
const K& k)
{
return internal::squared_distance(pt, line, k);
}
} // namespace internal
template <class K>
inline typename K::FT
squared_distance(const Point_2<K>& pt,
const Line_2<K>& line)
{
return K().compute_squared_distance_2_object()(pt, line);
}
template <class K>
inline typename K::FT
squared_distance(const Line_2<K>& line,
const Point_2<K>& pt)
{
return K().compute_squared_distance_2_object()(line, pt);
}
} // namespace CGAL
#endif // CGAL_DISTANCE_2_POINT_2_LINE_2_H

View File

@ -0,0 +1,49 @@
// Copyright (c) 1998-2004
// Utrecht University (The Netherlands),
// ETH Zurich (Switzerland),
// INRIA Sophia-Antipolis (France),
// Max-Planck-Institute Saarbruecken (Germany),
// and Tel-Aviv University (Israel). All rights reserved.
//
// This file is part of CGAL (www.cgal.org)
//
// $URL$
// $Id$
// SPDX-License-Identifier: LGPL-3.0-or-later OR LicenseRef-Commercial
//
//
// Author(s) : Geert-Jan Giezeman
// Michel Hoffmann <hoffmann@inf.ethz.ch>
// Andreas Fabri <Andreas.Fabri@geometryfactory.com>
#ifndef CGAL_DISTANCE_2_POINT_2_POINT_2_H
#define CGAL_DISTANCE_2_POINT_2_POINT_2_H
#include <CGAL/Point_2.h>
namespace CGAL {
namespace internal {
template <class K>
inline typename K::FT
squared_distance(const typename K::Point_2& pt1,
const typename K::Point_2& pt2,
const K& k)
{
typename K::Vector_2 vec = k.construct_vector_2_object()(pt2, pt1);
return k.compute_squared_length_2_object()(vec);
}
} // namespace internal
template <class K>
inline typename K::FT
squared_distance(const Point_2<K>& pt1,
const Point_2<K>& pt2)
{
return K().compute_squared_distance_2_object()(pt1, pt2);
}
} // namespace CGAL
#endif // CGAL_DISTANCE_2_POINT_2_POINT_2_H

View File

@ -0,0 +1,108 @@
// Copyright (c) 1998-2004
// Utrecht University (The Netherlands),
// ETH Zurich (Switzerland),
// INRIA Sophia-Antipolis (France),
// Max-Planck-Institute Saarbruecken (Germany),
// and Tel-Aviv University (Israel). All rights reserved.
//
// This file is part of CGAL (www.cgal.org)
//
// $URL$
// $Id$
// SPDX-License-Identifier: LGPL-3.0-or-later OR LicenseRef-Commercial
//
//
// Author(s) : Geert-Jan Giezeman
// Michel Hoffmann <hoffmann@inf.ethz.ch>
// Andreas Fabri <Andreas.Fabri@geometryfactory.com>
#ifndef CGAL_DISTANCE_2_POINT_2_RAY_2_H
#define CGAL_DISTANCE_2_POINT_2_RAY_2_H
#include <CGAL/Distance_2/internal/squared_distance_utils_2.h>
#include <CGAL/Distance_2/Point_2_Line_2.h>
#include <CGAL/Point_2.h>
#include <CGAL/Ray_2.h>
namespace CGAL {
namespace internal {
template <class K>
void
distance_index(int &ind,
const typename K::Point_2 &pt,
const typename K::Ray_2 &ray,
const K& k)
{
typename K::Construct_vector_2 construct_vector = k.construct_vector_2_object();
if(!is_acute_angle(ray.direction().vector(), construct_vector(ray.source(), pt), k))
{
ind = 0;
return;
}
ind = -1;
}
template <class K>
inline typename K::FT
squared_distance_indexed(const typename K::Point_2 &pt,
const typename K::Ray_2 &ray,
int ind,
const K& k)
{
if(ind == 0)
return internal::squared_distance(pt, ray.source(), k);
return internal::squared_distance(pt, ray.supporting_line(), k);
}
template <class K>
typename K::FT
squared_distance(const typename K::Point_2& pt,
const typename K::Ray_2& ray,
const K& k)
{
typedef typename K::Vector_2 Vector_2;
typename K::Construct_vector_2 construct_vector = k.construct_vector_2_object();
Vector_2 diff = construct_vector(ray.source(), pt);
const Vector_2& dir = ray.direction().vector();
if (!is_acute_angle(dir, diff, k))
return k.compute_squared_length_2_object()(diff);
return internal::squared_distance(pt, ray.supporting_line(), k);
}
template <class K>
inline typename K::FT
squared_distance(const typename K::Ray_2& ray,
const typename K::Point_2& pt,
const K& k)
{
return internal::squared_distance(pt, ray, k);
}
} // namespace internal
template <class K>
inline typename K::FT
squared_distance(const Point_2<K>& pt,
const Ray_2<K>& ray)
{
return internal::squared_distance(pt, ray, K());
}
template <class K>
inline typename K::FT
squared_distance(const Ray_2<K>& ray,
const Point_2<K>& pt)
{
return internal::squared_distance(pt, ray, K());
}
} // namespace CGAL
#endif // CGAL_DISTANCE_2_POINT_2_RAY_2_H

View File

@ -0,0 +1,126 @@
// Copyright (c) 1998-2004
// Utrecht University (The Netherlands),
// ETH Zurich (Switzerland),
// INRIA Sophia-Antipolis (France),
// Max-Planck-Institute Saarbruecken (Germany),
// and Tel-Aviv University (Israel). All rights reserved.
//
// This file is part of CGAL (www.cgal.org)
//
// $URL$
// $Id$
// SPDX-License-Identifier: LGPL-3.0-or-later OR LicenseRef-Commercial
//
//
// Author(s) : Geert-Jan Giezeman
// Michel Hoffmann <hoffmann@inf.ethz.ch>
// Andreas Fabri <Andreas.Fabri@geometryfactory.com>
#ifndef CGAL_DISTANCE_2_POINT_2_SEGMENT_2_H
#define CGAL_DISTANCE_2_POINT_2_SEGMENT_2_H
#include <CGAL/Distance_2/internal/squared_distance_utils_2.h>
#include <CGAL/Point_2.h>
#include <CGAL/Segment_2.h>
namespace CGAL {
namespace internal {
template <class K>
void
distance_index(int &ind,
const typename K::Point_2 &pt,
const typename K::Segment_2 &seg,
const K& k)
{
if(!is_acute_angle(seg.target(),seg.source(),pt, k))
{
ind = 0;
return;
}
if(!is_acute_angle(seg.source(),seg.target(),pt, k))
{
ind = 1;
return;
}
ind = -1;
}
template <class K>
inline typename K::FT
squared_distance_indexed(const typename K::Point_2 &pt,
const typename K::Segment_2 &seg,
int ind,
const K& k)
{
typename K::Compute_squared_distance_2 sq_dist = k.compute_squared_distance_2_object();
if(ind == 0)
return sq_dist(pt, seg.source());
if(ind == 1)
return sq_dist(pt, seg.target());
return sq_dist(pt, seg.supporting_line());
}
template <class K>
typename K::FT
squared_distance(const typename K::Point_2& pt,
const typename K::Segment_2& seg,
const K& k)
{
typedef typename K::Vector_2 Vector_2;
typedef typename K::RT RT;
typename K::Construct_vector_2 vector = k.construct_vector_2_object();
typename K::Compute_squared_length_2 sq_length = k.compute_squared_length_2_object();
typename K::Compute_squared_distance_2 sq_dist = k.compute_squared_distance_2_object();
// assert that the segment is valid (non zero length).
const Vector_2 diff = vector(seg.source(), pt);
const Vector_2 segvec = vector(seg.source(), seg.target());
const RT d = wdot(diff, segvec, k);
if(d <= RT(0))
return sq_length(diff);
const RT e = wdot(segvec,segvec, k);
if(wmult((K*)0 ,d, segvec.hw()) > wmult((K*)0, e, diff.hw()))
return sq_dist(pt, seg.target());
return sq_dist(pt, seg.supporting_line());
}
template <class K>
inline typename K::FT
squared_distance(const typename K::Segment_2& seg,
const typename K::Point_2& pt,
const K& k)
{
return internal::squared_distance(pt, seg, k);
}
} // namespace internal
template <class K>
inline typename K::FT
squared_distance(const Point_2<K>& pt,
const Segment_2<K>& seg)
{
return K().compute_squared_distance_2_object()(pt, seg);
}
template <class K>
inline typename K::FT
squared_distance(const Segment_2<K>& seg,
const Point_2<K>& pt)
{
return K().compute_squared_distance_2_object()(seg, pt);
}
} // namespace CGAL
#endif // CGAL_DISTANCE_2_POINT_2_SEGMENT_2_H

View File

@ -0,0 +1,266 @@
// Copyright (c) 1998-2004
// Utrecht University (The Netherlands),
// ETH Zurich (Switzerland),
// INRIA Sophia-Antipolis (France),
// Max-Planck-Institute Saarbruecken (Germany),
// and Tel-Aviv University (Israel). All rights reserved.
//
// This file is part of CGAL (www.cgal.org)
//
// $URL$
// $Id$
// SPDX-License-Identifier: LGPL-3.0-or-later OR LicenseRef-Commercial
//
//
// Author(s) : Geert-Jan Giezeman
// Michel Hoffmann <hoffmann@inf.ethz.ch>
// Andreas Fabri <Andreas.Fabri@geometryfactory.com>
#ifndef CGAL_DISTANCE_2_POINT_2_TRIANGLE_2_H
#define CGAL_DISTANCE_2_POINT_2_TRIANGLE_2_H
#include <CGAL/Distance_2/internal/squared_distance_utils_2.h>
#include <CGAL/Point_2.h>
#include <CGAL/Triangle_2.h>
namespace CGAL {
namespace internal {
template <class K>
void
distance_index(int &ind1,
int &ind2,
const typename K::Point_2 &pt,
const typename K::Triangle_2 &triangle,
const K& k)
{
typedef typename K::Point_2 Point_2;
typename K::Left_turn_2 leftturn = k.left_turn_2_object();
const Point_2& vt0 = triangle.vertex(0);
const Point_2& vt1 = triangle.vertex(1);
const Point_2& vt2 = triangle.vertex(2);
if(leftturn(vt0, vt1, vt2)) {
if(leftturn(pt, vt1, vt0)) {
if(!is_acute_angle(vt0, vt1, pt, k)) {
if(leftturn(pt, vt2, vt1)) {
if(!is_acute_angle(vt1, vt2, pt, k)) {
ind1 = 2; ind2 = -1;
return;
}
if(!is_acute_angle(vt2, vt1, pt, k)) {
ind1 = 1; ind2 = -1;
return;
}
ind1 = 1; ind2 = 2;
return;
}
ind1 = 1; ind2 = -1;
return;
}
if(!is_acute_angle(vt1, vt0, pt, k)) {
if(leftturn(pt, vt0, vt2)) {
if(!is_acute_angle(vt0, vt2, pt, k)) {
ind1 = 2; ind2 = -1;
return;
}
if(!is_acute_angle(vt2, vt0, pt, k)) {
ind1 = 0; ind2 = -1;
return;
}
ind1 = 2; ind2 = 0;
return;
}
ind1 = 0; ind2 = -1;
return;
}
ind1 = 0; ind2 = 1;
return;
} else {
if(leftturn(pt, vt2, vt1)) {
if(!is_acute_angle(vt1, vt2, pt, k)) {
if(leftturn(pt, vt0, vt2)) {
if(!is_acute_angle(vt0, vt2, pt, k)) {
ind1 = 2; ind2 = -1;
return;
}
if(!is_acute_angle(vt2, vt0, pt, k)) {
ind1 = 0; ind2 = -1;
return;
}
ind1 = 2; ind2 = 0;
return;
}
ind1 = 0; ind2 = -1;
return;
}
if(!is_acute_angle(vt2, vt1, pt, k)) {
ind1 = 1; ind2 = -1;
return;
}
ind1 = 1; ind2 = 2;
return;
} else {
if(leftturn(pt, vt0, vt2)) {
if(!is_acute_angle(vt2, vt0, pt, k)) {
ind1 = 0; ind2 = -1;
return;
}
if(!is_acute_angle(vt0, vt2, pt, k)) {
ind1 = 2; ind2 = -1;
return;
}
ind1 = 2; ind2 = 0;
return;
} else {
ind1 = -1; ind2 = -1; // point inside or on boundary.
return;
}
}
}
} else {
if(leftturn(pt, vt2, vt0)) {
if(!is_acute_angle(vt0, vt2, pt, k)) {
if(leftturn(pt, vt1, vt2)) {
if(!is_acute_angle(vt2, vt1, pt, k)) {
ind1 = 1; ind2 = -1;
return;
}
if(!is_acute_angle(vt1, vt2, pt, k)) {
ind1 = 2; ind2 = -1;
return;
}
ind1 = 2; ind2 = 1;
return;
}
ind1 = 2; ind2 = -1;
return;
}
if(!is_acute_angle(vt2, vt0, pt, k)) {
if(leftturn(pt, vt0, vt1)) {
if(!is_acute_angle(vt0, vt1, pt, k)) {
ind1 = 1; ind2 = -1;
return;
}
if(!is_acute_angle(vt1, vt0, pt, k)) {
ind1 = 0; ind2 = -1;
return;
}
ind1 = 1; ind2 = 0;
return;
}
ind1 = 0; ind2 = -1;
return;
}
ind1 = 0; ind2 = 2;
return;
} else {
if(leftturn(pt, vt1, vt2)) {
if(!is_acute_angle(vt2, vt1, pt, k)) {
if(leftturn(pt, vt0, vt1)) {
if(!is_acute_angle(vt0, vt1, pt, k)) {
ind1 = 1; ind2 = -1;
return;
}
if(!is_acute_angle(vt1, vt0, pt, k)) {
ind1 = 0; ind2 = -1;
return;
}
ind1 = 1; ind2 = 0;
return;
}
ind1 = 0; ind2 = -1;
return;
}
if(!is_acute_angle(vt1, vt2, pt, k)) {
ind1 = 2; ind2 = -1;
return;
}
ind1 = 2; ind2 = 1;
return;
} else {
if(leftturn(pt, vt0, vt1)) {
if(!is_acute_angle(vt1, vt0, pt, k)) {
ind1 = 0; ind2 = -1;
return;
}
if(!is_acute_angle(vt0, vt1, pt, k)) {
ind1 = 1; ind2 = -1;
return;
}
ind1 = 1; ind2 = 0;
return;
} else {
ind1 = -1; ind2 = -1; // point inside or on boundary.
return;
}
}
}
}
}
template <class K>
typename K::FT
squared_distance_indexed(const typename K::Point_2& pt,
const typename K::Triangle_2& triangle,
int ind1, int ind2,
const K& k)
{
typedef typename K::FT FT;
typedef typename K::Line_2 Line_2;
typename K::Compute_squared_distance_2 sq_dist = k.compute_squared_distance_2_object();
if(ind1 == -1)
return FT(0);
if(ind2 == -1)
return sq_dist(pt, triangle.vertex(ind1));
return sq_dist(pt, Line_2{triangle.vertex(ind1), triangle.vertex(ind2)});
}
template <class K>
typename K::FT
squared_distance(const typename K::Point_2& pt,
const typename K::Triangle_2& triangle,
const K& k)
{
int ind1, ind2;
distance_index<K>(ind1, ind2, pt, triangle, k);
return squared_distance_indexed(pt, triangle, ind1, ind2, k);
}
template <class K>
inline typename K::FT
squared_distance(const typename K::Triangle_2& triangle,
const typename K::Point_2& pt,
const K& k)
{
return internal::squared_distance(pt, triangle, k);
}
} // namespace internal
template <class K>
inline typename K::FT
squared_distance(const Point_2<K>& pt,
const Triangle_2<K>& triangle)
{
return K().compute_squared_distance_2_object()(pt, triangle);
}
template <class K>
inline typename K::FT
squared_distance(const Triangle_2<K>& triangle,
const Point_2<K>& pt)
{
return K().compute_squared_distance_2_object()(triangle, pt);
}
} // namespace CGAL
#endif // CGAL_DISTANCE_2_POINT_2_TRIANGLE_2_H

View File

@ -0,0 +1,88 @@
// Copyright (c) 1998-2004
// Utrecht University (The Netherlands),
// ETH Zurich (Switzerland),
// INRIA Sophia-Antipolis (France),
// Max-Planck-Institute Saarbruecken (Germany),
// and Tel-Aviv University (Israel). All rights reserved.
//
// This file is part of CGAL (www.cgal.org)
//
// $URL$
// $Id$
// SPDX-License-Identifier: LGPL-3.0-or-later OR LicenseRef-Commercial
//
//
// Author(s) : Geert-Jan Giezeman
// Michel Hoffmann <hoffmann@inf.ethz.ch>
// Andreas Fabri <Andreas.Fabri@geometryfactory.com>
#ifndef CGAL_DISTANCE_2_RAY_2_LINE_2_H
#define CGAL_DISTANCE_2_RAY_2_LINE_2_H
#include <CGAL/Distance_2/internal/squared_distance_utils_2.h>
#include <CGAL/Line_2.h>
#include <CGAL/Ray_2.h>
namespace CGAL {
namespace internal {
template <class K>
typename K::FT
squared_distance(const typename K::Line_2& line,
const typename K::Ray_2& ray,
const K& k)
{
typedef typename K::FT FT;
typedef typename K::Vector_2 Vector_2;
typename K::Construct_vector_2 construct_vector = k.construct_vector_2_object();
Vector_2 normalvec(line.a(), line.b());
Vector_2 diff = construct_vector(line.point(), ray.source());
FT sign_dist = k.compute_scalar_product_2_object()(diff, normalvec);
if(sign_dist < FT(0))
{
if(is_acute_angle(normalvec, ray.direction().vector(), k))
return FT(0);
}
else
{
if(is_obtuse_angle(normalvec, ray.direction().vector(), k))
return FT(0);
}
return (square(sign_dist) / k.compute_squared_length_2_object()(normalvec));
}
template <class K>
inline typename K::FT
squared_distance(const typename K::Ray_2& ray,
const typename K::Line_2& line,
const K& k)
{
return internal::squared_distance(line, ray, k);
}
} // namespace internal
template <class K>
inline typename K::FT
squared_distance(const Line_2<K>& line,
const Ray_2<K>& ray)
{
return K().compute_squared_distance_2_object()(line, ray);
}
template <class K>
inline typename K::FT
squared_distance(const Ray_2<K>& ray,
const Line_2<K>& line)
{
return K().compute_squared_distance_2_object()(ray, line);
}
} // namespace CGAL
#endif // CGAL_DISTANCE_2_RAY_2_LINE_2_H

View File

@ -0,0 +1,115 @@
// Copyright (c) 1998-2004
// Utrecht University (The Netherlands),
// ETH Zurich (Switzerland),
// INRIA Sophia-Antipolis (France),
// Max-Planck-Institute Saarbruecken (Germany),
// and Tel-Aviv University (Israel). All rights reserved.
//
// This file is part of CGAL (www.cgal.org)
//
// $URL$
// $Id$
// SPDX-License-Identifier: LGPL-3.0-or-later OR LicenseRef-Commercial
//
//
// Author(s) : Geert-Jan Giezeman
// Michel Hoffmann <hoffmann@inf.ethz.ch>
// Andreas Fabri <Andreas.Fabri@geometryfactory.com>
#ifndef CGAL_DISTANCE_2_RAY_2_RAY_2_H
#define CGAL_DISTANCE_2_RAY_2_RAY_2_H
#include <CGAL/Distance_2/internal/squared_distance_utils_2.h>
#include <CGAL/Distance_2/Point_2_Ray_2.h>
#include <CGAL/Ray_2.h>
namespace CGAL {
namespace internal {
template <class K>
typename K::FT
ray_ray_squared_distance_parallel(const typename K::Vector_2& ray1dir,
const typename K::Vector_2& ray2dir,
const typename K::Vector_2& from1to2,
const K& k)
{
typedef typename K::RT RT;
typedef typename K::FT FT;
if(!is_acute_angle(ray1dir, from1to2, k))
{
if(!same_direction(ray1dir, ray2dir, k))
return k.compute_squared_length_2_object()(from1to2);
}
RT wcr = wcross(ray1dir, from1to2, k);
RT w = from1to2.hw();
return (square(wcr) / FT(wmult((K*)0, wdot(ray1dir, ray1dir, k), w, w)));
}
template <class K>
typename K::FT
squared_distance(const typename K::Ray_2& ray1,
const typename K::Ray_2& ray2,
const K& k)
{
typedef typename K::Vector_2 Vector_2;
typedef typename K::FT FT;
typename K::Construct_vector_2 vector = k.construct_vector_2_object();
typename K::Compute_squared_distance_2 sq_dist = k.compute_squared_distance_2_object();
const Vector_2 ray1dir = ray1.direction().vector();
const Vector_2 ray2dir = ray2.direction().vector();
const Vector_2 diffvec = vector(ray1.source(),ray2.source());
bool crossing1, crossing2;
switch(orientation(ray1dir, ray2dir, k))
{
case COUNTERCLOCKWISE:
crossing1 = !clockwise(diffvec, ray2dir, k);
crossing2 = !counterclockwise(ray1dir, diffvec, k);
break;
case CLOCKWISE:
crossing1 = !counterclockwise(diffvec, ray2dir, k);
crossing2 = !clockwise(ray1dir, diffvec, k);
break;
default:
return ray_ray_squared_distance_parallel(ray1dir, ray2dir, diffvec,k);
}
if(crossing1)
{
if(crossing2)
return FT(0);
return sq_dist(ray2.source(), ray1);
}
else
{
if(crossing2)
{
return sq_dist(ray1.source(), ray2);
}
else
{
FT min1 = sq_dist(ray1.source(), ray2);
FT min2 = sq_dist(ray2.source(), ray1);
return (min1 < min2) ? min1 : min2;
}
}
}
} // namespace internal
template <class K>
inline typename K::FT
squared_distance(const Ray_2<K> &ray1, const Ray_2<K> &ray2)
{
return K().compute_squared_distance_2_object()(ray1, ray2);
}
} // namespace CGAL
#endif // CGAL_DISTANCE_2_RAY_2_RAY_2_H

View File

@ -0,0 +1,121 @@
// Copyright (c) 1998-2004
// Utrecht University (The Netherlands),
// ETH Zurich (Switzerland),
// INRIA Sophia-Antipolis (France),
// Max-Planck-Institute Saarbruecken (Germany),
// and Tel-Aviv University (Israel). All rights reserved.
//
// This file is part of CGAL (www.cgal.org)
//
// $URL$
// $Id$
// SPDX-License-Identifier: LGPL-3.0-or-later OR LicenseRef-Commercial
//
//
// Author(s) : Geert-Jan Giezeman
// Michel Hoffmann <hoffmann@inf.ethz.ch>
// Andreas Fabri <Andreas.Fabri@geometryfactory.com>
#ifndef CGAL_DISTANCE_2_RAY_2_TRIANGLE_2_H
#define CGAL_DISTANCE_2_RAY_2_TRIANGLE_2_H
#include <CGAL/Distance_2/internal/squared_distance_utils_2.h>
#include <CGAL/Distance_2/Point_2_Triangle_2.h>
#include <CGAL/Ray_2.h>
#include <CGAL/Triangle_2.h>
namespace CGAL {
namespace internal {
template <class K>
typename K::FT
squared_distance(const typename K::Ray_2& ray,
const typename K::Triangle_2& triangle,
const K& k)
{
typedef typename K::FT FT;
typedef typename K::Point_2 Point_2;
typedef typename K::Line_2 Line_2;
int ind_tr1, ind_tr2, ind_ray = 0, ind1;
distance_index<K>(ind_tr1, ind_tr2, ray.source(), triangle, k);
FT mindist = squared_distance_indexed(ray.source(), triangle, ind_tr1, ind_tr2, k);
for(int i=0; i<3; ++i)
{
const Point_2& pt = triangle.vertex(i);
distance_index<K>(ind1, pt, ray, k);
FT dist = squared_distance_indexed(pt, ray, ind1, k);
if(dist < mindist)
{
ind_ray = ind1;
ind_tr1 = i; ind_tr2 = -1;
mindist = dist;
}
}
// now check if all vertices are on the right side of the separating line.
// In case of vertex-vertex smallest distance this is the case.
if(ind_tr2 == -1 && ind_ray != -1)
return mindist;
if(ind_tr2 != -1)
{
// Check if all the segment vertices lie at the same side of
// the triangle segment.
const Point_2& vt1 = triangle.vertex(ind_tr1);
const Point_2& vt2 = triangle.vertex(ind_tr2);
if(clockwise(ray.direction().vector(), vt2-vt1, k))
mindist = FT(0);
}
else
{
// Check if all the triangle vertices lie
// at the same side of the segment.
const Line_2& sl = ray.supporting_line();
Oriented_side or_s = sl.oriented_side(triangle.vertex(0));
for(int i=1; i<3; ++i)
{
if(sl.oriented_side(triangle.vertex(i)) != or_s)
{
mindist = FT(0);
break;
}
}
}
return mindist;
}
template <class K>
inline typename K::FT
squared_distance(const typename K::Triangle_2& triangle,
const typename K::Ray_2& ray,
const K& k)
{
return internal::squared_distance(ray, triangle, k);
}
} // namespace internal
template <class K>
inline typename K::FT
squared_distance(const Ray_2<K>& ray,
const Triangle_2<K>& triangle)
{
return K().compute_squared_distance_2_object()(ray, triangle);
}
template <class K>
inline typename K::FT
squared_distance(const Triangle_2<K>& triangle,
const Ray_2<K>& ray)
{
return K().compute_squared_distance_2_object()(triangle, ray);
}
} // namespace CGAL
#endif // CGAL_DISTANCE_2_RAY_2_TRIANGLE_2_H

View File

@ -0,0 +1,129 @@
// Copyright (c) 1998-2004
// Utrecht University (The Netherlands),
// ETH Zurich (Switzerland),
// INRIA Sophia-Antipolis (France),
// Max-Planck-Institute Saarbruecken (Germany),
// and Tel-Aviv University (Israel). All rights reserved.
//
// This file is part of CGAL (www.cgal.org)
//
// $URL$
// $Id$
// SPDX-License-Identifier: LGPL-3.0-or-later OR LicenseRef-Commercial
//
//
// Author(s) : Geert-Jan Giezeman
// Michel Hoffmann <hoffmann@inf.ethz.ch>
// Andreas Fabri <Andreas.Fabri@geometryfactory.com>
#ifndef CGAL_DISTANCE_2_SEGMENT_2_LINE_2_H
#define CGAL_DISTANCE_2_SEGMENT_2_LINE_2_H
#include <CGAL/Distance_2/internal/squared_distance_utils_2.h>
#include <CGAL/Distance_2/Point_2_Line_2.h>
#include <CGAL/Distance_2/Segment_2_Ray_2.h>
#include <CGAL/number_utils.h>
#include <CGAL/Rational_traits.h>
#include <CGAL/Line_2.h>
#include <CGAL/Segment_2.h>
namespace CGAL {
namespace internal {
template <class K>
typename K::FT
_sqd_to_line(const typename K::Vector_2& diff,
const typename K::RT& wcross,
const typename K::Vector_2& dir)
{
typedef typename K::RT RT;
typedef typename K::FT FT;
RT numerator = CGAL_NTS square(wcross);
RT denominator = wmult((K*)0, RT(wdot(dir,dir, K())), diff.hw(), diff.hw());
return Rational_traits<FT>().make_rational(numerator, denominator);
}
template <class K>
typename K::FT
squared_distance(const typename K::Segment_2& seg,
const typename K::Line_2& line,
const K& k)
{
typedef typename K::RT RT;
typedef typename K::FT FT;
typedef typename K::Vector_2 Vector_2;
typedef typename K::Point_2 Point_2;
typename K::Construct_vector_2 vector = k.construct_vector_2_object();
typename K::Compute_squared_distance_2 sq_dist = k.compute_squared_distance_2_object();
const Vector_2 linedir = line.direction().vector();
const Point_2& linepoint = line.point();
const Vector_2 startvec = vector(linepoint, seg.source());
const Vector_2 endvec = vector(linepoint, seg.target());
if(seg.source() == seg.target())
return sq_dist(seg.source(), line);
bool crossing1;
const RT c1s = wcross(linedir, startvec, k);
const RT c1e = wcross(linedir, endvec, k);
if(c1s < RT(0))
{
crossing1 = (c1e >= RT(0));
}
else
{
if(c1e <= RT(0))
crossing1 = true;
else
crossing1 = (c1s == RT(0));
}
if(crossing1)
{
return FT(0);
}
else
{
const RT dm = _distance_measure_sub<K>(c1s, c1e, startvec, endvec);
if(dm <= RT(0))
return _sqd_to_line<K>(startvec, c1s, linedir);
else
return _sqd_to_line<K>(endvec, c1e, linedir);
}
}
template <class K>
inline typename K::FT
squared_distance(const typename K::Line_2& line,
const typename K::Segment_2& seg,
const K& k)
{
return internal::squared_distance(seg, line, k);
}
} // namespace internal
template <class K>
inline typename K::FT
squared_distance(const Segment_2<K>& seg,
const Line_2<K>& line)
{
return K().compute_squared_distance_2_object()(seg, line);
}
template <class K>
inline typename K::FT
squared_distance(const Line_2<K>& line,
const Segment_2<K>& seg)
{
return K().compute_squared_distance_2_object()(line, seg);
}
} // namespace CGAL
#endif // CGAL_DISTANCE_2_SEGMENT_2_LINE_2_H

View File

@ -0,0 +1,196 @@
// Copyright (c) 1998-2004
// Utrecht University (The Netherlands),
// ETH Zurich (Switzerland),
// INRIA Sophia-Antipolis (France),
// Max-Planck-Institute Saarbruecken (Germany),
// and Tel-Aviv University (Israel). All rights reserved.
//
// This file is part of CGAL (www.cgal.org)
//
// $URL$
// $Id$
// SPDX-License-Identifier: LGPL-3.0-or-later OR LicenseRef-Commercial
//
//
// Author(s) : Geert-Jan Giezeman
// Michel Hoffmann <hoffmann@inf.ethz.ch>
// Andreas Fabri <Andreas.Fabri@geometryfactory.com>
#ifndef CGAL_DISTANCE_2_SEGMENT_2_RAY_2_H
#define CGAL_DISTANCE_2_SEGMENT_2_RAY_2_H
#include <CGAL/Distance_2/internal/squared_distance_utils_2.h>
#include <CGAL/Distance_2/Point_2_Line_2.h>
#include <CGAL/Distance_2/Point_2_Point_2.h>
#include <CGAL/Distance_2/Point_2_Ray_2.h>
#include <CGAL/Segment_2.h>
#include <CGAL/Ray_2.h>
namespace CGAL {
namespace internal {
template <class K>
inline typename K::RT
_distance_measure_sub(const typename K::RT& startwcross,
const typename K::RT& endwcross,
const typename K::Vector_2& start,
const typename K::Vector_2& end)
{
return CGAL_NTS abs(wmult((K*)0, startwcross, end.hw())) -
CGAL_NTS abs(wmult((K*)0, endwcross, start.hw()));
}
template <class K>
typename K::FT
squared_distance_parallel(const typename K::Segment_2& seg,
const typename K::Ray_2& ray,
const K& k)
{
typedef typename K::Vector_2 Vector_2;
typename K::Compute_squared_distance_2 sq_dist = k.compute_squared_distance_2_object();
const Vector_2 dir1 = seg.direction().vector();
const Vector_2 dir2 = ray.direction().vector();
if(same_direction(dir1, dir2, k))
{
if(!is_acute_angle(seg.source(), seg.target(), ray.source(), k))
return sq_dist(seg.target(), ray.source());
}
else
{
if(!is_acute_angle(seg.target(), seg.source(), ray.source(), k))
return sq_dist(seg.source(), ray.source());
}
return sq_dist(ray.source(), seg.supporting_line());
}
template <class K>
typename K::FT
squared_distance(const typename K::Segment_2& seg,
const typename K::Ray_2& ray,
const K& k)
{
typedef typename K::RT RT;
typedef typename K::FT FT;
typedef typename K::Vector_2 Vector_2;
typename K::Construct_vector_2 vector = k.construct_vector_2_object();
typename K::Orientation_2 orientation = k.orientation_2_object();
typename K::Compute_squared_distance_2 sq_dist = k.compute_squared_distance_2_object();
const Vector_2& raydir = ray.direction().vector();
const Vector_2 startvec = vector(ray.source(), seg.source());
const Vector_2 endvec = vector(ray.source(), seg.target());
if(seg.source() == seg.target())
return internal::squared_distance(seg.source(), ray, k);
bool crossing1, crossing2;
const RT c1s = wcross(raydir, startvec, k);
const RT c1e = wcross(raydir, endvec, k);
if(c1s < RT(0))
{
crossing1 = (c1e >= RT(0));
}
else
{
if(c1e <= RT(0))
{
if(c1s == RT(0) && c1e == RT(0))
return internal::squared_distance_parallel(seg, ray, k);
crossing1 = true;
}
else
{
crossing1 = (c1s == RT(0));
}
}
switch (orientation(seg.source(), seg.target(), ray.source()))
{
case LEFT_TURN:
crossing2 = right_turn(vector(seg.source(), seg.target()), raydir, k);
break;
case RIGHT_TURN:
crossing2 = left_turn(vector(seg.source(), seg.target()), raydir, k);
break;
default:
crossing2 = true;
break;
}
if(crossing1)
{
if(crossing2)
return FT(0);
return sq_dist(ray.source(), seg);
}
else
{
if(crossing2)
{
const RT dm = _distance_measure_sub<K>(c1s, c1e, startvec, endvec);
if(dm < RT(0))
{
return sq_dist(seg.source(), ray);
}
else
{
if(dm > RT(0))
return sq_dist(seg.target(), ray);
else // parallel, should not happen (no crossing)
return internal::squared_distance_parallel(seg, ray, k);
}
}
else
{
const RT dm = _distance_measure_sub<K>(c1s, c1e, startvec, endvec);
if(dm == RT(0))
return internal::squared_distance_parallel(seg, ray, k);
const FT min1 = (dm < RT(0)) ? sq_dist(seg.source(), ray)
: sq_dist(seg.target(), ray);
const FT min2 = sq_dist(ray.source(), seg);
return (min1 < min2) ? min1 : min2;
}
}
}
template <class K>
inline typename K::FT
squared_distance(const typename K::Ray_2& ray,
const typename K::Segment_2& seg,
const K& k)
{
return internal::squared_distance(seg, ray, k);
}
} // namespace internal
template <class K>
inline typename K::FT
squared_distance(const Segment_2<K>& seg,
const Ray_2<K>& ray)
{
return K().compute_squared_distance_2_object()(seg, ray);
}
template <class K>
inline typename K::FT
squared_distance(const Ray_2<K>& ray,
const Segment_2<K>& seg)
{
return K().compute_squared_distance_2_object()(ray, seg);
}
} // namespace CGAL
#endif // CGAL_DISTANCE_2_SEGMENT_2_RAY_2_H

View File

@ -0,0 +1,351 @@
// Copyright (c) 1998-2004
// Utrecht University (The Netherlands),
// ETH Zurich (Switzerland),
// INRIA Sophia-Antipolis (France),
// Max-Planck-Institute Saarbruecken (Germany),
// and Tel-Aviv University (Israel). All rights reserved.
//
// This file is part of CGAL (www.cgal.org)
//
// $URL$
// $Id$
// SPDX-License-Identifier: LGPL-3.0-or-later OR LicenseRef-Commercial
//
//
// Author(s) : Geert-Jan Giezeman
// Michel Hoffmann <hoffmann@inf.ethz.ch>
// Andreas Fabri <Andreas.Fabri@geometryfactory.com>
#ifndef CGAL_DISTANCE_2_SEGMENT_2_SEGMENT_2_H
#define CGAL_DISTANCE_2_SEGMENT_2_SEGMENT_2_H
#include <CGAL/Distance_2/internal/squared_distance_utils_2.h>
#include <CGAL/Distance_2/Point_2_Line_2.h>
#include <CGAL/Distance_2/Point_2_Point_2.h>
#include <CGAL/Distance_2/Point_2_Segment_2.h>
#include <CGAL/number_utils.h>
#include <CGAL/tags.h>
#include <CGAL/Segment_2.h>
namespace CGAL {
namespace internal {
template <class K>
typename K::FT
squared_distance_parallel(const typename K::Segment_2& seg1,
const typename K::Segment_2& seg2,
const K& k)
{
typedef typename K::Vector_2 Vector_2;
typename K::Compute_squared_distance_2 sq_dist = k.compute_squared_distance_2_object();
const Vector_2 dir1 = seg1.direction().vector();
const Vector_2 dir2 = seg2.direction().vector();
if(same_direction(dir1, dir2, k))
{
if(!is_acute_angle(seg1.source(), seg1.target(), seg2.source(), k))
return sq_dist(seg1.target(), seg2.source());
if(!is_acute_angle(seg1.target(), seg1.source(), seg2.target(), k))
return sq_dist(seg1.source(), seg2.target());
}
else
{
if(!is_acute_angle(seg1.source(), seg1.target(), seg2.target(), k))
return sq_dist(seg1.target(), seg2.target());
if(!is_acute_angle(seg1.target(), seg1.source(), seg2.source(), k))
return sq_dist(seg1.source(), seg2.source());
}
return sq_dist(seg2.source(), seg1.supporting_line());
}
template <class K>
inline typename K::RT
_distance_measure_sub(const typename K::RT& startwcross,
const typename K::RT& endwcross,
const typename K::Point_2& start,
const typename K::Point_2& end)
{
return CGAL_NTS abs(wmult((K*)0, startwcross, end.hw())) -
CGAL_NTS abs(wmult((K*)0, endwcross, start.hw()));
}
template <class K>
typename K::FT
squared_distance(const typename K::Segment_2& seg1,
const typename K::Segment_2& seg2,
const K& k,
const Cartesian_tag&)
{
typedef typename K::RT RT;
typedef typename K::FT FT;
typename K::Orientation_2 orientation = k.orientation_2_object();
typename K::Compute_squared_distance_2 sq_dist = k.compute_squared_distance_2_object();
if(seg1.source() == seg1.target())
return sq_dist(seg1.source(), seg2);
if(seg2.source() == seg2.target())
return sq_dist(seg2.source(), seg1);
const Orientation o1s = orientation(seg2.source(), seg2.target(), seg1.source());
const Orientation o1e = orientation(seg2.source(), seg2.target(), seg1.target());
bool crossing1, crossing2;
if(o1s == RIGHT_TURN)
{
crossing1 = (o1e != RIGHT_TURN);
}
else
{
if(o1e != LEFT_TURN)
{
if(o1s == COLLINEAR && o1e == COLLINEAR)
return internal::squared_distance_parallel(seg1, seg2, k);
crossing1 = true;
}
else
{
crossing1 = (o1s == COLLINEAR);
}
}
const Orientation o2s = orientation(seg1.source(), seg1.target(), seg2.source());
const Orientation o2e = orientation(seg1.source(), seg1.target(), seg2.target());
if(o2s == RIGHT_TURN)
{
crossing2 = (o2e != RIGHT_TURN);
}
else
{
if(o2e != LEFT_TURN)
{
if(o2s == COLLINEAR && o2e == COLLINEAR)
return internal::squared_distance_parallel(seg1, seg2, k);
crossing2 = true;
}
else
{
crossing2 = (o2s == COLLINEAR);
}
}
if(crossing1)
{
if(crossing2)
return (FT)0;
const RT c2s = CGAL_NTS abs(wcross(seg1.source(), seg1.target(), seg2.source(), k));
const RT c2e = CGAL_NTS abs(wcross(seg1.source(), seg1.target(), seg2.target(), k));
Comparison_result dm = CGAL_NTS compare(c2s, c2e);
if(dm == SMALLER)
{
return sq_dist(seg2.source(), seg1);
}
else
{
if(dm == LARGER)
{
return sq_dist(seg2.target(), seg1);
}
else
{
// parallel, should not happen (no crossing)
return internal::squared_distance_parallel(seg1, seg2, k);
}
}
}
else
{
const RT c1s = CGAL_NTS abs(wcross(seg2.source(), seg2.target(), seg1.source(), k));
const RT c1e = CGAL_NTS abs(wcross(seg2.source(), seg2.target(), seg1.target(), k));
Comparison_result dm = CGAL_NTS compare(c1s, c1e);
if(crossing2)
{
if(dm == SMALLER)
{
return sq_dist(seg1.source(), seg2);
}
else
{
if(dm == LARGER)
return sq_dist(seg1.target(), seg2);
else // parallel, should not happen (no crossing)
return internal::squared_distance_parallel(seg1, seg2, k);
}
}
else
{
if(dm == EQUAL)
return internal::squared_distance_parallel(seg1, seg2, k);
FT min1 = (dm == SMALLER) ? sq_dist(seg1.source(), seg2):
sq_dist(seg1.target(), seg2);
const RT c2s = CGAL_NTS abs(wcross(seg1.source(), seg1.target(), seg2.source(), k));
const RT c2e = CGAL_NTS abs(wcross(seg1.source(), seg1.target(), seg2.target(), k));
dm = CGAL_NTS compare(c2s,c2e);
if(dm == EQUAL) // should not happen.
return internal::squared_distance_parallel(seg1, seg2, k);
FT min2 = (dm == SMALLER) ? sq_dist(seg2.source(), seg1):
sq_dist(seg2.target(), seg1);
return (min1 < min2) ? min1 : min2;
}
}
}
template <class K>
typename K::FT
squared_distance(const typename K::Segment_2& seg1,
const typename K::Segment_2& seg2,
const K& k,
const Homogeneous_tag&)
{
typedef typename K::RT RT;
typedef typename K::FT FT;
typename K::Compute_squared_distance_2 sq_dist = k.compute_squared_distance_2_object();
if(seg1.source() == seg1.target())
return sq_dist(seg1.source(), seg2);
if(seg2.source() == seg2.target())
return sq_dist(seg2.source(), seg1);
const RT c1s = wcross(seg2.source(), seg2.target(), seg1.source(), k);
const RT c1e = wcross(seg2.source(), seg2.target(), seg1.target(), k);
const RT c2s = wcross(seg1.source(), seg1.target(), seg2.source(), k);
const RT c2e = wcross(seg1.source(), seg1.target(), seg2.target(), k);
bool crossing1, crossing2;
if(c1s < RT(0))
{
crossing1 = (c1e >= RT(0));
}
else
{
if(c1e <= RT(0))
{
if(c1s == RT(0) && c1e == RT(0))
return internal::squared_distance_parallel(seg1, seg2, k);
crossing1 = true;
}
else
{
crossing1 = (c1s == RT(0));
}
}
if(c2s < RT(0))
{
crossing2 = (c2e >= RT(0));
}
else
{
if(c2e <= RT(0))
{
if(c2s == RT(0) && c2e == RT(0))
return internal::squared_distance_parallel(seg1, seg2, k);
crossing2 = true;
}
else
{
crossing2 = (c2s == RT(0));
}
}
if(crossing1)
{
if(crossing2)
return (FT)0;
const RT dm = _distance_measure_sub<K>(c2s,c2e, seg2.source(), seg2.target());
if(dm < RT(0))
{
return sq_dist(seg2.source(), seg1);
}
else
{
if(dm > RT(0))
return sq_dist(seg2.target(), seg1);
else // parallel, should not happen (no crossing)
return internal::squared_distance_parallel(seg1, seg2, k);
}
}
else
{
if(crossing2)
{
const RT dm = _distance_measure_sub<K>(c1s, c1e,seg1.source(),seg1.target());
if(dm < RT(0))
{
return sq_dist(seg1.source(), seg2);
}
else
{
if(dm > RT(0))
return sq_dist(seg1.target(), seg2);
else // parallel, should not happen (no crossing)
return internal::squared_distance_parallel(seg1, seg2, k);
}
}
else
{
RT dm = _distance_measure_sub<K>(c1s, c1e, seg1.source(), seg1.target());
if(dm == RT(0))
return internal::squared_distance_parallel(seg1, seg2, k);
FT min1 = (dm < RT(0)) ? sq_dist(seg1.source(), seg2):
sq_dist(seg1.target(), seg2);
dm = _distance_measure_sub<K>(c2s, c2e, seg2.source(), seg2.target());
if(dm == RT(0)) // should not happen.
return internal::squared_distance_parallel(seg1, seg2, k);
FT min2 = (dm < RT(0)) ? sq_dist(seg2.source(), seg1):
sq_dist(seg2.target(), seg1);
return (min1 < min2) ? min1 : min2;
}
}
}
template <class K>
inline typename K::FT
squared_distance(const Segment_2<K>& seg1,
const Segment_2<K>& seg2,
const K& k)
{
typedef typename K::Kernel_tag Tag;
return squared_distance(seg1, seg2, k, Tag());
}
} // namespace internal
template <class K>
inline typename K::FT
squared_distance(const Segment_2<K>& seg1,
const Segment_2<K>& seg2)
{
return K().compute_squared_distance_2_object()(seg1, seg2);
}
} // namespace CGAL
#endif // CGAL_DISTANCE_2_SEGMENT_2_SEGMENT_2_H

View File

@ -0,0 +1,136 @@
// Copyright (c) 1998-2004
// Utrecht University (The Netherlands),
// ETH Zurich (Switzerland),
// INRIA Sophia-Antipolis (France),
// Max-Planck-Institute Saarbruecken (Germany),
// and Tel-Aviv University (Israel). All rights reserved.
//
// This file is part of CGAL (www.cgal.org)
//
// $URL$
// $Id$
// SPDX-License-Identifier: LGPL-3.0-or-later OR LicenseRef-Commercial
//
//
// Author(s) : Geert-Jan Giezeman
// Michel Hoffmann <hoffmann@inf.ethz.ch>
// Andreas Fabri <Andreas.Fabri@geometryfactory.com>
#ifndef CGAL_DISTANCE_2_SEGMENT_2_TRIANGLE_2_H
#define CGAL_DISTANCE_2_SEGMENT_2_TRIANGLE_2_H
#include <CGAL/Distance_2/internal/squared_distance_utils_2.h>
#include <CGAL/Distance_2/Point_2_Triangle_2.h>
#include <CGAL/Segment_2.h>
#include <CGAL/Triangle_2.h>
namespace CGAL {
namespace internal {
template <class K>
typename K::FT
squared_distance(const typename K::Segment_2& seg,
const typename K::Triangle_2& triangle,
const K& k)
{
typedef typename K::FT FT;
typedef typename K::Point_2 Point_2;
typename K::Orientation_2 orientation = k.orientation_2_object();
int i, ind_tr1 = 0, ind_tr2 = -1, ind_seg = 0, ind1, ind2;
FT dist;
FT mindist = internal::squared_distance(seg.source(), triangle.vertex(0), k);
for(i=0; i<2; ++i)
{
const Point_2& pt = seg.vertex(i);
distance_index<K>(ind1, ind2, pt, triangle, k);
dist = internal::squared_distance_indexed(pt, triangle, ind1, ind2, k);
if(dist < mindist)
{
ind_seg = i;
ind_tr1 = ind1; ind_tr2 = ind2;
mindist = dist;
}
}
for(i=0; i<3; ++i)
{
const Point_2& pt = triangle.vertex(i);
distance_index<K>(ind1, pt, seg, k);
dist = internal::squared_distance_indexed(pt, seg, ind1, k);
if(dist < mindist)
{
ind_seg = ind1;
ind_tr1 = i; ind_tr2 = -1;
mindist = dist;
}
}
// now check if all vertices are on the right side of the separating line.
// In case of vertex-vertex smallest distance this is the case.
if(ind_tr2 == -1 && ind_seg != -1)
return mindist;
if(ind_tr2 != -1)
{
// Check if all the segment vertices lie at the same side of
// the triangle segment.
const Point_2 &vt1 = triangle.vertex(ind_tr1);
const Point_2 &vt2 = triangle.vertex(ind_tr2);
const Orientation or_s = orientation(vt1, vt2, seg.source());
if(orientation(vt1, vt2, seg.target()) != or_s)
mindist = FT(0);
}
else
{
// Check if all the triangle vertices lie
// at the same side of the segment.
const Point_2& vt1 = seg.source();
const Point_2& vt2 = seg.target();
const Orientation or_s = orientation(vt1, vt2, triangle.vertex(0));
for(i=1; i<3; ++i)
{
if(orientation(vt1, vt2, triangle.vertex(i)) != or_s)
{
mindist = FT(0);
break;
}
}
}
return mindist;
}
template <class K>
inline typename K::FT
squared_distance(const typename K::Triangle_2 & triangle,
const typename K::Segment_2 & seg,
const K& k)
{
return internal::squared_distance(seg, triangle, k);
}
} // namespace internal
template <class K>
inline typename K::FT
squared_distance(const Segment_2<K>& seg,
const Triangle_2<K>& triangle)
{
return K().compute_squared_distance_2_object()(seg, triangle);
}
template <class K>
inline typename K::FT
squared_distance(const Triangle_2<K>& triangle,
const Segment_2<K>& seg)
{
return K().compute_squared_distance_2_object()(triangle, seg);
}
} // namespace CGAL
#endif // CGAL_DISTANCE_2_SEGMENT_2_TRIANGLE_2_H

View File

@ -0,0 +1,123 @@
// Copyright (c) 1998-2004
// Utrecht University (The Netherlands),
// ETH Zurich (Switzerland),
// INRIA Sophia-Antipolis (France),
// Max-Planck-Institute Saarbruecken (Germany),
// and Tel-Aviv University (Israel). All rights reserved.
//
// This file is part of CGAL (www.cgal.org)
//
// $URL$
// $Id$
// SPDX-License-Identifier: LGPL-3.0-or-later OR LicenseRef-Commercial
//
//
// Author(s) : Geert-Jan Giezeman
// Michel Hoffmann <hoffmann@inf.ethz.ch>
// Andreas Fabri <Andreas.Fabri@geometryfactory.com>
#ifndef CGAL_DISTANCE_2_TRIANGLE_2_TRIANGLE_2_H
#define CGAL_DISTANCE_2_TRIANGLE_2_TRIANGLE_2_H
#include <CGAL/Distance_2/internal/squared_distance_utils_2.h>
#include <CGAL/Distance_2/Point_2_Point_2.h>
#include <CGAL/Distance_2/Point_2_Triangle_2.h>
#include <CGAL/Triangle_2.h>
namespace CGAL {
namespace internal {
template <class K>
typename K::FT
squared_distance(const typename K::Triangle_2& triangle1,
const typename K::Triangle_2& triangle2,
const K& k)
{
typedef typename K::FT FT;
typedef typename K::Point_2 Point_2;
typename K::Orientation_2 orientation = k.orientation_2_object();
int ind1_1 = 0, ind1_2 = -1, ind2_1 = 0, ind2_2 = -1, ind1, ind2;
FT dist;
FT mindist = internal::squared_distance(triangle1.vertex(0), triangle2.vertex(0), k);
for(int i=0; i<3; ++i)
{
const Point_2& pt = triangle1.vertex(i);
distance_index<K>(ind1, ind2, pt, triangle2, k);
dist = squared_distance_indexed(pt, triangle2, ind1, ind2, k);
if(dist < mindist)
{
ind1_1 = i; ind1_2 = -1;
ind2_1 = ind1; ind2_2 = ind2;
mindist = dist;
}
}
for(int i=0; i<3; ++i)
{
const Point_2& pt = triangle2.vertex(i);
distance_index<K>(ind1, ind2, pt, triangle1, k);
dist = squared_distance_indexed(pt, triangle1, ind1, ind2, k);
if(dist < mindist)
{
ind1_1 = ind1; ind1_2 = ind2;
ind2_1 = i; ind2_2 = -1;
mindist = dist;
}
}
// now check if all vertices are on the right side of the separating line.
if(ind1_2 == -1 && ind2_2 == -1)
return mindist;
// In case of point-segment closest distance, there is still the
// possibility of overlapping triangles. Check if all the
// vertices lie at the same side of the segment.
if(ind1_2 != -1)
{
const Point_2& vt1 = triangle1.vertex(ind1_1);
const Point_2& vt2 = triangle1.vertex(ind1_2);
const Orientation or_s = orientation(vt1, vt2, triangle2.vertex(0));
for(int i=1; i<3; ++i)
{
if(orientation(vt1, vt2, triangle2.vertex(i)) != or_s)
{
mindist = FT(0);
break;
}
}
}
else
{
const Point_2& vt1 = triangle2.vertex(ind2_1);
const Point_2& vt2 = triangle2.vertex(ind2_2);
const Orientation or_s = orientation(vt1, vt2, triangle1.vertex(0));
for(int i=1; i<3; ++i)
{
if(orientation(vt1, vt2, triangle1.vertex(i)) != or_s)
{
mindist = FT(0);
break;
}
}
}
return mindist;
}
} // namespace internal
template <class K>
inline typename K::FT
squared_distance(const Triangle_2<K>& triangle1,
const Triangle_2<K>& triangle2)
{
return K().compute_squared_distance_2_object()(triangle1, triangle2);
}
} // namespace CGAL
#endif // CGAL_DISTANCE_2_TRIANGLE_2_TRIANGLE_2_H

View File

@ -19,6 +19,7 @@
#define CGAL_SQUARED_DISTANCE_UTILS_H
#include <CGAL/determinant.h>
#include <CGAL/number_utils.h>
#include <CGAL/wmult.h>
namespace CGAL {
@ -294,7 +295,6 @@ same_direction(const typename K::Vector_2 &u,
return same_direction_tag(u,v, k, tag);
}
} // namespace internal
} //namespace CGAL

View File

@ -14,11 +14,27 @@
//
// Author(s) : Geert-Jan Giezeman
#ifndef CGAL_SQUARED_DISTANCE_2_H
#define CGAL_SQUARED_DISTANCE_2_H
#include <CGAL/squared_distance_2_1.h>
#include <CGAL/squared_distance_2_2.h>
#include <CGAL/Distance_2/Point_2_Point_2.h>
#include <CGAL/Distance_2/Point_2_Segment_2.h>
#include <CGAL/Distance_2/Point_2_Ray_2.h>
#include <CGAL/Distance_2/Point_2_Line_2.h>
#include <CGAL/Distance_2/Point_2_Triangle_2.h>
#include <CGAL/Distance_2/Segment_2_Segment_2.h>
#include <CGAL/Distance_2/Segment_2_Ray_2.h>
#include <CGAL/Distance_2/Segment_2_Line_2.h>
#include <CGAL/Distance_2/Segment_2_Triangle_2.h>
#include <CGAL/Distance_2/Ray_2_Ray_2.h>
#include <CGAL/Distance_2/Ray_2_Line_2.h>
#include <CGAL/Distance_2/Ray_2_Triangle_2.h>
#include <CGAL/Distance_2/Line_2_Line_2.h>
#include <CGAL/Distance_2/Line_2_Triangle_2.h>
#include <CGAL/Distance_2/Triangle_2_Triangle_2.h>
#endif

View File

@ -1,857 +0,0 @@
// Copyright (c) 1998-2004
// Utrecht University (The Netherlands),
// ETH Zurich (Switzerland),
// INRIA Sophia-Antipolis (France),
// Max-Planck-Institute Saarbruecken (Germany),
// and Tel-Aviv University (Israel). All rights reserved.
//
// This file is part of CGAL (www.cgal.org)
//
// $URL$
// $Id$
// SPDX-License-Identifier: LGPL-3.0-or-later OR LicenseRef-Commercial
//
//
// Author(s) : Geert-Jan Giezeman
// Michel Hoffmann <hoffmann@inf.ethz.ch>
// Andreas Fabri <Andreas.Fabri@geometryfactory.com>
#ifndef CGAL_SQUARED_DISTANCE_2_1_H
#define CGAL_SQUARED_DISTANCE_2_1_H
#include <CGAL/user_classes.h>
#include <CGAL/kernel_assertions.h>
#include <CGAL/enum.h>
#include <CGAL/wmult.h>
#include <CGAL/squared_distance_utils.h>
#include <CGAL/Kernel/global_functions_2.h>
namespace CGAL {
namespace internal {
template <class K>
inline typename K::FT
squared_distance(const typename K::Point_2 & pt1,
const typename K::Point_2 & pt2,
const K& k)
{
typename K::Vector_2 vec = k.construct_vector_2_object()(pt2, pt1);
return (typename K::FT)k.compute_squared_length_2_object()(vec);
}
template <class K>
typename K::FT
squared_distance(const typename K::Point_2 &pt,
const typename K::Line_2 &line,
const K&,
const Homogeneous_tag&)
{
typedef typename K::RT RT;
typedef typename K::FT FT;
const RT & a = line.a();
const RT & b = line.b();
const RT & w = pt.hw();
RT n = a*pt.hx() + b*pt.hy() + w * line.c();
RT d = (CGAL_NTS square(a) + CGAL_NTS square(b)) * CGAL_NTS square(w);
return Rational_traits<FT>().make_rational(CGAL_NTS square(n), d);
}
template <class K>
typename K::FT
squared_distance(const typename K::Point_2 &pt,
const typename K::Line_2 &line,
const K&,
const Cartesian_tag&)
{
typedef typename K::FT FT;
const FT & a = line.a();
const FT & b = line.b();
FT n = a*pt.x() + b*pt.y() + line.c();
FT d = CGAL_NTS square(a) + CGAL_NTS square(b);
return CGAL_NTS square(n)/d;
}
template <class K>
typename K::FT
squared_distance(const typename K::Point_2 &pt,
const typename K::Line_2 &line,
const K& k)
{
typedef typename K::Kernel_tag Tag;
Tag tag;
return squared_distance(pt, line, k, tag);
}
template <class K>
inline typename K::FT
squared_distance(const typename K::Line_2 &line,
const typename K::Point_2 &pt,
const K& k)
{
return internal::squared_distance(pt, line, k);
}
template <class K>
typename K::FT
squared_distance(const typename K::Point_2 &pt,
const typename K::Ray_2 &ray,
const K& k)
{
typedef typename K::Vector_2 Vector_2;
typename K::Construct_vector_2 construct_vector;
Vector_2 diff = construct_vector(ray.source(), pt);
const Vector_2 &dir = ray.direction().vector();
if (!is_acute_angle(dir,diff, k) )
return (typename K::FT)k.compute_squared_length_2_object()(diff);
return internal::squared_distance(pt, ray.supporting_line(), k);
}
template <class K>
inline typename K::FT
squared_distance(const typename K::Ray_2 &ray,
const typename K::Point_2 &pt,
const K& k)
{
return internal::squared_distance(pt, ray, k);
}
template <class K>
typename K::FT
squared_distance(const typename K::Point_2 &pt,
const typename K::Segment_2 &seg,
const K& k)
{
typename K::Construct_vector_2 construct_vector;
typedef typename K::Vector_2 Vector_2;
typedef typename K::RT RT;
// assert that the segment is valid (non zero length).
Vector_2 diff = construct_vector(seg.source(), pt);
Vector_2 segvec = construct_vector(seg.source(), seg.target());
RT d = wdot(diff,segvec, k);
if (d <= (RT)0)
return (typename K::FT)k.compute_squared_length_2_object()(diff);
RT e = wdot(segvec,segvec, k);
if (wmult((K*)0 ,d, segvec.hw()) > wmult((K*)0, e, diff.hw()))
return internal::squared_distance(pt, seg.target(), k);
return internal::squared_distance(pt, seg.supporting_line(), k);
}
template <class K>
inline typename K::FT
squared_distance(const typename K::Segment_2 &seg,
const typename K::Point_2 &pt,
const K& k)
{
return internal::squared_distance(pt, seg, k);
}
template <class K>
typename K::FT
squared_distance_parallel(const typename K::Segment_2 &seg1,
const typename K::Segment_2 &seg2,
const K& k)
{
typedef typename K::Vector_2 Vector_2;
const Vector_2 &dir1 = seg1.direction().vector();
const Vector_2 &dir2 = seg2.direction().vector();
if (same_direction(dir1, dir2, k)) {
if (!is_acute_angle(seg1.source(), seg1.target(), seg2.source(), k))
return internal::squared_distance(seg1.target(), seg2.source(), k);
if (!is_acute_angle(seg1.target(), seg1.source(), seg2.target(), k))
return internal::squared_distance(seg1.source(), seg2.target(), k);
} else {
if (!is_acute_angle(seg1.source(), seg1.target(), seg2.target(), k))
return internal::squared_distance(seg1.target(), seg2.target(), k);
if (!is_acute_angle(seg1.target(), seg1.source(), seg2.source(), k))
return internal::squared_distance(seg1.source(), seg2.source(), k);
}
return internal::squared_distance(seg2.source(), seg1.supporting_line(), k);
}
template <class K>
inline typename K::RT
_distance_measure_sub(const typename K::RT &startwcross,
const typename K::RT &endwcross,
const typename K::Point_2 &start,
const typename K::Point_2 &end)
{
return CGAL_NTS abs(wmult((K*)0, startwcross, end.hw())) -
CGAL_NTS abs(wmult((K*)0, endwcross, start.hw()));
}
template <class K>
typename K::FT
squared_distance(const typename K::Segment_2 &seg1,
const typename K::Segment_2 &seg2,
const K& k,
const Cartesian_tag&)
{
typedef typename K::RT RT;
typedef typename K::FT FT;
bool crossing1, crossing2;
RT c1s, c1e, c2s, c2e;
if (seg1.source() == seg1.target())
return internal::squared_distance(seg1.source(), seg2, k);
if (seg2.source() == seg2.target())
return internal::squared_distance(seg2.source(), seg1, k);
Orientation o1s = orientation(seg2.source(), seg2.target(), seg1.source());
Orientation o1e = orientation(seg2.source(), seg2.target(), seg1.target());
if (o1s == RIGHT_TURN) {
crossing1 = (o1e != RIGHT_TURN);
} else {
if (o1e != LEFT_TURN) {
if (o1s == COLLINEAR && o1e == COLLINEAR)
return internal::squared_distance_parallel(seg1, seg2, k);
crossing1 = true;
} else {
crossing1 = (o1s == COLLINEAR);
}
}
Orientation o2s = orientation(seg1.source(), seg1.target(), seg2.source());
Orientation o2e = orientation(seg1.source(), seg1.target(), seg2.target());
if (o2s == RIGHT_TURN) {
crossing2 = (o2e != RIGHT_TURN);
} else {
if (o2e != LEFT_TURN) {
if (o2s == COLLINEAR && o2e == COLLINEAR)
return internal::squared_distance_parallel(seg1, seg2, k);
crossing2 = true;
} else {
crossing2 = (o2s == COLLINEAR);
}
}
if (crossing1) {
if (crossing2)
return (FT)0;
c2s = CGAL::abs(wcross(seg1.source(), seg1.target(), seg2.source(), k));
c2e = CGAL::abs(wcross(seg1.source(), seg1.target(), seg2.target(), k));
Comparison_result dm = CGAL::compare(c2s,c2e);
if (dm == SMALLER) {
return internal::squared_distance(seg2.source(), seg1, k);
} else {
if (dm == LARGER) {
return internal::squared_distance(seg2.target(), seg1, k);
} else {
// parallel, should not happen (no crossing)
return internal::squared_distance_parallel(seg1, seg2, k);
}
}
} else {
c1s = CGAL::abs(wcross(seg2.source(), seg2.target(), seg1.source(), k));
c1e = CGAL::abs(wcross(seg2.source(), seg2.target(), seg1.target(), k));
Comparison_result dm = CGAL::compare(c1s,c1e);
if (crossing2) {
if (dm == SMALLER) {
return internal::squared_distance(seg1.source(), seg2, k);
} else {
if (dm == LARGER) {
return internal::squared_distance(seg1.target(), seg2, k);
} else {
// parallel, should not happen (no crossing)
return internal::squared_distance_parallel(seg1, seg2, k);
}
}
} else {
FT min1, min2;
if (dm == EQUAL)
return internal::squared_distance_parallel(seg1, seg2, k);
min1 = (dm == SMALLER) ?
internal::squared_distance(seg1.source(), seg2, k):
internal::squared_distance(seg1.target(), seg2, k);
c2s = CGAL::abs(wcross(seg1.source(), seg1.target(), seg2.source(), k));
c2e = CGAL::abs(wcross(seg1.source(), seg1.target(), seg2.target(), k));
dm = CGAL::compare(c2s,c2e);
if (dm == EQUAL) // should not happen.
return internal::squared_distance_parallel(seg1, seg2, k);
min2 = (dm == SMALLER) ?
internal::squared_distance(seg2.source(), seg1, k):
internal::squared_distance(seg2.target(), seg1, k);
return (min1 < min2) ? min1 : min2;
}
}
}
template <class K>
typename K::FT
squared_distance(const typename K::Segment_2 &seg1,
const typename K::Segment_2 &seg2,
const K& k,
const Homogeneous_tag&)
{
typedef typename K::RT RT;
typedef typename K::FT FT;
bool crossing1, crossing2;
RT c1s, c1e, c2s, c2e;
if (seg1.source() == seg1.target())
return internal::squared_distance(seg1.source(), seg2, k);
if (seg2.source() == seg2.target())
return internal::squared_distance(seg2.source(), seg1, k);
c1s = wcross(seg2.source(), seg2.target(), seg1.source(), k);
c1e = wcross(seg2.source(), seg2.target(), seg1.target(), k);
c2s = wcross(seg1.source(), seg1.target(), seg2.source(), k);
c2e = wcross(seg1.source(), seg1.target(), seg2.target(), k);
if (c1s < RT(0)) {
crossing1 = (c1e >= RT(0));
} else {
if (c1e <= RT(0)) {
if (c1s == RT(0) && c1e == RT(0))
return internal::squared_distance_parallel(seg1, seg2, k);
crossing1 = true;
} else {
crossing1 = (c1s == RT(0));
}
}
if (c2s < RT(0)) {
crossing2 = (c2e >= RT(0));
} else {
if (c2e <= RT(0)) {
if (c2s == RT(0) && c2e == RT(0))
return internal::squared_distance_parallel(seg1, seg2, k);
crossing2 = true;
} else {
crossing2 = (c2s == RT(0));
}
}
if (crossing1) {
if (crossing2)
return (FT)0;
RT dm;
dm = _distance_measure_sub<K>(c2s,c2e, seg2.source(), seg2.target());
if (dm < RT(0)) {
return internal::squared_distance(seg2.source(), seg1, k);
} else {
if (dm > RT(0)) {
return internal::squared_distance(seg2.target(), seg1, k);
} else {
// parallel, should not happen (no crossing)
return internal::squared_distance_parallel(seg1, seg2, k);
}
}
} else {
if (crossing2) {
RT dm;
dm =
_distance_measure_sub<K>(c1s, c1e,seg1.source(),seg1.target());
if (dm < RT(0)) {
return internal::squared_distance(seg1.source(), seg2, k);
} else {
if (dm > RT(0)) {
return internal::squared_distance(seg1.target(), seg2, k);
} else {
// parallel, should not happen (no crossing)
return internal::squared_distance_parallel(seg1, seg2, k);
}
}
} else {
FT min1, min2;
RT dm = _distance_measure_sub<K>(
c1s, c1e, seg1.source(), seg1.target());
if (dm == RT(0))
return internal::squared_distance_parallel(seg1, seg2, k);
min1 = (dm < RT(0)) ?
internal::squared_distance(seg1.source(), seg2, k):
internal::squared_distance(seg1.target(), seg2, k);
dm = _distance_measure_sub<K>(
c2s, c2e, seg2.source(), seg2.target());
if (dm == RT(0)) // should not happen.
return internal::squared_distance_parallel(seg1, seg2, k);
min2 = (dm < RT(0)) ?
internal::squared_distance(seg2.source(), seg1, k):
internal::squared_distance(seg2.target(), seg1, k);
return (min1 < min2) ? min1 : min2;
}
}
}
template <class K>
inline typename K::RT
_distance_measure_sub(const typename K::RT &startwcross,
const typename K::RT &endwcross,
const typename K::Vector_2 &start,
const typename K::Vector_2 &end)
{
return CGAL_NTS abs(wmult((K*)0, startwcross, end.hw())) -
CGAL_NTS abs(wmult((K*)0, endwcross, start.hw()));
}
template <class K>
typename K::FT
squared_distance_parallel(const typename K::Segment_2 &seg,
const typename K::Ray_2 &ray,
const K& k)
{
typedef typename K::Vector_2 Vector_2;
const Vector_2 &dir1 = seg.direction().vector();
const Vector_2 &dir2 = ray.direction().vector();
if (same_direction(dir1, dir2, k)) {
if (!is_acute_angle(seg.source(), seg.target(), ray.source(), k))
return internal::squared_distance(seg.target(), ray.source(), k);
} else {
if (!is_acute_angle(seg.target(), seg.source(), ray.source(), k))
return internal::squared_distance(seg.source(), ray.source(), k);
}
return internal::squared_distance(ray.source(), seg.supporting_line(), k);
}
template <class K>
typename K::FT
squared_distance(const typename K::Segment_2 &seg,
const typename K::Ray_2 &ray,
const K& k)
{
typename K::Construct_vector_2 construct_vector;
typedef typename K::RT RT;
typedef typename K::FT FT;
typedef typename K::Vector_2 Vector_2;
const Vector_2 &raydir = ray.direction().vector();
Vector_2 startvec(construct_vector(ray.source(), seg.source()));
Vector_2 endvec(construct_vector(ray.source(), seg.target()));
typename K::Orientation_2 orientation;
bool crossing1, crossing2;
RT c1s, c1e;
if (seg.source() == seg.target())
return internal::squared_distance(seg.source(), ray, k);
c1s = wcross(raydir, startvec, k);
c1e = wcross(raydir, endvec, k);
if (c1s < RT(0)) {
crossing1 = (c1e >= RT(0));
} else {
if (c1e <= RT(0)) {
if (c1s == RT(0) && c1e == RT(0))
return internal::squared_distance_parallel(seg, ray, k);
crossing1 = true;
} else {
crossing1 = (c1s == RT(0));
}
}
switch (orientation(seg.source(), seg.target(), ray.source())) {
case LEFT_TURN:
crossing2 = right_turn(construct_vector(seg.source(), seg.target()), raydir, k);
break;
case RIGHT_TURN:
crossing2 = left_turn(construct_vector(seg.source(), seg.target()), raydir, k);
break;
default:
crossing2 = true;
break;
}
if (crossing1) {
if (crossing2)
return FT(0);
return internal::squared_distance(ray.source(), seg, k);
} else {
if (crossing2) {
RT dm;
dm = _distance_measure_sub<K>(c1s, c1e, startvec, endvec);
if (dm < RT(0)) {
return internal::squared_distance(seg.source(), ray, k);
} else {
if (dm > RT(0)) {
return internal::squared_distance(seg.target(), ray, k);
} else {
// parallel, should not happen (no crossing)
return internal::squared_distance_parallel(seg, ray, k);
}
}
} else {
FT min1, min2;
RT dm = _distance_measure_sub<K>(c1s, c1e, startvec, endvec);
if (dm == RT(0))
return internal::squared_distance_parallel(seg, ray, k);
min1 = (dm < RT(0))
? internal::squared_distance(seg.source(), ray, k)
: internal::squared_distance(seg.target(), ray, k);
min2 = internal::squared_distance(ray.source(), seg, k);
return (min1 < min2) ? min1 : min2;
}
}
}
template <class K>
inline typename K::FT
squared_distance(const typename K::Ray_2 &ray,
const typename K::Segment_2 &seg,
const K& k)
{
return internal::squared_distance(seg, ray, k);
}
template <class K>
typename K::FT
_sqd_to_line(const typename K::Vector_2 &diff,
const typename K::RT & wcross,
const typename K::Vector_2 &dir )
{
typedef typename K::RT RT;
typedef typename K::FT FT;
RT numerator = CGAL_NTS square(wcross);
RT denominator = wmult((K*)0, RT(wdot(dir,dir, K())),
diff.hw(), diff.hw());
return Rational_traits<FT>().make_rational(numerator, denominator);
}
template <class K>
typename K::FT
squared_distance(const typename K::Segment_2 &seg,
const typename K::Line_2 &line,
const K& k)
{
typename K::Construct_vector_2 construct_vector;
typedef typename K::RT RT;
typedef typename K::FT FT;
typedef typename K::Vector_2 Vector_2;
typedef typename K::Point_2 Point_2;
const Vector_2 &linedir = line.direction().vector();
const Point_2 &linepoint = line.point();
Vector_2 startvec(construct_vector(linepoint, seg.source()));
Vector_2 endvec(construct_vector(linepoint, seg.target()));
bool crossing1;
RT c1s, c1e;
if (seg.source() == seg.target())
return internal::squared_distance(seg.source(), line, k);
c1s = wcross(linedir, startvec, k);
c1e = wcross(linedir, endvec, k);
if (c1s < RT(0)) {
crossing1 = (c1e >= RT(0));
} else {
if (c1e <= RT(0)) {
crossing1 = true;
} else {
crossing1 = (c1s == RT(0));
}
}
if (crossing1) {
return (FT)0;
} else {
RT dm;
dm = _distance_measure_sub<K>(c1s, c1e, startvec, endvec);
if (dm <= RT(0)) {
return _sqd_to_line<K>(startvec, c1s, linedir);
} else {
return _sqd_to_line<K>(endvec, c1e, linedir);
}
}
}
template <class K>
inline typename K::FT
squared_distance(const typename K::Line_2 &line,
const typename K::Segment_2 &seg,
const K& k)
{
return internal::squared_distance(seg, line, k);
}
template <class K>
typename K::FT
ray_ray_squared_distance_parallel(
const typename K::Vector_2 &ray1dir,
const typename K::Vector_2 &ray2dir,
const typename K::Vector_2 &from1to2,
const K& k)
{
typedef typename K::RT RT;
typedef typename K::FT FT;
if (!is_acute_angle(ray1dir, from1to2, k)) {
if (!same_direction(ray1dir, ray2dir, k))
return (typename K::FT)k.compute_squared_length_2_object()(from1to2);
}
RT wcr, w;
wcr = wcross(ray1dir, from1to2, k);
w = from1to2.hw();
return (typename K::FT)(FT(wcr*wcr)
/ FT(wmult((K*)0, RT(wdot(ray1dir, ray1dir, k)), w, w)));
}
template <class K>
typename K::FT
squared_distance(const typename K::Ray_2 &ray1,
const typename K::Ray_2 &ray2,
const K& k)
{
typename K::Construct_vector_2 construct_vector;
typedef typename K::Vector_2 Vector_2;
typedef typename K::FT FT;
const Vector_2 &ray1dir = ray1.direction().vector();
const Vector_2 &ray2dir = ray2.direction().vector();
Vector_2 diffvec(construct_vector(ray1.source(),ray2.source()));
bool crossing1, crossing2;
switch (orientation(ray1dir, ray2dir, k)) {
case COUNTERCLOCKWISE:
crossing1 = !clockwise(diffvec, ray2dir, k);
crossing2 = !counterclockwise(ray1dir, diffvec, k);
break;
case CLOCKWISE:
crossing1 = !counterclockwise(diffvec, ray2dir, k);
crossing2 = !clockwise(ray1dir, diffvec, k);
break;
default:
return ray_ray_squared_distance_parallel(ray1dir,ray2dir,diffvec,k);
}
if (crossing1) {
if (crossing2)
return (FT)0;
return internal::squared_distance(ray2.source(), ray1, k);
} else {
if (crossing2) {
return internal::squared_distance(ray1.source(), ray2, k);
} else {
FT min1, min2;
min1 = internal::squared_distance(ray1.source(), ray2, k);
min2 = internal::squared_distance(ray2.source(), ray1, k);
return (min1 < min2) ? min1 : min2;
}
}
}
template <class K>
typename K::FT
squared_distance(const typename K::Line_2 &line,
const typename K::Ray_2 &ray,
const K& k)
{
typename K::Construct_vector_2 construct_vector;
typedef typename K::FT FT;
typedef typename K::Vector_2 Vector_2;
Vector_2 normalvec(line.a(), line.b());
Vector_2 diff = construct_vector(line.point(), ray.source());
FT sign_dist = k.compute_scalar_product_2_object()(diff,normalvec);
if (sign_dist < FT(0)) {
if (is_acute_angle(normalvec, ray.direction().vector(), k) )
return (FT)0;
} else {
if (is_obtuse_angle(normalvec, ray.direction().vector(), k) )
return (FT)0;
}
return (typename K::FT)((sign_dist*sign_dist)/k.compute_squared_length_2_object()(normalvec));
}
template <class K>
inline typename K::FT
squared_distance(const typename K::Ray_2 &ray,
const typename K::Line_2 &line,
const K& k)
{
return internal::squared_distance(line, ray, k);
}
template <class K>
inline typename K::FT
squared_distance(const typename K::Line_2 &line1,
const typename K::Line_2 &line2,
const K& k)
{
typedef typename K::FT FT;
if (internal::parallel(line1, line2, k))
return internal::squared_distance(line1.point(), line2, k);
else
return (FT)0;
}
template <class K>
void
distance_index(int &ind,
const typename K::Point_2 &pt,
const typename K::Ray_2 &ray,
const K& k)
{
typename K::Construct_vector_2 construct_vector;
if (!is_acute_angle(ray.direction().vector(), construct_vector(ray.source(), pt), k)) {
ind = 0;
return;
}
ind = -1;
}
template <class K>
void
distance_index(int &ind,
const typename K::Point_2 &pt,
const typename K::Segment_2 &seg,
const K& k)
{
if (!is_acute_angle(seg.target(),seg.source(),pt, k)) {
ind = 0;
return;
}
if (!is_acute_angle(seg.source(),seg.target(),pt, k)) {
ind = 1;
return;
}
ind = -1;
}
template <class K>
inline typename K::FT
squared_distance_indexed(const typename K::Point_2 &pt,
const typename K::Ray_2 &ray,
int ind,
const K& k)
{
if (ind == 0)
return internal::squared_distance(pt, ray.source(), k);
return internal::squared_distance(pt, ray.supporting_line(), k);
}
template <class K>
inline typename K::FT
squared_distance_indexed(const typename K::Point_2 &pt,
const typename K::Segment_2 &seg,
int ind,
const K& k)
{
if (ind == 0)
return internal::squared_distance(pt, seg.source(), k);
if (ind == 1)
return internal::squared_distance(pt, seg.target(), k);
return internal::squared_distance(pt, seg.supporting_line(), k);
}
} // namespace internal
template <class K>
inline typename K::FT
squared_distance(const Point_2<K> & pt1, const Point_2<K> & pt2)
{
return internal::squared_distance(pt1, pt2, K());
}
template <class K>
inline typename K::FT
squared_distance(const Point_2<K> &pt, const Line_2<K> &line)
{
return internal::squared_distance(pt, line, K());
}
template <class K>
inline typename K::FT
squared_distance(const Line_2<K> & line, const Point_2<K> & pt)
{
return squared_distance(pt, line);
}
template <class K>
inline typename K::FT
squared_distance(const Point_2<K> &pt, const Ray_2<K> &ray)
{
return internal::squared_distance(pt, ray, K());
}
template <class K>
inline typename K::FT
squared_distance(const Ray_2<K> & ray, const Point_2<K> & pt)
{
return squared_distance(pt, ray);
}
template <class K>
inline typename K::FT
squared_distance(const Point_2<K> &pt, const Segment_2<K> &seg)
{
return internal::squared_distance(pt, seg, K());
}
template <class K>
inline typename K::FT
squared_distance(const Segment_2<K> & seg, const Point_2<K> & pt)
{
return internal::squared_distance(pt, seg, K());
}
template <class K>
inline typename K::FT
squared_distance(const Segment_2<K> &seg1, const Segment_2<K> &seg2)
{
typedef typename K::Kernel_tag Tag;
return internal::squared_distance(seg1, seg2, K(), Tag());
}
template <class K>
inline typename K::FT
squared_distance(const Segment_2<K> &seg, const Ray_2<K> &ray)
{
return internal::squared_distance(seg, ray, K());
}
template <class K>
inline typename K::FT
squared_distance(const Ray_2<K> & ray, const Segment_2<K> & seg)
{
return internal::squared_distance(seg, ray, K());
}
template <class K>
inline typename K::FT
squared_distance(const Segment_2<K> &seg, const Line_2<K> &line)
{
return internal::squared_distance(seg, line, K());
}
template <class K>
inline typename K::FT
squared_distance(const Line_2<K> & line, const Segment_2<K> & seg)
{
return internal::squared_distance(seg, line, K());
}
template <class K>
inline typename K::FT
squared_distance(const Ray_2<K> &ray1, const Ray_2<K> &ray2)
{
return internal::squared_distance(ray1, ray2, K());
}
template <class K>
inline typename K::FT
squared_distance(const Line_2<K> &line, const Ray_2<K> &ray)
{
return internal::squared_distance(line, ray, K());
}
template <class K>
inline typename K::FT
squared_distance(const Ray_2<K> & ray, const Line_2<K> & line)
{
return internal::squared_distance(line, ray, K());
}
template <class K>
inline typename K::FT
squared_distance(const Line_2<K> &line1, const Line_2<K> &line2)
{
return internal::squared_distance(line1, line2, K());
}
} //namespace CGAL
#endif

View File

@ -1,566 +0,0 @@
// Copyright (c) 1998-2004
// Utrecht University (The Netherlands),
// ETH Zurich (Switzerland),
// INRIA Sophia-Antipolis (France),
// Max-Planck-Institute Saarbruecken (Germany),
// and Tel-Aviv University (Israel). All rights reserved.
//
// This file is part of CGAL (www.cgal.org)
//
// $URL$
// $Id$
// SPDX-License-Identifier: LGPL-3.0-or-later OR LicenseRef-Commercial
//
//
// Author(s) : Geert-Jan Giezeman
#ifndef CGAL_SQUARED_DISTANCE_2_2_H
#define CGAL_SQUARED_DISTANCE_2_2_H
#include <CGAL/user_classes.h>
#include <CGAL/kernel_assertions.h>
#include <CGAL/Point_2.h>
#include <CGAL/Segment_2.h>
#include <CGAL/Line_2.h>
#include <CGAL/Ray_2.h>
#include <CGAL/Triangle_2.h>
#include <CGAL/enum.h>
#include <CGAL/wmult.h>
#include <CGAL/squared_distance_utils.h>
#include <CGAL/squared_distance_2_1.h>
namespace CGAL {
namespace internal {
template <class K>
void
distance_index(int &ind1,
int &ind2,
const typename K::Point_2 &pt,
const typename K::Triangle_2 &triangle,
const K& k )
{
typename K::Left_turn_2 leftturn = k.left_turn_2_object();
typedef typename K::Point_2 Point_2;
const Point_2 &vt0 = triangle.vertex(0);
const Point_2 &vt1 = triangle.vertex(1);
const Point_2 &vt2 = triangle.vertex(2);
if (leftturn(vt0, vt1, vt2)) {
if (leftturn(pt, vt1, vt0)) {
if (!is_acute_angle(vt0, vt1, pt, k)) {
if (leftturn(pt, vt2, vt1)) {
if (!is_acute_angle(vt1, vt2, pt, k)) {
ind1 = 2; ind2 = -1;
return;
}
if (!is_acute_angle(vt2, vt1, pt, k)) {
ind1 = 1; ind2 = -1;
return;
}
ind1 = 1; ind2 = 2;
return;
}
ind1 = 1; ind2 = -1;
return;
}
if (!is_acute_angle(vt1, vt0, pt, k)) {
if (leftturn(pt, vt0, vt2)) {
if (!is_acute_angle(vt0, vt2, pt, k)) {
ind1 = 2; ind2 = -1;
return;
}
if (!is_acute_angle(vt2, vt0, pt, k)) {
ind1 = 0; ind2 = -1;
return;
}
ind1 = 2; ind2 = 0;
return;
}
ind1 = 0; ind2 = -1;
return;
}
ind1 = 0; ind2 = 1;
return;
} else {
if (leftturn(pt, vt2, vt1)) {
if (!is_acute_angle(vt1, vt2, pt, k)) {
if (leftturn(pt, vt0, vt2)) {
if (!is_acute_angle(vt0, vt2, pt, k)) {
ind1 = 2; ind2 = -1;
return;
}
if (!is_acute_angle(vt2, vt0, pt, k)) {
ind1 = 0; ind2 = -1;
return;
}
ind1 = 2; ind2 = 0;
return;
}
ind1 = 0; ind2 = -1;
return;
}
if (!is_acute_angle(vt2, vt1, pt, k)) {
ind1 = 1; ind2 = -1;
return;
}
ind1 = 1; ind2 = 2;
return;
} else {
if (leftturn(pt, vt0, vt2)) {
if (!is_acute_angle(vt2, vt0, pt, k)) {
ind1 = 0; ind2 = -1;
return;
}
if (!is_acute_angle(vt0, vt2, pt, k)) {
ind1 = 2; ind2 = -1;
return;
}
ind1 = 2; ind2 = 0;
return;
} else {
ind1 = -1; ind2 = -1; // point inside or on boundary.
return;
}
}
}
} else {
if (leftturn(pt, vt2, vt0)) {
if (!is_acute_angle(vt0, vt2, pt, k)) {
if (leftturn(pt, vt1, vt2)) {
if (!is_acute_angle(vt2, vt1, pt, k)) {
ind1 = 1; ind2 = -1;
return;
}
if (!is_acute_angle(vt1, vt2, pt, k)) {
ind1 = 2; ind2 = -1;
return;
}
ind1 = 2; ind2 = 1;
return;
}
ind1 = 2; ind2 = -1;
return;
}
if (!is_acute_angle(vt2, vt0, pt, k)) {
if (leftturn(pt, vt0, vt1)) {
if (!is_acute_angle(vt0, vt1, pt, k)) {
ind1 = 1; ind2 = -1;
return;
}
if (!is_acute_angle(vt1, vt0, pt, k)) {
ind1 = 0; ind2 = -1;
return;
}
ind1 = 1; ind2 = 0;
return;
}
ind1 = 0; ind2 = -1;
return;
}
ind1 = 0; ind2 = 2;
return;
} else {
if (leftturn(pt, vt1, vt2)) {
if (!is_acute_angle(vt2, vt1, pt, k)) {
if (leftturn(pt, vt0, vt1)) {
if (!is_acute_angle(vt0, vt1, pt, k)) {
ind1 = 1; ind2 = -1;
return;
}
if (!is_acute_angle(vt1, vt0, pt, k)) {
ind1 = 0; ind2 = -1;
return;
}
ind1 = 1; ind2 = 0;
return;
}
ind1 = 0; ind2 = -1;
return;
}
if (!is_acute_angle(vt1, vt2, pt, k)) {
ind1 = 2; ind2 = -1;
return;
}
ind1 = 2; ind2 = 1;
return;
} else {
if (leftturn(pt, vt0, vt1)) {
if (!is_acute_angle(vt1, vt0, pt, k)) {
ind1 = 0; ind2 = -1;
return;
}
if (!is_acute_angle(vt0, vt1, pt, k)) {
ind1 = 1; ind2 = -1;
return;
}
ind1 = 1; ind2 = 0;
return;
} else {
ind1 = -1; ind2 = -1; // point inside or on boundary.
return;
}
}
}
}
}
template <class K>
typename K::FT
squared_distance_indexed(const typename K::Point_2 &pt,
const typename K::Triangle_2 &triangle,
int ind1, int ind2,
const K& k)
{
typedef typename K::FT FT;
typedef typename K::Line_2 Line_2;
if (ind1 == -1)
return FT(0);
if (ind2 == -1)
return internal::squared_distance(pt, triangle.vertex(ind1), k);
return internal::squared_distance(pt,
Line_2(triangle.vertex(ind1), triangle.vertex(ind2)),
k);
}
template <class K>
typename K::FT
squared_distance(const typename K::Point_2 &pt,
const typename K::Triangle_2 &triangle,
const K& k)
{
int ind1,ind2;
distance_index<K>(ind1, ind2, pt, triangle, k);
return squared_distance_indexed(pt, triangle, ind1, ind2, k);
}
template <class K>
inline typename K::FT
squared_distance(const typename K::Triangle_2 & triangle,
const typename K::Point_2 & pt,
const K& k)
{
return internal::squared_distance(pt, triangle, k);
}
template <class K>
typename K::FT
squared_distance(const typename K::Line_2 &line,
const typename K::Triangle_2 &triangle,
const K& k)
{
typedef typename K::FT FT;
Oriented_side side0;
side0 = line.oriented_side(triangle.vertex(0));
if (line.oriented_side(triangle.vertex(1)) != side0)
return FT(0);
if (line.oriented_side(triangle.vertex(2)) != side0)
return FT(0);
FT mindist, dist;
int i;
mindist = internal::squared_distance(triangle.vertex(0),line,k);
for (i=1; i<3; i++) {
dist = internal::squared_distance(triangle.vertex(i),line,k);
if (dist < mindist)
mindist = dist;
}
return mindist;
}
template <class K>
inline typename K::FT
squared_distance(const typename K::Triangle_2 & triangle,
const typename K::Line_2 & line,
const K& k)
{
return internal::squared_distance(line, triangle, k);
}
template <class K>
typename K::FT
squared_distance(const typename K::Ray_2 &ray,
const typename K::Triangle_2 &triangle,
const K& k)
{
typedef typename K::FT FT;
typedef typename K::Point_2 Point_2;
typedef typename K::Line_2 Line_2;
int i, ind_tr1, ind_tr2, ind_ray = 0, ind1;
FT mindist, dist;
distance_index<K>(ind_tr1, ind_tr2, ray.source(), triangle, k);
mindist =
squared_distance_indexed(ray.source(), triangle, ind_tr1, ind_tr2, k);
for (i=0; i<3; i++) {
const Point_2& pt = triangle.vertex(i);
distance_index<K>(ind1, pt, ray, k);
dist = squared_distance_indexed(pt, ray, ind1, k);
if (dist < mindist) {
ind_ray = ind1;
ind_tr1 = i; ind_tr2 = -1;
mindist = dist;
}
}
// now check if all vertices are on the right side of the separating line.
// In case of vertex-vertex smallest distance this is the case.
if (ind_tr2 == -1 && ind_ray != -1)
return mindist;
if (ind_tr2 != -1) {
// Check if all the segment vertices lie at the same side of
// the triangle segment.
const Point_2 &vt1 = triangle.vertex(ind_tr1);
const Point_2 &vt2 = triangle.vertex(ind_tr2);
if (clockwise(ray.direction().vector(), vt2-vt1, k)) {
mindist = FT(0);
}
} else {
// Check if all the triangle vertices lie
// at the same side of the segment.
const Line_2 &sl = ray.supporting_line();
Oriented_side or_s = sl.oriented_side(triangle.vertex(0));
for (i=1; i<3; i++) {
if (sl.oriented_side(triangle.vertex(i)) != or_s) {
mindist = FT(0);
break;
}
}
}
return mindist;
}
template <class K>
inline typename K::FT
squared_distance(const typename K::Triangle_2 & triangle,
const typename K::Ray_2 & ray,
const K& k)
{
return internal::squared_distance(ray, triangle, k);
}
template <class K>
typename K::FT
squared_distance(const typename K::Segment_2 &seg,
const typename K::Triangle_2 &triangle,
const K& k)
{
typedef typename K::FT FT;
typedef typename K::Point_2 Point_2;
typename K::Orientation_2 orientation;
int i, ind_tr1 = 0, ind_tr2 = -1, ind_seg = 0, ind1, ind2;
FT mindist, dist;
mindist = internal::squared_distance(seg.source(), triangle.vertex(0), k);
for (i=0; i<2; i++) {
const Point_2 &pt = seg.vertex(i);
distance_index<K>(ind1, ind2, pt, triangle, k);
dist = internal::squared_distance_indexed(pt, triangle, ind1, ind2, k);
if (dist < mindist) {
ind_seg = i;
ind_tr1 = ind1; ind_tr2 = ind2;
mindist = dist;
}
}
for (i=0; i<3; i++) {
const Point_2& pt = triangle.vertex(i);
distance_index<K>(ind1, pt, seg, k);
dist = internal::squared_distance_indexed(pt, seg, ind1, k);
if (dist < mindist) {
ind_seg = ind1;
ind_tr1 = i; ind_tr2 = -1;
mindist = dist;
}
}
// now check if all vertices are on the right side of the separating line.
// In case of vertex-vertex smallest distance this is the case.
if (ind_tr2 == -1 && ind_seg != -1)
return mindist;
if (ind_tr2 != -1) {
// Check if all the segment vertices lie at the same side of
// the triangle segment.
const Point_2 &vt1 = triangle.vertex(ind_tr1);
const Point_2 &vt2 = triangle.vertex(ind_tr2);
Orientation or_s = orientation(vt1, vt2, seg.source());
if (orientation(vt1, vt2, seg.target()) != or_s) {
mindist = FT(0);
}
} else {
// Check if all the triangle vertices lie
// at the same side of the segment.
const Point_2 &vt1 = seg.source();
const Point_2 &vt2 = seg.target();
Orientation or_s = orientation(vt1, vt2, triangle.vertex(0));
for (i=1; i<3; i++) {
if (orientation(vt1, vt2, triangle.vertex(i)) != or_s) {
mindist = FT(0);
break;
}
}
}
return mindist;
}
template <class K>
inline typename K::FT
squared_distance(const typename K::Triangle_2 & triangle,
const typename K::Segment_2 & seg,
const K& k)
{
return internal::squared_distance(seg, triangle, k);
}
template <class K>
typename K::FT
squared_distance(const typename K::Triangle_2 &triangle1,
const typename K::Triangle_2 &triangle2,
const K& k)
{
typedef typename K::FT FT;
typedef typename K::Point_2 Point_2;
typename K::Orientation_2 orientation;
int i, ind1_1 = 0,ind1_2 = -1, ind2_1 = 0, ind2_2 = -1, ind1, ind2;
FT mindist, dist;
mindist =
internal::squared_distance(triangle1.vertex(0), triangle2.vertex(0), k);
for (i=0; i<3; i++) {
const Point_2& pt = triangle1.vertex(i);
distance_index<K>(ind1, ind2, pt, triangle2, k);
dist = squared_distance_indexed(pt, triangle2, ind1, ind2, k);
if (dist < mindist) {
ind1_1 = i; ind1_2 = -1;
ind2_1 = ind1; ind2_2 = ind2;
mindist = dist;
}
}
for (i=0; i<3; i++) {
const Point_2& pt = triangle2.vertex(i);
distance_index<K>(ind1, ind2, pt, triangle1, k);
dist = squared_distance_indexed(pt, triangle1, ind1, ind2, k);
if (dist < mindist) {
ind1_1 = ind1; ind1_2 = ind2;
ind2_1 = i; ind2_2 = -1;
mindist = dist;
}
}
// now check if all vertices are on the right side of the
// separating line.
if (ind1_2 == -1 && ind2_2 == -1)
return mindist;
// In case of point-segment closest distance, there is still the
// possibility of overlapping triangles. Check if all the
// vertices lie at the same side of the segment.
if (ind1_2 != -1) {
const Point_2 &vt1 = triangle1.vertex(ind1_1);
const Point_2 &vt2 = triangle1.vertex(ind1_2);
Orientation or_s = orientation(vt1, vt2, triangle2.vertex(0));
for (i=1; i<3; i++) {
if (orientation(vt1, vt2, triangle2.vertex(i)) != or_s) {
mindist = FT(0);
break;
}
}
} else {
const Point_2 &vt1 = triangle2.vertex(ind2_1);
const Point_2 &vt2 = triangle2.vertex(ind2_2);
Orientation or_s = orientation(vt1, vt2, triangle1.vertex(0));
for (i=1; i<3; i++) {
if (orientation(vt1, vt2, triangle1.vertex(i)) != or_s) {
mindist = FT(0);
break;
}
}
}
return mindist;
}
} // namespace internal
template <class K>
inline typename K::FT
squared_distance(const Point_2<K> &pt,
const Triangle_2<K> &triangle)
{
return internal::squared_distance(pt, triangle, K());
}
template <class K>
inline typename K::FT
squared_distance(const Triangle_2<K> &triangle,
const Point_2<K> &pt)
{
return internal::squared_distance(pt, triangle, K());
}
template <class K>
inline typename K::FT
squared_distance(const Line_2<K> &line,
const Triangle_2<K> &triangle)
{
return internal::squared_distance(line, triangle, K());
}
template <class K>
inline typename K::FT
squared_distance(const Triangle_2<K> &triangle,
const Line_2<K> &line)
{
return internal::squared_distance(line, triangle, K());
}
template <class K>
inline typename K::FT
squared_distance(const Ray_2<K> &ray,
const Triangle_2<K> &triangle)
{
return internal::squared_distance(ray, triangle, K());
}
template <class K>
inline typename K::FT
squared_distance(const Triangle_2<K> &triangle,
const Ray_2<K> &ray)
{
return internal::squared_distance(ray, triangle, K());
}
template <class K>
inline typename K::FT
squared_distance(const Segment_2<K> &seg,
const Triangle_2<K> &triangle)
{
return internal::squared_distance(seg, triangle, K());
}
template <class K>
inline typename K::FT
squared_distance(const Triangle_2<K> &triangle,
const Segment_2<K> &seg)
{
return internal::squared_distance(seg, triangle, K());
}
template <class K>
inline typename K::FT
squared_distance(const Triangle_2<K> &triangle1,
const Triangle_2<K> &triangle2)
{
return internal::squared_distance(triangle1, triangle2, K());
}
} //namespace CGAL
#endif

View File

@ -1,12 +1,12 @@
// 2D distance tests.
#ifdef NDEBUG
#undef NDEBUG //this testsuite requires NDEBUG to be not defined
#endif
#include <CGAL/Simple_cartesian.h>
#include <CGAL/Simple_homogeneous.h>
#include <CGAL/Exact_predicates_inexact_constructions_kernel.h>
#include <CGAL/Exact_predicates_exact_constructions_kernel.h>
#include <CGAL/Homogeneous.h>
#include <vector>
#include <iostream>
@ -167,7 +167,7 @@ struct Test {
check_squared_distance (R(p( 4, 0), p(-3, -1)), R(p( 1, 1), p( 2, 11)), 2);
}
void R_S()
void S_R()
{
std::cout << "Ray - Segment\n";
check_squared_distance (R(p(2, 0), p( 0, 2)), S(p( 1, 1), p( 4, 0)), 0);
@ -216,7 +216,7 @@ struct Test {
check_squared_distance (p( 1, 1), L(p( 4, 0), p( -3, -1)), 2);
}
void L_S()
void S_L()
{
std::cout << "Line - Segment\n";
check_squared_distance (L(p( 0, 0), p( 1, 0)), S(p( 2, 2), p( 3, 3)), 4);
@ -268,29 +268,38 @@ struct Test {
void run()
{
std::cout << "2D Distance tests\n";
std::cout << "-- Kernel: " << typeid(K).name() << std::endl;
P_P();
P_S();
S_S();
P_R();
R_R();
R_S();
R_L();
P_L();
L_S();
L_L();
P_T();
L_T();
R_T();
S_S();
S_T();
S_R();
S_L();
R_R();
R_L();
R_T();
L_L();
L_T();
T_T();
}
};
int main()
{
Test< CGAL::Simple_cartesian<double> >().run();
Test< CGAL::Simple_homogeneous<double> >().run();
// TODO : test more kernels.
std::cout << "2D Distance tests\n";
Test<CGAL::Simple_cartesian<double> >().run();
Test<CGAL::Simple_homogeneous<double> >().run();
Test<CGAL::Homogeneous<CGAL::Epeck_ft> >().run();
Test<CGAL::Exact_predicates_inexact_constructions_kernel>().run();
Test<CGAL::Exact_predicates_exact_constructions_kernel>().run();
}

View File

@ -0,0 +1,61 @@
// Copyright (c) 1998-2021
// Utrecht University (The Netherlands),
// ETH Zurich (Switzerland),
// INRIA Sophia-Antipolis (France),
// Max-Planck-Institute Saarbruecken (Germany),
// and Tel-Aviv University (Israel). All rights reserved.
//
// This file is part of CGAL (www.cgal.org)
//
// $URL$
// $Id$
// SPDX-License-Identifier: LGPL-3.0-or-later OR LicenseRef-Commercial
//
//
// Author(s) : Geert-Jan Giezeman, Andreas Fabri
#ifndef CGAL_DISTANCE_3_LINE_3_LINE_3_H
#define CGAL_DISTANCE_3_LINE_3_LINE_3_H
#include <CGAL/Distance_3/internal/squared_distance_utils_3.h>
#include <CGAL/Line_3.h>
namespace CGAL {
namespace internal {
template <class K>
typename K::FT
squared_distance(const typename K::Line_3& line1,
const typename K::Line_3& line2,
const K& k)
{
typedef typename K::Vector_3 Vector_3;
typename K::Construct_vector_3 vector = k.construct_vector_3_object();
const Vector_3 dir1 = line1.direction().vector();
const Vector_3 dir2 = line2.direction().vector();
const Vector_3 normal = wcross(dir1, dir2, k);
const Vector_3 diff = vector(line1.point(), line2.point());
if (is_null(normal, k))
return squared_distance_to_line(dir2, diff, k);
return squared_distance_to_plane(normal, diff, k);
}
} // namespace internal
template <class K>
inline
typename K::FT
squared_distance(const Line_3<K>& line1,
const Line_3<K>& line2)
{
return K().compute_squared_distance_3_object()(line1, line2);
}
} // namespace CGAL
#endif // CGAL_DISTANCE_3_LINE_3_LINE_3_H

View File

@ -0,0 +1,86 @@
// Copyright (c) 1998-2021
// Utrecht University (The Netherlands),
// ETH Zurich (Switzerland),
// INRIA Sophia-Antipolis (France),
// Max-Planck-Institute Saarbruecken (Germany),
// and Tel-Aviv University (Israel). All rights reserved.
//
// This file is part of CGAL (www.cgal.org)
//
// $URL$
// $Id$
// SPDX-License-Identifier: LGPL-3.0-or-later OR LicenseRef-Commercial
//
//
// Author(s) : Geert-Jan Giezeman, Andreas Fabri
#ifndef CGAL_DISTANCE_3_LINE_3_PLANE_3_H
#define CGAL_DISTANCE_3_LINE_3_PLANE_3_H
#include <CGAL/Distance_3/internal/squared_distance_utils_3.h>
#include <CGAL/Line_3.h>
#include <CGAL/Plane_3.h>
namespace CGAL {
namespace internal {
template <class K>
bool
contains_vector(const typename K::Plane_3& pl,
const typename K::Vector_3& vec,
const K&)
{
typedef typename K::RT RT;
return pl.a()*vec.hx() + pl.b()*vec.hy() + pl.c() * vec.hz() == RT(0);
}
template <class K>
typename K::FT
squared_distance(const typename K::Line_3& l,
const typename K::Plane_3& pl,
const K& k)
{
typedef typename K::FT FT;
typename K::Compute_squared_distance_3 sq_dist = k.compute_squared_distance_3_object();
if(contains_vector(pl, l.direction().vector(), k))
return sq_dist(pl, l.point());
return FT(0);
}
template <class K>
inline typename K::FT
squared_distance(const typename K::Plane_3& pl,
const typename K::Line_3& l,
const K& k)
{
return squared_distance(l, pl, k);
}
} // namespace internal
template <class K>
inline
typename K::FT
squared_distance(const Line_3<K>& line,
const Plane_3<K>& plane)
{
return K().compute_squared_distance_3_object()(line, plane);
}
template <class K>
inline
typename K::FT
squared_distance(const Plane_3<K>& plane,
const Line_3<K>& line)
{
return K().compute_squared_distance_3_object()(plane, line);
}
} // namespace CGAL
#endif // CGAL_DISTANCE_3_LINE_3_PLANE_3_H

View File

@ -0,0 +1,55 @@
// Copyright (c) 1998-2021
// Utrecht University (The Netherlands),
// ETH Zurich (Switzerland),
// INRIA Sophia-Antipolis (France),
// Max-Planck-Institute Saarbruecken (Germany),
// and Tel-Aviv University (Israel). All rights reserved.
//
// This file is part of CGAL (www.cgal.org)
//
// $URL$
// $Id$
// SPDX-License-Identifier: LGPL-3.0-or-later OR LicenseRef-Commercial
//
//
// Author(s) : Geert-Jan Giezeman, Andreas Fabri
#ifndef CGAL_DISTANCE_3_PLANE_3_PLANE_3_H
#define CGAL_DISTANCE_3_PLANE_3_PLANE_3_H
#include <CGAL/Distance_3/internal/squared_distance_utils_3.h>
#include <CGAL/Plane_3.h>
namespace CGAL {
namespace internal {
template <class K>
inline typename K::FT
squared_distance(const typename K::Plane_3& plane1,
const typename K::Plane_3& plane2,
const K& k)
{
typename K::Construct_orthogonal_vector_3 ortho_vec = k.construct_orthogonal_vector_3_object();
typename K::Compute_squared_distance_3 sq_dist = k.compute_squared_distance_3_object();
if(!is_null(wcross(ortho_vec(plane1), ortho_vec(plane2), k), k))
return typename K::FT(0);
else
return sq_dist(plane1.point(), plane2);
}
} // namespace internal
template <class K>
inline
typename K::FT
squared_distance(const Plane_3<K>& plane1,
const Plane_3<K>& plane2)
{
return K().compute_squared_distance_3_object()(plane1, plane2);
}
} // namespace CGAL
#endif // CGAL_DISTANCE_3_PLANE_3_PLANE_3_H

View File

@ -0,0 +1,91 @@
// Copyright (c) 1998-2021
// Utrecht University (The Netherlands),
// ETH Zurich (Switzerland),
// INRIA Sophia-Antipolis (France),
// Max-Planck-Institute Saarbruecken (Germany),
// and Tel-Aviv University (Israel). All rights reserved.
//
// This file is part of CGAL (www.cgal.org)
//
// $URL$
// $Id$
// SPDX-License-Identifier: LGPL-3.0-or-later OR LicenseRef-Commercial
//
//
// Author(s) : Geert-Jan Giezeman, Andreas Fabri, Mael Rouxel-Labbé
#ifndef CGAL_DISTANCE_3_POINT_3_LINE_3_H
#define CGAL_DISTANCE_3_POINT_3_LINE_3_H
#include <CGAL/Distance_3/internal/squared_distance_utils_3.h>
#include <CGAL/Line_3.h>
#include <CGAL/Point_3.h>
namespace CGAL {
namespace internal {
template <class K>
void
squared_distance_RT(const typename K::Point_3 &pt,
const typename K::Line_3 &line,
typename K::RT& num,
typename K::RT& den,
const K& k)
{
typedef typename K::Vector_3 Vector_3;
typename K::Construct_vector_3 vector = k.construct_vector_3_object();
const Vector_3& dir = line.direction().vector();
const Vector_3 diff = vector(line.point(), pt);
return internal::squared_distance_to_line_RT(dir, diff, num, den, k);
}
template <class K>
typename K::FT
squared_distance(const typename K::Point_3& pt,
const typename K::Line_3& line,
const K& k)
{
typedef typename K::RT RT;
typedef typename K::FT FT;
RT num, den;
squared_distance_RT(pt, line, num, den, k);
return Rational_traits<FT>().make_rational(num, den);
}
template <class K>
inline
typename K::FT
squared_distance(const typename K::Line_3& line,
const typename K::Point_3& pt,
const K& k)
{
return squared_distance(pt, line, k);
}
} // namespace internal
template <class K>
inline
typename K::FT
squared_distance(const Point_3<K>& pt,
const Line_3<K>& line)
{
return K().compute_squared_distance_3_object()(pt, line);
}
template <class K>
inline
typename K::FT
squared_distance(const Line_3<K>& line,
const Point_3<K>& pt)
{
return K().compute_squared_distance_3_object()(line, pt);
}
} // namespace CGAL
#endif // CGAL_DISTANCE_3_POINT_3_LINE_3_H

View File

@ -0,0 +1,73 @@
// Copyright (c) 1998-2021
// Utrecht University (The Netherlands),
// ETH Zurich (Switzerland),
// INRIA Sophia-Antipolis (France),
// Max-Planck-Institute Saarbruecken (Germany),
// and Tel-Aviv University (Israel). All rights reserved.
//
// This file is part of CGAL (www.cgal.org)
//
// $URL$
// $Id$
// SPDX-License-Identifier: LGPL-3.0-or-later OR LicenseRef-Commercial
//
//
// Author(s) : Geert-Jan Giezeman, Andreas Fabri
#ifndef CGAL_DISTANCE_3_POINT_3_PLANE_3_H
#define CGAL_DISTANCE_3_POINT_3_PLANE_3_H
#include <CGAL/Distance_3/internal/squared_distance_utils_3.h>
#include <CGAL/Point_3.h>
#include <CGAL/Plane_3.h>
namespace CGAL {
namespace internal {
template <class K>
inline typename K::FT
squared_distance(const typename K::Point_3& pt,
const typename K::Plane_3& plane,
const K& k)
{
typedef typename K::Vector_3 Vector_3;
typename K::Construct_vector_3 vector = k.construct_vector_3_object();
Vector_3 diff = vector(plane.point(), pt);
return squared_distance_to_plane(plane.orthogonal_vector(), diff, k);
}
template <class K>
inline typename K::FT
squared_distance(const typename K::Plane_3& plane,
const typename K::Point_3& pt,
const K& k)
{
return squared_distance(pt, plane, k);
}
} // namespace internal
template <class K>
inline
typename K::FT
squared_distance(const Point_3<K>& pt,
const Plane_3<K>& plane)
{
return K().compute_squared_distance_3_object()(pt, plane);
}
template <class K>
inline
typename K::FT
squared_distance(const Plane_3<K>& plane,
const Point_3<K>& pt)
{
return K().compute_squared_distance_3_object()(plane, pt);
}
} // namespace CGAL
#endif // CGAL_DISTANCE_3_POINT_3_PLANE_3_H

View File

@ -0,0 +1,48 @@
// Copyright (c) 1998-2021
// Utrecht University (The Netherlands),
// ETH Zurich (Switzerland),
// INRIA Sophia-Antipolis (France),
// Max-Planck-Institute Saarbruecken (Germany),
// and Tel-Aviv University (Israel). All rights reserved.
//
// This file is part of CGAL (www.cgal.org)
//
// $URL$
// $Id$
// SPDX-License-Identifier: LGPL-3.0-or-later OR LicenseRef-Commercial
//
//
// Author(s) : Geert-Jan Giezeman, Andreas Fabri
#ifndef CGAL_DISTANCE_3_POINT_3_POINT_3_H
#define CGAL_DISTANCE_3_POINT_3_POINT_3_H
#include <CGAL/Point_3.h>
namespace CGAL {
namespace internal {
template <class K>
inline
typename K::FT
squared_distance(const typename K::Point_3& pt1,
const typename K::Point_3& pt2,
const K& k)
{
return k.compute_squared_distance_3_object()(pt1, pt2);
}
} // namespace internal
template <class K>
inline
typename K::FT
squared_distance(const Point_3<K>& pt1,
const Point_3<K>& pt2)
{
return internal::squared_distance(pt1, pt2, K());
}
} // namespace CGAL
#endif // CGAL_DISTANCE_3_POINT_3_POINT_3_H

View File

@ -0,0 +1,112 @@
// Copyright (c) 1998-2021
// Utrecht University (The Netherlands),
// ETH Zurich (Switzerland),
// INRIA Sophia-Antipolis (France),
// Max-Planck-Institute Saarbruecken (Germany),
// and Tel-Aviv University (Israel). All rights reserved.
//
// This file is part of CGAL (www.cgal.org)
//
// $URL$
// $Id$
// SPDX-License-Identifier: LGPL-3.0-or-later OR LicenseRef-Commercial
//
//
// Author(s) : Geert-Jan Giezeman, Andreas Fabri, Mael Rouxel-Labbé
#ifndef CGAL_DISTANCE_3_POINT_3_RAY_3_H
#define CGAL_DISTANCE_3_POINT_3_RAY_3_H
#include <CGAL/Distance_3/internal/squared_distance_utils_3.h>
#include <CGAL/Point_3.h>
#include <CGAL/Ray_3.h>
namespace CGAL {
namespace internal {
template <class K>
void
squared_distance_RT(const typename K::Point_3 &pt,
const typename K::Ray_3 &ray,
typename K::RT& num,
typename K::RT& den,
const K& k)
{
typedef typename K::Vector_3 Vector_3;
typedef typename K::RT RT;
typename K::Construct_vector_3 vector = k.construct_vector_3_object();
const Vector_3 dir = ray.direction().vector();
const Vector_3 diff = vector(ray.source(), pt);
if(!is_acute_angle(dir, diff, k))
{
num = wdot(diff, diff, k);
den = wmult((K*)0, RT(1), diff.hw(), diff.hw());
return;
}
squared_distance_to_line_RT(dir, diff, num, den, k);
}
template <class K>
typename K::FT
squared_distance(const typename K::Point_3& pt,
const typename K::Ray_3& ray,
const K& k)
{
// This duplicates code from the _RT functions, but it is a slowdown to do something like:
//
// RT num, den;
// squared_distance_RT(pt, ray, num, den, k);
// return Rational_traits<FT>().make_rational(num, den);
//
// See https://github.com/CGAL/cgal/pull/5680
typedef typename K::Vector_3 Vector_3;
typename K::Construct_vector_3 vector = k.construct_vector_3_object();
const Vector_3 dir = ray.direction().vector();
const Vector_3 diff = vector(ray.source(), pt);
if(!is_acute_angle(dir, diff, k))
return diff*diff;
return squared_distance_to_line(dir, diff, k);
}
template <class K>
typename K::FT
squared_distance(const typename K::Ray_3& ray,
const typename K::Point_3& pt,
const K& k)
{
return squared_distance(pt, ray, k);
}
} // namespace internal
template <class K>
inline
typename K::FT
squared_distance(const Point_3<K>& pt,
const Ray_3<K>& ray)
{
return K().compute_squared_distance_3_object()(pt, ray);
}
template <class K>
inline
typename K::FT
squared_distance(const Ray_3<K>& ray,
const Point_3<K>& pt)
{
return K().compute_squared_distance_3_object()(ray, pt);
}
} // namespace CGAL
#endif // CGAL_DISTANCE_3_POINT_3_RAY_3_H

View File

@ -0,0 +1,133 @@
// Copyright (c) 1998-2021
// Utrecht University (The Netherlands),
// ETH Zurich (Switzerland),
// INRIA Sophia-Antipolis (France),
// Max-Planck-Institute Saarbruecken (Germany),
// and Tel-Aviv University (Israel). All rights reserved.
//
// This file is part of CGAL (www.cgal.org)
//
// $URL$
// $Id$
// SPDX-License-Identifier: LGPL-3.0-or-later OR LicenseRef-Commercial
//
//
// Author(s) : Geert-Jan Giezeman, Andreas Fabri
#ifndef CGAL_DISTANCE_3_POINT_3_SEGMENT_3_H
#define CGAL_DISTANCE_3_POINT_3_SEGMENT_3_H
#include <CGAL/Distance_3/internal/squared_distance_utils_3.h>
#include <CGAL/Distance_3/Point_3_Point_3.h>
#include <CGAL/Point_3.h>
#include <CGAL/Segment_3.h>
namespace CGAL {
namespace internal {
template <class K>
void
squared_distance_RT(const typename K::Point_3& pt,
const typename K::Segment_3& seg,
typename K::RT& num,
typename K::RT& den,
const K& k)
{
typedef typename K::RT RT;
typedef typename K::Vector_3 Vector_3;
typename K::Construct_vector_3 vector = k.construct_vector_3_object();
// assert that the segment is valid (non zero length).
const Vector_3 diff_s = vector(seg.source(), pt);
const Vector_3 segvec = vector(seg.source(), seg.target());
const RT d = wdot(diff_s, segvec, k);
if(d <= RT(0))
{
// this is squared_distance(pt, seg.source())
num = wdot(diff_s, diff_s, k);
den = wmult((K*)0, RT(1), diff_s.hw(), diff_s.hw());
return;
}
const RT e = wdot(segvec, segvec, k);
if(wmult((K*)0, d, segvec.hw()) > wmult((K*)0, e, diff_s.hw()))
{
// this is squared_distance(pt, seg.target())
const Vector_3 diff_t = vector(seg.target(), pt);
num = wdot(diff_t, diff_t, k);
den = wmult((K*)0, RT(1), diff_t.hw(), diff_t.hw());
return;
}
// This is an expanded call to squared_distance_to_line_RT() to avoid recomputing 'e'
const Vector_3 wcr = wcross(segvec, diff_s, k);
num = wdot(wcr, wcr, k);
den = wmult((K*)0, e, diff_s.hw(), diff_s.hw());
}
template <class K>
typename K::FT
squared_distance(const typename K::Point_3& pt,
const typename K::Segment_3& seg,
const K& k)
{
typedef typename K::RT RT;
typedef typename K::FT FT;
typedef typename K::Vector_3 Vector_3;
typename K::Construct_vector_3 vector = k.construct_vector_3_object();
// assert that the segment is valid (non zero length).
const Vector_3 diff = vector(seg.source(), pt);
const Vector_3 segvec = vector(seg.source(), seg.target());
const RT d = wdot(diff, segvec, k);
if(d <= RT(0))
return (FT(diff*diff));
const RT e = wdot(segvec, segvec, k);
if(wmult((K*)0, d, segvec.hw()) > wmult((K*)0, e, diff.hw()))
return squared_distance(pt, seg.target(), k);
// This is an expanded call to squared_distance_to_line() to avoid recomputing 'e'
const Vector_3 wcr = wcross(segvec, diff, k);
return FT(wcr*wcr) / wmult((K*)0, e, diff.hw(), diff.hw());
}
template <class K>
inline
typename K::FT
squared_distance(const typename K::Segment_3& seg,
const typename K::Point_3& pt,
const K& k)
{
return squared_distance(pt, seg, k);
}
} // namespace internal
template <class K>
inline
typename K::FT
squared_distance(const Point_3<K>& pt,
const Segment_3<K>& seg)
{
return K().compute_squared_distance_3_object()(pt, seg);
}
template <class K>
inline
typename K::FT
squared_distance(const Segment_3<K>& seg,
const Point_3<K>& pt)
{
return K().compute_squared_distance_3_object()(seg, pt);
}
} // namespace CGAL
#endif // CGAL_DISTANCE_3_POINT_3_SEGMENT_3_H

View File

@ -0,0 +1,148 @@
// Copyright (c) 1998-2021
// Utrecht University (The Netherlands),
// ETH Zurich (Switzerland),
// INRIA Sophia-Antipolis (France),
// Max-Planck-Institute Saarbruecken (Germany),
// and Tel-Aviv University (Israel). All rights reserved.
//
// This file is part of CGAL (www.cgal.org)
//
// $URL$
// $Id$
// SPDX-License-Identifier: LGPL-3.0-or-later OR LicenseRef-Commercial
//
//
// Author(s) : Andreas Fabri
#ifndef CGAL_DISTANCE_3_POINT_3_TETRAHEDRON_3_H
#define CGAL_DISTANCE_3_POINT_3_TETRAHEDRON_3_H
#include <CGAL/Distance_3/Point_3_Triangle_3.h>
#include <CGAL/Point_3.h>
#include <CGAL/Tetrahedron_3.h>
namespace CGAL {
namespace internal {
template <class K>
inline
typename K::FT
squared_distance(const typename K::Point_3& pt,
const typename K::Tetrahedron_3& tet,
const K& k)
{
typedef typename K::Point_3 Point_3;
typename K::Construct_vertex_3 vertex = k.construct_vertex_3_object();
typename K::Orientation_3 orientation = k.orientation_3_object();
bool on_bounded_side = true;
const Point_3& t0 = vertex(tet, 0);
const Point_3& t1 = vertex(tet, 1);
const Point_3& t2 = vertex(tet, 2);
const Point_3& t3 = vertex(tet, 3);
bool dmin_initialized = false;
typename K::FT dmin;
bool inside = false;
if(orientation(t0,t1,t2, pt) == NEGATIVE)
{
on_bounded_side = false;
dmin = squared_distance_to_triangle(pt, t0, t1, t2, k, inside);
dmin_initialized = true;
if(inside)
return dmin;
}
if(orientation(t0,t3,t1, pt) == NEGATIVE)
{
on_bounded_side = false;
const typename K::FT d = squared_distance_to_triangle(pt, t0, t3, t1, k, inside);
if(inside)
return d;
if(!dmin_initialized)
{
dmin = d;
dmin_initialized = true;
}
else
{
dmin = (std::min)(d, dmin);
}
}
if(orientation(t1,t3,t2, pt) == NEGATIVE)
{
on_bounded_side = false;
const typename K::FT d = squared_distance_to_triangle(pt, t1, t3, t2, k, inside);
if(inside)
return d;
if(!dmin_initialized)
{
dmin = d;
dmin_initialized = true;
}
else
{
dmin = (std::min)(d, dmin);
}
}
if(orientation(t2,t3,t0, pt) == NEGATIVE)
{
on_bounded_side = false;
const typename K::FT d = squared_distance_to_triangle(pt, t2, t3, t0, k, inside);
if(inside)
return d;
if(!dmin_initialized)
{
dmin = d;
dmin_initialized = true;
}
else
{
dmin = (std::min)(d, dmin);
}
}
if(on_bounded_side)
return typename K::FT(0);
return dmin;
}
template <class K>
inline
typename K::FT
squared_distance(const typename K::Tetrahedron_3& tet,
const typename K::Point_3& pt,
const K& k)
{
return squared_distance(pt, tet, k);
}
} // namespace internal
template <class K>
typename K::FT
squared_distance(const Tetrahedron_3<K>& tet,
const Point_3<K>& pt)
{
return K().compute_squared_distance_3_object()(tet, pt);
}
template <class K>
typename K::FT
squared_distance(const Point_3<K>& pt,
const Tetrahedron_3<K>& tet)
{
return K().compute_squared_distance_3_object()(pt, tet);
}
} // namespace CGAL
#endif // CGAL_DISTANCE_3_POINT_3_TETRAHEDRON_3_H

View File

@ -0,0 +1,242 @@
// Copyright (c) 1998-2021
// Utrecht University (The Netherlands),
// ETH Zurich (Switzerland),
// INRIA Sophia-Antipolis (France),
// Max-Planck-Institute Saarbruecken (Germany),
// and Tel-Aviv University (Israel). All rights reserved.
//
// This file is part of CGAL (www.cgal.org)
//
// $URL$
// $Id$
// SPDX-License-Identifier: LGPL-3.0-or-later OR LicenseRef-Commercial
//
//
// Author(s) : Geert-Jan Giezeman, Andreas Fabri
#ifndef CGAL_DISTANCE_3_POINT_3_TRIANGLE_3_H
#define CGAL_DISTANCE_3_POINT_3_TRIANGLE_3_H
#include <CGAL/Distance_3/internal/squared_distance_utils_3.h>
#include <CGAL/Distance_3/Point_3_Segment_3.h>
#include <CGAL/Point_3.h>
#include <CGAL/Triangle_3.h>
namespace CGAL {
namespace internal {
// returns true iff pt is on the negative side of the plane defined by (ep0, ep1) and normal
template <class K>
inline bool
on_left_of_triangle_edge(const typename K::Point_3& pt,
const typename K::Vector_3& normal,
const typename K::Point_3& ep0,
const typename K::Point_3& ep1,
const K& k)
{
typedef typename K::RT RT;
typedef typename K::Vector_3 Vector_3;
typename K::Construct_vector_3 vector = k.construct_vector_3_object();
const Vector_3 edge = vector(ep0, ep1);
const Vector_3 diff = vector(ep0, pt);
return (wdot(wcross(edge, normal, k), diff, k) <= RT(0));
}
template <class K>
inline void
squared_distance_to_triangle_RT(const typename K::Point_3& pt,
const typename K::Point_3& t0,
const typename K::Point_3& t1,
const typename K::Point_3& t2,
bool& inside,
typename K::RT& num,
typename K::RT& den,
const K& k)
{
typedef typename K::Vector_3 Vector_3;
typename K::Construct_vector_3 vector = k.construct_vector_3_object();
typename K::Construct_segment_3 segment = k.construct_segment_3_object();
const Vector_3 e1 = vector(t0, t1);
const Vector_3 oe3 = vector(t0, t2);
const Vector_3 normal = wcross(e1, oe3, k);
if(normal == NULL_VECTOR)
{
// The case normal==NULL_VECTOR covers the case when the triangle
// is colinear, or even more degenerate. In that case, we can
// simply take also the distance to the three segments.
squared_distance_RT(pt, segment(t2, t0), num, den, k);
typename K::RT num2, den2;
squared_distance_RT(pt, segment(t1, t2), num2, den2, k);
if(compare_quotients(num2,den2, num,den) == SMALLER)
{
num = num2;
den = den2;
}
// Should not be needed since at most 2 edges cover the full triangle in the degenerate case,
// but leaving it for robustness
squared_distance_RT(pt, segment(t0, t1), num2, den2, k);
if(compare_quotients(num2,den2, num,den) == SMALLER)
{
num = num2;
den = den2;
}
return;
}
const bool b01 = on_left_of_triangle_edge(pt, normal, t0, t1, k);
if(!b01)
{
squared_distance_RT(pt, segment(t0, t1), num, den, k);
return;
}
const bool b12 = on_left_of_triangle_edge(pt, normal, t1, t2, k);
if(!b12)
{
squared_distance_RT(pt, segment(t1, t2), num, den, k);
return;
}
const bool b20 = on_left_of_triangle_edge(pt, normal, t2, t0, k);
if(!b20)
{
squared_distance_RT(pt, segment(t2, t0), num, den, k);
return;
}
// The projection of pt is inside the triangle
inside = true;
squared_distance_to_plane_RT(normal, vector(t0, pt), num, den, k);
}
template <class K>
void
squared_distance_RT(const typename K::Point_3& pt,
const typename K::Triangle_3& t,
typename K::RT& num,
typename K::RT& den,
const K& k)
{
typename K::Construct_vertex_3 vertex;
bool inside = false;
squared_distance_to_triangle_RT(pt,
vertex(t, 0),
vertex(t, 1),
vertex(t, 2),
inside,
num,
den,
k);
}
template <class K>
inline typename K::FT
squared_distance_to_triangle(const typename K::Point_3& pt,
const typename K::Point_3& t0,
const typename K::Point_3& t1,
const typename K::Point_3& t2,
const K& k,
bool& inside)
{
typedef typename K::Vector_3 Vector_3;
typename K::Construct_segment_3 segment = k.construct_segment_3_object();
typename K::Construct_vector_3 vector = k.construct_vector_3_object();
typename K::Compute_squared_distance_3 sq_dist = k.compute_squared_distance_3_object();
const Vector_3 e1 = vector(t0, t1);
const Vector_3 oe3 = vector(t0, t2);
const Vector_3 normal = wcross(e1, oe3, k);
if(normal == NULL_VECTOR)
{
// The case normal == NULL_VECTOR covers the case when the triangle
// is colinear, or even more degenerate. In that case, we can
// simply take also the distance to the three segments.
//
// Note that in the degenerate case, at most 2 edges cover the full triangle,
// and only two distances could be used, but leaving 3 for the case of
// inexact constructions as it might improve the accuracy.
typename K::FT d1 = sq_dist(pt, segment(t2, t0));
typename K::FT d2 = sq_dist(pt, segment(t1, t2));
typename K::FT d3 = sq_dist(pt, segment(t0, t1));
return (std::min)((std::min)(d1, d2), d3);
}
const bool b01 = on_left_of_triangle_edge(pt, normal, t0, t1, k);
if(!b01)
return sq_dist(pt, segment(t0, t1));
const bool b12 = on_left_of_triangle_edge(pt, normal, t1, t2, k);
if(!b12)
return sq_dist(pt, segment(t1, t2));
const bool b20 = on_left_of_triangle_edge(pt, normal, t2, t0, k);
if(!b20)
return sq_dist(pt, segment(t2, t0));
// The projection of pt is inside the triangle
inside = true;
return squared_distance_to_plane(normal, vector(t0, pt), k);
}
template <class K>
inline typename K::FT
squared_distance(const typename K::Point_3& pt,
const typename K::Triangle_3& t,
const K& k)
{
typename K::Construct_vertex_3 vertex = k.construct_vertex_3_object();
bool unused_inside = false;
return squared_distance_to_triangle(pt,
vertex(t, 0),
vertex(t, 1),
vertex(t, 2),
k,
unused_inside);
}
template <class K>
inline typename K::FT
squared_distance(const typename K::Triangle_3& t,
const typename K::Point_3& pt,
const K& k)
{
return squared_distance(pt, t, k);
}
} // namespace internal
template <class K>
inline
typename K::FT
squared_distance(const Point_3<K>& pt,
const Triangle_3<K>& t)
{
return K().compute_squared_distance_3_object()(pt, t);
}
template <class K>
inline
typename K::FT
squared_distance(const Triangle_3<K>& t,
const Point_3<K>& pt)
{
return K().compute_squared_distance_3_object()(t, pt);
}
} // namespace CGAL
#endif // CGAL_DISTANCE_3_POINT_3_TRIANGLE_3_H

View File

@ -0,0 +1,47 @@
// Copyright (c) 1998-2021
// Utrecht University (The Netherlands),
// ETH Zurich (Switzerland),
// INRIA Sophia-Antipolis (France),
// Max-Planck-Institute Saarbruecken (Germany),
// and Tel-Aviv University (Israel). All rights reserved.
//
// This file is part of CGAL (www.cgal.org)
//
// $URL$
// $Id$
// SPDX-License-Identifier: LGPL-3.0-or-later OR LicenseRef-Commercial
//
//
// Author(s) : Geert-Jan Giezeman, Andreas Fabri
#ifndef CGAL_DISTANCE_3_POINT_3_WEIGHTED_POINT_3_H
#define CGAL_DISTANCE_3_POINT_3_WEIGHTED_POINT_3_H
#include <CGAL/Distance_3/Point_3_Point_3.h>
#include <CGAL/Point_3.h>
#include <CGAL/Weighted_point_3.h>
namespace CGAL {
template <class K>
inline
typename K::FT
squared_distance(const Weighted_point_3<K>& wpt,
const Point_3<K>& pt)
{
return K().compute_squared_distance_3_object()(wpt.point(), pt);
}
template <class K>
inline
typename K::FT
squared_distance(const Point_3<K>& pt,
const Weighted_point_3<K>& wpt)
{
return K().compute_squared_distance_3_object()(pt, wpt.point());
}
} // namespace CGAL
#endif // CGAL_DISTANCE_3_POINT_3_WEIGHTED_POINT_3_H

View File

@ -0,0 +1,102 @@
// Copyright (c) 1998-2021
// Utrecht University (The Netherlands),
// ETH Zurich (Switzerland),
// INRIA Sophia-Antipolis (France),
// Max-Planck-Institute Saarbruecken (Germany),
// and Tel-Aviv University (Israel). All rights reserved.
//
// This file is part of CGAL (www.cgal.org)
//
// $URL$
// $Id$
// SPDX-License-Identifier: LGPL-3.0-or-later OR LicenseRef-Commercial
//
//
// Author(s) : Geert-Jan Giezeman, Andreas Fabri
#ifndef CGAL_DISTANCE_3_RAY_3_LINE_3_H
#define CGAL_DISTANCE_3_RAY_3_LINE_3_H
#include <CGAL/Distance_3/internal/squared_distance_utils_3.h>
#include <CGAL/Line_3.h>
#include <CGAL/Ray_3.h>
namespace CGAL {
namespace internal {
template <class K>
typename K::FT
squared_distance(const typename K::Ray_3& ray,
const typename K::Line_3& line,
const K& k)
{
typedef typename K::Vector_3 Vector_3;
typedef typename K::Point_3 Point_3;
typedef typename K::RT RT;
typename K::Construct_vector_3 vector = k.construct_vector_3_object();
const Point_3& rs = ray.source();
const Vector_3 linedir = line.direction().vector();
const Vector_3 raydir = ray.direction().vector();
const Vector_3 normal = wcross(raydir, linedir, k);
const Vector_3 rs_min_lp = vector(line.point(), rs);
if(is_null(normal, k))
return squared_distance_to_line(linedir, rs_min_lp, k);
bool crossing;
const Vector_3 perpend2l = wcross(linedir, normal, k);
const RT sdm_sr_l = wdot(perpend2l, rs_min_lp, k);
if(sdm_sr_l < RT(0))
{
crossing = (wdot(perpend2l, raydir, k) >= RT(0));
}
else
{
if(wdot(perpend2l, raydir, k) <= RT(0))
crossing = true;
else
crossing = (sdm_sr_l == RT(0));
}
if(crossing)
return squared_distance_to_plane(normal, rs_min_lp, k);
else
return squared_distance_to_line(linedir, rs_min_lp, k);
}
template <class K>
typename K::FT
squared_distance(const typename K::Line_3& line,
const typename K::Ray_3& ray,
const K& k)
{
return squared_distance(ray, line, k);
}
} // namespace internal
template <class K>
inline
typename K::FT
squared_distance(const Line_3<K>& line,
const Ray_3<K>& ray)
{
return K().compute_squared_distance_3_object()(line, ray);
}
template <class K>
inline
typename K::FT
squared_distance(const Ray_3<K>& ray,
const Line_3<K>& line)
{
return K().compute_squared_distance_3_object()(ray, line);
}
} // namespace CGAL
#endif // CGAL_DISTANCE_3_RAY_3_LINE_3_H

View File

@ -0,0 +1,97 @@
// Copyright (c) 1998-2021
// Utrecht University (The Netherlands),
// ETH Zurich (Switzerland),
// INRIA Sophia-Antipolis (France),
// Max-Planck-Institute Saarbruecken (Germany),
// and Tel-Aviv University (Israel). All rights reserved.
//
// This file is part of CGAL (www.cgal.org)
//
// $URL$
// $Id$
// SPDX-License-Identifier: LGPL-3.0-or-later OR LicenseRef-Commercial
//
//
// Author(s) : Geert-Jan Giezeman, Andreas Fabri
#ifndef CGAL_DISTANCE_3_RAY_3_PLANE_3_H
#define CGAL_DISTANCE_3_RAY_3_PLANE_3_H
#include <CGAL/Distance_3/internal/squared_distance_utils_3.h>
#include <CGAL/number_utils.h>
#include <CGAL/Plane_3.h>
#include <CGAL/Ray_3.h>
namespace CGAL {
namespace internal {
template <class K>
typename K::FT
squared_distance(const typename K::Ray_3 &ray,
const typename K::Plane_3 &plane,
const K& k)
{
typedef typename K::RT RT;
typedef typename K::FT FT;
typedef typename K::Point_3 Point_3;
typedef typename K::Vector_3 Vector_3;
typename K::Construct_vector_3 construct_vector = k.construct_vector_3_object();
const Point_3& start = ray.start();
const Point_3& planepoint = plane.point();
const Vector_3 start_min_pp = construct_vector(planepoint, start);
const Vector_3 end_min_pp = ray.direction().vector();
const Vector_3 normal = plane.orthogonal_vector();
const RT sdm_rs2pp = wdot(normal, start_min_pp, k);
const RT sdm_re2pp = wdot(normal, end_min_pp, k);
switch (CGAL_NTS sign(sdm_rs2pp))
{
case -1:
if(sdm_re2pp > RT(0))
return FT(0);
return squared_distance_to_plane(normal, start_min_pp, k);
case 0:
default:
return FT(0);
case 1:
if(sdm_re2pp < RT(0))
return FT(0);
return squared_distance_to_plane(normal, start_min_pp, k);
}
}
template <class K>
inline typename K::FT
squared_distance(const typename K::Plane_3& plane,
const typename K::Ray_3& ray,
const K& k)
{
return squared_distance(ray, plane, k);
}
} // namespace internal
template <class K>
inline
typename K::FT
squared_distance(const Ray_3<K>& ray,
const Plane_3<K>& plane)
{
return K().compute_squared_distance_3_object()(ray, plane);
}
template <class K>
inline
typename K::FT
squared_distance(const Plane_3<K>& plane,
const Ray_3<K>& ray)
{
return K().compute_squared_distance_3_object()(plane, ray);
}
} // namespace CGAL
#endif // CGAL_DISTANCE_3_RAY_3_PLANE_3_H

View File

@ -0,0 +1,143 @@
// Copyright (c) 1998-2021
// Utrecht University (The Netherlands),
// ETH Zurich (Switzerland),
// INRIA Sophia-Antipolis (France),
// Max-Planck-Institute Saarbruecken (Germany),
// and Tel-Aviv University (Israel). All rights reserved.
//
// This file is part of CGAL (www.cgal.org)
//
// $URL$
// $Id$
// SPDX-License-Identifier: LGPL-3.0-or-later OR LicenseRef-Commercial
//
//
// Author(s) : Geert-Jan Giezeman, Andreas Fabri
#ifndef CGAL_DISTANCE_3_RAY_3_RAY_3_H
#define CGAL_DISTANCE_3_RAY_3_RAY_3_H
#include <CGAL/Distance_3/internal/squared_distance_utils_3.h>
#include <CGAL/Ray_3.h>
#include <CGAL/Vector_3.h>
namespace CGAL {
namespace internal {
template <class K>
typename K::FT
ray_ray_squared_distance_parallel(const typename K::Vector_3& ray1dir,
const typename K::Vector_3& ray2dir,
const typename K::Vector_3& s1_min_s2,
const K& k)
{
if(!is_acute_angle(ray2dir, s1_min_s2, k))
if(!same_direction(ray1dir, ray2dir, k))
return typename K::FT(s1_min_s2*s1_min_s2);
return squared_distance_to_line(ray1dir, s1_min_s2, k);
}
template <class K>
typename K::FT
squared_distance(const typename K::Ray_3& ray1,
const typename K::Ray_3& ray2,
const K& k)
{
typedef typename K::RT RT;
typedef typename K::FT FT;
typedef typename K::Point_3 Point_3;
typedef typename K::Vector_3 Vector_3;
typename K::Construct_vector_3 construct_vector = k.construct_vector_3_object();
typename K::Compute_squared_distance_3 sq_dist = k.compute_squared_distance_3_object();
const Point_3& s1 = ray1.source();
const Point_3& s2 = ray2.source();
const Vector_3 dir1 = ray1.direction().vector();
const Vector_3 dir2 = ray2.direction().vector();
const Vector_3 normal = wcross(dir1, dir2, k);
const Vector_3 s1_min_s2 = construct_vector(s2, s1);
if(is_null(normal, k))
return ray_ray_squared_distance_parallel(dir1, dir2, s1_min_s2, k);
bool crossing1, crossing2;
const Vector_3 perpend1 = wcross(dir1, normal, k);
const Vector_3 perpend2 = wcross(dir2, normal, k);
const RT sdm_s1_2 = wdot(perpend2, s1_min_s2, k);
if(sdm_s1_2 < RT(0))
{
crossing1 = (wdot(perpend2, dir1, k) >= RT(0));
}
else
{
if(RT(wdot(perpend2, dir1, k)) <= RT(0))
crossing1 = true;
else
crossing1 = (sdm_s1_2 == RT(0));
}
const RT sdm_s2_1 = - wdot(perpend1, s1_min_s2, k);
if(sdm_s2_1 < RT(0))
{
crossing2 = (wdot(perpend1, dir2, k) >= RT(0));
}
else
{
if(wdot(perpend1, dir2, k) <= RT(0))
crossing2 = true;
else
crossing2 = (sdm_s2_1 == RT(0));
}
if(crossing1)
{
if(crossing2)
return squared_distance_to_plane(normal, s1_min_s2, k);
return sq_dist(s2, ray1);
}
else
{
if(crossing2)
{
return sq_dist(s1, ray2);
}
else
{
FT min1, min2;
min1 = sq_dist(s1, ray2);
min2 = sq_dist(s2, ray1);
return (min1 < min2) ? min1 : min2;
}
}
}
} // namespace internal
template <class K>
inline
typename K::FT
ray_ray_squared_distance_parallel(const Vector_3<K>& ray1dir,
const Vector_3<K>& ray2dir,
const Vector_3<K>& s1_min_s2)
{
return internal::ray_ray_squared_distance_parallel(ray1dir, ray2dir, s1_min_s2, K());
}
template <class K>
inline
typename K::FT
squared_distance(const Ray_3<K>& ray1,
const Ray_3<K>& ray2)
{
return K().compute_squared_distance_3_object()(ray1, ray2);
}
} // namespace CGAL
#endif // CGAL_DISTANCE_3_RAY_3_RAY_3_H

View File

@ -0,0 +1,116 @@
// Copyright (c) 1998-2021
// Utrecht University (The Netherlands),
// ETH Zurich (Switzerland),
// INRIA Sophia-Antipolis (France),
// Max-Planck-Institute Saarbruecken (Germany),
// and Tel-Aviv University (Israel). All rights reserved.
//
// This file is part of CGAL (www.cgal.org)
//
// $URL$
// $Id$
// SPDX-License-Identifier: LGPL-3.0-or-later OR LicenseRef-Commercial
//
//
// Author(s) : Geert-Jan Giezeman, Andreas Fabri
#ifndef CGAL_DISTANCE_3_SEGMENT_3_LINE_3_H
#define CGAL_DISTANCE_3_SEGMENT_3_LINE_3_H
#include <CGAL/Distance_3/internal/squared_distance_utils_3.h>
#include <CGAL/Line_3.h>
#include <CGAL/Segment_3.h>
namespace CGAL {
namespace internal {
template <class K>
typename K::FT
squared_distance(const typename K::Segment_3& seg,
const typename K::Line_3& line,
const K& k)
{
typedef typename K::RT RT;
typedef typename K::Point_3 Point_3;
typedef typename K::Vector_3 Vector_3;
typename K::Construct_vector_3 vector = k.construct_vector_3_object();
typename K::Compute_squared_distance_3 sq_dist = k.compute_squared_distance_3_object();
const Point_3& linepoint = line.point();
const Point_3& start = seg.source();
const Point_3& end = seg.target();
if(start == end)
return sq_dist(start, line);
const Vector_3 linedir = line.direction().vector();
const Vector_3 segdir = seg.direction().vector();
const Vector_3 normal = wcross(segdir, linedir, k);
if(is_null(normal, k))
return squared_distance_to_line(linedir, vector(linepoint,start), k);
bool crossing;
const Vector_3 perpend2line = wcross(linedir, normal, k);
const Vector_3 start_min_lp = vector(linepoint, start);
const Vector_3 end_min_lp = vector(linepoint, end);
const RT sdm_ss2l = wdot(perpend2line, start_min_lp, k);
const RT sdm_se2l = wdot(perpend2line, end_min_lp, k);
if(sdm_ss2l < RT(0)) {
crossing = (sdm_se2l >= RT(0));
} else {
if(sdm_se2l <= RT(0)) {
crossing = true;
} else {
crossing = (sdm_ss2l == RT(0));
}
}
if(crossing) {
return squared_distance_to_plane(normal, start_min_lp, k);
} else {
const RT dm = distance_measure_sub(sdm_ss2l, sdm_se2l, start_min_lp, end_min_lp, k);
if(dm <= RT(0)) {
return squared_distance_to_line(linedir, start_min_lp, k);
} else {
return squared_distance_to_line(linedir, end_min_lp, k);
}
}
}
template <class K>
typename K::FT
squared_distance(const typename K::Line_3& line,
const typename K::Segment_3& seg,
const K& k)
{
return squared_distance(seg, line, k);
}
} // namespace internal
template <class K>
inline
typename K::FT
squared_distance(const Segment_3<K>& seg,
const Line_3<K>& line)
{
return K().compute_squared_distance_3_object()(seg, line);
}
template <class K>
inline
typename K::FT
squared_distance(const Line_3<K>& line,
const Segment_3<K>& seg)
{
return K().compute_squared_distance_3_object()(line, seg);
}
} // namespace CGAL
#endif // CGAL_DISTANCE_3_SEGMENT_3_LINE_3_H

View File

@ -0,0 +1,108 @@
// Copyright (c) 1998-2021
// Utrecht University (The Netherlands),
// ETH Zurich (Switzerland),
// INRIA Sophia-Antipolis (France),
// Max-Planck-Institute Saarbruecken (Germany),
// and Tel-Aviv University (Israel). All rights reserved.
//
// This file is part of CGAL (www.cgal.org)
//
// $URL$
// $Id$
// SPDX-License-Identifier: LGPL-3.0-or-later OR LicenseRef-Commercial
//
//
// Author(s) : Geert-Jan Giezeman, Andreas Fabri
#ifndef CGAL_DISTANCE_3_SEGMENT_3_PLANE_3_H
#define CGAL_DISTANCE_3_SEGMENT_3_PLANE_3_H
#include <CGAL/Distance_3/internal/squared_distance_utils_3.h>
#include <CGAL/Segment_3.h>
#include <CGAL/Plane_3.h>
namespace CGAL {
namespace internal {
template <class K>
typename K::FT
squared_distance(const typename K::Segment_3 &seg,
const typename K::Plane_3 &plane,
const K& k)
{
typedef typename K::RT RT;
typedef typename K::FT FT;
typedef typename K::Vector_3 Vector_3;
typedef typename K::Point_3 Point_3;
typename K::Construct_vector_3 vector = k.construct_vector_3_object();
const Point_3& start = seg.start();
const Point_3& end = seg.end();
if (start == end)
return squared_distance(start, plane, k);
const Point_3& planepoint = plane.point();
const Vector_3 start_min_pp = vector(planepoint, start);
const Vector_3 end_min_pp = vector(planepoint, end);
const Vector_3& normal = plane.orthogonal_vector();
const RT sdm_ss2pp = wdot(normal, start_min_pp, k);
const RT sdm_se2pp = wdot(normal, end_min_pp, k);
switch (CGAL_NTS sign(sdm_ss2pp))
{
case -1:
if (sdm_se2pp >= RT(0))
return FT(0);
if (sdm_ss2pp * end_min_pp.hw() >= sdm_se2pp * start_min_pp.hw())
return squared_distance_to_plane(normal, start_min_pp, k);
else
return squared_distance_to_plane(normal, end_min_pp, k);
case 0:
default:
return FT(0);
case 1:
if (sdm_se2pp <= RT(0))
return FT(0);
if (sdm_ss2pp * end_min_pp.hw() <= sdm_se2pp * start_min_pp.hw())
return squared_distance_to_plane(normal, start_min_pp, k);
else
return squared_distance_to_plane(normal, end_min_pp, k);
}
}
template <class K>
inline typename K::FT
squared_distance(const typename K::Plane_3& plane,
const typename K::Segment_3& seg,
const K& k)
{
return squared_distance(seg, plane, k);
}
} // namespace internal
template <class K>
inline
typename K::FT
squared_distance(const Segment_3<K>& seg,
const Plane_3<K>& plane)
{
return K().compute_squared_distance_3_object()(seg, plane);
}
template <class K>
inline
typename K::FT
squared_distance(const Plane_3<K>& plane,
const Segment_3<K>& seg)
{
return K().compute_squared_distance_3_object()(plane, seg);
}
} // namespace CGAL
#endif // CGAL_DISTANCE_3_SEGMENT_3_PLANE_3_H

View File

@ -0,0 +1,200 @@
// Copyright (c) 1998-2021
// Utrecht University (The Netherlands),
// ETH Zurich (Switzerland),
// INRIA Sophia-Antipolis (France),
// Max-Planck-Institute Saarbruecken (Germany),
// and Tel-Aviv University (Israel). All rights reserved.
//
// This file is part of CGAL (www.cgal.org)
//
// $URL$
// $Id$
// SPDX-License-Identifier: LGPL-3.0-or-later OR LicenseRef-Commercial
//
//
// Author(s) : Geert-Jan Giezeman, Andreas Fabri
#ifndef CGAL_DISTANCE_3_SEGMENT_3_RAY_3_H
#define CGAL_DISTANCE_3_SEGMENT_3_RAY_3_H
#include <CGAL/Distance_3/internal/squared_distance_utils_3.h>
#include <CGAL/Segment_3.h>
#include <CGAL/Ray_3.h>
namespace CGAL {
namespace internal {
template <class K>
typename K::FT
squared_distance_parallel(const typename K::Segment_3& seg,
const typename K::Ray_3& ray,
const K& k)
{
typedef typename K::Vector_3 Vector_3;
const Vector_3 dir1 = seg.direction().vector();
const Vector_3 dir2 = ray.direction().vector();
bool same_direction;
if(CGAL_NTS abs(dir1.hx()) > CGAL_NTS abs(dir1.hy()))
same_direction = (CGAL_NTS sign(dir1.hx()) == CGAL_NTS sign(dir2.hx()));
else
same_direction = (CGAL_NTS sign(dir1.hy()) == CGAL_NTS sign(dir2.hy()));
if(same_direction)
{
if(!is_acute_angle(seg.source(), seg.target(), ray.source(), k))
return squared_distance(seg.target(), ray.source(), k);
}
else
{
if(!is_acute_angle(seg.target(), seg.source(), ray.source(), k))
return squared_distance(seg.source(), ray.source(), k);
}
return squared_distance(ray.source(), seg.supporting_line(), k);
}
template <class K>
typename K::FT
squared_distance(const typename K::Segment_3& seg,
const typename K::Ray_3& ray,
const K& k)
{
typedef typename K::RT RT;
typedef typename K::FT FT;
typedef typename K::Point_3 Point_3;
typedef typename K::Vector_3 Vector_3;
typename K::Construct_vector_3 vector = k.construct_vector_3_object();
typename K::Compute_squared_distance_3 sq_dist = k.compute_squared_distance_3_object();
const Point_3& ss = seg.source();
const Point_3& se = seg.target();
if(ss == se)
return sq_dist(ss, ray);
const Vector_3 raydir = ray.direction().vector();
const Vector_3 segdir = seg.direction().vector();
const Vector_3 normal = wcross(segdir, raydir, k);
if(is_null(normal, k))
return squared_distance_parallel(seg, ray, k);
bool crossing1, crossing2;
const Vector_3 perpend2seg = wcross(segdir, normal, k);
const Vector_3 perpend2ray = wcross(raydir, normal, k);
const Vector_3 ss_min_rs = vector(ray.source(), ss);
const Vector_3 se_min_rs = vector(ray.source(), se);
const RT sdm_ss2r = wdot(perpend2ray, ss_min_rs, k);
const RT sdm_se2r = wdot(perpend2ray, se_min_rs, k);
if(sdm_ss2r < RT(0))
{
crossing1 = (sdm_se2r >= RT(0));
}
else
{
if(sdm_se2r <= RT(0))
crossing1 = true;
else
crossing1 = (sdm_ss2r == RT(0));
}
const RT sdm_rs2s = - wdot(perpend2seg, ss_min_rs, k);
const RT sdm_re2s = wdot(perpend2seg, raydir, k);
if(sdm_rs2s < RT(0))
{
crossing2 = (sdm_re2s >= RT(0));
} else
{
if(sdm_re2s <= RT(0))
crossing2 = true;
else
crossing2 = (sdm_rs2s == RT(0));
}
if(crossing1)
{
if(crossing2)
return squared_distance_to_plane(normal, ss_min_rs, k);
return sq_dist(ray.source(), seg);
}
else
{
if(crossing2)
{
const RT dm = distance_measure_sub(sdm_ss2r, sdm_se2r, ss_min_rs, se_min_rs, k);
if(dm < RT(0))
{
return sq_dist(ss, ray);
}
else
{
if(dm > RT(0))
return sq_dist(se, ray);
else
// parallel, should not happen (no crossing)
return squared_distance_parallel(seg, ray, k);
}
}
else
{
const RT dm = distance_measure_sub(sdm_ss2r, sdm_se2r, ss_min_rs, se_min_rs, k);
if(dm == RT(0))
return squared_distance_parallel(seg, ray, k);
const FT min1 = (dm < RT(0)) ? sq_dist(ss, ray)
: sq_dist(se, ray);
const FT min2 = sq_dist(ray.source(), seg);
return (min1 < min2) ? min1 : min2;
}
}
}
template <class K>
typename K::FT
squared_distance(const typename K::Ray_3& ray,
const typename K::Segment_3& seg,
const K& k)
{
return squared_distance(seg, ray, k);
}
} // namespace internal
template <class K>
inline
typename K::FT
squared_distance_parallel(const Segment_3<K>& seg,
const Ray_3<K>& ray)
{
return internal::squared_distance_parallel(ray, seg, K());
}
template <class K>
inline
typename K::FT
squared_distance(const Segment_3<K>& seg,
const Ray_3<K>& ray)
{
return K().compute_squared_distance_3_object()(seg, ray);
}
template <class K>
inline
typename K::FT
squared_distance(const Ray_3<K>& ray,
const Segment_3<K>& seg)
{
return K().compute_squared_distance_3_object()(ray, seg);
}
} // namespace CGAL
#endif // CGAL_DISTANCE_3_SEGMENT_3_RAY_3_H

View File

@ -0,0 +1,208 @@
// Copyright (c) 1998-2021
// Utrecht University (The Netherlands),
// ETH Zurich (Switzerland),
// INRIA Sophia-Antipolis (France),
// Max-Planck-Institute Saarbruecken (Germany),
// and Tel-Aviv University (Israel). All rights reserved.
//
// This file is part of CGAL (www.cgal.org)
//
// $URL$
// $Id$
// SPDX-License-Identifier: LGPL-3.0-or-later OR LicenseRef-Commercial
//
//
// Author(s) : Mael Rouxel-Labbé
#ifndef CGAL_DISTANCE_3_SEGMENT_3_SEGMENT_3_H
#define CGAL_DISTANCE_3_SEGMENT_3_SEGMENT_3_H
#include <CGAL/Distance_3/internal/squared_distance_utils_3.h>
#include <CGAL/Segment_3.h>
#include <boost/algorithm/clamp.hpp>
namespace CGAL {
namespace Distance_3 {
namespace internal {
template <typename K>
struct Segment_3_Segment_3_Result
{
typename K::FT x, y;
typename K::FT squared_distance;
};
// Using Lumelsky, 'On Fast Computation of Distance Between Line Segments' 1984
template <typename K>
Segment_3_Segment_3_Result<K>
squared_distance(const typename K::Segment_3& s1,
const typename K::Segment_3& s2,
const K& k)
{
typedef typename K::FT FT;
typedef typename K::Point_3 Point_3;
typedef typename K::Vector_3 Vector_3;
typename K::Construct_vertex_3 vertex = k.construct_vertex_3_object();
typename K::Construct_vector_3 cv = k.construct_vector_3_object();
typename K::Compute_scalar_product_3 sp = k.compute_scalar_product_3_object();
typename K::Compute_squared_distance_3 sq_dist = k.compute_squared_distance_3_object();
Segment_3_Segment_3_Result<K> res;
const Point_3& p1 = vertex(s1, 0);
const Point_3& q1 = vertex(s1, 1);
const Point_3& p2 = vertex(s2, 0);
const Point_3& q2 = vertex(s2, 1);
const Vector_3 v1 = cv(p1, q1), v2 = cv(p2, q2);
const Vector_3 p1p2 = cv(p1, p2);
// @todo compute these only when needed?
const FT a = sp(v1, v1);
const FT b = - sp(v1, v2);
const FT c = - b;
const FT d = - sp(v2, v2);
const FT e = sp(v1, p1p2);
const FT f = sp(v2, p1p2);
if(p1 == q1)
{
if(p2 == q2)
{
res.x = 0;
res.y = 0;
res.squared_distance = sq_dist(p1, p2);
return res;
}
CGAL_assertion(d < 0);
res.x = 0;
res.y = boost::algorithm::clamp<FT>(f/d, 0, 1); // (f - x*c) / d
res.squared_distance = sq_dist(p1, p2 + res.y*v2);
return res;
}
else if(p2 == q2)
{
CGAL_assertion(a > 0);
res.y = 0;
res.x = boost::algorithm::clamp<FT>(e/a, 0, 1); // (e + y*c) / a
res.squared_distance = sq_dist(p1 + res.x*v1, p2);
return res;
}
CGAL_assertion(a > 0 && d < 0);
const FT det = a*d - b*c;
if(det == 0)
res.x = 0;
else
res.x = boost::algorithm::clamp<FT>((e*d - b*f) / det, 0, 1);
FT xc = res.x*c;
// res.y = (f - xc) / d, by definition, but building it up more efficiently
if(f > xc) // y < 0 <=> f - xc / d < 0 <=> f - xc > 0 (since d is -||v2||)
{
res.y = 0;
res.x = boost::algorithm::clamp<FT>(e/a, 0, 1); // (e + y*c) / a
}
else // y >= 0
{
FT n = f - xc; // delay the division by d
if(n < d) // y > 1 <=> n / d > 1 <=> n < d (once again, important to note that d is negative!)
{
res.y = 1;
res.x = boost::algorithm::clamp<FT>((e + c) / a, 0, 1); // (e + y*c) / a
}
else // 0 <= y <= 1
{
res.y = n / d;
}
}
CGAL_postcondition(FT(0) <= res.x && res.x <= FT(1));
CGAL_postcondition(FT(0) <= res.y && res.y <= FT(1));
res.squared_distance = sq_dist(p1 + res.x*v1, p2 + res.y*v2);
CGAL_postcondition(res.squared_distance >= FT(0));
return res;
}
} // namespace internal
} // namespace Distance_3
namespace internal {
template <class K>
typename K::FT
squared_distance_parallel(const typename K::Segment_3& seg1,
const typename K::Segment_3& seg2,
const K& k)
{
typedef typename K::Vector_3 Vector_3;
typename K::Compute_squared_distance_3 sq_dist = k.compute_squared_distance_3_object();
const Vector_3 dir1 = seg1.direction().vector();
const Vector_3 dir2 = seg2.direction().vector();
if(same_direction(dir1, dir2, k))
{
if(!is_acute_angle(seg1.source(), seg1.target(), seg2.source(), k))
return sq_dist(seg1.target(), seg2.source(), k);
if(!is_acute_angle(seg1.target(), seg1.source(), seg2.target(), k))
return sq_dist(seg1.source(), seg2.target(), k);
}
else
{
if(!is_acute_angle(seg1.source(), seg1.target(), seg2.target(), k))
return sq_dist(seg1.target(), seg2.target(), k);
if(!is_acute_angle(seg1.target(), seg1.source(), seg2.source(), k))
return sq_dist(seg1.source(), seg2.source(), k);
}
return sq_dist(seg2.source(), seg1.supporting_line(), k);
}
template <typename K>
typename K::FT
squared_distance(const typename K::Segment_3& seg1,
const typename K::Segment_3& seg2,
const K& k)
{
Distance_3::internal::Segment_3_Segment_3_Result<K> res =
Distance_3::internal::squared_distance(seg1, seg2, k);
return res.squared_distance;
}
} // namespace internal
template <class K>
inline
typename K::FT
squared_distance_parallel(const Segment_3<K>& seg1,
const Segment_3<K>& seg2)
{
return internal::squared_distance_parallel(seg1, seg2, K());
}
template <class K>
inline
typename K::FT
squared_distance(const Segment_3<K>& seg1,
const Segment_3<K>& seg2)
{
return K().compute_squared_distance_3_object()(seg1, seg2);
}
} // namespace CGAL
#endif // CGAL_DISTANCE_3_SEGMENT_3_SEGMENT_3_H

View File

@ -0,0 +1,229 @@
// Copyright (c) 1998-2021
// Utrecht University (The Netherlands),
// ETH Zurich (Switzerland),
// INRIA Sophia-Antipolis (France),
// Max-Planck-Institute Saarbruecken (Germany),
// and Tel-Aviv University (Israel). All rights reserved.
//
// This file is part of CGAL (www.cgal.org)
//
// $URL$
// $Id$
// SPDX-License-Identifier: LGPL-3.0-or-later OR LicenseRef-Commercial
//
//
// Author(s) : Mael Rouxel-Labbé
#ifndef CGAL_DISTANCE_3_TRIANGLE_3_TRIANGLE_3_H
#define CGAL_DISTANCE_3_TRIANGLE_3_TRIANGLE_3_H
#include <CGAL/Distance_3/Point_3_Point_3.h>
#include <CGAL/Distance_3/Segment_3_Segment_3.h>
#include <CGAL/Triangle_3.h>
namespace CGAL {
namespace Distance_3 {
namespace internal {
template <typename K>
std::pair<Segment_3_Segment_3_Result<K>, bool>
test_edge_pair(const typename K::Point_3& p1,
const typename K::Point_3& q1,
const typename K::Point_3& r1,
const typename K::Point_3& p2,
const typename K::Point_3& q2,
const typename K::Point_3& r2,
const K& k,
typename K::FT& global_min_sqd,
bool& are_triangles_known_to_be_disjoint)
{
typedef typename K::FT FT;
typedef typename K::Point_3 Point_3;
typedef typename K::Vector_3 Vector_3;
typename K::Compute_scalar_product_3 scalar_product = k.compute_scalar_product_3_object();
typename K::Construct_segment_3 segment = k.construct_segment_3_object();
typename K::Construct_scaled_vector_3 scale_vector = k.construct_scaled_vector_3_object();
typename K::Construct_vector_3 vector = k.construct_vector_3_object();
typename K::Construct_translated_point_3 translate = k.construct_translated_point_3_object();
Distance_3::internal::Segment_3_Segment_3_Result<K> res =
internal::squared_distance(segment(p1, q1), segment(p2, q2), k);
if(res.squared_distance <= global_min_sqd)
global_min_sqd = res.squared_distance;
else
return std::make_pair(res, false);
const Vector_3 v1 = vector(p1, q1), v2 = vector(p2, q2);
const Point_3 m1 = translate(p1, scale_vector(v1, res.x));
const Point_3 m2 = translate(p2, scale_vector(v2, res.y));
const Vector_3 vr1 = vector(m1, r1), vr2 = vector(m2, r2);
const Vector_3 n = vector(m1, m2);
const FT sp_r1 = scalar_product(vr1, n);
const FT sp_r2 = scalar_product(vr2, n);
const bool is_r1_closer = (sp_r1 > 0); // Plane_3{m1, n}.has_on_positive_side(r1);
const bool is_r2_closer = (sp_r2 < 0); // Plane_3{m2, -n}.has_on_positive_side(r2);
const bool is_best_pair = !is_r1_closer && !is_r2_closer;
// Even if it is not the best pair, one may be able to deduce if the triangles do not intersect
// by checking if there is a void space between the planes orthogonal to the vector realizing
// the min distance between the edges and passing through the third points.
if(!is_best_pair)
{
FT separating_distance = res.squared_distance;
if(is_r1_closer)
separating_distance -= sp_r1;
if(is_r2_closer)
separating_distance += sp_r2;
if(separating_distance > 0)
are_triangles_known_to_be_disjoint = true;
}
return std::make_pair(res, is_best_pair);
}
template <typename K>
std::pair<typename K::FT, bool>
test_vertex_triangle(const typename K::Triangle_3& tr1,
const typename K::Triangle_3& tr2,
const K& k,
bool& are_triangles_known_to_be_disjoint)
{
typedef typename K::FT FT;
typedef typename K::Point_3 Point_3;
typedef typename K::Vector_3 Vector_3;
typename K::Compute_scalar_product_3 scalar_product = k.compute_scalar_product_3_object();
typename K::Construct_cross_product_vector_3 cross_product = k.construct_cross_product_vector_3_object();
typename K::Construct_vector_3 vector = k.construct_vector_3_object();
typename K::Construct_vertex_3 vertex = k.construct_vertex_3_object();
const Point_3& p1 = vertex(tr1, 0);
const Point_3& q1 = vertex(tr1, 1);
const Point_3& r1 = vertex(tr1, 2);
const Point_3& p2 = vertex(tr2, 0);
const Point_3& q2 = vertex(tr2, 1);
const Point_3& r2 = vertex(tr2, 2);
const Vector_3 p2q2 = vector(p2, q2);
const Vector_3 p2r2 = vector(p2, r2);
const Vector_3 n2 = cross_product(p2q2, p2r2);
if(scalar_product(n2, n2) == FT(0))
return std::make_pair(0, false);
std::array<FT, 3> sps = { scalar_product(vector(p2, p1), n2),
scalar_product(vector(p2, q1), n2),
scalar_product(vector(p2, r1), n2) };
// All the vertices of tr1 must be on the same side of tr2
// Coplanarity is tolerated, so '1' and '0' should be allowed, but not '1' and '-1'
if(CGAL::sign(sps[0]) == - CGAL::sign(sps[1]) || CGAL::sign(sps[1]) == - CGAL::sign(sps[2]))
return std::make_pair(0, false);
std::for_each(sps.begin(), sps.end(), [](FT& v) { v = abs(v); });
const auto min_pos = std::min_element(sps.begin(), sps.end());
const std::size_t min_id = static_cast<std::size_t>(std::distance(sps.begin(), min_pos));
if(sps[min_id] > 0)
are_triangles_known_to_be_disjoint = true;
const Point_3& x1 = vertex(tr1, static_cast<int>(min_id));
if(CGAL::internal::on_left_of_triangle_edge(x1, n2, p2, q2, k) &&
CGAL::internal::on_left_of_triangle_edge(x1, n2, q2, r2, k) &&
CGAL::internal::on_left_of_triangle_edge(x1, n2, r2, p2, k))
{
// the projection of `x1` is inside the triangle
return std::make_pair(CGAL::internal::squared_distance_to_plane(n2, vector(p2, x1), k), true);
}
return std::make_pair(0, false);
}
} // namespace internal
} // namespace Distance_3
namespace internal {
template <typename K>
typename K::FT
squared_distance(const typename K::Triangle_3& tr1,
const typename K::Triangle_3& tr2,
const K& k)
{
typedef typename K::FT FT;
typename K::Construct_vertex_3 vertex = k.construct_vertex_3_object();
// ideally just limits<FT>::infinity|max(), but it is not available for exact NTs...
FT global_min_sqd = squared_distance(vertex(tr1, 0), vertex(tr2, 0));
bool are_triangles_known_to_be_disjoint = false;
std::pair<Distance_3::internal::Segment_3_Segment_3_Result<K>, bool> ss_res;
for(int i=0; i<3; ++i)
{
for(int j=0; j<3; ++j)
{
ss_res = Distance_3::internal::test_edge_pair(
vertex(tr1, i%3), vertex(tr1, (i+1)%3), vertex(tr1, (i+2)%3),
vertex(tr2, j%3), vertex(tr2, (j+1)%3), vertex(tr2, (j+2)%3), k,
global_min_sqd, are_triangles_known_to_be_disjoint);
if(ss_res.second)
return ss_res.first.squared_distance;
}
}
// Failed to find a minimum between segment pairs, explore vertex-triangle distances
#if 1
std::pair<FT, bool> pt_res =
Distance_3::internal::test_vertex_triangle(tr1, tr2, k, are_triangles_known_to_be_disjoint);
if(pt_res.second)
return pt_res.first;
pt_res = Distance_3::internal::test_vertex_triangle(tr2, tr1, k, are_triangles_known_to_be_disjoint);
if(pt_res.second)
return pt_res.first;
if(are_triangles_known_to_be_disjoint)
return global_min_sqd;
else
return 0;
#else // A tiny bit less efficient, but a lot clearer!
// @todo does not handle degenerate inputs
if(!are_triangles_known_to_be_disjoint && CGAL::do_intersect(tr1, tr2))
return 0;
FT sqd_p1 = CGAL::squared_distance(vertex(tr1, 0), tr2);
FT sqd_q1 = CGAL::squared_distance(vertex(tr1, 1), tr2);
FT sqd_r1 = CGAL::squared_distance(vertex(tr1, 2), tr2);
FT sqd_p2 = CGAL::squared_distance(vertex(tr2, 0), tr1);
FT sqd_q2 = CGAL::squared_distance(vertex(tr2, 1), tr1);
FT sqd_r2 = CGAL::squared_distance(vertex(tr2, 2), tr1);
const FT m = std::min({sqd_p1, sqd_q1, sqd_r1, sqd_p2, sqd_q2, sqd_r2});
return m;
#endif
}
} // namespace internal
template <class K>
inline
typename K::FT
squared_distance(const Triangle_3<K>& tr1,
const Triangle_3<K>& tr2)
{
return K().compute_squared_distance_3_object()(tr1, tr2);
}
} // namespace CGAL
#endif // CGAL_DISTANCE_3_TRIANGLE_3_TRIANGLE_3_H

View File

@ -0,0 +1,35 @@
// Copyright (c) 1998-2021
// Utrecht University (The Netherlands),
// ETH Zurich (Switzerland),
// INRIA Sophia-Antipolis (France),
// Max-Planck-Institute Saarbruecken (Germany),
// and Tel-Aviv University (Israel). All rights reserved.
//
// This file is part of CGAL (www.cgal.org)
//
// $URL$
// $Id$
// SPDX-License-Identifier: LGPL-3.0-or-later OR LicenseRef-Commercial
//
//
// Author(s) : Geert-Jan Giezeman, Andreas Fabri
#ifndef CGAL_DISTANCE_3_WEIGHTED_POINT_3_WEIGHTED_POINT_3_H
#define CGAL_DISTANCE_3_WEIGHTED_POINT_3_WEIGHTED_POINT_3_H
#include <CGAL/Weighted_point_3.h>
namespace CGAL {
template <class K>
inline
typename K::FT
squared_distance(const Weighted_point_3<K>& wpt1,
const Weighted_point_3<K>& wpt2)
{
return K().compute_squared_distance_3_object()(wpt1.point(), wpt2.point());
}
} // namespace CGAL
#endif // CGAL_DISTANCE_3_WEIGHTED_POINT_3_WEIGHTED_POINT_3_H

View File

@ -12,43 +12,34 @@
// SPDX-License-Identifier: LGPL-3.0-or-later OR LicenseRef-Commercial
//
//
// Author(s) : Geert-Jan Giezeman, Andreas Fabri
// Author(s) : Geert-Jan Giezeman
#ifndef CGAL_SQUARED_DISTANCE_UTILS_3_H
#define CGAL_SQUARED_DISTANCE_UTILS_3_H
#ifndef CGAL_DISTANCE_3_0_H
#define CGAL_DISTANCE_3_0_H
#include <CGAL/kernel_assertions.h>
#include <CGAL/determinant.h>
#include <CGAL/enum.h>
#include <CGAL/wmult.h>
#include <CGAL/Point_3.h>
#include <CGAL/Weighted_point_3.h>
#include <CGAL/Vector_3.h>
#include <CGAL/number_utils.h>
#include <CGAL/Rational_traits.h>
#include <CGAL/wmult.h>
namespace CGAL {
namespace internal {
template <class K>
bool is_null(const typename K::Vector_3 &v, const K&)
{
typedef typename K::RT RT;
return v.hx()==RT(0) && v.hy()==RT(0) && v.hz()==RT(0);
typedef typename K::RT RT;
return v.hx() == RT(0) && v.hy() == RT(0) && v.hz() == RT(0);
}
template <class K>
typename K::RT
wdot(const typename K::Vector_3 &u,
const typename K::Vector_3 &v,
const K&)
{
return (u.hx()*v.hx() + u.hy()*v.hy() + u.hz()*v.hz());
return (u.hx()*v.hx() + u.hy()*v.hy() + u.hz()*v.hz());
}
template <class K>
@ -72,12 +63,12 @@ wdot_tag(const typename K::Point_3 &p,
const K&,
const Homogeneous_tag&)
{
return ( (p.hx() * q.hw() - q.hx() * p.hw())
* (r.hx() * q.hw() - q.hx() * r.hw())
+ (p.hy() * q.hw() - q.hy() * p.hw())
* (r.hy() * q.hw() - q.hy() * r.hw())
+ (p.hz() * q.hw() - q.hz() * p.hw())
* (r.hz() * q.hw() - q.hz() * r.hw()));
return ( (p.hx() * q.hw() - q.hx() * p.hw())
* (r.hx() * q.hw() - q.hx() * r.hw())
+ (p.hy() * q.hw() - q.hy() * p.hw())
* (r.hy() * q.hw() - q.hy() * r.hw())
+ (p.hz() * q.hw() - q.hz() * p.hw())
* (r.hz() * q.hw() - q.hz() * r.hw()));
}
template <class K>
@ -93,9 +84,6 @@ wdot(const typename K::Point_3 &p,
return wdot_tag(p, q, r, k, tag);
}
template <class K>
typename K::Vector_3
wcross(const typename K::Vector_3 &u,
@ -103,13 +91,12 @@ wcross(const typename K::Vector_3 &u,
const K&)
{
typedef typename K::Vector_3 Vector_3;
return Vector_3(
return Vector_3(
u.hy()*v.hz() - u.hz()*v.hy(),
u.hz()*v.hx() - u.hx()*v.hz(),
u.hx()*v.hy() - u.hy()*v.hx());
}
template <class K>
inline
bool
@ -117,8 +104,8 @@ is_acute_angle(const typename K::Vector_3 &u,
const typename K::Vector_3 &v,
const K& k)
{
typedef typename K::RT RT;
return RT(wdot(u, v, k)) > RT(0) ;
typedef typename K::RT RT;
return RT(wdot(u, v, k)) > RT(0) ;
}
template <class K>
@ -128,8 +115,8 @@ is_straight_angle(const typename K::Vector_3 &u,
const typename K::Vector_3 &v,
const K& k)
{
typedef typename K::RT RT;
return RT(wdot(u, v, k)) == RT(0) ;
typedef typename K::RT RT;
return RT(wdot(u, v, k)) == RT(0) ;
}
template <class K>
@ -139,8 +126,8 @@ is_obtuse_angle(const typename K::Vector_3 &u,
const typename K::Vector_3 &v,
const K& k)
{
typedef typename K::RT RT;
return RT(wdot(u, v, k)) < RT(0) ;
typedef typename K::RT RT;
return RT(wdot(u, v, k)) < RT(0) ;
}
template <class K>
@ -151,8 +138,8 @@ is_acute_angle(const typename K::Point_3 &p,
const typename K::Point_3 &r,
const K& k)
{
typedef typename K::RT RT;
return RT(wdot(p, q, r, k)) > RT(0) ;
typedef typename K::RT RT;
return RT(wdot(p, q, r, k)) > RT(0) ;
}
template <class K>
@ -163,8 +150,8 @@ is_straight_angle(const typename K::Point_3 &p,
const typename K::Point_3 &r,
const K& k)
{
typedef typename K::RT RT;
return RT(wdot(p, q, r, k)) == RT(0) ;
typedef typename K::RT RT;
return RT(wdot(p, q, r, k)) == RT(0) ;
}
template <class K>
@ -173,25 +160,15 @@ bool
is_obtuse_angle(const typename K::Point_3 &p,
const typename K::Point_3 &q,
const typename K::Point_3 &r,
const K& k)
const K& k)
{
typedef typename K::RT RT;
return RT(wdot(p, q, r, k)) < RT(0) ;
typedef typename K::RT RT;
return RT(wdot(p, q, r, k)) < RT(0) ;
}
template <class K>
inline
typename K::FT
squared_distance(const typename K::Point_3 & pt1,
const typename K::Point_3 & pt2,
const K& k)
{
return k.compute_squared_distance_3_object()(pt1, pt2);
}
template <class K>
void
squared_distance_to_plane_RT(const typename K::Vector_3 & normal,
const typename K::Vector_3 & diff,
squared_distance_to_plane_RT(const typename K::Vector_3& normal,
const typename K::Vector_3& diff,
typename K::RT& num,
typename K::RT& den,
const K& k)
@ -206,8 +183,8 @@ squared_distance_to_plane_RT(const typename K::Vector_3 & normal,
template <class K>
typename K::FT
squared_distance_to_plane(const typename K::Vector_3 & normal,
const typename K::Vector_3 & diff,
squared_distance_to_plane(const typename K::Vector_3& normal,
const typename K::Vector_3& diff,
const K& k)
{
typedef typename K::RT RT;
@ -219,8 +196,8 @@ squared_distance_to_plane(const typename K::Vector_3 & normal,
template <class K>
void
squared_distance_to_line_RT(const typename K::Vector_3 & dir,
const typename K::Vector_3 & diff,
squared_distance_to_line_RT(const typename K::Vector_3& dir,
const typename K::Vector_3& diff,
typename K::RT& num,
typename K::RT& den,
const K& k)
@ -233,8 +210,8 @@ squared_distance_to_line_RT(const typename K::Vector_3 & dir,
template <class K>
typename K::FT
squared_distance_to_line(const typename K::Vector_3 & dir,
const typename K::Vector_3 & diff,
squared_distance_to_line(const typename K::Vector_3& dir,
const typename K::Vector_3& diff,
const K& k)
{
typedef typename K::RT RT;
@ -271,7 +248,6 @@ same_direction_tag(const typename K::Vector_3 &u,
}
}
template <class K>
inline
bool
@ -299,7 +275,6 @@ same_direction_tag(const typename K::Vector_3 &u,
}
}
template <class K>
inline
bool
@ -312,70 +287,19 @@ same_direction(const typename K::Vector_3 &u,
return same_direction_tag(u, v, k, tag);
}
template <class K>
inline
typename K::RT
distance_measure_sub(typename K::RT startwdist, typename K::RT endwdist,
const typename K::Vector_3 &start,
const typename K::Vector_3 &end,
const K&)
{
return CGAL_NTS abs(wmult((K*)0, startwdist, end.hw())) -
CGAL_NTS abs(wmult((K*)0, endwdist, start.hw()));
}
} // namespace internal
} // namespace CGAL
template <class K>
inline
typename K::FT
squared_distance(const Point_3<K> & pt1,
const Point_3<K> & pt2)
{
return internal::squared_distance(pt1,pt2, K());
}
template <class K>
inline
typename K::FT
squared_distance(const Weighted_point_3<K> & pt1,
const Weighted_point_3<K> & pt2)
{
return internal::squared_distance(pt1.point(),pt2.point(), K());
}
template <class K>
inline
typename K::FT
squared_distance(const Weighted_point_3<K> & pt1,
const Point_3<K> & pt2)
{
return internal::squared_distance(pt1.point(),pt2, K());
}
template <class K>
inline
typename K::FT
squared_distance(const Point_3<K> & pt1,
const Weighted_point_3<K> & pt2)
{
return internal::squared_distance(pt1,pt2.point(), K());
}
template <class K>
inline
typename K::FT
squared_distance_to_plane(const Vector_3<K> & normal,
const Vector_3<K> & diff)
{
return internal::squared_distance_to_plane(normal, diff, K());
}
template <class K>
inline
typename K::FT
squared_distance_to_line(const Vector_3<K> & dir,
const Vector_3<K> & diff)
{
return internal::squared_distance_to_line(dir, diff, K());
}
} //namespace CGAL
#endif
#endif // CGAL_SQUARED_DISTANCE_UTILS_3_H

View File

@ -18,9 +18,31 @@
#ifndef CGAL_DISTANCE_3_H
#define CGAL_DISTANCE_3_H
#include <CGAL/squared_distance_3_0.h>
#include <CGAL/squared_distance_3_1.h>
#include <CGAL/squared_distance_3_2.h>
#include <CGAL/squared_distance_3_3.h>
#include <CGAL/Distance_3/Point_3_Point_3.h>
#include <CGAL/Distance_3/Point_3_Weighted_point_3.h>
#include <CGAL/Distance_3/Point_3_Segment_3.h>
#include <CGAL/Distance_3/Point_3_Ray_3.h>
#include <CGAL/Distance_3/Point_3_Line_3.h>
#include <CGAL/Distance_3/Point_3_Triangle_3.h>
#include <CGAL/Distance_3/Point_3_Plane_3.h>
#include <CGAL/Distance_3/Point_3_Tetrahedron_3.h>
#endif
#include <CGAL/Distance_3/Weighted_point_3_Weighted_point_3.h>
#include <CGAL/Distance_3/Segment_3_Segment_3.h>
#include <CGAL/Distance_3/Segment_3_Ray_3.h>
#include <CGAL/Distance_3/Segment_3_Line_3.h>
#include <CGAL/Distance_3/Segment_3_Plane_3.h>
#include <CGAL/Distance_3/Ray_3_Ray_3.h>
#include <CGAL/Distance_3/Ray_3_Line_3.h>
#include <CGAL/Distance_3/Ray_3_Plane_3.h>
#include <CGAL/Distance_3/Line_3_Line_3.h>
#include <CGAL/Distance_3/Line_3_Plane_3.h>
#include <CGAL/Distance_3/Triangle_3_Triangle_3.h>
#include <CGAL/Distance_3/Plane_3_Plane_3.h>
#endif // CGAL_DISTANCE_3_H

File diff suppressed because it is too large Load Diff

View File

@ -1,505 +0,0 @@
// Copyright (c) 1998-2004
// Utrecht University (The Netherlands),
// ETH Zurich (Switzerland),
// INRIA Sophia-Antipolis (France),
// Max-Planck-Institute Saarbruecken (Germany),
// and Tel-Aviv University (Israel). All rights reserved.
//
// This file is part of CGAL (www.cgal.org)
//
// $URL$
// $Id$
// SPDX-License-Identifier: LGPL-3.0-or-later OR LicenseRef-Commercial
//
//
// Author(s) : Geert-Jan Giezeman, Andreas Fabri
#ifndef CGAL_DISTANCE_3_2_H
#define CGAL_DISTANCE_3_2_H
#include <CGAL/squared_distance_3_0.h>
#include <CGAL/squared_distance_3_1.h>
#include <CGAL/wmult.h>
#include <CGAL/Point_3.h>
#include <CGAL/Segment_3.h>
#include <CGAL/Line_3.h>
#include <CGAL/Ray_3.h>
#include <CGAL/Triangle_3.h>
#include <CGAL/Plane_3.h>
namespace CGAL {
namespace internal {
template <class K>
bool
contains_vector(const typename K::Plane_3 &pl,
const typename K::Vector_3 &vec,
const K&)
{
typedef typename K::RT RT;
return pl.a()*vec.hx() + pl.b()*vec.hy() + pl.c() * vec.hz() == RT(0);
}
template <class K>
inline typename K::FT
squared_distance(
const typename K::Point_3 & pt,
const typename K::Plane_3 & plane,
const K& k)
{
typename K::Construct_vector_3 construct_vector;
typedef typename K::Vector_3 Vector_3;
Vector_3 diff = construct_vector(plane.point(), pt);
return squared_distance_to_plane(plane.orthogonal_vector(), diff, k);
}
template <class K>
inline typename K::FT
squared_distance(
const typename K::Plane_3 & plane,
const typename K::Point_3 & pt,
const K& k)
{
return squared_distance(pt, plane, k);
}
template <class K>
typename K::FT
squared_distance(
const typename K::Line_3 &line,
const typename K::Plane_3 &plane,
const K& k)
{
typedef typename K::FT FT;
if (contains_vector(plane, line.direction().vector(), k))
return squared_distance(plane, line.point(), k);
return FT(0);
}
template <class K>
inline typename K::FT
squared_distance(
const typename K::Plane_3 & p,
const typename K::Line_3 & line,
const K& k)
{
return squared_distance(line, p, k);
}
template <class K>
typename K::FT
squared_distance(
const typename K::Ray_3 &ray,
const typename K::Plane_3 &plane,
const K& k)
{
typename K::Construct_vector_3 construct_vector;
typedef typename K::Point_3 Point_3;
typedef typename K::Vector_3 Vector_3;
typedef typename K::RT RT;
typedef typename K::FT FT;
const Point_3 &start = ray.start();
const Point_3 &planepoint = plane.point();
Vector_3 start_min_pp = construct_vector(planepoint, start);
Vector_3 end_min_pp = ray.direction().vector();
const Vector_3 &normal = plane.orthogonal_vector();
RT sdm_rs2pp = wdot(normal, start_min_pp, k);
RT sdm_re2pp = wdot(normal, end_min_pp, k);
switch (CGAL_NTS sign(sdm_rs2pp)) {
case -1:
if (sdm_re2pp > RT(0))
return FT(0);
return squared_distance_to_plane(normal, start_min_pp, k);
case 0:
default:
return FT(0);
case 1:
if (sdm_re2pp < RT(0))
return FT(0);
return squared_distance_to_plane(normal, start_min_pp, k);
}
}
template <class K>
inline typename K::FT
squared_distance(
const typename K::Plane_3 & plane,
const typename K::Ray_3 & ray,
const K& k)
{
return squared_distance(ray, plane, k);
}
template <class K>
typename K::FT
squared_distance(
const typename K::Segment_3 &seg,
const typename K::Plane_3 &plane,
const K& k)
{
typename K::Construct_vector_3 construct_vector;
typedef typename K::Point_3 Point_3;
typedef typename K::Vector_3 Vector_3;
typedef typename K::RT RT;
typedef typename K::FT FT;
const Point_3 &start = seg.start();
const Point_3 &end = seg.end();
if (start == end)
return squared_distance(start, plane, k);
const Point_3 &planepoint = plane.point();
Vector_3 start_min_pp = construct_vector(planepoint, start);
Vector_3 end_min_pp = construct_vector(planepoint, end);
const Vector_3 &normal = plane.orthogonal_vector();
RT sdm_ss2pp = wdot(normal, start_min_pp, k);
RT sdm_se2pp = wdot(normal, end_min_pp, k);
switch (CGAL_NTS sign(sdm_ss2pp)) {
case -1:
if (sdm_se2pp >= RT(0))
return FT(0);
if (sdm_ss2pp * end_min_pp.hw() >= sdm_se2pp * start_min_pp.hw())
return squared_distance_to_plane(normal, start_min_pp, k);
else
return squared_distance_to_plane(normal, end_min_pp, k);
case 0:
default:
return FT(0);
case 1:
if (sdm_se2pp <= RT(0))
return FT(0);
if (sdm_ss2pp * end_min_pp.hw() <= sdm_se2pp * start_min_pp.hw())
return squared_distance_to_plane(normal, start_min_pp, k);
else
return squared_distance_to_plane(normal, end_min_pp, k);
}
}
template <class K>
inline typename K::FT
squared_distance(
const typename K::Plane_3 & plane,
const typename K::Segment_3 & seg,
const K& k)
{
return squared_distance(seg, plane, k);
}
template <class K>
inline bool
on_left_of_triangle_edge(const typename K::Point_3 & pt,
const typename K::Vector_3 & normal,
const typename K::Point_3 & ep0,
const typename K::Point_3 & ep1,
const K& k)
{
// return true iff pt is on the negative side of the plane defined
// by (ep0, ep1) and normal
typename K::Construct_vector_3 vector;
typename K::Vector_3 edge = vector(ep0, ep1);
typename K::Vector_3 diff = vector(ep0, pt);
typedef typename K::RT RT;
const bool result =
RT(wdot(wcross(edge,
normal,
k),
diff,
k)) <= RT(0);
return result;
}
template <class K>
inline void
squared_distance_to_triangle_RT(
const typename K::Point_3 & pt,
const typename K::Point_3 & t0,
const typename K::Point_3 & t1,
const typename K::Point_3 & t2,
bool & inside,
typename K::RT& num,
typename K::RT& den,
const K& k)
{
typename K::Construct_vector_3 vector;
typedef typename K::Vector_3 Vector_3;
const Vector_3 e1 = vector(t0, t1);
const Vector_3 oe3 = vector(t0, t2);
const Vector_3 normal = wcross(e1, oe3, k);
if(normal == NULL_VECTOR) {
// The case normal==NULL_VECTOR covers the case when the triangle
// is colinear, or even more degenerate. In that case, we can
// simply take also the distance to the three segments.
squared_distance_RT(pt, typename K::Segment_3(t2, t0), num, den, k);
typename K::RT num2, den2;
squared_distance_RT(pt, typename K::Segment_3(t1, t2), num2, den2, k);
if(compare_quotients(num2,den2, num,den) == SMALLER) {
num = num2;
den = den2;
}
// should not be needed since at most 2 edges cover the full triangle in the degenerate case
squared_distance_RT(pt, typename K::Segment_3(t0, t1), num2, den2, k);
if(compare_quotients(num2,den2, num,den) == SMALLER){
num = num2;
den = den2;
}
return;
}
const bool b01 = on_left_of_triangle_edge(pt, normal, t0, t1, k);
if(!b01) {
squared_distance_RT(pt, typename K::Segment_3(t0, t1), num, den, k);
return;
}
const bool b12 = on_left_of_triangle_edge(pt, normal, t1, t2, k);
if(!b12) {
squared_distance_RT(pt, typename K::Segment_3(t1, t2), num, den, k);
return;
}
const bool b20 = on_left_of_triangle_edge(pt, normal, t2, t0, k);
if(!b20) {
squared_distance_RT(pt, typename K::Segment_3(t2, t0), num, den, k);
return;
}
// The projection of pt is inside the triangle
inside = true;
squared_distance_to_plane_RT(normal, vector(t0, pt), num, den, k);
}
template <class K>
void
squared_distance_RT(
const typename K::Point_3 & pt,
const typename K::Triangle_3 & t,
typename K::RT& num,
typename K::RT& den,
const K& k)
{
typename K::Construct_vertex_3 vertex;
bool inside = false;
squared_distance_to_triangle_RT(pt,
vertex(t, 0),
vertex(t, 1),
vertex(t, 2),
inside,
num,
den,
k);
}
template <class K>
inline typename K::FT
squared_distance_to_triangle(
const typename K::Point_3 & pt,
const typename K::Point_3 & t0,
const typename K::Point_3 & t1,
const typename K::Point_3 & t2,
bool & inside,
const K& k)
{
typename K::Construct_vector_3 vector;
typedef typename K::Vector_3 Vector_3;
const Vector_3 e1 = vector(t0, t1);
const Vector_3 oe3 = vector(t0, t2);
const Vector_3 normal = wcross(e1, oe3, k);
if(normal == NULL_VECTOR) {
// The case normal==NULL_VECTOR covers the case when the triangle
// is colinear, or even more degenerate. In that case, we can
// simply take also the distance to the three segments.
typename K::FT d1 = squared_distance(pt, typename K::Segment_3(t2, t0), k);
typename K::FT d2 = squared_distance(pt, typename K::Segment_3(t1, t2), k);
// should not be needed since at most 2 edges cover the full triangle in the degenerate case
typename K::FT d3 = squared_distance(pt, typename K::Segment_3(t0, t1), k);
return (std::min)( (std::min)(d1, d2), d3);
}
const bool b01 = on_left_of_triangle_edge(pt, normal, t0, t1, k);
if(!b01) {
return internal::squared_distance(pt, typename K::Segment_3(t0, t1), k);
}
const bool b12 = on_left_of_triangle_edge(pt, normal, t1, t2, k);
if(!b12) {
return internal::squared_distance(pt, typename K::Segment_3(t1, t2), k);
}
const bool b20 = on_left_of_triangle_edge(pt, normal, t2, t0, k);
if(!b20) {
return internal::squared_distance(pt, typename K::Segment_3(t2, t0), k);
}
// The projection of pt is inside the triangle
inside = true;
return squared_distance_to_plane(normal, vector(t0, pt), k);
}
template <class K>
inline typename K::FT
squared_distance(
const typename K::Point_3 & pt,
const typename K::Triangle_3 & t,
const K& k)
{
typename K::Construct_vertex_3 vertex = k.construct_vertex_3_object();
bool inside = false;
return squared_distance_to_triangle(pt,
vertex(t, 0),
vertex(t, 1),
vertex(t, 2),
inside,
k);
}
} // namespace internal
template <class K>
bool
contains_vector(const Plane_3<K> &pl, const Vector_3<K> &vec)
{
return internal::contains_vector(pl,vec, K());
}
template <class K>
inline
typename K::FT
squared_distance(
const Point_3<K> & pt,
const Plane_3<K> & plane)
{
return internal::squared_distance(pt, plane, K());
}
template <class K>
inline
typename K::FT
squared_distance(
const Plane_3<K> & plane,
const Point_3<K> & pt)
{
return internal::squared_distance(pt, plane, K());
}
template <class K>
inline
typename K::FT
squared_distance(
const Line_3<K> &line,
const Plane_3<K> &plane)
{
return internal::squared_distance(line, plane, K());
}
template <class K>
inline
typename K::FT
squared_distance(
const Plane_3<K> & p,
const Line_3<K> & line)
{
return internal::squared_distance(line, p, K());
}
template <class K>
inline
typename K::FT
squared_distance(
const Ray_3<K> &ray,
const Plane_3<K> &plane)
{
return internal::squared_distance(ray, plane, K());
}
template <class K>
inline
typename K::FT
squared_distance(
const Plane_3<K> & plane,
const Ray_3<K> & ray)
{
return internal::squared_distance(ray, plane, K());
}
template <class K>
inline
typename K::FT
squared_distance(
const Segment_3<K> &seg,
const Plane_3<K> &plane)
{
return internal::squared_distance(seg, plane, K());
}
template <class K>
inline
typename K::FT
squared_distance(
const Plane_3<K> & plane,
const Segment_3<K> & seg)
{
return internal::squared_distance(seg, plane, K());
}
template <class K>
inline
typename K::FT
squared_distance(const Point_3<K> & pt,
const Triangle_3<K> & t) {
return internal::squared_distance(pt, t, K());
}
template <class K>
inline
typename K::FT
squared_distance(const Triangle_3<K> & t,
const Point_3<K> & pt) {
return internal::squared_distance(pt, t, K());
}
template <class K>
inline
typename K::FT
squared_distance(const Plane_3<K> & p1,
const Plane_3<K> & p2) {
K k;
typename K::Construct_orthogonal_vector_3 ortho_vec =
k.construct_orthogonal_vector_3_object();
if (!internal::is_null(internal::wcross(ortho_vec(p1), ortho_vec(p2), k), k))
return typename K::FT(0);
else
return internal::squared_distance(p1.point(), p2, k);
}
} //namespace CGAL
#endif

View File

@ -1,126 +0,0 @@
// Copyright (c) 1998-2021
// Utrecht University (The Netherlands),
// ETH Zurich (Switzerland),
// INRIA Sophia-Antipolis (France),
// Max-Planck-Institute Saarbruecken (Germany),
// and Tel-Aviv University (Israel). All rights reserved.
//
// This file is part of CGAL (www.cgal.org)
//
// $URL$
// $Id$
// SPDX-License-Identifier: LGPL-3.0-or-later OR LicenseRef-Commercial
//
//
// Author(s) : Geert-Jan Giezeman, Andreas Fabri
#ifndef CGAL_DISTANCE_3_3_H
#define CGAL_DISTANCE_3_3_H
#include <CGAL/squared_distance_3_2.h>
#include <CGAL/Point_3.h>
#include <CGAL/Tetrahedron_3.h>
namespace CGAL {
namespace internal {
template <class K>
inline
typename K::FT
squared_distance(const typename K::Tetrahedron_3 & t,
const typename K::Point_3 & pt,
const K& k)
{
bool on_bounded_side = true;
const typename K::Point_3 t0 = t[0];
const typename K::Point_3 t1 = t[1];
const typename K::Point_3 t2 = t[2];
const typename K::Point_3 t3 = t[3];
bool dmin_initialized = false;
typename K::FT dmin;
bool inside = false;
if(orientation(t0,t1,t2, pt) == NEGATIVE){
on_bounded_side = false;
dmin = squared_distance_to_triangle(pt, t0, t1, t2, inside, k);
dmin_initialized = true;
if(inside){
return dmin;
}
}
if(orientation(t0,t3,t1, pt) == NEGATIVE){
on_bounded_side = false;
const typename K::FT d = squared_distance_to_triangle(pt, t0, t3, t1, inside, k);
if(inside){
return d;
}
if(! dmin_initialized){
dmin = d;
dmin_initialized = true;
}else{
dmin = (std::min)(d,dmin);
}
}
if(orientation(t1,t3,t2, pt) == NEGATIVE){
on_bounded_side = false;
const typename K::FT d = squared_distance_to_triangle(pt, t1, t3, t2, inside, k);
if(inside){
return d;
}
if(! dmin_initialized){
dmin = d;
dmin_initialized = true;
}else{
dmin = (std::min)(d,dmin);
}
}
if(orientation(t2,t3,t0, pt) == NEGATIVE){
on_bounded_side = false;
const typename K::FT d = squared_distance_to_triangle(pt, t2, t3, t0, inside, k);
if(inside){
return d;
}
if(! dmin_initialized){
dmin = d;
dmin_initialized = true;
}else{
dmin = (std::min)(d,dmin);
}
}
if(on_bounded_side){
return typename K::FT(0);
}
return dmin;
}
} // namespace internal
template <class K>
typename K::FT
squared_distance(const Tetrahedron_3<K> & t,
const Point_3<K> & pt)
{
return internal::squared_distance(t,pt,K());
}
template <class K>
typename K::FT
squared_distance(const Point_3<K> & pt,
const Tetrahedron_3<K> & t)
{
return internal::squared_distance(t,pt,K());
}
} //namespace CGAL
#endif

View File

@ -1,22 +1,33 @@
// 3D distance tests.
#ifdef NDEBUG
#undef NDEBUG //this testsuite requires NDEBUG to be not defined
#endif
#include <CGAL/Simple_cartesian.h>
#include <CGAL/Simple_homogeneous.h>
#include <CGAL/Exact_predicates_inexact_constructions_kernel.h>
#include <CGAL/Exact_predicates_exact_constructions_kernel.h>
#include <CGAL/Exact_integer.h>
#include <CGAL/Homogeneous.h>
#include <CGAL/squared_distance_3.h>
#include <CGAL/Random.h>
#include <CGAL/Timer.h>
// #define CGAL_USE_GTE_AS_SANITY_CHECK
#ifdef CGAL_USE_GTE_AS_SANITY_CHECK
#include <Mathematics/DistTriangle3Triangle3.h>
#include <Mathematics/DistSegmentSegment.h>
#endif
#include <vector>
#include <iostream>
#include <cassert>
#include <iostream>
const double epsilon = 0.001;
struct randomint {
struct randomint
{
randomint() ;
int get() const { return sequence[cur]; }
int next() { cur = (cur+1)%11; return get();}
int get() const { return sequence[cur]; }
int next() {
cur = (cur + 1) % 11;
return get();
}
private:
int sequence[11];
int cur;
@ -40,43 +51,32 @@ inline randomint::randomint()
randomint ri;
inline double to_nt(int d)
template <typename K>
struct Test
{
return double(d);
}
template < typename K >
struct Test {
typedef typename K::RT RT;
typedef typename K::FT FT;
typedef CGAL::Point_3< K > P;
typedef CGAL::Line_3< K > L;
typedef CGAL::Segment_3< K > S;
typedef CGAL::Ray_3< K > R;
typedef CGAL::Triangle_3< K > T;
typedef CGAL::Plane_3< K > Pl;
typedef CGAL::Iso_cuboid_3< K > Cub;
typedef CGAL::Tetrahedron_3< K > Tet;
typedef typename K::Point_3 P;
typedef typename K::Segment_3 S;
typedef typename K::Vector_3 V;
typedef typename K::Ray_3 R;
typedef typename K::Line_3 L;
typedef typename K::Triangle_3 T;
typedef typename K::Plane_3 Pl;
typedef typename K::Tetrahedron_3 Tet;
typedef typename K::Iso_cuboid_3 Cub;
private:
CGAL::Random& r;
const double epsilon = 1e-14;
int N = 10;
double m = 0, M = 1;
template < typename Type >
bool approx_equal_nt(const Type &t1, const Type &t2)
{
if (t1 == t2)
return true;
if (CGAL::abs(t1 - t2) / (CGAL::max)(CGAL::abs(t1), CGAL::abs(t2)) < epsilon)
return true;
std::cout << " Approximate comparison failed between : " << t1 << " and " << t2 << "\n";
return false;
}
template < typename O1, typename O2 >
void check_squared_distance(const O1& o1, const O2& o2, const FT& result)
{
assert(approx_equal_nt(CGAL::squared_distance(o1, o2), result));
assert(approx_equal_nt(CGAL::squared_distance(o2, o1), result));
}
public:
Test(CGAL::Random& r, const double epsilon) : r(r), epsilon(epsilon) { }
private:
inline RT to_nt(int d) const { return RT(d); }
P p(int x, int y, int z)
{
@ -84,34 +84,119 @@ struct Test {
return P(to_nt(x*w), to_nt(y*w), to_nt(z*w), to_nt(w));
}
P random_point() const
{
return P(r.get_double(m, M), r.get_double(m, M), r.get_double(m, M));
}
Pl pl(int a, int b, int c, int d)
{
int w = ri.next();
return Pl(to_nt(a*w), to_nt(b*w), to_nt(c*w), to_nt(d*w));
}
private:
template <typename Type>
bool are_equal(const Type& t1, const Type& t2, const bool verbose = true)
{
const FT diff = CGAL::abs(t1 - t2);
if(diff > std::numeric_limits<FT>::epsilon() &&
diff > epsilon * (CGAL::abs(t1) + CGAL::abs(t2)))
{
if(verbose)
{
std::cerr << "Approximate comparison failed (t1|t2): got " << t1 << " but expected " << t2 << std::endl;
std::cerr << "Diff: " << CGAL::abs(t1 - t2) << " vs eps: " << epsilon * (CGAL::abs(t1) + CGAL::abs(t2)) << std::endl;
}
return false;
}
return true;
}
template <typename O1, typename O2>
void check_ss_distance(const O1& o1, const O2& o2)
{
FT res = CGAL::squared_distance(o1, o2);
FT asd = compute_squared_distance_interval_between_segments(o1.source(), o1.target(),
o2.source(), o2.target(), K());
assert(res == asd);
std::cout << "input: " << o1.source() << " " << o1.target() << " " << o2.source() << " " << o2.target() << std::endl;
std::cout << "result (old) = " << res << std::endl;
std::cout << "result (new) = " << asd << std::endl;
}
void do_intersect_check(const P&, const P&) { }
template <typename O2>
void do_intersect_check(const P& p, const O2& o2)
{
if(!o2.is_degenerate() && CGAL::do_intersect(p, o2))
{
assert(are_equal(CGAL::squared_distance(p, o2), FT(0)));
assert(are_equal(CGAL::squared_distance(o2, p), FT(0)));
}
}
template <typename O1, typename O2>
void do_intersect_check(const O1& o1, const O2& o2)
{
if(!o1.is_degenerate() && !o2.is_degenerate() && CGAL::do_intersect(o1, o2))
{
assert(are_equal(CGAL::squared_distance(o1, o2), FT(0)));
assert(are_equal(CGAL::squared_distance(o2, o1), FT(0)));
}
}
template <typename O1, typename O2>
void check_squared_distance(const O1& o1, const O2& o2, const FT& expected_result)
{
const FT res_o1o2 = CGAL::squared_distance(o1, o2);
const FT res_o2o1 = CGAL::squared_distance(o2, o1);
assert(are_equal(res_o1o2, expected_result));
assert(are_equal(res_o2o1, expected_result));
do_intersect_check(o1, o2);
do_intersect_check(o1, o2);
}
template <typename O1, typename O2>
void check_squared_distance_with_bound(const O1& o1, const O2& o2, const FT& ubound)
{
const FT res_o1o2 = CGAL::squared_distance(o1, o2);
const FT res_o2o1 = CGAL::squared_distance(o2, o1);
do_intersect_check(o1, o2);
do_intersect_check(o1, o2);
assert(res_o1o2 <= ubound);
assert(res_o2o1 <= ubound);
}
private:
void P_P()
{
std::cout << "Point - Point\n";
check_squared_distance (p(0, 0, 0), p(0, 0, 0), 0);
check_squared_distance (p(1, 1, 1), p(0, 0, 0), 3);
std::cout << "Point - Point" << std::endl;
check_squared_distance(p(0, 0, 0), p(0, 0, 0), 0);
check_squared_distance(p(3, 5, 7), p(0, 0, 0), 83);
}
void P_S()
{
// Note : the values are not verified by hand
std::cout << "Point - Segment\n";
check_squared_distance (p(0, 1, 2), S(p(-3, 0, 0), p( 2, 0, 0)), 5);
check_squared_distance (p(0, 1, 2), S(p( 3, 0, 0), p( 2, 0, 0)), 9);
check_squared_distance (p(0, 1, 2), S(p( 2, 0, 0), p( 3, 0, 0)), 9);
check_squared_distance (p(6, 1, 2), S(p( 2, 0, 0), p( 3, 0, 0)), 14);
std::cout << "Point - Segment" << std::endl;
check_squared_distance(p(0, 1, 2), S{p(-3, 0, 0), p( 2, 0, 0)}, 5);
check_squared_distance(p(0, 1, 2), S{p( 3, 0, 0), p( 2, 0, 0)}, 9);
check_squared_distance(p(0, 1, 2), S{p( 2, 0, 0), p( 3, 0, 0)}, 9);
check_squared_distance(p(6, 1, 2), S{p( 2, 0, 0), p( 3, 0, 0)}, 14);
}
void P_T()
{
std::cout << "Point - Triangle\n";
check_squared_distance (p(0, 1, 2), T(p(0, 0, 0), p( 2, 0, 0), p( 0, 2, 0)), 4);
std::cout << "Point - Triangle" << std::endl;
check_squared_distance(p(0, 1, 2), T{p(0, 0, 0), p(2, 0, 0), p(0, 2, 0)}, 4);
T t(p(0,0,0), p(3,0,0), p(3,3,0));
check_squared_distance (p(-1, -1, 0), t, 2);
@ -136,150 +221,475 @@ struct Test {
void S_S()
{
std::cout << "Segment - Segment\n";
check_squared_distance (S(p( -8, -7, 0), p( 11, 6, 0)), S(p(23, -27, 2), p( -17, 16, 2)), 4);
check_squared_distance (S(p( 0, 0, 0), p( 5, 0, 0)), S(p( 1, 1, 2), p( 6, 1, 2)), 5);
check_squared_distance (S(p( 0, 0, 0), p( 5, 0, 0)), S(p( 1, 1, 2), p( 2, 1, 2)), 5);
check_squared_distance (S(p( 5, 0, 0), p( 8, 0, 0)), S(p( 1, 1, 2), p( 2, 1, 2)), 14);
check_squared_distance (S(p( 5, 0, 0), p( 0, 0, 0)), S(p( 1, 1, 2), p( 2, 1, 2)), 5);
check_squared_distance (S(p( 0, 0, 0), p( 5, 0, 0)), S(p( 6, 1, 2), p( 8, 1, 2)), 6);
check_squared_distance (S(p( 0, 0, 0), p( 0,-3, 0)), S(p( 1, 4, 2), p( 1, 7, 2)), 21);
check_squared_distance (S(p( 0, 0, 0), p( 5, 0, 0)), S(p( 8, 1, 2), p( 6, 1, 2)), 6);
check_squared_distance (S(p( 0, 0, 0), p( 0, 0, 0)), S(p( 8, 1, 2), p( 6, 1, 2)), 41);
check_squared_distance (S(p( 0, 0, 0), p( 1, 0, 0)), S(p( 2, 1, 2), p( 2, -1, 2)), 5);
check_squared_distance (S(p( 2, 0, 0), p( 0, 2, 0)), S(p( 1, 1, 4), p( 4, 0, 4)), 16);
check_squared_distance (S(p( 10, 0, 0), p( 0,10, 0)), S(p( 6, 6,20), p( 20, 0,20)), 402);
check_squared_distance (S(p(-10,-13, 0), p( 0,10, 0)), S(p(10, 5,20), p( 70,-30,20)), 524.642);
check_squared_distance (S(p( 0, 0, 0), p(30,-10, 0)), S(p(-5, 20,20), p( 40, 30,20)), 824.706);
check_squared_distance (S(p( 4, 0, 0), p(-3, -1, 0)), S(p( 1, 1, 2), p( 2, 11, 2)), 6);
check_squared_distance (S(p( 3, 4, 0), p( 7, 7, 0)), S(p( 7, 0, 2), p( 6, 5, 2)), 5);
check_squared_distance (S(p( -1, 1, 0), p( 3, 4, 0)), S(p( 7, 0, 2), p( 6, 5, 2)), 13.8462);
std::cout << "Segment - Segment" << std::endl;
// coplanar segments (hardcoded)
double z = std::sqrt(2.);
P p0{-1, 0, z};
P p1{ 1, 0, z};
// translations of (0, -1, z) -- (0, 1, z) to have all variations of x&y (<0, [0;1]; >1) in the code
for(int j=-2;j<4; j+=2)
{
for(int k=-3;k<3; k+=2)
{
P p2{j, k, z};
P p3{j, k+2, z};
// to explicit the expected distances
if(j == -2 && k == -3)
check_squared_distance(S{p0, p1}, S{p2, p3}, CGAL::squared_distance(p3, p0));
else if(j == -2 && k == -1)
check_squared_distance(S{p0, p1}, S{p2, p3}, 1);
else if(j == -2 && k == 1)
check_squared_distance(S{p0, p1}, S{p2, p3}, CGAL::squared_distance(p2, p0));
else if(j == 0 && k == -3)
check_squared_distance(S{p0, p1}, S{p2, p3}, 1);
else if(j == 0 && k == -1)
check_squared_distance(S{p0, p1}, S{p2, p3}, 0);
else if(j == 0 && k == 1)
check_squared_distance(S{p0, p1}, S{p2, p3}, 1);
else if(j == 2 && k == -3)
check_squared_distance(S{p0, p1}, S{p2, p3}, CGAL::squared_distance(p3, p1));
else if(j == 2 && k == -1)
check_squared_distance(S{p0, p1}, S{p2, p3}, 1);
else if(j == 2 && k == 1)
check_squared_distance(S{p0, p1}, S{p2, p3}, CGAL::squared_distance(p2, p1));
}
}
for(int i=0; i<N; ++i)
{
P p0 = random_point();
P p1 = random_point();
P p2 = random_point();
P p3 = random_point();
p0 = CGAL::midpoint(p0, p1);
p1 = p0 + FT(0.1) * V{p1 - p0};
p2 = p2 + V{p2 - CGAL::ORIGIN} / CGAL::approximate_sqrt(CGAL::square(p2.x()) + CGAL::square(p2.y()) + CGAL::square(p2.z()) + 3);
p3 = p3 + V{p3 - CGAL::ORIGIN} * FT(std::cos(1.3));
// degenerate inputs
check_squared_distance(S{p0, p0}, S{p0, p0}, 0); // both degen
check_squared_distance(S{p3, p3}, S{p3, p3}, 0); // both degen
check_squared_distance(S{p0, p0}, S{p0, p1}, 0); // left degen + common extremity (left)
check_squared_distance(S{p0, p0}, S{p1, p0}, 0); // left degen + common extremity (right)
check_squared_distance(S{p0, p0}, S{p2, p3}, CGAL::squared_distance(p0, S(p2, p3))); // left degen
// common extremities
check_squared_distance(S{p2, p3}, S{p2, p3}, 0); // equal segments
check_squared_distance(S{p3, p2}, S{p2, p3}, 0); // equal segments but opposite dirs
check_squared_distance(S{p2, p3}, S{p2, p1}, 0); // common generic (p2 common)
check_squared_distance(S{p2, p3}, S{p1, p2}, 0); // common generic (p2 common)
check_squared_distance(S{p2, p3}, S{p3, p1}, 0); // common generic (p3 common)
check_squared_distance(S{p2, p3}, S{p1, p3}, 0); // common generic (p3 common)
// collinear segments
const double lambda_4 = r.get_double(0, 1);
const P p4 = p2 + FT(lambda_4) * V{p3 - p2};
const double lambda_5 = r.get_double(0, 1);
const P p5 = p2 + FT(lambda_5) * V{p3 - p2};
// [p2;p3) fully contains [p4;p5]
check_squared_distance(S{p2, p3}, S{p4, p5}, 0);
check_squared_distance(S{p2, p3}, S{p5, p4}, 0);
check_squared_distance(S{p3, p2}, S{p4, p5}, 0);
check_squared_distance(S{p3, p2}, S{p4, p5}, 0);
const double lambda_6 = r.get_double(0, 1);
const P p6 = p3 + FT(lambda_6) * V{p3 - p2};
// [p2;p3] overlaps [p5;p6]
check_squared_distance(S{p2, p3}, S{p6, p5}, 0);
check_squared_distance(S{p2, p3}, S{p5, p6}, 0);
check_squared_distance(S{p3, p2}, S{p6, p5}, 0);
check_squared_distance(S{p3, p2}, S{p6, p5}, 0);
const double lambda_7 = r.get_double(1, 2);
const P p7 = p3 + FT(lambda_7) * V{p3 - p2};
// [p2;p3] disjoint && left of [p6;p7]
check_squared_distance(S{p2, p3}, S{p6, p7}, CGAL::squared_distance(p3, p6));
check_squared_distance(S{p2, p3}, S{p7, p6}, CGAL::squared_distance(p3, p6));
check_squared_distance(S{p3, p2}, S{p6, p7}, CGAL::squared_distance(p3, p6));
check_squared_distance(S{p3, p2}, S{p7, p6}, CGAL::squared_distance(p3, p6));
// Generic collinear
const double lambda_8 = r.get_double(-M, M);
const P p8 = p2 + FT(lambda_8) * V{p3 - p2};
const double lambda_9 = r.get_double(-M, M);
const P p9 = p2 + FT(lambda_9) * V{p3 - p2};
S s89(p8, p9);
S s32(p3, p2);
FT result;
if(!s89.is_degenerate() && !s32.is_degenerate()) // for do_intersect...
{
if(CGAL::do_intersect(s89, s32))
result = 0;
else
result = (std::min)(CGAL::squared_distance(p2, p8),
(std::min)(CGAL::squared_distance(p2, p9),
(std::min)(CGAL::squared_distance(p3, p8),
CGAL::squared_distance(p3, p9))));
#ifdef CGAL_USE_GTE_AS_SANITY_CHECK
gte::DCPQuery<FT, gte::Segment<3, FT>, gte::Segment<3, FT> > GTE_SS_checker;
gte::Segment<3, FT> gte_s1{{p8.x(), p8.y(), p8.z()}, {p9.x(), p9.y(), p9.z()}};
gte::Segment<3, FT> gte_s2{{p3.x(), p3.y(), p3.z()}, {p2.x(), p2.y(), p2.z()}};
auto gte_res = GTE_SS_checker(gte_s1, gte_s2);
std::cout << "-------" << std::endl;
std::cout << "old: " << CGAL::internal::squared_distance_old(s89, s32, K()) << std::endl;
std::cout << "dist (GTE) : " << gte_res.sqrDistance << std::endl;
#endif
// Because do_intersect() with constructions is likely to return 'false' even for overlaps
assert(are_equal(CGAL::squared_distance(s89, s32), result, false /*verbose*/) ||
are_equal(CGAL::squared_distance(s32, s89), FT(0)));
}
// completely generic
S s1{p0, p1}, s2{p2, p3};
do_intersect_check(s1, s2);
#ifdef CGAL_USE_GTE_AS_SANITY_CHECK
gte::DCPQuery<FT, gte::Segment<3, FT>, gte::Segment<3, FT> > GTE_SS_checker;
gte::Segment<3, FT> gte_s1{{p0.x(), p0.y(), p0.z()}, {p1.x(), p1.y(), p1.z()}};
gte::Segment<3, FT> gte_s2{{p2.x(), p2.y(), p2.z()}, {p3.x(), p3.y(), p3.z()}};
auto gte_res = GTE_SS_checker(gte_s1, gte_s2);
std::cout << "dist (CGAL) : " << CGAL::squared_distance(s1, s2) << std::endl;
std::cout << "dist (GTE) : " << gte_res.sqrDistance << std::endl;
assert(are_equal(CGAL::squared_distance(s1, s2), gte_res.sqrDistance));
#endif
}
// a few brute force checks: sample a segments and use squared_distance(P3, S3)
for(int i=0; i<10; ++i)
{
P p0 = random_point();
P p1 = random_point();
P p2 = random_point();
P p3 = random_point();
S s01{p0, p1};
S s23{p2, p3};
FT upper_bound = CGAL::squared_distance(p0, p2);
V p01 = V{p0, p1} / FT(N);
for(int l=0; l<N; ++l)
{
P tp = p0 + FT(l) * p01;
FT sqd = CGAL::squared_distance(tp, s23);
if(sqd < upper_bound)
upper_bound = sqd;
}
// bit ugly, but if constructions are not exact, building `tp` introduces some error
if(epsilon != 0)
upper_bound *= (1 + 1e-10);
check_squared_distance_with_bound(s01, s23, upper_bound);
}
}
void P_R()
{
// Note : the value is not verified by hand
std::cout << "Point - Ray\n";
check_squared_distance (p( -8, -7, 0), R(p(23, -27, 2), p( -17, 16, 2)), 86.3685);
std::cout << "Point - Ray" << std::endl;
check_squared_distance_with_bound(p( -8, -7, 0), R{p(23, -27, 2), p( -17, 16, 2)}, 86.368512613);
}
void R_R()
{
// Note : the values are not verified by hand
std::cout << "Ray - Ray\n";
check_squared_distance (R(p( 0, 0, 30), p( 0, 30, 30)), R(p(100, -100, 0), p( 200, 1, 0)), 20899.5);
check_squared_distance (R(p( 1, 0, 0), p( 0, 0, 0)), R(p( 1, 3, 3), p( 0, 0, 3)), 9);
check_squared_distance (R(p( 0, 0, 0), p( 1, 0, 0)), R(p( 0, 0, 2), p( -1, 0, 2)), 4);
std::cout << "Ray - Ray" << std::endl;
check_squared_distance_with_bound(R{p( 0, 0, 30), p( 0, 30, 30)}, R{p(100, -100, 0), p( 200, 1, 0)}, 20899.504975002);
check_squared_distance(R{p( 1, 0, 0), p( 0, 0, 0)}, R{p( 1, 3, 3), p( 0, 0, 3)}, 9);
check_squared_distance(R{p( 0, 0, 0), p( 1, 0, 0)}, R{p( 0, 0, 2), p( -1, 0, 2)}, 4);
}
void S_R()
{
// Note : the values are not verified by hand
std::cout << "Segment - Ray\n";
check_squared_distance (S(p( 0, 0, 30), p( 0, 30, 30)), R(p(100, -100, 0), p( 200, 1, 0)), 20899.5);
std::cout << "Segment - Ray" << std::endl;
check_squared_distance_with_bound(S{p( 0, 0, 30), p( 0, 30, 30)}, R{p(100, -100, 0), p( 200, 1, 0)}, 20899.504975002);
}
void R_L()
{
// Note : the values are not verified by hand
std::cout << "Ray - Line\n";
check_squared_distance (R(p(10, 0, 0), p( 20, 0, 0)), L(p( 0, 0, 3), p( 0, 3, 3)), 109);
check_squared_distance (R(p( 0, 0, 30), p( 0, 30, 30)), L(p(100, -100, 0), p( 200, 1, 0)), 20899.5);
check_squared_distance (R(p( 1, 0, 0), p( 0, 0, 0)), L(p( 1, 3, 3), p( 0, 0, 3)), 9);
check_squared_distance (R(p( 0, 0, 0), p( 1, 0, 0)), L(p( 0, 0, 2), p( -1, 0, 2)), 4);
std::cout << "Ray - Line" << std::endl;
check_squared_distance_with_bound(R{p( 0, 0, 30), p( 0, 30, 30)}, L{p(100, -100, 0), p( 200, 1, 0)}, 20899.504975002);
check_squared_distance(R{p(10, 0, 0), p( 20, 0, 0)}, L{p( 0, 0, 3), p( 0, 3, 3)}, 109);
check_squared_distance(R{p( 1, 0, 0), p( 0, 0, 0)}, L{p( 1, 3, 3), p( 0, 0, 3)}, 9);
check_squared_distance(R{p( 0, 0, 0), p( 1, 0, 0)}, L{p( 0, 0, 2), p( -1, 0, 2)}, 4);
}
void P_L()
{
std::cout << "Point - Line\n";
check_squared_distance (p( 0, 1, 2), L(p( 2, 0, 0), p( 3, 0, 0)), 5);
check_squared_distance (p( 0, 0, 2), L(p( 0, 0, 0), p( 1, 2, 0)), 4);
std::cout << "Point - Line" << std::endl;
check_squared_distance(p( 0, 1, 2), L{p( 2, 0, 0), p( 3, 0, 0)}, 5);
check_squared_distance(p( 0, 0, 2), L{p( 0, 0, 0), p( 1, 2, 0)}, 4);
}
void S_L()
{
// Note : the values are not verified by hand
std::cout << "Segment - Line\n";
check_squared_distance (S(p( 1, 0, 0), p( 0, 0, 0)), L(p( 1, 3, 3), p( 0, 0, 3)), 9);
check_squared_distance (S(p(-90, 0, 0), p(-10, 0, 0)), L(p( 0, 0, 3), p( 0, 3, 3)), 109);
check_squared_distance (S(p( 0, 0, 0), p( 1, 0, 0)), L(p( 0, 0, 2), p( -1, 0, 2)), 4);
std::cout << "Segment - Line" << std::endl;
check_squared_distance(S{p( 1, 0, 0), p( 0, 0, 0)}, L{p( 1, 3, 3), p( 0, 0, 3)}, 9);
check_squared_distance(S{p(-90, 0, 0), p(-10, 0, 0)}, L{p( 0, 0, 3), p( 0, 3, 3)}, 109);
check_squared_distance(S{p( 0, 0, 0), p( 1, 0, 0)}, L{p( 0, 0, 2), p( -1, 0, 2)}, 4);
}
void L_L()
{
// Note : the values are not verified by hand
std::cout << "Line - Line\n";
check_squared_distance (L(p(-10, 0, 0), p(-90, 0, 0)), L(p( 0, 0, 3), p( 0, 3, 3)), 9);
check_squared_distance (L(p( 1, 0, 0), p( 0, 0, 0)), L(p( 1, 3, 3), p( 0, 0, 3)), 9);
check_squared_distance (L(p( 0, 0, 0), p( 1, 0, 0)), L(p( 0, 0, 2), p( -1, 0, 2)), 4);
std::cout << "Line - Line" << std::endl;
check_squared_distance(L{p(-10, 0, 0), p(-90, 0, 0)}, L{p( 0, 0, 3), p( 0, 3, 3)}, 9);
check_squared_distance(L{p( 1, 0, 0), p( 0, 0, 0)}, L{p( 1, 3, 3), p( 0, 0, 3)}, 9);
check_squared_distance(L{p( 0, 0, 0), p( 1, 0, 0)}, L{p( 0, 0, 2), p( -1, 0, 2)}, 4);
}
void P_Pl()
{
std::cout << "Point - Plane\n";
check_squared_distance (p(2, 5, 3), Pl(0, 1, 0, 0), 25);
std::cout << "Point - Plane" << std::endl;
check_squared_distance(p(2, 5, 3), Pl(0, 1, 0, 0), 25);
}
void S_Pl()
{
std::cout << "Segment - Plane\n";
check_squared_distance (S(p(2, -3, 3), p( 3,-7, 4)), pl(0, 1, 0, 0), 9);
std::cout << "Segment - Plane" << std::endl;
check_squared_distance(S{p(2, -3, 3), p( 3,-7, 4)}, pl(0, 1, 0, 0), 9);
}
void R_Pl()
{
std::cout << "Ray - Plane\n";
check_squared_distance (R(p(2, -4, 3), p( 3,-4, 4)), Pl(0, 1, 0, 0), 16);
check_squared_distance (R(p(2, -4, 3), p( 3, 4, 4)), Pl(0, 1, 0, 0), 0);
check_squared_distance (R(p(2, -4, 3), p( 3,-8, 4)), Pl(0, 1, 0, 0), 16);
std::cout << "Ray - Plane" << std::endl;
check_squared_distance(R{p(2, -4, 3), p( 3,-4, 4)}, Pl(0, 1, 0, 0), 16);
check_squared_distance(R{p(2, -4, 3), p( 3, 4, 4)}, Pl(0, 1, 0, 0), 0);
check_squared_distance(R{p(2, -4, 3), p( 3,-8, 4)}, Pl(0, 1, 0, 0), 16);
}
void L_Pl()
{
std::cout << "Line - Plane\n";
check_squared_distance (L(p(2, -4, 3), p( 3,-4, 4)), Pl(0, 1, 0, 0), 16);
check_squared_distance (L(p(2, -4, 3), p( 3, 4, 4)), Pl(0, 1, 0, 0), 0);
check_squared_distance (L(p(2, -4, 3), p( 3,-8, 4)), Pl(0, 1, 0, 0), 0);
std::cout << "Line - Plane" << std::endl;
check_squared_distance(L{p(2, -4, 3), p( 3,-4, 4)}, Pl(0, 1, 0, 0), 16);
check_squared_distance(L{p(2, -4, 3), p( 3, 4, 4)}, Pl(0, 1, 0, 0), 0);
check_squared_distance(L{p(2, -4, 3), p( 3,-8, 4)}, Pl(0, 1, 0, 0), 0);
}
void Pl_Pl()
{
std::cout << "Plane - Plane\n";
std::cout << "Plane - Plane" << std::endl;
Pl p1(0, 1, 0, 0);
typename K::Vector_3 v = -p1.orthogonal_vector();
v /= CGAL::sqrt(v.squared_length());
v /= CGAL::approximate_sqrt(v.squared_length());
Pl p2 = Pl(0,-1,0,6);
check_squared_distance (p1,p2, 36);
check_squared_distance (Pl(-2, 1, 1, 0), Pl(2, 1, 3, 0), 0);
check_squared_distance(p1,p2, 36);
check_squared_distance(Pl(-2, 1, 1, 0), Pl(2, 1, 3, 0), 0);
}
void T_T()
{
std::cout << "Triangle - Triangle" << std::endl;
// min between vertices (hardcoded)
check_squared_distance(T{p(0,0,0), p(1,0,0), p(0,1,0)}, T{p(0,0,2), p(-1,0,2), p(0,-1,2)}, 4);
check_squared_distance(T{p(0,0,0), p(1,0,0), p(0,1,0)}, T{p(-1,0,2), p(0,0,2), p(0,-1,2)}, 4);
check_squared_distance(T{p(1,2,3), P{4.2,5.3,-6}, p(7,-8,9)},
T{P{10.1, 12, -10}, p(15, 14, -12), p(19, 45, -20)},
CGAL::squared_distance(P{4.2,5.3,-6}, P{10.1, 12, -10}));
// min vertex-edge (hardcoded)
check_squared_distance(T{p(0,0,0), p(1,0,0), p(0,1,0)}, T{p(1,1,0), p(2,1,0), p(1,2,0)}, 0.5);
check_squared_distance(T{p(0,0,0), p(2,0,0), p(0,2,0)}, T{p(0,-1,1), p(2,0,1), p(2,-1,1)}, 1);
for(int i=0; i<N; ++i)
{
P p0 = random_point();
P p1 = random_point();
P p2 = random_point();
P p3 = random_point();
P p4 = random_point();
P p5 = random_point();
// these are still exact with EPECK
p0 = CGAL::midpoint(p0, p1);
p1 = p0 + FT(0.1) * V{p1 - p0};
p2 = p2 + V{p2 - p0} / FT(CGAL_PI);
// this is still exact with EPECK_with_sqrt
p4 = p4 + V{p4 - CGAL::ORIGIN} / CGAL::approximate_sqrt(CGAL::square(p4.x()) + CGAL::square(p4.y()) + CGAL::square(p4.z()) + 3);
p5 = p5 + V{p5 - CGAL::ORIGIN} * FT(std::cos(1.3));
// degenerate inputs
check_squared_distance(T{p3, p3, p3}, T{p3, p3, p3}, 0); // both degen
check_squared_distance(T{p0, p0, p0}, T{p3, p3, p3}, CGAL::squared_distance(p0, p3)); // both degen
check_squared_distance(T{p0, p0, p0}, T{p0, p0, p3}, 0); // single degen and common edge
check_squared_distance(T{p0, p0, p0}, T{p3, p0, p0}, 0);
check_squared_distance(T{p0, p0, p0}, T{p0, p3, p0}, 0);
check_squared_distance(T{p0, p0, p0}, T{p0, p3, p4}, 0); // single degen and common vertex
check_squared_distance(T{p0, p0, p0}, T{p3, p0, p4}, 0);
check_squared_distance(T{p0, p0, p0}, T{p3, p4, p0}, 0);
// degen into point & degen into segment
check_squared_distance(T{p1, p1, p1}, T{p4, p3, p3}, CGAL::squared_distance(p1, S{p3, p4}));
check_squared_distance(T{p5, p5, p5}, T{p3, p3, p4}, CGAL::squared_distance(p5, S{p3, p4}));
// both degen into segment
check_squared_distance(T{p0, p1, p0}, T{p3, p3, p4}, CGAL::squared_distance(S{p0, p1}, S{p3, p4}));
check_squared_distance(T{p5, p5, p4}, T{p4, p3, p3}, CGAL::squared_distance(S{p5, p4}, S{p3, p4}));
// common vertex
check_squared_distance(T{p0, p1, p2}, T{p0, p3, p4}, 0);
check_squared_distance(T{p0, p1, p2}, T{p3, p0, p4}, 0);
check_squared_distance(T{p0, p1, p2}, T{p4, p3, p0}, 0);
check_squared_distance(T{p0, p1, p2}, T{p1, p3, p4}, 0);
check_squared_distance(T{p0, p1, p2}, T{p3, p1, p4}, 0);
check_squared_distance(T{p0, p1, p2}, T{p4, p3, p1}, 0);
check_squared_distance(T{p0, p1, p2}, T{p2, p3, p4}, 0);
check_squared_distance(T{p0, p1, p2}, T{p3, p2, p4}, 0);
check_squared_distance(T{p0, p1, p2}, T{p4, p3, p2}, 0);
// common edge
check_squared_distance(T{p0, p1, p2}, T{p0, p1, p4}, 0);
check_squared_distance(T{p0, p1, p2}, T{p1, p0, p4}, 0);
check_squared_distance(T{p0, p1, p2}, T{p4, p0, p1}, 0);
check_squared_distance(T{p0, p1, p2}, T{p4, p1, p0}, 0);
check_squared_distance(T{p0, p1, p2}, T{p0, p4, p1}, 0);
check_squared_distance(T{p0, p1, p2}, T{p1, p4, p2}, 0);
check_squared_distance(T{p0, p1, p2}, T{p2, p1, p4}, 0);
check_squared_distance(T{p0, p1, p2}, T{p1, p2, p4}, 0);
check_squared_distance(T{p0, p1, p2}, T{p4, p2, p1}, 0);
check_squared_distance(T{p0, p1, p2}, T{p4, p1, p2}, 0);
check_squared_distance(T{p0, p1, p2}, T{p2, p4, p1}, 0);
check_squared_distance(T{p0, p1, p2}, T{p1, p4, p2}, 0);
check_squared_distance(T{p0, p1, p2}, T{p0, p2, p4}, 0);
check_squared_distance(T{p0, p1, p2}, T{p2, p0, p4}, 0);
check_squared_distance(T{p0, p1, p2}, T{p4, p0, p2}, 0);
check_squared_distance(T{p0, p1, p2}, T{p4, p2, p0}, 0);
check_squared_distance(T{p0, p1, p2}, T{p0, p4, p2}, 0);
check_squared_distance(T{p0, p1, p2}, T{p2, p4, p0}, 0);
// same triangle
check_squared_distance(T{p0, p1, p2}, T{p0, p1, p2}, 0);
check_squared_distance(T{p0, p1, p2}, T{p1, p2, p0}, 0);
check_squared_distance(T{p0, p1, p2}, T{p2, p0, p1}, 0);
check_squared_distance(T{p0, p1, p2}, T{p2, p1, p0}, 0);
check_squared_distance(T{p0, p1, p2}, T{p0, p2, p1}, 0);
check_squared_distance(T{p0, p1, p2}, T{p1, p0, p2}, 0);
// vertex on triangle
double lambda = r.get_double(0, 1);
double mu = r.get_double(0, 1 - lambda);
const P bp = CGAL::barycenter(p0, lambda, p1, mu, p2, 1 - lambda - mu);
check_squared_distance(T{p0, p1, p2}, T{bp, p3, p4}, 0);
check_squared_distance(T{p0, p1, p2}, T{p3, bp, p4}, 0);
check_squared_distance(T{p0, p1, p2}, T{p3, p4, bp}, 0);
// edge on triangle
lambda = r.get_double(0, 1);
mu = r.get_double(0, 1 - lambda);
P bp2 = CGAL::barycenter(p0, lambda, p1, mu, p2, 1 - lambda - mu);
check_squared_distance(T{p0, p1, p2}, T{bp, bp2, p4}, 0);
check_squared_distance(T{p0, p1, p2}, T{bp2, bp, p4}, 0);
check_squared_distance(T{p0, p1, p2}, T{bp, p4, bp2}, 0);
check_squared_distance(T{p0, p1, p2}, T{bp2, p4, bp}, 0);
check_squared_distance(T{p0, p1, p2}, T{p4, bp, bp2}, 0);
check_squared_distance(T{p0, p1, p2}, T{p4, bp2, bp}, 0);
// part of the edge crossing the triangle
lambda = r.get_double(-1, 1);
mu = r.get_double(-1, 1);
bp2 = CGAL::barycenter(p0, lambda, p1, mu, p2, 1 - lambda - mu);
check_squared_distance(T{p0, p1, p2}, T{bp, bp2, p4}, 0);
check_squared_distance(T{p0, p1, p2}, T{bp2, bp, p4}, 0);
check_squared_distance(T{p0, p1, p2}, T{bp, p4, bp2}, 0);
check_squared_distance(T{p0, p1, p2}, T{bp2, p4, bp}, 0);
check_squared_distance(T{p0, p1, p2}, T{p4, bp, bp2}, 0);
check_squared_distance(T{p0, p1, p2}, T{p4, bp2, bp}, 0);
// generic triangles
T tr1{p0, p1, p2}, tr2{p3, p4, p5};
do_intersect_check(tr1, tr2);
#ifdef CGAL_USE_GTE_AS_SANITY_CHECK
gte::DCPQuery<FT, gte::Triangle3<FT>, gte::Triangle3<FT> > GTE_TT_checker;
gte::Triangle3<FT> gte_tr1{{p0.x(), p0.y(), p0.z()}, {p1.x(), p1.y(), p1.z()}, {p2.x(), p2.y(), p2.z()}};
gte::Triangle3<FT> gte_tr2{{p3.x(), p3.y(), p3.z()}, {p4.x(), p4.y(), p4.z()}, {p5.x(), p5.y(), p5.z()}};
auto gte_res = GTE_TT_checker(gte_tr1, gte_tr2);
std::cout << "dist (CGAL) : " << CGAL::squared_distance(tr1, tr2) << std::endl;
std::cout << "dist (GTE) : " << gte_res.sqrDistance << std::endl;
std::cout << "diff CGAL GTE : " << (gte_res.sqrDistance - CGAL::squared_distance(tr1, tr2)) << std::endl;
// don't assert on purpose, GTE has slightly (10^-30 different results, even with an exact NT)
are_equal(CGAL::squared_distance(tr1, tr2), gte_res.sqrDistance);
#endif
}
}
public:
void run()
{
std::cout << "3D Distance tests\n";
std::cout << "Kernel: " << typeid(K).name() << std::endl;
P_P();
P_S();
P_T();
P_Tet();
S_S();
P_R();
R_R();
S_R();
R_L();
P_L();
S_L();
L_L();
P_T();
P_Pl();
P_Tet();
S_S();
S_R();
S_L();
S_Pl();
R_R();
R_L();
R_Pl();
L_L();
L_Pl();
T_T();
Pl_Pl();
}
};
int main()
{
Test< CGAL::Simple_cartesian<double> >().run();
Test< CGAL::Simple_homogeneous<double> >().run();
// TODO : test more kernels.
std::cout.precision(17);
std::cerr.precision(17);
std::cout << "3D Distance tests" << std::endl;
CGAL::Random r;
std::cout << "random seed = " << r.get_seed() << std::endl;
// @todo Some tests are too difficult for these kernels
// Test<CGAL::Simple_cartesian<double> >(r, 1e-5).run();
// Test<CGAL::Simple_homogeneous<double> >(r, 1e-5).run();
// Test<CGAL::Simple_cartesian<CGAL::Interval_nt<true> > >(r, 1e-5).run();
Test<CGAL::Homogeneous<CGAL::Exact_integer> >(r, 0).run();
const double epick_eps = 10 * std::numeric_limits<double>::epsilon();
Test<CGAL::Exact_predicates_inexact_constructions_kernel>(r, epick_eps).run();
Test<CGAL::Exact_predicates_exact_constructions_kernel>(r, 0).run();
std::cout << "Done!" << std::endl;
return EXIT_SUCCESS;
}

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