This commit is contained in:
Efi Fogel 2007-10-06 15:18:42 +00:00
parent 4b55955472
commit 91c5cb92c2
1 changed files with 236 additions and 178 deletions

View File

@ -23,8 +23,8 @@
// #define CGAL_ARR_PLANE
/*! \file
* The great circular arc on a sphere traits-class for the arrangement on
* sphere package.
* The traits-class that handles great circular arc on a spheres for the
* arrangement on surface package.
*/
#include <CGAL/tags.h>
@ -173,6 +173,12 @@ protected:
inline static bool is_x_negative(Direction_2 d)
{ return (CGAL::sign(d.dx()) == NEGATIVE); }
inline static Sign x_sign(Direction_3 d) { return CGAL::sign(d.dx()); }
inline static Sign y_sign(Direction_3 d) { return CGAL::sign(d.dy()); }
inline static Sign z_sign(Direction_3 d) { return CGAL::sign(d.dz()); }
typedef Direction_2 (*Project)(const Direction_3 & d) ;
@ -281,7 +287,7 @@ protected:
#if defined(CGAL_ARR_PLANE)
Plane_3 plane(p1, p2);
#else
Plane_3 plane = kernel.construct_plane_3_object()(p1, ORIGIN, p2);
Plane_3 plane = kernel.construct_plane_3_object()(ORIGIN, p1, p2);
#endif
return plane;
}
@ -370,8 +376,7 @@ protected:
Direction_2 d1_2 = project_xy(d1);
Direction_2 d2_2 = project_xy(d2);
if (kernel.equal_2_object() (d1_2, d2_2))
return EQUAL;
if (kernel.equal_2_object()(d1_2, d2_2)) return EQUAL;
const Direction_2 & nx = neg_x_2();
return (kernel.counterclockwise_in_between_2_object()(nx, d1_2, d2_2)) ?
@ -404,8 +409,9 @@ protected:
* \return true iff dir pierces arc.
* \pre dir lies in the plane defined by arc.
*/
static bool is_in_between(const Arr_extended_direction_3<Kernel> & dir,
const Arr_x_monotone_great_circular_arc_on_sphere_3<Kernel> & arc)
static bool is_in_between
(const Arr_extended_direction_3<Kernel> & dir,
const Arr_x_monotone_great_circular_arc_on_sphere_3<Kernel> & arc)
{
const Point_2 & l = arc.left();
const Point_2 & r = arc.right();
@ -458,23 +464,14 @@ public:
* \return SMALLER - x(p1) < x(p2);
* EQUAL - x(p1) = x(p2);
* LARGER - x(p1) > x(p2).
* \pre p1 is not a singularity point.
* \pre p2 is not a singularity point.
* \pre p1 does not lie on the closed discontinuity arc.
* \pre p2 does not lie on the closed discontinuity arc.
*/
Comparison_result operator()(const Point_2 & p1, const Point_2 & p2) const
{
typedef Arr_great_circular_arc_on_sphere_traits_2<Kernel> Traits;
CGAL_precondition(!p1.is_min_boundary() && !p1.is_max_boundary());
CGAL_precondition(!p2.is_min_boundary() && !p2.is_max_boundary());
Kernel kernel;
Direction_2 d1 = Traits::project_xy(p1);
Direction_2 d2 = Traits::project_xy(p2);
if (kernel.equal_2_object()(d1, d2)) return EQUAL;
const Direction_2 & nx = Traits::neg_x_2();
return (kernel.counterclockwise_in_between_2_object()(nx, d1, d2)) ?
LARGER : SMALLER;
CGAL_precondition(p1.is_no_boundary() && p2.is_no_boundary());
return Traits::compare_x(p1, p2);
}
/*! Compare the x-coordinates of a point direction and an endpoint
@ -490,7 +487,7 @@ public:
* \return SMALLER - x(p) < x(xc, ind);
* EQUAL - x(p) = x(xc, ind);
* LARGER - x(p) > x(xc, ind).
* \pre p is not on the discontinuity arc.
* \pre p is not on the closed discontinuity arc.
* \pre the endpoint indicated by xv and ind is on the discontinuity arc.
*/
Comparison_result operator()(const Point_2 & p,
@ -584,7 +581,7 @@ public:
}
};
/*! Get a Compare_x_2 function object */
/*! Obtain a Compare_x_2 function object */
Compare_x_2 compare_x_2_object() const { return Compare_x_2(); }
class Compare_xy_2 {
@ -611,7 +608,7 @@ public:
}
};
/*! Get a Compare_xy_2 function object */
/*! Obtain a Compare_xy_2 function object */
Compare_xy_2 compare_xy_2_object() const { return Compare_xy_2(); }
class Boundary_in_x_2 {
@ -650,7 +647,7 @@ public:
}
};
/*! Get an Boundary_in_x_2 functor object. */
/*! Obtain an Boundary_in_x_2 functor object. */
Boundary_in_x_2 boundary_in_x_2_object() const { return Boundary_in_x_2(); }
class Boundary_in_y_2 {
@ -677,7 +674,7 @@ public:
}
};
/*! Get an Boundary_in_x_2 functor object. */
/*! Obtain an Boundary_in_x_2 functor object. */
Boundary_in_y_2 boundary_in_y_2_object() const { return Boundary_in_y_2(); }
class Construct_min_vertex_2 {
@ -690,7 +687,7 @@ public:
{ return xc.left(); }
};
/*! Get a Construct_min_vertex_2 function object */
/*! Obtain a Construct_min_vertex_2 function object */
Construct_min_vertex_2 construct_min_vertex_2_object() const
{ return Construct_min_vertex_2(); }
@ -704,7 +701,7 @@ public:
{ return xc.right(); }
};
/*! Get a Construct_max_vertex_2 function object */
/*! Obtain a Construct_max_vertex_2 function object */
Construct_max_vertex_2 construct_max_vertex_2_object() const
{ return Construct_max_vertex_2(); }
@ -722,7 +719,7 @@ public:
}
};
/*! Get an Is_vertical_2 function object */
/*! Obtain an Is_vertical_2 function object */
Is_vertical_2 is_vertical_2_object() const { return Is_vertical_2(); }
class Compare_y_at_x_2 {
@ -764,8 +761,8 @@ public:
Oriented_side os = oriented_side(xc.plane(), p);
return (os == ON_ORIENTED_BOUNDARY) ? EQUAL :
(xc.is_directed_right()) ?
((os == ON_NEGATIVE_SIDE) ? LARGER : SMALLER) :
((os == ON_NEGATIVE_SIDE) ? SMALLER : LARGER);
((os == ON_NEGATIVE_SIDE) ? SMALLER : LARGER) :
((os == ON_NEGATIVE_SIDE) ? LARGER : SMALLER);
}
/*! Compare the relative y-positions of two curves at an x-boundary.
@ -869,15 +866,15 @@ public:
Oriented_side os = oriented_side(xc1.plane(), r2);
return (os == ON_ORIENTED_BOUNDARY) ? EQUAL :
(xc1.is_directed_right()) ?
((os == ON_NEGATIVE_SIDE) ? SMALLER : LARGER) :
((os == ON_NEGATIVE_SIDE) ? LARGER : SMALLER);
((os == ON_NEGATIVE_SIDE) ? LARGER : SMALLER) :
((os == ON_NEGATIVE_SIDE) ? SMALLER : LARGER);
}
// use r1 and xc2:
Oriented_side os = oriented_side(xc2.plane(), r1);
return (os == ON_ORIENTED_BOUNDARY) ? EQUAL :
(xc2.is_directed_right()) ?
((os == ON_NEGATIVE_SIDE) ? LARGER: SMALLER) :
((os == ON_NEGATIVE_SIDE) ? SMALLER : LARGER);
((os == ON_NEGATIVE_SIDE) ? SMALLER : LARGER) :
((os == ON_NEGATIVE_SIDE) ? LARGER : SMALLER);
}
// ind == MAX_END
@ -913,19 +910,19 @@ public:
Oriented_side os = oriented_side(xc1.plane(), l2);
return (os == ON_ORIENTED_BOUNDARY) ? EQUAL :
(xc1.is_directed_right()) ?
((os == ON_NEGATIVE_SIDE) ? SMALLER : LARGER) :
((os == ON_NEGATIVE_SIDE) ? LARGER : SMALLER);
((os == ON_NEGATIVE_SIDE) ? LARGER : SMALLER) :
((os == ON_NEGATIVE_SIDE) ? SMALLER : LARGER);
}
// use l1 and xc2:
Oriented_side os = oriented_side(xc2.plane(), l1);
return (os == ON_ORIENTED_BOUNDARY) ? EQUAL :
(xc2.is_directed_right()) ?
((os == ON_NEGATIVE_SIDE) ? LARGER : SMALLER) :
((os == ON_NEGATIVE_SIDE) ? SMALLER : LARGER);
((os == ON_NEGATIVE_SIDE) ? SMALLER : LARGER) :
((os == ON_NEGATIVE_SIDE) ? LARGER : SMALLER);
}
};
/*! Get a Compare_y_at_x_2 function object */
/*! Obtain a Compare_y_at_x_2 function object */
Compare_y_at_x_2 compare_y_at_x_2_object() const
{ return Compare_y_at_x_2(); }
@ -965,16 +962,16 @@ public:
Oriented_side os = oriented_side(xc1.plane(), l2);
return (os == ON_ORIENTED_BOUNDARY) ? EQUAL :
(xc1.is_directed_right()) ?
((os == ON_NEGATIVE_SIDE) ? SMALLER: LARGER) :
((os == ON_NEGATIVE_SIDE) ? LARGER : SMALLER);
((os == ON_NEGATIVE_SIDE) ? LARGER : SMALLER) :
((os == ON_NEGATIVE_SIDE) ? SMALLER : LARGER);
}
if (!l2.is_no_boundary()) {
// use l1 and xc2:
Oriented_side os = oriented_side(xc2.plane(), l1);
return (os == ON_ORIENTED_BOUNDARY) ? EQUAL :
(xc2.is_directed_right()) ?
((os == ON_NEGATIVE_SIDE) ? LARGER : SMALLER) :
((os == ON_NEGATIVE_SIDE) ? SMALLER : LARGER);
((os == ON_NEGATIVE_SIDE) ? SMALLER : LARGER) :
((os == ON_NEGATIVE_SIDE) ? LARGER : SMALLER);
}
if (compare_xy(l1, l2) == SMALLER) {
@ -982,19 +979,19 @@ public:
Oriented_side os = oriented_side(xc1.plane(), l2);
return (os == ON_ORIENTED_BOUNDARY) ? EQUAL :
(xc1.is_directed_right()) ?
((os == ON_NEGATIVE_SIDE) ? SMALLER : LARGER) :
((os == ON_NEGATIVE_SIDE) ? LARGER : SMALLER);
((os == ON_NEGATIVE_SIDE) ? LARGER : SMALLER) :
((os == ON_NEGATIVE_SIDE) ? SMALLER : LARGER);
}
// use l1 and xc2:
Oriented_side os = oriented_side(xc2.plane(), l1);
return (os == ON_ORIENTED_BOUNDARY) ? EQUAL :
(xc2.is_directed_right()) ?
((os == ON_NEGATIVE_SIDE) ? LARGER : SMALLER) :
((os == ON_NEGATIVE_SIDE) ? SMALLER : LARGER);
((os == ON_NEGATIVE_SIDE) ? SMALLER : LARGER) :
((os == ON_NEGATIVE_SIDE) ? LARGER : SMALLER);
}
};
/*! Get a Compare_y_at_x_left_2 function object */
/*! Obtain a Compare_y_at_x_left_2 function object */
Compare_y_at_x_left_2 compare_y_at_x_left_2_object() const
{ return Compare_y_at_x_left_2(); }
@ -1035,35 +1032,35 @@ public:
Oriented_side os = oriented_side(xc1.plane(), r2);
return (os == ON_ORIENTED_BOUNDARY) ? EQUAL :
(xc1.is_directed_right()) ?
((os == ON_NEGATIVE_SIDE) ? SMALLER : LARGER) :
((os == ON_NEGATIVE_SIDE) ? LARGER : SMALLER);
((os == ON_NEGATIVE_SIDE) ? LARGER : SMALLER) :
((os == ON_NEGATIVE_SIDE) ? SMALLER : LARGER);
}
if (!r2.is_no_boundary()) {
// use r1 and xc2:
Oriented_side os = oriented_side(xc2.plane(), r1);
return (os == ON_ORIENTED_BOUNDARY) ? EQUAL :
(xc2.is_directed_right()) ?
((os == ON_NEGATIVE_SIDE) ? LARGER : SMALLER) :
((os == ON_NEGATIVE_SIDE) ? SMALLER : LARGER);
((os == ON_NEGATIVE_SIDE) ? SMALLER : LARGER) :
((os == ON_NEGATIVE_SIDE) ? LARGER : SMALLER);
}
if (compare_xy(r1, r2) == LARGER) {
// use r2 and xc1:
Oriented_side os = oriented_side(xc1.plane(), r2);
return (os == ON_ORIENTED_BOUNDARY) ? EQUAL :
(xc1.is_directed_right()) ?
((os == ON_NEGATIVE_SIDE) ? SMALLER : LARGER) :
((os == ON_NEGATIVE_SIDE) ? LARGER : SMALLER);
((os == ON_NEGATIVE_SIDE) ? LARGER : SMALLER) :
((os == ON_NEGATIVE_SIDE) ? SMALLER : LARGER);
}
// use r1 and xc2:
Oriented_side os = oriented_side(xc2.plane(), r1);
return (os == ON_ORIENTED_BOUNDARY) ? EQUAL :
(xc2.is_directed_right()) ?
((os == ON_NEGATIVE_SIDE) ? LARGER: SMALLER) :
((os == ON_NEGATIVE_SIDE) ? SMALLER : LARGER);
((os == ON_NEGATIVE_SIDE) ? SMALLER : LARGER) :
((os == ON_NEGATIVE_SIDE) ? LARGER : SMALLER);
}
};
/*! Get a Compare_y_at_x_right_2 function object */
/*! Obtain a Compare_y_at_x_right_2 function object */
Compare_y_at_x_right_2 compare_y_at_x_right_2_object() const
{ return Compare_y_at_x_right_2(); }
@ -1099,7 +1096,7 @@ public:
}
};
/*! Get an Equal_2 function object */
/*! Obtain an Equal_2 function object */
Equal_2 equal_2_object() const { return Equal_2(); }
//@}
@ -1142,8 +1139,8 @@ public:
// The arc is vertical => divide it into 2 half arcs;
const Direction_3 & np = Traits::neg_pole();
const Direction_3 & pp = Traits::pos_pole();
X_monotone_curve_2 xc1(np, pp, c.plane(), true, true, true);
X_monotone_curve_2 xc2(pp, np, c.plane(), true, true, false);
X_monotone_curve_2 xc1(np, pp, c.plane(), true, true);
X_monotone_curve_2 xc2(pp, np, c.plane(), true, false);
*oi++ = make_object(xc1);
*oi++ = make_object(xc2);
return oi;
@ -1157,109 +1154,78 @@ public:
const Point_2 & source = c.source();
const Point_2 & target = c.target();
const Plane_3 & plane = c.plane();
X_monotone_curve_2 xc1, xc2;
xc1.set_source(source);
xc1.set_plane(plane);
xc1.set_is_degenerate(false);
xc1.set_is_x_monotone(false);
xc2.set_target(target);
xc2.set_plane(plane);
xc2.set_is_degenerate(false);
xc2.set_is_x_monotone(false);
Kernel kernel;
// None of the enpoints coincide with a pole:
typename Kernel::Equal_2 equal_2 = kernel.equal_2_object();
Direction_2 s_2 = Traits::project_xy(source);
Direction_2 t_2 = Traits::project_xy(target);
Orientation orient = Traits::orientation(s_2, t_2);
if (orient == COLLINEAR) {
CGAL_assertion(!equal_2(s_2, t_2));
// The spherical_arc contains a pole. This implies that both new
// arcs are vertical.Find out which pole lies on c:
xc1.set_is_vertical(true);
xc2.set_is_vertical(true);
const Direction_2 & nx = Traits::neg_x_2();
if (Traits::orientation(nx, s_2) == COLLINEAR) {
// Project onto xz plane:
s_2 = Traits::project_xz(source);
t_2 = Traits::project_xz(target);
const Direction_2 & ny = Traits::neg_y_2();
Orientation orient1 = Traits::orientation(ny, s_2);
CGAL_assertion_code
(Orientation orient2 = Traits::orientation(ny, t_2););
CGAL_assertion((orient1 == LEFT_TURN && orient2 == RIGHT_TURN) ||
(orient1 == RIGHT_TURN && orient2 == LEFT_TURN));
orient = Traits::orientation(s_2, t_2);
if (orient1 == orient) {
// Positive pole:
const Direction_3 & pp = Traits::pos_pole();
xc1.set_target(pp);
xc2.set_source(pp);
xc1.set_is_directed_right(true);
xc2.set_is_directed_right(false);
} else {
// Negative pole:
const Direction_3 & np = Traits::neg_pole();
xc1.set_target(np);
xc2.set_source(np);
xc1.set_is_directed_right(false);
xc2.set_is_directed_right(true);
}
if (c.is_vertical()) {
/* If one of the endpoints coincide with a pole, divide the arc at
* the opposite pole:
*/
const Direction_3 & np = Traits::neg_pole();
const Direction_3 & pp = Traits::pos_pole();
if (source.is_min_boundary() || target.is_min_boundary()) {
X_monotone_curve_2 xc1(source, pp, plane, true, true);
X_monotone_curve_2 xc2(pp, target, plane, true, false);
*oi++ = make_object(xc1);
*oi++ = make_object(xc2);
return oi;
}
// Project onto yz plane:
s_2 = Traits::project_yz(source);
t_2 = Traits::project_yz(target);
const Direction_2 & ny = Traits::neg_y_2();
Orientation orient1 = Traits::orientation(ny, s_2);
CGAL_assertion_code
(Orientation orient2 = Traits::orientation(ny, t_2););
CGAL_assertion((orient1 == LEFT_TURN && orient2 == RIGHT_TURN) ||
(orient1 == RIGHT_TURN && orient2 == LEFT_TURN));
orient = Traits::orientation(s_2, t_2);
if (orient1 == orient) {
// positive pole:
const Direction_3 & pp = Traits::pos_pole();
xc1.set_target(pp);
xc2.set_source(pp);
xc1.set_is_directed_right(true);
xc2.set_is_directed_right(false);
} else {
// negative pole:
const Direction_3 & np = Traits::neg_pole();
xc1.set_target(np);
xc2.set_source(np);
xc1.set_is_directed_right(false);
xc2.set_is_directed_right(true);
if (source.is_max_boundary() || target.is_max_boundary()) {
X_monotone_curve_2 xc1(source, np, plane, true, false);
X_monotone_curve_2 xc2(np, target, plane, true, true);
*oi++ = make_object(xc1);
*oi++ = make_object(xc2);
return oi;
}
// None of the enpoints coincide with a pole.
Direction_3 normal = plane.orthogonal_direction();
bool xz_plane = x_sign(normal) == ZERO;
Project project = (xz_plane) ? project_xz : project_yz;
Direction_2 s = project(source);
Direction_2 t = project(target);
bool s_x_is_positive = Traits::is_x_positive(s);
bool t_x_is_positive = Traits::is_x_positive(t);
bool plane_is_positive = (xz_plane) ?
(y_sign(normal) == NEGATIVE) : (x_sign(normal) == POSITIVE);
bool ccw = ((plane_is_positive && s_x_is_positive) ||
(!plane_is_positive && !s_x_is_positive));
const Point_2 & pole1 = (ccw) ? pp : np;
X_monotone_curve_2 xc1(source, pole1, plane, true, ccw);
*oi++ = make_object(xc1);
if (s_x_is_positive != t_x_is_positive) {
// Construct 1 more arc:
X_monotone_curve_2 xc2(pole1, target, plane, true, !ccw);
*oi++ = make_object(xc2);
return oi;
}
// Construct 2 more arcs:
const Point_2 & pole2 = (ccw) ? np : pp;
X_monotone_curve_2 xc2(pole1, pole2, plane, true, !ccw);
*oi++ = make_object(xc2);
X_monotone_curve_2 xc3(pole2, target, plane, true, ccw);
*oi++ = make_object(xc3);
return oi;
}
// The projections of the endpoints are not colinear:
xc1.set_is_vertical(false);
xc2.set_is_vertical(false);
// The curve is not vertical, (none of the enpoints coincide with a pole)
Point_2 p(-1, 0, plane.a() / plane.c());
xc1.set_target(p);
xc2.set_source(p);
bool directed_right = orient == LEFT_TURN;
xc1.set_is_directed_right(directed_right);
xc2.set_is_directed_right(directed_right);
Direction_2 s = project_xy(source);
Direction_2 t = project_xy(target);
const Direction_2 & nx = Traits::neg_x_2();
Kernel kernel;
bool directed_right =
kernel.counterclockwise_in_between_2_object()(nx, s, t);
X_monotone_curve_2 xc1(source, p, plane, false, directed_right);
X_monotone_curve_2 xc2(p, target, plane, false, directed_right);
*oi++ = make_object(xc1);
*oi++ = make_object(xc2);
return oi;
}
};
/*! Get a Make_x_monotone_2 function object */
/*! Obtain a Make_x_monotone_2 function object */
Make_x_monotone_2 make_x_monotone_2_object() const
{ return Make_x_monotone_2(); }
@ -1375,7 +1341,7 @@ public:
if (equal(l1, l2)) {
const Point_2 & trg = (in_between(r1, l2, r2)) ? r1_3 : r2_3;
X_monotone_curve_2 xc(l1_3, trg, plane, true, vertical, true);
X_monotone_curve_2 xc(l1_3, trg, plane, vertical, true);
*oi++ = make_object(xc);
return oi;
}
@ -1392,7 +1358,7 @@ public:
return oi;
}
const Point_2 & trg = (in_between(r1, l2, r2)) ? r1_3 : r2_3;
X_monotone_curve_2 xc(l2_3, trg, plane, true, vertical, true);
X_monotone_curve_2 xc(l2_3, trg, plane, vertical, true);
*oi++ = make_object(xc);
return oi;
}
@ -1405,7 +1371,7 @@ public:
return oi;
}
const Point_2 & trg = (in_between(r1, l2, r2)) ? r1_3 : r2_3;
X_monotone_curve_2 xc(l1_3, trg, plane, true, vertical, true);
X_monotone_curve_2 xc(l1_3, trg, plane, vertical, true);
*oi++ = make_object(xc);
return oi;
}
@ -1558,7 +1524,7 @@ public:
}
};
/*! Get an Intersect_2 function object */
/*! Obtain an Intersect_2 function object */
Intersect_2 intersect_2_object() const { return Intersect_2(); }
class Are_mergeable_2 {
@ -1592,7 +1558,7 @@ public:
}
};
/*! Get an Are_mergeable_2 function object */
/*! Obtain an Are_mergeable_2 function object */
Are_mergeable_2 are_mergeable_2_object() const { return Are_mergeable_2(); }
class Merge_2 {
@ -1642,7 +1608,7 @@ public:
}
};
/*! Get a Merge_2 function object */
/*! Obtain a Merge_2 function object */
Merge_2 merge_2_object() const { return Merge_2(); }
//@}
@ -1667,7 +1633,7 @@ public:
}
};
/*! Get an Approximate_2 function object */
/*! Obtain an Approximate_2 function object */
Approximate_2 approximate_2_object() const { return Approximate_2(); }
class Construct_x_monotone_curve_2 {
@ -1683,7 +1649,7 @@ public:
{ return X_monotone_curve_2(p, q); }
};
/*! Get a Construct_x_monotone_curve_2 function object */
/*! Obtain a Construct_x_monotone_curve_2 function object */
Construct_x_monotone_curve_2 construct_x_monotone_curve_2_object() const
{ return Construct_x_monotone_curve_2(); }
//@}
@ -1706,7 +1672,7 @@ public:
{ return (xc.is_directed_right()) ? SMALLER : LARGER; }
};
/*! Get a Compare_endpoints_xy_2 function object */
/*! Obtain a Compare_endpoints_xy_2 function object */
Compare_endpoints_xy_2 compare_endpoints_xy_2_object() const
{ return Compare_endpoints_xy_2(); }
@ -1720,7 +1686,7 @@ public:
{ return xc.opposite(); }
};
/*! Get a Construct_opposite_2 function object */
/*! Obtain a Construct_opposite_2 function object */
Construct_opposite_2 construct_opposite_2_object() const
{ return Construct_opposite_2(); }
//@}
@ -1915,7 +1881,13 @@ protected:
inline bool is_x_negative(Direction_2 d)
{ return (CGAL::sign(d.dx()) == NEGATIVE); }
public:
inline static Sign x_sign(Direction_3 d) { return CGAL::sign(d.dx()); }
inline static Sign y_sign(Direction_3 d) { return CGAL::sign(d.dy()); }
inline static Sign z_sign(Direction_3 d) { return CGAL::sign(d.dz()); }
public:
/*! Default constructor */
Arr_x_monotone_great_circular_arc_on_sphere_3() :
m_is_x_monotone(true),
@ -1939,12 +1911,12 @@ public:
(const Arr_extended_direction_3 & src,
const Arr_extended_direction_3 & trg,
const Plane_3 & plane,
bool is_x_monotone, bool is_vertical,
bool is_directed_right, bool is_full = false, bool is_degenerate = false) :
bool is_vertical, bool is_directed_right,
bool is_full = false, bool is_degenerate = false) :
m_source(src),
m_target(trg),
m_plane(plane),
m_is_x_monotone(is_x_monotone),
m_is_x_monotone(true),
m_is_vertical(is_vertical),
m_is_directed_right(is_directed_right),
m_is_full(is_full),
@ -1999,6 +1971,7 @@ public:
target));
m_plane = Traits::construct_plane_3(source, target);
// Check whether any one of the endpoint coincide with a pole:
if (source.is_max_boundary()) {
set_is_vertical(true);
set_is_directed_right(false);
@ -2068,6 +2041,7 @@ public:
// The arc is not vertical!
set_is_vertical(false);
set_is_directed_right(orient == LEFT_TURN);
set_is_full(kernel.equal_3_object()(source, target));
}
/*! Construct a full spherical_arc from a plane
@ -2102,12 +2076,62 @@ public:
m_source(source),
m_target(target),
m_plane(plane),
m_is_x_monotone(true),
m_is_degenerate(false)
{
CGAL_precondition(has_on(plane, source));
CGAL_precondition(has_on(plane, target));
typedef Arr_great_circular_arc_on_sphere_traits_2<Kernel> Traits;
CGAL_assertion_msg(0, "Not implemented yet!");
CGAL_precondition(Traits::has_on(plane, source));
CGAL_precondition(Traits::has_on(plane, target));
// Check whether any one of the endpoint coincide with a pole:
if (source.is_max_boundary()) {
set_is_vertical(true);
set_is_directed_right(false);
set_if_full(false);
return;
}
if (source.is_min_boundary()) {
set_is_vertical(true);
set_is_directed_right(true);
set_if_full(false);
return;
}
if (target.is_max_boundary()) {
set_is_vertical(true);
set_is_directed_right(true);
set_if_full(false);
return;
}
if (target.is_min_boundary()) {
set_is_vertical(true);
set_is_directed_right(false);
set_if_full(false);
return;
}
Direction_3 normal = plane.orthogonal_direction();
if (z_sign(normal) == ZERO) {
set_is_vertical(true);
set_if_full(false);
bool xz_plane = x_sign(normal) == ZERO;
Project project = (xz_plane) ? Traits::project_xz : Traits::project_yz;
Direction_2 s = project(source);
Direction_2 t = project(target);
bool s_x_is_positive = Traits::is_x_positive(s);
bool t_x_is_positive = Traits::is_x_positive(t);
bool plane_is_positive = (xz_plane) ?
(y_sign(normal) == NEGATIVE) : (x_sign(normal) == POSITIVE);
bool ccw = ((plane_is_positive && s_x_is_positive) ||
(!plane_is_positive && !s_x_is_positive));
set_is_directed_right(ccw);
return;
}
// The arc is not vertical!
set_is_vertical(false);
set_is_directed_right(z_sign(normal) == POSITIVE);
}
/*! Set the source endpoint direction.
@ -2174,6 +2198,7 @@ public:
* \param p the query point direction.
* \return true if p is in the x-range of the (closed) spherical_arc and
* false otherwise.
* \pre p does not coincide with one of the poles
*/
bool is_in_x_range(const Arr_extended_direction_3 & p) const
{
@ -2181,22 +2206,30 @@ public:
CGAL_precondition(!p.is_min_boundary() && !p.is_max_boundary());
Direction_2 dir_xy = Traits::project_xy(p);
Kernel kernel;
if (is_vertical()) {
const Arr_extended_direction_3 & p =
if (left().is_min_boundary() && right().is_max_boundary()) {
// Both endpoints coincide with the poles resp.
CGAL_assertion_msg(0, "Not implemented yet!");
}
// At least one endpoint does not coincide with a pole.
// Obtain the endpoint that does not coincide with a pole:
const Arr_extended_direction_3 & q =
(left().is_min_boundary()) ? right() : left();
Direction_2 p_xy = Traits::project_xy(p);
return kernel.equal_2_object()(dir_xy, p_xy);
Direction_2 p_2 = Traits::project_xy(p);
Direction_2 q_2 = Traits::project_xy(q);
Kernel kernel;
return kernel.equal_2_object()(p_2, q_2);
}
// The curve is not vertical:
Direction_2 r_xy = Traits::project_xy(right());
if (kernel.equal_2_object()(dir_xy, r_xy)) return true;
Direction_2 l_xy = Traits::project_xy(left());
if (kernel.equal_2_object()(dir_xy, l_xy)) return true;
return kernel.counterclockwise_in_between_2_object()(dir_xy, l_xy, r_xy);
Direction_2 p_2 = Traits::project_xy(p);
Direction_2 r = Traits::project_xy(right());
Kernel kernel;
if (kernel.equal_2_object()(p_2, r)) return true;
Direction_2 l = Traits::project_xy(left());
if (kernel.equal_2_object()(p_2, l)) return true;
return kernel.counterclockwise_in_between_2_object()(p_2, l, r);
}
#if 0
@ -2226,8 +2259,13 @@ public:
}
};
/*! A Representation of a general great circular arc embedded on a sphere,
* as used by the Arr_great_circular_arc_on_sphere_traits_2 traits-class
/*! A representation of a general great circular arc embedded on a sphere,
* used by the Arr_great_circular_arc_on_sphere_traits_2 traits-class
* An arc is uniqely represented by a plane p, and two endpoints the source
* s and the target t, which lie in the plane p. The points of the arc are
* the locus of points visited when moving from the source s toward the
* target t on the plane p in counterclockwise direction along the circle
* defined by s and t.
*/
template <typename T_Kernel>
class Arr_great_circular_arc_on_sphere_3 :
@ -2269,8 +2307,10 @@ public:
bool is_full = false,
bool is_degenerate = false) :
Base(src, trg, plane,
is_x_monotone, is_vertical, is_directed_right, is_full, is_degenerate)
{}
is_vertical, is_directed_right, is_full, is_degenerate)
{
set_is_x_monotone(is_x_monotone);
}
/*! Construct a spherical_arc from two endpoint directions. It is assumed
* that the arc is the one with the smaller angle among the two.
@ -2330,8 +2370,8 @@ public:
Orientation orient = Traits::orientation(s, t);
if (orient == COLLINEAR) {
set_is_vertical(true);
if (equal_2(s, t)) {
set_is_vertical(true);
const Direction_2 & nx = Traits::neg_x_2();
if (Traits::orientation(nx, s) == COLLINEAR) {
// Project onto xz plane:
@ -2400,6 +2440,24 @@ public:
const Plane_3 & plane) :
Base(source, target, plane)
{}
/*! Construct a spherical_arc from two endpoints directions contained
* in a plane.
* \param plane the containing plane.
* \param source the source-point direction.
* \param target the target-point direction.
* \pre The two endpoints are not the same, and both lie on the given plane.
*/
Arr_great_circular_arc_on_sphere_3(const Plane_3 & plane) :
{
m_plane = plane;
m_is_x_monotone = false;
Direction_3 normal = plane.orthogonal_direction();
m_is_vertical = (CGAL::sign(normal.dz()) == ZERO);
m_is_directed_right = true;
m_is_full = true;
m_is_degenerate = false;
}
};
/*! Inserter for the spherical_arc class used by the traits-class */