mirror of https://github.com/CGAL/cgal
Fix predicate/construction inconsistencies in P3T3 canonicalization functions
There are two use cases: - either we care about the shifted position (for example for P3M3 where we will insert the shifted position) - either we don't care about the shifted position, and we are ok with point + shifting offset (for example in P3M3 predicates to determine is_bad) In the first case, we cannot determine the shift using predicates, otherwise we could have an inconsitency in the final result: the predicates say the point is in, but once constructed it is not. So this commit distinguishes between both. When we care about the actual shifted position, we construct the point. There might be numerical errors if we are not using exact constructions, but it does not really matter. What should be done better: - use compare_x/y/z_3 instead of < - handle the case where the numerical errors are such that you get a really silly point far from the truth. Maybe this should all be done in EPECK. There is something like this in the history of canonicalize_helper.h ....
This commit is contained in:
parent
425cfb5f07
commit
be6109dc14
|
|
@ -55,7 +55,7 @@ public:
|
||||||
|
|
||||||
return_type operator()(const Point_3& p) const
|
return_type operator()(const Point_3& p) const
|
||||||
{
|
{
|
||||||
const Point_3 cp = P3T3::internal::robust_canonicalize_point(p, m_gt);
|
const Point_3 cp = P3T3::internal::construct_canonical_point(p, m_gt);
|
||||||
CGAL::Bounded_side res = m_sotm(cp);
|
CGAL::Bounded_side res = m_sotm(cp);
|
||||||
return ((res == ON_BOUNDED_SIDE) ? 1 : 2); // set a region to '0' if it is not to be meshed
|
return ((res == ON_BOUNDED_SIDE) ? 1 : 2); // set a region to '0' if it is not to be meshed
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -41,7 +41,7 @@ public:
|
||||||
|
|
||||||
/// Operator ()
|
/// Operator ()
|
||||||
return_type operator()(const Point_3& p) const {
|
return_type operator()(const Point_3& p) const {
|
||||||
return f_(P3T3::internal::robust_canonicalize_point(p, gt_));
|
return f_(P3T3::internal::construct_canonical_point(p, gt_));
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
|
||||||
|
|
@ -193,14 +193,14 @@ public:
|
||||||
|
|
||||||
Bare_point canonicalize_point(const Bare_point& p) const
|
Bare_point canonicalize_point(const Bare_point& p) const
|
||||||
{
|
{
|
||||||
return P3T3::internal::robust_canonicalize_point(p, geom_traits());
|
return P3T3::internal::construct_canonical_point(p, geom_traits());
|
||||||
}
|
}
|
||||||
|
|
||||||
// @fixme it might be dangerous to call robust_canonicalize() without also changing
|
// @fixme it might be dangerous to call robust_canonicalize() without also changing
|
||||||
// <p, offset> = construct_periodic_point(p) (lack of consistency in the result)
|
// <p, offset> = construct_periodic_point(p) (lack of consistency in the result)
|
||||||
Weighted_point canonicalize_point(const Weighted_point& p) const
|
Weighted_point canonicalize_point(const Weighted_point& p) const
|
||||||
{
|
{
|
||||||
return P3T3::internal::robust_canonicalize_point(p, geom_traits());
|
return P3T3::internal::construct_canonical_point(p, geom_traits());
|
||||||
}
|
}
|
||||||
|
|
||||||
// 1-cover, so we can take a const&
|
// 1-cover, so we can take a const&
|
||||||
|
|
@ -430,9 +430,8 @@ public:
|
||||||
typename Geom_traits::Compute_squared_distance_3 compute_sd =
|
typename Geom_traits::Compute_squared_distance_3 compute_sd =
|
||||||
geom_traits().compute_squared_distance_3_object();
|
geom_traits().compute_squared_distance_3_object();
|
||||||
|
|
||||||
bool used_exact = false;
|
std::pair<Bare_point, Offset> pp_p = P3T3::internal::construct_periodic_point(p, geom_traits());
|
||||||
std::pair<Bare_point, Offset> pp_p = P3T3::internal::construct_periodic_point(p, used_exact, geom_traits());
|
std::pair<Bare_point, Offset> pp_q = P3T3::internal::construct_periodic_point(q, geom_traits());
|
||||||
std::pair<Bare_point, Offset> pp_q = P3T3::internal::construct_periodic_point(q, used_exact, geom_traits());
|
|
||||||
|
|
||||||
Offset min_off;
|
Offset min_off;
|
||||||
|
|
||||||
|
|
@ -474,8 +473,7 @@ public:
|
||||||
typename Geom_traits::Construct_point_3 cp =
|
typename Geom_traits::Construct_point_3 cp =
|
||||||
geom_traits().construct_point_3_object();
|
geom_traits().construct_point_3_object();
|
||||||
|
|
||||||
bool used_exact = false;
|
std::pair<Bare_point, Offset> pp_q = P3T3::internal::construct_periodic_point(q, geom_traits());
|
||||||
std::pair<Bare_point, Offset> pp_q = P3T3::internal::construct_periodic_point(q, used_exact, geom_traits());
|
|
||||||
|
|
||||||
Offset min_off;
|
Offset min_off;
|
||||||
Offset null_offset(0,0,0);
|
Offset null_offset(0,0,0);
|
||||||
|
|
@ -550,10 +548,9 @@ public:
|
||||||
geom_traits().compare_power_distance_3_object();
|
geom_traits().compare_power_distance_3_object();
|
||||||
|
|
||||||
// Compute the offsets that would bring p, q, and r into the canonical domain
|
// Compute the offsets that would bring p, q, and r into the canonical domain
|
||||||
bool used_exact = false;
|
std::pair<Bare_point, Offset> pp_p = P3T3::internal::construct_periodic_point(p, geom_traits());
|
||||||
std::pair<Bare_point, Offset> pp_p = P3T3::internal::construct_periodic_point(p, used_exact, geom_traits());
|
std::pair<Bare_point, Offset> pp_q = P3T3::internal::construct_periodic_point(cp(q), geom_traits());
|
||||||
std::pair<Bare_point, Offset> pp_q = P3T3::internal::construct_periodic_point(cp(q), used_exact, geom_traits());
|
std::pair<Bare_point, Offset> pp_r = P3T3::internal::construct_periodic_point(cp(r), geom_traits());
|
||||||
std::pair<Bare_point, Offset> pp_r = P3T3::internal::construct_periodic_point(cp(r), used_exact, geom_traits());
|
|
||||||
|
|
||||||
// To compare pp(p, q) to pp(p, r), we first need to know the best offsets that minimize these distances
|
// To compare pp(p, q) to pp(p, r), we first need to know the best offsets that minimize these distances
|
||||||
auto get_offset_minimizing_power_product = [&](const Weighted_point& wp,
|
auto get_offset_minimizing_power_product = [&](const Weighted_point& wp,
|
||||||
|
|
|
||||||
|
|
@ -765,22 +765,15 @@ public:
|
||||||
}
|
}
|
||||||
|
|
||||||
// same as the base construct_periodic_point(), but for weighted points
|
// same as the base construct_periodic_point(), but for weighted points
|
||||||
Periodic_weighted_point construct_periodic_weighted_point(const Weighted_point& p,
|
Periodic_weighted_point construct_periodic_weighted_point(const Weighted_point& p) const
|
||||||
bool& had_to_use_exact) const
|
|
||||||
{
|
{
|
||||||
const Bare_point& bp = geom_traits().construct_point_3_object()(p);
|
const Bare_point& bp = geom_traits().construct_point_3_object()(p);
|
||||||
const Periodic_bare_point pbp = Tr_Base::construct_periodic_point(bp, had_to_use_exact);
|
const Periodic_bare_point pbp = Tr_Base::construct_periodic_point(bp);
|
||||||
return std::make_pair(geom_traits().construct_weighted_point_3_object()(
|
return std::make_pair(geom_traits().construct_weighted_point_3_object()(
|
||||||
pbp.first, p.weight()),
|
pbp.first, p.weight()),
|
||||||
pbp.second);
|
pbp.second);
|
||||||
}
|
}
|
||||||
|
|
||||||
Periodic_weighted_point construct_periodic_weighted_point(const Weighted_point& p) const
|
|
||||||
{
|
|
||||||
bool useless = false;
|
|
||||||
return construct_periodic_weighted_point(p, useless);
|
|
||||||
}
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
/** @name Geometric access functions */
|
/** @name Geometric access functions */
|
||||||
// The following functions change the position of a vertex.
|
// The following functions change the position of a vertex.
|
||||||
|
|
|
||||||
|
|
@ -870,18 +870,11 @@ public:
|
||||||
return construct_point(pp.first, pp.second);
|
return construct_point(pp.first, pp.second);
|
||||||
}
|
}
|
||||||
|
|
||||||
Periodic_point_3 construct_periodic_point(const Point_3& p,
|
Periodic_point_3 construct_periodic_point(const Point_3& p) const
|
||||||
bool& had_to_use_exact) const
|
|
||||||
{
|
{
|
||||||
// The function is a different file to be able to be used where there is
|
// The function is a different file to be able to be used where there is
|
||||||
// no triangulation (namely, the domains of Periodic_3_mesh_3).
|
// no triangulation (namely, the domains of Periodic_3_mesh_3).
|
||||||
return ::CGAL::P3T3::internal::construct_periodic_point(p, had_to_use_exact, geom_traits());
|
return ::CGAL::P3T3::internal::construct_periodic_point(p, geom_traits());
|
||||||
}
|
|
||||||
|
|
||||||
Periodic_point_3 construct_periodic_point(const Point_3& p) const
|
|
||||||
{
|
|
||||||
bool useless = false;
|
|
||||||
return construct_periodic_point(p, useless);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// ---------------------------------------------------------------------------
|
// ---------------------------------------------------------------------------
|
||||||
|
|
|
||||||
|
|
@ -18,7 +18,7 @@
|
||||||
// Although 'canoncalize_point()' is used by Periodic_3_mesh_3, this file is here
|
// Although 'canoncalize_point()' is used by Periodic_3_mesh_3, this file is here
|
||||||
// (in Periodic_3_triangulation_3) because of 'construct_periodic_point()',
|
// (in Periodic_3_triangulation_3) because of 'construct_periodic_point()',
|
||||||
// which is a function used in P3T3.h and also needed by 'canonicalize_point()'.
|
// which is a function used in P3T3.h and also needed by 'canonicalize_point()'.
|
||||||
// However, P3M3 needs 'canoncalize_point()' without having access to a triangulation
|
// However, P3M3 needs 'canonicalize_point()' without having access to a triangulation
|
||||||
// and to avoid duplicating it, the function is here.
|
// and to avoid duplicating it, the function is here.
|
||||||
|
|
||||||
// Geom_traits must be a model of the concept 'P3T3Traits' for 'construct_periodic_point()'.
|
// Geom_traits must be a model of the concept 'P3T3Traits' for 'construct_periodic_point()'.
|
||||||
|
|
@ -44,7 +44,6 @@ namespace internal {
|
||||||
template <typename Gt_>
|
template <typename Gt_>
|
||||||
std::pair<typename Gt_::Point_3, typename Gt_::Periodic_3_offset_3>
|
std::pair<typename Gt_::Point_3, typename Gt_::Periodic_3_offset_3>
|
||||||
construct_periodic_point(const typename Gt_::Point_3& p,
|
construct_periodic_point(const typename Gt_::Point_3& p,
|
||||||
bool& encountered_issue,
|
|
||||||
const Gt_& gt)
|
const Gt_& gt)
|
||||||
{
|
{
|
||||||
typedef Gt_ Geom_traits;
|
typedef Gt_ Geom_traits;
|
||||||
|
|
@ -52,13 +51,13 @@ construct_periodic_point(const typename Gt_::Point_3& p,
|
||||||
typedef typename Geom_traits::Periodic_3_offset_3 Offset;
|
typedef typename Geom_traits::Periodic_3_offset_3 Offset;
|
||||||
typedef typename Geom_traits::Iso_cuboid_3 Iso_cuboid;
|
typedef typename Geom_traits::Iso_cuboid_3 Iso_cuboid;
|
||||||
|
|
||||||
const Iso_cuboid& domain = gt.get_domain();
|
// this assumes exact predicates, otherwise we could be looping
|
||||||
|
|
||||||
// Use these rather than Construct_point_3 to avoid construction inaccuracies
|
|
||||||
typename Geom_traits::Compare_x_3 cmp_x3 = gt.compare_x_3_object();
|
typename Geom_traits::Compare_x_3 cmp_x3 = gt.compare_x_3_object();
|
||||||
typename Geom_traits::Compare_y_3 cmp_y3 = gt.compare_y_3_object();
|
typename Geom_traits::Compare_y_3 cmp_y3 = gt.compare_y_3_object();
|
||||||
typename Geom_traits::Compare_z_3 cmp_z3 = gt.compare_z_3_object();
|
typename Geom_traits::Compare_z_3 cmp_z3 = gt.compare_z_3_object();
|
||||||
|
|
||||||
|
const Iso_cuboid& domain = gt.get_domain();
|
||||||
|
|
||||||
// Check if p lies within the domain. If not, translate.
|
// Check if p lies within the domain. If not, translate.
|
||||||
if(!(p.x() < domain.xmin()) && p.x() < domain.xmax() &&
|
if(!(p.x() < domain.xmin()) && p.x() < domain.xmax() &&
|
||||||
!(p.y() < domain.ymin()) && p.y() < domain.ymax() &&
|
!(p.y() < domain.ymin()) && p.y() < domain.ymax() &&
|
||||||
|
|
@ -67,109 +66,46 @@ construct_periodic_point(const typename Gt_::Point_3& p,
|
||||||
return std::make_pair(p, Offset());
|
return std::make_pair(p, Offset());
|
||||||
}
|
}
|
||||||
|
|
||||||
// Numerical approximations might create inconsistencies between the constructions
|
Point domain_m(domain.xmin(), domain.ymin(), domain.zmin());
|
||||||
// and the comparisons. For example in a cubic domain of size 2:
|
Point domain_M(domain.xmax(), domain.ymax(), domain.zmax());
|
||||||
// 1. initial point: P(2+1e-17, 0, 0)
|
|
||||||
// 2. the function computes an offset(1, 0, 0),
|
|
||||||
// 3. P + (-1, 0, 0) * domain_size constructs Q(-1e-17, 0, 0) // numerical approximation
|
|
||||||
// 4. the function computes an offset of (-1, 0, 0)
|
|
||||||
// 5. Q + (1, 0, 0) * domain_size constructs (2+1e-17, 0, 0) (that is P)
|
|
||||||
// And the function is looping...
|
|
||||||
//
|
|
||||||
// If this is happening the 'Last_change' enum will break this infinite
|
|
||||||
// loop and return the wrong point and the 'encountered_issue' bool will be
|
|
||||||
// set to 'true'. An exact version of this function is then be called.
|
|
||||||
|
|
||||||
enum Last_change
|
|
||||||
{
|
|
||||||
NO_LAST_CHANGE,
|
|
||||||
INCREASED_X, DECREASED_X, INCREASED_Y, DECREASED_Y, INCREASED_Z, DECREASED_Z
|
|
||||||
};
|
|
||||||
|
|
||||||
Last_change lc = NO_LAST_CHANGE;
|
|
||||||
bool in = false;
|
|
||||||
|
|
||||||
Offset transl(0, 0, 0);
|
Offset transl(0, 0, 0);
|
||||||
const Offset null_off(0, 0, 0);
|
const Offset null_off(0, 0, 0);
|
||||||
|
|
||||||
Point domain_m(domain.xmin(), domain.ymin(), domain.zmin());
|
for(;;)
|
||||||
Point domain_M(domain.xmax(), domain.ymax(), domain.zmax());
|
|
||||||
|
|
||||||
while(!in)
|
|
||||||
{
|
{
|
||||||
if(cmp_x3(p, domain_m, transl, null_off) == SMALLER)
|
if(cmp_x3(p, domain_m, transl, null_off) == SMALLER)
|
||||||
{
|
|
||||||
if(lc == DECREASED_X) // stuck in a loop
|
|
||||||
break;
|
|
||||||
|
|
||||||
lc = INCREASED_X;
|
|
||||||
transl.x() += 1;
|
transl.x() += 1;
|
||||||
}
|
|
||||||
else if(cmp_y3(p, domain_m, transl, null_off) == SMALLER)
|
else if(cmp_y3(p, domain_m, transl, null_off) == SMALLER)
|
||||||
{
|
|
||||||
if(lc == DECREASED_Y) // stuck in a loop
|
|
||||||
break;
|
|
||||||
|
|
||||||
lc = INCREASED_Y;
|
|
||||||
transl.y() += 1;
|
transl.y() += 1;
|
||||||
}
|
|
||||||
else if(cmp_z3(p, domain_m, transl, null_off) == SMALLER)
|
else if(cmp_z3(p, domain_m, transl, null_off) == SMALLER)
|
||||||
{
|
|
||||||
if(lc == DECREASED_Z) // stuck in a loop
|
|
||||||
break;
|
|
||||||
|
|
||||||
lc = INCREASED_Z;
|
|
||||||
transl.z() += 1;
|
transl.z() += 1;
|
||||||
}
|
|
||||||
else if(!(cmp_x3(p, domain_M, transl, null_off) == SMALLER))
|
else if(!(cmp_x3(p, domain_M, transl, null_off) == SMALLER))
|
||||||
{
|
|
||||||
if(lc == INCREASED_X) // stuck in a loop
|
|
||||||
break;
|
|
||||||
|
|
||||||
lc = DECREASED_X;
|
|
||||||
transl.x() -= 1;
|
transl.x() -= 1;
|
||||||
}
|
|
||||||
else if(!(cmp_y3(p, domain_M, transl, null_off) == SMALLER))
|
else if(!(cmp_y3(p, domain_M, transl, null_off) == SMALLER))
|
||||||
{
|
|
||||||
if(lc == INCREASED_Y) // stuck in a loop
|
|
||||||
break;
|
|
||||||
|
|
||||||
lc = DECREASED_Y;
|
|
||||||
transl.y() -= 1;
|
transl.y() -= 1;
|
||||||
}
|
|
||||||
else if(!(cmp_z3(p, domain_M, transl, null_off) == SMALLER))
|
else if(!(cmp_z3(p, domain_M, transl, null_off) == SMALLER))
|
||||||
{
|
|
||||||
if(lc == INCREASED_Z) // stuck in a loop
|
|
||||||
break;
|
|
||||||
|
|
||||||
lc = DECREASED_Z;
|
|
||||||
transl.z() -= 1;
|
transl.z() -= 1;
|
||||||
}
|
|
||||||
else
|
else
|
||||||
{
|
break;
|
||||||
in = true;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
std::pair<Point, Offset> pp(p, transl);
|
std::pair<Point, Offset> pp(p, transl);
|
||||||
|
|
||||||
if(cmp_x3(p, domain_m, transl, null_off) == SMALLER || // < min
|
CGAL_postcondition(!(cmp_x3(p, domain_m, transl, null_off) == SMALLER) &&
|
||||||
cmp_y3(p, domain_m, transl, null_off) == SMALLER ||
|
!(cmp_y3(p, domain_m, transl, null_off) == SMALLER) &&
|
||||||
cmp_z3(p, domain_m, transl, null_off) == SMALLER ||
|
!(cmp_z3(p, domain_m, transl, null_off) == SMALLER) &&
|
||||||
!(cmp_x3(p, domain_M, transl, null_off) == SMALLER) || // >= max
|
cmp_x3(p, domain_M, transl, null_off) == SMALLER &&
|
||||||
!(cmp_y3(p, domain_M, transl, null_off) == SMALLER) ||
|
cmp_y3(p, domain_M, transl, null_off) == SMALLER &&
|
||||||
!(cmp_z3(p, domain_M, transl, null_off) == SMALLER))
|
cmp_z3(p, domain_M, transl, null_off) == SMALLER);
|
||||||
{
|
|
||||||
encountered_issue = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
return pp;
|
return pp;
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename Gt_>
|
template <typename Gt_>
|
||||||
typename Gt_::Point_3
|
typename Gt_::Point_3
|
||||||
constrain_to_canonical_domain(const typename Gt_::Point_3& p,
|
clamp_to_canonical_domain(const typename Gt_::Point_3& p,
|
||||||
const Gt_& gt)
|
const Gt_& gt)
|
||||||
{
|
{
|
||||||
typedef Gt_ Geom_traits;
|
typedef Gt_ Geom_traits;
|
||||||
typedef typename Geom_traits::FT FT;
|
typedef typename Geom_traits::FT FT;
|
||||||
|
|
@ -196,31 +132,114 @@ constrain_to_canonical_domain(const typename Gt_::Point_3& p,
|
||||||
/// instance of the same bare point that lives inside the base domain
|
/// instance of the same bare point that lives inside the base domain
|
||||||
template <typename Gt_>
|
template <typename Gt_>
|
||||||
typename Gt_::Point_3
|
typename Gt_::Point_3
|
||||||
robust_canonicalize_point(const typename Gt_::Point_3& p,
|
construct_canonical_point(const typename Gt_::Point_3& p,
|
||||||
const Gt_& gt)
|
const Gt_& gt)
|
||||||
{
|
{
|
||||||
typedef Gt_ Geom_traits;
|
typedef Gt_ Geom_traits;
|
||||||
typedef typename Geom_traits::Point_3 Bare_point;
|
typedef typename Geom_traits::Periodic_3_offset_3 Offset;
|
||||||
typedef typename Geom_traits::Periodic_3_offset_3 Offset;
|
typedef typename Geom_traits::Iso_cuboid_3 Iso_cuboid;
|
||||||
typedef typename Geom_traits::Iso_cuboid_3 Iso_cuboid;
|
|
||||||
|
const Iso_cuboid& domain = gt.get_domain();
|
||||||
|
|
||||||
|
// Check if p lies within the domain. If not, translate.
|
||||||
|
if(!(p.x() < domain.xmin()) && p.x() < domain.xmax() &&
|
||||||
|
!(p.y() < domain.ymin()) && p.y() < domain.ymax() &&
|
||||||
|
!(p.z() < domain.zmin()) && p.z() < domain.zmax())
|
||||||
|
{
|
||||||
|
return p;
|
||||||
|
}
|
||||||
|
|
||||||
typename Geom_traits::Construct_point_3 cp = gt.construct_point_3_object();
|
typename Geom_traits::Construct_point_3 cp = gt.construct_point_3_object();
|
||||||
|
|
||||||
const Iso_cuboid& domain = gt.get_domain();
|
// Numerical approximations might create inconsistencies between the constructions
|
||||||
if(p.x() >= domain.xmin() && p.x() < domain.xmax() &&
|
// and the comparisons. For example in a cubic domain of size 2:
|
||||||
p.y() >= domain.ymin() && p.y() < domain.ymax() &&
|
// 1. initial point: P(2+1e-17, 0, 0)
|
||||||
p.z() >= domain.zmin() && p.z() < domain.zmax())
|
// 2. the function computes an offset(1, 0, 0),
|
||||||
return p;
|
// 3. P + (-1, 0, 0) * domain_size constructs Q(-1e-17, 0, 0) // numerical approximation
|
||||||
|
// 4. the function computes an offset of (-1, 0, 0)
|
||||||
|
// 5. Q + (1, 0, 0) * domain_size constructs (2+1e-17, 0, 0) (that is P)
|
||||||
|
// And the function is looping...
|
||||||
|
//
|
||||||
|
// If this is happening the 'Last_change' enum will break this infinite loop,
|
||||||
|
// and the function will snap the point to the domain.
|
||||||
|
|
||||||
bool encountered_issue = false;
|
enum Last_change
|
||||||
std::pair<Bare_point, Offset> pbp = construct_periodic_point(p, encountered_issue, gt);
|
|
||||||
Bare_point canonical_p = cp(pbp.first /*point*/, pbp.second /*offset*/);
|
|
||||||
|
|
||||||
if(encountered_issue)
|
|
||||||
{
|
{
|
||||||
// If we encountered an issue, there's no guarantee that the double construction gives a point
|
NO_LAST_CHANGE,
|
||||||
// in the domain (even if we computed it exactly beforehand). So, forcefully put it into the domain.
|
INCREASED_X, DECREASED_X, INCREASED_Y, DECREASED_Y, INCREASED_Z, DECREASED_Z
|
||||||
canonical_p = constrain_to_canonical_domain(canonical_p, gt);
|
};
|
||||||
|
|
||||||
|
Last_change lc = NO_LAST_CHANGE;
|
||||||
|
|
||||||
|
Offset transl(0, 0, 0);
|
||||||
|
Point_3 canonical_p = p;
|
||||||
|
|
||||||
|
for(;;)
|
||||||
|
{
|
||||||
|
// Here we actually construct because we are using a kernel with exact constructions
|
||||||
|
// so it is faster than using <Object, Offset> APIs which have to perform constructions
|
||||||
|
// within the predicates every single time
|
||||||
|
canonical_p = cp(p, transl);
|
||||||
|
|
||||||
|
if(canonical_p.x() < domain.xmin())
|
||||||
|
{
|
||||||
|
if(lc == DECREASED_X) // stuck in a loop
|
||||||
|
break;
|
||||||
|
|
||||||
|
lc = INCREASED_X;
|
||||||
|
transl.x() += 1;
|
||||||
|
}
|
||||||
|
else if(canonical_p.y() < domain.xmin())
|
||||||
|
{
|
||||||
|
if(lc == DECREASED_Y) // stuck in a loop
|
||||||
|
break;
|
||||||
|
|
||||||
|
lc = INCREASED_Y;
|
||||||
|
transl.y() += 1;
|
||||||
|
}
|
||||||
|
else if(canonical_p.z() < domain.xmin())
|
||||||
|
{
|
||||||
|
if(lc == DECREASED_Z) // stuck in a loop
|
||||||
|
break;
|
||||||
|
|
||||||
|
lc = INCREASED_Z;
|
||||||
|
transl.z() += 1;
|
||||||
|
}
|
||||||
|
else if(canonical_p.x() >= domain.xmax())
|
||||||
|
{
|
||||||
|
if(lc == INCREASED_X) // stuck in a loop
|
||||||
|
break;
|
||||||
|
|
||||||
|
lc = DECREASED_X;
|
||||||
|
transl.x() -= 1;
|
||||||
|
}
|
||||||
|
else if(canonical_p.y() >= domain.ymax())
|
||||||
|
{
|
||||||
|
if(lc == INCREASED_Y) // stuck in a loop
|
||||||
|
break;
|
||||||
|
|
||||||
|
lc = DECREASED_Y;
|
||||||
|
transl.y() -= 1;
|
||||||
|
}
|
||||||
|
else if(canonical_p.z() >= domain.zmax())
|
||||||
|
{
|
||||||
|
if(lc == INCREASED_Z) // stuck in a loop
|
||||||
|
break;
|
||||||
|
|
||||||
|
lc = DECREASED_Z;
|
||||||
|
transl.z() -= 1;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if(canonical_p.x() < domain.xmin() || canonical_p.x() >= domain.xmax() ||
|
||||||
|
canonical_p.y() < domain.ymin() || canonical_p.y() >= domain.ymax() ||
|
||||||
|
canonical_p.z() < domain.zmin() || canonical_p.z() >= domain.zmax())
|
||||||
|
{
|
||||||
|
canonical_p = clamp_to_canonical_domain(canonical_p, gt);
|
||||||
}
|
}
|
||||||
|
|
||||||
CGAL_postcondition( !(canonical_p.x() < domain.xmin()) && (canonical_p.x() < domain.xmax()));
|
CGAL_postcondition( !(canonical_p.x() < domain.xmin()) && (canonical_p.x() < domain.xmax()));
|
||||||
|
|
@ -234,7 +253,7 @@ robust_canonicalize_point(const typename Gt_::Point_3& p,
|
||||||
/// instance of the same weighted point that lives inside the base domain
|
/// instance of the same weighted point that lives inside the base domain
|
||||||
template <typename Gt_>
|
template <typename Gt_>
|
||||||
typename Gt_::Weighted_point_3
|
typename Gt_::Weighted_point_3
|
||||||
robust_canonicalize_point(const typename Gt_::Weighted_point_3& wp,
|
construct_canonical_point(const typename Gt_::Weighted_point_3& wp,
|
||||||
const Gt_& gt)
|
const Gt_& gt)
|
||||||
{
|
{
|
||||||
typedef Gt_ Geom_traits;
|
typedef Gt_ Geom_traits;
|
||||||
|
|
@ -252,7 +271,7 @@ robust_canonicalize_point(const typename Gt_::Weighted_point_3& wp,
|
||||||
typename Geom_traits::Construct_weighted_point_3 cwp = gt.construct_weighted_point_3_object();
|
typename Geom_traits::Construct_weighted_point_3 cwp = gt.construct_weighted_point_3_object();
|
||||||
|
|
||||||
const Bare_point& bp = cp(wp);
|
const Bare_point& bp = cp(wp);
|
||||||
Bare_point canonical_point = robust_canonicalize_point(bp, gt);
|
Bare_point canonical_point = construct_canonical_point(bp, gt);
|
||||||
|
|
||||||
return cwp(canonical_point, cw(wp));
|
return cwp(canonical_point, cw(wp));
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue