cgal/Kernel_d/noweb/intersection_objects_d.lw

1054 lines
31 KiB
Plaintext

\documentclass[a4paper,11pt,twoside]{article}
\usepackage{Lweb}
\input{defs}
\begin{document}
\section{Two elementary operations}
\subsection{Intersecting two lines}
Here we implement a $d$-dimensional intersection routine for two
non-parallel lines. We do the intersection and node calculation by the
help of some matrix calculation. We know that a common point $x$ of
two lines $s_1t_1$ and $s_2t_2$ through two $d$-dimensional points
obeys the equations:
\begin{eqnarray}
x_1 & = & s_1 + \lambda_1 (t_1 - s_1) \\
x_2 & = & s_2 + \lambda_2 (t_2 - s_2)
\end{eqnarray}
Assume $x_1 = x_2$ and rearrange with variables $\lambda_1$ and
$\lambda_2$. Then we get the $d \times 2$ cartesian matrix system
\begin{displaymath}
\begin{bmatrix}
t_{1_0} - s_{1_0} & s_{2_0} - t_{2_0} \\
\vdots & \vdots \\
t_{1_{d-1}} - s_{1_{d-1}} & s_{2_{d-1}} - t_{2_{d-1}}
\end{bmatrix}
*
\begin{bmatrix} \lambda_1 \\ \lambda_2 \end{bmatrix}
=
\begin{bmatrix}
s_{2_0} - s_{1_0} \\
\vdots \\
s_{2_{d-1}} - s_{1_{d-1}}
\end{bmatrix}
\end{displaymath}
The code below puts this linear system into a matrix after
multiplication of each row with its common denominator $s_{1_d}
s_{2_d} t_{1_d} t_{2_d}$. Afterwards we solve the system. If we get a
solution we calculate the intersection point $x$ and deliver
additionally $\lambda_1 = l1_{num}/l1_{den}$ and $\lambda_2 =
l2_{num}/l2_{den}$ as rational numbers for outside use.
Note the possible exceptions here. Each of the direction vectors of
the lines can be the zero vectors in case that its spanning points
are identical. In which case we just return that result.
<<homogeneous intersection working horses>>=
/*{\Manpage{Line_line_intersectionHd}{R}{intersecting two lines}}*/
template <class R>
class Line_line_intersectionHd {
typedef typename R::RT RT;
typedef typename R::FT FT;
typedef typename R::LA LA;
typedef typename R::Point_d Point_d;
public:
enum Intersection_result { NO, POINT, LINE };
Intersection_result operator()(
const Point_d& s1, const Point_d& t1,
const Point_d& s2, const Point_d& t2,
Point_d& p, FT& l1, FT& l2)
/*{\Mfunop returns |NO| if the lines which are represented by |s1t1|
and |s2t2| don't intersect, returns |POINT| if they intersect in a
unique point, and returns LINE if they are identical. In the |POINT|
case the point of intersection is assigned to |p|. Then |p = s1 + l1
* t1-s1| and |p = s2 + l2 * t2-s2|. \precond none of the point pairs
is degenerate.}*/
{
int d = s1.dimension(),i;
CGAL_assertion_msg(d==s2.dimension(),
"intersection: dimensions disagree!");
typename LA::Matrix M(d,2),S;
typename LA::Vector b(d), lambda(2), c;
RT D;
RT s1w = s1.homogeneous(d);
RT t1w = t1.homogeneous(d);
RT s2w = s2.homogeneous(d);
RT t2w = t2.homogeneous(d);
RT g1w = s1w*t1w;
RT g2w = s2w*t2w;
RT t12w = t1w*t2w;
/* init $d \times 2$ - matrix |M| and $d$ - vector |b| */
for (i = 0; i < d; i++) {
M(i,0) = g2w * (t1.homogeneous(i) * s1w - s1.homogeneous(i) * t1w);
M(i,1) = g1w * (s2.homogeneous(i) * t2w - t2.homogeneous(i) * s2w);
b[i] = t12w * (s2.homogeneous(i) * s1w - s1.homogeneous(i) * s2w);
}
if (LA::linear_solver(M,b,lambda,D,S,c)) {
if (S.column_dimension()>0) return LINE;
l1 = R::make_FT(lambda[0],D);
l2 = R::make_FT(lambda[1],D);
p = s1 + l1 * (t1 - s1);
return POINT;
}
return NO;
}
};
@ Now we implement the cartesian $d$-dimensional intersection routine
for two non-parallel lines. We do the intersection and node
calculation by the help of some matrix calculation. The code below
puts this linear system from above directly into a matrix. Afterwards
we solve the system. If we get a solution we calculate the
intersection point $x$ and deliver additionally $\lambda_1$ and
$\lambda_2$ for outside use.
Note the possible exceptions here. Each of the direction vectors of
the lines can be the zero vectors in case that its spanning points
are identical. In which case we just return that result.
<<cartesian intersection working horses>>=
/*{\Manpage{Line_line_intersectionCd}{R}{intersecting two lines}}*/
template <class R>
class Line_line_intersectionCd {
typedef typename R::FT FT;
typedef typename R::LA LA;
typedef typename R::Point_d Point_d;
typedef typename R::Line_d Line_d;
public:
enum Intersection_result { NO, POINT, LINE };
Intersection_result operator()(
const Point_d& s1, const Point_d& t1,
const Point_d& s2, const Point_d& t2,
Point_d& p, FT& l1, FT& l2)
/*{\Mfunop returns |NO| if the lines which are represented by |s1t1|
and |s2t2| don't intersect, returns |POINT| if they intersect in a
unique point, and returns LINE if they are identical. In the |POINT|
case the point of intersection is assigned to |p|. Then |p = s1 + l1
* t1-s1| and |p = s2 + l2 * t2-s2|. \precond none of the point pairs
is degenerate.}*/
{
int d = s1.dimension(),i;
CGAL_assertion_msg(d==s2.dimension(),
"intersection: dimensions disagree!");
typename LA::Matrix M(d,2),S;
typename LA::Vector b(d), lambda(2), c;
FT D;
/* init $d \times 2$ - matrix |M| and $d$ - vector |b| */
for (i = 0; i < d; i++) {
M(i,0) = t1.cartesian(i) - s1.cartesian(i);
M(i,1) = s2.cartesian(i) - t2.cartesian(i);
b[i] = s2.cartesian(i) - s1.cartesian(i);
}
if (LA::linear_solver(M,b,lambda,D,S,c)) {
if ( S.column_dimension()>0 ) return LINE;
l1 = lambda[0]; l2 = lambda[1];
p = s1 + l1 * (t1 - s1);
#ifdef CGAL_CHECK_EXACTNESS
Line_d L1(s1,t1), L2(s2,t2);
CGAL_assertion(L1.has_on(p)&&L2.has_on(p));
#endif
return POINT;
}
return NO;
}
};
@ \subsection{The intersection of a line and a hyperplane}
We want to calculate if a line defined by two points $s$ and $t$
intersects a hyperplane $h$. For the hyperplane intersection we first
check whether $s$ and $t$ lie in $h$. If both are contained we are
done with result |LINE|. If only one is contained we have already
found a single point of intersection for result |POINT|. If none is
contained there is at most one point of intersection. Let $s$ and $t$
be distinct points on $l$. Note that the evaluation of $h$ at point
$h(p) := h_d + \sum_{i=0}^{d-1} h_i |p.cartesian(i)|$ is different
from the evaluation with its homogeneous representation
$\sum_{i=0}^{d} h_i |p.homogeneous(i)|$. Let us write the latter
sloppily as an inner product of the representing vectors $h \cdot
p$. We have $h \cdot p = h(p) * p_d$.
Now let $S = s \cdot h$ and $T = t \cdot h$. If $h(s) = S/s_d = T/t_d
= h(t)$ then the line is parallel to the plane and there is no
intersection. The latter translates to the test $D := S t_d - T s_d =
0$? If non-zero, the point with homogeneous coordinates $(S t_0 - T
s_0, \ldots, S t_i - T s_i, \ldots, S t_d - T s_d)$ lies on $h$. For
if we interpret the tuples as vectors we get $p = St - Ts$ and the
homogeneous evaluation of $h$ on this point is $s \cdot h * t \cdot h
- t \cdot h * s \cdot h$. Note that with $p = s + \lambda (t-s)$ we
get for a valid point on the hyperplane $h(p) = 0 \Leftrightarrow h(s)
+ \lambda (h(t)-h(s)) = 0$ which gets us $\lambda = - h(s) /
(h(t)-h(s)) = S t_d / D$.
<<homogeneous intersection working horses>>=
/*{\Manpage {Line_hyperplane_intersectionHd}{R}
{intersecting a line and a hyperplane}}*/
template <class R>
class Line_hyperplane_intersectionHd {
typedef typename R::RT RT;
typedef typename R::FT FT;
typedef typename R::LA LA;
typedef typename R::Point_d Point_d;
typedef typename R::Hyperplane_d Hyperplane_d;
public:
enum Intersection_result { NO, POINT, LINE };
Intersection_result operator()(const Point_d& s, const Point_d& t,
const Hyperplane_d& h, Point_d& p, FT& lambda)
/*{\Mfunop returns |NO| if the line represented by |s1t1| and the
hyperplane |h| don't intersect, returns |POINT| if they intersect in a
unique point, and returns LINE if the line is part of the
hyperplane. In the |POINT| case the point of intersection is assigned
to |p|. Then |p = s1 + lambda * t1-s1|. \precond the point pair is
not degenerate.}*/
{
CGAL_assertion_msg((h.dimension()==s.dimension() &&
h.dimension()==t.dimension()),
"Line_hyperplane_intersection_d: dimensions do not agree.");
int d = h.dimension(),i;
RT S(0),T(0);
for (i=0; i<=d; ++i) {
S += h[i]*s.homogeneous(i);
T += h[i]*t.homogeneous(i);
}
bool s_contained = CGAL_NTS is_zero(S),
t_contained = CGAL_NTS is_zero(T);
if (s_contained && t_contained) { p = s; return LINE; }
if (s_contained) { p = s; return POINT; }
if (t_contained) { p = t; return POINT; }
// now the simple cases are done
RT D = S * t.homogeneous(d) - T * s.homogeneous(d);
if (CGAL_NTS is_zero(D)) return NO;
typename LA::Vector homog(d + 1);
for (i = 0; i < d; ++i)
homog[i] = S * t.homogeneous(i) - T * s.homogeneous(i);
homog[d] = D;
p = Point_d(d,homog.begin(),homog.end());
lambda = R::make_FT(S * t.homogeneous(d), D);
return POINT;
}
};
@ Again we save on the homogenizing denominators. We want to
calculate if a line defined by two points $s$ and $t$ intersects a
hyperplane $h$. For the hyperplane intersection we first check whether
$s$ and $t$ lie in $h$. If both are contained we are done with result
|LINE|. If only one is contained we have already found a single point
of intersection for result |POINT|. If none is contained there is at
most one point of intersection. Let $s$ and $t$ be distinct points on
$l$. Note that the evaluation of $h$ at point $h(p) := h_d +
\sum_{i=0}^{d-1} h_i |p.cartesian(i)|$ is a measure for the distance
of $p$ to the hyperplane $h$.
Now let $S = h(s)$ and $T = h(t)$. If $h(s) = h(t)$ then the line is
parallel to the plane and there is no intersection. The latter
translates to the test $D := S - T = 0$? If non-zero, the point with
homogeneous coordinates $p = \frac{S}{D} t - \frac{T}{D} s$ lies on
$h$. For the evaluation of $h$ on this point is $\frac{S}{D} h(t) -
\frac{T}{D} h(s) = (h(s)h(t) - h(t)h(s))/D = 0$. Note that with $p =
s + \lambda (t-s)$ we get for a valid point on the hyperplane $h(p) =
0 \Leftrightarrow h(s) + \lambda (h(t)-h(s)) = 0$ which gets us
$\lambda = - h(s) / (h(t)-h(s)) = S / D$.
<<cartesian intersection working horses>>=
/*{\Manpage {Line_hyperplane_intersectionCd}{R}
{intersecting a line and a hyperplane}}*/
template <class R>
class Line_hyperplane_intersectionCd {
typedef typename R::FT FT;
typedef typename R::LA LA;
typedef typename R::Point_d Point_d;
typedef typename R::Hyperplane_d Hyperplane_d;
public:
enum Intersection_result { NO, POINT, LINE };
Intersection_result operator()(const Point_d& s, const Point_d& t,
const Hyperplane_d& h, Point_d& p, FT& lambda)
/*{\Mfunop returns |NO| if the line represented by |s1t1| and the
hyperplane |h| don't intersect, returns |POINT| if they intersect in a
unique point, and returns LINE if the line is part of the
hyperplane. In the |POINT| case the point of intersection is assigned
to |p|. Then |p = s1 + lambda * t1-s1|. \precond the point pair is
not degenerate.}*/
{
CGAL_assertion_msg((h.dimension()==s.dimension() &&
h.dimension()==t.dimension()),
"Line_hyperplane_intersection_d: dimensions do not agree.");
int d = h.dimension(),i;
FT S = h.value_at(s), T = h.value_at(t);
bool s_contained = CGAL_NTS is_zero(S),
t_contained = CGAL_NTS is_zero(T);
if (s_contained && t_contained) { p = s; return LINE; }
if (s_contained) { p = s; return POINT; }
if (t_contained) { p = t; return POINT; }
// now the simple cases are done
FT D = S - T;
if ( CGAL_NTS is_zero(D) ) return NO;
typename LA::Vector v(d);
for (i = 0; i < d; ++i)
v[i] = (S * t.cartesian(i) - T * s.cartesian(i))/D;
p = Point_d(d,v.begin(),v.end()); lambda = S/D;
#ifdef CGAL_CHECK_EXACTNESS
Line_d l(s,t);
CGAL_assertion(h.has_on(p)&&l.has_on(p));
#endif
return POINT;
}
};
@ \section{The interface intersection pairs}
We use the engines above to write generic intersection routines.
<<line line intersection>>=
template <class R>
class Line_d_Line_d_pair {
public:
enum Intersection_result {NO, POINT, LINE};
typedef typename R::Point_d Point_d;
typedef typename R::Line_d Line_d;
typedef typename R::FT FT;
protected:
Line_d _l1, _l2;
bool _known;
Intersection_result _result;
Point_d _ip;
public:
Line_d_Line_d_pair() : _known(false) {}
Line_d_Line_d_pair(const Line_d& l1, const Line_d& l2)
: _l1(l1), _l2(l2), _known(false) {}
Intersection_result intersection_type();
bool intersection(Point_d& result);
bool intersection(Line_d& result);
};
template <class R>
Line_d_Line_d_pair<R>::Intersection_result
Line_d_Line_d_pair<R>::intersection_type()
{
if (_known) return _result;
_known = true;
//CGAL_assertion(!_l1.is_degenerate()&&!_l2.is_degenerate());
typedef typename R::Line_line_intersection_d Int_obj_type;
Int_obj_type Intersect;
FT l1,l2;
typename Int_obj_type::Intersection_result res =
Intersect(_l1.point(0),_l1.point(1),
_l2.point(0),_l2.point(1),
_ip,l1,l2);
if (res == Int_obj_type::LINE) { return _result = LINE; }
if (res == Int_obj_type::POINT) { return _result = POINT; }
return _result = NO;
}
template <class R>
bool Line_d_Line_d_pair<R>::intersection(Point_d& p)
{ if (!_known) intersection_type();
if (_result != POINT) return false;
p = _ip; return true;
}
template <class R>
bool Line_d_Line_d_pair<R>::intersection(Line_d& l)
{ if (!_known) intersection_type();
if (_result != LINE) return false;
l = _l1; return true;
}
<<line ray intersection>>=
template <class R>
class Line_d_Ray_d_pair {
public:
enum Intersection_result {NO, POINT, RAY};
typedef typename R::Point_d Point_d;
typedef typename R::Ray_d Ray_d;
typedef typename R::Line_d Line_d;
typedef typename R::FT FT;
protected:
Line_d _l; Ray_d _r;
bool _known;
Intersection_result _result;
Point_d _ip;
public:
Line_d_Ray_d_pair() : _known(false) {}
Line_d_Ray_d_pair(const Line_d& l, const Ray_d& r)
: _l(l), _r(r), _known(false) {}
Intersection_result intersection_type();
bool intersection(Point_d& result);
bool intersection(Ray_d& result);
};
template <class R>
Line_d_Ray_d_pair<R>::Intersection_result
Line_d_Ray_d_pair<R>::intersection_type()
{
if (_known) return _result;
_known = true;
//CGAL_assertion(!_l.is_degenerate()&&!_r.is_degenerate());
typedef typename R::Line_line_intersection_d Int_obj_type;
Int_obj_type Intersect;
FT l1,l2;
typename Int_obj_type::Intersection_result res =
Intersect(_l.point(0),_l.point(1),
_r.point(0),_r.point(1),
_ip,l1,l2);
if ( res == Int_obj_type::LINE ) { return _result = RAY; }
if ( res == Int_obj_type::POINT &&
l2 >= FT(0) )
{ return _result = POINT; }
return _result = NO;
}
template <class R>
bool Line_d_Ray_d_pair<R>::intersection(Point_d& p)
{ if (!_known) intersection_type();
if (_result != POINT) return false;
p = _ip; return true;
}
template <class R>
bool Line_d_Ray_d_pair<R>::intersection(Ray_d& r)
{ if (!_known) intersection_type();
if (_result != RAY) return false;
r = _r; return true;
}
<<line segment intersection>>=
template <class R>
class Line_d_Segment_d_pair {
public:
enum Intersection_result {NO, POINT, SEGMENT};
typedef typename R::Point_d Point_d;
typedef typename R::Segment_d Segment_d;
typedef typename R::Line_d Line_d;
typedef typename R::FT FT;
protected:
Line_d _l; Segment_d _s;
bool _known;
Intersection_result _result;
Point_d _ip;
public:
Line_d_Segment_d_pair() : _known(false) {}
Line_d_Segment_d_pair(const Line_d& l, const Segment_d& s)
: _l(l), _s(s), _known(false) {}
Intersection_result intersection_type();
bool intersection(Point_d& result);
bool intersection(Segment_d& result);
};
template <class R>
Line_d_Segment_d_pair<R>::Intersection_result
Line_d_Segment_d_pair<R>::intersection_type()
{
if (_known) return _result;
_known = true;
//CGAL_assertion(!_l.is_degenerate());
if ( _s.is_degenerate() ) {
if ( _l.has_on(_s.point(0)) ) {
_ip = _s.point(0);
return _result = POINT;
}
return _result = NO;
}
// _s not degenerate
typedef typename R::Line_line_intersection_d Int_obj_type;
Int_obj_type Intersect;
FT l1,l2;
typename Int_obj_type::Intersection_result res =
Intersect(_l.point(0),_l.point(1),
_s.point(0),_s.point(1),
_ip,l1,l2);
if ( res == Int_obj_type::LINE ) { return _result = SEGMENT; }
if ( res == Int_obj_type::POINT &&
FT(0) <= l2 && l2 <= FT(1) )
{ return _result = POINT; }
return _result = NO;
}
template <class R>
bool Line_d_Segment_d_pair<R>::intersection(Point_d& p)
{ if (!_known) intersection_type();
if (_result != POINT) return false;
p = _ip; return true;
}
template <class R>
bool Line_d_Segment_d_pair<R>::intersection(Segment_d& s)
{ if (!_known) intersection_type();
if (_result != SEGMENT) return false;
s = _s; return true;
}
<<ray ray intersection>>=
template <class R>
class Ray_d_Ray_d_pair {
public:
enum Intersection_result { NO, POINT, SEGMENT, RAY };
typedef typename R::FT FT;
typedef typename R::Point_d Point_d;
typedef typename R::Segment_d Segment_d;
typedef typename R::Ray_d Ray_d;
protected:
Ray_d _r1, _r2;
bool _known;
Intersection_result _result;
Point_d _ip; Segment_d _is; Ray_d _ir;
public:
Ray_d_Ray_d_pair() : _known(false) {}
Ray_d_Ray_d_pair(const Ray_d& r1, const Ray_d& r2)
: _r1(r1), _r2(r2), _known(false) {}
Intersection_result intersection_type();
bool intersection(Point_d& result);
bool intersection(Segment_d& result);
bool intersection(Ray_d& result);
};
template <class R>
Ray_d_Ray_d_pair<R>::Intersection_result
Ray_d_Ray_d_pair<R>::intersection_type()
{
if (_known) return _result;
_known = true;
//CGAL_assertion((!_r1.is_degenerate()&&!_r2.is_degenerate());
// none of the lines should be trivial
typedef typename R::Line_line_intersection_d Int_obj_type;
Int_obj_type Intersect;
FT l1,l2;
typename Int_obj_type::Intersection_result res =
Intersect(_r1.point(0),_r1.point(1),
_r2.point(0),_r2.point(1),_ip,l1,l2);
if (res == Int_obj_type::LINE)
<<determine common points of two rays>>
if (res == Int_obj_type::POINT &&
FT(0) <= l1 && FT(0) <= l2)
{ return _result = POINT; }
return _result = NO;
// now not parallel
}
@ We determine the common points of a ray and a segment whose
supporting lines are equal.
<<determine common points of two rays>>=
{
if ( _r1.direction() == _r2.direction() ) {
if ( _r1.has_on(_r2.source()) ) _ir = _r2;
else _ir = _r1;
return _result = RAY;
}
// now oppositely directed:
if ( _r1.has_on(_r2.source()) ) {
if ( _r1.source() != _r2.source() )
{ _is = Segment_d(_r1.source(),_r2.source());
return _result = SEGMENT; }
else
{ _ip = _r1.source(); return _result = POINT; }
}
return _result = NO;
}
<<ray ray intersection>>=
template <class R>
bool
Ray_d_Ray_d_pair<R>::intersection(Point_d& p)
{ if (!_known) intersection_type();
if (_result != POINT) return false;
p = _ip; return true;
}
template <class R>
bool
Ray_d_Ray_d_pair<R>::intersection(Segment_d& s)
{ if (!_known) intersection_type();
if (_result != SEGMENT) return false;
s = _is; return true;
}
template <class R>
bool
Ray_d_Ray_d_pair<R>::intersection(Ray_d& r)
{ if (!_known) intersection_type();
if (_result != RAY) return false;
r = _ir; return true;
}
<<ray segment intersection>>=
template <class R>
class Ray_d_Segment_d_pair {
public:
enum Intersection_result { NO, POINT, SEGMENT };
typedef typename R::FT FT;
typedef typename R::Point_d Point_d;
typedef typename R::Segment_d Segment_d;
typedef typename R::Ray_d Ray_d;
protected:
Ray_d _r; Segment_d _s;
bool _known;
Intersection_result _result;
Point_d _ip; Segment_d _is;
public:
Ray_d_Segment_d_pair() : _known(false) {}
Ray_d_Segment_d_pair(const Ray_d& r, const Segment_d& s)
: _r(r), _s(s), _known(false) {}
Intersection_result intersection_type();
bool intersection(Point_d& result);
bool intersection(Segment_d& result);
};
template <class R>
Ray_d_Segment_d_pair<R>::Intersection_result
Ray_d_Segment_d_pair<R>::intersection_type()
{
if (_known) return _result;
_known = true;
//CGAL_assertion(!_r.is_degenerate());
if ( _s.is_degenerate() ) {
if ( _r.has_on(_s.point(0)) )
{ _ip = _s.point(0); return _result = POINT; }
return _result = NO;
}
// now s is not degenerate
typedef typename R::Line_line_intersection_d Int_obj_type;
Int_obj_type Intersect;
FT l1,l2;
typename Int_obj_type::Intersection_result res =
Intersect(_r.point(0),_r.point(1),
_s.point(0),_s.point(1),_ip,l1,l2);
if (res == Int_obj_type::LINE)
<<determine common points of a ray and a segment>>
if (res == Int_obj_type::POINT &&
FT(0) <= l1 && FT(0) <= l2 && l2 <= FT(1))
{ return _result = POINT; }
return _result = NO;
// now not parallel
}
@ We determine the common points of a ray and a segment whose
supporting lines are equal.
<<determine common points of a ray and a segment>>=
{
Point_d p1 = _s.point(0), p2 = _s.point(1);
if ( _s.direction() != _r.direction() ) std::swap(p1,p2);
// now order p2 after p1 on r underlying line
typename R::Position_on_line_d pos;
pos(p1, _r.point(0),_r.point(1), l1);
pos(p2, _r.point(0),_r.point(1), l2);
if ( l1 < FT(0) ) p1 = _r.point(0);
if ( l2 < FT(0) ) { return _result = NO; }
if ( p1 == p2 ) { _ip = p1; return _result = NO; }
_is = Segment_d(p1,p2);
return _result = SEGMENT;
}
<<ray segment intersection>>=
template <class R>
bool
Ray_d_Segment_d_pair<R>::intersection(Point_d& p)
{ if (!_known) intersection_type();
if (_result != POINT) return false;
p = _ip; return true;
}
template <class R>
bool
Ray_d_Segment_d_pair<R>::intersection(Segment_d& s)
{ if (!_known) intersection_type();
if (_result != SEGMENT) return false;
s = _is; return true;
}
<<segment segment intersection>>=
template <class R>
class Segment_d_Segment_d_pair {
public:
enum Intersection_result { NO, POINT, SEGMENT };
typedef typename R::FT FT;
typedef typename R::Point_d Point_d;
typedef typename R::Segment_d Segment_d;
protected:
Segment_d _s1,_s2;
bool _known;
Intersection_result _result;
Point_d _ip; Segment_d _is;
public:
Segment_d_Segment_d_pair() : _known(false) {}
Segment_d_Segment_d_pair(const Segment_d& s1, const Segment_d& s2)
: _s1(s1), _s2(s2), _known(false) {}
Intersection_result intersection_type();
bool intersection(Point_d& result);
bool intersection(Segment_d& result);
};
template <class R>
Segment_d_Segment_d_pair<R>::Intersection_result
Segment_d_Segment_d_pair<R>::intersection_type()
{
if (_known) return _result;
_known = true;
if ( _s1.is_degenerate() ) {
if ( _s2.is_degenerate() ) {
if ( _s1.point(0) == _s2.point(0) )
{ _ip = _s1.point(0); return _result = POINT; }
else { return _result = NO; }
} else {
if ( _s2.has_on(_s1.point(0)) )
{ _ip = _s1.point(0); return _result = POINT; }
else { return _result = NO; }
}
}
if ( _s2.is_degenerate() ) {
CGAL_assertion( !_s1.is_degenerate() );
if ( _s1.has_on(_s2.point(0)) )
{ _ip = _s2.point(0); return _result = POINT; }
else { return _result = NO; }
}
// now s1,s2 not degenerate
typedef typename R::Line_line_intersection_d Int_obj_type;
Int_obj_type Intersect;
FT l1,l2;
typename Int_obj_type::Intersection_result res =
Intersect(_s1.point(0),_s1.point(1),
_s2.point(0),_s2.point(1),_ip,l1,l2);
if (res == Int_obj_type::LINE)
<<determine common points of two segments>>
if ( res == Int_obj_type::POINT &&
FT(0) <= l1 && l1 <= FT(1) &&
FT(0) <= l2 && l2 <= FT(1) )
{ return _result = POINT; }
return _result = NO;
}
<<determine common points of two segments>>=
{ Point_d p1 = _s1.min(), p2 = _s1.max();
Point_d q1 = _s2.min(), q2 = _s2.max();
Point_d s,t;
// now order the for points along the line
typename R::Position_on_line_d pos;
pos(p1, q1, q2, l1); pos(p2, q1, q2, l2);
if ( l1 < FT(0) ) {
if ( l2 < FT(0) ) { return _result = NO; }
else { s = q1; }
} else { s = p1; } // l1 >= 0
if ( l2 > FT(1) ) {
if ( l1 > FT(1) ) { return _result = NO; }
else { t = q2; }
} else { t = p2; } // l2 <= 1
if ( s == t ) { _ip = s; return _result = POINT; }
_is = Segment_d(s,t); return _result = SEGMENT;
}
<<segment segment intersection>>=
template <class R>
bool
Segment_d_Segment_d_pair<R>::intersection(Point_d& p)
{ if (!_known) intersection_type();
if (_result != POINT) return false;
p = _ip; return true;
}
template <class R>
bool
Segment_d_Segment_d_pair<R>::intersection(Segment_d& s)
{ if (!_known) intersection_type();
if (_result != SEGMENT) return false;
s = _is; return true;
}
<<line hyperplane intersection>>=
template <class R>
class Line_d_Hyperplane_d_pair {
public:
enum Intersection_result {NO, POINT, LINE};
typedef typename R::Point_d Point_d;
typedef typename R::Line_d Line_d;
typedef typename R::Hyperplane_d Hyperplane_d;
typedef typename R::FT FT;
protected:
Line_d _l; Hyperplane_d _h;
bool _known;
Intersection_result _result;
Point_d _ip;
public:
Line_d_Hyperplane_d_pair() : _known(false) {}
Line_d_Hyperplane_d_pair(const Line_d& l, const Hyperplane_d& h)
: _l(l), _h(h), _known(false) {}
Intersection_result intersection_type();
bool intersection(Point_d& result);
bool intersection(Line_d& result);
};
template <class R>
Line_d_Hyperplane_d_pair<R>::Intersection_result
Line_d_Hyperplane_d_pair<R>::intersection_type()
{ if (_known) return _result;
_known = true;
// CGAL_assertion_msg((!_l.is_degenerate()));
typedef typename R::Line_hyperplane_intersection_d Int_obj_type;
Int_obj_type Intersect;
FT lambda;
typename Int_obj_type::Intersection_result res =
Intersect(_l.point(0),_l.point(1),_h,_ip,lambda);
if (res == Int_obj_type::LINE) { return _result = LINE; }
if (res == Int_obj_type::POINT) { return _result = POINT; }
return _result = NO;
}
template <class R>
bool
Line_d_Hyperplane_d_pair<R>::intersection(Point_d& p)
{ if (!_known) intersection_type();
if (_result != POINT) return false;
p = _ip; return true;
}
template <class R>
bool
Line_d_Hyperplane_d_pair<R>::intersection(Line_d& l)
{ if (!_known) intersection_type();
if (_result != LINE) return false;
l = _l; return true;
}
<<ray hyperplane intersection>>=
template <class R>
class Ray_d_Hyperplane_d_pair {
public:
enum Intersection_result {NO, POINT, RAY};
typedef typename R::FT FT;
typedef typename R::Point_d Point_d;
typedef typename R::Ray_d Ray_d;
typedef typename R::Hyperplane_d Hyperplane_d;
protected:
Ray_d _r; Hyperplane_d _h;
bool _known;
Intersection_result _result;
Point_d _ip;
public:
Ray_d_Hyperplane_d_pair() : _known(false) {}
Ray_d_Hyperplane_d_pair(const Ray_d& r, const Hyperplane_d& h)
: _r(r), _h(h), _known(false) {}
Intersection_result intersection_type();
bool intersection(Point_d& result);
bool intersection(Ray_d& result);
};
template <class R>
Ray_d_Hyperplane_d_pair<R>::Intersection_result
Ray_d_Hyperplane_d_pair<R>::intersection_type()
{
if (_known) return _result;
_known = true;
// CGAL_assertion( !_r.is_degenerate() );
typedef typename R::Line_hyperplane_intersection_d Int_obj_type;
Int_obj_type Intersect;
FT lambda;
typename Int_obj_type::Intersection_result res =
Intersect(_r.point(0),_r.point(1),_h,_ip,lambda);
if ( res == Int_obj_type::POINT && FT(0) <= lambda )
{ return _result = POINT; }
if ( res == Int_obj_type::LINE )
{ return _result = RAY; }
return _result = NO;
}
template <class R>
bool
Ray_d_Hyperplane_d_pair<R>::intersection(Point_d& p)
{ if (!_known) intersection_type();
if (_result != POINT) return false;
p = _ip; return true;
}
template <class R>
bool
Ray_d_Hyperplane_d_pair<R>::intersection(Ray_d& r)
{ if (!_known) intersection_type();
if (_result != RAY) return false;
r = _r; return true;
}
<<segment hyperplane intersection>>=
template <class R>
class Segment_d_Hyperplane_d_pair {
public:
enum Intersection_result {NO, POINT, SEGMENT};
typedef typename R::FT FT;
typedef typename R::Point_d Point_d;
typedef typename R::Segment_d Segment_d;
typedef typename R::Hyperplane_d Hyperplane_d;
protected:
Segment_d _s;
Hyperplane_d _h;
bool _known;
Intersection_result _result;
Point_d _ip;
public:
/*{\Mcreation 4}*/
Segment_d_Hyperplane_d_pair() : _known(false) {}
Segment_d_Hyperplane_d_pair(
const Segment_d& s, const Hyperplane_d& h) :
_s(s), _h(h), _known(false) {}
Intersection_result intersection_type();
bool intersection(Point_d& result);
bool intersection(Segment_d& result);
};
template <class R>
Segment_d_Hyperplane_d_pair<R>::Intersection_result
Segment_d_Hyperplane_d_pair<R>::intersection_type()
{
if (_known) return _result;
_known = true;
if ( _s.is_degenerate() )
if ( _h.has_on(_s.point(0)) )
{ _ip = _s.point(0); return _result = POINT; }
else { return _result = NO; }
typedef typename R::Line_hyperplane_intersection_d Int_obj_type;
Int_obj_type Intersect;
FT lambda;
typename Int_obj_type::Intersection_result res =
Intersect(_s.point(0),_s.point(1),_h,_ip,lambda);
if ( res == Int_obj_type::LINE )
{ return _result = SEGMENT; }
if ( res == Int_obj_type::POINT &&
FT(0) <= lambda && lambda <= FT(1) )
{ return _result = POINT; }
return _result = NO;
}
template <class R>
bool
Segment_d_Hyperplane_d_pair<R>::intersection(Point_d& pt)
{ if (!_known) intersection_type();
if (_result != POINT) return false;
pt = _ip; return true;
}
template <class R>
bool
Segment_d_Hyperplane_d_pair<R>::intersection(Segment_d& s)
{ if (!_known) intersection_type();
if (_result != LINE) return false;
s = _s; return true;
}
<<intersection_objectsHd.h>>=
#ifndef CGAL_INTERSECTION_OBJECTSHD_H
#define CGAL_INTERSECTION_OBJECTSHD_H
#include <CGAL/basic.h>
namespace CGAL {
<<homogeneous intersection working horses>>
} //namespace CGAL
#include <CGAL/Kernel_d/intersection_objects_d.h>
#endif //CGAL_INTERSECTION_OBJECTSHD_H
<<intersection_objectsCd.h>>=
#ifndef CGAL_INTERSECTION_OBJECTSCD_H
#define CGAL_INTERSECTION_OBJECTSCD_H
#include <CGAL/basic.h>
#undef _DEBUG
#define _DEBUG 11
#include <CGAL/Kernel_d/debug.h>
namespace CGAL {
<<cartesian intersection working horses>>
} //namespace CGAL
#include <CGAL/Kernel_d/intersection_objects_d.h>
#endif //CGAL_INTERSECTION_OBJECTSCD_H
<<intersection_objects_d.h>>=
#ifndef CGAL_INTERSECTION_OBJECTS_D_H
#define CGAL_INTERSECTION_OBJECTS_D_H
namespace CGAL {
<<line line intersection>>
<<line ray intersection>>
<<line segment intersection>>
<<ray ray intersection>>
<<ray segment intersection>>
<<segment segment intersection>>
<<line hyperplane intersection>>
<<ray hyperplane intersection>>
<<segment hyperplane intersection>>
} //namespace CGAL
#endif //CGAL_INTERSECTION_OBJECTS_D_H
@ \end{document}